@xyd-js/uniform 0.0.0-build-8b31648-20250923204702 → 0.0.0-build-ec04de2-20250930214016
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/CHANGELOG.md +2 -2
- package/dist/index.cjs +156 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +154 -1
- package/dist/index.js.map +1 -1
- package/dist/markdown.d.cts +1 -1
- package/dist/markdown.d.ts +1 -1
- package/dist/{types-DiQsFerK.d.cts → types-DcJGRAj1.d.cts} +3 -2
- package/dist/{types-DiQsFerK.d.ts → types-DcJGRAj1.d.ts} +3 -2
- package/index.ts +1 -1
- package/output.json +617 -0
- package/package.json +2 -2
- package/src/__fixtures__/1.basic/input.json +1369 -0
- package/src/__fixtures__/1.basic/output.json +44 -0
- package/src/__fixtures__/2.advanced/input.json +1530 -0
- package/src/__fixtures__/2.advanced/output.json +323 -0
- package/src/__fixtures__/2.advanced.livesession/input.json +7079 -0
- package/src/__fixtures__/2.advanced.livesession/output.json +1448 -0
- package/src/converters.test.ts +74 -0
- package/src/converters.ts +215 -0
- package/src/index.ts +5 -0
- package/src/types.ts +3 -1
|
@@ -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?:
|
|
74
|
+
type?: "return" | DefinitionTypeREST
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
export type DefinitionVariantOpenAPIMeta = Meta<"status" | "contentType" | "definitionDescription" | "required">;
|