@w6w/embed 0.2.1 → 0.2.11
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/{ConfirmModal-RLbZT5_k.js → ConfirmModal-BE-SdX-O.js} +53 -49
- package/dist/{ConfirmModal-RLbZT5_k.js.map → ConfirmModal-BE-SdX-O.js.map} +1 -1
- package/dist/{CreateFunctionModal-DRsFx-FB.js → CreateFunctionModal-D6CQLpa_.js} +25 -25
- package/dist/{CreateFunctionModal-DRsFx-FB.js.map → CreateFunctionModal-D6CQLpa_.js.map} +1 -1
- package/dist/{DocumentFormModal-BExK1V-B.js → DocumentFormModal-YauVdolr.js} +5 -5
- package/dist/{DocumentFormModal-BExK1V-B.js.map → DocumentFormModal-YauVdolr.js.map} +1 -1
- package/dist/{ImportSpecModal-BDQIf6rg.js → ImportSpecModal-B7qd1Km2.js} +3 -3
- package/dist/{ImportSpecModal-BDQIf6rg.js.map → ImportSpecModal-B7qd1Km2.js.map} +1 -1
- package/dist/ModelRoutesManager-BGESQahw.js +345 -0
- package/dist/ModelRoutesManager-BGESQahw.js.map +1 -0
- package/dist/WorkflowEditor-CwvmAGp2.js +925 -0
- package/dist/WorkflowEditor-CwvmAGp2.js.map +1 -0
- package/dist/{apps-1FNUwbGv.js → apps-CboASBKr.js} +14 -14
- package/dist/{apps-1FNUwbGv.js.map → apps-CboASBKr.js.map} +1 -1
- package/dist/{callables-3mFrMVG_.js → callables-tOlflvbl.js} +11 -11
- package/dist/{callables-3mFrMVG_.js.map → callables-tOlflvbl.js.map} +1 -1
- package/dist/chrome/ConfirmModal.d.ts +4 -1
- package/dist/chrome/workspace.d.ts +4 -0
- package/dist/{coerce-input-BicYr7nc.js → coerce-input-DttlcSdO.js} +70 -58
- package/dist/coerce-input-DttlcSdO.js.map +1 -0
- package/dist/connections-D7cgXhDS.js +119 -0
- package/dist/connections-D7cgXhDS.js.map +1 -0
- package/dist/credentials-DaQU3Ca_.js +171 -0
- package/dist/credentials-DaQU3Ca_.js.map +1 -0
- package/dist/document-sources-UCwe8x77.js +91 -0
- package/dist/document-sources-UCwe8x77.js.map +1 -0
- package/dist/draft.mjs +1 -1
- package/dist/editor/BindingBanner.d.ts +13 -0
- package/dist/editor/CallableEditorFrame.d.ts +7 -0
- package/dist/editor/EndpointCards.d.ts +4 -1
- package/dist/editor/PublishControl.d.ts +19 -0
- package/dist/editor/TargetSelector.d.ts +15 -0
- package/dist/editor/TargetSelector.types.d.ts +2 -0
- package/dist/editor/definition.d.ts +2 -0
- package/dist/{editor-apps-BdenSV1o.js → editor-apps-BUZWld-m.js} +5 -5
- package/dist/{editor-apps-BdenSV1o.js.map → editor-apps-BUZWld-m.js.map} +1 -1
- package/dist/{editor-tools-RxmY5iyi.js → editor-tools-B_Lfx3kw.js} +11 -11
- package/dist/editor-tools-B_Lfx3kw.js.map +1 -0
- package/dist/editor.mjs +1 -1
- package/dist/editors.mjs +768 -621
- package/dist/editors.mjs.map +1 -1
- package/dist/{endpoints-B2ynbZo-.js → endpoints-DSRo1Lc5.js} +113 -107
- package/dist/endpoints-DSRo1Lc5.js.map +1 -0
- package/dist/fields-DvS8XZFc.js +21 -0
- package/dist/fields-DvS8XZFc.js.map +1 -0
- package/dist/forms/ModelBudgetsManager.d.ts +9 -0
- package/dist/forms/ModelRoutesManager.d.ts +14 -0
- package/dist/forms.d.ts +4 -0
- package/dist/forms.mjs +611 -212
- package/dist/forms.mjs.map +1 -1
- package/dist/index.mjs +119 -112
- package/dist/index.mjs.map +1 -1
- package/dist/lib/binding-problems.d.ts +38 -0
- package/dist/lib/code-rail.d.ts +4 -2
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/invoke-error.d.ts +1 -0
- package/dist/lib/sdk-snippets.d.ts +1 -1
- package/dist/lib/target-fields.d.ts +8 -0
- package/dist/lib/trigger-preview.d.ts +1 -0
- package/dist/lib/workflow-live-run.d.ts +9 -2
- package/dist/lib/workflow-nodes.d.ts +5 -0
- package/dist/lib/workflow-validity.d.ts +1 -0
- package/dist/lib.mjs +72 -70
- package/dist/lists/ConnectionDependents.d.ts +31 -0
- package/dist/lists/ConnectionDetail.d.ts +4 -1
- package/dist/lists/ConnectionList.d.ts +4 -1
- package/dist/lists/CredentialDetail.d.ts +15 -0
- package/dist/lists/CredentialList.d.ts +14 -0
- package/dist/lists/ModelCatalog.d.ts +12 -0
- package/dist/lists/ModelUsage.d.ts +12 -0
- package/dist/lists.d.ts +8 -0
- package/dist/lists.mjs +1322 -604
- package/dist/lists.mjs.map +1 -1
- package/dist/models-bAayQPJ_.js +270 -0
- package/dist/models-bAayQPJ_.js.map +1 -0
- package/dist/{project-context-BiCjv_E3.js → project-context-Tvp-La7A.js} +3 -3
- package/dist/{project-context-BiCjv_E3.js.map → project-context-Tvp-La7A.js.map} +1 -1
- package/dist/rail.mjs +4 -4
- package/dist/repos/agents-studio-agents.d.ts +52 -0
- package/dist/repos/agents-studio-assets.d.ts +68 -0
- package/dist/repos/connections.d.ts +30 -12
- package/dist/repos/credentials.d.ts +83 -0
- package/dist/repos/endpoints.d.ts +9 -3
- package/dist/repos/fields.d.ts +34 -0
- package/dist/repos/functions.d.ts +7 -5
- package/dist/repos/index.d.ts +5 -0
- package/dist/repos/models.d.ts +289 -0
- package/dist/repos.mjs +613 -176
- package/dist/repos.mjs.map +1 -1
- package/dist/{slug-C4ktDPdy.js → slug-BVdgiP_L.js} +64 -60
- package/dist/slug-BVdgiP_L.js.map +1 -0
- package/dist/{spec-export-Cf3VQSQS.js → spec-export-CBbloO_n.js} +7 -7
- package/dist/{spec-export-Cf3VQSQS.js.map → spec-export-CBbloO_n.js.map} +1 -1
- package/dist/{spec-import-CjmxyZDR.js → spec-import-CW6R_Wk1.js} +160 -156
- package/dist/spec-import-CW6R_Wk1.js.map +1 -0
- package/dist/theme-context-E2ZhlXDX.js +6 -0
- package/dist/theme-context-E2ZhlXDX.js.map +1 -0
- package/dist/theme-context.d.ts +2 -0
- package/dist/trigger-preview-DKxfjzUY.js +145 -0
- package/dist/trigger-preview-DKxfjzUY.js.map +1 -0
- package/dist/{use-callable-draft-zHLpcr-b.js → use-callable-draft-DsALnSfF.js} +22 -22
- package/dist/{use-callable-draft-zHLpcr-b.js.map → use-callable-draft-DsALnSfF.js.map} +1 -1
- package/dist/{workflow-blank-DyL3_RUA.js → workflow-blank-DFpGObrn.js} +6 -6
- package/dist/{workflow-blank-DyL3_RUA.js.map → workflow-blank-DFpGObrn.js.map} +1 -1
- package/package.json +1 -1
- package/src/styles.css +2 -6
- package/dist/WorkflowEditor-DlbVv6Fs.js +0 -854
- package/dist/WorkflowEditor-DlbVv6Fs.js.map +0 -1
- package/dist/coerce-input-BicYr7nc.js.map +0 -1
- package/dist/connections-CjjYeRqb.js +0 -78
- package/dist/connections-CjjYeRqb.js.map +0 -1
- package/dist/document-sources-C0grrtdq.js +0 -86
- package/dist/document-sources-C0grrtdq.js.map +0 -1
- package/dist/editor-tools-RxmY5iyi.js.map +0 -1
- package/dist/endpoints-B2ynbZo-.js.map +0 -1
- package/dist/slug-C4ktDPdy.js.map +0 -1
- package/dist/spec-import-CjmxyZDR.js.map +0 -1
- package/dist/trigger-preview-VPkrryDl.js +0 -120
- package/dist/trigger-preview-VPkrryDl.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowEditor-CwvmAGp2.js","sources":["../src/chrome/ExecutionProfileHeader.tsx","../src/chrome/history-open-run.ts","../src/chrome/HistoryModal.tsx","../src/chrome/HistoryButton.tsx","../src/chrome/JsonToggle.tsx","../src/editor/BindingBanner.tsx","../src/editor/EditorShell.tsx","../src/editor/WorkflowSettingsModal.tsx","../src/editor/definition.ts","../src/editor/WorkflowEditor.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\n\n/**\n * `ExecutionProfileHeader` — the ONE editor header every execution profile's\n * editor mounts (T3.1.1, `building-blocks.md` §Profile building blocks\n * §Mirror).\n *\n * Extracted verbatim from `WorkflowsPage.tsx`'s full-bleed editor head, which\n * is the presentation of record: back control, title, actions. Two hosts use\n * it with two title CONFIGURATIONS, never two headers:\n * - `WorkflowsPage.tsx` — an inline-editable, controlled name input\n * (`editable: true`); back clears the `?edit=` search param; the action row\n * (run / stop / publish / JSON / settings) stays host-owned and arrives as\n * `actions`.\n * - `CallablePage.tsx`'s `CallableEditorChrome` — a Function/Endpoint\n * read-only heading (`editable: false`) with the `incomplete` badge passed\n * as `titleAdornment`, and the host's own JSON toggle then Save button as\n * `actions`.\n *\n * Presentation only: no query, mutation or navigation logic lives here — every\n * callback (`onBack`, `onChange`, `onBlur`) and every node in the action row is\n * the host's, mirroring the `ConnectionHeader.tsx` action-slot precedent.\n *\n * The rendered DOM of the Workflow editor's header is byte-for-byte what it\n * was before the extraction (`wf-fullbleed-head` / `wf-back-btn` /\n * `wf-title-input` / `wf-head-actions`, every `data-testid`, the `aria-label`\n * and the attribute order), which is what `styles.css`'s\n * `.wf-fullbleed-head input.wf-title-input` ancestor specificity and the\n * workflow header screenshot guard both depend on.\n */\n\n/** The editable title variant: the Workflow editor's inline-editable name. */\nexport interface EditableProfileTitle {\n /** The controlled value. */\n value: string;\n /** Called with the new text on every keystroke. */\n onChange: (next: string) => void;\n /** Called when the field loses focus — the Workflow host saves here. */\n onBlur: () => void;\n /** Shown while the value is empty; also the field's minimum sizing basis. */\n placeholder: string;\n /** The `maxLength` the input carries. */\n maxLength: number;\n /** The input's accessible name. */\n ariaLabel: string;\n}\n\n/** The read-only title variant: a Function/Endpoint editor's heading text. */\nexport interface ReadOnlyProfileTitle {\n value: string;\n}\n\n/** Which title the host mounts. The discriminant is `editable`. */\nexport type ExecutionProfileTitle =\n | ({ editable: true } & EditableProfileTitle)\n | ({ editable: false } & ReadOnlyProfileTitle);\n\n/**\n * The editable title field itself. Extracted so the input's own JSX — and the\n * `size` expression `src/lib/__tests__/workflow-title-size.test.ts` extracts\n * and RUNS — lives in one readable place. `size` is capped at the literal 80\n * (the same cap `maxLength` carries on the workflow host), independently of\n * `maxLength`: a name longer than 80 characters can only ever come from the\n * server, so `maxLength` alone would leave a pre-existing long name overflowing\n * its header.\n */\nfunction EditableTitle({ title }: { title: EditableProfileTitle }) {\n const { value, placeholder, maxLength, ariaLabel, onChange, onBlur } = title;\n return (\n <input\n className=\"wf-title-input\"\n value={value}\n placeholder={placeholder}\n maxLength={maxLength}\n size={Math.min(Math.max(value.length, placeholder.length), 80)}\n aria-label={ariaLabel}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n />\n );\n}\n\nexport interface ExecutionProfileHeaderProps {\n /** The back control's click handler — host-owned (the Workflow host clears\n * `?edit=`; `CallableEditorChrome` navigates to the kind's listing). */\n onBack: () => void;\n /** The back control's visible text — host-owned copy (`\"← Workflows\"`,\n * `descriptor.editor.backLabel`). */\n backLabel: string;\n /** Editable (Workflow) or read-only (Function/Endpoint) title. */\n title: ExecutionProfileTitle;\n /** Rendered immediately after a read-only title — the `incomplete` badge. */\n titleAdornment?: ReactNode;\n /** The host's action row (buttons only; this component owns the wrapper). */\n actions: ReactNode;\n}\n\nexport function ExecutionProfileHeader({\n onBack,\n backLabel,\n title,\n titleAdornment,\n actions,\n}: ExecutionProfileHeaderProps) {\n return (\n <div className=\"wf-fullbleed-head\">\n <button\n type=\"button\"\n className=\"muted wf-back-btn\"\n data-testid=\"wf-editor-back\"\n onClick={onBack}\n >\n {backLabel}\n </button>\n {title.editable ? (\n <EditableTitle title={title} />\n ) : (\n <h2 className=\"exec-profile-title\">\n {title.value} {titleAdornment}\n </h2>\n )}\n <div className=\"wf-head-actions\" style={{ marginLeft: \"auto\" }}>\n {actions}\n </div>\n </div>\n );\n}\n","import type { CallableKind, ExecutionSummary } from \"../repos/index.ts\";\n\n/**\n * The open-in-editor decision for a History view: only a workflow run has an editor to open, and\n * only when the host supplied `onOpenRun`. The handler closes the modal BEFORE handing the run id\n * to the host (the host's navigation then lands on an unobscured page).\n */\nexport function historyOpenRun(\n kind: CallableKind,\n onOpenRun: ((runId: string) => void) | undefined,\n onClose: () => void,\n): ((execution: ExecutionSummary) => void) | undefined {\n if (kind !== \"workflow\" || onOpenRun === undefined) return undefined;\n return (execution) => {\n onClose();\n onOpenRun(execution.id);\n };\n}\n","/**\n * `HistoryModal` (R-2 / T3.2.1) — the callable's own execution history,\n * opened as a full-page modal OVER the profile instead of away from it: the\n * route and the URL never change, so the editor underneath (unsaved edits,\n * canvas position, selected node) stays exactly as the author left it.\n * Mounted by `HistoryButton` in place of the navigation it used to do.\n *\n * `@w6w/ui`'s `Modal` at `size=\"full\"` (a near-fullscreen work surface,\n * `ui/src/components/Modal.tsx:12`) wraps `HistoryView`, scoped to this one\n * callable (`{ callable: id }`) with `showKind={false}` — a per-callable\n * view already knows its own kind. Filters are LOCAL state, starting empty\n * every time the modal opens, and are never written to the URL (HB10):\n * bookmarking a filtered view only makes sense for the standalone History\n * page, which still owns the URL-backed form.\n *\n * Closeable by ✕ (the `headerRight` button below), Esc (the real `Modal`'s\n * own `cancel` handling) or its backdrop click — all three funnel through\n * the same `onClose`, so the caller's \"focus returns to the History button\"\n * behaviour (`HistoryButton.tsx`) covers every dismissal path.\n *\n * \"Open in visual editor\" only ever applies to a workflow run, and every\n * execution this modal lists already belongs to THIS callable — its scope\n * is `{ callable: id }`, never project-wide — so there is no \"other\n * workflow\" branch to handle here (that one only exists on the project-wide\n * History page, which `HistoryPage.tsx` still owns). Closes the modal and\n * seeds `?run=` on the SAME route; `WorkflowsPage`'s own `[editId, runParam]`\n * effect (T2.4.2 HB7) is what opens the run overlay in place.\n */\nimport { type CallableKind, EMPTY_HISTORY_FILTERS, type HistoryFilters } from \"@w6w/embed/repos\";\nimport { IconButton, Modal } from \"@w6w/ui\";\nimport { useState } from \"react\";\nimport { HistoryView } from \"./HistoryView.tsx\";\nimport { historyOpenRun } from \"./history-open-run.ts\";\n\nexport interface HistoryModalProps {\n kind: CallableKind;\n id: string;\n onClose: () => void;\n /** Open a workflow run in the host's editor; absent ⇒ no open-in-editor affordance. */\n onOpenRun?: (runId: string) => void;\n}\n\nexport function HistoryModal(props: HistoryModalProps) {\n const { kind, id, onClose, onOpenRun } = props;\n const [filters, setFilters] = useState<HistoryFilters>(EMPTY_HISTORY_FILTERS);\n\n const onOpenInEditor = historyOpenRun(kind, onOpenRun, onClose);\n\n return (\n <Modal\n size=\"full\"\n title=\"History\"\n subtitle={id}\n onClose={onClose}\n headerRight={<IconButton icon=\"close\" label=\"Close\" onClick={onClose} />}\n >\n <div className=\"w6w-modal-body\">\n <HistoryView\n scope={{ callable: id }}\n showKind={false}\n filters={filters}\n onFiltersChange={setFilters}\n onOpenInEditor={onOpenInEditor}\n />\n </div>\n </Modal>\n );\n}\n","/**\n * The History affordance in the Function/Endpoint/Workflow editor headers\n * (T2.4.2, reworked by T3.2.1/R-2) — one icon button that opens the\n * callable's own execution history as a full-page modal OVER the profile\n * (`HistoryModal.tsx`) instead of navigating away from it, and refuses to\n * open while that callable has never executed.\n *\n * \"Has it ever executed?\" is `repos/history.ts`'s `useHasExecutedQuery` — the\n * cheap one-row `GET /history?callable=<id>&limit=1` existence probe (D1:\n * caller-scoped, exactly the rows its own History page lists). `hasExecuted`\n * reads `false` while that probe is in flight or has failed, so the button's\n * disabled state can never claim history that isn't there — the same \"no\n * false yes\" rule the hook's own docblock states.\n *\n * FAIL CLOSED WHEN THE ANSWER IS UNREADABLE. The hook assumes the envelope\n * (`{executions, hasMore}`) and dereferences `executions` directly, so a\n * response that is JSON but not that envelope — a bare `[]`, which several\n * older page-guard harnesses return from their catch-all for any unmodelled\n * `GET` — throws DURING RENDER. An uncaught render throw unmounts the whole\n * editor, so a header icon would be able to take the page down. The boundary\n * below keeps that failure inside this component and renders the same button\n * in its disabled state: no history is claimed, no modal is opened, and the\n * editor survives. The envelope-vs-array mismatch itself belongs to T2.3.1's\n * file (`src/repos/history.ts`), which this node must not edit.\n *\n * Chrome is `@w6w/ui`'s `IconButton` — the same borderless glyph-only control\n * `JsonToggle.tsx`'s `JsonToggleButton` renders, so the two header icon buttons\n * read as one family. The glyph is that component's `icon=\"history\"` (T2; the\n * local `HistoryIcon` hand-drawn SVG is gone), named `history` in the shared\n * set because it is the same drawing the left rail's History entry uses.\n *\n * Focus handling (R-2's \"closing it puts the user back exactly where they\n * were\"): the button keeps a ref to its own DOM node and refocuses it the\n * moment the modal reports `onClose`, regardless of which of the modal's own\n * three dismiss paths (✕, Esc, backdrop) fired it.\n */\nimport { type CallableKind, useHasExecutedQuery } from \"@w6w/embed/repos\";\nimport { IconButton } from \"@w6w/ui\";\nimport { Component, type ReactNode, type Ref, useEffect, useRef, useState } from \"react\";\nimport { HistoryModal } from \"./HistoryModal.tsx\";\n\nexport interface HistoryButtonProps {\n kind: CallableKind;\n id: string;\n /** Forwarded to the modal; see `HistoryModalProps.onOpenRun`. */\n onOpenRun?: (runId: string) => void;\n}\n\n/** The chrome itself, shared by the live button and the fail-closed fallback —\n * the fallback must be the SAME control (same test id, same name, same\n * glyph), only disabled, or a caller could tell the two apart by shape. */\nfunction HistoryButtonChrome({\n hasExecuted,\n onClick,\n buttonRef,\n}: {\n hasExecuted: boolean;\n onClick: () => void;\n buttonRef?: Ref<HTMLButtonElement>;\n}) {\n return (\n <IconButton\n ref={buttonRef}\n icon=\"history\"\n data-testid=\"history-button\"\n label=\"Execution history\"\n title={hasExecuted ? \"Execution history\" : \"No executions yet\"}\n disabled={!hasExecuted}\n onClick={onClick}\n />\n );\n}\n\n/** The probe's own render — the only thing that reads the query. Kept separate\n * so a throw from the hook lands on the boundary, not on the page. */\nfunction HistoryButtonProbe({ kind, id, onOpenRun }: HistoryButtonProps) {\n const { hasExecuted } = useHasExecutedQuery(id);\n const [open, setOpen] = useState(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n // Tracks the PREVIOUS `open` so the effect below only fires the moment the\n // modal actually goes from open to closed — never on first mount.\n const wasOpen = useRef(false);\n\n // Deferred to an effect (runs after the modal's `<dialog>` is gone from the\n // DOM) rather than called straight from `onClose`: while the native dialog\n // is still the top-layer modal, it traps focus, so a `.focus()` call fired\n // DURING its own `cancel`/dismiss handling can be silently ignored. Waiting\n // for the post-commit effect sidesteps that race for all three dismiss\n // paths (✕, Esc, backdrop) alike.\n useEffect(() => {\n if (wasOpen.current && !open) buttonRef.current?.focus();\n wasOpen.current = open;\n }, [open]);\n\n return (\n <>\n <HistoryButtonChrome\n hasExecuted={hasExecuted}\n buttonRef={buttonRef}\n onClick={() => setOpen(true)}\n />\n {open && (\n <HistoryModal kind={kind} id={id} onClose={() => setOpen(false)} onOpenRun={onOpenRun} />\n )}\n </>\n );\n}\n\n/** Last-resort boundary: an unreadable history answer disables the button\n * instead of unmounting the editor that hosts it. The fallback's `onClick` can\n * never fire (the button is disabled), so it does not need the router. */\nclass HistoryProbeBoundary extends Component<{ children: ReactNode }, { failed: boolean }> {\n state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n componentDidCatch(error: unknown): void {\n console.error(\"history probe answer was unreadable; disabling the button\", error);\n }\n\n render(): ReactNode {\n if (this.state.failed) return <HistoryButtonChrome hasExecuted={false} onClick={() => {}} />;\n return this.props.children;\n }\n}\n\nexport function HistoryButton(props: HistoryButtonProps) {\n return (\n <HistoryProbeBoundary>\n <HistoryButtonProbe {...props} />\n </HistoryProbeBoundary>\n );\n}\n","import { IconButton, JsonEditor } from \"@w6w/ui\";\nimport { Modal } from \"./Modal.tsx\";\n\nexport type JsonToggleMode = \"synced\" | \"disconnected\";\n\n/** The header icon button: `IconButton` with the set's `json` glyph — the\n * curly-brace icon, distinct from the `code` `</>` \"Call from code\" icon\n * beside it, so the two stop reading as the same button. The local\n * `JsonIcon` SVG this file used to carry is now `icon=\"json\"` in the shared\n * set. */\nexport function JsonToggleButton(props: { onClick: () => void }) {\n return <IconButton icon=\"json\" onClick={props.onClick} label=\"Edit raw JSON definition\" />;\n}\n\nexport interface JsonToggleProps {\n /** Parent-owned; render nothing when false. */\n open: boolean;\n onClose: () => void;\n /** Modal title. */\n title: string;\n mode: JsonToggleMode;\n /** Parent-owned text; the component keeps NO copy of it. */\n value: string;\n /** Every JsonEditor change, both modes. */\n onChange: (text: string) => void;\n /** JsonEditor's, error ?? null. */\n onValidityChange?: (v: { valid: boolean; error: string | null }) => void;\n /** When non-null: \"Invalid JSON — {invalidReason}\" (Workflow's existing line). */\n invalidReason?: string | null;\n /** Evaluated on `value` every render; non-null → shown in\n * <p className=\"muted small\" data-testid=\"json-toggle-reason\">. */\n guard?: (text: string) => string | null;\n /** disconnected only. */\n onSave?: () => void;\n /** disconnected only. */\n saving?: boolean;\n /** disconnected only; rendered as <div className=\"error\"> inside the dialog. */\n error?: string | null;\n /** JsonEditor aria-label. */\n editorLabel: string;\n}\n\n/**\n * The JSON⇄editor toggle's chrome — the header icon button's dialog, extracted\n * verbatim from `WorkflowsPage.tsx`'s raw-JSON modal (T2.1.1 D-2) so a second\n * host can reuse it in `mode=\"disconnected\"` (T2.1.2). Wraps `@w6w/ui`'s\n * `JsonEditor` and studio's own `Modal` (not `@w6w/ui`'s) — both existing\n * JSON-toggle-shaped precedents in this repo use studio's `Modal`.\n *\n * The component holds NO copy of `value`: every render shows exactly what the\n * parent hands it, which is what keeps a reopened dialog free of a stale\n * snapshot from the previous time it was open.\n */\nexport function JsonToggle(props: JsonToggleProps): JSX.Element | null {\n const {\n open,\n onClose,\n title,\n mode,\n value,\n onChange,\n onValidityChange,\n invalidReason,\n guard,\n onSave,\n saving,\n error,\n editorLabel,\n } = props;\n if (!open) return null;\n\n const guardReason = guard?.(value) ?? null;\n\n return (\n <Modal title={title} onClose={onClose} wide>\n <div className=\"modal-body\">\n <p className=\"muted small\">\n {mode === \"synced\" ? (\n <>\n Edit the raw definition (<code>manifestVersion: \"2\"</code>). Changes sync live to the\n visual editor.\n </>\n ) : (\n \"Save replaces the stored definition.\"\n )}\n </p>\n <JsonEditor\n value={value}\n onChange={onChange}\n onValidityChange={({ valid, error: err }) =>\n onValidityChange?.({ valid, error: err ?? null })\n }\n minHeight=\"420px\"\n aria-label={editorLabel}\n />\n {guardReason && (\n <p className=\"muted small\" data-testid=\"json-toggle-reason\">\n {guardReason}\n </p>\n )}\n {invalidReason && <div className=\"muted small\">Invalid JSON — {invalidReason}</div>}\n {error && <div className=\"error\">{error}</div>}\n </div>\n <div className=\"modal-actions\">\n {mode === \"synced\" ? (\n <button type=\"button\" className=\"btn ghost\" onClick={onClose}>\n Done\n </button>\n ) : (\n <>\n <button type=\"button\" className=\"btn ghost\" onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"btn\"\n data-testid=\"json-toggle-save\"\n disabled={guardReason != null || Boolean(saving)}\n onClick={onSave}\n >\n {saving ? \"Saving…\" : \"Save\"}\n </button>\n </>\n )}\n </div>\n </Modal>\n );\n}\n","import { createElement } from \"react\";\n\nexport interface BindingBannerProps {\n kind: \"workflow\" | \"function\" | \"endpoint\";\n problemCount: number;\n canEnable: boolean;\n onEnable: () => void;\n pending?: boolean;\n}\n\n/** The one \"disabled because a connection is gone\" banner all three editors render. */\nexport function BindingBanner(props: BindingBannerProps) {\n const { kind, problemCount, canEnable, onEnable, pending } = props;\n const text =\n problemCount > 0\n ? `This ${kind} is disabled and ${problemCount} ${problemCount === 1 ? \"step uses\" : \"steps use\"} a connection that no longer exists. Choose another connection, save, then Enable.`\n : \"Connections fixed. Enable to run again.\";\n return createElement(\n \"div\",\n { role: \"alert\", className: \"error\", \"data-testid\": \"binding-disabled-banner\" },\n createElement(\"span\", null, text),\n \" \",\n createElement(\n \"button\",\n {\n type: \"button\",\n \"data-testid\": \"binding-enable\",\n disabled: !canEnable || pending === true,\n onClick: onEnable,\n },\n \"Enable\",\n ),\n );\n}\n","/**\n * The editor frame shared by every callable editor: the rail environment, the project expression\n * scope, and (unless `rail={false}`) the workspace + `RightRail`. `WorkflowEditor` uses it; the\n * Function and Endpoint editors reuse it rather than re-inlining the providers.\n *\n * - `rail` omitted / `true`: its OWN nested `WorkspaceProvider` plus a `RightRail` — the editor's\n * rail, and the nested provider is what keeps a host's outer rail empty.\n * - `rail={false}`: no `RightRail`. Inside a `<CallableWorkspace>` the editor publishes into that\n * workspace; with none it mounts its own provider (no rail) so it can still publish and edit.\n */\nimport type { ReactNode } from \"react\";\nimport { type RailTool, RightRail } from \"../chrome/RightRail.tsx\";\nimport { WorkspaceProvider, useHasWorkspace } from \"../chrome/workspace.tsx\";\nimport { ProjectExpressionScope } from \"../rail/ExpressionScope.tsx\";\nimport { editorRailTools } from \"../rail/editor-tools.ts\";\nimport { RailEnvProvider, type RailNavigation } from \"../rail/rail-env.tsx\";\n\nexport interface EditorShellProps {\n /** Resolved project (`null` = none; tools refuse to save). */\n project: string | null;\n onNavigate: (to: RailNavigation) => void;\n /** Default `true`. `false`: render no rail; publish into the enclosing workspace if any. */\n rail?: boolean;\n /** Persisted-rail key; `null` = not yet persistable. */\n storageKey: string | null;\n /** Default {@link editorRailTools}. */\n tools?: readonly RailTool[];\n children: ReactNode;\n}\n\nexport function EditorShell({\n project,\n onNavigate,\n rail = true,\n storageKey,\n tools = editorRailTools,\n children,\n}: EditorShellProps): ReactNode {\n const enclosed = useHasWorkspace();\n const body = (\n <RailEnvProvider project={project} onNavigate={onNavigate}>\n <ProjectExpressionScope project={project}>\n {children}\n {rail && <RightRail tools={tools} storageKey={storageKey} />}\n </ProjectExpressionScope>\n </RailEnvProvider>\n );\n // Own provider when the rail is ours, or when there is no workspace to publish into.\n return rail || !enclosed ? <WorkspaceProvider>{body}</WorkspaceProvider> : body;\n}\n","import {\n type ExprValue,\n ExpressionInput,\n ExpressionOptionsProvider,\n IconButton,\n type SecretValue,\n useExpressionOptions,\n} from \"@w6w/ui\";\nimport { useState } from \"react\";\nimport { Modal } from \"../chrome/Modal.tsx\";\nimport { type WorkflowVariableRow, duplicateKeyIndexes, varsRailFor } from \"../lib/index.ts\";\n\n/** The settings modal's two tabs — General is always the one it opens on. */\nconst SETTINGS_TABS = [\"general\", \"variables\"] as const;\ntype SettingsTab = (typeof SETTINGS_TABS)[number];\n\n/** The `WorkflowVariable.type` union a row's type `<select>` offers. */\nconst VARIABLE_TYPES = [\"string\", \"number\", \"boolean\", \"object\", \"array\"] as const;\n\n/**\n * Per-workflow authoring settings (General) plus the Variables tab (T1.1.5) —\n * the workflow's declared `variables` list, its public input schema (HITL-5).\n * Both General flags are on unless the workflow says otherwise and persist\n * immediately (`saveMeta`, via `onChange`); every Variables edit instead goes\n * through the auto-saver (`onVariablesChange` → `patchMeta`, never an\n * immediate save — see the module docstring's Save path decision).\n */\nexport function WorkflowSettingsModal(props: {\n autoSave: boolean;\n savePosition: boolean;\n variables: WorkflowVariableRow[];\n onClose: () => void;\n onChange: (key: \"autoSave\" | \"savePosition\", value: boolean) => void;\n onVariablesChange: (next: WorkflowVariableRow[]) => void;\n}) {\n const { autoSave, savePosition, variables, onClose, onChange, onVariablesChange } = props;\n // The project's variable names, inherited from the app shell — the base list\n // `varsRailFor` narrows per row below.\n const inheritedVars = useExpressionOptions().vars ?? [];\n const [tab, setTab] = useState<SettingsTab>(\"general\");\n\n function addVariable() {\n onVariablesChange([...variables, { key: \"\" }]);\n }\n function updateVariable(i: number, next: Partial<WorkflowVariableRow>) {\n onVariablesChange(variables.map((v, idx) => (idx === i ? { ...v, ...next } : v)));\n }\n function removeVariable(i: number) {\n onVariablesChange(variables.filter((_, idx) => idx !== i));\n }\n const dupIndexes = duplicateKeyIndexes(variables);\n\n return (\n <Modal title=\"Workflow settings\" onClose={onClose} wide>\n <div className=\"w6w-subtabs\">\n <button\n type=\"button\"\n className={`w6w-subtab${tab === \"general\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"general\")}\n >\n General\n </button>\n <button\n type=\"button\"\n className={`w6w-subtab${tab === \"variables\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"variables\")}\n >\n Variables\n </button>\n </div>\n\n {tab === \"general\" ? (\n <>\n <div className=\"modal-body\">\n <p className=\"muted small\">\n These settings belong to the workflow, so everyone who opens it gets the same\n behaviour. Both are on unless you turn them off; each change saves straight away.\n </p>\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--w6w-sp-2)\",\n cursor: \"pointer\",\n }}\n title=\"Save edits as you make them, without pressing Save.\"\n >\n <input\n type=\"checkbox\"\n checked={autoSave}\n onChange={(e) => onChange(\"autoSave\", e.target.checked)}\n />\n <span className=\"muted small\">Auto-save edits</span>\n </label>\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--w6w-sp-2)\",\n cursor: \"pointer\",\n }}\n title=\"Keep the arrangement of the canvas — where each node sits, and the view you left it at.\"\n >\n <input\n type=\"checkbox\"\n checked={savePosition}\n onChange={(e) => onChange(\"savePosition\", e.target.checked)}\n />\n <span className=\"muted small\">Save node positions and canvas view</span>\n </label>\n </div>\n <div className=\"modal-actions\">\n {/* T1.3.1: Archive/Delete moved to the right rail's Settings tool\n — one consistent Settings surface, same archive-before-delete\n lifecycle, only relocated (D-I0.1-1). See\n `SettingsTool.tsx`'s own module docstring. */}\n <button type=\"button\" className=\"btn ghost\" onClick={onClose}>\n Done\n </button>\n </div>\n </>\n ) : (\n <>\n <div className=\"modal-body\">\n {/* HITL-5: declaring a variable flips this workflow's generated MCP\n tool from a pass-through schema to a declared one — say so. */}\n <p className=\"muted small\">\n Declaring variables here defines this workflow's <strong>public input schema</strong>:\n API and AI (MCP) callers then see exactly these inputs. With none declared, they may\n send anything.\n </p>\n <div className=\"row\" style={{ justifyContent: \"space-between\", alignItems: \"center\" }}>\n <span className=\"muted small\">\n {variables.length === 0\n ? \"No variables declared.\"\n : `${variables.length} variable${variables.length === 1 ? \"\" : \"s\"} declared.`}\n </span>\n <button type=\"button\" className=\"btn ghost\" onClick={addVariable}>\n + Add variable\n </button>\n </div>\n {variables.length > 0 && (\n <ul className=\"list\" data-testid=\"workflow-variables-list\">\n {variables.map((v, i) => (\n <li\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and reorderable\n key={i}\n style={{\n flexDirection: \"column\",\n alignItems: \"stretch\",\n gap: \"var(--w6w-sp-1)\",\n }}\n >\n <div className=\"row\" style={{ alignItems: \"center\", gap: \"var(--w6w-sp-2)\" }}>\n <input\n type=\"text\"\n value={v.key}\n placeholder=\"key\"\n aria-label=\"Variable key\"\n onChange={(e) => updateVariable(i, { key: e.target.value })}\n />\n <select\n value={v.type ?? \"\"}\n aria-label=\"Variable type\"\n onChange={(e) =>\n updateVariable(i, {\n type: (e.target.value || undefined) as WorkflowVariableRow[\"type\"],\n })\n }\n >\n <option value=\"\">(unset)</option>\n {VARIABLE_TYPES.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <label\n className=\"row\"\n style={{ gap: \"var(--w6w-sp-1)\", alignItems: \"center\" }}\n >\n <input\n type=\"checkbox\"\n checked={v.required ?? false}\n onChange={(e) => updateVariable(i, { required: e.target.checked })}\n />\n <span className=\"muted small\">required</span>\n </label>\n {/* Narrow `vars` for THIS row only: a variable's default\n may reference the variables declared above it, never\n itself or the ones below. Only that one key is\n contributed — secrets, documents, sample values and the\n callbacks come through from the app shell untouched,\n because the provider layers rather than replaces. */}\n <ExpressionOptionsProvider\n value={{ vars: varsRailFor(variables, i, inheritedVars) }}\n >\n <ExpressionInput\n // Re-key on the list's shape (not just `i`): ExpressionInput\n // seeds its parts once on mount and never again, so when a\n // row is removed and later rows shift up an index, React\n // must remount the widget rather than reuse the instance —\n // otherwise the surviving cell keeps showing the previous\n // occupant's default (see ExpressionInput.tsx:56-57).\n key={`${variables.length}:${i}`}\n value={v.default as ExprValue | string | SecretValue | undefined}\n onChange={(next) => updateVariable(i, { default: next })}\n placeholder=\"default\"\n aria-label=\"Variable default\"\n />\n </ExpressionOptionsProvider>\n <IconButton\n danger\n icon=\"close\"\n label={`Remove variable ${v.key || i + 1}`}\n onClick={() => removeVariable(i)}\n />\n </div>\n {dupIndexes.includes(i) && (\n <span className=\"muted small\" data-testid=\"variable-duplicate\">\n Duplicate key — a later row with the same name wins.\n </span>\n )}\n </li>\n ))}\n </ul>\n )}\n </div>\n <div className=\"modal-actions\">\n <button type=\"button\" className=\"btn ghost\" onClick={onClose}>\n Done\n </button>\n </div>\n </>\n )}\n </Modal>\n );\n}\n","import type { WorkflowStatus } from \"@w6w/sdk\";\nimport type { CallablePolicy, WorkflowSettings, WorkflowVariableRow } from \"../lib/index.ts\";\n\nexport type Parsed = Record<string, unknown> & {\n id?: string;\n name?: string;\n /** D-1: nullable, no backfill; `undefined` when the field is absent from\n * the text entirely — both mean \"no key\" to {@link workflowKeyEditAllowed}\n * (D-3). The rail's Key control (`SettingsTool.tsx`) is the only place\n * this is ever ASSIGNED; this page only ever reads it back. */\n key?: string | null;\n nodes?: unknown[];\n /** Legacy name for `nodes`; read via `workflowNodes`. */\n steps?: unknown[];\n status?: WorkflowStatus;\n tags?: string[];\n /** Authoring presentation — rides in the definition, no column of its own. */\n settings?: WorkflowSettings;\n /** Declared public input schema (T1.1.5) — see `workflow-variables.ts`. */\n variables?: WorkflowVariableRow[];\n /**\n * The RUN-level error policy (core Workflow RFC — *Amendment — 2026-08-21:\n * the run-level error handler*). Authored from the right rail's Error\n * handling tool, which this page hands a writer to rather than letting it\n * save independently — see the `useWorkspace` call below.\n */\n retry?: CallablePolicy[\"retry\"];\n onError?: CallablePolicy[\"onError\"];\n reroute?: CallablePolicy[\"reroute\"];\n};\n\n/** Workflow ids: start alphanumeric, then word chars / dots / dashes. */\nexport const ID_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;\n\n/** Placeholder + minimum sizing basis for the inline title field. */\nexport const TITLE_PLACEHOLDER = \"Untitled workflow\";\n","import { useQueries, useQueryClient } from \"@tanstack/react-query\";\nimport { ApiError } from \"@w6w/sdk\";\nimport {\n ExecutionLogPanel,\n IconButton,\n W6WUIProvider,\n isTestRequired,\n requiredParamsFilled,\n useW6WApi,\n} from \"@w6w/ui\";\nimport type { InternalNodeDef } from \"@w6w/ui/flow\";\nimport {\n type ReactNode,\n Suspense,\n lazy,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { ExecutionProfileHeader } from \"../chrome/ExecutionProfileHeader.tsx\";\nimport { HistoryButton } from \"../chrome/HistoryButton.tsx\";\nimport { JsonToggle, JsonToggleButton } from \"../chrome/JsonToggle.tsx\";\nimport { Modal } from \"../chrome/Modal.tsx\";\nimport { useWorkspace } from \"../chrome/workspace.tsx\";\nimport { useEmbedClient, useWorkflowDraft } from \"../draft/index.ts\";\nimport {\n type AppConnections,\n disabledBannerState,\n findBindingProblems,\n} from \"../lib/binding-problems.ts\";\nimport {\n type ActionParamLike,\n type CallablePolicy,\n type TriggerPreview,\n type TriggerPreviewFieldDef,\n type ValidityContext,\n type WorkflowLike,\n type WorkflowStepLike,\n definitionWithPolicy,\n invalidReason,\n policyFromDefinition,\n readSettings,\n readVariables,\n triggerPreviews,\n variablesForSave,\n workflowKeyEditAllowed,\n workflowValid,\n writeSetting,\n} from \"../lib/index.ts\";\nimport { workflowNodes } from \"../lib/workflow-nodes.ts\";\nimport { useEditorProject } from \"../project-context.ts\";\nimport type { RailNavigation } from \"../rail/rail-env.tsx\";\nimport { connectionsForAppKey, listConnectionsForApp } from \"../repos/connections.ts\";\nimport {\n classifyCancelError,\n isRunInFlight,\n listStepTests,\n mapRunStateToLogSteps,\n resolveHeaderRunInput,\n runButtonLabel,\n runLevelErrors,\n runNodeMap,\n stepTestsKey,\n useCancelRunMutation,\n useLiveRunQuery,\n usePublishMutation,\n useSetEnabledMutation,\n useStartRunMutation,\n useVersionsQuery,\n} from \"../repos/index.ts\";\nimport { EmbedThemeContext } from \"../theme-context.ts\";\nimport { BindingBanner } from \"./BindingBanner.tsx\";\nimport { EditorShell } from \"./EditorShell.tsx\";\nimport { WorkflowSettingsModal } from \"./WorkflowSettingsModal.tsx\";\nimport { ID_RE, type Parsed, TITLE_PLACEHOLDER } from \"./definition.ts\";\nimport { appActionsKey, useEditorApps } from \"./editor-apps.ts\";\nimport type {\n WorkflowEditorNavigation,\n WorkflowEditorProps,\n WorkflowEditorSlots,\n} from \"./types.ts\";\n\n// The visual editor is code-split — its @xyflow/react payload only loads when\n// the editor is actually open.\nconst WorkflowFlowEditor = lazy(() =>\n import(\"@w6w/ui/flow\").then((m) => ({ default: m.WorkflowFlowEditor })),\n);\n\nfunction EditorBody(props: {\n workflowId: string;\n project: string | null;\n initialRunId?: string;\n onNavigate: (to: WorkflowEditorNavigation) => void;\n slots?: WorkflowEditorSlots;\n}) {\n const { workflowId, project, initialRunId, onNavigate, slots } = props;\n const apiClient = useEmbedClient();\n const api = useW6WApi();\n const [valid, setValid] = useState(true);\n const [validityError, setValidityError] = useState<string | null>(null);\n // Page-level errors only (run, publish, create); the draft's own load/save errors come from\n // `useWorkflowDraft` (`draftError` below).\n const [error, setError] = useState<string | null>(null);\n const [showJson, setShowJson] = useState(false);\n const [showSettings, setShowSettings] = useState(false);\n const [reloading, setReloading] = useState(false);\n\n // D-3/P4: the key the SERVER most recently sent for the row the buffer is showing — what\n // `workflowKeyEditAllowed` compares the parsed text's own `key` against. `undefined` = nothing\n // loaded yet (refuses unconditionally). Captured whenever the buffer equals the server's copy\n // (load, 409 reload, and after a save), never while it holds unsaved edits. State, not a ref:\n // the guard below must change identity for the draft to re-evaluate it.\n const [loadedKey, setLoadedKey] = useState<string | null | undefined>(undefined);\n // Injected into the draft (the hook is headless — these are Studio's own rules).\n // `autoSave` and the publish-validity reason both depend on the parsed text, which the hook\n // itself produces, so they ride refs assigned after the call (one render of lag at most).\n const autoSaveRef = useRef(true);\n const publishReasonRef = useRef<(def: unknown) => string | null>(() => null);\n const saveGuard = useCallback(\n (def: unknown): string | null => {\n const d = def as Parsed;\n if (!ID_RE.test(typeof d.id === \"string\" ? d.id : \"\")) return \"Invalid workflow id.\";\n // D-3/P4: the rail's Key control is the only place a key is ever assigned — this JSON\n // editor must refuse to save a definition whose `key` differs from what was loaded. Folded\n // into the draft's save gate (never a separate `disabled` on the Save button): auto-save\n // reads the same gate, so a guard on the button alone would be bypassed by typing.\n return workflowKeyEditAllowed(loadedKey, d.key).reason;\n },\n [loadedKey],\n );\n // Load, buffer, save, auto-save, flush-on-hide/unmount and the 409 all live in the hook\n // (`../draft`). The project is `useEditorProject`'s answer (prop, else the provider's): with\n // none, the hook refuses to save (`saveBlockedReason`) rather than let the server pick the\n // account default.\n const draft = useWorkflowDraft({\n workflowId,\n project,\n autoSave: autoSaveRef.current,\n // The expression editor holds uncommitted parts in its own local state until its Save\n // button, so saving from under it would persist a workflow without the expression the user\n // is looking at. Read at fire time (opening it changes neither the buffer nor `canSave`).\n canAutoSave: () => !document.querySelector(\".w6w-exprmodal\"),\n saveGuard,\n publishBlockedReason: (def) => publishReasonRef.current(def),\n });\n const json = draft.json;\n const parsed = draft.parsed as Parsed | null;\n const canSave = draft.canSave;\n const dirty = draft.dirty;\n\n // Capture the server's key whenever the buffer equals the server's copy (never while it holds\n // unsaved edits), and forget it while a workflow is loading or failed to load.\n useEffect(() => {\n if (draft.loading || draft.loadError !== null) {\n setLoadedKey(undefined);\n return;\n }\n if (!draft.dirty && parsed) setLoadedKey((parsed.key as string | null | undefined) ?? null);\n }, [draft.loading, draft.loadError, draft.dirty, parsed]);\n\n // \"Keep editing\" dismisses the 409 modal; the draft stays stale (it refuses to save into the\n // conflict) until the author reloads.\n const [staleDismissed, setStaleDismissed] = useState(false);\n useEffect(() => {\n if (!draft.stale) setStaleDismissed(false);\n }, [draft.stale]);\n\n // The \"Saved.\" marker: a save finished without error since the last one began.\n const [saved, setSaved] = useState(false);\n const wasSaving = useRef(false);\n useEffect(() => {\n if (draft.saving) setSaved(false);\n else if (wasSaving.current && draft.error === null) setSaved(true);\n wasSaving.current = draft.saving;\n }, [draft.saving, draft.error]);\n\n // T2.1.1: the run this canvas is currently showing, if any. Reset inside\n // the `workflowId` load effect below, so a run from a previously open\n // workflow never bleeds into a different one's canvas.\n const [activeRunId, setActiveRunId] = useState<string | null>(null);\n\n // Names offered by each step field's expression picker (task 3.2). The vault\n // No project-scope memo here any more. The ƒx rail's vars, secrets,\n // documents, sample values and \"+ Add\"/seal callbacks are INHERITED from\n // `ProjectExpressionScope` (`App.tsx`); `WorkflowFlowEditor` and the settings\n // modal below both read them from context. What this page's editor\n // contributes on top — the upstream `steps` for one node, and the narrowed\n // `vars` rail for a variable's own default row — is added where it is known,\n // not restated here. See `ui/ExpressionScope.tsx`.\n\n // ── T2.1.1: Run/Stop in the visual editor — live poll, canvas feedback, ──\n // ── log panel, read-only lock. See building-blocks.md §G3/§G4/§G6/§5. ────\n const startRunMut = useStartRunMutation();\n const cancelRunMut = useCancelRunMutation();\n const runQuery = useLiveRunQuery(activeRunId);\n const runStatus = runQuery.data?.status;\n const runPollFailed = runQuery.isError;\n const runInFlight = isRunInFlight(runStatus, runPollFailed);\n // 26-10-04-01-fixes I-1: the run log's rows (each carrying its step's error)\n // and the run-level `error`/`stepErrors` the rows don't already show —\n // mapped once per render, shared by the panel's three props.\n // T5.1.1: a run record carries its per-node map under `nodes` (canonical) or\n // the legacy `steps` — `runNodeMap` prefers `nodes`.\n const runLogSteps = mapRunStateToLogSteps(runNodeMap(runQuery.data));\n const runLogErrors = runLevelErrors(runQuery.data, runLogSteps);\n // Header Run fetches the trigger's saved fixture before starting the run;\n // the ref guards re-entry synchronously (a second click can land before the\n // re-render that disables the button), the state disables the button.\n const runStartingRef = useRef(false);\n const [runStarting, setRunStarting] = useState(false);\n\n // ── T2.4.2: `?run=<runId>` — the History page's \"Open in visual editor\" ──\n // A workflow run's History row links to `workflows/<id>?run=<runId>`, and\n // THIS editor is what that link opens. The run plumbing above already\n // renders a terminal run exactly like a live one (`useLiveRunQuery` stops\n // polling on a terminal status by itself), so seeding `activeRunId` from the\n // URL is the whole feature — nothing about the poll, the canvas, the\n // read-only lock or the log panel moves.\n //\n // Declared AFTER the `workflowId` load effect on purpose: that effect resets\n // `activeRunId` for the row it is opening, and effects run in declaration\n // order, so on a mount the URL's run wins. Keyed on `[workflowId, initialRunId]`\n // rather than on mount alone, so an in-app transition to `?run=…` while the\n // editor stays mounted (`history.pushState` + `popstate`) still opens the\n // panel.\n // T2.1.1: a run belongs to the row that started it — the draft's load (formerly this page's\n // `workflowId` effect) reset it; declared BEFORE the `?run=` seed below so the URL's run still wins.\n // biome-ignore lint/correctness/useExhaustiveDependencies: `workflowId` is the trigger, not a value read\n useEffect(() => {\n setActiveRunId(null);\n }, [workflowId]);\n // biome-ignore lint/correctness/useExhaustiveDependencies: `workflowId`'s own value is never read below — it exists solely to re-seed the URL's run when the OPEN WORKFLOW changes, not as a value this closure needs (same retrigger-dependency shape as `api/w6wApiFacade.tsx`).\n useEffect(() => {\n if (initialRunId) setActiveRunId(initialRunId);\n }, [workflowId, initialRunId]);\n\n // The run id alone is not enough: a stale or hand-edited `?run=` can name a\n // run belonging to a DIFFERENT workflow, and painting that run's steps on\n // this canvas would be a lie. `RunState` carries its own `workflowId`, so the\n // first answer that names another workflow drops the run instead of\n // rendering it.\n useEffect(() => {\n if (runQuery.data && runQuery.data.workflowId !== workflowId) setActiveRunId(null);\n }, [runQuery.data, workflowId]);\n\n /**\n * T2.1.5: run `action` only once the buffer is saved. `blocked` shows its reason in the banner;\n * `failed` is already surfaced by the draft itself (banner, or the 409 modal via `draft.stale`).\n */\n async function runAfterFlush(action: () => Promise<unknown>) {\n try {\n const r = await draft.flushThen(action);\n if (!r.ok && r.outcome.status === \"blocked\") setError(r.outcome.reason);\n } catch (e) {\n setError(e instanceof ApiError ? e.message : String(e));\n }\n }\n\n async function onRunClick() {\n if (!workflowId || runInFlight || runStartingRef.current) return;\n setError(null);\n runStartingRef.current = true;\n setRunStarting(true);\n try {\n // 26-10-04-01-fixes I-1 (pinned): the manual trigger's latest saved Test-tab\n // values become the run's `input`, verbatim; no fixture (or no trigger,\n // or a failed fetch) sends no `input` key, exactly as before.\n const input = await resolveHeaderRunInput(triggerPreviewList?.[0]?.id, (stepId) =>\n listStepTests(apiClient, workflowId, stepId),\n );\n // T2.1.5 (R-27): the stored row is what runs, so an unsaved edit is saved FIRST. A refused\n // flush (`blocked` reason / `failed` save) never starts the run.\n await runAfterFlush(() =>\n startRunMut\n .mutateAsync({\n id: workflowId,\n variables: {},\n ...(input ? { input } : {}),\n })\n .then((res) => setActiveRunId(res.runId)),\n );\n } finally {\n runStartingRef.current = false;\n setRunStarting(false);\n }\n }\n\n function onStopClick() {\n if (!activeRunId) return;\n cancelRunMut.mutate(activeRunId, {\n onError: (e) => {\n const code = e instanceof ApiError ? e.code : \"\";\n // A `409 run_not_cancelable` means the run already finished before the\n // cancel request landed — reconcile via the next poll, no error banner.\n if (classifyCancelError(code) === \"surface\") {\n setError(e instanceof ApiError ? e.message : String(e));\n }\n },\n });\n // T1.1.1 A1: ask the server to cancel, but reset the LOCAL run state now —\n // the cancel is cooperative (heartbeat-driven) and may land long after the\n // click, so waiting for a poll to observe a terminal status would leave the\n // canvas greyed out in front of the user who just pressed Stop. The request\n // above still goes out, and `onError` still classifies the 409.\n setActiveRunId(null);\n }\n\n /** Replace the editor's contents with the server's copy and re-arm the token. */\n async function reloadFromServer() {\n setReloading(true);\n try {\n await draft.reload();\n setValid(true);\n setValidityError(null);\n setError(null);\n } finally {\n setReloading(false);\n }\n }\n\n // Page-level errors win; the draft's own load/save failure shows otherwise. A 409 is the\n // modal's business, not the banner's.\n const draftFailure = draft.stale ? null : (draft.error ?? draft.loadError);\n const bannerError =\n error ??\n (draftFailure === null\n ? null\n : draftFailure instanceof Error\n ? draftFailure.message\n : String(draftFailure));\n\n // Parse for the visual view + meta fields — the draft already parses (memoized) per edit.\n // T5.1.1: a definition declares its vertices under `nodes` (canonical) or the\n // legacy `steps` — either shape is drawable.\n const flowUsable =\n parsed !== null && (Array.isArray(parsed.nodes) || Array.isArray(parsed.steps));\n\n const displayName = (parsed?.displayName as string) ?? \"\";\n // Both flags are ON for a workflow that declares no `settings` — see readSettings.\n const settings = readSettings(parsed?.settings);\n // The Variables tab's rows (T1.1.5) — declaring the workflow's public input\n // schema (HITL-5). `useMemo` because `varsRailFor` runs once per row on\n // every render otherwise.\n const variables = useMemo(() => readVariables(parsed?.variables), [parsed?.variables]);\n // Visible only once something has actually loaded AND the parsed text is\n // real JSON — never flashes \"Workflow not loaded yet\" on a fresh mount\n // before the initial fetch resolves.\n const keyEdit = workflowKeyEditAllowed(loadedKey, parsed?.key);\n const keyGuardReason =\n parsed !== null && loadedKey !== undefined && !keyEdit.allowed ? keyEdit.reason : null;\n\n // ── Publish-time validity gate (T4.2.1) ──────────────────────────────────\n // T5.1.1: `workflowNodes` reads `nodes` (canonical) or the legacy `steps`.\n const steps = useMemo<WorkflowStepLike[]>(\n () => workflowNodes<WorkflowStepLike>(parsed as WorkflowLike | null),\n [parsed],\n );\n\n // `INTERNAL_NODES`/`isInternalApp`/`internalNodeParams` resolve from the SAME\n // `import(\"@w6w/ui/flow\")` the canvas's `lazy()` above already triggers (a\n // module-cache hit, not a second bundle) — only needed while the editor is\n // open, same as the canvas itself. Defaults to \"nothing resolved yet\", which\n // fails `hasTrigger`/`actionParamsByKey` closed (invalid) until it lands.\n const [flowHelpers, setFlowHelpers] = useState<{\n internalNodes: InternalNodeDef[];\n isInternalApp: (app: string) => boolean;\n internalNodeParams: (app: string, action: string) => ActionParamLike[];\n // \"Call from code\" trigger preview (T2.2.1) — `TRIGGER_APP`/`asFieldDefs`\n // resolve from the SAME import, no second dynamic import.\n isManualTrigger: (app: string) => boolean;\n asFieldDefs: (fields: unknown) => TriggerPreviewFieldDef[];\n } | null>(null);\n useEffect(() => {\n let canceled = false;\n import(\"@w6w/ui/flow\").then((m) => {\n if (canceled) return;\n setFlowHelpers({\n internalNodes: m.INTERNAL_NODES,\n isInternalApp: m.isInternalApp,\n internalNodeParams: m.internalNodeParams,\n isManualTrigger: (app) => app === m.TRIGGER_APP,\n asFieldDefs: m.asFieldDefs,\n });\n });\n return () => {\n canceled = true;\n };\n }, []);\n\n // \"Call from code\" trigger preview (T2.2.1, HITL-2/HITL-4 pinned): the\n // modal's per-trigger field picker, derived from the SAME `steps` above —\n // no new fetch, no new query key.\n const triggerPreviewList = useMemo<TriggerPreview[] | undefined>(() => {\n if (!flowHelpers) return undefined;\n return triggerPreviews(\n { steps },\n {\n isManualTrigger: flowHelpers.isManualTrigger,\n asFieldDefs: flowHelpers.asFieldDefs,\n },\n );\n }, [flowHelpers, steps]);\n\n // \"A trigger exists\" means a graph STEP whose (app, action) is a trigger\n // node (an `INTERNAL_NODES` entry with `group: \"trigger\"`) — not the\n // workflow's top-level `trigger` field, which `blankDefinition` always\n // seeds and so is truthy unconditionally (rfcs/workflow.md:114).\n const hasTrigger = useMemo(() => {\n if (!flowHelpers) return false;\n const triggerKeys = new Set(\n flowHelpers.internalNodes\n .filter((n) => n.group === \"trigger\")\n .map((n) => `${n.app}::${n.action}`),\n );\n return steps.some((s) => {\n const { app, action } = s.uses ?? {};\n return !!app && !!action && triggerKeys.has(`${app}::${action}`);\n });\n }, [flowHelpers, steps]);\n\n // Unique third-party (non-internal) app ids across the graph, batch-fetched\n // once each — mirrors the per-step fetch WorkflowFlowEditor already does\n // (WorkflowFlowEditor.tsx:~1432), hoisted to page level and de-duplicated.\n const thirdPartyAppIds = useMemo(() => {\n if (!flowHelpers) return [];\n const ids = new Set<string>();\n for (const s of steps) {\n const { app, action } = s.uses ?? {};\n if (app && action && !flowHelpers.isInternalApp(app)) ids.add(app);\n }\n return [...ids];\n }, [flowHelpers, steps]);\n // Registered apps, so the visual editor can render each action node with its\n // owning app's icon, display name, and version — bounded to the ids this\n // graph actually references (src/apps provider, T3.1.2).\n const { byId: fetchedAppsById } = useEditorApps(thirdPartyAppIds);\n const appsList = useMemo(() => [...fetchedAppsById.values()], [fetchedAppsById]);\n const appActionsQueries = useQueries({\n queries: thirdPartyAppIds.map((appId) => ({\n queryKey: appActionsKey(appId),\n queryFn: () => api.getAppActions(appId),\n })),\n });\n\n // Declared params for every step's target, internal (sync) or third-party\n // (fetched above) — keyed `${app}::${action}`, one entry per unique target.\n const actionParamsByKey = useMemo(() => {\n const out: Record<string, ActionParamLike[]> = {};\n if (!flowHelpers) return out;\n for (const s of steps) {\n const { app, action } = s.uses ?? {};\n if (!app || !action) continue;\n const key = `${app}::${action}`;\n if (key in out) continue;\n if (flowHelpers.isInternalApp(app)) {\n out[key] = flowHelpers.internalNodeParams(app, action);\n } else {\n const idx = thirdPartyAppIds.indexOf(app);\n const fetched = idx >= 0 ? appActionsQueries[idx]?.data : undefined;\n out[key] = fetched?.find((a) => a.key === action)?.params ?? [];\n }\n }\n return out;\n }, [flowHelpers, steps, thirdPartyAppIds, appActionsQueries]);\n\n const appsById = useMemo(() => {\n const out: Record<string, unknown> = {};\n for (const [id, a] of fetchedAppsById) out[id] = a;\n return out;\n }, [fetchedAppsById]);\n\n // Only a step whose app is BOTH a real fetched app AND opts into\n // testRequired needs a `listStepTests` fetch — an internal/trigger/control\n // step's app is never a key in `appsById`, so it is never gated.\n const testGatedSteps = useMemo(\n () =>\n steps.filter((s) => {\n const app = s.uses?.app;\n return !!app && app in appsById && isTestRequired(appsById[app]);\n }),\n [steps, appsById],\n );\n const stepTestsQueries = useQueries({\n queries: testGatedSteps.map((s) => ({\n queryKey: stepTestsKey(workflowId, s.id),\n queryFn: () => listStepTests(apiClient, workflowId, s.id),\n enabled: !!workflowId,\n })),\n });\n const testStatus = useMemo(() => {\n const out: Record<string, boolean> = {};\n testGatedSteps.forEach((s, i) => {\n out[s.id] = !!stepTestsQueries[i]?.data?.some((t) => t.lastRunStatus === \"succeeded\");\n });\n return out;\n }, [testGatedSteps, stepTestsQueries]);\n\n // T3.1.1: the Publish button's own published-state, gated the same shape\n // as `stepTestsQueries` above (`!!workflowId`) — never on mount\n // alone. Shares its cache entry with the Settings rail's own History\n // section (same `[\"versions\", \"workflow\", id]` key), so either surface's\n // Publish click refreshes both without a reload.\n const versionsQuery = useVersionsQuery(\"workflow\", workflowId, !!workflowId);\n const publishMut = usePublishMutation(\"workflow\");\n\n // R5: steps bound to a connection id the account no longer has. Connections per third-party\n // app share the `connectionsForAppKey` cache entry; only a settled, successful list can\n // convict a binding (loading / error never paint a false problem).\n const qc = useQueryClient();\n const connQueries = useQueries({\n queries: thirdPartyAppIds.map((appId) => ({\n queryKey: connectionsForAppKey(appId),\n queryFn: () => listConnectionsForApp(apiClient, appId),\n })),\n });\n const connByApp = useMemo(() => {\n const m = new Map<string, AppConnections>();\n thirdPartyAppIds.forEach((appId, i) => {\n const q = connQueries[i];\n if (!q) return;\n if (q.isError) m.set(appId, { state: \"error\" });\n else if (q.isSuccess && !q.isFetching)\n m.set(appId, { state: \"ready\", ids: new Set((q.data ?? []).map((c) => c.id)) });\n else m.set(appId, { state: \"loading\" });\n });\n return m;\n }, [thirdPartyAppIds, connQueries]);\n const bindingProblems = useMemo(\n () => findBindingProblems(steps, (app) => connByApp.get(app)),\n [steps, connByApp],\n );\n const stepProblems = useMemo(() => {\n const out: Record<string, { code: \"unknown_connection\"; connection: string }> = {};\n for (const p of bindingProblems) out[p.siteId] = { code: p.code, connection: p.connection };\n return out;\n }, [bindingProblems]);\n // A connection created through the step modal never touched this cache: refetch once per\n // (app, id) pair when the bound id is absent from a ready list. The latch stops any loop.\n const refetchedPairs = useRef(new Set<string>());\n useEffect(() => {\n for (const p of bindingProblems) {\n const pair = `${p.app}|${p.connection}`;\n if (refetchedPairs.current.has(pair)) continue;\n refetchedPairs.current.add(pair);\n qc.invalidateQueries({ queryKey: connectionsForAppKey(p.app) });\n }\n }, [bindingProblems, qc]);\n const hadProblemsRef = useRef({ id: workflowId, had: false });\n if (hadProblemsRef.current.id !== workflowId)\n hadProblemsRef.current = { id: workflowId, had: false };\n if (bindingProblems.length > 0) hadProblemsRef.current.had = true;\n const setEnabledMut = useSetEnabledMutation(\"workflow\");\n const bannerState = disabledBannerState({\n enabled: versionsQuery.data?.enabled,\n problemCount: bindingProblems.length,\n dirty: draft.dirty,\n hadProblems: hadProblemsRef.current.had,\n });\n\n const validityCtx = useMemo<ValidityContext>(\n () => ({\n hasTrigger,\n actionParamsByKey,\n appsById,\n testStatus,\n requiredParamsFilled,\n isTestRequired,\n }),\n [hasTrigger, actionParamsByKey, appsById, testStatus],\n );\n const workflowIsValid =\n parsed !== null && workflowValid(parsed as unknown as WorkflowLike, validityCtx);\n const publishInvalidReason =\n parsed !== null ? invalidReason(parsed as unknown as WorkflowLike, validityCtx) : null;\n\n publishReasonRef.current = (def) =>\n def !== null && typeof def === \"object\"\n ? invalidReason(def as unknown as WorkflowLike, validityCtx)\n : null;\n autoSaveRef.current = settings.autoSave;\n\n /** Patch top-level workflow fields, keeping the JSON text as source of truth. */\n function patchMeta(patch: Partial<Parsed>) {\n if (!parsed) return;\n const next: Parsed = { ...parsed, ...patch };\n draft.setJson(JSON.stringify(next, null, 2));\n }\n\n /** Patch top-level fields and persist immediately (for publish/tags edits). */\n function saveMeta(patch: Partial<Parsed>) {\n if (!parsed) return;\n const next: Parsed = { ...parsed, ...patch };\n setError(null);\n void draft.commit(JSON.stringify(next, null, 2));\n }\n\n // The rail's `onPolicyChange` must be referentially stable (see the `useWorkspace` call\n // below) and therefore cannot close over `parsed`/`draft` directly: it reads the live\n // definition and the draft's `commit` through refs.\n const parsedRef = useRef(parsed);\n parsedRef.current = parsed;\n const commitRef = useRef(draft.commit);\n commitRef.current = draft.commit;\n const saveNowRef = useRef(draft.saveNow);\n saveNowRef.current = draft.saveNow;\n\n // Cmd/Ctrl+S saves while the visual editor is open (mirrors the project\n // switcher's keydown effect in components/Layout.tsx: one guarded document\n // listener, symmetric cleanup).\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.altKey || !(e.metaKey || e.ctrlKey) || e.key.toLowerCase() !== \"s\") return;\n // Suppress the browser's Save Page dialog on every match, including the\n // paths below that decline to save.\n e.preventDefault();\n // The expression editor holds uncommitted parts in its own local state\n // until its Save button, so saving from under it would persist a workflow\n // without the expression the user is looking at.\n if (document.querySelector(\".w6w-exprmodal\")) return;\n if (!canSave) return;\n saveNowRef.current();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(\"keydown\", onKey);\n };\n }, [canSave]);\n\n // T2.1.2: publishes into the right rail's Code/Aliases tools — called on\n // EVERY render, into the `WorkspaceProvider` the outer `WorkflowEditor` mounts.\n //\n // The `policy`/`onPolicyChange` pair is the right rail's Error handling tool\n // (core Workflow RFC — *Amendment — 2026-08-21: the run-level error\n // handler*). The rail does NOT save a workflow itself: this page owns the\n // definition buffer and the draft saves it, so a second writer over the wire\n // would race the canvas and one side's edit would vanish. Handing the rail a\n // writer instead makes its Save fold into the very same JSON text.\n const wfPolicy = useMemo<CallablePolicy>(\n () => (parsed ? policyFromDefinition(parsed) : {}),\n [parsed],\n );\n // Referentially STABLE, as `workspace.tsx` requires: `useWorkspace` keys its\n // publish effect on `JSON.stringify(resource)`, which drops functions, so a\n // callback rebuilt per render would be stored once and then go stale. It\n // reads the current definition through `parsedRef` — always the live value,\n // never a captured one. Persists immediately, exactly like `saveMeta`'s\n // publish/tags edits.\n const onPolicyChange = useCallback((policy: CallablePolicy) => {\n const current = parsedRef.current;\n if (!current) return;\n const next = definitionWithPolicy(current, policy);\n setError(null);\n void commitRef.current(JSON.stringify(next, null, 2));\n }, []);\n\n useWorkspace({\n kind: \"workflow\",\n id: workflowId,\n label: displayName,\n key: parsed?.key ?? undefined,\n triggers: triggerPreviewList,\n policy: wfPolicy,\n onPolicyChange,\n });\n\n return (\n <div className=\"wf-fullbleed\" style={{ height: \"100%\", minWidth: 0, flex: 1 }}>\n {/* T3.1.1: the header itself is `ExecutionProfileHeader` — the SAME\n component a Function/Endpoint editor mounts through\n `CallableEditorChrome`. Everything below is host business: the\n back control (A8, updated by T4.1.1: the editor is its own route\n now, so \"back\" navigates to the LISTING — the sibling params it was\n opened with are kept, since they are the author's), the controlled\n name field that persists on blur, and the action row. */}\n {slots?.header ?? (\n <ExecutionProfileHeader\n onBack={() => onNavigate({ type: \"list\" })}\n backLabel={slots?.backLabel ?? \"← Workflows\"}\n title={{\n editable: true,\n value: displayName,\n placeholder: TITLE_PLACEHOLDER,\n maxLength: 80,\n ariaLabel: \"Workflow name\",\n onChange: (next) => patchMeta({ displayName: next }),\n onBlur: () => {\n if (canSave) draft.saveNow();\n },\n }}\n actions={\n <>\n <IconButton\n icon=\"play\"\n label={runButtonLabel(runStatus, runPollFailed)}\n data-testid=\"wf-run-start\"\n onClick={onRunClick}\n disabled={!workflowId || runInFlight || runStarting || startRunMut.isPending}\n />\n {runInFlight && (\n <IconButton\n icon=\"stop\"\n label=\"Stop this run\"\n data-testid=\"wf-run-stop\"\n onClick={onStopClick}\n disabled={cancelRunMut.isPending}\n />\n )}\n <button\n type=\"button\"\n className={`btn ghost wf-publish${versionsQuery.data?.currentPublishedVersion != null ? \" active\" : \"\"}`}\n data-testid=\"wf-publish\"\n onClick={() => {\n if (!workflowId) return;\n setError(null);\n void runAfterFlush(() => publishMut.mutateAsync(workflowId));\n }}\n disabled={project === null || !canSave || !workflowIsValid || publishMut.isPending}\n title={\n canSave && !workflowIsValid\n ? (publishInvalidReason ?? \"Workflow is not valid\")\n : versionsQuery.data?.currentPublishedVersion != null\n ? \"Published — click to publish a new version\"\n : \"Never published — click to publish\"\n }\n >\n {publishMut.isPending\n ? \"Publishing…\"\n : versionsQuery.data?.currentPublishedVersion != null\n ? \"● Published\"\n : \"Publish\"}\n </button>\n <HistoryButton\n kind=\"workflow\"\n id={workflowId}\n onOpenRun={(runId) => {\n setActiveRunId(runId);\n onNavigate({ type: \"run\", id: workflowId, runId });\n }}\n />\n <JsonToggleButton onClick={() => setShowJson(true)} />\n {/* T2.1.2: \"Call from code\" moved to the right rail's Code tool —\n see the `useWorkspace` call above (this closes the prior\n project's HITL-1: the flow editor now publishes, since the\n gate is the editor's own mount, not the route wrapper that could\n never see this component's route param). */}\n <IconButton\n icon=\"settings\"\n label=\"Workflow settings\"\n onClick={() => setShowSettings(true)}\n />\n {slots?.headerActions}\n </>\n }\n />\n )}\n {bannerState.show && (\n <BindingBanner\n kind=\"workflow\"\n problemCount={bannerState.problemCount}\n canEnable={bannerState.canEnable}\n pending={setEnabledMut.isPending}\n onEnable={() => setEnabledMut.mutate({ id: workflowId, enabled: true })}\n />\n )}\n <div className=\"wf-fullbleed-canvas\">\n <div className=\"wf-run-area\">\n <div className=\"wf-run-canvas\">\n <Suspense fallback={<p className=\"muted\">Loading visual editor…</p>}>\n {flowUsable && parsed ? (\n <WorkflowFlowEditor\n // The parsed cast is safe: onChange only receives shapes we produced.\n value={parsed as unknown as Parameters<typeof WorkflowFlowEditor>[0][\"value\"]}\n onChange={(next) => {\n draft.setJson(JSON.stringify(next, null, 2));\n setValid(true);\n setValidityError(null);\n // T1.1.1 A2.1: an edit to the graph — a canvas edit or a\n // step-config commit from `StepEditModal`, both of which\n // arrive here — means the run this canvas was showing is\n // no longer the thing the author is looking at.\n setActiveRunId(null);\n }}\n apps={appsList}\n project={project ?? undefined}\n height=\"100%\"\n // A4: locked while the run this canvas is showing is still\n // in flight, unlocked again on every terminal status AND\n // when the poll itself gives up or errors.\n readOnly={runInFlight}\n // L-3b: re-frame the graph when the run-log panel docks\n // beside it and again when it leaves — keyed on the panel\n // being MOUNTED (`activeRunId`, same condition as the\n // `wf-run-log` block below), not on `runInFlight` (the\n // panel stays after a terminal status) nor on the run's\n // data (changes every poll tick).\n fitViewKey={activeRunId !== null}\n stepProblems={stepProblems}\n // A3: each intermediate RunState reaches the canvas as it\n // arrives — the cast crosses the same opaque-`steps`\n // boundary `getRunState`'s own callers already cross (the\n // SDK's console `RunState.steps` is `Record<string,\n // unknown>` on purpose; the server's real per-step shape\n // structurally satisfies `ui`'s narrower `RunState`).\n runState={\n runQuery.data as unknown as Parameters<typeof WorkflowFlowEditor>[0][\"runState\"]\n }\n // T1.1.1 A3: a step test starts → the run this canvas was\n // showing is no longer the thing under test, so drop it on\n // the click rather than waiting for the test's result.\n onTestRun={() => setActiveRunId(null)}\n />\n ) : json === \"\" ? (\n <p className=\"muted\">Loading…</p>\n ) : (\n <p className=\"muted\">Fix the JSON to render the visual editor.</p>\n )}\n </Suspense>\n </div>\n {activeRunId && (\n <div className=\"wf-run-log\" data-testid=\"wf-run-log\">\n <ExecutionLogPanel\n steps={runLogSteps}\n runError={runLogErrors.runError}\n stepErrors={runLogErrors.stepErrors}\n // T1.1.1 A4: the one explicit \"I'm done looking at this run\"\n // control — same lever as Stop, so it must work in the empty\n // branch too (the panel renders its head there as well).\n onDismiss={() => setActiveRunId(null)}\n />\n </div>\n )}\n </div>\n </div>\n {project === null && (\n <div role=\"alert\" className=\"error\" data-testid=\"wf-project-required\">\n No project selected — pass a <code>project</code> prop (or set the provider's project) to\n edit and save this workflow.\n </div>\n )}\n <div className=\"wf-fullbleed-foot\">\n <div className=\"row\" style={{ flexWrap: \"wrap\", alignItems: \"center\" }}>\n {/* Auto-save does not remove this button (it is the escape hatch when\n `autoSave` is off, and the only legible signal of save state when it\n is on): it flushes the pending window now, and greys out once the\n canvas matches the server. */}\n <button\n type=\"button\"\n className=\"btn\"\n disabled={project === null || !canSave || !dirty}\n onClick={draft.saveNow}\n >\n {draft.saving ? \"Saving…\" : \"Save\"}\n </button>\n {saved && <span className=\"ok\">Saved.</span>}\n </div>\n {bannerError && <div className=\"error\">{bannerError}</div>}\n {keyGuardReason && (\n <div className=\"error\" data-testid=\"wf-key-guard\">\n {keyGuardReason}\n </div>\n )}\n </div>\n\n <JsonToggle\n open={showJson}\n onClose={() => setShowJson(false)}\n title={`JSON — ${(parsed?.displayName as string) || \"workflow\"}`}\n mode=\"synced\"\n value={json}\n onChange={(next) => {\n draft.setJson(next);\n // T1.1.1 A2.2 (D-2): the raw-JSON surface is an edit surface\n // too, so it clears the shown run the same way the canvas does.\n setActiveRunId(null);\n }}\n onValidityChange={({ valid: v, error: err }) => {\n setValid(v);\n setValidityError(err);\n }}\n invalidReason={!valid ? validityError : null}\n editorLabel=\"Workflow definition JSON\"\n />\n\n {draft.stale && !staleDismissed && (\n <Modal title=\"This workflow changed on the server\" onClose={() => setStaleDismissed(true)}>\n <div className=\"modal-body\">\n <p className=\"muted small\">\n Someone else — another tab, another session — saved this workflow after you opened it.\n Your save was refused rather than applied, so their work is still intact.\n </p>\n <p className=\"muted small\">\n <strong>Reload from server</strong> replaces what is on this canvas with the saved\n copy; anything you changed here and have not saved is lost.{\" \"}\n <strong>Keep editing</strong> leaves your version exactly as it is — but every save\n will be refused the same way until you reload, so copy out anything you need first.\n </p>\n </div>\n <div className=\"modal-actions\">\n <button type=\"button\" className=\"btn ghost\" onClick={() => setStaleDismissed(true)}>\n Keep editing\n </button>\n <button type=\"button\" className=\"btn\" disabled={reloading} onClick={reloadFromServer}>\n {reloading ? \"Reloading…\" : \"Reload from server\"}\n </button>\n </div>\n </Modal>\n )}\n\n {showSettings && (\n <WorkflowSettingsModal\n autoSave={settings.autoSave}\n savePosition={settings.savePosition}\n variables={variables}\n onClose={() => setShowSettings(false)}\n onChange={(key, value) =>\n saveMeta({ settings: writeSetting(parsed?.settings, key, value) })\n }\n onVariablesChange={(next) => patchMeta({ variables: variablesForSave(next) })}\n />\n )}\n </div>\n );\n}\n\nfunction StepTestApiProvider({ children }: { children: ReactNode }) {\n const api = useW6WApi();\n const qc = useQueryClient();\n const theme = useContext(EmbedThemeContext);\n const wrappedApi = useMemo(() => {\n const saveStepTest = (...args: Parameters<typeof api.saveStepTest>) =>\n api.saveStepTest(...args).finally(() => {\n void qc.invalidateQueries({ queryKey: stepTestsKey(args[0], args[1]) });\n });\n const recordStepTestRun = (...args: Parameters<typeof api.recordStepTestRun>) =>\n api.recordStepTestRun(...args).finally(() => {\n void qc.invalidateQueries({ queryKey: stepTestsKey(args[0], args[1]) });\n });\n return { ...api, saveStepTest, recordStepTestRun };\n }, [api, qc]);\n return (\n <W6WUIProvider api={wrappedApi} theme={theme}>\n {children}\n </W6WUIProvider>\n );\n}\n\nconst NOOP = (): void => {};\n\n/**\n * The managed workflow editor. The outermost element is `.w6w-embed-root` (pinned for the embed\n * stylesheet); everything the editor renders — header, canvas, modals, rail — stays a descendant of\n * it, and nothing goes through a portal. It fills its host container (`height: 100%`), so the host\n * decides how tall the editor is.\n *\n * `useEditorProject(props.project)` is the ONLY project source: it feeds the draft, the expression\n * scope, the rail environment and the canvas. `null` (no project) refuses — see `EditorBody`.\n */\nexport function WorkflowEditor(props: WorkflowEditorProps): ReactNode {\n const { workflowId, initialRunId, onNavigate = NOOP, slots } = props;\n const project = useEditorProject(props.project);\n const railNavigate = useCallback(\n (to: RailNavigation) => {\n if (to.type === \"list\") onNavigate({ type: \"list\" });\n else if (to.kind === \"workflow\") onNavigate({ type: \"workflow\", id: to.id });\n },\n [onNavigate],\n );\n return (\n <div\n className=\"w6w-embed-root\"\n style={{ display: \"flex\", width: \"100%\", height: \"100%\", minHeight: 0 }}\n >\n <EditorShell\n project={project}\n onNavigate={railNavigate}\n rail={props.rail}\n storageKey={project === null ? null : `w6w.rail.embed.${project}`}\n >\n <StepTestApiProvider>\n <EditorBody\n workflowId={workflowId}\n project={project}\n initialRunId={initialRunId}\n onNavigate={onNavigate}\n slots={slots}\n />\n </StepTestApiProvider>\n </EditorShell>\n </div>\n );\n}\n"],"names":["EditableTitle","title","value","placeholder","maxLength","ariaLabel","onChange","onBlur","jsx","e","ExecutionProfileHeader","onBack","backLabel","titleAdornment","actions","jsxs","historyOpenRun","kind","onOpenRun","onClose","execution","HistoryModal","props","id","filters","setFilters","useState","EMPTY_HISTORY_FILTERS","onOpenInEditor","Modal","IconButton","HistoryView","HistoryButtonChrome","hasExecuted","onClick","buttonRef","HistoryButtonProbe","useHasExecutedQuery","open","setOpen","useRef","wasOpen","useEffect","_a","Fragment","HistoryProbeBoundary","Component","__publicField","error","HistoryButton","JsonToggleButton","JsonToggle","mode","onValidityChange","invalidReason","guard","onSave","saving","editorLabel","guardReason","JsonEditor","valid","err","BindingBanner","problemCount","canEnable","onEnable","pending","text","createElement","EditorShell","project","onNavigate","rail","storageKey","tools","editorRailTools","children","enclosed","useHasWorkspace","body","RailEnvProvider","ProjectExpressionScope","RightRail","WorkspaceProvider","VARIABLE_TYPES","WorkflowSettingsModal","autoSave","savePosition","variables","onVariablesChange","inheritedVars","useExpressionOptions","tab","setTab","addVariable","updateVariable","i","next","v","idx","removeVariable","_","dupIndexes","duplicateKeyIndexes","t","ExpressionOptionsProvider","varsRailFor","ExpressionInput","ID_RE","TITLE_PLACEHOLDER","WorkflowFlowEditor","lazy","m","EditorBody","workflowId","initialRunId","slots","apiClient","useEmbedClient","api","useW6WApi","setValid","validityError","setValidityError","setError","showJson","setShowJson","showSettings","setShowSettings","reloading","setReloading","loadedKey","setLoadedKey","autoSaveRef","publishReasonRef","saveGuard","useCallback","def","d","workflowKeyEditAllowed","draft","useWorkflowDraft","json","parsed","canSave","dirty","staleDismissed","setStaleDismissed","saved","setSaved","wasSaving","activeRunId","setActiveRunId","startRunMut","useStartRunMutation","cancelRunMut","useCancelRunMutation","runQuery","useLiveRunQuery","runStatus","runPollFailed","runInFlight","isRunInFlight","runLogSteps","mapRunStateToLogSteps","runNodeMap","runLogErrors","runLevelErrors","runStartingRef","runStarting","setRunStarting","runAfterFlush","action","r","ApiError","onRunClick","input","resolveHeaderRunInput","triggerPreviewList","stepId","listStepTests","res","onStopClick","code","classifyCancelError","reloadFromServer","draftFailure","bannerError","flowUsable","displayName","settings","readSettings","useMemo","readVariables","keyEdit","keyGuardReason","steps","workflowNodes","flowHelpers","setFlowHelpers","canceled","app","triggerPreviews","hasTrigger","triggerKeys","s","thirdPartyAppIds","ids","fetchedAppsById","useEditorApps","appsList","appActionsQueries","useQueries","appId","appActionsKey","actionParamsByKey","out","key","fetched","_b","a","appsById","testGatedSteps","isTestRequired","stepTestsQueries","stepTestsKey","testStatus","versionsQuery","useVersionsQuery","publishMut","usePublishMutation","qc","useQueryClient","connQueries","connectionsForAppKey","listConnectionsForApp","connByApp","q","c","bindingProblems","findBindingProblems","stepProblems","p","refetchedPairs","pair","hadProblemsRef","setEnabledMut","useSetEnabledMutation","bannerState","disabledBannerState","validityCtx","requiredParamsFilled","workflowIsValid","workflowValid","publishInvalidReason","patchMeta","patch","saveMeta","parsedRef","commitRef","saveNowRef","onKey","wfPolicy","policyFromDefinition","onPolicyChange","policy","current","definitionWithPolicy","useWorkspace","runButtonLabel","_c","_d","_e","runId","Suspense","ExecutionLogPanel","writeSetting","variablesForSave","StepTestApiProvider","theme","useContext","EmbedThemeContext","wrappedApi","args","W6WUIProvider","NOOP","WorkflowEditor","useEditorProject","railNavigate","to"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useQuery as s, keepPreviousData as p } from "@tanstack/react-query";
|
|
2
2
|
import { u } from "./client-context-CX61Bgw-.js";
|
|
3
|
-
import { H as l,
|
|
3
|
+
import { H as l, j as y, o, k as a, E as q, l as d } from "./spec-import-CW6R_Wk1.js";
|
|
4
4
|
const c = { project: "" };
|
|
5
5
|
function F(e, t, n = l) {
|
|
6
6
|
const i = u();
|
|
@@ -30,7 +30,7 @@ function S(e) {
|
|
|
30
30
|
isLoading: n.isLoading
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
-
function
|
|
33
|
+
function C(e) {
|
|
34
34
|
const t = u();
|
|
35
35
|
return s({
|
|
36
36
|
queryKey: o.detail((e == null ? void 0 : e.kind) ?? "function", (e == null ? void 0 : e.id) ?? ""),
|
|
@@ -42,7 +42,7 @@ const f = (e) => ["app-actions", e];
|
|
|
42
42
|
function g(e, t) {
|
|
43
43
|
return e.console.apps.getActions(t);
|
|
44
44
|
}
|
|
45
|
-
function
|
|
45
|
+
function b(e, t = !0) {
|
|
46
46
|
const n = u();
|
|
47
47
|
return s({
|
|
48
48
|
queryKey: f(e),
|
|
@@ -54,7 +54,7 @@ const E = (e) => ["app", e];
|
|
|
54
54
|
function A(e, t) {
|
|
55
55
|
return e.console.apps.get(t);
|
|
56
56
|
}
|
|
57
|
-
function
|
|
57
|
+
function h(e, t = !0) {
|
|
58
58
|
const n = u();
|
|
59
59
|
return s({
|
|
60
60
|
queryKey: E(e ?? ""),
|
|
@@ -63,15 +63,15 @@ function b(e, t = !0) {
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
export {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
Q as a,
|
|
67
|
+
C as b,
|
|
68
|
+
f as c,
|
|
69
|
+
E as d,
|
|
70
|
+
g as e,
|
|
71
|
+
b as f,
|
|
72
72
|
A as g,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
h,
|
|
74
|
+
S as i,
|
|
75
|
+
F as u
|
|
76
76
|
};
|
|
77
|
-
//# sourceMappingURL=apps-
|
|
77
|
+
//# sourceMappingURL=apps-CboASBKr.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps-
|
|
1
|
+
{"version":3,"file":"apps-CboASBKr.js","sources":["../src/repos/history.ts","../src/repos/apps.ts"],"sourcesContent":["/**\n * The `history` domain repo (T2.3.1) — thin react-query hooks over\n * `lib/history-query.ts`'s pure fetchers, mirroring `./dashboard.ts`'s\n * shape exactly: the query keys ship from the pure module, not from here or\n * from a caller; every hook is `useEmbedClient()` + one `useQuery`.\n *\n * `lib/history-query.ts` carries every judgment call (URL⇄filter mapping,\n * request params, cache keys, fetchers, detail mapping) so it stays loadable\n * by `node --test`; this file adds nothing but React wiring on top of it.\n */\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\nimport {\n EMPTY_HISTORY_FILTERS,\n type ExecutionSummary,\n HISTORY_PAGE_SIZE,\n type HistoryFilters,\n type HistoryScope,\n getExecutionDetail,\n getHistory,\n getHistoryStats,\n historyKeys,\n} from \"../lib/history-query.ts\";\n\n/** A placeholder scope to key a disabled query by — never fetched, since\n * `enabled` gates on the real (possibly `null`) scope, matching\n * `repos/workflows.ts`'s `useLiveRunQuery(runId ?? \"\")` idiom. */\nconst NO_SCOPE: HistoryScope = { project: \"\" };\n\n/** The project-wide or per-callable execution list, one page at a time.\n * Disabled while `scope` is `null` (no project/callable selected yet).\n * `placeholderData: keepPreviousData` keeps the previous page's rows on\n * screen while a filter/page change is in flight, instead of flashing to\n * an empty list. */\nexport function useHistoryQuery(\n scope: HistoryScope | null,\n f: HistoryFilters,\n limit: number = HISTORY_PAGE_SIZE,\n) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: historyKeys.list(scope ?? NO_SCOPE, f, limit),\n queryFn: () => getHistory(apiClient, scope as HistoryScope, f, limit),\n enabled: scope !== null,\n placeholderData: keepPreviousData,\n });\n}\n\n/** The aggregate stats card above the list — same scope/filters, no paging.\n * Disabled while `scope` is `null`. */\nexport function useHistoryStatsQuery(scope: HistoryScope | null, f: HistoryFilters) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: historyKeys.stats(scope ?? NO_SCOPE, f),\n queryFn: () => getHistoryStats(apiClient, scope as HistoryScope, f),\n enabled: scope !== null,\n });\n}\n\n/** \"Has this callable ever been executed?\" — the cheap existence probe the\n * header's History button uses to decide its disabled state (one row,\n * every filter at its default). `hasExecuted` reads `false` while loading\n * or on error — never a false \"yes\". */\nexport function useHasExecutedQuery(callableId: string): {\n hasExecuted: boolean;\n isLoading: boolean;\n} {\n const apiClient = useEmbedClient();\n const query = useQuery({\n queryKey: historyKeys.exists(callableId),\n queryFn: () => getHistory(apiClient, { callable: callableId }, EMPTY_HISTORY_FILTERS, 1),\n });\n return {\n hasExecuted: (query.data?.executions?.length ?? 0) > 0,\n isLoading: query.isLoading,\n };\n}\n\n/** One execution's full detail, opened from a list row. Disabled while\n * `summary` is `null` (no row selected). */\nexport function useExecutionDetailQuery(summary: ExecutionSummary | null) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: historyKeys.detail(summary?.kind ?? \"function\", summary?.id ?? \"\"),\n queryFn: () => getExecutionDetail(apiClient, summary as ExecutionSummary),\n enabled: summary !== null,\n });\n}\n","/**\n * The per-app Actions repo — what the Target selector and the canvas's step pickers read.\n *\n * Moved from Studio's `repos/apps.ts` (B-3a); the Studio file re-exports these names. The client\n * comes from `useEmbedClient()`. `GET /apps/:id` through `client.console.apps.getActions` is the\n * same payload the W6WApi adapter serves the canvas, and the key is byte-identical to the one\n * the editor and `WorkflowsPage` compose by hand, so every reader shares one cache entry.\n */\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { W6WClient } from \"@w6w/sdk\";\nimport type { ActionDef, AppDetail } from \"@w6w/sdk/console\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n\nexport const appActionsKey = (id: string) => [\"app-actions\", id] as const;\n\nexport function getAppActions(client: W6WClient, id: string): Promise<ActionDef[]> {\n return client.console.apps.getActions(id);\n}\n\n/** `enabled` defaults to `true`; a selector passes `app !== \"\"` so an empty app issues nothing. */\nexport function useAppActionsQuery(id: string, enabled = true) {\n const client = useEmbedClient();\n return useQuery({\n queryKey: appActionsKey(id),\n queryFn: () => getAppActions(client, id),\n enabled,\n });\n}\n\n// ── app (detail) ─────────────────────────────────────────────────────────\n\nexport const appKey = (id: string) => [\"app\", id] as const;\n\nexport function getApp(client: W6WClient, id: string): Promise<AppDetail> {\n return client.console.apps.get(id);\n}\n\n/**\n * `id` accepts `string | undefined`: a detail view's app id is `undefined` until its own\n * connection query resolves, so the caller passes `enabled` (its `!!id` guard) instead of\n * `!`-asserting.\n */\nexport function useAppQuery(id: string | undefined, enabled = true) {\n const client = useEmbedClient();\n return useQuery({\n queryKey: appKey(id ?? \"\"),\n queryFn: () => getApp(client, id as string),\n enabled,\n });\n}\n"],"names":["NO_SCOPE","useHistoryQuery","scope","f","limit","HISTORY_PAGE_SIZE","apiClient","useEmbedClient","useQuery","historyKeys","getHistory","keepPreviousData","useHistoryStatsQuery","getHistoryStats","useHasExecutedQuery","callableId","query","EMPTY_HISTORY_FILTERS","_b","_a","useExecutionDetailQuery","summary","getExecutionDetail","appActionsKey","id","getAppActions","client","useAppActionsQuery","enabled","appKey","getApp","useAppQuery"],"mappings":";;;AA2BA,MAAMA,IAAyB,EAAE,SAAS,GAAA;AAOnC,SAASC,EACdC,GACAC,GACAC,IAAgBC,GAChB;AACA,QAAMC,IAAYC,EAAA;AAClB,SAAOC,EAAS;AAAA,IACd,UAAUC,EAAY,KAAKP,KAASF,GAAUG,GAAGC,CAAK;AAAA,IACtD,SAAS,MAAMM,EAAWJ,GAAWJ,GAAuBC,GAAGC,CAAK;AAAA,IACpE,SAASF,MAAU;AAAA,IACnB,iBAAiBS;AAAA,EAAA,CAClB;AACH;AAIO,SAASC,EAAqBV,GAA4BC,GAAmB;AAClF,QAAMG,IAAYC,EAAA;AAClB,SAAOC,EAAS;AAAA,IACd,UAAUC,EAAY,MAAMP,KAASF,GAAUG,CAAC;AAAA,IAChD,SAAS,MAAMU,EAAgBP,GAAWJ,GAAuBC,CAAC;AAAA,IAClE,SAASD,MAAU;AAAA,EAAA,CACpB;AACH;AAMO,SAASY,EAAoBC,GAGlC;;AACA,QAAMT,IAAYC,EAAA,GACZS,IAAQR,EAAS;AAAA,IACrB,UAAUC,EAAY,OAAOM,CAAU;AAAA,IACvC,SAAS,MAAML,EAAWJ,GAAW,EAAE,UAAUS,EAAA,GAAcE,GAAuB,CAAC;AAAA,EAAA,CACxF;AACD,SAAO;AAAA,IACL,gBAAcC,KAAAC,IAAAH,EAAM,SAAN,gBAAAG,EAAY,eAAZ,gBAAAD,EAAwB,WAAU,KAAK;AAAA,IACrD,WAAWF,EAAM;AAAA,EAAA;AAErB;AAIO,SAASI,EAAwBC,GAAkC;AACxE,QAAMf,IAAYC,EAAA;AAClB,SAAOC,EAAS;AAAA,IACd,UAAUC,EAAY,QAAOY,KAAA,gBAAAA,EAAS,SAAQ,aAAYA,KAAA,gBAAAA,EAAS,OAAM,EAAE;AAAA,IAC3E,SAAS,MAAMC,EAAmBhB,GAAWe,CAA2B;AAAA,IACxE,SAASA,MAAY;AAAA,EAAA,CACtB;AACH;AC1EO,MAAME,IAAgB,CAACC,MAAe,CAAC,eAAeA,CAAE;AAExD,SAASC,EAAcC,GAAmBF,GAAkC;AACjF,SAAOE,EAAO,QAAQ,KAAK,WAAWF,CAAE;AAC1C;AAGO,SAASG,EAAmBH,GAAYI,IAAU,IAAM;AAC7D,QAAMF,IAASnB,EAAA;AACf,SAAOC,EAAS;AAAA,IACd,UAAUe,EAAcC,CAAE;AAAA,IAC1B,SAAS,MAAMC,EAAcC,GAAQF,CAAE;AAAA,IACvC,SAAAI;AAAA,EAAA,CACD;AACH;AAIO,MAAMC,IAAS,CAACL,MAAe,CAAC,OAAOA,CAAE;AAEzC,SAASM,EAAOJ,GAAmBF,GAAgC;AACxE,SAAOE,EAAO,QAAQ,KAAK,IAAIF,CAAE;AACnC;AAOO,SAASO,EAAYP,GAAwBI,IAAU,IAAM;AAClE,QAAMF,IAASnB,EAAA;AACf,SAAOC,EAAS;AAAA,IACd,UAAUqB,EAAOL,KAAM,EAAE;AAAA,IACzB,SAAS,MAAMM,EAAOJ,GAAQF,CAAY;AAAA,IAC1C,SAAAI;AAAA,EAAA,CACD;AACH;"}
|
|
@@ -130,22 +130,22 @@ function F(e) {
|
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
132
|
export {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
w as a,
|
|
134
|
+
q as b,
|
|
135
|
+
u as c,
|
|
136
|
+
Q as d,
|
|
137
|
+
S as e,
|
|
138
138
|
p as f,
|
|
139
139
|
b as g,
|
|
140
140
|
v as h,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
C as i,
|
|
142
|
+
k as j,
|
|
143
|
+
g as k,
|
|
144
144
|
h as l,
|
|
145
|
-
|
|
145
|
+
L as m,
|
|
146
146
|
F as n,
|
|
147
147
|
$ as o,
|
|
148
148
|
m as s,
|
|
149
|
-
|
|
149
|
+
R as u
|
|
150
150
|
};
|
|
151
|
-
//# sourceMappingURL=callables-
|
|
151
|
+
//# sourceMappingURL=callables-tOlflvbl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callables-3mFrMVG_.js","sources":["../src/lib/callable-kind.ts","../src/lib/save-invalidation.ts","../src/repos/callables.ts"],"sourcesContent":["/**\n * The three callable kinds and the single-resource query key per kind.\n *\n * Moved verbatim out of Studio's `repos/callables.ts` (`CallableKind`, `callableKey` and the one\n * pure table `callableKey` closes over, `RESOURCE_KEY`) so `repos/versions.ts` — which ships in\n * this package for all three kind arms — can invalidate a definition by key without importing a\n * Studio module. `repos/callables.ts` imports these from `@w6w/embed/repos` and does NOT re-export\n * them. No React, no client: loadable by `node --test`.\n */\n\n/** The three kinds the callable repos are total over. */\nexport type CallableKind = \"function\" | \"endpoint\" | \"workflow\";\n\n/** The single-resource key's own prefix — byte-identical to `functionKey`/`endpointKey`/\n * `workflowKey`. */\nconst RESOURCE_KEY: Record<CallableKind, (id: string) => readonly unknown[]> = {\n function: (id) => [\"function\", id],\n endpoint: (id) => [\"endpoint\", id],\n workflow: (id) => [\"workflow\", id],\n};\n\n/** `GET /<coll>/:id`'s own query key — the literal `lib/save-invalidation.ts` invalidates. */\nexport function callableKey(kind: CallableKind, id: string): readonly unknown[] {\n return RESOURCE_KEY[kind](id);\n}\n","/**\n * Shared invalidation for a whole-definition save (T3.1.1). `useSaveFunctionMutation` and\n * `useSaveEndpointMutation` (`src/repos/functions.ts`, `src/repos/endpoints.ts`) both route their\n * `onSuccess` through this one helper rather than inlining the two `invalidateQueries` calls at\n * each site — so a save invalidates the LIST key (both list pages and the editor depend on it)\n * *and* the saved resource's own single-resource key (`functionKey(id)` / `endpointKey(id)`),\n * never just the list.\n *\n * No value imports on purpose: `node --test` throws `ERR_UNKNOWN_FILE_EXTENSION` on anything that\n * reaches the `@w6w/ui` / `Layout.tsx` import graph, and `src/repos/*.ts` reaches it through\n * `../api/apiClient.tsx` (JSX). This module has none of that, so it is loadable by `node --test`\n * directly — see `src/lib/alias-rail.ts`'s docstring for the same reasoning.\n */\n\nexport interface QueryInvalidator {\n invalidateQueries(filters: { queryKey: readonly unknown[] }): unknown;\n}\n\n/**\n * Invalidate the list key, then the saved resource's own key. List first: both keys are\n * invalidated regardless of order, but the order is asserted (see the unit test) so a future edit\n * that drops one call is a diff a reviewer can spot in a single line.\n */\nexport function invalidateSavedCallable(\n qc: QueryInvalidator,\n listKey: readonly unknown[],\n callableKey: readonly unknown[],\n): void {\n qc.invalidateQueries({ queryKey: listKey });\n qc.invalidateQueries({ queryKey: callableKey });\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { W6WClient } from \"@w6w/sdk\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n/**\n * The kind-parametrised resource repo (T4.2.1, `building-blocks.F3.md` §F-3) — ONE module\n * answering \"list / get / save / archive / delete a resource of kind K\" for all three kinds,\n * instead of `functions.ts`/`endpoints.ts`/`workflows.ts` each restating the same five shapes with\n * their own key builder.\n *\n * **Mirrors `src/repos/versions.ts`'s `COLLECTION_PATH: Record<VersionsKind, …>` idiom**: every\n * per-kind fact is a TOTAL `Record` whose arms are all named explicitly, never a string\n * pluralisation rule — a typo'd suffix would silently send one kind's requests at another kind's\n * collection (that module's own docblock gives the reasoning in full). The two tables that are\n * genuinely per-kind *data* — the collection segment and the two query-key shapes — are `Record`s;\n * the three calls whose SIGNATURE differs per kind (get's return shape, save's envelope key,\n * archive/delete's SDK-vs-escape-hatch split) are `switch`es with every arm named and no\n * `default:`, so a fourth kind is a compile error rather than a silent fall-through.\n *\n * **Query keys are byte-identical to the ones this repo replaces** — `[\"functions\"]`,\n * `[\"function\", id]`, `[\"endpoints\"]`, `[\"endpoint\", id]`, `[\"workflows\", project]`,\n * `[\"workflow\", id]` — because `lib/save-invalidation.ts`, `lib/spec-import-invalidation.ts` and\n * `repos/versions.ts`'s revert arm all invalidate those literals through helpers that take a key,\n * not a hook. A renamed key here would leave a saved resource's page showing its pre-save draft,\n * invisible to `tsc` and to every page guard (this is `spec-import-invalidation.ts`'s own\n * argument, restated for the whole family).\n *\n * `repos/functions.ts` stays as the Function-bound facade over this module — every existing\n * importer (`ui/rail/SettingsTool.tsx`, `ui/rail/AliasesTool.tsx`, `ui/rail/ErrorHandlingTool.tsx`,\n * `components/TargetSelector.tsx`, `components/FunctionIdentityModal.tsx`, `api/w6wApiFacade.tsx`)\n * keeps its import and its call shape; only where the code lives changed.\n */\nimport { type CallableKind, callableKey } from \"../lib/callable-kind.ts\";\nimport { invalidateSavedCallable } from \"../lib/save-invalidation.ts\";\n\n/** `<coll>` — the wire contract's own path segment per kind, every arm named explicitly\n * (never derived by string pluralisation), mirroring `versions.ts`'s `COLLECTION_PATH`. */\nconst COLLECTION_PATH: Record<CallableKind, \"functions\" | \"endpoints\" | \"workflows\"> = {\n function: \"functions\",\n endpoint: \"endpoints\",\n workflow: \"workflows\",\n};\n\n/**\n * The LIST query key per kind — byte-identical to `functionsKey`, `endpointsKey` and\n * `workflowsKey(project)`. A function per kind, not a literal, because the Workflow arm is\n * genuinely project-scoped (`repos/workflows.ts`'s own note: `[\"workflows\", undefined]` and\n * `[\"workflows\", \"prj_x\"]` are DIFFERENT cache entries, deliberately).\n */\nconst LIST_KEY: Record<CallableKind, (project?: string) => readonly unknown[]> = {\n function: () => [\"functions\"],\n endpoint: () => [\"endpoints\"],\n workflow: (project) => [\"workflows\", project],\n};\n\n/**\n * The structural minimum every list row of every kind satisfies — what the shared list chrome\n * (`pages/CallablePage.tsx`) renders and the Settings rail reads by id. Kind-specific widening\n * (`archivedAt`, an Endpoint's `status`/`incomplete`) stays in the kind's own facade, which is\n * where the comment explaining \"the SDK does not know this column yet\" belongs.\n */\nexport interface CallableRow {\n id: string;\n /** `null` for a Workflow that has no key of its own yet (`WorkflowSummary`'s own\n * type) — never coerced to `\"\"` here, so the list renders exactly what the server sent. */\n key: string | null;\n displayName?: string | null;\n description?: string | null;\n archivedAt?: string | null;\n}\n\n/** `<coll>` for a kind — the wire segment AND (studio mirrors the wire) the route segment. */\nexport function callableCollection(kind: CallableKind): string {\n return COLLECTION_PATH[kind];\n}\n\n/** The studio route for a kind, or for one of its resources: `\"functions\"`, `\"functions/fn_x\"`. */\nexport function callableRoute(kind: CallableKind, id?: string): string {\n const collection = COLLECTION_PATH[kind];\n return id === undefined ? collection : `${collection}/${id}`;\n}\n\n/** The wire path for one resource: `/functions/fn_x`. */\nexport function callablePath(kind: CallableKind, id: string): string {\n return `/${COLLECTION_PATH[kind]}/${id}`;\n}\n\n/** The studio route for one resource's History tab/page (T2.3.1/T2.4.1):\n * `\"functions/fn_x/history\"`. A sibling of {@link callableRoute}, not a\n * hand-written string per call site. */\nexport function callableHistoryRoute(kind: CallableKind, id: string): string {\n return `${callableRoute(kind, id)}/history`;\n}\n\n/** `GET /<coll>`'s own query key — the literal `lib/spec-import-invalidation.ts` invalidates. */\nexport function callableListKey(kind: CallableKind, project?: string): readonly unknown[] {\n return LIST_KEY[kind](project);\n}\n\n/**\n * `GET /<coll>`. A `switch`, not a table: the three SDK calls return three different summary\n * types, and the union is what the shared chrome consumes structurally.\n */\nexport function listCallables(\n client: W6WClient,\n kind: CallableKind,\n project?: string,\n): Promise<CallableRow[]> {\n switch (kind) {\n case \"function\":\n return client.console.functions.list();\n case \"endpoint\":\n return client.console.endpoints.list();\n case \"workflow\":\n return client.workflows.list({ project });\n }\n}\n\n/**\n * `GET /<coll>/:id`, each arm returning exactly what that kind's existing repo function returns —\n * Function's `{...function, valid}` splice, Endpoint's `{endpoint, invokeUrl, …}` envelope,\n * Workflow's three-field body — never re-shaped here. The return type is the honest `unknown`:\n * the per-kind reader in the kind's own facade is what narrows it.\n */\nexport function getCallable(client: W6WClient, kind: CallableKind, id: string): Promise<unknown> {\n switch (kind) {\n case \"function\":\n return client.console.functions.get(id);\n case \"endpoint\":\n return client.console.endpoints.get(id);\n case \"workflow\":\n return client.console.workflows.get(id);\n }\n}\n\n/**\n * `POST /<coll>`, normalised to the one thing EVERY caller of a save needs — the saved resource's\n * id and key, for the invalidation below and for a create modal's own \"created\" callback. The two\n * envelopes (`{endpoint: {id, key}}`, `{workflow: {id, key}}`) and the flat one (`{id, key}`) are\n * unwrapped in the arm that knows its own shape, so no caller outside this module ever has to.\n *\n * Workflow refuses without a `project` for the same reason `repos/workflows.ts`'s own save does:\n * a missing project on a WRITE lands the definition in the account's default project instead of\n * the one the operator is looking at.\n */\nexport function saveCallable(\n client: W6WClient,\n kind: CallableKind,\n definition: unknown,\n options?: { project?: string },\n): Promise<{ id: string; key: string }> {\n switch (kind) {\n case \"function\":\n return client.console.functions\n .upsert(definition as never)\n .then((saved) => ({ id: saved.id, key: saved.key }));\n case \"endpoint\":\n return client.console.endpoints\n .upsert(definition as never)\n .then((saved) => ({ id: saved.endpoint.id, key: saved.endpoint.key }));\n case \"workflow\": {\n const project = options?.project;\n if (!project) return Promise.reject(new Error(\"No project selected yet.\"));\n return client.console.workflows.upsert(definition, { project }).then((saved) => ({\n id: saved.workflow.id,\n key: saved.workflow.key ?? \"\",\n }));\n }\n }\n}\n\n/**\n * `POST /<coll>/:id/archive`. Function and Endpoint go through the plain `apiClient.request()`\n * escape hatch (T4.1.1/A7/D-I0-7: no typed `@w6w/sdk` method exists, and adding one would drag\n * `packages/wrappers` into this task's scope for an internal route); Workflow keeps the typed\n * `console.workflows.archive` it has had since the rail's DangerZone landed.\n */\nexport function archiveCallable(\n client: W6WClient,\n kind: CallableKind,\n id: string,\n): Promise<unknown> {\n switch (kind) {\n case \"function\":\n case \"endpoint\":\n return client.request({\n method: \"POST\",\n path: `${callablePath(kind, encodeURIComponent(id))}/archive`,\n });\n case \"workflow\":\n return client.console.workflows.archive(id);\n }\n}\n\n/** `DELETE /<coll>/:id` — same split, and the same reasoning, as {@link archiveCallable}. */\nexport function deleteCallable(\n client: W6WClient,\n kind: CallableKind,\n id: string,\n): Promise<unknown> {\n switch (kind) {\n case \"function\":\n case \"endpoint\":\n return client.request({ method: \"DELETE\", path: callablePath(kind, encodeURIComponent(id)) });\n case \"workflow\":\n return client.console.workflows.delete(id);\n }\n}\n\n/**\n * `useQuery` over {@link listCallables}, keyed by {@link callableListKey}. Generic over the row\n * type so a kind's own facade can narrow it to that kind's widened summary (Function's\n * `archivedAt`, Endpoint's `status`/`incomplete`) without a cast at the call site.\n */\nexport function useCallableListQuery<Row extends CallableRow = CallableRow>(\n kind: CallableKind,\n enabled = true,\n project?: string,\n) {\n const apiClient = useEmbedClient();\n return useQuery<Row[]>({\n queryKey: callableListKey(kind, project),\n queryFn: () => listCallables(apiClient, kind, project) as Promise<Row[]>,\n enabled,\n });\n}\n\n/** `useQuery` over {@link getCallable}, keyed by {@link callableKey}. */\nexport function useCallableQuery<Def = unknown>(kind: CallableKind, id: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery<Def>({\n queryKey: callableKey(kind, id),\n queryFn: () => getCallable(apiClient, kind, id) as Promise<Def>,\n enabled,\n });\n}\n\n/**\n * `useMutation` over {@link saveCallable}. `onSuccess` routes through the SAME\n * `invalidateSavedCallable` helper every save in studio already uses, with the SAME two keys —\n * the list AND the saved resource — so the Function arm's invalidation is the one\n * `repos/functions.ts` performs today, byte for byte.\n */\nexport function useSaveCallableMutation(kind: CallableKind, options?: { project?: string }) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (definition: unknown) => saveCallable(apiClient, kind, definition, options),\n onSuccess: (saved) =>\n invalidateSavedCallable(qc, callableListKey(kind), callableKey(kind, saved.id)),\n });\n}\n\n/** `useMutation` over {@link archiveCallable} — the list key, so the row's archived badge\n * refreshes and the rail's Delete control appears in Archive's place. */\nexport function useArchiveCallableMutation(kind: CallableKind) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => archiveCallable(apiClient, kind, id),\n onSuccess: () => qc.invalidateQueries({ queryKey: callableListKey(kind) }),\n });\n}\n\n/** `useMutation` over {@link deleteCallable}. */\nexport function useDeleteCallableMutation(kind: CallableKind) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => deleteCallable(apiClient, kind, id),\n onSuccess: () => qc.invalidateQueries({ queryKey: callableListKey(kind) }),\n });\n}\n"],"names":["RESOURCE_KEY","id","callableKey","kind","invalidateSavedCallable","qc","listKey","COLLECTION_PATH","LIST_KEY","project","callableCollection","callableRoute","collection","callablePath","callableHistoryRoute","callableListKey","listCallables","client","getCallable","saveCallable","definition","options","saved","archiveCallable","deleteCallable","useCallableListQuery","enabled","apiClient","useEmbedClient","useQuery","useCallableQuery","useSaveCallableMutation","useQueryClient","useMutation","useArchiveCallableMutation","useDeleteCallableMutation"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"callables-tOlflvbl.js","sources":["../src/lib/callable-kind.ts","../src/lib/save-invalidation.ts","../src/repos/callables.ts"],"sourcesContent":["/**\n * The three callable kinds and the single-resource query key per kind.\n *\n * Moved verbatim out of Studio's `repos/callables.ts` (`CallableKind`, `callableKey` and the one\n * pure table `callableKey` closes over, `RESOURCE_KEY`) so `repos/versions.ts` — which ships in\n * this package for all three kind arms — can invalidate a definition by key without importing a\n * Studio module. `repos/callables.ts` imports these from `@w6w/embed/repos` and does NOT re-export\n * them. No React, no client: loadable by `node --test`.\n */\n\n/** The three kinds the callable repos are total over. */\nexport type CallableKind = \"function\" | \"endpoint\" | \"workflow\";\n\n/** The single-resource key's own prefix — byte-identical to `functionKey`/`endpointKey`/\n * `workflowKey`. */\nconst RESOURCE_KEY: Record<CallableKind, (id: string) => readonly unknown[]> = {\n function: (id) => [\"function\", id],\n endpoint: (id) => [\"endpoint\", id],\n workflow: (id) => [\"workflow\", id],\n};\n\n/** `GET /<coll>/:id`'s own query key — the literal `lib/save-invalidation.ts` invalidates. */\nexport function callableKey(kind: CallableKind, id: string): readonly unknown[] {\n return RESOURCE_KEY[kind](id);\n}\n","/**\n * Shared invalidation for a whole-definition save (T3.1.1). `useSaveFunctionMutation` and\n * `useSaveEndpointMutation` (`src/repos/functions.ts`, `src/repos/endpoints.ts`) both route their\n * `onSuccess` through this one helper rather than inlining the two `invalidateQueries` calls at\n * each site — so a save invalidates the LIST key (both list pages and the editor depend on it)\n * *and* the saved resource's own single-resource key (`functionKey(id)` / `endpointKey(id)`),\n * never just the list.\n *\n * No value imports on purpose: `node --test` throws `ERR_UNKNOWN_FILE_EXTENSION` on anything that\n * reaches the `@w6w/ui` / `Layout.tsx` import graph, and `src/repos/*.ts` reaches it through\n * `../api/apiClient.tsx` (JSX). This module has none of that, so it is loadable by `node --test`\n * directly — see `src/lib/alias-rail.ts`'s docstring for the same reasoning.\n */\n\nexport interface QueryInvalidator {\n invalidateQueries(filters: { queryKey: readonly unknown[] }): unknown;\n}\n\n/**\n * Invalidate the list key, then the saved resource's own key. List first: both keys are\n * invalidated regardless of order, but the order is asserted (see the unit test) so a future edit\n * that drops one call is a diff a reviewer can spot in a single line.\n */\nexport function invalidateSavedCallable(\n qc: QueryInvalidator,\n listKey: readonly unknown[],\n callableKey: readonly unknown[],\n): void {\n qc.invalidateQueries({ queryKey: listKey });\n qc.invalidateQueries({ queryKey: callableKey });\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { W6WClient } from \"@w6w/sdk\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n/**\n * The kind-parametrised resource repo (T4.2.1, `building-blocks.F3.md` §F-3) — ONE module\n * answering \"list / get / save / archive / delete a resource of kind K\" for all three kinds,\n * instead of `functions.ts`/`endpoints.ts`/`workflows.ts` each restating the same five shapes with\n * their own key builder.\n *\n * **Mirrors `src/repos/versions.ts`'s `COLLECTION_PATH: Record<VersionsKind, …>` idiom**: every\n * per-kind fact is a TOTAL `Record` whose arms are all named explicitly, never a string\n * pluralisation rule — a typo'd suffix would silently send one kind's requests at another kind's\n * collection (that module's own docblock gives the reasoning in full). The two tables that are\n * genuinely per-kind *data* — the collection segment and the two query-key shapes — are `Record`s;\n * the three calls whose SIGNATURE differs per kind (get's return shape, save's envelope key,\n * archive/delete's SDK-vs-escape-hatch split) are `switch`es with every arm named and no\n * `default:`, so a fourth kind is a compile error rather than a silent fall-through.\n *\n * **Query keys are byte-identical to the ones this repo replaces** — `[\"functions\"]`,\n * `[\"function\", id]`, `[\"endpoints\"]`, `[\"endpoint\", id]`, `[\"workflows\", project]`,\n * `[\"workflow\", id]` — because `lib/save-invalidation.ts`, `lib/spec-import-invalidation.ts` and\n * `repos/versions.ts`'s revert arm all invalidate those literals through helpers that take a key,\n * not a hook. A renamed key here would leave a saved resource's page showing its pre-save draft,\n * invisible to `tsc` and to every page guard (this is `spec-import-invalidation.ts`'s own\n * argument, restated for the whole family).\n *\n * `repos/functions.ts` stays as the Function-bound facade over this module — every existing\n * importer (`ui/rail/SettingsTool.tsx`, `ui/rail/AliasesTool.tsx`, `ui/rail/ErrorHandlingTool.tsx`,\n * `components/TargetSelector.tsx`, `components/FunctionIdentityModal.tsx`, `api/w6wApiFacade.tsx`)\n * keeps its import and its call shape; only where the code lives changed.\n */\nimport { type CallableKind, callableKey } from \"../lib/callable-kind.ts\";\nimport { invalidateSavedCallable } from \"../lib/save-invalidation.ts\";\n\n/** `<coll>` — the wire contract's own path segment per kind, every arm named explicitly\n * (never derived by string pluralisation), mirroring `versions.ts`'s `COLLECTION_PATH`. */\nconst COLLECTION_PATH: Record<CallableKind, \"functions\" | \"endpoints\" | \"workflows\"> = {\n function: \"functions\",\n endpoint: \"endpoints\",\n workflow: \"workflows\",\n};\n\n/**\n * The LIST query key per kind — byte-identical to `functionsKey`, `endpointsKey` and\n * `workflowsKey(project)`. A function per kind, not a literal, because the Workflow arm is\n * genuinely project-scoped (`repos/workflows.ts`'s own note: `[\"workflows\", undefined]` and\n * `[\"workflows\", \"prj_x\"]` are DIFFERENT cache entries, deliberately).\n */\nconst LIST_KEY: Record<CallableKind, (project?: string) => readonly unknown[]> = {\n function: () => [\"functions\"],\n endpoint: () => [\"endpoints\"],\n workflow: (project) => [\"workflows\", project],\n};\n\n/**\n * The structural minimum every list row of every kind satisfies — what the shared list chrome\n * (`pages/CallablePage.tsx`) renders and the Settings rail reads by id. Kind-specific widening\n * (`archivedAt`, an Endpoint's `status`/`incomplete`) stays in the kind's own facade, which is\n * where the comment explaining \"the SDK does not know this column yet\" belongs.\n */\nexport interface CallableRow {\n id: string;\n /** `null` for a Workflow that has no key of its own yet (`WorkflowSummary`'s own\n * type) — never coerced to `\"\"` here, so the list renders exactly what the server sent. */\n key: string | null;\n displayName?: string | null;\n description?: string | null;\n archivedAt?: string | null;\n}\n\n/** `<coll>` for a kind — the wire segment AND (studio mirrors the wire) the route segment. */\nexport function callableCollection(kind: CallableKind): string {\n return COLLECTION_PATH[kind];\n}\n\n/** The studio route for a kind, or for one of its resources: `\"functions\"`, `\"functions/fn_x\"`. */\nexport function callableRoute(kind: CallableKind, id?: string): string {\n const collection = COLLECTION_PATH[kind];\n return id === undefined ? collection : `${collection}/${id}`;\n}\n\n/** The wire path for one resource: `/functions/fn_x`. */\nexport function callablePath(kind: CallableKind, id: string): string {\n return `/${COLLECTION_PATH[kind]}/${id}`;\n}\n\n/** The studio route for one resource's History tab/page (T2.3.1/T2.4.1):\n * `\"functions/fn_x/history\"`. A sibling of {@link callableRoute}, not a\n * hand-written string per call site. */\nexport function callableHistoryRoute(kind: CallableKind, id: string): string {\n return `${callableRoute(kind, id)}/history`;\n}\n\n/** `GET /<coll>`'s own query key — the literal `lib/spec-import-invalidation.ts` invalidates. */\nexport function callableListKey(kind: CallableKind, project?: string): readonly unknown[] {\n return LIST_KEY[kind](project);\n}\n\n/**\n * `GET /<coll>`. A `switch`, not a table: the three SDK calls return three different summary\n * types, and the union is what the shared chrome consumes structurally.\n */\nexport function listCallables(\n client: W6WClient,\n kind: CallableKind,\n project?: string,\n): Promise<CallableRow[]> {\n switch (kind) {\n case \"function\":\n return client.console.functions.list();\n case \"endpoint\":\n return client.console.endpoints.list();\n case \"workflow\":\n return client.workflows.list({ project });\n }\n}\n\n/**\n * `GET /<coll>/:id`, each arm returning exactly what that kind's existing repo function returns —\n * Function's `{...function, valid}` splice, Endpoint's `{endpoint, invokeUrl, …}` envelope,\n * Workflow's three-field body — never re-shaped here. The return type is the honest `unknown`:\n * the per-kind reader in the kind's own facade is what narrows it.\n */\nexport function getCallable(client: W6WClient, kind: CallableKind, id: string): Promise<unknown> {\n switch (kind) {\n case \"function\":\n return client.console.functions.get(id);\n case \"endpoint\":\n return client.console.endpoints.get(id);\n case \"workflow\":\n return client.console.workflows.get(id);\n }\n}\n\n/**\n * `POST /<coll>`, normalised to the one thing EVERY caller of a save needs — the saved resource's\n * id and key, for the invalidation below and for a create modal's own \"created\" callback. The two\n * envelopes (`{endpoint: {id, key}}`, `{workflow: {id, key}}`) and the flat one (`{id, key}`) are\n * unwrapped in the arm that knows its own shape, so no caller outside this module ever has to.\n *\n * Workflow refuses without a `project` for the same reason `repos/workflows.ts`'s own save does:\n * a missing project on a WRITE lands the definition in the account's default project instead of\n * the one the operator is looking at.\n */\nexport function saveCallable(\n client: W6WClient,\n kind: CallableKind,\n definition: unknown,\n options?: { project?: string },\n): Promise<{ id: string; key: string }> {\n switch (kind) {\n case \"function\":\n return client.console.functions\n .upsert(definition as never)\n .then((saved) => ({ id: saved.id, key: saved.key }));\n case \"endpoint\":\n return client.console.endpoints\n .upsert(definition as never)\n .then((saved) => ({ id: saved.endpoint.id, key: saved.endpoint.key }));\n case \"workflow\": {\n const project = options?.project;\n if (!project) return Promise.reject(new Error(\"No project selected yet.\"));\n return client.console.workflows.upsert(definition, { project }).then((saved) => ({\n id: saved.workflow.id,\n key: saved.workflow.key ?? \"\",\n }));\n }\n }\n}\n\n/**\n * `POST /<coll>/:id/archive`. Function and Endpoint go through the plain `apiClient.request()`\n * escape hatch (T4.1.1/A7/D-I0-7: no typed `@w6w/sdk` method exists, and adding one would drag\n * `packages/wrappers` into this task's scope for an internal route); Workflow keeps the typed\n * `console.workflows.archive` it has had since the rail's DangerZone landed.\n */\nexport function archiveCallable(\n client: W6WClient,\n kind: CallableKind,\n id: string,\n): Promise<unknown> {\n switch (kind) {\n case \"function\":\n case \"endpoint\":\n return client.request({\n method: \"POST\",\n path: `${callablePath(kind, encodeURIComponent(id))}/archive`,\n });\n case \"workflow\":\n return client.console.workflows.archive(id);\n }\n}\n\n/** `DELETE /<coll>/:id` — same split, and the same reasoning, as {@link archiveCallable}. */\nexport function deleteCallable(\n client: W6WClient,\n kind: CallableKind,\n id: string,\n): Promise<unknown> {\n switch (kind) {\n case \"function\":\n case \"endpoint\":\n return client.request({ method: \"DELETE\", path: callablePath(kind, encodeURIComponent(id)) });\n case \"workflow\":\n return client.console.workflows.delete(id);\n }\n}\n\n/**\n * `useQuery` over {@link listCallables}, keyed by {@link callableListKey}. Generic over the row\n * type so a kind's own facade can narrow it to that kind's widened summary (Function's\n * `archivedAt`, Endpoint's `status`/`incomplete`) without a cast at the call site.\n */\nexport function useCallableListQuery<Row extends CallableRow = CallableRow>(\n kind: CallableKind,\n enabled = true,\n project?: string,\n) {\n const apiClient = useEmbedClient();\n return useQuery<Row[]>({\n queryKey: callableListKey(kind, project),\n queryFn: () => listCallables(apiClient, kind, project) as Promise<Row[]>,\n enabled,\n });\n}\n\n/** `useQuery` over {@link getCallable}, keyed by {@link callableKey}. */\nexport function useCallableQuery<Def = unknown>(kind: CallableKind, id: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery<Def>({\n queryKey: callableKey(kind, id),\n queryFn: () => getCallable(apiClient, kind, id) as Promise<Def>,\n enabled,\n });\n}\n\n/**\n * `useMutation` over {@link saveCallable}. `onSuccess` routes through the SAME\n * `invalidateSavedCallable` helper every save in studio already uses, with the SAME two keys —\n * the list AND the saved resource — so the Function arm's invalidation is the one\n * `repos/functions.ts` performs today, byte for byte.\n */\nexport function useSaveCallableMutation(kind: CallableKind, options?: { project?: string }) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (definition: unknown) => saveCallable(apiClient, kind, definition, options),\n onSuccess: (saved) =>\n invalidateSavedCallable(qc, callableListKey(kind), callableKey(kind, saved.id)),\n });\n}\n\n/** `useMutation` over {@link archiveCallable} — the list key, so the row's archived badge\n * refreshes and the rail's Delete control appears in Archive's place. */\nexport function useArchiveCallableMutation(kind: CallableKind) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => archiveCallable(apiClient, kind, id),\n onSuccess: () => qc.invalidateQueries({ queryKey: callableListKey(kind) }),\n });\n}\n\n/** `useMutation` over {@link deleteCallable}. */\nexport function useDeleteCallableMutation(kind: CallableKind) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => deleteCallable(apiClient, kind, id),\n onSuccess: () => qc.invalidateQueries({ queryKey: callableListKey(kind) }),\n });\n}\n"],"names":["RESOURCE_KEY","id","callableKey","kind","invalidateSavedCallable","qc","listKey","COLLECTION_PATH","LIST_KEY","project","callableCollection","callableRoute","collection","callablePath","callableHistoryRoute","callableListKey","listCallables","client","getCallable","saveCallable","definition","options","saved","archiveCallable","deleteCallable","useCallableListQuery","enabled","apiClient","useEmbedClient","useQuery","useCallableQuery","useSaveCallableMutation","useQueryClient","useMutation","useArchiveCallableMutation","useDeleteCallableMutation"],"mappings":"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"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
interface ConfirmModalProps {
|
|
2
3
|
title: string;
|
|
3
4
|
message: string;
|
|
5
|
+
/** Optional content rendered under the message (e.g. a list of impacted items). */
|
|
6
|
+
children?: ReactNode;
|
|
4
7
|
/** Fired when the user confirms. The caller clears its pending state via onClose. */
|
|
5
8
|
onConfirm: () => void;
|
|
6
9
|
/** Fired on Cancel, Esc, or outside-click — dismisses without confirming. */
|
|
@@ -16,5 +19,5 @@ interface ConfirmModalProps {
|
|
|
16
19
|
* confirmation prompt for destructive actions: Confirm fires `onConfirm`;
|
|
17
20
|
* Cancel/Esc/outside-click fires `onClose` only (no confirmation).
|
|
18
21
|
*/
|
|
19
|
-
export declare function ConfirmModal({ title, message, onConfirm, onClose, confirmLabel, cancelLabel, destructive, }: ConfirmModalProps): import("react").JSX.Element;
|
|
22
|
+
export declare function ConfirmModal({ title, message, children, onConfirm, onClose, confirmLabel, cancelLabel, destructive, }: ConfirmModalProps): import("react").JSX.Element;
|
|
20
23
|
export {};
|
|
@@ -72,6 +72,10 @@ export type WorkspaceCallable = {
|
|
|
72
72
|
kind: "connection";
|
|
73
73
|
id: string;
|
|
74
74
|
label?: string;
|
|
75
|
+
/** Set by the connection ACTION page: the Code tool needs an action to show a snippet. */
|
|
76
|
+
action?: string;
|
|
77
|
+
/** Declared param keys of `action` (plain data — the registry keys on JSON). */
|
|
78
|
+
params?: readonly SnippetInput[];
|
|
75
79
|
} | null;
|
|
76
80
|
/** Derived from {@link WorkspaceCallable}, never redeclared — the arm a
|
|
77
81
|
* `RailTool.isAvailable`/route wrapper narrows on. */
|