@tileflow/capture 0.1.0-alpha.27 → 0.1.0-alpha.29

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
@@ -195,9 +195,8 @@ validation, browser startup, resource loading, MapLibre readiness, and screensho
195
195
  Resource diagnostics contain safe classification and origin/status information, not credentials,
196
196
  query strings, response bodies, raw browser stacks, or DOM contents.
197
197
 
198
- New receipts use schema version 4. Version-2 and version-3 receipts remain readable as historical
199
- evidence, not as newly verified version-4 captures. Import `@tileflow/capture/receipt` for receipt-only
200
- tooling without loading the capture runtime. World selectors resolve once per capture session to
198
+ Receipts use schema version 4; parsing rejects any other version. Import
199
+ `@tileflow/capture/receipt` for receipt-only tooling without loading the capture runtime. World selectors resolve once per capture session to
201
200
  an immutable release. Capture retains the complete resolved TileJSON, including its zoom range,
202
201
  bounds, attribution and vector-layer metadata. Above the data's maximum zoom, MapLibre enlarges
203
202
  available tiles while preserving the scene camera. Retries reuse the same frozen metadata.
@@ -18,7 +18,7 @@ the platform-specific headless shell into its versioned per-user browser cache;
18
18
  distribution carries Chromium's license and credits. Chromium source and license information are
19
19
  available at https://www.chromium.org/chromium-projects/.
20
20
 
21
- ## MapLibre GL JS 6.9.0
21
+ ## MapLibre GL JS 6.13.0
22
22
 
23
23
  Copyright (c) 2023 MapLibre contributors. Licensed under BSD-3-Clause. The installed `maplibre-gl`
24
24
  package includes `LICENSE.txt`, including notices for code derived from Mapbox GL JS and other
