@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/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-BeIEDJBW.cjs';
2
- export { j as CONNECTION_QUALITIES, k as ConnectionQuality, l as Constraint, m as FieldDescriptor, n as FieldMergeStrategy, H as HLCTimestamp, o as HybridLogicalClock, K as KoraEvent, p as KoraEventByType, q as KoraEventEmitter, r as KoraEventListener, s as KoraEventType, t as MERGE_STRATEGIES, u as MergeStrategy, v as MergeTrace, w as MigrationBuilder, x as OnDeleteAction, y as OperationInput, z as RelationType, B as RollbackBuilder, D as SequenceConfig, G as StateMachineDefinition, I as SyncDiagnosticsSnapshot, J as SyncRuleDefinition, L as TimeSource, N as createOperation, P as isValidOperation, Q as migrate, U as t, W as verifyOperationIntegrity } from './events-BeIEDJBW.cjs';
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, type ScopeMap, StateMachineConstraint, type StateMachineInput, StorageError, SyncError, TransitionMap, TransitionValidationResult, type TypedSchemaDefinition, VersionVector, advanceVector, applyOperationTransforms, buildScopeMap, buildStateMachineConstraints, canAutoRollback, collectSchemaScopeFields, collectSchemaScopeValueKeys, computeDelta, createReversibleMigration, createVersionVector, defaultApplyFailureReason, defaultSequenceFormat, defineSchema, deserializeVector, dominates, extractScopeValuesFromClaims, extractTimestamp, formatSequenceValue, generateFullDDL, generateProtoDefinitions, generateRollbackSteps, generateSQL, generateUUIDv7, getCollectionScopeBindings, getKoraErrorFix, getTransitionMap, hasSchemaSyncRules, isApplyFailure, isAtomicOp, isCollectionSyncScoped, isValidUUIDv7, mergeVectors, migrationStepsToSQL, op, resolveAtomicOp, rollbackStepsToSQL, serializeVector, toAtomicOp, validateRecord, validateTransition, vectorsEqual };
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-BeIEDJBW.js';
2
- export { j as CONNECTION_QUALITIES, k as ConnectionQuality, l as Constraint, m as FieldDescriptor, n as FieldMergeStrategy, H as HLCTimestamp, o as HybridLogicalClock, K as KoraEvent, p as KoraEventByType, q as KoraEventEmitter, r as KoraEventListener, s as KoraEventType, t as MERGE_STRATEGIES, u as MergeStrategy, v as MergeTrace, w as MigrationBuilder, x as OnDeleteAction, y as OperationInput, z as RelationType, B as RollbackBuilder, D as SequenceConfig, G as StateMachineDefinition, I as SyncDiagnosticsSnapshot, J as SyncRuleDefinition, L as TimeSource, N as createOperation, P as isValidOperation, Q as migrate, U as t, W as verifyOperationIntegrity } from './events-BeIEDJBW.js';
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, type ScopeMap, StateMachineConstraint, type StateMachineInput, StorageError, SyncError, TransitionMap, TransitionValidationResult, type TypedSchemaDefinition, VersionVector, advanceVector, applyOperationTransforms, buildScopeMap, buildStateMachineConstraints, canAutoRollback, collectSchemaScopeFields, collectSchemaScopeValueKeys, computeDelta, createReversibleMigration, createVersionVector, defaultApplyFailureReason, defaultSequenceFormat, defineSchema, deserializeVector, dominates, extractScopeValuesFromClaims, extractTimestamp, formatSequenceValue, generateFullDDL, generateProtoDefinitions, generateRollbackSteps, generateSQL, generateUUIDv7, getCollectionScopeBindings, getKoraErrorFix, getTransitionMap, hasSchemaSyncRules, isApplyFailure, isAtomicOp, isCollectionSyncScoped, isValidUUIDv7, mergeVectors, migrationStepsToSQL, op, resolveAtomicOp, rollbackStepsToSQL, serializeVector, toAtomicOp, validateRecord, validateTransition, vectorsEqual };
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-H4FXU5OP.js";
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,