@forgezero/runtime 0.1.3 → 0.1.5

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.
@@ -21,6 +21,7 @@ var DEFAULT_RESTRICTIONS = {
21
21
  maxDepth: 4,
22
22
  maxFields: 100,
23
23
  maxBytes: 64 * 1024,
24
+ maxArrayItems: 1000,
24
25
  forbidden: ["$ref", "$id", "$dynamicRef", "$dynamicAnchor", "$schema", "definitions", "$defs"]
25
26
  };
26
27
  function restrictJsonSchema(schema, limits = DEFAULT_RESTRICTIONS) {
@@ -59,8 +60,20 @@ function restrictJsonSchema(schema, limits = DEFAULT_RESTRICTIONS) {
59
60
  walk(properties[name], depth + 1, path ? `${path}.${name}` : name);
60
61
  }
61
62
  }
62
- if (record.type === "array" && record.items) {
63
- walk(record.items, depth + 1, `${path}[]`);
63
+ if (record.type === "array") {
64
+ const maximum = record.maxItems;
65
+ if (!Number.isInteger(maximum) || maximum < 0) {
66
+ throw new SchemaError("SCHEMA_ARRAY_UNBOUNDED", "Arrays must declare a finite non-negative integer maxItems.", path || "(root)");
67
+ }
68
+ if (maximum > limits.maxArrayItems) {
69
+ throw new SchemaError("SCHEMA_ARRAY_TOO_LARGE", `Array maxItems ${maximum} exceeds the platform limit of ${limits.maxArrayItems}.`, path || "(root)");
70
+ }
71
+ const minimum = record.minItems;
72
+ if (minimum !== undefined && (!Number.isInteger(minimum) || minimum < 0 || minimum > maximum)) {
73
+ throw new SchemaError("SCHEMA_ARRAY_BOUNDS_INVALID", "minItems must be a non-negative integer no larger than maxItems.", path || "(root)");
74
+ }
75
+ if (record.items)
76
+ walk(record.items, depth + 1, `${path}[]`);
64
77
  }
65
78
  };
66
79
  walk(schema, 1, "");
@@ -194,7 +207,24 @@ function parse(schema, value) {
194
207
  const first = result.errors[0];
195
208
  throw new SchemaError("SCHEMA_INVALID", first?.message ?? "Value does not match schema", first?.path);
196
209
  }
