js-bao 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.js CHANGED
@@ -1163,6 +1163,19 @@ var init_DocumentQueryTranslator = __esm({
1163
1163
 
1164
1164
  // src/models/metaSync.ts
1165
1165
  import * as Y from "yjs";
1166
+ function inferFieldType(value) {
1167
+ if (value instanceof Y.Map) return "stringset";
1168
+ switch (typeof value) {
1169
+ case "string":
1170
+ return "string";
1171
+ case "number":
1172
+ return "number";
1173
+ case "boolean":
1174
+ return "boolean";
1175
+ default:
1176
+ return null;
1177
+ }
1178
+ }
1166
1179
  function registerFunctionDefault(fn, name) {
1167
1180
  KNOWN_FUNCTION_DEFAULTS.set(fn, name);
1168
1181
  }
@@ -1174,6 +1187,11 @@ function encodeDefault(value) {
1174
1187
  }
1175
1188
  return value;
1176
1189
  }
1190
+ function clearMetaSyncCache(yDoc) {
1191
+ if (yDoc) {
1192
+ _syncedCache.delete(yDoc);
1193
+ }
1194
+ }
1177
1195
  function syncModelMeta(yDoc, modelName, schema) {
1178
1196
  let synced = _syncedCache.get(yDoc);
1179
1197
  if (synced?.has(modelName)) return;
@@ -1249,6 +1267,23 @@ function syncRelationshipMeta(relsMap, relName, relConfig) {
1249
1267
  }
1250
1268
  }
1251
1269
  }
