@w6w/embed 0.1.0 → 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 +34 -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":"document-sources-C0grrtdq.js","sources":["../src/lib/code-rail.ts","../src/lib/error-handler-self.ts","../src/lib/document-sources.ts"],"sourcesContent":["/**\n * Pure decisions behind the right rail's Code tool (`src/ui/rail/CodeTool.tsx`).\n * Split out so `node --test` can gate them directly — mirrors\n * `src/lib/alias-rail.ts`'s own reason for existing: `node --test` throws\n * `ERR_UNKNOWN_FILE_EXTENSION` on any `@w6w/ui`-adjacent import, and\n * `src/ui/workspace.tsx` sits one hop from that barrel through `Layout.tsx`'s\n * import graph. So this module declares its own structural mirror of\n * `WorkspaceCallable` instead of importing it.\n */\nimport type { SnippetCallable, SnippetInput } from \"./sdk-snippets.ts\";\n\n/** Structural mirror of T2.1.2's widened `WorkspaceCallable` (`src/ui/workspace.tsx`). */\nexport type RailCallable =\n | { kind: \"function\"; id: string; key?: string; inputs?: readonly SnippetInput[]; alias?: string }\n | {\n kind: \"endpoint\";\n id: string;\n key?: string;\n invokeUrl?: string;\n invokeUrlByKey?: string;\n urlForm?: \"id\" | \"key\";\n alias?: string;\n inputs?: readonly SnippetInput[];\n }\n | { kind: \"workflow\"; id: string; label?: string; key?: string }\n | { kind: \"connection\"; id: string }\n | null;\n\n/**\n * Is a \"Call from code\" panel meaningful for this context? Mirrors\n * `alias-rail.ts`'s `targetForCallable` fail-closed shape exactly (its own\n * comment: *\"'connection' and no resource at all both fail closed to null —\n * house style\"*) — `\"connection\"` and `null` both answer `false`.\n */\nexport function isAvailable(ctx: RailCallable): boolean {\n if (!ctx) return false;\n switch (ctx.kind) {\n case \"function\":\n case \"endpoint\":\n case \"workflow\":\n return true;\n default:\n return false;\n }\n}\n\n/**\n * The widened-union -> `SnippetCallable` conversion `CodeTool.Panel` hands to\n * `CallFromCodeBody`. `null` for a context this tool has no snippet for\n * (`\"connection\"`, or no resource at all) — defensive, since `isAvailable`\n * already keeps the tool off the strip for those.\n *\n * The one easy-to-miss field: `WorkspaceCallable`'s `label` maps to\n * `SnippetCallable`'s `workflow` arm's `displayName` — NOT the same field\n * name. A naive `{...ctx}` spread compiles (both optional) but silently\n * drops the label everywhere it matters, never caught by `tsc`.\n */\nexport function toSnippetCallable(ctx: RailCallable): SnippetCallable | null {\n if (!ctx) return null;\n switch (ctx.kind) {\n case \"function\":\n return { kind: \"function\", id: ctx.id, key: ctx.key, inputs: ctx.inputs, alias: ctx.alias };\n case \"endpoint\":\n return {\n kind: \"endpoint\",\n id: ctx.id,\n key: ctx.key,\n invokeUrl: ctx.invokeUrl,\n invokeUrlByKey: ctx.invokeUrlByKey,\n urlForm: ctx.urlForm,\n alias: ctx.alias,\n inputs: ctx.inputs,\n };\n case \"workflow\":\n return { kind: \"workflow\", id: ctx.id, displayName: ctx.label, key: ctx.key };\n default:\n return null;\n }\n}\n","/**\n * The authoring-time half of the error-handler recursion guard. The server\n * compares resolved values at dispatch time; this small, pure decision keeps\n * the rail from creating the known-identical no-adapter case in the first\n * place without losing an adapter imported or authored elsewhere.\n */\nexport type ErrorHandlerSelfDecision = \"allow\" | \"warn\" | \"block\";\n\nexport interface ErrorHandlerSelfInput {\n resource: { kind: string; id: string };\n target: { kind: string; id: string };\n hasAdapter: boolean;\n}\n\n/**\n * Only Function and Workflow targets can re-enter the currently edited\n * resource. Actions are always allowed. A self-target with no adapter passes\n * the failed input through unchanged, so it is refused; an adapter is kept\n * and called out because only the runtime can determine its resolved values.\n */\nexport function errorHandlerSelfDecision({\n resource,\n target,\n hasAdapter,\n}: ErrorHandlerSelfInput): ErrorHandlerSelfDecision {\n const selfTarget =\n (target.kind === \"function\" || target.kind === \"workflow\") &&\n target.kind === resource.kind &&\n target.id === resource.id;\n if (!selfTarget) return \"allow\";\n return hasAdapter ? \"warn\" : \"block\";\n}\n","/**\n * Pure `Doc[]` → `ExpressionOptions` projections for the ƒx picker's\n * Documents group — extracted out of `ExpressionScope.tsx` so studio's\n * Node-native `test:unit` runner (globbed to `src/lib/__tests__/`,\n * `src/api/__tests__/` and `src/repos/__tests__/` only — `.ai/PLANNER.md`\n * fact 10) can reach it. No React, no import from `src/ui/` — `@w6w/ui`'s\n * `ExpressionDocumentSource` interface is not imported either (it is not\n * exported from `@w6w/ui`'s barrel, D-P3): the object literals returned below\n * are structurally identical to it, so TypeScript carries the shape without a\n * type import.\n *\n * ## The gate — mirrors the engine's own, bit-for-bit\n *\n * A document contributes field data **iff**: `doc.format === \"json\"` AND\n * `JSON.parse(doc.content)` succeeds into a plain object, OR\n * `doc.format === \"yaml\"` AND npm `yaml`'s `parse(doc.content)` succeeds into\n * a plain object — where *plain object* means\n * `typeof v === \"object\" && v !== null && !Array.isArray(v)`. This mirrors\n * the engine's own gate (`documentsSeed` /\n * `packages/server/packages/api/run-seed.ts`, read-only, out of scope)\n * bit-for-bit for each format: `format === \"json\"` or `format === \"yaml\"`,\n * then a `try/catch` parse, falling back to the raw content string on either\n * a non-matching format or a throw. Reproduced here so the picker never\n * offers a ref the run scope itself would refuse to resolve\n * (`render_ref_unresolved`) — `text`/`markdown`/`html` documents, and a\n * `json`/`yaml` document whose parse throws or yields a non-plain-object, are\n * excluded.\n *\n * The two parsers are not identical for every input — `@std/yaml` (server,\n * `{ schema: \"core\" }`) and npm `yaml` (here) diverge on tab-indented content\n * and on an unresolvable custom tag (`!!js/function`), both accepted, tested\n * debt (D-3). Every other input, including a plain JSON object (JSON is a\n * subset of YAML), agrees between the two.\n *\n * Field keys are enumerated RAW and UNFILTERED by {@link projectDocumentSources}\n * — arbitrary user-authored JSON keys (which can contain `.`/`{`/`}`/\n * whitespace) reach the modal; `isRefSafeKey` filters them exactly once, at\n * the modal's render site (`ExpressionEditorModal.tsx`), never here\n * (`building-blocks.md`: \"enumerate raw at the source, filter once at the\n * single render site\").\n */\nimport type { Doc } from \"@w6w/sdk\";\nimport { parse as parseYaml } from \"yaml\";\n\n/** One document's contribution to `ExpressionOptions.documents` — structurally\n * identical to `@w6w/ui`'s (unexported) `ExpressionDocumentSource`. */\nexport interface DocumentSource {\n key: string;\n fields?: { key: string }[];\n}\n\n/**\n * `doc`'s parsed content when the gate holds, else `null`. The one place both\n * functions below apply the gate, so they cannot silently disagree on it.\n */\nfunction gatedFields(doc: Doc): Record<string, unknown> | null {\n let parsed: unknown;\n if (doc.format === \"json\") {\n try {\n parsed = JSON.parse(doc.content);\n } catch {\n return null;\n }\n } else if (doc.format === \"yaml\") {\n try {\n parsed = parseYaml(doc.content);\n } catch {\n return null;\n }\n } else {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return null;\n return parsed as Record<string, unknown>;\n}\n\n/**\n * The `ExpressionOptions.documents` array: `{ key }` for every document, plus\n * `fields` (raw, unfiltered top-level keys) when the gate holds AND the\n * parsed object has at least one key. `fields` is OMITTED (not `[]`) both\n * when the gate fails and when it holds but yields zero keys — a consumer\n * must be able to tell \"nothing declared\" from \"declared none\".\n */\nexport function projectDocumentSources(docs: Doc[]): DocumentSource[] {\n return docs.map((d) => {\n const parsed = gatedFields(d);\n if (!parsed) return { key: d.key };\n const keys = Object.keys(parsed);\n return keys.length > 0 ? { key: d.key, fields: keys.map((key) => ({ key })) } : { key: d.key };\n });\n}\n\n/**\n * The `sampleValues` entries the ƒx Result preview substitutes for document\n * refs: `documents.<key>` → the document's raw content, for every document\n * (unconditional, exactly as before this project), PLUS `documents.<key>.<field>`\n * → the field's own parsed value, for the gated set only. Without the second\n * half, every field ref this project newly makes pickable would preview as\n * the empty string (`renderResult` does an exact flat-key lookup).\n */\nexport function documentSampleValues(docs: Doc[]): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const d of docs) {\n out[`documents.${d.key}`] = d.content;\n const parsed = gatedFields(d);\n if (!parsed) continue;\n for (const [key, value] of Object.entries(parsed)) {\n out[`documents.${d.key}.${key}`] = value;\n }\n }\n return out;\n}\n"],"names":["isAvailable","ctx","toSnippetCallable","errorHandlerSelfDecision","resource","target","hasAdapter","gatedFields","doc","parsed","parseYaml","projectDocumentSources","docs","d","keys","key","documentSampleValues","out","value"],"mappings":";AAkCO,SAASA,EAAYC,GAA4B;AACtD,MAAI,CAACA,EAAK,QAAO;AACjB,UAAQA,EAAI,MAAA;AAAA,IACV,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EAAA;AAEb;AAaO,SAASC,EAAkBD,GAA2C;AAC3E,MAAI,CAACA,EAAK,QAAO;AACjB,UAAQA,EAAI,MAAA;AAAA,IACV,KAAK;AACH,aAAO,EAAE,MAAM,YAAY,IAAIA,EAAI,IAAI,KAAKA,EAAI,KAAK,QAAQA,EAAI,QAAQ,OAAOA,EAAI,MAAA;AAAA,IACtF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,IAAIA,EAAI;AAAA,QACR,KAAKA,EAAI;AAAA,QACT,WAAWA,EAAI;AAAA,QACf,gBAAgBA,EAAI;AAAA,QACpB,SAASA,EAAI;AAAA,QACb,OAAOA,EAAI;AAAA,QACX,QAAQA,EAAI;AAAA,MAAA;AAAA,IAEhB,KAAK;AACH,aAAO,EAAE,MAAM,YAAY,IAAIA,EAAI,IAAI,aAAaA,EAAI,OAAO,KAAKA,EAAI,IAAA;AAAA,IAC1E;AACE,aAAO;AAAA,EAAA;AAEb;AC1DO,SAASE,EAAyB;AAAA,EACvC,UAAAC;AAAA,EACA,QAAAC;AAAA,EACA,YAAAC;AACF,GAAoD;AAKlD,UAHGD,EAAO,SAAS,cAAcA,EAAO,SAAS,eAC/CA,EAAO,SAASD,EAAS,QACzBC,EAAO,OAAOD,EAAS,KAElBE,IAAa,SAAS,UADL;AAE1B;ACwBA,SAASC,EAAYC,GAA0C;AAC7D,MAAIC;AACJ,MAAID,EAAI,WAAW;AACjB,QAAI;AACF,MAAAC,IAAS,KAAK,MAAMD,EAAI,OAAO;AAAA,IACjC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,WACSA,EAAI,WAAW;AACxB,QAAI;AACF,MAAAC,IAASC,EAAUF,EAAI,OAAO;AAAA,IAChC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA;AAEA,WAAO;AAET,SAAI,OAAOC,KAAW,YAAYA,MAAW,QAAQ,MAAM,QAAQA,CAAM,IAAU,OAC5EA;AACT;AASO,SAASE,EAAuBC,GAA+B;AACpE,SAAOA,EAAK,IAAI,CAACC,MAAM;AACrB,UAAMJ,IAASF,EAAYM,CAAC;AAC5B,QAAI,CAACJ,EAAQ,QAAO,EAAE,KAAKI,EAAE,IAAA;AAC7B,UAAMC,IAAO,OAAO,KAAKL,CAAM;AAC/B,WAAOK,EAAK,SAAS,IAAI,EAAE,KAAKD,EAAE,KAAK,QAAQC,EAAK,IAAI,CAACC,OAAS,EAAE,KAAAA,IAAM,EAAA,IAAM,EAAE,KAAKF,EAAE,IAAA;AAAA,EAC3F,CAAC;AACH;AAUO,SAASG,EAAqBJ,GAAsC;AACzE,QAAMK,IAA+B,CAAA;AACrC,aAAWJ,KAAKD,GAAM;AACpB,IAAAK,EAAI,aAAaJ,EAAE,GAAG,EAAE,IAAIA,EAAE;AAC9B,UAAMJ,IAASF,EAAYM,CAAC;AAC5B,QAAKJ;AACL,iBAAW,CAACM,GAAKG,CAAK,KAAK,OAAO,QAAQT,CAAM;AAC9C,QAAAQ,EAAI,aAAaJ,EAAE,GAAG,IAAIE,CAAG,EAAE,IAAIG;AAAA,EAEvC;AACA,SAAOD;AACT;"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * `@w6w/embed/draft` — the headless draft lifecycle (debounced autosave, flush-on-hide, the
3
- * workflow save precondition). No UI and no `@w6w/ui`: it imports only `react`,
3
+ * workflow / function / endpoint save precondition). No UI and no `@w6w/ui`: it imports only `react`,
4
4
  * `@tanstack/react-query` and type-only `@w6w/sdk`, so a host can use it without the editor.
