@burdenoff/fluidgrids-fe-sdk 2026.1017.2 → 2026.1019.1

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 (30) hide show
  1. package/dist/{ExecutionDetailPage-5ZLI6YZP.js → ExecutionDetailPage-TWLLKOCJ.js} +3 -3
  2. package/dist/{ExecutionsListPage-4OKTQUB7.js → ExecutionsListPage-NZZFAU5B.js} +4 -4
  3. package/dist/{WorkflowBuilder-3AZ5D3L7.js → WorkflowBuilder-423I22RL.js} +5 -5
  4. package/dist/{WorkflowsList-FESCHECO.js → WorkflowsList-LDIKEXC3.js} +4 -4
  5. package/dist/{chunk-DIQQNS6K.js → chunk-3ZQVSPPA.js} +2 -2
  6. package/dist/{chunk-Y33ZGP5F.js → chunk-7S5WTQ7X.js} +2 -2
  7. package/dist/{chunk-UNRFUBE5.js → chunk-BEOGOFNQ.js} +2 -2
  8. package/dist/{chunk-PYQHV2NT.js → chunk-BXRTBIUQ.js} +15 -1
  9. package/dist/{chunk-MESOVECH.js → chunk-EPYVZPGU.js} +1 -1
  10. package/dist/{chunk-5KAMCVQN.js → chunk-HNZ7MGRO.js} +3 -3
  11. package/dist/{chunk-JPH6XZ5V.js → chunk-HY4XW2FZ.js} +1 -1
  12. package/dist/{chunk-NFBNWXJH.js → chunk-L2UWPFJM.js} +4 -1
  13. package/dist/{chunk-XZO64J5O.js → chunk-MYWXF7S5.js} +11 -3
  14. package/dist/{chunk-UUELRAQ2.js → chunk-O6E247J6.js} +1 -1
  15. package/dist/{chunk-OBH5MEIP.js → chunk-SMGJB7DL.js} +431 -46
  16. package/dist/{chunk-P6EUVE3U.js → chunk-WQ7CETWI.js} +1 -1
  17. package/dist/{chunk-7ZVWGAVI.js → chunk-YA73BHRQ.js} +2 -2
  18. package/dist/{chunk-XL3QSK42.js → chunk-YKIIHFTU.js} +3 -3
  19. package/dist/executions.js +5 -5
  20. package/dist/history.js +3 -3
  21. package/dist/index.d.ts +101 -3
  22. package/dist/index.js +20 -20
  23. package/dist/nodes.js +2 -2
  24. package/dist/settings.js +3 -3
  25. package/dist/templates.js +5 -5
  26. package/dist/{workflow-builder-CBLLeFzM.d.ts → workflow-builder-Uhk2DIB6.d.ts} +12 -0
  27. package/dist/workflow-builder.d.ts +1 -1
  28. package/dist/workflow-builder.js +6 -6
  29. package/dist/workflows-list.js +4 -4
  30. package/package.json +1 -1
