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.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);
@@ -1599,11 +1634,11 @@ var init_ModelRegistry = __esm({
1599
1634
  init_relationshipManager();
1600
1635
  ModelRegistry = class _ModelRegistry {
1601
1636
  static instance;
1602
- // Stores globally registered model classes by their name (from @Model decorator)
1637
+ // Stores globally registered model classes by their name
1603
1638
  models = /* @__PURE__ */ new Map();
1604
- // Stores options for globally registered models (from @Model decorator)
1639
+ // Stores options for globally registered models
1605
1640
  modelOptions = /* @__PURE__ */ new Map();
1606
- // Stores fields for globally registered models (from @Model decorator, or a static getter on class)
1641
+ // Stores fields for globally registered models (or a static getter on class)
1607
1642
  // For simplicity, let's assume fields can be derived or are less critical for this registry part
1608
1643
  // private modelFields: Map<string, Map<string, FieldOptions>> = new Map();
1609
1644
  // Holds the subset of models explicitly set for the current initialization session
@@ -1621,7 +1656,7 @@ var init_ModelRegistry = __esm({
1621
1656
  registerModel(modelClass, options, fields) {
1622
1657
  if (!options.name) {
1623
1658
  throw new Error(
1624
- `[ModelRegistry] Model class is missing a name in its @Model options. Ensure the @Model decorator includes a 'name' property.`
1659
+ `[ModelRegistry] Model class is missing a name in its options. Ensure the schema passed to defineModelSchema/createModelClass/attachAndRegisterModel includes a 'name' property.`
1625
1660
  );
1626
1661
  }
1627
1662
  if (this.models.has(options.name)) {
@@ -1665,7 +1700,7 @@ var init_ModelRegistry = __esm({
1665
1700
  }
1666
1701
  return infos;
1667
1702
  }
1668
- // Helper to get model name from class (assuming static property from @Model decorator)
1703
+ // Helper to get model name from class (set by attachAndRegisterModel/createModelClass)
1669
1704
  getModelNameFromClass(modelClass) {
1670
1705
  return modelClass.modelName;
1671
1706
  }
@@ -1676,13 +1711,13 @@ var init_ModelRegistry = __esm({
1676
1711
  const modelName = this.getModelNameFromClass(modelClass);
1677
1712
  if (!modelName) {
1678
1713
  console.warn(
1679
- `[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.`
1714
+ `[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.`
1680
1715
  );
1681
1716
  return;
1682
1717
  }
1683
1718
  if (!this.models.has(modelName) || this.models.get(modelName) !== modelClass) {
1684
1719
  console.warn(
1685
- `[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.`
1720
+ `[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.`
1686
1721
  );
1687
1722
  return;
1688
1723
  }
@@ -1712,7 +1747,7 @@ var init_ModelRegistry = __esm({
1712
1747
  } else {
1713
1748
  this.activeSessionModels = null;
1714
1749
  console.log(
1715
- "[ModelRegistry] No explicit models specified for session (undefined), will use all decorator-registered models."
1750
+ "[ModelRegistry] No explicit models specified for session (undefined), will use all globally registered models."
1716
1751
  );
1717
1752
  }
1718
1753
  this.validateSessionModels();
@@ -1723,7 +1758,7 @@ var init_ModelRegistry = __esm({
1723
1758
  const modelsToInitialize = this.activeSessionModels || this.models;
1724
1759
  if (modelsToInitialize.size === 0) {
1725
1760
  console.warn(
1726
- "[ModelRegistry] No models to initialize (either no explicit models set for session or no models globally registered via @Model decorator)."
1761
+ "[ModelRegistry] No models to initialize (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
1727
1762
  );
1728
1763
  return;
1729
1764
  }
@@ -1754,7 +1789,7 @@ var init_ModelRegistry = __esm({
1754
1789
  const modelsToInitialize = this.activeSessionModels || this.models;
1755
1790
  if (modelsToInitialize.size === 0) {
1756
1791
  Logger.warn(
1757
- "[ModelRegistry] No models to initialize for document (either no explicit models set for session or no models globally registered via @Model decorator)."
1792
+ "[ModelRegistry] No models to initialize for document (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
1758
1793
  );
1759
1794
  return;
1760
1795
  }
@@ -1792,7 +1827,7 @@ var init_ModelRegistry = __esm({
1792
1827
  const modelsToCleanup = this.activeSessionModels || this.models;
1793
1828
  if (modelsToCleanup.size === 0) {
1794
1829
  console.warn(
1795
- "[ModelRegistry] No models to cleanup for document (either no explicit models set for session or no models globally registered via @Model decorator)."
1830
+ "[ModelRegistry] No models to cleanup for document (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
1796
1831
  );
1797
1832
  return;
1798
1833
  }
@@ -2556,7 +2591,7 @@ var init_BaseModel = __esm({
2556
2591
  getDocumentId() {
2557
2592
  return this._metaDocId;
2558
2593
  }
2559
- // id is now a plain property. Subclasses will define it with @Field.
2594
+ // id is a plain property. Subclasses define it via defineModelSchema.
2560
2595
  id;
2561
2596
  type;
2562
2597
  // This should be the modelName from ModelOptions
@@ -3103,7 +3138,7 @@ var init_BaseModel = __esm({
3103
3138
  const verboseEnabled = Logger.getLogLevel() >= 5 /* VERBOSE */;
3104
3139
  if (!schema || !schema.options || !schema.options.name || !schema.resolvedUniqueConstraints) {
3105
3140
  throw new Error(
3106
- `[${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?`
3141
+ `[${this.name}] Model schema is not registered, missing options, or missing resolvedUniqueConstraints. Did you forget to call attachAndRegisterModel (or autoRegisterModel) for this model?`
3107
3142
  );
3108
3143
  }
3109
3144
  const modelName = schema.options.name;
@@ -5498,11 +5533,11 @@ var init_BaseModel = __esm({
5498
5533
  });
5499
5534
 
5500
5535
  // src/engines/SqljsEngine.ts
5501
- var import_sql5, import_async_mutex, SQL_WASM_URL, TransactionalSQLJSOperations, SqljsEngine;
5536
+ var import_sql4, import_async_mutex, SQL_WASM_URL, TransactionalSQLJSOperations, SqljsEngine;
5502
5537
  var init_SqljsEngine = __esm({
5503
5538
  "src/engines/SqljsEngine.ts"() {
5504
5539
  "use strict";
5505
- import_sql5 = __toESM(require("sql.js"), 1);
5540
+ import_sql4 = __toESM(require("sql.js"), 1);
5506
5541
  init_BaseModel();
5507
5542
  import_async_mutex = require("async-mutex");
5508
5543
  init_sql();
@@ -5579,7 +5614,7 @@ var init_SqljsEngine = __esm({
5579
5614
  "[SqljsEngine] Attempting to load SQL.js WASM from:",
5580
5615
  locateFileConfig("sql-wasm.wasm")
5581
5616
  );
5582
- _SqljsEngine.SQL = await (0, import_sql5.default)({
5617
+ _SqljsEngine.SQL = await (0, import_sql4.default)({
5583
5618
  locateFile: locateFileConfig
5584
5619
  });
5585
5620
  Logger.info("[SqljsEngine] SQL.js WASM loaded successfully.");
@@ -6626,10 +6661,8 @@ __export(node_exports, {
6626
6661
  BaseModel: () => BaseModel2,
6627
6662
  DatabaseEngine: () => DatabaseEngine,
6628
6663
  DatabaseFactory: () => NodeDatabaseFactory,
6629
- Field: () => Field,
6630
6664
  LogLevel: () => LogLevel,
6631
6665
  Logger: () => Logger,
6632
- Model: () => Model,
6633
6666
  ModelRegistry: () => ModelRegistry,
6634
6667
  RecordNotFoundError: () => RecordNotFoundError,
6635
6668
  SqljsEngine: () => SqljsEngine,
@@ -6638,150 +6671,35 @@ __export(node_exports, {
6638
6671
  attachAndRegisterModel: () => attachAndRegisterModel,
6639
6672
  attachSchemaToClass: () => attachSchemaToClass,
6640
6673
  autoRegisterModel: () => autoRegisterModel,
6674
+ clearMetaSyncCache: () => clearMetaSyncCache,
6641
6675
  constants: () => constants,
6642
6676
  createModelClass: () => createModelClass,
6643
6677
  defineModelSchema: () => defineModelSchema,
6644
6678
  detectEnvironment: () => detectEnvironment,
6679
+ discoverModelNames: () => discoverModelNames,
6680
+ discoverSchema: () => discoverSchema,
6645
6681
  dumpYDocToPlain: () => dumpYDocToPlain,
6646
6682
  features: () => features,
6647
6683
  generateULID: () => generateULID,
6648
6684
  getRecommendedNodeEngine: () => getRecommendedNodeEngine,
6685
+ inferFieldType: () => inferFieldType,
6649
6686
  initJsBao: () => initJsBao,
6650
6687
  isBrowser: () => isBrowser,
6651
6688
  isNode: () => isNode,
6652
6689
  isNodeModuleAvailable: () => isNodeModuleAvailable,
6690
+ loadSchemaFromToml: () => loadSchemaFromToml,
6691
+ loadSchemaFromTomlString: () => loadSchemaFromTomlString,
6692
+ registerFunctionDefault: () => registerFunctionDefault,
6653
6693
  resetJsBao: () => resetJsBao,
6654
- summarizePlainYDoc: () => summarizePlainYDoc
6694
+ schemaToToml: () => schemaToToml,
6695
+ summarizePlainYDoc: () => summarizePlainYDoc,
6696
+ syncInferredMeta: () => syncInferredMeta,
6697
+ syncModelMeta: () => syncModelMeta
6655
6698
  });
6656
6699
  module.exports = __toCommonJS(node_exports);
6657
6700
  init_BaseModel();
6658
6701
  init_ModelRegistry();
6659
6702
 
6660
- // src/models/decorators.ts
6661
- init_ModelRegistry();
6662
- init_BaseModel();
6663
- init_sql();
6664
- var SCHEMA_FIELDS_PROPERTY = "_jsbaoSchemaFields";
6665
- function Field(options) {
6666
- return function(target, propertyKey) {
6667
- const fieldName = String(propertyKey);
6668
- const modelConstructor = target.constructor || target;
6669
- assertValidIdentifier(
6670
- fieldName,
6671
- `[Field Decorator] Invalid field name on ${modelConstructor?.name || "unknown"}`
6672
- );
6673
- if (!modelConstructor) {
6674
- console.error(
6675
- "[Field Decorator] Could not determine model constructor for field:",
6676
- fieldName,
6677
- "Target:",
6678
- target
6679
- );
6680
- throw new Error(
6681
- `Failed to resolve model constructor for field '${fieldName}'.`
6682
- );
6683
- }
6684
- if (!Object.prototype.hasOwnProperty.call(
6685
- modelConstructor,
6686
- SCHEMA_FIELDS_PROPERTY
6687
- )) {
6688
- modelConstructor[SCHEMA_FIELDS_PROPERTY] = /* @__PURE__ */ new Map();
6689
- }
6690
- modelConstructor[SCHEMA_FIELDS_PROPERTY].set(
6691
- fieldName,
6692
- options
6693
- );
6694
- Logger.debug(
6695
- `[Field Decorator] Staged field "${fieldName}" for class ${modelConstructor.name}:`,
6696
- options
6697
- );
6698
- };
6699
- }
6700
- function Model(options) {
6701
- return function(targetClass) {
6702
- Logger.debug(
6703
- `[Model Decorator] Registering model:`,
6704
- targetClass.name,
6705
- options
6706
- );
6707
- assertValidIdentifier(
6708
- options.name,
6709
- `[Model Decorator] Invalid model name for ${targetClass.name}`
6710
- );
6711
- const registry = ModelRegistry.getInstance();
6712
- targetClass.modelName = options.name;
6713
- targetClass.getSchema = () => {
6714
- const combinedFields = /* @__PURE__ */ new Map();
6715
- const hierarchyStack = [];
6716
- let currentEvalClass = targetClass;
6717
- while (currentEvalClass && currentEvalClass.prototype) {
6718
- hierarchyStack.push(currentEvalClass);
6719
- const parentPrototype = Object.getPrototypeOf(
6720
- currentEvalClass.prototype
6721
- );
6722
- currentEvalClass = parentPrototype ? parentPrototype.constructor : null;
6723
- if (currentEvalClass === Object) break;
6724
- }
6725
- for (let i = hierarchyStack.length - 1; i >= 0; i--) {
6726
- const cls = hierarchyStack[i];
6727
- if (Object.prototype.hasOwnProperty.call(cls, SCHEMA_FIELDS_PROPERTY)) {
6728
- const fieldsForClass = cls[SCHEMA_FIELDS_PROPERTY];
6729
- fieldsForClass.forEach((fieldOpts, fieldName) => {
6730
- combinedFields.set(fieldName, fieldOpts);
6731
- });
6732
- }
6733
- }
6734
- const resolvedUniqueConstraints = [];
6735
- combinedFields.forEach((fieldOpts, fieldName) => {
6736
- if (fieldOpts.unique) {
6737
- const constraintName = `${options.name}_${fieldName}_unique`;
6738
- resolvedUniqueConstraints.push({
6739
- name: constraintName,
6740
- fields: [fieldName]
6741
- });
6742
- }
6743
- });
6744
- if (options.uniqueConstraints) {
6745
- options.uniqueConstraints.forEach(
6746
- (constraintConfig) => {
6747
- const allFieldsExist = constraintConfig.fields.every(
6748
- (f) => combinedFields.has(f)
6749
- );
6750
- if (!allFieldsExist) {
6751
- console.warn(
6752
- `[Model Decorator] Unique constraint "${constraintConfig.name}" for model "${options.name}" specifies non-existent fields. Skipping.`
6753
- );
6754
- return;
6755
- }
6756
- if (resolvedUniqueConstraints.some(
6757
- (rc) => rc.name === constraintConfig.name
6758
- )) {
6759
- console.warn(
6760
- `[Model Decorator] Duplicate unique constraint name "${constraintConfig.name}" in model "${options.name}".`
6761
- );
6762
- }
6763
- resolvedUniqueConstraints.push({
6764
- name: constraintConfig.name,
6765
- fields: constraintConfig.fields
6766
- });
6767
- }
6768
- );
6769
- }
6770
- return {
6771
- class: targetClass,
6772
- options,
6773
- fields: combinedFields,
6774
- resolvedUniqueConstraints
6775
- };
6776
- };
6777
- const directFieldsForThisClass = Object.prototype.hasOwnProperty.call(
6778
- targetClass,
6779
- SCHEMA_FIELDS_PROPERTY
6780
- ) ? targetClass[SCHEMA_FIELDS_PROPERTY] : /* @__PURE__ */ new Map();
6781
- registry.registerModel(targetClass, options, directFieldsForThisClass);
6782
- };
6783
- }
6784
-
6785
6703
  // src/engines/DatabaseEngine.ts
6786
6704
  var DatabaseEngine = class {
6787
6705
  createTable(_modelName, _schema, _options) {
@@ -7182,17 +7100,344 @@ function attachAndRegisterModel(modelClass, schema) {
7182
7100
  autoRegisterModel(modelClass, runtimeShape);
7183
7101
  }
7184
7102
 
7185
- // src/utils/yDocDump.ts
7103
+ // src/utils/yDocSchema.ts
7186
7104
  var Y3 = __toESM(require("yjs"), 1);
7105
+ function discoverSchema(yDoc) {
7106
+ const models = {};
7107
+ const metaNames = /* @__PURE__ */ new Set();
7108
+ for (const key of yDoc.share.keys()) {
7109
+ if (!key.startsWith("_meta_")) continue;
7110
+ const map = materializeMap(yDoc, key);
7111
+ if (!map) continue;
7112
+ const modelName = key.slice("_meta_".length);
7113
+ metaNames.add(modelName);
7114
+ models[modelName] = readModelMeta(map);
7115
+ }
7116
+ for (const key of yDoc.share.keys()) {
7117
+ if (key.startsWith("_")) continue;
7118
+ if (metaNames.has(key)) continue;
7119
+ const map = materializeMap(yDoc, key);
7120
+ if (!map || map.size === 0) continue;
7121
+ const inferred = inferModelFromData(map);
7122
+ if (inferred) models[key] = inferred;
7123
+ }
7124
+ return { models };
7125
+ }
7126
+ function discoverModelNames(yDoc) {
7127
+ const names = [];
7128
+ for (const key of yDoc.share.keys()) {
7129
+ if (key.startsWith("_")) continue;
7130
+ const map = materializeMap(yDoc, key);
7131
+ if (map) names.push(key);
7132
+ }
7133
+ return names.sort();
7134
+ }
7135
+ function materializeMap(yDoc, key) {
7136
+ try {
7137
+ const map = yDoc.getMap(key);
7138
+ return map instanceof Y3.Map ? map : null;
7139
+ } catch {
7140
+ return null;
7141
+ }
7142
+ }
7143
+ function readModelMeta(metaMap) {
7144
+ const fields = {};
7145
+ let constraints;
7146
+ let relationships;
7147
+ for (const [key, value] of metaMap.entries()) {
7148
+ if (key === "_constraints" && value instanceof Y3.Map) {
7149
+ constraints = readConstraints(value);
7150
+ } else if (key === "_relationships" && value instanceof Y3.Map) {
7151
+ relationships = readRelationships(value);
7152
+ } else if (value instanceof Y3.Map) {
7153
+ fields[key] = readFieldMeta(value);
7154
+ }
7155
+ }
7156
+ const model = { fields };
7157
+ if (constraints && Object.keys(constraints).length > 0) {
7158
+ model.constraints = constraints;
7159
+ }
7160
+ if (relationships && Object.keys(relationships).length > 0) {
7161
+ model.relationships = relationships;
7162
+ }
7163
+ return model;
7164
+ }
7165
+ function readFieldMeta(fieldMap) {
7166
+ const field = { type: fieldMap.get("type") ?? "unknown" };
7167
+ if (fieldMap.get("indexed") === true) field.indexed = true;
7168
+ if (fieldMap.get("unique") === true) field.unique = true;
7169
+ if (fieldMap.get("required") === true) field.required = true;
7170
+ if (fieldMap.get("autoAssign") === true) field.autoAssign = true;
7171
+ const def = fieldMap.get("default");
7172
+ if (def !== void 0) field.default = def;
7173
+ const maxLength = fieldMap.get("maxLength");
7174
+ if (maxLength !== void 0) field.maxLength = maxLength;
7175
+ const maxCount = fieldMap.get("maxCount");
7176
+ if (maxCount !== void 0) field.maxCount = maxCount;
7177
+ return field;
7178
+ }
7179
+ function inferModelFromData(dataMap) {
7180
+ const fields = {};
7181
+ let sampled = 0;
7182
+ for (const [_recordId, recordValue] of dataMap.entries()) {
7183
+ if (!(recordValue instanceof Y3.Map)) continue;
7184
+ if (++sampled > 5) break;
7185
+ for (const [fieldName, value] of recordValue.entries()) {
7186
+ if (fieldName.startsWith("_")) continue;
7187
+ if (fields[fieldName]) continue;
7188
+ const type = inferTypeFromValue(value);
7189
+ if (type) fields[fieldName] = { type };
7190
+ }
7191
+ }
7192
+ if (Object.keys(fields).length === 0) return null;
7193
+ return { fields };
7194
+ }
7195
+ function inferTypeFromValue(value) {
7196
+ if (value instanceof Y3.Map) return "stringset";
7197
+ switch (typeof value) {
7198
+ case "string":
7199
+ return "string";
7200
+ case "number":
7201
+ return "number";
7202
+ case "boolean":
7203
+ return "boolean";
7204
+ default:
7205
+ return null;
7206
+ }
7207
+ }
7208
+ function readConstraints(constraintsMap) {
7209
+ const out = {};
7210
+ for (const [name, value] of constraintsMap.entries()) {
7211
+ if (!(value instanceof Y3.Map)) continue;
7212
+ let fields = [];
7213
+ const rawFields = value.get("fields");
7214
+ if (typeof rawFields === "string") {
7215
+ try {
7216
+ fields = JSON.parse(rawFields);
7217
+ } catch {
7218
+ }
7219
+ }
7220
+ out[name] = {
7221
+ type: value.get("type") ?? "unknown",
7222
+ fields
7223
+ };
7224
+ }
7225
+ return out;
7226
+ }
7227
+ function readRelationships(relsMap) {
7228
+ const out = {};
7229
+ for (const [name, value] of relsMap.entries()) {
7230
+ if (!(value instanceof Y3.Map)) continue;
7231
+ const rel = {};
7232
+ for (const [k, v] of value.entries()) {
7233
+ rel[k] = v;
7234
+ }
7235
+ out[name] = rel;
7236
+ }
7237
+ return out;
7238
+ }
7239
+ var CAMEL_TO_SNAKE = {
7240
+ autoAssign: "auto_assign",
7241
+ maxLength: "max_length",
7242
+ maxCount: "max_count",
7243
+ relatedIdField: "related_id_field",
7244
+ joinModel: "join_model",
7245
+ joinModelLocalField: "join_model_local_field",
7246
+ joinModelRelatedField: "join_model_related_field",
7247
+ joinModelOrderByField: "join_model_order_by_field",
7248
+ joinModelOrderDirection: "join_model_order_direction",
7249
+ orderByField: "order_by_field",
7250
+ orderDirection: "order_direction"
7251
+ };
7252
+ function toSnake(key) {
7253
+ return CAMEL_TO_SNAKE[key] ?? key;
7254
+ }
7255
+ function tomlValue(v) {
7256
+ if (typeof v === "string") {
7257
+ return `"${v.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
7258
+ }
7259
+ return String(v);
7260
+ }
7261
+ function schemaToToml(schema) {
7262
+ const lines = [];
7263
+ for (const [modelName, model] of Object.entries(schema.models)) {
7264
+ if (lines.length > 0) lines.push("", "");
7265
+ lines.push(`[models.${modelName}]`);
7266
+ for (const [fieldName, field] of Object.entries(model.fields)) {
7267
+ lines.push("");
7268
+ lines.push(`[models.${modelName}.fields.${fieldName}]`);
7269
+ lines.push(`type = ${tomlValue(field.type)}`);
7270
+ if (field.autoAssign) lines.push("auto_assign = true");
7271
+ if (field.indexed) lines.push("indexed = true");
7272
+ if (field.unique) lines.push("unique = true");
7273
+ if (field.required) lines.push("required = true");
7274
+ if (field.maxLength !== void 0) lines.push(`max_length = ${field.maxLength}`);
7275
+ if (field.maxCount !== void 0) lines.push(`max_count = ${field.maxCount}`);
7276
+ if (field.default !== void 0) lines.push(`default = ${tomlValue(field.default)}`);
7277
+ }
7278
+ if (model.relationships) {
7279
+ for (const [relName, rel] of Object.entries(model.relationships)) {
7280
+ lines.push("");
7281
+ lines.push(`[models.${modelName}.relationships.${relName}]`);
7282
+ for (const [k, v] of Object.entries(rel)) {
7283
+ if (v === void 0) continue;
7284
+ lines.push(`${toSnake(k)} = ${tomlValue(v)}`);
7285
+ }
7286
+ }
7287
+ }
7288
+ if (model.constraints) {
7289
+ for (const [cName, c] of Object.entries(model.constraints)) {
7290
+ lines.push("");
7291
+ lines.push(`[[models.${modelName}.unique_constraints]]`);
7292
+ lines.push(`name = ${tomlValue(cName)}`);
7293
+ lines.push(`fields = [${c.fields.map((f) => tomlValue(f)).join(", ")}]`);
7294
+ }
7295
+ }
7296
+ }
7297
+ lines.push("");
7298
+ return lines.join("\n");
7299
+ }
7300
+
7301
+ // src/models/tomlLoader.ts
7302
+ var import_smol_toml = require("smol-toml");
7303
+ var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
7304
+ "string",
7305
+ "number",
7306
+ "boolean",
7307
+ "date",
7308
+ "id",
7309
+ "stringset"
7310
+ ]);
7311
+ function parseFieldOptions(raw) {
7312
+ if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
7313
+ throw new Error(
7314
+ `Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
7315
+ );
7316
+ }
7317
+ const opts = { type: raw.type };
7318
+ if (raw.indexed === true) opts.indexed = true;
7319
+ if (raw.unique === true) opts.unique = true;
7320
+ if (raw.required === true) opts.required = true;
7321
+ if (raw.auto_assign === true) opts.autoAssign = true;
7322
+ if (raw.max_length !== void 0) opts.maxLength = raw.max_length;
7323
+ if (raw.max_count !== void 0) opts.maxCount = raw.max_count;
7324
+ if (raw.default !== void 0) opts.default = raw.default;
7325
+ return opts;
7326
+ }
7327
+ function requireField(raw, field, context) {
7328
+ if (!raw[field]) {
7329
+ throw new Error(`Relationship ${context}: missing required field "${field}"`);
7330
+ }
7331
+ }
7332
+ function parseRelationship(raw) {
7333
+ const type = raw.type;
7334
+ if (type === "refersTo") {
7335
+ requireField(raw, "model", "refersTo");
7336
+ requireField(raw, "related_id_field", "refersTo");
7337
+ return {
7338
+ type: "refersTo",
7339
+ model: raw.model,
7340
+ relatedIdField: raw.related_id_field
7341
+ };
7342
+ }
7343
+ if (type === "hasMany") {
7344
+ requireField(raw, "model", "hasMany");
7345
+ requireField(raw, "related_id_field", "hasMany");
7346
+ const rel = {
7347
+ type: "hasMany",
7348
+ model: raw.model,
7349
+ relatedIdField: raw.related_id_field
7350
+ };
7351
+ if (raw.order_by_field) rel.orderByField = raw.order_by_field;
7352
+ if (raw.order_direction) rel.orderDirection = raw.order_direction;
7353
+ return rel;
7354
+ }
7355
+ if (type === "hasManyThrough") {
7356
+ requireField(raw, "model", "hasManyThrough");
7357
+ requireField(raw, "join_model", "hasManyThrough");
7358
+ requireField(raw, "join_model_local_field", "hasManyThrough");
7359
+ requireField(raw, "join_model_related_field", "hasManyThrough");
7360
+ const rel = {
7361
+ type: "hasManyThrough",
7362
+ model: raw.model,
7363
+ joinModel: raw.join_model,
7364
+ joinModelLocalField: raw.join_model_local_field,
7365
+ joinModelRelatedField: raw.join_model_related_field
7366
+ };
7367
+ if (raw.join_model_order_by_field)
7368
+ rel.joinModelOrderByField = raw.join_model_order_by_field;
7369
+ if (raw.join_model_order_direction)
7370
+ rel.joinModelOrderDirection = raw.join_model_order_direction;
7371
+ return rel;
7372
+ }
7373
+ throw new Error(`Unknown relationship type: ${type}`);
7374
+ }
7375
+ function loadSchemaFromTomlString(tomlString) {
7376
+ const parsed = (0, import_smol_toml.parse)(tomlString);
7377
+ const models = parsed.models;
7378
+ if (!models || typeof models !== "object") {
7379
+ throw new Error("TOML schema must have a [models] section");
7380
+ }
7381
+ const schemas = [];
7382
+ for (const [modelName, modelDef] of Object.entries(models)) {
7383
+ const fields = {};
7384
+ if (modelDef.fields) {
7385
+ for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
7386
+ fields[fieldName] = parseFieldOptions(fieldDef);
7387
+ }
7388
+ }
7389
+ let relationships;
7390
+ if (modelDef.relationships) {
7391
+ relationships = {};
7392
+ for (const [relName, relDef] of Object.entries(
7393
+ modelDef.relationships
7394
+ )) {
7395
+ relationships[relName] = parseRelationship(relDef);
7396
+ }
7397
+ }
7398
+ let uniqueConstraints;
7399
+ if (modelDef.unique_constraints) {
7400
+ uniqueConstraints = [];
7401
+ for (const raw of modelDef.unique_constraints) {
7402
+ uniqueConstraints.push({
7403
+ name: raw.name,
7404
+ fields: [...raw.fields]
7405
+ });
7406
+ }
7407
+ }
7408
+ schemas.push(
7409
+ defineModelSchema({
7410
+ name: modelName,
7411
+ fields,
7412
+ options: {
7413
+ uniqueConstraints,
7414
+ relationships
7415
+ }
7416
+ })
7417
+ );
7418
+ }
7419
+ return schemas;
7420
+ }
7421
+ async function loadSchemaFromToml(filePath) {
7422
+ const { readFile } = await import("fs/promises");
7423
+ const content = await readFile(filePath, "utf-8");
7424
+ return loadSchemaFromTomlString(content);
7425
+ }
7426
+
7427
+ // src/node.ts
7428
+ init_metaSync();
7429
+
7430
+ // src/utils/yDocDump.ts
7431
+ var Y4 = __toESM(require("yjs"), 1);
7187
7432
  function toPlain(value) {
7188
- if (value instanceof Y3.Map) {
7433
+ if (value instanceof Y4.Map) {
7189
7434
  const obj = {};
7190
7435
  value.forEach((v, k) => {
7191
7436
  obj[k] = toPlain(v);
7192
7437
  });
7193
7438
  return obj;
7194
7439
  }
7195
- if (value instanceof Y3.Array) {
7440
+ if (value instanceof Y4.Array) {
7196
7441
  return value.toArray().map((item) => toPlain(item));
7197
7442
  }
7198
7443
  return value;
@@ -7201,7 +7446,7 @@ function dumpYDocToPlain(yDoc, options = {}) {
7201
7446
  const result = {};
7202
7447
  const includeIndexes = !!options.includeIndexes;
7203
7448
  yDoc.share.forEach((type, name) => {
7204
- if (!(type instanceof Y3.Map)) return;
7449
+ if (!(type instanceof Y4.Map)) return;
7205
7450
  if (!includeIndexes && name.startsWith("_uniqueIdx_")) return;
7206
7451
  const records = {};
7207
7452
  type.forEach((recordValue, recordId) => {
@@ -7255,10 +7500,8 @@ async function getRecommendedNodeEngine() {
7255
7500
  BaseModel,
7256
7501
  DatabaseEngine,
7257
7502
  DatabaseFactory,
7258
- Field,
7259
7503
  LogLevel,
7260
7504
  Logger,
7261
- Model,
7262
7505
  ModelRegistry,
7263
7506
  RecordNotFoundError,
7264
7507
  SqljsEngine,
@@ -7267,18 +7510,28 @@ async function getRecommendedNodeEngine() {
7267
7510
  attachAndRegisterModel,
7268
7511
  attachSchemaToClass,
7269
7512
  autoRegisterModel,
7513
+ clearMetaSyncCache,
7270
7514
  constants,
7271
7515
  createModelClass,
7272
7516
  defineModelSchema,
7273
7517
  detectEnvironment,
7518
+ discoverModelNames,
7519
+ discoverSchema,
7274
7520
  dumpYDocToPlain,
7275
7521
  features,
7276
7522
  generateULID,
7277
7523
  getRecommendedNodeEngine,
7524
+ inferFieldType,
7278
7525
  initJsBao,
7279
7526
  isBrowser,
7280
7527
  isNode,
7281
7528
  isNodeModuleAvailable,
7529
+ loadSchemaFromToml,
7530
+ loadSchemaFromTomlString,
7531
+ registerFunctionDefault,
7282
7532
  resetJsBao,
7283
- summarizePlainYDoc
7533
+ schemaToToml,
7534
+ summarizePlainYDoc,
7535
+ syncInferredMeta,
7536
+ syncModelMeta
7284
7537
  });