@tileflow/dev 0.1.0-alpha.2 → 0.1.0-alpha.20

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.
@@ -0,0 +1,191 @@
1
+ import { TileflowStyleOptions, MapLibreStyle } from '@tileflow/core';
2
+ import { TileflowBuildCatalog, TileflowBuildStyles, TileflowMapBuildManifestV1, TileflowStyleInspection, TileflowMapBuildProvenanceV1, TileflowPreparedMapAssets } from '@tileflow/core/build';
3
+ import { TileflowRuntimeManifest } from '@tileflow/core/manifest';
4
+ import { TileflowBuildAsset, PreparedTileflowBuildCatalog, TileflowSourceCatalog, PreparedTileflowCatalog } from './icons.js';
5
+ export { defaultTileflowConfigPath } from './config.js';
6
+
7
+ type TileflowLocalTilesetFile = Readonly<{
8
+ byteLength: number;
9
+ etag: string;
10
+ fileName: string;
11
+ logicalId: string;
12
+ sourcePath: string;
13
+ }>;
14
+ declare function prepareTileflowLocalTilesets(project: TileflowBuildCatalog, styles: TileflowBuildStyles, options: {
15
+ assetBaseUrl: string;
16
+ baseDirectory: string;
17
+ cwd: string;
18
+ }): Promise<{
19
+ dispose(): Promise<void>;
20
+ files: TileflowLocalTilesetFile[];
21
+ styles: TileflowBuildStyles;
22
+ watchPaths: string[];
23
+ }>;
24
+
25
+ declare const tileflowArtifactSessionSchemaVersion: 1;
26
+ type TileflowArtifactDiagnostic = {
27
+ code?: string;
28
+ message: string;
29
+ path: string;
30
+ phase?: string;
31
+ };
32
+ type TileflowArtifactSessionState = {
33
+ status: 'building';
34
+ generation: number;
35
+ lastGoodGeneration?: number;
36
+ } | {
37
+ status: 'ready';
38
+ generation: number;
39
+ artifacts: TileflowBuildArtifacts;
40
+ lastGoodGeneration: number;
41
+ } | {
42
+ status: 'invalid';
43
+ generation: number;
44
+ diagnostics: TileflowArtifactDiagnostic[];
45
+ lastGoodGeneration?: number;
46
+ };
47
+ type TileflowArtifactSessionOptions = TileflowBuildArtifactsOptions & {
48
+ debounceMs?: number;
49
+ ignoredPaths?: string[];
50
+ watch?: boolean;
51
+ };
52
+ type TileflowArtifactAcquisition = Readonly<{
53
+ artifacts: TileflowBuildArtifacts;
54
+ generation: number;
55
+ release(): Promise<void>;
56
+ }>;
57
+ type TileflowArtifactSession = {
58
+ /** Pins the current generation for asynchronous work; the caller must release it. */
59
+ acquireArtifacts(generation?: number): TileflowArtifactAcquisition | undefined;
60
+ close(): Promise<void>;
61
+ /** Borrowed synchronous view. Use acquireArtifacts() before retaining it across an await. */
62
+ getLastGoodArtifacts(): TileflowBuildArtifacts | undefined;
63
+ /** Ready-state artifacts are a borrowed synchronous view. */
64
+ getState(): TileflowArtifactSessionState;
65
+ refresh(reason?: string): Promise<void>;
66
+ subscribe(listener: (state: TileflowArtifactSessionState) => void): () => void;
67
+ };
68
+ declare function createTileflowArtifactDiagnostics(error: unknown, cwd: string): TileflowArtifactDiagnostic[];
69
+
70
+ /** Normalize a development route base. This is a URL pathname, never a filesystem path. */
71
+ declare function normalizeTileflowBasePath(value?: string): string;
72
+ /**
73
+ * Join a bundler public URL prefix to the Tileflow route without changing URL-reference kind.
74
+ * In particular, `./` and `../` remain path-relative rather than becoming root-relative.
75
+ */
76
+ declare function joinTileflowPublicUrl(publicBase: string, basePath: string): string;
77
+ /**
78
+ * Resolve the public URL at which a manifest is exposed and the URLs embedded inside its artifacts.
79
+ * Path-relative deployments use owner-relative references because the manifest already lives below
80
+ * the public prefix.
81
+ */
82
+ declare function resolveTileflowArtifactPublicUrls(publicBase: string, basePath: string): {
83
+ assetBaseUrl?: string;
84
+ publicBaseUrl: string;
85
+ styleBaseUrl: string;
86
+ };
87
+ /** Convert a validated route base to a bundler-relative asset prefix. */
88
+ declare function getTileflowAssetBasePath(basePath: string): string;
89
+ declare function getTileflowAssetFileName(basePath: string, fileName: string): string;
90
+
91
+ declare const tileflowArtifactPlanSchemaVersion: 1;
92
+ declare const tileflowArtifactInventoryFileName = ".tileflow-artifacts.json";
93
+ type TileflowManifestOptions = {
94
+ styleBaseUrl?: string;
95
+ };
96
+ type TileflowBuildArtifactsOptions = {
97
+ apiBaseUrl?: string;
98
+ assetBaseUrl?: string;
99
+ config?: string;
100
+ cwd?: string;
101
+ /** Build a memory-only compiler sidecar for local authoring tools. */
102
+ inspection?: boolean;
103
+ styleBaseUrl?: string;
104
+ /** Local tools may snapshot local PMTiles; production output must resolve them explicitly. */
105
+ target?: 'local' | 'production';
106
+ };
107
+ type TileflowBuildStyleInspections = Record<string, Record<string, TileflowStyleInspection>>;
108
+ /** Compatibility shape consumed by sessions and capture callers. */
109
+ type TileflowBuildArtifacts = {
110
+ assets: TileflowBuildAsset[];
111
+ buildManifest: TileflowMapBuildManifestV1;
112
+ /** Releases local immutable snapshot references owned by this artifact generation. */
113
+ dispose?: () => Promise<void>;
114
+ manifest: TileflowRuntimeManifest;
115
+ project: TileflowBuildCatalog;
116
+ /** Local-only archive ports. Paths never enter serialized build artifacts. */
117
+ localTilesets?: TileflowLocalTilesetFile[];
118
+ /** Optional local-only provenance. It is never serialized as a build artifact. */
119
+ styleInspections?: TileflowBuildStyleInspections;
120
+ styles: TileflowBuildStyles;
121
+ watchPaths: string[];
122
+ };
123
+ type TileflowArtifactFile = TileflowBuildAsset;
124
+ type TileflowArtifactInputGraph = {
125
+ /** Exact executable config modules and data files observed during evaluation. */
126
+ files: string[];
127
+ /** Asset directories whose children can change without changing the config module. */
128
+ directories: string[];
129
+ };
130
+ /**
131
+ * Complete, deterministic output of compiling one prepared source generation.
132
+ * `sourceProject` is retained for diagnostics only; `project` is the portable runtime input.
133
+ */
134
+ type TileflowArtifactPlan = TileflowBuildArtifacts & {
135
+ files: TileflowArtifactFile[];
136
+ inputs: TileflowArtifactInputGraph;
137
+ project: PreparedTileflowBuildCatalog;
138
+ schemaVersion: typeof tileflowArtifactPlanSchemaVersion;
139
+ sourceProject: TileflowSourceCatalog;
140
+ };
141
+ type CreateTileflowArtifactPlanOptions = Pick<TileflowBuildArtifactsOptions, 'apiBaseUrl' | 'assetBaseUrl' | 'inspection' | 'styleBaseUrl' | 'target'> & {
142
+ inputFiles?: readonly string[];
143
+ };
144
+ type WriteTileflowArtifactPlanOptions = {
145
+ cwd?: string;
146
+ outDir: string;
147
+ /** Explicit escape hatch for replacing a Hosted delivery manifest with self-hosted artifacts. */
148
+ overwriteHostedManifest?: boolean;
149
+ };
150
+ type WriteTileflowBuildArtifactsOptions = TileflowBuildArtifactsOptions & WriteTileflowArtifactPlanOptions;
151
+ declare class TileflowHostedManifestOverwriteError extends Error {
152
+ readonly code: "HOSTED_MANIFEST_OVERWRITE_REFUSED";
153
+ constructor(path: string);
154
+ }
155
+ declare class TileflowLocalTilesetProductionError extends Error {
156
+ readonly code: "TF_LOCAL_TILESET_PRODUCTION_UNRESOLVED";
157
+ constructor();
158
+ }
159
+ declare function createTileflowManifest(project: TileflowBuildCatalog, options?: TileflowManifestOptions): TileflowRuntimeManifest;
160
+ declare function createTileflowStyle(project: TileflowBuildCatalog, mapName: string, options?: TileflowStyleOptions): MapLibreStyle;
161
+ declare function createTileflowStyles(project: TileflowBuildCatalog, options?: Omit<TileflowStyleOptions, 'preparedAssets' | 'theme'> & {
162
+ mapAssets?: Readonly<Record<string, TileflowPreparedMapAssets>>;
163
+ }): TileflowBuildStyles;
164
+ /** Compiles only a prepared project, keeping local source resolution out of core compilation. */
165
+ declare function createTileflowArtifactPlan(prepared: PreparedTileflowCatalog, options?: CreateTileflowArtifactPlanOptions): Promise<TileflowArtifactPlan>;
166
+ declare function createTileflowBuildArtifacts(options?: TileflowBuildArtifactsOptions): Promise<TileflowArtifactPlan>;
167
+ declare function getTileflowArtifactFiles(artifacts: TileflowBuildArtifacts): TileflowArtifactFile[];
168
+ /** Resolve portable build provenance without making it part of any map authoring revision. */
169
+ declare function createTileflowBuildProvenance(cwd: string): Promise<TileflowMapBuildProvenanceV1>;
170
+ declare function createTileflowArtifactSession(options?: TileflowArtifactSessionOptions): Promise<TileflowArtifactSession>;
171
+ declare function getTileflowWatchPaths(options?: Pick<TileflowBuildArtifactsOptions, 'config' | 'cwd'>): Promise<string[]>;
172
+ declare function isTileflowArtifactInputPath(inputs: TileflowArtifactInputGraph, path: string): boolean;
173
+ /** Shared refresh gate for adapters that receive filesystem or framework lifecycle events. */
174
+ declare function refreshTileflowArtifactSession(session: TileflowArtifactSession, options: {
175
+ inputPath?: string;
176
+ reason: string;
177
+ }): Promise<boolean>;
178
+ declare function writeTileflowBuildArtifacts(options: WriteTileflowBuildArtifactsOptions): Promise<TileflowArtifactPlan>;
179
+ declare function disposeTileflowBuildArtifacts(artifacts: Pick<TileflowBuildArtifacts, 'dispose'>): Promise<void>;
180
+ /**
181
+ * Replaces one managed artifact generation and records its exact file inventory. Unmanaged files
182
+ * are never scanned or removed. A caught filesystem failure restores every previous managed file.
183
+ */
184
+ declare function writeTileflowArtifactPlan(artifacts: TileflowArtifactPlan, options: WriteTileflowArtifactPlanOptions): Promise<void>;
185
+ declare function assertNoLocalTilesetsForProduction(artifacts: Pick<TileflowBuildArtifacts, 'localTilesets'>): void;
186
+ /** Prevents a framework build from silently replacing the frontend's Hosted delivery contract. */
187
+ declare function assertTileflowSelfHostedManifestTarget(manifestPath: string, options?: {
188
+ overwriteHostedManifest?: boolean;
189
+ }): Promise<void>;
190
+
191
+ export { type CreateTileflowArtifactPlanOptions, PreparedTileflowBuildCatalog, PreparedTileflowCatalog, type TileflowArtifactAcquisition, type TileflowArtifactDiagnostic, type TileflowArtifactFile, type TileflowArtifactInputGraph, type TileflowArtifactPlan, type TileflowArtifactSession, type TileflowArtifactSessionOptions, type TileflowArtifactSessionState, type TileflowBuildArtifacts, type TileflowBuildArtifactsOptions, TileflowBuildAsset, type TileflowBuildStyleInspections, TileflowHostedManifestOverwriteError, type TileflowLocalTilesetFile, TileflowLocalTilesetProductionError, type TileflowManifestOptions, TileflowSourceCatalog, type WriteTileflowArtifactPlanOptions, type WriteTileflowBuildArtifactsOptions, assertNoLocalTilesetsForProduction, assertTileflowSelfHostedManifestTarget, createTileflowArtifactDiagnostics, createTileflowArtifactPlan, createTileflowArtifactSession, createTileflowBuildArtifacts, createTileflowBuildProvenance, createTileflowManifest, createTileflowStyle, createTileflowStyles, disposeTileflowBuildArtifacts, getTileflowArtifactFiles, getTileflowAssetBasePath, getTileflowAssetFileName, getTileflowWatchPaths, isTileflowArtifactInputPath, joinTileflowPublicUrl, normalizeTileflowBasePath, prepareTileflowLocalTilesets, refreshTileflowArtifactSession, resolveTileflowArtifactPublicUrls, tileflowArtifactInventoryFileName, tileflowArtifactPlanSchemaVersion, tileflowArtifactSessionSchemaVersion, writeTileflowArtifactPlan, writeTileflowBuildArtifacts };
@@ -0,0 +1,71 @@
1
+ import {
2
+ TileflowHostedManifestOverwriteError,
3
+ TileflowLocalTilesetProductionError,
4
+ assertNoLocalTilesetsForProduction,
5
+ assertTileflowSelfHostedManifestTarget,
6
+ createTileflowArtifactDiagnostics,
7
+ createTileflowArtifactPlan,
8
+ createTileflowArtifactSession,
9
+ createTileflowBuildArtifacts,
10
+ createTileflowBuildProvenance,
11
+ createTileflowManifest,
12
+ createTileflowStyle,
13
+ createTileflowStyles,
14
+ disposeTileflowBuildArtifacts,
15
+ getTileflowArtifactFiles,
16
+ getTileflowWatchPaths,
17
+ isTileflowArtifactInputPath,
18
+ prepareTileflowLocalTilesets,
19
+ refreshTileflowArtifactSession,
20
+ tileflowArtifactInventoryFileName,
21
+ tileflowArtifactPlanSchemaVersion,
22
+ tileflowArtifactSessionSchemaVersion,
23
+ writeTileflowArtifactPlan,
24
+ writeTileflowBuildArtifacts
25
+ } from "./chunk-XTRHREXO.js";
26
+ import "./chunk-ONYQNLNA.js";
27
+ import {
28
+ getTileflowAssetBasePath,
29
+ getTileflowAssetFileName,
30
+ joinTileflowPublicUrl,
31
+ normalizeTileflowBasePath,
32
+ resolveTileflowArtifactPublicUrls
33
+ } from "./chunk-RSBV4L2Y.js";
34
+ import "./chunk-CENQR5Q2.js";
35
+ import "./chunk-BL3FK4GO.js";
36
+ import "./chunk-KDFTE4Q5.js";
37
+ import {
38
+ defaultTileflowConfigPath
39
+ } from "./chunk-6MGFMKG3.js";
40
+ import "./chunk-D4OE4ITL.js";
41
+ export {
42
+ TileflowHostedManifestOverwriteError,
43
+ TileflowLocalTilesetProductionError,
44
+ assertNoLocalTilesetsForProduction,
45
+ assertTileflowSelfHostedManifestTarget,
46
+ createTileflowArtifactDiagnostics,
47
+ createTileflowArtifactPlan,
48
+ createTileflowArtifactSession,
49
+ createTileflowBuildArtifacts,
50
+ createTileflowBuildProvenance,
51
+ createTileflowManifest,
52
+ createTileflowStyle,
53
+ createTileflowStyles,
54
+ defaultTileflowConfigPath,
55
+ disposeTileflowBuildArtifacts,
56
+ getTileflowArtifactFiles,
57
+ getTileflowAssetBasePath,
58
+ getTileflowAssetFileName,
59
+ getTileflowWatchPaths,
60
+ isTileflowArtifactInputPath,
61
+ joinTileflowPublicUrl,
62
+ normalizeTileflowBasePath,
63
+ prepareTileflowLocalTilesets,
64
+ refreshTileflowArtifactSession,
65
+ resolveTileflowArtifactPublicUrls,
66
+ tileflowArtifactInventoryFileName,
67
+ tileflowArtifactPlanSchemaVersion,
68
+ tileflowArtifactSessionSchemaVersion,
69
+ writeTileflowArtifactPlan,
70
+ writeTileflowBuildArtifacts
71
+ };
@@ -0,0 +1,284 @@
1
+ import {
2
+ isPathWithin
3
+ } from "./chunk-D4OE4ITL.js";
4
+
5
+ // src/config.ts
6
+ import { createJiti } from "jiti";
7
+ import { existsSync, realpathSync } from "fs";
8
+ import { createRequire } from "module";
9
+ import { dirname, resolve, sep } from "path";
10
+ import {
11
+ parseResolvedTileflowMap,
12
+ parseTileflowMap,
13
+ tileflowCaptureSceneNameSchema,
14
+ TileflowResolvedMapValidationError
15
+ } from "@tileflow/core";
16
+ import { collectTileflowMapBuildLineage } from "@tileflow/core/build";
17
+ var defaultTileflowApiUrl = "https://api.tileflow.dev";
18
+ var defaultTileflowConfigPath = "tileflow.config.ts";
19
+ var defaultTileflowManifestPath = "public/tileflow/manifest.json";
20
+ var TileflowValidationError = class extends Error {
21
+ code = "CONFIG_INVALID";
22
+ messages;
23
+ phase = "config-validation";
24
+ constructor(messages) {
25
+ super("Invalid Tileflow config");
26
+ this.name = "TileflowValidationError";
27
+ this.messages = messages;
28
+ }
29
+ };
30
+ async function loadTileflowConfig(configPath = defaultTileflowConfigPath, options = {}) {
31
+ return (await loadTileflowConfigWithInputs(configPath, options)).project;
32
+ }
33
+ async function loadTileflowConfigWithInputs(configPath = defaultTileflowConfigPath, options = {}) {
34
+ const cwd = options.cwd ?? process.cwd();
35
+ const resolvedPath = resolve(cwd, configPath);
36
+ if (!existsSync(resolvedPath)) {
37
+ throw new Error(`Config not found: ${configPath}`);
38
+ }
39
+ if (options.fresh) {
40
+ clearTileflowLocalModuleCache(resolvedPath, cwd);
41
+ }
42
+ const jiti = createJiti(import.meta.url, {
43
+ fsCache: false,
44
+ moduleCache: true
45
+ });
46
+ const imported = await jiti.import(resolvedPath, { default: true });
47
+ const allowWorkspace = /\.workspace\.(?:[cm]?[jt]s)$/u.test(resolvedPath);
48
+ const project = asTileflowBuildCatalog(imported, { allowWorkspace });
49
+ return {
50
+ authoringMaps: getTileflowAuthoringMaps(imported, project, allowWorkspace),
51
+ configFile: resolvedPath,
52
+ inputFiles: collectTileflowConfigInputs(resolvedPath, cwd),
53
+ project
54
+ };
55
+ }
56
+ async function loadValidTileflowConfig(configPath = defaultTileflowConfigPath, options = {}) {
57
+ const project = await loadTileflowConfig(configPath, options);
58
+ assertValidTileflowConfig(project);
59
+ return project;
60
+ }
61
+ async function loadValidTileflowConfigWithInputs(configPath = defaultTileflowConfigPath, options = {}) {
62
+ const loaded = await loadTileflowConfigWithInputs(configPath, options);
63
+ assertValidTileflowConfig(loaded.project);
64
+ return loaded;
65
+ }
66
+ function assertValidTileflowConfig(project) {
67
+ const messages = [];
68
+ for (const [mapId, map] of Object.entries(project.maps)) {
69
+ try {
70
+ parseResolvedTileflowMap(map);
71
+ } catch (error) {
72
+ messages.push({
73
+ level: "error",
74
+ path: `maps.${mapId}`,
75
+ message: error instanceof Error ? error.message : String(error)
76
+ });
77
+ }
78
+ }
79
+ for (const [sceneId, scene] of Object.entries(project.scenes ?? {})) {
80
+ if (!Object.hasOwn(project.maps, scene.map)) {
81
+ messages.push({
82
+ level: "error",
83
+ path: `scenes.${sceneId}.map`,
84
+ message: `Unknown Tileflow map "${scene.map}".`
85
+ });
86
+ }
87
+ }
88
+ if (messages.length > 0) throw new TileflowValidationError(messages);
89
+ }
90
+ function asTileflowBuildCatalog(input, options = {}) {
91
+ if (isRecord(input) && isRecord(input.maps)) {
92
+ if (!options.allowWorkspace) {
93
+ throw tileflowConfigValidationError(
94
+ "maps",
95
+ new Error(
96
+ "tileflow.config.ts must export one map. Multi-map catalogs are internal workspaces and must use a *.workspace.ts file."
97
+ )
98
+ );
99
+ }
100
+ const unknownKey = Object.keys(input).find((key) => key !== "maps");
101
+ if (unknownKey) {
102
+ throw tileflowConfigValidationError(
103
+ unknownKey,
104
+ new Error(`Tileflow workspace has unrecognized key "${unknownKey}".`)
105
+ );
106
+ }
107
+ const entries = Object.entries(input.maps).map(([key, value]) => {
108
+ const map2 = value;
109
+ const resolved2 = parseTileflowCatalogMap(map2, `maps.${key}`);
110
+ if (key !== resolved2.id) {
111
+ throw tileflowConfigValidationError(
112
+ `maps.${key}`,
113
+ new Error(`Tileflow workspace map key "${key}" must match the map id "${resolved2.id}".`)
114
+ );
115
+ }
116
+ return [
117
+ key,
118
+ resolved2,
119
+ collectTileflowMapBuildLineage(map2),
120
+ normalizeSingularMapScenes(map2, resolved2.id)
121
+ ];
122
+ });
123
+ if (entries.length === 0) {
124
+ throw tileflowConfigValidationError(
125
+ "maps",
126
+ new Error("Tileflow workspace must contain at least one map.")
127
+ );
128
+ }
129
+ const scenes2 = /* @__PURE__ */ new Map();
130
+ for (const [mapId, , , mapScenes] of entries) {
131
+ for (const [sceneId, scene] of Object.entries(mapScenes ?? {})) {
132
+ if (scenes2.has(sceneId)) {
133
+ throw tileflowConfigValidationError(
134
+ `maps.${mapId}.scenes.${sceneId}`,
135
+ new Error(`Tileflow workspace scene "${sceneId}" is already defined by another map.`)
136
+ );
137
+ }
138
+ scenes2.set(sceneId, scene);
139
+ }
140
+ }
141
+ return {
142
+ mapMetadata: Object.fromEntries(
143
+ entries.map(([id, map2, lineage]) => [id, { id, lineage, version: map2.version }])
144
+ ),
145
+ maps: Object.fromEntries(entries.map(([id, map2]) => [id, map2])),
146
+ ...scenes2.size > 0 ? { scenes: Object.fromEntries(scenes2) } : {}
147
+ };
148
+ }
149
+ const map = input;
150
+ const resolved = parseTileflowCatalogMap(map, "");
151
+ let scenes;
152
+ try {
153
+ scenes = normalizeSingularMapScenes(map, resolved.id);
154
+ } catch (error) {
155
+ throw tileflowConfigValidationError("scenes", error);
156
+ }
157
+ return {
158
+ mapMetadata: {
159
+ [resolved.id]: {
160
+ id: resolved.id,
161
+ lineage: collectTileflowMapBuildLineage(map),
162
+ version: resolved.version
163
+ }
164
+ },
165
+ maps: { [resolved.id]: resolved },
166
+ ...scenes ? { scenes } : {}
167
+ };
168
+ }
169
+ function parseTileflowCatalogMap(map, path) {
170
+ try {
171
+ return parseTileflowMap(map);
172
+ } catch (error) {
173
+ throw tileflowConfigValidationError(path, error);
174
+ }
175
+ }
176
+ function getTileflowAuthoringMaps(input, project, allowWorkspace) {
177
+ if (allowWorkspace && isRecord(input) && isRecord(input.maps)) {
178
+ const maps = input.maps;
179
+ return Object.fromEntries(
180
+ Object.keys(project.maps).map((mapId2) => [mapId2, maps[mapId2]])
181
+ );
182
+ }
183
+ const [mapId] = Object.keys(project.maps);
184
+ return mapId ? { [mapId]: input } : {};
185
+ }
186
+ function tileflowConfigValidationError(path, error) {
187
+ if (error instanceof TileflowValidationError) return error;
188
+ if (error instanceof TileflowResolvedMapValidationError) {
189
+ return new TileflowValidationError(
190
+ error.messages.map((message) => ({
191
+ ...message,
192
+ path: prefixValidationPath(path, message.path)
193
+ }))
194
+ );
195
+ }
196
+ return new TileflowValidationError([
197
+ {
198
+ level: "error",
199
+ path: path || "map",
200
+ message: error instanceof Error ? error.message : String(error)
201
+ }
202
+ ]);
203
+ }
204
+ function prefixValidationPath(prefix, path) {
205
+ const child = path === "config" ? "" : path;
206
+ if (!prefix) return child || "map";
207
+ return child ? `${prefix}.${child}` : prefix;
208
+ }
209
+ function normalizeSingularMapScenes(map, mapId) {
210
+ if (!map.scenes) return void 0;
211
+ return Object.fromEntries(
212
+ Object.entries(map.scenes).map(([sceneId, scene]) => {
213
+ const normalizedSceneId = tileflowCaptureSceneNameSchema.parse(sceneId);
214
+ return [normalizedSceneId, { ...scene, map: mapId }];
215
+ })
216
+ );
217
+ }
218
+ function getTileflowMapNames(project) {
219
+ return Object.keys(project.maps);
220
+ }
221
+ function getFirstTileflowMapName(project) {
222
+ const [mapName] = getTileflowMapNames(project);
223
+ if (!mapName) {
224
+ throw new Error("Tileflow config must define at least one map.");
225
+ }
226
+ return mapName;
227
+ }
228
+ var localRequire = createRequire(import.meta.url);
229
+ function collectTileflowConfigInputs(configPath, cwd) {
230
+ const roots = [canonicalPath(cwd), canonicalPath(dirname(resolve(configPath)))];
231
+ const inputs = /* @__PURE__ */ new Set([canonicalPath(configPath)]);
232
+ const pending = [localRequire.cache[canonicalPath(configPath)]];
233
+ const visited = /* @__PURE__ */ new Set();
234
+ while (pending.length > 0) {
235
+ const module = pending.pop();
236
+ if (!module || visited.has(module.filename)) continue;
237
+ visited.add(module.filename);
238
+ const path = canonicalPath(module.filename);
239
+ if (!path.split(sep).includes("node_modules") && roots.some((root) => isPathWithin(root, path))) {
240
+ inputs.add(path);
241
+ }
242
+ pending.push(...module.children);
243
+ }
244
+ for (const cachePath of Object.keys(localRequire.cache)) {
245
+ const path = canonicalPath(cachePath);
246
+ if (!path.split(sep).includes("node_modules") && roots.some((root) => isPathWithin(root, path))) {
247
+ inputs.add(path);
248
+ }
249
+ }
250
+ return [...inputs].sort();
251
+ }
252
+ function clearTileflowLocalModuleCache(configPath, cwd) {
253
+ const roots = [canonicalPath(cwd), canonicalPath(dirname(resolve(configPath)))];
254
+ for (const cachePath of Object.keys(localRequire.cache)) {
255
+ if (cachePath.split(sep).includes("node_modules")) continue;
256
+ if (roots.some((root) => isPathWithin(root, canonicalPath(cachePath)))) {
257
+ delete localRequire.cache[cachePath];
258
+ }
259
+ }
260
+ }
261
+ function canonicalPath(path) {
262
+ try {
263
+ return realpathSync.native(resolve(path));
264
+ } catch {
265
+ return resolve(path);
266
+ }
267
+ }
268
+ function isRecord(value) {
269
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
270
+ }
271
+
272
+ export {
273
+ defaultTileflowApiUrl,
274
+ defaultTileflowConfigPath,
275
+ defaultTileflowManifestPath,
276
+ TileflowValidationError,
277
+ loadTileflowConfig,
278
+ loadTileflowConfigWithInputs,
279
+ loadValidTileflowConfig,
280
+ loadValidTileflowConfigWithInputs,
281
+ assertValidTileflowConfig,
282
+ getTileflowMapNames,
283
+ getFirstTileflowMapName
284
+ };