@@ -7,10 +7,10 @@ import { getGlobalStoreClient, createGlobalStoreClient, setGlobalStoreClient, re
7
7
  import { GetMyNodeInstallationsDocument, BrowseWorkflowTemplatesDocument, InstallWorkflowNodeDocument, InstallPurchasedNodeDocument, BrowseWorkflowNodesDocument, UninstallWorkflowNodeDocument, CreateStoreOrderDocument, GetNodeInstallableVersionsDocument } from './chunk-WBH2XEWO.js';
8
8
  import { SdkPermissionGate, FLUIDGRIDS_PERMISSIONS, SdkPermissionButton } from './chunk-ONVGFVNH.js';
9
9
  import { cn as cn$1 } from './chunk-JL7CASN5.js';
10
- import { useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeleteWorkflow, useLazyWorkflowDefinition, useDeactivateWorkflow } from './chunk-UUELRAQ2.js';
10
+ import { useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeleteWorkflow, useLazyWorkflowDefinition, useDeactivateWorkflow } from './chunk-O6E247J6.js';
11
11
  import { config, getFluidGridsConfig, validateTrustedOrigin, resetFluidGridsExecutionState, setFluidGridsConfig, resetFluidGridsConfig } from './chunk-UZG3ZIQM.js';
12
- import { useFlowStore, isNodeTrigger, useIsValidConnection, isTriggerOperation } from './chunk-PYQHV2NT.js';
13
- import { NodeEndpointConfigsDocument, NodeManifestDocument, UpdateWorkflowDefinitionDocument, CreateWorkflowDefinitionDocument, CreateWorkflowVersionDocument, ExecuteStepDocument, TriggerWorkflowDocument, RunFromNodeDocument, ExecutionDetailDocument, WorkflowRunDocument, FluidgridsEntityTagsDocument, AvailableFluidgridsTagsDocument, SearchFluidgridsTagsDocument, TagFluidgridsEntityDocument, UntagFluidgridsEntityDocument, ReplaceFluidgridsEntityTagsDocument, CreateFluidgridsTagDocument, NodeSchemaIntrospectionDocument, useWorkflowPinnedDataQuery, usePinNodeDataMutation, useUnpinNodeDataMutation, useRunFromNodeEligibilityQuery, EventRegistrationsDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-NFBNWXJH.js';
12
+ import { useFlowStore, isNodeTrigger, useIsValidConnection, isTriggerOperation } from './chunk-BXRTBIUQ.js';
13
+ import { NodeEndpointConfigsDocument, NodeManifestDocument, UpdateWorkflowDefinitionDocument, CreateWorkflowDefinitionDocument, CreateWorkflowVersionDocument, ExecuteStepDocument, TriggerWorkflowDocument, RunFromNodeDocument, ExecutionDetailDocument, WorkflowRunDocument, FluidgridsEntityTagsDocument, AvailableFluidgridsTagsDocument, SearchFluidgridsTagsDocument, TagFluidgridsEntityDocument, UntagFluidgridsEntityDocument, ReplaceFluidgridsEntityTagsDocument, CreateFluidgridsTagDocument, NodeSchemaIntrospectionDocument, useWorkflowPinnedDataQuery, usePinNodeDataMutation, useUnpinNodeDataMutation, useRunFromNodeEligibilityQuery, EventRegistrationsDocument, WebhookTestListenerDocument, StopWebhookTestListenerDocument, ListenForWebhookTestEventDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-L2UWPFJM.js';
14
14
  import { throwIfResultError, describeOperationError } from './chunk-CFCUM4CN.js';
15
15
  import { useTr, FluidGridsTranslationProvider, ENGLISH_FALLBACK_TRANSLATOR } from './chunk-UULVIT25.js';
16
16
  import { waitForFluidGridsClient, getFluidGridsClient, getFluidGridsClientSafe, createFluidGridsClient, setFluidGridsClient, resetFluidGridsClient } from './chunk-NTWG3CJX.js';
@@ -6235,6 +6235,29 @@ function useNodeExecution() {
6235
6235
  completeExecution
6236
6236
  ]
6237
6237
  );
6238
+ const followRun = useCallback(
6239
+ (runId, triggerNodeId) => {
6240
+ cleanup();
6241
+ clearLogs();
6242
+ setNodeStatus(triggerNodeId, "running");
6243
+ startExecution(triggerNodeId, runId, {
6244
+ workflowKey: workflow.workflowKey || workflow.id,
6245
+ version: workflow.version,
6246
+ sourceMode: "TEST"
6247
+ });
6248
+ pollRunUpdates(runId);
6249
+ },
6250
+ [
6251
+ cleanup,
6252
+ clearLogs,
6253
+ setNodeStatus,
6254
+ startExecution,
6255
+ workflow.workflowKey,
6256
+ workflow.id,
6257
+ workflow.version,
6258
+ pollRunUpdates
6259
+ ]
6260
+ );
6238
6261
  const executeFromNode = useCallback(
6239
6262
  async (sourceRunId, nodeId) => {
6240
6263
  cleanup();
@@ -6372,6 +6395,7 @@ function useNodeExecution() {
6372
6395
  executeStep,
6373
6396
  executeFullWorkflow,
6374
6397
  executeFromNode,
6398
+ followRun,
6375
6399
  loadExecution,
6376
6400
  cleanup,
6377
6401
  findTriggerNode
@@ -21641,69 +21665,405 @@ function WaitResumeUrlField() {
21641
21665
  ) })
21642
21666
  ] });
21643
21667
  }
