@tileflow/dev 0.1.0-alpha.4 → 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/LICENSE +201 -0
- package/README.md +264 -5
- package/THIRD_PARTY_NOTICES.md +309 -0
- package/dist/artifacts.d.ts +269 -0
- package/dist/artifacts.js +98 -0
- package/dist/chunk-AQUGMUZW.js +324 -0
- package/dist/chunk-C4VPHZ3F.js +4062 -0
- package/dist/chunk-D4OE4ITL.js +13 -0
- package/dist/chunk-FOMTSCOP.js +671 -0
- package/dist/chunk-GXLY73PD.js +3199 -0
- package/dist/chunk-KDFTE4Q5.js +156 -0
- package/dist/chunk-ONYQNLNA.js +1108 -0
- package/dist/chunk-RTU7TD4M.js +172 -0
- package/dist/chunk-XHJBCVBB.js +241 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.js +27 -0
- package/dist/fonts.d.ts +47 -0
- package/dist/fonts.js +16 -0
- package/dist/icons-BIHpw5Zy.d.ts +417 -0
- package/dist/icons.d.ts +3 -0
- package/dist/icons.js +41 -0
- package/dist/inspect.d.ts +149 -0
- package/dist/inspect.js +805 -0
- package/dist/inspector-browser.js +16955 -0
- package/dist/inspector-observer.js +95 -0
- package/dist/preview-assets-ATLLYY72.js +103 -0
- package/dist/preview.d.ts +31 -0
- package/dist/preview.js +1974 -0
- package/dist/server.d.ts +89 -0
- package/dist/server.js +3662 -0
- package/dist/tilesets.d.ts +89 -0
- package/dist/tilesets.js +6 -0
- package/dist/validation.d.ts +65 -0
- package/dist/validation.js +24 -0
- package/package.json +77 -13
- package/ui-fonts/hubot-sans-OFL.txt +93 -0
- package/ui-fonts/hubot-sans.woff2 +0 -0
- package/ui-fonts/inter-OFL.txt +92 -0
- package/ui-fonts/inter.woff2 +0 -0
- package/ui-fonts/jetbrains-mono-OFL.txt +93 -0
- package/ui-fonts/jetbrains-mono.woff2 +0 -0
- package/ui-fonts/mona-sans-OFL.txt +93 -0
- package/ui-fonts/mona-sans.woff2 +0 -0
- package/dist/index.d.ts +0 -54
- package/dist/index.js +0 -314
|
@@ -0,0 +1,324 @@
|
|
|
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
|
+
tileflowCaptureShotNameSchema,
|
|
15
|
+
TileflowResolvedMapValidationError
|
|
16
|
+
} from "@tileflow/core";
|
|
17
|
+
import { collectTileflowMapBuildLineage } from "@tileflow/core/build";
|
|
18
|
+
var defaultTileflowApiUrl = "https://api.tileflow.dev";
|
|
19
|
+
var defaultTileflowConfigPath = "tileflow.config.ts";
|
|
20
|
+
var defaultTileflowManifestPath = "public/tileflow/manifest.json";
|
|
21
|
+
var TileflowValidationError = class extends Error {
|
|
22
|
+
code = "CONFIG_INVALID";
|
|
23
|
+
messages;
|
|
24
|
+
phase = "config-validation";
|
|
25
|
+
constructor(messages) {
|
|
26
|
+
super("Invalid Tileflow config");
|
|
27
|
+
this.name = "TileflowValidationError";
|
|
28
|
+
this.messages = messages;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
async function loadTileflowConfig(configPath = defaultTileflowConfigPath, options = {}) {
|
|
32
|
+
return (await loadTileflowConfigWithInputs(configPath, options)).project;
|
|
33
|
+
}
|
|
34
|
+
async function loadTileflowConfigWithInputs(configPath = defaultTileflowConfigPath, options = {}) {
|
|
35
|
+
const cwd = options.cwd ?? process.cwd();
|
|
36
|
+
const resolvedPath = resolve(cwd, configPath);
|
|
37
|
+
if (!existsSync(resolvedPath)) {
|
|
38
|
+
throw new Error(`Config not found: ${configPath}`);
|
|
39
|
+
}
|
|
40
|
+
if (options.fresh) {
|
|
41
|
+
clearTileflowLocalModuleCache(resolvedPath, cwd);
|
|
42
|
+
}
|
|
43
|
+
const jiti = createJiti(import.meta.url, {
|
|
44
|
+
fsCache: false,
|
|
45
|
+
moduleCache: true
|
|
46
|
+
});
|
|
47
|
+
const imported = await jiti.import(resolvedPath, { default: true });
|
|
48
|
+
const allowWorkspace = /\.workspace\.(?:[cm]?[jt]s)$/u.test(resolvedPath);
|
|
49
|
+
const project = asTileflowBuildCatalog(imported, { allowWorkspace });
|
|
50
|
+
return {
|
|
51
|
+
authoringMaps: getTileflowAuthoringMaps(imported, project, allowWorkspace),
|
|
52
|
+
configFile: resolvedPath,
|
|
53
|
+
inputFiles: collectTileflowConfigInputs(resolvedPath, cwd),
|
|
54
|
+
project
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async function loadValidTileflowConfig(configPath = defaultTileflowConfigPath, options = {}) {
|
|
58
|
+
const project = await loadTileflowConfig(configPath, options);
|
|
59
|
+
assertValidTileflowConfig(project);
|
|
60
|
+
return project;
|
|
61
|
+
}
|
|
62
|
+
async function loadValidTileflowConfigWithInputs(configPath = defaultTileflowConfigPath, options = {}) {
|
|
63
|
+
const loaded = await loadTileflowConfigWithInputs(configPath, options);
|
|
64
|
+
assertValidTileflowConfig(loaded.project);
|
|
65
|
+
return loaded;
|
|
66
|
+
}
|
|
67
|
+
function assertValidTileflowConfig(project) {
|
|
68
|
+
const messages = [];
|
|
69
|
+
for (const [mapId, map] of Object.entries(project.maps)) {
|
|
70
|
+
try {
|
|
71
|
+
parseResolvedTileflowMap(map);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
messages.push({
|
|
74
|
+
level: "error",
|
|
75
|
+
path: `maps.${mapId}`,
|
|
76
|
+
message: error instanceof Error ? error.message : String(error)
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
for (const [sceneId, scene] of Object.entries(project.scenes ?? {})) {
|
|
81
|
+
if (!Object.hasOwn(project.maps, scene.map)) {
|
|
82
|
+
messages.push({
|
|
83
|
+
level: "error",
|
|
84
|
+
path: `scenes.${sceneId}.map`,
|
|
85
|
+
message: `Unknown Tileflow map "${scene.map}".`
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const [shotId, shot] of Object.entries(project.shots ?? {})) {
|
|
90
|
+
if (!Object.hasOwn(project.maps, shot.map)) {
|
|
91
|
+
messages.push({
|
|
92
|
+
level: "error",
|
|
93
|
+
path: `shots.${shotId}.map`,
|
|
94
|
+
message: `Unknown Tileflow map "${shot.map}".`
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (messages.length > 0) throw new TileflowValidationError(messages);
|
|
99
|
+
}
|
|
100
|
+
function asTileflowBuildCatalog(input, options = {}) {
|
|
101
|
+
if (isRecord(input) && isRecord(input.maps)) {
|
|
102
|
+
if (!options.allowWorkspace) {
|
|
103
|
+
throw tileflowConfigValidationError(
|
|
104
|
+
"maps",
|
|
105
|
+
new Error(
|
|
106
|
+
"tileflow.config.ts must export one map. Multi-map catalogs are internal workspaces and must use a *.workspace.ts file."
|
|
107
|
+
)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
const unknownKey = Object.keys(input).find((key) => key !== "maps");
|
|
111
|
+
if (unknownKey) {
|
|
112
|
+
throw tileflowConfigValidationError(
|
|
113
|
+
unknownKey,
|
|
114
|
+
new Error(`Tileflow workspace has unrecognized key "${unknownKey}".`)
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
const entries = Object.entries(input.maps).map(([key, value]) => {
|
|
118
|
+
const map2 = value;
|
|
119
|
+
const resolved2 = parseTileflowCatalogMap(map2, `maps.${key}`);
|
|
120
|
+
if (key !== resolved2.id) {
|
|
121
|
+
throw tileflowConfigValidationError(
|
|
122
|
+
`maps.${key}`,
|
|
123
|
+
new Error(`Tileflow workspace map key "${key}" must match the map id "${resolved2.id}".`)
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return [
|
|
127
|
+
key,
|
|
128
|
+
resolved2,
|
|
129
|
+
collectTileflowMapBuildLineage(map2),
|
|
130
|
+
normalizeSingularMapScenes(map2, resolved2.id),
|
|
131
|
+
normalizeSingularMapShots(map2, resolved2.id)
|
|
132
|
+
];
|
|
133
|
+
});
|
|
134
|
+
if (entries.length === 0) {
|
|
135
|
+
throw tileflowConfigValidationError(
|
|
136
|
+
"maps",
|
|
137
|
+
new Error("Tileflow workspace must contain at least one map.")
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
const scenes2 = /* @__PURE__ */ new Map();
|
|
141
|
+
for (const [mapId, , , mapScenes] of entries) {
|
|
142
|
+
for (const [sceneId, scene] of Object.entries(mapScenes ?? {})) {
|
|
143
|
+
if (scenes2.has(sceneId)) {
|
|
144
|
+
throw tileflowConfigValidationError(
|
|
145
|
+
`maps.${mapId}.scenes.${sceneId}`,
|
|
146
|
+
new Error(`Tileflow workspace scene "${sceneId}" is already defined by another map.`)
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
scenes2.set(sceneId, scene);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const shots2 = /* @__PURE__ */ new Map();
|
|
153
|
+
for (const [mapId, , , , mapShots] of entries) {
|
|
154
|
+
for (const [shotId, shot] of Object.entries(mapShots ?? {})) {
|
|
155
|
+
if (shots2.has(shotId)) {
|
|
156
|
+
throw tileflowConfigValidationError(
|
|
157
|
+
`maps.${mapId}.shots.${shotId}`,
|
|
158
|
+
new Error(`Tileflow workspace shot "${shotId}" is already defined by another map.`)
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
shots2.set(shotId, shot);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
mapMetadata: Object.fromEntries(
|
|
166
|
+
entries.map(([id, map2, lineage]) => [id, { id, lineage, version: map2.version }])
|
|
167
|
+
),
|
|
168
|
+
maps: Object.fromEntries(entries.map(([id, map2]) => [id, map2])),
|
|
169
|
+
...scenes2.size > 0 ? { scenes: Object.fromEntries(scenes2) } : {},
|
|
170
|
+
...shots2.size > 0 ? { shots: Object.fromEntries(shots2) } : {}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
const map = input;
|
|
174
|
+
const resolved = parseTileflowCatalogMap(map, "");
|
|
175
|
+
let scenes;
|
|
176
|
+
try {
|
|
177
|
+
scenes = normalizeSingularMapScenes(map, resolved.id);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
throw tileflowConfigValidationError("scenes", error);
|
|
180
|
+
}
|
|
181
|
+
let shots;
|
|
182
|
+
try {
|
|
183
|
+
shots = normalizeSingularMapShots(map, resolved.id);
|
|
184
|
+
} catch (error) {
|
|
185
|
+
throw tileflowConfigValidationError("shots", error);
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
mapMetadata: {
|
|
189
|
+
[resolved.id]: {
|
|
190
|
+
id: resolved.id,
|
|
191
|
+
lineage: collectTileflowMapBuildLineage(map),
|
|
192
|
+
version: resolved.version
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
maps: { [resolved.id]: resolved },
|
|
196
|
+
...scenes ? { scenes } : {},
|
|
197
|
+
...shots ? { shots } : {}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function parseTileflowCatalogMap(map, path) {
|
|
201
|
+
try {
|
|
202
|
+
return parseTileflowMap(map);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
throw tileflowConfigValidationError(path, error);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function getTileflowAuthoringMaps(input, project, allowWorkspace) {
|
|
208
|
+
if (allowWorkspace && isRecord(input) && isRecord(input.maps)) {
|
|
209
|
+
const maps = input.maps;
|
|
210
|
+
return Object.fromEntries(
|
|
211
|
+
Object.keys(project.maps).map((mapId2) => [mapId2, maps[mapId2]])
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
const [mapId] = Object.keys(project.maps);
|
|
215
|
+
return mapId ? { [mapId]: input } : {};
|
|
216
|
+
}
|
|
217
|
+
function tileflowConfigValidationError(path, error) {
|
|
218
|
+
if (error instanceof TileflowValidationError) return error;
|
|
219
|
+
if (error instanceof TileflowResolvedMapValidationError) {
|
|
220
|
+
return new TileflowValidationError(
|
|
221
|
+
error.messages.map((message) => ({
|
|
222
|
+
...message,
|
|
223
|
+
path: prefixValidationPath(path, message.path)
|
|
224
|
+
}))
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
return new TileflowValidationError([
|
|
228
|
+
{
|
|
229
|
+
level: "error",
|
|
230
|
+
path: path || "map",
|
|
231
|
+
message: error instanceof Error ? error.message : String(error)
|
|
232
|
+
}
|
|
233
|
+
]);
|
|
234
|
+
}
|
|
235
|
+
function prefixValidationPath(prefix, path) {
|
|
236
|
+
const child = path === "config" ? "" : path;
|
|
237
|
+
if (!prefix) return child || "map";
|
|
238
|
+
return child ? `${prefix}.${child}` : prefix;
|
|
239
|
+
}
|
|
240
|
+
function normalizeSingularMapScenes(map, mapId) {
|
|
241
|
+
if (!map.scenes) return void 0;
|
|
242
|
+
return Object.fromEntries(
|
|
243
|
+
Object.entries(map.scenes).map(([sceneId, scene]) => {
|
|
244
|
+
const normalizedSceneId = tileflowCaptureSceneNameSchema.parse(sceneId);
|
|
245
|
+
return [normalizedSceneId, { ...scene, map: mapId }];
|
|
246
|
+
})
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
function normalizeSingularMapShots(map, mapId) {
|
|
250
|
+
if (!map.shots) return void 0;
|
|
251
|
+
return Object.fromEntries(
|
|
252
|
+
Object.entries(map.shots).map(([shotId, shot]) => {
|
|
253
|
+
const normalizedShotId = tileflowCaptureShotNameSchema.parse(shotId);
|
|
254
|
+
return [normalizedShotId, { ...shot, map: mapId }];
|
|
255
|
+
})
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
function getTileflowMapNames(project) {
|
|
259
|
+
return Object.keys(project.maps);
|
|
260
|
+
}
|
|
261
|
+
function getFirstTileflowMapName(project) {
|
|
262
|
+
const [mapName] = getTileflowMapNames(project);
|
|
263
|
+
if (!mapName) {
|
|
264
|
+
throw new Error("Tileflow config must define at least one map.");
|
|
265
|
+
}
|
|
266
|
+
return mapName;
|
|
267
|
+
}
|
|
268
|
+
var localRequire = createRequire(import.meta.url);
|
|
269
|
+
function collectTileflowConfigInputs(configPath, cwd) {
|
|
270
|
+
const roots = [canonicalPath(cwd), canonicalPath(dirname(resolve(configPath)))];
|
|
271
|
+
const inputs = /* @__PURE__ */ new Set([canonicalPath(configPath)]);
|
|
272
|
+
const pending = [localRequire.cache[canonicalPath(configPath)]];
|
|
273
|
+
const visited = /* @__PURE__ */ new Set();
|
|
274
|
+
while (pending.length > 0) {
|
|
275
|
+
const module = pending.pop();
|
|
276
|
+
if (!module || visited.has(module.filename)) continue;
|
|
277
|
+
visited.add(module.filename);
|
|
278
|
+
const path = canonicalPath(module.filename);
|
|
279
|
+
if (!path.split(sep).includes("node_modules") && roots.some((root) => isPathWithin(root, path))) {
|
|
280
|
+
inputs.add(path);
|
|
281
|
+
}
|
|
282
|
+
pending.push(...module.children);
|
|
283
|
+
}
|
|
284
|
+
for (const cachePath of Object.keys(localRequire.cache)) {
|
|
285
|
+
const path = canonicalPath(cachePath);
|
|
286
|
+
if (!path.split(sep).includes("node_modules") && roots.some((root) => isPathWithin(root, path))) {
|
|
287
|
+
inputs.add(path);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return [...inputs].sort();
|
|
291
|
+
}
|
|
292
|
+
function clearTileflowLocalModuleCache(configPath, cwd) {
|
|
293
|
+
const roots = [canonicalPath(cwd), canonicalPath(dirname(resolve(configPath)))];
|
|
294
|
+
for (const cachePath of Object.keys(localRequire.cache)) {
|
|
295
|
+
if (cachePath.split(sep).includes("node_modules")) continue;
|
|
296
|
+
if (roots.some((root) => isPathWithin(root, canonicalPath(cachePath)))) {
|
|
297
|
+
delete localRequire.cache[cachePath];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function canonicalPath(path) {
|
|
302
|
+
try {
|
|
303
|
+
return realpathSync.native(resolve(path));
|
|
304
|
+
} catch {
|
|
305
|
+
return resolve(path);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function isRecord(value) {
|
|
309
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export {
|
|
313
|
+
defaultTileflowApiUrl,
|
|
314
|
+
defaultTileflowConfigPath,
|
|
315
|
+
defaultTileflowManifestPath,
|
|
316
|
+
TileflowValidationError,
|
|
317
|
+
loadTileflowConfig,
|
|
318
|
+
loadTileflowConfigWithInputs,
|
|
319
|
+
loadValidTileflowConfig,
|
|
320
|
+
loadValidTileflowConfigWithInputs,
|
|
321
|
+
assertValidTileflowConfig,
|
|
322
|
+
getTileflowMapNames,
|
|
323
|
+
getFirstTileflowMapName
|
|
324
|
+
};
|