feat!: @rudder/sdk 0.1.0: createClient, idempotent modules.call retries, storage save(type, data), drop resources and projectStorage

This commit is contained in:
edmand46
2026-09-17 15:26:42 +03:00
parent c25b1c2c61
commit 1e4e0d928d
35 changed files with 474 additions and 467 deletions
+11 -11
View File
@@ -1,7 +1,7 @@
/**
* SyncedState — an observable cell for a single server-synced entity.
*
* Tracks `{ status, data, error }`, deduplicates parallel loads, and notifies
* Tracks `{ status, value, error }`, deduplicates parallel loads, and notifies
* listeners on every data/status change. `onChange` calls the callback
* immediately with the current snapshot, which makes syncing into external
* stores (React/zustand) trivial.
@@ -11,7 +11,7 @@ export type SyncedStatus = 'idle' | 'loading' | 'ready' | 'error';
export interface SyncedSnapshot<T> {
status: SyncedStatus;
data?: T;
value?: T;
error?: Error;
}
@@ -27,8 +27,8 @@ export class SyncedState<T> {
constructor(private readonly loader: () => Promise<T>) {}
/** Current data, or undefined when not loaded yet. */
get data(): T | undefined {
return this.snapshot.data;
get value(): T | undefined {
return this.snapshot.value;
}
get status(): SyncedStatus {
@@ -54,7 +54,7 @@ export class SyncedState<T> {
/** Loads the entity if needed; deduplicates parallel loads. */
load(): Promise<T> {
if (this.snapshot.status === 'ready') {
return Promise.resolve(this.snapshot.data as T);
return Promise.resolve(this.snapshot.value as T);
}
return this.startLoad(false);
}
@@ -100,18 +100,18 @@ export class SyncedState<T> {
private startLoad(force: boolean): Promise<T> {
if (this.pending && !force) return this.pending;
const generation = ++this.generation;
this.setSnapshot({ status: 'loading', data: this.snapshot.data });
this.setSnapshot({ status: 'loading', value: this.snapshot.value });
this.pending = this.loader()
.then((data) => {
.then((value) => {
if (generation === this.generation) {
this.setSnapshot({ status: 'ready', data });
this.setSnapshot({ status: 'ready', value });
}
return data;
return value;
})
.catch((err) => {
const error = err instanceof Error ? err : new Error(String(err));
if (generation === this.generation) {
this.setSnapshot({ status: 'error', error, data: this.snapshot.data });
this.setSnapshot({ status: 'error', error, value: this.snapshot.value });
}
throw error;
})
@@ -127,7 +127,7 @@ export class SyncedState<T> {
const previous = this.snapshot;
if (
previous.status === next.status &&
previous.data === next.data &&
previous.value === next.value &&
previous.error === next.error
) {
return;