toolcraft-openapi 0.0.122 → 0.0.124

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.
Files changed (39) hide show
  1. package/dist/composition.json +6 -1
  2. package/node_modules/toolcraft-schema/LICENSE +21 -0
  3. package/node_modules/toolcraft-schema/README.md +89 -0
  4. package/node_modules/toolcraft-schema/dist/index.compile-check.d.ts +1 -0
  5. package/node_modules/toolcraft-schema/dist/index.compile-check.js +17 -0
  6. package/node_modules/toolcraft-schema/dist/index.d.ts +184 -0
  7. package/node_modules/toolcraft-schema/dist/index.js +295 -0
  8. package/node_modules/toolcraft-schema/dist/json-schema/compiler.d.ts +11 -0
  9. package/node_modules/toolcraft-schema/dist/json-schema/compiler.js +390 -0
  10. package/node_modules/toolcraft-schema/dist/json-schema/evaluate.d.ts +3 -0
  11. package/node_modules/toolcraft-schema/dist/json-schema/evaluate.js +442 -0
  12. package/node_modules/toolcraft-schema/dist/json-schema/index.d.ts +5 -0
  13. package/node_modules/toolcraft-schema/dist/json-schema/index.js +19 -0
  14. package/node_modules/toolcraft-schema/dist/json-schema/types.d.ts +33 -0
  15. package/node_modules/toolcraft-schema/dist/json-schema/types.js +1 -0
  16. package/node_modules/toolcraft-schema/dist/json-schema/utils.d.ts +19 -0
  17. package/node_modules/toolcraft-schema/dist/json-schema/utils.js +171 -0
  18. package/node_modules/toolcraft-schema/dist/json-schema-document.d.ts +14 -0
  19. package/node_modules/toolcraft-schema/dist/json-schema-document.js +17 -0
  20. package/node_modules/toolcraft-schema/dist/json.compile-check.d.ts +1 -0
  21. package/node_modules/toolcraft-schema/dist/json.compile-check.js +2 -0
  22. package/node_modules/toolcraft-schema/dist/json.d.ts +10 -0
  23. package/node_modules/toolcraft-schema/dist/json.js +5 -0
  24. package/node_modules/toolcraft-schema/dist/oneof.compile-check.d.ts +1 -0
  25. package/node_modules/toolcraft-schema/dist/oneof.compile-check.js +12 -0
  26. package/node_modules/toolcraft-schema/dist/oneof.d.ts +15 -0
  27. package/node_modules/toolcraft-schema/dist/oneof.js +18 -0
  28. package/node_modules/toolcraft-schema/dist/record.compile-check.d.ts +1 -0
  29. package/node_modules/toolcraft-schema/dist/record.compile-check.js +2 -0
  30. package/node_modules/toolcraft-schema/dist/record.d.ts +5 -0
  31. package/node_modules/toolcraft-schema/dist/record.js +6 -0
  32. package/node_modules/toolcraft-schema/dist/union.compile-check.d.ts +1 -0
  33. package/node_modules/toolcraft-schema/dist/union.compile-check.js +9 -0
  34. package/node_modules/toolcraft-schema/dist/union.d.ts +8 -0
  35. package/node_modules/toolcraft-schema/dist/union.js +45 -0
  36. package/node_modules/toolcraft-schema/dist/validate.d.ts +17 -0
  37. package/node_modules/toolcraft-schema/dist/validate.js +379 -0
  38. package/node_modules/toolcraft-schema/package.json +33 -0
  39. package/package.json +6 -4
