@effected/schemastore 0.4.0 → 0.6.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/DocumentLint.js +2 -2
- package/KeywordFamilies.js +50 -9
- package/README.md +40 -11
- package/SchemaPipeline.js +91 -6
- package/SchemaValidator.js +8 -5
- package/SchemaVersioning.js +56 -0
- package/StoreDocument.js +61 -15
- package/index.d.ts +716 -540
- package/index.js +4 -5
- package/package.json +3 -3
- package/tsdoc-metadata.json +1 -1
- package/AnnotationCarriers.js +0 -137
package/index.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { KeywordFamilies } from "./KeywordFamilies.js";
|
|
2
|
-
import { AnnotationCarriers, CarrierDepthExceededError } from "./AnnotationCarriers.js";
|
|
3
1
|
import { CanonicalJson, JsonDepthExceededError, NonJsonValueError } from "./CanonicalJson.js";
|
|
4
2
|
import { InvalidSchemaVersionError, SchemaVersion, SchemaVersioning } from "./SchemaVersioning.js";
|
|
5
3
|
import { CatalogEntry, CatalogLintFinding } from "./CatalogEntry.js";
|
|
4
|
+
import { KeywordFamilies } from "./KeywordFamilies.js";
|
|
6
5
|
import { DocumentDiff } from "./DocumentDiff.js";
|
|
7
6
|
import { DocumentLint, DocumentLintFinding } from "./DocumentLint.js";
|
|
8
7
|
import { SchemaFile, SchemaFileNotFoundError, SchemaFileReadError, SchemaFileWriteError } from "./SchemaFile.js";
|
|
9
8
|
import { SchemaValidator, SchemaValidatorError, ValidationFinding } from "./SchemaValidator.js";
|
|
10
|
-
import { DRAFT_07_META_SCHEMA, SchemaConversionError, StoreDocument } from "./StoreDocument.js";
|
|
11
|
-
import { PipelineFinding, SchemaGateError, SchemaPipeline } from "./SchemaPipeline.js";
|
|
9
|
+
import { DRAFT_07_META_SCHEMA, SchemaConversionError, StoreDocument, UndeclaredAnnotationKeyError } from "./StoreDocument.js";
|
|
10
|
+
import { ContractChangeTarget, PipelineFinding, SchemaContractChangeError, SchemaGateError, SchemaPipeline } from "./SchemaPipeline.js";
|
|
12
11
|
import { SchemaTarget } from "./SchemaTarget.js";
|
|
13
12
|
|
|
14
|
-
export {
|
|
13
|
+
export { CanonicalJson, CatalogEntry, CatalogLintFinding, ContractChangeTarget, DRAFT_07_META_SCHEMA, DocumentDiff, DocumentLint, DocumentLintFinding, InvalidSchemaVersionError, JsonDepthExceededError, KeywordFamilies, NonJsonValueError, PipelineFinding, SchemaContractChangeError, SchemaConversionError, SchemaFile, SchemaFileNotFoundError, SchemaFileReadError, SchemaFileWriteError, SchemaGateError, SchemaPipeline, SchemaTarget, SchemaValidator, SchemaValidatorError, SchemaVersion, SchemaVersioning, StoreDocument, UndeclaredAnnotationKeyError, ValidationFinding };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effected/schemastore",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Build, validate, version and publish SchemaStore-shaped Draft-07 JSON Schema documents from Effect Schema sources: document assembly, ajv strict-mode validation, structural lints, catalog entries, canonical JSON and a content-comparing emit pipeline.",
|
|
6
6
|
"keywords": [
|
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
"./package.json": "./package.json"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@effected/semver": "^0.
|
|
41
|
+
"@effected/semver": "^0.6.0",
|
|
42
42
|
"ajv": "^8.20.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"effect": "4.0.0-rc.
|
|
45
|
+
"effect": "4.0.0-rc.112"
|
|
46
46
|
},
|
|
47
47
|
"engines": {
|
|
48
48
|
"node": ">=24.11.0"
|
package/tsdoc-metadata.json
CHANGED
package/AnnotationCarriers.js
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { KeywordFamilies } from "./KeywordFamilies.js";
|
|
2
|
-
import { Effect, Result, Schema } from "effect";
|
|
3
|
-
|
|
4
|
-
//#region src/AnnotationCarriers.ts
|
|
5
|
-
/**
|
|
6
|
-
* Indicates that the carrier re-graft walk nested past the package's
|
|
7
|
-
* hardening cap (256 levels), which also intercepts cyclic inputs before
|
|
8
|
-
* they can recurse forever.
|
|
9
|
-
*
|
|
10
|
-
* Raised by {@link AnnotationCarriers.carry}.
|
|
11
|
-
*
|
|
12
|
-
* @public
|
|
13
|
-
*/
|
|
14
|
-
var CarrierDepthExceededError = class extends Schema.TaggedError()("CarrierDepthExceededError", {
|
|
15
|
-
/** JSON pointer (in the lowered document's coordinates) where the cap was hit. */
|
|
16
|
-
path: Schema.String,
|
|
17
|
-
/** The nesting cap that was exceeded. */
|
|
18
|
-
maxDepth: Schema.Number
|
|
19
|
-
}) {
|
|
20
|
-
get message() {
|
|
21
|
-
return `Carrier re-graft nesting exceeds ${this.maxDepth} levels at "${this.path}"`;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
var CarryFailure = class {
|
|
25
|
-
error;
|
|
26
|
-
constructor(error) {
|
|
27
|
-
this.error = error;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
const escapePointerSegment = (segment) => segment.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
31
|
-
const isSchemaObject = (node) => typeof node === "object" && node !== null && !Array.isArray(node);
|
|
32
|
-
const graftMap = (source, target, path, depth) => {
|
|
33
|
-
if (!isSchemaObject(source) || !isSchemaObject(target)) return target;
|
|
34
|
-
const out = { ...target };
|
|
35
|
-
for (const [name, subschema] of Object.entries(source)) if (Object.hasOwn(target, name)) out[name] = graft(subschema, target[name], `${path}/${escapePointerSegment(name)}`, depth + 1);
|
|
36
|
-
return out;
|
|
37
|
-
};
|
|
38
|
-
const graftArray = (source, target, path, depth) => {
|
|
39
|
-
if (!Array.isArray(source) || !Array.isArray(target)) return target;
|
|
40
|
-
return target.map((element, index) => index < source.length ? graft(source[index], element, `${path}/${index}`, depth + 1) : element);
|
|
41
|
-
};
|
|
42
|
-
const graft = (source, target, path, depth) => {
|
|
43
|
-
if (depth >= 256) throw new CarryFailure(CarrierDepthExceededError.make({
|
|
44
|
-
path,
|
|
45
|
-
maxDepth: 256
|
|
46
|
-
}));
|
|
47
|
-
if (!isSchemaObject(source) || !isSchemaObject(target)) return target;
|
|
48
|
-
const out = { ...target };
|
|
49
|
-
for (const [key, value] of Object.entries(source)) {
|
|
50
|
-
if (KeywordFamilies.isDeclared(key)) {
|
|
51
|
-
out[key] = value;
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
const keyPath = `${path}/${escapePointerSegment(key)}`;
|
|
55
|
-
switch (key) {
|
|
56
|
-
case "properties":
|
|
57
|
-
case "patternProperties":
|
|
58
|
-
if (Object.hasOwn(out, key)) out[key] = graftMap(value, out[key], keyPath, depth);
|
|
59
|
-
break;
|
|
60
|
-
case "additionalProperties":
|
|
61
|
-
case "propertyNames":
|
|
62
|
-
if (Object.hasOwn(out, key)) out[key] = graft(value, out[key], keyPath, depth + 1);
|
|
63
|
-
break;
|
|
64
|
-
case "allOf":
|
|
65
|
-
case "anyOf":
|
|
66
|
-
case "oneOf":
|
|
67
|
-
if (Object.hasOwn(out, key)) out[key] = graftArray(value, out[key], keyPath, depth);
|
|
68
|
-
break;
|
|
69
|
-
case "prefixItems":
|
|
70
|
-
if (Object.hasOwn(out, "items")) out.items = Array.isArray(value) ? graftArray(value, out.items, `${path}/items`, depth) : graft(value, out.items, `${path}/items`, depth + 1);
|
|
71
|
-
break;
|
|
72
|
-
case "items": if (Object.hasOwn(source, "prefixItems")) {
|
|
73
|
-
if (Object.hasOwn(out, "additionalItems")) out.additionalItems = graft(value, out.additionalItems, `${path}/additionalItems`, depth + 1);
|
|
74
|
-
} else if (Object.hasOwn(out, "items")) out.items = graft(value, out.items, keyPath, depth + 1);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return out;
|
|
78
|
-
};
|
|
79
|
-
/**
|
|
80
|
-
* Re-grafts the declared non-standard keyword families
|
|
81
|
-
* ({@link KeywordFamilies}) from a Draft 2020-12 schema node onto its
|
|
82
|
-
* lowered Draft-07 counterpart.
|
|
83
|
-
*
|
|
84
|
-
* Why this exists: annotation keys admitted into the Draft 2020-12 document
|
|
85
|
-
* (core's `includeAnnotationKey`) are **dropped by core's Draft-07 lowering**,
|
|
86
|
-
* whose keyword walk copies a fixed subset — verified against the installed
|
|
87
|
-
* beta. Carrying `x-taplo`, `x-tombi-*`, `x-intellij-*` or the vscode set
|
|
88
|
-
* into an emitted SchemaStore document therefore requires this post-lowering
|
|
89
|
-
* step; it cannot ride `ToJsonSchemaOptions` alone.
|
|
90
|
-
*
|
|
91
|
-
* The walk mirrors the lowering's own structural rules, so every carrier
|
|
92
|
-
* lands on the node the annotation was attached to — including the one
|
|
93
|
-
* coordinate move the lowering makes (2020-12 `prefixItems[i]` → Draft-07
|
|
94
|
-
* `items[i]`, trailing `items` → `additionalItems`). Only declared-family
|
|
95
|
-
* keys are copied; nothing else about the target changes.
|
|
96
|
-
*
|
|
97
|
-
* `StoreDocument.fromSchema` applies this automatically to the root schema
|
|
98
|
-
* and every `$defs` pool entry — annotate a schema node
|
|
99
|
-
* (`Schema.String.annotate({ "x-taplo": { hidden: true } })`) and the key
|
|
100
|
-
* appears in the built document. Call this directly only when driving core's
|
|
101
|
-
* pipeline yourself.
|
|
102
|
-
*
|
|
103
|
-
* Know the boundary (core behavior, probed at the installed beta): an
|
|
104
|
-
* annotation must sit on the schema **definition** node. Annotating a
|
|
105
|
-
* hoisted (identifier-carrying) schema at its *usage* site — e.g.
|
|
106
|
-
* `Person.annotate({...})` inside a struct field — reaches neither the
|
|
107
|
-
* `$ref` node nor the pool entry, even in the 2020-12 document, so there is
|
|
108
|
-
* nothing to carry.
|
|
109
|
-
*
|
|
110
|
-
* @public
|
|
111
|
-
*/
|
|
112
|
-
var AnnotationCarriers = class AnnotationCarriers {
|
|
113
|
-
constructor() {}
|
|
114
|
-
/**
|
|
115
|
-
* Grafts declared-family keys from `source` (a Draft 2020-12 schema
|
|
116
|
-
* node) onto `target` (its lowered Draft-07 counterpart), returning a
|
|
117
|
-
* new node. Pure and synchronous — the primitive form;
|
|
118
|
-
* {@link AnnotationCarriers.carry} is the same walk behind a span.
|
|
119
|
-
*/
|
|
120
|
-
static carryResult(source, target) {
|
|
121
|
-
try {
|
|
122
|
-
return Result.succeed(graft(source, target, "", 0));
|
|
123
|
-
} catch (cause) {
|
|
124
|
-
if (cause instanceof CarryFailure) return Result.fail(cause.error);
|
|
125
|
-
throw cause;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Effect form of {@link AnnotationCarriers.carryResult}, adding only the
|
|
130
|
-
* `AnnotationCarriers.carry` span. Defined in terms of the `Result`
|
|
131
|
-
* primitive — synchronous callers can use that variant directly.
|
|
132
|
-
*/
|
|
133
|
-
static carry = Effect.fn("AnnotationCarriers.carry")((source, target) => Effect.fromResult(AnnotationCarriers.carryResult(source, target)));
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
//#endregion
|
|
137
|
-
export { AnnotationCarriers, CarrierDepthExceededError };
|