wrekenfile-converter 2.0.3 → 2.0.6
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 +58 -63
- package/dist/openapi-to-wreken.js +37 -30
- package/dist/openapi-v2-to-wrekenfile.js +1 -1
- package/dist/postman-to-wrekenfile.js +39 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,49 +77,79 @@ const variables = {}; // Optionally provide Postman environment variables
|
|
|
77
77
|
const wrekenfileYaml = generateWrekenfileFromPostman(collection, variables);
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
### Validate a Wrekenfile
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
```typescript
|
|
83
|
+
import { validateWrekenfile } from 'wrekenfile-converter';
|
|
83
84
|
|
|
84
|
-
|
|
85
|
+
const result = validateWrekenfile('./Wrekenfile.yaml');
|
|
86
|
+
console.log(result.isValid ? '✅ Valid' : '❌ Invalid');
|
|
87
|
+
console.log(result.errors, result.warnings);
|
|
88
|
+
```
|
|
85
89
|
|
|
86
|
-
|
|
90
|
+
### Generate Mini Wrekenfiles
|
|
87
91
|
|
|
88
|
-
```
|
|
89
|
-
|
|
92
|
+
```typescript
|
|
93
|
+
import { generateMiniWrekenfiles, MiniWrekenfile } from 'wrekenfile-converter';
|
|
94
|
+
|
|
95
|
+
const miniFiles: MiniWrekenfile[] = generateMiniWrekenfiles('./Wrekenfile.yaml');
|
|
96
|
+
// Each miniFile contains { content, metadata }
|
|
90
97
|
```
|
|
91
98
|
|
|
92
|
-
|
|
99
|
+
## CLI Tools
|
|
93
100
|
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
### Convert OpenAPI to Wrekenfile
|
|
102
|
+
|
|
103
|
+
Generate a Wrekenfile YAML from an OpenAPI (YAML or JSON) spec:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npx ts-node src/cli/cli-openapi-to-wrekenfile.ts --input <openapi.yaml|json> [--output <wrekenfile.yaml>] [--cwd <dir>]
|
|
96
107
|
```
|
|
97
108
|
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
109
|
+
**Options:**
|
|
110
|
+
- `--input` or `-i`: Path to your OpenAPI YAML or JSON file (required)
|
|
111
|
+
- `--output` or `-o`: Path to output Wrekenfile YAML (optional, defaults to `output_wrekenfile.yaml`)
|
|
112
|
+
- `--cwd`: Working directory for resolving $refs (optional, defaults to the input file's directory)
|
|
101
113
|
|
|
102
|
-
|
|
114
|
+
**Example:**
|
|
115
|
+
```bash
|
|
116
|
+
npx ts-node src/cli/cli-openapi-to-wrekenfile.ts --input examples/p3id_swagger.json --output wrekenfile.yaml --cwd .
|
|
117
|
+
```
|
|
103
118
|
|
|
104
|
-
###
|
|
119
|
+
### Convert Postman Collection to Wrekenfile
|
|
105
120
|
|
|
106
|
-
|
|
107
|
-
import { validateWrekenfile } from 'wrekenfile-converter';
|
|
121
|
+
Convert a Postman collection JSON to a Wrekenfile YAML file:
|
|
108
122
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
console.log(result.errors, result.warnings);
|
|
123
|
+
```bash
|
|
124
|
+
npx ts-node src/cli/cli-postman-to-wrekenfile.ts <postman_collection.json> <output_wrekenfile.yaml> [postman_environment.json]
|
|
112
125
|
```
|
|
113
126
|
|
|
127
|
+
**Example:**
|
|
128
|
+
```bash
|
|
129
|
+
npx ts-node src/cli/cli-postman-to-wrekenfile.ts examples/transact_bridge_postman.json wrekenfile.yaml
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Note:** The third argument (environment file) is optional.
|
|
133
|
+
|
|
114
134
|
### Generate Mini Wrekenfiles
|
|
115
135
|
|
|
116
|
-
|
|
117
|
-
import { generateMiniWrekenfiles, MiniWrekenfile } from 'wrekenfile-converter';
|
|
136
|
+
Generate mini Wrekenfiles for each endpoint from a main Wrekenfile YAML:
|
|
118
137
|
|
|
119
|
-
|
|
120
|
-
|
|
138
|
+
```bash
|
|
139
|
+
npx ts-node src/cli/cli-mini-wrekenfile-generator.ts --input <wrekenfile.yaml> [--output <dir>]
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Options:**
|
|
143
|
+
- `--input` or `-i`: Path to your main Wrekenfile YAML (required)
|
|
144
|
+
- `--output` or `-o`: Output directory for mini Wrekenfiles (optional, defaults to `./mini-wrekenfiles`)
|
|
145
|
+
|
|
146
|
+
**Example:**
|
|
147
|
+
```bash
|
|
148
|
+
npx ts-node src/cli/cli-mini-wrekenfile-generator.ts --input wrekenfile.yaml --output ./mini-wrekenfiles
|
|
121
149
|
```
|
|
122
150
|
|
|
151
|
+
This will generate one mini Wrekenfile per endpoint in the specified output directory.
|
|
152
|
+
|
|
123
153
|
## API Reference
|
|
124
154
|
|
|
125
155
|
### Core Functions
|
|
@@ -191,6 +221,10 @@ src/
|
|
|
191
221
|
├── postman-to-wrekenfile.ts # Postman converter
|
|
192
222
|
├── wrekenfile-validator.ts # Validation logic
|
|
193
223
|
├── mini-wrekenfile-generator.ts # Mini chunk generator
|
|
224
|
+
├── cli/ # CLI tools
|
|
225
|
+
│ ├── cli-openapi-to-wrekenfile.ts
|
|
226
|
+
│ ├── cli-postman-to-wrekenfile.ts
|
|
227
|
+
│ └── cli-mini-wrekenfile-generator.ts
|
|
194
228
|
└── example-usage.ts # Usage examples
|
|
195
229
|
|
|
196
230
|
dist/ # Compiled JavaScript + types
|
|
@@ -206,43 +240,4 @@ mini-wrekenfiles/ # Generated mini chunks (if you save them)
|
|
|
206
240
|
|
|
207
241
|
## License
|
|
208
242
|
|
|
209
|
-
MIT
|
|
210
|
-
|
|
211
|
-
# Wrekenfile Tools
|
|
212
|
-
|
|
213
|
-
## Generate Wrekenfile from OpenAPI
|
|
214
|
-
|
|
215
|
-
You can generate a Wrekenfile YAML from an OpenAPI (YAML or JSON) spec using the CLI:
|
|
216
|
-
|
|
217
|
-
```
|
|
218
|
-
npx ts-node src/cli/cli-openapi-to-wrekenfile.ts --input <openapi.yaml|json> [--output <wrekenfile.yaml>] [--cwd <dir>]
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
- `--input` or `-i`: Path to your OpenAPI YAML or JSON file (required)
|
|
222
|
-
- `--output` or `-o`: Path to output Wrekenfile YAML (optional, defaults to `output_wrekenfile.yaml`)
|
|
223
|
-
- `--cwd`: Working directory for resolving $refs (optional, defaults to the input file's directory)
|
|
224
|
-
|
|
225
|
-
**Example:**
|
|
226
|
-
```
|
|
227
|
-
npx ts-node src/cli/cli-openapi-to-wrekenfile.ts --input examples/p3id_swagger.json --output wrekenfile.yaml --cwd .
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
---
|
|
231
|
-
|
|
232
|
-
## Generate Mini Wrekenfiles from a Wrekenfile
|
|
233
|
-
|
|
234
|
-
You can generate mini Wrekenfiles for each endpoint from a main Wrekenfile YAML using the CLI:
|
|
235
|
-
|
|
236
|
-
```
|
|
237
|
-
npx ts-node src/cli/cli-mini-wrekenfile-generator.ts --input <wrekenfile.yaml> [--output <dir>]
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
- `--input` or `-i`: Path to your main Wrekenfile YAML (required)
|
|
241
|
-
- `--output` or `-o`: Output directory for mini Wrekenfiles (optional, defaults to `./mini-wrekenfiles`)
|
|
242
|
-
|
|
243
|
-
**Example:**
|
|
244
|
-
```
|
|
245
|
-
npx ts-node src/cli/cli-mini-wrekenfile-generator.ts --input wrekenfile.yaml --output ./mini-wrekenfiles
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
This will generate one mini Wrekenfile per endpoint in the specified output directory.
|
|
243
|
+
MIT
|
|
@@ -256,39 +256,41 @@ function extractStructs(spec, baseDir) {
|
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
// Extract inline schemas from operations
|
|
259
|
-
|
|
260
|
-
for (const [
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if (content
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
259
|
+
if (spec.paths && typeof spec.paths === 'object') {
|
|
260
|
+
for (const [pathStr, methods] of Object.entries(spec.paths)) {
|
|
261
|
+
for (const [method, op] of Object.entries(methods)) {
|
|
262
|
+
const operationId = op.operationId || `${method}-${pathStr.replace(/[\/{}]/g, '-')}`;
|
|
263
|
+
// Extract request body schemas
|
|
264
|
+
if ((_b = op.requestBody) === null || _b === void 0 ? void 0 : _b.content) {
|
|
265
|
+
for (const [contentType, content] of Object.entries(op.requestBody.content)) {
|
|
266
|
+
if (content && content.schema) {
|
|
267
|
+
if (content.schema && content.schema.$ref) {
|
|
268
|
+
const refName = content.schema.$ref.split('/').pop();
|
|
269
|
+
if (refName)
|
|
270
|
+
collectAllReferencedSchemas(resolveRef(content.schema.$ref, spec, baseDir), refName);
|
|
271
|
+
}
|
|
272
|
+
else if (content.schema && typeof content.schema === 'object') {
|
|
273
|
+
const requestStructName = generateStructName(operationId, method, pathStr, 'Request');
|
|
274
|
+
collectAllReferencedSchemas(content.schema, requestStructName);
|
|
275
|
+
}
|
|
274
276
|
}
|
|
275
277
|
}
|
|
276
278
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
279
|
+
// Extract response schemas
|
|
280
|
+
if (op.responses) {
|
|
281
|
+
for (const [code, response] of Object.entries(op.responses)) {
|
|
282
|
+
if (response && response.content) {
|
|
283
|
+
for (const [contentType, content] of Object.entries(response.content)) {
|
|
284
|
+
if (content && content.schema) {
|
|
285
|
+
if (content.schema && content.schema.$ref) {
|
|
286
|
+
const refName = content.schema.$ref.split('/').pop();
|
|
287
|
+
if (refName)
|
|
288
|
+
collectAllReferencedSchemas(resolveRef(content.schema.$ref, spec, baseDir), refName);
|
|
289
|
+
}
|
|
290
|
+
else if (content.schema && typeof content.schema === 'object') {
|
|
291
|
+
const responseStructName = generateStructName(operationId, method, pathStr, `Response${code}`);
|
|
292
|
+
collectAllReferencedSchemas(content.schema, responseStructName);
|
|
293
|
+
}
|
|
292
294
|
}
|
|
293
295
|
}
|
|
294
296
|
}
|
|
@@ -488,6 +490,11 @@ function extractInterfaces(spec, baseDir) {
|
|
|
488
490
|
const interfaces = {};
|
|
489
491
|
// Valid HTTP methods
|
|
490
492
|
const validMethods = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'];
|
|
493
|
+
// Check if paths exists and is an object
|
|
494
|
+
if (!spec.paths || typeof spec.paths !== 'object') {
|
|
495
|
+
console.warn('Warning: No paths found in OpenAPI specification');
|
|
496
|
+
return interfaces;
|
|
497
|
+
}
|
|
491
498
|
for (const [pathStr, methods] of Object.entries(spec.paths)) {
|
|
492
499
|
for (const [method, op] of Object.entries(methods)) {
|
|
493
500
|
// Skip extension fields (x-*) and only process valid HTTP methods
|
|
@@ -427,8 +427,8 @@ function extractInterfaces(spec) {
|
|
|
427
427
|
const returns = extractResponses(op, operationId, method, pathStr);
|
|
428
428
|
interfaces[alias] = {
|
|
429
429
|
SUMMARY: op.summary || '',
|
|
430
|
-
DESCRIPTION: op.description || '',
|
|
431
430
|
DESC: generateDesc(op, method, pathStr),
|
|
431
|
+
TAGS: Array.isArray(op.tags) ? op.tags : [],
|
|
432
432
|
ENDPOINT: endpoint,
|
|
433
433
|
VISIBILITY: visibility,
|
|
434
434
|
HTTP: {
|
|
@@ -70,11 +70,23 @@ function mapType(value) {
|
|
|
70
70
|
return 'ANY';
|
|
71
71
|
return 'ANY';
|
|
72
72
|
}
|
|
73
|
+
function getItemDescription(item) {
|
|
74
|
+
var _a, _b, _c, _d, _e;
|
|
75
|
+
let description = (_c = (_a = item === null || item === void 0 ? void 0 : item.description) !== null && _a !== void 0 ? _a : (_b = item === null || item === void 0 ? void 0 : item.request) === null || _b === void 0 ? void 0 : _b.description) !== null && _c !== void 0 ? _c : (_e = (_d = item === null || item === void 0 ? void 0 : item.request) === null || _d === void 0 ? void 0 : _d.body) === null || _e === void 0 ? void 0 : _e.description;
|
|
76
|
+
if (!description)
|
|
77
|
+
return '';
|
|
78
|
+
// Postman can store description as an object with { content: string }
|
|
79
|
+
if (typeof description === 'object' && typeof description.content === 'string') {
|
|
80
|
+
description = description.content;
|
|
81
|
+
}
|
|
82
|
+
if (typeof description !== 'string')
|
|
83
|
+
return '';
|
|
84
|
+
return description.replace(/<[^>]*>/g, '').replace(/\n+/g, ' ').trim();
|
|
85
|
+
}
|
|
73
86
|
function generateDesc(item, method, path) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return
|
|
77
|
-
}
|
|
87
|
+
const cleaned = getItemDescription(item);
|
|
88
|
+
if (cleaned)
|
|
89
|
+
return cleaned;
|
|
78
90
|
return `${method.toUpperCase()} ${path}`;
|
|
79
91
|
}
|
|
80
92
|
function generateStructName(itemName, method, path, suffix) {
|
|
@@ -423,12 +435,13 @@ function extractOperations(collection, variables) {
|
|
|
423
435
|
return `${name} ${operationNameCount[name]}`;
|
|
424
436
|
}
|
|
425
437
|
}
|
|
426
|
-
function processItem(item) {
|
|
438
|
+
function processItem(item, parentName = null) {
|
|
427
439
|
if (item.request) {
|
|
428
440
|
const method = item.request.method || 'GET';
|
|
429
441
|
const url = item.request.url;
|
|
430
442
|
const path = extractPathFromUrl(url, variables);
|
|
431
443
|
const itemName = item.name || 'unknown';
|
|
444
|
+
const immediateParentName = parentName || null;
|
|
432
445
|
// Generate operation ID
|
|
433
446
|
let operationId = itemName.toLowerCase().replace(/[^a-z0-9]/g, '-');
|
|
434
447
|
operationId = getUniqueOperationName(operationId);
|
|
@@ -444,8 +457,8 @@ function extractOperations(collection, variables) {
|
|
|
444
457
|
operations.push({
|
|
445
458
|
name: operationId,
|
|
446
459
|
SUMMARY: itemName || '',
|
|
447
|
-
DESCRIPTION: item.description ? item.description.replace(/<[^>]*>/g, '').replace(/\n+/g, ' ').trim() : '',
|
|
448
460
|
DESC: generateDesc(item, method, path),
|
|
461
|
+
TAGS: immediateParentName ? [immediateParentName] : (itemName ? [itemName] : []),
|
|
449
462
|
ENDPOINT: `"/${path}"`,
|
|
450
463
|
VISIBILITY: 'PUBLIC',
|
|
451
464
|
HTTP: {
|
|
@@ -459,12 +472,12 @@ function extractOperations(collection, variables) {
|
|
|
459
472
|
}
|
|
460
473
|
if (item.item) {
|
|
461
474
|
for (const subItem of item.item) {
|
|
462
|
-
processItem(subItem);
|
|
475
|
+
processItem(subItem, item.name || parentName || null);
|
|
463
476
|
}
|
|
464
477
|
}
|
|
465
478
|
}
|
|
466
479
|
for (const item of collection.item) {
|
|
467
|
-
processItem(item);
|
|
480
|
+
processItem(item, null);
|
|
468
481
|
}
|
|
469
482
|
return operations;
|
|
470
483
|
}
|
|
@@ -531,9 +544,24 @@ function generateWrekenfile(collection, variables) {
|
|
|
531
544
|
wrekenfile += `INTERFACES:\n`;
|
|
532
545
|
for (const operation of operations) {
|
|
533
546
|
wrekenfile += ` ${operation.name}:\n`;
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
547
|
+
// Quote SUMMARY and DESC if they contain special characters
|
|
548
|
+
const summary = operation.SUMMARY.includes(':') || operation.SUMMARY.includes('"') ? `"${operation.SUMMARY.replace(/"/g, '\\"')}"` : operation.SUMMARY;
|
|
549
|
+
const desc = operation.DESC.includes(':') || operation.DESC.includes('"') ? `"${operation.DESC.replace(/"/g, '\\"')}"` : operation.DESC;
|
|
550
|
+
wrekenfile += ` SUMMARY: ${summary}\n`;
|
|
551
|
+
wrekenfile += ` DESC: ${desc}\n`;
|
|
552
|
+
// TAGS
|
|
553
|
+
if (!operation.TAGS || operation.TAGS.length === 0) {
|
|
554
|
+
wrekenfile += ` TAGS: []\n`;
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
wrekenfile += ` TAGS:\n`;
|
|
558
|
+
for (const tag of operation.TAGS) {
|
|
559
|
+
const tagVal = (typeof tag === 'string' && (tag.includes(':') || tag.includes('"')))
|
|
560
|
+
? `"${String(tag).replace(/"/g, '\\"')}"`
|
|
561
|
+
: String(tag);
|
|
562
|
+
wrekenfile += ` - ${tagVal}\n`;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
537
565
|
wrekenfile += ` ENDPOINT: ${operation.ENDPOINT}\n`;
|
|
538
566
|
wrekenfile += ` VISIBILITY: ${operation.VISIBILITY}\n`;
|
|
539
567
|
wrekenfile += ` HTTP:\n`;
|
package/package.json
CHANGED