@flanksource/clicky-ui 0.3.12 → 0.3.14

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 (53) hide show
  1. package/dist/data/ai/SessionViewer.input.cjs +2 -1
  2. package/dist/data/ai/SessionViewer.input.cjs.map +1 -1
  3. package/dist/data/ai/SessionViewer.input.d.ts.map +1 -1
  4. package/dist/data/ai/SessionViewer.input.js +2 -1
  5. package/dist/data/ai/SessionViewer.input.js.map +1 -1
  6. package/dist/data/diagnostics/error-diagnostics.cjs +38 -6
  7. package/dist/data/diagnostics/error-diagnostics.cjs.map +1 -1
  8. package/dist/data/diagnostics/error-diagnostics.js +38 -6
  9. package/dist/data/diagnostics/error-diagnostics.js.map +1 -1
  10. package/dist/data/diagnostics/jvm-stacktrace.cjs +35 -3
  11. package/dist/data/diagnostics/jvm-stacktrace.cjs.map +1 -1
  12. package/dist/data/diagnostics/jvm-stacktrace.d.ts.map +1 -1
  13. package/dist/data/diagnostics/jvm-stacktrace.js +35 -3
  14. package/dist/data/diagnostics/jvm-stacktrace.js.map +1 -1
  15. package/dist/data/diagnostics/stacktrace-parse.cjs +19 -5
  16. package/dist/data/diagnostics/stacktrace-parse.cjs.map +1 -1
  17. package/dist/data/diagnostics/stacktrace-parse.d.ts.map +1 -1
  18. package/dist/data/diagnostics/stacktrace-parse.js +19 -5
  19. package/dist/data/diagnostics/stacktrace-parse.js.map +1 -1
  20. package/dist/data/diagnostics/stacktrace.cjs +50 -7
  21. package/dist/data/diagnostics/stacktrace.cjs.map +1 -1
  22. package/dist/data/diagnostics/stacktrace.d.ts.map +1 -1
  23. package/dist/data/diagnostics/stacktrace.js +50 -7
  24. package/dist/data/diagnostics/stacktrace.js.map +1 -1
  25. package/dist/data/test-runner/routePath.cjs +3 -1
  26. package/dist/data/test-runner/routePath.cjs.map +1 -1
  27. package/dist/data/test-runner/routePath.d.ts.map +1 -1
  28. package/dist/data/test-runner/routePath.js +3 -1
  29. package/dist/data/test-runner/routePath.js.map +1 -1
  30. package/dist/data/version-info.cjs +3 -3
  31. package/dist/data/version-info.js +3 -3
  32. package/dist/lib/string.cjs +15 -0
  33. package/dist/lib/string.cjs.map +1 -0
  34. package/dist/lib/string.d.ts +3 -0
  35. package/dist/lib/string.d.ts.map +1 -0
  36. package/dist/lib/string.js +15 -0
  37. package/dist/lib/string.js.map +1 -0
  38. package/dist/rpc/OperationActionDialog.cjs +4 -10
  39. package/dist/rpc/OperationActionDialog.cjs.map +1 -1
  40. package/dist/rpc/OperationActionDialog.d.ts.map +1 -1
  41. package/dist/rpc/OperationActionDialog.js +2 -8
  42. package/dist/rpc/OperationActionDialog.js.map +1 -1
  43. package/dist/rpc/OperationCommandPage.cjs +3 -2
  44. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  45. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  46. package/dist/rpc/OperationCommandPage.js +3 -2
  47. package/dist/rpc/OperationCommandPage.js.map +1 -1
  48. package/dist/rpc/apiClient.cjs +2 -1
  49. package/dist/rpc/apiClient.cjs.map +1 -1
  50. package/dist/rpc/apiClient.d.ts.map +1 -1
  51. package/dist/rpc/apiClient.js +2 -1
  52. package/dist/rpc/apiClient.js.map +1 -1
  53. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"routePath.cjs","sources":["../../../src/data/test-runner/routePath.ts"],"sourcesContent":["// Stable, URL-safe paths for selection/navigation. A host that wants to encode\n// the selected node in its route annotates the forest once with annotateRoutePaths\n// (writing Test.route_path), then resolves a path back to a node with\n// findNodeByRoutePath. Tree's nodeKey already prefers route_path, so an annotated\n// forest also gets stable React keys for free.\n\nimport type { Test } from \"./types\";\n\nexport function slugify(value: string): string {\n const slug = (value || \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return slug || \"node\";\n}\n\n/**\n * Return a deep copy of the forest with a stable, unique `route_path` on every\n * node. Each segment is the slug of the node's name; siblings that slug to the\n * same value are disambiguated with a `~N` ordinal so paths stay unique.\n */\nexport function annotateRoutePaths(nodes: Test[], parentSegments: string[] = []): Test[] {\n const counts = new Map<string, number>();\n for (const node of nodes) {\n const slug = slugify(node.name);\n counts.set(slug, (counts.get(slug) || 0) + 1);\n }\n\n const seen = new Map<string, number>();\n return nodes.map((node) => {\n const slug = slugify(node.name);\n const ordinal = (seen.get(slug) || 0) + 1;\n seen.set(slug, ordinal);\n const finalSlug = (counts.get(slug) || 0) > 1 ? `${slug}~${ordinal}` : slug;\n const segments = [...parentSegments, finalSlug];\n const annotated: Test = { ...node, route_path: segments.join(\"/\") };\n if (node.children) annotated.children = annotateRoutePaths(node.children, segments);\n return annotated;\n });\n}\n\n/** Depth-first lookup of the node whose route_path equals target, or null. */\nexport function findNodeByRoutePath(nodes: Test[], target: string): Test | null {\n if (!target) return null;\n for (const node of nodes) {\n if (node.route_path === target) return node;\n if (node.children) {\n const child = findNodeByRoutePath(node.children, target);\n if (child) return child;\n }\n }\n return null;\n}\n"],"names":[],"mappings":";;AAQO,SAAS,QAAQ,OAAuB;AAC7C,QAAM,QAAQ,SAAS,IACpB,YAAA,EACA,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AACzB,SAAO,QAAQ;AACjB;AAOO,SAAS,mBAAmB,OAAe,iBAA2B,IAAY;AACvF,QAAM,6BAAa,IAAA;AACnB,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,WAAO,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,KAAK,CAAC;AAAA,EAC9C;AAEA,QAAM,2BAAW,IAAA;AACjB,SAAO,MAAM,IAAI,CAAC,SAAS;AACzB,UAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,UAAM,WAAW,KAAK,IAAI,IAAI,KAAK,KAAK;AACxC,SAAK,IAAI,MAAM,OAAO;AACtB,UAAM,aAAa,OAAO,IAAI,IAAI,KAAK,KAAK,IAAI,GAAG,IAAI,IAAI,OAAO,KAAK;AACvE,UAAM,WAAW,CAAC,GAAG,gBAAgB,SAAS;AAC9C,UAAM,YAAkB,EAAE,GAAG,MAAM,YAAY,SAAS,KAAK,GAAG,EAAA;AAChE,QAAI,KAAK,SAAU,WAAU,WAAW,mBAAmB,KAAK,UAAU,QAAQ;AAClF,WAAO;AAAA,EACT,CAAC;AACH;AAGO,SAAS,oBAAoB,OAAe,QAA6B;AAC9E,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,eAAe,OAAQ,QAAO;AACvC,QAAI,KAAK,UAAU;AACjB,YAAM,QAAQ,oBAAoB,KAAK,UAAU,MAAM;AACvD,UAAI,MAAO,QAAO;AAAA,IACpB;AAAA,EACF;AACA,SAAO;AACT;;;;"}
