@tileflow/capture 0.1.0-alpha.25 → 0.1.0-alpha.26

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
@@ -198,7 +198,10 @@ query strings, response bodies, raw browser stacks, or DOM contents.
198
198
  New receipts use schema version 4. Version-2 and version-3 receipts remain readable as historical
199
199
  evidence, not as newly verified version-4 captures. Import `@tileflow/capture/receipt` for receipt-only
200
200
  tooling without loading the capture runtime. World selectors resolve once per capture session to
201
- an immutable release. Remote-dependent rendering is not a guarantee of globally identical pixels
201
+ an immutable release. Capture retains the complete resolved TileJSON, including its zoom range,
202
+ bounds, attribution and vector-layer metadata. Above the data's maximum zoom, MapLibre enlarges
203
+ available tiles while preserving the scene camera. Retries reuse the same frozen metadata.
204
+ Remote-dependent rendering is not a guarantee of globally identical pixels
202
205
  across platforms or future runs.
203
206
 
204
207
  Read the [capture contract](https://github.com/tileflow/tileflow-sdk/blob/main/docs/contracts/local-visual-capture.md)
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Browser } from 'playwright';
2
2
  import { T as TileflowCaptureRendererIdentity, a as TileflowCaptureReceiptV4, b as TileflowCaptureDataInput, c as TileflowCaptureWorldIdentityV3, d as TileflowCaptureReceipt } from './receipt-Q7wQ68tG.js';
3
3
  export { C as CreateTileflowCaptureReceiptInput, e as TileflowCaptureDataBindingsV2, f as TileflowCaptureDataCapabilitiesV2, g as TileflowCaptureDataIdentityV2, h as TileflowCaptureDataIdentityV3, i as TileflowCaptureDataSemanticsV2, j as TileflowCaptureDataSourceV2, k as TileflowCaptureReceiptV2, l as TileflowCaptureReceiptV3, m as TileflowCaptureVectorIdentityV3, n as TileflowCaptureVerificationV2, o as createTileflowCaptureReceipt, p as createTileflowCaptureRendererIdentity, q as parseTileflowCaptureReceipt, s as serializeTileflowCaptureReceipt, t as tileflowCaptureReceiptLimits, r as tileflowCaptureReceiptSchemaVersion, u as tileflowCaptureRuntime, v as validateTileflowCaptureReceipt } from './receipt-Q7wQ68tG.js';
4
4
  import { TileflowCaptureScene, MapLibreStyle, NormalizedTileflowCaptureScene } from '@tileflow/core';
5
- import { TileflowIconResolutionOptions, TileflowBuildArtifacts } from '@tileflow/dev/artifacts';
5
+ import { TileflowIconResolutionOptions, TileflowBuildArtifacts, TileflowBuildAsset } from '@tileflow/dev/artifacts';
6
6
 
7
7
  type TileflowBrowserInstallProgress = 'installing' | 'installed';
