@octaviaflow/core 3.1.0-beta.67 → 3.1.0-beta.69

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 (107) hide show
  1. package/dist/chunk-64R3BAO7.js +2755 -0
  2. package/dist/chunk-64R3BAO7.js.map +1 -0
  3. package/dist/chunk-7S3CSRRV.js +5700 -0
  4. package/dist/chunk-7S3CSRRV.js.map +1 -0
  5. package/dist/chunk-JMSZOWT2.js +2616 -0
  6. package/dist/chunk-JMSZOWT2.js.map +1 -0
  7. package/dist/chunk-KCA7V5VN.js +5752 -0
  8. package/dist/chunk-KCA7V5VN.js.map +1 -0
  9. package/dist/chunk-KQKD4Z4H.js +1682 -0
  10. package/dist/chunk-KQKD4Z4H.js.map +1 -0
  11. package/dist/chunk-KZP2MNBO.js +2516 -0
  12. package/dist/chunk-KZP2MNBO.js.map +1 -0
  13. package/dist/chunk-PWCRELX4.js +5700 -0
  14. package/dist/chunk-PWCRELX4.js.map +1 -0
  15. package/dist/chunk-S4LE4BFQ.js +5934 -0
  16. package/dist/chunk-S4LE4BFQ.js.map +1 -0
  17. package/dist/chunk-U5T63SPL.js +5695 -0
  18. package/dist/chunk-U5T63SPL.js.map +1 -0
  19. package/dist/chunk-X7YETDK7.js +107 -0
  20. package/dist/chunk-X7YETDK7.js.map +1 -0
  21. package/dist/chunk-YIPBLM3G.js +2698 -0
  22. package/dist/chunk-YIPBLM3G.js.map +1 -0
  23. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  24. package/dist/components/WorkflowShowcase/ShowcaseScene.d.ts +20 -0
  25. package/dist/components/WorkflowShowcase/ShowcaseScene.d.ts.map +1 -0
  26. package/dist/components/WorkflowShowcase/ShowcaseSignup.d.ts +14 -0
  27. package/dist/components/WorkflowShowcase/ShowcaseSignup.d.ts.map +1 -0
  28. package/dist/components/WorkflowShowcase/WorkflowShowcase.d.ts +48 -0
  29. package/dist/components/WorkflowShowcase/WorkflowShowcase.d.ts.map +1 -0
  30. package/dist/components/WorkflowShowcase/index.d.ts +3 -0
  31. package/dist/components/WorkflowShowcase/index.d.ts.map +1 -0
  32. package/dist/components/WorkflowShowcase/showcaseEngine.d.ts +102 -0
  33. package/dist/components/WorkflowShowcase/showcaseEngine.d.ts.map +1 -0
  34. package/dist/index.cjs +5 -0
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.js +18795 -25817
  37. package/dist/index.js.map +1 -1
  38. package/dist/marketing/components/AssistantTranscript/AssistantTranscript.d.ts +15 -0
  39. package/dist/marketing/components/AssistantTranscript/AssistantTranscript.d.ts.map +1 -0
  40. package/dist/marketing/components/BackedBy/BackedBy.d.ts +17 -0
  41. package/dist/marketing/components/BackedBy/BackedBy.d.ts.map +1 -0
  42. package/dist/marketing/components/BetaAccessForm/BetaAccessForm.d.ts +36 -0
  43. package/dist/marketing/components/BetaAccessForm/BetaAccessForm.d.ts.map +1 -0
  44. package/dist/marketing/components/BlogGrid/BlogGrid.d.ts +32 -0
  45. package/dist/marketing/components/BlogGrid/BlogGrid.d.ts.map +1 -0
  46. package/dist/marketing/components/ContactForm/ContactForm.d.ts +31 -0
  47. package/dist/marketing/components/ContactForm/ContactForm.d.ts.map +1 -0
  48. package/dist/marketing/components/CtaBanner/CtaBanner.d.ts +16 -0
  49. package/dist/marketing/components/CtaBanner/CtaBanner.d.ts.map +1 -0
  50. package/dist/marketing/components/FaqSection/FaqSection.d.ts +13 -0
  51. package/dist/marketing/components/FaqSection/FaqSection.d.ts.map +1 -0
  52. package/dist/marketing/components/FeatureGrid/FeatureGrid.d.ts +15 -0
  53. package/dist/marketing/components/FeatureGrid/FeatureGrid.d.ts.map +1 -0
  54. package/dist/marketing/components/IntegrationsFinder/IntegrationsFinder.d.ts +32 -0
  55. package/dist/marketing/components/IntegrationsFinder/IntegrationsFinder.d.ts.map +1 -0
  56. package/dist/marketing/components/IntegrationsWall/IntegrationsWall.d.ts +21 -0
  57. package/dist/marketing/components/IntegrationsWall/IntegrationsWall.d.ts.map +1 -0
  58. package/dist/marketing/components/LiveConsole/LiveConsole.d.ts +21 -0
  59. package/dist/marketing/components/LiveConsole/LiveConsole.d.ts.map +1 -0
  60. package/dist/marketing/components/LogoMarquee/LogoMarquee.d.ts +18 -0
  61. package/dist/marketing/components/LogoMarquee/LogoMarquee.d.ts.map +1 -0
  62. package/dist/marketing/components/MarketingFooter/MarketingFooter.d.ts +30 -0
  63. package/dist/marketing/components/MarketingFooter/MarketingFooter.d.ts.map +1 -0
  64. package/dist/marketing/components/MarketingHero/MarketingHero.d.ts +11 -0
  65. package/dist/marketing/components/MarketingHero/MarketingHero.d.ts.map +1 -0
  66. package/dist/marketing/components/MarketingNav/MarketingNav.d.ts +17 -0
  67. package/dist/marketing/components/MarketingNav/MarketingNav.d.ts.map +1 -0
  68. package/dist/marketing/components/MarketingSection/MarketingSection.d.ts +15 -0
  69. package/dist/marketing/components/MarketingSection/MarketingSection.d.ts.map +1 -0
  70. package/dist/marketing/components/PageHero/PageHero.d.ts +12 -0
  71. package/dist/marketing/components/PageHero/PageHero.d.ts.map +1 -0
  72. package/dist/marketing/components/PricingTiers/PricingTiers.d.ts +29 -0
  73. package/dist/marketing/components/PricingTiers/PricingTiers.d.ts.map +1 -0
  74. package/dist/marketing/components/StatBand/StatBand.d.ts +16 -0
  75. package/dist/marketing/components/StatBand/StatBand.d.ts.map +1 -0
  76. package/dist/marketing/components/TestimonialStrip/TestimonialStrip.d.ts +24 -0
  77. package/dist/marketing/components/TestimonialStrip/TestimonialStrip.d.ts.map +1 -0
  78. package/dist/marketing/components/WorkflowShowcase/ShowcaseScene.d.ts +22 -0
  79. package/dist/marketing/components/WorkflowShowcase/ShowcaseScene.d.ts.map +1 -0
  80. package/dist/marketing/components/WorkflowShowcase/ShowcaseSignup.d.ts +14 -0
  81. package/dist/marketing/components/WorkflowShowcase/ShowcaseSignup.d.ts.map +1 -0
  82. package/dist/marketing/components/WorkflowShowcase/WorkflowShowcase.d.ts +56 -0
  83. package/dist/marketing/components/WorkflowShowcase/WorkflowShowcase.d.ts.map +1 -0
  84. package/dist/marketing/components/WorkflowShowcase/index.d.ts +3 -0
  85. package/dist/marketing/components/WorkflowShowcase/index.d.ts.map +1 -0
  86. package/dist/marketing/components/WorkflowShowcase/showcaseEngine.d.ts +104 -0
  87. package/dist/marketing/components/WorkflowShowcase/showcaseEngine.d.ts.map +1 -0
  88. package/dist/marketing/glyphs.d.ts +20 -0
  89. package/dist/marketing/glyphs.d.ts.map +1 -0
  90. package/dist/marketing/index.d.ts +23 -0
  91. package/dist/marketing/index.d.ts.map +1 -0
  92. package/dist/marketing.cjs +6581 -0
  93. package/dist/marketing.cjs.map +1 -0
  94. package/dist/marketing.js +2602 -0
  95. package/dist/marketing.js.map +1 -0
  96. package/dist/styles.css +1 -1
  97. package/dist/workflow/components/HttpActionPanel/HttpActionPanel.d.ts +29 -0
  98. package/dist/workflow/components/HttpActionPanel/HttpActionPanel.d.ts.map +1 -0
  99. package/dist/workflow/components/HttpActionPanel/httpActionTypes.d.ts +135 -0
  100. package/dist/workflow/components/HttpActionPanel/httpActionTypes.d.ts.map +1 -0
  101. package/dist/workflow/index.d.ts +2 -0
  102. package/dist/workflow/index.d.ts.map +1 -1
  103. package/dist/workflow.cjs +6931 -271
  104. package/dist/workflow.cjs.map +1 -1
  105. package/dist/workflow.js +1591 -56
  106. package/dist/workflow.js.map +1 -1
  107. package/package.json +6 -1
