@tileflow/dev 0.1.0-alpha.3 → 0.1.0-alpha.30

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.
Files changed (41) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +201 -5
  3. package/THIRD_PARTY_NOTICES.md +87 -0
  4. package/dist/artifacts.d.ts +265 -0
  5. package/dist/artifacts.js +81 -0
  6. package/dist/chunk-6MGFMKG3.js +284 -0
  7. package/dist/chunk-7C4F6GAX.js +170 -0
  8. package/dist/chunk-A2VTI43Y.js +1824 -0
  9. package/dist/chunk-D4OE4ITL.js +13 -0
  10. package/dist/chunk-KDFTE4Q5.js +156 -0
  11. package/dist/chunk-L56FLV4R.js +3061 -0
  12. package/dist/chunk-ONYQNLNA.js +1108 -0
  13. package/dist/chunk-UTRO4IBQ.js +671 -0
  14. package/dist/chunk-XHJBCVBB.js +241 -0
  15. package/dist/config.d.ts +33 -0
  16. package/dist/config.js +27 -0
  17. package/dist/fonts.d.ts +47 -0
  18. package/dist/fonts.js +16 -0
  19. package/dist/icons.d.ts +337 -0
  20. package/dist/icons.js +39 -0
  21. package/dist/inspect.d.ts +149 -0
  22. package/dist/inspect.js +805 -0
  23. package/dist/preview-assets-MVUJJ5XR.js +148 -0
  24. package/dist/preview.d.ts +71 -0
  25. package/dist/preview.js +4286 -0
  26. package/dist/server.d.ts +82 -0
  27. package/dist/server.js +2094 -0
  28. package/dist/tilesets.d.ts +89 -0
  29. package/dist/tilesets.js +6 -0
  30. package/dist/validation.d.ts +65 -0
  31. package/dist/validation.js +24 -0
  32. package/docs/artifact-lifecycle.md +152 -0
  33. package/docs/bounded-pmtiles-resource-inspection.md +21 -0
  34. package/docs/bounded-vector-feature-inspection.md +100 -0
  35. package/docs/local-comparison-workbench-and-compiler-inspection.md +249 -0
  36. package/docs/native-artifacts.md +285 -0
  37. package/docs/native-icons.md +129 -0
  38. package/docs/structured-config-inspection-and-diagnostics.md +39 -0
  39. package/package.json +77 -13
  40. package/dist/index.d.ts +0 -54
  41. package/dist/index.js +0 -314
