@kindgi/schema 0.1.7-rc.0 → 0.1.8-rc.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/dialect.js CHANGED
@@ -1,31 +1,6 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // Copyright (C) 2026 Kindgi Inc.
3
- /**
4
- * Compile a JSON Schema in the dialect it declares (`$schema`). Kindgi's
5
- * own schemas are Draft 2020-12, the default when a schema declares none.
6
- * A schema from elsewhere (an MCP server: the TypeScript MCP SDK emits
7
- * draft-07) means its keywords as its dialect defines them: draft-07's
8
- * array-form `items` is a tuple, 2020-12's is not. So each dialect gets
9
- * Ajv's class for it, not 2020-12's with another meta-schema added.
10
- *
11
- * `strict` is Ajv's strict mode, an authoring lint (unknown keywords and
12
- * formats, loose tuples): right for the schemas a pack's author writes,
13
- * wrong for a schema someone else's server sends, which is valid JSON Schema
14
- * without being written to that standard. A union of types
15
- * (`type: ['string', 'number']`) is standard JSON Schema, and what Zod 4
16
- * writes for a union of scalars, so it's allowed in either mode
17
- * (`ALLOW_UNION_TYPES`).
18
- */
19
- import { createRequire } from 'node:module';
20
- import { Ajv } from 'ajv';
21
- import * as addFormatsModule from 'ajv-formats';
22
- import { Ajv2019 } from 'ajv/dist/2019.js';
23
- import { Ajv2020 } from 'ajv/dist/2020.js';
24
- const addFormatsRaw = addFormatsModule;
25
- const addFormats = typeof addFormatsRaw === 'function'
26
- ? addFormatsRaw
27
- : addFormatsRaw.default;
28
- const require = createRequire(import.meta.url);
3
+ import { compileTenantSchema, holdTenantSchema } from './bounded.js';
29
4
  /**
30
5
  * Every Kindgi schema compiler takes a union of types (`type: ['string', 'number']`): standard
31
6
  * JSON Schema, which Ajv's strict mode otherwise refuses, and what Zod 4 writes for
@@ -63,30 +38,33 @@ function listOf(items) {
63
38
  return items.length < 2 ? items.join('') : `${items.slice(0, -1).join(', ')} or ${items.at(-1)}`;
64
39
  }
65
40
  /**
66
- * A validator for `schema`, compiled in its declared dialect. Throws when
67
- * the dialect isn't supported (or allowed) or the schema doesn't compile,
68
- * as `ajv.compile` does.
41
+ * A validator for `schema`, compiled in its declared dialect under the
42
+ * process's bounds (`compileTenantSchema`). Throws when the dialect isn't
43
+ * supported (or allowed), the schema is over a bound, or it doesn't
44
+ * compile, as `ajv.compile` does.
69
45
  */
