@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.
- package/dist/chunk-64R3BAO7.js +2755 -0
- package/dist/chunk-64R3BAO7.js.map +1 -0
- package/dist/chunk-7S3CSRRV.js +5700 -0
- package/dist/chunk-7S3CSRRV.js.map +1 -0
- package/dist/chunk-JMSZOWT2.js +2616 -0
- package/dist/chunk-JMSZOWT2.js.map +1 -0
- package/dist/chunk-KCA7V5VN.js +5752 -0
- package/dist/chunk-KCA7V5VN.js.map +1 -0
- package/dist/chunk-KQKD4Z4H.js +1682 -0
- package/dist/chunk-KQKD4Z4H.js.map +1 -0
- package/dist/chunk-KZP2MNBO.js +2516 -0
- package/dist/chunk-KZP2MNBO.js.map +1 -0
- package/dist/chunk-PWCRELX4.js +5700 -0
- package/dist/chunk-PWCRELX4.js.map +1 -0
- package/dist/chunk-S4LE4BFQ.js +5934 -0
- package/dist/chunk-S4LE4BFQ.js.map +1 -0
- package/dist/chunk-U5T63SPL.js +5695 -0
- package/dist/chunk-U5T63SPL.js.map +1 -0
- package/dist/chunk-X7YETDK7.js +107 -0
- package/dist/chunk-X7YETDK7.js.map +1 -0
- package/dist/chunk-YIPBLM3G.js +2698 -0
- package/dist/chunk-YIPBLM3G.js.map +1 -0
- package/dist/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/components/WorkflowShowcase/ShowcaseScene.d.ts +20 -0
- package/dist/components/WorkflowShowcase/ShowcaseScene.d.ts.map +1 -0
- package/dist/components/WorkflowShowcase/ShowcaseSignup.d.ts +14 -0
- package/dist/components/WorkflowShowcase/ShowcaseSignup.d.ts.map +1 -0
- package/dist/components/WorkflowShowcase/WorkflowShowcase.d.ts +48 -0
- package/dist/components/WorkflowShowcase/WorkflowShowcase.d.ts.map +1 -0
- package/dist/components/WorkflowShowcase/index.d.ts +3 -0
- package/dist/components/WorkflowShowcase/index.d.ts.map +1 -0
- package/dist/components/WorkflowShowcase/showcaseEngine.d.ts +102 -0
- package/dist/components/WorkflowShowcase/showcaseEngine.d.ts.map +1 -0
- package/dist/index.cjs +5 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +18795 -25817
- package/dist/index.js.map +1 -1
- package/dist/marketing/components/AssistantTranscript/AssistantTranscript.d.ts +15 -0
- package/dist/marketing/components/AssistantTranscript/AssistantTranscript.d.ts.map +1 -0
- package/dist/marketing/components/BackedBy/BackedBy.d.ts +17 -0
- package/dist/marketing/components/BackedBy/BackedBy.d.ts.map +1 -0
- package/dist/marketing/components/BetaAccessForm/BetaAccessForm.d.ts +36 -0
- package/dist/marketing/components/BetaAccessForm/BetaAccessForm.d.ts.map +1 -0
- package/dist/marketing/components/BlogGrid/BlogGrid.d.ts +32 -0
- package/dist/marketing/components/BlogGrid/BlogGrid.d.ts.map +1 -0
- package/dist/marketing/components/ContactForm/ContactForm.d.ts +31 -0
- package/dist/marketing/components/ContactForm/ContactForm.d.ts.map +1 -0
- package/dist/marketing/components/CtaBanner/CtaBanner.d.ts +16 -0
- package/dist/marketing/components/CtaBanner/CtaBanner.d.ts.map +1 -0
- package/dist/marketing/components/FaqSection/FaqSection.d.ts +13 -0
- package/dist/marketing/components/FaqSection/FaqSection.d.ts.map +1 -0
- package/dist/marketing/components/FeatureGrid/FeatureGrid.d.ts +15 -0
- package/dist/marketing/components/FeatureGrid/FeatureGrid.d.ts.map +1 -0
- package/dist/marketing/components/IntegrationsFinder/IntegrationsFinder.d.ts +32 -0
- package/dist/marketing/components/IntegrationsFinder/IntegrationsFinder.d.ts.map +1 -0
- package/dist/marketing/components/IntegrationsWall/IntegrationsWall.d.ts +21 -0
- package/dist/marketing/components/IntegrationsWall/IntegrationsWall.d.ts.map +1 -0
- package/dist/marketing/components/LiveConsole/LiveConsole.d.ts +21 -0
- package/dist/marketing/components/LiveConsole/LiveConsole.d.ts.map +1 -0
- package/dist/marketing/components/LogoMarquee/LogoMarquee.d.ts +18 -0
- package/dist/marketing/components/LogoMarquee/LogoMarquee.d.ts.map +1 -0
- package/dist/marketing/components/MarketingFooter/MarketingFooter.d.ts +30 -0
- package/dist/marketing/components/MarketingFooter/MarketingFooter.d.ts.map +1 -0
- package/dist/marketing/components/MarketingHero/MarketingHero.d.ts +11 -0
- package/dist/marketing/components/MarketingHero/MarketingHero.d.ts.map +1 -0
- package/dist/marketing/components/MarketingNav/MarketingNav.d.ts +17 -0
- package/dist/marketing/components/MarketingNav/MarketingNav.d.ts.map +1 -0
- package/dist/marketing/components/MarketingSection/MarketingSection.d.ts +15 -0
- package/dist/marketing/components/MarketingSection/MarketingSection.d.ts.map +1 -0
- package/dist/marketing/components/PageHero/PageHero.d.ts +12 -0
- package/dist/marketing/components/PageHero/PageHero.d.ts.map +1 -0
- package/dist/marketing/components/PricingTiers/PricingTiers.d.ts +29 -0
- package/dist/marketing/components/PricingTiers/PricingTiers.d.ts.map +1 -0
- package/dist/marketing/components/StatBand/StatBand.d.ts +16 -0
- package/dist/marketing/components/StatBand/StatBand.d.ts.map +1 -0
- package/dist/marketing/components/TestimonialStrip/TestimonialStrip.d.ts +24 -0
- package/dist/marketing/components/TestimonialStrip/TestimonialStrip.d.ts.map +1 -0
- package/dist/marketing/components/WorkflowShowcase/ShowcaseScene.d.ts +22 -0
- package/dist/marketing/components/WorkflowShowcase/ShowcaseScene.d.ts.map +1 -0
- package/dist/marketing/components/WorkflowShowcase/ShowcaseSignup.d.ts +14 -0
- package/dist/marketing/components/WorkflowShowcase/ShowcaseSignup.d.ts.map +1 -0
- package/dist/marketing/components/WorkflowShowcase/WorkflowShowcase.d.ts +56 -0
- package/dist/marketing/components/WorkflowShowcase/WorkflowShowcase.d.ts.map +1 -0
- package/dist/marketing/components/WorkflowShowcase/index.d.ts +3 -0
- package/dist/marketing/components/WorkflowShowcase/index.d.ts.map +1 -0
- package/dist/marketing/components/WorkflowShowcase/showcaseEngine.d.ts +104 -0
- package/dist/marketing/components/WorkflowShowcase/showcaseEngine.d.ts.map +1 -0
- package/dist/marketing/glyphs.d.ts +20 -0
- package/dist/marketing/glyphs.d.ts.map +1 -0
- package/dist/marketing/index.d.ts +23 -0
- package/dist/marketing/index.d.ts.map +1 -0
- package/dist/marketing.cjs +6581 -0
- package/dist/marketing.cjs.map +1 -0
- package/dist/marketing.js +2602 -0
- package/dist/marketing.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/workflow/components/HttpActionPanel/HttpActionPanel.d.ts +29 -0
- package/dist/workflow/components/HttpActionPanel/HttpActionPanel.d.ts.map +1 -0
- package/dist/workflow/components/HttpActionPanel/httpActionTypes.d.ts +135 -0
- package/dist/workflow/components/HttpActionPanel/httpActionTypes.d.ts.map +1 -0
- package/dist/workflow/index.d.ts +2 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow.cjs +6931 -271
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.js +1591 -56
- package/dist/workflow.js.map +1 -1
- 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-
|
|
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
|
|
626
|
-
useRef as
|
|
627
|
-
useState as
|
|
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
|
|
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] =
|
|
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 =
|
|
2228
|
+
const visibleCategories = useMemo3(
|
|
707
2229
|
() => categories.filter((c) => c.items.length > 0),
|
|
708
2230
|
[categories]
|
|
709
2231
|
);
|
|
710
|
-
const [internalCat, setInternalCat] =
|
|
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] =
|
|
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] =
|
|
748
|
-
const [focusedId, setFocusedId] =
|
|
749
|
-
const hits =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
871
|
-
hasChildren ? /* @__PURE__ */
|
|
872
|
-
/* @__PURE__ */
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
mono ? /* @__PURE__ */
|
|
875
|
-
item.valueType && /* @__PURE__ */
|
|
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__ */
|
|
887
|
-
crumb && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
904
|
-
/* @__PURE__ */
|
|
905
|
-
onClose && /* @__PURE__ */
|
|
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__ */
|
|
2434
|
+
children: /* @__PURE__ */ jsx3(CloseIcon, { size: "sm" })
|
|
913
2435
|
}
|
|
914
2436
|
)
|
|
915
2437
|
] }),
|
|
916
|
-
/* @__PURE__ */
|
|
917
|
-
/* @__PURE__ */
|
|
918
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2458
|
+
children: /* @__PURE__ */ jsx3(CloseIcon, { size: "sm" })
|
|
937
2459
|
}
|
|
938
2460
|
)
|
|
939
2461
|
] }),
|
|
940
|
-
hint && !query && /* @__PURE__ */
|
|
941
|
-
/* @__PURE__ */
|
|
942
|
-
query && hits && (hits.length > 0 ? /* @__PURE__ */
|
|
943
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
968
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2535
|
+
/* @__PURE__ */ jsx3("span", { className: "ods-flow-fx-panel__count", children: countLeaves(cat.items) })
|
|
1014
2536
|
]
|
|
1015
2537
|
}
|
|
1016
2538
|
),
|
|
1017
|
-
isOpen && hasTree && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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
|