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.
package/dist/node.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
  }
@@ -974,15 +981,27 @@ declare function schemaToToml(schema: DiscoveredSchema): string;
974
981
  * - Compound unique constraints are [[models.*.unique_constraints]]
975
982
  */
976
983
 
984
+ interface LoadSchemaOptions {
985
+ /**
986
+ * When true (default), throw on unknown keys at the model, field,
987
+ * relationship, and unique-constraint level. When false, unknown
988
+ * keys are silently ignored (legacy behavior).
989
+ */
990
+ strict?: boolean;
991
+ }
977
992
  /**
978
993
  * Parse a TOML string and return an array of DefinedModelSchema objects.
994
+ *
995
+ * By default operates in strict mode: unknown keys at the model, field,
996
+ * relationship, or unique-constraint level cause an error. Pass
997
+ * `{ strict: false }` to silently ignore unknown keys (legacy behavior).
979
998
  */
980
- declare function loadSchemaFromTomlString(tomlString: string): DefinedModelSchema[];
999
+ declare function loadSchemaFromTomlString(tomlString: string, options?: LoadSchemaOptions): DefinedModelSchema[];
981
1000
  /**
982
1001
  * Read a TOML file from disk and return an array of DefinedModelSchema objects.
983
1002
  * Only available in Node.js environments.
984
1003
  */
985
- declare function loadSchemaFromToml(filePath: string): Promise<DefinedModelSchema[]>;
1004
+ declare function loadSchemaFromToml(filePath: string, options?: LoadSchemaOptions): Promise<DefinedModelSchema[]>;
986
1005
 
987
1006
  /**
988
1007
  * Meta Sync — writes _meta_* YMaps into a YDoc.
package/dist/node.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
  }
@@ -974,15 +981,27 @@ declare function schemaToToml(schema: DiscoveredSchema): string;
974
981
  * - Compound unique constraints are [[models.*.unique_constraints]]
975
982
  */
976
983
 
984
+ interface LoadSchemaOptions {
985
+ /**
986
+ * When true (default), throw on unknown keys at the model, field,
987
+ * relationship, and unique-constraint level. When false, unknown
988
+ * keys are silently ignored (legacy behavior).
989
+ */
990
+ strict?: boolean;
991
+ }
977
992
  /**
978
993
  * Parse a TOML string and return an array of DefinedModelSchema objects.
994
+ *
995
+ * By default operates in strict mode: unknown keys at the model, field,
996
+ * relationship, or unique-constraint level cause an error. Pass
997
+ * `{ strict: false }` to silently ignore unknown keys (legacy behavior).
979
998
  */
980
- declare function loadSchemaFromTomlString(tomlString: string): DefinedModelSchema[];
999
+ declare function loadSchemaFromTomlString(tomlString: string, options?: LoadSchemaOptions): DefinedModelSchema[];
981
1000
  /**
982
1001
  * Read a TOML file from disk and return an array of DefinedModelSchema objects.
983
1002
  * Only available in Node.js environments.
984
1003
  */
985
- declare function loadSchemaFromToml(filePath: string): Promise<DefinedModelSchema[]>;
1004
+ declare function loadSchemaFromToml(filePath: string, options?: LoadSchemaOptions): Promise<DefinedModelSchema[]>;
986
1005
 
