@w6w/embed 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/README.md +231 -4
  2. package/dist/ConfirmModal-RLbZT5_k.js +181 -0
  3. package/dist/ConfirmModal-RLbZT5_k.js.map +1 -0
  4. package/dist/CreateFunctionModal-DRsFx-FB.js +221 -0
  5. package/dist/CreateFunctionModal-DRsFx-FB.js.map +1 -0
  6. package/dist/DocumentFormModal-BExK1V-B.js +89 -0
  7. package/dist/DocumentFormModal-BExK1V-B.js.map +1 -0
  8. package/dist/ImportSpecModal-BDQIf6rg.js +136 -0
  9. package/dist/ImportSpecModal-BDQIf6rg.js.map +1 -0
  10. package/dist/W6WEmbedProvider.d.ts +22 -4
  11. package/dist/WorkflowEditor-DlbVv6Fs.js +854 -0
  12. package/dist/WorkflowEditor-DlbVv6Fs.js.map +1 -0
  13. package/dist/api-calls--JHyif6a.js +107 -0
  14. package/dist/api-calls--JHyif6a.js.map +1 -0
  15. package/dist/apps-1FNUwbGv.js +77 -0
  16. package/dist/apps-1FNUwbGv.js.map +1 -0
  17. package/dist/callables-3mFrMVG_.js +151 -0
  18. package/dist/callables-3mFrMVG_.js.map +1 -0
  19. package/dist/chrome/index.d.ts +6 -0
  20. package/dist/chrome/workspace.d.ts +29 -1
  21. package/dist/coerce-input-BicYr7nc.js +139 -0
  22. package/dist/coerce-input-BicYr7nc.js.map +1 -0
  23. package/dist/connections-CjjYeRqb.js +78 -0
  24. package/dist/connections-CjjYeRqb.js.map +1 -0
  25. package/dist/document-sources-C0grrtdq.js +86 -0
  26. package/dist/document-sources-C0grrtdq.js.map +1 -0
  27. package/dist/draft/index.d.ts +3 -1
  28. package/dist/draft/use-callable-draft.d.ts +65 -0
  29. package/dist/draft/workflow-save.d.ts +3 -0
  30. package/dist/draft.mjs +9 -5
  31. package/dist/draft.mjs.map +1 -1
  32. package/dist/editor/CallableEditorFrame.d.ts +33 -0
  33. package/dist/editor/EditorShell.d.ts +16 -0
  34. package/dist/editor/EndpointCards.d.ts +56 -0
  35. package/dist/editor/EndpointEditor.d.ts +26 -0
  36. package/dist/editor/FunctionEditor.d.ts +21 -0
  37. package/dist/editor/InputListEditor.d.ts +29 -0
  38. package/dist/editor/TargetSelector.d.ts +30 -0
  39. package/dist/editor/TargetSelector.types.d.ts +62 -0
  40. package/dist/editor/editor-apps.d.ts +8 -2
  41. package/dist/editor/types.d.ts +57 -0
  42. package/dist/editor-apps-BdenSV1o.js +95 -0
  43. package/dist/editor-apps-BdenSV1o.js.map +1 -0
  44. package/dist/editor-tools-RxmY5iyi.js +1279 -0
  45. package/dist/editor-tools-RxmY5iyi.js.map +1 -0
  46. package/dist/editor.mjs +2 -2166
  47. package/dist/editor.mjs.map +1 -1
  48. package/dist/editors/DocumentEditor.d.ts +20 -0
  49. package/dist/editors/doc-format.d.ts +3 -0
  50. package/dist/editors.d.ts +12 -0
  51. package/dist/editors.mjs +1313 -0
  52. package/dist/editors.mjs.map +1 -0
  53. package/dist/embed-status.d.ts +20 -0
  54. package/dist/endpoints-B2ynbZo-.js +227 -0
  55. package/dist/endpoints-B2ynbZo-.js.map +1 -0
  56. package/dist/forms/CreateEndpointModal.d.ts +54 -0
  57. package/dist/forms/CreateFunctionModal.d.ts +55 -0
  58. package/dist/forms/DocumentFormModal.d.ts +8 -0
  59. package/dist/forms/SecretsManager.d.ts +12 -0
  60. package/dist/forms/VarsManager.d.ts +29 -0
  61. package/dist/forms.d.ts +6 -0
  62. package/dist/forms.mjs +407 -0
  63. package/dist/forms.mjs.map +1 -0
  64. package/dist/index.d.ts +3 -1
  65. package/dist/index.mjs +153 -50
  66. package/dist/index.mjs.map +1 -1
  67. package/dist/lib/callable-record.d.ts +21 -0
  68. package/dist/lib/coerce-input.d.ts +6 -0
  69. package/dist/lib/endpoint-editor.d.ts +23 -0
  70. package/dist/lib/index.d.ts +7 -0
  71. package/dist/lib/input-coverage.d.ts +28 -0
  72. package/dist/lib/input-seeding.d.ts +67 -0
  73. package/dist/lib/rail-settings.d.ts +3 -3
  74. package/dist/lib/recent-activity.d.ts +128 -0
  75. package/dist/lib/target-fields.d.ts +168 -0
  76. package/dist/lib/workflow-blank.d.ts +2 -0
  77. package/dist/lib.mjs +70 -48
  78. package/dist/lib.mjs.map +1 -1
  79. package/dist/lists/ActivitySummary.d.ts +29 -0
  80. package/dist/lists/CallableKindList.d.ts +34 -0
  81. package/dist/lists/ConnectionDetail.d.ts +17 -0
  82. package/dist/lists/ConnectionList.d.ts +16 -0
  83. package/dist/lists/DocumentList.d.ts +29 -0
  84. package/dist/lists/EndpointList.d.ts +19 -0
  85. package/dist/lists/FunctionList.d.ts +18 -0
  86. package/dist/lists/ReliabilityBoard.d.ts +23 -0
  87. package/dist/lists/RunHistory.d.ts +11 -0
  88. package/dist/lists/ServiceDetail.d.ts +20 -0
  89. package/dist/lists/WorkflowList.d.ts +19 -0
  90. package/dist/lists/vendor-history.d.ts +40 -0
  91. package/dist/lists.d.ts +20 -0
  92. package/dist/lists.mjs +1185 -0
  93. package/dist/lists.mjs.map +1 -0
  94. package/dist/project-context-BiCjv_E3.js +25 -0
  95. package/dist/project-context-BiCjv_E3.js.map +1 -0
  96. package/dist/project-context.d.ts +15 -1
  97. package/dist/rail/CallableRail.d.ts +12 -0
  98. package/dist/rail/CallableWorkspace.d.ts +16 -0
  99. package/dist/rail/SettingsTool.d.ts +7 -1
  100. package/dist/rail/settings-sections.d.ts +2 -2
  101. package/dist/rail-settings-XYGToh00.js +111 -0
  102. package/dist/rail-settings-XYGToh00.js.map +1 -0
  103. package/dist/rail.d.ts +11 -0
  104. package/dist/rail.mjs +35 -0
  105. package/dist/rail.mjs.map +1 -0
  106. package/dist/repos/api-calls.d.ts +4 -0
  107. package/dist/repos/apps.d.ts +14 -0
  108. package/dist/repos/callables.d.ts +91 -0
  109. package/dist/repos/connections.d.ts +33 -0
  110. package/dist/repos/dashboard.d.ts +4 -0
  111. package/dist/repos/endpoints.d.ts +125 -0
  112. package/dist/repos/functions.d.ts +79 -0
  113. package/dist/repos/index.d.ts +10 -0
  114. package/dist/repos/reliability.d.ts +42 -0
  115. package/dist/repos/saved-tests.d.ts +46 -0
  116. package/dist/repos/spec-export.d.ts +23 -0
  117. package/dist/repos/workflows.d.ts +138 -0
  118. package/dist/repos.mjs +174 -88
  119. package/dist/repos.mjs.map +1 -1
  120. package/dist/settings-rail--GdRMusb.js +33 -0
  121. package/dist/settings-rail--GdRMusb.js.map +1 -0
  122. package/dist/slug-C4ktDPdy.js +315 -0
  123. package/dist/slug-C4ktDPdy.js.map +1 -0
  124. package/dist/spec-export-Cf3VQSQS.js +176 -0
  125. package/dist/spec-export-Cf3VQSQS.js.map +1 -0
  126. package/dist/spec-import-CjmxyZDR.js +465 -0
  127. package/dist/spec-import-CjmxyZDR.js.map +1 -0
  128. package/dist/step-tests-CivICmTq.js +18 -0
  129. package/dist/step-tests-CivICmTq.js.map +1 -0
  130. package/dist/trigger-preview-VPkrryDl.js +120 -0
  131. package/dist/trigger-preview-VPkrryDl.js.map +1 -0
  132. package/dist/use-callable-draft-zHLpcr-b.js +271 -0
  133. package/dist/use-callable-draft-zHLpcr-b.js.map +1 -0
  134. package/dist/{use-workflow-draft-oI02dsP-.js → use-workflow-draft-DzAyUeA6.js} +48 -46
  135. package/dist/use-workflow-draft-DzAyUeA6.js.map +1 -0
  136. package/dist/vault-BSEWhMYC.js +117 -0
  137. package/dist/vault-BSEWhMYC.js.map +1 -0
  138. package/dist/workflow-blank-DyL3_RUA.js +14 -0
  139. package/dist/workflow-blank-DyL3_RUA.js.map +1 -0
  140. package/package.json +21 -5
  141. package/src/styles.css +408 -1
  142. package/dist/project-context-Dbk0Gr1K.js +0 -16
  143. package/dist/project-context-Dbk0Gr1K.js.map +0 -1
  144. package/dist/slug-ByKQgxrf.js +0 -642
  145. package/dist/slug-ByKQgxrf.js.map +0 -1
  146. package/dist/spec-import-HgO7ZkLZ.js +0 -898
  147. package/dist/spec-import-HgO7ZkLZ.js.map +0 -1
  148. package/dist/use-workflow-draft-oI02dsP-.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forms.mjs","sources":["../src/forms/VarsManager.tsx","../src/forms/SecretsManager.tsx"],"sourcesContent":["/**\n * `<VarsManager>` — list, add, edit and delete the project's variables. Variables are\n * plaintext typed values scoped to ONE project (secrets, by contrast, are per account — see\n * `SecretsManager`).\n *\n * The project comes from `useEditorProject(project)`: omitted defers to `<W6WEmbedProvider\n * project>`; `null` or `\"\"` REFUSES — the list query is disabled, no `/vars` request is sent and\n * \"Add\" is disabled. Every list/create/update/delete call names the resolved project, never\n * `undefined` (a project-less write lands in the account default project).\n */\nimport { ApiError } from \"@w6w/sdk\";\nimport type { Var, VarType } from \"@w6w/sdk\";\nimport { Copyable, DeleteButton, EditButton, useEnterSubmit } from \"@w6w/ui\";\nimport { type ReactNode, useState } from \"react\";\nimport { CallFromCodeButton } from \"../chrome/CallFromCodeButton.tsx\";\nimport { ConfirmModal } from \"../chrome/ConfirmModal.tsx\";\nimport { Modal } from \"../chrome/Modal.tsx\";\nimport { useEditorProject } from \"../project-context.ts\";\nimport {\n useCreateVarMutation,\n useDeleteVarMutation,\n useUpdateVarMutation,\n useVarsQuery,\n} from \"../repos/vars.ts\";\n\nconst TYPES: readonly VarType[] = [\"string\", \"number\", \"boolean\", \"json\"];\n\n/** What a function-form `actions` slot receives. */\nexport interface ConfigManagerActionsApi {\n /** Open the create form (a no-op while the manager is refusing, e.g. no project). */\n openCreate: () => void;\n /** `false` when the create control must be disabled (no project). */\n canCreate: boolean;\n}\n\n/**\n * Each slot: omitted ⇒ the built-in default; `null` ⇒ nothing; a node replaces it. `actions` also\n * accepts a function so a host that replaces the default \"+ Add\" button can still open the form.\n */\nexport interface VarsManagerSlots {\n /** The section heading + description. */\n header?: ReactNode;\n /** The trailing control(s) of the head row (the \"+ Add variable\" button). */\n actions?: ReactNode | ((api: ConfigManagerActionsApi) => ReactNode);\n /** Shown instead of the list when there are no variables. */\n empty?: ReactNode;\n}\n\nexport interface VarsManagerProps {\n /**\n * The project whose variables are managed. Omitted: the `<W6WEmbedProvider project>`. `null` or\n * `\"\"`: no project — nothing is requested and nothing can be written.\n */\n project?: string | null;\n slots?: VarsManagerSlots;\n}\n\n/** One-line preview of a var's current value, safe against long strings. */\nfunction previewValue(v: Var): string {\n if (v.type === \"boolean\") return String(v.value);\n if (v.type === \"number\") return String(v.value);\n if (v.type === \"string\") return String(v.value);\n const s = JSON.stringify(v.value);\n return s.length > 80 ? `${s.slice(0, 80)}…` : s;\n}\n\nexport function VarsManager(props: VarsManagerProps): ReactNode {\n const slots = props.slots;\n const project = useEditorProject(props.project);\n const [modal, setModal] = useState<{ mode: \"create\" } | { mode: \"edit\"; v: Var } | null>(null);\n const [pending, setPending] = useState<Var | null>(null);\n\n const varsQuery = useVarsQuery(project ?? undefined, project != null);\n const deleteMut = useDeleteVarMutation();\n const canCreate = project != null;\n const openCreate = () => {\n if (project != null) setModal({ mode: \"create\" });\n };\n\n const header =\n slots?.header === undefined ? (\n <div>\n <h3>Variables</h3>\n <p className=\"muted small\">\n User-defined typed values addressable by name. Plaintext — use <strong>Secrets</strong>{\" \"}\n for sensitive values.\n </p>\n </div>\n ) : (\n slots.header\n );\n const actionsSlot = slots?.actions;\n const actions =\n actionsSlot === undefined ? (\n <button type=\"button\" className=\"btn\" disabled={!canCreate} onClick={openCreate}>\n + Add variable\n </button>\n ) : typeof actionsSlot === \"function\" ? (\n actionsSlot({ openCreate, canCreate })\n ) : (\n actionsSlot\n );\n const empty =\n slots?.empty === undefined ? <p className=\"muted\">No variables yet.</p> : slots.empty;\n\n return (\n <div className=\"w6w-embed-root\">\n <section className=\"section\">\n {(header != null || actions != null) && (\n <div className=\"section-head\">\n {header}\n {actions}\n </div>\n )}\n\n <div className=\"card\">\n {varsQuery.isLoading && <p className=\"muted\">Loading…</p>}\n {varsQuery.data?.length === 0 && empty}\n <ul className=\"list\">\n {varsQuery.data?.map((v) => (\n <li key={v.id}>\n <div className=\"list-main\">\n <strong className=\"list-name\" title={v.name}>\n {v.name}\n </strong>{\" \"}\n <span className=\"tag\">{v.type}</span>\n <div className=\"muted small list-preview\" title={previewValue(v)}>\n <Copyable value={previewValue(v)} readOnly>\n {/* `.w6w-copyable`'s flex rule only targets `> input, > textarea, > pre` —\n never `> code` — so this `<code>` keeps flexbox's automatic min-content\n floor unless told otherwise. `overflowWrap: \"anywhere\"` alone still\n leaves the content unshrunk, pushing the Copy button outside\n `.list-preview`'s clipped box at narrow widths. `minWidth: 0` lets the\n flex item shrink to the box; `overflow`/`textOverflow` give IT the\n ellipsis, restoring the single-line truncation `.list-preview` set up. */}\n <code\n style={{\n overflowWrap: \"anywhere\",\n display: \"block\",\n minWidth: 0,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n flex: 1,\n }}\n >\n {previewValue(v)}\n </code>\n </Copyable>\n {v.description && <> · {v.description}</>}\n </div>\n </div>\n <div style={{ display: \"flex\", gap: \"var(--w6w-sp-1-5)\" }}>\n <CallFromCodeButton resource={{ kind: \"var\", name: v.name }} />\n <EditButton\n label=\"Edit\"\n onClick={() => setModal({ mode: \"edit\", v })}\n data-testid={`var-edit-${v.id}`}\n />\n <DeleteButton\n label=\"Delete\"\n onClick={() => setPending(v)}\n disabled={deleteMut.isPending}\n data-testid={`var-delete-${v.id}`}\n />\n </div>\n </li>\n ))}\n </ul>\n </div>\n\n {modal && project != null && (\n <VarModal\n project={project}\n initial={modal.mode === \"edit\" ? modal.v : undefined}\n onClose={() => setModal(null)}\n onSaved={() => setModal(null)}\n />\n )}\n\n {pending && project != null && (\n <ConfirmModal\n title=\"Delete variable\"\n message={`Delete the variable \"${pending.name}\"? This cannot be undone.`}\n confirmLabel=\"Delete\"\n onConfirm={() => {\n deleteMut.mutate({ id: pending.id, project });\n setPending(null);\n }}\n onClose={() => setPending(null)}\n />\n )}\n </section>\n </div>\n );\n}\n\n/**\n * Create/edit modal. The value widget switches on `type`; the raw string in the form is parsed to\n * the declared type at submit time so what's stored round-trips faithfully (e.g. the number `42`,\n * not the string `\"42\"`).\n */\nfunction VarModal(props: {\n project: string;\n initial?: Var;\n onClose: () => void;\n onSaved: () => void;\n}) {\n const isEdit = !!props.initial;\n const [name, setName] = useState(props.initial?.name ?? \"\");\n const [type, setType] = useState<VarType>(props.initial?.type ?? \"string\");\n const [raw, setRaw] = useState<string>(() => {\n if (!props.initial) return \"\";\n if (props.initial.type === \"string\") return String(props.initial.value ?? \"\");\n return JSON.stringify(props.initial.value, null, 2);\n });\n const [description, setDescription] = useState(props.initial?.description ?? \"\");\n const [error, setError] = useState<string | null>(null);\n\n /** Parse the raw string into a value that matches `type`. */\n function parseValue(): { ok: true; value: unknown } | { ok: false; error: string } {\n if (type === \"string\") return { ok: true, value: raw };\n if (type === \"boolean\") {\n if (raw === \"true\") return { ok: true, value: true };\n if (raw === \"false\") return { ok: true, value: false };\n return { ok: false, error: \"Value must be `true` or `false`.\" };\n }\n if (type === \"number\") {\n const n = Number(raw);\n if (!Number.isFinite(n)) return { ok: false, error: \"Value must be a finite number.\" };\n return { ok: true, value: n };\n }\n // json\n try {\n return { ok: true, value: JSON.parse(raw) };\n } catch (e) {\n return { ok: false, error: `Invalid JSON: ${(e as Error).message}` };\n }\n }\n\n const createMut = useCreateVarMutation();\n const updateMut = useUpdateVarMutation();\n const saving = createMut.isPending || updateMut.isPending;\n\n function save() {\n const parsed = parseValue();\n if (!parsed.ok) {\n setError(parsed.error);\n return;\n }\n setError(null);\n const onSettled = {\n onSuccess: () => props.onSaved(),\n onError: (e: unknown) => setError(e instanceof ApiError ? e.message : (e as Error).message),\n };\n if (props.initial) {\n updateMut.mutate(\n {\n id: props.initial.id,\n patch: { type, value: parsed.value, description },\n project: props.project,\n },\n onSettled,\n );\n return;\n }\n createMut.mutate(\n { input: { name, type, value: parsed.value, description }, project: props.project },\n onSettled,\n );\n }\n\n const enterSubmit = useEnterSubmit(save, { enabled: !!name && !saving });\n\n return (\n <Modal\n title={props.initial ? `Edit ${props.initial.name}` : \"Add variable\"}\n onClose={props.onClose}\n >\n <div className=\"modal-body\">\n <label className=\"field\">\n <span>Name</span>\n <input\n type=\"text\"\n value={name}\n disabled={isEdit}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. api_base_url\"\n maxLength={64}\n {...enterSubmit}\n />\n {!isEdit && (\n <span className=\"hint\">\n Lowercase letters, digits, and underscores. Must start with a letter or underscore.\n </span>\n )}\n </label>\n\n <label className=\"field\">\n <span>Type</span>\n <select value={type} onChange={(e) => setType(e.target.value as VarType)}>\n {TYPES.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n </label>\n\n <label className=\"field\" htmlFor=\"var-value\">\n <span>Value</span>\n {type === \"boolean\" ? (\n <select id=\"var-value\" value={raw || \"true\"} onChange={(e) => setRaw(e.target.value)}>\n <option value=\"true\">true</option>\n <option value=\"false\">false</option>\n </select>\n ) : type === \"number\" ? (\n <input\n id=\"var-value\"\n type=\"number\"\n value={raw}\n onChange={(e) => setRaw(e.target.value)}\n placeholder=\"0\"\n {...enterSubmit}\n />\n ) : type === \"json\" ? (\n <textarea\n id=\"var-value\"\n className=\"code\"\n rows={6}\n value={raw}\n onChange={(e) => setRaw(e.target.value)}\n placeholder='{\"key\": \"value\"}'\n />\n ) : (\n <input\n id=\"var-value\"\n type=\"text\"\n value={raw}\n onChange={(e) => setRaw(e.target.value)}\n placeholder=\"\"\n {...enterSubmit}\n />\n )}\n </label>\n\n <label className=\"field\">\n <span>Description</span>\n <input\n type=\"text\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Optional\"\n {...enterSubmit}\n />\n </label>\n\n {error && <div className=\"result error\">{error}</div>}\n </div>\n <div className=\"modal-actions\">\n <button type=\"button\" className=\"btn ghost\" onClick={props.onClose}>\n Cancel\n </button>\n <button type=\"button\" className=\"btn\" disabled={!name || saving} onClick={save}>\n {saving ? \"Saving…\" : isEdit ? \"Save changes\" : \"Save variable\"}\n </button>\n </div>\n </Modal>\n );\n}\n","/**\n * `<SecretsManager>` — list, add, rotate and delete the account's secrets (vault). Secrets are\n * per ACCOUNT, not per project (variables are per project — see `VarsManager`), so there is no\n * `project` prop.\n *\n * WRITE-ONLY. A secret's value is typed into a form and sent; it is never read back. The value\n * field starts empty in create and in rotate; a blank rotate sends no `value` key; a blank create\n * is refused before any request; rows render only `name`, `description`, `updatedAt` and a fixed\n * mask — a row object is never spread or stringified, so a server that wrongly returns `value`\n * cannot reach the DOM. No prop receives, and no callback is handed, a secret value, and nothing\n * here writes the `[\"secrets\"]` cache (only the repo's own invalidation).\n */\nimport { ApiError } from \"@w6w/sdk\";\nimport { DeleteButton, EditButton, useEnterSubmit } from \"@w6w/ui\";\nimport { type ReactNode, useState } from \"react\";\nimport { ConfirmModal } from \"../chrome/ConfirmModal.tsx\";\nimport { Modal } from \"../chrome/Modal.tsx\";\nimport {\n type VaultSecretSummary,\n useCreateSecretMutation,\n useDeleteSecretMutation,\n useSecretsQuery,\n useUpdateSecretMutation,\n} from \"../repos/vault.ts\";\nimport type { ConfigManagerActionsApi } from \"./VarsManager.tsx\";\n\n/** Same contract as `VarsManagerSlots`: omitted ⇒ default, `null` ⇒ nothing, a node replaces. */\nexport interface SecretsManagerSlots {\n header?: ReactNode;\n actions?: ReactNode | ((api: ConfigManagerActionsApi) => ReactNode);\n empty?: ReactNode;\n}\n\nexport interface SecretsManagerProps {\n slots?: SecretsManagerSlots;\n}\n\nexport function SecretsManager(props: SecretsManagerProps): ReactNode {\n const slots = props.slots;\n const [modal, setModal] = useState<\n { mode: \"create\" } | { mode: \"edit\"; s: VaultSecretSummary } | null\n >(null);\n const [pending, setPending] = useState<VaultSecretSummary | null>(null);\n\n const secretsQuery = useSecretsQuery();\n const deleteMut = useDeleteSecretMutation();\n const openCreate = () => setModal({ mode: \"create\" });\n\n const header =\n slots?.header === undefined ? (\n <div>\n <h3>Secrets</h3>\n <p className=\"muted small\">\n Secrets addressable by name. Stored encrypted at rest and never returned from the server —\n to change a secret, overwrite it.\n </p>\n </div>\n ) : (\n slots.header\n );\n const actionsSlot = slots?.actions;\n const actions =\n actionsSlot === undefined ? (\n <button type=\"button\" className=\"btn\" onClick={openCreate}>\n + Add secret\n </button>\n ) : typeof actionsSlot === \"function\" ? (\n actionsSlot({ openCreate, canCreate: true })\n ) : (\n actionsSlot\n );\n const empty = slots?.empty === undefined ? <p className=\"muted\">No secrets yet.</p> : slots.empty;\n\n return (\n <div className=\"w6w-embed-root\">\n <section className=\"section\">\n {(header != null || actions != null) && (\n <div className=\"section-head\">\n {header}\n {actions}\n </div>\n )}\n\n <div className=\"card\">\n {secretsQuery.isLoading && <p className=\"muted\">Loading…</p>}\n {secretsQuery.data?.length === 0 && empty}\n <ul className=\"list\">\n {secretsQuery.data?.map((s) => (\n <li key={s.id}>\n <div className=\"list-main\">\n <strong className=\"list-name\" title={s.name}>\n {s.name}\n </strong>{\" \"}\n <code className=\"muted small\">••••••••</code>\n <div className=\"muted small list-preview\">\n {s.description && <>{s.description} · </>}\n updated {new Date(s.updatedAt).toLocaleString()}\n </div>\n </div>\n <div style={{ display: \"flex\", gap: \"var(--w6w-sp-1-5)\" }}>\n <EditButton\n label=\"Rotate\"\n onClick={() => setModal({ mode: \"edit\", s })}\n data-testid={`secret-rotate-${s.id}`}\n />\n <DeleteButton\n label=\"Delete\"\n onClick={() => setPending(s)}\n disabled={deleteMut.isPending}\n data-testid={`secret-delete-${s.id}`}\n />\n </div>\n </li>\n ))}\n </ul>\n </div>\n\n {modal && (\n <SecretModal\n initial={modal.mode === \"edit\" ? modal.s : undefined}\n onClose={() => setModal(null)}\n onSaved={() => setModal(null)}\n />\n )}\n\n {pending && (\n <ConfirmModal\n title=\"Delete secret\"\n message={`Delete the secret \"${pending.name}\"? This cannot be undone.`}\n confirmLabel=\"Delete\"\n onConfirm={() => {\n deleteMut.mutate(pending.id);\n setPending(null);\n }}\n onClose={() => setPending(null)}\n />\n )}\n </section>\n </div>\n );\n}\n\n/**\n * Create/rotate a secret. On edit, the current value is intentionally not pre-filled — the server\n * never returns it. Leaving the value blank in edit mode updates only the description.\n */\nfunction SecretModal(props: {\n initial?: VaultSecretSummary;\n onClose: () => void;\n onSaved: () => void;\n}) {\n const isEdit = !!props.initial;\n const [name, setName] = useState(props.initial?.name ?? \"\");\n const [value, setValue] = useState(\"\");\n const [description, setDescription] = useState(props.initial?.description ?? \"\");\n const [error, setError] = useState<string | null>(null);\n\n const createMut = useCreateSecretMutation();\n const updateMut = useUpdateSecretMutation(props.initial?.id ?? \"\");\n const saveMut = isEdit ? updateMut : createMut;\n const canSave = !!name && (isEdit || !!value) && !saveMut.isPending;\n\n function handleSave() {\n setError(null);\n if (isEdit) {\n updateMut.mutate(\n { value: value === \"\" ? undefined : value, description },\n {\n onSuccess: () => props.onSaved(),\n onError: (e) => setError(e instanceof ApiError ? e.message : (e as Error).message),\n },\n );\n return;\n }\n if (value === \"\") {\n setError(\"A secret value is required.\");\n return;\n }\n createMut.mutate(\n { name, value, description },\n {\n onSuccess: () => props.onSaved(),\n onError: (e) => setError(e instanceof ApiError ? e.message : (e as Error).message),\n },\n );\n }\n const enterSubmit = useEnterSubmit(handleSave, { enabled: canSave });\n\n return (\n <Modal\n title={props.initial ? `Rotate ${props.initial.name}` : \"Add secret\"}\n onClose={props.onClose}\n >\n <div className=\"modal-body\">\n <label className=\"field\">\n <span>Name</span>\n <input\n type=\"text\"\n value={name}\n disabled={isEdit}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. openai_api_key\"\n maxLength={64}\n {...enterSubmit}\n />\n {!isEdit && (\n <span className=\"hint\">\n Lowercase letters, digits, and underscores. Must start with a letter or underscore.\n </span>\n )}\n </label>\n\n <label className=\"field\">\n <span>{isEdit ? \"New value\" : \"Value\"}</span>\n <textarea\n className=\"code\"\n rows={3}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n placeholder={isEdit ? \"Leave blank to keep the current value\" : \"sk-…\"}\n autoComplete=\"off\"\n spellCheck={false}\n />\n <span className=\"hint\">\n Stored encrypted at rest. Once saved, it is not readable through the UI.\n </span>\n </label>\n\n <label className=\"field\">\n <span>Description</span>\n <input\n type=\"text\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Optional\"\n {...enterSubmit}\n />\n </label>\n\n {error && <div className=\"result error\">{error}</div>}\n </div>\n <div className=\"modal-actions\">\n <button type=\"button\" className=\"btn ghost\" onClick={props.onClose}>\n Cancel\n </button>\n <button type=\"button\" className=\"btn\" disabled={!canSave} onClick={handleSave}>\n {saveMut.isPending ? \"Saving…\" : isEdit ? \"Save changes\" : \"Save secret\"}\n </button>\n </div>\n </Modal>\n );\n}\n"],"names":["TYPES","previewValue","v","s","VarsManager","props","slots","project","useEditorProject","modal","setModal","useState","pending","setPending","varsQuery","useVarsQuery","deleteMut","useDeleteVarMutation","canCreate","openCreate","header","jsx","jsxs","actionsSlot","actions","empty","_a","_b","Copyable","Fragment","CallFromCodeButton","EditButton","DeleteButton","VarModal","ConfirmModal","isEdit","name","setName","type","setType","raw","setRaw","description","setDescription","_c","error","setError","parseValue","n","e","createMut","useCreateVarMutation","updateMut","useUpdateVarMutation","saving","save","parsed","onSettled","ApiError","enterSubmit","useEnterSubmit","Modal","t","SecretsManager","secretsQuery","useSecretsQuery","useDeleteSecretMutation","SecretModal","value","setValue","useCreateSecretMutation","useUpdateSecretMutation","saveMut","canSave","handleSave"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1 +1,3 @@
1
- export { W6WEmbedProvider, type W6WEmbedProviderProps } from './W6WEmbedProvider.tsx';
1
+ export { W6WEmbedProvider, type W6WEmbedProviderProps, useEmbedStatus, } from './W6WEmbedProvider.tsx';
2
+ export { EmbedAuthError, type EmbedStatus, type EmbedStatusValue } from './embed-status.ts';
3
+ export { type EmbedProjectState, useEmbedProject } from './project-context.ts';
package/dist/index.mjs CHANGED
@@ -1,67 +1,170 @@
1
1
  "use client";
2
- import { jsx as r } from "react/jsx-runtime";
3
- import { QueryClientProvider as w, QueryClient as R } from "@tanstack/react-query";
4
- import { W6WProvider as j, useW6WClient as h, createW6WUiAdapter as S } from "@w6w/react";
5
- import { W6WUIProvider as U } from "@w6w/ui";
6
- import { useState as u, useRef as y, useEffect as C, useMemo as x } from "react";
7
- import { E as A } from "./client-context-CX61Bgw-.js";
8
- import { c as D, D as Q } from "./draft-registry-YF0tqNN0.js";
9
- import { E as B } from "./project-context-Dbk0Gr1K.js";
10
- function W() {
11
- return new R({
2
+ import { jsx as i, jsxs as G } from "react/jsx-runtime";
3
+ import { QueryClientProvider as M, QueryClient as H, useQuery as J } from "@tanstack/react-query";
4
+ import { W6WProvider as L, useW6WClient as P, useW6WSession as N, createW6WUiAdapter as V } from "@w6w/react";
5
+ import { W6WUIProvider as X } from "@w6w/ui";
6
+ import { useState as h, useRef as k, useEffect as j, useCallback as D, useMemo as C, useContext as Y, createContext as Z } from "react";
7
+ import { E as _ } from "./client-context-CX61Bgw-.js";
8
+ import { c as $, D as ee } from "./draft-registry-YF0tqNN0.js";
9
+ import { E as re } from "./project-context-BiCjv_E3.js";
10
+ import { a as Ee } from "./project-context-BiCjv_E3.js";
11
+ import { u as te } from "./connections-CjjYeRqb.js";
12
+ class ne extends Error {
13
+ constructor(t) {
14
+ super("The w6w API rejected the embed session token (401).", { cause: t }), this.name = "EmbedAuthError";
15
+ }
16
+ }
17
+ function oe(r, t, e) {
18
+ if (e) return { status: "error", error: e };
19
+ switch (r) {
20
+ case "ready":
21
+ case "renewing":
22
+ return { status: "ready", error: null };
23
+ case "error":
24
+ return { status: "error", error: t };
25
+ case "loading":
26
+ case "expired":
27
+ return { status: "connecting", error: null };
28
+ }
29
+ }
30
+ function F() {
31
+ return new H({
12
32
  defaultOptions: { queries: { retry: !1, refetchOnWindowFocus: !1 } }
13
33
  });
14
34
  }
15
- function K({ children: t }) {
16
- return /* @__PURE__ */ r(A, { client: h(), children: t });
35
+ function se({ children: r }) {
36
+ return /* @__PURE__ */ i(_, { client: P(), children: r });
37
+ }
38
+ function ue({ theme: r, children: t }) {
39
+ const e = P(), d = C(() => {
40
+ const n = V(e);
41
+ return typeof n.updateConnection == "function" ? n : { ...n, updateConnection: (c, o) => te(e, c, o) };
42
+ }, [e]);
43
+ return /* @__PURE__ */ i(X, { api: d, theme: r, children: t });
44
+ }
45
+ const U = Z({ status: "connecting", error: null });
46
+ function Ce() {
47
+ return Y(U);
17
48
  }
18
- function O({ theme: t, children: o }) {
19
- const e = h(), s = x(() => S(e), [e]);
20
- return /* @__PURE__ */ r(U, { api: s, theme: t, children: o });
49
+ function ie({
50
+ eager: r,
51
+ authError: t,
52
+ onAcquire: e,
53
+ children: d
54
+ }) {
55
+ const { status: n, error: c, refresh: o } = N();
56
+ j(() => {
57
+ r && o();
58
+ }, [r, o]), j(() => {
59
+ (n === "loading" || n === "renewing") && e();
60
+ }, [n, e]);
61
+ const l = C(
62
+ () => oe(n, c, t),
63
+ [n, c, t]
64
+ );
65
+ return /* @__PURE__ */ i(U.Provider, { value: l, children: d });
66
+ }
67
+ function ce({
68
+ identityKey: r,
69
+ enabled: t,
70
+ onState: e
71
+ }) {
72
+ const d = P(), n = J({
73
+ queryKey: ["w6w-embed", "default-project"],
74
+ enabled: t,
75
+ queryFn: async () => {
76
+ const p = (await d.projects.list()).find((s) => s.isDefault === !0);
77
+ if (!p) throw new Error("The account has no default project.");
78
+ return p.id;
79
+ }
80
+ }), { isError: c, error: o, data: l } = n, w = C(
81
+ () => c ? { project: null, status: "error", error: o } : l !== void 0 ? { project: l, status: "ready" } : { project: null, status: "resolving" },
82
+ [c, o, l]
83
+ );
84
+ return j(() => {
85
+ e(r, w);
86
+ }, [r, w, e]), null;
21
87
  }
22
- function L({
23
- apiOrigin: t,
24
- getSession: o,
88
+ function we({
89
+ apiOrigin: r,
90
+ getSession: t,
25
91
  identityKey: e,
26
- theme: s,
27
- ready: g,
28
- project: f,
29
- fetch: v,
30
- children: P
92
+ fallback: d = null,
93
+ eager: n = !1,
94
+ theme: c,
95
+ ready: o,
96
+ project: l,
97
+ fetch: w,
98
+ children: q
31
99
  }) {
32
- const [c] = u(D), [i, E] = u(() => ({
100
+ const [p] = h($), [s, K] = h(() => ({
33
101
  identityKey: e,
34
- queryClient: W()
35
- })), b = e !== i.identityKey, d = y({ apiOrigin: t, project: f, getSession: o });
36
- b || (d.current = { apiOrigin: t, project: f, getSession: o });
37
- const n = d.current, a = y(n.getSession);
38
- a.current = n.getSession;
39
- const [q] = u(() => () => a.current());
40
- C(() => {
41
- if (e === i.identityKey) return;
42
- let m = !1;
43
- const p = () => {
44
- m || E({ identityKey: e, queryClient: W() });
102
+ queryClient: F()
103
+ })), Q = e !== s.identityKey, x = k({ apiOrigin: r, project: l, getSession: t });
104
+ Q || (x.current = { apiOrigin: r, project: l, getSession: t });
105
+ const b = x.current, A = k(b.getSession);
106
+ A.current = b.getSession;
107
+ const [B] = h(() => () => A.current());
108
+ j(() => {
109
+ if (e === s.identityKey) return;
110
+ let a = !1;
111
+ const u = () => {
112
+ a || K({ identityKey: e, queryClient: F() });
45
113
  };
46
- return c.flushAll().then(p, p), () => {
47
- m = !0;
114
+ return s.identityKey === null ? (u(), () => {
115
+ a = !0;
116
+ }) : (p.flushAll().then(u, u), () => {
117
+ a = !0;
118
+ });
119
+ }, [e, s.identityKey, p]);
120
+ const g = s.queryClient;
121
+ j(() => () => g.clear(), [g]);
122
+ const [E, I] = h(null), O = D((a, u) => {
123
+ I(
124
+ (m) => m && m.key === a && m.state.project === u.project && m.state.status === u.status && m.state.error === u.error ? m : { key: a, state: u }
125
+ );
126
+ }, []), [v, S] = h(null), T = C(() => {
127
+ const a = s.queryClient;
128
+ return (u) => {
129
+ S({ key: a, error: new ne(u) });
48
130
  };
49
- }, [e, i.identityKey, c]);
50
- const l = i.queryClient;
51
- return C(() => () => l.clear(), [l]), /* @__PURE__ */ r(Q, { registry: c, children: /* @__PURE__ */ r(w, { client: l, children: /* @__PURE__ */ r(
52
- j,
131
+ }, [s.queryClient]), z = D(() => S(null), []), y = s.identityKey, f = b.project, W = typeof f == "object" && f !== null && !Array.isArray(f) && f.use === "default", R = C(() => typeof f == "string" ? { project: f, status: "ready" } : W ? E && E.key === y ? E.state : { project: null, status: "resolving" } : { project: null, status: "ready" }, [f, W, E, y]);
132
+ return y === null ? d : /* @__PURE__ */ i(ee, { registry: p, children: /* @__PURE__ */ i(M, { client: g, children: /* @__PURE__ */ G(
133
+ L,
53
134
  {
54
- baseUrl: n.apiOrigin,
55
- getSession: q,
56
- identityKey: i.identityKey,
57
- ready: g,
58
- project: n.project,
59
- fetch: v,
60
- children: /* @__PURE__ */ r(B.Provider, { value: n.project, children: /* @__PURE__ */ r(K, { children: /* @__PURE__ */ r(O, { theme: s, children: P }) }) })
135
+ baseUrl: b.apiOrigin,
136
+ getSession: B,
137
+ identityKey: y,
138
+ ready: o,
139
+ project: R.project ?? void 0,
140
+ fetch: w,
141
+ onUnauthorized: T,
142
+ children: [
143
+ W ? /* @__PURE__ */ i(
144
+ ce,
145
+ {
146
+ identityKey: y,
147
+ enabled: o !== !1,
148
+ onState: O
149
+ }
150
+ ) : null,
151
+ /* @__PURE__ */ i(re.Provider, { value: R, children: /* @__PURE__ */ i(
152
+ ie,
153
+ {
154
+ eager: n,
155
+ authError: v && v.key === g ? v.error : null,
156
+ onAcquire: z,
157
+ children: /* @__PURE__ */ i(se, { children: /* @__PURE__ */ i(ue, { theme: c, children: q }) })
158
+ }
159
+ ) })
160
+ ]
61
161
  }
62
- ) }, i.identityKey) });
162
+ ) }, y) });
63
163
  }
64
164
  export {
65
- L as W6WEmbedProvider
165
+ ne as EmbedAuthError,
166
+ we as W6WEmbedProvider,
167
+ Ee as useEmbedProject,
168
+ Ce as useEmbedStatus
66
169
  };
67
170
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/W6WEmbedProvider.tsx"],"sourcesContent":["import { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\n/**\n * `<W6WEmbedProvider>` — everything an embedded w6w surface needs from a host, behind one\n * element: an identity-scoped `QueryClient`, a `@w6w/react` `<W6WProvider>` (client, session\n * renewal, per-request token) and `@w6w/ui`'s `<W6WUIProvider>` fed by `createW6WUiAdapter`.\n * It composes the three public pieces exactly as `@w6w/react`'s README bridge does: it never\n * spreads or patches the adapter, never reaches into `client.console`, and keeps no session\n * store of its own (`getSession` goes straight to `<W6WProvider>`).\n *\n * **Identity cache.** The `QueryClient` is owned here, not borrowed from the host, and it is a\n * NEW instance whenever `identityKey` changes — so a query cached while signed in as account A\n * is unreachable once the host switches to B. A new client alone is NOT enough: a mounted\n * `useQuery` keeps the `QueryObserver` it was born with, and that observer is bound to the client\n * it was created against, so a child that survives the swap would keep rendering A's cache. The\n * subtree is therefore also re-mounted (`key`), which drops every observer and every piece of\n * child state from the previous identity. The client, the `key` and the tuple handed to\n * `<W6WProvider>` all change in ONE state update: there is no render in which B's tree reads A's\n * cache. The old client is cleared once it is no longer mounted.\n *\n * **Identity switch (flush first).** A draft with a pending save must be written into the account\n * that produced the edit. When `identityKey` changes this provider therefore HOLDS the applied\n * tuple — `identityKey`, `apiOrigin`, `project`, `getSession`, the client — and keeps handing the\n * OLD one to `<W6WProvider>`, awaits `registry.flushAll()` (bounded, never rejects), and only then\n * applies the new tuple in a single update. `<W6WProvider>` swaps its client synchronously on a\n * new `identityKey` and detaches the old session store, so the flush must finish first; and the\n * new `getSession` is NOT forwarded early: `<W6WProvider>` reaches it through the stable wrapper\n * below, whose target is swapped in the same update as the tuple (forwarded early, the new\n * account's token would be minted on the old client). A flush that fails or times out still lets\n * the switch proceed (Q6) and is never retried with the new identity. A token rotation under an\n * unchanged `identityKey` is not a switch: it is forwarded at once, no hold.\n */\nimport { W6WProvider, type W6WSession, createW6WUiAdapter, useW6WClient } from \"@w6w/react\";\nimport type { FetchLike } from \"@w6w/sdk\";\nimport { type ThemeMode, W6WUIProvider } from \"@w6w/ui\";\nimport { type ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport { DraftRegistryProvider, EmbedClientProvider, createDraftRegistry } from \"./draft/index.ts\";\nimport { EmbedProjectContext } from \"./project-context.ts\";\n\nexport interface W6WEmbedProviderProps {\n /** The w6w API origin, e.g. `\"https://api.w6w.io\"`. */\n apiOrigin: string;\n /**\n * Mints a session for the CURRENT host user (`{token, expiresAt, expiresIn?}`). Always the\n * latest callback; the provider caches and renews the result.\n */\n getSession: () => Promise<W6WSession>;\n /**\n * Which signed-in identity this provider speaks for (e.g. `${userId}:${accountId}`). Changing it\n * rebuilds the API client AND replaces the `QueryClient`, so nothing cached for the previous\n * identity is ever shown under the new one.\n */\n identityKey: string;\n /** Force the `@w6w/ui` theme to follow the host's. Omit to resolve it the library's default way. */\n theme?: ThemeMode;\n /** Gates every read hook while `false` (default `true`) — e.g. until the host has a user. */\n ready?: boolean;\n /** Default project id for project-scoped operations. */\n project?: string;\n /** Transport override (tests, request recording). Defaults to `globalThis.fetch`. */\n fetch?: FetchLike;\n children: ReactNode;\n}\n\nfunction makeQueryClient(): QueryClient {\n // Same defaults as Studio's own client (`studio/src/main.tsx`).\n return new QueryClient({\n defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false } },\n });\n}\n\n/** The part of the tuple that changes only when a switch has been APPLIED (after the flush). */\ninterface Applied {\n identityKey: string;\n queryClient: QueryClient;\n}\n\n/** What `<W6WProvider>` is fed while no switch is in progress; frozen at the last such render. */\ninterface Forwarded {\n apiOrigin: string;\n project: string | undefined;\n getSession: () => Promise<W6WSession>;\n}\n\n/** Hands the SDK client of the nearest `<W6WProvider>` to `useWorkflowDraft`. */\nfunction ClientBridge({ children }: { children: ReactNode }) {\n return <EmbedClientProvider client={useW6WClient()}>{children}</EmbedClientProvider>;\n}\n\n/** The README bridge: `useW6WClient` -> `createW6WUiAdapter` -> `<W6WUIProvider>`. */\nfunction UiBridge({ theme, children }: { theme?: ThemeMode; children: ReactNode }) {\n const client = useW6WClient();\n const api = useMemo(() => createW6WUiAdapter(client), [client]);\n return (\n <W6WUIProvider api={api} theme={theme}>\n {children}\n </W6WUIProvider>\n );\n}\n\nexport function W6WEmbedProvider({\n apiOrigin,\n getSession,\n identityKey,\n theme,\n ready,\n project,\n fetch,\n children,\n}: W6WEmbedProviderProps): ReactNode {\n const [registry] = useState(createDraftRegistry);\n const [applied, setApplied] = useState<Applied>(() => ({\n identityKey,\n queryClient: makeQueryClient(),\n }));\n\n // While `identityKey` differs from the applied one a switch is pending: everything below keeps\n // using the values frozen at the last render that was not pending. Otherwise props flow straight\n // through (project / origin changes, token rotation). Idempotent latest-value writes, the same\n // pattern `<W6WProvider>` uses for its own refs.\n const switching = identityKey !== applied.identityKey;\n const forwardedRef = useRef<Forwarded>({ apiOrigin, project, getSession });\n if (!switching) forwardedRef.current = { apiOrigin, project, getSession };\n const forwarded = forwardedRef.current;\n\n // The stable `getSession` handed to `<W6WProvider>`: reads whatever is applied RIGHT NOW. Its\n // target changes in the same render that applies the new tuple, never before the flush settles.\n const sessionRef = useRef(forwarded.getSession);\n sessionRef.current = forwarded.getSession;\n const [stableGetSession] = useState(() => () => sessionRef.current());\n\n useEffect(() => {\n if (identityKey === applied.identityKey) return;\n let cancelled = false;\n const apply = () => {\n if (cancelled) return;\n setApplied({ identityKey, queryClient: makeQueryClient() });\n };\n // `flushAll` never rejects and is bounded; the switch proceeds either way (Q6).\n registry.flushAll().then(apply, apply);\n return () => {\n cancelled = true;\n };\n }, [identityKey, applied.identityKey, registry]);\n\n // The replaced client is dropped once nothing mounted reads it.\n const queryClient = applied.queryClient;\n useEffect(() => () => queryClient.clear(), [queryClient]);\n\n return (\n <DraftRegistryProvider registry={registry}>\n <QueryClientProvider key={applied.identityKey} client={queryClient}>\n <W6WProvider\n baseUrl={forwarded.apiOrigin}\n getSession={stableGetSession}\n identityKey={applied.identityKey}\n ready={ready}\n project={forwarded.project}\n fetch={fetch}\n >\n <EmbedProjectContext.Provider value={forwarded.project}>\n <ClientBridge>\n <UiBridge theme={theme}>{children}</UiBridge>\n </ClientBridge>\n </EmbedProjectContext.Provider>\n </W6WProvider>\n </QueryClientProvider>\n </DraftRegistryProvider>\n );\n}\n"],"names":["makeQueryClient","QueryClient","ClientBridge","children","jsx","EmbedClientProvider","useW6WClient","UiBridge","theme","client","api","useMemo","createW6WUiAdapter","W6WUIProvider","W6WEmbedProvider","apiOrigin","getSession","identityKey","ready","project","fetch","registry","useState","createDraftRegistry","applied","setApplied","switching","forwardedRef","useRef","forwarded","sessionRef","stableGetSession","useEffect","cancelled","apply","queryClient","DraftRegistryProvider","QueryClientProvider","W6WProvider","EmbedProjectContext"],"mappings":";;;;;;;;;AA+DA,SAASA,IAA+B;AAEtC,SAAO,IAAIC,EAAY;AAAA,IACrB,gBAAgB,EAAE,SAAS,EAAE,OAAO,IAAO,sBAAsB,KAAM;AAAA,EAAE,CAC1E;AACH;AAgBA,SAASC,EAAa,EAAE,UAAAC,KAAqC;AAC3D,SAAO,gBAAAC,EAACC,GAAA,EAAoB,QAAQC,EAAA,GAAiB,UAAAH,GAAS;AAChE;AAGA,SAASI,EAAS,EAAE,OAAAC,GAAO,UAAAL,KAAwD;AACjF,QAAMM,IAASH,EAAA,GACTI,IAAMC,EAAQ,MAAMC,EAAmBH,CAAM,GAAG,CAACA,CAAM,CAAC;AAC9D,SACE,gBAAAL,EAACS,GAAA,EAAc,KAAAH,GAAU,OAAAF,GACtB,UAAAL,EAAA,CACH;AAEJ;AAEO,SAASW,EAAiB;AAAA,EAC/B,WAAAC;AAAA,EACA,YAAAC;AAAA,EACA,aAAAC;AAAA,EACA,OAAAT;AAAA,EACA,OAAAU;AAAA,EACA,SAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAjB;AACF,GAAqC;AACnC,QAAM,CAACkB,CAAQ,IAAIC,EAASC,CAAmB,GACzC,CAACC,GAASC,CAAU,IAAIH,EAAkB,OAAO;AAAA,IACrD,aAAAL;AAAA,IACA,aAAajB,EAAA;AAAA,EAAgB,EAC7B,GAMI0B,IAAYT,MAAgBO,EAAQ,aACpCG,IAAeC,EAAkB,EAAE,WAAAb,GAAW,SAAAI,GAAS,YAAAH,GAAY;AACzE,EAAKU,MAAWC,EAAa,UAAU,EAAE,WAAAZ,GAAW,SAAAI,GAAS,YAAAH,EAAA;AAC7D,QAAMa,IAAYF,EAAa,SAIzBG,IAAaF,EAAOC,EAAU,UAAU;AAC9C,EAAAC,EAAW,UAAUD,EAAU;AAC/B,QAAM,CAACE,CAAgB,IAAIT,EAAS,MAAM,MAAMQ,EAAW,SAAS;AAEpE,EAAAE,EAAU,MAAM;AACd,QAAIf,MAAgBO,EAAQ,YAAa;AACzC,QAAIS,IAAY;AAChB,UAAMC,IAAQ,MAAM;AAClB,MAAID,KACJR,EAAW,EAAE,aAAAR,GAAa,aAAajB,EAAA,GAAmB;AAAA,IAC5D;AAEA,WAAAqB,EAAS,SAAA,EAAW,KAAKa,GAAOA,CAAK,GAC9B,MAAM;AACX,MAAAD,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAChB,GAAaO,EAAQ,aAAaH,CAAQ,CAAC;AAG/C,QAAMc,IAAcX,EAAQ;AAC5B,SAAAQ,EAAU,MAAM,MAAMG,EAAY,SAAS,CAACA,CAAW,CAAC,qBAGrDC,GAAA,EAAsB,UAAAf,GACrB,UAAA,gBAAAjB,EAACiC,GAAA,EAA8C,QAAQF,GACrD,UAAA,gBAAA/B;AAAA,IAACkC;AAAA,IAAA;AAAA,MACC,SAAST,EAAU;AAAA,MACnB,YAAYE;AAAA,MACZ,aAAaP,EAAQ;AAAA,MACrB,OAAAN;AAAA,MACA,SAASW,EAAU;AAAA,MACnB,OAAAT;AAAA,MAEA,UAAA,gBAAAhB,EAACmC,EAAoB,UAApB,EAA6B,OAAOV,EAAU,SAC7C,UAAA,gBAAAzB,EAACF,GAAA,EACC,UAAA,gBAAAE,EAACG,GAAA,EAAS,OAAAC,GAAe,UAAAL,EAAA,CAAS,GACpC,EAAA,CACF;AAAA,IAAA;AAAA,EAAA,KAbsBqB,EAAQ,WAelC,GACF;AAEJ;"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/embed-status.ts","../src/W6WEmbedProvider.tsx"],"sourcesContent":["/**\n * The embed's public session status, as a pure total function over the `@w6w/react` session\n * store's status plus whether a terminal partner-token 401 has been seen. No React here, so\n * `node:test` covers it exhaustively.\n */\nimport type { W6WSessionStatus } from \"@w6w/react\";\n\nexport type EmbedStatusValue = \"connecting\" | \"ready\" | \"error\";\n\nexport interface EmbedStatus {\n status: EmbedStatusValue;\n /** `EmbedAuthError` for a terminal 401, else the session store's own error; `null` otherwise. */\n error: unknown;\n}\n\n/**\n * The terminal partner-token 401: the host's `getSession` minted a token the API refused, and a\n * renewal did not fix it. `cause` is the SDK `ApiError`.\n */\nexport class EmbedAuthError extends Error {\n constructor(cause: unknown) {\n super(\"The w6w API rejected the embed session token (401).\", { cause });\n this.name = \"EmbedAuthError\";\n }\n}\n\n/**\n * `loading -> connecting`, `ready|renewing -> ready`, `expired -> connecting` (the provider\n * re-acquires), `error -> error`. A seen 401 wins over everything: it is `error` with the\n * `EmbedAuthError`, whatever the store currently says.\n */\nexport function deriveEmbedStatus(\n sessionStatus: W6WSessionStatus,\n sessionError: unknown,\n authError: EmbedAuthError | null,\n): EmbedStatus {\n if (authError) return { status: \"error\", error: authError };\n switch (sessionStatus) {\n case \"ready\":\n case \"renewing\":\n return { status: \"ready\", error: null };\n case \"error\":\n return { status: \"error\", error: sessionError };\n case \"loading\":\n case \"expired\":\n return { status: \"connecting\", error: null };\n }\n}\n","import { QueryClient, QueryClientProvider, useQuery } from \"@tanstack/react-query\";\n/**\n * `<W6WEmbedProvider>` — everything an embedded w6w surface needs from a host, behind one\n * element: an identity-scoped `QueryClient`, a `@w6w/react` `<W6WProvider>` (client, session\n * renewal, per-request token) and `@w6w/ui`'s `<W6WUIProvider>` fed by `createW6WUiAdapter`.\n * It composes the three public pieces exactly as `@w6w/react`'s README bridge does: it never\n * spreads or patches the adapter, never reaches into `client.console`, and keeps no session\n * store of its own (`getSession` goes straight to `<W6WProvider>`).\n *\n * **Identity cache.** The `QueryClient` is owned here, not borrowed from the host, and it is a\n * NEW instance whenever `identityKey` changes — so a query cached while signed in as account A\n * is unreachable once the host switches to B. A new client alone is NOT enough: a mounted\n * `useQuery` keeps the `QueryObserver` it was born with, and that observer is bound to the client\n * it was created against, so a child that survives the swap would keep rendering A's cache. The\n * subtree is therefore also re-mounted (`key`), which drops every observer and every piece of\n * child state from the previous identity. The client, the `key` and the tuple handed to\n * `<W6WProvider>` all change in ONE state update: there is no render in which B's tree reads A's\n * cache. The old client is cleared once it is no longer mounted.\n *\n * **Identity switch (flush first).** A draft with a pending save must be written into the account\n * that produced the edit. When `identityKey` changes this provider therefore HOLDS the applied\n * tuple — `identityKey`, `apiOrigin`, `project`, `getSession`, the client — and keeps handing the\n * OLD one to `<W6WProvider>`, awaits `registry.flushAll()` (bounded, never rejects), and only then\n * applies the new tuple in a single update. `<W6WProvider>` swaps its client synchronously on a\n * new `identityKey` and detaches the old session store, so the flush must finish first; and the\n * new `getSession` is NOT forwarded early: `<W6WProvider>` reaches it through the stable wrapper\n * below, whose target is swapped in the same update as the tuple (forwarded early, the new\n * account's token would be minted on the old client). A flush that fails or times out still lets\n * the switch proceed (Q6) and is never retried with the new identity. A token rotation under an\n * unchanged `identityKey` is not a switch: it is forwarded at once, no hold.\n *\n * **No identity.** `identityKey={null}` mounts nothing but `fallback`: no `<W6WProvider>`, no\n * `QueryClientProvider`, no children — so no `getSession` call and no request. `null -> \"A\"`\n * applies at once (nothing can be pending); `\"A\" -> null` takes the SAME flush-first path as any\n * other switch before the fallback renders.\n *\n * **Default project.** `project={{ use: \"default\" }}` resolves ONCE per applied identity, through\n * one `client.projects.list()` query inside the identity-scoped `QueryClient`, to the row with\n * `isDefault === true` — never `list[0]`, never a fallback. `<W6WProvider>` gets no project until\n * it resolves; the client rebuild that follows reuses the cached answer (the query is keyed\n * without the client and lives in a component that stays mounted, so it is not re-issued).\n *\n * **Status.** `useEmbedStatus()` is `deriveEmbedStatus` over the `@w6w/react` session store plus a\n * terminal 401 seen through the forwarded `onUnauthorized`.\n */\nimport {\n W6WProvider,\n type W6WSession,\n createW6WUiAdapter,\n useW6WClient,\n useW6WSession,\n} from \"@w6w/react\";\nimport type { ApiError, FetchLike } from \"@w6w/sdk\";\nimport { type ThemeMode, type W6WApi, W6WUIProvider } from \"@w6w/ui\";\nimport {\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { DraftRegistryProvider, EmbedClientProvider, createDraftRegistry } from \"./draft/index.ts\";\nimport { EmbedAuthError, type EmbedStatus, deriveEmbedStatus } from \"./embed-status.ts\";\nimport { EmbedProjectContext, type EmbedProjectState } from \"./project-context.ts\";\nimport { updateConnection } from \"./repos/connections.ts\";\n\nexport interface W6WEmbedProviderProps {\n /** The w6w API origin, e.g. `\"https://api.w6w.io\"`. */\n apiOrigin: string;\n /**\n * Mints a session for the CURRENT host user (`{token, expiresAt, expiresIn?}`). Always the\n * latest callback; the provider caches and renews the result.\n */\n getSession: () => Promise<W6WSession>;\n /**\n * Which signed-in identity this provider speaks for (e.g. `${userId}:${accountId}`). Changing it\n * rebuilds the API client AND replaces the `QueryClient`, so nothing cached for the previous\n * identity is ever shown under the new one.\n */\n identityKey: string | null;\n /**\n * Rendered instead of the embed while `identityKey` is `null` (no signed-in user). Nothing of\n * the embed mounts then: no `getSession` call, no request. Default `null`.\n */\n fallback?: ReactNode;\n /**\n * Start acquiring a session on mount. Without it the session is acquired lazily, by the first\n * request a mounted surface makes, and `useEmbedStatus()` stays `\"connecting\"` until then.\n */\n eager?: boolean;\n /** Force the `@w6w/ui` theme to follow the host's. Omit to resolve it the library's default way. */\n theme?: ThemeMode;\n /** Gates every read hook while `false` (default `true`) — e.g. until the host has a user. */\n ready?: boolean;\n /**\n * Default project for project-scoped operations: a project id, or `{ use: \"default\" }` to use\n * the account's default project (resolved once per identity; see `useEmbedProject()`).\n */\n project?: string | { use: \"default\" };\n /** Transport override (tests, request recording). Defaults to `globalThis.fetch`. */\n fetch?: FetchLike;\n children: ReactNode;\n}\n\nfunction makeQueryClient(): QueryClient {\n // Same defaults as Studio's own client (`studio/src/main.tsx`).\n return new QueryClient({\n defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false } },\n });\n}\n\n/** The part of the tuple that changes only when a switch has been APPLIED (after the flush). */\ninterface Applied {\n identityKey: string | null;\n queryClient: QueryClient;\n}\n\n/** What `<W6WProvider>` is fed while no switch is in progress; frozen at the last such render. */\ninterface Forwarded {\n apiOrigin: string;\n project: string | { use: \"default\" } | undefined;\n getSession: () => Promise<W6WSession>;\n}\n\n/** Hands the SDK client of the nearest `<W6WProvider>` to `useWorkflowDraft`. */\nfunction ClientBridge({ children }: { children: ReactNode }) {\n return <EmbedClientProvider client={useW6WClient()}>{children}</EmbedClientProvider>;\n}\n\n/** The README bridge: `useW6WClient` -> `createW6WUiAdapter` -> `<W6WUIProvider>`. */\nfunction UiBridge({ theme, children }: { theme?: ThemeMode; children: ReactNode }) {\n const client = useW6WClient();\n // `createW6WUiAdapter` has no `updateConnection`; keep one if it ever gains it, else supply the\n // embed repo's write so the ui Edit modal can save.\n const api = useMemo(() => {\n const base: W6WApi = createW6WUiAdapter(client);\n if (typeof base.updateConnection === \"function\") return base;\n return { ...base, updateConnection: (id, body) => updateConnection(client, id, body) };\n }, [client]);\n return (\n <W6WUIProvider api={api} theme={theme}>\n {children}\n </W6WUIProvider>\n );\n}\n\nconst EmbedStatusContext = createContext<EmbedStatus>({ status: \"connecting\", error: null });\n\n/** The session status of the nearest `<W6WEmbedProvider>`. See `deriveEmbedStatus`. */\nexport function useEmbedStatus(): EmbedStatus {\n return useContext(EmbedStatusContext);\n}\n\n/** Publishes `useEmbedStatus()`, and starts the session on mount when `eager`. */\nfunction StatusBridge({\n eager,\n authError,\n onAcquire,\n children,\n}: {\n eager: boolean;\n authError: EmbedAuthError | null;\n onAcquire: () => void;\n children: ReactNode;\n}) {\n const { status, error, refresh } = useW6WSession();\n // `refresh` is per session store, so a rebuilt client (project resolved) is started again.\n useEffect(() => {\n if (eager) void refresh();\n }, [eager, refresh]);\n useEffect(() => {\n if (status === \"loading\" || status === \"renewing\") onAcquire();\n }, [status, onAcquire]);\n const value = useMemo(\n () => deriveEmbedStatus(status, error, authError),\n [status, error, authError],\n );\n return <EmbedStatusContext.Provider value={value}>{children}</EmbedStatusContext.Provider>;\n}\n\n/**\n * Resolves `{use:\"default\"}`. Lives INSIDE `<W6WProvider>` (it needs the client) but at a fixed\n * slot, so it survives the client rebuild that follows resolution; the query key carries no\n * client, so nothing refetches.\n */\nfunction DefaultProjectResolver({\n identityKey,\n enabled,\n onState,\n}: {\n identityKey: string;\n enabled: boolean;\n onState: (key: string, state: EmbedProjectState) => void;\n}) {\n const client = useW6WClient();\n const q = useQuery({\n queryKey: [\"w6w-embed\", \"default-project\"],\n enabled,\n queryFn: async () => {\n const rows = await client.projects.list();\n const home = rows.find((p) => p.isDefault === true);\n if (!home) throw new Error(\"The account has no default project.\");\n return home.id;\n },\n });\n const { isError, error, data } = q;\n const state = useMemo<EmbedProjectState>(\n () =>\n isError\n ? { project: null, status: \"error\", error }\n : data !== undefined\n ? { project: data, status: \"ready\" }\n : { project: null, status: \"resolving\" },\n [isError, error, data],\n );\n useEffect(() => {\n onState(identityKey, state);\n }, [identityKey, state, onState]);\n return null;\n}\n\nexport function W6WEmbedProvider({\n apiOrigin,\n getSession,\n identityKey,\n fallback = null,\n eager = false,\n theme,\n ready,\n project,\n fetch,\n children,\n}: W6WEmbedProviderProps): ReactNode {\n const [registry] = useState(createDraftRegistry);\n const [applied, setApplied] = useState<Applied>(() => ({\n identityKey,\n queryClient: makeQueryClient(),\n }));\n\n // While `identityKey` differs from the applied one a switch is pending: everything below keeps\n // using the values frozen at the last render that was not pending. Otherwise props flow straight\n // through (project / origin changes, token rotation). Idempotent latest-value writes, the same\n // pattern `<W6WProvider>` uses for its own refs.\n const switching = identityKey !== applied.identityKey;\n const forwardedRef = useRef<Forwarded>({ apiOrigin, project, getSession });\n if (!switching) forwardedRef.current = { apiOrigin, project, getSession };\n const forwarded = forwardedRef.current;\n\n // The stable `getSession` handed to `<W6WProvider>`: reads whatever is applied RIGHT NOW. Its\n // target changes in the same render that applies the new tuple, never before the flush settles.\n const sessionRef = useRef(forwarded.getSession);\n sessionRef.current = forwarded.getSession;\n const [stableGetSession] = useState(() => () => sessionRef.current());\n\n useEffect(() => {\n if (identityKey === applied.identityKey) return;\n let cancelled = false;\n const apply = () => {\n if (cancelled) return;\n setApplied({ identityKey, queryClient: makeQueryClient() });\n };\n // Nothing is mounted under a null identity, so nothing can be pending: apply at once.\n if (applied.identityKey === null) {\n apply();\n return () => {\n cancelled = true;\n };\n }\n // `flushAll` never rejects and is bounded; the switch proceeds either way (Q6).\n registry.flushAll().then(apply, apply);\n return () => {\n cancelled = true;\n };\n }, [identityKey, applied.identityKey, registry]);\n\n // The replaced client is dropped once nothing mounted reads it.\n const queryClient = applied.queryClient;\n useEffect(() => () => queryClient.clear(), [queryClient]);\n\n // Default-project resolution, tagged with the identity it was resolved for: a result for A is\n // never read once B is applied.\n const [resolved, setResolved] = useState<{ key: string; state: EmbedProjectState } | null>(null);\n const onResolved = useCallback((key: string, state: EmbedProjectState) => {\n setResolved((prev) =>\n prev &&\n prev.key === key &&\n prev.state.project === state.project &&\n prev.state.status === state.status &&\n prev.state.error === state.error\n ? prev\n : { key, state },\n );\n }, []);\n\n // The terminal partner-token 401, tagged with its identity; cleared when the next acquisition\n // starts (StatusBridge) or the identity changes (the tag no longer matches).\n const [authFailure, setAuthFailure] = useState<{\n key: QueryClient;\n error: EmbedAuthError;\n } | null>(null);\n // The handler is bound to the per-mount client it was created for: a late 401 from a previous\n // `<W6WProvider>` is tagged with ITS client, never the one applied by the time it fires — even\n // when the identity key came back (A -> B -> A mints a new client for the same key).\n const onUnauthorized = useMemo(() => {\n const key = applied.queryClient;\n return (error: ApiError) => {\n setAuthFailure({ key, error: new EmbedAuthError(error) });\n };\n }, [applied.queryClient]);\n const clearAuthFailure = useCallback(() => setAuthFailure(null), []);\n\n const appliedKey = applied.identityKey;\n const spec = forwarded.project;\n // Only exactly `{ use: \"default\" }` asks for the account default; null, `{}`, `[]` or any other\n // object (JS hosts, casts) is \"no project\" and makes no lookup.\n const wantsDefault =\n typeof spec === \"object\" && spec !== null && !Array.isArray(spec) && spec.use === \"default\";\n const projectState: EmbedProjectState = useMemo(() => {\n if (typeof spec === \"string\") return { project: spec, status: \"ready\" };\n if (!wantsDefault) return { project: null, status: \"ready\" };\n return resolved && resolved.key === appliedKey\n ? resolved.state\n : { project: null, status: \"resolving\" };\n }, [spec, wantsDefault, resolved, appliedKey]);\n\n if (appliedKey === null) return fallback;\n\n return (\n <DraftRegistryProvider registry={registry}>\n <QueryClientProvider key={appliedKey} client={queryClient}>\n <W6WProvider\n baseUrl={forwarded.apiOrigin}\n getSession={stableGetSession}\n identityKey={appliedKey}\n ready={ready}\n project={projectState.project ?? undefined}\n fetch={fetch}\n onUnauthorized={onUnauthorized}\n >\n {wantsDefault ? (\n <DefaultProjectResolver\n identityKey={appliedKey}\n enabled={ready !== false}\n onState={onResolved}\n />\n ) : null}\n <EmbedProjectContext.Provider value={projectState}>\n <StatusBridge\n eager={eager}\n authError={authFailure && authFailure.key === queryClient ? authFailure.error : null}\n onAcquire={clearAuthFailure}\n >\n <ClientBridge>\n <UiBridge theme={theme}>{children}</UiBridge>\n </ClientBridge>\n </StatusBridge>\n </EmbedProjectContext.Provider>\n </W6WProvider>\n </QueryClientProvider>\n </DraftRegistryProvider>\n );\n}\n"],"names":["EmbedAuthError","cause","deriveEmbedStatus","sessionStatus","sessionError","authError","makeQueryClient","QueryClient","ClientBridge","children","jsx","EmbedClientProvider","useW6WClient","UiBridge","theme","client","api","useMemo","base","createW6WUiAdapter","id","body","updateConnection","W6WUIProvider","EmbedStatusContext","createContext","useEmbedStatus","useContext","StatusBridge","eager","onAcquire","status","error","refresh","useW6WSession","useEffect","value","DefaultProjectResolver","identityKey","enabled","onState","q","useQuery","home","p","isError","data","state","W6WEmbedProvider","apiOrigin","getSession","fallback","ready","project","fetch","registry","useState","createDraftRegistry","applied","setApplied","switching","forwardedRef","useRef","forwarded","sessionRef","stableGetSession","cancelled","apply","queryClient","resolved","setResolved","onResolved","useCallback","key","prev","authFailure","setAuthFailure","onUnauthorized","clearAuthFailure","appliedKey","spec","wantsDefault","projectState","DraftRegistryProvider","QueryClientProvider","jsxs","W6WProvider","EmbedProjectContext"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The ONE split of a Function's / Endpoint's `get` response into the editable definition and the
3
+ * stale-write token. `useCallableDraft` (seed, external-change detection, the posted body) and the
4
+ * rail's write paths (B-4) both read through it, so "what do we post, and which `updatedAt` do we
5
+ * guard it with" has one answer.
6
+ *
7
+ * - **function** — the `console.functions.get` result is `FunctionDef & {valid, updatedAt}` with the
8
+ * top-level values spread LAST. The definition is that object minus `valid` and `updatedAt`
9
+ * (both read-only splices that must never ride back in a save body); the token is its top-level
10
+ * `updatedAt`, so a stale `updatedAt` stored INSIDE a definition never wins.
11
+ * - **endpoint** — the response is the verbatim envelope `{endpoint, invokeUrl, …, updatedAt}`.
12
+ * The definition is `data.endpoint` as-is; the token is the TOP-LEVEL `data.updatedAt`, never
13
+ * `data.endpoint.updatedAt`.
14
+ *
15
+ * `null` when `data` is absent or is not the shape the kind answers with. Pure, no imports:
16
+ * loadable by `node --test`.
17
+ */
18
+ export declare function callableRecord(kind: "function" | "endpoint", data: unknown): {
19
+ definition: Record<string, unknown>;
20
+ updatedAt: string | null;
21
+ } | null;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Coerce a text field's value to the canonical input's declared type, for a callable's test-invoke
3
+ * form. Empty ⇒ undefined (the field is omitted from the payload). Unparseable `number`/`json` text
4
+ * is passed through raw, so the server's own validation names the problem.
5
+ */
6
+ export declare function coerceInput(type: string, raw: string): unknown;
@@ -0,0 +1,23 @@
1
+ import { EndpointDef, EndpointOwnTarget, InvokeUrlOption } from '../repos/endpoints.ts';
2
+ /** A blank `action` target — what an absent `target` hydrates to. */
3
+ export declare const BLANK_TARGET: EndpointOwnTarget;
4
+ /** `target` falls back to {@link BLANK_TARGET} and `input` to `[]`, only when absent. */
5
+ export declare function normalizeEndpoint(e: EndpointDef): EndpointDef;
6
+ /**
7
+ * The exact body a Save posts. Unbound target ⇒ no `target` key; empty Input ⇒ no `input` key
8
+ * (a documented pass-through mode server-side — saving `[]` would persist a spurious list). The
9
+ * key is trimmed. Everything else, secrets included, passes through unchanged.
10
+ */
11
+ export declare function buildEndpointSaveBody(draft: EndpointDef): Record<string, unknown>;
12
+ /** Which of the two server-rendered forms of the URL is on screen. */
13
+ export type UrlForm = "id" | "key";
14
+ /** The domain picker's options: only when there IS a second option (≤ 1 ⇒ `undefined`). */
15
+ export declare function urlOptions(invokeUrls: InvokeUrlOption[] | null | undefined): InvokeUrlOption[] | undefined;
16
+ /** The entry the card shows: the session pick (by domain NAME), else `default`, else the first. */
17
+ export declare function selectedUrlEntry(invokeUrls: InvokeUrlOption[] | null | undefined, pickedDomain: string | null): InvokeUrlOption | null;
18
+ /** What the URL card renders: the selected domain's entry, else the flat envelope fields. */
19
+ export declare function urlCardEntry(selected: InvokeUrlOption | null, invokeUrl: string | undefined, invokeUrlByKey: string | undefined): {
20
+ url: string;
21
+ urlByKey?: string;
22
+ resolves: boolean;
23
+ };
@@ -15,3 +15,10 @@ export { triggerInputSeed, triggerPreviews } from './trigger-preview.ts';
15
15
  export * from './sdk-snippets.ts';
16
16
  export * from './slug.ts';
17
17
  export * from './spec-import-invalidation.ts';
18
+ export * from './workflow-blank.ts';
19
+ export type { ActionImplLike, ActionTargetLike, CallableTargetLike, EndpointRefTargetLike, FunctionImplLike, InputRowLike, ParamLike, ShowIfPredicate, TargetField, TargetKind, TargetLike, TriggerFieldDefLike, WorkflowFieldCtx, WorkflowLike as TargetWorkflowLike, WorkflowStepLike as TargetWorkflowStepLike, } from './target-fields.ts';
20
+ export { fieldsFromWorkflow, implToTarget, paramsToFields, targetIsBound, targetRef, targetToImpl, } from './target-fields.ts';
21
+ export * from './input-seeding.ts';
22
+ export * from './input-coverage.ts';
23
+ export * from './coerce-input.ts';
24
+ export * from './callable-record.ts';
@@ -0,0 +1,28 @@
1
+ import { InputRow } from './input-seeding.ts';
2
+ import { FunctionImplLike, TargetField, TargetLike } from './target-fields.ts';
3
+ /**
4
+ * The required target-field keys an Endpoint does **not** feed — P1–P4 above.
5
+ * Empty means saveable as far as coverage is concerned; `EndpointsPage`'s own
6
+ * `targetIsBound`/`key` terms are separate and survive unchanged.
7
+ *
8
+ * `fields` is the target's normalized field list as `TargetSelector` resolved
9
+ * it. While a target's detail is still loading it is `[]`, so the gate is
10
+ * vacuous until the fields arrive — this fails **open**, deliberately: an
11
+ * unresolvable target (a deleted app, a failed fetch) must never trap an
12
+ * author in a form they cannot save.
13
+ */
14
+ export declare function uncoveredForEndpoint(args: {
15
+ target: TargetLike;
16
+ rows: InputRow[];
17
+ fields: TargetField[];
18
+ }): string[];
19
+ /**
20
+ * The required action-param keys a Function's `impl.with` does not map — P5.
21
+ * No skip arm: a Function has no pass-through mode. An unbound Function
22
+ * resolves to an empty `fields`, so this returns `[]` and the Functions save
23
+ * gate keeps allowing a deliberately incomplete save.
24
+ */
25
+ export declare function uncoveredForFunction(args: {
26
+ impl: FunctionImplLike | undefined;
27
+ fields: TargetField[];
28
+ }): string[];
@@ -0,0 +1,67 @@
1
+ import { TargetField } from './target-fields.ts';
2
+ /** The input-row types the two builders offer (`ActionParam`'s subset). */
3
+ export declare const INPUT_TYPES: readonly ["string", "text", "number", "boolean", "json", "secret"];
4
+ /**
5
+ * One row of an input-contract list — `FunctionInput`/`EndpointInput`'s
6
+ * common shape (`../api/types.ts`), mirrored locally so this pure module
7
+ * never imports a value from a `.tsx`-reexporting barrel. Structurally
8
+ * identical to both wire types, so a page's `draft.inputs`/`draft.input`
9
+ * needs no cast at the `InputListEditor` boundary in either direction.
10
+ */
11
+ export interface InputRow {
12
+ key: string;
13
+ label: string;
14
+ type: string;
15
+ required?: boolean;
16
+ default?: unknown;
17
+ hint?: string;
18
+ }
19
+ /**
20
+ * Is there a wholly empty, still-untouched list to seed? Any manual edit —
21
+ * add, update or remove, via the row editor's own `onChange` — makes the
22
+ * list the user's forever after (HITL-1); the seeding effect itself must
23
+ * never be what sets `touched`.
24
+ */
25
+ export declare function shouldSeed(args: {
26
+ rows: InputRow[];
27
+ touched: boolean;
28
+ }): boolean;
29
+ /**
30
+ * `rows` plus one appended row per `fields` key not already present, in
31
+ * field order. **Never modifies or removes an existing row, never
32
+ * re-orders.** A seeded row is
33
+ * `{ key, label: field.label ?? field.key, type, required: Boolean(field.required) }`
34
+ * and nothing else — `default`/`hint` are deliberately not copied, because
35
+ * the row editor cannot show or remove them and they would become invisible
36
+ * state on the saved definition. Fields with a missing/blank key are
37
+ * skipped; a duplicate key (in `fields`, or already present in `rows`)
38
+ * seeds once.
39
+ */
40
+ export declare function mergeSeed(rows: InputRow[], fields: TargetField[]): InputRow[];
41
+ /**
42
+ * The required field keys `fields` declares that no row in `rows` covers,
43
+ * in field order — what a target change leaves for the operator to notice
44
+ * once the list is the user's (HITL-1) and can no longer be auto-filled.
45
+ * Informational here: T3.2.2's save gate is what turns this into a block,
46
+ * and imports this same predicate rather than forking a second copy of it.
47
+ *
48
+ * Skips a required field that is currently hidden by its own `showIf` or
49
+ * that declares a usable `default` — mirroring
50
+ * `packages/ui/src/StepBuilderModal.tsx:686-711`'s `requiredParamsFilled`.
51
+ * `values` is the `with` mapping; omitting it leaves existing callers'
52
+ * behaviour unchanged apart from the two new skips.
53
+ */
54
+ export declare function uncoveredRequiredKeys(rows: InputRow[], fields: TargetField[], values?: Record<string, unknown>): string[];
55
+ /**
56
+ * The write-back both pages route their input list through (see the module
57
+ * docstring's pass-through guard). The overloads let a call site that
58
+ * passes the literal `emptyMeansPassthrough: false` (every Function save)
59
+ * keep a non-nullable return type at compile time, matching
60
+ * `FunctionDef.inputs`'s wire shape without a cast.
61
+ */
62
+ export declare function inputsForSave(rows: InputRow[], opts: {
63
+ emptyMeansPassthrough: false;
64
+ }): InputRow[];
65
+ export declare function inputsForSave(rows: InputRow[], opts: {
66
+ emptyMeansPassthrough: boolean;
67
+ }): InputRow[] | undefined;
@@ -177,9 +177,9 @@ export interface ArchivableRow {
177
177
  archivedAt?: string | null;
178
178
  }
179
179
  /**
180
- * A6: is this row archived? `status` takes priority when the row carries one
181
- * (Workflow rows always do) — falls back to `archivedAt` otherwise (Function/
182
- * Endpoint rows, which have no `status` field at all).
180
+ * A6: is this row archived? Archived when the row's `status` is `"archived"` OR it carries a
181
+ * non-null `archivedAt` (Endpoint rows carry both fields; Workflow rows carry a `status` that is
182
+ * `"archived"` exactly when `archivedAt` is set).
183
183
  */
184
184
  export declare function isRowArchived(row: ArchivableRow): boolean;
185
185
  /**