@tileflow/dev 0.1.0-alpha.14 → 0.1.0-alpha.17

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/README.md CHANGED
@@ -14,10 +14,131 @@ const artifacts = await createTileflowBuildArtifacts({
14
14
  });
15
15
  ```
16
16
 
17
+ `createTileflowStyle`, `createTileflowStyles`, and artifact construction all enforce the same
18
+ recursive JSON-value invariant and MapLibre style-spec semantics without fetching remote resources.
19
+ Invalid output throws `TileflowStyleValidationError` with at most 32 deterministic
20
+ `map`/`path`/`message` issues; layer indexes are projected to stable layer IDs.
21
+
22
+ For a watched, last-known-good integration, use one artifact session rather than recompiling each
23
+ request independently:
24
+
25
+ ```ts
26
+ import {createTileflowArtifactSession} from '@tileflow/dev';
27
+
28
+ const session = await createTileflowArtifactSession({
29
+ config: 'tileflow.config.ts',
30
+ watch: true,
31
+ });
32
+
33
+ const unsubscribe = session.subscribe((state) => {
34
+ // building -> ready, or invalid while getLastGoodArtifacts() remains available
35
+ console.log(state.status, state.generation);
36
+ });
37
+
38
+ unsubscribe();
39
+ await session.close();
40
+ ```
41
+
42
+ The bounded watcher follows the config, transitive local TypeScript/JavaScript/JSON imports, and
43
+ effective icon inputs. Generations are monotonic, overlapping refreshes are latest-wins, invalid
44
+ edits retain the last good snapshot, and caller-supplied output directories can be ignored to avoid
45
+ feedback loops. `tileflow dev`, `capture --watch`, and framework adapters use this shared status
46
+ vocabulary.
47
+
48
+ Custom preview servers can select the same map or standalone scene semantics as the CLI:
49
+
50
+ ```ts
51
+ import {createTileflowDevRequestHandler} from '@tileflow/dev';
52
+
53
+ const fetch = createTileflowDevRequestHandler({
54
+ session,
55
+ scene: 'madrid-mobile',
56
+ });
57
+ ```
58
+
59
+ `map` and `scene` are mutually exclusive. Map preview uses the configured `view`; scene preview
60
+ uses its committed camera and CSS viewport. `resolveTileflowPreview()` exposes the validated
61
+ selection for custom integrations. Application-target scenes remain the responsibility of the
62
+ application's development server.
63
+
17
64
  If a map uses `icons: './icons/brand'`, build artifacts include the generated
18
65
  MapLibre `sprite.json`, `sprite.png`, `sprite@2x.json`, and `sprite@2x.png`
19
66
  assets alongside the styles.
20
67
 
68
+ ## Bounded vector-feature inspection
69
+
70
+ Custom Node tooling can inspect only the features visible near a configured camera without opening
71
+ a browser:
72
+
73
+ ```ts
74
+ import {inspectTileflowFeatures} from '@tileflow/dev';
75
+
76
+ const inspection = await inspectTileflowFeatures(project, 'madrid', {
77
+ center: [-3.6927512, 40.4086555],
78
+ zoom: 16,
79
+ sourceLayers: ['poi'],
80
+ properties: ['name', 'class', 'subclass', 'rank'],
81
+ width: 512,
82
+ height: 512,
83
+ limit: 100,
84
+ });
85
+ ```
86
+
87
+ The inspector supports ordinary HTTP(S) vector sources and TileJSON. It bounds viewport, tile
88
+ count, individual/total bytes, scanned and returned features, property count/string lengths, and
89
+ request time; results are deduplicated and sorted deterministically. Output contains projected
90
+ properties, geometry summaries, safe origin/path metadata, and the configured source revision or
91
+ `null`. It never emits URL queries, credentials, hidden properties, response bodies, or absolute
92
+ paths. PMTiles and authenticated provider adapters are not currently supported by this primitive.
93
+
94
+ Deployment adapters can compile the same sources without writing them to disk:
95
+
96
+ ```ts
97
+ import {compileTileflowIconPackages} from '@tileflow/dev';
98
+
99
+ const result = await compileTileflowIconPackages(project, {
100
+ cwd: process.cwd(),
101
+ target: 'hosted',
102
+ });
103
+ ```
104
+
105
+ The hosted target enforces repository containment, portable icon IDs, safe SVG
106
+ references, deterministic ordering, and the public package limits. It returns
107
+ deduplicated generated files plus a canonical manifest/content hash. Upload only
108
+ those generated files: source icons and absolute paths remain local. External
109
+ sprite URLs are preserved as references and are not downloaded.
110
+
111
+ The version-1 manifest includes `renderedIcons` in the exact sorted `iconNames` order. Each entry
112
+ contains SHA-256 digests for the normalized 1x and 2x RGBA cell. The digest framing includes its
113
+ density and dimensions, zeroes RGB only where alpha is zero, and excludes filenames/source bytes.
114
+ The package content hash still covers the complete canonical manifest, including all four encoded
115
+ file hashes. Consumers can therefore distinguish a visible per-icon change from an atlas-layout or
116
+ encoding-only package change without receiving the original SVG/raster file.
117
+
118
+ `compileTileflowIconPackages` retains the exact RGBA cells used to assemble each atlas, so its
119
+ pixel digests describe delivered pixels rather than a second render. Hosted upload services must
120
+ decode the submitted PNGs and reconstruct those digests independently; client-authored manifest
121
+ analysis is not authoritative.
122
+
123
+ Custom Node tooling can inspect the same local pipeline without walking or decoding source files a
124
+ second time:
125
+
126
+ ```ts
127
+ import {inspectTileflowIconCatalogs} from '@tileflow/dev';
128
+
129
+ const inspection = await inspectTileflowIconCatalogs(project, {
130
+ cwd: process.cwd(),
131
+ mapNames: ['madrid'],
132
+ });
133
+ ```
134
+
135
+ The result keeps one catalog per resolved source directory, map-specific resolved mappings,
136
+ cwd-relative source metadata, exact atlas rectangles, both manifest pixel digests, and the shared
137
+ compiled package. It classifies remote and absent catalogs without fetching them. This is a
138
+ local-authoring integration surface: use the hosted compilation target separately for deployment
139
+ compatibility, and project only the metadata needed by an external protocol rather than serializing
140
+ generated byte arrays accidentally.
141
+
21
142
  This package is public, but it is an integration layer. Map styling primitives live in
22
143
  `@tileflow/core`; React rendering lives in `@tileflow/react`.
23
144
 
package/dist/index.d.ts CHANGED
@@ -1,11 +1,232 @@
1
1
  import { IncomingMessage, ServerResponse } from 'node:http';
2
- import { TileflowManifest, MapLibreStyle, ValidationMessage, TileflowProjectConfig, TileflowStyleOptions } from '@tileflow/core';
2
+ import { TileflowIconPackageFileName, TileflowIconPackageManifest, TileflowProjectConfig, MapLibreStyle, NormalizedTileflowCaptureScene, TileflowManifest, ValidationMessage, TileflowStyleOptions } from '@tileflow/core';
3
+
4
+ declare const tileflowArtifactSessionSchemaVersion: 1;
5
+ type TileflowArtifactDiagnostic = {
6
+ code?: string;
7
+ message: string;
8
+ path: string;
9
+ phase?: string;
10
+ };
11
+ type TileflowArtifactSessionState = {
12
+ status: 'building';
13
+ generation: number;
14
+ lastGoodGeneration?: number;
15
+ } | {
16
+ status: 'ready';
17
+ generation: number;
18
+ artifacts: TileflowBuildArtifacts;
19
+ lastGoodGeneration: number;
20
+ } | {
21
+ status: 'invalid';
22
+ generation: number;
23
+ diagnostics: TileflowArtifactDiagnostic[];
24
+ lastGoodGeneration?: number;
25
+ };
26
+ type TileflowArtifactSessionOptions = TileflowBuildArtifactsOptions & {
27
+ debounceMs?: number;
28
+ ignoredPaths?: string[];
29
+ watch?: boolean;
30
+ };
31
+ type TileflowArtifactSession = {
32
+ close(): Promise<void>;
33
+ getLastGoodArtifacts(): TileflowBuildArtifacts | undefined;
34
+ getState(): TileflowArtifactSessionState;
35
+ refresh(reason?: string): Promise<void>;
36
+ subscribe(listener: (state: TileflowArtifactSessionState) => void): () => void;
37
+ };
38
+ declare function createTileflowArtifactDiagnostics(error: unknown, cwd: string): TileflowArtifactDiagnostic[];
3
39
 
4
40
  type TileflowBuildAsset = {
5
41
  contentType: string;
6
42
  fileName: string;
7
43
  source: string | Uint8Array;
8
44
  };
45
+ type PreparedTileflowProject = {
46
+ assets: TileflowBuildAsset[];
47
+ project: TileflowProjectConfig;
48
+ watchPaths: string[];
49
+ };
50
+ type TileflowIconCompilationTarget = 'hosted' | 'local';
51
+ type TileflowIconCompilationIssue = {
52
+ message: string;
53
+ path: string;
54
+ };
55
+ type CompiledTileflowIconPackageFile = {
56
+ contentType: 'application/json' | 'image/png';
57
+ fileName: TileflowIconPackageFileName;
58
+ source: Uint8Array;
59
+ };
60
+ type CompiledTileflowIconPackage = {
61
+ contentHash: string;
62
+ files: CompiledTileflowIconPackageFile[];
63
+ manifest: TileflowIconPackageManifest;
64
+ };
65
+ type TileflowMapIconPackageBinding = {
66
+ label: string;
67
+ mapName: string;
68
+ mapping?: Record<string, string>;
69
+ packageHash: string;
70
+ };
71
+ type CompileTileflowIconPackagesResult = {
72
+ bindings: TileflowMapIconPackageBinding[];
73
+ packages: CompiledTileflowIconPackage[];
74
+ watchPaths: string[];
75
+ };
76
+ type InspectTileflowIconCatalogsOptions = {
77
+ cwd: string;
78
+ mapNames?: readonly string[];
79
+ };
80
+ type TileflowIconCatalogSourceFormat = 'jpeg' | 'png' | 'svg' | 'webp';
81
+ type TileflowIconCatalogMapping = {
82
+ iconId: string;
83
+ semantic: string;
84
+ targetStatus: 'missing' | 'present' | 'unknown';
85
+ };
86
+ type TileflowIconCatalogMappedFrom = {
87
+ map: string;
88
+ semantic: string;
89
+ };
90
+ type TileflowIconCatalogAtlasRectangle = {
91
+ height: number;
92
+ width: number;
93
+ x: number;
94
+ y: number;
95
+ };
96
+ type TileflowIconCatalogRenderedDensity = {
97
+ atlas: TileflowIconCatalogAtlasRectangle;
98
+ height: number;
99
+ pixelRatio: 1 | 2;
100
+ pixelSha256: string;
101
+ width: number;
102
+ };
103
+ type TileflowIconCatalogIcon = {
104
+ id: string;
105
+ mappedFrom: TileflowIconCatalogMappedFrom[];
106
+ rendered: {
107
+ oneX: TileflowIconCatalogRenderedDensity;
108
+ twoX: TileflowIconCatalogRenderedDensity;
109
+ };
110
+ source: {
111
+ byteLength: number;
112
+ dimensions: {
113
+ height: number;
114
+ width: number;
115
+ } | null;
116
+ format: TileflowIconCatalogSourceFormat;
117
+ path: string;
118
+ };
119
+ };
120
+ type TileflowIconCatalog = {
121
+ compiledPackage: CompiledTileflowIconPackage;
122
+ icons: TileflowIconCatalogIcon[];
123
+ insideWorkingTree: boolean;
124
+ sourcePath: string;
125
+ };
126
+ type TileflowIconCatalogMap = {
127
+ name: string;
128
+ icons: {
129
+ catalogSourcePath: string;
130
+ kind: 'local';
131
+ label: string;
132
+ mappings: TileflowIconCatalogMapping[];
133
+ packageHash: string;
134
+ } | {
135
+ inspectable: false;
136
+ kind: 'external';
137
+ mappings: TileflowIconCatalogMapping[];
138
+ } | {
139
+ inspectable: false;
140
+ kind: 'none';
141
+ mappings: TileflowIconCatalogMapping[];
142
+ };
143
+ };
144
+ type TileflowIconCatalogInspection = {
145
+ catalogs: TileflowIconCatalog[];
146
+ maps: TileflowIconCatalogMap[];
147
+ };
148
+ declare class TileflowIconCompilationError extends Error {
149
+ readonly code: "ICON_INVALID";
150
+ readonly issues: TileflowIconCompilationIssue[];
151
+ readonly phase: "icon-compilation";
152
+ constructor(issues: TileflowIconCompilationIssue[]);
153
+ }
154
+ declare const iconFileExtensions: Set<string>;
155
+ declare function compileTileflowIconPackages(project: TileflowProjectConfig, options: {
156
+ cwd: string;
157
+ target: TileflowIconCompilationTarget;
158
+ }): Promise<CompileTileflowIconPackagesResult>;
159
+ declare function inspectTileflowIconCatalogs(project: TileflowProjectConfig, options: InspectTileflowIconCatalogsOptions): Promise<TileflowIconCatalogInspection>;
160
+ declare function prepareTileflowProjectIcons(project: TileflowProjectConfig, options: {
161
+ assetBaseUrl: string;
162
+ cwd: string;
163
+ }): Promise<PreparedTileflowProject>;
164
+
165
+ type TileflowFeatureInspectionOptions = {
166
+ center: readonly [number, number];
167
+ fetch?: typeof fetch;
168
+ height?: number;
169
+ limit?: number;
170
+ properties?: readonly string[];
171
+ signal?: AbortSignal;
172
+ sourceLayers: readonly string[];
173
+ tileBaseUrl?: string;
174
+ timeoutMs?: number;
175
+ width?: number;
176
+ zoom: number;
177
+ };
178
+ type TileflowInspectedProperty = boolean | number | string;
179
+ type TileflowInspectedFeature = {
180
+ sourceLayer: string;
181
+ id: number | null;
182
+ geometry: {
183
+ type: string;
184
+ center: [number, number];
185
+ bounds: [number, number, number, number];
186
+ };
187
+ properties: Record<string, TileflowInspectedProperty>;
188
+ };
189
+ type TileflowFeatureInspection = {
190
+ schemaVersion: 1;
191
+ map: string;
192
+ camera: {
193
+ center: [number, number];
194
+ zoom: number;
195
+ viewport: {
196
+ width: number;
197
+ height: number;
198
+ };
199
+ };
200
+ source: {
201
+ id: string;
202
+ origin: string;
203
+ tileJsonPath: string | null;
204
+ tileOrigins: string[];
205
+ version: string | null;
206
+ };
207
+ sourceLayers: string[];
208
+ properties: string[];
209
+ tileZoom: number;
210
+ tilesRead: number;
211
+ scannedFeatures: number;
212
+ truncated: boolean;
213
+ features: TileflowInspectedFeature[];
214
+ };
215
+ declare function inspectTileflowFeatures(project: TileflowProjectConfig, mapName: string, input: TileflowFeatureInspectionOptions): Promise<TileflowFeatureInspection>;
216
+
217
+ type TileflowStyleValidationIssue = {
218
+ map: string;
219
+ message: string;
220
+ path: string;
221
+ };
222
+ declare class TileflowStyleValidationError extends Error {
223
+ readonly code: "STYLE_INVALID";
224
+ readonly issues: TileflowStyleValidationIssue[];
225
+ readonly phase: "style-validation";
226
+ constructor(issues: readonly TileflowStyleValidationIssue[]);
227
+ }
228
+ declare function assertValidTileflowStyle(style: MapLibreStyle, map: string): void;
229
+ declare function validateTileflowStyle(style: MapLibreStyle, map: string): TileflowStyleValidationIssue[];
9
230
 
10
231
  declare const defaultTileflowApiUrl = "https://api.tileflow.dev";
11
232
  declare const defaultTileflowConfigPath = "tileflow.config.ts";
@@ -23,10 +244,27 @@ type TileflowDevRequestHandlerOptions = {
23
244
  basePath?: string;
24
245
  config?: string;
25
246
  cwd?: string;
247
+ map?: string;
26
248
  onError?: (error: unknown) => void;
249
+ scene?: string;
250
+ session?: TileflowArtifactSession;
27
251
  styleBaseUrl?: string;
28
252
  tileBaseUrl?: string;
29
253
  };
254
+ type TileflowPreviewSelection = {
255
+ map?: string;
256
+ scene?: string;
257
+ };
258
+ type ResolvedTileflowPreview = {
259
+ camera: NormalizedTileflowCaptureScene['camera'];
260
+ label: string;
261
+ mapName: string;
262
+ viewport?: NormalizedTileflowCaptureScene['viewport'];
263
+ };
264
+ declare class TileflowPreviewSelectionError extends Error {
265
+ readonly code: "PREVIEW_SELECTION_INVALID";
266
+ constructor(message: string);
267
+ }
30
268
  type TileflowBuildArtifactsOptions = {
31
269
  assetBaseUrl?: string;
32
270
  config?: string;
@@ -37,6 +275,7 @@ type TileflowBuildArtifactsOptions = {
37
275
  type TileflowBuildArtifacts = {
38
276
  assets: TileflowBuildAsset[];
39
277
  manifest: TileflowManifest;
278
+ project: TileflowProjectConfig;
40
279
  styles: Record<string, MapLibreStyle>;
41
280
  watchPaths: string[];
42
281
  };
@@ -44,7 +283,9 @@ type WriteTileflowBuildArtifactsOptions = TileflowBuildArtifactsOptions & {
44
283
  outDir: string;
45
284
  };
46
285
  declare class TileflowValidationError extends Error {
286
+ readonly code: "CONFIG_INVALID";
47
287
  readonly messages: ValidationMessage[];
288
+ readonly phase: "config-validation";
48
289
  constructor(messages: ValidationMessage[]);
49
290
  }
50
291
  declare function loadTileflowConfig(configPath?: string, options?: LoadTileflowConfigOptions): Promise<TileflowProjectConfig>;
@@ -53,10 +294,13 @@ declare function assertValidTileflowConfig(project: TileflowProjectConfig): void
53
294
  declare function asTileflowProjectConfig(input: unknown): TileflowProjectConfig;
54
295
  declare function getTileflowMapNames(project: TileflowProjectConfig): string[];
55
296
  declare function getFirstTileflowMapName(project: TileflowProjectConfig): string;
297
+ declare function resolveTileflowPreview(project: TileflowProjectConfig, selection?: TileflowPreviewSelection): ResolvedTileflowPreview;
56
298
  declare function getTileflowStyleMapName(path: string): string;
57
299
  declare function createTileflowManifest(project: TileflowProjectConfig, options?: TileflowManifestOptions): TileflowManifest;
58
300
  declare function createTileflowStyle(project: TileflowProjectConfig, mapName: string, options?: TileflowStyleOptions): MapLibreStyle;
301
+ declare function createTileflowStyles(project: TileflowProjectConfig, options?: TileflowStyleOptions): Record<string, MapLibreStyle>;
59
302
  declare function createTileflowBuildArtifacts(options?: TileflowBuildArtifactsOptions): Promise<TileflowBuildArtifacts>;
303
+ declare function createTileflowArtifactSession(options?: TileflowArtifactSessionOptions): Promise<TileflowArtifactSession>;
60
304
  declare function getTileflowWatchPaths(options?: Pick<TileflowBuildArtifactsOptions, 'config' | 'cwd'>): Promise<string[]>;
61
305
  declare function writeTileflowBuildArtifacts(options: WriteTileflowBuildArtifactsOptions): Promise<TileflowBuildArtifacts>;
62
306
  declare function isTileflowRequestUrl(url: string | undefined, basePath: string): boolean;
@@ -66,6 +310,13 @@ declare function joinTileflowPublicUrl(publicBase: string, basePath: string): st
66
310
  declare function getTileflowAssetBasePath(basePath: string): string;
67
311
  declare function getTileflowAssetFileName(basePath: string, fileName: string): string;
68
312
  declare function createTileflowDevRequestHandler(options?: TileflowDevRequestHandlerOptions): (request: Request) => Promise<Response>;
313
+ declare function createTileflowArtifactStatus(state: TileflowArtifactSessionState): {
314
+ diagnostics?: TileflowArtifactDiagnostic[] | undefined;
315
+ lastGoodGeneration?: number | undefined;
316
+ schemaVersion: 1;
317
+ generation: number;
318
+ status: "building" | "ready" | "invalid";
319
+ };
69
320
  declare function normalizeTileflowBasePath(value?: string): string;
70
321
 
71
- export { type LoadTileflowConfigOptions, type TileflowBuildArtifacts, type TileflowBuildArtifactsOptions, type TileflowDevRequestHandlerOptions, type TileflowManifestOptions, TileflowValidationError, type WriteTileflowBuildArtifactsOptions, asTileflowProjectConfig, assertValidTileflowConfig, createTileflowBuildArtifacts, createTileflowDevRequestHandler, createTileflowManifest, createTileflowNodeRequest, createTileflowStyle, defaultTileflowApiUrl, defaultTileflowConfigPath, defaultTileflowManifestPath, defaultTileflowTileset, getFirstTileflowMapName, getTileflowAssetBasePath, getTileflowAssetFileName, getTileflowMapNames, getTileflowStyleMapName, getTileflowWatchPaths, isTileflowRequestUrl, joinTileflowPublicUrl, loadTileflowConfig, loadValidTileflowConfig, normalizeTileflowBasePath, writeTileflowBuildArtifacts, writeTileflowNodeResponse };
322
+ export { type CompileTileflowIconPackagesResult, type CompiledTileflowIconPackage, type CompiledTileflowIconPackageFile, type InspectTileflowIconCatalogsOptions, type LoadTileflowConfigOptions, type PreparedTileflowProject, type ResolvedTileflowPreview, type TileflowArtifactDiagnostic, type TileflowArtifactSession, type TileflowArtifactSessionOptions, type TileflowArtifactSessionState, type TileflowBuildArtifacts, type TileflowBuildArtifactsOptions, type TileflowBuildAsset, type TileflowDevRequestHandlerOptions, type TileflowFeatureInspection, type TileflowFeatureInspectionOptions, type TileflowIconCatalog, type TileflowIconCatalogAtlasRectangle, type TileflowIconCatalogIcon, type TileflowIconCatalogInspection, type TileflowIconCatalogMap, type TileflowIconCatalogMappedFrom, type TileflowIconCatalogMapping, type TileflowIconCatalogRenderedDensity, type TileflowIconCatalogSourceFormat, TileflowIconCompilationError, type TileflowIconCompilationIssue, type TileflowIconCompilationTarget, type TileflowInspectedFeature, type TileflowInspectedProperty, type TileflowManifestOptions, type TileflowMapIconPackageBinding, type TileflowPreviewSelection, TileflowPreviewSelectionError, TileflowStyleValidationError, type TileflowStyleValidationIssue, TileflowValidationError, type WriteTileflowBuildArtifactsOptions, asTileflowProjectConfig, assertValidTileflowConfig, assertValidTileflowStyle, compileTileflowIconPackages, createTileflowArtifactDiagnostics, createTileflowArtifactSession, createTileflowArtifactStatus, createTileflowBuildArtifacts, createTileflowDevRequestHandler, createTileflowManifest, createTileflowNodeRequest, createTileflowStyle, createTileflowStyles, defaultTileflowApiUrl, defaultTileflowConfigPath, defaultTileflowManifestPath, defaultTileflowTileset, getFirstTileflowMapName, getTileflowAssetBasePath, getTileflowAssetFileName, getTileflowMapNames, getTileflowStyleMapName, getTileflowWatchPaths, iconFileExtensions, inspectTileflowFeatures, inspectTileflowIconCatalogs, isTileflowRequestUrl, joinTileflowPublicUrl, loadTileflowConfig, loadValidTileflowConfig, normalizeTileflowBasePath, prepareTileflowProjectIcons, resolveTileflowPreview, tileflowArtifactSessionSchemaVersion, validateTileflowStyle, writeTileflowBuildArtifacts, writeTileflowNodeResponse };