1
+ {"version":3,"file":"routePath.cjs","sources":["../../../src/data/test-runner/routePath.ts"],"sourcesContent":["// Stable, URL-safe paths for selection/navigation. A host that wants to encode\n// the selected node in its route annotates the forest once with annotateRoutePaths\n// (writing Test.route_path), then resolves a path back to a node with\n// findNodeByRoutePath. Tree's nodeKey already prefers route_path, so an annotated\n// forest also gets stable React keys for free.\n\nimport type { Test } from \"./types\";\n\nexport function slugify(value: string): string {\n let slug = (value || \"\").toLowerCase().replace(/[^a-z0-9]+/g, \"-\");\n if (slug.startsWith(\"-\")) slug = slug.slice(1);\n if (slug.endsWith(\"-\")) slug = slug.slice(0, -1);\n return slug || \"node\";\n}\n\n/**\n * Return a deep copy of the forest with a stable, unique `route_path` on every\n * node. Each segment is the slug of the node's name; siblings that slug to the\n * same value are disambiguated with a `~N` ordinal so paths stay unique.\n */\nexport function annotateRoutePaths(nodes: Test[], parentSegments: string[] = []): Test[] {\n const counts = new Map<string, number>();\n for (const node of nodes) {\n const slug = slugify(node.name);\n counts.set(slug, (counts.get(slug) || 0) + 1);\n }\n\n const seen = new Map<string, number>();\n return nodes.map((node) => {\n const slug = slugify(node.name);\n const ordinal = (seen.get(slug) || 0) + 1;\n seen.set(slug, ordinal);\n const finalSlug = (counts.get(slug) || 0) > 1 ? `${slug}~${ordinal}` : slug;\n const segments = [...parentSegments, finalSlug];\n const annotated: Test = { ...node, route_path: segments.join(\"/\") };\n if (node.children) annotated.children = annotateRoutePaths(node.children, segments);\n return annotated;\n });\n}\n\n/** Depth-first lookup of the node whose route_path equals target, or null. */\nexport function findNodeByRoutePath(nodes: Test[], target: string): Test | null {\n if (!target) return null;\n for (const node of nodes) {\n if (node.route_path === target) return node;\n if (node.children) {\n const child = findNodeByRoutePath(node.children, target);\n if (child) return child;\n }\n }\n return null;\n}\n"],"names":[],"mappings":";;AAQO,SAAS,QAAQ,OAAuB;AAC7C,MAAI,QAAQ,SAAS,IAAI,cAAc,QAAQ,eAAe,GAAG;AACjE,MAAI,KAAK,WAAW,GAAG,EAAG,QAAO,KAAK,MAAM,CAAC;AAC7C,MAAI,KAAK,SAAS,GAAG,UAAU,KAAK,MAAM,GAAG,EAAE;AAC/C,SAAO,QAAQ;AACjB;AAOO,SAAS,mBAAmB,OAAe,iBAA2B,IAAY;AACvF,QAAM,6BAAa,IAAA;AACnB,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,WAAO,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,KAAK,CAAC;AAAA,EAC9C;AAEA,QAAM,2BAAW,IAAA;AACjB,SAAO,MAAM,IAAI,CAAC,SAAS;AACzB,UAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,UAAM,WAAW,KAAK,IAAI,IAAI,KAAK,KAAK;AACxC,SAAK,IAAI,MAAM,OAAO;AACtB,UAAM,aAAa,OAAO,IAAI,IAAI,KAAK,KAAK,IAAI,GAAG,IAAI,IAAI,OAAO,KAAK;AACvE,UAAM,WAAW,CAAC,GAAG,gBAAgB,SAAS;AAC9C,UAAM,YAAkB,EAAE,GAAG,MAAM,YAAY,SAAS,KAAK,GAAG,EAAA;AAChE,QAAI,KAAK,SAAU,WAAU,WAAW,mBAAmB,KAAK,UAAU,QAAQ;AAClF,WAAO;AAAA,EACT,CAAC;AACH;AAGO,SAAS,oBAAoB,OAAe,QAA6B;AAC9E,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,eAAe,OAAQ,QAAO;AACvC,QAAI,KAAK,UAAU;AACjB,YAAM,QAAQ,oBAAoB,KAAK,UAAU,MAAM;AACvD,UAAI,MAAO,QAAO;AAAA,IACpB;AAAA,EACF;AACA,SAAO;AACT;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"routePath.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/routePath.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAEpC,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM7C;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,cAAc,GAAE,MAAM,EAAO,GAAG,IAAI,EAAE,CAkBvF;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAU9E"}
1
+ {"version":3,"file":"routePath.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/routePath.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAEpC,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK7C;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,cAAc,GAAE,MAAM,EAAO,GAAG,IAAI,EAAE,CAkBvF;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAU9E"}
@@ -1,5 +1,7 @@
1
1
  function slugify(value) {
2
- const slug = (value || "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
2
+ let slug = (value || "").toLowerCase().replace(/[^a-z0-9]+/g, "-");
3
+ if (slug.startsWith("-")) slug = slug.slice(1);
4
+ if (slug.endsWith("-")) slug = slug.slice(0, -1);
3
5
  return slug || "node";
4
6
  }
5
7
  function annotateRoutePaths(nodes, parentSegments = []) {
@@ -1 +1 @@
1
- {"version":3,"file":"routePath.js","sources":["../../../src/data/test-runner/routePath.ts"],"sourcesContent":["// Stable, URL-safe paths for selection/navigation. A host that wants to encode\n// the selected node in its route annotates the forest once with annotateRoutePaths\n// (writing Test.route_path), then resolves a path back to a node with\n// findNodeByRoutePath. Tree's nodeKey already prefers route_path, so an annotated\n// forest also gets stable React keys for free.\n\nimport type { Test } from \"./types\";\n\nexport function slugify(value: string): string {\n const slug = (value || \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return slug || \"node\";\n}\n\n/**\n * Return a deep copy of the forest with a stable, unique `route_path` on every\n * node. Each segment is the slug of the node's name; siblings that slug to the\n * same value are disambiguated with a `~N` ordinal so paths stay unique.\n */\nexport function annotateRoutePaths(nodes: Test[], parentSegments: string[] = []): Test[] {\n const counts = new Map<string, number>();\n for (const node of nodes) {\n const slug = slugify(node.name);\n counts.set(slug, (counts.get(slug) || 0) + 1);\n }\n\n const seen = new Map<string, number>();\n return nodes.map((node) => {\n const slug = slugify(node.name);\n const ordinal = (seen.get(slug) || 0) + 1;\n seen.set(slug, ordinal);\n const finalSlug = (counts.get(slug) || 0) > 1 ? `${slug}~${ordinal}` : slug;\n const segments = [...parentSegments, finalSlug];\n const annotated: Test = { ...node, route_path: segments.join(\"/\") };\n if (node.children) annotated.children = annotateRoutePaths(node.children, segments);\n return annotated;\n });\n}\n\n/** Depth-first lookup of the node whose route_path equals target, or null. */\nexport function findNodeByRoutePath(nodes: Test[], target: string): Test | null {\n if (!target) return null;\n for (const node of nodes) {\n if (node.route_path === target) return node;\n if (node.children) {\n const child = findNodeByRoutePath(node.children, target);\n if (child) return child;\n }\n }\n return null;\n}\n"],"names":[],"mappings":"AAQO,SAAS,QAAQ,OAAuB;AAC7C,QAAM,QAAQ,SAAS,IACpB,YAAA,EACA,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AACzB,SAAO,QAAQ;AACjB;AAOO,SAAS,mBAAmB,OAAe,iBAA2B,IAAY;AACvF,QAAM,6BAAa,IAAA;AACnB,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,WAAO,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,KAAK,CAAC;AAAA,EAC9C;AAEA,QAAM,2BAAW,IAAA;AACjB,SAAO,MAAM,IAAI,CAAC,SAAS;AACzB,UAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,UAAM,WAAW,KAAK,IAAI,IAAI,KAAK,KAAK;AACxC,SAAK,IAAI,MAAM,OAAO;AACtB,UAAM,aAAa,OAAO,IAAI,IAAI,KAAK,KAAK,IAAI,GAAG,IAAI,IAAI,OAAO,KAAK;AACvE,UAAM,WAAW,CAAC,GAAG,gBAAgB,SAAS;AAC9C,UAAM,YAAkB,EAAE,GAAG,MAAM,YAAY,SAAS,KAAK,GAAG,EAAA;AAChE,QAAI,KAAK,SAAU,WAAU,WAAW,mBAAmB,KAAK,UAAU,QAAQ;AAClF,WAAO;AAAA,EACT,CAAC;AACH;AAGO,SAAS,oBAAoB,OAAe,QAA6B;AAC9E,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,eAAe,OAAQ,QAAO;AACvC,QAAI,KAAK,UAAU;AACjB,YAAM,QAAQ,oBAAoB,KAAK,UAAU,MAAM;AACvD,UAAI,MAAO,QAAO;AAAA,IACpB;AAAA,EACF;AACA,SAAO;AACT;"}
1
+ {"version":3,"file":"routePath.js","sources":["../../../src/data/test-runner/routePath.ts"],"sourcesContent":["// Stable, URL-safe paths for selection/navigation. A host that wants to encode\n// the selected node in its route annotates the forest once with annotateRoutePaths\n// (writing Test.route_path), then resolves a path back to a node with\n// findNodeByRoutePath. Tree's nodeKey already prefers route_path, so an annotated\n// forest also gets stable React keys for free.\n\nimport type { Test } from \"./types\";\n\nexport function slugify(value: string): string {\n let slug = (value || \"\").toLowerCase().replace(/[^a-z0-9]+/g, \"-\");\n if (slug.startsWith(\"-\")) slug = slug.slice(1);\n if (slug.endsWith(\"-\")) slug = slug.slice(0, -1);\n return slug || \"node\";\n}\n\n/**\n * Return a deep copy of the forest with a stable, unique `route_path` on every\n * node. Each segment is the slug of the node's name; siblings that slug to the\n * same value are disambiguated with a `~N` ordinal so paths stay unique.\n */\nexport function annotateRoutePaths(nodes: Test[], parentSegments: string[] = []): Test[] {\n const counts = new Map<string, number>();\n for (const node of nodes) {\n const slug = slugify(node.name);\n counts.set(slug, (counts.get(slug) || 0) + 1);\n }\n\n const seen = new Map<string, number>();\n return nodes.map((node) => {\n const slug = slugify(node.name);\n const ordinal = (seen.get(slug) || 0) + 1;\n seen.set(slug, ordinal);\n const finalSlug = (counts.get(slug) || 0) > 1 ? `${slug}~${ordinal}` : slug;\n const segments = [...parentSegments, finalSlug];\n const annotated: Test = { ...node, route_path: segments.join(\"/\") };\n if (node.children) annotated.children = annotateRoutePaths(node.children, segments);\n return annotated;\n });\n}\n\n/** Depth-first lookup of the node whose route_path equals target, or null. */\nexport function findNodeByRoutePath(nodes: Test[], target: string): Test | null {\n if (!target) return null;\n for (const node of nodes) {\n if (node.route_path === target) return node;\n if (node.children) {\n const child = findNodeByRoutePath(node.children, target);\n if (child) return child;\n }\n }\n return null;\n}\n"],"names":[],"mappings":"AAQO,SAAS,QAAQ,OAAuB;AAC7C,MAAI,QAAQ,SAAS,IAAI,cAAc,QAAQ,eAAe,GAAG;AACjE,MAAI,KAAK,WAAW,GAAG,EAAG,QAAO,KAAK,MAAM,CAAC;AAC7C,MAAI,KAAK,SAAS,GAAG,UAAU,KAAK,MAAM,GAAG,EAAE;AAC/C,SAAO,QAAQ;AACjB;AAOO,SAAS,mBAAmB,OAAe,iBAA2B,IAAY;AACvF,QAAM,6BAAa,IAAA;AACnB,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,WAAO,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,KAAK,CAAC;AAAA,EAC9C;AAEA,QAAM,2BAAW,IAAA;AACjB,SAAO,MAAM,IAAI,CAAC,SAAS;AACzB,UAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,UAAM,WAAW,KAAK,IAAI,IAAI,KAAK,KAAK;AACxC,SAAK,IAAI,MAAM,OAAO;AACtB,UAAM,aAAa,OAAO,IAAI,IAAI,KAAK,KAAK,IAAI,GAAG,IAAI,IAAI,OAAO,KAAK;AACvE,UAAM,WAAW,CAAC,GAAG,gBAAgB,SAAS;AAC9C,UAAM,YAAkB,EAAE,GAAG,MAAM,YAAY,SAAS,KAAK,GAAG,EAAA;AAChE,QAAI,KAAK,SAAU,WAAU,WAAW,mBAAmB,KAAK,UAAU,QAAQ;AAClF,WAAO;AAAA,EACT,CAAC;AACH;AAGO,SAAS,oBAAoB,OAAe,QAA6B;AAC9E,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,eAAe,OAAQ,QAAO;AACvC,QAAI,KAAK,UAAU;AACjB,YAAM,QAAQ,oBAAoB,KAAK,UAAU,MAAM;AACvD,UAAI,MAAO,QAAO;AAAA,IACpB;AAAA,EACF;AACA,SAAO;AACT;"}
@@ -15,9 +15,9 @@ function detectMode() {
15
15
  }
16
16
  function getVersionInfo() {
17
17
  return {
18
- commit: read(() => "8467248c", ""),
19
- tag: read(() => "clicky-ui@0.3.11", ""),
20
- date: read(() => "2026-07-16T15:46:57.662Z", ""),
18
+ commit: read(() => "2ab76b33", ""),
19
+ tag: read(() => "clicky-ui@0.3.13", ""),
20
+ date: read(() => "2026-07-16T18:37:04.048Z", ""),
21
21
  dirty: read(() => true, false),
22
22
  mode: detectMode()
23
23
  };
@@ -13,9 +13,9 @@ function detectMode() {
13
13
  }
14
14
  function getVersionInfo() {
15
15
  return {
16
- commit: read(() => "8467248c", ""),
17
- tag: read(() => "clicky-ui@0.3.11", ""),
18
- date: read(() => "2026-07-16T15:46:39.266Z", ""),
16
+ commit: read(() => "2ab76b33", ""),
17
+ tag: read(() => "clicky-ui@0.3.13", ""),
18
+ date: read(() => "2026-07-16T18:36:45.992Z", ""),
19
19
  dirty: read(() => true, false),
20
20
  mode: detectMode()
21
21
  };
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ function stripLeadingSlashes(value) {
4
+ let start = 0;
5
+ while (start < value.length && value[start] === "/") start++;
6
+ return value.slice(start);
7
+ }
8
+ function stripTrailingSlashes(value) {
9
+ let end = value.length;
10
+ while (end > 0 && value[end - 1] === "/") end--;
11
+ return value.slice(0, end);
12
+ }
13
+ exports.stripLeadingSlashes = stripLeadingSlashes;
14
+ exports.stripTrailingSlashes = stripTrailingSlashes;
15
+ //# sourceMappingURL=string.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string.cjs","sources":["../../src/lib/string.ts"],"sourcesContent":["export function stripLeadingSlashes(value: string): string {\n let start = 0;\n while (start < value.length && value[start] === \"/\") start++;\n return value.slice(start);\n}\n\nexport function stripTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end--;\n return value.slice(0, end);\n}\n"],"names":[],"mappings":";;AAAO,SAAS,oBAAoB,OAAuB;AACzD,MAAI,QAAQ;AACZ,SAAO,QAAQ,MAAM,UAAU,MAAM,KAAK,MAAM,IAAK;AACrD,SAAO,MAAM,MAAM,KAAK;AAC1B;AAEO,SAAS,qBAAqB,OAAuB;AAC1D,MAAI,MAAM,MAAM;AAChB,SAAO,MAAM,KAAK,MAAM,MAAM,CAAC,MAAM,IAAK;AAC1C,SAAO,MAAM,MAAM,GAAG,GAAG;AAC3B;;;"}
@@ -0,0 +1,3 @@
1
+ export declare function stripLeadingSlashes(value: string): string;
2
+ export declare function stripTrailingSlashes(value: string): string;
3
+ //# sourceMappingURL=string.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../src/lib/string.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI1D"}
@@ -0,0 +1,15 @@
1
+ function stripLeadingSlashes(value) {
2
+ let start = 0;
3
+ while (start < value.length && value[start] === "/") start++;
4
+ return value.slice(start);
5
+ }
6
+ function stripTrailingSlashes(value) {
7
+ let end = value.length;
8
+ while (end > 0 && value[end - 1] === "/") end--;
9
+ return value.slice(0, end);
10
+ }
11
+ export {
12
+ stripLeadingSlashes,
13
+ stripTrailingSlashes
14
+ };
15
+ //# sourceMappingURL=string.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string.js","sources":["../../src/lib/string.ts"],"sourcesContent":["export function stripLeadingSlashes(value: string): string {\n let start = 0;\n while (start < value.length && value[start] === \"/\") start++;\n return value.slice(start);\n}\n\nexport function stripTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end--;\n return value.slice(0, end);\n}\n"],"names":[],"mappings":"AAAO,SAAS,oBAAoB,OAAuB;AACzD,MAAI,QAAQ;AACZ,SAAO,QAAQ,MAAM,UAAU,MAAM,KAAK,MAAM,IAAK;AACrD,SAAO,MAAM,MAAM,KAAK;AAC1B;AAEO,SAAS,qBAAqB,OAAuB;AAC1D,MAAI,MAAM,MAAM;AAChB,SAAO,MAAM,KAAK,MAAM,MAAM,CAAC,MAAM,IAAK;AAC1C,SAAO,MAAM,MAAM,GAAG,GAAG;AAC3B;"}
@@ -7,7 +7,9 @@ const Icon = require("../data/Icon.cjs");
7
7
  const Modal = require("../overlay/Modal.cjs");
8
8
  const CommandForm = require("./CommandForm.cjs");
9
9
  const CommandOutput = require("./CommandOutput.cjs");
10
+ const commandFormUtils = require("./command-form-utils.cjs");
10
11
  const InlineError = require("./InlineError.cjs");
12
+ const rowNavigation = require("./rowNavigation.cjs");
11
13
  const UiPlay = require("../icons/components/UiPlay.cjs");
12
14
  function OperationActionDialog({
13
15
  operation,
@@ -66,8 +68,8 @@ function OperationActionDialog({
66
68
  function hrefForOperationAction(path, params) {
67
69
  const nextParams = { ...params };
68
70
  const args = parseArgsParam(params.args);
69
- let route = apiPathToRoutePath(path);
70
- for (const [index, name] of pathParamNames(path).entries()) {
71
+ let route = rowNavigation.apiPathToRoutePath(path);
72
+ for (const [index, name] of commandFormUtils.pathParamNames(path).entries()) {
71
73
  const value = nextParams[name] || args[index];
72
74
  if (!value) return void 0;
73
75
  route = route.replace(`:${name}`, encodeURIComponent(value));
@@ -83,14 +85,6 @@ function hrefForOperationAction(path, params) {
83
85
  const query = search.toString();
84
86
  return query ? `${route}?${query}` : route;
85
87
  }
86
- function apiPathToRoutePath(path) {
87
- const cliPath = path.trim().replace(/^\/api\/v1\/?/, "").replace(/^\/+/, "").replace(/\/+$/, "");
88
- if (!cliPath) return "/";
89
- return `/${cliPath.replace(/\{([^}]+)\}/g, ":$1")}`;
90
- }
91
- function pathParamNames(path) {
92
- return [...path.matchAll(/\{([^}]+)\}/g)].map((match) => match[1]).filter((name) => Boolean(name));
93
- }
94
88
  function parseArgsParam(value) {
95
89
  if (!value) return [];
96
90
  const trimmed = value.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"OperationActionDialog.cjs","sources":["../../src/rpc/OperationActionDialog.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { Icon } from \"../data/Icon\";\nimport { UiPlay } from \"../icons\";\nimport { Modal } from \"../overlay/Modal\";\nimport { CommandForm } from \"./CommandForm\";\nimport { CommandOutput } from \"./CommandOutput\";\nimport { InlineError } from \"./InlineError\";\nimport type { ExecutionResponse, ResolvedOperation } from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nexport type OperationActionDialogProps = {\n operation: ResolvedOperation;\n client: OperationsApiClient;\n initialValues: Record<string, string>;\n label: string;\n defaultAccept?: string;\n onNavigateAction?: (href: string) => void;\n};\n\nexport function OperationActionDialog({\n operation,\n client,\n initialValues,\n label,\n defaultAccept = \"application/clicky+json\",\n onNavigateAction,\n}: OperationActionDialogProps) {\n const [open, setOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n const [response, setResponse] = useState<ExecutionResponse | null>(null);\n const [error, setError] = useState<unknown>(null);\n\n async function handleExecute(params: Record<string, string>, headers: Record<string, string>) {\n if (onNavigateAction) {\n const href = hrefForOperationAction(operation.path, params);\n if (!href) return;\n const separator = href.includes(\"?\") ? \"&\" : \"?\";\n onNavigateAction(`${href}${separator}autoRun=1`);\n return;\n }\n\n setIsExecuting(true);\n setError(null);\n setResponse(null);\n try {\n const result = await client.executeCommand(operation.path, operation.method, params, headers);\n setResponse(result);\n } catch (err) {\n setError(err);\n } finally {\n setIsExecuting(false);\n }\n }\n\n return (\n <>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setOpen(true)}>\n <Icon icon={UiPlay} />\n {label}\n </Button>\n <Modal open={open} onClose={() => setOpen(false)} title={label} size=\"lg\">\n <div className=\"space-y-4\">\n <CommandForm\n parameters={operation.operation.parameters ?? []}\n onExecute={handleExecute}\n isPending={isExecuting}\n method={operation.method}\n path={operation.path}\n accept={defaultAccept}\n initialValues={initialValues}\n />\n\n {error ? (\n <InlineError title={`Failed to execute ${operation.path}`} error={error} />\n ) : response ? (\n <CommandOutput response={response} />\n ) : null}\n </div>\n </Modal>\n </>\n );\n}\n\nfunction hrefForOperationAction(path: string, params: Record<string, string>): string | undefined {\n const nextParams = { ...params };\n const args = parseArgsParam(params.args);\n let route = apiPathToRoutePath(path);\n\n for (const [index, name] of pathParamNames(path).entries()) {\n const value = nextParams[name] || args[index];\n if (!value) return undefined;\n route = route.replace(`:${name}`, encodeURIComponent(value));\n delete nextParams[name];\n if (!nextParams[name] && value === args[index]) {\n delete nextParams.args;\n }\n }\n\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(nextParams)) {\n if (value && key !== \"autoRun\" && key !== \"__autoRun\") search.set(key, value);\n }\n const query = search.toString();\n return query ? `${route}?${query}` : route;\n}\n\nfunction apiPathToRoutePath(path: string): string {\n const cliPath = path\n .trim()\n .replace(/^\\/api\\/v1\\/?/, \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n if (!cliPath) return \"/\";\n return `/${cliPath.replace(/\\{([^}]+)\\}/g, \":$1\")}`;\n}\n\nfunction pathParamNames(path: string): string[] {\n return [...path.matchAll(/\\{([^}]+)\\}/g)]\n .map((match) => match[1])\n .filter((name): name is string => Boolean(name));\n}\n\nfunction parseArgsParam(value: string | undefined): string[] {\n if (!value) return [];\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"[]\" || trimmed.toLowerCase() === \"null\") return [];\n try {\n const parsed = JSON.parse(trimmed);\n if (Array.isArray(parsed)) return parsed.map(String).filter(Boolean);\n } catch {\n // Fall back to comma-delimited args below.\n }\n return trimmed\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean);\n}\n"],"names":["useState","jsxs","Fragment","Button","jsx","Icon","UiPlay","Modal","CommandForm","InlineError","CommandOutput"],"mappings":"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"}
1
+ {"version":3,"file":"OperationActionDialog.cjs","sources":["../../src/rpc/OperationActionDialog.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { Icon } from \"../data/Icon\";\nimport { UiPlay } from \"../icons\";\nimport { Modal } from \"../overlay/Modal\";\nimport { CommandForm } from \"./CommandForm\";\nimport { CommandOutput } from \"./CommandOutput\";\nimport { pathParamNames } from \"./command-form-utils\";\nimport { InlineError } from \"./InlineError\";\nimport { apiPathToRoutePath } from \"./rowNavigation\";\nimport type { ExecutionResponse, ResolvedOperation } from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nexport type OperationActionDialogProps = {\n operation: ResolvedOperation;\n client: OperationsApiClient;\n initialValues: Record<string, string>;\n label: string;\n defaultAccept?: string;\n onNavigateAction?: (href: string) => void;\n};\n\nexport function OperationActionDialog({\n operation,\n client,\n initialValues,\n label,\n defaultAccept = \"application/clicky+json\",\n onNavigateAction,\n}: OperationActionDialogProps) {\n const [open, setOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n const [response, setResponse] = useState<ExecutionResponse | null>(null);\n const [error, setError] = useState<unknown>(null);\n\n async function handleExecute(params: Record<string, string>, headers: Record<string, string>) {\n if (onNavigateAction) {\n const href = hrefForOperationAction(operation.path, params);\n if (!href) return;\n const separator = href.includes(\"?\") ? \"&\" : \"?\";\n onNavigateAction(`${href}${separator}autoRun=1`);\n return;\n }\n\n setIsExecuting(true);\n setError(null);\n setResponse(null);\n try {\n const result = await client.executeCommand(operation.path, operation.method, params, headers);\n setResponse(result);\n } catch (err) {\n setError(err);\n } finally {\n setIsExecuting(false);\n }\n }\n\n return (\n <>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setOpen(true)}>\n <Icon icon={UiPlay} />\n {label}\n </Button>\n <Modal open={open} onClose={() => setOpen(false)} title={label} size=\"lg\">\n <div className=\"space-y-4\">\n <CommandForm\n parameters={operation.operation.parameters ?? []}\n onExecute={handleExecute}\n isPending={isExecuting}\n method={operation.method}\n path={operation.path}\n accept={defaultAccept}\n initialValues={initialValues}\n />\n\n {error ? (\n <InlineError title={`Failed to execute ${operation.path}`} error={error} />\n ) : response ? (\n <CommandOutput response={response} />\n ) : null}\n </div>\n </Modal>\n </>\n );\n}\n\nfunction hrefForOperationAction(path: string, params: Record<string, string>): string | undefined {\n const nextParams = { ...params };\n const args = parseArgsParam(params.args);\n let route = apiPathToRoutePath(path);\n\n for (const [index, name] of pathParamNames(path).entries()) {\n const value = nextParams[name] || args[index];\n if (!value) return undefined;\n route = route.replace(`:${name}`, encodeURIComponent(value));\n delete nextParams[name];\n if (!nextParams[name] && value === args[index]) {\n delete nextParams.args;\n }\n }\n\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(nextParams)) {\n if (value && key !== \"autoRun\" && key !== \"__autoRun\") search.set(key, value);\n }\n const query = search.toString();\n return query ? `${route}?${query}` : route;\n}\n\nfunction parseArgsParam(value: string | undefined): string[] {\n if (!value) return [];\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"[]\" || trimmed.toLowerCase() === \"null\") return [];\n try {\n const parsed = JSON.parse(trimmed);\n if (Array.isArray(parsed)) return parsed.map(String).filter(Boolean);\n } catch {\n // Fall back to comma-delimited args below.\n }\n return trimmed\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean);\n}\n"],"names":["useState","jsxs","Fragment","Button","jsx","Icon","UiPlay","Modal","CommandForm","InlineError","CommandOutput","apiPathToRoutePath","pathParamNames"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"OperationActionDialog.d.ts","sourceRoot":"","sources":["../../src/rpc/OperationActionDialog.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,MAAM,EACN,aAAa,EACb,KAAK,EACL,aAAyC,EACzC,gBAAgB,GACjB,EAAE,0BAA0B,2CAuD5B"}
1
+ {"version":3,"file":"OperationActionDialog.d.ts","sourceRoot":"","sources":["../../src/rpc/OperationActionDialog.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,MAAM,EACN,aAAa,EACb,KAAK,EACL,aAAyC,EACzC,gBAAgB,GACjB,EAAE,0BAA0B,2CAuD5B"}
@@ -5,7 +5,9 @@ import { Icon } from "../data/Icon.js";
5
5
  import { Modal } from "../overlay/Modal.js";
6
6
  import { CommandForm } from "./CommandForm.js";
7
7
  import { CommandOutput } from "./CommandOutput.js";
8
+ import { pathParamNames } from "./command-form-utils.js";
8
9
  import { InlineError } from "./InlineError.js";
10
+ import { apiPathToRoutePath } from "./rowNavigation.js";
9
11
  import { UiPlay } from "../icons/components/UiPlay.js";
10
12
  function OperationActionDialog({
11
13
  operation,
@@ -81,14 +83,6 @@ function hrefForOperationAction(path, params) {
81
83
  const query = search.toString();
82
84
  return query ? `${route}?${query}` : route;
83
85
  }
84
- function apiPathToRoutePath(path) {
85
- const cliPath = path.trim().replace(/^\/api\/v1\/?/, "").replace(/^\/+/, "").replace(/\/+$/, "");
86
- if (!cliPath) return "/";
87
- return `/${cliPath.replace(/\{([^}]+)\}/g, ":$1")}`;
88
- }
89
- function pathParamNames(path) {
90
- return [...path.matchAll(/\{([^}]+)\}/g)].map((match) => match[1]).filter((name) => Boolean(name));
91
- }
92
86
  function parseArgsParam(value) {
93
87
  if (!value) return [];
94
88
  const trimmed = value.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"OperationActionDialog.js","sources":["../../src/rpc/OperationActionDialog.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { Icon } from \"../data/Icon\";\nimport { UiPlay } from \"../icons\";\nimport { Modal } from \"../overlay/Modal\";\nimport { CommandForm } from \"./CommandForm\";\nimport { CommandOutput } from \"./CommandOutput\";\nimport { InlineError } from \"./InlineError\";\nimport type { ExecutionResponse, ResolvedOperation } from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nexport type OperationActionDialogProps = {\n operation: ResolvedOperation;\n client: OperationsApiClient;\n initialValues: Record<string, string>;\n label: string;\n defaultAccept?: string;\n onNavigateAction?: (href: string) => void;\n};\n\nexport function OperationActionDialog({\n operation,\n client,\n initialValues,\n label,\n defaultAccept = \"application/clicky+json\",\n onNavigateAction,\n}: OperationActionDialogProps) {\n const [open, setOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n const [response, setResponse] = useState<ExecutionResponse | null>(null);\n const [error, setError] = useState<unknown>(null);\n\n async function handleExecute(params: Record<string, string>, headers: Record<string, string>) {\n if (onNavigateAction) {\n const href = hrefForOperationAction(operation.path, params);\n if (!href) return;\n const separator = href.includes(\"?\") ? \"&\" : \"?\";\n onNavigateAction(`${href}${separator}autoRun=1`);\n return;\n }\n\n setIsExecuting(true);\n setError(null);\n setResponse(null);\n try {\n const result = await client.executeCommand(operation.path, operation.method, params, headers);\n setResponse(result);\n } catch (err) {\n setError(err);\n } finally {\n setIsExecuting(false);\n }\n }\n\n return (\n <>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setOpen(true)}>\n <Icon icon={UiPlay} />\n {label}\n </Button>\n <Modal open={open} onClose={() => setOpen(false)} title={label} size=\"lg\">\n <div className=\"space-y-4\">\n <CommandForm\n parameters={operation.operation.parameters ?? []}\n onExecute={handleExecute}\n isPending={isExecuting}\n method={operation.method}\n path={operation.path}\n accept={defaultAccept}\n initialValues={initialValues}\n />\n\n {error ? (\n <InlineError title={`Failed to execute ${operation.path}`} error={error} />\n ) : response ? (\n <CommandOutput response={response} />\n ) : null}\n </div>\n </Modal>\n </>\n );\n}\n\nfunction hrefForOperationAction(path: string, params: Record<string, string>): string | undefined {\n const nextParams = { ...params };\n const args = parseArgsParam(params.args);\n let route = apiPathToRoutePath(path);\n\n for (const [index, name] of pathParamNames(path).entries()) {\n const value = nextParams[name] || args[index];\n if (!value) return undefined;\n route = route.replace(`:${name}`, encodeURIComponent(value));\n delete nextParams[name];\n if (!nextParams[name] && value === args[index]) {\n delete nextParams.args;\n }\n }\n\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(nextParams)) {\n if (value && key !== \"autoRun\" && key !== \"__autoRun\") search.set(key, value);\n }\n const query = search.toString();\n return query ? `${route}?${query}` : route;\n}\n\nfunction apiPathToRoutePath(path: string): string {\n const cliPath = path\n .trim()\n .replace(/^\\/api\\/v1\\/?/, \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n if (!cliPath) return \"/\";\n return `/${cliPath.replace(/\\{([^}]+)\\}/g, \":$1\")}`;\n}\n\nfunction pathParamNames(path: string): string[] {\n return [...path.matchAll(/\\{([^}]+)\\}/g)]\n .map((match) => match[1])\n .filter((name): name is string => Boolean(name));\n}\n\nfunction parseArgsParam(value: string | undefined): string[] {\n if (!value) return [];\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"[]\" || trimmed.toLowerCase() === \"null\") return [];\n try {\n const parsed = JSON.parse(trimmed);\n if (Array.isArray(parsed)) return parsed.map(String).filter(Boolean);\n } catch {\n // Fall back to comma-delimited args below.\n }\n return trimmed\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean);\n}\n"],"names":[],"mappings":";;;;;;;;;AAoBO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AACF,GAA+B;AAC7B,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmC,IAAI;AACvE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAkB,IAAI;AAEhD,iBAAe,cAAc,QAAgC,SAAiC;AAC5F,QAAI,kBAAkB;AACpB,YAAM,OAAO,uBAAuB,UAAU,MAAM,MAAM;AAC1D,UAAI,CAAC,KAAM;AACX,YAAM,YAAY,KAAK,SAAS,GAAG,IAAI,MAAM;AAC7C,uBAAiB,GAAG,IAAI,GAAG,SAAS,WAAW;AAC/C;AAAA,IACF;AAEA,mBAAe,IAAI;AACnB,aAAS,IAAI;AACb,gBAAY,IAAI;AAChB,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,eAAe,UAAU,MAAM,UAAU,QAAQ,QAAQ,OAAO;AAC5F,kBAAY,MAAM;AAAA,IACpB,SAAS,KAAK;AACZ,eAAS,GAAG;AAAA,IACd,UAAA;AACE,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAEA,SACE,qBAAA,UAAA,EACE,UAAA;AAAA,IAAA,qBAAC,QAAA,EAAO,MAAK,UAAS,SAAQ,WAAU,MAAK,MAAK,SAAS,MAAM,QAAQ,IAAI,GAC3E,UAAA;AAAA,MAAA,oBAAC,MAAA,EAAK,MAAM,OAAA,CAAQ;AAAA,MACnB;AAAA,IAAA,GACH;AAAA,IACA,oBAAC,OAAA,EAAM,MAAY,SAAS,MAAM,QAAQ,KAAK,GAAG,OAAO,OAAO,MAAK,MACnE,UAAA,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,YAAY,UAAU,UAAU,cAAc,CAAA;AAAA,UAC9C,WAAW;AAAA,UACX,WAAW;AAAA,UACX,QAAQ,UAAU;AAAA,UAClB,MAAM,UAAU;AAAA,UAChB,QAAQ;AAAA,UACR;AAAA,QAAA;AAAA,MAAA;AAAA,MAGD,QACC,oBAAC,aAAA,EAAY,OAAO,qBAAqB,UAAU,IAAI,IAAI,MAAA,CAAc,IACvE,WACF,oBAAC,eAAA,EAAc,UAAoB,IACjC;AAAA,IAAA,EAAA,CACN,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,uBAAuB,MAAc,QAAoD;AAChG,QAAM,aAAa,EAAE,GAAG,OAAA;AACxB,QAAM,OAAO,eAAe,OAAO,IAAI;AACvC,MAAI,QAAQ,mBAAmB,IAAI;AAEnC,aAAW,CAAC,OAAO,IAAI,KAAK,eAAe,IAAI,EAAE,WAAW;AAC1D,UAAM,QAAQ,WAAW,IAAI,KAAK,KAAK,KAAK;AAC5C,QAAI,CAAC,MAAO,QAAO;AACnB,YAAQ,MAAM,QAAQ,IAAI,IAAI,IAAI,mBAAmB,KAAK,CAAC;AAC3D,WAAO,WAAW,IAAI;AACtB,QAAI,CAAC,WAAW,IAAI,KAAK,UAAU,KAAK,KAAK,GAAG;AAC9C,aAAO,WAAW;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,SAAS,IAAI,gBAAA;AACnB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACrD,QAAI,SAAS,QAAQ,aAAa,QAAQ,YAAa,QAAO,IAAI,KAAK,KAAK;AAAA,EAC9E;AACA,QAAM,QAAQ,OAAO,SAAA;AACrB,SAAO,QAAQ,GAAG,KAAK,IAAI,KAAK,KAAK;AACvC;AAEA,SAAS,mBAAmB,MAAsB;AAChD,QAAM,UAAU,KACb,KAAA,EACA,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,QAAQ,EAAE,EAClB,QAAQ,QAAQ,EAAE;AACrB,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,IAAI,QAAQ,QAAQ,gBAAgB,KAAK,CAAC;AACnD;AAEA,SAAS,eAAe,MAAwB;AAC9C,SAAO,CAAC,GAAG,KAAK,SAAS,cAAc,CAAC,EACrC,IAAI,CAAC,UAAU,MAAM,CAAC,CAAC,EACvB,OAAO,CAAC,SAAyB,QAAQ,IAAI,CAAC;AACnD;AAEA,SAAS,eAAe,OAAqC;AAC3D,MAAI,CAAC,MAAO,QAAO,CAAA;AACnB,QAAM,UAAU,MAAM,KAAA;AACtB,MAAI,CAAC,WAAW,YAAY,QAAQ,QAAQ,YAAA,MAAkB,OAAQ,QAAO,CAAA;AAC7E,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,QAAI,MAAM,QAAQ,MAAM,EAAG,QAAO,OAAO,IAAI,MAAM,EAAE,OAAO,OAAO;AAAA,EACrE,QAAQ;AAAA,EAER;AACA,SAAO,QACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAA,CAAM,EACzB,OAAO,OAAO;AACnB;"}
1
+ {"version":3,"file":"OperationActionDialog.js","sources":["../../src/rpc/OperationActionDialog.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { Icon } from \"../data/Icon\";\nimport { UiPlay } from \"../icons\";\nimport { Modal } from \"../overlay/Modal\";\nimport { CommandForm } from \"./CommandForm\";\nimport { CommandOutput } from \"./CommandOutput\";\nimport { pathParamNames } from \"./command-form-utils\";\nimport { InlineError } from \"./InlineError\";\nimport { apiPathToRoutePath } from \"./rowNavigation\";\nimport type { ExecutionResponse, ResolvedOperation } from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nexport type OperationActionDialogProps = {\n operation: ResolvedOperation;\n client: OperationsApiClient;\n initialValues: Record<string, string>;\n label: string;\n defaultAccept?: string;\n onNavigateAction?: (href: string) => void;\n};\n\nexport function OperationActionDialog({\n operation,\n client,\n initialValues,\n label,\n defaultAccept = \"application/clicky+json\",\n onNavigateAction,\n}: OperationActionDialogProps) {\n const [open, setOpen] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n const [response, setResponse] = useState<ExecutionResponse | null>(null);\n const [error, setError] = useState<unknown>(null);\n\n async function handleExecute(params: Record<string, string>, headers: Record<string, string>) {\n if (onNavigateAction) {\n const href = hrefForOperationAction(operation.path, params);\n if (!href) return;\n const separator = href.includes(\"?\") ? \"&\" : \"?\";\n onNavigateAction(`${href}${separator}autoRun=1`);\n return;\n }\n\n setIsExecuting(true);\n setError(null);\n setResponse(null);\n try {\n const result = await client.executeCommand(operation.path, operation.method, params, headers);\n setResponse(result);\n } catch (err) {\n setError(err);\n } finally {\n setIsExecuting(false);\n }\n }\n\n return (\n <>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setOpen(true)}>\n <Icon icon={UiPlay} />\n {label}\n </Button>\n <Modal open={open} onClose={() => setOpen(false)} title={label} size=\"lg\">\n <div className=\"space-y-4\">\n <CommandForm\n parameters={operation.operation.parameters ?? []}\n onExecute={handleExecute}\n isPending={isExecuting}\n method={operation.method}\n path={operation.path}\n accept={defaultAccept}\n initialValues={initialValues}\n />\n\n {error ? (\n <InlineError title={`Failed to execute ${operation.path}`} error={error} />\n ) : response ? (\n <CommandOutput response={response} />\n ) : null}\n </div>\n </Modal>\n </>\n );\n}\n\nfunction hrefForOperationAction(path: string, params: Record<string, string>): string | undefined {\n const nextParams = { ...params };\n const args = parseArgsParam(params.args);\n let route = apiPathToRoutePath(path);\n\n for (const [index, name] of pathParamNames(path).entries()) {\n const value = nextParams[name] || args[index];\n if (!value) return undefined;\n route = route.replace(`:${name}`, encodeURIComponent(value));\n delete nextParams[name];\n if (!nextParams[name] && value === args[index]) {\n delete nextParams.args;\n }\n }\n\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(nextParams)) {\n if (value && key !== \"autoRun\" && key !== \"__autoRun\") search.set(key, value);\n }\n const query = search.toString();\n return query ? `${route}?${query}` : route;\n}\n\nfunction parseArgsParam(value: string | undefined): string[] {\n if (!value) return [];\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"[]\" || trimmed.toLowerCase() === \"null\") return [];\n try {\n const parsed = JSON.parse(trimmed);\n if (Array.isArray(parsed)) return parsed.map(String).filter(Boolean);\n } catch {\n // Fall back to comma-delimited args below.\n }\n return trimmed\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean);\n}\n"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const react = require("react");
5
5
  const reactQuery = require("@tanstack/react-query");
6
6
  const MethodBadge = require("../data/MethodBadge.cjs");
7
+ const string = require("../lib/string.cjs");
7
8
  const CommandForm = require("./CommandForm.cjs");
8
9
  const commandFormUtils = require("./command-form-utils.cjs");
9
10
  const formMetadata = require("./formMetadata.cjs");
@@ -301,7 +302,7 @@ function OperationCommandPage({
301
302
  function findRelatedOperations(current, operations, pathValues) {
302
303
  if (current.method.toUpperCase() !== "GET") return [];
303
304
  if (!pathTemplateSatisfied(current.path, pathValues)) return [];
304
- const basePath = current.path.replace(/\/+$/, "");
305
+ const basePath = string.stripTrailingSlashes(current.path);
305
306
  return operations.filter((candidate) => {
306
307
  if (candidate === current) return false;
307
308
  if (!candidate.path.startsWith(`${basePath}/`)) return false;
@@ -322,7 +323,7 @@ function findRelatedOperations(current, operations, pathValues) {
322
323
  }
323
324
  function findDetailOperation(current, operations) {
324
325
  const method = current.method.toUpperCase();
325
- const detailPath = `${current.path.replace(/\/+$/, "")}/{id}`;
326
+ const detailPath = `${string.stripTrailingSlashes(current.path)}/{id}`;
326
327
  return operations.find(
327
328
  (candidate) => {
328
329
  var _a;
@@ -1 +1 @@
1
- {"version":3,"file":"OperationCommandPage.cjs","sources":["../../src/rpc/OperationCommandPage.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { ClickyCommandRuntime } from \"../data/Clicky\";\nimport { MethodBadge } from \"../data/MethodBadge\";\nimport { CommandForm } from \"./CommandForm\";\nimport { pathParamNames, submitValue } from \"./command-form-utils\";\nimport type { RenderLink } from \"./EndpointList\";\nimport {\n buildInitialParameterValues,\n dataTablePaginationFromForm,\n packParameterValues,\n parametersToFormConfig,\n pruneParameterValues,\n titleCase,\n useDebouncedRecord,\n type ParameterValues,\n} from \"./formMetadata\";\nimport { InlineError } from \"./InlineError\";\nimport { OperationActionDialog } from \"./OperationActionDialog\";\nimport { OperationResultView } from \"./OperationResultView\";\nimport { hrefForOperation } from \"./rowNavigation\";\nimport type {\n ExecutionResponse,\n OpenAPIParameter,\n ResolvedOperation,\n} from \"./types\";\nimport { useOperationById, type OperationsApiClient } from \"./useOperations\";\n\n// All operation results are fetched as clicky documents; the in-result View\n// menu re-fetches other formats on demand via the response's requestUrl.\nconst RESULT_ACCEPT = \"application/clicky+json\";\n\nexport type OperationCommandPageProps = {\n client: OperationsApiClient;\n operationId?: string;\n operation?: ResolvedOperation;\n operations?: ResolvedOperation[];\n initialValues?: ParameterValues;\n autoRun?: boolean;\n backHref?: string;\n backLabel?: string;\n renderLink?: RenderLink;\n commandRuntime?: ClickyCommandRuntime;\n onNavigate?: (href: string) => void;\n onResult?: (\n response: ExecutionResponse,\n operation: ResolvedOperation,\n values: ParameterValues,\n ) => void;\n hideLockedPathFilters?: boolean;\n className?: string;\n};\n\nconst EMPTY_PARAMETER_VALUES: ParameterValues = {};\n\nexport function OperationCommandPage({\n client,\n operationId,\n operation: providedOperation,\n operations = providedOperation ? [providedOperation] : [],\n initialValues = EMPTY_PARAMETER_VALUES,\n autoRun,\n backHref,\n backLabel = \"Back\",\n renderLink,\n onNavigate,\n onResult,\n commandRuntime,\n hideLockedPathFilters = Boolean(providedOperation),\n className,\n}: OperationCommandPageProps) {\n const lookup = useOperationById(\n client,\n providedOperation ? undefined : operationId,\n );\n const operation = providedOperation ?? lookup.operation;\n const isLoading = providedOperation ? false : lookup.isLoading;\n const [isExecuting, setIsExecuting] = useState(false);\n const [result, setResult] = useState<ExecutionResponse | null>(null);\n const [error, setError] = useState<unknown>(null);\n const [hasAutoRun, setHasAutoRun] = useState(false);\n const parameters = operation?.operation.parameters ?? [];\n const isGet = (operation?.method ?? \"\").toUpperCase() === \"GET\";\n const effectiveAutoRun = operation ? (autoRun ?? isGet) : false;\n const parameterSignature = JSON.stringify(\n parameters.map((param) => ({\n name: param.name,\n in: param.in,\n required: param.required ?? false,\n default: param.schema?.default ?? null,\n })),\n );\n const operationKey = `${operation?.method ?? \"\"}:${operation?.path ?? \"\"}:${operation?.operation.operationId ?? \"\"}`;\n const effectiveInitialValues = useMemo(\n () =>\n operation\n ? buildInitialParameterValues(\n parameters,\n operation.method,\n {},\n {\n ...readQueryParameterValuesFromUrl(parameters),\n ...stripRunnerParams(initialValues),\n },\n )\n : stripRunnerParams(initialValues),\n [initialValues, operation?.method, parameterSignature],\n );\n const pathParameters = parameters.filter((param) => param.in === \"path\");\n const lockedPathValues = useMemo<ParameterValues>(() => {\n const values: ParameterValues = {};\n for (const param of pathParameters) {\n const value = effectiveInitialValues[param.name];\n if (typeof value === \"string\" && value.trim() !== \"\") {\n values[param.name] = value;\n }\n }\n return values;\n }, [effectiveInitialValues, pathParameters]);\n const detailOperation = useMemo(\n () => (operation ? findDetailOperation(operation, operations) : undefined),\n [operation, operations],\n );\n const relatedOperations = useMemo(\n () =>\n operation\n ? findRelatedOperations(operation, operations, lockedPathValues)\n : [],\n [lockedPathValues, operation, operations],\n );\n\n // GET-mode parameter state: filter values + pagination cursor are driven\n // by the page so they can flow natively into the result table's in-table\n // FilterBar and pagination footer (via OperationResultView's filterConfig).\n const [values, setValues] = useState<ParameterValues>(effectiveInitialValues);\n useEffect(() => {\n setValues(effectiveInitialValues);\n }, [effectiveInitialValues]);\n const debouncedValues = useDebouncedRecord(values, 250);\n\n useEffect(() => {\n if (!isGet || !operation) return;\n writeQueryParameterValuesToUrl(debouncedValues, parameters);\n }, [isGet, operationKey, debouncedValues, parameterSignature]);\n\n const lookupQuery = useQuery({\n queryKey: [\n \"operation-query-lookup\",\n operation?.method,\n operation?.path,\n debouncedValues,\n ],\n queryFn: async () => {\n if (!operation) return { filters: {} };\n return (\n (await client.lookupFilters?.(\n operation.path,\n operation.method,\n packParameterValues(debouncedValues, parameters),\n { Accept: \"application/json+clicky\" },\n )) ?? { filters: {} }\n );\n },\n enabled:\n isGet &&\n !!operation &&\n !!client.lookupFilters &&\n parameters.some((param) => param.in === \"query\"),\n staleTime: 30_000,\n retry: 0,\n });\n\n const formConfig = useMemo(() => {\n if (!isGet) return { filters: [] };\n return parametersToFormConfig(parameters, values, setValues, {\n lookup: lookupQuery.data,\n lockedValues: lockedPathValues,\n hideLocked: hideLockedPathFilters,\n });\n }, [\n isGet,\n parameters,\n values,\n lookupQuery.data,\n lockedPathValues,\n hideLockedPathFilters,\n ]);\n\n const dataTablePagination = useMemo(\n () => dataTablePaginationFromForm(formConfig.pagination, result),\n [formConfig.pagination, result],\n );\n\n // Ref tracking the last submitted parameter signature so the\n // auto-submit-on-debounced-change effect coordinates against the same\n // \"have I already fired this set of values\" check.\n const lastSubmittedSignature = useRef(\"\");\n\n async function executeOperation(values: ParameterValues) {\n if (!operation) return;\n\n setIsExecuting(true);\n setError(null);\n\n try {\n const response = await client.executeCommand(\n operation.path,\n operation.method,\n packParameterValues(values, operation.operation.parameters ?? []),\n { Accept: RESULT_ACCEPT },\n );\n setResult(response);\n onResult?.(response, operation, values);\n } catch (err) {\n setResult(null);\n setError(err);\n } finally {\n setIsExecuting(false);\n }\n }\n\n useEffect(() => {\n setHasAutoRun(false);\n setResult(null);\n setError(null);\n lastSubmittedSignature.current = \"\";\n }, [effectiveAutoRun, operationKey]);\n\n useEffect(() => {\n if (!effectiveAutoRun || !operation || hasAutoRun) return;\n // Auto-run a GET as long as every required parameter has a value. Optional\n // params (limit/offset, filter chips, etc.) get their defaults; the\n // sidebar's \"click → instant table\" flow depends on this not bailing just\n // because the operation declares any parameters at all.\n const missingRequired = parameters.filter((param) => {\n if (!param.required) return false;\n return (effectiveInitialValues[param.name] ?? \"\").trim() === \"\";\n });\n if (missingRequired.length > 0) return;\n\n setHasAutoRun(true);\n lastSubmittedSignature.current = JSON.stringify(\n pruneParameterValues(effectiveInitialValues),\n );\n void executeOperation(effectiveInitialValues);\n }, [\n effectiveAutoRun,\n effectiveInitialValues,\n hasAutoRun,\n operationKey,\n parameterSignature,\n ]);\n\n // GET re-runs on debounced filter/pagination changes once the initial\n // auto-run has fired; non-GETs keep their explicit-submit behavior.\n useEffect(() => {\n if (!isGet || !operation || !hasAutoRun) return;\n const merged = { ...debouncedValues, ...lockedPathValues };\n const missingRequired = parameters.filter((param) => {\n if (!param.required) return false;\n return (merged[param.name] ?? \"\").trim() === \"\";\n });\n if (missingRequired.length > 0) return;\n const signature = JSON.stringify(pruneParameterValues(merged));\n if (lastSubmittedSignature.current === signature) return;\n lastSubmittedSignature.current = signature;\n void executeOperation(merged);\n }, [\n isGet,\n hasAutoRun,\n debouncedValues,\n lockedPathValues,\n parameterSignature,\n ]);\n\n const backLink =\n backHref == null ? null : renderLink ? (\n renderLink({\n to: backHref,\n className: \"text-sm text-primary underline-offset-4 hover:underline\",\n children: backLabel,\n })\n ) : (\n <a\n href={backHref}\n className=\"text-sm text-primary underline-offset-4 hover:underline\"\n >\n {backLabel}\n </a>\n );\n\n if (isLoading) {\n return (\n <div className=\"text-sm text-muted-foreground\">Loading operation...</div>\n );\n }\n\n if (!operation) {\n return (\n <div className=\"space-y-4\">\n <div className=\"text-sm text-muted-foreground\">\n Unknown operation: <code>{operationId}</code>\n </div>\n {backLink}\n </div>\n );\n }\n\n const { path, method, operation: op } = operation;\n\n return (\n <div className={className ?? \"min-w-0 flex-1 space-y-6 p-6\"}>\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0 flex-1\">\n {backLink}\n <div className=\"flex items-center gap-3\">\n <MethodBadge method={method} />\n <h1 className=\"truncate text-xl font-bold\">\n {op.summary || op.operationId || path}\n </h1>\n </div>\n <p className=\"mt-1 font-mono text-xs text-muted-foreground\">{path}</p>\n {op.operationId && op.summary && (\n <p className=\"mt-2 font-mono text-xs text-muted-foreground\">\n {op.operationId}\n </p>\n )}\n {op.description && op.description !== op.summary && (\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {op.description}\n </p>\n )}\n </div>\n <div className=\"flex shrink-0 flex-col items-end gap-3\">\n {relatedOperations.length > 0 && (\n <div className=\"flex flex-wrap justify-end gap-2\">\n {relatedOperations.map((related) =>\n related.href ? (\n renderLink ? (\n renderLink({\n key: `${related.operation.method}:${related.operation.path}`,\n to: related.href,\n className:\n \"inline-flex h-8 items-center justify-center gap-2 rounded-md border border-input bg-background px-3 text-xs font-medium hover:bg-accent hover:text-accent-foreground\",\n children: related.label,\n })\n ) : (\n <a\n key={`${related.operation.method}:${related.operation.path}`}\n href={related.href}\n className=\"inline-flex h-8 items-center justify-center gap-2 rounded-md border border-input bg-background px-3 text-xs font-medium hover:bg-accent hover:text-accent-foreground\"\n >\n {related.label}\n </a>\n )\n ) : (\n <OperationActionDialog\n key={`${related.operation.method}:${related.operation.path}`}\n operation={related.operation}\n client={client}\n initialValues={lockedPathValues}\n label={related.label}\n defaultAccept={RESULT_ACCEPT}\n {...(onNavigate ? { onNavigateAction: onNavigate } : {})}\n />\n ),\n )}\n </div>\n )}\n </div>\n </div>\n\n {method.toUpperCase() !== \"GET\" && (\n <section className=\"space-y-3\">\n <div className=\"rounded-lg border p-4\">\n <CommandForm\n parameters={parameters}\n onExecute={(params) => executeOperation(params)}\n isPending={isExecuting}\n method={method}\n path={path}\n accept={RESULT_ACCEPT}\n initialValues={effectiveInitialValues}\n />\n </div>\n </section>\n )}\n\n {error ? (\n <InlineError title={`Failed to load ${path}`} error={error} />\n ) : isExecuting || result ? (\n <OperationResultView\n response={result}\n loading={isExecuting}\n loadingMessage=\"Loading execution results…\"\n ariaLabel=\"Response body\"\n detailOperation={detailOperation}\n {...(commandRuntime ? { commandRuntime } : {})}\n {...(isGet && effectiveAutoRun\n ? {\n filterConfig: {\n filters: formConfig.filters,\n ...(formConfig.timeRange\n ? { timeRange: formConfig.timeRange }\n : {}),\n },\n }\n : {})}\n {...(isGet && effectiveAutoRun && dataTablePagination\n ? { pagination: dataTablePagination }\n : {})}\n />\n ) : null}\n </div>\n );\n}\n\ntype RelatedOperation = {\n operation: ResolvedOperation;\n label: string;\n href?: string;\n};\n\nfunction findRelatedOperations(\n current: ResolvedOperation,\n operations: ResolvedOperation[],\n pathValues: Record<string, string>,\n): RelatedOperation[] {\n if (current.method.toUpperCase() !== \"GET\") return [];\n if (!pathTemplateSatisfied(current.path, pathValues)) return [];\n\n const basePath = current.path.replace(/\\/+$/, \"\");\n return operations\n .filter((candidate) => {\n if (candidate === current) return false;\n if (!candidate.path.startsWith(`${basePath}/`)) return false;\n if (!pathTemplateSatisfied(candidate.path, pathValues)) return false;\n const method = candidate.method.toUpperCase();\n return (\n method === \"GET\" ||\n method === \"POST\" ||\n method === \"PUT\" ||\n method === \"DELETE\"\n );\n })\n .map((related) => {\n const method = related.method.toUpperCase();\n const href =\n method === \"GET\"\n ? hrefForOperation(related, [], pathValues)\n : undefined;\n return {\n operation: related,\n label: operationLabel(related),\n ...(href ? { href } : {}),\n };\n })\n .filter(\n (related) =>\n related.operation.method.toUpperCase() !== \"GET\" || related.href,\n );\n}\n\nfunction findDetailOperation(\n current: ResolvedOperation,\n operations: ResolvedOperation[],\n) {\n const method = current.method.toUpperCase();\n const detailPath = `${current.path.replace(/\\/+$/, \"\")}/{id}`;\n return operations.find(\n (candidate) =>\n candidate.method.toUpperCase() === method &&\n candidate.path === detailPath &&\n candidate.operation.parameters?.some(\n (param) => param.in === \"path\" && param.name === \"id\" && param.required,\n ),\n );\n}\n\nfunction pathTemplateSatisfied(path: string, values: Record<string, string>) {\n return pathParamNames(path).every((name) => Boolean(values[name]));\n}\n\nfunction operationLabel(operation: ResolvedOperation): string {\n const actionName =\n operation.operation[\"x-clicky\"]?.actionName ||\n operation.path.split(\"/\").filter(Boolean).at(-1) ||\n operation.operation.operationId ||\n operation.method;\n return titleCase(actionName.replace(/[_-]+/g, \" \"));\n}\n\nfunction stripRunnerParams(values: ParameterValues): ParameterValues {\n const next: ParameterValues = {};\n for (const [key, value] of Object.entries(values)) {\n if (key === \"autoRun\" || key.startsWith(\"__\")) continue;\n next[key] = value;\n }\n return next;\n}\n\nfunction readQueryParameterValuesFromUrl(\n parameters: OpenAPIParameter[],\n): ParameterValues {\n if (typeof window === \"undefined\") return {};\n const queryParamNames = new Set(\n parameters.filter((param) => param.in === \"query\").map((p) => p.name),\n );\n if (queryParamNames.size === 0) return {};\n\n const values: ParameterValues = {};\n const search = new URLSearchParams(window.location.search);\n for (const name of queryParamNames) {\n const value = search.get(name);\n if (value != null && value !== \"\") {\n values[name] = value;\n }\n }\n return values;\n}\n\nfunction writeQueryParameterValuesToUrl(\n values: ParameterValues,\n parameters: OpenAPIParameter[],\n) {\n if (typeof window === \"undefined\") return;\n const queryParameters = parameters.filter((param) => param.in === \"query\");\n if (queryParameters.length === 0) return;\n\n const search = new URLSearchParams(window.location.search);\n for (const param of queryParameters) {\n const value = submitValue(param, values[param.name]);\n if (value == null) {\n search.delete(param.name);\n } else {\n search.set(param.name, value);\n }\n }\n\n const query = search.toString();\n const next = `${window.location.pathname}${query ? `?${query}` : \"\"}${window.location.hash}`;\n const current = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n if (next !== current) {\n window.history.replaceState(window.history.state, \"\", next);\n }\n}\n"],"names":["useOperationById","useState","useMemo","buildInitialParameterValues","values","useEffect","useDebouncedRecord","useQuery","packParameterValues","parametersToFormConfig","dataTablePaginationFromForm","useRef","pruneParameterValues","jsx","jsxs","MethodBadge","OperationActionDialog","CommandForm","InlineError","OperationResultView","hrefForOperation","pathParamNames","titleCase","submitValue"],"mappings":";;;;;;;;;;;;;;AA8BA,MAAM,gBAAgB;AAuBtB,MAAM,yBAA0C,CAAA;AAEzC,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,aAAa,oBAAoB,CAAC,iBAAiB,IAAI,CAAA;AAAA,EACvD,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,wBAAwB,QAAQ,iBAAiB;AAAA,EACjD;AACF,GAA8B;AAC5B,QAAM,SAASA,cAAAA;AAAAA,IACb;AAAA,IACA,oBAAoB,SAAY;AAAA,EAAA;AAElC,QAAM,YAAY,qBAAqB,OAAO;AAC9C,QAAM,YAAY,oBAAoB,QAAQ,OAAO;AACrD,QAAM,CAAC,aAAa,cAAc,IAAIC,MAAAA,SAAS,KAAK;AACpD,QAAM,CAAC,QAAQ,SAAS,IAAIA,MAAAA,SAAmC,IAAI;AACnE,QAAM,CAAC,OAAO,QAAQ,IAAIA,MAAAA,SAAkB,IAAI;AAChD,QAAM,CAAC,YAAY,aAAa,IAAIA,MAAAA,SAAS,KAAK;AAClD,QAAM,cAAa,uCAAW,UAAU,eAAc,CAAA;AACtD,QAAM,UAAS,uCAAW,WAAU,IAAI,kBAAkB;AAC1D,QAAM,mBAAmB,YAAa,WAAW,QAAS;AAC1D,QAAM,qBAAqB,KAAK;AAAA,IAC9B,WAAW,IAAI,CAAC,UAAA;;AAAW;AAAA,QACzB,MAAM,MAAM;AAAA,QACZ,IAAI,MAAM;AAAA,QACV,UAAU,MAAM,YAAY;AAAA,QAC5B,WAAS,WAAM,WAAN,mBAAc,YAAW;AAAA,MAAA;AAAA,KAClC;AAAA,EAAA;AAEJ,QAAM,eAAe,IAAG,uCAAW,WAAU,EAAE,KAAI,uCAAW,SAAQ,EAAE,KAAI,uCAAW,UAAU,gBAAe,EAAE;AAClH,QAAM,yBAAyBC,MAAAA;AAAAA,IAC7B,MACE,YACIC,aAAAA;AAAAA,MACE;AAAA,MACA,UAAU;AAAA,MACV,CAAA;AAAA,MACA;AAAA,QACE,GAAG,gCAAgC,UAAU;AAAA,QAC7C,GAAG,kBAAkB,aAAa;AAAA,MAAA;AAAA,IACpC,IAEF,kBAAkB,aAAa;AAAA,IACrC,CAAC,eAAe,uCAAW,QAAQ,kBAAkB;AAAA,EAAA;AAEvD,QAAM,iBAAiB,WAAW,OAAO,CAAC,UAAU,MAAM,OAAO,MAAM;AACvE,QAAM,mBAAmBD,MAAAA,QAAyB,MAAM;AACtD,UAAME,UAA0B,CAAA;AAChC,eAAW,SAAS,gBAAgB;AAClC,YAAM,QAAQ,uBAAuB,MAAM,IAAI;AAC/C,UAAI,OAAO,UAAU,YAAY,MAAM,KAAA,MAAW,IAAI;AACpDA,gBAAO,MAAM,IAAI,IAAI;AAAA,MACvB;AAAA,IACF;AACA,WAAOA;AAAAA,EACT,GAAG,CAAC,wBAAwB,cAAc,CAAC;AAC3C,QAAM,kBAAkBF,MAAAA;AAAAA,IACtB,MAAO,YAAY,oBAAoB,WAAW,UAAU,IAAI;AAAA,IAChE,CAAC,WAAW,UAAU;AAAA,EAAA;AAExB,QAAM,oBAAoBA,MAAAA;AAAAA,IACxB,MACE,YACI,sBAAsB,WAAW,YAAY,gBAAgB,IAC7D,CAAA;AAAA,IACN,CAAC,kBAAkB,WAAW,UAAU;AAAA,EAAA;AAM1C,QAAM,CAAC,QAAQ,SAAS,IAAID,MAAAA,SAA0B,sBAAsB;AAC5EI,QAAAA,UAAU,MAAM;AACd,cAAU,sBAAsB;AAAA,EAClC,GAAG,CAAC,sBAAsB,CAAC;AAC3B,QAAM,kBAAkBC,aAAAA,mBAAmB,QAAQ,GAAG;AAEtDD,QAAAA,UAAU,MAAM;AACd,QAAI,CAAC,SAAS,CAAC,UAAW;AAC1B,mCAA+B,iBAAiB,UAAU;AAAA,EAC5D,GAAG,CAAC,OAAO,cAAc,iBAAiB,kBAAkB,CAAC;AAE7D,QAAM,cAAcE,WAAAA,SAAS;AAAA,IAC3B,UAAU;AAAA,MACR;AAAA,MACA,uCAAW;AAAA,MACX,uCAAW;AAAA,MACX;AAAA,IAAA;AAAA,IAEF,SAAS,YAAY;;AACnB,UAAI,CAAC,UAAW,QAAO,EAAE,SAAS,CAAA,EAAC;AACnC,aACG,QAAM,YAAO,kBAAP;AAAA;AAAA,QACL,UAAU;AAAA,QACV,UAAU;AAAA,QACVC,aAAAA,oBAAoB,iBAAiB,UAAU;AAAA,QAC/C,EAAE,QAAQ,0BAAA;AAAA,YACN,EAAE,SAAS,GAAC;AAAA,IAEtB;AAAA,IACA,SACE,SACA,CAAC,CAAC,aACF,CAAC,CAAC,OAAO,iBACT,WAAW,KAAK,CAAC,UAAU,MAAM,OAAO,OAAO;AAAA,IACjD,WAAW;AAAA,IACX,OAAO;AAAA,EAAA,CACR;AAED,QAAM,aAAaN,MAAAA,QAAQ,MAAM;AAC/B,QAAI,CAAC,MAAO,QAAO,EAAE,SAAS,CAAA,EAAC;AAC/B,WAAOO,oCAAuB,YAAY,QAAQ,WAAW;AAAA,MAC3D,QAAQ,YAAY;AAAA,MACpB,cAAc;AAAA,MACd,YAAY;AAAA,IAAA,CACb;AAAA,EACH,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,EAAA,CACD;AAED,QAAM,sBAAsBP,MAAAA;AAAAA,IAC1B,MAAMQ,yCAA4B,WAAW,YAAY,MAAM;AAAA,IAC/D,CAAC,WAAW,YAAY,MAAM;AAAA,EAAA;AAMhC,QAAM,yBAAyBC,MAAAA,OAAO,EAAE;AAExC,iBAAe,iBAAiBP,SAAyB;AACvD,QAAI,CAAC,UAAW;AAEhB,mBAAe,IAAI;AACnB,aAAS,IAAI;AAEb,QAAI;AACF,YAAM,WAAW,MAAM,OAAO;AAAA,QAC5B,UAAU;AAAA,QACV,UAAU;AAAA,QACVI,aAAAA,oBAAoBJ,SAAQ,UAAU,UAAU,cAAc,CAAA,CAAE;AAAA,QAChE,EAAE,QAAQ,cAAA;AAAA,MAAc;AAE1B,gBAAU,QAAQ;AAClB,2CAAW,UAAU,WAAWA;AAAAA,IAClC,SAAS,KAAK;AACZ,gBAAU,IAAI;AACd,eAAS,GAAG;AAAA,IACd,UAAA;AACE,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAEAC,QAAAA,UAAU,MAAM;AACd,kBAAc,KAAK;AACnB,cAAU,IAAI;AACd,aAAS,IAAI;AACb,2BAAuB,UAAU;AAAA,EACnC,GAAG,CAAC,kBAAkB,YAAY,CAAC;AAEnCA,QAAAA,UAAU,MAAM;AACd,QAAI,CAAC,oBAAoB,CAAC,aAAa,WAAY;AAKnD,UAAM,kBAAkB,WAAW,OAAO,CAAC,UAAU;AACnD,UAAI,CAAC,MAAM,SAAU,QAAO;AAC5B,cAAQ,uBAAuB,MAAM,IAAI,KAAK,IAAI,WAAW;AAAA,IAC/D,CAAC;AACD,QAAI,gBAAgB,SAAS,EAAG;AAEhC,kBAAc,IAAI;AAClB,2BAAuB,UAAU,KAAK;AAAA,MACpCO,aAAAA,qBAAqB,sBAAsB;AAAA,IAAA;AAE7C,SAAK,iBAAiB,sBAAsB;AAAA,EAC9C,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AAIDP,QAAAA,UAAU,MAAM;AACd,QAAI,CAAC,SAAS,CAAC,aAAa,CAAC,WAAY;AACzC,UAAM,SAAS,EAAE,GAAG,iBAAiB,GAAG,iBAAA;AACxC,UAAM,kBAAkB,WAAW,OAAO,CAAC,UAAU;AACnD,UAAI,CAAC,MAAM,SAAU,QAAO;AAC5B,cAAQ,OAAO,MAAM,IAAI,KAAK,IAAI,WAAW;AAAA,IAC/C,CAAC;AACD,QAAI,gBAAgB,SAAS,EAAG;AAChC,UAAM,YAAY,KAAK,UAAUO,aAAAA,qBAAqB,MAAM,CAAC;AAC7D,QAAI,uBAAuB,YAAY,UAAW;AAClD,2BAAuB,UAAU;AACjC,SAAK,iBAAiB,MAAM;AAAA,EAC9B,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AAED,QAAM,WACJ,YAAY,OAAO,OAAO,aACxB,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,WAAW;AAAA,IACX,UAAU;AAAA,EAAA,CACX,IAEDC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM;AAAA,MACN,WAAU;AAAA,MAET,UAAA;AAAA,IAAA;AAAA,EAAA;AAIP,MAAI,WAAW;AACb,WACEA,2BAAAA,IAAC,OAAA,EAAI,WAAU,iCAAgC,UAAA,wBAAoB;AAAA,EAEvE;AAEA,MAAI,CAAC,WAAW;AACd,WACEC,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,iCAAgC,UAAA;AAAA,QAAA;AAAA,QAC1BD,2BAAAA,IAAC,UAAM,UAAA,YAAA,CAAY;AAAA,MAAA,GACxC;AAAA,MACC;AAAA,IAAA,GACH;AAAA,EAEJ;AAEA,QAAM,EAAE,MAAM,QAAQ,WAAW,OAAO;AAExC,SACEC,2BAAAA,KAAC,OAAA,EAAI,WAAW,aAAa,gCAC3B,UAAA;AAAA,IAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,MAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,kBACZ,UAAA;AAAA,QAAA;AAAA,QACDA,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,UAAAD,+BAACE,YAAAA,eAAY,QAAgB;AAAA,UAC7BF,2BAAAA,IAAC,QAAG,WAAU,8BACX,aAAG,WAAW,GAAG,eAAe,KAAA,CACnC;AAAA,QAAA,GACF;AAAA,QACAA,2BAAAA,IAAC,KAAA,EAAE,WAAU,gDAAgD,UAAA,MAAK;AAAA,QACjE,GAAG,eAAe,GAAG,0CACnB,KAAA,EAAE,WAAU,gDACV,UAAA,GAAG,YAAA,CACN;AAAA,QAED,GAAG,eAAe,GAAG,gBAAgB,GAAG,WACvCA,2BAAAA,IAAC,KAAA,EAAE,WAAU,sCACV,UAAA,GAAG,YAAA,CACN;AAAA,MAAA,GAEJ;AAAA,MACAA,2BAAAA,IAAC,OAAA,EAAI,WAAU,0CACZ,UAAA,kBAAkB,SAAS,KAC1BA,2BAAAA,IAAC,OAAA,EAAI,WAAU,oCACZ,UAAA,kBAAkB;AAAA,QAAI,CAAC,YACtB,QAAQ,OACN,aACE,WAAW;AAAA,UACT,KAAK,GAAG,QAAQ,UAAU,MAAM,IAAI,QAAQ,UAAU,IAAI;AAAA,UAC1D,IAAI,QAAQ;AAAA,UACZ,WACE;AAAA,UACF,UAAU,QAAQ;AAAA,QAAA,CACnB,IAEDA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YAEC,MAAM,QAAQ;AAAA,YACd,WAAU;AAAA,YAET,UAAA,QAAQ;AAAA,UAAA;AAAA,UAJJ,GAAG,QAAQ,UAAU,MAAM,IAAI,QAAQ,UAAU,IAAI;AAAA,QAAA,IAQ9DA,2BAAAA;AAAAA,UAACG,sBAAAA;AAAAA,UAAA;AAAA,YAEC,WAAW,QAAQ;AAAA,YACnB;AAAA,YACA,eAAe;AAAA,YACf,OAAO,QAAQ;AAAA,YACf,eAAe;AAAA,YACd,GAAI,aAAa,EAAE,kBAAkB,eAAe,CAAA;AAAA,UAAC;AAAA,UANjD,GAAG,QAAQ,UAAU,MAAM,IAAI,QAAQ,UAAU,IAAI;AAAA,QAAA;AAAA,MAO5D,GAGN,EAAA,CAEJ;AAAA,IAAA,GACF;AAAA,IAEC,OAAO,YAAA,MAAkB,SACxBH,2BAAAA,IAAC,WAAA,EAAQ,WAAU,aACjB,UAAAA,2BAAAA,IAAC,OAAA,EAAI,WAAU,yBACb,UAAAA,2BAAAA;AAAAA,MAACI,YAAAA;AAAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,CAAC,WAAW,iBAAiB,MAAM;AAAA,QAC9C,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,eAAe;AAAA,MAAA;AAAA,IAAA,GAEnB,EAAA,CACF;AAAA,IAGD,QACCJ,2BAAAA,IAACK,YAAAA,aAAA,EAAY,OAAO,kBAAkB,IAAI,IAAI,MAAA,CAAc,IAC1D,eAAe,SACjBL,2BAAAA;AAAAA,MAACM,oBAAAA;AAAAA,MAAA;AAAA,QACC,UAAU;AAAA,QACV,SAAS;AAAA,QACT,gBAAe;AAAA,QACf,WAAU;AAAA,QACV;AAAA,QACC,GAAI,iBAAiB,EAAE,eAAA,IAAmB,CAAA;AAAA,QAC1C,GAAI,SAAS,mBACV;AAAA,UACE,cAAc;AAAA,YACZ,SAAS,WAAW;AAAA,YACpB,GAAI,WAAW,YACX,EAAE,WAAW,WAAW,UAAA,IACxB,CAAA;AAAA,UAAC;AAAA,QACP,IAEF,CAAA;AAAA,QACH,GAAI,SAAS,oBAAoB,sBAC9B,EAAE,YAAY,oBAAA,IACd,CAAA;AAAA,MAAC;AAAA,IAAA,IAEL;AAAA,EAAA,GACN;AAEJ;AAQA,SAAS,sBACP,SACA,YACA,YACoB;AACpB,MAAI,QAAQ,OAAO,YAAA,MAAkB,cAAc,CAAA;AACnD,MAAI,CAAC,sBAAsB,QAAQ,MAAM,UAAU,UAAU,CAAA;AAE7D,QAAM,WAAW,QAAQ,KAAK,QAAQ,QAAQ,EAAE;AAChD,SAAO,WACJ,OAAO,CAAC,cAAc;AACrB,QAAI,cAAc,QAAS,QAAO;AAClC,QAAI,CAAC,UAAU,KAAK,WAAW,GAAG,QAAQ,GAAG,EAAG,QAAO;AACvD,QAAI,CAAC,sBAAsB,UAAU,MAAM,UAAU,EAAG,QAAO;AAC/D,UAAM,SAAS,UAAU,OAAO,YAAA;AAChC,WACE,WAAW,SACX,WAAW,UACX,WAAW,SACX,WAAW;AAAA,EAEf,CAAC,EACA,IAAI,CAAC,YAAY;AAChB,UAAM,SAAS,QAAQ,OAAO,YAAA;AAC9B,UAAM,OACJ,WAAW,QACPC,cAAAA,iBAAiB,SAAS,CAAA,GAAI,UAAU,IACxC;AACN,WAAO;AAAA,MACL,WAAW;AAAA,MACX,OAAO,eAAe,OAAO;AAAA,MAC7B,GAAI,OAAO,EAAE,SAAS,CAAA;AAAA,IAAC;AAAA,EAE3B,CAAC,EACA;AAAA,IACC,CAAC,YACC,QAAQ,UAAU,OAAO,YAAA,MAAkB,SAAS,QAAQ;AAAA,EAAA;AAEpE;AAEA,SAAS,oBACP,SACA,YACA;AACA,QAAM,SAAS,QAAQ,OAAO,YAAA;AAC9B,QAAM,aAAa,GAAG,QAAQ,KAAK,QAAQ,QAAQ,EAAE,CAAC;AACtD,SAAO,WAAW;AAAA,IAChB,CAAC,cAAA;;AACC,uBAAU,OAAO,YAAA,MAAkB,UACnC,UAAU,SAAS,gBACnB,eAAU,UAAU,eAApB,mBAAgC;AAAA,QAC9B,CAAC,UAAU,MAAM,OAAO,UAAU,MAAM,SAAS,QAAQ,MAAM;AAAA;AAAA;AAAA,EACjE;AAEN;AAEA,SAAS,sBAAsB,MAAc,QAAgC;AAC3E,SAAOC,iBAAAA,eAAe,IAAI,EAAE,MAAM,CAAC,SAAS,QAAQ,OAAO,IAAI,CAAC,CAAC;AACnE;AAEA,SAAS,eAAe,WAAsC;;AAC5D,QAAM,eACJ,eAAU,UAAU,UAAU,MAA9B,mBAAiC,eACjC,UAAU,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,GAAG,EAAE,KAC/C,UAAU,UAAU,eACpB,UAAU;AACZ,SAAOC,aAAAA,UAAU,WAAW,QAAQ,UAAU,GAAG,CAAC;AACpD;AAEA,SAAS,kBAAkB,QAA0C;AACnE,QAAM,OAAwB,CAAA;AAC9B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,QAAQ,aAAa,IAAI,WAAW,IAAI,EAAG;AAC/C,SAAK,GAAG,IAAI;AAAA,EACd;AACA,SAAO;AACT;AAEA,SAAS,gCACP,YACiB;AACjB,MAAI,OAAO,WAAW,YAAa,QAAO,CAAA;AAC1C,QAAM,kBAAkB,IAAI;AAAA,IAC1B,WAAW,OAAO,CAAC,UAAU,MAAM,OAAO,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EAAA;AAEtE,MAAI,gBAAgB,SAAS,EAAG,QAAO,CAAA;AAEvC,QAAM,SAA0B,CAAA;AAChC,QAAM,SAAS,IAAI,gBAAgB,OAAO,SAAS,MAAM;AACzD,aAAW,QAAQ,iBAAiB;AAClC,UAAM,QAAQ,OAAO,IAAI,IAAI;AAC7B,QAAI,SAAS,QAAQ,UAAU,IAAI;AACjC,aAAO,IAAI,IAAI;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,+BACP,QACA,YACA;AACA,MAAI,OAAO,WAAW,YAAa;AACnC,QAAM,kBAAkB,WAAW,OAAO,CAAC,UAAU,MAAM,OAAO,OAAO;AACzE,MAAI,gBAAgB,WAAW,EAAG;AAElC,QAAM,SAAS,IAAI,gBAAgB,OAAO,SAAS,MAAM;AACzD,aAAW,SAAS,iBAAiB;AACnC,UAAM,QAAQC,iBAAAA,YAAY,OAAO,OAAO,MAAM,IAAI,CAAC;AACnD,QAAI,SAAS,MAAM;AACjB,aAAO,OAAO,MAAM,IAAI;AAAA,IAC1B,OAAO;AACL,aAAO,IAAI,MAAM,MAAM,KAAK;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,QAAQ,OAAO,SAAA;AACrB,QAAM,OAAO,GAAG,OAAO,SAAS,QAAQ,GAAG,QAAQ,IAAI,KAAK,KAAK,EAAE,GAAG,OAAO,SAAS,IAAI;AAC1F,QAAM,UAAU,GAAG,OAAO,SAAS,QAAQ,GAAG,OAAO,SAAS,MAAM,GAAG,OAAO,SAAS,IAAI;AAC3F,MAAI,SAAS,SAAS;AACpB,WAAO,QAAQ,aAAa,OAAO,QAAQ,OAAO,IAAI,IAAI;AAAA,EAC5D;AACF;;"}
1
+ {"version":3,"file":"OperationCommandPage.cjs","sources":["../../src/rpc/OperationCommandPage.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { ClickyCommandRuntime } from \"../data/Clicky\";\nimport { MethodBadge } from \"../data/MethodBadge\";\nimport { stripTrailingSlashes } from \"../lib/string\";\nimport { CommandForm } from \"./CommandForm\";\nimport { pathParamNames, submitValue } from \"./command-form-utils\";\nimport type { RenderLink } from \"./EndpointList\";\nimport {\n buildInitialParameterValues,\n dataTablePaginationFromForm,\n packParameterValues,\n parametersToFormConfig,\n pruneParameterValues,\n titleCase,\n useDebouncedRecord,\n type ParameterValues,\n} from \"./formMetadata\";\nimport { InlineError } from \"./InlineError\";\nimport { OperationActionDialog } from \"./OperationActionDialog\";\nimport { OperationResultView } from \"./OperationResultView\";\nimport { hrefForOperation } from \"./rowNavigation\";\nimport type {\n ExecutionResponse,\n OpenAPIParameter,\n ResolvedOperation,\n} from \"./types\";\nimport { useOperationById, type OperationsApiClient } from \"./useOperations\";\n\n// All operation results are fetched as clicky documents; the in-result View\n// menu re-fetches other formats on demand via the response's requestUrl.\nconst RESULT_ACCEPT = \"application/clicky+json\";\n\nexport type OperationCommandPageProps = {\n client: OperationsApiClient;\n operationId?: string;\n operation?: ResolvedOperation;\n operations?: ResolvedOperation[];\n initialValues?: ParameterValues;\n autoRun?: boolean;\n backHref?: string;\n backLabel?: string;\n renderLink?: RenderLink;\n commandRuntime?: ClickyCommandRuntime;\n onNavigate?: (href: string) => void;\n onResult?: (\n response: ExecutionResponse,\n operation: ResolvedOperation,\n values: ParameterValues,\n ) => void;\n hideLockedPathFilters?: boolean;\n className?: string;\n};\n\nconst EMPTY_PARAMETER_VALUES: ParameterValues = {};\n\nexport function OperationCommandPage({\n client,\n operationId,\n operation: providedOperation,\n operations = providedOperation ? [providedOperation] : [],\n initialValues = EMPTY_PARAMETER_VALUES,\n autoRun,\n backHref,\n backLabel = \"Back\",\n renderLink,\n onNavigate,\n onResult,\n commandRuntime,\n hideLockedPathFilters = Boolean(providedOperation),\n className,\n}: OperationCommandPageProps) {\n const lookup = useOperationById(\n client,\n providedOperation ? undefined : operationId,\n );\n const operation = providedOperation ?? lookup.operation;\n const isLoading = providedOperation ? false : lookup.isLoading;\n const [isExecuting, setIsExecuting] = useState(false);\n const [result, setResult] = useState<ExecutionResponse | null>(null);\n const [error, setError] = useState<unknown>(null);\n const [hasAutoRun, setHasAutoRun] = useState(false);\n const parameters = operation?.operation.parameters ?? [];\n const isGet = (operation?.method ?? \"\").toUpperCase() === \"GET\";\n const effectiveAutoRun = operation ? (autoRun ?? isGet) : false;\n const parameterSignature = JSON.stringify(\n parameters.map((param) => ({\n name: param.name,\n in: param.in,\n required: param.required ?? false,\n default: param.schema?.default ?? null,\n })),\n );\n const operationKey = `${operation?.method ?? \"\"}:${operation?.path ?? \"\"}:${operation?.operation.operationId ?? \"\"}`;\n const effectiveInitialValues = useMemo(\n () =>\n operation\n ? buildInitialParameterValues(\n parameters,\n operation.method,\n {},\n {\n ...readQueryParameterValuesFromUrl(parameters),\n ...stripRunnerParams(initialValues),\n },\n )\n : stripRunnerParams(initialValues),\n [initialValues, operation?.method, parameterSignature],\n );\n const pathParameters = parameters.filter((param) => param.in === \"path\");\n const lockedPathValues = useMemo<ParameterValues>(() => {\n const values: ParameterValues = {};\n for (const param of pathParameters) {\n const value = effectiveInitialValues[param.name];\n if (typeof value === \"string\" && value.trim() !== \"\") {\n values[param.name] = value;\n }\n }\n return values;\n }, [effectiveInitialValues, pathParameters]);\n const detailOperation = useMemo(\n () => (operation ? findDetailOperation(operation, operations) : undefined),\n [operation, operations],\n );\n const relatedOperations = useMemo(\n () =>\n operation\n ? findRelatedOperations(operation, operations, lockedPathValues)\n : [],\n [lockedPathValues, operation, operations],\n );\n\n // GET-mode parameter state: filter values + pagination cursor are driven\n // by the page so they can flow natively into the result table's in-table\n // FilterBar and pagination footer (via OperationResultView's filterConfig).\n const [values, setValues] = useState<ParameterValues>(effectiveInitialValues);\n useEffect(() => {\n setValues(effectiveInitialValues);\n }, [effectiveInitialValues]);\n const debouncedValues = useDebouncedRecord(values, 250);\n\n useEffect(() => {\n if (!isGet || !operation) return;\n writeQueryParameterValuesToUrl(debouncedValues, parameters);\n }, [isGet, operationKey, debouncedValues, parameterSignature]);\n\n const lookupQuery = useQuery({\n queryKey: [\n \"operation-query-lookup\",\n operation?.method,\n operation?.path,\n debouncedValues,\n ],\n queryFn: async () => {\n if (!operation) return { filters: {} };\n return (\n (await client.lookupFilters?.(\n operation.path,\n operation.method,\n packParameterValues(debouncedValues, parameters),\n { Accept: \"application/json+clicky\" },\n )) ?? { filters: {} }\n );\n },\n enabled:\n isGet &&\n !!operation &&\n !!client.lookupFilters &&\n parameters.some((param) => param.in === \"query\"),\n staleTime: 30_000,\n retry: 0,\n });\n\n const formConfig = useMemo(() => {\n if (!isGet) return { filters: [] };\n return parametersToFormConfig(parameters, values, setValues, {\n lookup: lookupQuery.data,\n lockedValues: lockedPathValues,\n hideLocked: hideLockedPathFilters,\n });\n }, [\n isGet,\n parameters,\n values,\n lookupQuery.data,\n lockedPathValues,\n hideLockedPathFilters,\n ]);\n\n const dataTablePagination = useMemo(\n () => dataTablePaginationFromForm(formConfig.pagination, result),\n [formConfig.pagination, result],\n );\n\n // Ref tracking the last submitted parameter signature so the\n // auto-submit-on-debounced-change effect coordinates against the same\n // \"have I already fired this set of values\" check.\n const lastSubmittedSignature = useRef(\"\");\n\n async function executeOperation(values: ParameterValues) {\n if (!operation) return;\n\n setIsExecuting(true);\n setError(null);\n\n try {\n const response = await client.executeCommand(\n operation.path,\n operation.method,\n packParameterValues(values, operation.operation.parameters ?? []),\n { Accept: RESULT_ACCEPT },\n );\n setResult(response);\n onResult?.(response, operation, values);\n } catch (err) {\n setResult(null);\n setError(err);\n } finally {\n setIsExecuting(false);\n }\n }\n\n useEffect(() => {\n setHasAutoRun(false);\n setResult(null);\n setError(null);\n lastSubmittedSignature.current = \"\";\n }, [effectiveAutoRun, operationKey]);\n\n useEffect(() => {\n if (!effectiveAutoRun || !operation || hasAutoRun) return;\n // Auto-run a GET as long as every required parameter has a value. Optional\n // params (limit/offset, filter chips, etc.) get their defaults; the\n // sidebar's \"click → instant table\" flow depends on this not bailing just\n // because the operation declares any parameters at all.\n const missingRequired = parameters.filter((param) => {\n if (!param.required) return false;\n return (effectiveInitialValues[param.name] ?? \"\").trim() === \"\";\n });\n if (missingRequired.length > 0) return;\n\n setHasAutoRun(true);\n lastSubmittedSignature.current = JSON.stringify(\n pruneParameterValues(effectiveInitialValues),\n );\n void executeOperation(effectiveInitialValues);\n }, [\n effectiveAutoRun,\n effectiveInitialValues,\n hasAutoRun,\n operationKey,\n parameterSignature,\n ]);\n\n // GET re-runs on debounced filter/pagination changes once the initial\n // auto-run has fired; non-GETs keep their explicit-submit behavior.\n useEffect(() => {\n if (!isGet || !operation || !hasAutoRun) return;\n const merged = { ...debouncedValues, ...lockedPathValues };\n const missingRequired = parameters.filter((param) => {\n if (!param.required) return false;\n return (merged[param.name] ?? \"\").trim() === \"\";\n });\n if (missingRequired.length > 0) return;\n const signature = JSON.stringify(pruneParameterValues(merged));\n if (lastSubmittedSignature.current === signature) return;\n lastSubmittedSignature.current = signature;\n void executeOperation(merged);\n }, [\n isGet,\n hasAutoRun,\n debouncedValues,\n lockedPathValues,\n parameterSignature,\n ]);\n\n const backLink =\n backHref == null ? null : renderLink ? (\n renderLink({\n to: backHref,\n className: \"text-sm text-primary underline-offset-4 hover:underline\",\n children: backLabel,\n })\n ) : (\n <a\n href={backHref}\n className=\"text-sm text-primary underline-offset-4 hover:underline\"\n >\n {backLabel}\n </a>\n );\n\n if (isLoading) {\n return (\n <div className=\"text-sm text-muted-foreground\">Loading operation...</div>\n );\n }\n\n if (!operation) {\n return (\n <div className=\"space-y-4\">\n <div className=\"text-sm text-muted-foreground\">\n Unknown operation: <code>{operationId}</code>\n </div>\n {backLink}\n </div>\n );\n }\n\n const { path, method, operation: op } = operation;\n\n return (\n <div className={className ?? \"min-w-0 flex-1 space-y-6 p-6\"}>\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"min-w-0 flex-1\">\n {backLink}\n <div className=\"flex items-center gap-3\">\n <MethodBadge method={method} />\n <h1 className=\"truncate text-xl font-bold\">\n {op.summary || op.operationId || path}\n </h1>\n </div>\n <p className=\"mt-1 font-mono text-xs text-muted-foreground\">{path}</p>\n {op.operationId && op.summary && (\n <p className=\"mt-2 font-mono text-xs text-muted-foreground\">\n {op.operationId}\n </p>\n )}\n {op.description && op.description !== op.summary && (\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {op.description}\n </p>\n )}\n </div>\n <div className=\"flex shrink-0 flex-col items-end gap-3\">\n {relatedOperations.length > 0 && (\n <div className=\"flex flex-wrap justify-end gap-2\">\n {relatedOperations.map((related) =>\n related.href ? (\n renderLink ? (\n renderLink({\n key: `${related.operation.method}:${related.operation.path}`,\n to: related.href,\n className:\n \"inline-flex h-8 items-center justify-center gap-2 rounded-md border border-input bg-background px-3 text-xs font-medium hover:bg-accent hover:text-accent-foreground\",\n children: related.label,\n })\n ) : (\n <a\n key={`${related.operation.method}:${related.operation.path}`}\n href={related.href}\n className=\"inline-flex h-8 items-center justify-center gap-2 rounded-md border border-input bg-background px-3 text-xs font-medium hover:bg-accent hover:text-accent-foreground\"\n >\n {related.label}\n </a>\n )\n ) : (\n <OperationActionDialog\n key={`${related.operation.method}:${related.operation.path}`}\n operation={related.operation}\n client={client}\n initialValues={lockedPathValues}\n label={related.label}\n defaultAccept={RESULT_ACCEPT}\n {...(onNavigate ? { onNavigateAction: onNavigate } : {})}\n />\n ),\n )}\n </div>\n )}\n </div>\n </div>\n\n {method.toUpperCase() !== \"GET\" && (\n <section className=\"space-y-3\">\n <div className=\"rounded-lg border p-4\">\n <CommandForm\n parameters={parameters}\n onExecute={(params) => executeOperation(params)}\n isPending={isExecuting}\n method={method}\n path={path}\n accept={RESULT_ACCEPT}\n initialValues={effectiveInitialValues}\n />\n </div>\n </section>\n )}\n\n {error ? (\n <InlineError title={`Failed to load ${path}`} error={error} />\n ) : isExecuting || result ? (\n <OperationResultView\n response={result}\n loading={isExecuting}\n loadingMessage=\"Loading execution results…\"\n ariaLabel=\"Response body\"\n detailOperation={detailOperation}\n {...(commandRuntime ? { commandRuntime } : {})}\n {...(isGet && effectiveAutoRun\n ? {\n filterConfig: {\n filters: formConfig.filters,\n ...(formConfig.timeRange\n ? { timeRange: formConfig.timeRange }\n : {}),\n },\n }\n : {})}\n {...(isGet && effectiveAutoRun && dataTablePagination\n ? { pagination: dataTablePagination }\n : {})}\n />\n ) : null}\n </div>\n );\n}\n\ntype RelatedOperation = {\n operation: ResolvedOperation;\n label: string;\n href?: string;\n};\n\nfunction findRelatedOperations(\n current: ResolvedOperation,\n operations: ResolvedOperation[],\n pathValues: Record<string, string>,\n): RelatedOperation[] {\n if (current.method.toUpperCase() !== \"GET\") return [];\n if (!pathTemplateSatisfied(current.path, pathValues)) return [];\n\n const basePath = stripTrailingSlashes(current.path);\n return operations\n .filter((candidate) => {\n if (candidate === current) return false;\n if (!candidate.path.startsWith(`${basePath}/`)) return false;\n if (!pathTemplateSatisfied(candidate.path, pathValues)) return false;\n const method = candidate.method.toUpperCase();\n return (\n method === \"GET\" ||\n method === \"POST\" ||\n method === \"PUT\" ||\n method === \"DELETE\"\n );\n })\n .map((related) => {\n const method = related.method.toUpperCase();\n const href =\n method === \"GET\"\n ? hrefForOperation(related, [], pathValues)\n : undefined;\n return {\n operation: related,\n label: operationLabel(related),\n ...(href ? { href } : {}),\n };\n })\n .filter(\n (related) =>\n related.operation.method.toUpperCase() !== \"GET\" || related.href,\n );\n}\n\nfunction findDetailOperation(\n current: ResolvedOperation,\n operations: ResolvedOperation[],\n) {\n const method = current.method.toUpperCase();\n const detailPath = `${stripTrailingSlashes(current.path)}/{id}`;\n return operations.find(\n (candidate) =>\n candidate.method.toUpperCase() === method &&\n candidate.path === detailPath &&\n candidate.operation.parameters?.some(\n (param) => param.in === \"path\" && param.name === \"id\" && param.required,\n ),\n );\n}\n\nfunction pathTemplateSatisfied(path: string, values: Record<string, string>) {\n return pathParamNames(path).every((name) => Boolean(values[name]));\n}\n\nfunction operationLabel(operation: ResolvedOperation): string {\n const actionName =\n operation.operation[\"x-clicky\"]?.actionName ||\n operation.path.split(\"/\").filter(Boolean).at(-1) ||\n operation.operation.operationId ||\n operation.method;\n return titleCase(actionName.replace(/[_-]+/g, \" \"));\n}\n\nfunction stripRunnerParams(values: ParameterValues): ParameterValues {\n const next: ParameterValues = {};\n for (const [key, value] of Object.entries(values)) {\n if (key === \"autoRun\" || key.startsWith(\"__\")) continue;\n next[key] = value;\n }\n return next;\n}\n\nfunction readQueryParameterValuesFromUrl(\n parameters: OpenAPIParameter[],\n): ParameterValues {\n if (typeof window === \"undefined\") return {};\n const queryParamNames = new Set(\n parameters.filter((param) => param.in === \"query\").map((p) => p.name),\n );\n if (queryParamNames.size === 0) return {};\n\n const values: ParameterValues = {};\n const search = new URLSearchParams(window.location.search);\n for (const name of queryParamNames) {\n const value = search.get(name);\n if (value != null && value !== \"\") {\n values[name] = value;\n }\n }\n return values;\n}\n\nfunction writeQueryParameterValuesToUrl(\n values: ParameterValues,\n parameters: OpenAPIParameter[],\n) {\n if (typeof window === \"undefined\") return;\n const queryParameters = parameters.filter((param) => param.in === \"query\");\n if (queryParameters.length === 0) return;\n\n const search = new URLSearchParams(window.location.search);\n for (const param of queryParameters) {\n const value = submitValue(param, values[param.name]);\n if (value == null) {\n search.delete(param.name);\n } else {\n search.set(param.name, value);\n }\n }\n\n const query = search.toString();\n const next = `${window.location.pathname}${query ? `?${query}` : \"\"}${window.location.hash}`;\n const current = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n if (next !== current) {\n window.history.replaceState(window.history.state, \"\", next);\n }\n}\n"],"names":["useOperationById","useState","useMemo","buildInitialParameterValues","values","useEffect","useDebouncedRecord","useQuery","packParameterValues","parametersToFormConfig","dataTablePaginationFromForm","useRef","pruneParameterValues","jsx","jsxs","MethodBadge","OperationActionDialog","CommandForm","InlineError","OperationResultView","stripTrailingSlashes","hrefForOperation","pathParamNames","titleCase","submitValue"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"OperationCommandPage.d.ts","sourceRoot":"","sources":["../../src/rpc/OperationCommandPage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAI3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAQL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAKxB,OAAO,KAAK,EACV,iBAAiB,EAEjB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAoB,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAM7E,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CACT,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,eAAe,KACpB,IAAI,CAAC;IACV,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAIF,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACX,SAAS,EAAE,iBAAiB,EAC5B,UAAyD,EACzD,aAAsC,EACtC,OAAO,EACP,QAAQ,EACR,SAAkB,EAClB,UAAU,EACV,UAAU,EACV,QAAQ,EACR,cAAc,EACd,qBAAkD,EAClD,SAAS,GACV,EAAE,yBAAyB,2CAyV3B"}
1
+ {"version":3,"file":"OperationCommandPage.d.ts","sourceRoot":"","sources":["../../src/rpc/OperationCommandPage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAK3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAQL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAKxB,OAAO,KAAK,EACV,iBAAiB,EAEjB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAoB,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAM7E,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CACT,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,eAAe,KACpB,IAAI,CAAC;IACV,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAIF,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACX,SAAS,EAAE,iBAAiB,EAC5B,UAAyD,EACzD,aAAsC,EACtC,OAAO,EACP,QAAQ,EACR,SAAkB,EAClB,UAAU,EACV,UAAU,EACV,QAAQ,EACR,cAAc,EACd,qBAAkD,EAClD,SAAS,GACV,EAAE,yBAAyB,2CAyV3B"}
@@ -2,6 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useState, useMemo, useEffect, useRef } from "react";
3
3
  import { useQuery } from "@tanstack/react-query";
4
4
  import { MethodBadge } from "../data/MethodBadge.js";
5
+ import { stripTrailingSlashes } from "../lib/string.js";
5
6
  import { CommandForm } from "./CommandForm.js";
6
7
  import { submitValue, pathParamNames } from "./command-form-utils.js";
7
8
  import { buildInitialParameterValues, useDebouncedRecord, packParameterValues, parametersToFormConfig, dataTablePaginationFromForm, pruneParameterValues, titleCase } from "./formMetadata.js";
@@ -299,7 +300,7 @@ function OperationCommandPage({
299
300
  function findRelatedOperations(current, operations, pathValues) {
300
301
  if (current.method.toUpperCase() !== "GET") return [];
301
302
  if (!pathTemplateSatisfied(current.path, pathValues)) return [];
302
- const basePath = current.path.replace(/\/+$/, "");
303
+ const basePath = stripTrailingSlashes(current.path);
303
304
  return operations.filter((candidate) => {
304
305
  if (candidate === current) return false;
305
306
  if (!candidate.path.startsWith(`${basePath}/`)) return false;
@@ -320,7 +321,7 @@ function findRelatedOperations(current, operations, pathValues) {
320
321
  }
321
322
  function findDetailOperation(current, operations) {
322
323
  const method = current.method.toUpperCase();
323
- const detailPath = `${current.path.replace(/\/+$/, "")}/{id}`;
324
+ const detailPath = `${stripTrailingSlashes(current.path)}/{id}`;
324
325
  return operations.find(
325
326
  (candidate) => {
326
327
  var _a;