package/dist/workflow.js CHANGED
@@ -1,9 +1,14 @@
1
1
  import {
2
2
  ActionNode,
3
+ Badge,
4
+ Banner,
5
+ CodeEditor,
6
+ Combobox,
3
7
  ConditionNode,
4
8
  DEFAULT_NODE_HEIGHT,
5
9
  DEFAULT_NODE_KINDS,
6
10
  DEFAULT_NODE_WIDTH,
11
+ Disclosure,
7
12
  ErrorNode,
8
13
  FlowCanvas,
9
14
  FlowEdge,
@@ -12,10 +17,17 @@ import {
12
17
  GroupNode,
13
18
  Handle,
14
19
  HttpRequestNode,
20
+ JsonViewer,
21
+ KeyValueEditor,
15
22
  NodeResizer,
23
+ NumberInput,
16
24
  OutputNode,
17
25
  ParallelNode,
26
+ PasswordInput,
27
+ SegmentedControl,
18
28
  StickyNode,
29
+ Switch,
30
+ Tabs,
19
31
  TriggerNode,
20
32
  WaitNode,
21
33
  WebhookNode,
@@ -50,7 +62,14 @@ import {
50
62
  useSelection,
51
63
  useViewport,
52
64
  useViewportOrNull
53
- } from "./chunk-5AKA6EJB.js";
65
+ } from "./chunk-7S3CSRRV.js";
66
+ import {
67
+ Accordion,
68
+ Button,
69
+ Input,
70
+ Select,
71
+ Spinner
72
+ } from "./chunk-64R3BAO7.js";
54
73
  import {
55
74
  cn
56
75
  } from "./chunk-ZAUUGK2Y.js";
@@ -620,11 +639,1514 @@ function ConfigPanel({
620
639
  );
621
640
  }
622
641
 
642
+ // src/workflow/components/HttpActionPanel/HttpActionPanel.tsx
643
+ import {
644
+ CheckmarkIcon,
645
+ CodeIcon,
646
+ CopyIcon,
647
+ DataViewAltIcon,
648
+ GlobeIcon,
649
+ ListIcon,
650
+ LockedIcon,
651
+ PlayIcon,
652
+ RenewIcon,
653
+ TagIcon
654
+ } from "@octaviaflow/icons";
655
+ import { useCallback as useCallback4, useId, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
656
+
657
+ // src/workflow/components/HttpActionPanel/httpActionTypes.ts
658
+ var HTTP_METHODS = [
659
+ "GET",
660
+ "POST",
661
+ "PUT",
662
+ "PATCH",
663
+ "DELETE",
664
+ "HEAD",
665
+ "OPTIONS"
666
+ ];
667
+ var HTTP_ACTION_DEFAULTS = {
668
+ apiType: "rest",
669
+ method: "GET",
670
+ url: "",
671
+ queryParams: [],
672
+ headers: [],
673
+ bodyType: "json",
674
+ formData: [],
675
+ graphqlQuery: "",
676
+ graphqlVariables: {},
677
+ auth: { type: "none" },
678
+ timeout: 3e4,
679
+ failOnError: true,
680
+ followRedirects: true,
681
+ retry: {
682
+ maxAttempts: 1,
683
+ retryOn: [429, 500, 502, 503, 504],
684
+ initialDelayMs: 1e3,
685
+ backoffFactor: 2,
686
+ maxDelayMs: 3e4
687
+ },
688
+ pagination: { type: "none" },
689
+ extract: {},
690
+ responseType: "json",
691
+ expectedContentTypes: []
692
+ };
693
+ function normalizeKeyValues(raw) {
694
+ if (Array.isArray(raw)) {
695
+ return raw.map((r) => ({
696
+ key: String(r.key ?? ""),
697
+ value: String(r.value ?? ""),
698
+ description: r.description,
699
+ enabled: r.enabled !== false
700
+ }));
701
+ }
702
+ if (raw && typeof raw === "object") {
703
+ return Object.entries(raw).map(([key, value]) => ({
704
+ key,
705
+ value: String(value),
706
+ enabled: true
707
+ }));
708
+ }
709
+ return [];
710
+ }
711
+ function normalizeAuth(raw) {
712
+ const r = raw ?? {};
713
+ const rawType = r.type ?? "none";
714
+ const type = rawType === "oauth2" ? "bearer" : rawType;
715
+ return {
716
+ type: ["none", "basic", "bearer", "apikey"].includes(type) ? type : "none",
717
+ username: r.username ?? "",
718
+ password: r.password ?? "",
719
+ token: r.token ?? r.accessToken ?? "",
720
+ apiKeyName: r.apiKeyName ?? "X-API-Key",
721
+ apiKeyValue: r.apiKeyValue ?? "",
722
+ apiKeyLocation: r.apiKeyLocation === "query" ? "query" : "header"
723
+ };
724
+ }
725
+ function effectiveUrl(baseUrl, url) {
726
+ const base = (baseUrl ?? "").trim();
727
+ if (!base) return url;
728
+ return `${base.replace(/\/$/, "")}/${url.replace(/^\//, "")}`;
729
+ }
730
+ function serializeKeyValues(rows) {
731
+ return rows.filter((r) => r.key || r.value).map((r) => ({
732
+ key: r.key,
733
+ value: r.value,
734
+ enabled: r.enabled !== false,
735
+ ...r.description ? { description: r.description } : {}
736
+ }));
737
+ }
738
+ function validateHttpConfig(config) {
739
+ const errors = [];
740
+ const apiType = config.apiType ?? "rest";
741
+ if (apiType === "rest" && !config.method) errors.push("Method is required");
742
+ if (apiType === "graphql" && !String(config.graphqlQuery ?? "").trim()) {
743
+ errors.push("GraphQL query is required");
744
+ }
745
+ const hasConnection = Boolean(config.connectionId);
746
+ if (!config.url && !hasConnection) {
747
+ errors.push("URL is required");
748
+ } else if (config.url && !hasConnection && !config.baseUrl && !config.url.includes("{{")) {
749
+ try {
750
+ new URL(config.url);
751
+ } catch {
752
+ errors.push("Invalid URL format");
753
+ }
754
+ }
755
+ if (typeof config.timeout === "number" && config.timeout < 1e3) {
756
+ errors.push("Timeout must be at least 1000ms");
757
+ }
758
+ return { valid: errors.length === 0, errors };
759
+ }
760
+ function countGraphqlVariables(query) {
761
+ return new Set(query.match(/\$[A-Za-z_][A-Za-z0-9_]*/g) ?? []).size;
762
+ }
763
+ function shellTokens(input) {
764
+ const tokens = [];
765
+ const flat = input.replace(/\\\r?\n/g, " ");
766
+ const re = /'([^']*)'|"((?:[^"\\]|\\.)*)"|(\S+)/g;
767
+ let m = re.exec(flat);
768
+ while (m !== null) {
769
+ if (m[1] !== void 0) tokens.push(m[1]);
770
+ else if (m[2] !== void 0) tokens.push(m[2].replace(/\\(["\\])/g, "$1"));
771
+ else tokens.push(m[3]);
772
+ m = re.exec(flat);
773
+ }
774
+ return tokens;
775
+ }
776
+ function parseCurl(input) {
777
+ const tokens = shellTokens(input.trim());
778
+ if (!tokens.length || !/^curl$/i.test(tokens[0])) return null;
779
+ let method;
780
+ let url = "";
781
+ const headers = [];
782
+ const formData = [];
783
+ let bodyRaw;
784
+ let basicUser;
785
+ let followRedirects;
786
+ for (let i = 1; i < tokens.length; i++) {
787
+ const t = tokens[i];
788
+ const next = () => tokens[++i] ?? "";
789
+ if (t === "-X" || t === "--request") {
790
+ const m = next().toUpperCase();
791
+ if (HTTP_METHODS.includes(m)) method = m;
792
+ } else if (t === "-H" || t === "--header") {
793
+ const raw = next();
794
+ const idx = raw.indexOf(":");
795
+ if (idx > 0) {
796
+ headers.push({
797
+ key: raw.slice(0, idx).trim(),
798
+ value: raw.slice(idx + 1).trim(),
799
+ enabled: true
800
+ });
801
+ }
802
+ } else if (t === "-d" || t === "--data" || t === "--data-raw" || t === "--data-binary" || t === "--data-urlencode") {
803
+ bodyRaw = next();
804
+ } else if (t === "-F" || t === "--form") {
805
+ const raw = next();
806
+ const idx = raw.indexOf("=");
807
+ if (idx > 0) {
808
+ formData.push({ key: raw.slice(0, idx), value: raw.slice(idx + 1), enabled: true });
809
+ }
810
+ } else if (t === "-u" || t === "--user") {
811
+ basicUser = next();
812
+ } else if (t === "--url") {
813
+ url = next();
814
+ } else if (t === "-L" || t === "--location") {
815
+ followRedirects = true;
816
+ } else if (t.startsWith("-")) {
817
+ if ([
818
+ "-o",
819
+ "--output",
820
+ "-A",
821
+ "--user-agent",
822
+ "-e",
823
+ "--referer",
824
+ "-b",
825
+ "--cookie",
826
+ "--connect-timeout",
827
+ "-m",
828
+ "--max-time"
829
+ ].includes(t)) {
830
+ next();
831
+ }
832
+ } else if (!url) {
833
+ url = t;
834
+ }
835
+ }
836
+ if (!url) return null;
837
+ const patch = { url, apiType: "rest" };
838
+ const qIdx = url.indexOf("?");
839
+ if (qIdx >= 0) {
840
+ const query = url.slice(qIdx + 1);
841
+ patch.url = url.slice(0, qIdx);
842
+ patch.queryParams = query.split("&").filter(Boolean).map((pair) => {
843
+ const eq = pair.indexOf("=");
844
+ const rawKey = eq >= 0 ? pair.slice(0, eq) : pair;
845
+ const rawValue = eq >= 0 ? pair.slice(eq + 1) : "";
846
+ const decode = (s) => {
847
+ try {
848
+ return decodeURIComponent(s.replace(/\+/g, "%20"));
849
+ } catch {
850
+ return s;
851
+ }
852
+ };
853
+ return { key: decode(rawKey), value: decode(rawValue), enabled: true };
854
+ });
855
+ }
856
+ const authHeaderIdx = headers.findIndex((h) => h.key.toLowerCase() === "authorization");
857
+ if (authHeaderIdx >= 0 && /^bearer\s+/i.test(headers[authHeaderIdx].value)) {
858
+ patch.auth = {
859
+ type: "bearer",
860
+ token: headers[authHeaderIdx].value.replace(/^bearer\s+/i, "")
861
+ };
862
+ headers.splice(authHeaderIdx, 1);
863
+ } else if (basicUser) {
864
+ const sep = basicUser.indexOf(":");
865
+ patch.auth = {
866
+ type: "basic",
867
+ username: sep >= 0 ? basicUser.slice(0, sep) : basicUser,
868
+ password: sep >= 0 ? basicUser.slice(sep + 1) : ""
869
+ };
870
+ }
871
+ if (headers.length) patch.headers = headers;
872
+ if (followRedirects !== void 0) patch.followRedirects = followRedirects;
873
+ if (formData.length) {
874
+ patch.bodyType = "form-data";
875
+ patch.formData = formData;
876
+ patch.method = method ?? "POST";
877
+ } else if (bodyRaw !== void 0) {
878
+ try {
879
+ patch.body = JSON.parse(bodyRaw);
880
+ patch.bodyType = "json";
881
+ } catch {
882
+ patch.body = bodyRaw;
883
+ patch.bodyType = "raw";
884
+ }
885
+ patch.method = method ?? "POST";
886
+ } else {
887
+ patch.method = method ?? "GET";
888
+ patch.bodyType = "none";
889
+ }
890
+ return patch;
891
+ }
892
+ function shellQuote(value) {
893
+ return `'${value.replace(/'/g, `'\\''`)}'`;
894
+ }
895
+ function buildCurl(config) {
896
+ const parts = ["curl"];
897
+ const method = config.apiType === "graphql" ? "POST" : config.method ?? "GET";
898
+ if (method !== "GET") parts.push(`-X ${method}`);
899
+ let url = effectiveUrl(config.baseUrl, config.url);
900
+ const params = normalizeKeyValues(config.queryParams).filter((p) => p.enabled !== false && p.key);
901
+ if (params.length) {
902
+ const qs = params.map((p) => `${encodeURIComponent(p.key)}=${encodeURIComponent(p.value)}`).join("&");
903
+ url += (url.includes("?") ? "&" : "?") + qs;
904
+ }
905
+ parts.push(shellQuote(url));
906
+ for (const h of normalizeKeyValues(config.headers).filter((h2) => h2.enabled !== false && h2.key)) {
907
+ parts.push(`-H ${shellQuote(`${h.key}: ${h.value}`)}`);
908
+ }
909
+ const auth = config.auth;
910
+ if (auth?.type === "bearer" && auth.token) {
911
+ parts.push(`-H ${shellQuote(`Authorization: Bearer ${auth.token}`)}`);
912
+ } else if (auth?.type === "basic" && auth.username) {
913
+ parts.push(`-u ${shellQuote(`${auth.username}:${auth.password ?? ""}`)}`);
914
+ } else if (auth?.type === "apikey" && auth.apiKeyName && auth.apiKeyValue) {
915
+ if ((auth.apiKeyLocation ?? "header") === "header") {
916
+ parts.push(`-H ${shellQuote(`${auth.apiKeyName}: ${auth.apiKeyValue}`)}`);
917
+ }
918
+ }
919
+ if (config.apiType === "graphql") {
920
+ const payload = JSON.stringify({
921
+ query: config.graphqlQuery ?? "",
922
+ variables: typeof config.graphqlVariables === "string" ? config.graphqlVariables : config.graphqlVariables ?? {}
923
+ });
924
+ parts.push(`-H ${shellQuote("Content-Type: application/json")}`);
925
+ parts.push(`-d ${shellQuote(payload)}`);
926
+ } else if (config.bodyType === "form-data") {
927
+ for (const f of normalizeKeyValues(config.formData).filter(
928
+ (f2) => f2.enabled !== false && f2.key
929
+ )) {
930
+ parts.push(`-F ${shellQuote(`${f.key}=${f.value}`)}`);
931
+ }
932
+ } else if (config.bodyType && config.bodyType !== "none" && config.body != null) {
933
+ const raw = typeof config.body === "string" ? config.body : JSON.stringify(config.body);
934
+ if (raw) {
935
+ if (config.bodyType === "json") {
936
+ parts.push(`-H ${shellQuote("Content-Type: application/json")}`);
937
+ }
938
+ parts.push(`-d ${shellQuote(raw)}`);
939
+ }
940
+ }
941
+ if (config.followRedirects !== false) parts.push("-L");
942
+ return parts.join(" ");
943
+ }
944
+ function inferJsonSchema(value, depth = 0) {
945
+ if (value === null || value === void 0) return { type: "null" };
946
+ if (Array.isArray(value)) {
947
+ if (!value.length || depth > 6) return { type: "array" };
948
+ return { type: "array", items: inferJsonSchema(value[0], depth + 1) };
949
+ }
950
+ if (typeof value === "object") {
951
+ if (depth > 6) return { type: "object" };
952
+ const properties = {};
953
+ for (const [k, v] of Object.entries(value)) {
954
+ properties[k] = inferJsonSchema(v, depth + 1);
955
+ }
956
+ return { type: "object", properties };
957
+ }
958
+ return { type: typeof value };
959
+ }
960
+ function countSchemaPaths(schema, depth = 0) {
961
+ if (!schema || typeof schema !== "object" || depth > 8) return 0;
962
+ const s = schema;
963
+ let count = 0;
964
+ if (s.type === "object" && s.properties) {
965
+ for (const child of Object.values(s.properties)) {
966
+ count += 1 + countSchemaPaths(child, depth + 1);
967
+ }
968
+ } else if (s.type === "array" && s.items) {
969
+ count += countSchemaPaths(s.items, depth + 1);
970
+ }
971
+ return count;
972
+ }
973
+ function statusTone(status) {
974
+ if (status < 300) return "success";
975
+ if (status < 400) return "info";
976
+ if (status < 500) return "warning";
977
+ return "error";
978
+ }
979
+ function formatBytes(size) {
980
+ return size < 1024 ? `${size} B` : `${(size / 1024).toFixed(1)} KB`;
981
+ }
982
+
983
+ // src/workflow/components/HttpActionPanel/HttpActionPanel.tsx
984
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
985
+ function toPairs(rows) {
986
+ return rows.map((r) => ({
987
+ key: r.key,
988
+ value: r.value,
989
+ enabled: r.enabled !== false,
990
+ description: r.description
991
+ }));
992
+ }
993
+ function textOf(raw) {
994
+ if (typeof raw === "string") return raw;
995
+ if (raw == null) return "";
996
+ try {
997
+ return JSON.stringify(raw, null, 2);
998
+ } catch {
999
+ return "";
1000
+ }
1001
+ }
1002
+ function HttpActionPanel({
1003
+ value,
1004
+ onChange,
1005
+ disabled = false,
1006
+ connections,
1007
+ connectionsLoading = false,
1008
+ onSendPreview,
1009
+ className
1010
+ }) {
1011
+ const uid = useId();
1012
+ const cfgRef = useRef4({
1013
+ ...HTTP_ACTION_DEFAULTS,
1014
+ ...value,
1015
+ queryParams: normalizeKeyValues(value?.queryParams),
1016
+ headers: normalizeKeyValues(value?.headers),
1017
+ formData: normalizeKeyValues(value?.formData),
1018
+ auth: normalizeAuth(value?.auth),
1019
+ retry: {
1020
+ ...HTTP_ACTION_DEFAULTS.retry,
1021
+ ...value?.retry
1022
+ },
1023
+ pagination: {
1024
+ ...HTTP_ACTION_DEFAULTS.pagination,
1025
+ ...value?.pagination
1026
+ }
1027
+ });
1028
+ const [, force] = useState4(0);
1029
+ const emit = useCallback4(
1030
+ (patch) => {
1031
+ cfgRef.current = { ...cfgRef.current, ...patch };
1032
+ force((n) => n + 1);
1033
+ onChange?.(cfgRef.current);
1034
+ },
1035
+ [onChange]
1036
+ );
1037
+ const cfg = cfgRef.current;
1038
+ const connectionId = cfg.connectionId ?? "";
1039
+ const selectedConnection = connections?.find((c) => c.id === connectionId) ?? null;
1040
+ const endpoints = selectedConnection?.endpoints ?? [];
1041
+ const method = cfg.method ?? "GET";
1042
+ const url = cfg.url ?? "";
1043
+ const baseUrl = cfg.baseUrl ?? "";
1044
+ const fullUrl = connectionId ? url : effectiveUrl(baseUrl, url);
1045
+ const queryParams = normalizeKeyValues(cfg.queryParams);
1046
+ const headers = normalizeKeyValues(cfg.headers);
1047
+ const formData = normalizeKeyValues(cfg.formData);
1048
+ const auth = normalizeAuth(cfg.auth);
1049
+ const retry = cfg.retry ?? HTTP_ACTION_DEFAULTS.retry;
1050
+ const pagination = cfg.pagination ?? { type: "none" };
1051
+ const responseType = cfg.responseType ?? "json";
1052
+ const [bodyText, setBodyText] = useState4(() => textOf(cfg.body));
1053
+ const [bodyError, setBodyError] = useState4();
1054
+ const [gqlVarsText, setGqlVarsText] = useState4(() => textOf(cfg.graphqlVariables));
1055
+ const [gqlVarsError, setGqlVarsError] = useState4();
1056
+ const [retryOnText, setRetryOnText] = useState4(() => (retry?.retryOn ?? []).join(", "));
1057
+ const [expectedCtText, setExpectedCtText] = useState4(
1058
+ () => (cfg.expectedContentTypes ?? []).join(", ")
1059
+ );
1060
+ const [urlError, setUrlError] = useState4();
1061
+ const [extractRows, setExtractRows] = useState4(
1062
+ () => Object.entries(cfg.extract ?? {}).map(([key, v]) => ({ key, value: v, enabled: true }))
1063
+ );
1064
+ const [curlOpen, setCurlOpen] = useState4(false);
1065
+ const [curlText, setCurlText] = useState4("");
1066
+ const [curlError, setCurlError] = useState4();
1067
+ const [copiedCurl, setCopiedCurl] = useState4(false);
1068
+ const [copiedResult, setCopiedResult] = useState4(false);
1069
+ const applyCurl = () => {
1070
+ const patch = parseCurl(curlText);
1071
+ if (!patch) {
1072
+ setCurlError(
1073
+ "That doesn't look like a cURL command \u2014 it should start with `curl` and include a URL."
1074
+ );
1075
+ return;
1076
+ }
1077
+ setCurlError(void 0);
1078
+ setCurlText("");
1079
+ setCurlOpen(false);
1080
+ setBodyText(textOf(patch.body));
1081
+ setBodyError(void 0);
1082
+ emit({ ...patch, connectionId: void 0, baseUrl: void 0 });
1083
+ };
1084
+ const copyCurl = async () => {
1085
+ try {
1086
+ await navigator.clipboard?.writeText(buildCurl(cfg));
1087
+ setCopiedCurl(true);
1088
+ setTimeout(() => setCopiedCurl(false), 1600);
1089
+ } catch {
1090
+ }
1091
+ };
1092
+ const copyResult = async () => {
1093
+ if (preview.phase !== "success") return;
1094
+ const r = preview.response;
1095
+ const bundle = {
1096
+ request: {
1097
+ method: cfg.apiType === "graphql" ? "POST" : method,
1098
+ url: connectionId ? `${selectedConnection?.name ?? connectionId} \xB7 ${url}` : fullUrl
1099
+ },
1100
+ response: {
1101
+ status: r.status,
1102
+ statusText: r.statusText,
1103
+ ok: r.ok,
1104
+ durationMs: r.duration,
1105
+ sizeBytes: r.size,
1106
+ headers: r.headers,
1107
+ body: r.body
1108
+ }
1109
+ };
1110
+ try {
1111
+ await navigator.clipboard?.writeText(JSON.stringify(bundle, null, 2));
1112
+ setCopiedResult(true);
1113
+ setTimeout(() => setCopiedResult(false), 1600);
1114
+ } catch {
1115
+ }
1116
+ };
1117
+ const validateUrl = (nextUrl, nextBase, hasConnection) => {
1118
+ if (!nextUrl && !nextBase && !hasConnection) {
1119
+ setUrlError("URL is required");
1120
+ return;
1121
+ }
1122
+ if (!nextUrl || hasConnection || nextBase || nextUrl.includes("{{")) {
1123
+ setUrlError(void 0);
1124
+ return;
1125
+ }
1126
+ try {
1127
+ new URL(nextUrl);
1128
+ setUrlError(void 0);
1129
+ } catch {
1130
+ setUrlError("URL does not look valid");
1131
+ }
1132
+ };
1133
+ const bodyMode = cfg.apiType === "graphql" ? "graphql" : cfg.bodyType ?? "json";
1134
+ const gqlVarCount = useMemo2(
1135
+ () => countGraphqlVariables(cfg.graphqlQuery ?? ""),
1136
+ [cfg.graphqlQuery]
1137
+ );
1138
+ const handleBodyMode = (next) => {
1139
+ if (next === "graphql") {
1140
+ emit(method === "GET" ? { apiType: "graphql", method: "POST" } : { apiType: "graphql" });
1141
+ return;
1142
+ }
1143
+ emit({ apiType: "rest", bodyType: next });
1144
+ };
1145
+ const [preview, setPreview] = useState4({ phase: "idle" });
1146
+ const [schemaInfo, setSchemaInfo] = useState4(
1147
+ null
1148
+ );
1149
+ const lastSchemaKey = useRef4("");
1150
+ const inferAndEmitSchema = useCallback4(
1151
+ (response, forceRefresh = false) => {
1152
+ if (responseType === "binary") return;
1153
+ const snapshot = {
1154
+ status: response.status,
1155
+ statusText: response.statusText,
1156
+ ok: response.ok,
1157
+ headers: response.headers,
1158
+ body: response.body,
1159
+ duration: response.duration,
1160
+ attempts: 1,
1161
+ extracted: {}
1162
+ };
1163
+ const inferred = inferJsonSchema(snapshot);
1164
+ const key = JSON.stringify(inferred);
1165
+ if (!forceRefresh && key === lastSchemaKey.current) return;
1166
+ lastSchemaKey.current = key;
1167
+ emit({ _outputSchema: inferred });
1168
+ const bodySchema = inferred.properties?.body;
1169
+ const topKeys = Object.keys(bodySchema?.properties ?? inferred.properties ?? {});
1170
+ setSchemaInfo({ pathCount: countSchemaPaths(inferred), topKeys });
1171
+ },
1172
+ [emit, responseType]
1173
+ );
1174
+ const sendPreview = async () => {
1175
+ if (!onSendPreview) return;
1176
+ setPreview({ phase: "loading" });
1177
+ try {
1178
+ const response = await onSendPreview({
1179
+ method: cfg.apiType === "graphql" ? "POST" : method,
1180
+ url: connectionId ? url : fullUrl,
1181
+ connectionId: connectionId || void 0,
1182
+ headers,
1183
+ queryParams,
1184
+ bodyType: cfg.bodyType ?? "json",
1185
+ body: bodyText,
1186
+ formData,
1187
+ graphqlQuery: cfg.apiType === "graphql" ? cfg.graphqlQuery ?? "" : void 0,
1188
+ graphqlVariables: cfg.apiType === "graphql" ? gqlVarsText : void 0,
1189
+ auth,
1190
+ timeout: cfg.timeout ?? 3e4
1191
+ });
1192
+ setPreview({ phase: "success", response });
1193
+ inferAndEmitSchema(response);
1194
+ } catch (err) {
1195
+ setPreview({
1196
+ phase: "error",
1197
+ message: err instanceof Error ? err.message : "Request failed"
1198
+ });
1199
+ }
1200
+ };
1201
+ const previewUrlOk = Boolean(fullUrl) && !fullUrl.includes("{{");
1202
+ const canSend = Boolean(onSendPreview) && previewUrlOk && preview.phase !== "loading" && !disabled;
1203
+ const paramCount = queryParams.filter((r) => r.enabled !== false && r.key).length;
1204
+ const headerCount = headers.filter((r) => r.enabled !== false && r.key).length;
1205
+ const extractCount = extractRows.filter((r) => r.key).length;
1206
+ const advancedSummary = [];
1207
+ if ((cfg.timeout ?? 3e4) !== 3e4) advancedSummary.push(`${(cfg.timeout ?? 0) / 1e3}s`);
1208
+ if ((retry?.maxAttempts ?? 1) > 1) advancedSummary.push(`retry \xD7${retry?.maxAttempts}`);
1209
+ if (pagination.type !== "none") advancedSummary.push(pagination.type.replace("_", " "));
1210
+ if (extractCount > 0) advancedSummary.push(`${extractCount} extracted`);
1211
+ const kvTab = (rows, key, desc, keyPlaceholder) => /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__tab", children: [
1212
+ /* @__PURE__ */ jsx2("p", { className: "ods-http-panel__desc", children: desc }),
1213
+ /* @__PURE__ */ jsx2(
1214
+ KeyValueEditor,
1215
+ {
1216
+ pairs: toPairs(rows),
1217
+ onChange: (pairs) => emit({ [key]: pairs }),
1218
+ rowToggle: true,
1219
+ showDescription: true,
1220
+ keyPlaceholder,
1221
+ valuePlaceholder: "value or {{var}}",
1222
+ emptyLabel: "No entries yet \u2014 click Add to begin.",
1223
+ addLabel: "Add",
1224
+ size: "sm",
1225
+ disabled
1226
+ }
1227
+ )
1228
+ ] });
1229
+ const paramsTab = kvTab(
1230
+ queryParams,
1231
+ "queryParams",
1232
+ /* @__PURE__ */ jsxs2(Fragment2, { children: [
1233
+ "Query parameters appended to the URL. Supports ",
1234
+ /* @__PURE__ */ jsx2("code", { children: "{{variable}}" }),
1235
+ " interpolation."
1236
+ ] }),
1237
+ "param name"
1238
+ );
1239
+ const headersTab = kvTab(
1240
+ headers,
1241
+ "headers",
1242
+ /* @__PURE__ */ jsxs2(Fragment2, { children: [
1243
+ "Request headers. Auth headers are injected automatically from the Auth tab. Supports",
1244
+ " ",
1245
+ /* @__PURE__ */ jsx2("code", { children: "{{variable}}" }),
1246
+ " interpolation."
1247
+ ] }),
1248
+ "Header-Name"
1249
+ );
1250
+ const bodyTab = /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__tab", children: [
1251
+ /* @__PURE__ */ jsx2(
1252
+ SegmentedControl,
1253
+ {
1254
+ size: "sm",
1255
+ "aria-label": "Body type",
1256
+ options: [
1257
+ { value: "none", label: "None" },
1258
+ { value: "json", label: "JSON" },
1259
+ { value: "graphql", label: "GraphQL" },
1260
+ { value: "raw", label: "Raw" },
1261
+ { value: "form-data", label: "Form" },
1262
+ { value: "xml", label: "XML" }
1263
+ ],
1264
+ value: bodyMode,
1265
+ onChange: handleBodyMode
1266
+ }
1267
+ ),
1268
+ bodyMode === "none" && /* @__PURE__ */ jsx2("p", { className: "ods-http-panel__empty", children: "No request body will be sent." }),
1269
+ (bodyMode === "json" || bodyMode === "raw" || bodyMode === "xml") && /* @__PURE__ */ jsxs2(Fragment2, { children: [
1270
+ /* @__PURE__ */ jsx2(
1271
+ CodeEditor,
1272
+ {
1273
+ value: bodyText,
1274
+ language: bodyMode === "json" ? "json" : "plain",
1275
+ onChange: (next) => {
1276
+ setBodyText(next);
1277
+ if (bodyMode === "json" && next.trim()) {
1278
+ try {
1279
+ emit({ body: JSON.parse(next) });
1280
+ setBodyError(void 0);
1281
+ } catch {
1282
+ setBodyError("Invalid JSON");
1283
+ emit({ body: next });
1284
+ }
1285
+ } else {
1286
+ setBodyError(void 0);
1287
+ emit({ body: next || void 0 });
1288
+ }
1289
+ },
1290
+ readOnly: disabled,
1291
+ minHeight: 180,
1292
+ ariaLabel: "Request body"
1293
+ }
1294
+ ),
1295
+ bodyError && /* @__PURE__ */ jsxs2("p", { className: "ods-http-panel__error", children: [
1296
+ "\u26A0 ",
1297
+ bodyError
1298
+ ] }),
1299
+ /* @__PURE__ */ jsxs2("p", { className: "ods-http-panel__desc", children: [
1300
+ "Supports ",
1301
+ /* @__PURE__ */ jsx2("code", { children: "{{variable}}" }),
1302
+ " interpolation."
1303
+ ] })
1304
+ ] }),
1305
+ bodyMode === "graphql" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
1306
+ /* @__PURE__ */ jsx2(
1307
+ CodeEditor,
1308
+ {
1309
+ value: cfg.graphqlQuery ?? "",
1310
+ language: "plain",
1311
+ onChange: (next) => emit({ graphqlQuery: next }),
1312
+ readOnly: disabled,
1313
+ minHeight: 160,
1314
+ placeholder: "query ($id: ID!) {\n node(id: $id) { id }\n}",
1315
+ ariaLabel: "GraphQL query"
1316
+ }
1317
+ ),
1318
+ /* @__PURE__ */ jsxs2(
1319
+ Disclosure,
1320
+ {
1321
+ size: "sm",
1322
+ title: "Variables",
1323
+ defaultOpen: Boolean(gqlVarsText.trim()) || gqlVarCount > 0,
1324
+ trailing: gqlVarCount > 0 ? /* @__PURE__ */ jsx2(Badge, { size: "sm", variant: "neutral", children: gqlVarCount }) : void 0,
1325
+ children: [
1326
+ /* @__PURE__ */ jsx2(
1327
+ CodeEditor,
1328
+ {
1329
+ value: gqlVarsText,
1330
+ language: "json",
1331
+ onChange: (next) => {
1332
+ setGqlVarsText(next);
1333
+ if (!next.trim()) {
1334
+ setGqlVarsError(void 0);
1335
+ emit({ graphqlVariables: {} });
1336
+ return;
1337
+ }
1338
+ try {
1339
+ emit({ graphqlVariables: JSON.parse(next) });
1340
+ setGqlVarsError(void 0);
1341
+ } catch {
1342
+ setGqlVarsError("Invalid JSON");
1343
+ }
1344
+ },
1345
+ readOnly: disabled,
1346
+ minHeight: 100,
1347
+ ariaLabel: "GraphQL variables (JSON)"
1348
+ }
1349
+ ),
1350
+ gqlVarsError && /* @__PURE__ */ jsxs2("p", { className: "ods-http-panel__error", children: [
1351
+ "\u26A0 ",
1352
+ gqlVarsError
1353
+ ] })
1354
+ ]
1355
+ }
1356
+ )
1357
+ ] }),
1358
+ bodyMode === "form-data" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
1359
+ /* @__PURE__ */ jsx2("p", { className: "ods-http-panel__desc", children: "Multipart form fields. Content-Type is set automatically with the boundary." }),
1360
+ /* @__PURE__ */ jsx2(
1361
+ KeyValueEditor,
1362
+ {
1363
+ pairs: toPairs(formData),
1364
+ onChange: (pairs) => (
1365
+ // Raw rows — see the params/headers note; serializing here ate
1366
+ // the blank row that Add appends.
1367
+ emit({ formData: pairs, bodyType: "form-data" })
1368
+ ),
1369
+ rowToggle: true,
1370
+ keyPlaceholder: "field name",
1371
+ valuePlaceholder: "value or {{var}}",
1372
+ emptyLabel: "No fields yet \u2014 click Add to begin.",
1373
+ addLabel: "Add",
1374
+ size: "sm",
1375
+ disabled
1376
+ }
1377
+ )
1378
+ ] })
1379
+ ] });
1380
+ const authTab = /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__tab", children: [
1381
+ connectionId ? /* @__PURE__ */ jsxs2(Banner, { variant: "success", appearance: "subtle", size: "sm", children: [
1382
+ "Authentication is inherited from ",
1383
+ /* @__PURE__ */ jsx2("strong", { children: selectedConnection?.name }),
1384
+ " and refreshed automatically. Choose a type below only to override it for this step."
1385
+ ] }) : /* @__PURE__ */ jsx2(Banner, { variant: "info", appearance: "subtle", size: "sm", children: "For OAuth 2.0 APIs that need a login screen, create an API connection and select it as the Source \u2014 the token is obtained once and refreshed automatically. Inline auth here is for non-interactive credentials only." }),
1386
+ /* @__PURE__ */ jsx2(
1387
+ Select,
1388
+ {
1389
+ id: `${uid}-auth-type`,
1390
+ label: connectionId ? "Override authentication" : "Authentication",
1391
+ value: auth.type,
1392
+ onChange: (next) => emit({ auth: { ...auth, type: next } }),
1393
+ disabled,
1394
+ options: [
1395
+ { value: "none", label: connectionId ? "Inherit from connection" : "No auth" },
1396
+ { value: "basic", label: "Basic auth (username + password)" },
1397
+ { value: "bearer", label: "Bearer token" },
1398
+ { value: "apikey", label: "API key" }
1399
+ ]
1400
+ }
1401
+ ),
1402
+ auth.type === "basic" && /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__grid", children: [
1403
+ /* @__PURE__ */ jsx2(
1404
+ Input,
1405
+ {
1406
+ id: `${uid}-auth-user`,
1407
+ label: "Username",
1408
+ value: auth.username ?? "",
1409
+ placeholder: "username or {{var}}",
1410
+ onChange: (e) => emit({ auth: { ...auth, username: e.target.value } }),
1411
+ disabled
1412
+ }
1413
+ ),
1414
+ /* @__PURE__ */ jsx2(
1415
+ PasswordInput,
1416
+ {
1417
+ id: `${uid}-auth-pass`,
1418
+ label: "Password",
1419
+ value: auth.password ?? "",
1420
+ placeholder: "password or {{var}}",
1421
+ onChange: (next) => emit({ auth: { ...auth, password: next } }),
1422
+ disabled
1423
+ }
1424
+ )
1425
+ ] }),
1426
+ auth.type === "bearer" && /* @__PURE__ */ jsx2(
1427
+ PasswordInput,
1428
+ {
1429
+ id: `${uid}-auth-token`,
1430
+ label: "Token",
1431
+ value: auth.token ?? "",
1432
+ placeholder: "your-token or {{step.token}}",
1433
+ onChange: (next) => emit({ auth: { ...auth, token: next } }),
1434
+ disabled
1435
+ }
1436
+ ),
1437
+ auth.type === "apikey" && /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__grid", children: [
1438
+ /* @__PURE__ */ jsx2(
1439
+ Input,
1440
+ {
1441
+ id: `${uid}-auth-keyname`,
1442
+ label: "Key name",
1443
+ value: auth.apiKeyName ?? "",
1444
+ placeholder: "X-API-Key",
1445
+ onChange: (e) => emit({ auth: { ...auth, apiKeyName: e.target.value } }),
1446
+ disabled
1447
+ }
1448
+ ),
1449
+ /* @__PURE__ */ jsx2(
1450
+ PasswordInput,
1451
+ {
1452
+ id: `${uid}-auth-keyval`,
1453
+ label: "Key value",
1454
+ value: auth.apiKeyValue ?? "",
1455
+ placeholder: "your-api-key or {{var}}",
1456
+ onChange: (next) => emit({ auth: { ...auth, apiKeyValue: next } }),
1457
+ disabled
1458
+ }
1459
+ ),
1460
+ /* @__PURE__ */ jsx2(
1461
+ Select,
1462
+ {
1463
+ id: `${uid}-auth-keyloc`,
1464
+ label: "Send in",
1465
+ value: auth.apiKeyLocation ?? "header",
1466
+ onChange: (next) => emit({ auth: { ...auth, apiKeyLocation: next } }),
1467
+ disabled,
1468
+ options: [
1469
+ { value: "header", label: "Request header" },
1470
+ { value: "query", label: "Query parameter" }
1471
+ ]
1472
+ }
1473
+ )
1474
+ ] }),
1475
+ auth.type === "none" && /* @__PURE__ */ jsx2("p", { className: "ods-http-panel__empty", children: connectionId ? "This step uses the connection's authentication." : "No authentication will be added to this request." })
1476
+ ] });
1477
+ const responseTab = /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__tab", children: [
1478
+ /* @__PURE__ */ jsx2(
1479
+ SegmentedControl,
1480
+ {
1481
+ size: "sm",
1482
+ "aria-label": "Response type",
1483
+ options: [
1484
+ { value: "json", label: "JSON" },
1485
+ { value: "text", label: "Text" },
1486
+ { value: "binary", label: "Binary" }
1487
+ ],
1488
+ value: responseType,
1489
+ onChange: (next) => emit({ responseType: next })
1490
+ }
1491
+ ),
1492
+ /* @__PURE__ */ jsxs2("p", { className: "ods-http-panel__desc", children: [
1493
+ responseType === "json" && "Tries to parse the response body as JSON; falls back to raw text on parse failure.",
1494
+ responseType === "text" && "Returns the raw response body as a string. No JSON parsing.",
1495
+ responseType === "binary" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
1496
+ "Returns the response as bytes with ",
1497
+ /* @__PURE__ */ jsx2("code", { children: "fileName" }),
1498
+ ", ",
1499
+ /* @__PURE__ */ jsx2("code", { children: "contentType" }),
1500
+ " and",
1501
+ " ",
1502
+ /* @__PURE__ */ jsx2("code", { children: "size" }),
1503
+ " on the step output \u2014 for downloads feeding file actions. Pagination is not compatible with binary responses."
1504
+ ] })
1505
+ ] }),
1506
+ /* @__PURE__ */ jsx2(
1507
+ Input,
1508
+ {
1509
+ id: `${uid}-expected-ct`,
1510
+ label: "Expected content-types (optional)",
1511
+ value: expectedCtText,
1512
+ placeholder: "application/pdf, application/json",
1513
+ helperText: "Comma-separated. A warning is logged when the response Content-Type matches none of these.",
1514
+ onChange: (e) => {
1515
+ setExpectedCtText(e.target.value);
1516
+ const parts = e.target.value.split(",").map((s) => s.trim()).filter(Boolean);
1517
+ emit({ expectedContentTypes: parts.length ? parts : void 0 });
1518
+ },
1519
+ disabled
1520
+ }
1521
+ ),
1522
+ /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__schema", children: [
1523
+ /* @__PURE__ */ jsx2("span", { className: "ods-http-panel__schema-label", children: "Data stream schema" }),
1524
+ schemaInfo ? /* @__PURE__ */ jsxs2("p", { className: "ods-http-panel__desc", children: [
1525
+ /* @__PURE__ */ jsxs2(Badge, { size: "sm", variant: "success", children: [
1526
+ schemaInfo.pathCount,
1527
+ " paths"
1528
+ ] }),
1529
+ " ",
1530
+ "Inferred from the last test send. Top-level keys:",
1531
+ " ",
1532
+ /* @__PURE__ */ jsx2("code", { children: schemaInfo.topKeys.join(", ") }),
1533
+ ". Downstream binding (Field Mapper, Transform, ForEach) sees this shape immediately; Save persists it."
1534
+ ] }) : /* @__PURE__ */ jsxs2("p", { className: "ods-http-panel__desc", children: [
1535
+ "No schema yet \u2014 hit ",
1536
+ /* @__PURE__ */ jsx2("strong", { children: "Send" }),
1537
+ " in the request bar. On success the response shape is inferred so downstream steps bind against real field names."
1538
+ ] }),
1539
+ /* @__PURE__ */ jsx2(
1540
+ Button,
1541
+ {
1542
+ variant: "ghost",
1543
+ size: "sm",
1544
+ disabled: preview.phase !== "success" || responseType === "binary" || disabled,
1545
+ onClick: () => {
1546
+ if (preview.phase === "success") inferAndEmitSchema(preview.response, true);
1547
+ },
1548
+ children: "Refresh schema from last send"
1549
+ }
1550
+ )
1551
+ ] })
1552
+ ] });
1553
+ const tabItems = [
1554
+ {
1555
+ value: "params",
1556
+ label: paramCount ? `Params \xB7 ${paramCount}` : "Params",
1557
+ icon: /* @__PURE__ */ jsx2(ListIcon, { size: "sm" }),
1558
+ children: paramsTab
1559
+ },
1560
+ {
1561
+ value: "headers",
1562
+ label: headerCount ? `Headers \xB7 ${headerCount}` : "Headers",
1563
+ icon: /* @__PURE__ */ jsx2(TagIcon, { size: "sm" }),
1564
+ children: headersTab
1565
+ },
1566
+ {
1567
+ value: "body",
1568
+ label: bodyMode === "none" ? "Body" : `Body \xB7 ${bodyMode === "form-data" ? "form" : bodyMode}`,
1569
+ icon: /* @__PURE__ */ jsx2(CodeIcon, { size: "sm" }),
1570
+ children: bodyTab
1571
+ },
1572
+ {
1573
+ value: "auth",
1574
+ label: auth.type === "none" ? "Auth" : `Auth \xB7 ${auth.type}`,
1575
+ icon: /* @__PURE__ */ jsx2(LockedIcon, { size: "sm" }),
1576
+ children: authTab
1577
+ },
1578
+ {
1579
+ value: "response",
1580
+ label: responseType === "json" ? "Response" : `Response \xB7 ${responseType}`,
1581
+ icon: /* @__PURE__ */ jsx2(DataViewAltIcon, { size: "sm" }),
1582
+ children: responseTab
1583
+ }
1584
+ ];
1585
+ return /* @__PURE__ */ jsxs2("div", { className: cn("ods-http-panel", className), children: [
1586
+ connections && /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__source", children: [
1587
+ /* @__PURE__ */ jsx2(
1588
+ Select,
1589
+ {
1590
+ id: `${uid}-connection`,
1591
+ label: "Source",
1592
+ placeholder: connectionsLoading ? "Loading\u2026" : "No connection (manual config)",
1593
+ options: connections.map((c) => ({ value: c.id, label: c.name, icon: c.icon })),
1594
+ value: connectionId,
1595
+ onChange: (next) => emit({ connectionId: next || void 0 }),
1596
+ disabled: disabled || connectionsLoading,
1597
+ helperText: connectionId ? `Base URL and auth are inherited from "${selectedConnection?.name}" at runtime.` : "Select a saved API connection to inherit base URL and auth, or configure manually."
1598
+ }
1599
+ ),
1600
+ connectionId && endpoints.length > 0 && /* @__PURE__ */ jsx2(
1601
+ Combobox,
1602
+ {
1603
+ ariaLabel: "Endpoint",
1604
+ placeholder: `Search ${endpoints.length} discovered endpoints\u2026`,
1605
+ value: url,
1606
+ creatable: true,
1607
+ options: endpoints.map((e) => ({
1608
+ value: e.path,
1609
+ label: `${e.method} ${e.path}`,
1610
+ description: e.summary
1611
+ })),
1612
+ onChange: (nextPath) => {
1613
+ const match = endpoints.find((e) => e.path === nextPath);
1614
+ validateUrl(nextPath, baseUrl, true);
1615
+ emit(
1616
+ match && HTTP_METHODS.includes(match.method.toUpperCase()) ? { url: nextPath, method: match.method.toUpperCase() } : { url: nextPath }
1617
+ );
1618
+ }
1619
+ }
1620
+ )
1621
+ ] }),
1622
+ /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__bar", children: [
1623
+ /* @__PURE__ */ jsx2(
1624
+ Select,
1625
+ {
1626
+ id: `${uid}-method`,
1627
+ "aria-label": "HTTP method",
1628
+ className: cn(
1629
+ "ods-http-panel__method",
1630
+ `ods-http-panel__method--${method.toLowerCase()}`
1631
+ ),
1632
+ value: method,
1633
+ onChange: (next) => emit({ method: next }),
1634
+ disabled,
1635
+ options: HTTP_METHODS.map((m) => ({ value: m, label: m }))
1636
+ }
1637
+ ),
1638
+ /* @__PURE__ */ jsx2(
1639
+ Input,
1640
+ {
1641
+ id: `${uid}-url`,
1642
+ "aria-label": connectionId ? "Path" : "URL",
1643
+ "data-fx-droppable": "true",
1644
+ className: "ods-http-panel__url",
1645
+ value: url,
1646
+ placeholder: connectionId ? "/v1/users" : "https://api.example.com/v1/users or {{var}}",
1647
+ error: Boolean(urlError),
1648
+ errorMessage: urlError,
1649
+ onChange: (e) => {
1650
+ validateUrl(e.target.value, baseUrl, Boolean(connectionId));
1651
+ emit({ url: e.target.value });
1652
+ },
1653
+ disabled
1654
+ }
1655
+ ),
1656
+ onSendPreview && /* @__PURE__ */ jsx2(
1657
+ Button,
1658
+ {
1659
+ variant: "primary",
1660
+ size: "md",
1661
+ leftIcon: preview.phase === "loading" ? void 0 : /* @__PURE__ */ jsx2(PlayIcon, { size: "sm" }),
1662
+ onClick: sendPreview,
1663
+ disabled: !canSend,
1664
+ children: preview.phase === "loading" ? "Sending\u2026" : "Send"
1665
+ }
1666
+ )
1667
+ ] }),
1668
+ !connectionId && baseUrl && /* @__PURE__ */ jsxs2("p", { className: "ods-http-panel__effective", children: [
1669
+ /* @__PURE__ */ jsx2("span", { children: "Effective URL:" }),
1670
+ " ",
1671
+ /* @__PURE__ */ jsx2("code", { children: fullUrl || "\u2014" })
1672
+ ] }),
1673
+ fullUrl.includes("{{") && /* @__PURE__ */ jsxs2("p", { className: "ods-http-panel__desc", children: [
1674
+ "\u26A0 URL contains ",
1675
+ /* @__PURE__ */ jsx2("code", { children: "{{variables}}" }),
1676
+ " \u2014 they resolve at run time; testing needs literal values."
1677
+ ] }),
1678
+ /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__tools", children: [
1679
+ /* @__PURE__ */ jsxs2("span", { className: "ods-http-panel__hint", children: [
1680
+ "Use ",
1681
+ /* @__PURE__ */ jsx2("code", { children: "{{stepName.fieldPath}}" }),
1682
+ " to insert data from upstream steps."
1683
+ ] }),
1684
+ /* @__PURE__ */ jsxs2("span", { className: "ods-http-panel__tools-actions", children: [
1685
+ /* @__PURE__ */ jsx2(Button, { variant: "ghost", size: "sm", onClick: () => setCurlOpen((o) => !o), children: "Import cURL" }),
1686
+ /* @__PURE__ */ jsx2(
1687
+ Button,
1688
+ {
1689
+ variant: "ghost",
1690
+ size: "sm",
1691
+ className: cn(copiedCurl && "ods-http-panel__copy-done"),
1692
+ leftIcon: copiedCurl ? /* @__PURE__ */ jsx2(CheckmarkIcon, { size: "sm" }) : /* @__PURE__ */ jsx2(CopyIcon, { size: "sm" }),
1693
+ onClick: copyCurl,
1694
+ children: copiedCurl ? "Copied" : "Copy as cURL"
1695
+ }
1696
+ )
1697
+ ] })
1698
+ ] }),
1699
+ curlOpen && /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__curl", children: [
1700
+ /* @__PURE__ */ jsx2(
1701
+ CodeEditor,
1702
+ {
1703
+ value: curlText,
1704
+ language: "plain",
1705
+ onChange: setCurlText,
1706
+ minHeight: 90,
1707
+ showLineNumbers: false,
1708
+ placeholder: "curl -X POST 'https://api.example.com/v1/users' -H 'Authorization: Bearer \u2026' -d '{\u2026}'",
1709
+ ariaLabel: "cURL command"
1710
+ }
1711
+ ),
1712
+ curlError && /* @__PURE__ */ jsxs2("p", { className: "ods-http-panel__error", children: [
1713
+ "\u26A0 ",
1714
+ curlError
1715
+ ] }),
1716
+ /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__curl-actions", children: [
1717
+ /* @__PURE__ */ jsx2(Button, { variant: "secondary", size: "sm", onClick: () => setCurlOpen(false), children: "Cancel" }),
1718
+ /* @__PURE__ */ jsx2(Button, { variant: "primary", size: "sm", onClick: applyCurl, disabled: !curlText.trim(), children: "Apply to request" })
1719
+ ] })
1720
+ ] }),
1721
+ /* @__PURE__ */ jsx2(Tabs, { items: tabItems, defaultValue: "params", className: "ods-http-panel__tabs" }),
1722
+ /* @__PURE__ */ jsxs2(
1723
+ Disclosure,
1724
+ {
1725
+ size: "sm",
1726
+ icon: /* @__PURE__ */ jsx2(GlobeIcon, { size: "sm" }),
1727
+ title: "Advanced options",
1728
+ description: "Base URL, timeout, retries, pagination, response extraction",
1729
+ trailing: advancedSummary.length ? /* @__PURE__ */ jsx2(Badge, { size: "sm", variant: "info", children: advancedSummary.join(" \xB7 ") }) : void 0,
1730
+ children: [
1731
+ /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__grid", children: [
1732
+ !connectionId && /* @__PURE__ */ jsx2(
1733
+ Input,
1734
+ {
1735
+ id: `${uid}-base-url`,
1736
+ label: "Base URL (optional)",
1737
+ value: baseUrl,
1738
+ placeholder: "https://api.example.com",
1739
+ helperText: "Combined with the request path to form the full URL.",
1740
+ onChange: (e) => {
1741
+ validateUrl(url, e.target.value, Boolean(connectionId));
1742
+ emit({ baseUrl: e.target.value || void 0 });
1743
+ },
1744
+ disabled
1745
+ }
1746
+ ),
1747
+ /* @__PURE__ */ jsx2(
1748
+ NumberInput,
1749
+ {
1750
+ label: "Timeout (ms)",
1751
+ helperText: "Minimum 1000 ms",
1752
+ value: cfg.timeout ?? 3e4,
1753
+ min: 1e3,
1754
+ step: 1e3,
1755
+ onChange: (next) => {
1756
+ if (!Number.isNaN(next) && next >= 1e3) emit({ timeout: next });
1757
+ },
1758
+ disabled
1759
+ }
1760
+ ),
1761
+ /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__switches", children: [
1762
+ /* @__PURE__ */ jsx2(
1763
+ Switch,
1764
+ {
1765
+ id: `${uid}-fail`,
1766
+ label: "Fail on non-2xx",
1767
+ checked: cfg.failOnError !== false,
1768
+ onChange: (next) => emit({ failOnError: next }),
1769
+ disabled,
1770
+ size: "sm"
1771
+ }
1772
+ ),
1773
+ /* @__PURE__ */ jsx2(
1774
+ Switch,
1775
+ {
1776
+ id: `${uid}-redirects`,
1777
+ label: "Follow redirects",
1778
+ checked: cfg.followRedirects !== false,
1779
+ onChange: (next) => emit({ followRedirects: next }),
1780
+ disabled,
1781
+ size: "sm"
1782
+ }
1783
+ )
1784
+ ] })
1785
+ ] }),
1786
+ /* @__PURE__ */ jsx2(
1787
+ Disclosure,
1788
+ {
1789
+ size: "sm",
1790
+ title: "Retry",
1791
+ trailing: (retry?.maxAttempts ?? 1) > 1 ? /* @__PURE__ */ jsxs2(Badge, { size: "sm", variant: "info", children: [
1792
+ retry?.maxAttempts,
1793
+ " attempts"
1794
+ ] }) : void 0,
1795
+ children: /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__grid", children: [
1796
+ /* @__PURE__ */ jsx2(
1797
+ NumberInput,
1798
+ {
1799
+ label: "Max attempts",
1800
+ helperText: "1 = no retry",
1801
+ value: retry?.maxAttempts ?? 1,
1802
+ min: 1,
1803
+ max: 10,
1804
+ onChange: (next) => {
1805
+ if (!Number.isNaN(next) && next >= 1 && retry) {
1806
+ emit({ retry: { ...retry, maxAttempts: next } });
1807
+ }
1808
+ },
1809
+ disabled
1810
+ }
1811
+ ),
1812
+ /* @__PURE__ */ jsx2(
1813
+ Input,
1814
+ {
1815
+ id: `${uid}-retry-on`,
1816
+ label: "Retry on (status codes)",
1817
+ value: retryOnText,
1818
+ placeholder: "429, 500, 502, 503, 504",
1819
+ helperText: "Comma-separated HTTP status codes",
1820
+ onChange: (e) => {
1821
+ setRetryOnText(e.target.value);
1822
+ const codes = e.target.value.split(",").map((s) => Number.parseInt(s.trim(), 10)).filter((n) => !Number.isNaN(n));
1823
+ if (retry) emit({ retry: { ...retry, retryOn: codes } });
1824
+ },
1825
+ disabled
1826
+ }
1827
+ ),
1828
+ /* @__PURE__ */ jsx2(
1829
+ NumberInput,
1830
+ {
1831
+ label: "Initial delay (ms)",
1832
+ value: retry?.initialDelayMs ?? 1e3,
1833
+ min: 100,
1834
+ step: 100,
1835
+ onChange: (next) => {
1836
+ if (!Number.isNaN(next) && retry)
1837
+ emit({ retry: { ...retry, initialDelayMs: next } });
1838
+ },
1839
+ disabled
1840
+ }
1841
+ ),
1842
+ /* @__PURE__ */ jsx2(
1843
+ NumberInput,
1844
+ {
1845
+ label: "Backoff factor",
1846
+ helperText: "Delay multiplies by this each retry",
1847
+ value: retry?.backoffFactor ?? 2,
1848
+ min: 1,
1849
+ step: 0.5,
1850
+ onChange: (next) => {
1851
+ if (!Number.isNaN(next) && retry)
1852
+ emit({ retry: { ...retry, backoffFactor: next } });
1853
+ },
1854
+ disabled
1855
+ }
1856
+ ),
1857
+ /* @__PURE__ */ jsx2(
1858
+ NumberInput,
1859
+ {
1860
+ label: "Max delay (ms)",
1861
+ value: retry?.maxDelayMs ?? 3e4,
1862
+ min: 1e3,
1863
+ step: 1e3,
1864
+ onChange: (next) => {
1865
+ if (!Number.isNaN(next) && retry) emit({ retry: { ...retry, maxDelayMs: next } });
1866
+ },
1867
+ disabled
1868
+ }
1869
+ )
1870
+ ] })
1871
+ }
1872
+ ),
1873
+ /* @__PURE__ */ jsxs2(
1874
+ Disclosure,
1875
+ {
1876
+ size: "sm",
1877
+ title: "Pagination",
1878
+ trailing: pagination.type !== "none" ? /* @__PURE__ */ jsx2(Badge, { size: "sm", variant: "success", children: pagination.type.replace("_", " ") }) : void 0,
1879
+ children: [
1880
+ /* @__PURE__ */ jsx2(
1881
+ Select,
1882
+ {
1883
+ id: `${uid}-pag-type`,
1884
+ label: "Strategy",
1885
+ value: pagination.type,
1886
+ onChange: (next) => emit({
1887
+ pagination: { ...pagination, type: next }
1888
+ }),
1889
+ disabled,
1890
+ options: [
1891
+ { value: "none", label: "None (single request)" },
1892
+ { value: "offset", label: "Offset / page number" },
1893
+ { value: "cursor", label: "Cursor-based" },
1894
+ { value: "link_header", label: 'Link header (rel="next")' },
1895
+ { value: "next_url", label: "Next URL in response body" }
1896
+ ]
1897
+ }
1898
+ ),
1899
+ pagination.type !== "none" && /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__grid", children: [
1900
+ /* @__PURE__ */ jsx2(
1901
+ NumberInput,
1902
+ {
1903
+ label: "Max pages",
1904
+ helperText: "Safety cap against infinite loops",
1905
+ value: pagination.maxPages ?? 20,
1906
+ min: 1,
1907
+ onChange: (next) => {
1908
+ if (!Number.isNaN(next)) emit({ pagination: { ...pagination, maxPages: next } });
1909
+ },
1910
+ disabled
1911
+ }
1912
+ ),
1913
+ /* @__PURE__ */ jsx2(
1914
+ Input,
1915
+ {
1916
+ id: `${uid}-pag-merge`,
1917
+ label: "Merge key (dot path)",
1918
+ value: pagination.mergeKey ?? "",
1919
+ placeholder: "data.items",
1920
+ helperText: "Array to merge across pages",
1921
+ onChange: (e) => emit({ pagination: { ...pagination, mergeKey: e.target.value } }),
1922
+ disabled
1923
+ }
1924
+ ),
1925
+ (pagination.type === "offset" || pagination.type === "cursor") && /* @__PURE__ */ jsxs2(Fragment2, { children: [
1926
+ /* @__PURE__ */ jsx2(
1927
+ Input,
1928
+ {
1929
+ id: `${uid}-pag-limitp`,
1930
+ label: "Limit param",
1931
+ value: pagination.limitParam ?? "limit",
1932
+ onChange: (e) => emit({ pagination: { ...pagination, limitParam: e.target.value } }),
1933
+ disabled
1934
+ }
1935
+ ),
1936
+ /* @__PURE__ */ jsx2(
1937
+ NumberInput,
1938
+ {
1939
+ label: "Page size",
1940
+ value: pagination.limitValue ?? 100,
1941
+ min: 1,
1942
+ onChange: (next) => {
1943
+ if (!Number.isNaN(next)) {
1944
+ emit({ pagination: { ...pagination, limitValue: next } });
1945
+ }
1946
+ },
1947
+ disabled
1948
+ }
1949
+ )
1950
+ ] }),
1951
+ pagination.type === "offset" && /* @__PURE__ */ jsx2(
1952
+ Input,
1953
+ {
1954
+ id: `${uid}-pag-offset`,
1955
+ label: "Offset param",
1956
+ value: pagination.offsetParam ?? "offset",
1957
+ onChange: (e) => emit({ pagination: { ...pagination, offsetParam: e.target.value } }),
1958
+ disabled
1959
+ }
1960
+ ),
1961
+ pagination.type === "cursor" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
1962
+ /* @__PURE__ */ jsx2(
1963
+ Input,
1964
+ {
1965
+ id: `${uid}-pag-cres`,
1966
+ label: "Cursor in response (dot path)",
1967
+ value: pagination.cursorResponsePath ?? "",
1968
+ placeholder: "meta.next_cursor",
1969
+ onChange: (e) => emit({ pagination: { ...pagination, cursorResponsePath: e.target.value } }),
1970
+ disabled
1971
+ }
1972
+ ),
1973
+ /* @__PURE__ */ jsx2(
1974
+ Input,
1975
+ {
1976
+ id: `${uid}-pag-creq`,
1977
+ label: "Cursor request param",
1978
+ value: pagination.cursorRequestParam ?? "cursor",
1979
+ onChange: (e) => emit({ pagination: { ...pagination, cursorRequestParam: e.target.value } }),
1980
+ disabled
1981
+ }
1982
+ )
1983
+ ] }),
1984
+ pagination.type === "next_url" && /* @__PURE__ */ jsx2(
1985
+ Input,
1986
+ {
1987
+ id: `${uid}-pag-next`,
1988
+ label: "Next URL in response (dot path)",
1989
+ value: pagination.nextUrlResponsePath ?? "",
1990
+ placeholder: "links.next",
1991
+ onChange: (e) => emit({ pagination: { ...pagination, nextUrlResponsePath: e.target.value } }),
1992
+ disabled
1993
+ }
1994
+ )
1995
+ ] })
1996
+ ]
1997
+ }
1998
+ ),
1999
+ /* @__PURE__ */ jsxs2(
2000
+ Disclosure,
2001
+ {
2002
+ size: "sm",
2003
+ title: "Response field extraction",
2004
+ trailing: extractCount > 0 ? /* @__PURE__ */ jsxs2(Badge, { size: "sm", variant: "info", children: [
2005
+ extractCount,
2006
+ " field",
2007
+ extractCount === 1 ? "" : "s"
2008
+ ] }) : void 0,
2009
+ children: [
2010
+ /* @__PURE__ */ jsxs2("p", { className: "ods-http-panel__desc", children: [
2011
+ "Extract fields from the response with dot paths \u2014 available downstream as",
2012
+ " ",
2013
+ /* @__PURE__ */ jsx2("code", { children: "{{extracted.keyName}}" }),
2014
+ "."
2015
+ ] }),
2016
+ /* @__PURE__ */ jsx2(
2017
+ KeyValueEditor,
2018
+ {
2019
+ pairs: extractRows.map((r) => ({ key: r.key, value: r.value })),
2020
+ onChange: (pairs) => {
2021
+ const rows = pairs.map((p) => ({ key: p.key, value: p.value, enabled: true }));
2022
+ setExtractRows(rows);
2023
+ const extract = {};
2024
+ for (const r of rows) if (r.key && r.value) extract[r.key] = r.value;
2025
+ emit({ extract: Object.keys(extract).length ? extract : void 0 });
2026
+ },
2027
+ keyPlaceholder: "outputKey",
2028
+ valuePlaceholder: "data.user.id",
2029
+ emptyLabel: "No extractions yet \u2014 click Add to begin.",
2030
+ addLabel: "Add",
2031
+ size: "sm",
2032
+ disabled
2033
+ }
2034
+ )
2035
+ ]
2036
+ }
2037
+ )
2038
+ ]
2039
+ }
2040
+ ),
2041
+ preview.phase !== "idle" && /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__console", children: [
2042
+ /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__console-head", children: [
2043
+ /* @__PURE__ */ jsx2(
2044
+ "code",
2045
+ {
2046
+ className: cn(
2047
+ "ods-http-panel__console-method",
2048
+ `ods-http-panel__method--${method.toLowerCase()}`
2049
+ ),
2050
+ children: cfg.apiType === "graphql" ? "POST" : method
2051
+ }
2052
+ ),
2053
+ /* @__PURE__ */ jsx2("code", { className: "ods-http-panel__console-url", children: connectionId ? `${selectedConnection?.name ?? connectionId} \xB7 ${url || "\u2014"}` : fullUrl || "\u2014" }),
2054
+ preview.phase === "success" && /* @__PURE__ */ jsx2(
2055
+ Button,
2056
+ {
2057
+ variant: "ghost",
2058
+ size: "sm",
2059
+ className: cn(copiedResult && "ods-http-panel__copy-done"),
2060
+ leftIcon: copiedResult ? /* @__PURE__ */ jsx2(CheckmarkIcon, { size: "sm" }) : /* @__PURE__ */ jsx2(CopyIcon, { size: "sm" }),
2061
+ onClick: copyResult,
2062
+ children: copiedResult ? "Copied" : "Copy result"
2063
+ }
2064
+ ),
2065
+ /* @__PURE__ */ jsx2(
2066
+ Button,
2067
+ {
2068
+ variant: "ghost",
2069
+ size: "sm",
2070
+ leftIcon: /* @__PURE__ */ jsx2(RenewIcon, { size: "sm" }),
2071
+ onClick: () => {
2072
+ setPreview({ phase: "idle" });
2073
+ },
2074
+ disabled: preview.phase === "loading",
2075
+ children: "Clear"
2076
+ }
2077
+ )
2078
+ ] }),
2079
+ preview.phase === "loading" && /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__console-loading", children: [
2080
+ /* @__PURE__ */ jsx2(Spinner, { size: "sm" }),
2081
+ /* @__PURE__ */ jsx2("span", { children: "Sending request\u2026" })
2082
+ ] }),
2083
+ preview.phase === "error" && /* @__PURE__ */ jsxs2(Banner, { variant: "error", appearance: "subtle", size: "sm", children: [
2084
+ /* @__PURE__ */ jsx2("strong", { children: "Request failed." }),
2085
+ " ",
2086
+ preview.message
2087
+ ] }),
2088
+ preview.phase === "success" && /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__console-result", children: [
2089
+ /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__console-status", children: [
2090
+ /* @__PURE__ */ jsxs2(Badge, { size: "sm", variant: statusTone(preview.response.status), children: [
2091
+ preview.response.status,
2092
+ " ",
2093
+ preview.response.statusText
2094
+ ] }),
2095
+ /* @__PURE__ */ jsxs2("span", { className: "ods-http-panel__meta", children: [
2096
+ preview.response.duration,
2097
+ "ms"
2098
+ ] }),
2099
+ /* @__PURE__ */ jsx2("span", { className: "ods-http-panel__meta", children: formatBytes(preview.response.size) })
2100
+ ] }),
2101
+ /* @__PURE__ */ jsx2(
2102
+ Accordion,
2103
+ {
2104
+ size: "sm",
2105
+ mode: "multiple",
2106
+ defaultValue: ["res-body"],
2107
+ items: [
2108
+ {
2109
+ id: "res-headers",
2110
+ label: "Response headers",
2111
+ trailing: /* @__PURE__ */ jsx2(Badge, { size: "sm", variant: "neutral", children: Object.keys(preview.response.headers).length }),
2112
+ content: /* @__PURE__ */ jsx2("div", { className: "ods-http-panel__res-headers", children: Object.entries(preview.response.headers).map(([k, v]) => /* @__PURE__ */ jsxs2("div", { className: "ods-http-panel__res-header", children: [
2113
+ /* @__PURE__ */ jsx2("span", { className: "ods-http-panel__res-header-key", children: k }),
2114
+ /* @__PURE__ */ jsx2("span", { className: "ods-http-panel__res-header-val", children: v })
2115
+ ] }, k)) })
2116
+ },
2117
+ {
2118
+ id: "res-body",
2119
+ label: "Response body",
2120
+ trailing: !preview.response.ok ? /* @__PURE__ */ jsx2(Badge, { size: "sm", variant: "error", children: "Error" }) : null,
2121
+ content: (
2122
+ // Size guard: the tree view renders recursively (no
2123
+ // virtualization) — very large bodies fall back to text.
2124
+ preview.response.body !== null && typeof preview.response.body === "object" && preview.response.size <= 15e5 ? /* @__PURE__ */ jsx2(
2125
+ JsonViewer,
2126
+ {
2127
+ data: preview.response.body,
2128
+ mode: "view",
2129
+ maxHeight: 320,
2130
+ copyable: true
2131
+ }
2132
+ ) : /* @__PURE__ */ jsx2("pre", { className: "ods-http-panel__res-body", children: typeof preview.response.body === "object" ? JSON.stringify(preview.response.body, null, 2) : String(
2133
+ preview.response.bodyRaw ?? preview.response.body ?? "(empty body)"
2134
+ ) })
2135
+ )
2136
+ }
2137
+ ]
2138
+ }
2139
+ )
2140
+ ] })
2141
+ ] })
2142
+ ] });
2143
+ }
2144
+
623
2145
  // src/workflow/components/FxPanel/FxPanel.tsx
624
2146
  import {
625
- useMemo as useMemo2,
626
- useRef as useRef4,
627
- useState as useState4
2147
+ useMemo as useMemo3,
2148
+ useRef as useRef5,
2149
+ useState as useState5
628
2150
  } from "react";
629
2151
  import {
630
2152
  ChevronDownIcon,
@@ -637,7 +2159,7 @@ import {
637
2159
  SearchIcon,
638
2160
  ValueVariableIcon
639
2161
  } from "@octaviaflow/icons";
640
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
2162
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
641
2163
  var KIND_ICON = {
642
2164
  function: FunctionMathIcon,
643
2165
  variable: ValueVariableIcon
@@ -696,18 +2218,18 @@ function FxPanel({
696
2218
  className,
697
2219
  style
698
2220
  }) {
699
- const [internalSearch, setInternalSearch] = useState4(defaultSearch);
2221
+ const [internalSearch, setInternalSearch] = useState5(defaultSearch);
700
2222
  const search = controlledSearch ?? internalSearch;
701
2223
  const query = search.trim().toLowerCase();
702
2224
  const setSearch = (next) => {
703
2225
  if (controlledSearch === void 0) setInternalSearch(next);
704
2226
  onSearchChange?.(next);
705
2227
  };
706
- const visibleCategories = useMemo2(
2228
+ const visibleCategories = useMemo3(
707
2229
  () => categories.filter((c) => c.items.length > 0),
708
2230
  [categories]
709
2231
  );
710
- const [internalCat, setInternalCat] = useState4(
2232
+ const [internalCat, setInternalCat] = useState5(
711
2233
  defaultExpandedCategory !== void 0 ? defaultExpandedCategory : visibleCategories[0]?.id ?? null
712
2234
  );
713
2235
  const openCategoryId = controlledExpanded ?? internalCat;
@@ -715,7 +2237,7 @@ function FxPanel({
715
2237
  if (controlledExpanded === void 0) setInternalCat(id);
716
2238
  onExpandedCategoryChange?.(id);
717
2239
  };
718
- const [expandedItems, setExpandedItems] = useState4(() => {
2240
+ const [expandedItems, setExpandedItems] = useState5(() => {
719
2241
  const ids = /* @__PURE__ */ new Set();
720
2242
  for (const cat of categories) {
721
2243
  for (const item of cat.items) {
@@ -744,9 +2266,9 @@ function FxPanel({
744
2266
  return next;
745
2267
  });
746
2268
  };
747
- const [draggingId, setDraggingId] = useState4(null);
748
- const [focusedId, setFocusedId] = useState4(null);
749
- const hits = useMemo2(() => {
2269
+ const [draggingId, setDraggingId] = useState5(null);
2270
+ const [focusedId, setFocusedId] = useState5(null);
2271
+ const hits = useMemo3(() => {
750
2272
  if (!query) return null;
751
2273
  const all = [];
752
2274
  for (const cat of visibleCategories) {
@@ -770,7 +2292,7 @@ function FxPanel({
770
2292
  e.dataTransfer.effectAllowed = "copy";
771
2293
  }
772
2294
  };
773
- const listRef = useRef4(null);
2295
+ const listRef = useRef5(null);
774
2296
  const focusRow = (id) => {
775
2297
  setFocusedId(id);
776
2298
  requestAnimationFrame(() => {
@@ -828,7 +2350,7 @@ function FxPanel({
828
2350
  break;
829
2351
  }
830
2352
  };
831
- const searchRows = useMemo2(
2353
+ const searchRows = useMemo3(
832
2354
  () => hits ? hits.map(({ hit }) => ({
833
2355
  item: hit.item,
834
2356
  depth: 0,
@@ -842,7 +2364,7 @@ function FxPanel({
842
2364
  const mono = category.kind === "function";
843
2365
  const draggable = !!item.insertValue;
844
2366
  const isFocused = focusedId === item.id;
845
- return /* @__PURE__ */ jsxs2(
2367
+ return /* @__PURE__ */ jsxs3(
846
2368
  "div",
847
2369
  {
848
2370
  "data-fx-row": item.id,
@@ -867,12 +2389,12 @@ function FxPanel({
867
2389
  },
868
2390
  title: item.insertValue,
869
2391
  children: [
870
- Array.from({ length: depth }, (_, i) => /* @__PURE__ */ jsx2("span", { className: "ods-flow-fx-panel__indent", "aria-hidden": "true" }, i)),
871
- hasChildren ? /* @__PURE__ */ jsx2("span", { className: "ods-flow-fx-panel__twisty", "aria-hidden": "true", children: expanded ? /* @__PURE__ */ jsx2(ChevronDownIcon, { size: "sm" }) : /* @__PURE__ */ jsx2(ChevronRightIcon, { size: "sm" }) }) : /* @__PURE__ */ jsx2("span", { className: "ods-flow-fx-panel__grip", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(DraggableIcon, { size: "sm" }) }),
872
- /* @__PURE__ */ jsxs2("span", { className: "ods-flow-fx-panel__row-main", children: [
873
- /* @__PURE__ */ jsxs2("span", { className: "ods-flow-fx-panel__row-line", children: [
874
- mono ? /* @__PURE__ */ jsx2("code", { className: "ods-flow-fx-panel__row-label ods-flow-fx-panel__row-label--mono", children: item.label }) : /* @__PURE__ */ jsx2("span", { className: "ods-flow-fx-panel__row-label", children: item.label }),
875
- item.valueType && /* @__PURE__ */ jsx2(
2392
+ Array.from({ length: depth }, (_, i) => /* @__PURE__ */ jsx3("span", { className: "ods-flow-fx-panel__indent", "aria-hidden": "true" }, i)),
2393
+ hasChildren ? /* @__PURE__ */ jsx3("span", { className: "ods-flow-fx-panel__twisty", "aria-hidden": "true", children: expanded ? /* @__PURE__ */ jsx3(ChevronDownIcon, { size: "sm" }) : /* @__PURE__ */ jsx3(ChevronRightIcon, { size: "sm" }) }) : /* @__PURE__ */ jsx3("span", { className: "ods-flow-fx-panel__grip", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(DraggableIcon, { size: "sm" }) }),
2394
+ /* @__PURE__ */ jsxs3("span", { className: "ods-flow-fx-panel__row-main", children: [
2395
+ /* @__PURE__ */ jsxs3("span", { className: "ods-flow-fx-panel__row-line", children: [
2396
+ mono ? /* @__PURE__ */ jsx3("code", { className: "ods-flow-fx-panel__row-label ods-flow-fx-panel__row-label--mono", children: item.label }) : /* @__PURE__ */ jsx3("span", { className: "ods-flow-fx-panel__row-label", children: item.label }),
2397
+ item.valueType && /* @__PURE__ */ jsx3(
876
2398
  "span",
877
2399
  {
878
2400
  className: cn(
@@ -883,8 +2405,8 @@ function FxPanel({
883
2405
  }
884
2406
  )
885
2407
  ] }),
886
- (item.description || crumb) && /* @__PURE__ */ jsxs2("span", { className: "ods-flow-fx-panel__row-sub", children: [
887
- crumb && /* @__PURE__ */ jsx2("span", { className: "ods-flow-fx-panel__crumb", children: crumb }),
2408
+ (item.description || crumb) && /* @__PURE__ */ jsxs3("span", { className: "ods-flow-fx-panel__row-sub", children: [
2409
+ crumb && /* @__PURE__ */ jsx3("span", { className: "ods-flow-fx-panel__crumb", children: crumb }),
888
2410
  item.description
889
2411
  ] })
890
2412
  ] })
@@ -893,29 +2415,29 @@ function FxPanel({
893
2415
  item.id
894
2416
  );
895
2417
  };
896
- return /* @__PURE__ */ jsxs2(
2418
+ return /* @__PURE__ */ jsxs3(
897
2419
  "aside",
898
2420
  {
899
2421
  className: cn("ods-flow-fx-panel", className),
900
2422
  style: { width, ...style },
901
2423
  "aria-label": typeof title === "string" ? title : "Data References",
902
2424
  children: [
903
- /* @__PURE__ */ jsxs2("header", { className: "ods-flow-fx-panel__header", children: [
904
- /* @__PURE__ */ jsx2("h3", { className: "ods-flow-fx-panel__title", children: title }),
905
- onClose && /* @__PURE__ */ jsx2(
2425
+ /* @__PURE__ */ jsxs3("header", { className: "ods-flow-fx-panel__header", children: [
2426
+ /* @__PURE__ */ jsx3("h3", { className: "ods-flow-fx-panel__title", children: title }),
2427
+ onClose && /* @__PURE__ */ jsx3(
906
2428
  "button",
907
2429
  {
908
2430
  type: "button",
909
2431
  className: "ods-flow-fx-panel__close",
910
2432
  onClick: onClose,
911
2433
  "aria-label": "Close data references",
912
- children: /* @__PURE__ */ jsx2(CloseIcon, { size: "sm" })
2434
+ children: /* @__PURE__ */ jsx3(CloseIcon, { size: "sm" })
913
2435
  }
914
2436
  )
915
2437
  ] }),
916
- /* @__PURE__ */ jsxs2("div", { className: "ods-flow-fx-panel__search", children: [
917
- /* @__PURE__ */ jsx2("span", { className: "ods-flow-fx-panel__search-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(SearchIcon, { size: "sm" }) }),
918
- /* @__PURE__ */ jsx2(
2438
+ /* @__PURE__ */ jsxs3("div", { className: "ods-flow-fx-panel__search", children: [
2439
+ /* @__PURE__ */ jsx3("span", { className: "ods-flow-fx-panel__search-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(SearchIcon, { size: "sm" }) }),
2440
+ /* @__PURE__ */ jsx3(
919
2441
  "input",
920
2442
  {
921
2443
  type: "text",
@@ -926,21 +2448,21 @@ function FxPanel({
926
2448
  onChange: (e) => setSearch(e.target.value)
927
2449
  }
928
2450
  ),
929
- search && /* @__PURE__ */ jsx2(
2451
+ search && /* @__PURE__ */ jsx3(
930
2452
  "button",
931
2453
  {
932
2454
  type: "button",
933
2455
  className: "ods-flow-fx-panel__search-clear",
934
2456
  onClick: () => setSearch(""),
935
2457
  "aria-label": "Clear search",
936
- children: /* @__PURE__ */ jsx2(CloseIcon, { size: "sm" })
2458
+ children: /* @__PURE__ */ jsx3(CloseIcon, { size: "sm" })
937
2459
  }
938
2460
  )
939
2461
  ] }),
940
- hint && !query && /* @__PURE__ */ jsx2("p", { className: "ods-flow-fx-panel__hint", children: hint }),
941
- /* @__PURE__ */ jsxs2("div", { className: "ods-flow-fx-panel__list", ref: listRef, role: "tree", children: [
942
- query && hits && (hits.length > 0 ? /* @__PURE__ */ jsxs2("div", { className: "ods-flow-fx-panel__results", children: [
943
- /* @__PURE__ */ jsxs2("div", { className: "ods-flow-fx-panel__results-count", children: [
2462
+ hint && !query && /* @__PURE__ */ jsx3("p", { className: "ods-flow-fx-panel__hint", children: hint }),
2463
+ /* @__PURE__ */ jsxs3("div", { className: "ods-flow-fx-panel__list", ref: listRef, role: "tree", children: [
2464
+ query && hits && (hits.length > 0 ? /* @__PURE__ */ jsxs3("div", { className: "ods-flow-fx-panel__results", children: [
2465
+ /* @__PURE__ */ jsxs3("div", { className: "ods-flow-fx-panel__results-count", children: [
944
2466
  hits.length,
945
2467
  " ",
946
2468
  hits.length === 1 ? "match" : "matches"
@@ -953,7 +2475,7 @@ function FxPanel({
953
2475
  hit.ancestors.length ? hit.ancestors.join(" / ") : category.label
954
2476
  )
955
2477
  )
956
- ] }) : /* @__PURE__ */ jsx2("div", { className: "ods-flow-fx-panel__empty", children: emptyLabel })),
2478
+ ] }) : /* @__PURE__ */ jsx3("div", { className: "ods-flow-fx-panel__empty", children: emptyLabel })),
957
2479
  !query && visibleCategories.map((cat) => {
958
2480
  const isOpen = openCategoryId === cat.id;
959
2481
  const kind = cat.kind ?? "function";
@@ -964,8 +2486,8 @@ function FxPanel({
964
2486
  const rows = [];
965
2487
  if (isOpen) flattenTree(cat.items, 0, expandedItems, rows);
966
2488
  const allExpanded = hasTree && [...branchIds].every((id) => expandedItems.has(id));
967
- return /* @__PURE__ */ jsxs2("div", { className: "ods-flow-fx-panel__category", children: [
968
- /* @__PURE__ */ jsxs2(
2489
+ return /* @__PURE__ */ jsxs3("div", { className: "ods-flow-fx-panel__category", children: [
2490
+ /* @__PURE__ */ jsxs3(
969
2491
  "div",
970
2492
  {
971
2493
  className: cn(
@@ -973,7 +2495,7 @@ function FxPanel({
973
2495
  isOpen && "ods-flow-fx-panel__cat-header--open"
974
2496
  ),
975
2497
  children: [
976
- /* @__PURE__ */ jsxs2(
2498
+ /* @__PURE__ */ jsxs3(
977
2499
  "button",
978
2500
  {
979
2501
  type: "button",
@@ -981,7 +2503,7 @@ function FxPanel({
981
2503
  "aria-expanded": isOpen,
982
2504
  onClick: () => setOpenCategory(isOpen ? null : cat.id),
983
2505
  children: [
984
- /* @__PURE__ */ jsx2(
2506
+ /* @__PURE__ */ jsx3(
985
2507
  ChevronRightIcon,
986
2508
  {
987
2509
  size: "sm",
@@ -991,7 +2513,7 @@ function FxPanel({
991
2513
  )
992
2514
  }
993
2515
  ),
994
- /* @__PURE__ */ jsxs2(
2516
+ /* @__PURE__ */ jsxs3(
995
2517
  "span",
996
2518
  {
997
2519
  className: cn(
@@ -999,7 +2521,7 @@ function FxPanel({
999
2521
  `ods-flow-fx-panel__badge--${kind}`
1000
2522
  ),
1001
2523
  children: [
1002
- /* @__PURE__ */ jsx2(
2524
+ /* @__PURE__ */ jsx3(
1003
2525
  KindIcon,
1004
2526
  {
1005
2527
  size: "sm",
@@ -1010,11 +2532,11 @@ function FxPanel({
1010
2532
  ]
1011
2533
  }
1012
2534
  ),
1013
- /* @__PURE__ */ jsx2("span", { className: "ods-flow-fx-panel__count", children: countLeaves(cat.items) })
2535
+ /* @__PURE__ */ jsx3("span", { className: "ods-flow-fx-panel__count", children: countLeaves(cat.items) })
1014
2536
  ]
1015
2537
  }
1016
2538
  ),
1017
- isOpen && hasTree && /* @__PURE__ */ jsx2(
2539
+ isOpen && hasTree && /* @__PURE__ */ jsx3(
1018
2540
  "button",
1019
2541
  {
1020
2542
  type: "button",
@@ -1022,13 +2544,13 @@ function FxPanel({
1022
2544
  "aria-label": allExpanded ? "Collapse all" : "Expand all",
1023
2545
  title: allExpanded ? "Collapse all" : "Expand all",
1024
2546
  onClick: () => setCategoryExpansion(cat, !allExpanded),
1025
- children: allExpanded ? /* @__PURE__ */ jsx2(CollapseAllIcon, { size: "sm" }) : /* @__PURE__ */ jsx2(ExpandAllIcon, { size: "sm" })
2547
+ children: allExpanded ? /* @__PURE__ */ jsx3(CollapseAllIcon, { size: "sm" }) : /* @__PURE__ */ jsx3(ExpandAllIcon, { size: "sm" })
1026
2548
  }
1027
2549
  )
1028
2550
  ]
1029
2551
  }
1030
2552
  ),
1031
- isOpen && /* @__PURE__ */ jsx2(
2553
+ isOpen && /* @__PURE__ */ jsx3(
1032
2554
  "div",
1033
2555
  {
1034
2556
  className: "ods-flow-fx-panel__rows",
@@ -1047,7 +2569,7 @@ function FxPanel({
1047
2569
 
1048
2570
  // src/workflow/components/FxPanel/DataRefButton.tsx
1049
2571
  import { DataReferenceIcon } from "@octaviaflow/icons";
1050
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
2572
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1051
2573
  function DataRefButton({
1052
2574
  active = false,
1053
2575
  label = "Data ref",
@@ -1055,7 +2577,7 @@ function DataRefButton({
1055
2577
  type = "button",
1056
2578
  ...rest
1057
2579
  }) {
1058
- return /* @__PURE__ */ jsxs3(
2580
+ return /* @__PURE__ */ jsxs4(
1059
2581
  "button",
1060
2582
  {
1061
2583
  ...rest,
@@ -1069,21 +2591,21 @@ function DataRefButton({
1069
2591
  "aria-pressed": active,
1070
2592
  title: active ? "Hide data references" : "Show data references",
1071
2593
  children: [
1072
- /* @__PURE__ */ jsx3(
2594
+ /* @__PURE__ */ jsx4(
1073
2595
  DataReferenceIcon,
1074
2596
  {
1075
2597
  size: "sm",
1076
2598
  className: "ods-flow-dataref-button__icon"
1077
2599
  }
1078
2600
  ),
1079
- label != null && /* @__PURE__ */ jsx3("span", { className: "ods-flow-dataref-button__label", children: label })
2601
+ label != null && /* @__PURE__ */ jsx4("span", { className: "ods-flow-dataref-button__label", children: label })
1080
2602
  ]
1081
2603
  }
1082
2604
  );
1083
2605
  }
1084
2606
 
1085
2607
  // src/workflow/components/NodeToolbar/NodeToolbar.tsx
1086
- import { jsx as jsx4 } from "react/jsx-runtime";
2608
+ import { jsx as jsx5 } from "react/jsx-runtime";
1087
2609
  function NodeToolbar({
1088
2610
  isVisible,
1089
2611
  position = "top",
@@ -1098,7 +2620,7 @@ function NodeToolbar({
1098
2620
  const show = isVisible ?? node.selected;
1099
2621
  if (!show) return null;
1100
2622
  const inverseScale = 1 / viewport.zoom;
1101
- return /* @__PURE__ */ jsx4(
2623
+ return /* @__PURE__ */ jsx5(
1102
2624
  "div",
1103
2625
  {
1104
2626
  className: cn("ods-node-toolbar", `ods-node-toolbar--${position}`, className),
@@ -1110,7 +2632,7 @@ function NodeToolbar({
1110
2632
  onPointerDown: (e) => e.stopPropagation(),
1111
2633
  onMouseDown: (e) => e.stopPropagation(),
1112
2634
  onClick: (e) => e.stopPropagation(),
1113
- children: /* @__PURE__ */ jsx4(
2635
+ children: /* @__PURE__ */ jsx5(
1114
2636
  "div",
1115
2637
  {
1116
2638
  className: "ods-node-toolbar__inner",
@@ -1266,7 +2788,10 @@ export {
1266
2788
  ForEachNode,
1267
2789
  FxPanel,
1268
2790
  GroupNode,
2791
+ HTTP_ACTION_DEFAULTS,
2792
+ HTTP_METHODS,
1269
2793
  Handle,
2794
+ HttpActionPanel,
1270
2795
  HttpRequestNode,
1271
2796
  NodeResizer,
1272
2797
  NodeToolbar,
@@ -1280,19 +2805,28 @@ export {
1280
2805
  applyNodeChanges,
1281
2806
  bezierPath2 as bezierPath,
1282
2807
  bezierPath as bezierPathFn,
2808
+ buildCurl,
1283
2809
  buildEdgePath,
1284
2810
  buildNodeKindRegistry,
1285
2811
  change,
1286
2812
  clampToParentExtent,
1287
2813
  collapseFor,
2814
+ countGraphqlVariables,
2815
+ countSchemaPaths,
1288
2816
  createDagreEngine,
1289
2817
  createElkEngine,
1290
2818
  descendantsOf,
2819
+ effectiveUrl,
1291
2820
  findAncestor,
1292
2821
  findContainingGroup,
1293
2822
  flowToScreen,
1294
2823
  handleCentre,
2824
+ inferJsonSchema,
2825
+ normalizeAuth,
2826
+ normalizeKeyValues,
2827
+ parseCurl,
1295
2828
  screenToFlow,
2829
+ serializeKeyValues,
1296
2830
  smoothStepPath,
1297
2831
  stepPath,
1298
2832
  straightPath,
@@ -1312,6 +2846,7 @@ export {
1312
2846
  useNodes,
1313
2847
  useSelection,
1314
2848
  useViewport,
1315
- useViewportOrNull
2849
+ useViewportOrNull,
2850
+ validateHttpConfig
1316
2851
  };
1317
2852
  //# sourceMappingURL=workflow.js.map