5
5
  */
6
6
  export { AUTOSAVE_DEBOUNCE_MS, createAutoSaver } from './autosave.ts';
@@ -13,3 +13,5 @@ export { DraftRegistryProvider, createDraftRegistry, useDraftRegistry, } from '.
13
13
  export type { DraftRegistry } from './draft-registry.ts';
14
14
  export { useWorkflowDraft } from './use-workflow-draft.ts';
15
15
  export type { FlushOutcome, UseWorkflowDraftOptions, WorkflowDraft, } from './use-workflow-draft.ts';
16
+ export { useCallableDraft, useEndpointDraft, useFunctionDraft } from './use-callable-draft.ts';
17
+ export type { CallableDraft, CallableDraftKind, UseCallableDraftOptions, } from './use-callable-draft.ts';
@@ -0,0 +1,65 @@
1
+ import { CallablePolicy } from '../lib/settings-rail.ts';
2
+ import { FlushOutcome } from './use-workflow-draft.ts';
3
+ export type CallableDraftKind = "function" | "endpoint";
4
+ type Definition = Record<string, unknown>;
5
+ export interface UseCallableDraftOptions {
6
+ /** `null` ⇒ idle (the hook stays mounted above an early return). */
7
+ id: string | null;
8
+ /** Default FALSE: nothing is sent until `saveNow()` / `flush()` / `commit()`. */
9
+ autoSave?: boolean;
10
+ /** Injected busy probe. Gates AUTOMATIC saves only. */
11
+ canAutoSave?: () => boolean;
12
+ /** Injected edit guard: a reason blocks saving. */
13
+ saveGuard?: (definition: Definition) => string | null;
14
+ /**
15
+ * Called once when a handover or an identity switch (`flushAll`) drops a dirty buffer it could
16
+ * not save. `blocked`: refused before a request; `failed`: the request failed or the row was
17
+ * stale. No UI here.
18
+ */
19
+ onDiscard?: (info: {
20
+ id: string;
21
+ definition: Definition;
22
+ reason: "blocked" | "failed";
23
+ }) => void;
24
+ }
25
+ export interface CallableDraft {
26
+ /** The editable definition (no `valid` / `updatedAt`); `null` until loaded. */
27
+ definition: Definition | null;
28
+ setDefinition(next: Definition | ((prev: Definition) => Definition)): void;
29
+ /** `{retry, onError, reroute}` read off the buffer. */
30
+ policy: CallablePolicy;
31
+ /** Referentially stable. Saves `definitionWithPolicy(buffer, next)` now. */
32
+ onPolicyChange(policy: CallablePolicy): void;
33
+ loading: boolean;
34
+ loadError: unknown | null;
35
+ dirty: boolean;
36
+ saving: boolean;
37
+ canSave: boolean;
38
+ saveBlockedReason: string | null;
39
+ /** The last save was refused as stale (`function_stale` / `endpoint_stale`). */
40
+ stale: boolean;
41
+ /** Another writer changed the resource while this buffer is dirty. Never merged. */
42
+ changedElsewhere: boolean;
43
+ error: unknown | null;
44
+ /** Push + fire now. */
45
+ saveNow(): void;
46
+ flush(): Promise<FlushOutcome>;
47
+ /** Flush, then run `action` only when the buffer is clean or just saved. */
48
+ flushThen<T>(action: () => Promise<T>): Promise<{
49
+ ok: true;
50
+ value: T;
51
+ } | {
52
+ ok: false;
53
+ outcome: FlushOutcome;
54
+ }>;
55
+ /** `setDefinition(def)` + an immediate save. */
56
+ commit(def: Definition): Promise<FlushOutcome>;
57
+ /** Refetch the shared query, replace the buffer and token, clear `stale` / `changedElsewhere`. */
58
+ reload(): Promise<void>;
59
+ }
60
+ export declare function useCallableDraft(kind: CallableDraftKind, o: UseCallableDraftOptions): CallableDraft;
61
+ /** {@link useCallableDraft} bound to a Function. */
62
+ export declare function useFunctionDraft(o: UseCallableDraftOptions): CallableDraft;
63
+ /** {@link useCallableDraft} bound to an Endpoint. */
64
+ export declare function useEndpointDraft(o: UseCallableDraftOptions): CallableDraft;
65
+ export {};
@@ -23,6 +23,9 @@
23
23
  * - `workflow_conflict` — another `(tenant, subject)` owns that workflow id.
