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.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
3
9
|
var __esm = (fn, res) => function __init() {
|
|
4
10
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
11
|
};
|
|
@@ -344,21 +350,36 @@ var init_CursorManager = __esm({
|
|
|
344
350
|
return fields;
|
|
345
351
|
}
|
|
346
352
|
/**
|
|
347
|
-
* Build ORDER BY clause from sort specification
|
|
353
|
+
* Build ORDER BY clause from sort specification.
|
|
354
|
+
*
|
|
355
|
+
* `direction` is the pagination direction (1 = forward, -1 = backward).
|
|
356
|
+
* For backward pagination each field's effective ORDER BY direction is
|
|
357
|
+
* reversed so the cursor's flipped inequality (built by
|
|
358
|
+
* `buildPaginationConditions`) returns the page adjacent to the cursor,
|
|
359
|
+
* not the globally smallest/largest window. Without this,
|
|
360
|
+
* `field < cursor ... ORDER BY field ASC LIMIT n` returns the n smallest
|
|
361
|
+
* rows overall instead of the n rows just below the cursor.
|
|
362
|
+
*
|
|
363
|
+
* The returned `directions` array carries the *declared* per-field sort
|
|
364
|
+
* directions (unaffected by `direction`) — `buildPaginationConditions`
|
|
365
|
+
* needs the declared directions to pick each field's comparison operator.
|
|
348
366
|
*/
|
|
349
|
-
static buildOrderClause(sort, fieldFormatter = (field) => field) {
|
|
367
|
+
static buildOrderClause(sort, fieldFormatter = (field) => field, direction = 1) {
|
|
350
368
|
const fields = this.extractSortFields(sort);
|
|
351
369
|
const clauses = [];
|
|
352
370
|
const directions = [];
|
|
371
|
+
const sqlDir = (declared) => {
|
|
372
|
+
const effective = direction === -1 ? declared === 1 ? -1 : 1 : declared;
|
|
373
|
+
return effective === 1 ? "ASC" : "DESC";
|
|
374
|
+
};
|
|
353
375
|
if (sort && Object.keys(sort).length > 0) {
|
|
354
376
|
for (const [field, dir] of Object.entries(sort)) {
|
|
355
|
-
|
|
356
|
-
clauses.push(`${fieldFormatter(field)} ${sqlDirection}`);
|
|
377
|
+
clauses.push(`${fieldFormatter(field)} ${sqlDir(dir)}`);
|
|
357
378
|
directions.push(dir);
|
|
358
379
|
}
|
|
359
380
|
}
|
|
360
381
|
if (!sort || !sort.hasOwnProperty("id")) {
|
|
361
|
-
clauses.push(`${fieldFormatter("id")}
|
|
382
|
+
clauses.push(`${fieldFormatter("id")} ${sqlDir(1)}`);
|
|
362
383
|
directions.push(1);
|
|
363
384
|
} else if (sort && sort.hasOwnProperty("id")) {
|
|
364
385
|
directions.push(sort["id"]);
|
|
@@ -381,18 +402,27 @@ var init_CursorManager = __esm({
|
|
|
381
402
|
/**
|
|
382
403
|
* Generate next and previous cursors from result set
|
|
383
404
|
*/
|
|
384
|
-
static generateResultCursors(results, sortFields,
|
|
405
|
+
static generateResultCursors(results, sortFields, requestedDirection, hasMore, isFirstPage = false) {
|
|
385
406
|
if (results.length === 0) {
|
|
386
407
|
return {};
|
|
387
408
|
}
|
|
388
409
|
const cursors = {};
|
|
389
410
|
if (hasMore && results.length > 0) {
|
|
390
411
|
const lastResult = results[results.length - 1];
|
|
391
|
-
cursors.nextCursor = this.generateCursor(
|
|
412
|
+
cursors.nextCursor = this.generateCursor(
|
|
413
|
+
lastResult,
|
|
414
|
+
sortFields,
|
|
415
|
+
requestedDirection
|
|
416
|
+
);
|
|
392
417
|
}
|
|
393
418
|
if (results.length > 0 && !isFirstPage) {
|
|
394
419
|
const firstResult = results[0];
|
|
395
|
-
|
|
420
|
+
const opposite = requestedDirection === 1 ? -1 : 1;
|
|
421
|
+
cursors.prevCursor = this.generateCursor(
|
|
422
|
+
firstResult,
|
|
423
|
+
sortFields,
|
|
424
|
+
opposite
|
|
425
|
+
);
|
|
396
426
|
}
|
|
397
427
|
return cursors;
|
|
398
428
|
}
|
|
@@ -525,7 +555,8 @@ var init_DocumentQueryTranslator = __esm({
|
|
|
525
555
|
const whereClause = this.translateFilter(filter);
|
|
526
556
|
const orderClause = CursorManager.buildOrderClause(
|
|
527
557
|
options?.sort,
|
|
528
|
-
(field) => this.getQuotedField(field)
|
|
558
|
+
(field) => this.getQuotedField(field),
|
|
559
|
+
options?.direction || 1
|
|
529
560
|
);
|
|
530
561
|
const limitClause = this.buildLimitClause(options);
|
|
531
562
|
const paginationClause = this.buildPaginationClause(
|
|
@@ -1197,8 +1228,206 @@ var init_yjsValues = __esm({
|
|
|
1197
1228
|
}
|
|
1198
1229
|
});
|
|
1199
1230
|
|
|
1200
|
-
// src/models/
|
|
1231
|
+
// src/models/writeLifecycle.ts
|
|
1201
1232
|
import * as Y2 from "yjs";
|
|
1233
|
+
import { ulid } from "ulid";
|
|
1234
|
+
function assertNever(x) {
|
|
1235
|
+
throw new Error(`Unhandled field type: ${String(x)}`);
|
|
1236
|
+
}
|
|
1237
|
+
function fieldWriteKind(type) {
|
|
1238
|
+
switch (type) {
|
|
1239
|
+
case "string":
|
|
1240
|
+
case "number":
|
|
1241
|
+
case "boolean":
|
|
1242
|
+
case "date":
|
|
1243
|
+
case "id":
|
|
1244
|
+
return "scalar";
|
|
1245
|
+
case "stringset":
|
|
1246
|
+
return "stringset";
|
|
1247
|
+
default:
|
|
1248
|
+
return assertNever(type);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
function isKnownFieldType(type) {
|
|
1252
|
+
return KNOWN_FIELD_TYPES.has(type);
|
|
1253
|
+
}
|
|
1254
|
+
function ensureStringSetYMap(rm, fieldName) {
|
|
1255
|
+
const nested = rm.get(fieldName);
|
|
1256
|
+
if (nested instanceof Y2.Map) return nested;
|
|
1257
|
+
const fresh = new Y2.Map();
|
|
1258
|
+
if (nested && typeof nested === "object") {
|
|
1259
|
+
for (const [member, marker] of Object.entries(
|
|
1260
|
+
nested
|
|
1261
|
+
)) {
|
|
1262
|
+
if (Boolean(marker)) fresh.set(member, true);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
rm.set(fieldName, fresh);
|
|
1266
|
+
return fresh;
|
|
1267
|
+
}
|
|
1268
|
+
function applyStringSetDelta(target, delta) {
|
|
1269
|
+
if (delta.clear) {
|
|
1270
|
+
for (const member of Array.from(target.keys())) target.delete(member);
|
|
1271
|
+
}
|
|
1272
|
+
if (delta.remove) {
|
|
1273
|
+
for (const member of delta.remove) target.delete(String(member));
|
|
1274
|
+
}
|
|
1275
|
+
if (delta.add) {
|
|
1276
|
+
for (const member of delta.add) {
|
|
1277
|
+
const key = String(member);
|
|
1278
|
+
if (target.get(key) !== true) target.set(key, true);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
function replaceStringSet(rm, fieldName, members) {
|
|
1283
|
+
const target = ensureStringSetYMap(rm, fieldName);
|
|
1284
|
+
const desired = /* @__PURE__ */ new Set();
|
|
1285
|
+
for (const member of members) desired.add(String(member));
|
|
1286
|
+
for (const existing of Array.from(target.keys())) {
|
|
1287
|
+
if (!desired.has(existing)) target.delete(existing);
|
|
1288
|
+
}
|
|
1289
|
+
for (const member of desired) {
|
|
1290
|
+
if (target.get(member) !== true) target.set(member, true);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
function applyStringSetChange(recordYMap, fieldName, change) {
|
|
1294
|
+
const target = ensureStringSetYMap(recordYMap, fieldName);
|
|
1295
|
+
applyStringSetDelta(target, {
|
|
1296
|
+
add: change.additions,
|
|
1297
|
+
remove: change.removals
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
function parseStringSetOp(value) {
|
|
1301
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Y2.AbstractType) {
|
|
1302
|
+
return null;
|
|
1303
|
+
}
|
|
1304
|
+
const keys = Object.keys(value);
|
|
1305
|
+
const opKeys = keys.filter((k) => k.startsWith("$"));
|
|
1306
|
+
if (opKeys.length === 0) return null;
|
|
1307
|
+
const known = /* @__PURE__ */ new Set(["$add", "$remove", "$clear"]);
|
|
1308
|
+
const unknown = keys.filter((k) => !known.has(k));
|
|
1309
|
+
if (unknown.length > 0) {
|
|
1310
|
+
throw new Error(
|
|
1311
|
+
`Invalid stringset op: unexpected key(s) [${unknown.join(", ")}]. Only $add, $remove and $clear are supported.`
|
|
1312
|
+
);
|
|
1313
|
+
}
|
|
1314
|
+
const obj = value;
|
|
1315
|
+
const toMembers = (raw, opName) => {
|
|
1316
|
+
if (raw === void 0) return [];
|
|
1317
|
+
if (!Array.isArray(raw)) {
|
|
1318
|
+
throw new Error(`Invalid stringset op: ${opName} must be an array.`);
|
|
1319
|
+
}
|
|
1320
|
+
return raw.map((m) => String(m));
|
|
1321
|
+
};
|
|
1322
|
+
return {
|
|
1323
|
+
add: toMembers(obj.$add, "$add"),
|
|
1324
|
+
remove: toMembers(obj.$remove, "$remove"),
|
|
1325
|
+
clear: obj.$clear === true
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
function writeField(rm, declaredType, key, value, modelName) {
|
|
1329
|
+
const kind = declaredType && isKnownFieldType(declaredType) ? fieldWriteKind(declaredType) : "scalar";
|
|
1330
|
+
if (Array.isArray(value)) {
|
|
1331
|
+
if (kind !== "stringset") {
|
|
1332
|
+
throw new Error(
|
|
1333
|
+
`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.`
|
|
1334
|
+
);
|
|
1335
|
+
}
|
|
1336
|
+
replaceStringSet(rm, key, value);
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
const op = parseStringSetOp(value);
|
|
1340
|
+
if (op) {
|
|
1341
|
+
if (kind !== "stringset") {
|
|
1342
|
+
throw new Error(
|
|
1343
|
+
`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}).`
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1346
|
+
applyStringSetDelta(ensureStringSetYMap(rm, key), op);
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
if (kind === "stringset") {
|
|
1350
|
+
throw new Error(
|
|
1351
|
+
`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}.`
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1354
|
+
rm.set(key, value);
|
|
1355
|
+
}
|
|
1356
|
+
function registerFunctionDefaultGenerator(name, fn) {
|
|
1357
|
+
FUNCTION_DEFAULT_GENERATORS.set(name, fn);
|
|
1358
|
+
}
|
|
1359
|
+
function decodeFunctionDefault(name) {
|
|
1360
|
+
return FUNCTION_DEFAULT_GENERATORS.get(name);
|
|
1361
|
+
}
|
|
1362
|
+
function resolveLiteralOrFunctionDefault(rawDefault) {
|
|
1363
|
+
return typeof rawDefault === "function" ? rawDefault() : rawDefault;
|
|
1364
|
+
}
|
|
1365
|
+
function resolveDefaultValue(rawDefault, opts = {}) {
|
|
1366
|
+
if (typeof rawDefault === "function") return rawDefault();
|
|
1367
|
+
if (typeof rawDefault === "string" && rawDefault.startsWith("$")) {
|
|
1368
|
+
if (rawDefault.startsWith("$$")) return rawDefault.slice(1);
|
|
1369
|
+
const name = rawDefault.slice(1);
|
|
1370
|
+
const gen = opts.decode?.(name) ?? decodeFunctionDefault(name);
|
|
1371
|
+
if (!gen) {
|
|
1372
|
+
throw new Error(
|
|
1373
|
+
`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.`
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
return gen();
|
|
1377
|
+
}
|
|
1378
|
+
return rawDefault;
|
|
1379
|
+
}
|
|
1380
|
+
function applyDefaultsFromSchema(fields, data, opts = {}) {
|
|
1381
|
+
for (const [fieldName, field] of Object.entries(fields)) {
|
|
1382
|
+
if (fieldName === "id") continue;
|
|
1383
|
+
if (!field || field.default === void 0) continue;
|
|
1384
|
+
if (field.default === UNKNOWN_FUNCTION_DEFAULT) {
|
|
1385
|
+
continue;
|
|
1386
|
+
}
|
|
1387
|
+
if (Object.prototype.hasOwnProperty.call(data, fieldName) && data[fieldName] !== void 0) {
|
|
1388
|
+
continue;
|
|
1389
|
+
}
|
|
1390
|
+
data[fieldName] = resolveDefaultValue(field.default, {
|
|
1391
|
+
fieldName,
|
|
1392
|
+
modelName: opts.modelName,
|
|
1393
|
+
decode: opts.decodeFunctionDefault
|
|
1394
|
+
});
|
|
1395
|
+
}
|
|
1396
|
+
return data;
|
|
1397
|
+
}
|
|
1398
|
+
function applyAutoStampsFromSchema(fields, data, opts) {
|
|
1399
|
+
const { isNew, now } = opts;
|
|
1400
|
+
for (const [fieldName, field] of Object.entries(fields)) {
|
|
1401
|
+
const stamp = field?.autoStamp;
|
|
1402
|
+
if (!stamp) continue;
|
|
1403
|
+
const explicit = Object.prototype.hasOwnProperty.call(data, fieldName) && data[fieldName] !== null && data[fieldName] !== void 0;
|
|
1404
|
+
if (explicit) continue;
|
|
1405
|
+
if (stamp === "create" && !isNew) continue;
|
|
1406
|
+
data[fieldName] = now;
|
|
1407
|
+
}
|
|
1408
|
+
return data;
|
|
1409
|
+
}
|
|
1410
|
+
var KNOWN_FIELD_TYPE_MAP, KNOWN_FIELD_TYPES, FUNCTION_DEFAULT_GENERATORS, UNKNOWN_FUNCTION_DEFAULT;
|
|
1411
|
+
var init_writeLifecycle = __esm({
|
|
1412
|
+
"src/models/writeLifecycle.ts"() {
|
|
1413
|
+
"use strict";
|
|
1414
|
+
KNOWN_FIELD_TYPE_MAP = {
|
|
1415
|
+
string: true,
|
|
1416
|
+
number: true,
|
|
1417
|
+
boolean: true,
|
|
1418
|
+
date: true,
|
|
1419
|
+
id: true,
|
|
1420
|
+
stringset: true
|
|
1421
|
+
};
|
|
1422
|
+
KNOWN_FIELD_TYPES = new Set(Object.keys(KNOWN_FIELD_TYPE_MAP));
|
|
1423
|
+
FUNCTION_DEFAULT_GENERATORS = /* @__PURE__ */ new Map();
|
|
1424
|
+
registerFunctionDefaultGenerator("generate_ulid", () => ulid());
|
|
1425
|
+
UNKNOWN_FUNCTION_DEFAULT = "$unknown_function";
|
|
1426
|
+
}
|
|
1427
|
+
});
|
|
1428
|
+
|
|
1429
|
+
// src/models/metaSync.ts
|
|
1430
|
+
import * as Y3 from "yjs";
|
|
1202
1431
|
function inferFieldType(value) {
|
|
1203
1432
|
if (isStringSetYMap(value)) return "stringset";
|
|
1204
1433
|
switch (typeof value) {
|
|
@@ -1219,7 +1448,10 @@ function encodeDefault(value) {
|
|
|
1219
1448
|
if (value === void 0 || value === null) return void 0;
|
|
1220
1449
|
if (typeof value === "function") {
|
|
1221
1450
|
const name = KNOWN_FUNCTION_DEFAULTS.get(value);
|
|
1222
|
-
return name ? `$${name}` :
|
|
1451
|
+
return name ? `$${name}` : UNKNOWN_FUNCTION_DEFAULT;
|
|
1452
|
+
}
|
|
1453
|
+
if (typeof value === "string" && value.startsWith("$")) {
|
|
1454
|
+
return `$${value}`;
|
|
1223
1455
|
}
|
|
1224
1456
|
return value;
|
|
1225
1457
|
}
|
|
@@ -1245,7 +1477,7 @@ function syncModelMeta(yDoc, modelName, schema) {
|
|
|
1245
1477
|
if (compoundConstraints.length > 0) {
|
|
1246
1478
|
let constraints = meta.get("_constraints");
|
|
1247
1479
|
if (!constraints) {
|
|
1248
|
-
constraints = new
|
|
1480
|
+
constraints = new Y3.Map();
|
|
1249
1481
|
meta.set("_constraints", constraints);
|
|
1250
1482
|
}
|
|
1251
1483
|
for (const constraint of compoundConstraints) {
|
|
@@ -1256,7 +1488,7 @@ function syncModelMeta(yDoc, modelName, schema) {
|
|
|
1256
1488
|
if (relationships && Object.keys(relationships).length > 0) {
|
|
1257
1489
|
let rels = meta.get("_relationships");
|
|
1258
1490
|
if (!rels) {
|
|
1259
|
-
rels = new
|
|
1491
|
+
rels = new Y3.Map();
|
|
1260
1492
|
meta.set("_relationships", rels);
|
|
1261
1493
|
}
|
|
1262
1494
|
for (const [relName, relConfig] of Object.entries(relationships)) {
|
|
@@ -1268,7 +1500,7 @@ function syncModelMeta(yDoc, modelName, schema) {
|
|
|
1268
1500
|
function syncFieldMeta(metaMap, fieldName, fieldOpts) {
|
|
1269
1501
|
let fieldMeta = metaMap.get(fieldName);
|
|
1270
1502
|
if (!fieldMeta) {
|
|
1271
|
-
fieldMeta = new
|
|
1503
|
+
fieldMeta = new Y3.Map();
|
|
1272
1504
|
metaMap.set(fieldName, fieldMeta);
|
|
1273
1505
|
}
|
|
1274
1506
|
setIfChanged(fieldMeta, "type", fieldOpts.type);
|
|
@@ -1285,7 +1517,7 @@ function syncFieldMeta(metaMap, fieldName, fieldOpts) {
|
|
|
1285
1517
|
function syncConstraintMeta(constraintsMap, constraint) {
|
|
1286
1518
|
let cMeta = constraintsMap.get(constraint.name);
|
|
1287
1519
|
if (!cMeta) {
|
|
1288
|
-
cMeta = new
|
|
1520
|
+
cMeta = new Y3.Map();
|
|
1289
1521
|
constraintsMap.set(constraint.name, cMeta);
|
|
1290
1522
|
}
|
|
1291
1523
|
setIfChanged(cMeta, "type", "unique");
|
|
@@ -1295,7 +1527,7 @@ function syncConstraintMeta(constraintsMap, constraint) {
|
|
|
1295
1527
|
function syncRelationshipMeta(relsMap, relName, relConfig) {
|
|
1296
1528
|
let relMeta = relsMap.get(relName);
|
|
1297
1529
|
if (!relMeta) {
|
|
1298
|
-
relMeta = new
|
|
1530
|
+
relMeta = new Y3.Map();
|
|
1299
1531
|
relsMap.set(relName, relMeta);
|
|
1300
1532
|
}
|
|
1301
1533
|
for (const [key, value] of Object.entries(relConfig)) {
|
|
@@ -1310,7 +1542,7 @@ function syncInferredMeta(yDoc, modelName, recordData) {
|
|
|
1310
1542
|
if (fieldName.startsWith("_")) continue;
|
|
1311
1543
|
let fieldMeta = meta.get(fieldName);
|
|
1312
1544
|
if (!fieldMeta) {
|
|
1313
|
-
fieldMeta = new
|
|
1545
|
+
fieldMeta = new Y3.Map();
|
|
1314
1546
|
meta.set(fieldName, fieldMeta);
|
|
1315
1547
|
}
|
|
1316
1548
|
if (!fieldMeta.has("type")) {
|
|
@@ -1331,12 +1563,51 @@ var init_metaSync = __esm({
|
|
|
1331
1563
|
"src/models/metaSync.ts"() {
|
|
1332
1564
|
"use strict";
|
|
1333
1565
|
init_yjsValues();
|
|
1566
|
+
init_writeLifecycle();
|
|
1334
1567
|
KNOWN_FUNCTION_DEFAULTS = /* @__PURE__ */ new WeakMap();
|
|
1335
1568
|
_syncedCache = /* @__PURE__ */ new WeakMap();
|
|
1336
1569
|
}
|
|
1337
1570
|
});
|
|
1338
1571
|
|
|
1572
|
+
// src/utils/uniqueIndex.ts
|
|
1573
|
+
import * as Y4 from "yjs";
|
|
1574
|
+
function buildUniqueKey(recordData, fields) {
|
|
1575
|
+
const keyParts = [];
|
|
1576
|
+
for (const field of fields) {
|
|
1577
|
+
const value = recordData instanceof Y4.Map ? recordData.get(field) : recordData[field];
|
|
1578
|
+
if (value === null || value === void 0) {
|
|
1579
|
+
return null;
|
|
1580
|
+
}
|
|
1581
|
+
keyParts.push(String(value));
|
|
1582
|
+
}
|
|
1583
|
+
return keyParts.join("|");
|
|
1584
|
+
}
|
|
1585
|
+
function uniqueIndexMapName(modelName, constraintName) {
|
|
1586
|
+
return `_uniqueIdx_${modelName}_${constraintName}`;
|
|
1587
|
+
}
|
|
1588
|
+
function fieldUniqueConstraintName(modelName, fieldName) {
|
|
1589
|
+
return `${modelName}_${fieldName}_unique`;
|
|
1590
|
+
}
|
|
1591
|
+
var init_uniqueIndex = __esm({
|
|
1592
|
+
"src/utils/uniqueIndex.ts"() {
|
|
1593
|
+
"use strict";
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
|
|
1339
1597
|
// src/models/relationshipManager.ts
|
|
1598
|
+
function warnIfOrderFieldNullable(modelClass, orderByField, relationshipDescription) {
|
|
1599
|
+
if (ALWAYS_PRESENT_ORDER_FIELDS.has(orderByField)) return;
|
|
1600
|
+
const schema = modelClass.getSchema?.();
|
|
1601
|
+
const fields = schema?.fields;
|
|
1602
|
+
if (!fields || typeof fields.get !== "function") return;
|
|
1603
|
+
const fieldOptions = fields.get(orderByField);
|
|
1604
|
+
if (!fieldOptions) return;
|
|
1605
|
+
if (fieldOptions.required !== true) {
|
|
1606
|
+
Logger.warn(
|
|
1607
|
+
`[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.)`
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1340
1611
|
function generateRefersToMethod(_sourceModelClass, config, targetModelClass) {
|
|
1341
1612
|
return async function() {
|
|
1342
1613
|
const relatedId = this[config.relatedIdField];
|
|
@@ -1345,6 +1616,16 @@ function generateRefersToMethod(_sourceModelClass, config, targetModelClass) {
|
|
|
1345
1616
|
};
|
|
1346
1617
|
}
|
|
1347
1618
|
function generateHasManyMethod(_sourceModelClass, config, targetModelClass, _dbEngine) {
|
|
1619
|
+
const {
|
|
1620
|
+
relatedIdField,
|
|
1621
|
+
orderByField = "id",
|
|
1622
|
+
orderDirection = "ASC"
|
|
1623
|
+
} = config;
|
|
1624
|
+
warnIfOrderFieldNullable(
|
|
1625
|
+
targetModelClass,
|
|
1626
|
+
orderByField,
|
|
1627
|
+
`hasMany(${targetModelClass.name})`
|
|
1628
|
+
);
|
|
1348
1629
|
return async function(paginationArgs) {
|
|
1349
1630
|
const {
|
|
1350
1631
|
limit,
|
|
@@ -1352,71 +1633,39 @@ function generateHasManyMethod(_sourceModelClass, config, targetModelClass, _dbE
|
|
|
1352
1633
|
beforeCursor,
|
|
1353
1634
|
direction = "forward"
|
|
1354
1635
|
} = paginationArgs || {};
|
|
1355
|
-
const {
|
|
1356
|
-
relatedIdField,
|
|
1357
|
-
orderByField = "id",
|
|
1358
|
-
orderDirection = "ASC"
|
|
1359
|
-
} = config;
|
|
1360
1636
|
const targetSchema = targetModelClass.getSchema();
|
|
1361
1637
|
if (!targetSchema || !targetSchema.options || !targetSchema.options.name) {
|
|
1362
1638
|
Logger.error(
|
|
1363
1639
|
`[RelationshipManager] Target model ${targetModelClass.name} for hasMany relationship has no valid schema name.`
|
|
1364
1640
|
);
|
|
1365
|
-
return { data: [],
|
|
1641
|
+
return { data: [], hasMore: false };
|
|
1366
1642
|
}
|
|
1367
|
-
const
|
|
1643
|
+
const forward = direction !== "backward";
|
|
1644
|
+
const cursor = forward ? afterCursor : beforeCursor;
|
|
1368
1645
|
const queryOptions = {
|
|
1369
|
-
sort: { [orderByField]: orderDirection === "ASC" ? 1 : -1 }
|
|
1646
|
+
sort: { [orderByField]: orderDirection === "ASC" ? 1 : -1 },
|
|
1647
|
+
direction: forward ? 1 : -1
|
|
1370
1648
|
};
|
|
1371
|
-
if (limit !== void 0)
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
};
|
|
1378
|
-
} else if (direction === "backward") {
|
|
1379
|
-
if (beforeCursor) {
|
|
1380
|
-
filter[orderByField] = {
|
|
1381
|
-
[orderDirection === "ASC" ? "$lt" : "$gt"]: beforeCursor
|
|
1382
|
-
};
|
|
1383
|
-
}
|
|
1384
|
-
queryOptions.sort = { [orderByField]: orderDirection === "ASC" ? -1 : 1 };
|
|
1385
|
-
}
|
|
1386
|
-
const result = await targetModelClass.query(filter, queryOptions);
|
|
1387
|
-
const results = result.data;
|
|
1388
|
-
let nextCursor = null;
|
|
1389
|
-
let prevCursor = null;
|
|
1390
|
-
const isFirstPage = direction === "forward" && !afterCursor;
|
|
1391
|
-
if (limit !== void 0) {
|
|
1392
|
-
if (direction === "forward") {
|
|
1393
|
-
if (results.length > limit) {
|
|
1394
|
-
nextCursor = results[limit - 1][orderByField];
|
|
1395
|
-
results.pop();
|
|
1396
|
-
}
|
|
1397
|
-
if (results.length > 0 && !isFirstPage) {
|
|
1398
|
-
prevCursor = results[0][orderByField];
|
|
1399
|
-
}
|
|
1400
|
-
} else {
|
|
1401
|
-
if (results.length > limit) {
|
|
1402
|
-
prevCursor = results[limit - 1][orderByField];
|
|
1403
|
-
results.pop();
|
|
1404
|
-
}
|
|
1405
|
-
results.reverse();
|
|
1406
|
-
if (results.length > 0 && beforeCursor) {
|
|
1407
|
-
nextCursor = results[results.length - 1][orderByField];
|
|
1408
|
-
}
|
|
1409
|
-
if (results.length > 0 && !beforeCursor) {
|
|
1410
|
-
if (results.length === limit) {
|
|
1411
|
-
prevCursor = results[0][orderByField];
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
return { data: results, nextCursor, prevCursor };
|
|
1649
|
+
if (limit !== void 0) queryOptions.limit = limit;
|
|
1650
|
+
if (cursor != null) queryOptions.uniqueStartKey = cursor;
|
|
1651
|
+
return targetModelClass.query(
|
|
1652
|
+
{ [relatedIdField]: this.id },
|
|
1653
|
+
queryOptions
|
|
1654
|
+
);
|
|
1417
1655
|
};
|
|
1418
1656
|
}
|
|
1419
1657
|
function generateHasManyThroughMethod(_sourceModelClass, config, targetModelClass, joinModelClass, _dbEngine) {
|
|
1658
|
+
const {
|
|
1659
|
+
joinModelLocalField,
|
|
1660
|
+
joinModelRelatedField,
|
|
1661
|
+
joinModelOrderByField = "id",
|
|
1662
|
+
joinModelOrderDirection = "ASC"
|
|
1663
|
+
} = config;
|
|
1664
|
+
warnIfOrderFieldNullable(
|
|
1665
|
+
joinModelClass,
|
|
1666
|
+
joinModelOrderByField,
|
|
1667
|
+
`hasManyThrough(${targetModelClass.name} via ${joinModelClass.name})`
|
|
1668
|
+
);
|
|
1420
1669
|
return async function(paginationArgs) {
|
|
1421
1670
|
const {
|
|
1422
1671
|
limit,
|
|
@@ -1430,87 +1679,42 @@ function generateHasManyThroughMethod(_sourceModelClass, config, targetModelClas
|
|
|
1430
1679
|
Logger.error(
|
|
1431
1680
|
`[RelationshipManager] Join model ${joinModelClass.name} for hasManyThrough relationship has no valid schema name.`
|
|
1432
1681
|
);
|
|
1433
|
-
return { data: [],
|
|
1682
|
+
return { data: [], hasMore: false };
|
|
1434
1683
|
}
|
|
1435
1684
|
if (!targetSchema || !targetSchema.options || !targetSchema.options.name) {
|
|
1436
1685
|
Logger.error(
|
|
1437
1686
|
`[RelationshipManager] Target model ${targetModelClass.name} for hasManyThrough relationship has no valid schema name.`
|
|
1438
1687
|
);
|
|
1439
|
-
return { data: [],
|
|
1688
|
+
return { data: [], hasMore: false };
|
|
1440
1689
|
}
|
|
1441
|
-
const
|
|
1442
|
-
|
|
1443
|
-
joinModelRelatedField,
|
|
1444
|
-
joinModelOrderByField = "id",
|
|
1445
|
-
joinModelOrderDirection = "ASC"
|
|
1446
|
-
} = config;
|
|
1447
|
-
const joinFilter = { [joinModelLocalField]: this.id };
|
|
1690
|
+
const forward = direction !== "backward";
|
|
1691
|
+
const cursor = forward ? afterCursor : beforeCursor;
|
|
1448
1692
|
const joinQueryOptions = {
|
|
1449
1693
|
sort: {
|
|
1450
1694
|
[joinModelOrderByField]: joinModelOrderDirection === "ASC" ? 1 : -1
|
|
1451
1695
|
},
|
|
1452
|
-
projection: { [joinModelRelatedField]: 1, [joinModelOrderByField]: 1 }
|
|
1696
|
+
projection: { [joinModelRelatedField]: 1, [joinModelOrderByField]: 1 },
|
|
1697
|
+
direction: forward ? 1 : -1
|
|
1453
1698
|
};
|
|
1454
|
-
if (limit !== void 0)
|
|
1455
|
-
|
|
1456
|
-
}
|
|
1457
|
-
if (direction === "forward" && afterCursor) {
|
|
1458
|
-
joinFilter[joinModelOrderByField] = {
|
|
1459
|
-
[joinModelOrderDirection === "ASC" ? "$gt" : "$lt"]: afterCursor
|
|
1460
|
-
};
|
|
1461
|
-
} else if (direction === "backward") {
|
|
1462
|
-
if (beforeCursor) {
|
|
1463
|
-
joinFilter[joinModelOrderByField] = {
|
|
1464
|
-
[joinModelOrderDirection === "ASC" ? "$lt" : "$gt"]: beforeCursor
|
|
1465
|
-
};
|
|
1466
|
-
}
|
|
1467
|
-
joinQueryOptions.sort = {
|
|
1468
|
-
[joinModelOrderByField]: joinModelOrderDirection === "ASC" ? -1 : 1
|
|
1469
|
-
};
|
|
1470
|
-
}
|
|
1699
|
+
if (limit !== void 0) joinQueryOptions.limit = limit;
|
|
1700
|
+
if (cursor != null) joinQueryOptions.uniqueStartKey = cursor;
|
|
1471
1701
|
const joinResult = await joinModelClass.query(
|
|
1472
|
-
|
|
1702
|
+
{ [joinModelLocalField]: this.id },
|
|
1473
1703
|
joinQueryOptions
|
|
1474
1704
|
);
|
|
1475
|
-
const
|
|
1476
|
-
let
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
nextCursorFromJoin = joinResults[limit - 1][joinModelOrderByField];
|
|
1483
|
-
joinResults.pop();
|
|
1484
|
-
}
|
|
1485
|
-
if (joinResults.length > 0 && !isFirstPage) {
|
|
1486
|
-
prevCursorFromJoin = joinResults[0][joinModelOrderByField];
|
|
1487
|
-
}
|
|
1488
|
-
} else {
|
|
1489
|
-
if (joinResults.length > limit) {
|
|
1490
|
-
prevCursorFromJoin = joinResults[limit - 1][joinModelOrderByField];
|
|
1491
|
-
joinResults.pop();
|
|
1492
|
-
}
|
|
1493
|
-
joinResults.reverse();
|
|
1494
|
-
if (joinResults.length > 0 && beforeCursor) {
|
|
1495
|
-
nextCursorFromJoin = joinResults[joinResults.length - 1][joinModelOrderByField];
|
|
1496
|
-
}
|
|
1497
|
-
if (joinResults.length > 0 && !beforeCursor) {
|
|
1498
|
-
if (joinResults.length === limit) {
|
|
1499
|
-
prevCursorFromJoin = joinResults[0][joinModelOrderByField];
|
|
1500
|
-
}
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1705
|
+
const relatedIds = joinResult.data.map((r) => r[joinModelRelatedField]).filter((id) => id != null && typeof id === "string");
|
|
1706
|
+
let targetData = [];
|
|
1707
|
+
if (relatedIds.length > 0) {
|
|
1708
|
+
const targetResult = await targetModelClass.query({
|
|
1709
|
+
id: { $in: relatedIds }
|
|
1710
|
+
});
|
|
1711
|
+
targetData = targetResult.data;
|
|
1503
1712
|
}
|
|
1504
|
-
const relatedIds = joinResults.map((r) => r[joinModelRelatedField]).filter((id) => id != null && typeof id === "string");
|
|
1505
|
-
if (relatedIds.length === 0)
|
|
1506
|
-
return { data: [], nextCursor: null, prevCursor: null };
|
|
1507
|
-
const targetResult = await targetModelClass.query({
|
|
1508
|
-
id: { $in: relatedIds }
|
|
1509
|
-
});
|
|
1510
1713
|
return {
|
|
1511
|
-
data:
|
|
1512
|
-
nextCursor:
|
|
1513
|
-
prevCursor:
|
|
1714
|
+
data: targetData,
|
|
1715
|
+
nextCursor: joinResult.nextCursor,
|
|
1716
|
+
prevCursor: joinResult.prevCursor,
|
|
1717
|
+
hasMore: joinResult.hasMore
|
|
1514
1718
|
};
|
|
1515
1719
|
};
|
|
1516
1720
|
}
|
|
@@ -1634,10 +1838,12 @@ function generateHasManyThroughRemoveMethod(_sourceModelClass, config, _targetMo
|
|
|
1634
1838
|
}, `remove-join-${config.joinModel}-${this.id}-${targetId}`);
|
|
1635
1839
|
};
|
|
1636
1840
|
}
|
|
1841
|
+
var ALWAYS_PRESENT_ORDER_FIELDS;
|
|
1637
1842
|
var init_relationshipManager = __esm({
|
|
1638
1843
|
"src/models/relationshipManager.ts"() {
|
|
1639
1844
|
"use strict";
|
|
1640
1845
|
init_BaseModel();
|
|
1846
|
+
ALWAYS_PRESENT_ORDER_FIELDS = /* @__PURE__ */ new Set(["id", "type"]);
|
|
1641
1847
|
}
|
|
1642
1848
|
});
|
|
1643
1849
|
|
|
@@ -2408,7 +2614,13 @@ var init_IncludeResolver = __esm({
|
|
|
2408
2614
|
}
|
|
2409
2615
|
return null;
|
|
2410
2616
|
}
|
|
2411
|
-
/**
|
|
2617
|
+
/**
|
|
2618
|
+
* Apply a projection to a single record. Assumes the projection was already
|
|
2619
|
+
* validated upstream (mixed inclusion+exclusion rejected by the translator):
|
|
2620
|
+
* `isInclusion` treats "any value === 1" as inclusion mode. `id` and `type`
|
|
2621
|
+
* are system-identity fields and are always kept in BOTH modes (mirrors the
|
|
2622
|
+
* DatabaseDO `_applyProjection`); `_meta` stays excludable.
|
|
2623
|
+
*/
|
|
2412
2624
|
_applyProjection(record, projection) {
|
|
2413
2625
|
const fields = Object.entries(projection);
|
|
2414
2626
|
if (fields.length === 0) return record;
|
|
@@ -2427,7 +2639,7 @@ var init_IncludeResolver = __esm({
|
|
|
2427
2639
|
} else {
|
|
2428
2640
|
const result = { ...record };
|
|
2429
2641
|
for (const [f, v] of fields) {
|
|
2430
|
-
if (v === 0) delete result[f];
|
|
2642
|
+
if (v === 0 && f !== "id" && f !== "type") delete result[f];
|
|
2431
2643
|
}
|
|
2432
2644
|
return result;
|
|
2433
2645
|
}
|
|
@@ -2446,10 +2658,10 @@ __export(BaseModel_exports, {
|
|
|
2446
2658
|
UniqueConstraintViolationError: () => UniqueConstraintViolationError,
|
|
2447
2659
|
generateULID: () => generateULID
|
|
2448
2660
|
});
|
|
2449
|
-
import * as
|
|
2450
|
-
import { ulid } from "ulid";
|
|
2661
|
+
import * as Y5 from "yjs";
|
|
2662
|
+
import { ulid as ulid2 } from "ulid";
|
|
2451
2663
|
function generateULID() {
|
|
2452
|
-
return
|
|
2664
|
+
return ulid2();
|
|
2453
2665
|
}
|
|
2454
2666
|
var LogLevel, Logger, UniqueConstraintViolationError, RecordNotFoundError, SCHEMA_ACCESSORS_KEY, BaseModel2;
|
|
2455
2667
|
var init_BaseModel = __esm({
|
|
@@ -2461,7 +2673,9 @@ var init_BaseModel = __esm({
|
|
|
2461
2673
|
init_CursorManager();
|
|
2462
2674
|
init_sql();
|
|
2463
2675
|
init_metaSync();
|
|
2676
|
+
init_writeLifecycle();
|
|
2464
2677
|
init_yjsValues();
|
|
2678
|
+
init_uniqueIndex();
|
|
2465
2679
|
LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
2466
2680
|
LogLevel2[LogLevel2["SILENT"] = 0] = "SILENT";
|
|
2467
2681
|
LogLevel2[LogLevel2["ERROR"] = 1] = "ERROR";
|
|
@@ -2846,7 +3060,9 @@ var init_BaseModel = __esm({
|
|
|
2846
3060
|
this.setValue(fieldKey, data[fieldKey]);
|
|
2847
3061
|
this._constructorProvidedFields.add(fieldKey);
|
|
2848
3062
|
} else if (fieldOptions.default !== void 0) {
|
|
2849
|
-
const defaultValue =
|
|
3063
|
+
const defaultValue = resolveLiteralOrFunctionDefault(
|
|
3064
|
+
fieldOptions.default
|
|
3065
|
+
);
|
|
2850
3066
|
this.setValue(fieldKey, defaultValue);
|
|
2851
3067
|
}
|
|
2852
3068
|
}
|
|
@@ -3138,7 +3354,7 @@ var init_BaseModel = __esm({
|
|
|
3138
3354
|
}
|
|
3139
3355
|
getStringSetFromYjs(fieldName) {
|
|
3140
3356
|
const yjsData = this.getFromYjs(fieldName);
|
|
3141
|
-
if (yjsData instanceof
|
|
3357
|
+
if (yjsData instanceof Y5.Map) {
|
|
3142
3358
|
return Array.from(yjsData.keys());
|
|
3143
3359
|
}
|
|
3144
3360
|
if (yjsData && typeof yjsData === "object") {
|
|
@@ -3246,7 +3462,7 @@ var init_BaseModel = __esm({
|
|
|
3246
3462
|
}
|
|
3247
3463
|
const extractStringSetValues = (value) => {
|
|
3248
3464
|
if (!value) return [];
|
|
3249
|
-
if (value instanceof
|
|
3465
|
+
if (value instanceof Y5.Map) {
|
|
3250
3466
|
return Array.from(value.entries()).filter(([, isMember]) => Boolean(isMember)).map(([key]) => key);
|
|
3251
3467
|
}
|
|
3252
3468
|
if (Array.isArray(value)) {
|
|
@@ -3263,7 +3479,7 @@ var init_BaseModel = __esm({
|
|
|
3263
3479
|
if (!recordId) continue;
|
|
3264
3480
|
let itemData;
|
|
3265
3481
|
const stringSetValuesByField = {};
|
|
3266
|
-
if (recordData instanceof
|
|
3482
|
+
if (recordData instanceof Y5.Map) {
|
|
3267
3483
|
itemData = {};
|
|
3268
3484
|
const unknownFields = [];
|
|
3269
3485
|
for (const [fieldKey, value] of recordData.entries()) {
|
|
@@ -3379,20 +3595,10 @@ var init_BaseModel = __esm({
|
|
|
3379
3595
|
Logger.verbose(
|
|
3380
3596
|
`[${this.name}] Setting up YMap observer for document ${docId}/${modelName}...`
|
|
3381
3597
|
);
|
|
3382
|
-
const
|
|
3383
|
-
const keyParts = [];
|
|
3384
|
-
for (const field of fields) {
|
|
3385
|
-
const value = recordData instanceof Y3.Map ? recordData.get(field) : recordData[field];
|
|
3386
|
-
if (value === null || value === void 0) {
|
|
3387
|
-
return null;
|
|
3388
|
-
}
|
|
3389
|
-
keyParts.push(String(value));
|
|
3390
|
-
}
|
|
3391
|
-
return keyParts.join("|");
|
|
3392
|
-
};
|
|
3598
|
+
const buildUniqueKey2 = (recordData, fields) => buildUniqueKey(recordData, fields);
|
|
3393
3599
|
const extractItemData = (key, recordData) => {
|
|
3394
3600
|
let itemData;
|
|
3395
|
-
if (recordData instanceof
|
|
3601
|
+
if (recordData instanceof Y5.Map) {
|
|
3396
3602
|
itemData = {};
|
|
3397
3603
|
const unknownFields = [];
|
|
3398
3604
|
for (const [fieldKey, value] of recordData.entries()) {
|
|
@@ -3476,7 +3682,7 @@ var init_BaseModel = __esm({
|
|
|
3476
3682
|
const recordsByUniqueKey = /* @__PURE__ */ new Map();
|
|
3477
3683
|
for (const [recordId, recordData] of allRecords.entries()) {
|
|
3478
3684
|
if (recordIdsToDiscard.has(recordId)) continue;
|
|
3479
|
-
const uniqueKey =
|
|
3685
|
+
const uniqueKey = buildUniqueKey2(recordData, constraint.fields);
|
|
3480
3686
|
if (uniqueKey === null) continue;
|
|
3481
3687
|
if (!recordsByUniqueKey.has(uniqueKey)) {
|
|
3482
3688
|
recordsByUniqueKey.set(uniqueKey, []);
|
|
@@ -3522,7 +3728,7 @@ var init_BaseModel = __esm({
|
|
|
3522
3728
|
if (!recordData || !key) continue;
|
|
3523
3729
|
const itemData = extractItemData(key, recordData);
|
|
3524
3730
|
if (!itemData) continue;
|
|
3525
|
-
if (change.action === "add" && recordData instanceof
|
|
3731
|
+
if (change.action === "add" && recordData instanceof Y5.Map) {
|
|
3526
3732
|
Logger.verbose(
|
|
3527
3733
|
`[${this.name}] Setting up observer on newly added nested YMap for record ${key} in document ${docId}`
|
|
3528
3734
|
);
|
|
@@ -3620,9 +3826,12 @@ var init_BaseModel = __esm({
|
|
|
3620
3826
|
const recordData = documentYMap.get(idToDiscard);
|
|
3621
3827
|
if (!recordData) continue;
|
|
3622
3828
|
for (const constraint of schema.resolvedUniqueConstraints) {
|
|
3623
|
-
const uniqueKey =
|
|
3829
|
+
const uniqueKey = buildUniqueKey2(recordData, constraint.fields);
|
|
3624
3830
|
if (uniqueKey === null) continue;
|
|
3625
|
-
const constraintMapName =
|
|
3831
|
+
const constraintMapName = uniqueIndexMapName(
|
|
3832
|
+
modelName,
|
|
3833
|
+
constraint.name
|
|
3834
|
+
);
|
|
3626
3835
|
const constraintMap = yDoc.getMap(constraintMapName);
|
|
3627
3836
|
const currentIndexValue = constraintMap.get(uniqueKey);
|
|
3628
3837
|
if (currentIndexValue === idToDiscard) {
|
|
@@ -3640,11 +3849,14 @@ var init_BaseModel = __esm({
|
|
|
3640
3849
|
}, `conflict-resolution-${modelName}-${docId}`);
|
|
3641
3850
|
yDoc.transact(() => {
|
|
3642
3851
|
for (const constraint of schema.resolvedUniqueConstraints) {
|
|
3643
|
-
const constraintMapName =
|
|
3852
|
+
const constraintMapName = uniqueIndexMapName(
|
|
3853
|
+
modelName,
|
|
3854
|
+
constraint.name
|
|
3855
|
+
);
|
|
3644
3856
|
const constraintMap = yDoc.getMap(constraintMapName);
|
|
3645
3857
|
for (const [recordId, recordData] of documentYMap.entries()) {
|
|
3646
3858
|
if (!recordData) continue;
|
|
3647
|
-
const uniqueKey =
|
|
3859
|
+
const uniqueKey = buildUniqueKey2(recordData, constraint.fields);
|
|
3648
3860
|
if (uniqueKey === null) continue;
|
|
3649
3861
|
const currentIndexValue = constraintMap.get(uniqueKey);
|
|
3650
3862
|
if (currentIndexValue !== recordId) {
|
|
@@ -3667,7 +3879,7 @@ var init_BaseModel = __esm({
|
|
|
3667
3879
|
`[${this.name}] Setting up observers on existing nested YMaps for ${modelName}/${docId}...`
|
|
3668
3880
|
);
|
|
3669
3881
|
for (const [recordId, recordData] of documentYMap.entries()) {
|
|
3670
|
-
if (recordData instanceof
|
|
3882
|
+
if (recordData instanceof Y5.Map) {
|
|
3671
3883
|
Logger.verbose(
|
|
3672
3884
|
`[${this.name}] Setting up observer on existing nested YMap for record ${recordId} in document ${docId}`
|
|
3673
3885
|
);
|
|
@@ -3893,26 +4105,7 @@ var init_BaseModel = __esm({
|
|
|
3893
4105
|
* if the field hasn't been touched since the wire-format change in #561.
|
|
3894
4106
|
*/
|
|
3895
4107
|
applyStringSetChangeToYMap(recordYMap, fieldName, change) {
|
|
3896
|
-
|
|
3897
|
-
if (!(nested instanceof Y3.Map)) {
|
|
3898
|
-
const migrated = new Y3.Map();
|
|
3899
|
-
if (nested && typeof nested === "object") {
|
|
3900
|
-
for (const [member, marker] of Object.entries(
|
|
3901
|
-
nested
|
|
3902
|
-
)) {
|
|
3903
|
-
if (Boolean(marker)) migrated.set(member, true);
|
|
3904
|
-
}
|
|
3905
|
-
}
|
|
3906
|
-
recordYMap.set(fieldName, migrated);
|
|
3907
|
-
nested = migrated;
|
|
3908
|
-
}
|
|
3909
|
-
const target = nested;
|
|
3910
|
-
for (const member of change.additions) {
|
|
3911
|
-
target.set(member, true);
|
|
3912
|
-
}
|
|
3913
|
-
for (const member of change.removals) {
|
|
3914
|
-
target.delete(member);
|
|
3915
|
-
}
|
|
4108
|
+
applyStringSetChange(recordYMap, fieldName, change);
|
|
3916
4109
|
}
|
|
3917
4110
|
/**
|
|
3918
4111
|
* Deep equality check for comparing field values
|
|
@@ -4114,6 +4307,34 @@ var init_BaseModel = __esm({
|
|
|
4114
4307
|
`[${modelName}.save] getCurrentJSState() returned:`,
|
|
4115
4308
|
dataToSave
|
|
4116
4309
|
);
|
|
4310
|
+
const uniqueMissConflicts = /* @__PURE__ */ new Map();
|
|
4311
|
+
for (const constraint of schema.resolvedUniqueConstraints) {
|
|
4312
|
+
const newUniqueKey = this._buildUniqueKey(
|
|
4313
|
+
constraint.fields,
|
|
4314
|
+
dataToSave,
|
|
4315
|
+
modelName,
|
|
4316
|
+
constraint.name
|
|
4317
|
+
);
|
|
4318
|
+
if (newUniqueKey === null) {
|
|
4319
|
+
continue;
|
|
4320
|
+
}
|
|
4321
|
+
const constraintMap = yDoc.getMap(
|
|
4322
|
+
uniqueIndexMapName(modelName, constraint.name)
|
|
4323
|
+
);
|
|
4324
|
+
if (!constraintMap.get(newUniqueKey)) {
|
|
4325
|
+
const constraintKeyValues = constraint.fields.map(
|
|
4326
|
+
(field) => dataToSave[field]
|
|
4327
|
+
);
|
|
4328
|
+
const conflictingRecord = await modelConstructor._resolveByUniqueFallback(
|
|
4329
|
+
constraint,
|
|
4330
|
+
constraintKeyValues,
|
|
4331
|
+
{ excludeId: this.id }
|
|
4332
|
+
);
|
|
4333
|
+
if (conflictingRecord) {
|
|
4334
|
+
uniqueMissConflicts.set(constraint.name, conflictingRecord.id);
|
|
4335
|
+
}
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4117
4338
|
await yDoc.transact(async () => {
|
|
4118
4339
|
if (upsertOnConstraint && upsertOnKey) {
|
|
4119
4340
|
const constraintMapName = `_uniqueIdx_${modelName}_${upsertOnConstraint.name}`;
|
|
@@ -4155,7 +4376,7 @@ var init_BaseModel = __esm({
|
|
|
4155
4376
|
Logger.debug(`[${modelName}.save] isUpdate: ${isUpdate}`);
|
|
4156
4377
|
Logger.debug(`[${modelName}.save] recordYMap exists: ${!!recordYMap}`);
|
|
4157
4378
|
if (!recordYMap) {
|
|
4158
|
-
recordYMap = new
|
|
4379
|
+
recordYMap = new Y5.Map();
|
|
4159
4380
|
Logger.verbose(
|
|
4160
4381
|
`[${modelName}] Creating new nested YMap for record ${this.id} in document ${targetDocId || "legacy"}`
|
|
4161
4382
|
);
|
|
@@ -4207,7 +4428,10 @@ var init_BaseModel = __esm({
|
|
|
4207
4428
|
);
|
|
4208
4429
|
continue;
|
|
4209
4430
|
}
|
|
4210
|
-
const constraintMapName =
|
|
4431
|
+
const constraintMapName = uniqueIndexMapName(
|
|
4432
|
+
modelName,
|
|
4433
|
+
constraint.name
|
|
4434
|
+
);
|
|
4211
4435
|
const constraintMap = yDoc.getMap(constraintMapName);
|
|
4212
4436
|
Logger.verbose(
|
|
4213
4437
|
`[${modelName}] Save Check (Item '${this.id}'): GET from '${constraintMapName}' with Key '${newUniqueKey.substring(
|
|
@@ -4236,6 +4460,26 @@ var init_BaseModel = __esm({
|
|
|
4236
4460
|
this.id,
|
|
4237
4461
|
existingRecordIdWithNewKey
|
|
4238
4462
|
);
|
|
4463
|
+
} else if (!existingRecordIdWithNewKey) {
|
|
4464
|
+
const conflictingRecordId = uniqueMissConflicts.get(constraint.name);
|
|
4465
|
+
if (conflictingRecordId && conflictingRecordId !== this.id) {
|
|
4466
|
+
Logger.verbose(
|
|
4467
|
+
`[${modelName}] Save Check (Item '${this.id}'): index miss for '${constraint.name}', but engine fallback found conflicting index-less record ${conflictingRecordId}.`
|
|
4468
|
+
);
|
|
4469
|
+
throw new UniqueConstraintViolationError(
|
|
4470
|
+
`Unique constraint '${constraint.name}' violated for model '${modelName}' on fields [${constraint.fields.join(
|
|
4471
|
+
", "
|
|
4472
|
+
)}]. Attempted ID: ${this.id}. Value(s) starting with '${newUniqueKey.substring(
|
|
4473
|
+
0,
|
|
4474
|
+
50
|
|
4475
|
+
)}...' already exist for index-less record ID ${conflictingRecordId}.`,
|
|
4476
|
+
modelName,
|
|
4477
|
+
constraint.name,
|
|
4478
|
+
constraint.fields,
|
|
4479
|
+
this.id,
|
|
4480
|
+
conflictingRecordId
|
|
4481
|
+
);
|
|
4482
|
+
}
|
|
4239
4483
|
}
|
|
4240
4484
|
}
|
|
4241
4485
|
if (isUpdate && oldData) {
|
|
@@ -4579,34 +4823,46 @@ var init_BaseModel = __esm({
|
|
|
4579
4823
|
const modelName = schema.options.name;
|
|
4580
4824
|
Logger.verbose(`[${modelName}] Executing query:`, { filter, options });
|
|
4581
4825
|
const hasIncludes = options?.include && options.include.length > 0;
|
|
4582
|
-
const
|
|
4826
|
+
const requestedLimit = options?.limit;
|
|
4827
|
+
const overFetch = typeof requestedLimit === "number" && requestedLimit > 0;
|
|
4828
|
+
let translatorOptions = hasIncludes && options?.projection ? { ...options, projection: void 0 } : options;
|
|
4829
|
+
if (overFetch) {
|
|
4830
|
+
translatorOptions = {
|
|
4831
|
+
...translatorOptions || {},
|
|
4832
|
+
limit: requestedLimit + 1
|
|
4833
|
+
};
|
|
4834
|
+
}
|
|
4583
4835
|
const translator = new DocumentQueryTranslator(modelName, schema.fields);
|
|
4584
4836
|
const translatedQuery = translator.translateFind(filter, translatorOptions);
|
|
4585
4837
|
Logger.verbose(`[${modelName}] Translated SQL:`, translatedQuery.sql);
|
|
4586
4838
|
Logger.verbose(`[${modelName}] SQL params:`, translatedQuery.params);
|
|
4587
|
-
|
|
4839
|
+
let results = await _BaseModel.dbInstance.query(
|
|
4588
4840
|
translatedQuery.sql,
|
|
4589
4841
|
translatedQuery.params
|
|
4590
4842
|
);
|
|
4591
4843
|
Logger.verbose(`[${modelName}] Query returned ${results.length} results`);
|
|
4844
|
+
let hasMore = false;
|
|
4845
|
+
if (overFetch && results.length > requestedLimit) {
|
|
4846
|
+
hasMore = true;
|
|
4847
|
+
results = results.slice(0, requestedLimit);
|
|
4848
|
+
}
|
|
4592
4849
|
if (options?.include && options.include.length > 0) {
|
|
4593
4850
|
const { IncludeResolver: IncludeResolver2 } = await Promise.resolve().then(() => (init_IncludeResolver(), IncludeResolver_exports));
|
|
4594
4851
|
const resolver = new IncludeResolver2(_BaseModel.dbInstance);
|
|
4595
4852
|
await resolver.resolve(results, options.include, 0, modelName);
|
|
4596
4853
|
}
|
|
4597
|
-
const requestedLimit = options?.limit;
|
|
4598
|
-
const hasMore = CursorManager.hasMoreResults(
|
|
4599
|
-
requestedLimit,
|
|
4600
|
-
results.length
|
|
4601
|
-
);
|
|
4602
4854
|
const isFirstPage = !options?.uniqueStartKey;
|
|
4855
|
+
const direction = options?.direction || 1;
|
|
4603
4856
|
const cursors = CursorManager.generateResultCursors(
|
|
4604
4857
|
results,
|
|
4605
4858
|
translatedQuery.sortFields,
|
|
4606
|
-
|
|
4859
|
+
direction,
|
|
4607
4860
|
hasMore,
|
|
4608
4861
|
isFirstPage
|
|
4609
4862
|
);
|
|
4863
|
+
if (direction === -1) {
|
|
4864
|
+
results.reverse();
|
|
4865
|
+
}
|
|
4610
4866
|
let transformedData;
|
|
4611
4867
|
if (options?.projection && Object.keys(options.projection).length > 0) {
|
|
4612
4868
|
transformedData = results.map((row) => {
|
|
@@ -5182,7 +5438,7 @@ var init_BaseModel = __esm({
|
|
|
5182
5438
|
);
|
|
5183
5439
|
}
|
|
5184
5440
|
for (const [recordId, recordYMap] of documentYMap.entries()) {
|
|
5185
|
-
if (recordYMap instanceof
|
|
5441
|
+
if (recordYMap instanceof Y5.Map) {
|
|
5186
5442
|
const instance = new this({ id: recordId });
|
|
5187
5443
|
instance._metaDocId = docId;
|
|
5188
5444
|
const connectedDoc = modelConstructor.connectedDocuments.get(docId);
|
|
@@ -5207,6 +5463,50 @@ var init_BaseModel = __esm({
|
|
|
5207
5463
|
}
|
|
5208
5464
|
return allInstances;
|
|
5209
5465
|
}
|
|
5466
|
+
/**
|
|
5467
|
+
* Resolve a record by its unique-constraint field values via an engine query.
|
|
5468
|
+
* Used as a fallback when the `_uniqueIdx_<model>_<constraint>` map has no
|
|
5469
|
+
* entry for a key.
|
|
5470
|
+
*
|
|
5471
|
+
* The index map is a cache over the SQLite projection, not the source of
|
|
5472
|
+
* truth: every record is loaded into the projection on `initializeForDocument`
|
|
5473
|
+
* regardless of index presence, but a record written by a client predating
|
|
5474
|
+
* index maintenance (legacy data) is missing from the index. Such a record
|
|
5475
|
+
* silently escapes both `upsertByUnique` lookups and the `save()` uniqueness
|
|
5476
|
+
* check. A query over the constraint fields finds it reliably.
|
|
5477
|
+
*
|
|
5478
|
+
* Contract: RESOLVE ONLY. Returns the owning record (with `_metaDocId` set to
|
|
5479
|
+
* the document that holds it, via `queryOne`) or `null`. Callers decide
|
|
5480
|
+
* whether to heal the missing index entry (write paths) and do their own
|
|
5481
|
+
* logging — this method never mutates the index, so read paths stay
|
|
5482
|
+
* read-only. Mirrors `buildUniqueKey`: a null/undefined value in any
|
|
5483
|
+
* constraint field means the record does not participate in the constraint,
|
|
5484
|
+
* so no query runs.
|
|
5485
|
+
*/
|
|
5486
|
+
static async _resolveByUniqueFallback(constraint, keyValues, options) {
|
|
5487
|
+
if (!_BaseModel.dbInstance) {
|
|
5488
|
+
return null;
|
|
5489
|
+
}
|
|
5490
|
+
const filter = {};
|
|
5491
|
+
for (let i = 0; i < constraint.fields.length; i++) {
|
|
5492
|
+
const value = keyValues[i];
|
|
5493
|
+
if (value === null || value === void 0) {
|
|
5494
|
+
return null;
|
|
5495
|
+
}
|
|
5496
|
+
filter[constraint.fields[i]] = value;
|
|
5497
|
+
}
|
|
5498
|
+
if (options?.excludeId) {
|
|
5499
|
+
if ("id" in filter) {
|
|
5500
|
+
if (filter.id === options.excludeId) {
|
|
5501
|
+
return null;
|
|
5502
|
+
}
|
|
5503
|
+
} else {
|
|
5504
|
+
filter.id = { $ne: options.excludeId };
|
|
5505
|
+
}
|
|
5506
|
+
}
|
|
5507
|
+
const found = await this.queryOne(filter);
|
|
5508
|
+
return found ?? null;
|
|
5509
|
+
}
|
|
5210
5510
|
static async findByUnique(constraintName, value) {
|
|
5211
5511
|
const modelConstructor = this;
|
|
5212
5512
|
const schema = modelConstructor.getSchema();
|
|
@@ -5245,7 +5545,10 @@ var init_BaseModel = __esm({
|
|
|
5245
5545
|
const documentInfo = modelConstructor.connectedDocuments.get(docId);
|
|
5246
5546
|
if (!documentInfo) continue;
|
|
5247
5547
|
const yDoc = documentInfo.yDoc;
|
|
5248
|
-
const constraintMapName2 =
|
|
5548
|
+
const constraintMapName2 = uniqueIndexMapName(
|
|
5549
|
+
currentModelName,
|
|
5550
|
+
constraint.name
|
|
5551
|
+
);
|
|
5249
5552
|
const constraintMap2 = yDoc.getMap(constraintMapName2);
|
|
5250
5553
|
const recordId2 = constraintMap2.get(uniqueKeyString);
|
|
5251
5554
|
if (recordId2) {
|
|
@@ -5253,7 +5556,7 @@ var init_BaseModel = __esm({
|
|
|
5253
5556
|
const documentYMap = modelConstructor.documentYMaps.get(documentYMapKey);
|
|
5254
5557
|
if (documentYMap) {
|
|
5255
5558
|
const recordYMap2 = documentYMap.get(recordId2);
|
|
5256
|
-
if (recordYMap2 && recordYMap2 instanceof
|
|
5559
|
+
if (recordYMap2 && recordYMap2 instanceof Y5.Map) {
|
|
5257
5560
|
const instance = new modelConstructor({
|
|
5258
5561
|
id: recordId2
|
|
5259
5562
|
});
|
|
@@ -5267,6 +5570,16 @@ var init_BaseModel = __esm({
|
|
|
5267
5570
|
}
|
|
5268
5571
|
}
|
|
5269
5572
|
}
|
|
5573
|
+
const fallbackRecord = await modelConstructor._resolveByUniqueFallback(
|
|
5574
|
+
constraint,
|
|
5575
|
+
keyValues
|
|
5576
|
+
);
|
|
5577
|
+
if (fallbackRecord) {
|
|
5578
|
+
Logger.verbose(
|
|
5579
|
+
`[${currentModelName}.findByUnique] Index miss for '${constraintName}' resolved via engine fallback to record ${fallbackRecord.id} (legacy index-less record; index left unchanged on read path).`
|
|
5580
|
+
);
|
|
5581
|
+
return fallbackRecord;
|
|
5582
|
+
}
|
|
5270
5583
|
Logger.verbose(
|
|
5271
5584
|
`[${currentModelName}.findByUnique] Record not found in any connected document`
|
|
5272
5585
|
);
|
|
@@ -5280,17 +5593,30 @@ var init_BaseModel = __esm({
|
|
|
5280
5593
|
`[${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.`
|
|
5281
5594
|
);
|
|
5282
5595
|
}
|
|
5283
|
-
const constraintMapName =
|
|
5596
|
+
const constraintMapName = uniqueIndexMapName(
|
|
5597
|
+
currentModelName,
|
|
5598
|
+
constraint.name
|
|
5599
|
+
);
|
|
5284
5600
|
const constraintMap = legacyDocInfo.yDoc.getMap(constraintMapName);
|
|
5285
5601
|
const recordId = constraintMap.get(uniqueKeyString);
|
|
5286
5602
|
if (!recordId) {
|
|
5603
|
+
const fallbackRecord = await modelConstructor._resolveByUniqueFallback(
|
|
5604
|
+
constraint,
|
|
5605
|
+
keyValues
|
|
5606
|
+
);
|
|
5607
|
+
if (fallbackRecord) {
|
|
5608
|
+
Logger.verbose(
|
|
5609
|
+
`[${currentModelName}.findByUnique] Index miss for '${constraintName}' resolved via engine fallback to record ${fallbackRecord.id} (legacy index-less record; index left unchanged on read path).`
|
|
5610
|
+
);
|
|
5611
|
+
return fallbackRecord;
|
|
5612
|
+
}
|
|
5287
5613
|
return null;
|
|
5288
5614
|
}
|
|
5289
5615
|
const recordYMap = legacyDocumentMap.get(recordId);
|
|
5290
5616
|
if (!recordYMap) {
|
|
5291
5617
|
return null;
|
|
5292
5618
|
}
|
|
5293
|
-
if (recordYMap instanceof
|
|
5619
|
+
if (recordYMap instanceof Y5.Map) {
|
|
5294
5620
|
const instance = new modelConstructor({
|
|
5295
5621
|
id: recordId
|
|
5296
5622
|
});
|
|
@@ -5348,7 +5674,10 @@ var init_BaseModel = __esm({
|
|
|
5348
5674
|
`[${currentModelName}] upsertByUnique for '${constraintName}': unique key cannot be built due to null/undefined values. Upsert cannot proceed reliably.`
|
|
5349
5675
|
);
|
|
5350
5676
|
}
|
|
5351
|
-
const constraintMapName =
|
|
5677
|
+
const constraintMapName = uniqueIndexMapName(
|
|
5678
|
+
currentModelName,
|
|
5679
|
+
constraint.name
|
|
5680
|
+
);
|
|
5352
5681
|
let existingRecord = null;
|
|
5353
5682
|
if (connectedDocuments && connectedDocuments.size > 0) {
|
|
5354
5683
|
for (const docId of connectedDocuments.keys()) {
|
|
@@ -5366,6 +5695,33 @@ var init_BaseModel = __esm({
|
|
|
5366
5695
|
}
|
|
5367
5696
|
} else {
|
|
5368
5697
|
}
|
|
5698
|
+
if (!existingRecord) {
|
|
5699
|
+
const fallbackRecord = await modelConstructor._resolveByUniqueFallback(
|
|
5700
|
+
constraint,
|
|
5701
|
+
keyValuesForLookup
|
|
5702
|
+
);
|
|
5703
|
+
if (fallbackRecord) {
|
|
5704
|
+
existingRecord = fallbackRecord;
|
|
5705
|
+
const healDocId = fallbackRecord._metaDocId;
|
|
5706
|
+
const healDocInfo = healDocId ? connectedDocuments.get(healDocId) : void 0;
|
|
5707
|
+
const canHeal = !!healDocInfo && healDocInfo.permissionHint !== "read";
|
|
5708
|
+
if (healDocInfo && canHeal) {
|
|
5709
|
+
healDocInfo.yDoc.transact(() => {
|
|
5710
|
+
const healMap = healDocInfo.yDoc.getMap(constraintMapName);
|
|
5711
|
+
if (healMap.get(uniqueKeyString) !== fallbackRecord.id) {
|
|
5712
|
+
healMap.set(uniqueKeyString, fallbackRecord.id);
|
|
5713
|
+
}
|
|
5714
|
+
}, `heal-unique-index-${currentModelName}-${healDocId}`);
|
|
5715
|
+
Logger.verbose(
|
|
5716
|
+
`[${currentModelName}] upsertByUnique: index miss for '${constraintName}' resolved via engine fallback to record ${fallbackRecord.id}; healed missing index entry (legacy index-less record).`
|
|
5717
|
+
);
|
|
5718
|
+
} else {
|
|
5719
|
+
Logger.verbose(
|
|
5720
|
+
`[${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).`
|
|
5721
|
+
);
|
|
5722
|
+
}
|
|
5723
|
+
}
|
|
5724
|
+
}
|
|
5369
5725
|
if (options?.objectMustExist) {
|
|
5370
5726
|
if (!existingRecord) {
|
|
5371
5727
|
throw new RecordNotFoundError(
|
|
@@ -5522,7 +5878,7 @@ var init_BaseModel = __esm({
|
|
|
5522
5878
|
for (const [fieldKey, fieldOptions] of schema.fields) {
|
|
5523
5879
|
if (fieldOptions?.type !== "stringset") continue;
|
|
5524
5880
|
const value = recordYMap.get(fieldKey);
|
|
5525
|
-
if (value instanceof
|
|
5881
|
+
if (value instanceof Y5.Map) {
|
|
5526
5882
|
this.observeStringSetMapOnce(value);
|
|
5527
5883
|
}
|
|
5528
5884
|
}
|
|
@@ -5707,16 +6063,170 @@ var init_BaseModel = __esm({
|
|
|
5707
6063
|
}
|
|
5708
6064
|
});
|
|
5709
6065
|
|
|
6066
|
+
// src/utils/environment.ts
|
|
6067
|
+
var environment_exports = {};
|
|
6068
|
+
__export(environment_exports, {
|
|
6069
|
+
constants: () => constants,
|
|
6070
|
+
detectEnvironment: () => detectEnvironment,
|
|
6071
|
+
features: () => features,
|
|
6072
|
+
isBrowser: () => isBrowser,
|
|
6073
|
+
isNode: () => isNode,
|
|
6074
|
+
isNodeModuleAvailable: () => isNodeModuleAvailable
|
|
6075
|
+
});
|
|
6076
|
+
function detectEnvironment() {
|
|
6077
|
+
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
6078
|
+
return "node";
|
|
6079
|
+
}
|
|
6080
|
+
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
6081
|
+
return "browser";
|
|
6082
|
+
}
|
|
6083
|
+
if (typeof self !== "undefined" && typeof self.importScripts === "function") {
|
|
6084
|
+
return "browser";
|
|
6085
|
+
}
|
|
6086
|
+
return "unknown";
|
|
6087
|
+
}
|
|
6088
|
+
function isNode() {
|
|
6089
|
+
return detectEnvironment() === "node";
|
|
6090
|
+
}
|
|
6091
|
+
function isBrowser() {
|
|
6092
|
+
return detectEnvironment() === "browser";
|
|
6093
|
+
}
|
|
6094
|
+
async function isNodeModuleAvailable(moduleName) {
|
|
6095
|
+
if (!isNode()) {
|
|
6096
|
+
return false;
|
|
6097
|
+
}
|
|
6098
|
+
try {
|
|
6099
|
+
await import(
|
|
6100
|
+
/* @vite-ignore */
|
|
6101
|
+
moduleName
|
|
6102
|
+
);
|
|
6103
|
+
return true;
|
|
6104
|
+
} catch {
|
|
6105
|
+
return false;
|
|
6106
|
+
}
|
|
6107
|
+
}
|
|
6108
|
+
var features, constants;
|
|
6109
|
+
var init_environment = __esm({
|
|
6110
|
+
"src/utils/environment.ts"() {
|
|
6111
|
+
"use strict";
|
|
6112
|
+
features = {
|
|
6113
|
+
get hasWebWorkers() {
|
|
6114
|
+
return isBrowser() && typeof Worker !== "undefined";
|
|
6115
|
+
},
|
|
6116
|
+
get hasFileSystem() {
|
|
6117
|
+
return isNode();
|
|
6118
|
+
},
|
|
6119
|
+
get hasWebAssembly() {
|
|
6120
|
+
return typeof WebAssembly !== "undefined";
|
|
6121
|
+
},
|
|
6122
|
+
async hasBetterSqlite3() {
|
|
6123
|
+
return await isNodeModuleAvailable("better-sqlite3");
|
|
6124
|
+
}
|
|
6125
|
+
};
|
|
6126
|
+
constants = {
|
|
6127
|
+
DEFAULT_NODE_SQLITE_PATH: ":memory:",
|
|
6128
|
+
DEFAULT_BROWSER_WASM_PATH: "/sql-wasm.wasm"
|
|
6129
|
+
};
|
|
6130
|
+
}
|
|
6131
|
+
});
|
|
6132
|
+
|
|
5710
6133
|
// src/engines/SqljsEngine.ts
|
|
5711
6134
|
import initSqlJs from "sql.js";
|
|
5712
6135
|
import { Mutex } from "async-mutex";
|
|
5713
|
-
|
|
6136
|
+
async function resolveNodeWasmPath() {
|
|
6137
|
+
if (!isNode()) {
|
|
6138
|
+
return null;
|
|
6139
|
+
}
|
|
6140
|
+
try {
|
|
6141
|
+
const cjsRequire = typeof __require !== "undefined" ? __require : void 0;
|
|
6142
|
+
if (cjsRequire) {
|
|
6143
|
+
return cjsRequire.resolve("sql.js/dist/sql-wasm.wasm");
|
|
6144
|
+
}
|
|
6145
|
+
} catch {
|
|
6146
|
+
}
|
|
6147
|
+
try {
|
|
6148
|
+
const metaUrl = import.meta.url;
|
|
6149
|
+
if (metaUrl) {
|
|
6150
|
+
const { createRequire } = await import(
|
|
6151
|
+
/* @vite-ignore */
|
|
6152
|
+
"module"
|
|
6153
|
+
);
|
|
6154
|
+
const req = createRequire(metaUrl);
|
|
6155
|
+
return req.resolve("sql.js/dist/sql-wasm.wasm");
|
|
6156
|
+
}
|
|
6157
|
+
} catch {
|
|
6158
|
+
}
|
|
6159
|
+
return null;
|
|
6160
|
+
}
|
|
6161
|
+
async function preflightNodeWasm(wasmPath) {
|
|
6162
|
+
if (!isNode()) {
|
|
6163
|
+
return;
|
|
6164
|
+
}
|
|
6165
|
+
if (/^[a-z]+:\/\//i.test(wasmPath)) {
|
|
6166
|
+
return;
|
|
6167
|
+
}
|
|
6168
|
+
const { existsSync } = await import(
|
|
6169
|
+
/* @vite-ignore */
|
|
6170
|
+
"fs"
|
|
6171
|
+
);
|
|
6172
|
+
if (!existsSync(wasmPath)) {
|
|
6173
|
+
throw new Error(
|
|
6174
|
+
`[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()).`
|
|
6175
|
+
);
|
|
6176
|
+
}
|
|
6177
|
+
}
|
|
6178
|
+
async function loadSqlJsModule(locateFile) {
|
|
6179
|
+
let abortReject;
|
|
6180
|
+
const toError = (reason) => reason instanceof Error ? reason : new Error(
|
|
6181
|
+
`[SqljsEngine] sql.js aborted during initialization: ${String(
|
|
6182
|
+
reason
|
|
6183
|
+
)}`
|
|
6184
|
+
);
|
|
6185
|
+
const nodeProcess = isNode() && typeof process !== "undefined" ? process : void 0;
|
|
6186
|
+
const onUnhandled = (reason) => {
|
|
6187
|
+
const err = toError(reason);
|
|
6188
|
+
if (/Aborted/.test(err.message) || /Aborted/.test(String(reason))) {
|
|
6189
|
+
abortReject?.(err);
|
|
6190
|
+
return;
|
|
6191
|
+
}
|
|
6192
|
+
if (nodeProcess && nodeProcess.listenerCount("unhandledRejection") === 1) {
|
|
6193
|
+
nodeProcess.removeListener("unhandledRejection", onUnhandled);
|
|
6194
|
+
void Promise.reject(reason);
|
|
6195
|
+
}
|
|
6196
|
+
};
|
|
6197
|
+
if (nodeProcess) {
|
|
6198
|
+
nodeProcess.on("unhandledRejection", onUnhandled);
|
|
6199
|
+
}
|
|
6200
|
+
const abortGuard = new Promise((_resolve, reject) => {
|
|
6201
|
+
abortReject = reject;
|
|
6202
|
+
});
|
|
6203
|
+
abortGuard.catch(() => {
|
|
6204
|
+
});
|
|
6205
|
+
try {
|
|
6206
|
+
const initPromise = initSqlJs({
|
|
6207
|
+
locateFile,
|
|
6208
|
+
// Layer 1: emscripten onAbort.
|
|
6209
|
+
onAbort: (reason) => abortReject?.(toError(reason))
|
|
6210
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6211
|
+
});
|
|
6212
|
+
return await Promise.race([initPromise, abortGuard]);
|
|
6213
|
+
} finally {
|
|
6214
|
+
if (nodeProcess) {
|
|
6215
|
+
setTimeout(() => {
|
|
6216
|
+
nodeProcess.removeListener("unhandledRejection", onUnhandled);
|
|
6217
|
+
}, 0);
|
|
6218
|
+
}
|
|
6219
|
+
}
|
|
6220
|
+
}
|
|
6221
|
+
var SQL_WASM_URL, SQL_WASM_FILENAME, TransactionalSQLJSOperations, SqljsEngine;
|
|
5714
6222
|
var init_SqljsEngine = __esm({
|
|
5715
6223
|
"src/engines/SqljsEngine.ts"() {
|
|
5716
6224
|
"use strict";
|
|
5717
6225
|
init_BaseModel();
|
|
5718
6226
|
init_sql();
|
|
6227
|
+
init_environment();
|
|
5719
6228
|
SQL_WASM_URL = "/sql-wasm.wasm";
|
|
6229
|
+
SQL_WASM_FILENAME = "sql-wasm.wasm";
|
|
5720
6230
|
TransactionalSQLJSOperations = class {
|
|
5721
6231
|
db;
|
|
5722
6232
|
engine;
|
|
@@ -5782,22 +6292,37 @@ var init_SqljsEngine = __esm({
|
|
|
5782
6292
|
}
|
|
5783
6293
|
async initialize(engineOptions) {
|
|
5784
6294
|
Logger.info("[SqljsEngine] Initializing SQL.js engine...");
|
|
6295
|
+
const loadingModuleThisCall = !_SqljsEngine.SQL;
|
|
5785
6296
|
try {
|
|
5786
6297
|
if (!_SqljsEngine.SQL) {
|
|
5787
|
-
|
|
6298
|
+
let locateFileConfig;
|
|
6299
|
+
if (engineOptions?.locateFile) {
|
|
6300
|
+
locateFileConfig = engineOptions.locateFile;
|
|
6301
|
+
} else if (engineOptions?.wasmURL) {
|
|
6302
|
+
const url = engineOptions.wasmURL;
|
|
6303
|
+
locateFileConfig = (_file) => url;
|
|
6304
|
+
} else {
|
|
6305
|
+
const nodeWasmPath = await resolveNodeWasmPath();
|
|
6306
|
+
const resolved = nodeWasmPath ?? SQL_WASM_URL;
|
|
6307
|
+
locateFileConfig = (_file) => resolved;
|
|
6308
|
+
}
|
|
6309
|
+
const wasmPath = locateFileConfig(SQL_WASM_FILENAME);
|
|
5788
6310
|
Logger.debug(
|
|
5789
6311
|
"[SqljsEngine] Attempting to load SQL.js WASM from:",
|
|
5790
|
-
|
|
6312
|
+
wasmPath
|
|
5791
6313
|
);
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
6314
|
+
await preflightNodeWasm(wasmPath);
|
|
6315
|
+
const SQL = await loadSqlJsModule(locateFileConfig);
|
|
6316
|
+
_SqljsEngine.SQL = SQL;
|
|
5795
6317
|
Logger.info("[SqljsEngine] SQL.js WASM loaded successfully.");
|
|
5796
6318
|
}
|
|
5797
6319
|
this.db = new _SqljsEngine.SQL.Database();
|
|
5798
6320
|
Logger.info("[SqljsEngine] SQL.js Database initialized in memory.");
|
|
5799
6321
|
this.updateTableNames();
|
|
5800
6322
|
} catch (error) {
|
|
6323
|
+
if (loadingModuleThisCall) {
|
|
6324
|
+
_SqljsEngine.SQL = null;
|
|
6325
|
+
}
|
|
5801
6326
|
Logger.error("[SqljsEngine] Error during SQL.js initialization:", error);
|
|
5802
6327
|
throw error;
|
|
5803
6328
|
}
|
|
@@ -6085,73 +6610,6 @@ var init_SqljsEngine = __esm({
|
|
|
6085
6610
|
}
|
|
6086
6611
|
});
|
|
6087
6612
|
|
|
6088
|
-
// src/utils/environment.ts
|
|
6089
|
-
var environment_exports = {};
|
|
6090
|
-
__export(environment_exports, {
|
|
6091
|
-
constants: () => constants,
|
|
6092
|
-
detectEnvironment: () => detectEnvironment,
|
|
6093
|
-
features: () => features,
|
|
6094
|
-
isBrowser: () => isBrowser,
|
|
6095
|
-
isNode: () => isNode,
|
|
6096
|
-
isNodeModuleAvailable: () => isNodeModuleAvailable
|
|
6097
|
-
});
|
|
6098
|
-
function detectEnvironment() {
|
|
6099
|
-
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
6100
|
-
return "node";
|
|
6101
|
-
}
|
|
6102
|
-
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
6103
|
-
return "browser";
|
|
6104
|
-
}
|
|
6105
|
-
if (typeof self !== "undefined" && typeof self.importScripts === "function") {
|
|
6106
|
-
return "browser";
|
|
6107
|
-
}
|
|
6108
|
-
return "unknown";
|
|
6109
|
-
}
|
|
6110
|
-
function isNode() {
|
|
6111
|
-
return detectEnvironment() === "node";
|
|
6112
|
-
}
|
|
6113
|
-
function isBrowser() {
|
|
6114
|
-
return detectEnvironment() === "browser";
|
|
6115
|
-
}
|
|
6116
|
-
async function isNodeModuleAvailable(moduleName) {
|
|
6117
|
-
if (!isNode()) {
|
|
6118
|
-
return false;
|
|
6119
|
-
}
|
|
6120
|
-
try {
|
|
6121
|
-
await import(
|
|
6122
|
-
/* @vite-ignore */
|
|
6123
|
-
moduleName
|
|
6124
|
-
);
|
|
6125
|
-
return true;
|
|
6126
|
-
} catch {
|
|
6127
|
-
return false;
|
|
6128
|
-
}
|
|
6129
|
-
}
|
|
6130
|
-
var features, constants;
|
|
6131
|
-
var init_environment = __esm({
|
|
6132
|
-
"src/utils/environment.ts"() {
|
|
6133
|
-
"use strict";
|
|
6134
|
-
features = {
|
|
6135
|
-
get hasWebWorkers() {
|
|
6136
|
-
return isBrowser() && typeof Worker !== "undefined";
|
|
6137
|
-
},
|
|
6138
|
-
get hasFileSystem() {
|
|
6139
|
-
return isNode();
|
|
6140
|
-
},
|
|
6141
|
-
get hasWebAssembly() {
|
|
6142
|
-
return typeof WebAssembly !== "undefined";
|
|
6143
|
-
},
|
|
6144
|
-
async hasBetterSqlite3() {
|
|
6145
|
-
return await isNodeModuleAvailable("better-sqlite3");
|
|
6146
|
-
}
|
|
6147
|
-
};
|
|
6148
|
-
constants = {
|
|
6149
|
-
DEFAULT_NODE_SQLITE_PATH: ":memory:",
|
|
6150
|
-
DEFAULT_BROWSER_WASM_PATH: "/sql-wasm.wasm"
|
|
6151
|
-
};
|
|
6152
|
-
}
|
|
6153
|
-
});
|
|
6154
|
-
|
|
6155
6613
|
// src/engines/node/NodeSqliteEngine.ts
|
|
6156
6614
|
var NodeSqliteEngine_exports = {};
|
|
6157
6615
|
__export(NodeSqliteEngine_exports, {
|
|
@@ -7095,6 +7553,7 @@ init_StringSet();
|
|
|
7095
7553
|
// src/models/schema.ts
|
|
7096
7554
|
init_BaseModel();
|
|
7097
7555
|
init_ModelRegistry();
|
|
7556
|
+
init_uniqueIndex();
|
|
7098
7557
|
function defineModelSchema(input) {
|
|
7099
7558
|
const { name, fields } = input;
|
|
7100
7559
|
const options = {
|
|
@@ -7167,7 +7626,7 @@ function resolveUniqueConstraints(modelName, fields, customConstraints) {
|
|
|
7167
7626
|
for (const [fieldName, options] of fields.entries()) {
|
|
7168
7627
|
if (options.unique) {
|
|
7169
7628
|
resolved.push({
|
|
7170
|
-
name:
|
|
7629
|
+
name: fieldUniqueConstraintName(modelName, fieldName),
|
|
7171
7630
|
fields: [fieldName]
|
|
7172
7631
|
});
|
|
7173
7632
|
}
|
|
@@ -7232,7 +7691,7 @@ function attachAndRegisterModel(modelClass, schema) {
|
|
|
7232
7691
|
|
|
7233
7692
|
// src/utils/yDocSchema.ts
|
|
7234
7693
|
init_yjsValues();
|
|
7235
|
-
import * as
|
|
7694
|
+
import * as Y6 from "yjs";
|
|
7236
7695
|
function discoverSchema(yDoc) {
|
|
7237
7696
|
const models = {};
|
|
7238
7697
|
const metaNames = /* @__PURE__ */ new Set();
|
|
@@ -7266,7 +7725,7 @@ function discoverModelNames(yDoc) {
|
|
|
7266
7725
|
function materializeMap(yDoc, key) {
|
|
7267
7726
|
try {
|
|
7268
7727
|
const map = yDoc.getMap(key);
|
|
7269
|
-
return map instanceof
|
|
7728
|
+
return map instanceof Y6.Map ? map : null;
|
|
7270
7729
|
} catch {
|
|
7271
7730
|
return null;
|
|
7272
7731
|
}
|
|
@@ -7276,11 +7735,11 @@ function readModelMeta(metaMap) {
|
|
|
7276
7735
|
let constraints;
|
|
7277
7736
|
let relationships;
|
|
7278
7737
|
for (const [key, value] of metaMap.entries()) {
|
|
7279
|
-
if (key === "_constraints" && value instanceof
|
|
7738
|
+
if (key === "_constraints" && value instanceof Y6.Map) {
|
|
7280
7739
|
constraints = readConstraints(value);
|
|
7281
|
-
} else if (key === "_relationships" && value instanceof
|
|
7740
|
+
} else if (key === "_relationships" && value instanceof Y6.Map) {
|
|
7282
7741
|
relationships = readRelationships(value);
|
|
7283
|
-
} else if (value instanceof
|
|
7742
|
+
} else if (value instanceof Y6.Map) {
|
|
7284
7743
|
fields[key] = readFieldMeta(value);
|
|
7285
7744
|
}
|
|
7286
7745
|
}
|
|
@@ -7315,7 +7774,7 @@ function inferModelFromData(dataMap) {
|
|
|
7315
7774
|
const fields = {};
|
|
7316
7775
|
let sampled = 0;
|
|
7317
7776
|
for (const [_recordId, recordValue] of dataMap.entries()) {
|
|
7318
|
-
if (!(recordValue instanceof
|
|
7777
|
+
if (!(recordValue instanceof Y6.Map)) continue;
|
|
7319
7778
|
if (++sampled > 5) break;
|
|
7320
7779
|
for (const [fieldName, value] of recordValue.entries()) {
|
|
7321
7780
|
if (fieldName.startsWith("_")) continue;
|
|
@@ -7343,7 +7802,7 @@ function inferTypeFromValue(value) {
|
|
|
7343
7802
|
function readConstraints(constraintsMap) {
|
|
7344
7803
|
const out = {};
|
|
7345
7804
|
for (const [name, value] of constraintsMap.entries()) {
|
|
7346
|
-
if (!(value instanceof
|
|
7805
|
+
if (!(value instanceof Y6.Map)) continue;
|
|
7347
7806
|
let fields = [];
|
|
7348
7807
|
const rawFields = value.get("fields");
|
|
7349
7808
|
if (typeof rawFields === "string") {
|
|
@@ -7362,7 +7821,7 @@ function readConstraints(constraintsMap) {
|
|
|
7362
7821
|
function readRelationships(relsMap) {
|
|
7363
7822
|
const out = {};
|
|
7364
7823
|
for (const [name, value] of relsMap.entries()) {
|
|
7365
|
-
if (!(value instanceof
|
|
7824
|
+
if (!(value instanceof Y6.Map)) continue;
|
|
7366
7825
|
const rel = {};
|
|
7367
7826
|
for (const [k, v] of value.entries()) {
|
|
7368
7827
|
rel[k] = v;
|
|
@@ -7658,18 +8117,19 @@ async function loadSchemaFromToml(filePath, options = {}) {
|
|
|
7658
8117
|
|
|
7659
8118
|
// src/node.ts
|
|
7660
8119
|
init_metaSync();
|
|
8120
|
+
init_writeLifecycle();
|
|
7661
8121
|
|
|
7662
8122
|
// src/utils/yDocDump.ts
|
|
7663
|
-
import * as
|
|
8123
|
+
import * as Y7 from "yjs";
|
|
7664
8124
|
function toPlain(value) {
|
|
7665
|
-
if (value instanceof
|
|
8125
|
+
if (value instanceof Y7.Map) {
|
|
7666
8126
|
const obj = {};
|
|
7667
8127
|
value.forEach((v, k) => {
|
|
7668
8128
|
obj[k] = toPlain(v);
|
|
7669
8129
|
});
|
|
7670
8130
|
return obj;
|
|
7671
8131
|
}
|
|
7672
|
-
if (value instanceof
|
|
8132
|
+
if (value instanceof Y7.Array) {
|
|
7673
8133
|
return value.toArray().map((item) => toPlain(item));
|
|
7674
8134
|
}
|
|
7675
8135
|
return value;
|
|
@@ -7678,7 +8138,7 @@ function dumpYDocToPlain(yDoc, options = {}) {
|
|
|
7678
8138
|
const result = {};
|
|
7679
8139
|
const includeIndexes = !!options.includeIndexes;
|
|
7680
8140
|
yDoc.share.forEach((type, name) => {
|
|
7681
|
-
if (!(type instanceof
|
|
8141
|
+
if (!(type instanceof Y7.Map)) return;
|
|
7682
8142
|
if (!includeIndexes && name.startsWith("_uniqueIdx_")) return;
|
|
7683
8143
|
const records = {};
|
|
7684
8144
|
type.forEach((recordValue, recordId) => {
|
|
@@ -7738,31 +8198,45 @@ export {
|
|
|
7738
8198
|
SqljsEngine,
|
|
7739
8199
|
StringSet,
|
|
7740
8200
|
UniqueConstraintViolationError,
|
|
8201
|
+
applyAutoStampsFromSchema,
|
|
8202
|
+
applyDefaultsFromSchema,
|
|
8203
|
+
applyStringSetChange,
|
|
8204
|
+
applyStringSetDelta,
|
|
8205
|
+
assertNever,
|
|
7741
8206
|
attachAndRegisterModel,
|
|
7742
8207
|
attachSchemaToClass,
|
|
7743
8208
|
autoRegisterModel,
|
|
7744
8209
|
clearMetaSyncCache,
|
|
7745
8210
|
constants,
|
|
7746
8211
|
createModelClass,
|
|
8212
|
+
decodeFunctionDefault,
|
|
7747
8213
|
defineModelSchema,
|
|
7748
8214
|
detectEnvironment,
|
|
7749
8215
|
discoverModelNames,
|
|
7750
8216
|
discoverSchema,
|
|
7751
8217
|
dumpYDocToPlain,
|
|
8218
|
+
ensureStringSetYMap,
|
|
7752
8219
|
features,
|
|
8220
|
+
fieldWriteKind,
|
|
7753
8221
|
generateULID,
|
|
7754
8222
|
getRecommendedNodeEngine,
|
|
7755
8223
|
inferFieldType,
|
|
7756
8224
|
initJsBao,
|
|
7757
8225
|
isBrowser,
|
|
8226
|
+
isKnownFieldType,
|
|
7758
8227
|
isNode,
|
|
7759
8228
|
isNodeModuleAvailable,
|
|
7760
8229
|
loadSchemaFromToml,
|
|
7761
8230
|
loadSchemaFromTomlString,
|
|
8231
|
+
parseStringSetOp,
|
|
7762
8232
|
registerFunctionDefault,
|
|
8233
|
+
registerFunctionDefaultGenerator,
|
|
8234
|
+
replaceStringSet,
|
|
7763
8235
|
resetJsBao,
|
|
8236
|
+
resolveDefaultValue,
|
|
7764
8237
|
schemaToToml,
|
|
7765
8238
|
summarizePlainYDoc,
|
|
7766
8239
|
syncInferredMeta,
|
|
7767
|
-
syncModelMeta
|
|
8240
|
+
syncModelMeta,
|
|
8241
|
+
writeField
|
|
7768
8242
|
};
|