21668
+ var POLL_INTERVAL_MS = 2e3;
21669
+ function useWebhookTestListener(target, onReceived) {
21670
+ const [listener, setListener] = useState(
21671
+ null
21672
+ );
21673
+ const [busy, setBusy] = useState(false);
21674
+ const [error, setError] = useState(null);
21675
+ const pollTimer = useRef(null);
21676
+ const openId = useRef(null);
21677
+ const generation = useRef(0);
21678
+ const onReceivedRef = useRef(onReceived);
21679
+ onReceivedRef.current = onReceived;
21680
+ const workflowKey = target?.workflowKey;
21681
+ const version = target?.version;
21682
+ const triggerNodeId = target?.triggerNodeId;
21683
+ const clearPoll = useCallback(() => {
21684
+ if (pollTimer.current) {
21685
+ clearTimeout(pollTimer.current);
21686
+ pollTimer.current = null;
21687
+ }
21688
+ }, []);
21689
+ const poll = useCallback(
21690
+ (id) => {
21691
+ clearPoll();
21692
+ pollTimer.current = setTimeout(async () => {
21693
+ const client = getFluidGridsClientSafe();
21694
+ if (!client || openId.current !== id) return;
21695
+ try {
21696
+ const result = await client.query({
21697
+ query: WebhookTestListenerDocument,
21698
+ variables: { id },
21699
+ fetchPolicy: "network-only"
21700
+ });
21701
+ const latest = result.data?.webhookTestListener;
21702
+ if (openId.current !== id) return;
21703
+ if (!latest) {
21704
+ openId.current = null;
21705
+ setListener(null);
21706
+ return;
21707
+ }
21708
+ const status = latest.status;
21709
+ setListener(
21710
+ (current) => current && current.id === id ? {
21711
+ ...current,
21712
+ status,
21713
+ runId: latest.runId ?? null,
21714
+ error: latest.error ?? null
21715
+ } : current
21716
+ );
21717
+ if (status === "LISTENING") {
21718
+ poll(id);
21719
+ return;
21720
+ }
21721
+ openId.current = null;
21722
+ if (status === "RECEIVED" && latest.runId) {
21723
+ onReceivedRef.current(latest.runId);
21724
+ }
21725
+ } catch {
21726
+ if (openId.current === id) poll(id);
21727
+ }
21728
+ }, POLL_INTERVAL_MS);
21729
+ },
21730
+ [clearPoll]
21731
+ );
21732
+ const stopAbandoned = useCallback((id) => {
21733
+ void getFluidGridsClientSafe()?.mutate({ mutation: StopWebhookTestListenerDocument, variables: { id } }).catch(() => void 0);
21734
+ }, []);
21735
+ const stopOpenListener = useCallback(() => {
21736
+ const id = openId.current;
21737
+ openId.current = null;
21738
+ clearPoll();
21739
+ if (id) stopAbandoned(id);
21740
+ }, [clearPoll, stopAbandoned]);
21741
+ const listen = useCallback(async () => {
21742
+ const client = getFluidGridsClientSafe();
21743
+ if (!client || !workflowKey || !version || !triggerNodeId) return;
21744
+ stopOpenListener();
21745
+ const armedFor = generation.current;
21746
+ setBusy(true);
21747
+ setError(null);
21748
+ try {
21749
+ const result = await client.mutate({
21750
+ mutation: ListenForWebhookTestEventDocument,
21751
+ variables: { input: { workflowKey, version, triggerNodeId } }
21752
+ });
21753
+ const armed = result.data?.listenForWebhookTestEvent;
21754
+ if (!armed) throw new Error("The test listener could not be started");
21755
+ if (generation.current !== armedFor) {
21756
+ stopAbandoned(armed.id);
21757
+ return;
21758
+ }
21759
+ openId.current = armed.id;
21760
+ setListener({
21761
+ id: armed.id,
21762
+ status: armed.status,
21763
+ testUrl: armed.testUrl ?? null,
21764
+ expiresAt: armed.expiresAt,
21765
+ runId: armed.runId ?? null,
21766
+ error: armed.error ?? null
21767
+ });
21768
+ poll(armed.id);
21769
+ } catch (err) {
21770
+ if (generation.current === armedFor)
21771
+ setError(describeOperationError(err));
21772
+ } finally {
21773
+ if (generation.current === armedFor) setBusy(false);
21774
+ }
21775
+ }, [
21776
+ workflowKey,
21777
+ version,
21778
+ triggerNodeId,
21779
+ poll,
21780
+ stopOpenListener,
21781
+ stopAbandoned
21782
+ ]);
21783
+ const stop = useCallback(async () => {
21784
+ const id = openId.current;
21785
+ const client = getFluidGridsClientSafe();
21786
+ if (!id || !client) return;
21787
+ clearPoll();
21788
+ const stoppedFor = generation.current;
21789
+ setBusy(true);
21790
+ try {
21791
+ const result = await client.mutate({ mutation: StopWebhookTestListenerDocument, variables: { id } });
21792
+ const stopped = result.data?.stopWebhookTestListener;
21793
+ if (generation.current !== stoppedFor) return;
21794
+ if (!stopped) throw new Error("The test listener could not be stopped");
21795
+ const closedHere = openId.current === id;
21796
+ if (closedHere) openId.current = null;
21797
+ const status = stopped.status;
21798
+ setListener(
21799
+ (current) => current && current.id === id ? {
21800
+ ...current,
21801
+ status,
21802
+ runId: stopped.runId ?? null,
21803
+ error: stopped.error ?? null
21804
+ } : current
21805
+ );
21806
+ if (closedHere && status === "RECEIVED" && stopped.runId) {
21807
+ onReceivedRef.current(stopped.runId);
21808
+ }
21809
+ } catch (err) {
21810
+ if (generation.current !== stoppedFor) return;
21811
+ setError(describeOperationError(err));
21812
+ if (openId.current === id) poll(id);
21813
+ } finally {
21814
+ if (generation.current === stoppedFor) setBusy(false);
21815
+ }
21816
+ }, [clearPoll, poll]);
21817
+ useEffect(() => {
21818
+ setListener(null);
21819
+ setError(null);
21820
+ setBusy(false);
21821
+ return () => {
21822
+ generation.current += 1;
21823
+ stopOpenListener();
21824
+ };
21825
+ }, [workflowKey, version, triggerNodeId, stopOpenListener]);
21826
+ return { listener, busy, error, listen, stop };
21827
+ }
21828
+ var BuilderReadOnlyContext = createContext(false);
21829
+ var BuilderReadOnlyProvider = BuilderReadOnlyContext.Provider;
21830
+ function useBuilderReadOnly() {
21831
+ return useContext(BuilderReadOnlyContext);
21832
+ }
21644
21833
  var SECTION_LABEL2 = "text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground";