@@ -0,0 +1,170 @@
1
+ // src/asset-directories.ts
2
+ import { realpath, stat } from "fs/promises";
3
+ import { createRequire } from "module";
4
+ import { dirname, isAbsolute, relative, resolve, sep } from "path";
5
+ import {
6
+ isTileflowLocalDirectory,
7
+ tileflowLocalDirectoryMessage
8
+ } from "@tileflow/core";
9
+ var TileflowAssetDirectoryError = class extends Error {
10
+ code = "ASSET_DIRECTORY_INVALID";
11
+ issues;
12
+ phase = "asset-directory-resolution";
13
+ constructor(kind, issues) {
14
+ super(
15
+ [
16
+ `Invalid Tileflow ${kind} directories`,
17
+ ...issues.map((issue) => `- ${issue.path}: ${issue.message}`)
18
+ ].join("\n")
19
+ );
20
+ this.name = "TileflowAssetDirectoryError";
21
+ this.issues = issues;
22
+ }
23
+ };
24
+ async function resolveTileflowAssetDirectories(directories, options) {
25
+ const issues = [];
26
+ let realCwd;
27
+ let realBaseDirectory;
28
+ try {
29
+ realCwd = await realpath(options.cwd);
30
+ if (!(await stat(realCwd)).isDirectory()) throw new Error("Working tree is not a directory");
31
+ } catch (error) {
32
+ throw new TileflowAssetDirectoryError(options.kind, [
33
+ { message: filesystemMessage(error, "Selected working tree was not found"), path: "cwd" }
34
+ ]);
35
+ }
36
+ try {
37
+ realBaseDirectory = await realpath(options.baseDirectory ?? options.cwd);
38
+ if (!(await stat(realBaseDirectory)).isDirectory()) {
39
+ throw new Error("Config base is not a directory");
40
+ }
41
+ if (!isPathInside(realCwd, realBaseDirectory)) {
42
+ throw new Error("Config base directory escapes the selected working tree");
43
+ }
44
+ } catch (error) {
45
+ throw new TileflowAssetDirectoryError(options.kind, [
46
+ {
47
+ message: filesystemMessage(error, "Config base directory was not found"),
48
+ path: "baseDirectory"
49
+ }
50
+ ]);
51
+ }
52
+ const result = [];
53
+ const seen = /* @__PURE__ */ new Map();
54
+ for (const [index, directory] of directories.entries()) {
55
+ const configPath = `${options.configPath}.${index + (options.ordinalOffset ?? 0)}`;
56
+ let candidate;
57
+ let containmentRoot;
58
+ let packageOwned = false;
59
+ if (typeof directory === "string") {
60
+ if (!isTileflowLocalDirectory(directory)) {
61
+ issues.push({
62
+ message: tileflowLocalDirectoryMessage,
63
+ path: configPath
64
+ });
65
+ continue;
66
+ }
67
+ candidate = resolve(realBaseDirectory, directory);
68
+ containmentRoot = realCwd;
69
+ } else if (isPackageDirectory(directory)) {
70
+ packageOwned = true;
71
+ let packageRoot;
72
+ try {
73
+ validatePackageDirectory(directory);
74
+ const requireFromProject = createRequire(resolve(realCwd, "__tileflow_config__.cjs"));
75
+ let packageJson;
76
+ try {
77
+ packageJson = requireFromProject.resolve(`${directory.package}/package.json`);
78
+ } catch {
79
+ packageJson = createRequire(import.meta.url).resolve(`${directory.package}/package.json`);
80
+ }
81
+ packageRoot = dirname(packageJson);
82
+ containmentRoot = await realpath(packageRoot);
83
+ candidate = resolve(containmentRoot, ...directory.path.split("/"));
84
+ } catch (error) {
85
+ issues.push({
86
+ message: error instanceof Error ? error.message : "Package directory could not be resolved",
87
+ path: configPath
88
+ });
89
+ continue;
90
+ }
91
+ } else {
92
+ issues.push({
93
+ message: "Expected a relative directory or imported package-directory descriptor",
94
+ path: configPath
95
+ });
96
+ continue;
97
+ }
98
+ try {
99
+ const realCandidate = await realpath(candidate);
100
+ if (!(await stat(realCandidate)).isDirectory()) {
101
+ throw new Error("Asset source must be a directory");
102
+ }
103
+ if (!isPathInside(containmentRoot, realCandidate)) {
104
+ throw new Error(
105
+ packageOwned ? "Package asset directory escapes its installed package" : "Asset directory escapes the selected working tree"
106
+ );
107
+ }
108
+ if (options.target === "hosted" && !packageOwned && !isPathInside(realCwd, realCandidate)) {
109
+ throw new Error("Hosted asset directories must remain inside the selected working tree");
110
+ }
111
+ const previous = seen.get(realCandidate);
112
+ if (previous) {
113
+ issues.push({ message: `Directory duplicates ${previous}`, path: configPath });
114
+ continue;
115
+ }
116
+ seen.set(realCandidate, configPath);
117
+ result.push({
118
+ authoring: directory,
119
+ configPath,
120
+ containmentRoot,
121
+ packageOwned,
122
+ realPath: realCandidate,
123
+ watch: !packageOwned
124
+ });
125
+ } catch (error) {
126
+ issues.push({
127
+ message: filesystemMessage(error, "Asset directory was not found"),
128
+ path: configPath
129
+ });
130
+ }
131
+ }
132
+ if (issues.length > 0) throw new TileflowAssetDirectoryError(options.kind, issues);
133
+ return result;
134
+ }
135
+ function isPackageDirectory(value) {
136
+ return Boolean(
137
+ value && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype && value.kind === "package-directory"
138
+ );
139
+ }
140
+ function validatePackageDirectory(directory) {
141
+ const keys = Object.keys(directory).sort();
142
+ if (keys.join(",") !== "kind,package,path") {
143
+ throw new Error("Package directory accepts exactly kind, package, and path");
144
+ }
145
+ if (!/^(?:@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)$/u.test(
146
+ directory.package
147
+ )) {
148
+ throw new Error("Package directory has an invalid npm package name");
149
+ }
150
+ if (!directory.path || directory.path.startsWith("/") || directory.path.includes("\\") || directory.path.split("/").some((segment) => !segment || segment === "." || segment === "..")) {
151
+ throw new Error("Package directory path must be a portable package-relative path");
152
+ }
153
+ }
154
+ function isPathInside(root, candidate) {
155
+ const pathFromRoot = relative(root, candidate);
156
+ return pathFromRoot === "" || !isAbsolute(pathFromRoot) && pathFromRoot !== ".." && !pathFromRoot.startsWith(`..${sep}`);
157
+ }
158
+ function filesystemMessage(error, fallback) {
159
+ if (error && typeof error === "object" && "code" in error) {
160
+ const code = String(error.code ?? "");
161
+ if (code === "ENOENT") return fallback;
162
+ if (code === "EACCES" || code === "EPERM") return "Asset directory is not readable";
163
+ }
164
+ return error instanceof Error && error.message ? error.message : fallback;
165
+ }
166
+
167
+ export {
168
+ TileflowAssetDirectoryError,
169
+ resolveTileflowAssetDirectories
170
+ };