@burdenoff/fluidgrids-fe-sdk 2026.1111.21 → 2026.1111.22

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 (62) hide show
  1. package/README.md +13 -0
  2. package/dist/{AiStudioPage-CJdzRL26.js → AiStudioPage-DIfF4LhQ.js} +5 -5
  3. package/dist/{DataSinkDashboardPage-hrwQSvks.js → DataSinkDashboardPage-DDvNPS8Z.js} +1 -1
  4. package/dist/{DataTablesPage-BZy2z0LB.js → DataTablesPage-BpnF13UT.js} +9 -1
  5. package/dist/{ExecutionDetailPage-DKp421Fj.js → ExecutionDetailPage-DYLWtHRG.js} +5 -5
  6. package/dist/{ExecutionsListPage-DwJQfDPt.js → ExecutionsListPage-D63aCXJH.js} +4 -4
  7. package/dist/{FluidGridsProvider-CbY91ZQq.js → FluidGridsProvider-CWyQ8ziM.js} +2 -1
  8. package/dist/{HistoryPage-BLXZJDoJ.js → HistoryPage-CNXgUMb0.js} +1 -1
  9. package/dist/{InsightsPage-ChnoW5U4.js → InsightsPage-Duo83yAM.js} +1 -1
  10. package/dist/{MissingNodesInstallModal-mYFfy9Gg.js → MissingNodesInstallModal-Q3RYBvS8.js} +1 -1
  11. package/dist/{QuotaExhaustedDialog-DWm_YWL7.js → QuotaExhaustedDialog-ChBoJnRo.js} +3 -2
  12. package/dist/{SettingsPage-CXoKX0px.js → SettingsPage-DI_vIG7t.js} +2 -2
  13. package/dist/{TemplateCard-HIMsb47R.js → TemplateCard-6W2q2wiK.js} +4 -3
  14. package/dist/{TemplateConfigurationModal-BNtbJ2fv.js → TemplateConfigurationModal-qNQGP7cm.js} +1 -1
  15. package/dist/{TemplateDetailPanel-C6Zh2WRF.js → TemplateDetailPanel-CQvYqhVO.js} +1 -1
  16. package/dist/{TemplatePreview-_wUMSwh_.js → TemplatePreview-t3251W_n.js} +4 -4
  17. package/dist/{TemplatesPage-DBfL-ao9.js → TemplatesPage-Bvg6R2P9.js} +6 -5
  18. package/dist/{WorkflowBuilder-CYmpQtIQ.js → WorkflowBuilder-C-hgvww2.js} +3 -3
  19. package/dist/{WorkflowBuilder-CMZi6wQE.js → WorkflowBuilder-DdvSGsxr.js} +8 -8
  20. package/dist/{WorkflowSearchRedirect-iWzvY9Qo.js → WorkflowSearchRedirect-33Vs4FKc.js} +1 -1
  21. package/dist/{WorkflowsList-C8aoqtRE.js → WorkflowsList-C3bHLpSv.js} +147 -22
  22. package/dist/agent-tools.js +1 -1
  23. package/dist/{agentTools-CrEWQ5st.js → agentTools-BjhxAdlt.js} +3 -3
  24. package/dist/{canvasNoteTools-6BQYNCee.js → canvasNoteTools-CZEFFhRp.js} +2 -2
  25. package/dist/{code-editor-field-CoRq10k7.js → code-editor-field-CfP0QYUD.js} +1 -1
  26. package/dist/executions.js +2 -2
  27. package/dist/{flow-builder-Dwev-C_g.js → flow-builder-CE8cNXNi.js} +16 -73
  28. package/dist/fluidgridsEvents-Dm5CaHtr.js +162 -0
  29. package/dist/history.js +1 -1
  30. package/dist/{index-6JR2vD9J.d.ts → index-7eJQwsNS.d.ts} +3 -19
  31. package/dist/index.d.ts +2 -1
  32. package/dist/index.js +29 -27
  33. package/dist/{node-detail-view-BFBSKj5w.js → node-detail-view-BoR0vYZ3.js} +5 -5
  34. package/dist/{node-editor-tab-body-Cz9kOlxu.js → node-editor-tab-body-DxMbKspp.js} +2 -2
  35. package/dist/observability.d.ts +1 -1
  36. package/dist/observability.js +2 -2
  37. package/dist/{popover-xPh0iIzy.js → popover-B1aKz7DC.js} +1 -1
  38. package/dist/{quick-config-panel-Ym05lyGn.js → quick-config-panel-DXvLJdeW.js} +3 -3
  39. package/dist/quota-Cdt8yz7N.js +152 -0
  40. package/dist/quota.d.ts +3 -0
  41. package/dist/quota.js +4 -0
  42. package/dist/runsQuota-DsniKiSg.d.ts +20 -0
  43. package/dist/runsQuota-DvXR6mRN.js +100 -0
  44. package/dist/{schedule-panel-54D5W5Qk.js → schedule-panel-CY6S4JMd.js} +5 -5
  45. package/dist/settings.js +1 -1
  46. package/dist/{sidebar-node-editor-LL3ofDN7.js → sidebar-node-editor-FU3fvOjh.js} +3 -3
  47. package/dist/templates.js +2 -2
  48. package/dist/{uiMarkTools-nlmzsHQM.js → uiMarkTools-DZ6akjQK.js} +1 -1
  49. package/dist/useActionParam-B0ebTZmg.js +83 -0
  50. package/dist/{useDurableParity-BScby67i.js → useDurableParity-BApRraSO.js} +1 -1
  51. package/dist/{useExecutions-B0VzQcY2.js → useExecutions-C2a4EcvC.js} +2 -2
  52. package/dist/{useObservability-FfQGgW6W.js → useObservability-BmbeK5bG.js} +2 -2
  53. package/dist/{useRunHistory-BZJg72kd.js → useRunHistory-CqfDFRzr.js} +1 -1
  54. package/dist/{useWorkflowCodeExport-CUWMlJbi.js → useWorkflowCodeExport-DebpM48M.js} +1 -1
  55. package/dist/{useWorkflows-Czz5DlL0.js → useWorkflows-D1-rYzGK.js} +2 -2
  56. package/dist/workflow-builder.js +4 -4
  57. package/dist/workflow-pages.d.ts +1 -1
  58. package/dist/workflow-pages.js +14 -14
  59. package/dist/workflows-list.d.ts +6 -0
  60. package/dist/workflows-list.js +3 -2
  61. package/package.json +5 -1
  62. package/dist/fluidgridsEvents-CNdcrUNN.js +0 -310