21645
- function WebhookUrlField({ webhookUrl, loading }) {
21834
+ function CopyableUrl({
21835
+ url,
21836
+ copyAriaLabel,
21837
+ testId
21838
+ }) {
21646
21839
  const tr = useTr();
21647
21840
  const [copied, setCopied] = useState(false);
21648
21841
  const handleCopy = async () => {
21649
- if (!webhookUrl) return;
21650
21842
  try {
21651
- await navigator.clipboard.writeText(webhookUrl);
21843
+ await navigator.clipboard.writeText(url);
21652
21844
  setCopied(true);
21653
21845
  setTimeout(() => setCopied(false), 1500);
21654
21846
  } catch {
21655
21847
  }
21656
21848
  };
21849
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-stretch gap-2", children: [
21850
+ /* @__PURE__ */ jsx(
21851
+ "input",
21852
+ {
21853
+ readOnly: true,
21854
+ value: url,
21855
+ "data-testid": testId,
21856
+ onFocus: (e) => e.currentTarget.select(),
21857
+ className: "min-w-0 flex-1 rounded-md border border-border bg-muted/40 px-3 py-2 font-mono text-xs text-foreground outline-none focus:border-primary"
21858
+ }
21859
+ ),
21860
+ /* @__PURE__ */ jsxs(
21861
+ "button",
21862
+ {
21863
+ type: "button",
21864
+ onClick: handleCopy,
21865
+ className: cn(
21866
+ "inline-flex shrink-0 items-center gap-1.5 rounded-md border border-border px-3 py-2 text-xs font-medium transition-colors",
21867
+ copied ? "border-primary bg-primary/10 text-primary" : "bg-background text-foreground hover:bg-muted"
21868
+ ),
21869
+ "aria-label": copyAriaLabel,
21870
+ children: [
21871
+ /* @__PURE__ */ jsx(
21872
+ Icon,
21873
+ {
21874
+ icon: copied ? "mdi:check" : "mdi:content-copy",
21875
+ className: "h-4 w-4"
21876
+ }
21877
+ ),
21878
+ copied ? tr("fluidgrids.builder.webhookUrlField.copied", "Copied") : tr("fluidgrids.builder.webhookUrlField.copy", "Copy")
21879
+ ]
21880
+ }
21881
+ )
21882
+ ] });
21883
+ }
21884
+ function WebhookUrlField({ webhookUrl, loading }) {
21885
+ const tr = useTr();
21886
+ const isActiveVersion = useFlowStore((s) => s.workflow.status === "ACTIVE");
21657
21887
  return /* @__PURE__ */ jsxs("div", { className: "space-y-2", "data-testid": "ndv-webhook-url", children: [
21658
- /* @__PURE__ */ jsx("div", { className: SECTION_LABEL2, children: tr("fluidgrids.builder.webhookUrlField.label", "Webhook URL") }),
21888
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
21889
+ /* @__PURE__ */ jsx("div", { className: SECTION_LABEL2, children: tr(
21890
+ "fluidgrids.builder.webhookUrlField.productionLabel",
21891
+ "Production URL"
21892
+ ) }),
21893
+ webhookUrl && isActiveVersion && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-primary/10 px-2 py-0.5 text-[10px] font-medium text-primary", children: tr("fluidgrids.builder.webhookUrlField.live", "Live") })
21894
+ ] }),
21659
21895
  webhookUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
21660
- /* @__PURE__ */ jsxs("div", { className: "flex items-stretch gap-2", children: [
21661
- /* @__PURE__ */ jsx(
21662
- "input",
21663
- {
21664
- readOnly: true,
21665
- value: webhookUrl,
21666
- onFocus: (e) => e.currentTarget.select(),
21667
- className: "min-w-0 flex-1 rounded-md border border-border bg-muted/40 px-3 py-2 font-mono text-xs text-foreground outline-none focus:border-primary"
21668
- }
21669
- ),
21896
+ /* @__PURE__ */ jsx(
21897
+ CopyableUrl,
21898
+ {
21899
+ url: webhookUrl,
21900
+ testId: "ndv-webhook-production-url",
21901
+ copyAriaLabel: tr(
21902
+ "fluidgrids.builder.webhookUrlField.copyAriaLabel",
21903
+ "Copy webhook URL"
21904
+ )
21905
+ }
21906
+ ),
21907
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: isActiveVersion ? tr(
21908
+ "fluidgrids.builder.webhookUrlField.activeHint",
21909
+ "Requests to this URL run this version of the workflow."
21910
+ ) : tr(
21911
+ "fluidgrids.builder.webhookUrlField.inactiveHint",
21912
+ "Requests to this URL run the workflow's active version only. Activate this version to make it live, or use a test URL to try it."
21913
+ ) })
21914
+ ] }) : /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: loading ? tr(
21915
+ "fluidgrids.builder.webhookUrlField.loading",
21916
+ "Loading webhook URL\u2026"
21917
+ ) : tr(
21918
+ "fluidgrids.builder.webhookUrlField.unsaved",
21919
+ "Save the workflow to generate its webhook URL."
21920
+ ) })
21921
+ ] });
21922
+ }
21923
+ function useSecondsLeft(expiresAt) {
21924
+ const [now, setNow] = useState(() => Date.now());
21925
+ useEffect(() => {
21926
+ if (!expiresAt) return;
21927
+ const timer = setInterval(() => setNow(Date.now()), 1e3);
21928
+ return () => clearInterval(timer);
21929
+ }, [expiresAt]);
21930
+ if (!expiresAt) return 0;
21931
+ return Math.max(0, Math.ceil((Date.parse(expiresAt) - now) / 1e3));
21932
+ }
21933
+ function WebhookTestListenerField({
21934
+ nodeId
21935
+ }) {
21936
+ const readOnly = useBuilderReadOnly();
21937
+ return readOnly ? null : /* @__PURE__ */ jsx(WebhookTestListenerControls, { nodeId });
21938
+ }
21939
+ function WebhookTestListenerControls({
21940
+ nodeId
21941
+ }) {
21942
+ const tr = useTr();
21943
+ const workflowKey = useFlowStore((s) => s.workflow.workflowKey);
21944
+ const version = useFlowStore((s) => s.workflow.version);
21945
+ const requestFollowRun = useFlowStore(
21946
+ (s) => s.actions.execution.requestFollowRun
21947
+ );
21948
+ const saved = !!workflowKey && !!version && !!nodeId;
21949
+ const target = saved ? { workflowKey, version, triggerNodeId: nodeId } : null;
21950
+ const { listener, busy, error, listen, stop } = useWebhookTestListener(
21951
+ target,
21952
+ (runId) => {
21953
+ if (nodeId) requestFollowRun(runId, nodeId);
21954
+ }
21955
+ );
21956
+ const listening = listener?.status === "LISTENING";
21957
+ const secondsLeft = useSecondsLeft(listening ? listener.expiresAt : null);
21958
+ const outcome = (() => {
21959
+ switch (listener?.status) {
21960
+ case "RECEIVED":
21961
+ return tr(
21962
+ "fluidgrids.builder.webhookTestListener.received",
21963
+ "Test event received \u2014 the run is shown on the canvas."
21964
+ );
21965
+ case "EXPIRED":
21966
+ return tr(
21967
+ "fluidgrids.builder.webhookTestListener.expired",
21968
+ "Stopped listening: no test event arrived in time."
21969
+ );
21970
+ case "STOPPED":
21971
+ return tr(
21972
+ "fluidgrids.builder.webhookTestListener.stopped",
21973
+ "Stopped listening."
21974
+ );
21975
+ case "FAILED":
21976
+ return listener.error ?? tr(
21977
+ "fluidgrids.builder.webhookTestListener.failed",
21978
+ "The test event arrived but the run could not be started."
21979
+ );
21980
+ default:
21981
+ return null;
21982
+ }
21983
+ })();
21984
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", "data-testid": "ndv-webhook-test", children: [
21985
+ /* @__PURE__ */ jsx("div", { className: SECTION_LABEL2, children: tr("fluidgrids.builder.webhookTestListener.label", "Test URL") }),
21986
+ !saved ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: tr(
21987
+ "fluidgrids.builder.webhookTestListener.unsaved",
21988
+ "Save the workflow to test this webhook."
21989
+ ) }) : listening && listener.testUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
21990
+ /* @__PURE__ */ jsx(
21991
+ CopyableUrl,
21992
+ {
21993
+ url: listener.testUrl,
21994
+ testId: "ndv-webhook-test-url",
21995
+ copyAriaLabel: tr(
21996
+ "fluidgrids.builder.webhookTestListener.copyAriaLabel",
21997
+ "Copy test URL"
21998
+ )
21999
+ }
22000
+ ),
22001
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
21670
22002
  /* @__PURE__ */ jsxs(
21671
- "button",
22003
+ "p",
21672
22004
  {
21673
- type: "button",
21674
- onClick: handleCopy,
21675
- className: cn(
21676
- "inline-flex shrink-0 items-center gap-1.5 rounded-md border border-border px-3 py-2 text-xs font-medium transition-colors",
21677
- copied ? "border-primary bg-primary/10 text-primary" : "bg-background text-foreground hover:bg-muted"
21678
- ),
21679
- "aria-label": tr(
21680
- "fluidgrids.builder.webhookUrlField.copyAriaLabel",
21681
- "Copy webhook URL"
21682
- ),
22005
+ className: "flex items-center gap-1.5 text-[11px] text-muted-foreground",
22006
+ "data-testid": "ndv-webhook-test-status",
21683
22007
  children: [
21684
22008
  /* @__PURE__ */ jsx(
21685
22009
  Icon,
21686
22010
  {
21687
- icon: copied ? "mdi:check" : "mdi:content-copy",
21688
- className: "h-4 w-4"
22011
+ icon: "mdi:access-point",
22012
+ className: "h-3.5 w-3.5 text-primary"
21689
22013
  }
21690
22014
  ),
21691
- copied ? tr("fluidgrids.builder.webhookUrlField.copied", "Copied") : tr("fluidgrids.builder.webhookUrlField.copy", "Copy")
22015
+ tr(
22016
+ "fluidgrids.builder.webhookTestListener.listening",
22017
+ "Listening for one test event to version {{version}} \u2014 {{seconds}}s left",
22018
+ { version, seconds: secondsLeft }
22019
+ )
21692
22020
  ]
21693
22021
  }
22022
+ ),
22023
+ /* @__PURE__ */ jsx(
22024
+ "button",
22025
+ {
22026
+ type: "button",
22027
+ onClick: () => void stop(),
22028
+ disabled: busy,
22029
+ "data-testid": "ndv-webhook-test-stop",
22030
+ className: "shrink-0 rounded-md border border-border bg-background px-3 py-1.5 text-xs font-medium text-foreground hover:bg-muted disabled:opacity-50",
22031
+ children: tr("fluidgrids.builder.webhookTestListener.stop", "Stop")
22032
+ }
21694
22033
  )
