x-openapi-flow 1.3.7 → 1.4.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
CHANGED
|
@@ -11,10 +11,8 @@
|
|
|
11
11
|
[](https://github.com/tiago-marques/x-openapi-flow/commits/main)
|
|
12
12
|

|
|
13
13
|
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
**OpenAPI describes APIs.**
|
|
17
|
-
**x-openapi-flow describes how they actually work — for developers and AI.**
|
|
14
|
+
# OpenAPI describes APIs.
|
|
15
|
+
# x-openapi-flow describes how they actually work — for developers and AI.
|
|
18
16
|
|
|
19
17
|
`x-openapi-flow` is an OpenAPI vendor extension and CLI for documenting and validating resource lifecycle workflows.
|
|
20
18
|
It adds explicit state-machine metadata (`x-openapi-flow`) to operations and validates both schema and lifecycle graph consistency.
|
|
@@ -52,14 +50,22 @@ Default adoption path:
|
|
|
52
50
|
2. Run `init` to create/sync sidecar flow metadata.
|
|
53
51
|
3. Run `apply` whenever the OpenAPI file is regenerated.
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
Troubleshooting: [docs/wiki/Troubleshooting.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/Troubleshooting.md)
|
|
53
|
+
Sidecar and output roles:
|
|
57
54
|
|
|
58
|
-
|
|
55
|
+
- `{context}.x.(json|yaml)`: sidecar source of lifecycle metadata (the file you edit).
|
|
56
|
+
- `{context}.flow.(json|yaml)`: generated OpenAPI output after merge (the file you validate and serve in docs/tools).
|
|
57
|
+
|
|
58
|
+
Practical rule:
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
1. edit `.x`
|
|
61
|
+
2. run `apply`
|
|
62
|
+
3. validate/use `.flow`
|
|
63
|
+
|
|
64
|
+
Full rollout guide: [docs/wiki/getting-started/Adoption-Playbook.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/getting-started/Adoption-Playbook.md)
|
|
65
|
+
Troubleshooting: [docs/wiki/reference/Troubleshooting.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/reference/Troubleshooting.md)
|
|
66
|
+
|
|
67
|
+
---
|
|
61
68
|
|
|
62
|
-
Typical routine when your OpenAPI source changes frequently:
|
|
63
69
|
|
|
64
70
|
1. Bootstrap once per project.
|
|
65
71
|
|
|
@@ -73,8 +79,6 @@ npx x-openapi-flow init
|
|
|
73
79
|
npx x-openapi-flow apply openapi.yaml
|
|
74
80
|
```
|
|
75
81
|
|
|
76
|
-
3. Validate lifecycle quality before opening a PR.
|
|
77
|
-
|
|
78
82
|
```bash
|
|
79
83
|
npx x-openapi-flow validate openapi.flow.yaml --profile strict --strict-quality
|
|
80
84
|
```
|
|
@@ -93,8 +97,6 @@ What this gives your team in practice:
|
|
|
93
97
|
- explicit transition contracts instead of implicit tribal knowledge
|
|
94
98
|
- safer API evolution with fewer integration regressions
|
|
95
99
|
|
|
96
|
-
---
|
|
97
|
-
|
|
98
100
|
## Integration Experience (What You See)
|
|
99
101
|
|
|
100
102
|
### Swagger UI
|
|
@@ -108,6 +110,8 @@ npm run apply
|
|
|
108
110
|
npm start
|
|
109
111
|
```
|
|
110
112
|
|
|
113
|
+
Note: in this example, `npm run apply` prefers local sidecars (`swagger.x.yaml|yml|json`) and falls back to `examples/swagger.x.yaml|json` when a local sidecar is not present.
|
|
114
|
+
|
|
111
115
|
Experience outcome:
|
|
112
116
|
|
|
113
117
|
- operation docs enriched with `x-openapi-flow` fields
|
|
@@ -115,8 +119,8 @@ Experience outcome:
|
|
|
115
119
|
|
|
116
120
|
Demo media:
|
|
117
121
|
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+

|
|
123
|
+

|
|
120
124
|
|
|
121
125
|
### Redoc
|
|
122
126
|
|
|
@@ -136,8 +140,9 @@ Experience outcome:
|
|
|
136
140
|
|
|
137
141
|
Demo media:
|
|
138
142
|
|
|
139
|
-
|
|
140
|
-
|
|
143
|
+

|
|
144
|
+

|
|
145
|
+

|
|
141
146
|
|
|
142
147
|
### Postman
|
|
143
148
|
|
|
@@ -157,8 +162,8 @@ Experience outcome:
|
|
|
157
162
|
|
|
158
163
|
Demo media:
|
|
159
164
|
|
|
160
|
-
|
|
161
|
-
|
|
165
|
+

|
|
166
|
+

|
|
162
167
|
|
|
163
168
|
### Insomnia
|
|
164
169
|
|
|
@@ -178,15 +183,37 @@ Experience outcome:
|
|
|
178
183
|
|
|
179
184
|
Demo media:
|
|
180
185
|
|
|
181
|
-
|
|
182
|
-
|
|
186
|
+

|
|
187
|
+

|
|
188
|
+
|
|
189
|
+
### SDK (TypeScript)
|
|
190
|
+
|
|
191
|
+
Use this when you want a generated flow-aware SDK for application integration.
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
cd example/sdk/typescript
|
|
195
|
+
npm install
|
|
196
|
+
npm run apply
|
|
197
|
+
npm run generate
|
|
198
|
+
npm run run:sample
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Experience outcome:
|
|
202
|
+
|
|
203
|
+
- generated TypeScript SDK in `sdk/` from `x-openapi-flow` metadata
|
|
204
|
+
- minimal runnable sample showing typed SDK usage in `src/sample.ts`
|
|
205
|
+
- lifecycle-oriented methods and transition-aware resource instances
|
|
206
|
+
|
|
207
|
+
Example project:
|
|
208
|
+
|
|
209
|
+
- [example/sdk/typescript/README.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/example/sdk/typescript/README.md)
|
|
183
210
|
|
|
184
211
|
More integration details:
|
|
185
212
|
|
|
186
|
-
- [docs/wiki/Swagger-UI-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/Swagger-UI-Integration.md)
|
|
187
|
-
- [docs/wiki/Redoc-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/Redoc-Integration.md)
|
|
188
|
-
- [docs/wiki/Postman-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/Postman-Integration.md)
|
|
189
|
-
- [docs/wiki/Insomnia-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/Insomnia-Integration.md)
|
|
213
|
+
- [docs/wiki/integrations/Swagger-UI-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/integrations/Swagger-UI-Integration.md)
|
|
214
|
+
- [docs/wiki/integrations/Redoc-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/integrations/Redoc-Integration.md)
|
|
215
|
+
- [docs/wiki/integrations/Postman-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/integrations/Postman-Integration.md)
|
|
216
|
+
- [docs/wiki/integrations/Insomnia-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/integrations/Insomnia-Integration.md)
|
|
190
217
|
|
|
191
218
|
---
|
|
192
219
|
|
|
@@ -249,11 +276,6 @@ await payment.authorize();
|
|
|
249
276
|
await payment.capture();
|
|
250
277
|
```
|
|
251
278
|
|
|
252
|
-
Demo media:
|
|
253
|
-
|
|
254
|
-
- GIF slot: `docs/assets/demo-sdk-generation.gif`
|
|
255
|
-
- Image slot: `docs/assets/demo-sdk-generation.png`
|
|
256
|
-
|
|
257
279
|
---
|
|
258
280
|
|
|
259
281
|
## Example: Payment Flow
|
|
@@ -316,10 +338,8 @@ npx x-openapi-flow apply [openapi-file] [--flows path] [--out path]
|
|
|
316
338
|
npx x-openapi-flow analyze [openapi-file] [--format pretty|json] [--out path] [--merge] [--flows path]
|
|
317
339
|
npx x-openapi-flow generate-sdk [openapi-file] --lang typescript [--output path]
|
|
318
340
|
npx x-openapi-flow export-doc-flows [openapi-file] [--output path] [--format markdown|json]
|
|
319
|
-
npx x-openapi-flow generate-postman [openapi-file] [--output path] [--with-scripts]
|
|
320
|
-
npx x-openapi-flow generate-insomnia [openapi-file] [--output path]
|
|
321
341
|
npx x-openapi-flow generate-redoc [openapi-file] [--output path]
|
|
322
|
-
|
|
342
|
+
<!-- Demo media removed -->
|
|
323
343
|
npx x-openapi-flow doctor [--config path]
|
|
324
344
|
npx x-openapi-flow completion [bash|zsh]
|
|
325
345
|
```
|
|
@@ -332,14 +352,12 @@ npx x-openapi-flow <command> --verbose
|
|
|
332
352
|
|
|
333
353
|
Full command details:
|
|
334
354
|
|
|
335
|
-
- [docs/wiki/CLI-Reference.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/CLI-Reference.md)
|
|
355
|
+
- [docs/wiki/reference/CLI-Reference.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/reference/CLI-Reference.md)
|
|
336
356
|
- [x-openapi-flow/README.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/x-openapi-flow/README.md)
|
|
337
357
|
|
|
338
358
|
---
|
|
339
359
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
Running `init`:
|
|
360
|
+
<!-- Demo media removed -->
|
|
343
361
|
|
|
344
362
|
- Auto-detects OpenAPI source files (`openapi.yaml`, `openapi.json`, `swagger.yaml`, etc.)
|
|
345
363
|
- Creates or syncs `{context}.x.(json|yaml)` (sidecar with lifecycle metadata)
|
|
@@ -357,12 +375,8 @@ npx x-openapi-flow validate openapi.yaml --profile strict
|
|
|
357
375
|
|
|
358
376
|
## Validation Profiles
|
|
359
377
|
|
|
360
|
-
- `strict` (default): schema + advanced graph checks as errors; quality as warnings (or errors with `--strict-quality`)
|
|
361
|
-
- `relaxed`: schema and orphan checks as errors; advanced/quality checks as warnings
|
|
362
378
|
- `core`: schema and orphan checks only
|
|
363
|
-
|
|
364
|
-
Validation covers:
|
|
365
|
-
|
|
379
|
+
<!-- Demo media removed -->
|
|
366
380
|
- Schema contract correctness
|
|
367
381
|
- Orphan states
|
|
368
382
|
- Initial/terminal state structure
|
|
@@ -378,20 +392,11 @@ Validation covers:
|
|
|
378
392
|
- Postman and Insomnia: generated lifecycle-aware collections/workspaces
|
|
379
393
|
- SDK generator: TypeScript available, other languages planned
|
|
380
394
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-

|
|
384
|
-

|
|
385
|
-
|
|
395
|
+
<!-- Demo media removed -->
|
|
386
396
|
Integration docs:
|
|
387
397
|
|
|
388
|
-
- [docs/wiki/Swagger-UI-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/Swagger-UI-Integration.md)
|
|
389
|
-
- [docs/wiki/Redoc-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/Redoc-Integration.md)
|
|
390
|
-
- [docs/wiki/Postman-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/Postman-Integration.md)
|
|
391
|
-
- [docs/wiki/Insomnia-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/Insomnia-Integration.md)
|
|
392
|
-
|
|
398
|
+
- [docs/wiki/integrations/Swagger-UI-Integration.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/integrations/Swagger-UI-Integration.md)
|
|
393
399
|
---
|
|
394
|
-
|
|
395
400
|
## Copilot Ready (AI Sidecar Authoring)
|
|
396
401
|
|
|
397
402
|
Use [llm.txt](https://github.com/tiago-marques/x-openapi-flow/blob/main/llm.txt) as authoring guidance for sidecar population.
|
|
@@ -435,7 +440,7 @@ npx x-openapi-flow apply openapi.x.yaml
|
|
|
435
440
|
- `quality-warning-api.yaml` (quality warnings)
|
|
436
441
|
- `non-terminating-api.yaml` (non-terminating states)
|
|
437
442
|
|
|
438
|
-
More examples: [docs/wiki/Real-Examples.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/Real-Examples.md)
|
|
443
|
+
More examples: [docs/wiki/engineering/Real-Examples.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/engineering/Real-Examples.md)
|
|
439
444
|
|
|
440
445
|
---
|
|
441
446
|
|
|
@@ -452,7 +457,7 @@ More examples: [docs/wiki/Real-Examples.md](https://github.com/tiago-marques/x-o
|
|
|
452
457
|
## Changelog
|
|
453
458
|
|
|
454
459
|
Version history: [CHANGELOG.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/CHANGELOG.md)
|
|
455
|
-
Release notes: [RELEASE_NOTES_v1.
|
|
460
|
+
Release notes: [docs/wiki/releases/RELEASE_NOTES_v1.4.0.md](https://github.com/tiago-marques/x-openapi-flow/blob/main/docs/wiki/releases/RELEASE_NOTES_v1.4.0.md)
|
|
456
461
|
|
|
457
462
|
---
|
|
458
463
|
|
|
@@ -6,14 +6,179 @@ const { loadApi } = require("../../lib/validator");
|
|
|
6
6
|
const { buildIntermediateModel } = require("../../lib/sdk-generator");
|
|
7
7
|
const { toTitleCase, pathToPostmanUrl, buildLifecycleSequences } = require("../shared/helpers");
|
|
8
8
|
|
|
9
|
+
function getOperationMapById(api) {
|
|
10
|
+
const map = new Map();
|
|
11
|
+
const paths = (api && api.paths) || {};
|
|
12
|
+
|
|
13
|
+
for (const [pathKey, pathItem] of Object.entries(paths)) {
|
|
14
|
+
for (const [method, operation] of Object.entries(pathItem || {})) {
|
|
15
|
+
if (!operation || typeof operation !== "object") continue;
|
|
16
|
+
if (!operation.operationId) continue;
|
|
17
|
+
map.set(operation.operationId, {
|
|
18
|
+
...operation,
|
|
19
|
+
__path: pathKey,
|
|
20
|
+
__method: String(method || "get").toLowerCase(),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return map;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function buildExampleFromSchema(schema) {
|
|
29
|
+
if (!schema || typeof schema !== "object") return {};
|
|
30
|
+
|
|
31
|
+
if (Object.prototype.hasOwnProperty.call(schema, "example")) {
|
|
32
|
+
return schema.example;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (Array.isArray(schema.enum) && schema.enum.length > 0) {
|
|
36
|
+
return schema.enum[0];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (schema.default !== undefined) {
|
|
40
|
+
return schema.default;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const type = schema.type;
|
|
44
|
+
if (type === "string") {
|
|
45
|
+
if (schema.format === "date-time") return "2026-01-01T00:00:00Z";
|
|
46
|
+
if (schema.format === "date") return "2026-01-01";
|
|
47
|
+
if (schema.format === "email") return "user@example.com";
|
|
48
|
+
return "string";
|
|
49
|
+
}
|
|
50
|
+
if (type === "number" || type === "integer") return 0;
|
|
51
|
+
if (type === "boolean") return false;
|
|
52
|
+
if (type === "array") {
|
|
53
|
+
const itemExample = buildExampleFromSchema(schema.items || {});
|
|
54
|
+
return itemExample === undefined ? [] : [itemExample];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const properties = schema.properties || {};
|
|
58
|
+
const required = Array.isArray(schema.required) ? schema.required : Object.keys(properties);
|
|
59
|
+
const payload = {};
|
|
60
|
+
for (const key of required) {
|
|
61
|
+
if (!properties[key]) continue;
|
|
62
|
+
payload[key] = buildExampleFromSchema(properties[key]);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (Object.keys(payload).length === 0) {
|
|
66
|
+
for (const [key, propertySchema] of Object.entries(properties)) {
|
|
67
|
+
payload[key] = buildExampleFromSchema(propertySchema);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return payload;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function extractJsonRequestExample(rawOperation) {
|
|
75
|
+
if (!rawOperation || !rawOperation.requestBody || !rawOperation.requestBody.content) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const jsonContent = rawOperation.requestBody.content["application/json"];
|
|
80
|
+
if (!jsonContent) return null;
|
|
81
|
+
|
|
82
|
+
if (jsonContent.example !== undefined) {
|
|
83
|
+
return jsonContent.example;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (jsonContent.examples && typeof jsonContent.examples === "object") {
|
|
87
|
+
const firstExample = Object.values(jsonContent.examples)[0];
|
|
88
|
+
if (firstExample && typeof firstExample === "object" && firstExample.value !== undefined) {
|
|
89
|
+
return firstExample.value;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (jsonContent.schema) {
|
|
94
|
+
return buildExampleFromSchema(jsonContent.schema);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function buildJourneyName(sequence, index) {
|
|
101
|
+
if (!Array.isArray(sequence) || sequence.length === 0) {
|
|
102
|
+
return `Journey ${index + 1}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (sequence.length === 1) {
|
|
106
|
+
return `Journey ${index + 1}: ${sequence[0].operationId}`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const first = sequence[0].operationId;
|
|
110
|
+
const last = sequence[sequence.length - 1].operationId;
|
|
111
|
+
return `Journey ${index + 1}: ${first} -> ${last}`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function buildFlowDescription(operation) {
|
|
115
|
+
const lines = [];
|
|
116
|
+
|
|
117
|
+
if (operation.currentState) {
|
|
118
|
+
lines.push(`Current state: ${operation.currentState}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (Array.isArray(operation.prerequisites) && operation.prerequisites.length > 0) {
|
|
122
|
+
lines.push(`Prerequisites: ${operation.prerequisites.join(", ")}`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (Array.isArray(operation.nextOperations) && operation.nextOperations.length > 0) {
|
|
126
|
+
const transitions = operation.nextOperations
|
|
127
|
+
.map((next) => {
|
|
128
|
+
const parts = [];
|
|
129
|
+
if (next.targetState) parts.push(`state ${next.targetState}`);
|
|
130
|
+
if (next.nextOperationId) parts.push(`op ${next.nextOperationId}`);
|
|
131
|
+
if (next.triggerType) parts.push(`trigger ${next.triggerType}`);
|
|
132
|
+
return parts.join(" | ");
|
|
133
|
+
})
|
|
134
|
+
.filter(Boolean);
|
|
135
|
+
if (transitions.length > 0) {
|
|
136
|
+
lines.push(`Next: ${transitions.join(" ; ")}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return lines.join("\n");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function createInsomniaRequest(requestId, parentId, operation, resource, rawOperation) {
|
|
144
|
+
const request = {
|
|
145
|
+
_id: requestId,
|
|
146
|
+
_type: "request",
|
|
147
|
+
parentId,
|
|
148
|
+
name: operation.operationId,
|
|
149
|
+
method: String(operation.httpMethod || "get").toUpperCase(),
|
|
150
|
+
url: `{{ base_url }}${pathToPostmanUrl(operation.path, resource.resourcePropertyName)}`,
|
|
151
|
+
headers: [],
|
|
152
|
+
body: {},
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const description = buildFlowDescription(operation);
|
|
156
|
+
if (description) {
|
|
157
|
+
request.description = description;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (["POST", "PUT", "PATCH"].includes(request.method)) {
|
|
161
|
+
request.headers.push({ name: "Content-Type", value: "application/json" });
|
|
162
|
+
const bodyExample = extractJsonRequestExample(rawOperation);
|
|
163
|
+
request.body = {
|
|
164
|
+
mimeType: "application/json",
|
|
165
|
+
text: JSON.stringify(bodyExample !== null ? bodyExample : {}, null, 2),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return request;
|
|
170
|
+
}
|
|
171
|
+
|
|
9
172
|
function generateInsomniaWorkspace(options) {
|
|
10
173
|
const apiPath = path.resolve(options.apiPath);
|
|
11
174
|
const outputPath = path.resolve(options.outputPath || path.join(process.cwd(), "x-openapi-flow.insomnia.json"));
|
|
12
175
|
|
|
13
176
|
const api = loadApi(apiPath);
|
|
14
177
|
const model = buildIntermediateModel(api);
|
|
178
|
+
const operationMapById = getOperationMapById(api);
|
|
15
179
|
|
|
16
180
|
const workspaceId = "wrk_x_openapi_flow";
|
|
181
|
+
const environmentId = "env_x_openapi_flow_base";
|
|
17
182
|
const resources = [
|
|
18
183
|
{
|
|
19
184
|
_id: workspaceId,
|
|
@@ -22,6 +187,15 @@ function generateInsomniaWorkspace(options) {
|
|
|
22
187
|
description: `Generated from ${apiPath}`,
|
|
23
188
|
scope: "collection",
|
|
24
189
|
},
|
|
190
|
+
{
|
|
191
|
+
_id: environmentId,
|
|
192
|
+
_type: "environment",
|
|
193
|
+
parentId: workspaceId,
|
|
194
|
+
name: "Base Environment",
|
|
195
|
+
data: {
|
|
196
|
+
base_url: "http://localhost:3000",
|
|
197
|
+
},
|
|
198
|
+
},
|
|
25
199
|
];
|
|
26
200
|
|
|
27
201
|
for (const resource of model.resources) {
|
|
@@ -34,22 +208,44 @@ function generateInsomniaWorkspace(options) {
|
|
|
34
208
|
});
|
|
35
209
|
|
|
36
210
|
const sequences = buildLifecycleSequences(resource);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
211
|
+
if (sequences.length > 0) {
|
|
212
|
+
sequences.forEach((sequence, sequenceIndex) => {
|
|
213
|
+
const journeyId = `fld_${resource.resourcePropertyName}_journey_${sequenceIndex + 1}`;
|
|
214
|
+
resources.push({
|
|
215
|
+
_id: journeyId,
|
|
216
|
+
_type: "request_group",
|
|
217
|
+
parentId: groupId,
|
|
218
|
+
name: buildJourneyName(sequence, sequenceIndex),
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
sequence.forEach((operation, operationIndex) => {
|
|
222
|
+
const requestId = `req_${resource.resourcePropertyName}_${sequenceIndex + 1}_${operationIndex + 1}`;
|
|
223
|
+
resources.push(
|
|
224
|
+
createInsomniaRequest(
|
|
225
|
+
requestId,
|
|
226
|
+
journeyId,
|
|
227
|
+
operation,
|
|
228
|
+
resource,
|
|
229
|
+
operationMapById.get(operation.operationId)
|
|
230
|
+
)
|
|
231
|
+
);
|
|
232
|
+
});
|
|
51
233
|
});
|
|
52
|
-
}
|
|
234
|
+
} else {
|
|
235
|
+
const operations = resource.operations.filter((operation) => operation.hasFlow);
|
|
236
|
+
operations.forEach((operation, index) => {
|
|
237
|
+
const requestId = `req_${resource.resourcePropertyName}_${index + 1}`;
|
|
238
|
+
resources.push(
|
|
239
|
+
createInsomniaRequest(
|
|
240
|
+
requestId,
|
|
241
|
+
groupId,
|
|
242
|
+
operation,
|
|
243
|
+
resource,
|
|
244
|
+
operationMapById.get(operation.operationId)
|
|
245
|
+
)
|
|
246
|
+
);
|
|
247
|
+
});
|
|
248
|
+
}
|
|
53
249
|
}
|
|
54
250
|
|
|
55
251
|
const exportPayload = {
|