genoc 0.2.0 → 0.4.0
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 +30 -163
- package/dist/analyzer/analyze.d.ts +18 -0
- package/dist/analyzer/analyze.js +534 -0
- package/dist/analyzer/naming.js +3 -2
- package/dist/analyzer/path-analyzer.d.ts +45 -6
- package/dist/analyzer/path-analyzer.js +82 -81
- package/dist/analyzer/schema-mapper.d.ts +3 -2
- package/dist/analyzer/schema-mapper.js +16 -8
- package/dist/analyzer/types.d.ts +119 -0
- package/dist/cli/app.d.ts +5 -2
- package/dist/cli/app.js +30 -4
- package/dist/cli/config-loader.d.ts +20 -0
- package/dist/cli/config-loader.js +186 -0
- package/dist/cli/config-schema.d.ts +105 -0
- package/dist/cli/config-schema.js +183 -0
- package/dist/cli/impl.d.ts +9 -1
- package/dist/cli/impl.js +190 -31
- package/dist/generator/client-generator.d.ts +13 -14
- package/dist/generator/client-generator.js +45 -77
- package/dist/generator/contracts-generator.d.ts +11 -9
- package/dist/generator/contracts-generator.js +45 -482
- package/dist/generator/method-generator.d.ts +1 -1
- package/dist/generator/method-generator.js +10 -150
- package/dist/parser/ref-resolver.d.ts +1 -1
- package/dist/parser/ref-resolver.js +1 -2
- package/dist/parser/spec-reader.d.ts +3 -2
- package/dist/parser/spec-reader.js +5 -4
- package/dist/parser/version/index.d.ts +4 -16
- package/dist/parser/version/index.js +3 -14
- package/dist/parser/version/v3.0/validator.d.ts +1 -1
- package/dist/parser/version/v3.1/validator.d.ts +17 -0
- package/dist/parser/version/v3.1/validator.js +126 -0
- package/dist/parser/version/validate.d.ts +9 -0
- package/dist/parser/version/validate.js +12 -0
- package/dist/parser/version/version-detector.d.ts +21 -0
- package/dist/parser/version/version-detector.js +19 -0
- package/dist/pipeline.d.ts +13 -0
- package/dist/pipeline.js +24 -0
- package/dist/types/client.d.ts +1 -12
- package/dist/utils/generator-helpers.d.ts +23 -25
- package/dist/utils/generator-helpers.js +144 -76
- package/dist/utils/operation-naming.d.ts +84 -0
- package/dist/utils/operation-naming.js +178 -0
- package/dist/utils/proxy.d.ts +6 -0
- package/dist/utils/proxy.js +81 -0
- package/package.json +5 -8
- package/dist/generator/error-types.d.ts +0 -13
- package/dist/generator/error-types.js +0 -67
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -8
- package/dist/parser/validators.d.ts +0 -7
- package/dist/parser/validators.js +0 -79
- package/dist/parser/version/normalized-spec.d.ts +0 -199
- package/dist/parser/version/registry.d.ts +0 -28
- package/dist/parser/version/registry.js +0 -44
- package/dist/parser/version/v3.0/index.d.ts +0 -3
- package/dist/parser/version/v3.0/index.js +0 -3
- package/dist/parser/version/v3.0/normalizer.d.ts +0 -15
- package/dist/parser/version/v3.0/normalizer.js +0 -389
- package/dist/parser/version/v3.0/strategy.d.ts +0 -27
- package/dist/parser/version/v3.0/strategy.js +0 -96
- package/dist/parser/version/v3.1/index.d.ts +0 -1
- package/dist/parser/version/v3.1/index.js +0 -1
- package/dist/parser/version/v3.1/strategy.d.ts +0 -42
- package/dist/parser/version/v3.1/strategy.js +0 -513
- package/dist/parser/version/v3.2/index.d.ts +0 -4
- package/dist/parser/version/v3.2/index.js +0 -4
- package/dist/parser/version/v3.2/strategy.d.ts +0 -39
- package/dist/parser/version/v3.2/strategy.js +0 -57
- package/dist/parser/version/version-strategy.d.ts +0 -31
- package/dist/parser/version/version-strategy.js +0 -1
- /package/dist/{parser/version/normalized-spec.js → analyzer/types.js} +0 -0
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Normalize a raw OpenAPI 3.0.x specification to a consistent format.
|
|
3
|
-
*
|
|
4
|
-
* 3.0-specific transformations applied during normalization:
|
|
5
|
-
* - `nullable: true` → `nullable: true` on the NormalizedSchema
|
|
6
|
-
* - `exclusiveMinimum: true` + `minimum: 5` → `exclusiveMinimum: 5`
|
|
7
|
-
* - `exclusiveMinimum: false` → removed (not included in output)
|
|
8
|
-
* - `example: value` → `examples: [value]`
|
|
9
|
-
* - `format: "binary"` → `fileUpload: { binary: true, base64: false }`
|
|
10
|
-
* - `format: "byte"` → `fileUpload: { binary: false, base64: true }`
|
|
11
|
-
* - `$ref` siblings are stripped (3.0 compliant behavior)
|
|
12
|
-
* - Error if `items` is an array (3.1-only tuple syntax)
|
|
13
|
-
*/
|
|
14
|
-
export function normalizeSpec30(rawSpec) {
|
|
15
|
-
if (!rawSpec || typeof rawSpec !== 'object' || Array.isArray(rawSpec)) {
|
|
16
|
-
throw new Error('Invalid spec: must be a non-null object');
|
|
17
|
-
}
|
|
18
|
-
const raw = rawSpec;
|
|
19
|
-
const rawInfo = raw.info;
|
|
20
|
-
if (!rawInfo || typeof rawInfo !== 'object' || Array.isArray(rawInfo)) {
|
|
21
|
-
throw new Error("Invalid spec: missing or invalid 'info' field");
|
|
22
|
-
}
|
|
23
|
-
const ri = rawInfo;
|
|
24
|
-
const info = {
|
|
25
|
-
title: typeof ri.title === 'string' ? ri.title : '',
|
|
26
|
-
version: typeof ri.version === 'string' ? ri.version : '',
|
|
27
|
-
description: typeof ri.description === 'string' ? ri.description : undefined,
|
|
28
|
-
termsOfService: typeof ri.termsOfService === 'string' ? ri.termsOfService : undefined,
|
|
29
|
-
contact: ri.contact && typeof ri.contact === 'object' && !Array.isArray(ri.contact)
|
|
30
|
-
? ri.contact
|
|
31
|
-
: undefined,
|
|
32
|
-
license: ri.license && typeof ri.license === 'object' && !Array.isArray(ri.license)
|
|
33
|
-
? ri.license
|
|
34
|
-
: undefined,
|
|
35
|
-
};
|
|
36
|
-
const servers = Array.isArray(raw.servers)
|
|
37
|
-
? raw.servers
|
|
38
|
-
: undefined;
|
|
39
|
-
let paths;
|
|
40
|
-
if (raw.paths && typeof raw.paths === 'object' && !Array.isArray(raw.paths)) {
|
|
41
|
-
paths = {};
|
|
42
|
-
for (const [pathKey, pathItem] of Object.entries(raw.paths)) {
|
|
43
|
-
if (pathItem && typeof pathItem === 'object' && !Array.isArray(pathItem)) {
|
|
44
|
-
paths[pathKey] = normalizePathItem(pathItem);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
let components;
|
|
49
|
-
if (raw.components && typeof raw.components === 'object' && !Array.isArray(raw.components)) {
|
|
50
|
-
const rc = raw.components;
|
|
51
|
-
components = {};
|
|
52
|
-
if (rc.schemas && typeof rc.schemas === 'object' && !Array.isArray(rc.schemas)) {
|
|
53
|
-
components.schemas = {};
|
|
54
|
-
for (const [name, schema] of Object.entries(rc.schemas)) {
|
|
55
|
-
components.schemas[name] = normalizeSchema(schema);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
if (rc.responses && typeof rc.responses === 'object')
|
|
59
|
-
components.responses = rc.responses;
|
|
60
|
-
if (rc.parameters && typeof rc.parameters === 'object')
|
|
61
|
-
components.parameters = rc.parameters;
|
|
62
|
-
if (rc.requestBodies && typeof rc.requestBodies === 'object')
|
|
63
|
-
components.requestBodies = rc.requestBodies;
|
|
64
|
-
if (rc.headers && typeof rc.headers === 'object')
|
|
65
|
-
components.headers = rc.headers;
|
|
66
|
-
if (rc.securitySchemes && typeof rc.securitySchemes === 'object')
|
|
67
|
-
components.securitySchemes = rc.securitySchemes;
|
|
68
|
-
if (rc.links && typeof rc.links === 'object')
|
|
69
|
-
components.links = rc.links;
|
|
70
|
-
if (rc.callbacks && typeof rc.callbacks === 'object')
|
|
71
|
-
components.callbacks = rc.callbacks;
|
|
72
|
-
if (rc.examples && typeof rc.examples === 'object')
|
|
73
|
-
components.examples = rc.examples;
|
|
74
|
-
}
|
|
75
|
-
let webhooks;
|
|
76
|
-
if (raw.webhooks && typeof raw.webhooks === 'object' && !Array.isArray(raw.webhooks)) {
|
|
77
|
-
webhooks = {};
|
|
78
|
-
for (const [name, pathItem] of Object.entries(raw.webhooks)) {
|
|
79
|
-
if (pathItem && typeof pathItem === 'object' && !Array.isArray(pathItem)) {
|
|
80
|
-
webhooks[name] = normalizePathItem(pathItem);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
openapi: typeof raw.openapi === 'string' ? raw.openapi : '3.0.0',
|
|
86
|
-
info,
|
|
87
|
-
servers,
|
|
88
|
-
paths,
|
|
89
|
-
components,
|
|
90
|
-
security: Array.isArray(raw.security) ? raw.security : undefined,
|
|
91
|
-
tags: Array.isArray(raw.tags) ? raw.tags : undefined,
|
|
92
|
-
externalDocs: raw.externalDocs && typeof raw.externalDocs === 'object' && !Array.isArray(raw.externalDocs)
|
|
93
|
-
? raw.externalDocs
|
|
94
|
-
: undefined,
|
|
95
|
-
webhooks,
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Normalize a schema object with 3.0-specific transformations.
|
|
100
|
-
*
|
|
101
|
-
* Key differences from 3.1 normalization:
|
|
102
|
-
* - `nullable` keyword is the primary null indicator (not type arrays with "null")
|
|
103
|
-
* - `exclusiveMinimum`/`exclusiveMaximum` are boolean modifiers of `minimum`/`maximum`
|
|
104
|
-
* - `$ref` siblings are stripped (3.0 compliant behavior)
|
|
105
|
-
* - `items` as array is an error (3.1-only tuple syntax)
|
|
106
|
-
*/
|
|
107
|
-
function normalizeSchema(schema) {
|
|
108
|
-
if (!schema || typeof schema !== 'object' || Array.isArray(schema)) {
|
|
109
|
-
return { types: [], nullable: false, examples: [] };
|
|
110
|
-
}
|
|
111
|
-
const s = schema;
|
|
112
|
-
if (typeof s.$ref === 'string') {
|
|
113
|
-
return {
|
|
114
|
-
$ref: s.$ref,
|
|
115
|
-
types: [],
|
|
116
|
-
nullable: false,
|
|
117
|
-
examples: [],
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
let types = [];
|
|
121
|
-
let nullable = false;
|
|
122
|
-
if (typeof s.type === 'string') {
|
|
123
|
-
types = [s.type];
|
|
124
|
-
}
|
|
125
|
-
else if (Array.isArray(s.type)) {
|
|
126
|
-
const typeArr = s.type;
|
|
127
|
-
if (typeArr.includes('null')) {
|
|
128
|
-
nullable = true;
|
|
129
|
-
types = typeArr.filter((t) => t !== 'null');
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
types = [...typeArr];
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
if (s.nullable === true) {
|
|
136
|
-
nullable = true;
|
|
137
|
-
}
|
|
138
|
-
let examples = [];
|
|
139
|
-
if (Array.isArray(s.examples)) {
|
|
140
|
-
examples = [...s.examples];
|
|
141
|
-
}
|
|
142
|
-
else if (s.example !== undefined) {
|
|
143
|
-
examples = [s.example];
|
|
144
|
-
}
|
|
145
|
-
let exclusiveMinimum;
|
|
146
|
-
if (s.exclusiveMinimum === true && typeof s.minimum === 'number') {
|
|
147
|
-
exclusiveMinimum = s.minimum;
|
|
148
|
-
}
|
|
149
|
-
else if (typeof s.exclusiveMinimum === 'number') {
|
|
150
|
-
exclusiveMinimum = s.exclusiveMinimum;
|
|
151
|
-
}
|
|
152
|
-
let exclusiveMaximum;
|
|
153
|
-
if (s.exclusiveMaximum === true && typeof s.maximum === 'number') {
|
|
154
|
-
exclusiveMaximum = s.maximum;
|
|
155
|
-
}
|
|
156
|
-
else if (typeof s.exclusiveMaximum === 'number') {
|
|
157
|
-
exclusiveMaximum = s.exclusiveMaximum;
|
|
158
|
-
}
|
|
159
|
-
let fileUpload;
|
|
160
|
-
if (typeof s.format === 'string') {
|
|
161
|
-
if (s.format === 'binary') {
|
|
162
|
-
fileUpload = { binary: true, base64: false };
|
|
163
|
-
}
|
|
164
|
-
else if (s.format === 'byte') {
|
|
165
|
-
fileUpload = { binary: false, base64: true };
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
const properties = normalizePropertyMap(s.properties);
|
|
169
|
-
let items;
|
|
170
|
-
if (s.items !== undefined) {
|
|
171
|
-
if (Array.isArray(s.items)) {
|
|
172
|
-
throw new Error("Schema 'items' as an array is not supported in OpenAPI 3.0 (tuple syntax is 3.1-only). Use prefixItems in 3.1.");
|
|
173
|
-
}
|
|
174
|
-
items = normalizeSchema(s.items);
|
|
175
|
-
}
|
|
176
|
-
const allOf = Array.isArray(s.allOf)
|
|
177
|
-
? s.allOf.map((item) => normalizeSchema(item))
|
|
178
|
-
: undefined;
|
|
179
|
-
const oneOf = Array.isArray(s.oneOf)
|
|
180
|
-
? s.oneOf.map((item) => normalizeSchema(item))
|
|
181
|
-
: undefined;
|
|
182
|
-
const anyOf = Array.isArray(s.anyOf)
|
|
183
|
-
? s.anyOf.map((item) => normalizeSchema(item))
|
|
184
|
-
: undefined;
|
|
185
|
-
let additionalProperties;
|
|
186
|
-
if (s.additionalProperties === true) {
|
|
187
|
-
additionalProperties = true;
|
|
188
|
-
}
|
|
189
|
-
else if (s.additionalProperties === false) {
|
|
190
|
-
additionalProperties = false;
|
|
191
|
-
}
|
|
192
|
-
else if (s.additionalProperties &&
|
|
193
|
-
typeof s.additionalProperties === 'object' &&
|
|
194
|
-
!Array.isArray(s.additionalProperties)) {
|
|
195
|
-
additionalProperties = normalizeSchema(s.additionalProperties);
|
|
196
|
-
}
|
|
197
|
-
return {
|
|
198
|
-
types,
|
|
199
|
-
nullable,
|
|
200
|
-
format: typeof s.format === 'string' ? s.format : undefined,
|
|
201
|
-
properties,
|
|
202
|
-
required: Array.isArray(s.required) ? s.required : undefined,
|
|
203
|
-
items,
|
|
204
|
-
additionalProperties,
|
|
205
|
-
allOf,
|
|
206
|
-
oneOf,
|
|
207
|
-
anyOf,
|
|
208
|
-
enum: Array.isArray(s.enum) ? [...s.enum] : undefined,
|
|
209
|
-
const: 'const' in s ? s.const : undefined,
|
|
210
|
-
default: 'default' in s ? s.default : undefined,
|
|
211
|
-
description: typeof s.description === 'string' ? s.description : undefined,
|
|
212
|
-
examples,
|
|
213
|
-
fileUpload,
|
|
214
|
-
exclusiveMinimum,
|
|
215
|
-
exclusiveMaximum,
|
|
216
|
-
minimum: typeof s.minimum === 'number' ? s.minimum : undefined,
|
|
217
|
-
maximum: typeof s.maximum === 'number' ? s.maximum : undefined,
|
|
218
|
-
readOnly: s.readOnly === true ? true : undefined,
|
|
219
|
-
writeOnly: s.writeOnly === true ? true : undefined,
|
|
220
|
-
deprecated: s.deprecated === true ? true : undefined,
|
|
221
|
-
discriminator: s.discriminator && typeof s.discriminator === 'object' && !Array.isArray(s.discriminator)
|
|
222
|
-
? s.discriminator
|
|
223
|
-
: undefined,
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
function normalizePropertyMap(raw) {
|
|
227
|
-
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
228
|
-
return undefined;
|
|
229
|
-
}
|
|
230
|
-
const entries = Object.entries(raw);
|
|
231
|
-
if (entries.length === 0)
|
|
232
|
-
return undefined;
|
|
233
|
-
const result = {};
|
|
234
|
-
for (const [key, val] of entries) {
|
|
235
|
-
result[key] = normalizeSchema(val);
|
|
236
|
-
}
|
|
237
|
-
return result;
|
|
238
|
-
}
|
|
239
|
-
function normalizePathItem(raw) {
|
|
240
|
-
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
241
|
-
return {};
|
|
242
|
-
}
|
|
243
|
-
const pi = raw;
|
|
244
|
-
const httpMethods = [
|
|
245
|
-
'get',
|
|
246
|
-
'put',
|
|
247
|
-
'post',
|
|
248
|
-
'delete',
|
|
249
|
-
'options',
|
|
250
|
-
'head',
|
|
251
|
-
'patch',
|
|
252
|
-
'trace',
|
|
253
|
-
];
|
|
254
|
-
const result = {};
|
|
255
|
-
if (typeof pi.$ref === 'string')
|
|
256
|
-
result.$ref = pi.$ref;
|
|
257
|
-
if (typeof pi.summary === 'string')
|
|
258
|
-
result.summary = pi.summary;
|
|
259
|
-
if (typeof pi.description === 'string')
|
|
260
|
-
result.description = pi.description;
|
|
261
|
-
if (Array.isArray(pi.servers))
|
|
262
|
-
result.servers = pi.servers;
|
|
263
|
-
if (Array.isArray(pi.parameters)) {
|
|
264
|
-
result.parameters = pi.parameters.map((p) => normalizeParameter(p));
|
|
265
|
-
}
|
|
266
|
-
for (const method of httpMethods) {
|
|
267
|
-
const op = pi[method];
|
|
268
|
-
if (op && typeof op === 'object' && !Array.isArray(op)) {
|
|
269
|
-
result[method] = normalizeOperation(op);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return result;
|
|
273
|
-
}
|
|
274
|
-
function normalizeOperation(raw) {
|
|
275
|
-
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
276
|
-
return { responses: {} };
|
|
277
|
-
}
|
|
278
|
-
const o = raw;
|
|
279
|
-
const result = {
|
|
280
|
-
responses: {},
|
|
281
|
-
};
|
|
282
|
-
if (Array.isArray(o.tags))
|
|
283
|
-
result.tags = o.tags;
|
|
284
|
-
if (typeof o.summary === 'string')
|
|
285
|
-
result.summary = o.summary;
|
|
286
|
-
if (typeof o.description === 'string')
|
|
287
|
-
result.description = o.description;
|
|
288
|
-
if (typeof o.operationId === 'string')
|
|
289
|
-
result.operationId = o.operationId;
|
|
290
|
-
if (o.deprecated === true)
|
|
291
|
-
result.deprecated = true;
|
|
292
|
-
if (Array.isArray(o.security))
|
|
293
|
-
result.security = o.security;
|
|
294
|
-
if (Array.isArray(o.servers))
|
|
295
|
-
result.servers = o.servers;
|
|
296
|
-
if (Array.isArray(o.parameters)) {
|
|
297
|
-
result.parameters = o.parameters.map((p) => normalizeParameter(p));
|
|
298
|
-
}
|
|
299
|
-
if (o.requestBody && typeof o.requestBody === 'object' && !Array.isArray(o.requestBody)) {
|
|
300
|
-
const rb = o.requestBody;
|
|
301
|
-
result.requestBody = {
|
|
302
|
-
content: normalizeContentMap(rb.content),
|
|
303
|
-
};
|
|
304
|
-
if (typeof rb.description === 'string')
|
|
305
|
-
result.requestBody.description = rb.description;
|
|
306
|
-
if (rb.required === true)
|
|
307
|
-
result.requestBody.required = true;
|
|
308
|
-
}
|
|
309
|
-
if (o.responses && typeof o.responses === 'object' && !Array.isArray(o.responses)) {
|
|
310
|
-
const responses = {};
|
|
311
|
-
for (const [code, resp] of Object.entries(o.responses)) {
|
|
312
|
-
if (resp && typeof resp === 'object' && !Array.isArray(resp)) {
|
|
313
|
-
const r = resp;
|
|
314
|
-
responses[code] = {
|
|
315
|
-
description: typeof r.description === 'string' ? r.description : '',
|
|
316
|
-
};
|
|
317
|
-
if (r.headers && typeof r.headers === 'object')
|
|
318
|
-
responses[code].headers = r.headers;
|
|
319
|
-
if (r.content && typeof r.content === 'object')
|
|
320
|
-
responses[code].content = normalizeContentMap(r.content);
|
|
321
|
-
if (r.links && typeof r.links === 'object')
|
|
322
|
-
responses[code].links = r.links;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
result.responses = responses;
|
|
326
|
-
}
|
|
327
|
-
return result;
|
|
328
|
-
}
|
|
329
|
-
function normalizeContentMap(raw) {
|
|
330
|
-
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
331
|
-
return {};
|
|
332
|
-
}
|
|
333
|
-
const result = {};
|
|
334
|
-
for (const [mediaType, mediaObj] of Object.entries(raw)) {
|
|
335
|
-
if (mediaObj && typeof mediaObj === 'object' && !Array.isArray(mediaObj)) {
|
|
336
|
-
const m = mediaObj;
|
|
337
|
-
const entry = {};
|
|
338
|
-
if (m.schema) {
|
|
339
|
-
entry.schema = normalizeSchema(m.schema);
|
|
340
|
-
}
|
|
341
|
-
if (m.examples && typeof m.examples === 'object')
|
|
342
|
-
entry.examples = m.examples;
|
|
343
|
-
if ('example' in m)
|
|
344
|
-
entry.example = m.example;
|
|
345
|
-
if (m.encoding && typeof m.encoding === 'object')
|
|
346
|
-
entry.encoding = m.encoding;
|
|
347
|
-
result[mediaType] = entry;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
return result;
|
|
351
|
-
}
|
|
352
|
-
function normalizeParameter(raw) {
|
|
353
|
-
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
354
|
-
return { name: '', in: 'query' };
|
|
355
|
-
}
|
|
356
|
-
const p = raw;
|
|
357
|
-
if (typeof p.$ref === 'string') {
|
|
358
|
-
return {
|
|
359
|
-
name: '',
|
|
360
|
-
in: 'query',
|
|
361
|
-
$ref: p.$ref,
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
const result = {
|
|
365
|
-
name: typeof p.name === 'string' ? p.name : '',
|
|
366
|
-
in: ['query', 'path', 'header', 'cookie'].includes(p.in)
|
|
367
|
-
? p.in
|
|
368
|
-
: 'query',
|
|
369
|
-
};
|
|
370
|
-
if (typeof p.description === 'string')
|
|
371
|
-
result.description = p.description;
|
|
372
|
-
if (p.required === true)
|
|
373
|
-
result.required = true;
|
|
374
|
-
if (p.deprecated === true)
|
|
375
|
-
result.deprecated = true;
|
|
376
|
-
if (p.schema)
|
|
377
|
-
result.schema = normalizeSchema(p.schema);
|
|
378
|
-
if (typeof p.style === 'string')
|
|
379
|
-
result.style = p.style;
|
|
380
|
-
if (p.explode !== undefined)
|
|
381
|
-
result.explode = p.explode;
|
|
382
|
-
if (p.allowEmptyValue === true)
|
|
383
|
-
result.allowEmptyValue = true;
|
|
384
|
-
if ('example' in p)
|
|
385
|
-
result.example = p.example;
|
|
386
|
-
if (p.examples && typeof p.examples === 'object')
|
|
387
|
-
result.examples = p.examples;
|
|
388
|
-
return result;
|
|
389
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { ValidationResult } from '../../validators.js';
|
|
2
|
-
import type { NormalizedSpec } from '../normalized-spec.js';
|
|
3
|
-
import type { VersionStrategy } from '../version-strategy.js';
|
|
4
|
-
/**
|
|
5
|
-
* Version strategy for OpenAPI 3.0.x specifications.
|
|
6
|
-
*
|
|
7
|
-
* OpenAPI 3.0 is the original version of the OpenAPI specification and differs
|
|
8
|
-
* from 3.1 in several key ways:
|
|
9
|
-
* - `nullable` keyword (not type arrays with "null")
|
|
10
|
-
* - `exclusiveMinimum`/`exclusiveMaximum` as booleans modifying `minimum`/`maximum`
|
|
11
|
-
* - `$ref` siblings are ignored (not merged)
|
|
12
|
-
* - `example` keyword (not `examples`)
|
|
13
|
-
* - `paths` is required
|
|
14
|
-
*/
|
|
15
|
-
export declare class V3_0_VersionStrategy implements VersionStrategy {
|
|
16
|
-
version(): string;
|
|
17
|
-
matches(spec: unknown): boolean;
|
|
18
|
-
normalizeSpec(rawSpec: unknown): NormalizedSpec;
|
|
19
|
-
validateSpec(spec: NormalizedSpec): ValidationResult;
|
|
20
|
-
/**
|
|
21
|
-
* Resolve a $ref within the document. For OpenAPI 3.0, sibling properties
|
|
22
|
-
* alongside `$ref` are ignored — only the $ref target is returned.
|
|
23
|
-
*/
|
|
24
|
-
resolveRef(ref: string, doc: unknown, _context?: unknown): unknown;
|
|
25
|
-
getSupportedFeatures(): string[];
|
|
26
|
-
private resolveRefInternal;
|
|
27
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { parseJsonPointer } from '../../../utils/url.js';
|
|
2
|
-
import { normalizeSpec30 } from './normalizer.js';
|
|
3
|
-
import { validateSpec30 } from './validator.js';
|
|
4
|
-
const MAX_REF_DEPTH = 10;
|
|
5
|
-
/**
|
|
6
|
-
* Version strategy for OpenAPI 3.0.x specifications.
|
|
7
|
-
*
|
|
8
|
-
* OpenAPI 3.0 is the original version of the OpenAPI specification and differs
|
|
9
|
-
* from 3.1 in several key ways:
|
|
10
|
-
* - `nullable` keyword (not type arrays with "null")
|
|
11
|
-
* - `exclusiveMinimum`/`exclusiveMaximum` as booleans modifying `minimum`/`maximum`
|
|
12
|
-
* - `$ref` siblings are ignored (not merged)
|
|
13
|
-
* - `example` keyword (not `examples`)
|
|
14
|
-
* - `paths` is required
|
|
15
|
-
*/
|
|
16
|
-
export class V3_0_VersionStrategy {
|
|
17
|
-
version() {
|
|
18
|
-
return '3.0';
|
|
19
|
-
}
|
|
20
|
-
matches(spec) {
|
|
21
|
-
if (!spec || typeof spec !== 'object' || Array.isArray(spec)) {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
const specObj = spec;
|
|
25
|
-
const openapiVersion = specObj.openapi;
|
|
26
|
-
if (typeof openapiVersion === 'string') {
|
|
27
|
-
return openapiVersion.startsWith('3.0');
|
|
28
|
-
}
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
normalizeSpec(rawSpec) {
|
|
32
|
-
return normalizeSpec30(rawSpec);
|
|
33
|
-
}
|
|
34
|
-
validateSpec(spec) {
|
|
35
|
-
return validateSpec30(spec);
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Resolve a $ref within the document. For OpenAPI 3.0, sibling properties
|
|
39
|
-
* alongside `$ref` are ignored — only the $ref target is returned.
|
|
40
|
-
*/
|
|
41
|
-
resolveRef(ref, doc, _context) {
|
|
42
|
-
const resolving = new Set();
|
|
43
|
-
return this.resolveRefInternal(ref, doc, resolving, 0);
|
|
44
|
-
}
|
|
45
|
-
getSupportedFeatures() {
|
|
46
|
-
return ['nullable', 'example'];
|
|
47
|
-
}
|
|
48
|
-
resolveRefInternal(ref, doc, resolving, depth) {
|
|
49
|
-
if (ref.startsWith('http://') || ref.startsWith('https://')) {
|
|
50
|
-
throw new Error(`External $ref resolution is not supported: ${ref}`);
|
|
51
|
-
}
|
|
52
|
-
if (!ref.startsWith('#')) {
|
|
53
|
-
throw new Error(`External $ref resolution is not supported: ${ref}`);
|
|
54
|
-
}
|
|
55
|
-
if (depth >= MAX_REF_DEPTH) {
|
|
56
|
-
throw new Error(`Maximum $ref depth (${MAX_REF_DEPTH}) exceeded: ${ref}`);
|
|
57
|
-
}
|
|
58
|
-
if (resolving.has(ref)) {
|
|
59
|
-
const cyclePath = [...resolving, ref].join(' -> ');
|
|
60
|
-
throw new Error(`Circular $ref detected: ${cyclePath}`);
|
|
61
|
-
}
|
|
62
|
-
resolving.add(ref);
|
|
63
|
-
const pointer = ref.slice(1);
|
|
64
|
-
const segments = parseJsonPointer(pointer);
|
|
65
|
-
let current = doc;
|
|
66
|
-
for (const segment of segments) {
|
|
67
|
-
if (current === null || current === undefined) {
|
|
68
|
-
throw new Error(`$ref "${ref}" could not be resolved: segment "${segment}" not found`);
|
|
69
|
-
}
|
|
70
|
-
if (typeof current !== 'object') {
|
|
71
|
-
throw new Error(`$ref "${ref}" could not be resolved: segment "${segment}" is not an object`);
|
|
72
|
-
}
|
|
73
|
-
if (Array.isArray(current)) {
|
|
74
|
-
const index = Number(segment);
|
|
75
|
-
if (Number.isNaN(index)) {
|
|
76
|
-
throw new Error(`$ref "${ref}" could not be resolved: "${segment}" is not a valid array index`);
|
|
77
|
-
}
|
|
78
|
-
current = current[index];
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
current = current[segment];
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (current === undefined) {
|
|
85
|
-
throw new Error(`$ref "${ref}" could not be resolved`);
|
|
86
|
-
}
|
|
87
|
-
if (current !== null &&
|
|
88
|
-
typeof current === 'object' &&
|
|
89
|
-
!Array.isArray(current) &&
|
|
90
|
-
'$ref' in current) {
|
|
91
|
-
const chainedRef = current.$ref;
|
|
92
|
-
return this.resolveRefInternal(chainedRef, doc, new Set(resolving), depth + 1);
|
|
93
|
-
}
|
|
94
|
-
return current;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { V3_1_VersionStrategy } from './strategy.js';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { V3_1_VersionStrategy } from './strategy.js';
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { ValidationResult } from '../../validators.js';
|
|
2
|
-
import type { NormalizedSpec } from '../normalized-spec.js';
|
|
3
|
-
import type { VersionStrategy } from '../version-strategy.js';
|
|
4
|
-
/**
|
|
5
|
-
* Version strategy for OpenAPI 3.1.x specifications.
|
|
6
|
-
*
|
|
7
|
-
* OpenAPI 3.1 is aligned with JSON Schema 2020-12 and supports:
|
|
8
|
-
* - Type arrays (e.g., `type: ["string", "null"]`)
|
|
9
|
-
* - Sibling properties alongside `$ref`
|
|
10
|
-
* - `exclusiveMinimum`/`exclusiveMaximum` as numbers
|
|
11
|
-
* - `webhooks` at the top level
|
|
12
|
-
*/
|
|
13
|
-
export declare class V3_1_VersionStrategy implements VersionStrategy {
|
|
14
|
-
version(): string;
|
|
15
|
-
matches(spec: unknown): boolean;
|
|
16
|
-
/**
|
|
17
|
-
* Normalize a raw OpenAPI 3.1 specification to a consistent format.
|
|
18
|
-
*
|
|
19
|
-
* Schema normalization:
|
|
20
|
-
* - `type: "string"` → `types: ["string"]`
|
|
21
|
-
* - `type: ["string", "null"]` → `types: ["string"]`, `nullable: true`
|
|
22
|
-
* - `example: value` → `examples: [value]` (defensive)
|
|
23
|
-
* - `exclusiveMinimum`/`exclusiveMaximum` extracted as numbers
|
|
24
|
-
* - `format: "binary"` → `fileUpload: { binary: true, base64: false }`
|
|
25
|
-
* - `format: "byte"` → `fileUpload: { binary: false, base64: true }`
|
|
26
|
-
*/
|
|
27
|
-
normalizeSpec(rawSpec: unknown): NormalizedSpec;
|
|
28
|
-
validateSpec(spec: NormalizedSpec): ValidationResult;
|
|
29
|
-
/**
|
|
30
|
-
* Resolve a $ref within the document. For OpenAPI 3.1, sibling properties
|
|
31
|
-
* alongside `$ref` are preserved via shallow merge (siblings override target).
|
|
32
|
-
*/
|
|
33
|
-
resolveRef(ref: string, doc: unknown, context?: unknown): unknown;
|
|
34
|
-
getSupportedFeatures(): string[];
|
|
35
|
-
private resolveRefInternal;
|
|
36
|
-
private normalizeSchema;
|
|
37
|
-
private normalizePropertyMap;
|
|
38
|
-
private normalizePathItem;
|
|
39
|
-
private normalizeOperation;
|
|
40
|
-
private normalizeContentMap;
|
|
41
|
-
private normalizeParameter;
|
|
42
|
-
}
|