js-bao 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/codegen.cjs CHANGED
@@ -1189,7 +1189,7 @@ var SchemaExtractor = class {
1189
1189
  // package.json
1190
1190
  var package_default = {
1191
1191
  name: "js-bao",
1192
- version: "0.3.0",
1192
+ version: "0.3.1",
1193
1193
  description: "A library providing data modeling capabilities which support live updates and queries.",
1194
1194
  types: "dist/index.d.ts",
1195
1195
  type: "module",
@@ -1245,17 +1245,17 @@ var package_default = {
1245
1245
  scripts: {
1246
1246
  build: "pnpm build:cli && pnpm codegen && rm -f dist/index.* dist/node.* dist/browser.* dist/cloudflare.* dist/cloudflare-do.* dist/client.* && pnpm build:main",
1247
1247
  "build:main": "pnpm build:browser && pnpm build:node && pnpm build:universal && pnpm build:cloudflare && pnpm build:cloudflare-do && pnpm build:client",
1248
- "build:browser": "tsup src/browser.ts --format esm,cjs --dts --platform browser --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --no-splitting",
1248
+ "build:browser": "tsup src/browser.ts --format esm,cjs --dts --platform browser --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --external fs --no-splitting",
1249
1249
  "build:node": "tsup src/node.ts --format esm,cjs --dts --platform node --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --no-splitting",
1250
1250
  "build:universal": "tsup src/index.ts --format esm,cjs --dts --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --no-splitting",
1251
- "build:cloudflare": "tsup src/cloudflare.ts --format esm,cjs --dts --platform browser --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --no-splitting",
1252
- "build:cloudflare-do": "tsup src/cloudflare-do.ts --format esm,cjs --dts --platform neutral --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --no-splitting",
1253
- "build:client": "tsup src/client.ts --format esm,cjs --dts --platform browser --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --no-splitting",
1251
+ "build:cloudflare": "tsup src/cloudflare.ts --format esm,cjs --dts --platform browser --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --external fs --no-splitting",
1252
+ "build:cloudflare-do": "tsup src/cloudflare-do.ts --format esm,cjs --dts --platform neutral --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --external fs --no-splitting",
1253
+ "build:client": "tsup src/client.ts --format esm,cjs --dts --platform browser --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --external fs --no-splitting",
1254
1254
  "build:cli": "tsup src/cli/codegen.ts --format cjs --dts --platform node --target node18 --external commander --external typescript --external fs --external path --external util --no-splitting",
1255
1255
  dev: 'pnpm build:cli && concurrently "pnpm codegen:watch" "pnpm dev:main"',
1256
1256
  "dev:main": 'concurrently "pnpm build:browser:dev --watch" "pnpm build:node:dev --watch" "pnpm build:universal:dev --watch"',
1257
1257
  "dev:simple": "pnpm build:cli && pnpm codegen && pnpm build:main --watch",
1258
- "build:browser:dev": "tsup src/browser.ts --format esm,cjs --dts --sourcemap --platform browser --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs",
1258
+ "build:browser:dev": "tsup src/browser.ts --format esm,cjs --dts --sourcemap --platform browser --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs --external fs",
1259
1259
  "build:node:dev": "tsup src/node.ts --format esm,cjs --dts --sourcemap --platform node --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs",
1260
1260
  "build:universal:dev": "tsup src/index.ts --format esm,cjs --dts --sourcemap --external better-sqlite3 --external sql.js --external async-mutex --external ulid --external yjs",
1261
1261
  codegen: "./dist/codegen.cjs --config js-bao.config.cjs || echo 'Codegen skipped (likely in consumer project)'",
package/dist/index.cjs CHANGED
@@ -7338,32 +7338,41 @@ var Y3 = __toESM(require("yjs"), 1);
7338
7338
  function discoverSchema(yDoc) {
7339
7339
  const models = {};
7340
7340
  const metaNames = /* @__PURE__ */ new Set();
7341
- for (const [key, type] of yDoc.share.entries()) {
7341
+ for (const key of yDoc.share.keys()) {
7342
7342
  if (!key.startsWith("_meta_")) continue;
7343
- if (!(type instanceof Y3.Map)) continue;
7343
+ const map = materializeMap(yDoc, key);
7344
+ if (!map) continue;
7344
7345
  const modelName = key.slice("_meta_".length);
7345
7346
  metaNames.add(modelName);
7346
- models[modelName] = readModelMeta(type);
7347
+ models[modelName] = readModelMeta(map);
7347
7348
  }
7348
- for (const [key, type] of yDoc.share.entries()) {
7349
+ for (const key of yDoc.share.keys()) {
7349
7350
  if (key.startsWith("_")) continue;
7350
- if (!(type instanceof Y3.Map)) continue;
7351
7351
  if (metaNames.has(key)) continue;
7352
- const dataMap = type;
7353
- if (dataMap.size === 0) continue;
7354
- const inferred = inferModelFromData(dataMap);
7352
+ const map = materializeMap(yDoc, key);
7353
+ if (!map || map.size === 0) continue;
7354
+ const inferred = inferModelFromData(map);
7355
7355
  if (inferred) models[key] = inferred;
7356
7356
  }
7357
7357
  return { models };
7358
7358
  }
7359
7359
  function discoverModelNames(yDoc) {
7360
7360
  const names = [];
7361
- for (const [key, type] of yDoc.share.entries()) {
7361
+ for (const key of yDoc.share.keys()) {
7362
7362
  if (key.startsWith("_")) continue;
7363
- if (type instanceof Y3.Map) names.push(key);
7363
+ const map = materializeMap(yDoc, key);
7364
+ if (map) names.push(key);
7364
7365
  }
7365
7366
  return names.sort();
7366
7367
  }
7368
+ function materializeMap(yDoc, key) {
7369
+ try {
7370
+ const map = yDoc.getMap(key);
7371
+ return map instanceof Y3.Map ? map : null;
7372
+ } catch {
7373
+ return null;
7374
+ }
7375
+ }
7367
7376
  function readModelMeta(metaMap) {
7368
7377
  const fields = {};
7369
7378
  let constraints;
package/dist/index.js CHANGED
@@ -7278,32 +7278,41 @@ import * as Y3 from "yjs";
7278
7278
  function discoverSchema(yDoc) {
7279
7279
  const models = {};
7280
7280
  const metaNames = /* @__PURE__ */ new Set();
7281
- for (const [key, type] of yDoc.share.entries()) {
7281
+ for (const key of yDoc.share.keys()) {
7282
7282
  if (!key.startsWith("_meta_")) continue;
7283
- if (!(type instanceof Y3.Map)) continue;
7283
+ const map = materializeMap(yDoc, key);
7284
+ if (!map) continue;
7284
7285
  const modelName = key.slice("_meta_".length);
7285
7286
  metaNames.add(modelName);
7286
- models[modelName] = readModelMeta(type);
7287
+ models[modelName] = readModelMeta(map);
7287
7288
  }
7288
- for (const [key, type] of yDoc.share.entries()) {
7289
+ for (const key of yDoc.share.keys()) {
7289
7290
  if (key.startsWith("_")) continue;
7290
- if (!(type instanceof Y3.Map)) continue;
7291
7291
  if (metaNames.has(key)) continue;
7292
- const dataMap = type;
7293
- if (dataMap.size === 0) continue;
7294
- const inferred = inferModelFromData(dataMap);
7292
+ const map = materializeMap(yDoc, key);
7293
+ if (!map || map.size === 0) continue;
7294
+ const inferred = inferModelFromData(map);
7295
7295
  if (inferred) models[key] = inferred;
7296
7296
  }
7297
7297
  return { models };
7298
7298
  }
7299
7299
  function discoverModelNames(yDoc) {
7300
7300
  const names = [];
7301
- for (const [key, type] of yDoc.share.entries()) {
7301
+ for (const key of yDoc.share.keys()) {
7302
7302
  if (key.startsWith("_")) continue;
7303
- if (type instanceof Y3.Map) names.push(key);
7303
+ const map = materializeMap(yDoc, key);
7304
+ if (map) names.push(key);
7304
7305
  }
7305
7306
  return names.sort();
7306
7307
  }
7308
+ function materializeMap(yDoc, key) {
7309
+ try {
7310
+ const map = yDoc.getMap(key);
7311
+ return map instanceof Y3.Map ? map : null;
7312
+ } catch {
7313
+ return null;
7314
+ }
7315
+ }
7307
7316
  function readModelMeta(metaMap) {
7308
7317
  const fields = {};
7309
7318
  let constraints;
package/dist/node.cjs CHANGED
@@ -1184,6 +1184,19 @@ var init_DocumentQueryTranslator = __esm({
1184
1184
  });
1185
1185
 
1186
1186
  // src/models/metaSync.ts
1187
+ function inferFieldType(value) {
1188
+ if (value instanceof Y.Map) return "stringset";
1189
+ switch (typeof value) {
1190
+ case "string":
1191
+ return "string";
1192
+ case "number":
1193
+ return "number";
1194
+ case "boolean":
1195
+ return "boolean";
1196
+ default:
1197
+ return null;
1198
+ }
1199
+ }
1187
1200
  function registerFunctionDefault(fn, name) {
1188
1201
  KNOWN_FUNCTION_DEFAULTS.set(fn, name);
1189
1202
  }
@@ -1195,6 +1208,11 @@ function encodeDefault(value) {
1195
1208
  }
1196
1209
  return value;
1197
1210
  }
1211
+ function clearMetaSyncCache(yDoc) {
1212
+ if (yDoc) {
1213
+ _syncedCache.delete(yDoc);
1214
+ }
1215
+ }
1198
1216
  function syncModelMeta(yDoc, modelName, schema) {
1199
1217
  let synced = _syncedCache.get(yDoc);
1200
1218
  if (synced?.has(modelName)) return;
@@ -1270,6 +1288,23 @@ function syncRelationshipMeta(relsMap, relName, relConfig) {
1270
1288
  }
1271
1289
  }
1272
1290
  }
1291
+ function syncInferredMeta(yDoc, modelName, recordData) {
1292
+ const meta = yDoc.getMap(`_meta_${modelName}`);
1293
+ for (const [fieldName, value] of Object.entries(recordData)) {
1294
+ if (fieldName.startsWith("_")) continue;
1295
+ let fieldMeta = meta.get(fieldName);
1296
+ if (!fieldMeta) {
1297
+ fieldMeta = new Y.Map();
1298
+ meta.set(fieldName, fieldMeta);
1299
+ }
1300
+ if (!fieldMeta.has("type")) {
1301
+ const inferredType = inferFieldType(value);
1302
+ if (inferredType) {
1303
+ fieldMeta.set("type", inferredType);
1304
+ }
1305
+ }
1306
+ }
1307
+ }
1273
1308
  function setIfChanged(map, key, value) {
1274
1309
  if (map.get(key) !== value) {
1275
1310
  map.set(key, value);
@@ -6638,20 +6673,30 @@ __export(node_exports, {
6638
6673
  attachAndRegisterModel: () => attachAndRegisterModel,
6639
6674
  attachSchemaToClass: () => attachSchemaToClass,
6640
6675
  autoRegisterModel: () => autoRegisterModel,
6676
+ clearMetaSyncCache: () => clearMetaSyncCache,
6641
6677
  constants: () => constants,
6642
6678
  createModelClass: () => createModelClass,
6643
6679
  defineModelSchema: () => defineModelSchema,
6644
6680
  detectEnvironment: () => detectEnvironment,
6681
+ discoverModelNames: () => discoverModelNames,
6682
+ discoverSchema: () => discoverSchema,
6645
6683
  dumpYDocToPlain: () => dumpYDocToPlain,
6646
6684
  features: () => features,
6647
6685
  generateULID: () => generateULID,
6648
6686
  getRecommendedNodeEngine: () => getRecommendedNodeEngine,
6687
+ inferFieldType: () => inferFieldType,
6649
6688
  initJsBao: () => initJsBao,
6650
6689
  isBrowser: () => isBrowser,
6651
6690
  isNode: () => isNode,
6652
6691
  isNodeModuleAvailable: () => isNodeModuleAvailable,
6692
+ loadSchemaFromToml: () => loadSchemaFromToml,
6693
+ loadSchemaFromTomlString: () => loadSchemaFromTomlString,
6694
+ registerFunctionDefault: () => registerFunctionDefault,
6653
6695
  resetJsBao: () => resetJsBao,
6654
- summarizePlainYDoc: () => summarizePlainYDoc
6696
+ schemaToToml: () => schemaToToml,
6697
+ summarizePlainYDoc: () => summarizePlainYDoc,
6698
+ syncInferredMeta: () => syncInferredMeta,
6699
+ syncModelMeta: () => syncModelMeta
6655
6700
  });
6656
6701
  module.exports = __toCommonJS(node_exports);
6657
6702
  init_BaseModel();
@@ -7182,17 +7227,344 @@ function attachAndRegisterModel(modelClass, schema) {
7182
7227
  autoRegisterModel(modelClass, runtimeShape);
7183
7228
  }
7184
7229
 
7185
- // src/utils/yDocDump.ts
7230
+ // src/utils/yDocSchema.ts
7186
7231
  var Y3 = __toESM(require("yjs"), 1);
7232
+ function discoverSchema(yDoc) {
7233
+ const models = {};
7234
+ const metaNames = /* @__PURE__ */ new Set();
7235
+ for (const key of yDoc.share.keys()) {
7236
+ if (!key.startsWith("_meta_")) continue;
7237
+ const map = materializeMap(yDoc, key);
7238
+ if (!map) continue;
7239
+ const modelName = key.slice("_meta_".length);
7240
+ metaNames.add(modelName);
7241
+ models[modelName] = readModelMeta(map);
7242
+ }
7243
+ for (const key of yDoc.share.keys()) {
7244
+ if (key.startsWith("_")) continue;
7245
+ if (metaNames.has(key)) continue;
7246
+ const map = materializeMap(yDoc, key);
7247
+ if (!map || map.size === 0) continue;
7248
+ const inferred = inferModelFromData(map);
7249
+ if (inferred) models[key] = inferred;
7250
+ }
7251
+ return { models };
7252
+ }
7253
+ function discoverModelNames(yDoc) {
7254
+ const names = [];
7255
+ for (const key of yDoc.share.keys()) {
7256
+ if (key.startsWith("_")) continue;
7257
+ const map = materializeMap(yDoc, key);
7258
+ if (map) names.push(key);
7259
+ }
7260
+ return names.sort();
7261
+ }
7262
+ function materializeMap(yDoc, key) {
7263
+ try {
7264
+ const map = yDoc.getMap(key);
7265
+ return map instanceof Y3.Map ? map : null;
7266
+ } catch {
7267
+ return null;
7268
+ }
7269
+ }
7270
+ function readModelMeta(metaMap) {
7271
+ const fields = {};
7272
+ let constraints;
7273
+ let relationships;
7274
+ for (const [key, value] of metaMap.entries()) {
7275
+ if (key === "_constraints" && value instanceof Y3.Map) {
7276
+ constraints = readConstraints(value);
7277
+ } else if (key === "_relationships" && value instanceof Y3.Map) {
7278
+ relationships = readRelationships(value);
7279
+ } else if (value instanceof Y3.Map) {
7280
+ fields[key] = readFieldMeta(value);
7281
+ }
7282
+ }
7283
+ const model = { fields };
7284
+ if (constraints && Object.keys(constraints).length > 0) {
7285
+ model.constraints = constraints;
7286
+ }
7287
+ if (relationships && Object.keys(relationships).length > 0) {
7288
+ model.relationships = relationships;
7289
+ }
7290
+ return model;
7291
+ }
7292
+ function readFieldMeta(fieldMap) {
7293
+ const field = { type: fieldMap.get("type") ?? "unknown" };
7294
+ if (fieldMap.get("indexed") === true) field.indexed = true;
7295
+ if (fieldMap.get("unique") === true) field.unique = true;
7296
+ if (fieldMap.get("required") === true) field.required = true;
7297
+ if (fieldMap.get("autoAssign") === true) field.autoAssign = true;
7298
+ const def = fieldMap.get("default");
7299
+ if (def !== void 0) field.default = def;
7300
+ const maxLength = fieldMap.get("maxLength");
7301
+ if (maxLength !== void 0) field.maxLength = maxLength;
7302
+ const maxCount = fieldMap.get("maxCount");
7303
+ if (maxCount !== void 0) field.maxCount = maxCount;
7304
+ return field;
7305
+ }
7306
+ function inferModelFromData(dataMap) {
7307
+ const fields = {};
7308
+ let sampled = 0;
7309
+ for (const [_recordId, recordValue] of dataMap.entries()) {
7310
+ if (!(recordValue instanceof Y3.Map)) continue;
7311
+ if (++sampled > 5) break;
7312
+ for (const [fieldName, value] of recordValue.entries()) {
7313
+ if (fieldName.startsWith("_")) continue;
7314
+ if (fields[fieldName]) continue;
7315
+ const type = inferTypeFromValue(value);
7316
+ if (type) fields[fieldName] = { type };
7317
+ }
7318
+ }
7319
+ if (Object.keys(fields).length === 0) return null;
7320
+ return { fields };
7321
+ }
7322
+ function inferTypeFromValue(value) {
7323
+ if (value instanceof Y3.Map) return "stringset";
7324
+ switch (typeof value) {
7325
+ case "string":
7326
+ return "string";
7327
+ case "number":
7328
+ return "number";
7329
+ case "boolean":
7330
+ return "boolean";
7331
+ default:
7332
+ return null;
7333
+ }
7334
+ }
7335
+ function readConstraints(constraintsMap) {
7336
+ const out = {};
7337
+ for (const [name, value] of constraintsMap.entries()) {
7338
+ if (!(value instanceof Y3.Map)) continue;
7339
+ let fields = [];
7340
+ const rawFields = value.get("fields");
7341
+ if (typeof rawFields === "string") {
7342
+ try {
7343
+ fields = JSON.parse(rawFields);
7344
+ } catch {
7345
+ }
7346
+ }
7347
+ out[name] = {
7348
+ type: value.get("type") ?? "unknown",
7349
+ fields
7350
+ };
7351
+ }
7352
+ return out;
7353
+ }
7354
+ function readRelationships(relsMap) {
7355
+ const out = {};
7356
+ for (const [name, value] of relsMap.entries()) {
7357
+ if (!(value instanceof Y3.Map)) continue;
7358
+ const rel = {};
7359
+ for (const [k, v] of value.entries()) {
7360
+ rel[k] = v;
7361
+ }
7362
+ out[name] = rel;
7363
+ }
7364
+ return out;
7365
+ }
7366
+ var CAMEL_TO_SNAKE = {
7367
+ autoAssign: "auto_assign",
7368
+ maxLength: "max_length",
7369
+ maxCount: "max_count",
7370
+ relatedIdField: "related_id_field",
7371
+ joinModel: "join_model",
7372
+ joinModelLocalField: "join_model_local_field",
7373
+ joinModelRelatedField: "join_model_related_field",
7374
+ joinModelOrderByField: "join_model_order_by_field",
7375
+ joinModelOrderDirection: "join_model_order_direction",
7376
+ orderByField: "order_by_field",
7377
+ orderDirection: "order_direction"
7378
+ };
7379
+ function toSnake(key) {
7380
+ return CAMEL_TO_SNAKE[key] ?? key;
7381
+ }
7382
+ function tomlValue(v) {
7383
+ if (typeof v === "string") {
7384
+ return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
7385
+ }
7386
+ return String(v);
7387
+ }
7388
+ function schemaToToml(schema) {
7389
+ const lines = [];
7390
+ for (const [modelName, model] of Object.entries(schema.models)) {
7391
+ if (lines.length > 0) lines.push("", "");
7392
+ lines.push(`[models.${modelName}]`);
7393
+ for (const [fieldName, field] of Object.entries(model.fields)) {
7394
+ lines.push("");
7395
+ lines.push(`[models.${modelName}.fields.${fieldName}]`);
7396
+ lines.push(`type = ${tomlValue(field.type)}`);
7397
+ if (field.autoAssign) lines.push("auto_assign = true");
7398
+ if (field.indexed) lines.push("indexed = true");
7399
+ if (field.unique) lines.push("unique = true");
7400
+ if (field.required) lines.push("required = true");
7401
+ if (field.maxLength !== void 0) lines.push(`max_length = ${field.maxLength}`);
7402
+ if (field.maxCount !== void 0) lines.push(`max_count = ${field.maxCount}`);
7403
+ if (field.default !== void 0) lines.push(`default = ${tomlValue(field.default)}`);
7404
+ }
7405
+ if (model.relationships) {
7406
+ for (const [relName, rel] of Object.entries(model.relationships)) {
7407
+ lines.push("");
7408
+ lines.push(`[models.${modelName}.relationships.${relName}]`);
7409
+ for (const [k, v] of Object.entries(rel)) {
7410
+ if (v === void 0) continue;
7411
+ lines.push(`${toSnake(k)} = ${tomlValue(v)}`);
7412
+ }
7413
+ }
7414
+ }
7415
+ if (model.constraints) {
7416
+ for (const [cName, c] of Object.entries(model.constraints)) {
7417
+ lines.push("");
7418
+ lines.push(`[[models.${modelName}.unique_constraints]]`);
7419
+ lines.push(`name = ${tomlValue(cName)}`);
7420
+ lines.push(`fields = [${c.fields.map((f) => tomlValue(f)).join(", ")}]`);
7421
+ }
7422
+ }
7423
+ }
7424
+ lines.push("");
7425
+ return lines.join("\n");
7426
+ }
7427
+
7428
+ // src/models/tomlLoader.ts
7429
+ var import_smol_toml = require("smol-toml");
7430
+ var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
7431
+ "string",
7432
+ "number",
7433
+ "boolean",
7434
+ "date",
7435
+ "id",
7436
+ "stringset"
7437
+ ]);
7438
+ function parseFieldOptions(raw) {
7439
+ if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
7440
+ throw new Error(
7441
+ `Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
7442
+ );
7443
+ }
7444
+ const opts = { type: raw.type };
7445
+ if (raw.indexed === true) opts.indexed = true;
7446
+ if (raw.unique === true) opts.unique = true;
7447
+ if (raw.required === true) opts.required = true;
7448
+ if (raw.auto_assign === true) opts.autoAssign = true;
7449
+ if (raw.max_length !== void 0) opts.maxLength = raw.max_length;
7450
+ if (raw.max_count !== void 0) opts.maxCount = raw.max_count;
7451
+ if (raw.default !== void 0) opts.default = raw.default;
7452
+ return opts;
7453
+ }
7454
+ function requireField(raw, field, context) {
7455
+ if (!raw[field]) {
7456
+ throw new Error(`Relationship ${context}: missing required field "${field}"`);
7457
+ }
7458
+ }
7459
+ function parseRelationship(raw) {
7460
+ const type = raw.type;
7461
+ if (type === "refersTo") {
7462
+ requireField(raw, "model", "refersTo");
7463
+ requireField(raw, "related_id_field", "refersTo");
7464
+ return {
7465
+ type: "refersTo",
7466
+ model: raw.model,
7467
+ relatedIdField: raw.related_id_field
7468
+ };
7469
+ }
7470
+ if (type === "hasMany") {
7471
+ requireField(raw, "model", "hasMany");
7472
+ requireField(raw, "related_id_field", "hasMany");
7473
+ const rel = {
7474
+ type: "hasMany",
7475
+ model: raw.model,
7476
+ relatedIdField: raw.related_id_field
7477
+ };
7478
+ if (raw.order_by_field) rel.orderByField = raw.order_by_field;
7479
+ if (raw.order_direction) rel.orderDirection = raw.order_direction;
7480
+ return rel;
7481
+ }
7482
+ if (type === "hasManyThrough") {
7483
+ requireField(raw, "model", "hasManyThrough");
7484
+ requireField(raw, "join_model", "hasManyThrough");
7485
+ requireField(raw, "join_model_local_field", "hasManyThrough");
7486
+ requireField(raw, "join_model_related_field", "hasManyThrough");
7487
+ const rel = {
7488
+ type: "hasManyThrough",
7489
+ model: raw.model,
7490
+ joinModel: raw.join_model,
7491
+ joinModelLocalField: raw.join_model_local_field,
7492
+ joinModelRelatedField: raw.join_model_related_field
7493
+ };
7494
+ if (raw.join_model_order_by_field)
7495
+ rel.joinModelOrderByField = raw.join_model_order_by_field;
7496
+ if (raw.join_model_order_direction)
7497
+ rel.joinModelOrderDirection = raw.join_model_order_direction;
7498
+ return rel;
7499
+ }
7500
+ throw new Error(`Unknown relationship type: ${type}`);
7501
+ }
7502
+ function loadSchemaFromTomlString(tomlString) {
7503
+ const parsed = (0, import_smol_toml.parse)(tomlString);
7504
+ const models = parsed.models;
7505
+ if (!models || typeof models !== "object") {
7506
+ throw new Error("TOML schema must have a [models] section");
7507
+ }
7508
+ const schemas = [];
7509
+ for (const [modelName, modelDef] of Object.entries(models)) {
7510
+ const fields = {};
7511
+ if (modelDef.fields) {
7512
+ for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
7513
+ fields[fieldName] = parseFieldOptions(fieldDef);
7514
+ }
7515
+ }
7516
+ let relationships;
7517
+ if (modelDef.relationships) {
7518
+ relationships = {};
7519
+ for (const [relName, relDef] of Object.entries(
7520
+ modelDef.relationships
7521
+ )) {
7522
+ relationships[relName] = parseRelationship(relDef);
7523
+ }
7524
+ }
7525
+ let uniqueConstraints;
7526
+ if (modelDef.unique_constraints) {
7527
+ uniqueConstraints = [];
7528
+ for (const raw of modelDef.unique_constraints) {
7529
+ uniqueConstraints.push({
7530
+ name: raw.name,
7531
+ fields: [...raw.fields]
7532
+ });
7533
+ }
7534
+ }
7535
+ schemas.push(
7536
+ defineModelSchema({
7537
+ name: modelName,
7538
+ fields,
7539
+ options: {
7540
+ uniqueConstraints,
7541
+ relationships
7542
+ }
7543
+ })
7544
+ );
7545
+ }
7546
+ return schemas;
7547
+ }
7548
+ async function loadSchemaFromToml(filePath) {
7549
+ const { readFile } = await import("fs/promises");
7550
+ const content = await readFile(filePath, "utf-8");
7551
+ return loadSchemaFromTomlString(content);
7552
+ }
7553
+
7554
+ // src/node.ts
7555
+ init_metaSync();
7556
+
7557
+ // src/utils/yDocDump.ts
7558
+ var Y4 = __toESM(require("yjs"), 1);
7187
7559
  function toPlain(value) {
7188
- if (value instanceof Y3.Map) {
7560
+ if (value instanceof Y4.Map) {
7189
7561
  const obj = {};
7190
7562
  value.forEach((v, k) => {
7191
7563
  obj[k] = toPlain(v);
7192
7564
  });
7193
7565
  return obj;
7194
7566
  }
7195
- if (value instanceof Y3.Array) {
7567
+ if (value instanceof Y4.Array) {
7196
7568
  return value.toArray().map((item) => toPlain(item));
7197
7569
  }
7198
7570
  return value;
@@ -7201,7 +7573,7 @@ function dumpYDocToPlain(yDoc, options = {}) {
7201
7573
  const result = {};
7202
7574
  const includeIndexes = !!options.includeIndexes;
7203
7575
  yDoc.share.forEach((type, name) => {
7204
- if (!(type instanceof Y3.Map)) return;
7576
+ if (!(type instanceof Y4.Map)) return;
7205
7577
  if (!includeIndexes && name.startsWith("_uniqueIdx_")) return;
7206
7578
  const records = {};
7207
7579
  type.forEach((recordValue, recordId) => {
@@ -7267,18 +7639,28 @@ async function getRecommendedNodeEngine() {
7267
7639
  attachAndRegisterModel,
7268
7640
  attachSchemaToClass,
7269
7641
  autoRegisterModel,
7642
+ clearMetaSyncCache,
7270
7643
  constants,
7271
7644
  createModelClass,
7272
7645
  defineModelSchema,
7273
7646
  detectEnvironment,
7647
+ discoverModelNames,
7648
+ discoverSchema,
7274
7649
  dumpYDocToPlain,
7275
7650
  features,
7276
7651
  generateULID,
7277
7652
  getRecommendedNodeEngine,
7653
+ inferFieldType,
7278
7654
  initJsBao,
7279
7655
  isBrowser,
7280
7656
  isNode,
7281
7657
  isNodeModuleAvailable,
7658
+ loadSchemaFromToml,
7659
+ loadSchemaFromTomlString,
7660
+ registerFunctionDefault,
7282
7661
  resetJsBao,
7283
- summarizePlainYDoc
7662
+ schemaToToml,
7663
+ summarizePlainYDoc,
7664
+ syncInferredMeta,
7665
+ syncModelMeta
7284
7666
  });