@@ -0,0 +1,171 @@
1
+ export function isSchema(value) {
2
+ return typeof value === "boolean" || isObject(value);
3
+ }
4
+ export function isObject(value) {
5
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6
+ }
7
+ export function dialectFor(schema, inherited) {
8
+ const dialect = schema.$schema;
9
+ if (typeof dialect !== "string") {
10
+ return inherited;
11
+ }
12
+ if (dialect.includes("draft-07")) {
13
+ return "draft7";
14
+ }
15
+ if (dialect.includes("2020-12")) {
16
+ return "draft2020-12";
17
+ }
18
+ return inherited;
19
+ }
20
+ export function resolveUri(reference, baseUri) {
21
+ try {
22
+ return new URL(reference, baseUri).href;
23
+ }
24
+ catch {
25
+ throw new Error(`Invalid schema URI: ${reference}`);
26
+ }
27
+ }
28
+ export function withoutFragment(uri) {
29
+ const index = uri.indexOf("#");
30
+ return index === -1 ? uri : uri.slice(0, index);
31
+ }
32
+ export function fragmentOf(uri) {
33
+ const index = uri.indexOf("#");
34
+ return index === -1 ? "" : uri.slice(index + 1);
35
+ }
36
+ export function escapePointer(value) {
37
+ return value.replaceAll("~", "~0").replaceAll("/", "~1");
38
+ }
39
+ export function decodePointer(value) {
40
+ return decodeURIComponent(value).replaceAll("~1", "/").replaceAll("~0", "~");
41
+ }
42
+ export function deepEqual(left, right) {
43
+ if (Object.is(left, right)) {
44
+ return true;
45
+ }
46
+ if (typeof left !== typeof right || left === null || right === null) {
47
+ return false;
48
+ }
49
+ if (Array.isArray(left)) {
50
+ return (Array.isArray(right) &&
51
+ left.length === right.length &&
52
+ left.every((value, index) => deepEqual(value, right[index])));
53
+ }
54
+ if (isObject(left) && isObject(right)) {
55
+ const leftKeys = Object.keys(left);
56
+ const rightKeys = Object.keys(right);
57
+ return (leftKeys.length === rightKeys.length &&
58
+ leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key])));
59
+ }
60
+ return false;
61
+ }
62
+ export function receivedType(value) {
63
+ if (value === null) {
64
+ return "null";
65
+ }
66
+ if (Array.isArray(value)) {
67
+ return "array";
68
+ }
69
+ if (typeof value === "number" && Number.isInteger(value)) {
70
+ return "integer";
71
+ }
72
+ return typeof value;
73
+ }
74
+ export function issue(path, expected, value, message, keyword = keywordFor(expected)) {
75
+ return { path, expected, received: receivedType(value), message, keyword };
76
+ }
77
+ function keywordFor(expected) {
78
+ if (["null", "boolean", "object", "array", "number", "integer", "string"].includes(expected)) {
79
+ return "type";
80
+ }
81
+ if (expected.startsWith("multiple of"))
82
+ return "multipleOf";
83
+ if (expected.startsWith("length <="))
84
+ return "maxLength";
85
+ if (expected.startsWith("length >="))
86
+ return "minLength";
87
+ if (expected.startsWith("pattern "))
88
+ return "pattern";
89
+ if (expected.startsWith("items <="))
90
+ return "maxItems";
91
+ if (expected.startsWith("items >="))
92
+ return "minItems";
93
+ if (expected === "unique items")
94
+ return "uniqueItems";
95
+ if (expected.startsWith("properties <="))
96
+ return "maxProperties";
97
+ if (expected.startsWith("properties >="))
98
+ return "minProperties";
99
+ if (expected.startsWith("<= "))
100
+ return "maximum";
101
+ if (expected.startsWith(">= "))
102
+ return "minimum";
103
+ if (expected.startsWith("< "))
104
+ return "exclusiveMaximum";
105
+ if (expected.startsWith("> "))
106
+ return "exclusiveMinimum";
107
+ if (expected === "valid schema")
108
+ return "false schema";
109
+ return expected;
110
+ }
111
+ export function validResult() {
112
+ return {
113
+ valid: true,
114
+ issues: [],
115
+ evaluatedProperties: new Set(),
116
+ evaluatedItems: new Set()
117
+ };
118
+ }
119
+ export function invalidResult(problem) {
120
+ return {
121
+ valid: false,
122
+ issues: [problem],
123
+ evaluatedProperties: new Set(),
124
+ evaluatedItems: new Set()
125
+ };
126
+ }
127
+ export function mergeResults(results) {
128
+ const merged = validResult();
129
+ for (const result of results) {
130
+ merged.valid &&= result.valid;
131
+ merged.issues.push(...result.issues);
132
+ for (const key of result.evaluatedProperties) {
133
+ merged.evaluatedProperties.add(key);
134
+ }
135
+ for (const index of result.evaluatedItems) {
136
+ merged.evaluatedItems.add(index);
137
+ }
138
+ }
139
+ return merged;
140
+ }
141
+ export function typeMatches(type, value) {
142
+ switch (type) {
143
+ case "null":
144
+ return value === null;
145
+ case "boolean":
146
+ return typeof value === "boolean";
147
+ case "object":
148
+ return isObject(value);
149
+ case "array":
150
+ return Array.isArray(value);
151
+ case "number":
152
+ return typeof value === "number" && Number.isFinite(value);
153
+ case "integer":
154
+ return typeof value === "number" && Number.isInteger(value);
155
+ case "string":
156
+ return typeof value === "string";
157
+ default:
158
+ return true;
159
+ }
160
+ }
161
+ export function unicodeLength(value) {
162
+ return [...value].length;
163
+ }
164
+ export function isMultipleOf(value, divisor) {
165
+ if (divisor === 0) {
166
+ return false;
167
+ }
168
+ const quotient = value / divisor;
169
+ return (Math.abs(quotient - Math.round(quotient)) <=
170
+ Number.EPSILON * Math.max(1, Math.abs(quotient)) * 4);
171
+ }
@@ -0,0 +1,14 @@
1
+ import type { JsonSchema } from "./index.js";
2
+ export interface JsonSchemaDocumentOptions {
3
+ id?: string;
4
+ title?: string;
5
+ description?: string;
6
+ schema?: string;
7
+ }
8
+ export type JsonSchemaDocument = JsonSchema & {
9
+ $schema: string;
10
+ $id?: string;
11
+ title?: string;
12
+ description?: string;
13
+ };
14
+ export declare function createJsonSchemaDocument(jsonSchema: JsonSchema, options?: JsonSchemaDocumentOptions): JsonSchemaDocument;
@@ -0,0 +1,17 @@
1
+ export function createJsonSchemaDocument(jsonSchema, options = {}) {
2
+ const { id, schema: schemaUri = "https://json-schema.org/draft/2020-12/schema", ...metadata } = options;
3
+ const document = {
4
+ $schema: schemaUri,
5
+ ...jsonSchema
6
+ };
7
+ if (id !== undefined) {
8
+ document.$id = id;
9
+ }
10
+ if (metadata.title !== undefined) {
11
+ document.title = metadata.title;
12
+ }
13
+ if (metadata.description !== undefined) {
14
+ document.description = metadata.description;
15
+ }
16
+ return document;
17
+ }
@@ -0,0 +1,2 @@
1
+ import { S } from "./index.js";
2
+ const ignoredSchema = S.Json();
@@ -0,0 +1,10 @@
1
+ import type { SchemaBase } from "./index.js";
2
+ type JsonPrimitive = string | number | boolean | null;
3
+ export type JsonValue = JsonPrimitive | {
4
+ [key: string]: JsonValue;
5
+ } | JsonValue[];
6
+ export interface JsonValueSchema extends SchemaBase<"json", JsonValue> {
7
+ readonly kind: "json";
8
+ }
9
+ export declare function Json(): JsonValueSchema;
10
+ export {};
@@ -0,0 +1,5 @@
1
+ export function Json() {
2
+ return {
3
+ kind: "json",
4
+ };
5
+ }
@@ -0,0 +1,12 @@
1
+ import { S } from "./index.js";
2
+ const ignoredSchema = S.OneOf({
3
+ discriminator: "kind",
4
+ branches: {
5
+ text: S.Object({
6
+ value: S.String(),
7
+ }),
8
+ count: S.Object({
9
+ value: S.Number(),
10
+ }),
11
+ },
12
+ });
@@ -0,0 +1,15 @@
1
+ import type { ObjectSchema, SchemaBase, Static } from "./index.js";
2
+ type OneOfStatic<TBranches extends Record<string, ObjectSchema<any>>, TDiscriminator extends string> = {
3
+ [TBranchName in keyof TBranches & string]: Omit<Static<TBranches[TBranchName]>, TDiscriminator> & {
4
+ [TFieldName in TDiscriminator]: TBranchName;
5
+ };
6
+ }[keyof TBranches & string];
7
+ export interface OneOfSchema<TBranches extends Record<string, ObjectSchema<any>>, TDiscriminator extends string = string> extends SchemaBase<"oneOf", OneOfStatic<TBranches, TDiscriminator>> {
8
+ readonly discriminator: TDiscriminator;
9
+ readonly branches: TBranches;
10
+ }
11
+ export declare function OneOf<TDiscriminator extends string, TBranches extends Record<string, ObjectSchema<any>>>(config: {
12
+ discriminator: TDiscriminator;
13
+ branches: TBranches;
14
+ }): OneOfSchema<TBranches, TDiscriminator>;
15
+ export {};
@@ -0,0 +1,18 @@
1
+ function assertValidBranches(branches, discriminator) {
2
+ if (Object.keys(branches).length === 0) {
3
+ throw new Error("OneOf schema requires at least one branch");
4
+ }
5
+ for (const [branchName, branch] of Object.entries(branches)) {
6
+ if (Object.prototype.hasOwnProperty.call(branch.shape, discriminator)) {
7
+ throw new Error(`OneOf branch "${branchName}" must not declare discriminator field "${discriminator}".`);
8
+ }
9
+ }
10
+ }
11
+ export function OneOf(config) {
12
+ assertValidBranches(config.branches, config.discriminator);
13
+ return {
14
+ kind: "oneOf",
15
+ discriminator: config.discriminator,
16
+ branches: config.branches,
17
+ };
18
+ }
@@ -0,0 +1,2 @@
1
+ import { S } from "./index.js";
2
+ const ignoredSchema = S.Record(S.String());
@@ -0,0 +1,5 @@
1
+ import type { AnySchema, SchemaBase, Static } from "./index.js";
2
+ export interface RecordSchema<TValue extends AnySchema> extends SchemaBase<"record", Record<string, Static<TValue>>> {
3
+ readonly value: TValue;
4
+ }
5
+ export declare function Record<TValue extends AnySchema>(value: TValue): RecordSchema<TValue>;
@@ -0,0 +1,6 @@
1
+ export function Record(value) {
2
+ return {
3
+ kind: "record",
4
+ value,
5
+ };
6
+ }
@@ -0,0 +1,9 @@
1
+ import { S } from "./index.js";
2
+ const ignoredSchema = S.Union([
3
+ S.Object({
4
+ email: S.String(),
5
+ }),
6
+ S.Object({
7
+ phone: S.String(),
8
+ }),
9
+ ]);
@@ -0,0 +1,8 @@
1
+ import type { ObjectSchema, SchemaBase, Static } from "./index.js";
2
+ type UnionStatic<TBranches extends readonly ObjectSchema<any>[]> = Static<TBranches[number]>;
3
+ export interface UnionSchema<TBranches extends readonly ObjectSchema<any>[]> extends SchemaBase<"union", UnionStatic<TBranches>> {
4
+ readonly branches: TBranches;
5
+ }
6
+ export declare function getRequiredKeyFingerprint(schema: ObjectSchema<any>): string;
7
+ export declare function Union<const TBranches extends readonly ObjectSchema<any>[]>(branches: TBranches): UnionSchema<TBranches>;
8
+ export {};
@@ -0,0 +1,45 @@
1
+ function isOptionalSchema(schema) {
2
+ return schema.kind === "optional";
3
+ }
4
+ function getRequiredKeys(schema) {
5
+ return Object.keys(schema.shape)
6
+ .filter((key) => !isOptionalSchema(schema.shape[key]))
7
+ .sort();
8
+ }
9
+ export function getRequiredKeyFingerprint(schema) {
10
+ return getRequiredKeys(schema).join("+");
11
+ }
12
+ function assertUniqueRequiredKeyFingerprints(branches) {
13
+ const fingerprints = new Map();
14
+ branches.forEach((branch, index) => {
15
+ const requiredKeys = getRequiredKeys(branch);
16
+ const fingerprint = JSON.stringify(requiredKeys);
17
+ const existing = fingerprints.get(fingerprint);
18
+ if (existing === undefined) {
19
+ fingerprints.set(fingerprint, {
20
+ display: requiredKeys.join("+"),
21
+ indices: [index],
22
+ });
23
+ return;
24
+ }
25
+ existing.indices.push(index);
26
+ });
27
+ for (const { display, indices } of fingerprints.values()) {
28
+ if (indices.length > 1) {
29
+ throw new Error(`Union branches [${indices.join(", ")}] share required-key fingerprint "${display}". Each branch must require a distinct set of keys.`);
30
+ }
31
+ }
32
+ }
33
+ function assertValidBranches(branches) {
34
+ if (branches.length === 0) {
35
+ throw new Error("Union schema requires at least one branch");
36
+ }
37
+ assertUniqueRequiredKeyFingerprints(branches);
38
+ }
39
+ export function Union(branches) {
40
+ assertValidBranches(branches);
41
+ return {
42
+ kind: "union",
43
+ branches,
44
+ };
45
+ }
@@ -0,0 +1,17 @@
1
+ import type { AnySchema, Static } from "./index.js";
2
+ export type SchemaDescriptor = AnySchema;
3
+ export type ValidationIssue = {
4
+ path: readonly string[];
5
+ expected: string;
6
+ received: string;
7
+ message: string;
8
+ keyword?: string;
9
+ };
10
+ export type ValidationResult<T> = {
11
+ ok: true;
12
+ value: T;
13
+ } | {
14
+ ok: false;
15
+ issues: readonly ValidationIssue[];
16
+ };
17
+ export declare function validate<S extends SchemaDescriptor>(schema: S, value: unknown): ValidationResult<Static<S>>;