70
46
  export function compileJsonSchema(schema, options = {}) {
71
- const dialect = jsonSchemaDialect(schema, options.dialects);
72
- const ajvOptions = {
73
- strict: options.strict ?? true,
74
- allErrors: true,
75
- allowUnionTypes: ALLOW_UNION_TYPES,
76
- ...(options.useDefaults === true && { useDefaults: true }),
47
+ return compileTenantSchema(schema, compileFor(schema, options));
48
+ }
49
+ /**
50
+ * `compileJsonSchema` for a caller that keeps the schema: compiled now,
51
+ * and what to call for its validator each time (`holdTenantSchema`). The
52
+ * cache stays all that holds a JSON schema's validator. A schema JSON
53
+ * can't carry (a key whose value is `undefined`, say) is never cached, so
54
+ * it's held as compiled rather than compiled on every call.
55
+ */
56
+ export function holdJsonSchema(schema, options = {}) {
57
+ return holdTenantSchema(schema, compileFor(schema, options));
58
+ }
59
+ function compileFor(schema, options) {
60
+ return {
61
+ dialect: jsonSchemaDialect(schema, options.dialects),
62
+ options: {
63
+ strict: options.strict ?? true,
64
+ allErrors: true,
65
+ allowUnionTypes: ALLOW_UNION_TYPES,
66
+ ...(options.useDefaults === true && { useDefaults: true }),
67
+ },
77
68
  };
78
- let ajv;
79
- if (dialect === '2020-12')
80
- ajv = new Ajv2020(ajvOptions);
81
- else if (dialect === '2019-09')
82
- ajv = new Ajv2019(ajvOptions);
83
- else {
84
- ajv = new Ajv(ajvOptions);
85
- if (dialect === 'draft-06') {
86
- ajv.addMetaSchema(require('ajv/dist/refs/json-schema-draft-06.json'));
87
- }
88
- }
89
- addFormats(ajv);
90
- return ajv.compile(schema);
91
69
  }
92
70
  //# sourceMappingURL=dialect.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dialect.js","sourceRoot":"","sources":["../src/dialect.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,OAAO,KAAK,gBAAgB,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAI3C,MAAM,aAAa,GAAG,gBAA2B,CAAC;AAClD,MAAM,UAAU,GACd,OAAO,aAAa,KAAK,UAAU;IACjC,CAAC,CAAE,aAA8B;IACjC,CAAC,CAAE,aAA2C,CAAC,OAAO,CAAC;AAE3D,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAKtC,MAAM,QAAQ,GAA2C,IAAI,GAAG,CAA4B;IAC1F,CAAC,wCAAwC,EAAE,UAAU,CAAC;IACtD,CAAC,wCAAwC,EAAE,UAAU,CAAC;IACtD,CAAC,8CAA8C,EAAE,SAAS,CAAC;IAC3D,CAAC,8CAA8C,EAAE,SAAS,CAAC;CAC5D,CAAC,CAAC;AAEH,MAAM,YAAY,GAAiC,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;AAE1E;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAyC,EACzC,UAAwC,YAAY;IAEpD,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC;IAChC,MAAM,OAAO,GACX,QAAQ,KAAK,SAAS;QACpB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,OAAO,QAAQ,KAAK,QAAQ;YAC5B,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC1C,CAAC,CAAC,SAAS,CAAC;IAClB,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,wBAAwB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,gDAAgD,KAAK,KAAK,MAAM,CAAC,OAAO,CAAC,GAAG,CAC7H,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,kCAAkC;AAClC,SAAS,MAAM,CAAC,KAAwB;IACtC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACnG,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAyC,EACzC,UAAoC,EAAE;IAEtC,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG;QACjB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI;QAC9B,SAAS,EAAE,IAAI;QACf,eAAe,EAAE,iBAAiB;QAClC,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,IAAI,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;KAC3D,CAAC;IACF,IAAI,GAAW,CAAC;IAChB,IAAI,OAAO,KAAK,SAAS;QAAE,GAAG,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;SACpD,IAAI,OAAO,KAAK,SAAS;QAAE,GAAG,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;SACzD,CAAC;QACJ,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QAC1B,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;YAC3B,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,UAAU,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,GAAG,CAAC,OAAO,CAAC,MAAgB,CAAC,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"dialect.js","sourceRoot":"","sources":["../src/dialect.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAqBjC,OAAO,EAA4B,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE/F;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAKtC,MAAM,QAAQ,GAA2C,IAAI,GAAG,CAA4B;IAC1F,CAAC,wCAAwC,EAAE,UAAU,CAAC;IACtD,CAAC,wCAAwC,EAAE,UAAU,CAAC;IACtD,CAAC,8CAA8C,EAAE,SAAS,CAAC;IAC3D,CAAC,8CAA8C,EAAE,SAAS,CAAC;CAC5D,CAAC,CAAC;AAEH,MAAM,YAAY,GAAiC,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;AAE1E;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAyC,EACzC,UAAwC,YAAY;IAEpD,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC;IAChC,MAAM,OAAO,GACX,QAAQ,KAAK,SAAS;QACpB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,OAAO,QAAQ,KAAK,QAAQ;YAC5B,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC1C,CAAC,CAAC,SAAS,CAAC;IAClB,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,wBAAwB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,gDAAgD,KAAK,KAAK,MAAM,CAAC,OAAO,CAAC,GAAG,CAC7H,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,kCAAkC;AAClC,SAAS,MAAM,CAAC,KAAwB;IACtC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACnG,CAAC;AAWD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAyC,EACzC,UAAoC,EAAE;IAEtC,OAAO,mBAAmB,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAyC,EACzC,UAAoC,EAAE;IAEtC,OAAO,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,UAAU,CACjB,MAAyC,EACzC,OAAiC;IAEjC,OAAO;QACL,OAAO,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;QACpD,OAAO,EAAE;YACP,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI;YAC9B,SAAS,EAAE,IAAI;YACf,eAAe,EAAE,iBAAiB;YAClC,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,IAAI,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;SAC3D;KACF,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export { canonicalize } from './canonical.js';
2
2
  export type { InvalidZodConversionError, SchemaCompileError, SchemaError, SchemaLoadError, SchemaNotFoundError, SchemaParseError, ValidationError, } from './errors.js';
3
3
  export { compileInlineSchema, createSpecRegistry, loadSpecRegistry } from './registry.js';
4
- export { ALLOW_UNION_TYPES, compileJsonSchema, jsonSchemaDialect } from './dialect.js';
4
+ export { SchemaCompileBudgetError } from './compile-budget.js';
5
+ export { ALLOW_UNION_TYPES, compileJsonSchema, holdJsonSchema, jsonSchemaDialect, } from './dialect.js';
5
6
  export type { CompileJsonSchemaOptions, JsonSchemaDialect } from './dialect.js';
6
7
  export type { CompiledInlineSchema, SpecRegistry, ValidationErrorLike } from './registry.js';
7
8
  export { versionOf } from './version.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACV,yBAAyB,EACzB,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACvF,YAAY,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAChF,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,UAAU,EACV,YAAY,EACZ,aAAa,GACd,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACV,yBAAyB,EACzB,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAChF,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,UAAU,EACV,YAAY,EACZ,aAAa,GACd,MAAM,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -2,7 +2,8 @@
2
2
  // Copyright (C) 2026 Kindgi Inc.
3
3
  export { canonicalize } from './canonical.js';
4
4
  export { compileInlineSchema, createSpecRegistry, loadSpecRegistry } from './registry.js';
5
- export { ALLOW_UNION_TYPES, compileJsonSchema, jsonSchemaDialect } from './dialect.js';
5
+ export { SchemaCompileBudgetError } from './compile-budget.js';
6
+ export { ALLOW_UNION_TYPES, compileJsonSchema, holdJsonSchema, jsonSchemaDialect, } from './dialect.js';
6
7
  export { versionOf } from './version.js';
7
8
  export { isJsonSchemaObject, isZodSchema, loadZodConverter, loadZodConverterSync, parseWithSchema, schemaKindOf, toJSONSchema, toJSONSchemaSync, } from './zod.js';
8
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAU9C,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGvF,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,gBAAgB,GACjB,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAU9C,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,gBAAgB,GACjB,MAAM,UAAU,CAAC"}
@@ -27,7 +27,10 @@ export interface SpecRegistry {
27
27
  ids(): readonly string[];
28
28
  }
29
29
  /**
30
- * Build a SpecRegistry from an array of already-parsed schema documents.
30
+ * Build a SpecRegistry from an array of already-parsed schema documents:
31
+ * Kindgi's own (`@kindgi/specs`), whose patterns run on V8 as the rest of
32
+ * Kindgi's code does. A tenant's schema goes through `compileJsonSchema`
33
+ * or `compileInlineSchema`, under the bounds.
31
34
  *
32
35
  * All schemas are registered with the Ajv instance FIRST (so cross-schema
33
36
  * `$ref`s can resolve), then validators are compiled and cached.
@@ -48,7 +51,10 @@ export interface CompiledInlineSchema {
48
51
  /**
49
52
  * Validate `data`. Returns the original value on success (typed as `T`
50
53
  * for caller convenience — the runtime does not verify the T assertion
51
- * beyond schema conformance).
54
+ * beyond schema conformance). It keeps the schema's cache key, not its
55
+ * validator: once the cache has dropped the validator, it compiles the
56
+ * schema again, a recompile the tenant's budget counts, so it throws
57
+ * `SchemaCompileBudgetError` when the tenant has spent its budget.
52
58
  */
53
59
  validate<T = unknown>(data: unknown): Result<T, ValidationErrorLike>;
54
60
  /** The raw schema JSON, for round-tripping or debugging. */
@@ -65,21 +71,23 @@ export interface ValidationErrorLike {
65
71
  readonly message: string;
66
72
  readonly errors: readonly unknown[];
67
73
  }
74
+ /**
75
+ * Keywords an inline schema may carry for Kindgi to read, with no effect
76
+ * on validation: `x-kindgi-tunable` marks a settings key an improvement
77
+ * pass may search.
78
+ */
79
+ export declare const INLINE_ANNOTATIONS: readonly string[];
68
80
  /**
69
81
  * Compile a single anonymous JSON Schema (draft 2020-12) into a reusable
70
82
  * validator. Returns `err` if the schema itself is malformed (Ajv rejects
71
83
  * it), which is how the flow loader surfaces `LoopOutputSchemaError` and
72
- * similar load-time diagnostics.
84
+ * similar load-time diagnostics. Throws `SchemaCompileBudgetError` when the
85
+ * compile counts against a tenant that has spent its budget: that isn't
86
+ * the schema's fault, and the caller answers it as a limit, not an issue.
73
87
  *
74
88
  * Design note: this is intentionally decoupled from `SpecRegistry` — inline
75
89
  * schemas don't have a `$id` and don't need cross-schema `$ref` resolution.
76
90
  */
77
- /**
78
- * Keywords an inline schema may carry for Kindgi to read, with no effect
79
- * on validation: `x-kindgi-tunable` marks a settings key an improvement
80
- * pass may search.
81
- */
82
- export declare const INLINE_ANNOTATIONS: readonly string[];
83
91
  export declare function compileInlineSchema(schema: unknown): Result<CompiledInlineSchema, SchemaError>;
84
92
  /**
85
93
  * Load a SpecRegistry from a directory of `*.schema.json` files.
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY/C;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAEzE,+DAA+D;IAC/D,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAEpD,+DAA+D;IAC/D,GAAG,IAAI,SAAS,MAAM,EAAE,CAAC;CAC1B;AA2ED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CAiEjG;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;IACrE,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC;CACrC;AAED;;;;;;;;GAQG;AACH;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAAyB,CAAC;AAE1E,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,oBAAoB,EAAE,WAAW,CAAC,CA4C9F;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAmD9F"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAK5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAEzE,+DAA+D;IAC/D,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAEpD,+DAA+D;IAC/D,GAAG,IAAI,SAAS,MAAM,EAAE,CAAC;CAC1B;AA2ED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CAgEjG;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;IACrE,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC;CACrC;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAAyB,CAAC;AAE1E;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,oBAAoB,EAAE,WAAW,CAAC,CA0C9F;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAmD9F"}
package/dist/registry.js CHANGED
@@ -2,15 +2,9 @@
2
2
  // Copyright (C) 2026 Kindgi Inc.
3
3
  import { readFile, readdir } from 'node:fs/promises';
4
4
  import { join } from 'node:path';
5
- import * as addFormatsModule from 'ajv-formats';
6
- // Ajv 8's `/dist/2020` entry exports the Ajv2020 class as a named export.
7
- // The named-import form is stable across ESM/CJS/bundler interop; the default form is not.
8
- import { Ajv2020 } from 'ajv/dist/2020.js';
5
+ import { boundedAjv, holdTenantSchema } from './bounded.js';
6
+ import { SchemaCompileBudgetError } from './compile-budget.js';
9
7
  import { ALLOW_UNION_TYPES } from './dialect.js';
10
- const addFormatsRaw = addFormatsModule;
11
- const addFormats = typeof addFormatsRaw === 'function'
12
- ? addFormatsRaw
13
- : addFormatsRaw.default;
14
8
  function notFound(id) {
15
9
  return {
16
10
  code: 'schema-not-found',
@@ -77,7 +71,10 @@ function extractId(schema) {
77
71
  return { kind: 'ok', value: id };
78
72
  }
79
73
  /**
80
- * Build a SpecRegistry from an array of already-parsed schema documents.
74
+ * Build a SpecRegistry from an array of already-parsed schema documents:
75
+ * Kindgi's own (`@kindgi/specs`), whose patterns run on V8 as the rest of
76
+ * Kindgi's code does. A tenant's schema goes through `compileJsonSchema`
77
+ * or `compileInlineSchema`, under the bounds.
81
78
  *
82
79
  * All schemas are registered with the Ajv instance FIRST (so cross-schema
83
80
  * `$ref`s can resolve), then validators are compiled and cached.
@@ -86,12 +83,7 @@ function extractId(schema) {
86
83
  * spec is broken, downstream validators are meaningless.
87
84
  */
88
85
  export function createSpecRegistry(schemas) {
89
- const ajv = new Ajv2020({
90
- strict: true,
91
- allErrors: true,
92
- allowUnionTypes: ALLOW_UNION_TYPES,
93
- });
94
- addFormats(ajv);
86
+ const ajv = boundedAjv('2020-12', { strict: true, allErrors: true, allowUnionTypes: ALLOW_UNION_TYPES }, { schemasFrom: 'kindgi' });
95
87
  const schemaMap = new Map();
96
88
  // Pass 1: register every schema so $refs can resolve during compilation.
97
89
  for (const schema of schemas) {
@@ -149,36 +141,36 @@ export function createSpecRegistry(schemas) {
149
141
  }
150
142
  return { kind: 'ok', value: makeRegistry({ schemas: schemaMap, validators }) };
151
143
  }
144
+ /**
145
+ * Keywords an inline schema may carry for Kindgi to read, with no effect
146
+ * on validation: `x-kindgi-tunable` marks a settings key an improvement
147
+ * pass may search.
148
+ */
149
+ export const INLINE_ANNOTATIONS = ['x-kindgi-tunable'];
152
150
  /**
153
151
  * Compile a single anonymous JSON Schema (draft 2020-12) into a reusable
154
152
  * validator. Returns `err` if the schema itself is malformed (Ajv rejects
155
153
  * it), which is how the flow loader surfaces `LoopOutputSchemaError` and
156
- * similar load-time diagnostics.
154
+ * similar load-time diagnostics. Throws `SchemaCompileBudgetError` when the
155
+ * compile counts against a tenant that has spent its budget: that isn't
156
+ * the schema's fault, and the caller answers it as a limit, not an issue.
157
157
  *
158
158
  * Design note: this is intentionally decoupled from `SpecRegistry` — inline
159
159
  * schemas don't have a `$id` and don't need cross-schema `$ref` resolution.
160
160
  */
161
- /**
162
- * Keywords an inline schema may carry for Kindgi to read, with no effect
163
- * on validation: `x-kindgi-tunable` marks a settings key an improvement
164
- * pass may search.
165
- */
166
- export const INLINE_ANNOTATIONS = ['x-kindgi-tunable'];
167
161
  export function compileInlineSchema(schema) {
168
- const ajv = new Ajv2020({
169
- strict: true,
170
- allErrors: true,
171
- allowUnionTypes: ALLOW_UNION_TYPES,
172
- });
173
- addFormats(ajv);
174
- // Annotations Kindgi reads off a schema, which validate nothing.
175
- for (const keyword of INLINE_ANNOTATIONS)
176
- ajv.addKeyword(keyword);
177
162
  let validator;
178
163
  try {
179
- validator = ajv.compile(schema);
164
+ validator = holdTenantSchema(schema, {
165
+ dialect: '2020-12',
166
+ options: { strict: true, allErrors: true, allowUnionTypes: ALLOW_UNION_TYPES },
167
+ // Annotations Kindgi reads off a schema, which validate nothing.
168
+ annotations: INLINE_ANNOTATIONS,
169
+ });
180
170
  }
181
171
  catch (cause) {
172
+ if (cause instanceof SchemaCompileBudgetError)
173
+ throw cause;
182
174
  return {
183
175
  kind: 'err',
184
176
  error: {
@@ -194,7 +186,8 @@ export function compileInlineSchema(schema) {
194
186
  value: {
195
187
  source: schema,
196
188
  validate(data) {
197
- if (validator(data)) {
189
+ const validate = validator();
190
+ if (validate(data)) {
198
191
  return { kind: 'ok', value: data };
199
192
  }
200
193
  return {
@@ -202,7 +195,7 @@ export function compileInlineSchema(schema) {
202
195
  error: {
203
196
  code: 'validation-error',
204
197
  message: 'Data does not validate against inline schema',
205
- errors: validator.errors ?? [],
198
+ errors: validate.errors ?? [],
206
199
  },
207
200
  };
208
201
  },
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,KAAK,gBAAgB,MAAM,aAAa,CAAC;AAChD,0EAA0E;AAC1E,2FAA2F;AAC3F,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAI3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAOjD,MAAM,aAAa,GAAG,gBAA2B,CAAC;AAClD,MAAM,UAAU,GACd,OAAO,aAAa,KAAK,UAAU;IACjC,CAAC,CAAE,aAA8B;IACjC,CAAC,CAAE,aAA2C,CAAC,OAAO,CAAC;AAoC3D,SAAS,QAAQ,CAAC,EAAU;IAC1B,OAAO;QACL,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,kCAAkC,EAAE,EAAE;QAC/C,EAAE;KACH,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAoB;IACxC,OAAO;QACL,QAAQ,CAAc,EAAU,EAAE,IAAa;YAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC3C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YAC9C,CAAC;YACD,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAS,EAAE,CAAC;YAC1C,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE;oBACL,IAAI,EAAE,kBAAkB;oBACxB,OAAO,EAAE,kCAAkC,EAAE,EAAE;oBAC/C,EAAE;oBACF,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,EAAE;iBAC/B;aACF,CAAC;QACJ,CAAC;QACD,SAAS,CAAC,EAAE;YACV,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACrC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YAC9C,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QACvC,CAAC;QACD,GAAG;YACD,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,MAAe;IAChC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,EAAE,CAAC;QACxE,OAAO;YACL,IAAI,EAAE,KAAK;YACX,KAAK,EAAE;gBACL,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,iCAAiC;gBAC1C,EAAE,EAAE,WAAW;gBACf,KAAK,EAAE,MAAM;aACd;SACF,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,GAAI,MAA2B,CAAC,GAAG,CAAC;IAC5C,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,OAAO;YACL,IAAI,EAAE,KAAK;YACX,KAAK,EAAE;gBACL,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,sCAAsC;gBAC/C,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC;gBACd,KAAK,EAAE,MAAM;aACd;SACF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AACnC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAA2B;IAC5D,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC;QACtB,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,IAAI;QACf,eAAe,EAAE,iBAAiB;KACnC,CAAC,CAAC;IACH,UAAU,CAAC,GAAG,CAAC,CAAC;IAEhB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAmB,CAAC;IAE7C,yEAAyE;IACzE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,QAAQ,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAC5B,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC;YACH,GAAG,CAAC,SAAS,CAAC,MAAgB,EAAE,EAAE,CAAC,CAAC;YACpC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE;oBACL,IAAI,EAAE,sBAAsB;oBAC5B,OAAO,EAAE,sCAAsC,EAAE,EAAE;oBACnD,EAAE;oBACF,KAAK;iBACN;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,2DAA2D;IAC3D,MAAM,UAAU,GAAG,IAAI,GAAG,EAA4B,CAAC;IACvD,KAAK,MAAM,EAAE,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QAClC,IAAI,SAAuC,CAAC;QAC5C,IAAI,CAAC;YACH,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE;oBACL,IAAI,EAAE,sBAAsB;oBAC5B,OAAO,EAAE,uCAAuC,EAAE,EAAE;oBACpD,EAAE;oBACF,KAAK;iBACN;aACF,CAAC;QACJ,CAAC;QACD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE;oBACL,IAAI,EAAE,sBAAsB;oBAC5B,OAAO,EAAE,0CAA0C,EAAE,EAAE;oBACvD,EAAE;oBACF,KAAK,EAAE,IAAI;iBACZ;aACF,CAAC;QACJ,CAAC;QACD,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;AACjF,CAAC;AAiCD;;;;;;;;GAQG;AACH;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAsB,CAAC,kBAAkB,CAAC,CAAC;AAE1E,MAAM,UAAU,mBAAmB,CAAC,MAAe;IACjD,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC;QACtB,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,IAAI;QACf,eAAe,EAAE,iBAAiB;KACnC,CAAC,CAAC;IACH,UAAU,CAAC,GAAG,CAAC,CAAC;IAChB,iEAAiE;IACjE,KAAK,MAAM,OAAO,IAAI,kBAAkB;QAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAElE,IAAI,SAA2B,CAAC;IAChC,IAAI,CAAC;QACH,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,MAAgB,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,IAAI,EAAE,KAAK;YACX,KAAK,EAAE;gBACL,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,oCAAqC,KAAe,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE;gBACzF,EAAE,EAAE,UAAU;gBACd,KAAK;aACN;SACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,IAAI;QACV,KAAK,EAAE;YACL,MAAM,EAAE,MAAM;YACd,QAAQ,CAAc,IAAa;gBACjC,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;oBACpB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAS,EAAE,CAAC;gBAC1C,CAAC;gBACD,OAAO;oBACL,IAAI,EAAE,KAAK;oBACX,KAAK,EAAE;wBACL,IAAI,EAAE,kBAAkB;wBACxB,OAAO,EAAE,8CAA8C;wBACvD,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,EAAE;qBAC/B;iBACF,CAAC;YACJ,CAAC;SACF;KACF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAW;IAChD,IAAI,OAA0B,CAAC;IAC/B,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,IAAI,EAAE,KAAK;YACX,KAAK,EAAE;gBACL,IAAI,EAAE,mBAAmB;gBACzB,OAAO,EAAE,gCAAgC,GAAG,EAAE;gBAC9C,IAAI,EAAE,GAAG;gBACT,KAAK;aACN;SACF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvE,MAAM,OAAO,GAAc,EAAE,CAAC;IAE9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjC,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE;oBACL,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EAAE,4BAA4B,QAAQ,EAAE;oBAC/C,IAAI,EAAE,QAAQ;oBACd,KAAK;iBACN;aACF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE;oBACL,IAAI,EAAE,oBAAoB;oBAC1B,OAAO,EAAE,gCAAgC,QAAQ,EAAE;oBACnD,IAAI,EAAE,QAAQ;oBACd,KAAK;iBACN;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { CodeKeywordDefinition } from 'ajv';
2
+ /** The keyword: `ajv.removeKeyword('uniqueItems')`, then `ajv.addKeyword(linearUniqueItems())`. */
3
+ export declare function linearUniqueItems(): CodeKeywordDefinition;
4
+ /**
5
+ * The pair Ajv's own keyword reports for items it compares pair by pair:
6
+ * `i`, the last item equal to an earlier one, and `j`, the last earlier
7
+ * item it equals. Undefined when every item is unique.
8
+ */
9
+ export declare function lastRepeat(items: readonly unknown[]): readonly [number, number] | undefined;
10
+ //# sourceMappingURL=unique-items.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unique-items.d.ts","sourceRoot":"","sources":["../src/unique-items.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,qBAAqB,EAAc,MAAM,KAAK,CAAC;AA4C7D,mGAAmG;AACnG,wBAAgB,iBAAiB,IAAI,qBAAqB,CAEzD;AAiCD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAW3F"}
@@ -0,0 +1,186 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ /**
4
+ * `uniqueItems` in time linear in the data's size times its depth (each
5
+ * level's key is built from its children's), for schemas compiled on RE2
6
+ * (the hosted bounds).
7
+ *
8
+ * Ajv's own keyword compares every pair of items (n² deep-equals) unless
9
+ * the schema declares only scalar types for them: items typed `object` or
10
+ * `array`, or with no `type` at all, as most schemas leave them. 300,000
11
+ * small objects fit in 2 MiB. This one gives each item a key, its JSON with
12
+ * the keys of every object sorted, and looks for a repeat in a `Map`.
13
+ *
14
+ * The verdict is Ajv's, and so is the error: the same pair of items (`i`,
15
+ * `j`), the same `params` and message. Two items are the same as
16
+ * `fast-deep-equal` (what Ajv uses) finds them for JSON values: key order
17
+ * doesn't matter, array order does, and `-0` is `0`. Items declared
18
+ * scalar go through Ajv's own code, which is linear already. Two cases
19
+ * differ, neither of them from JSON:
20
+ * - an item JSON can't carry (a `Date`, a class instance, a `Map`) makes
21
+ * the whole array compared as Ajv does, pair by pair, with its
22
+ * `fast-deep-equal`. Only code in the server's own process passes those;
23
+ * - an object with its own `valueOf` or `toString` key is compared by its
24
+ * keys, where `fast-deep-equal` throws a `TypeError` calling it.
25
+ */
26
+ import { _ } from 'ajv';
27
+ import { getSchemaTypes } from 'ajv/dist/compile/validate/dataType.js';
28
+ import * as equalModule from 'ajv/dist/runtime/equal.js';
29
+ import * as uniqueItemsModule from 'ajv/dist/vocabularies/validation/uniqueItems.js';
30
+ // Ajv's dist modules are CommonJS with `exports.default`. An ESM import
31
+ // wraps that once or twice, depending on the resolver (Node's, Vite's),
32
+ // and a wrapper can answer for the export's own keys without holding them,
33
+ // so take the innermost `default`. Read on first use, so a process that
34
+ // never compiles on RE2 never depends on their shape.
35
+ let ajvUniqueItems;
36
+ let ajvEqual;
37
+ function ajvKeyword() {
38
+ ajvUniqueItems ??= unwrapDefault(uniqueItemsModule, (value) => typeof value === 'object' &&
39
+ value !== null &&
40
+ Object.hasOwn(value, 'keyword') &&
41
+ typeof value.code === 'function');
42
+ return ajvUniqueItems;
43
+ }
44
+ function equal(a, b) {
45
+ ajvEqual ??= unwrapDefault(equalModule, (value) => typeof value === 'function');
46
+ return ajvEqual(a, b);
47
+ }
48
+ function unwrapDefault(module, is) {
49
+ let value = module;
50
+ for (let step = 0; step < 3; step += 1) {
51
+ const inner = value?.default;
52
+ if (inner === undefined || inner === null)
53
+ break;
54
+ value = inner;
55
+ }
56
+ if (!is(value))
57
+ throw new Error("Ajv's module isn't the shape @kindgi/schema expects.");
58
+ return value;
59
+ }
60
+ /** The keyword: `ajv.removeKeyword('uniqueItems')`, then `ajv.addKeyword(linearUniqueItems())`. */
61
+ export function linearUniqueItems() {
62
+ return { ...ajvKeyword(), code: linearCode };
63
+ }
64
+ function linearCode(cxt) {
65
+ const { gen, data, $data, schema, parentSchema, schemaCode } = cxt;
66
+ const itemTypes = parentSchema.items ? getSchemaTypes(parentSchema.items) : [];
67
+ // Ajv's own test: items declared scalar are compared by a key already.
68
+ if (itemTypes.length > 0 && !itemTypes.some((t) => t === 'object' || t === 'array')) {
69
+ ajvKeyword().code(cxt);
70
+ return;
71
+ }
72
+ if (!$data && !schema)
73
+ return;
74
+ const valid = gen.let('valid');
75
+ cxt.block$data(valid, validateUniqueItems, _ `${schemaCode} === false`);
76
+ cxt.ok(valid);
77
+ function validateUniqueItems() {
78
+ const i = gen.let('i', _ `${data}.length`);
79
+ const j = gen.let('j');
80
+ cxt.setParams({ i, j });
81
+ gen.assign(valid, true);
82
+ gen.if(_ `${i} > 1`, () => {
83
+ const find = gen.scopeValue('func', { ref: lastRepeat });
84
+ const pair = gen.const('pair', _ `${find}(${data})`);
85
+ gen.if(pair, () => {
86
+ gen.assign(i, _ `${pair}[0]`);
87
+ gen.assign(j, _ `${pair}[1]`);
88
+ cxt.error();
89
+ gen.assign(valid, false);
90
+ });
91
+ });
92
+ }
93
+ }
94
+ /**
95
+ * The pair Ajv's own keyword reports for items it compares pair by pair:
96
+ * `i`, the last item equal to an earlier one, and `j`, the last earlier
97
+ * item it equals. Undefined when every item is unique.
98
+ */
99
+ export function lastRepeat(items) {
100
+ const seen = new Map();
101
+ let found;
102
+ for (let k = 0; k < items.length; k += 1) {
103
+ const key = itemKey(items[k]);
104
+ if (key === undefined)
105
+ return pairwise(items);
106
+ const before = seen.get(key);
107
+ if (before !== undefined)
108
+ found = [k, before];
109
+ seen.set(key, k);
110
+ }
111
+ return found;
112
+ }
113
+ /** Ajv's own loop: from the last item back, each against every item before it. */
114
+ function pairwise(items) {
115
+ for (let i = items.length - 1; i > 0; i -= 1) {
116
+ for (let j = i - 1; j >= 0; j -= 1) {
117
+ if (equal(items[i], items[j]))
118
+ return [i, j];
119
+ }
120
+ }
121
+ return undefined;
122
+ }
123
+ /**
124
+ * A key two items share exactly when `fast-deep-equal` finds them equal:
125
+ * JSON with each object's keys sorted, numbers as `String` writes them
126
+ * (`-0` is `0`, every `NaN` the same), and `undefined` kept. Undefined for
127
+ * a value JSON can't carry.
128
+ */
129
+ function itemKey(value) {
130
+ switch (typeof value) {
131
+ case 'string':
132
+ return JSON.stringify(value);
133
+ case 'number':
134
+ return String(value);
135
+ case 'boolean':
136
+ return value ? 'true' : 'false';
137
+ case 'undefined':
138
+ return 'undefined';
139
+ case 'object': {
140
+ if (value === null)
141
+ return 'null';
142
+ const proto = Object.getPrototypeOf(value);
143
+ if (proto === Array.prototype) {
144
+ const parts = [];
145
+ for (const item of value) {
146
+ const key = itemKey(item);
147
+ if (key === undefined)
148
+ return undefined;
149
+ parts.push(key);
150
+ }
151
+ return `[${parts.join(',')}]`;
152
+ }
153
+ if (proto !== Object.prototype)
154
+ return undefined;
155
+ const record = value;
156
+ const parts = [];
157
+ for (const name of Object.keys(record).sort()) {
158
+ const key = itemKey(record[name]);
159
+ if (key === undefined)
160
+ return undefined;
161
+ parts.push(`${JSON.stringify(name)}:${key}`);
162
+ }
163
+ // `fast-deep-equal` first compares `a.constructor` with `===`: an
164
+ // own `constructor` key holding an object or array matches only the
165
+ // same object, never an equal one.
166
+ const ctor = Object.hasOwn(record, 'constructor') ? record.constructor : undefined;
167
+ const same = typeof ctor === 'object' && ctor !== null ? `@${identity(ctor)}` : '';
168
+ return `{${parts.join(',')}}${same}`;
169
+ }
170
+ default:
171
+ return undefined;
172
+ }
173
+ }
174
+ const identities = new WeakMap();
175
+ let lastIdentity = 0;
176
+ /** A number for `value` itself: the same object, the same number. */
177
+ function identity(value) {
178
+ let id = identities.get(value);
179
+ if (id === undefined) {
180
+ lastIdentity += 1;
181
+ id = lastIdentity;
182
+ identities.set(value, id);
183
+ }
184
+ return id;
185
+ }
186
+ //# sourceMappingURL=unique-items.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unique-items.js","sourceRoot":"","sources":["../src/unique-items.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kindgi/schema",
3
- "version": "0.1.7-rc.0",
3
+ "version": "0.1.8-rc.0",
4
4
  "description": "JSON Schema utilities for Kindgi. Loads specs, provides Ajv-based validation, extracts schema versions. Consumers validate incoming data against the wire contracts in @kindgi/specs.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -30,7 +30,8 @@
30
30
  "type-manifest.json"
31
31
  ],
32
32
  "dependencies": {
33
- "@kindgi/types": "0.1.7-rc.0",
33
+ "@kindgi/bounds": "0.1.8-rc.0",
34
+ "@kindgi/types": "0.1.8-rc.0",
34
35
  "ajv": "^8.17.1",
35
36
  "ajv-formats": "^3.0.1"
36
37
  },
@@ -43,7 +44,7 @@
43
44
  }
44
45
  },
45
46
  "devDependencies": {
46
- "@kindgi/specs": "0.1.7-rc.0",
47
+ "@kindgi/specs": "0.1.8-rc.0",
47
48
  "@types/node": "^22.10.5",
48
49
  "typescript": "^5.7.3",
49
50
  "vitest": "^2.1.8",