737729c9ce
Le nom @ng-eventually/sdk entrait en collision avec le SDK de NextGraph, dont ce paquet est justement un polyfill. Impossible d'écrire « le SDK » sans lever l'ambiguïté à chaque phrase — et le contrat publié, lu par une application, était le pire endroit pour laisser traîner ça. packages/sdk → packages/polyfill, @ng-eventually/sdk → @ng-eventually/polyfill, contract_sdk-surface → contract_polyfill-surface, e2e/sdk-entry.ts → e2e/polyfill-entry.ts, docs/sdk-reference.md → docs/polyfill-reference.md. Les occurrences de « SDK » qui désignent celui de NextGraph restent intactes, y compris les chemins dans nextgraph-rs (sdk/js/orm, sdk/js/web). Le tri s'est fait occurrence par occurrence, pas par substitution. Le contrat énonce désormais son identité en une phrase : « This package is a polyfill of NextGraph's SDK. »
97 lines
3.3 KiB
TypeScript
97 lines
3.3 KiB
TypeScript
/**
|
|
* accounts — a framework-agnostic store for the current identity id.
|
|
*
|
|
* The identity a session acts as is established when its wallet is imported; the
|
|
* SDK is told who that is via the current-identity call. This small store just
|
|
* persists that id (in an injected storage) so it survives reloads and a second
|
|
* device, re-opening the same wallet, lands on the same identity. It carries no
|
|
* notion of a login step, a password, or a username — only an opaque identity id.
|
|
*
|
|
* Framework-agnostic on purpose: no React, no DOM assumption beyond an optional
|
|
* storage. A consumer's React `Context`/`Provider` wraps `useState` around
|
|
* {@link IdentityStore.set}/{@link IdentityStore.clear}. The lib does not force a
|
|
* React dependency. Removed against real NextGraph, where the wallet session is
|
|
* the source of the identity id.
|
|
*/
|
|
|
|
/** localStorage key holding the current identity id. */
|
|
export const ACCOUNT_STORAGE_KEY = "ng-eventually.account.id";
|
|
|
|
/**
|
|
* Minimal storage contract (a subset of the Web `Storage` interface). The
|
|
* consumer injects one — `window.localStorage` in a browser, a fake in tests —
|
|
* so this stays framework/DOM-agnostic. When none is available (SSR, no
|
|
* `window`), pass `null` and the store degrades to in-memory-null (no persist).
|
|
*/
|
|
export interface VirtualUserStorage {
|
|
getItem(key: string): string | null;
|
|
setItem(key: string, value: string): void;
|
|
removeItem(key: string): void;
|
|
}
|
|
|
|
/**
|
|
* The persisted current identity id. A tiny store around an injected
|
|
* {@link VirtualUserStorage}. It holds no framework state; the consumer's Provider
|
|
* mirrors `get()` into framework state and re-reads after `set`/`clear`.
|
|
*/
|
|
export class IdentityStore {
|
|
private readonly storage: VirtualUserStorage | null;
|
|
private readonly key: string;
|
|
|
|
constructor(storage: VirtualUserStorage | null, key: string = ACCOUNT_STORAGE_KEY) {
|
|
this.storage = storage;
|
|
this.key = key;
|
|
}
|
|
|
|
/** The current identity id. null = no identity set yet. */
|
|
get(): string | null {
|
|
if (!this.storage) return null;
|
|
try {
|
|
return this.storage.getItem(this.key);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Persist the (trimmed) identity id. An empty/blank value is ignored and the
|
|
* previous id is kept (returns the resulting id, or null). No NextGraph call.
|
|
*/
|
|
set(id: string): string | null {
|
|
const clean = id.trim();
|
|
if (!clean) return this.get();
|
|
if (this.storage) {
|
|
try {
|
|
this.storage.setItem(this.key, clean);
|
|
} catch {
|
|
/* ignore — staging, no security */
|
|
}
|
|
}
|
|
return clean;
|
|
}
|
|
|
|
/** Clear the persisted identity id. No NextGraph call. */
|
|
clear(): void {
|
|
if (this.storage) {
|
|
try {
|
|
this.storage.removeItem(this.key);
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convenience factory using `globalThis.localStorage` when present, else a
|
|
* null (non-persisting) store — so the same call is safe in browser and SSR.
|
|
*/
|
|
export function browserIdentityStore(key: string = ACCOUNT_STORAGE_KEY): IdentityStore {
|
|
const ls =
|
|
typeof globalThis !== "undefined" &&
|
|
(globalThis as { localStorage?: VirtualUserStorage }).localStorage
|
|
? (globalThis as { localStorage: VirtualUserStorage }).localStorage
|
|
: null;
|
|
return new IdentityStore(ls, key);
|
|
}
|