@w6w/ui 0.2.0 → 0.2.54

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 (160) hide show
  1. package/CHANGELOG.md +146 -2
  2. package/README.md +28 -10
  3. package/dist/AppPicker.d.ts +58 -2
  4. package/dist/CanvasContextMenu.d.ts +19 -0
  5. package/dist/CanvasLayer.d.ts +38 -0
  6. package/dist/{CodeBlock-Dot3Pd7P.js → CodeBlock-C-oIIYfC.js} +1436 -555
  7. package/dist/CodeBlock-C-oIIYfC.js.map +1 -0
  8. package/dist/CodeBlock-CymlfyeA.cjs +15 -0
  9. package/dist/CodeBlock-CymlfyeA.cjs.map +1 -0
  10. package/dist/CodeEditor.d.ts +4 -1
  11. package/dist/ConditionEditor.d.ts +11 -0
  12. package/dist/EditConnectionModal.d.ts +6 -1
  13. package/dist/JsonEditor.d.ts +20 -0
  14. package/dist/Markdown.d.ts +25 -0
  15. package/dist/ParamCustomization.d.ts +5 -0
  16. package/dist/ParamsForm.d.ts +18 -4
  17. package/dist/RouterEditor.d.ts +5 -0
  18. package/dist/StepBuilderModal.d.ts +103 -15
  19. package/dist/StepNameEditor.d.ts +11 -0
  20. package/dist/StopEditor.d.ts +5 -0
  21. package/dist/TriggerFillForm.d.ts +14 -1
  22. package/dist/WebhookListenPanel.d.ts +28 -0
  23. package/dist/WorkflowConnections.d.ts +29 -0
  24. package/dist/WorkflowFlowEditor.d.ts +74 -7
  25. package/dist/app-pages.d.ts +2 -0
  26. package/dist/assets/script-completion.worker-DDJKkj5M.js +8290 -0
  27. package/dist/assets/script-completion.worker-DDJKkj5M.js.map +1 -0
  28. package/dist/canvas-context-menu.d.ts +27 -0
  29. package/dist/canvas-types.d.ts +36 -0
  30. package/dist/canvas-utils.d.ts +44 -0
  31. package/dist/code.cjs +1 -1
  32. package/dist/code.mjs +3 -4
  33. package/dist/code.mjs.map +1 -1
  34. package/dist/components/AnchoredFlyout.d.ts +7 -0
  35. package/dist/components/AuthFieldsForm.d.ts +11 -0
  36. package/dist/components/BudgetMeter.d.ts +15 -0
  37. package/dist/components/CallableList.d.ts +3 -2
  38. package/dist/components/ColumnsEditor.d.ts +27 -0
  39. package/dist/components/Combobox.d.ts +19 -1
  40. package/dist/components/ConnectionList.d.ts +2 -3
  41. package/dist/components/CredentialPicker.d.ts +35 -0
  42. package/dist/components/CsvPanel.d.ts +21 -0
  43. package/dist/components/DataEntryEditor.d.ts +38 -0
  44. package/dist/components/DataEntryList.d.ts +33 -0
  45. package/dist/components/DataStoreList.d.ts +33 -0
  46. package/dist/components/DataTable.d.ts +27 -0
  47. package/dist/components/DataTableGrid.d.ts +46 -0
  48. package/dist/components/EmptyState.d.ts +9 -0
  49. package/dist/components/EventbriteTriggerPicker.d.ts +7 -0
  50. package/dist/components/ExecutionDetail.d.ts +17 -1
  51. package/dist/components/ExecutionList.d.ts +19 -1
  52. package/dist/components/ExecutionLogPanel.d.ts +61 -3
  53. package/dist/components/ExpressionEditorModal.d.ts +33 -10
  54. package/dist/components/ExpressionOptions.d.ts +101 -15
  55. package/dist/components/HtmlPreview.d.ts +7 -0
  56. package/dist/components/JsonTree.d.ts +32 -0
  57. package/dist/components/ResolvedParams.d.ts +6 -1
  58. package/dist/components/ResultViewer.d.ts +46 -0
  59. package/dist/components/ScriptBindingsNotice.d.ts +31 -0
  60. package/dist/components/ScriptCodeField.d.ts +13 -0
  61. package/dist/components/StepStatusPill.d.ts +7 -0
  62. package/dist/components/expression-authoring.d.ts +13 -0
  63. package/dist/components/expression-dom.d.ts +17 -2
  64. package/dist/components/expression-template.d.ts +25 -3
  65. package/dist/components/icons.d.ts +1 -1
  66. package/dist/components/json-compose.d.ts +53 -0
  67. package/dist/components/result-format.d.ts +13 -0
  68. package/dist/condition-editor.d.ts +44 -0
  69. package/dist/data-stores/data-store-view.d.ts +371 -0
  70. package/dist/dynamic-fields.d.ts +60 -0
  71. package/dist/editor-theme.d.ts +24 -0
  72. package/dist/eventbrite-trigger-selection.d.ts +13 -0
  73. package/dist/flow-connect.d.ts +22 -16
  74. package/dist/flow-delete.d.ts +16 -0
  75. package/dist/flow-fanout.d.ts +2 -2
  76. package/dist/flow-history.d.ts +75 -0
  77. package/dist/flow-layout.d.ts +13 -0
  78. package/dist/flow-loop-colors.d.ts +39 -0
  79. package/dist/flow-loop.d.ts +98 -0
  80. package/dist/flow-node-flags.d.ts +14 -0
  81. package/dist/flow-problems.d.ts +69 -0
  82. package/dist/flow-state.d.ts +20 -0
  83. package/dist/flow-types.d.ts +155 -10
  84. package/dist/flow-utils.d.ts +33 -12
  85. package/dist/flow.cjs +4 -2
  86. package/dist/flow.cjs.map +1 -1
  87. package/dist/flow.d.ts +15 -2
  88. package/dist/flow.mjs +3737 -1350
  89. package/dist/flow.mjs.map +1 -1
  90. package/dist/index.cjs +2 -1
  91. package/dist/index.cjs.map +1 -1
  92. package/dist/index.d.ts +43 -5
  93. package/dist/index.mjs +2855 -1333
  94. package/dist/index.mjs.map +1 -1
  95. package/dist/node-samples-ChdyMBnJ.cjs +22 -0
  96. package/dist/node-samples-ChdyMBnJ.cjs.map +1 -0
  97. package/dist/node-samples-DkJL07EX.js +12302 -0
  98. package/dist/node-samples-DkJL07EX.js.map +1 -0
  99. package/dist/node-samples.d.ts +80 -0
  100. package/dist/note-markdown.d.ts +22 -0
  101. package/dist/output-shape.d.ts +30 -14
  102. package/dist/param-customization.d.ts +7 -0
  103. package/dist/provider.d.ts +174 -13
  104. package/dist/resolve-params.d.ts +50 -11
  105. package/dist/run-visuals.d.ts +18 -22
  106. package/dist/script-bindings.d.ts +63 -0
  107. package/dist/script-completion-service.d.ts +9 -0
  108. package/dist/script-completion.worker.d.ts +1 -0
  109. package/dist/script-completions.d.ts +2 -0
  110. package/dist/state-shape.d.ts +38 -0
  111. package/dist/step-preview-state.d.ts +155 -6
  112. package/dist/step-problems.d.ts +64 -0
  113. package/dist/test-inputs.d.ts +25 -0
  114. package/dist/trigger-registration.d.ts +28 -0
  115. package/dist/types.d.ts +179 -11
  116. package/dist/use-app-action-defs.d.ts +9 -1
  117. package/dist/use-dynamic-fields.d.ts +23 -0
  118. package/dist/use-test-input.d.ts +18 -0
  119. package/dist/workflow-connections.d.ts +30 -0
  120. package/package.json +18 -7
  121. package/src/code.css +60 -6
  122. package/src/styles/_budget-meter.scss +46 -0
  123. package/src/styles/_callable-list.scss +15 -6
  124. package/src/styles/_canvas.scss +353 -0
  125. package/src/styles/_code-editor.scss +35 -0
  126. package/src/styles/_code.scss +6 -5
  127. package/src/styles/_connections.scss +2 -14
  128. package/src/styles/_copyable.scss +24 -0
  129. package/src/styles/_data-stores.scss +138 -0
  130. package/src/styles/_data-table.scss +55 -0
  131. package/src/styles/_data-vars.scss +17 -6
  132. package/src/styles/_empty-state.scss +21 -0
  133. package/src/styles/_execution-history.scss +73 -0
  134. package/src/styles/_execution-log.scss +145 -1
  135. package/src/styles/_expression-modal.scss +106 -16
  136. package/src/styles/_fields.scss +11 -0
  137. package/src/styles/_flow.scss +171 -0
  138. package/src/styles/_fx.scss +26 -1
  139. package/src/styles/_incoming-state.scss +33 -0
  140. package/src/styles/_layout.scss +10 -0
  141. package/src/styles/_markdown.scss +20 -0
  142. package/src/styles/_modal.scss +12 -0
  143. package/src/styles/_multiselect.scss +35 -0
  144. package/src/styles/_sections.scss +36 -0
  145. package/src/styles/_step-builder.scss +145 -0
  146. package/src/styles/_tester.scss +57 -14
  147. package/src/styles/_tokens.scss +27 -1
  148. package/src/styles.css +1861 -115
  149. package/src/styles.scss +7 -0
  150. package/dist/CodeBlock-CZu4TFSi.cjs +0 -15
  151. package/dist/CodeBlock-CZu4TFSi.cjs.map +0 -1
  152. package/dist/CodeBlock-Dot3Pd7P.js.map +0 -1
  153. package/dist/ConfirmModal-ChoiGy2K.cjs +0 -11
  154. package/dist/ConfirmModal-ChoiGy2K.cjs.map +0 -1
  155. package/dist/ConfirmModal-Wx3i8F1n.js +0 -6359
  156. package/dist/ConfirmModal-Wx3i8F1n.js.map +0 -1
  157. package/dist/Copyable-1niV9gUa.js +0 -771
  158. package/dist/Copyable-1niV9gUa.js.map +0 -1
  159. package/dist/Copyable-CYZU1o4X.cjs +0 -2
  160. package/dist/Copyable-CYZU1o4X.cjs.map +0 -1