210
+ function typeboxQueryCodec(schema) {
211
+ const issues = (value) => [...Value.Errors(schema, value)].map((error) => ({
212
+ path: error.path || "(root)",
213
+ message: error.message
214
+ }));
215
+ return {
216
+ schema,
217
+ decode(value) {
218
+ const converted = Value.Convert(schema, value);
219
+ return Value.Check(schema, converted) ? { ok: true, value: Value.Clean(schema, converted) } : { ok: false, issues: issues(converted) };
220
+ },
221
+ encode(value) {
222
+ return Value.Check(schema, value) ? { ok: true, value: Value.Clean(schema, value) } : { ok: false, issues: issues(value) };
223
+ }
224
+ };
225
+ }
197
226
  export {
227
+ typeboxQueryCodec,
198
228
  typebox,
199
229
  parse,
200
230
  Type as T
package/dist/schema.d.ts CHANGED
@@ -38,6 +38,8 @@ export interface Restrictions {
38
38
  maxDepth: number;
39
39
  maxFields: number;
40
40
  maxBytes: number;
41
+ /** Largest caller-authored array a persisted value may contain. */
42
+ maxArrayItems: number;
41
43
  /** Keywords refused outright, wherever they appear. */
42
44
  forbidden: readonly string[];
43
45
  }
package/dist/schema.js CHANGED
@@ -21,6 +21,7 @@ var DEFAULT_RESTRICTIONS = {
21
21
  maxDepth: 4,
22
22
  maxFields: 100,
23
23
  maxBytes: 64 * 1024,
24
+ maxArrayItems: 1000,
24
25
  forbidden: ["$ref", "$id", "$dynamicRef", "$dynamicAnchor", "$schema", "definitions", "$defs"]
25
26
  };
26
27
  function restrictJsonSchema(schema, limits = DEFAULT_RESTRICTIONS) {
@@ -59,8 +60,20 @@ function restrictJsonSchema(schema, limits = DEFAULT_RESTRICTIONS) {
59
60
  walk(properties[name], depth + 1, path ? `${path}.${name}` : name);
60
61
  }
61
62
  }
62
- if (record.type === "array" && record.items) {
63
- walk(record.items, depth + 1, `${path}[]`);
63
+ if (record.type === "array") {
64
+ const maximum = record.maxItems;
65
+ if (!Number.isInteger(maximum) || maximum < 0) {
66
+ throw new SchemaError("SCHEMA_ARRAY_UNBOUNDED", "Arrays must declare a finite non-negative integer maxItems.", path || "(root)");
67
+ }
68
+ if (maximum > limits.maxArrayItems) {
69
+ throw new SchemaError("SCHEMA_ARRAY_TOO_LARGE", `Array maxItems ${maximum} exceeds the platform limit of ${limits.maxArrayItems}.`, path || "(root)");
70
+ }
71
+ const minimum = record.minItems;
72
+ if (minimum !== undefined && (!Number.isInteger(minimum) || minimum < 0 || minimum > maximum)) {
73
+ throw new SchemaError("SCHEMA_ARRAY_BOUNDS_INVALID", "minItems must be a non-negative integer no larger than maxItems.", path || "(root)");
74
+ }
75
+ if (record.items)
76
+ walk(record.items, depth + 1, `${path}[]`);
64
77
  }
65
78
  };
66
79
  walk(schema, 1, "");
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
- "//": "Publishing happens from an operator's machine, not CI \u2014 CLAUDE.md records that the absence of CI is deliberate. npm's `provenance` attests a tarball was built by a recognised CI provider from a named commit, so it cannot be produced here: it was set, and the first publish failed with `Automatic provenance generation not supported for provider: null`. A setting that can never be satisfied is worse than none, because it reads as a guarantee nobody is getting. Restore it the day this publishes from CI, and not before.",
3
2
  "name": "@forgezero/runtime",
4
- "version": "0.1.3",
3
+ "version": "0.1.5",
5
4
  "type": "module",
6
- "publishConfig": {
7
- "access": "public"
5
+ "publishConfig": {
6
+ "access": "public",
7
+ "provenance": true
8
8
  },
9
9
  "exports": {
10
10
  "./jobs": {
@@ -43,6 +43,10 @@
43
43
  "types": "./dist/schema-typebox.d.ts",
44
44
  "default": "./dist/schema-typebox.js"
45
45
  },
46
+ "./query": {
47
+ "types": "./dist/query.d.ts",
48
+ "default": "./dist/query.js"
49
+ },
46
50
  "./calendar": {
47
51
  "types": "./dist/calendar.d.ts",
48
52
  "default": "./dist/calendar.js"
@@ -179,7 +183,7 @@
179
183
  "scripts": {
180
184
  "check": "tsc --noEmit",
181
185
  "prebuild": "rm -rf dist",
182
- "build": "bun build src/jobs.ts src/queue.ts src/outbox.ts src/audit.ts src/backup.ts src/notify.ts src/notify-templates.ts src/calendar.ts src/compliance.ts src/pipeline.ts src/totp.ts src/otpauth.ts src/identity.ts src/slip10.ts src/openssh.ts src/ssh-cert.ts src/importers.ts src/snp.ts src/passkey.ts src/custody-crypto.ts src/custody-share.ts src/phrase.ts src/ssh-agent.ts src/schema.ts src/schema-typebox.ts src/finance/discounts.ts src/finance/money.ts src/finance/storage.ts src/finance/custody.ts src/finance/tax.ts src/finance/derive.ts src/finance/venues.ts src/finance/ledger.ts src/finance/rates.ts src/finance/transfers.ts src/finance/chain.ts src/finance/chain-addresses.ts src/finance/chain-deposits.ts src/finance/chain-withdrawals.ts src/finance/chain-reconcile.ts src/finance/market.ts src/finance/commission.ts --root src --outdir dist --target browser --format esm --packages external && tsc --emitDeclarationOnly --declaration --noEmit false --outDir dist",
186
+ "build": "bun build src/query.ts src/jobs.ts src/queue.ts src/outbox.ts src/audit.ts src/backup.ts src/notify.ts src/notify-templates.ts src/calendar.ts src/compliance.ts src/pipeline.ts src/totp.ts src/otpauth.ts src/identity.ts src/slip10.ts src/openssh.ts src/ssh-cert.ts src/importers.ts src/snp.ts src/passkey.ts src/custody-crypto.ts src/custody-share.ts src/phrase.ts src/ssh-agent.ts src/schema.ts src/schema-typebox.ts src/finance/discounts.ts src/finance/money.ts src/finance/storage.ts src/finance/custody.ts src/finance/tax.ts src/finance/derive.ts src/finance/venues.ts src/finance/ledger.ts src/finance/rates.ts src/finance/transfers.ts src/finance/chain.ts src/finance/chain-addresses.ts src/finance/chain-deposits.ts src/finance/chain-withdrawals.ts src/finance/chain-reconcile.ts src/finance/market.ts src/finance/commission.ts --root src --outdir dist --target browser --format esm --packages external && tsc --emitDeclarationOnly --declaration --noEmit false --outDir dist",
183
187
  "prepublishOnly": "bun run check && bun run build"
184
188
  },
185
189
  "dependencies": {
@@ -242,7 +246,7 @@
242
246
  "repository": {
243
247
  "type": "git",
244
248
  "url": "git+https://github.com/forgezero-net/packages.git",
245
- "directory": "packages/runtime"
249
+ "directory": "runtime"
246
250
  },
247
251
  "bugs": "https://github.com/forgezero-net/packages/issues",
248
252
  "sideEffects": false,