@takeshape/json-schema 11.105.1 → 11.107.1

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.
@@ -1,7 +1,7 @@
1
1
  import { assert, ensureArray } from '@takeshape/util';
2
2
  import intersection from 'lodash/intersection.js';
3
3
  import uniq from 'lodash/uniq.js';
4
- import { getReferenceMap, isAllOfSchema, isAnyOfSchema, isArraySchema, isEnumSchema, isListSchema, isObjectSchema, isOneOfSchema, isPropertySchema, isRefSchema, isTupleSchema, pickJSONSchema7 } from "../utils/index.js";
4
+ import { getReferenceMap, isAllOfSchema, isAnyOfSchema, isArraySchema, isEnumSchema, isListSchema, isObjectSchema, isObjectSchemaWithProperties, isOneOfSchema, isRefSchema, isTupleSchema, pickJSONSchema7 } from "../utils/index.js";
5
5
  export var SchemaConversionTarget;
6
6
  (function (SchemaConversionTarget) {
7
7
  SchemaConversionTarget["OpenAI"] = "OPENAI";
@@ -74,7 +74,7 @@ export class SchemaConverter {
74
74
  this.warnings.push(`Schema has ${this.stats.enumValuesCount} enum values across all properties, exceeding the 500 limit`);
75
75
  }
76
76
  // Check if root is an object
77
- if (target === SchemaConversionTarget.OpenAI && !isPropertySchema(result)) {
77
+ if (target === SchemaConversionTarget.OpenAI && !isObjectSchemaWithProperties(result)) {
78
78
  this.warnings.push('Root level must be an object type, wrapping in an object');
79
79
  // Attempt to fix by wrapping in an object if possible
80
80
  return {
@@ -116,7 +116,7 @@ export class SchemaConverter {
116
116
  return this.processRefSchema(context, schemaCopy);
117
117
  }
118
118
  // Process specific types
119
- if (isObjectSchema(schemaCopy) || isPropertySchema(schemaCopy)) {
119
+ if (isObjectSchema(schemaCopy)) {
120
120
  return this.addNullable(this.processObjectSchema(context, schemaCopy), isRequired);
121
121
  }
122
122
  if (isArraySchema(schemaCopy)) {
@@ -419,7 +419,7 @@ export class SchemaConverter {
419
419
  // Try to merge properties from all schemas
420
420
  for (const [index, value] of allOfSchemas.entries()) {
421
421
  const subSchema = this.processSchema({ ...context, path: [...path, 'allOf', index] }, value);
422
- if (isObjectSchema(subSchema) && isPropertySchema(subSchema)) {
422
+ if (isObjectSchemaWithProperties(subSchema)) {
423
423
  // Merge properties
424
424
  newSchema.properties = {
425
425
  ...newSchema.properties,
@@ -1,5 +1,145 @@
1
- import type { JSONSchema7Definition } from 'json-schema';
1
+ import type { JSONSchema7, JSONSchema7Definition } from 'json-schema';
2
+ export declare function getDefinitionKey(ref: string): string;
2
3
  /**
3
4
  * Get all the definitions that are referenced by other definitions.
4
5
  */
5
6
  export declare function getReferenceMap(definitions: Record<string, JSONSchema7Definition>): Map<string, Set<string>>;
7
+ /**
8
+ * Prunes the schema definitions to only include those that are referenced either directly
9
+ * or indirectly by the specified root reference.
10
+ *
11
+ * @param {JSONSchema7} schema - The JSON schema object containing the definitions to prune.
12
+ * @param {string} ref - The reference identifier that serves as the root for pruning definitions.
13
+ * @return {JSONSchema7} - A new JSON schema object with pruned definitions.
14
+ */
15
+ export declare function pruneSchemaDefinitions(schema: JSONSchema7, ref: string): {
16
+ definitions: Record<string, JSONSchema7Definition>;
17
+ $id?: string | undefined;
18
+ $ref?: string | undefined;
19
+ $schema?: import("json-schema").JSONSchema7Version | undefined;
20
+ $comment?: string | undefined;
21
+ $defs?: {
22
+ [key: string]: JSONSchema7Definition;
23
+ } | undefined;
24
+ type?: import("json-schema").JSONSchema7TypeName | import("json-schema").JSONSchema7TypeName[] | undefined;
25
+ enum?: import("json-schema").JSONSchema7Type[] | undefined;
26
+ const?: import("json-schema").JSONSchema7Type | undefined;
27
+ multipleOf?: number | undefined;
28
+ maximum?: number | undefined;
29
+ exclusiveMaximum?: number | undefined;
30
+ minimum?: number | undefined;
31
+ exclusiveMinimum?: number | undefined;
32
+ maxLength?: number | undefined;
33
+ minLength?: number | undefined;
34
+ pattern?: string | undefined;
35
+ items?: JSONSchema7Definition | JSONSchema7Definition[] | undefined;
36
+ additionalItems?: JSONSchema7Definition | undefined;
37
+ maxItems?: number | undefined;
38
+ minItems?: number | undefined;
39
+ uniqueItems?: boolean | undefined;
40
+ contains?: JSONSchema7Definition | undefined;
41
+ maxProperties?: number | undefined;
42
+ minProperties?: number | undefined;
43
+ required?: string[] | undefined;
44
+ properties?: {
45
+ [key: string]: JSONSchema7Definition;
46
+ } | undefined;
47
+ patternProperties?: {
48
+ [key: string]: JSONSchema7Definition;
49
+ } | undefined;
50
+ additionalProperties?: JSONSchema7Definition | undefined;
51
+ dependencies?: {
52
+ [key: string]: JSONSchema7Definition | string[];
53
+ } | undefined;
54
+ propertyNames?: JSONSchema7Definition | undefined;
55
+ if?: JSONSchema7Definition | undefined;
56
+ then?: JSONSchema7Definition | undefined;
57
+ else?: JSONSchema7Definition | undefined;
58
+ allOf?: JSONSchema7Definition[] | undefined;
59
+ anyOf?: JSONSchema7Definition[] | undefined;
60
+ oneOf?: JSONSchema7Definition[] | undefined;
61
+ not?: JSONSchema7Definition | undefined;
62
+ format?: string | undefined;
63
+ contentMediaType?: string | undefined;
64
+ contentEncoding?: string | undefined;
65
+ title?: string | undefined;
66
+ description?: string | undefined;
67
+ default?: import("json-schema").JSONSchema7Type | undefined;
68
+ readOnly?: boolean | undefined;
69
+ writeOnly?: boolean | undefined;
70
+ examples?: import("json-schema").JSONSchema7Type | undefined;
71
+ discriminator?: {
72
+ propertyName: string;
73
+ };
74
+ };
75
+ /**
76
+ * Promotes a specific object schema definition within a JSON Schema, potentially simplifying the schema
77
+ * by focusing on the desired object and pruning unused definitions.
78
+ *
79
+ * Note this does not support promoting schemas that are self-referential
80
+ *
81
+ * @param {JSONSchema7} schema - The full JSON Schema to process.
82
+ * @param {string} ref - The reference string identifying the target object schema within the definitions.
83
+ * @return {ObjectSchemaWithProperties} The promoted object schema along with pruned definitions.
84
+ * @throws {Error} If the specified reference does not correspond to a valid object definition within the schema.
85
+ */
86
+ export declare function promoteObjectSchema(schema: JSONSchema7, ref: string): {
87
+ definitions: {
88
+ [x: string]: JSONSchema7Definition;
89
+ };
90
+ minimum?: number | undefined | undefined;
91
+ maximum?: number | undefined | undefined;
92
+ exclusiveMinimum?: number | undefined | undefined;
93
+ exclusiveMaximum?: number | undefined | undefined;
94
+ multipleOf?: number | undefined | undefined;
95
+ format?: string | undefined | undefined;
96
+ allOf?: JSONSchema7Definition[] | undefined | undefined;
97
+ anyOf?: JSONSchema7Definition[] | undefined | undefined;
98
+ oneOf?: JSONSchema7Definition[] | undefined | undefined;
99
+ if?: JSONSchema7Definition | undefined;
100
+ then?: JSONSchema7Definition | undefined;
101
+ else?: JSONSchema7Definition | undefined;
102
+ not?: JSONSchema7Definition | undefined;
103
+ $id?: string | undefined | undefined;
104
+ $ref?: string | undefined | undefined;
105
+ $defs?: {
106
+ [key: string]: JSONSchema7Definition;
107
+ } | undefined | undefined;
108
+ $schema?: string | undefined;
109
+ $comment?: string | undefined | undefined;
110
+ type: "object";
111
+ enum?: import("json-schema").JSONSchema7Type[] | undefined | undefined;
112
+ const?: import("json-schema").JSONSchema7Type | undefined;
113
+ maxLength?: number | undefined | undefined;
114
+ minLength?: number | undefined | undefined;
115
+ pattern?: string | undefined | undefined;
116
+ items?: JSONSchema7Definition | JSONSchema7Definition[] | undefined;
117
+ additionalItems?: JSONSchema7Definition | undefined;
118
+ maxItems?: number | undefined | undefined;
119
+ minItems?: number | undefined | undefined;
120
+ uniqueItems?: boolean | undefined | undefined;
121
+ contains?: JSONSchema7Definition | undefined;
122
+ maxProperties?: number | undefined | undefined;
123
+ minProperties?: number | undefined | undefined;
124
+ required?: string[] | undefined | undefined;
125
+ patternProperties?: {
126
+ [key: string]: JSONSchema7Definition;
127
+ } | undefined | undefined;
128
+ additionalProperties?: JSONSchema7Definition | undefined;
129
+ dependencies?: {
130
+ [key: string]: JSONSchema7Definition | string[];
131
+ } | undefined | undefined;
132
+ propertyNames?: JSONSchema7Definition | undefined;
133
+ contentMediaType?: string | undefined | undefined;
134
+ contentEncoding?: string | undefined | undefined;
135
+ title?: string | undefined | undefined;
136
+ description?: string | undefined | undefined;
137
+ default?: import("json-schema").JSONSchema7Type | undefined;
138
+ readOnly?: boolean | undefined | undefined;
139
+ writeOnly?: boolean | undefined | undefined;
140
+ examples?: import("json-schema").JSONSchema7Type | undefined;
141
+ discriminator?: {
142
+ propertyName: string;
143
+ } | undefined;
144
+ properties: Exclude<JSONSchema7["properties"], undefined>;
145
+ };
@@ -1,47 +1,21 @@
1
- import { isAllOfSchema, isAnyOfSchema, isOneOfSchema, isPropertySchema, isRefSchema, isSchema } from "./type-utils.js";
2
- const SCHEMA_DEFINITION_PREFIX = ['#/definitions/', '#/$defs/'];
3
- function collectRef(def, key, collect) {
4
- if (isRefSchema(def)) {
5
- collect(def.$ref, key);
6
- }
7
- else if (isSchema(def)) {
8
- collectRefs(def, key, collect);
9
- }
10
- }
1
+ import { visit } from '@takeshape/util';
2
+ import { isObjectSchemaWithProperties, isSchema } from "./type-utils.js";
11
3
  function collectRefs(def, key, collect) {
12
- if (isPropertySchema(def)) {
13
- for (const d of Object.values(def.properties)) {
14
- collectRef(d, key, collect);
15
- }
16
- }
17
- else if (isAllOfSchema(def)) {
18
- for (const d of def.allOf) {
19
- collectRef(d, key, collect);
20
- }
21
- }
22
- else if (isAnyOfSchema(def)) {
23
- for (const d of def.anyOf) {
24
- collectRef(d, key, collect);
25
- }
4
+ if (!isSchema(def)) {
5
+ return;
26
6
  }
27
- else if (isOneOfSchema(def)) {
28
- for (const d of def.oneOf) {
29
- collectRef(d, key, collect);
7
+ visit(def, ['$ref'], ($ref) => {
8
+ if ($ref && typeof $ref === 'string') {
9
+ collect($ref, key);
30
10
  }
11
+ });
12
+ }
13
+ export function getDefinitionKey(ref) {
14
+ const [, prefix, name] = ref.split('/');
15
+ if (!name || (prefix !== 'definitions' && prefix !== '$defs')) {
16
+ throw new Error(`Invalid reference: ${ref}`);
31
17
  }
32
- else if (Array.isArray(def.items)) {
33
- for (const d of def.items) {
34
- collectRef(d, key, collect);
35
- }
36
- }
37
- else if (def.items) {
38
- if (isSchema(def.items) && isRefSchema(def.items)) {
39
- collect(def.items.$ref, key);
40
- }
41
- }
42
- else if (isRefSchema(def)) {
43
- collect(def.$ref, key);
44
- }
18
+ return name;
45
19
  }
46
20
  /**
47
21
  * Get all the definitions that are referenced by other definitions.
@@ -50,7 +24,7 @@ export function getReferenceMap(definitions) {
50
24
  const references = new Map();
51
25
  const visited = new Set();
52
26
  const addToReferenceMap = (ref, key) => {
53
- const refKey = ref.replace(SCHEMA_DEFINITION_PREFIX[0], '').replace(SCHEMA_DEFINITION_PREFIX[1], '');
27
+ const refKey = getDefinitionKey(ref);
54
28
  // Circular reference
55
29
  if (key === refKey) {
56
30
  return;
@@ -74,3 +48,66 @@ export function getReferenceMap(definitions) {
74
48
  }
75
49
  return references;
76
50
  }
51
+ /**
52
+ * Prunes the schema definitions to only include those that are referenced either directly
53
+ * or indirectly by the specified root reference.
54
+ *
55
+ * @param {JSONSchema7} schema - The JSON schema object containing the definitions to prune.
56
+ * @param {string} ref - The reference identifier that serves as the root for pruning definitions.
57
+ * @return {JSONSchema7} - A new JSON schema object with pruned definitions.
58
+ */
59
+ export function pruneSchemaDefinitions(schema, ref) {
60
+ if (!schema.definitions) {
61
+ throw new Error('Schema does not have definitions');
62
+ }
63
+ const references = new Set();
64
+ const visited = new Set();
65
+ const addToReferences = (ref) => {
66
+ const definitionKey = getDefinitionKey(ref);
67
+ if (visited.has(definitionKey)) {
68
+ return;
69
+ }
70
+ visited.add(definitionKey);
71
+ references.add(definitionKey);
72
+ const refDef = schema.definitions?.[definitionKey];
73
+ if (refDef && isSchema(refDef)) {
74
+ collectRefs(refDef, definitionKey, addToReferences);
75
+ }
76
+ };
77
+ addToReferences(ref);
78
+ const newDefinitions = {};
79
+ for (const ref of references) {
80
+ const def = schema.definitions?.[ref];
81
+ if (def) {
82
+ newDefinitions[ref] = def;
83
+ }
84
+ }
85
+ return {
86
+ ...schema,
87
+ definitions: newDefinitions
88
+ };
89
+ }
90
+ /**
91
+ * Promotes a specific object schema definition within a JSON Schema, potentially simplifying the schema
92
+ * by focusing on the desired object and pruning unused definitions.
93
+ *
94
+ * Note this does not support promoting schemas that are self-referential
95
+ *
96
+ * @param {JSONSchema7} schema - The full JSON Schema to process.
97
+ * @param {string} ref - The reference string identifying the target object schema within the definitions.
98
+ * @return {ObjectSchemaWithProperties} The promoted object schema along with pruned definitions.
99
+ * @throws {Error} If the specified reference does not correspond to a valid object definition within the schema.
100
+ */
101
+ export function promoteObjectSchema(schema, ref) {
102
+ const key = getDefinitionKey(ref);
103
+ const definition = schema.definitions?.[key];
104
+ if (!definition || !isObjectSchemaWithProperties(definition)) {
105
+ throw new Error(`Could not find object definition for ${ref}`);
106
+ }
107
+ const prunedSchema = pruneSchemaDefinitions(schema, ref);
108
+ const { [key]: _, ...rest } = prunedSchema.definitions;
109
+ return {
110
+ ...definition,
111
+ definitions: rest
112
+ };
113
+ }
@@ -1,5 +1,5 @@
1
1
  import type { JSONSchema7Definition } from 'json-schema';
2
- import type { AllOfSchema, AnyOfSchema, ArraySchema, ConstSchema, EnumSchema, ListSchema, ObjectSchema, OneOfSchema, PrimitiveSchema, PropertySchema, RefSchema, TupleSchema, TypeUnionSchema } from './types.ts';
2
+ import type { AllOfSchema, AnyOfSchema, ArraySchema, ConstSchema, EnumSchema, ListSchema, ObjectSchema, ObjectSchemaWithProperties, OneOfSchema, PrimitiveSchema, RefSchema, TupleSchema, TypeUnionSchema } from './types.ts';
3
3
  export declare function isBooleanProperty(schema: JSONSchema7Definition): schema is boolean;
4
4
  export declare function isSchema(schema: JSONSchema7Definition): schema is Exclude<JSONSchema7Definition, boolean>;
5
5
  export declare function isOneOfSchema(schema: JSONSchema7Definition): schema is OneOfSchema;
@@ -7,7 +7,7 @@ export declare function isAnyOfSchema(schema: JSONSchema7Definition): schema is
7
7
  export declare function isAllOfSchema(schema: JSONSchema7Definition): schema is AllOfSchema;
8
8
  export declare function isUnionSchema(schema: JSONSchema7Definition): schema is OneOfSchema | AnyOfSchema | AllOfSchema;
9
9
  export declare function isObjectSchema(schema: JSONSchema7Definition): schema is ObjectSchema;
10
- export declare function isPropertySchema(schema: JSONSchema7Definition): schema is PropertySchema;
10
+ export declare function isObjectSchemaWithProperties(schema: JSONSchema7Definition): schema is ObjectSchemaWithProperties;
11
11
  export declare function isArraySchema(schema: JSONSchema7Definition): schema is ArraySchema;
12
12
  export declare function isListSchema(schema: JSONSchema7Definition): schema is ListSchema;
13
13
  export declare function isTupleSchema(schema: JSONSchema7Definition): schema is TupleSchema;
@@ -20,7 +20,7 @@ export function isUnionSchema(schema) {
20
20
  export function isObjectSchema(schema) {
21
21
  return isSchema(schema) && schema.type === 'object';
22
22
  }
23
- export function isPropertySchema(schema) {
23
+ export function isObjectSchemaWithProperties(schema) {
24
24
  return isObjectSchema(schema) && typeof schema.properties === 'object';
25
25
  }
26
26
  export function isArraySchema(schema) {
@@ -22,7 +22,7 @@ export type AllOfSchema = Omit<JSONSchema7, 'allOf'> & {
22
22
  export type ObjectSchema = Omit<JSONSchema7, 'type'> & {
23
23
  type: 'object';
24
24
  };
25
- export type PropertySchema = Omit<ObjectSchema, 'properties'> & {
25
+ export type ObjectSchemaWithProperties = Omit<ObjectSchema, 'properties'> & {
26
26
  properties: Exclude<JSONSchema7['properties'], undefined>;
27
27
  };
28
28
  export type ArraySchema = Omit<JSONSchema7, 'type'> & {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takeshape/json-schema",
3
- "version": "11.105.1",
3
+ "version": "11.107.1",
4
4
  "description": "JSON Schema validator",
5
5
  "homepage": "https://www.takeshape.io",
6
6
  "repository": {
@@ -37,13 +37,13 @@
37
37
  "ajv": "8.13.0",
38
38
  "ajv-formats": "3.0.1",
39
39
  "lodash": "4.17.21",
40
- "minimatch": "^3.0.4",
41
- "@takeshape/util": "11.105.1"
40
+ "minimatch": "3.1.2",
41
+ "@takeshape/util": "11.107.1"
42
42
  },
43
43
  "devDependencies": {
44
- "@types/json-schema": "^7.0.7",
44
+ "@types/json-schema": "7.0.15",
45
45
  "@types/lodash": "4.17.20",
46
- "@types/minimatch": "^3.0.3"
46
+ "@types/minimatch": "3.0.5"
47
47
  },
48
48
  "engines": {
49
49
  "node": ">=22"