@xyd-js/uniform 0.0.0-build-8b31648-20250923204702 → 0.0.0-build-9f87f13-20250930210637

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.
@@ -0,0 +1,74 @@
1
+ import {describe, it, expect} from "vitest";
2
+ import {JSONSchema7} from "json-schema";
3
+ import fs from "fs";
4
+ import path from "path";
5
+
6
+ import {uniformPropertiesToJsonSchema, uniformToInputJsonSchema} from "./converters";
7
+ import {
8
+ DefinitionProperty,
9
+ DEFINED_DEFINITION_PROPERTY_TYPE,
10
+ Reference,
11
+ } from "./types";
12
+
13
+ describe("uniformPropertiesToJsonSchema", () => {
14
+ const tests = [
15
+ {
16
+ input: "./__fixtures__/1.basic/input.json",
17
+ output: "./__fixtures__/1.basic/output.json",
18
+ },
19
+ {
20
+ input: "./__fixtures__/2.advanced/input.json",
21
+ output: "./__fixtures__/2.advanced/output.json",
22
+ },
23
+ {
24
+ input: "./__fixtures__/2.advanced.livesession/input.json",
25
+ output: "./__fixtures__/2.advanced.livesession/output.json",
26
+ },
27
+ ];
28
+
29
+ describe("fixture-based tests", () => {
30
+ tests.forEach((testCase, index) => {
31
+ it(`should convert ${testCase.input} correctly`, () => {
32
+ // Check if input file exists
33
+ const inputPath = path.resolve(__dirname, testCase.input);
34
+ const outputPath = path.resolve(__dirname, testCase.output);
35
+
36
+ if (!fs.existsSync(inputPath)) {
37
+ console.warn(`Input file ${inputPath} does not exist, skipping test`);
38
+ return;
39
+ }
40
+
41
+ if (!fs.existsSync(outputPath)) {
42
+ console.warn(
43
+ `Output file ${outputPath} does not exist, skipping test`
44
+ );
45
+ return;
46
+ }
47
+
48
+ // Read input file
49
+ const inputData = JSON.parse(fs.readFileSync(inputPath, "utf8"));
50
+ const expectedOutput = JSON.parse(fs.readFileSync(outputPath, "utf8"));
51
+ // Convert input data
52
+
53
+ let inputCheck: JSONSchema7[] | JSONSchema7 | null = null;
54
+
55
+ if (Array.isArray(inputData)) {
56
+ inputCheck = []
57
+ for (const def of inputData) {
58
+ const inputJsonSchema = uniformToInputJsonSchema(def);
59
+ if (inputJsonSchema) {
60
+ inputCheck.push(inputJsonSchema);
61
+ }
62
+ }
63
+ } else {
64
+ const inputJsonSchema = uniformToInputJsonSchema(inputData);
65
+ inputCheck = inputJsonSchema
66
+ }
67
+
68
+ // Compare with expected output
69
+ expect(inputCheck).toEqual(expectedOutput);
70
+ // fs.writeFileSync(outputPath, JSON.stringify(inputCheck, null, 2))
71
+ });
72
+ });
73
+ });
74
+ });
@@ -0,0 +1,215 @@
1
+ import {DEFINED_DEFINITION_PROPERTY_TYPE, DefinitionProperty, Reference} from "./types";
2
+ import {JSONSchema7, JSONSchema7TypeName} from "json-schema";
3
+
4
+ export function uniformToInputJsonSchema(reference: Reference): JSONSchema7 | null {
5
+ if (!reference?.definitions?.length) {
6
+ return null;
7
+ }
8
+
9
+ const inputDefinitions: JSONSchema7[] = [];
10
+
11
+ for (const def of reference.definitions) {
12
+ if (def?.type === "return") {
13
+ continue;
14
+ }
15
+
16
+ // Process each definition
17
+ const definitionSchemas: JSONSchema7[] = [];
18
+
19
+ // Add main properties if they exist
20
+ if (def?.properties?.length) {
21
+ const result = uniformPropertiesToJsonSchema(def.properties, def.type);
22
+ if (result) {
23
+ definitionSchemas.push(result as JSONSchema7);
24
+ }
25
+ }
26
+
27
+ // Add variant properties if they exist
28
+ if (def?.variants?.length) {
29
+ const variantSchemas: JSONSchema7[] = [];
30
+
31
+ for (const variant of def.variants) {
32
+ if (variant?.properties?.length) {
33
+ const result = uniformPropertiesToJsonSchema(variant.properties, def.type);
34
+ if (result) {
35
+ variantSchemas.push(result as JSONSchema7);
36
+ }
37
+ }
38
+ }
39
+
40
+ // If there are variants, use oneOf
41
+ if (variantSchemas.length > 0) {
42
+ if (variantSchemas.length === 1) {
43
+ definitionSchemas.push(variantSchemas[0]);
44
+ } else {
45
+ definitionSchemas.push({
46
+ oneOf: variantSchemas
47
+ });
48
+ }
49
+ }
50
+ }
51
+
52
+ // Add this definition's schema(s) to the input definitions
53
+ if (definitionSchemas.length === 1) {
54
+ inputDefinitions.push(definitionSchemas[0]);
55
+ } else if (definitionSchemas.length > 1) {
56
+ inputDefinitions.push({
57
+ allOf: definitionSchemas
58
+ });
59
+ }
60
+ }
61
+
62
+ // Return the final schema
63
+ if (inputDefinitions.length === 0) {
64
+ return null;
65
+ } else if (inputDefinitions.length === 1) {
66
+ return inputDefinitions[0];
67
+ } else {
68
+ // Multiple definitions use allOf
69
+ return {
70
+ allOf: inputDefinitions
71
+ };
72
+ }
73
+ }
74
+
75
+ export function uniformPropertiesToJsonSchema(
76
+ properties: DefinitionProperty[] | DefinitionProperty,
77
+ id?: string
78
+ ): JSONSchema7 | null {
79
+ if (Array.isArray(properties)) {
80
+ let jsonSchemaProps: { [key: string]: JSONSchema7 } = {};
81
+ let requiredFields: string[] = [];
82
+
83
+ if (properties.length) {
84
+ for (const property of properties) {
85
+ const v = uniformPropertiesToJsonSchema(property);
86
+ if (v) {
87
+ jsonSchemaProps[property.name] = v;
88
+ }
89
+
90
+ // Check if property is required
91
+ const isRequired = property.meta?.some(
92
+ (meta) => meta.name === "required" && meta.value === "true"
93
+ );
94
+ if (isRequired) {
95
+ requiredFields.push(property.name);
96
+ }
97
+ }
98
+ }
99
+
100
+ const schema: JSONSchema7 = {
101
+ $id: id || undefined,
102
+ type: "object",
103
+ properties: jsonSchemaProps,
104
+ };
105
+
106
+ // Only add required array if there are required fields
107
+ if (requiredFields.length > 0) {
108
+ schema.required = requiredFields;
109
+ }
110
+
111
+ return schema;
112
+ }
113
+
114
+ // Handle enum types
115
+ if (properties.type === DEFINED_DEFINITION_PROPERTY_TYPE.ENUM) {
116
+ const schema: JSONSchema7 = {
117
+ description: properties.description as string,
118
+ };
119
+
120
+ // Get the base type from ofProperty or meta
121
+ const enumType: string =
122
+ (properties.ofProperty && (properties.ofProperty as any).type) ||
123
+ (properties.meta?.find((meta) => meta.name === "enum-type")
124
+ ?.value as string) ||
125
+ "string";
126
+
127
+ schema.type = enumType as JSONSchema7TypeName;
128
+
129
+ // Extract enum values from properties array
130
+ if (properties.properties && properties.properties.length > 0) {
131
+ schema.enum = properties.properties.map((prop) => prop.name);
132
+ }
133
+
134
+ return schema;
135
+ }
136
+
137
+ // Handle array types
138
+ if (properties.type === DEFINED_DEFINITION_PROPERTY_TYPE.ARRAY) {
139
+ const schema: JSONSchema7 = {
140
+ type: "array",
141
+ description: properties.description as string,
142
+ };
143
+
144
+ // Set items schema from ofProperty
145
+ if (properties.ofProperty) {
146
+ const itemsSchema = uniformPropertiesToJsonSchema(properties.ofProperty);
147
+ if (itemsSchema) {
148
+ schema.items = itemsSchema;
149
+ }
150
+ }
151
+
152
+ return schema;
153
+ }
154
+
155
+ // Handle XOR (oneOf) types
156
+ if (properties.type === DEFINED_DEFINITION_PROPERTY_TYPE.XOR) {
157
+ const schema: JSONSchema7 = {
158
+ description: properties.description as string,
159
+ };
160
+
161
+ // Convert properties array to oneOf schemas
162
+ if (properties.properties && properties.properties.length > 0) {
163
+ schema.oneOf = properties.properties
164
+ .map((prop) => {
165
+ const propSchema = uniformPropertiesToJsonSchema(prop);
166
+ return propSchema || {};
167
+ })
168
+ .filter((schema) => Object.keys(schema).length > 0);
169
+ }
170
+
171
+ return schema;
172
+ }
173
+
174
+ // Handle UNION (anyOf) types
175
+ if (properties.type === DEFINED_DEFINITION_PROPERTY_TYPE.UNION) {
176
+ const schema: JSONSchema7 = {
177
+ description: properties.description as string,
178
+ };
179
+
180
+ // Convert properties array to anyOf schemas
181
+ if (properties.properties && properties.properties.length > 0) {
182
+ schema.anyOf = properties.properties
183
+ .map((prop) => {
184
+ const propSchema = uniformPropertiesToJsonSchema(prop);
185
+ return propSchema || {};
186
+ })
187
+ .filter((schema) => Object.keys(schema).length > 0);
188
+ }
189
+
190
+ return schema;
191
+ }
192
+
193
+ if (properties.ofProperty) {
194
+ return uniformPropertiesToJsonSchema(properties.ofProperty);
195
+ }
196
+
197
+ // Build the schema for single property
198
+ const schema: JSONSchema7 = {
199
+ type: properties.type as JSONSchema7TypeName,
200
+ description: properties.description as string,
201
+ };
202
+
203
+ // Handle object types with nested properties
204
+ if (properties.type === "object" && properties.properties && properties.properties.length > 0) {
205
+ const nestedSchema = uniformPropertiesToJsonSchema(properties.properties);
206
+ if (nestedSchema && nestedSchema.properties) {
207
+ schema.properties = nestedSchema.properties;
208
+ if (nestedSchema.required) {
209
+ schema.required = nestedSchema.required;
210
+ }
211
+ }
212
+ }
213
+
214
+ return schema;
215
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  // Define the new PluginV type with a callback function that returns another function
2
2
  import {Reference} from "./types";
3
3
 
4
+ export {
5
+ uniformToInputJsonSchema,
6
+ uniformPropertiesToJsonSchema
7
+ } from "./converters";
8
+
4
9
  export * from "./types";
5
10
 
6
11
  // Define the new PluginV type with a callback function that returns another function
package/src/types.ts CHANGED
@@ -40,6 +40,8 @@ export type SymbolDef = {
40
40
  canonical?: string | string[];
41
41
  }
42
42
 
43
+ export type DefinitionTypeREST = "$rest.param.path" | "$rest.param.query" | "$rest.param.header" | "$rest.param.cookie" | "$rest.request.body"
44
+
43
45
  export interface Definition<
44
46
  M extends DefinitionMeta = DefinitionMeta,
45
47
  VM extends DefinitionVariantMeta = DefinitionVariantMeta
@@ -69,7 +71,7 @@ export interface Definition<
69
71
  /**
70
72
  * @internal
71
73
  */
72
- type?: string;
74
+ type?: "return" | DefinitionTypeREST
73
75
  }
74
76
 
75
77
  export type DefinitionVariantOpenAPIMeta = Meta<"status" | "contentType" | "definitionDescription" | "required">;