@w6w/ui 0.2.11 → 0.2.55

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 (138) hide show
  1. package/CHANGELOG.md +139 -2
  2. package/README.md +28 -10
  3. package/dist/AppPicker.d.ts +12 -1
  4. package/dist/CanvasContextMenu.d.ts +19 -0
  5. package/dist/{CodeBlock-BqXDA35P.js → CodeBlock-C-oIIYfC.js} +1436 -555
  6. package/dist/CodeBlock-C-oIIYfC.js.map +1 -0
  7. package/dist/CodeBlock-CymlfyeA.cjs +15 -0
  8. package/dist/CodeBlock-CymlfyeA.cjs.map +1 -0
  9. package/dist/CodeEditor.d.ts +4 -1
  10. package/dist/ConditionEditor.d.ts +11 -0
  11. package/dist/JsonEditor.d.ts +12 -0
  12. package/dist/ParamCustomization.d.ts +5 -0
  13. package/dist/ParamsForm.d.ts +11 -3
  14. package/dist/RouterEditor.d.ts +5 -0
  15. package/dist/StepBuilderModal.d.ts +83 -13
  16. package/dist/StepNameEditor.d.ts +11 -0
  17. package/dist/StopEditor.d.ts +5 -0
  18. package/dist/TriggerFillForm.d.ts +14 -1
  19. package/dist/WebhookListenPanel.d.ts +28 -0
  20. package/dist/WorkflowConnections.d.ts +29 -0
  21. package/dist/WorkflowConnectionsPanel.d.ts +5 -0
  22. package/dist/WorkflowFlowEditor.d.ts +67 -8
  23. package/dist/assets/script-completion.worker-DDJKkj5M.js +8290 -0
  24. package/dist/assets/script-completion.worker-DDJKkj5M.js.map +1 -0
  25. package/dist/canvas-context-menu.d.ts +27 -0
  26. package/dist/code.cjs +1 -1
  27. package/dist/code.mjs +3 -4
  28. package/dist/code.mjs.map +1 -1
  29. package/dist/components/AnchoredFlyout.d.ts +7 -0
  30. package/dist/components/ColumnsEditor.d.ts +27 -0
  31. package/dist/components/Combobox.d.ts +12 -1
  32. package/dist/components/ConfirmModal.d.ts +3 -1
  33. package/dist/components/CsvPanel.d.ts +21 -0
  34. package/dist/components/DataEntryEditor.d.ts +38 -0
  35. package/dist/components/DataEntryList.d.ts +33 -0
  36. package/dist/components/DataStoreList.d.ts +33 -0
  37. package/dist/components/DataTableGrid.d.ts +46 -0
  38. package/dist/components/EventbriteTriggerPicker.d.ts +7 -0
  39. package/dist/components/ExecutionDetail.d.ts +17 -1
  40. package/dist/components/ExecutionList.d.ts +19 -1
  41. package/dist/components/ExecutionLogPanel.d.ts +61 -3
  42. package/dist/components/ExpressionEditorModal.d.ts +33 -10
  43. package/dist/components/ExpressionOptions.d.ts +101 -15
  44. package/dist/components/HtmlPreview.d.ts +7 -0
  45. package/dist/components/JsonTree.d.ts +32 -0
  46. package/dist/components/ResolvedParams.d.ts +6 -1
  47. package/dist/components/ResultViewer.d.ts +46 -0
  48. package/dist/components/ScriptBindingsNotice.d.ts +31 -0
  49. package/dist/components/ScriptCodeField.d.ts +13 -0
  50. package/dist/components/StepStatusPill.d.ts +7 -0
  51. package/dist/components/expression-authoring.d.ts +13 -0
  52. package/dist/components/expression-dom.d.ts +17 -2
  53. package/dist/components/expression-template.d.ts +25 -3
  54. package/dist/components/icons.d.ts +1 -1
  55. package/dist/components/json-compose.d.ts +53 -0
  56. package/dist/components/result-format.d.ts +13 -0
  57. package/dist/condition-editor.d.ts +44 -0
  58. package/dist/connection-app-meta-BEXlKBgV.cjs +22 -0
  59. package/dist/connection-app-meta-BEXlKBgV.cjs.map +1 -0
  60. package/dist/connection-app-meta-ZCPakGjD.js +12422 -0
  61. package/dist/connection-app-meta-ZCPakGjD.js.map +1 -0
  62. package/dist/data-stores/data-store-view.d.ts +371 -0
  63. package/dist/eventbrite-trigger-selection.d.ts +13 -0
  64. package/dist/flow-connect.d.ts +22 -16
  65. package/dist/flow-delete.d.ts +16 -0
  66. package/dist/flow-history.d.ts +75 -0
  67. package/dist/flow-layout.d.ts +13 -0
  68. package/dist/flow-loop-colors.d.ts +39 -0
  69. package/dist/flow-loop.d.ts +98 -0
  70. package/dist/flow-node-flags.d.ts +14 -0
  71. package/dist/flow-problems.d.ts +69 -0
  72. package/dist/flow-state.d.ts +20 -0
  73. package/dist/flow-types.d.ts +137 -9
  74. package/dist/flow-utils.d.ts +27 -13
  75. package/dist/flow.cjs +4 -2
  76. package/dist/flow.cjs.map +1 -1
  77. package/dist/flow.d.ts +9 -3
  78. package/dist/flow.mjs +4028 -1585
  79. package/dist/flow.mjs.map +1 -1
  80. package/dist/index.cjs +2 -1
  81. package/dist/index.cjs.map +1 -1
  82. package/dist/index.d.ts +30 -4
  83. package/dist/index.mjs +2559 -1287
  84. package/dist/index.mjs.map +1 -1
  85. package/dist/node-samples.d.ts +80 -0
  86. package/dist/output-shape.d.ts +30 -14
  87. package/dist/param-customization.d.ts +7 -0
  88. package/dist/provider.d.ts +119 -7
  89. package/dist/resolve-params.d.ts +45 -11
  90. package/dist/run-visuals.d.ts +14 -21
  91. package/dist/script-bindings.d.ts +63 -0
  92. package/dist/script-completion-service.d.ts +9 -0
  93. package/dist/script-completion.worker.d.ts +1 -0
  94. package/dist/script-completions.d.ts +2 -0
  95. package/dist/state-shape.d.ts +38 -0
  96. package/dist/step-preview-state.d.ts +155 -6
  97. package/dist/step-problems.d.ts +42 -12
  98. package/dist/test-inputs.d.ts +25 -0
  99. package/dist/trigger-registration.d.ts +28 -0
  100. package/dist/types.d.ts +70 -8
  101. package/dist/use-app-action-defs.d.ts +9 -1
  102. package/dist/use-test-input.d.ts +18 -0
  103. package/dist/workflow-connections.d.ts +78 -0
  104. package/package.json +16 -7
  105. package/src/code.css +60 -6
  106. package/src/styles/_canvas.scss +35 -0
  107. package/src/styles/_code-editor.scss +35 -0
  108. package/src/styles/_code.scss +6 -5
  109. package/src/styles/_connections.scss +64 -0
  110. package/src/styles/_copyable.scss +24 -0
  111. package/src/styles/_data-stores.scss +138 -0
  112. package/src/styles/_data-vars.scss +17 -6
  113. package/src/styles/_execution-history.scss +73 -0
  114. package/src/styles/_execution-log.scss +145 -1
  115. package/src/styles/_expression-modal.scss +106 -16
  116. package/src/styles/_fields.scss +11 -0
  117. package/src/styles/_flow.scss +166 -0
  118. package/src/styles/_fx.scss +3 -1
  119. package/src/styles/_incoming-state.scss +33 -0
  120. package/src/styles/_modal.scss +12 -0
  121. package/src/styles/_multiselect.scss +35 -0
  122. package/src/styles/_sections.scss +36 -0
  123. package/src/styles/_step-builder.scss +145 -0
  124. package/src/styles/_tester.scss +56 -0
  125. package/src/styles/_tokens.scss +27 -1
  126. package/src/styles.css +1347 -41
  127. package/src/styles.scss +2 -0
  128. package/dist/CodeBlock-BqXDA35P.js.map +0 -1
  129. package/dist/CodeBlock-CulfbnZD.cjs +0 -15
  130. package/dist/CodeBlock-CulfbnZD.cjs.map +0 -1
  131. package/dist/ConfirmModal-Ln99S9NT.js +0 -7919
  132. package/dist/ConfirmModal-Ln99S9NT.js.map +0 -1
  133. package/dist/ConfirmModal-fjHW5rN-.cjs +0 -14
  134. package/dist/ConfirmModal-fjHW5rN-.cjs.map +0 -1
  135. package/dist/Copyable-DA6eiU7w.cjs +0 -2
  136. package/dist/Copyable-DA6eiU7w.cjs.map +0 -1
  137. package/dist/Copyable-F4NTaG77.js +0 -847
  138. package/dist/Copyable-F4NTaG77.js.map +0 -1
