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.
Files changed (52) hide show
  1. package/README.md +45 -26
  2. package/dist/example-usage.d.ts +1 -1
  3. package/dist/index.d.ts +6 -5
  4. package/dist/index.js +53 -20
  5. package/dist/v1/index.d.ts +3 -0
  6. package/dist/v1/index.js +21 -0
  7. package/dist/{wrekenfile-validator.js → v1/wrekenfile-validator.js} +30 -8
  8. package/dist/v2/cli/cli-mini-wrekenfile-generator.d.ts +2 -0
  9. package/dist/v2/cli/cli-mini-wrekenfile-generator.js +107 -0
  10. package/dist/v2/cli/cli-openapi-to-wrekenfile.d.ts +2 -0
  11. package/dist/v2/cli/cli-openapi-to-wrekenfile.js +115 -0
  12. package/dist/v2/cli/cli-openapi-v2-to-wrekenfile.d.ts +2 -0
  13. package/dist/v2/cli/cli-openapi-v2-to-wrekenfile.js +115 -0
  14. package/dist/v2/cli/cli-postman-to-wrekenfile.d.ts +2 -0
  15. package/dist/v2/cli/cli-postman-to-wrekenfile.js +54 -0
  16. package/dist/v2/index.d.ts +4 -0
  17. package/dist/v2/index.js +25 -0
  18. package/dist/v2/mini-wrekenfile-generator.d.ts +13 -0
  19. package/dist/v2/mini-wrekenfile-generator.js +289 -0
  20. package/dist/v2/openapi-to-wreken.d.ts +2 -0
  21. package/dist/v2/openapi-to-wreken.js +829 -0
  22. package/dist/v2/openapi-v2-to-wrekenfile.d.ts +2 -0
  23. package/dist/v2/openapi-v2-to-wrekenfile.js +806 -0
  24. package/dist/v2/postman-to-wrekenfile.d.ts +11 -0
  25. package/dist/v2/postman-to-wrekenfile.js +742 -0
  26. package/dist/v2/utils/constants.d.ts +80 -0
  27. package/dist/v2/utils/constants.js +104 -0
  28. package/dist/v2/utils/response-utils.d.ts +11 -0
  29. package/dist/v2/utils/response-utils.js +39 -0
  30. package/dist/v2/utils/yaml-utils.d.ts +4 -0
  31. package/dist/v2/utils/yaml-utils.js +96 -0
  32. package/dist/versions.d.ts +9 -0
  33. package/dist/versions.js +12 -0
  34. package/package.json +12 -14
  35. package/dist/openapi-to-wrekenfile.d.ts +0 -0
  36. package/dist/openapi-to-wrekenfile.js +0 -10
  37. package/wrekenfile.md +0 -726
  38. /package/dist/{cli → v1/cli}/cli-mini-wrekenfile-generator.d.ts +0 -0
  39. /package/dist/{cli → v1/cli}/cli-mini-wrekenfile-generator.js +0 -0
  40. /package/dist/{cli → v1/cli}/cli-openapi-to-wrekenfile.d.ts +0 -0
  41. /package/dist/{cli → v1/cli}/cli-openapi-to-wrekenfile.js +0 -0
  42. /package/dist/{cli → v1/cli}/cli-postman-to-wrekenfile.d.ts +0 -0
  43. /package/dist/{cli → v1/cli}/cli-postman-to-wrekenfile.js +0 -0
  44. /package/dist/{mini-wrekenfile-generator.d.ts → v1/mini-wrekenfile-generator.d.ts} +0 -0
  45. /package/dist/{mini-wrekenfile-generator.js → v1/mini-wrekenfile-generator.js} +0 -0
  46. /package/dist/{openapi-to-wreken.d.ts → v1/openapi-to-wreken.d.ts} +0 -0
  47. /package/dist/{openapi-to-wreken.js → v1/openapi-to-wreken.js} +0 -0
  48. /package/dist/{openapi-v2-to-wrekenfile.d.ts → v1/openapi-v2-to-wrekenfile.d.ts} +0 -0
  49. /package/dist/{openapi-v2-to-wrekenfile.js → v1/openapi-v2-to-wrekenfile.js} +0 -0
  50. /package/dist/{postman-to-wrekenfile.d.ts → v1/postman-to-wrekenfile.d.ts} +0 -0
  51. /package/dist/{postman-to-wrekenfile.js → v1/postman-to-wrekenfile.js} +0 -0
  52. /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
+ }