@ngis/plugin-sdk 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 +31 -0
- package/dist/index.cjs +76 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.mjs +102 -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/domain/algorithms/deck-layer-style.d.ts +34 -0
- package/dist/src/domain/algorithms/maplibre-style.d.ts +63 -0
- package/dist/src/domain/algorithms/raster-color-ramps.d.ts +37 -0
- package/dist/src/domain/algorithms/scene-layer-type.d.ts +25 -0
- package/dist/src/domain/algorithms/symbol-compile.d.ts +100 -0
- package/dist/src/domain/algorithms/symbol-params.d.ts +90 -0
- package/dist/src/domain/map/bounds.d.ts +8 -0
- package/dist/src/domain/map/constants.d.ts +40 -0
- package/dist/src/domain/map/layer-builders.d.ts +32 -0
- package/dist/src/domain/map/rendered-layers.d.ts +30 -0
- package/dist/src/domain/map/style-ready.d.ts +24 -0
- package/dist/src/domain/map/tile-url.d.ts +20 -0
- package/dist/src/domain/map/types.d.ts +128 -0
- package/dist/src/domain/models/deck-layer-style.d.ts +211 -0
- package/dist/src/domain/models/scene-layer-type.d.ts +23 -0
- package/dist/src/domain/models/symbol.d.ts +424 -0
- package/dist/src/lib/api.d.ts +82 -0
- package/dist/src/lib/auth-session.d.ts +22 -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/sdk/commands.d.ts +113 -0
- package/dist/src/sdk/context/keys.d.ts +148 -0
- package/dist/src/sdk/context/publishers.d.ts +198 -0
- package/dist/src/sdk/context/store.d.ts +78 -0
- package/dist/src/sdk/context/when.d.ts +69 -0
- package/dist/src/sdk/contributions/dispatch.d.ts +78 -0
- package/dist/src/sdk/contributions/panel-id.d.ts +25 -0
- package/dist/src/sdk/contributions/registry.d.ts +199 -0
- package/dist/src/sdk/contributions/symbol-renderers.d.ts +107 -0
- package/dist/src/sdk/contributions/types.d.ts +288 -0
- package/dist/src/sdk/contributions/views-bridge.d.ts +92 -0
- package/dist/src/sdk/define-plugin.d.ts +17 -0
- package/dist/src/sdk/facets/storage.d.ts +152 -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/sdk/plugin.d.ts +145 -0
- package/dist/src/sdk/rail-tools.d.ts +58 -0
- package/dist/src/sdk/scopes.d.ts +158 -0
- package/dist/src/systems/renderer/DeckSceneRenderer.d.ts +26 -0
- package/dist/src/systems/renderer/FlowFieldLayer.d.ts +68 -0
- package/dist/src/systems/renderer/LayerRendererRegistry.d.ts +132 -0
- package/dist/src/systems/renderer/authenticated-deck-load.d.ts +4 -0
- package/dist/src/systems/renderer/deck/deck-layer-builders.d.ts +29 -0
- package/dist/src/systems/renderer/deck/deck-layer-helpers.d.ts +21 -0
- package/dist/src/systems/renderer/deck/mvt-point-aggregation-layer.d.ts +107 -0
- package/dist/src/systems/renderer/flow-field/flow-field-resources.d.ts +84 -0
- package/dist/src/systems/renderer/flow-field/flow-field-shaders.d.ts +4 -0
- package/dist/src/systems/renderer/symbol/SpriteRegistry.d.ts +34 -0
- package/dist/src/systems/renderer/symbol/entries.d.ts +67 -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/package.json +47 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 13 (capability contract) — the frozen type text for the four **core**
|
|
3
|
+
* 0.4 facets: `scene`, `resources`, `models`, `tasks`.
|
|
4
|
+
*
|
|
5
|
+
* Every interface below is **F13.2 verbatim**
|
|
6
|
+
* (`docs/capability_contract_stage/README.md` → "Frozen contracts (X0)").
|
|
7
|
+
* Signature text is the contract; the JSDoc here is richer than the frozen
|
|
8
|
+
* text, never narrower. A session that needs a change here stops and raises
|
|
9
|
+
* it — it does not diverge locally, because XB1's validator tests and X4's
|
|
10
|
+
* parser tests must round-trip the *same* fixtures.
|
|
11
|
+
*
|
|
12
|
+
* **Worker-readiness (L6, binding on every signature).** Every method is
|
|
13
|
+
* `async` and takes/returns JSON-serializable values; every observation is a
|
|
14
|
+
* subscription returning the existing synchronous `NgisUnsubscribe`. The one
|
|
15
|
+
* handle-returning method here (`tasks.watch`) returns an object whose members
|
|
16
|
+
* are themselves async — proxyable as an RPC handle. No facet ever returns a
|
|
17
|
+
* DOM node, a React element, a class instance, or a function other than
|
|
18
|
+
* `NgisUnsubscribe`.
|
|
19
|
+
*
|
|
20
|
+
* No runtime *imports*, so a worker/RPC tier can consume the contract without
|
|
21
|
+
* pulling the host's implementation in with it. Stage 14's W1 kickoff adds two
|
|
22
|
+
* runtime *exports* — `NGIS_DATA_TYPES` and `NGIS_DATA_TYPE_TO_RESOURCE_TYPES`
|
|
23
|
+
* (F14.1 puts them in this file by name) — which are self-contained frozen data
|
|
24
|
+
* and preserve that property.
|
|
25
|
+
*
|
|
26
|
+
* ## Stage 14 (F14.1, F14.3) — kickoff-authored, read-only to W1 sessions
|
|
27
|
+
*
|
|
28
|
+
* The canonical `NgisDataType` vocabulary and the three additive `models` legs
|
|
29
|
+
* plus `viz.chart` were authored at the **W1 kickoff**
|
|
30
|
+
* (`docs/components_flow_stage/README.md` → F14.24). **No F13.2 member
|
|
31
|
+
* changes.** A session that needs a change here stops and raises it.
|
|
32
|
+
*/
|
|
33
|
+
import type { AnalysisToolSchema } from "../../api/analysis";
|
|
34
|
+
import type { SceneType } from "../../api/scenes";
|
|
35
|
+
import type { NgisExecutionValidation, NgisToolUiSchema } from "../../types/analysis";
|
|
36
|
+
import type { NgisBounds, NgisUnsubscribe } from "../map-api";
|
|
37
|
+
export interface NgisSceneInfo {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
/** `"MAP" | "ANALYSIS" | "GIS"` — `SceneType` from `src/api/scenes.ts`. */
|
|
41
|
+
type: SceneType;
|
|
42
|
+
ownerId: string | null;
|
|
43
|
+
/** Drives `storage.scene` writability and the `scene.isOwner` context key. */
|
|
44
|
+
isOwner: boolean;
|
|
45
|
+
resourceCount: number;
|
|
46
|
+
layerCount: number;
|
|
47
|
+
}
|
|
48
|
+
export interface NgisSceneFacet {
|
|
49
|
+
/** `null` on an unsaved scratch workspace — boot-payload plugins still run there. */
|
|
50
|
+
get(): Promise<NgisSceneInfo | null>;
|
|
51
|
+
onChange(listener: (scene: NgisSceneInfo | null) => void): NgisUnsubscribe;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* XD7. `"table"` is in the union for forward compatibility and is **never
|
|
55
|
+
* emitted in v1** — see F13.6.
|
|
56
|
+
*
|
|
57
|
+
* Classification is `DatasetInfo.datasetType`: `VECTOR`→`vector`,
|
|
58
|
+
* `RASTER`→`raster`, everything else **including `GENERIC`**→`file`. Producing
|
|
59
|
+
* `"table"` would need `NgisFile.fileType`, i.e. a second
|
|
60
|
+
* `GET /api/files/{fileId}` per resource — an N+1 fan-out for a distinction no
|
|
61
|
+
* v1 consumer needs.
|
|
62
|
+
*/
|
|
63
|
+
export type NgisResourceType = "vector" | "raster" | "table" | "file";
|
|
64
|
+
/**
|
|
65
|
+
* **The one wire vocabulary for port and parameter data types (F14.1).**
|
|
66
|
+
*
|
|
67
|
+
* Six vocabularies existed; this one is canonical from here on, and it is
|
|
68
|
+
* **lowercase** — which makes {@link NgisResourceType} a strict subset, so no
|
|
69
|
+
* shipped plugin, no shipped `when` expression and no shipped fixture changes.
|
|
70
|
+
* {@link NgisResourceType} is **not** widened: it classifies *scene resources*,
|
|
71
|
+
* and `DatasetInfo.datasetType` produces only `VECTOR`/`RASTER`/everything-else.
|
|
72
|
+
*
|
|
73
|
+
* Canonicalization is **case- and separator-insensitive**: lowercase, strip
|
|
74
|
+
* `_`, `-` and spaces, then match. `"Point Cloud"`, `"point_cloud"` and
|
|
75
|
+
* `"POINTCLOUD"` all canonicalize to `pointcloud`; `null`/absent → `file`.
|
|
76
|
+
*
|
|
77
|
+
* | canonical | BE `x-data-type` | binding-validation | classified as | workflow slot `dataType` |
|
|
78
|
+
* |---|---|---|---|---|
|
|
79
|
+
* | `raster` | `Raster` | `RASTER` | `raster` | `Raster` |
|
|
80
|
+
* | `vector` | `Vector` | `VECTOR` | `vector` | `Vector` |
|
|
81
|
+
* | `table` | `Table` | `TABLE` | `file` | `Table` |
|
|
82
|
+
* | `pointcloud` | `PointCloud` | `POINTCLOUD` | `file` | `PointCloud` |
|
|
83
|
+
* | `raster3d` | `Raster3D` | `RASTER` | `raster` \| `file` | `Raster3D` |
|
|
84
|
+
* | `file` | `File` (or absent) | `FILE` | any | `File` |
|
|
85
|
+
*
|
|
86
|
+
* **The last column is Pascal and that is not cosmetic.**
|
|
87
|
+
* `WorkflowTypeCheckService.compatible` is case-sensitive `String.equals`, so
|
|
88
|
+
* writing `"raster"` into a `ToolInputSlot.dataType` silently fails type-check
|
|
89
|
+
* against a builtin node's `"Raster"` and `400`s at workflow save. Y6 applies
|
|
90
|
+
* that column at, and **only** at, the `ngis-workflow` boundary. Nowhere else
|
|
91
|
+
* in either repo is Pascal correct.
|
|
92
|
+
*/
|
|
93
|
+
export type NgisDataType = "raster" | "vector" | "table" | "pointcloud" | "raster3d" | "file";
|
|
94
|
+
export declare const NGIS_DATA_TYPES: readonly ["raster", "vector", "table", "pointcloud", "raster3d", "file"];
|
|
95
|
+
/**
|
|
96
|
+
* **Frozen (F14.1).** How a requested data type resolves to the resource types
|
|
97
|
+
* v1 can actually classify.
|
|
98
|
+
*
|
|
99
|
+
* `table` stays reserved and **unemitted** in `resources.types` and in
|
|
100
|
+
* `NgisResourceSummary.type` through Stage 14 (XD7 unchanged) — producing it
|
|
101
|
+
* needs `NgisFile.fileType`, an N+1 `GET /api/files/{fileId}`, and the
|
|
102
|
+
* server-side alternative lives in `ngis-scene`/`ngis-file`, which no Stage 14
|
|
103
|
+
* backend session owns. So `'table' in resources.types` is permanently false
|
|
104
|
+
* and stays on the grep-proof list.
|
|
105
|
+
*
|
|
106
|
+
* **But `table` is legal in a `types={…}` prop**, because that prop speaks
|
|
107
|
+
* `NgisDataType`, not `NgisResourceType`. A widened request (`table`,
|
|
108
|
+
* `pointcloud`, `raster3d`) must be **surfaced, never silent**: `ResourceSelect`
|
|
109
|
+
* renders `GIS.pluginUi.pick.widened` naming the requested type and the types
|
|
110
|
+
* actually listed. Refusals and approximations are surfaced, not masked.
|
|
111
|
+
*/
|
|
112
|
+
export declare const NGIS_DATA_TYPE_TO_RESOURCE_TYPES: Readonly<Record<NgisDataType, readonly NgisResourceType[]>>;
|
|
113
|
+
export interface NgisResourceSummary {
|
|
114
|
+
/** Scene-resource id (`SceneResourceDto.id`), not a file id. */
|
|
115
|
+
id: string;
|
|
116
|
+
sceneId: string;
|
|
117
|
+
name: string;
|
|
118
|
+
/** `SceneResourceDto.effectiveFileId` — the id every dataset API takes. */
|
|
119
|
+
fileId: string;
|
|
120
|
+
type: NgisResourceType;
|
|
121
|
+
/** `DatasetInfo.status` verbatim (`PENDING|PROCESSING|DONE|FAILED|NOT_REGISTERED|N/A`).
|
|
122
|
+
* Passed through, never collapsed: a plugin must be able to tell "not ready"
|
|
123
|
+
* from "failed". */
|
|
124
|
+
datasetStatus: string;
|
|
125
|
+
/**
|
|
126
|
+
* Whether the scene service could resolve the cached Dataset summary. A
|
|
127
|
+
* resource whose metadata is unavailable or missing is not type-matchable.
|
|
128
|
+
*/
|
|
129
|
+
metadataState: NgisResourceMetadataState;
|
|
130
|
+
geometryType: string | null;
|
|
131
|
+
layerCount: number;
|
|
132
|
+
rendered: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Scene layers that render this resource, when the host can supply them.
|
|
135
|
+
*
|
|
136
|
+
* A resource is still the data identity and {@link fileId} is still the
|
|
137
|
+
* value tools submit. These are deliberately a display projection so a
|
|
138
|
+
* picker can let a person choose the layer they recognise without leaking a
|
|
139
|
+
* layer id into a file-typed tool parameter. `undefined` preserves the
|
|
140
|
+
* v0.4 source contract for hosts that cannot enumerate scene layers yet.
|
|
141
|
+
*/
|
|
142
|
+
layers?: readonly NgisResourceLayer[];
|
|
143
|
+
}
|
|
144
|
+
/** A data-backed scene layer, projected for resource-picking UI. */
|
|
145
|
+
export interface NgisResourceLayer {
|
|
146
|
+
/** `NgisSceneLayer.id`; unique even when several layers share one file. */
|
|
147
|
+
id: string;
|
|
148
|
+
name: string;
|
|
149
|
+
/** Scene render-layer type (for example `MAPLIBRE_FILL`), if known. */
|
|
150
|
+
layerType: string | null;
|
|
151
|
+
/** A hidden layer remains selectable, but is labelled honestly in the UI. */
|
|
152
|
+
visible: boolean;
|
|
153
|
+
/** Parent group names from root to leaf, when the host exposes groups. */
|
|
154
|
+
groupPath?: string | null;
|
|
155
|
+
}
|
|
156
|
+
/** Scene-resource summary freshness from `GET /api/scenes/{sceneId}/resources`. */
|
|
157
|
+
export type NgisResourceMetadataState = "AVAILABLE" | "MISSING" | "UNAVAILABLE" | "UNKNOWN";
|
|
158
|
+
export interface NgisResourceField {
|
|
159
|
+
name: string;
|
|
160
|
+
type: string;
|
|
161
|
+
}
|
|
162
|
+
export interface NgisResourceDetail extends NgisResourceSummary {
|
|
163
|
+
srid: number | null;
|
|
164
|
+
/** Vector only; `null` otherwise. */
|
|
165
|
+
featureCount: number | null;
|
|
166
|
+
/** Vector only; `[]` otherwise. */
|
|
167
|
+
fields: readonly NgisResourceField[];
|
|
168
|
+
/** Raster only; `null` otherwise. */
|
|
169
|
+
bandCount: number | null;
|
|
170
|
+
bbox: NgisBounds | null;
|
|
171
|
+
}
|
|
172
|
+
export interface NgisResourceValueCount {
|
|
173
|
+
value: string | number | boolean | null;
|
|
174
|
+
count: number;
|
|
175
|
+
}
|
|
176
|
+
/** A field's most frequent values, projected as plain worker-safe data. */
|
|
177
|
+
export interface NgisResourceFieldValues {
|
|
178
|
+
field: string;
|
|
179
|
+
type: string;
|
|
180
|
+
totalCount: number;
|
|
181
|
+
uniqueCount: number;
|
|
182
|
+
truncated: boolean;
|
|
183
|
+
values: readonly NgisResourceValueCount[];
|
|
184
|
+
}
|
|
185
|
+
export interface NgisResourcesFacet {
|
|
186
|
+
list(filter?: {
|
|
187
|
+
types?: readonly NgisResourceType[];
|
|
188
|
+
/** Refresh the scene service's persisted, bounded resource summaries. */
|
|
189
|
+
refresh?: boolean;
|
|
190
|
+
}): Promise<NgisResourceSummary[]>;
|
|
191
|
+
get(resourceId: string): Promise<NgisResourceDetail | null>;
|
|
192
|
+
/** Read field frequencies for a dataset file. `resources:read`. */
|
|
193
|
+
fieldValues?(fileId: string, field: string, limit?: number): Promise<NgisResourceFieldValues>;
|
|
194
|
+
onChange(listener: () => void): NgisUnsubscribe;
|
|
195
|
+
}
|
|
196
|
+
export interface NgisModelSummary {
|
|
197
|
+
id: string;
|
|
198
|
+
name: string;
|
|
199
|
+
/** `"workflow"` selects the WORKFLOW branch inside `tasks.run`; anything else
|
|
200
|
+
* (including `null`) is DIRECT. */
|
|
201
|
+
provider: string | null;
|
|
202
|
+
category: string | null;
|
|
203
|
+
description: string | null;
|
|
204
|
+
enabled: boolean;
|
|
205
|
+
modelboxId: string | null;
|
|
206
|
+
/** Stage 16. **Never** project id, revision id or any other runtime provenance —
|
|
207
|
+
* the shared-consumer detail endpoint deliberately withholds those. */
|
|
208
|
+
compatibilityStatus: string | null;
|
|
209
|
+
}
|
|
210
|
+
export interface NgisModelboxNode {
|
|
211
|
+
id: string;
|
|
212
|
+
name: string;
|
|
213
|
+
provider: string | null;
|
|
214
|
+
parentId: string | null;
|
|
215
|
+
children: readonly NgisModelboxNode[];
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* `AnalysisToolSchema` passed through unmodified — including `x-role`,
|
|
219
|
+
* `x-data-type` and every other `x-` key. v1 does **not** normalize it;
|
|
220
|
+
* one normalized UI schema is Stage 14 Y1 (design-v2 §8 item 4).
|
|
221
|
+
*
|
|
222
|
+
* XD19 makes normalizing `tool_schema` a **prohibition** for this stage, not a
|
|
223
|
+
* deferral: the object handed to a plugin is the response body itself.
|
|
224
|
+
*/
|
|
225
|
+
export type NgisModelSchema = AnalysisToolSchema;
|
|
226
|
+
/**
|
|
227
|
+
* `host.models.validate` request. Camel-cased at the facet boundary like every
|
|
228
|
+
* other F13.2 request type; the facade snake-cases it onto
|
|
229
|
+
* `POST /api/analysis/tools/{toolId}/validate-execution`.
|
|
230
|
+
*
|
|
231
|
+
* `ownerId` is deliberately absent: it comes from the authenticated caller and
|
|
232
|
+
* is **never** read from a body.
|
|
233
|
+
*/
|
|
234
|
+
export interface NgisModelValidateRequest {
|
|
235
|
+
toolId: string;
|
|
236
|
+
expectedToolVersion?: number;
|
|
237
|
+
bindings?: readonly {
|
|
238
|
+
portName: string;
|
|
239
|
+
fileIds: readonly string[];
|
|
240
|
+
}[];
|
|
241
|
+
params?: Readonly<Record<string, string>>;
|
|
242
|
+
sceneId?: string;
|
|
243
|
+
/** Lab-scene optimistic fence. Omitted for ordinary scenes. */
|
|
244
|
+
expectedSceneGeneration?: number;
|
|
245
|
+
outputMode?: "ADD_LAYER" | "UPDATE_RESOURCE";
|
|
246
|
+
targetResourceId?: string;
|
|
247
|
+
targetSrid?: number;
|
|
248
|
+
}
|
|
249
|
+
export interface NgisModelSearchRequest {
|
|
250
|
+
query?: string;
|
|
251
|
+
/** Server default 10, server maximum 50. */
|
|
252
|
+
limit?: number;
|
|
253
|
+
providers?: readonly string[];
|
|
254
|
+
kinds?: readonly string[];
|
|
255
|
+
inputTypes?: readonly NgisDataType[];
|
|
256
|
+
outputTypes?: readonly NgisDataType[];
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* One hit from `host.models.search` — the camel-cased facet projection of
|
|
260
|
+
* `ToolSearchResult`.
|
|
261
|
+
*
|
|
262
|
+
* **Note the deliberate asymmetry with `validate`,** which returns
|
|
263
|
+
* `NgisExecutionValidation` — the snake_case response DTO **verbatim**, because
|
|
264
|
+
* F14.3 says so: its field names are the client's contract with the proto and
|
|
265
|
+
* re-spelling them would be a second normalization of the very thing YB2 is
|
|
266
|
+
* projecting. `search` has no such constraint, so it follows F13.2's
|
|
267
|
+
* `NgisModelSummary` shape instead and stays a *summary*, not a wire echo.
|
|
268
|
+
*
|
|
269
|
+
* `inputTypes`/`outputTypes` are canonicalized to {@link NgisDataType} by the
|
|
270
|
+
* facade; the wire carries the search-meta strings.
|
|
271
|
+
*/
|
|
272
|
+
export interface NgisModelSearchResult {
|
|
273
|
+
toolId: string;
|
|
274
|
+
version: number;
|
|
275
|
+
kind: string;
|
|
276
|
+
name: string;
|
|
277
|
+
provider: string | null;
|
|
278
|
+
summary: string | null;
|
|
279
|
+
domains: readonly string[];
|
|
280
|
+
operationTypes: readonly string[];
|
|
281
|
+
inputTypes: readonly NgisDataType[];
|
|
282
|
+
outputTypes: readonly NgisDataType[];
|
|
283
|
+
modelboxPath: string | null;
|
|
284
|
+
score: number;
|
|
285
|
+
}
|
|
286
|
+
export interface NgisModelsFacet {
|
|
287
|
+
/** F13.2, unchanged. `query` filters the list responses client-side on
|
|
288
|
+
* name/description; the facet-level {@link NgisModelsFacet.search} leg is
|
|
289
|
+
* the server-side facet query and is what `ModelSelect` and Flow use, because
|
|
290
|
+
* client-side filtering cannot express `inputTypes`/`outputTypes`. */
|
|
291
|
+
list(filter?: {
|
|
292
|
+
provider?: string;
|
|
293
|
+
category?: string;
|
|
294
|
+
modelboxId?: string;
|
|
295
|
+
query?: string;
|
|
296
|
+
}): Promise<NgisModelSummary[]>;
|
|
297
|
+
tree(): Promise<NgisModelboxNode[]>;
|
|
298
|
+
get(toolId: string): Promise<NgisModelSummary | null>;
|
|
299
|
+
schema(toolId: string): Promise<NgisModelSchema | null>;
|
|
300
|
+
/** The one normalized UI schema (F14.2). `null` when the tool or its schema
|
|
301
|
+
* is absent. Scope `models:read`. */
|
|
302
|
+
uiSchema(toolId: string): Promise<NgisToolUiSchema | null>;
|
|
303
|
+
/** REST projection of `ValidateToolExecution`. Returns the response DTO
|
|
304
|
+
* **verbatim**. Scope `models:read`, **not** `models:run` — it runs nothing,
|
|
305
|
+
* and returns only registry facts plus dataset metadata the caller can
|
|
306
|
+
* already read through `host.resources`. */
|
|
307
|
+
validate(request: NgisModelValidateRequest): Promise<NgisExecutionValidation>;
|
|
308
|
+
/** REST projection of `SearchTools`. Scope `models:read`. */
|
|
309
|
+
search(request: NgisModelSearchRequest): Promise<NgisModelSearchResult[]>;
|
|
310
|
+
}
|
|
311
|
+
export type NgisTaskStatus = "submitting" | "QUEUED" | "RUNNING" | "SUCCESS" | "FAILED" | "CANCELLED";
|
|
312
|
+
/**
|
|
313
|
+
* Mirrors `AnalysisTaskLifecycleStage` (`src/store/analysis-scene.ts:52-61`) —
|
|
314
|
+
* the reason a plugin can tell **complete from integrated**. `status: "SUCCESS"`
|
|
315
|
+
* with `stage: "waiting_scene_integration"` is a real, common state.
|
|
316
|
+
*/
|
|
317
|
+
export type NgisTaskStage = "submitting" | "queued" | "running" | "waiting_output_datasets" | "waiting_scene_integration" | "refreshing_scene" | "success" | "failed" | "cancelled";
|
|
318
|
+
export interface NgisTaskRunRequest {
|
|
319
|
+
toolId: string;
|
|
320
|
+
/** The analysis API takes string-valued params; the facade does not coerce. */
|
|
321
|
+
params: Record<string, string>;
|
|
322
|
+
sceneId?: string;
|
|
323
|
+
/** Lab-scene optimistic fence. Omitted for ordinary scenes. */
|
|
324
|
+
expectedSceneGeneration?: number;
|
|
325
|
+
outputMode?: "ADD_LAYER" | "UPDATE_RESOURCE";
|
|
326
|
+
targetResourceId?: string;
|
|
327
|
+
}
|
|
328
|
+
export interface NgisTaskHandle {
|
|
329
|
+
/** DIRECT: the analysis task id. WORKFLOW: the workflow instance id. */
|
|
330
|
+
id: string;
|
|
331
|
+
kind: "direct" | "workflow";
|
|
332
|
+
}
|
|
333
|
+
export interface NgisTaskOutput {
|
|
334
|
+
name: string | null;
|
|
335
|
+
fileId: string | null;
|
|
336
|
+
primary: boolean;
|
|
337
|
+
}
|
|
338
|
+
export interface NgisTaskState {
|
|
339
|
+
id: string;
|
|
340
|
+
kind: "direct" | "workflow";
|
|
341
|
+
toolId: string;
|
|
342
|
+
status: NgisTaskStatus;
|
|
343
|
+
stage: NgisTaskStage;
|
|
344
|
+
/** DIRECT only. Workflow tools have no log stream, so this is always `[]`
|
|
345
|
+
* for `kind: "workflow"` — the facade does not fabricate one. */
|
|
346
|
+
logs: readonly string[];
|
|
347
|
+
error: string | null;
|
|
348
|
+
outputs: readonly NgisTaskOutput[];
|
|
349
|
+
startedAt: number;
|
|
350
|
+
updatedAt: number;
|
|
351
|
+
completedAt: number | null;
|
|
352
|
+
}
|
|
353
|
+
export interface NgisTaskWatcher {
|
|
354
|
+
close(): Promise<void>;
|
|
355
|
+
}
|
|
356
|
+
export interface NgisTasksFacet {
|
|
357
|
+
/** Branches on `NgisModelSummary.provider` inside the facade. The plugin sees
|
|
358
|
+
* one API and must not branch itself. */
|
|
359
|
+
run(request: NgisTaskRunRequest): Promise<NgisTaskHandle>;
|
|
360
|
+
get(taskId: string): Promise<NgisTaskState | null>;
|
|
361
|
+
list(filter?: {
|
|
362
|
+
active?: boolean;
|
|
363
|
+
}): Promise<NgisTaskState[]>;
|
|
364
|
+
/** DIRECT → the existing `analysisApi.streamTask` fetch-reader SSE transport,
|
|
365
|
+
* then `integration_status` polling. WORKFLOW → instance polling; **there is
|
|
366
|
+
* no workflow SSE** and the facade must not pretend otherwise. */
|
|
367
|
+
watch(taskId: string, listener: (state: NgisTaskState) => void): NgisTaskWatcher;
|
|
368
|
+
cancel(taskId: string): Promise<void>;
|
|
369
|
+
outputs(taskId: string): Promise<NgisTaskOutput[]>;
|
|
370
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `NgisHostAPI` — the 0.4 host facade (Stage 13, session X2).
|
|
3
|
+
*
|
|
4
|
+
* The 0.3 map facade **keeps its name and its position**: it stays at
|
|
5
|
+
* `host.api`, holding exactly today's `NgisMapAPI`, and is *not* re-exported
|
|
6
|
+
* facet-by-facet onto the root. `host.api.layers` remains the only spelling, so
|
|
7
|
+
* no shipped call site moves.
|
|
8
|
+
*
|
|
9
|
+
* **XD1, amendment on record.** design-v2 §4's table spells the map leg
|
|
10
|
+
* `host.map`. Renaming `api` → `map` would touch every first-party plugin, the
|
|
11
|
+
* E7 command executor and `useRemoteExtensionPlugins`, for zero capability.
|
|
12
|
+
* `host.api` is the locked spelling; design-v2 §4 is amended, not implemented
|
|
13
|
+
* as written.
|
|
14
|
+
*
|
|
15
|
+
* **Worker-readiness (L6).** Every facet method is `async` and
|
|
16
|
+
* takes/returns JSON-serializable values; every observation is a subscription
|
|
17
|
+
* returning the synchronous `NgisUnsubscribe`. The two handle-returning methods
|
|
18
|
+
* (`ui.progress`, `tasks.watch`) return objects whose members are themselves
|
|
19
|
+
* async — proxyable as RPC handles. No facet returns a DOM node, a React
|
|
20
|
+
* element, a class instance, or a function other than `NgisUnsubscribe`.
|
|
21
|
+
*
|
|
22
|
+
* ## What this file owns, and what it deliberately does not
|
|
23
|
+
*
|
|
24
|
+
* X2 (W1) implements `scene` / `resources` / `models` / `tasks`. The remaining
|
|
25
|
+
* five slots are typed here — verbatim from F13.2, so the facade is
|
|
26
|
+
* type-complete from W1 — and implemented by later sessions:
|
|
27
|
+
*
|
|
28
|
+
* | slot | implementer |
|
|
29
|
+
* |---|---|
|
|
30
|
+
* | `context` | X1 (W1), `src/sdk/context/**` |
|
|
31
|
+
* | `viz` · `storage` · `ui` | X3 (W2), `src/sdk/facets/{viz,storage,ui}.ts` |
|
|
32
|
+
* | `commands` | X4 (W2), over the E7 `gisCommandRegistry` seam |
|
|
33
|
+
*
|
|
34
|
+
* Those sessions should **import** these interfaces rather than redeclare them.
|
|
35
|
+
* Anything omitted at construction is filled with a facet whose every member
|
|
36
|
+
* rejects loudly (`pendingFacet`) — never with fake empty data, which per F13.5
|
|
37
|
+
* is indistinguishable from a real empty scene.
|
|
38
|
+
*/
|
|
39
|
+
import { type NgisMapAPI } from "./map-api";
|
|
40
|
+
import type { NgisBounds, NgisUnsubscribe } from "./map-api";
|
|
41
|
+
import type { NgisModelsFacet, NgisResourcesFacet, NgisSceneFacet, NgisTasksFacet } from "./facets/types";
|
|
42
|
+
export type { NgisModelSchema, NgisModelSummary, NgisModelboxNode, NgisModelsFacet, NgisResourceDetail, NgisResourceField, NgisResourceFieldValues, NgisResourceSummary, NgisResourceValueCount, NgisResourceType, NgisResourcesFacet, NgisSceneFacet, NgisSceneInfo, NgisTaskHandle, NgisTaskOutput, NgisTaskRunRequest, NgisTaskStage, NgisTaskState, NgisTaskStatus, NgisTaskWatcher, NgisTasksFacet, } from "./facets/types";
|
|
43
|
+
export type NgisChartKind = "bar" | "line" | "pie" | "scatter" | "histogram";
|
|
44
|
+
export interface NgisChartSeries {
|
|
45
|
+
name: string;
|
|
46
|
+
values: readonly number[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* **Declarative only (F14.3).** No DOM, no React element, no function — L6's
|
|
50
|
+
* worker-readiness rule (F13.1) binds every member added here, and the host is
|
|
51
|
+
* what renders it. A spec that carried a formatter callback or an ECharts
|
|
52
|
+
* option object would not survive Stage 15's worker tier.
|
|
53
|
+
*/
|
|
54
|
+
export interface NgisChartSpec {
|
|
55
|
+
kind: NgisChartKind;
|
|
56
|
+
title?: string;
|
|
57
|
+
categories?: readonly string[];
|
|
58
|
+
series: readonly NgisChartSeries[];
|
|
59
|
+
xLabel?: string;
|
|
60
|
+
yLabel?: string;
|
|
61
|
+
}
|
|
62
|
+
/** F13.2 verbatim, plus F14.3's additive `chart` leg. Implemented by X3 (W2) in
|
|
63
|
+
* `src/sdk/facets/viz.ts`; `chart` is Y4's (W2). */
|
|
64
|
+
export interface NgisVizFacet {
|
|
65
|
+
/** Post-hoc add: registers a scene resource for `fileId` if absent, then adds a
|
|
66
|
+
* layer. Submit-time integration is the better path and is reached by passing
|
|
67
|
+
* `sceneId`/`outputMode` to `tasks.run` — this is for outputs produced without it. */
|
|
68
|
+
addResultLayer(options: {
|
|
69
|
+
fileId: string;
|
|
70
|
+
name?: string;
|
|
71
|
+
}): Promise<{
|
|
72
|
+
resourceId: string;
|
|
73
|
+
layerId: string;
|
|
74
|
+
}>;
|
|
75
|
+
/** Opens the existing attribute panel over the resource. */
|
|
76
|
+
openTable(resourceId: string): Promise<void>;
|
|
77
|
+
fit(target: {
|
|
78
|
+
resourceId: string;
|
|
79
|
+
} | {
|
|
80
|
+
bounds: NgisBounds;
|
|
81
|
+
}): Promise<void>;
|
|
82
|
+
/** F14.3, additive. **Ungated**, for the same reason `openTable`/`fit` are —
|
|
83
|
+
* it mutates nothing. Y4 (W2) implements it over `StatChart`'s renderer. */
|
|
84
|
+
chart(spec: NgisChartSpec): Promise<void>;
|
|
85
|
+
}
|
|
86
|
+
/** F13.2 verbatim. Implemented by X3 (W2) in `src/sdk/facets/storage.ts`;
|
|
87
|
+
* `NgisStorageError` is runtime code and ships with that session. */
|
|
88
|
+
export type NgisStorageWriteFailure = "read-only" | "too-large" | "conflict";
|
|
89
|
+
export interface NgisStorageLeg {
|
|
90
|
+
get(): Promise<unknown | null>;
|
|
91
|
+
/** Rejects with `NgisStorageError` (`read-only` · `too-large` · `conflict`) or
|
|
92
|
+
* `NgisScopeError`. Never silently no-ops. */
|
|
93
|
+
set(value: unknown): Promise<void>;
|
|
94
|
+
/** Scene leg: `false` for a non-owner viewer. User leg: always `true` while
|
|
95
|
+
* installed. Surfaced, never masked — a settings form must render read-only
|
|
96
|
+
* rather than fail on submit. */
|
|
97
|
+
canWrite(): Promise<boolean>;
|
|
98
|
+
onChange(listener: (value: unknown | null) => void): NgisUnsubscribe;
|
|
99
|
+
}
|
|
100
|
+
export interface NgisStorageFacet {
|
|
101
|
+
/** Per (user, extension). XB2's install-row column. */
|
|
102
|
+
user: NgisStorageLeg;
|
|
103
|
+
/** Per (scene, extension) — `extension_config.plugins[].settings`, owner-write-only. */
|
|
104
|
+
scene: NgisStorageLeg;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* F13.2's `NgisContextFacet`, declared here under an `NgisHost`-prefixed name.
|
|
108
|
+
*
|
|
109
|
+
* X1 is building `src/sdk/context/**` **concurrently** in this same wave and
|
|
110
|
+
* owns the canonical `NgisContextFacet` / `NgisContextValue` spelling. Naming
|
|
111
|
+
* the slot type differently is what lets X1 and X2 merge without touching the
|
|
112
|
+
* same declaration; the two are structurally identical by construction (both
|
|
113
|
+
* are F13.2 verbatim), so X1's facet satisfies this slot as-is.
|
|
114
|
+
*
|
|
115
|
+
* At the X1→X2 rebase these two lines may collapse to
|
|
116
|
+
* `export type NgisHostContextFacet = NgisContextFacet;` — a mechanical change
|
|
117
|
+
* with no behavioural effect.
|
|
118
|
+
*/
|
|
119
|
+
export type NgisHostContextValue = string | number | boolean | null | readonly (string | number)[];
|
|
120
|
+
export interface NgisHostContextFacet {
|
|
121
|
+
get(key: string): Promise<NgisHostContextValue | undefined>;
|
|
122
|
+
getAll(): Promise<Readonly<Record<string, NgisHostContextValue>>>;
|
|
123
|
+
/** Auto-namespaced to `plugin:<pluginId>:<key>` — **F14.11, as amended by
|
|
124
|
+
* F15.14**: the deprecated dotted `plugin.<pluginId>.<key>` spelling was
|
|
125
|
+
* removed in Stage 15 (W1, Z10) and is now written by nothing, so an
|
|
126
|
+
* expression against it names a key no publisher produces. A caller-supplied
|
|
127
|
+
* namespace prefix is rejected, not silently re-prefixed. */
|
|
128
|
+
set(key: string, value: NgisHostContextValue): Promise<void>;
|
|
129
|
+
/** Compiles and evaluates a when-grammar v1 expression once. */
|
|
130
|
+
evaluate(expression: string): Promise<boolean>;
|
|
131
|
+
/** Fires when any listed key changes, batched per microtask. */
|
|
132
|
+
onChange(keys: readonly string[], listener: (changed: Readonly<Record<string, NgisHostContextValue>>) => void): NgisUnsubscribe;
|
|
133
|
+
}
|
|
134
|
+
/** F13.2 verbatim. Implemented by X3 (W2) in `src/sdk/facets/ui.ts`. */
|
|
135
|
+
export interface NgisQuickPickItem {
|
|
136
|
+
id: string;
|
|
137
|
+
label: string;
|
|
138
|
+
description?: string;
|
|
139
|
+
}
|
|
140
|
+
export interface NgisProgressHandle {
|
|
141
|
+
update(patch: {
|
|
142
|
+
percent?: number;
|
|
143
|
+
message?: string;
|
|
144
|
+
}): Promise<void>;
|
|
145
|
+
done(): Promise<void>;
|
|
146
|
+
}
|
|
147
|
+
export interface NgisUiFacet {
|
|
148
|
+
toast(options: {
|
|
149
|
+
message: string;
|
|
150
|
+
kind?: "info" | "success" | "warning" | "error";
|
|
151
|
+
description?: string;
|
|
152
|
+
}): Promise<void>;
|
|
153
|
+
confirm(options: {
|
|
154
|
+
title: string;
|
|
155
|
+
description?: string;
|
|
156
|
+
confirmLabel?: string;
|
|
157
|
+
cancelLabel?: string;
|
|
158
|
+
destructive?: boolean;
|
|
159
|
+
}): Promise<boolean>;
|
|
160
|
+
/** Resolves to the chosen item's `id`, or `null` if dismissed. */
|
|
161
|
+
quickPick(options: {
|
|
162
|
+
title?: string;
|
|
163
|
+
items: readonly NgisQuickPickItem[];
|
|
164
|
+
}): Promise<string | null>;
|
|
165
|
+
progress(options: {
|
|
166
|
+
title: string;
|
|
167
|
+
}): Promise<NgisProgressHandle>;
|
|
168
|
+
}
|
|
169
|
+
/** F13.2 verbatim. Implemented by X4 (W2) over the E7 `gisCommandRegistry`. */
|
|
170
|
+
export interface NgisCommandSummary {
|
|
171
|
+
id: string;
|
|
172
|
+
title: string;
|
|
173
|
+
/** The declaring plugin — a plugin can see that a command is not its own. */
|
|
174
|
+
pluginId: string;
|
|
175
|
+
}
|
|
176
|
+
export interface NgisCommandsFacet {
|
|
177
|
+
list(): Promise<NgisCommandSummary[]>;
|
|
178
|
+
/** The E7 `gisCommandRegistry` seam. Cross-plugin invocation is allowed in v1
|
|
179
|
+
* and is **not** ordered — `pluginDependencies` activation ordering is Stage 15
|
|
180
|
+
* (XD15). A command whose plugin has not activated rejects. */
|
|
181
|
+
invoke(commandId: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
182
|
+
}
|
|
183
|
+
export interface NgisHostAPI {
|
|
184
|
+
/** `NGIS_MAP_API_VERSION` — "0.4.0". */
|
|
185
|
+
readonly version: string;
|
|
186
|
+
/** The plugin this facade is bound to. Every facade is per-plugin: it is what
|
|
187
|
+
* namespaces `storage`/`context.set` and what attributes audit events. */
|
|
188
|
+
readonly pluginId: string;
|
|
189
|
+
/** **FROZEN 0.3.0 surface, ungated.** `layers` · `camera` · `selection` ·
|
|
190
|
+
* `draw` · `measure` · `panels` · `events` · `getMap()`. Not re-exported
|
|
191
|
+
* facet-by-facet onto the root: `host.api.layers` stays the only spelling,
|
|
192
|
+
* so no shipped call site moves. */
|
|
193
|
+
api: NgisMapAPI;
|
|
194
|
+
scene: NgisSceneFacet;
|
|
195
|
+
resources: NgisResourcesFacet;
|
|
196
|
+
models: NgisModelsFacet;
|
|
197
|
+
tasks: NgisTasksFacet;
|
|
198
|
+
viz: NgisVizFacet;
|
|
199
|
+
storage: NgisStorageFacet;
|
|
200
|
+
context: NgisHostContextFacet;
|
|
201
|
+
ui: NgisUiFacet;
|
|
202
|
+
commands: NgisCommandsFacet;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Back-compat alias — `activate(host: NgisPluginHost)` signatures do not change,
|
|
206
|
+
* and a 0.3-era plugin reading only `host.api` still type-checks and still runs.
|
|
207
|
+
*
|
|
208
|
+
* **Not yet re-exported from `@/sdk`.** `src/sdk/plugin.ts` still exports the
|
|
209
|
+
* 0.3 `NgisPluginHost = { api }`, and that is the name `@/sdk` re-exports today.
|
|
210
|
+
* Widening it is X4's atomic `NGIS_MAP_API_VERSION` → 0.4.0 flip in W2 (ED19):
|
|
211
|
+
* `plugin.ts`, `plugin-runtime.ts` and every host call site
|
|
212
|
+
* (`GisWorkspace.tsx:182` builds `{ api }`) are X4's files, and widening the
|
|
213
|
+
* type without them would break `tsc` across four modules X2 does not own.
|
|
214
|
+
*/
|
|
215
|
+
export type NgisPluginHost = NgisHostAPI;
|
|
216
|
+
/**
|
|
217
|
+
* Thrown by every member of a facet slot that has not been wired yet. Loud on
|
|
218
|
+
* purpose: F13.5's refusal rule is "a typed error, never empty data", because a
|
|
219
|
+
* silent empty list is indistinguishable from a real empty scene.
|
|
220
|
+
*/
|
|
221
|
+
export declare class NgisFacetUnavailableError extends Error {
|
|
222
|
+
readonly facet: string;
|
|
223
|
+
readonly member: string;
|
|
224
|
+
constructor(facet: string, member: string, owner: string);
|
|
225
|
+
}
|
|
226
|
+
export interface NgisHostAPIOptions {
|
|
227
|
+
pluginId: string;
|
|
228
|
+
/** The 0.3 facade from `createNgisMapAPI(...).api` — kept at `host.api`. */
|
|
229
|
+
api: NgisMapAPI;
|
|
230
|
+
scene: NgisSceneFacet;
|
|
231
|
+
resources: NgisResourcesFacet;
|
|
232
|
+
models: NgisModelsFacet;
|
|
233
|
+
tasks: NgisTasksFacet;
|
|
234
|
+
/** X1 (W1). Omitted until the context store is wired. */
|
|
235
|
+
context?: NgisHostContextFacet;
|
|
236
|
+
/** X3 (W2). */
|
|
237
|
+
viz?: NgisVizFacet;
|
|
238
|
+
/** X3 (W2). */
|
|
239
|
+
storage?: NgisStorageFacet;
|
|
240
|
+
/** X3 (W2). */
|
|
241
|
+
ui?: NgisUiFacet;
|
|
242
|
+
/** X4 (W2). */
|
|
243
|
+
commands?: NgisCommandsFacet;
|
|
244
|
+
/** Defaults to `NGIS_MAP_API_VERSION`. F13.13 bumps that constant to
|
|
245
|
+
* `"0.4.0"` in X4, atomically with its consumers (ED19) — this facade reads
|
|
246
|
+
* it rather than hard-coding a version that would then disagree with the
|
|
247
|
+
* runtime's negotiation. */
|
|
248
|
+
version?: string;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Assembles the 0.4 facade. Every facet is injected: `src/sdk/` sits below
|
|
252
|
+
* `src/store/`, `src/api/` and `src/features/`, so the wiring lives at the host
|
|
253
|
+
* call site — which is also what makes the facade worker-ready (a worker tier
|
|
254
|
+
* injects RPC-backed facets against the same interfaces).
|
|
255
|
+
*/
|
|
256
|
+
export declare function createNgisHostAPI(options: NgisHostAPIOptions): NgisHostAPI;
|