korajs 0.3.5 → 0.5.0

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/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- import { KoraEventEmitter, SchemaDefinition, SchemaInput, FieldBuilder, InferRecord, InferInsertInput, InferUpdateInput } from '@korajs/core';
2
- export { CollectionDefinition, ConnectionQuality, Constraint, FieldDescriptor, FieldKindToType, HLCTimestamp, HybridLogicalClock, InferFieldType, InferInsertInput, InferRecord, InferUpdateInput, KoraError, KoraEvent, KoraEventEmitter, KoraEventListener, KoraEventType, MergeStrategy, MergeTrace, Operation, SchemaDefinition, SchemaInput, TypedSchemaDefinition, VersionVector, createOperation, defineSchema, generateUUIDv7, t } from '@korajs/core';
3
- import * as _korajs_store from '@korajs/store';
4
- import { QueryBuilder, CollectionAccessor } from '@korajs/store';
5
- export { CollectionAccessor, CollectionRecord, StorageAdapter, Store, StoreConfig } from '@korajs/store';
1
+ import * as _korajs_core from '@korajs/core';
2
+ import { KoraEventEmitter, SequenceConfig, Operation, SchemaDefinition, KoraEvent, SchemaInput, FieldBuilder, InferRecord, InferInsertInput, InferUpdateInput } from '@korajs/core';
3
+ export { AtomicOp, AtomicOpType, CollectionDefinition, ConnectionQuality, Constraint, FieldDescriptor, FieldKindToType, HLCTimestamp, HybridLogicalClock, InferFieldType, InferInsertInput, InferRecord, InferUpdateInput, KoraError, KoraEvent, KoraEventEmitter, KoraEventListener, KoraEventType, MergeStrategy, MergeTrace, MigrationDefinition, MigrationStep, Operation, SchemaDefinition, SchemaInput, SequenceConfig, SyncRuleDefinition, TypedSchemaDefinition, VersionVector, createOperation, defineSchema, generateUUIDv7, migrate, op, t } from '@korajs/core';
4
+ import * as _korajs_sync from '@korajs/sync';
6
5
  import { SyncStatusInfo, SyncEngine } from '@korajs/sync';
7
- export { SyncConfig, SyncEngine, SyncState, SyncStatus, SyncStatusInfo, SyncStore, WebSocketTransport } from '@korajs/sync';
6
+ export { SyncConfig, SyncDiagnostics, SyncEncryptionConfig, SyncEngine, SyncState, SyncStatus, SyncStatusInfo, SyncStore, WebSocketTransport } from '@korajs/sync';
7
+ import * as _korajs_store from '@korajs/store';
8
+ import { CollectionRecord, BackupOptions, RestoreOptions, RestoreResult, ReplaySnapshot, AuditExportOptions, QueryBuilder, CollectionAccessor } from '@korajs/store';
9
+ export { AuditExportManifest, AuditExportOptions, AuditExportPayload, BackupManifest, BackupOptions, BackupProgress, CollectionAccessor, CollectionRecord, PersistedAuditTrace, ReplaySnapshot, RestoreOptions, RestoreResult, SequenceManager, StorageAdapter, Store, StoreConfig, TransactionCollectionAccessor, TransactionContext, TransactionContextConfig, decodeAuditExport, exportBackup, readAuditExportManifest, readBackupManifest, restoreBackup, verifyAuditExportChecksum, verifyBackupChecksum } from '@korajs/store';
8
10
  export { MergeEngine, MergeInput, MergeResult } from '@korajs/merge';
9
11
 
10
12
  /**
@@ -23,8 +25,36 @@ interface StoreOptions {
23
25
  adapter?: AdapterType;
24
26
  /** Database name. Defaults to 'kora-db'. */
25
27
  name?: string;
28
+ /**
29
+ * `shared` (default): one sync node id per database.
30
+ * `per-tab`: unique node id per browser tab (sessionStorage).
31
+ */
32
+ isolation?: _korajs_store.StoreIsolation;
26
33
  /** URL to the SQLite WASM worker script. Required for browser adapters (sqlite-wasm, indexeddb). */
27
34
  workerUrl?: string | URL;