@@ -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 {};
@@ -1,34 +1,64 @@
1
- /**
2
- * Host-supplied per-step problems painted on the canvas. Pure — no React or
3
- * @xyflow imports. The host owns detection; ui never infers a problem itself.
4
- */
5
- export interface StepProblem {
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 = {
6
12
  code: "unknown_connection";
7
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[];
8
31
  }
9
- /** Keyed by step id. */
10
- export type StepProblems = Record<string, StepProblem>;
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[]>;
11
39
  interface ProblemNode {
12
40
  id: string;
13
41
  data: {
14
- stepProblem?: StepProblem;
42
+ stepProblems?: StepProblem[];
15
43
  };
16
44
  }
17
45
  /**
18
- * Stamp `data.stepProblem` from `problems`, clearing it for steps no longer in
19
- * the map. Returns the SAME node object when nothing changed.
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.
20
49
  */
21
50
  export declare function applyStepProblems<N extends ProblemNode>(nodes: N[], problems: StepProblems | undefined): N[];
22
51
  export declare function stepProblemTooltip(p: StepProblem): string;
23
- /** True while the step still points at the connection the host reports missing. */
52
+ /** True while the step still points at a connection the host reports missing (any entry). */
24
53
  export declare function isConnectionBlocked(step: {
25
54
  uses: {
26
55
  connection?: string | null;
27
56
  };
28
- }, problem: StepProblem | undefined): boolean;
57
+ }, problems: StepProblem[] | undefined): boolean;
29
58
  /** The Setup tab's Connection button label — exactly five outcomes. */