@@ -0,0 +1,63 @@
1
+ /**
2
+ * `{{ }}` inside a Run script's CODE. The host never templates `@w6w/script`'s `code` (the
3
+ * engine's `LITERAL_PARAMS`, node-types RFC amendment 2026-10-30): a marker typed into the code
4
+ * reaches the sandbox as literal text — `'{{ nodes.a.output.total }}'` is that exact string at
5
+ * run time, never the value. JavaScript/TypeScript insert `$.get(root, ...keys)` reads;
6
+ * Python inserts `ctx.get(root, *keys)` reads. Existing globals remain supported.
7
+ *
8
+ * {@link findCodeBindings} finds the markers that would run (strings and code, not comments),
9
+ * {@link codeReadFor} spells one reference as that code read, and
10
+ * {@link convertCodeBindingsToReads} rewrites every convertible marker in a script — what the
11
+ * step editor does when a script opens, behind a visible note with Undo.
12
+ */
13
+ export type ScriptLanguage = "javascript" | "typescript" | "python";
14
+ /** Where a marker sits: plain code, or inside a string literal of the given quote. */
15
+ type Context = {
16
+ kind: "code";
17
+ } | {
18
+ kind: "string";
19
+ quote: string;
20
+ start: number;
21
+ end: number;
22
+ };
23
+ export interface CodeBinding {
24
+ /** Offset of the `{{` in the code. */
25
+ start: number;
26
+ /** Offset just past the `}}`. */
27
+ end: number;
28
+ /** The marker's inner text, trimmed — what Input binds (`{{ <ref> }}`). */
29
+ ref: string;
30
+ context: Context;
31
+ }
32
+ /**
33
+ * Every `{{ … }}` in `code` that is not inside a comment, with the string literal (if any)
34
+ * around it. A small scanner, not a parser: it tracks `'…'`, `"…"` (and, in JavaScript,
35
+ * `` `…` ``; in Python, triple quotes) and the language's comments, which is what deciding
36
+ * "would this marker run" needs.
37
+ */
38
+ export declare function findCodeBindings(code: string, language?: ScriptLanguage): CodeBinding[];
39
+ /**
40
+ * Turn a reference into `$.get(root, ...keys)` (JavaScript/TypeScript) or
41
+ * `ctx.get(root, *keys)` (Python). Unsupported roots (secrets, documents, Function inputs)
42
+ * and non-path expressions return null. State always means the state tree without run aliases.
43
+ */
44
+ export declare function codeReadFor(ref: string, language?: ScriptLanguage): string | null;
45
+ export interface ConvertResult {
46
+ code: string;
47
+ /** Markers rewritten to code reads. */
48
+ converted: number;
49
+ /** Markers left as they were: not a readable reference, or inside a string they can't leave. */
50
+ left: number;
51
+ }
52
+ /**
53
+ * Rewrite each running `{{ ref }}` in `code` to the code read {@link codeReadFor} gives:
54
+ * - a marker that IS a whole string literal (`'{{ ref }}'`) becomes the read, keeping the
55
+ * value's type;
56
+ * - a bare marker in code becomes the read;
57
+ * - inside a JavaScript template literal it becomes `${read}`;
58
+ * - inside a longer `'…'`/`"…"` string it is spliced in by concatenation (`str(read)` in Python);
59
+ * - anything else (a Python triple-quoted or prefixed string, a reference with no code read) is
60
+ * left as it was and counted in `left`.
61
+ */
62
+ export declare function convertCodeBindingsToReads(code: string, language?: ScriptLanguage): ConvertResult;
63
+ export {};
@@ -0,0 +1,9 @@
1
+ export interface ScriptSuggestion {
2
+ label: string;
3
+ type: string;
4
+ }
5
+ /** Virtual files only: no evaluation of user code, filesystem, or network access. */
6
+ export declare function createScriptCompletionService(libraries: Record<string, string>): {
7
+ complete(code: string, position: number): ScriptSuggestion[];
8
+ dispose: () => void;
9
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ /** Per-editor lazy worker; compiling suggestions never blocks typing or runs the script. */
2
+ export declare function scriptCompletions(): import('@codemirror/state').Extension[];
@@ -0,0 +1,38 @@
1
+ import { Edge } from '@xyflow/react';
2
+ import { ExpressionStateField } from './components/ExpressionOptions.tsx';
3
+ import { FlowWorkflow } from './flow-types.ts';
4
+ import { StepNode } from './flow-utils.ts';
5
+ import { StepShapeContext } from './step-preview-state.ts';
6
+ /** The merged state at one anchor node. */
7
+ export interface StateShape {
8
+ /** Every field path of the merged tree (depth/count capped like a step's output fields). */
9
+ fields: ExpressionStateField[];
10
+ /**
11
+ * Preview values keyed by the ref the picker inserts (`state.<path>`), from REAL values only
12
+ * (test outputs, the app's `sample`, starting data, variable defaults) — never a skeleton.
13
+ */
14
+ sampleValues: Record<string, unknown>;
15
+ }
16
+ export interface StateShapeInput {
17
+ /** The node whose incoming state this is (`null` → empty shape). */
18
+ anchorId: string | null | undefined;
19
+ nodes: StepNode[];
20
+ edges: Edge[];
21
+ initialState?: FlowWorkflow["initialState"];
22
+ variables?: FlowWorkflow["variables"];
23
+ /** The same shape context the picker's "Previous steps" projection reads. */
24
+ shapes?: StepShapeContext;
25
+ /** Each node's REAL output (fresh test, else persisted), for preview values. */
26
+ previewOutputs?: Record<string, unknown>;
27
+ }
28
+ /**
29
+ * The engine's run order over `nodes`/`edges`: Kahn's, the ready queue seeded in declared node
30
+ * order, successors released in declared edge order. Nodes a cycle leaves out follow in declared
31
+ * order (the engine refuses such a plan; the editor still has to show something).
32
+ */
33
+ export declare function stateWriteOrder(nodes: StepNode[], edges: Edge[]): string[];
34
+ /**
35
+ * The merged state shape a node reads — see the file header. Empty (no fields) when nothing on
36
+ * any path into `anchorId` writes state and there is no starting data or variable.
37
+ */
38
+ export declare function computeStateShape(input: StateShapeInput): StateShape;
@@ -1,8 +1,10 @@
1
1
  import { Edge } from '@xyflow/react';
2
- import { ExpressionStepSource } from './components/ExpressionOptions.tsx';
2
+ import { ExpressionFieldSource, ExpressionLoopSource, ExpressionStepSource } from './components/ExpressionOptions.tsx';
3
3
  import { StepNode } from './flow-utils.ts';
4
- import { ActionShapeDef } from './output-shape.ts';
4
+ import { ActionShapeDef, OutputShapeSource } from './output-shape.ts';
5
5
  import { StepMeta, StepStartState, StepTest } from './provider.tsx';
6
+ import { SubscriptionSummary } from './types.ts';
7
+ import { FlowConnections } from './workflow-connections.ts';
6
8
  /**
7
9
  * What the editor knows about upstream steps' output SHAPES beyond the static
8
10
  * `internalNodeDef(...).output` — both optional, so a caller without them gets
@@ -15,8 +17,20 @@ export interface StepShapeContext {
15
17
  * no "run a test" claim it might have to retract a moment later.
16
18
  */
17
19
  actionDef?: (app: string, action: string) => ActionShapeDef | undefined;
18
- /** Each step's latest saved test-run output, by step id. */
20
+ /**
21
+ * An app TRIGGER's definition (its declared `output` / `sample`), same "undefined = not
22
+ * loaded, no claim" semantics as `actionDef`. Feeds `trigger.event.<key>`.
23
+ */
24
+ triggerDef?: (app: string, trigger: string) => ActionShapeDef | undefined;
25
+ /** Each step's FRESH test-run output (this session), by step id. */
19
26
  testOutputs?: Record<string, unknown>;
27
+ /**
28
+ * Each step's PERSISTED test output (server-side `node_samples`), by step id. A SEPARATE
29
+ * input from `testOutputs` so the tiers stay visible; fresh beats persisted.
30
+ */
31
+ persistedOutputs?: Record<string, unknown>;
32
+ /** Each For each's saved Test sample (`foreachTestSample`), by step id — the item-shape fallback. */
33
+ loopSamples?: Record<string, unknown[]>;
20
34
  }
