@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/README.md +31 -3
- package/dist/bounded.d.ts +57 -0
- package/dist/bounded.d.ts.map +1 -0
- package/dist/bounded.js +308 -0
- package/dist/bounded.js.map +1 -0
- package/dist/compile-budget.d.ts +47 -0
- package/dist/compile-budget.d.ts.map +1 -0
- package/dist/compile-budget.js +91 -0
- package/dist/compile-budget.js.map +1 -0
- package/dist/dialect.d.ts +28 -3
- package/dist/dialect.d.ts.map +1 -1
- package/dist/dialect.js +26 -48
- package/dist/dialect.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/registry.d.ts +17 -9
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +27 -34
- package/dist/registry.js.map +1 -1
- package/dist/unique-items.d.ts +10 -0
- package/dist/unique-items.d.ts.map +1 -0
- package/dist/unique-items.js +186 -0
- package/dist/unique-items.js.map +1 -0
- package/package.json +4 -3
- package/src/bounded.ts +376 -0
- package/src/compile-budget.ts +112 -0
- package/src/dialect.ts +34 -35
- package/src/index.ts +7 -1
- package/src/registry.ts +36 -43
- package/src/unique-items.ts +197 -0
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
|
|
67
|
-
*
|
|
68
|
-
*
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
package/dist/dialect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialect.js","sourceRoot":"","sources":["../src/dialect.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;
|
|
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 {
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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 {
|
|
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,
|
|
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"}
|
package/dist/registry.d.ts
CHANGED
|
@@ -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.
|
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"
|
|
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
|
|
6
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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:
|
|
198
|
+
errors: validate.errors ?? [],
|
|
206
199
|
},
|
|
207
200
|
};
|
|
208
201
|
},
|
package/dist/registry.js.map
CHANGED
|
@@ -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;
|
|
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.
|
|
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/
|
|
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.
|
|
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",
|