@@ -0,0 +1,83 @@
1
+ "use client";
2
+ import { useCallback, useEffect, useRef } from "react";
3
+ import { useSearchParams } from "react-router";
4
+
5
+ // src/hooks/useActionParam.ts
6
+ /**
7
+ * One-shot `?action=` links (BOFF-10854).
8
+ *
9
+ * The shell's "+ New" menu links to pages with an action in the query string,
10
+ * e.g. `/workflows/list?action=import`. The page opens the matching dialog
11
+ * once and then removes the parameter (history replace), so reload, back and
12
+ * a later re-render do not open it again.
13
+ *
14
+ * const request = useActionParam("import", importPermission);
15
+ * <WorkflowImportDialog
16
+ * openRequested={request.requested}
17
+ * onOpenRequestHandled={request.handled}
18
+ * />
19
+ */
20
+ const ACTION_PARAM = "action";
21
+ /** Values the fe-sdk pages act on. */
22
+ const ACTION_PARAM_VALUES = {
23
+ /** Workflows list: the workflow import dialog. */
24
+ import: "import",
25
+ /** Workflows list: the create-folder dialog. */
26
+ newFolder: "new-folder",
27
+ /** Data tables: the create-table dialog. */
28
+ new: "new"
29
+ };
30
+ const OPEN_GATE = {
31
+ allowed: true,
32
+ isLoading: false
33
+ };
34
+ /** Returns a copy of `params` without the action parameter. */
35
+ function withoutActionParam(params) {
36
+ const next = new URLSearchParams(params);
37
+ next.delete(ACTION_PARAM);
38
+ return next;
39
+ }
40
+ /**
41
+ * Watches `?action=<action>`. While `gate` is loading the request waits; when
42
+ * the gate denies it the parameter is dropped without opening anything (the
43
+ * page's own button already explains the missing permission).
44
+ */
45
+ function useActionParam(action, gate = OPEN_GATE) {
46
+ const [searchParams, setSearchParams] = useSearchParams();
47
+ const present = searchParams.get(ACTION_PARAM) === action;
48
+ const handled = useCallback(() => {
49
+ setSearchParams((prev) => withoutActionParam(prev), { replace: true });
50
+ }, [setSearchParams]);
51
+ const denied = present && !gate.isLoading && !gate.allowed;
52
+ useEffect(() => {
53
+ if (denied) handled();
54
+ }, [denied, handled]);
55
+ return {
56
+ requested: present && !gate.isLoading && gate.allowed,
57
+ handled
58
+ };
59
+ }
60
+ /**
61
+ * Fires `open` then `onHandled` once each time `requested` turns true. A
62
+ * change of callback identity while the request is still pending (the URL
63
+ * update has not landed yet) does not fire it again.
64
+ */
65
+ function useOpenRequest(requested, open, onHandled) {
66
+ const fired = useRef(false);
67
+ useEffect(() => {
68
+ if (!requested) {
69
+ fired.current = false;
70
+ return;
71
+ }
72
+ if (fired.current) return;
73
+ fired.current = true;
74
+ open();
75
+ onHandled?.();
76
+ }, [
77
+ requested,
78
+ open,
79
+ onHandled
80
+ ]);
81
+ }
82
+
83
+ export { useOpenRequest as i, ACTION_PARAM_VALUES as n, useActionParam as r, ACTION_PARAM as t };
@@ -2,7 +2,7 @@
2
2
  import { _ as throwIfResultError, m as describeOperationError, n as getFluidGridsClient } from "./client-C9XSzSXr.js";
3
3
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
4
4
  import { $r as WorkflowRunPendingDocument, Qr as WorkflowRunMetadataDocument, jn as SetWorkflowRunVersioningOverrideDocument, ni as WorkflowRunsCountDocument, tt as DurableParityRunFieldsDocument } from "./graphql-operation-types-kX-MMjgW.js";
5
- import { _ as statusCountFilter, d as STATUS_COUNT_GROUP_BY, v as statusCountsOf } from "./useExecutions-B0VzQcY2.js";
5
+ import { _ as statusCountFilter, d as STATUS_COUNT_GROUP_BY, v as statusCountsOf } from "./useExecutions-C2a4EcvC.js";
6
6
  import { useCallback, useEffect, useRef, useState } from "react";
