@korajs/core 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-CFP5YFXC.js → chunk-H4FXU5OP.js} +41 -5
- package/dist/chunk-H4FXU5OP.js.map +1 -0
- package/dist/{events-BMulupSB.d.cts → events-BeIEDJBW.d.cts} +46 -3
- package/dist/{events-BMulupSB.d.ts → events-BeIEDJBW.d.ts} +46 -3
- package/dist/index.cjs +368 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +185 -35
- package/dist/index.d.ts +185 -35
- package/dist/index.js +319 -12
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +37 -4
- 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/package.json +2 -1
- package/dist/chunk-CFP5YFXC.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ClockDriftError,
|
|
3
3
|
HybridLogicalClock,
|
|
4
|
+
KORA_ERROR_FIX_SUGGESTIONS,
|
|
4
5
|
KoraError,
|
|
5
6
|
MergeConflictError,
|
|
6
7
|
OperationError,
|
|
@@ -8,10 +9,11 @@ import {
|
|
|
8
9
|
StorageError,
|
|
9
10
|
SyncError,
|
|
10
11
|
createOperation,
|
|
12
|
+
getKoraErrorFix,
|
|
11
13
|
isValidOperation,
|
|
12
14
|
topologicalSort,
|
|
13
15
|
verifyOperationIntegrity
|
|
14
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-H4FXU5OP.js";
|
|
15
17
|
|
|
16
18
|
// src/types.ts
|
|
17
19
|
var MERGE_STRATEGIES = [
|
|
@@ -23,6 +25,50 @@ var MERGE_STRATEGIES = [
|
|
|
23
25
|
];
|
|
24
26
|
var CONNECTION_QUALITIES = ["excellent", "good", "fair", "poor", "offline"];
|
|
25
27
|
|
|
28
|
+
// src/causal/causal-tracker.ts
|
|
29
|
+
var CausalTracker = class {
|
|
30
|
+
lastOpIdByCollection = /* @__PURE__ */ new Map();
|
|
31
|
+
lastTransactionOpId = null;
|
|
32
|
+
/**
|
|
33
|
+
* Start a new transaction boundary. Clears in-transaction op ids.
|
|
34
|
+
*/
|
|
35
|
+
beginTransaction() {
|
|
36
|
+
this.lastTransactionOpId = null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Clear the transaction boundary without recording ops (after rollback).
|
|
40
|
+
*/
|
|
41
|
+
clearTransaction() {
|
|
42
|
+
this.lastTransactionOpId = null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Compute causal dependencies for the next operation in a collection.
|
|
46
|
+
* Uses direct parents only: collection head and the previous op in the open transaction.
|
|
47
|
+
*/
|
|
48
|
+
nextCausalDeps(collection, inTransaction) {
|
|
49
|
+
const deps = [];
|
|
50
|
+
const lastInCollection = this.lastOpIdByCollection.get(collection);
|
|
51
|
+
if (lastInCollection !== void 0) {
|
|
52
|
+
deps.push(lastInCollection);
|
|
53
|
+
}
|
|
54
|
+
if (inTransaction && this.lastTransactionOpId !== null) {
|
|
55
|
+
if (!deps.includes(this.lastTransactionOpId)) {
|
|
56
|
+
deps.push(this.lastTransactionOpId);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return deps;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Record an operation after it has been created and assigned an id.
|
|
63
|
+
*/
|
|
64
|
+
afterOperation(collection, operationId, inTransaction) {
|
|
65
|
+
this.lastOpIdByCollection.set(collection, operationId);
|
|
66
|
+
if (inTransaction) {
|
|
67
|
+
this.lastTransactionOpId = operationId;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
26
72
|
// src/identifiers/uuid-v7.ts
|
|
27
73
|
var defaultRandom = globalThis.crypto;
|
|
28
74
|
function generateUUIDv7(timestamp = Date.now(), randomSource = defaultRandom) {
|
|
@@ -59,6 +105,37 @@ function formatUUID(bytes) {
|
|
|
59
105
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
60
106
|
}
|
|
61
107
|
|
|
108
|
+
// src/operations/apply-result.ts
|
|
109
|
+
var APPLY_RESULTS = ["applied", "duplicate", "skipped", "rejected", "deferred"];
|
|
110
|
+
var APPLY_FAILURE_CODES = {
|
|
111
|
+
APPLY_FAILED: "APPLY_FAILED",
|
|
112
|
+
APPLY_SKIPPED: "APPLY_SKIPPED",
|
|
113
|
+
APPLY_REJECTED: "APPLY_REJECTED",
|
|
114
|
+
APPLY_DEFERRED: "APPLY_DEFERRED",
|
|
115
|
+
CLOCK_DRIFT: "CLOCK_DRIFT",
|
|
116
|
+
REFERENTIAL_INTEGRITY: "REFERENTIAL_INTEGRITY",
|
|
117
|
+
SCHEMA_MISMATCH: "SCHEMA_MISMATCH"
|
|
118
|
+
};
|
|
119
|
+
function isApplyFailure(result) {
|
|
120
|
+
return result === "skipped" || result === "rejected" || result === "deferred";
|
|
121
|
+
}
|
|
122
|
+
function defaultApplyFailureReason(result, overrides) {
|
|
123
|
+
const base = result === "deferred" ? {
|
|
124
|
+
code: APPLY_FAILURE_CODES.APPLY_DEFERRED,
|
|
125
|
+
message: "Operation apply was deferred.",
|
|
126
|
+
retriable: true
|
|
127
|
+
} : result === "rejected" ? {
|
|
128
|
+
code: APPLY_FAILURE_CODES.APPLY_REJECTED,
|
|
129
|
+
message: "Operation apply was rejected.",
|
|
130
|
+
retriable: false
|
|
131
|
+
} : {
|
|
132
|
+
code: APPLY_FAILURE_CODES.APPLY_SKIPPED,
|
|
133
|
+
message: "Operation apply was skipped.",
|
|
134
|
+
retriable: false
|
|
135
|
+
};
|
|
136
|
+
return { ...base, ...overrides };
|
|
137
|
+
}
|
|
138
|
+
|
|
62
139
|
// src/operations/atomic-ops.ts
|
|
63
140
|
var KORA_ATOMIC_OP = /* @__PURE__ */ Symbol.for("kora.atomic_op");
|
|
64
141
|
function isAtomicOp(value) {
|
|
@@ -157,6 +234,69 @@ function toAtomicOp(sentinel) {
|
|
|
157
234
|
return { type: sentinel.type, value: sentinel.value };
|
|
158
235
|
}
|
|
159
236
|
|
|
237
|
+
// src/scopes/sync-scope-bindings.ts
|
|
238
|
+
function hasSchemaSyncRules(schema) {
|
|
239
|
+
return schema.sync !== void 0 && Object.keys(schema.sync).length > 0;
|
|
240
|
+
}
|
|
241
|
+
function getCollectionScopeBindings(schema, collectionName) {
|
|
242
|
+
const syncRule = schema.sync?.[collectionName];
|
|
243
|
+
if (syncRule && Object.keys(syncRule.where).length > 0) {
|
|
244
|
+
return { ...syncRule.where };
|
|
245
|
+
}
|
|
246
|
+
const scopeFields = schema.collections[collectionName]?.scope ?? [];
|
|
247
|
+
if (scopeFields.length === 0) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
const bindings = {};
|
|
251
|
+
for (const field of scopeFields) {
|
|
252
|
+
bindings[field] = field;
|
|
253
|
+
}
|
|
254
|
+
return bindings;
|
|
255
|
+
}
|
|
256
|
+
function isCollectionSyncScoped(schema, collectionName) {
|
|
257
|
+
if (hasSchemaSyncRules(schema)) {
|
|
258
|
+
if (schema.sync?.[collectionName]) {
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
const legacyScope = schema.collections[collectionName]?.scope ?? [];
|
|
262
|
+
return legacyScope.length > 0;
|
|
263
|
+
}
|
|
264
|
+
return getCollectionScopeBindings(schema, collectionName) !== null;
|
|
265
|
+
}
|
|
266
|
+
function collectSchemaScopeValueKeys(schema) {
|
|
267
|
+
const keys = /* @__PURE__ */ new Set();
|
|
268
|
+
for (const collection of Object.values(schema.collections)) {
|
|
269
|
+
for (const field of collection.scope) {
|
|
270
|
+
keys.add(field);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (schema.sync) {
|
|
274
|
+
for (const rule of Object.values(schema.sync)) {
|
|
275
|
+
for (const scopeKey of Object.values(rule.where)) {
|
|
276
|
+
keys.add(scopeKey);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return [...keys];
|
|
281
|
+
}
|
|
282
|
+
function normalizeSyncRuleWhere(collectionName, where) {
|
|
283
|
+
const normalized = {};
|
|
284
|
+
for (const [field, scopeKey] of Object.entries(where)) {
|
|
285
|
+
if (scopeKey === true) {
|
|
286
|
+
normalized[field] = field;
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (typeof scopeKey === "string" && scopeKey.length > 0) {
|
|
290
|
+
normalized[field] = scopeKey;
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
throw new Error(
|
|
294
|
+
`Invalid sync rule for collection "${collectionName}": where.${field} must be true or a non-empty scope key string`
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
return normalized;
|
|
298
|
+
}
|
|
299
|
+
|
|
160
300
|
// src/state-machine/state-machine.ts
|
|
161
301
|
function validateTransition(constraint, fromValue, toValue) {
|
|
162
302
|
const from = String(fromValue);
|
|
@@ -246,7 +386,7 @@ function validateStateMachineDefinition(collectionName, sm, fields) {
|
|
|
246
386
|
// src/schema/define.ts
|
|
247
387
|
var COLLECTION_NAME_RE = /^[a-z][a-z0-9_]*$/;
|
|
248
388
|
var FIELD_NAME_RE = /^[a-z][a-zA-Z0-9_]*$/;
|
|
249
|
-
var RESERVED_FIELDS = /* @__PURE__ */ new Set(["id", "_created_at", "_updated_at", "_deleted"]);
|
|
389
|
+
var RESERVED_FIELDS = /* @__PURE__ */ new Set(["id", "_created_at", "_updated_at", "_version", "_deleted"]);
|
|
250
390
|
function defineSchema(input) {
|
|
251
391
|
validateVersion(input.version);
|
|
252
392
|
const collections = {};
|
|
@@ -289,7 +429,15 @@ function defineSchema(input) {
|
|
|
289
429
|
migrations[version] = migration;
|
|
290
430
|
}
|
|
291
431
|
}
|
|
292
|
-
|
|
432
|
+
const sync = buildSyncRules(input.sync, collections);
|
|
433
|
+
applySyncRulesToCollectionScope(collections, sync);
|
|
434
|
+
return {
|
|
435
|
+
version: input.version,
|
|
436
|
+
collections,
|
|
437
|
+
relations,
|
|
438
|
+
migrations,
|
|
439
|
+
...sync ? { sync } : {}
|
|
440
|
+
};
|
|
293
441
|
}
|
|
294
442
|
function validateVersion(version) {
|
|
295
443
|
if (typeof version !== "number" || !Number.isInteger(version) || version < 1) {
|
|
@@ -370,6 +518,63 @@ function buildCollection(name, input) {
|
|
|
370
518
|
}
|
|
371
519
|
return { fields, indexes, constraints, resolvers, scope, stateMachine };
|
|
372
520
|
}
|
|
521
|
+
function buildSyncRules(syncInput, collections) {
|
|
522
|
+
if (!syncInput) {
|
|
523
|
+
return void 0;
|
|
524
|
+
}
|
|
525
|
+
const sync = {};
|
|
526
|
+
for (const [collectionName, ruleInput] of Object.entries(syncInput)) {
|
|
527
|
+
if (!(collectionName in collections)) {
|
|
528
|
+
throw new SchemaValidationError(
|
|
529
|
+
`Sync rule references collection "${collectionName}" which does not exist. Available collections: ${Object.keys(collections).join(", ")}`,
|
|
530
|
+
{ collection: collectionName }
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
if (!ruleInput.where || Object.keys(ruleInput.where).length === 0) {
|
|
534
|
+
throw new SchemaValidationError(
|
|
535
|
+
`Sync rule for collection "${collectionName}" must declare at least one where binding`,
|
|
536
|
+
{ collection: collectionName }
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
const collection = collections[collectionName];
|
|
540
|
+
if (!collection) {
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
for (const fieldName of Object.keys(ruleInput.where)) {
|
|
544
|
+
if (!(fieldName in collection.fields)) {
|
|
545
|
+
throw new SchemaValidationError(
|
|
546
|
+
`Sync rule where field "${fieldName}" does not exist in collection "${collectionName}". Available fields: ${Object.keys(collection.fields).join(", ")}`,
|
|
547
|
+
{ collection: collectionName, field: fieldName }
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
try {
|
|
552
|
+
sync[collectionName] = { where: normalizeSyncRuleWhere(collectionName, ruleInput.where) };
|
|
553
|
+
} catch (error) {
|
|
554
|
+
throw new SchemaValidationError(
|
|
555
|
+
error instanceof Error ? error.message : "Invalid sync rule",
|
|
556
|
+
{ collection: collectionName }
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return sync;
|
|
561
|
+
}
|
|
562
|
+
function applySyncRulesToCollectionScope(collections, sync) {
|
|
563
|
+
if (!sync) {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
for (const [collectionName, rule] of Object.entries(sync)) {
|
|
567
|
+
const collection = collections[collectionName];
|
|
568
|
+
if (!collection) {
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
for (const fieldName of Object.keys(rule.where)) {
|
|
572
|
+
if (!collection.scope.includes(fieldName)) {
|
|
573
|
+
collection.scope.push(fieldName);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
373
578
|
function validateFieldName(collection, fieldName) {
|
|
374
579
|
if (RESERVED_FIELDS.has(fieldName)) {
|
|
375
580
|
throw new SchemaValidationError(
|
|
@@ -457,6 +662,7 @@ function generateSQL(collectionName, collection, relations) {
|
|
|
457
662
|
}
|
|
458
663
|
columns.push("_created_at INTEGER NOT NULL");
|
|
459
664
|
columns.push("_updated_at INTEGER NOT NULL");
|
|
665
|
+
columns.push("_version TEXT NOT NULL DEFAULT ''");
|
|
460
666
|
columns.push("_deleted INTEGER NOT NULL DEFAULT 0");
|
|
461
667
|
statements.push(`CREATE TABLE IF NOT EXISTS ${collectionName} (
|
|
462
668
|
${columns.join(",\n ")}
|
|
@@ -466,6 +672,10 @@ function generateSQL(collectionName, collection, relations) {
|
|
|
466
672
|
statements.push(`--kora:safe-alter
|
|
467
673
|
ALTER TABLE ${collectionName} ADD COLUMN ${colDef}`);
|
|
468
674
|
}
|
|
675
|
+
statements.push(
|
|
676
|
+
`--kora:safe-alter
|
|
677
|
+
ALTER TABLE ${collectionName} ADD COLUMN _version TEXT NOT NULL DEFAULT ''`
|
|
678
|
+
);
|
|
469
679
|
for (const indexField of collection.indexes) {
|
|
470
680
|
statements.push(
|
|
471
681
|
`CREATE INDEX IF NOT EXISTS idx_${collectionName}_${indexField} ON ${collectionName} (${indexField})`
|
|
@@ -505,6 +715,18 @@ function generateFullDDL(schema) {
|
|
|
505
715
|
statements.push(
|
|
506
716
|
"CREATE TABLE IF NOT EXISTS _kora_sequences (\n name TEXT NOT NULL,\n scope TEXT NOT NULL DEFAULT '',\n node_id TEXT NOT NULL,\n counter INTEGER NOT NULL DEFAULT 0,\n PRIMARY KEY (name, scope, node_id)\n)"
|
|
507
717
|
);
|
|
718
|
+
statements.push(
|
|
719
|
+
"CREATE TABLE IF NOT EXISTS _kora_sync_queue (\n id TEXT PRIMARY KEY NOT NULL,\n payload TEXT NOT NULL\n)"
|
|
720
|
+
);
|
|
721
|
+
statements.push(
|
|
722
|
+
"CREATE TABLE IF NOT EXISTS _kora_audit_traces (\n id TEXT PRIMARY KEY NOT NULL,\n recorded_at INTEGER NOT NULL,\n event_type TEXT NOT NULL,\n collection TEXT NOT NULL,\n record_id TEXT NOT NULL,\n field TEXT NOT NULL,\n strategy TEXT NOT NULL,\n tier INTEGER NOT NULL,\n constraint_name TEXT,\n trace_json TEXT NOT NULL\n)"
|
|
723
|
+
);
|
|
724
|
+
statements.push(
|
|
725
|
+
"CREATE INDEX IF NOT EXISTS idx_kora_audit_traces_recorded_at ON _kora_audit_traces (recorded_at)"
|
|
726
|
+
);
|
|
727
|
+
statements.push(
|
|
728
|
+
"CREATE INDEX IF NOT EXISTS idx_kora_audit_traces_collection ON _kora_audit_traces (collection)"
|
|
729
|
+
);
|
|
508
730
|
for (const [name, collection] of Object.entries(schema.collections)) {
|
|
509
731
|
statements.push(...generateSQL(name, collection, schema.relations));
|
|
510
732
|
}
|
|
@@ -633,10 +855,24 @@ var EnumFieldBuilder = class _EnumFieldBuilder extends FieldBuilder {
|
|
|
633
855
|
);
|
|
634
856
|
}
|
|
635
857
|
default(value) {
|
|
636
|
-
return new _EnumFieldBuilder(
|
|
858
|
+
return new _EnumFieldBuilder(
|
|
859
|
+
this._enumValues,
|
|
860
|
+
false,
|
|
861
|
+
value,
|
|
862
|
+
this._auto,
|
|
863
|
+
this._mergeStrategy,
|
|
864
|
+
this._transitions
|
|
865
|
+
);
|
|
637
866
|
}
|
|
638
867
|
auto() {
|
|
639
|
-
return new _EnumFieldBuilder(
|
|
868
|
+
return new _EnumFieldBuilder(
|
|
869
|
+
this._enumValues,
|
|
870
|
+
false,
|
|
871
|
+
void 0,
|
|
872
|
+
true,
|
|
873
|
+
this._mergeStrategy,
|
|
874
|
+
this._transitions
|
|
875
|
+
);
|
|
640
876
|
}
|
|
641
877
|
merge(strategy) {
|
|
642
878
|
return new _EnumFieldBuilder(
|
|
@@ -1004,12 +1240,13 @@ function vectorsEqual(a, b) {
|
|
|
1004
1240
|
}
|
|
1005
1241
|
return true;
|
|
1006
1242
|
}
|
|
1007
|
-
function computeDelta(localVector, remoteVector, operationLog) {
|
|
1243
|
+
async function computeDelta(localVector, remoteVector, operationLog) {
|
|
1008
1244
|
const missing = [];
|
|
1009
1245
|
for (const [nodeId, localSeq] of localVector) {
|
|
1010
1246
|
const remoteSeq = remoteVector.get(nodeId) ?? 0;
|
|
1011
1247
|
if (localSeq > remoteSeq) {
|
|
1012
|
-
|
|
1248
|
+
const ops = await operationLog.getRange(nodeId, remoteSeq + 1, localSeq);
|
|
1249
|
+
missing.push(...ops);
|
|
1013
1250
|
}
|
|
1014
1251
|
}
|
|
1015
1252
|
return topologicalSort(missing);
|
|
@@ -1026,12 +1263,17 @@ function deserializeVector(s) {
|
|
|
1026
1263
|
// src/scopes/build-scope-map.ts
|
|
1027
1264
|
function buildScopeMap(schema, scopeValues) {
|
|
1028
1265
|
const result = {};
|
|
1029
|
-
|
|
1030
|
-
|
|
1266
|
+
const partialSync = hasSchemaSyncRules(schema);
|
|
1267
|
+
for (const collName of Object.keys(schema.collections)) {
|
|
1268
|
+
if (partialSync && !isCollectionSyncScoped(schema, collName)) {
|
|
1269
|
+
continue;
|
|
1270
|
+
}
|
|
1271
|
+
const bindings = getCollectionScopeBindings(schema, collName);
|
|
1272
|
+
if (bindings) {
|
|
1031
1273
|
const collScope = {};
|
|
1032
|
-
for (const field of
|
|
1033
|
-
if (
|
|
1034
|
-
collScope[field] = scopeValues[
|
|
1274
|
+
for (const [field, scopeKey] of Object.entries(bindings)) {
|
|
1275
|
+
if (scopeKey in scopeValues) {
|
|
1276
|
+
collScope[field] = scopeValues[scopeKey];
|
|
1035
1277
|
}
|
|
1036
1278
|
}
|
|
1037
1279
|
result[collName] = collScope;
|
|
@@ -1042,6 +1284,34 @@ function buildScopeMap(schema, scopeValues) {
|
|
|
1042
1284
|
return result;
|
|
1043
1285
|
}
|
|
1044
1286
|
|
|
1287
|
+
// src/scopes/extract-scope-from-claims.ts
|
|
1288
|
+
function collectSchemaScopeFields(schema) {
|
|
1289
|
+
return collectSchemaScopeValueKeys(schema);
|
|
1290
|
+
}
|
|
1291
|
+
function extractScopeValuesFromClaims(schema, claims) {
|
|
1292
|
+
const scopeFields = collectSchemaScopeValueKeys(schema);
|
|
1293
|
+
if (scopeFields.length === 0) {
|
|
1294
|
+
return {};
|
|
1295
|
+
}
|
|
1296
|
+
const nestedScope = claims.scope;
|
|
1297
|
+
const scopeObject = typeof nestedScope === "object" && nestedScope !== null && !Array.isArray(nestedScope) ? nestedScope : {};
|
|
1298
|
+
const result = {};
|
|
1299
|
+
for (const field of scopeFields) {
|
|
1300
|
+
if (field in claims) {
|
|
1301
|
+
result[field] = claims[field];
|
|
1302
|
+
continue;
|
|
1303
|
+
}
|
|
1304
|
+
if (field in scopeObject) {
|
|
1305
|
+
result[field] = scopeObject[field];
|
|
1306
|
+
continue;
|
|
1307
|
+
}
|
|
1308
|
+
if (field === "userId" && typeof claims.sub === "string") {
|
|
1309
|
+
result.userId = claims.sub;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
return result;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1045
1315
|
// src/sequences/sequence-format.ts
|
|
1046
1316
|
function formatSequenceValue(template, counter, nodeId, now) {
|
|
1047
1317
|
const date = now ?? /* @__PURE__ */ new Date();
|
|
@@ -1068,6 +1338,29 @@ function defaultSequenceFormat(name) {
|
|
|
1068
1338
|
return `${name}-{seq:4}`;
|
|
1069
1339
|
}
|
|
1070
1340
|
|
|
1341
|
+
// src/migration/apply-operation-transforms.ts
|
|
1342
|
+
var MAX_TRANSFORM_STEPS = 32;
|
|
1343
|
+
function applyOperationTransforms(operation, targetSchemaVersion, transforms) {
|
|
1344
|
+
let current = operation;
|
|
1345
|
+
for (let step = 0; step < MAX_TRANSFORM_STEPS; step++) {
|
|
1346
|
+
if (current.schemaVersion === targetSchemaVersion) {
|
|
1347
|
+
return current;
|
|
1348
|
+
}
|
|
1349
|
+
const transform = transforms.find(
|
|
1350
|
+
(candidate) => candidate.fromVersion === current.schemaVersion
|
|
1351
|
+
);
|
|
1352
|
+
if (!transform) {
|
|
1353
|
+
return null;
|
|
1354
|
+
}
|
|
1355
|
+
const next = transform.transform(current);
|
|
1356
|
+
if (next === null) {
|
|
1357
|
+
return null;
|
|
1358
|
+
}
|
|
1359
|
+
current = next;
|
|
1360
|
+
}
|
|
1361
|
+
return null;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1071
1364
|
// src/migrations/migration-builder.ts
|
|
1072
1365
|
var RollbackBuilder = class {
|
|
1073
1366
|
_steps = [];
|
|
@@ -1611,12 +1904,16 @@ function generateProtoDefinitions(schema) {
|
|
|
1611
1904
|
return { proto, typeMap, jsonDescriptor };
|
|
1612
1905
|
}
|
|
1613
1906
|
export {
|
|
1907
|
+
APPLY_FAILURE_CODES,
|
|
1908
|
+
APPLY_RESULTS,
|
|
1614
1909
|
ArrayFieldBuilder,
|
|
1615
1910
|
CONNECTION_QUALITIES,
|
|
1911
|
+
CausalTracker,
|
|
1616
1912
|
ClockDriftError,
|
|
1617
1913
|
EnumFieldBuilder,
|
|
1618
1914
|
FieldBuilder,
|
|
1619
1915
|
HybridLogicalClock,
|
|
1916
|
+
KORA_ERROR_FIX_SUGGESTIONS,
|
|
1620
1917
|
KoraError,
|
|
1621
1918
|
MERGE_STRATEGIES,
|
|
1622
1919
|
MergeConflictError,
|
|
@@ -1628,17 +1925,22 @@ export {
|
|
|
1628
1925
|
StorageError,
|
|
1629
1926
|
SyncError,
|
|
1630
1927
|
advanceVector,
|
|
1928
|
+
applyOperationTransforms,
|
|
1631
1929
|
buildScopeMap,
|
|
1632
1930
|
buildStateMachineConstraints,
|
|
1633
1931
|
canAutoRollback,
|
|
1932
|
+
collectSchemaScopeFields,
|
|
1933
|
+
collectSchemaScopeValueKeys,
|
|
1634
1934
|
computeDelta,
|
|
1635
1935
|
createOperation,
|
|
1636
1936
|
createReversibleMigration,
|
|
1637
1937
|
createVersionVector,
|
|
1938
|
+
defaultApplyFailureReason,
|
|
1638
1939
|
defaultSequenceFormat,
|
|
1639
1940
|
defineSchema,
|
|
1640
1941
|
deserializeVector,
|
|
1641
1942
|
dominates,
|
|
1943
|
+
extractScopeValuesFromClaims,
|
|
1642
1944
|
extractTimestamp,
|
|
1643
1945
|
formatSequenceValue,
|
|
1644
1946
|
generateFullDDL,
|
|
@@ -1646,8 +1948,13 @@ export {
|
|
|
1646
1948
|
generateRollbackSteps,
|
|
1647
1949
|
generateSQL,
|
|
1648
1950
|
generateUUIDv7,
|
|
1951
|
+
getCollectionScopeBindings,
|
|
1952
|
+
getKoraErrorFix,
|
|
1649
1953
|
getTransitionMap,
|
|
1954
|
+
hasSchemaSyncRules,
|
|
1955
|
+
isApplyFailure,
|
|
1650
1956
|
isAtomicOp,
|
|
1957
|
+
isCollectionSyncScoped,
|
|
1651
1958
|
isValidOperation,
|
|
1652
1959
|
isValidUUIDv7,
|
|
1653
1960
|
mergeVectors,
|