x-openapi-flow 1.2.1 → 1.2.3

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
@@ -36,9 +36,15 @@ Use a GitHub PAT with `read:packages` (install) and `write:packages` (publish).
36
36
  ## Quick Start
37
37
 
38
38
  ```bash
39
- x-openapi-flow validate openapi.yaml
40
- x-openapi-flow graph openapi.yaml
41
- x-openapi-flow doctor
39
+ npx x-openapi-flow init openapi.yaml
40
+ npx x-openapi-flow apply openapi.yaml
41
+ ```
42
+
43
+ Optional checks:
44
+
45
+ ```bash
46
+ npx x-openapi-flow validate openapi.yaml --profile strict
47
+ npx x-openapi-flow graph openapi.yaml
42
48
  ```
43
49
 
44
50
  ## CLI Commands
@@ -100,7 +106,7 @@ Field reference format:
100
106
  ### Swagger UI
101
107
 
102
108
  - There is no Swagger UI-based automated test in this repo today (tests are CLI-only).
103
- - For UI interpretation of `x-openapi-flow`, use `showExtensions: true` plus the example plugin at `examples/swagger-ui/x-openapi-flow-plugin.js`.
109
+ - For UI interpretation of `x-openapi-flow`, use `showExtensions: true` plus the plugin at `lib/swagger-ui/x-openapi-flow-plugin.js`.
104
110
  - A ready HTML example is available at `examples/swagger-ui/index.html`.
105
111
  - The plugin renders a global **Flow Overview** (Mermaid image) near the top of the docs, plus operation-level flow cards.
106
112
 
