@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.
Files changed (70) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +31 -0
  3. package/dist/index.cjs +76 -0
  4. package/dist/index.d.ts +77 -0
  5. package/dist/index.mjs +102 -0
  6. package/dist/src/api/analysis.d.ts +140 -0
  7. package/dist/src/api/resources.d.ts +530 -0
  8. package/dist/src/api/scenes.d.ts +251 -0
  9. package/dist/src/api/users.d.ts +22 -0
  10. package/dist/src/domain/algorithms/deck-layer-style.d.ts +34 -0
  11. package/dist/src/domain/algorithms/maplibre-style.d.ts +63 -0
  12. package/dist/src/domain/algorithms/raster-color-ramps.d.ts +37 -0
  13. package/dist/src/domain/algorithms/scene-layer-type.d.ts +25 -0
  14. package/dist/src/domain/algorithms/symbol-compile.d.ts +100 -0
  15. package/dist/src/domain/algorithms/symbol-params.d.ts +90 -0
  16. package/dist/src/domain/map/bounds.d.ts +8 -0
  17. package/dist/src/domain/map/constants.d.ts +40 -0
  18. package/dist/src/domain/map/layer-builders.d.ts +32 -0
  19. package/dist/src/domain/map/rendered-layers.d.ts +30 -0
  20. package/dist/src/domain/map/style-ready.d.ts +24 -0
  21. package/dist/src/domain/map/tile-url.d.ts +20 -0
  22. package/dist/src/domain/map/types.d.ts +128 -0
  23. package/dist/src/domain/models/deck-layer-style.d.ts +211 -0
  24. package/dist/src/domain/models/scene-layer-type.d.ts +23 -0
  25. package/dist/src/domain/models/symbol.d.ts +424 -0
  26. package/dist/src/lib/api.d.ts +82 -0
  27. package/dist/src/lib/auth-session.d.ts +22 -0
  28. package/dist/src/lib/raster-color-layer/RasterColorLayer.d.ts +48 -0
  29. package/dist/src/lib/raster-color-layer/TileGrid.d.ts +31 -0
  30. package/dist/src/lib/raster-color-layer/colorRamp.d.ts +18 -0
  31. package/dist/src/lib/raster-color-layer/shaders/raster-color.frag.d.ts +2 -0
  32. package/dist/src/lib/raster-color-layer/shaders/raster-color.vert.d.ts +2 -0
  33. package/dist/src/lib/raster-color-layer/zoomInterpolate.d.ts +2 -0
  34. package/dist/src/sdk/commands.d.ts +113 -0
  35. package/dist/src/sdk/context/keys.d.ts +148 -0
  36. package/dist/src/sdk/context/publishers.d.ts +198 -0
  37. package/dist/src/sdk/context/store.d.ts +78 -0
  38. package/dist/src/sdk/context/when.d.ts +69 -0
  39. package/dist/src/sdk/contributions/dispatch.d.ts +78 -0
  40. package/dist/src/sdk/contributions/panel-id.d.ts +25 -0
  41. package/dist/src/sdk/contributions/registry.d.ts +199 -0
  42. package/dist/src/sdk/contributions/symbol-renderers.d.ts +107 -0
  43. package/dist/src/sdk/contributions/types.d.ts +288 -0
  44. package/dist/src/sdk/contributions/views-bridge.d.ts +92 -0
  45. package/dist/src/sdk/define-plugin.d.ts +17 -0
  46. package/dist/src/sdk/facets/storage.d.ts +152 -0
  47. package/dist/src/sdk/facets/types.d.ts +370 -0
  48. package/dist/src/sdk/host-api.d.ts +256 -0
  49. package/dist/src/sdk/map-api.d.ts +288 -0
  50. package/dist/src/sdk/panels.d.ts +130 -0
  51. package/dist/src/sdk/plugin.d.ts +145 -0
  52. package/dist/src/sdk/rail-tools.d.ts +58 -0
  53. package/dist/src/sdk/scopes.d.ts +158 -0
  54. package/dist/src/systems/renderer/DeckSceneRenderer.d.ts +26 -0
  55. package/dist/src/systems/renderer/FlowFieldLayer.d.ts +68 -0
  56. package/dist/src/systems/renderer/LayerRendererRegistry.d.ts +132 -0
  57. package/dist/src/systems/renderer/authenticated-deck-load.d.ts +4 -0
  58. package/dist/src/systems/renderer/deck/deck-layer-builders.d.ts +29 -0
  59. package/dist/src/systems/renderer/deck/deck-layer-helpers.d.ts +21 -0
  60. package/dist/src/systems/renderer/deck/mvt-point-aggregation-layer.d.ts +107 -0
  61. package/dist/src/systems/renderer/flow-field/flow-field-resources.d.ts +84 -0
  62. package/dist/src/systems/renderer/flow-field/flow-field-shaders.d.ts +4 -0
  63. package/dist/src/systems/renderer/symbol/SpriteRegistry.d.ts +34 -0
  64. package/dist/src/systems/renderer/symbol/entries.d.ts +67 -0
  65. package/dist/src/types/analysis.d.ts +205 -0
  66. package/dist/src/types/common.d.ts +17 -0
  67. package/dist/src/types/extensions.d.ts +560 -0
  68. package/dist/src/types/gis.d.ts +242 -0
  69. package/dist/src/types/market-social.d.ts +378 -0
  70. 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;
@@ -0,0 +1,2 @@
1
+ export type ZoomStop = [zoom: number, value: number];
2
+ export declare function resolveZoomStops(value: number | ZoomStop[], zoom: number): number;