@w6w/embed 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +231 -4
- package/dist/ConfirmModal-RLbZT5_k.js +181 -0
- package/dist/ConfirmModal-RLbZT5_k.js.map +1 -0
- package/dist/CreateFunctionModal-DRsFx-FB.js +221 -0
- package/dist/CreateFunctionModal-DRsFx-FB.js.map +1 -0
- package/dist/DocumentFormModal-BExK1V-B.js +89 -0
- package/dist/DocumentFormModal-BExK1V-B.js.map +1 -0
- package/dist/ImportSpecModal-BDQIf6rg.js +136 -0
- package/dist/ImportSpecModal-BDQIf6rg.js.map +1 -0
- package/dist/W6WEmbedProvider.d.ts +22 -4
- package/dist/WorkflowEditor-DlbVv6Fs.js +854 -0
- package/dist/WorkflowEditor-DlbVv6Fs.js.map +1 -0
- package/dist/api-calls--JHyif6a.js +107 -0
- package/dist/api-calls--JHyif6a.js.map +1 -0
- package/dist/apps-1FNUwbGv.js +77 -0
- package/dist/apps-1FNUwbGv.js.map +1 -0
- package/dist/callables-3mFrMVG_.js +151 -0
- package/dist/callables-3mFrMVG_.js.map +1 -0
- package/dist/chrome/index.d.ts +6 -0
- package/dist/chrome/workspace.d.ts +29 -1
- package/dist/coerce-input-BicYr7nc.js +139 -0
- package/dist/coerce-input-BicYr7nc.js.map +1 -0
- package/dist/connections-CjjYeRqb.js +78 -0
- package/dist/connections-CjjYeRqb.js.map +1 -0
- package/dist/document-sources-C0grrtdq.js +86 -0
- package/dist/document-sources-C0grrtdq.js.map +1 -0
- package/dist/draft/index.d.ts +3 -1
- package/dist/draft/use-callable-draft.d.ts +65 -0
- package/dist/draft/workflow-save.d.ts +3 -0
- package/dist/draft.mjs +9 -5
- package/dist/draft.mjs.map +1 -1
- package/dist/editor/CallableEditorFrame.d.ts +33 -0
- package/dist/editor/EditorShell.d.ts +16 -0
- package/dist/editor/EndpointCards.d.ts +56 -0
- package/dist/editor/EndpointEditor.d.ts +26 -0
- package/dist/editor/FunctionEditor.d.ts +21 -0
- package/dist/editor/InputListEditor.d.ts +29 -0
- package/dist/editor/TargetSelector.d.ts +30 -0
- package/dist/editor/TargetSelector.types.d.ts +62 -0
- package/dist/editor/editor-apps.d.ts +8 -2
- package/dist/editor/types.d.ts +57 -0
- package/dist/editor-apps-BdenSV1o.js +95 -0
- package/dist/editor-apps-BdenSV1o.js.map +1 -0
- package/dist/editor-tools-RxmY5iyi.js +1279 -0
- package/dist/editor-tools-RxmY5iyi.js.map +1 -0
- package/dist/editor.mjs +2 -2166
- package/dist/editor.mjs.map +1 -1
- package/dist/editors/DocumentEditor.d.ts +20 -0
- package/dist/editors/doc-format.d.ts +3 -0
- package/dist/editors.d.ts +12 -0
- package/dist/editors.mjs +1313 -0
- package/dist/editors.mjs.map +1 -0
- package/dist/embed-status.d.ts +20 -0
- package/dist/endpoints-B2ynbZo-.js +227 -0
- package/dist/endpoints-B2ynbZo-.js.map +1 -0
- package/dist/forms/CreateEndpointModal.d.ts +54 -0
- package/dist/forms/CreateFunctionModal.d.ts +55 -0
- package/dist/forms/DocumentFormModal.d.ts +8 -0
- package/dist/forms/SecretsManager.d.ts +12 -0
- package/dist/forms/VarsManager.d.ts +29 -0
- package/dist/forms.d.ts +6 -0
- package/dist/forms.mjs +407 -0
- package/dist/forms.mjs.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.mjs +153 -50
- package/dist/index.mjs.map +1 -1
- package/dist/lib/callable-record.d.ts +21 -0
- package/dist/lib/coerce-input.d.ts +6 -0
- package/dist/lib/endpoint-editor.d.ts +23 -0
- package/dist/lib/index.d.ts +7 -0
- package/dist/lib/input-coverage.d.ts +28 -0
- package/dist/lib/input-seeding.d.ts +67 -0
- package/dist/lib/rail-settings.d.ts +3 -3
- package/dist/lib/recent-activity.d.ts +128 -0
- package/dist/lib/target-fields.d.ts +168 -0
- package/dist/lib/workflow-blank.d.ts +2 -0
- package/dist/lib.mjs +70 -48
- package/dist/lib.mjs.map +1 -1
- package/dist/lists/ActivitySummary.d.ts +29 -0
- package/dist/lists/CallableKindList.d.ts +34 -0
- package/dist/lists/ConnectionDetail.d.ts +17 -0
- package/dist/lists/ConnectionList.d.ts +16 -0
- package/dist/lists/DocumentList.d.ts +29 -0
- package/dist/lists/EndpointList.d.ts +19 -0
- package/dist/lists/FunctionList.d.ts +18 -0
- package/dist/lists/ReliabilityBoard.d.ts +23 -0
- package/dist/lists/RunHistory.d.ts +11 -0
- package/dist/lists/ServiceDetail.d.ts +20 -0
- package/dist/lists/WorkflowList.d.ts +19 -0
- package/dist/lists/vendor-history.d.ts +40 -0
- package/dist/lists.d.ts +20 -0
- package/dist/lists.mjs +1185 -0
- package/dist/lists.mjs.map +1 -0
- package/dist/project-context-BiCjv_E3.js +25 -0
- package/dist/project-context-BiCjv_E3.js.map +1 -0
- package/dist/project-context.d.ts +15 -1
- package/dist/rail/CallableRail.d.ts +12 -0
- package/dist/rail/CallableWorkspace.d.ts +16 -0
- package/dist/rail/SettingsTool.d.ts +7 -1
- package/dist/rail/settings-sections.d.ts +2 -2
- package/dist/rail-settings-XYGToh00.js +111 -0
- package/dist/rail-settings-XYGToh00.js.map +1 -0
- package/dist/rail.d.ts +11 -0
- package/dist/rail.mjs +35 -0
- package/dist/rail.mjs.map +1 -0
- package/dist/repos/api-calls.d.ts +4 -0
- package/dist/repos/apps.d.ts +14 -0
- package/dist/repos/callables.d.ts +91 -0
- package/dist/repos/connections.d.ts +33 -0
- package/dist/repos/dashboard.d.ts +4 -0
- package/dist/repos/endpoints.d.ts +125 -0
- package/dist/repos/functions.d.ts +79 -0
- package/dist/repos/index.d.ts +10 -0
- package/dist/repos/reliability.d.ts +42 -0
- package/dist/repos/saved-tests.d.ts +46 -0
- package/dist/repos/spec-export.d.ts +23 -0
- package/dist/repos/workflows.d.ts +138 -0
- package/dist/repos.mjs +174 -88
- package/dist/repos.mjs.map +1 -1
- package/dist/settings-rail--GdRMusb.js +33 -0
- package/dist/settings-rail--GdRMusb.js.map +1 -0
- package/dist/slug-C4ktDPdy.js +315 -0
- package/dist/slug-C4ktDPdy.js.map +1 -0
- package/dist/spec-export-Cf3VQSQS.js +176 -0
- package/dist/spec-export-Cf3VQSQS.js.map +1 -0
- package/dist/spec-import-CjmxyZDR.js +465 -0
- package/dist/spec-import-CjmxyZDR.js.map +1 -0
- package/dist/step-tests-CivICmTq.js +18 -0
- package/dist/step-tests-CivICmTq.js.map +1 -0
- package/dist/trigger-preview-VPkrryDl.js +120 -0
- package/dist/trigger-preview-VPkrryDl.js.map +1 -0
- package/dist/use-callable-draft-zHLpcr-b.js +271 -0
- package/dist/use-callable-draft-zHLpcr-b.js.map +1 -0
- package/dist/{use-workflow-draft-oI02dsP-.js → use-workflow-draft-DzAyUeA6.js} +48 -46
- package/dist/use-workflow-draft-DzAyUeA6.js.map +1 -0
- package/dist/vault-BSEWhMYC.js +117 -0
- package/dist/vault-BSEWhMYC.js.map +1 -0
- package/dist/workflow-blank-DyL3_RUA.js +14 -0
- package/dist/workflow-blank-DyL3_RUA.js.map +1 -0
- package/package.json +21 -5
- package/src/styles.css +408 -1
- package/dist/project-context-Dbk0Gr1K.js +0 -16
- package/dist/project-context-Dbk0Gr1K.js.map +0 -1
- package/dist/slug-ByKQgxrf.js +0 -642
- package/dist/slug-ByKQgxrf.js.map +0 -1
- package/dist/spec-import-HgO7ZkLZ.js +0 -898
- package/dist/spec-import-HgO7ZkLZ.js.map +0 -1
- package/dist/use-workflow-draft-oI02dsP-.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoints-B2ynbZo-.js","sources":["../src/lib/new-id.ts","../src/lib/callable-descriptors.ts","../src/repos/functions.ts","../src/repos/endpoints.ts"],"sourcesContent":["/**\n * Platform id minter (studio copy). Algorithm is byte-identical to the server's\n * `packages/ids/ids.ts`: alphabet base62, drop byte b >= 248 (largest multiple of 62\n * that fits a byte), keep ALPHABET[b % 62]. No modulo bias.\n */\n\nexport const ID_ALPHABET = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\n/** Largest multiple of 62 <= 256; bytes at or above it are rejected. */\nconst REJECT_AT = 248;\n\n/** Byte source seam; defaults to `crypto.getRandomValues`. */\nexport type ByteSource = (n: number) => Uint8Array;\n\nconst defaultBytes: ByteSource = (n) => crypto.getRandomValues(new Uint8Array(n));\n\n/** `<prefix>_<len chars of base62>`. */\nexport function newId(prefix: string, len = 16, bytes: ByteSource = defaultBytes): string {\n let out = \"\";\n while (out.length < len) {\n for (const b of bytes(Math.max(len - out.length, 8))) {\n if (b >= REJECT_AT) continue;\n out += ID_ALPHABET[b % 62];\n if (out.length === len) break;\n }\n }\n return `${prefix}_${out}`;\n}\n","/**\n * `CALLABLE_DESCRIPTORS` — the ONE place the three resource kinds' chrome copy,\n * their Settings-modal behaviour and their id minting are named (T4.2.1,\n * `building-blocks.F3.md` §F-3).\n *\n * Before this file, every \"is this a workflow?\" branch lived inline at its call\n * site: `CallableSettingsModal.tsx` carried seven `kind ===` conditionals for\n * three different questions (may the key be edited? does this kind have tags?\n * which placeholder does the name field use?), and each list page repeated the\n * same title/description/empty-state/`data-testid` literals. A fourth kind — or\n * a rename — meant finding them all by hand.\n *\n * **Data only, never JSX.** A `Descriptor` holds strings, booleans and the one\n * id prefix; the kind-specific *editor body* stays React code in its own page\n * (`src/pages/FunctionsPage.tsx`), because this file is `.ts` and is loaded by\n * `node --test` (`.tsx` cannot be — `package.json`'s `test:unit` glob), exactly\n * the constraint `src/lib/save-invalidation.ts` and `src/lib/alias-rail.ts`\n * document for themselves. So `kind ===` moves OUT of the modal and the pages\n * and INTO a total `Record`, never into a render function.\n *\n * The wire plumbing these descriptors describe — collection segment, query keys,\n * the SDK call per kind — lives one layer down, in `src/repos/callables.ts`,\n * which owns its own total `Record` per kind (mirroring `src/repos/versions.ts`'s\n * `COLLECTION_PATH`). `callable-descriptors.test.ts` asserts the two tables name\n * the same three kinds and the same three collections, so they cannot drift.\n */\nimport type { CallableKind } from \"./callable-kind.ts\";\nimport { newId } from \"./new-id.ts\";\n\nexport type { CallableKind };\n\n/** The Settings modal's own per-kind behaviour (T4.2.1's formalization of the\n * seven `kind ===` conditionals `CallableSettingsModal.tsx` used to carry). */\nexport interface CallableSettingsDescriptor {\n /** May the `key` be typed here at all? Function/Workflow yes, Endpoint no\n * (`rfcs/endpoint.md` — an Endpoint's address is its identity). */\n canEditKey: boolean;\n /** Does this kind store tags? Workflow only. */\n hasTags: boolean;\n /** Placeholder for the Name field. */\n namePlaceholder: string;\n /** Placeholder for the Key field (read only when {@link canEditKey}). */\n keyPlaceholder: string;\n /** Appended to the shared \"Lowercase, kebab-case, 3–39 characters.\" hint —\n * `\"\"` for a kind that cannot unset its key, the \"Leave empty to unset.\"\n * sentence for the one that can. */\n keyHintSuffix: string;\n}\n\n/** The editor chrome's own per-kind copy. */\nexport interface CallableEditorDescriptor {\n /** The back control's label, e.g. `\"← Functions\"`. */\n backLabel: string;\n /** Heading fallback while the definition is still hydrating. */\n newTitle: string;\n /** Rendered in place of the form when the hydration GET 404s. */\n notFoundTitle: string;\n /** The Save button's idle label. */\n saveLabel: string;\n}\n\nexport interface CallableDescriptor {\n kind: CallableKind;\n /** The list page's `<h2>`, and the editor document title's second segment. */\n listTitle: string;\n /** The list page's explanatory paragraph. */\n listDescription: string;\n /** The empty-state paragraph (verbatim, including its typographic quotes). */\n emptyCopy: string;\n /** The create button's label, e.g. `\"+ New function\"`. */\n newLabel: string;\n /** The synthetic id's own prefix — `fn_…`/`ep_…`/`wf_…`, never user-edited. */\n newIdPrefix: string;\n /** `data-testid` of the list's Import affordance. */\n importOpenTestId: string;\n /** `data-testid` of the list's \"Show archived\" checkbox. */\n showArchivedTestId: string;\n /** `data-testid` of a row's \"archived\" badge. */\n archivedBadgeTestId: string;\n /** The row button's `title` tooltip (T4.2.3 — replaces the shared template literal\n * `` `Open this ${kind} in the editor.` ``, since Workflow's own row opens the visual editor,\n * not \"the editor\"). */\n openRowTitle: string;\n editor: CallableEditorDescriptor;\n settings: CallableSettingsDescriptor;\n}\n\n/**\n * The three kinds, every arm named explicitly — a total `Record<CallableKind,\n * …>`, so a fourth kind fails to compile here rather than silently rendering\n * another kind's copy (the same reasoning `COLLECTION_PATH` gives in\n * `src/repos/versions.ts`).\n *\n * Only the `function` arm is consumed today: Endpoints and Workflows keep their\n * own pages until T4.2.2/T4.2.3. Their arms are filled from those pages'\n * current literals so the later nodes are a deletion, not a re-derivation.\n */\nexport const CALLABLE_DESCRIPTORS: Record<CallableKind, CallableDescriptor> = {\n function: {\n kind: \"function\",\n listTitle: \"Functions\",\n listDescription:\n 'A Function is a reusable, vendor-abstracted operation — \"Send Email\", \"Create Contact\" — ' +\n \"with a stable interface bound to one swappable app action. Switch provider by \" +\n \"re-binding; callers never change.\",\n emptyCopy:\n \"None yet — click “New function” to create one, or “Import” to bring in a spec document.\",\n newLabel: \"+ New function\",\n newIdPrefix: \"fn\",\n importOpenTestId: \"functions-import-open\",\n showArchivedTestId: \"functions-show-archived\",\n archivedBadgeTestId: \"function-archived\",\n openRowTitle: \"Open this function in the editor.\",\n editor: {\n backLabel: \"← Functions\",\n newTitle: \"New function\",\n notFoundTitle: \"Function not found\",\n saveLabel: \"Save\",\n },\n settings: {\n canEditKey: true,\n hasTags: false,\n namePlaceholder: \"Send Email\",\n keyPlaceholder: \"send-email\",\n keyHintSuffix: \"\",\n },\n },\n endpoint: {\n kind: \"endpoint\",\n listTitle: \"Endpoints\",\n listDescription:\n \"An Endpoint is a named, stable entry point that dispatches to one app action, Function, \" +\n \"or Workflow. Callers bind to the Endpoint; the target behind it can change — promote an \" +\n \"action to a Function or a Workflow, or re-bind it — without breaking a single caller.\",\n emptyCopy: \"None yet — click “New endpoint” to create one.\",\n newLabel: \"+ New endpoint\",\n newIdPrefix: \"ep\",\n importOpenTestId: \"endpoints-import-open\",\n showArchivedTestId: \"endpoints-show-archived\",\n archivedBadgeTestId: \"endpoint-archived\",\n openRowTitle: \"Open this endpoint in the editor.\",\n editor: {\n backLabel: \"← Endpoints\",\n newTitle: \"New endpoint\",\n notFoundTitle: \"Endpoint not found\",\n saveLabel: \"Save\",\n },\n settings: {\n canEditKey: false,\n hasTags: false,\n namePlaceholder: \"My endpoint\",\n keyPlaceholder: \"send-email\",\n keyHintSuffix: \"\",\n },\n },\n workflow: {\n kind: \"workflow\",\n listTitle: \"Workflows\",\n listDescription:\n \"A Workflow is a durable, multi-step run: each step calls an app action, a Function, or \" +\n \"another Workflow, and a run keeps its own state, history and error handling.\",\n emptyCopy: \"None yet — click “New workflow” to create one.\",\n newLabel: \"+ New workflow\",\n newIdPrefix: \"wf\",\n importOpenTestId: \"workflows-import-open\",\n showArchivedTestId: \"workflows-show-archived\",\n archivedBadgeTestId: \"workflow-archived\",\n openRowTitle: \"Open this workflow in the visual editor.\",\n editor: {\n backLabel: \"← Workflows\",\n newTitle: \"New workflow\",\n notFoundTitle: \"Workflow not found\",\n saveLabel: \"Save\",\n },\n settings: {\n canEditKey: true,\n hasTags: true,\n namePlaceholder: \"My workflow\",\n keyPlaceholder: \"unset\",\n keyHintSuffix: \" Leave empty to unset.\",\n },\n },\n};\n\n/** Look a descriptor up by kind. A plain index, never a `switch`: the `Record`\n * above already made every arm total. */\nexport function descriptorFor(kind: CallableKind): CallableDescriptor {\n return CALLABLE_DESCRIPTORS[kind];\n}\n\n/**\n * A fresh synthetic id for a create-modal's first POST — `fn_<uuid>` for a\n * Function (verbatim the `newFunctionId` `FunctionsPage.tsx` used to hold),\n * `ep_`/`wf_` for the other two, whose pages mint the same shapes today. The\n * prefix comes from the descriptor, so \"which kind is this?\" is answered by the\n * same table that answers every other kind question.\n */\nexport function newCallableId(kind: CallableKind): string {\n return newId(descriptorFor(kind).newIdPrefix);\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { type W6WClient, isFunctionRun } from \"@w6w/sdk\";\nimport type { FunctionSummary as SdkFunctionSummary } from \"@w6w/sdk/console\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n/**\n * The Function-bound facade over the kind-parametrised repo (`src/repos/callables.ts`, T4.2.1).\n *\n * Everything here that is not Function-specific is one line delegating to `callables.ts` with\n * `\"function\"` bound in — the list/get queries, the save mutation, archive and delete — so the\n * Function arm of every kind-wide behaviour has exactly ONE implementation to fix. What stays is\n * what only a Function has: the `manifestVersion: \"2\"` literal, the SDK's Function type re-exports,\n * the `valid`-carrying summary widening, and the run-plane invoke (`client.run`, `isFunctionRun`)\n * that no other kind's page uses.\n *\n * The delegations keep their original names and call shapes on purpose: `ui/rail/SettingsTool.tsx`,\n * `ui/rail/AliasesTool.tsx`, `ui/rail/ErrorHandlingTool.tsx`, `components/TargetSelector.tsx`,\n * `components/FunctionIdentityModal.tsx` and `api/w6wApiFacade.tsx` all import from here, and this\n * node moves no behaviour — only where the code lives.\n */\nimport { callableKey } from \"../lib/callable-kind.ts\";\nimport { invalidateSavedCallable } from \"../lib/save-invalidation.ts\";\nimport {\n callableListKey,\n useArchiveCallableMutation,\n useCallableListQuery,\n useCallableQuery,\n useDeleteCallableMutation,\n useSaveCallableMutation,\n} from \"./callables.ts\";\n\nexport type {\n FunctionDef,\n FunctionImpl,\n FunctionInput,\n FunctionOutputField,\n} from \"@w6w/sdk/console\";\n\n/** A Function list row — the SDK's own summary (it carries `archivedAt` since W-12). */\nexport type FunctionSummary = SdkFunctionSummary;\n\n/** The list key {@link useFunctionsQuery} reads — `callables.ts`'s own\n * `callableListKey(\"function\")`, kept as a named export because\n * `lib/spec-import-invalidation.ts` invalidates it by value. */\nexport const functionsKey = callableListKey(\"function\");\n\n/** Function definitions carry `manifestVersion: \"2\"` - the one literal, shared\n * by the editor's blank draft and the create modal's first POST. */\nexport const FUNCTION_MANIFEST_VERSION = \"2\";\n\nexport function listFunctions(client: W6WClient) {\n return client.console.functions.list();\n}\n\nexport function useFunctionsQuery(enabled = true) {\n return useCallableListQuery<FunctionSummary>(\"function\", enabled);\n}\n\nexport const functionKey = (id: string) => callableKey(\"function\", id);\n\n/** The Function arm's own reader: the SDK's typed `get`, whose `{...function, valid}` splice is\n * what `FunctionEditor` hydrates its draft from (pin 5 — the server computes `valid`; studio\n * never reimplements the check). */\nexport function getFunction(client: W6WClient, id: string) {\n return client.console.functions.get(id);\n}\n\nexport function useFunctionQuery(id: string, enabled = true) {\n return useCallableQuery<Awaited<ReturnType<typeof getFunction>>>(\"function\", id, enabled);\n}\n\nexport function useSaveFunctionMutation() {\n return useSaveCallableMutation(\"function\");\n}\n\n/**\n * The GUARDED Function save: `console.functions.upsert(definition, {ifUnmodifiedSince})`, so a\n * save made from a stale copy answers `409 function_stale` instead of overwriting the newer one.\n * `ifUnmodifiedSince` is REQUIRED in the variables (pass `null` to opt out explicitly) so a call\n * site cannot forget the token; it is the `updatedAt` of the copy the definition was edited from\n * (`callableRecord(\"function\", …).updatedAt`). Same invalidation as {@link useSaveFunctionMutation}\n * (list + the saved resource's key); resolves `{id, key, updatedAt}`. Additive: the unguarded\n * hook's `mutate(definition)` shape is unchanged.\n */\nexport function useGuardedSaveFunctionMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { definition: unknown; ifUnmodifiedSince: string | null }) =>\n apiClient.console.functions.upsert(vars.definition as never, {\n ifUnmodifiedSince: vars.ifUnmodifiedSince,\n }),\n onSuccess: (saved) => invalidateSavedCallable(qc, functionsKey, functionKey(saved.id)),\n });\n}\n\n/**\n * One test invoke's result: the Function's own output, plus the platform's\n * record of the attempt.\n *\n * The two are kept apart rather than merged because they answer different\n * questions, and merging them is what the invocation envelope exists to stop:\n * a vendor payload reading `{\"statusCode\": 202}` is SendGrid describing its own\n * request, while `status` here is whether w6w considered the call a success.\n * The frame fields are optional — an older server sends only the output.\n */\nexport interface FunctionInvokeResult {\n output: unknown;\n invocationId?: string;\n status?: string;\n durationMs?: number;\n}\n\n/**\n * `fn_…` ids are already URN-shaped, so the base dispatcher resolves them\n * directly — no id translation. `isFunctionRun` narrows the open\n * `RunEnvelope`; a `fn_…` URN can only ever resolve to the `function` arm\n * server-side, so the `else` branch is defensive, not a real code path.\n */\nexport function invokeFunction(\n client: W6WClient,\n id: string,\n inputs: Record<string, unknown>,\n): Promise<FunctionInvokeResult> {\n return client.run({ urn: id, payload: inputs }).then((env) => {\n if (!isFunctionRun(env)) {\n throw new Error(`expected a function-kind run envelope for \"${id}\", got \"${env.kind}\"`);\n }\n return {\n output: env.output,\n invocationId: env.invocationId,\n status: env.status,\n durationMs: env.durationMs,\n };\n });\n}\n\nexport function useInvokeFunctionMutation() {\n const apiClient = useEmbedClient();\n return useMutation({\n mutationFn: (vars: { id: string; inputs: Record<string, unknown> }) =>\n invokeFunction(apiClient, vars.id, vars.inputs),\n });\n}\n\n/**\n * T4.1.1/A7/D-I0-7: `POST /functions/:id/archive`, `DELETE /functions/:id` — the Function arm of\n * `callables.ts`'s generic pair (the plain `apiClient.request()` escape hatch, NOT a typed\n * `@w6w/sdk` method, which would drag `packages/wrappers` into this task's scope for two internal\n * routes). Both invalidate `functionsKey`, so the list's `archivedAt` refreshes and the rail's\n * Delete control appears in Archive's place.\n */\nexport function useArchiveFunctionMutation() {\n return useArchiveCallableMutation(\"function\");\n}\n\nexport function useDeleteFunctionMutation() {\n return useDeleteCallableMutation(\"function\");\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { W6WClient } from \"@w6w/sdk\";\nimport type {\n EndpointDef as SdkEndpointDef,\n EndpointSummary as SdkEndpointSummary,\n EndpointTarget as SdkEndpointTarget,\n} from \"@w6w/sdk/console\";\n/**\n * The Endpoint-bound facade over the kind-parametrised repo (`src/repos/callables.ts`, T4.2.2).\n *\n * Everything here that is not Endpoint-specific is one line delegating to `callables.ts` with\n * `\"endpoint\"` bound in — the list/get queries, archive and delete — so the Endpoint arm of every\n * kind-wide behaviour has exactly ONE implementation to fix (the shape `repos/functions.ts` took in\n * T4.2.1, and the \"keep the facade's exports\" rule that module documents). What stays is what only\n * an Endpoint has: the `manifestVersion: \"2\"` literal, the SDK's Endpoint type re-exports, the\n * `status`/`incomplete`/`archivedAt`-carrying summary widening with its one reader\n * {@link isEndpointDraft}, the server-rendered `invokeUrls[]` widening, the synchronous invoke\n * (`client.console.endpoints.invoke`), and the SAVE — whose 201 carries those `invokeUrls[]` back to\n * the editor's URL card, which is why its `mutationFn` is the one arm the generic `saveCallable`\n * cannot serve.\n *\n * The delegations keep their original names and call shapes on purpose: `ui/rail/SettingsTool.tsx`,\n * `ui/rail/AliasesTool.tsx`, `ui/rail/ErrorHandlingTool.tsx`, `components/TargetSelector.tsx`,\n * `components/EndpointIdentityModal.tsx`, `repos/versions.ts` (the revert arm's `endpointKey`) and\n * `repos/spec-import.ts` (`endpointsKey`) all import from here, and this node moves no behaviour —\n * only where the code lives. The two key exports stay byte-identical because both are the builders\n * `callables.ts` already documents as frozen (`[\"endpoints\"]`, `[\"endpoint\", id]`).\n */\nimport { callableKey } from \"../lib/callable-kind.ts\";\nimport { invalidateSavedCallable } from \"../lib/save-invalidation.ts\";\n\nexport type {\n ActionTarget,\n CallableRef,\n CallableOnError,\n ErrorHandlerTarget,\n EndpointAuthMode,\n EndpointInput,\n EndpointInvokeResult,\n EndpointSecurity,\n EndpointTarget,\n ErrorReroute,\n Exposure,\n RetryPolicy,\n} from \"@w6w/sdk/console\";\nexport { SECRET_MASK } from \"@w6w/sdk/console\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\nimport {\n callableListKey,\n useArchiveCallableMutation,\n useCallableListQuery,\n useCallableQuery,\n useDeleteCallableMutation,\n} from \"./callables.ts\";\n\n/** An Endpoint's OWN target: the alias-only `endpoint` arm excluded, mirroring the\n * server fence in admin/endpoints.ts's validateDefinition. Aliases use the full union\n * (`EndpointTarget`, re-exported above verbatim). */\nexport type EndpointOwnTarget = Exclude<SdkEndpointTarget, { kind: \"endpoint\" }>;\nexport type EndpointDef = Omit<SdkEndpointDef, \"target\"> & { target: EndpointOwnTarget };\n\n/**\n * One entry of the `invokeUrls[]` array the server renders on `GET\n * /endpoints/:id` and the `POST /endpoints` 201 (T3.4.1, `admin/endpoints.ts`'s\n * `InvokeUrlEntry` — the shapes are kept in sync by hand, not shared, because\n * `@w6w/sdk` does not type this field yet: it is server-fresh and\n * `packages/wrappers` publishes in lockstep at one `VERSION` across four\n * languages, outside this project's boundary (HITL-10). `entries[0]` is always\n * the platform entry; every entry after it is one of the tenant's domains.\n * `default` mirrors the tenant's stored default domain and, since D-S1\n * (intake T-0.2), it is what CHOOSES the open-on entry: absent an\n * in-session pick, the URL card opens on whichever entry carries it,\n * falling back to `entries[0]` only when no entry does. `resolves` is a\n * static host comparison the server already made; the client never\n * re-derives it.\n */\nexport interface InvokeUrlOption {\n domain: string;\n default: boolean;\n url: string;\n urlByKey?: string;\n resolves: boolean;\n}\n\n/** The two SDK-typed URL fields, widened with the untyped `invokeUrls[]`\n * array — the ONE seam `getEndpoint`, the save mutation and the editor's own\n * 201 read all widen through, so `EndpointsPage.tsx` never casts. */\ntype WithInvokeUrls = {\n invokeUrl: string;\n invokeUrlByKey?: string;\n invokeUrls?: InvokeUrlOption[];\n};\n\n/** An Endpoint list row — the SDK's own summary (`status`, `incomplete` and `archivedAt` are\n * on it since W-12), read for draft-ness only through {@link isEndpointDraft}. */\nexport type EndpointSummary = SdkEndpointSummary;\n\n/** Is this row a draft — not authorised to dispatch (HITL-7/HITL-8,\n * `rfcs/endpoint.md` § Amendment — 2026-08-14b)? Prefers the server's `status`\n * field (`!== \"ready\"`), falling back to the older `incomplete` boolean only\n * when `status` is absent (a server that has not shipped it yet). The sole\n * reader of both fields in studio; every \"unfinished\" UI decision (the\n * list's tag, and any future one) calls this rather than reading either\n * field inline. */\nexport function isEndpointDraft(ep: Pick<EndpointSummary, \"status\" | \"incomplete\">): boolean {\n return ep.status !== undefined ? ep.status !== \"ready\" : ep.incomplete === true;\n}\n\n/** Endpoint definitions carry `manifestVersion: \"2\"` — the one literal, shared\n * by the editor's blank draft and the create modal's first POST. */\nexport const ENDPOINT_MANIFEST_VERSION = \"2\";\n\n/** The list key {@link useEndpointsQuery} reads — `callables.ts`'s own\n * `callableListKey(\"endpoint\")` (byte-identical `[\"endpoints\"]`), kept as a named export because\n * `repos/spec-import.ts` invalidates it by value. */\nexport const endpointsKey = callableListKey(\"endpoint\");\n\nexport function useEndpointsQuery(enabled = true) {\n return useCallableListQuery<EndpointSummary>(\"endpoint\", enabled);\n}\n\n/** Fetch one Endpoint. Widens the SDK's return once — the server sends\n * `invokeUrls[]` (T3.4.1) that `@w6w/sdk`'s typed `get()` does not know about\n * yet; see {@link WithInvokeUrls}. */\nexport function getEndpoint(\n client: W6WClient,\n id: string,\n): Promise<{ endpoint: EndpointDef } & WithInvokeUrls> {\n return client.console.endpoints.get(id) as Promise<{ endpoint: EndpointDef } & WithInvokeUrls>;\n}\n\n/** The single-resource key — `callables.ts`'s own `callableKey(\"endpoint\", id)` (byte-identical\n * `[\"endpoint\", id]`), kept as a named export because `repos/versions.ts`'s revert arm invalidates\n * it by value. */\nexport const endpointKey = (id: string) => callableKey(\"endpoint\", id);\n\n/** `TargetSelector`'s `endpoint` arm needs one Endpoint's own `input` contract\n * to project into fields — mirrors `useFunctionQuery`/`useWorkflowQuery`\n * (`repos/functions.ts`/`repos/workflows.ts`) exactly. */\nexport function useEndpointQuery(id: string, enabled = true) {\n return useCallableQuery<Awaited<ReturnType<typeof getEndpoint>>>(\"endpoint\", id, enabled);\n}\n\n/**\n * The Endpoint arm's SAVE — the one delegated name whose `mutationFn` is NOT `callables.ts`'s\n * `saveCallable`: that helper normalises every kind's success envelope down to `{id, key}` for the\n * invalidation below, while this kind's 201 also carries the fresh server-rendered `invokeUrl`/\n * `invokeUrlByKey`/`invokeUrls[]` the editor's URL card renders from (`onSaveSuccess` in\n * `EndpointsPage.tsx`). Its KEYS and its invalidation, though, are the generic pair's — so the\n * \"which keys does an Endpoint save refresh\" answer still has one home.\n */\nexport function useSaveEndpointMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n // Same widening as `getEndpoint` — the save's 201 carries `invokeUrls[]` too.\n mutationFn: (definition: unknown) =>\n apiClient.console.endpoints.upsert(definition as never) as Promise<\n { endpoint: { id: string; key: string } } & WithInvokeUrls\n >,\n onSuccess: (saved) => invalidateSavedCallable(qc, endpointsKey, endpointKey(saved.endpoint.id)),\n });\n}\n\n/**\n * The GUARDED Endpoint save: `console.endpoints.upsert(definition, {ifUnmodifiedSince})`, so a\n * save from a stale copy answers `409 endpoint_stale`. Variables and invalidation as\n * {@link useSaveEndpointMutation}'s, plus the required token (`null` opts out explicitly; it is\n * `callableRecord(\"endpoint\", …).updatedAt`, the envelope's TOP-LEVEL `updatedAt`). Resolves the\n * verbatim upsert body (`{endpoint:{id,key}, invokeUrl, …, updatedAt}`). Additive: the unguarded\n * hook's `mutate(definition)` shape is unchanged.\n */\nexport function useGuardedSaveEndpointMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { definition: unknown; ifUnmodifiedSince: string | null }) =>\n apiClient.console.endpoints.upsert(vars.definition as never, {\n ifUnmodifiedSince: vars.ifUnmodifiedSince,\n }) as Promise<{ endpoint: { id: string; key: string }; updatedAt: string } & WithInvokeUrls>,\n onSuccess: (saved) => invalidateSavedCallable(qc, endpointsKey, endpointKey(saved.endpoint.id)),\n });\n}\n\nexport function invokeEndpoint(client: W6WClient, id: string, input: Record<string, unknown>) {\n return client.console.endpoints.invoke(id, input);\n}\n\nexport function useInvokeEndpointMutation() {\n const apiClient = useEmbedClient();\n return useMutation({\n mutationFn: (vars: { id: string; input: Record<string, unknown> }) =>\n invokeEndpoint(apiClient, vars.id, vars.input),\n });\n}\n\n/**\n * T4.1.1/A7/D-I0-7: `POST /endpoints/:id/archive` — the Endpoint arm of `callables.ts`'s generic\n * pair (the plain `apiClient.request()` escape hatch, NOT a typed `@w6w/sdk` method, which would\n * drag `packages/wrappers` into this task's scope for one internal route). Invalidates\n * `endpointsKey`, so the list's `archivedAt` refreshes and the rail's Delete control appears in\n * Archive's place.\n */\nexport function useArchiveEndpointMutation() {\n return useArchiveCallableMutation(\"endpoint\");\n}\n\n/** `DELETE /endpoints/:id` — the Endpoint arm of the same generic pair. */\nexport function useDeleteEndpointMutation() {\n return useDeleteCallableMutation(\"endpoint\");\n}\n"],"names":["ID_ALPHABET","REJECT_AT","defaultBytes","newId","prefix","len","bytes","out","b","CALLABLE_DESCRIPTORS","descriptorFor","kind","newCallableId","functionsKey","callableListKey","FUNCTION_MANIFEST_VERSION","listFunctions","client","useFunctionsQuery","enabled","useCallableListQuery","functionKey","id","callableKey","getFunction","useFunctionQuery","useCallableQuery","useSaveFunctionMutation","useSaveCallableMutation","useGuardedSaveFunctionMutation","apiClient","useEmbedClient","qc","useQueryClient","useMutation","vars","saved","invalidateSavedCallable","invokeFunction","inputs","env","isFunctionRun","useInvokeFunctionMutation","useArchiveFunctionMutation","useArchiveCallableMutation","useDeleteFunctionMutation","useDeleteCallableMutation","isEndpointDraft","ep","ENDPOINT_MANIFEST_VERSION","endpointsKey","useEndpointsQuery","getEndpoint","endpointKey","useEndpointQuery","useSaveEndpointMutation","definition","useGuardedSaveEndpointMutation","invokeEndpoint","input","useInvokeEndpointMutation","useArchiveEndpointMutation","useDeleteEndpointMutation"],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity modal shared by the Endpoints list ("+ New endpoint" — create
|
|
3
|
+
* mode) and the editor's read-only info block ("edit" icon-button — edit
|
|
4
|
+
* mode). `isEdit = !!props.initial`, mirroring `VarModal` and `FunctionIdentityModal`.
|
|
5
|
+
*
|
|
6
|
+
* **Create mode POSTs for real, right here — before any editor exists.**
|
|
7
|
+
* That is this node's whole point: the row is created against the server
|
|
8
|
+
* before the operator can put target/input work into a plain `useState` that
|
|
9
|
+
* used to die on a missing var, a lost tab, or anything else short of a
|
|
10
|
+
* completed Save. Submit is disabled unless the key clears
|
|
11
|
+
* {@link isEndpointKey}; `takenKeys` (from the list's own `GET /endpoints`)
|
|
12
|
+
* is an ADVISORY pre-check only — the account-scoped unique index is the
|
|
13
|
+
* arbiter, and any refusal (409 `endpoint_key_conflict`, 409
|
|
14
|
+
* `key_immutable`, 400 `invalid_endpoint`) renders `ApiError.message`
|
|
15
|
+
* verbatim and leaves the modal open with what was typed intact.
|
|
16
|
+
*
|
|
17
|
+
* **Edit mode writes NOTHING.** `POST /endpoints` is a whole-definition
|
|
18
|
+
* upsert, so an identity-only PATCH here would silently wipe the target and
|
|
19
|
+
* input the editor already has saved — precisely the data loss this whole
|
|
20
|
+
* node exists to stop. The patched fields go back through `onSaved`; the
|
|
21
|
+
* editor's own `onSave()` stays the one path that ever persists them.
|
|
22
|
+
*/
|
|
23
|
+
export declare function EndpointIdentityModal(props: {
|
|
24
|
+
/** Edit mode when present; create mode when absent. Mirrors VarModal's `isEdit = !!props.initial`. */
|
|
25
|
+
initial?: {
|
|
26
|
+
key: string;
|
|
27
|
+
displayName: string;
|
|
28
|
+
description: string;
|
|
29
|
+
};
|
|
30
|
+
/** Create mode only: the caller-minted `ep_…` id the POST carries. */
|
|
31
|
+
newId?: string;
|
|
32
|
+
/** Create mode only: keys already taken in this account — advisory pre-check. */
|
|
33
|
+
takenKeys?: readonly string[];
|
|
34
|
+
onClose: () => void;
|
|
35
|
+
/** Create mode: the id the SERVER returned (`saved.endpoint.id`). */
|
|
36
|
+
onCreated?: (id: string) => void;
|
|
37
|
+
/** Edit mode: the patched identity fields. The modal itself writes NOTHING. */
|
|
38
|
+
onSaved?: (next: {
|
|
39
|
+
displayName: string;
|
|
40
|
+
description: string;
|
|
41
|
+
}) => void;
|
|
42
|
+
}): import("react").JSX.Element;
|
|
43
|
+
/**
|
|
44
|
+
* Creates an Endpoint: the identity modal in create mode, in its own `.w6w-embed-root`. The id is
|
|
45
|
+
* minted once per mount. Without `takenKeys` the modal reads the account's keys itself
|
|
46
|
+
* (`GET /endpoints`) for the advisory "already in use" hint; the server stays the arbiter.
|
|
47
|
+
*/
|
|
48
|
+
export declare function CreateEndpointModal(props: {
|
|
49
|
+
onClose: () => void;
|
|
50
|
+
/** The id the SERVER returned for the new Endpoint. */
|
|
51
|
+
onCreated: (id: string) => void;
|
|
52
|
+
/** Keys already taken in this account. Omitted: read from the Endpoints list. */
|
|
53
|
+
takenKeys?: readonly string[];
|
|
54
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity modal shared by the Functions list ("+ New function" — create
|
|
3
|
+
* mode) and the editor's read-only info block ("edit" icon-button — edit
|
|
4
|
+
* mode). `isEdit = !!props.initial`, mirroring `VarModal` and
|
|
5
|
+
* `EndpointIdentityModal`.
|
|
6
|
+
*
|
|
7
|
+
* **Create mode POSTs for real, right here — before any editor exists.**
|
|
8
|
+
* That is this node's whole point: the row is created against the server
|
|
9
|
+
* before the operator can put impl/input work into a plain `useState` that
|
|
10
|
+
* used to die on a missing var, a lost tab, or anything else short of a
|
|
11
|
+
* completed Save. Submit is disabled unless the key clears
|
|
12
|
+
* {@link isEndpointKey} (reused — pin 2: the grammar is identical, so no
|
|
13
|
+
* `isFunctionKey`); `takenKeys` (from the list's own `GET /functions`) is an
|
|
14
|
+
* ADVISORY pre-check only — the account-scoped unique index is the arbiter,
|
|
15
|
+
* and any refusal renders `ApiError.message` verbatim and leaves the modal
|
|
16
|
+
* open with what was typed intact.
|
|
17
|
+
*
|
|
18
|
+
* **Edit mode writes NOTHING.** `POST /functions` is a whole-definition
|
|
19
|
+
* upsert, so an identity-only PATCH here would silently wipe the impl and
|
|
20
|
+
* inputs the editor already has saved — precisely the data loss this whole
|
|
21
|
+
* node exists to stop. The patched fields go back through `onSaved`; the
|
|
22
|
+
* editor's own `onSave()` stays the one path that ever persists them.
|
|
23
|
+
*/
|
|
24
|
+
export declare function FunctionIdentityModal(props: {
|
|
25
|
+
/** Edit mode when present; create mode when absent. Mirrors VarModal's `isEdit = !!props.initial`. */
|
|
26
|
+
initial?: {
|
|
27
|
+
key: string;
|
|
28
|
+
displayName: string;
|
|
29
|
+
description: string;
|
|
30
|
+
};
|
|
31
|
+
/** Create mode only: the caller-minted `fn_…` id the POST carries. */
|
|
32
|
+
newId?: string;
|
|
33
|
+
/** Create mode only: keys already taken in this account — advisory pre-check. */
|
|
34
|
+
takenKeys?: readonly string[];
|
|
35
|
+
onClose: () => void;
|
|
36
|
+
/** Create mode: the id the SERVER returned (`saved.function.id`). */
|
|
37
|
+
onCreated?: (id: string) => void;
|
|
38
|
+
/** Edit mode: the patched identity fields. The modal itself writes NOTHING. */
|
|
39
|
+
onSaved?: (next: {
|
|
40
|
+
displayName: string;
|
|
41
|
+
description: string;
|
|
42
|
+
}) => void;
|
|
43
|
+
}): import("react").JSX.Element;
|
|
44
|
+
/**
|
|
45
|
+
* Creates a Function: the identity modal in create mode, in its own `.w6w-embed-root`. The id is
|
|
46
|
+
* minted once per mount. Without `takenKeys` the modal reads the account's keys itself
|
|
47
|
+
* (`GET /functions`) for the advisory "already in use" hint; the server stays the arbiter.
|
|
48
|
+
*/
|
|
49
|
+
export declare function CreateFunctionModal(props: {
|
|
50
|
+
onClose: () => void;
|
|
51
|
+
/** The id the SERVER returned for the new Function. */
|
|
52
|
+
onCreated: (id: string) => void;
|
|
53
|
+
/** Keys already taken in this account. Omitted: read from the Functions list. */
|
|
54
|
+
takenKeys?: readonly string[];
|
|
55
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Doc } from '@w6w/sdk';
|
|
2
|
+
export declare function DocumentFormModal(props: {
|
|
3
|
+
initial?: Doc;
|
|
4
|
+
/** The resolved project, or `null` (none yet): a save is refused, never sent project-less. */
|
|
5
|
+
project: string | null;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
onSaved: () => void;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ConfigManagerActionsApi } from './VarsManager.tsx';
|
|
3
|
+
/** Same contract as `VarsManagerSlots`: omitted ⇒ default, `null` ⇒ nothing, a node replaces. */
|
|
4
|
+
export interface SecretsManagerSlots {
|
|
5
|
+
header?: ReactNode;
|
|
6
|
+
actions?: ReactNode | ((api: ConfigManagerActionsApi) => ReactNode);
|
|
7
|
+
empty?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export interface SecretsManagerProps {
|
|
10
|
+
slots?: SecretsManagerSlots;
|
|
11
|
+
}
|
|
12
|
+
export declare function SecretsManager(props: SecretsManagerProps): ReactNode;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
/** What a function-form `actions` slot receives. */
|
|
3
|
+
export interface ConfigManagerActionsApi {
|
|
4
|
+
/** Open the create form (a no-op while the manager is refusing, e.g. no project). */
|
|
5
|
+
openCreate: () => void;
|
|
6
|
+
/** `false` when the create control must be disabled (no project). */
|
|
7
|
+
canCreate: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Each slot: omitted ⇒ the built-in default; `null` ⇒ nothing; a node replaces it. `actions` also
|
|
11
|
+
* accepts a function so a host that replaces the default "+ Add" button can still open the form.
|
|
12
|
+
*/
|
|
13
|
+
export interface VarsManagerSlots {
|
|
14
|
+
/** The section heading + description. */
|
|
15
|
+
header?: ReactNode;
|
|
16
|
+
/** The trailing control(s) of the head row (the "+ Add variable" button). */
|
|
17
|
+
actions?: ReactNode | ((api: ConfigManagerActionsApi) => ReactNode);
|
|
18
|
+
/** Shown instead of the list when there are no variables. */
|
|
19
|
+
empty?: ReactNode;
|
|
20
|
+
}
|
|
21
|
+
export interface VarsManagerProps {
|
|
22
|
+
/**
|
|
23
|
+
* The project whose variables are managed. Omitted: the `<W6WEmbedProvider project>`. `null` or
|
|
24
|
+
* `""`: no project — nothing is requested and nothing can be written.
|
|
25
|
+
*/
|
|
26
|
+
project?: string | null;
|
|
27
|
+
slots?: VarsManagerSlots;
|
|
28
|
+
}
|
|
29
|
+
export declare function VarsManager(props: VarsManagerProps): ReactNode;
|
package/dist/forms.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { CreateFunctionModal } from './forms/CreateFunctionModal.tsx';
|
|
2
|
+
export { CreateEndpointModal } from './forms/CreateEndpointModal.tsx';
|
|
3
|
+
export { VarsManager } from './forms/VarsManager.tsx';
|
|
4
|
+
export type { ConfigManagerActionsApi, VarsManagerProps, VarsManagerSlots, } from './forms/VarsManager.tsx';
|
|
5
|
+
export { SecretsManager } from './forms/SecretsManager.tsx';
|
|
6
|
+
export type { SecretsManagerProps, SecretsManagerSlots } from './forms/SecretsManager.tsx';
|
package/dist/forms.mjs
ADDED
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { C as re, a as se } from "./CreateFunctionModal-DRsFx-FB.js";
|
|
3
|
+
import { jsxs as n, jsx as e, Fragment as V } from "react/jsx-runtime";
|
|
4
|
+
import { ApiError as x } from "@w6w/sdk";
|
|
5
|
+
import { Copyable as A, EditButton as L, DeleteButton as j, useEnterSubmit as P } from "@w6w/ui";
|
|
6
|
+
import { useState as h } from "react";
|
|
7
|
+
import { C as F, a as $, M as O } from "./ConfirmModal-RLbZT5_k.js";
|
|
8
|
+
import { u as T } from "./project-context-BiCjv_E3.js";
|
|
9
|
+
import { i as J, d as Q, b as U, h as _, f as B, c as R, u as I, g as W } from "./vault-BSEWhMYC.js";
|
|
10
|
+
const q = ["string", "number", "boolean", "json"];
|
|
11
|
+
function M(t) {
|
|
12
|
+
if (t.type === "boolean" || t.type === "number" || t.type === "string") return String(t.value);
|
|
13
|
+
const a = JSON.stringify(t.value);
|
|
14
|
+
return a.length > 80 ? `${a.slice(0, 80)}…` : a;
|
|
15
|
+
}
|
|
16
|
+
function ae(t) {
|
|
17
|
+
var d, S;
|
|
18
|
+
const a = t.slots, s = T(t.project), [v, i] = h(null), [f, o] = h(null), u = J(s ?? void 0, s != null), g = Q(), p = s != null, m = () => {
|
|
19
|
+
s != null && i({ mode: "create" });
|
|
20
|
+
}, b = (a == null ? void 0 : a.header) === void 0 ? /* @__PURE__ */ n("div", { children: [
|
|
21
|
+
/* @__PURE__ */ e("h3", { children: "Variables" }),
|
|
22
|
+
/* @__PURE__ */ n("p", { className: "muted small", children: [
|
|
23
|
+
"User-defined typed values addressable by name. Plaintext — use ",
|
|
24
|
+
/* @__PURE__ */ e("strong", { children: "Secrets" }),
|
|
25
|
+
" ",
|
|
26
|
+
"for sensitive values."
|
|
27
|
+
] })
|
|
28
|
+
] }) : a.header, N = a == null ? void 0 : a.actions, y = N === void 0 ? /* @__PURE__ */ e("button", { type: "button", className: "btn", disabled: !p, onClick: m, children: "+ Add variable" }) : typeof N == "function" ? N({ openCreate: m, canCreate: p }) : N, C = (a == null ? void 0 : a.empty) === void 0 ? /* @__PURE__ */ e("p", { className: "muted", children: "No variables yet." }) : a.empty;
|
|
29
|
+
return /* @__PURE__ */ e("div", { className: "w6w-embed-root", children: /* @__PURE__ */ n("section", { className: "section", children: [
|
|
30
|
+
(b != null || y != null) && /* @__PURE__ */ n("div", { className: "section-head", children: [
|
|
31
|
+
b,
|
|
32
|
+
y
|
|
33
|
+
] }),
|
|
34
|
+
/* @__PURE__ */ n("div", { className: "card", children: [
|
|
35
|
+
u.isLoading && /* @__PURE__ */ e("p", { className: "muted", children: "Loading…" }),
|
|
36
|
+
((d = u.data) == null ? void 0 : d.length) === 0 && C,
|
|
37
|
+
/* @__PURE__ */ e("ul", { className: "list", children: (S = u.data) == null ? void 0 : S.map((r) => /* @__PURE__ */ n("li", { children: [
|
|
38
|
+
/* @__PURE__ */ n("div", { className: "list-main", children: [
|
|
39
|
+
/* @__PURE__ */ e("strong", { className: "list-name", title: r.name, children: r.name }),
|
|
40
|
+
" ",
|
|
41
|
+
/* @__PURE__ */ e("span", { className: "tag", children: r.type }),
|
|
42
|
+
/* @__PURE__ */ n("div", { className: "muted small list-preview", title: M(r), children: [
|
|
43
|
+
/* @__PURE__ */ e(A, { value: M(r), readOnly: !0, children: /* @__PURE__ */ e(
|
|
44
|
+
"code",
|
|
45
|
+
{
|
|
46
|
+
style: {
|
|
47
|
+
overflowWrap: "anywhere",
|
|
48
|
+
display: "block",
|
|
49
|
+
minWidth: 0,
|
|
50
|
+
overflow: "hidden",
|
|
51
|
+
textOverflow: "ellipsis",
|
|
52
|
+
flex: 1
|
|
53
|
+
},
|
|
54
|
+
children: M(r)
|
|
55
|
+
}
|
|
56
|
+
) }),
|
|
57
|
+
r.description && /* @__PURE__ */ n(V, { children: [
|
|
58
|
+
" · ",
|
|
59
|
+
r.description
|
|
60
|
+
] })
|
|
61
|
+
] })
|
|
62
|
+
] }),
|
|
63
|
+
/* @__PURE__ */ n("div", { style: { display: "flex", gap: "var(--w6w-sp-1-5)" }, children: [
|
|
64
|
+
/* @__PURE__ */ e(F, { resource: { kind: "var", name: r.name } }),
|
|
65
|
+
/* @__PURE__ */ e(
|
|
66
|
+
L,
|
|
67
|
+
{
|
|
68
|
+
label: "Edit",
|
|
69
|
+
onClick: () => i({ mode: "edit", v: r }),
|
|
70
|
+
"data-testid": `var-edit-${r.id}`
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ e(
|
|
74
|
+
j,
|
|
75
|
+
{
|
|
76
|
+
label: "Delete",
|
|
77
|
+
onClick: () => o(r),
|
|
78
|
+
disabled: g.isPending,
|
|
79
|
+
"data-testid": `var-delete-${r.id}`
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
] })
|
|
83
|
+
] }, r.id)) })
|
|
84
|
+
] }),
|
|
85
|
+
v && s != null && /* @__PURE__ */ e(
|
|
86
|
+
Y,
|
|
87
|
+
{
|
|
88
|
+
project: s,
|
|
89
|
+
initial: v.mode === "edit" ? v.v : void 0,
|
|
90
|
+
onClose: () => i(null),
|
|
91
|
+
onSaved: () => i(null)
|
|
92
|
+
}
|
|
93
|
+
),
|
|
94
|
+
f && s != null && /* @__PURE__ */ e(
|
|
95
|
+
$,
|
|
96
|
+
{
|
|
97
|
+
title: "Delete variable",
|
|
98
|
+
message: `Delete the variable "${f.name}"? This cannot be undone.`,
|
|
99
|
+
confirmLabel: "Delete",
|
|
100
|
+
onConfirm: () => {
|
|
101
|
+
g.mutate({ id: f.id, project: s }), o(null);
|
|
102
|
+
},
|
|
103
|
+
onClose: () => o(null)
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
] }) });
|
|
107
|
+
}
|
|
108
|
+
function Y(t) {
|
|
109
|
+
var k, c, D;
|
|
110
|
+
const a = !!t.initial, [s, v] = h(((k = t.initial) == null ? void 0 : k.name) ?? ""), [i, f] = h(((c = t.initial) == null ? void 0 : c.type) ?? "string"), [o, u] = h(() => t.initial ? t.initial.type === "string" ? String(t.initial.value ?? "") : JSON.stringify(t.initial.value, null, 2) : ""), [g, p] = h(((D = t.initial) == null ? void 0 : D.description) ?? ""), [m, b] = h(null);
|
|
111
|
+
function N() {
|
|
112
|
+
if (i === "string") return { ok: !0, value: o };
|
|
113
|
+
if (i === "boolean")
|
|
114
|
+
return o === "true" ? { ok: !0, value: !0 } : o === "false" ? { ok: !0, value: !1 } : { ok: !1, error: "Value must be `true` or `false`." };
|
|
115
|
+
if (i === "number") {
|
|
116
|
+
const l = Number(o);
|
|
117
|
+
return Number.isFinite(l) ? { ok: !0, value: l } : { ok: !1, error: "Value must be a finite number." };
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
return { ok: !0, value: JSON.parse(o) };
|
|
121
|
+
} catch (l) {
|
|
122
|
+
return { ok: !1, error: `Invalid JSON: ${l.message}` };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const y = U(), C = _(), d = y.isPending || C.isPending;
|
|
126
|
+
function S() {
|
|
127
|
+
const l = N();
|
|
128
|
+
if (!l.ok) {
|
|
129
|
+
b(l.error);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
b(null);
|
|
133
|
+
const E = {
|
|
134
|
+
onSuccess: () => t.onSaved(),
|
|
135
|
+
onError: (w) => b((w instanceof x, w.message))
|
|
136
|
+
};
|
|
137
|
+
if (t.initial) {
|
|
138
|
+
C.mutate(
|
|
139
|
+
{
|
|
140
|
+
id: t.initial.id,
|
|
141
|
+
patch: { type: i, value: l.value, description: g },
|
|
142
|
+
project: t.project
|
|
143
|
+
},
|
|
144
|
+
E
|
|
145
|
+
);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
y.mutate(
|
|
149
|
+
{ input: { name: s, type: i, value: l.value, description: g }, project: t.project },
|
|
150
|
+
E
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
const r = P(S, { enabled: !!s && !d });
|
|
154
|
+
return /* @__PURE__ */ n(
|
|
155
|
+
O,
|
|
156
|
+
{
|
|
157
|
+
title: t.initial ? `Edit ${t.initial.name}` : "Add variable",
|
|
158
|
+
onClose: t.onClose,
|
|
159
|
+
children: [
|
|
160
|
+
/* @__PURE__ */ n("div", { className: "modal-body", children: [
|
|
161
|
+
/* @__PURE__ */ n("label", { className: "field", children: [
|
|
162
|
+
/* @__PURE__ */ e("span", { children: "Name" }),
|
|
163
|
+
/* @__PURE__ */ e(
|
|
164
|
+
"input",
|
|
165
|
+
{
|
|
166
|
+
type: "text",
|
|
167
|
+
value: s,
|
|
168
|
+
disabled: a,
|
|
169
|
+
onChange: (l) => v(l.target.value),
|
|
170
|
+
placeholder: "e.g. api_base_url",
|
|
171
|
+
maxLength: 64,
|
|
172
|
+
...r
|
|
173
|
+
}
|
|
174
|
+
),
|
|
175
|
+
!a && /* @__PURE__ */ e("span", { className: "hint", children: "Lowercase letters, digits, and underscores. Must start with a letter or underscore." })
|
|
176
|
+
] }),
|
|
177
|
+
/* @__PURE__ */ n("label", { className: "field", children: [
|
|
178
|
+
/* @__PURE__ */ e("span", { children: "Type" }),
|
|
179
|
+
/* @__PURE__ */ e("select", { value: i, onChange: (l) => f(l.target.value), children: q.map((l) => /* @__PURE__ */ e("option", { value: l, children: l }, l)) })
|
|
180
|
+
] }),
|
|
181
|
+
/* @__PURE__ */ n("label", { className: "field", htmlFor: "var-value", children: [
|
|
182
|
+
/* @__PURE__ */ e("span", { children: "Value" }),
|
|
183
|
+
i === "boolean" ? /* @__PURE__ */ n("select", { id: "var-value", value: o || "true", onChange: (l) => u(l.target.value), children: [
|
|
184
|
+
/* @__PURE__ */ e("option", { value: "true", children: "true" }),
|
|
185
|
+
/* @__PURE__ */ e("option", { value: "false", children: "false" })
|
|
186
|
+
] }) : i === "number" ? /* @__PURE__ */ e(
|
|
187
|
+
"input",
|
|
188
|
+
{
|
|
189
|
+
id: "var-value",
|
|
190
|
+
type: "number",
|
|
191
|
+
value: o,
|
|
192
|
+
onChange: (l) => u(l.target.value),
|
|
193
|
+
placeholder: "0",
|
|
194
|
+
...r
|
|
195
|
+
}
|
|
196
|
+
) : i === "json" ? /* @__PURE__ */ e(
|
|
197
|
+
"textarea",
|
|
198
|
+
{
|
|
199
|
+
id: "var-value",
|
|
200
|
+
className: "code",
|
|
201
|
+
rows: 6,
|
|
202
|
+
value: o,
|
|
203
|
+
onChange: (l) => u(l.target.value),
|
|
204
|
+
placeholder: '{"key": "value"}'
|
|
205
|
+
}
|
|
206
|
+
) : /* @__PURE__ */ e(
|
|
207
|
+
"input",
|
|
208
|
+
{
|
|
209
|
+
id: "var-value",
|
|
210
|
+
type: "text",
|
|
211
|
+
value: o,
|
|
212
|
+
onChange: (l) => u(l.target.value),
|
|
213
|
+
placeholder: "",
|
|
214
|
+
...r
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
] }),
|
|
218
|
+
/* @__PURE__ */ n("label", { className: "field", children: [
|
|
219
|
+
/* @__PURE__ */ e("span", { children: "Description" }),
|
|
220
|
+
/* @__PURE__ */ e(
|
|
221
|
+
"input",
|
|
222
|
+
{
|
|
223
|
+
type: "text",
|
|
224
|
+
value: g,
|
|
225
|
+
onChange: (l) => p(l.target.value),
|
|
226
|
+
placeholder: "Optional",
|
|
227
|
+
...r
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
] }),
|
|
231
|
+
m && /* @__PURE__ */ e("div", { className: "result error", children: m })
|
|
232
|
+
] }),
|
|
233
|
+
/* @__PURE__ */ n("div", { className: "modal-actions", children: [
|
|
234
|
+
/* @__PURE__ */ e("button", { type: "button", className: "btn ghost", onClick: t.onClose, children: "Cancel" }),
|
|
235
|
+
/* @__PURE__ */ e("button", { type: "button", className: "btn", disabled: !s || d, onClick: S, children: d ? "Saving…" : a ? "Save changes" : "Save variable" })
|
|
236
|
+
] })
|
|
237
|
+
]
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
function ne(t) {
|
|
242
|
+
var y, C;
|
|
243
|
+
const a = t.slots, [s, v] = h(null), [i, f] = h(null), o = B(), u = R(), g = () => v({ mode: "create" }), p = (a == null ? void 0 : a.header) === void 0 ? /* @__PURE__ */ n("div", { children: [
|
|
244
|
+
/* @__PURE__ */ e("h3", { children: "Secrets" }),
|
|
245
|
+
/* @__PURE__ */ e("p", { className: "muted small", children: "Secrets addressable by name. Stored encrypted at rest and never returned from the server — to change a secret, overwrite it." })
|
|
246
|
+
] }) : a.header, m = a == null ? void 0 : a.actions, b = m === void 0 ? /* @__PURE__ */ e("button", { type: "button", className: "btn", onClick: g, children: "+ Add secret" }) : typeof m == "function" ? m({ openCreate: g, canCreate: !0 }) : m, N = (a == null ? void 0 : a.empty) === void 0 ? /* @__PURE__ */ e("p", { className: "muted", children: "No secrets yet." }) : a.empty;
|
|
247
|
+
return /* @__PURE__ */ e("div", { className: "w6w-embed-root", children: /* @__PURE__ */ n("section", { className: "section", children: [
|
|
248
|
+
(p != null || b != null) && /* @__PURE__ */ n("div", { className: "section-head", children: [
|
|
249
|
+
p,
|
|
250
|
+
b
|
|
251
|
+
] }),
|
|
252
|
+
/* @__PURE__ */ n("div", { className: "card", children: [
|
|
253
|
+
o.isLoading && /* @__PURE__ */ e("p", { className: "muted", children: "Loading…" }),
|
|
254
|
+
((y = o.data) == null ? void 0 : y.length) === 0 && N,
|
|
255
|
+
/* @__PURE__ */ e("ul", { className: "list", children: (C = o.data) == null ? void 0 : C.map((d) => /* @__PURE__ */ n("li", { children: [
|
|
256
|
+
/* @__PURE__ */ n("div", { className: "list-main", children: [
|
|
257
|
+
/* @__PURE__ */ e("strong", { className: "list-name", title: d.name, children: d.name }),
|
|
258
|
+
" ",
|
|
259
|
+
/* @__PURE__ */ e("code", { className: "muted small", children: "••••••••" }),
|
|
260
|
+
/* @__PURE__ */ n("div", { className: "muted small list-preview", children: [
|
|
261
|
+
d.description && /* @__PURE__ */ n(V, { children: [
|
|
262
|
+
d.description,
|
|
263
|
+
" · "
|
|
264
|
+
] }),
|
|
265
|
+
"updated ",
|
|
266
|
+
new Date(d.updatedAt).toLocaleString()
|
|
267
|
+
] })
|
|
268
|
+
] }),
|
|
269
|
+
/* @__PURE__ */ n("div", { style: { display: "flex", gap: "var(--w6w-sp-1-5)" }, children: [
|
|
270
|
+
/* @__PURE__ */ e(
|
|
271
|
+
L,
|
|
272
|
+
{
|
|
273
|
+
label: "Rotate",
|
|
274
|
+
onClick: () => v({ mode: "edit", s: d }),
|
|
275
|
+
"data-testid": `secret-rotate-${d.id}`
|
|
276
|
+
}
|
|
277
|
+
),
|
|
278
|
+
/* @__PURE__ */ e(
|
|
279
|
+
j,
|
|
280
|
+
{
|
|
281
|
+
label: "Delete",
|
|
282
|
+
onClick: () => f(d),
|
|
283
|
+
disabled: u.isPending,
|
|
284
|
+
"data-testid": `secret-delete-${d.id}`
|
|
285
|
+
}
|
|
286
|
+
)
|
|
287
|
+
] })
|
|
288
|
+
] }, d.id)) })
|
|
289
|
+
] }),
|
|
290
|
+
s && /* @__PURE__ */ e(
|
|
291
|
+
z,
|
|
292
|
+
{
|
|
293
|
+
initial: s.mode === "edit" ? s.s : void 0,
|
|
294
|
+
onClose: () => v(null),
|
|
295
|
+
onSaved: () => v(null)
|
|
296
|
+
}
|
|
297
|
+
),
|
|
298
|
+
i && /* @__PURE__ */ e(
|
|
299
|
+
$,
|
|
300
|
+
{
|
|
301
|
+
title: "Delete secret",
|
|
302
|
+
message: `Delete the secret "${i.name}"? This cannot be undone.`,
|
|
303
|
+
confirmLabel: "Delete",
|
|
304
|
+
onConfirm: () => {
|
|
305
|
+
u.mutate(i.id), f(null);
|
|
306
|
+
},
|
|
307
|
+
onClose: () => f(null)
|
|
308
|
+
}
|
|
309
|
+
)
|
|
310
|
+
] }) });
|
|
311
|
+
}
|
|
312
|
+
function z(t) {
|
|
313
|
+
var S, r, k;
|
|
314
|
+
const a = !!t.initial, [s, v] = h(((S = t.initial) == null ? void 0 : S.name) ?? ""), [i, f] = h(""), [o, u] = h(((r = t.initial) == null ? void 0 : r.description) ?? ""), [g, p] = h(null), m = I(), b = W(((k = t.initial) == null ? void 0 : k.id) ?? ""), N = a ? b : m, y = !!s && (a || !!i) && !N.isPending;
|
|
315
|
+
function C() {
|
|
316
|
+
if (p(null), a) {
|
|
317
|
+
b.mutate(
|
|
318
|
+
{ value: i === "" ? void 0 : i, description: o },
|
|
319
|
+
{
|
|
320
|
+
onSuccess: () => t.onSaved(),
|
|
321
|
+
onError: (c) => p((c instanceof x, c.message))
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (i === "") {
|
|
327
|
+
p("A secret value is required.");
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
m.mutate(
|
|
331
|
+
{ name: s, value: i, description: o },
|
|
332
|
+
{
|
|
333
|
+
onSuccess: () => t.onSaved(),
|
|
334
|
+
onError: (c) => p((c instanceof x, c.message))
|
|
335
|
+
}
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
const d = P(C, { enabled: y });
|
|
339
|
+
return /* @__PURE__ */ n(
|
|
340
|
+
O,
|
|
341
|
+
{
|
|
342
|
+
title: t.initial ? `Rotate ${t.initial.name}` : "Add secret",
|
|
343
|
+
onClose: t.onClose,
|
|
344
|
+
children: [
|
|
345
|
+
/* @__PURE__ */ n("div", { className: "modal-body", children: [
|
|
346
|
+
/* @__PURE__ */ n("label", { className: "field", children: [
|
|
347
|
+
/* @__PURE__ */ e("span", { children: "Name" }),
|
|
348
|
+
/* @__PURE__ */ e(
|
|
349
|
+
"input",
|
|
350
|
+
{
|
|
351
|
+
type: "text",
|
|
352
|
+
value: s,
|
|
353
|
+
disabled: a,
|
|
354
|
+
onChange: (c) => v(c.target.value),
|
|
355
|
+
placeholder: "e.g. openai_api_key",
|
|
356
|
+
maxLength: 64,
|
|
357
|
+
...d
|
|
358
|
+
}
|
|
359
|
+
),
|
|
360
|
+
!a && /* @__PURE__ */ e("span", { className: "hint", children: "Lowercase letters, digits, and underscores. Must start with a letter or underscore." })
|
|
361
|
+
] }),
|
|
362
|
+
/* @__PURE__ */ n("label", { className: "field", children: [
|
|
363
|
+
/* @__PURE__ */ e("span", { children: a ? "New value" : "Value" }),
|
|
364
|
+
/* @__PURE__ */ e(
|
|
365
|
+
"textarea",
|
|
366
|
+
{
|
|
367
|
+
className: "code",
|
|
368
|
+
rows: 3,
|
|
369
|
+
value: i,
|
|
370
|
+
onChange: (c) => f(c.target.value),
|
|
371
|
+
placeholder: a ? "Leave blank to keep the current value" : "sk-…",
|
|
372
|
+
autoComplete: "off",
|
|
373
|
+
spellCheck: !1
|
|
374
|
+
}
|
|
375
|
+
),
|
|
376
|
+
/* @__PURE__ */ e("span", { className: "hint", children: "Stored encrypted at rest. Once saved, it is not readable through the UI." })
|
|
377
|
+
] }),
|
|
378
|
+
/* @__PURE__ */ n("label", { className: "field", children: [
|
|
379
|
+
/* @__PURE__ */ e("span", { children: "Description" }),
|
|
380
|
+
/* @__PURE__ */ e(
|
|
381
|
+
"input",
|
|
382
|
+
{
|
|
383
|
+
type: "text",
|
|
384
|
+
value: o,
|
|
385
|
+
onChange: (c) => u(c.target.value),
|
|
386
|
+
placeholder: "Optional",
|
|
387
|
+
...d
|
|
388
|
+
}
|
|
389
|
+
)
|
|
390
|
+
] }),
|
|
391
|
+
g && /* @__PURE__ */ e("div", { className: "result error", children: g })
|
|
392
|
+
] }),
|
|
393
|
+
/* @__PURE__ */ n("div", { className: "modal-actions", children: [
|
|
394
|
+
/* @__PURE__ */ e("button", { type: "button", className: "btn ghost", onClick: t.onClose, children: "Cancel" }),
|
|
395
|
+
/* @__PURE__ */ e("button", { type: "button", className: "btn", disabled: !y, onClick: C, children: N.isPending ? "Saving…" : a ? "Save changes" : "Save secret" })
|
|
396
|
+
] })
|
|
397
|
+
]
|
|
398
|
+
}
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
export {
|
|
402
|
+
re as CreateEndpointModal,
|
|
403
|
+
se as CreateFunctionModal,
|
|
404
|
+
ne as SecretsManager,
|
|
405
|
+
ae as VarsManager
|
|
406
|
+
};
|
|
407
|
+
//# sourceMappingURL=forms.mjs.map
|