7
7
  import { Icon } from "@iconify/react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -3,8 +3,8 @@ import { N as useExecutionsStore, _ as throwIfResultError, d as emitFluidGridsEv
3
3
  import { Gn as TerminateExecutionDocument, Lt as PauseExecutionDocument, cn as RetryNodeDocument, ct as ExecutionStatsDocument, lt as ExecutionsListDocument, ot as ExecutionDetailDocument, qn as TriggerWorkflowDocument, sn as ResumeExecutionDocument, v as CancelExecutionDocument } from "./graphql-operation-types-kX-MMjgW.js";
4
4
  import { hD as RunGroupBy, yP as VersioningBehavior } from "./graphql-types-CDKVWH2R.js";
5
5
  import { c as REPLAY_WORKFLOW_RUN, l as RETRY_WORKFLOW_RUNS } from "./operations-HU-xb78H.js";
6
- import { _n as openRunQuotaUpgradePrompt, gn as useFluidGridsAnalytics } from "./FluidGridsProvider-CbY91ZQq.js";
7
- import { i as emitRunStarted } from "./fluidgridsEvents-CNdcrUNN.js";
6
+ import { _n as openRunQuotaUpgradePrompt, gn as useFluidGridsAnalytics } from "./FluidGridsProvider-CWyQ8ziM.js";
7
+ import { i as emitRunStarted } from "./fluidgridsEvents-Dm5CaHtr.js";
8
8
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
9
9
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
10
10
 
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { _ as throwIfResultError, d as emitFluidGridsEvent, m as describeOperationError, n as getFluidGridsClient } from "./client-C9XSzSXr.js";
3
- import { _n as openRunQuotaUpgradePrompt, gn as useFluidGridsAnalytics } from "./FluidGridsProvider-CbY91ZQq.js";
3
+ import { _n as openRunQuotaUpgradePrompt, gn as useFluidGridsAnalytics } from "./FluidGridsProvider-CWyQ8ziM.js";
4
4
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
5
- import { i as emitRunStarted } from "./fluidgridsEvents-CNdcrUNN.js";
5
+ import { i as emitRunStarted } from "./fluidgridsEvents-Dm5CaHtr.js";
6
6
  import { a as OBSERVABILITY_DATA_SINKS, c as REPLAY_WORKFLOW_RUN, d as UPDATE_LOG_STREAM_DESTINATION, i as OBSERVABILITY_DASHBOARD_SUMMARY, l as RETRY_WORKFLOW_RUNS, n as DELETE_LOG_STREAM_DESTINATION, o as OBSERVABILITY_DATA_SINK_DATA, r as LOG_STREAM_DESTINATIONS, s as OBSERVABILITY_FAILED_RUNS, t as CREATE_LOG_STREAM_DESTINATION, u as TEST_LOG_STREAM_DESTINATION } from "./operations-HU-xb78H.js";
7
7
  import { useCallback, useEffect, useState } from "react";
8
8
 
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { _ as throwIfResultError, m as describeOperationError, n as getFluidGridsClient, r as getFluidGridsClientSafe } from "./client-C9XSzSXr.js";
3
- import { Dn as payloadFromCardValues, En as parseRawSignalPayload, kn as signalPayloadCard } from "./FluidGridsProvider-CbY91ZQq.js";
3
+ import { Dn as payloadFromCardValues, En as parseRawSignalPayload, kn as signalPayloadCard } from "./FluidGridsProvider-CWyQ8ziM.js";
4
4
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
5
5
  import { Kn as TerminateWorkflowRunDocument, Kr as WorkflowRunDeterminismStatusDocument, Nn as SignalWorkflowRunDocument, Zr as WorkflowRunHistoryDocument, ei as WorkflowRunStackTraceDocument, mn as RunEventAppendedDocument, nt as DurableRunFieldsDocument } from "./graphql-operation-types-kX-MMjgW.js";
6
6
  import { yd as ExecutionKind } from "./graphql-types-CDKVWH2R.js";
@@ -2,7 +2,7 @@
2
2
  import { _ as throwIfResultError, m as describeOperationError, n as getFluidGridsClient } from "./client-C9XSzSXr.js";
3
3
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
4
4
  import { dt as ExportWorkflowCodeDocument } from "./graphql-operation-types-kX-MMjgW.js";
5
- import { t as QuotaExhaustedDialog } from "./QuotaExhaustedDialog-DWm_YWL7.js";
5
+ import { t as QuotaExhaustedDialog } from "./QuotaExhaustedDialog-ChBoJnRo.js";
6
6
  import { CF as WorkflowExportFormat, Fd as FidelityLevel } from "./graphql-types-CDKVWH2R.js";
7
7
  import { useCallback, useEffect, useRef, useState } from "react";