@@ -44,7 +44,7 @@ function printHelp() {
44
44
  Usage:
45
45
  x-openapi-flow validate <openapi-file> [--format pretty|json] [--profile core|relaxed|strict] [--strict-quality] [--config path]
46
46
  x-openapi-flow init [openapi-file] [--flows path]
47
- x-openapi-flow apply [openapi-file] [--flows path] [--out path]
47
+ x-openapi-flow apply [openapi-file] [--flows path] [--out path] [--in-place]
48
48
  x-openapi-flow graph <openapi-file> [--format mermaid|json]
49
49
  x-openapi-flow doctor [--config path]
50
50
  x-openapi-flow --help
@@ -56,12 +56,19 @@ Examples:
56
56
  x-openapi-flow init openapi.yaml --flows openapi-openapi-flow.yaml
57
57
  x-openapi-flow init
58
58
  x-openapi-flow apply openapi.yaml
59
+ x-openapi-flow apply openapi.yaml --in-place
59
60
  x-openapi-flow apply openapi.yaml --out openapi.flow.yaml
60
61
  x-openapi-flow graph examples/order-api.yaml
61
62
  x-openapi-flow doctor
62
63
  `);
63
64
  }
64
65
 
66
+ function deriveFlowOutputPath(openApiFile) {
67
+ const parsed = path.parse(openApiFile);
68
+ const extension = parsed.ext || ".yaml";
69
+ return path.join(parsed.dir, `${parsed.name}.flow${extension}`);
70
+ }
71
+
65
72
  function getOptionValue(args, optionName) {
66
73
  const index = args.indexOf(optionName);
67
74
  if (index === -1) {
@@ -199,7 +206,7 @@ function parseInitArgs(args) {
199
206
  }
200
207
 
201
208
  function parseApplyArgs(args) {
202
- const unknown = findUnknownOptions(args, ["--flows", "--out"], []);
209
+ const unknown = findUnknownOptions(args, ["--flows", "--out"], ["--in-place"]);
203
210
  if (unknown) {
204
211
  return { error: `Unknown option: ${unknown}` };
205
212
  }
@@ -214,8 +221,13 @@ function parseApplyArgs(args) {
214
221
  return { error: outOpt.error };
215
222
  }
216
223
 
224
+ const inPlace = args.includes("--in-place");
225
+ if (inPlace && outOpt.found) {
226
+ return { error: "Options --in-place and --out cannot be used together." };
227
+ }
228
+
217
229
  const positional = args.filter((token, index) => {
218
- if (token === "--flows" || token === "--out") {
230
+ if (token === "--flows" || token === "--out" || token === "--in-place") {
219
231
  return false;
220
232
  }
221
233
  if (index > 0 && (args[index - 1] === "--flows" || args[index - 1] === "--out")) {
@@ -232,6 +244,7 @@ function parseApplyArgs(args) {
232
244
  openApiFile: positional[0] ? path.resolve(positional[0]) : undefined,
233
245
  flowsPath: flowsOpt.found ? path.resolve(flowsOpt.value) : undefined,
234
246
  outPath: outOpt.found ? path.resolve(outOpt.value) : undefined,
247
+ inPlace,
235
248
  };
236
249
  }
237
250
 
@@ -656,7 +669,9 @@ function runApply(parsed) {
656
669
  }
657
670
 
658
671
  const appliedCount = applyFlowsToOpenApi(api, flowsDoc);
659
- const outputPath = parsed.outPath || targetOpenApiFile;
672
+ const outputPath = parsed.inPlace
673
+ ? targetOpenApiFile
674
+ : (parsed.outPath || deriveFlowOutputPath(targetOpenApiFile));
660
675
  saveOpenApi(outputPath, api);
661
676
 
662
677
  console.log(`OpenAPI source: ${targetOpenApiFile}`);
@@ -18,7 +18,7 @@
18
18
  <script>
19
19
  window.XOpenApiFlowGraphImageUrl = "https://raw.githubusercontent.com/tiago-marques/x-openapi-flow/main/docs/assets/graph-order-guided.svg";
20
20
  </script>
21
- <script src="./x-openapi-flow-plugin.js"></script>
21
+ <script src="../../lib/swagger-ui/x-openapi-flow-plugin.js"></script>
22
22
  <script>
23
23
  window.ui = SwaggerUIBundle({
24
24
  url: "../payment-api.yaml",
@@ -256,6 +256,10 @@ window.XOpenApiFlowPlugin = function () {
256
256
  return result;
257
257
  }
258
258
 
259
+ function hasFlowData(spec) {
260
+ return extractFlowsFromSpec(spec).length > 0;
261
+ }
262
+
259
263
  function buildOverviewMermaid(flows) {
260
264
  const lines = ['stateDiagram-v2'];
261
265
  const states = new Set();
@@ -331,6 +335,8 @@ window.XOpenApiFlowPlugin = function () {
331
335
  }
332
336
 
333
337
  let overviewRenderedHash = null;
338
+ let overviewRenderInProgress = false;
339
+ let overviewPendingHash = null;
334
340
  async function renderOverview() {
335
341
  const spec = getSpecFromUi();
336
342
  const flows = extractFlowsFromSpec(spec);
@@ -339,6 +345,7 @@ window.XOpenApiFlowPlugin = function () {
339
345
  const mermaid = buildOverviewMermaid(flows);
340
346
  const currentHash = `${flows.length}:${mermaid}`;
341
347
  if (overviewRenderedHash === currentHash) return;
348
+ if (overviewRenderInProgress && overviewPendingHash === currentHash) return;
342
349
 
343
350
  const infoContainer = document.querySelector('.swagger-ui .information-container');
344
351
  if (!infoContainer) return;
@@ -352,6 +359,8 @@ window.XOpenApiFlowPlugin = function () {
352
359
  }
353
360
 
354
361
  holder.innerHTML = '<div class="xof-title">x-openapi-flow — Flow Overview</div><div class="xof-empty">Rendering Mermaid graph...</div>';
362
+ overviewRenderInProgress = true;
363
+ overviewPendingHash = currentHash;
355
364
 
356
365
  try {
357
366
  const mermaidLib = await ensureMermaid();
@@ -374,6 +383,8 @@ window.XOpenApiFlowPlugin = function () {
374
383
  <div class="xof-empty">Could not render Mermaid image in this environment.</div>
375
384
  <div class="xof-overview-code">${mermaid.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</div>
376
385
  `;
386
+ } finally {
387
+ overviewRenderInProgress = false;
377
388
  }
378
389
 
379
390
  overviewRenderedHash = currentHash;
@@ -410,18 +421,35 @@ window.XOpenApiFlowPlugin = function () {
410
421
  }
411
422
 
412
423
  function enhanceAll() {
424
+ const spec = getSpecFromUi();
425
+ if (!hasFlowData(spec)) {
426
+ return;
427
+ }
428
+
413
429
  injectStyles();
414
430
  const opblocks = document.querySelectorAll('.opblock');
415
431
  opblocks.forEach((opblock) => enhanceOperation(opblock));
416
- renderOverview();
432
+ renderOverview().catch(() => {
433
+ // keep plugin resilient in environments where async rendering fails
434
+ });
435
+ }
436
+
437
+ let enhanceScheduled = false;
438
+ function scheduleEnhance() {
439
+ if (enhanceScheduled) return;
440
+ enhanceScheduled = true;
441
+ window.requestAnimationFrame(() => {
442
+ enhanceScheduled = false;
443
+ enhanceAll();
444
+ });
417
445
  }
418
446
 
419
447
  const observer = new MutationObserver(() => {
420
- enhanceAll();
448
+ scheduleEnhance();
421
449
  });
422
450
 
423
451
  window.addEventListener('load', () => {
424
- enhanceAll();
452
+ scheduleEnhance();
425
453
  observer.observe(document.body, { childList: true, subtree: true });
426
454
  });
427
455
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x-openapi-flow",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "OpenAPI extension for resource workflow and lifecycle management",
5
5
  "main": "lib/validator.js",
6
6
  "repository": {