wrekenfile-converter 2.0.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 +185 -0
- package/dist/example-usage.d.ts +4 -0
- package/dist/example-usage.js +57 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +33 -0
- package/dist/mini-wrekenfile-generator.d.ts +18 -0
- package/dist/mini-wrekenfile-generator.js +246 -0
- package/dist/openapi-to-wreken.d.ts +2 -0
- package/dist/openapi-to-wreken.js +563 -0
- package/dist/openapi-v2-to-wrekenfile.d.ts +2 -0
- package/dist/openapi-v2-to-wrekenfile.js +467 -0
- package/dist/postman-to-wrekenfile.d.ts +11 -0
- package/dist/postman-to-wrekenfile.js +530 -0
- package/dist/wrekenfile-validator.d.ts +17 -0
- package/dist/wrekenfile-validator.js +653 -0
- package/package.json +78 -0
- package/wrekenfile.md +726 -0
|
@@ -0,0 +1,563 @@
|
|
|
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-wreken.ts
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const js_yaml_1 = require("js-yaml");
|
|
41
|
+
const externalRefCache = {};
|
|
42
|
+
function mapType(type, format) {
|
|
43
|
+
if (format === 'uuid')
|
|
44
|
+
return 'UUID';
|
|
45
|
+
if (format === 'date-time')
|
|
46
|
+
return 'TIMESTAMP';
|
|
47
|
+
if (format === 'binary')
|
|
48
|
+
return 'STRING'; // File uploads
|
|
49
|
+
const t = type === null || type === void 0 ? void 0 : type.toLowerCase();
|
|
50
|
+
if (t === 'string')
|
|
51
|
+
return 'STRING';
|
|
52
|
+
if (t === 'integer' || t === 'int')
|
|
53
|
+
return 'INT';
|
|
54
|
+
if (t === 'number')
|
|
55
|
+
return 'FLOAT';
|
|
56
|
+
if (t === 'boolean')
|
|
57
|
+
return 'BOOL';
|
|
58
|
+
return 'ANY';
|
|
59
|
+
}
|
|
60
|
+
function generateDesc(op, method, path) {
|
|
61
|
+
if (op.summary)
|
|
62
|
+
return op.summary;
|
|
63
|
+
if (op.description)
|
|
64
|
+
return op.description;
|
|
65
|
+
if (op.operationId)
|
|
66
|
+
return `Perform operation ${op.operationId}`;
|
|
67
|
+
const verb = {
|
|
68
|
+
get: 'Fetch',
|
|
69
|
+
post: 'Create',
|
|
70
|
+
put: 'Update',
|
|
71
|
+
delete: 'Delete',
|
|
72
|
+
patch: 'Modify',
|
|
73
|
+
}[method.toLowerCase()] || 'Call';
|
|
74
|
+
const entity = path.split('/').filter(p => p && !p.startsWith('{')).pop() || 'resource';
|
|
75
|
+
return `${verb} ${entity}`;
|
|
76
|
+
}
|
|
77
|
+
function resolveRef(ref, spec, baseDir) {
|
|
78
|
+
if (ref.startsWith('#/')) {
|
|
79
|
+
return ref.split('/').slice(1).reduce((o, k) => o === null || o === void 0 ? void 0 : o[k], spec);
|
|
80
|
+
}
|
|
81
|
+
const [filePath, internal] = ref.split('#');
|
|
82
|
+
const fullPath = path.resolve(baseDir, filePath);
|
|
83
|
+
if (!externalRefCache[fullPath]) {
|
|
84
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
85
|
+
externalRefCache[fullPath] = (0, js_yaml_1.load)(content);
|
|
86
|
+
}
|
|
87
|
+
return internal
|
|
88
|
+
? internal.split('/').slice(1).reduce((o, k) => o === null || o === void 0 ? void 0 : o[k], externalRefCache[fullPath])
|
|
89
|
+
: externalRefCache[fullPath];
|
|
90
|
+
}
|
|
91
|
+
function getTypeFromSchema(schema, spec, baseDir) {
|
|
92
|
+
var _a, _b;
|
|
93
|
+
if (schema.$ref) {
|
|
94
|
+
const resolvedSchema = resolveRef(schema.$ref, spec, baseDir);
|
|
95
|
+
// Check if the resolved schema is a simple type
|
|
96
|
+
if (resolvedSchema.type && resolvedSchema.type !== 'object') {
|
|
97
|
+
return mapType(resolvedSchema.type, resolvedSchema.format);
|
|
98
|
+
}
|
|
99
|
+
// It's a complex type, use STRUCT
|
|
100
|
+
return `STRUCT(${schema.$ref.split('/').pop()})`;
|
|
101
|
+
}
|
|
102
|
+
if (schema.type === 'array') {
|
|
103
|
+
if ((_a = schema.items) === null || _a === void 0 ? void 0 : _a.$ref) {
|
|
104
|
+
const resolvedItems = resolveRef(schema.items.$ref, spec, baseDir);
|
|
105
|
+
if (resolvedItems.type && resolvedItems.type !== 'object') {
|
|
106
|
+
return `[]${mapType(resolvedItems.type, resolvedItems.format)}`;
|
|
107
|
+
}
|
|
108
|
+
return `[]STRUCT(${schema.items.$ref.split('/').pop()})`;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return `[]${mapType((_b = schema.items) === null || _b === void 0 ? void 0 : _b.type)}`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (schema.type && schema.type !== 'object') {
|
|
115
|
+
return mapType(schema.type, schema.format);
|
|
116
|
+
}
|
|
117
|
+
return 'ANY';
|
|
118
|
+
}
|
|
119
|
+
function parseSchema(name, schema, spec, baseDir, depth = 0) {
|
|
120
|
+
var _a;
|
|
121
|
+
if (depth > 3)
|
|
122
|
+
return [];
|
|
123
|
+
if (schema.$ref)
|
|
124
|
+
return parseSchema(name, resolveRef(schema.$ref, spec, baseDir), spec, baseDir, depth + 1);
|
|
125
|
+
if (schema.allOf)
|
|
126
|
+
return schema.allOf.flatMap((s) => parseSchema(name, s, spec, baseDir, depth + 1));
|
|
127
|
+
if (schema.oneOf || schema.anyOf) {
|
|
128
|
+
return [{
|
|
129
|
+
name: 'variant',
|
|
130
|
+
type: `STRUCT(${name}_Union)`,
|
|
131
|
+
required: 'FALSE'
|
|
132
|
+
}];
|
|
133
|
+
}
|
|
134
|
+
const fields = [];
|
|
135
|
+
if ((_a = schema.discriminator) === null || _a === void 0 ? void 0 : _a.propertyName) {
|
|
136
|
+
fields.push({
|
|
137
|
+
name: schema.discriminator.propertyName,
|
|
138
|
+
type: 'STRING',
|
|
139
|
+
required: 'TRUE',
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
// Handle simple types (string, integer, etc.) - these should not create structs
|
|
143
|
+
if (schema.type && schema.type !== 'object') {
|
|
144
|
+
// For simple types, return empty array to indicate no struct fields
|
|
145
|
+
// The type will be used directly as a primitive
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
if (schema.type === 'object' && schema.properties) {
|
|
149
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
150
|
+
const type = getTypeFromSchema(prop, spec, baseDir);
|
|
151
|
+
// Use the required field from the OpenAPI spec
|
|
152
|
+
const required = (schema.required || []).includes(key) ? 'TRUE' : 'FALSE';
|
|
153
|
+
fields.push({
|
|
154
|
+
name: key,
|
|
155
|
+
type,
|
|
156
|
+
required,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return fields;
|
|
161
|
+
}
|
|
162
|
+
function generateStructName(operationId, method, path, suffix) {
|
|
163
|
+
if (operationId) {
|
|
164
|
+
return `${operationId}${suffix}`;
|
|
165
|
+
}
|
|
166
|
+
// Generate from path and method
|
|
167
|
+
const pathParts = path.replace(/[\/{}]/g, '_').replace(/^_|_$/g, '');
|
|
168
|
+
return `${method}_${pathParts}${suffix}`;
|
|
169
|
+
}
|
|
170
|
+
function extractStructs(spec, baseDir) {
|
|
171
|
+
var _a, _b;
|
|
172
|
+
const structs = {};
|
|
173
|
+
const schemas = ((_a = spec.components) === null || _a === void 0 ? void 0 : _a.schemas) || {};
|
|
174
|
+
// Helper to recursively collect all referenced schemas, traversing all properties, arrays, and combiners
|
|
175
|
+
function collectAllReferencedSchemas(schema, name) {
|
|
176
|
+
if (!name || structs[name])
|
|
177
|
+
return;
|
|
178
|
+
const resolved = schema.$ref ? resolveRef(schema.$ref, spec, baseDir) : schema;
|
|
179
|
+
const fields = parseSchema(name, resolved, spec, baseDir);
|
|
180
|
+
structs[name] = fields;
|
|
181
|
+
// Traverse all properties
|
|
182
|
+
if (resolved.type === 'object' && resolved.properties) {
|
|
183
|
+
for (const [propName, prop] of Object.entries(resolved.properties)) {
|
|
184
|
+
if (prop.$ref) {
|
|
185
|
+
const refName = prop.$ref.split('/').pop();
|
|
186
|
+
if (refName)
|
|
187
|
+
collectAllReferencedSchemas(resolveRef(prop.$ref, spec, baseDir), refName);
|
|
188
|
+
}
|
|
189
|
+
else if (prop.type === 'array' && prop.items) {
|
|
190
|
+
if (prop.items.$ref) {
|
|
191
|
+
const refName = prop.items.$ref.split('/').pop();
|
|
192
|
+
if (refName)
|
|
193
|
+
collectAllReferencedSchemas(resolveRef(prop.items.$ref, spec, baseDir), refName);
|
|
194
|
+
}
|
|
195
|
+
else if (prop.items.type === 'object' || prop.items.properties || prop.items.allOf || prop.items.oneOf || prop.items.anyOf) {
|
|
196
|
+
collectAllReferencedSchemas(prop.items, name + '_' + propName + '_Item');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else if (prop.type === 'object' || prop.properties || prop.allOf || prop.oneOf || prop.anyOf) {
|
|
200
|
+
collectAllReferencedSchemas(prop, name + '_' + propName);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Traverse array items at root
|
|
205
|
+
if (resolved.type === 'array' && resolved.items) {
|
|
206
|
+
if (resolved.items.$ref) {
|
|
207
|
+
const refName = resolved.items.$ref.split('/').pop();
|
|
208
|
+
if (refName)
|
|
209
|
+
collectAllReferencedSchemas(resolveRef(resolved.items.$ref, spec, baseDir), refName);
|
|
210
|
+
}
|
|
211
|
+
else if (resolved.items.type === 'object' || resolved.items.properties || resolved.items.allOf || resolved.items.oneOf || resolved.items.anyOf) {
|
|
212
|
+
collectAllReferencedSchemas(resolved.items, name + '_Item');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// Traverse allOf/oneOf/anyOf
|
|
216
|
+
for (const combiner of ['allOf', 'oneOf', 'anyOf']) {
|
|
217
|
+
if (Array.isArray(resolved[combiner])) {
|
|
218
|
+
for (const subSchema of resolved[combiner]) {
|
|
219
|
+
if (subSchema.$ref) {
|
|
220
|
+
const refName = subSchema.$ref.split('/').pop();
|
|
221
|
+
if (refName)
|
|
222
|
+
collectAllReferencedSchemas(resolveRef(subSchema.$ref, spec, baseDir), refName);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
collectAllReferencedSchemas(subSchema, name + '_' + combiner);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Extract schemas from components
|
|
232
|
+
for (const name in schemas) {
|
|
233
|
+
collectAllReferencedSchemas(schemas[name], name);
|
|
234
|
+
const schema = schemas[name];
|
|
235
|
+
if (schema.oneOf || schema.anyOf) {
|
|
236
|
+
structs[`${name}_Union`] = [{ name: 'value', type: 'ANY', required: 'FALSE' }];
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// Extract inline schemas from operations
|
|
240
|
+
for (const [pathStr, methods] of Object.entries(spec.paths)) {
|
|
241
|
+
for (const [method, op] of Object.entries(methods)) {
|
|
242
|
+
const operationId = op.operationId || `${method}-${pathStr.replace(/[\/{}]/g, '-')}`;
|
|
243
|
+
// Extract request body schemas
|
|
244
|
+
if ((_b = op.requestBody) === null || _b === void 0 ? void 0 : _b.content) {
|
|
245
|
+
for (const [contentType, content] of Object.entries(op.requestBody.content)) {
|
|
246
|
+
if (content.schema) {
|
|
247
|
+
if (content.schema.$ref) {
|
|
248
|
+
const refName = content.schema.$ref.split('/').pop();
|
|
249
|
+
if (refName)
|
|
250
|
+
collectAllReferencedSchemas(resolveRef(content.schema.$ref, spec, baseDir), refName);
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
const requestStructName = generateStructName(operationId, method, pathStr, 'Request');
|
|
254
|
+
collectAllReferencedSchemas(content.schema, requestStructName);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Extract response schemas
|
|
260
|
+
if (op.responses) {
|
|
261
|
+
for (const [code, response] of Object.entries(op.responses)) {
|
|
262
|
+
if (response.content) {
|
|
263
|
+
for (const [contentType, content] of Object.entries(response.content)) {
|
|
264
|
+
if (content.schema) {
|
|
265
|
+
if (content.schema.$ref) {
|
|
266
|
+
const refName = content.schema.$ref.split('/').pop();
|
|
267
|
+
if (refName)
|
|
268
|
+
collectAllReferencedSchemas(resolveRef(content.schema.$ref, spec, baseDir), refName);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
const responseStructName = generateStructName(operationId, method, pathStr, `Response${code}`);
|
|
272
|
+
collectAllReferencedSchemas(content.schema, responseStructName);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return structs;
|
|
282
|
+
}
|
|
283
|
+
function getContentTypeAndBodyType(op) {
|
|
284
|
+
const requestBody = op.requestBody;
|
|
285
|
+
if (!(requestBody === null || requestBody === void 0 ? void 0 : requestBody.content)) {
|
|
286
|
+
return { contentType: 'application/json', bodyType: 'RAW' };
|
|
287
|
+
}
|
|
288
|
+
const contentTypes = Object.keys(requestBody.content);
|
|
289
|
+
const contentType = contentTypes[0] || 'application/json';
|
|
290
|
+
let bodyType = 'RAW';
|
|
291
|
+
if (contentType === 'multipart/form-data') {
|
|
292
|
+
bodyType = 'FORM';
|
|
293
|
+
}
|
|
294
|
+
else if (contentType === 'application/x-www-form-urlencoded') {
|
|
295
|
+
bodyType = 'FORM';
|
|
296
|
+
}
|
|
297
|
+
else if (contentType === 'application/json') {
|
|
298
|
+
bodyType = 'JSON';
|
|
299
|
+
}
|
|
300
|
+
return { contentType, bodyType };
|
|
301
|
+
}
|
|
302
|
+
function getHeadersForOperation(op, spec) {
|
|
303
|
+
var _a, _b;
|
|
304
|
+
const { contentType } = getContentTypeAndBodyType(op);
|
|
305
|
+
// Use a Map to prevent duplicate headers
|
|
306
|
+
const headerMap = new Map();
|
|
307
|
+
const cookieMap = new Map();
|
|
308
|
+
// Add Content-Type header
|
|
309
|
+
headerMap.set('Content-Type', contentType);
|
|
310
|
+
// Add security headers based on the operation's security requirements
|
|
311
|
+
const security = op.security || spec.security || [];
|
|
312
|
+
for (const securityRequirement of security) {
|
|
313
|
+
for (const [schemeName, scopes] of Object.entries(securityRequirement)) {
|
|
314
|
+
const scheme = (_b = (_a = spec.components) === null || _a === void 0 ? void 0 : _a.securitySchemes) === null || _b === void 0 ? void 0 : _b[schemeName];
|
|
315
|
+
if (scheme) {
|
|
316
|
+
if (scheme.type === 'http') {
|
|
317
|
+
if (scheme.scheme === 'bearer') {
|
|
318
|
+
headerMap.set('Authorization', 'bearer_token');
|
|
319
|
+
}
|
|
320
|
+
else if (scheme.scheme === 'basic') {
|
|
321
|
+
headerMap.set('Authorization', 'basic_auth');
|
|
322
|
+
}
|
|
323
|
+
else if (scheme.scheme === 'digest') {
|
|
324
|
+
headerMap.set('Authorization', 'digest_auth');
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
// Unknown HTTP auth scheme
|
|
328
|
+
headerMap.set('Authorization', `<${scheme.scheme}_auth>`);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
else if (scheme.type === 'apiKey') {
|
|
332
|
+
if (scheme.in === 'header') {
|
|
333
|
+
headerMap.set(scheme.name, scheme.name.toLowerCase());
|
|
334
|
+
}
|
|
335
|
+
else if (scheme.in === 'query') {
|
|
336
|
+
// Query params are not headers, but we can note them for completeness
|
|
337
|
+
// (Wrekenfile may not support query auth directly in HEADERS)
|
|
338
|
+
headerMap.set(`[QUERY] ${scheme.name}`, scheme.name.toLowerCase());
|
|
339
|
+
}
|
|
340
|
+
else if (scheme.in === 'cookie') {
|
|
341
|
+
cookieMap.set(scheme.name, `<${scheme.name.toUpperCase()}>`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
else if (scheme.type === 'oauth2') {
|
|
345
|
+
headerMap.set('Authorization', 'bearer_token');
|
|
346
|
+
}
|
|
347
|
+
else if (scheme.type === 'openIdConnect') {
|
|
348
|
+
headerMap.set('Authorization', 'id_token');
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// Convert Map back to array of objects
|
|
354
|
+
const headers = [];
|
|
355
|
+
for (const [key, value] of headerMap.entries()) {
|
|
356
|
+
headers.push({ [key]: value });
|
|
357
|
+
}
|
|
358
|
+
// Add cookies as a special header if present
|
|
359
|
+
if (cookieMap.size > 0) {
|
|
360
|
+
const cookieHeader = Array.from(cookieMap.entries()).map(([k, v]) => `${k}=${v}`).join('; ');
|
|
361
|
+
headers.push({ Cookie: cookieHeader });
|
|
362
|
+
}
|
|
363
|
+
return headers;
|
|
364
|
+
}
|
|
365
|
+
function extractParameters(op, spec, baseDir) {
|
|
366
|
+
const inputParams = [];
|
|
367
|
+
// Handle path, query, and header parameters
|
|
368
|
+
for (let param of op.parameters || []) {
|
|
369
|
+
// Resolve $ref if present
|
|
370
|
+
if (param.$ref) {
|
|
371
|
+
param = resolveRef(param.$ref, spec, baseDir);
|
|
372
|
+
}
|
|
373
|
+
const paramType = param.in || 'query';
|
|
374
|
+
const paramName = param.name;
|
|
375
|
+
const paramSchema = param.schema || {};
|
|
376
|
+
const paramRequired = param.required ? 'TRUE' : 'FALSE';
|
|
377
|
+
let type = 'STRING';
|
|
378
|
+
if (paramSchema.type) {
|
|
379
|
+
type = mapType(paramSchema.type, paramSchema.format);
|
|
380
|
+
}
|
|
381
|
+
inputParams.push({
|
|
382
|
+
name: paramName,
|
|
383
|
+
type,
|
|
384
|
+
required: paramRequired,
|
|
385
|
+
location: paramType.toUpperCase(), // PATH, QUERY, HEADER
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
return inputParams;
|
|
389
|
+
}
|
|
390
|
+
function extractRequestBody(op, operationId, method, path, spec, baseDir) {
|
|
391
|
+
var _a, _b;
|
|
392
|
+
const inputParams = [];
|
|
393
|
+
const requestBody = op.requestBody;
|
|
394
|
+
if (!(requestBody === null || requestBody === void 0 ? void 0 : requestBody.content)) {
|
|
395
|
+
return inputParams;
|
|
396
|
+
}
|
|
397
|
+
const contentTypes = Object.keys(requestBody.content);
|
|
398
|
+
const contentType = contentTypes[0];
|
|
399
|
+
if (contentType === 'application/json' && ((_a = requestBody.content[contentType]) === null || _a === void 0 ? void 0 : _a.schema)) {
|
|
400
|
+
const bodySchema = requestBody.content[contentType].schema;
|
|
401
|
+
let type;
|
|
402
|
+
if (bodySchema.$ref) {
|
|
403
|
+
type = getTypeFromSchema(bodySchema, spec, baseDir);
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
const requestStructName = generateStructName(operationId, method, path, 'Request');
|
|
407
|
+
type = `STRUCT(${requestStructName})`;
|
|
408
|
+
}
|
|
409
|
+
inputParams.push({
|
|
410
|
+
name: 'body',
|
|
411
|
+
type,
|
|
412
|
+
required: requestBody.required ? 'TRUE' : 'FALSE',
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
else if (contentType === 'multipart/form-data' && ((_b = requestBody.content[contentType]) === null || _b === void 0 ? void 0 : _b.schema)) {
|
|
416
|
+
const bodySchema = requestBody.content[contentType].schema;
|
|
417
|
+
if (bodySchema.properties) {
|
|
418
|
+
for (const [key, prop] of Object.entries(bodySchema.properties)) {
|
|
419
|
+
const type = prop.format === 'binary' ? 'FILE' : getTypeFromSchema(prop, spec, baseDir);
|
|
420
|
+
const required = (bodySchema.required || []).includes(key) ? 'TRUE' : 'FALSE';
|
|
421
|
+
inputParams.push({
|
|
422
|
+
name: key,
|
|
423
|
+
type,
|
|
424
|
+
required,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return inputParams;
|
|
430
|
+
}
|
|
431
|
+
function extractResponses(op, operationId, method, path, spec, baseDir) {
|
|
432
|
+
const returns = [];
|
|
433
|
+
// Handle all response codes (success and error)
|
|
434
|
+
for (const [code, response] of Object.entries(op.responses || {})) {
|
|
435
|
+
const content = response.content;
|
|
436
|
+
let returnType = 'ANY';
|
|
437
|
+
if (content) {
|
|
438
|
+
const jsonContent = content['application/json'];
|
|
439
|
+
if (jsonContent === null || jsonContent === void 0 ? void 0 : jsonContent.schema) {
|
|
440
|
+
const schema = jsonContent.schema;
|
|
441
|
+
if (schema.$ref) {
|
|
442
|
+
returnType = getTypeFromSchema(schema, spec, baseDir);
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
// It's an inline schema, so we need to generate a struct name for it
|
|
446
|
+
const responseStructName = generateStructName(operationId, method, path, `Response${code}`);
|
|
447
|
+
returnType = `STRUCT(${responseStructName})`;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
else if (code === '204') {
|
|
452
|
+
// 204 No Content - no response body
|
|
453
|
+
returnType = 'VOID';
|
|
454
|
+
}
|
|
455
|
+
returns.push({
|
|
456
|
+
RETURNTYPE: returnType,
|
|
457
|
+
RETURNNAME: 'response',
|
|
458
|
+
CODE: code === 'default' ? '500' : code,
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
return returns;
|
|
462
|
+
}
|
|
463
|
+
function extractInterfaces(spec, baseDir) {
|
|
464
|
+
var _a, _b;
|
|
465
|
+
const base = ((_b = (_a = spec.servers) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.url) || '';
|
|
466
|
+
const interfaces = {};
|
|
467
|
+
// Valid HTTP methods
|
|
468
|
+
const validMethods = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'];
|
|
469
|
+
for (const [pathStr, methods] of Object.entries(spec.paths)) {
|
|
470
|
+
for (const [method, op] of Object.entries(methods)) {
|
|
471
|
+
// Skip extension fields (x-*) and only process valid HTTP methods
|
|
472
|
+
if (method.startsWith('x-') || !validMethods.includes(method.toLowerCase())) {
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
const operationId = op.operationId || `${method}-${pathStr.replace(/[\/{}]/g, '-')}`;
|
|
476
|
+
const alias = operationId;
|
|
477
|
+
const endpoint = pathStr.includes('{') ? `\`${base}${pathStr}\`` : `${base}${pathStr}`;
|
|
478
|
+
// Check if operation is hidden from docs
|
|
479
|
+
const isPrivate = op['x-hidden-from-docs'] === true;
|
|
480
|
+
const visibility = isPrivate ? 'PRIVATE' : 'PUBLIC';
|
|
481
|
+
const { bodyType } = getContentTypeAndBodyType(op);
|
|
482
|
+
const headers = getHeadersForOperation(op, spec);
|
|
483
|
+
const pathQueryHeaderParams = extractParameters(op, spec, baseDir);
|
|
484
|
+
const bodyParams = extractRequestBody(op, operationId, method, pathStr, spec, baseDir);
|
|
485
|
+
const inputParams = [...pathQueryHeaderParams, ...bodyParams];
|
|
486
|
+
const returns = extractResponses(op, operationId, method, pathStr, spec, baseDir);
|
|
487
|
+
interfaces[alias] = {
|
|
488
|
+
SUMMARY: op.summary || '',
|
|
489
|
+
DESCRIPTION: op.description || '',
|
|
490
|
+
DESC: generateDesc(op, method, pathStr),
|
|
491
|
+
ENDPOINT: endpoint,
|
|
492
|
+
VISIBILITY: visibility,
|
|
493
|
+
HTTP: {
|
|
494
|
+
METHOD: method.toUpperCase(),
|
|
495
|
+
HEADERS: headers,
|
|
496
|
+
BODYTYPE: bodyType,
|
|
497
|
+
},
|
|
498
|
+
INPUTS: inputParams,
|
|
499
|
+
RETURNS: returns,
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return interfaces;
|
|
504
|
+
}
|
|
505
|
+
function extractSecurityDefaults(spec) {
|
|
506
|
+
var _a;
|
|
507
|
+
const defs = [];
|
|
508
|
+
const securitySchemes = ((_a = spec.components) === null || _a === void 0 ? void 0 : _a.securitySchemes) || {};
|
|
509
|
+
for (const [name, scheme] of Object.entries(securitySchemes)) {
|
|
510
|
+
if (scheme.type === 'http') {
|
|
511
|
+
if (scheme.scheme === 'bearer') {
|
|
512
|
+
defs.push({ bearer_token: 'BEARER <TOKEN>' });
|
|
513
|
+
}
|
|
514
|
+
else if (scheme.scheme === 'basic') {
|
|
515
|
+
defs.push({ basic_auth: 'Basic <BASE64>' });
|
|
516
|
+
}
|
|
517
|
+
else if (scheme.scheme === 'digest') {
|
|
518
|
+
defs.push({ digest_auth: 'Digest <CREDENTIALS>' });
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
defs.push({ [`${scheme.scheme}_auth`]: `<${scheme.scheme.toUpperCase()}_CREDENTIALS>` });
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
else if (scheme.type === 'apiKey') {
|
|
525
|
+
if (scheme.in === 'header') {
|
|
526
|
+
defs.push({ [scheme.name.toLowerCase()]: `<${scheme.name.toUpperCase()}>` });
|
|
527
|
+
}
|
|
528
|
+
else if (scheme.in === 'query') {
|
|
529
|
+
defs.push({ [`query_${scheme.name.toLowerCase()}`]: `<${scheme.name.toUpperCase()}>` });
|
|
530
|
+
}
|
|
531
|
+
else if (scheme.in === 'cookie') {
|
|
532
|
+
defs.push({ [`cookie_${scheme.name.toLowerCase()}`]: `<${scheme.name.toUpperCase()}>` });
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
else if (scheme.type === 'oauth2') {
|
|
536
|
+
defs.push({ bearer_token: 'BEARER <ACCESS_TOKEN>' });
|
|
537
|
+
}
|
|
538
|
+
else if (scheme.type === 'openIdConnect') {
|
|
539
|
+
defs.push({ id_token: 'ID_TOKEN <JWT>' });
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return defs;
|
|
543
|
+
}
|
|
544
|
+
function generateWrekenfile(spec, baseDir) {
|
|
545
|
+
var _a, _b;
|
|
546
|
+
if (!spec || typeof spec !== 'object') {
|
|
547
|
+
throw new Error("Argument 'spec' is required and must be an object");
|
|
548
|
+
}
|
|
549
|
+
if (!baseDir || typeof baseDir !== 'string') {
|
|
550
|
+
throw new Error("Argument 'baseDir' is required and must be a string");
|
|
551
|
+
}
|
|
552
|
+
return (0, js_yaml_1.dump)({
|
|
553
|
+
VERSION: '1.2',
|
|
554
|
+
INIT: {
|
|
555
|
+
DEFAULTS: [
|
|
556
|
+
...extractSecurityDefaults(spec),
|
|
557
|
+
{ w_base_url: ((_b = (_a = spec.servers) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.url) || 'https://api.default.com' },
|
|
558
|
+
],
|
|
559
|
+
},
|
|
560
|
+
INTERFACES: extractInterfaces(spec, baseDir),
|
|
561
|
+
STRUCTS: extractStructs(spec, baseDir),
|
|
562
|
+
});
|
|
563
|
+
}
|