21
35
  /** A graph ancestor carrying a saved step-test, offered as a one-click seed. */
22
36
  export interface SeedSource {
@@ -35,7 +49,41 @@ export interface SeedSource {
35
49
  interface PendingConnect {
36
50
  nodeId: string;
37
51
  handleType: "source" | "target";
52
+ /** The lane the drag came off (WFE's `pendingConnect` carries it). */
53
+ lane?: "success" | "error" | "each";
38
54
  }
55
+ /**
56
+ * Every node id that is a graph ancestor of `rootId` — walks `edges` backward. Exported for
57
+ * `state-shape.ts` (which imports this module, never the reverse).
58
+ */
59
+ export declare function ancestorIds(rootId: string, edges: Edge[]): Set<string>;
60
+ /**
61
+ * The array a For each's `items` resolves to at design time, or `undefined`.
62
+ * A whole-value ref (`{{ nodes.x.output.tickets }}` / `{ "$": … }`) resolves through
63
+ * `resolve-params.ts` against the saved test outputs; a literal array is returned as-is;
64
+ * anything else (a non-array result, a multipart template, a missing ref) is `undefined`.
65
+ */
66
+ export declare function resolveLoopItems(items: unknown, testOutputs: Record<string, unknown>): unknown[] | undefined;
67
+ /**
68
+ * {@link resolveLoopItems} against a whole Test start state (`startStateFromSeeds`), so a
69
+ * For each's own Test resolves `items` exactly as the other steps' Test previews do — a
70
+ * `trigger.event` ref included.
71
+ */
72
+ export declare function resolveLoopItemsInState(items: unknown, state: StepStartState | undefined): unknown[] | undefined;
73
+ /** How many items a For each's saved Test keeps: enough for the shape, never the whole list. */
74
+ export declare const FOREACH_TEST_SAMPLE_MAX = 10;
75
+ /**
76
+ * The step-test fixture a For each's Test saves. Nothing runs, so no run is recorded and
77
+ * `lastRunOutput` stays empty — the For each's real output is its BODY's results, and an
78
+ * after-loop step must not preview (or be seeded with) the input list as that. The sample
79
+ * rides in the fixture's `with` instead: the resolved `items` (capped) and the full count.
80
+ */
81
+ export declare function foreachTestFixture(items: unknown[], input: Record<string, unknown>): {
82
+ input: Record<string, unknown>;
83
+ with: Record<string, unknown>;
84
+ };
85
+ /** The sample a For each's saved Test carries (`foreachTestFixture`), or `undefined`. */
86
+ export declare function foreachTestSample(test: StepTest | null | undefined): unknown[] | undefined;
39
87
  /**
40
88
  * The workflow state a given step can reference: the outputs of every step
41
89
  * that runs before it (its graph ancestors) plus whether a trigger precedes
@@ -77,9 +125,19 @@ interface PendingConnect {
77
125
  *
78
126
  * With no specific step (shouldn't happen for a field edit) every node is offered.
79
127
  */
80
- export declare function upstreamStateSources(editingId: string | null, nodes: StepNode[], edges: Edge[], shapes?: StepShapeContext): {
128
+ export declare function upstreamStateSources(editingId: string | null, nodes: StepNode[], edges: Edge[], shapes?: StepShapeContext, draftId?: string | null): {
81
129
  steps: ExpressionStepSource[];
82
130
  hasTrigger: boolean;
131
+ /** Present iff the anchor step is a loop-body member. */
132
+ loop?: ExpressionLoopSource;
133
+ /**
134
+ * Saved tests the projection reads beyond `steps`: an after-loop For each's last body step,
135
+ * and the enclosing For each itself (its Test's item sample).
136
+ */
137
+ extraSampleIds?: string[];
138
+ /** An app trigger ancestor's declared `trigger.event.<key>` fields. */
139
+ eventOutputs?: ExpressionFieldSource[];
140
+ eventOutputsFrom?: OutputShapeSource;
83
141
  };
84
142
  /**
85
143
  * The new add-step wizard's graph ancestors, derived from `pendingConnect` —
@@ -98,6 +156,8 @@ export declare function upstreamStateSources(editingId: string | null, nodes: St
98
156
  * {@link upstreamStateSources} uses.
99
157
  */
100
158
  export declare function stepBuilderUpstreamSteps(pendingConnect: PendingConnect | null, nodes: StepNode[], edges: Edge[], shapes?: StepShapeContext): ExpressionStepSource[];
159
+ /** The `loop` source for the add-step builder's new step — the same decision as its rail. */
160
+ export declare function stepBuilderLoop(pendingConnect: PendingConnect | null, nodes: StepNode[], edges: Edge[], shapes?: StepShapeContext): ExpressionLoopSource | undefined;
101
161
  /**
102
162
  * Gather each graph ancestor's latest saved step-test so the incoming-state
103
163
  * control can offer it as a seed. **One implementation**, called by every
@@ -133,11 +193,100 @@ export declare function fetchSeedSources(listStepTests: (stepId: string) => Prom
133
193
  * ⚠️ Single-step scope only. A full run (`POST /workflows/:id/run`) builds its
134
194
  * own scope and is not affected by this.
135
195
  */
136
- export declare function startStateFromSeeds(seeds: SeedSource[]): StepStartState | undefined;
196
+ export declare function startStateFromSeeds(seeds: SeedSource[], loop?: {
197
+ item?: unknown;
198
+ index?: number;
199
+ }): StepStartState | undefined;
200
+ /** The default `{ item, index }` a loop-body Test is seeded with: the sample item, index 0. */
201
+ export declare function loopSeedFromSource(loop: ExpressionLoopSource | undefined): {
202
+ item?: unknown;
203
+ index?: number;
204
+ } | undefined;
205
+ /** The editable "Current item" text a loop's sample item starts as (`""` when there is none). */
206
+ export declare function loopItemText(loop: ExpressionLoopSource | undefined): string;
207
+ /**
208
+ * Parse the loop seed control's two fields. A blank item means "no item"; a blank index means 0.
209
+ * Invalid item JSON, or an index that is not a non-negative integer, is an ERROR — the caller
210
+ * refuses the run rather than falling back to the sample.
211
+ */
212
+ export declare function parseLoopSeed(itemText: string, indexText: string): {
213
+ ok: true;
214
+ value: {
215
+ item?: unknown;
216
+ index: number;
217
+ };
218
+ } | {
219
+ ok: false;
220
+ error: string;
221
+ };
137
222
  /**
138
- * Sample values for a step's `steps.<id>.meta.*` refs, from a saved fixture's
223
+ * Sample values for a step's `nodes.<id>.meta.*` refs (and the `steps.` alias), from a saved fixture's
139
224
  * `lastRunMeta`. Reads the four named fields only; absent meta yields nothing
140
225
  * (a version or connection is never derived from anywhere else).
141
226
  */
142
227
  export declare function stepMetaSampleValues(stepId: string, meta: StepMeta | null | undefined): Record<string, unknown>;
228
+ /**
229
+ * The flat `sampleValues` the expression editor's Result preview reads: each upstream step's
230
+ * last test output on the very refs the picker inserts (`nodes.<id>.output`, `.output.<key>`,
231
+ * each offered nested path), mirrored under `steps.` (the compat alias), plus metadata and,
232
+ * for a loop-body step, `foreach.item` / `foreach.item.<key>` / `foreach.index` (= 0, the
233
+ * sample element's position). Lives here (not in WFE) so a render test can drive it.
234
+ */
235
+ export declare function upstreamSampleValues(steps: ExpressionStepSource[], testOutputs: Record<string, unknown>, testMetas: Record<string, StepMeta>, loop?: ExpressionLoopSource, tiers?: SampleTiers): Record<string, unknown>;
236
+ /**
237
+ * The lower tiers of preview values, beside the fresh `testOutputs`: the PERSISTED test
238
+ * outputs and the app's declared `sample`s (by step id; `event` is an app trigger's sample,
239
+ * read as `trigger.event`). Precedence per ref: fresh > persisted > sample.
240
+ */
241
+ export interface SampleTiers {
242
+ persisted?: Record<string, unknown>;
243
+ samples?: Record<string, unknown>;
244
+ event?: unknown;
245
+ }
246
+ /** Which tier each value in {@link upstreamSampleValues} came from, keyed by the same ref. */
247
+ export declare function upstreamSampleValueSources(steps: ExpressionStepSource[], testOutputs: Record<string, unknown>, testMetas: Record<string, StepMeta>, loop?: ExpressionLoopSource, tiers?: SampleTiers): Record<string, "fresh" | "persisted" | "sample">;
248
+ /**
249
+ * The declared `sample` of each app step (by id) and of an app trigger (as the event
250
+ * sample), read through `shapes.actionDef` / `triggerDef`. An `output`-only definition
251
+ * contributes nothing: no placeholders are fabricated.
252
+ */
253
+ export declare function declaredSamples(nodes: StepNode[], shapes: StepShapeContext): {
254
+ samples: Record<string, unknown>;
255
+ event?: unknown;
256
+ };
257
+ /**
258
+ * Each node's configuration keys for the picker's "Node settings" group — what the engine lays
259
+ * at `nodes.<id>.config` (`nodeConfigOf`): the step's literal `with` keys (never a secret, never a
260
+ * binding), plus `url` for a webhook trigger node (the host adds it from the node's subscription).
261
+ * A node with none is left out.
262
+ */
263
+ export declare function nodeConfigSources(nodes: StepNode[]): {
264
+ id: string;
265
+ keys: string[];
266
+ }[];
267
+ /**
268
+ * Each node's configuration VALUES — the client's `nodeConfigOf`: the step's static `with`
269
+ * (sealed secrets and bindings dropped, so nothing sealed ever reaches a preview) with a webhook
270
+ * trigger node's `url` laid over it from the workflow's subscriptions, picked as the server's
271
+ * `hostNodeConfig` picks it (the one bound to the node, else for a `@w6w/webhook` node the newest
272
+ * webhook subscription). A node with nothing to configure is absent.
273
+ */
274
+ export declare function nodeConfigValues(nodes: StepNode[], subs: readonly SubscriptionSummary[]): Record<string, Record<string, unknown>>;
275
+ /**
276
+ * Each node's static metadata VALUES — the client's `nodeMetaOf`: `app`, `action` and
277
+ * `connectionId` (the node's own connection, else `null`) from the definition, plus a webhook
278
+ * trigger node's `subscriptionId` and `url` from its subscription ({@link subscriptionFor}), and
279
+ * `version` from `apps` — the same summary the canvas labels the node with (`<id> - v<version>`),
280
+ * i.e. the version it will dispatch. Readable at `nodes.<id>.meta.<key>` whether or not the node
281
+ * ran; a run's reported meta overrides it. An app with no known version has no `version` (the
282
+ * previews then say "resolved at run"). A node with no app is absent.
283
+ */
284
+ export declare function nodeMetaValues(nodes: StepNode[], subs: readonly SubscriptionSummary[], apps?: ReadonlyMap<string, {
285
+ version?: string;
286
+ }>, connections?: FlowConnections): Record<string, Record<string, unknown>>;
287
+ /**
288
+ * {@link nodeMetaValues} as the flat `sampleValues` the Result preview reads, on the refs the
289
+ * picker inserts (`nodes.<id>.meta.<key>`, mirrored under `steps.`).
290
+ */
291
+ export declare function nodeMetaSampleValues(meta: Record<string, Record<string, unknown>>): Record<string, unknown>;
143
292
  export {};
@@ -0,0 +1,64 @@
1
+ import { LoopInvalid } from './flow-loop.ts';
2
+ /** A one-click fix: pure data, applied by `applyStepProblemFix` on the author's click. */
3
+ export type StepProblemFix = {
4
+ kind: "unwrap_items";
5
+ label: "Unwrap Items";
6
+ } | {
7
+ kind: "use_current_item";
8
+ foreachId: string;
9
+ label: "Use Current item";
10
+ };
11
+ export type StepProblem = {
12
+ code: "unknown_connection";
13
+ connection: string;
14
+ } | {
15
+ code: "foreach_wrapped_items";
16
+ fix: StepProblemFix;
17
+ } | {
18
+ code: "foreach_body_refs_output";
19
+ foreachId: string;
20
+ refs: string[];
21
+ fix: StepProblemFix;
22
+ } | {
23
+ code: "loop_body_invalid";
24
+ reason: LoopInvalid;
25
+ }
26
+ /** Writes a state path that a step running at the same time (`with`) also writes (`findStateWriteProblems`). */
27
+ | {
28
+ code: "state_parallel_write";
29
+ path: string[];
30
+ with: string[];
31
+ }
32
+ /** The saved workflow still lacks setup (unbound alias, empty store, missing var/secret/constant); `items` name what. */
33
+ | {
34
+ code: "setup_incomplete";
35
+ items: string[];
36
+ };
37
+ /** Keyed by step id; a step carries every problem it has (D-B1). */
38
+ export type StepProblems = Record<string, StepProblem[]>;
39
+ interface ProblemNode {
40
+ id: string;
41
+ data: {
42
+ stepProblems?: StepProblem[];
43
+ };
44
+ }
45
+ /**
46
+ * Stamp `data.stepProblems` from `problems`, clearing it for steps no longer in
47
+ * the map (or mapped to `[]`). Returns the SAME node object when the incoming
48
+ * list deep-equals the stamped one.
49
+ */
50
+ export declare function applyStepProblems<N extends ProblemNode>(nodes: N[], problems: StepProblems | undefined): N[];
51
+ export declare function stepProblemTooltip(p: StepProblem): string;
52
+ /** True while the step still points at a connection the host reports missing (any entry). */
53
+ export declare function isConnectionBlocked(step: {
54
+ uses: {
55
+ connection?: string | null;
56
+ };
57
+ }, problems: StepProblem[] | undefined): boolean;
58
+ /** The Setup tab's Connection button label — exactly five outcomes. */
59
+ export declare function connectionButtonLabel(connection: string | undefined | null, conns: {
60
+ id: string;
61
+ displayName?: string;
62
+ builtIn?: boolean;
63
+ }[] | null, failed: boolean): string;
64
+ export {};
@@ -0,0 +1,25 @@
1
+ import { ActionParam } from './types.ts';
2
+ /** One remembered input (`GET /workflows/:id/test-inputs` → `testInputs[]`). */
3
+ export interface NodeTestInput {
4
+ nodeId: string;
5
+ input: Record<string, unknown>;
6
+ /** ISO timestamp of the write. */
7
+ updatedAt: string;
8
+ }
9
+ /**
10
+ * The remembered input of `nodeId`: `undefined` when the node has no row (the
11
+ * caller may fall back to an older source, e.g. the latest step-test fixture),
12
+ * `{}` when it was CLEARED (stay on the declared defaults), else the values.
13
+ */
14
+ export declare function findTestInput(rows: readonly NodeTestInput[] | undefined, nodeId: string): Record<string, unknown> | undefined;
15
+ /**
16
+ * What may be remembered of `values`: a literal typed into a `secret` param is
17
+ * DROPPED (it must never be persisted in plain text — the operator re-enters
18
+ * it), a binding to a secret is kept as the expression, and a sealed envelope
19
+ * is dropped anywhere at the top level (the server strips nested ones too).
20
+ */
21
+ export declare function rememberableInput(values: Record<string, unknown>, params?: readonly ActionParam[]): Record<string, unknown>;
22
+ /** Track `save` until it settles (it never rejects into the tracker). Returns `save`. */
23
+ export declare function trackTestInputSave<T>(save: Promise<T>): Promise<T>;
24
+ /** Resolves once every remembered-input save issued so far has settled (never rejects). */
25
+ export declare function testInputSavesSettled(): Promise<void>;
@@ -0,0 +1,28 @@
1
+ import { SubscriptionSummary } from './types.ts';
2
+ export type RegistrationTone = "ok" | "pending" | "danger" | "muted";
3
+ export interface RegistrationDisplay {
4
+ label: string;
5
+ tone: RegistrationTone;
6
+ /** `lastError.message`, only for a failed subscription that carries one. */
7
+ error: string | null;
8
+ /** Always set: a distinct "never fired" text when `lastFireAt` is null/absent/unparseable. */
9
+ lastFire: string;
10
+ /** True iff the subscription is `failed` AND the host can retry. */
11
+ retryVisible: boolean;
12
+ }
13
+ export declare const NEVER_FIRED = "Never fired";
14
+ /** UTC, minute precision, so the text is stable across locales and test hosts. */
15
+ export declare function formatLastFire(iso: string | null | undefined): string;
16
+ /** Null when the summary has no known status (older server): the node shows no badge. */
17
+ export declare function registrationDisplay(sub: SubscriptionSummary | undefined, canRetry: boolean): RegistrationDisplay | null;
18
+ /** nodeId -> subscription for the node-bound ones (a null `nodeId` is workflow-level). */
19
+ export declare function subscriptionsByNode(subs: readonly SubscriptionSummary[]): Map<string, SubscriptionSummary>;
20
+ /**
21
+ * The app trigger nodes of a workflow value. Total over a value that has no `nodes` yet
22
+ * (embed mounts pass a partial value): an absent list is no trigger nodes.
23
+ */
24
+ export declare function appTriggerNodesOf<N extends {
25
+ uses?: {
26
+ trigger?: boolean;
27
+ };
28
+ }>(nodes: readonly N[] | null | undefined): N[];