@tileflow/dev 0.1.0-alpha.40 → 0.1.0-alpha.41

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,6 +59,9 @@ The artifact plan exposes files and observed inputs from the same generation. St
59
59
  `styles[map][theme]`, never as an implicit default-theme alias. Keep that generation alive for the
60
60
  whole operation, then release it. Do not reconstruct its asset list from directory guesses.
61
61
 
62
+ Generated style files use compact JSON in both stable and immutable generation paths. Their
63
+ parsed contents are unchanged; format the JSON in your editor when inspecting a generated file.
64
+
62
65
  Map-owned tree models are prepared alongside icons and embedded in the styles. Custom tools that
63
66
  compile icons separately can use `prepareTileflowMapTreeModels` from `@tileflow/dev/icons` with
64
67
  the map's model directories, base directory, working directory, target and diagnostic path. Pass
@@ -82,6 +85,10 @@ await writeTileflowBuildArtifacts({
82
85
 
83
86
  Serve the complete output. The writer installs immutable generation assets before changing the
84
87
  manifest pointer, tracks its own files, and refuses to replace a hosted manifest by default.
88
+ Web output includes `families/<map>.json` and its immutable generation copy. The version-3
89
+ manifest selects that shared document; conventional theme JSON remains available for exports.
90
+ Web artifacts include semantic runtime colour programs. Native artifacts keep concrete styles.
91
+ Changing SDK/map package versions requires rebuilding and publishing the new artifacts.
85
92
  Native builds retain embedded PNG image sources as hashed files beside the styles, so their
86
93
  resource URLs remain portable without permitting data URLs in the native profile.
87
94
  `overwriteHostedManifest: true` is an explicit migration option, not a normal build setting.
package/dist/artifacts.js CHANGED
@@ -32,7 +32,7 @@ import {
32
32
  usesTileflowLineBackgroundGlyphs,
33
33
  writeTileflowArtifactPlan,
34
34
  writeTileflowBuildArtifacts
35
- } from "./chunk-AVJMTXW5.js";
35
+ } from "./chunk-GXLY73PD.js";
36
36
  import {
37
37
  getTileflowAssetBasePath,
38
38
  getTileflowAssetFileName,
@@ -57,6 +57,7 @@ import {
57
57
  createStylesFromCatalog,
58
58
  createStylesFromCatalogWithInspection,
59
59
  createTileflowMapBuildManifest,
60
+ createTileflowStyleFamily,
60
61
  tileflowMapBuildManifestFileName
61
62
  } from "@tileflow/core/build";
62
63
  import { parseTileflowRuntimeManifest } from "@tileflow/core/manifest";
@@ -67,6 +68,7 @@ import {
67
68
  tileflowNativeBuildRecordFileName,
68
69
  TileflowNativeCompatibilityError as TileflowNativeCompatibilityError4
69
70
  } from "@tileflow/core/native-profile";
71
+ import { prepareTileflowStyleFamilyForRendering } from "@tileflow/core/runtime";
70
72
 
71
73
  // src/image-source-assets.ts
72
74
  import { createHash } from "crypto";
@@ -1446,6 +1448,7 @@ function prepareTileflowNativeStyles(input, assets, policy = {}) {
1446
1448
  Object.defineProperty(nativeFaces, face.family, { value: face.source, enumerable: true });
1447
1449
  }
1448
1450
  delete metadata[tileflowStyleFontFacesMetadataKey];
1451
+ delete metadata["tileflow:colors"];
1449
1452
  const { projection: _projection, ...rest } = original;
1450
1453
  const style = {
1451
1454
  ...rest,
@@ -2264,11 +2267,15 @@ async function createTileflowArtifactPlan(prepared, options = {}) {
2264
2267
  throw new TileflowLocalTilesetProductionError();
2265
2268
  }
2266
2269
  const inspected = options.inspection ? createTileflowStylesWithInspection(prepared.project, {
2270
+ runtimeColors: true,
2267
2271
  apiBaseUrl: options.apiBaseUrl,
2268
2272
  mapAssets: prepared.mapAssets
2269
2273
  }) : void 0;
2270
2274
  const compileStyles = renderer === "native" ? createStylesFromCatalog : createTileflowStyles;
2271
2275
  const compiledStyles = inspected?.styles ?? compileStyles(prepared.project, {
2276
+ // Both renderers share compilation before Native's representation-only lowering.
2277
+ // Native removes the web-only binding catalog after that common semantic pipeline.
2278
+ runtimeColors: true,
2272
2279
  apiBaseUrl: options.apiBaseUrl,
2273
2280
  mapAssets: prepared.mapAssets
2274
2281
  });
@@ -2335,7 +2342,7 @@ async function createTileflowArtifactPlan(prepared, options = {}) {
2335
2342
  const stableManifest = renderer === "native" ? createManifest(prepared.project, {
2336
2343
  styleBaseUrl: nativePublicBase(options.styleBaseUrl ?? ".")
2337
2344
  }) : createFontAwareManifest(
2338
- createManifest(prepared.project, { styleBaseUrl: options.styleBaseUrl }),
2345
+ createManifest(prepared.project, { styleBaseUrl: options.styleBaseUrl, families: true }),
2339
2346
  styles
2340
2347
  );
2341
2348
  const inputs = {
@@ -2409,6 +2416,9 @@ function getTileflowArtifactFiles(artifacts) {
2409
2416
  return getStableTileflowArtifactFiles(artifacts);
2410
2417
  }
2411
2418
  function getStableTileflowArtifactFiles(artifacts) {
2419
+ for (const [mapName, themes] of Object.entries(artifacts.styles))
2420
+ for (const themeName of Object.keys(themes))
2421
+ assertTileflowArtifactFileName(`styles/${mapName}/${themeName}.json`);
2412
2422
  const files = [
2413
2423
  {
2414
2424
  contentType: "application/json; charset=utf-8",
@@ -2426,10 +2436,16 @@ function getStableTileflowArtifactFiles(artifacts) {
2426
2436
  ([mapName, themes]) => Object.entries(themes).map(([themeName, style]) => ({
2427
2437
  contentType: "application/json; charset=utf-8",
2428
2438
  fileName: `styles/${mapName}/${themeName}.json`,
2429
- source: `${JSON.stringify(style, null, 2)}
2439
+ source: `${JSON.stringify(style)}
2430
2440
  `
2431
2441
  }))
2432
2442
  ),
2443
+ ...!artifacts.nativeBuild ? Object.entries(artifacts.styles).map(([mapName, styles]) => ({
2444
+ contentType: "application/json; charset=utf-8",
2445
+ fileName: `families/${mapName}.json`,
2446
+ source: `${JSON.stringify(prepareTileflowStyleFamilyForRendering(createTileflowStyleFamily(styles)))}
2447
+ `
2448
+ })) : [],
2433
2449
  ...artifacts.assets,
2434
2450
  ...artifacts.nativeBuild ? [
2435
2451
  {
@@ -2464,6 +2480,13 @@ function createGenerationManifest(manifest, generation, assets) {
2464
2480
  mapName,
2465
2481
  {
2466
2482
  ...map,
2483
+ ...map.familyUrl ? {
2484
+ familyUrl: insertGenerationInPublicUrl(
2485
+ map.familyUrl,
2486
+ `families/${mapName}.json`,
2487
+ generation
2488
+ )
2489
+ } : {},
2467
2490
  themes: Object.fromEntries(
2468
2491
  Object.entries(map.themes).map(([themeName, theme]) => [
2469
2492
  themeName,
@@ -2517,7 +2540,7 @@ function createGenerationArtifactFiles(artifacts, generation, nativeUrls) {
2517
2540
  return {
2518
2541
  contentType: "application/json; charset=utf-8",
2519
2542
  fileName: `${prefix}/styles/${mapName}/${themeName}.json`,
2520
- source: `${JSON.stringify(generationStyle, null, 2)}
2543
+ source: `${JSON.stringify(generationStyle)}
2521
2544
  `
2522
2545
  };
2523
2546
  })
@@ -2526,7 +2549,35 @@ function createGenerationArtifactFiles(artifacts, generation, nativeUrls) {
2526
2549
  ...asset,
2527
2550
  fileName: `${prefix}/${asset.fileName}`
2528
2551
  }));
2529
- return validateArtifactFiles([...stableFiles, ...immutableStyles, ...immutableAssets]);
2552
+ const immutableFamilies = artifacts.nativeBuild ? [] : Object.keys(artifacts.styles).map((mapName) => ({
2553
+ contentType: "application/json; charset=utf-8",
2554
+ fileName: `${prefix}/families/${mapName}.json`,
2555
+ source: `${JSON.stringify(
2556
+ prepareTileflowStyleFamilyForRendering(
2557
+ createTileflowStyleFamily(
2558
+ Object.fromEntries(
2559
+ Object.keys(artifacts.styles[mapName]).map((theme) => [
2560
+ theme,
2561
+ JSON.parse(
2562
+ String(
2563
+ immutableStyles.find(
2564
+ (file) => file.fileName === `${prefix}/styles/${mapName}/${theme}.json`
2565
+ ).source
2566
+ )
2567
+ )
2568
+ ])
2569
+ )
2570
+ )
2571
+ )
2572
+ )}
2573
+ `
2574
+ }));
2575
+ return validateArtifactFiles([
2576
+ ...stableFiles,
2577
+ ...immutableStyles,
2578
+ ...immutableFamilies,
2579
+ ...immutableAssets
2580
+ ]);
2530
2581
  }
2531
2582
  function createFontAwareManifest(manifest, styles) {
2532
2583
  const maps = Object.fromEntries(
@@ -3014,12 +3065,13 @@ function assertTileflowArtifactFileName(fileName) {
3014
3065
  assertSafeManagedFileName(fileName);
3015
3066
  const logicalName = fileName.replace(/^generations\/[a-f0-9]{64}\//, "");
3016
3067
  const styleMatch = /^styles\/([^/]+)\/([^/]+)\.json$/u.exec(logicalName);
3068
+ const familyMatch = /^families\/([^/]+)\.json$/u.exec(logicalName);
3017
3069
  const iconMatch = /^icons\/([^/]+)\/sprite(?:@2x)?\.(?:json|png)$/u.exec(logicalName);
3018
3070
  const imageMatch = /^images\/([^/]+)\/[a-f0-9]{64}\.png$/u.exec(logicalName);
3019
3071
  const modelMatch = /^models\/([^/]+)\/[a-z0-9]+(?:-[a-z0-9]+)*-[a-f0-9]{16}\.glb$/u.exec(
3020
3072
  logicalName
3021
3073
  );
3022
- if (fileName === "manifest.json" || fileName === tileflowMapBuildManifestFileName || fileName === tileflowNativeBuildRecordFileName || styleMatch && tileflowMapIdSchema.safeParse(styleMatch[1]).success && tileflowThemeNameSchema.safeParse(styleMatch[2]).success || iconMatch && tileflowMapIdSchema.safeParse(iconMatch[1]).success || imageMatch && tileflowMapIdSchema.safeParse(imageMatch[1]).success || modelMatch && tileflowMapIdSchema.safeParse(modelMatch[1]).success || /^tilesets\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}\.pmtiles$/u.test(logicalName) || /^fonts\/[a-z0-9]+(?:-[a-z0-9]+)*-[a-f0-9]{64}\.(?:otf|ttf|woff2)$/.test(logicalName) || /^fonts\/licenses\/license-[a-f0-9]{64}\.txt$/.test(logicalName)) {
3074
+ if (fileName === "manifest.json" || fileName === tileflowMapBuildManifestFileName || fileName === tileflowNativeBuildRecordFileName || styleMatch && tileflowMapIdSchema.safeParse(styleMatch[1]).success && tileflowThemeNameSchema.safeParse(styleMatch[2]).success || familyMatch && tileflowMapIdSchema.safeParse(familyMatch[1]).success || iconMatch && tileflowMapIdSchema.safeParse(iconMatch[1]).success || imageMatch && tileflowMapIdSchema.safeParse(imageMatch[1]).success || modelMatch && tileflowMapIdSchema.safeParse(modelMatch[1]).success || /^tilesets\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}\.pmtiles$/u.test(logicalName) || /^fonts\/[a-z0-9]+(?:-[a-z0-9]+)*-[a-f0-9]{64}\.(?:otf|ttf|woff2)$/.test(logicalName) || /^fonts\/licenses\/license-[a-f0-9]{64}\.txt$/.test(logicalName)) {
3023
3075
  return;
3024
3076
  }
3025
3077
  throw new Error(`Unexpected Tileflow managed artifact file name: ${fileName}`);
package/dist/preview.js CHANGED
@@ -1306,7 +1306,7 @@ function renderTileflowPreviewHtml(preview, basePath, initialStatus, isSemanticP
1306
1306
  const runtimeLayerVisibility = {};
1307
1307
  globalThis.__tileflowPreviewScene = coreScene;
1308
1308
  globalThis.__tileflowRuntimeVisibility = (id, visible) => {
1309
- if (!['tileflow-buildings-3d','tileflow-trees-3d','tileflow-street-lights'].includes(id)) return undefined;
1309
+ if (!['tileflow-buildings-scene-3d','tileflow-trees-3d','tileflow-street-lights'].includes(id)) return undefined;
1310
1310
  const previewMap = globalThis.__tileflowPreviewMap;
1311
1311
  if (typeof visible === 'boolean') {
1312
1312
  runtimeLayerVisibility[id] = visible;
@@ -1320,7 +1320,7 @@ function renderTileflowPreviewHtml(preview, basePath, initialStatus, isSemanticP
1320
1320
  globalThis.__tileflowDescribeRuntimeLayers = () => {
1321
1321
  const {buildings, vegetation, streetLights} = coreScene.scene ?? {};
1322
1322
  return {
1323
- ...(buildings ? {"tileflow-buildings-3d": {controller:"Buildings 3D", state:{visible:runtimeLayerVisibility["tileflow-buildings-3d"] !== false, shown:coreScene.buildingsShown, scale:buildings.scale}, stats:buildings.stats}} : {}),
1323
+ ...(buildings ? {"tileflow-buildings-scene-3d": {controller:"Buildings 3D", state:{visible:runtimeLayerVisibility["tileflow-buildings-scene-3d"] !== false, shown:coreScene.buildingsShown, scale:buildings.scale}, stats:buildings.stats}} : {}),
1324
1324
  ...(vegetation ? {"tileflow-trees-3d": {controller:"Vegetation", state:{visible:runtimeLayerVisibility["tileflow-trees-3d"] !== false, representation:vegetation.representation}, stats:vegetation.stats}} : {}),
1325
1325
  ...(streetLights ? {"tileflow-street-lights": {controller:"Street lights", state:{visible:runtimeLayerVisibility["tileflow-street-lights"] !== false, mounted:true}, stats:streetLights.stats}} : {})
1326
1326
  };
@@ -1376,7 +1376,7 @@ function renderTileflowPreviewHtml(preview, basePath, initialStatus, isSemanticP
1376
1376
  void (threeDimensionalEnabled ? scene.show({transition: {duration, mode: animation === "fade" ? "fade" : "grow"}}) : scene.hide(instant));
1377
1377
  }
1378
1378
  // The inspector can hide the buildings alone.
1379
- const showBuildings = threeDimensionalEnabled && runtimeLayerVisibility["tileflow-buildings-3d"] !== false;
1379
+ const showBuildings = threeDimensionalEnabled && runtimeLayerVisibility["tileflow-buildings-scene-3d"] !== false;
1380
1380
  if (scene.buildings && coreScene.buildingsShown !== showBuildings) {
1381
1381
  coreScene.buildingsShown = showBuildings;
1382
1382
  void (showBuildings ? scene.buildings.show(instant) : scene.buildings.hide(instant));
@@ -1438,6 +1438,7 @@ function renderTileflowPreviewHtml(preview, basePath, initialStatus, isSemanticP
1438
1438
  if (toggle !== "building" && toggle !== "landmark") continue;
1439
1439
  // Core's 3D buildings stand in for the compiled extrusion where the style describes them.
1440
1440
  const replaced = toggle === "building" && reads.metadata()?.["tileflow:buildings"];
1441
+ if (replaced) continue; // Core switches the native extrusion only when its scene can draw.
1441
1442
  const visibility = this.enabled && !replaced ? "visible" : "none";
1442
1443
  if (this.map.getLayoutProperty(layer.id, "visibility") !== visibility) {
1443
1444
  this.map.setLayoutProperty(layer.id, "visibility", visibility);
@@ -1636,6 +1637,7 @@ function renderTileflowPreviewHtml(preview, basePath, initialStatus, isSemanticP
1636
1637
  // Core's 3D buildings and trees stand in for compiled extrusions and flat trees.
1637
1638
  const replacedByCore =
1638
1639
  threeDimensionalToggle === "building" && styleMetadata["tileflow:buildings"];
1640
+ if (replacedByCore && !hideLayer) continue;
1639
1641
  const toggleVisibility = replacedByCore
1640
1642
  ? "none"
1641
1643
  : threeDimensionalToggle === "building" || threeDimensionalToggle === "landmark"
package/dist/server.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  parseTileflowLineBackgroundGlyphPath,
6
6
  tileflowArtifactSessionSchemaVersion,
7
7
  tileflowLineBackgroundGlyphRoute
8
- } from "./chunk-AVJMTXW5.js";
8
+ } from "./chunk-GXLY73PD.js";
9
9
  import {
10
10
  getTileflowAssetBasePath,
11
11
  getTileflowAssetFileName,
@@ -3387,6 +3387,11 @@ function createTileflowDevRequestHandler(options = {}) {
3387
3387
  }
3388
3388
  return compactJsonResponse(style);
3389
3389
  }
3390
+ if (path.startsWith("/families/")) {
3391
+ const fileName = path.slice(1);
3392
+ const asset = artifacts.files?.find((candidate) => candidate.fileName === fileName);
3393
+ return asset ? assetResponse(asset) : jsonResponse2({ error: "Unknown map family." }, 404);
3394
+ }
3390
3395
  if (path.startsWith("/icons/")) {
3391
3396
  const assetName = path.replace(/^\/+/, "");
3392
3397
  const asset = artifacts.assets.find((candidate) => candidate.fileName === assetName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/dev",
3
- "version": "0.1.0-alpha.40",
3
+ "version": "0.1.0-alpha.41",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Node development utilities for Tileflow configs and builds.",
6
6
  "type": "module",
@@ -83,7 +83,7 @@
83
83
  "dependencies": {
84
84
  "@mapbox/vector-tile": "3.0.0",
85
85
  "@maplibre/maplibre-gl-style-spec": "26.4.4",
86
- "@tileflow/core": ">=0.1.0-alpha.44 <0.1.0-beta.0",
86
+ "@tileflow/core": ">=0.1.0-alpha.45 <0.1.0-beta.0",
87
87
  "chokidar": "6.0.0",
88
88
  "fontkit": "2.0.4",
89
89
  "jiti": "^2.7.0",
@@ -95,7 +95,7 @@
95
95
  "three": "0.185.1"
96
96
  },
97
97
  "devDependencies": {
98
- "@tileflow/maps": "0.1.0-alpha.17"
98
+ "@tileflow/maps": "0.1.0-alpha.18"
99
99
  },
100
100
  "optionalDependencies": {
101
101
  "sharp": "0.35.5"