35
+ /** Optional SharedWorker host for multi-tab SQLite (see `@korajs/store/sqlite-wasm/shared-host`). */
36
+ sharedWorkerUrl?: string | URL;
37
+ /** Max wait for a worker RPC (e.g. `open`). Defaults to 30000ms. */
38
+ workerResponseTimeoutMs?: number;
39
+ }
40
+ /**
41
+ * Pre-built auth binding from `createKoraAuthSync()` in `@korajs/auth`.
42
+ * Wires token refresh, JWT scope maps, and device-bound sync node ids.
43
+ */
44
+ interface AuthSyncBinding {
45
+ /** Returns the access token for sync handshake (empty string when signed out). */
46
+ auth: () => Promise<{
47
+ token: string;
48
+ }>;
49
+ /** Builds a scope map from the current token and schema. */
50
+ resolveScopeMap?: () => Promise<Record<string, Record<string, unknown>> | undefined>;
51
+ /**
52
+ * Returns the device-bound sync node id from the token `dev` claim.
53
+ * Separate from the user id (`sub`).
54
+ */
55
+ resolveNodeId?: () => Promise<string | undefined>;
56
+ /** Notifies when auth state changes so sync can refresh scope or reconnect. */
57
+ subscribe?: (listener: () => void) => () => void;
28
58
  }
29
59
  /**
30
60
  * Sync configuration within createApp.
@@ -38,18 +68,50 @@ interface SyncOptions {
38
68
  auth?: () => Promise<{
39
69
  token: string;
40
70
  }>;
71
+ /**
72
+ * Pre-built auth binding from `createKoraAuthSync({ authClient, schema })`.
73
+ * When set, overrides `auth`, auto-builds `scopeMap`, and binds store node id to `dev`.
74
+ */
75
+ authClient?: AuthSyncBinding;
41
76
  /** Sync scopes per collection. */
42
77
  scopes?: Record<string, (ctx: Record<string, unknown>) => Record<string, unknown>>;
78
+ /**
79
+ * Flat scope values. Combined with schema scope declarations to build
80
+ * per-collection scope filters sent to the server during handshake.
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * createApp({
85
+ * schema,
86
+ * sync: {
87
+ * url: 'wss://server/kora',
88
+ * scope: { orgId: 'org-123', storeId: 'store-456' },
89
+ * },
90
+ * })
91
+ * ```
92
+ */
93
+ scope?: Record<string, unknown>;
43
94
  /** Number of operations per batch. Defaults to 100. */
44
95
  batchSize?: number;
45
96
  /** Schema version of this client. */
46
97
  schemaVersion?: number;
98
+ /** Connect to the sync server automatically after `app.ready`. Defaults to false. */
99
+ autoConnect?: boolean;
100
+ /** Wait for server ACK on each handshake delta batch before streaming. Defaults to false. */
101
+ strictHandshake?: boolean;
102
+ /** Rewrites legacy operations during sync when schema versions differ. */
103
+ operationTransforms?: _korajs_core.OperationTransform[];
47
104
  /** Enable auto-reconnection on unexpected disconnect. Defaults to true. */
48
105
  autoReconnect?: boolean;
49
106
  /** Initial reconnection delay in ms. Defaults to 1000. */
50
107
  reconnectInterval?: number;
51
108
  /** Maximum reconnection delay in ms. Defaults to 30000. */
52
109
  maxReconnectInterval?: number;
110
+ /**
111
+ * End-to-end encryption for operation payloads on the sync wire.
112
+ * When enabled, `data` and `previousData` are encrypted before send.
113
+ */
114
+ encryption?: _korajs_sync.SyncEncryptionConfig;
53
115
  }
54
116
  /**
55
117
  * Full configuration passed to createApp().
@@ -63,7 +125,15 @@ interface KoraConfig {
63
125
  sync?: SyncOptions;
64
126
  /** Enable DevTools instrumentation. Defaults to false. */
65
127
  devtools?: boolean;
128
+ /** Called for each sync-related framework event. */
129
+ onSyncEvent?: (event: Extract<KoraEvent, {
130
+ type: `sync:${string}`;
131
+ }>) => void;
66
132
  }
133
+ /** Sync event types delivered to {@link KoraConfig.onSyncEvent}. */
134
+ type KoraSyncEvent = Extract<KoraEvent, {
135
+ type: `sync:${string}`;
136
+ }>;
67
137
  /**
68
138
  * Typed configuration passed to createApp() when using a TypedSchemaDefinition.
69
139
  */
@@ -78,6 +148,8 @@ interface TypedKoraConfig<S extends SchemaInput> {
78
148
  sync?: SyncOptions;
79
149
  /** Enable DevTools instrumentation. Defaults to false. */
80
150
  devtools?: boolean;
151
+ /** Called for each sync-related framework event. */
152
+ onSyncEvent?: (event: KoraSyncEvent) => void;
81
153
  }
82
154
  /**
83
155
  * Controls for the sync subsystem exposed on the KoraApp.
@@ -87,8 +159,79 @@ interface SyncControl {
87
159
  connect(): Promise<void>;
88
160
  /** Disconnect from the sync server. */
