@korajs/core 0.5.0 → 1.0.0-beta.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/LICENSE +21 -0
- package/dist/bindings/index.cjs +105 -0
- package/dist/bindings/index.cjs.map +1 -0
- package/dist/bindings/index.d.cts +103 -0
- package/dist/bindings/index.d.ts +103 -0
- package/dist/bindings/index.js +78 -0
- package/dist/bindings/index.js.map +1 -0
- package/dist/build-scope-map-BIeawJzC.d.cts +33 -0
- package/dist/build-scope-map-DOf4JLTh.d.ts +33 -0
- package/dist/{chunk-H4FXU5OP.js → chunk-5IICSH6H.js} +159 -7
- package/dist/chunk-5IICSH6H.js.map +1 -0
- package/dist/{events-BeIEDJBW.d.cts → events-BynBOsO3.d.cts} +14 -93
- package/dist/{events-BeIEDJBW.d.ts → events-BynBOsO3.d.ts} +14 -93
- package/dist/index.cjs +284 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -33
- package/dist/index.d.ts +79 -33
- package/dist/index.js +125 -3
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +142 -17
- 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 +1 -1
- package/dist/operation-BpZlYSpe.d.cts +164 -0
- package/dist/operation-D5WOZYvy.d.ts +164 -0
- package/package.json +11 -1
- package/dist/chunk-H4FXU5OP.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { R as RandomSource, A as AtomicOpType, a as AtomicOp, F as FieldBuilder, C as CustomResolver, M as MigrationDefinition, S as SchemaDefinition, b as CollectionDefinition, c as RelationDefinition, O as OperationType, E as EnumFieldBuilder, d as ArrayFieldBuilder, e as FieldKind, f as Operation, V as VersionVector, g as MigrationStep, h as StateMachineConstraint, T as TransitionMap, i as TransitionValidationResult } from './events-
|
|
2
|
-
export { j as CONNECTION_QUALITIES, k as ConnectionQuality, l as Constraint, m as FieldDescriptor, n as FieldMergeStrategy, H as HLCTimestamp,
|
|
1
|
+
import { R as RandomSource, A as AtomicOpType, a as AtomicOp, F as FieldBuilder, C as CustomResolver, M as MigrationDefinition, S as SchemaDefinition, b as CollectionDefinition, c as RelationDefinition, O as OperationType, E as EnumFieldBuilder, d as ArrayFieldBuilder, e as FieldKind, f as Operation, V as VersionVector, g as MigrationStep, h as StateMachineConstraint, T as TransitionMap, i as TransitionValidationResult } from './events-BynBOsO3.cjs';
|
|
2
|
+
export { j as CONNECTION_QUALITIES, k as ConnectionQuality, l as Constraint, m as FieldDescriptor, n as FieldMergeStrategy, H as HLCTimestamp, K as KoraEvent, o as KoraEventByType, p as KoraEventEmitter, q as KoraEventListener, r as KoraEventType, s as MERGE_STRATEGIES, t as MergeStrategy, u as MergeTrace, v as MigrationBuilder, w as OnDeleteAction, x as OperationInput, y as RelationType, z as RollbackBuilder, B as SequenceConfig, D as StateMachineDefinition, G as SyncDiagnosticsSnapshot, I as SyncRuleDefinition, J as TimeSource, L as migrate, N as t } from './events-BynBOsO3.cjs';
|
|
3
|
+
export { H as HybridLogicalClock, M as MAX_LOGICAL, c as createOperation, i as isValidOperation, v as verifyOperationIntegrity } from './operation-BpZlYSpe.cjs';
|
|
4
|
+
export { S as ScopeMap, b as buildScopeMap } from './build-scope-map-BIeawJzC.cjs';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Base error class for all Kora errors.
|
|
@@ -59,10 +61,33 @@ declare class SyncError extends KoraError {
|
|
|
59
61
|
declare class StorageError extends KoraError {
|
|
60
62
|
constructor(message: string, context?: Record<string, unknown>);
|
|
61
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Thrown when collection/query APIs are used before {@link KoraApp.ready} resolves.
|
|
66
|
+
*/
|
|
67
|
+
declare class AppNotReadyError extends KoraError {
|
|
68
|
+
constructor(detail: string);
|
|
69
|
+
}
|
|
62
70
|
/**
|
|
63
71
|
* Thrown when the HLC detects excessive clock drift.
|
|
64
72
|
* Drift > 60s: warning. Drift > 5min: this error is thrown, refusing to generate timestamps.
|
|
65
73
|
*/
|
|
74
|
+
declare class RemoteClockDriftError extends KoraError {
|
|
75
|
+
readonly remoteWallTime: number;
|
|
76
|
+
readonly localReferenceTime: number;
|
|
77
|
+
constructor(remoteWallTime: number, localReferenceTime: number);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Thrown when an HLC timestamp has structurally invalid fields: non-integer or
|
|
81
|
+
* negative wallTime/logical, or a logical counter beyond the serializable cap.
|
|
82
|
+
* Rejected BEFORE any clock state changes, so a malformed remote timestamp can
|
|
83
|
+
* never corrupt a replica's clock or break the lexicographic ordering of the
|
|
84
|
+
* serialized form.
|
|
85
|
+
*/
|
|
86
|
+
declare class InvalidTimestampError extends KoraError {
|
|
87
|
+
readonly wallTime: number;
|
|
88
|
+
readonly logical: number;
|
|
89
|
+
constructor(message: string, wallTime: number, logical: number);
|
|
90
|
+
}
|
|
66
91
|
declare class ClockDriftError extends KoraError {
|
|
67
92
|
readonly currentHlcTime: number;
|
|
68
93
|
readonly physicalTime: number;
|
|
@@ -281,6 +306,57 @@ declare const op: {
|
|
|
281
306
|
*/
|
|
282
307
|
declare function toAtomicOp(sentinel: AtomicOpSentinel): AtomicOp;
|
|
283
308
|
|
|
309
|
+
/**
|
|
310
|
+
* Canonical JSON-safe encoding of binary bytes stored inside `op.data` /
|
|
311
|
+
* `op.previousData` (currently richtext field values). A raw Uint8Array
|
|
312
|
+
* JSON-serializes to a numeric-key object and an ArrayBuffer to `{}` (silent
|
|
313
|
+
* data loss), which breaks content-hash stability, persistence round-trips,
|
|
314
|
+
* remote application, and merge. Tagging the bytes as base64 at
|
|
315
|
+
* operation-creation time makes the hashed value, the persisted JSON, the wire
|
|
316
|
+
* payload, and the value the merge engine sees the identical canonical value.
|
|
317
|
+
*
|
|
318
|
+
* This convention lives in `@korajs/core` because `op.data` is a core concept:
|
|
319
|
+
* both `@korajs/store` (persistence, creation) and `@korajs/merge` (CRDT merge)
|
|
320
|
+
* must agree on it, and neither may depend on the other.
|
|
321
|
+
*/
|
|
322
|
+
interface KoraBytesValue {
|
|
323
|
+
$koraBytes: string;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Type guard for the tagged binary form. Requires exactly the single
|
|
327
|
+
* `$koraBytes` key so arbitrary user objects that happen to contain the key
|
|
328
|
+
* are never silently reinterpreted as bytes.
|
|
329
|
+
*/
|
|
330
|
+
declare function isKoraBytesValue(value: unknown): value is KoraBytesValue;
|
|
331
|
+
/**
|
|
332
|
+
* Detects the numeric-key object shape a raw Uint8Array produced when
|
|
333
|
+
* JSON-serialized before the tagged encoding existed ({"0":1,"1":2,...}).
|
|
334
|
+
*/
|
|
335
|
+
declare function isLegacyNumericByteObject(value: unknown): value is Record<string, number>;
|
|
336
|
+
/**
|
|
337
|
+
* Dependency-free base64 encoder. btoa is unavailable for bytes in Node and
|
|
338
|
+
* Buffer is unavailable in browsers, so a manual implementation is the only
|
|
339
|
+
* deterministic option that works in every runtime Kora targets.
|
|
340
|
+
*/
|
|
341
|
+
declare function bytesToBase64(bytes: Uint8Array): string;
|
|
342
|
+
/**
|
|
343
|
+
* Inverse of {@link bytesToBase64}.
|
|
344
|
+
*/
|
|
345
|
+
declare function base64ToBytes(base64: string): Uint8Array;
|
|
346
|
+
/**
|
|
347
|
+
* Normalize a validated binary-or-string value into the canonical form stored
|
|
348
|
+
* in `op.data`: strings pass through unchanged (backward compatible with every
|
|
349
|
+
* existing operation), binary values become the tagged base64 form.
|
|
350
|
+
*/
|
|
351
|
+
declare function encodeBytesForOpData(value: string | Uint8Array | ArrayBuffer): string | KoraBytesValue;
|
|
352
|
+
/**
|
|
353
|
+
* Reverse of {@link encodeBytesForOpData}, tolerant of every shape a binary
|
|
354
|
+
* op-data value has ever taken: canonical strings and tagged bytes, in-memory
|
|
355
|
+
* Uint8Array/ArrayBuffer (ops that never round-tripped through JSON), and
|
|
356
|
+
* pre-fix numeric-key objects.
|
|
357
|
+
*/
|
|
358
|
+
declare function decodeBytesFromOpData(value: unknown): string | Uint8Array;
|
|
359
|
+
|
|
284
360
|
/**
|
|
285
361
|
* Input shape for defineSchema() — what the developer writes.
|
|
286
362
|
*/
|
|
@@ -546,36 +622,6 @@ declare function isCollectionSyncScoped(schema: SchemaDefinition, collectionName
|
|
|
546
622
|
*/
|
|
547
623
|
declare function collectSchemaScopeValueKeys(schema: SchemaDefinition): string[];
|
|
548
624
|
|
|
549
|
-
/**
|
|
550
|
-
* Per-collection scope map: `{ collectionName: { field: value, ... } }`
|
|
551
|
-
*
|
|
552
|
-
* Used to filter which operations a client should receive during sync.
|
|
553
|
-
*/
|
|
554
|
-
type ScopeMap = Record<string, Record<string, unknown>>;
|
|
555
|
-
/**
|
|
556
|
-
* Build a per-collection scope map from the schema's scope declarations
|
|
557
|
-
* and the client's flat scope values.
|
|
558
|
-
*
|
|
559
|
-
* Supports both legacy `collection.scope` arrays and declarative `schema.sync`
|
|
560
|
-
* rules (`sync: { todos: { where: { userId: true } } }`).
|
|
561
|
-
*
|
|
562
|
-
* When `schema.sync` is present, only collections with sync rules or legacy
|
|
563
|
-
* scope fields are included in the result. Other collections are omitted so
|
|
564
|
-
* sync engines treat them as out of scope (partial sync).
|
|
565
|
-
*
|
|
566
|
-
* @param schema - The schema definition with scope declarations
|
|
567
|
-
* @param scopeValues - Flat key-value scope values from the client
|
|
568
|
-
* @returns A per-collection scope map
|
|
569
|
-
*
|
|
570
|
-
* @example
|
|
571
|
-
* ```typescript
|
|
572
|
-
* // Schema declares: sales.scope = ['orgId', 'storeId']
|
|
573
|
-
* // Client provides: { orgId: 'org-123', storeId: 'store-456' }
|
|
574
|
-
* // Result: { sales: { orgId: 'org-123', storeId: 'store-456' }, products: {} }
|
|
575
|
-
* ```
|
|
576
|
-
*/
|
|
577
|
-
declare function buildScopeMap(schema: SchemaDefinition, scopeValues: Record<string, unknown>): ScopeMap;
|
|
578
|
-
|
|
579
625
|
/**
|
|
580
626
|
* Collect every unique scope field name declared across all collections.
|
|
581
627
|
*
|
|
@@ -864,4 +910,4 @@ interface ProtoOutput {
|
|
|
864
910
|
*/
|
|
865
911
|
declare function generateProtoDefinitions(schema: SchemaDefinition): ProtoOutput;
|
|
866
912
|
|
|
867
|
-
export { APPLY_FAILURE_CODES, APPLY_RESULTS, type ApplyFailureReason, type ApplyResult, ArrayFieldBuilder, AtomicOp, type AtomicOpSentinel, AtomicOpType, CausalTracker, ClockDriftError, CollectionDefinition, type CollectionInput, type ConstraintInput, CustomResolver, EnumFieldBuilder, FieldBuilder, FieldKind, type FieldKindToType, type InferFieldType, type InferInsertInput, type InferRecord, type InferUpdateInput, KORA_ERROR_FIX_SUGGESTIONS, KoraError, MergeConflictError, MigrationDefinition, MigrationRollbackError, MigrationStep, Operation, OperationError, type OperationLog, type OperationTransform, OperationType, type ProtoOutput, RandomSource, RelationDefinition, type RelationInput, type ReversibleMigration, SchemaDefinition, type SchemaInput, SchemaValidationError,
|
|
913
|
+
export { APPLY_FAILURE_CODES, APPLY_RESULTS, AppNotReadyError, type ApplyFailureReason, type ApplyResult, ArrayFieldBuilder, AtomicOp, type AtomicOpSentinel, AtomicOpType, CausalTracker, ClockDriftError, CollectionDefinition, type CollectionInput, type ConstraintInput, CustomResolver, EnumFieldBuilder, FieldBuilder, FieldKind, type FieldKindToType, type InferFieldType, type InferInsertInput, type InferRecord, type InferUpdateInput, InvalidTimestampError, KORA_ERROR_FIX_SUGGESTIONS, type KoraBytesValue, KoraError, MergeConflictError, MigrationDefinition, MigrationRollbackError, MigrationStep, Operation, OperationError, type OperationLog, type OperationTransform, OperationType, type ProtoOutput, RandomSource, RelationDefinition, type RelationInput, RemoteClockDriftError, type ReversibleMigration, SchemaDefinition, type SchemaInput, SchemaValidationError, StateMachineConstraint, type StateMachineInput, StorageError, SyncError, TransitionMap, TransitionValidationResult, type TypedSchemaDefinition, VersionVector, advanceVector, applyOperationTransforms, base64ToBytes, buildStateMachineConstraints, bytesToBase64, canAutoRollback, collectSchemaScopeFields, collectSchemaScopeValueKeys, computeDelta, createReversibleMigration, createVersionVector, decodeBytesFromOpData, defaultApplyFailureReason, defaultSequenceFormat, defineSchema, deserializeVector, dominates, encodeBytesForOpData, extractScopeValuesFromClaims, extractTimestamp, formatSequenceValue, generateFullDDL, generateProtoDefinitions, generateRollbackSteps, generateSQL, generateUUIDv7, getCollectionScopeBindings, getKoraErrorFix, getTransitionMap, hasSchemaSyncRules, isApplyFailure, isAtomicOp, isCollectionSyncScoped, isKoraBytesValue, isLegacyNumericByteObject, isValidUUIDv7, mergeVectors, migrationStepsToSQL, op, resolveAtomicOp, rollbackStepsToSQL, serializeVector, toAtomicOp, validateRecord, validateTransition, vectorsEqual };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { R as RandomSource, A as AtomicOpType, a as AtomicOp, F as FieldBuilder, C as CustomResolver, M as MigrationDefinition, S as SchemaDefinition, b as CollectionDefinition, c as RelationDefinition, O as OperationType, E as EnumFieldBuilder, d as ArrayFieldBuilder, e as FieldKind, f as Operation, V as VersionVector, g as MigrationStep, h as StateMachineConstraint, T as TransitionMap, i as TransitionValidationResult } from './events-
|
|
2
|
-
export { j as CONNECTION_QUALITIES, k as ConnectionQuality, l as Constraint, m as FieldDescriptor, n as FieldMergeStrategy, H as HLCTimestamp,
|
|
1
|
+
import { R as RandomSource, A as AtomicOpType, a as AtomicOp, F as FieldBuilder, C as CustomResolver, M as MigrationDefinition, S as SchemaDefinition, b as CollectionDefinition, c as RelationDefinition, O as OperationType, E as EnumFieldBuilder, d as ArrayFieldBuilder, e as FieldKind, f as Operation, V as VersionVector, g as MigrationStep, h as StateMachineConstraint, T as TransitionMap, i as TransitionValidationResult } from './events-BynBOsO3.js';
|
|
2
|
+
export { j as CONNECTION_QUALITIES, k as ConnectionQuality, l as Constraint, m as FieldDescriptor, n as FieldMergeStrategy, H as HLCTimestamp, K as KoraEvent, o as KoraEventByType, p as KoraEventEmitter, q as KoraEventListener, r as KoraEventType, s as MERGE_STRATEGIES, t as MergeStrategy, u as MergeTrace, v as MigrationBuilder, w as OnDeleteAction, x as OperationInput, y as RelationType, z as RollbackBuilder, B as SequenceConfig, D as StateMachineDefinition, G as SyncDiagnosticsSnapshot, I as SyncRuleDefinition, J as TimeSource, L as migrate, N as t } from './events-BynBOsO3.js';
|
|
3
|
+
export { H as HybridLogicalClock, M as MAX_LOGICAL, c as createOperation, i as isValidOperation, v as verifyOperationIntegrity } from './operation-D5WOZYvy.js';
|
|
4
|
+
export { S as ScopeMap, b as buildScopeMap } from './build-scope-map-DOf4JLTh.js';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Base error class for all Kora errors.
|
|
@@ -59,10 +61,33 @@ declare class SyncError extends KoraError {
|
|
|
59
61
|
declare class StorageError extends KoraError {
|
|
60
62
|
constructor(message: string, context?: Record<string, unknown>);
|
|
61
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Thrown when collection/query APIs are used before {@link KoraApp.ready} resolves.
|
|
66
|
+
*/
|
|
67
|
+
declare class AppNotReadyError extends KoraError {
|
|
68
|
+
constructor(detail: string);
|
|
69
|
+
}
|
|
62
70
|
/**
|
|
63
71
|
* Thrown when the HLC detects excessive clock drift.
|
|
64
72
|
* Drift > 60s: warning. Drift > 5min: this error is thrown, refusing to generate timestamps.
|
|
65
73
|
*/
|
|
74
|
+
declare class RemoteClockDriftError extends KoraError {
|
|
75
|
+
readonly remoteWallTime: number;
|
|
76
|
+
readonly localReferenceTime: number;
|
|
77
|
+
constructor(remoteWallTime: number, localReferenceTime: number);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Thrown when an HLC timestamp has structurally invalid fields: non-integer or
|
|
81
|
+
* negative wallTime/logical, or a logical counter beyond the serializable cap.
|
|
82
|
+
* Rejected BEFORE any clock state changes, so a malformed remote timestamp can
|
|
83
|
+
* never corrupt a replica's clock or break the lexicographic ordering of the
|
|
84
|
+
* serialized form.
|
|
85
|
+
*/
|
|
86
|
+
declare class InvalidTimestampError extends KoraError {
|
|
87
|
+
readonly wallTime: number;
|
|
88
|
+
readonly logical: number;
|
|
89
|
+
constructor(message: string, wallTime: number, logical: number);
|
|
90
|
+
}
|
|
66
91
|
declare class ClockDriftError extends KoraError {
|
|
67
92
|
readonly currentHlcTime: number;
|
|
68
93
|
readonly physicalTime: number;
|
|
@@ -281,6 +306,57 @@ declare const op: {
|
|
|
281
306
|
*/
|
|
282
307
|
declare function toAtomicOp(sentinel: AtomicOpSentinel): AtomicOp;
|
|
283
308
|
|
|
309
|
+
/**
|
|
310
|
+
* Canonical JSON-safe encoding of binary bytes stored inside `op.data` /
|
|
311
|
+
* `op.previousData` (currently richtext field values). A raw Uint8Array
|
|
312
|
+
* JSON-serializes to a numeric-key object and an ArrayBuffer to `{}` (silent
|
|
313
|
+
* data loss), which breaks content-hash stability, persistence round-trips,
|
|
314
|
+
* remote application, and merge. Tagging the bytes as base64 at
|
|
315
|
+
* operation-creation time makes the hashed value, the persisted JSON, the wire
|
|
316
|
+
* payload, and the value the merge engine sees the identical canonical value.
|
|
317
|
+
*
|
|
318
|
+
* This convention lives in `@korajs/core` because `op.data` is a core concept:
|
|
319
|
+
* both `@korajs/store` (persistence, creation) and `@korajs/merge` (CRDT merge)
|
|
320
|
+
* must agree on it, and neither may depend on the other.
|
|
321
|
+
*/
|
|
322
|
+
interface KoraBytesValue {
|
|
323
|
+
$koraBytes: string;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Type guard for the tagged binary form. Requires exactly the single
|
|
327
|
+
* `$koraBytes` key so arbitrary user objects that happen to contain the key
|
|
328
|
+
* are never silently reinterpreted as bytes.
|
|
329
|
+
*/
|
|
330
|
+
declare function isKoraBytesValue(value: unknown): value is KoraBytesValue;
|
|
331
|
+
/**
|
|
332
|
+
* Detects the numeric-key object shape a raw Uint8Array produced when
|
|
333
|
+
* JSON-serialized before the tagged encoding existed ({"0":1,"1":2,...}).
|
|
334
|
+
*/
|
|
335
|
+
declare function isLegacyNumericByteObject(value: unknown): value is Record<string, number>;
|
|
336
|
+
/**
|
|
337
|
+
* Dependency-free base64 encoder. btoa is unavailable for bytes in Node and
|
|
338
|
+
* Buffer is unavailable in browsers, so a manual implementation is the only
|
|
339
|
+
* deterministic option that works in every runtime Kora targets.
|
|
340
|
+
*/
|
|
341
|
+
declare function bytesToBase64(bytes: Uint8Array): string;
|
|
342
|
+
/**
|
|
343
|
+
* Inverse of {@link bytesToBase64}.
|
|
344
|
+
*/
|
|
345
|
+
declare function base64ToBytes(base64: string): Uint8Array;
|
|
346
|
+
/**
|
|
347
|
+
* Normalize a validated binary-or-string value into the canonical form stored
|
|
348
|
+
* in `op.data`: strings pass through unchanged (backward compatible with every
|
|
349
|
+
* existing operation), binary values become the tagged base64 form.
|
|
350
|
+
*/
|
|
351
|
+
declare function encodeBytesForOpData(value: string | Uint8Array | ArrayBuffer): string | KoraBytesValue;
|
|
352
|
+
/**
|
|
353
|
+
* Reverse of {@link encodeBytesForOpData}, tolerant of every shape a binary
|
|
354
|
+
* op-data value has ever taken: canonical strings and tagged bytes, in-memory
|
|
355
|
+
* Uint8Array/ArrayBuffer (ops that never round-tripped through JSON), and
|
|
356
|
+
* pre-fix numeric-key objects.
|
|
357
|
+
*/
|
|
358
|
+
declare function decodeBytesFromOpData(value: unknown): string | Uint8Array;
|
|
359
|
+
|
|
284
360
|
/**
|
|
285
361
|
* Input shape for defineSchema() — what the developer writes.
|
|
286
362
|
*/
|
|
@@ -546,36 +622,6 @@ declare function isCollectionSyncScoped(schema: SchemaDefinition, collectionName
|
|
|
546
622
|
*/
|
|
547
623
|
declare function collectSchemaScopeValueKeys(schema: SchemaDefinition): string[];
|
|
548
624
|
|
|
549
|
-
/**
|
|
550
|
-
* Per-collection scope map: `{ collectionName: { field: value, ... } }`
|
|
551
|
-
*
|
|
552
|
-
* Used to filter which operations a client should receive during sync.
|
|
553
|
-
*/
|
|
554
|
-
type ScopeMap = Record<string, Record<string, unknown>>;
|
|
555
|
-
/**
|
|
556
|
-
* Build a per-collection scope map from the schema's scope declarations
|
|
557
|
-
* and the client's flat scope values.
|
|
558
|
-
*
|
|
559
|
-
* Supports both legacy `collection.scope` arrays and declarative `schema.sync`
|
|
560
|
-
* rules (`sync: { todos: { where: { userId: true } } }`).
|
|
561
|
-
*
|
|
562
|
-
* When `schema.sync` is present, only collections with sync rules or legacy
|
|
563
|
-
* scope fields are included in the result. Other collections are omitted so
|
|
564
|
-
* sync engines treat them as out of scope (partial sync).
|
|
565
|
-
*
|
|
566
|
-
* @param schema - The schema definition with scope declarations
|
|
567
|
-
* @param scopeValues - Flat key-value scope values from the client
|
|
568
|
-
* @returns A per-collection scope map
|
|
569
|
-
*
|
|
570
|
-
* @example
|
|
571
|
-
* ```typescript
|
|
572
|
-
* // Schema declares: sales.scope = ['orgId', 'storeId']
|
|
573
|
-
* // Client provides: { orgId: 'org-123', storeId: 'store-456' }
|
|
574
|
-
* // Result: { sales: { orgId: 'org-123', storeId: 'store-456' }, products: {} }
|
|
575
|
-
* ```
|
|
576
|
-
*/
|
|
577
|
-
declare function buildScopeMap(schema: SchemaDefinition, scopeValues: Record<string, unknown>): ScopeMap;
|
|
578
|
-
|
|
579
625
|
/**
|
|
580
626
|
* Collect every unique scope field name declared across all collections.
|
|
581
627
|
*
|
|
@@ -864,4 +910,4 @@ interface ProtoOutput {
|
|
|
864
910
|
*/
|
|
865
911
|
declare function generateProtoDefinitions(schema: SchemaDefinition): ProtoOutput;
|
|
866
912
|
|
|
867
|
-
export { APPLY_FAILURE_CODES, APPLY_RESULTS, type ApplyFailureReason, type ApplyResult, ArrayFieldBuilder, AtomicOp, type AtomicOpSentinel, AtomicOpType, CausalTracker, ClockDriftError, CollectionDefinition, type CollectionInput, type ConstraintInput, CustomResolver, EnumFieldBuilder, FieldBuilder, FieldKind, type FieldKindToType, type InferFieldType, type InferInsertInput, type InferRecord, type InferUpdateInput, KORA_ERROR_FIX_SUGGESTIONS, KoraError, MergeConflictError, MigrationDefinition, MigrationRollbackError, MigrationStep, Operation, OperationError, type OperationLog, type OperationTransform, OperationType, type ProtoOutput, RandomSource, RelationDefinition, type RelationInput, type ReversibleMigration, SchemaDefinition, type SchemaInput, SchemaValidationError,
|
|
913
|
+
export { APPLY_FAILURE_CODES, APPLY_RESULTS, AppNotReadyError, type ApplyFailureReason, type ApplyResult, ArrayFieldBuilder, AtomicOp, type AtomicOpSentinel, AtomicOpType, CausalTracker, ClockDriftError, CollectionDefinition, type CollectionInput, type ConstraintInput, CustomResolver, EnumFieldBuilder, FieldBuilder, FieldKind, type FieldKindToType, type InferFieldType, type InferInsertInput, type InferRecord, type InferUpdateInput, InvalidTimestampError, KORA_ERROR_FIX_SUGGESTIONS, type KoraBytesValue, KoraError, MergeConflictError, MigrationDefinition, MigrationRollbackError, MigrationStep, Operation, OperationError, type OperationLog, type OperationTransform, OperationType, type ProtoOutput, RandomSource, RelationDefinition, type RelationInput, RemoteClockDriftError, type ReversibleMigration, SchemaDefinition, type SchemaInput, SchemaValidationError, StateMachineConstraint, type StateMachineInput, StorageError, SyncError, TransitionMap, TransitionValidationResult, type TypedSchemaDefinition, VersionVector, advanceVector, applyOperationTransforms, base64ToBytes, buildStateMachineConstraints, bytesToBase64, canAutoRollback, collectSchemaScopeFields, collectSchemaScopeValueKeys, computeDelta, createReversibleMigration, createVersionVector, decodeBytesFromOpData, defaultApplyFailureReason, defaultSequenceFormat, defineSchema, deserializeVector, dominates, encodeBytesForOpData, extractScopeValuesFromClaims, extractTimestamp, formatSequenceValue, generateFullDDL, generateProtoDefinitions, generateRollbackSteps, generateSQL, generateUUIDv7, getCollectionScopeBindings, getKoraErrorFix, getTransitionMap, hasSchemaSyncRules, isApplyFailure, isAtomicOp, isCollectionSyncScoped, isKoraBytesValue, isLegacyNumericByteObject, isValidUUIDv7, mergeVectors, migrationStepsToSQL, op, resolveAtomicOp, rollbackStepsToSQL, serializeVector, toAtomicOp, validateRecord, validateTransition, vectorsEqual };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AppNotReadyError,
|
|
2
3
|
ClockDriftError,
|
|
3
4
|
HybridLogicalClock,
|
|
5
|
+
InvalidTimestampError,
|
|
4
6
|
KORA_ERROR_FIX_SUGGESTIONS,
|
|
5
7
|
KoraError,
|
|
8
|
+
MAX_LOGICAL,
|
|
6
9
|
MergeConflictError,
|
|
7
10
|
OperationError,
|
|
11
|
+
RemoteClockDriftError,
|
|
8
12
|
SchemaValidationError,
|
|
9
13
|
StorageError,
|
|
10
14
|
SyncError,
|
|
@@ -13,7 +17,7 @@ import {
|
|
|
13
17
|
isValidOperation,
|
|
14
18
|
topologicalSort,
|
|
15
19
|
verifyOperationIntegrity
|
|
16
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-5IICSH6H.js";
|
|
17
21
|
|
|
18
22
|
// src/types.ts
|
|
19
23
|
var MERGE_STRATEGIES = [
|
|
@@ -234,6 +238,106 @@ function toAtomicOp(sentinel) {
|
|
|
234
238
|
return { type: sentinel.type, value: sentinel.value };
|
|
235
239
|
}
|
|
236
240
|
|
|
241
|
+
// src/operations/op-data-binary.ts
|
|
242
|
+
function isKoraBytesValue(value) {
|
|
243
|
+
if (typeof value !== "object" || value === null) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
const record = value;
|
|
247
|
+
return Object.keys(record).length === 1 && typeof record.$koraBytes === "string";
|
|
248
|
+
}
|
|
249
|
+
function isLegacyNumericByteObject(value) {
|
|
250
|
+
if (typeof value !== "object" || value === null || ArrayBuffer.isView(value)) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
const record = value;
|
|
254
|
+
const keys = Object.keys(record);
|
|
255
|
+
if (keys.length === 0) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
for (let i = 0; i < keys.length; i++) {
|
|
259
|
+
const byte = record[String(i)];
|
|
260
|
+
if (typeof byte !== "number" || !Number.isInteger(byte) || byte < 0 || byte > 255) {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
267
|
+
var BASE64_REVERSE = new Map(
|
|
268
|
+
Array.from(BASE64_ALPHABET, (char, index) => [char, index])
|
|
269
|
+
);
|
|
270
|
+
function bytesToBase64(bytes) {
|
|
271
|
+
let out = "";
|
|
272
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
273
|
+
const b0 = bytes[i] ?? 0;
|
|
274
|
+
const b1 = bytes[i + 1] ?? 0;
|
|
275
|
+
const b2 = bytes[i + 2] ?? 0;
|
|
276
|
+
const triple = b0 << 16 | b1 << 8 | b2;
|
|
277
|
+
out += BASE64_ALPHABET[triple >> 18 & 63] ?? "";
|
|
278
|
+
out += BASE64_ALPHABET[triple >> 12 & 63] ?? "";
|
|
279
|
+
out += i + 1 < bytes.length ? BASE64_ALPHABET[triple >> 6 & 63] ?? "" : "=";
|
|
280
|
+
out += i + 2 < bytes.length ? BASE64_ALPHABET[triple & 63] ?? "" : "=";
|
|
281
|
+
}
|
|
282
|
+
return out;
|
|
283
|
+
}
|
|
284
|
+
function base64ToBytes(base64) {
|
|
285
|
+
const cleaned = base64.replace(/=+$/, "");
|
|
286
|
+
const out = new Uint8Array(Math.floor(cleaned.length * 6 / 8));
|
|
287
|
+
let buffer = 0;
|
|
288
|
+
let bits = 0;
|
|
289
|
+
let index = 0;
|
|
290
|
+
for (const char of cleaned) {
|
|
291
|
+
const value = BASE64_REVERSE.get(char);
|
|
292
|
+
if (value === void 0) {
|
|
293
|
+
throw new OperationError(`Invalid base64 character "${char}" in tagged binary value.`, {
|
|
294
|
+
char
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
buffer = buffer << 6 | value;
|
|
298
|
+
bits += 6;
|
|
299
|
+
if (bits >= 8) {
|
|
300
|
+
bits -= 8;
|
|
301
|
+
out[index] = buffer >> bits & 255;
|
|
302
|
+
index += 1;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return out;
|
|
306
|
+
}
|
|
307
|
+
function encodeBytesForOpData(value) {
|
|
308
|
+
if (typeof value === "string") {
|
|
309
|
+
return value;
|
|
310
|
+
}
|
|
311
|
+
const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
312
|
+
return { $koraBytes: bytesToBase64(bytes) };
|
|
313
|
+
}
|
|
314
|
+
function decodeBytesFromOpData(value) {
|
|
315
|
+
if (typeof value === "string") {
|
|
316
|
+
return value;
|
|
317
|
+
}
|
|
318
|
+
if (value instanceof Uint8Array) {
|
|
319
|
+
return value;
|
|
320
|
+
}
|
|
321
|
+
if (value instanceof ArrayBuffer) {
|
|
322
|
+
return new Uint8Array(value);
|
|
323
|
+
}
|
|
324
|
+
if (isKoraBytesValue(value)) {
|
|
325
|
+
return base64ToBytes(value.$koraBytes);
|
|
326
|
+
}
|
|
327
|
+
if (isLegacyNumericByteObject(value)) {
|
|
328
|
+
const keys = Object.keys(value);
|
|
329
|
+
const bytes = new Uint8Array(keys.length);
|
|
330
|
+
for (let i = 0; i < keys.length; i++) {
|
|
331
|
+
bytes[i] = value[String(i)] ?? 0;
|
|
332
|
+
}
|
|
333
|
+
return bytes;
|
|
334
|
+
}
|
|
335
|
+
throw new OperationError(
|
|
336
|
+
"Binary op-data value must be a string, Uint8Array, ArrayBuffer, tagged { $koraBytes } object, or legacy numeric-key byte object.",
|
|
337
|
+
{ receivedType: typeof value }
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
|
|
237
341
|
// src/scopes/sync-scope-bindings.ts
|
|
238
342
|
function hasSchemaSyncRules(schema) {
|
|
239
343
|
return schema.sync !== void 0 && Object.keys(schema.sync).length > 0;
|
|
@@ -663,6 +767,7 @@ function generateSQL(collectionName, collection, relations) {
|
|
|
663
767
|
columns.push("_created_at INTEGER NOT NULL");
|
|
664
768
|
columns.push("_updated_at INTEGER NOT NULL");
|
|
665
769
|
columns.push("_version TEXT NOT NULL DEFAULT ''");
|
|
770
|
+
columns.push("_field_versions TEXT NOT NULL DEFAULT '{}'");
|
|
666
771
|
columns.push("_deleted INTEGER NOT NULL DEFAULT 0");
|
|
667
772
|
statements.push(`CREATE TABLE IF NOT EXISTS ${collectionName} (
|
|
668
773
|
${columns.join(",\n ")}
|
|
@@ -675,6 +780,10 @@ ALTER TABLE ${collectionName} ADD COLUMN ${colDef}`);
|
|
|
675
780
|
statements.push(
|
|
676
781
|
`--kora:safe-alter
|
|
677
782
|
ALTER TABLE ${collectionName} ADD COLUMN _version TEXT NOT NULL DEFAULT ''`
|
|
783
|
+
);
|
|
784
|
+
statements.push(
|
|
785
|
+
`--kora:safe-alter
|
|
786
|
+
ALTER TABLE ${collectionName} ADD COLUMN _field_versions TEXT NOT NULL DEFAULT '{}'`
|
|
678
787
|
);
|
|
679
788
|
for (const indexField of collection.indexes) {
|
|
680
789
|
statements.push(
|
|
@@ -702,6 +811,9 @@ ALTER TABLE ${collectionName} ADD COLUMN _version TEXT NOT NULL DEFAULT ''`
|
|
|
702
811
|
schema_version INTEGER NOT NULL
|
|
703
812
|
)`
|
|
704
813
|
);
|
|
814
|
+
statements.push(
|
|
815
|
+
`CREATE INDEX IF NOT EXISTS idx_kora_ops_${collectionName}_record_id ON _kora_ops_${collectionName} (record_id)`
|
|
816
|
+
);
|
|
705
817
|
return statements;
|
|
706
818
|
}
|
|
707
819
|
function generateFullDDL(schema) {
|
|
@@ -1167,9 +1279,9 @@ function validateFieldValue(collection, fieldName, descriptor, value) {
|
|
|
1167
1279
|
break;
|
|
1168
1280
|
}
|
|
1169
1281
|
case "richtext": {
|
|
1170
|
-
if (!(value instanceof Uint8Array) && typeof value !== "string") {
|
|
1282
|
+
if (!(value instanceof Uint8Array) && !(value instanceof ArrayBuffer) && typeof value !== "string") {
|
|
1171
1283
|
throw new SchemaValidationError(
|
|
1172
|
-
`Field "${fieldName}" in collection "${collection}" must be a Uint8Array or string for richtext, got ${typeof value}`,
|
|
1284
|
+
`Field "${fieldName}" in collection "${collection}" must be a Uint8Array, ArrayBuffer, or string for richtext, got ${typeof value}`,
|
|
1173
1285
|
{
|
|
1174
1286
|
collection,
|
|
1175
1287
|
field: fieldName,
|
|
@@ -1906,6 +2018,7 @@ function generateProtoDefinitions(schema) {
|
|
|
1906
2018
|
export {
|
|
1907
2019
|
APPLY_FAILURE_CODES,
|
|
1908
2020
|
APPLY_RESULTS,
|
|
2021
|
+
AppNotReadyError,
|
|
1909
2022
|
ArrayFieldBuilder,
|
|
1910
2023
|
CONNECTION_QUALITIES,
|
|
1911
2024
|
CausalTracker,
|
|
@@ -1913,21 +2026,26 @@ export {
|
|
|
1913
2026
|
EnumFieldBuilder,
|
|
1914
2027
|
FieldBuilder,
|
|
1915
2028
|
HybridLogicalClock,
|
|
2029
|
+
InvalidTimestampError,
|
|
1916
2030
|
KORA_ERROR_FIX_SUGGESTIONS,
|
|
1917
2031
|
KoraError,
|
|
2032
|
+
MAX_LOGICAL,
|
|
1918
2033
|
MERGE_STRATEGIES,
|
|
1919
2034
|
MergeConflictError,
|
|
1920
2035
|
MigrationBuilder,
|
|
1921
2036
|
MigrationRollbackError,
|
|
1922
2037
|
OperationError,
|
|
2038
|
+
RemoteClockDriftError,
|
|
1923
2039
|
RollbackBuilder,
|
|
1924
2040
|
SchemaValidationError,
|
|
1925
2041
|
StorageError,
|
|
1926
2042
|
SyncError,
|
|
1927
2043
|
advanceVector,
|
|
1928
2044
|
applyOperationTransforms,
|
|
2045
|
+
base64ToBytes,
|
|
1929
2046
|
buildScopeMap,
|
|
1930
2047
|
buildStateMachineConstraints,
|
|
2048
|
+
bytesToBase64,
|
|
1931
2049
|
canAutoRollback,
|
|
1932
2050
|
collectSchemaScopeFields,
|
|
1933
2051
|
collectSchemaScopeValueKeys,
|
|
@@ -1935,11 +2053,13 @@ export {
|
|
|
1935
2053
|
createOperation,
|
|
1936
2054
|
createReversibleMigration,
|
|
1937
2055
|
createVersionVector,
|
|
2056
|
+
decodeBytesFromOpData,
|
|
1938
2057
|
defaultApplyFailureReason,
|
|
1939
2058
|
defaultSequenceFormat,
|
|
1940
2059
|
defineSchema,
|
|
1941
2060
|
deserializeVector,
|
|
1942
2061
|
dominates,
|
|
2062
|
+
encodeBytesForOpData,
|
|
1943
2063
|
extractScopeValuesFromClaims,
|
|
1944
2064
|
extractTimestamp,
|
|
1945
2065
|
formatSequenceValue,
|
|
@@ -1955,6 +2075,8 @@ export {
|
|
|
1955
2075
|
isApplyFailure,
|
|
1956
2076
|
isAtomicOp,
|
|
1957
2077
|
isCollectionSyncScoped,
|
|
2078
|
+
isKoraBytesValue,
|
|
2079
|
+
isLegacyNumericByteObject,
|
|
1958
2080
|
isValidOperation,
|
|
1959
2081
|
isValidUUIDv7,
|
|
1960
2082
|
mergeVectors,
|