987
1006
  /**
988
1007
  * Meta Sync — writes _meta_* YMaps into a YDoc.
package/dist/node.js CHANGED
@@ -6902,6 +6902,7 @@ function defineModelSchema(input) {
6902
6902
  const { name, fields } = input;
6903
6903
  const options = {
6904
6904
  name,
6905
+ className: input.options?.className,
6905
6906
  uniqueConstraints: input.options?.uniqueConstraints ? [...input.options.uniqueConstraints] : void 0,
6906
6907
  relationships: input.options?.relationships
6907
6908
  };
@@ -7001,18 +7002,13 @@ function resolveUniqueConstraints(modelName, fields, customConstraints) {
7001
7002
  function attachSchemaToClass(modelClass, schema) {
7002
7003
  modelClass.schema = schema;
7003
7004
  modelClass.modelName = schema.options.name;
7004
- if (!modelClass.getSchema) {
7005
- Object.defineProperty(modelClass, "getSchema", {
7006
- value: function() {
7007
- return schema.buildRuntimeShape(modelClass);
7008
- },
7009
- writable: false
7010
- });
7011
- } else {
7012
- modelClass.getSchema = function() {
7005
+ Object.defineProperty(modelClass, "getSchema", {
7006
+ value: function() {
7013
7007
  return schema.buildRuntimeShape(modelClass);
7014
- };
7015
- }
7008
+ },
7009
+ writable: false,
7010
+ configurable: true
7011
+ });
7016
7012
  const runtimeShape = schema.buildRuntimeShape(modelClass);
7017
7013
  BaseModel2.attachFieldAccessors(modelClass, runtimeShape.fields);
7018
7014
  return runtimeShape;
@@ -7245,12 +7241,52 @@ var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
7245
7241
  "id",
7246
7242
  "stringset"
7247
7243
  ]);
7248
- function parseFieldOptions(raw) {
7244
+ var KNOWN_FIELD_KEYS = /* @__PURE__ */ new Set([
7245
+ "type",
7246
+ "indexed",
7247
+ "unique",
7248
+ "required",
7249
+ "auto_assign",
7250
+ "max_length",
7251
+ "max_count",
7252
+ "default"
7253
+ ]);
7254
+ var KNOWN_MODEL_KEYS = /* @__PURE__ */ new Set([
7255
+ "fields",
7256
+ "relationships",
7257
+ "unique_constraints",
7258
+ "class_name"
7259
+ ]);
7260
+ var KNOWN_RELATIONSHIP_KEYS = /* @__PURE__ */ new Set([
7261
+ "type",
7262
+ "model",
7263
+ "related_id_field",
7264
+ "join_model",
7265
+ "join_model_local_field",
7266
+ "join_model_related_field",
7267
+ "order_by_field",
7268
+ "order_direction",
7269
+ "join_model_order_by_field",
7270
+ "join_model_order_direction"
7271
+ ]);
7272
+ var KNOWN_UNIQUE_CONSTRAINT_KEYS = /* @__PURE__ */ new Set(["name", "fields"]);
7273
+ function checkUnknownKeys(raw, known, context, strict) {
7274
+ if (!strict) return;
7275
+ for (const key of Object.keys(raw)) {
7276
+ if (!known.has(key)) {
7277
+ throw new Error(
7278
+ `${context}: unknown key "${key}". Allowed: ${[...known].join(", ")}`
7279
+ );
7280
+ }
7281
+ }
7282
+ }
7283
+ function parseFieldOptions(raw, context, strict) {
7249
7284
  if (!raw.type || !VALID_FIELD_TYPES.has(raw.type)) {
7250
7285
  throw new Error(
7251
7286
  `Invalid field type "${raw.type}". Must be one of: ${[...VALID_FIELD_TYPES].join(", ")}`
7252
7287
  );
7253
7288
  }
7289
+ checkUnknownKeys(raw, KNOWN_FIELD_KEYS, context, strict);
7254
7290
  const opts = { type: raw.type };
7255
7291
  if (raw.indexed === true) opts.indexed = true;
7256
7292
  if (raw.unique === true) opts.unique = true;
@@ -7266,8 +7302,9 @@ function requireField(raw, field, context) {
7266
7302
  throw new Error(`Relationship ${context}: missing required field "${field}"`);
7267
7303
  }
7268
7304
  }
