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