24
24
  * Reloading changes nothing; offering a reload here would be a dead end.
25
25
  *
26
+ * The same precondition guards Function and Endpoint saves, answered with `function_stale` /
27
+ * `endpoint_stale`; all three are the recoverable "your copy is out of date" verdict.
28
+ *
26
29
  * Anything that carries no `code` (a thrown `TypeError`, a string, `null`) is
27
30
  * not a server verdict at all, so it is not a stale write either.
28
31
  *
package/dist/draft.mjs CHANGED
@@ -1,18 +1,22 @@
1
1
  "use client";
2
- import { A as s, c as a, i as t, n as i, r as o, u } from "./use-workflow-draft-oI02dsP-.js";
2
+ import { A as a, c as s, i as t, n as o, r as i, u } from "./use-workflow-draft-DzAyUeA6.js";
3
3
  import { E as n, u as l } from "./client-context-CX61Bgw-.js";
4
4
  import { D as E, c, u as d } from "./draft-registry-YF0tqNN0.js";
5
+ import { u as p, a as x, b as S } from "./use-callable-draft-zHLpcr-b.js";
5
6
  export {
6
- s as AUTOSAVE_DEBOUNCE_MS,
7
+ a as AUTOSAVE_DEBOUNCE_MS,
7
8
  E as DraftRegistryProvider,
8
9
  n as EmbedClientProvider,
9
- a as createAutoSaver,
10
+ s as createAutoSaver,
10
11
  c as createDraftRegistry,
11
12
  t as isStaleWrite,
12
- i as nextSaveToken,
13
- o as registerFlushOnHide,
13
+ o as nextSaveToken,
14
+ i as registerFlushOnHide,
15
+ p as useCallableDraft,
14
16
  d as useDraftRegistry,
15
17
  l as useEmbedClient,
18
+ x as useEndpointDraft,
19
+ S as useFunctionDraft,
16
20
  u as useWorkflowDraft
17
21
  };
