@tileflow/dev 0.1.0-alpha.2 → 0.1.0-alpha.21
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/GENERATED_OUTPUT_LICENSE.md +21 -0
- package/LICENSE +201 -0
- package/NOTICE +9 -0
- package/README.md +547 -2
- package/THIRD_PARTY_NOTICES.md +69 -0
- package/TRADEMARKS.md +10 -0
- package/dist/artifacts.d.ts +191 -0
- package/dist/artifacts.js +71 -0
- package/dist/chunk-6MGFMKG3.js +284 -0
- package/dist/chunk-BL3FK4GO.js +170 -0
- package/dist/chunk-CENQR5Q2.js +844 -0
- package/dist/chunk-D4OE4ITL.js +13 -0
- package/dist/chunk-KDFTE4Q5.js +156 -0
- package/dist/chunk-KH7CMHT3.js +2069 -0
- package/dist/chunk-LNCTVFUD.js +236 -0
- package/dist/chunk-MIGBHCXX.js +4222 -0
- package/dist/chunk-MKPSQSMX.js +805 -0
- package/dist/chunk-ONYQNLNA.js +1108 -0
- package/dist/chunk-RSBV4L2Y.js +671 -0
- package/dist/chunk-XTRHREXO.js +1688 -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.d.ts +136 -0
- package/dist/icons.js +17 -0
- package/dist/index.d.ts +13 -54
- package/dist/index.js +171 -297
- package/dist/inspect.d.ts +149 -0
- package/dist/inspect.js +18 -0
- package/dist/preview-assets-6LYL7GP7.js +145 -0
- package/dist/preview.d.ts +69 -0
- package/dist/preview.js +18 -0
- package/dist/server.d.ts +81 -0
- package/dist/server.js +48 -0
- package/dist/tilesets-C0tGeenP.d.ts +94 -0
- package/dist/tilesets.d.ts +1 -0
- package/dist/tilesets.js +6 -0
- package/dist/validation.d.ts +63 -0
- package/dist/validation.js +24 -0
- package/package.json +80 -7
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sanitizeDiagnosticSecrets
|
|
3
|
+
} from "./chunk-KDFTE4Q5.js";
|
|
4
|
+
|
|
5
|
+
// src/validation.ts
|
|
6
|
+
import { realpathSync } from "fs";
|
|
7
|
+
import { isAbsolute, relative, resolve, sep, win32 } from "path";
|
|
8
|
+
import { compareCodeUnits } from "@tileflow/core";
|
|
9
|
+
var tileflowCommandDocumentSchemaVersion = 1;
|
|
10
|
+
function createTileflowCommandSummary(input) {
|
|
11
|
+
return {
|
|
12
|
+
schemaVersion: tileflowCommandDocumentSchemaVersion,
|
|
13
|
+
command: normalizeCommandField(input.command, "command"),
|
|
14
|
+
ok: input.ok,
|
|
15
|
+
phase: normalizePhase(input.phase, "command"),
|
|
16
|
+
code: normalizeCode(input.code, input.ok ? "COMMAND_OK" : "COMMAND_FAILED"),
|
|
17
|
+
path: boundText(input.path ?? "", 300),
|
|
18
|
+
severity: input.severity,
|
|
19
|
+
message: boundText(input.message.replace(/[\r\n]+/gu, " ").trim(), 300),
|
|
20
|
+
suggestion: boundText(input.suggestion.replace(/[\r\n]+/gu, " ").trim(), 300)
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function createTileflowStructuredDiagnostics(error, cwd, defaults) {
|
|
24
|
+
const inheritedCode = optionalField(error, "code");
|
|
25
|
+
const inheritedDomain = optionalField(error, "domain") ?? optionalField(error, "owner") ?? optionalNestedField(error, "domain") ?? optionalNestedField(error, "owner");
|
|
26
|
+
const inheritedLevel = optionalField(error, "level") ?? optionalNestedField(error, "level");
|
|
27
|
+
const inheritedMessage = optionalField(error, "message") ?? optionalNestedField(error, "message");
|
|
28
|
+
const inheritedPath = optionalField(error, "path") ?? optionalNestedField(error, "path");
|
|
29
|
+
const inheritedPhase = optionalField(error, "phase") ?? optionalNestedField(error, "phase");
|
|
30
|
+
const inheritedSeverity = optionalField(error, "severity") ?? optionalNestedField(error, "severity");
|
|
31
|
+
const inheritedSuggestion = optionalField(error, "suggestion") ?? optionalNestedField(error, "suggestion");
|
|
32
|
+
const inheritedTarget = optionalField(error, "target") ?? optionalNestedField(error, "target");
|
|
33
|
+
const issues = getIssues(error);
|
|
34
|
+
const candidates = issues.length ? issues : [
|
|
35
|
+
{
|
|
36
|
+
message: inheritedMessage ?? (error instanceof Error ? error.message : "The Tileflow command failed."),
|
|
37
|
+
path: inheritedPath ?? ""
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
const diagnostics = candidates.map((issue) => {
|
|
41
|
+
const phase = normalizePhase(issue.phase ?? inheritedPhase, defaults.phase);
|
|
42
|
+
const code = normalizeCode(issue.code ?? inheritedCode, defaults.code);
|
|
43
|
+
const severity = normalizeSeverity(
|
|
44
|
+
issue.severity ?? issue.level ?? inheritedSeverity ?? inheritedLevel,
|
|
45
|
+
defaults.severity ?? "error"
|
|
46
|
+
);
|
|
47
|
+
const domain = sanitizeDiagnosticContext(issue.domain ?? issue.owner ?? inheritedDomain, cwd);
|
|
48
|
+
const target = sanitizeDiagnosticContext(issue.target ?? inheritedTarget, cwd);
|
|
49
|
+
const suggestion = issue.suggestion ?? inheritedSuggestion;
|
|
50
|
+
return {
|
|
51
|
+
phase,
|
|
52
|
+
code,
|
|
53
|
+
...domain ? { domain } : {},
|
|
54
|
+
path: boundText(sanitizePath(issue.path ?? inheritedPath ?? "", cwd), 300),
|
|
55
|
+
...target ? { target } : {},
|
|
56
|
+
severity,
|
|
57
|
+
message: boundText(sanitizeMessage(issue.message, cwd), 300),
|
|
58
|
+
suggestion: suggestion ? boundText(sanitizeMessage(suggestion, cwd), 300) : suggestionForDiagnostic(code, phase)
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
diagnostics.sort(compareDiagnostics);
|
|
62
|
+
return diagnostics.filter(
|
|
63
|
+
(diagnostic, index) => index === 0 || JSON.stringify(diagnostic) !== JSON.stringify(diagnostics[index - 1])
|
|
64
|
+
).slice(0, 32);
|
|
65
|
+
}
|
|
66
|
+
function createTileflowCommandFailureDocument(command, error, cwd, defaults) {
|
|
67
|
+
const diagnostics = createTileflowStructuredDiagnostics(error, cwd, defaults);
|
|
68
|
+
const primary = diagnostics[0] ?? {
|
|
69
|
+
phase: normalizePhase(defaults.phase, "command"),
|
|
70
|
+
code: normalizeCode(defaults.code, "COMMAND_FAILED"),
|
|
71
|
+
path: "",
|
|
72
|
+
severity: defaults.severity ?? "error",
|
|
73
|
+
message: "The Tileflow command failed.",
|
|
74
|
+
suggestion: "Review the command input and run it again."
|
|
75
|
+
};
|
|
76
|
+
return {
|
|
77
|
+
schemaVersion: tileflowCommandDocumentSchemaVersion,
|
|
78
|
+
command: normalizeCommandField(command, "command"),
|
|
79
|
+
ok: false,
|
|
80
|
+
phase: primary.phase,
|
|
81
|
+
code: primary.code,
|
|
82
|
+
...primary.domain ? { domain: primary.domain } : {},
|
|
83
|
+
path: primary.path,
|
|
84
|
+
...primary.target ? { target: primary.target } : {},
|
|
85
|
+
severity: primary.severity,
|
|
86
|
+
message: primary.message,
|
|
87
|
+
suggestion: primary.suggestion,
|
|
88
|
+
diagnostics
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function serializeTileflowCommandDocument(value) {
|
|
92
|
+
return `${JSON.stringify(value, null, 2)}
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
function getIssues(error) {
|
|
96
|
+
if (!error || typeof error !== "object") return [];
|
|
97
|
+
const containers = [];
|
|
98
|
+
for (const key of ["diagnostics", "messages", "issues"]) {
|
|
99
|
+
const value = error[key];
|
|
100
|
+
if (Array.isArray(value)) containers.push(value);
|
|
101
|
+
}
|
|
102
|
+
const details = error.details;
|
|
103
|
+
if (details && typeof details === "object") {
|
|
104
|
+
const diagnostics = details.diagnostics;
|
|
105
|
+
if (Array.isArray(diagnostics)) containers.push(diagnostics);
|
|
106
|
+
}
|
|
107
|
+
return containers.flatMap(
|
|
108
|
+
(container) => container.flatMap((entry) => {
|
|
109
|
+
if (!entry || typeof entry !== "object") return [];
|
|
110
|
+
const candidate = entry;
|
|
111
|
+
if (typeof candidate.message !== "string") return [];
|
|
112
|
+
return [
|
|
113
|
+
{
|
|
114
|
+
...typeof candidate.code === "string" ? { code: candidate.code } : {},
|
|
115
|
+
...typeof candidate.domain === "string" ? { domain: candidate.domain } : {},
|
|
116
|
+
...typeof candidate.level === "string" ? { level: candidate.level } : {},
|
|
117
|
+
message: candidate.message,
|
|
118
|
+
...typeof candidate.owner === "string" ? { owner: candidate.owner } : {},
|
|
119
|
+
...typeof candidate.path === "string" ? { path: candidate.path } : {},
|
|
120
|
+
...typeof candidate.phase === "string" ? { phase: candidate.phase } : {},
|
|
121
|
+
...typeof candidate.severity === "string" ? { severity: candidate.severity } : {},
|
|
122
|
+
...typeof candidate.suggestion === "string" ? { suggestion: candidate.suggestion } : {},
|
|
123
|
+
...typeof candidate.target === "string" ? { target: candidate.target } : {}
|
|
124
|
+
}
|
|
125
|
+
];
|
|
126
|
+
})
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
function sanitizeMessage(value, cwd) {
|
|
130
|
+
let sanitized = value;
|
|
131
|
+
for (const root of localPathAliases(cwd)) sanitized = sanitized.replaceAll(root, ".");
|
|
132
|
+
sanitized = sanitized.replace(/[\r\n]+/gu, " ").trim();
|
|
133
|
+
sanitized = sanitized.replace(/https?:\/\/[^\s'")<>]+/giu, (url) => {
|
|
134
|
+
try {
|
|
135
|
+
return new URL(url.replace(/[),.;]+$/u, "")).origin;
|
|
136
|
+
} catch {
|
|
137
|
+
return "(resource URL)";
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
sanitized = sanitized.replace(/(^|[\s'"(])[A-Za-z]:[\\/][^\s'")]+/gu, "$1(external path)");
|
|
141
|
+
sanitized = sanitized.replace(/(^|[\s'"(])(?:\\\\|\/\/)[^\s'")]+/gu, "$1(external path)");
|
|
142
|
+
sanitized = sanitized.replace(/(^|[\s'"(])\/[^\s'")]+/gu, "$1(external path)");
|
|
143
|
+
return sanitizeDiagnosticSecrets(sanitized);
|
|
144
|
+
}
|
|
145
|
+
function sanitizePath(value, cwd) {
|
|
146
|
+
if (!value) return "";
|
|
147
|
+
if (win32.isAbsolute(value) && !isAbsolute(value)) return "(external)";
|
|
148
|
+
if (!isAbsolute(value)) return sanitizeDiagnosticSecrets(value.replaceAll("\\", "/"));
|
|
149
|
+
const local = relative(canonicalPath(cwd), canonicalPath(value)).replaceAll(sep, "/");
|
|
150
|
+
return local.startsWith("../") || local === ".." ? "(external)" : local || ".";
|
|
151
|
+
}
|
|
152
|
+
function sanitizeDiagnosticContext(value, cwd) {
|
|
153
|
+
if (!value) return void 0;
|
|
154
|
+
const sanitized = boundText(sanitizeMessage(value, cwd), 300);
|
|
155
|
+
return sanitized || void 0;
|
|
156
|
+
}
|
|
157
|
+
function localPathAliases(path) {
|
|
158
|
+
return [.../* @__PURE__ */ new Set([resolve(path), canonicalPath(path)])].sort(
|
|
159
|
+
(left, right) => right.length - left.length
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
function canonicalPath(path) {
|
|
163
|
+
try {
|
|
164
|
+
return realpathSync.native(resolve(path));
|
|
165
|
+
} catch {
|
|
166
|
+
return resolve(path);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function suggestionForDiagnostic(code, phase) {
|
|
170
|
+
if (code === "INVALID_TARGET" || phase === "command-validation") {
|
|
171
|
+
return "Use a documented command option and run the command again.";
|
|
172
|
+
}
|
|
173
|
+
if (phase === "config-load") {
|
|
174
|
+
return "Check the config path and its installed imports, then run the command again.";
|
|
175
|
+
}
|
|
176
|
+
if (phase === "config-validation" || code === "CONFIG_INVALID") {
|
|
177
|
+
return "Edit the reported config path to match the Tileflow config reference, then validate again.";
|
|
178
|
+
}
|
|
179
|
+
if (phase.includes("icon") || code.includes("ICON")) {
|
|
180
|
+
return "Fix the reported icon input and run validation again.";
|
|
181
|
+
}
|
|
182
|
+
if (phase.includes("font") || code.includes("FONT") || code.includes("GLYPH")) {
|
|
183
|
+
return "Fix the reported font or glyph input and run validation again.";
|
|
184
|
+
}
|
|
185
|
+
if (phase === "style-validation" || code === "STYLE_INVALID") {
|
|
186
|
+
return "Adjust the reported semantic map value and run validation again.";
|
|
187
|
+
}
|
|
188
|
+
if (phase === "hosted-validation" || code === "HOSTED_INCOMPATIBLE") {
|
|
189
|
+
return "Use a supported Hosted input or validate with the local target.";
|
|
190
|
+
}
|
|
191
|
+
if (phase === "config-inspection") {
|
|
192
|
+
return "Resolve the reported config diagnostic before inspecting the map again.";
|
|
193
|
+
}
|
|
194
|
+
return "Review the reported path and run the command again.";
|
|
195
|
+
}
|
|
196
|
+
function compareDiagnostics(left, right) {
|
|
197
|
+
return diagnosticSeverityRank(left.severity) - diagnosticSeverityRank(right.severity) || compareCodeUnits(left.path, right.path) || compareCodeUnits(left.domain ?? "", right.domain ?? "") || compareCodeUnits(left.target ?? "", right.target ?? "") || compareCodeUnits(left.phase, right.phase) || compareCodeUnits(left.code, right.code) || compareCodeUnits(left.message, right.message) || compareCodeUnits(left.suggestion, right.suggestion);
|
|
198
|
+
}
|
|
199
|
+
function diagnosticSeverityRank(severity) {
|
|
200
|
+
return severity === "error" ? 0 : severity === "warning" ? 1 : 2;
|
|
201
|
+
}
|
|
202
|
+
function normalizeSeverity(value, fallback) {
|
|
203
|
+
return value === "error" || value === "info" || value === "warning" ? value : fallback;
|
|
204
|
+
}
|
|
205
|
+
function normalizeCode(value, fallback) {
|
|
206
|
+
const normalized = sanitizeDiagnosticSecrets(value ?? fallback).toUpperCase().replace(/[^A-Z0-9_]/gu, "_").slice(0, 64);
|
|
207
|
+
return normalized || fallback;
|
|
208
|
+
}
|
|
209
|
+
function normalizePhase(value, fallback) {
|
|
210
|
+
const normalized = sanitizeDiagnosticSecrets(value ?? fallback).toLowerCase().replace(/[^a-z0-9-]/gu, "-").slice(0, 64);
|
|
211
|
+
return normalized || fallback;
|
|
212
|
+
}
|
|
213
|
+
function normalizeCommandField(value, fallback) {
|
|
214
|
+
const normalized = sanitizeDiagnosticSecrets(value).toLowerCase().replace(/[^a-z0-9 ._-]/gu, "").trim().slice(0, 64);
|
|
215
|
+
return normalized || fallback;
|
|
216
|
+
}
|
|
217
|
+
function optionalField(value, key) {
|
|
218
|
+
if (!value || typeof value !== "object") return void 0;
|
|
219
|
+
const field = value[key];
|
|
220
|
+
return typeof field === "string" && field.trim() ? field : void 0;
|
|
221
|
+
}
|
|
222
|
+
function optionalNestedField(value, key) {
|
|
223
|
+
if (!value || typeof value !== "object") return void 0;
|
|
224
|
+
return optionalField(value.details, key);
|
|
225
|
+
}
|
|
226
|
+
function boundText(value, limit) {
|
|
227
|
+
return value.length <= limit ? value : `${value.slice(0, limit - 1)}\u2026`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export {
|
|
231
|
+
tileflowCommandDocumentSchemaVersion,
|
|
232
|
+
createTileflowCommandSummary,
|
|
233
|
+
createTileflowStructuredDiagnostics,
|
|
234
|
+
createTileflowCommandFailureDocument,
|
|
235
|
+
serializeTileflowCommandDocument
|
|
236
|
+
};
|