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

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
@@ -59,7 +59,9 @@ const fetch = createTileflowDevRequestHandler({
59
59
  `map` and `scene` are mutually exclusive. Map preview uses the configured `view`; scene preview
60
60
  uses its committed camera and CSS viewport. `resolveTileflowPreview()` exposes the validated
61
61
  selection for custom integrations. Application-target scenes remain the responsibility of the
62
- application's development server.
62
+ application's development server. The built-in preview records longitude, latitude, zoom, bearing,
63
+ and pitch in the current URL after the camera moves, so browser refreshes and config-triggered
64
+ reloads return to the same view. Removing those query parameters restores the configured camera.
63
65
 
64
66
  If a map uses `icons: './icons/brand'`, build artifacts include the generated
65
67
  MapLibre `sprite.json`, `sprite.png`, `sprite@2x.json`, and `sprite@2x.png`
@@ -102,8 +104,14 @@ const result = await compileTileflowIconPackages(project, {
102
104
  });
103
105
  ```
104
106
 
107
+ When a Streets map does not select a local or external icon set, the pipeline compiles the built-in
108
+ `tileflow-streets` POI catalog and merges any mapping-only overrides on top of its semantic mapping.
109
+ `modules.poi.icons: false`, a disabled POI module, or the `none` POI preset suppresses that implicit
110
+ package. An explicit local source or hosted sprite always replaces it.
111
+
105
112
  The hosted target enforces repository containment, portable icon IDs, safe SVG
106
- references, deterministic ordering, and the public package limits. It returns
113
+ references, deterministic ordering, and the public package limits. The package-owned Streets
114
+ catalog is trusted input and is the only source exempt from project-root containment. It returns
107
115
  deduplicated generated files plus a canonical manifest/content hash. Upload only
108
116
  those generated files: source icons and absolute paths remain local. External
109
117
  sprite URLs are preserved as references and are not downloaded.
@@ -0,0 +1,11 @@
1
+ # Third-party notices
2
+
3
+ ## Google Places icons
4
+
5
+ The glyph artwork in `assets/streets-poi` is adapted from Google Places icons published in the
6
+ [Google Places API documentation](https://developers.google.com/maps/documentation/places/web-service/icons).
7
+ Copyright Google LLC. The documentation content is licensed under the
8
+ [Creative Commons Attribution 4.0 License](https://creativecommons.org/licenses/by/4.0/).
9
+
10
+ Tileflow modifies the source artwork by resizing and recoloring the glyphs, then composing them
11
+ inside circular category markers with a white rim and shadow.
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <title>Cafe</title>
3
+ <circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
4
+ <circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
5
+ <circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
6
+ <circle cx="12" cy="11" r="8.25" fill="#FF9E67"/>
7
+ <svg x="6.75" y="7" width="10.5" height="7.875" viewBox="0 0 12 9" fill="#FFFFFF">
8
+ <path transform="translate(-5 -7)" fill-rule="evenodd" d="M13.4656593,7 L15.1589761,7 C15.6924964,7 16.125,7.43246448 16.125,7.96611494 L16.125,9.90201693 C16.125,10.4355875 15.6906762,10.8681319 15.1589761,10.8681319 L13.7074176,10.8681319 L11.8942308,13.043956 L8.0260989,13.043956 L6.09203297,10.8681319 L5.125,7 L13.4656593,7 Z M5.48763736,14.2527473 L15.157967,14.2527473 L15.157967,15.7032967 L5.48763736,15.7032967 Z M13.7074176,7.96703297 L15.157967,7.96703297 L15.157967,9.9010989 L13.7074176,9.9010989 Z"/>
9
+ </svg>
10
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <title>Hospital</title>
3
+ <circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
4
+ <circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
5
+ <circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
6
+ <circle cx="12" cy="11" r="8.25" fill="#F88181"/>
7
+ <svg x="8.5" y="6" width="7" height="10" viewBox="0 0 7 10" fill="#FFFFFF">
8
+ <path transform="translate(-7 -5)" fill-rule="evenodd" d="M8.55555556,14.8333333 L7,14.8333333 L7,5.5 L8.55555556,5.5 L8.55555556,9.38888889 L12.4444444,9.38888889 L12.4444444,5.5 L14,5.5 L14,14.8333333 L12.4444444,14.8333333 L12.4444444,10.9444444 L8.55555556,10.9444444 Z"/>
9
+ </svg>
10
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <title>Lodging</title>
3
+ <circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
4
+ <circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
5
+ <circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
6
+ <circle cx="12" cy="11" r="8.25" fill="#909CE1"/>
7
+ <svg x="6.5" y="7.5" width="11" height="7" viewBox="0 0 11 7" fill="#FFFFFF">
8
+ <path transform="translate(-5 -7)" fill-rule="evenodd" d="M5.86454849,7 C6.07788926,7 6.25083612,7.16733023 6.25083612,7.38333841 L6.25026087,11.23 L13.8162609,11.23 L13.8162609,11.229 L9.55363082,11.2296026 L9.55363082,7.94186138 C9.55363082,7.94186138 10.4141238,8.05735202 10.7150234,8.05735206 C12.2129784,8.05735203 13.5048382,9.50607239 14.0681491,10.3167693 L14.7461904,7.83035651 L14.7482609,8.617 L14.7491639,8.01836305 C14.7491639,7.83291732 14.8863533,7.67819481 15.0593924,7.64241177 L15.1354515,7.63461538 C15.3487923,7.63461538 15.5217391,7.8115966 15.5217391,8.01836305 L15.5217391,13.7692308 L14.7491639,13.7692308 L14.7482609,12.5 L6.25026087,12.5 L6.25083612,13.7692308 L5.47826087,13.7692308 L5.47826087,7.38333841 C5.47826087,7.19809045 5.61545027,7.04353295 5.78848942,7.00778807 L5.86454849,7 Z M7.98913043,8.05769231 C8.62915273,8.05769231 9.14799331,8.62594628 9.14799331,9.32692308 C9.14799331,10.0278999 8.62915273,10.5961538 7.98913043,10.5961538 C7.34910814,10.5961538 6.83026756,10.0278999 6.83026756,9.32692308 C6.83026756,8.62594628 7.34910814,8.05769231 7.98913043,8.05769231 Z"/>
9
+ </svg>
10
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <title>Museum</title>
3
+ <circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
4
+ <circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
5
+ <circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
6
+ <circle cx="12" cy="11" r="8.25" fill="#13B5C7"/>
7
+ <svg x="7.5" y="5.75" width="9" height="9.82" viewBox="0 0 11 12" fill="#FFFFFF">
8
+ <path transform="translate(-5 -4)" fill-rule="evenodd" d="M10.5,4.5 L16,8.5 L16,9.5 L15,9.5 L15,15 L16,15 L16,16 L5,16 L5,15 L6,15 L6,9.5 L5,9.5 L5,8.5 L10.5,4.5 Z M14,8.5 L7,8.5 L7,15 L14,15 L14,8.5 Z M8.99948459,9.49839952 L10.5053982,11.6376682 L12,9.512 L12,9.5 L13,9.5 L13,14 L12,14 L12,11.264 L10.5053982,13.6524794 L8.999,11.277 L9,14 L8,14 L8,9.5 L9,9.5 Z"/>
9
+ </svg>
10
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <title>Restaurant</title>
3
+ <circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
4
+ <circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
5
+ <circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
6
+ <circle cx="12" cy="11" r="8.25" fill="#FF9E67"/>
7
+ <svg x="8.5" y="6" width="7" height="9.625" viewBox="0 0 8 11" fill="#FFFFFF">
8
+ <path transform="translate(-6 -6)" fill-rule="evenodd" d="M12.4864865,12.0540541 L12.4864865,16.1621622 L14,16.1621622 L14,6.21621622 L12.4864865,6.21621622 L11.6216216,7.94594595 L11.6216216,10.7567568 L12.4864865,12.0540541 Z M9.02702703,10.7567568 L9.02702703,11.1891892 L10.7567568,10.3243243 L10.7567568,9.89189189 L10.7567568,7.08108108 L9.67567568,6.21621622 L9.67567568,9.45945946 L9.13513514,9.45945946 L8.81081081,9.45945946 L8.81081081,6 L7.94594595,6 L7.94594595,9.45945946 L7.62162162,9.45945946 L7.08108108,9.45945946 L7.08108108,6.21621622 L6,7.08108108 L6,9.89189189 L6,10.3243243 L7.72972973,11.1891892 L7.72972973,10.7567568 L7.72972973,16.1621622 L9.02702703,16.1621622 Z"/>
9
+ </svg>
10
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <title>School</title>
3
+ <circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
4
+ <circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
5
+ <circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
6
+ <circle cx="12" cy="11" r="8.25" fill="#7B9EB0"/>
7
+ <svg x="6.75" y="6.5" width="10.5" height="8.9" viewBox="0 0 13 11" fill="#FFFFFF">
8
+ <path transform="translate(-4 -5)" fill-rule="evenodd" d="M14.0097657,12.019911 L14.0097657,13.8695475 C13.1038778,15.4241579 10.6537375,15.3674047 10.5024279,15.3623802 C10.3511182,15.3674047 7.90097798,15.4241579 6.99509006,13.8695475 L6.99509006,12.019911 C6.99509006,12.019911 9.60423929,13.5859459 10.5024279,13.6268096 C11.4006164,13.5859459 14.0097657,12.019911 14.0097657,12.019911 Z M10.5,5 L17,8.25037977 L17,9.23855252 L16,9.738 L16,14.7579754 L15,14.7579754 L15,10.238 L10.5,12.4889323 L4,9.23855252 L4,8.25037977 L10.5,5 Z"/>
9
+ </svg>
10
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <title>Services</title>
3
+ <circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
4
+ <circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
5
+ <circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
6
+ <circle cx="12" cy="11" r="8.25" fill="#7B9EB0"/>
7
+ <svg x="6.75" y="6.25" width="10.5" height="9.55" viewBox="0 0 11 10" fill="#FFFFFF">
8
+ <path transform="translate(-5 -6)" fill-rule="evenodd" d="M11.015625,7.32533488 C13.2436218,5.65449747 15.9996948,6.04597697 15.9996948,6.04597697 L15.999,7.327 L16,7.32722697 L16,14.327227 L15.9140184,14.3269458 C11.9704111,14.3496822 11.930542,15.8108695 11.930542,15.8108695 L11.0158997,15.8108695 L11.015,14.327 L11,14.327227 L11,7.32722697 L12.123,7.327 Z M5.0078125,6.03795084 C5.0078125,6.03795084 7.7638855,5.65449747 9.99188232,7.32533488 L8.883,7.327 L10.0075073,7.32722697 L10.0075073,14.327227 L9.991,14.327 L9.99160767,15.8108695 L9.07696533,15.8108695 C9.06464946,15.6770402 8.85223435,14.3486164 5.09348894,14.3269458 L5.00750732,14.327227 L5.0078125,6.03795084 Z"/>
9
+ </svg>
10
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <title>Shopping</title>
3
+ <circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
4
+ <circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
5
+ <circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
6
+ <circle cx="12" cy="11" r="8.25" fill="#4B96F3"/>
7
+ <svg x="7" y="6.25" width="10" height="9.23" viewBox="0 0 13 12" fill="#FFFFFF">
8
+ <path transform="translate(-4 -3)" fill-rule="evenodd" d="M7.49019231,10.9275 C7.49019231,10.6215865 7.75802885,10.3747356 8.09141827,10.3747356 C8.42242788,10.3747356 8.69286058,10.6215865 8.69286058,10.9275 C8.69286058,11.6896875 9.46045673,12.3811298 10.5012981,12.3852404 C11.5421394,12.3811298 12.3060577,11.6896875 12.3086538,10.9275 C12.311899,10.6215865 12.5777885,10.3747356 12.9107452,10.3747356 C13.2415385,10.3747356 13.5137019,10.6215865 13.5137019,10.9275 C13.503101,12.3852404 12.1208654,13.4855769 10.5012981,13.4864423 C8.88259615,13.4855769 7.49689904,12.3852404 7.49019231,10.9275 Z M9.41415865,5.7046875 C9.77740385,5.03704327 10.2157212,4.76574519 10.5038942,4.78024038 C10.7881731,4.76574519 11.2264904,5.03704327 11.5901683,5.7046875 C11.8982452,6.26675481 12.1091827,7.15074519 12.1665144,8.03971154 L8.83608173,8.03971154 C8.89341346,7.15074519 9.10478365,6.26675481 9.41415865,5.7046875 M15.5291827,8.18855769 C15.4253365,8.09293269 15.2786538,8.03971154 15.130024,8.03971154 L13.2858894,8.03971154 C13.1439663,5.85439904 12.2803125,3.879375 10.5038942,3.75 C8.72314904,3.879375 7.85819712,5.85439904 7.71670673,8.03971154 L5.87213942,8.03971154 C5.72394231,8.03971154 5.57725962,8.09293269 5.47254808,8.18855769 C5.36848558,8.28569712 5.30769231,8.4159375 5.30769231,8.55439904 L4.875,14.4861779 C4.875,14.6222596 4.93665865,14.7548798 5.03985577,14.8496394 C5.14802885,14.9459135 5.29125,15 5.43944712,15 L15.5627163,15 C15.7139423,15 15.8541346,14.9476442 15.9590625,14.8496394 C16.0678846,14.7525 16.125,14.6248558 16.125,14.4861779 L15.6923077,8.55439904 C15.6923077,8.41918269 15.6328125,8.28569712 15.5291827,8.18855769"/>
9
+ </svg>
10
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
2
+ <title>Train and rail</title>
3
+ <circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
4
+ <circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
5
+ <circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
6
+ <circle cx="12" cy="11" r="8.25" fill="#10BDFF"/>
7
+ <svg x="7.875" y="5.9" width="8.25" height="9.8" viewBox="0 0 16 19" fill="#FFFFFF">
8
+ <path d="M8,0C4,0,0,.5,0,4v9.5A3.5,3.5,0,0,0,3.5,17L2,18.5V19H4.23l2-2H10l2,2h2v-.5L12.5,17A3.5,3.5,0,0,0,16,13.5V4c0-3.5-3.58-4-8-4ZM3.5,15A1.5,1.5,0,1,1,5,13.5,1.5,1.5,0,0,1,3.5,15ZM7,8H2V4H7V8ZM9,8V4h5V8Zm3.5,7A1.5,1.5,0,1,1,14,13.5,1.5,1.5,0,0,1,12.5,15Z"/>
9
+ </svg>
10
+ </svg>
package/dist/index.d.ts CHANGED
@@ -163,6 +163,7 @@ declare function prepareTileflowProjectIcons(project: TileflowProjectConfig, opt
163
163
  }): Promise<PreparedTileflowProject>;
164
164
 
165
165
  type TileflowFeatureInspectionOptions = {
166
+ apiBaseUrl?: string;
166
167
  center: readonly [number, number];
167
168
  fetch?: typeof fetch;
168
169
  height?: number;
@@ -170,7 +171,6 @@ type TileflowFeatureInspectionOptions = {
170
171
  properties?: readonly string[];
171
172
  signal?: AbortSignal;
172
173
  sourceLayers: readonly string[];
173
- tileBaseUrl?: string;
174
174
  timeoutMs?: number;
175
175
  width?: number;
176
176
  zoom: number;
@@ -231,16 +231,15 @@ declare function validateTileflowStyle(style: MapLibreStyle, map: string): Tilef
231
231
  declare const defaultTileflowApiUrl = "https://api.tileflow.dev";
232
232
  declare const defaultTileflowConfigPath = "tileflow.config.ts";
233
233
  declare const defaultTileflowManifestPath = "public/tileflow/manifest.json";
234
- declare const defaultTileflowTileset = "world";
235
234
  type LoadTileflowConfigOptions = {
236
235
  cwd?: string;
237
236
  fresh?: boolean;
238
237
  };
239
238
  type TileflowManifestOptions = {
240
239
  styleBaseUrl?: string;
241
- tileBaseUrl?: string;
242
240
  };
243
241
  type TileflowDevRequestHandlerOptions = {
242
+ apiBaseUrl?: string;
244
243
  basePath?: string;
245
244
  config?: string;
246
245
  cwd?: string;
@@ -249,7 +248,6 @@ type TileflowDevRequestHandlerOptions = {
249
248
  scene?: string;
250
249
  session?: TileflowArtifactSession;
251
250
  styleBaseUrl?: string;
252
- tileBaseUrl?: string;
253
251
  };
254
252
  type TileflowPreviewSelection = {
255
253
  map?: string;
@@ -266,11 +264,11 @@ declare class TileflowPreviewSelectionError extends Error {
266
264
  constructor(message: string);
267
265
  }
268
266
  type TileflowBuildArtifactsOptions = {
267
+ apiBaseUrl?: string;
269
268
  assetBaseUrl?: string;
270
269
  config?: string;
271
270
  cwd?: string;
272
271
  styleBaseUrl?: string;
273
- tileBaseUrl?: string;
274
272
  };
275
273
  type TileflowBuildArtifacts = {
276
274
  assets: TileflowBuildAsset[];
@@ -319,4 +317,4 @@ declare function createTileflowArtifactStatus(state: TileflowArtifactSessionStat
319
317
  };
320
318
  declare function normalizeTileflowBasePath(value?: string): string;
321
319
 
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 };
320
+ 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, getFirstTileflowMapName, getTileflowAssetBasePath, getTileflowAssetFileName, getTileflowMapNames, getTileflowStyleMapName, getTileflowWatchPaths, iconFileExtensions, inspectTileflowFeatures, inspectTileflowIconCatalogs, isTileflowRequestUrl, joinTileflowPublicUrl, loadTileflowConfig, loadValidTileflowConfig, normalizeTileflowBasePath, prepareTileflowProjectIcons, resolveTileflowPreview, tileflowArtifactSessionSchemaVersion, validateTileflowStyle, writeTileflowBuildArtifacts, writeTileflowNodeResponse };
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  // src/icons.ts
16
16
  import { readdir, readFile, realpath, stat } from "fs/promises";
17
17
  import { basename, extname, isAbsolute, relative, resolve, sep } from "path";
18
+ import { fileURLToPath } from "url";
18
19
  import { SaxesParser } from "saxes";
19
20
  import {
20
21
  compareCodeUnits,
@@ -25,7 +26,8 @@ import {
25
26
  tileflowHostedIconIdPattern,
26
27
  tileflowIconPackageLabelSchema,
27
28
  tileflowIconPackageLimits,
28
- tileflowIconPackageManifestSchema
29
+ tileflowIconPackageManifestSchema,
30
+ tileflowStreetsPoiIconMapping
29
31
  } from "@tileflow/core";
30
32
  var TileflowIconCompilationError = class extends Error {
31
33
  code = "ICON_INVALID";
@@ -44,6 +46,7 @@ var TileflowIconCompilationError = class extends Error {
44
46
  };
45
47
  var iconFileExtensions = /* @__PURE__ */ new Set([".svg", ".png", ".jpg", ".jpeg", ".webp"]);
46
48
  var iconSpriteSize = 24;
49
+ var streetsPoiIconSourceDir = fileURLToPath(new URL("../assets/streets-poi", import.meta.url));
47
50
  async function compileTileflowIconPackages(project, options) {
48
51
  const result = await compileIconSources(project, options);
49
52
  const packagesByHash = /* @__PURE__ */ new Map();
@@ -67,7 +70,11 @@ async function compileTileflowIconPackages(project, options) {
67
70
  packages: [...packagesByHash.values()].sort(
68
71
  (left, right) => compareCodeUnits(left.contentHash, right.contentHash)
69
72
  ),
70
- watchPaths: [...result.compiledBySource.keys()].sort(compareCodeUnits)
73
+ watchPaths: [
74
+ ...new Set(
75
+ result.resolvedRequests.filter((request) => !request.builtIn).map((request) => request.realSourceDir)
76
+ )
77
+ ].sort(compareCodeUnits)
71
78
  };
72
79
  }
73
80
  async function inspectTileflowIconCatalogs(project, options) {
@@ -193,7 +200,7 @@ async function compileIconSources(project, options) {
193
200
  for (const request of requests) {
194
201
  try {
195
202
  const realSourceDir = await realpath(request.sourceDir);
196
- if (options.target === "hosted" && realCwd && !isPathInside(realCwd, realSourceDir)) {
203
+ if (options.target === "hosted" && realCwd && !request.builtIn && !isPathInside(realCwd, realSourceDir)) {
197
204
  issues.push({
198
205
  message: "Hosted icon sources must remain inside the selected working tree",
199
206
  path: sourcePath(request.mapName)
@@ -293,9 +300,9 @@ async function prepareTileflowProjectIcons(project, options) {
293
300
  };
294
301
  }
295
302
  function getTileflowIconWatchPaths(project, cwd) {
296
- return uniqueStrings(getLocalIconRequests(project, cwd).map((request) => request.sourceDir)).sort(
297
- compareCodeUnits
298
- );
303
+ return uniqueStrings(
304
+ getLocalIconRequests(project, cwd).filter((request) => !request.builtIn).map((request) => request.sourceDir)
305
+ ).sort(compareCodeUnits);
299
306
  }
300
307
  function getLocalIconRequests(project, cwd) {
301
308
  return getMapIconRequests(project, cwd).filter(
@@ -310,6 +317,18 @@ function getMapIconRequests(project, cwd, mapNames) {
310
317
  throw new Error(`Unknown Tileflow map: ${mapName}`);
311
318
  }
312
319
  const iconSet = resolveIconSet(mapConfig.icons, project.icons);
320
+ if (!iconSet?.source && !iconSet?.sprite && usesBuiltInStreetsPoiIcons(mapConfig)) {
321
+ const mapping2 = sortMapping({ ...tileflowStreetsPoiIconMapping, ...iconSet?.mapping });
322
+ return {
323
+ builtIn: true,
324
+ kind: "local",
325
+ label: "tileflow-streets",
326
+ mapName,
327
+ ...mapping2 ? { mapping: mapping2 } : {},
328
+ source: "@tileflow/dev/assets/streets-poi",
329
+ sourceDir: streetsPoiIconSourceDir
330
+ };
331
+ }
313
332
  const mapping = sortMapping(iconSet?.mapping);
314
333
  if (iconSet?.source) {
315
334
  return {
@@ -328,6 +347,10 @@ function getMapIconRequests(project, cwd, mapNames) {
328
347
  };
329
348
  });
330
349
  }
350
+ function usesBuiltInStreetsPoiIcons(mapConfig) {
351
+ const poi = mapConfig.modules?.poi;
352
+ return mapConfig.basemap?.type === "streets" && poi?.enabled !== false && poi?.preset !== "none" && poi?.icons !== false;
353
+ }
331
354
  function resolveIconSet(icons, iconSets, path = []) {
332
355
  if (!icons) {
333
356
  return void 0;
@@ -994,11 +1017,11 @@ var TileflowArtifactSessionImpl = class {
994
1017
  this.#ignoredPaths = (options.ignoredPaths ?? []).map((path) => resolve2(this.#cwd, path));
995
1018
  this.#buildArtifacts = buildArtifacts;
996
1019
  this.#buildOptions = {
1020
+ apiBaseUrl: options.apiBaseUrl,
997
1021
  assetBaseUrl: options.assetBaseUrl,
998
1022
  config: options.config,
999
1023
  cwd: this.#cwd,
1000
- styleBaseUrl: options.styleBaseUrl,
1001
- tileBaseUrl: options.tileBaseUrl
1024
+ styleBaseUrl: options.styleBaseUrl
1002
1025
  };
1003
1026
  }
1004
1027
  async start() {
@@ -1429,7 +1452,7 @@ async function inspectTileflowFeatures(project, mapName, input) {
1429
1452
  `Unknown map "${mapName}". Available maps: ${available.join(", ") || "(none)"}`
1430
1453
  );
1431
1454
  }
1432
- const style = createStyleFromProject(project, mapName, { tileBaseUrl: options.tileBaseUrl });
1455
+ const style = createStyleFromProject(project, mapName, { apiBaseUrl: options.apiBaseUrl });
1433
1456
  assertValidTileflowStyle(style, mapName);
1434
1457
  const source = resolveVectorSource(style, options.sourceLayers);
1435
1458
  const fetchImplementation = options.fetch ?? globalThis.fetch;
@@ -1495,7 +1518,8 @@ async function inspectTileflowFeatures(project, mapName, input) {
1495
1518
  }
1496
1519
  const uniqueFeatures = deduplicateFeatures(features).sort(compareInspectedFeatures);
1497
1520
  const limitedFeatures = uniqueFeatures.slice(0, options.limit);
1498
- const metadataVersion = style.metadata?.["tileflow:tilesetVersion"];
1521
+ const dataIdentity = style.metadata?.["tileflow:data"];
1522
+ const metadataVersion = dataIdentity && typeof dataIdentity === "object" && "revision" in dataIdentity ? dataIdentity.revision : void 0;
1499
1523
  return {
1500
1524
  schemaVersion: 1,
1501
1525
  map: mapName,
@@ -1840,7 +1864,6 @@ function isRecord(value) {
1840
1864
  var defaultTileflowApiUrl = "https://api.tileflow.dev";
1841
1865
  var defaultTileflowConfigPath = "tileflow.config.ts";
1842
1866
  var defaultTileflowManifestPath = "public/tileflow/manifest.json";
1843
- var defaultTileflowTileset = "world";
1844
1867
  var TileflowPreviewSelectionError = class extends Error {
1845
1868
  code = "PREVIEW_SELECTION_INVALID";
1846
1869
  constructor(message) {
@@ -1889,17 +1912,7 @@ function asTileflowProjectConfig(input) {
1889
1912
  if (input && typeof input === "object" && "maps" in input && typeof input.maps === "object") {
1890
1913
  return input;
1891
1914
  }
1892
- return {
1893
- tilesets: {
1894
- [defaultTileflowTileset]: {
1895
- id: defaultTileflowTileset,
1896
- name: "World"
1897
- }
1898
- },
1899
- maps: {
1900
- main: input
1901
- }
1902
- };
1915
+ return { maps: { main: input } };
1903
1916
  }
1904
1917
  function getTileflowMapNames(project) {
1905
1918
  return Object.keys(project.maps);
@@ -1951,7 +1964,7 @@ function resolveTileflowPreview(project, selection = {}) {
1951
1964
  center: map.view?.center ? [map.view.center[0], map.view.center[1]] : [0, 0],
1952
1965
  zoom: map.view?.zoom ?? 0,
1953
1966
  bearing: map.view?.bearing ?? 0,
1954
- pitch: 0
1967
+ pitch: map.view?.pitch ?? 0
1955
1968
  },
1956
1969
  label: mapName,
1957
1970
  mapName
@@ -1991,13 +2004,12 @@ async function createTileflowBuildArtifacts(options = {}) {
1991
2004
  assetBaseUrl: resolveAssetBaseUrl(options),
1992
2005
  cwd: options.cwd ?? process.cwd()
1993
2006
  });
1994
- const styleOptions = { tileBaseUrl: options.tileBaseUrl };
2007
+ const styleOptions = { apiBaseUrl: options.apiBaseUrl };
1995
2008
  const styles = createTileflowStyles(prepared.project, styleOptions);
1996
2009
  return {
1997
2010
  assets: prepared.assets,
1998
2011
  manifest: createManifest(prepared.project, {
1999
- styleBaseUrl: options.styleBaseUrl,
2000
- tileBaseUrl: options.tileBaseUrl
2012
+ styleBaseUrl: options.styleBaseUrl
2001
2013
  }),
2002
2014
  project: prepared.project,
2003
2015
  styles,
@@ -2102,7 +2114,7 @@ function createTileflowDevRequestHandler(options = {}) {
2102
2114
  const basePath = normalizeTileflowBasePath(options.basePath);
2103
2115
  const configPath = options.config ?? defaultTileflowConfigPath;
2104
2116
  const cwd = options.cwd ?? process.cwd();
2105
- const tileBaseUrl = options.tileBaseUrl ?? defaultTileflowApiUrl;
2117
+ const apiBaseUrl = options.apiBaseUrl ?? defaultTileflowApiUrl;
2106
2118
  return async function handleTileflowDevRequest(request) {
2107
2119
  if (request.method !== "GET" && request.method !== "HEAD") {
2108
2120
  return jsonResponse({ error: "Method not allowed" }, 405);
@@ -2133,7 +2145,7 @@ function createTileflowDevRequestHandler(options = {}) {
2133
2145
  config: configPath,
2134
2146
  cwd,
2135
2147
  styleBaseUrl: options.styleBaseUrl ?? `${url.origin}${basePath}`,
2136
- tileBaseUrl
2148
+ apiBaseUrl
2137
2149
  });
2138
2150
  state = {
2139
2151
  artifacts,
@@ -2390,13 +2402,77 @@ function previewHtml(preview, basePath, state) {
2390
2402
  const styleUrl = ${JSON.stringify(styleUrl)};
2391
2403
  const previewMapOptions = ${JSON.stringify(mapOptions)};
2392
2404
 
2405
+ const cameraRanges = {
2406
+ bearing: [-180, 180],
2407
+ lat: [-90, 90],
2408
+ lng: [-180, 180],
2409
+ pitch: [0, 85],
2410
+ zoom: [0, 24]
2411
+ };
2412
+
2413
+ function readCameraFromUrl() {
2414
+ const params = new URL(location.href).searchParams;
2415
+ const camera = {};
2416
+
2417
+ for (const [name, range] of Object.entries(cameraRanges)) {
2418
+ const values = params.getAll(name);
2419
+ if (values.length !== 1 || values[0].trim() === "") return undefined;
2420
+ const value = Number(values[0]);
2421
+ if (!Number.isFinite(value) || value < range[0] || value > range[1]) return undefined;
2422
+ camera[name] = value;
2423
+ }
2424
+
2425
+ return {
2426
+ bearing: camera.bearing,
2427
+ center: [camera.lng, camera.lat],
2428
+ pitch: camera.pitch,
2429
+ zoom: camera.zoom
2430
+ };
2431
+ }
2432
+
2433
+ function resolveInitialMapOptions(options) {
2434
+ const camera = readCameraFromUrl();
2435
+ if (!camera) return options;
2436
+ const resolved = {...options};
2437
+ delete resolved.bounds;
2438
+ delete resolved.fitBoundsOptions;
2439
+ return {...resolved, ...camera};
2440
+ }
2441
+
2442
+ function formatCameraNumber(value) {
2443
+ return String(Number(value.toFixed(6)));
2444
+ }
2445
+
2446
+ function wrapLongitude(value) {
2447
+ return ((value + 180) % 360 + 360) % 360 - 180;
2448
+ }
2449
+
2450
+ function writeCameraToUrl(map) {
2451
+ const center = map.getCenter();
2452
+ const url = new URL(location.href);
2453
+ const camera = {
2454
+ bearing: map.getBearing(),
2455
+ lat: center.lat,
2456
+ lng: wrapLongitude(center.lng),
2457
+ pitch: map.getPitch(),
2458
+ zoom: map.getZoom()
2459
+ };
2460
+
2461
+ for (const [name, value] of Object.entries(camera)) {
2462
+ url.searchParams.set(name, formatCameraNumber(value));
2463
+ }
2464
+ history.replaceState(history.state, "", url.href);
2465
+ }
2466
+
2393
2467
  if (styleUrl) {
2394
2468
  const map = new maplibregl.Map({
2395
2469
  container: "map",
2396
2470
  style: styleUrl,
2397
- ...previewMapOptions
2471
+ ...resolveInitialMapOptions(previewMapOptions)
2398
2472
  });
2399
2473
  map.addControl(new maplibregl.NavigationControl(), "top-right");
2474
+ map.on("load", () => writeCameraToUrl(map));
2475
+ map.on("moveend", () => writeCameraToUrl(map));
2400
2476
  }
2401
2477
 
2402
2478
  function applyStatus(next) {
@@ -2509,7 +2585,6 @@ export {
2509
2585
  defaultTileflowApiUrl,
2510
2586
  defaultTileflowConfigPath,
2511
2587
  defaultTileflowManifestPath,
2512
- defaultTileflowTileset,
2513
2588
  getFirstTileflowMapName,
2514
2589
  getTileflowAssetBasePath,
2515
2590
  getTileflowAssetFileName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/dev",
3
- "version": "0.1.0-alpha.17",
3
+ "version": "0.1.0-alpha.18",
4
4
  "description": "Node development utilities for Tileflow configs and builds.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -23,7 +23,9 @@
23
23
  "main": "./dist/index.js",
24
24
  "types": "./dist/index.d.ts",
25
25
  "files": [
26
- "dist"
26
+ "assets",
27
+ "dist",
28
+ "THIRD_PARTY_NOTICES.md"
27
29
  ],
28
30
  "exports": {
29
31
  ".": {
@@ -38,7 +40,7 @@
38
40
  "dependencies": {
39
41
  "@mapbox/vector-tile": "2.0.5",
40
42
  "@maplibre/maplibre-gl-style-spec": "24.8.5",
41
- "@tileflow/core": ">=0.1.0-alpha.17 <0.1.0-beta.0",
43
+ "@tileflow/core": ">=0.1.0-alpha.19 <0.1.0-beta.0",
42
44
  "chokidar": "4.0.3",
43
45
  "jiti": "^2.7.0",
44
46
  "maplibre-gl": "5.24.0",