@@ -4,7 +4,6 @@ import { types as nodeUtilTypes } from "util";
4
4
  import {
5
5
  isTileflowWorldReleaseId,
6
6
  serializeCanonicalJson,
7
- tileflowCaptureIdSchema,
8
7
  tileflowCaptureSceneLimits,
9
8
  tileflowCaptureSceneNameSchema,
10
9
  tileflowPortableIdSchema,
@@ -132,11 +131,10 @@ function parseTileflowCaptureReceipt(source) {
132
131
  function validateTileflowCaptureReceipt(value) {
133
132
  assertPlainReceiptData(value);
134
133
  const receipt = requireRecord(value, "receipt");
135
- const schemaVersion = receipt.schemaVersion;
136
- if (schemaVersion !== 2 && schemaVersion !== 3 && schemaVersion !== tileflowCaptureReceiptSchemaVersion) {
134
+ if (receipt.schemaVersion !== tileflowCaptureReceiptSchemaVersion) {
137
135
  throw invalidReceipt("The baseline receipt schema version is unsupported.");
138
136
  }
139
- const commonKeys = [
137
+ requireExactKeys(receipt, [
140
138
  "schemaVersion",
141
139
  "scene",
142
140
  "style",
@@ -144,18 +142,14 @@ function validateTileflowCaptureReceipt(value) {
144
142
  "renderer",
145
143
  "platform",
146
144
  "data",
147
- ...schemaVersion === 2 && receipt.verification === void 0 ? [] : ["verification"],
145
+ "verification",
148
146
  "networkDependent"
149
- ];
150
- requireExactKeys(receipt, commonKeys);
147
+ ]);
151
148
  const scene = requireRecord(receipt.scene, "scene");
152
- requireExactKeys(
153
- scene,
154
- schemaVersion === tileflowCaptureReceiptSchemaVersion ? ["name", "map", "theme", "target", "sha256"] : ["name", "map", "target", "sha256"]
155
- );
149
+ requireExactKeys(scene, ["name", "map", "theme", "target", "sha256"]);
156
150
  const name = requireSceneName(scene.name);
157
- const map = schemaVersion === tileflowCaptureReceiptSchemaVersion ? requirePortableIdentifier(scene.map, "scene.map") : requireIdentifier(scene.map, "scene.map");
158
- const theme = schemaVersion === tileflowCaptureReceiptSchemaVersion ? requireConcreteTheme(scene.theme) : void 0;
151
+ const map = requirePortableIdentifier(scene.map, "scene.map");
152
+ const theme = requireConcreteTheme(scene.theme);
159
153
  if (scene.target !== "map" && scene.target !== "application") {
160
154
  throw invalidReceipt("The baseline receipt has an invalid scene target.");
161
155
  }
@@ -197,13 +191,13 @@ function validateTileflowCaptureReceipt(value) {
197
191
  if (typeof receipt.networkDependent !== "boolean") {
198
192
  throw invalidReceipt("The baseline receipt has an invalid network dependency flag.");
199
193
  }
200
- const data = schemaVersion === 2 ? validateDataIdentityV2(receipt.data) : validateDataIdentityV3(receipt.data);
194
+ const data = validateDataIdentity(receipt.data);
201
195
  const normalized = {
202
- schemaVersion,
196
+ schemaVersion: tileflowCaptureReceiptSchemaVersion,
203
197
  scene: {
204
198
  name,
205
199
  map,
206
- ...theme === void 0 ? {} : { theme },
200
+ theme,
207
201
  target: scene.target,
208
202
  sha256: requireHash(scene.sha256, "scene.sha256")
209
203
  },
@@ -237,61 +231,7 @@ function validateTileflowCaptureReceipt(value) {
237
231
  assertCanonicalReceiptByteLimit(normalized);
238
232
  return normalized;
239
233
  }
240
- function validateDataIdentityV2(value) {
241
- const data = requireRecord(value, "data");
242
- if (data.url !== void 0 && data.source !== void 0) {
243
- throw invalidReceipt(
244
- "The baseline receipt data identity must not mix legacy and safe sources."
245
- );
246
- }
247
- requireExactKeys(data, [
248
- ...data.bindings === void 0 ? [] : ["bindings"],
249
- ...data.capabilities === void 0 ? [] : ["capabilities"],
250
- "kind",
251
- ...data.generation === void 0 ? [] : ["generation"],
252
- ...data.revision === void 0 ? [] : ["revision"],
253
- "schema",
254
- "schemaVersion",
255
- ...data.semantics === void 0 ? [] : ["semantics"],
256
- "sourceId",
257
- ...data.source === void 0 ? [] : ["source"],
258
- ...data.url === void 0 ? [] : ["url"]
259
- ]);
260
- if (data.kind !== "tileflow-world" && data.kind !== "vector-tiles") {
261
- throw invalidReceipt("The baseline receipt has an invalid data.kind.");
262
- }
263
- if (data.schema !== "openmaptiles" || data.sourceId !== "tileflow") {
264
- throw invalidReceipt("The baseline receipt has an unsupported data contract.");
265
- }
266
- if (data.kind === "tileflow-world") {
267
- const hasGeneration = data.generation !== void 0;
268
- const hasLegacyRevision = data.revision !== void 0;
269
- if (hasGeneration === hasLegacyRevision) {
270
- throw invalidReceipt(
271
- "The baseline receipt must identify World by one generation or one legacy revision."
272
- );
273
- }
274
- } else if (data.generation !== void 0) {
275
- throw invalidReceipt("The baseline receipt has an invalid data.generation.");
276
- }
277
- const bindings = data.bindings === void 0 ? void 0 : validateDataBindings(data.bindings, "data.bindings");
278
- const capabilities = data.capabilities === void 0 ? void 0 : validateDataCapabilities(data.capabilities, "data.capabilities");
279
- const source = data.source === void 0 ? data.url === void 0 ? void 0 : fingerprintLegacyDataUrl(data.url) : validateDataSource(data.source, "data.source");
280
- const semantics = data.semantics === void 0 ? void 0 : validateDataSemantics(data.semantics, "data.semantics");
281
- return {
282
- ...bindings ? { bindings } : {},
283
- ...capabilities ? { capabilities } : {},
284
- ...data.generation === void 0 ? {} : { generation: requireWorldGeneration(data.generation) },
285
- kind: data.kind,
286
- ...data.revision === void 0 ? {} : { revision: requireSourceRevision(data.revision) },
287
- schema: data.schema,
288
- schemaVersion: requirePositiveInteger(data.schemaVersion, "data.schemaVersion"),
289
- ...semantics ? { semantics } : {},
290
- sourceId: data.sourceId,
291
- ...source ? { source } : {}
292
- };
293
- }
294
- function validateDataIdentityV3(value) {
234
+ function validateDataIdentity(value) {
295
235
  const data = requireRecord(value, "data");
296
236
  if (data.kind === "tileflow-world") {
297
237
  requireExactKeys(data, [
@@ -304,13 +244,12 @@ function validateDataIdentityV3(value) {
304
244
  "releaseId",
305
245
  "schema",
306
246
  "schemaVersion",
307
- ...data.semantics === void 0 ? [] : ["semantics"],
247
+ "semantics",
308
248
  "sourceId"
309
249
  ]);
310
250
  if (data.product !== "world-v1" || data.schema !== "openmaptiles" || data.sourceId !== "tileflow") {
311
251
  throw invalidReceipt("The baseline receipt has an unsupported World data contract.");
312
252
  }
313
- const semantics2 = data.semantics === void 0 ? void 0 : validateDataSemantics(data.semantics, "data.semantics");
314
253
  return {
315
254
  archiveSha256: requireHash(data.archiveSha256, "data.archiveSha256"),
316
255
  contractSha256: requireHash(data.contractSha256, "data.contractSha256"),
@@ -321,7 +260,7 @@ function validateDataIdentityV3(value) {
321
260
  releaseId: requireWorldReleaseId(data.releaseId),
322
261
  schema: "openmaptiles",
323
262
  schemaVersion: requirePositiveInteger(data.schemaVersion, "data.schemaVersion"),
324
- ...semantics2 ? { semantics: semantics2 } : {},
263
+ semantics: validateDataSemantics(data.semantics, "data.semantics"),
325
264
  sourceId: "tileflow"
326
265
  };
327
266
  }
@@ -329,41 +268,35 @@ function validateDataIdentityV3(value) {
329
268
  throw invalidReceipt("The baseline receipt has an invalid data.kind.");
330
269
  }
331
270
  requireExactKeys(data, [
332
- ...data.bindings === void 0 ? [] : ["bindings"],
333
- ...data.capabilities === void 0 ? [] : ["capabilities"],
271
+ "bindings",
272
+ "capabilities",
334
273
  "kind",
335
274
  ...data.revision === void 0 ? [] : ["revision"],
336
275
  "schema",
337
276
  "schemaVersion",
338
- ...data.semantics === void 0 ? [] : ["semantics"],
339
- "sourceId",
340
- ...data.source === void 0 ? [] : ["source"]
277
+ "semantics",
278
+ "source",
279
+ "sourceId"
341
280
  ]);
342
281
  if (data.schema !== "openmaptiles" || data.sourceId !== "tileflow") {
343
282
  throw invalidReceipt("The baseline receipt has an unsupported data contract.");
344
283
  }
345
- const bindings = data.bindings === void 0 ? void 0 : validateDataBindings(data.bindings, "data.bindings");
346
- const capabilities = data.capabilities === void 0 ? void 0 : validateDataCapabilities(data.capabilities, "data.capabilities");
347
- const semantics = data.semantics === void 0 ? void 0 : validateDataSemantics(data.semantics, "data.semantics");
348
284
  return {
349
- ...bindings ? { bindings } : {},
350
- ...capabilities ? { capabilities } : {},
285
+ bindings: validateDataBindings(data.bindings, "data.bindings"),
286
+ capabilities: validateDataCapabilities(data.capabilities, "data.capabilities"),
351
287
  kind: "vector-tiles",
352
288
  ...data.revision === void 0 ? {} : { revision: requireSourceRevision(data.revision) },
353
289
  schema: "openmaptiles",
354
290
  schemaVersion: requirePositiveInteger(data.schemaVersion, "data.schemaVersion"),
355
- ...semantics ? { semantics } : {},
356
- sourceId: "tileflow",
357
- ...data.source === void 0 ? {} : { source: validateDataSource(data.source, "data.source") }
291
+ semantics: validateDataSemantics(data.semantics, "data.semantics"),
292
+ source: validateDataSource(data.source, "data.source"),
293
+ sourceId: "tileflow"
358
294
  };
359
295
  }
360
296
  function normalizeCaptureDataInput(input) {
361
297
  if (input.kind === "tileflow-world") return input;
362
298
  const { url, ...identity } = input;
363
- return {
364
- ...identity,
365
- ...url === void 0 ? {} : { source: fingerprintLegacyDataUrl(url) }
366
- };
299
+ return { ...identity, source: fingerprintDataUrl(url) };
367
300
  }
368
301
  function validateDataSemantics(value, field) {
369
302
  const semantics = requireRecord(value, field);
@@ -410,16 +343,18 @@ function validateDataCapabilities(value, field) {
410
343
  const capabilities = requireRecord(value, field);
411
344
  requireExactKeys(capabilities, [
412
345
  "businessCorridor",
413
- ...capabilities.bathymetry === void 0 ? [] : ["bathymetry"],
346
+ "bathymetry",
347
+ "canopy",
414
348
  "globalLandcover",
415
349
  "tree"
416
350
  ]);
417
- if (typeof capabilities.businessCorridor !== "boolean" || capabilities.bathymetry !== void 0 && typeof capabilities.bathymetry !== "boolean" || typeof capabilities.globalLandcover !== "boolean" || typeof capabilities.tree !== "boolean") {
351
+ if (typeof capabilities.businessCorridor !== "boolean" || typeof capabilities.bathymetry !== "boolean" || typeof capabilities.canopy !== "boolean" || typeof capabilities.globalLandcover !== "boolean" || typeof capabilities.tree !== "boolean") {
418
352
  throw invalidReceipt(`The baseline receipt has an invalid ${field} object.`);
419
353
  }
420
354
  return {
421
355
  businessCorridor: capabilities.businessCorridor,
422
- ...capabilities.bathymetry === void 0 ? {} : { bathymetry: capabilities.bathymetry },
356
+ bathymetry: capabilities.bathymetry,
357
+ canopy: capabilities.canopy,
423
358
  globalLandcover: capabilities.globalLandcover,
424
359
  tree: capabilities.tree
425
360
  };
@@ -434,7 +369,6 @@ function validateDataSource(value, field) {
434
369
  }
435
370
  function validateVerification(value, target) {
436
371
  const expected = verificationForTarget(target);
437
- if (value === void 0) return expected;
438
372
  const verification = requireRecord(value, "verification");
439
373
  requireExactKeys(verification, ["data", "style"]);
440
374
  if (verification.data !== expected.data || verification.style !== expected.style) {
@@ -513,11 +447,6 @@ function requireExactKeys(value, expected) {
513
447
  throw invalidReceipt("The baseline receipt contains missing or unsupported fields.");
514
448
  }
515
449
  }
516
- function requireIdentifier(value, field) {
517
- const result = tileflowCaptureIdSchema.safeParse(value);
518
- if (!result.success) throw invalidReceipt(`The baseline receipt has an invalid ${field}.`);
519
- return result.data;
520
- }
521
450
  function requirePortableIdentifier(value, field) {
522
451
  const result = tileflowPortableIdSchema.safeParse(value);
523
452
  if (!result.success) throw invalidReceipt(`The baseline receipt has an invalid ${field}.`);
@@ -566,7 +495,7 @@ function requireSourceRevision(value) {
566
495
  }
567
496
  return value;
568
497
  }
569
- function fingerprintLegacyDataUrl(value) {
498
+ function fingerprintDataUrl(value) {
570
499
  if (typeof value !== "string" || value.length < 1 || value.length > 2048) {
571
500
  throw invalidReceipt("The baseline receipt has an invalid data.url.");
572
501
  }
@@ -594,12 +523,6 @@ function isLoopbackHostname(value) {
594
523
  const hostname = value.toLowerCase().replace(/^\[|\]$/g, "");
595
524
  return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1";
596
525
  }
597
- function requireWorldGeneration(value) {
598
- if (value !== "v1") {
599
- throw invalidReceipt("The baseline receipt has an invalid data.generation.");
600
- }
601
- return value;
602
- }
603
526
  function requireWorldReleaseId(value) {
604
527
  if (!isTileflowWorldReleaseId(value)) {
605
528
  throw invalidReceipt("The baseline receipt has an invalid data.releaseId.");
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Browser } from 'playwright';
2
- import { T as TileflowCaptureRendererIdentity, a as TileflowCaptureReceiptV4, b as TileflowCaptureDataInput, c as TileflowCaptureWorldIdentityV3, d as TileflowCaptureReceipt } from './receipt-Q7wQ68tG.js';
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';
2
+ import { T as TileflowCaptureRendererIdentity, a as TileflowCaptureReceipt, b as TileflowCaptureDataInput, c as TileflowCaptureWorldIdentity } from './receipt-DhFOATRO.js';
3
+ export { C as CreateTileflowCaptureReceiptInput, d as TileflowCaptureDataBindings, e as TileflowCaptureDataCapabilities, f as TileflowCaptureDataIdentity, g as TileflowCaptureDataSemantics, h as TileflowCaptureDataSource, i as TileflowCaptureVectorIdentity, j as TileflowCaptureVerification, k as createTileflowCaptureReceipt, l as createTileflowCaptureRendererIdentity, p as parseTileflowCaptureReceipt, s as serializeTileflowCaptureReceipt, t as tileflowCaptureReceiptLimits, m as tileflowCaptureReceiptSchemaVersion, n as tileflowCaptureRuntime, v as validateTileflowCaptureReceipt } from './receipt-DhFOATRO.js';
4
4
  import { TileflowCaptureScene, MapLibreStyle, NormalizedTileflowCaptureScene } from '@tileflow/core';
5
5
  import { TileflowIconResolutionOptions, TileflowBuildArtifacts, TileflowBuildAsset } from '@tileflow/dev/artifacts';
6
6
 
@@ -61,7 +61,7 @@ type TileflowCapture = {
61
61
  networkDependent: boolean;
62
62
  renderer: TileflowCaptureRendererIdentity;
63
63
  /** Newly captured evidence is always the concrete-theme receipt contract. */
64
- receipt: TileflowCaptureReceiptV4;
64
+ receipt: TileflowCaptureReceipt;
65
65
  warnings: string[];
66
66
  };
67
67
  type TileflowCaptureResult = {
@@ -118,7 +118,7 @@ type FetchTileJson = (input: string, init: {
118
118
  signal?: AbortSignal;
119
119
  }) => Promise<Pick<Response, 'ok' | 'status' | 'text'>>;
120
120
  type TileflowCaptureResolvedWorldV1 = Readonly<{
121
- identity: Omit<TileflowCaptureWorldIdentityV3, 'kind' | 'schema' | 'schemaVersion' | 'semantics' | 'sourceId'>;
121
+ identity: Omit<TileflowCaptureWorldIdentity, 'kind' | 'schema' | 'schemaVersion' | 'semantics' | 'sourceId'>;
122
122
  tileJsonUrl: string;
123
123
  tileJson: string;
124
124
  tiles: readonly [string];
@@ -321,13 +321,13 @@ type TileflowVisualReviewFrameIdentity = {
321
321
  };
322
322
  };
323
323
  type TileflowVisualReviewSide = {
324
- scene: TileflowCaptureReceiptV4['scene'];
325
- style: TileflowCaptureReceiptV4['style'];
324
+ scene: TileflowCaptureReceipt['scene'];
325
+ style: TileflowCaptureReceipt['style'];
326
326
  frame: TileflowVisualReviewFrameIdentity;
327
327
  image: TileflowVisualImageIdentity;
328
- runtime: Pick<TileflowCaptureReceiptV4, 'renderer' | 'platform'>;
329
- data: TileflowCaptureReceiptV4['data'];
330
- verification: TileflowCaptureReceiptV4['verification'];
328
+ runtime: Pick<TileflowCaptureReceipt, 'renderer' | 'platform'>;
329
+ data: TileflowCaptureReceipt['data'];
330
+ verification: TileflowCaptureReceipt['verification'];
331
331
  palette: TileflowVisualPaletteColor[];
332
332
  };
333
333
  type TileflowVisualReviewComparison = {
@@ -365,4 +365,4 @@ declare const tileflowVisualReviewLimits: Readonly<{
365
365
  maximumAggregatePngBytes: number;
366
366
  }>;
367
367
 
368
- export { type CreateTileflowCaptureSessionOptions, type PreparedTileflowCaptureStyle, type TileflowBrowserInstallProgress, type TileflowBrowserLaunchOptions, type TileflowCapture, TileflowCaptureBrowserManager, TileflowCaptureDataInput, type TileflowCaptureDiagnostic, TileflowCaptureError, type TileflowCaptureErrorCode, type TileflowCaptureErrorDetails, type TileflowCaptureOptions, type TileflowCapturePhase, TileflowCaptureReceipt, TileflowCaptureReceiptV4, TileflowCaptureRendererIdentity, type TileflowCaptureResolvedWorldV1, type TileflowCaptureResourceDiagnostic, type TileflowCaptureResourceKind, type TileflowCaptureResult, type TileflowCaptureSession, TileflowCaptureWorldIdentityV3, TileflowCaptureWorldSession, type TileflowVisualAppearanceDelta, type TileflowVisualAppearanceProfile, type TileflowVisualAppearanceStatistics, type TileflowVisualBaseline, type TileflowVisualComparison, type TileflowVisualComparisonDocument, type TileflowVisualComparisonStatus, type TileflowVisualImageIdentity, type TileflowVisualPaletteColor, type TileflowVisualPixelMetric, type TileflowVisualReferenceAnalysis, type TileflowVisualReferenceAnalysisDocument, type TileflowVisualReferenceAnalysisOptions, type TileflowVisualReferenceAppearance, type TileflowVisualRegion, type TileflowVisualReviewAppearance, type TileflowVisualReviewCapture, type TileflowVisualReviewComparison, type TileflowVisualReviewDefinition, type TileflowVisualReviewDocument, TileflowVisualReviewError, type TileflowVisualReviewFrameIdentity, type TileflowVisualReviewOptions, type TileflowVisualReviewSide, type TileflowVisualReviewStatus, type TileflowVisualRuntimeIdentity, type TileflowVisualSceneIdentity, analyzeTileflowCaptureReference, captureErrorMessage, captureTileflowScenes, compareTileflowCaptureToBaseline, compareTileflowCapturesForReview, createTileflowCaptureBrowserEnvironment, createTileflowCaptureSession, createTileflowVisualComparisonDocument, createTileflowVisualReferenceAnalysisDocument, createTileflowVisualReviewDocument, launchTileflowCaptureBrowser, resolveTileflowApplicationUrl, resolveTileflowCaptureWorldTileJson, serializeTileflowVisualComparison, setupTileflowCaptureBrowser, tileflowCaptureResultSchemaVersion, tileflowSyntheticAssetOrigin, tileflowVisualArtifactLimits, tileflowVisualComparisonSchemaVersion, tileflowVisualEdgeThreshold, tileflowVisualPerceptualThreshold, tileflowVisualReviewLimits, tileflowVisualReviewSchemaVersion, tileflowWorldCurrentTileJsonUrl, validateTileflowVisualReferencePng };
368
+ export { type CreateTileflowCaptureSessionOptions, type PreparedTileflowCaptureStyle, type TileflowBrowserInstallProgress, type TileflowBrowserLaunchOptions, type TileflowCapture, TileflowCaptureBrowserManager, TileflowCaptureDataInput, type TileflowCaptureDiagnostic, TileflowCaptureError, type TileflowCaptureErrorCode, type TileflowCaptureErrorDetails, type TileflowCaptureOptions, type TileflowCapturePhase, TileflowCaptureReceipt, TileflowCaptureRendererIdentity, type TileflowCaptureResolvedWorldV1, type TileflowCaptureResourceDiagnostic, type TileflowCaptureResourceKind, type TileflowCaptureResult, type TileflowCaptureSession, TileflowCaptureWorldIdentity, TileflowCaptureWorldSession, type TileflowVisualAppearanceDelta, type TileflowVisualAppearanceProfile, type TileflowVisualAppearanceStatistics, type TileflowVisualBaseline, type TileflowVisualComparison, type TileflowVisualComparisonDocument, type TileflowVisualComparisonStatus, type TileflowVisualImageIdentity, type TileflowVisualPaletteColor, type TileflowVisualPixelMetric, type TileflowVisualReferenceAnalysis, type TileflowVisualReferenceAnalysisDocument, type TileflowVisualReferenceAnalysisOptions, type TileflowVisualReferenceAppearance, type TileflowVisualRegion, type TileflowVisualReviewAppearance, type TileflowVisualReviewCapture, type TileflowVisualReviewComparison, type TileflowVisualReviewDefinition, type TileflowVisualReviewDocument, TileflowVisualReviewError, type TileflowVisualReviewFrameIdentity, type TileflowVisualReviewOptions, type TileflowVisualReviewSide, type TileflowVisualReviewStatus, type TileflowVisualRuntimeIdentity, type TileflowVisualSceneIdentity, analyzeTileflowCaptureReference, captureErrorMessage, captureTileflowScenes, compareTileflowCaptureToBaseline, compareTileflowCapturesForReview, createTileflowCaptureBrowserEnvironment, createTileflowCaptureSession, createTileflowVisualComparisonDocument, createTileflowVisualReferenceAnalysisDocument, createTileflowVisualReviewDocument, launchTileflowCaptureBrowser, resolveTileflowApplicationUrl, resolveTileflowCaptureWorldTileJson, serializeTileflowVisualComparison, setupTileflowCaptureBrowser, tileflowCaptureResultSchemaVersion, tileflowSyntheticAssetOrigin, tileflowVisualArtifactLimits, tileflowVisualComparisonSchemaVersion, tileflowVisualEdgeThreshold, tileflowVisualPerceptualThreshold, tileflowVisualReviewLimits, tileflowVisualReviewSchemaVersion, tileflowWorldCurrentTileJsonUrl, validateTileflowVisualReferencePng };
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  tileflowCaptureReceiptLimits,
8
8
  tileflowCaptureReceiptSchemaVersion,
9
9
  validateTileflowCaptureReceipt
10
- } from "./chunk-BSTB4FN6.js";
10
+ } from "./chunk-VNDAYGXY.js";
11
11
 
12
12
  // src/browser.ts
13
13
  import { spawn } from "child_process";
@@ -317,6 +317,11 @@ import { open } from "fs/promises";
317
317
  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
+ import {
321
+ createTileflowLineBackgroundGlyphResponder,
322
+ parseTileflowLineBackgroundGlyphPath,
323
+ tileflowLineBackgroundGlyphRoute
324
+ } from "@tileflow/dev/artifacts";
320
325
  import { assertValidTileflowStyle, TileflowStyleValidationError } from "@tileflow/dev/validation";
321
326
 
322
327
  // src/assets.ts
@@ -327,7 +332,6 @@ var require3 = createRequire2(import.meta.url);
327
332
  var mapLibreRuntimePaths = Object.freeze({
328
333
  css: require3.resolve("maplibre-gl/dist/maplibre-gl.css"),
329
334
  main: require3.resolve("maplibre-gl/dist/maplibre-gl.mjs"),
330
- shared: require3.resolve("maplibre-gl/dist/maplibre-gl-shared.mjs"),
331
335
  worker: require3.resolve("maplibre-gl/dist/maplibre-gl-worker.mjs")
332
336
  });
333
337
  var tileflowCorePackagePath = require3.resolve("@tileflow/core/package.json");
@@ -409,6 +413,7 @@ async function captureStandaloneTileflowScene(input) {
409
413
  );
410
414
  const fontFaces = getTileflowStyleFontFaces(input.style);
411
415
  const remoteOrigins = /* @__PURE__ */ new Set();
416
+ let lineBackgroundGlyphs;
412
417
  let syntheticAssetFailure;
413
418
  const resourceFailures = [];
414
419
  let pageFailed = false;
@@ -439,6 +444,35 @@ async function captureStandaloneTileflowScene(input) {
439
444
  return;
440
445
  }
441
446
  }
447
+ if (url.origin === tileflowSyntheticAssetOrigin && url.pathname.startsWith(`/${tileflowLineBackgroundGlyphRoute}/`)) {
448
+ const glyphRequest = parseTileflowLineBackgroundGlyphPath(url.pathname);
449
+ const upstream = glyphRequest ? input.lineBackgroundGlyphs?.[glyphRequest.mapName] : void 0;
450
+ if (!glyphRequest || !upstream || url.search !== "") {
451
+ syntheticAssetFailure = url.pathname.slice(1) || "unknown";
452
+ await route.abort("blockedbyclient");
453
+ return;
454
+ }
455
+ const provider = new URL(
456
+ upstream.replace("{fontstack}", "stack").replace("{range}", "0-255")
457
+ );
458
+ if (!isLoopbackUrl(provider)) remoteOrigins.add(provider.origin);
459
+ lineBackgroundGlyphs ??= createTileflowLineBackgroundGlyphResponder({
460
+ cwd: input.glyphCacheDirectory ?? process.cwd()
461
+ });
462
+ const response = await lineBackgroundGlyphs(
463
+ upstream,
464
+ glyphRequest.fontStack,
465
+ glyphRequest.range
466
+ );
467
+ if (response.status !== 200) recordResourceFailure(url.toString(), response.status);
468
+ await route.fulfill({
469
+ body: Buffer.from(await response.arrayBuffer()),
470
+ contentType: response.headers.get("content-type") ?? "application/x-protobuf",
471
+ headers: { "Access-Control-Allow-Origin": "*" },
472
+ status: response.status
473
+ });
474
+ return;
475
+ }
442
476
  if (url.origin === tileflowSyntheticAssetOrigin) {
443
477
  const fileName = decodeURIComponent(url.pathname.slice(1));
444
478
  const localTileset = url.search === "" ? localTilesets.get(fileName) : void 0;
@@ -609,7 +643,6 @@ function createMapLibreRuntimeUrls(origin) {
609
643
  document: `${origin}/__runtime/document.html`,
610
644
  main: `${origin}/__runtime/maplibre-gl.mjs`,
611
645
  origin,
612
- shared: `${origin}/__runtime/maplibre-gl-shared.mjs`,
613
646
  worker: `${origin}/__runtime/maplibre-gl-worker.mjs`
614
647
  });
615
648
  }
@@ -667,7 +700,7 @@ function getMapLibreRuntimeResponse(pathname, viewport) {
667
700
  status: 200
668
701
  };
669
702
  }
670
- const asset = pathname === "/__runtime/maplibre-gl.mjs" ? mapLibreRuntimePaths.main : pathname === "/__runtime/maplibre-gl-shared.mjs" ? mapLibreRuntimePaths.shared : pathname === "/__runtime/maplibre-gl-worker.mjs" ? mapLibreRuntimePaths.worker : pathname === "/__runtime/maplibre-gl.css" ? mapLibreRuntimePaths.css : void 0;
703
+ const asset = pathname === "/__runtime/maplibre-gl.mjs" ? mapLibreRuntimePaths.main : pathname === "/__runtime/maplibre-gl-worker.mjs" ? mapLibreRuntimePaths.worker : pathname === "/__runtime/maplibre-gl.css" ? mapLibreRuntimePaths.css : void 0;
671
704
  if (!asset) return void 0;
672
705
  return {
673
706
  body: readFileSync2(asset, "utf8"),
@@ -1499,13 +1532,12 @@ var TileflowCaptureWorldSession = class {
1499
1532
  const source = requirePrimaryVectorSource(style);
1500
1533
  const lookupUrl = worldTileJsonLookupUrl(source, metadata);
1501
1534
  const resolution = await this.#resolveOne(lookupUrl, signal);
1502
- const semantics = validateSemantics(metadata.semantics);
1503
1535
  const data = {
1504
1536
  ...resolution.identity,
1505
1537
  kind: "tileflow-world",
1506
1538
  schema: requireLiteral(metadata.schema, "openmaptiles", "schema"),
1507
1539
  schemaVersion: requirePositiveInteger(metadata.schemaVersion, "schemaVersion"),
1508
- ...semantics ? { semantics } : {},
1540
+ semantics: validateSemantics(metadata.semantics),
1509
1541
  sourceId: requireLiteral(metadata.sourceId, "tileflow", "sourceId")
1510
1542
  };
1511
1543
  const { tiles: _mutableTiles, url: _mutableUrl, ...sourceWithoutSelector } = source;
@@ -1691,7 +1723,6 @@ function validateExactTileTemplate(value, releaseId, descriptorSha256) {
1691
1723
  return value;
1692
1724
  }
1693
1725
  function validateSemantics(value) {
1694
- if (value === void 0) return void 0;
1695
1726
  const semantics = requireRecord(value, "data semantics");
1696
1727
  requireExactKeys(semantics, ["parkLayer"]);
1697
1728
  if (semantics.parkLayer !== "mixed" && semantics.parkLayer !== "protected-only") {
@@ -1873,6 +1904,10 @@ var TileflowCaptureSessionImpl = class {
1873
1904
  assets: [...artifacts.assets, ...prepared.assets ?? []],
1874
1905
  browser,
1875
1906
  ...artifacts.localTilesets ? { localTilesets: artifacts.localTilesets } : {},
1907
+ ...artifacts.lineBackgroundGlyphs ? {
1908
+ glyphCacheDirectory: resolve(this.#options.cwd ?? process.cwd()),
1909
+ lineBackgroundGlyphs: artifacts.lineBackgroundGlyphs
1910
+ } : {},
1876
1911
  scene,
1877
1912
  signal,
1878
1913
  style,
@@ -2151,9 +2186,6 @@ function validateTileflowVisualReferencePng(png) {
2151
2186
  async function analyzeTileflowCaptureReference(actualCapture, referencePng, options = {}) {
2152
2187
  const requestedRegion = snapshotTileflowVisualReferenceAnalysisOptions(options);
2153
2188
  const receipt = validateTileflowCaptureReceipt(actualCapture.receipt);
2154
- if (receipt.schemaVersion !== 4) {
2155
- throw invalidBaseline("Visual reference analysis requires a schema-v4 capture receipt.");
2156
- }
2157
2189
  const actualImage = await validatePngAgainstReceipt(actualCapture.png, receipt, "actual");
2158
2190
  const referenceImage = decodePng(referencePng, "reference");
2159
2191
  const dimensionsMatch = referenceImage.width === actualImage.width && referenceImage.height === actualImage.height;
@@ -2726,45 +2758,7 @@ function pixelMetric(changedPixels, totalPixels) {
2726
2758
  return { changedPixels, totalPixels, ratio: changedPixels / totalPixels };
2727
2759
  }
2728
2760
  function sameSceneIdentity(baseline, actual) {
2729
- return baseline.scene.name === actual.scene.name && baseline.scene.map === actual.scene.map && baseline.scene.target === actual.scene.target && baseline.scene.sha256 === actual.scene.sha256 && sameDataIdentity(baseline.data, actual.data);
2730
- }
2731
- function sameDataIdentity(baseline, actual) {
2732
- if (baseline.kind !== actual.kind || baseline.schema !== actual.schema || baseline.schemaVersion !== actual.schemaVersion || baseline.sourceId !== actual.sourceId) {
2733
- return false;
2734
- }
2735
- const baselineExactWorld = exactWorldIdentity(baseline);
2736
- const actualExactWorld = exactWorldIdentity(actual);
2737
- if (baselineExactWorld || actualExactWorld) {
2738
- if (!baselineExactWorld || !actualExactWorld) return false;
2739
- return baselineExactWorld.product === actualExactWorld.product && baselineExactWorld.releaseId === actualExactWorld.releaseId && baselineExactWorld.descriptorSha256 === actualExactWorld.descriptorSha256 && baselineExactWorld.archiveSha256 === actualExactWorld.archiveSha256 && baselineExactWorld.dataContractSha256 === actualExactWorld.dataContractSha256 && baselineExactWorld.contractSha256 === actualExactWorld.contractSha256 && sameOptionalSemantics(baselineExactWorld.semantics, actualExactWorld.semantics);
2740
- }
2741
- const baselineLegacy = baseline;
2742
- const actualLegacy = actual;
2743
- if (baselineLegacy.generation !== actualLegacy.generation || baselineLegacy.revision !== actualLegacy.revision || !sameOptionalSemantics(baselineLegacy.semantics, actualLegacy.semantics)) {
2744
- return false;
2745
- }
2746
- if (baselineLegacy.source && (!actualLegacy.source || baselineLegacy.source.kind !== actualLegacy.source.kind || baselineLegacy.source.sha256 !== actualLegacy.source.sha256)) {
2747
- return false;
2748
- }
2749
- if (baselineLegacy.capabilities && (!actualLegacy.capabilities || !isRecordSubset(baselineLegacy.capabilities, actualLegacy.capabilities))) {
2750
- return false;
2751
- }
2752
- if (baselineLegacy.bindings) {
2753
- if (!actualLegacy.bindings) return false;
2754
- if (!isRecordSubset(baselineLegacy.bindings.fields, actualLegacy.bindings.fields) || !isRecordSubset(baselineLegacy.bindings.layers, actualLegacy.bindings.layers)) {
2755
- return false;
2756
- }
2757
- }
2758
- return true;
2759
- }
2760
- function exactWorldIdentity(value) {
2761
- return value.kind === "tileflow-world" && "product" in value ? value : void 0;
2762
- }
2763
- function sameOptionalSemantics(baseline, actual) {
2764
- return baseline === void 0 || baseline.parkLayer === actual?.parkLayer;
2765
- }
2766
- function isRecordSubset(baseline, actual) {
2767
- return Object.entries(baseline).every(([key, value]) => actual[key] === value);
2761
+ return baseline.scene.name === actual.scene.name && baseline.scene.map === actual.scene.map && baseline.scene.theme === actual.scene.theme && baseline.scene.target === actual.scene.target && baseline.scene.sha256 === actual.scene.sha256 && serializeCanonicalJson2(baseline.data) === serializeCanonicalJson2(actual.data);
2768
2762
  }
2769
2763
  function sameRuntimeIdentity(baseline, actual) {
2770
2764
  return baseline.renderer.tileflow === actual.renderer.tileflow && baseline.renderer.maplibre === actual.renderer.maplibre && baseline.renderer.playwright === actual.renderer.playwright && baseline.renderer.chromiumRevision === actual.renderer.chromiumRevision && baseline.renderer.chromiumVersion === actual.renderer.chromiumVersion && baseline.platform.os === actual.platform.os && baseline.platform.architecture === actual.platform.architecture;
@@ -3103,9 +3097,6 @@ async function validateReviewCapture(input, role) {
3103
3097
  throw invalidReview(`The ${role} capture receipt is invalid.`, error);
3104
3098
  }
3105
3099
  const receipt = parsedReceipt;
3106
- if (receipt.schemaVersion !== 4) {
3107
- throw invalidReview(`The ${role} review capture requires a schema-v4 receipt.`);
3108
- }
3109
3100
  if (definition.map !== receipt.scene.map || definition.theme !== receipt.scene.theme || definition.target.kind !== receipt.scene.target) {
3110
3101
  throw invalidReview(`The ${role} review identity does not match its capture receipt.`);
3111
3102
  }
@@ -0,0 +1,131 @@
1
+ import { Browser } from 'playwright';
2
+
3
+ type TileflowCaptureRendererIdentity = {
4
+ tileflow: string;
5
+ maplibre: string;
6
+ playwright: string;
7
+ chromiumRevision: string;
8
+ chromiumVersion: string;
9
+ };
10
+ declare const tileflowCaptureRuntime: Readonly<{
11
+ tileflow: string;
12
+ maplibre: string;
13
+ playwright: string;
14
+ chromiumRevision: string;
15
+ chromiumVersion: string;
16
+ }>;
17
+ declare function createTileflowCaptureRendererIdentity(browser?: Pick<Browser, 'version'>): TileflowCaptureRendererIdentity;
18
+
19
+ declare const tileflowCaptureReceiptSchemaVersion: 4;
20
+ declare const tileflowCaptureReceiptLimits: Readonly<{
21
+ maximumBytes: number;
22
+ }>;
23
+ type TileflowCaptureDataBindings = {
24
+ fields: Record<string, string>;
25
+ layers: Record<string, string>;
26
+ };
27
+ type TileflowCaptureDataCapabilities = {
28
+ businessCorridor: boolean;
29
+ bathymetry: boolean;
30
+ canopy: boolean;
31
+ globalLandcover: boolean;
32
+ tree: boolean;
33
+ };
34
+ type TileflowCaptureDataSource = {
35
+ kind: 'loopback' | 'opaque' | 'remote' | 'root-relative';
36
+ /** SHA-256 of a credential-free, query-free endpoint identity. */
37
+ sha256: string;
38
+ };
39
+ type TileflowCaptureDataSemantics = {
40
+ parkLayer: 'mixed' | 'protected-only';
41
+ };
42
+ /** Exact Tileflow World release identity. */
43
+ type TileflowCaptureWorldIdentity = {
44
+ archiveSha256: string;
45
+ contractSha256: string;
46
+ dataContractSha256: string;
47
+ descriptorSha256: string;
48
+ kind: 'tileflow-world';
49
+ product: 'world-v1';
50
+ releaseId: string;
51
+ schema: 'openmaptiles';
52
+ schemaVersion: number;
53
+ semantics: TileflowCaptureDataSemantics;
54
+ sourceId: 'tileflow';
55
+ };
56
+ /** External vector-tile identity. Its endpoint is recorded only as a safe fingerprint. */
57
+ type TileflowCaptureVectorIdentity = {
58
+ bindings: TileflowCaptureDataBindings;
59
+ capabilities: TileflowCaptureDataCapabilities;
60
+ kind: 'vector-tiles';
61
+ /** Explicit revision supplied by the data configuration. */
62
+ revision?: string;
63
+ schema: 'openmaptiles';
64
+ schemaVersion: number;
65
+ semantics: TileflowCaptureDataSemantics;
66
+ source: TileflowCaptureDataSource;
67
+ sourceId: 'tileflow';
68
+ };
69
+ /** Durable data identity owned by capture rather than the live core authoring API. */
70
+ type TileflowCaptureDataIdentity = TileflowCaptureVectorIdentity | TileflowCaptureWorldIdentity;
71
+ /**
72
+ * Data identity accepted by `createTileflowCaptureReceipt`. A vector `url` is transient input:
73
+ * it is converted to `source` and never returned or serialized.
74
+ */
75
+ type TileflowCaptureDataInput = (Omit<TileflowCaptureVectorIdentity, 'source'> & {
76
+ url: string;
77
+ }) | TileflowCaptureWorldIdentity;
78
+ type TileflowCaptureVerification = {
79
+ data: 'expected-unverified' | 'rendered';
80
+ style: 'expected-unverified' | 'rendered';
81
+ };
82
+ type TileflowCaptureReceipt = {
83
+ schemaVersion: typeof tileflowCaptureReceiptSchemaVersion;
84
+ scene: {
85
+ name: string;
86
+ map: string;
87
+ theme: string;
88
+ target: 'map' | 'application';
89
+ sha256: string;
90
+ };
91
+ style: {
92
+ sha256: string;
93
+ };
94
+ image: {
95
+ sha256: string;
96
+ cssWidth: number;
97
+ cssHeight: number;
98
+ physicalWidth: number;
99
+ physicalHeight: number;
100
+ dpr: 1 | 2;
101
+ };
102
+ renderer: TileflowCaptureRendererIdentity;
103
+ platform: {
104
+ os: string;
105
+ architecture: string;
106
+ };
107
+ data: TileflowCaptureDataIdentity;
108
+ verification: TileflowCaptureVerification;
109
+ networkDependent: boolean;
110
+ };
111
+ type CreateTileflowCaptureReceiptInput = {
112
+ dpr: 1 | 2;
113
+ data: TileflowCaptureDataInput;
114
+ height: number;
115
+ map: string;
116
+ theme: string;
117
+ networkDependent: boolean;
118
+ pngSha256: string;
119
+ renderer: TileflowCaptureRendererIdentity;
120
+ scene: string;
121
+ sceneSha256: string;
122
+ styleSha256: string;
123
+ target: 'map' | 'application';
124
+ width: number;
125
+ };
126
+ declare function createTileflowCaptureReceipt(input: CreateTileflowCaptureReceiptInput): TileflowCaptureReceipt;
127
+ declare function serializeTileflowCaptureReceipt(receipt: TileflowCaptureReceipt): string;
128
+ declare function parseTileflowCaptureReceipt(source: string | Uint8Array): TileflowCaptureReceipt;
129
+ declare function validateTileflowCaptureReceipt(value: unknown): TileflowCaptureReceipt;
130
+
131
+ export { type CreateTileflowCaptureReceiptInput as C, type TileflowCaptureRendererIdentity as T, type TileflowCaptureReceipt as a, type TileflowCaptureDataInput as b, type TileflowCaptureWorldIdentity as c, type TileflowCaptureDataBindings as d, type TileflowCaptureDataCapabilities as e, type TileflowCaptureDataIdentity as f, type TileflowCaptureDataSemantics as g, type TileflowCaptureDataSource as h, type TileflowCaptureVectorIdentity as i, type TileflowCaptureVerification as j, createTileflowCaptureReceipt as k, createTileflowCaptureRendererIdentity as l, tileflowCaptureReceiptSchemaVersion as m, tileflowCaptureRuntime as n, parseTileflowCaptureReceipt as p, serializeTileflowCaptureReceipt as s, tileflowCaptureReceiptLimits as t, validateTileflowCaptureReceipt as v };
package/dist/receipt.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { C as CreateTileflowCaptureReceiptInput, e as TileflowCaptureDataBindingsV2, f as TileflowCaptureDataCapabilitiesV2, g as TileflowCaptureDataIdentityV2, h as TileflowCaptureDataIdentityV3, b as TileflowCaptureDataInput, i as TileflowCaptureDataSemanticsV2, j as TileflowCaptureDataSourceV2, d as TileflowCaptureReceipt, k as TileflowCaptureReceiptV2, l as TileflowCaptureReceiptV3, a as TileflowCaptureReceiptV4, m as TileflowCaptureVectorIdentityV3, n as TileflowCaptureVerificationV2, c as TileflowCaptureWorldIdentityV3, o as createTileflowCaptureReceipt, q as parseTileflowCaptureReceipt, s as serializeTileflowCaptureReceipt, t as tileflowCaptureReceiptLimits, r as tileflowCaptureReceiptSchemaVersion, v as validateTileflowCaptureReceipt } from './receipt-Q7wQ68tG.js';
1
+ export { C as CreateTileflowCaptureReceiptInput, d as TileflowCaptureDataBindings, e as TileflowCaptureDataCapabilities, f as TileflowCaptureDataIdentity, b as TileflowCaptureDataInput, g as TileflowCaptureDataSemantics, h as TileflowCaptureDataSource, a as TileflowCaptureReceipt, i as TileflowCaptureVectorIdentity, j as TileflowCaptureVerification, c as TileflowCaptureWorldIdentity, k as createTileflowCaptureReceipt, p as parseTileflowCaptureReceipt, s as serializeTileflowCaptureReceipt, t as tileflowCaptureReceiptLimits, m as tileflowCaptureReceiptSchemaVersion, v as validateTileflowCaptureReceipt } from './receipt-DhFOATRO.js';
2
2
  import 'playwright';
package/dist/receipt.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  tileflowCaptureReceiptLimits,
6
6
  tileflowCaptureReceiptSchemaVersion,
7
7
  validateTileflowCaptureReceipt
8
- } from "./chunk-BSTB4FN6.js";
8
+ } from "./chunk-VNDAYGXY.js";
9
9
  export {
10
10
  createTileflowCaptureReceipt,
11
11
  parseTileflowCaptureReceipt,
@@ -15,8 +15,7 @@ For Tileflow World, Capture resolves the map's TileJSON selector once per sessio
15
15
  `tileflow.world` to identify `world-v1` with exact release, descriptor, archive, data-contract, and
16
16
  product-contract SHA-256 values, and renders every standalone scene from the returned immutable tile
17
17
  template. Repeated scenes and retries reuse that one resolution; another selector in the same
18
- session fails instead of mixing releases. Existing canonical schema-v2 and schema-v3 receipts remain
19
- readable as historical evidence and are never reclassified as schema v4.
18
+ session fails instead of mixing releases. Parsing accepts only schema version 4.
20
19
 
21
20
  Capture reuses Core's exact World V1 release-ID contract: 12–128 characters matching
22
21
  `^world-v1-[a-z0-9][a-z0-9._-]*[a-z0-9]$`. Selector responses and durable receipts reject rather
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/capture",
3
- "version": "0.1.0-alpha.27",
3
+ "version": "0.1.0-alpha.29",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Deterministic local visual capture and comparison for Tileflow maps.",
6
6
  "engines": {
@@ -48,9 +48,9 @@
48
48
  "access": "public"
49
49
  },
50
50
  "dependencies": {
51
- "@tileflow/core": ">=0.1.0-alpha.29 <0.1.0-beta.0",
52
- "@tileflow/dev": ">=0.1.0-alpha.27 <0.1.0-beta.0",
53
- "maplibre-gl": "6.9.0",
51
+ "@tileflow/core": ">=0.1.0-alpha.32 <0.1.0-beta.0",
52
+ "@tileflow/dev": ">=0.1.0-alpha.30 <0.1.0-beta.0",
53
+ "maplibre-gl": "6.13.0",
54
54
  "pixelmatch": "7.2.0",
55
55
  "playwright": "1.62.1",
56
56
  "pngjs": "7.0.0"
@@ -61,20 +61,20 @@
61
61
  "@types/pngjs": "6.0.5",
62
62
  "@vitejs/plugin-vue": "^6.0.8",
63
63
  "maplibre-gl-min": "npm:maplibre-gl@6.4.1",
64
- "next": "16.3.3",
65
- "react": "^19.2.7",
66
- "react-dom": "^19.2.7",
67
- "svelte": "^5.56.4",
64
+ "next": "16.3.8",
65
+ "react": "^19.3.0",
66
+ "react-dom": "^19.3.0",
67
+ "svelte": "^5.57.2",
68
68
  "vite": "^8.0.16",
69
- "vue": "^3.5.39",
69
+ "vue": "^3.5.43",
70
70
  "webpack": "5.108.3",
71
- "@tileflow/maps": "0.1.0-alpha.6",
72
- "@tileflow/next": "0.1.0-alpha.24",
73
- "@tileflow/react": "0.1.0-alpha.27",
74
- "@tileflow/vite": "0.1.0-alpha.24",
75
- "@tileflow/svelte": "0.1.0-alpha.26",
76
- "@tileflow/vue": "0.1.0-alpha.26",
77
- "@tileflow/webpack": "0.1.0-alpha.24"
71
+ "@tileflow/maps": "0.1.0-alpha.8",
72
+ "@tileflow/next": "0.1.0-alpha.25",
73
+ "@tileflow/vue": "0.1.0-alpha.28",
74
+ "@tileflow/svelte": "0.1.0-alpha.28",
75
+ "@tileflow/vite": "0.1.0-alpha.25",
76
+ "@tileflow/react": "0.1.0-alpha.29",
77
+ "@tileflow/webpack": "0.1.0-alpha.25"
78
78
  },
79
79
  "scripts": {
80
80
  "build": "tsup src/index.ts src/receipt.ts --format esm --dts --clean --platform node",
@@ -1,160 +0,0 @@
1
- import { Browser } from 'playwright';
2
-
3
- type TileflowCaptureRendererIdentity = {
4
- tileflow: string;
5
- maplibre: string;
6
- playwright: string;
7
- chromiumRevision: string;
8
- chromiumVersion: string;
9
- };
10
- declare const tileflowCaptureRuntime: Readonly<{
11
- tileflow: string;
12
- maplibre: string;
13
- playwright: string;
14
- chromiumRevision: string;
15
- chromiumVersion: string;
16
- }>;
17
- declare function createTileflowCaptureRendererIdentity(browser?: Pick<Browser, 'version'>): TileflowCaptureRendererIdentity;
18
-
19
- declare const tileflowCaptureReceiptSchemaVersion: 4;
20
- declare const tileflowCaptureReceiptLimits: Readonly<{
21
- maximumBytes: number;
22
- }>;
23
- type TileflowCaptureDataBindingsV2 = {
24
- fields: Record<string, string>;
25
- layers: Record<string, string>;
26
- };
27
- type TileflowCaptureDataCapabilitiesV2 = {
28
- businessCorridor: boolean;
29
- /** Optional because receipts written before this capability existed remain valid schema v2. */
30
- bathymetry?: boolean;
31
- globalLandcover: boolean;
32
- tree: boolean;
33
- };
34
- type TileflowCaptureDataSourceV2 = {
35
- kind: 'loopback' | 'opaque' | 'remote' | 'root-relative';
36
- /** SHA-256 of a credential-free, query-free endpoint identity. */
37
- sha256: string;
38
- };
39
- type TileflowCaptureDataSemanticsV2 = {
40
- parkLayer: 'mixed' | 'protected-only';
41
- };
42
- /** Durable schema-v2 data identity owned by capture rather than the live core authoring API. */
43
- type TileflowCaptureDataIdentityV2 = {
44
- bindings?: TileflowCaptureDataBindingsV2;
45
- capabilities?: TileflowCaptureDataCapabilitiesV2;
46
- generation?: 'v1';
47
- kind: 'tileflow-world' | 'vector-tiles';
48
- revision?: string;
49
- schema: 'openmaptiles';
50
- schemaVersion: number;
51
- /** Optional because earlier schema-v2 receipts predate explicit park semantics. */
52
- semantics?: TileflowCaptureDataSemanticsV2;
53
- sourceId: 'tileflow';
54
- source?: TileflowCaptureDataSourceV2;
55
- };
56
- type TileflowCaptureWorldIdentityV3 = {
57
- archiveSha256: string;
58
- contractSha256: string;
59
- dataContractSha256: string;
60
- descriptorSha256: string;
61
- kind: 'tileflow-world';
62
- product: 'world-v1';
63
- releaseId: string;
64
- schema: 'openmaptiles';
65
- schemaVersion: number;
66
- semantics?: TileflowCaptureDataSemanticsV2;
67
- sourceId: 'tileflow';
68
- };
69
- type TileflowCaptureVectorIdentityV3 = {
70
- bindings?: {
71
- fields: Readonly<Record<string, string>>;
72
- layers: Readonly<Record<string, string>>;
73
- };
74
- capabilities?: {
75
- businessCorridor: boolean;
76
- bathymetry?: boolean;
77
- globalLandcover: boolean;
78
- tree: boolean;
79
- };
80
- kind: 'vector-tiles';
81
- revision?: string;
82
- schema: 'openmaptiles';
83
- schemaVersion: number;
84
- semantics?: TileflowCaptureDataSemanticsV2;
85
- sourceId: 'tileflow';
86
- /** Accepted only as transient input and converted to `source`; never returned or serialized. */
87
- url?: string;
88
- };
89
- /** Exact data-identity input embedded in every newly written schema-v4 receipt. */
90
- type TileflowCaptureDataInput = TileflowCaptureVectorIdentityV3 | TileflowCaptureWorldIdentityV3;
91
- type TileflowCaptureDataIdentityV3 = (Omit<TileflowCaptureVectorIdentityV3, 'url'> & {
92
- source?: TileflowCaptureDataSourceV2;
93
- }) | TileflowCaptureWorldIdentityV3;
94
- type TileflowCaptureVerificationV2 = {
95
- data: 'expected-unverified' | 'rendered';
96
- style: 'expected-unverified' | 'rendered';
97
- };
98
- type TileflowCaptureReceiptCommon = {
99
- scene: {
100
- name: string;
101
- map: string;
102
- target: 'map' | 'application';
103
- sha256: string;
104
- };
105
- style: {
106
- sha256: string;
107
- };
108
- image: {
109
- sha256: string;
110
- cssWidth: number;
111
- cssHeight: number;
112
- physicalWidth: number;
113
- physicalHeight: number;
114
- dpr: 1 | 2;
115
- };
116
- renderer: TileflowCaptureRendererIdentity;
117
- platform: {
118
- os: string;
119
- architecture: string;
120
- };
121
- verification: TileflowCaptureVerificationV2;
122
- networkDependent: boolean;
123
- };
124
- type TileflowCaptureReceiptV2 = TileflowCaptureReceiptCommon & {
125
- schemaVersion: 2;
126
- data: TileflowCaptureDataIdentityV2;
127
- };
128
- type TileflowCaptureReceiptV3 = TileflowCaptureReceiptCommon & {
129
- schemaVersion: 3;
130
- data: TileflowCaptureDataIdentityV3;
131
- };
132
- type TileflowCaptureReceiptV4 = Omit<TileflowCaptureReceiptCommon, 'scene'> & {
133
- schemaVersion: 4;
134
- data: TileflowCaptureDataIdentityV3;
135
- scene: TileflowCaptureReceiptCommon['scene'] & {
136
- theme: string;
137
- };
138
- };
139
- type TileflowCaptureReceipt = TileflowCaptureReceiptV2 | TileflowCaptureReceiptV3 | TileflowCaptureReceiptV4;
140
- type CreateTileflowCaptureReceiptInput = {
141
- dpr: 1 | 2;
142
- data: TileflowCaptureDataInput;
143
- height: number;
144
- map: string;
145
- theme: string;
146
- networkDependent: boolean;
147
- pngSha256: string;
148
- renderer: TileflowCaptureRendererIdentity;
149
- scene: string;
150
- sceneSha256: string;
151
- styleSha256: string;
152
- target: 'map' | 'application';
153
- width: number;
154
- };
155
- declare function createTileflowCaptureReceipt(input: CreateTileflowCaptureReceiptInput): TileflowCaptureReceiptV4;
156
- declare function serializeTileflowCaptureReceipt(receipt: TileflowCaptureReceipt): string;
157
- declare function parseTileflowCaptureReceipt(source: string | Uint8Array): TileflowCaptureReceipt;
158
- declare function validateTileflowCaptureReceipt(value: unknown): TileflowCaptureReceipt;
159
-
160
- export { type CreateTileflowCaptureReceiptInput as C, type TileflowCaptureRendererIdentity as T, type TileflowCaptureReceiptV4 as a, type TileflowCaptureDataInput as b, type TileflowCaptureWorldIdentityV3 as c, type TileflowCaptureReceipt as d, type TileflowCaptureDataBindingsV2 as e, type TileflowCaptureDataCapabilitiesV2 as f, type TileflowCaptureDataIdentityV2 as g, type TileflowCaptureDataIdentityV3 as h, type TileflowCaptureDataSemanticsV2 as i, type TileflowCaptureDataSourceV2 as j, type TileflowCaptureReceiptV2 as k, type TileflowCaptureReceiptV3 as l, type TileflowCaptureVectorIdentityV3 as m, type TileflowCaptureVerificationV2 as n, createTileflowCaptureReceipt as o, createTileflowCaptureRendererIdentity as p, parseTileflowCaptureReceipt as q, tileflowCaptureReceiptSchemaVersion as r, serializeTileflowCaptureReceipt as s, tileflowCaptureReceiptLimits as t, tileflowCaptureRuntime as u, validateTileflowCaptureReceipt as v };