js-bao 0.4.0 → 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.
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/codegen.cjs CHANGED
@@ -1181,7 +1181,7 @@ var SchemaExtractor = class {
1181
1181
  // package.json
1182
1182
  var package_default = {
1183
1183
  name: "js-bao",
1184
- version: "0.4.0",
1184
+ version: "0.4.1",
1185
1185
  description: "A library providing data modeling capabilities which support live updates and queries.",
1186
1186
  types: "dist/index.d.ts",
1187
1187
  type: "module",
@@ -1232,10 +1232,12 @@ var package_default = {
1232
1232
  },
1233
1233
  bin: {
1234
1234
  "js-bao-codegen": "./dist/codegen.cjs",
1235
- "jsbao-codegen": "./dist/codegen.cjs"
1235
+ "jsbao-codegen": "./dist/codegen.cjs",
1236
+ "js-bao-codegen-v2": "./dist/codegen-v2.cjs",
1237
+ "jsbao-codegen-v2": "./dist/codegen-v2.cjs"
1236
1238
  },
1237
1239
  scripts: {
1238
- build: "pnpm build:cli && pnpm codegen && rm -f dist/index.* dist/node.* dist/browser.* dist/cloudflare.* dist/cloudflare-do.* dist/client.* && pnpm build:main",
1240
+ build: "pnpm build:cli && pnpm build:cli-v2 && pnpm codegen && rm -f dist/index.* dist/node.* dist/browser.* dist/cloudflare.* dist/cloudflare-do.* dist/client.* && pnpm build:main",
1239
1241
  "build:main": "pnpm build:browser && pnpm build:node && pnpm build:universal && pnpm build:cloudflare && pnpm build:cloudflare-do && pnpm build:client",
1240
1242
  "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",
1241
1243
  "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",
@@ -1244,6 +1246,7 @@ var package_default = {
1244
1246
  "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",
1245
1247
  "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",
1246
1248
  "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",
1249
+ "build:cli-v2": "tsup src/cli/codegen-v2.ts --format cjs --dts --platform node --target node18 --external commander --external typescript --external fs --external path --external util --no-splitting",
1247
1250
  dev: 'pnpm build:cli && concurrently "pnpm codegen:watch" "pnpm dev:main"',
1248
1251
  "dev:main": 'concurrently "pnpm build:browser:dev --watch" "pnpm build:node:dev --watch" "pnpm build:universal:dev --watch"',
1249
1252
  "dev:simple": "pnpm build:cli && pnpm codegen && pnpm build:main --watch",
@@ -1297,13 +1300,7 @@ var package_default = {
1297
1300
  "workers"
1298
1301
  ],
1299
1302
  author: "Primitive LLC",
1300
- license: "UNLICENSED",
1301
- pnpm: {
1302
- onlyBuiltDependencies: [
1303
- "better-sqlite3",
1304
- "esbuild"
1305
- ]
1306
- }
1303
+ license: "UNLICENSED"
1307
1304
  };
1308
1305
 
1309
1306
  // src/cli/codegen.ts
package/dist/index.cjs CHANGED
@@ -6901,6 +6901,7 @@ function defineModelSchema(input) {
6901
6901
  const { name, fields } = input;
6902
6902
  const options = {
6903
6903
  name,
6904
+ className: input.options?.className,
6904
6905
  uniqueConstraints: input.options?.uniqueConstraints ? [...input.options.uniqueConstraints] : void 0,
6905
6906
  relationships: input.options?.relationships
6906
6907
  };
@@ -7000,18 +7001,13 @@ function resolveUniqueConstraints(modelName, fields, customConstraints) {
7000
7001
  function attachSchemaToClass(modelClass, schema) {
7001
7002
  modelClass.schema = schema;
7002
7003
  modelClass.modelName = schema.options.name;
7003
- if (!modelClass.getSchema) {
7004
- Object.defineProperty(modelClass, "getSchema", {
7005
- value: function() {
7006
- return schema.buildRuntimeShape(modelClass);
7007
- },
7008
- writable: false
7009
- });
7010
- } else {
7011
- modelClass.getSchema = function() {
7004
+ Object.defineProperty(modelClass, "getSchema", {
7005
+ value: function() {
7012
7006
  return schema.buildRuntimeShape(modelClass);
7013
- };
7014
- }
7007
+ },
7008
+ writable: false,
7009
+ configurable: true
7010
+ });
7015
7011
  const runtimeShape = schema.buildRuntimeShape(modelClass);
7016
7012
  BaseModel.attachFieldAccessors(modelClass, runtimeShape.fields);
7017
7013
  return runtimeShape;
@@ -7088,12 +7084,52 @@ var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
7088
7084
  "id",
7089
7085
  "stringset"
7090
7086
  ]);
7091
- function parseFieldOptions(raw) {
7087
+ var KNOWN_FIELD_KEYS = /* @__PURE__ */ new Set([
7088
+ "type",
7089
+ "indexed",
7090
+ "unique",
7091
+ "required",
7092
+ "auto_assign",
7093
+ "max_length",
7094
+ "max_count",
7095
+ "default"
7096
+ ]);
7097
+ var KNOWN_MODEL_KEYS = /* @__PURE__ */ new Set([
7098
+ "fields",
7099
+ "relationships",
7100
+ "unique_constraints",
7101
+ "class_name"
7102
+ ]);
7103
+ var KNOWN_RELATIONSHIP_KEYS = /* @__PURE__ */ new Set([
7104
+ "type",
7105
+ "model",
7106
+ "related_id_field",
7107
+ "join_model",
7108
+ "join_model_local_field",
7109
+ "join_model_related_field",
7110
+ "order_by_field",
7111
+ "order_direction",
7112
+ "join_model_order_by_field",
7113
+ "join_model_order_direction"
7114
+ ]);
7115
+ var KNOWN_UNIQUE_CONSTRAINT_KEYS = /* @__PURE__ */ new Set(["name", "fields"]);
7116
+ function checkUnknownKeys(raw, known, context, strict) {
7117
+ if (!strict) return;
7118
+ for (const key of Object.keys(raw)) {
7119
+ if (!known.has(key)) {
7120
+ throw new Error(
7121
+ `${context}: unknown key "${key}". Allowed: ${[...known].join(", ")}`
7122
+ );
7123
+ }
7124
+ }
7125
+ }
7126
+ function parseFieldOptions(raw, context, strict) {
7092
7127
  if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
7093
7128
  throw new Error(
7094
7129
  `Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
7095
7130
  );
7096
7131
  }
7132
+ checkUnknownKeys(raw, KNOWN_FIELD_KEYS, context, strict);
7097
7133
  const opts = { type: raw.type };
7098
7134
  if (raw.indexed === true) opts.indexed = true;
7099
7135
  if (raw.unique === true) opts.unique = true;
@@ -7109,8 +7145,9 @@ function requireField(raw, field, context) {
7109
7145
  throw new Error(`Relationship ${context}: missing required field "${field}"`);
7110
7146
  }
7111
7147
  }
7112
- function parseRelationship(raw) {
7148
+ function parseRelationship(raw, context, strict) {
7113
7149
  const type = raw.type;
7150
+ checkUnknownKeys(raw, KNOWN_RELATIONSHIP_KEYS, context, strict);
7114
7151
  if (type === "refersTo") {
7115
7152
  requireField(raw, "model", "refersTo");
7116
7153
  requireField(raw, "related_id_field", "refersTo");
@@ -7152,7 +7189,8 @@ function parseRelationship(raw) {
7152
7189
  }
7153
7190
  throw new Error(`Unknown relationship type: ${type}`);
7154
7191
  }
7155
- function loadSchemaFromTomlString(tomlString) {
7192
+ function loadSchemaFromTomlString(tomlString, options = {}) {
7193
+ const strict = options.strict !== false;
7156
7194
  const parsed = (0, import_smol_toml.parse)(tomlString);
7157
7195
  const models = parsed.models;
7158
7196
  if (!models || typeof models !== "object") {
@@ -7160,10 +7198,20 @@ function loadSchemaFromTomlString(tomlString) {
7160
7198
  }
7161
7199
  const schemas = [];
7162
7200
  for (const [modelName, modelDef] of Object.entries(models)) {
7201
+ checkUnknownKeys(
7202
+ modelDef,
7203
+ KNOWN_MODEL_KEYS,
7204
+ `[models.${modelName}]`,
7205
+ strict
7206
+ );
7163
7207
  const fields = {};
7164
7208
  if (modelDef.fields) {
7165
7209
  for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
7166
- fields[fieldName] = parseFieldOptions(fieldDef);
7210
+ fields[fieldName] = parseFieldOptions(
7211
+ fieldDef,
7212
+ `[models.${modelName}.fields.${fieldName}]`,
7213
+ strict
7214
+ );
7167
7215
  }
7168
7216
  }
7169
7217
  let relationships;
@@ -7172,24 +7220,36 @@ function loadSchemaFromTomlString(tomlString) {
7172
7220
  for (const [relName, relDef] of Object.entries(
7173
7221
  modelDef.relationships
7174
7222
  )) {
7175
- relationships[relName] = parseRelationship(relDef);
7223
+ relationships[relName] = parseRelationship(
7224
+ relDef,
7225
+ `[models.${modelName}.relationships.${relName}]`,
7226
+ strict
7227
+ );
7176
7228
  }
7177
7229
  }
7178
7230
  let uniqueConstraints;
7179
7231
  if (modelDef.unique_constraints) {
7180
7232
  uniqueConstraints = [];
7181
7233
  for (const raw of modelDef.unique_constraints) {
7234
+ checkUnknownKeys(
7235
+ raw,
7236
+ KNOWN_UNIQUE_CONSTRAINT_KEYS,
7237
+ `[[models.${modelName}.unique_constraints]]`,
7238
+ strict
7239
+ );
7182
7240
  uniqueConstraints.push({
7183
7241
  name: raw.name,
7184
7242
  fields: [...raw.fields]
7185
7243
  });
7186
7244
  }
7187
7245
  }
7246
+ const className = typeof modelDef.class_name === "string" ? modelDef.class_name : void 0;
7188
7247
  schemas.push(
7189
7248
  defineModelSchema({
7190
7249
  name: modelName,
7191
7250
  fields,
7192
7251
  options: {
7252
+ className,
7193
7253
  uniqueConstraints,
7194
7254
  relationships
7195
7255
  }
@@ -7198,10 +7258,10 @@ function loadSchemaFromTomlString(tomlString) {
7198
7258
  }
7199
7259
  return schemas;
7200
7260
  }
7201
- async function loadSchemaFromToml(filePath) {
7261
+ async function loadSchemaFromToml(filePath, options = {}) {
7202
7262
  const { readFile } = await import("fs/promises");
7203
7263
  const content = await readFile(filePath, "utf-8");
7204
- return loadSchemaFromTomlString(content);
7264
+ return loadSchemaFromTomlString(content, options);
7205
7265
  }
7206
7266
 
7207
7267
  // src/utils/yDocSchema.ts
package/dist/index.d.cts CHANGED
@@ -40,6 +40,13 @@ interface UniqueConstraintConfig {
40
40
  }
41
41
  interface ModelOptions {
42
42
  name: string;
43
+ /**
44
+ * Optional PascalCase class name. Used by the v2 codegen to drive
45
+ * generated TypeScript class names (and relationship method names that
46
+ * derive from a target's class name). When absent, the v2 codegen
47
+ * falls back to suffix-based singularization of `name`.
48
+ */
49
+ className?: string;
43
50
  uniqueConstraints?: UniqueConstraintConfig[];
44
51
  relationships?: Record<string, RelationshipConfig>;
45
52
  }
@@ -847,15 +854,27 @@ declare function syncInferredMeta(yDoc: Y.Doc, modelName: string, recordData: Re
847
854
  * - Compound unique constraints are [[models.*.unique_constraints]]
848
855
  */
849
856
 
857
+ interface LoadSchemaOptions {
858
+ /**
859
+ * When true (default), throw on unknown keys at the model, field,
860
+ * relationship, and unique-constraint level. When false, unknown
861
+ * keys are silently ignored (legacy behavior).
862
+ */
863
+ strict?: boolean;
864
+ }
850
865
  /**
851
866
  * Parse a TOML string and return an array of DefinedModelSchema objects.
867
+ *
868
+ * By default operates in strict mode: unknown keys at the model, field,
869
+ * relationship, or unique-constraint level cause an error. Pass
870
+ * `{ strict: false }` to silently ignore unknown keys (legacy behavior).
852
871
  */
853
- declare function loadSchemaFromTomlString(tomlString: string): DefinedModelSchema[];
872
+ declare function loadSchemaFromTomlString(tomlString: string, options?: LoadSchemaOptions): DefinedModelSchema[];
854
873
  /**
855
874
  * Read a TOML file from disk and return an array of DefinedModelSchema objects.
856
875
  * Only available in Node.js environments.
857
876
  */
858
- declare function loadSchemaFromToml(filePath: string): Promise<DefinedModelSchema[]>;
877
+ declare function loadSchemaFromToml(filePath: string, options?: LoadSchemaOptions): Promise<DefinedModelSchema[]>;
859
878
 
860
879
  /**
861
880
  * YDoc Schema Discovery
package/dist/index.d.ts CHANGED
@@ -40,6 +40,13 @@ interface UniqueConstraintConfig {
40
40
  }
41
41
  interface ModelOptions {
42
42
  name: string;
43
+ /**
44
+ * Optional PascalCase class name. Used by the v2 codegen to drive
45
+ * generated TypeScript class names (and relationship method names that
46
+ * derive from a target's class name). When absent, the v2 codegen
47
+ * falls back to suffix-based singularization of `name`.
48
+ */
49
+ className?: string;
43
50
  uniqueConstraints?: UniqueConstraintConfig[];
44
51
  relationships?: Record<string, RelationshipConfig>;
45
52
  }
@@ -847,15 +854,27 @@ declare function syncInferredMeta(yDoc: Y.Doc, modelName: string, recordData: Re
847
854
  * - Compound unique constraints are [[models.*.unique_constraints]]
848
855
  */
849
856
 
857
+ interface LoadSchemaOptions {
858
+ /**
859
+ * When true (default), throw on unknown keys at the model, field,
860
+ * relationship, and unique-constraint level. When false, unknown
861
+ * keys are silently ignored (legacy behavior).
862
+ */
863
+ strict?: boolean;
864
+ }
850
865
  /**
851
866
  * Parse a TOML string and return an array of DefinedModelSchema objects.
867
+ *
868
+ * By default operates in strict mode: unknown keys at the model, field,
869
+ * relationship, or unique-constraint level cause an error. Pass
870
+ * `{ strict: false }` to silently ignore unknown keys (legacy behavior).
852
871
  */
853
- declare function loadSchemaFromTomlString(tomlString: string): DefinedModelSchema[];
872
+ declare function loadSchemaFromTomlString(tomlString: string, options?: LoadSchemaOptions): DefinedModelSchema[];
854
873
  /**
855
874
  * Read a TOML file from disk and return an array of DefinedModelSchema objects.
856
875
  * Only available in Node.js environments.
857
876
  */
858
- declare function loadSchemaFromToml(filePath: string): Promise<DefinedModelSchema[]>;
877
+ declare function loadSchemaFromToml(filePath: string, options?: LoadSchemaOptions): Promise<DefinedModelSchema[]>;
859
878
 
860
879
  /**
861
880
  * YDoc Schema Discovery
package/dist/index.js CHANGED
@@ -6843,6 +6843,7 @@ function defineModelSchema(input) {
6843
6843
  const { name, fields } = input;
6844
6844
  const options = {
6845
6845
  name,
6846
+ className: input.options?.className,
6846
6847
  uniqueConstraints: input.options?.uniqueConstraints ? [...input.options.uniqueConstraints] : void 0,
6847
6848
  relationships: input.options?.relationships
6848
6849
  };
@@ -6942,18 +6943,13 @@ function resolveUniqueConstraints(modelName, fields, customConstraints) {
6942
6943
  function attachSchemaToClass(modelClass, schema) {
6943
6944
  modelClass.schema = schema;
6944
6945
  modelClass.modelName = schema.options.name;
6945
- if (!modelClass.getSchema) {
6946
- Object.defineProperty(modelClass, "getSchema", {
6947
- value: function() {
6948
- return schema.buildRuntimeShape(modelClass);
6949
- },
6950
- writable: false
6951
- });
6952
- } else {
6953
- modelClass.getSchema = function() {
6946
+ Object.defineProperty(modelClass, "getSchema", {
6947
+ value: function() {
6954
6948
  return schema.buildRuntimeShape(modelClass);
6955
- };
6956
- }
6949
+ },
6950
+ writable: false,
6951
+ configurable: true
6952
+ });
6957
6953
  const runtimeShape = schema.buildRuntimeShape(modelClass);
6958
6954
  BaseModel.attachFieldAccessors(modelClass, runtimeShape.fields);
6959
6955
  return runtimeShape;
@@ -7030,12 +7026,52 @@ var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
7030
7026
  "id",
7031
7027
  "stringset"
7032
7028
  ]);
7033
- 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) {
7034
7069
  if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
7035
7070
  throw new Error(
7036
7071
  `Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
7037
7072
  );
7038
7073
  }
7074
+ checkUnknownKeys(raw, KNOWN_FIELD_KEYS, context, strict);
7039
7075
  const opts = { type: raw.type };
7040
7076
  if (raw.indexed === true) opts.indexed = true;
7041
7077
  if (raw.unique === true) opts.unique = true;
@@ -7051,8 +7087,9 @@ function requireField(raw, field, context) {
7051
7087
  throw new Error(`Relationship ${context}: missing required field "${field}"`);
7052
7088
  }
7053
7089
  }
7054
- function parseRelationship(raw) {
7090
+ function parseRelationship(raw, context, strict) {
7055
7091
  const type = raw.type;
7092
+ checkUnknownKeys(raw, KNOWN_RELATIONSHIP_KEYS, context, strict);
7056
7093
  if (type === "refersTo") {
7057
7094
  requireField(raw, "model", "refersTo");
7058
7095
  requireField(raw, "related_id_field", "refersTo");
@@ -7094,7 +7131,8 @@ function parseRelationship(raw) {
7094
7131
  }
7095
7132
  throw new Error(`Unknown relationship type: ${type}`);
7096
7133
  }
7097
- function loadSchemaFromTomlString(tomlString) {
7134
+ function loadSchemaFromTomlString(tomlString, options = {}) {
7135
+ const strict = options.strict !== false;
7098
7136
  const parsed = parseToml(tomlString);
7099
7137
  const models = parsed.models;
7100
7138
  if (!models || typeof models !== "object") {
@@ -7102,10 +7140,20 @@ function loadSchemaFromTomlString(tomlString) {
7102
7140
  }
7103
7141
  const schemas = [];
7104
7142
  for (const [modelName, modelDef] of Object.entries(models)) {
7143
+ checkUnknownKeys(
7144
+ modelDef,
7145
+ KNOWN_MODEL_KEYS,
7146
+ `[models.${modelName}]`,
7147
+ strict
7148
+ );
7105
7149
  const fields = {};
7106
7150
  if (modelDef.fields) {
7107
7151
  for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
7108
- fields[fieldName] = parseFieldOptions(fieldDef);
7152
+ fields[fieldName] = parseFieldOptions(
7153
+ fieldDef,
7154
+ `[models.${modelName}.fields.${fieldName}]`,
7155
+ strict
7156
+ );
7109
7157
  }
7110
7158
  }
7111
7159
  let relationships;
@@ -7114,24 +7162,36 @@ function loadSchemaFromTomlString(tomlString) {
7114
7162
  for (const [relName, relDef] of Object.entries(
7115
7163
  modelDef.relationships
7116
7164
  )) {
7117
- relationships[relName] = parseRelationship(relDef);
7165
+ relationships[relName] = parseRelationship(
7166
+ relDef,
7167
+ `[models.${modelName}.relationships.${relName}]`,
7168
+ strict
7169
+ );
7118
7170
  }
7119
7171
  }
7120
7172
  let uniqueConstraints;
7121
7173
  if (modelDef.unique_constraints) {
7122
7174
  uniqueConstraints = [];
7123
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
+ );
7124
7182
  uniqueConstraints.push({
7125
7183
  name: raw.name,
7126
7184
  fields: [...raw.fields]
7127
7185
  });
7128
7186
  }
7129
7187
  }
7188
+ const className = typeof modelDef.class_name === "string" ? modelDef.class_name : void 0;
7130
7189
  schemas.push(
7131
7190
  defineModelSchema({
7132
7191
  name: modelName,
7133
7192
  fields,
7134
7193
  options: {
7194
+ className,
7135
7195
  uniqueConstraints,
7136
7196
  relationships
7137
7197
  }
@@ -7140,10 +7200,10 @@ function loadSchemaFromTomlString(tomlString) {
7140
7200
  }
7141
7201
  return schemas;
7142
7202
  }
7143
- async function loadSchemaFromToml(filePath) {
7203
+ async function loadSchemaFromToml(filePath, options = {}) {
7144
7204
  const { readFile } = await import("fs/promises");
7145
7205
  const content = await readFile(filePath, "utf-8");
7146
- return loadSchemaFromTomlString(content);
7206
+ return loadSchemaFromTomlString(content, options);
7147
7207
  }
7148
7208
 
7149
7209
  // src/utils/yDocSchema.ts
package/dist/node.cjs CHANGED
@@ -6965,6 +6965,7 @@ function defineModelSchema(input) {
6965
6965
  const { name, fields } = input;
6966
6966
  const options = {
6967
6967
  name,
6968
+ className: input.options?.className,
6968
6969
  uniqueConstraints: input.options?.uniqueConstraints ? [...input.options.uniqueConstraints] : void 0,
6969
6970
  relationships: input.options?.relationships
6970
6971
  };
@@ -7064,18 +7065,13 @@ function resolveUniqueConstraints(modelName, fields, customConstraints) {
7064
7065
  function attachSchemaToClass(modelClass, schema) {
7065
7066
  modelClass.schema = schema;
7066
7067
  modelClass.modelName = schema.options.name;
7067
- if (!modelClass.getSchema) {
7068
- Object.defineProperty(modelClass, "getSchema", {
7069
- value: function() {
7070
- return schema.buildRuntimeShape(modelClass);
7071
- },
7072
- writable: false
7073
- });
7074
- } else {
7075
- modelClass.getSchema = function() {
7068
+ Object.defineProperty(modelClass, "getSchema", {
7069
+ value: function() {
7076
7070
  return schema.buildRuntimeShape(modelClass);
7077
- };
7078
- }
7071
+ },
7072
+ writable: false,
7073
+ configurable: true
7074
+ });
7079
7075
  const runtimeShape = schema.buildRuntimeShape(modelClass);
7080
7076
  BaseModel2.attachFieldAccessors(modelClass, runtimeShape.fields);
7081
7077
  return runtimeShape;
@@ -7308,12 +7304,52 @@ var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
7308
7304
  "id",
7309
7305
  "stringset"
7310
7306
  ]);
7311
- function parseFieldOptions(raw) {
7307
+ var KNOWN_FIELD_KEYS = /* @__PURE__ */ new Set([
7308
+ "type",
7309
+ "indexed",
7310
+ "unique",
7311
+ "required",
7312
+ "auto_assign",
7313
+ "max_length",
7314
+ "max_count",
7315
+ "default"
7316
+ ]);
7317
+ var KNOWN_MODEL_KEYS = /* @__PURE__ */ new Set([
7318
+ "fields",
7319
+ "relationships",
7320
+ "unique_constraints",
7321
+ "class_name"
7322
+ ]);
7323
+ var KNOWN_RELATIONSHIP_KEYS = /* @__PURE__ */ new Set([
7324
+ "type",
7325
+ "model",
7326
+ "related_id_field",
7327
+ "join_model",
7328
+ "join_model_local_field",
7329
+ "join_model_related_field",
7330
+ "order_by_field",
7331
+ "order_direction",
7332
+ "join_model_order_by_field",
7333
+ "join_model_order_direction"
7334
+ ]);
7335
+ var KNOWN_UNIQUE_CONSTRAINT_KEYS = /* @__PURE__ */ new Set(["name", "fields"]);
7336
+ function checkUnknownKeys(raw, known, context, strict) {
7337
+ if (!strict) return;
7338
+ for (const key of Object.keys(raw)) {
7339
+ if (!known.has(key)) {
7340
+ throw new Error(
7341
+ `${context}: unknown key "${key}". Allowed: ${[...known].join(", ")}`
7342
+ );
7343
+ }
7344
+ }
7345
+ }
7346
+ function parseFieldOptions(raw, context, strict) {
7312
7347
  if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
7313
7348
  throw new Error(
7314
7349
  `Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
7315
7350
  );
7316
7351
  }
7352
+ checkUnknownKeys(raw, KNOWN_FIELD_KEYS, context, strict);
7317
7353
  const opts = { type: raw.type };
7318
7354
  if (raw.indexed === true) opts.indexed = true;
7319
7355
  if (raw.unique === true) opts.unique = true;
@@ -7329,8 +7365,9 @@ function requireField(raw, field, context) {
7329
7365
  throw new Error(`Relationship ${context}: missing required field "${field}"`);
7330
7366
  }
7331
7367
  }
7332
- function parseRelationship(raw) {
7368
+ function parseRelationship(raw, context, strict) {
7333
7369
  const type = raw.type;
7370
+ checkUnknownKeys(raw, KNOWN_RELATIONSHIP_KEYS, context, strict);
7334
7371
  if (type === "refersTo") {
7335
7372
  requireField(raw, "model", "refersTo");
7336
7373
  requireField(raw, "related_id_field", "refersTo");
@@ -7372,7 +7409,8 @@ function parseRelationship(raw) {
7372
7409
  }
7373
7410
  throw new Error(`Unknown relationship type: ${type}`);
7374
7411
  }
7375
- function loadSchemaFromTomlString(tomlString) {
7412
+ function loadSchemaFromTomlString(tomlString, options = {}) {
7413
+ const strict = options.strict !== false;
7376
7414
  const parsed = (0, import_smol_toml.parse)(tomlString);
7377
7415
  const models = parsed.models;
7378
7416
  if (!models || typeof models !== "object") {
@@ -7380,10 +7418,20 @@ function loadSchemaFromTomlString(tomlString) {
7380
7418
  }
7381
7419
  const schemas = [];
7382
7420
  for (const [modelName, modelDef] of Object.entries(models)) {
7421
+ checkUnknownKeys(
7422
+ modelDef,
7423
+ KNOWN_MODEL_KEYS,
7424
+ `[models.${modelName}]`,
7425
+ strict
7426
+ );
7383
7427
  const fields = {};
7384
7428
  if (modelDef.fields) {
7385
7429
  for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
7386
- fields[fieldName] = parseFieldOptions(fieldDef);
7430
+ fields[fieldName] = parseFieldOptions(
7431
+ fieldDef,
7432
+ `[models.${modelName}.fields.${fieldName}]`,
7433
+ strict
7434
+ );
7387
7435
  }
7388
7436
  }
7389
7437
  let relationships;
@@ -7392,24 +7440,36 @@ function loadSchemaFromTomlString(tomlString) {
7392
7440
  for (const [relName, relDef] of Object.entries(
7393
7441
  modelDef.relationships
7394
7442
  )) {
7395
- relationships[relName] = parseRelationship(relDef);
7443
+ relationships[relName] = parseRelationship(
7444
+ relDef,
7445
+ `[models.${modelName}.relationships.${relName}]`,
7446
+ strict
7447
+ );
7396
7448
  }
7397
7449
  }
7398
7450
  let uniqueConstraints;
7399
7451
  if (modelDef.unique_constraints) {
7400
7452
  uniqueConstraints = [];
7401
7453
  for (const raw of modelDef.unique_constraints) {
7454
+ checkUnknownKeys(
7455
+ raw,
7456
+ KNOWN_UNIQUE_CONSTRAINT_KEYS,
7457
+ `[[models.${modelName}.unique_constraints]]`,
7458
+ strict
7459
+ );
7402
7460
  uniqueConstraints.push({
7403
7461
  name: raw.name,
7404
7462
  fields: [...raw.fields]
7405
7463
  });
7406
7464
  }
7407
7465
  }
7466
+ const className = typeof modelDef.class_name === "string" ? modelDef.class_name : void 0;
7408
7467
  schemas.push(
7409
7468
  defineModelSchema({
7410
7469
  name: modelName,
7411
7470
  fields,
7412
7471
  options: {
7472
+ className,
7413
7473
  uniqueConstraints,
7414
7474
  relationships
7415
7475
  }
@@ -7418,10 +7478,10 @@ function loadSchemaFromTomlString(tomlString) {
7418
7478
  }
7419
7479
  return schemas;
7420
7480
  }
7421
- async function loadSchemaFromToml(filePath) {
7481
+ async function loadSchemaFromToml(filePath, options = {}) {
7422
7482
  const { readFile } = await import("fs/promises");
7423
7483
  const content = await readFile(filePath, "utf-8");
7424
- return loadSchemaFromTomlString(content);
7484
+ return loadSchemaFromTomlString(content, options);
7425
7485
  }
7426
7486
 
7427
7487
  // src/node.ts