@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,424 @@
|
|
|
1
|
+
export type SymbolGeometry = "point" | "line" | "polygon";
|
|
2
|
+
export type SymbolTier = 0 | 1 | 2 | 3;
|
|
3
|
+
export interface SymbolTier0LayerSpec {
|
|
4
|
+
tier: 0;
|
|
5
|
+
renderer: `builtin:${string}`;
|
|
6
|
+
params?: SymbolParamBindings;
|
|
7
|
+
}
|
|
8
|
+
export interface SymbolTier1LayerSpec {
|
|
9
|
+
tier: 1;
|
|
10
|
+
renderer: "sprite";
|
|
11
|
+
asset: string;
|
|
12
|
+
sdf?: boolean;
|
|
13
|
+
anchor?: [number, number];
|
|
14
|
+
params?: SymbolParamBindings;
|
|
15
|
+
}
|
|
16
|
+
export interface SymbolTier2LayerSpec {
|
|
17
|
+
tier: 2;
|
|
18
|
+
renderer: "shader";
|
|
19
|
+
asset: string;
|
|
20
|
+
params?: SymbolParamBindings;
|
|
21
|
+
}
|
|
22
|
+
export interface SymbolTier3LayerSpec {
|
|
23
|
+
tier: 3;
|
|
24
|
+
renderer: `plugin:${string}@${string}/${string}`;
|
|
25
|
+
params?: SymbolParamBindings;
|
|
26
|
+
}
|
|
27
|
+
export type SymbolLayerSpec = SymbolTier0LayerSpec | SymbolTier1LayerSpec | SymbolTier2LayerSpec | SymbolTier3LayerSpec;
|
|
28
|
+
export interface SymbolAnimationSpec {
|
|
29
|
+
period?: number;
|
|
30
|
+
footprint?: number;
|
|
31
|
+
reducedMotion?: "freeze" | "slow";
|
|
32
|
+
}
|
|
33
|
+
export interface SymbolExtendsRef {
|
|
34
|
+
symbolId: string;
|
|
35
|
+
version: string;
|
|
36
|
+
params: SymbolParamValues;
|
|
37
|
+
}
|
|
38
|
+
export interface SymbolManifest {
|
|
39
|
+
schema: 1;
|
|
40
|
+
id: string;
|
|
41
|
+
version: string;
|
|
42
|
+
name: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
tags?: string[];
|
|
45
|
+
category?: string;
|
|
46
|
+
geometry: SymbolGeometry;
|
|
47
|
+
/** 1..8, bottom → top. Absent on a T0 preset, which carries `extends` instead. */
|
|
48
|
+
layers?: SymbolLayerSpec[];
|
|
49
|
+
params?: Record<string, SymbolParamDef>;
|
|
50
|
+
slots?: Partial<Record<SymbolSlot, SymbolSlotDef>>;
|
|
51
|
+
animation?: SymbolAnimationSpec;
|
|
52
|
+
/** REQUIRED iff any layer.tier is 2 or 3; tiers 0/1 only. */
|
|
53
|
+
fallback?: SymbolLayerSpec[];
|
|
54
|
+
extends?: SymbolExtendsRef;
|
|
55
|
+
}
|
|
56
|
+
export type SymbolParamType = "number" | "color" | "boolean" | "enum" | "angle" | "percent";
|
|
57
|
+
export type SymbolParamValue = number | string | boolean;
|
|
58
|
+
export type SymbolParamValues = Record<string, SymbolParamValue>;
|
|
59
|
+
export interface SymbolParamDef {
|
|
60
|
+
type: SymbolParamType;
|
|
61
|
+
label?: string;
|
|
62
|
+
default: SymbolParamValue;
|
|
63
|
+
min?: number;
|
|
64
|
+
max?: number;
|
|
65
|
+
step?: number;
|
|
66
|
+
unit?: string;
|
|
67
|
+
values?: string[];
|
|
68
|
+
}
|
|
69
|
+
/** A stack layer's view of the symbol's params: alias → param name or literal.
|
|
70
|
+
*
|
|
71
|
+
* Three forms, resolved by `resolveSymbolLayerParams` (symbol-params.ts):
|
|
72
|
+
* `{ param: "speed" }` is always a reference; a bare string that names a
|
|
73
|
+
* declared param is a reference (the spelling every seed manifest uses); any
|
|
74
|
+
* other value is a literal. The explicit form exists so a symbol whose param
|
|
75
|
+
* name collides with an intended string literal can still say which it meant. */
|
|
76
|
+
export type SymbolParamBindings = Record<string, SymbolParamValue | {
|
|
77
|
+
param: string;
|
|
78
|
+
}>;
|
|
79
|
+
export declare const SYMBOL_SLOTS: readonly ["size", "color", "angle", "startTime", "phase", "data0", "data1", "data2", "data3"];
|
|
80
|
+
export type SymbolSlot = (typeof SYMBOL_SLOTS)[number];
|
|
81
|
+
export interface SymbolSlotDef {
|
|
82
|
+
label?: string;
|
|
83
|
+
/** A declared param whose resolved value is this slot's default. The seed
|
|
84
|
+
* manifests (sym01/sym02) spell it this way; `default` is the literal form
|
|
85
|
+
* and the two are mutually exclusive, `from` winning when both appear. */
|
|
86
|
+
from?: string;
|
|
87
|
+
default?: SymbolParamValue;
|
|
88
|
+
}
|
|
89
|
+
/** A scene layer's binding of one slot: a constant, a feature field, or a host-stamped value. */
|
|
90
|
+
export type SymbolSlotBinding = {
|
|
91
|
+
const: SymbolParamValue;
|
|
92
|
+
} | {
|
|
93
|
+
field: string;
|
|
94
|
+
mapping?: Record<string, unknown>;
|
|
95
|
+
} | {
|
|
96
|
+
host: string;
|
|
97
|
+
};
|
|
98
|
+
/** The fixed uniform block a manifest may not exceed (F24.5). */
|
|
99
|
+
export declare const SYMBOL_PARAM_FLOAT_SLOTS = 16;
|
|
100
|
+
export declare const SYMBOL_PARAM_COLOR_SLOTS = 8;
|
|
101
|
+
export type SymbolVisibility = "PRIVATE" | "PUBLIC";
|
|
102
|
+
export type SymbolVersionStatus = "DRAFT" | "IN_REVIEW" | "PUBLISHED" | "REJECTED" | "YANKED";
|
|
103
|
+
export type SymbolVersionPolicy = "PINNED" | "LATEST";
|
|
104
|
+
export type SymbolCatalogScope = "builtin" | "mine" | "shared" | "public";
|
|
105
|
+
export type SymbolCostHint = "light" | "moderate" | "heavy";
|
|
106
|
+
export declare const SYMBOL_ID_PATTERN: RegExp;
|
|
107
|
+
export declare const SYMBOL_BUILTIN_PREFIX = "builtin.";
|
|
108
|
+
export declare const SYMBOL_MAX_LAYERS = 8;
|
|
109
|
+
/** F24.10 caps. */
|
|
110
|
+
export declare const SYMBOL_SOURCE_MAX_BYTES: number;
|
|
111
|
+
/** F24.6.3 caps. */
|
|
112
|
+
export declare const SYMBOL_SHADER_MAX_BYTES: number;
|
|
113
|
+
export type SymbolRef = {
|
|
114
|
+
symbolId: string;
|
|
115
|
+
version: string;
|
|
116
|
+
} | {
|
|
117
|
+
symbolId: string;
|
|
118
|
+
policy: "LATEST";
|
|
119
|
+
} | {
|
|
120
|
+
inline: SymbolManifest;
|
|
121
|
+
};
|
|
122
|
+
export declare const SYMBOL_STYLE_VERSION = 1;
|
|
123
|
+
export interface SymbolStyleJson {
|
|
124
|
+
version: typeof SYMBOL_STYLE_VERSION;
|
|
125
|
+
type: "symbol";
|
|
126
|
+
symbol: SymbolRef;
|
|
127
|
+
params?: SymbolParamValues;
|
|
128
|
+
bindings?: Partial<Record<SymbolSlot, SymbolSlotBinding>>;
|
|
129
|
+
}
|
|
130
|
+
export declare const SYMBOL_FALLBACK_REASONS: readonly ["missing", "forbidden", "yanked", "incompatible", "extension-unavailable"];
|
|
131
|
+
export type SymbolFallbackReason = (typeof SYMBOL_FALLBACK_REASONS)[number];
|
|
132
|
+
/**
|
|
133
|
+
* The SCREAMING words the **server** actually emits on
|
|
134
|
+
* `SymbolResolveEntryDto.reason` — `SymbolResolveService`s four constants.
|
|
135
|
+
*
|
|
136
|
+
* This is **not** `Uppercase<SymbolFallbackReason>`, which is what it was
|
|
137
|
+
* declared as until 2026-09-02. Two of the five members do not survive that
|
|
138
|
+
* transform: the server says `NOT_FOUND` where the domain says `missing`, and
|
|
139
|
+
* `Uppercase<"extension-unavailable">` keeps the hyphen the wire spells with an
|
|
140
|
+
* underscore. There is no `INCOMPATIBLE` on the wire at all — `incompatible` is
|
|
141
|
+
* a decision the client reaches on its own.
|
|
142
|
+
*
|
|
143
|
+
* `toSymbolFallbackReason` in `src/api/symbols.ts` is the one place the two
|
|
144
|
+
* vocabularies meet, and it is the only thing that should ever translate them.
|
|
145
|
+
*/
|
|
146
|
+
export declare const SYMBOL_RESOLVE_WIRE_REASONS: readonly ["NOT_FOUND", "FORBIDDEN", "YANKED", "EXTENSION_UNAVAILABLE"];
|
|
147
|
+
export type SymbolResolveWireReason = (typeof SYMBOL_RESOLVE_WIRE_REASONS)[number];
|
|
148
|
+
export type SymbolRenderEngine = "maplibre" | "deck";
|
|
149
|
+
export interface SymbolRenderPlanLayer {
|
|
150
|
+
index: number;
|
|
151
|
+
tier: SymbolTier;
|
|
152
|
+
engine: SymbolRenderEngine;
|
|
153
|
+
spriteId?: string;
|
|
154
|
+
/** Whether the registered T1 image is an SDF and can use `icon-color`. */
|
|
155
|
+
spriteSdf?: boolean;
|
|
156
|
+
/** Constant slots MapLibre can apply to a T1 image. */
|
|
157
|
+
spriteColor?: string;
|
|
158
|
+
spriteSizePx?: number;
|
|
159
|
+
shaderAsset?: string;
|
|
160
|
+
pluginRef?: string;
|
|
161
|
+
animated: boolean;
|
|
162
|
+
}
|
|
163
|
+
export interface SymbolRenderPlanHint {
|
|
164
|
+
code: "deck-z-order-group" | "heavy-feature-count" | "reduced-motion";
|
|
165
|
+
detail: string;
|
|
166
|
+
}
|
|
167
|
+
/** A runtime resource/renderer condition that did not alter the saved style. */
|
|
168
|
+
export interface SymbolRenderRuntimeNote {
|
|
169
|
+
code: string;
|
|
170
|
+
detail: string;
|
|
171
|
+
}
|
|
172
|
+
export interface SymbolRenderPlan {
|
|
173
|
+
engine: SymbolRenderEngine;
|
|
174
|
+
geometry: SymbolGeometry;
|
|
175
|
+
layers: SymbolRenderPlanLayer[];
|
|
176
|
+
animated: boolean;
|
|
177
|
+
hints: SymbolRenderPlanHint[];
|
|
178
|
+
fallbackSource: "none" | "author" | "host";
|
|
179
|
+
fallbackReason?: SymbolFallbackReason;
|
|
180
|
+
runtimeNotes?: SymbolRenderRuntimeNote[];
|
|
181
|
+
}
|
|
182
|
+
export interface SymbolCapabilities {
|
|
183
|
+
webgl2: boolean;
|
|
184
|
+
maplibreSdf: boolean;
|
|
185
|
+
reducedMotion: boolean;
|
|
186
|
+
featureCount?: number;
|
|
187
|
+
}
|
|
188
|
+
/** Measured on one GPU (F24.8.2) — an input to the default, not a constant to freeze. */
|
|
189
|
+
export declare const SYMBOL_HEAVY_MAX_FEATURES = 10000;
|
|
190
|
+
export type SymbolClockKind = "wall" | "data" | "event";
|
|
191
|
+
export interface SymbolClockState {
|
|
192
|
+
time: number;
|
|
193
|
+
dataTime: number;
|
|
194
|
+
ticks: number;
|
|
195
|
+
running: boolean;
|
|
196
|
+
}
|
|
197
|
+
export declare const SYMBOL_CLOCK_TEST_HOOK = "__ngisSymbolClock";
|
|
198
|
+
export declare const SYMBOL_LINT_RULE_IDS: readonly ["NO_PREPROCESSOR", "NO_STORAGE_QUALIFIER", "NO_GL_IDENTIFIER", "NO_TEXTURE_SAMPLING", "NO_UNBOUNDED_LOOP", "LOOP_BOUND_TOO_LARGE", "LOOP_NESTING_TOO_DEEP", "TOO_MANY_HELPERS", "SOURCE_TOO_LARGE", "RESERVED_IDENTIFIER_PREFIX", "ENTRY_POINT_MISSING", "ENTRY_POINT_DUPLICATED"];
|
|
199
|
+
export type SymbolLintRuleId = (typeof SYMBOL_LINT_RULE_IDS)[number];
|
|
200
|
+
export interface SymbolLintDiagnostic {
|
|
201
|
+
rule: SymbolLintRuleId;
|
|
202
|
+
/** 1-based, in the AUTHOR's coordinates. */
|
|
203
|
+
line: number;
|
|
204
|
+
detail: string;
|
|
205
|
+
}
|
|
206
|
+
export interface SymbolLintResult {
|
|
207
|
+
ok: boolean;
|
|
208
|
+
diagnostics: SymbolLintDiagnostic[];
|
|
209
|
+
}
|
|
210
|
+
export declare const SYMBOL_ENTRY_FUNCTION = "ngisSymbol";
|
|
211
|
+
/** GLSL shares one namespace between a block instance and a function, so the block may not be
|
|
212
|
+
* spelled `ngisSymbol` (S24-01 finding 11). */
|
|
213
|
+
export declare const SYMBOL_UNIFORM_BLOCK_INSTANCE = "ngisU";
|
|
214
|
+
export declare const SYMBOL_RESERVED_IDENTIFIER_PREFIXES: readonly ["ngis", "P_", "DECKGL_", "project_"];
|
|
215
|
+
export interface SymbolSummaryDto {
|
|
216
|
+
symbolId: string;
|
|
217
|
+
geometry: SymbolGeometry;
|
|
218
|
+
displayName: string;
|
|
219
|
+
summary: string;
|
|
220
|
+
category: string;
|
|
221
|
+
tags: string[];
|
|
222
|
+
visibility: SymbolVisibility;
|
|
223
|
+
ownerId: string;
|
|
224
|
+
tierMax: SymbolTier;
|
|
225
|
+
animated: boolean;
|
|
226
|
+
costHint: SymbolCostHint;
|
|
227
|
+
latestPublishedVersion: string | null;
|
|
228
|
+
thumbnailUrl: string | null;
|
|
229
|
+
/**
|
|
230
|
+
* Absent when the version carries no 2× thumbnail — never a URL derived by
|
|
231
|
+
* appending `@2x`, which is the 404 the existence check exists to prevent
|
|
232
|
+
* (`S24-V208`). Amends F24.14's frozen `SymbolSummaryDto` (orchestrator
|
|
233
|
+
* ruling, 2026-09-02): the 2× became storable with `S24-V252` and would
|
|
234
|
+
* otherwise have been unaddressable from the catalog.
|
|
235
|
+
*/
|
|
236
|
+
thumbnail2xUrl?: string | null;
|
|
237
|
+
thumbnailStripUrl?: string | null;
|
|
238
|
+
}
|
|
239
|
+
export interface SymbolAssetDescriptorDto {
|
|
240
|
+
url: string;
|
|
241
|
+
sha256: string;
|
|
242
|
+
size: number;
|
|
243
|
+
contentType: string;
|
|
244
|
+
}
|
|
245
|
+
/** F24.11.2: no naga block and no `portable` flag this stage. Reintroducing `portable` is a later
|
|
246
|
+
* ruling, never a session's call. */
|
|
247
|
+
export interface SymbolValidationDto {
|
|
248
|
+
lint: {
|
|
249
|
+
tool: string;
|
|
250
|
+
version: string;
|
|
251
|
+
ok: boolean;
|
|
252
|
+
diagnostics: SymbolLintDiagnostic[];
|
|
253
|
+
};
|
|
254
|
+
glslang?: {
|
|
255
|
+
tool: string;
|
|
256
|
+
version: string;
|
|
257
|
+
variant: "es300";
|
|
258
|
+
lineOffset: number;
|
|
259
|
+
ok: boolean;
|
|
260
|
+
ms: number;
|
|
261
|
+
};
|
|
262
|
+
costHint: SymbolCostHint;
|
|
263
|
+
animated: boolean;
|
|
264
|
+
}
|
|
265
|
+
export interface SymbolVersionDto {
|
|
266
|
+
symbolId: string;
|
|
267
|
+
version: string;
|
|
268
|
+
status: SymbolVersionStatus;
|
|
269
|
+
manifest: SymbolManifest;
|
|
270
|
+
assets: Record<string, SymbolAssetDescriptorDto>;
|
|
271
|
+
validation: SymbolValidationDto | null;
|
|
272
|
+
submittedBy: string;
|
|
273
|
+
reviewedBy: string | null;
|
|
274
|
+
reviewNote: string | null;
|
|
275
|
+
publishedAt: string | null;
|
|
276
|
+
createdAt: string;
|
|
277
|
+
}
|
|
278
|
+
export interface SymbolResolveEntryDto {
|
|
279
|
+
ref: string;
|
|
280
|
+
available: boolean;
|
|
281
|
+
/** SCREAMING on the wire; the domain spelling is lower-kebab. The two
|
|
282
|
+
* vocabularies are **not** related by `Uppercase<>` — see
|
|
283
|
+
* `SYMBOL_RESOLVE_WIRE_REASONS`, which is what the server emits.
|
|
284
|
+
* `toSymbolFallbackReason` in src/api/symbols.ts is the one place they meet. */
|
|
285
|
+
reason?: SymbolResolveWireReason;
|
|
286
|
+
version?: string;
|
|
287
|
+
manifest?: SymbolManifest;
|
|
288
|
+
assets?: Record<string, SymbolAssetDescriptorDto>;
|
|
289
|
+
}
|
|
290
|
+
export interface SymbolResolveResponseDto {
|
|
291
|
+
entries: SymbolResolveEntryDto[];
|
|
292
|
+
}
|
|
293
|
+
export interface SymbolShareGrantDto {
|
|
294
|
+
symbolId: string;
|
|
295
|
+
userId: string;
|
|
296
|
+
grantedBy: string;
|
|
297
|
+
grantedAt: string;
|
|
298
|
+
}
|
|
299
|
+
export interface SymbolCatalogPageDto {
|
|
300
|
+
content: SymbolSummaryDto[];
|
|
301
|
+
page: number;
|
|
302
|
+
size: number;
|
|
303
|
+
totalElements: number;
|
|
304
|
+
totalPages: number;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* One row of the ADMIN review queue's symbols tab
|
|
308
|
+
* (`GET /api/symbols/review-queue`, `SymbolReviewQueueEntryDto`).
|
|
309
|
+
*
|
|
310
|
+
* It carries the symbol's identity beside the version's so a queue of N rows is
|
|
311
|
+
* one request rather than N+1 — the server already paid that cost once and the
|
|
312
|
+
* DTO exists so the client does not pay it again. The manifest, the `assets` map
|
|
313
|
+
* and the `validation` blob are deliberately **absent**: a reviewer opening a row
|
|
314
|
+
* fetches `GET /api/symbols/{symbolId}/versions/{version}`, which carries all
|
|
315
|
+
* three.
|
|
316
|
+
*
|
|
317
|
+
* The server serializes with `NON_NULL`, so `reviewedBy`, `reviewNote` and
|
|
318
|
+
* `thumbnailUrl` are **missing keys, not nulls**, on a row that has none —
|
|
319
|
+
* `sym19-review-queue-page.json` pins both spellings, one row each.
|
|
320
|
+
*/
|
|
321
|
+
export interface SymbolReviewQueueEntryDto {
|
|
322
|
+
symbolId: string;
|
|
323
|
+
displayName: string;
|
|
324
|
+
geometry: SymbolGeometry;
|
|
325
|
+
visibility: SymbolVisibility;
|
|
326
|
+
ownerId: string;
|
|
327
|
+
version: string;
|
|
328
|
+
status: SymbolVersionStatus;
|
|
329
|
+
tierMax: SymbolTier;
|
|
330
|
+
animated: boolean;
|
|
331
|
+
costHint: SymbolCostHint;
|
|
332
|
+
submittedBy: string;
|
|
333
|
+
reviewedBy?: string;
|
|
334
|
+
reviewNote?: string;
|
|
335
|
+
createdAt: string;
|
|
336
|
+
thumbnailUrl?: string;
|
|
337
|
+
}
|
|
338
|
+
/** The same five members as `SymbolCatalogPageDto` — the symbol domain has one
|
|
339
|
+
* page envelope, not two. Unlike the extension queue there is no unpaged array
|
|
340
|
+
* form: `/api/symbols/review-queue` answers an envelope for every request. */
|
|
341
|
+
export interface SymbolReviewQueuePageDto {
|
|
342
|
+
content: SymbolReviewQueueEntryDto[];
|
|
343
|
+
page: number;
|
|
344
|
+
size: number;
|
|
345
|
+
totalElements: number;
|
|
346
|
+
totalPages: number;
|
|
347
|
+
}
|
|
348
|
+
/** `reviewNote` is optional on approve and **required, non-blank** on reject. */
|
|
349
|
+
export interface SymbolApproveRequestDto {
|
|
350
|
+
reviewNote?: string;
|
|
351
|
+
}
|
|
352
|
+
export interface SymbolRejectRequestDto {
|
|
353
|
+
reviewNote: string;
|
|
354
|
+
}
|
|
355
|
+
export interface SymbolCreateRequestDto {
|
|
356
|
+
symbolId: string;
|
|
357
|
+
geometry: SymbolGeometry;
|
|
358
|
+
displayName: string;
|
|
359
|
+
summary?: string;
|
|
360
|
+
category?: string;
|
|
361
|
+
tags?: string[];
|
|
362
|
+
visibility?: SymbolVisibility;
|
|
363
|
+
}
|
|
364
|
+
export interface SymbolVersionCreateRequestDto {
|
|
365
|
+
version: string;
|
|
366
|
+
manifest: SymbolManifest;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* `PATCH /api/symbols/{symbolId}` — mirrors the backend's `UpdateSymbolRequest`.
|
|
370
|
+
* Every member is optional; an omitted one is left unchanged.
|
|
371
|
+
*
|
|
372
|
+
* **Not on the F24.18 name list.** Added by the W2 kickoff and recorded rather
|
|
373
|
+
* than invented silently, per F24.18's own rule: the studio (S24-21) edits
|
|
374
|
+
* identity and visibility and there was no request DTO for the leg.
|
|
375
|
+
*/
|
|
376
|
+
export interface SymbolUpdateRequestDto {
|
|
377
|
+
displayName?: string;
|
|
378
|
+
summary?: string;
|
|
379
|
+
description?: string;
|
|
380
|
+
category?: string;
|
|
381
|
+
tags?: string[];
|
|
382
|
+
visibility?: SymbolVisibility;
|
|
383
|
+
}
|
|
384
|
+
/** F24.10.2 — no `column`: StAX reports the tag's end column, which reads as wrong. */
|
|
385
|
+
export interface SymbolSanitizeErrorDto {
|
|
386
|
+
code: "SVG_ELEMENT_FORBIDDEN" | "SVG_ATTRIBUTE_FORBIDDEN" | "SVG_DTD_FORBIDDEN" | "SVG_EXTERNAL_REF" | "SVG_TOO_LARGE" | "SVG_INFLATE_LIMIT" | "SVG_PARSE_ERROR";
|
|
387
|
+
element: string;
|
|
388
|
+
/** The offending element's line — except for SVG_DTD_FORBIDDEN, where it is where parsing was
|
|
389
|
+
* refused (the end of the internal subset). */
|
|
390
|
+
line: number;
|
|
391
|
+
detail: string;
|
|
392
|
+
}
|
|
393
|
+
export interface SymbolShaderErrorDto {
|
|
394
|
+
stage: "lint" | "glslang";
|
|
395
|
+
/** The symbol layer whose function was refused, or absent when the refusal is
|
|
396
|
+
* not attributable to one. F24.14 amendment 2026-09-02 (`S24-V406`): the
|
|
397
|
+
* server already parses it — shaders arrive as `<layerIndex>.glsl` multipart
|
|
398
|
+
* parts — and after ruling A3 a symbol may carry eight tier-2 layers authored
|
|
399
|
+
* in eight composer rows, so without it the studio cannot mark the row that
|
|
400
|
+
* failed and must render the refusal as prose. */
|
|
401
|
+
layerIndex?: number;
|
|
402
|
+
rule: SymbolLintRuleId | null;
|
|
403
|
+
/** Always in the AUTHOR's coordinates; a glslang line is mapped back through the single +40
|
|
404
|
+
* offset and the assembled line is kept in `detail`. */
|
|
405
|
+
line: number;
|
|
406
|
+
column: number | null;
|
|
407
|
+
variant: "es300" | null;
|
|
408
|
+
detail: string;
|
|
409
|
+
}
|
|
410
|
+
/** Storage keys relative to `sym/{symbolId}/{version}/` (F24.14). No `.wgsl` key — F24.11.2. */
|
|
411
|
+
export declare const SYMBOL_ASSET_KEYS: {
|
|
412
|
+
readonly manifest: "manifest.json";
|
|
413
|
+
readonly source: (name: string) => string;
|
|
414
|
+
readonly sprite: "sprite.png";
|
|
415
|
+
readonly spriteJson: "sprite.json";
|
|
416
|
+
readonly sprite2x: "sprite@2x.png";
|
|
417
|
+
readonly sprite2xJson: "sprite@2x.json";
|
|
418
|
+
readonly sprite3x: "sprite@3x.png";
|
|
419
|
+
readonly sprite3xJson: "sprite@3x.json";
|
|
420
|
+
readonly shader: (layer: number) => string;
|
|
421
|
+
readonly thumbnail: "thumbnail.png";
|
|
422
|
+
readonly thumbnail2x: "thumbnail@2x.png";
|
|
423
|
+
readonly thumbnailStrip: "thumbnail-strip.png";
|
|
424
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export declare const GATEWAY_ORIGIN: string;
|
|
2
|
+
export declare const SERVER_GATEWAY_ORIGIN: string;
|
|
3
|
+
export declare const API_BASE_URL: string;
|
|
4
|
+
export declare const WS_BASE_URL: string;
|
|
5
|
+
export interface CommonResult<T = unknown> {
|
|
6
|
+
code: number;
|
|
7
|
+
message: string;
|
|
8
|
+
data: T;
|
|
9
|
+
traceId?: string | null;
|
|
10
|
+
details?: unknown;
|
|
11
|
+
}
|
|
12
|
+
export type ApiResponse<T> = CommonResult<T>;
|
|
13
|
+
export interface ApiRequestOptions {
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
headers?: HeadersInit;
|
|
16
|
+
}
|
|
17
|
+
export declare class ApiError extends Error {
|
|
18
|
+
code: number;
|
|
19
|
+
traceId?: string | null;
|
|
20
|
+
/**
|
|
21
|
+
* The parsed error payload, **verbatim**, or `null` when the body was absent
|
|
22
|
+
* or not JSON.
|
|
23
|
+
*
|
|
24
|
+
* Deliberately **not** named `detail` (Stage 12 W2.2): FastAPI's error body
|
|
25
|
+
* *contains* a `detail` key, while the Java services put a `CommonResult`
|
|
26
|
+
* envelope in exactly the same position. One field carries both, and callers
|
|
27
|
+
* narrow it themselves — see `asSkillPackageValidationError` in
|
|
28
|
+
* `src/api/skills.ts` for the structured-422 case this exists for.
|
|
29
|
+
*
|
|
30
|
+
* `unknown` on purpose: nothing may read a property off it without a guard.
|
|
31
|
+
*/
|
|
32
|
+
body?: unknown;
|
|
33
|
+
constructor(message: string, code: number, traceId?: string | null, body?: unknown);
|
|
34
|
+
}
|
|
35
|
+
export declare function getErrorMessage(err: unknown, t: (key: string) => string): string;
|
|
36
|
+
/** Called after login/refresh with the new `{accessToken, csrfToken}` pair. */
|
|
37
|
+
export declare function setSession(accessToken: string, csrfToken: string): void;
|
|
38
|
+
/** Drops the in-memory session (logout / session-expired). Does not touch the server-side cookie. */
|
|
39
|
+
export declare function clearSession(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Silent-refresh bootstrap (SG2): call once on app startup (see `AuthProvider`) to re-derive an
|
|
42
|
+
* in-memory access token from the HttpOnly refresh cookie, since memory doesn't survive a page
|
|
43
|
+
* reload. Returns whether a session was recovered; failure (no cookie / expired) just means
|
|
44
|
+
* "not logged in" and is never surfaced as an error.
|
|
45
|
+
*/
|
|
46
|
+
export declare function bootstrapSession(): Promise<boolean>;
|
|
47
|
+
export declare function getAccessToken(): string | null;
|
|
48
|
+
export declare function getAccessTokenSubject(): string | null;
|
|
49
|
+
export declare function getAuthHeaders(token?: string): HeadersInit;
|
|
50
|
+
export declare function fetchWithAuth(input: string, init?: RequestInit, token?: string): Promise<Response>;
|
|
51
|
+
/**
|
|
52
|
+
* Mints a short-lived, single-use WebSocket handshake ticket (SG2) via the authenticated
|
|
53
|
+
* `POST /api/auth/ws-ticket`. Call this immediately before opening the socket — the ticket
|
|
54
|
+
* expires quickly (`expiresInSec`, ~30s) and is consumed on first use, so don't cache the result.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getWsTicket(): Promise<string | null>;
|
|
57
|
+
/**
|
|
58
|
+
* Builds an authenticated WS URL (SG2). Replaces the previous `?token=<JWT>` pattern — which
|
|
59
|
+
* leaked the access token into server logs/browser history/referrers and, on the backend side,
|
|
60
|
+
* was never even validated — with a single-use `?ticket=` minted right before connecting. Async:
|
|
61
|
+
* returns `null` if minting the ticket fails (e.g. not authenticated), in which case the caller
|
|
62
|
+
* should not attempt to open the socket.
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildAuthorizedWsUrl(path: string, params?: Record<string, string | undefined | null>): Promise<string | null>;
|
|
65
|
+
export declare function buildAuthorizedApiUrl(input: string, params?: Record<string, string | undefined | null>): string;
|
|
66
|
+
/**
|
|
67
|
+
* CSRF-aware POST for the `/api/auth/**` endpoints that require the double-submit header
|
|
68
|
+
* (SG2: `refresh`/`logout`) — kept out of the generic `api` client below since no other
|
|
69
|
+
* endpoint needs it. Auth/token state stays owned by this file per the architecture rule.
|
|
70
|
+
*/
|
|
71
|
+
export declare function postAuthCsrf<T>(endpoint: string, body?: unknown, options?: {
|
|
72
|
+
readonly keepalive?: boolean;
|
|
73
|
+
}): Promise<T>;
|
|
74
|
+
export declare const api: {
|
|
75
|
+
get<T>(endpoint: string, params?: Record<string, unknown>, token?: string, signalOrOptions?: AbortSignal | ApiRequestOptions): Promise<T>;
|
|
76
|
+
post<T>(endpoint: string, body?: unknown, token?: string, signalOrOptions?: AbortSignal | ApiRequestOptions): Promise<T>;
|
|
77
|
+
postForm<T>(endpoint: string, formData: FormData, token?: string, signal?: AbortSignal): Promise<T>;
|
|
78
|
+
put<T>(endpoint: string, body: unknown, token?: string, signalOrOptions?: AbortSignal | ApiRequestOptions): Promise<T>;
|
|
79
|
+
patch<T>(endpoint: string, body: unknown, token?: string, signalOrOptions?: AbortSignal | ApiRequestOptions): Promise<T>;
|
|
80
|
+
delete<T>(endpoint: string, token?: string, signalOrOptions?: AbortSignal | ApiRequestOptions): Promise<T>;
|
|
81
|
+
deleteWithBody<T>(endpoint: string, body: unknown, token?: string, signal?: AbortSignal): Promise<T>;
|
|
82
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const SESSION_EXPIRED_EVENT = "glmw:session-expired";
|
|
2
|
+
export declare const SESSION_EXPIRED_REDIRECT_PATH = "/login";
|
|
3
|
+
/** The minimal user profile we persist alongside the session. Not sensitive — no tokens here. */
|
|
4
|
+
export interface StoredUser {
|
|
5
|
+
id?: string;
|
|
6
|
+
email?: string;
|
|
7
|
+
username?: string;
|
|
8
|
+
avatar?: string;
|
|
9
|
+
role?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function getStoredDeviceId(): string;
|
|
12
|
+
/**
|
|
13
|
+
* SG2: only the display profile is cached here now — no tokens. `src/lib/api.ts` owns the
|
|
14
|
+
* actual session (in-memory access token + CSRF token, backed by the HttpOnly refresh cookie).
|
|
15
|
+
*/
|
|
16
|
+
export declare function storeUser(user: StoredUser | null): void;
|
|
17
|
+
export declare function getStoredUser(): StoredUser | null;
|
|
18
|
+
/** Bumps the cross-tab auth-epoch marker — call on login/logout so other tabs re-hydrate. */
|
|
19
|
+
export declare function bumpAuthEpoch(): void;
|
|
20
|
+
/** True if a `storage` event's key is the auth-epoch marker (vs. some unrelated key). */
|
|
21
|
+
export declare function isAuthEpochKey(key: string | null): boolean;
|
|
22
|
+
export declare function notifySessionExpired(): void;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { CustomLayerInterface, CustomRenderMethodInput, Map as MapLibreMap } from "maplibre-gl";
|
|
2
|
+
import { type TileBounds, type TileRequestInitFactory } from "./TileGrid";
|
|
3
|
+
import { type ColorStop, type RasterColorMode } from "./colorRamp";
|
|
4
|
+
import { type ZoomStop } from "./zoomInterpolate";
|
|
5
|
+
export type RasterColorLayerOptions = {
|
|
6
|
+
urlTemplate: string;
|
|
7
|
+
maxZoom: number;
|
|
8
|
+
mix: [number, number, number, number];
|
|
9
|
+
range: [number, number];
|
|
10
|
+
ramp: ColorStop[];
|
|
11
|
+
colorMode?: RasterColorMode;
|
|
12
|
+
classBreaks?: number[];
|
|
13
|
+
valueRange?: [number, number];
|
|
14
|
+
opacity: number | ZoomStop[];
|
|
15
|
+
visibleZoomRange?: [number, number];
|
|
16
|
+
bounds?: TileBounds;
|
|
17
|
+
getRequestInit?: TileRequestInitFactory;
|
|
18
|
+
};
|
|
19
|
+
export declare function getRasterProjectionMatrix(options: Pick<CustomRenderMethodInput, "defaultProjectionData">): import("maplibre-gl").ProjectionMatrix;
|
|
20
|
+
export declare class RasterColorLayer implements CustomLayerInterface {
|
|
21
|
+
id: string;
|
|
22
|
+
type: "custom";
|
|
23
|
+
renderingMode: "2d";
|
|
24
|
+
private opts;
|
|
25
|
+
private map;
|
|
26
|
+
private gl;
|
|
27
|
+
private program;
|
|
28
|
+
private quadBuffer;
|
|
29
|
+
private tileGrid;
|
|
30
|
+
private rampTexture;
|
|
31
|
+
private rampDirty;
|
|
32
|
+
private uniforms;
|
|
33
|
+
private attribs;
|
|
34
|
+
constructor(id: string, options: RasterColorLayerOptions);
|
|
35
|
+
onAdd(map: MapLibreMap, gl: WebGLRenderingContext | WebGL2RenderingContext): void;
|
|
36
|
+
setColorStyle(options: {
|
|
37
|
+
ramp: ColorStop[];
|
|
38
|
+
colorMode?: RasterColorMode;
|
|
39
|
+
classBreaks?: number[];
|
|
40
|
+
valueRange?: [number, number];
|
|
41
|
+
}): void;
|
|
42
|
+
setRange(range: [number, number]): void;
|
|
43
|
+
setOpacity(opacity: number | ZoomStop[]): void;
|
|
44
|
+
setVisibleZoomRange(range: [number, number]): void;
|
|
45
|
+
render(gl: WebGLRenderingContext | WebGL2RenderingContext, options: CustomRenderMethodInput): void;
|
|
46
|
+
onRemove(): void;
|
|
47
|
+
private ensureRampTexture;
|
|
48
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type TileId = {
|
|
2
|
+
z: number;
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
};
|
|
6
|
+
export type TileBounds = [number, number, number, number];
|
|
7
|
+
export type TileRequestInitFactory = () => RequestInit | undefined;
|
|
8
|
+
export declare class TileGrid {
|
|
9
|
+
private gl;
|
|
10
|
+
private urlTemplate;
|
|
11
|
+
private maxZoom;
|
|
12
|
+
private onTileLoaded;
|
|
13
|
+
private getRequestInit?;
|
|
14
|
+
private bounds?;
|
|
15
|
+
private cache;
|
|
16
|
+
private queue;
|
|
17
|
+
private activeRequests;
|
|
18
|
+
private destroyed;
|
|
19
|
+
private frame;
|
|
20
|
+
private readonly maxCacheSize;
|
|
21
|
+
constructor(gl: WebGLRenderingContext | WebGL2RenderingContext, urlTemplate: string, maxZoom: number, onTileLoaded: () => void, getRequestInit?: TileRequestInitFactory | undefined, bounds?: TileBounds | undefined);
|
|
22
|
+
coveringTiles(west: number, south: number, east: number, north: number, zoom: number): TileId[];
|
|
23
|
+
ensure(tiles: TileId[]): void;
|
|
24
|
+
getTexture(tile: TileId): WebGLTexture | null;
|
|
25
|
+
private fetchTile;
|
|
26
|
+
private pumpQueue;
|
|
27
|
+
private scheduleRetry;
|
|
28
|
+
private evictIfNeeded;
|
|
29
|
+
private disposeEntry;
|
|
30
|
+
destroy(): void;
|
|
31
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type ColorStop = {
|
|
2
|
+
stop: number;
|
|
3
|
+
color: [number, number, number, number];
|
|
4
|
+
};
|
|
5
|
+
export type RasterColorMode = "continuous" | "classified";
|
|
6
|
+
export type RasterClassificationMethod = "equal-interval" | "manual";
|
|
7
|
+
export declare function buildColorRampData(stops: ColorStop[], resolution?: number): Uint8Array<ArrayBuffer>;
|
|
8
|
+
export declare function isValidClassBreaks(value: unknown, range?: [number, number], colorCount?: number): value is number[];
|
|
9
|
+
export declare function buildEqualIntervalBreaks(min: number, max: number, classCount: number): number[] | null;
|
|
10
|
+
export declare function normalizeClassBreaks(classBreaks: unknown, range: [number, number], colorCount?: number): number[] | null;
|
|
11
|
+
export declare function buildClassifiedColorRampData(stops: ColorStop[], classBreaks: unknown, range: [number, number], resolution?: number): Uint8Array<ArrayBuffer> | null;
|
|
12
|
+
export declare function buildRasterColorRampData(stops: ColorStop[], options?: {
|
|
13
|
+
colorMode?: RasterColorMode;
|
|
14
|
+
classBreaks?: unknown;
|
|
15
|
+
valueRange?: [number, number];
|
|
16
|
+
}, resolution?: number): Uint8Array<ArrayBuffer>;
|
|
17
|
+
export declare function computeRasterColorMix(colorRampRes: number, mix: [number, number, number, number], range: [number, number]): [number, number, number, number];
|
|
18
|
+
export declare function computeRasterColorOffset(colorRampRes: number, offset: number, range: [number, number]): number;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const fragSrc = "\nprecision mediump float;\n\nuniform sampler2D u_tile;\nuniform sampler2D u_color_ramp;\nuniform vec3 u_colorization_mix;\nuniform float u_colorization_offset;\nuniform float u_opacity;\n\nvarying vec2 v_uv;\n\nvoid main() {\n vec4 c = texture2D(u_tile, v_uv);\n\n float value = u_colorization_offset + dot(c.rgb, u_colorization_mix);\n vec4 ramped = texture2D(u_color_ramp, vec2(value, 0.5));\n\n if (ramped.a > 0.0) ramped.rgb /= ramped.a;\n\n float alpha = ramped.a * u_opacity * c.a;\n gl_FragColor = vec4(ramped.rgb * alpha, alpha);\n}\n";
|
|
2
|
+
export default fragSrc;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const vertSrc = "\nattribute vec2 a_pos;\n\nuniform mat4 u_matrix;\nuniform vec2 u_tile_tl;\nuniform vec2 u_tile_scale;\n\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_pos;\n vec2 mercator = u_tile_tl + a_pos * u_tile_scale;\n gl_Position = u_matrix * vec4(mercator, 0.0, 1.0);\n}\n";
|
|
2
|
+
export default vertSrc;
|