89
161
  disconnect(): Promise<void>;
162
+ /** Current sync status snapshot (updates on sync events). */
163
+ readonly status: SyncStatusInfo;
90
164
  /** Get the current developer-facing sync status. */
91
165
  getStatus(): SyncStatusInfo;
166
+ /** Subscribe to status changes (event-driven, no polling). */
167
+ subscribeStatus(listener: (status: SyncStatusInfo) => void): () => void;
168
+ /** Force an immediate reconnection attempt. No-op if already connected. */
169
+ retryNow(): Promise<void>;
170
+ /** Clear schema-mismatch block after upgrading schema; then call `connect()`. */
171
+ clearSchemaBlock(): void;
172
+ /** Export a diagnostics snapshot for debugging and support tickets. */
173
+ exportDiagnostics(): _korajs_sync.SyncDiagnostics;
174
+ }
175
+ /**
176
+ * A transaction collection accessor providing insert, update, delete, and findById.
177
+ */
178
+ interface TransactionCollectionProxy {
179
+ insert(data: Record<string, unknown>): Promise<CollectionRecord>;
180
+ update(id: string, data: Record<string, unknown>): Promise<CollectionRecord>;
181
+ delete(id: string): Promise<void>;
182
+ findById(id: string): Promise<CollectionRecord | null>;
183
+ }
184
+ /**
185
+ * Transaction proxy passed to the transaction callback.
186
+ * Provides collection accessors as direct properties (e.g., tx.todos.insert(...)).
187
+ */
188
+ interface TransactionProxy {
189
+ /** Dynamic collection accessors for transaction operations. */
190
+ [collection: string]: TransactionCollectionProxy;
191
+ }
192
+ /**
193
+ * Accessor for offline-safe sequences.
194
+ * Generates monotonically increasing, collision-free identifiers
195
+ * that work across offline devices.
196
+ */
197
+ interface SequenceAccessor {
198
+ /**
199
+ * Get the next value in a sequence, atomically incrementing the counter.
200
+ *
201
+ * @param name - The sequence name (e.g., 'receipt', 'invoice')
202
+ * @param config - Optional configuration for scope, format, and starting value
203
+ * @returns The formatted sequence value
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * const receiptNo = await app.sequences.next('receipt', {
208
+ * scope: storeId,
209
+ * format: 'S-{date}-{node4}-{seq}',
210
+ * })
211
+ * // → "S-20260508-a1b2-0042"
212
+ * ```
213
+ */
214
+ next(name: string, config?: SequenceConfig): Promise<string>;
215
+ /**
216
+ * Get the current counter value without incrementing.
217
+ *
218
+ * @param name - The sequence name
219
+ * @param config - Optional scope
220
+ * @returns The current counter value, or 0 if never used
221
+ */
222
+ current(name: string, config?: {
223
+ scope?: string;
224
+ }): Promise<number>;
225
+ /**
226
+ * Reset a sequence counter.
227
+ *
228
+ * @param name - The sequence name
229
+ * @param config - Optional scope and target value
230
+ */
231
+ reset(name: string, config?: {
232
+ scope?: string;
233
+ to?: number;
234
+ }): Promise<void>;
92
235
  }
93
236
  /**
94
237
  * The main application object returned by createApp().
@@ -101,12 +244,70 @@ interface KoraApp {
101
244
  events: KoraEventEmitter;
102
245
  /** Sync control (connect/disconnect/status). Null if sync not configured. */
103
246
  sync: SyncControl | null;
247
+ /** Offline-safe sequence generation. */
248
+ sequences: SequenceAccessor;
104
249
  /** Get the underlying Store instance (for advanced use / React integration). */
105
250
  getStore(): _korajs_store.Store;
106
251
  /** Get the underlying SyncEngine instance. Null if sync not configured. */
107
252
  getSyncEngine(): SyncEngine | null;
108
253
  /** Gracefully close the app: stop sync, close store. */
109
254
  close(): Promise<void>;