7269
- function parseRelationship(raw) {
7305
+ function parseRelationship(raw, context, strict) {
7270
7306
  const type = raw.type;
7307
+ checkUnknownKeys(raw, KNOWN_RELATIONSHIP_KEYS, context, strict);
7271
7308
  if (type === "refersTo") {
7272
7309
  requireField(raw, "model", "refersTo");
7273
7310
  requireField(raw, "related_id_field", "refersTo");
@@ -7309,7 +7346,8 @@ function parseRelationship(raw) {
7309
7346
  }
7310
7347
  throw new Error(`Unknown relationship type: ${type}`);
7311
7348
  }
7312
- function loadSchemaFromTomlString(tomlString) {
7349
+ function loadSchemaFromTomlString(tomlString, options = {}) {
7350
+ const strict = options.strict !== false;
7313
7351
  const parsed = parseToml(tomlString);
7314
7352
  const models = parsed.models;
7315
7353
  if (!models || typeof models !== "object") {
@@ -7317,10 +7355,20 @@ function loadSchemaFromTomlString(tomlString) {
7317
7355
  }
7318
7356
  const schemas = [];
7319
7357
  for (const [modelName, modelDef] of Object.entries(models)) {
7358
+ checkUnknownKeys(
7359
+ modelDef,
7360
+ KNOWN_MODEL_KEYS,
7361
+ `[models.${modelName}]`,
7362
+ strict
7363
+ );
7320
7364
  const fields = {};
7321
7365
  if (modelDef.fields) {
7322
7366
  for (const [fieldName, fieldDef] of Object.entries(modelDef.fields)) {
7323
- fields[fieldName] = parseFieldOptions(fieldDef);
7367
+ fields[fieldName] = parseFieldOptions(
7368
+ fieldDef,
7369
+ `[models.${modelName}.fields.${fieldName}]`,
7370
+ strict
7371
+ );
7324
7372
  }
7325
7373
  }
7326
7374
  let relationships;
@@ -7329,24 +7377,36 @@ function loadSchemaFromTomlString(tomlString) {
7329
7377
  for (const [relName, relDef] of Object.entries(
7330
7378
  modelDef.relationships
7331
7379
  )) {
7332
- relationships[relName] = parseRelationship(relDef);
7380
+ relationships[relName] = parseRelationship(
7381
+ relDef,
7382
+ `[models.${modelName}.relationships.${relName}]`,
7383
+ strict
7384
+ );
7333
7385
  }
7334
7386
  }
7335
7387
  let uniqueConstraints;
7336
7388
  if (modelDef.unique_constraints) {
7337
7389
  uniqueConstraints = [];
7338
7390
  for (const raw of modelDef.unique_constraints) {
7391
+ checkUnknownKeys(
7392
+ raw,
7393
+ KNOWN_UNIQUE_CONSTRAINT_KEYS,
7394
+ `[[models.${modelName}.unique_constraints]]`,
7395
+ strict
7396
+ );
7339
7397
  uniqueConstraints.push({
7340
7398
  name: raw.name,
7341
7399
  fields: [...raw.fields]
7342
7400
  });
7343
7401
  }
7344
7402
  }
7403
+ const className = typeof modelDef.class_name === "string" ? modelDef.class_name : void 0;
7345
7404
  schemas.push(
7346
7405
  defineModelSchema({
7347
7406
  name: modelName,
7348
7407
  fields,
7349
7408
  options: {
7409
+ className,
7350
7410
  uniqueConstraints,
7351
7411
  relationships
7352
7412
  }
@@ -7355,10 +7415,10 @@ function loadSchemaFromTomlString(tomlString) {
7355
7415
  }
7356
7416
  return schemas;
7357
7417
  }
7358
- async function loadSchemaFromToml(filePath) {
7418
+ async function loadSchemaFromToml(filePath, options = {}) {
7359
7419
  const { readFile } = await import("fs/promises");
7360
7420
  const content = await readFile(filePath, "utf-8");
7361
- return loadSchemaFromTomlString(content);
7421
+ return loadSchemaFromTomlString(content, options);
7362
7422
  }
7363
7423
 
7364
7424
  // src/node.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-bao",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "A library providing data modeling capabilities which support live updates and queries.",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -51,10 +51,12 @@
51
51
  },
52
52
  "bin": {
53
53
  "js-bao-codegen": "./dist/codegen.cjs",
54
- "jsbao-codegen": "./dist/codegen.cjs"
54
+ "jsbao-codegen": "./dist/codegen.cjs",
55
+ "js-bao-codegen-v2": "./dist/codegen-v2.cjs",
56
+ "jsbao-codegen-v2": "./dist/codegen-v2.cjs"
55
57
  },
56
58
  "scripts": {
57
- "build": "pnpm build:cli && pnpm codegen && rm -f dist/index.* dist/node.* dist/browser.* dist/cloudflare.* dist/cloudflare-do.* dist/client.* && pnpm build:main",
59
+ "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",
58
60
  "build:main": "pnpm build:browser && pnpm build:node && pnpm build:universal && pnpm build:cloudflare && pnpm build:cloudflare-do && pnpm build:client",
59
61
  "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",
60
62
  "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",
@@ -63,6 +65,7 @@
63
65
  "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",
64
66
  "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",
65
67
  "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",
68
+ "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",
66
69
  "dev": "pnpm build:cli && concurrently \"pnpm codegen:watch\" \"pnpm dev:main\"",
67
70
  "dev:main": "concurrently \"pnpm build:browser:dev --watch\" \"pnpm build:node:dev --watch\" \"pnpm build:universal:dev --watch\"",
68
71
  "dev:simple": "pnpm build:cli && pnpm codegen && pnpm build:main --watch",
@@ -116,11 +119,5 @@
116
119
  "workers"
117
120
  ],
118
121
  "author": "Primitive LLC",
119
- "license": "UNLICENSED",
120
- "pnpm": {
121
- "onlyBuiltDependencies": [
122
- "better-sqlite3",
123
- "esbuild"
124
- ]
125
- }
122
+ "license": "UNLICENSED"
126
123
  }