@korajs/store 1.0.0-beta.13 → 1.0.0-beta.14
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/adapters/better-sqlite3.cjs.map +1 -1
- package/dist/adapters/better-sqlite3.js +1 -1
- package/dist/adapters/indexeddb.cjs.map +1 -1
- package/dist/adapters/indexeddb.js +4 -4
- package/dist/adapters/sqlite-wasm-worker.cjs +67 -15
- package/dist/adapters/sqlite-wasm-worker.cjs.map +1 -1
- package/dist/adapters/sqlite-wasm-worker.js +65 -17
- package/dist/adapters/sqlite-wasm-worker.js.map +1 -1
- package/dist/adapters/sqlite-wasm.cjs.map +1 -1
- package/dist/adapters/sqlite-wasm.js +5 -5
- package/dist/{backup-4NUPDEMB.js → backup-IHKVMUAM.js} +5 -5
- package/dist/{chunk-Y5LRH7KI.js → chunk-5AQSGMJV.js} +151 -21
- package/dist/chunk-5AQSGMJV.js.map +1 -0
- package/dist/{chunk-W5F2LWG6.js → chunk-5JMGMPUE.js} +2 -2
- package/dist/{chunk-HZTDBLDB.js → chunk-BILSA6XZ.js} +4 -3
- package/dist/{chunk-HZTDBLDB.js.map → chunk-BILSA6XZ.js.map} +1 -1
- package/dist/{chunk-QDUSJMFV.js → chunk-BQSIL6TT.js} +5 -5
- package/dist/{chunk-MCQKEHOD.js → chunk-KK3GBONL.js} +2 -2
- package/dist/{chunk-32EDKWMI.js → chunk-KTVNANUH.js} +2 -2
- package/dist/{chunk-SJP2HTYZ.js → chunk-QW4UU7NG.js} +2 -2
- package/dist/{chunk-DUKTWVZW.js → chunk-SRHDJF5B.js} +13 -2
- package/dist/{chunk-DUKTWVZW.js.map → chunk-SRHDJF5B.js.map} +1 -1
- package/dist/{chunk-P4V375FY.js → chunk-UC2LGFPV.js} +4 -4
- package/dist/index.cjs +203 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +96 -6
- package/dist/index.d.ts +96 -6
- package/dist/index.js +55 -39
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +1 -0
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +2 -2
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +3 -3
- package/dist/{restore-FR7XIKT2.js → restore-MNDPR557.js} +4 -4
- package/dist/{sql-builder-C4u55jKW.d.cts → sql-builder-D0tC3sv9.d.cts} +8 -1
- package/dist/{sql-builder-CGckdBDL.d.ts → sql-builder-D5UMzHEo.d.ts} +8 -1
- package/dist/sqlite-wasm-channel-QCCNBYCU.js +12 -0
- package/dist/store-HNGX4KTT.js +16 -0
- package/package.json +2 -2
- package/dist/chunk-Y5LRH7KI.js.map +0 -1
- package/dist/sqlite-wasm-channel-MLHLKEED.js +0 -12
- package/dist/store-IMWKZLWB.js +0 -16
- /package/dist/{backup-4NUPDEMB.js.map → backup-IHKVMUAM.js.map} +0 -0
- /package/dist/{chunk-W5F2LWG6.js.map → chunk-5JMGMPUE.js.map} +0 -0
- /package/dist/{chunk-QDUSJMFV.js.map → chunk-BQSIL6TT.js.map} +0 -0
- /package/dist/{chunk-MCQKEHOD.js.map → chunk-KK3GBONL.js.map} +0 -0
- /package/dist/{chunk-32EDKWMI.js.map → chunk-KTVNANUH.js.map} +0 -0
- /package/dist/{chunk-SJP2HTYZ.js.map → chunk-QW4UU7NG.js.map} +0 -0
- /package/dist/{chunk-P4V375FY.js.map → chunk-UC2LGFPV.js.map} +0 -0
- /package/dist/{restore-FR7XIKT2.js.map → restore-MNDPR557.js.map} +0 -0
- /package/dist/{sqlite-wasm-channel-MLHLKEED.js.map → sqlite-wasm-channel-QCCNBYCU.js.map} +0 -0
- /package/dist/{store-IMWKZLWB.js.map → store-HNGX4KTT.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -2,8 +2,8 @@ import { C as CollectionRecord, S as StorageAdapter, Q as QueryDescriptor, d as
|
|
|
2
2
|
export { M as MigrationPlan, k as OrderByClause, l as QueryErrorPhase, m as StorageFallbackReason, a as StorageOpenState, n as StoreIsolation, T as Transaction, o as WhereOperators } from './types-Dh-xyUjP.cjs';
|
|
3
3
|
import { Operation, KoraError, VersionVector, SchemaDefinition, HLCTimestamp, MergeTrace, CollectionDefinition, SequenceConfig, HybridLogicalClock, CausalTracker, SecretKeyProvider, OperationLog, OperationTransform, ApplyResult, FoldState, KoraEventEmitter, StateMachineDefinition, KoraBytesValue, KoraEvent, BlobRefMetadata, BlobRef } from '@korajs/core';
|
|
4
4
|
export { ApplyResult } from '@korajs/core';
|
|
5
|
-
import { R as RelationEnforcer, j as LocalDeleteHook, k as RecordFolder, L as LocalMutationContext, A as AdoptionSchedule, T as TerminalRejection, l as LocalNodeRecord } from './sql-builder-
|
|
6
|
-
export { C as Collection, P as ParkedAdoption, V as VIRTUAL_TIMESTAMP_FIELDS, m as VIRTUAL_TIMESTAMP_FIELD_NAMES, n as VirtualTimestampField, o as mergeYjsUpdates } from './sql-builder-
|
|
5
|
+
import { R as RelationEnforcer, j as LocalDeleteHook, k as RecordFolder, L as LocalMutationContext, A as AdoptionSchedule, T as TerminalRejection, l as LocalNodeRecord } from './sql-builder-D0tC3sv9.cjs';
|
|
6
|
+
export { C as Collection, P as ParkedAdoption, V as VIRTUAL_TIMESTAMP_FIELDS, m as VIRTUAL_TIMESTAMP_FIELD_NAMES, n as VirtualTimestampField, o as mergeYjsUpdates } from './sql-builder-D0tC3sv9.cjs';
|
|
7
7
|
import * as yjs from 'yjs';
|
|
8
8
|
import { C as ContentAddressedBlobStore, M as MemoryBlobStore } from './content-addressed-blob-store-Dcj3SB9r.cjs';
|
|
9
9
|
export { B as BlobIntegrityError } from './content-addressed-blob-store-Dcj3SB9r.cjs';
|
|
@@ -157,6 +157,14 @@ declare class StorageBackendMismatchError extends KoraError {
|
|
|
157
157
|
declare class PersistenceError extends KoraError {
|
|
158
158
|
constructor(message: string, context?: Record<string, unknown>);
|
|
159
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Thrown by a local write while the store's pinned node id (an auth device id) belongs
|
|
162
|
+
* to another user than the one signed in (F9): a browser two users shared. The write
|
|
163
|
+
* could only be stored under the owner's node and would later upload as the owner's.
|
|
164
|
+
*/
|
|
165
|
+
declare class NodeOwnedByAnotherUserError extends KoraError {
|
|
166
|
+
constructor(nodeId: string, principal: string | null);
|
|
167
|
+
}
|
|
160
168
|
|
|
161
169
|
/**
|
|
162
170
|
* How the local operation log may be compacted.
|
|
@@ -396,8 +404,13 @@ interface RestoreResult {
|
|
|
396
404
|
success: boolean;
|
|
397
405
|
/** Error message if failed */
|
|
398
406
|
error?: string;
|
|
399
|
-
/** Error code if failed (`
|
|
407
|
+
/** Error code if failed (`BACKUP_CHECKSUM_MISMATCH`, `BACKUP_OPERATION_INVALID`, ...) */
|
|
400
408
|
errorCode?: string;
|
|
409
|
+
/**
|
|
410
|
+
* Set when the file was a version-1 backup (Kora 1.0.0-beta.12 and earlier) that the
|
|
411
|
+
* import converted first, as `convertBackupV1` does.
|
|
412
|
+
*/
|
|
413
|
+
convertedFromVersion?: 1;
|
|
401
414
|
/**
|
|
402
415
|
* Replace mode: this device's own writes the sync server had not acknowledged,
|
|
403
416
|
* re-applied on top of the restored data (see `RestoreOptions.keepUnsyncedWrites`).
|
|
@@ -924,6 +937,10 @@ interface TransactionContextConfig {
|
|
|
924
937
|
onStorageError?: (error: unknown) => void;
|
|
925
938
|
/** The W7 record fold (see `WriteEnv.fold`). */
|
|
926
939
|
fold?: RecordFolder;
|
|
940
|
+
/** See `WriteEnv.maxOperationBytes`. */
|
|
941
|
+
maxOperationBytes?: number;
|
|
942
|
+
/** See `WriteEnv.assertLocalWriteAllowed`. */
|
|
943
|
+
assertLocalWriteAllowed?: () => void;
|
|
927
944
|
}
|
|
928
945
|
/**
|
|
929
946
|
* A collection accessor within a transaction.
|
|
@@ -1038,6 +1055,12 @@ declare class Store implements OperationLog {
|
|
|
1038
1055
|
private readonly schema;
|
|
1039
1056
|
private readonly adapter;
|
|
1040
1057
|
private readonly configNodeId;
|
|
1058
|
+
/** The owner of the pinned node while it belongs to another user than the signed-in one (F9). */
|
|
1059
|
+
private pinnedNodeOwnedBy;
|
|
1060
|
+
/** The sync server refused the pinned node as another user's (F9). */
|
|
1061
|
+
private pinnedNodeRefusedByServer;
|
|
1062
|
+
/** The user of the last {@link bindPrincipal}. */
|
|
1063
|
+
private signedInPrincipal;
|
|
1041
1064
|
private readonly dbName;
|
|
1042
1065
|
private readonly isolation;
|
|
1043
1066
|
private readonly emitter;
|
|
@@ -1485,6 +1508,23 @@ declare class Store implements OperationLog {
|
|
|
1485
1508
|
* @throws {KoraError} When the node id is pinned (`StoreConfig.nodeId`, or per-tab isolation)
|
|
1486
1509
|
*/
|
|
1487
1510
|
rotateNodeId(unsyncedOpIds: string[]): Promise<NodeRotationResult>;
|
|
1511
|
+
/**
|
|
1512
|
+
* Re-author another local node's never-acknowledged operations under a fresh node id
|
|
1513
|
+
* bound to `principal` (the user they belong to). Used when the sync server refuses an
|
|
1514
|
+
* adopted node whose writes belong to the signed-in user (the app assigned them, or
|
|
1515
|
+
* the node was created for them) but which no claims-aware server ever accepted: a
|
|
1516
|
+
* beta.12 database's node with history the server recorded no owner for. The store's
|
|
1517
|
+
* own node id, clock and counters are untouched; the fresh node is registered, so the
|
|
1518
|
+
* sync engine adopts it like any other local node.
|
|
1519
|
+
*
|
|
1520
|
+
* @param fromNodeId - The refused local node (never the store's own)
|
|
1521
|
+
* @param unsyncedOpIds - Ids of its operations the server never acknowledged
|
|
1522
|
+
* @param principal - The user the writes belong to (the fresh node's binding)
|
|
1523
|
+
* @returns The fresh node id and the rewritten operations (for the outbound queue)
|
|
1524
|
+
* @throws {KoraError} `NODE_ID_UNKNOWN` when `fromNodeId` is the store's own node or
|
|
1525
|
+
* not a local node
|
|
1526
|
+
*/
|
|
1527
|
+
reauthorLocalNode(fromNodeId: string, unsyncedOpIds: string[], principal: string): Promise<NodeRotationResult>;
|
|
1488
1528
|
/**
|
|
1489
1529
|
* Move this database back to a node id it authored under before (RT-38): after the
|
|
1490
1530
|
* sync server refused the current node, the device tries a node a returning user
|
|
@@ -1525,6 +1565,19 @@ declare class Store implements OperationLog {
|
|
|
1525
1565
|
* @returns The node now in use and whether it changed
|
|
1526
1566
|
*/
|
|
1527
1567
|
bindPrincipal(principal: string): Promise<PrincipalBinding>;
|
|
1568
|
+
/**
|
|
1569
|
+
* The sync server refused this store's pinned node id because another user owns it
|
|
1570
|
+
* (`owned: true`), or later accepted it (`false`). A pinned node cannot move to a fresh
|
|
1571
|
+
* id, so writes made under it could only ever upload as its owner: while the server
|
|
1572
|
+
* says so, local writes are refused (F9). A no-op for a store whose node is not pinned
|
|
1573
|
+
* (it moves to a fresh node instead).
|
|
1574
|
+
*
|
|
1575
|
+
* @param owned - Whether the server reported the node owned by another user
|
|
1576
|
+
*/
|
|
1577
|
+
setPinnedNodeOwnedElsewhere(owned: boolean): void;
|
|
1578
|
+
/** Refuse a local write while the pinned node belongs to another user (F9). */
|
|
1579
|
+
private assertLocalWriteAllowed;
|
|
1580
|
+
private bindPrincipalToNode;
|
|
1528
1581
|
/**
|
|
1529
1582
|
* A sync handshake as `nodeId` was accepted for `principal` (RT-50): bind an unbound
|
|
1530
1583
|
* node (or replace a guessed binding) from the server's answer.
|
|
@@ -1684,8 +1737,9 @@ declare class Store implements OperationLog {
|
|
|
1684
1737
|
* move backwards, and unsynced own writes are kept (see
|
|
1685
1738
|
* `RestoreOptions.keepUnsyncedWrites`). Then {@link reloadFromDisk} runs.
|
|
1686
1739
|
*
|
|
1687
|
-
* A version-1 file
|
|
1688
|
-
* `convertBackupV1
|
|
1740
|
+
* A version-1 file (Kora 1.0.0-beta.12 and earlier) is converted first, exactly as
|
|
1741
|
+
* `convertBackupV1` does (`result.convertedFromVersion: 1`); one holding an operation
|
|
1742
|
+
* whose timestamp cannot be recovered is refused (`BACKUP_OPERATION_INVALID`).
|
|
1689
1743
|
*
|
|
1690
1744
|
* @param data - The backup data
|
|
1691
1745
|
* @param options - Restore options (merge, collections, keepUnsyncedWrites, onProgress)
|
|
@@ -1738,6 +1792,19 @@ declare class Store implements OperationLog {
|
|
|
1738
1792
|
* write path so they sync, unless declared `localOnly`.
|
|
1739
1793
|
*/
|
|
1740
1794
|
private runMigrationsIfNeeded;
|
|
1795
|
+
/** The node id the database persisted before this open, if any. */
|
|
1796
|
+
private readPersistedNodeId;
|
|
1797
|
+
/**
|
|
1798
|
+
* Register node ids this database authored under that the registry does not know
|
|
1799
|
+
* yet: the node id a pinned `nodeId` (the auth device id) just replaced, and the
|
|
1800
|
+
* authors of queued operations. A beta.12 database had no registry, and a template
|
|
1801
|
+
* app created before its user signed in authored under a random node; once the
|
|
1802
|
+
* store is pinned to the device id, that node's queued writes would otherwise sit in
|
|
1803
|
+
* the queue forever, neither uploaded nor reported. Registered, they are adopted or
|
|
1804
|
+
* held (`status.heldNodes`) like any other local node's writes. Only the outbound
|
|
1805
|
+
* queue is read: received operations never enter it.
|
|
1806
|
+
*/
|
|
1807
|
+
private registerUnregisteredAuthors;
|
|
1741
1808
|
private loadOrGenerateNodeId;
|
|
1742
1809
|
private loadSequenceNumber;
|
|
1743
1810
|
private loadVersionVector;
|
|
@@ -2167,6 +2234,12 @@ interface RichTextControllerSnapshot {
|
|
|
2167
2234
|
canUndo: boolean;
|
|
2168
2235
|
canRedo: boolean;
|
|
2169
2236
|
cursors: readonly RichTextCursorInfo[];
|
|
2237
|
+
/**
|
|
2238
|
+
* True while local edits are not in a successful save: a save is pending, in
|
|
2239
|
+
* flight, or was refused (see `error`). The edits stay in the live document and
|
|
2240
|
+
* are saved by the next edit or `retrySave()`.
|
|
2241
|
+
*/
|
|
2242
|
+
hasUnsavedChanges: boolean;
|
|
2170
2243
|
}
|
|
2171
2244
|
interface RichTextController {
|
|
2172
2245
|
readonly doc: yjs.Doc;
|
|
@@ -2178,12 +2251,29 @@ interface RichTextController {
|
|
|
2178
2251
|
setCursor(anchor: number, head: number): void;
|
|
2179
2252
|
clearCursor(): void;
|
|
2180
2253
|
setUser(user: RichTextAwarenessUser | undefined): void;
|
|
2254
|
+
/**
|
|
2255
|
+
* Save the live document now (for example after a refused save, once the cause
|
|
2256
|
+
* is fixed). Resolves when the save settled; its outcome is in the snapshot.
|
|
2257
|
+
*/
|
|
2258
|
+
retrySave(): Promise<void>;
|
|
2259
|
+
/**
|
|
2260
|
+
* The full document state (a Yjs update) while local edits are unsaved, else
|
|
2261
|
+
* null. Keep it as a recovery copy when saves keep failing.
|
|
2262
|
+
*/
|
|
2263
|
+
getUnsavedState(): Uint8Array | null;
|
|
2264
|
+
/** Stop syncing; edits still waiting for the debounced save are saved first. */
|
|
2181
2265
|
destroy(): void;
|
|
2182
2266
|
}
|
|
2183
2267
|
|
|
2184
2268
|
/**
|
|
2185
2269
|
* Framework-agnostic richtext binding: Yjs document lifecycle, persistence,
|
|
2186
2270
|
* incremental doc channel, and awareness cursors.
|
|
2271
|
+
*
|
|
2272
|
+
* Every save writes the full state of the live Y.Doc, which holds every local edit
|
|
2273
|
+
* and every merged remote change, so a stored change arriving while a save waits
|
|
2274
|
+
* cannot drop local typing. A refused save keeps the edits unsaved
|
|
2275
|
+
* (`hasUnsavedChanges`, `getUnsavedState()`) and the next edit or `retrySave()`
|
|
2276
|
+
* saves them again; the first successful save clears `error`.
|
|
2187
2277
|
*/
|
|
2188
2278
|
declare function createRichTextController(options: CreateRichTextControllerOptions): RichTextController;
|
|
2189
2279
|
|
|
@@ -2750,4 +2840,4 @@ declare function createChunkPortPair(): {
|
|
|
2750
2840
|
b: ChunkMessagePort;
|
|
2751
2841
|
};
|
|
2752
2842
|
|
|
2753
|
-
export { AdapterError, AdoptionSchedule, ApplyRemoteOptions, type AuditExportManifest, type AuditExportOptions, type AuditExportPayload, type AuditExportProgress, type AuditTraceQuery, BACKUP_VERSION, BackupFormatError, type BackupManifest, type BackupOptions, type BackupProgress, type BlobGcOptions, type BlobGcResult, type BlobManifest, type BlobManifestMetadata, BridgeTerminatedError, COMPACTION_BASELINE_META_KEY, type ChunkMessage, type ChunkMessagePort, type ChunkProvider, type ChunkRequestMessage, type ChunkResponseMessage, type ClockRebaseResult, type CollectionAccessor, CollectionRecord, type CompactionResult, type CompactionStrategy, ContentAddressedBlobStore, type ConvertBackupV1Options, type CreateRichTextControllerOptions, DEFAULT_CHUNK_SIZE, InvalidStateTransitionError, LAST_ACKED_SERVER_VECTOR_META_KEY, LOG_QUARANTINE_TABLE, LeaderUnresponsiveError, LocalMutationHandler, LocalNodeRecord, type LogIntegrityReport, type LogIntegrityRow, type LogRowProblem, type LogSequenceGap, MaterializedRowSnapshot, MemoryBlobStore, NoLeaderError, type NodeRotationResult, type OpfsBlobDirectory, OpfsBlobStore, OptimisticLockError, OrderByDirection, type PersistedAuditTrace, PersistenceError, type PersistenceRequestReason, type PersistenceStorageManager, type PrincipalBinding, QueryBuilder, QueryDescriptor, QueryError, QueryStore, QueryStoreCache, QuerySubscriptionError, type ReceiveBlobResult, type ReceiveBlobStores, RecordNotFoundError, type RecordsChange, type RecordsChangeListener, type RegisterOptions, type RematerializationMode, type RemoteChunkProvider, type RemoteChunkProviderOptions, type ReplaySnapshot, RequestAbortedError, type ResequenceResult, type RestoreOptions, type RestoreResult, type ResultsEqual, type RichTextAwarenessUser, type RichTextController, type RichTextControllerSnapshot, type RichTextCursorInfo, type RichTextSyncEngine, RowVersionState, SchemaVersionAheadError, SequenceManager, type ServerBlobCallbacks, StorageAdapter, StorageBackendMismatchError, StorageDurabilityError, StorageInUseError, StoragePersistence, type StoragePersistenceOptions, type StoragePersistenceState, type StoragePersistenceStatus, Store, StoreConfig, StoreNotOpenError, SubscribeOptions, SubscriptionBloomFilter, SubscriptionCallback, SubscriptionManager, type SubscriptionManagerOptions, type SubscriptionStats, TerminalRejection, type TransactionCollectionAccessor, TransactionContext, type TransactionContextConfig, type UnappliedOperation, UnsyncedDataError, WhereClause, WorkerInitError, WorkerTimeoutError, asRichTextSyncEngine, assertQueryReady, chunkBlob, collectBlobGarbage, collectOperationsAheadOfServer, compactOperationLog, computeAckCompactionWatermark, convertBackupV1, createChunkPortPair, createMemoryServerBlobStore, createOpfsBlobDirectory, createOpfsBlobStore, createRemoteChunkProvider, createRichTextController, decodeAuditExport, decodeRichtext, deserializeVersionVectorFromMeta, encodeRichtext, exportBackup, extractBlobRefs, fetchBlobManifest, getSharedQueryStoreCache, mergeVersionVectors, normalizeWhere, parseBlobManifest, persistedAuditTraceFromEvent, pluralize, prepareBlobForSend, putBlobForTransfer, queryKey, readAuditExportManifest, readBackupManifest, reassembleBlob, receiveBlob, resolveBlobManifest, restoreBackup, richtextStatesEqual, richtextToPlainText, serializeBlobManifest, serializeVersionVectorToMeta, serveBlobChunks, singularize, toServerBlobCallbacks, validateStateTransition, validateUpdateStateMachine, verifyAuditExportChecksum, verifyBackupChecksum };
|
|
2843
|
+
export { AdapterError, AdoptionSchedule, ApplyRemoteOptions, type AuditExportManifest, type AuditExportOptions, type AuditExportPayload, type AuditExportProgress, type AuditTraceQuery, BACKUP_VERSION, BackupFormatError, type BackupManifest, type BackupOptions, type BackupProgress, type BlobGcOptions, type BlobGcResult, type BlobManifest, type BlobManifestMetadata, BridgeTerminatedError, COMPACTION_BASELINE_META_KEY, type ChunkMessage, type ChunkMessagePort, type ChunkProvider, type ChunkRequestMessage, type ChunkResponseMessage, type ClockRebaseResult, type CollectionAccessor, CollectionRecord, type CompactionResult, type CompactionStrategy, ContentAddressedBlobStore, type ConvertBackupV1Options, type CreateRichTextControllerOptions, DEFAULT_CHUNK_SIZE, InvalidStateTransitionError, LAST_ACKED_SERVER_VECTOR_META_KEY, LOG_QUARANTINE_TABLE, LeaderUnresponsiveError, LocalMutationHandler, LocalNodeRecord, type LogIntegrityReport, type LogIntegrityRow, type LogRowProblem, type LogSequenceGap, MaterializedRowSnapshot, MemoryBlobStore, NoLeaderError, NodeOwnedByAnotherUserError, type NodeRotationResult, type OpfsBlobDirectory, OpfsBlobStore, OptimisticLockError, OrderByDirection, type PersistedAuditTrace, PersistenceError, type PersistenceRequestReason, type PersistenceStorageManager, type PrincipalBinding, QueryBuilder, QueryDescriptor, QueryError, QueryStore, QueryStoreCache, QuerySubscriptionError, type ReceiveBlobResult, type ReceiveBlobStores, RecordNotFoundError, type RecordsChange, type RecordsChangeListener, type RegisterOptions, type RematerializationMode, type RemoteChunkProvider, type RemoteChunkProviderOptions, type ReplaySnapshot, RequestAbortedError, type ResequenceResult, type RestoreOptions, type RestoreResult, type ResultsEqual, type RichTextAwarenessUser, type RichTextController, type RichTextControllerSnapshot, type RichTextCursorInfo, type RichTextSyncEngine, RowVersionState, SchemaVersionAheadError, SequenceManager, type ServerBlobCallbacks, StorageAdapter, StorageBackendMismatchError, StorageDurabilityError, StorageInUseError, StoragePersistence, type StoragePersistenceOptions, type StoragePersistenceState, type StoragePersistenceStatus, Store, StoreConfig, StoreNotOpenError, SubscribeOptions, SubscriptionBloomFilter, SubscriptionCallback, SubscriptionManager, type SubscriptionManagerOptions, type SubscriptionStats, TerminalRejection, type TransactionCollectionAccessor, TransactionContext, type TransactionContextConfig, type UnappliedOperation, UnsyncedDataError, WhereClause, WorkerInitError, WorkerTimeoutError, asRichTextSyncEngine, assertQueryReady, chunkBlob, collectBlobGarbage, collectOperationsAheadOfServer, compactOperationLog, computeAckCompactionWatermark, convertBackupV1, createChunkPortPair, createMemoryServerBlobStore, createOpfsBlobDirectory, createOpfsBlobStore, createRemoteChunkProvider, createRichTextController, decodeAuditExport, decodeRichtext, deserializeVersionVectorFromMeta, encodeRichtext, exportBackup, extractBlobRefs, fetchBlobManifest, getSharedQueryStoreCache, mergeVersionVectors, normalizeWhere, parseBlobManifest, persistedAuditTraceFromEvent, pluralize, prepareBlobForSend, putBlobForTransfer, queryKey, readAuditExportManifest, readBackupManifest, reassembleBlob, receiveBlob, resolveBlobManifest, restoreBackup, richtextStatesEqual, richtextToPlainText, serializeBlobManifest, serializeVersionVectorToMeta, serveBlobChunks, singularize, toServerBlobCallbacks, validateStateTransition, validateUpdateStateMachine, verifyAuditExportChecksum, verifyBackupChecksum };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { C as CollectionRecord, S as StorageAdapter, Q as QueryDescriptor, d as
|
|
|
2
2
|
export { M as MigrationPlan, k as OrderByClause, l as QueryErrorPhase, m as StorageFallbackReason, a as StorageOpenState, n as StoreIsolation, T as Transaction, o as WhereOperators } from './types-Dh-xyUjP.js';
|
|
3
3
|
import { Operation, KoraError, VersionVector, SchemaDefinition, HLCTimestamp, MergeTrace, CollectionDefinition, SequenceConfig, HybridLogicalClock, CausalTracker, SecretKeyProvider, OperationLog, OperationTransform, ApplyResult, FoldState, KoraEventEmitter, StateMachineDefinition, KoraBytesValue, KoraEvent, BlobRefMetadata, BlobRef } from '@korajs/core';
|
|
4
4
|
export { ApplyResult } from '@korajs/core';
|
|
5
|
-
import { R as RelationEnforcer, j as LocalDeleteHook, k as RecordFolder, L as LocalMutationContext, A as AdoptionSchedule, T as TerminalRejection, l as LocalNodeRecord } from './sql-builder-
|
|
6
|
-
export { C as Collection, P as ParkedAdoption, V as VIRTUAL_TIMESTAMP_FIELDS, m as VIRTUAL_TIMESTAMP_FIELD_NAMES, n as VirtualTimestampField, o as mergeYjsUpdates } from './sql-builder-
|
|
5
|
+
import { R as RelationEnforcer, j as LocalDeleteHook, k as RecordFolder, L as LocalMutationContext, A as AdoptionSchedule, T as TerminalRejection, l as LocalNodeRecord } from './sql-builder-D5UMzHEo.js';
|
|
6
|
+
export { C as Collection, P as ParkedAdoption, V as VIRTUAL_TIMESTAMP_FIELDS, m as VIRTUAL_TIMESTAMP_FIELD_NAMES, n as VirtualTimestampField, o as mergeYjsUpdates } from './sql-builder-D5UMzHEo.js';
|
|
7
7
|
import * as yjs from 'yjs';
|
|
8
8
|
import { C as ContentAddressedBlobStore, M as MemoryBlobStore } from './content-addressed-blob-store-Dcj3SB9r.js';
|
|
9
9
|
export { B as BlobIntegrityError } from './content-addressed-blob-store-Dcj3SB9r.js';
|
|
@@ -157,6 +157,14 @@ declare class StorageBackendMismatchError extends KoraError {
|
|
|
157
157
|
declare class PersistenceError extends KoraError {
|
|
158
158
|
constructor(message: string, context?: Record<string, unknown>);
|
|
159
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Thrown by a local write while the store's pinned node id (an auth device id) belongs
|
|
162
|
+
* to another user than the one signed in (F9): a browser two users shared. The write
|
|
163
|
+
* could only be stored under the owner's node and would later upload as the owner's.
|
|
164
|
+
*/
|
|
165
|
+
declare class NodeOwnedByAnotherUserError extends KoraError {
|
|
166
|
+
constructor(nodeId: string, principal: string | null);
|
|
167
|
+
}
|
|
160
168
|
|
|
161
169
|
/**
|
|
162
170
|
* How the local operation log may be compacted.
|
|
@@ -396,8 +404,13 @@ interface RestoreResult {
|
|
|
396
404
|
success: boolean;
|
|
397
405
|
/** Error message if failed */
|
|
398
406
|
error?: string;
|
|
399
|
-
/** Error code if failed (`
|
|
407
|
+
/** Error code if failed (`BACKUP_CHECKSUM_MISMATCH`, `BACKUP_OPERATION_INVALID`, ...) */
|
|
400
408
|
errorCode?: string;
|
|
409
|
+
/**
|
|
410
|
+
* Set when the file was a version-1 backup (Kora 1.0.0-beta.12 and earlier) that the
|
|
411
|
+
* import converted first, as `convertBackupV1` does.
|
|
412
|
+
*/
|
|
413
|
+
convertedFromVersion?: 1;
|
|
401
414
|
/**
|
|
402
415
|
* Replace mode: this device's own writes the sync server had not acknowledged,
|
|
403
416
|
* re-applied on top of the restored data (see `RestoreOptions.keepUnsyncedWrites`).
|
|
@@ -924,6 +937,10 @@ interface TransactionContextConfig {
|
|
|
924
937
|
onStorageError?: (error: unknown) => void;
|
|
925
938
|
/** The W7 record fold (see `WriteEnv.fold`). */
|
|
926
939
|
fold?: RecordFolder;
|
|
940
|
+
/** See `WriteEnv.maxOperationBytes`. */
|
|
941
|
+
maxOperationBytes?: number;
|
|
942
|
+
/** See `WriteEnv.assertLocalWriteAllowed`. */
|
|
943
|
+
assertLocalWriteAllowed?: () => void;
|
|
927
944
|
}
|
|
928
945
|
/**
|
|
929
946
|
* A collection accessor within a transaction.
|
|
@@ -1038,6 +1055,12 @@ declare class Store implements OperationLog {
|
|
|
1038
1055
|
private readonly schema;
|
|
1039
1056
|
private readonly adapter;
|
|
1040
1057
|
private readonly configNodeId;
|
|
1058
|
+
/** The owner of the pinned node while it belongs to another user than the signed-in one (F9). */
|
|
1059
|
+
private pinnedNodeOwnedBy;
|
|
1060
|
+
/** The sync server refused the pinned node as another user's (F9). */
|
|
1061
|
+
private pinnedNodeRefusedByServer;
|
|
1062
|
+
/** The user of the last {@link bindPrincipal}. */
|
|
1063
|
+
private signedInPrincipal;
|
|
1041
1064
|
private readonly dbName;
|
|
1042
1065
|
private readonly isolation;
|
|
1043
1066
|
private readonly emitter;
|
|
@@ -1485,6 +1508,23 @@ declare class Store implements OperationLog {
|
|
|
1485
1508
|
* @throws {KoraError} When the node id is pinned (`StoreConfig.nodeId`, or per-tab isolation)
|
|
1486
1509
|
*/
|
|
1487
1510
|
rotateNodeId(unsyncedOpIds: string[]): Promise<NodeRotationResult>;
|
|
1511
|
+
/**
|
|
1512
|
+
* Re-author another local node's never-acknowledged operations under a fresh node id
|
|
1513
|
+
* bound to `principal` (the user they belong to). Used when the sync server refuses an
|
|
1514
|
+
* adopted node whose writes belong to the signed-in user (the app assigned them, or
|
|
1515
|
+
* the node was created for them) but which no claims-aware server ever accepted: a
|
|
1516
|
+
* beta.12 database's node with history the server recorded no owner for. The store's
|
|
1517
|
+
* own node id, clock and counters are untouched; the fresh node is registered, so the
|
|
1518
|
+
* sync engine adopts it like any other local node.
|
|
1519
|
+
*
|
|
1520
|
+
* @param fromNodeId - The refused local node (never the store's own)
|
|
1521
|
+
* @param unsyncedOpIds - Ids of its operations the server never acknowledged
|
|
1522
|
+
* @param principal - The user the writes belong to (the fresh node's binding)
|
|
1523
|
+
* @returns The fresh node id and the rewritten operations (for the outbound queue)
|
|
1524
|
+
* @throws {KoraError} `NODE_ID_UNKNOWN` when `fromNodeId` is the store's own node or
|
|
1525
|
+
* not a local node
|
|
1526
|
+
*/
|
|
1527
|
+
reauthorLocalNode(fromNodeId: string, unsyncedOpIds: string[], principal: string): Promise<NodeRotationResult>;
|
|
1488
1528
|
/**
|
|
1489
1529
|
* Move this database back to a node id it authored under before (RT-38): after the
|
|
1490
1530
|
* sync server refused the current node, the device tries a node a returning user
|
|
@@ -1525,6 +1565,19 @@ declare class Store implements OperationLog {
|
|
|
1525
1565
|
* @returns The node now in use and whether it changed
|
|
1526
1566
|
*/
|
|
1527
1567
|
bindPrincipal(principal: string): Promise<PrincipalBinding>;
|
|
1568
|
+
/**
|
|
1569
|
+
* The sync server refused this store's pinned node id because another user owns it
|
|
1570
|
+
* (`owned: true`), or later accepted it (`false`). A pinned node cannot move to a fresh
|
|
1571
|
+
* id, so writes made under it could only ever upload as its owner: while the server
|
|
1572
|
+
* says so, local writes are refused (F9). A no-op for a store whose node is not pinned
|
|
1573
|
+
* (it moves to a fresh node instead).
|
|
1574
|
+
*
|
|
1575
|
+
* @param owned - Whether the server reported the node owned by another user
|
|
1576
|
+
*/
|
|
1577
|
+
setPinnedNodeOwnedElsewhere(owned: boolean): void;
|
|
1578
|
+
/** Refuse a local write while the pinned node belongs to another user (F9). */
|
|
1579
|
+
private assertLocalWriteAllowed;
|
|
1580
|
+
private bindPrincipalToNode;
|
|
1528
1581
|
/**
|
|
1529
1582
|
* A sync handshake as `nodeId` was accepted for `principal` (RT-50): bind an unbound
|
|
1530
1583
|
* node (or replace a guessed binding) from the server's answer.
|
|
@@ -1684,8 +1737,9 @@ declare class Store implements OperationLog {
|
|
|
1684
1737
|
* move backwards, and unsynced own writes are kept (see
|
|
1685
1738
|
* `RestoreOptions.keepUnsyncedWrites`). Then {@link reloadFromDisk} runs.
|
|
1686
1739
|
*
|
|
1687
|
-
* A version-1 file
|
|
1688
|
-
* `convertBackupV1
|
|
1740
|
+
* A version-1 file (Kora 1.0.0-beta.12 and earlier) is converted first, exactly as
|
|
1741
|
+
* `convertBackupV1` does (`result.convertedFromVersion: 1`); one holding an operation
|
|
1742
|
+
* whose timestamp cannot be recovered is refused (`BACKUP_OPERATION_INVALID`).
|
|
1689
1743
|
*
|
|
1690
1744
|
* @param data - The backup data
|
|
1691
1745
|
* @param options - Restore options (merge, collections, keepUnsyncedWrites, onProgress)
|
|
@@ -1738,6 +1792,19 @@ declare class Store implements OperationLog {
|
|
|
1738
1792
|
* write path so they sync, unless declared `localOnly`.
|
|
1739
1793
|
*/
|
|
1740
1794
|
private runMigrationsIfNeeded;
|
|
1795
|
+
/** The node id the database persisted before this open, if any. */
|
|
1796
|
+
private readPersistedNodeId;
|
|
1797
|
+
/**
|
|
1798
|
+
* Register node ids this database authored under that the registry does not know
|
|
1799
|
+
* yet: the node id a pinned `nodeId` (the auth device id) just replaced, and the
|
|
1800
|
+
* authors of queued operations. A beta.12 database had no registry, and a template
|
|
1801
|
+
* app created before its user signed in authored under a random node; once the
|
|
1802
|
+
* store is pinned to the device id, that node's queued writes would otherwise sit in
|
|
1803
|
+
* the queue forever, neither uploaded nor reported. Registered, they are adopted or
|
|
1804
|
+
* held (`status.heldNodes`) like any other local node's writes. Only the outbound
|
|
1805
|
+
* queue is read: received operations never enter it.
|
|
1806
|
+
*/
|
|
1807
|
+
private registerUnregisteredAuthors;
|
|
1741
1808
|
private loadOrGenerateNodeId;
|
|
1742
1809
|
private loadSequenceNumber;
|
|
1743
1810
|
private loadVersionVector;
|
|
@@ -2167,6 +2234,12 @@ interface RichTextControllerSnapshot {
|
|
|
2167
2234
|
canUndo: boolean;
|
|
2168
2235
|
canRedo: boolean;
|
|
2169
2236
|
cursors: readonly RichTextCursorInfo[];
|
|
2237
|
+
/**
|
|
2238
|
+
* True while local edits are not in a successful save: a save is pending, in
|
|
2239
|
+
* flight, or was refused (see `error`). The edits stay in the live document and
|
|
2240
|
+
* are saved by the next edit or `retrySave()`.
|
|
2241
|
+
*/
|
|
2242
|
+
hasUnsavedChanges: boolean;
|
|
2170
2243
|
}
|
|
2171
2244
|
interface RichTextController {
|
|
2172
2245
|
readonly doc: yjs.Doc;
|
|
@@ -2178,12 +2251,29 @@ interface RichTextController {
|
|
|
2178
2251
|
setCursor(anchor: number, head: number): void;
|
|
2179
2252
|
clearCursor(): void;
|
|
2180
2253
|
setUser(user: RichTextAwarenessUser | undefined): void;
|
|
2254
|
+
/**
|
|
2255
|
+
* Save the live document now (for example after a refused save, once the cause
|
|
2256
|
+
* is fixed). Resolves when the save settled; its outcome is in the snapshot.
|
|
2257
|
+
*/
|
|
2258
|
+
retrySave(): Promise<void>;
|
|
2259
|
+
/**
|
|
2260
|
+
* The full document state (a Yjs update) while local edits are unsaved, else
|
|
2261
|
+
* null. Keep it as a recovery copy when saves keep failing.
|
|
2262
|
+
*/
|
|
2263
|
+
getUnsavedState(): Uint8Array | null;
|
|
2264
|
+
/** Stop syncing; edits still waiting for the debounced save are saved first. */
|
|
2181
2265
|
destroy(): void;
|
|
2182
2266
|
}
|
|
2183
2267
|
|
|
2184
2268
|
/**
|
|
2185
2269
|
* Framework-agnostic richtext binding: Yjs document lifecycle, persistence,
|
|
2186
2270
|
* incremental doc channel, and awareness cursors.
|
|
2271
|
+
*
|
|
2272
|
+
* Every save writes the full state of the live Y.Doc, which holds every local edit
|
|
2273
|
+
* and every merged remote change, so a stored change arriving while a save waits
|
|
2274
|
+
* cannot drop local typing. A refused save keeps the edits unsaved
|
|
2275
|
+
* (`hasUnsavedChanges`, `getUnsavedState()`) and the next edit or `retrySave()`
|
|
2276
|
+
* saves them again; the first successful save clears `error`.
|
|
2187
2277
|
*/
|
|
2188
2278
|
declare function createRichTextController(options: CreateRichTextControllerOptions): RichTextController;
|
|
2189
2279
|
|
|
@@ -2750,4 +2840,4 @@ declare function createChunkPortPair(): {
|
|
|
2750
2840
|
b: ChunkMessagePort;
|
|
2751
2841
|
};
|
|
2752
2842
|
|
|
2753
|
-
export { AdapterError, AdoptionSchedule, ApplyRemoteOptions, type AuditExportManifest, type AuditExportOptions, type AuditExportPayload, type AuditExportProgress, type AuditTraceQuery, BACKUP_VERSION, BackupFormatError, type BackupManifest, type BackupOptions, type BackupProgress, type BlobGcOptions, type BlobGcResult, type BlobManifest, type BlobManifestMetadata, BridgeTerminatedError, COMPACTION_BASELINE_META_KEY, type ChunkMessage, type ChunkMessagePort, type ChunkProvider, type ChunkRequestMessage, type ChunkResponseMessage, type ClockRebaseResult, type CollectionAccessor, CollectionRecord, type CompactionResult, type CompactionStrategy, ContentAddressedBlobStore, type ConvertBackupV1Options, type CreateRichTextControllerOptions, DEFAULT_CHUNK_SIZE, InvalidStateTransitionError, LAST_ACKED_SERVER_VECTOR_META_KEY, LOG_QUARANTINE_TABLE, LeaderUnresponsiveError, LocalMutationHandler, LocalNodeRecord, type LogIntegrityReport, type LogIntegrityRow, type LogRowProblem, type LogSequenceGap, MaterializedRowSnapshot, MemoryBlobStore, NoLeaderError, type NodeRotationResult, type OpfsBlobDirectory, OpfsBlobStore, OptimisticLockError, OrderByDirection, type PersistedAuditTrace, PersistenceError, type PersistenceRequestReason, type PersistenceStorageManager, type PrincipalBinding, QueryBuilder, QueryDescriptor, QueryError, QueryStore, QueryStoreCache, QuerySubscriptionError, type ReceiveBlobResult, type ReceiveBlobStores, RecordNotFoundError, type RecordsChange, type RecordsChangeListener, type RegisterOptions, type RematerializationMode, type RemoteChunkProvider, type RemoteChunkProviderOptions, type ReplaySnapshot, RequestAbortedError, type ResequenceResult, type RestoreOptions, type RestoreResult, type ResultsEqual, type RichTextAwarenessUser, type RichTextController, type RichTextControllerSnapshot, type RichTextCursorInfo, type RichTextSyncEngine, RowVersionState, SchemaVersionAheadError, SequenceManager, type ServerBlobCallbacks, StorageAdapter, StorageBackendMismatchError, StorageDurabilityError, StorageInUseError, StoragePersistence, type StoragePersistenceOptions, type StoragePersistenceState, type StoragePersistenceStatus, Store, StoreConfig, StoreNotOpenError, SubscribeOptions, SubscriptionBloomFilter, SubscriptionCallback, SubscriptionManager, type SubscriptionManagerOptions, type SubscriptionStats, TerminalRejection, type TransactionCollectionAccessor, TransactionContext, type TransactionContextConfig, type UnappliedOperation, UnsyncedDataError, WhereClause, WorkerInitError, WorkerTimeoutError, asRichTextSyncEngine, assertQueryReady, chunkBlob, collectBlobGarbage, collectOperationsAheadOfServer, compactOperationLog, computeAckCompactionWatermark, convertBackupV1, createChunkPortPair, createMemoryServerBlobStore, createOpfsBlobDirectory, createOpfsBlobStore, createRemoteChunkProvider, createRichTextController, decodeAuditExport, decodeRichtext, deserializeVersionVectorFromMeta, encodeRichtext, exportBackup, extractBlobRefs, fetchBlobManifest, getSharedQueryStoreCache, mergeVersionVectors, normalizeWhere, parseBlobManifest, persistedAuditTraceFromEvent, pluralize, prepareBlobForSend, putBlobForTransfer, queryKey, readAuditExportManifest, readBackupManifest, reassembleBlob, receiveBlob, resolveBlobManifest, restoreBackup, richtextStatesEqual, richtextToPlainText, serializeBlobManifest, serializeVersionVectorToMeta, serveBlobChunks, singularize, toServerBlobCallbacks, validateStateTransition, validateUpdateStateMachine, verifyAuditExportChecksum, verifyBackupChecksum };
|
|
2843
|
+
export { AdapterError, AdoptionSchedule, ApplyRemoteOptions, type AuditExportManifest, type AuditExportOptions, type AuditExportPayload, type AuditExportProgress, type AuditTraceQuery, BACKUP_VERSION, BackupFormatError, type BackupManifest, type BackupOptions, type BackupProgress, type BlobGcOptions, type BlobGcResult, type BlobManifest, type BlobManifestMetadata, BridgeTerminatedError, COMPACTION_BASELINE_META_KEY, type ChunkMessage, type ChunkMessagePort, type ChunkProvider, type ChunkRequestMessage, type ChunkResponseMessage, type ClockRebaseResult, type CollectionAccessor, CollectionRecord, type CompactionResult, type CompactionStrategy, ContentAddressedBlobStore, type ConvertBackupV1Options, type CreateRichTextControllerOptions, DEFAULT_CHUNK_SIZE, InvalidStateTransitionError, LAST_ACKED_SERVER_VECTOR_META_KEY, LOG_QUARANTINE_TABLE, LeaderUnresponsiveError, LocalMutationHandler, LocalNodeRecord, type LogIntegrityReport, type LogIntegrityRow, type LogRowProblem, type LogSequenceGap, MaterializedRowSnapshot, MemoryBlobStore, NoLeaderError, NodeOwnedByAnotherUserError, type NodeRotationResult, type OpfsBlobDirectory, OpfsBlobStore, OptimisticLockError, OrderByDirection, type PersistedAuditTrace, PersistenceError, type PersistenceRequestReason, type PersistenceStorageManager, type PrincipalBinding, QueryBuilder, QueryDescriptor, QueryError, QueryStore, QueryStoreCache, QuerySubscriptionError, type ReceiveBlobResult, type ReceiveBlobStores, RecordNotFoundError, type RecordsChange, type RecordsChangeListener, type RegisterOptions, type RematerializationMode, type RemoteChunkProvider, type RemoteChunkProviderOptions, type ReplaySnapshot, RequestAbortedError, type ResequenceResult, type RestoreOptions, type RestoreResult, type ResultsEqual, type RichTextAwarenessUser, type RichTextController, type RichTextControllerSnapshot, type RichTextCursorInfo, type RichTextSyncEngine, RowVersionState, SchemaVersionAheadError, SequenceManager, type ServerBlobCallbacks, StorageAdapter, StorageBackendMismatchError, StorageDurabilityError, StorageInUseError, StoragePersistence, type StoragePersistenceOptions, type StoragePersistenceState, type StoragePersistenceStatus, Store, StoreConfig, StoreNotOpenError, SubscribeOptions, SubscriptionBloomFilter, SubscriptionCallback, SubscriptionManager, type SubscriptionManagerOptions, type SubscriptionStats, TerminalRejection, type TransactionCollectionAccessor, TransactionContext, type TransactionContextConfig, type UnappliedOperation, UnsyncedDataError, WhereClause, WorkerInitError, WorkerTimeoutError, asRichTextSyncEngine, assertQueryReady, chunkBlob, collectBlobGarbage, collectOperationsAheadOfServer, compactOperationLog, computeAckCompactionWatermark, convertBackupV1, createChunkPortPair, createMemoryServerBlobStore, createOpfsBlobDirectory, createOpfsBlobStore, createRemoteChunkProvider, createRichTextController, decodeAuditExport, decodeRichtext, deserializeVersionVectorFromMeta, encodeRichtext, exportBackup, extractBlobRefs, fetchBlobManifest, getSharedQueryStoreCache, mergeVersionVectors, normalizeWhere, parseBlobManifest, persistedAuditTraceFromEvent, pluralize, prepareBlobForSend, putBlobForTransfer, queryKey, readAuditExportManifest, readBackupManifest, reassembleBlob, receiveBlob, resolveBlobManifest, restoreBackup, richtextStatesEqual, richtextToPlainText, serializeBlobManifest, serializeVersionVectorToMeta, serveBlobChunks, singularize, toServerBlobCallbacks, validateStateTransition, validateUpdateStateMachine, verifyAuditExportChecksum, verifyBackupChecksum };
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
pluralize,
|
|
21
21
|
queryKey,
|
|
22
22
|
singularize
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-5AQSGMJV.js";
|
|
24
24
|
import {
|
|
25
25
|
BlobIntegrityError,
|
|
26
26
|
MemoryBlobStore
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
InvalidStateTransitionError,
|
|
30
30
|
validateStateTransition,
|
|
31
31
|
validateUpdateStateMachine
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-BILSA6XZ.js";
|
|
33
33
|
import "./chunk-A6GFH5IG.js";
|
|
34
34
|
import {
|
|
35
35
|
BACKUP_VERSION,
|
|
@@ -41,10 +41,10 @@ import {
|
|
|
41
41
|
readBackupManifest,
|
|
42
42
|
restoreBackup,
|
|
43
43
|
verifyBackupChecksum
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-UC2LGFPV.js";
|
|
45
45
|
import {
|
|
46
46
|
mergeYjsUpdates
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-KTVNANUH.js";
|
|
48
48
|
import {
|
|
49
49
|
LAST_ACKED_SERVER_VECTOR_META_KEY,
|
|
50
50
|
VIRTUAL_TIMESTAMP_FIELDS,
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
deserializeVersionVectorFromMeta,
|
|
54
54
|
mergeVersionVectors,
|
|
55
55
|
serializeVersionVectorToMeta
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-QW4UU7NG.js";
|
|
57
57
|
import {
|
|
58
58
|
decodeRichtext,
|
|
59
59
|
encodeRichtext,
|
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
BridgeTerminatedError,
|
|
66
66
|
LeaderUnresponsiveError,
|
|
67
67
|
NoLeaderError,
|
|
68
|
+
NodeOwnedByAnotherUserError,
|
|
68
69
|
OptimisticLockError,
|
|
69
70
|
PersistenceError,
|
|
70
71
|
QueryError,
|
|
@@ -78,7 +79,7 @@ import {
|
|
|
78
79
|
UnsyncedDataError,
|
|
79
80
|
WorkerInitError,
|
|
80
81
|
WorkerTimeoutError
|
|
81
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-SRHDJF5B.js";
|
|
82
83
|
|
|
83
84
|
// src/persistence/storage-persistence.ts
|
|
84
85
|
function defaultStorageManager() {
|
|
@@ -355,7 +356,6 @@ var LOAD_ORIGIN = "kora-load";
|
|
|
355
356
|
var REMOTE_ORIGIN = "kora-remote";
|
|
356
357
|
var DOC_CHANNEL_ORIGIN = "kora-doc-channel";
|
|
357
358
|
var TEXT_KEY = "content";
|
|
358
|
-
var COMPACT_AFTER_DELTAS = 20;
|
|
359
359
|
var PERSIST_DEBOUNCE_MS = 400;
|
|
360
360
|
function createRichTextController(options) {
|
|
361
361
|
const {
|
|
@@ -377,16 +377,19 @@ function createRichTextController(options) {
|
|
|
377
377
|
let canUndo = false;
|
|
378
378
|
let canRedo = false;
|
|
379
379
|
let cursors = [];
|
|
380
|
+
let editGeneration = 0;
|
|
381
|
+
let savedGeneration = 0;
|
|
382
|
+
let saving = null;
|
|
383
|
+
let saveAgain = false;
|
|
380
384
|
const listeners = /* @__PURE__ */ new Set();
|
|
381
385
|
let snapshot = {
|
|
382
386
|
ready: false,
|
|
383
387
|
error: null,
|
|
384
388
|
canUndo: false,
|
|
385
389
|
canRedo: false,
|
|
386
|
-
cursors: []
|
|
390
|
+
cursors: [],
|
|
391
|
+
hasUnsavedChanges: false
|
|
387
392
|
};
|
|
388
|
-
const baseUpdateRef = { current: null };
|
|
389
|
-
const pendingDeltasRef = { current: [] };
|
|
390
393
|
const docChannelActiveRef = { current: false };
|
|
391
394
|
let persistTimer = null;
|
|
392
395
|
let recordUnsubscribe = null;
|
|
@@ -398,7 +401,8 @@ function createRichTextController(options) {
|
|
|
398
401
|
error,
|
|
399
402
|
canUndo,
|
|
400
403
|
canRedo,
|
|
401
|
-
cursors: [...cursors]
|
|
404
|
+
cursors: [...cursors],
|
|
405
|
+
hasUnsavedChanges: editGeneration > savedGeneration
|
|
402
406
|
};
|
|
403
407
|
};
|
|
404
408
|
const notify = () => {
|
|
@@ -469,26 +473,38 @@ function createRichTextController(options) {
|
|
|
469
473
|
return;
|
|
470
474
|
}
|
|
471
475
|
Y.applyUpdate(doc, encoded, REMOTE_ORIGIN);
|
|
472
|
-
baseUpdateRef.current = encoded;
|
|
473
|
-
pendingDeltasRef.current = [];
|
|
474
476
|
syncHistoryState();
|
|
475
477
|
};
|
|
476
|
-
const
|
|
477
|
-
const
|
|
478
|
-
|
|
479
|
-
baseUpdateRef.current = snapshot2;
|
|
480
|
-
pendingDeltasRef.current = [];
|
|
481
|
-
}
|
|
478
|
+
const persistOnce = async () => {
|
|
479
|
+
const generation = editGeneration;
|
|
480
|
+
const state = Y.encodeStateAsUpdate(doc);
|
|
482
481
|
try {
|
|
483
482
|
await collection.update(recordId, {
|
|
484
|
-
[fieldName]:
|
|
483
|
+
[fieldName]: state
|
|
485
484
|
});
|
|
485
|
+
if (generation > savedGeneration) savedGeneration = generation;
|
|
486
|
+
error = null;
|
|
486
487
|
} catch (cause) {
|
|
487
|
-
|
|
488
|
-
error = cause instanceof Error ? cause : new Error(String(cause));
|
|
489
|
-
notify();
|
|
490
|
-
}
|
|
488
|
+
error = cause instanceof Error ? cause : new Error(String(cause));
|
|
491
489
|
}
|
|
490
|
+
if (!disposed) notify();
|
|
491
|
+
};
|
|
492
|
+
const flushPersist = () => {
|
|
493
|
+
if (saving) {
|
|
494
|
+
saveAgain = true;
|
|
495
|
+
return saving;
|
|
496
|
+
}
|
|
497
|
+
const run = (async () => {
|
|
498
|
+
do {
|
|
499
|
+
saveAgain = false;
|
|
500
|
+
await persistOnce();
|
|
501
|
+
} while (saveAgain);
|
|
502
|
+
})();
|
|
503
|
+
saving = run;
|
|
504
|
+
void run.finally(() => {
|
|
505
|
+
if (saving === run) saving = null;
|
|
506
|
+
});
|
|
507
|
+
return run;
|
|
492
508
|
};
|
|
493
509
|
const schedulePersist = () => {
|
|
494
510
|
if (persistTimer) {
|
|
@@ -504,7 +520,7 @@ function createRichTextController(options) {
|
|
|
504
520
|
if (origin === LOAD_ORIGIN || origin === REMOTE_ORIGIN || origin === DOC_CHANNEL_ORIGIN) {
|
|
505
521
|
return;
|
|
506
522
|
}
|
|
507
|
-
|
|
523
|
+
editGeneration += 1;
|
|
508
524
|
if (docChannelActiveRef.current && syncEngine) {
|
|
509
525
|
syncEngine.getRichtextDocChannel?.().send(collectionName, recordId, fieldName, update);
|
|
510
526
|
schedulePersist();
|
|
@@ -588,8 +604,6 @@ function createRichTextController(options) {
|
|
|
588
604
|
target.delete(0, target.length);
|
|
589
605
|
}, LOAD_ORIGIN);
|
|
590
606
|
const encoded = encodeRichtextInput(record?.[fieldName]);
|
|
591
|
-
baseUpdateRef.current = encoded;
|
|
592
|
-
pendingDeltasRef.current = [];
|
|
593
607
|
if (encoded) {
|
|
594
608
|
Y.applyUpdate(doc, encoded, LOAD_ORIGIN);
|
|
595
609
|
}
|
|
@@ -632,6 +646,16 @@ function createRichTextController(options) {
|
|
|
632
646
|
setUser(nextUser) {
|
|
633
647
|
user = nextUser;
|
|
634
648
|
},
|
|
649
|
+
retrySave() {
|
|
650
|
+
if (persistTimer) {
|
|
651
|
+
clearTimeout(persistTimer);
|
|
652
|
+
persistTimer = null;
|
|
653
|
+
}
|
|
654
|
+
return flushPersist();
|
|
655
|
+
},
|
|
656
|
+
getUnsavedState() {
|
|
657
|
+
return editGeneration > savedGeneration ? Y.encodeStateAsUpdate(doc) : null;
|
|
658
|
+
},
|
|
635
659
|
destroy() {
|
|
636
660
|
if (disposed) {
|
|
637
661
|
return;
|
|
@@ -641,14 +665,15 @@ function createRichTextController(options) {
|
|
|
641
665
|
clearTimeout(persistTimer);
|
|
642
666
|
persistTimer = null;
|
|
643
667
|
}
|
|
668
|
+
if (editGeneration > savedGeneration) {
|
|
669
|
+
void flushPersist();
|
|
670
|
+
}
|
|
644
671
|
doc.off("update", onDocUpdate);
|
|
645
672
|
recordUnsubscribe?.();
|
|
646
673
|
docChannelUnsubscribe?.();
|
|
647
674
|
awarenessUnsubscribe?.();
|
|
648
675
|
clearCursor();
|
|
649
676
|
undoManager.destroy();
|
|
650
|
-
baseUpdateRef.current = null;
|
|
651
|
-
pendingDeltasRef.current = [];
|
|
652
677
|
docChannelActiveRef.current = false;
|
|
653
678
|
listeners.clear();
|
|
654
679
|
}
|
|
@@ -669,16 +694,6 @@ function encodeRichtextInput(value) {
|
|
|
669
694
|
throw new Error("Richtext record value must be a string, Uint8Array, ArrayBuffer, or null.");
|
|
670
695
|
}
|
|
671
696
|
}
|
|
672
|
-
function composeRichtextSnapshot(base, deltas) {
|
|
673
|
-
const mergedDoc = new Y.Doc();
|
|
674
|
-
if (base) {
|
|
675
|
-
Y.applyUpdate(mergedDoc, base);
|
|
676
|
-
}
|
|
677
|
-
for (const delta of deltas) {
|
|
678
|
-
Y.applyUpdate(mergedDoc, delta);
|
|
679
|
-
}
|
|
680
|
-
return Y.encodeStateAsUpdate(mergedDoc);
|
|
681
|
-
}
|
|
682
697
|
function updatesEqual(left, right) {
|
|
683
698
|
if (left.length !== right.length) {
|
|
684
699
|
return false;
|
|
@@ -1241,6 +1256,7 @@ export {
|
|
|
1241
1256
|
LeaderUnresponsiveError,
|
|
1242
1257
|
MemoryBlobStore,
|
|
1243
1258
|
NoLeaderError,
|
|
1259
|
+
NodeOwnedByAnotherUserError,
|
|
1244
1260
|
OpfsBlobStore,
|
|
1245
1261
|
OptimisticLockError,
|
|
1246
1262
|
PersistenceError,
|