constructa-schema 0.0.3 → 0.0.4
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 +23 -0
- package/dist/index.d.ts +34 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,6 +18,29 @@ Complete portable definitions must include `schemaVersion: 1`. `CURRENT_SCHEMA_V
|
|
|
18
18
|
|
|
19
19
|
Use `isSchemaVersion`, `assertSchemaVersion`, `isVersionedDefinition`, `assertVersionedDefinition`, `findSchemaVersionValueFailure`, or `findSchemaVersionFailure` to reject missing or unsupported version markers with structured failures.
|
|
20
20
|
|
|
21
|
+
## Definition envelope
|
|
22
|
+
|
|
23
|
+
The canonical top-level generator definition document is:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"schemaVersion": 1,
|
|
28
|
+
"type": "integer",
|
|
29
|
+
"configuration": {
|
|
30
|
+
"min": 1,
|
|
31
|
+
"max": 100
|
|
32
|
+
},
|
|
33
|
+
"name": "Small integer",
|
|
34
|
+
"description": "An integer in a bounded range."
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`schemaVersion`, `type`, and `configuration` are required. `type` must be a non-empty string, and `configuration` must be a JSON object. `name` and `description` are optional strings.
|
|
39
|
+
|
|
40
|
+
Unknown top-level properties are rejected so all surfaces exchange one canonical document shape. Generator-specific data belongs inside `configuration`, where each generator can validate its own fields in later phases.
|
|
41
|
+
|
|
42
|
+
Use `isDefinitionEnvelope`, `assertDefinitionEnvelope`, `parseDefinitionEnvelope`, `safeParseDefinitionEnvelope`, or `findDefinitionEnvelopeFailure` to validate the complete envelope.
|
|
43
|
+
|
|
21
44
|
## Dependency boundary
|
|
22
45
|
|
|
23
46
|
This is the bottom of the domain dependency graph and has no Constructa runtime dependencies. In particular, it must not import core, generators, exporters, the SDK, applications, UI, environment, persistence, or transport code.
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,14 @@ type SchemaVersion = (typeof SUPPORTED_SCHEMA_VERSIONS)[number];
|
|
|
11
11
|
type VersionedDefinition = JsonObject & {
|
|
12
12
|
readonly schemaVersion: SchemaVersion;
|
|
13
13
|
};
|
|
14
|
+
type DefinitionEnvelope = {
|
|
15
|
+
readonly schemaVersion: SchemaVersion;
|
|
16
|
+
readonly type: string;
|
|
17
|
+
readonly configuration: JsonObject;
|
|
18
|
+
readonly name?: string;
|
|
19
|
+
readonly description?: string;
|
|
20
|
+
};
|
|
21
|
+
declare const DEFINITION_ENVELOPE_TOP_LEVEL_KEYS: readonly ["schemaVersion", "type", "configuration", "name", "description"];
|
|
14
22
|
type SchemaVersionFailureCode = "schema_version_missing" | "schema_version_unsupported";
|
|
15
23
|
type SchemaVersionFailure = {
|
|
16
24
|
readonly code: SchemaVersionFailureCode;
|
|
@@ -19,6 +27,22 @@ type SchemaVersionFailure = {
|
|
|
19
27
|
readonly severity: "error";
|
|
20
28
|
readonly supportedVersions: readonly SchemaVersion[];
|
|
21
29
|
};
|
|
30
|
+
type DefinitionEnvelopeFailureCode = SchemaVersionFailureCode | "definition_envelope_not_json" | "definition_envelope_not_object" | "generator_type_missing" | "generator_type_invalid" | "configuration_missing" | "configuration_invalid" | "name_invalid" | "description_invalid" | "top_level_property_unknown";
|
|
31
|
+
type DefinitionEnvelopeShapeFailureCode = Exclude<DefinitionEnvelopeFailureCode, SchemaVersionFailureCode>;
|
|
32
|
+
type DefinitionEnvelopeShapeFailure = {
|
|
33
|
+
readonly code: DefinitionEnvelopeShapeFailureCode;
|
|
34
|
+
readonly message: string;
|
|
35
|
+
readonly path: string;
|
|
36
|
+
readonly severity: "error";
|
|
37
|
+
};
|
|
38
|
+
type DefinitionEnvelopeFailure = SchemaVersionFailure | DefinitionEnvelopeShapeFailure;
|
|
39
|
+
type DefinitionEnvelopeParseResult = {
|
|
40
|
+
readonly success: true;
|
|
41
|
+
readonly value: DefinitionEnvelope;
|
|
42
|
+
} | {
|
|
43
|
+
readonly success: false;
|
|
44
|
+
readonly failure: DefinitionEnvelopeFailure;
|
|
45
|
+
};
|
|
22
46
|
declare class JsonValueError extends TypeError {
|
|
23
47
|
constructor(path: string, reason: string);
|
|
24
48
|
}
|
|
@@ -26,18 +50,27 @@ declare class SchemaVersionError extends TypeError {
|
|
|
26
50
|
readonly failure: SchemaVersionFailure;
|
|
27
51
|
constructor(failure: SchemaVersionFailure);
|
|
28
52
|
}
|
|
53
|
+
declare class DefinitionEnvelopeError extends TypeError {
|
|
54
|
+
readonly failure: DefinitionEnvelopeFailure;
|
|
55
|
+
constructor(failure: DefinitionEnvelopeFailure);
|
|
56
|
+
}
|
|
29
57
|
declare function isJsonValue(value: unknown): value is JsonValue;
|
|
30
58
|
declare function isSchemaVersion(value: unknown): value is SchemaVersion;
|
|
31
59
|
declare function isVersionedDefinition(value: unknown): value is VersionedDefinition;
|
|
60
|
+
declare function isDefinitionEnvelope(value: unknown): value is DefinitionEnvelope;
|
|
32
61
|
declare function assertJsonValue(value: unknown, path?: string): asserts value is JsonValue;
|
|
33
62
|
declare function assertSchemaVersion(value: unknown, path?: string): asserts value is SchemaVersion;
|
|
34
63
|
declare function assertVersionedDefinition(value: unknown, path?: string): asserts value is VersionedDefinition;
|
|
64
|
+
declare function assertDefinitionEnvelope(value: unknown, path?: string): asserts value is DefinitionEnvelope;
|
|
65
|
+
declare function parseDefinitionEnvelope(value: unknown, path?: string): DefinitionEnvelope;
|
|
66
|
+
declare function safeParseDefinitionEnvelope(value: unknown, path?: string): DefinitionEnvelopeParseResult;
|
|
35
67
|
declare function findJsonValueError(value: unknown, path?: string): {
|
|
36
68
|
path: string;
|
|
37
69
|
reason: string;
|
|
38
70
|
} | undefined;
|
|
71
|
+
declare function findDefinitionEnvelopeFailure(value: unknown, path?: string): DefinitionEnvelopeFailure | undefined;
|
|
39
72
|
declare function findSchemaVersionFailure(value: unknown, path?: string): SchemaVersionFailure | undefined;
|
|
40
73
|
declare function findSchemaVersionValueFailure(value: unknown, path?: string): SchemaVersionFailure | undefined;
|
|
41
74
|
//#endregion
|
|
42
|
-
export { CURRENT_SCHEMA_VERSION, JsonArray, JsonObject, JsonPrimitive, JsonValue, JsonValueError, SUPPORTED_SCHEMA_VERSIONS, SchemaVersion, SchemaVersionError, SchemaVersionFailure, SchemaVersionFailureCode, VersionedDefinition, assertJsonValue, assertSchemaVersion, assertVersionedDefinition, findJsonValueError, findSchemaVersionFailure, findSchemaVersionValueFailure, isJsonValue, isSchemaVersion, isVersionedDefinition };
|
|
75
|
+
export { CURRENT_SCHEMA_VERSION, DEFINITION_ENVELOPE_TOP_LEVEL_KEYS, DefinitionEnvelope, DefinitionEnvelopeError, DefinitionEnvelopeFailure, DefinitionEnvelopeFailureCode, DefinitionEnvelopeParseResult, DefinitionEnvelopeShapeFailure, DefinitionEnvelopeShapeFailureCode, JsonArray, JsonObject, JsonPrimitive, JsonValue, JsonValueError, SUPPORTED_SCHEMA_VERSIONS, SchemaVersion, SchemaVersionError, SchemaVersionFailure, SchemaVersionFailureCode, VersionedDefinition, assertDefinitionEnvelope, assertJsonValue, assertSchemaVersion, assertVersionedDefinition, findDefinitionEnvelopeFailure, findJsonValueError, findSchemaVersionFailure, findSchemaVersionValueFailure, isDefinitionEnvelope, isJsonValue, isSchemaVersion, isVersionedDefinition, parseDefinitionEnvelope, safeParseDefinitionEnvelope };
|
|
43
76
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";KAAY;KAEA,YAAY,YAAY,aAAa;KAErC,qBAAqB;KAErB;YACA,cAAc;;cAGb;cAEA;KAED,wBAAwB;KAExB,sBAAsB;WACvB,eAAe;;KAGd;KAIA;WACD,MAAM;WACN;WACA;WACA;WACA,4BAA4B;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";KAAY;KAEA,YAAY,YAAY,aAAa;KAErC,qBAAqB;KAErB;YACA,cAAc;;cAGb;cAEA;KAED,wBAAwB;KAExB,sBAAsB;WACvB,eAAe;;KAGd;WACD,eAAe;WACf;WACA,eAAe;WACf;WACA;;cAGE;KAQD;KAIA;WACD,MAAM;WACN;WACA;WACA;WACA,4BAA4B;;KAG3B,gCACR;KAWQ,qCAAqC,QAC/C,+BACA;KAGU;WACD,MAAM;WACN;WACA;WACA;;KAGC,4BACR,uBACA;KAEQ;WAEG;WACA,OAAO;;WAGP;WACA,SAAS;;cAGX,uBAAuB;EACtB,YAAA,cAAc;;cAMf,2BAA2B;WAC7B,SAAS;EAEN,YAAA,SAAS;;cAOV,gCAAgC;WAClC,SAAS;EAEN,YAAA,SAAS;;iBAOP,YAAY,iBAAiB,SAAS;iBAItC,gBAAgB,iBAAiB,SAAS;iBAI1C,sBACd,iBACC,SAAS;iBAQI,qBACd,iBACC,SAAS;iBAII,gBACd,gBACA,wBACS,SAAS;iBAQJ,oBACd,gBACA,wBACS,SAAS;iBAQJ,0BACd,gBACA,wBACS,SAAS;iBAUJ,yBACd,gBACA,wBACS,SAAS;iBAQJ,wBACd,gBACA,gBACC;iBAKa,4BACd,gBACA,gBACC;iBAUa,mBACd,gBACA;EACG;EAAc;;iBAIH,8BACd,gBACA,gBACC;iBA8Ea,yBACd,gBACA,gBACC;iBAaa,8BACd,gBACA,gBACC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
//#region src/index.ts
|
|
2
2
|
const CURRENT_SCHEMA_VERSION = 1;
|
|
3
3
|
const SUPPORTED_SCHEMA_VERSIONS = [1];
|
|
4
|
+
const DEFINITION_ENVELOPE_TOP_LEVEL_KEYS = [
|
|
5
|
+
"schemaVersion",
|
|
6
|
+
"type",
|
|
7
|
+
"configuration",
|
|
8
|
+
"name",
|
|
9
|
+
"description"
|
|
10
|
+
];
|
|
4
11
|
var JsonValueError = class extends TypeError {
|
|
5
12
|
constructor(path, reason) {
|
|
6
13
|
super(`${path}: ${reason}`);
|
|
@@ -15,6 +22,14 @@ var SchemaVersionError = class extends TypeError {
|
|
|
15
22
|
this.failure = failure;
|
|
16
23
|
}
|
|
17
24
|
};
|
|
25
|
+
var DefinitionEnvelopeError = class extends TypeError {
|
|
26
|
+
failure;
|
|
27
|
+
constructor(failure) {
|
|
28
|
+
super(`${failure.path}: ${failure.message}`);
|
|
29
|
+
this.name = "DefinitionEnvelopeError";
|
|
30
|
+
this.failure = failure;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
18
33
|
function isJsonValue(value) {
|
|
19
34
|
return findJsonValueError(value) === void 0;
|
|
20
35
|
}
|
|
@@ -24,6 +39,9 @@ function isSchemaVersion(value) {
|
|
|
24
39
|
function isVersionedDefinition(value) {
|
|
25
40
|
return findSchemaVersionFailure(value) === void 0 && isJsonRecord(value) && isJsonValue(value);
|
|
26
41
|
}
|
|
42
|
+
function isDefinitionEnvelope(value) {
|
|
43
|
+
return findDefinitionEnvelopeFailure(value) === void 0;
|
|
44
|
+
}
|
|
27
45
|
function assertJsonValue(value, path = "$") {
|
|
28
46
|
const error = findJsonValueError(value, path);
|
|
29
47
|
if (error !== void 0) throw new JsonValueError(error.path, error.reason);
|
|
@@ -37,9 +55,56 @@ function assertVersionedDefinition(value, path = "$") {
|
|
|
37
55
|
if (failure !== void 0) throw new SchemaVersionError(failure);
|
|
38
56
|
assertJsonValue(value, path);
|
|
39
57
|
}
|
|
58
|
+
function assertDefinitionEnvelope(value, path = "$") {
|
|
59
|
+
const failure = findDefinitionEnvelopeFailure(value, path);
|
|
60
|
+
if (failure !== void 0) throw new DefinitionEnvelopeError(failure);
|
|
61
|
+
}
|
|
62
|
+
function parseDefinitionEnvelope(value, path = "$") {
|
|
63
|
+
assertDefinitionEnvelope(value, path);
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
function safeParseDefinitionEnvelope(value, path = "$") {
|
|
67
|
+
const failure = findDefinitionEnvelopeFailure(value, path);
|
|
68
|
+
if (failure !== void 0) return {
|
|
69
|
+
failure,
|
|
70
|
+
success: false
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
success: true,
|
|
74
|
+
value
|
|
75
|
+
};
|
|
76
|
+
}
|
|
40
77
|
function findJsonValueError(value, path = "$") {
|
|
41
78
|
return findJsonValueErrorInternal(value, path, /* @__PURE__ */ new Set());
|
|
42
79
|
}
|
|
80
|
+
function findDefinitionEnvelopeFailure(value, path = "$") {
|
|
81
|
+
const jsonError = findJsonValueError(value, path);
|
|
82
|
+
if (jsonError !== void 0) return createDefinitionEnvelopeFailure("definition_envelope_not_json", {
|
|
83
|
+
message: jsonError.reason,
|
|
84
|
+
path: jsonError.path
|
|
85
|
+
});
|
|
86
|
+
if (!isJsonRecord(value)) return createDefinitionEnvelopeFailure("definition_envelope_not_object", { path });
|
|
87
|
+
const versionFailure = findSchemaVersionFailure(value, path);
|
|
88
|
+
if (versionFailure !== void 0) return versionFailure;
|
|
89
|
+
if (!Object.hasOwn(value, "type")) return createDefinitionEnvelopeFailure("generator_type_missing", { path: appendPathSegment(path, "type") });
|
|
90
|
+
const typeValue = value.type;
|
|
91
|
+
if (typeof typeValue !== "string" || typeValue.trim().length === 0) return createDefinitionEnvelopeFailure("generator_type_invalid", { path: appendPathSegment(path, "type") });
|
|
92
|
+
if (!Object.hasOwn(value, "configuration")) return createDefinitionEnvelopeFailure("configuration_missing", { path: appendPathSegment(path, "configuration") });
|
|
93
|
+
if (!isJsonRecord(value.configuration)) return createDefinitionEnvelopeFailure("configuration_invalid", { path: appendPathSegment(path, "configuration") });
|
|
94
|
+
for (const optionalStringField of ["name", "description"]) {
|
|
95
|
+
const fieldFailure = findDefinitionEnvelopeStringFieldFailure(value, {
|
|
96
|
+
invalidCode: optionalStringField === "name" ? "name_invalid" : "description_invalid",
|
|
97
|
+
path: appendPathSegment(path, optionalStringField),
|
|
98
|
+
property: optionalStringField
|
|
99
|
+
});
|
|
100
|
+
if (fieldFailure !== void 0) return fieldFailure;
|
|
101
|
+
}
|
|
102
|
+
const unknownKey = Object.keys(value).find((key) => !DEFINITION_ENVELOPE_TOP_LEVEL_KEYS.includes(key));
|
|
103
|
+
if (unknownKey !== void 0) return createDefinitionEnvelopeFailure("top_level_property_unknown", {
|
|
104
|
+
message: `Unknown top-level property: ${unknownKey}`,
|
|
105
|
+
path: appendPathSegment(path, unknownKey)
|
|
106
|
+
});
|
|
107
|
+
}
|
|
43
108
|
function findSchemaVersionFailure(value, path = "$") {
|
|
44
109
|
if (!isJsonRecord(value) || !Object.hasOwn(value, "schemaVersion")) return createSchemaVersionFailure("schema_version_missing", { path: appendPathSegment(path, "schemaVersion") });
|
|
45
110
|
return findSchemaVersionValueFailure(value.schemaVersion, appendPathSegment(path, "schemaVersion"));
|
|
@@ -83,6 +148,31 @@ function createSchemaVersionFailure(code, options) {
|
|
|
83
148
|
supportedVersions: SUPPORTED_SCHEMA_VERSIONS
|
|
84
149
|
};
|
|
85
150
|
}
|
|
151
|
+
function createDefinitionEnvelopeFailure(code, options) {
|
|
152
|
+
return {
|
|
153
|
+
code,
|
|
154
|
+
message: options.message ?? getDefinitionEnvelopeFailureMessage(code),
|
|
155
|
+
path: options.path,
|
|
156
|
+
severity: "error"
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function getDefinitionEnvelopeFailureMessage(code) {
|
|
160
|
+
switch (code) {
|
|
161
|
+
case "definition_envelope_not_json": return "definition envelope must be portable JSON data";
|
|
162
|
+
case "definition_envelope_not_object": return "definition envelope must be a JSON object";
|
|
163
|
+
case "generator_type_missing": return "type is required";
|
|
164
|
+
case "generator_type_invalid": return "type must be a non-empty string";
|
|
165
|
+
case "configuration_missing": return "configuration is required";
|
|
166
|
+
case "configuration_invalid": return "configuration must be a JSON object";
|
|
167
|
+
case "name_invalid": return "name must be a string when present";
|
|
168
|
+
case "description_invalid": return "description must be a string when present";
|
|
169
|
+
case "top_level_property_unknown": return "unknown top-level properties are not allowed";
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function findDefinitionEnvelopeStringFieldFailure(value, options) {
|
|
173
|
+
if (!Object.hasOwn(value, options.property)) return;
|
|
174
|
+
return typeof value[options.property] === "string" ? void 0 : createDefinitionEnvelopeFailure(options.invalidCode, { path: options.path });
|
|
175
|
+
}
|
|
86
176
|
function appendPathSegment(path, segment) {
|
|
87
177
|
return path === "$" ? `$.${segment}` : `${path}.${segment}`;
|
|
88
178
|
}
|
|
@@ -160,6 +250,6 @@ function findUnsupportedOwnProperty(value, path, allowedNonEnumerableProperties
|
|
|
160
250
|
}
|
|
161
251
|
}
|
|
162
252
|
//#endregion
|
|
163
|
-
export { CURRENT_SCHEMA_VERSION, JsonValueError, SUPPORTED_SCHEMA_VERSIONS, SchemaVersionError, assertJsonValue, assertSchemaVersion, assertVersionedDefinition, findJsonValueError, findSchemaVersionFailure, findSchemaVersionValueFailure, isJsonValue, isSchemaVersion, isVersionedDefinition };
|
|
253
|
+
export { CURRENT_SCHEMA_VERSION, DEFINITION_ENVELOPE_TOP_LEVEL_KEYS, DefinitionEnvelopeError, JsonValueError, SUPPORTED_SCHEMA_VERSIONS, SchemaVersionError, assertDefinitionEnvelope, assertJsonValue, assertSchemaVersion, assertVersionedDefinition, findDefinitionEnvelopeFailure, findJsonValueError, findSchemaVersionFailure, findSchemaVersionValueFailure, isDefinitionEnvelope, isJsonValue, isSchemaVersion, isVersionedDefinition, parseDefinitionEnvelope, safeParseDefinitionEnvelope };
|
|
164
254
|
|
|
165
255
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["export type JsonPrimitive = boolean | null | number | string;\n\nexport type JsonValue = JsonArray | JsonObject | JsonPrimitive;\n\nexport type JsonArray = readonly JsonValue[];\n\nexport type JsonObject = {\n readonly [key: string]: JsonValue;\n};\n\nexport const CURRENT_SCHEMA_VERSION = 1;\n\nexport const SUPPORTED_SCHEMA_VERSIONS = [CURRENT_SCHEMA_VERSION] as const;\n\nexport type SchemaVersion = (typeof SUPPORTED_SCHEMA_VERSIONS)[number];\n\nexport type VersionedDefinition = JsonObject & {\n readonly schemaVersion: SchemaVersion;\n};\n\nexport type SchemaVersionFailureCode =\n | \"schema_version_missing\"\n | \"schema_version_unsupported\";\n\nexport type SchemaVersionFailure = {\n readonly code: SchemaVersionFailureCode;\n readonly message: string;\n readonly path: string;\n readonly severity: \"error\";\n readonly supportedVersions: readonly SchemaVersion[];\n};\n\nexport class JsonValueError extends TypeError {\n constructor(path: string, reason: string) {\n super(`${path}: ${reason}`);\n this.name = \"JsonValueError\";\n }\n}\n\nexport class SchemaVersionError extends TypeError {\n readonly failure: SchemaVersionFailure;\n\n constructor(failure: SchemaVersionFailure) {\n super(`${failure.path}: ${failure.message}`);\n this.name = \"SchemaVersionError\";\n this.failure = failure;\n }\n}\n\nexport function isJsonValue(value: unknown): value is JsonValue {\n return findJsonValueError(value) === undefined;\n}\n\nexport function isSchemaVersion(value: unknown): value is SchemaVersion {\n return value === CURRENT_SCHEMA_VERSION;\n}\n\nexport function isVersionedDefinition(\n value: unknown,\n): value is VersionedDefinition {\n return (\n findSchemaVersionFailure(value) === undefined &&\n isJsonRecord(value) &&\n isJsonValue(value)\n );\n}\n\nexport function assertJsonValue(\n value: unknown,\n path = \"$\",\n): asserts value is JsonValue {\n const error = findJsonValueError(value, path);\n\n if (error !== undefined) {\n throw new JsonValueError(error.path, error.reason);\n }\n}\n\nexport function assertSchemaVersion(\n value: unknown,\n path = \"$.schemaVersion\",\n): asserts value is SchemaVersion {\n const failure = findSchemaVersionValueFailure(value, path);\n\n if (failure !== undefined) {\n throw new SchemaVersionError(failure);\n }\n}\n\nexport function assertVersionedDefinition(\n value: unknown,\n path = \"$\",\n): asserts value is VersionedDefinition {\n const failure = findSchemaVersionFailure(value, path);\n\n if (failure !== undefined) {\n throw new SchemaVersionError(failure);\n }\n\n assertJsonValue(value, path);\n}\n\nexport function findJsonValueError(\n value: unknown,\n path = \"$\",\n): { path: string; reason: string } | undefined {\n return findJsonValueErrorInternal(value, path, new Set());\n}\n\nexport function findSchemaVersionFailure(\n value: unknown,\n path = \"$\",\n): SchemaVersionFailure | undefined {\n if (!isJsonRecord(value) || !Object.hasOwn(value, \"schemaVersion\")) {\n return createSchemaVersionFailure(\"schema_version_missing\", {\n path: appendPathSegment(path, \"schemaVersion\"),\n });\n }\n\n return findSchemaVersionValueFailure(\n value.schemaVersion,\n appendPathSegment(path, \"schemaVersion\"),\n );\n}\n\nexport function findSchemaVersionValueFailure(\n value: unknown,\n path = \"$.schemaVersion\",\n): SchemaVersionFailure | undefined {\n if (isSchemaVersion(value)) {\n return undefined;\n }\n\n return createSchemaVersionFailure(\"schema_version_unsupported\", { path });\n}\n\nfunction findJsonValueErrorInternal(\n value: unknown,\n path: string,\n ancestors: Set<object>,\n): { path: string; reason: string } | undefined {\n switch (typeof value) {\n case \"boolean\":\n case \"string\":\n return undefined;\n case \"number\":\n if (!Number.isFinite(value)) {\n return { path, reason: \"number must be finite\" };\n }\n if (Object.is(value, -0)) {\n return { path, reason: \"number must not be negative zero\" };\n }\n return undefined;\n case \"object\":\n if (value === null) {\n return undefined;\n }\n return findJsonObjectError(value, path, ancestors);\n case \"bigint\":\n case \"function\":\n case \"symbol\":\n case \"undefined\":\n return { path, reason: `${typeof value} is not JSON-compatible` };\n }\n}\n\nfunction createSchemaVersionFailure(\n code: SchemaVersionFailureCode,\n options: { readonly path: string },\n): SchemaVersionFailure {\n return {\n code,\n message:\n code === \"schema_version_missing\"\n ? `schemaVersion is required and must be ${CURRENT_SCHEMA_VERSION}`\n : `schemaVersion must be ${CURRENT_SCHEMA_VERSION}`,\n path: options.path,\n severity: \"error\",\n supportedVersions: SUPPORTED_SCHEMA_VERSIONS,\n };\n}\n\nfunction appendPathSegment(path: string, segment: string) {\n return path === \"$\" ? `$.${segment}` : `${path}.${segment}`;\n}\n\nfunction isJsonRecord(value: unknown): value is Record<string, unknown> {\n const prototype =\n typeof value === \"object\" && value !== null\n ? Object.getPrototypeOf(value)\n : undefined;\n\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n (prototype === null || prototype === Object.prototype)\n );\n}\n\nfunction findJsonObjectError(\n value: object,\n path: string,\n ancestors: Set<object>,\n): { path: string; reason: string } | undefined {\n if (ancestors.has(value)) {\n return { path, reason: \"cyclic objects are not JSON-compatible\" };\n }\n\n if (hasCallableToJson(value)) {\n return { path, reason: \"objects with toJSON behavior are not portable\" };\n }\n\n ancestors.add(value);\n const error = Array.isArray(value)\n ? findJsonArrayError(value, path, ancestors)\n : findJsonRecordError(value, path, ancestors);\n ancestors.delete(value);\n\n return error;\n}\n\nfunction hasCallableToJson(value: object) {\n return (\n \"toJSON\" in value &&\n typeof (value as { readonly toJSON?: unknown }).toJSON === \"function\"\n );\n}\n\nfunction findJsonArrayError(\n value: readonly unknown[],\n path: string,\n ancestors: Set<object>,\n): { path: string; reason: string } | undefined {\n const extraProperty = Object.keys(value).find((key) => !isArrayIndexKey(key));\n\n if (extraProperty !== undefined) {\n return {\n path: `${path}.${extraProperty}`,\n reason: \"array object properties would be omitted from JSON\",\n };\n }\n\n const ownPropertyError = findUnsupportedOwnProperty(value, path, [\"length\"]);\n\n if (ownPropertyError !== undefined) {\n return ownPropertyError;\n }\n\n for (let index = 0; index < value.length; index += 1) {\n if (!(index in value)) {\n return {\n path: `${path}[${index}]`,\n reason: \"sparse array slots are not JSON-compatible\",\n };\n }\n\n const itemError = findJsonValueErrorInternal(\n value[index],\n `${path}[${index}]`,\n ancestors,\n );\n\n if (itemError !== undefined) {\n return itemError;\n }\n }\n\n return undefined;\n}\n\nfunction isArrayIndexKey(key: string) {\n const index = Number(key);\n\n return (\n Number.isInteger(index) &&\n index >= 0 &&\n index < 2 ** 32 - 1 &&\n String(index) === key\n );\n}\n\nfunction findJsonRecordError(\n value: object,\n path: string,\n ancestors: Set<object>,\n): { path: string; reason: string } | undefined {\n const prototype = Object.getPrototypeOf(value);\n\n if (prototype !== null && prototype !== Object.prototype) {\n return { path, reason: \"object must be a plain JSON record\" };\n }\n\n const ownPropertyError = findUnsupportedOwnProperty(value, path);\n\n if (ownPropertyError !== undefined) {\n return ownPropertyError;\n }\n\n for (const key of Object.keys(value)) {\n const itemError = findJsonValueErrorInternal(\n (value as Record<string, unknown>)[key],\n `${path}.${key}`,\n ancestors,\n );\n\n if (itemError !== undefined) {\n return itemError;\n }\n }\n\n return undefined;\n}\n\nfunction findUnsupportedOwnProperty(\n value: object,\n path: string,\n allowedNonEnumerableProperties: readonly string[] = [],\n): { path: string; reason: string } | undefined {\n if (Object.getOwnPropertySymbols(value).length > 0) {\n return { path, reason: \"symbol keys are not JSON-compatible\" };\n }\n\n const allowedNonEnumerable = new Set(allowedNonEnumerableProperties);\n const descriptors = Object.getOwnPropertyDescriptors(value);\n\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (\"get\" in descriptor || \"set\" in descriptor) {\n return {\n path: `${path}.${key}`,\n reason: \"accessor properties are not portable JSON data\",\n };\n }\n\n if (!descriptor.enumerable && !allowedNonEnumerable.has(key)) {\n return {\n path: `${path}.${key}`,\n reason: \"non-enumerable properties would be omitted from JSON\",\n };\n }\n }\n\n return undefined;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["export type JsonPrimitive = boolean | null | number | string;\n\nexport type JsonValue = JsonArray | JsonObject | JsonPrimitive;\n\nexport type JsonArray = readonly JsonValue[];\n\nexport type JsonObject = {\n readonly [key: string]: JsonValue;\n};\n\nexport const CURRENT_SCHEMA_VERSION = 1;\n\nexport const SUPPORTED_SCHEMA_VERSIONS = [CURRENT_SCHEMA_VERSION] as const;\n\nexport type SchemaVersion = (typeof SUPPORTED_SCHEMA_VERSIONS)[number];\n\nexport type VersionedDefinition = JsonObject & {\n readonly schemaVersion: SchemaVersion;\n};\n\nexport type DefinitionEnvelope = {\n readonly schemaVersion: SchemaVersion;\n readonly type: string;\n readonly configuration: JsonObject;\n readonly name?: string;\n readonly description?: string;\n};\n\nexport const DEFINITION_ENVELOPE_TOP_LEVEL_KEYS = [\n \"schemaVersion\",\n \"type\",\n \"configuration\",\n \"name\",\n \"description\",\n] as const;\n\nexport type SchemaVersionFailureCode =\n | \"schema_version_missing\"\n | \"schema_version_unsupported\";\n\nexport type SchemaVersionFailure = {\n readonly code: SchemaVersionFailureCode;\n readonly message: string;\n readonly path: string;\n readonly severity: \"error\";\n readonly supportedVersions: readonly SchemaVersion[];\n};\n\nexport type DefinitionEnvelopeFailureCode =\n | SchemaVersionFailureCode\n | \"definition_envelope_not_json\"\n | \"definition_envelope_not_object\"\n | \"generator_type_missing\"\n | \"generator_type_invalid\"\n | \"configuration_missing\"\n | \"configuration_invalid\"\n | \"name_invalid\"\n | \"description_invalid\"\n | \"top_level_property_unknown\";\n\nexport type DefinitionEnvelopeShapeFailureCode = Exclude<\n DefinitionEnvelopeFailureCode,\n SchemaVersionFailureCode\n>;\n\nexport type DefinitionEnvelopeShapeFailure = {\n readonly code: DefinitionEnvelopeShapeFailureCode;\n readonly message: string;\n readonly path: string;\n readonly severity: \"error\";\n};\n\nexport type DefinitionEnvelopeFailure =\n | SchemaVersionFailure\n | DefinitionEnvelopeShapeFailure;\n\nexport type DefinitionEnvelopeParseResult =\n | {\n readonly success: true;\n readonly value: DefinitionEnvelope;\n }\n | {\n readonly success: false;\n readonly failure: DefinitionEnvelopeFailure;\n };\n\nexport class JsonValueError extends TypeError {\n constructor(path: string, reason: string) {\n super(`${path}: ${reason}`);\n this.name = \"JsonValueError\";\n }\n}\n\nexport class SchemaVersionError extends TypeError {\n readonly failure: SchemaVersionFailure;\n\n constructor(failure: SchemaVersionFailure) {\n super(`${failure.path}: ${failure.message}`);\n this.name = \"SchemaVersionError\";\n this.failure = failure;\n }\n}\n\nexport class DefinitionEnvelopeError extends TypeError {\n readonly failure: DefinitionEnvelopeFailure;\n\n constructor(failure: DefinitionEnvelopeFailure) {\n super(`${failure.path}: ${failure.message}`);\n this.name = \"DefinitionEnvelopeError\";\n this.failure = failure;\n }\n}\n\nexport function isJsonValue(value: unknown): value is JsonValue {\n return findJsonValueError(value) === undefined;\n}\n\nexport function isSchemaVersion(value: unknown): value is SchemaVersion {\n return value === CURRENT_SCHEMA_VERSION;\n}\n\nexport function isVersionedDefinition(\n value: unknown,\n): value is VersionedDefinition {\n return (\n findSchemaVersionFailure(value) === undefined &&\n isJsonRecord(value) &&\n isJsonValue(value)\n );\n}\n\nexport function isDefinitionEnvelope(\n value: unknown,\n): value is DefinitionEnvelope {\n return findDefinitionEnvelopeFailure(value) === undefined;\n}\n\nexport function assertJsonValue(\n value: unknown,\n path = \"$\",\n): asserts value is JsonValue {\n const error = findJsonValueError(value, path);\n\n if (error !== undefined) {\n throw new JsonValueError(error.path, error.reason);\n }\n}\n\nexport function assertSchemaVersion(\n value: unknown,\n path = \"$.schemaVersion\",\n): asserts value is SchemaVersion {\n const failure = findSchemaVersionValueFailure(value, path);\n\n if (failure !== undefined) {\n throw new SchemaVersionError(failure);\n }\n}\n\nexport function assertVersionedDefinition(\n value: unknown,\n path = \"$\",\n): asserts value is VersionedDefinition {\n const failure = findSchemaVersionFailure(value, path);\n\n if (failure !== undefined) {\n throw new SchemaVersionError(failure);\n }\n\n assertJsonValue(value, path);\n}\n\nexport function assertDefinitionEnvelope(\n value: unknown,\n path = \"$\",\n): asserts value is DefinitionEnvelope {\n const failure = findDefinitionEnvelopeFailure(value, path);\n\n if (failure !== undefined) {\n throw new DefinitionEnvelopeError(failure);\n }\n}\n\nexport function parseDefinitionEnvelope(\n value: unknown,\n path = \"$\",\n): DefinitionEnvelope {\n assertDefinitionEnvelope(value, path);\n return value;\n}\n\nexport function safeParseDefinitionEnvelope(\n value: unknown,\n path = \"$\",\n): DefinitionEnvelopeParseResult {\n const failure = findDefinitionEnvelopeFailure(value, path);\n\n if (failure !== undefined) {\n return { failure, success: false };\n }\n\n return { success: true, value: value as DefinitionEnvelope };\n}\n\nexport function findJsonValueError(\n value: unknown,\n path = \"$\",\n): { path: string; reason: string } | undefined {\n return findJsonValueErrorInternal(value, path, new Set());\n}\n\nexport function findDefinitionEnvelopeFailure(\n value: unknown,\n path = \"$\",\n): DefinitionEnvelopeFailure | undefined {\n const jsonError = findJsonValueError(value, path);\n\n if (jsonError !== undefined) {\n return createDefinitionEnvelopeFailure(\"definition_envelope_not_json\", {\n message: jsonError.reason,\n path: jsonError.path,\n });\n }\n\n if (!isJsonRecord(value)) {\n return createDefinitionEnvelopeFailure(\"definition_envelope_not_object\", {\n path,\n });\n }\n\n const versionFailure = findSchemaVersionFailure(value, path);\n\n if (versionFailure !== undefined) {\n return versionFailure;\n }\n\n if (!Object.hasOwn(value, \"type\")) {\n return createDefinitionEnvelopeFailure(\"generator_type_missing\", {\n path: appendPathSegment(path, \"type\"),\n });\n }\n\n const typeValue = value.type;\n\n if (typeof typeValue !== \"string\" || typeValue.trim().length === 0) {\n return createDefinitionEnvelopeFailure(\"generator_type_invalid\", {\n path: appendPathSegment(path, \"type\"),\n });\n }\n\n if (!Object.hasOwn(value, \"configuration\")) {\n return createDefinitionEnvelopeFailure(\"configuration_missing\", {\n path: appendPathSegment(path, \"configuration\"),\n });\n }\n\n if (!isJsonRecord(value.configuration)) {\n return createDefinitionEnvelopeFailure(\"configuration_invalid\", {\n path: appendPathSegment(path, \"configuration\"),\n });\n }\n\n for (const optionalStringField of [\"name\", \"description\"] as const) {\n const fieldFailure = findDefinitionEnvelopeStringFieldFailure(value, {\n invalidCode:\n optionalStringField === \"name\" ? \"name_invalid\" : \"description_invalid\",\n path: appendPathSegment(path, optionalStringField),\n property: optionalStringField,\n });\n\n if (fieldFailure !== undefined) {\n return fieldFailure;\n }\n }\n\n const unknownKey = Object.keys(value).find(\n (key) =>\n !DEFINITION_ENVELOPE_TOP_LEVEL_KEYS.includes(\n key as (typeof DEFINITION_ENVELOPE_TOP_LEVEL_KEYS)[number],\n ),\n );\n\n if (unknownKey !== undefined) {\n return createDefinitionEnvelopeFailure(\"top_level_property_unknown\", {\n message: `Unknown top-level property: ${unknownKey}`,\n path: appendPathSegment(path, unknownKey),\n });\n }\n\n return undefined;\n}\n\nexport function findSchemaVersionFailure(\n value: unknown,\n path = \"$\",\n): SchemaVersionFailure | undefined {\n if (!isJsonRecord(value) || !Object.hasOwn(value, \"schemaVersion\")) {\n return createSchemaVersionFailure(\"schema_version_missing\", {\n path: appendPathSegment(path, \"schemaVersion\"),\n });\n }\n\n return findSchemaVersionValueFailure(\n value.schemaVersion,\n appendPathSegment(path, \"schemaVersion\"),\n );\n}\n\nexport function findSchemaVersionValueFailure(\n value: unknown,\n path = \"$.schemaVersion\",\n): SchemaVersionFailure | undefined {\n if (isSchemaVersion(value)) {\n return undefined;\n }\n\n return createSchemaVersionFailure(\"schema_version_unsupported\", { path });\n}\n\nfunction findJsonValueErrorInternal(\n value: unknown,\n path: string,\n ancestors: Set<object>,\n): { path: string; reason: string } | undefined {\n switch (typeof value) {\n case \"boolean\":\n case \"string\":\n return undefined;\n case \"number\":\n if (!Number.isFinite(value)) {\n return { path, reason: \"number must be finite\" };\n }\n if (Object.is(value, -0)) {\n return { path, reason: \"number must not be negative zero\" };\n }\n return undefined;\n case \"object\":\n if (value === null) {\n return undefined;\n }\n return findJsonObjectError(value, path, ancestors);\n case \"bigint\":\n case \"function\":\n case \"symbol\":\n case \"undefined\":\n return { path, reason: `${typeof value} is not JSON-compatible` };\n }\n}\n\nfunction createSchemaVersionFailure(\n code: SchemaVersionFailureCode,\n options: { readonly path: string },\n): SchemaVersionFailure {\n return {\n code,\n message:\n code === \"schema_version_missing\"\n ? `schemaVersion is required and must be ${CURRENT_SCHEMA_VERSION}`\n : `schemaVersion must be ${CURRENT_SCHEMA_VERSION}`,\n path: options.path,\n severity: \"error\",\n supportedVersions: SUPPORTED_SCHEMA_VERSIONS,\n };\n}\n\nfunction createDefinitionEnvelopeFailure(\n code: DefinitionEnvelopeShapeFailureCode,\n options: { readonly message?: string; readonly path: string },\n): DefinitionEnvelopeShapeFailure {\n return {\n code,\n message: options.message ?? getDefinitionEnvelopeFailureMessage(code),\n path: options.path,\n severity: \"error\",\n };\n}\n\nfunction getDefinitionEnvelopeFailureMessage(\n code: DefinitionEnvelopeShapeFailureCode,\n) {\n switch (code) {\n case \"definition_envelope_not_json\":\n return \"definition envelope must be portable JSON data\";\n case \"definition_envelope_not_object\":\n return \"definition envelope must be a JSON object\";\n case \"generator_type_missing\":\n return \"type is required\";\n case \"generator_type_invalid\":\n return \"type must be a non-empty string\";\n case \"configuration_missing\":\n return \"configuration is required\";\n case \"configuration_invalid\":\n return \"configuration must be a JSON object\";\n case \"name_invalid\":\n return \"name must be a string when present\";\n case \"description_invalid\":\n return \"description must be a string when present\";\n case \"top_level_property_unknown\":\n return \"unknown top-level properties are not allowed\";\n }\n}\n\nfunction findDefinitionEnvelopeStringFieldFailure(\n value: Record<string, unknown>,\n options: {\n readonly invalidCode: DefinitionEnvelopeShapeFailureCode;\n readonly path: string;\n readonly property: string;\n },\n): DefinitionEnvelopeShapeFailure | undefined {\n if (!Object.hasOwn(value, options.property)) {\n return undefined;\n }\n\n return typeof value[options.property] === \"string\"\n ? undefined\n : createDefinitionEnvelopeFailure(options.invalidCode, {\n path: options.path,\n });\n}\n\nfunction appendPathSegment(path: string, segment: string) {\n return path === \"$\" ? `$.${segment}` : `${path}.${segment}`;\n}\n\nfunction isJsonRecord(value: unknown): value is Record<string, unknown> {\n const prototype =\n typeof value === \"object\" && value !== null\n ? Object.getPrototypeOf(value)\n : undefined;\n\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n (prototype === null || prototype === Object.prototype)\n );\n}\n\nfunction findJsonObjectError(\n value: object,\n path: string,\n ancestors: Set<object>,\n): { path: string; reason: string } | undefined {\n if (ancestors.has(value)) {\n return { path, reason: \"cyclic objects are not JSON-compatible\" };\n }\n\n if (hasCallableToJson(value)) {\n return { path, reason: \"objects with toJSON behavior are not portable\" };\n }\n\n ancestors.add(value);\n const error = Array.isArray(value)\n ? findJsonArrayError(value, path, ancestors)\n : findJsonRecordError(value, path, ancestors);\n ancestors.delete(value);\n\n return error;\n}\n\nfunction hasCallableToJson(value: object) {\n return (\n \"toJSON\" in value &&\n typeof (value as { readonly toJSON?: unknown }).toJSON === \"function\"\n );\n}\n\nfunction findJsonArrayError(\n value: readonly unknown[],\n path: string,\n ancestors: Set<object>,\n): { path: string; reason: string } | undefined {\n const extraProperty = Object.keys(value).find((key) => !isArrayIndexKey(key));\n\n if (extraProperty !== undefined) {\n return {\n path: `${path}.${extraProperty}`,\n reason: \"array object properties would be omitted from JSON\",\n };\n }\n\n const ownPropertyError = findUnsupportedOwnProperty(value, path, [\"length\"]);\n\n if (ownPropertyError !== undefined) {\n return ownPropertyError;\n }\n\n for (let index = 0; index < value.length; index += 1) {\n if (!(index in value)) {\n return {\n path: `${path}[${index}]`,\n reason: \"sparse array slots are not JSON-compatible\",\n };\n }\n\n const itemError = findJsonValueErrorInternal(\n value[index],\n `${path}[${index}]`,\n ancestors,\n );\n\n if (itemError !== undefined) {\n return itemError;\n }\n }\n\n return undefined;\n}\n\nfunction isArrayIndexKey(key: string) {\n const index = Number(key);\n\n return (\n Number.isInteger(index) &&\n index >= 0 &&\n index < 2 ** 32 - 1 &&\n String(index) === key\n );\n}\n\nfunction findJsonRecordError(\n value: object,\n path: string,\n ancestors: Set<object>,\n): { path: string; reason: string } | undefined {\n const prototype = Object.getPrototypeOf(value);\n\n if (prototype !== null && prototype !== Object.prototype) {\n return { path, reason: \"object must be a plain JSON record\" };\n }\n\n const ownPropertyError = findUnsupportedOwnProperty(value, path);\n\n if (ownPropertyError !== undefined) {\n return ownPropertyError;\n }\n\n for (const key of Object.keys(value)) {\n const itemError = findJsonValueErrorInternal(\n (value as Record<string, unknown>)[key],\n `${path}.${key}`,\n ancestors,\n );\n\n if (itemError !== undefined) {\n return itemError;\n }\n }\n\n return undefined;\n}\n\nfunction findUnsupportedOwnProperty(\n value: object,\n path: string,\n allowedNonEnumerableProperties: readonly string[] = [],\n): { path: string; reason: string } | undefined {\n if (Object.getOwnPropertySymbols(value).length > 0) {\n return { path, reason: \"symbol keys are not JSON-compatible\" };\n }\n\n const allowedNonEnumerable = new Set(allowedNonEnumerableProperties);\n const descriptors = Object.getOwnPropertyDescriptors(value);\n\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (\"get\" in descriptor || \"set\" in descriptor) {\n return {\n path: `${path}.${key}`,\n reason: \"accessor properties are not portable JSON data\",\n };\n }\n\n if (!descriptor.enumerable && !allowedNonEnumerable.has(key)) {\n return {\n path: `${path}.${key}`,\n reason: \"non-enumerable properties would be omitted from JSON\",\n };\n }\n }\n\n return undefined;\n}\n"],"mappings":"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"}
|