21695
- ] }),
21696
- /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: tr(
21697
- "fluidgrids.builder.webhookUrlField.hint",
21698
- "Send HTTP requests to this URL to trigger the workflow."
21699
- ) })
21700
- ] }) : /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: loading ? tr(
21701
- "fluidgrids.builder.webhookUrlField.loading",
21702
- "Loading webhook URL\u2026"
21703
- ) : tr(
21704
- "fluidgrids.builder.webhookUrlField.unsaved",
21705
- "Save the workflow to generate its webhook URL."
21706
- ) })
22034
+ ] })
22035
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
22036
+ /* @__PURE__ */ jsxs(
22037
+ "button",
22038
+ {
22039
+ type: "button",
22040
+ onClick: () => void listen(),
22041
+ disabled: busy,
22042
+ "data-testid": "ndv-webhook-test-listen",
22043
+ className: "inline-flex items-center gap-1.5 rounded-md border border-border bg-background px-3 py-2 text-xs font-medium text-foreground hover:bg-muted disabled:opacity-50",
22044
+ children: [
22045
+ /* @__PURE__ */ jsx(Icon, { icon: "mdi:access-point", className: "h-4 w-4" }),
22046
+ tr(
22047
+ "fluidgrids.builder.webhookTestListener.listen",
22048
+ "Listen for test event"
22049
+ )
22050
+ ]
22051
+ }
22052
+ ),
22053
+ /* @__PURE__ */ jsx(
22054
+ "p",
22055
+ {
22056
+ className: "text-[11px] text-muted-foreground",
22057
+ "data-testid": "ndv-webhook-test-status",
22058
+ children: outcome ?? tr(
22059
+ "fluidgrids.builder.webhookTestListener.hint",
22060
+ "Creates a one-time URL for the saved version {{version}}. Unsaved changes are not included.",
22061
+ { version }
22062
+ )
22063
+ }
22064
+ )
22065
+ ] }),
22066
+ error && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-destructive", role: "alert", children: error })
21707
22067
  ] });