18
22
  //# sourceMappingURL=draft.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"draft.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"draft.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
@@ -0,0 +1,33 @@
1
+ import { ReactNode } from 'react';
2
+ import { CallableKind } from '../lib/callable-kind.ts';
3
+ import { CallableEditorNavigation, CallableEditorSlots } from './types.ts';
4
+ export interface CallableEditorFrameProps {
5
+ /** Which kind's copy (back/save labels, not-found heading) the frame shows. */
6
+ kind: CallableKind;
7
+ /** The heading's text — the kind computes it from its own draft, because only it knows what
8
+ * "empty" means for its definition. */
9
+ title: string;
10
+ /** Renders the `incomplete` badge beside the heading. */
11
+ incomplete: boolean;
12
+ canSave: boolean;
13
+ isSaving: boolean;
14
+ onSave: () => void;
15
+ error: string | null;
16
+ /** A 404 from the hydration GET: render the not-found card, never a blank editable form. */
17
+ notFound: boolean;
18
+ /** Where the host should take the user; back asks for `{ type: "list" }`. */
19
+ onNavigate: (to: CallableEditorNavigation) => void;
20
+ slots?: CallableEditorSlots;
21
+ /** Statements BETWEEN the error banner and the body — the save-gate explanation, "Saved.". */
22
+ banners?: ReactNode;
23
+ /** Rendered as the FIRST child of the header action row, before Save (e.g. a JSON toggle). */
24
+ headerActions?: ReactNode;
25
+ children: ReactNode;
26
+ }
27
+ /**
28
+ * The shared editor frame of the Function and Endpoint editors: back control, heading with the
29
+ * `incomplete` badge, Save, the error banner and the body (or the not-found card). Router-free —
30
+ * it asks the host to navigate through `onNavigate` and sets no document title. It publishes
31
+ * nothing to the rail workspace either: each editor body does that itself (`useWorkspace`).
32
+ */
33
+ export declare function CallableEditorFrame(props: CallableEditorFrameProps): import("react").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { ReactNode } from 'react';
2
+ import { RailTool } from '../chrome/RightRail.tsx';
3
+ import { RailNavigation } from '../rail/rail-env.tsx';
4
+ export interface EditorShellProps {
5
+ /** Resolved project (`null` = none; tools refuse to save). */
6
+ project: string | null;
7
+ onNavigate: (to: RailNavigation) => void;
8
+ /** Default `true`. `false`: render no rail; publish into the enclosing workspace if any. */
9
+ rail?: boolean;
10
+ /** Persisted-rail key; `null` = not yet persistable. */
11
+ storageKey: string | null;
12
+ /** Default {@link editorRailTools}. */
13
+ tools?: readonly RailTool[];
14
+ children: ReactNode;
15
+ }
16
+ export declare function EditorShell({ project, onNavigate, rail, storageKey, tools, children, }: EditorShellProps): ReactNode;
@@ -0,0 +1,56 @@
1
+ import { UrlForm } from '../lib/endpoint-editor.ts';
2
+ import { EndpointInput, EndpointSecurity, InvokeUrlOption } from '../repos/endpoints.ts';
3
+ /**
4
+ * The Endpoint's callable URL — its own card, directly beneath Identity.
5
+ *
6
+ * **Every URL here comes from the SERVER, verbatim** (the `["endpoint", id]` envelope's
7
+ * `invokeUrl`, `invokeUrlByKey` and `invokeUrls[]`): this component picks between strings and
8
+ * renders one. It holds no hostname, no path grammar and no account slug. `entry.urlByKey` is
9
+ * absent until the server renders it; then the card is one URL line and one Copy button, no
10
+ * id/key toggle. `domainOptions` renders the domain `<select>` only when there is a second option
11
+ * (`lib/endpoint-editor.ts`'s `urlOptions` does that collapse).
12
+ */
13
+ export declare function UrlCard(props: {
14
+ entry: {
15
+ url: string;
16
+ urlByKey?: string;
17
+ resolves: boolean;
18
+ };
19
+ domainOptions?: InvokeUrlOption[];
20
+ urlDomain: string | null;
21
+ onUrlDomain: (domain: string) => void;
22
+ urlForm: UrlForm;
23
+ onUrlForm: (form: UrlForm) => void;
24
+ }): import("react").JSX.Element;
25
+ /**
26
+ * Who may call the URL above.
27
+ *
28
+ * Every mode except `platform` runs the target as the Endpoint's owner (there is no platform
29
+ * identity on such a request), which is what the warning below says before an operator switches off
30
+ * platform auth. Secrets are write-only: the server returns a mask for a configured secret, and
31
+ * saving the mask back keeps the stored value.
32
+ */
33
+ export declare function SecurityCard(props: {
34
+ security: EndpointSecurity;
35
+ onPatch: (next: Partial<EndpointSecurity>) => void;
36
+ }): import("react").JSX.Element;
37
+ /**
38
+ * A write-only secret input. A stored secret comes back as {@link SECRET_MASK}; the input renders
39
+ * EMPTY (the mask is never a DOM value) with the "stored — type to replace" hint, and the buffer
40
+ * keeps the mask until the operator types, so a save that never touches it preserves what is stored.
41
+ */
42
+ export declare function SecretField(props: {
43
+ label: string;
44
+ value: string | undefined;
45
+ onChange: (v: string) => void;
46
+ }): import("react").JSX.Element;
47
+ /**
48
+ * Test-invoke panel: one field per declared input, POSTed to /endpoints/:id/invoke. The server
49
+ * invokes the STORED definition, so unsaved edits are not what runs. The result is the
50
+ * `kind`-tagged envelope: an Action or Function target answers with an inline `output`; a Workflow
51
+ * target answers with a `runId` to poll.
52
+ */
53
+ export declare function EndpointTestInvoke(props: {
54
+ id: string;
55
+ inputs: EndpointInput[];
56
+ }): import("react").JSX.Element;
@@ -0,0 +1,26 @@
1
+ import { ReactNode } from 'react';
2
+ import { EndpointEditorProps } from './types.ts';
3
+ /**
4
+ * `<EndpointEditor endpointId>` — Studio's endpoint editor body (Identity, URL, Input, Target,
5
+ * Security, Test invoke, History, JSON toggle) as a published component. The outermost element is
6
+ * `.w6w-embed-root`; nothing goes through a portal.
7
+ *
8
+ * ## One cache, one draft
9
+ *
10
+ * Every field is the buffer of `useEndpointDraft` (seeded from, and refreshed by, the ONE
11
+ * `["endpoint", id]` query), and every write — the header Save, the bottom Save and the JSON
12
+ * toggle's Save — is that draft's `commit`, so each issues one POST carrying the stored
13
+ * `updatedAt` (`If-Unmodified-Since`). A 409 `endpoint_stale` is shown inline with a Reload and is
14
+ * never retried. The invoke URLs are read from the same query's envelope, never copied into state,
15
+ * so a rail save or an external change shows without a remount.
16
+ *
17
+ * A Save with nothing changed since the last read sends no request (the draft is clean).
18
+ *
19
+ * ## Rail
20
+ *
21
+ * `rail` omitted: the editor owns a rail. `rail={false}` inside a `<CallableWorkspace>` for the
22
+ * SAME endpoint id publishes into it; with `rail={false}` the rail saves use the WORKSPACE's
23
+ * `project`, not the `project` prop here. A workspace for a different id is silently overridden
24
+ * while this editor is mounted.
25
+ */
26
+ export declare function EndpointEditor(props: EndpointEditorProps): ReactNode;
@@ -0,0 +1,21 @@
1
+ import { ReactNode } from 'react';
2
+ import { FunctionEditorProps } from './types.ts';
3
+ /**
4
+ * The managed Function editor: Interface, Inputs, Implementation, Test invoke, History and a JSON
5
+ * toggle, on `EditorShell`. The outermost element is `.w6w-embed-root`; nothing goes through a
6
+ * portal.
7
+ *
8
+ * Every read and write goes through `useFunctionDraft` (one cache entry, `["function", id]`; one
9
+ * stale-write token). Save, the JSON toggle's Save and the rail's Error handling (`onPolicyChange`)
10
+ * all persist through the draft, so each carries `If-Unmodified-Since`; a 409 shows inline with a
11
+ * reload control and is never retried. `project` is not a save precondition (a Function is
12
+ * account-scoped): it scopes the expression rail and the rail's storage key only.
13
+ *
14
+ * `rail` defaults to `true`: the editor renders its own right rail. `rail={false}` renders none and
15
+ * publishes the Function (key, inputs, policy, `onPolicyChange`) into an enclosing
16
+ * `<CallableWorkspace kind="function" id>` for the SAME id; an editor whose id differs from its
17
+ * workspace's overrides it and the host's rail renders empty. With `rail={false}` inside a
18
+ * workspace, the rail's saves use that workspace's `project`, not this editor's `project` prop.
19
+ * Aliases are not part of this editor; a host adds its own through `tools`.
20
+ */
21
+ export declare function FunctionEditor(props: FunctionEditorProps): ReactNode;
@@ -0,0 +1,29 @@
1
+ import { ReactNode } from 'react';
2
+ import { InputRow } from '../lib/input-seeding.ts';
3
+ /**
4
+ * One input-row card, shared by the Functions "Inputs" editor and the
5
+ * Endpoints "Input" editor (T3.2.1) — the two were byte-identical from
6
+ * `<li key={i}>` through `</li>` on the merged branch, apart from the map
7
+ * source variable (`draft.inputs` vs the `inputs` local alias for
8
+ * `draft.input ?? []`). Controlled: the page owns `rows` as its `draft`'s
9
+ * single source of truth and passes the next array back through `onChange`
10
+ * on every add/update/remove — this component never holds its own copy.
11
+ *
12
+ * `emptyMeansPassthrough` carries the one real divergence between the two
13
+ * forms: an Endpoint's declared `input` list absent/empty is a documented
14
+ * pass-through mode, a Function's empty `inputs` just means "no arguments" —
15
+ * so the empty-state copy (and nothing else) differs per page.
16
+ */
17
+ export interface InputListEditorProps {
18
+ rows: InputRow[];
19
+ onChange: (next: InputRow[]) => void;
20
+ /** The card's `<h3>` — "Inputs" (Functions) or "Input" (Endpoints). */
21
+ title: string;
22
+ /** The card's descriptive copy, caller-owned so wording stays per-surface. */
23
+ description: ReactNode;
24
+ /** Endpoints: `true` (the empty-state copy talks about pass-through). Functions: `false`. */
25
+ emptyMeansPassthrough: boolean;
26
+ /** Required target-field keys the current rows don't cover (HITL-1's post-touch flag). */
27
+ uncoveredKeys?: string[];
28
+ }
29
+ export declare function InputListEditor(props: InputListEditorProps): import("react").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { TargetKind, TargetSelectorProps } from './TargetSelector.types.ts';
2
+ /**
3
+ * One `target` picker for both the Functions editor's Implementation card and
4
+ * the Endpoints editor's Target card (rfcs/endpoint.md:339-347,
5
+ * rfcs/function.md:61-62). `allowedKinds` is the type-level RFC guard (A1,
6
+ * see `TargetSelector.types.ts`) — Functions passes `["action"]`, which makes
7
+ * `{kind:"function"}`/`{kind:"workflow"}` unconstructable at that call site
8
+ * and renders no kind control at all (A2); Endpoints passes all three.
9
+ *
10
+ * Owns every fetch its three arms need (apps/actions/connections for `action`;
11
+ * the functions/workflows lists plus the picked one's own detail for the
12
+ * other two — A8, gated `useQuery`s, mirroring the pages' existing
13
+ * `actionsQuery` gating) and reuses `StepBuilderModal` verbatim for the
14
+ * `action` arm (A3) — this is the one remaining `<StepBuilderModal` call
15
+ * site; no second app/action picker.
16
+ *
17
+ * Resolves the picked target to a normalized `TargetField[]` (A5) and reports
18
+ * it via `onResolved` on every change, so a page's own `useEffect` can seed
19
+ * its input list from the same fields the mapping table below renders from
20
+ * (A7) — by the time that table can render, `inputs.*` already resolves.
21
+ *
22
+ * **Takes no `exprOptions`.** The ƒx rail its mapping rows and its picker modal
23
+ * offer is INHERITED — the app shell contributes the project's vars/secrets/
24
+ * documents, the page contributes its `inputs` — so every expression editor
25
+ * reachable from this card sees the same sources wherever it is opened. It used
26
+ * to take the scope as a prop and wrap only the picker modal in a provider,
27
+ * which is precisely how the mapping rows' `ƒx` toggles ended up offering an
28
+ * empty rail while the "Change" button offered the full one.
29
+ */
30
+ export declare function TargetSelector<K extends TargetKind>(props: TargetSelectorProps<K>): import("react").JSX.Element;
@@ -0,0 +1,62 @@
1
+ import { ReactNode } from 'react';
2
+ import { TargetField } from '../lib/target-fields.ts';
3
+ import { EndpointTarget } from '../repos/endpoints.ts';
4
+ /** The three arms an Endpoint's `target` can take (`EndpointTarget["kind"]`). */
5
+ export type TargetKind = EndpointTarget["kind"];
6
+ /** Narrow `EndpointTarget` to exactly the arm(s) named by `K`. */
7
+ export type TargetValue<K extends TargetKind> = Extract<EndpointTarget, {
8
+ kind: K;
9
+ }>;
10
+ /** Metadata resolved for the picked target, common across all three arms. */
11
+ export interface TargetMeta {
12
+ kind: TargetKind;
13
+ /** The app id for `action`; the function/workflow id for the other two arms. */
14
+ ref: string;
15
+ }
16
+ export interface TargetSelectorProps<K extends TargetKind> {
17
+ /** Which kinds the caller may construct. A single-element array offers no kind control at all (A2). */
18
+ allowedKinds: readonly K[];
19
+ value: TargetValue<NoInfer<K>>;
20
+ onChange: (next: TargetValue<NoInfer<K>>) => void;
21
+ /** Fired whenever the picked target resolves to a normalized field list (A5/A7). */
22
+ onResolved?: (t: {
23
+ meta: TargetMeta;
24
+ kind: K;
25
+ fields: TargetField[];
26
+ }) => void;
27
+ /** The card's `<h3>` — exactly "Implementation" (Functions) or "Target" (Endpoints), A11. */
28
+ title: string;
29
+ /** The card's descriptive copy, above the kind control — caller-owned so wording stays per-surface. */
30
+ description: ReactNode;
31
+ /** Endpoints only: renders the pass-through sentence in the action arm's mapping sub-panel (A11). */
32
+ passthroughHint?: boolean;
33
+ }
34
+ /**
35
+ * Compile-time proof of the generic narrowing described above. Never called —
36
+ * its only job is to fail `tsc` with `TS2578: Unused '@ts-expect-error'
37
+ * directive` the moment `TargetValue<K>` is ever widened from a type-level
38
+ * constraint to something an invalid kind could pass through undetected (e.g.
39
+ * a runtime `if` with no compile-time teeth). `allowedKinds={["action"]}`
40
+ * must make a `{kind:"function"}` (or `{kind:"workflow"}`) value literally
41
+ * unconstructable as `TargetValue<K>` — no shipped call site is single-kind
42
+ * today, but every one of them (`EndpointsPage`, `AliasesPage`) depends on
43
+ * the SAME generic holding at its own, wider `allowedKinds`.
44
+ */
45
+ export declare function _actionOnlyGuardProof(): void;
46
+ /**
47
+ * Call-site-shaped companion to `_actionOnlyGuardProof`. That proof only
48
+ * exercises `TargetValue<"action">` with an EXPLICIT type argument — the one
49
+ * form that already errored before `NoInfer` — while every real call site
50
+ * (`FunctionsPage.tsx`, `EndpointsPage.tsx`, `AliasesPage.tsx`) supplies none;
51
+ * `K` is INFERRED from the props object, exactly like JSX calling a generic
52
+ * component. This proof mirrors that inference site: no explicit `<...>`
53
+ * anywhere, `allowedKinds` narrowed via `as const` (as every call site does),
54
+ * `value`/`onChange` passed as plain object/arrow-function literals. Before
55
+ * `NoInfer`, `K` inferred to `"action" | "function"` here and this compiled
56
+ * clean — the exact vacuous-guard failure mode this file now proves closed.
57
+ * `["action"]` is used as the tightest, single-kind shape of `allowedKinds`
58
+ * for the same reason `_actionOnlyGuardProof` does — no shipped call site
59
+ * is single-kind post-D-8, but the inference mechanism this exercises is the
60
+ * one every wider `allowedKinds` array (every real call site's) still needs.
61
+ */
62
+ export declare function _actionOnlyGuardCallSiteProof(): void;
@@ -1,7 +1,13 @@
1
1
  import { AppSummary } from '@w6w/ui';