1270
+ function syncInferredMeta(yDoc, modelName, recordData) {
1271
+ const meta = yDoc.getMap(`_meta_${modelName}`);
1272
+ for (const [fieldName, value] of Object.entries(recordData)) {
1273
+ if (fieldName.startsWith("_")) continue;
1274
+ let fieldMeta = meta.get(fieldName);
1275
+ if (!fieldMeta) {
1276
+ fieldMeta = new Y.Map();
1277
+ meta.set(fieldName, fieldMeta);
1278
+ }
1279
+ if (!fieldMeta.has("type")) {
1280
+ const inferredType = inferFieldType(value);
1281
+ if (inferredType) {
1282
+ fieldMeta.set("type", inferredType);
1283
+ }
1284
+ }
1285
+ }
1286
+ }
1252
1287
  function setIfChanged(map, key, value) {
1253
1288
  if (map.get(key) !== value) {
1254
1289
  map.set(key, value);
@@ -1577,11 +1612,11 @@ var init_ModelRegistry = __esm({
1577
1612
  init_relationshipManager();
1578
1613
  ModelRegistry = class _ModelRegistry {
1579
1614
  static instance;
1580
- // Stores globally registered model classes by their name (from @Model decorator)
1615
+ // Stores globally registered model classes by their name
1581
1616
  models = /* @__PURE__ */ new Map();
1582
- // Stores options for globally registered models (from @Model decorator)
1617
+ // Stores options for globally registered models
1583
1618
  modelOptions = /* @__PURE__ */ new Map();
1584
- // Stores fields for globally registered models (from @Model decorator, or a static getter on class)
1619
+ // Stores fields for globally registered models (or a static getter on class)
1585
1620
  // For simplicity, let's assume fields can be derived or are less critical for this registry part
1586
1621
  // private modelFields: Map<string, Map<string, FieldOptions>> = new Map();
1587
1622
  // Holds the subset of models explicitly set for the current initialization session
@@ -1599,7 +1634,7 @@ var init_ModelRegistry = __esm({
1599
1634
  registerModel(modelClass, options, fields) {
1600
1635
  if (!options.name) {
1601
1636
  throw new Error(
1602
- `[ModelRegistry] Model class is missing a name in its @Model options. Ensure the @Model decorator includes a 'name' property.`
1637
+ `[ModelRegistry] Model class is missing a name in its options. Ensure the schema passed to defineModelSchema/createModelClass/attachAndRegisterModel includes a 'name' property.`
1603
1638
  );
1604
1639
  }
1605
1640
  if (this.models.has(options.name)) {
@@ -1643,7 +1678,7 @@ var init_ModelRegistry = __esm({
1643
1678
  }
1644
1679
  return infos;
1645
1680
  }
1646
- // Helper to get model name from class (assuming static property from @Model decorator)
1681
+ // Helper to get model name from class (set by attachAndRegisterModel/createModelClass)
1647
1682
  getModelNameFromClass(modelClass) {
1648
1683
  return modelClass.modelName;
1649
1684
  }
@@ -1654,13 +1689,13 @@ var init_ModelRegistry = __esm({
1654
1689
  const modelName = this.getModelNameFromClass(modelClass);
1655
1690
  if (!modelName) {
1656
1691
  console.warn(
1657
- `[ModelRegistry] A model class provided to setExplicitModelsForSession does not have a static 'modelName' property or it's undefined. It will be ignored. Ensure @Model decorator sets this.`
1692
+ `[ModelRegistry] A model class provided to setExplicitModelsForSession does not have a static 'modelName' property or it's undefined. It will be ignored. Ensure attachAndRegisterModel (or createModelClass) was called for this model.`
1658
1693
  );
1659
1694
  return;
1660
1695
  }
1661
1696
  if (!this.models.has(modelName) || this.models.get(modelName) !== modelClass) {
1662
1697
  console.warn(
1663
- `[ModelRegistry] Model class with name ${modelName} provided to setExplicitModelsForSession was not found in the global decorator-based registry or does not match. It will be ignored. Ensure the model file is imported and the @Model decorator has run correctly.`
1698
+ `[ModelRegistry] Model class with name ${modelName} provided to setExplicitModelsForSession was not found in the global registry or does not match. It will be ignored. Ensure the model file is imported and attachAndRegisterModel (or createModelClass) has run.`
1664
1699
  );
1665
1700
  return;
1666
1701
  }
@@ -1690,7 +1725,7 @@ var init_ModelRegistry = __esm({
1690
1725
  } else {
1691
1726
  this.activeSessionModels = null;
1692
1727
  console.log(
1693
- "[ModelRegistry] No explicit models specified for session (undefined), will use all decorator-registered models."
1728
+ "[ModelRegistry] No explicit models specified for session (undefined), will use all globally registered models."
1694
1729
  );
1695
1730
  }
1696
1731
  this.validateSessionModels();
@@ -1701,7 +1736,7 @@ var init_ModelRegistry = __esm({
1701
1736
  const modelsToInitialize = this.activeSessionModels || this.models;
1702
1737
  if (modelsToInitialize.size === 0) {
1703
1738
  console.warn(
1704
- "[ModelRegistry] No models to initialize (either no explicit models set for session or no models globally registered via @Model decorator)."
1739
+ "[ModelRegistry] No models to initialize (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
1705
1740
  );
1706
1741
  return;
1707
1742
  }
@@ -1732,7 +1767,7 @@ var init_ModelRegistry = __esm({
1732
1767
  const modelsToInitialize = this.activeSessionModels || this.models;
1733
1768
  if (modelsToInitialize.size === 0) {
1734
1769
  Logger.warn(
1735
- "[ModelRegistry] No models to initialize for document (either no explicit models set for session or no models globally registered via @Model decorator)."
1770
+ "[ModelRegistry] No models to initialize for document (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
1736
1771
  );
1737
1772
  return;
1738
1773
  }
@@ -1770,7 +1805,7 @@ var init_ModelRegistry = __esm({
1770
1805
  const modelsToCleanup = this.activeSessionModels || this.models;
1771
1806
  if (modelsToCleanup.size === 0) {
1772
1807
  console.warn(
1773
- "[ModelRegistry] No models to cleanup for document (either no explicit models set for session or no models globally registered via @Model decorator)."
1808
+ "[ModelRegistry] No models to cleanup for document (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
1774
1809
  );
1775
1810
  return;
1776
1811
  }
@@ -2534,7 +2569,7 @@ var init_BaseModel = __esm({
2534
2569
  getDocumentId() {
2535
2570
  return this._metaDocId;
2536
2571
  }
2537
- // id is now a plain property. Subclasses will define it with @Field.
2572
+ // id is a plain property. Subclasses define it via defineModelSchema.
2538
2573
  id;
2539
2574
  type;
2540
2575
  // This should be the modelName from ModelOptions
@@ -3081,7 +3116,7 @@ var init_BaseModel = __esm({
3081
3116
  const verboseEnabled = Logger.getLogLevel() >= 5 /* VERBOSE */;
3082
3117
  if (!schema || !schema.options || !schema.options.name || !schema.resolvedUniqueConstraints) {
3083
3118
  throw new Error(
3084
- `[${this.name}] Model schema is not registered, missing options, or missing resolvedUniqueConstraints. Did you forget to use the @Model decorator or has the schema structure changed?`
3119
+ `[${this.name}] Model schema is not registered, missing options, or missing resolvedUniqueConstraints. Did you forget to call attachAndRegisterModel (or autoRegisterModel) for this model?`
3085
3120
  );
3086
3121
  }
3087
3122
  const modelName = schema.options.name;
@@ -6602,131 +6637,6 @@ var init_BrowserDatabaseFactory = __esm({
6602
6637
  init_BaseModel();
6603
6638
  init_ModelRegistry();
6604
6639
 
6605
- // src/models/decorators.ts
6606
- init_ModelRegistry();
6607
- init_BaseModel();
6608
- init_sql();
6609
- var SCHEMA_FIELDS_PROPERTY = "_jsbaoSchemaFields";
6610
- function Field(options) {
6611
- return function(target, propertyKey) {
6612
- const fieldName = String(propertyKey);
6613
- const modelConstructor = target.constructor || target;
6614
- assertValidIdentifier(
6615
- fieldName,
6616
- `[Field Decorator] Invalid field name on ${modelConstructor?.name || "unknown"}`
6617
- );
6618
- if (!modelConstructor) {
6619
- console.error(
6620
- "[Field Decorator] Could not determine model constructor for field:",
6621
- fieldName,
6622
- "Target:",
6623
- target
6624
- );
6625
- throw new Error(
6626
- `Failed to resolve model constructor for field '${fieldName}'.`
6627
- );
6628
- }
6629
- if (!Object.prototype.hasOwnProperty.call(
6630
- modelConstructor,
6631
- SCHEMA_FIELDS_PROPERTY
6632
- )) {
6633
- modelConstructor[SCHEMA_FIELDS_PROPERTY] = /* @__PURE__ */ new Map();
6634
- }
6635
- modelConstructor[SCHEMA_FIELDS_PROPERTY].set(
6636
- fieldName,
6637
- options
6638
- );
6639
- Logger.debug(
6640
- `[Field Decorator] Staged field "${fieldName}" for class ${modelConstructor.name}:`,
6641
- options
6642
- );
6643
- };
6644
- }
6645
- function Model(options) {
6646
- return function(targetClass) {
6647
- Logger.debug(
6648
- `[Model Decorator] Registering model:`,
6649
- targetClass.name,
6650
- options
6651
- );
6652
- assertValidIdentifier(
6653
- options.name,
6654
- `[Model Decorator] Invalid model name for ${targetClass.name}`
6655
- );
6656
- const registry = ModelRegistry.getInstance();
6657
- targetClass.modelName = options.name;
6658
- targetClass.getSchema = () => {
6659
- const combinedFields = /* @__PURE__ */ new Map();
6660
- const hierarchyStack = [];
6661
- let currentEvalClass = targetClass;
6662
- while (currentEvalClass && currentEvalClass.prototype) {
6663
- hierarchyStack.push(currentEvalClass);
6664
- const parentPrototype = Object.getPrototypeOf(
6665
- currentEvalClass.prototype
6666
- );
6667
- currentEvalClass = parentPrototype ? parentPrototype.constructor : null;
6668
- if (currentEvalClass === Object) break;
6669
- }
6670
- for (let i = hierarchyStack.length - 1; i >= 0; i--) {
6671
- const cls = hierarchyStack[i];
6672
- if (Object.prototype.hasOwnProperty.call(cls, SCHEMA_FIELDS_PROPERTY)) {
6673
- const fieldsForClass = cls[SCHEMA_FIELDS_PROPERTY];
6674
- fieldsForClass.forEach((fieldOpts, fieldName) => {
6675
- combinedFields.set(fieldName, fieldOpts);
6676
- });
6677
- }
6678
- }
6679
- const resolvedUniqueConstraints = [];
6680
- combinedFields.forEach((fieldOpts, fieldName) => {
6681
- if (fieldOpts.unique) {
6682
- const constraintName = `${options.name}_${fieldName}_unique`;
6683
- resolvedUniqueConstraints.push({
6684
- name: constraintName,
6685
- fields: [fieldName]
6686
- });
6687
- }
6688
- });
6689
- if (options.uniqueConstraints) {
6690
- options.uniqueConstraints.forEach(
6691
- (constraintConfig) => {
6692
- const allFieldsExist = constraintConfig.fields.every(
6693
- (f) => combinedFields.has(f)
6694
- );
6695
- if (!allFieldsExist) {
6696
- console.warn(
6697
- `[Model Decorator] Unique constraint "${constraintConfig.name}" for model "${options.name}" specifies non-existent fields. Skipping.`
6698
- );
6699
- return;
6700
- }
6701
- if (resolvedUniqueConstraints.some(
6702
- (rc) => rc.name === constraintConfig.name
6703
- )) {
6704
- console.warn(
6705
- `[Model Decorator] Duplicate unique constraint name "${constraintConfig.name}" in model "${options.name}".`
6706
- );
6707
- }
6708
- resolvedUniqueConstraints.push({
6709
- name: constraintConfig.name,
6710
- fields: constraintConfig.fields
6711
- });
6712
- }
6713
- );
6714
- }
6715
- return {
6716
- class: targetClass,
6717
- options,
6718
- fields: combinedFields,
6719
- resolvedUniqueConstraints
6720
- };
6721
- };
6722
- const directFieldsForThisClass = Object.prototype.hasOwnProperty.call(
6723
- targetClass,
6724
- SCHEMA_FIELDS_PROPERTY
6725
- ) ? targetClass[SCHEMA_FIELDS_PROPERTY] : /* @__PURE__ */ new Map();
6726
- registry.registerModel(targetClass, options, directFieldsForThisClass);
6727
- };
6728
- }
6729
-
6730
6640
  // src/engines/DatabaseEngine.ts
6731
6641
  var DatabaseEngine = class {
6732
6642
  createTable(_modelName, _schema, _options) {
@@ -7127,17 +7037,344 @@ function attachAndRegisterModel(modelClass, schema) {
7127
7037
  autoRegisterModel(modelClass, runtimeShape);
7128
7038
  }
7129
7039
 
7130
- // src/utils/yDocDump.ts
7040
+ // src/utils/yDocSchema.ts
7131
7041
  import * as Y3 from "yjs";
7042
+ function discoverSchema(yDoc) {
7043
+ const models = {};
7044
+ const metaNames = /* @__PURE__ */ new Set();
7045
+ for (const key of yDoc.share.keys()) {
7046
+ if (!key.startsWith("_meta_")) continue;
7047
+ const map = materializeMap(yDoc, key);
7048
+ if (!map) continue;
7049
+ const modelName = key.slice("_meta_".length);
7050
+ metaNames.add(modelName);
7051
+ models[modelName] = readModelMeta(map);
7052
+ }
7053
+ for (const key of yDoc.share.keys()) {
7054
+ if (key.startsWith("_")) continue;
7055
+ if (metaNames.has(key)) continue;
7056
+ const map = materializeMap(yDoc, key);
7057
+ if (!map || map.size === 0) continue;
7058
+ const inferred = inferModelFromData(map);
7059
+ if (inferred) models[key] = inferred;
7060
+ }
7061
+ return { models };
7062
+ }
7063
+ function discoverModelNames(yDoc) {
7064
+ const names = [];
7065
+ for (const key of yDoc.share.keys()) {
7066
+ if (key.startsWith("_")) continue;
7067
+ const map = materializeMap(yDoc, key);
7068
+ if (map) names.push(key);
7069
+ }
7070
+ return names.sort();
7071
+ }
7072
+ function materializeMap(yDoc, key) {
7073
+ try {
7074
+ const map = yDoc.getMap(key);
7075
+ return map instanceof Y3.Map ? map : null;
7076
+ } catch {
7077
+ return null;
7078
+ }
7079
+ }
7080
+ function readModelMeta(metaMap) {
7081
+ const fields = {};
7082
+ let constraints;
7083
+ let relationships;
7084
+ for (const [key, value] of metaMap.entries()) {
7085
+ if (key === "_constraints" && value instanceof Y3.Map) {
7086
+ constraints = readConstraints(value);
7087
+ } else if (key === "_relationships" && value instanceof Y3.Map) {
7088
+ relationships = readRelationships(value);
7089
+ } else if (value instanceof Y3.Map) {
7090
+ fields[key] = readFieldMeta(value);
7091
+ }
7092
+ }
7093
+ const model = { fields };
7094
+ if (constraints && Object.keys(constraints).length > 0) {
7095
+ model.constraints = constraints;
7096
+ }
7097
+ if (relationships && Object.keys(relationships).length > 0) {
7098
+ model.relationships = relationships;
7099
+ }
7100
+ return model;
7101
+ }
7102
+ function readFieldMeta(fieldMap) {
7103
+ const field = { type: fieldMap.get("type") ?? "unknown" };
7104
+ if (fieldMap.get("indexed") === true) field.indexed = true;
7105
+ if (fieldMap.get("unique") === true) field.unique = true;
7106
+ if (fieldMap.get("required") === true) field.required = true;
7107
+ if (fieldMap.get("autoAssign") === true) field.autoAssign = true;
7108
+ const def = fieldMap.get("default");
7109
+ if (def !== void 0) field.default = def;
7110
+ const maxLength = fieldMap.get("maxLength");
7111
+ if (maxLength !== void 0) field.maxLength = maxLength;
7112
+ const maxCount = fieldMap.get("maxCount");
7113
+ if (maxCount !== void 0) field.maxCount = maxCount;
7114
+ return field;
7115
+ }
7116
+ function inferModelFromData(dataMap) {
7117
+ const fields = {};
7118
+ let sampled = 0;
7119
+ for (const [_recordId, recordValue] of dataMap.entries()) {
7120
+ if (!(recordValue instanceof Y3.Map)) continue;
7121
+ if (++sampled > 5) break;
7122
+ for (const [fieldName, value] of recordValue.entries()) {
7123
+ if (fieldName.startsWith("_")) continue;
7124
+ if (fields[fieldName]) continue;
7125
+ const type = inferTypeFromValue(value);
7126
+ if (type) fields[fieldName] = { type };
7127
+ }
7128
+ }
7129
+ if (Object.keys(fields).length === 0) return null;
7130
+ return { fields };
7131
+ }
7132
+ function inferTypeFromValue(value) {
7133
+ if (value instanceof Y3.Map) return "stringset";
7134
+ switch (typeof value) {
7135
+ case "string":
7136
+ return "string";
7137
+ case "number":
7138
+ return "number";
7139
+ case "boolean":
7140
+ return "boolean";
7141
+ default:
7142
+ return null;
7143
+ }
7144
+ }
7145
+ function readConstraints(constraintsMap) {
7146
+ const out = {};
7147
+ for (const [name, value] of constraintsMap.entries()) {
7148
+ if (!(value instanceof Y3.Map)) continue;
7149
+ let fields = [];
7150
+ const rawFields = value.get("fields");
7151
+ if (typeof rawFields === "string") {
7152
+ try {
7153
+ fields = JSON.parse(rawFields);
7154
+ } catch {
7155
+ }
7156
+ }
7157
+ out[name] = {
7158
+ type: value.get("type") ?? "unknown",
7159
+ fields
7160
+ };
7161
+ }
7162
+ return out;
7163
+ }
7164
+ function readRelationships(relsMap) {
7165
+ const out = {};
7166
+ for (const [name, value] of relsMap.entries()) {
7167
+ if (!(value instanceof Y3.Map)) continue;
7168
+ const rel = {};
7169
+ for (const [k, v] of value.entries()) {
7170
+ rel[k] = v;
7171
+ }
7172
+ out[name] = rel;
7173
+ }
7174
+ return out;
7175
+ }
7176
+ var CAMEL_TO_SNAKE = {
7177
+ autoAssign: "auto_assign",
7178
+ maxLength: "max_length",
7179
+ maxCount: "max_count",
7180
+ relatedIdField: "related_id_field",
7181
+ joinModel: "join_model",
7182
+ joinModelLocalField: "join_model_local_field",
7183
+ joinModelRelatedField: "join_model_related_field",
7184
+ joinModelOrderByField: "join_model_order_by_field",
7185
+ joinModelOrderDirection: "join_model_order_direction",
7186
+ orderByField: "order_by_field",
7187
+ orderDirection: "order_direction"
7188
+ };
7189
+ function toSnake(key) {
7190
+ return CAMEL_TO_SNAKE[key] ?? key;
7191
+ }
7192
+ function tomlValue(v) {
7193
+ if (typeof v === "string") {
7194
+ return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
7195
+ }
7196
+ return String(v);
7197
+ }
7198
+ function schemaToToml(schema) {
7199
+ const lines = [];
7200
+ for (const [modelName, model] of Object.entries(schema.models)) {
7201
+ if (lines.length > 0) lines.push("", "");
7202
+ lines.push(`[models.${modelName}]`);
7203
+ for (const [fieldName, field] of Object.entries(model.fields)) {
7204
+ lines.push("");
7205
+ lines.push(`[models.${modelName}.fields.${fieldName}]`);
7206
+ lines.push(`type = ${tomlValue(field.type)}`);
7207
+ if (field.autoAssign) lines.push("auto_assign = true");
7208
+ if (field.indexed) lines.push("indexed = true");
7209
+ if (field.unique) lines.push("unique = true");
7210
+ if (field.required) lines.push("required = true");
7211
+ if (field.maxLength !== void 0) lines.push(`max_length = ${field.maxLength}`);
7212
+ if (field.maxCount !== void 0) lines.push(`max_count = ${field.maxCount}`);
7213
+ if (field.default !== void 0) lines.push(`default = ${tomlValue(field.default)}`);
7214
+ }
7215
+ if (model.relationships) {
7216
+ for (const [relName, rel] of Object.entries(model.relationships)) {
7217
+ lines.push("");
7218
+ lines.push(`[models.${modelName}.relationships.${relName}]`);
7219
+ for (const [k, v] of Object.entries(rel)) {
7220
+ if (v === void 0) continue;
7221
+ lines.push(`${toSnake(k)} = ${tomlValue(v)}`);
7222
+ }
7223
+ }
7224
+ }
7225
+ if (model.constraints) {
7226
+ for (const [cName, c] of Object.entries(model.constraints)) {
7227
+ lines.push("");
7228
+ lines.push(`[[models.${modelName}.unique_constraints]]`);
7229
+ lines.push(`name = ${tomlValue(cName)}`);
7230
+ lines.push(`fields = [${c.fields.map((f) => tomlValue(f)).join(", ")}]`);
7231
+ }
7232
+ }
7233
+ }
7234
+ lines.push("");
7235
+ return lines.join("\n");
7236
+ }
7237
+
7238
+ // src/models/tomlLoader.ts
7239
+ import { parse as parseToml } from "smol-toml";
7240
+ var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
7241
+ "string",
7242
+ "number",
7243
+ "boolean",
7244
+ "date",
7245
+ "id",
7246
+ "stringset"
7247
+ ]);
7248
+ function parseFieldOptions(raw) {
7249
+ if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
7250
+ throw new Error(
7251
+ `Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
7252
+ );
7253
+ }
7254
+ const opts = { type: raw.type };
7255
+ if (raw.indexed === true) opts.indexed = true;
7256
+ if (raw.unique === true) opts.unique = true;
7257
+ if (raw.required === true) opts.required = true;
7258
+ if (raw.auto_assign === true) opts.autoAssign = true;
7259
+ if (raw.max_length !== void 0) opts.maxLength = raw.max_length;
7260
+ if (raw.max_count !== void 0) opts.maxCount = raw.max_count;
7261
+ if (raw.default !== void 0) opts.default = raw.default;
7262
+ return opts;
7263
+ }
7264
+ function requireField(raw, field, context) {
7265
+ if (!raw[field]) {
7266
+ throw new Error(`Relationship ${context}: missing required field "${field}"`);
7267
+ }
7268
+ }
7269
+ function parseRelationship(raw) {
7270
+ const type = raw.type;
7271
+ if (type === "refersTo") {
7272
+ requireField(raw, "model", "refersTo");
7273
+ requireField(raw, "related_id_field", "refersTo");
7274
+ return {
7275
+ type: "refersTo",
7276
+ model: raw.model,
7277
+ relatedIdField: raw.related_id_field
7278
+ };
7279
+ }
7280
+ if (type === "hasMany") {
7281
+ requireField(raw, "model", "hasMany");
7282
+ requireField(raw, "related_id_field", "hasMany");
7283
+ const rel = {
7284
+ type: "hasMany",
7285
+ model: raw.model,
7286
+ relatedIdField: raw.related_id_field
7287
+ };
7288
+ if (raw.order_by_field) rel.orderByField = raw.order_by_field;
7289
+ if (raw.order_direction) rel.orderDirection = raw.order_direction;
7290
+ return rel;
7291
+ }
7292
+ if (type === "hasManyThrough") {
7293
+ requireField(raw, "model", "hasManyThrough");
7294
+ requireField(raw, "join_model", "hasManyThrough");
7295
+ requireField(raw, "join_model_local_field", "hasManyThrough");
7296
+ requireField(raw, "join_model_related_field", "hasManyThrough");
7297
+ const rel = {
7298
+ type: "hasManyThrough",
7299
+ model: raw.model,
7300
+ joinModel: raw.join_model,
7301
+ joinModelLocalField: raw.join_model_local_field,
7302
+ joinModelRelatedField: raw.join_model_related_field
7303
+ };
7304
+ if (raw.join_model_order_by_field)
7305
+ rel.joinModelOrderByField = raw.join_model_order_by_field;
7306
+ if (raw.join_model_order_direction)
7307
+ rel.joinModelOrderDirection = raw.join_model_order_direction;
7308
+ return rel;
7309
+ }
7310
+ throw new Error(`Unknown relationship type: ${type}`);
7311
+ }
7312
+ function loadSchemaFromTomlString(tomlString) {
7313
+ const parsed = parseToml(tomlString);
7314
+ const models = parsed.models;
7315
+ if (!models || typeof models !== "object") {
7316
+ throw new Error("TOML schema must have a [models] section");
7317
+ }
7318
+ const schemas = [];
7319
+ for (const [modelName, modelDef] of Object.entries(models)) {
7320
+ const fields = {};
7321
+ if (modelDef.fields) {
7322
+ for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
7323
+ fields[fieldName] = parseFieldOptions(fieldDef);
7324
+ }
7325
+ }
7326
+ let relationships;
7327
+ if (modelDef.relationships) {
7328
+ relationships = {};
7329
+ for (const [relName, relDef] of Object.entries(
7330
+ modelDef.relationships
7331
+ )) {
7332
+ relationships[relName] = parseRelationship(relDef);
7333
+ }
7334
+ }
7335
+ let uniqueConstraints;
7336
+ if (modelDef.unique_constraints) {
7337
+ uniqueConstraints = [];
7338
+ for (const raw of modelDef.unique_constraints) {
7339
+ uniqueConstraints.push({
7340
+ name: raw.name,
7341
+ fields: [...raw.fields]
7342
+ });
7343
+ }
7344
+ }
7345
+ schemas.push(
7346
+ defineModelSchema({
7347
+ name: modelName,
7348
+ fields,
7349
+ options: {
7350
+ uniqueConstraints,
7351
+ relationships
7352
+ }
7353
+ })
7354
+ );
7355
+ }
7356
+ return schemas;
7357
+ }
7358
+ async function loadSchemaFromToml(filePath) {
7359
+ const { readFile } = await import("fs/promises");
7360
+ const content = await readFile(filePath, "utf-8");
7361
+ return loadSchemaFromTomlString(content);
7362
+ }
7363
+
7364
+ // src/node.ts
7365
+ init_metaSync();
7366
+
7367
+ // src/utils/yDocDump.ts
7368
+ import * as Y4 from "yjs";
7132
7369
  function toPlain(value) {
7133
- if (value instanceof Y3.Map) {
7370
+ if (value instanceof Y4.Map) {
7134
7371
  const obj = {};
7135
7372
  value.forEach((v, k) => {
7136
7373
  obj[k] = toPlain(v);
7137
7374
  });
7138
7375
  return obj;
7139
7376
  }
7140
- if (value instanceof Y3.Array) {
7377
+ if (value instanceof Y4.Array) {
7141
7378
  return value.toArray().map((item) => toPlain(item));
7142
7379
  }
7143
7380
  return value;
@@ -7146,7 +7383,7 @@ function dumpYDocToPlain(yDoc, options = {}) {
7146
7383
  const result = {};
7147
7384
  const includeIndexes = !!options.includeIndexes;
7148
7385
  yDoc.share.forEach((type, name) => {
7149
- if (!(type instanceof Y3.Map)) return;
7386
+ if (!(type instanceof Y4.Map)) return;
7150
7387
  if (!includeIndexes && name.startsWith("_uniqueIdx_")) return;
7151
7388
  const records = {};
7152
7389
  type.forEach((recordValue, recordId) => {
@@ -7199,10 +7436,8 @@ export {
7199
7436
  BaseModel2 as BaseModel,
7200
7437
  DatabaseEngine,
7201
7438
  NodeDatabaseFactory as DatabaseFactory,
7202
- Field,
7203
7439
  LogLevel,
7204
7440
  Logger,
7205
- Model,
7206
7441
  ModelRegistry,
7207
7442
  RecordNotFoundError,
7208
7443
  SqljsEngine,
@@ -7211,18 +7446,28 @@ export {
7211
7446
  attachAndRegisterModel,
7212
7447
  attachSchemaToClass,
7213
7448
  autoRegisterModel,
7449
+ clearMetaSyncCache,
7214
7450
  constants,
7215
7451
  createModelClass,
7216
7452
  defineModelSchema,
7217
7453
  detectEnvironment,
7454
+ discoverModelNames,
7455
+ discoverSchema,
7218
7456
  dumpYDocToPlain,
7219
7457
  features,
7220
7458
  generateULID,
7221
7459
  getRecommendedNodeEngine,
7460
+ inferFieldType,
7222
7461
  initJsBao,
7223
7462
  isBrowser,
7224
7463
  isNode,
7225
7464
  isNodeModuleAvailable,
7465
+ loadSchemaFromToml,
7466
+ loadSchemaFromTomlString,
7467
+ registerFunctionDefault,
7226
7468
  resetJsBao,
7227
- summarizePlainYDoc
7469
+ schemaToToml,
7470
+ summarizePlainYDoc,
7471
+ syncInferredMeta,
7472
+ syncModelMeta
7228
7473
  };