wrekenfile-converter 2.0.6 → 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/{postman-to-wrekenfile.js → v1/postman-to-wrekenfile.js} +7 -19
- 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/{wrekenfile-validator.d.ts → v1/wrekenfile-validator.d.ts} +0 -0
|
@@ -0,0 +1,806 @@
|
|
|
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-v2-swagger-to-wrekenfile-v2.ts
|
|
38
|
+
// Converts OpenAPI v2 (Swagger) 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 && typeof schema === 'object' && schema.$ref) {
|
|
175
|
+
return parseSchema(name, resolveRef(schema.$ref, spec, baseDir), spec, baseDir, depth + 1);
|
|
176
|
+
}
|
|
177
|
+
if (schema && typeof schema === 'object' && schema.allOf) {
|
|
178
|
+
return schema.allOf.flatMap((s) => parseSchema(name, s, spec, baseDir, depth + 1));
|
|
179
|
+
}
|
|
180
|
+
if (schema && typeof schema === 'object' && (schema.oneOf || schema.anyOf)) {
|
|
181
|
+
return [{
|
|
182
|
+
name: 'variant',
|
|
183
|
+
type: `STRUCT(${name}_Union)`,
|
|
184
|
+
REQUIRED: false
|
|
185
|
+
}];
|
|
186
|
+
}
|
|
187
|
+
const fields = [];
|
|
188
|
+
if (schema && typeof schema === 'object' && ((_a = schema.discriminator) === null || _a === void 0 ? void 0 : _a.propertyName)) {
|
|
189
|
+
fields.push({
|
|
190
|
+
name: schema.discriminator.propertyName,
|
|
191
|
+
type: 'STRING',
|
|
192
|
+
REQUIRED: true,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// Handle simple types (string, integer, etc.) - these should not create structs
|
|
196
|
+
if (schema && typeof schema === 'object' && schema.type && schema.type !== 'object' && schema.type !== 'array') {
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
199
|
+
if (schema && typeof schema === 'object' && schema.type === 'object' && schema.properties) {
|
|
200
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
201
|
+
const type = getTypeFromSchema(prop, spec, baseDir);
|
|
202
|
+
// Use the required field from the OpenAPI spec
|
|
203
|
+
const required = (schema.required || []).includes(key);
|
|
204
|
+
const field = {
|
|
205
|
+
name: key,
|
|
206
|
+
type,
|
|
207
|
+
REQUIRED: required,
|
|
208
|
+
};
|
|
209
|
+
// Add comment if description exists
|
|
210
|
+
if (prop && typeof prop === 'object' && prop.description) {
|
|
211
|
+
field.comment = prop.description;
|
|
212
|
+
}
|
|
213
|
+
fields.push(field);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return fields;
|
|
217
|
+
}
|
|
218
|
+
function generateStructName(operationId, method, path, suffix) {
|
|
219
|
+
if (operationId) {
|
|
220
|
+
return `${operationId}${suffix}`;
|
|
221
|
+
}
|
|
222
|
+
// Generate from path and method
|
|
223
|
+
const pathParts = path.replace(/[\/{}]/g, '_').replace(/^_|_$/g, '');
|
|
224
|
+
return `${method}_${pathParts}${suffix}`;
|
|
225
|
+
}
|
|
226
|
+
function extractStructs(spec, baseDir) {
|
|
227
|
+
const structs = {};
|
|
228
|
+
const definitions = spec.definitions || {}; // OpenAPI v2 uses 'definitions' instead of 'components.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 definitions (OpenAPI v2)
|
|
290
|
+
for (const name in definitions) {
|
|
291
|
+
collectAllReferencedSchemas(definitions[name], name);
|
|
292
|
+
const schema = definitions[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, pathMethods] of Object.entries(spec.paths)) {
|
|
300
|
+
for (const [method, op] of Object.entries(pathMethods)) {
|
|
301
|
+
const operationId = op.operationId || `${method}-${pathStr.replace(/[\/{}]/g, '-')}`;
|
|
302
|
+
// Extract request body schemas (OpenAPI v2 uses parameters with in: body)
|
|
303
|
+
if (op.parameters) {
|
|
304
|
+
for (const param of op.parameters) {
|
|
305
|
+
if (param && typeof param === 'object' && param.in === 'body' && param.schema) {
|
|
306
|
+
if (param.schema && param.schema.$ref) {
|
|
307
|
+
const refName = param.schema.$ref.split('/').pop();
|
|
308
|
+
if (refName)
|
|
309
|
+
collectAllReferencedSchemas(resolveRef(param.schema.$ref, spec, baseDir), refName);
|
|
310
|
+
}
|
|
311
|
+
else if (param.schema && typeof param.schema === 'object') {
|
|
312
|
+
const requestStructName = generateStructName(operationId, method, pathStr, 'Request');
|
|
313
|
+
collectAllReferencedSchemas(param.schema, requestStructName);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// Extract response schemas (OpenAPI v2 has schema directly in response)
|
|
319
|
+
if (op.responses) {
|
|
320
|
+
for (const [code, response] of Object.entries(op.responses)) {
|
|
321
|
+
// Handle response references
|
|
322
|
+
let actualResponse = response;
|
|
323
|
+
if (response && typeof response === 'object' && response.$ref) {
|
|
324
|
+
actualResponse = resolveRef(response.$ref, spec, baseDir);
|
|
325
|
+
}
|
|
326
|
+
if (actualResponse && typeof actualResponse === 'object' && actualResponse.schema) {
|
|
327
|
+
if (actualResponse.schema && actualResponse.schema.$ref) {
|
|
328
|
+
const refName = actualResponse.schema.$ref.split('/').pop();
|
|
329
|
+
if (refName)
|
|
330
|
+
collectAllReferencedSchemas(resolveRef(actualResponse.schema.$ref, spec, baseDir), refName);
|
|
331
|
+
}
|
|
332
|
+
else if (actualResponse.schema && typeof actualResponse.schema === 'object') {
|
|
333
|
+
const responseStructName = generateStructName(operationId, method, pathStr, `Response${code}`);
|
|
334
|
+
collectAllReferencedSchemas(actualResponse.schema, responseStructName);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return structs;
|
|
343
|
+
}
|
|
344
|
+
function getContentTypeAndBodyType(op, spec) {
|
|
345
|
+
var _a;
|
|
346
|
+
// Check if there are formData parameters
|
|
347
|
+
const hasFormData = (_a = op.parameters) === null || _a === void 0 ? void 0 : _a.some((param) => param && typeof param === 'object' && param.in === 'formData');
|
|
348
|
+
if (hasFormData) {
|
|
349
|
+
return { contentType: 'multipart/form-data', bodyType: 'form-data' };
|
|
350
|
+
}
|
|
351
|
+
// OpenAPI v2 determines content type from consumes array or defaults
|
|
352
|
+
const consumes = op.consumes || spec.consumes || ['application/json'];
|
|
353
|
+
const contentType = consumes[0] || 'application/json';
|
|
354
|
+
let bodyType = 'raw';
|
|
355
|
+
if (contentType === 'multipart/form-data') {
|
|
356
|
+
bodyType = 'form-data';
|
|
357
|
+
}
|
|
358
|
+
else if (contentType === 'application/x-www-form-urlencoded') {
|
|
359
|
+
bodyType = 'x-www-form-urlencoded';
|
|
360
|
+
}
|
|
361
|
+
return { contentType, bodyType };
|
|
362
|
+
}
|
|
363
|
+
function getHeadersForOperation(op, spec) {
|
|
364
|
+
var _a, _b;
|
|
365
|
+
const { contentType } = getContentTypeAndBodyType(op, spec);
|
|
366
|
+
// Use a Map to prevent duplicate headers
|
|
367
|
+
const headerMap = new Map();
|
|
368
|
+
// Add Content-Type header for POST/PUT/PATCH requests
|
|
369
|
+
if (['post', 'put', 'patch'].includes(((_a = op.method) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '')) {
|
|
370
|
+
headerMap.set('Content-Type', contentType);
|
|
371
|
+
}
|
|
372
|
+
// Add security headers based on the operation's security requirements
|
|
373
|
+
const security = op.security || spec.security || [];
|
|
374
|
+
for (const securityRequirement of security) {
|
|
375
|
+
for (const [schemeName, scopes] of Object.entries(securityRequirement)) {
|
|
376
|
+
const scheme = (_b = spec.securityDefinitions) === null || _b === void 0 ? void 0 : _b[schemeName]; // OpenAPI v2 uses securityDefinitions
|
|
377
|
+
if (scheme) {
|
|
378
|
+
if (scheme.type === 'basic') {
|
|
379
|
+
headerMap.set('Authorization', 'basic_auth');
|
|
380
|
+
}
|
|
381
|
+
else if (scheme.type === 'apiKey') {
|
|
382
|
+
if (scheme.in === 'header') {
|
|
383
|
+
headerMap.set(scheme.name, scheme.name.toLowerCase());
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
else if (scheme.type === 'oauth2') {
|
|
387
|
+
headerMap.set('Authorization', 'bearer_token');
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// Check if Authorization is used as a parameter but not defined in securityDefinitions
|
|
393
|
+
if (op.parameters) {
|
|
394
|
+
for (const param of op.parameters) {
|
|
395
|
+
if (param && typeof param === 'object' && param.in === 'header' && param.name === 'Authorization' && !headerMap.has('Authorization')) {
|
|
396
|
+
headerMap.set('Authorization', 'bearer_token');
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// Convert Map to object
|
|
401
|
+
const headers = {};
|
|
402
|
+
for (const [key, value] of headerMap.entries()) {
|
|
403
|
+
headers[key] = value;
|
|
404
|
+
}
|
|
405
|
+
return headers;
|
|
406
|
+
}
|
|
407
|
+
function extractParameters(op, spec, baseDir) {
|
|
408
|
+
const inputParams = [];
|
|
409
|
+
// Handle path, query, and header parameters
|
|
410
|
+
if (op.parameters) {
|
|
411
|
+
for (let param of op.parameters) {
|
|
412
|
+
// Resolve parameter references
|
|
413
|
+
if (param && typeof param === 'object' && param.$ref) {
|
|
414
|
+
param = resolveRef(param.$ref, spec, baseDir);
|
|
415
|
+
}
|
|
416
|
+
// Skip body and formData parameters, they are handled in extractRequestBody
|
|
417
|
+
if (param && typeof param === 'object' && (param.in === 'body' || param.in === 'formData')) {
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
const paramName = param && typeof param === 'object' ? param.name : '';
|
|
421
|
+
const paramSchema = param && typeof param === 'object' ? param.schema || {} : {};
|
|
422
|
+
const isRequired = param && typeof param === 'object' ? param.required !== false : false;
|
|
423
|
+
let type = 'STRING';
|
|
424
|
+
if (param && typeof param === 'object' && param.type) {
|
|
425
|
+
type = getTypeFromSchema({ type: param.type, format: param.format }, spec, baseDir);
|
|
426
|
+
}
|
|
427
|
+
else if (paramSchema && typeof paramSchema === 'object' && paramSchema.type) {
|
|
428
|
+
type = getTypeFromSchema(paramSchema, spec, baseDir);
|
|
429
|
+
}
|
|
430
|
+
// Build input parameter in v2.0.1 format
|
|
431
|
+
if (isRequired) {
|
|
432
|
+
// Simple form
|
|
433
|
+
const inputParam = {};
|
|
434
|
+
inputParam[paramName] = type;
|
|
435
|
+
inputParams.push(inputParam);
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
// Extended form
|
|
439
|
+
const inputParam = {};
|
|
440
|
+
inputParam[paramName] = {
|
|
441
|
+
TYPE: type,
|
|
442
|
+
REQUIRED: false,
|
|
443
|
+
};
|
|
444
|
+
inputParams.push(inputParam);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return inputParams;
|
|
449
|
+
}
|
|
450
|
+
function extractRequestBody(op, operationId, method, path, spec, baseDir) {
|
|
451
|
+
var _a;
|
|
452
|
+
const inputParams = [];
|
|
453
|
+
// OpenAPI v2 uses parameters with in: body
|
|
454
|
+
const bodyParam = (op.parameters || []).find((p) => p && typeof p === 'object' && p.in === 'body');
|
|
455
|
+
if (bodyParam) {
|
|
456
|
+
let type;
|
|
457
|
+
if (bodyParam && typeof bodyParam === 'object' && ((_a = bodyParam.schema) === null || _a === void 0 ? void 0 : _a.$ref)) {
|
|
458
|
+
type = getTypeFromSchema(bodyParam.schema, spec, baseDir);
|
|
459
|
+
}
|
|
460
|
+
else if (bodyParam && typeof bodyParam === 'object' && bodyParam.schema) {
|
|
461
|
+
// Inline schema - use generated struct name
|
|
462
|
+
const requestStructName = generateStructName(operationId, method, path, 'Request');
|
|
463
|
+
type = `STRUCT(${requestStructName})`;
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
type = 'ANY';
|
|
467
|
+
}
|
|
468
|
+
const isRequired = bodyParam && typeof bodyParam === 'object' ? bodyParam.required !== false : false;
|
|
469
|
+
if (isRequired) {
|
|
470
|
+
// Simple form
|
|
471
|
+
const inputParam = {};
|
|
472
|
+
inputParam.body = type;
|
|
473
|
+
inputParams.push(inputParam);
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
// Extended form
|
|
477
|
+
const inputParam = {};
|
|
478
|
+
inputParam.body = {
|
|
479
|
+
TYPE: type,
|
|
480
|
+
REQUIRED: false,
|
|
481
|
+
};
|
|
482
|
+
inputParams.push(inputParam);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
// Handle formData for multipart/form-data (OpenAPI v2)
|
|
486
|
+
if (op.parameters) {
|
|
487
|
+
for (const param of op.parameters) {
|
|
488
|
+
if (param && typeof param === 'object' && param.in === 'formData') {
|
|
489
|
+
const type = param.type === 'file' ? 'STRING' : getTypeFromSchema({ type: param.type, format: param.format }, spec, baseDir);
|
|
490
|
+
const isRequired = param.required !== false;
|
|
491
|
+
const hasDefault = param.default !== undefined;
|
|
492
|
+
const inputParam = {};
|
|
493
|
+
if (isRequired && !hasDefault) {
|
|
494
|
+
// Simple form
|
|
495
|
+
inputParam[param.name] = type;
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
// Extended form
|
|
499
|
+
inputParam[param.name] = {
|
|
500
|
+
TYPE: type,
|
|
501
|
+
REQUIRED: isRequired,
|
|
502
|
+
};
|
|
503
|
+
if (hasDefault) {
|
|
504
|
+
inputParam[param.name].DEFAULT = param.default;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
inputParams.push(inputParam);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return inputParams;
|
|
512
|
+
}
|
|
513
|
+
function extractResponses(op, operationId, method, path, spec, baseDir) {
|
|
514
|
+
var _a;
|
|
515
|
+
const returns = [];
|
|
516
|
+
// Only include success responses (2xx) in RETURNS section
|
|
517
|
+
// Error responses go in ERRORS section
|
|
518
|
+
for (const [code, response] of Object.entries(op.responses || {})) {
|
|
519
|
+
const statusCode = parseInt(code);
|
|
520
|
+
// Only process 2xx success responses
|
|
521
|
+
if (isNaN(statusCode) || statusCode < 200 || statusCode >= 300) {
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
// Handle response references (OpenAPI v2)
|
|
525
|
+
let actualResponse = response;
|
|
526
|
+
if (response && typeof response === 'object' && response.$ref) {
|
|
527
|
+
actualResponse = resolveRef(response.$ref, spec, baseDir);
|
|
528
|
+
}
|
|
529
|
+
let returnType = null;
|
|
530
|
+
// 204 No Content - no response body
|
|
531
|
+
if (code === '204') {
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
if (actualResponse && typeof actualResponse === 'object' && actualResponse.schema) {
|
|
535
|
+
const schema = actualResponse.schema;
|
|
536
|
+
if (schema.$ref) {
|
|
537
|
+
returnType = getTypeFromSchema(schema, spec, baseDir);
|
|
538
|
+
}
|
|
539
|
+
else if (schema.type === 'array') {
|
|
540
|
+
if ((_a = schema.items) === null || _a === void 0 ? void 0 : _a.$ref) {
|
|
541
|
+
returnType = getTypeFromSchema(schema, spec, baseDir);
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
returnType = getTypeFromSchema(schema, spec, baseDir);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
else if (schema.type === 'object') {
|
|
548
|
+
// Inline schema - use generated struct name
|
|
549
|
+
const responseStructName = generateStructName(operationId, method, path, `Response${code}`);
|
|
550
|
+
returnType = `STRUCT(${responseStructName})`;
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
returnType = getTypeFromSchema(schema, spec, baseDir);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
// No schema - might be a header-only response
|
|
558
|
+
const statusCode = parseInt(code);
|
|
559
|
+
if (statusCode >= 200 && statusCode < 300) {
|
|
560
|
+
continue; // Skip void success responses
|
|
561
|
+
}
|
|
562
|
+
returnType = 'ANY'; // Error responses without schema
|
|
563
|
+
}
|
|
564
|
+
// Only add to RETURNS if there's actually a return type
|
|
565
|
+
if (returnType) {
|
|
566
|
+
// Generate descriptive RETURNVAR name based on response code and operation
|
|
567
|
+
const returnVarName = (0, response_utils_1.generateReturnVarName)(operationId, code);
|
|
568
|
+
const returnItem = {
|
|
569
|
+
RETURNTYPE: returnType,
|
|
570
|
+
RETURNVAR: returnVarName,
|
|
571
|
+
};
|
|
572
|
+
// Check for pagination hints in response schema
|
|
573
|
+
if (actualResponse && typeof actualResponse === 'object' && actualResponse.schema) {
|
|
574
|
+
const schema = actualResponse.schema;
|
|
575
|
+
const resolvedSchema = schema.$ref ? resolveRef(schema.$ref, spec, baseDir) : schema;
|
|
576
|
+
if (resolvedSchema && resolvedSchema.properties) {
|
|
577
|
+
// Look for common pagination fields
|
|
578
|
+
if (resolvedSchema.properties.next_cursor || resolvedSchema.properties.cursor) {
|
|
579
|
+
returnItem.PAGINATION = {
|
|
580
|
+
TYPE: 'cursor',
|
|
581
|
+
CURSOR_FIELD: resolvedSchema.properties.next_cursor ? 'next_cursor' : 'cursor',
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
else if (resolvedSchema.properties.offset !== undefined || resolvedSchema.properties.skip !== undefined) {
|
|
585
|
+
returnItem.PAGINATION = {
|
|
586
|
+
TYPE: 'offset',
|
|
587
|
+
OFFSET_FIELD: resolvedSchema.properties.offset !== undefined ? 'offset' : 'skip',
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
else if (resolvedSchema.properties.page !== undefined || resolvedSchema.properties.pageNumber !== undefined) {
|
|
591
|
+
returnItem.PAGINATION = {
|
|
592
|
+
TYPE: 'page',
|
|
593
|
+
PAGE_SIZE_FIELD: resolvedSchema.properties.pageSize || 'limit',
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
returns.push(returnItem);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return returns;
|
|
602
|
+
}
|
|
603
|
+
function extractErrors(op, spec, baseDir) {
|
|
604
|
+
const errors = [];
|
|
605
|
+
// Extract error responses (4xx, 5xx)
|
|
606
|
+
for (const [code, response] of Object.entries(op.responses || {})) {
|
|
607
|
+
const statusCode = parseInt(code);
|
|
608
|
+
if (isNaN(statusCode) && code !== 'default')
|
|
609
|
+
continue;
|
|
610
|
+
if (statusCode >= 400 || code === 'default') {
|
|
611
|
+
// Handle response references
|
|
612
|
+
let actualResponse = response;
|
|
613
|
+
if (response && typeof response === 'object' && response.$ref) {
|
|
614
|
+
actualResponse = resolveRef(response.$ref, spec, baseDir);
|
|
615
|
+
}
|
|
616
|
+
let errorType = constants_1.TYPE_ANY;
|
|
617
|
+
let when = `HTTP ${code}`;
|
|
618
|
+
if (actualResponse && typeof actualResponse === 'object' && actualResponse.schema) {
|
|
619
|
+
const schema = actualResponse.schema;
|
|
620
|
+
if (schema.$ref) {
|
|
621
|
+
errorType = getTypeFromSchema(schema, spec, baseDir);
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
// Inline error schema - generate a struct name
|
|
625
|
+
const errorStructName = `Error${code}`;
|
|
626
|
+
errorType = `STRUCT(${errorStructName})`;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
// Generate descriptive WHEN clause with HTTP status code
|
|
630
|
+
when = (0, response_utils_1.generateErrorWhen)(actualResponse, code);
|
|
631
|
+
errors.push({
|
|
632
|
+
TYPE: errorType,
|
|
633
|
+
WHEN: when,
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return errors;
|
|
638
|
+
}
|
|
639
|
+
function generateMethodAlias(operationId, method, path) {
|
|
640
|
+
if (operationId) {
|
|
641
|
+
// Convert operationId to kebab-case if needed
|
|
642
|
+
return operationId.replace(/_/g, '-').toLowerCase();
|
|
643
|
+
}
|
|
644
|
+
// Generate from path and method
|
|
645
|
+
const pathParts = path.replace(/[\/{}]/g, '-').replace(/^-|-$/g, '');
|
|
646
|
+
return `${method.toLowerCase()}-${pathParts}`;
|
|
647
|
+
}
|
|
648
|
+
function extractMethods(spec, baseDir) {
|
|
649
|
+
var _a;
|
|
650
|
+
// OpenAPI v2 constructs base URL from schemes, host, and basePath
|
|
651
|
+
const scheme = ((_a = spec.schemes) === null || _a === void 0 ? void 0 : _a[0]) || constants_1.DEFAULT_HTTP_SCHEME;
|
|
652
|
+
const host = spec.host || '';
|
|
653
|
+
const basePath = spec.basePath || '';
|
|
654
|
+
const base = `${scheme}://${host}${basePath}`;
|
|
655
|
+
const methods = {};
|
|
656
|
+
// Valid HTTP methods
|
|
657
|
+
const validMethods = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'];
|
|
658
|
+
// Check if paths exists and is an object
|
|
659
|
+
if (!spec.paths || typeof spec.paths !== 'object') {
|
|
660
|
+
return methods;
|
|
661
|
+
}
|
|
662
|
+
for (const [pathStr, pathMethods] of Object.entries(spec.paths)) {
|
|
663
|
+
// Handle path-level parameters (OpenAPI v2)
|
|
664
|
+
const pathLevelParams = pathMethods.parameters || [];
|
|
665
|
+
for (const [method, op] of Object.entries(pathMethods)) {
|
|
666
|
+
// Skip extension fields (x-*) and only process valid HTTP methods
|
|
667
|
+
if (method.startsWith('x-') || !validMethods.includes(method.toLowerCase())) {
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
const operationId = op.operationId || `${method}-${pathStr.replace(/[\/{}]/g, '-')}`;
|
|
671
|
+
const alias = generateMethodAlias(operationId, method, pathStr);
|
|
672
|
+
const summary = generateSummary(op, method, pathStr);
|
|
673
|
+
const endpoint = pathStr;
|
|
674
|
+
// Merge path-level and operation-level parameters
|
|
675
|
+
const allParams = [...pathLevelParams, ...(op.parameters || [])];
|
|
676
|
+
const opWithMergedParams = Object.assign(Object.assign({}, op), { parameters: allParams });
|
|
677
|
+
const { bodyType } = getContentTypeAndBodyType(opWithMergedParams, spec);
|
|
678
|
+
const headers = getHeadersForOperation(opWithMergedParams, spec);
|
|
679
|
+
const pathQueryHeaderParams = extractParameters(opWithMergedParams, spec, baseDir);
|
|
680
|
+
const bodyParams = extractRequestBody(opWithMergedParams, operationId, method, pathStr, spec, baseDir);
|
|
681
|
+
const inputParams = [...pathQueryHeaderParams, ...bodyParams];
|
|
682
|
+
const returns = extractResponses(opWithMergedParams, operationId, method, pathStr, spec, baseDir);
|
|
683
|
+
const errors = extractErrors(opWithMergedParams, spec, baseDir);
|
|
684
|
+
// Build method in v2.0.1 format
|
|
685
|
+
const methodDef = {
|
|
686
|
+
SUMMARY: summary,
|
|
687
|
+
};
|
|
688
|
+
// Add DESC if description exists
|
|
689
|
+
if (op.description) {
|
|
690
|
+
methodDef.DESC = op.description;
|
|
691
|
+
}
|
|
692
|
+
// HTTP section (mandatory for API methods)
|
|
693
|
+
methodDef.HTTP = {
|
|
694
|
+
METHOD: method.toUpperCase(),
|
|
695
|
+
ENDPOINT: endpoint,
|
|
696
|
+
HEADERS: headers,
|
|
697
|
+
};
|
|
698
|
+
if (bodyType !== constants_1.BODYTYPE_RAW) {
|
|
699
|
+
methodDef.HTTP.BODYTYPE = bodyType;
|
|
700
|
+
}
|
|
701
|
+
// EXECUTION section (mandatory)
|
|
702
|
+
methodDef.EXECUTION = {
|
|
703
|
+
MODE: constants_1.EXECUTION_MODE_ASYNC, // HTTP methods default to async
|
|
704
|
+
};
|
|
705
|
+
// ASYNC section (required when MODE = async)
|
|
706
|
+
const resultType = returns.length > 0 ? returns[0].RETURNTYPE : constants_1.TYPE_VOID;
|
|
707
|
+
methodDef.ASYNC = {
|
|
708
|
+
RETURNS: constants_1.ASYNC_RETURNS_RESULT,
|
|
709
|
+
RESULT: {
|
|
710
|
+
TYPE: resultType,
|
|
711
|
+
},
|
|
712
|
+
};
|
|
713
|
+
// INPUTS section (optional)
|
|
714
|
+
if (inputParams.length > 0) {
|
|
715
|
+
methodDef.INPUTS = inputParams;
|
|
716
|
+
}
|
|
717
|
+
// RETURNS section (optional - omit for void)
|
|
718
|
+
if (returns.length > 0) {
|
|
719
|
+
methodDef.RETURNS = returns;
|
|
720
|
+
}
|
|
721
|
+
// ERRORS section (optional)
|
|
722
|
+
if (errors.length > 0) {
|
|
723
|
+
methodDef.ERRORS = errors;
|
|
724
|
+
}
|
|
725
|
+
methods[alias] = methodDef;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
return methods;
|
|
729
|
+
}
|
|
730
|
+
function extractSecurityDefaults(spec) {
|
|
731
|
+
var _a;
|
|
732
|
+
const defs = {};
|
|
733
|
+
const securityDefinitions = spec.securityDefinitions || {}; // OpenAPI v2 uses securityDefinitions
|
|
734
|
+
for (const [name, scheme] of Object.entries(securityDefinitions)) {
|
|
735
|
+
if (scheme && typeof scheme === 'object' && scheme.type === 'basic') {
|
|
736
|
+
defs.basic_auth = 'Basic <BASE64>';
|
|
737
|
+
}
|
|
738
|
+
else if (scheme && typeof scheme === 'object' && scheme.type === 'apiKey') {
|
|
739
|
+
if (scheme.in === 'header') {
|
|
740
|
+
defs[scheme.name.toLowerCase()] = `<${scheme.name.toUpperCase()}>`;
|
|
741
|
+
}
|
|
742
|
+
else if (scheme.in === 'query') {
|
|
743
|
+
defs[`query_${scheme.name.toLowerCase()}`] = `<${scheme.name.toUpperCase()}>`;
|
|
744
|
+
}
|
|
745
|
+
else if (scheme.in === 'cookie') {
|
|
746
|
+
defs[`cookie_${scheme.name.toLowerCase()}`] = `<${scheme.name.toUpperCase()}>`;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
else if (scheme && typeof scheme === 'object' && scheme.type === 'oauth2') {
|
|
750
|
+
defs.bearer_token = 'BEARER <ACCESS_TOKEN>';
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
// Add base URL (OpenAPI v2 constructs from schemes, host, basePath)
|
|
754
|
+
const scheme = ((_a = spec.schemes) === null || _a === void 0 ? void 0 : _a[0]) || 'https';
|
|
755
|
+
const host = spec.host || '';
|
|
756
|
+
const basePath = spec.basePath || '';
|
|
757
|
+
const baseUrl = `${scheme}://${host}${basePath}`;
|
|
758
|
+
defs.w_base_url = baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
759
|
+
return defs;
|
|
760
|
+
}
|
|
761
|
+
function generateWrekenfile(spec, baseDir) {
|
|
762
|
+
if (!spec || typeof spec !== 'object') {
|
|
763
|
+
throw new Error("Argument 'spec' is required and must be an object");
|
|
764
|
+
}
|
|
765
|
+
if (!baseDir || typeof baseDir !== 'string') {
|
|
766
|
+
throw new Error("Argument 'baseDir' is required and must be a string");
|
|
767
|
+
}
|
|
768
|
+
const defaults = extractSecurityDefaults(spec);
|
|
769
|
+
const methods = extractMethods(spec, baseDir);
|
|
770
|
+
const structs = extractStructs(spec, baseDir);
|
|
771
|
+
const wrekenfile = {
|
|
772
|
+
VERSION: constants_1.WREKENFILE_VERSION,
|
|
773
|
+
};
|
|
774
|
+
// Add DEFAULTS if we have any
|
|
775
|
+
if (Object.keys(defaults).length > 0) {
|
|
776
|
+
wrekenfile.DEFAULTS = defaults;
|
|
777
|
+
}
|
|
778
|
+
// Add METHODS (mandatory)
|
|
779
|
+
wrekenfile.METHODS = methods;
|
|
780
|
+
// Add STRUCTS if we have any
|
|
781
|
+
if (Object.keys(structs).length > 0) {
|
|
782
|
+
wrekenfile.STRUCTS = structs;
|
|
783
|
+
}
|
|
784
|
+
let yamlString = (0, js_yaml_1.dump)(wrekenfile, {
|
|
785
|
+
indent: 2,
|
|
786
|
+
lineWidth: -1,
|
|
787
|
+
noRefs: true,
|
|
788
|
+
sortKeys: false,
|
|
789
|
+
quotingType: '"',
|
|
790
|
+
forceQuotes: false,
|
|
791
|
+
});
|
|
792
|
+
// Post-process to remove quotes from type strings
|
|
793
|
+
// Remove quotes from STRUCT(...) values
|
|
794
|
+
yamlString = yamlString.replace(/(TYPE|RETURNTYPE):\s*"STRUCT\(([^)]+)\)"/g, '$1: STRUCT($2)');
|
|
795
|
+
// Remove quotes from array types - use YAML block scalar syntax (|-) to avoid quotes
|
|
796
|
+
// YAML requires quotes for values starting with [], so we use block scalar format
|
|
797
|
+
// Handle both regular lines and array items (lines starting with -)
|
|
798
|
+
yamlString = yamlString.replace(/^(\s+)(-?\s*)(TYPE|RETURNTYPE):\s*['"](\[\]STRUCT\([^)]+\)|\[\][A-Z]+)['"]/gm, (match, indent, arrayPrefix, key, value) => {
|
|
799
|
+
// Use block scalar format: key: |-\n value (requires newline after |-)
|
|
800
|
+
return `${indent}${arrayPrefix}${key}: |-\n${indent}${arrayPrefix.replace(/-/, ' ')} ${value}`;
|
|
801
|
+
});
|
|
802
|
+
yamlString = (0, yaml_utils_1.cleanYaml)(yamlString);
|
|
803
|
+
(0, yaml_utils_1.checkYamlForHiddenChars)(yamlString);
|
|
804
|
+
(0, yaml_utils_1.validateYaml)(yamlString);
|
|
805
|
+
return yamlString;
|
|
806
|
+
}
|