@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,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure, data-free vocabulary of a Data store (F-2, lifted from Studio's
|
|
3
|
+
* `lib/data-stores-view`, `data-cells`, `data-grid` and `data-store-errors`).
|
|
4
|
+
*
|
|
5
|
+
* One import point for every consumer (Studio, `@w6w/embed`, the components in
|
|
6
|
+
* this package): the wire types, the closed kind/scalar vocabularies, the
|
|
7
|
+
* cell text codec, the row-draft/write helpers and the error locator. Paths,
|
|
8
|
+
* query builders and cache keys deliberately stay in Studio.
|
|
9
|
+
*
|
|
10
|
+
* Pure and dependency-free on purpose: no React, no SDK, no `fetch`, only
|
|
11
|
+
* relative imports, so `node --test` loads it with nothing but type-stripping.
|
|
12
|
+
*/
|
|
13
|
+
/** Display label per store kind (shared by every list and picker). */
|
|
14
|
+
export declare const DATA_STORE_KIND_LABEL: {
|
|
15
|
+
readonly kv: "Key-value";
|
|
16
|
+
readonly doc: "Document";
|
|
17
|
+
readonly table: "Table";
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* The three store shapes. `kv` holds one value per key, `doc` holds a JSON
|
|
21
|
+
* document per key, `table` holds rows whose columns are declared in the
|
|
22
|
+
* store's schema.
|
|
23
|
+
*/
|
|
24
|
+
export type DataStoreKind = "kv" | "doc" | "table";
|
|
25
|
+
/**
|
|
26
|
+
* The server's scalar vocabulary (S-1). A value of this type is validated
|
|
27
|
+
* server-side and stored as the string the caller sent — never coerced.
|
|
28
|
+
*/
|
|
29
|
+
export type ScalarType = "string" | "number" | "integer" | "boolean" | "date" | "datetime";
|
|
30
|
+
/** One declared table column (S-2). `default` is the column's JSON default, verbatim. */
|
|
31
|
+
export interface TableColumn {
|
|
32
|
+
name: string;
|
|
33
|
+
type: ScalarType;
|
|
34
|
+
required: boolean;
|
|
35
|
+
default?: unknown;
|
|
36
|
+
}
|
|
37
|
+
/** A `kv` store's schema (S-2): one scalar type for every value. */
|
|
38
|
+
export interface KvSchema {
|
|
39
|
+
valueType: ScalarType;
|
|
40
|
+
}
|
|
41
|
+
/** A `table` store's schema (S-2); `key` names the column whose cell is the row's key. */
|
|
42
|
+
export interface TableSchema {
|
|
43
|
+
columns: TableColumn[];
|
|
44
|
+
key?: string;
|
|
45
|
+
}
|
|
46
|
+
/** A store as the wire carries it (S-3). Timestamps are ISO-8601 strings. */
|
|
47
|
+
export interface DataStore {
|
|
48
|
+
id: string;
|
|
49
|
+
kind: DataStoreKind;
|
|
50
|
+
name: string;
|
|
51
|
+
description: string;
|
|
52
|
+
project: string;
|
|
53
|
+
schema: Record<string, unknown>;
|
|
54
|
+
entryCount: number;
|
|
55
|
+
sizeBytes: number;
|
|
56
|
+
createdBy: string;
|
|
57
|
+
createdAt: string;
|
|
58
|
+
updatedAt: string;
|
|
59
|
+
}
|
|
60
|
+
/** One entry as the wire carries it (S-3). `expiresAt` is `null` when the entry never expires. */
|
|
61
|
+
export interface Entry {
|
|
62
|
+
key: string;
|
|
63
|
+
value: unknown;
|
|
64
|
+
version: number;
|
|
65
|
+
sizeBytes: number;
|
|
66
|
+
expiresAt: string | null;
|
|
67
|
+
createdAt: string;
|
|
68
|
+
updatedAt: string;
|
|
69
|
+
}
|
|
70
|
+
/** `GET /data-stores` — one page of stores plus the cursor for the next one. */
|
|
71
|
+
export interface DataStorePage {
|
|
72
|
+
items: DataStore[];
|
|
73
|
+
nextCursor?: string;
|
|
74
|
+
}
|
|
75
|
+
/** `GET /data-stores/:id/entries` — one page of entries (a table query never carries a cursor). */
|
|
76
|
+
export interface EntryPage {
|
|
77
|
+
items: Entry[];
|
|
78
|
+
nextCursor?: string;
|
|
79
|
+
}
|
|
80
|
+
/** `POST /data-stores/:id/import` — how many CSV rows the host upserted/appended. */
|
|
81
|
+
export interface ImportResult {
|
|
82
|
+
imported: number;
|
|
83
|
+
}
|
|
84
|
+
/** `POST /data-stores` body. `schema` is the S-2 shape for the chosen `kind`. */
|
|
85
|
+
export interface DataStoreCreateInput {
|
|
86
|
+
kind: DataStoreKind;
|
|
87
|
+
name: string;
|
|
88
|
+
description?: string;
|
|
89
|
+
schema?: Record<string, unknown>;
|
|
90
|
+
}
|
|
91
|
+
/** `PATCH /data-stores/:id` body — every field optional, none of them the kind. */
|
|
92
|
+
export interface DataStorePatch {
|
|
93
|
+
name?: string;
|
|
94
|
+
description?: string;
|
|
95
|
+
schema?: Record<string, unknown>;
|
|
96
|
+
}
|
|
97
|
+
/** The closed set of store kinds, in the order the create dialog offers them. */
|
|
98
|
+
export declare const DATA_STORE_KINDS: readonly ["kv", "doc", "table"];
|
|
99
|
+
/** The closed set of scalar cell types, in the order the columns editor offers them. */
|
|
100
|
+
export declare const SCALAR_TYPES: readonly ["string", "number", "integer", "boolean", "date", "datetime"];
|
|
101
|
+
/** R-7: a CSV upload is at most 5 MB (5 242 880 bytes). The client checks before sending. */
|
|
102
|
+
export declare const CSV_MAX_BYTES = 5242880;
|
|
103
|
+
/**
|
|
104
|
+
* A `kv` store's declared value type, defaulting to `"string"` — S-2's own
|
|
105
|
+
* default, and the only safe reading of a schema the client did not write
|
|
106
|
+
* (a store created before the field existed, or one whose schema is garbage).
|
|
107
|
+
*/
|
|
108
|
+
export declare function kvValueTypeOf(store: DataStore): ScalarType;
|
|
109
|
+
/**
|
|
110
|
+
* A `table` store's schema, or `null` when the store is not a table or its
|
|
111
|
+
* schema has no column array. `null` — not an empty column list — so the grid
|
|
112
|
+
* can tell "not a table" from "a table with nothing declared".
|
|
113
|
+
*/
|
|
114
|
+
export declare function tableSchemaOf(store: DataStore): TableSchema | null;
|
|
115
|
+
/**
|
|
116
|
+
* The filename to save an export under: the host's own `filename="…"` from the
|
|
117
|
+
* `Content-Disposition` header when it sent one, otherwise `<store name>.csv`.
|
|
118
|
+
* A header without that parameter (`attachment` alone, or `null` when a
|
|
119
|
+
* proxy stripped it) falls back rather than producing a nameless file.
|
|
120
|
+
*/
|
|
121
|
+
export declare function csvFilenameOf(contentDisposition: string | null, storeName: string): string;
|
|
122
|
+
/** Why a cell's text could not become a value. */
|
|
123
|
+
export type CellProblem = "required" | "not_a_number" | "not_an_integer" | "not_a_boolean" | "not_a_date" | "not_a_datetime";
|
|
124
|
+
/** The one sentence rendered beside the offending cell, per problem. */
|
|
125
|
+
export declare const CELL_PROBLEM_COPY: Record<CellProblem, string>;
|
|
126
|
+
/**
|
|
127
|
+
* Turn the text an operator typed into the value the wire takes, for a column
|
|
128
|
+
* of `type`.
|
|
129
|
+
*
|
|
130
|
+
* `required` is applied to the EMPTY cell only (R-7): every other rule is the
|
|
131
|
+
* server's own, so a cell this returns `ok` for is a cell the server accepts.
|
|
132
|
+
* `string` is the one type that keeps the text as typed — trimming it would
|
|
133
|
+
* silently edit the operator's value.
|
|
134
|
+
*/
|
|
135
|
+
export declare function parseCell(type: ScalarType, text: string, required: boolean): {
|
|
136
|
+
ok: true;
|
|
137
|
+
value: string | number | boolean | undefined;
|
|
138
|
+
} | {
|
|
139
|
+
ok: false;
|
|
140
|
+
problem: CellProblem;
|
|
141
|
+
message: string;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* The text to put in a cell for an already-typed value.
|
|
145
|
+
*
|
|
146
|
+
* `undefined`/`null` render as the empty cell (never `"undefined"` or `"null"`);
|
|
147
|
+
* a string value for a string-ish column is shown as itself; a finite number
|
|
148
|
+
* and a boolean render as their JSON literals; anything else (an object cell,
|
|
149
|
+
* a `null` inside a document) falls back to its JSON text so the cell shows
|
|
150
|
+
* what the server holds rather than `[object Object]`.
|
|
151
|
+
*/
|
|
152
|
+
export declare function serializeCell(type: ScalarType, value: unknown): string;
|
|
153
|
+
/**
|
|
154
|
+
* Is an already-typed JSON value of `type`? The same rules {@linkcode parseCell}
|
|
155
|
+
* applies to text, applied to a value that came back from the server — the grid
|
|
156
|
+
* uses it to mark a row the server would refuse before the operator presses
|
|
157
|
+
* Save. `required` plays no part here: an absent value is the caller's problem
|
|
158
|
+
* to decide about, not this predicate's.
|
|
159
|
+
*/
|
|
160
|
+
export declare function isCellValue(type: ScalarType, value: unknown): boolean;
|
|
161
|
+
/** What is shown when the server said nothing a human can read. */
|
|
162
|
+
export declare const DATA_STORE_ERROR_FALLBACK = "The request failed.";
|
|
163
|
+
/** `rawRequest`'s `status: 0` — the request never reached the server. */
|
|
164
|
+
export declare const DATA_STORE_NETWORK_ERROR = "Could not reach the server.";
|
|
165
|
+
/** A failure, flattened into the fields the page needs and nothing else. */
|
|
166
|
+
export interface DataStoreErrorLocator {
|
|
167
|
+
/** Always present: the server's own sentence, or one of the two copy constants above. */
|
|
168
|
+
message: string;
|
|
169
|
+
/** The host's machine-readable code (`invalid_value`, `invalid_cursor`, …). */
|
|
170
|
+
code?: string;
|
|
171
|
+
/** The HTTP status; `0` is the transport-failure convention. */
|
|
172
|
+
status?: number;
|
|
173
|
+
/** The request-body field the host blamed. */
|
|
174
|
+
field?: string;
|
|
175
|
+
/** The 0-based CSV data row the host blamed (header excluded). */
|
|
176
|
+
row?: number;
|
|
177
|
+
/** The table column the host blamed. */
|
|
178
|
+
column?: string;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Locate a thrown JSON-call failure: an `ApiError` (whose parsed body lives on
|
|
182
|
+
* `.raw`), a plain `Error`, or anything else at all.
|
|
183
|
+
*
|
|
184
|
+
* The message falls back in that order — the envelope's `message`, the error's
|
|
185
|
+
* own `message`, then {@linkcode DATA_STORE_ERROR_FALLBACK} — so an unfamiliar
|
|
186
|
+
* throw still produces a sentence rather than an empty panel.
|
|
187
|
+
*/
|
|
188
|
+
export declare function locateDataStoreError(e: unknown): DataStoreErrorLocator;
|
|
189
|
+
/**
|
|
190
|
+
* Locate a CSV-call failure from P-RAW's `{status, text}` — the body is still
|
|
191
|
+
* unparsed text because that transport does not know the content type.
|
|
192
|
+
*
|
|
193
|
+
* `status: 0` means the request never produced a response, and gets the
|
|
194
|
+
* transport sentence rather than an attempt to parse an empty body. Otherwise
|
|
195
|
+
* the body is parsed iff it is JSON: an HTML error page from a proxy is
|
|
196
|
+
* `{status, message: fallback}`, not a crash.
|
|
197
|
+
*/
|
|
198
|
+
export declare function locateRawResponseError(res: {
|
|
199
|
+
status: number;
|
|
200
|
+
text: string;
|
|
201
|
+
}): DataStoreErrorLocator;
|
|
202
|
+
/** Where the message is rendered: under one table cell, under one form field, or over the whole form. */
|
|
203
|
+
export declare function errorPlacement(loc: DataStoreErrorLocator): {
|
|
204
|
+
kind: "cell";
|
|
205
|
+
column: string;
|
|
206
|
+
row?: number;
|
|
207
|
+
} | {
|
|
208
|
+
kind: "field";
|
|
209
|
+
field: string;
|
|
210
|
+
} | {
|
|
211
|
+
kind: "form";
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* The operator's 1-based line number in the CSV they uploaded, from the host's
|
|
215
|
+
* 0-based data-row index: the header row is line 1, so data row 0 is line 2.
|
|
216
|
+
*/
|
|
217
|
+
export declare function csvLineOf(row: number): number;
|
|
218
|
+
/**
|
|
219
|
+
* The draft id of a row that does not exist yet: a NUL-prefixed sentinel, which
|
|
220
|
+
* R-5 forbids a real key from ever being (no control characters in a key), so
|
|
221
|
+
* `id === NEW_ROW_ID` and "this row has no server-side key" are the same fact.
|
|
222
|
+
*/
|
|
223
|
+
export declare const NEW_ROW_ID = "\0new";
|
|
224
|
+
/** Rendered beside a row whose `ifVersion` was stale — never as the server's sentence alone. */
|
|
225
|
+
export declare const VERSION_CONFLICT_COPY = "Changed by someone else since you loaded it.";
|
|
226
|
+
/** A `doc` store holds a JSON object or array; anything else is not a document. */
|
|
227
|
+
export declare const DOC_VALUE_COPY = "Enter a JSON object or array.";
|
|
228
|
+
/** R-7's client-side ceiling copy — the check runs before anything is sent. */
|
|
229
|
+
export declare const CSV_TOO_LARGE_COPY = "The file is larger than 5 MB.";
|
|
230
|
+
/**
|
|
231
|
+
* One row's editable state: the id it is saved under (`entry.key`, or
|
|
232
|
+
* {@linkcode NEW_ROW_ID}), the version the save guards with (`null` for a new
|
|
233
|
+
* row) and the cell TEXT per declared column (never a parsed value — the text
|
|
234
|
+
* is what the operator is editing, and re-serialising it on every keystroke
|
|
235
|
+
* would fight their cursor).
|
|
236
|
+
*/
|
|
237
|
+
export interface RowDraft {
|
|
238
|
+
id: string;
|
|
239
|
+
version: number | null;
|
|
240
|
+
cells: Record<string, string>;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* An entry's value read as a table row: the object the server stored, or `{}`
|
|
244
|
+
* for anything that is not a plain object (a `null`, an array, a scalar from a
|
|
245
|
+
* column set that has since changed).
|
|
246
|
+
*/
|
|
247
|
+
export declare function rowValueOf(entry: Entry): Record<string, unknown>;
|
|
248
|
+
/** The draft an entry starts as: its key, its version, and each declared column's text. */
|
|
249
|
+
export declare function draftFromEntry(entry: Entry, columns: readonly TableColumn[]): RowDraft;
|
|
250
|
+
/**
|
|
251
|
+
* The draft a brand-new row starts as: {@linkcode NEW_ROW_ID}, no version, and
|
|
252
|
+
* each column seeded from its declared `default` (absent default = empty cell).
|
|
253
|
+
*/
|
|
254
|
+
export declare function newRowDraft(columns: readonly TableColumn[]): RowDraft;
|
|
255
|
+
/**
|
|
256
|
+
* Which declared columns the operator actually changed, in DECLARED order.
|
|
257
|
+
*
|
|
258
|
+
* Declared order (not object order) so the answer is stable across browsers and
|
|
259
|
+
* the row's Save button can decide "dirty" with one empty-array check. An
|
|
260
|
+
* untouched draft is `[]`.
|
|
261
|
+
*/
|
|
262
|
+
export declare function dirtyColumns(draft: RowDraft, base: RowDraft, columns: readonly TableColumn[]): string[];
|
|
263
|
+
/**
|
|
264
|
+
* The row body a Save sends, or the per-cell refusals that stop it.
|
|
265
|
+
*
|
|
266
|
+
* Every DECLARED column is parsed through {@linkcode parseCell} with its own
|
|
267
|
+
* `required` flag: an absent value omits the key entirely (R-7's empty-cell
|
|
268
|
+
* rule, so the host's default applies), a `string` cell keeps its text verbatim
|
|
269
|
+
* and every other type is the JSON value the server expects — never the typed
|
|
270
|
+
* text. Failures are keyed by column name so the caller renders them under the
|
|
271
|
+
* offending cell.
|
|
272
|
+
*/
|
|
273
|
+
export declare function buildRowValue(draft: RowDraft, columns: readonly TableColumn[]): {
|
|
274
|
+
ok: true;
|
|
275
|
+
value: Record<string, unknown>;
|
|
276
|
+
} | {
|
|
277
|
+
ok: false;
|
|
278
|
+
errors: Record<string, string>;
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* The `ttlSeconds` a save must resend so it does not CLEAR an existing expiry
|
|
282
|
+
* (S-1: a PUT without `ttlSeconds` sets `expires_at = NULL`).
|
|
283
|
+
*
|
|
284
|
+
* `undefined` for an entry that never expires, for an unparseable timestamp and
|
|
285
|
+
* for one already in the past — in all three cases sending nothing is correct
|
|
286
|
+
* (and a non-positive TTL is not a TTL the host accepts). Rounded UP, so a save
|
|
287
|
+
* one millisecond before the deadline does not shorten the entry's life.
|
|
288
|
+
*/
|
|
289
|
+
export declare function remainingTtlSeconds(expiresAt: string | null, nowMs: number): number | undefined;
|
|
290
|
+
/**
|
|
291
|
+
* Which request a draft implies: an INSERT (`POST entries`, no `ifVersion`) for
|
|
292
|
+
* a row that does not exist yet, otherwise a PUT under the row's key guarded by
|
|
293
|
+
* the version the operator loaded.
|
|
294
|
+
*
|
|
295
|
+
* `ttlSeconds` is present ONLY when the caller has one: it reaches the wire as
|
|
296
|
+
* a defining key, and an explicit `undefined` would be indistinguishable from
|
|
297
|
+
* "the caller measured nothing".
|
|
298
|
+
*/
|
|
299
|
+
export declare function rowWriteOf(draft: RowDraft, value: Record<string, unknown>, ttlSeconds: number | undefined): {
|
|
300
|
+
kind: "insert";
|
|
301
|
+
value: Record<string, unknown>;
|
|
302
|
+
ttlSeconds?: number;
|
|
303
|
+
} | {
|
|
304
|
+
kind: "put";
|
|
305
|
+
key: string;
|
|
306
|
+
value: Record<string, unknown>;
|
|
307
|
+
ifVersion: number;
|
|
308
|
+
ttlSeconds?: number;
|
|
309
|
+
};
|
|
310
|
+
/**
|
|
311
|
+
* The cell errors a refusal places, or `null` when it belongs somewhere else
|
|
312
|
+
* (the form, a request-body field, a column this table does not declare).
|
|
313
|
+
*
|
|
314
|
+
* `null` is load-bearing: the grid renders `grid-error` exactly when this
|
|
315
|
+
* returns `null`, so "the message shows in one slot" is a property of the
|
|
316
|
+
* answer rather than of the caller's care.
|
|
317
|
+
*/
|
|
318
|
+
export declare function cellErrorsOf(loc: DataStoreErrorLocator, columns: readonly TableColumn[]): Record<string, string> | null;
|
|
319
|
+
/**
|
|
320
|
+
* Is this failure the optimistic-concurrency refusal — and nothing else?
|
|
321
|
+
*
|
|
322
|
+
* `409` alone is not enough: `entry_exists` and `store_exists` share the status
|
|
323
|
+
* and neither is fixed by reloading, so both halves of the locator must agree.
|
|
324
|
+
*/
|
|
325
|
+
export declare function isVersionConflict(loc: DataStoreErrorLocator): boolean;
|
|
326
|
+
/**
|
|
327
|
+
* A `doc` store's value from the editor's text: any JSON object or array.
|
|
328
|
+
*
|
|
329
|
+
* A scalar is refused rather than wrapped — the store's own `doc` shape is an
|
|
330
|
+
* object/array (S-2), and the host would refuse `42` anyway; failing here means
|
|
331
|
+
* the operator sees why without a round trip. `null` parses but is not a
|
|
332
|
+
* document, so it is refused with the same sentence.
|
|
333
|
+
*/
|
|
334
|
+
export declare function parseDocText(text: string): {
|
|
335
|
+
ok: true;
|
|
336
|
+
value: object;
|
|
337
|
+
} | {
|
|
338
|
+
ok: false;
|
|
339
|
+
message: string;
|
|
340
|
+
};
|
|
341
|
+
/**
|
|
342
|
+
* A `kv` store's value from the editor's text.
|
|
343
|
+
*
|
|
344
|
+
* `string` is the one type whose text IS the value, empty string included (an
|
|
345
|
+
* empty `string` entry is a real value, not an absent one), so it never passes
|
|
346
|
+
* through {@linkcode parseCell} — which reads an empty cell as absent. Every
|
|
347
|
+
* other type is parsed exactly as a table cell would be, `required` on, because
|
|
348
|
+
* a kv entry always has a value.
|
|
349
|
+
*/
|
|
350
|
+
export declare function kvValueOf(type: ScalarType, text: string): {
|
|
351
|
+
ok: true;
|
|
352
|
+
value: unknown;
|
|
353
|
+
} | {
|
|
354
|
+
ok: false;
|
|
355
|
+
message: string;
|
|
356
|
+
};
|
|
357
|
+
/**
|
|
358
|
+
* What a CSV import's `RawResponse` says to the operator.
|
|
359
|
+
*
|
|
360
|
+
* The host is the only parser (R-7): a `200` reports how many rows it took, and
|
|
361
|
+
* a refusal is located rather than interpreted — a `row` becomes the operator's
|
|
362
|
+
* own 1-based line (`csvLineOf`), the `column` is named when the host named one,
|
|
363
|
+
* and everything else is the host's sentence verbatim.
|
|
364
|
+
*/
|
|
365
|
+
export declare function csvImportMessage(res: {
|
|
366
|
+
status: number;
|
|
367
|
+
text: string;
|
|
368
|
+
}): {
|
|
369
|
+
ok: boolean;
|
|
370
|
+
message: string;
|
|
371
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ActionDef } from './types.ts';
|
|
2
|
+
export interface EventbriteTriggerChoices {
|
|
3
|
+
triggerKey: string;
|
|
4
|
+
options: {
|
|
5
|
+
value: string;
|
|
6
|
+
label: string;
|
|
7
|
+
triggerKey: string;
|
|
8
|
+
}[];
|
|
9
|
+
selected: string[];
|
|
10
|
+
}
|
|
11
|
+
/** Eventbrite's activity trigger registers several events on one webhook. Keep its
|
|
12
|
+
* event catalog in the app manifest; the editor only adapts the existing trigger keys. */
|
|
13
|
+
export declare function eventbriteTriggerChoices(appId: string, triggers: ActionDef[] | null, triggerKey: string, values: Record<string, unknown>): EventbriteTriggerChoices | null;
|
package/dist/flow-connect.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Edge } from '@xyflow/react';
|
|
2
|
-
import {
|
|
2
|
+
import { LoopRefusalReason } from './flow-loop.ts';
|
|
3
|
+
import { CanvasLane, PortsLookup } from './flow-types.ts';
|
|
3
4
|
import { StepNode } from './flow-utils.ts';
|
|
4
5
|
/**
|
|
5
6
|
* Which lane a React Flow edge belongs to (core `rfcs/workflow.md` · `Edge.when`
|
|
@@ -8,7 +9,7 @@ import { StepNode } from './flow-utils.ts';
|
|
|
8
9
|
* `data` at all. The single accessor: every consumer calls this rather than
|
|
9
10
|
* re-deriving the fallback, so "absent means success" is decided once.
|
|
10
11
|
*/
|
|
11
|
-
export declare function edgeLane(e: Edge):
|
|
12
|
+
export declare function edgeLane(e: Edge): CanvasLane;
|
|
12
13
|
/**
|
|
13
14
|
* A refused connection: the source's exit port is full **in this lane** and the cap
|
|
14
15
|
* is finite. Drawing past a finite `out` cap is refused, never satisfied by evicting
|
|
@@ -18,14 +19,22 @@ export type OutCapRefusal = {
|
|
|
18
19
|
refused: "out_cap";
|
|
19
20
|
cap: number;
|
|
20
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* A refused connection that would break the v1 linear-body rule of a For each
|
|
24
|
+
* (see {@link loopRefusal}). Raised before the out-cap census and before any
|
|
25
|
+
* inbound eviction, always against the INPUT edges.
|
|
26
|
+
*/
|
|
27
|
+
export type LoopRefusal = {
|
|
28
|
+
refused: "loop";
|
|
29
|
+
reason: LoopRefusalReason;
|
|
30
|
+
};
|
|
21
31
|
/**
|
|
22
32
|
* The hard rules for an edge `source → target` — the ones no amount of
|
|
23
33
|
* replacement can satisfy: a real, *distinct* pair (no self-loops), no duplicate
|
|
24
34
|
* edge, the target accepts an entry port (blocks connecting *into* a trigger,
|
|
25
35
|
* which declares `in: 0`), and the source has an exit port. Port **capacity** is
|
|
26
|
-
* deliberately NOT checked here:
|
|
27
|
-
*
|
|
28
|
-
* re-points it rather than being rejected. Used as the live `isValidConnection`.
|
|
36
|
+
* deliberately NOT checked here: an input accepts any number of edges, and the exit
|
|
37
|
+
* cap is refused in `applyConnect`. Used as the live `isValidConnection`.
|
|
29
38
|
*
|
|
30
39
|
* The duplicate-pair check is **lane-blind by design**, and that is a v1 *editor*
|
|
31
40
|
* limit, not a model limit: the model permits a success edge and an error edge
|
|
@@ -41,13 +50,13 @@ export type OutCapRefusal = {
|
|
|
41
50
|
* Letting the drop through and refusing in `applyConnect` is what lets the reason
|
|
42
51
|
* paint — see {@link connectConflict}.
|
|
43
52
|
*/
|
|
44
|
-
export declare function canConnect(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], lookup?: PortsLookup): boolean;
|
|
53
|
+
export declare function canConnect(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], lookup?: PortsLookup, route?: string): boolean;
|
|
45
54
|
/**
|
|
46
55
|
* Build the next edge set for a new `source → target` connection. **Additive at the
|
|
47
56
|
* source**: a source under its `out` cap (or unbounded) keeps every existing edge and
|
|
48
57
|
* gains one; at a finite cap the connection is **refused** (see {@link connectRefusal}),
|
|
49
|
-
* never satisfied by evicting. The target's entry port
|
|
50
|
-
*
|
|
58
|
+
* never satisfied by evicting. The target's entry port accepts any number of
|
|
59
|
+
* inbound edges, so nothing is ever evicted there. Returns `null` when the
|
|
51
60
|
* connection is disallowed by {@link canConnect}, refused at the out cap — **or when the minted id would
|
|
52
61
|
* duplicate a surviving edge's id**, the same refusal {@link setEdgeWhen} performs
|
|
53
62
|
* through the same {@link collidingEdgeId} test.
|
|
@@ -68,13 +77,10 @@ export declare function canConnect(source: string | null | undefined, target: st
|
|
|
68
77
|
* `send → (error) → fallback` shape authorable at all. No `ports.out` bump is
|
|
69
78
|
* needed, so every persisted definition and palette entry stays valid.
|
|
70
79
|
*
|
|
71
|
-
* The target's entry capacity
|
|
72
|
-
*
|
|
73
|
-
* governed by `ports.in` alone. Partitioning the target rule by lane too — the
|
|
74
|
-
* plausible "symmetry" cleanup — would let a `ports.in: 1` node silently accept
|
|
75
|
-
* two inbound edges.
|
|
80
|
+
* The target's entry has no capacity: any number of edges, from any number of
|
|
81
|
+
* sources (several triggers may feed one node), converge on it.
|
|
76
82
|
*/
|
|
77
|
-
export declare function applyConnect(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?:
|
|
83
|
+
export declare function applyConnect(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?: CanvasLane, lookup?: PortsLookup, route?: string): Edge[] | null;
|
|
78
84
|
/**
|
|
79
85
|
* The id of the existing edge that drawing `source → target` would collide with, or
|
|
80
86
|
* `null` when the connection is safe (or refused for an ordinary reason — a
|
|
@@ -85,13 +91,13 @@ export declare function applyConnect(source: string | null | undefined, target:
|
|
|
85
91
|
* selects that edge and renders the message in the edge-lane panel (never a browser
|
|
86
92
|
* dialog; see `.ai/conventions.md`).
|
|
87
93
|
*/
|
|
88
|
-
export declare function connectConflict(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?:
|
|
94
|
+
export declare function connectConflict(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?: CanvasLane, lookup?: PortsLookup, route?: string): string | null;
|
|
89
95
|
/**
|
|
90
96
|
* The out-cap refusal for drawing `source → target`, or `null` when the source has
|
|
91
97
|
* room (or is unbounded). The editor renders `cap` in an inline message on the same
|
|
92
98
|
* channel as {@link connectConflict}; {@link applyConnect} returns `null` for it.
|
|
93
99
|
*/
|
|
94
|
-
export declare function connectRefusal(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?:
|
|
100
|
+
export declare function connectRefusal(source: string | null | undefined, target: string | null | undefined, nodes: StepNode[], edges: Edge[], when?: CanvasLane, lookup?: PortsLookup, route?: string): OutCapRefusal | LoopRefusal | null;
|
|
95
101
|
/**
|
|
96
102
|
* Re-lane one edge. Updates its `data.when`, its visuals and its id, and frees
|
|
97
103
|
* nothing: when the destination lane is at a finite out cap the switch is refused
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { FlowCanvas } from './canvas-types.ts';
|
|
3
|
+
import { StepNode } from './flow-utils.ts';
|
|
4
|
+
export interface FlowDeleteSelection {
|
|
5
|
+
nodeIds: string[];
|
|
6
|
+
edgeIds: string[];
|
|
7
|
+
}
|
|
8
|
+
/** Capture the full selection, independently of the first item shown in the side panel. */
|
|
9
|
+
export declare function selectedFlowElements(nodes: StepNode[], edges: Edge[]): FlowDeleteSelection;
|
|
10
|
+
/** Apply the entire confirmed selection before the editor emits one change/history entry. */
|
|
11
|
+
export declare function deleteFlowSelection(selection: FlowDeleteSelection, nodes: StepNode[], edges: Edge[], canvas: FlowCanvas): {
|
|
12
|
+
nodes: StepNode[];
|
|
13
|
+
edges: Edge[];
|
|
14
|
+
canvas: FlowCanvas;
|
|
15
|
+
};
|
|
16
|
+
export declare function flowDeleteMessage(selection: FlowDeleteSelection, nodes: StepNode[], edges: Edge[]): string;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { FlowCanvas } from './canvas-types.ts';
|
|
3
|
+
import { FlowStep, FlowWorkflow } from './flow-types.ts';
|
|
4
|
+
import { StepNode } from './flow-utils.ts';
|
|
5
|
+
/** Only authored graph data. Tests, samples, run paint, selection and viewport never enter history. */
|
|
6
|
+
export interface FlowEditSnapshot {
|
|
7
|
+
nodes: FlowStep[];
|
|
8
|
+
edges: NonNullable<FlowWorkflow["edges"]>;
|
|
9
|
+
connections: NonNullable<FlowWorkflow["connections"]>;
|
|
10
|
+
canvas: FlowCanvas;
|
|
11
|
+
/** Keep the live layout even when saving positions is switched off. */
|
|
12
|
+
positions: Record<string, {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
export declare function captureFlowEdit(base: FlowWorkflow, nodes: StepNode[], edges: Edge[], connections: FlowEditSnapshot["connections"], canvas: FlowCanvas): FlowEditSnapshot;
|
|
18
|
+
export declare function restoreFlowEdit(base: FlowWorkflow, snapshot: FlowEditSnapshot): {
|
|
19
|
+
nodes: {
|
|
20
|
+
position: {
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
};
|
|
24
|
+
id: string;
|
|
25
|
+
data: import('./flow-utils.ts').StepNodeData;
|
|
26
|
+
sourcePosition?: import('@xyflow/react').Position;
|
|
27
|
+
targetPosition?: import('@xyflow/react').Position;
|
|
28
|
+
hidden?: boolean;
|
|
29
|
+
selected?: boolean;
|
|
30
|
+
dragging?: boolean;
|
|
31
|
+
draggable?: boolean;
|
|
32
|
+
selectable?: boolean;
|
|
33
|
+
connectable?: boolean;
|
|
34
|
+
deletable?: boolean;
|
|
35
|
+
dragHandle?: string;
|
|
36
|
+
width?: number;
|
|
37
|
+
height?: number;
|
|
38
|
+
initialWidth?: number;
|
|
39
|
+
initialHeight?: number;
|
|
40
|
+
parentId?: string;
|
|
41
|
+
zIndex?: number;
|
|
42
|
+
extent?: "parent" | import('@xyflow/react').CoordinateExtent | null;
|
|
43
|
+
expandParent?: boolean;
|
|
44
|
+
ariaLabel?: string;
|
|
45
|
+
origin?: import('@xyflow/react').NodeOrigin;
|
|
46
|
+
handles?: import('@xyflow/react').NodeHandle[];
|
|
47
|
+
measured?: {
|
|
48
|
+
width?: number;
|
|
49
|
+
height?: number;
|
|
50
|
+
};
|
|
51
|
+
type?: string | undefined;
|
|
52
|
+
style?: import('react').CSSProperties;
|
|
53
|
+
className?: string;
|
|
54
|
+
resizing?: boolean;
|
|
55
|
+
focusable?: boolean;
|
|
56
|
+
ariaRole?: import('react').AriaRole;
|
|
57
|
+
domAttributes?: Omit<import('react').HTMLAttributes<HTMLDivElement>, "id" | "style" | "className" | "draggable" | "role" | "aria-label" | "defaultValue" | "dangerouslySetInnerHTML" | keyof import('react').DOMAttributes<HTMLDivElement>>;
|
|
58
|
+
}[];
|
|
59
|
+
edges: Edge[];
|
|
60
|
+
};
|
|
61
|
+
/** Bounded, editor-session history. One text-field focus session is one undoable edit. */
|
|
62
|
+
export declare class FlowEditHistory {
|
|
63
|
+
private past;
|
|
64
|
+
private future;
|
|
65
|
+
private present;
|
|
66
|
+
private group;
|
|
67
|
+
private readonly limit;
|
|
68
|
+
constructor(initial: FlowEditSnapshot, limit?: number);
|
|
69
|
+
reset(initial: FlowEditSnapshot): void;
|
|
70
|
+
record(snapshot: FlowEditSnapshot, group?: object): void;
|
|
71
|
+
undo(): FlowEditSnapshot | undefined;
|
|
72
|
+
redo(): FlowEditSnapshot | undefined;
|
|
73
|
+
}
|
|
74
|
+
/** Leave native text undo and CodeMirror's own history alone. */
|
|
75
|
+
export declare function isFlowTextTarget(target: EventTarget | null): boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { FlowCanvas } from './canvas-types.ts';
|
|
3
|
+
import { StepNode } from './flow-utils.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Arrange paths and their section frames together. Membership is authored data:
|
|
6
|
+
* fit each frame to its members, never infer new membership from moved geometry.
|
|
7
|
+
* A section spanning non-members is moved with its members below the obstruction.
|
|
8
|
+
* Notes and empty sections retain their authored geometry.
|
|
9
|
+
*/
|
|
10
|
+
export declare function relayoutFlow(nodes: StepNode[], edges: Edge[], canvas: FlowCanvas): {
|
|
11
|
+
nodes: StepNode[];
|
|
12
|
+
canvas: FlowCanvas;
|
|
13
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Edge } from '@xyflow/react';
|
|
2
|
+
import { CSSProperties } from 'react';
|
|
3
|
+
import { StepNode } from './flow-utils.ts';
|
|
4
|
+
/** How many `--w6w-loop-N` tokens `_tokens.scss` defines. */
|
|
5
|
+
export declare const LOOP_TONES = 6;
|
|
6
|
+
/**
|
|
7
|
+
* Tone index (1-based) per For each id. Ids are visited in sorted order so the result
|
|
8
|
+
* does not depend on node order; each takes its hashed tone, or the next free one.
|
|
9
|
+
*/
|
|
10
|
+
export declare function assignLoopTones(foreachIds: Iterable<string>): Map<string, number>;
|
|
11
|
+
/** The CSS colour for a tone index. */
|
|
12
|
+
export declare function loopToneVar(tone: number): string;
|
|
13
|
+
/** The loops enclosing `id`, outermost first, following each For each's own `loopOf`. */
|
|
14
|
+
export declare function enclosingLoops(id: string, loopOfById: ReadonlyMap<string, string | undefined>): string[];
|
|
15
|
+
/**
|
|
16
|
+
* Paint each-lane edges with the colour of the loop they belong to: the For each itself
|
|
17
|
+
* for its Each item link, else the loop the edge's source step runs in. Sets the
|
|
18
|
+
* `--w6w-loop-color` custom property the `.w6w-edge-each` rule reads, so run-state
|
|
19
|
+
* classes still compose over it. Same array when nothing needs painting.
|
|
20
|
+
*/
|
|
21
|
+
export declare function paintLoopEdges(edges: Edge[], tones: ReadonlyMap<string, number>, loopOfById: ReadonlyMap<string, string | undefined>): Edge[];
|
|
22
|
+
/**
|
|
23
|
+
* The colour custom property a card's root carries: a For each's own tone, read by its
|
|
24
|
+
* Each item port. A loop-body step gets none — it looks exactly like a step outside a
|
|
25
|
+
* loop; its dots are what mark it.
|
|
26
|
+
*/
|
|
27
|
+
export declare function loopCardStyle(id: string, tones: ReadonlyMap<string, number>): CSSProperties | undefined;
|
|
28
|
+
/** What the canvas paints loops from: each For each's tone, and each step's own loop. */
|
|
29
|
+
export type LoopPaint = {
|
|
30
|
+
tones: ReadonlyMap<string, number>;
|
|
31
|
+
loopOf: ReadonlyMap<string, string | undefined>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A string that changes only when a loop's membership does — the memo key for
|
|
35
|
+
* {@link loopPaint}, so dragging a node does not hand every card a new context value.
|
|
36
|
+
*/
|
|
37
|
+
export declare function loopPaintKey(nodes: readonly StepNode[]): string;
|
|
38
|
+
/** Rebuild the {@link LoopPaint} a {@link loopPaintKey} describes. */
|
|
39
|
+
export declare function loopPaint(key: string): LoopPaint;
|