8
8
  import { jsx } from "react/jsx-runtime";
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import { _ as throwIfResultError, d as emitFluidGridsEvent, f as emitOperationErrorEvent, n as getFluidGridsClient, x as getFluidGridsConfig } from "./client-C9XSzSXr.js";
3
3
  import { $ as DuplicateWorkflowDocument, A as CreateWorkflowDefinitionDocument, B as DeactivateWorkflowDefinitionDocument, Bt as PreviewN8nImportDocument, Dr as WorkflowDefinitionForBuilderDocument, Er as WorkflowDefinitionDocument, L as CreateWorkflowVersionDocument, Or as WorkflowDefinitionsDocument, R as DashboardSummaryDocument, Si as WorkflowVersionsDocument, W as DeleteWorkflowDefinitionDocument, bt as ImportWorkflowDocument, n as ActivateWorkflowDefinitionDocument, on as RestoreWorkflowVersionDocument, or as UpdateWorkflowDefinitionDocument, qn as TriggerWorkflowDocument, qr as WorkflowRunDocument, ri as WorkflowRunsDocument } from "./graphql-operation-types-kX-MMjgW.js";
4
- import { _n as openRunQuotaUpgradePrompt, gn as useFluidGridsAnalytics } from "./FluidGridsProvider-CbY91ZQq.js";
4
+ import { _n as openRunQuotaUpgradePrompt, gn as useFluidGridsAnalytics } from "./FluidGridsProvider-CWyQ8ziM.js";
5
5
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
6
- import { d as runTriggerFromMode, i as emitRunStarted, l as emitWorkflowPublished, s as emitWorkflowCreated } from "./fluidgridsEvents-CNdcrUNN.js";
6
+ import { d as runTriggerFromMode, i as emitRunStarted, l as emitWorkflowPublished, s as emitWorkflowCreated } from "./fluidgridsEvents-Dm5CaHtr.js";
7
7
  import { s as takePrefetchedWorkflowForBuilder } from "./workflowRouteData-BkfVOc-O.js";
8
8
  import { useCallback, useEffect, useMemo, useState } from "react";
9
9
 
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { n as WorkflowBuilderCore, t as WorkflowBuilder } from "./WorkflowBuilder-CYmpQtIQ.js";
3
- import { t as WorkflowBuilder$1 } from "./WorkflowBuilder-CMZi6wQE.js";
2
+ import { n as WorkflowBuilderCore, t as WorkflowBuilder } from "./WorkflowBuilder-C-hgvww2.js";
3
+ import { t as WorkflowBuilder$1 } from "./WorkflowBuilder-DdvSGsxr.js";
4
4
  import { H as useFlowStore } from "./node-operation-selection--oy-yEq_.js";
5
- import { m as refetchStoreNodes } from "./FluidGridsProvider-CbY91ZQq.js";
6
- import { t as WorkflowSearchRedirect } from "./WorkflowSearchRedirect-iWzvY9Qo.js";
5
+ import { m as refetchStoreNodes } from "./FluidGridsProvider-CWyQ8ziM.js";
6
+ import { t as WorkflowSearchRedirect } from "./WorkflowSearchRedirect-33Vs4FKc.js";
7
7
 
8
8
  export { WorkflowBuilder, WorkflowBuilderCore, WorkflowBuilder$1 as WorkflowBuilderPage, WorkflowSearchRedirect, refetchStoreNodes, useFlowStore };
@@ -2,7 +2,7 @@
2
2
  import { n as WorkflowsList_d_exports } from "./WorkflowsList-CcNDQge5.js";
3
3
  import { a as WorkflowSearchRedirect_d_exports, o as WorkflowBuilder } from "./index-DjiFgEQl.js";
4
4
  import { i as TemplatePreview_d_exports, n as TemplatesPage_d_exports } from "./TemplatesPage-BG3H-6v6.js";
5
- import { Li as ApprovalInboxPage_d_exports, Qi as RunnersPage_d_exports, Sa as VariablesPage_d_exports, cAa as InsightsPageProps, dAa as DataSinkDashboardPage_d_exports, gi as DataTablesPage_d_exports, jAa as AiStudioPage_d_exports, lAa as InsightsPage_d_exports, qi as TaskQueuesPage_d_exports } from "./index-6JR2vD9J.js";
5
+ import { EAa as AiStudioPage_d_exports, Hi as TaskQueuesPage_d_exports, Mi as ApprovalInboxPage_d_exports, _a as VariablesPage_d_exports, di as DataTablesPage_d_exports, iAa as InsightsPage_d_exports, oAa as DataSinkDashboardPage_d_exports, qi as RunnersPage_d_exports, rAa as InsightsPageProps } from "./index-7eJQwsNS.js";
6
6
  import { i as ExecutionsListPage_d_exports, n as ExecutionDetailPage_d_exports } from "./ExecutionDetailPage-DvQ667OE.js";
7
7
  import { n as HistoryPage_d_exports } from "./HistoryPage-BLoRpJ1R.js";
8
8
  import { n as NodesPage_d_exports } from "./NodesPage-DEbnz9iU.js";
