@burdenoff/fluidgrids-fe-sdk 2026.1022.1 → 2026.1022.2
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/{ExecutionDetailPage-6UKPMPL2.js → ExecutionDetailPage-NFZVCUCA.js} +4 -4
- package/dist/{ExecutionsListPage-3IFRZU6A.js → ExecutionsListPage-KSOHJU4T.js} +5 -5
- package/dist/{WorkflowBuilder-PYJ5T23Q.js → WorkflowBuilder-FR3TUJ33.js} +7 -7
- package/dist/{WorkflowsList-3ZDCAB4D.js → WorkflowsList-BAYEP7TU.js} +5 -5
- package/dist/{chunk-2CDLVDSU.js → chunk-2HUSQTUK.js} +182 -18
- package/dist/{chunk-GU233T6U.js → chunk-3XEIMQNT.js} +51 -41
- package/dist/chunk-4UAWCWS7.js +162 -0
- package/dist/{chunk-XGFADY55.js → chunk-5TW5JP5R.js} +1 -1
- package/dist/{chunk-QL7CDZ7B.js → chunk-6LMWVUD7.js} +3 -3
- package/dist/{chunk-OJL6UH5K.js → chunk-CU23L6GP.js} +2 -2
- package/dist/{chunk-RFG3PJX3.js → chunk-EU5ANGO4.js} +2 -2
- package/dist/{chunk-3RIZZY32.js → chunk-FJHERSHE.js} +5 -5
- package/dist/{chunk-O6E247J6.js → chunk-HP3A6BPK.js} +29 -23
- package/dist/{chunk-V2UCWUBQ.js → chunk-JG65547T.js} +2 -2
- package/dist/{chunk-OM5X65LG.js → chunk-KNFGMDDU.js} +48 -39
- package/dist/{chunk-EPYVZPGU.js → chunk-LHOW7QKK.js} +1 -1
- package/dist/{chunk-IKVHPXHC.js → chunk-PBIN6ERJ.js} +9 -9
- package/dist/{chunk-L2UWPFJM.js → chunk-SAZVBFMO.js} +2 -1
- package/dist/{chunk-SQFFJUAT.js → chunk-SYVLFHWV.js} +2 -2
- package/dist/{chunk-6B6XOZ4V.js → chunk-TWIORNPU.js} +2 -2
- package/dist/{chunk-CGRYQMWL.js → chunk-XQVQKEZK.js} +1 -1
- package/dist/{chunk-YB6WGQTY.js → chunk-YPF7LVUZ.js} +2 -2
- package/dist/executions.js +6 -6
- package/dist/history.js +4 -4
- package/dist/index.d.ts +171 -2
- package/dist/index.js +26 -26
- package/dist/nodes.js +3 -3
- package/dist/observability.js +3 -3
- package/dist/settings.js +4 -4
- package/dist/templates.js +7 -7
- package/dist/workflow-builder.js +8 -8
- package/dist/workflows-list.js +5 -5
- package/package.json +1 -1
- package/dist/chunk-CFCUM4CN.js +0 -41
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export { ExecutionDetailPage } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
export { ExecutionDetailPage } from './chunk-6LMWVUD7.js';
|
|
2
|
+
import './chunk-3XEIMQNT.js';
|
|
3
3
|
import './chunk-QBFAJNUC.js';
|
|
4
4
|
import './chunk-ONVGFVNH.js';
|
|
5
5
|
import './chunk-JL7CASN5.js';
|
|
6
6
|
import './chunk-D3UWK7GY.js';
|
|
7
7
|
import './chunk-UZG3ZIQM.js';
|
|
8
8
|
import './chunk-PJAWNFJV.js';
|
|
9
|
-
import './chunk-
|
|
10
|
-
import './chunk-
|
|
9
|
+
import './chunk-SAZVBFMO.js';
|
|
10
|
+
import './chunk-4UAWCWS7.js';
|
|
11
11
|
import './chunk-UULVIT25.js';
|
|
12
12
|
import './chunk-NTWG3CJX.js';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { ExecutionsListPage } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
export { ExecutionsListPage } from './chunk-YPF7LVUZ.js';
|
|
2
|
+
import './chunk-3XEIMQNT.js';
|
|
3
3
|
import './chunk-QBFAJNUC.js';
|
|
4
|
-
import './chunk-
|
|
4
|
+
import './chunk-HP3A6BPK.js';
|
|
5
5
|
import './chunk-D3UWK7GY.js';
|
|
6
6
|
import './chunk-UZG3ZIQM.js';
|
|
7
7
|
import './chunk-PJAWNFJV.js';
|
|
8
|
-
import './chunk-
|
|
9
|
-
import './chunk-
|
|
8
|
+
import './chunk-SAZVBFMO.js';
|
|
9
|
+
import './chunk-4UAWCWS7.js';
|
|
10
10
|
import './chunk-UULVIT25.js';
|
|
11
11
|
import './chunk-NTWG3CJX.js';
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
export { WorkflowBuilder } from './chunk-
|
|
1
|
+
export { WorkflowBuilder } from './chunk-EU5ANGO4.js';
|
|
2
2
|
import './chunk-6N27YGMB.js';
|
|
3
|
-
import './chunk-
|
|
3
|
+
import './chunk-2HUSQTUK.js';
|
|
4
4
|
import './chunk-GEMNVFPK.js';
|
|
5
5
|
import './chunk-IEVSFCFS.js';
|
|
6
6
|
import './chunk-7LSGGJ7D.js';
|
|
7
7
|
import './chunk-GDAFKRQO.js';
|
|
8
|
-
import './chunk-
|
|
8
|
+
import './chunk-SYVLFHWV.js';
|
|
9
9
|
import './chunk-PXIFUMLA.js';
|
|
10
10
|
import './chunk-WBH2XEWO.js';
|
|
11
11
|
import './chunk-ONVGFVNH.js';
|
|
12
12
|
import './chunk-JL7CASN5.js';
|
|
13
|
-
import './chunk-
|
|
13
|
+
import './chunk-HP3A6BPK.js';
|
|
14
14
|
import './chunk-UZG3ZIQM.js';
|
|
15
|
-
import './chunk-
|
|
15
|
+
import './chunk-5TW5JP5R.js';
|
|
16
16
|
import './chunk-EGYJKHAL.js';
|
|
17
|
-
import './chunk-
|
|
18
|
-
import './chunk-
|
|
17
|
+
import './chunk-SAZVBFMO.js';
|
|
18
|
+
import './chunk-4UAWCWS7.js';
|
|
19
19
|
import './chunk-UULVIT25.js';
|
|
20
20
|
import './chunk-NTWG3CJX.js';
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export { WorkflowsList } from './chunk-
|
|
1
|
+
export { WorkflowsList } from './chunk-FJHERSHE.js';
|
|
2
2
|
import './chunk-6N27YGMB.js';
|
|
3
|
-
import './chunk-
|
|
3
|
+
import './chunk-SYVLFHWV.js';
|
|
4
4
|
import './chunk-ONVGFVNH.js';
|
|
5
5
|
import './chunk-JL7CASN5.js';
|
|
6
|
-
import './chunk-
|
|
6
|
+
import './chunk-HP3A6BPK.js';
|
|
7
7
|
import './chunk-D3UWK7GY.js';
|
|
8
8
|
import './chunk-UZG3ZIQM.js';
|
|
9
9
|
import './chunk-PJAWNFJV.js';
|
|
10
10
|
import './chunk-EGYJKHAL.js';
|
|
11
|
-
import './chunk-
|
|
12
|
-
import './chunk-
|
|
11
|
+
import './chunk-SAZVBFMO.js';
|
|
12
|
+
import './chunk-4UAWCWS7.js';
|
|
13
13
|
import './chunk-UULVIT25.js';
|
|
14
14
|
import './chunk-NTWG3CJX.js';
|
|
@@ -2,17 +2,17 @@ import { deepClone, applyTemplateInputs } from './chunk-GEMNVFPK.js';
|
|
|
2
2
|
import { Input as Input$1 } from './chunk-IEVSFCFS.js';
|
|
3
3
|
import { Dialog as Dialog$1, DialogContent as DialogContent$1, DialogHeader as DialogHeader$1, DialogTitle as DialogTitle$1, DialogDescription as DialogDescription$1, DialogFooter } from './chunk-7LSGGJ7D.js';
|
|
4
4
|
import { Badge as Badge$1, Button as Button$1 } from './chunk-GDAFKRQO.js';
|
|
5
|
-
import { QuotaExhaustedDialog } from './chunk-
|
|
5
|
+
import { QuotaExhaustedDialog } from './chunk-SYVLFHWV.js';
|
|
6
6
|
import { getGlobalStoreClient, createGlobalStoreClient, setGlobalStoreClient, resetGlobalStoreClient } from './chunk-PXIFUMLA.js';
|
|
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-
|
|
10
|
+
import { useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeleteWorkflow, useLazyWorkflowDefinition, useDeactivateWorkflow } from './chunk-HP3A6BPK.js';
|
|
11
11
|
import { config, getFluidGridsConfig, validateTrustedOrigin, resetFluidGridsExecutionState, setFluidGridsConfig, resetFluidGridsConfig } from './chunk-UZG3ZIQM.js';
|
|
12
|
-
import { fetchAllNodeEndpointConfigs } from './chunk-
|
|
12
|
+
import { fetchAllNodeEndpointConfigs } from './chunk-5TW5JP5R.js';
|
|
13
13
|
import { useFlowStore, isNodeTrigger, useIsValidConnection, isTriggerOperation } from './chunk-EGYJKHAL.js';
|
|
14
|
-
import { 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-
|
|
15
|
-
import { throwIfResultError, describeOperationError } from './chunk-
|
|
14
|
+
import { NodeManifestDocument, UpdateWorkflowDefinitionDocument, CreateWorkflowDefinitionDocument, CreateWorkflowVersionDocument, ExecuteStepDocument, TriggerWorkflowDocument, RunFromNodeDocument, ExecutionDetailDocument, WorkflowRunDocument, FluidgridsEntityTagsDocument, AvailableFluidgridsTagsDocument, SearchFluidgridsTagsDocument, TagFluidgridsEntityDocument, UntagFluidgridsEntityDocument, ReplaceFluidgridsEntityTagsDocument, CreateFluidgridsTagDocument, WorkspaceRunsQuotaDocument, NodeSchemaIntrospectionDocument, useWorkflowPinnedDataQuery, usePinNodeDataMutation, useUnpinNodeDataMutation, useRunFromNodeEligibilityQuery, EventRegistrationsDocument, WebhookTestListenerDocument, StopWebhookTestListenerDocument, ListenForWebhookTestEventDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-SAZVBFMO.js';
|
|
15
|
+
import { throwIfResultError, isQuotaExhaustedFailure, describeOperationError, openRunQuotaUpgradePrompt, RUNS_QUOTA_NAME, BILLING_PLANS_PATH } from './chunk-4UAWCWS7.js';
|
|
16
16
|
import { useTr, FluidGridsTranslationProvider, ENGLISH_FALLBACK_TRANSLATOR } from './chunk-UULVIT25.js';
|
|
17
17
|
import { waitForFluidGridsClient, getFluidGridsClient, getFluidGridsClientSafe, createFluidGridsClient, setFluidGridsClient, resetFluidGridsClient } from './chunk-NTWG3CJX.js';
|
|
18
18
|
import * as React2 from 'react';
|
|
@@ -30,9 +30,8 @@ import { Handle, Position, getBezierPath, MarkerType, useReactFlow, NodeResizer,
|
|
|
30
30
|
import { nanoid } from 'nanoid';
|
|
31
31
|
import ReactMarkdown from 'react-markdown';
|
|
32
32
|
import { toast } from 'sonner';
|
|
33
|
-
import { useParams, useNavigate } from 'react-router';
|
|
33
|
+
import { useParams, useNavigate, Link } from 'react-router';
|
|
34
34
|
import { useShallow, shallow } from 'zustand/shallow';
|
|
35
|
-
import { isQuotaExhaustedError } from '@burdenoff/fe-libs/shared/utils';
|
|
36
35
|
import { InfoCircledIcon } from '@radix-ui/react-icons';
|
|
37
36
|
import { ApolloProvider, useQuery, useMutation } from '@apollo/client/react';
|
|
38
37
|
import { TagBadge, TagsWidget } from '@burdenoff/fe-libs/tag';
|
|
@@ -4178,7 +4177,7 @@ function useSaveWorkflow() {
|
|
|
4178
4177
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
4179
4178
|
console.error("Error saving workflow:", message);
|
|
4180
4179
|
const cause = error instanceof Error ? error.cause : void 0;
|
|
4181
|
-
if (
|
|
4180
|
+
if (isQuotaExhaustedFailure(cause) || isQuotaExhaustedFailure(error)) {
|
|
4182
4181
|
setQuotaExhausted(true);
|
|
4183
4182
|
} else {
|
|
4184
4183
|
toast.error("Failed to save workflow", {
|
|
@@ -5906,6 +5905,7 @@ function calculateItemCount(output) {
|
|
|
5906
5905
|
return 1;
|
|
5907
5906
|
}
|
|
5908
5907
|
function useNodeExecution() {
|
|
5908
|
+
const tr = useTr();
|
|
5909
5909
|
const pollTimerRef = useRef(null);
|
|
5910
5910
|
const pollStartRef = useRef(0);
|
|
5911
5911
|
const activeRunIdRef = useRef(null);
|
|
@@ -6253,6 +6253,7 @@ function useNodeExecution() {
|
|
|
6253
6253
|
return { success: false, error: "No result from trigger" };
|
|
6254
6254
|
} catch (error) {
|
|
6255
6255
|
console.error("[useNodeExecution] Error triggering workflow:", error);
|
|
6256
|
+
openRunQuotaUpgradePrompt(error, tr);
|
|
6256
6257
|
const errorMessage = describeOperationError(error);
|
|
6257
6258
|
const errorRunId = nanoid$1();
|
|
6258
6259
|
const errorLog = {
|
|
@@ -6285,7 +6286,8 @@ function useNodeExecution() {
|
|
|
6285
6286
|
addLog,
|
|
6286
6287
|
setNodeStatus,
|
|
6287
6288
|
pollRunUpdates,
|
|
6288
|
-
completeExecution
|
|
6289
|
+
completeExecution,
|
|
6290
|
+
tr
|
|
6289
6291
|
]
|
|
6290
6292
|
);
|
|
6291
6293
|
const followRun = useCallback(
|
|
@@ -6348,6 +6350,7 @@ function useNodeExecution() {
|
|
|
6348
6350
|
return { success: false, error: "No result from runFromNode" };
|
|
6349
6351
|
} catch (error) {
|
|
6350
6352
|
console.error("[useNodeExecution] Error running from node:", error);
|
|
6353
|
+
openRunQuotaUpgradePrompt(error, tr);
|
|
6351
6354
|
const errorMessage = describeOperationError(error);
|
|
6352
6355
|
setNodeStatus(nodeId, "error");
|
|
6353
6356
|
completeExecution();
|
|
@@ -6360,7 +6363,8 @@ function useNodeExecution() {
|
|
|
6360
6363
|
setNodeStatus,
|
|
6361
6364
|
startExecution,
|
|
6362
6365
|
pollRunUpdates,
|
|
6363
|
-
completeExecution
|
|
6366
|
+
completeExecution,
|
|
6367
|
+
tr
|
|
6364
6368
|
]
|
|
6365
6369
|
);
|
|
6366
6370
|
const loadExecution = useCallback(
|
|
@@ -7209,6 +7213,159 @@ function EntityTagPicker({
|
|
|
7209
7213
|
}
|
|
7210
7214
|
);
|
|
7211
7215
|
}
|
|
7216
|
+
|
|
7217
|
+
// src/billing/runsQuota.ts
|
|
7218
|
+
var MAX_ASSIGNMENTS_PER_QUOTA = 100;
|
|
7219
|
+
var RUNS_QUOTA_WARNING_RATIO = 0.8;
|
|
7220
|
+
var createdAtMs = (row) => {
|
|
7221
|
+
const ms = Date.parse(row.createdAt);
|
|
7222
|
+
return Number.isNaN(ms) ? Number.POSITIVE_INFINITY : ms;
|
|
7223
|
+
};
|
|
7224
|
+
function summarizeRunsQuota(rows, quotaName = RUNS_QUOTA_NAME) {
|
|
7225
|
+
const assignments = rows.filter((row) => row.isActive && row.quotaName === quotaName).sort((a, b) => createdAtMs(a) - createdAtMs(b)).slice(0, MAX_ASSIGNMENTS_PER_QUOTA);
|
|
7226
|
+
if (assignments.length === 0) return null;
|
|
7227
|
+
const used = assignments.reduce((sum, row) => sum + row.used, 0);
|
|
7228
|
+
if (assignments.some((row) => row.noLimit || row.limit == null)) {
|
|
7229
|
+
return { used, limit: null, noLimit: true };
|
|
7230
|
+
}
|
|
7231
|
+
const limit = assignments.reduce((sum, row) => sum + (row.limit ?? 0), 0);
|
|
7232
|
+
return { used, limit, noLimit: false };
|
|
7233
|
+
}
|
|
7234
|
+
function runsQuotaLevel(quota) {
|
|
7235
|
+
if (quota.noLimit || quota.limit === null) return "ok";
|
|
7236
|
+
if (quota.limit <= 0 || quota.used >= quota.limit) return "exhausted";
|
|
7237
|
+
return quota.used / quota.limit >= RUNS_QUOTA_WARNING_RATIO ? "warning" : "ok";
|
|
7238
|
+
}
|
|
7239
|
+
async function readRunsQuota(client, workspaceId) {
|
|
7240
|
+
if (!workspaceId) return null;
|
|
7241
|
+
try {
|
|
7242
|
+
const result = await client.query({
|
|
7243
|
+
query: WorkspaceRunsQuotaDocument,
|
|
7244
|
+
variables: { workspaceId },
|
|
7245
|
+
fetchPolicy: "network-only",
|
|
7246
|
+
errorPolicy: "all"
|
|
7247
|
+
});
|
|
7248
|
+
if (result.error) return null;
|
|
7249
|
+
const rows = result.data?.workspaceQuotaAssignments;
|
|
7250
|
+
return rows ? summarizeRunsQuota(rows) : null;
|
|
7251
|
+
} catch {
|
|
7252
|
+
return null;
|
|
7253
|
+
}
|
|
7254
|
+
}
|
|
7255
|
+
function useRunsQuota() {
|
|
7256
|
+
const [quota, setQuota] = useState(null);
|
|
7257
|
+
const isExecuting = useFlowStore((s) => s.execution.isExecuting);
|
|
7258
|
+
const request = useRef(0);
|
|
7259
|
+
const refresh = useCallback(async () => {
|
|
7260
|
+
const client = getFluidGridsClientSafe();
|
|
7261
|
+
const { workspaceId } = getFluidGridsConfig();
|
|
7262
|
+
const id = ++request.current;
|
|
7263
|
+
const next = client ? await readRunsQuota(client, workspaceId) : null;
|
|
7264
|
+
if (id === request.current) setQuota(next);
|
|
7265
|
+
}, []);
|
|
7266
|
+
useEffect(() => {
|
|
7267
|
+
if (!isExecuting) void refresh();
|
|
7268
|
+
}, [isExecuting, refresh]);
|
|
7269
|
+
useEffect(
|
|
7270
|
+
() => () => {
|
|
7271
|
+
request.current += 1;
|
|
7272
|
+
},
|
|
7273
|
+
[]
|
|
7274
|
+
);
|
|
7275
|
+
return quota;
|
|
7276
|
+
}
|
|
7277
|
+
var BAR_CLASS = {
|
|
7278
|
+
ok: "bg-primary",
|
|
7279
|
+
warning: "bg-status-warning-bg",
|
|
7280
|
+
exhausted: "bg-status-error-bg"
|
|
7281
|
+
};
|
|
7282
|
+
var TEXT_CLASS = {
|
|
7283
|
+
ok: "text-muted-foreground",
|
|
7284
|
+
warning: "text-status-warning-text",
|
|
7285
|
+
exhausted: "text-status-error-text"
|
|
7286
|
+
};
|
|
7287
|
+
function RunsUsageMeterView({
|
|
7288
|
+
quota,
|
|
7289
|
+
className
|
|
7290
|
+
}) {
|
|
7291
|
+
const tr = useTr();
|
|
7292
|
+
const level = runsQuotaLevel(quota);
|
|
7293
|
+
const used = quota.used.toLocaleString();
|
|
7294
|
+
if (quota.noLimit || quota.limit === null) {
|
|
7295
|
+
return /* @__PURE__ */ jsx(
|
|
7296
|
+
"span",
|
|
7297
|
+
{
|
|
7298
|
+
"data-testid": "fluidgrids-runs-meter",
|
|
7299
|
+
"data-level": level,
|
|
7300
|
+
className: cn("text-xs text-muted-foreground", className),
|
|
7301
|
+
children: tr(
|
|
7302
|
+
"fluidgrids.billing.runsMeter.unlimited",
|
|
7303
|
+
"{{used}} runs this month",
|
|
7304
|
+
{ used }
|
|
7305
|
+
)
|
|
7306
|
+
}
|
|
7307
|
+
);
|
|
7308
|
+
}
|
|
7309
|
+
const limit = quota.limit.toLocaleString();
|
|
7310
|
+
const percent = quota.limit > 0 ? Math.min(100, Math.round(quota.used / quota.limit * 100)) : 100;
|
|
7311
|
+
const label = tr(
|
|
7312
|
+
"fluidgrids.billing.runsMeter.label",
|
|
7313
|
+
"{{used}} of {{limit}} runs used this month",
|
|
7314
|
+
{ used, limit }
|
|
7315
|
+
);
|
|
7316
|
+
return /* @__PURE__ */ jsxs(
|
|
7317
|
+
"div",
|
|
7318
|
+
{
|
|
7319
|
+
"data-testid": "fluidgrids-runs-meter",
|
|
7320
|
+
"data-level": level,
|
|
7321
|
+
className: cn("flex items-center gap-2 text-xs", className),
|
|
7322
|
+
children: [
|
|
7323
|
+
/* @__PURE__ */ jsxs(
|
|
7324
|
+
"div",
|
|
7325
|
+
{
|
|
7326
|
+
className: "flex flex-col gap-1",
|
|
7327
|
+
title: label,
|
|
7328
|
+
role: "meter",
|
|
7329
|
+
"aria-label": label,
|
|
7330
|
+
"aria-valuemin": 0,
|
|
7331
|
+
"aria-valuemax": quota.limit,
|
|
7332
|
+
"aria-valuenow": Math.min(quota.used, quota.limit),
|
|
7333
|
+
children: [
|
|
7334
|
+
/* @__PURE__ */ jsx("span", { className: cn("whitespace-nowrap", TEXT_CLASS[level]), children: tr(
|
|
7335
|
+
"fluidgrids.billing.runsMeter.short",
|
|
7336
|
+
"Runs {{used}} / {{limit}}",
|
|
7337
|
+
{
|
|
7338
|
+
used,
|
|
7339
|
+
limit
|
|
7340
|
+
}
|
|
7341
|
+
) }),
|
|
7342
|
+
/* @__PURE__ */ jsx("span", { className: "block h-1 w-24 overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx(
|
|
7343
|
+
"span",
|
|
7344
|
+
{
|
|
7345
|
+
className: cn("block h-full rounded-full", BAR_CLASS[level]),
|
|
7346
|
+
style: { width: `${percent}%` }
|
|
7347
|
+
}
|
|
7348
|
+
) })
|
|
7349
|
+
]
|
|
7350
|
+
}
|
|
7351
|
+
),
|
|
7352
|
+
level !== "ok" && /* @__PURE__ */ jsx(
|
|
7353
|
+
Link,
|
|
7354
|
+
{
|
|
7355
|
+
to: BILLING_PLANS_PATH,
|
|
7356
|
+
className: "whitespace-nowrap font-medium text-primary hover:underline",
|
|
7357
|
+
children: tr("fluidgrids.billing.runsMeter.upgrade", "Upgrade")
|
|
7358
|
+
}
|
|
7359
|
+
)
|
|
7360
|
+
]
|
|
7361
|
+
}
|
|
7362
|
+
);
|
|
7363
|
+
}
|
|
7364
|
+
function RunsUsageMeter({ className }) {
|
|
7365
|
+
const quota = useRunsQuota();
|
|
7366
|
+
if (!quota) return null;
|
|
7367
|
+
return /* @__PURE__ */ jsx(RunsUsageMeterView, { quota, className });
|
|
7368
|
+
}
|
|
7212
7369
|
function useGlobalStoreClient() {
|
|
7213
7370
|
const context = useContext(FluidGridsContext);
|
|
7214
7371
|
if (context?.globalClient) {
|
|
@@ -20089,7 +20246,7 @@ var SaveFlowButton = ({ className }) => {
|
|
|
20089
20246
|
},
|
|
20090
20247
|
onUpgrade: () => {
|
|
20091
20248
|
dismissQuotaExhausted();
|
|
20092
|
-
navigate(
|
|
20249
|
+
navigate(BILLING_PLANS_PATH);
|
|
20093
20250
|
}
|
|
20094
20251
|
}
|
|
20095
20252
|
)
|
|
@@ -21748,6 +21905,7 @@ function useWebhookTestListener(target, onReceived) {
|
|
|
21748
21905
|
);
|
|
21749
21906
|
const [busy, setBusy] = useState(false);
|
|
21750
21907
|
const [error, setError] = useState(null);
|
|
21908
|
+
const tr = useTr();
|
|
21751
21909
|
const pollTimer = useRef(null);
|
|
21752
21910
|
const openId = useRef(null);
|
|
21753
21911
|
const generation = useRef(0);
|
|
@@ -21822,10 +21980,12 @@ function useWebhookTestListener(target, onReceived) {
|
|
|
21822
21980
|
setBusy(true);
|
|
21823
21981
|
setError(null);
|
|
21824
21982
|
try {
|
|
21825
|
-
const result =
|
|
21826
|
-
|
|
21827
|
-
|
|
21828
|
-
|
|
21983
|
+
const result = throwIfResultError(
|
|
21984
|
+
await client.mutate({
|
|
21985
|
+
mutation: ListenForWebhookTestEventDocument,
|
|
21986
|
+
variables: { input: { workflowKey, version, triggerNodeId } }
|
|
21987
|
+
})
|
|
21988
|
+
);
|
|
21829
21989
|
const armed = result.data?.listenForWebhookTestEvent;
|
|
21830
21990
|
if (!armed) throw new Error("The test listener could not be started");
|
|
21831
21991
|
if (generation.current !== armedFor) {
|
|
@@ -21843,8 +22003,10 @@ function useWebhookTestListener(target, onReceived) {
|
|
|
21843
22003
|
});
|
|
21844
22004
|
poll(armed.id);
|
|
21845
22005
|
} catch (err) {
|
|
21846
|
-
if (generation.current === armedFor)
|
|
22006
|
+
if (generation.current === armedFor) {
|
|
22007
|
+
openRunQuotaUpgradePrompt(err, tr);
|
|
21847
22008
|
setError(describeOperationError(err));
|
|
22009
|
+
}
|
|
21848
22010
|
} finally {
|
|
21849
22011
|
if (generation.current === armedFor) setBusy(false);
|
|
21850
22012
|
}
|
|
@@ -21854,7 +22016,8 @@ function useWebhookTestListener(target, onReceived) {
|
|
|
21854
22016
|
triggerNodeId,
|
|
21855
22017
|
poll,
|
|
21856
22018
|
stopOpenListener,
|
|
21857
|
-
stopAbandoned
|
|
22019
|
+
stopAbandoned,
|
|
22020
|
+
tr
|
|
21858
22021
|
]);
|
|
21859
22022
|
const stop = useCallback(async () => {
|
|
21860
22023
|
const id = openId.current;
|
|
@@ -26722,6 +26885,7 @@ var FlowBuilder = ({ readOnly = false }) => {
|
|
|
26722
26885
|
] }),
|
|
26723
26886
|
name !== "" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
26724
26887
|
/* @__PURE__ */ jsxs("div", { className: "hidden shrink-0 lg:inline-flex items-center gap-2", children: [
|
|
26888
|
+
/* @__PURE__ */ jsx(RunsUsageMeter, { className: "mr-1" }),
|
|
26725
26889
|
/* @__PURE__ */ jsx(VersionHistoryPanel, {}),
|
|
26726
26890
|
/* @__PURE__ */ jsx(SaveFlowButton, {}),
|
|
26727
26891
|
/* @__PURE__ */ jsx(ActivateWorkflowButton, {}),
|
|
@@ -26992,4 +27156,4 @@ var FlowBuilderPage = ({
|
|
|
26992
27156
|
] });
|
|
26993
27157
|
};
|
|
26994
27158
|
|
|
26995
|
-
export { Card2 as Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ConnectionFormDialog, ConnectionSelector, EntityTagPicker, FLUIDGRIDS_ENTITY_TYPES, FlowBuilderPage, FluidGridsMark, FluidGridsProvider, RUNNER_INSTALL_SCRIPT_URL, RunOnSection, RunnerStatusPill, TemplateCard, buildNodeCheck, buildRequiredNodeTypes, listCustomBlocks, mergeStickyNotes, refetchStoreNodes, registerCustomBlock, resolveUiSpec, runnerInstallCommand, stripSubmitActions, tagLabel, useAvailableTags, useConnection, useConnections, useConnectionsByProvider, useCreateConnection, useCreateTag, useDraftEntityTags, useEntityTags, useFluidGridsContext, useImportWorkflowTemplate, useInitiateOAuth, useInstalledNodes, useNodeExecution, useProviders, useReplaceEntityTags, useRunnerActions, useRunners, useSearchTags, useTagEntity, useUntagEntity, useWorkflowTemplates };
|
|
27159
|
+
export { Card2 as Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ConnectionFormDialog, ConnectionSelector, EntityTagPicker, FLUIDGRIDS_ENTITY_TYPES, FlowBuilderPage, FluidGridsMark, FluidGridsProvider, RUNNER_INSTALL_SCRIPT_URL, RunOnSection, RunnerStatusPill, RunsUsageMeter, RunsUsageMeterView, TemplateCard, buildNodeCheck, buildRequiredNodeTypes, listCustomBlocks, mergeStickyNotes, readRunsQuota, refetchStoreNodes, registerCustomBlock, resolveUiSpec, runnerInstallCommand, runsQuotaLevel, stripSubmitActions, summarizeRunsQuota, tagLabel, useAvailableTags, useConnection, useConnections, useConnectionsByProvider, useCreateConnection, useCreateTag, useDraftEntityTags, useEntityTags, useFluidGridsContext, useImportWorkflowTemplate, useInitiateOAuth, useInstalledNodes, useNodeExecution, useProviders, useReplaceEntityTags, useRunnerActions, useRunners, useRunsQuota, useSearchTags, useTagEntity, useUntagEntity, useWorkflowTemplates };
|
|
@@ -2,8 +2,8 @@ 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-
|
|
6
|
-
import { throwIfResultError } from './chunk-
|
|
5
|
+
import { ExecutionDetailDocument, ExecutionStatsDocument, PauseExecutionDocument, ResumeExecutionDocument, CancelExecutionDocument, RetryNodeDocument, TriggerWorkflowDocument, TerminateExecutionDocument, ExecutionsListDocument } from './chunk-SAZVBFMO.js';
|
|
6
|
+
import { throwIfResultError, openRunQuotaUpgradePrompt } from './chunk-4UAWCWS7.js';
|
|
7
7
|
import { useTr } from './chunk-UULVIT25.js';
|
|
8
8
|
import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
|
|
9
9
|
import { Icon } from '@iconify/react';
|
|
@@ -2885,6 +2885,7 @@ function useExecutionStats(options = {}) {
|
|
|
2885
2885
|
};
|
|
2886
2886
|
}
|
|
2887
2887
|
function useExecutionActions() {
|
|
2888
|
+
const tr = useTr();
|
|
2888
2889
|
const [loading, setLoading] = useState(false);
|
|
2889
2890
|
const [error, setError] = useState(null);
|
|
2890
2891
|
const pauseExecution = useCallback(async (id) => {
|
|
@@ -2991,51 +2992,60 @@ function useExecutionActions() {
|
|
|
2991
2992
|
} catch (err) {
|
|
2992
2993
|
const error2 = err;
|
|
2993
2994
|
setError(error2);
|
|
2995
|
+
openRunQuotaUpgradePrompt(err, tr);
|
|
2994
2996
|
return { ok: false, message: error2.message };
|
|
2995
2997
|
} finally {
|
|
2996
2998
|
setLoading(false);
|
|
2997
2999
|
}
|
|
2998
3000
|
},
|
|
2999
|
-
[]
|
|
3001
|
+
[tr]
|
|
3002
|
+
);
|
|
3003
|
+
const replayExecution = useCallback(
|
|
3004
|
+
async (runId) => {
|
|
3005
|
+
setLoading(true);
|
|
3006
|
+
setError(null);
|
|
3007
|
+
try {
|
|
3008
|
+
const client = getFluidGridsClient();
|
|
3009
|
+
const result = throwIfResultError(
|
|
3010
|
+
await client.mutate({
|
|
3011
|
+
mutation: REPLAY_WORKFLOW_RUN,
|
|
3012
|
+
variables: { runId }
|
|
3013
|
+
})
|
|
3014
|
+
);
|
|
3015
|
+
return result.data?.replayWorkflowRun ?? null;
|
|
3016
|
+
} catch (err) {
|
|
3017
|
+
setError(err);
|
|
3018
|
+
openRunQuotaUpgradePrompt(err, tr);
|
|
3019
|
+
return null;
|
|
3020
|
+
} finally {
|
|
3021
|
+
setLoading(false);
|
|
3022
|
+
}
|
|
3023
|
+
},
|
|
3024
|
+
[tr]
|
|
3025
|
+
);
|
|
3026
|
+
const retryExecutions = useCallback(
|
|
3027
|
+
async (runIds) => {
|
|
3028
|
+
setLoading(true);
|
|
3029
|
+
setError(null);
|
|
3030
|
+
try {
|
|
3031
|
+
const client = getFluidGridsClient();
|
|
3032
|
+
const result = throwIfResultError(
|
|
3033
|
+
await client.mutate({
|
|
3034
|
+
mutation: RETRY_WORKFLOW_RUNS,
|
|
3035
|
+
variables: { runIds }
|
|
3036
|
+
})
|
|
3037
|
+
);
|
|
3038
|
+
return result.data?.retryWorkflowRuns ?? [];
|
|
3039
|
+
} catch (err) {
|
|
3040
|
+
setError(err);
|
|
3041
|
+
openRunQuotaUpgradePrompt(err, tr);
|
|
3042
|
+
return [];
|
|
3043
|
+
} finally {
|
|
3044
|
+
setLoading(false);
|
|
3045
|
+
}
|
|
3046
|
+
},
|
|
3047
|
+
[tr]
|
|
3000
3048
|
);
|
|
3001
|
-
const replayExecution = useCallback(async (runId) => {
|
|
3002
|
-
setLoading(true);
|
|
3003
|
-
setError(null);
|
|
3004
|
-
try {
|
|
3005
|
-
const client = getFluidGridsClient();
|
|
3006
|
-
const result = throwIfResultError(
|
|
3007
|
-
await client.mutate({
|
|
3008
|
-
mutation: REPLAY_WORKFLOW_RUN,
|
|
3009
|
-
variables: { runId }
|
|
3010
|
-
})
|
|
3011
|
-
);
|
|
3012
|
-
return result.data?.replayWorkflowRun ?? null;
|
|
3013
|
-
} catch (err) {
|
|
3014
|
-
setError(err);
|
|
3015
|
-
return null;
|
|
3016
|
-
} finally {
|
|
3017
|
-
setLoading(false);
|
|
3018
|
-
}
|
|
3019
|
-
}, []);
|
|
3020
|
-
const retryExecutions = useCallback(async (runIds) => {
|
|
3021
|
-
setLoading(true);
|
|
3022
|
-
setError(null);
|
|
3023
|
-
try {
|
|
3024
|
-
const client = getFluidGridsClient();
|
|
3025
|
-
const result = throwIfResultError(
|
|
3026
|
-
await client.mutate({
|
|
3027
|
-
mutation: RETRY_WORKFLOW_RUNS,
|
|
3028
|
-
variables: { runIds }
|
|
3029
|
-
})
|
|
3030
|
-
);
|
|
3031
|
-
return result.data?.retryWorkflowRuns ?? [];
|
|
3032
|
-
} catch (err) {
|
|
3033
|
-
setError(err);
|
|
3034
|
-
return [];
|
|
3035
|
-
} finally {
|
|
3036
|
-
setLoading(false);
|
|
3037
|
-
}
|
|
3038
|
-
}, []);
|
|
3039
3049
|
const terminateExecution = useCallback(
|
|
3040
3050
|
async (runId, reason) => {
|
|
3041
3051
|
setLoading(true);
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { ENGLISH_FALLBACK_TRANSLATOR } from './chunk-UULVIT25.js';
|
|
2
|
+
import { CombinedGraphQLErrors, ServerError } from '@apollo/client/errors';
|
|
3
|
+
import { dispatchUpgradePrompt } from '@burdenoff/fe-libs/shared/components';
|
|
4
|
+
|
|
5
|
+
function describeGraphQLError(error) {
|
|
6
|
+
const code = typeof error.extensions?.code === "string" ? error.extensions.code : void 0;
|
|
7
|
+
switch (code) {
|
|
8
|
+
case "QUOTA_EXHAUSTED": {
|
|
9
|
+
const quota = /Quota exhausted for (\S+)/.exec(error.message)?.[1];
|
|
10
|
+
const allowance = quota ? `"${quota}" quota` : "usage quota";
|
|
11
|
+
return `Quota exhausted \u2014 your workspace has used up its ${allowance}. Upgrade your plan or wait for the quota to reset.`;
|
|
12
|
+
}
|
|
13
|
+
case "QUOTA_NOT_PROVISIONED":
|
|
14
|
+
return "This workspace's plan does not include this usage allowance yet. Contact your workspace admin or support to have it provisioned.";
|
|
15
|
+
case "UNAUTHENTICATED":
|
|
16
|
+
return "Your session has expired. Please sign in again.";
|
|
17
|
+
case "FORBIDDEN":
|
|
18
|
+
return error.message || "You don't have permission to perform this action.";
|
|
19
|
+
default:
|
|
20
|
+
return error.message || "Unknown error";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function firstGraphQLErrorInBody(bodyText) {
|
|
24
|
+
try {
|
|
25
|
+
const parsed = JSON.parse(bodyText);
|
|
26
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
27
|
+
const errors = parsed.errors;
|
|
28
|
+
if (!Array.isArray(errors) || errors.length === 0) return null;
|
|
29
|
+
const first = errors[0];
|
|
30
|
+
if (typeof first !== "object" || first === null) return null;
|
|
31
|
+
const message = first.message;
|
|
32
|
+
if (typeof message !== "string") return null;
|
|
33
|
+
return first;
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function describeOperationError(error, fallback = "Unknown error") {
|
|
39
|
+
if (CombinedGraphQLErrors.is(error)) {
|
|
40
|
+
const first = error.errors[0];
|
|
41
|
+
return first ? describeGraphQLError(first) : error.message || fallback;
|
|
42
|
+
}
|
|
43
|
+
if (ServerError.is(error)) {
|
|
44
|
+
const first = firstGraphQLErrorInBody(error.bodyText);
|
|
45
|
+
if (first) return describeGraphQLError(first);
|
|
46
|
+
}
|
|
47
|
+
if (error instanceof Error) {
|
|
48
|
+
return error.message || fallback;
|
|
49
|
+
}
|
|
50
|
+
if (typeof error === "string" && error.length > 0) {
|
|
51
|
+
return error;
|
|
52
|
+
}
|
|
53
|
+
return fallback;
|
|
54
|
+
}
|
|
55
|
+
function throwIfResultError(result) {
|
|
56
|
+
if (result.error) {
|
|
57
|
+
throw new Error(describeOperationError(result.error), {
|
|
58
|
+
cause: result.error
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/billing/quota.ts
|
|
65
|
+
var RUNS_QUOTA_NAME = "fluidgrids.runs.monthly";
|
|
66
|
+
var WORKFLOWS_QUOTA_NAME = "fluidgrids.workflows.count";
|
|
67
|
+
var BILLING_PLANS_PATH = "/billing/plans";
|
|
68
|
+
var QUOTA_EXHAUSTED_CODE = "QUOTA_EXHAUSTED";
|
|
69
|
+
var QUOTA_NOT_PROVISIONED_CODE = "QUOTA_NOT_PROVISIONED";
|
|
70
|
+
function asRecord(value) {
|
|
71
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
72
|
+
}
|
|
73
|
+
function extensionsOfList(list) {
|
|
74
|
+
if (!Array.isArray(list)) return [];
|
|
75
|
+
const found = [];
|
|
76
|
+
for (const entry of list) {
|
|
77
|
+
const extensions = asRecord(asRecord(entry)?.extensions);
|
|
78
|
+
if (extensions) found.push(extensions);
|
|
79
|
+
}
|
|
80
|
+
return found;
|
|
81
|
+
}
|
|
82
|
+
function extensionsOfBody(bodyText) {
|
|
83
|
+
if (typeof bodyText !== "string" || !bodyText.includes("errors")) return [];
|
|
84
|
+
try {
|
|
85
|
+
const parsed = JSON.parse(bodyText);
|
|
86
|
+
return extensionsOfList(asRecord(parsed)?.errors);
|
|
87
|
+
} catch {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
var MAX_CAUSE_DEPTH = 5;
|
|
92
|
+
function collectExtensions(error) {
|
|
93
|
+
const found = [];
|
|
94
|
+
const seen = /* @__PURE__ */ new Set();
|
|
95
|
+
let current = error;
|
|
96
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH; depth += 1) {
|
|
97
|
+
const host = asRecord(current);
|
|
98
|
+
if (!host || seen.has(host)) break;
|
|
99
|
+
seen.add(host);
|
|
100
|
+
const direct = asRecord(host.extensions);
|
|
101
|
+
if (direct) found.push(direct);
|
|
102
|
+
found.push(...extensionsOfList(host.errors));
|
|
103
|
+
found.push(...extensionsOfList(host.graphQLErrors));
|
|
104
|
+
const networkError = asRecord(host.networkError);
|
|
105
|
+
found.push(...extensionsOfList(asRecord(networkError?.result)?.errors));
|
|
106
|
+
found.push(...extensionsOfBody(networkError?.bodyText));
|
|
107
|
+
found.push(...extensionsOfList(asRecord(host.result)?.errors));
|
|
108
|
+
found.push(...extensionsOfBody(host.bodyText));
|
|
109
|
+
current = host.cause;
|
|
110
|
+
}
|
|
111
|
+
return found;
|
|
112
|
+
}
|
|
113
|
+
function stringField(extensions, key) {
|
|
114
|
+
const value = extensions[key];
|
|
115
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
116
|
+
}
|
|
117
|
+
function findQuotaRefusal(error) {
|
|
118
|
+
const all = collectExtensions(error);
|
|
119
|
+
const notProvisioned = all.find(
|
|
120
|
+
(ext) => ext.code === QUOTA_NOT_PROVISIONED_CODE
|
|
121
|
+
);
|
|
122
|
+
if (notProvisioned) {
|
|
123
|
+
return {
|
|
124
|
+
kind: "not-provisioned",
|
|
125
|
+
quotaName: stringField(notProvisioned, "quotaName"),
|
|
126
|
+
limitLeft: null
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const exhausted = all.find((ext) => ext.code === QUOTA_EXHAUSTED_CODE);
|
|
130
|
+
if (exhausted) {
|
|
131
|
+
const limitLeft = exhausted.limitLeft;
|
|
132
|
+
return {
|
|
133
|
+
kind: "exhausted",
|
|
134
|
+
quotaName: stringField(exhausted, "quotaName"),
|
|
135
|
+
limitLeft: typeof limitLeft === "number" ? limitLeft : null
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
function isQuotaExhaustedFailure(error) {
|
|
141
|
+
return findQuotaRefusal(error)?.kind === "exhausted";
|
|
142
|
+
}
|
|
143
|
+
function openRunQuotaUpgradePrompt(error, tr = ENGLISH_FALLBACK_TRANSLATOR) {
|
|
144
|
+
const refusal = findQuotaRefusal(error);
|
|
145
|
+
if (refusal?.kind !== "exhausted") return false;
|
|
146
|
+
dispatchUpgradePrompt({
|
|
147
|
+
extensions: {
|
|
148
|
+
code: QUOTA_EXHAUSTED_CODE,
|
|
149
|
+
quotaName: refusal.quotaName ?? RUNS_QUOTA_NAME,
|
|
150
|
+
resource: tr("fluidgrids.billing.runQuota.resource", "workflow runs"),
|
|
151
|
+
...refusal.limitLeft !== null ? { limitLeft: refusal.limitLeft } : {}
|
|
152
|
+
},
|
|
153
|
+
title: tr("fluidgrids.billing.runQuota.title", "Monthly run limit reached"),
|
|
154
|
+
description: tr(
|
|
155
|
+
"fluidgrids.billing.runQuota.description",
|
|
156
|
+
"Your workspace has used all the workflow runs included in its plan this month. Upgrade your plan to keep running workflows, or wait for the monthly reset."
|
|
157
|
+
)
|
|
158
|
+
});
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export { BILLING_PLANS_PATH, RUNS_QUOTA_NAME, WORKFLOWS_QUOTA_NAME, describeOperationError, findQuotaRefusal, isQuotaExhaustedFailure, openRunQuotaUpgradePrompt, throwIfResultError };
|