8
8
  type TileflowBrowserLaunchOptions = {
@@ -106,6 +106,11 @@ declare class TileflowCaptureError extends Error {
106
106
  }
107
107
  declare function captureErrorMessage(error: unknown, fallback: string): string;
108
108
 
109
+ declare const tileflowSyntheticAssetOrigin = "https://tileflow.local.invalid";
110
+ type TileflowCaptureAsset = TileflowBuildAsset & {
111
+ url?: string;
112
+ };
113
+
109
114
  declare const tileflowWorldCurrentTileJsonUrl: "https://api.tileflow.dev/tiles/world/tiles.json";
110
115
  type FetchTileJson = (input: string, init: {
111
116
  cache: 'no-store';
@@ -115,9 +120,11 @@ type FetchTileJson = (input: string, init: {
115
120
  type TileflowCaptureResolvedWorldV1 = Readonly<{
116
121
  identity: Omit<TileflowCaptureWorldIdentityV3, 'kind' | 'schema' | 'schemaVersion' | 'semantics' | 'sourceId'>;
117
122
  tileJsonUrl: string;
123
+ tileJson: string;
118
124
  tiles: readonly [string];
119
125
  }>;
120
126
  type PreparedTileflowCaptureStyle = Readonly<{
127
+ assets?: TileflowCaptureAsset[];
121
128
  data: TileflowCaptureDataInput;
122
129
  style: MapLibreStyle;
123
130
  }>;
@@ -135,8 +142,6 @@ declare function resolveTileflowCaptureWorldTileJson(tileJsonUrl: string, option
135
142
  signal?: AbortSignal;
136
143
  }): Promise<TileflowCaptureResolvedWorldV1>;
137
144
 
138
- declare const tileflowSyntheticAssetOrigin = "https://tileflow.local.invalid";
139
-
140
145
  declare function resolveTileflowApplicationUrl(input: {
141
146
  appOrigin?: string;
142
147
  appUrl?: string;
package/dist/index.js CHANGED
@@ -318,7 +318,11 @@ import { createRequire as createRequire2 } from "module";
318
318
  import { dirname as dirname2, join as join2 } from "path";
319
319
  import { getTileflowStyleFontFaces } from "@tileflow/core/runtime";
320
320
  import { assertValidTileflowStyle, TileflowStyleValidationError } from "@tileflow/dev/validation";
321
+
322
+ // src/assets.ts
321
323
  var tileflowSyntheticAssetOrigin = "https://tileflow.local.invalid";
324
+
325
+ // src/standalone.ts
322
326
  var require3 = createRequire2(import.meta.url);
323
327
  var mapLibreRuntimePaths = Object.freeze({
324
328
  css: require3.resolve("maplibre-gl/dist/maplibre-gl.css"),
@@ -396,6 +400,9 @@ async function captureStandaloneTileflowScene(input) {
396
400
  }, timeoutMs);
397
401
  timeout.unref?.();
398
402
  const assets = new Map(input.assets.map((asset) => [asset.fileName, asset]));
403
+ const frozenResources = new Map(
404
+ input.assets.filter((asset) => asset.url !== void 0).map((asset) => [asset.url, asset])
405
+ );
399
406
  const localTilesets = new Map(
400
407
  (input.localTilesets ?? []).map((tileset) => [tileset.fileName, tileset])
401
408
  );
@@ -414,6 +421,16 @@ async function captureStandaloneTileflowScene(input) {
414
421
  };
415
422
  await context.route("**/*", async (route) => {
416
423
  const url = new URL(route.request().url());
424
+ const frozenResource = frozenResources.get(url.toString());
425
+ if (frozenResource) {
426
+ await route.fulfill({
427
+ body: typeof frozenResource.source === "string" ? frozenResource.source : Buffer.from(frozenResource.source),
428
+ contentType: frozenResource.contentType,
429
+ headers: { "Access-Control-Allow-Origin": "*" },
430
+ status: 200
431
+ });
432
+ return;
433
+ }
417
434
  if (url.origin === mapLibreRuntimeUrls.origin) {
418
435
  const runtime = getMapLibreRuntimeResponse(url.pathname, input.scene.viewport);
419
436
  if (runtime) {
@@ -887,8 +904,10 @@ window.__tileflowCaptureLoad = async function(input) {
887
904
  await loadTileflowFontFaces(input.fontFaces || []);
888
905
  window.__tileflowRegisterContourProtocol?.({addProtocol: window.maplibregl.addProtocol});
889
906
  window.__tileflowRegisterPmtilesProtocol?.({addProtocol: window.maplibregl.addProtocol});
907
+ const data = input.style.metadata?.["tileflow:data"];
908
+ const worldSourceId = data?.kind === "tileflow-world" ? data.sourceId : undefined;
890
909
  window.__tileflowCaptureLoopbackSourceIds = Object.entries(input.style.sources || {})
891
- .filter(([, source]) => isLoopbackSourceUrl(source?.url))
910
+ .filter(([sourceId, source]) => sourceId !== worldSourceId && isLoopbackSourceUrl(source?.url))
892
911
  .map(([sourceId]) => sourceId);
893
912
  const map = new window.maplibregl.Map({
894
913
  attributionControl: false,
@@ -1456,6 +1475,7 @@ function compareCodeUnits2(left, right) {
1456
1475
  }
1457
1476
 
1458
1477
  // src/world.ts
1478
+ import { createHash } from "crypto";
1459
1479
  import {
1460
1480
  isTileflowWorldReleaseId,
1461
1481
  tileflowWorldTileJsonUrl
@@ -1487,13 +1507,21 @@ var TileflowCaptureWorldSession = class {
1487
1507
  sourceId: requireLiteral(metadata.sourceId, "tileflow", "sourceId")
1488
1508
  };
1489
1509
  const { tiles: _mutableTiles, url: _mutableUrl, ...sourceWithoutSelector } = source;
1510
+ const tileJsonSha256 = createHash("sha256").update(resolution.tileJson).digest("hex");
1511
+ const fileName = `capture/world/${tileJsonSha256}.json`;
1512
+ const exactSelector = new URL(resolution.tileJsonUrl);
1513
+ exactSelector.searchParams.set("worldReleaseId", resolution.identity.releaseId);
1514
+ exactSelector.searchParams.set("worldDescriptorSha256", resolution.identity.descriptorSha256);
1515
+ const url = exactSelector.toString();
1490
1516
  return {
1517
+ assets: [{ contentType: "application/json", fileName, source: resolution.tileJson, url }],
1491
1518
  data,
1492
1519
  style: {
1493
1520
  ...style,
1521
+ metadata: { ...style.metadata, "tileflow:captureWorldTileJsonSha256": tileJsonSha256 },
1494
1522
  sources: {
1495
1523
  ...style.sources,
1496
- tileflow: { ...sourceWithoutSelector, tiles: [...resolution.tiles] }
1524
+ tileflow: { ...sourceWithoutSelector, url }
1497
1525
  }
1498
1526
  }
1499
1527
  };
@@ -1580,6 +1608,7 @@ async function resolveTileflowCaptureWorldTileJson(tileJsonUrl, options = {}) {
1580
1608
  releaseId
1581
1609
  },
1582
1610
  tileJsonUrl: normalizedUrl,
1611
+ tileJson: text,
1583
1612
  tiles: [tileTemplate]
1584
1613
  };
1585
1614
  }
@@ -1839,7 +1868,7 @@ var TileflowCaptureSessionImpl = class {
1839
1868
  signal,
1840
1869
  timeoutMs: this.#options.timeoutMs
1841
1870
  }) : await captureStandaloneTileflowScene({
1842
- assets: artifacts.assets,
1871
+ assets: [...artifacts.assets, ...prepared.assets ?? []],
1843
1872
  browser,
1844
1873
  ...artifacts.localTilesets ? { localTilesets: artifacts.localTilesets } : {},
1845
1874
  scene,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/capture",
3
- "version": "0.1.0-alpha.25",
3
+ "version": "0.1.0-alpha.26",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Deterministic local visual capture and comparison for Tileflow maps.",
6
6
  "engines": {
@@ -48,7 +48,7 @@
48
48
  "access": "public"
49
49
  },
50
50
  "dependencies": {
51
- "@tileflow/core": ">=0.1.0-alpha.27 <0.1.0-beta.0",
51
+ "@tileflow/core": ">=0.1.0-alpha.28 <0.1.0-beta.0",
52
52
  "@tileflow/dev": ">=0.1.0-alpha.26 <0.1.0-beta.0",
53
53
  "maplibre-gl": "6.9.0",
54
54
  "pixelmatch": "7.2.0",
@@ -68,10 +68,10 @@
68
68
  "vite": "^8.0.16",
69
69
  "vue": "^3.5.39",
70
70
  "webpack": "5.108.3",
71
+ "@tileflow/maps": "0.1.0-alpha.5",
71
72
  "@tileflow/next": "0.1.0-alpha.24",
72
- "@tileflow/react": "0.1.0-alpha.26",
73
73
  "@tileflow/svelte": "0.1.0-alpha.25",
74
- "@tileflow/maps": "0.1.0-alpha.5",
74
+ "@tileflow/react": "0.1.0-alpha.26",
75
75
  "@tileflow/vite": "0.1.0-alpha.24",
76
76
  "@tileflow/vue": "0.1.0-alpha.25",
77
77
  "@tileflow/webpack": "0.1.0-alpha.24"