wrekenfile-converter 2.0.7 → 2.1.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 +45 -26
- package/dist/example-usage.d.ts +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.js +53 -20
- package/dist/v1/index.d.ts +3 -0
- package/dist/v1/index.js +21 -0
- package/dist/{wrekenfile-validator.js → v1/wrekenfile-validator.js} +30 -8
- package/dist/v2/cli/cli-mini-wrekenfile-generator.d.ts +2 -0
- package/dist/v2/cli/cli-mini-wrekenfile-generator.js +107 -0
- package/dist/v2/cli/cli-openapi-to-wrekenfile.d.ts +2 -0
- package/dist/v2/cli/cli-openapi-to-wrekenfile.js +115 -0
- package/dist/v2/cli/cli-openapi-v2-to-wrekenfile.d.ts +2 -0
- package/dist/v2/cli/cli-openapi-v2-to-wrekenfile.js +115 -0
- package/dist/v2/cli/cli-postman-to-wrekenfile.d.ts +2 -0
- package/dist/v2/cli/cli-postman-to-wrekenfile.js +54 -0
- package/dist/v2/index.d.ts +4 -0
- package/dist/v2/index.js +25 -0
- package/dist/v2/mini-wrekenfile-generator.d.ts +13 -0
- package/dist/v2/mini-wrekenfile-generator.js +289 -0
- package/dist/v2/openapi-to-wreken.d.ts +2 -0
- package/dist/v2/openapi-to-wreken.js +829 -0
- package/dist/v2/openapi-v2-to-wrekenfile.d.ts +2 -0
- package/dist/v2/openapi-v2-to-wrekenfile.js +806 -0
- package/dist/v2/postman-to-wrekenfile.d.ts +11 -0
- package/dist/v2/postman-to-wrekenfile.js +742 -0
- package/dist/v2/utils/constants.d.ts +80 -0
- package/dist/v2/utils/constants.js +104 -0
- package/dist/v2/utils/response-utils.d.ts +11 -0
- package/dist/v2/utils/response-utils.js +39 -0
- package/dist/v2/utils/yaml-utils.d.ts +4 -0
- package/dist/v2/utils/yaml-utils.js +96 -0
- package/dist/versions.d.ts +9 -0
- package/dist/versions.js +12 -0
- package/package.json +12 -14
- package/dist/openapi-to-wrekenfile.d.ts +0 -0
- package/dist/openapi-to-wrekenfile.js +0 -10
- package/wrekenfile.md +0 -726
- /package/dist/{cli → v1/cli}/cli-mini-wrekenfile-generator.d.ts +0 -0
- /package/dist/{cli → v1/cli}/cli-mini-wrekenfile-generator.js +0 -0
- /package/dist/{cli → v1/cli}/cli-openapi-to-wrekenfile.d.ts +0 -0
- /package/dist/{cli → v1/cli}/cli-openapi-to-wrekenfile.js +0 -0
- /package/dist/{cli → v1/cli}/cli-postman-to-wrekenfile.d.ts +0 -0
- /package/dist/{cli → v1/cli}/cli-postman-to-wrekenfile.js +0 -0
- /package/dist/{mini-wrekenfile-generator.d.ts → v1/mini-wrekenfile-generator.d.ts} +0 -0
- /package/dist/{mini-wrekenfile-generator.js → v1/mini-wrekenfile-generator.js} +0 -0
- /package/dist/{openapi-to-wreken.d.ts → v1/openapi-to-wreken.d.ts} +0 -0
- /package/dist/{openapi-to-wreken.js → v1/openapi-to-wreken.js} +0 -0
- /package/dist/{openapi-v2-to-wrekenfile.d.ts → v1/openapi-v2-to-wrekenfile.d.ts} +0 -0
- /package/dist/{openapi-v2-to-wrekenfile.js → v1/openapi-v2-to-wrekenfile.js} +0 -0
- /package/dist/{postman-to-wrekenfile.d.ts → v1/postman-to-wrekenfile.d.ts} +0 -0
- /package/dist/{postman-to-wrekenfile.js → v1/postman-to-wrekenfile.js} +0 -0
- /package/dist/{wrekenfile-validator.d.ts → v1/wrekenfile-validator.d.ts} +0 -0
|
@@ -0,0 +1,829 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.generateWrekenfile = generateWrekenfile;
|
|
37
|
+
// openapi-to-wrekenfile-v2.ts
|
|
38
|
+
// Converts OpenAPI v3 specifications to Wrekenfile v2.0.1 format
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const js_yaml_1 = require("js-yaml");
|
|
42
|
+
const yaml_utils_1 = require("./utils/yaml-utils");
|
|
43
|
+
const constants_1 = require("./utils/constants");
|
|
44
|
+
const response_utils_1 = require("./utils/response-utils");
|
|
45
|
+
const externalRefCache = {};
|
|
46
|
+
function mapType(type, format) {
|
|
47
|
+
if (format === 'uuid')
|
|
48
|
+
return 'STRING'; // UUID is typically a string
|
|
49
|
+
if (format === 'date-time')
|
|
50
|
+
return 'TIMESTAMP';
|
|
51
|
+
if (format === 'date')
|
|
52
|
+
return 'DATE';
|
|
53
|
+
if (format === 'time')
|
|
54
|
+
return 'TIME';
|
|
55
|
+
if (format === 'binary')
|
|
56
|
+
return 'STRING'; // File uploads
|
|
57
|
+
if (typeof type === 'string') {
|
|
58
|
+
const t = type.toLowerCase();
|
|
59
|
+
if (t === 'string')
|
|
60
|
+
return 'STRING';
|
|
61
|
+
if (t === 'integer' || t === 'int')
|
|
62
|
+
return 'INT';
|
|
63
|
+
if (t === 'number')
|
|
64
|
+
return 'FLOAT';
|
|
65
|
+
if (t === 'boolean' || t === 'bool')
|
|
66
|
+
return 'BOOL';
|
|
67
|
+
if (t === 'null')
|
|
68
|
+
return 'NULL';
|
|
69
|
+
return 'ANY';
|
|
70
|
+
}
|
|
71
|
+
// Handle array of types (OpenAPI allows type: ['string', 'null'])
|
|
72
|
+
if (Array.isArray(type) && type.length > 0 && typeof type[0] === 'string') {
|
|
73
|
+
const t = type[0].toLowerCase();
|
|
74
|
+
if (t === 'string')
|
|
75
|
+
return 'STRING';
|
|
76
|
+
if (t === 'integer' || t === 'int')
|
|
77
|
+
return 'INT';
|
|
78
|
+
if (t === 'number')
|
|
79
|
+
return 'FLOAT';
|
|
80
|
+
if (t === 'boolean' || t === 'bool')
|
|
81
|
+
return 'BOOL';
|
|
82
|
+
return 'ANY';
|
|
83
|
+
}
|
|
84
|
+
// Fallback for missing or unexpected type
|
|
85
|
+
return 'ANY';
|
|
86
|
+
}
|
|
87
|
+
function generateSummary(op, method, path) {
|
|
88
|
+
if (op.summary)
|
|
89
|
+
return op.summary;
|
|
90
|
+
if (op.description) {
|
|
91
|
+
// Use first sentence of description as summary
|
|
92
|
+
const firstSentence = op.description.split(/[.!?]\s/)[0];
|
|
93
|
+
return firstSentence || op.description.substring(0, 100);
|
|
94
|
+
}
|
|
95
|
+
if (op.operationId)
|
|
96
|
+
return `Perform operation ${op.operationId}`;
|
|
97
|
+
const verb = {
|
|
98
|
+
get: 'Fetch',
|
|
99
|
+
post: 'Create',
|
|
100
|
+
put: 'Update',
|
|
101
|
+
delete: 'Delete',
|
|
102
|
+
patch: 'Modify',
|
|
103
|
+
}[method.toLowerCase()] || 'Call';
|
|
104
|
+
const entity = path.split('/').filter(p => p && !p.startsWith('{')).pop() || 'resource';
|
|
105
|
+
return `${verb} ${entity}`;
|
|
106
|
+
}
|
|
107
|
+
function resolveRef(ref, spec, baseDir) {
|
|
108
|
+
if (ref.startsWith('#/')) {
|
|
109
|
+
return ref.split('/').slice(1).reduce((o, k) => o === null || o === void 0 ? void 0 : o[k], spec);
|
|
110
|
+
}
|
|
111
|
+
const [filePath, internal] = ref.split('#');
|
|
112
|
+
const fullPath = path.resolve(baseDir, filePath);
|
|
113
|
+
if (!externalRefCache[fullPath]) {
|
|
114
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
115
|
+
externalRefCache[fullPath] = (0, js_yaml_1.load)(content);
|
|
116
|
+
}
|
|
117
|
+
return internal
|
|
118
|
+
? internal.split('/').slice(1).reduce((o, k) => o === null || o === void 0 ? void 0 : o[k], externalRefCache[fullPath])
|
|
119
|
+
: externalRefCache[fullPath];
|
|
120
|
+
}
|
|
121
|
+
function getTypeFromSchema(schema, spec, baseDir) {
|
|
122
|
+
if (!schema || typeof schema !== 'object') {
|
|
123
|
+
return 'ANY';
|
|
124
|
+
}
|
|
125
|
+
if (schema.$ref) {
|
|
126
|
+
const resolvedSchema = resolveRef(schema.$ref, spec, baseDir);
|
|
127
|
+
if (resolvedSchema && resolvedSchema.type && resolvedSchema.type !== 'object') {
|
|
128
|
+
return mapType(resolvedSchema.type, resolvedSchema.format);
|
|
129
|
+
}
|
|
130
|
+
const refName = schema.$ref.split('/').pop();
|
|
131
|
+
return `STRUCT(${refName})`;
|
|
132
|
+
}
|
|
133
|
+
if (schema.type === 'array') {
|
|
134
|
+
if (schema.items && schema.items.$ref) {
|
|
135
|
+
const resolvedItems = resolveRef(schema.items.$ref, spec, baseDir);
|
|
136
|
+
if (resolvedItems && resolvedItems.type && resolvedItems.type !== 'object') {
|
|
137
|
+
return `[]${mapType(resolvedItems.type, resolvedItems.format)}`;
|
|
138
|
+
}
|
|
139
|
+
const refName = schema.items.$ref.split('/').pop();
|
|
140
|
+
return `[]STRUCT(${refName})`;
|
|
141
|
+
}
|
|
142
|
+
else if (schema.items) {
|
|
143
|
+
return `[]${mapType(schema.items.type, schema.items.format)}`;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
return '[]ANY';
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (schema.type === 'object') {
|
|
150
|
+
// Check if it has properties or is a generic object
|
|
151
|
+
if (schema.properties || schema.additionalProperties) {
|
|
152
|
+
// If it has additionalProperties, it's a map
|
|
153
|
+
if (schema.additionalProperties) {
|
|
154
|
+
const valueType = typeof schema.additionalProperties === 'object' && schema.additionalProperties.type
|
|
155
|
+
? mapType(schema.additionalProperties.type, schema.additionalProperties.format)
|
|
156
|
+
: 'ANY';
|
|
157
|
+
return `map[STRING]${valueType}`;
|
|
158
|
+
}
|
|
159
|
+
// Otherwise it's a struct (will be defined in STRUCTS)
|
|
160
|
+
return 'OBJECT';
|
|
161
|
+
}
|
|
162
|
+
// Generic object without properties
|
|
163
|
+
return 'OBJECT';
|
|
164
|
+
}
|
|
165
|
+
if (schema.type && schema.type !== 'object') {
|
|
166
|
+
return mapType(schema.type, schema.format);
|
|
167
|
+
}
|
|
168
|
+
return 'ANY';
|
|
169
|
+
}
|
|
170
|
+
function parseSchema(name, schema, spec, baseDir, depth = 0) {
|
|
171
|
+
var _a;
|
|
172
|
+
if (depth > 3)
|
|
173
|
+
return [];
|
|
174
|
+
if (schema.$ref)
|
|
175
|
+
return parseSchema(name, resolveRef(schema.$ref, spec, baseDir), spec, baseDir, depth + 1);
|
|
176
|
+
if (schema.allOf)
|
|
177
|
+
return schema.allOf.flatMap((s) => parseSchema(name, s, spec, baseDir, depth + 1));
|
|
178
|
+
if (schema.oneOf || schema.anyOf) {
|
|
179
|
+
// For unions, create a simple struct
|
|
180
|
+
return [{
|
|
181
|
+
name: 'variant',
|
|
182
|
+
type: `STRUCT(${name}_Union)`,
|
|
183
|
+
REQUIRED: false
|
|
184
|
+
}];
|
|
185
|
+
}
|
|
186
|
+
const fields = [];
|
|
187
|
+
if ((_a = schema.discriminator) === null || _a === void 0 ? void 0 : _a.propertyName) {
|
|
188
|
+
fields.push({
|
|
189
|
+
name: schema.discriminator.propertyName,
|
|
190
|
+
type: 'STRING',
|
|
191
|
+
REQUIRED: true,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
// Handle simple types (string, integer, etc.) - these should not create structs
|
|
195
|
+
if (schema.type && schema.type !== 'object') {
|
|
196
|
+
return [];
|
|
197
|
+
}
|
|
198
|
+
if (schema.type === 'object' && schema.properties) {
|
|
199
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
200
|
+
const type = getTypeFromSchema(prop, spec, baseDir);
|
|
201
|
+
// Use the required field from the OpenAPI spec
|
|
202
|
+
const required = (schema.required || []).includes(key);
|
|
203
|
+
const field = {
|
|
204
|
+
name: key,
|
|
205
|
+
type,
|
|
206
|
+
REQUIRED: required,
|
|
207
|
+
};
|
|
208
|
+
// Add comment if description exists
|
|
209
|
+
if (prop && typeof prop === 'object' && prop.description) {
|
|
210
|
+
field.comment = prop.description;
|
|
211
|
+
}
|
|
212
|
+
fields.push(field);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return fields;
|
|
216
|
+
}
|
|
217
|
+
function generateStructName(operationId, method, path, suffix) {
|
|
218
|
+
if (operationId) {
|
|
219
|
+
return `${operationId}${suffix}`;
|
|
220
|
+
}
|
|
221
|
+
// Generate from path and method
|
|
222
|
+
const pathParts = path.replace(/[\/{}]/g, '_').replace(/^_|_$/g, '');
|
|
223
|
+
return `${method}_${pathParts}${suffix}`;
|
|
224
|
+
}
|
|
225
|
+
function extractStructs(spec, baseDir) {
|
|
226
|
+
var _a, _b;
|
|
227
|
+
const structs = {};
|
|
228
|
+
const schemas = ((_a = spec.components) === null || _a === void 0 ? void 0 : _a.schemas) || {};
|
|
229
|
+
// Helper to recursively collect all referenced schemas
|
|
230
|
+
function collectAllReferencedSchemas(schema, name) {
|
|
231
|
+
if (!schema || typeof schema !== 'object' || !name || structs[name])
|
|
232
|
+
return;
|
|
233
|
+
const resolved = schema.$ref ? resolveRef(schema.$ref, spec, baseDir) : schema;
|
|
234
|
+
const fields = parseSchema(name, resolved, spec, baseDir);
|
|
235
|
+
// Only add struct if it has at least one field
|
|
236
|
+
if (fields.length > 0) {
|
|
237
|
+
structs[name] = fields;
|
|
238
|
+
}
|
|
239
|
+
// Traverse all properties
|
|
240
|
+
if (resolved && resolved.type === 'object' && resolved.properties && typeof resolved.properties === 'object') {
|
|
241
|
+
for (const [propName, prop] of Object.entries(resolved.properties)) {
|
|
242
|
+
if (prop && typeof prop === 'object' && prop.$ref) {
|
|
243
|
+
const refName = prop.$ref.split('/').pop();
|
|
244
|
+
if (refName)
|
|
245
|
+
collectAllReferencedSchemas(resolveRef(prop.$ref, spec, baseDir), refName);
|
|
246
|
+
}
|
|
247
|
+
else if (prop && typeof prop === 'object' && prop.type === 'array' && prop.items) {
|
|
248
|
+
if (prop.items && typeof prop.items === 'object' && prop.items.$ref) {
|
|
249
|
+
const refName = prop.items.$ref.split('/').pop();
|
|
250
|
+
if (refName)
|
|
251
|
+
collectAllReferencedSchemas(resolveRef(prop.items.$ref, spec, baseDir), refName);
|
|
252
|
+
}
|
|
253
|
+
else if (prop.items && typeof prop.items === 'object' && (prop.items.type === 'object' || prop.items.properties || prop.items.allOf || prop.items.oneOf || prop.items.anyOf)) {
|
|
254
|
+
collectAllReferencedSchemas(prop.items, name + '_' + propName + '_Item');
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
else if (prop && typeof prop === 'object' && (prop.type === 'object' || prop.properties || prop.allOf || prop.oneOf || prop.anyOf)) {
|
|
258
|
+
collectAllReferencedSchemas(prop, name + '_' + propName);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Traverse array items at root
|
|
263
|
+
if (resolved && resolved.type === 'array' && resolved.items) {
|
|
264
|
+
if (resolved.items && typeof resolved.items === 'object' && resolved.items.$ref) {
|
|
265
|
+
const refName = resolved.items.$ref.split('/').pop();
|
|
266
|
+
if (refName)
|
|
267
|
+
collectAllReferencedSchemas(resolveRef(resolved.items.$ref, spec, baseDir), refName);
|
|
268
|
+
}
|
|
269
|
+
else if (resolved.items && typeof resolved.items === 'object' && (resolved.items.type === 'object' || resolved.items.properties || resolved.items.allOf || resolved.items.oneOf || resolved.items.anyOf)) {
|
|
270
|
+
collectAllReferencedSchemas(resolved.items, name + '_Item');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Traverse allOf/oneOf/anyOf
|
|
274
|
+
for (const combiner of ['allOf', 'oneOf', 'anyOf']) {
|
|
275
|
+
if (resolved && Array.isArray(resolved[combiner])) {
|
|
276
|
+
for (const subSchema of resolved[combiner]) {
|
|
277
|
+
if (subSchema && typeof subSchema === 'object' && subSchema.$ref) {
|
|
278
|
+
const refName = subSchema.$ref.split('/').pop();
|
|
279
|
+
if (refName)
|
|
280
|
+
collectAllReferencedSchemas(resolveRef(subSchema.$ref, spec, baseDir), refName);
|
|
281
|
+
}
|
|
282
|
+
else if (subSchema && typeof subSchema === 'object') {
|
|
283
|
+
collectAllReferencedSchemas(subSchema, name + '_' + combiner);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Extract schemas from components
|
|
290
|
+
for (const name in schemas) {
|
|
291
|
+
collectAllReferencedSchemas(schemas[name], name);
|
|
292
|
+
const schema = schemas[name];
|
|
293
|
+
if (schema && (schema.oneOf || schema.anyOf)) {
|
|
294
|
+
structs[`${name}_Union`] = [{ name: 'value', type: 'ANY', REQUIRED: false }];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Extract inline schemas from operations
|
|
298
|
+
if (spec.paths && typeof spec.paths === 'object') {
|
|
299
|
+
for (const [pathStr, methods] of Object.entries(spec.paths)) {
|
|
300
|
+
for (const [method, op] of Object.entries(methods)) {
|
|
301
|
+
const operationId = op.operationId || `${method}-${pathStr.replace(/[\/{}]/g, '-')}`;
|
|
302
|
+
// Extract request body schemas
|
|
303
|
+
if ((_b = op.requestBody) === null || _b === void 0 ? void 0 : _b.content) {
|
|
304
|
+
for (const [contentType, content] of Object.entries(op.requestBody.content)) {
|
|
305
|
+
if (content && content.schema) {
|
|
306
|
+
if (content.schema && content.schema.$ref) {
|
|
307
|
+
const refName = content.schema.$ref.split('/').pop();
|
|
308
|
+
if (refName)
|
|
309
|
+
collectAllReferencedSchemas(resolveRef(content.schema.$ref, spec, baseDir), refName);
|
|
310
|
+
}
|
|
311
|
+
else if (content.schema && typeof content.schema === 'object') {
|
|
312
|
+
const requestStructName = generateStructName(operationId, method, pathStr, 'Request');
|
|
313
|
+
collectAllReferencedSchemas(content.schema, requestStructName);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// Extract response schemas
|
|
319
|
+
if (op.responses) {
|
|
320
|
+
for (const [code, response] of Object.entries(op.responses)) {
|
|
321
|
+
if (response && response.content) {
|
|
322
|
+
for (const [contentType, content] of Object.entries(response.content)) {
|
|
323
|
+
if (content && content.schema) {
|
|
324
|
+
const schema = content.schema;
|
|
325
|
+
if (schema.$ref) {
|
|
326
|
+
const refName = schema.$ref.split('/').pop();
|
|
327
|
+
if (refName)
|
|
328
|
+
collectAllReferencedSchemas(resolveRef(schema.$ref, spec, baseDir), refName);
|
|
329
|
+
}
|
|
330
|
+
else if (schema.type === 'array' && schema.items) {
|
|
331
|
+
// For array responses, extract the item type
|
|
332
|
+
if (schema.items.$ref) {
|
|
333
|
+
const refName = schema.items.$ref.split('/').pop();
|
|
334
|
+
if (refName)
|
|
335
|
+
collectAllReferencedSchemas(resolveRef(schema.items.$ref, spec, baseDir), refName);
|
|
336
|
+
}
|
|
337
|
+
else if (schema.items.type === 'object') {
|
|
338
|
+
// Inline object in array - create struct for the item
|
|
339
|
+
const responseStructName = generateStructName(operationId, method, pathStr, `Response${code}Item`);
|
|
340
|
+
collectAllReferencedSchemas(schema.items, responseStructName);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
else if (schema.type === 'object' && typeof schema === 'object') {
|
|
344
|
+
// Inline object schema - create struct
|
|
345
|
+
const responseStructName = generateStructName(operationId, method, pathStr, `Response${code}`);
|
|
346
|
+
collectAllReferencedSchemas(schema, responseStructName);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return structs;
|
|
357
|
+
}
|
|
358
|
+
function getContentTypeAndBodyType(op) {
|
|
359
|
+
const requestBody = op.requestBody;
|
|
360
|
+
if (!(requestBody === null || requestBody === void 0 ? void 0 : requestBody.content)) {
|
|
361
|
+
return { contentType: 'application/json', bodyType: 'raw' };
|
|
362
|
+
}
|
|
363
|
+
const contentTypes = Object.keys(requestBody.content);
|
|
364
|
+
const contentType = contentTypes[0] || 'application/json';
|
|
365
|
+
let bodyType = 'raw';
|
|
366
|
+
if (contentType === 'multipart/form-data') {
|
|
367
|
+
bodyType = 'form-data';
|
|
368
|
+
}
|
|
369
|
+
else if (contentType === 'application/x-www-form-urlencoded') {
|
|
370
|
+
bodyType = 'x-www-form-urlencoded';
|
|
371
|
+
}
|
|
372
|
+
return { contentType, bodyType };
|
|
373
|
+
}
|
|
374
|
+
function getHeadersForOperation(op, spec) {
|
|
375
|
+
var _a, _b, _c;
|
|
376
|
+
const { contentType } = getContentTypeAndBodyType(op);
|
|
377
|
+
// Use a Map to prevent duplicate headers
|
|
378
|
+
const headerMap = new Map();
|
|
379
|
+
// Add Content-Type header for POST/PUT/PATCH requests
|
|
380
|
+
if (['post', 'put', 'patch'].includes(((_a = op.method) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '')) {
|
|
381
|
+
headerMap.set('Content-Type', contentType);
|
|
382
|
+
}
|
|
383
|
+
// Add security headers based on the operation's security requirements
|
|
384
|
+
const security = op.security || spec.security || [];
|
|
385
|
+
for (const securityRequirement of security) {
|
|
386
|
+
for (const [schemeName, scopes] of Object.entries(securityRequirement)) {
|
|
387
|
+
const scheme = (_c = (_b = spec.components) === null || _b === void 0 ? void 0 : _b.securitySchemes) === null || _c === void 0 ? void 0 : _c[schemeName];
|
|
388
|
+
if (scheme) {
|
|
389
|
+
if (scheme.type === 'http') {
|
|
390
|
+
if (scheme.scheme === 'bearer') {
|
|
391
|
+
headerMap.set('Authorization', 'bearer_token');
|
|
392
|
+
}
|
|
393
|
+
else if (scheme.scheme === 'basic') {
|
|
394
|
+
headerMap.set('Authorization', 'basic_auth');
|
|
395
|
+
}
|
|
396
|
+
else if (scheme.scheme === 'digest') {
|
|
397
|
+
headerMap.set('Authorization', 'digest_auth');
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
headerMap.set('Authorization', `<${scheme.scheme}_auth>`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
else if (scheme.type === 'apiKey') {
|
|
404
|
+
if (scheme.in === 'header') {
|
|
405
|
+
headerMap.set(scheme.name, scheme.name.toLowerCase());
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
else if (scheme.type === 'oauth2') {
|
|
409
|
+
headerMap.set('Authorization', 'bearer_token');
|
|
410
|
+
}
|
|
411
|
+
else if (scheme.type === 'openIdConnect') {
|
|
412
|
+
headerMap.set('Authorization', 'id_token');
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// Convert Map to object
|
|
418
|
+
const headers = {};
|
|
419
|
+
for (const [key, value] of headerMap.entries()) {
|
|
420
|
+
headers[key] = value;
|
|
421
|
+
}
|
|
422
|
+
return headers;
|
|
423
|
+
}
|
|
424
|
+
function extractParameters(op, spec, baseDir) {
|
|
425
|
+
const inputParams = [];
|
|
426
|
+
// Handle path, query, and header parameters
|
|
427
|
+
for (let param of op.parameters || []) {
|
|
428
|
+
// Resolve $ref if present
|
|
429
|
+
if (param.$ref) {
|
|
430
|
+
param = resolveRef(param.$ref, spec, baseDir);
|
|
431
|
+
}
|
|
432
|
+
const paramName = param.name;
|
|
433
|
+
const paramSchema = param.schema || {};
|
|
434
|
+
let type = 'STRING';
|
|
435
|
+
if (paramSchema.type) {
|
|
436
|
+
type = getTypeFromSchema(paramSchema, spec, baseDir);
|
|
437
|
+
}
|
|
438
|
+
else if (paramSchema.$ref) {
|
|
439
|
+
type = getTypeFromSchema(paramSchema, spec, baseDir);
|
|
440
|
+
}
|
|
441
|
+
const isRequired = param.required !== false; // Default to true if not specified
|
|
442
|
+
const hasDefault = paramSchema.default !== undefined;
|
|
443
|
+
// Build input parameter in v2.0.1 format
|
|
444
|
+
// Use simple form if required and no default, extended form otherwise
|
|
445
|
+
if (isRequired && !hasDefault) {
|
|
446
|
+
// Simple form: - paramName: TYPE
|
|
447
|
+
const inputParam = {};
|
|
448
|
+
inputParam[paramName] = type;
|
|
449
|
+
inputParams.push(inputParam);
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
// Extended form: - paramName: { TYPE: ..., REQUIRED: ..., DEFAULT: ... }
|
|
453
|
+
const inputParam = {};
|
|
454
|
+
inputParam[paramName] = {
|
|
455
|
+
TYPE: type,
|
|
456
|
+
REQUIRED: isRequired,
|
|
457
|
+
};
|
|
458
|
+
if (hasDefault) {
|
|
459
|
+
inputParam[paramName].DEFAULT = paramSchema.default;
|
|
460
|
+
}
|
|
461
|
+
inputParams.push(inputParam);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return inputParams;
|
|
465
|
+
}
|
|
466
|
+
function extractRequestBody(op, operationId, method, path, spec, baseDir) {
|
|
467
|
+
var _a, _b, _c;
|
|
468
|
+
const inputParams = [];
|
|
469
|
+
const requestBody = op.requestBody;
|
|
470
|
+
if (!(requestBody === null || requestBody === void 0 ? void 0 : requestBody.content)) {
|
|
471
|
+
return inputParams;
|
|
472
|
+
}
|
|
473
|
+
const contentTypes = Object.keys(requestBody.content);
|
|
474
|
+
const contentType = contentTypes[0];
|
|
475
|
+
if (contentType === 'application/json' && ((_a = requestBody.content[contentType]) === null || _a === void 0 ? void 0 : _a.schema)) {
|
|
476
|
+
const bodySchema = requestBody.content[contentType].schema;
|
|
477
|
+
let type;
|
|
478
|
+
if (bodySchema && bodySchema.$ref) {
|
|
479
|
+
type = getTypeFromSchema(bodySchema, spec, baseDir);
|
|
480
|
+
}
|
|
481
|
+
else if (bodySchema) {
|
|
482
|
+
const requestStructName = generateStructName(operationId, method, path, 'Request');
|
|
483
|
+
type = `STRUCT(${requestStructName})`;
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
type = 'ANY';
|
|
487
|
+
}
|
|
488
|
+
const isRequired = requestBody.required !== false;
|
|
489
|
+
if (isRequired) {
|
|
490
|
+
// Simple form
|
|
491
|
+
const inputParam = {};
|
|
492
|
+
inputParam.body = type;
|
|
493
|
+
inputParams.push(inputParam);
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
// Extended form
|
|
497
|
+
const inputParam = {};
|
|
498
|
+
inputParam.body = {
|
|
499
|
+
TYPE: type,
|
|
500
|
+
REQUIRED: false,
|
|
501
|
+
};
|
|
502
|
+
inputParams.push(inputParam);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
else if (contentType === 'multipart/form-data' && ((_b = requestBody.content[contentType]) === null || _b === void 0 ? void 0 : _b.schema)) {
|
|
506
|
+
const bodySchema = requestBody.content[contentType].schema;
|
|
507
|
+
if (bodySchema && bodySchema.properties) {
|
|
508
|
+
for (const [key, prop] of Object.entries(bodySchema.properties)) {
|
|
509
|
+
const type = prop && prop.format === 'binary' ? 'STRING' : getTypeFromSchema(prop, spec, baseDir);
|
|
510
|
+
const required = (bodySchema.required || []).includes(key);
|
|
511
|
+
const hasDefault = prop && prop.default !== undefined;
|
|
512
|
+
const inputParam = {};
|
|
513
|
+
if (required && !hasDefault) {
|
|
514
|
+
// Simple form
|
|
515
|
+
inputParam[key] = type;
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
// Extended form
|
|
519
|
+
inputParam[key] = {
|
|
520
|
+
TYPE: type,
|
|
521
|
+
REQUIRED: required,
|
|
522
|
+
};
|
|
523
|
+
if (hasDefault) {
|
|
524
|
+
inputParam[key].DEFAULT = prop.default;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
inputParams.push(inputParam);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
else if (contentType === 'application/x-www-form-urlencoded' && ((_c = requestBody.content[contentType]) === null || _c === void 0 ? void 0 : _c.schema)) {
|
|
532
|
+
const bodySchema = requestBody.content[contentType].schema;
|
|
533
|
+
if (bodySchema && bodySchema.properties) {
|
|
534
|
+
for (const [key, prop] of Object.entries(bodySchema.properties)) {
|
|
535
|
+
const type = getTypeFromSchema(prop, spec, baseDir);
|
|
536
|
+
const required = (bodySchema.required || []).includes(key);
|
|
537
|
+
const hasDefault = prop && prop.default !== undefined;
|
|
538
|
+
const inputParam = {};
|
|
539
|
+
if (required && !hasDefault) {
|
|
540
|
+
// Simple form
|
|
541
|
+
inputParam[key] = type;
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
// Extended form
|
|
545
|
+
inputParam[key] = {
|
|
546
|
+
TYPE: type,
|
|
547
|
+
REQUIRED: required,
|
|
548
|
+
};
|
|
549
|
+
if (hasDefault) {
|
|
550
|
+
inputParam[key].DEFAULT = prop.default;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
inputParams.push(inputParam);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return inputParams;
|
|
558
|
+
}
|
|
559
|
+
function extractResponses(op, operationId, method, path, spec, baseDir) {
|
|
560
|
+
const returns = [];
|
|
561
|
+
// Only include success responses (2xx) in RETURNS section
|
|
562
|
+
// Error responses go in ERRORS section
|
|
563
|
+
for (const [code, response] of Object.entries(op.responses || {})) {
|
|
564
|
+
const statusCode = parseInt(code);
|
|
565
|
+
// Only process 2xx success responses
|
|
566
|
+
if (statusCode < 200 || statusCode >= 300) {
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
const content = response.content;
|
|
570
|
+
let returnType = null;
|
|
571
|
+
// 204 No Content - no response body
|
|
572
|
+
if (code === '204') {
|
|
573
|
+
// Skip void responses - they should not have RETURNS section
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
if (content) {
|
|
577
|
+
const jsonContent = content['application/json'];
|
|
578
|
+
if (jsonContent === null || jsonContent === void 0 ? void 0 : jsonContent.schema) {
|
|
579
|
+
const schema = jsonContent.schema;
|
|
580
|
+
// Use getTypeFromSchema to handle arrays, $refs, and inline schemas correctly
|
|
581
|
+
returnType = getTypeFromSchema(schema, spec, baseDir);
|
|
582
|
+
// If it's an inline object schema (not array, not $ref), we need to create a struct
|
|
583
|
+
if (returnType === 'OBJECT' && !schema.$ref && schema.type === 'object') {
|
|
584
|
+
const responseStructName = generateStructName(operationId, method, path, `Response${code}`);
|
|
585
|
+
returnType = `STRUCT(${responseStructName})`;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
else {
|
|
589
|
+
// No schema but has content - might be empty body
|
|
590
|
+
returnType = 'ANY';
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
else {
|
|
594
|
+
// No content - skip void success responses
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
// Only add to RETURNS if there's actually a return type
|
|
598
|
+
if (returnType) {
|
|
599
|
+
// Generate descriptive RETURNVAR name based on response code and operation
|
|
600
|
+
const operationName = operationId || method.toLowerCase() + path.replace(/[\/{}]/g, '_');
|
|
601
|
+
const returnVarName = (0, response_utils_1.generateReturnVarName)(operationName, code);
|
|
602
|
+
const returnItem = {
|
|
603
|
+
RETURNTYPE: returnType,
|
|
604
|
+
RETURNVAR: returnVarName,
|
|
605
|
+
};
|
|
606
|
+
// Check for pagination hints in response schema
|
|
607
|
+
if (content) {
|
|
608
|
+
const jsonContent = content['application/json'];
|
|
609
|
+
if (jsonContent === null || jsonContent === void 0 ? void 0 : jsonContent.schema) {
|
|
610
|
+
const schema = jsonContent.schema;
|
|
611
|
+
const resolvedSchema = schema.$ref ? resolveRef(schema.$ref, spec, baseDir) : schema;
|
|
612
|
+
if (resolvedSchema && resolvedSchema.properties) {
|
|
613
|
+
// Look for common pagination fields
|
|
614
|
+
if (resolvedSchema.properties.next_cursor || resolvedSchema.properties.cursor) {
|
|
615
|
+
returnItem.PAGINATION = {
|
|
616
|
+
TYPE: 'cursor',
|
|
617
|
+
CURSOR_FIELD: resolvedSchema.properties.next_cursor ? 'next_cursor' : 'cursor',
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
else if (resolvedSchema.properties.offset !== undefined || resolvedSchema.properties.skip !== undefined) {
|
|
621
|
+
returnItem.PAGINATION = {
|
|
622
|
+
TYPE: 'offset',
|
|
623
|
+
OFFSET_FIELD: resolvedSchema.properties.offset !== undefined ? 'offset' : 'skip',
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
else if (resolvedSchema.properties.page !== undefined || resolvedSchema.properties.pageNumber !== undefined) {
|
|
627
|
+
returnItem.PAGINATION = {
|
|
628
|
+
TYPE: 'page',
|
|
629
|
+
PAGE_SIZE_FIELD: resolvedSchema.properties.pageSize || 'limit',
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
returns.push(returnItem);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return returns;
|
|
639
|
+
}
|
|
640
|
+
function extractErrors(op, spec, baseDir) {
|
|
641
|
+
const errors = [];
|
|
642
|
+
// Extract error responses (4xx, 5xx)
|
|
643
|
+
for (const [code, response] of Object.entries(op.responses || {})) {
|
|
644
|
+
const statusCode = parseInt(code);
|
|
645
|
+
if (isNaN(statusCode) && code !== 'default')
|
|
646
|
+
continue;
|
|
647
|
+
if (statusCode >= 400 || code === 'default') {
|
|
648
|
+
const content = response.content;
|
|
649
|
+
let errorType = constants_1.TYPE_ANY;
|
|
650
|
+
let when = `HTTP ${code}`;
|
|
651
|
+
if (content) {
|
|
652
|
+
const jsonContent = content['application/json'];
|
|
653
|
+
if (jsonContent === null || jsonContent === void 0 ? void 0 : jsonContent.schema) {
|
|
654
|
+
const schema = jsonContent.schema;
|
|
655
|
+
if (schema.$ref) {
|
|
656
|
+
errorType = getTypeFromSchema(schema, spec, baseDir);
|
|
657
|
+
}
|
|
658
|
+
else {
|
|
659
|
+
// Inline error schema - generate a struct name
|
|
660
|
+
const errorStructName = `Error${code}`;
|
|
661
|
+
errorType = `STRUCT(${errorStructName})`;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
// Generate descriptive WHEN clause with HTTP status code
|
|
666
|
+
when = (0, response_utils_1.generateErrorWhen)(response, code);
|
|
667
|
+
errors.push({
|
|
668
|
+
TYPE: errorType,
|
|
669
|
+
WHEN: when,
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
return errors;
|
|
674
|
+
}
|
|
675
|
+
function generateMethodAlias(operationId, method, path) {
|
|
676
|
+
if (operationId) {
|
|
677
|
+
// Convert operationId to kebab-case if needed
|
|
678
|
+
return operationId.replace(/_/g, '-').toLowerCase();
|
|
679
|
+
}
|
|
680
|
+
// Generate from path and method
|
|
681
|
+
const pathParts = path.replace(/[\/{}]/g, '-').replace(/^-|-$/g, '');
|
|
682
|
+
return `${method.toLowerCase()}-${pathParts}`;
|
|
683
|
+
}
|
|
684
|
+
function extractMethods(spec, baseDir) {
|
|
685
|
+
var _a, _b;
|
|
686
|
+
const base = ((_b = (_a = spec.servers) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.url) || '';
|
|
687
|
+
const methods = {};
|
|
688
|
+
// Valid HTTP methods
|
|
689
|
+
const validMethods = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'];
|
|
690
|
+
// Check if paths exists and is an object
|
|
691
|
+
if (!spec.paths || typeof spec.paths !== 'object') {
|
|
692
|
+
return methods;
|
|
693
|
+
}
|
|
694
|
+
for (const [pathStr, pathMethods] of Object.entries(spec.paths)) {
|
|
695
|
+
for (const [method, op] of Object.entries(pathMethods)) {
|
|
696
|
+
// Skip extension fields (x-*) and only process valid HTTP methods
|
|
697
|
+
if (method.startsWith('x-') || !validMethods.includes(method.toLowerCase())) {
|
|
698
|
+
continue;
|
|
699
|
+
}
|
|
700
|
+
const operationId = op.operationId || `${method}-${pathStr.replace(/[\/{}]/g, '-')}`;
|
|
701
|
+
const alias = generateMethodAlias(operationId, method, pathStr);
|
|
702
|
+
const summary = generateSummary(op, method, pathStr);
|
|
703
|
+
const endpoint = pathStr;
|
|
704
|
+
const { bodyType } = getContentTypeAndBodyType(op);
|
|
705
|
+
const headers = getHeadersForOperation(op, spec);
|
|
706
|
+
const pathQueryHeaderParams = extractParameters(op, spec, baseDir);
|
|
707
|
+
const bodyParams = extractRequestBody(op, operationId, method, pathStr, spec, baseDir);
|
|
708
|
+
const inputParams = [...pathQueryHeaderParams, ...bodyParams];
|
|
709
|
+
const returns = extractResponses(op, operationId, method, pathStr, spec, baseDir);
|
|
710
|
+
const errors = extractErrors(op, spec, baseDir);
|
|
711
|
+
// Build method in v2.0.1 format
|
|
712
|
+
const methodDef = {
|
|
713
|
+
SUMMARY: summary,
|
|
714
|
+
};
|
|
715
|
+
// Add DESC if description exists
|
|
716
|
+
if (op.description) {
|
|
717
|
+
methodDef.DESC = op.description;
|
|
718
|
+
}
|
|
719
|
+
// HTTP section (mandatory for API methods)
|
|
720
|
+
methodDef.HTTP = {
|
|
721
|
+
METHOD: method.toUpperCase(),
|
|
722
|
+
ENDPOINT: endpoint,
|
|
723
|
+
HEADERS: headers,
|
|
724
|
+
};
|
|
725
|
+
if (bodyType !== constants_1.BODYTYPE_RAW) {
|
|
726
|
+
methodDef.HTTP.BODYTYPE = bodyType;
|
|
727
|
+
}
|
|
728
|
+
// EXECUTION section (mandatory)
|
|
729
|
+
methodDef.EXECUTION = {
|
|
730
|
+
MODE: constants_1.EXECUTION_MODE_ASYNC, // HTTP methods default to async
|
|
731
|
+
};
|
|
732
|
+
// ASYNC section (required when MODE = async)
|
|
733
|
+
const resultType = returns.length > 0 ? returns[0].RETURNTYPE : constants_1.TYPE_VOID;
|
|
734
|
+
methodDef.ASYNC = {
|
|
735
|
+
RETURNS: constants_1.ASYNC_RETURNS_RESULT,
|
|
736
|
+
RESULT: {
|
|
737
|
+
TYPE: resultType,
|
|
738
|
+
},
|
|
739
|
+
};
|
|
740
|
+
// INPUTS section (optional)
|
|
741
|
+
if (inputParams.length > 0) {
|
|
742
|
+
methodDef.INPUTS = inputParams;
|
|
743
|
+
}
|
|
744
|
+
// RETURNS section (optional - omit for void)
|
|
745
|
+
if (returns.length > 0) {
|
|
746
|
+
methodDef.RETURNS = returns;
|
|
747
|
+
}
|
|
748
|
+
// ERRORS section (optional)
|
|
749
|
+
if (errors.length > 0) {
|
|
750
|
+
methodDef.ERRORS = errors;
|
|
751
|
+
}
|
|
752
|
+
methods[alias] = methodDef;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
return methods;
|
|
756
|
+
}
|
|
757
|
+
function extractSecurityDefaults(spec) {
|
|
758
|
+
var _a, _b, _c;
|
|
759
|
+
const defs = {};
|
|
760
|
+
const securitySchemes = ((_a = spec.components) === null || _a === void 0 ? void 0 : _a.securitySchemes) || {};
|
|
761
|
+
for (const [name, scheme] of Object.entries(securitySchemes)) {
|
|
762
|
+
if (scheme.type === 'http') {
|
|
763
|
+
if (scheme.scheme === 'bearer') {
|
|
764
|
+
defs.bearer_token = 'BEARER <TOKEN>';
|
|
765
|
+
}
|
|
766
|
+
else if (scheme.scheme === 'basic') {
|
|
767
|
+
defs.basic_auth = 'Basic <BASE64>';
|
|
768
|
+
}
|
|
769
|
+
else if (scheme.scheme === 'digest') {
|
|
770
|
+
defs.digest_auth = 'Digest <CREDENTIALS>';
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
defs[`${scheme.scheme}_auth`] = `<${scheme.scheme.toUpperCase()}_CREDENTIALS>`;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
else if (scheme.type === 'apiKey') {
|
|
777
|
+
if (scheme.in === 'header') {
|
|
778
|
+
defs[scheme.name.toLowerCase()] = `<${scheme.name.toUpperCase()}>`;
|
|
779
|
+
}
|
|
780
|
+
else if (scheme.in === 'query') {
|
|
781
|
+
defs[`query_${scheme.name.toLowerCase()}`] = `<${scheme.name.toUpperCase()}>`;
|
|
782
|
+
}
|
|
783
|
+
else if (scheme.in === 'cookie') {
|
|
784
|
+
defs[`cookie_${scheme.name.toLowerCase()}`] = `<${scheme.name.toUpperCase()}>`;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
else if (scheme.type === 'oauth2') {
|
|
788
|
+
defs.bearer_token = 'BEARER <ACCESS_TOKEN>';
|
|
789
|
+
}
|
|
790
|
+
else if (scheme.type === 'openIdConnect') {
|
|
791
|
+
defs.id_token = 'ID_TOKEN <JWT>';
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
// Add base URL
|
|
795
|
+
const baseUrl = ((_c = (_b = spec.servers) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.url) || constants_1.DEFAULT_BASE_URL;
|
|
796
|
+
defs.w_base_url = baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
797
|
+
return defs;
|
|
798
|
+
}
|
|
799
|
+
function generateWrekenfile(spec, baseDir) {
|
|
800
|
+
if (!spec || typeof spec !== 'object') {
|
|
801
|
+
throw new Error("Argument 'spec' is required and must be an object");
|
|
802
|
+
}
|
|
803
|
+
if (!baseDir || typeof baseDir !== 'string') {
|
|
804
|
+
throw new Error("Argument 'baseDir' is required and must be a string");
|
|
805
|
+
}
|
|
806
|
+
const defaults = extractSecurityDefaults(spec);
|
|
807
|
+
const methods = extractMethods(spec, baseDir);
|
|
808
|
+
const structs = extractStructs(spec, baseDir);
|
|
809
|
+
const wrekenfile = {
|
|
810
|
+
VERSION: constants_1.WREKENFILE_VERSION,
|
|
811
|
+
};
|
|
812
|
+
// Add DEFAULTS if we have any
|
|
813
|
+
if (Object.keys(defaults).length > 0) {
|
|
814
|
+
wrekenfile.DEFAULTS = defaults;
|
|
815
|
+
}
|
|
816
|
+
// Add METHODS (mandatory)
|
|
817
|
+
wrekenfile.METHODS = methods;
|
|
818
|
+
// Add STRUCTS if we have any
|
|
819
|
+
if (Object.keys(structs).length > 0) {
|
|
820
|
+
wrekenfile.STRUCTS = structs;
|
|
821
|
+
}
|
|
822
|
+
let yamlString = (0, js_yaml_1.dump)(wrekenfile, constants_1.YAML_DUMP_OPTIONS);
|
|
823
|
+
// Post-process to remove quotes from type strings
|
|
824
|
+
yamlString = (0, yaml_utils_1.removeTypeQuotes)(yamlString);
|
|
825
|
+
yamlString = (0, yaml_utils_1.cleanYaml)(yamlString);
|
|
826
|
+
(0, yaml_utils_1.checkYamlForHiddenChars)(yamlString);
|
|
827
|
+
(0, yaml_utils_1.validateYaml)(yamlString);
|
|
828
|
+
return yamlString;
|
|
829
|
+
}
|