255
+ /**
256
+ * Execute multiple mutations atomically within a transaction.
257
+ * All operations are committed together or rolled back on error.
258
+ * Subscription notifications are batched after commit.
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * await app.transaction(async (tx) => {
263
+ * await tx.sales.update(saleId, { status: 'completed' })
264
+ * await tx.payments.insert({ saleId, method: 'cash', amount: total })
265
+ * })
266
+ * ```
267
+ */
268
+ transaction(fn: (tx: TransactionProxy) => Promise<void>): Promise<Operation[]>;
269
+ /**
270
+ * Execute a named mutation — a transaction with a human-readable name.
271
+ * The mutation name is attached to all operations and visible in DevTools.
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * await app.mutation('complete-sale', async (tx) => {
276
+ * await tx.sales.update(saleId, { status: 'completed' })
277
+ * await tx.payments.insert({ saleId, method: 'cash', amount: total })
278
+ * })
279
+ * ```
280
+ */
281
+ mutation(name: string, fn: (tx: TransactionProxy) => Promise<void>): Promise<Operation[]>;
282
+ /**
283
+ * Export all data as a portable backup binary.
284
+ * Delegates to the underlying store's exportBackup.
285
+ *
286
+ * @param options - Backup options (includeRecords, collections, onProgress)
287
+ * @returns Backup as a Uint8Array
288
+ */
289
+ exportBackup(options?: BackupOptions): Promise<Uint8Array>;
290
+ /**
291
+ * Restore data from a backup binary.
292
+ * Delegates to the underlying store's importBackup.
293
+ *
294
+ * @param data - The backup data
295
+ * @param options - Restore options (merge, collections, onProgress)
296
+ * @returns Result of the restore operation
297
+ */
298
+ importBackup(data: Uint8Array, options?: RestoreOptions): Promise<RestoreResult>;
299
+ /**
300
+ * Rebuild an in-memory snapshot at a causal cut in the operation log.
301
+ * Does not mutate live data — for DevTools time-travel and audit inspection.
302
+ *
303
+ * @param operationId - Content-addressed operation id to replay through (inclusive)
304
+ */
305
+ replayTo(operationId: string): Promise<ReplaySnapshot>;
306
+ /**
307
+ * Export the operation log and persisted merge traces as a portable audit bundle.
308
+ * Merge traces are recorded automatically when conflicts are resolved.
309
+ */
310
+ exportAudit(options?: AuditExportOptions): Promise<Uint8Array>;
110
311
  /** Dynamic collection accessors (e.g., app.todos). Typed via Object.defineProperty. */
111
312
  [collection: string]: unknown;
112
313
  }
@@ -137,12 +338,26 @@ type TypedKoraApp<S extends SchemaInput> = {
137
338
  events: KoraEventEmitter;
138
339
  /** Sync control (connect/disconnect/status). Null if sync not configured. */
139
340
  sync: SyncControl | null;
341
+ /** Offline-safe sequence generation. */
342
+ sequences: SequenceAccessor;
140
343
  /** Get the underlying Store instance (for advanced use / React integration). */
141
344
  getStore(): _korajs_store.Store;
142
345
  /** Get the underlying SyncEngine instance. Null if sync not configured. */
143
346
  getSyncEngine(): SyncEngine | null;
144
347
  /** Gracefully close the app: stop sync, close store. */
145
348
  close(): Promise<void>;
349
+ /** Execute multiple mutations atomically within a transaction. */
350
+ transaction(fn: (tx: TransactionProxy) => Promise<void>): Promise<Operation[]>;
351
+ /** Execute a named mutation — a transaction with a DevTools-visible name. */
352
+ mutation(name: string, fn: (tx: TransactionProxy) => Promise<void>): Promise<Operation[]>;
353
+ /** Export all data as a portable backup binary. */
354
+ exportBackup(options?: BackupOptions): Promise<Uint8Array>;
355
+ /** Restore data from a backup binary. */
356
+ importBackup(data: Uint8Array, options?: RestoreOptions): Promise<RestoreResult>;
357
+ /** Rebuild an in-memory snapshot at a causal cut in the operation log. */
358
+ replayTo(operationId: string): Promise<ReplaySnapshot>;
359
+ /** Export the operation log and persisted merge traces as a portable audit bundle. */
360
+ exportAudit(options?: AuditExportOptions): Promise<Uint8Array>;
146
361
  } & {
147
362
  readonly [C in keyof S['collections'] & string]: S['collections'][C] extends {
148
363
  fields: infer F extends Record<string, FieldBuilder<any, any, any>>;
@@ -190,4 +405,4 @@ declare function createApp<const S extends SchemaInput>(config: TypedKoraConfig<
190
405
  */
191
406
  declare function createApp(config: KoraConfig): KoraApp;
192
407
 
193
- export { type AdapterType, type KoraApp, type KoraConfig, type StoreOptions, type SyncControl, type SyncOptions, type TypedCollectionAccessor, type TypedKoraApp, type TypedKoraConfig, createApp };
408
+ export { type AdapterType, type AuthSyncBinding, type KoraApp, type KoraConfig, type SequenceAccessor, type StoreOptions, type SyncControl, type SyncOptions, type TransactionCollectionProxy, type TransactionProxy, type TypedCollectionAccessor, type TypedKoraApp, type TypedKoraConfig, createApp };