2
- /** The per-app actions query key — byte-identical to Studio's `repos/apps.ts#appActionsKey`. */
3
- export declare const appActionsKey: (id: string) => readonly ["app-actions", string];
2
+ /** The per-app actions query key — the repos export itself (one declaration, no copy). */
3
+ export { appActionsKey } from '../repos/apps.ts';
4
4
  /** A bounded set of app records by id. Empty when the host's API has no `listAppsByIds`. */
5
5
  export declare function useEditorApps(ids: readonly string[]): {
6
6
  byId: ReadonlyMap<string, AppSummary>;
7
7
  };
8
+ /**
9
+ * One app record by id, over {@link useEditorApps} (same `/apps` request, same cache entry as the
10
+ * canvas's batch lookup). `undefined` while loading, for an empty id (which issues no request),
11
+ * or when the host's API cannot look apps up by id.
12
+ */
13
+ export declare function useEditorApp(id: string): AppSummary | undefined;
@@ -1,4 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
+ import { RailTool } from '../chrome/RightRail.tsx';
3
+ import { RailNavigation } from '../rail/rail-env.tsx';
2
4
  /** Where the host should take the user. The editor never touches a router: it asks. */
3
5
  export type WorkflowEditorNavigation = {
4
6
  type: "list";
@@ -31,4 +33,59 @@ export interface WorkflowEditorProps {
31
33
  /** Optional (a Next.js server component cannot pass a function); default is a no-op. */
32
34
  onNavigate?: (to: WorkflowEditorNavigation) => void;
33
35
  slots?: WorkflowEditorSlots;
36
+ /**
37
+ * Default `true`: the editor renders its own right rail. `false`: no rail is rendered; the editor
38
+ * publishes its policy/triggers into an enclosing `<CallableWorkspace>` (from `@w6w/embed/rail`)
39
+ * so a `<CallableRail>` placed elsewhere shows them. With no enclosing workspace it simply has no
40
+ * rail.
41
+ */
42
+ rail?: boolean;
43
+ }
44
+ /**
45
+ * Where a Function/Endpoint editor asks the host to go: back to the list, or (after a spec import
46
+ * from the rail) to the imported resource. The rail's own union, re-exported — no second one.
47
+ */
48
+ export type CallableEditorNavigation = RailNavigation;
49
+ /** The Function/Endpoint editors' slots — the same shape as the workflow editor's. */
50
+ export type CallableEditorSlots = WorkflowEditorSlots;
51
+ /** Props of `<EndpointEditor>` (`@w6w/embed/editors`). */
52
+ export interface EndpointEditorProps {
53
+ /** The Endpoint to edit (`ep_…`). */
54
+ endpointId: string;
55
+ /**
56
+ * The project the editor's expression scope and rail tools belong to. Omitted: the
57
+ * `<W6WEmbedProvider project>`. `null` or `""`: no project — rail tools refuse to save. An
58
+ * Endpoint's own save carries no project.
59
+ */
60
+ project?: string | null;
61
+ /** Optional (a Next.js server component cannot pass a function); default is a no-op. */
62
+ onNavigate?: (to: CallableEditorNavigation) => void;
63
+ slots?: CallableEditorSlots;
64
+ /**
65
+ * Default `true`: the editor renders its own right rail. `false`: no rail; the editor publishes
66
+ * its resource (invoke URL, inputs, policy and its writer) into an enclosing `<CallableWorkspace>`
67
+ * for the SAME endpoint id. Rail saves then use the WORKSPACE's `project`, not this `project`
68
+ * prop. With no enclosing workspace it simply has no rail.
69
+ */
70
+ rail?: boolean;
71
+ /** Replaces the rail's tool list (default: the editor rail tools). */
72
+ tools?: readonly RailTool[];
73
+ }
74
+ export interface FunctionEditorProps {
75
+ functionId: string;
76
+ /**
77
+ * Scopes the expression rail and the rail's storage key (a Function is account-scoped, so it is
78
+ * never a save precondition). Omitted: the `<W6WEmbedProvider project>`. `null` or `""`: none.
79
+ */
80
+ project?: string | null;
81
+ /** Optional (a Next.js server component cannot pass a function); default is a no-op. */
82
+ onNavigate?: (to: CallableEditorNavigation) => void;
83
+ slots?: CallableEditorSlots;
84
+ /**
85
+ * Default `true`: the editor renders its own right rail. `false`: none; the editor publishes into
86
+ * an enclosing `<CallableWorkspace kind="function" id>` for the SAME id.
87
+ */
88
+ rail?: boolean;
89
+ /** Replaces the rail's tools (default: the editor tools; no Aliases tool). */
90
+ tools?: readonly RailTool[];
34
91
  }
@@ -0,0 +1,95 @@
1
+ import { jsxs as F, Fragment as N, jsx as f } from "react/jsx-runtime";
2
+ import { h as O, i as _, e as R } from "./apps-1FNUwbGv.js";
3
+ import { H as g } from "./spec-import-CjmxyZDR.js";
4
+ import { ExecutionStats as j, ExecutionFilters as D, ExecutionList as L, ExecutionDetail as B, useW6WApi as K } from "@w6w/ui";
5
+ import { useRef as I, useState as S, useEffect as b, useCallback as V, useMemo as W } from "react";
6
+ import { useQuery as G } from "@tanstack/react-query";
7
+ const U = 300;
8
+ function ot(e) {
9
+ var x, q;
10
+ const { scope: n, showKind: a, filters: t, onFiltersChange: l, onOpenInEditor: u } = e, p = I(t);
11
+ p.current = t;
12
+ const [r, i] = S(t.q), c = I(null), [o, h] = S(null);
13
+ b(() => {
14
+ i(t.q);
15
+ }, [t.q]), b(
16
+ () => () => {
17
+ c.current && clearTimeout(c.current);
18
+ },
19
+ []
20
+ );
21
+ const d = O(n, t), v = _(n, t), m = R(o), y = ((x = d.data) == null ? void 0 : x.executions) ?? [], E = t.offset, C = ((q = d.data) == null ? void 0 : q.hasMore) ?? !1, M = (s) => {
22
+ l({ ...s, offset: 0 });
23
+ }, Q = (s) => {
24
+ if (s.q === r) {
25
+ M(s);
26
+ return;
27
+ }
28
+ i(s.q), c.current && clearTimeout(c.current), c.current = setTimeout(() => {
29
+ c.current = null, l({ ...p.current, q: s.q, offset: 0 });
30
+ }, U);
31
+ }, w = () => l({ ...t, q: r, offset: Math.max(0, E - g) }), A = () => l({ ...t, q: r, offset: E + g }), H = V(
32
+ (s) => {
33
+ h(y.find((T) => T.id === s) ?? null);
34
+ },
35
+ [y]
36
+ ), k = {
37
+ status: t.status,
38
+ kind: t.kind,
39
+ from: t.from,
40
+ to: t.to,
41
+ q: r
42
+ }, P = (o == null ? void 0 : o.kind) === "workflow" && u ? () => u(o) : void 0;
43
+ return /* @__PURE__ */ F(N, { children: [
44
+ /* @__PURE__ */ f(j, { stats: v.data ?? null }),
45
+ /* @__PURE__ */ f(D, { showKind: a, value: k, onChange: Q }),
46
+ d.isError && /* @__PURE__ */ f("p", { className: "error", "data-testid": "history-error", children: "Couldn't load execution history." }),
47
+ /* @__PURE__ */ f(
48
+ L,
49
+ {
50
+ items: y,
51
+ showCallable: a,
52
+ loading: d.isLoading,
53
+ selectedId: (o == null ? void 0 : o.id) ?? null,
54
+ hasPrev: E > 0,
55
+ hasNext: C,
56
+ onPrev: w,
57
+ onNext: A,
58
+ onSelect: H
59
+ }
60
+ ),
61
+ o && /* @__PURE__ */ f(
62
+ B,
63
+ {
64
+ execution: m.data ?? null,
65
+ loading: m.isLoading,
66
+ errorMessage: m.isError ? "This execution is no longer available." : void 0,
67
+ onClose: () => h(null),
68
+ onOpenInEditor: P
69
+ }
70
+ )
71
+ ] });
72
+ }
73
+ const Y = /* @__PURE__ */ new Map();
74
+ function Z(e) {
75
+ var r;
76
+ const n = K(), a = (r = n.listAppsByIds) == null ? void 0 : r.bind(n), t = [...e].sort().join(","), u = G({
77
+ queryKey: ["editor-apps", t],
78
+ queryFn: ({ signal: i }) => a ? a(e, { signal: i }) : Promise.resolve([]),
79
+ enabled: e.length > 0 && typeof a == "function"
80
+ }).data;
81
+ return { byId: W(
82
+ () => u ? new Map(u.map((i) => [i.id, i])) : Y,
83
+ [u]
84
+ ) };
85
+ }
86
+ function st(e) {
87
+ const { byId: n } = Z(e ? [e] : []);
88
+ return e ? n.get(e) : void 0;
89
+ }
90
+ export {
91
+ ot as H,
92
+ Z as a,
93
+ st as u
94
+ };
95
+ //# sourceMappingURL=editor-apps-BdenSV1o.js.map