21708
22068
  }
21709
22069
  var LIST_WORKFLOWS_QUERY = gql`
@@ -23006,7 +23366,16 @@ function NodeParamsForm({
23006
23366
  return "1.0.0";
23007
23367
  })();
23008
23368
  return /* @__PURE__ */ jsxs(Fragment, { children: [
23009
- isWebhookTrigger && /* @__PURE__ */ jsx(WebhookUrlField, { webhookUrl, loading: webhookUrlLoading }),
23369
+ isWebhookTrigger && /* @__PURE__ */ jsxs(Fragment, { children: [
23370
+ /* @__PURE__ */ jsx(
23371
+ WebhookUrlField,
23372
+ {
23373
+ webhookUrl,
23374
+ loading: webhookUrlLoading
23375
+ }
23376
+ ),
23377
+ /* @__PURE__ */ jsx(WebhookTestListenerField, { nodeId: config2.node?.id })
23378
+ ] }),
23010
23379
  isWebhookWait && /* @__PURE__ */ jsx(WaitResumeUrlField, {}),
23011
23380
  connectionAdapters.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-2", "data-testid": `${testIdPrefix}-connections`, children: [
23012
23381
  /* @__PURE__ */ jsx("div", { className: SECTION_LABEL3, children: tr(
@@ -24803,6 +25172,19 @@ function EmptyState({
24803
25172
  /* @__PURE__ */ jsx("div", { className: "max-w-[14rem] text-xs text-muted-foreground", children: hint })
24804
25173
  ] });
24805
25174
  }
25175
+ function WebhookRunFollower() {
25176
+ const followRequest = useFlowStore((s) => s.execution.followRequest);
25177
+ const clearFollowRequest = useFlowStore(
25178
+ (s) => s.actions.execution.clearFollowRequest
25179
+ );
25180
+ const { followRun } = useNodeExecution();
25181
+ useEffect(() => {
25182
+ if (!followRequest) return;
25183
+ clearFollowRequest();
25184
+ followRun(followRequest.runId, followRequest.triggerNodeId);
25185
+ }, [followRequest, clearFollowRequest, followRun]);
25186
+ return null;
25187
+ }
24806
25188
  var PANEL_WIDTH = 380;
24807
25189
  var PANEL_EST_HEIGHT = 480;
24808
25190
  var MAPPER_WIDTH = 260;
@@ -26358,8 +26740,11 @@ var FlowBuilder = ({ readOnly = false }) => {
26358
26740
  ),
26359
26741
  /* @__PURE__ */ jsx(ChatPanel, {}),
26360
26742
  /* @__PURE__ */ jsx(LogsPanel, {}),
26361
- /* @__PURE__ */ jsx(NodeDetailView, {}),
26362
- /* @__PURE__ */ jsx(QuickConfigPanel, {}),
26743
+ /* @__PURE__ */ jsxs(BuilderReadOnlyProvider, { value: isReadOnly, children: [
26744
+ /* @__PURE__ */ jsx(NodeDetailView, {}),
26745
+ /* @__PURE__ */ jsx(QuickConfigPanel, {})
26746
+ ] }),
26747
+ !isReadOnly && /* @__PURE__ */ jsx(WebhookRunFollower, {}),
26363
26748
  /* @__PURE__ */ jsx(
26364
26749
  "div",
26365
26750
  {
@@ -2,7 +2,7 @@ import { REPLAY_WORKFLOW_RUN, RETRY_WORKFLOW_RUNS } from './chunk-QBFAJNUC.js';
2
2
  import { executionsControls } from './chunk-D3UWK7GY.js';
3
3
  import { useExecutionsStore } from './chunk-UZG3ZIQM.js';
4
4
  import { useFluidGridsPageControls } from './chunk-PJAWNFJV.js';
5
- import { ExecutionDetailDocument, ExecutionStatsDocument, PauseExecutionDocument, ResumeExecutionDocument, CancelExecutionDocument, RetryNodeDocument, TriggerWorkflowDocument, TerminateExecutionDocument, ExecutionsListDocument } from './chunk-NFBNWXJH.js';
5
+ import { ExecutionDetailDocument, ExecutionStatsDocument, PauseExecutionDocument, ResumeExecutionDocument, CancelExecutionDocument, RetryNodeDocument, TriggerWorkflowDocument, TerminateExecutionDocument, ExecutionsListDocument } from './chunk-L2UWPFJM.js';
6
6
  import { throwIfResultError } from './chunk-CFCUM4CN.js';
7
7
  import { useTr } from './chunk-UULVIT25.js';
8
8
  import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
@@ -1,7 +1,7 @@
1
- import { useExecution, buildNodeDisplayMap, useExecutionActions, useAutoRefresh, ExecutionStatusBadge, formatRunVersion, NodeTimeline, RunLogViewer } from './chunk-P6EUVE3U.js';
1
+ import { useExecution, buildNodeDisplayMap, useExecutionActions, useAutoRefresh, ExecutionStatusBadge, formatRunVersion, NodeTimeline, RunLogViewer } from './chunk-WQ7CETWI.js';
2
2
  import { useFluidGridsPermission, FLUIDGRIDS_PERMISSIONS } from './chunk-ONVGFVNH.js';
3
3
  import { getFluidGridsConfig } from './chunk-UZG3ZIQM.js';
4
- import { RunLogsDocument, RunLogAppendedDocument } from './chunk-NFBNWXJH.js';
4
+ import { RunLogsDocument, RunLogAppendedDocument } from './chunk-L2UWPFJM.js';
5
5
  import { throwIfResultError } from './chunk-CFCUM4CN.js';
6
6
  import { useTr } from './chunk-UULVIT25.js';
7
7
  import { getFluidGridsClientSafe } from './chunk-NTWG3CJX.js';
@@ -1,7 +1,7 @@
1
1
  import { isCreateIntent, decideMissingWorkflow } from './chunk-6N27YGMB.js';
2
- import { useInstalledNodes, buildNodeCheck, refetchStoreNodes, FlowBuilderPage, buildRequiredNodeTypes, mergeStickyNotes } from './chunk-OBH5MEIP.js';
3
- import { useLazyWorkflowDefinition, useCreateWorkflow } from './chunk-UUELRAQ2.js';
4
- import { useFlowStore } from './chunk-PYQHV2NT.js';
2
+ import { useInstalledNodes, buildNodeCheck, refetchStoreNodes, FlowBuilderPage, buildRequiredNodeTypes, mergeStickyNotes } from './chunk-SMGJB7DL.js';
3
+ import { useLazyWorkflowDefinition, useCreateWorkflow } from './chunk-O6E247J6.js';
4
+ import { useFlowStore } from './chunk-BXRTBIUQ.js';
5
5
  import { useTr } from './chunk-UULVIT25.js';
6
6
  import { useNavigate, useParams, useLocation } from 'react-router';
7
7
  import { toast } from 'sonner';
@@ -1,15 +1,15 @@
1
1
  import './chunk-AD3BXTJS.js';
2
- export { ExecutionsListPage } from './chunk-UNRFUBE5.js';
3
- export { ExecutionDetailPage } from './chunk-7ZVWGAVI.js';
4
- import './chunk-P6EUVE3U.js';
2
+ export { ExecutionsListPage } from './chunk-BEOGOFNQ.js';
3
+ export { ExecutionDetailPage } from './chunk-YA73BHRQ.js';
4
+ import './chunk-WQ7CETWI.js';
5
5
  import './chunk-QBFAJNUC.js';
6
6
  import './chunk-ONVGFVNH.js';
7
7
  import './chunk-JL7CASN5.js';
8
- import './chunk-UUELRAQ2.js';
8
+ import './chunk-O6E247J6.js';
9
9
  import './chunk-D3UWK7GY.js';
10
10
  import './chunk-UZG3ZIQM.js';
11
11
  import './chunk-PJAWNFJV.js';
12
- import './chunk-NFBNWXJH.js';
12
+ import './chunk-L2UWPFJM.js';
13
13
  import './chunk-CFCUM4CN.js';
14
14
  import './chunk-UULVIT25.js';
15
15
  import './chunk-NTWG3CJX.js';
package/dist/history.js CHANGED
@@ -1,9 +1,9 @@
1
- export { HistoryPage } from './chunk-MESOVECH.js';
2
- import './chunk-UUELRAQ2.js';
1
+ export { HistoryPage } from './chunk-EPYVZPGU.js';
2
+ import './chunk-O6E247J6.js';
3
3
  import './chunk-D3UWK7GY.js';
4
4
  import './chunk-UZG3ZIQM.js';
5
5
  import './chunk-PJAWNFJV.js';
6
- import './chunk-NFBNWXJH.js';
6
+ import './chunk-L2UWPFJM.js';
7
7
  import './chunk-CFCUM4CN.js';
8
8
  import './chunk-UULVIT25.js';
9
9
  import './chunk-NTWG3CJX.js';