30
59
  export declare function connectionButtonLabel(connection: string | undefined | null, conns: {
31
60
  id: string;
32
61
  displayName?: string;
62
+ builtIn?: boolean;
33
63
  }[] | null, failed: boolean): string;
34
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[];
package/dist/types.d.ts CHANGED
@@ -1,8 +1,4 @@
1
- /**
2
- * Wire types the components consume. These mirror the shapes the w6w server
3
- * returns over HTTP. They are intentionally a local copy so consumers who
4
- * don't use `@w6w/types` (partners, non-TypeScript backends) don't need it.
5
- */
1
+ import { ParamWhen } from '@w6w/expr';
6
2
  /** Summary of a registered app as returned by GET /apps. */
7
3
  export interface AppSummary {
8
4
  id: string;
@@ -33,6 +29,8 @@ export interface AppSummary {
33
29
  * `packages/server/packages/api/wire-summary.ts`'s `zeroCredential`).
34
30
  */
35
31
  zeroCredential?: boolean;
32
+ /** Number of triggers the app declares (wire already carries it). */
33
+ triggerCount?: number;
36
34
  }
37
35
  /** One trigger an app declares, as returned by GET /apps/:id/triggers. */
38
36
  export interface TriggerSummary {
@@ -43,9 +41,15 @@ export interface TriggerSummary {
43
41
  description?: string;
44
42
  requiresAuth?: boolean;
45
43
  /** `"poll"` triggers are fetched on an interval; absent or `"webhook"` receive pushes. */
46
- type?: "webhook" | "poll";
44
+ type?: "webhook" | "poll" | "protocol";
47
45
  /** Host floor for a poll trigger's interval, in milliseconds. */
48
46
  minIntervalMs?: number;
47
+ /** The trigger's declared parameters (the route returns the full declaration). */
48
+ params?: readonly unknown[];
49
+ /** The event's declared fields (an `OutputField[]`) — keys for `trigger.event.<key>`. */
50
+ output?: unknown;
51
+ /** A representative event payload the app declares (never fabricated). */
52
+ sample?: unknown;
49
53
  }
50
54
  /** A Subscription (rfcs/trigger.md) as returned by the console subscription routes. */
51
55
  export interface SubscriptionSummary {
@@ -56,15 +60,43 @@ export interface SubscriptionSummary {
56
60
  connectionId: string | null;
57
61
  /** Present only for `appId === "@w6w/webhook"` — the server's own computed receive URL. */
58
62
  webhookUrl?: string;
59
- type?: "webhook" | "poll";
60
- status?: string;
63
+ type?: "webhook" | "poll" | "protocol";
64
+ status?: SubscriptionStatus;
61
65
  /** Poll interval in milliseconds; null for webhook subscriptions. */
62
66
  intervalMs?: number | null;
63
67
  lastError?: {
64
68
  code: string;
65
69
  message: string;
66
70
  } | null;
71
+ /** The workflow trigger node this subscription is bound to; null for a workflow-level one. */
72
+ nodeId?: string | null;
73
+ /** When registration with the app succeeded; null until it has. */
74
+ registeredAt?: string | null;
75
+ /** When the subscription last fired; null/absent when it never has. */
76
+ lastFireAt?: string | null;
77
+ }
78
+ /**
79
+ * A "Listen for test event" session on a `@w6w/webhook` subscription
80
+ * (`POST /subscriptions/:id/listen`). `request` is the captured, credential-masked call —
81
+ * exactly what a real run's webhook trigger emits as its output.
82
+ */
83
+ export interface WebhookListenSession {
84
+ id: string;
85
+ subscriptionId: string;
86
+ nodeId: string | null;
87
+ expiresAt: string;
88
+ status: "waiting" | "captured" | "expired";
89
+ request?: {
90
+ method: string;
91
+ path: string;
92
+ query: Record<string, string>;
93
+ headers: Record<string, string>;
94
+ body: unknown;
95
+ };
96
+ receivedAt?: string;
67
97
  }
98
+ /** Registration state of a Subscription (rfcs/trigger-protocol.md §Lifecycle). */
99
+ export type SubscriptionStatus = "pending" | "registered" | "failed" | "paused" | "destroying";
68
100
  /** One field on an Auth method's connection form. Drives the input widgets. */
69
101
  export interface AuthField {
70
102
  key: string;
@@ -94,6 +126,8 @@ export interface ActionParam {
94
126
  required?: boolean;
95
127
  default?: unknown;
96
128
  hint?: string;
129
+ /** Render hint; multiselect supports "checkboxes" or the default chip picker. */
130
+ ui?: string;
97
131
  /** Placeholder text for the input (e.g. the trailing prompt on a multiselect). */
98
132
  placeholder?: string;
99
133
  /**
@@ -102,6 +136,18 @@ export interface ActionParam {
102
136
  * params (they always show).
103
137
  */
104
138
  advanced?: boolean;
139
+ /**
140
+ * The field holds ONE value or expression, never a composed container: in the JSON-binding
141
+ * editor, picking a reference into an empty draft (or a bare `[]` / `{}`) stores the bare
142
+ * whole-value ref `"{{ ref }}"`, not `[ref]`. A literal still can be typed.
143
+ */
144
+ whole?: boolean;
145
+ /**
146
+ * The param is declared on the action but never rendered by any param form, and never gates
147
+ * the required check. Its stored value is preserved untouched (e.g. a canvas-owned `body`).
148
+ * Not the entry-level `InternalNodeDef.hidden` (a palette hide).
149
+ */
150
+ hidden?: boolean;
105
151
  /**
106
152
  * Lay this param out on a shared row with adjacent params carrying the same
107
153
  * `row` id — e.g. a username/password pair side by side.
@@ -122,6 +168,12 @@ export interface ActionParam {
122
168
  * (e.g. Basic-auth fields shown only when `auth` is `"basic"`).
123
169
  */
124
170
  showIf?: ParamCondition;
171
+ /**
172
+ * Conditional overlay: the first entry whose `if` holds overlays
173
+ * label/hint/required/ui/options onto this param (see `effectiveParam` in
174
+ * `@w6w/expr`). Mirrors `@w6w/types`' `Param.when`.
175
+ */
176
+ when?: ParamWhen<ParamOption[] | DynamicOptions>[];
125
177
  /**
126
178
  * Constrained choices. Renders as a single-select dropdown for `select` (or any
127
179
  * param with options), and as a multi-select pill picker for `multiselect`.
@@ -148,6 +200,14 @@ export interface ActionParam {
148
200
  layout?: "row" | "stack";
149
201
  /** `section: "collapsible"` only — start collapsed (default `true`). */
150
202
  collapsed?: boolean;
203
+ /** `section: "collapsible"` only — start open when any child already holds a value. */
204
+ openWhenSet?: boolean;
205
+ /**
206
+ * `type: "code"` only — a Run script's code, which reads run data from its `state` / `vars` /
207
+ * `consts` globals: its insert actions write code reads, never `{{ }}` (the host does not
208
+ * substitute in code).
209
+ */
210
+ scriptReads?: boolean;
151
211
  }
152
212
  /** A single choice for a param rendered as a dropdown. */
153
213
  export interface ParamOption {
@@ -221,6 +281,8 @@ export interface ParamConfig {
221
281
  multiline?: boolean;
222
282
  /** With options: accept a value not in the list (Combobox `forceSelection` off). */
223
283
  allowCustom?: boolean;
284
+ /** Multiselect storage format. Defaults to an array; CSV preserves string-based API inputs. */
285
+ valueFormat?: "array" | "csv";
224
286
  }
225
287
  /** Summary of an action an app exposes, as returned by GET /apps/:id. */
226
288
  export interface ActionDef {
@@ -1,7 +1,15 @@
1
1
  import { PortsLookup } from './flow-types.ts';
2
2
  import { StepNode } from './flow-utils.ts';
3
3
  import { W6WApi } from './provider.tsx';
4
- import { ActionDef } from './types.ts';
4
+ import { ActionDef, TriggerSummary } from './types.ts';
5
5
  export declare function useAppActionDefs(api: W6WApi, nodes: StepNode[]): Record<string, ActionDef[]>;
6
+ /**
7
+ * The trigger definitions of every app a workflow's APP-TRIGGER nodes (`uses.trigger === true`)
8
+ * use, so the editor can offer `trigger.event.<field>` from a trigger's declared `output` /
9
+ * `sample` without a run. Same shape as {@link useAppActionDefs}: fetched once per app id
10
+ * (`getAppTriggers`, optional on the api — absent means no claim), keyed on the sorted set of
11
+ * app ids, best-effort, a failed fetch retried by a later change.
12
+ */
13
+ export declare function useAppTriggerDefs(api: W6WApi, nodes: StepNode[]): Record<string, TriggerSummary[]>;
6
14
  /** Build a `PortsLookup` over the fetched catalog defs (`useAppActionDefs`' result). */
7
15
  export declare function portsLookupFromDefs(defs: Record<string, ActionDef[]>): PortsLookup;
@@ -0,0 +1,18 @@
1
+ import { ActionParam } from './types.ts';
2
+ export interface RememberedTestInput {
3
+ /** `true` once the read settled (or there was nothing to read). */
4
+ loaded: boolean;
5
+ /** `false` when the host has no `loadTestInputs` — fall back to the older source. */
6
+ supported: boolean;
7
+ /** `undefined` = no row; `{}` = cleared; else the values last used. */
8
+ input: Record<string, unknown> | undefined;
9
+ /** Remember `values` (secret literals dropped). Best-effort: never throws. */
10
+ save: (values: Record<string, unknown>, params?: readonly ActionParam[]) => void;
11
+ /** Forget the values (stored as `{}`, so no older source refills the form). */
12
+ clear: () => void;
13
+ }
14
+ export declare function useRememberedTestInput(workflowId: string | undefined, nodeId: string | undefined): RememberedTestInput;
15
+ /** The small muted note under a prefilled form: "last used values · Clear". */
16
+ export declare function LastUsedNote({ onClear }: {
17
+ onClear: () => void;
18
+ }): import("react").JSX.Element;
@@ -0,0 +1,78 @@
1
+ import { FlowStep, FlowWorkflow } from './flow-types.ts';
2
+ import { AppSummary, AuthDef, ConnectionSummary } from './types.ts';
3
+ export type FlowConnections = Record<string, {
4
+ app: string;
5
+ connection: string | null;
6
+ }>;
7
+ export type ConnectionResourceEdit = {
8
+ type: "add";
9
+ name: string;
10
+ app: string;
11
+ connection: string;
12
+ } | {
13
+ type: "update";
14
+ ref: string;
15
+ name: string;
16
+ connection: string;
17
+ nodeIds?: string[];
18
+ } | {
19
+ type: "replace";
20
+ ref: string;
21
+ connection: string;
22
+ } | {
23
+ type: "rename";
24
+ ref: string;
25
+ name: string;
26
+ } | {
27
+ type: "remove";
28
+ ref: string;
29
+ } | {
30
+ type: "assign";
31
+ ref: string;
32
+ nodeIds: string[];
33
+ };
34
+ export interface WorkflowConnectionResources {
35
+ workflowId: string;
36
+ nodes: Pick<FlowStep, "id" | "uses">[];
37
+ connections: FlowConnections;
38
+ /** App identity already resolved for the canvas; reuse it in the connections rail. */
39
+ apps?: ReadonlyMap<string, AppSummary>;
40
+ readOnly?: boolean;
41
+ /** Select and reveal a consuming node on the canvas. Available in read-only views too. */
42
+ focusNode?: (nodeId: string) => void;
43
+ /** Temporary canvas emphasis, without changing selection or the saved workflow. */
44
+ highlightNode?: (nodeId: string | null) => void;
45
+ /** Stable callback against the current canvas, including edits made since the panel opened. */
46
+ edit: (edit: ConnectionResourceEdit) => void;
47
+ }
48
+ /** Edit references and their consumers together, so one undo restores the whole change. */
49
+ export declare function editConnectionResources(nodes: FlowStep[], connections: FlowConnections, edit: ConnectionResourceEdit): {
50
+ nodes: FlowStep[];
51
+ connections: FlowConnections;
52
+ };
53
+ /** Missing/foreign bindings stay unresolved in the editor; the server rejects invalid references. */
54
+ export declare function connectionIdFor(step: FlowStep, connections?: FlowConnections): string | undefined;
55
+ /** A workflow-owned name, independent of the first node or the account's display name. */
56
+ export declare function nextWorkflowConnectionName(appId: string, connections: FlowConnections): string;
57
+ /** Lift old inline IDs on the next editor save. Independent bindings remain independent. */
58
+ export declare function centralizeConnections<T extends Pick<FlowWorkflow, "connections" | "nodes">>(workflow: T): T;
59
+ /** Drop only unreferenced aliases when serializing the complete workflow. */
60
+ export declare function pruneUnusedConnections<T extends Pick<FlowWorkflow, "connections" | "nodes">>(workflow: T): T;
61
+ export declare function withConnectionRef(step: FlowStep, connectionRef: string): FlowStep;
62
+ /** An ordinary account selection affects this node only, detaching it from a shared entry. */
63
+ export declare function selectNodeConnection(step: FlowStep, connection: string | undefined, nodes: FlowStep[], connections: FlowConnections): {
64
+ step: FlowStep;
65
+ connections: FlowConnections;
66
+ };
67
+ export declare function connectionSourceNodes(step: FlowStep, nodes: FlowStep[], connections: FlowConnections): FlowStep[];
68
+ /** Accounts used anywhere in the workflow, including independently stored bindings. */
69
+ export declare function connectionUsers(app: string, connection: string | undefined, nodes: FlowStep[], connections: FlowConnections): FlowStep[];
70
+ /** An explicit initial selection wins; otherwise inherit the last added configured node. */
71
+ export declare function defaultConnectionFor(step: FlowStep, choices: ConnectionSummary[], nodes: FlowStep[], connections: FlowConnections, initialConnection?: string): {
72
+ connection?: string;
73
+ connectionRef?: string;
74
+ };
75
+ /** The server's zero-credential sentinel is a real picker choice, without creating a row. */
76
+ export declare function withDefaultConnection(appId: string, auths: AuthDef[], choices: ConnectionSummary[]): ConnectionSummary[];
77
+ /** Change every binding used by the displayed account's consumers, retaining reference keys. */
78
+ export declare function replaceWorkflowConnection(app: string, before: string, after: string, nodes: FlowStep[], connections: FlowConnections): FlowConnections;