@@ -54,25 +54,25 @@ function createWorkflowPages(importers) {
54
54
  * loader, so it costs a host's first load about a kilobyte.
55
55
  */
56
56
  const pages = createWorkflowPages({
57
- WorkflowsList: () => import("./WorkflowsList-C8aoqtRE.js").then((n) => n.n),
58
- WorkflowBuilderPage: () => import("./WorkflowBuilder-CMZi6wQE.js").then((n) => n.n).then((m) => ({ WorkflowBuilderPage: m.WorkflowBuilder })),
59
- WorkflowSearchRedirect: () => import("./WorkflowSearchRedirect-iWzvY9Qo.js").then((n) => n.n),
60
- TemplatePreview: () => import("./TemplatePreview-_wUMSwh_.js").then((n) => n.n),
61
- AiStudioPage: () => import("./AiStudioPage-CJdzRL26.js").then((n) => n.n),
62
- ExecutionsListPage: () => import("./ExecutionsListPage-DwJQfDPt.js").then((n) => n.n),
63
- ExecutionDetailPage: () => import("./ExecutionDetailPage-DKp421Fj.js").then((n) => n.n),
64
- HistoryPage: () => import("./HistoryPage-BLXZJDoJ.js").then((n) => n.n),
65
- TemplatesPage: () => import("./TemplatesPage-DBfL-ao9.js").then((n) => n.n),
57
+ WorkflowsList: () => import("./WorkflowsList-C3bHLpSv.js").then((n) => n.n),
58
+ WorkflowBuilderPage: () => import("./WorkflowBuilder-DdvSGsxr.js").then((n) => n.n).then((m) => ({ WorkflowBuilderPage: m.WorkflowBuilder })),
59
+ WorkflowSearchRedirect: () => import("./WorkflowSearchRedirect-33Vs4FKc.js").then((n) => n.n),
60
+ TemplatePreview: () => import("./TemplatePreview-t3251W_n.js").then((n) => n.n),
61
+ AiStudioPage: () => import("./AiStudioPage-DIfF4LhQ.js").then((n) => n.n),
62
+ ExecutionsListPage: () => import("./ExecutionsListPage-D63aCXJH.js").then((n) => n.n),
63
+ ExecutionDetailPage: () => import("./ExecutionDetailPage-DYLWtHRG.js").then((n) => n.n),
64
+ HistoryPage: () => import("./HistoryPage-CNXgUMb0.js").then((n) => n.n),
65
+ TemplatesPage: () => import("./TemplatesPage-Bvg6R2P9.js").then((n) => n.n),
66
66
  NodesPage: () => import("./NodesPage-Bf5PhfBK.js").then((n) => n.n),
67
- SettingsPage: () => import("./SettingsPage-CXoKX0px.js").then((n) => n.n),
68
- InsightsPage: () => import("./InsightsPage-ChnoW5U4.js").then((n) => n.r),
69
- ErrorAnalyticsPage: () => import("./InsightsPage-ChnoW5U4.js").then((n) => n.r),
70
- DataSinkDashboardPage: () => import("./DataSinkDashboardPage-hrwQSvks.js").then((n) => n.n),
67
+ SettingsPage: () => import("./SettingsPage-DI_vIG7t.js").then((n) => n.n),
68
+ InsightsPage: () => import("./InsightsPage-Duo83yAM.js").then((n) => n.r),
69
+ ErrorAnalyticsPage: () => import("./InsightsPage-Duo83yAM.js").then((n) => n.r),
70
+ DataSinkDashboardPage: () => import("./DataSinkDashboardPage-DDvNPS8Z.js").then((n) => n.n),
71
71
  VariablesPage: () => import("./VariablesPage-67WR_lVE.js").then((n) => n.n),
72
72
  RunnersPage: () => import("./RunnersPage-CLCOCclc.js").then((n) => n.n),
73
73
  TaskQueuesPage: () => import("./TaskQueuesPage-9VgSnLdL.js").then((n) => n.r),
74
74
  ApprovalInboxPage: () => import("./ApprovalInboxPage-dbBDSJ-f.js").then((n) => n.n),
75
- DataTablesPage: () => import("./DataTablesPage-BZy2z0LB.js").then((n) => n.n)
75
+ DataTablesPage: () => import("./DataTablesPage-BpnF13UT.js").then((n) => n.n)
76
76
  });
77
77
  /** Every workflow page this entry exports. */
78
78
  const WORKFLOW_PAGE_NAMES = pages.names;
@@ -1,3 +1,9 @@
1
1
 
2
2
  import { t as WorkflowsList } from "./WorkflowsList-CcNDQge5.js";
3
+ export declare const ACTION_PARAM = "action";
4
+ export declare const ACTION_PARAM_VALUES: {
5
+ readonly import: "import";
6
+ readonly newFolder: "new-folder";
7
+ readonly new: "new";
8
+ };
3
9
  export { WorkflowsList };
@@ -1,4 +1,5 @@
1
1
  "use client";
2
- import { t as WorkflowsList } from "./WorkflowsList-C8aoqtRE.js";
2
+ import { t as WorkflowsList } from "./WorkflowsList-C3bHLpSv.js";
3
+ import { n as ACTION_PARAM_VALUES, t as ACTION_PARAM } from "./useActionParam-B0ebTZmg.js";
3
4
 
4
- export { WorkflowsList };
5
+ export { ACTION_PARAM, ACTION_PARAM_VALUES, WorkflowsList };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/fluidgrids-fe-sdk",
3
- "version": "2026.1111.21",
3
+ "version": "2026.1111.22",
4
4
  "description": "FluidGrids Workflow Builder SDK - Embeddable visual workflow automation",
5
5
  "type": "module",
6
6
  "imports": {
@@ -74,6 +74,10 @@
74
74
  "types": "./dist/flags.d.ts",
75
75
  "import": "./dist/flags.js"
76
76
  },
77
+ "./quota": {
78
+ "types": "./dist/quota.d.ts",
79
+ "import": "./dist/quota.js"
80
+ },
77
81
  "./styles.css": "./dist/styles.css"
78
82
  },
