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