@ngis/plugin-ui 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +13 -0
- package/README.md +25 -0
- package/dist/index.cjs +71 -0
- package/dist/index.d.ts +114 -0
- package/dist/index.mjs +69 -0
- package/dist/src/api/analysis.d.ts +140 -0
- package/dist/src/api/resources.d.ts +530 -0
- package/dist/src/api/scenes.d.ts +251 -0
- package/dist/src/api/users.d.ts +22 -0
- package/dist/src/api/workflows.d.ts +191 -0
- package/dist/src/components/plugin-ui/AttributeTable.d.ts +26 -0
- package/dist/src/components/plugin-ui/BatchTable.d.ts +47 -0
- package/dist/src/components/plugin-ui/ChartCanvas.d.ts +14 -0
- package/dist/src/components/plugin-ui/ExtentPicker.d.ts +22 -0
- package/dist/src/components/plugin-ui/FieldSelect.d.ts +23 -0
- package/dist/src/components/plugin-ui/Flow.d.ts +256 -0
- package/dist/src/components/plugin-ui/ModelSelect.d.ts +36 -0
- package/dist/src/components/plugin-ui/ParamForm.d.ts +63 -0
- package/dist/src/components/plugin-ui/PickerField.d.ts +52 -0
- package/dist/src/components/plugin-ui/ResourceSelect.d.ts +37 -0
- package/dist/src/components/plugin-ui/ResultActions.d.ts +48 -0
- package/dist/src/components/plugin-ui/RunButton.d.ts +49 -0
- package/dist/src/components/plugin-ui/StatChart.d.ts +66 -0
- package/dist/src/components/plugin-ui/TaskChrome.d.ts +35 -0
- package/dist/src/components/plugin-ui/TaskList.d.ts +29 -0
- package/dist/src/components/plugin-ui/TaskStatus.d.ts +55 -0
- package/dist/src/components/plugin-ui/batch-model.d.ts +442 -0
- package/dist/src/components/plugin-ui/flow-inputs.d.ts +61 -0
- package/dist/src/components/plugin-ui/flow-model.d.ts +303 -0
- package/dist/src/components/plugin-ui/flow-ports.d.ts +155 -0
- package/dist/src/components/plugin-ui/param-form-data.d.ts +122 -0
- package/dist/src/components/plugin-ui/param-form-model.d.ts +187 -0
- package/dist/src/components/plugin-ui/param-widgets.d.ts +88 -0
- package/dist/src/components/plugin-ui/picker-data.d.ts +141 -0
- package/dist/src/components/plugin-ui/picker-model.d.ts +150 -0
- package/dist/src/components/plugin-ui/recipe-model.d.ts +320 -0
- package/dist/src/components/plugin-ui/result-data.d.ts +112 -0
- package/dist/src/components/plugin-ui/result-model.d.ts +96 -0
- package/dist/src/components/plugin-ui/run-data.d.ts +118 -0
- package/dist/src/components/plugin-ui/run-model.d.ts +179 -0
- package/dist/src/components/plugin-ui/stat-chart-model.d.ts +168 -0
- package/dist/src/components/plugin-ui/validation-messages.d.ts +18 -0
- package/dist/src/components/plugin-ui/w2-contracts.d.ts +151 -0
- package/dist/src/components/plugin-ui/w3-contracts.d.ts +328 -0
- package/dist/src/components/plugin-ui/w4-contracts.d.ts +510 -0
- package/dist/src/components/ui/button.d.ts +12 -0
- package/dist/src/components/ui/checkbox.d.ts +4 -0
- package/dist/src/components/ui/column-resize-handle.d.ts +23 -0
- package/dist/src/components/ui/dropdown-menu.d.ts +25 -0
- package/dist/src/components/ui/input.d.ts +3 -0
- package/dist/src/components/ui/label.d.ts +4 -0
- package/dist/src/components/ui/popover.d.ts +10 -0
- package/dist/src/components/ui/select.d.ts +15 -0
- package/dist/src/components/ui/switch.d.ts +6 -0
- package/dist/src/domain/map/types.d.ts +128 -0
- package/dist/src/features/gis/components/GisAttributeTable.d.ts +56 -0
- package/dist/src/features/gis/hooks/useDatasetFeatureWindow.d.ts +51 -0
- package/dist/src/lib/api-error.d.ts +81 -0
- package/dist/src/lib/api.d.ts +82 -0
- package/dist/src/lib/auth-session.d.ts +22 -0
- package/dist/src/lib/hooks/useColumnResize.d.ts +57 -0
- package/dist/src/lib/raster-color-layer/RasterColorLayer.d.ts +48 -0
- package/dist/src/lib/raster-color-layer/TileGrid.d.ts +31 -0
- package/dist/src/lib/raster-color-layer/colorRamp.d.ts +18 -0
- package/dist/src/lib/raster-color-layer/shaders/raster-color.frag.d.ts +2 -0
- package/dist/src/lib/raster-color-layer/shaders/raster-color.vert.d.ts +2 -0
- package/dist/src/lib/raster-color-layer/zoomInterpolate.d.ts +2 -0
- package/dist/src/lib/utils.d.ts +2 -0
- package/dist/src/sdk/facets/types.d.ts +370 -0
- package/dist/src/sdk/host-api.d.ts +256 -0
- package/dist/src/sdk/map-api.d.ts +288 -0
- package/dist/src/sdk/panels.d.ts +130 -0
- package/dist/src/types/analysis.d.ts +205 -0
- package/dist/src/types/common.d.ts +17 -0
- package/dist/src/types/extensions.d.ts +560 -0
- package/dist/src/types/gis.d.ts +242 -0
- package/dist/src/types/market-social.d.ts +378 -0
- package/dist/src/types/workflow.d.ts +83 -0
- package/package.json +59 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { NgisHostAPI } from "../../sdk/host-api";
|
|
2
|
+
import { type NgisTaskVariant } from "./TaskStatus";
|
|
3
|
+
export interface TaskListProps {
|
|
4
|
+
host: NgisHostAPI;
|
|
5
|
+
/** The flow port scope id (F14.5). Also seeds the DOM id. */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Plugin-authored; rendered **literally** (F13.11). */
|
|
8
|
+
label?: string;
|
|
9
|
+
/**
|
|
10
|
+
* The tasks to show. Empty renders a reason, not a blank panel.
|
|
11
|
+
*
|
|
12
|
+
* Inside a `<Flow>`, **one** entry may be a reference (`"@run.taskId"`): F14.5
|
|
13
|
+
* gives this component a single `taskId` in port, and a bound port contributes a
|
|
14
|
+
* one-element list, so the resolved value joins the literal ids. A second
|
|
15
|
+
* reference has no port to bind to and is surfaced rather than watched.
|
|
16
|
+
*/
|
|
17
|
+
taskIds: readonly string[];
|
|
18
|
+
/** Defaults to `full` — the point of the list is the detail. */
|
|
19
|
+
variant?: NgisTaskVariant;
|
|
20
|
+
/**
|
|
21
|
+
* Hide rows whose lifecycle has finished. **`SUCCESS` while integration is
|
|
22
|
+
* still pending is not finished** ({@link isTerminalTaskState}), so such a row
|
|
23
|
+
* survives this filter — collapsing it would be the `complete`/`integrated`
|
|
24
|
+
* conflation the whole facet is built to prevent.
|
|
25
|
+
*/
|
|
26
|
+
activeOnly?: boolean;
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function TaskList({ host, id, label, taskIds: taskIdsProp, variant, activeOnly, className, }: TaskListProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { NgisHostAPI } from "../../sdk/host-api";
|
|
2
|
+
import type { NgisTaskState } from "../../sdk/facets/types";
|
|
3
|
+
export type NgisTaskVariant = "compact" | "full";
|
|
4
|
+
export interface NgisWatchedTasks {
|
|
5
|
+
/** Keyed by task id; absent until the first update for that id arrives. */
|
|
6
|
+
readonly states: Readonly<Record<string, NgisTaskState>>;
|
|
7
|
+
/** A `watch` that threw synchronously — a scope refusal, most likely. */
|
|
8
|
+
readonly error: unknown;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* One watcher per id, opened on mount and closed on change or unmount.
|
|
12
|
+
*
|
|
13
|
+
* `watch` is synchronous and returns the watcher, so a scope refusal
|
|
14
|
+
* (`tasks:read`) throws *here* rather than rejecting later — caught and reported,
|
|
15
|
+
* because an unhandled throw in an effect takes the whole panel down and tells the
|
|
16
|
+
* author nothing.
|
|
17
|
+
*
|
|
18
|
+
* The dependency is the **joined** id list: `taskIds` is typically a fresh array
|
|
19
|
+
* literal every render, and depending on its identity would tear every watcher
|
|
20
|
+
* down and rebuild it on each keystroke elsewhere in the panel.
|
|
21
|
+
*/
|
|
22
|
+
export declare function useWatchedTaskStates(host: NgisHostAPI, taskIds: readonly string[]): NgisWatchedTasks;
|
|
23
|
+
export interface TaskStateViewProps {
|
|
24
|
+
host: NgisHostAPI;
|
|
25
|
+
state: NgisTaskState;
|
|
26
|
+
variant: NgisTaskVariant;
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The presentation of one `NgisTaskState`, shared by both surfaces so
|
|
31
|
+
* `<TaskList>` is genuinely `<TaskStatus>` repeated rather than a second
|
|
32
|
+
* rendering of the same facts. Not on `@ngis/plugin-ui`'s export table — it is an
|
|
33
|
+
* internal of this pair.
|
|
34
|
+
*/
|
|
35
|
+
export declare function TaskStateView({ host, state, variant, className }: TaskStateViewProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
export interface TaskStatusProps {
|
|
37
|
+
host: NgisHostAPI;
|
|
38
|
+
/** The flow port scope id (F14.5). Also seeds the DOM id. */
|
|
39
|
+
id?: string;
|
|
40
|
+
/** Plugin-authored; rendered **literally** (F13.11). */
|
|
41
|
+
label?: string;
|
|
42
|
+
/**
|
|
43
|
+
* The bound `taskId` port value. `null` renders a reason, not an empty box.
|
|
44
|
+
*
|
|
45
|
+
* Inside a `<Flow>` this may be a **reference** — F14.22 writes
|
|
46
|
+
* `taskId="@run.taskId"` — which is resolved through the `taskId` in port.
|
|
47
|
+
* Outside a scope, or for a string that is not a reference, it is the task id
|
|
48
|
+
* itself; `"@@"` opens a literal.
|
|
49
|
+
*/
|
|
50
|
+
taskId: string | null;
|
|
51
|
+
variant?: NgisTaskVariant;
|
|
52
|
+
onStateChange?: (state: NgisTaskState) => void;
|
|
53
|
+
className?: string;
|
|
54
|
+
}
|
|
55
|
+
export declare function TaskStatus({ host, id, label, taskId: taskIdProp, variant, onStateChange, className, }: TaskStatusProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<BatchTable>`'s pure half (Stage 14 Y7 — **F14.21**, F14.9, F14.4).
|
|
3
|
+
*
|
|
4
|
+
* The seam this stage has now used five times — `picker-model`/`picker-data`,
|
|
5
|
+
* `param-form-model`, `run-model`, `flow-model`, and here. Nothing below imports
|
|
6
|
+
* React, a host, an API client or the DOM, and for batch that is load-bearing
|
|
7
|
+
* rather than stylistic: **two of F14.21's three hard rules are statements about
|
|
8
|
+
* scheduling**, and a rule that lives in a `useEffect` cannot be asserted.
|
|
9
|
+
*
|
|
10
|
+
* | F14.21 rule | where it lives here |
|
|
11
|
+
* |---|---|
|
|
12
|
+
* | one `host.tasks.run` per row | {@link runBatchQueue}, one `submit` call per row id |
|
|
13
|
+
* | a **concurrency cap of 3** | {@link batchQueueDispatch} + {@link NGIS_BATCH_CONCURRENCY} |
|
|
14
|
+
* | **a failed row does not cancel the rest** | {@link settleBatchQueueRow} — see below |
|
|
15
|
+
* | one row per run, same generated widgets | {@link batchColumns} + one {@link NgisParamFormState} per row |
|
|
16
|
+
* | JSON-saveable | {@link toBatchConfig} / {@link parseBatchConfig} / {@link fromBatchConfig} |
|
|
17
|
+
*
|
|
18
|
+
* **"A failed row does not cancel the rest" is expressed as an absence.** The
|
|
19
|
+
* queue has no notion of success or failure at all: {@link settleBatchQueueRow}
|
|
20
|
+
* moves a row from `running` to `settled` and takes no outcome, so there is no
|
|
21
|
+
* arm in which it could stop. A queue that read the outcome and *chose* to
|
|
22
|
+
* continue would be one edit away from choosing not to; a queue that cannot see
|
|
23
|
+
* the outcome cannot regress. {@link runBatchQueue} therefore catches everything
|
|
24
|
+
* `submit` can do — resolve, reject, or throw synchronously — and turns each into
|
|
25
|
+
* a per-row result rather than a rejected batch.
|
|
26
|
+
*
|
|
27
|
+
* **The cap is not a tuning knob** (F14.21, and the seam says so again at
|
|
28
|
+
* `w4-contracts.ts:614-621`): the task fabric and the `UsageLimiter` windows are
|
|
29
|
+
* shared and nothing below this line bounds concurrency. {@link runBatchQueue}
|
|
30
|
+
* measures its own {@link NgisBatchRunReport.peakInFlight} so the cap is
|
|
31
|
+
* assertable from the runner's own report rather than from a test's
|
|
32
|
+
* instrumentation of the callback it passed in.
|
|
33
|
+
*
|
|
34
|
+
* ## Each row is a whole `ParamForm` lifecycle, not a row of raw strings
|
|
35
|
+
*
|
|
36
|
+
* F14.21's *"the same generated widgets per cell"* means the cell values are
|
|
37
|
+
* subject to the same four phases as a single-run form (F14.9), including the one
|
|
38
|
+
* hard rule — *a repopulate never overwrites a field whose `altered` is `true`* —
|
|
39
|
+
* and including `depends_on` visibility, which is **per row**: two rows of one
|
|
40
|
+
* tool can legitimately disagree about whether a parameter applies. So a row
|
|
41
|
+
* holds an {@link NgisParamFormState} and every mutation goes through
|
|
42
|
+
* `param-form-model.ts`. Nothing here re-implements a phase.
|
|
43
|
+
*
|
|
44
|
+
* ## Expression-driven row generation is OUT for v1
|
|
45
|
+
*
|
|
46
|
+
* F14.21, verbatim. {@link fillBatchColumnDown} is *not* that: it copies the
|
|
47
|
+
* first row's value into the others, which is QGIS's own "fill down" and involves
|
|
48
|
+
* no expression, no grammar and no new vocabulary. Anything that computed a value
|
|
49
|
+
* would need a third grammar, which F14.4 forbids outright.
|
|
50
|
+
*/
|
|
51
|
+
import type { NgisToolUiParam, NgisToolUiSchema } from "../../types/analysis";
|
|
52
|
+
import { type NgisParamFormError, type NgisParamFormState } from "./param-form-model";
|
|
53
|
+
import type { NgisRunOutcome } from "./run-data";
|
|
54
|
+
import type { NgisParamValue, NgisRunSubmission } from "./w2-contracts";
|
|
55
|
+
import { type NgisBatchConfig, type NgisRecipe } from "./w4-contracts";
|
|
56
|
+
/**
|
|
57
|
+
* The kickoff seam's rows, re-exported here so the barrels take them from this
|
|
58
|
+
* module and `w4-contracts.ts` stays a wave artifact — the same rule
|
|
59
|
+
* `flow-model.ts` keeps for `w3-contracts.ts` (and `w4-contracts.ts:26-31` states
|
|
60
|
+
* for itself). Nothing is re-declared: these are the seam's own definitions.
|
|
61
|
+
*
|
|
62
|
+
* **`recipeColumns` is deliberately NOT re-exported here — `recipe-model.ts`
|
|
63
|
+
* publishes it, and this module only imports it.** Found at the W4 merge, and it
|
|
64
|
+
* is the shape of defect the merge exists to catch: it is the one seam function
|
|
65
|
+
* *both* W4 sessions read, so each re-exported it from its own labelled hunk in
|
|
66
|
+
* the host barrel, the two hunks are disjoint so the merge was textually clean,
|
|
67
|
+
* and the result was `error TS2300: Duplicate identifier 'recipeColumns'` that
|
|
68
|
+
* **neither branch could produce alone**. The rule the kickoff should have
|
|
69
|
+
* carved and did not: a *shared* seam row is published by exactly one owner, and
|
|
70
|
+
* for a recipe function that owner is the session that owns recipes. Y7's own
|
|
71
|
+
* `recipeBatchColumns` — which composes it with the batch's column projection —
|
|
72
|
+
* is unaffected and is genuinely Y7's.
|
|
73
|
+
*/
|
|
74
|
+
export { NGIS_BATCH_CONCURRENCY, NGIS_BATCH_VERSION, ngisBatchCellId, } from "./w4-contracts";
|
|
75
|
+
export type { NgisBatchConfig } from "./w4-contracts";
|
|
76
|
+
/**
|
|
77
|
+
* Something the table found in its own inputs. **Surfaced, never masked** — the
|
|
78
|
+
* `ExtensionSettingsForm` rule that F14.9 already applies to an author's
|
|
79
|
+
* `widgets`/`hide` overrides, applied to a saved config and to a recipe's
|
|
80
|
+
* promoted inputs.
|
|
81
|
+
*
|
|
82
|
+
* None of these is a refusal. The only refusal is an unknown `batchVersion`, and
|
|
83
|
+
* it is an arm of {@link NgisBatchConfigParse} rather than a defect, because
|
|
84
|
+
* F14.21 carries F14.2's rule verbatim: a reader that does not know the version
|
|
85
|
+
* **refuses**; it never best-efforts.
|
|
86
|
+
*/
|
|
87
|
+
export interface NgisBatchDefect {
|
|
88
|
+
readonly kind:
|
|
89
|
+
/** A column that is not a parameter of the loaded schema. */
|
|
90
|
+
"unknown-column"
|
|
91
|
+
/** The config was authored against a different tool. */
|
|
92
|
+
| "tool-mismatch"
|
|
93
|
+
/** Same tool, different `tool_version`. */
|
|
94
|
+
| "version-mismatch"
|
|
95
|
+
/**
|
|
96
|
+
* A saved value F14.9's *mutate* replaced on load — off the parameter's
|
|
97
|
+
* current `choices`, or uncoercible to its `value_type`.
|
|
98
|
+
*
|
|
99
|
+
* **This is the one silent data loss a batch config can suffer, and finding
|
|
100
|
+
* it is why the defect exists.** `initializeParamForm` seeds with
|
|
101
|
+
* `altered: false` (F14.9's text is explicit), and *mutate* drops an
|
|
102
|
+
* unaltered value the current option list no longer offers — so a config
|
|
103
|
+
* carrying `MODE: "legacy"` for a tool whose choices are now
|
|
104
|
+
* `simple|advanced|expert` loads as `"simple"` with nothing on screen. The
|
|
105
|
+
* rule is right and is not changed here; what was missing was anybody saying
|
|
106
|
+
* so. `subject` is the parameter, `detail` the value that was dropped.
|
|
107
|
+
*/
|
|
108
|
+
| "dropped-value";
|
|
109
|
+
readonly subject: string;
|
|
110
|
+
readonly detail: string | null;
|
|
111
|
+
}
|
|
112
|
+
/** One run. */
|
|
113
|
+
export interface NgisBatchRow {
|
|
114
|
+
/**
|
|
115
|
+
* Stable for the row's whole life, minted from {@link
|
|
116
|
+
* NgisBatchTableState.nextRowId} and **never reused** — it is the React key,
|
|
117
|
+
* and a reused key would carry one row's widget state onto another.
|
|
118
|
+
*
|
|
119
|
+
* Deliberately *not* the cell-id seed: {@link ngisBatchCellId} takes a **row
|
|
120
|
+
* index**, and that spelling is the seam's (CORRECTION 10). See
|
|
121
|
+
* {@link batchCellId}.
|
|
122
|
+
*/
|
|
123
|
+
readonly id: string;
|
|
124
|
+
/** F14.9's state for this row, in full. */
|
|
125
|
+
readonly form: NgisParamFormState;
|
|
126
|
+
/**
|
|
127
|
+
* Values from a loaded config whose keys name no parameter of the current
|
|
128
|
+
* schema. Carried verbatim so a load-then-save cannot silently delete an
|
|
129
|
+
* author's data — the same reason F14.9 keeps unknown override keys.
|
|
130
|
+
*/
|
|
131
|
+
readonly extras: Readonly<Record<string, string>>;
|
|
132
|
+
}
|
|
133
|
+
export interface NgisBatchTableState {
|
|
134
|
+
readonly toolId: string;
|
|
135
|
+
readonly toolVersion: number;
|
|
136
|
+
/** UI-schema param names, in display order (F14.21). */
|
|
137
|
+
readonly columns: readonly string[];
|
|
138
|
+
readonly rows: readonly NgisBatchRow[];
|
|
139
|
+
readonly outputMode: "ADD_LAYER" | "UPDATE_RESOURCE";
|
|
140
|
+
readonly sceneId: string | null;
|
|
141
|
+
readonly defects: readonly NgisBatchDefect[];
|
|
142
|
+
/** Next row-id ordinal. Monotonic, so ids are unique across removals. */
|
|
143
|
+
readonly nextRowId: number;
|
|
144
|
+
}
|
|
145
|
+
export interface NgisBatchInit {
|
|
146
|
+
/** How many empty rows to open with. Clamped to at least one. */
|
|
147
|
+
readonly rows?: number;
|
|
148
|
+
/**
|
|
149
|
+
* The column order to prefer over the schema's own — a published recipe's
|
|
150
|
+
* promoted inputs (F14.21, via {@link recipeColumns}), or a saved config's
|
|
151
|
+
* columns. Names the schema does not know become `unknown-column` defects.
|
|
152
|
+
*/
|
|
153
|
+
readonly columns?: readonly string[];
|
|
154
|
+
readonly outputMode?: "ADD_LAYER" | "UPDATE_RESOURCE";
|
|
155
|
+
readonly sceneId?: string | null;
|
|
156
|
+
/** Wire-shaped seed applied to every opening row. */
|
|
157
|
+
readonly seed?: Readonly<Record<string, string>>;
|
|
158
|
+
}
|
|
159
|
+
export interface NgisBatchColumns {
|
|
160
|
+
readonly columns: readonly string[];
|
|
161
|
+
/** Preferred names the schema does not declare. Reported, never dropped. */
|
|
162
|
+
readonly unknown: readonly string[];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The columns, and which requested names the tool does not have.
|
|
166
|
+
*
|
|
167
|
+
* With no `preferred`, the order is the schema's own — which is F14.21's
|
|
168
|
+
* "display order" and is the order the server served. With a `preferred` list,
|
|
169
|
+
* the known names lead in *that* order and the remaining parameters follow, so a
|
|
170
|
+
* recipe's or a config's ordering is honoured without ever hiding a parameter
|
|
171
|
+
* the tool actually takes. A parameter absent from the table is a parameter that
|
|
172
|
+
* silently submits its `default_value` on every row, which is the batch version
|
|
173
|
+
* of the `V-224` failure.
|
|
174
|
+
*/
|
|
175
|
+
export declare function batchColumns(schema: NgisToolUiSchema, preferred?: readonly string[]): NgisBatchColumns;
|
|
176
|
+
/**
|
|
177
|
+
* A published recipe's batch columns (F14.21), through the seam's own function.
|
|
178
|
+
*
|
|
179
|
+
* Thin on purpose: {@link recipeColumns} is the one function both W4 sessions
|
|
180
|
+
* read, so the recipe → column mapping exists once. What this adds is the
|
|
181
|
+
* *reconciliation* — a recipe input id that is not a parameter of the published
|
|
182
|
+
* tool's UI schema becomes a defect here rather than a missing column nobody
|
|
183
|
+
* mentions.
|
|
184
|
+
*/
|
|
185
|
+
export declare function recipeBatchColumns(schema: NgisToolUiSchema, recipe: NgisRecipe): NgisBatchColumns;
|
|
186
|
+
export declare function initializeBatchTable(schema: NgisToolUiSchema, init?: NgisBatchInit): NgisBatchTableState;
|
|
187
|
+
export declare function addBatchRow(schema: NgisToolUiSchema, state: NgisBatchTableState, seed?: Readonly<Record<string, string>>): NgisBatchTableState;
|
|
188
|
+
/**
|
|
189
|
+
* Copy a row, values and all.
|
|
190
|
+
*
|
|
191
|
+
* The copy's fields keep the source's `altered` flags, because the values really
|
|
192
|
+
* were chosen by a user and F14.9's repopulation rule protects exactly that. A
|
|
193
|
+
* duplicate whose fields claimed `altered: false` would have its values dropped
|
|
194
|
+
* by the next `mutate` that repopulated a list.
|
|
195
|
+
*/
|
|
196
|
+
export declare function duplicateBatchRow(state: NgisBatchTableState, rowId: string): NgisBatchTableState;
|
|
197
|
+
/** Removing the last row leaves the table empty; it does not re-seed one. A
|
|
198
|
+
* batch with no rows is a real state and the caller says so. */
|
|
199
|
+
export declare function removeBatchRow(state: NgisBatchTableState, rowId: string): NgisBatchTableState;
|
|
200
|
+
/**
|
|
201
|
+
* One cell edit, through F14.9's `setParamValue` — which sets `altered` and
|
|
202
|
+
* re-runs *mutate* for that row only.
|
|
203
|
+
*
|
|
204
|
+
* `optionLists` is per row for the same reason visibility is: `field-select`
|
|
205
|
+
* follows a sibling resource cell, and two rows pointing at different datasets
|
|
206
|
+
* have different field lists.
|
|
207
|
+
*/
|
|
208
|
+
export declare function setBatchCell(schema: NgisToolUiSchema, state: NgisBatchTableState, rowId: string, name: string, value: NgisParamValue, optionLists?: Readonly<Record<string, readonly string[]>>): NgisBatchTableState;
|
|
209
|
+
/**
|
|
210
|
+
* QGIS's fill-down: the first row's value for one column, copied into every
|
|
211
|
+
* other row.
|
|
212
|
+
*
|
|
213
|
+
* **Not expression-driven row generation** (F14.21 puts that out of v1) — no
|
|
214
|
+
* value is computed, and the source is a value a user already typed. It goes
|
|
215
|
+
* through {@link setBatchCell}, so each target row runs its own *mutate* and a
|
|
216
|
+
* column whose value the target row's option list does not offer is handled by
|
|
217
|
+
* F14.9's rule rather than by a second one written here.
|
|
218
|
+
*/
|
|
219
|
+
export declare function fillBatchColumnDown(schema: NgisToolUiSchema, state: NgisBatchTableState, name: string): NgisBatchTableState;
|
|
220
|
+
export declare function setBatchOutput(state: NgisBatchTableState, output: {
|
|
221
|
+
readonly outputMode?: "ADD_LAYER" | "UPDATE_RESOURCE";
|
|
222
|
+
readonly sceneId?: string | null;
|
|
223
|
+
}): NgisBatchTableState;
|
|
224
|
+
/**
|
|
225
|
+
* A cell's node/DOM id — **the seam's spelling, never a local one**
|
|
226
|
+
* (`ngisBatchCellId`, CORRECTION 10).
|
|
227
|
+
*
|
|
228
|
+
* Four of the twelve widgets delegate to components that are themselves flow
|
|
229
|
+
* nodes keyed by their `id` prop, and the flow registry is last-wins on node id,
|
|
230
|
+
* so N rows rendering one parameter under one id collapse to a single node and
|
|
231
|
+
* N−1 cells bind to nothing.
|
|
232
|
+
*
|
|
233
|
+
* **It takes a row *index*, not a row id, and that is worth stating.** Removing a
|
|
234
|
+
* row therefore renumbers every cell below it, and the surviving rows'
|
|
235
|
+
* widget-level nodes re-register under their new ids. That is correct — the
|
|
236
|
+
* registry keys on the id it is given and a vanished id unregisters — but it also
|
|
237
|
+
* means a cell id is not a durable handle for anything outside one render. Use
|
|
238
|
+
* {@link NgisBatchRow.id} for identity and this for the DOM.
|
|
239
|
+
*/
|
|
240
|
+
export declare function batchCellId(scopeId: string, rowIndex: number, name: string): string;
|
|
241
|
+
export interface NgisBatchGate {
|
|
242
|
+
/** Row ids whose client validation passed. Submitted, in this order. */
|
|
243
|
+
readonly ready: readonly string[];
|
|
244
|
+
/** Row id → its client errors. Never submitted; a reason is rendered instead. */
|
|
245
|
+
readonly blocked: Readonly<Record<string, readonly NgisParamFormError[]>>;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* F14.9's *validate (client)*, per row.
|
|
249
|
+
*
|
|
250
|
+
* Blocked rows are **partitioned out before anything is submitted**, rather than
|
|
251
|
+
* being enqueued and refused later. Both would honour F14.9, but a fifty-row
|
|
252
|
+
* batch where six rows are incomplete should say "six rows can't run yet" before
|
|
253
|
+
* it spends the other forty-four's worth of task-fabric budget — and a blocked
|
|
254
|
+
* row that occupied a concurrency slot for the duration of a refusal would make
|
|
255
|
+
* the cap of 3 mean something slightly different from what F14.21 says.
|
|
256
|
+
*/
|
|
257
|
+
export declare function gateBatchRows(schema: NgisToolUiSchema, state: NgisBatchTableState): NgisBatchGate;
|
|
258
|
+
/**
|
|
259
|
+
* Fold the client errors back onto every row's fields, marking them
|
|
260
|
+
* `hasBeenValidated` — F14.9's `applyClientErrors`, applied row-wise so each
|
|
261
|
+
* cell can render its own message.
|
|
262
|
+
*/
|
|
263
|
+
export declare function applyBatchClientErrors(schema: NgisToolUiSchema, state: NgisBatchTableState, render: (error: NgisParamFormError) => string): NgisBatchTableState;
|
|
264
|
+
/** The `NgisRunSubmission` for one row — `toSubmission`, unchanged. */
|
|
265
|
+
export declare function batchRowSubmission(schema: NgisToolUiSchema, row: NgisBatchRow): NgisRunSubmission;
|
|
266
|
+
/** Whether a cell applies to its row at all (`depends_on`, F14.9). Per row. */
|
|
267
|
+
export declare function batchCellVisible(row: NgisBatchRow, name: string): boolean;
|
|
268
|
+
export type NgisBatchRowPhase =
|
|
269
|
+
/** Never submitted. */
|
|
270
|
+
"idle"
|
|
271
|
+
/** Waiting for a concurrency slot. */
|
|
272
|
+
| "queued"
|
|
273
|
+
/** Submitted; the task is in flight. */
|
|
274
|
+
| "running"
|
|
275
|
+
/** Client validation, or the server's pre-flight verdict, refused it. */
|
|
276
|
+
| "blocked"
|
|
277
|
+
/** Submitted successfully — there is a task id. */
|
|
278
|
+
| "submitted"
|
|
279
|
+
/** The validate or the run call itself rejected. */
|
|
280
|
+
| "failed";
|
|
281
|
+
export interface NgisBatchRowResult {
|
|
282
|
+
readonly phase: "blocked" | "submitted" | "failed";
|
|
283
|
+
readonly taskId: string | null;
|
|
284
|
+
/**
|
|
285
|
+
* Why, on this row. F14.21 says a failed row does not cancel the rest, so this
|
|
286
|
+
* is the only per-row signal there is — which is why the caller resolves it
|
|
287
|
+
* through `readApiErrorMessage` (F14.15) rather than off `Error.message`.
|
|
288
|
+
*/
|
|
289
|
+
readonly messages: readonly string[];
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* One row's `NgisRunOutcome`, projected.
|
|
293
|
+
*
|
|
294
|
+
* The three arms map one-for-one and deliberately do not collapse: `blocked` is
|
|
295
|
+
* *the server answered and said no*, `failed` is *we could not ask* (a scope
|
|
296
|
+
* refusal, a transport failure, a facet stub). Those are different things to tell
|
|
297
|
+
* an author, and `run-data.ts:121-124` keeps them apart for the same reason.
|
|
298
|
+
*
|
|
299
|
+
* `message` is the caller's already-extracted server message — `null` when the
|
|
300
|
+
* error carried none, in which case the caller renders its own generic string
|
|
301
|
+
* (F14.15). This module never touches `ApiError`, which is what keeps it pure.
|
|
302
|
+
*/
|
|
303
|
+
export declare function batchRowResultOf(outcome: NgisRunOutcome, message: string | null): NgisBatchRowResult;
|
|
304
|
+
/** A row refused before any host call, from its client errors. */
|
|
305
|
+
export declare function blockedBatchRowResult(messages: readonly string[]): NgisBatchRowResult;
|
|
306
|
+
export interface NgisBatchQueueState {
|
|
307
|
+
readonly pending: readonly string[];
|
|
308
|
+
readonly running: readonly string[];
|
|
309
|
+
readonly settled: readonly string[];
|
|
310
|
+
}
|
|
311
|
+
export declare function startBatchQueue(rowIds: readonly string[]): NgisBatchQueueState;
|
|
312
|
+
/**
|
|
313
|
+
* The whole of F14.21's concurrency rule: which rows may start **now**.
|
|
314
|
+
*
|
|
315
|
+
* `concurrency` is a parameter only so the property can be tested at other
|
|
316
|
+
* values; every call site passes {@link NGIS_BATCH_CONCURRENCY} and no prop
|
|
317
|
+
* exposes it. A value below 1 is clamped to 1 rather than deadlocking the queue.
|
|
318
|
+
*/
|
|
319
|
+
export declare function batchQueueDispatch(queue: NgisBatchQueueState, concurrency?: number): {
|
|
320
|
+
readonly queue: NgisBatchQueueState;
|
|
321
|
+
readonly start: readonly string[];
|
|
322
|
+
};
|
|
323
|
+
/**
|
|
324
|
+
* A row left `running`. **Takes no outcome, on purpose.**
|
|
325
|
+
*
|
|
326
|
+
* F14.21's *"a failed row does not cancel the rest"* is implemented as an
|
|
327
|
+
* absence: this function cannot see whether the row succeeded, so there is no
|
|
328
|
+
* arm in which it could drain `pending`. A queue that inspected the outcome and
|
|
329
|
+
* chose to continue would be one edit away from choosing not to.
|
|
330
|
+
*/
|
|
331
|
+
export declare function settleBatchQueueRow(queue: NgisBatchQueueState, rowId: string): NgisBatchQueueState;
|
|
332
|
+
export declare function batchQueueDone(queue: NgisBatchQueueState): boolean;
|
|
333
|
+
export interface NgisBatchRunReport {
|
|
334
|
+
readonly results: Readonly<Record<string, NgisBatchRowResult>>;
|
|
335
|
+
/**
|
|
336
|
+
* The most submissions the runner ever had in flight at once. Reported by the
|
|
337
|
+
* runner rather than measured by the caller, so *"the cap of 3 is respected"*
|
|
338
|
+
* is a property of the code under test and not of the test's own bookkeeping.
|
|
339
|
+
*/
|
|
340
|
+
readonly peakInFlight: number;
|
|
341
|
+
readonly submitted: readonly string[];
|
|
342
|
+
readonly blocked: readonly string[];
|
|
343
|
+
readonly failed: readonly string[];
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Rows whose last submission failed before a task existed, or whose submitted
|
|
347
|
+
* task later reached a failed/cancelled lifecycle. Successful and still-active
|
|
348
|
+
* rows are deliberately excluded so a retry cannot duplicate healthy work.
|
|
349
|
+
*/
|
|
350
|
+
export declare function retryableBatchRowIds(rowIds: readonly string[], results: Readonly<Record<string, NgisBatchRowResult>>, taskStages: Readonly<Record<string, string | undefined>>): readonly string[];
|
|
351
|
+
export declare const NGIS_BATCH_COLUMN_DEFAULT_WIDTH = 192;
|
|
352
|
+
export declare const NGIS_BATCH_COLUMN_MIN_WIDTH = 160;
|
|
353
|
+
export declare const NGIS_BATCH_COLUMN_MAX_WIDTH = 480;
|
|
354
|
+
export declare const NGIS_BATCH_COLUMN_KEYBOARD_STEP = 16;
|
|
355
|
+
/** Keep pointer and keyboard resizing inside the table's readable range. */
|
|
356
|
+
export declare function clampBatchColumnWidth(width: number): number;
|
|
357
|
+
export interface NgisBatchRunOptions {
|
|
358
|
+
readonly concurrency?: number;
|
|
359
|
+
readonly onStart?: (rowId: string) => void;
|
|
360
|
+
readonly onSettle?: (rowId: string, result: NgisBatchRowResult) => void;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Drive N rows through `submit` at most {@link NGIS_BATCH_CONCURRENCY} at a time,
|
|
364
|
+
* and report every row.
|
|
365
|
+
*
|
|
366
|
+
* `submit` is injected rather than called through a host, which is what keeps
|
|
367
|
+
* this module React- and host-free while still being *the* implementation the
|
|
368
|
+
* component runs: `BatchTable` passes a closure over
|
|
369
|
+
* `runSubmission(host, submission, options)` and the offline proof passes a
|
|
370
|
+
* deferred stub. One scheduler, two callers — the alternative is a scheduler in a
|
|
371
|
+
* `useEffect` and a second one in a test, which is the shape that let `V-224`
|
|
372
|
+
* ship.
|
|
373
|
+
*
|
|
374
|
+
* **Every way `submit` can fail is a per-row `failed`, never a rejected batch:**
|
|
375
|
+
* a rejected promise, a synchronous throw, and a resolved `failed` result all
|
|
376
|
+
* land in `results`. The returned promise resolves once every row has settled and
|
|
377
|
+
* does not reject.
|
|
378
|
+
*/
|
|
379
|
+
export declare function runBatchQueue(rowIds: readonly string[], submit: (rowId: string) => Promise<NgisBatchRowResult>, options?: NgisBatchRunOptions): Promise<NgisBatchRunReport>;
|
|
380
|
+
/**
|
|
381
|
+
* F14.21's JSON, from the current table.
|
|
382
|
+
*
|
|
383
|
+
* Two decisions worth naming:
|
|
384
|
+
*
|
|
385
|
+
* 1. **A cell that is currently hidden still saves.** `toSubmission` drops a
|
|
386
|
+
* hidden field, because F14.9 says a parameter the schema declares
|
|
387
|
+
* inapplicable must not be submitted — but a *config* is the author's
|
|
388
|
+
* document, and a value that vanished because a sibling cell was toggled and
|
|
389
|
+
* did not come back when it was toggled again would be data loss with a very
|
|
390
|
+
* confusing cause.
|
|
391
|
+
* 2. **`extras` are re-emitted.** Keys a load could not place are written back
|
|
392
|
+
* exactly as they arrived, so round-tripping a config authored against a newer
|
|
393
|
+
* tool version is lossless.
|
|
394
|
+
*/
|
|
395
|
+
export declare function toBatchConfig(state: NgisBatchTableState): NgisBatchConfig;
|
|
396
|
+
export type NgisBatchConfigParse = {
|
|
397
|
+
readonly kind: "ok";
|
|
398
|
+
readonly config: NgisBatchConfig;
|
|
399
|
+
}
|
|
400
|
+
/** F14.21 carries F14.2's rule: an unknown version **refuses**. */
|
|
401
|
+
| {
|
|
402
|
+
readonly kind: "unsupported-version";
|
|
403
|
+
readonly version: number;
|
|
404
|
+
} | {
|
|
405
|
+
readonly kind: "malformed";
|
|
406
|
+
readonly field: string;
|
|
407
|
+
};
|
|
408
|
+
/**
|
|
409
|
+
* Parse a saved config out of `unknown`.
|
|
410
|
+
*
|
|
411
|
+
* Separate from {@link fromBatchConfig} because the two failures are different
|
|
412
|
+
* kinds: this one is *the document is not a batch config we understand*, which is
|
|
413
|
+
* a refusal; the other is *this config was written for a different tool*, which is
|
|
414
|
+
* a defect the author can look at and act on. Collapsing them would make a
|
|
415
|
+
* version bump and a typo'd tool id read the same on screen.
|
|
416
|
+
*
|
|
417
|
+
* The version check comes **first**, before any field is inspected. A v2 config
|
|
418
|
+
* whose `columns` moved would otherwise be reported as malformed, which names the
|
|
419
|
+
* wrong problem.
|
|
420
|
+
*/
|
|
421
|
+
export declare function parseBatchConfig(raw: unknown): NgisBatchConfigParse;
|
|
422
|
+
/**
|
|
423
|
+
* A parsed config, against the schema actually loaded.
|
|
424
|
+
*
|
|
425
|
+
* A mismatched `toolId` or `toolVersion` is a **defect, not a refusal**: the
|
|
426
|
+
* server re-resolves and overwrites a pinned tool version at publish
|
|
427
|
+
* (`w4-contracts.ts:166-173`), so a config authored a version ago is the normal
|
|
428
|
+
* case rather than an error, and refusing it would make every republished tool
|
|
429
|
+
* orphan its saved batches. The values load, the mismatch is on screen, and the
|
|
430
|
+
* author decides.
|
|
431
|
+
*
|
|
432
|
+
* Every row's cells are seeded through F14.9's *initialize*, so `default_value`
|
|
433
|
+
* fills any column the config omitted and `fromWireValue` coerces the strings —
|
|
434
|
+
* which is what keeps a saved config and a form value from disagreeing about how
|
|
435
|
+
* `false` is spelled.
|
|
436
|
+
*/
|
|
437
|
+
export declare function fromBatchConfig(schema: NgisToolUiSchema, config: NgisBatchConfig): NgisBatchTableState;
|
|
438
|
+
/** A column's header text — the parameter's `label`, F14.10's provenance chain
|
|
439
|
+
* (`x-display-name` → `title` → `name`). A plugin string, rendered literally. */
|
|
440
|
+
export declare function batchColumnParams(schema: NgisToolUiSchema, state: NgisBatchTableState): readonly NgisToolUiParam[];
|
|
441
|
+
/** The values of one row, for a caller that wants them flat. */
|
|
442
|
+
export declare function batchRowValues(row: NgisBatchRow): Readonly<Record<string, NgisParamValue>>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `RunButton`'s `toolId` + `inputs` → the one {@link NgisRunSubmission}
|
|
3
|
+
* (Stage 14 Y5b, **F14.4 / F14.5**).
|
|
4
|
+
*
|
|
5
|
+
* ## Additive over the same submit path, not a second one
|
|
6
|
+
*
|
|
7
|
+
* W2 shipped `RunButton` taking an **already-resolved** `submission`, deliberately:
|
|
8
|
+
* `"@dem"` is a reference form only a `<Flow>` scope can resolve, and taking
|
|
9
|
+
* `inputs` before `<Flow>` existed would have shipped a prop that silently did
|
|
10
|
+
* nothing. W3 adds the pair, and it lands *here* rather than in `run-data.ts`
|
|
11
|
+
* because everything downstream is unchanged: `runSubmission` still validates then
|
|
12
|
+
* submits, and `toWireParams` is still the single coercion. **A differing coercion
|
|
13
|
+
* is exactly what makes a validate pass and the run fail**, so there is not a
|
|
14
|
+
* second one.
|
|
15
|
+
*
|
|
16
|
+
* ## The role split is Y3's, reused rather than copied
|
|
17
|
+
*
|
|
18
|
+
* A tool's params are `input` (→ `bindings`), `output` (→ `outputNames`) or
|
|
19
|
+
* `option` (→ `params`), and `toSubmission` already owns those rules. So resolved
|
|
20
|
+
* port values are turned into **wire-shaped seed values** and handed to
|
|
21
|
+
* `initializeParamForm` → `toSubmission`: the same two functions a rendered
|
|
22
|
+
* `<ParamForm>` goes through, which is why a flow-bound run and a form-driven run
|
|
23
|
+
* cannot disagree about how a boolean or a multi-valued input is spelled. A second
|
|
24
|
+
* role-splitter here would be the `toWireParams` lesson in a new place.
|
|
25
|
+
*
|
|
26
|
+
* A consequence worth stating: seeding through `initializeParamForm` also applies
|
|
27
|
+
* each param's `default_value`, so a tool option the author did not bind is
|
|
28
|
+
* submitted with its declared default rather than omitted. That is what a
|
|
29
|
+
* generated dialog does, and a flow that behaved differently would run a different
|
|
30
|
+
* tool invocation than the dialog for the same graph.
|
|
31
|
+
*/
|
|
32
|
+
import type { NgisToolUiSchema } from "../../types/analysis";
|
|
33
|
+
import type { NgisRunSubmission } from "./w2-contracts";
|
|
34
|
+
import { type NgisResolvedValue } from "./w3-contracts";
|
|
35
|
+
/** Resolved in-port values, by member name. */
|
|
36
|
+
export type NgisFlowInputValues = Readonly<Record<string, NgisResolvedValue>>;
|
|
37
|
+
/**
|
|
38
|
+
* One resolved port value in the wire spelling the seed takes.
|
|
39
|
+
*
|
|
40
|
+
* `null` means "not a scalar a param can carry" — a `record`, which is a spread
|
|
41
|
+
* source rather than a value, and is flattened by the caller before it gets here.
|
|
42
|
+
* A `resources` list and an `extent` both comma-join, because that is what
|
|
43
|
+
* `toSubmission` splits an `input` param on and what F14.2's `extent` widget
|
|
44
|
+
* produces.
|
|
45
|
+
*/
|
|
46
|
+
export declare function flowValueToWire(value: NgisResolvedValue): string | null;
|
|
47
|
+
/**
|
|
48
|
+
* Flattens one node's satisfied in-port values: every spread's record contents,
|
|
49
|
+
* then the explicitly-bound ports written over them.
|
|
50
|
+
*
|
|
51
|
+
* F14.4: **later explicit keys win over spread keys**, which is why the spreads
|
|
52
|
+
* are laid down first. Both kinds of key live in the same resolution map, because
|
|
53
|
+
* `NgisFlowNode.inputs` holds both.
|
|
54
|
+
*/
|
|
55
|
+
export declare function flattenFlowInputs(values: NgisFlowInputValues): NgisFlowInputValues;
|
|
56
|
+
/** The submission a flow-bound `RunButton` submits. */
|
|
57
|
+
export declare function submissionFromFlowInputs(schema: NgisToolUiSchema, values: NgisFlowInputValues): NgisRunSubmission;
|
|
58
|
+
/** `inputs` keys that name an in port, i.e. everything but a spread directive. */
|
|
59
|
+
export declare function flowInputNames(inputs: Readonly<Record<string, unknown>> | undefined): readonly string[];
|
|
60
|
+
/** `inputs` keys the tool's schema does not know — surfaced, never dropped. */
|
|
61
|
+
export declare function unknownFlowInputNames(schema: NgisToolUiSchema | null, names: readonly string[]): readonly string[];
|