79
83
  "files": [
@@ -1,310 +0,0 @@
1
- "use client";
2
- // src/billing/quota.ts
3
- /**
4
- * Plan-quota refusals for the FluidGrids SDK.
5
- *
6
- * wspace-workflow-svc meters two quotas with `@usage`, and the gateway refuses
7
- * a call past either one with `429 QUOTA_EXHAUSTED`:
8
- *
9
- * - `fluidgrids.runs.monthly` — every mutation that starts a run:
10
- * `triggerWorkflow`, `runFromNode`, `replayWorkflowRun`, `retryWorkflowRuns`
11
- * and `listenForWebhookTestEvent`.
12
- * - `fluidgrids.workflows.count` — the mutations that create a workflow
13
- * (save, duplicate, template import). Those keep their local
14
- * `QuotaExhaustedDialog`.
15
- * - `fluidgrids.nodes.count` — node additions are counted by workflow save;
16
- * the same save dialog handles its refusal.
17
- *
18
- * A run refusal opens the shell's shared upgrade prompt — see
19
- * `openRunQuotaUpgradePrompt` in `./upgradePrompt`. This module is the pure
20
- * detection half, so it imports nothing from `@burdenoff/fe-libs`.
21
- *
22
- * ★★ Why this does not just call fe-libs `isQuotaExhaustedError`. That helper
23
- * reads the Apollo 3 shapes (`graphQLErrors`, `networkError.result.errors`, a
24
- * code in the message). Under Apollo 4 — what every host runs — the refusal
25
- * never takes those shapes:
26
- *
27
- * - the gateway answers `429`, and Apollo 4's HTTP link turns any non-2xx
28
- * `application/json` response into a `ServerError` whose GraphQL body is
29
- * only in `bodyText` (message: "Response not successful: Received status
30
- * code 429");
31
- * - a 2xx GraphQL error arrives as `CombinedGraphQLErrors`, whose list is
32
- * `.errors`, not `.graphQLErrors`;
33
- * - `throwIfResultError` wraps either one in a plain `Error`, keeping the
34
- * original as `cause`.
35
- *
36
- * None of those match, so the refusal read as an ordinary failure. This walker
37
- * reads all of them, and the Apollo 3 shapes too.
38
- */
39
- /** The monthly run allowance every run-starting mutation is metered against. */
40
- const RUNS_QUOTA_NAME = "fluidgrids.runs.monthly";
41
- /** The workflow-count allowance save / duplicate / template import consume. */
42
- const WORKFLOWS_QUOTA_NAME = "fluidgrids.workflows.count";
43
- /**
44
- * Where an upgrade CTA sends the user: the plan picker, not the billing
45
- * overview. Matches the shared `UpgradePromptModal` default and the shell nav.
46
- */
47
- const BILLING_PLANS_PATH = "/billing/plans";
48
- const QUOTA_EXHAUSTED_CODE = "QUOTA_EXHAUSTED";
49
- const QUOTA_NOT_PROVISIONED_CODE = "QUOTA_NOT_PROVISIONED";
50
- function asRecord$1(value) {
51
- return typeof value === "object" && value !== null ? value : null;
52
- }
53
- /** The `extensions` of each entry of an `errors`-like list. */
54
- function extensionsOfList(list) {
55
- if (!Array.isArray(list)) return [];
56
- const found = [];
57
- for (const entry of list) {
58
- const extensions = asRecord$1(asRecord$1(entry)?.extensions);
59
- if (extensions) found.push(extensions);
60
- }
61
- return found;
62
- }
63
- /** The GraphQL `errors[].extensions` inside a raw response body, if it is JSON. */
64
- function extensionsOfBody(bodyText) {
65
- if (typeof bodyText !== "string" || !bodyText.includes("errors")) return [];
66
- try {
67
- return extensionsOfList(asRecord$1(JSON.parse(bodyText))?.errors);
68
- } catch {
69
- return [];
70
- }
71
- }
72
- /** Bounds the `cause` walk; real chains are one or two links long. */
73
- const MAX_CAUSE_DEPTH = 5;
74
- /**
75
- * Every `extensions` object reachable on a thrown value, across the Apollo 3
76
- * and Apollo 4 shapes and the `cause` chain `throwIfResultError` adds.
77
- */
78
- function collectExtensions(error) {
79
- const found = [];
80
- const seen = /* @__PURE__ */ new Set();
81
- let current = error;
82
- for (let depth = 0; depth < MAX_CAUSE_DEPTH; depth += 1) {
83
- const host = asRecord$1(current);
84
- if (!host || seen.has(host)) break;
85
- seen.add(host);
86
- const direct = asRecord$1(host.extensions);
87
- if (direct) found.push(direct);
88
- found.push(...extensionsOfList(host.errors));
89
- found.push(...extensionsOfList(host.graphQLErrors));
90
- const networkError = asRecord$1(host.networkError);
91
- found.push(...extensionsOfList(asRecord$1(networkError?.result)?.errors));
92
- found.push(...extensionsOfBody(networkError?.bodyText));
93
- found.push(...extensionsOfList(asRecord$1(host.result)?.errors));
94
- found.push(...extensionsOfBody(host.bodyText));
95
- current = host.cause;
96
- }
97
- return found;
98
- }
99
- /** Every GraphQL `extensions.code` carried by `error` or its causes. */
100
- function errorCodesOf(error) {
101
- return collectExtensions(error).map((ext) => ext.code).filter((code) => typeof code === "string");
102
- }
103
- function stringField(extensions, key) {
104
- const value = extensions[key];
105
- return typeof value === "string" && value.length > 0 ? value : null;
106
- }
107
- /**
108
- * The refusal kind one GraphQL `extensions` object reports, or null.
109
- *
110
- * The gateway sets both `code` and `quotaBlock` on a quota refusal
111
- * (`sendQuotaExhausted` in wspace-public-gateway); either is enough here, so
112
- * a refusal relayed with only one of them (a proxy, an older gateway build)
113
- * still reads as one.
114
- */
115
- function refusalKindOf(extensions) {
116
- if (extensions.code === "QUOTA_NOT_PROVISIONED" || extensions.quotaBlock === "not-provisioned") return "not-provisioned";
117
- if (extensions.code === "QUOTA_EXHAUSTED" || extensions.quotaBlock === "exhausted") return "exhausted";
118
- return null;
119
- }
120
- /**
121
- * The quota refusal carried by `error`, or null when it is not one.
122
- *
123
- * Keyed on `extensions.code` (or the gateway's `extensions.quotaBlock`), never
124
- * on the HTTP status or the message: both refusals are 429s, and only those
125
- * fields tell "used up" from "never granted". `not-provisioned` wins when both
126
- * appear.
127
- */
128
- function findQuotaRefusal(error) {
129
- const all = collectExtensions(error);
130
- const notProvisioned = all.find((ext) => refusalKindOf(ext) === "not-provisioned");
131
- if (notProvisioned) return {
132
- kind: "not-provisioned",
133
- quotaName: stringField(notProvisioned, "quotaName"),
134
- limitLeft: null
135
- };
136
- const exhausted = all.find((ext) => refusalKindOf(ext) === "exhausted");
137
- if (exhausted) {
138
- const limitLeft = exhausted.limitLeft;
139
- return {
140
- kind: "exhausted",
141
- quotaName: stringField(exhausted, "quotaName"),
142
- limitLeft: typeof limitLeft === "number" ? limitLeft : null
143
- };
144
- }
145
- return null;
146
- }
147
- /** True when `error` is an exhausted (not merely unprovisioned) plan quota. */
148
- function isQuotaExhaustedFailure(error) {
149
- return findQuotaRefusal(error)?.kind === "exhausted";
150
- }
151
-
152
- // src/analytics/fluidgridsEvents.ts
153
- /** `component` stamped on every event so devtools/OTel can tell the emitter. */
154
- const FLUIDGRIDS_ANALYTICS_COMPONENT = "fluidgrids-fe-sdk";
155
- /** Upper bound for a slug-like dimension; anything longer is not a slug. */
156
- const MAX_DIMENSION_LENGTH = 64;
157
- const SLUG_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_./:-]*$/;
158
- /**
159
- * Keep a dimension only when it is a short slug (`integration/slack`,
160
- * `trigger_webhook`, `marketing`). Anything else — spaces, free text, a very
161
- * long value — is dropped rather than risk sending user data.
162
- */
163
- function toDimension(value) {
164
- if (typeof value !== "string") return void 0;
165
- const trimmed = value.trim();
166
- if (!trimmed || trimmed.length > MAX_DIMENSION_LENGTH) return void 0;
167
- return SLUG_PATTERN.test(trimmed) ? trimmed : void 0;
168
- }
169
- /** Non-empty string id, or undefined. */
170
- function idOrUndefined(value) {
171
- return typeof value === "string" && value.length > 0 ? value : void 0;
172
- }
173
- /** A finite, non-negative integer count, or undefined. */
174
- function countOrUndefined(value) {
175
- return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.round(value) : void 0;
176
- }
177
- function emit(bus, name, payload) {
178
- if (!bus) return;
179
- const clean = Object.fromEntries(Object.entries(payload).filter(([, value]) => value !== void 0));
180
- try {
181
- bus.emit(name, clean, { component: FLUIDGRIDS_ANALYTICS_COMPONENT });
182
- } catch (error) {
183
- console.warn(`[fluidgrids analytics] failed to emit ${name}`, error);
184
- }
185
- }
186
- function asRecord(value) {
187
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
188
- }
189
- /**
190
- * The executable node list of a workflow definition, wherever it sits: the
191
- * flow store's `{ nodes }`, a saved `definitionJson` (`{ data: { nodes } }`) or
192
- * a raw list.
193
- */
194
- function nodesOf(definition) {
195
- if (Array.isArray(definition)) return definition;
196
- const record = asRecord(definition);
197
- if (!record) return [];
198
- if (Array.isArray(record.nodes)) return record.nodes;
199
- const data = asRecord(record.data);
200
- if (data && Array.isArray(data.nodes)) return data.nodes;
201
- return [];
202
- }
203
- function isTriggerNode(node) {
204
- if ((typeof node.type === "string" ? node.type.toLowerCase() : "").includes("trigger")) return true;
205
- const data = asRecord(node.data);
206
- return data?.isTrigger === true || data?.category === "trigger";
207
- }
208
- /** Node-type slug of the workflow's trigger node, when it has one. */
209
- function triggerTypeOf(definition) {
210
- const trigger = nodesOf(definition).find(isTriggerNode);
211
- return trigger ? toDimension(trigger.type) : void 0;
212
- }
213
- /** Number of executable nodes on the canvas. */
214
- function nodeCountOf(definition) {
215
- const nodes = nodesOf(definition);
216
- return nodes.length > 0 ? nodes.length : void 0;
217
- }
218
- /** `fluidgrids.workflow.created` — a new workflow exists in the workspace. */
219
- function emitWorkflowCreated(bus, fact) {
220
- emit(bus, "fluidgrids.workflow.created", {
221
- workspaceId: idOrUndefined(fact.workspaceId),
222
- workflowId: idOrUndefined(fact.workflowId),
223
- source: fact.source,
224
- triggerType: triggerTypeOf(fact.definition),
225
- nodeCount: nodeCountOf(fact.definition)
226
- });
227
- }
228
- /** `fluidgrids.workflow.published` — a version was activated. */
229
- function emitWorkflowPublished(bus, fact) {
230
- emit(bus, "fluidgrids.workflow.published", {
231
- workspaceId: idOrUndefined(fact.workspaceId),
232
- workflowId: idOrUndefined(fact.workflowId),
233
- triggerType: triggerTypeOf(fact.definition),
234
- nodeCount: nodeCountOf(fact.definition)
235
- });
236
- }
237
- /** `fluidgrids.workflow.run_started` — the backend accepted a run. */
238
- function emitRunStarted(bus, fact) {
239
- emit(bus, "fluidgrids.workflow.run_started", {
240
- workspaceId: idOrUndefined(fact.workspaceId),
241
- workflowId: idOrUndefined(fact.workflowId),
242
- executionId: idOrUndefined(fact.executionId),
243
- trigger: fact.trigger
244
- });
245
- }
246
- /**
247
- * `fluidgrids.workflow.run_failed` — a run this user started ended FAILED.
248
- * `errorCode` is the run's machine error classification (`TIMEOUT`,
249
- * `VALIDATION`, …), never its message.
250
- */
251
- function emitRunFailed(bus, fact) {
252
- emit(bus, "fluidgrids.workflow.run_failed", {
253
- workspaceId: idOrUndefined(fact.workspaceId),
254
- workflowId: idOrUndefined(fact.workflowId),
255
- executionId: idOrUndefined(fact.executionId),
256
- trigger: fact.trigger,
257
- errorCode: toDimension(fact.errorCode),
258
- durationMs: countOrUndefined(fact.durationMs)
259
- });
260
- }
261
- /** `fluidgrids.template.used` — a store template became a workflow. */
262
- function emitTemplateUsed(bus, fact) {
263
- emit(bus, "fluidgrids.template.used", {
264
- workspaceId: idOrUndefined(fact.workspaceId),
265
- templateId: idOrUndefined(fact.templateId),
266
- category: toDimension(fact.category)
267
- });
268
- }
269
- /** `fluidgrids.node.installed` — a store node was installed. */
270
- function emitNodeInstalled(bus, fact) {
271
- emit(bus, "fluidgrids.node.installed", {
272
- workspaceId: idOrUndefined(fact.workspaceId),
273
- nodeType: toDimension(fact.nodeType),
274
- source: fact.source
275
- });
276
- }
277
- /** `fluidgrids.quota.workflow_limit_hit` — a create was refused at the limit. */
278
- function emitWorkflowLimitHit(bus, fact) {
279
- emit(bus, "fluidgrids.quota.workflow_limit_hit", {
280
- workspaceId: idOrUndefined(fact.workspaceId),
281
- quotaKey: WORKFLOWS_QUOTA_NAME,
282
- surface: fact.surface
283
- });
284
- }
285
- /** `fluidgrids.quota.run_limit_hit` — a run was refused at the monthly limit. */
286
- function emitRunLimitHit(bus, fact) {
287
- emit(bus, "fluidgrids.quota.run_limit_hit", {
288
- workspaceId: idOrUndefined(fact.workspaceId),
289
- quotaKey: toDimension(fact.quotaKey) ?? "fluidgrids.runs.monthly",
290
- surface: fact.surface
291
- });
292
- }
293
- /** `fluidgrids.billing.upgrade_clicked` — a FluidGrids upgrade CTA was clicked. */
294
- function emitUpgradeClicked(bus, fact) {
295
- emit(bus, "fluidgrids.billing.upgrade_clicked", {
296
- workspaceId: idOrUndefined(fact.workspaceId),
297
- surface: fact.surface,
298
- quotaKey: toDimension(fact.quotaKey)
299
- });
300
- }
301
- /**
302
- * Map a run's backend mode/trigger to the analytics trigger dimension. The
303
- * builder's debug paths are always `TEST`; anything else a person started by
304
- * hand is `manual`.
305
- */
306
- function runTriggerFromMode(mode) {
307
- return typeof mode === "string" && mode.toUpperCase() === "TEST" ? "test" : "manual";
308
- }
309
-
310
- export { errorCodesOf as _, emitTemplateUsed as a, emitWorkflowLimitHit as c, runTriggerFromMode as d, BILLING_PLANS_PATH as f, collectExtensions as g, WORKFLOWS_QUOTA_NAME as h, emitRunStarted as i, emitWorkflowPublished as l, RUNS_QUOTA_NAME as m, emitRunFailed as n, emitUpgradeClicked as o, QUOTA_EXHAUSTED_CODE as p, emitRunLimitHit as r, emitWorkflowCreated as s, emitNodeInstalled as t, nodesOf as u, findQuotaRefusal as v, isQuotaExhaustedFailure as y };