tileflow 0.1.0-alpha.7 → 0.1.0-alpha.8
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 +11 -0
- package/dist/index.js +1001 -392
- package/docs/build-artifacts.md +7 -0
- package/docs/command-families.md +5 -1
- package/docs/hosted-authentication-and-deploy.md +3 -2
- package/docs/native-artifacts.md +169 -0
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -7,58 +7,59 @@ import { createHash as createHash4, randomBytes as randomBytes2 } from "crypto";
|
|
|
7
7
|
import { existsSync, readFileSync, realpathSync } from "fs";
|
|
8
8
|
import { readFile as readFile7, writeFile as writeFile2 } from "fs/promises";
|
|
9
9
|
import { hostname } from "os";
|
|
10
|
-
import { dirname as
|
|
10
|
+
import { dirname as dirname12, isAbsolute as isAbsolute5, relative as relative5, resolve as resolve8, sep as sep5 } from "path";
|
|
11
11
|
import { createInterface } from "readline/promises";
|
|
12
12
|
import pc6 from "picocolors";
|
|
13
13
|
import { createLocalCoordinates, setupCoordinates } from "@tileflow/coordinates-runtime";
|
|
14
14
|
import {
|
|
15
|
-
auditTileflowMapThemeValues,
|
|
16
|
-
getTileflowStyleFontFaces,
|
|
17
|
-
parseResolvedTileflowMap as
|
|
15
|
+
auditTileflowMapThemeValues as auditTileflowMapThemeValues2,
|
|
16
|
+
getTileflowStyleFontFaces as getTileflowStyleFontFaces2,
|
|
17
|
+
parseResolvedTileflowMap as parseResolvedTileflowMap5,
|
|
18
18
|
tileflowMapIdSchema as tileflowMapIdSchema2
|
|
19
19
|
} from "@tileflow/core";
|
|
20
20
|
import {
|
|
21
|
-
createTileflowMapBuildManifest
|
|
21
|
+
createTileflowMapBuildManifest as createTileflowMapBuildManifest2
|
|
22
22
|
} from "@tileflow/core/build";
|
|
23
23
|
import {
|
|
24
|
-
parseTileflowRuntimeManifest
|
|
24
|
+
parseTileflowRuntimeManifest as parseTileflowRuntimeManifest2
|
|
25
25
|
} from "@tileflow/core/manifest";
|
|
26
|
+
import { resolveTileflowRenderer as resolveTileflowRenderer2 } from "@tileflow/core/native-profile";
|
|
26
27
|
import {
|
|
27
28
|
createTileflowArtifactDiagnostics as createTileflowArtifactDiagnostics3,
|
|
28
29
|
createTileflowArtifactSession as createTileflowArtifactSession3,
|
|
29
|
-
createTileflowBuildProvenance,
|
|
30
|
-
createTileflowStyles,
|
|
31
|
-
prepareTileflowLocalTilesets,
|
|
30
|
+
createTileflowBuildProvenance as createTileflowBuildProvenance2,
|
|
31
|
+
createTileflowStyles as createTileflowStyles2,
|
|
32
|
+
prepareTileflowLocalTilesets as prepareTileflowLocalTilesets2,
|
|
32
33
|
writeTileflowBuildArtifacts
|
|
33
34
|
} from "@tileflow/dev/artifacts";
|
|
34
35
|
import {
|
|
35
|
-
assertValidTileflowConfig as
|
|
36
|
+
assertValidTileflowConfig as assertValidTileflowConfig3,
|
|
36
37
|
defaultTileflowApiUrl,
|
|
37
38
|
defaultTileflowConfigPath,
|
|
38
39
|
defaultTileflowManifestPath,
|
|
39
|
-
getTileflowMapNames as
|
|
40
|
-
loadTileflowConfigWithInputs as
|
|
40
|
+
getTileflowMapNames as getTileflowMapNames5,
|
|
41
|
+
loadTileflowConfigWithInputs as loadTileflowConfigWithInputs4,
|
|
41
42
|
TileflowValidationError as TileflowValidationError5
|
|
42
43
|
} from "@tileflow/dev/config";
|
|
43
44
|
import {
|
|
44
45
|
bindTileflowStyleFontBundle,
|
|
45
|
-
prepareTileflowStyleFonts,
|
|
46
|
+
prepareTileflowStyleFonts as prepareTileflowStyleFonts2,
|
|
46
47
|
TileflowFontCompilationError
|
|
47
48
|
} from "@tileflow/dev/fonts";
|
|
48
49
|
import {
|
|
49
|
-
compileTileflowIconPackages as
|
|
50
|
+
compileTileflowIconPackages as compileTileflowIconPackages3,
|
|
50
51
|
TileflowIconCompilationError as TileflowIconCompilationError3
|
|
51
52
|
} from "@tileflow/dev/icons";
|
|
52
53
|
import { resolveTileflowPreview } from "@tileflow/dev/preview";
|
|
53
54
|
import {
|
|
54
55
|
createTileflowComparisonRequestHandler,
|
|
55
|
-
createTileflowDevRequestHandler
|
|
56
|
+
createTileflowDevRequestHandler as createTileflowDevRequestHandler2
|
|
56
57
|
} from "@tileflow/dev/server";
|
|
57
58
|
import {
|
|
58
|
-
createTileflowCommandFailureDocument as
|
|
59
|
-
createTileflowCommandSummary as
|
|
60
|
-
createTileflowStructuredDiagnostics as
|
|
61
|
-
serializeTileflowCommandDocument as
|
|
59
|
+
createTileflowCommandFailureDocument as createTileflowCommandFailureDocument5,
|
|
60
|
+
createTileflowCommandSummary as createTileflowCommandSummary3,
|
|
61
|
+
createTileflowStructuredDiagnostics as createTileflowStructuredDiagnostics3,
|
|
62
|
+
serializeTileflowCommandDocument as serializeTileflowCommandDocument5,
|
|
62
63
|
TileflowStyleValidationError as TileflowStyleValidationError2
|
|
63
64
|
} from "@tileflow/dev/validation";
|
|
64
65
|
|
|
@@ -385,14 +386,14 @@ async function runExplain(options, compileStyle) {
|
|
|
385
386
|
});
|
|
386
387
|
if (!selection) throw new Error("Explain selection was not resolved.");
|
|
387
388
|
if (!output.result.ok) {
|
|
388
|
-
const
|
|
389
|
+
const failure2 = createTileflowCommandFailureDocument(
|
|
389
390
|
"explain",
|
|
390
391
|
{ diagnostics: output.structuredDiagnostics },
|
|
391
392
|
process.cwd(),
|
|
392
393
|
{ code: "COMPILATION_FAILED", phase: "compilation" }
|
|
393
394
|
);
|
|
394
395
|
const document2 = {
|
|
395
|
-
...
|
|
396
|
+
...failure2,
|
|
396
397
|
authoringManifestSchemaVersion: tileflowAuthoringManifestSchemaVersion,
|
|
397
398
|
selection,
|
|
398
399
|
compilation: output.compilation
|
|
@@ -422,12 +423,12 @@ async function runExplain(options, compileStyle) {
|
|
|
422
423
|
if (options.json) process.stdout.write(serializeTileflowCommandDocument(document));
|
|
423
424
|
else printHumanExplain(document);
|
|
424
425
|
} catch (error) {
|
|
425
|
-
const
|
|
426
|
+
const failure2 = createTileflowCommandFailureDocument("explain", error, process.cwd(), {
|
|
426
427
|
code: "EXPLAIN_FAILED",
|
|
427
428
|
phase: "compilation"
|
|
428
429
|
});
|
|
429
|
-
if (options.json) process.stderr.write(serializeTileflowCommandDocument(
|
|
430
|
-
else printHumanCommandFailure(
|
|
430
|
+
if (options.json) process.stderr.write(serializeTileflowCommandDocument(failure2));
|
|
431
|
+
else printHumanCommandFailure(failure2);
|
|
431
432
|
process.exitCode = 1;
|
|
432
433
|
}
|
|
433
434
|
}
|
|
@@ -471,12 +472,12 @@ async function runSemanticDiff(options, defaultConfigPath2) {
|
|
|
471
472
|
if (options.json) process.stdout.write(serializeTileflowCommandDocument(document));
|
|
472
473
|
else printHumanSemanticDiff(difference);
|
|
473
474
|
} catch (error) {
|
|
474
|
-
const
|
|
475
|
+
const failure2 = createTileflowCommandFailureDocument("semantic-diff", error, process.cwd(), {
|
|
475
476
|
code: "SEMANTIC_DIFF_FAILED",
|
|
476
477
|
phase: "semantic-diff"
|
|
477
478
|
});
|
|
478
|
-
if (options.json) process.stderr.write(serializeTileflowCommandDocument(
|
|
479
|
-
else printHumanCommandFailure(
|
|
479
|
+
if (options.json) process.stderr.write(serializeTileflowCommandDocument(failure2));
|
|
480
|
+
else printHumanCommandFailure(failure2);
|
|
480
481
|
process.exitCode = 1;
|
|
481
482
|
}
|
|
482
483
|
}
|
|
@@ -1215,14 +1216,14 @@ async function runCaptureWatchCommand(positionalScenes, options) {
|
|
|
1215
1216
|
} catch (error) {
|
|
1216
1217
|
if (signal.aborted || stopped) return;
|
|
1217
1218
|
unresolvedFailure = true;
|
|
1218
|
-
const
|
|
1219
|
+
const failure2 = createTileflowCaptureFailureJson(error, cwd);
|
|
1219
1220
|
emit({
|
|
1220
1221
|
event: "failed",
|
|
1221
1222
|
generation,
|
|
1222
|
-
code:
|
|
1223
|
-
phase:
|
|
1224
|
-
diagnostics:
|
|
1225
|
-
...
|
|
1223
|
+
code: failure2.code,
|
|
1224
|
+
phase: failure2.phase,
|
|
1225
|
+
diagnostics: failure2.diagnostics,
|
|
1226
|
+
...failure2.resources ? { resources: failure2.resources } : {}
|
|
1226
1227
|
});
|
|
1227
1228
|
}
|
|
1228
1229
|
};
|
|
@@ -1548,6 +1549,11 @@ function runGit(cwd, args) {
|
|
|
1548
1549
|
});
|
|
1549
1550
|
}
|
|
1550
1551
|
|
|
1552
|
+
// src/cli-version.ts
|
|
1553
|
+
function isRootCliVersionRequest(arguments_) {
|
|
1554
|
+
return arguments_.length === 1 && (arguments_[0] === "--version" || arguments_[0] === "-V");
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1551
1557
|
// src/config-inspect-command.ts
|
|
1552
1558
|
import { inspectTileflowConfig } from "@tileflow/dev/inspect";
|
|
1553
1559
|
import {
|
|
@@ -1566,18 +1572,18 @@ function registerConfigInspectCommand(inspect, dependencies) {
|
|
|
1566
1572
|
}
|
|
1567
1573
|
printHumanConfigInspection(document);
|
|
1568
1574
|
} catch (error) {
|
|
1569
|
-
const
|
|
1575
|
+
const failure2 = createTileflowCommandFailureDocument2("inspect", error, process.cwd(), {
|
|
1570
1576
|
code: "INSPECTION_FAILED",
|
|
1571
1577
|
phase: "config-inspection"
|
|
1572
1578
|
});
|
|
1573
1579
|
if (options.json) {
|
|
1574
|
-
process.stderr.write(serializeTileflowCommandDocument2(
|
|
1580
|
+
process.stderr.write(serializeTileflowCommandDocument2(failure2));
|
|
1575
1581
|
} else {
|
|
1576
|
-
console.error(`${
|
|
1577
|
-
for (const diagnostic of
|
|
1582
|
+
console.error(`${failure2.message} [${failure2.code}; ${failure2.phase}]`);
|
|
1583
|
+
for (const diagnostic of failure2.diagnostics.slice(1)) {
|
|
1578
1584
|
console.error(`- ${diagnostic.path || "(root)"}: ${diagnostic.message}`);
|
|
1579
1585
|
}
|
|
1580
|
-
console.error(`Suggestion: ${
|
|
1586
|
+
console.error(`Suggestion: ${failure2.suggestion}`);
|
|
1581
1587
|
}
|
|
1582
1588
|
process.exitCode = 1;
|
|
1583
1589
|
}
|
|
@@ -1657,19 +1663,19 @@ function registerCoordinatesCommands(program2, dependencies) {
|
|
|
1657
1663
|
coordinates,
|
|
1658
1664
|
"search",
|
|
1659
1665
|
dependencies,
|
|
1660
|
-
(options) =>
|
|
1666
|
+
(options) => parseCoordinatesRequest("search", { query: options.query })
|
|
1661
1667
|
);
|
|
1662
1668
|
registerOperation(
|
|
1663
1669
|
coordinates,
|
|
1664
1670
|
"describe",
|
|
1665
1671
|
dependencies,
|
|
1666
|
-
(options) =>
|
|
1672
|
+
(options) => parseCoordinatesRequest("describe", { id: options.id })
|
|
1667
1673
|
);
|
|
1668
1674
|
registerOperation(
|
|
1669
1675
|
coordinates,
|
|
1670
1676
|
"operations",
|
|
1671
1677
|
dependencies,
|
|
1672
|
-
(options) =>
|
|
1678
|
+
(options) => parseCoordinatesRequest("operations", { from: options.from, to: options.to })
|
|
1673
1679
|
);
|
|
1674
1680
|
registerOperation(
|
|
1675
1681
|
coordinates,
|
|
@@ -1768,9 +1774,6 @@ function hasConvenienceOptions(command2, options) {
|
|
|
1768
1774
|
const transform = options;
|
|
1769
1775
|
return transform.from !== void 0 || transform.to !== void 0 || transform.positions !== void 0;
|
|
1770
1776
|
}
|
|
1771
|
-
function parseRequest(command2, options, request) {
|
|
1772
|
-
return parseCoordinatesRequest(command2, request);
|
|
1773
|
-
}
|
|
1774
1777
|
function parseTransformRequest(options) {
|
|
1775
1778
|
let positions;
|
|
1776
1779
|
try {
|
|
@@ -1815,7 +1818,7 @@ async function readCoordinatesInput(input, signal) {
|
|
|
1815
1818
|
async function readStandardInput(signal) {
|
|
1816
1819
|
const chunks = [];
|
|
1817
1820
|
let length = 0;
|
|
1818
|
-
return new Promise((
|
|
1821
|
+
return new Promise((resolve9, reject) => {
|
|
1819
1822
|
const finish = (result) => {
|
|
1820
1823
|
process.stdin.removeListener("data", onData);
|
|
1821
1824
|
process.stdin.removeListener("end", onEnd);
|
|
@@ -1837,7 +1840,7 @@ async function readStandardInput(signal) {
|
|
|
1837
1840
|
}
|
|
1838
1841
|
chunks.push(bytes);
|
|
1839
1842
|
};
|
|
1840
|
-
const onEnd = () => finish(() =>
|
|
1843
|
+
const onEnd = () => finish(() => resolve9(decodeInput(Buffer.concat(chunks))));
|
|
1841
1844
|
const onError = () => finish(() => reject(new CoordinatesInputError("INVALID_VALUE")));
|
|
1842
1845
|
if (signal.aborted) {
|
|
1843
1846
|
onAbort();
|
|
@@ -1895,10 +1898,10 @@ function serializeCoordinatesFailure(error, command2) {
|
|
|
1895
1898
|
if (!(error instanceof CoordinatesContractError)) return void 0;
|
|
1896
1899
|
const parsed = coordinatesFailureSchema.safeParse(error.toJSON());
|
|
1897
1900
|
if (!parsed.success) return void 0;
|
|
1898
|
-
const
|
|
1901
|
+
const failure2 = parsed.data;
|
|
1899
1902
|
return new CoordinatesContractError({
|
|
1900
|
-
...
|
|
1901
|
-
command:
|
|
1903
|
+
...failure2,
|
|
1904
|
+
command: failure2.command ?? command2 ?? null
|
|
1902
1905
|
}).toJSON();
|
|
1903
1906
|
}
|
|
1904
1907
|
function serializeSetupFailure(error) {
|
|
@@ -2220,6 +2223,7 @@ import { tileflowIconPackageLimits } from "@tileflow/core";
|
|
|
2220
2223
|
var maximumHostedResponseBytes = 1024 * 1024;
|
|
2221
2224
|
var safeTextSchema = z2.string().min(1).max(300).refine((value) => !/[\p{Cc}]/u.test(value));
|
|
2222
2225
|
var safeIdentifierSchema = z2.string().min(1).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9._:-]*$/u);
|
|
2226
|
+
var safeStorageKeySchema = z2.string().min(1).max(512).regex(/^[A-Za-z0-9][A-Za-z0-9._:/-]*$/u).refine((value) => value.split("/").every((segment) => segment !== "." && segment !== ".."));
|
|
2223
2227
|
var publicHttpUrlSchema = z2.url().max(2048).refine((value) => {
|
|
2224
2228
|
const url = new URL(value);
|
|
2225
2229
|
return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password && !url.hash;
|
|
@@ -2255,7 +2259,7 @@ var hostedFontBundleResponseSchema = z2.object({
|
|
|
2255
2259
|
});
|
|
2256
2260
|
var hostedStatusStyleSchema = z2.object({
|
|
2257
2261
|
environment: safeTextSchema,
|
|
2258
|
-
key:
|
|
2262
|
+
key: safeStorageKeySchema,
|
|
2259
2263
|
mapId: safeIdentifierSchema,
|
|
2260
2264
|
size: z2.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
|
|
2261
2265
|
uploaded: z2.iso.datetime({ offset: true })
|
|
@@ -2346,7 +2350,7 @@ async function startDeviceAuthorization(appUrl, body, options = {}) {
|
|
|
2346
2350
|
async function pollDeviceToken(appUrl, authorization, input, options = {}) {
|
|
2347
2351
|
const expiresAt = Date.now() + authorization.expiresIn * 1e3;
|
|
2348
2352
|
const intervalMs = Math.max(authorization.interval, 1) * 1e3;
|
|
2349
|
-
const wait = input.sleep ?? ((milliseconds) => new Promise((
|
|
2353
|
+
const wait = input.sleep ?? ((milliseconds) => new Promise((resolve9) => setTimeout(resolve9, milliseconds)));
|
|
2350
2354
|
while (Date.now() < expiresAt) {
|
|
2351
2355
|
await wait(intervalMs);
|
|
2352
2356
|
const response = await requestHostedJson(
|
|
@@ -2676,7 +2680,7 @@ async function withHostedResponse(apiUrl, path, init, options, consume) {
|
|
|
2676
2680
|
}
|
|
2677
2681
|
function raceWithAbort(operation, signal) {
|
|
2678
2682
|
if (signal.aborted) return Promise.reject(signal.reason);
|
|
2679
|
-
return new Promise((
|
|
2683
|
+
return new Promise((resolve9, reject) => {
|
|
2680
2684
|
const cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
2681
2685
|
const onAbort = () => {
|
|
2682
2686
|
cleanup();
|
|
@@ -2686,7 +2690,7 @@ function raceWithAbort(operation, signal) {
|
|
|
2686
2690
|
operation.then(
|
|
2687
2691
|
(value) => {
|
|
2688
2692
|
cleanup();
|
|
2689
|
-
|
|
2693
|
+
resolve9(value);
|
|
2690
2694
|
},
|
|
2691
2695
|
(error) => {
|
|
2692
2696
|
cleanup();
|
|
@@ -2804,6 +2808,33 @@ function safeTransportError(error, fallback) {
|
|
|
2804
2808
|
return fallback;
|
|
2805
2809
|
}
|
|
2806
2810
|
|
|
2811
|
+
// src/hosted-native-deploy.ts
|
|
2812
|
+
import { dirname as dirname5 } from "path";
|
|
2813
|
+
import {
|
|
2814
|
+
getTileflowStyleFontFaces,
|
|
2815
|
+
parseResolvedTileflowMap as parseResolvedTileflowMap2,
|
|
2816
|
+
serializeCanonicalJson
|
|
2817
|
+
} from "@tileflow/core";
|
|
2818
|
+
import {
|
|
2819
|
+
createTileflowMapBuildManifest,
|
|
2820
|
+
parseTileflowRendererDeploymentArtifact,
|
|
2821
|
+
tileflowRendererDeploymentResponseSchema
|
|
2822
|
+
} from "@tileflow/core/build";
|
|
2823
|
+
import { parseTileflowRuntimeManifest } from "@tileflow/core/manifest";
|
|
2824
|
+
import {
|
|
2825
|
+
createTileflowBuildProvenance,
|
|
2826
|
+
createTileflowStyles,
|
|
2827
|
+
prepareTileflowHostedNativeDeployment,
|
|
2828
|
+
prepareTileflowLocalTilesets
|
|
2829
|
+
} from "@tileflow/dev/artifacts";
|
|
2830
|
+
import {
|
|
2831
|
+
assertValidTileflowConfig,
|
|
2832
|
+
getTileflowMapNames,
|
|
2833
|
+
loadTileflowConfigWithInputs as loadTileflowConfigWithInputs2
|
|
2834
|
+
} from "@tileflow/dev/config";
|
|
2835
|
+
import { prepareTileflowStyleFonts } from "@tileflow/dev/fonts";
|
|
2836
|
+
import { compileTileflowIconPackages } from "@tileflow/dev/icons";
|
|
2837
|
+
|
|
2807
2838
|
// src/hosted-preflight.ts
|
|
2808
2839
|
import {
|
|
2809
2840
|
compareCodeUnits as compareCodeUnits4,
|
|
@@ -2868,46 +2899,312 @@ function cloneStyle(style) {
|
|
|
2868
2899
|
return JSON.parse(JSON.stringify(style));
|
|
2869
2900
|
}
|
|
2870
2901
|
|
|
2902
|
+
// src/hosted-native-deploy.ts
|
|
2903
|
+
function failure(message) {
|
|
2904
|
+
return Object.assign(new Error(message), { code: "TF_NATIVE_DEPLOYMENT_INVALID" });
|
|
2905
|
+
}
|
|
2906
|
+
function requireNativeTarget(options) {
|
|
2907
|
+
if (!options.mapId || !/^map_[A-Za-z0-9_-]{16}$/u.test(options.mapId))
|
|
2908
|
+
throw failure("--with-native requires one valid --map-id.");
|
|
2909
|
+
const apiOrigin = normalizeApiOrigin(options.apiUrl);
|
|
2910
|
+
if (!apiOrigin.startsWith("https://"))
|
|
2911
|
+
throw failure("Hosted Native deployment requires an HTTPS API origin.");
|
|
2912
|
+
return { apiOrigin, mapId: options.mapId };
|
|
2913
|
+
}
|
|
2914
|
+
async function prepareNativeHostedDeploy(options) {
|
|
2915
|
+
const { apiOrigin } = requireNativeTarget(options);
|
|
2916
|
+
const loaded = await withTileflowConfigSecretsHidden(
|
|
2917
|
+
() => loadTileflowConfigWithInputs2(options.config)
|
|
2918
|
+
);
|
|
2919
|
+
assertValidTileflowConfig(loaded.project);
|
|
2920
|
+
const names = getTileflowMapNames(loaded.project);
|
|
2921
|
+
const mapName = options.map ?? (names.length === 1 ? names[0] : void 0);
|
|
2922
|
+
if (!mapName || !names.includes(mapName))
|
|
2923
|
+
throw failure("Select one configured map with --map for this Native deployment.");
|
|
2924
|
+
const map = loaded.project.maps[mapName];
|
|
2925
|
+
const project = { ...loaded.project, maps: { [mapName]: map } };
|
|
2926
|
+
const baseDirectory = dirname5(loaded.configFile);
|
|
2927
|
+
const compiledIcons = await compileTileflowIconPackages(project, {
|
|
2928
|
+
baseDirectory,
|
|
2929
|
+
cwd: process.cwd(),
|
|
2930
|
+
target: "hosted",
|
|
2931
|
+
icons: {
|
|
2932
|
+
...options.cacheDir ? { cacheRoot: options.cacheDir } : {},
|
|
2933
|
+
...options.offline ? { offline: true } : {}
|
|
2934
|
+
}
|
|
2935
|
+
});
|
|
2936
|
+
const binding = compiledIcons.bindings.find((entry) => entry.mapName === mapName);
|
|
2937
|
+
const iconPackage = binding ? compiledIcons.packages.find((entry) => entry.contentHash === binding.packageHash) : void 0;
|
|
2938
|
+
const sprite = binding ? `${apiOrigin}/sprites/preflight/${binding.packageHash}/sprite` : void 0;
|
|
2939
|
+
const mapAssets = Object.fromEntries(
|
|
2940
|
+
compiledIcons.bindings.map((entry) => [
|
|
2941
|
+
entry.mapName,
|
|
2942
|
+
{
|
|
2943
|
+
icons: {
|
|
2944
|
+
ids: entry.iconIds,
|
|
2945
|
+
sprite: `${apiOrigin}/sprites/preflight/${entry.packageHash}/sprite`
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
])
|
|
2949
|
+
);
|
|
2950
|
+
const styles = createTileflowStyles(project, { apiBaseUrl: apiOrigin, mapAssets });
|
|
2951
|
+
const local = await prepareTileflowLocalTilesets(project, styles, {
|
|
2952
|
+
assetBaseUrl: apiOrigin,
|
|
2953
|
+
baseDirectory,
|
|
2954
|
+
cwd: process.cwd()
|
|
2955
|
+
});
|
|
2956
|
+
try {
|
|
2957
|
+
const fonts = await prepareTileflowStyleFonts(project, local.styles, {
|
|
2958
|
+
assetBaseUrl: `${apiOrigin}/fonts/preflight`,
|
|
2959
|
+
baseDirectory,
|
|
2960
|
+
cwd: process.cwd(),
|
|
2961
|
+
target: "hosted"
|
|
2962
|
+
});
|
|
2963
|
+
if (inspectTileflowHostedCompatibility(project, fonts.styles).length)
|
|
2964
|
+
throw failure("Hosted renderer deployment requires compatible Tileflow World sources.");
|
|
2965
|
+
if (Object.keys(fonts.bundles).length)
|
|
2966
|
+
throw failure(
|
|
2967
|
+
"Hosted deploy does not yet support package-owned web fonts. Use an explicit public glyph provider."
|
|
2968
|
+
);
|
|
2969
|
+
const assets = (iconPackage?.files ?? []).map((file) => ({
|
|
2970
|
+
contentType: file.contentType,
|
|
2971
|
+
fileName: `icons/${mapName}/${file.fileName}`,
|
|
2972
|
+
source: file.source
|
|
2973
|
+
}));
|
|
2974
|
+
const provenance = await createTileflowBuildProvenance(process.cwd());
|
|
2975
|
+
const resolved = parseResolvedTileflowMap2(map);
|
|
2976
|
+
const inputStyles = JSON.parse(
|
|
2977
|
+
serializeCanonicalJson(fonts.styles[mapName])
|
|
2978
|
+
);
|
|
2979
|
+
const createArtifact = async (selectedSprite) => {
|
|
2980
|
+
const selected = JSON.parse(
|
|
2981
|
+
serializeCanonicalJson(inputStyles)
|
|
2982
|
+
);
|
|
2983
|
+
if (binding) {
|
|
2984
|
+
if (!sprite || !selectedSprite) throw failure("Missing confirmed sprite binding.");
|
|
2985
|
+
for (const style of Object.values(selected)) {
|
|
2986
|
+
if (style.sprite !== sprite)
|
|
2987
|
+
throw failure("Compiled sprite identity changed before publication.");
|
|
2988
|
+
style.sprite = selectedSprite;
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
const family = prepareTileflowHostedThemeFamily(mapName, map, selected);
|
|
2992
|
+
const buildManifest = await createTileflowMapBuildManifest(
|
|
2993
|
+
{
|
|
2994
|
+
[mapName]: {
|
|
2995
|
+
assets,
|
|
2996
|
+
lineage: project.mapMetadata?.[mapName]?.lineage ?? [
|
|
2997
|
+
{ id: map.id, mapVersion: map.version }
|
|
2998
|
+
],
|
|
2999
|
+
map,
|
|
3000
|
+
sourceAssets: {
|
|
3001
|
+
fonts: fonts.sourceIdentities[mapName] ?? [],
|
|
3002
|
+
icons: compiledIcons.sourceIdentities[mapName] ?? [],
|
|
3003
|
+
...compiledIcons.compositions[mapName] ? { iconComposition: compiledIcons.compositions[mapName] } : {}
|
|
3004
|
+
},
|
|
3005
|
+
styles: family.styles
|
|
3006
|
+
}
|
|
3007
|
+
},
|
|
3008
|
+
{ provenance }
|
|
3009
|
+
);
|
|
3010
|
+
return prepareTileflowHostedNativeDeployment({
|
|
3011
|
+
mapId: mapName,
|
|
3012
|
+
buildManifest,
|
|
3013
|
+
styles: family.styles,
|
|
3014
|
+
teamSources: family.teamSources,
|
|
3015
|
+
assets,
|
|
3016
|
+
...resolved.view ? { view: resolved.view } : {}
|
|
3017
|
+
});
|
|
3018
|
+
};
|
|
3019
|
+
const artifact = await createArtifact(sprite);
|
|
3020
|
+
return {
|
|
3021
|
+
mapName,
|
|
3022
|
+
artifact,
|
|
3023
|
+
packages: compiledIcons.packages,
|
|
3024
|
+
...binding ? { iconBinding: binding } : {},
|
|
3025
|
+
...compiledIcons.compositions[mapName] ? { iconComposition: compiledIcons.compositions[mapName] } : {},
|
|
3026
|
+
async retarget(sprites) {
|
|
3027
|
+
return binding ? createArtifact(sprites.get(binding.packageHash)) : artifact;
|
|
3028
|
+
},
|
|
3029
|
+
dispose: local.dispose
|
|
3030
|
+
};
|
|
3031
|
+
} catch (error) {
|
|
3032
|
+
await local.dispose();
|
|
3033
|
+
throw error;
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
async function runHostedNativeDeploy(options, ports) {
|
|
3037
|
+
const { apiOrigin, mapId } = requireNativeTarget(options);
|
|
3038
|
+
const prepared = await (ports.prepare ?? prepareNativeHostedDeploy)({
|
|
3039
|
+
...options,
|
|
3040
|
+
apiUrl: apiOrigin
|
|
3041
|
+
});
|
|
3042
|
+
try {
|
|
3043
|
+
const preflight = await parseTileflowRendererDeploymentArtifact(prepared.artifact);
|
|
3044
|
+
if (preflight.mapId !== prepared.mapName)
|
|
3045
|
+
throw failure("The prepared map does not match its artifact.");
|
|
3046
|
+
const existing = await ports.loadManifest(options.manifest, {
|
|
3047
|
+
overwriteSelfHosted: options.overwriteSelfHostedManifest === true
|
|
3048
|
+
});
|
|
3049
|
+
const previousOrigin = existing?.apiUrl ?? (existing ? Object.values(existing.maps)[0]?.apiUrl : void 0);
|
|
3050
|
+
if (previousOrigin !== void 0 && normalizeApiOrigin(previousOrigin) !== apiOrigin)
|
|
3051
|
+
throw failure("Existing manifest belongs to a different Tileflow API origin.");
|
|
3052
|
+
const api = await ports.resolveApi(prepared.mapName);
|
|
3053
|
+
if (!api) return null;
|
|
3054
|
+
if (api.apiUrl !== apiOrigin || api.mapId !== mapId || !api.apiKey || api.apiKey.length > 8192 || /[\p{Cc}]/u.test(api.apiKey))
|
|
3055
|
+
throw failure("Authorization did not confirm the requested API and Map.");
|
|
3056
|
+
const sprites = /* @__PURE__ */ new Map();
|
|
3057
|
+
for (const icon of prepared.packages) {
|
|
3058
|
+
if (sprites.has(icon.contentHash)) continue;
|
|
3059
|
+
let uploaded;
|
|
3060
|
+
try {
|
|
3061
|
+
uploaded = await (ports.uploadIcon ?? uploadHostedIconPackage)(api, icon, ports.request);
|
|
3062
|
+
} catch {
|
|
3063
|
+
throw failure("Native deployment icon upload failed. The local manifest was preserved.");
|
|
3064
|
+
}
|
|
3065
|
+
if (!uploaded.ok)
|
|
3066
|
+
throw failure("Native deployment icon upload failed. Retry the same artifact.");
|
|
3067
|
+
const expected = `${apiOrigin}/sprites/${uploaded.value.id}/sprite`;
|
|
3068
|
+
if (uploaded.value.contentHash !== icon.contentHash || uploaded.value.spriteUrl !== expected)
|
|
3069
|
+
throw failure("Icon publication did not confirm the owned resource and origin.");
|
|
3070
|
+
sprites.set(icon.contentHash, expected);
|
|
3071
|
+
}
|
|
3072
|
+
const artifact = await parseTileflowRendererDeploymentArtifact(
|
|
3073
|
+
await prepared.retarget(sprites)
|
|
3074
|
+
);
|
|
3075
|
+
if (artifact.mapId !== preflight.mapId || artifact.renderers.web.buildManifest.maps[artifact.mapId].mapRevisionSha256 !== preflight.renderers.web.buildManifest.maps[preflight.mapId].mapRevisionSha256)
|
|
3076
|
+
throw failure("Authored map identity changed after preflight.");
|
|
3077
|
+
const iconPackage = prepared.iconBinding ? prepared.packages.find((entry) => entry.contentHash === prepared.iconBinding.packageHash) : void 0;
|
|
3078
|
+
if (prepared.iconComposition && prepared.iconComposition.packageHash !== iconPackage?.contentHash)
|
|
3079
|
+
throw failure("Icon composition does not match the confirmed effective package.");
|
|
3080
|
+
let response;
|
|
3081
|
+
try {
|
|
3082
|
+
response = await requestHostedJson(
|
|
3083
|
+
apiOrigin,
|
|
3084
|
+
"/v1/styles",
|
|
3085
|
+
{
|
|
3086
|
+
method: "POST",
|
|
3087
|
+
headers: {
|
|
3088
|
+
Authorization: `Bearer ${api.apiKey}`,
|
|
3089
|
+
"X-Tileflow-Map-Id": mapId,
|
|
3090
|
+
"Content-Type": "application/json"
|
|
3091
|
+
},
|
|
3092
|
+
body: serializeCanonicalJson({
|
|
3093
|
+
artifact,
|
|
3094
|
+
environment: prepared.mapName,
|
|
3095
|
+
managedMapId: mapId,
|
|
3096
|
+
usageMode: "session",
|
|
3097
|
+
source: ports.source,
|
|
3098
|
+
...iconPackage && prepared.iconBinding ? {
|
|
3099
|
+
iconPackage: {
|
|
3100
|
+
contentHash: iconPackage.contentHash,
|
|
3101
|
+
label: prepared.iconBinding.label
|
|
3102
|
+
}
|
|
3103
|
+
} : {},
|
|
3104
|
+
...prepared.iconComposition ? { iconComposition: prepared.iconComposition } : {}
|
|
3105
|
+
})
|
|
3106
|
+
},
|
|
3107
|
+
ports.request
|
|
3108
|
+
);
|
|
3109
|
+
} catch {
|
|
3110
|
+
throw failure(
|
|
3111
|
+
"Renderer deployment response was unavailable. Retry the same artifact; the local manifest was preserved."
|
|
3112
|
+
);
|
|
3113
|
+
}
|
|
3114
|
+
if (!response.ok || !response.json)
|
|
3115
|
+
throw failure("Renderer deployment failed. The local manifest was preserved.");
|
|
3116
|
+
const parsed = tileflowRendererDeploymentResponseSchema.safeParse(response.body);
|
|
3117
|
+
if (!parsed.success)
|
|
3118
|
+
throw failure("Invalid renderer deployment response. The local manifest was preserved.");
|
|
3119
|
+
const result = parsed.data;
|
|
3120
|
+
const names = Object.keys(artifact.renderers.web.styles).sort();
|
|
3121
|
+
const expectedManifestUrl = `${apiOrigin}/maps/${mapId}/native/manifest.json`;
|
|
3122
|
+
if (result.mapId !== mapId || result.renderers.native.manifestUrl !== expectedManifestUrl || names.join("\0") !== Object.keys(result.renderers.web.themes).sort().join("\0") || names.join("\0") !== Object.keys(result.renderers.native.themes).sort().join("\0"))
|
|
3123
|
+
throw failure(
|
|
3124
|
+
"Renderer deployment did not confirm the requested Map and complete theme families."
|
|
3125
|
+
);
|
|
3126
|
+
for (const name of names) {
|
|
3127
|
+
if (result.renderers.web.themes[name].styleUrl !== `${apiOrigin}/maps/${mapId}/${name}.json` || result.renderers.native.themes[name].styleUrl !== `${apiOrigin}/maps/${mapId}/native/v${result.version}/${name}.json`)
|
|
3128
|
+
throw failure("Renderer deployment returned an unexpected delivery route.");
|
|
3129
|
+
}
|
|
3130
|
+
const build = artifact.renderers.web.buildManifest.maps[artifact.mapId];
|
|
3131
|
+
const manifest = parseTileflowRuntimeManifest({
|
|
3132
|
+
apiUrl: apiOrigin,
|
|
3133
|
+
version: 1,
|
|
3134
|
+
maps: {
|
|
3135
|
+
...existing?.maps ?? {},
|
|
3136
|
+
[prepared.mapName]: {
|
|
3137
|
+
defaultTheme: build.defaultTheme,
|
|
3138
|
+
environment: prepared.mapName,
|
|
3139
|
+
mapId,
|
|
3140
|
+
...build.systemThemes ? { systemThemes: build.systemThemes } : {},
|
|
3141
|
+
...artifact.view ? { view: artifact.view } : {},
|
|
3142
|
+
usageMode: "session",
|
|
3143
|
+
worldGeneration: "v1",
|
|
3144
|
+
themes: Object.fromEntries(
|
|
3145
|
+
names.map((name) => [
|
|
3146
|
+
name,
|
|
3147
|
+
{
|
|
3148
|
+
colorScheme: build.themes[name].colorScheme,
|
|
3149
|
+
fontFaces: getTileflowStyleFontFaces(
|
|
3150
|
+
artifact.renderers.web.styles[name]
|
|
3151
|
+
),
|
|
3152
|
+
revision: build.themes[name].styleSha256,
|
|
3153
|
+
...result.renderers.web.themes[name]
|
|
3154
|
+
}
|
|
3155
|
+
])
|
|
3156
|
+
)
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
});
|
|
3160
|
+
const manifestPath = await ports.writeManifest(options.manifest, manifest);
|
|
3161
|
+
return Object.freeze({
|
|
3162
|
+
manifestPath,
|
|
3163
|
+
mapName: prepared.mapName,
|
|
3164
|
+
mapId,
|
|
3165
|
+
deploymentId: result.deploymentId,
|
|
3166
|
+
version: result.version,
|
|
3167
|
+
changed: result.changed,
|
|
3168
|
+
nativeManifestUrl: expectedManifestUrl
|
|
3169
|
+
});
|
|
3170
|
+
} finally {
|
|
3171
|
+
await prepared.dispose();
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3174
|
+
|
|
2871
3175
|
// src/icon-diff-command.ts
|
|
2872
|
-
import { dirname as
|
|
2873
|
-
import { z as
|
|
3176
|
+
import { dirname as dirname7, resolve as resolve4 } from "path";
|
|
3177
|
+
import { z as z3 } from "zod";
|
|
2874
3178
|
import {
|
|
2875
3179
|
diffTileflowIconPackageManifests,
|
|
2876
3180
|
hashTileflowIconPackageManifest,
|
|
2877
3181
|
tileflowIconPackageContentHashSchema,
|
|
2878
3182
|
tileflowIconPackageLabelSchema,
|
|
2879
|
-
tileflowIconPackageLimits as
|
|
3183
|
+
tileflowIconPackageLimits as tileflowIconPackageLimits2,
|
|
2880
3184
|
tileflowIconPackageManifestSchema,
|
|
2881
3185
|
tileflowMapIdSchema
|
|
2882
3186
|
} from "@tileflow/core";
|
|
2883
3187
|
import {
|
|
2884
|
-
assertValidTileflowConfig,
|
|
2885
|
-
getTileflowMapNames,
|
|
2886
|
-
loadTileflowConfigWithInputs as
|
|
3188
|
+
assertValidTileflowConfig as assertValidTileflowConfig2,
|
|
3189
|
+
getTileflowMapNames as getTileflowMapNames2,
|
|
3190
|
+
loadTileflowConfigWithInputs as loadTileflowConfigWithInputs3
|
|
2887
3191
|
} from "@tileflow/dev/config";
|
|
2888
3192
|
import {
|
|
2889
|
-
compileTileflowIconPackages
|
|
3193
|
+
compileTileflowIconPackages as compileTileflowIconPackages2
|
|
2890
3194
|
} from "@tileflow/dev/icons";
|
|
2891
3195
|
|
|
2892
3196
|
// src/icon-diff-report.ts
|
|
2893
3197
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2894
3198
|
import { mkdir as mkdir3, readFile as readFile3, rename as rename3, unlink as unlink3, writeFile } from "fs/promises";
|
|
2895
|
-
import { basename as basename2, dirname as
|
|
2896
|
-
import { z as z3 } from "zod";
|
|
3199
|
+
import { basename as basename2, dirname as dirname6, join } from "path";
|
|
2897
3200
|
import {
|
|
2898
3201
|
compareCodeUnits as compareCodeUnits5,
|
|
2899
3202
|
sha256Hex,
|
|
2900
|
-
|
|
2901
|
-
tileflowIconPackageLimits as tileflowIconPackageLimits2
|
|
3203
|
+
tileflowIconSpriteIndexSchema
|
|
2902
3204
|
} from "@tileflow/core";
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
width: z3.number().int().positive().max(tileflowIconPackageLimits2.maxAtlasDimension),
|
|
2907
|
-
x: z3.number().int().nonnegative().max(tileflowIconPackageLimits2.maxAtlasDimension),
|
|
2908
|
-
y: z3.number().int().nonnegative().max(tileflowIconPackageLimits2.maxAtlasDimension)
|
|
2909
|
-
}).strict();
|
|
2910
|
-
var spriteIndexSchema = z3.record(tileflowIconIdSchema, spriteEntrySchema);
|
|
3205
|
+
import {
|
|
3206
|
+
renderTileflowIconAtlasPreview
|
|
3207
|
+
} from "@tileflow/dev/icons";
|
|
2911
3208
|
async function writeIconDiffReport(input) {
|
|
2912
3209
|
const [before, after] = await Promise.all([
|
|
2913
3210
|
input.baseline?.package ? loadRemoteSprite(input.baseline.package) : null,
|
|
@@ -2945,18 +3242,20 @@ function loadCompiledSprite(iconPackage) {
|
|
|
2945
3242
|
iconPackage.manifest.sprites.twoX
|
|
2946
3243
|
);
|
|
2947
3244
|
}
|
|
2948
|
-
function reportSpriteFromFiles(files, oneX, twoX) {
|
|
3245
|
+
async function reportSpriteFromFiles(files, oneX, twoX) {
|
|
2949
3246
|
const oneXJson = requiredFile(files, "sprite.json");
|
|
2950
3247
|
const oneXPng = requiredFile(files, "sprite.png");
|
|
2951
3248
|
const twoXJson = requiredFile(files, "sprite@2x.json");
|
|
2952
3249
|
const twoXPng = requiredFile(files, "sprite@2x.png");
|
|
3250
|
+
const indexOneX = parseIndex(oneXJson, 1, oneX.width, oneX.height);
|
|
3251
|
+
const indexTwoX = parseIndex(twoXJson, 2, twoX.width, twoX.height);
|
|
2953
3252
|
return {
|
|
2954
|
-
indexOneX
|
|
2955
|
-
indexTwoX
|
|
2956
|
-
oneXDataUrl: pngDataUrl(oneXPng),
|
|
3253
|
+
indexOneX,
|
|
3254
|
+
indexTwoX,
|
|
3255
|
+
oneXDataUrl: pngDataUrl(await renderTileflowIconAtlasPreview(oneXPng, indexOneX)),
|
|
2957
3256
|
oneXHeight: oneX.height,
|
|
2958
3257
|
oneXWidth: oneX.width,
|
|
2959
|
-
twoXDataUrl: pngDataUrl(twoXPng),
|
|
3258
|
+
twoXDataUrl: pngDataUrl(await renderTileflowIconAtlasPreview(twoXPng, indexTwoX)),
|
|
2960
3259
|
twoXHeight: twoX.height,
|
|
2961
3260
|
twoXWidth: twoX.width
|
|
2962
3261
|
};
|
|
@@ -2968,7 +3267,7 @@ function parseIndex(source, pixelRatio, atlasWidth, atlasHeight) {
|
|
|
2968
3267
|
} catch {
|
|
2969
3268
|
throw new Error("Sprite report index is not valid UTF-8 JSON");
|
|
2970
3269
|
}
|
|
2971
|
-
const parsed =
|
|
3270
|
+
const parsed = tileflowIconSpriteIndexSchema.safeParse(value);
|
|
2972
3271
|
if (!parsed.success) {
|
|
2973
3272
|
throw new Error("Sprite report index does not match the MapLibre schema");
|
|
2974
3273
|
}
|
|
@@ -3363,9 +3662,9 @@ async function writeAtomicReport(path, html, force) {
|
|
|
3363
3662
|
} catch (error) {
|
|
3364
3663
|
if (!isMissingFile3(error)) throw error;
|
|
3365
3664
|
}
|
|
3366
|
-
await mkdir3(
|
|
3665
|
+
await mkdir3(dirname6(path), { recursive: true });
|
|
3367
3666
|
const temporaryPath = join(
|
|
3368
|
-
|
|
3667
|
+
dirname6(path),
|
|
3369
3668
|
`.${basename2(path)}.${process.pid}.${randomUUID2()}.tmp`
|
|
3370
3669
|
);
|
|
3371
3670
|
try {
|
|
@@ -3394,56 +3693,56 @@ function isMissingFile3(error) {
|
|
|
3394
3693
|
|
|
3395
3694
|
// src/icon-diff-command.ts
|
|
3396
3695
|
var environmentSchema = tileflowMapIdSchema;
|
|
3397
|
-
var publicHttpUrlSchema2 =
|
|
3696
|
+
var publicHttpUrlSchema2 = z3.url().max(2048).refine((value) => {
|
|
3398
3697
|
const url = new URL(value);
|
|
3399
3698
|
return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password;
|
|
3400
3699
|
});
|
|
3401
|
-
var iconPackageBaselineResponseSchema =
|
|
3402
|
-
baseline:
|
|
3403
|
-
deployedAt:
|
|
3404
|
-
deploymentId:
|
|
3405
|
-
package:
|
|
3700
|
+
var iconPackageBaselineResponseSchema = z3.object({
|
|
3701
|
+
baseline: z3.object({
|
|
3702
|
+
deployedAt: z3.iso.datetime({ offset: true }),
|
|
3703
|
+
deploymentId: z3.string().min(1).max(128),
|
|
3704
|
+
package: z3.object({
|
|
3406
3705
|
contentHash: tileflowIconPackageContentHashSchema,
|
|
3407
3706
|
label: tileflowIconPackageLabelSchema,
|
|
3408
3707
|
manifest: tileflowIconPackageManifestSchema,
|
|
3409
3708
|
spriteUrl: publicHttpUrlSchema2,
|
|
3410
|
-
totalBytes:
|
|
3709
|
+
totalBytes: z3.number().int().positive().max(tileflowIconPackageLimits2.maxGeneratedPackageBytes)
|
|
3411
3710
|
}).strict().nullable(),
|
|
3412
|
-
version:
|
|
3711
|
+
version: z3.number().int().positive()
|
|
3413
3712
|
}).strict().nullable(),
|
|
3414
3713
|
environment: environmentSchema,
|
|
3415
|
-
schemaVersion:
|
|
3714
|
+
schemaVersion: z3.literal(1)
|
|
3416
3715
|
}).strict();
|
|
3417
|
-
var packageSummarySchema =
|
|
3716
|
+
var packageSummarySchema = z3.object({
|
|
3418
3717
|
contentHash: tileflowIconPackageContentHashSchema,
|
|
3419
|
-
iconCount:
|
|
3718
|
+
iconCount: z3.number().int().nonnegative().max(tileflowIconPackageLimits2.maxIconCount),
|
|
3420
3719
|
label: tileflowIconPackageLabelSchema,
|
|
3421
|
-
totalBytes:
|
|
3720
|
+
totalBytes: z3.number().int().nonnegative().max(tileflowIconPackageLimits2.maxGeneratedPackageBytes)
|
|
3422
3721
|
}).strict();
|
|
3423
|
-
var tileflowIconDiffDocumentSchema =
|
|
3424
|
-
schemaVersion:
|
|
3722
|
+
var tileflowIconDiffDocumentSchema = z3.object({
|
|
3723
|
+
schemaVersion: z3.literal(1),
|
|
3425
3724
|
environment: environmentSchema,
|
|
3426
|
-
baseline:
|
|
3427
|
-
deploymentId:
|
|
3725
|
+
baseline: z3.object({
|
|
3726
|
+
deploymentId: z3.string(),
|
|
3428
3727
|
package: packageSummarySchema.nullable(),
|
|
3429
|
-
version:
|
|
3728
|
+
version: z3.number().int().positive()
|
|
3430
3729
|
}).strict().nullable(),
|
|
3431
|
-
proposed:
|
|
3730
|
+
proposed: z3.object({
|
|
3432
3731
|
package: packageSummarySchema.nullable()
|
|
3433
3732
|
}).strict(),
|
|
3434
|
-
icons:
|
|
3435
|
-
added:
|
|
3436
|
-
removed:
|
|
3437
|
-
modified:
|
|
3438
|
-
unchangedCount:
|
|
3733
|
+
icons: z3.object({
|
|
3734
|
+
added: z3.array(z3.string()),
|
|
3735
|
+
removed: z3.array(z3.string()),
|
|
3736
|
+
modified: z3.array(z3.string()),
|
|
3737
|
+
unchangedCount: z3.number().int().nonnegative()
|
|
3439
3738
|
}).strict(),
|
|
3440
|
-
generatedBytes:
|
|
3441
|
-
before:
|
|
3442
|
-
after:
|
|
3443
|
-
delta:
|
|
3739
|
+
generatedBytes: z3.object({
|
|
3740
|
+
before: z3.number().int().nonnegative(),
|
|
3741
|
+
after: z3.number().int().nonnegative(),
|
|
3742
|
+
delta: z3.number().int()
|
|
3444
3743
|
}).strict(),
|
|
3445
|
-
artifacts:
|
|
3446
|
-
hasChanges:
|
|
3744
|
+
artifacts: z3.object({ report: z3.string().nullable() }).strict(),
|
|
3745
|
+
hasChanges: z3.boolean()
|
|
3447
3746
|
}).strict();
|
|
3448
3747
|
function registerIconDiffCommand(icons, dependencies) {
|
|
3449
3748
|
icons.command("diff").description("Preview a local icon package against an active hosted revision").requiredOption("--against <environment>", "named map environment to compare").option("-c, --config <path>", "config path", dependencies.defaultConfigPath).option("--api-url <url>", "Tileflow API URL", process.env.TILEFLOW_API_URL).option("--api-key <key>", "Tileflow API key", process.env.TILEFLOW_API_KEY).requiredOption("--map-id <id>", "managed Map destination").option("--json", "print deterministic schema-version-1 JSON").option("--cache-dir <path>", "verified Icon Set artifact cache root").option("--offline", "fail a locked Icon Set cache miss instead of hydrating it").option("--report <path>", "write a self-contained HTML visual report").option("--open", "open an explicitly requested report").option("--force", "replace a different explicitly requested report").action(async (options) => {
|
|
@@ -3467,11 +3766,11 @@ async function runIconDiff(options, dependencies) {
|
|
|
3467
3766
|
}
|
|
3468
3767
|
const environment = environmentSchema.parse(options.against);
|
|
3469
3768
|
const loaded = await withTileflowConfigSecretsHidden(
|
|
3470
|
-
() =>
|
|
3769
|
+
() => loadTileflowConfigWithInputs3(options.config)
|
|
3471
3770
|
);
|
|
3472
3771
|
const project = loaded.project;
|
|
3473
|
-
|
|
3474
|
-
const mapNames =
|
|
3772
|
+
assertValidTileflowConfig2(project);
|
|
3773
|
+
const mapNames = getTileflowMapNames2(project);
|
|
3475
3774
|
if (!Object.hasOwn(project.maps, environment)) {
|
|
3476
3775
|
throw new Error(
|
|
3477
3776
|
`Unknown map environment "${environment}". Available maps: ${mapNames.join(", ") || "(none)"}`
|
|
@@ -3486,8 +3785,8 @@ async function runIconDiff(options, dependencies) {
|
|
|
3486
3785
|
...options.cacheDir ? { cacheRoot: options.cacheDir } : {},
|
|
3487
3786
|
...options.offline ? { offline: true } : {}
|
|
3488
3787
|
};
|
|
3489
|
-
const compiled = await
|
|
3490
|
-
baseDirectory:
|
|
3788
|
+
const compiled = await compileTileflowIconPackages2(selectedProject, {
|
|
3789
|
+
baseDirectory: dirname7(loaded.configFile),
|
|
3491
3790
|
cwd: process.cwd(),
|
|
3492
3791
|
...Object.keys(icons).length > 0 ? { icons } : {},
|
|
3493
3792
|
target: "hosted"
|
|
@@ -3631,10 +3930,10 @@ function formatSignedBytes(bytes) {
|
|
|
3631
3930
|
}
|
|
3632
3931
|
|
|
3633
3932
|
// src/icon-list-command.ts
|
|
3634
|
-
import { dirname as
|
|
3933
|
+
import { dirname as dirname8 } from "path";
|
|
3635
3934
|
import { compareCodeUnits as compareCodeUnits6 } from "@tileflow/core";
|
|
3636
3935
|
import {
|
|
3637
|
-
getTileflowMapNames as
|
|
3936
|
+
getTileflowMapNames as getTileflowMapNames3,
|
|
3638
3937
|
loadValidTileflowConfigWithInputs as loadValidTileflowConfigWithInputs2,
|
|
3639
3938
|
TileflowValidationError as TileflowValidationError3
|
|
3640
3939
|
} from "@tileflow/dev/config";
|
|
@@ -3675,7 +3974,7 @@ async function runIconList(options) {
|
|
|
3675
3974
|
() => loadValidTileflowConfigWithInputs2(options.config)
|
|
3676
3975
|
);
|
|
3677
3976
|
const project = loaded.project;
|
|
3678
|
-
const mapIds =
|
|
3977
|
+
const mapIds = getTileflowMapNames3(project).sort(compareCodeUnits6);
|
|
3679
3978
|
if (options.map && !Object.hasOwn(project.maps, options.map)) {
|
|
3680
3979
|
throw new Error(
|
|
3681
3980
|
`Unknown map "${options.map}". Available maps: ${mapIds.join(", ") || "(none)"}`
|
|
@@ -3686,7 +3985,7 @@ async function runIconList(options) {
|
|
|
3686
3985
|
...options.offline ? { offline: true } : {}
|
|
3687
3986
|
};
|
|
3688
3987
|
const inspection = await inspectTileflowIconCatalogs(project, {
|
|
3689
|
-
baseDirectory:
|
|
3988
|
+
baseDirectory: dirname8(loaded.configFile),
|
|
3690
3989
|
cwd: process.cwd(),
|
|
3691
3990
|
...Object.keys(icons).length > 0 ? { icons } : {},
|
|
3692
3991
|
...options.map ? { mapNames: [options.map] } : {}
|
|
@@ -3710,6 +4009,18 @@ function createMapJson(map, catalogs) {
|
|
|
3710
4009
|
kind: "sources",
|
|
3711
4010
|
contributors: mapIcons.contributors.map(createContributorJson),
|
|
3712
4011
|
finalIds: [...mapIcons.iconIds],
|
|
4012
|
+
...catalog.icons.some((icon) => icon.appearance) ? {
|
|
4013
|
+
appearances: Object.fromEntries(
|
|
4014
|
+
catalog.icons.flatMap(
|
|
4015
|
+
(icon) => icon.appearance ? [[icon.id, icon.appearance]] : []
|
|
4016
|
+
)
|
|
4017
|
+
)
|
|
4018
|
+
} : {},
|
|
4019
|
+
...catalog.icons.some((icon) => icon.layout) ? {
|
|
4020
|
+
layouts: Object.fromEntries(
|
|
4021
|
+
catalog.icons.flatMap((icon) => icon.layout ? [[icon.id, icon.layout]] : [])
|
|
4022
|
+
)
|
|
4023
|
+
} : {},
|
|
3713
4024
|
insideWorkingTree: catalog.insideWorkingTree,
|
|
3714
4025
|
replacements: catalog.replacements.map((replacement) => ({
|
|
3715
4026
|
id: replacement.id,
|
|
@@ -3773,18 +4084,18 @@ function printIssues(heading, issues) {
|
|
|
3773
4084
|
}
|
|
3774
4085
|
|
|
3775
4086
|
// src/icon-lock-command.ts
|
|
3776
|
-
import { dirname as
|
|
4087
|
+
import { dirname as dirname9 } from "path";
|
|
3777
4088
|
import pc3 from "picocolors";
|
|
3778
4089
|
import {
|
|
3779
4090
|
collectTileflowIconSetReferences,
|
|
3780
4091
|
compareCodeUnits as compareCodeUnits7,
|
|
3781
|
-
parseResolvedTileflowMap as
|
|
4092
|
+
parseResolvedTileflowMap as parseResolvedTileflowMap3,
|
|
3782
4093
|
parseTileflowIconsLockfile,
|
|
3783
4094
|
tileflowIconSetReferenceSchema as tileflowIconSetReferenceSchema2,
|
|
3784
4095
|
tileflowIconsLockfileName
|
|
3785
4096
|
} from "@tileflow/core";
|
|
3786
4097
|
import {
|
|
3787
|
-
getTileflowMapNames as
|
|
4098
|
+
getTileflowMapNames as getTileflowMapNames4,
|
|
3788
4099
|
loadValidTileflowConfigWithInputs as loadValidTileflowConfigWithInputs3,
|
|
3789
4100
|
TileflowValidationError as TileflowValidationError4
|
|
3790
4101
|
} from "@tileflow/dev/config";
|
|
@@ -3792,7 +4103,7 @@ import { readTileflowIconsLockfileText, writeTileflowIconsLockfile } from "@tile
|
|
|
3792
4103
|
|
|
3793
4104
|
// src/hosted-team.ts
|
|
3794
4105
|
import pc from "picocolors";
|
|
3795
|
-
import { serializeCanonicalJson } from "@tileflow/core";
|
|
4106
|
+
import { serializeCanonicalJson as serializeCanonicalJson2 } from "@tileflow/core";
|
|
3796
4107
|
async function resolveTeamAuthority(options, scopes, dependencies) {
|
|
3797
4108
|
let apiOrigin;
|
|
3798
4109
|
try {
|
|
@@ -3872,13 +4183,13 @@ function authorizedTeamRequest(authority, path, method, init = {}) {
|
|
|
3872
4183
|
});
|
|
3873
4184
|
}
|
|
3874
4185
|
function emitJson(value) {
|
|
3875
|
-
process.stdout.write(`${
|
|
4186
|
+
process.stdout.write(`${serializeCanonicalJson2(value)}
|
|
3876
4187
|
`);
|
|
3877
4188
|
}
|
|
3878
4189
|
function emitFailure(json, code, message, context = {}) {
|
|
3879
4190
|
if (json) {
|
|
3880
4191
|
process.stderr.write(
|
|
3881
|
-
`${
|
|
4192
|
+
`${serializeCanonicalJson2({ error: { code, ...context, message }, ok: false, schemaVersion: 1 })}
|
|
3882
4193
|
`
|
|
3883
4194
|
);
|
|
3884
4195
|
} else {
|
|
@@ -3893,8 +4204,9 @@ function safeMessage(error) {
|
|
|
3893
4204
|
// src/icon-set-command.ts
|
|
3894
4205
|
import { isAbsolute as isAbsolute2 } from "path";
|
|
3895
4206
|
import pc2 from "picocolors";
|
|
3896
|
-
import { z as
|
|
4207
|
+
import { z as z4 } from "zod";
|
|
3897
4208
|
import {
|
|
4209
|
+
tileflowIconPackageLimits as tileflowIconPackageLimits3,
|
|
3898
4210
|
tileflowIconSetPackageIdSchema,
|
|
3899
4211
|
tileflowIconSetPinSchema,
|
|
3900
4212
|
tileflowIconSetReferenceSchema
|
|
@@ -4338,27 +4650,27 @@ function isIconSetSlug(value) {
|
|
|
4338
4650
|
function isIdempotencyKey(value) {
|
|
4339
4651
|
return value.length >= 8 && value.length <= 128 && /^[A-Za-z0-9._:-]+$/u.test(value);
|
|
4340
4652
|
}
|
|
4341
|
-
var cursorSchema =
|
|
4342
|
-
var isoDateSchema =
|
|
4343
|
-
var setSchema =
|
|
4344
|
-
id:
|
|
4653
|
+
var cursorSchema = z4.string().min(1).max(2048).nullable();
|
|
4654
|
+
var isoDateSchema = z4.iso.datetime({ offset: true });
|
|
4655
|
+
var setSchema = z4.object({
|
|
4656
|
+
id: z4.string().regex(/^ics_[A-Za-z0-9_-]{16}$/u),
|
|
4345
4657
|
reference: tileflowIconSetReferenceSchema,
|
|
4346
|
-
name:
|
|
4347
|
-
description:
|
|
4658
|
+
name: z4.string().max(200),
|
|
4659
|
+
description: z4.string().max(2e3),
|
|
4348
4660
|
archivedAt: isoDateSchema.nullable(),
|
|
4349
|
-
latestVersion:
|
|
4661
|
+
latestVersion: z4.number().int().positive().max(Number.MAX_SAFE_INTEGER).nullable(),
|
|
4350
4662
|
createdAt: isoDateSchema,
|
|
4351
4663
|
updatedAt: isoDateSchema
|
|
4352
4664
|
}).strict();
|
|
4353
|
-
var revisionBaseSchema =
|
|
4354
|
-
id:
|
|
4665
|
+
var revisionBaseSchema = z4.object({
|
|
4666
|
+
id: z4.string().regex(/^icv_[A-Za-z0-9_-]{16}$/u),
|
|
4355
4667
|
reference: tileflowIconSetReferenceSchema,
|
|
4356
|
-
version:
|
|
4668
|
+
version: z4.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
4357
4669
|
publishedAt: isoDateSchema,
|
|
4358
4670
|
purgedAt: isoDateSchema.nullable(),
|
|
4359
|
-
iconCount:
|
|
4360
|
-
totalBytes:
|
|
4361
|
-
publisher:
|
|
4671
|
+
iconCount: z4.number().int().min(0).max(tileflowIconPackageLimits3.maxIconCount),
|
|
4672
|
+
totalBytes: z4.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
|
4673
|
+
publisher: z4.object({ kind: z4.enum(["credential", "membership"]), id: z4.string().max(200).nullable() }).strict()
|
|
4362
4674
|
}).strict();
|
|
4363
4675
|
var revisionSchema = revisionBaseSchema.extend({ pin: tileflowIconSetPinSchema.nullable() }).transform(({ id, reference, version, publishedAt, purgedAt, iconCount, totalBytes, pin }) => ({
|
|
4364
4676
|
iconCount,
|
|
@@ -4382,53 +4694,53 @@ var revisionSummarySchema = revisionBaseSchema.extend({ packageId: tileflowIconS
|
|
|
4382
4694
|
version
|
|
4383
4695
|
})
|
|
4384
4696
|
);
|
|
4385
|
-
var catalogListResponseSchema =
|
|
4386
|
-
schemaVersion:
|
|
4387
|
-
sets:
|
|
4697
|
+
var catalogListResponseSchema = z4.object({
|
|
4698
|
+
schemaVersion: z4.literal(1),
|
|
4699
|
+
sets: z4.array(setSchema).max(pageSize),
|
|
4388
4700
|
nextCursor: cursorSchema.optional()
|
|
4389
4701
|
}).strict();
|
|
4390
|
-
var catalogDetailResponseSchema =
|
|
4391
|
-
var versionsResponseSchema =
|
|
4392
|
-
schemaVersion:
|
|
4393
|
-
versions:
|
|
4702
|
+
var catalogDetailResponseSchema = z4.object({ schemaVersion: z4.literal(1), set: setSchema }).strict();
|
|
4703
|
+
var versionsResponseSchema = z4.object({
|
|
4704
|
+
schemaVersion: z4.literal(1),
|
|
4705
|
+
versions: z4.array(revisionSummarySchema).max(pageSize),
|
|
4394
4706
|
nextCursor: cursorSchema.optional()
|
|
4395
4707
|
}).strict();
|
|
4396
|
-
var revisionResponseSchema =
|
|
4397
|
-
schemaVersion:
|
|
4398
|
-
archived:
|
|
4708
|
+
var revisionResponseSchema = z4.object({
|
|
4709
|
+
schemaVersion: z4.literal(1),
|
|
4710
|
+
archived: z4.boolean(),
|
|
4399
4711
|
revision: revisionSchema
|
|
4400
4712
|
}).strict();
|
|
4401
|
-
var publishResponseSchema =
|
|
4402
|
-
var usesResponseSchema =
|
|
4403
|
-
schemaVersion:
|
|
4404
|
-
uses:
|
|
4405
|
-
|
|
4406
|
-
deploymentId:
|
|
4407
|
-
deploymentVersion:
|
|
4408
|
-
mapId:
|
|
4409
|
-
mapName:
|
|
4410
|
-
mapState:
|
|
4411
|
-
versionId:
|
|
4412
|
-
version:
|
|
4413
|
-
ordinal:
|
|
4414
|
-
relationship:
|
|
4713
|
+
var publishResponseSchema = z4.object({ schemaVersion: z4.literal(1), changed: z4.boolean(), revision: revisionSchema }).strict();
|
|
4714
|
+
var usesResponseSchema = z4.object({
|
|
4715
|
+
schemaVersion: z4.literal(1),
|
|
4716
|
+
uses: z4.array(
|
|
4717
|
+
z4.object({
|
|
4718
|
+
deploymentId: z4.string().min(1).max(160),
|
|
4719
|
+
deploymentVersion: z4.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
4720
|
+
mapId: z4.string().min(1).max(160),
|
|
4721
|
+
mapName: z4.string().max(200).nullable(),
|
|
4722
|
+
mapState: z4.string().max(64),
|
|
4723
|
+
versionId: z4.string().regex(/^icv_[A-Za-z0-9_-]{16}$/u),
|
|
4724
|
+
version: z4.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
4725
|
+
ordinal: z4.number().int().min(0).max(31),
|
|
4726
|
+
relationship: z4.enum(["active", "retained"])
|
|
4415
4727
|
}).strict()
|
|
4416
4728
|
).max(pageSize),
|
|
4417
4729
|
nextCursor: cursorSchema.optional(),
|
|
4418
|
-
coverage:
|
|
4419
|
-
includesUndeployedRepositoryLocks:
|
|
4730
|
+
coverage: z4.literal("known-hosted-deployments"),
|
|
4731
|
+
includesUndeployedRepositoryLocks: z4.literal(false)
|
|
4420
4732
|
}).strict();
|
|
4421
|
-
var purgeResponseSchema =
|
|
4422
|
-
schemaVersion:
|
|
4423
|
-
result:
|
|
4424
|
-
schemaVersion:
|
|
4425
|
-
versionId:
|
|
4426
|
-
version:
|
|
4427
|
-
purged:
|
|
4428
|
-
knownRetainedDeployments:
|
|
4429
|
-
physicalBytesReleased:
|
|
4430
|
-
unknownRepositoryLocks:
|
|
4431
|
-
warning:
|
|
4733
|
+
var purgeResponseSchema = z4.object({
|
|
4734
|
+
schemaVersion: z4.literal(1),
|
|
4735
|
+
result: z4.object({
|
|
4736
|
+
schemaVersion: z4.literal(1),
|
|
4737
|
+
versionId: z4.string().regex(/^icv_[A-Za-z0-9_-]{16}$/u),
|
|
4738
|
+
version: z4.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
4739
|
+
purged: z4.boolean(),
|
|
4740
|
+
knownRetainedDeployments: z4.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
|
4741
|
+
physicalBytesReleased: z4.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
|
4742
|
+
unknownRepositoryLocks: z4.boolean(),
|
|
4743
|
+
warning: z4.string().max(400)
|
|
4432
4744
|
}).strict()
|
|
4433
4745
|
}).strict();
|
|
4434
4746
|
|
|
@@ -4467,7 +4779,7 @@ function registerIconLockCommands(program2, dependencies) {
|
|
|
4467
4779
|
const loaded = await withTileflowConfigSecretsHidden(
|
|
4468
4780
|
() => loadValidTileflowConfigWithInputs3(options.config)
|
|
4469
4781
|
);
|
|
4470
|
-
baseDirectory =
|
|
4782
|
+
baseDirectory = dirname9(loaded.configFile);
|
|
4471
4783
|
declared = collectDeclaredReferences(loaded.project);
|
|
4472
4784
|
} catch (error) {
|
|
4473
4785
|
return emitFailure(
|
|
@@ -4620,8 +4932,8 @@ function withLockOptions(command2, dependencies) {
|
|
|
4620
4932
|
function collectDeclaredReferences(project) {
|
|
4621
4933
|
const references = [];
|
|
4622
4934
|
const seen = /* @__PURE__ */ new Set();
|
|
4623
|
-
for (const mapName of
|
|
4624
|
-
const sources =
|
|
4935
|
+
for (const mapName of getTileflowMapNames4(project).sort(compareCodeUnits7)) {
|
|
4936
|
+
const sources = parseResolvedTileflowMap3(project.maps[mapName]).icons ?? [];
|
|
4625
4937
|
for (const reference of collectTileflowIconSetReferences(sources)) {
|
|
4626
4938
|
if (seen.has(reference)) continue;
|
|
4627
4939
|
seen.add(reference);
|
|
@@ -4669,7 +4981,7 @@ async function readCurrentPins(contents) {
|
|
|
4669
4981
|
import { readFile as readFile4 } from "fs/promises";
|
|
4670
4982
|
import { fileURLToPath } from "url";
|
|
4671
4983
|
import {
|
|
4672
|
-
serializeCanonicalJson as
|
|
4984
|
+
serializeCanonicalJson as serializeCanonicalJson3,
|
|
4673
4985
|
tileflowAuthoringManifest
|
|
4674
4986
|
} from "@tileflow/core";
|
|
4675
4987
|
import {
|
|
@@ -4697,21 +5009,21 @@ async function runLanguageCommand(command2, options, operation) {
|
|
|
4697
5009
|
try {
|
|
4698
5010
|
await operation();
|
|
4699
5011
|
} catch (error) {
|
|
4700
|
-
const
|
|
5012
|
+
const failure2 = createTileflowCommandFailureDocument3(command2, error, process.cwd(), {
|
|
4701
5013
|
code: command2 === "language-manifest" ? "LANGUAGE_MANIFEST_FAILED" : "LANGUAGE_SCHEMA_FAILED",
|
|
4702
5014
|
phase: "language-discovery"
|
|
4703
5015
|
});
|
|
4704
|
-
if (options.json) process.stderr.write(serializeTileflowCommandDocument3(
|
|
5016
|
+
if (options.json) process.stderr.write(serializeTileflowCommandDocument3(failure2));
|
|
4705
5017
|
else {
|
|
4706
|
-
console.error(`${
|
|
4707
|
-
console.error(`Suggestion: ${
|
|
5018
|
+
console.error(`${failure2.message} [${failure2.code}; ${failure2.phase}]`);
|
|
5019
|
+
console.error(`Suggestion: ${failure2.suggestion}`);
|
|
4708
5020
|
}
|
|
4709
5021
|
process.exitCode = 1;
|
|
4710
5022
|
}
|
|
4711
5023
|
}
|
|
4712
5024
|
function printManifest(manifest, options) {
|
|
4713
5025
|
if (options.json) {
|
|
4714
|
-
process.stdout.write(`${
|
|
5026
|
+
process.stdout.write(`${serializeCanonicalJson3(manifest)}
|
|
4715
5027
|
`);
|
|
4716
5028
|
return;
|
|
4717
5029
|
}
|
|
@@ -4722,7 +5034,7 @@ function printManifest(manifest, options) {
|
|
|
4722
5034
|
}
|
|
4723
5035
|
function printSchema(schema, options) {
|
|
4724
5036
|
if (options.json) {
|
|
4725
|
-
process.stdout.write(`${
|
|
5037
|
+
process.stdout.write(`${serializeCanonicalJson3(schema)}
|
|
4726
5038
|
`);
|
|
4727
5039
|
return;
|
|
4728
5040
|
}
|
|
@@ -4742,6 +5054,62 @@ function isRecord(value) {
|
|
|
4742
5054
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
4743
5055
|
}
|
|
4744
5056
|
|
|
5057
|
+
// src/native-preview-command.ts
|
|
5058
|
+
import { tileflowNativeProfile } from "@tileflow/core/native-profile";
|
|
5059
|
+
import {
|
|
5060
|
+
createTileflowDevRequestHandler
|
|
5061
|
+
} from "@tileflow/dev/server";
|
|
5062
|
+
var tileflowNativePreviewBasePath = "/native";
|
|
5063
|
+
var tileflowNativePreviewProfile = tileflowNativeProfile.id;
|
|
5064
|
+
function getTileflowNativePreviewManifestUrl(origin) {
|
|
5065
|
+
return `${origin}${tileflowNativePreviewBasePath}/manifest.json`;
|
|
5066
|
+
}
|
|
5067
|
+
function resolveTileflowNativePreviewSelection(manifest, options) {
|
|
5068
|
+
const mapNames = Object.keys(manifest.maps).sort();
|
|
5069
|
+
const mapName = options.map ?? (mapNames.length === 1 ? mapNames[0] : void 0);
|
|
5070
|
+
if (!mapName || !Object.hasOwn(manifest.maps, mapName)) {
|
|
5071
|
+
throw new Error(
|
|
5072
|
+
options.map ? "The selected map is not present in the native artifact manifest." : "Select one configured map with --map for native artifact preview."
|
|
5073
|
+
);
|
|
5074
|
+
}
|
|
5075
|
+
const map = manifest.maps[mapName];
|
|
5076
|
+
const themeName = options.theme ?? map.defaultTheme;
|
|
5077
|
+
if (!Object.hasOwn(map.themes, themeName)) {
|
|
5078
|
+
throw new Error("The selected theme is not present in the native artifact manifest.");
|
|
5079
|
+
}
|
|
5080
|
+
return Object.freeze({ mapName, themeName });
|
|
5081
|
+
}
|
|
5082
|
+
var nativePreviewUnavailablePaths = /* @__PURE__ */ new Set([
|
|
5083
|
+
`${tileflowNativePreviewBasePath}/__events`,
|
|
5084
|
+
`${tileflowNativePreviewBasePath}/__status`
|
|
5085
|
+
]);
|
|
5086
|
+
function createTileflowNativePreviewRequestHandler(options) {
|
|
5087
|
+
const delegate = createTileflowDevRequestHandler({
|
|
5088
|
+
...options,
|
|
5089
|
+
basePath: tileflowNativePreviewBasePath
|
|
5090
|
+
});
|
|
5091
|
+
const notFound = () => new Response(JSON.stringify({ error: "Not found" }), {
|
|
5092
|
+
headers: { "Content-Type": "application/json; charset=utf-8" },
|
|
5093
|
+
status: 404
|
|
5094
|
+
});
|
|
5095
|
+
const handler = async (request) => {
|
|
5096
|
+
let pathname;
|
|
5097
|
+
try {
|
|
5098
|
+
pathname = new URL(request.url).pathname;
|
|
5099
|
+
} catch {
|
|
5100
|
+
return notFound();
|
|
5101
|
+
}
|
|
5102
|
+
if (pathname === tileflowNativePreviewBasePath || pathname === `${tileflowNativePreviewBasePath}/` || nativePreviewUnavailablePaths.has(pathname) || pathname.startsWith(`${tileflowNativePreviewBasePath}/__runtime/`) || pathname.startsWith(`${tileflowNativePreviewBasePath}/__inspection/`)) {
|
|
5103
|
+
return notFound();
|
|
5104
|
+
}
|
|
5105
|
+
return delegate(request);
|
|
5106
|
+
};
|
|
5107
|
+
return Object.assign(handler, {
|
|
5108
|
+
close: delegate.close,
|
|
5109
|
+
refresh: delegate.refresh
|
|
5110
|
+
});
|
|
5111
|
+
}
|
|
5112
|
+
|
|
4745
5113
|
// src/open-external.ts
|
|
4746
5114
|
import { spawn as spawnChild } from "child_process";
|
|
4747
5115
|
import { platform as hostPlatform } from "os";
|
|
@@ -5056,17 +5424,126 @@ function safeMessage2(error) {
|
|
|
5056
5424
|
return error instanceof Error && error.message.length <= 300 ? error.message : "Tileflow auth state is unavailable.";
|
|
5057
5425
|
}
|
|
5058
5426
|
|
|
5427
|
+
// src/renderer-artifact-command.ts
|
|
5428
|
+
import { resolve as resolve5 } from "path";
|
|
5429
|
+
import { auditTileflowMapThemeValues } from "@tileflow/core";
|
|
5430
|
+
import {
|
|
5431
|
+
createTileflowNativeDiagnostic,
|
|
5432
|
+
resolveTileflowRenderer,
|
|
5433
|
+
TileflowNativeCompatibilityError
|
|
5434
|
+
} from "@tileflow/core/native-profile";
|
|
5435
|
+
import {
|
|
5436
|
+
createTileflowBuildArtifacts,
|
|
5437
|
+
disposeTileflowBuildArtifacts,
|
|
5438
|
+
writeTileflowArtifactPlan
|
|
5439
|
+
} from "@tileflow/dev/artifacts";
|
|
5440
|
+
import {
|
|
5441
|
+
createTileflowCommandFailureDocument as createTileflowCommandFailureDocument4,
|
|
5442
|
+
createTileflowCommandSummary as createTileflowCommandSummary2,
|
|
5443
|
+
createTileflowStructuredDiagnostics as createTileflowStructuredDiagnostics2,
|
|
5444
|
+
serializeTileflowCommandDocument as serializeTileflowCommandDocument4
|
|
5445
|
+
} from "@tileflow/dev/validation";
|
|
5446
|
+
async function runRendererArtifactCommand(command2, options) {
|
|
5447
|
+
let artifacts;
|
|
5448
|
+
try {
|
|
5449
|
+
const renderer = resolveTileflowRenderer(options.renderer);
|
|
5450
|
+
if (options.target !== "local" && options.target !== "hosted") {
|
|
5451
|
+
throw Object.assign(new Error("Expected a local or hosted target."), {
|
|
5452
|
+
code: "INVALID_TARGET",
|
|
5453
|
+
phase: "command-validation",
|
|
5454
|
+
path: "target"
|
|
5455
|
+
});
|
|
5456
|
+
}
|
|
5457
|
+
if (renderer === "native" && options.target === "hosted") {
|
|
5458
|
+
throw new TileflowNativeCompatibilityError([
|
|
5459
|
+
createTileflowNativeDiagnostic("NATIVE_RENDERER_UNSUPPORTED", "/target")
|
|
5460
|
+
]);
|
|
5461
|
+
}
|
|
5462
|
+
if (command2 === "build" && options.target === "hosted") {
|
|
5463
|
+
throw Object.assign(
|
|
5464
|
+
new Error("Build prepares local artifacts; Hosted publication uses deploy."),
|
|
5465
|
+
{
|
|
5466
|
+
code: "HOSTED_INCOMPATIBLE",
|
|
5467
|
+
phase: "command-validation",
|
|
5468
|
+
path: "target",
|
|
5469
|
+
suggestion: "Use validate --target hosted for web preflight, or build --target local."
|
|
5470
|
+
}
|
|
5471
|
+
);
|
|
5472
|
+
}
|
|
5473
|
+
artifacts = await withTileflowConfigSecretsHidden(
|
|
5474
|
+
() => createTileflowBuildArtifacts({
|
|
5475
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
5476
|
+
config: options.config,
|
|
5477
|
+
...options.icons ? { icons: options.icons } : {},
|
|
5478
|
+
renderer,
|
|
5479
|
+
styleBaseUrl: ".",
|
|
5480
|
+
target: "production"
|
|
5481
|
+
})
|
|
5482
|
+
);
|
|
5483
|
+
const outDir = options.out ?? "dist/tileflow";
|
|
5484
|
+
if (command2 === "build") await writeTileflowArtifactPlan(artifacts, { outDir });
|
|
5485
|
+
const summary = createTileflowCommandSummary2({
|
|
5486
|
+
code: command2 === "validate" ? "VALIDATION_OK" : "BUILD_OK",
|
|
5487
|
+
command: command2,
|
|
5488
|
+
message: command2 === "validate" ? "Tileflow artifact validation passed." : "Built Tileflow artifacts.",
|
|
5489
|
+
ok: true,
|
|
5490
|
+
phase: command2 === "validate" ? "validation" : "build",
|
|
5491
|
+
severity: "info",
|
|
5492
|
+
suggestion: renderer === "native" ? "Use the prepared native manifest with a separately qualified native runtime." : "Serve the prepared artifact directory."
|
|
5493
|
+
});
|
|
5494
|
+
const warnings = Object.values(artifacts.project.maps).flatMap(
|
|
5495
|
+
(map) => auditTileflowMapThemeValues(map).filter(({ severity }) => severity === "warning")
|
|
5496
|
+
);
|
|
5497
|
+
const diagnostics = warnings.length ? createTileflowStructuredDiagnostics2({ diagnostics: warnings }, process.cwd(), {
|
|
5498
|
+
code: "VALIDATION_WARNING",
|
|
5499
|
+
phase: "theme-audit"
|
|
5500
|
+
}) : [];
|
|
5501
|
+
const document = {
|
|
5502
|
+
...summary,
|
|
5503
|
+
target: options.target,
|
|
5504
|
+
renderer,
|
|
5505
|
+
...artifacts.nativeBuild ? { profile: artifacts.nativeBuild.profile, validation: "static-artifacts" } : {},
|
|
5506
|
+
maps: Object.keys(artifacts.project.maps).sort(),
|
|
5507
|
+
diagnostics
|
|
5508
|
+
};
|
|
5509
|
+
if (options.json) process.stdout.write(serializeTileflowCommandDocument4(document));
|
|
5510
|
+
else {
|
|
5511
|
+
console.log(summary.message);
|
|
5512
|
+
for (const issue of diagnostics) console.warn(`${issue.path}: ${issue.message}`);
|
|
5513
|
+
if (artifacts.nativeBuild)
|
|
5514
|
+
console.log("Profile: native-v1 (static artifacts; no device qualification).");
|
|
5515
|
+
if (command2 === "build")
|
|
5516
|
+
console.log(`Output: ${resolve5(outDir, ...renderer === "native" ? ["native"] : [])}`);
|
|
5517
|
+
}
|
|
5518
|
+
} catch (error) {
|
|
5519
|
+
const document = createTileflowCommandFailureDocument4(command2, error, process.cwd(), {
|
|
5520
|
+
code: command2 === "validate" ? "VALIDATION_FAILED" : "BUILD_FAILED",
|
|
5521
|
+
phase: "artifact-preparation"
|
|
5522
|
+
});
|
|
5523
|
+
if (options.json) process.stderr.write(serializeTileflowCommandDocument4(document));
|
|
5524
|
+
else {
|
|
5525
|
+
for (const issue of document.diagnostics) {
|
|
5526
|
+
console.error(`${issue.code} ${issue.path || "(root)"}: ${issue.message}`);
|
|
5527
|
+
console.error(`Suggestion: ${issue.suggestion}`);
|
|
5528
|
+
}
|
|
5529
|
+
}
|
|
5530
|
+
process.exitCode = 1;
|
|
5531
|
+
} finally {
|
|
5532
|
+
if (artifacts) await disposeTileflowBuildArtifacts(artifacts);
|
|
5533
|
+
}
|
|
5534
|
+
}
|
|
5535
|
+
|
|
5059
5536
|
// src/tileset-command.ts
|
|
5060
5537
|
import pc5 from "picocolors";
|
|
5061
|
-
import {
|
|
5538
|
+
import { z as z6 } from "zod";
|
|
5539
|
+
import { serializeCanonicalJson as serializeCanonicalJson5 } from "@tileflow/core";
|
|
5062
5540
|
import { inspectTileflowPmtiles } from "@tileflow/dev/tilesets";
|
|
5063
|
-
import { z as z7 } from "zod";
|
|
5064
5541
|
|
|
5065
5542
|
// src/tileset-upload.ts
|
|
5066
5543
|
import { createHash } from "crypto";
|
|
5067
5544
|
import { open as open4, stat } from "fs/promises";
|
|
5068
|
-
import { z as
|
|
5069
|
-
import { serializeCanonicalJson as
|
|
5545
|
+
import { z as z5 } from "zod";
|
|
5546
|
+
import { serializeCanonicalJson as serializeCanonicalJson4 } from "@tileflow/core";
|
|
5070
5547
|
var teamTilesetPartSize = 16777216;
|
|
5071
5548
|
var maximumTeamTilesetBytes = 4e9;
|
|
5072
5549
|
var authorizationBatchSize = 16;
|
|
@@ -5206,7 +5683,7 @@ async function prepareTeamTilesetUpload(file) {
|
|
|
5206
5683
|
};
|
|
5207
5684
|
return Object.freeze({
|
|
5208
5685
|
byteCount: identity.size,
|
|
5209
|
-
contentHash: createHash("sha256").update(
|
|
5686
|
+
contentHash: createHash("sha256").update(serializeCanonicalJson4(contentIdentity)).digest("hex"),
|
|
5210
5687
|
contentHashAlgorithm: "sha256-fixed-parts-v1",
|
|
5211
5688
|
identity,
|
|
5212
5689
|
partSize: teamTilesetPartSize,
|
|
@@ -5222,7 +5699,7 @@ function createTeamTilesetUploadIdempotencyKey(tilesetId, upload) {
|
|
|
5222
5699
|
);
|
|
5223
5700
|
}
|
|
5224
5701
|
return createHash("sha256").update(
|
|
5225
|
-
|
|
5702
|
+
serializeCanonicalJson4({
|
|
5226
5703
|
byteCount: upload.byteCount,
|
|
5227
5704
|
contentHash: upload.contentHash,
|
|
5228
5705
|
contentHashAlgorithm: upload.contentHashAlgorithm,
|
|
@@ -5626,36 +6103,36 @@ function asRecord3(value) {
|
|
|
5626
6103
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
5627
6104
|
}
|
|
5628
6105
|
function defaultSleep(milliseconds) {
|
|
5629
|
-
return new Promise((
|
|
5630
|
-
}
|
|
5631
|
-
var identifierSchema =
|
|
5632
|
-
var uploadPartStatusSchema =
|
|
5633
|
-
byteCount:
|
|
5634
|
-
partNumber:
|
|
5635
|
-
uploaded:
|
|
5636
|
-
validationState:
|
|
6106
|
+
return new Promise((resolve9) => setTimeout(resolve9, milliseconds));
|
|
6107
|
+
}
|
|
6108
|
+
var identifierSchema = z5.string().min(20).max(80).regex(/^[A-Za-z0-9_-]+$/u);
|
|
6109
|
+
var uploadPartStatusSchema = z5.object({
|
|
6110
|
+
byteCount: z5.number().int().min(1).max(teamTilesetPartSize),
|
|
6111
|
+
partNumber: z5.number().int().min(1).max(239),
|
|
6112
|
+
uploaded: z5.boolean(),
|
|
6113
|
+
validationState: z5.enum(["mismatch", "pending", "processing", "valid"])
|
|
5637
6114
|
}).strict();
|
|
5638
|
-
var publishedVersionSchema =
|
|
5639
|
-
byteCount:
|
|
5640
|
-
contentHash:
|
|
5641
|
-
contentHashAlgorithm:
|
|
5642
|
-
publishedVersion:
|
|
5643
|
-
schemaVersion:
|
|
5644
|
-
state:
|
|
6115
|
+
var publishedVersionSchema = z5.object({
|
|
6116
|
+
byteCount: z5.number().int().min(1).max(maximumTeamTilesetBytes),
|
|
6117
|
+
contentHash: z5.string().regex(/^[0-9a-f]{64}$/u),
|
|
6118
|
+
contentHashAlgorithm: z5.literal("sha256-fixed-parts-v1"),
|
|
6119
|
+
publishedVersion: z5.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
6120
|
+
schemaVersion: z5.literal(1),
|
|
6121
|
+
state: z5.literal("published"),
|
|
5645
6122
|
versionId: identifierSchema.regex(/^tsv_[A-Za-z0-9_-]+$/u)
|
|
5646
6123
|
}).strict();
|
|
5647
|
-
var uploadControlSchema =
|
|
5648
|
-
byteCount:
|
|
5649
|
-
contentHash:
|
|
5650
|
-
contentHashAlgorithm:
|
|
5651
|
-
expiresAt:
|
|
5652
|
-
failure:
|
|
5653
|
-
partCount:
|
|
5654
|
-
parts:
|
|
5655
|
-
partSize:
|
|
5656
|
-
publishedVersion:
|
|
5657
|
-
schemaVersion:
|
|
5658
|
-
state:
|
|
6124
|
+
var uploadControlSchema = z5.object({
|
|
6125
|
+
byteCount: z5.number().int().min(1).max(maximumTeamTilesetBytes),
|
|
6126
|
+
contentHash: z5.string().regex(/^[0-9a-f]{64}$/u),
|
|
6127
|
+
contentHashAlgorithm: z5.literal("sha256-fixed-parts-v1"),
|
|
6128
|
+
expiresAt: z5.iso.datetime({ offset: true }),
|
|
6129
|
+
failure: z5.object({ code: z5.string().regex(/^TF_[A-Z0-9_]{1,96}$/u) }).strict().nullable(),
|
|
6130
|
+
partCount: z5.number().int().min(1).max(239),
|
|
6131
|
+
parts: z5.array(uploadPartStatusSchema).max(239),
|
|
6132
|
+
partSize: z5.literal(teamTilesetPartSize),
|
|
6133
|
+
publishedVersion: z5.null(),
|
|
6134
|
+
schemaVersion: z5.literal(1),
|
|
6135
|
+
state: z5.enum([
|
|
5659
6136
|
"aborted",
|
|
5660
6137
|
"aborting",
|
|
5661
6138
|
"expired",
|
|
@@ -5668,32 +6145,32 @@ var uploadControlSchema = z6.object({
|
|
|
5668
6145
|
"uploading",
|
|
5669
6146
|
"validating"
|
|
5670
6147
|
]),
|
|
5671
|
-
uploadId:
|
|
5672
|
-
versionId:
|
|
6148
|
+
uploadId: z5.string().min(20).max(80).regex(/^tsu_[A-Za-z0-9_-]+$/u),
|
|
6149
|
+
versionId: z5.null()
|
|
5673
6150
|
}).strict();
|
|
5674
|
-
var uploadSessionSchema =
|
|
5675
|
-
var authorizationSchema =
|
|
5676
|
-
expiresAt:
|
|
5677
|
-
headers:
|
|
5678
|
-
"Content-Length":
|
|
5679
|
-
"Content-MD5":
|
|
6151
|
+
var uploadSessionSchema = z5.union([publishedVersionSchema, uploadControlSchema]);
|
|
6152
|
+
var authorizationSchema = z5.object({
|
|
6153
|
+
expiresAt: z5.iso.datetime({ offset: true }),
|
|
6154
|
+
headers: z5.object({
|
|
6155
|
+
"Content-Length": z5.string().regex(/^[1-9][0-9]{0,9}$/u),
|
|
6156
|
+
"Content-MD5": z5.string().regex(/^[A-Za-z0-9+/]{22}==$/u)
|
|
5680
6157
|
}).strict(),
|
|
5681
|
-
method:
|
|
5682
|
-
partNumber:
|
|
5683
|
-
url:
|
|
6158
|
+
method: z5.literal("PUT"),
|
|
6159
|
+
partNumber: z5.number().int().min(1).max(239),
|
|
6160
|
+
url: z5.url().max(8192).refine((value) => {
|
|
5684
6161
|
const url = new URL(value);
|
|
5685
6162
|
return url.protocol === "https:" && !url.username && !url.password && !url.hash;
|
|
5686
6163
|
})
|
|
5687
6164
|
}).strict();
|
|
5688
|
-
var authorizationResponseSchema =
|
|
5689
|
-
authorizations:
|
|
5690
|
-
schemaVersion:
|
|
6165
|
+
var authorizationResponseSchema = z5.object({
|
|
6166
|
+
authorizations: z5.array(authorizationSchema).min(1).max(16),
|
|
6167
|
+
schemaVersion: z5.literal(1)
|
|
5691
6168
|
}).strict();
|
|
5692
|
-
var partReceiptResponseSchema =
|
|
5693
|
-
changed:
|
|
5694
|
-
etag:
|
|
5695
|
-
partNumber:
|
|
5696
|
-
schemaVersion:
|
|
6169
|
+
var partReceiptResponseSchema = z5.object({
|
|
6170
|
+
changed: z5.boolean(),
|
|
6171
|
+
etag: z5.string().regex(/^[0-9a-f]{32}$/u),
|
|
6172
|
+
partNumber: z5.number().int().min(1).max(239),
|
|
6173
|
+
schemaVersion: z5.literal(1)
|
|
5697
6174
|
}).strict();
|
|
5698
6175
|
|
|
5699
6176
|
// src/tileset-command.ts
|
|
@@ -5713,7 +6190,7 @@ function registerTilesetCommands(program2, dependencies) {
|
|
|
5713
6190
|
sample: options.sample
|
|
5714
6191
|
});
|
|
5715
6192
|
if (options.json) {
|
|
5716
|
-
process.stdout.write(`${
|
|
6193
|
+
process.stdout.write(`${serializeCanonicalJson5(inspection)}
|
|
5717
6194
|
`);
|
|
5718
6195
|
return;
|
|
5719
6196
|
}
|
|
@@ -5736,7 +6213,7 @@ function registerTilesetCommands(program2, dependencies) {
|
|
|
5736
6213
|
const message = error instanceof Error ? error.message : "Tileset inspection failed.";
|
|
5737
6214
|
if (options.json) {
|
|
5738
6215
|
process.stderr.write(
|
|
5739
|
-
`${
|
|
6216
|
+
`${serializeCanonicalJson5({ error: { code, message, path }, ok: false, schemaVersion: 1 })}
|
|
5740
6217
|
`
|
|
5741
6218
|
);
|
|
5742
6219
|
} else {
|
|
@@ -5987,69 +6464,69 @@ function inspectionOptionError(message) {
|
|
|
5987
6464
|
function asRecord4(value) {
|
|
5988
6465
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
5989
6466
|
}
|
|
5990
|
-
var safeIdentifierSchema2 =
|
|
5991
|
-
var physicalTilesetIdSchema =
|
|
5992
|
-
var cursorSchema2 =
|
|
5993
|
-
var tilesetInventoryItemSchema =
|
|
5994
|
-
currentVersion:
|
|
5995
|
-
hasCurrent:
|
|
6467
|
+
var safeIdentifierSchema2 = z6.string().min(1).max(160).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/u);
|
|
6468
|
+
var physicalTilesetIdSchema = z6.string().min(20).max(80).regex(/^tls_[A-Za-z0-9_-]+$/u);
|
|
6469
|
+
var cursorSchema2 = z6.string().min(1).max(2048).nullable();
|
|
6470
|
+
var tilesetInventoryItemSchema = z6.object({
|
|
6471
|
+
currentVersion: z6.number().int().positive().max(Number.MAX_SAFE_INTEGER).nullable(),
|
|
6472
|
+
hasCurrent: z6.boolean(),
|
|
5996
6473
|
id: physicalTilesetIdSchema,
|
|
5997
|
-
logicalName:
|
|
5998
|
-
name:
|
|
5999
|
-
retainedBytes:
|
|
6000
|
-
retainedDeploymentCount:
|
|
6001
|
-
status:
|
|
6002
|
-
updatedAt:
|
|
6003
|
-
usedByMapCount:
|
|
6474
|
+
logicalName: z6.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/u),
|
|
6475
|
+
name: z6.string().min(1).max(200),
|
|
6476
|
+
retainedBytes: z6.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
|
6477
|
+
retainedDeploymentCount: z6.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
|
6478
|
+
status: z6.enum(["active", "purging", "retired"]),
|
|
6479
|
+
updatedAt: z6.iso.datetime({ offset: true }),
|
|
6480
|
+
usedByMapCount: z6.number().int().min(0).max(Number.MAX_SAFE_INTEGER)
|
|
6004
6481
|
}).strict();
|
|
6005
|
-
var tilesetListResponseSchema =
|
|
6482
|
+
var tilesetListResponseSchema = z6.object({
|
|
6006
6483
|
nextCursor: cursorSchema2.optional(),
|
|
6007
|
-
schemaVersion:
|
|
6008
|
-
tilesets:
|
|
6484
|
+
schemaVersion: z6.literal(1),
|
|
6485
|
+
tilesets: z6.array(tilesetInventoryItemSchema).max(100)
|
|
6009
6486
|
}).strict();
|
|
6010
|
-
var tilesetDependencySchema =
|
|
6011
|
-
active:
|
|
6487
|
+
var tilesetDependencySchema = z6.object({
|
|
6488
|
+
active: z6.boolean(),
|
|
6012
6489
|
deploymentId: safeIdentifierSchema2,
|
|
6013
|
-
deploymentVersion:
|
|
6014
|
-
environment:
|
|
6490
|
+
deploymentVersion: z6.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
6491
|
+
environment: z6.string().min(1).max(64),
|
|
6015
6492
|
mapId: safeIdentifierSchema2,
|
|
6016
6493
|
sourceId: safeIdentifierSchema2
|
|
6017
6494
|
}).strict();
|
|
6018
|
-
var tilesetDetailResponseSchema =
|
|
6019
|
-
schemaVersion:
|
|
6020
|
-
tileset:
|
|
6021
|
-
attribution:
|
|
6022
|
-
currentVersion:
|
|
6023
|
-
dependencies:
|
|
6495
|
+
var tilesetDetailResponseSchema = z6.object({
|
|
6496
|
+
schemaVersion: z6.literal(1),
|
|
6497
|
+
tileset: z6.object({
|
|
6498
|
+
attribution: z6.string().max(4096).nullable(),
|
|
6499
|
+
currentVersion: z6.number().int().positive().max(Number.MAX_SAFE_INTEGER).nullable(),
|
|
6500
|
+
dependencies: z6.array(tilesetDependencySchema).max(25),
|
|
6024
6501
|
dependencyNextCursor: cursorSchema2,
|
|
6025
6502
|
id: physicalTilesetIdSchema,
|
|
6026
|
-
name:
|
|
6027
|
-
slug:
|
|
6028
|
-
state:
|
|
6503
|
+
name: z6.string().min(1).max(200),
|
|
6504
|
+
slug: z6.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/u),
|
|
6505
|
+
state: z6.enum(["active", "purging", "purged"])
|
|
6029
6506
|
}).strict()
|
|
6030
6507
|
}).strict();
|
|
6031
|
-
var purgeDependencySchema =
|
|
6508
|
+
var purgeDependencySchema = z6.object({
|
|
6032
6509
|
deploymentId: safeIdentifierSchema2,
|
|
6033
6510
|
mapId: safeIdentifierSchema2,
|
|
6034
6511
|
sourceId: safeIdentifierSchema2
|
|
6035
6512
|
}).strict();
|
|
6036
|
-
var tilesetInUseResponseSchema =
|
|
6037
|
-
code:
|
|
6038
|
-
dependencies:
|
|
6039
|
-
error:
|
|
6513
|
+
var tilesetInUseResponseSchema = z6.object({
|
|
6514
|
+
code: z6.literal("TF_TILESET_IN_USE"),
|
|
6515
|
+
dependencies: z6.array(purgeDependencySchema).max(32),
|
|
6516
|
+
error: z6.literal("Tileset is used by retained Map deployments"),
|
|
6040
6517
|
nextCursor: cursorSchema2
|
|
6041
6518
|
}).strict();
|
|
6042
|
-
var tilesetPurgeResponseSchema =
|
|
6043
|
-
deliveryFence:
|
|
6044
|
-
pendingVersions:
|
|
6045
|
-
reclamation:
|
|
6046
|
-
state:
|
|
6519
|
+
var tilesetPurgeResponseSchema = z6.object({
|
|
6520
|
+
deliveryFence: z6.enum(["complete", "pending"]),
|
|
6521
|
+
pendingVersions: z6.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
|
|
6522
|
+
reclamation: z6.enum(["complete", "pending"]),
|
|
6523
|
+
state: z6.enum(["purged", "purging"]),
|
|
6047
6524
|
tilesetId: physicalTilesetIdSchema
|
|
6048
6525
|
}).strict();
|
|
6049
6526
|
|
|
6050
6527
|
// src/visual-command.ts
|
|
6051
6528
|
import { lstat as lstat4, readFile as readFile6 } from "fs/promises";
|
|
6052
|
-
import { dirname as
|
|
6529
|
+
import { dirname as dirname11, isAbsolute as isAbsolute4, parse as parse2, relative as relative4, resolve as resolve7, sep as sep4 } from "path";
|
|
6053
6530
|
import {
|
|
6054
6531
|
analyzeTileflowCaptureReference,
|
|
6055
6532
|
compareTileflowCaptureToBaseline,
|
|
@@ -6068,7 +6545,7 @@ import { compareCodeUnits as compareCodeUnits9 } from "@tileflow/core";
|
|
|
6068
6545
|
// src/visual-compare-command.ts
|
|
6069
6546
|
import { createHash as createHash3 } from "crypto";
|
|
6070
6547
|
import { lstat as lstat3, readFile as readFile5, realpath } from "fs/promises";
|
|
6071
|
-
import { basename as basename3, dirname as
|
|
6548
|
+
import { basename as basename3, dirname as dirname10, extname, isAbsolute as isAbsolute3, parse, relative as relative3, resolve as resolve6, sep as sep3 } from "path";
|
|
6072
6549
|
import {
|
|
6073
6550
|
compareTileflowCapturesForReview,
|
|
6074
6551
|
createTileflowCaptureSession as createTileflowCaptureSession2,
|
|
@@ -6079,14 +6556,14 @@ import {
|
|
|
6079
6556
|
import {
|
|
6080
6557
|
compareCodeUnits as compareCodeUnits8,
|
|
6081
6558
|
normalizeTileflowCaptureScene as normalizeTileflowCaptureScene2,
|
|
6082
|
-
parseResolvedTileflowMap as
|
|
6559
|
+
parseResolvedTileflowMap as parseResolvedTileflowMap4,
|
|
6083
6560
|
resolveThemeSelection,
|
|
6084
6561
|
tileflowCaptureSceneLimits
|
|
6085
6562
|
} from "@tileflow/core";
|
|
6086
6563
|
import {
|
|
6087
6564
|
createTileflowArtifactDiagnostics as createTileflowArtifactDiagnostics2,
|
|
6088
6565
|
createTileflowArtifactSession as createTileflowArtifactSession2,
|
|
6089
|
-
createTileflowBuildArtifacts
|
|
6566
|
+
createTileflowBuildArtifacts as createTileflowBuildArtifacts2
|
|
6090
6567
|
} from "@tileflow/dev/artifacts";
|
|
6091
6568
|
|
|
6092
6569
|
// src/visual-compare-report.ts
|
|
@@ -6381,15 +6858,15 @@ async function parseVisualComparePlan(options) {
|
|
|
6381
6858
|
}
|
|
6382
6859
|
async function createArtifactPair(plan) {
|
|
6383
6860
|
const cwd = process.cwd();
|
|
6384
|
-
const leftPath = portablePathIdentity(
|
|
6385
|
-
const rightPath = portablePathIdentity(
|
|
6386
|
-
const left = await
|
|
6861
|
+
const leftPath = portablePathIdentity(resolve6(cwd, plan.config));
|
|
6862
|
+
const rightPath = portablePathIdentity(resolve6(cwd, plan.againstConfig));
|
|
6863
|
+
const left = await createTileflowBuildArtifacts2({
|
|
6387
6864
|
assetBaseUrl: tileflowSyntheticAssetOrigin2,
|
|
6388
6865
|
config: plan.config,
|
|
6389
6866
|
cwd
|
|
6390
6867
|
});
|
|
6391
6868
|
if (leftPath === rightPath) return [left, left];
|
|
6392
|
-
const right = await
|
|
6869
|
+
const right = await createTileflowBuildArtifacts2({
|
|
6393
6870
|
assetBaseUrl: tileflowSyntheticAssetOrigin2,
|
|
6394
6871
|
config: plan.againstConfig,
|
|
6395
6872
|
cwd
|
|
@@ -6534,7 +7011,7 @@ async function prepareVisualCompareOutput(plan, leftArtifacts, rightArtifacts, c
|
|
|
6534
7011
|
files,
|
|
6535
7012
|
incompatible,
|
|
6536
7013
|
nextAssets: inventory.assets.map((asset) => ({
|
|
6537
|
-
path:
|
|
7014
|
+
path: resolve6(plan.output.assetDirectory, asset.path),
|
|
6538
7015
|
sha256: asset.sha256
|
|
6539
7016
|
})),
|
|
6540
7017
|
removePaths: [...new Set(removePaths)].filter((path) => !filePaths.has(path))
|
|
@@ -6553,7 +7030,7 @@ async function writePreparedVisualCompareOutput(output, prepared) {
|
|
|
6553
7030
|
async function runVisualCompareWatch(plan, openReport) {
|
|
6554
7031
|
const cwd = process.cwd();
|
|
6555
7032
|
const controller = installSignalAbortController();
|
|
6556
|
-
const sameConfig = portablePathIdentity(
|
|
7033
|
+
const sameConfig = portablePathIdentity(resolve6(cwd, plan.config)) === portablePathIdentity(resolve6(cwd, plan.againstConfig));
|
|
6557
7034
|
let leftSession;
|
|
6558
7035
|
let rightSession;
|
|
6559
7036
|
let captureSession;
|
|
@@ -6810,7 +7287,7 @@ function resolveVisualCompareSide(artifacts, config, requestedMap, requestedThem
|
|
|
6810
7287
|
`Unknown ${role} map "${map}". Available maps: ${availableMaps.join(", ") || "(none)"}.`
|
|
6811
7288
|
);
|
|
6812
7289
|
}
|
|
6813
|
-
const resolvedMap =
|
|
7290
|
+
const resolvedMap = parseResolvedTileflowMap4(candidate);
|
|
6814
7291
|
const theme = resolveThemeSelection(resolvedMap, requestedTheme).name;
|
|
6815
7292
|
if (!artifacts.styles[map]?.[theme]) {
|
|
6816
7293
|
throw new Error(`The ${role} map theme "${map}/${theme}" was not compiled.`);
|
|
@@ -6862,11 +7339,11 @@ function requireCapture(captures, scene, role) {
|
|
|
6862
7339
|
return capture;
|
|
6863
7340
|
}
|
|
6864
7341
|
async function resolveVisualCompareOutput(cwd, value, managed, force, watch, zooms) {
|
|
6865
|
-
const reportPath =
|
|
7342
|
+
const reportPath = resolve6(cwd, value);
|
|
6866
7343
|
if (extname(reportPath).toLowerCase() !== ".html") {
|
|
6867
7344
|
throw new Error("--report must name an .html file.");
|
|
6868
7345
|
}
|
|
6869
|
-
const reportDirectory =
|
|
7346
|
+
const reportDirectory = dirname10(reportPath);
|
|
6870
7347
|
if (reportDirectory === cwd || reportDirectory === parse(reportPath).root) {
|
|
6871
7348
|
throw new Error("Visual compare output must use a dedicated subdirectory.");
|
|
6872
7349
|
}
|
|
@@ -6876,7 +7353,7 @@ async function resolveVisualCompareOutput(cwd, value, managed, force, watch, zoo
|
|
|
6876
7353
|
const stem = reportPath.slice(0, -".html".length);
|
|
6877
7354
|
const documentPath = `${stem}.json`;
|
|
6878
7355
|
const assetDirectory = `${stem}.assets`;
|
|
6879
|
-
const inventoryPath =
|
|
7356
|
+
const inventoryPath = resolve6(assetDirectory, tileflowVisualCompareInventoryFileName);
|
|
6880
7357
|
const boundary = isInside(cwd, reportDirectory) ? cwd : reportDirectory;
|
|
6881
7358
|
await assertNoSymlinkComponents(reportDirectory, boundary);
|
|
6882
7359
|
await assertNoSymlinkComponents(assetDirectory, boundary);
|
|
@@ -6916,16 +7393,16 @@ async function resolveVisualCompareOutput(cwd, value, managed, force, watch, zoo
|
|
|
6916
7393
|
function visualCompareRowPaths(output, index, zoom, includeDiff) {
|
|
6917
7394
|
const prefix = `${String(index + 1).padStart(2, "0")}-z${zoomSlug(zoom)}`;
|
|
6918
7395
|
return {
|
|
6919
|
-
leftPath:
|
|
6920
|
-
rightPath:
|
|
6921
|
-
leftReceiptPath:
|
|
6922
|
-
rightReceiptPath:
|
|
6923
|
-
diffPath: includeDiff ?
|
|
7396
|
+
leftPath: resolve6(output.assetDirectory, `${prefix}.left.png`),
|
|
7397
|
+
rightPath: resolve6(output.assetDirectory, `${prefix}.right.png`),
|
|
7398
|
+
leftReceiptPath: resolve6(output.assetDirectory, `${prefix}.left.receipt.json`),
|
|
7399
|
+
rightReceiptPath: resolve6(output.assetDirectory, `${prefix}.right.receipt.json`),
|
|
7400
|
+
diffPath: includeDiff ? resolve6(output.assetDirectory, `${prefix}.diff.png`) : void 0
|
|
6924
7401
|
};
|
|
6925
7402
|
}
|
|
6926
7403
|
function sideJson(side, cwd) {
|
|
6927
7404
|
return {
|
|
6928
|
-
config: relativePath(cwd,
|
|
7405
|
+
config: relativePath(cwd, resolve6(cwd, side.config)),
|
|
6929
7406
|
label: side.label,
|
|
6930
7407
|
map: side.map,
|
|
6931
7408
|
theme: side.theme
|
|
@@ -6933,13 +7410,13 @@ function sideJson(side, cwd) {
|
|
|
6933
7410
|
}
|
|
6934
7411
|
function watchSideLabel(cwd, config, map, theme) {
|
|
6935
7412
|
const selection = map ? `${map} / ${theme ?? "default theme"}` : `singular map / ${theme ?? "default theme"}`;
|
|
6936
|
-
return `${relativePath(cwd,
|
|
7413
|
+
return `${relativePath(cwd, resolve6(cwd, config))} (${selection})`;
|
|
6937
7414
|
}
|
|
6938
7415
|
async function assertVisualCompareOutputDoesNotOverlapInputs(plan, leftArtifacts, rightArtifacts) {
|
|
6939
7416
|
const cwd = process.cwd();
|
|
6940
7417
|
const inputs = mergeVisualCompareInputPaths([
|
|
6941
|
-
{ kind: "file", path:
|
|
6942
|
-
{ kind: "file", path:
|
|
7418
|
+
{ kind: "file", path: resolve6(cwd, plan.config) },
|
|
7419
|
+
{ kind: "file", path: resolve6(cwd, plan.againstConfig) },
|
|
6943
7420
|
...visualCompareArtifactInputPaths(leftArtifacts),
|
|
6944
7421
|
...visualCompareArtifactInputPaths(rightArtifacts)
|
|
6945
7422
|
]);
|
|
@@ -7014,7 +7491,7 @@ function serializeVisualCompareInventory(inventory) {
|
|
|
7014
7491
|
`;
|
|
7015
7492
|
}
|
|
7016
7493
|
async function readVisualCompareInventory(assetDirectory, inventoryPath, boundary) {
|
|
7017
|
-
await assertNoSymlinkComponents(
|
|
7494
|
+
await assertNoSymlinkComponents(dirname10(inventoryPath), boundary);
|
|
7018
7495
|
let info;
|
|
7019
7496
|
try {
|
|
7020
7497
|
info = await lstat3(inventoryPath);
|
|
@@ -7037,8 +7514,8 @@ async function readVisualCompareInventory(assetDirectory, inventoryPath, boundar
|
|
|
7037
7514
|
const inventory = validateVisualCompareInventory(parsed);
|
|
7038
7515
|
const assets = [];
|
|
7039
7516
|
for (const asset of inventory.assets) {
|
|
7040
|
-
const path =
|
|
7041
|
-
await assertNoSymlinkComponents(
|
|
7517
|
+
const path = resolve6(assetDirectory, asset.path);
|
|
7518
|
+
await assertNoSymlinkComponents(dirname10(path), boundary);
|
|
7042
7519
|
let assetInfo;
|
|
7043
7520
|
try {
|
|
7044
7521
|
assetInfo = await lstat3(path);
|
|
@@ -7109,17 +7586,17 @@ function sha256Source(source) {
|
|
|
7109
7586
|
return createHash3("sha256").update(typeof source === "string" ? Buffer.from(source, "utf8") : Buffer.from(source)).digest("hex");
|
|
7110
7587
|
}
|
|
7111
7588
|
async function canonicalPathIdentity(path) {
|
|
7112
|
-
const absolute =
|
|
7589
|
+
const absolute = resolve6(path);
|
|
7113
7590
|
let current = absolute;
|
|
7114
7591
|
const missingSegments = [];
|
|
7115
7592
|
while (true) {
|
|
7116
7593
|
try {
|
|
7117
7594
|
const existing = await realpath(current);
|
|
7118
|
-
const canonical =
|
|
7595
|
+
const canonical = resolve6(existing, ...missingSegments.reverse()).normalize("NFC");
|
|
7119
7596
|
return process.platform === "win32" ? canonical.toLowerCase() : canonical;
|
|
7120
7597
|
} catch (error) {
|
|
7121
7598
|
if (!isMissingPathComponent(error)) throw error;
|
|
7122
|
-
const parent =
|
|
7599
|
+
const parent = dirname10(current);
|
|
7123
7600
|
if (parent === current) {
|
|
7124
7601
|
const canonical = absolute.normalize("NFC");
|
|
7125
7602
|
return process.platform === "win32" ? canonical.toLowerCase() : canonical;
|
|
@@ -7191,7 +7668,7 @@ function formatCoordinate(value) {
|
|
|
7191
7668
|
return String(Math.round(value * 1e6) / 1e6);
|
|
7192
7669
|
}
|
|
7193
7670
|
function portablePathIdentity(path) {
|
|
7194
|
-
const normalized =
|
|
7671
|
+
const normalized = resolve6(path).normalize("NFC");
|
|
7195
7672
|
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
7196
7673
|
}
|
|
7197
7674
|
function isInside(parent, child) {
|
|
@@ -7304,14 +7781,14 @@ async function runVisualAnalyze(scene, options) {
|
|
|
7304
7781
|
validateVisualSelection([scene]);
|
|
7305
7782
|
const region = options.region === void 0 ? void 0 : parseTileflowVisualRegion(options.region);
|
|
7306
7783
|
const cwd = process.cwd();
|
|
7307
|
-
const referencePath =
|
|
7784
|
+
const referencePath = resolve7(cwd, options.reference);
|
|
7308
7785
|
const referencePng = await readVisualReference(referencePath);
|
|
7309
7786
|
const referenceDimensions = validateTileflowVisualReferencePng(referencePng);
|
|
7310
7787
|
if (region) assertTileflowVisualRegionFits(region, referenceDimensions, "reference PNG");
|
|
7311
7788
|
const outputDirectory = await resolveVisualDirectory(cwd, options.outputDir, "output");
|
|
7312
|
-
const actualPath =
|
|
7313
|
-
const managedDiffPath =
|
|
7314
|
-
const reportPath =
|
|
7789
|
+
const actualPath = resolve7(outputDirectory.path, `${scene}.actual.png`);
|
|
7790
|
+
const managedDiffPath = resolve7(outputDirectory.path, `${scene}.diff.png`);
|
|
7791
|
+
const reportPath = resolve7(outputDirectory.path, `${scene}.analysis.json`);
|
|
7315
7792
|
assertReferenceIsReadOnly(referencePath, [actualPath, managedDiffPath, reportPath]);
|
|
7316
7793
|
const controller = installSignalAbortController();
|
|
7317
7794
|
const session = createTileflowCaptureSession3({
|
|
@@ -7400,15 +7877,15 @@ async function runVisualDiff(scenes, options) {
|
|
|
7400
7877
|
capture,
|
|
7401
7878
|
files.kind === "complete" ? files.baseline : void 0
|
|
7402
7879
|
);
|
|
7403
|
-
const actualPath =
|
|
7404
|
-
const diffPath = comparison.diffPng ?
|
|
7880
|
+
const actualPath = resolve7(outputDirectory.path, `${capture.scene}.actual.png`);
|
|
7881
|
+
const diffPath = comparison.diffPng ? resolve7(outputDirectory.path, `${capture.scene}.diff.png`) : void 0;
|
|
7405
7882
|
prepared.push({
|
|
7406
7883
|
capture,
|
|
7407
7884
|
comparison,
|
|
7408
7885
|
baselinePath: files.pngPath,
|
|
7409
7886
|
actualPath,
|
|
7410
7887
|
diffPath,
|
|
7411
|
-
reportPath:
|
|
7888
|
+
reportPath: resolve7(outputDirectory.path, `${capture.scene}.visual.json`)
|
|
7412
7889
|
});
|
|
7413
7890
|
}
|
|
7414
7891
|
const document = createTileflowVisualDiffJson(prepared, cwd);
|
|
@@ -7428,7 +7905,7 @@ async function runVisualDiff(scenes, options) {
|
|
|
7428
7905
|
}
|
|
7429
7906
|
]),
|
|
7430
7907
|
removePaths: prepared.flatMap(
|
|
7431
|
-
(item) => item.diffPath ? [] : [
|
|
7908
|
+
(item) => item.diffPath ? [] : [resolve7(outputDirectory.path, `${item.capture.scene}.diff.png`)]
|
|
7432
7909
|
)
|
|
7433
7910
|
});
|
|
7434
7911
|
if (options.json) {
|
|
@@ -7549,7 +8026,7 @@ async function resolvePreviousBaseline(capture, files) {
|
|
|
7549
8026
|
}
|
|
7550
8027
|
}
|
|
7551
8028
|
async function readBaselineFiles(directory, scene) {
|
|
7552
|
-
const pngPath =
|
|
8029
|
+
const pngPath = resolve7(directory.path, `${scene}.png`);
|
|
7553
8030
|
const receiptPath = captureReceiptPath(pngPath);
|
|
7554
8031
|
const [png, receipt] = await Promise.all([
|
|
7555
8032
|
readOptionalArtifact(pngPath, directory.boundary, tileflowVisualArtifactLimits.maximumPngBytes),
|
|
@@ -7564,7 +8041,7 @@ async function readBaselineFiles(directory, scene) {
|
|
|
7564
8041
|
return { kind: "complete", pngPath, receiptPath, baseline: { png, receipt } };
|
|
7565
8042
|
}
|
|
7566
8043
|
async function readOptionalArtifact(path, boundary, maximumBytes) {
|
|
7567
|
-
await assertNoSymlinkComponents(
|
|
8044
|
+
await assertNoSymlinkComponents(dirname11(path), boundary);
|
|
7568
8045
|
let info;
|
|
7569
8046
|
try {
|
|
7570
8047
|
info = await lstat4(path);
|
|
@@ -7609,12 +8086,12 @@ async function readVisualReference(path) {
|
|
|
7609
8086
|
return new Uint8Array(await readFile6(path));
|
|
7610
8087
|
}
|
|
7611
8088
|
async function resolveVisualDirectory(cwd, value, kind) {
|
|
7612
|
-
const path =
|
|
8089
|
+
const path = resolve7(cwd, value);
|
|
7613
8090
|
if (path === cwd || path === parse2(path).root) {
|
|
7614
8091
|
throw new Error(`Visual ${kind} directory must be a dedicated subdirectory.`);
|
|
7615
8092
|
}
|
|
7616
8093
|
if (kind === "baseline") {
|
|
7617
|
-
for (const managed of [
|
|
8094
|
+
for (const managed of [resolve7(cwd, ".tileflow/captures"), resolve7(cwd, ".tileflow/diffs")]) {
|
|
7618
8095
|
if (pathsOverlap2(path, managed)) {
|
|
7619
8096
|
throw new Error("Visual baselines must not overlap Tileflow-managed capture/diff outputs.");
|
|
7620
8097
|
}
|
|
@@ -7650,7 +8127,7 @@ function assertReferenceIsReadOnly(referencePath, outputPaths) {
|
|
|
7650
8127
|
}
|
|
7651
8128
|
}
|
|
7652
8129
|
function portablePathIdentity2(path) {
|
|
7653
|
-
return
|
|
8130
|
+
return resolve7(path).normalize("NFC").toLowerCase();
|
|
7654
8131
|
}
|
|
7655
8132
|
function isInside2(parent, child) {
|
|
7656
8133
|
const path = relative4(parent, child);
|
|
@@ -7669,13 +8146,14 @@ var defaultApiUrl = defaultTileflowApiUrl;
|
|
|
7669
8146
|
var defaultAppUrl = "https://tileflow.dev";
|
|
7670
8147
|
var defaultConfigPath = defaultTileflowConfigPath;
|
|
7671
8148
|
var defaultManifestPath = defaultTileflowManifestPath;
|
|
7672
|
-
program.name("tileflow").description("Beautiful maps from config.").
|
|
8149
|
+
program.name("tileflow").description("Beautiful maps from config.").showHelpAfterError(pc6.gray("\nRun tileflow <command> --help for usage.")).showSuggestionAfterError();
|
|
8150
|
+
program.addHelpText("after", "\n -V, --version output the version number\n");
|
|
7673
8151
|
registerLanguageCommand(program);
|
|
7674
8152
|
registerTilesetCommands(program, { defaultApiUrl, loadAuthConfig });
|
|
7675
8153
|
registerIconSetCommands(program, { defaultApiUrl, loadAuthConfig });
|
|
7676
8154
|
program.command("init").description("Create a starter tileflow.config.ts").option("-f, --force", "overwrite an existing config").action(async (options) => {
|
|
7677
|
-
const configPath =
|
|
7678
|
-
const ignorePath =
|
|
8155
|
+
const configPath = resolve8(process.cwd(), defaultConfigPath);
|
|
8156
|
+
const ignorePath = resolve8(process.cwd(), ".gitignore");
|
|
7679
8157
|
if (existsSync(configPath) && !options.force) {
|
|
7680
8158
|
logWarning(`${pathLabel(defaultConfigPath)} already exists.`);
|
|
7681
8159
|
printNextSteps([`Run ${command("tileflow init --force")} to replace it.`]);
|
|
@@ -7782,15 +8260,22 @@ program.command("whoami").description("Show the authenticated Tileflow account")
|
|
|
7782
8260
|
logSuccess("Tileflow CLI is authenticated.");
|
|
7783
8261
|
printAccountDetails(selected.session);
|
|
7784
8262
|
});
|
|
7785
|
-
program.command("validate").description("Validate a Tileflow config").option("-c, --config <path>", "config path", defaultConfigPath).option("--target <target>", "validation target: local or hosted", "local").option(
|
|
8263
|
+
program.command("validate").description("Validate a Tileflow config").option("-c, --config <path>", "config path", defaultConfigPath).option("--target <target>", "validation target: local or hosted", "local").option("--renderer <renderer>", "artifact renderer: web or native", "web").option(
|
|
7786
8264
|
"--api-base-url <url>",
|
|
7787
8265
|
"Tileflow API base URL used to resolve official map assets",
|
|
7788
8266
|
process.env.TILEFLOW_API_URL ?? defaultApiUrl
|
|
7789
8267
|
).option("--cache-dir <path>", "verified Icon Set artifact cache root").option("--offline", "fail a locked Icon Set cache miss instead of hydrating it").option("--json", "print deterministic schema-version-1 JSON").action(
|
|
7790
8268
|
async (options) => {
|
|
8269
|
+
if (options.renderer !== "web") {
|
|
8270
|
+
await runRendererArtifactCommand("validate", {
|
|
8271
|
+
...options,
|
|
8272
|
+
icons: resolveIconOptions(options)
|
|
8273
|
+
});
|
|
8274
|
+
return;
|
|
8275
|
+
}
|
|
7791
8276
|
if (options.target !== "local" && options.target !== "hosted") {
|
|
7792
8277
|
if (options.json) {
|
|
7793
|
-
const
|
|
8278
|
+
const failure2 = createTileflowCommandFailureDocument5(
|
|
7794
8279
|
"validate",
|
|
7795
8280
|
{
|
|
7796
8281
|
code: "INVALID_TARGET",
|
|
@@ -7807,7 +8292,7 @@ program.command("validate").description("Validate a Tileflow config").option("-c
|
|
|
7807
8292
|
process.cwd(),
|
|
7808
8293
|
{ code: "INVALID_TARGET", phase: "command-validation" }
|
|
7809
8294
|
);
|
|
7810
|
-
process.stderr.write(
|
|
8295
|
+
process.stderr.write(serializeTileflowCommandDocument5(failure2));
|
|
7811
8296
|
process.exitCode = 1;
|
|
7812
8297
|
return;
|
|
7813
8298
|
}
|
|
@@ -7822,15 +8307,15 @@ program.command("validate").description("Validate a Tileflow config").option("-c
|
|
|
7822
8307
|
try {
|
|
7823
8308
|
if (!options.json) logInfo(`Validating ${pathLabel(options.config)}.`);
|
|
7824
8309
|
const loaded = await withTileflowConfigSecretsHidden(
|
|
7825
|
-
() =>
|
|
8310
|
+
() => loadTileflowConfigWithInputs4(options.config)
|
|
7826
8311
|
);
|
|
7827
8312
|
const project = loaded.project;
|
|
7828
|
-
const baseDirectory =
|
|
8313
|
+
const baseDirectory = dirname12(loaded.configFile);
|
|
7829
8314
|
failureDefaults = { code: "CONFIG_INVALID", phase: "config-validation" };
|
|
7830
|
-
|
|
7831
|
-
const mapNames =
|
|
8315
|
+
assertValidTileflowConfig3(project);
|
|
8316
|
+
const mapNames = getTileflowMapNames5(project).sort();
|
|
7832
8317
|
failureDefaults = { code: "ICON_COMPILATION_FAILED", phase: "icon-compilation" };
|
|
7833
|
-
const compiledIcons = await
|
|
8318
|
+
const compiledIcons = await compileTileflowIconPackages3(project, {
|
|
7834
8319
|
baseDirectory,
|
|
7835
8320
|
cwd: process.cwd(),
|
|
7836
8321
|
icons: resolveIconOptions(options),
|
|
@@ -7841,18 +8326,18 @@ program.command("validate").description("Validate a Tileflow config").option("-c
|
|
|
7841
8326
|
(binding) => options.target === "hosted" ? `${normalizeUrl(options.apiBaseUrl)}/sprites/preflight/${binding.packageHash}/sprite` : `/tileflow/icons/${binding.mapName}/sprite`
|
|
7842
8327
|
);
|
|
7843
8328
|
failureDefaults = { code: "STYLE_INVALID", phase: "style-validation" };
|
|
7844
|
-
const compiledStyles =
|
|
8329
|
+
const compiledStyles = createTileflowStyles2(project, {
|
|
7845
8330
|
apiBaseUrl: options.apiBaseUrl,
|
|
7846
8331
|
mapAssets
|
|
7847
8332
|
});
|
|
7848
8333
|
failureDefaults = { code: "TF_LOCAL_TILESET_INVALID", phase: "local-tileset-resolution" };
|
|
7849
|
-
const localTilesets = await
|
|
8334
|
+
const localTilesets = await prepareTileflowLocalTilesets2(project, compiledStyles, {
|
|
7850
8335
|
assetBaseUrl: "/tileflow",
|
|
7851
8336
|
baseDirectory,
|
|
7852
8337
|
cwd: process.cwd()
|
|
7853
8338
|
});
|
|
7854
8339
|
failureDefaults = { code: "FONT_COMPILATION_FAILED", phase: "font-compilation" };
|
|
7855
|
-
const { styles } = await
|
|
8340
|
+
const { styles } = await prepareTileflowStyleFonts2(project, localTilesets.styles, {
|
|
7856
8341
|
assetBaseUrl: "/tileflow",
|
|
7857
8342
|
baseDirectory,
|
|
7858
8343
|
cwd: process.cwd(),
|
|
@@ -7877,11 +8362,11 @@ program.command("validate").description("Validate a Tileflow config").option("-c
|
|
|
7877
8362
|
});
|
|
7878
8363
|
}
|
|
7879
8364
|
const themeWarnings = mapNames.flatMap(
|
|
7880
|
-
(mapName) =>
|
|
8365
|
+
(mapName) => auditTileflowMapThemeValues2(project.maps[mapName]).filter(
|
|
7881
8366
|
({ severity }) => severity === "warning"
|
|
7882
8367
|
)
|
|
7883
8368
|
);
|
|
7884
|
-
const diagnostics = themeWarnings.length === 0 ? [] :
|
|
8369
|
+
const diagnostics = themeWarnings.length === 0 ? [] : createTileflowStructuredDiagnostics3({ diagnostics: themeWarnings }, process.cwd(), {
|
|
7885
8370
|
code: "VALIDATION_WARNING",
|
|
7886
8371
|
phase: "theme-audit"
|
|
7887
8372
|
});
|
|
@@ -7896,7 +8381,7 @@ program.command("validate").description("Validate a Tileflow config").option("-c
|
|
|
7896
8381
|
...options.target === "hosted" ? ["Hosted compatibility"] : []
|
|
7897
8382
|
];
|
|
7898
8383
|
if (options.json) {
|
|
7899
|
-
const summary =
|
|
8384
|
+
const summary = createTileflowCommandSummary3({
|
|
7900
8385
|
code: "VALIDATION_OK",
|
|
7901
8386
|
command: "validate",
|
|
7902
8387
|
message: `Tileflow config is valid (${plural(mapNames.length, "map")}).`,
|
|
@@ -7907,7 +8392,7 @@ program.command("validate").description("Validate a Tileflow config").option("-c
|
|
|
7907
8392
|
suggestion: "No changes are required."
|
|
7908
8393
|
});
|
|
7909
8394
|
process.stdout.write(
|
|
7910
|
-
|
|
8395
|
+
serializeTileflowCommandDocument5({
|
|
7911
8396
|
...summary,
|
|
7912
8397
|
target: options.target,
|
|
7913
8398
|
maps: mapNames,
|
|
@@ -7924,25 +8409,29 @@ program.command("validate").description("Validate a Tileflow config").option("-c
|
|
|
7924
8409
|
}
|
|
7925
8410
|
} catch (error) {
|
|
7926
8411
|
if (!options.json) throw error;
|
|
7927
|
-
const
|
|
8412
|
+
const failure2 = createTileflowCommandFailureDocument5(
|
|
7928
8413
|
"validate",
|
|
7929
8414
|
error,
|
|
7930
8415
|
process.cwd(),
|
|
7931
8416
|
failureDefaults
|
|
7932
8417
|
);
|
|
7933
|
-
process.stderr.write(
|
|
8418
|
+
process.stderr.write(serializeTileflowCommandDocument5(failure2));
|
|
7934
8419
|
process.exitCode = 1;
|
|
7935
8420
|
}
|
|
7936
8421
|
}
|
|
7937
8422
|
);
|
|
7938
|
-
program.command("build").description("Generate static Tileflow styles").option("-c, --config <path>", "config path", defaultConfigPath).option("-o, --out <path>", "output directory", "dist/tileflow").option(
|
|
8423
|
+
program.command("build").description("Generate static Tileflow styles").option("-c, --config <path>", "config path", defaultConfigPath).option("-o, --out <path>", "output directory", "dist/tileflow").option("--renderer <renderer>", "artifact renderer: web or native", "web").option("--target <target>", "artifact target: local or hosted (build supports local)", "local").option("--json", "print deterministic schema-version-1 JSON").option(
|
|
7939
8424
|
"--api-base-url <url>",
|
|
7940
8425
|
"Tileflow API base URL used to resolve official map assets",
|
|
7941
8426
|
process.env.TILEFLOW_API_URL ?? defaultApiUrl
|
|
7942
8427
|
).option("--cache-dir <path>", "verified Icon Set artifact cache root").option("--offline", "fail a locked Icon Set cache miss instead of hydrating it").action(
|
|
7943
8428
|
async (options) => {
|
|
7944
|
-
logInfo(`Building ${pathLabel(options.config)}.`);
|
|
7945
8429
|
const icons = resolveIconOptions(options);
|
|
8430
|
+
if (options.renderer !== "web" || options.target !== "local" || options.json) {
|
|
8431
|
+
await runRendererArtifactCommand("build", { ...options, icons });
|
|
8432
|
+
return;
|
|
8433
|
+
}
|
|
8434
|
+
logInfo(`Building ${pathLabel(options.config)}.`);
|
|
7946
8435
|
await withTileflowConfigSecretsHidden(
|
|
7947
8436
|
() => writeTileflowBuildArtifacts({
|
|
7948
8437
|
config: options.config,
|
|
@@ -7953,15 +8442,62 @@ program.command("build").description("Generate static Tileflow styles").option("
|
|
|
7953
8442
|
})
|
|
7954
8443
|
);
|
|
7955
8444
|
logSuccess("Built Tileflow artifacts.");
|
|
7956
|
-
printKeyValue("Output", pathLabel(
|
|
8445
|
+
printKeyValue("Output", pathLabel(resolve8(process.cwd(), options.out)));
|
|
7957
8446
|
}
|
|
7958
8447
|
);
|
|
7959
|
-
program.command("preview").alias("dev").description("Run a local map preview").option("-c, --config <path>", "config path", defaultConfigPath).option("--against-config <path>", "second config for the comparison workbench").option("--against-map <name>", "map on the right; defaults to --map").option("--against-scene <name>", "committed standalone scene on the right").option("--against-theme <name>", "concrete theme on the right; defaults to --theme").option("--host <host>", "bind host: an explicit IP address or localhost", defaultTileflowDevHost).option("--map <name>", "preview one configured map").option("--theme <name>", "preview one concrete theme; defaults to the map default").option("-p, --port <port>", "preview port", "3333").option("--scene <name>", "preview one committed standalone map scene").option(
|
|
8448
|
+
program.command("preview").alias("dev").description("Run a local map preview").option("-c, --config <path>", "config path", defaultConfigPath).option("--against-config <path>", "second config for the comparison workbench").option("--against-map <name>", "map on the right; defaults to --map").option("--against-scene <name>", "committed standalone scene on the right").option("--against-theme <name>", "concrete theme on the right; defaults to --theme").option("--host <host>", "bind host: an explicit IP address or localhost", defaultTileflowDevHost).option("--map <name>", "preview one configured map").option("--theme <name>", "preview one concrete theme; defaults to the map default").option("--renderer <renderer>", "artifact renderer: web or native", "web").option("-p, --port <port>", "preview port", "3333").option("--scene <name>", "preview one committed standalone map scene").option(
|
|
7960
8449
|
"--api-base-url <url>",
|
|
7961
8450
|
"Tileflow API base URL used to resolve official map assets",
|
|
7962
8451
|
process.env.TILEFLOW_API_URL ?? defaultApiUrl
|
|
7963
8452
|
).option("--cache-dir <path>", "verified Icon Set artifact cache root").option("--offline", "fail a locked Icon Set cache miss instead of hydrating it").option("--json", "emit schema-version-1 NDJSON lifecycle events").action(
|
|
7964
8453
|
async (options) => {
|
|
8454
|
+
let renderer;
|
|
8455
|
+
try {
|
|
8456
|
+
renderer = resolveTileflowRenderer2(options.renderer);
|
|
8457
|
+
} catch (error) {
|
|
8458
|
+
const diagnostics = createTileflowArtifactDiagnostics3(error, process.cwd());
|
|
8459
|
+
if (options.json) {
|
|
8460
|
+
const first = diagnostics[0];
|
|
8461
|
+
process.stdout.write(
|
|
8462
|
+
`${JSON.stringify({
|
|
8463
|
+
schemaVersion: 1,
|
|
8464
|
+
command: "dev",
|
|
8465
|
+
event: "error",
|
|
8466
|
+
code: first?.code ?? "NATIVE_RENDERER_UNSUPPORTED",
|
|
8467
|
+
phase: first?.phase ?? "command-validation",
|
|
8468
|
+
diagnostics
|
|
8469
|
+
})}
|
|
8470
|
+
`
|
|
8471
|
+
);
|
|
8472
|
+
} else {
|
|
8473
|
+
logError(diagnostics[0]?.message ?? "Unsupported artifact renderer.");
|
|
8474
|
+
}
|
|
8475
|
+
process.exitCode = 1;
|
|
8476
|
+
return;
|
|
8477
|
+
}
|
|
8478
|
+
const comparisonRequested = options.againstConfig !== void 0 || options.againstMap !== void 0 || options.againstScene !== void 0 || options.againstTheme !== void 0;
|
|
8479
|
+
if (renderer === "native" && (options.scene !== void 0 || comparisonRequested)) {
|
|
8480
|
+
if (options.json) {
|
|
8481
|
+
process.stdout.write(
|
|
8482
|
+
`${JSON.stringify({
|
|
8483
|
+
schemaVersion: 1,
|
|
8484
|
+
command: "dev",
|
|
8485
|
+
event: "error",
|
|
8486
|
+
code: "NATIVE_RENDERER_UNSUPPORTED",
|
|
8487
|
+
phase: "command-validation",
|
|
8488
|
+
renderer: "native",
|
|
8489
|
+
profile: tileflowNativePreviewProfile
|
|
8490
|
+
})}
|
|
8491
|
+
`
|
|
8492
|
+
);
|
|
8493
|
+
} else {
|
|
8494
|
+
logError(
|
|
8495
|
+
"Native preview serves assets only; scenes and comparison workbench options are unavailable."
|
|
8496
|
+
);
|
|
8497
|
+
}
|
|
8498
|
+
process.exitCode = 1;
|
|
8499
|
+
return;
|
|
8500
|
+
}
|
|
7965
8501
|
const port = parsePort(options.port);
|
|
7966
8502
|
if (port === null) {
|
|
7967
8503
|
logError(`Invalid port: ${options.port}`);
|
|
@@ -8006,30 +8542,45 @@ program.command("preview").alias("dev").description("Run a local map preview").o
|
|
|
8006
8542
|
process.exitCode = 1;
|
|
8007
8543
|
return;
|
|
8008
8544
|
}
|
|
8009
|
-
const comparisonRequested = options.againstConfig !== void 0 || options.againstMap !== void 0 || options.againstScene !== void 0 || options.againstTheme !== void 0;
|
|
8010
8545
|
if (comparisonRequested) {
|
|
8011
8546
|
await runTileflowComparisonPreview(options, { host, port });
|
|
8012
8547
|
return;
|
|
8013
8548
|
}
|
|
8014
8549
|
await withTileflowConfigSecretsHidden(async () => {
|
|
8015
8550
|
const origin = tileflowDevOrigin(host, port);
|
|
8551
|
+
const manifestUrl = renderer === "native" ? getTileflowNativePreviewManifestUrl(origin) : void 0;
|
|
8552
|
+
const nativeLifecycleFields = manifestUrl ? {
|
|
8553
|
+
renderer: "native",
|
|
8554
|
+
profile: tileflowNativePreviewProfile,
|
|
8555
|
+
manifest: manifestUrl,
|
|
8556
|
+
assetsOnly: true
|
|
8557
|
+
} : {};
|
|
8016
8558
|
const icons = resolveIconOptions(options);
|
|
8017
8559
|
const session = await createTileflowArtifactSession3({
|
|
8018
8560
|
assetBaseUrl: origin,
|
|
8019
8561
|
apiBaseUrl: options.apiBaseUrl,
|
|
8020
8562
|
config: options.config,
|
|
8021
8563
|
...icons ? { icons } : {},
|
|
8564
|
+
...renderer === "native" ? { renderer: "native" } : {},
|
|
8022
8565
|
styleBaseUrl: origin,
|
|
8023
8566
|
watch: true
|
|
8024
8567
|
});
|
|
8025
8568
|
const initialArtifacts = session.getLastGoodArtifacts();
|
|
8569
|
+
let nativeSelection;
|
|
8026
8570
|
try {
|
|
8027
8571
|
if (initialArtifacts) {
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
|
|
8572
|
+
if (renderer === "native") {
|
|
8573
|
+
nativeSelection = resolveTileflowNativePreviewSelection(initialArtifacts.manifest, {
|
|
8574
|
+
map: options.map,
|
|
8575
|
+
theme: options.theme
|
|
8576
|
+
});
|
|
8577
|
+
} else {
|
|
8578
|
+
resolveTileflowPreview(initialArtifacts.project, {
|
|
8579
|
+
map: options.map,
|
|
8580
|
+
scene: options.scene,
|
|
8581
|
+
theme: options.theme
|
|
8582
|
+
});
|
|
8583
|
+
}
|
|
8033
8584
|
}
|
|
8034
8585
|
} catch (error) {
|
|
8035
8586
|
await session.close();
|
|
@@ -8037,7 +8588,12 @@ program.command("preview").alias("dev").description("Run a local map preview").o
|
|
|
8037
8588
|
process.exitCode = 1;
|
|
8038
8589
|
return;
|
|
8039
8590
|
}
|
|
8040
|
-
const fetch2 =
|
|
8591
|
+
const fetch2 = renderer === "native" ? createTileflowNativePreviewRequestHandler({
|
|
8592
|
+
config: options.config,
|
|
8593
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
8594
|
+
onError: printTileflowPreviewError,
|
|
8595
|
+
session
|
|
8596
|
+
}) : createTileflowDevRequestHandler2({
|
|
8041
8597
|
config: options.config,
|
|
8042
8598
|
apiBaseUrl: options.apiBaseUrl,
|
|
8043
8599
|
map: options.map,
|
|
@@ -8062,7 +8618,8 @@ program.command("preview").alias("dev").description("Run a local map preview").o
|
|
|
8062
8618
|
..."lastGoodGeneration" in state && state.lastGoodGeneration !== void 0 ? { lastGoodGeneration: state.lastGoodGeneration } : {},
|
|
8063
8619
|
...firstDiagnostic?.code ? { code: firstDiagnostic.code } : {},
|
|
8064
8620
|
...firstDiagnostic?.phase ? { phase: firstDiagnostic.phase } : {},
|
|
8065
|
-
...state.status === "invalid" ? { diagnostics: state.diagnostics } : {}
|
|
8621
|
+
...state.status === "invalid" ? { diagnostics: state.diagnostics } : {},
|
|
8622
|
+
...nativeLifecycleFields
|
|
8066
8623
|
})}
|
|
8067
8624
|
`
|
|
8068
8625
|
);
|
|
@@ -8071,14 +8628,16 @@ program.command("preview").alias("dev").description("Run a local map preview").o
|
|
|
8071
8628
|
if (state.status === "invalid") {
|
|
8072
8629
|
console.error(
|
|
8073
8630
|
[
|
|
8074
|
-
`Tileflow generation ${state.generation} is invalid; preserving the last valid preview.`,
|
|
8631
|
+
renderer === "native" ? `Tileflow generation ${state.generation} is invalid; preserving the last valid native artifact family.` : `Tileflow generation ${state.generation} is invalid; preserving the last valid preview.`,
|
|
8075
8632
|
...state.diagnostics.map(
|
|
8076
8633
|
(diagnostic) => `- ${diagnostic.path || "(root)"}: ${diagnostic.message}`
|
|
8077
8634
|
)
|
|
8078
8635
|
].join("\n")
|
|
8079
8636
|
);
|
|
8080
8637
|
} else if (recovered) {
|
|
8081
|
-
logSuccess(
|
|
8638
|
+
logSuccess(
|
|
8639
|
+
renderer === "native" ? `Tileflow native artifact preview recovered at generation ${state.generation}.` : `Tileflow preview recovered at generation ${state.generation}.`
|
|
8640
|
+
);
|
|
8082
8641
|
}
|
|
8083
8642
|
};
|
|
8084
8643
|
emitState(session.getState());
|
|
@@ -8091,13 +8650,26 @@ program.command("preview").alias("dev").description("Run a local map preview").o
|
|
|
8091
8650
|
server = createdServer;
|
|
8092
8651
|
});
|
|
8093
8652
|
if (!options.json) {
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
|
|
8099
|
-
|
|
8100
|
-
|
|
8653
|
+
if (renderer === "native") {
|
|
8654
|
+
logSuccess("Tileflow native artifact preview is running and watching for changes.");
|
|
8655
|
+
printKeyValue("Manifest", link(manifestUrl));
|
|
8656
|
+
printKeyValue("Profile", tileflowNativePreviewProfile);
|
|
8657
|
+
printKeyValue("Endpoint", "assets-only");
|
|
8658
|
+
printKeyValue("Config", pathLabel(options.config));
|
|
8659
|
+
if (nativeSelection) {
|
|
8660
|
+
printKeyValue("Map", nativeSelection.mapName);
|
|
8661
|
+
printKeyValue("Theme", nativeSelection.themeName);
|
|
8662
|
+
}
|
|
8663
|
+
logMuted("Metro remains the JavaScript development server. Press Ctrl+C to stop.");
|
|
8664
|
+
} else {
|
|
8665
|
+
logSuccess("Tileflow preview is running and watching for changes.");
|
|
8666
|
+
printKeyValue("Local", link(origin));
|
|
8667
|
+
printKeyValue("Config", pathLabel(options.config));
|
|
8668
|
+
if (options.map) printKeyValue("Map", options.map);
|
|
8669
|
+
if (options.theme) printKeyValue("Theme", options.theme);
|
|
8670
|
+
if (options.scene) printKeyValue("Scene", options.scene);
|
|
8671
|
+
logMuted("Press Ctrl+C to stop.");
|
|
8672
|
+
}
|
|
8101
8673
|
}
|
|
8102
8674
|
await waitForTerminationSignal(server);
|
|
8103
8675
|
} finally {
|
|
@@ -8107,7 +8679,13 @@ program.command("preview").alias("dev").description("Run a local map preview").o
|
|
|
8107
8679
|
await session.close();
|
|
8108
8680
|
if (options.json) {
|
|
8109
8681
|
process.stdout.write(
|
|
8110
|
-
`${JSON.stringify({
|
|
8682
|
+
`${JSON.stringify({
|
|
8683
|
+
schemaVersion: 1,
|
|
8684
|
+
command: "dev",
|
|
8685
|
+
event: "stopped",
|
|
8686
|
+
generation,
|
|
8687
|
+
...nativeLifecycleFields
|
|
8688
|
+
})}
|
|
8111
8689
|
`
|
|
8112
8690
|
);
|
|
8113
8691
|
}
|
|
@@ -8115,7 +8693,7 @@ program.command("preview").alias("dev").description("Run a local map preview").o
|
|
|
8115
8693
|
});
|
|
8116
8694
|
}
|
|
8117
8695
|
);
|
|
8118
|
-
program.command("deploy").description("Deploy maps to Tileflow and write the frontend manifest").option("-c, --config <path>", "config path", defaultConfigPath).option("--manifest <path>", "manifest path written for frontend bundlers", defaultManifestPath).option("--api-url <url>", "Tileflow API URL", process.env.TILEFLOW_API_URL).option("--api-key <key>", "Tileflow API key", process.env.TILEFLOW_API_KEY).option("--map-id <id>", "managed Map destination").option("--map <name>", "configured map to connect when the repository contains multiple maps").option(
|
|
8696
|
+
program.command("deploy").description("Deploy maps to Tileflow and write the frontend manifest").option("-c, --config <path>", "config path", defaultConfigPath).option("--manifest <path>", "manifest path written for frontend bundlers", defaultManifestPath).option("--api-url <url>", "Tileflow API URL", process.env.TILEFLOW_API_URL).option("--api-key <key>", "Tileflow API key", process.env.TILEFLOW_API_KEY).option("--map-id <id>", "managed Map destination").option("--with-native", "publish web and native-v1 together for the selected managed Map").option("--map <name>", "configured map to connect when the repository contains multiple maps").option(
|
|
8119
8697
|
"--overwrite-self-hosted-manifest",
|
|
8120
8698
|
"explicitly replace an existing self-hosted manifest at --manifest"
|
|
8121
8699
|
).option("--cache-dir <path>", "verified Icon Set artifact cache root").option("--offline", "fail a locked Icon Set cache miss instead of hydrating it").action(
|
|
@@ -8136,19 +8714,39 @@ program.command("deploy").description("Deploy maps to Tileflow and write the fro
|
|
|
8136
8714
|
options.apiUrl ?? defaultApiUrl,
|
|
8137
8715
|
...options.overwriteSelfHostedManifest ? ["--overwrite-self-hosted-manifest"] : [],
|
|
8138
8716
|
...options.mapId ? ["--map-id", options.mapId] : [],
|
|
8139
|
-
...options.map && selectedMap ? ["--map", selectedMap] : []
|
|
8717
|
+
...options.map && selectedMap ? ["--map", selectedMap] : [],
|
|
8718
|
+
...options.withNative ? ["--with-native"] : []
|
|
8140
8719
|
])
|
|
8141
8720
|
});
|
|
8142
8721
|
const apiUrl = normalizeApiOrigin(options.apiUrl ?? defaultApiUrl);
|
|
8143
8722
|
delete process.env.TILEFLOW_API_KEY;
|
|
8723
|
+
if (options.withNative) {
|
|
8724
|
+
const result = await runHostedNativeDeploy(
|
|
8725
|
+
{ ...options, apiUrl },
|
|
8726
|
+
{
|
|
8727
|
+
source,
|
|
8728
|
+
resolveApi,
|
|
8729
|
+
loadManifest: loadExistingDeployManifest,
|
|
8730
|
+
writeManifest: writeDeployManifest
|
|
8731
|
+
}
|
|
8732
|
+
);
|
|
8733
|
+
if (result) {
|
|
8734
|
+
logSuccess(
|
|
8735
|
+
`${result.changed ? "Published" : "Unchanged"} ${pc6.bold(result.mapName)} web + native-v1 (v${result.version}).`
|
|
8736
|
+
);
|
|
8737
|
+
printKeyValue("Manifest", pathLabel(result.manifestPath));
|
|
8738
|
+
printKeyValue("Native", link(result.nativeManifestUrl));
|
|
8739
|
+
}
|
|
8740
|
+
return;
|
|
8741
|
+
}
|
|
8144
8742
|
logInfo(`Deploying ${pathLabel(options.config)}.`);
|
|
8145
8743
|
const loaded = await withTileflowConfigSecretsHidden(
|
|
8146
|
-
() =>
|
|
8744
|
+
() => loadTileflowConfigWithInputs4(options.config)
|
|
8147
8745
|
);
|
|
8148
8746
|
const project = loaded.project;
|
|
8149
|
-
const baseDirectory =
|
|
8150
|
-
|
|
8151
|
-
const configuredMapNames =
|
|
8747
|
+
const baseDirectory = dirname12(loaded.configFile);
|
|
8748
|
+
assertValidTileflowConfig3(project);
|
|
8749
|
+
const configuredMapNames = getTileflowMapNames5(project);
|
|
8152
8750
|
const mapNames = selectManagedDeployMaps(configuredMapNames, options);
|
|
8153
8751
|
if (!mapNames) return;
|
|
8154
8752
|
if (!validateDeployTarget(options)) return;
|
|
@@ -8159,7 +8757,7 @@ program.command("deploy").description("Deploy maps to Tileflow and write the fro
|
|
|
8159
8757
|
mapNames.map((mapName) => [mapName, project.maps[mapName]])
|
|
8160
8758
|
)
|
|
8161
8759
|
};
|
|
8162
|
-
const compiledIcons = await
|
|
8760
|
+
const compiledIcons = await compileTileflowIconPackages3(deploymentProject, {
|
|
8163
8761
|
baseDirectory,
|
|
8164
8762
|
cwd: process.cwd(),
|
|
8165
8763
|
icons: resolveIconOptions(options),
|
|
@@ -8175,16 +8773,16 @@ program.command("deploy").description("Deploy maps to Tileflow and write the fro
|
|
|
8175
8773
|
compiledIcons,
|
|
8176
8774
|
(binding) => `${apiUrl}/sprites/preflight/${binding.packageHash}/sprite`
|
|
8177
8775
|
);
|
|
8178
|
-
const compiledPreflightStyles =
|
|
8776
|
+
const compiledPreflightStyles = createTileflowStyles2(deploymentProject, {
|
|
8179
8777
|
apiBaseUrl: apiUrl,
|
|
8180
8778
|
mapAssets: preflightMapAssets
|
|
8181
8779
|
});
|
|
8182
|
-
const preflightLocalTilesets = await
|
|
8780
|
+
const preflightLocalTilesets = await prepareTileflowLocalTilesets2(
|
|
8183
8781
|
deploymentProject,
|
|
8184
8782
|
compiledPreflightStyles,
|
|
8185
8783
|
{ assetBaseUrl: apiUrl, baseDirectory, cwd: process.cwd() }
|
|
8186
8784
|
);
|
|
8187
|
-
const preflightFonts = await
|
|
8785
|
+
const preflightFonts = await prepareTileflowStyleFonts2(
|
|
8188
8786
|
deploymentProject,
|
|
8189
8787
|
preflightLocalTilesets.styles,
|
|
8190
8788
|
{
|
|
@@ -8252,16 +8850,16 @@ program.command("deploy").description("Deploy maps to Tileflow and write the fro
|
|
|
8252
8850
|
if (!sprite) throw new Error(`Missing hosted sprite URL for map ${binding.mapName}`);
|
|
8253
8851
|
return sprite;
|
|
8254
8852
|
});
|
|
8255
|
-
const compiledHostedStyles =
|
|
8853
|
+
const compiledHostedStyles = createTileflowStyles2(deploymentProject, {
|
|
8256
8854
|
apiBaseUrl: api.apiUrl,
|
|
8257
8855
|
mapAssets: hostedMapAssets
|
|
8258
8856
|
});
|
|
8259
|
-
const hostedLocalTilesets = await
|
|
8857
|
+
const hostedLocalTilesets = await prepareTileflowLocalTilesets2(
|
|
8260
8858
|
deploymentProject,
|
|
8261
8859
|
compiledHostedStyles,
|
|
8262
8860
|
{ assetBaseUrl: api.apiUrl, baseDirectory, cwd: process.cwd() }
|
|
8263
8861
|
);
|
|
8264
|
-
const hostedFonts = await
|
|
8862
|
+
const hostedFonts = await prepareTileflowStyleFonts2(
|
|
8265
8863
|
deploymentProject,
|
|
8266
8864
|
hostedLocalTilesets.styles,
|
|
8267
8865
|
{
|
|
@@ -8326,7 +8924,7 @@ program.command("deploy").description("Deploy maps to Tileflow and write the fro
|
|
|
8326
8924
|
const styles = Object.fromEntries(
|
|
8327
8925
|
Object.entries(hostedThemeFamilies).map(([mapName, family]) => [mapName, family.styles])
|
|
8328
8926
|
);
|
|
8329
|
-
const buildManifest = await
|
|
8927
|
+
const buildManifest = await createTileflowMapBuildManifest2(
|
|
8330
8928
|
Object.fromEntries(
|
|
8331
8929
|
mapNames.map((mapName) => {
|
|
8332
8930
|
const map = deploymentProject.maps[mapName];
|
|
@@ -8357,7 +8955,7 @@ program.command("deploy").description("Deploy maps to Tileflow and write the fro
|
|
|
8357
8955
|
];
|
|
8358
8956
|
})
|
|
8359
8957
|
),
|
|
8360
|
-
{ provenance: await
|
|
8958
|
+
{ provenance: await createTileflowBuildProvenance2(process.cwd()) }
|
|
8361
8959
|
);
|
|
8362
8960
|
const deployments = mapNames.map((mapName) => {
|
|
8363
8961
|
const iconBinding = bindingsByMap.get(mapName);
|
|
@@ -8448,7 +9046,7 @@ program.command("deploy").description("Deploy maps to Tileflow and write the fro
|
|
|
8448
9046
|
process.exitCode = 1;
|
|
8449
9047
|
return;
|
|
8450
9048
|
}
|
|
8451
|
-
const resolvedMap =
|
|
9049
|
+
const resolvedMap = parseResolvedTileflowMap5(deploymentProject.maps[mapName]);
|
|
8452
9050
|
const mapBuild = buildManifest2.maps[mapName];
|
|
8453
9051
|
deployedMaps[mapName] = {
|
|
8454
9052
|
defaultTheme: resolvedMap.defaultTheme,
|
|
@@ -8458,7 +9056,7 @@ program.command("deploy").description("Deploy maps to Tileflow and write the fro
|
|
|
8458
9056
|
themes: Object.fromEntries(
|
|
8459
9057
|
themeNames.map((themeName) => {
|
|
8460
9058
|
const deployedTheme = body.themes[themeName];
|
|
8461
|
-
const fontFaces =
|
|
9059
|
+
const fontFaces = getTileflowStyleFontFaces2(themeStyles[themeName]);
|
|
8462
9060
|
return [
|
|
8463
9061
|
themeName,
|
|
8464
9062
|
{
|
|
@@ -8595,10 +9193,15 @@ registerProjectCommands(program, {
|
|
|
8595
9193
|
defaultApiUrl,
|
|
8596
9194
|
loadAuthConfig
|
|
8597
9195
|
});
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
}
|
|
9196
|
+
if (isRootCliVersionRequest(process.argv.slice(2))) {
|
|
9197
|
+
process.stdout.write(`${packageJson.version}
|
|
9198
|
+
`);
|
|
9199
|
+
} else {
|
|
9200
|
+
program.parseAsync().catch((error) => {
|
|
9201
|
+
printCliError(error);
|
|
9202
|
+
process.exitCode = 1;
|
|
9203
|
+
});
|
|
9204
|
+
}
|
|
8602
9205
|
async function runTileflowComparisonPreview(options, address) {
|
|
8603
9206
|
await withTileflowConfigSecretsHidden(async () => {
|
|
8604
9207
|
const origin = tileflowDevOrigin(address.host, address.port);
|
|
@@ -8702,7 +9305,7 @@ async function runTileflowComparisonPreview(options, address) {
|
|
|
8702
9305
|
scene: rightScene,
|
|
8703
9306
|
theme: rightTheme
|
|
8704
9307
|
});
|
|
8705
|
-
const leftHandler =
|
|
9308
|
+
const leftHandler = createTileflowDevRequestHandler2({
|
|
8706
9309
|
apiBaseUrl: options.apiBaseUrl,
|
|
8707
9310
|
basePath: leftBasePath,
|
|
8708
9311
|
config: options.config,
|
|
@@ -8712,7 +9315,7 @@ async function runTileflowComparisonPreview(options, address) {
|
|
|
8712
9315
|
session: leftSession,
|
|
8713
9316
|
theme: options.theme
|
|
8714
9317
|
});
|
|
8715
|
-
const rightHandler =
|
|
9318
|
+
const rightHandler = createTileflowDevRequestHandler2({
|
|
8716
9319
|
apiBaseUrl: options.apiBaseUrl,
|
|
8717
9320
|
basePath: rightBasePath,
|
|
8718
9321
|
config: rightConfig,
|
|
@@ -8783,8 +9386,8 @@ async function runTileflowComparisonPreview(options, address) {
|
|
|
8783
9386
|
}
|
|
8784
9387
|
function comparisonCaptureConfigArgument(configPath) {
|
|
8785
9388
|
const cwd = realpathSync(process.cwd());
|
|
8786
|
-
const requestedConfigPath =
|
|
8787
|
-
const defaultRequestedPath =
|
|
9389
|
+
const requestedConfigPath = resolve8(process.cwd(), configPath);
|
|
9390
|
+
const defaultRequestedPath = resolve8(process.cwd(), defaultConfigPath);
|
|
8788
9391
|
const absoluteConfigPath = existsSync(requestedConfigPath) ? realpathSync(requestedConfigPath) : requestedConfigPath;
|
|
8789
9392
|
const absoluteDefaultPath = existsSync(defaultRequestedPath) ? realpathSync(defaultRequestedPath) : defaultRequestedPath;
|
|
8790
9393
|
if (absoluteConfigPath === absoluteDefaultPath) return void 0;
|
|
@@ -8889,9 +9492,9 @@ function openBrowser(url, errorsToStderr = false) {
|
|
|
8889
9492
|
});
|
|
8890
9493
|
}
|
|
8891
9494
|
async function writeDeployManifest(manifestPath, manifest) {
|
|
8892
|
-
const outputPath =
|
|
9495
|
+
const outputPath = resolve8(process.cwd(), manifestPath);
|
|
8893
9496
|
await writeAtomicFile({
|
|
8894
|
-
boundaryPath:
|
|
9497
|
+
boundaryPath: dirname12(outputPath),
|
|
8895
9498
|
force: true,
|
|
8896
9499
|
label: "Deploy manifest",
|
|
8897
9500
|
managed: true,
|
|
@@ -8912,7 +9515,13 @@ function createCompiledMapAssets(compiled, resolveSprite) {
|
|
|
8912
9515
|
return Object.fromEntries(
|
|
8913
9516
|
compiled.bindings.map((binding) => [
|
|
8914
9517
|
binding.mapName,
|
|
8915
|
-
{
|
|
9518
|
+
{
|
|
9519
|
+
icons: {
|
|
9520
|
+
ids: binding.iconIds,
|
|
9521
|
+
sprite: resolveSprite(binding),
|
|
9522
|
+
...binding.appearances ? { appearances: binding.appearances } : {}
|
|
9523
|
+
}
|
|
9524
|
+
}
|
|
8916
9525
|
])
|
|
8917
9526
|
);
|
|
8918
9527
|
}
|
|
@@ -8969,7 +9578,7 @@ function validateDeployManifestMapNames(mapNames) {
|
|
|
8969
9578
|
async function loadExistingDeployManifest(manifestPath, options) {
|
|
8970
9579
|
let source;
|
|
8971
9580
|
try {
|
|
8972
|
-
source = await readFile7(
|
|
9581
|
+
source = await readFile7(resolve8(process.cwd(), manifestPath), "utf8");
|
|
8973
9582
|
} catch (error) {
|
|
8974
9583
|
if (error.code === "ENOENT") return null;
|
|
8975
9584
|
throw new Error("Existing Tileflow manifest could not be read.");
|
|
@@ -8983,7 +9592,7 @@ async function loadExistingDeployManifest(manifestPath, options) {
|
|
|
8983
9592
|
}
|
|
8984
9593
|
let manifest;
|
|
8985
9594
|
try {
|
|
8986
|
-
manifest =
|
|
9595
|
+
manifest = parseTileflowRuntimeManifest2(value);
|
|
8987
9596
|
} catch {
|
|
8988
9597
|
throw new Error(
|
|
8989
9598
|
"Existing Tileflow manifest does not match the strict theme manifest contract."
|