@datafn/client 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +199 -0
- package/dist/index.cjs +1216 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +248 -0
- package/dist/index.d.ts +248 -0
- package/dist/index.js +1183 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { DatafnEvent, DatafnSignal, DatafnSchema, DatafnPlugin, DatafnErrorCode } from '@datafn/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Event filtering logic
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
interface EventFilter {
|
|
8
|
+
type?: string | string[];
|
|
9
|
+
resource?: string | string[];
|
|
10
|
+
ids?: string | string[];
|
|
11
|
+
mutationId?: string | string[];
|
|
12
|
+
action?: string | string[];
|
|
13
|
+
fields?: string | string[];
|
|
14
|
+
contextKeys?: string[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if an event matches the filter
|
|
18
|
+
*/
|
|
19
|
+
declare function matchesFilter(event: DatafnEvent, filter?: EventFilter): boolean;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* In-process event bus
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
type EventHandler = (event: DatafnEvent) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Simple in-process event bus
|
|
28
|
+
*/
|
|
29
|
+
declare class EventBus {
|
|
30
|
+
private subscriptions;
|
|
31
|
+
private nextId;
|
|
32
|
+
/**
|
|
33
|
+
* Subscribe to events with optional filtering
|
|
34
|
+
*/
|
|
35
|
+
subscribe(handler: EventHandler, filter?: EventFilter): () => void;
|
|
36
|
+
/**
|
|
37
|
+
* Emit an event to all matching subscribers
|
|
38
|
+
*/
|
|
39
|
+
emit(event: DatafnEvent): void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* DataFn Table Handle
|
|
44
|
+
*
|
|
45
|
+
* Represents a table/resource from the schema with methods for query, mutation, signals, and subscriptions.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
interface DatafnTable<TRecord = unknown> {
|
|
49
|
+
name: string;
|
|
50
|
+
version: number;
|
|
51
|
+
query(q: unknown): Promise<unknown>;
|
|
52
|
+
mutate(m: unknown): Promise<unknown>;
|
|
53
|
+
transact(payload: unknown): Promise<unknown>;
|
|
54
|
+
signal(q: unknown): DatafnSignal<unknown>;
|
|
55
|
+
subscribe(handler: EventHandler, filter?: EventFilter): () => void;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Storage adapter types for local persistence
|
|
60
|
+
*/
|
|
61
|
+
type DatafnHydrationState = "notStarted" | "hydrating" | "ready";
|
|
62
|
+
type DatafnChangelogEntry = {
|
|
63
|
+
/** Monotonic local sequence (assigned by storage adapter). */
|
|
64
|
+
seq: number;
|
|
65
|
+
clientId: string;
|
|
66
|
+
mutationId: string;
|
|
67
|
+
mutation: Record<string, unknown>;
|
|
68
|
+
timestampMs: number;
|
|
69
|
+
};
|
|
70
|
+
interface DatafnStorageAdapter {
|
|
71
|
+
getRecord(resource: string, id: string): Promise<Record<string, unknown> | null>;
|
|
72
|
+
listRecords(resource: string): Promise<Record<string, unknown>[]>;
|
|
73
|
+
upsertRecord(resource: string, record: Record<string, unknown>): Promise<void>;
|
|
74
|
+
deleteRecord(resource: string, id: string): Promise<void>;
|
|
75
|
+
listJoinRows(relationKey: string): Promise<Array<Record<string, unknown>>>;
|
|
76
|
+
upsertJoinRow(relationKey: string, row: Record<string, unknown>): Promise<void>;
|
|
77
|
+
deleteJoinRow(relationKey: string, from: string, to: string): Promise<void>;
|
|
78
|
+
getCursor(resource: string): Promise<string | null>;
|
|
79
|
+
setCursor(resource: string, cursor: string): Promise<void>;
|
|
80
|
+
getHydrationState(resource: string): Promise<DatafnHydrationState>;
|
|
81
|
+
setHydrationState(resource: string, state: DatafnHydrationState): Promise<void>;
|
|
82
|
+
changelogAppend(entry: Omit<DatafnChangelogEntry, "seq">): Promise<DatafnChangelogEntry>;
|
|
83
|
+
changelogList(options?: {
|
|
84
|
+
limit?: number;
|
|
85
|
+
}): Promise<DatafnChangelogEntry[]>;
|
|
86
|
+
changelogAck(options: {
|
|
87
|
+
throughSeq: number;
|
|
88
|
+
}): Promise<void>;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Sync Facade
|
|
93
|
+
*
|
|
94
|
+
* Client-side sync methods that delegate to remote adapter.
|
|
95
|
+
* When storage is configured, clone/pull results are applied to local storage.
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
interface SyncFacade {
|
|
99
|
+
seed(payload: unknown): Promise<unknown>;
|
|
100
|
+
clone(payload: unknown): Promise<unknown>;
|
|
101
|
+
pull(payload: unknown): Promise<unknown>;
|
|
102
|
+
push(payload: unknown): Promise<unknown>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* DataFn client factory
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
interface DatafnRemoteAdapter {
|
|
110
|
+
query(q: unknown): Promise<unknown>;
|
|
111
|
+
mutation(m: unknown): Promise<unknown>;
|
|
112
|
+
transact(t: unknown): Promise<unknown>;
|
|
113
|
+
seed(payload: unknown): Promise<unknown>;
|
|
114
|
+
clone(payload: unknown): Promise<unknown>;
|
|
115
|
+
pull(payload: unknown): Promise<unknown>;
|
|
116
|
+
push(payload: unknown): Promise<unknown>;
|
|
117
|
+
}
|
|
118
|
+
interface DatafnClientConfig {
|
|
119
|
+
schema: DatafnSchema;
|
|
120
|
+
remote: DatafnRemoteAdapter;
|
|
121
|
+
/**
|
|
122
|
+
* Optional plugins for client-side hook execution
|
|
123
|
+
*/
|
|
124
|
+
plugins?: DatafnPlugin[];
|
|
125
|
+
/**
|
|
126
|
+
* Stable client/device identifier used for idempotency and offline change logs.
|
|
127
|
+
* Required when `storage` is provided.
|
|
128
|
+
*/
|
|
129
|
+
clientId?: string;
|
|
130
|
+
/**
|
|
131
|
+
* Local persistence adapter. When provided, sync results are applied to local storage.
|
|
132
|
+
*/
|
|
133
|
+
storage?: DatafnStorageAdapter;
|
|
134
|
+
getTimestamp?: () => number;
|
|
135
|
+
}
|
|
136
|
+
interface DatafnClient {
|
|
137
|
+
table<TRecord = unknown>(name: string): DatafnTable<TRecord>;
|
|
138
|
+
query(q: unknown | unknown[]): Promise<unknown>;
|
|
139
|
+
mutate(mutation: unknown | unknown[]): Promise<unknown>;
|
|
140
|
+
transact(payload: unknown): Promise<unknown>;
|
|
141
|
+
subscribe(handler: EventHandler, filter?: EventFilter): () => void;
|
|
142
|
+
sync: SyncFacade;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Create a DataFn client
|
|
146
|
+
*/
|
|
147
|
+
declare function createDatafnClient(config: DatafnClientConfig): DatafnClient;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* DataFn Client Error Types
|
|
151
|
+
*/
|
|
152
|
+
|
|
153
|
+
type DatafnClientError = {
|
|
154
|
+
code: DatafnErrorCode | "TRANSPORT_ERROR";
|
|
155
|
+
message: string;
|
|
156
|
+
details: {
|
|
157
|
+
path: string;
|
|
158
|
+
[key: string]: unknown;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Create a DataFnClientError and throw it
|
|
163
|
+
*/
|
|
164
|
+
declare function createClientError(code: DatafnClientError["code"], message: string, details: {
|
|
165
|
+
path: string;
|
|
166
|
+
[key: string]: unknown;
|
|
167
|
+
}): never;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Remote Response Unwrapping Utilities
|
|
171
|
+
*
|
|
172
|
+
* Handles both wrapped (DatafnEnvelope) and unwrapped server responses.
|
|
173
|
+
*/
|
|
174
|
+
/**
|
|
175
|
+
* Unwrap a remote response that may be wrapped in DatafnEnvelope or unwrapped.
|
|
176
|
+
*
|
|
177
|
+
* - If wrapped success `{ ok: true, result }`, return `result`
|
|
178
|
+
* - If wrapped error `{ ok: false, error }`, throw DatafnClientError
|
|
179
|
+
* - If unwrapped query result `{ data, nextCursor }`, return as-is
|
|
180
|
+
* - If unwrapped aggregate result `{ groups, nextCursor }`, return as-is
|
|
181
|
+
* - Otherwise throw TRANSPORT_ERROR
|
|
182
|
+
*/
|
|
183
|
+
declare function unwrapRemoteSuccess<T>(response: unknown): T;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* In-memory storage adapter for testing and development.
|
|
187
|
+
* Implements deterministic ordering and changelog deduplication.
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
declare class MemoryStorageAdapter implements DatafnStorageAdapter {
|
|
191
|
+
private records;
|
|
192
|
+
private joinRows;
|
|
193
|
+
private cursors;
|
|
194
|
+
private hydration;
|
|
195
|
+
private changelog;
|
|
196
|
+
private changelogSeq;
|
|
197
|
+
constructor();
|
|
198
|
+
getRecord(resource: string, id: string): Promise<Record<string, unknown> | null>;
|
|
199
|
+
listRecords(resource: string): Promise<Record<string, unknown>[]>;
|
|
200
|
+
upsertRecord(resource: string, record: Record<string, unknown>): Promise<void>;
|
|
201
|
+
deleteRecord(resource: string, id: string): Promise<void>;
|
|
202
|
+
listJoinRows(relationKey: string): Promise<Array<Record<string, unknown>>>;
|
|
203
|
+
upsertJoinRow(relationKey: string, row: Record<string, unknown>): Promise<void>;
|
|
204
|
+
deleteJoinRow(relationKey: string, from: string, to: string): Promise<void>;
|
|
205
|
+
getCursor(resource: string): Promise<string | null>;
|
|
206
|
+
setCursor(resource: string, cursor: string): Promise<void>;
|
|
207
|
+
getHydrationState(resource: string): Promise<DatafnHydrationState>;
|
|
208
|
+
setHydrationState(resource: string, state: DatafnHydrationState): Promise<void>;
|
|
209
|
+
changelogAppend(entry: Omit<DatafnChangelogEntry, "seq">): Promise<DatafnChangelogEntry>;
|
|
210
|
+
changelogList(options?: {
|
|
211
|
+
limit?: number;
|
|
212
|
+
}): Promise<DatafnChangelogEntry[]>;
|
|
213
|
+
changelogAck(options: {
|
|
214
|
+
throughSeq: number;
|
|
215
|
+
}): Promise<void>;
|
|
216
|
+
clear(): void;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* IndexedDB storage adapter for persistent client storage.
|
|
221
|
+
* Implements deterministic ordering and changelog deduplication.
|
|
222
|
+
*/
|
|
223
|
+
|
|
224
|
+
declare class IndexedDbStorageAdapter implements DatafnStorageAdapter {
|
|
225
|
+
private dbPromise;
|
|
226
|
+
constructor(dbName?: string);
|
|
227
|
+
private getStore;
|
|
228
|
+
getRecord(resource: string, id: string): Promise<Record<string, unknown> | null>;
|
|
229
|
+
listRecords(resource: string): Promise<Record<string, unknown>[]>;
|
|
230
|
+
upsertRecord(resource: string, record: Record<string, unknown>): Promise<void>;
|
|
231
|
+
deleteRecord(resource: string, id: string): Promise<void>;
|
|
232
|
+
listJoinRows(relationKey: string): Promise<Array<Record<string, unknown>>>;
|
|
233
|
+
upsertJoinRow(relationKey: string, row: Record<string, unknown>): Promise<void>;
|
|
234
|
+
deleteJoinRow(relationKey: string, from: string, to: string): Promise<void>;
|
|
235
|
+
getCursor(resource: string): Promise<string | null>;
|
|
236
|
+
setCursor(resource: string, cursor: string): Promise<void>;
|
|
237
|
+
getHydrationState(resource: string): Promise<DatafnHydrationState>;
|
|
238
|
+
setHydrationState(resource: string, state: DatafnHydrationState): Promise<void>;
|
|
239
|
+
changelogAppend(entry: Omit<DatafnChangelogEntry, "seq">): Promise<DatafnChangelogEntry>;
|
|
240
|
+
changelogList(options?: {
|
|
241
|
+
limit?: number;
|
|
242
|
+
}): Promise<DatafnChangelogEntry[]>;
|
|
243
|
+
changelogAck(options: {
|
|
244
|
+
throughSeq: number;
|
|
245
|
+
}): Promise<void>;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export { type DatafnChangelogEntry, type DatafnClient, type DatafnClientConfig, type DatafnClientError, type DatafnHydrationState, type DatafnRemoteAdapter, type DatafnStorageAdapter, type DatafnTable, EventBus, type EventFilter, type EventHandler, IndexedDbStorageAdapter, MemoryStorageAdapter, createClientError, createDatafnClient, matchesFilter, unwrapRemoteSuccess };
|