@w6w/ui 0.2.11 → 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.
- package/CHANGELOG.md +139 -2
- package/README.md +28 -10
- package/dist/AppPicker.d.ts +12 -1
- package/dist/CanvasContextMenu.d.ts +19 -0
- package/dist/{CodeBlock-BqXDA35P.js → CodeBlock-C-oIIYfC.js} +1436 -555
- package/dist/CodeBlock-C-oIIYfC.js.map +1 -0
- package/dist/CodeBlock-CymlfyeA.cjs +15 -0
- package/dist/CodeBlock-CymlfyeA.cjs.map +1 -0
- package/dist/CodeEditor.d.ts +4 -1
- package/dist/ConditionEditor.d.ts +11 -0
- package/dist/JsonEditor.d.ts +12 -0
- package/dist/ParamCustomization.d.ts +5 -0
- package/dist/ParamsForm.d.ts +11 -3
- package/dist/RouterEditor.d.ts +5 -0
- package/dist/StepBuilderModal.d.ts +83 -13
- package/dist/StepNameEditor.d.ts +11 -0
- package/dist/StopEditor.d.ts +5 -0
- package/dist/TriggerFillForm.d.ts +14 -1
- package/dist/WebhookListenPanel.d.ts +28 -0
- package/dist/WorkflowConnections.d.ts +29 -0
- package/dist/WorkflowFlowEditor.d.ts +64 -8
- package/dist/assets/script-completion.worker-DDJKkj5M.js +8290 -0
- package/dist/assets/script-completion.worker-DDJKkj5M.js.map +1 -0
- package/dist/canvas-context-menu.d.ts +27 -0
- package/dist/code.cjs +1 -1
- package/dist/code.mjs +3 -4
- package/dist/code.mjs.map +1 -1
- package/dist/components/AnchoredFlyout.d.ts +7 -0
- package/dist/components/ColumnsEditor.d.ts +27 -0
- package/dist/components/Combobox.d.ts +12 -1
- package/dist/components/CsvPanel.d.ts +21 -0
- package/dist/components/DataEntryEditor.d.ts +38 -0
- package/dist/components/DataEntryList.d.ts +33 -0
- package/dist/components/DataStoreList.d.ts +33 -0
- package/dist/components/DataTableGrid.d.ts +46 -0
- package/dist/components/EventbriteTriggerPicker.d.ts +7 -0
- package/dist/components/ExecutionDetail.d.ts +17 -1
- package/dist/components/ExecutionList.d.ts +19 -1
- package/dist/components/ExecutionLogPanel.d.ts +61 -3
- package/dist/components/ExpressionEditorModal.d.ts +33 -10
- package/dist/components/ExpressionOptions.d.ts +101 -15
- package/dist/components/HtmlPreview.d.ts +7 -0
- package/dist/components/JsonTree.d.ts +32 -0
- package/dist/components/ResolvedParams.d.ts +6 -1
- package/dist/components/ResultViewer.d.ts +46 -0
- package/dist/components/ScriptBindingsNotice.d.ts +31 -0
- package/dist/components/ScriptCodeField.d.ts +13 -0
- package/dist/components/StepStatusPill.d.ts +7 -0
- package/dist/components/expression-authoring.d.ts +13 -0
- package/dist/components/expression-dom.d.ts +17 -2
- package/dist/components/expression-template.d.ts +25 -3
- package/dist/components/icons.d.ts +1 -1
- package/dist/components/json-compose.d.ts +53 -0
- package/dist/components/result-format.d.ts +13 -0
- package/dist/condition-editor.d.ts +44 -0
- package/dist/data-stores/data-store-view.d.ts +371 -0
- package/dist/eventbrite-trigger-selection.d.ts +13 -0
- package/dist/flow-connect.d.ts +22 -16
- package/dist/flow-delete.d.ts +16 -0
- package/dist/flow-history.d.ts +75 -0
- package/dist/flow-layout.d.ts +13 -0
- package/dist/flow-loop-colors.d.ts +39 -0
- package/dist/flow-loop.d.ts +98 -0
- package/dist/flow-node-flags.d.ts +14 -0
- package/dist/flow-problems.d.ts +69 -0
- package/dist/flow-state.d.ts +20 -0
- package/dist/flow-types.d.ts +137 -9
- package/dist/flow-utils.d.ts +27 -13
- package/dist/flow.cjs +4 -2
- package/dist/flow.cjs.map +1 -1
- package/dist/flow.d.ts +7 -3
- package/dist/flow.mjs +3563 -1557
- package/dist/flow.mjs.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +30 -4
- package/dist/index.mjs +2555 -1272
- package/dist/index.mjs.map +1 -1
- package/dist/node-samples-ChdyMBnJ.cjs +22 -0
- package/dist/node-samples-ChdyMBnJ.cjs.map +1 -0
- package/dist/node-samples-DkJL07EX.js +12302 -0
- package/dist/node-samples-DkJL07EX.js.map +1 -0
- package/dist/node-samples.d.ts +80 -0
- package/dist/output-shape.d.ts +30 -14
- package/dist/param-customization.d.ts +7 -0
- package/dist/provider.d.ts +119 -7
- package/dist/resolve-params.d.ts +45 -11
- package/dist/run-visuals.d.ts +14 -21
- package/dist/script-bindings.d.ts +63 -0
- package/dist/script-completion-service.d.ts +9 -0
- package/dist/script-completion.worker.d.ts +1 -0
- package/dist/script-completions.d.ts +2 -0
- package/dist/state-shape.d.ts +38 -0
- package/dist/step-preview-state.d.ts +155 -6
- package/dist/step-problems.d.ts +42 -12
- package/dist/test-inputs.d.ts +25 -0
- package/dist/trigger-registration.d.ts +28 -0
- package/dist/types.d.ts +70 -8
- package/dist/use-app-action-defs.d.ts +9 -1
- package/dist/use-test-input.d.ts +18 -0
- package/dist/workflow-connections.d.ts +30 -0
- package/package.json +16 -7
- package/src/code.css +60 -6
- package/src/styles/_canvas.scss +35 -0
- package/src/styles/_code-editor.scss +35 -0
- package/src/styles/_code.scss +6 -5
- package/src/styles/_copyable.scss +24 -0
- package/src/styles/_data-stores.scss +138 -0
- package/src/styles/_data-vars.scss +17 -6
- package/src/styles/_execution-history.scss +73 -0
- package/src/styles/_execution-log.scss +145 -1
- package/src/styles/_expression-modal.scss +106 -16
- package/src/styles/_fields.scss +11 -0
- package/src/styles/_flow.scss +160 -0
- package/src/styles/_fx.scss +3 -1
- package/src/styles/_incoming-state.scss +33 -0
- package/src/styles/_modal.scss +12 -0
- package/src/styles/_multiselect.scss +35 -0
- package/src/styles/_sections.scss +36 -0
- package/src/styles/_step-builder.scss +145 -0
- package/src/styles/_tester.scss +56 -0
- package/src/styles/_tokens.scss +27 -1
- package/src/styles.css +1290 -77
- package/src/styles.scss +2 -0
- package/dist/CodeBlock-BqXDA35P.js.map +0 -1
- package/dist/CodeBlock-CulfbnZD.cjs +0 -15
- package/dist/CodeBlock-CulfbnZD.cjs.map +0 -1
- package/dist/ConfirmModal-Ln99S9NT.js +0 -7919
- package/dist/ConfirmModal-Ln99S9NT.js.map +0 -1
- package/dist/ConfirmModal-fjHW5rN-.cjs +0 -14
- package/dist/ConfirmModal-fjHW5rN-.cjs.map +0 -1
- package/dist/Copyable-DA6eiU7w.cjs +0 -2
- package/dist/Copyable-DA6eiU7w.cjs.map +0 -1
- package/dist/Copyable-F4NTaG77.js +0 -847
- package/dist/Copyable-F4NTaG77.js.map +0 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { FlowEdge, FlowStep, FlowWorkflow } from './flow-types.ts';
|
|
3
|
+
import { StepNode } from './flow-utils.ts';
|
|
4
|
+
type UsesLike = {
|
|
5
|
+
uses?: {
|
|
6
|
+
app?: string;
|
|
7
|
+
action?: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
/** A step is a foreach iff it is `@w6w/control` · `foreach` (P1). */
|
|
11
|
+
export declare function isForeachStep(step: UsesLike | undefined): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* The step ids a control step owns — engine `controlOwnedIds`, arm for arm
|
|
14
|
+
* (foreach `body`, parallel `branches`, if `then`/`else`; strings at any array depth).
|
|
15
|
+
*/
|
|
16
|
+
export declare function controlOwnedIds(step: FlowStep): string[];
|
|
17
|
+
/** Every step id owned by some control step (engine `ownedByControl`). */
|
|
18
|
+
export declare function ownedStepIds(steps: readonly FlowStep[]): Set<string>;
|
|
19
|
+
/** A canvas each-lane edge in the ONE shape load, bridge and `applyConnect` share (P3). */
|
|
20
|
+
export declare function eachLaneEdge(from: string, to: string, fromIsForeach: boolean, route?: string): Edge;
|
|
21
|
+
/**
|
|
22
|
+
* The body drawn from `foreachId`: every step reachable from its Each-item port
|
|
23
|
+
* over each-lane edges, as a topological order (Kahn over the body's own each-lane
|
|
24
|
+
* edges, ties broken by discovery order) so the Each-item target is first and every
|
|
25
|
+
* edge goes from an earlier id to a later one. A plain chain comes out exactly as
|
|
26
|
+
* the chain. Never includes `foreachId` or a repeat — so it terminates on a cycle
|
|
27
|
+
* (steps stuck in one are appended in discovery order). `claimed` (internal) stops
|
|
28
|
+
* the walk BEFORE a step an earlier foreach already owns.
|
|
29
|
+
*/
|
|
30
|
+
export declare function loopBody(foreachId: string, nodes: readonly StepNode[], edges: readonly Edge[], claimed?: ReadonlySet<string>): string[];
|
|
31
|
+
/** The each-lane edges with both ends inside `body` (the For each → body[0] link is not one). */
|
|
32
|
+
export declare function bodyInternalEdges(body: readonly string[], edges: readonly Edge[]): Edge[];
|
|
33
|
+
/**
|
|
34
|
+
* A body is plain iff it is a chain the ordered `with.body` list already says: every
|
|
35
|
+
* body node has at most one outgoing each-lane edge and none carries a route. Plain
|
|
36
|
+
* bodies serialize as the list alone; anything else also emits its body edges.
|
|
37
|
+
*/
|
|
38
|
+
export declare function isPlainBody(body: readonly string[], edges: readonly Edge[]): boolean;
|
|
39
|
+
/** The definition edges a canvas's non-plain loop bodies need (empty for plain chains). */
|
|
40
|
+
export declare function loopBodyDefinitionEdges(nodes: readonly StepNode[], edges: readonly Edge[]): FlowEdge[];
|
|
41
|
+
/** Every foreach's body, handled in `nodes` order so emitted bodies are disjoint (P6). */
|
|
42
|
+
export declare function loopBodies(nodes: readonly StepNode[], edges: readonly Edge[]): Map<string, string[]>;
|
|
43
|
+
/** `bodyStepId → foreachId` over the whole canvas. */
|
|
44
|
+
export declare function loopMembership(nodes: readonly StepNode[], edges: readonly Edge[]): Record<string, string>;
|
|
45
|
+
/**
|
|
46
|
+
* The edge set after deleting step `id` (D-A4). A body step with exactly one inbound
|
|
47
|
+
* and one outbound each-lane edge is bridged (`prev → next`, each lane, keeping the
|
|
48
|
+
* inbound edge's route when `prev` is an If/Router, `out-each` iff `prev` is the
|
|
49
|
+
* foreach); any other body step just loses its incident edges; deleting the foreach
|
|
50
|
+
* also removes the each-lane edges of its whole body (the body steps stay, as
|
|
51
|
+
* ordinary unconnected nodes). A non-body step is the plain incident-edge filter.
|
|
52
|
+
*/
|
|
53
|
+
export declare function bridgeDeletedBodyStep(id: string, nodes: readonly StepNode[], edges: readonly Edge[]): Edge[];
|
|
54
|
+
/** `with.body` is the derived view of the each lane — drop it from a foreach (P1); other steps untouched. */
|
|
55
|
+
export declare function stripBody<T extends UsesLike & {
|
|
56
|
+
with?: Record<string, unknown>;
|
|
57
|
+
}>(step: T): T;
|
|
58
|
+
/** Why a connection would break the v1 linear-body rule (exhaustive; see {@link loopRefusal}). */
|
|
59
|
+
export type LoopRefusalReason = "error_lane_in_body" | "outside_inbound" | "loop_cycle" | "already_in_loop" | "control_in_body" | "body_branch" | "body_exit";
|
|
60
|
+
/**
|
|
61
|
+
* The loop rule for drawing `source → target` in `lane` (already promoted: a success
|
|
62
|
+
* connect from a body node arrives as `"each"`). First match wins. Pure; run on the
|
|
63
|
+
* INPUT edges, never a post-eviction set.
|
|
64
|
+
*/
|
|
65
|
+
export declare function loopRefusal(source: string, target: string, lane: "success" | "error" | "each", nodes: StepNode[], edges: Edge[]): LoopRefusalReason | null;
|
|
66
|
+
export declare function loopRefusalMessage(reason: LoopRefusalReason): string;
|
|
67
|
+
/**
|
|
68
|
+
* Set or clear `data.loopOf` from {@link loopMembership}. Same array reference when
|
|
69
|
+
* nothing changed, and the same node object for every unchanged node.
|
|
70
|
+
*/
|
|
71
|
+
export declare function stampLoopOf(nodes: StepNode[], edges: Edge[]): StepNode[];
|
|
72
|
+
/** The delete-confirm text. Byte-identical to the plain message unless a For each owns a body. */
|
|
73
|
+
export declare function deleteStepMessage(id: string, nodes: StepNode[], edges: Edge[]): string;
|
|
74
|
+
export type LoopInvalidReason = "body_not_literal" | "body_unknown_step" | "body_self" | "body_duplicate" | "body_claimed_twice" | "body_contains_control" | "body_step_has_edges" | "legacy_not_linear";
|
|
75
|
+
export type LoopInvalid = {
|
|
76
|
+
reason: LoopInvalidReason;
|
|
77
|
+
stepId?: string;
|
|
78
|
+
};
|
|
79
|
+
export type LoopResult = {
|
|
80
|
+
body: string[];
|
|
81
|
+
source: "body" | "legacy";
|
|
82
|
+
edges?: FlowEdge[];
|
|
83
|
+
} | {
|
|
84
|
+
invalid: LoopInvalid;
|
|
85
|
+
};
|
|
86
|
+
/** The edges the engine would run: declared, else the implicit chain over main-graph (non-owned) steps. */
|
|
87
|
+
export declare function effectiveEdges(wf: FlowWorkflow): FlowEdge[];
|
|
88
|
+
/** A saved For each → `body[0]` link ({@link FOREACH_EACH_ROUTE}); the canvas draws it from `with.body`. */
|
|
89
|
+
export declare const isEachLink: (e: FlowEdge) => boolean;
|
|
90
|
+
/**
|
|
91
|
+
* What each foreach's loop is, in a stored definition — the ONE place that knows
|
|
92
|
+
* the legacy-chain rule (D-A3). A foreach carrying a `body` key is judged on it;
|
|
93
|
+
* one without is a legacy loop iff its success-lane successors form a valid linear
|
|
94
|
+
* chain (every node a non-control step owned by no control, whose only inbound edge
|
|
95
|
+
* is from its predecessor and whose only outbound edge is a success edge onward).
|
|
96
|
+
*/
|
|
97
|
+
export declare function definitionLoops(wf: FlowWorkflow): Record<string, LoopResult>;
|
|
98
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FlowStep } from './flow-types.ts';
|
|
2
|
+
export declare const PAUSED_LABEL = "Paused \u2014 test runs stop before this node";
|
|
3
|
+
export declare const DISABLED_LABEL = "Disabled \u2014 skipped in every run";
|
|
4
|
+
export declare function isPausedStep(step: FlowStep): boolean;
|
|
5
|
+
export declare function isDisabledStep(step: FlowStep): boolean;
|
|
6
|
+
/** `step` with `ui.paused` set (on) or removed (off); an emptied `ui` is dropped. */
|
|
7
|
+
export declare function withPaused(step: FlowStep, on: boolean): FlowStep;
|
|
8
|
+
/** `step` with `disabled: true` (on) or without the key (off). */
|
|
9
|
+
export declare function withDisabled(step: FlowStep, on: boolean): FlowStep;
|
|
10
|
+
/**
|
|
11
|
+
* The `stopAt` of a run started from `startId`'s ▶: every paused node except the start itself
|
|
12
|
+
* (pressing ▶ on a paused node runs it — the pause stops runs that ARRIVE at it).
|
|
13
|
+
*/
|
|
14
|
+
export declare function pausedStopAt(steps: readonly FlowStep[], startId: string): string[];
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { LoopRefusalReason } from './flow-loop.ts';
|
|
3
|
+
import { CanvasLane, FlowStep, FlowWorkflowInput } from './flow-types.ts';
|
|
4
|
+
import { StepNode } from './flow-utils.ts';
|
|
5
|
+
import { StepProblem, StepProblems } from './step-problems.ts';
|
|
6
|
+
/**
|
|
7
|
+
* THE matcher: is `ref` a reference to foreach `foreachId`'s output, and what
|
|
8
|
+
* does it become inside the loop. `R.F.output` → `foreach.item`, `R.F.output.<rest>`
|
|
9
|
+
* → `foreach.item.<rest>`, `R.F.output[<rest>` → `foreach.item[<rest>`. Segment
|
|
10
|
+
* boundary only: `…outputs` and `for_each_10` never match.
|
|
11
|
+
*/
|
|
12
|
+
export declare function loopOutputRef(ref: string, foreachId: string): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* The loop problems of a stored definition, keyed by step id. Never throws and
|
|
15
|
+
* never mutates: any input `workflowToFlow` would reject gives `{}` (it runs in a
|
|
16
|
+
* host memo with no error boundary).
|
|
17
|
+
*/
|
|
18
|
+
export declare function findLoopProblems(input: FlowWorkflowInput): StepProblems;
|
|
19
|
+
/** One editor-side parallel-write warning — the engine's `StateWriteWarning`, this code only. */
|
|
20
|
+
export interface StateParallelWrite {
|
|
21
|
+
code: "state_parallel_write";
|
|
22
|
+
nodes: string[];
|
|
23
|
+
path: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The editor mirror of the engine's plan-time parallel-write warning (R16, plan
|
|
27
|
+
* §2.3; proven equal on `core/packages/expr/tests/fixtures/state-write-conflicts.json`).
|
|
28
|
+
* Two writers are concurrent iff they sit in different branches of one
|
|
29
|
+
* `@w6w/control` `parallel`; else never when they share an anchor (outermost
|
|
30
|
+
* owning control, else the step) or one anchor reaches the other; else iff one
|
|
31
|
+
* `fanOut: "parallel"` step has two distinct outgoing edges in the SAME lane
|
|
32
|
+
* whose targets reach the two anchors. Each overlapping pair of static write
|
|
33
|
+
* paths gives one warning on the shorter path; deduped, sorted by the engine's
|
|
34
|
+
* order (`code`, then `nodes`, then `path`). Never throws (→ `[]`), never mutates.
|
|
35
|
+
*/
|
|
36
|
+
export declare function stateWriteConflicts(input: FlowWorkflowInput): StateParallelWrite[];
|
|
37
|
+
/**
|
|
38
|
+
* `stateWriteConflicts` as canvas problems: each warning lands on both of its
|
|
39
|
+
* steps, naming the other one (`with`). Never throws (→ `{}`), never mutates.
|
|
40
|
+
*/
|
|
41
|
+
export declare function findStateWriteProblems(input: FlowWorkflowInput): StepProblems;
|
|
42
|
+
/**
|
|
43
|
+
* Apply a problem's fix to `step`, returning a new step. Re-scans the step it is
|
|
44
|
+
* given (never trusts the problem's `refs` snapshot); the SAME reference comes
|
|
45
|
+
* back for a problem with no fix or nothing left to fix. Never mutates.
|
|
46
|
+
*/
|
|
47
|
+
export declare function applyStepProblemFix(step: FlowStep, problem: StepProblem): FlowStep;
|
|
48
|
+
/**
|
|
49
|
+
* The lane of a drag, read from the handle the pointer went down on. xyflow's
|
|
50
|
+
* `connectionState.fromHandle` resolves an id-less handle (the Done port) to the
|
|
51
|
+
* node's FIRST handle (`out-each`), so it cannot tell Done from Each item;
|
|
52
|
+
* `onConnectStart` reports the real `handleId` (null for Done). Falls back to
|
|
53
|
+
* `fromHandle.id` when no matching start was recorded.
|
|
54
|
+
*/
|
|
55
|
+
export declare function dragLane(start: {
|
|
56
|
+
nodeId: string | null;
|
|
57
|
+
handleId: string | null;
|
|
58
|
+
handleType: string | null;
|
|
59
|
+
} | null, fromNodeId: string, fromHandle: {
|
|
60
|
+
id?: string | null;
|
|
61
|
+
type?: string;
|
|
62
|
+
} | null | undefined): CanvasLane;
|
|
63
|
+
/**
|
|
64
|
+
* The loop reason a source-handle drag dropped ON an existing node is refused for
|
|
65
|
+
* (`null` when the loop rule has nothing to say). `onConnectEnd` shows it as the
|
|
66
|
+
* node-anchored notice instead of opening the step builder. The lane is promoted the
|
|
67
|
+
* way `planConnect` does: a success drag from a body node extends the body.
|
|
68
|
+
*/
|
|
69
|
+
export declare function connectDropRefusal(source: string, target: string, lane: "success" | "error" | "each", nodes: StepNode[], edges: Edge[]): LoopRefusalReason | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { StateWriteConfig } from '@w6w/expr';
|
|
2
|
+
import { FlowStep } from './flow-types.ts';
|
|
3
|
+
export type StateMode = StateWriteConfig["mode"];
|
|
4
|
+
/** The five modes, in the order the control lists them. */
|
|
5
|
+
export declare const STATE_MODES: readonly StateMode[];
|
|
6
|
+
export declare const STATE_MODE_LABELS: Record<StateMode, string>;
|
|
7
|
+
type StepLike = Pick<FlowStep, "id" | "uses" | "state">;
|
|
8
|
+
/** What the step writes, the default applied (R14: Set data merges at root, every other step is Off). */
|
|
9
|
+
export declare function stateWriteFor(step: StepLike): StateWriteConfig;
|
|
10
|
+
/**
|
|
11
|
+
* The step with `config` as its state write. The default is the key's ABSENCE
|
|
12
|
+
* (Off on an ordinary step, Merge at root on Set data), so writing the default
|
|
13
|
+
* removes `state`. Never mutates; every other key passes through.
|
|
14
|
+
*/
|
|
15
|
+
export declare function setStateWrite<S extends StepLike>(step: S, config: StateWriteConfig): S;
|
|
16
|
+
/** The config written when the author picks `mode`: named after the step so it is valid at once. */
|
|
17
|
+
export declare function seedStateWrite(step: Pick<FlowStep, "id">, mode: StateMode): StateWriteConfig;
|
|
18
|
+
/** The control shows for app steps and triggers; every control-flow step (If, For each, Parallel, Race) hides it. */
|
|
19
|
+
export declare function stateWriteVisible(step: Pick<FlowStep, "uses">): boolean;
|
|
20
|
+
export {};
|
package/dist/flow-types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StateWriteConfig } from '@w6w/expr';
|
|
1
2
|
import { FlowCanvas } from './canvas-types.ts';
|
|
2
3
|
import { EdgeRunState } from './run-visuals.ts';
|
|
3
4
|
import { ActionParam } from './types.ts';
|
|
@@ -7,13 +8,16 @@ export interface FlowStep {
|
|
|
7
8
|
app: string;
|
|
8
9
|
action: string;
|
|
9
10
|
connection?: string | null;
|
|
11
|
+
connectionRef?: string;
|
|
12
|
+
/** An app TRIGGER node (`action` is the trigger key): behaves like a built-in trigger on the canvas. */
|
|
13
|
+
trigger?: true;
|
|
10
14
|
};
|
|
11
15
|
/**
|
|
12
16
|
* Declared connection-port cardinality for this step (see core
|
|
13
17
|
* `rfcs/node-types.md` · Ports & cardinality). Omitted fields fall through field-wise to the catalog action, the internal def, then `{ in: 1, out: "many" }`.
|
|
14
|
-
* A persisted value wins over the node's default
|
|
15
|
-
*
|
|
16
|
-
*
|
|
18
|
+
* A persisted value wins over the node's default. Only `in: 0` binds (no entry
|
|
19
|
+
* port); any `in >= 1` accepts any number of inbound edges (core node-types ·
|
|
20
|
+
* Alternate entries).
|
|
17
21
|
*/
|
|
18
22
|
ports?: PortsDecl;
|
|
19
23
|
with?: Record<string, unknown>;
|
|
@@ -37,6 +41,8 @@ export interface FlowStep {
|
|
|
37
41
|
* runs them one after another.
|
|
38
42
|
*/
|
|
39
43
|
fanOut?: "sequential" | "parallel";
|
|
44
|
+
/** Write to state (`Node.state`, core/rfcs/workflow.md). Absent = the default: Off, or Merge at root for `@w6w/data` set. */
|
|
45
|
+
state?: StateWriteConfig;
|
|
40
46
|
/**
|
|
41
47
|
* Authoring-time canvas coordinate for this step, in this editor's own
|
|
42
48
|
* coordinate space (core `rfcs/workflow.md` · "Amendment — 2026-07-29:
|
|
@@ -60,10 +66,26 @@ export interface FlowStep {
|
|
|
60
66
|
x: number;
|
|
61
67
|
y: number;
|
|
62
68
|
};
|
|
69
|
+
/**
|
|
70
|
+
* Disabled: skipped in EVERY run, published and triggered included — the node does not
|
|
71
|
+
* execute and its outgoing edges are skipped, so a node that depends only on it does not run
|
|
72
|
+
* either. An engine semantic (mirrors `Node.disabled` in `@w6w/workflow-types`). Written as
|
|
73
|
+
* `true` or absent, never `false`.
|
|
74
|
+
*/
|
|
75
|
+
disabled?: true;
|
|
76
|
+
/**
|
|
77
|
+
* Editor-only metadata; the engine ignores it. `paused`: a test run started from a node's ▶
|
|
78
|
+
* stops BEFORE this node (it does not execute). Never affects a published or triggered run.
|
|
79
|
+
* Absent when empty, never `{}`.
|
|
80
|
+
*/
|
|
81
|
+
ui?: {
|
|
82
|
+
paused?: true;
|
|
83
|
+
};
|
|
63
84
|
}
|
|
64
85
|
export interface FlowEdge {
|
|
65
86
|
from: string;
|
|
66
87
|
to: string;
|
|
88
|
+
route?: string;
|
|
67
89
|
/**
|
|
68
90
|
* Which outcome of the `from` step this edge carries (core
|
|
69
91
|
* `rfcs/workflow.md` · "Amendment — 2026-07-29: failure-conditioned edges
|
|
@@ -111,7 +133,7 @@ export interface FlowEdge {
|
|
|
111
133
|
* leaves the class in place, so `setEdgeWhen` assigns both keys explicitly
|
|
112
134
|
* rather than spreading.
|
|
113
135
|
*/
|
|
114
|
-
export declare function edgeVisuals(when:
|
|
136
|
+
export declare function edgeVisuals(when: CanvasLane | undefined, runState?: EdgeRunState): {
|
|
115
137
|
className?: string;
|
|
116
138
|
label?: string;
|
|
117
139
|
};
|
|
@@ -121,6 +143,25 @@ export declare function edgeVisuals(when: "success" | "error" | undefined, runSt
|
|
|
121
143
|
* (D-P2), since no consumer outside this package needs it.
|
|
122
144
|
*/
|
|
123
145
|
export declare const ERROR_SOURCE_HANDLE = "out-error";
|
|
146
|
+
/**
|
|
147
|
+
* The handle id of a For each's **Each item** exit port. The `each` lane derives
|
|
148
|
+
* `with.body` on save; its link to the first body step is also saved as a
|
|
149
|
+
* {@link FOREACH_EACH_ROUTE} edge so a reader sees which port it leaves.
|
|
150
|
+
*/
|
|
151
|
+
export declare const EACH_SOURCE_HANDLE = "out-each";
|
|
152
|
+
/**
|
|
153
|
+
* `Edge.route` of a For each's **Done** port (the engine's `FOREACH_DONE_ROUTE`): the
|
|
154
|
+
* success edge that runs once, after every iteration. An unrouted For each success
|
|
155
|
+
* edge — the shape saved before the port had an id — is read as Done.
|
|
156
|
+
*/
|
|
157
|
+
export declare const FOREACH_DONE_ROUTE = "done";
|
|
158
|
+
/** `Edge.route` of a For each's Each item link to `with.body[0]` (engine `FOREACH_EACH_ROUTE`). */
|
|
159
|
+
export declare const FOREACH_EACH_ROUTE = "each";
|
|
160
|
+
/**
|
|
161
|
+
* A lane on the CANVAS. `"each"` is canvas-only (a For each → body-step edge);
|
|
162
|
+
* the persisted {@link FlowEdge}`["when"]` deliberately stays `"success" | "error"`.
|
|
163
|
+
*/
|
|
164
|
+
export type CanvasLane = "success" | "error" | "each";
|
|
124
165
|
/**
|
|
125
166
|
* The `sourceHandle` a minted/re-laned/loaded edge carries for a given lane —
|
|
126
167
|
* the inverse of {@link laneForSourceHandle}. `undefined` for `"success"`/
|
|
@@ -129,7 +170,7 @@ export declare const ERROR_SOURCE_HANDLE = "out-error";
|
|
|
129
170
|
* already-saved workflow's edges implicitly use. An empty string would not do
|
|
130
171
|
* this — an empty string is a real, if degenerate, handle id.
|
|
131
172
|
*/
|
|
132
|
-
export declare function sourceHandleForLane(when:
|
|
173
|
+
export declare function sourceHandleForLane(when: CanvasLane | undefined): string | undefined;
|
|
133
174
|
/**
|
|
134
175
|
* The lane a drag started from, read off the handle id React Flow reports.
|
|
135
176
|
* **The one canonicalisation point** every minting/re-laning site calls
|
|
@@ -139,7 +180,7 @@ export declare function sourceHandleForLane(when: "success" | "error" | undefine
|
|
|
139
180
|
* `"error"`; everything else — a near-miss id, `null`, `undefined` — is
|
|
140
181
|
* `"success"`.
|
|
141
182
|
*/
|
|
142
|
-
export declare function laneForSourceHandle(handleId: string | null | undefined):
|
|
183
|
+
export declare function laneForSourceHandle(handleId: string | null | undefined): CanvasLane;
|
|
143
184
|
export interface FlowWorkflow {
|
|
144
185
|
manifestVersion: string;
|
|
145
186
|
id: string;
|
|
@@ -152,7 +193,13 @@ export interface FlowWorkflow {
|
|
|
152
193
|
required?: boolean;
|
|
153
194
|
default?: unknown;
|
|
154
195
|
}>;
|
|
196
|
+
/** Starting data (`Workflow.initialState`): a literal JSON object that seeds the run's state tree. */
|
|
197
|
+
initialState?: Record<string, unknown>;
|
|
155
198
|
nodes: FlowStep[];
|
|
199
|
+
connections?: Record<string, {
|
|
200
|
+
app: string;
|
|
201
|
+
connection: string | null;
|
|
202
|
+
}>;
|
|
156
203
|
edges?: FlowEdge[];
|
|
157
204
|
canvas?: FlowCanvas;
|
|
158
205
|
/**
|
|
@@ -259,7 +306,7 @@ export declare const DOCUMENT_APP = "@w6w/document";
|
|
|
259
306
|
*/
|
|
260
307
|
export declare const MODEL_APP = "@w6w/model";
|
|
261
308
|
/**
|
|
262
|
-
*
|
|
309
|
+
* Render Handlebars text or JSON string values against a resolved `values` object
|
|
263
310
|
* (core rfcs/node-types.md · F-3 amendment, "the `@w6w/template` host node").
|
|
264
311
|
* Host node: `runInternalNode` short-circuits this id before the registry
|
|
265
312
|
* loads a module — it needs no privileged host resource (no DB, no
|
|
@@ -267,6 +314,74 @@ export declare const MODEL_APP = "@w6w/model";
|
|
|
267
314
|
* compiles to a JS function, the same risk shape `@w6w/script` has.
|
|
268
315
|
*/
|
|
269
316
|
export declare const TEMPLATE_APP = "@w6w/template";
|
|
317
|
+
/** Host-run regular-expression operations. */
|
|
318
|
+
export declare const REGEX_APP = "@w6w/regex";
|
|
319
|
+
/**
|
|
320
|
+
* Read, write, count, list and query the entries of a named data store (core
|
|
321
|
+
* rfcs/node-types.md, the `@w6w/store` amendment). Host node, like
|
|
322
|
+
* {@link DOCUMENT_APP}: the run's own account and project are bound host-side, so
|
|
323
|
+
* there is no scope param — a store is addressed by NAME. The params mirror the
|
|
324
|
+
* `@w6w/store` internal-app manifest (pinned by `store-node-parity.test.ts`).
|
|
325
|
+
*/
|
|
326
|
+
export declare const STORE_APP = "@w6w/store";
|
|
327
|
+
/** End the whole workflow successfully when its optional condition matches. */
|
|
328
|
+
export declare const STOP_APP = "@w6w/stop";
|
|
329
|
+
export declare const ROUTER_APP = "@w6w/router";
|
|
330
|
+
export declare const RACE_APP = "@w6w/race";
|
|
331
|
+
export declare const RACE_DESCRIPTION = "Continue once with the first arriving path\u2019s output. Later arrivals are ignored for this run. Other paths keep running.";
|
|
332
|
+
export interface RouterRoute {
|
|
333
|
+
id: string;
|
|
334
|
+
label?: string;
|
|
335
|
+
condition?: unknown;
|
|
336
|
+
default?: boolean;
|
|
337
|
+
}
|
|
338
|
+
export declare function routesForStep(step: FlowStep): RouterRoute[];
|
|
339
|
+
export declare const routeHandle: (id: string) => string;
|
|
340
|
+
export declare const routeFromHandle: (handle: string | null | undefined) => string | undefined;
|
|
341
|
+
/** Route ports the Router card's right edge holds at its natural height. */
|
|
342
|
+
export declare const ROUTER_PORTS_AT_BASE_HEIGHT = 3;
|
|
343
|
+
/** Card height (px, border-box) added per route port past the third. */
|
|
344
|
+
export declare const ROUTER_PORT_STEP = 16;
|
|
345
|
+
export interface RouterPort {
|
|
346
|
+
id: string;
|
|
347
|
+
/** Absent for an If's True port: the unnamed handle a route-less edge anchors to. */
|
|
348
|
+
handleId?: string;
|
|
349
|
+
label: string;
|
|
350
|
+
/** Handle position along its edge, as a CSS `top` (right-edge ports only). */
|
|
351
|
+
top?: string;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Where a Router's ports sit (human report, 2026-10-31: "they need to be
|
|
355
|
+
* attached to the router"). Condition routes go on the card's right edge,
|
|
356
|
+
* evenly spaced; the fallback route takes the bottom edge, the slot every
|
|
357
|
+
* other node gives its error port. Up to three right-edge ports fit the
|
|
358
|
+
* card's natural height; each one past that adds a fixed step, so five
|
|
359
|
+
* routes make a slightly taller card. Handle ids stay `route:<id>`, so
|
|
360
|
+
* saved edges keep resolving.
|
|
361
|
+
*/
|
|
362
|
+
export interface PortLayout {
|
|
363
|
+
right: RouterPort[];
|
|
364
|
+
bottom?: RouterPort;
|
|
365
|
+
minHeight?: number;
|
|
366
|
+
}
|
|
367
|
+
export declare function routerPortLayout(routes: RouterRoute[]): PortLayout;
|
|
368
|
+
/**
|
|
369
|
+
* `Edge.route` of an If's false branch (the engine's `IF_FALSE_ROUTE`). The true
|
|
370
|
+
* branch is an edge with no route, which is what every If edge saved before the
|
|
371
|
+
* False port existed already is.
|
|
372
|
+
*/
|
|
373
|
+
export declare const IF_FALSE_ROUTE = "false";
|
|
374
|
+
export declare function isIfStep(step: FlowStep): boolean;
|
|
375
|
+
/**
|
|
376
|
+
* An If's ports, laid out the way {@link routerPortLayout} lays out a Router's
|
|
377
|
+
* (human report, 2026-10-31: "should not have error, it should have: true port
|
|
378
|
+
* and false port"). True takes the right edge; False takes the bottom edge, the
|
|
379
|
+
* slot every other node gives its error port, so an If has no error port. True
|
|
380
|
+
* keeps the unnamed handle, so saved If edges stay on it; False is `route:false`.
|
|
381
|
+
*/
|
|
382
|
+
export declare function ifPortLayout(): PortLayout & {
|
|
383
|
+
bottom: RouterPort;
|
|
384
|
+
};
|
|
270
385
|
/** True when `app` is a reserved internal pseudo-app id (`@w6w/*`). */
|
|
271
386
|
export declare function isInternalApp(app: string): boolean;
|
|
272
387
|
/** True when a node is an engine-native flow-control node (can't run standalone). */
|
|
@@ -278,6 +393,16 @@ export declare function isControlApp(app: string): boolean;
|
|
|
278
393
|
* and send the filled values as `{ input }` rather than running the raw config.
|
|
279
394
|
*/
|
|
280
395
|
export declare function isTriggerApp(app: string): boolean;
|
|
396
|
+
/**
|
|
397
|
+
* Whether a step is a trigger NODE: one of the built-in triggers, or an app
|
|
398
|
+
* trigger node (`uses.trigger === true`). Canvas chrome, wiring and editing key
|
|
399
|
+
* on this; {@link isTriggerApp} stays for readers that mean the built-in
|
|
400
|
+
* `@w6w/*` triggers only (a callable workflow's input fields).
|
|
401
|
+
*/
|
|
402
|
+
export declare function isTriggerStep(uses: {
|
|
403
|
+
app: string;
|
|
404
|
+
trigger?: true;
|
|
405
|
+
}): boolean;
|
|
281
406
|
/** A palette entry for an internal node: its id, label, group, and config schema. */
|
|
282
407
|
export interface InternalNodeDef {
|
|
283
408
|
app: string;
|
|
@@ -289,6 +414,8 @@ export interface InternalNodeDef {
|
|
|
289
414
|
* does. Shown wherever an app's name would be.
|
|
290
415
|
*/
|
|
291
416
|
displayName: string;
|
|
417
|
+
/** Show one app entry in the palette and choose its action in configuration. */
|
|
418
|
+
groupActions?: boolean;
|
|
292
419
|
group: "trigger" | "control" | "compute" | "request";
|
|
293
420
|
/**
|
|
294
421
|
* Inline SVG *inner* markup (paths / circles / polylines) for this primitive's
|
|
@@ -303,8 +430,9 @@ export interface InternalNodeDef {
|
|
|
303
430
|
*/
|
|
304
431
|
hidden?: boolean;
|
|
305
432
|
/**
|
|
306
|
-
* Connection ports:
|
|
307
|
-
*
|
|
433
|
+
* Connection ports: whether this node has an entry (`in >= 1` takes any number
|
|
434
|
+
* of inbound edges; `in: 0` takes none) and how many outbound (exit) connections
|
|
435
|
+
* it allows. A port is the ability to receive/emit a connection —
|
|
308
436
|
* rendered as a React Flow Handle. Defaults to one of each (`{ in: 1, out: 1 }`)
|
|
309
437
|
* when omitted; a trigger overrides to `{ in: 0, out: 1 }` (nothing flows into
|
|
310
438
|
* the entry node). Fixed for now — not user-editable.
|
package/dist/flow-utils.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Edge, Node } from '@xyflow/react';
|
|
2
|
-
import {
|
|
2
|
+
import { CanvasLane, FlowStep, FlowWorkflow, FlowWorkflowInput } from './flow-types.ts';
|
|
3
3
|
import { RunStatus, StepVisualState } from './run-visuals.ts';
|
|
4
4
|
import { StepProblem } from './step-problems.ts';
|
|
5
5
|
export interface StepNodeData extends Record<string, unknown> {
|
|
@@ -23,11 +23,18 @@ export interface StepNodeData extends Record<string, unknown> {
|
|
|
23
23
|
*/
|
|
24
24
|
runStatus?: RunStatus;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* Host-supplied problems with this step (a dangling connection, loop problems).
|
|
27
27
|
* Patched in by `WorkflowFlowEditor.tsx`'s `stepProblems` effect — never set
|
|
28
|
-
* here and never read by {@link flowToWorkflow} (not persisted).
|
|
28
|
+
* here, absent (never `[]`) when there are none, and never read by {@link flowToWorkflow} (not persisted).
|
|
29
29
|
*/
|
|
30
|
-
|
|
30
|
+
stepProblems?: StepProblem[];
|
|
31
|
+
/**
|
|
32
|
+
* The For each this step is a loop-body member of (canvas-only; derived on load
|
|
33
|
+
* and by the editor, never read by {@link flowToWorkflow}).
|
|
34
|
+
*/
|
|
35
|
+
loopOf?: string;
|
|
36
|
+
/** This For each was converted from a legacy (no-`body`) loop on load. Canvas-only. */
|
|
37
|
+
legacyLoop?: boolean;
|
|
31
38
|
}
|
|
32
39
|
export type StepNode = Node<StepNodeData>;
|
|
33
40
|
/**
|
|
@@ -46,13 +53,19 @@ export type StepNode = Node<StepNodeData>;
|
|
|
46
53
|
* rewrite) in `flow-connect.ts`. A second hand-rolled copy of the template is
|
|
47
54
|
* exactly how the rename path came to drop the qualifier.
|
|
48
55
|
*/
|
|
49
|
-
export declare function flowEdgeId(from: string, to: string, when?:
|
|
56
|
+
export declare function flowEdgeId(from: string, to: string, when?: CanvasLane, route?: string): string;
|
|
50
57
|
/**
|
|
51
58
|
* Why a step id may not be saved from the editor, or `null` when it may. The one
|
|
52
59
|
* rule here is "no `.`" (a dotted id cannot be addressed by `steps.<id>.output`);
|
|
53
60
|
* duplicates and the edge-time `->` / `:error` checks are NOT this function's job.
|
|
54
61
|
*/
|
|
55
62
|
export declare function stepIdError(id: string): string | null;
|
|
63
|
+
/**
|
|
64
|
+
* {@link stepIdError} plus uniqueness: why `id` may not name a node of a graph whose other
|
|
65
|
+
* nodes are `taken`, or `null`. The rename in the step editor and the name in the add flow
|
|
66
|
+
* both validate through this.
|
|
67
|
+
*/
|
|
68
|
+
export declare function stepNameError(id: string, taken: Iterable<string>): string | null;
|
|
56
69
|
/**
|
|
57
70
|
* The one wording for a refused edge id, shared by both routes into the collision —
|
|
58
71
|
* drawing a wire whose minted id is taken (`applyConnect` / `connectConflict`) and
|
|
@@ -108,6 +121,8 @@ export declare function stepIdError(id: string): string | null;
|
|
|
108
121
|
* vague-but-true message beats a confident false one.
|
|
109
122
|
*/
|
|
110
123
|
export declare function idClashMessage(lead: string, id: string, involved: readonly (string | null | undefined)[]): string;
|
|
124
|
+
/** Read a definition in either shape into the canonical `nodes[]` form. */
|
|
125
|
+
export declare function normalizeInput(input: FlowWorkflowInput): FlowWorkflow;
|
|
111
126
|
/**
|
|
112
127
|
* Turn a Workflow into (nodes, edges) with an auto-layout when no positions are
|
|
113
128
|
* known.
|
|
@@ -117,11 +132,8 @@ export declare function idClashMessage(lead: string, id: string, involved: reado
|
|
|
117
132
|
* positioned graph mixes the two: positioned steps sit where they were left,
|
|
118
133
|
* unpositioned ones take their computed slot.
|
|
119
134
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* unpositioned step's computed coordinate is a pure function of the graph and
|
|
123
|
-
* does not shift depending on which of its neighbours happen to carry a
|
|
124
|
-
* coordinate.
|
|
135
|
+
* Layout runs over the whole graph, including positioned steps, so a fallback
|
|
136
|
+
* coordinate does not depend on which neighbours already have saved positions.
|
|
125
137
|
*/
|
|
126
138
|
export declare function workflowToFlow(input: FlowWorkflowInput): {
|
|
127
139
|
nodes: StepNode[];
|
|
@@ -135,12 +147,12 @@ export declare function workflowToFlow(input: FlowWorkflowInput): {
|
|
|
135
147
|
* button acts on **what is currently on the canvas**, including steps added and
|
|
136
148
|
* wires drawn since the last save.
|
|
137
149
|
*
|
|
138
|
-
* Same {@link
|
|
150
|
+
* Same {@link computePositions} as {@link
|
|
139
151
|
* workflowToFlow}, so a graph with no stored positions lays out byte-identically
|
|
140
152
|
* either way (pinned by `flow-utils.test.ts` — "auto-layout agrees with first
|
|
141
153
|
* open"). The **only** difference is that a stored coordinate does not win here:
|
|
142
154
|
* overriding hand placement is precisely what the author asked for by clicking.
|
|
143
|
-
*
|
|
155
|
+
* The editor records this as one undoable layout change.
|
|
144
156
|
*
|
|
145
157
|
* Layering is keyed by **`node.id`**, not `node.data.step.id`: React Flow's
|
|
146
158
|
* `edge.source`/`edge.target` name node ids, so keying by anything else would
|
|
@@ -287,5 +299,7 @@ export declare function stepToJson(step: StepLike): string;
|
|
|
287
299
|
* writable: the params-only `JsonEditor`'s `onValidChange` feeds straight back
|
|
288
300
|
* into `with`/`withValues`, same as it always has.
|
|
289
301
|
*/
|
|
290
|
-
export declare function paramsToJson(step: Pick<StepLike, "with">
|
|
302
|
+
export declare function paramsToJson(step: Pick<StepLike, "with"> & {
|
|
303
|
+
uses?: StepLike["uses"];
|
|
304
|
+
}): string;
|
|
291
305
|
export {};
|