js-bao 0.3.1 → 0.4.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/index.js CHANGED
@@ -1855,7 +1855,7 @@ var init_BaseModel = __esm({
1855
1855
  getDocumentId() {
1856
1856
  return this._metaDocId;
1857
1857
  }
1858
- // id is now a plain property. Subclasses will define it with @Field.
1858
+ // id is a plain property. Subclasses define it via defineModelSchema.
1859
1859
  id;
1860
1860
  type;
1861
1861
  // This should be the modelName from ModelOptions
@@ -2402,7 +2402,7 @@ var init_BaseModel = __esm({
2402
2402
  const verboseEnabled = Logger.getLogLevel() >= 5 /* VERBOSE */;
2403
2403
  if (!schema || !schema.options || !schema.options.name || !schema.resolvedUniqueConstraints) {
2404
2404
  throw new Error(
2405
- `[${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?`
2405
+ `[${this.name}] Model schema is not registered, missing options, or missing resolvedUniqueConstraints. Did you forget to call attachAndRegisterModel (or autoRegisterModel) for this model?`
2406
2406
  );
2407
2407
  }
2408
2408
  const modelName = schema.options.name;
@@ -5110,11 +5110,11 @@ var init_ModelRegistry = __esm({
5110
5110
  init_relationshipManager();
5111
5111
  ModelRegistry = class _ModelRegistry {
5112
5112
  static instance;
5113
- // Stores globally registered model classes by their name (from @Model decorator)
5113
+ // Stores globally registered model classes by their name
5114
5114
  models = /* @__PURE__ */ new Map();
5115
- // Stores options for globally registered models (from @Model decorator)
5115
+ // Stores options for globally registered models
5116
5116
  modelOptions = /* @__PURE__ */ new Map();
5117
- // Stores fields for globally registered models (from @Model decorator, or a static getter on class)
5117
+ // Stores fields for globally registered models (or a static getter on class)
5118
5118
  // For simplicity, let's assume fields can be derived or are less critical for this registry part
5119
5119
  // private modelFields: Map<string, Map<string, FieldOptions>> = new Map();
5120
5120
  // Holds the subset of models explicitly set for the current initialization session
@@ -5132,7 +5132,7 @@ var init_ModelRegistry = __esm({
5132
5132
  registerModel(modelClass, options, fields) {
5133
5133
  if (!options.name) {
5134
5134
  throw new Error(
5135
- `[ModelRegistry] Model class is missing a name in its @Model options. Ensure the @Model decorator includes a 'name' property.`
5135
+ `[ModelRegistry] Model class is missing a name in its options. Ensure the schema passed to defineModelSchema/createModelClass/attachAndRegisterModel includes a 'name' property.`
5136
5136
  );
5137
5137
  }
5138
5138
  if (this.models.has(options.name)) {
@@ -5176,7 +5176,7 @@ var init_ModelRegistry = __esm({
5176
5176
  }
5177
5177
  return infos;
5178
5178
  }
5179
- // Helper to get model name from class (assuming static property from @Model decorator)
5179
+ // Helper to get model name from class (set by attachAndRegisterModel/createModelClass)
5180
5180
  getModelNameFromClass(modelClass) {
5181
5181
  return modelClass.modelName;
5182
5182
  }
@@ -5187,13 +5187,13 @@ var init_ModelRegistry = __esm({
5187
5187
  const modelName = this.getModelNameFromClass(modelClass);
5188
5188
  if (!modelName) {
5189
5189
  console.warn(
5190
- `[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.`
5190
+ `[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.`
5191
5191
  );
5192
5192
  return;
5193
5193
  }
5194
5194
  if (!this.models.has(modelName) || this.models.get(modelName) !== modelClass) {
5195
5195
  console.warn(
5196
- `[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.`
5196
+ `[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.`
5197
5197
  );
5198
5198
  return;
5199
5199
  }
@@ -5223,7 +5223,7 @@ var init_ModelRegistry = __esm({
5223
5223
  } else {
5224
5224
  this.activeSessionModels = null;
5225
5225
  console.log(
5226
- "[ModelRegistry] No explicit models specified for session (undefined), will use all decorator-registered models."
5226
+ "[ModelRegistry] No explicit models specified for session (undefined), will use all globally registered models."
5227
5227
  );
5228
5228
  }
5229
5229
  this.validateSessionModels();
@@ -5234,7 +5234,7 @@ var init_ModelRegistry = __esm({
5234
5234
  const modelsToInitialize = this.activeSessionModels || this.models;
5235
5235
  if (modelsToInitialize.size === 0) {
5236
5236
  console.warn(
5237
- "[ModelRegistry] No models to initialize (either no explicit models set for session or no models globally registered via @Model decorator)."
5237
+ "[ModelRegistry] No models to initialize (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
5238
5238
  );
5239
5239
  return;
5240
5240
  }
@@ -5265,7 +5265,7 @@ var init_ModelRegistry = __esm({
5265
5265
  const modelsToInitialize = this.activeSessionModels || this.models;
5266
5266
  if (modelsToInitialize.size === 0) {
5267
5267
  Logger.warn(
5268
- "[ModelRegistry] No models to initialize for document (either no explicit models set for session or no models globally registered via @Model decorator)."
5268
+ "[ModelRegistry] No models to initialize for document (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
5269
5269
  );
5270
5270
  return;
5271
5271
  }
@@ -5303,7 +5303,7 @@ var init_ModelRegistry = __esm({
5303
5303
  const modelsToCleanup = this.activeSessionModels || this.models;
5304
5304
  if (modelsToCleanup.size === 0) {
5305
5305
  console.warn(
5306
- "[ModelRegistry] No models to cleanup for document (either no explicit models set for session or no models globally registered via @Model decorator)."
5306
+ "[ModelRegistry] No models to cleanup for document (either no explicit models set for session or no models globally registered via attachAndRegisterModel)."
5307
5307
  );
5308
5308
  return;
5309
5309
  }
@@ -6834,133 +6834,6 @@ async function resetJsBao() {
6834
6834
  // src/index.ts
6835
6835
  init_documentTypes();
6836
6836
  init_BaseModel();
6837
-
6838
- // src/models/decorators.ts
6839
- init_ModelRegistry();
6840
- init_BaseModel();
6841
- init_sql();
6842
- var SCHEMA_FIELDS_PROPERTY = "_jsbaoSchemaFields";
6843
- function Field(options) {
6844
- return function(target, propertyKey) {
6845
- const fieldName = String(propertyKey);
6846
- const modelConstructor = target.constructor || target;
6847
- assertValidIdentifier(
6848
- fieldName,
6849
- `[Field Decorator] Invalid field name on ${modelConstructor?.name || "unknown"}`
6850
- );
6851
- if (!modelConstructor) {
6852
- console.error(
6853
- "[Field Decorator] Could not determine model constructor for field:",
6854
- fieldName,
6855
- "Target:",
6856
- target
6857
- );
6858
- throw new Error(
6859
- `Failed to resolve model constructor for field '${fieldName}'.`
6860
- );
6861
- }
6862
- if (!Object.prototype.hasOwnProperty.call(
6863
- modelConstructor,
6864
- SCHEMA_FIELDS_PROPERTY
6865
- )) {
6866
- modelConstructor[SCHEMA_FIELDS_PROPERTY] = /* @__PURE__ */ new Map();
6867
- }
6868
- modelConstructor[SCHEMA_FIELDS_PROPERTY].set(
6869
- fieldName,
6870
- options
6871
- );
6872
- Logger.debug(
6873
- `[Field Decorator] Staged field "${fieldName}" for class ${modelConstructor.name}:`,
6874
- options
6875
- );
6876
- };
6877
- }
6878
- function Model(options) {
6879
- return function(targetClass) {
6880
- Logger.debug(
6881
- `[Model Decorator] Registering model:`,
6882
- targetClass.name,
6883
- options
6884
- );
6885
- assertValidIdentifier(
6886
- options.name,
6887
- `[Model Decorator] Invalid model name for ${targetClass.name}`
6888
- );
6889
- const registry = ModelRegistry.getInstance();
6890
- targetClass.modelName = options.name;
6891
- targetClass.getSchema = () => {
6892
- const combinedFields = /* @__PURE__ */ new Map();
6893
- const hierarchyStack = [];
6894
- let currentEvalClass = targetClass;
6895
- while (currentEvalClass && currentEvalClass.prototype) {
6896
- hierarchyStack.push(currentEvalClass);
6897
- const parentPrototype = Object.getPrototypeOf(
6898
- currentEvalClass.prototype
6899
- );
6900
- currentEvalClass = parentPrototype ? parentPrototype.constructor : null;
6901
- if (currentEvalClass === Object) break;
6902
- }
6903
- for (let i = hierarchyStack.length - 1; i >= 0; i--) {
6904
- const cls = hierarchyStack[i];
6905
- if (Object.prototype.hasOwnProperty.call(cls, SCHEMA_FIELDS_PROPERTY)) {
6906
- const fieldsForClass = cls[SCHEMA_FIELDS_PROPERTY];
6907
- fieldsForClass.forEach((fieldOpts, fieldName) => {
6908
- combinedFields.set(fieldName, fieldOpts);
6909
- });
6910
- }
6911
- }
6912
- const resolvedUniqueConstraints = [];
6913
- combinedFields.forEach((fieldOpts, fieldName) => {
6914
- if (fieldOpts.unique) {
6915
- const constraintName = `${options.name}_${fieldName}_unique`;
6916
- resolvedUniqueConstraints.push({
6917
- name: constraintName,
6918
- fields: [fieldName]
6919
- });
6920
- }
6921
- });
6922
- if (options.uniqueConstraints) {
6923
- options.uniqueConstraints.forEach(
6924
- (constraintConfig) => {
6925
- const allFieldsExist = constraintConfig.fields.every(
6926
- (f) => combinedFields.has(f)
6927
- );
6928
- if (!allFieldsExist) {
6929
- console.warn(
6930
- `[Model Decorator] Unique constraint "${constraintConfig.name}" for model "${options.name}" specifies non-existent fields. Skipping.`
6931
- );
6932
- return;
6933
- }
6934
- if (resolvedUniqueConstraints.some(
6935
- (rc) => rc.name === constraintConfig.name
6936
- )) {
6937
- console.warn(
6938
- `[Model Decorator] Duplicate unique constraint name "${constraintConfig.name}" in model "${options.name}".`
6939
- );
6940
- }
6941
- resolvedUniqueConstraints.push({
6942
- name: constraintConfig.name,
6943
- fields: constraintConfig.fields
6944
- });
6945
- }
6946
- );
6947
- }
6948
- return {
6949
- class: targetClass,
6950
- options,
6951
- fields: combinedFields,
6952
- resolvedUniqueConstraints
6953
- };
6954
- };
6955
- const directFieldsForThisClass = Object.prototype.hasOwnProperty.call(
6956
- targetClass,
6957
- SCHEMA_FIELDS_PROPERTY
6958
- ) ? targetClass[SCHEMA_FIELDS_PROPERTY] : /* @__PURE__ */ new Map();
6959
- registry.registerModel(targetClass, options, directFieldsForThisClass);
6960
- };
6961
- }
6962
-
6963
- // src/index.ts
6964
6837
  init_StringSet();
6965
6838
 
6966
6839
  // src/models/schema.ts
@@ -6970,6 +6843,7 @@ function defineModelSchema(input) {
6970
6843
  const { name, fields } = input;
6971
6844
  const options = {
6972
6845
  name,
6846
+ className: input.options?.className,
6973
6847
  uniqueConstraints: input.options?.uniqueConstraints ? [...input.options.uniqueConstraints] : void 0,
6974
6848
  relationships: input.options?.relationships
6975
6849
  };
@@ -7069,18 +6943,13 @@ function resolveUniqueConstraints(modelName, fields, customConstraints) {
7069
6943
  function attachSchemaToClass(modelClass, schema) {
7070
6944
  modelClass.schema = schema;
7071
6945
  modelClass.modelName = schema.options.name;
7072
- if (!modelClass.getSchema) {
7073
- Object.defineProperty(modelClass, "getSchema", {
7074
- value: function() {
7075
- return schema.buildRuntimeShape(modelClass);
7076
- },
7077
- writable: false
7078
- });
7079
- } else {
7080
- modelClass.getSchema = function() {
6946
+ Object.defineProperty(modelClass, "getSchema", {
6947
+ value: function() {
7081
6948
  return schema.buildRuntimeShape(modelClass);
7082
- };
7083
- }
6949
+ },
6950
+ writable: false,
6951
+ configurable: true
6952
+ });
7084
6953
  const runtimeShape = schema.buildRuntimeShape(modelClass);
7085
6954
  BaseModel.attachFieldAccessors(modelClass, runtimeShape.fields);
7086
6955
  return runtimeShape;
@@ -7157,12 +7026,52 @@ var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
7157
7026
  "id",
7158
7027
  "stringset"
7159
7028
  ]);
7160
- function parseFieldOptions(raw) {
7029
+ var KNOWN_FIELD_KEYS = /* @__PURE__ */ new Set([
7030
+ "type",
7031
+ "indexed",
7032
+ "unique",
7033
+ "required",
7034
+ "auto_assign",
7035
+ "max_length",
7036
+ "max_count",
7037
+ "default"
7038
+ ]);
7039
+ var KNOWN_MODEL_KEYS = /* @__PURE__ */ new Set([
7040
+ "fields",
7041
+ "relationships",
7042
+ "unique_constraints",
7043
+ "class_name"
7044
+ ]);
7045
+ var KNOWN_RELATIONSHIP_KEYS = /* @__PURE__ */ new Set([
7046
+ "type",
7047
+ "model",
7048
+ "related_id_field",
7049
+ "join_model",
7050
+ "join_model_local_field",
7051
+ "join_model_related_field",
7052
+ "order_by_field",
7053
+ "order_direction",
7054
+ "join_model_order_by_field",
7055
+ "join_model_order_direction"
7056
+ ]);
7057
+ var KNOWN_UNIQUE_CONSTRAINT_KEYS = /* @__PURE__ */ new Set(["name", "fields"]);
7058
+ function checkUnknownKeys(raw, known, context, strict) {
7059
+ if (!strict) return;
7060
+ for (const key of Object.keys(raw)) {
7061
+ if (!known.has(key)) {
7062
+ throw new Error(
7063
+ `${context}: unknown key "${key}". Allowed: ${[...known].join(", ")}`
7064
+ );
7065
+ }
7066
+ }
7067
+ }
7068
+ function parseFieldOptions(raw, context, strict) {
7161
7069
  if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
7162
7070
  throw new Error(
7163
7071
  `Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
7164
7072
  );
7165
7073
  }
7074
+ checkUnknownKeys(raw, KNOWN_FIELD_KEYS, context, strict);
7166
7075
  const opts = { type: raw.type };
7167
7076
  if (raw.indexed === true) opts.indexed = true;
7168
7077
  if (raw.unique === true) opts.unique = true;
@@ -7178,8 +7087,9 @@ function requireField(raw, field, context) {
7178
7087
  throw new Error(`Relationship ${context}: missing required field "${field}"`);
7179
7088
  }
7180
7089
  }
7181
- function parseRelationship(raw) {
7090
+ function parseRelationship(raw, context, strict) {
7182
7091
  const type = raw.type;
7092
+ checkUnknownKeys(raw, KNOWN_RELATIONSHIP_KEYS, context, strict);
7183
7093
  if (type === "refersTo") {
7184
7094
  requireField(raw, "model", "refersTo");
7185
7095
  requireField(raw, "related_id_field", "refersTo");
@@ -7221,7 +7131,8 @@ function parseRelationship(raw) {
7221
7131
  }
7222
7132
  throw new Error(`Unknown relationship type: ${type}`);
7223
7133
  }
7224
- function loadSchemaFromTomlString(tomlString) {
7134
+ function loadSchemaFromTomlString(tomlString, options = {}) {
7135
+ const strict = options.strict !== false;
7225
7136
  const parsed = parseToml(tomlString);
7226
7137
  const models = parsed.models;
7227
7138
  if (!models || typeof models !== "object") {
@@ -7229,10 +7140,20 @@ function loadSchemaFromTomlString(tomlString) {
7229
7140
  }
7230
7141
  const schemas = [];
7231
7142
  for (const [modelName, modelDef] of Object.entries(models)) {
7143
+ checkUnknownKeys(
7144
+ modelDef,
7145
+ KNOWN_MODEL_KEYS,
7146
+ `[models.${modelName}]`,
7147
+ strict
7148
+ );
7232
7149
  const fields = {};
7233
7150
  if (modelDef.fields) {
7234
7151
  for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
7235
- fields[fieldName] = parseFieldOptions(fieldDef);
7152
+ fields[fieldName] = parseFieldOptions(
7153
+ fieldDef,
7154
+ `[models.${modelName}.fields.${fieldName}]`,
7155
+ strict
7156
+ );
7236
7157
  }
7237
7158
  }
7238
7159
  let relationships;
@@ -7241,24 +7162,36 @@ function loadSchemaFromTomlString(tomlString) {
7241
7162
  for (const [relName, relDef] of Object.entries(
7242
7163
  modelDef.relationships
7243
7164
  )) {
7244
- relationships[relName] = parseRelationship(relDef);
7165
+ relationships[relName] = parseRelationship(
7166
+ relDef,
7167
+ `[models.${modelName}.relationships.${relName}]`,
7168
+ strict
7169
+ );
7245
7170
  }
7246
7171
  }
7247
7172
  let uniqueConstraints;
7248
7173
  if (modelDef.unique_constraints) {
7249
7174
  uniqueConstraints = [];
7250
7175
  for (const raw of modelDef.unique_constraints) {
7176
+ checkUnknownKeys(
7177
+ raw,
7178
+ KNOWN_UNIQUE_CONSTRAINT_KEYS,
7179
+ `[[models.${modelName}.unique_constraints]]`,
7180
+ strict
7181
+ );
7251
7182
  uniqueConstraints.push({
7252
7183
  name: raw.name,
7253
7184
  fields: [...raw.fields]
7254
7185
  });
7255
7186
  }
7256
7187
  }
7188
+ const className = typeof modelDef.class_name === "string" ? modelDef.class_name : void 0;
7257
7189
  schemas.push(
7258
7190
  defineModelSchema({
7259
7191
  name: modelName,
7260
7192
  fields,
7261
7193
  options: {
7194
+ className,
7262
7195
  uniqueConstraints,
7263
7196
  relationships
7264
7197
  }
@@ -7267,10 +7200,10 @@ function loadSchemaFromTomlString(tomlString) {
7267
7200
  }
7268
7201
  return schemas;
7269
7202
  }
7270
- async function loadSchemaFromToml(filePath) {
7203
+ async function loadSchemaFromToml(filePath, options = {}) {
7271
7204
  const { readFile } = await import("fs/promises");
7272
7205
  const content = await readFile(filePath, "utf-8");
7273
- return loadSchemaFromTomlString(content);
7206
+ return loadSchemaFromTomlString(content, options);
7274
7207
  }
7275
7208
 
7276
7209
  // src/utils/yDocSchema.ts
@@ -7532,10 +7465,8 @@ export {
7532
7465
  DatabaseEngine,
7533
7466
  DocumentClosedError,
7534
7467
  DocumentResolutionError,
7535
- Field,
7536
7468
  LogLevel,
7537
7469
  Logger,
7538
- Model,
7539
7470
  ModelRegistry,
7540
7471
  RecordNotFoundError,
7541
7472
  StringSet,