js-bao 0.5.1 → 0.5.2
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/README.md +124 -30
- package/dist/browser.cjs +586 -265
- package/dist/browser.d.cts +21 -0
- package/dist/browser.d.ts +21 -0
- package/dist/browser.js +588 -263
- package/dist/client.cjs +42 -6
- package/dist/client.d.cts +71 -0
- package/dist/client.d.ts +71 -0
- package/dist/client.js +39 -4
- package/dist/cloudflare-do.cjs +462 -215
- package/dist/cloudflare-do.d.cts +111 -1
- package/dist/cloudflare-do.d.ts +111 -1
- package/dist/cloudflare-do.js +459 -213
- package/dist/cloudflare.cjs +270 -23
- package/dist/cloudflare.d.cts +276 -1
- package/dist/cloudflare.d.ts +276 -1
- package/dist/cloudflare.js +267 -21
- package/dist/codegen-v2.cjs +77 -19
- package/dist/codegen.cjs +2 -1
- package/dist/index.cjs +551 -224
- package/dist/index.d.cts +57 -1
- package/dist/index.d.ts +57 -1
- package/dist/index.js +549 -221
- package/dist/node.cjs +775 -291
- package/dist/node.d.cts +179 -1
- package/dist/node.d.ts +179 -1
- package/dist/node.js +762 -288
- package/package.json +2 -1
package/dist/node.cjs
CHANGED
|
@@ -366,21 +366,36 @@ var init_CursorManager = __esm({
|
|
|
366
366
|
return fields;
|
|
367
367
|
}
|
|
368
368
|
/**
|
|
369
|
-
* Build ORDER BY clause from sort specification
|
|
369
|
+
* Build ORDER BY clause from sort specification.
|
|
370
|
+
*
|
|
371
|
+
* `direction` is the pagination direction (1 = forward, -1 = backward).
|
|
372
|
+
* For backward pagination each field's effective ORDER BY direction is
|
|
373
|
+
* reversed so the cursor's flipped inequality (built by
|
|
374
|
+
* `buildPaginationConditions`) returns the page adjacent to the cursor,
|
|
375
|
+
* not the globally smallest/largest window. Without this,
|
|
376
|
+
* `field < cursor ... ORDER BY field ASC LIMIT n` returns the n smallest
|
|
377
|
+
* rows overall instead of the n rows just below the cursor.
|
|
378
|
+
*
|
|
379
|
+
* The returned `directions` array carries the *declared* per-field sort
|
|
380
|
+
* directions (unaffected by `direction`) — `buildPaginationConditions`
|
|
381
|
+
* needs the declared directions to pick each field's comparison operator.
|
|
370
382
|
*/
|
|
371
|
-
static buildOrderClause(sort, fieldFormatter = (field) => field) {
|
|
383
|
+
static buildOrderClause(sort, fieldFormatter = (field) => field, direction = 1) {
|
|
372
384
|
const fields = this.extractSortFields(sort);
|
|
373
385
|
const clauses = [];
|
|
374
386
|
const directions = [];
|
|
387
|
+
const sqlDir = (declared) => {
|
|
388
|
+
const effective = direction === -1 ? declared === 1 ? -1 : 1 : declared;
|
|
389
|
+
return effective === 1 ? "ASC" : "DESC";
|
|
390
|
+
};
|
|
375
391
|
if (sort && Object.keys(sort).length > 0) {
|
|
376
392
|
for (const [field, dir] of Object.entries(sort)) {
|
|
377
|
-
|
|
378
|
-
clauses.push(`${fieldFormatter(field)} ${sqlDirection}`);
|
|
393
|
+
clauses.push(`${fieldFormatter(field)} ${sqlDir(dir)}`);
|
|
379
394
|
directions.push(dir);
|
|
380
395
|
}
|
|
381
396
|
}
|
|
382
397
|
if (!sort || !sort.hasOwnProperty("id")) {
|
|
383
|
-
clauses.push(`${fieldFormatter("id")}
|
|
398
|
+
clauses.push(`${fieldFormatter("id")} ${sqlDir(1)}`);
|
|
384
399
|
directions.push(1);
|
|
385
400
|
} else if (sort && sort.hasOwnProperty("id")) {
|
|
386
401
|
directions.push(sort["id"]);
|
|
@@ -403,18 +418,27 @@ var init_CursorManager = __esm({
|
|
|
403
418
|
/**
|
|
404
419
|
* Generate next and previous cursors from result set
|
|
405
420
|
*/
|
|
406
|
-
static generateResultCursors(results, sortFields,
|
|
421
|
+
static generateResultCursors(results, sortFields, requestedDirection, hasMore, isFirstPage = false) {
|
|
407
422
|
if (results.length === 0) {
|
|
408
423
|
return {};
|
|
409
424
|
}
|
|
410
425
|
const cursors = {};
|
|
411
426
|
if (hasMore && results.length > 0) {
|
|
412
427
|
const lastResult = results[results.length - 1];
|
|
413
|
-
cursors.nextCursor = this.generateCursor(
|
|
428
|
+
cursors.nextCursor = this.generateCursor(
|
|
429
|
+
lastResult,
|
|
430
|
+
sortFields,
|
|
431
|
+
requestedDirection
|
|
432
|
+
);
|
|
414
433
|
}
|
|
415
434
|
if (results.length > 0 && !isFirstPage) {
|
|
416
435
|
const firstResult = results[0];
|
|
417
|
-
|
|
436
|
+
const opposite = requestedDirection === 1 ? -1 : 1;
|
|
437
|
+
cursors.prevCursor = this.generateCursor(
|
|
438
|
+
firstResult,
|
|
439
|
+
sortFields,
|
|
440
|
+
opposite
|
|
441
|
+
);
|
|
418
442
|
}
|
|
419
443
|
return cursors;
|
|
420
444
|
}
|
|
@@ -547,7 +571,8 @@ var init_DocumentQueryTranslator = __esm({
|
|
|
547
571
|
const whereClause = this.translateFilter(filter);
|
|
548
572
|
const orderClause = CursorManager.buildOrderClause(
|
|
549
573
|
options?.sort,
|
|
550
|
-
(field) => this.getQuotedField(field)
|
|
574
|
+
(field) => this.getQuotedField(field),
|
|
575
|
+
options?.direction || 1
|
|
551
576
|
);
|
|
552
577
|
const limitClause = this.buildLimitClause(options);
|
|
553
578
|
const paginationClause = this.buildPaginationClause(
|
|
@@ -1220,6 +1245,204 @@ var init_yjsValues = __esm({
|
|
|
1220
1245
|
}
|
|
1221
1246
|
});
|
|
1222
1247
|
|
|
1248
|
+
// src/models/writeLifecycle.ts
|
|
1249
|
+
function assertNever(x) {
|
|
1250
|
+
throw new Error(`Unhandled field type: ${String(x)}`);
|
|
1251
|
+
}
|
|
1252
|
+
function fieldWriteKind(type) {
|
|
1253
|
+
switch (type) {
|
|
1254
|
+
case "string":
|
|
1255
|
+
case "number":
|
|
1256
|
+
case "boolean":
|
|
1257
|
+
case "date":
|
|
1258
|
+
case "id":
|
|
1259
|
+
return "scalar";
|
|
1260
|
+
case "stringset":
|
|
1261
|
+
return "stringset";
|
|
1262
|
+
default:
|
|
1263
|
+
return assertNever(type);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
function isKnownFieldType(type) {
|
|
1267
|
+
return KNOWN_FIELD_TYPES.has(type);
|
|
1268
|
+
}
|
|
1269
|
+
function ensureStringSetYMap(rm, fieldName) {
|
|
1270
|
+
const nested = rm.get(fieldName);
|
|
1271
|
+
if (nested instanceof Y2.Map) return nested;
|
|
1272
|
+
const fresh = new Y2.Map();
|
|
1273
|
+
if (nested && typeof nested === "object") {
|
|
1274
|
+
for (const [member, marker] of Object.entries(
|
|
1275
|
+
nested
|
|
1276
|
+
)) {
|
|
1277
|
+
if (Boolean(marker)) fresh.set(member, true);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
rm.set(fieldName, fresh);
|
|
1281
|
+
return fresh;
|
|
1282
|
+
}
|
|
1283
|
+
function applyStringSetDelta(target, delta) {
|
|
1284
|
+
if (delta.clear) {
|
|
1285
|
+
for (const member of Array.from(target.keys())) target.delete(member);
|
|
1286
|
+
}
|
|
1287
|
+
if (delta.remove) {
|
|
1288
|
+
for (const member of delta.remove) target.delete(String(member));
|
|
1289
|
+
}
|
|
1290
|
+
if (delta.add) {
|
|
1291
|
+
for (const member of delta.add) {
|
|
1292
|
+
const key = String(member);
|
|
1293
|
+
if (target.get(key) !== true) target.set(key, true);
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
function replaceStringSet(rm, fieldName, members) {
|
|
1298
|
+
const target = ensureStringSetYMap(rm, fieldName);
|
|
1299
|
+
const desired = /* @__PURE__ */ new Set();
|
|
1300
|
+
for (const member of members) desired.add(String(member));
|
|
1301
|
+
for (const existing of Array.from(target.keys())) {
|
|
1302
|
+
if (!desired.has(existing)) target.delete(existing);
|
|
1303
|
+
}
|
|
1304
|
+
for (const member of desired) {
|
|
1305
|
+
if (target.get(member) !== true) target.set(member, true);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
function applyStringSetChange(recordYMap, fieldName, change) {
|
|
1309
|
+
const target = ensureStringSetYMap(recordYMap, fieldName);
|
|
1310
|
+
applyStringSetDelta(target, {
|
|
1311
|
+
add: change.additions,
|
|
1312
|
+
remove: change.removals
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
function parseStringSetOp(value) {
|
|
1316
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Y2.AbstractType) {
|
|
1317
|
+
return null;
|
|
1318
|
+
}
|
|
1319
|
+
const keys = Object.keys(value);
|
|
1320
|
+
const opKeys = keys.filter((k) => k.startsWith("$"));
|
|
1321
|
+
if (opKeys.length === 0) return null;
|
|
1322
|
+
const known = /* @__PURE__ */ new Set(["$add", "$remove", "$clear"]);
|
|
1323
|
+
const unknown = keys.filter((k) => !known.has(k));
|
|
1324
|
+
if (unknown.length > 0) {
|
|
1325
|
+
throw new Error(
|
|
1326
|
+
`Invalid stringset op: unexpected key(s) [${unknown.join(", ")}]. Only $add, $remove and $clear are supported.`
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
const obj = value;
|
|
1330
|
+
const toMembers = (raw, opName) => {
|
|
1331
|
+
if (raw === void 0) return [];
|
|
1332
|
+
if (!Array.isArray(raw)) {
|
|
1333
|
+
throw new Error(`Invalid stringset op: ${opName} must be an array.`);
|
|
1334
|
+
}
|
|
1335
|
+
return raw.map((m) => String(m));
|
|
1336
|
+
};
|
|
1337
|
+
return {
|
|
1338
|
+
add: toMembers(obj.$add, "$add"),
|
|
1339
|
+
remove: toMembers(obj.$remove, "$remove"),
|
|
1340
|
+
clear: obj.$clear === true
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
function writeField(rm, declaredType, key, value, modelName) {
|
|
1344
|
+
const kind = declaredType && isKnownFieldType(declaredType) ? fieldWriteKind(declaredType) : "scalar";
|
|
1345
|
+
if (Array.isArray(value)) {
|
|
1346
|
+
if (kind !== "stringset") {
|
|
1347
|
+
throw new Error(
|
|
1348
|
+
`Cannot write array value to field "${key}" on model "${modelName}": its declared type could not be resolved to a collection (stringset). Collection fields require schema metadata in the document (_meta_${modelName}); the model must be saved by a client at least once before a workflow writes one of its collection fields.`
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
replaceStringSet(rm, key, value);
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
const op = parseStringSetOp(value);
|
|
1355
|
+
if (op) {
|
|
1356
|
+
if (kind !== "stringset") {
|
|
1357
|
+
throw new Error(
|
|
1358
|
+
`Cannot apply a stringset op ({ $add/$remove/$clear }) to field "${key}" on model "${modelName}": its declared type is ${declaredType ? `"${declaredType}"` : "unresolved"}, not a collection (stringset). Op-objects are only valid for stringset / refersToMany fields with schema metadata (_meta_${modelName}).`
|
|
1359
|
+
);
|
|
1360
|
+
}
|
|
1361
|
+
applyStringSetDelta(ensureStringSetYMap(rm, key), op);
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
if (kind === "stringset") {
|
|
1365
|
+
throw new Error(
|
|
1366
|
+
`Field "${key}" on model "${modelName}" is a stringset and requires an array (replace) or { $add/$remove/$clear } (delta) value; received ${value === null ? "null" : typeof value}.`
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1369
|
+
rm.set(key, value);
|
|
1370
|
+
}
|
|
1371
|
+
function registerFunctionDefaultGenerator(name, fn) {
|
|
1372
|
+
FUNCTION_DEFAULT_GENERATORS.set(name, fn);
|
|
1373
|
+
}
|
|
1374
|
+
function decodeFunctionDefault(name) {
|
|
1375
|
+
return FUNCTION_DEFAULT_GENERATORS.get(name);
|
|
1376
|
+
}
|
|
1377
|
+
function resolveLiteralOrFunctionDefault(rawDefault) {
|
|
1378
|
+
return typeof rawDefault === "function" ? rawDefault() : rawDefault;
|
|
1379
|
+
}
|
|
1380
|
+
function resolveDefaultValue(rawDefault, opts = {}) {
|
|
1381
|
+
if (typeof rawDefault === "function") return rawDefault();
|
|
1382
|
+
if (typeof rawDefault === "string" && rawDefault.startsWith("$")) {
|
|
1383
|
+
if (rawDefault.startsWith("$$")) return rawDefault.slice(1);
|
|
1384
|
+
const name = rawDefault.slice(1);
|
|
1385
|
+
const gen = opts.decode?.(name) ?? decodeFunctionDefault(name);
|
|
1386
|
+
if (!gen) {
|
|
1387
|
+
throw new Error(
|
|
1388
|
+
`Unknown function default "${rawDefault}" for field "${opts.fieldName ?? "?"}"${opts.modelName ? ` on model "${opts.modelName}"` : ""}: no generator is registered for "${name}". Register it via registerFunctionDefaultGenerator("${name}", fn) so the server can populate the field the same way the client does.`
|
|
1389
|
+
);
|
|
1390
|
+
}
|
|
1391
|
+
return gen();
|
|
1392
|
+
}
|
|
1393
|
+
return rawDefault;
|
|
1394
|
+
}
|
|
1395
|
+
function applyDefaultsFromSchema(fields, data, opts = {}) {
|
|
1396
|
+
for (const [fieldName, field] of Object.entries(fields)) {
|
|
1397
|
+
if (fieldName === "id") continue;
|
|
1398
|
+
if (!field || field.default === void 0) continue;
|
|
1399
|
+
if (field.default === UNKNOWN_FUNCTION_DEFAULT) {
|
|
1400
|
+
continue;
|
|
1401
|
+
}
|
|
1402
|
+
if (Object.prototype.hasOwnProperty.call(data, fieldName) && data[fieldName] !== void 0) {
|
|
1403
|
+
continue;
|
|
1404
|
+
}
|
|
1405
|
+
data[fieldName] = resolveDefaultValue(field.default, {
|
|
1406
|
+
fieldName,
|
|
1407
|
+
modelName: opts.modelName,
|
|
1408
|
+
decode: opts.decodeFunctionDefault
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
return data;
|
|
1412
|
+
}
|
|
1413
|
+
function applyAutoStampsFromSchema(fields, data, opts) {
|
|
1414
|
+
const { isNew, now } = opts;
|
|
1415
|
+
for (const [fieldName, field] of Object.entries(fields)) {
|
|
1416
|
+
const stamp = field?.autoStamp;
|
|
1417
|
+
if (!stamp) continue;
|
|
1418
|
+
const explicit = Object.prototype.hasOwnProperty.call(data, fieldName) && data[fieldName] !== null && data[fieldName] !== void 0;
|
|
1419
|
+
if (explicit) continue;
|
|
1420
|
+
if (stamp === "create" && !isNew) continue;
|
|
1421
|
+
data[fieldName] = now;
|
|
1422
|
+
}
|
|
1423
|
+
return data;
|
|
1424
|
+
}
|
|
1425
|
+
var Y2, import_ulid, KNOWN_FIELD_TYPE_MAP, KNOWN_FIELD_TYPES, FUNCTION_DEFAULT_GENERATORS, UNKNOWN_FUNCTION_DEFAULT;
|
|
1426
|
+
var init_writeLifecycle = __esm({
|
|
1427
|
+
"src/models/writeLifecycle.ts"() {
|
|
1428
|
+
"use strict";
|
|
1429
|
+
Y2 = __toESM(require("yjs"), 1);
|
|
1430
|
+
import_ulid = require("ulid");
|
|
1431
|
+
KNOWN_FIELD_TYPE_MAP = {
|
|
1432
|
+
string: true,
|
|
1433
|
+
number: true,
|
|
1434
|
+
boolean: true,
|
|
1435
|
+
date: true,
|
|
1436
|
+
id: true,
|
|
1437
|
+
stringset: true
|
|
1438
|
+
};
|
|
1439
|
+
KNOWN_FIELD_TYPES = new Set(Object.keys(KNOWN_FIELD_TYPE_MAP));
|
|
1440
|
+
FUNCTION_DEFAULT_GENERATORS = /* @__PURE__ */ new Map();
|
|
1441
|
+
registerFunctionDefaultGenerator("generate_ulid", () => (0, import_ulid.ulid)());
|
|
1442
|
+
UNKNOWN_FUNCTION_DEFAULT = "$unknown_function";
|
|
1443
|
+
}
|
|
1444
|
+
});
|
|
1445
|
+
|
|
1223
1446
|
// src/models/metaSync.ts
|
|
1224
1447
|
function inferFieldType(value) {
|
|
1225
1448
|
if (isStringSetYMap(value)) return "stringset";
|
|
@@ -1241,7 +1464,10 @@ function encodeDefault(value) {
|
|
|
1241
1464
|
if (value === void 0 || value === null) return void 0;
|
|
1242
1465
|
if (typeof value === "function") {
|
|
1243
1466
|
const name = KNOWN_FUNCTION_DEFAULTS.get(value);
|
|
1244
|
-
return name ? `$${name}` :
|
|
1467
|
+
return name ? `$${name}` : UNKNOWN_FUNCTION_DEFAULT;
|
|
1468
|
+
}
|
|
1469
|
+
if (typeof value === "string" && value.startsWith("$")) {
|
|
1470
|
+
return `$${value}`;
|
|
1245
1471
|
}
|
|
1246
1472
|
return value;
|
|
1247
1473
|
}
|
|
@@ -1267,7 +1493,7 @@ function syncModelMeta(yDoc, modelName, schema) {
|
|
|
1267
1493
|
if (compoundConstraints.length > 0) {
|
|
1268
1494
|
let constraints = meta.get("_constraints");
|
|
1269
1495
|
if (!constraints) {
|
|
1270
|
-
constraints = new
|
|
1496
|
+
constraints = new Y3.Map();
|
|
1271
1497
|
meta.set("_constraints", constraints);
|
|
1272
1498
|
}
|
|
1273
1499
|
for (const constraint of compoundConstraints) {
|
|
@@ -1278,7 +1504,7 @@ function syncModelMeta(yDoc, modelName, schema) {
|
|
|
1278
1504
|
if (relationships && Object.keys(relationships).length > 0) {
|
|
1279
1505
|
let rels = meta.get("_relationships");
|
|
1280
1506
|
if (!rels) {
|
|
1281
|
-
rels = new
|
|
1507
|
+
rels = new Y3.Map();
|
|
1282
1508
|
meta.set("_relationships", rels);
|
|
1283
1509
|
}
|
|
1284
1510
|
for (const [relName, relConfig] of Object.entries(relationships)) {
|
|
@@ -1290,7 +1516,7 @@ function syncModelMeta(yDoc, modelName, schema) {
|
|
|
1290
1516
|
function syncFieldMeta(metaMap, fieldName, fieldOpts) {
|
|
1291
1517
|
let fieldMeta = metaMap.get(fieldName);
|
|
1292
1518
|
if (!fieldMeta) {
|
|
1293
|
-
fieldMeta = new
|
|
1519
|
+
fieldMeta = new Y3.Map();
|
|
1294
1520
|
metaMap.set(fieldName, fieldMeta);
|
|
1295
1521
|
}
|
|
1296
1522
|
setIfChanged(fieldMeta, "type", fieldOpts.type);
|
|
@@ -1307,7 +1533,7 @@ function syncFieldMeta(metaMap, fieldName, fieldOpts) {
|
|
|
1307
1533
|
function syncConstraintMeta(constraintsMap, constraint) {
|
|
1308
1534
|
let cMeta = constraintsMap.get(constraint.name);
|
|
1309
1535
|
if (!cMeta) {
|
|
1310
|
-
cMeta = new
|
|
1536
|
+
cMeta = new Y3.Map();
|
|
1311
1537
|
constraintsMap.set(constraint.name, cMeta);
|
|
1312
1538
|
}
|
|
1313
1539
|
setIfChanged(cMeta, "type", "unique");
|
|
@@ -1317,7 +1543,7 @@ function syncConstraintMeta(constraintsMap, constraint) {
|
|
|
1317
1543
|
function syncRelationshipMeta(relsMap, relName, relConfig) {
|
|
1318
1544
|
let relMeta = relsMap.get(relName);
|
|
1319
1545
|
if (!relMeta) {
|
|
1320
|
-
relMeta = new
|
|
1546
|
+
relMeta = new Y3.Map();
|
|
1321
1547
|
relsMap.set(relName, relMeta);
|
|
1322
1548
|
}
|
|
1323
1549
|
for (const [key, value] of Object.entries(relConfig)) {
|
|
@@ -1332,7 +1558,7 @@ function syncInferredMeta(yDoc, modelName, recordData) {
|
|
|
1332
1558
|
if (fieldName.startsWith("_")) continue;
|
|
1333
1559
|
let fieldMeta = meta.get(fieldName);
|
|
1334
1560
|
if (!fieldMeta) {
|
|
1335
|
-
fieldMeta = new
|
|
1561
|
+
fieldMeta = new Y3.Map();
|
|
1336
1562
|
meta.set(fieldName, fieldMeta);
|
|
1337
1563
|
}
|
|
1338
1564
|
if (!fieldMeta.has("type")) {
|
|
@@ -1348,18 +1574,58 @@ function setIfChanged(map, key, value) {
|
|
|
1348
1574
|
map.set(key, value);
|
|
1349
1575
|
}
|
|
1350
1576
|
}
|
|
1351
|
-
var
|
|
1577
|
+
var Y3, KNOWN_FUNCTION_DEFAULTS, _syncedCache;
|
|
1352
1578
|
var init_metaSync = __esm({
|
|
1353
1579
|
"src/models/metaSync.ts"() {
|
|
1354
1580
|
"use strict";
|
|
1355
|
-
|
|
1581
|
+
Y3 = __toESM(require("yjs"), 1);
|
|
1356
1582
|
init_yjsValues();
|
|
1583
|
+
init_writeLifecycle();
|
|
1357
1584
|
KNOWN_FUNCTION_DEFAULTS = /* @__PURE__ */ new WeakMap();
|
|
1358
1585
|
_syncedCache = /* @__PURE__ */ new WeakMap();
|
|
1359
1586
|
}
|
|
1360
1587
|
});
|
|
1361
1588
|
|
|
1589
|
+
// src/utils/uniqueIndex.ts
|
|
1590
|
+
function buildUniqueKey(recordData, fields) {
|
|
1591
|
+
const keyParts = [];
|
|
1592
|
+
for (const field of fields) {
|
|
1593
|
+
const value = recordData instanceof Y4.Map ? recordData.get(field) : recordData[field];
|
|
1594
|
+
if (value === null || value === void 0) {
|
|
1595
|
+
return null;
|
|
1596
|
+
}
|
|
1597
|
+
keyParts.push(String(value));
|
|
1598
|
+
}
|
|
1599
|
+
return keyParts.join("|");
|
|
1600
|
+
}
|
|
1601
|
+
function uniqueIndexMapName(modelName, constraintName) {
|
|
1602
|
+
return `_uniqueIdx_${modelName}_${constraintName}`;
|
|
1603
|
+
}
|
|
1604
|
+
function fieldUniqueConstraintName(modelName, fieldName) {
|
|
1605
|
+
return `${modelName}_${fieldName}_unique`;
|
|
1606
|
+
}
|
|
1607
|
+
var Y4;
|
|
1608
|
+
var init_uniqueIndex = __esm({
|
|
1609
|
+
"src/utils/uniqueIndex.ts"() {
|
|
1610
|
+
"use strict";
|
|
1611
|
+
Y4 = __toESM(require("yjs"), 1);
|
|
1612
|
+
}
|
|
1613
|
+
});
|
|
1614
|
+
|
|
1362
1615
|
// src/models/relationshipManager.ts
|
|
1616
|
+
function warnIfOrderFieldNullable(modelClass, orderByField, relationshipDescription) {
|
|
1617
|
+
if (ALWAYS_PRESENT_ORDER_FIELDS.has(orderByField)) return;
|
|
1618
|
+
const schema = modelClass.getSchema?.();
|
|
1619
|
+
const fields = schema?.fields;
|
|
1620
|
+
if (!fields || typeof fields.get !== "function") return;
|
|
1621
|
+
const fieldOptions = fields.get(orderByField);
|
|
1622
|
+
if (!fieldOptions) return;
|
|
1623
|
+
if (fieldOptions.required !== true) {
|
|
1624
|
+
Logger.warn(
|
|
1625
|
+
`[RelationshipManager] ${relationshipDescription} orders by '${orderByField}', which is not marked required on ${modelClass.name}. The composite (${orderByField}, id) cursor paginates deterministically, but a row whose '${orderByField}' is actually NULL has no stable cursor position and may drop from the tail. Mark '${orderByField}' as required, or order by a required field such as 'id', to remove the risk. (Full NULL-ordering support is tracked in #1316.)`
|
|
1626
|
+
);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1363
1629
|
function generateRefersToMethod(_sourceModelClass, config, targetModelClass) {
|
|
1364
1630
|
return async function() {
|
|
1365
1631
|
const relatedId = this[config.relatedIdField];
|
|
@@ -1368,6 +1634,16 @@ function generateRefersToMethod(_sourceModelClass, config, targetModelClass) {
|
|
|
1368
1634
|
};
|
|
1369
1635
|
}
|
|
1370
1636
|
function generateHasManyMethod(_sourceModelClass, config, targetModelClass, _dbEngine) {
|
|
1637
|
+
const {
|
|
1638
|
+
relatedIdField,
|
|
1639
|
+
orderByField = "id",
|
|
1640
|
+
orderDirection = "ASC"
|
|
1641
|
+
} = config;
|
|
1642
|
+
warnIfOrderFieldNullable(
|
|
1643
|
+
targetModelClass,
|
|
1644
|
+
orderByField,
|
|
1645
|
+
`hasMany(${targetModelClass.name})`
|
|
1646
|
+
);
|
|
1371
1647
|
return async function(paginationArgs) {
|
|
1372
1648
|
const {
|
|
1373
1649
|
limit,
|
|
@@ -1375,71 +1651,39 @@ function generateHasManyMethod(_sourceModelClass, config, targetModelClass, _dbE
|
|
|
1375
1651
|
beforeCursor,
|
|
1376
1652
|
direction = "forward"
|
|
1377
1653
|
} = paginationArgs || {};
|
|
1378
|
-
const {
|
|
1379
|
-
relatedIdField,
|
|
1380
|
-
orderByField = "id",
|
|
1381
|
-
orderDirection = "ASC"
|
|
1382
|
-
} = config;
|
|
1383
1654
|
const targetSchema = targetModelClass.getSchema();
|
|
1384
1655
|
if (!targetSchema || !targetSchema.options || !targetSchema.options.name) {
|
|
1385
1656
|
Logger.error(
|
|
1386
1657
|
`[RelationshipManager] Target model ${targetModelClass.name} for hasMany relationship has no valid schema name.`
|
|
1387
1658
|
);
|
|
1388
|
-
return { data: [],
|
|
1659
|
+
return { data: [], hasMore: false };
|
|
1389
1660
|
}
|
|
1390
|
-
const
|
|
1661
|
+
const forward = direction !== "backward";
|
|
1662
|
+
const cursor = forward ? afterCursor : beforeCursor;
|
|
1391
1663
|
const queryOptions = {
|
|
1392
|
-
sort: { [orderByField]: orderDirection === "ASC" ? 1 : -1 }
|
|
1664
|
+
sort: { [orderByField]: orderDirection === "ASC" ? 1 : -1 },
|
|
1665
|
+
direction: forward ? 1 : -1
|
|
1393
1666
|
};
|
|
1394
|
-
if (limit !== void 0)
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
};
|
|
1401
|
-
} else if (direction === "backward") {
|
|
1402
|
-
if (beforeCursor) {
|
|
1403
|
-
filter[orderByField] = {
|
|
1404
|
-
[orderDirection === "ASC" ? "$lt" : "$gt"]: beforeCursor
|
|
1405
|
-
};
|
|
1406
|
-
}
|
|
1407
|
-
queryOptions.sort = { [orderByField]: orderDirection === "ASC" ? -1 : 1 };
|
|
1408
|
-
}
|
|
1409
|
-
const result = await targetModelClass.query(filter, queryOptions);
|
|
1410
|
-
const results = result.data;
|
|
1411
|
-
let nextCursor = null;
|
|
1412
|
-
let prevCursor = null;
|
|
1413
|
-
const isFirstPage = direction === "forward" && !afterCursor;
|
|
1414
|
-
if (limit !== void 0) {
|
|
1415
|
-
if (direction === "forward") {
|
|
1416
|
-
if (results.length > limit) {
|
|
1417
|
-
nextCursor = results[limit - 1][orderByField];
|
|
1418
|
-
results.pop();
|
|
1419
|
-
}
|
|
1420
|
-
if (results.length > 0 && !isFirstPage) {
|
|
1421
|
-
prevCursor = results[0][orderByField];
|
|
1422
|
-
}
|
|
1423
|
-
} else {
|
|
1424
|
-
if (results.length > limit) {
|
|
1425
|
-
prevCursor = results[limit - 1][orderByField];
|
|
1426
|
-
results.pop();
|
|
1427
|
-
}
|
|
1428
|
-
results.reverse();
|
|
1429
|
-
if (results.length > 0 && beforeCursor) {
|
|
1430
|
-
nextCursor = results[results.length - 1][orderByField];
|
|
1431
|
-
}
|
|
1432
|
-
if (results.length > 0 && !beforeCursor) {
|
|
1433
|
-
if (results.length === limit) {
|
|
1434
|
-
prevCursor = results[0][orderByField];
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1439
|
-
return { data: results, nextCursor, prevCursor };
|
|
1667
|
+
if (limit !== void 0) queryOptions.limit = limit;
|
|
1668
|
+
if (cursor != null) queryOptions.uniqueStartKey = cursor;
|
|
1669
|
+
return targetModelClass.query(
|
|
1670
|
+
{ [relatedIdField]: this.id },
|
|
1671
|
+
queryOptions
|
|
1672
|
+
);
|
|
1440
1673
|
};
|
|
1441
1674
|
}
|
|
1442
1675
|
function generateHasManyThroughMethod(_sourceModelClass, config, targetModelClass, joinModelClass, _dbEngine) {
|
|
1676
|
+
const {
|
|
1677
|
+
joinModelLocalField,
|
|
1678
|
+
joinModelRelatedField,
|
|
1679
|
+
joinModelOrderByField = "id",
|
|
1680
|
+
joinModelOrderDirection = "ASC"
|
|
1681
|
+
} = config;
|
|
1682
|
+
warnIfOrderFieldNullable(
|
|
1683
|
+
joinModelClass,
|
|
1684
|
+
joinModelOrderByField,
|
|
1685
|
+
`hasManyThrough(${targetModelClass.name} via ${joinModelClass.name})`
|
|
1686
|
+
);
|
|
1443
1687
|
return async function(paginationArgs) {
|
|
1444
1688
|
const {
|
|
1445
1689
|
limit,
|
|
@@ -1453,87 +1697,42 @@ function generateHasManyThroughMethod(_sourceModelClass, config, targetModelClas
|
|
|
1453
1697
|
Logger.error(
|
|
1454
1698
|
`[RelationshipManager] Join model ${joinModelClass.name} for hasManyThrough relationship has no valid schema name.`
|
|
1455
1699
|
);
|
|
1456
|
-
return { data: [],
|
|
1700
|
+
return { data: [], hasMore: false };
|
|
1457
1701
|
}
|
|
1458
1702
|
if (!targetSchema || !targetSchema.options || !targetSchema.options.name) {
|
|
1459
1703
|
Logger.error(
|
|
1460
1704
|
`[RelationshipManager] Target model ${targetModelClass.name} for hasManyThrough relationship has no valid schema name.`
|
|
1461
1705
|
);
|
|
1462
|
-
return { data: [],
|
|
1706
|
+
return { data: [], hasMore: false };
|
|
1463
1707
|
}
|
|
1464
|
-
const
|
|
1465
|
-
|
|
1466
|
-
joinModelRelatedField,
|
|
1467
|
-
joinModelOrderByField = "id",
|
|
1468
|
-
joinModelOrderDirection = "ASC"
|
|
1469
|
-
} = config;
|
|
1470
|
-
const joinFilter = { [joinModelLocalField]: this.id };
|
|
1708
|
+
const forward = direction !== "backward";
|
|
1709
|
+
const cursor = forward ? afterCursor : beforeCursor;
|
|
1471
1710
|
const joinQueryOptions = {
|
|
1472
1711
|
sort: {
|
|
1473
1712
|
[joinModelOrderByField]: joinModelOrderDirection === "ASC" ? 1 : -1
|
|
1474
1713
|
},
|
|
1475
|
-
projection: { [joinModelRelatedField]: 1, [joinModelOrderByField]: 1 }
|
|
1714
|
+
projection: { [joinModelRelatedField]: 1, [joinModelOrderByField]: 1 },
|
|
1715
|
+
direction: forward ? 1 : -1
|
|
1476
1716
|
};
|
|
1477
|
-
if (limit !== void 0)
|
|
1478
|
-
|
|
1479
|
-
}
|
|
1480
|
-
if (direction === "forward" && afterCursor) {
|
|
1481
|
-
joinFilter[joinModelOrderByField] = {
|
|
1482
|
-
[joinModelOrderDirection === "ASC" ? "$gt" : "$lt"]: afterCursor
|
|
1483
|
-
};
|
|
1484
|
-
} else if (direction === "backward") {
|
|
1485
|
-
if (beforeCursor) {
|
|
1486
|
-
joinFilter[joinModelOrderByField] = {
|
|
1487
|
-
[joinModelOrderDirection === "ASC" ? "$lt" : "$gt"]: beforeCursor
|
|
1488
|
-
};
|
|
1489
|
-
}
|
|
1490
|
-
joinQueryOptions.sort = {
|
|
1491
|
-
[joinModelOrderByField]: joinModelOrderDirection === "ASC" ? -1 : 1
|
|
1492
|
-
};
|
|
1493
|
-
}
|
|
1717
|
+
if (limit !== void 0) joinQueryOptions.limit = limit;
|
|
1718
|
+
if (cursor != null) joinQueryOptions.uniqueStartKey = cursor;
|
|
1494
1719
|
const joinResult = await joinModelClass.query(
|
|
1495
|
-
|
|
1720
|
+
{ [joinModelLocalField]: this.id },
|
|
1496
1721
|
joinQueryOptions
|
|
1497
1722
|
);
|
|
1498
|
-
const
|
|
1499
|
-
let
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
nextCursorFromJoin = joinResults[limit - 1][joinModelOrderByField];
|
|
1506
|
-
joinResults.pop();
|
|
1507
|
-
}
|
|
1508
|
-
if (joinResults.length > 0 && !isFirstPage) {
|
|
1509
|
-
prevCursorFromJoin = joinResults[0][joinModelOrderByField];
|
|
1510
|
-
}
|
|
1511
|
-
} else {
|
|
1512
|
-
if (joinResults.length > limit) {
|
|
1513
|
-
prevCursorFromJoin = joinResults[limit - 1][joinModelOrderByField];
|
|
1514
|
-
joinResults.pop();
|
|
1515
|
-
}
|
|
1516
|
-
joinResults.reverse();
|
|
1517
|
-
if (joinResults.length > 0 && beforeCursor) {
|
|
1518
|
-
nextCursorFromJoin = joinResults[joinResults.length - 1][joinModelOrderByField];
|
|
1519
|
-
}
|
|
1520
|
-
if (joinResults.length > 0 && !beforeCursor) {
|
|
1521
|
-
if (joinResults.length === limit) {
|
|
1522
|
-
prevCursorFromJoin = joinResults[0][joinModelOrderByField];
|
|
1523
|
-
}
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1723
|
+
const relatedIds = joinResult.data.map((r) => r[joinModelRelatedField]).filter((id) => id != null && typeof id === "string");
|
|
1724
|
+
let targetData = [];
|
|
1725
|
+
if (relatedIds.length > 0) {
|
|
1726
|
+
const targetResult = await targetModelClass.query({
|
|
1727
|
+
id: { $in: relatedIds }
|
|
1728
|
+
});
|
|
1729
|
+
targetData = targetResult.data;
|
|
1526
1730
|
}
|
|
1527
|
-
const relatedIds = joinResults.map((r) => r[joinModelRelatedField]).filter((id) => id != null && typeof id === "string");
|
|
1528
|
-
if (relatedIds.length === 0)
|
|
1529
|
-
return { data: [], nextCursor: null, prevCursor: null };
|
|
1530
|
-
const targetResult = await targetModelClass.query({
|
|
1531
|
-
id: { $in: relatedIds }
|
|
1532
|
-
});
|
|
1533
1731
|
return {
|
|
1534
|
-
data:
|
|
1535
|
-
nextCursor:
|
|
1536
|
-
prevCursor:
|
|
1732
|
+
data: targetData,
|
|
1733
|
+
nextCursor: joinResult.nextCursor,
|
|
1734
|
+
prevCursor: joinResult.prevCursor,
|
|
1735
|
+
hasMore: joinResult.hasMore
|
|
1537
1736
|
};
|
|
1538
1737
|
};
|
|
1539
1738
|
}
|
|
@@ -1657,10 +1856,12 @@ function generateHasManyThroughRemoveMethod(_sourceModelClass, config, _targetMo
|
|
|
1657
1856
|
}, `remove-join-${config.joinModel}-${this.id}-${targetId}`);
|
|
1658
1857
|
};
|
|
1659
1858
|
}
|
|
1859
|
+
var ALWAYS_PRESENT_ORDER_FIELDS;
|
|
1660
1860
|
var init_relationshipManager = __esm({
|
|
1661
1861
|
"src/models/relationshipManager.ts"() {
|
|
1662
1862
|
"use strict";
|
|
1663
1863
|
init_BaseModel();
|
|
1864
|
+
ALWAYS_PRESENT_ORDER_FIELDS = /* @__PURE__ */ new Set(["id", "type"]);
|
|
1664
1865
|
}
|
|
1665
1866
|
});
|
|
1666
1867
|
|
|
@@ -2431,7 +2632,13 @@ var init_IncludeResolver = __esm({
|
|
|
2431
2632
|
}
|
|
2432
2633
|
return null;
|
|
2433
2634
|
}
|
|
2434
|
-
/**
|
|
2635
|
+
/**
|
|
2636
|
+
* Apply a projection to a single record. Assumes the projection was already
|
|
2637
|
+
* validated upstream (mixed inclusion+exclusion rejected by the translator):
|
|
2638
|
+
* `isInclusion` treats "any value === 1" as inclusion mode. `id` and `type`
|
|
2639
|
+
* are system-identity fields and are always kept in BOTH modes (mirrors the
|
|
2640
|
+
* DatabaseDO `_applyProjection`); `_meta` stays excludable.
|
|
2641
|
+
*/
|
|
2435
2642
|
_applyProjection(record, projection) {
|
|
2436
2643
|
const fields = Object.entries(projection);
|
|
2437
2644
|
if (fields.length === 0) return record;
|
|
@@ -2450,7 +2657,7 @@ var init_IncludeResolver = __esm({
|
|
|
2450
2657
|
} else {
|
|
2451
2658
|
const result = { ...record };
|
|
2452
2659
|
for (const [f, v] of fields) {
|
|
2453
|
-
if (v === 0) delete result[f];
|
|
2660
|
+
if (v === 0 && f !== "id" && f !== "type") delete result[f];
|
|
2454
2661
|
}
|
|
2455
2662
|
return result;
|
|
2456
2663
|
}
|
|
@@ -2470,21 +2677,23 @@ __export(BaseModel_exports, {
|
|
|
2470
2677
|
generateULID: () => generateULID
|
|
2471
2678
|
});
|
|
2472
2679
|
function generateULID() {
|
|
2473
|
-
return (0,
|
|
2680
|
+
return (0, import_ulid2.ulid)();
|
|
2474
2681
|
}
|
|
2475
|
-
var
|
|
2682
|
+
var Y5, import_ulid2, LogLevel, Logger, UniqueConstraintViolationError, RecordNotFoundError, SCHEMA_ACCESSORS_KEY, BaseModel2;
|
|
2476
2683
|
var init_BaseModel = __esm({
|
|
2477
2684
|
"src/models/BaseModel.ts"() {
|
|
2478
2685
|
"use strict";
|
|
2479
|
-
|
|
2480
|
-
|
|
2686
|
+
Y5 = __toESM(require("yjs"), 1);
|
|
2687
|
+
import_ulid2 = require("ulid");
|
|
2481
2688
|
init_StringSet();
|
|
2482
2689
|
init_documentTypes();
|
|
2483
2690
|
init_DocumentQueryTranslator();
|
|
2484
2691
|
init_CursorManager();
|
|
2485
2692
|
init_sql();
|
|
2486
2693
|
init_metaSync();
|
|
2694
|
+
init_writeLifecycle();
|
|
2487
2695
|
init_yjsValues();
|
|
2696
|
+
init_uniqueIndex();
|
|
2488
2697
|
LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
2489
2698
|
LogLevel2[LogLevel2["SILENT"] = 0] = "SILENT";
|
|
2490
2699
|
LogLevel2[LogLevel2["ERROR"] = 1] = "ERROR";
|
|
@@ -2869,7 +3078,9 @@ var init_BaseModel = __esm({
|
|
|
2869
3078
|
this.setValue(fieldKey, data[fieldKey]);
|
|
2870
3079
|
this._constructorProvidedFields.add(fieldKey);
|
|
2871
3080
|
} else if (fieldOptions.default !== void 0) {
|
|
2872
|
-
const defaultValue =
|
|
3081
|
+
const defaultValue = resolveLiteralOrFunctionDefault(
|
|
3082
|
+
fieldOptions.default
|
|
3083
|
+
);
|
|
2873
3084
|
this.setValue(fieldKey, defaultValue);
|
|
2874
3085
|
}
|
|
2875
3086
|
}
|
|
@@ -3161,7 +3372,7 @@ var init_BaseModel = __esm({
|
|
|
3161
3372
|
}
|
|
3162
3373
|
getStringSetFromYjs(fieldName) {
|
|
3163
3374
|
const yjsData = this.getFromYjs(fieldName);
|
|
3164
|
-
if (yjsData instanceof
|
|
3375
|
+
if (yjsData instanceof Y5.Map) {
|
|
3165
3376
|
return Array.from(yjsData.keys());
|
|
3166
3377
|
}
|
|
3167
3378
|
if (yjsData && typeof yjsData === "object") {
|
|
@@ -3269,7 +3480,7 @@ var init_BaseModel = __esm({
|
|
|
3269
3480
|
}
|
|
3270
3481
|
const extractStringSetValues = (value) => {
|
|
3271
3482
|
if (!value) return [];
|
|
3272
|
-
if (value instanceof
|
|
3483
|
+
if (value instanceof Y5.Map) {
|
|
3273
3484
|
return Array.from(value.entries()).filter(([, isMember]) => Boolean(isMember)).map(([key]) => key);
|
|
3274
3485
|
}
|
|
3275
3486
|
if (Array.isArray(value)) {
|
|
@@ -3286,7 +3497,7 @@ var init_BaseModel = __esm({
|
|
|
3286
3497
|
if (!recordId) continue;
|
|
3287
3498
|
let itemData;
|
|
3288
3499
|
const stringSetValuesByField = {};
|
|
3289
|
-
if (recordData instanceof
|
|
3500
|
+
if (recordData instanceof Y5.Map) {
|
|
3290
3501
|
itemData = {};
|
|
3291
3502
|
const unknownFields = [];
|
|
3292
3503
|
for (const [fieldKey, value] of recordData.entries()) {
|
|
@@ -3402,20 +3613,10 @@ var init_BaseModel = __esm({
|
|
|
3402
3613
|
Logger.verbose(
|
|
3403
3614
|
`[${this.name}] Setting up YMap observer for document ${docId}/${modelName}...`
|
|
3404
3615
|
);
|
|
3405
|
-
const
|
|
3406
|
-
const keyParts = [];
|
|
3407
|
-
for (const field of fields) {
|
|
3408
|
-
const value = recordData instanceof Y3.Map ? recordData.get(field) : recordData[field];
|
|
3409
|
-
if (value === null || value === void 0) {
|
|
3410
|
-
return null;
|
|
3411
|
-
}
|
|
3412
|
-
keyParts.push(String(value));
|
|
3413
|
-
}
|
|
3414
|
-
return keyParts.join("|");
|
|
3415
|
-
};
|
|
3616
|
+
const buildUniqueKey2 = (recordData, fields) => buildUniqueKey(recordData, fields);
|
|
3416
3617
|
const extractItemData = (key, recordData) => {
|
|
3417
3618
|
let itemData;
|
|
3418
|
-
if (recordData instanceof
|
|
3619
|
+
if (recordData instanceof Y5.Map) {
|
|
3419
3620
|
itemData = {};
|
|
3420
3621
|
const unknownFields = [];
|
|
3421
3622
|
for (const [fieldKey, value] of recordData.entries()) {
|
|
@@ -3499,7 +3700,7 @@ var init_BaseModel = __esm({
|
|
|
3499
3700
|
const recordsByUniqueKey = /* @__PURE__ */ new Map();
|
|
3500
3701
|
for (const [recordId, recordData] of allRecords.entries()) {
|
|
3501
3702
|
if (recordIdsToDiscard.has(recordId)) continue;
|
|
3502
|
-
const uniqueKey =
|
|
3703
|
+
const uniqueKey = buildUniqueKey2(recordData, constraint.fields);
|
|
3503
3704
|
if (uniqueKey === null) continue;
|
|
3504
3705
|
if (!recordsByUniqueKey.has(uniqueKey)) {
|
|
3505
3706
|
recordsByUniqueKey.set(uniqueKey, []);
|
|
@@ -3545,7 +3746,7 @@ var init_BaseModel = __esm({
|
|
|
3545
3746
|
if (!recordData || !key) continue;
|
|
3546
3747
|
const itemData = extractItemData(key, recordData);
|
|
3547
3748
|
if (!itemData) continue;
|
|
3548
|
-
if (change.action === "add" && recordData instanceof
|
|
3749
|
+
if (change.action === "add" && recordData instanceof Y5.Map) {
|
|
3549
3750
|
Logger.verbose(
|
|
3550
3751
|
`[${this.name}] Setting up observer on newly added nested YMap for record ${key} in document ${docId}`
|
|
3551
3752
|
);
|
|
@@ -3643,9 +3844,12 @@ var init_BaseModel = __esm({
|
|
|
3643
3844
|
const recordData = documentYMap.get(idToDiscard);
|
|
3644
3845
|
if (!recordData) continue;
|
|
3645
3846
|
for (const constraint of schema.resolvedUniqueConstraints) {
|
|
3646
|
-
const uniqueKey =
|
|
3847
|
+
const uniqueKey = buildUniqueKey2(recordData, constraint.fields);
|
|
3647
3848
|
if (uniqueKey === null) continue;
|
|
3648
|
-
const constraintMapName =
|
|
3849
|
+
const constraintMapName = uniqueIndexMapName(
|
|
3850
|
+
modelName,
|
|
3851
|
+
constraint.name
|
|
3852
|
+
);
|
|
3649
3853
|
const constraintMap = yDoc.getMap(constraintMapName);
|
|
3650
3854
|
const currentIndexValue = constraintMap.get(uniqueKey);
|
|
3651
3855
|
if (currentIndexValue === idToDiscard) {
|
|
@@ -3663,11 +3867,14 @@ var init_BaseModel = __esm({
|
|
|
3663
3867
|
}, `conflict-resolution-${modelName}-${docId}`);
|
|
3664
3868
|
yDoc.transact(() => {
|
|
3665
3869
|
for (const constraint of schema.resolvedUniqueConstraints) {
|
|
3666
|
-
const constraintMapName =
|
|
3870
|
+
const constraintMapName = uniqueIndexMapName(
|
|
3871
|
+
modelName,
|
|
3872
|
+
constraint.name
|
|
3873
|
+
);
|
|
3667
3874
|
const constraintMap = yDoc.getMap(constraintMapName);
|
|
3668
3875
|
for (const [recordId, recordData] of documentYMap.entries()) {
|
|
3669
3876
|
if (!recordData) continue;
|
|
3670
|
-
const uniqueKey =
|
|
3877
|
+
const uniqueKey = buildUniqueKey2(recordData, constraint.fields);
|
|
3671
3878
|
if (uniqueKey === null) continue;
|
|
3672
3879
|
const currentIndexValue = constraintMap.get(uniqueKey);
|
|
3673
3880
|
if (currentIndexValue !== recordId) {
|
|
@@ -3690,7 +3897,7 @@ var init_BaseModel = __esm({
|
|
|
3690
3897
|
`[${this.name}] Setting up observers on existing nested YMaps for ${modelName}/${docId}...`
|
|
3691
3898
|
);
|
|
3692
3899
|
for (const [recordId, recordData] of documentYMap.entries()) {
|
|
3693
|
-
if (recordData instanceof
|
|
3900
|
+
if (recordData instanceof Y5.Map) {
|
|
3694
3901
|
Logger.verbose(
|
|
3695
3902
|
`[${this.name}] Setting up observer on existing nested YMap for record ${recordId} in document ${docId}`
|
|
3696
3903
|
);
|
|
@@ -3916,26 +4123,7 @@ var init_BaseModel = __esm({
|
|
|
3916
4123
|
* if the field hasn't been touched since the wire-format change in #561.
|
|
3917
4124
|
*/
|
|
3918
4125
|
applyStringSetChangeToYMap(recordYMap, fieldName, change) {
|
|
3919
|
-
|
|
3920
|
-
if (!(nested instanceof Y3.Map)) {
|
|
3921
|
-
const migrated = new Y3.Map();
|
|
3922
|
-
if (nested && typeof nested === "object") {
|
|
3923
|
-
for (const [member, marker] of Object.entries(
|
|
3924
|
-
nested
|
|
3925
|
-
)) {
|
|
3926
|
-
if (Boolean(marker)) migrated.set(member, true);
|
|
3927
|
-
}
|
|
3928
|
-
}
|
|
3929
|
-
recordYMap.set(fieldName, migrated);
|
|
3930
|
-
nested = migrated;
|
|
3931
|
-
}
|
|
3932
|
-
const target = nested;
|
|
3933
|
-
for (const member of change.additions) {
|
|
3934
|
-
target.set(member, true);
|
|
3935
|
-
}
|
|
3936
|
-
for (const member of change.removals) {
|
|
3937
|
-
target.delete(member);
|
|
3938
|
-
}
|
|
4126
|
+
applyStringSetChange(recordYMap, fieldName, change);
|
|
3939
4127
|
}
|
|
3940
4128
|
/**
|
|
3941
4129
|
* Deep equality check for comparing field values
|
|
@@ -4137,6 +4325,34 @@ var init_BaseModel = __esm({
|
|
|
4137
4325
|
`[${modelName}.save] getCurrentJSState() returned:`,
|
|
4138
4326
|
dataToSave
|
|
4139
4327
|
);
|
|
4328
|
+
const uniqueMissConflicts = /* @__PURE__ */ new Map();
|
|
4329
|
+
for (const constraint of schema.resolvedUniqueConstraints) {
|
|
4330
|
+
const newUniqueKey = this._buildUniqueKey(
|
|
4331
|
+
constraint.fields,
|
|
4332
|
+
dataToSave,
|
|
4333
|
+
modelName,
|
|
4334
|
+
constraint.name
|
|
4335
|
+
);
|
|
4336
|
+
if (newUniqueKey === null) {
|
|
4337
|
+
continue;
|
|
4338
|
+
}
|
|
4339
|
+
const constraintMap = yDoc.getMap(
|
|
4340
|
+
uniqueIndexMapName(modelName, constraint.name)
|
|
4341
|
+
);
|
|
4342
|
+
if (!constraintMap.get(newUniqueKey)) {
|
|
4343
|
+
const constraintKeyValues = constraint.fields.map(
|
|
4344
|
+
(field) => dataToSave[field]
|
|
4345
|
+
);
|
|
4346
|
+
const conflictingRecord = await modelConstructor._resolveByUniqueFallback(
|
|
4347
|
+
constraint,
|
|
4348
|
+
constraintKeyValues,
|
|
4349
|
+
{ excludeId: this.id }
|
|
4350
|
+
);
|
|
4351
|
+
if (conflictingRecord) {
|
|
4352
|
+
uniqueMissConflicts.set(constraint.name, conflictingRecord.id);
|
|
4353
|
+
}
|
|
4354
|
+
}
|
|
4355
|
+
}
|
|
4140
4356
|
await yDoc.transact(async () => {
|
|
4141
4357
|
if (upsertOnConstraint && upsertOnKey) {
|
|
4142
4358
|
const constraintMapName = `_uniqueIdx_${modelName}_${upsertOnConstraint.name}`;
|
|
@@ -4178,7 +4394,7 @@ var init_BaseModel = __esm({
|
|
|
4178
4394
|
Logger.debug(`[${modelName}.save] isUpdate: ${isUpdate}`);
|
|
4179
4395
|
Logger.debug(`[${modelName}.save] recordYMap exists: ${!!recordYMap}`);
|
|
4180
4396
|
if (!recordYMap) {
|
|
4181
|
-
recordYMap = new
|
|
4397
|
+
recordYMap = new Y5.Map();
|
|
4182
4398
|
Logger.verbose(
|
|
4183
4399
|
`[${modelName}] Creating new nested YMap for record ${this.id} in document ${targetDocId || "legacy"}`
|
|
4184
4400
|
);
|
|
@@ -4230,7 +4446,10 @@ var init_BaseModel = __esm({
|
|
|
4230
4446
|
);
|
|
4231
4447
|
continue;
|
|
4232
4448
|
}
|
|
4233
|
-
const constraintMapName =
|
|
4449
|
+
const constraintMapName = uniqueIndexMapName(
|
|
4450
|
+
modelName,
|
|
4451
|
+
constraint.name
|
|
4452
|
+
);
|
|
4234
4453
|
const constraintMap = yDoc.getMap(constraintMapName);
|
|
4235
4454
|
Logger.verbose(
|
|
4236
4455
|
`[${modelName}] Save Check (Item '${this.id}'): GET from '${constraintMapName}' with Key '${newUniqueKey.substring(
|
|
@@ -4259,6 +4478,26 @@ var init_BaseModel = __esm({
|
|
|
4259
4478
|
this.id,
|
|
4260
4479
|
existingRecordIdWithNewKey
|
|
4261
4480
|
);
|
|
4481
|
+
} else if (!existingRecordIdWithNewKey) {
|
|
4482
|
+
const conflictingRecordId = uniqueMissConflicts.get(constraint.name);
|
|
4483
|
+
if (conflictingRecordId && conflictingRecordId !== this.id) {
|
|
4484
|
+
Logger.verbose(
|
|
4485
|
+
`[${modelName}] Save Check (Item '${this.id}'): index miss for '${constraint.name}', but engine fallback found conflicting index-less record ${conflictingRecordId}.`
|
|
4486
|
+
);
|
|
4487
|
+
throw new UniqueConstraintViolationError(
|
|
4488
|
+
`Unique constraint '${constraint.name}' violated for model '${modelName}' on fields [${constraint.fields.join(
|
|
4489
|
+
", "
|
|
4490
|
+
)}]. Attempted ID: ${this.id}. Value(s) starting with '${newUniqueKey.substring(
|
|
4491
|
+
0,
|
|
4492
|
+
50
|
|
4493
|
+
)}...' already exist for index-less record ID ${conflictingRecordId}.`,
|
|
4494
|
+
modelName,
|
|
4495
|
+
constraint.name,
|
|
4496
|
+
constraint.fields,
|
|
4497
|
+
this.id,
|
|
4498
|
+
conflictingRecordId
|
|
4499
|
+
);
|
|
4500
|
+
}
|
|
4262
4501
|
}
|
|
4263
4502
|
}
|
|
4264
4503
|
if (isUpdate && oldData) {
|
|
@@ -4602,34 +4841,46 @@ var init_BaseModel = __esm({
|
|
|
4602
4841
|
const modelName = schema.options.name;
|
|
4603
4842
|
Logger.verbose(`[${modelName}] Executing query:`, { filter, options });
|
|
4604
4843
|
const hasIncludes = options?.include && options.include.length > 0;
|
|
4605
|
-
const
|
|
4844
|
+
const requestedLimit = options?.limit;
|
|
4845
|
+
const overFetch = typeof requestedLimit === "number" && requestedLimit > 0;
|
|
4846
|
+
let translatorOptions = hasIncludes && options?.projection ? { ...options, projection: void 0 } : options;
|
|
4847
|
+
if (overFetch) {
|
|
4848
|
+
translatorOptions = {
|
|
4849
|
+
...translatorOptions || {},
|
|
4850
|
+
limit: requestedLimit + 1
|
|
4851
|
+
};
|
|
4852
|
+
}
|
|
4606
4853
|
const translator = new DocumentQueryTranslator(modelName, schema.fields);
|
|
4607
4854
|
const translatedQuery = translator.translateFind(filter, translatorOptions);
|
|
4608
4855
|
Logger.verbose(`[${modelName}] Translated SQL:`, translatedQuery.sql);
|
|
4609
4856
|
Logger.verbose(`[${modelName}] SQL params:`, translatedQuery.params);
|
|
4610
|
-
|
|
4857
|
+
let results = await _BaseModel.dbInstance.query(
|
|
4611
4858
|
translatedQuery.sql,
|
|
4612
4859
|
translatedQuery.params
|
|
4613
4860
|
);
|
|
4614
4861
|
Logger.verbose(`[${modelName}] Query returned ${results.length} results`);
|
|
4862
|
+
let hasMore = false;
|
|
4863
|
+
if (overFetch && results.length > requestedLimit) {
|
|
4864
|
+
hasMore = true;
|
|
4865
|
+
results = results.slice(0, requestedLimit);
|
|
4866
|
+
}
|
|
4615
4867
|
if (options?.include && options.include.length > 0) {
|
|
4616
4868
|
const { IncludeResolver: IncludeResolver2 } = await Promise.resolve().then(() => (init_IncludeResolver(), IncludeResolver_exports));
|
|
4617
4869
|
const resolver = new IncludeResolver2(_BaseModel.dbInstance);
|
|
4618
4870
|
await resolver.resolve(results, options.include, 0, modelName);
|
|
4619
4871
|
}
|
|
4620
|
-
const requestedLimit = options?.limit;
|
|
4621
|
-
const hasMore = CursorManager.hasMoreResults(
|
|
4622
|
-
requestedLimit,
|
|
4623
|
-
results.length
|
|
4624
|
-
);
|
|
4625
4872
|
const isFirstPage = !options?.uniqueStartKey;
|
|
4873
|
+
const direction = options?.direction || 1;
|
|
4626
4874
|
const cursors = CursorManager.generateResultCursors(
|
|
4627
4875
|
results,
|
|
4628
4876
|
translatedQuery.sortFields,
|
|
4629
|
-
|
|
4877
|
+
direction,
|
|
4630
4878
|
hasMore,
|
|
4631
4879
|
isFirstPage
|
|
4632
4880
|
);
|
|
4881
|
+
if (direction === -1) {
|
|
4882
|
+
results.reverse();
|
|
4883
|
+
}
|
|
4633
4884
|
let transformedData;
|
|
4634
4885
|
if (options?.projection && Object.keys(options.projection).length > 0) {
|
|
4635
4886
|
transformedData = results.map((row) => {
|
|
@@ -5205,7 +5456,7 @@ var init_BaseModel = __esm({
|
|
|
5205
5456
|
);
|
|
5206
5457
|
}
|
|
5207
5458
|
for (const [recordId, recordYMap] of documentYMap.entries()) {
|
|
5208
|
-
if (recordYMap instanceof
|
|
5459
|
+
if (recordYMap instanceof Y5.Map) {
|
|
5209
5460
|
const instance = new this({ id: recordId });
|
|
5210
5461
|
instance._metaDocId = docId;
|
|
5211
5462
|
const connectedDoc = modelConstructor.connectedDocuments.get(docId);
|
|
@@ -5230,6 +5481,50 @@ var init_BaseModel = __esm({
|
|
|
5230
5481
|
}
|
|
5231
5482
|
return allInstances;
|
|
5232
5483
|
}
|
|
5484
|
+
/**
|
|
5485
|
+
* Resolve a record by its unique-constraint field values via an engine query.
|
|
5486
|
+
* Used as a fallback when the `_uniqueIdx_<model>_<constraint>` map has no
|
|
5487
|
+
* entry for a key.
|
|
5488
|
+
*
|
|
5489
|
+
* The index map is a cache over the SQLite projection, not the source of
|
|
5490
|
+
* truth: every record is loaded into the projection on `initializeForDocument`
|
|
5491
|
+
* regardless of index presence, but a record written by a client predating
|
|
5492
|
+
* index maintenance (legacy data) is missing from the index. Such a record
|
|
5493
|
+
* silently escapes both `upsertByUnique` lookups and the `save()` uniqueness
|
|
5494
|
+
* check. A query over the constraint fields finds it reliably.
|
|
5495
|
+
*
|
|
5496
|
+
* Contract: RESOLVE ONLY. Returns the owning record (with `_metaDocId` set to
|
|
5497
|
+
* the document that holds it, via `queryOne`) or `null`. Callers decide
|
|
5498
|
+
* whether to heal the missing index entry (write paths) and do their own
|
|
5499
|
+
* logging — this method never mutates the index, so read paths stay
|
|
5500
|
+
* read-only. Mirrors `buildUniqueKey`: a null/undefined value in any
|
|
5501
|
+
* constraint field means the record does not participate in the constraint,
|
|
5502
|
+
* so no query runs.
|
|
5503
|
+
*/
|
|
5504
|
+
static async _resolveByUniqueFallback(constraint, keyValues, options) {
|
|
5505
|
+
if (!_BaseModel.dbInstance) {
|
|
5506
|
+
return null;
|
|
5507
|
+
}
|
|
5508
|
+
const filter = {};
|
|
5509
|
+
for (let i = 0; i < constraint.fields.length; i++) {
|
|
5510
|
+
const value = keyValues[i];
|
|
5511
|
+
if (value === null || value === void 0) {
|
|
5512
|
+
return null;
|
|
5513
|
+
}
|
|
5514
|
+
filter[constraint.fields[i]] = value;
|
|
5515
|
+
}
|
|
5516
|
+
if (options?.excludeId) {
|
|
5517
|
+
if ("id" in filter) {
|
|
5518
|
+
if (filter.id === options.excludeId) {
|
|
5519
|
+
return null;
|
|
5520
|
+
}
|
|
5521
|
+
} else {
|
|
5522
|
+
filter.id = { $ne: options.excludeId };
|
|
5523
|
+
}
|
|
5524
|
+
}
|
|
5525
|
+
const found = await this.queryOne(filter);
|
|
5526
|
+
return found ?? null;
|
|
5527
|
+
}
|
|
5233
5528
|
static async findByUnique(constraintName, value) {
|
|
5234
5529
|
const modelConstructor = this;
|
|
5235
5530
|
const schema = modelConstructor.getSchema();
|
|
@@ -5268,7 +5563,10 @@ var init_BaseModel = __esm({
|
|
|
5268
5563
|
const documentInfo = modelConstructor.connectedDocuments.get(docId);
|
|
5269
5564
|
if (!documentInfo) continue;
|
|
5270
5565
|
const yDoc = documentInfo.yDoc;
|
|
5271
|
-
const constraintMapName2 =
|
|
5566
|
+
const constraintMapName2 = uniqueIndexMapName(
|
|
5567
|
+
currentModelName,
|
|
5568
|
+
constraint.name
|
|
5569
|
+
);
|
|
5272
5570
|
const constraintMap2 = yDoc.getMap(constraintMapName2);
|
|
5273
5571
|
const recordId2 = constraintMap2.get(uniqueKeyString);
|
|
5274
5572
|
if (recordId2) {
|
|
@@ -5276,7 +5574,7 @@ var init_BaseModel = __esm({
|
|
|
5276
5574
|
const documentYMap = modelConstructor.documentYMaps.get(documentYMapKey);
|
|
5277
5575
|
if (documentYMap) {
|
|
5278
5576
|
const recordYMap2 = documentYMap.get(recordId2);
|
|
5279
|
-
if (recordYMap2 && recordYMap2 instanceof
|
|
5577
|
+
if (recordYMap2 && recordYMap2 instanceof Y5.Map) {
|
|
5280
5578
|
const instance = new modelConstructor({
|
|
5281
5579
|
id: recordId2
|
|
5282
5580
|
});
|
|
@@ -5290,6 +5588,16 @@ var init_BaseModel = __esm({
|
|
|
5290
5588
|
}
|
|
5291
5589
|
}
|
|
5292
5590
|
}
|
|
5591
|
+
const fallbackRecord = await modelConstructor._resolveByUniqueFallback(
|
|
5592
|
+
constraint,
|
|
5593
|
+
keyValues
|
|
5594
|
+
);
|
|
5595
|
+
if (fallbackRecord) {
|
|
5596
|
+
Logger.verbose(
|
|
5597
|
+
`[${currentModelName}.findByUnique] Index miss for '${constraintName}' resolved via engine fallback to record ${fallbackRecord.id} (legacy index-less record; index left unchanged on read path).`
|
|
5598
|
+
);
|
|
5599
|
+
return fallbackRecord;
|
|
5600
|
+
}
|
|
5293
5601
|
Logger.verbose(
|
|
5294
5602
|
`[${currentModelName}.findByUnique] Record not found in any connected document`
|
|
5295
5603
|
);
|
|
@@ -5303,17 +5611,30 @@ var init_BaseModel = __esm({
|
|
|
5303
5611
|
`[${currentModelName}] No Y.Doc is connected for this model. Connect a document via initJsBao(...).connectDocument or call initializeForDocument(yDoc, db, docId, permissionHint) before using legacy findByUnique.`
|
|
5304
5612
|
);
|
|
5305
5613
|
}
|
|
5306
|
-
const constraintMapName =
|
|
5614
|
+
const constraintMapName = uniqueIndexMapName(
|
|
5615
|
+
currentModelName,
|
|
5616
|
+
constraint.name
|
|
5617
|
+
);
|
|
5307
5618
|
const constraintMap = legacyDocInfo.yDoc.getMap(constraintMapName);
|
|
5308
5619
|
const recordId = constraintMap.get(uniqueKeyString);
|
|
5309
5620
|
if (!recordId) {
|
|
5621
|
+
const fallbackRecord = await modelConstructor._resolveByUniqueFallback(
|
|
5622
|
+
constraint,
|
|
5623
|
+
keyValues
|
|
5624
|
+
);
|
|
5625
|
+
if (fallbackRecord) {
|
|
5626
|
+
Logger.verbose(
|
|
5627
|
+
`[${currentModelName}.findByUnique] Index miss for '${constraintName}' resolved via engine fallback to record ${fallbackRecord.id} (legacy index-less record; index left unchanged on read path).`
|
|
5628
|
+
);
|
|
5629
|
+
return fallbackRecord;
|
|
5630
|
+
}
|
|
5310
5631
|
return null;
|
|
5311
5632
|
}
|
|
5312
5633
|
const recordYMap = legacyDocumentMap.get(recordId);
|
|
5313
5634
|
if (!recordYMap) {
|
|
5314
5635
|
return null;
|
|
5315
5636
|
}
|
|
5316
|
-
if (recordYMap instanceof
|
|
5637
|
+
if (recordYMap instanceof Y5.Map) {
|
|
5317
5638
|
const instance = new modelConstructor({
|
|
5318
5639
|
id: recordId
|
|
5319
5640
|
});
|
|
@@ -5371,7 +5692,10 @@ var init_BaseModel = __esm({
|
|
|
5371
5692
|
`[${currentModelName}] upsertByUnique for '${constraintName}': unique key cannot be built due to null/undefined values. Upsert cannot proceed reliably.`
|
|
5372
5693
|
);
|
|
5373
5694
|
}
|
|
5374
|
-
const constraintMapName =
|
|
5695
|
+
const constraintMapName = uniqueIndexMapName(
|
|
5696
|
+
currentModelName,
|
|
5697
|
+
constraint.name
|
|
5698
|
+
);
|
|
5375
5699
|
let existingRecord = null;
|
|
5376
5700
|
if (connectedDocuments && connectedDocuments.size > 0) {
|
|
5377
5701
|
for (const docId of connectedDocuments.keys()) {
|
|
@@ -5389,6 +5713,33 @@ var init_BaseModel = __esm({
|
|
|
5389
5713
|
}
|
|
5390
5714
|
} else {
|
|
5391
5715
|
}
|
|
5716
|
+
if (!existingRecord) {
|
|
5717
|
+
const fallbackRecord = await modelConstructor._resolveByUniqueFallback(
|
|
5718
|
+
constraint,
|
|
5719
|
+
keyValuesForLookup
|
|
5720
|
+
);
|
|
5721
|
+
if (fallbackRecord) {
|
|
5722
|
+
existingRecord = fallbackRecord;
|
|
5723
|
+
const healDocId = fallbackRecord._metaDocId;
|
|
5724
|
+
const healDocInfo = healDocId ? connectedDocuments.get(healDocId) : void 0;
|
|
5725
|
+
const canHeal = !!healDocInfo && healDocInfo.permissionHint !== "read";
|
|
5726
|
+
if (healDocInfo && canHeal) {
|
|
5727
|
+
healDocInfo.yDoc.transact(() => {
|
|
5728
|
+
const healMap = healDocInfo.yDoc.getMap(constraintMapName);
|
|
5729
|
+
if (healMap.get(uniqueKeyString) !== fallbackRecord.id) {
|
|
5730
|
+
healMap.set(uniqueKeyString, fallbackRecord.id);
|
|
5731
|
+
}
|
|
5732
|
+
}, `heal-unique-index-${currentModelName}-${healDocId}`);
|
|
5733
|
+
Logger.verbose(
|
|
5734
|
+
`[${currentModelName}] upsertByUnique: index miss for '${constraintName}' resolved via engine fallback to record ${fallbackRecord.id}; healed missing index entry (legacy index-less record).`
|
|
5735
|
+
);
|
|
5736
|
+
} else {
|
|
5737
|
+
Logger.verbose(
|
|
5738
|
+
`[${currentModelName}] upsertByUnique: index miss for '${constraintName}' resolved via engine fallback to record ${fallbackRecord.id}; skipped index heal (owning document is read-only or not connected).`
|
|
5739
|
+
);
|
|
5740
|
+
}
|
|
5741
|
+
}
|
|
5742
|
+
}
|
|
5392
5743
|
if (options?.objectMustExist) {
|
|
5393
5744
|
if (!existingRecord) {
|
|
5394
5745
|
throw new RecordNotFoundError(
|
|
@@ -5545,7 +5896,7 @@ var init_BaseModel = __esm({
|
|
|
5545
5896
|
for (const [fieldKey, fieldOptions] of schema.fields) {
|
|
5546
5897
|
if (fieldOptions?.type !== "stringset") continue;
|
|
5547
5898
|
const value = recordYMap.get(fieldKey);
|
|
5548
|
-
if (value instanceof
|
|
5899
|
+
if (value instanceof Y5.Map) {
|
|
5549
5900
|
this.observeStringSetMapOnce(value);
|
|
5550
5901
|
}
|
|
5551
5902
|
}
|
|
@@ -5730,8 +6081,160 @@ var init_BaseModel = __esm({
|
|
|
5730
6081
|
}
|
|
5731
6082
|
});
|
|
5732
6083
|
|
|
6084
|
+
// src/utils/environment.ts
|
|
6085
|
+
var environment_exports = {};
|
|
6086
|
+
__export(environment_exports, {
|
|
6087
|
+
constants: () => constants,
|
|
6088
|
+
detectEnvironment: () => detectEnvironment,
|
|
6089
|
+
features: () => features,
|
|
6090
|
+
isBrowser: () => isBrowser,
|
|
6091
|
+
isNode: () => isNode,
|
|
6092
|
+
isNodeModuleAvailable: () => isNodeModuleAvailable
|
|
6093
|
+
});
|
|
6094
|
+
function detectEnvironment() {
|
|
6095
|
+
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
6096
|
+
return "node";
|
|
6097
|
+
}
|
|
6098
|
+
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
6099
|
+
return "browser";
|
|
6100
|
+
}
|
|
6101
|
+
if (typeof self !== "undefined" && typeof self.importScripts === "function") {
|
|
6102
|
+
return "browser";
|
|
6103
|
+
}
|
|
6104
|
+
return "unknown";
|
|
6105
|
+
}
|
|
6106
|
+
function isNode() {
|
|
6107
|
+
return detectEnvironment() === "node";
|
|
6108
|
+
}
|
|
6109
|
+
function isBrowser() {
|
|
6110
|
+
return detectEnvironment() === "browser";
|
|
6111
|
+
}
|
|
6112
|
+
async function isNodeModuleAvailable(moduleName) {
|
|
6113
|
+
if (!isNode()) {
|
|
6114
|
+
return false;
|
|
6115
|
+
}
|
|
6116
|
+
try {
|
|
6117
|
+
await import(
|
|
6118
|
+
/* @vite-ignore */
|
|
6119
|
+
moduleName
|
|
6120
|
+
);
|
|
6121
|
+
return true;
|
|
6122
|
+
} catch {
|
|
6123
|
+
return false;
|
|
6124
|
+
}
|
|
6125
|
+
}
|
|
6126
|
+
var features, constants;
|
|
6127
|
+
var init_environment = __esm({
|
|
6128
|
+
"src/utils/environment.ts"() {
|
|
6129
|
+
"use strict";
|
|
6130
|
+
features = {
|
|
6131
|
+
get hasWebWorkers() {
|
|
6132
|
+
return isBrowser() && typeof Worker !== "undefined";
|
|
6133
|
+
},
|
|
6134
|
+
get hasFileSystem() {
|
|
6135
|
+
return isNode();
|
|
6136
|
+
},
|
|
6137
|
+
get hasWebAssembly() {
|
|
6138
|
+
return typeof WebAssembly !== "undefined";
|
|
6139
|
+
},
|
|
6140
|
+
async hasBetterSqlite3() {
|
|
6141
|
+
return await isNodeModuleAvailable("better-sqlite3");
|
|
6142
|
+
}
|
|
6143
|
+
};
|
|
6144
|
+
constants = {
|
|
6145
|
+
DEFAULT_NODE_SQLITE_PATH: ":memory:",
|
|
6146
|
+
DEFAULT_BROWSER_WASM_PATH: "/sql-wasm.wasm"
|
|
6147
|
+
};
|
|
6148
|
+
}
|
|
6149
|
+
});
|
|
6150
|
+
|
|
5733
6151
|
// src/engines/SqljsEngine.ts
|
|
5734
|
-
|
|
6152
|
+
async function resolveNodeWasmPath() {
|
|
6153
|
+
if (!isNode()) {
|
|
6154
|
+
return null;
|
|
6155
|
+
}
|
|
6156
|
+
try {
|
|
6157
|
+
const cjsRequire = typeof require !== "undefined" ? require : void 0;
|
|
6158
|
+
if (cjsRequire) {
|
|
6159
|
+
return cjsRequire.resolve("sql.js/dist/sql-wasm.wasm");
|
|
6160
|
+
}
|
|
6161
|
+
} catch {
|
|
6162
|
+
}
|
|
6163
|
+
try {
|
|
6164
|
+
const metaUrl = import_meta.url;
|
|
6165
|
+
if (metaUrl) {
|
|
6166
|
+
const { createRequire } = await import(
|
|
6167
|
+
/* @vite-ignore */
|
|
6168
|
+
"module"
|
|
6169
|
+
);
|
|
6170
|
+
const req = createRequire(metaUrl);
|
|
6171
|
+
return req.resolve("sql.js/dist/sql-wasm.wasm");
|
|
6172
|
+
}
|
|
6173
|
+
} catch {
|
|
6174
|
+
}
|
|
6175
|
+
return null;
|
|
6176
|
+
}
|
|
6177
|
+
async function preflightNodeWasm(wasmPath) {
|
|
6178
|
+
if (!isNode()) {
|
|
6179
|
+
return;
|
|
6180
|
+
}
|
|
6181
|
+
if (/^[a-z]+:\/\//i.test(wasmPath)) {
|
|
6182
|
+
return;
|
|
6183
|
+
}
|
|
6184
|
+
const { existsSync } = await import(
|
|
6185
|
+
/* @vite-ignore */
|
|
6186
|
+
"fs"
|
|
6187
|
+
);
|
|
6188
|
+
if (!existsSync(wasmPath)) {
|
|
6189
|
+
throw new Error(
|
|
6190
|
+
`[SqljsEngine] sql.js wasm not found at "${wasmPath}". Pass \`locateFile\`/\`wasmURL\` pointing at sql-wasm.wasm, or install \`better-sqlite3\` and use the \`node-sqlite\` engine (see getRecommendedNodeEngine()).`
|
|
6191
|
+
);
|
|
6192
|
+
}
|
|
6193
|
+
}
|
|
6194
|
+
async function loadSqlJsModule(locateFile) {
|
|
6195
|
+
let abortReject;
|
|
6196
|
+
const toError = (reason) => reason instanceof Error ? reason : new Error(
|
|
6197
|
+
`[SqljsEngine] sql.js aborted during initialization: ${String(
|
|
6198
|
+
reason
|
|
6199
|
+
)}`
|
|
6200
|
+
);
|
|
6201
|
+
const nodeProcess = isNode() && typeof process !== "undefined" ? process : void 0;
|
|
6202
|
+
const onUnhandled = (reason) => {
|
|
6203
|
+
const err = toError(reason);
|
|
6204
|
+
if (/Aborted/.test(err.message) || /Aborted/.test(String(reason))) {
|
|
6205
|
+
abortReject?.(err);
|
|
6206
|
+
return;
|
|
6207
|
+
}
|
|
6208
|
+
if (nodeProcess && nodeProcess.listenerCount("unhandledRejection") === 1) {
|
|
6209
|
+
nodeProcess.removeListener("unhandledRejection", onUnhandled);
|
|
6210
|
+
void Promise.reject(reason);
|
|
6211
|
+
}
|
|
6212
|
+
};
|
|
6213
|
+
if (nodeProcess) {
|
|
6214
|
+
nodeProcess.on("unhandledRejection", onUnhandled);
|
|
6215
|
+
}
|
|
6216
|
+
const abortGuard = new Promise((_resolve, reject) => {
|
|
6217
|
+
abortReject = reject;
|
|
6218
|
+
});
|
|
6219
|
+
abortGuard.catch(() => {
|
|
6220
|
+
});
|
|
6221
|
+
try {
|
|
6222
|
+
const initPromise = (0, import_sql4.default)({
|
|
6223
|
+
locateFile,
|
|
6224
|
+
// Layer 1: emscripten onAbort.
|
|
6225
|
+
onAbort: (reason) => abortReject?.(toError(reason))
|
|
6226
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6227
|
+
});
|
|
6228
|
+
return await Promise.race([initPromise, abortGuard]);
|
|
6229
|
+
} finally {
|
|
6230
|
+
if (nodeProcess) {
|
|
6231
|
+
setTimeout(() => {
|
|
6232
|
+
nodeProcess.removeListener("unhandledRejection", onUnhandled);
|
|
6233
|
+
}, 0);
|
|
6234
|
+
}
|
|
6235
|
+
}
|
|
6236
|
+
}
|
|
6237
|
+
var import_sql4, import_async_mutex, import_meta, SQL_WASM_URL, SQL_WASM_FILENAME, TransactionalSQLJSOperations, SqljsEngine;
|
|
5735
6238
|
var init_SqljsEngine = __esm({
|
|
5736
6239
|
"src/engines/SqljsEngine.ts"() {
|
|
5737
6240
|
"use strict";
|
|
@@ -5739,7 +6242,10 @@ var init_SqljsEngine = __esm({
|
|
|
5739
6242
|
init_BaseModel();
|
|
5740
6243
|
import_async_mutex = require("async-mutex");
|
|
5741
6244
|
init_sql();
|
|
6245
|
+
init_environment();
|
|
6246
|
+
import_meta = {};
|
|
5742
6247
|
SQL_WASM_URL = "/sql-wasm.wasm";
|
|
6248
|
+
SQL_WASM_FILENAME = "sql-wasm.wasm";
|
|
5743
6249
|
TransactionalSQLJSOperations = class {
|
|
5744
6250
|
db;
|
|
5745
6251
|
engine;
|
|
@@ -5805,22 +6311,37 @@ var init_SqljsEngine = __esm({
|
|
|
5805
6311
|
}
|
|
5806
6312
|
async initialize(engineOptions) {
|
|
5807
6313
|
Logger.info("[SqljsEngine] Initializing SQL.js engine...");
|
|
6314
|
+
const loadingModuleThisCall = !_SqljsEngine.SQL;
|
|
5808
6315
|
try {
|
|
5809
6316
|
if (!_SqljsEngine.SQL) {
|
|
5810
|
-
|
|
6317
|
+
let locateFileConfig;
|
|
6318
|
+
if (engineOptions?.locateFile) {
|
|
6319
|
+
locateFileConfig = engineOptions.locateFile;
|
|
6320
|
+
} else if (engineOptions?.wasmURL) {
|
|
6321
|
+
const url = engineOptions.wasmURL;
|
|
6322
|
+
locateFileConfig = (_file) => url;
|
|
6323
|
+
} else {
|
|
6324
|
+
const nodeWasmPath = await resolveNodeWasmPath();
|
|
6325
|
+
const resolved = nodeWasmPath ?? SQL_WASM_URL;
|
|
6326
|
+
locateFileConfig = (_file) => resolved;
|
|
6327
|
+
}
|
|
6328
|
+
const wasmPath = locateFileConfig(SQL_WASM_FILENAME);
|
|
5811
6329
|
Logger.debug(
|
|
5812
6330
|
"[SqljsEngine] Attempting to load SQL.js WASM from:",
|
|
5813
|
-
|
|
6331
|
+
wasmPath
|
|
5814
6332
|
);
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
6333
|
+
await preflightNodeWasm(wasmPath);
|
|
6334
|
+
const SQL = await loadSqlJsModule(locateFileConfig);
|
|
6335
|
+
_SqljsEngine.SQL = SQL;
|
|
5818
6336
|
Logger.info("[SqljsEngine] SQL.js WASM loaded successfully.");
|
|
5819
6337
|
}
|
|
5820
6338
|
this.db = new _SqljsEngine.SQL.Database();
|
|
5821
6339
|
Logger.info("[SqljsEngine] SQL.js Database initialized in memory.");
|
|
5822
6340
|
this.updateTableNames();
|
|
5823
6341
|
} catch (error) {
|
|
6342
|
+
if (loadingModuleThisCall) {
|
|
6343
|
+
_SqljsEngine.SQL = null;
|
|
6344
|
+
}
|
|
5824
6345
|
Logger.error("[SqljsEngine] Error during SQL.js initialization:", error);
|
|
5825
6346
|
throw error;
|
|
5826
6347
|
}
|
|
@@ -6108,73 +6629,6 @@ var init_SqljsEngine = __esm({
|
|
|
6108
6629
|
}
|
|
6109
6630
|
});
|
|
6110
6631
|
|
|
6111
|
-
// src/utils/environment.ts
|
|
6112
|
-
var environment_exports = {};
|
|
6113
|
-
__export(environment_exports, {
|
|
6114
|
-
constants: () => constants,
|
|
6115
|
-
detectEnvironment: () => detectEnvironment,
|
|
6116
|
-
features: () => features,
|
|
6117
|
-
isBrowser: () => isBrowser,
|
|
6118
|
-
isNode: () => isNode,
|
|
6119
|
-
isNodeModuleAvailable: () => isNodeModuleAvailable
|
|
6120
|
-
});
|
|
6121
|
-
function detectEnvironment() {
|
|
6122
|
-
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
6123
|
-
return "node";
|
|
6124
|
-
}
|
|
6125
|
-
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
6126
|
-
return "browser";
|
|
6127
|
-
}
|
|
6128
|
-
if (typeof self !== "undefined" && typeof self.importScripts === "function") {
|
|
6129
|
-
return "browser";
|
|
6130
|
-
}
|
|
6131
|
-
return "unknown";
|
|
6132
|
-
}
|
|
6133
|
-
function isNode() {
|
|
6134
|
-
return detectEnvironment() === "node";
|
|
6135
|
-
}
|
|
6136
|
-
function isBrowser() {
|
|
6137
|
-
return detectEnvironment() === "browser";
|
|
6138
|
-
}
|
|
6139
|
-
async function isNodeModuleAvailable(moduleName) {
|
|
6140
|
-
if (!isNode()) {
|
|
6141
|
-
return false;
|
|
6142
|
-
}
|
|
6143
|
-
try {
|
|
6144
|
-
await import(
|
|
6145
|
-
/* @vite-ignore */
|
|
6146
|
-
moduleName
|
|
6147
|
-
);
|
|
6148
|
-
return true;
|
|
6149
|
-
} catch {
|
|
6150
|
-
return false;
|
|
6151
|
-
}
|
|
6152
|
-
}
|
|
6153
|
-
var features, constants;
|
|
6154
|
-
var init_environment = __esm({
|
|
6155
|
-
"src/utils/environment.ts"() {
|
|
6156
|
-
"use strict";
|
|
6157
|
-
features = {
|
|
6158
|
-
get hasWebWorkers() {
|
|
6159
|
-
return isBrowser() && typeof Worker !== "undefined";
|
|
6160
|
-
},
|
|
6161
|
-
get hasFileSystem() {
|
|
6162
|
-
return isNode();
|
|
6163
|
-
},
|
|
6164
|
-
get hasWebAssembly() {
|
|
6165
|
-
return typeof WebAssembly !== "undefined";
|
|
6166
|
-
},
|
|
6167
|
-
async hasBetterSqlite3() {
|
|
6168
|
-
return await isNodeModuleAvailable("better-sqlite3");
|
|
6169
|
-
}
|
|
6170
|
-
};
|
|
6171
|
-
constants = {
|
|
6172
|
-
DEFAULT_NODE_SQLITE_PATH: ":memory:",
|
|
6173
|
-
DEFAULT_BROWSER_WASM_PATH: "/sql-wasm.wasm"
|
|
6174
|
-
};
|
|
6175
|
-
}
|
|
6176
|
-
});
|
|
6177
|
-
|
|
6178
6632
|
// src/engines/node/NodeSqliteEngine.ts
|
|
6179
6633
|
var NodeSqliteEngine_exports = {};
|
|
6180
6634
|
__export(NodeSqliteEngine_exports, {
|
|
@@ -6866,33 +7320,47 @@ __export(node_exports, {
|
|
|
6866
7320
|
SqljsEngine: () => SqljsEngine,
|
|
6867
7321
|
StringSet: () => StringSet,
|
|
6868
7322
|
UniqueConstraintViolationError: () => UniqueConstraintViolationError,
|
|
7323
|
+
applyAutoStampsFromSchema: () => applyAutoStampsFromSchema,
|
|
7324
|
+
applyDefaultsFromSchema: () => applyDefaultsFromSchema,
|
|
7325
|
+
applyStringSetChange: () => applyStringSetChange,
|
|
7326
|
+
applyStringSetDelta: () => applyStringSetDelta,
|
|
7327
|
+
assertNever: () => assertNever,
|
|
6869
7328
|
attachAndRegisterModel: () => attachAndRegisterModel,
|
|
6870
7329
|
attachSchemaToClass: () => attachSchemaToClass,
|
|
6871
7330
|
autoRegisterModel: () => autoRegisterModel,
|
|
6872
7331
|
clearMetaSyncCache: () => clearMetaSyncCache,
|
|
6873
7332
|
constants: () => constants,
|
|
6874
7333
|
createModelClass: () => createModelClass,
|
|
7334
|
+
decodeFunctionDefault: () => decodeFunctionDefault,
|
|
6875
7335
|
defineModelSchema: () => defineModelSchema,
|
|
6876
7336
|
detectEnvironment: () => detectEnvironment,
|
|
6877
7337
|
discoverModelNames: () => discoverModelNames,
|
|
6878
7338
|
discoverSchema: () => discoverSchema,
|
|
6879
7339
|
dumpYDocToPlain: () => dumpYDocToPlain,
|
|
7340
|
+
ensureStringSetYMap: () => ensureStringSetYMap,
|
|
6880
7341
|
features: () => features,
|
|
7342
|
+
fieldWriteKind: () => fieldWriteKind,
|
|
6881
7343
|
generateULID: () => generateULID,
|
|
6882
7344
|
getRecommendedNodeEngine: () => getRecommendedNodeEngine,
|
|
6883
7345
|
inferFieldType: () => inferFieldType,
|
|
6884
7346
|
initJsBao: () => initJsBao,
|
|
6885
7347
|
isBrowser: () => isBrowser,
|
|
7348
|
+
isKnownFieldType: () => isKnownFieldType,
|
|
6886
7349
|
isNode: () => isNode,
|
|
6887
7350
|
isNodeModuleAvailable: () => isNodeModuleAvailable,
|
|
6888
7351
|
loadSchemaFromToml: () => loadSchemaFromToml,
|
|
6889
7352
|
loadSchemaFromTomlString: () => loadSchemaFromTomlString,
|
|
7353
|
+
parseStringSetOp: () => parseStringSetOp,
|
|
6890
7354
|
registerFunctionDefault: () => registerFunctionDefault,
|
|
7355
|
+
registerFunctionDefaultGenerator: () => registerFunctionDefaultGenerator,
|
|
7356
|
+
replaceStringSet: () => replaceStringSet,
|
|
6891
7357
|
resetJsBao: () => resetJsBao,
|
|
7358
|
+
resolveDefaultValue: () => resolveDefaultValue,
|
|
6892
7359
|
schemaToToml: () => schemaToToml,
|
|
6893
7360
|
summarizePlainYDoc: () => summarizePlainYDoc,
|
|
6894
7361
|
syncInferredMeta: () => syncInferredMeta,
|
|
6895
|
-
syncModelMeta: () => syncModelMeta
|
|
7362
|
+
syncModelMeta: () => syncModelMeta,
|
|
7363
|
+
writeField: () => writeField
|
|
6896
7364
|
});
|
|
6897
7365
|
module.exports = __toCommonJS(node_exports);
|
|
6898
7366
|
init_BaseModel();
|
|
@@ -7159,6 +7627,7 @@ init_StringSet();
|
|
|
7159
7627
|
// src/models/schema.ts
|
|
7160
7628
|
init_BaseModel();
|
|
7161
7629
|
init_ModelRegistry();
|
|
7630
|
+
init_uniqueIndex();
|
|
7162
7631
|
function defineModelSchema(input) {
|
|
7163
7632
|
const { name, fields } = input;
|
|
7164
7633
|
const options = {
|
|
@@ -7231,7 +7700,7 @@ function resolveUniqueConstraints(modelName, fields, customConstraints) {
|
|
|
7231
7700
|
for (const [fieldName, options] of fields.entries()) {
|
|
7232
7701
|
if (options.unique) {
|
|
7233
7702
|
resolved.push({
|
|
7234
|
-
name:
|
|
7703
|
+
name: fieldUniqueConstraintName(modelName, fieldName),
|
|
7235
7704
|
fields: [fieldName]
|
|
7236
7705
|
});
|
|
7237
7706
|
}
|
|
@@ -7295,7 +7764,7 @@ function attachAndRegisterModel(modelClass, schema) {
|
|
|
7295
7764
|
}
|
|
7296
7765
|
|
|
7297
7766
|
// src/utils/yDocSchema.ts
|
|
7298
|
-
var
|
|
7767
|
+
var Y6 = __toESM(require("yjs"), 1);
|
|
7299
7768
|
init_yjsValues();
|
|
7300
7769
|
function discoverSchema(yDoc) {
|
|
7301
7770
|
const models = {};
|
|
@@ -7330,7 +7799,7 @@ function discoverModelNames(yDoc) {
|
|
|
7330
7799
|
function materializeMap(yDoc, key) {
|
|
7331
7800
|
try {
|
|
7332
7801
|
const map = yDoc.getMap(key);
|
|
7333
|
-
return map instanceof
|
|
7802
|
+
return map instanceof Y6.Map ? map : null;
|
|
7334
7803
|
} catch {
|
|
7335
7804
|
return null;
|
|
7336
7805
|
}
|
|
@@ -7340,11 +7809,11 @@ function readModelMeta(metaMap) {
|
|
|
7340
7809
|
let constraints;
|
|
7341
7810
|
let relationships;
|
|
7342
7811
|
for (const [key, value] of metaMap.entries()) {
|
|
7343
|
-
if (key === "_constraints" && value instanceof
|
|
7812
|
+
if (key === "_constraints" && value instanceof Y6.Map) {
|
|
7344
7813
|
constraints = readConstraints(value);
|
|
7345
|
-
} else if (key === "_relationships" && value instanceof
|
|
7814
|
+
} else if (key === "_relationships" && value instanceof Y6.Map) {
|
|
7346
7815
|
relationships = readRelationships(value);
|
|
7347
|
-
} else if (value instanceof
|
|
7816
|
+
} else if (value instanceof Y6.Map) {
|
|
7348
7817
|
fields[key] = readFieldMeta(value);
|
|
7349
7818
|
}
|
|
7350
7819
|
}
|
|
@@ -7379,7 +7848,7 @@ function inferModelFromData(dataMap) {
|
|
|
7379
7848
|
const fields = {};
|
|
7380
7849
|
let sampled = 0;
|
|
7381
7850
|
for (const [_recordId, recordValue] of dataMap.entries()) {
|
|
7382
|
-
if (!(recordValue instanceof
|
|
7851
|
+
if (!(recordValue instanceof Y6.Map)) continue;
|
|
7383
7852
|
if (++sampled > 5) break;
|
|
7384
7853
|
for (const [fieldName, value] of recordValue.entries()) {
|
|
7385
7854
|
if (fieldName.startsWith("_")) continue;
|
|
@@ -7407,7 +7876,7 @@ function inferTypeFromValue(value) {
|
|
|
7407
7876
|
function readConstraints(constraintsMap) {
|
|
7408
7877
|
const out = {};
|
|
7409
7878
|
for (const [name, value] of constraintsMap.entries()) {
|
|
7410
|
-
if (!(value instanceof
|
|
7879
|
+
if (!(value instanceof Y6.Map)) continue;
|
|
7411
7880
|
let fields = [];
|
|
7412
7881
|
const rawFields = value.get("fields");
|
|
7413
7882
|
if (typeof rawFields === "string") {
|
|
@@ -7426,7 +7895,7 @@ function readConstraints(constraintsMap) {
|
|
|
7426
7895
|
function readRelationships(relsMap) {
|
|
7427
7896
|
const out = {};
|
|
7428
7897
|
for (const [name, value] of relsMap.entries()) {
|
|
7429
|
-
if (!(value instanceof
|
|
7898
|
+
if (!(value instanceof Y6.Map)) continue;
|
|
7430
7899
|
const rel = {};
|
|
7431
7900
|
for (const [k, v] of value.entries()) {
|
|
7432
7901
|
rel[k] = v;
|
|
@@ -7722,18 +8191,19 @@ async function loadSchemaFromToml(filePath, options = {}) {
|
|
|
7722
8191
|
|
|
7723
8192
|
// src/node.ts
|
|
7724
8193
|
init_metaSync();
|
|
8194
|
+
init_writeLifecycle();
|
|
7725
8195
|
|
|
7726
8196
|
// src/utils/yDocDump.ts
|
|
7727
|
-
var
|
|
8197
|
+
var Y7 = __toESM(require("yjs"), 1);
|
|
7728
8198
|
function toPlain(value) {
|
|
7729
|
-
if (value instanceof
|
|
8199
|
+
if (value instanceof Y7.Map) {
|
|
7730
8200
|
const obj = {};
|
|
7731
8201
|
value.forEach((v, k) => {
|
|
7732
8202
|
obj[k] = toPlain(v);
|
|
7733
8203
|
});
|
|
7734
8204
|
return obj;
|
|
7735
8205
|
}
|
|
7736
|
-
if (value instanceof
|
|
8206
|
+
if (value instanceof Y7.Array) {
|
|
7737
8207
|
return value.toArray().map((item) => toPlain(item));
|
|
7738
8208
|
}
|
|
7739
8209
|
return value;
|
|
@@ -7742,7 +8212,7 @@ function dumpYDocToPlain(yDoc, options = {}) {
|
|
|
7742
8212
|
const result = {};
|
|
7743
8213
|
const includeIndexes = !!options.includeIndexes;
|
|
7744
8214
|
yDoc.share.forEach((type, name) => {
|
|
7745
|
-
if (!(type instanceof
|
|
8215
|
+
if (!(type instanceof Y7.Map)) return;
|
|
7746
8216
|
if (!includeIndexes && name.startsWith("_uniqueIdx_")) return;
|
|
7747
8217
|
const records = {};
|
|
7748
8218
|
type.forEach((recordValue, recordId) => {
|
|
@@ -7803,31 +8273,45 @@ async function getRecommendedNodeEngine() {
|
|
|
7803
8273
|
SqljsEngine,
|
|
7804
8274
|
StringSet,
|
|
7805
8275
|
UniqueConstraintViolationError,
|
|
8276
|
+
applyAutoStampsFromSchema,
|
|
8277
|
+
applyDefaultsFromSchema,
|
|
8278
|
+
applyStringSetChange,
|
|
8279
|
+
applyStringSetDelta,
|
|
8280
|
+
assertNever,
|
|
7806
8281
|
attachAndRegisterModel,
|
|
7807
8282
|
attachSchemaToClass,
|
|
7808
8283
|
autoRegisterModel,
|
|
7809
8284
|
clearMetaSyncCache,
|
|
7810
8285
|
constants,
|
|
7811
8286
|
createModelClass,
|
|
8287
|
+
decodeFunctionDefault,
|
|
7812
8288
|
defineModelSchema,
|
|
7813
8289
|
detectEnvironment,
|
|
7814
8290
|
discoverModelNames,
|
|
7815
8291
|
discoverSchema,
|
|
7816
8292
|
dumpYDocToPlain,
|
|
8293
|
+
ensureStringSetYMap,
|
|
7817
8294
|
features,
|
|
8295
|
+
fieldWriteKind,
|
|
7818
8296
|
generateULID,
|
|
7819
8297
|
getRecommendedNodeEngine,
|
|
7820
8298
|
inferFieldType,
|
|
7821
8299
|
initJsBao,
|
|
7822
8300
|
isBrowser,
|
|
8301
|
+
isKnownFieldType,
|
|
7823
8302
|
isNode,
|
|
7824
8303
|
isNodeModuleAvailable,
|
|
7825
8304
|
loadSchemaFromToml,
|
|
7826
8305
|
loadSchemaFromTomlString,
|
|
8306
|
+
parseStringSetOp,
|
|
7827
8307
|
registerFunctionDefault,
|
|
8308
|
+
registerFunctionDefaultGenerator,
|
|
8309
|
+
replaceStringSet,
|
|
7828
8310
|
resetJsBao,
|
|
8311
|
+
resolveDefaultValue,
|
|
7829
8312
|
schemaToToml,
|
|
7830
8313
|
summarizePlainYDoc,
|
|
7831
8314
|
syncInferredMeta,
|
|
7832
|
-
syncModelMeta
|
|
8315
|
+
syncModelMeta,
|
|
8316
|
+
writeField
|
|
7833
8317
|
});
|