@wix/himalaya-cli 0.1454.0 → 0.1456.0
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/dist/cli.mjs +565 -470
- package/guides/designing-himi-screens.md +7 -1
- package/guides/hhp.md +16 -0
- package/guides/recipe-search.md +125 -0
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -4346,8 +4346,8 @@ function committedProvisioningPath(name) {
|
|
|
4346
4346
|
function committedShellFor(path2) {
|
|
4347
4347
|
const normalized = path2.replace(/\\/g, "/");
|
|
4348
4348
|
return SHELL_NAMES2.find((name) => {
|
|
4349
|
-
const
|
|
4350
|
-
return normalized ===
|
|
4349
|
+
const relative18 = committedProvisioningPath(name);
|
|
4350
|
+
return normalized === relative18 || normalized.endsWith(`/${relative18}`);
|
|
4351
4351
|
});
|
|
4352
4352
|
}
|
|
4353
4353
|
function isBrandable(repoRoot2, name) {
|
|
@@ -7070,9 +7070,9 @@ function compileV2(html, profile, options) {
|
|
|
7070
7070
|
if (!row) error(el2, "HHP-BINDING-SCOPE", "Item bindings require a keyed list template.");
|
|
7071
7071
|
return raw;
|
|
7072
7072
|
}
|
|
7073
|
-
const
|
|
7074
|
-
if (!info4?.paths.has(
|
|
7075
|
-
return `$service:${serviceName}.${
|
|
7073
|
+
const relative18 = statePath(raw);
|
|
7074
|
+
if (!info4?.paths.has(relative18)) error(el2, "HHP-BINDING-PATH", `Unknown controller state path ${relative18}.`);
|
|
7075
|
+
return `$service:${serviceName}.${relative18}`;
|
|
7076
7076
|
}
|
|
7077
7077
|
const read = (value, dotted) => dotted.split(".").reduce((current, key3) => current && typeof current === "object" && Object.hasOwn(current, key3) ? current[key3] : void 0, value);
|
|
7078
7078
|
function rowValues(row, raw) {
|
|
@@ -14624,6 +14624,277 @@ var init_loader = __esm({
|
|
|
14624
14624
|
}
|
|
14625
14625
|
});
|
|
14626
14626
|
|
|
14627
|
+
// ../app-icons/pixels.ts
|
|
14628
|
+
var pixels_exports = {};
|
|
14629
|
+
__export(pixels_exports, {
|
|
14630
|
+
LETTERBOX_ERROR_FRACTION: () => LETTERBOX_ERROR_FRACTION,
|
|
14631
|
+
LETTERBOX_WARN_FRACTION: () => LETTERBOX_WARN_FRACTION,
|
|
14632
|
+
NORMALIZE_FIT_FRACTION: () => NORMALIZE_FIT_FRACTION,
|
|
14633
|
+
PIXEL_TOOLCHAIN_HINT: () => PIXEL_TOOLCHAIN_HINT,
|
|
14634
|
+
PixelToolchainUnavailable: () => PixelToolchainUnavailable,
|
|
14635
|
+
SVG_RASTER_MAX_EDGE: () => SVG_RASTER_MAX_EDGE,
|
|
14636
|
+
appStoreIconPixelFindings: () => appStoreIconPixelFindings,
|
|
14637
|
+
derivePlayListingIcon: () => derivePlayListingIcon,
|
|
14638
|
+
inspectIconPixels: () => inspectIconPixels,
|
|
14639
|
+
normalizeSourceIcon: () => normalizeSourceIcon,
|
|
14640
|
+
pixelToolchainAvailable: () => pixelToolchainAvailable,
|
|
14641
|
+
pixelToolchainProblem: () => pixelToolchainProblem,
|
|
14642
|
+
rasterizeSvg: () => rasterizeSvg,
|
|
14643
|
+
renderGlyphTile: () => renderGlyphTile
|
|
14644
|
+
});
|
|
14645
|
+
function isNotInstalled(e2) {
|
|
14646
|
+
const code = e2?.code;
|
|
14647
|
+
return code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND";
|
|
14648
|
+
}
|
|
14649
|
+
function messageOf(e2) {
|
|
14650
|
+
return e2 instanceof Error ? e2.message : String(e2);
|
|
14651
|
+
}
|
|
14652
|
+
async function loadSharp() {
|
|
14653
|
+
if (cachedSharp) return cachedSharp;
|
|
14654
|
+
const failures = [];
|
|
14655
|
+
let presentButBroken = false;
|
|
14656
|
+
try {
|
|
14657
|
+
const { createRequire: createRequire4 } = await import("node:module");
|
|
14658
|
+
cachedSharp = createRequire4(import.meta.url)("sharp");
|
|
14659
|
+
lastProblem = null;
|
|
14660
|
+
return cachedSharp;
|
|
14661
|
+
} catch (e2) {
|
|
14662
|
+
presentButBroken ||= !isNotInstalled(e2);
|
|
14663
|
+
failures.push(`require: ${messageOf(e2)}`);
|
|
14664
|
+
}
|
|
14665
|
+
try {
|
|
14666
|
+
cachedSharp = (await import("sharp")).default;
|
|
14667
|
+
lastProblem = null;
|
|
14668
|
+
return cachedSharp;
|
|
14669
|
+
} catch (e2) {
|
|
14670
|
+
presentButBroken ||= !isNotInstalled(e2);
|
|
14671
|
+
failures.push(`import: ${messageOf(e2)}`);
|
|
14672
|
+
}
|
|
14673
|
+
lastProblem = presentButBroken ? `the image toolchain (sharp) is installed but could not be loaded \u2014 ${failures.join("; ")}` : PIXEL_TOOLCHAIN_HINT;
|
|
14674
|
+
return null;
|
|
14675
|
+
}
|
|
14676
|
+
async function pixelToolchainAvailable() {
|
|
14677
|
+
return await loadSharp() !== null;
|
|
14678
|
+
}
|
|
14679
|
+
async function pixelToolchainProblem() {
|
|
14680
|
+
return await loadSharp() === null ? lastProblem ?? PIXEL_TOOLCHAIN_HINT : null;
|
|
14681
|
+
}
|
|
14682
|
+
async function sharpOrThrow() {
|
|
14683
|
+
const s2 = await loadSharp();
|
|
14684
|
+
if (!s2) throw new PixelToolchainUnavailable(lastProblem ?? PIXEL_TOOLCHAIN_HINT);
|
|
14685
|
+
return s2;
|
|
14686
|
+
}
|
|
14687
|
+
async function inspectIconPixels(png) {
|
|
14688
|
+
const sharp = await sharpOrThrow();
|
|
14689
|
+
const { data, info: info4 } = await sharp(png).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
14690
|
+
const { width, height, channels: channels3 } = info4;
|
|
14691
|
+
if (channels3 !== 4) throw new Error(`app-icons: expected RGBA after ensureAlpha, got ${channels3} channels`);
|
|
14692
|
+
let minAlpha = 255;
|
|
14693
|
+
let transparent = 0;
|
|
14694
|
+
for (let i2 = 3; i2 < data.length; i2 += 4) {
|
|
14695
|
+
const a2 = data[i2];
|
|
14696
|
+
if (a2 < minAlpha) minAlpha = a2;
|
|
14697
|
+
if (a2 <= ALPHA_OPAQUE) transparent++;
|
|
14698
|
+
}
|
|
14699
|
+
const probe = Math.max(1, Math.round(Math.min(width, height) * CORNER_PROBE));
|
|
14700
|
+
let minCornerAlpha = 255;
|
|
14701
|
+
for (const [x0, y0] of [
|
|
14702
|
+
[0, 0],
|
|
14703
|
+
[width - probe, 0],
|
|
14704
|
+
[0, height - probe],
|
|
14705
|
+
[width - probe, height - probe]
|
|
14706
|
+
]) {
|
|
14707
|
+
for (let y2 = y0; y2 < y0 + probe; y2++) {
|
|
14708
|
+
for (let x2 = x0; x2 < x0 + probe; x2++) {
|
|
14709
|
+
const a2 = data[(y2 * width + x2) * 4 + 3];
|
|
14710
|
+
if (a2 < minCornerAlpha) minCornerAlpha = a2;
|
|
14711
|
+
}
|
|
14712
|
+
}
|
|
14713
|
+
}
|
|
14714
|
+
const inset = Math.round(Math.min(width, height) * INTERIOR_INSET);
|
|
14715
|
+
let interiorMinAlpha = 255;
|
|
14716
|
+
for (let y2 = inset; y2 < height - inset; y2++) {
|
|
14717
|
+
for (let x2 = inset; x2 < width - inset; x2++) {
|
|
14718
|
+
const a2 = data[(y2 * width + x2) * 4 + 3];
|
|
14719
|
+
if (a2 < interiorMinAlpha) interiorMinAlpha = a2;
|
|
14720
|
+
}
|
|
14721
|
+
}
|
|
14722
|
+
return {
|
|
14723
|
+
width,
|
|
14724
|
+
height,
|
|
14725
|
+
minAlpha,
|
|
14726
|
+
transparentFraction: transparent / (width * height),
|
|
14727
|
+
minCornerAlpha,
|
|
14728
|
+
interiorMinAlpha,
|
|
14729
|
+
// `minAlpha <= ALPHA_OPAQUE` IS "has transparency", and the caller has just computed
|
|
14730
|
+
// it — contentBox used to re-derive it with a full extra sweep of the raster.
|
|
14731
|
+
contentBox: contentBox(data, width, height, minAlpha <= ALPHA_OPAQUE)
|
|
14732
|
+
};
|
|
14733
|
+
}
|
|
14734
|
+
function contentBox(data, width, height, hasTransparency) {
|
|
14735
|
+
const at2 = (x2, y2) => (y2 * width + x2) * 4;
|
|
14736
|
+
const bg = [data[at2(0, 0)], data[at2(0, 0) + 1], data[at2(0, 0) + 2]];
|
|
14737
|
+
const isInk = (x2, y2) => {
|
|
14738
|
+
const i2 = at2(x2, y2);
|
|
14739
|
+
if (hasTransparency) return data[i2 + 3] > ALPHA_OPAQUE;
|
|
14740
|
+
return Math.abs(data[i2] - bg[0]) > INK_TOLERANCE || Math.abs(data[i2 + 1] - bg[1]) > INK_TOLERANCE || Math.abs(data[i2 + 2] - bg[2]) > INK_TOLERANCE;
|
|
14741
|
+
};
|
|
14742
|
+
let minX = width, minY = height, maxX = -1, maxY = -1;
|
|
14743
|
+
for (let y2 = 0; y2 < height; y2++) {
|
|
14744
|
+
for (let x2 = 0; x2 < width; x2++) {
|
|
14745
|
+
if (!isInk(x2, y2)) continue;
|
|
14746
|
+
if (x2 < minX) minX = x2;
|
|
14747
|
+
if (x2 > maxX) maxX = x2;
|
|
14748
|
+
if (y2 < minY) minY = y2;
|
|
14749
|
+
if (y2 > maxY) maxY = y2;
|
|
14750
|
+
}
|
|
14751
|
+
}
|
|
14752
|
+
if (maxX < 0) return null;
|
|
14753
|
+
return {
|
|
14754
|
+
widthFraction: (maxX - minX + 1) / width,
|
|
14755
|
+
heightFraction: (maxY - minY + 1) / height
|
|
14756
|
+
};
|
|
14757
|
+
}
|
|
14758
|
+
function appStoreIconPixelFindings(f2) {
|
|
14759
|
+
const out2 = [];
|
|
14760
|
+
const preMasked = f2.interiorMinAlpha > ALPHA_OPAQUE && f2.minCornerAlpha <= ALPHA_OPAQUE && f2.transparentFraction <= PRE_MASK_MAX_TRANSPARENT_FRACTION;
|
|
14761
|
+
if (preMasked) {
|
|
14762
|
+
out2.push({
|
|
14763
|
+
level: "error",
|
|
14764
|
+
message: "App icon looks pre-masked: its corners are transparent while the middle is opaque. iOS and Play both apply their own corner mask, so rounded artwork is rounded twice and looks visibly wrong on device \u2014 and the transparency itself is an App Store rejection (ITMS-90717 / ITMS-90647). Ship a full-bleed square with 90-degree corners and no inset."
|
|
14765
|
+
});
|
|
14766
|
+
} else if (f2.minAlpha <= ALPHA_OPAQUE) {
|
|
14767
|
+
out2.push({
|
|
14768
|
+
level: "error",
|
|
14769
|
+
message: `App icon has transparent pixels (${(f2.transparentFraction * 100).toFixed(1)}% of the canvas, lowest alpha ${f2.minAlpha}). An App Store icon may carry an alpha channel but no transparent regions \u2014 Apple rejects this as ITMS-90717 / ITMS-90647. Flatten it onto an opaque background (\`himi icon set <file>\` does this for you).`
|
|
14770
|
+
});
|
|
14771
|
+
}
|
|
14772
|
+
if (f2.contentBox === null) {
|
|
14773
|
+
out2.push({
|
|
14774
|
+
level: "error",
|
|
14775
|
+
message: "App icon is a single flat colour with no distinguishable artwork \u2014 the mark is not visible in it. Supply art that contrasts with the background, or use `himi icon generate` for a glyph tile."
|
|
14776
|
+
});
|
|
14777
|
+
return out2;
|
|
14778
|
+
}
|
|
14779
|
+
const shorter = Math.min(f2.contentBox.widthFraction, f2.contentBox.heightFraction);
|
|
14780
|
+
if (shorter < LETTERBOX_ERROR_FRACTION) {
|
|
14781
|
+
out2.push({
|
|
14782
|
+
level: "error",
|
|
14783
|
+
message: `App icon artwork fills only ${(shorter * 100).toFixed(0)}% of the canvas on its shorter side, so it reads as a speck on a home screen. This is what a wide wordmark centred in a square looks like \u2014 crop to the mark, or use a monogram/glyph instead of the wordmark.`
|
|
14784
|
+
});
|
|
14785
|
+
} else if (shorter < LETTERBOX_WARN_FRACTION) {
|
|
14786
|
+
out2.push({
|
|
14787
|
+
level: "warn",
|
|
14788
|
+
message: `App icon artwork fills ${(shorter * 100).toFixed(0)}% of the canvas on its shorter side \u2014 it will read as a thin strip at home-screen size. Consider cropping to the mark.`
|
|
14789
|
+
});
|
|
14790
|
+
}
|
|
14791
|
+
return out2;
|
|
14792
|
+
}
|
|
14793
|
+
function luminance([r2, g2, b2]) {
|
|
14794
|
+
const lin = [r2, g2, b2].map((v2) => {
|
|
14795
|
+
const c2 = v2 / 255;
|
|
14796
|
+
return c2 <= 0.04045 ? c2 / 12.92 : ((c2 + 0.055) / 1.055) ** 2.4;
|
|
14797
|
+
});
|
|
14798
|
+
return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2];
|
|
14799
|
+
}
|
|
14800
|
+
function contrastRatio(a2, b2) {
|
|
14801
|
+
const [hi2, lo2] = [luminance(a2), luminance(b2)].sort((x2, y2) => y2 - x2);
|
|
14802
|
+
return (hi2 + 0.05) / (lo2 + 0.05);
|
|
14803
|
+
}
|
|
14804
|
+
async function contrastingBackdrop(mark, requested) {
|
|
14805
|
+
const sharp = await sharpOrThrow();
|
|
14806
|
+
const { dominant } = await sharp(mark).stats();
|
|
14807
|
+
const ink = [dominant.r, dominant.g, dominant.b];
|
|
14808
|
+
const want = hexToRgb(requested);
|
|
14809
|
+
if (!want || contrastRatio(ink, want) >= MIN_BACKDROP_CONTRAST) return requested;
|
|
14810
|
+
const towardsWhite = luminance(ink) < 0.5;
|
|
14811
|
+
for (const amount of [0.35, 0.55, 0.75, 0.9]) {
|
|
14812
|
+
const candidate = mix(want, towardsWhite ? [255, 255, 255] : [0, 0, 0], amount);
|
|
14813
|
+
if (contrastRatio(ink, candidate) >= MIN_BACKDROP_CONTRAST) return rgbToHex(candidate);
|
|
14814
|
+
}
|
|
14815
|
+
return towardsWhite ? "#FFFFFF" : "#000000";
|
|
14816
|
+
}
|
|
14817
|
+
function hexToRgb(hex2) {
|
|
14818
|
+
const m2 = /^#([0-9a-fA-F]{6})$/.exec(hex2);
|
|
14819
|
+
if (!m2) return null;
|
|
14820
|
+
const n2 = parseInt(m2[1], 16);
|
|
14821
|
+
return [n2 >> 16 & 255, n2 >> 8 & 255, n2 & 255];
|
|
14822
|
+
}
|
|
14823
|
+
function mix(a2, b2, t2) {
|
|
14824
|
+
return [0, 1, 2].map((i2) => Math.round(a2[i2] + (b2[i2] - a2[i2]) * t2));
|
|
14825
|
+
}
|
|
14826
|
+
function rgbToHex([r2, g2, b2]) {
|
|
14827
|
+
return `#${[r2, g2, b2].map((v2) => v2.toString(16).padStart(2, "0")).join("")}`.toUpperCase();
|
|
14828
|
+
}
|
|
14829
|
+
async function normalizeSourceIcon(input, opts) {
|
|
14830
|
+
const sharp = await sharpOrThrow();
|
|
14831
|
+
const size = opts.size ?? 1024;
|
|
14832
|
+
const fit2 = opts.fit ?? NORMALIZE_FIT_FRACTION;
|
|
14833
|
+
const inner = Math.max(1, Math.round(size * fit2));
|
|
14834
|
+
const pad3 = Math.round((size - inner) / 2);
|
|
14835
|
+
let trimmed;
|
|
14836
|
+
try {
|
|
14837
|
+
trimmed = await sharp(input).ensureAlpha().trim().png().toBuffer();
|
|
14838
|
+
} catch {
|
|
14839
|
+
trimmed = await sharp(input).ensureAlpha().png().toBuffer();
|
|
14840
|
+
}
|
|
14841
|
+
const mark = await sharp(trimmed).resize(inner, inner, { fit: "contain", background: { r: 0, g: 0, b: 0, alpha: 0 } }).png().toBuffer();
|
|
14842
|
+
const background = await contrastingBackdrop(mark, opts.background);
|
|
14843
|
+
return sharp({
|
|
14844
|
+
create: {
|
|
14845
|
+
width: size,
|
|
14846
|
+
height: size,
|
|
14847
|
+
channels: 4,
|
|
14848
|
+
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
|
14849
|
+
}
|
|
14850
|
+
}).composite([{ input: mark, top: pad3, left: pad3 }]).flatten({ background }).removeAlpha().png({ palette: false }).toBuffer();
|
|
14851
|
+
}
|
|
14852
|
+
async function derivePlayListingIcon(master, size = 512) {
|
|
14853
|
+
const sharp = await sharpOrThrow();
|
|
14854
|
+
return sharp(master).resize(size, size).ensureAlpha().png({ palette: false }).toBuffer();
|
|
14855
|
+
}
|
|
14856
|
+
async function renderGlyphTile(svg, background, size = 1024) {
|
|
14857
|
+
const sharp = await sharpOrThrow();
|
|
14858
|
+
return sharp(Buffer.from(svg)).resize(size, size).flatten({ background }).removeAlpha().png({ palette: false }).toBuffer();
|
|
14859
|
+
}
|
|
14860
|
+
async function rasterizeSvg(svg, scale = 3) {
|
|
14861
|
+
const sharp = await loadSharp();
|
|
14862
|
+
if (!sharp) return null;
|
|
14863
|
+
const { width = 0, height = 0 } = await sharp(svg, { limitInputPixels: false }).metadata();
|
|
14864
|
+
const edge = Math.max(width, height);
|
|
14865
|
+
const density = edge > 0 ? Math.max(1, Math.min(72 * scale, 72 * SVG_RASTER_MAX_EDGE / edge)) : 72 * scale;
|
|
14866
|
+
const decoded = width * density / 72 * (height * density / 72);
|
|
14867
|
+
if (decoded > SHARP_INPUT_PIXEL_LIMIT) {
|
|
14868
|
+
throw new Error(`SVG is too large to rasterize: ${width}x${height} intrinsic size; give it a width/height (or viewBox) under ${Math.floor(72 * Math.sqrt(SHARP_INPUT_PIXEL_LIMIT))}px per side`);
|
|
14869
|
+
}
|
|
14870
|
+
return sharp(svg, { density }).resize({ width: SVG_RASTER_MAX_EDGE, height: SVG_RASTER_MAX_EDGE, fit: "inside", withoutEnlargement: true }).png().toBuffer();
|
|
14871
|
+
}
|
|
14872
|
+
var cachedSharp, lastProblem, PIXEL_TOOLCHAIN_HINT, PixelToolchainUnavailable, ALPHA_OPAQUE, CORNER_PROBE, INTERIOR_INSET, INK_TOLERANCE, PRE_MASK_MAX_TRANSPARENT_FRACTION, LETTERBOX_WARN_FRACTION, LETTERBOX_ERROR_FRACTION, NORMALIZE_FIT_FRACTION, MIN_BACKDROP_CONTRAST, SVG_RASTER_MAX_EDGE, SHARP_INPUT_PIXEL_LIMIT;
|
|
14873
|
+
var init_pixels = __esm({
|
|
14874
|
+
"../app-icons/pixels.ts"() {
|
|
14875
|
+
cachedSharp = null;
|
|
14876
|
+
lastProblem = null;
|
|
14877
|
+
PIXEL_TOOLCHAIN_HINT = "the image toolchain (sharp) is not installed \u2014 run `npm i -g sharp` to enable transparency, pre-masked-corner and letterbox checks";
|
|
14878
|
+
PixelToolchainUnavailable = class extends Error {
|
|
14879
|
+
constructor(reason = PIXEL_TOOLCHAIN_HINT) {
|
|
14880
|
+
super(`app-icons: ${reason}`);
|
|
14881
|
+
this.name = "PixelToolchainUnavailable";
|
|
14882
|
+
}
|
|
14883
|
+
};
|
|
14884
|
+
ALPHA_OPAQUE = 250;
|
|
14885
|
+
CORNER_PROBE = 0.06;
|
|
14886
|
+
INTERIOR_INSET = 0.2;
|
|
14887
|
+
INK_TOLERANCE = 24;
|
|
14888
|
+
PRE_MASK_MAX_TRANSPARENT_FRACTION = 0.1;
|
|
14889
|
+
LETTERBOX_WARN_FRACTION = 0.35;
|
|
14890
|
+
LETTERBOX_ERROR_FRACTION = 0.2;
|
|
14891
|
+
NORMALIZE_FIT_FRACTION = 0.82;
|
|
14892
|
+
MIN_BACKDROP_CONTRAST = 1.5;
|
|
14893
|
+
SVG_RASTER_MAX_EDGE = 2048;
|
|
14894
|
+
SHARP_INPUT_PIXEL_LIMIT = 16383 * 16383;
|
|
14895
|
+
}
|
|
14896
|
+
});
|
|
14897
|
+
|
|
14627
14898
|
// ../../apps/himi-player/player-host-manifest.ts
|
|
14628
14899
|
var PLAYER_HOST_MANIFEST;
|
|
14629
14900
|
var init_player_host_manifest = __esm({
|
|
@@ -15011,8 +15282,8 @@ var init_hhp_command = __esm({
|
|
|
15011
15282
|
|
|
15012
15283
|
// src/hhp.ts
|
|
15013
15284
|
import { existsSync as existsSync15, readFileSync as readFileSync16, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, renameSync, rmSync as rmSync4, lstatSync as lstatSync5, readdirSync as readdirSync12 } from "node:fs";
|
|
15014
|
-
import { dirname as dirname11, resolve as resolve17, relative as relative3, sep as sep6, join as join15 } from "node:path";
|
|
15015
|
-
import { randomUUID } from "node:crypto";
|
|
15285
|
+
import { basename as basename7, dirname as dirname11, resolve as resolve17, relative as relative3, sep as sep6, join as join15 } from "node:path";
|
|
15286
|
+
import { createHash as createHash8, randomUUID } from "node:crypto";
|
|
15016
15287
|
import ts3 from "typescript";
|
|
15017
15288
|
function localPath(root, path2, from = join15(root, "hhp.json")) {
|
|
15018
15289
|
if (/^[a-z]+:|^\/\//i.test(path2)) throw new Error("HHP source dependencies must be local files.");
|
|
@@ -15082,7 +15353,7 @@ export function withHhpScreens<T extends { screens: { exact: Record<string, any>
|
|
|
15082
15353
|
for (const id of Object.keys(descriptors)) if (Object.hasOwn(app.screens.exact, id)) throw new Error("HHP screen conflicts with authored screen: " + id);
|
|
15083
15354
|
const exact = Object.fromEntries(Object.entries(descriptors).map(([id, descriptor]) => [id, (ctx: { serverBaseUrl: string; bundleIntegrity(name: string): string | null; asset(name: string): {url:string} | null }) => {
|
|
15084
15355
|
const result = structuredClone(descriptor);
|
|
15085
|
-
const resolveAssets = (value: any, field = ""): any => { if (["url", "imageUrl", "src"].includes(field) && typeof value === "string" && value.startsWith("asset:")) { const asset = ctx.asset(value.slice(6)); if (!asset) throw new Error("Missing HHP asset " + value); return asset.url; } if (Array.isArray(value)) return value.map((child) => resolveAssets(child, field)); if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, resolveAssets(child, key)])); return value; }; result.payload = resolveAssets(result.payload);
|
|
15356
|
+
const resolveAssets = (value: any, field = ""): any => { if (["url", "imageUrl", "src"].includes(field) && typeof value === "string" && value.startsWith("asset:")) { const asset = ctx.asset(value.slice(6)); if (!asset) throw new Error("Missing HHP asset " + value); return asset.url.replace(/^[a-z][a-z0-9+.-]*:\\/\\/[^/?#]*/i, ""); } if (Array.isArray(value)) return value.map((child) => resolveAssets(child, field)); if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, resolveAssets(child, key)])); return value; }; result.payload = resolveAssets(result.payload);
|
|
15086
15357
|
if (result.logicBundle) { const name = result.logicBundle.url.split("/").pop()!; const sri = ctx.bundleIntegrity(name); if (!sri) return null; result.logicBundle.url = ctx.serverBaseUrl + result.logicBundle.url; result.logicBundle.integrity = sri; }
|
|
15087
15358
|
return result;
|
|
15088
15359
|
}]));
|
|
@@ -15097,9 +15368,18 @@ async function compileContentHhp(root, opts = {}) {
|
|
|
15097
15368
|
const diagnostics = [], results = [];
|
|
15098
15369
|
const outputs = /* @__PURE__ */ new Map();
|
|
15099
15370
|
const assets = collectAssets(root);
|
|
15371
|
+
const svgRefs = /* @__PURE__ */ new Map();
|
|
15372
|
+
const directRasters = /* @__PURE__ */ new Set();
|
|
15100
15373
|
const assetName = (path2, from) => {
|
|
15101
15374
|
const hit = path2.startsWith("asset:") ? assets.find((asset) => asset.name === path2.slice(6)) : assets.find((asset) => asset.path === localPath(root, path2, from));
|
|
15102
15375
|
if (!hit) throw new Error(`Local resource ${path2} must exist in the app's declared assets directory.`);
|
|
15376
|
+
if (/\.svg$/i.test(hit.name) && !hit.name.startsWith(`${RASTER_DIR}/`)) {
|
|
15377
|
+
const ref = svgRefs.get(hit.path) ?? { name: hit.name, raster: rasterName(hit.name, readFileSync16(hit.path)), files: /* @__PURE__ */ new Set() };
|
|
15378
|
+
ref.files.add(from);
|
|
15379
|
+
svgRefs.set(hit.path, ref);
|
|
15380
|
+
return ref.raster;
|
|
15381
|
+
}
|
|
15382
|
+
if (hit.name.startsWith(`${RASTER_DIR}/`)) directRasters.add(hit.path);
|
|
15103
15383
|
return hit.name;
|
|
15104
15384
|
};
|
|
15105
15385
|
const indexPath = localPath(root, "dev/index.ts"), originalIndex = readFileSync16(indexPath, "utf8"), wiredIndex = managedRegistry(originalIndex);
|
|
@@ -15146,6 +15426,28 @@ async function compileContentHhp(root, opts = {}) {
|
|
|
15146
15426
|
const existing = (await loadContent(root, { fresh: true })).module.screens.exact;
|
|
15147
15427
|
for (const id of Object.keys(manifest.screens)) if (Object.hasOwn(existing, id)) diagnostics.push({ code: "HHP-REGISTRY-CONFLICT", severity: "error", file: indexPath, line: 1, column: 1, message: `HHP screen ${id} conflicts with an authored screen.` });
|
|
15148
15428
|
}
|
|
15429
|
+
const rasters = /* @__PURE__ */ new Map();
|
|
15430
|
+
for (const path2 of directRasters) rasters.set(path2, null);
|
|
15431
|
+
const assetsDir = findAssetsDir(root);
|
|
15432
|
+
for (const [path2, ref] of [...svgRefs].sort(([a2], [b2]) => a2.localeCompare(b2))) {
|
|
15433
|
+
let png;
|
|
15434
|
+
try {
|
|
15435
|
+
png = await (opts.rasterizeSvg ?? rasterizeSvg)(readFileSync16(path2));
|
|
15436
|
+
} catch (e2) {
|
|
15437
|
+
for (const file2 of ref.files) diagnostics.push({ code: "HHP-ASSET-SVG", severity: "error", file: file2, line: 1, column: 1, message: `Could not rasterize ${ref.name} (${e2.message.split("\n")[0]}). Fix the SVG, or export it as PNG or WebP.` });
|
|
15438
|
+
continue;
|
|
15439
|
+
}
|
|
15440
|
+
const target2 = assetsDir && join15(assetsDir, ref.raster);
|
|
15441
|
+
if (!png && target2 && existsExact(target2)) {
|
|
15442
|
+
rasters.set(target2, null);
|
|
15443
|
+
continue;
|
|
15444
|
+
}
|
|
15445
|
+
if (!png || !target2) {
|
|
15446
|
+
for (const file2 of ref.files) diagnostics.push({ code: "HHP-ASSET-SVG", severity: "error", file: file2, line: 1, column: 1, message: `${ref.name} is an SVG image, which iOS and Android cannot decode, and the image toolchain (sharp) that converts it to PNG is unavailable. Export it as PNG or WebP, or install sharp (\`npm i -g sharp\`).` });
|
|
15447
|
+
continue;
|
|
15448
|
+
}
|
|
15449
|
+
rasters.set(target2, png);
|
|
15450
|
+
}
|
|
15149
15451
|
const ok2 = !diagnostics.some((d2) => d2.severity === "error");
|
|
15150
15452
|
if (!ok2) return { ok: ok2, diagnostics, screens: Object.keys(manifest.screens), outputs: [] };
|
|
15151
15453
|
outputs.set("dev/hhp/index.ts", registry(results));
|
|
@@ -15167,6 +15469,14 @@ async function compileContentHhp(root, opts = {}) {
|
|
|
15167
15469
|
const path2 = localPath(root, rel);
|
|
15168
15470
|
if (existsSync15(path2) && rel.endsWith(".ts") && !readFileSync16(path2, "utf8").startsWith(GENERATED.trim()) && !readFileSync16(path2, "utf8").startsWith("// GENERATED HHP v2 worker.")) throw new Error(`HHP output conflicts with authored file ${rel}.`);
|
|
15169
15471
|
}
|
|
15472
|
+
for (const [path2, png] of rasters) {
|
|
15473
|
+
if (!png) continue;
|
|
15474
|
+
if (existsExact(path2) && readFileSync16(path2).equals(png)) continue;
|
|
15475
|
+
mkdirSync7(dirname11(path2), { recursive: true });
|
|
15476
|
+
writeFileSync7(`${path2}.tmp`, png);
|
|
15477
|
+
rmSync4(path2, { force: true });
|
|
15478
|
+
renameSync(`${path2}.tmp`, path2);
|
|
15479
|
+
}
|
|
15170
15480
|
const target = localPath(root, "dev/hhp"), stage = localPath(root, `dev/.hhp-${randomUUID()}`), backup = `${stage}-old`;
|
|
15171
15481
|
mkdirSync7(stage, { recursive: true });
|
|
15172
15482
|
try {
|
|
@@ -15211,8 +15521,26 @@ async function compileContentHhp(root, opts = {}) {
|
|
|
15211
15521
|
} finally {
|
|
15212
15522
|
rmSync4(stage, { recursive: true, force: true });
|
|
15213
15523
|
}
|
|
15524
|
+
pruneRasters(root, rasters);
|
|
15214
15525
|
return result;
|
|
15215
15526
|
}
|
|
15527
|
+
function pruneRasters(root, rasters) {
|
|
15528
|
+
const keep = new Set(rasters.keys());
|
|
15529
|
+
const assetsDir = findAssetsDir(root);
|
|
15530
|
+
const dir = assetsDir && join15(assetsDir, RASTER_DIR);
|
|
15531
|
+
if (!dir || !existsSync15(dir)) return;
|
|
15532
|
+
const walk2 = (abs) => {
|
|
15533
|
+
for (const entry of readdirSync12(abs, { withFileTypes: true })) {
|
|
15534
|
+
const child = join15(abs, entry.name);
|
|
15535
|
+
if (entry.isDirectory()) {
|
|
15536
|
+
walk2(child);
|
|
15537
|
+
if (!readdirSync12(child).length) rmSync4(child, { recursive: true });
|
|
15538
|
+
} else if (entry.isFile() && RASTER_FILE.test(entry.name) && !keep.has(child)) rmSync4(child);
|
|
15539
|
+
}
|
|
15540
|
+
};
|
|
15541
|
+
walk2(dir);
|
|
15542
|
+
if (!readdirSync12(dir).length) rmSync4(dir, { recursive: true });
|
|
15543
|
+
}
|
|
15216
15544
|
async function initHhpScreen(root, id) {
|
|
15217
15545
|
if (!/^[a-z][a-z0-9_]*$/.test(id)) throw new Error("Use a lowercase screen name with underscores.");
|
|
15218
15546
|
const manifest = readHhpManifest(root) ?? { version: "hhp/2", screens: {} };
|
|
@@ -15270,7 +15598,7 @@ function hhpEditorSettings(source) {
|
|
|
15270
15598
|
}
|
|
15271
15599
|
return JSON.stringify(settings, null, 2) + "\n";
|
|
15272
15600
|
}
|
|
15273
|
-
var GENERATED, BEGIN, END;
|
|
15601
|
+
var GENERATED, BEGIN, END, RASTER_DIR, existsExact, rasterName, RASTER_FILE;
|
|
15274
15602
|
var init_hhp = __esm({
|
|
15275
15603
|
"src/hhp.ts"() {
|
|
15276
15604
|
init_catalog();
|
|
@@ -15279,9 +15607,14 @@ var init_hhp = __esm({
|
|
|
15279
15607
|
init_loader();
|
|
15280
15608
|
init_preview_surfaces();
|
|
15281
15609
|
init_app_assets();
|
|
15610
|
+
init_pixels();
|
|
15282
15611
|
GENERATED = "// GENERATED HHP v2 \u2014 edit screens/, then run himi build.\n";
|
|
15283
15612
|
BEGIN = "// himi:hhp:begin";
|
|
15284
15613
|
END = "// himi:hhp:end";
|
|
15614
|
+
RASTER_DIR = "hhp-raster";
|
|
15615
|
+
existsExact = (path2) => existsSync15(path2) && readdirSync12(dirname11(path2)).includes(basename7(path2));
|
|
15616
|
+
rasterName = (svgName, svg) => `${RASTER_DIR}/${svgName.split("/").join("__")}.${createHash8("sha256").update(svg).digest("hex").slice(0, 12)}.png`;
|
|
15617
|
+
RASTER_FILE = /\.svg\.[0-9a-f]{12}\.png$/i;
|
|
15285
15618
|
}
|
|
15286
15619
|
});
|
|
15287
15620
|
|
|
@@ -17842,7 +18175,7 @@ function relativeLuminance(hex2) {
|
|
|
17842
18175
|
const lin = [1, 3, 5].map((i2) => parseInt(hex2.slice(i2, i2 + 2), 16) / 255).map((v2) => v2 <= 0.03928 ? v2 / 12.92 : ((v2 + 0.055) / 1.055) ** 2.4);
|
|
17843
18176
|
return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2];
|
|
17844
18177
|
}
|
|
17845
|
-
function
|
|
18178
|
+
function contrastRatio2(a2, b2) {
|
|
17846
18179
|
const la2 = relativeLuminance(a2);
|
|
17847
18180
|
const lb = relativeLuminance(b2);
|
|
17848
18181
|
return (Math.max(la2, lb) + 0.05) / (Math.min(la2, lb) + 0.05);
|
|
@@ -17930,7 +18263,7 @@ function channel2(hex2, offset) {
|
|
|
17930
18263
|
function toHex(r2, g2, b2) {
|
|
17931
18264
|
return `#${[r2, g2, b2].map((value) => Math.round(value).toString(16).padStart(2, "0")).join("")}`.toUpperCase();
|
|
17932
18265
|
}
|
|
17933
|
-
function
|
|
18266
|
+
function mix2(color, background, colorWeight) {
|
|
17934
18267
|
const values = [1, 3, 5].map((offset) => channel2(color, offset) * colorWeight + channel2(background, offset) * (1 - colorWeight));
|
|
17935
18268
|
return toHex(values[0], values[1], values[2]);
|
|
17936
18269
|
}
|
|
@@ -17941,7 +18274,7 @@ function relativeLuminance2(color) {
|
|
|
17941
18274
|
});
|
|
17942
18275
|
return 0.2126 * linear[0] + 0.7152 * linear[1] + 0.0722 * linear[2];
|
|
17943
18276
|
}
|
|
17944
|
-
function
|
|
18277
|
+
function contrastRatio3(a2, b2) {
|
|
17945
18278
|
const la2 = relativeLuminance2(a2);
|
|
17946
18279
|
const lb = relativeLuminance2(b2);
|
|
17947
18280
|
return (Math.max(la2, lb) + 0.05) / (Math.min(la2, lb) + 0.05);
|
|
@@ -17951,19 +18284,19 @@ function lstar(color) {
|
|
|
17951
18284
|
return y2 <= 8856e-6 ? y2 * 903.3 : 116 * Math.cbrt(y2) - 16;
|
|
17952
18285
|
}
|
|
17953
18286
|
function deriveAccentSurface(accent, surface, weight) {
|
|
17954
|
-
const tint =
|
|
17955
|
-
if (
|
|
18287
|
+
const tint = mix2(accent, surface, weight);
|
|
18288
|
+
if (contrastRatio3(tint, surface) >= ACCENT_SURFACE_MIN_DELTA) return tint;
|
|
17956
18289
|
const away = relativeLuminance2(surface) < 0.5 ? "#FFFFFF" : "#000000";
|
|
17957
18290
|
for (let w2 = 0.02; w2 <= 0.5; w2 += 0.02) {
|
|
17958
|
-
const candidate =
|
|
17959
|
-
if (
|
|
18291
|
+
const candidate = mix2(away, surface, w2);
|
|
18292
|
+
if (contrastRatio3(candidate, surface) >= ACCENT_SURFACE_MIN_DELTA) return candidate;
|
|
17960
18293
|
}
|
|
17961
18294
|
return tint;
|
|
17962
18295
|
}
|
|
17963
18296
|
function deriveSecondaryAccent(primary) {
|
|
17964
|
-
const shade2 =
|
|
18297
|
+
const shade2 = mix2(primary, "#000000", SECONDARY_SHADE_WEIGHT);
|
|
17965
18298
|
if (lstar(shade2) >= SECONDARY_MIN_LSTAR) return shade2;
|
|
17966
|
-
return
|
|
18299
|
+
return mix2(primary, "#FFFFFF", SECONDARY_SHADE_WEIGHT);
|
|
17967
18300
|
}
|
|
17968
18301
|
function textOn(color) {
|
|
17969
18302
|
const luminance2 = relativeLuminance2(color);
|
|
@@ -17973,42 +18306,42 @@ function textOn(color) {
|
|
|
17973
18306
|
}
|
|
17974
18307
|
function tuneDarkAccent(brand, darkSurface, lightSurface) {
|
|
17975
18308
|
const kitInherentlyDark = lstar(lightSurface) < 50;
|
|
17976
|
-
if (kitInherentlyDark &&
|
|
18309
|
+
if (kitInherentlyDark && contrastRatio3(brand, darkSurface) >= DARK_ARM_TARGET_CONTRAST && lstar(brand) <= DARK_ARM_LSTAR_CAP) {
|
|
17977
18310
|
return brand;
|
|
17978
18311
|
}
|
|
17979
18312
|
let lift = DARK_ARM_MIN_LIFT;
|
|
17980
|
-
let candidate =
|
|
17981
|
-
while (
|
|
18313
|
+
let candidate = mix2(brand, "#FFFFFF", 1 - lift);
|
|
18314
|
+
while (contrastRatio3(candidate, darkSurface) < DARK_ARM_TARGET_CONTRAST && lift < 0.6) {
|
|
17982
18315
|
lift += 0.04;
|
|
17983
|
-
candidate =
|
|
18316
|
+
candidate = mix2(brand, "#FFFFFF", 1 - lift);
|
|
17984
18317
|
}
|
|
17985
18318
|
while (lstar(candidate) > DARK_ARM_LSTAR_CAP) {
|
|
17986
|
-
const darker =
|
|
17987
|
-
if (
|
|
18319
|
+
const darker = mix2(candidate, "#000000", 0.94);
|
|
18320
|
+
if (contrastRatio3(darker, darkSurface) < DARK_ARM_FLOOR_CONTRAST) break;
|
|
17988
18321
|
candidate = darker;
|
|
17989
18322
|
}
|
|
17990
18323
|
return candidate;
|
|
17991
18324
|
}
|
|
17992
18325
|
function textOnArm(accent) {
|
|
17993
|
-
return
|
|
18326
|
+
return contrastRatio3("#FFFFFF", accent) >= 4.5 ? "#FFFFFF" : textOn(accent);
|
|
17994
18327
|
}
|
|
17995
18328
|
function tuneHighContrastAccent(brand, surface) {
|
|
17996
18329
|
const towards = relativeLuminance2(surface) < 0.5 ? "#FFFFFF" : "#000000";
|
|
17997
18330
|
let candidate = brand;
|
|
17998
|
-
for (let lift = 0; lift <= 0.9 &&
|
|
17999
|
-
candidate =
|
|
18331
|
+
for (let lift = 0; lift <= 0.9 && contrastRatio3(candidate, surface) < HIGH_CONTRAST_TARGET; lift += 0.04) {
|
|
18332
|
+
candidate = mix2(brand, towards, 1 - lift);
|
|
18000
18333
|
}
|
|
18001
18334
|
return candidate;
|
|
18002
18335
|
}
|
|
18003
18336
|
function deriveAccentText(accent, surfaces) {
|
|
18004
18337
|
const all = (typeof surfaces === "string" ? [surfaces] : [...surfaces]).map((s2) => s2.slice(0, 7));
|
|
18005
18338
|
const page = all[0];
|
|
18006
|
-
const worst = (color) => Math.min(...all.map((s2) =>
|
|
18007
|
-
const opaque = accent.length === 9 ?
|
|
18339
|
+
const worst = (color) => Math.min(...all.map((s2) => contrastRatio3(color, s2)));
|
|
18340
|
+
const opaque = accent.length === 9 ? mix2(accent.slice(0, 7), page, channel2(accent, 7) / 255) : accent;
|
|
18008
18341
|
if (worst(opaque) >= ACCENT_TEXT_MIN_CONTRAST) return opaque;
|
|
18009
18342
|
const pole = worst("#FFFFFF") >= worst("#000000") ? "#FFFFFF" : "#000000";
|
|
18010
18343
|
for (let step = 1; step <= 100; step++) {
|
|
18011
|
-
const candidate =
|
|
18344
|
+
const candidate = mix2(pole, opaque, step / 100);
|
|
18012
18345
|
if (worst(candidate) >= ACCENT_TEXT_MIN_CONTRAST) return candidate;
|
|
18013
18346
|
}
|
|
18014
18347
|
if (all.length > 1) {
|
|
@@ -18352,10 +18685,10 @@ function paintedOver(fg, bg) {
|
|
|
18352
18685
|
function sameHueForContrast(fg, bg, target = AA_TEXT) {
|
|
18353
18686
|
const base = fg.slice(0, 7);
|
|
18354
18687
|
const opaqueBg = bg.slice(0, 7);
|
|
18355
|
-
const pole =
|
|
18688
|
+
const pole = contrastRatio2("#000000", opaqueBg) >= contrastRatio2("#FFFFFF", opaqueBg) ? "#000000" : "#FFFFFF";
|
|
18356
18689
|
for (let step = 0; step <= 100; step++) {
|
|
18357
18690
|
const candidate = mixHex(base, pole, 1 - step / 100);
|
|
18358
|
-
if (
|
|
18691
|
+
if (contrastRatio2(candidate, opaqueBg) >= target) return candidate;
|
|
18359
18692
|
}
|
|
18360
18693
|
return void 0;
|
|
18361
18694
|
}
|
|
@@ -18377,7 +18710,7 @@ function contrastFindings(colors) {
|
|
|
18377
18710
|
const painted2 = paintedOver(fg, bg);
|
|
18378
18711
|
if (!painted2) continue;
|
|
18379
18712
|
const opaqueBg = bg.slice(0, 7);
|
|
18380
|
-
const ratio =
|
|
18713
|
+
const ratio = contrastRatio2(painted2, opaqueBg);
|
|
18381
18714
|
if (ratio >= AA_TEXT) continue;
|
|
18382
18715
|
const key3 = `${fgName}|${pair.bg}|${fg}|${bg}`;
|
|
18383
18716
|
const same3 = findings.get(key3);
|
|
@@ -18385,10 +18718,10 @@ function contrastFindings(colors) {
|
|
|
18385
18718
|
same3.schemes.push(scheme);
|
|
18386
18719
|
continue;
|
|
18387
18720
|
}
|
|
18388
|
-
const darker =
|
|
18721
|
+
const darker = contrastRatio2("#000000", opaqueBg) >= contrastRatio2("#FFFFFF", opaqueBg);
|
|
18389
18722
|
const ink = darker ? "#000000" : "#FFFFFF";
|
|
18390
|
-
const suggestion = pair.suggest === "same-hue" ? sameHueForContrast(painted2, opaqueBg) : pair.suggest === "ink" &&
|
|
18391
|
-
const fix = !suggestion ? ` Pick a ${fgName} that clears ${AA_TEXT}:1 against ${pair.bg}.` : pair.suggest === "same-hue" ? ` A ${darker ? "darker" : "lighter"} ${fgName} of the same hue that clears it is ${suggestion} (${
|
|
18723
|
+
const suggestion = pair.suggest === "same-hue" ? sameHueForContrast(painted2, opaqueBg) : pair.suggest === "ink" && contrastRatio2(ink, opaqueBg) >= AA_TEXT ? ink : void 0;
|
|
18724
|
+
const fix = !suggestion ? ` Pick a ${fgName} that clears ${AA_TEXT}:1 against ${pair.bg}.` : pair.suggest === "same-hue" ? ` A ${darker ? "darker" : "lighter"} ${fgName} of the same hue that clears it is ${suggestion} (${contrastRatio2(suggestion, opaqueBg).toFixed(2)}:1).` : ` ${suggestion} clears it (${contrastRatio2(suggestion, opaqueBg).toFixed(2)}:1).`;
|
|
18392
18725
|
findings.set(key3, {
|
|
18393
18726
|
key: key3,
|
|
18394
18727
|
schemes: [scheme],
|
|
@@ -18405,7 +18738,7 @@ function sameHueClearingAll(fg, bgs, target = AA_TEXT) {
|
|
|
18405
18738
|
for (let step = 0; step <= 100; step++) {
|
|
18406
18739
|
for (const pole of poles) {
|
|
18407
18740
|
const candidate = mixHex(base, pole, 1 - step / 100);
|
|
18408
|
-
if (bgs.every((bg) =>
|
|
18741
|
+
if (bgs.every((bg) => contrastRatio2(candidate, bg) >= target)) return candidate;
|
|
18409
18742
|
}
|
|
18410
18743
|
}
|
|
18411
18744
|
return void 0;
|
|
@@ -18432,8 +18765,8 @@ function accentOnSurfacesFor(fgName, role, colors, declared, findings) {
|
|
|
18432
18765
|
const page = pageRaw && paintedOver(fg, pageRaw) ? pageRaw.slice(0, 7) : void 0;
|
|
18433
18766
|
const opaqueBg = bg.slice(0, 7);
|
|
18434
18767
|
if (page === opaqueBg) continue;
|
|
18435
|
-
if (page &&
|
|
18436
|
-
const ratio =
|
|
18768
|
+
if (page && contrastRatio2(paintedOver(fg, pageRaw), page) < AA_TEXT) continue;
|
|
18769
|
+
const ratio = contrastRatio2(painted2, opaqueBg);
|
|
18437
18770
|
if (ratio >= AA_TEXT) continue;
|
|
18438
18771
|
const key3 = `${fgName}|${surface}|${fg}|${bg}|${page ?? ""}`;
|
|
18439
18772
|
const same3 = findings.get(key3);
|
|
@@ -18442,9 +18775,9 @@ function accentOnSurfacesFor(fgName, role, colors, declared, findings) {
|
|
|
18442
18775
|
continue;
|
|
18443
18776
|
}
|
|
18444
18777
|
const opposite = page !== void 0 && onLightSide(page) !== onLightSide(opaqueBg);
|
|
18445
|
-
const noSingle = page !== void 0 && opposite &&
|
|
18778
|
+
const noSingle = page !== void 0 && opposite && contrastRatio2(page, opaqueBg) < AA_TEXT * AA_TEXT;
|
|
18446
18779
|
const suggestion = noSingle ? void 0 : sameHueClearingAll(painted2, page ? [page, opaqueBg] : [opaqueBg]);
|
|
18447
|
-
const measured = (c2) => page ? `${
|
|
18780
|
+
const measured = (c2) => page ? `${contrastRatio2(c2, opaqueBg).toFixed(2)}:1 on ${surface}, ${contrastRatio2(c2, page).toFixed(2)}:1 on surfacePrimary` : `${contrastRatio2(c2, opaqueBg).toFixed(2)}:1`;
|
|
18448
18781
|
const restructure = ` Move ${surface} to the page's side of mid-grey (a ${page && onLightSide(page) ? "light" : "dark"} ${surface} on this page), or scope an explicit accent for that section with \`modifiers.theme\` (e.g. { "colors": { "accentText": "#RRGGBB" } } on the card).`;
|
|
18449
18782
|
const fix = noSingle ? ` surfacePrimary (${page}) and ${surface} (${opaqueBg}) sit on opposite sides of mid-grey, so no single accent text colour can clear ${AA_TEXT}:1 on both.${restructure}` : suggestion ? ` A same-hue ${fgName} that clears it${page ? " and the page" : ""} is ${suggestion} (${measured(suggestion)}).` + (opposite ? ` The page and ${surface} sit on opposite sides of mid-grey, so only a narrow mid-tone clears both.${restructure}` : "") : ` No ${fgName} of this hue clears ${AA_TEXT}:1 on ${surface}${page ? " and the page" : ""}.` + (opposite ? restructure : "");
|
|
18450
18783
|
findings.set(key3, {
|
|
@@ -18487,7 +18820,7 @@ var init_token_lint = __esm({
|
|
|
18487
18820
|
const [ca2, cb] = [channels(a2), channels(b2)];
|
|
18488
18821
|
return toHex2(ca2.map((c2, i2) => c2 * w2 + cb[i2] * (1 - w2)));
|
|
18489
18822
|
};
|
|
18490
|
-
onLightSide = (hex2) =>
|
|
18823
|
+
onLightSide = (hex2) => contrastRatio2("#000000", hex2) >= contrastRatio2("#FFFFFF", hex2);
|
|
18491
18824
|
}
|
|
18492
18825
|
});
|
|
18493
18826
|
|
|
@@ -19085,261 +19418,6 @@ var init_app_icon = __esm({
|
|
|
19085
19418
|
}
|
|
19086
19419
|
});
|
|
19087
19420
|
|
|
19088
|
-
// ../app-icons/pixels.ts
|
|
19089
|
-
var pixels_exports = {};
|
|
19090
|
-
__export(pixels_exports, {
|
|
19091
|
-
LETTERBOX_ERROR_FRACTION: () => LETTERBOX_ERROR_FRACTION,
|
|
19092
|
-
LETTERBOX_WARN_FRACTION: () => LETTERBOX_WARN_FRACTION,
|
|
19093
|
-
NORMALIZE_FIT_FRACTION: () => NORMALIZE_FIT_FRACTION,
|
|
19094
|
-
PIXEL_TOOLCHAIN_HINT: () => PIXEL_TOOLCHAIN_HINT,
|
|
19095
|
-
PixelToolchainUnavailable: () => PixelToolchainUnavailable,
|
|
19096
|
-
appStoreIconPixelFindings: () => appStoreIconPixelFindings,
|
|
19097
|
-
derivePlayListingIcon: () => derivePlayListingIcon,
|
|
19098
|
-
inspectIconPixels: () => inspectIconPixels,
|
|
19099
|
-
normalizeSourceIcon: () => normalizeSourceIcon,
|
|
19100
|
-
pixelToolchainAvailable: () => pixelToolchainAvailable,
|
|
19101
|
-
pixelToolchainProblem: () => pixelToolchainProblem,
|
|
19102
|
-
renderGlyphTile: () => renderGlyphTile
|
|
19103
|
-
});
|
|
19104
|
-
function isNotInstalled(e2) {
|
|
19105
|
-
const code = e2?.code;
|
|
19106
|
-
return code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND";
|
|
19107
|
-
}
|
|
19108
|
-
function messageOf(e2) {
|
|
19109
|
-
return e2 instanceof Error ? e2.message : String(e2);
|
|
19110
|
-
}
|
|
19111
|
-
async function loadSharp() {
|
|
19112
|
-
if (cachedSharp) return cachedSharp;
|
|
19113
|
-
const failures = [];
|
|
19114
|
-
let presentButBroken = false;
|
|
19115
|
-
try {
|
|
19116
|
-
const { createRequire: createRequire4 } = await import("node:module");
|
|
19117
|
-
cachedSharp = createRequire4(import.meta.url)("sharp");
|
|
19118
|
-
lastProblem = null;
|
|
19119
|
-
return cachedSharp;
|
|
19120
|
-
} catch (e2) {
|
|
19121
|
-
presentButBroken ||= !isNotInstalled(e2);
|
|
19122
|
-
failures.push(`require: ${messageOf(e2)}`);
|
|
19123
|
-
}
|
|
19124
|
-
try {
|
|
19125
|
-
cachedSharp = (await import("sharp")).default;
|
|
19126
|
-
lastProblem = null;
|
|
19127
|
-
return cachedSharp;
|
|
19128
|
-
} catch (e2) {
|
|
19129
|
-
presentButBroken ||= !isNotInstalled(e2);
|
|
19130
|
-
failures.push(`import: ${messageOf(e2)}`);
|
|
19131
|
-
}
|
|
19132
|
-
lastProblem = presentButBroken ? `the image toolchain (sharp) is installed but could not be loaded \u2014 ${failures.join("; ")}` : PIXEL_TOOLCHAIN_HINT;
|
|
19133
|
-
return null;
|
|
19134
|
-
}
|
|
19135
|
-
async function pixelToolchainAvailable() {
|
|
19136
|
-
return await loadSharp() !== null;
|
|
19137
|
-
}
|
|
19138
|
-
async function pixelToolchainProblem() {
|
|
19139
|
-
return await loadSharp() === null ? lastProblem ?? PIXEL_TOOLCHAIN_HINT : null;
|
|
19140
|
-
}
|
|
19141
|
-
async function sharpOrThrow() {
|
|
19142
|
-
const s2 = await loadSharp();
|
|
19143
|
-
if (!s2) throw new PixelToolchainUnavailable(lastProblem ?? PIXEL_TOOLCHAIN_HINT);
|
|
19144
|
-
return s2;
|
|
19145
|
-
}
|
|
19146
|
-
async function inspectIconPixels(png) {
|
|
19147
|
-
const sharp = await sharpOrThrow();
|
|
19148
|
-
const { data, info: info4 } = await sharp(png).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
19149
|
-
const { width, height, channels: channels3 } = info4;
|
|
19150
|
-
if (channels3 !== 4) throw new Error(`app-icons: expected RGBA after ensureAlpha, got ${channels3} channels`);
|
|
19151
|
-
let minAlpha = 255;
|
|
19152
|
-
let transparent = 0;
|
|
19153
|
-
for (let i2 = 3; i2 < data.length; i2 += 4) {
|
|
19154
|
-
const a2 = data[i2];
|
|
19155
|
-
if (a2 < minAlpha) minAlpha = a2;
|
|
19156
|
-
if (a2 <= ALPHA_OPAQUE) transparent++;
|
|
19157
|
-
}
|
|
19158
|
-
const probe = Math.max(1, Math.round(Math.min(width, height) * CORNER_PROBE));
|
|
19159
|
-
let minCornerAlpha = 255;
|
|
19160
|
-
for (const [x0, y0] of [
|
|
19161
|
-
[0, 0],
|
|
19162
|
-
[width - probe, 0],
|
|
19163
|
-
[0, height - probe],
|
|
19164
|
-
[width - probe, height - probe]
|
|
19165
|
-
]) {
|
|
19166
|
-
for (let y2 = y0; y2 < y0 + probe; y2++) {
|
|
19167
|
-
for (let x2 = x0; x2 < x0 + probe; x2++) {
|
|
19168
|
-
const a2 = data[(y2 * width + x2) * 4 + 3];
|
|
19169
|
-
if (a2 < minCornerAlpha) minCornerAlpha = a2;
|
|
19170
|
-
}
|
|
19171
|
-
}
|
|
19172
|
-
}
|
|
19173
|
-
const inset = Math.round(Math.min(width, height) * INTERIOR_INSET);
|
|
19174
|
-
let interiorMinAlpha = 255;
|
|
19175
|
-
for (let y2 = inset; y2 < height - inset; y2++) {
|
|
19176
|
-
for (let x2 = inset; x2 < width - inset; x2++) {
|
|
19177
|
-
const a2 = data[(y2 * width + x2) * 4 + 3];
|
|
19178
|
-
if (a2 < interiorMinAlpha) interiorMinAlpha = a2;
|
|
19179
|
-
}
|
|
19180
|
-
}
|
|
19181
|
-
return {
|
|
19182
|
-
width,
|
|
19183
|
-
height,
|
|
19184
|
-
minAlpha,
|
|
19185
|
-
transparentFraction: transparent / (width * height),
|
|
19186
|
-
minCornerAlpha,
|
|
19187
|
-
interiorMinAlpha,
|
|
19188
|
-
// `minAlpha <= ALPHA_OPAQUE` IS "has transparency", and the caller has just computed
|
|
19189
|
-
// it — contentBox used to re-derive it with a full extra sweep of the raster.
|
|
19190
|
-
contentBox: contentBox(data, width, height, minAlpha <= ALPHA_OPAQUE)
|
|
19191
|
-
};
|
|
19192
|
-
}
|
|
19193
|
-
function contentBox(data, width, height, hasTransparency) {
|
|
19194
|
-
const at2 = (x2, y2) => (y2 * width + x2) * 4;
|
|
19195
|
-
const bg = [data[at2(0, 0)], data[at2(0, 0) + 1], data[at2(0, 0) + 2]];
|
|
19196
|
-
const isInk = (x2, y2) => {
|
|
19197
|
-
const i2 = at2(x2, y2);
|
|
19198
|
-
if (hasTransparency) return data[i2 + 3] > ALPHA_OPAQUE;
|
|
19199
|
-
return Math.abs(data[i2] - bg[0]) > INK_TOLERANCE || Math.abs(data[i2 + 1] - bg[1]) > INK_TOLERANCE || Math.abs(data[i2 + 2] - bg[2]) > INK_TOLERANCE;
|
|
19200
|
-
};
|
|
19201
|
-
let minX = width, minY = height, maxX = -1, maxY = -1;
|
|
19202
|
-
for (let y2 = 0; y2 < height; y2++) {
|
|
19203
|
-
for (let x2 = 0; x2 < width; x2++) {
|
|
19204
|
-
if (!isInk(x2, y2)) continue;
|
|
19205
|
-
if (x2 < minX) minX = x2;
|
|
19206
|
-
if (x2 > maxX) maxX = x2;
|
|
19207
|
-
if (y2 < minY) minY = y2;
|
|
19208
|
-
if (y2 > maxY) maxY = y2;
|
|
19209
|
-
}
|
|
19210
|
-
}
|
|
19211
|
-
if (maxX < 0) return null;
|
|
19212
|
-
return {
|
|
19213
|
-
widthFraction: (maxX - minX + 1) / width,
|
|
19214
|
-
heightFraction: (maxY - minY + 1) / height
|
|
19215
|
-
};
|
|
19216
|
-
}
|
|
19217
|
-
function appStoreIconPixelFindings(f2) {
|
|
19218
|
-
const out2 = [];
|
|
19219
|
-
const preMasked = f2.interiorMinAlpha > ALPHA_OPAQUE && f2.minCornerAlpha <= ALPHA_OPAQUE && f2.transparentFraction <= PRE_MASK_MAX_TRANSPARENT_FRACTION;
|
|
19220
|
-
if (preMasked) {
|
|
19221
|
-
out2.push({
|
|
19222
|
-
level: "error",
|
|
19223
|
-
message: "App icon looks pre-masked: its corners are transparent while the middle is opaque. iOS and Play both apply their own corner mask, so rounded artwork is rounded twice and looks visibly wrong on device \u2014 and the transparency itself is an App Store rejection (ITMS-90717 / ITMS-90647). Ship a full-bleed square with 90-degree corners and no inset."
|
|
19224
|
-
});
|
|
19225
|
-
} else if (f2.minAlpha <= ALPHA_OPAQUE) {
|
|
19226
|
-
out2.push({
|
|
19227
|
-
level: "error",
|
|
19228
|
-
message: `App icon has transparent pixels (${(f2.transparentFraction * 100).toFixed(1)}% of the canvas, lowest alpha ${f2.minAlpha}). An App Store icon may carry an alpha channel but no transparent regions \u2014 Apple rejects this as ITMS-90717 / ITMS-90647. Flatten it onto an opaque background (\`himi icon set <file>\` does this for you).`
|
|
19229
|
-
});
|
|
19230
|
-
}
|
|
19231
|
-
if (f2.contentBox === null) {
|
|
19232
|
-
out2.push({
|
|
19233
|
-
level: "error",
|
|
19234
|
-
message: "App icon is a single flat colour with no distinguishable artwork \u2014 the mark is not visible in it. Supply art that contrasts with the background, or use `himi icon generate` for a glyph tile."
|
|
19235
|
-
});
|
|
19236
|
-
return out2;
|
|
19237
|
-
}
|
|
19238
|
-
const shorter = Math.min(f2.contentBox.widthFraction, f2.contentBox.heightFraction);
|
|
19239
|
-
if (shorter < LETTERBOX_ERROR_FRACTION) {
|
|
19240
|
-
out2.push({
|
|
19241
|
-
level: "error",
|
|
19242
|
-
message: `App icon artwork fills only ${(shorter * 100).toFixed(0)}% of the canvas on its shorter side, so it reads as a speck on a home screen. This is what a wide wordmark centred in a square looks like \u2014 crop to the mark, or use a monogram/glyph instead of the wordmark.`
|
|
19243
|
-
});
|
|
19244
|
-
} else if (shorter < LETTERBOX_WARN_FRACTION) {
|
|
19245
|
-
out2.push({
|
|
19246
|
-
level: "warn",
|
|
19247
|
-
message: `App icon artwork fills ${(shorter * 100).toFixed(0)}% of the canvas on its shorter side \u2014 it will read as a thin strip at home-screen size. Consider cropping to the mark.`
|
|
19248
|
-
});
|
|
19249
|
-
}
|
|
19250
|
-
return out2;
|
|
19251
|
-
}
|
|
19252
|
-
function luminance([r2, g2, b2]) {
|
|
19253
|
-
const lin = [r2, g2, b2].map((v2) => {
|
|
19254
|
-
const c2 = v2 / 255;
|
|
19255
|
-
return c2 <= 0.04045 ? c2 / 12.92 : ((c2 + 0.055) / 1.055) ** 2.4;
|
|
19256
|
-
});
|
|
19257
|
-
return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2];
|
|
19258
|
-
}
|
|
19259
|
-
function contrastRatio3(a2, b2) {
|
|
19260
|
-
const [hi2, lo2] = [luminance(a2), luminance(b2)].sort((x2, y2) => y2 - x2);
|
|
19261
|
-
return (hi2 + 0.05) / (lo2 + 0.05);
|
|
19262
|
-
}
|
|
19263
|
-
async function contrastingBackdrop(mark, requested) {
|
|
19264
|
-
const sharp = await sharpOrThrow();
|
|
19265
|
-
const { dominant } = await sharp(mark).stats();
|
|
19266
|
-
const ink = [dominant.r, dominant.g, dominant.b];
|
|
19267
|
-
const want = hexToRgb(requested);
|
|
19268
|
-
if (!want || contrastRatio3(ink, want) >= MIN_BACKDROP_CONTRAST) return requested;
|
|
19269
|
-
const towardsWhite = luminance(ink) < 0.5;
|
|
19270
|
-
for (const amount of [0.35, 0.55, 0.75, 0.9]) {
|
|
19271
|
-
const candidate = mix2(want, towardsWhite ? [255, 255, 255] : [0, 0, 0], amount);
|
|
19272
|
-
if (contrastRatio3(ink, candidate) >= MIN_BACKDROP_CONTRAST) return rgbToHex(candidate);
|
|
19273
|
-
}
|
|
19274
|
-
return towardsWhite ? "#FFFFFF" : "#000000";
|
|
19275
|
-
}
|
|
19276
|
-
function hexToRgb(hex2) {
|
|
19277
|
-
const m2 = /^#([0-9a-fA-F]{6})$/.exec(hex2);
|
|
19278
|
-
if (!m2) return null;
|
|
19279
|
-
const n2 = parseInt(m2[1], 16);
|
|
19280
|
-
return [n2 >> 16 & 255, n2 >> 8 & 255, n2 & 255];
|
|
19281
|
-
}
|
|
19282
|
-
function mix2(a2, b2, t2) {
|
|
19283
|
-
return [0, 1, 2].map((i2) => Math.round(a2[i2] + (b2[i2] - a2[i2]) * t2));
|
|
19284
|
-
}
|
|
19285
|
-
function rgbToHex([r2, g2, b2]) {
|
|
19286
|
-
return `#${[r2, g2, b2].map((v2) => v2.toString(16).padStart(2, "0")).join("")}`.toUpperCase();
|
|
19287
|
-
}
|
|
19288
|
-
async function normalizeSourceIcon(input, opts) {
|
|
19289
|
-
const sharp = await sharpOrThrow();
|
|
19290
|
-
const size = opts.size ?? 1024;
|
|
19291
|
-
const fit2 = opts.fit ?? NORMALIZE_FIT_FRACTION;
|
|
19292
|
-
const inner = Math.max(1, Math.round(size * fit2));
|
|
19293
|
-
const pad3 = Math.round((size - inner) / 2);
|
|
19294
|
-
let trimmed;
|
|
19295
|
-
try {
|
|
19296
|
-
trimmed = await sharp(input).ensureAlpha().trim().png().toBuffer();
|
|
19297
|
-
} catch {
|
|
19298
|
-
trimmed = await sharp(input).ensureAlpha().png().toBuffer();
|
|
19299
|
-
}
|
|
19300
|
-
const mark = await sharp(trimmed).resize(inner, inner, { fit: "contain", background: { r: 0, g: 0, b: 0, alpha: 0 } }).png().toBuffer();
|
|
19301
|
-
const background = await contrastingBackdrop(mark, opts.background);
|
|
19302
|
-
return sharp({
|
|
19303
|
-
create: {
|
|
19304
|
-
width: size,
|
|
19305
|
-
height: size,
|
|
19306
|
-
channels: 4,
|
|
19307
|
-
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
|
19308
|
-
}
|
|
19309
|
-
}).composite([{ input: mark, top: pad3, left: pad3 }]).flatten({ background }).removeAlpha().png({ palette: false }).toBuffer();
|
|
19310
|
-
}
|
|
19311
|
-
async function derivePlayListingIcon(master, size = 512) {
|
|
19312
|
-
const sharp = await sharpOrThrow();
|
|
19313
|
-
return sharp(master).resize(size, size).ensureAlpha().png({ palette: false }).toBuffer();
|
|
19314
|
-
}
|
|
19315
|
-
async function renderGlyphTile(svg, background, size = 1024) {
|
|
19316
|
-
const sharp = await sharpOrThrow();
|
|
19317
|
-
return sharp(Buffer.from(svg)).resize(size, size).flatten({ background }).removeAlpha().png({ palette: false }).toBuffer();
|
|
19318
|
-
}
|
|
19319
|
-
var cachedSharp, lastProblem, PIXEL_TOOLCHAIN_HINT, PixelToolchainUnavailable, ALPHA_OPAQUE, CORNER_PROBE, INTERIOR_INSET, INK_TOLERANCE, PRE_MASK_MAX_TRANSPARENT_FRACTION, LETTERBOX_WARN_FRACTION, LETTERBOX_ERROR_FRACTION, NORMALIZE_FIT_FRACTION, MIN_BACKDROP_CONTRAST;
|
|
19320
|
-
var init_pixels = __esm({
|
|
19321
|
-
"../app-icons/pixels.ts"() {
|
|
19322
|
-
cachedSharp = null;
|
|
19323
|
-
lastProblem = null;
|
|
19324
|
-
PIXEL_TOOLCHAIN_HINT = "the image toolchain (sharp) is not installed \u2014 run `npm i -g sharp` to enable transparency, pre-masked-corner and letterbox checks";
|
|
19325
|
-
PixelToolchainUnavailable = class extends Error {
|
|
19326
|
-
constructor(reason = PIXEL_TOOLCHAIN_HINT) {
|
|
19327
|
-
super(`app-icons: ${reason}`);
|
|
19328
|
-
this.name = "PixelToolchainUnavailable";
|
|
19329
|
-
}
|
|
19330
|
-
};
|
|
19331
|
-
ALPHA_OPAQUE = 250;
|
|
19332
|
-
CORNER_PROBE = 0.06;
|
|
19333
|
-
INTERIOR_INSET = 0.2;
|
|
19334
|
-
INK_TOLERANCE = 24;
|
|
19335
|
-
PRE_MASK_MAX_TRANSPARENT_FRACTION = 0.1;
|
|
19336
|
-
LETTERBOX_WARN_FRACTION = 0.35;
|
|
19337
|
-
LETTERBOX_ERROR_FRACTION = 0.2;
|
|
19338
|
-
NORMALIZE_FIT_FRACTION = 0.82;
|
|
19339
|
-
MIN_BACKDROP_CONTRAST = 1.5;
|
|
19340
|
-
}
|
|
19341
|
-
});
|
|
19342
|
-
|
|
19343
19421
|
// src/icon.ts
|
|
19344
19422
|
var icon_exports = {};
|
|
19345
19423
|
__export(icon_exports, {
|
|
@@ -19360,9 +19438,9 @@ __export(icon_exports, {
|
|
|
19360
19438
|
siteLogoAbsence: () => siteLogoAbsence,
|
|
19361
19439
|
summarize: () => summarize
|
|
19362
19440
|
});
|
|
19363
|
-
import { createHash as
|
|
19441
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
19364
19442
|
import { existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync21, statSync as statSync5, writeFileSync as writeFileSync8 } from "node:fs";
|
|
19365
|
-
import { basename as
|
|
19443
|
+
import { basename as basename8, dirname as dirname15, join as join21, resolve as resolve21, sep as sep7 } from "node:path";
|
|
19366
19444
|
function readManifest(dir) {
|
|
19367
19445
|
try {
|
|
19368
19446
|
return JSON.parse(readFileSync21(join21(dir, MANIFEST), "utf8"));
|
|
@@ -19449,7 +19527,7 @@ async function iconStatus(dir) {
|
|
|
19449
19527
|
...base,
|
|
19450
19528
|
templateIcon: templateIconMatch(png),
|
|
19451
19529
|
bytes: png.length,
|
|
19452
|
-
sha256:
|
|
19530
|
+
sha256: createHash9("sha256").update(png).digest("hex"),
|
|
19453
19531
|
header: pngHeader(png),
|
|
19454
19532
|
byteIssues
|
|
19455
19533
|
};
|
|
@@ -19537,7 +19615,7 @@ async function installIcon(dir, sourcePath, opts = {}) {
|
|
|
19537
19615
|
const issues = appStoreIconIssues(input);
|
|
19538
19616
|
if (issues.length) {
|
|
19539
19617
|
throw new Error(
|
|
19540
|
-
`himi icon: ${
|
|
19618
|
+
`himi icon: ${basename8(src)} ${issues.join("; ")}. Normalizing it needs the image toolchain \u2014 ${await pixelToolchainProblem() ?? PIXEL_TOOLCHAIN_HINT} \u2014 or supply an opaque 1024x1024 PNG. The existing icon was left alone.`
|
|
19541
19619
|
);
|
|
19542
19620
|
}
|
|
19543
19621
|
}
|
|
@@ -19843,17 +19921,17 @@ var init_plan_fonts = __esm({
|
|
|
19843
19921
|
});
|
|
19844
19922
|
|
|
19845
19923
|
// ../font-bake/face-source.ts
|
|
19846
|
-
import { createHash as
|
|
19924
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
19847
19925
|
import { existsSync as existsSync24, mkdirSync as mkdirSync11, readFileSync as readFileSync23, renameSync as renameSync2, rmSync as rmSync5, writeFileSync as writeFileSync9 } from "node:fs";
|
|
19848
19926
|
import { homedir as homedir3 } from "node:os";
|
|
19849
|
-
import { basename as
|
|
19927
|
+
import { basename as basename9, join as join24 } from "node:path";
|
|
19850
19928
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
19851
19929
|
function hasVendoredFloor() {
|
|
19852
19930
|
return existsSync24(VENDORED_DIR);
|
|
19853
19931
|
}
|
|
19854
19932
|
function faceSource(file2, sha2567) {
|
|
19855
|
-
const vendored = join24(VENDORED_DIR,
|
|
19856
|
-
if (existsSync24(vendored) &&
|
|
19933
|
+
const vendored = join24(VENDORED_DIR, basename9(file2));
|
|
19934
|
+
if (existsSync24(vendored) && createHash10("sha256").update(readFileSync23(vendored)).digest("hex") === sha2567) {
|
|
19857
19935
|
return vendored;
|
|
19858
19936
|
}
|
|
19859
19937
|
const cached3 = join24(CACHE_DIR, sha2567);
|
|
@@ -19987,7 +20065,7 @@ var init_face_source = __esm({
|
|
|
19987
20065
|
REPO_ROOT5 = fileURLToPath11(new URL("../..", import.meta.url));
|
|
19988
20066
|
VENDORED_DIR = process.env.HIMI_FONTS_VENDORED_DIR || join24(REPO_ROOT5, "stdlib", "fonts", "vendored", "wix-madefor");
|
|
19989
20067
|
CACHE_DIR = join24(process.env.XDG_CACHE_HOME || join24(homedir3(), ".cache"), "himi", "fonts");
|
|
19990
|
-
sha256Hex3 = (bytes2) =>
|
|
20068
|
+
sha256Hex3 = (bytes2) => createHash10("sha256").update(bytes2).digest("hex");
|
|
19991
20069
|
RAW = ["https://", "raw.", "githubuser", "content.com"].join("");
|
|
19992
20070
|
UPSTREAM_DIR = /^(ofl|apache|ufl)\/[a-z0-9_-]+$/;
|
|
19993
20071
|
FETCH_TIMEOUT_MS = 2e4;
|
|
@@ -21193,7 +21271,7 @@ __export(catalog_cache_exports, {
|
|
|
21193
21271
|
catalogCompatible: () => catalogCompatible,
|
|
21194
21272
|
catalogManifestDigest: () => catalogManifestDigest
|
|
21195
21273
|
});
|
|
21196
|
-
import { createHash as
|
|
21274
|
+
import { createHash as createHash11, randomUUID as randomUUID2 } from "node:crypto";
|
|
21197
21275
|
import {
|
|
21198
21276
|
existsSync as existsSync29,
|
|
21199
21277
|
mkdirSync as mkdirSync13,
|
|
@@ -21289,7 +21367,7 @@ var init_catalog_cache = __esm({
|
|
|
21289
21367
|
this.name = "CatalogError";
|
|
21290
21368
|
}
|
|
21291
21369
|
};
|
|
21292
|
-
hash = (b2) => `sha256-${
|
|
21370
|
+
hash = (b2) => `sha256-${createHash11("sha256").update(b2).digest("hex")}`;
|
|
21293
21371
|
CatalogCache = class {
|
|
21294
21372
|
root;
|
|
21295
21373
|
baseUrl;
|
|
@@ -21307,7 +21385,7 @@ var init_catalog_cache = __esm({
|
|
|
21307
21385
|
homedir4(),
|
|
21308
21386
|
".himi",
|
|
21309
21387
|
"authoring-cache",
|
|
21310
|
-
|
|
21388
|
+
createHash11("sha256").update(this.baseUrl).digest("hex").slice(0, 16)
|
|
21311
21389
|
)
|
|
21312
21390
|
);
|
|
21313
21391
|
this.cliVersion = opts.cliVersion;
|
|
@@ -23547,7 +23625,7 @@ var init_src2 = __esm({
|
|
|
23547
23625
|
|
|
23548
23626
|
// ../app-icons/plan.ts
|
|
23549
23627
|
import { existsSync as existsSync31, readFileSync as readFileSync31, readdirSync as readdirSync18 } from "node:fs";
|
|
23550
|
-
import { createHash as
|
|
23628
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
23551
23629
|
import { dirname as dirname19, join as join32, resolve as resolve26 } from "node:path";
|
|
23552
23630
|
function stripComments(src) {
|
|
23553
23631
|
let out2 = "";
|
|
@@ -23634,7 +23712,7 @@ function parseIconConfig(configTs) {
|
|
|
23634
23712
|
return out2;
|
|
23635
23713
|
}
|
|
23636
23714
|
function idHash(id) {
|
|
23637
|
-
return
|
|
23715
|
+
return createHash12("sha1").update(id).digest();
|
|
23638
23716
|
}
|
|
23639
23717
|
function deriveGlyph(id) {
|
|
23640
23718
|
const h2 = idHash(id);
|
|
@@ -23812,7 +23890,7 @@ function placeholderHashes() {
|
|
|
23812
23890
|
}
|
|
23813
23891
|
function fileSha256(path2) {
|
|
23814
23892
|
try {
|
|
23815
|
-
return
|
|
23893
|
+
return createHash12("sha256").update(readFileSync31(path2)).digest("hex");
|
|
23816
23894
|
} catch {
|
|
23817
23895
|
return null;
|
|
23818
23896
|
}
|
|
@@ -25518,7 +25596,7 @@ __export(progress_exports, {
|
|
|
25518
25596
|
writeFileAtomic: () => writeFileAtomic
|
|
25519
25597
|
});
|
|
25520
25598
|
import { spawn as spawn3 } from "node:child_process";
|
|
25521
|
-
import { createHash as
|
|
25599
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
25522
25600
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
25523
25601
|
import { appendFileSync, closeSync, existsSync as existsSync35, lstatSync as lstatSync8, mkdirSync as mkdirSync16, openSync, readdirSync as readdirSync21, readFileSync as readFileSync35, readSync, renameSync as renameSync5, rmSync as rmSync8, statSync as statSync8, writeFileSync as writeFileSync14 } from "node:fs";
|
|
25524
25602
|
import { isAbsolute as isAbsolute3, join as join36, relative as relative6, resolve as resolve28, sep as sep8 } from "node:path";
|
|
@@ -25604,7 +25682,7 @@ function isSymlink(file2) {
|
|
|
25604
25682
|
function archiveBytes(dir, bytes2) {
|
|
25605
25683
|
const ext = imageExtension(bytes2);
|
|
25606
25684
|
if (!ext) return null;
|
|
25607
|
-
const sha2567 =
|
|
25685
|
+
const sha2567 = createHash13("sha256").update(bytes2).digest("hex");
|
|
25608
25686
|
const rel = join36(HISTORY_DIR, `${sha2567}.${ext}`);
|
|
25609
25687
|
const dest = join36(dir, rel);
|
|
25610
25688
|
if (!realDirIn(dir, HISTORY_DIR)) throw new UnsafeHimiDirError(HISTORY_DIR);
|
|
@@ -25689,7 +25767,7 @@ function journalMilestone(dir, input) {
|
|
|
25689
25767
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
25690
25768
|
const step = MILESTONE_STEP[input.milestone];
|
|
25691
25769
|
const abs = input.image ? locateImage(dir, input.image) : null;
|
|
25692
|
-
const images = abs ? [{ sha256:
|
|
25770
|
+
const images = abs ? [{ sha256: createHash13("sha256").update(readFileSync35(abs)).digest("hex") }] : [];
|
|
25693
25771
|
let message = input.message;
|
|
25694
25772
|
if (input.unlessUnchanged) {
|
|
25695
25773
|
const latest = [...entries].reverse().find((e2) => isCliEntry(e2) && e2.milestone === input.milestone);
|
|
@@ -26608,7 +26686,7 @@ var init_claude_plugin = __esm({
|
|
|
26608
26686
|
});
|
|
26609
26687
|
|
|
26610
26688
|
// src/run-identity.ts
|
|
26611
|
-
import { createHash as
|
|
26689
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
26612
26690
|
import { realpathSync as realpathSync5 } from "node:fs";
|
|
26613
26691
|
import { resolve as resolve29 } from "node:path";
|
|
26614
26692
|
function runRootId(dir) {
|
|
@@ -26618,7 +26696,7 @@ function runRootId(dir) {
|
|
|
26618
26696
|
} catch {
|
|
26619
26697
|
real = resolve29(dir);
|
|
26620
26698
|
}
|
|
26621
|
-
return
|
|
26699
|
+
return createHash14("sha256").update(real).digest("hex");
|
|
26622
26700
|
}
|
|
26623
26701
|
function runIdentity(dir) {
|
|
26624
26702
|
return { pid: process.pid, root: runRootId(dir) };
|
|
@@ -26634,7 +26712,7 @@ var init_run_identity = __esm({
|
|
|
26634
26712
|
import { spawn as nodeSpawn } from "node:child_process";
|
|
26635
26713
|
import { closeSync as closeSync2, constants as fsc, existsSync as existsSync36, lstatSync as lstatSync9, mkdirSync as mkdirSync17, openSync as openSync2, readFileSync as readFileSync36, rmSync as rmSync9 } from "node:fs";
|
|
26636
26714
|
import { createServer as createServer2 } from "node:net";
|
|
26637
|
-
import { basename as
|
|
26715
|
+
import { basename as basename10, join as join37 } from "node:path";
|
|
26638
26716
|
function previewPortFor(appName2) {
|
|
26639
26717
|
let h2 = 2166136261;
|
|
26640
26718
|
for (let i2 = 0; i2 < appName2.length; i2++) {
|
|
@@ -26649,7 +26727,7 @@ function previewKey(manifestText, dir) {
|
|
|
26649
26727
|
if (typeof name === "string" && name) return name;
|
|
26650
26728
|
} catch {
|
|
26651
26729
|
}
|
|
26652
|
-
return
|
|
26730
|
+
return basename10(dir);
|
|
26653
26731
|
}
|
|
26654
26732
|
function previewPortForDir(dir) {
|
|
26655
26733
|
const p2 = join37(dir, "himalaya.content.json");
|
|
@@ -30799,7 +30877,7 @@ var init_wix_push_links = __esm({
|
|
|
30799
30877
|
});
|
|
30800
30878
|
|
|
30801
30879
|
// ../../core/dev-server/src/app-config.ts
|
|
30802
|
-
import { createHash as
|
|
30880
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
30803
30881
|
function deriveTelemetryConfig(app) {
|
|
30804
30882
|
const cfg = { enabled: true, samplingRate: 1 };
|
|
30805
30883
|
const prodTelemetry = app.environments?.prod?.telemetry;
|
|
@@ -30996,7 +31074,7 @@ function buildAppConfigDocument(req, meta, override, bundleCtx, devNetMocks) {
|
|
|
30996
31074
|
const locale = pickLocale(typeof acceptLanguage === "string" ? acceptLanguage : null);
|
|
30997
31075
|
const config = locale ? translate(JSON.parse(JSON.stringify(baseline)), locale) : baseline;
|
|
30998
31076
|
const body = JSON.stringify(config);
|
|
30999
|
-
const etag = `"${
|
|
31077
|
+
const etag = `"${createHash15("sha1").update(`${locale ?? "en"}:${body}`).digest("hex")}"`;
|
|
31000
31078
|
return { config, body, etag, locale };
|
|
31001
31079
|
}
|
|
31002
31080
|
function handleAppConfigRequest(req, res, meta, override, bundleCtx, devNetMocks) {
|
|
@@ -35540,7 +35618,7 @@ __export(wix_member_login_exports, {
|
|
|
35540
35618
|
webWixCall: () => webWixCall,
|
|
35541
35619
|
webWixStream: () => webWixStream
|
|
35542
35620
|
});
|
|
35543
|
-
import { createHash as
|
|
35621
|
+
import { createHash as createHash16, randomBytes as randomBytes3 } from "node:crypto";
|
|
35544
35622
|
function b64url(buf) {
|
|
35545
35623
|
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
35546
35624
|
}
|
|
@@ -35579,7 +35657,7 @@ function authCodeFrom(url) {
|
|
|
35579
35657
|
}
|
|
35580
35658
|
async function exchangeSessionToken(clientId, redirectUri, visitorToken, sessionToken) {
|
|
35581
35659
|
const verifier = b64url(randomBytes3(32));
|
|
35582
|
-
const challenge = b64url(
|
|
35660
|
+
const challenge = b64url(createHash16("sha256").update(verifier).digest());
|
|
35583
35661
|
const state = b64url(randomBytes3(8));
|
|
35584
35662
|
const rs2 = await postJson(
|
|
35585
35663
|
"/_api/redirects-api/v1/redirect-session",
|
|
@@ -36430,7 +36508,7 @@ var init_person_session_auth = __esm({
|
|
|
36430
36508
|
import { readFileSync as readFileSync45 } from "node:fs";
|
|
36431
36509
|
import { homedir as homedir6 } from "node:os";
|
|
36432
36510
|
import { join as pathJoin2 } from "node:path";
|
|
36433
|
-
import { createHash as
|
|
36511
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
36434
36512
|
function captureAccountSession(req, opts = {}) {
|
|
36435
36513
|
const env = opts.env ?? process.env;
|
|
36436
36514
|
const now = opts.now ?? Date.now();
|
|
@@ -36469,7 +36547,7 @@ async function accountPrincipal(cookie, fetchImpl = fetch) {
|
|
|
36469
36547
|
const identity = await resolveWixAccounts(cookie, fetchImpl);
|
|
36470
36548
|
if (!identity.ok) return { ok: false, reason: identity.reason };
|
|
36471
36549
|
const ids = identity.accounts.map((a2) => a2.accountId).sort().join("\n");
|
|
36472
|
-
return { ok: true, principal: `acct_${
|
|
36550
|
+
return { ok: true, principal: `acct_${createHash17("sha256").update(ids).digest("hex").slice(0, 32)}` };
|
|
36473
36551
|
}
|
|
36474
36552
|
function safeAccountReturn(raw, requestHost, requestProto = "http") {
|
|
36475
36553
|
if (typeof raw !== "string" || !raw) return "/";
|
|
@@ -36579,9 +36657,9 @@ var init_flag_assignments = __esm({
|
|
|
36579
36657
|
});
|
|
36580
36658
|
|
|
36581
36659
|
// ../../core/dev-server/src/images.ts
|
|
36582
|
-
import { createHash as
|
|
36660
|
+
import { createHash as createHash18 } from "node:crypto";
|
|
36583
36661
|
function svgFor(productId, title, sku) {
|
|
36584
|
-
const seedHex =
|
|
36662
|
+
const seedHex = createHash18("sha1").update(productId + ":" + title).digest("hex");
|
|
36585
36663
|
const h2 = (n2) => parseInt(seedHex.slice(n2, n2 + 2), 16);
|
|
36586
36664
|
const hue1 = h2(0) % 360;
|
|
36587
36665
|
const hue2 = (hue1 + 30 + h2(2) % 60) % 360;
|
|
@@ -36613,7 +36691,7 @@ function escapeXml(s2) {
|
|
|
36613
36691
|
return s2.replace(/[<>&"']/g, (c2) => ({ "<": "<", ">": ">", "&": "&", '"': """, "'": "'" })[c2] ?? c2);
|
|
36614
36692
|
}
|
|
36615
36693
|
function wixPhotoSvg(category, seed2) {
|
|
36616
|
-
const seedHex =
|
|
36694
|
+
const seedHex = createHash18("sha1").update(category + ":" + seed2).digest("hex");
|
|
36617
36695
|
const h2 = (n2) => parseInt(seedHex.slice(n2, n2 + 2), 16);
|
|
36618
36696
|
const palette2 = paletteForCategory(category, h2);
|
|
36619
36697
|
const glyph = glyphForCategory(category);
|
|
@@ -36738,7 +36816,7 @@ var init_stable_ids = __esm({
|
|
|
36738
36816
|
|
|
36739
36817
|
// ../../core/dev-server/src/preview.ts
|
|
36740
36818
|
import { spawn as spawn4 } from "node:child_process";
|
|
36741
|
-
import { createHash as
|
|
36819
|
+
import { createHash as createHash19 } from "node:crypto";
|
|
36742
36820
|
import { existsSync as existsSync44, createReadStream, statSync as statSync11, readFileSync as readFileSync46, renameSync as renameSync9, unlinkSync as unlinkSync3 } from "node:fs";
|
|
36743
36821
|
import { homedir as homedir7, tmpdir as tmpdir2 } from "node:os";
|
|
36744
36822
|
import { resolve as resolvePath, dirname as dirname27 } from "node:path";
|
|
@@ -36754,7 +36832,7 @@ function macosWinlistBin() {
|
|
|
36754
36832
|
}
|
|
36755
36833
|
function macosWinlistSourceHash() {
|
|
36756
36834
|
try {
|
|
36757
|
-
return
|
|
36835
|
+
return createHash19("sha1").update(readFileSync46(MACOS_WINLIST)).digest("hex").slice(0, 12);
|
|
36758
36836
|
} catch {
|
|
36759
36837
|
return "missing";
|
|
36760
36838
|
}
|
|
@@ -37610,9 +37688,9 @@ var init_preview2 = __esm({
|
|
|
37610
37688
|
});
|
|
37611
37689
|
|
|
37612
37690
|
// ../../core/dev-server/src/tier4-integrity.ts
|
|
37613
|
-
import { createHash as
|
|
37691
|
+
import { createHash as createHash20 } from "node:crypto";
|
|
37614
37692
|
function computeSri(bytes2) {
|
|
37615
|
-
const digest2 =
|
|
37693
|
+
const digest2 = createHash20("sha384").update(bytes2).digest("base64");
|
|
37616
37694
|
return `sha384-${digest2}`;
|
|
37617
37695
|
}
|
|
37618
37696
|
function parseManifestIntegrity(manifest) {
|
|
@@ -131370,7 +131448,8 @@ function renderDescriptorToHtml(payload, tokens2, scheme = "light", provider = n
|
|
|
131370
131448
|
...typeof width === "number" && Number.isFinite(width) && width > 0 ? { sizeClass: sizeClassFromWidth(width), containerWidth: width } : {},
|
|
131371
131449
|
...rtl ? { isRTL: true } : {},
|
|
131372
131450
|
...opts?.idiomContext ? { idiomContext: opts.idiomContext } : {},
|
|
131373
|
-
...opts?.debugUnknownComponents ? { debugUnknownComponents: true } : {}
|
|
131451
|
+
...opts?.debugUnknownComponents ? { debugUnknownComponents: true } : {},
|
|
131452
|
+
...opts?.assetBaseUrl ? { assetBaseUrl: opts.assetBaseUrl } : {}
|
|
131374
131453
|
});
|
|
131375
131454
|
const FOCUS_STYLE_MARKUP = `<style data-himalaya-focus-ring>${FOCUS_RING_CSS}</style>`;
|
|
131376
131455
|
const withFocusRing = (markup) => markup ? FOCUS_STYLE_MARKUP + markup : markup;
|
|
@@ -131791,7 +131870,7 @@ function composeStickyTree(payload, header, footer) {
|
|
|
131791
131870
|
if (footer) children.push(footer);
|
|
131792
131871
|
return { id: "screen", type: "ScreenChrome", children };
|
|
131793
131872
|
}
|
|
131794
|
-
async function renderDescriptorWeb(descriptor, tokens2, scheme, wantPng, services = null, width, isRTL, idiomContext) {
|
|
131873
|
+
async function renderDescriptorWeb(descriptor, tokens2, scheme, wantPng, services = null, width, isRTL, idiomContext, assetBaseUrl) {
|
|
131795
131874
|
const desc = descriptor;
|
|
131796
131875
|
const tooDeep = rawJsonDepthFinding(descriptor);
|
|
131797
131876
|
if (tooDeep) return { renderable: false, reason: `depth_budget_exceeded: ${tooDeep.message}` };
|
|
@@ -131832,7 +131911,7 @@ async function renderDescriptorWeb(descriptor, tokens2, scheme, wantPng, service
|
|
|
131832
131911
|
stickyHeader || stickyFooter ? { stickyHeader, stickyFooter } : void 0,
|
|
131833
131912
|
// #4497 — the agent fast loop is a dev tool: an unknown component type keeps its
|
|
131834
131913
|
// developer label here (a shipped web app renders nothing for it).
|
|
131835
|
-
{ ...isRTL ? { isRTL: true } : {}, ...idiomContext ? { idiomContext } : {}, debugUnknownComponents: true }
|
|
131914
|
+
{ ...isRTL ? { isRTL: true } : {}, ...idiomContext ? { idiomContext } : {}, ...assetBaseUrl ? { assetBaseUrl } : {}, debugUnknownComponents: true }
|
|
131836
131915
|
);
|
|
131837
131916
|
} catch (err) {
|
|
131838
131917
|
return {
|
|
@@ -132594,7 +132673,7 @@ __export(widgets_exports, {
|
|
|
132594
132673
|
viewWidgetId: () => viewWidgetId,
|
|
132595
132674
|
widgetRealm: () => widgetRealm
|
|
132596
132675
|
});
|
|
132597
|
-
import { createHash as
|
|
132676
|
+
import { createHash as createHash21 } from "node:crypto";
|
|
132598
132677
|
import { inspect } from "node:util";
|
|
132599
132678
|
async function widgetRealm() {
|
|
132600
132679
|
if (!realmPromise) {
|
|
@@ -132650,7 +132729,7 @@ function dropEntry(cache, key3) {
|
|
|
132650
132729
|
cache.bytes -= entry.bytes;
|
|
132651
132730
|
}
|
|
132652
132731
|
function produceCacheKey(bundleJs, timeoutMs, clock) {
|
|
132653
|
-
const digest2 =
|
|
132732
|
+
const digest2 = createHash21("sha256").update(bundleJs).digest("base64");
|
|
132654
132733
|
return `${timeoutMs}|${clock === void 0 ? "live" : Math.trunc(clock)}|${digest2}`;
|
|
132655
132734
|
}
|
|
132656
132735
|
function cachedProduce(evaluator, key3) {
|
|
@@ -133040,7 +133119,7 @@ function contentEtag(snapshot2) {
|
|
|
133040
133119
|
// Lever A — a timeline change must bump the etag (frame values/times are content).
|
|
133041
133120
|
frames: snapshot2.frames ?? null
|
|
133042
133121
|
});
|
|
133043
|
-
return "sha256-" +
|
|
133122
|
+
return "sha256-" + createHash21("sha256").update(canonical6).digest("base64");
|
|
133044
133123
|
}
|
|
133045
133124
|
async function buildWidgetSnapshot(bundleJs, widgetId, opts = {}) {
|
|
133046
133125
|
const { widgets } = await extractWidgets(bundleJs, opts);
|
|
@@ -133543,8 +133622,8 @@ var init_config2 = __esm({
|
|
|
133543
133622
|
import { createServer as createServer3 } from "node:http";
|
|
133544
133623
|
import { readFile, stat } from "node:fs/promises";
|
|
133545
133624
|
import { readFileSync as readFileSync53, existsSync as existsSync47, watch, mkdirSync as mkdirSync23, rmSync as rmSync11 } from "node:fs";
|
|
133546
|
-
import { basename as
|
|
133547
|
-
import { createHash as
|
|
133625
|
+
import { basename as basename11, dirname as dirname30, extname as extname2, join as join47, relative as relative8, resolve as resolve38, normalize as normalize3, sep as sep10 } from "node:path";
|
|
133626
|
+
import { createHash as createHash22, randomUUID as randomUUID5 } from "node:crypto";
|
|
133548
133627
|
import { fileURLToPath as fileURLToPath23, pathToFileURL as pathToFileURL6 } from "node:url";
|
|
133549
133628
|
function readLogicBundle(read, tier5Dir, name) {
|
|
133550
133629
|
return read(tier5Dir ?? TIER5_ROOT2, name) ?? (tier5Dir && tier5Dir !== TIER5_ROOT2 ? read(TIER5_ROOT2, name) : void 0);
|
|
@@ -133590,7 +133669,7 @@ async function readBody2(req) {
|
|
|
133590
133669
|
return Buffer.concat(chunks).toString("utf-8");
|
|
133591
133670
|
}
|
|
133592
133671
|
function makeEtag(body) {
|
|
133593
|
-
return `"${
|
|
133672
|
+
return `"${createHash22("sha256").update(body).digest("hex").slice(0, 32)}"`;
|
|
133594
133673
|
}
|
|
133595
133674
|
function servedTokensPath(app) {
|
|
133596
133675
|
return app.module.designTokensPath ?? resolve38(app.dir, uiConfig(app.module.config).designTokensPath ?? "tokens.json");
|
|
@@ -134121,7 +134200,7 @@ function bundleIntegritySync(name, dir) {
|
|
|
134121
134200
|
for (const root of dir ? [dir, TIER5_ROOT2] : [TIER5_ROOT2]) {
|
|
134122
134201
|
try {
|
|
134123
134202
|
const bytes2 = readFileSync53(resolve38(root, `${name}.bundle.js`));
|
|
134124
|
-
return "sha256-" +
|
|
134203
|
+
return "sha256-" + createHash22("sha256").update(bytes2).digest("base64");
|
|
134125
134204
|
} catch {
|
|
134126
134205
|
}
|
|
134127
134206
|
}
|
|
@@ -134542,7 +134621,7 @@ function tokensAreDerived(state) {
|
|
|
134542
134621
|
}
|
|
134543
134622
|
function servedTokensHash(app) {
|
|
134544
134623
|
try {
|
|
134545
|
-
return
|
|
134624
|
+
return createHash22("sha256").update(readFileSync53(servedTokensPath(app))).digest("hex");
|
|
134546
134625
|
} catch {
|
|
134547
134626
|
return "";
|
|
134548
134627
|
}
|
|
@@ -134570,7 +134649,7 @@ function syncAppDependencyWatchers(state, inputs) {
|
|
|
134570
134649
|
for (const file2 of appDependencyFiles(inputs, state.app.dir)) {
|
|
134571
134650
|
const dir = dirname30(file2);
|
|
134572
134651
|
if (!byDir.has(dir)) byDir.set(dir, /* @__PURE__ */ new Set());
|
|
134573
|
-
byDir.get(dir).add(
|
|
134652
|
+
byDir.get(dir).add(basename11(file2));
|
|
134574
134653
|
}
|
|
134575
134654
|
let timer;
|
|
134576
134655
|
const changed = /* @__PURE__ */ new Set();
|
|
@@ -135292,7 +135371,7 @@ async function handleWebWix(req, res, state) {
|
|
|
135292
135371
|
userId: userId ?? session.email ?? null,
|
|
135293
135372
|
email: session.email ?? "",
|
|
135294
135373
|
preferenceContext: preferenceIdentity ? {
|
|
135295
|
-
accountId: `m_${
|
|
135374
|
+
accountId: `m_${createHash22("sha256").update(preferenceIdentity).digest("hex")}`,
|
|
135296
135375
|
// Headless client IDs are site-bound and come from the server's app
|
|
135297
135376
|
// configuration, never the URL's user-supplied business parameter.
|
|
135298
135377
|
businessId: auth.clientId
|
|
@@ -135392,7 +135471,10 @@ async function handleDev(req, res, state) {
|
|
|
135392
135471
|
body.services ?? null,
|
|
135393
135472
|
width,
|
|
135394
135473
|
body.rtl === true,
|
|
135395
|
-
idiomContext
|
|
135474
|
+
idiomContext,
|
|
135475
|
+
// #4595 — HHP package images arrive host-less (`/v1/asset/<sha>?app=`); a PNG page loads at
|
|
135476
|
+
// about:blank, so resolve them against this server, as a device resolves them against its origin.
|
|
135477
|
+
state.serverBaseUrl
|
|
135396
135478
|
);
|
|
135397
135479
|
const legacy = { screenId, scheme, ...render, diagnostics };
|
|
135398
135480
|
const report3 = foldLegacyReport(legacy, {
|
|
@@ -136032,7 +136114,7 @@ async function readBundleFile(name, dir) {
|
|
|
136032
136114
|
if (!roots.some((root) => path2.startsWith(root))) continue;
|
|
136033
136115
|
try {
|
|
136034
136116
|
const bytes2 = await readFile(path2);
|
|
136035
|
-
const integrity2 = "sha256-" +
|
|
136117
|
+
const integrity2 = "sha256-" + createHash22("sha256").update(bytes2).digest("base64");
|
|
136036
136118
|
return { bytes: bytes2, integrity: integrity2 };
|
|
136037
136119
|
} catch {
|
|
136038
136120
|
}
|
|
@@ -136202,7 +136284,7 @@ function readActionHandlerManifest(app) {
|
|
|
136202
136284
|
} catch {
|
|
136203
136285
|
return { handlers: [] };
|
|
136204
136286
|
}
|
|
136205
|
-
const integrity2 = "sha256-" +
|
|
136287
|
+
const integrity2 = "sha256-" + createHash22("sha256").update(bytes2).digest("base64");
|
|
136206
136288
|
const bundleUrl = `/v1/action-handler-bundles/${app}`;
|
|
136207
136289
|
return { handlers: decls.map((d2) => ({ id: d2.id, policy: d2.policy, description: d2.description, bundleUrl, integrity: integrity2 })) };
|
|
136208
136290
|
}
|
|
@@ -136215,7 +136297,7 @@ async function handleActionHandlerBundleGet(res, app) {
|
|
|
136215
136297
|
if (!path2.startsWith(ACTION_HANDLERS_ROOT)) return sendJson(res, 404, { error: "not_found" });
|
|
136216
136298
|
try {
|
|
136217
136299
|
const bytes2 = await readFile(path2);
|
|
136218
|
-
const integrity2 = "sha256-" +
|
|
136300
|
+
const integrity2 = "sha256-" + createHash22("sha256").update(bytes2).digest("base64");
|
|
136219
136301
|
res.setHeader("content-type", "application/javascript; charset=utf-8");
|
|
136220
136302
|
res.setHeader("cache-control", "max-age=300");
|
|
136221
136303
|
res.setHeader("x-himalaya-bundle-integrity", integrity2);
|
|
@@ -136228,8 +136310,8 @@ async function handleActionHandlerBundleGet(res, app) {
|
|
|
136228
136310
|
}
|
|
136229
136311
|
async function serveStatic(req, res, root, prefix) {
|
|
136230
136312
|
const requested = decodeURIComponent((req.url ?? "").split("?")[0]);
|
|
136231
|
-
const
|
|
136232
|
-
const safe = normalize3(
|
|
136313
|
+
const relative18 = requested.replace(prefix, "").replace(/^\//, "");
|
|
136314
|
+
const safe = normalize3(relative18).replace(/^(\.\.[\/\\])+/, "");
|
|
136233
136315
|
const fullPath = resolve38(root, safe);
|
|
136234
136316
|
if (!fullPath.startsWith(root)) {
|
|
136235
136317
|
return send(res, 403, "forbidden");
|
|
@@ -137010,9 +137092,9 @@ var init_src6 = __esm({
|
|
|
137010
137092
|
});
|
|
137011
137093
|
|
|
137012
137094
|
// ../../core/serve-storage/src/release-patch.ts
|
|
137013
|
-
import { createHash as
|
|
137095
|
+
import { createHash as createHash23 } from "node:crypto";
|
|
137014
137096
|
function sha256hex(b2) {
|
|
137015
|
-
return
|
|
137097
|
+
return createHash23("sha256").update(b2).digest("hex");
|
|
137016
137098
|
}
|
|
137017
137099
|
function stableStringify(value) {
|
|
137018
137100
|
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
@@ -140045,11 +140127,11 @@ var init_dependencies = __esm({
|
|
|
140045
140127
|
});
|
|
140046
140128
|
|
|
140047
140129
|
// ../../core/functions-build/src/sbom.ts
|
|
140048
|
-
import { createHash as
|
|
140130
|
+
import { createHash as createHash24 } from "node:crypto";
|
|
140049
140131
|
function createFunctionSbom(packages) {
|
|
140050
140132
|
const components2 = [...packages].sort((a2, b2) => a2.name.localeCompare(b2.name)).map(({ name, version: version4, integrity: integrity2, license }) => ({ name, version: version4, integrity: integrity2, license }));
|
|
140051
140133
|
const body = JSON.stringify({ format: "himalaya-sbom-v1", components: components2 });
|
|
140052
|
-
return { format: "himalaya-sbom-v1", components: components2, hash:
|
|
140134
|
+
return { format: "himalaya-sbom-v1", components: components2, hash: createHash24("sha256").update(body).digest("hex") };
|
|
140053
140135
|
}
|
|
140054
140136
|
var init_sbom = __esm({
|
|
140055
140137
|
"../../core/functions-build/src/sbom.ts"() {
|
|
@@ -140057,12 +140139,12 @@ var init_sbom = __esm({
|
|
|
140057
140139
|
});
|
|
140058
140140
|
|
|
140059
140141
|
// ../../core/functions-build/src/build.ts
|
|
140060
|
-
import { createHash as
|
|
140142
|
+
import { createHash as createHash25 } from "node:crypto";
|
|
140061
140143
|
function sha2563(value) {
|
|
140062
|
-
return
|
|
140144
|
+
return createHash25("sha256").update(value).digest("hex");
|
|
140063
140145
|
}
|
|
140064
140146
|
function sri(value) {
|
|
140065
|
-
return `sha256-${
|
|
140147
|
+
return `sha256-${createHash25("sha256").update(value).digest("base64")}`;
|
|
140066
140148
|
}
|
|
140067
140149
|
function schemaHash(schema) {
|
|
140068
140150
|
if (!schema) return "";
|
|
@@ -140257,7 +140339,7 @@ __export(build_exports2, {
|
|
|
140257
140339
|
withStoreNavBundle: () => withStoreNavBundle,
|
|
140258
140340
|
withoutDevOnlyAppConfig: () => withoutDevOnlyAppConfig
|
|
140259
140341
|
});
|
|
140260
|
-
import { createHash as
|
|
140342
|
+
import { createHash as createHash26 } from "node:crypto";
|
|
140261
140343
|
import { readFileSync as readFileSync54, readdirSync as readdirSync25, existsSync as existsSync48 } from "node:fs";
|
|
140262
140344
|
import { dirname as dirname31, join as join48, resolve as resolve39 } from "node:path";
|
|
140263
140345
|
import { fileURLToPath as fileURLToPath24 } from "node:url";
|
|
@@ -140340,10 +140422,10 @@ function servesMessages(text9) {
|
|
|
140340
140422
|
}
|
|
140341
140423
|
}
|
|
140342
140424
|
function sha2564(buf) {
|
|
140343
|
-
return
|
|
140425
|
+
return createHash26("sha256").update(buf).digest("hex");
|
|
140344
140426
|
}
|
|
140345
140427
|
function sri2(buf) {
|
|
140346
|
-
return "sha256-" +
|
|
140428
|
+
return "sha256-" + createHash26("sha256").update(buf).digest("base64");
|
|
140347
140429
|
}
|
|
140348
140430
|
async function widgetFailureDetail(res) {
|
|
140349
140431
|
try {
|
|
@@ -140771,7 +140853,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
140771
140853
|
const compareScheme = collect2?.render?.compareScheme;
|
|
140772
140854
|
const renderCompare = async (descriptor, services) => {
|
|
140773
140855
|
if (!compareScheme || compareScheme === renderScheme) return {};
|
|
140774
|
-
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, compareScheme, false, services, collect2?.render?.width, collect2?.render?.rtl === true);
|
|
140856
|
+
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, compareScheme, false, services, collect2?.render?.width, collect2?.render?.rtl === true, void 0, base);
|
|
140775
140857
|
return { compare: { scheme: compareScheme, renderable: rr2.renderable, ...rr2.html ? { html: rr2.html } : {}, ...rr2.reason ? { reason: rr2.reason } : {} } };
|
|
140776
140858
|
};
|
|
140777
140859
|
const LIVE_LOAD_BUDGET_MS = 3e4;
|
|
@@ -141213,7 +141295,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
141213
141295
|
}
|
|
141214
141296
|
if (collect2?.render && (!collect2.render.screenId || collect2.render.screenId === screenId)) {
|
|
141215
141297
|
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed, liveFailed } = await renderServicesFor(bundleName, descriptor, screenId);
|
|
141216
|
-
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
|
|
141298
|
+
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true, void 0, base);
|
|
141217
141299
|
renders.push({ screenId, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveFailed ? { liveFailed } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
141218
141300
|
}
|
|
141219
141301
|
}
|
|
@@ -141241,7 +141323,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
141241
141323
|
lint.push({ screenId: wantedRender, ok: report3.ok, issues: report3.issues });
|
|
141242
141324
|
}
|
|
141243
141325
|
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed, liveFailed } = await renderServicesFor(bundleName, descriptor, wantedRender);
|
|
141244
|
-
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
|
|
141326
|
+
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true, void 0, base);
|
|
141245
141327
|
renders.push({ screenId: wantedRender, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveFailed ? { liveFailed } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
141246
141328
|
} else if (res.status === 422) {
|
|
141247
141329
|
const finding = await depthRefusalOf(res);
|
|
@@ -142555,9 +142637,9 @@ __export(studio_exports, {
|
|
|
142555
142637
|
renderStudioHtml: () => renderStudioHtml,
|
|
142556
142638
|
writeStudioRecord: () => writeStudioRecord
|
|
142557
142639
|
});
|
|
142558
|
-
import { createHash as
|
|
142640
|
+
import { createHash as createHash27 } from "node:crypto";
|
|
142559
142641
|
import { existsSync as existsSync51, readdirSync as readdirSync27, readFileSync as readFileSync57, realpathSync as realpathSync8, statSync as statSync12 } from "node:fs";
|
|
142560
|
-
import { basename as
|
|
142642
|
+
import { basename as basename12, extname as extname3, join as join51, relative as relative9, resolve as resolve40, sep as sep11 } from "node:path";
|
|
142561
142643
|
import { pathToFileURL as pathToFileURL7 } from "node:url";
|
|
142562
142644
|
function realInside(dir, abs) {
|
|
142563
142645
|
try {
|
|
@@ -142605,7 +142687,7 @@ function observeShots(dir, memory, now) {
|
|
|
142605
142687
|
const seen = /* @__PURE__ */ new Set();
|
|
142606
142688
|
const files = existsSync51(shotsDir) ? readdirSync27(shotsDir).filter((f2) => /\.(png|jpe?g)$/i.test(f2)).sort() : [];
|
|
142607
142689
|
for (const f2 of files) {
|
|
142608
|
-
const id =
|
|
142690
|
+
const id = basename12(f2, extname3(f2));
|
|
142609
142691
|
const archived = archiveFile(dir, memory, join51(shotsDir, f2));
|
|
142610
142692
|
if (!archived) continue;
|
|
142611
142693
|
seen.add(id);
|
|
@@ -142639,7 +142721,7 @@ function palette(dir) {
|
|
|
142639
142721
|
}
|
|
142640
142722
|
function appIdentity(dir) {
|
|
142641
142723
|
const manifest = obj(readJson4(join51(dir, "himalaya.content.json")));
|
|
142642
|
-
const name = text(manifest?.name) ??
|
|
142724
|
+
const name = text(manifest?.name) ?? basename12(resolve40(dir));
|
|
142643
142725
|
const icon = text(manifest?.icon)?.trim();
|
|
142644
142726
|
const iconPath = icon ? resolve40(dir, icon) : null;
|
|
142645
142727
|
const real = iconPath ? realInside(dir, iconPath) : null;
|
|
@@ -142818,7 +142900,7 @@ function buildView(dir, memory, now) {
|
|
|
142818
142900
|
message: e2.message,
|
|
142819
142901
|
step: isCliEntry(e2) ? null : e2.step ?? null,
|
|
142820
142902
|
stepNumber: isCliEntry(e2) ? null : e2.stepNumber ?? null,
|
|
142821
|
-
images: (e2.images ?? []).map((i2) => historyUrl(
|
|
142903
|
+
images: (e2.images ?? []).map((i2) => historyUrl(basename12(i2.file))),
|
|
142822
142904
|
by: isCliEntry(e2) ? CLI_AUTHOR : null
|
|
142823
142905
|
})),
|
|
142824
142906
|
screens,
|
|
@@ -142837,7 +142919,7 @@ function buildView(dir, memory, now) {
|
|
|
142837
142919
|
reveal: memory.reveal ?? null
|
|
142838
142920
|
};
|
|
142839
142921
|
const { generatedAt: _ignored, timelineFrames: _count, ...stable } = view;
|
|
142840
|
-
const v2 =
|
|
142922
|
+
const v2 = createHash27("sha256").update(JSON.stringify(stable)).digest("hex").slice(0, 16);
|
|
142841
142923
|
return { v: v2, ...view };
|
|
142842
142924
|
}
|
|
142843
142925
|
function writeAtomic(file2, content) {
|
|
@@ -149687,7 +149769,7 @@ var init_fxp = __esm({
|
|
|
149687
149769
|
});
|
|
149688
149770
|
|
|
149689
149771
|
// ../../packages/serve/src/pkcs12.ts
|
|
149690
|
-
import { X509Certificate, createHash as
|
|
149772
|
+
import { X509Certificate, createHash as createHash28, createPrivateKey as createPrivateKey2, createPublicKey, pbkdf2Sync, createDecipheriv } from "node:crypto";
|
|
149691
149773
|
function decodePkcs12(der, password) {
|
|
149692
149774
|
try {
|
|
149693
149775
|
const pfx = readSequence(der, 0);
|
|
@@ -149961,7 +150043,7 @@ function expand(src, v2) {
|
|
|
149961
150043
|
return out2;
|
|
149962
150044
|
}
|
|
149963
150045
|
function sha12(data) {
|
|
149964
|
-
return
|
|
150046
|
+
return createHash28("sha1").update(data).digest();
|
|
149965
150047
|
}
|
|
149966
150048
|
function readAt(buf, i2) {
|
|
149967
150049
|
if (i2 >= buf.length) return void 0;
|
|
@@ -150050,7 +150132,7 @@ var init_pkcs12 = __esm({
|
|
|
150050
150132
|
});
|
|
150051
150133
|
|
|
150052
150134
|
// ../../packages/serve/src/customer-signing-assets.ts
|
|
150053
|
-
import { createHash as
|
|
150135
|
+
import { createHash as createHash29 } from "node:crypto";
|
|
150054
150136
|
function readValue(node) {
|
|
150055
150137
|
const [tag, children] = Object.entries(node)[0] ?? [];
|
|
150056
150138
|
if (!tag || !Array.isArray(children)) return refuse3("customer_profile_invalid");
|
|
@@ -150128,7 +150210,7 @@ function toBundle(assets, expected, decoded, profileType, apns, deviceCount) {
|
|
|
150128
150210
|
provisioningProfile: Buffer.from(assets.provisioningProfile).toString("base64"),
|
|
150129
150211
|
profileSha256: sha2565(assets.provisioningProfile),
|
|
150130
150212
|
certificateSha256: sha2565(decoded.cert.raw),
|
|
150131
|
-
certificateSha1:
|
|
150213
|
+
certificateSha1: createHash29("sha1").update(decoded.cert.raw).digest("hex").toUpperCase(),
|
|
150132
150214
|
expiresAt: new Date(Math.min(decoded.expiration, Date.parse(decoded.cert.validTo))).toISOString(),
|
|
150133
150215
|
...apns ? { apnsEnvironment: apns } : {},
|
|
150134
150216
|
deviceCount
|
|
@@ -150179,7 +150261,7 @@ var init_customer_signing_assets = __esm({
|
|
|
150179
150261
|
init_fxp();
|
|
150180
150262
|
init_pkcs12();
|
|
150181
150263
|
init_customer_dist_signing();
|
|
150182
|
-
sha2565 = (bytes2) =>
|
|
150264
|
+
sha2565 = (bytes2) => createHash29("sha256").update(bytes2).digest("hex");
|
|
150183
150265
|
refuse3 = (code) => {
|
|
150184
150266
|
throw new CustomerSigningError(code);
|
|
150185
150267
|
};
|
|
@@ -150347,7 +150429,7 @@ var init_customer_signing_inspect = __esm({
|
|
|
150347
150429
|
|
|
150348
150430
|
// src/push-onboarding.ts
|
|
150349
150431
|
import { existsSync as existsSync53, mkdirSync as mkdirSync24, readFileSync as readFileSync60, statSync as statSync13, writeFileSync as writeFileSync20, chmodSync as chmodSync2 } from "node:fs";
|
|
150350
|
-
import { basename as
|
|
150432
|
+
import { basename as basename13, dirname as dirname32, join as join52, resolve as resolve43 } from "node:path";
|
|
150351
150433
|
function readJson5(path2) {
|
|
150352
150434
|
try {
|
|
150353
150435
|
const parsed = JSON.parse(readFileSync60(path2, "utf8"));
|
|
@@ -150368,7 +150450,7 @@ function pushInputsFromContent(dir) {
|
|
|
150368
150450
|
// autoClaimSlug's docblock describes as the project-declared slug. Without the fallback a
|
|
150369
150451
|
// package with no `name` sent a body missing `app` and earned `400 invalid_app_id` with both
|
|
150370
150452
|
// private keys already on the wire.
|
|
150371
|
-
app: text3(content.name) ??
|
|
150453
|
+
app: text3(content.name) ?? basename13(root),
|
|
150372
150454
|
...text3(provisioning.siteId) ? { site: text3(provisioning.siteId) } : {},
|
|
150373
150455
|
...text3(native.iosBundleId) ? { bundleId: text3(native.iosBundleId) } : {},
|
|
150374
150456
|
...text3(native.androidApplicationId) ? { androidApplicationId: text3(native.androidApplicationId) } : {}
|
|
@@ -150978,7 +151060,7 @@ __export(config_push_edit_exports, {
|
|
|
150978
151060
|
previewPushConfigEdit: () => previewPushConfigEdit
|
|
150979
151061
|
});
|
|
150980
151062
|
import { readFileSync as readFileSync62 } from "node:fs";
|
|
150981
|
-
import { basename as
|
|
151063
|
+
import { basename as basename14 } from "node:path";
|
|
150982
151064
|
import ts6 from "typescript";
|
|
150983
151065
|
function enablePushInConfig(source, options) {
|
|
150984
151066
|
const pingAppName = DEFAULT_PING_APP_NAME;
|
|
@@ -151097,13 +151179,13 @@ function noLiteralInstruction(pingAppName) {
|
|
|
151097
151179
|
function previewPushConfigEdit(dir, options) {
|
|
151098
151180
|
const path2 = configEntry(dir);
|
|
151099
151181
|
if (!path2) return void 0;
|
|
151100
|
-
const { applied, instructions } = enablePushInConfig(readFileSync62(path2, "utf8"), { ...options, fileName:
|
|
151182
|
+
const { applied, instructions } = enablePushInConfig(readFileSync62(path2, "utf8"), { ...options, fileName: basename14(path2) });
|
|
151101
151183
|
return { wouldApply: applied, instructions };
|
|
151102
151184
|
}
|
|
151103
151185
|
async function applyPushConfigEdit(dir, options, validate5) {
|
|
151104
151186
|
const path2 = configEntry(dir);
|
|
151105
151187
|
if (!path2) return void 0;
|
|
151106
|
-
const fileName =
|
|
151188
|
+
const fileName = basename14(path2);
|
|
151107
151189
|
const refuse7 = (why) => ({ changed: false, pushOn: false, applied: [], instructions: [why] });
|
|
151108
151190
|
if (isSymlink2(path2)) return refuse7(`${fileName} is a symlink, so it was not edited: turn push on in the file it points to.`);
|
|
151109
151191
|
const original = readFileSync62(path2, "utf8");
|
|
@@ -151424,7 +151506,7 @@ __export(pack_exports, {
|
|
|
151424
151506
|
unpackTo: () => unpackTo,
|
|
151425
151507
|
writeZip: () => writeZip
|
|
151426
151508
|
});
|
|
151427
|
-
import { createHash as
|
|
151509
|
+
import { createHash as createHash30 } from "node:crypto";
|
|
151428
151510
|
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
151429
151511
|
import { existsSync as existsSync55, mkdirSync as mkdirSync25, readFileSync as readFileSync63, readdirSync as readdirSync28, rmSync as rmSync12, statSync as statSync15, writeFileSync as writeFileSync21 } from "node:fs";
|
|
151430
151512
|
import { dirname as dirname33, join as join54, resolve as resolve46 } from "node:path";
|
|
@@ -151574,11 +151656,11 @@ function gatherReleaseEntries(appDir3) {
|
|
|
151574
151656
|
return { entries, manifest, skipped };
|
|
151575
151657
|
}
|
|
151576
151658
|
function sha256Hex4(bytes2) {
|
|
151577
|
-
return
|
|
151659
|
+
return createHash30("sha256").update(bytes2).digest("hex");
|
|
151578
151660
|
}
|
|
151579
151661
|
function computeContentHash(entries) {
|
|
151580
151662
|
const input = packageHashInput(entries.map((e2) => ({ path: e2.path, hash: sha256Hex4(e2.bytes) })));
|
|
151581
|
-
return "sha256-" +
|
|
151663
|
+
return "sha256-" + createHash30("sha256").update(input).digest("base64");
|
|
151582
151664
|
}
|
|
151583
151665
|
function buildEntries(appDir3, app, opts) {
|
|
151584
151666
|
const { entries: released, manifest, skipped } = gatherReleaseEntries(appDir3);
|
|
@@ -151769,7 +151851,7 @@ __export(app_source_exports, {
|
|
|
151769
151851
|
writeConflicts: () => writeConflicts,
|
|
151770
151852
|
zipAppSource: () => zipAppSource
|
|
151771
151853
|
});
|
|
151772
|
-
import { createHash as
|
|
151854
|
+
import { createHash as createHash31 } from "node:crypto";
|
|
151773
151855
|
import { readdirSync as readdirSync29, lstatSync as lstatSync15, readFileSync as readFileSync64, mkdirSync as mkdirSync26, writeFileSync as writeFileSync22, existsSync as existsSync56, rmSync as rmSync13, rmdirSync as rmdirSync2, unlinkSync as unlinkSync4 } from "node:fs";
|
|
151774
151856
|
import { join as join55, resolve as resolve47, sep as sep13 } from "node:path";
|
|
151775
151857
|
import { createRequire as createRequire3 } from "node:module";
|
|
@@ -151885,13 +151967,13 @@ function sourceFingerprint(dir) {
|
|
|
151885
151967
|
dir,
|
|
151886
151968
|
(archivePath, hostRel) => {
|
|
151887
151969
|
if (/\.md$/i.test(archivePath)) return;
|
|
151888
|
-
files.push(`${archivePath}\0${
|
|
151970
|
+
files.push(`${archivePath}\0${createHash31("sha256").update(readFileSync64(join55(dir, hostRel))).digest("hex")}`);
|
|
151889
151971
|
},
|
|
151890
151972
|
() => {
|
|
151891
151973
|
}
|
|
151892
151974
|
);
|
|
151893
151975
|
files.sort();
|
|
151894
|
-
return
|
|
151976
|
+
return createHash31("sha256").update(files.join("\n")).digest("hex");
|
|
151895
151977
|
}
|
|
151896
151978
|
function largestEntries(entries, limit = 5) {
|
|
151897
151979
|
return entries.map((e2) => ({
|
|
@@ -152085,6 +152167,7 @@ __export(run_watch_exports, {
|
|
|
152085
152167
|
ReloadBus: () => ReloadBus,
|
|
152086
152168
|
boardFile: () => boardFile,
|
|
152087
152169
|
diffReleases: () => diffReleases,
|
|
152170
|
+
hhpRasterDir: () => hhpRasterDir,
|
|
152088
152171
|
himiDir: () => himiDir,
|
|
152089
152172
|
ignoredChange: () => ignoredChange,
|
|
152090
152173
|
isEmptyDiff: () => isEmptyDiff,
|
|
@@ -152100,7 +152183,7 @@ __export(run_watch_exports, {
|
|
|
152100
152183
|
});
|
|
152101
152184
|
import { closeSync as closeSync4, constants as constants2, existsSync as existsSync57, fstatSync, lstatSync as lstatSync16, statSync as statSync16, readdirSync as readdirSync30, mkdirSync as mkdirSync27, openSync as openSync4, readFileSync as readFileSync65, realpathSync as realpathSync9, renameSync as renameSync10, rmSync as rmSync14, writeFileSync as writeFileSync23, watch as fsWatch } from "node:fs";
|
|
152102
152185
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
152103
|
-
import { extname as extname4, join as join56, resolve as resolve48, sep as sep14 } from "node:path";
|
|
152186
|
+
import { extname as extname4, join as join56, relative as relative11, resolve as resolve48, sep as sep14 } from "node:path";
|
|
152104
152187
|
function diffReleases(prev, next) {
|
|
152105
152188
|
const bundles = Object.keys(next.bundles).filter((b2) => prev.bundles[b2]?.sha256 !== next.bundles[b2].sha256).sort();
|
|
152106
152189
|
const changedBundles = new Set(bundles);
|
|
@@ -152125,10 +152208,20 @@ function reloadEvents(d2) {
|
|
|
152125
152208
|
if (d2.config) out2.push(["config.invalidated", {}]);
|
|
152126
152209
|
return out2;
|
|
152127
152210
|
}
|
|
152128
|
-
function
|
|
152211
|
+
function hhpRasterDir(dir) {
|
|
152212
|
+
const assets = findAssetsDir(dir);
|
|
152213
|
+
if (!assets) return null;
|
|
152214
|
+
const rel = relative11(dir, assets).split(sep14).join("/");
|
|
152215
|
+
return rel ? `${rel}/hhp-raster` : "hhp-raster";
|
|
152216
|
+
}
|
|
152217
|
+
function ignoredChange(relPath, isDirectory = () => false, rasterDir = "assets/hhp-raster") {
|
|
152129
152218
|
const parts = relPath.split(/[\\/]/).filter(Boolean);
|
|
152130
152219
|
if (parts[0] === "dev" && (parts[1] === "hhp" || parts[1]?.startsWith(".hhp-"))) return true;
|
|
152131
152220
|
if (parts[0] === "tier5-src" && parts[1]?.startsWith("hhp-")) return true;
|
|
152221
|
+
if (rasterDir) {
|
|
152222
|
+
const rel = parts.join("/");
|
|
152223
|
+
if (rel === rasterDir || rel.startsWith(`${rasterDir}/`)) return true;
|
|
152224
|
+
}
|
|
152132
152225
|
if (!parts.length) return true;
|
|
152133
152226
|
const [top] = parts;
|
|
152134
152227
|
if ([".himi", "dist", "node_modules", ".git", ".build", ...AGENT_TOOLING_DIRS].includes(top)) return true;
|
|
@@ -152139,11 +152232,12 @@ function ignoredChange(relPath, isDirectory = () => false) {
|
|
|
152139
152232
|
}
|
|
152140
152233
|
function watchContent(dir, onChange, opts = {}) {
|
|
152141
152234
|
const debounceMs = opts.debounceMs ?? 200;
|
|
152235
|
+
const rasterDir = hhpRasterDir(dir);
|
|
152142
152236
|
const watch2 = opts.watch ?? ((p2, o2, l2) => fsWatch(p2, o2, (event, file2) => l2(event, file2 === null ? null : String(file2))));
|
|
152143
152237
|
let timer = null;
|
|
152144
152238
|
const pending = /* @__PURE__ */ new Set();
|
|
152145
152239
|
const changed = (_event, file2) => {
|
|
152146
|
-
if (!file2 || ignoredChange(file2, (rel) => isDir(join56(dir, rel)))) return;
|
|
152240
|
+
if (!file2 || ignoredChange(file2, (rel) => isDir(join56(dir, rel)), rasterDir)) return;
|
|
152147
152241
|
pending.add(file2);
|
|
152148
152242
|
if (timer) clearTimeout(timer);
|
|
152149
152243
|
timer = setTimeout(() => {
|
|
@@ -152167,7 +152261,7 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
152167
152261
|
const path2 = join56(directory, String(name)), rel = prefix ? `${prefix}/${name}` : String(name);
|
|
152168
152262
|
try {
|
|
152169
152263
|
const stat2 = lstatSync16(path2);
|
|
152170
|
-
if (stat2.isSymbolicLink() || ignoredChange(rel, () => stat2.isDirectory())) continue;
|
|
152264
|
+
if (stat2.isSymbolicLink() || ignoredChange(rel, () => stat2.isDirectory(), rasterDir)) continue;
|
|
152171
152265
|
if (stat2.isDirectory()) visit(path2, rel);
|
|
152172
152266
|
else if (stat2.isFile()) files.set(rel, `${stat2.mtimeMs}:${stat2.ctimeMs}:${stat2.size}`);
|
|
152173
152267
|
} catch {
|
|
@@ -152369,6 +152463,7 @@ var init_run_watch = __esm({
|
|
|
152369
152463
|
"src/run-watch.ts"() {
|
|
152370
152464
|
init_source_deny();
|
|
152371
152465
|
init_run_identity();
|
|
152466
|
+
init_app_assets();
|
|
152372
152467
|
isEmptyDiff = (d2) => !d2.screens.length && !d2.bundles.length && !d2.tokens && !d2.config;
|
|
152373
152468
|
ReloadBus = class {
|
|
152374
152469
|
subscribers = /* @__PURE__ */ new Set();
|
|
@@ -152413,7 +152508,7 @@ __export(screen_state_exports, {
|
|
|
152413
152508
|
shotStateFor: () => shotStateFor,
|
|
152414
152509
|
withHomeCaveat: () => withHomeCaveat
|
|
152415
152510
|
});
|
|
152416
|
-
import { createHash as
|
|
152511
|
+
import { createHash as createHash32 } from "node:crypto";
|
|
152417
152512
|
import { lstatSync as lstatSync17, readFileSync as readFileSync66 } from "node:fs";
|
|
152418
152513
|
import { join as join57 } from "node:path";
|
|
152419
152514
|
function quotableLine(text9) {
|
|
@@ -152533,7 +152628,7 @@ var init_screen_state = __esm({
|
|
|
152533
152628
|
KEEP = 40;
|
|
152534
152629
|
LINE_MAX = 120;
|
|
152535
152630
|
str3 = (v2) => typeof v2 === "string" && v2.trim() ? v2 : void 0;
|
|
152536
|
-
sha256Of = (file2) =>
|
|
152631
|
+
sha256Of = (file2) => createHash32("sha256").update(readFileSync66(file2)).digest("hex");
|
|
152537
152632
|
}
|
|
152538
152633
|
});
|
|
152539
152634
|
|
|
@@ -152548,9 +152643,9 @@ __export(studio_reel_exports, {
|
|
|
152548
152643
|
thin: () => thin,
|
|
152549
152644
|
utcDay: () => utcDay
|
|
152550
152645
|
});
|
|
152551
|
-
import { createHash as
|
|
152646
|
+
import { createHash as createHash33 } from "node:crypto";
|
|
152552
152647
|
import { lstatSync as lstatSync18, readFileSync as readFileSync67 } from "node:fs";
|
|
152553
|
-
import { basename as
|
|
152648
|
+
import { basename as basename15, join as join58 } from "node:path";
|
|
152554
152649
|
function loadMemory2(dir) {
|
|
152555
152650
|
const m2 = readJson6(join58(dir, ".himi", "studio", "memory.json"));
|
|
152556
152651
|
if (!isObj3(m2) || m2.version !== 1 || !isObj3(m2.shots) || !Array.isArray(m2.timeline)) return null;
|
|
@@ -152606,13 +152701,13 @@ function planReel(dir) {
|
|
|
152606
152701
|
message: e2.message,
|
|
152607
152702
|
step: isCliEntry(e2) ? null : str4(e2.step),
|
|
152608
152703
|
by: isCliEntry(e2) ? CLI_AUTHOR : null,
|
|
152609
|
-
files: (Array.isArray(e2.images) ? e2.images : []).map((i2) => isObj3(i2) && typeof i2.file === "string" ?
|
|
152704
|
+
files: (Array.isArray(e2.images) ? e2.images : []).map((i2) => isObj3(i2) && typeof i2.file === "string" ? basename15(i2.file) : "").filter((f2) => HISTORY_NAME.test(f2))
|
|
152610
152705
|
}));
|
|
152611
152706
|
const times = [summary2.startedAt, ...timeline.map((t2) => t2.ts), memory?.createdAt].filter((x2) => !!x2).sort();
|
|
152612
152707
|
const startedAt = times[0] ?? null;
|
|
152613
152708
|
const endedAt = [summary2.lastAt, ...timeline.map((t2) => t2.ts)].filter((x2) => !!x2).sort().pop() ?? null;
|
|
152614
152709
|
return {
|
|
152615
|
-
app: typeof manifest?.name === "string" && manifest.name ? manifest.name :
|
|
152710
|
+
app: typeof manifest?.name === "string" && manifest.name ? manifest.name : basename15(dir),
|
|
152616
152711
|
accent,
|
|
152617
152712
|
startedAt,
|
|
152618
152713
|
endedAt,
|
|
@@ -152637,7 +152732,7 @@ function inlineImages(dir, plan, budget = REEL_BUDGET_BYTES) {
|
|
|
152637
152732
|
const st2 = lstatSync18(path2);
|
|
152638
152733
|
if (!st2.isFile() || st2.nlink !== 1) return null;
|
|
152639
152734
|
const bytes2 = readFileSync67(path2);
|
|
152640
|
-
return
|
|
152735
|
+
return createHash33("sha256").update(bytes2).digest("hex") === f2.slice(0, 64) && imageExtension(bytes2) === f2.slice(65) ? bytes2 : null;
|
|
152641
152736
|
} catch {
|
|
152642
152737
|
return null;
|
|
152643
152738
|
}
|
|
@@ -152858,11 +152953,11 @@ __export(milestones_exports, {
|
|
|
152858
152953
|
watchUrlFor: () => watchUrlFor,
|
|
152859
152954
|
writeHandoverReel: () => writeHandoverReel
|
|
152860
152955
|
});
|
|
152861
|
-
import { createHash as
|
|
152956
|
+
import { createHash as createHash34, randomUUID as randomUUID7 } from "node:crypto";
|
|
152862
152957
|
import { spawn as spawn5 } from "node:child_process";
|
|
152863
152958
|
import { closeSync as closeSync5, existsSync as existsSync58, lstatSync as lstatSync19, readFileSync as readFileSync69, statSync as statSync17 } from "node:fs";
|
|
152864
152959
|
import { createServer as createServer4 } from "node:net";
|
|
152865
|
-
import { basename as
|
|
152960
|
+
import { basename as basename16, dirname as dirname34, isAbsolute as isAbsolute6, join as join60, relative as relative12, resolve as resolve49, sep as sep15 } from "node:path";
|
|
152866
152961
|
function homeShotPath(dir, home) {
|
|
152867
152962
|
const root = resolve49(dir);
|
|
152868
152963
|
const base = resolve49(root, ".himi", "shots");
|
|
@@ -152877,7 +152972,7 @@ function homeShotPath(dir, home) {
|
|
|
152877
152972
|
return shot;
|
|
152878
152973
|
}
|
|
152879
152974
|
function displayPath(p2, cwd = process.cwd()) {
|
|
152880
|
-
const rel =
|
|
152975
|
+
const rel = relative12(cwd, p2);
|
|
152881
152976
|
return rel && !rel.startsWith("..") && !isAbsolute6(rel) ? rel : p2;
|
|
152882
152977
|
}
|
|
152883
152978
|
function progressCommand(opts) {
|
|
@@ -153018,7 +153113,7 @@ async function openBoardForSession(dir, cwd = process.cwd()) {
|
|
|
153018
153113
|
try {
|
|
153019
153114
|
const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
153020
153115
|
const { page, url } = openStudio2(dir);
|
|
153021
|
-
const rel =
|
|
153116
|
+
const rel = relative12(cwd, page);
|
|
153022
153117
|
return { page: rel && !rel.startsWith("..") && !isAbsolute6(rel) ? rel : page, url, opened: false };
|
|
153023
153118
|
} catch (e2) {
|
|
153024
153119
|
return { opened: false, error: `the build board was not created: ${e2.message} \u2014 \`himi studio --no-open\` in the app retries it` };
|
|
@@ -153502,7 +153597,7 @@ function writeHandoverReel(dir) {
|
|
|
153502
153597
|
const { html } = buildReel(dir);
|
|
153503
153598
|
const file2 = join60(dir, ".himi", "making-of.html");
|
|
153504
153599
|
writeFileAtomic(file2, html);
|
|
153505
|
-
return { file: file2, hint: `hand ${
|
|
153600
|
+
return { file: file2, hint: `hand ${basename16(file2)} to the owner at the handover \u2014 one self-contained page of their app taking shape; send it beside the preview link, never instead of it` };
|
|
153506
153601
|
} catch (e2) {
|
|
153507
153602
|
return { skipped: `the making-of was not written: ${e2.message.split("\n")[0]} \u2014 \`himi studio reel\` retries it` };
|
|
153508
153603
|
}
|
|
@@ -153516,7 +153611,7 @@ function afterHandoverPostcard(dir, opts = {}) {
|
|
|
153516
153611
|
} catch {
|
|
153517
153612
|
fresh = false;
|
|
153518
153613
|
}
|
|
153519
|
-
const makingOf = fresh ? { file: file2, hint: `hand ${
|
|
153614
|
+
const makingOf = fresh ? { file: file2, hint: `hand ${basename16(file2)} to the owner at the handover \u2014 one self-contained page of their app taking shape; send it beside the preview link, never instead of it` } : writeHandoverReel(dir);
|
|
153520
153615
|
const next = "file" in makingOf ? [`hand the owner the making-of, ${shellQuote(displayPath(makingOf.file))}, beside the preview link \u2014 in your final message and report, never instead of the link`] : [`\`himi studio reel${contentArg(opts.content)}\` writes the making-of to hand the owner beside the preview link (${makingOf.skipped})`];
|
|
153521
153616
|
return { makingOf, next };
|
|
153522
153617
|
}
|
|
@@ -153539,7 +153634,7 @@ var init_milestones = __esm({
|
|
|
153539
153634
|
FIRST_LOOK_BUDGET_MS = 9e4;
|
|
153540
153635
|
VALIDATE_PICTURE_BUDGET_MS = 3e4;
|
|
153541
153636
|
plural2 = (n2, one, many = `${one}s`) => `${n2} ${n2 === 1 ? one : many}`;
|
|
153542
|
-
appName = (dir) => appLabel(dir) ??
|
|
153637
|
+
appName = (dir) => appLabel(dir) ?? basename16(dir);
|
|
153543
153638
|
STILL_BUILDING_AFTER_MS = 10 * 60 * 1e3;
|
|
153544
153639
|
STILL_BUILDING_MESSAGE = "Still building: here's the home screen now.";
|
|
153545
153640
|
yourFirstLookMessage = (dir) => `First look at your app: ${appName(dir)}'s home screen, with your changes.`;
|
|
@@ -153548,7 +153643,7 @@ var init_milestones = __esm({
|
|
|
153548
153643
|
INIT_SOURCE_FILE = join60(".himi", "init-source.json");
|
|
153549
153644
|
STARTING_POINT_REF = "starting-point";
|
|
153550
153645
|
TEMPLATE_NAME = /^[A-Za-z0-9._-]{1,64}$/;
|
|
153551
|
-
sha256Of2 = (file2) =>
|
|
153646
|
+
sha256Of2 = (file2) => createHash34("sha256").update(readFileSync69(file2)).digest("hex");
|
|
153552
153647
|
WATCH_REMINDER_EVERY_MS = 10 * 60 * 1e3;
|
|
153553
153648
|
REMINDERS_FILE = join60(".himi", "reminders.json");
|
|
153554
153649
|
pidAlive = (pid) => {
|
|
@@ -154598,7 +154693,7 @@ __export(eject_exports, {
|
|
|
154598
154693
|
ejectModule: () => ejectModule
|
|
154599
154694
|
});
|
|
154600
154695
|
import { existsSync as existsSync61, mkdirSync as mkdirSync29, readFileSync as readFileSync73, writeFileSync as writeFileSync26 } from "node:fs";
|
|
154601
|
-
import { dirname as dirname36, join as join64, relative as
|
|
154696
|
+
import { dirname as dirname36, join as join64, relative as relative13, resolve as resolve50, sep as sep16 } from "node:path";
|
|
154602
154697
|
function locate(repoRootOrCwd, mod) {
|
|
154603
154698
|
const inRepo = resolve50(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
|
|
154604
154699
|
if (existsSync61(inRepo)) return { path: inRepo, form: "source" };
|
|
@@ -154651,7 +154746,7 @@ function ejectModule(opts) {
|
|
|
154651
154746
|
if (!existsSync61(f2)) continue;
|
|
154652
154747
|
const before = readFileSync73(f2, "utf8");
|
|
154653
154748
|
let after = before;
|
|
154654
|
-
let rel =
|
|
154749
|
+
let rel = relative13(dirname36(f2), target).split(sep16).join("/").replace(/\.tsx?$/, ".js");
|
|
154655
154750
|
if (!rel.startsWith(".")) rel = `./${rel}`;
|
|
154656
154751
|
for (const spec of specifiersFor(mod)) {
|
|
154657
154752
|
const q2 = spec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -156613,10 +156708,10 @@ var init_calls = __esm({
|
|
|
156613
156708
|
});
|
|
156614
156709
|
|
|
156615
156710
|
// ../../core/functions-runtime/src/queue.ts
|
|
156616
|
-
import { createHash as
|
|
156711
|
+
import { createHash as createHash35 } from "node:crypto";
|
|
156617
156712
|
function inputSchemaHash(definition) {
|
|
156618
156713
|
const schema = definition.input;
|
|
156619
|
-
return schema ?
|
|
156714
|
+
return schema ? createHash35("sha256").update(JSON.stringify(schema.descriptor ?? { kind: schema.kind, optional: schema.optional === true })).digest("hex") : "";
|
|
156620
156715
|
}
|
|
156621
156716
|
function createFunctionEnqueueCapability(options) {
|
|
156622
156717
|
return {
|
|
@@ -156682,14 +156777,14 @@ var init_queue = __esm({
|
|
|
156682
156777
|
});
|
|
156683
156778
|
|
|
156684
156779
|
// ../../core/data-resources/src/plan.ts
|
|
156685
|
-
import { createHash as
|
|
156780
|
+
import { createHash as createHash36 } from "node:crypto";
|
|
156686
156781
|
function canonical3(value) {
|
|
156687
156782
|
if (Array.isArray(value)) return `[${value.map(canonical3).join(",")}]`;
|
|
156688
156783
|
if (value && typeof value === "object") return `{${Object.entries(value).sort(([a2], [b2]) => a2.localeCompare(b2)).map(([key3, item]) => `${JSON.stringify(key3)}:${canonical3(item)}`).join(",")}}`;
|
|
156689
156784
|
return JSON.stringify(value);
|
|
156690
156785
|
}
|
|
156691
156786
|
function hashResourcePlan(plan) {
|
|
156692
|
-
return
|
|
156787
|
+
return createHash36("sha256").update(canonical3(plan)).digest("hex");
|
|
156693
156788
|
}
|
|
156694
156789
|
function finalize(input) {
|
|
156695
156790
|
return { ...input, hash: hashResourcePlan(input) };
|
|
@@ -157656,7 +157751,7 @@ var init_cli_bridge = __esm({
|
|
|
157656
157751
|
// src/mcp/file-tools.ts
|
|
157657
157752
|
import { closeSync as closeSync6, constants as constants3, lstatSync as lstatSync20, mkdirSync as mkdirSync31, openSync as openSync5, readdirSync as readdirSync31, readFileSync as readFileSync78, realpathSync as realpathSync10, renameSync as renameSync11, rmSync as rmSync15, statSync as statSync18, writeSync, existsSync as existsSync66 } from "node:fs";
|
|
157658
157753
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
157659
|
-
import { dirname as dirname37, isAbsolute as isAbsolute7, join as join69, relative as
|
|
157754
|
+
import { dirname as dirname37, isAbsolute as isAbsolute7, join as join69, relative as relative14, resolve as resolve53, sep as sep17 } from "node:path";
|
|
157660
157755
|
import * as z2 from "zod";
|
|
157661
157756
|
function within(root, p2) {
|
|
157662
157757
|
return p2 === root || p2.startsWith(root.endsWith(sep17) ? root : root + sep17);
|
|
@@ -157674,10 +157769,10 @@ function realish(p2) {
|
|
|
157674
157769
|
}
|
|
157675
157770
|
function symlinkComponent(base, abs) {
|
|
157676
157771
|
let cur = base;
|
|
157677
|
-
for (const part3 of
|
|
157772
|
+
for (const part3 of relative14(base, abs).split(sep17).filter(Boolean)) {
|
|
157678
157773
|
cur = join69(cur, part3);
|
|
157679
157774
|
try {
|
|
157680
|
-
if (lstatSync20(cur).isSymbolicLink()) return
|
|
157775
|
+
if (lstatSync20(cur).isSymbolicLink()) return relative14(base, cur);
|
|
157681
157776
|
} catch {
|
|
157682
157777
|
return void 0;
|
|
157683
157778
|
}
|
|
@@ -157700,7 +157795,7 @@ async function confinedAppDir(args, deps) {
|
|
|
157700
157795
|
if (!within(root, dir) || !within(realpathSync10(root), realish(dir))) return refuse5("outside_workspace", `"${String(args.dir)}" is outside the workspace folder`);
|
|
157701
157796
|
const link = symlinkComponent(root, dir);
|
|
157702
157797
|
if (link) return refuse5("outside_workspace", `"${link}" is a symlink \u2014 the app folder must be a real folder in the workspace`);
|
|
157703
|
-
const rel =
|
|
157798
|
+
const rel = relative14(root, dir);
|
|
157704
157799
|
if (rel && (isDeniedSourcePath(`${rel}/x`) || isDeniedSourcePath(`${rel.toLowerCase()}/x`))) return refuse5("denied", `"${rel}" is a folder this tool does not touch`);
|
|
157705
157800
|
if (!existsSync66(join69(dir, CONTENT_MARKER))) {
|
|
157706
157801
|
return refuse5("not_an_app", `"${rel || "."}" is not an app folder (no ${CONTENT_MARKER}) \u2014 see himi_list_apps, or create one with himi_init`);
|
|
@@ -157719,10 +157814,10 @@ function onDiskSpelling(abs) {
|
|
|
157719
157814
|
return join69(realpathSync10.native(cur), ...tail);
|
|
157720
157815
|
}
|
|
157721
157816
|
function denied(appDir3, abs) {
|
|
157722
|
-
const rel =
|
|
157817
|
+
const rel = relative14(appDir3, abs);
|
|
157723
157818
|
if (isDeniedSourcePath(rel) || isDeniedSourcePath(rel.toLowerCase())) return true;
|
|
157724
157819
|
try {
|
|
157725
|
-
return isDeniedSourcePath(
|
|
157820
|
+
return isDeniedSourcePath(relative14(realpathSync10.native(appDir3), onDiskSpelling(abs)));
|
|
157726
157821
|
} catch {
|
|
157727
157822
|
return true;
|
|
157728
157823
|
}
|
|
@@ -157755,14 +157850,14 @@ function writeNoFollow2(appDir3, abs, content) {
|
|
|
157755
157850
|
const link = symlinkComponent(appDir3, abs);
|
|
157756
157851
|
if (link || !within(realpathSync10(appDir3), realpathSync10(dirname37(abs)))) {
|
|
157757
157852
|
rmSync15(tmp, { force: true });
|
|
157758
|
-
throw new Error(`"${link ??
|
|
157853
|
+
throw new Error(`"${link ?? relative14(appDir3, dirname37(abs))}" changed into a link while writing`);
|
|
157759
157854
|
}
|
|
157760
157855
|
renameSync11(tmp, abs);
|
|
157761
157856
|
}
|
|
157762
157857
|
function listFiles(appDir3) {
|
|
157763
157858
|
const files = [];
|
|
157764
157859
|
const walk2 = (d2) => {
|
|
157765
|
-
const parentRel =
|
|
157860
|
+
const parentRel = relative14(appDir3, d2);
|
|
157766
157861
|
for (const e2 of readdirSync31(d2, { withFileTypes: true }).sort((a2, b2) => a2.name.localeCompare(b2.name))) {
|
|
157767
157862
|
if (e2.isSymbolicLink()) continue;
|
|
157768
157863
|
const p2 = join69(d2, e2.name);
|
|
@@ -157770,7 +157865,7 @@ function listFiles(appDir3) {
|
|
|
157770
157865
|
if (isDeniedSourceDir(e2.name, parentRel) || isDeniedSourceDir(e2.name.toLowerCase(), parentRel)) continue;
|
|
157771
157866
|
if (!walk2(p2)) return false;
|
|
157772
157867
|
} else if (e2.isFile()) {
|
|
157773
|
-
const rel =
|
|
157868
|
+
const rel = relative14(appDir3, p2);
|
|
157774
157869
|
if (isDeniedSourcePath(rel) || isDeniedSourcePath(rel.toLowerCase())) continue;
|
|
157775
157870
|
if (files.length >= MAX_LISTED) return false;
|
|
157776
157871
|
files.push({ path: rel.split(sep17).join("/"), bytes: statSync18(p2).size });
|
|
@@ -158866,9 +158961,9 @@ __export(browser_authoring_exports, {
|
|
|
158866
158961
|
sdkSubpathReader: () => sdkSubpathReader
|
|
158867
158962
|
});
|
|
158868
158963
|
import { createServer as createServer5 } from "node:http";
|
|
158869
|
-
import { createHash as
|
|
158964
|
+
import { createHash as createHash37, randomBytes as randomBytes5 } from "node:crypto";
|
|
158870
158965
|
import { existsSync as existsSync68, readdirSync as readdirSync32, readFileSync as readFileSync81, realpathSync as realpathSync11, statSync as statSync19 } from "node:fs";
|
|
158871
|
-
import { join as join71, posix as posix3, relative as
|
|
158966
|
+
import { join as join71, posix as posix3, relative as relative15, sep as sep18 } from "node:path";
|
|
158872
158967
|
function humanMs(ms2) {
|
|
158873
158968
|
return ms2 < 1e3 ? `${ms2}ms` : `${Math.round(ms2 / 1e3)}s`;
|
|
158874
158969
|
}
|
|
@@ -158918,7 +159013,7 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
158918
159013
|
];
|
|
158919
159014
|
for (const abs of candidates) {
|
|
158920
159015
|
if (!existsSync68(abs) || statSync19(abs).isDirectory()) continue;
|
|
158921
|
-
const key3 = `/tier5-src/${
|
|
159016
|
+
const key3 = `/tier5-src/${relative15(tier5SrcDir, abs).split(sep18).join(posix3.sep)}`;
|
|
158922
159017
|
if (key3 in files) break;
|
|
158923
159018
|
files[key3] = readFileSync81(abs, "utf8");
|
|
158924
159019
|
queue.push(key3);
|
|
@@ -158965,7 +159060,7 @@ function encodeJob(job) {
|
|
|
158965
159060
|
return Buffer.from(JSON.stringify(job), "utf8").toString("base64");
|
|
158966
159061
|
}
|
|
158967
159062
|
function mintToken2(payload, nonce = randomBytes5(16).toString("hex")) {
|
|
158968
|
-
const digest2 =
|
|
159063
|
+
const digest2 = createHash37("sha256").update(payload, "utf8").digest("base64url");
|
|
158969
159064
|
return `${nonce}.${digest2}`;
|
|
158970
159065
|
}
|
|
158971
159066
|
function defaultOpenBrowser2(url) {
|
|
@@ -159417,7 +159512,7 @@ __export(design_kits_exports, {
|
|
|
159417
159512
|
listKits: () => listKits2
|
|
159418
159513
|
});
|
|
159419
159514
|
import { existsSync as existsSync70, readFileSync as readFileSync83, readdirSync as readdirSync33 } from "node:fs";
|
|
159420
|
-
import { join as join73, basename as
|
|
159515
|
+
import { join as join73, basename as basename17 } from "node:path";
|
|
159421
159516
|
import { fileURLToPath as fileURLToPath27 } from "node:url";
|
|
159422
159517
|
function kitsDir() {
|
|
159423
159518
|
return KIT_DIR_CANDIDATES.find((p2) => existsSync70(p2));
|
|
@@ -159425,7 +159520,7 @@ function kitsDir() {
|
|
|
159425
159520
|
function listKits2() {
|
|
159426
159521
|
const dir = kitsDir();
|
|
159427
159522
|
if (!dir) return [];
|
|
159428
|
-
return readdirSync33(dir).filter((f2) => f2.endsWith(".json")).map((f2) =>
|
|
159523
|
+
return readdirSync33(dir).filter((f2) => f2.endsWith(".json")).map((f2) => basename17(f2, ".json")).sort();
|
|
159429
159524
|
}
|
|
159430
159525
|
function kitReport(name) {
|
|
159431
159526
|
const dir = kitsDir();
|
|
@@ -159485,7 +159580,7 @@ __export(assets_exports, {
|
|
|
159485
159580
|
verifyReport: () => verifyReport
|
|
159486
159581
|
});
|
|
159487
159582
|
import { readFileSync as readFileSync84 } from "node:fs";
|
|
159488
|
-
import { basename as
|
|
159583
|
+
import { basename as basename18 } from "node:path";
|
|
159489
159584
|
function declaredAssets(dir) {
|
|
159490
159585
|
return collectAssets(dir).map((a2) => {
|
|
159491
159586
|
const bytes2 = readFileSync84(a2.path);
|
|
@@ -159566,7 +159661,7 @@ function verifyReport(dir, app, manifest) {
|
|
|
159566
159661
|
}
|
|
159567
159662
|
function addAssetPayload(manifest, filePath, opts) {
|
|
159568
159663
|
const bytes2 = readFileSync84(filePath);
|
|
159569
|
-
const name = opts.name ??
|
|
159664
|
+
const name = opts.name ?? basename18(filePath);
|
|
159570
159665
|
const sha2567 = assetSha256(bytes2);
|
|
159571
159666
|
const record2 = {
|
|
159572
159667
|
sha256: sha2567,
|
|
@@ -162691,7 +162786,7 @@ var init_iap_api = __esm({
|
|
|
162691
162786
|
});
|
|
162692
162787
|
|
|
162693
162788
|
// ../store-release/iap-manifest.ts
|
|
162694
|
-
import { createHash as
|
|
162789
|
+
import { createHash as createHash38 } from "node:crypto";
|
|
162695
162790
|
function readTarget(reader, value) {
|
|
162696
162791
|
const obj4 = reader.object(value, "target", TARGET_KEYS);
|
|
162697
162792
|
return {
|
|
@@ -162837,7 +162932,7 @@ function canonicalJson(value) {
|
|
|
162837
162932
|
return JSON.stringify(sortKeys(value));
|
|
162838
162933
|
}
|
|
162839
162934
|
function sha256Digest(value) {
|
|
162840
|
-
return `sha256:${
|
|
162935
|
+
return `sha256:${createHash38("sha256").update(canonicalJson(value)).digest("hex")}`;
|
|
162841
162936
|
}
|
|
162842
162937
|
function manifestDigest(manifest) {
|
|
162843
162938
|
return sha256Digest(manifest);
|
|
@@ -163028,7 +163123,7 @@ var init_iap_pricing = __esm({
|
|
|
163028
163123
|
});
|
|
163029
163124
|
|
|
163030
163125
|
// ../store-release/iap-result.ts
|
|
163031
|
-
import { basename as
|
|
163126
|
+
import { basename as basename19 } from "node:path";
|
|
163032
163127
|
function missingMetadataRequirement(screenshotState, itemNamesFile) {
|
|
163033
163128
|
if (screenshotState === void 0) return MISSING_SCREENSHOT;
|
|
163034
163129
|
const leftover = LEFTOVER_STATES[screenshotState];
|
|
@@ -163060,7 +163155,7 @@ function metadataVersion(observed) {
|
|
|
163060
163155
|
}
|
|
163061
163156
|
function screenshotReport(path2, observed) {
|
|
163062
163157
|
const held = observed?.reviewScreenshot;
|
|
163063
|
-
return { requested:
|
|
163158
|
+
return { requested: basename19(path2), ...held ? { observed: { fileName: held.fileName, state: held.state } } : {} };
|
|
163064
163159
|
}
|
|
163065
163160
|
function itemResult(input) {
|
|
163066
163161
|
const { target, item, observed } = input;
|
|
@@ -163192,8 +163287,8 @@ var init_screenshot_display_types = __esm({
|
|
|
163192
163287
|
});
|
|
163193
163288
|
|
|
163194
163289
|
// ../store-release/iap-review-screenshot.ts
|
|
163195
|
-
import { createHash as
|
|
163196
|
-
import { basename as
|
|
163290
|
+
import { createHash as createHash39 } from "node:crypto";
|
|
163291
|
+
import { basename as basename20, resolve as resolve56 } from "node:path";
|
|
163197
163292
|
function pngSize(bytes2) {
|
|
163198
163293
|
const signed = PNG_SIGNATURE.every((b2, i2) => bytes2[i2] === b2);
|
|
163199
163294
|
if (!signed || bytes2.length < 24 || bytes2.toString("ascii", 12, 16) !== "IHDR") return void 0;
|
|
@@ -163211,7 +163306,7 @@ function readImageSize(bytes2) {
|
|
|
163211
163306
|
return pngSize(buffer) ?? jpegSize(buffer);
|
|
163212
163307
|
}
|
|
163213
163308
|
function md5Hex(bytes2) {
|
|
163214
|
-
return
|
|
163309
|
+
return createHash39("md5").update(bytes2).digest("hex");
|
|
163215
163310
|
}
|
|
163216
163311
|
function isAppStoreScreenshotSize(file2) {
|
|
163217
163312
|
return displayTypeForSize(file2.width, file2.height) !== null;
|
|
@@ -163233,7 +163328,7 @@ function readReviewScreenshot(path2, source) {
|
|
|
163233
163328
|
}
|
|
163234
163329
|
const size = readImageSize(bytes2);
|
|
163235
163330
|
if (!size) throw new Error(`${absolute} is not a PNG or JPEG image`);
|
|
163236
|
-
return { ...size, path: absolute, fileName:
|
|
163331
|
+
return { ...size, path: absolute, fileName: basename20(absolute), bytes: bytes2, checksum: md5Hex(bytes2) };
|
|
163237
163332
|
}
|
|
163238
163333
|
function loadReviewScreenshots(manifest, source, indices = manifest.items.map((_2, i2) => i2)) {
|
|
163239
163334
|
const files = /* @__PURE__ */ new Map();
|
|
@@ -164144,11 +164239,11 @@ var init_credential_profile = __esm({
|
|
|
164144
164239
|
});
|
|
164145
164240
|
|
|
164146
164241
|
// ../store-release/iap-credentials.ts
|
|
164147
|
-
import { createHash as
|
|
164242
|
+
import { createHash as createHash40 } from "node:crypto";
|
|
164148
164243
|
import { existsSync as existsSync75, readFileSync as readFileSync90, realpathSync as realpathSync12 } from "node:fs";
|
|
164149
164244
|
import { homedir as homedir11 } from "node:os";
|
|
164150
164245
|
function accountFingerprint(keyId, issuerId) {
|
|
164151
|
-
return `sha256:${
|
|
164246
|
+
return `sha256:${createHash40("sha256").update(`${issuerId}:${keyId}`).digest("hex").slice(0, 16)}`;
|
|
164152
164247
|
}
|
|
164153
164248
|
function requireExplicitProfile(profileFlag, target) {
|
|
164154
164249
|
const profile = profileFlag?.trim();
|
|
@@ -164235,7 +164330,7 @@ var init_wix_payments_contract = __esm({
|
|
|
164235
164330
|
});
|
|
164236
164331
|
|
|
164237
164332
|
// ../store-release/iap-draft.ts
|
|
164238
|
-
import { createHash as
|
|
164333
|
+
import { createHash as createHash41 } from "node:crypto";
|
|
164239
164334
|
function fit(text9, max) {
|
|
164240
164335
|
const chars = [...text9];
|
|
164241
164336
|
return chars.length <= max ? text9 : `${chars.slice(0, max - 1).join("").trimEnd()}${ELLIPSIS}`;
|
|
@@ -164385,7 +164480,7 @@ var init_iap_draft = __esm({
|
|
|
164385
164480
|
TIER_DESCRIPTION = "Unlocks one item in the app";
|
|
164386
164481
|
ELLIPSIS = "\u2026";
|
|
164387
164482
|
entityKey = (entityType, entityId) => `${entityType}:${entityId}`;
|
|
164388
|
-
sha = (text9) =>
|
|
164483
|
+
sha = (text9) => createHash41("sha256").update(text9).digest("hex");
|
|
164389
164484
|
ENTITIES = { "&": "&", " ": " ", "<": "<", ">": ">", """: '"', "'": "'" };
|
|
164390
164485
|
MAX_SUFFIX = 24;
|
|
164391
164486
|
ReferenceNames = class {
|
|
@@ -164711,7 +164806,7 @@ var init_store_spec = __esm({
|
|
|
164711
164806
|
|
|
164712
164807
|
// src/iap-config-edit.ts
|
|
164713
164808
|
import { existsSync as existsSync76, readFileSync as readFileSync92 } from "node:fs";
|
|
164714
|
-
import { basename as
|
|
164809
|
+
import { basename as basename21, join as join77 } from "node:path";
|
|
164715
164810
|
import ts8 from "typescript";
|
|
164716
164811
|
function bindPurchasesAppInConfig(source, options) {
|
|
164717
164812
|
const fileName = options.fileName ?? "config.ts";
|
|
@@ -164798,14 +164893,14 @@ function withStoreBundle(dir, options) {
|
|
|
164798
164893
|
function previewIapConfigEdit(dir, options) {
|
|
164799
164894
|
const path2 = configEntry(dir);
|
|
164800
164895
|
if (!path2) return void 0;
|
|
164801
|
-
if (isSymlink2(path2)) return { path: path2, changed: false, applied: [], conflicts: [], instructions: [`${
|
|
164802
|
-
const { changed, applied, conflicts, instructions } = bindPurchasesAppInConfig(readFileSync92(path2, "utf8"), { ...withStoreBundle(dir, options), fileName:
|
|
164896
|
+
if (isSymlink2(path2)) return { path: path2, changed: false, applied: [], conflicts: [], instructions: [`${basename21(path2)} is a symlink, so it would not be edited: add the purchases app in the file it points to.`] };
|
|
164897
|
+
const { changed, applied, conflicts, instructions } = bindPurchasesAppInConfig(readFileSync92(path2, "utf8"), { ...withStoreBundle(dir, options), fileName: basename21(path2) });
|
|
164803
164898
|
return { path: path2, changed, applied, conflicts, instructions };
|
|
164804
164899
|
}
|
|
164805
164900
|
async function applyIapConfigEdit(dir, options, validate5) {
|
|
164806
164901
|
const path2 = configEntry(dir);
|
|
164807
164902
|
if (!path2) return void 0;
|
|
164808
|
-
const fileName =
|
|
164903
|
+
const fileName = basename21(path2);
|
|
164809
164904
|
const refuse7 = (why) => ({ path: path2, changed: false, applied: [], conflicts: [], instructions: [why] });
|
|
164810
164905
|
if (isSymlink2(path2)) return refuse7(`${fileName} is a symlink, so it was not edited: add the purchases app in the file it points to.`);
|
|
164811
164906
|
const original = readFileSync92(path2, "utf8");
|
|
@@ -165265,7 +165360,7 @@ var init_store_iap_connect = __esm({
|
|
|
165265
165360
|
});
|
|
165266
165361
|
|
|
165267
165362
|
// src/store-iap-screenshots.ts
|
|
165268
|
-
import { dirname as dirname41, join as join78, relative as
|
|
165363
|
+
import { dirname as dirname41, join as join78, relative as relative16 } from "node:path";
|
|
165269
165364
|
function purchaseScreensFor(item) {
|
|
165270
165365
|
const screen = item.wix && PURCHASE_SCREENS[item.wix.entityType];
|
|
165271
165366
|
if (!screen || !item.wix) return [];
|
|
@@ -165393,7 +165488,7 @@ async function shoot(selected, run2, outDir) {
|
|
|
165393
165488
|
} catch (e2) {
|
|
165394
165489
|
return { ...report3, skipped: `could not save the screenshot: ${e2.message}` };
|
|
165395
165490
|
}
|
|
165396
|
-
return { ...report3, screenshot:
|
|
165491
|
+
return { ...report3, screenshot: relative16(dirname41(run2.manifestPath), path2) };
|
|
165397
165492
|
}
|
|
165398
165493
|
function visibleText2(html) {
|
|
165399
165494
|
return html.replace(/ | | /gi, "\xA0").replace(/&/g, "&");
|
|
@@ -166669,7 +166764,7 @@ __export(preflight_app_exports, {
|
|
|
166669
166764
|
readXcconfigVars: () => readXcconfigVars
|
|
166670
166765
|
});
|
|
166671
166766
|
import { readFileSync as readFileSync95, existsSync as existsSync78, readdirSync as readdirSync34, statSync as statSync21 } from "node:fs";
|
|
166672
|
-
import { createHash as
|
|
166767
|
+
import { createHash as createHash42 } from "node:crypto";
|
|
166673
166768
|
import { dirname as dirname43, join as join81 } from "node:path";
|
|
166674
166769
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
166675
166770
|
const f2 = [];
|
|
@@ -167050,7 +167145,7 @@ function placeholderHashes2() {
|
|
|
167050
167145
|
const p2 = join81(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
167051
167146
|
try {
|
|
167052
167147
|
if (!statSync21(p2).isFile()) continue;
|
|
167053
|
-
return [LEGACY_PLACEHOLDER_SHA2562,
|
|
167148
|
+
return [LEGACY_PLACEHOLDER_SHA2562, createHash42("sha256").update(readFileSync95(p2)).digest("hex")];
|
|
167054
167149
|
} catch {
|
|
167055
167150
|
}
|
|
167056
167151
|
}
|
|
@@ -167087,7 +167182,7 @@ async function appIconState(iosDir) {
|
|
|
167087
167182
|
try {
|
|
167088
167183
|
if (!statSync21(p2).isFile()) continue;
|
|
167089
167184
|
const bytes2 = readFileSync95(p2);
|
|
167090
|
-
const hash2 =
|
|
167185
|
+
const hash2 = createHash42("sha256").update(bytes2).digest("hex");
|
|
167091
167186
|
const pixels = await pixelIssues(bytes2);
|
|
167092
167187
|
return {
|
|
167093
167188
|
exists: true,
|
|
@@ -167690,7 +167785,7 @@ var init_site_member = __esm({
|
|
|
167690
167785
|
});
|
|
167691
167786
|
|
|
167692
167787
|
// src/notify-ping-all.ts
|
|
167693
|
-
import { createHash as
|
|
167788
|
+
import { createHash as createHash43 } from "node:crypto";
|
|
167694
167789
|
async function listApprovedMembers(input) {
|
|
167695
167790
|
const first = await scanMembers(input);
|
|
167696
167791
|
const second = await scanMembers(input);
|
|
@@ -167744,7 +167839,7 @@ async function scanMembers(input) {
|
|
|
167744
167839
|
}
|
|
167745
167840
|
}
|
|
167746
167841
|
function campaignRequestId(campaignId, memberId) {
|
|
167747
|
-
const bytes2 =
|
|
167842
|
+
const bytes2 = createHash43("sha256").update(JSON.stringify(["himi-push-campaign", campaignId, memberId])).digest().subarray(0, 16);
|
|
167748
167843
|
bytes2[6] = bytes2[6] & 15 | 80;
|
|
167749
167844
|
bytes2[8] = bytes2[8] & 63 | 128;
|
|
167750
167845
|
const hex2 = bytes2.toString("hex");
|
|
@@ -168728,7 +168823,7 @@ __export(generate_exports, {
|
|
|
168728
168823
|
withHeader: () => withHeader,
|
|
168729
168824
|
writeGenerated: () => writeGenerated
|
|
168730
168825
|
});
|
|
168731
|
-
import { createHash as
|
|
168826
|
+
import { createHash as createHash44 } from "node:crypto";
|
|
168732
168827
|
import { existsSync as existsSync80, mkdirSync as mkdirSync38, readdirSync as readdirSync35, readFileSync as readFileSync100, writeFileSync as writeFileSync34 } from "node:fs";
|
|
168733
168828
|
import { dirname as dirname46, join as join84 } from "node:path";
|
|
168734
168829
|
function withHeader(body) {
|
|
@@ -168894,7 +168989,7 @@ var init_generate = __esm({
|
|
|
168894
168989
|
GENERATED_HEADER = "// @generated by himi base44 screens \u2014 sha256:";
|
|
168895
168990
|
HEADER_RE = /^\/\/ @generated by himi base44 screens — sha256:([0-9a-f]{64})\n/;
|
|
168896
168991
|
ENGINE_FILES = ["tier5-src/_shared/entity-list.ts", "tier5-src/_shared/entity-detail.ts", "tier5-src/_shared/entity-plan.ts", "dev/entity-screens.ts"];
|
|
168897
|
-
sha2566 = (s2) =>
|
|
168992
|
+
sha2566 = (s2) => createHash44("sha256").update(s2).digest("hex");
|
|
168898
168993
|
planFile = (p2) => `${p2.ids.bundleDetail}-plan`;
|
|
168899
168994
|
ident = (p2) => `plan_${p2.ids.detail.replace(/^b44_/, "")}`;
|
|
168900
168995
|
json7 = (v2) => JSON.stringify(v2, null, 2);
|
|
@@ -172272,9 +172367,9 @@ function tokensFromWst(wst) {
|
|
|
172272
172367
|
if (surface2) colors.surfaceSecondary = { light: surface2 };
|
|
172273
172368
|
const opaque = (c2) => c2 && c2.length === 7 ? c2 : void 0;
|
|
172274
172369
|
const surface = opaque(usableCssColor(wst["--wst-color-fill-base-1"]));
|
|
172275
|
-
const ramp = !surface ? [] : ["--wst-color-fill-base-shade-1", "--wst-color-fill-base-shade-2", "--wst-color-fill-base-shade-3"].map((v2) => opaque(usableCssColor(wst[v2]))).filter((c2) => !!c2).map((c2) => ({ c: c2, ratio:
|
|
172370
|
+
const ramp = !surface ? [] : ["--wst-color-fill-base-shade-1", "--wst-color-fill-base-shade-2", "--wst-color-fill-base-shade-3"].map((v2) => opaque(usableCssColor(wst[v2]))).filter((c2) => !!c2).map((c2) => ({ c: c2, ratio: contrastRatio2(c2, surface) }));
|
|
172276
172371
|
const primary = surface ? opaque(usableCssColor(wst["--wst-color-text-primary"])) : void 0;
|
|
172277
|
-
const primaryRatio = primary && surface ?
|
|
172372
|
+
const primaryRatio = primary && surface ? contrastRatio2(primary, surface) : void 0;
|
|
172278
172373
|
const tertiary = primaryRatio === void 0 ? void 0 : ramp.filter((x2) => x2.ratio >= 4.5 && x2.ratio < primaryRatio).sort((a2, b2) => a2.ratio - b2.ratio)[0];
|
|
172279
172374
|
if (tertiary) colors.textTertiary = { light: tertiary.c };
|
|
172280
172375
|
const border = ramp.filter((x2) => x2.ratio >= 1.3 && x2.ratio <= 3).sort((a2, b2) => a2.ratio - b2.ratio)[0];
|
|
@@ -177074,7 +177169,7 @@ var init_errors2 = __esm({
|
|
|
177074
177169
|
});
|
|
177075
177170
|
|
|
177076
177171
|
// src/one-app/collect.ts
|
|
177077
|
-
import { createHash as
|
|
177172
|
+
import { createHash as createHash45 } from "node:crypto";
|
|
177078
177173
|
function isObject2(value) {
|
|
177079
177174
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
177080
177175
|
}
|
|
@@ -177146,7 +177241,7 @@ function semanticFingerprint(structure) {
|
|
|
177146
177241
|
}
|
|
177147
177242
|
return JSON.stringify(value);
|
|
177148
177243
|
};
|
|
177149
|
-
return
|
|
177244
|
+
return createHash45("sha256").update(canonical6(structure, true)).digest("hex");
|
|
177150
177245
|
}
|
|
177151
177246
|
async function collectOneApp(input, deps = {}) {
|
|
177152
177247
|
if (typeof input.metaSiteId !== "string" || !UUID.test(input.metaSiteId)) {
|
|
@@ -177358,7 +177453,7 @@ var init_collect = __esm({
|
|
|
177358
177453
|
});
|
|
177359
177454
|
|
|
177360
177455
|
// src/one-app/validate-topbar.ts
|
|
177361
|
-
import { createHash as
|
|
177456
|
+
import { createHash as createHash46 } from "node:crypto";
|
|
177362
177457
|
import { readFileSync as readFileSync105, statSync as statSync22 } from "node:fs";
|
|
177363
177458
|
import { resolve as resolve62, join as join92 } from "node:path";
|
|
177364
177459
|
import ts9 from "typescript";
|
|
@@ -177516,7 +177611,7 @@ function validate4(evidenceDir, contentDir2) {
|
|
|
177516
177611
|
if (typeof expectedHash !== "string" || !/^[a-f0-9]{64}$/i.test(expectedHash)) {
|
|
177517
177612
|
throw new Error("manifest.json is missing a valid raw-structure.json hash.");
|
|
177518
177613
|
}
|
|
177519
|
-
if (
|
|
177614
|
+
if (createHash46("sha256").update(rawBytes).digest("hex") !== expectedHash) {
|
|
177520
177615
|
throw new Error("raw-structure.json does not match the hash recorded in manifest.json.");
|
|
177521
177616
|
}
|
|
177522
177617
|
source = authoredControls(JSON.parse(rawBytes.toString("utf8")));
|
|
@@ -177993,7 +178088,7 @@ __export(cli_exports2, {
|
|
|
177993
178088
|
runOneAppCommand: () => runOneAppCommand
|
|
177994
178089
|
});
|
|
177995
178090
|
import { closeSync as closeSync7, constants as constants4, lstatSync as lstatSync22, mkdirSync as mkdirSync43, openSync as openSync6, readFileSync as readFileSync106, realpathSync as realpathSync14, writeFileSync as writeFileSync41 } from "node:fs";
|
|
177996
|
-
import { createHash as
|
|
178091
|
+
import { createHash as createHash47 } from "node:crypto";
|
|
177997
178092
|
import { dirname as dirname49, join as join93, parse as parse3, resolve as resolve63 } from "node:path";
|
|
177998
178093
|
function readOptions(argv, cwd, commandIncluded) {
|
|
177999
178094
|
let cursor = 0;
|
|
@@ -178134,7 +178229,7 @@ validate-topbar checks authored source top-bar controls against the migrated con
|
|
|
178134
178229
|
throw new OneAppError("artifact_write_failed", "Could not save the migration evidence. Existing files were kept.", { stage });
|
|
178135
178230
|
}
|
|
178136
178231
|
artifacts[name] = path2;
|
|
178137
|
-
hashes[name] =
|
|
178232
|
+
hashes[name] = createHash47("sha256").update(content).digest("hex");
|
|
178138
178233
|
return path2;
|
|
178139
178234
|
};
|
|
178140
178235
|
const progress = (nextStage) => {
|
|
@@ -182933,9 +183028,9 @@ var init_context = __esm({
|
|
|
182933
183028
|
import { mkdtempSync as mkdtempSync6, readFileSync as readFileSync110, mkdirSync as mkdirSync45, writeFileSync as writeFileSync44, existsSync as existsSync89, rmSync as rmSync24, readdirSync as readdirSync36, statSync as statSync24, lstatSync as lstatSync23, accessSync, constants as constants5, renameSync as renameSync13, cpSync as cpSync3 } from "node:fs";
|
|
182934
183029
|
import { execFile as execFile2, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
|
|
182935
183030
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
182936
|
-
import { createHash as
|
|
183031
|
+
import { createHash as createHash48, randomUUID as randomUUID11 } from "node:crypto";
|
|
182937
183032
|
import { tmpdir as tmpdir7, homedir as homedir15, hostname as hostname2 } from "node:os";
|
|
182938
|
-
import { join as join95, resolve as resolve66, relative as
|
|
183033
|
+
import { join as join95, resolve as resolve66, relative as relative17, basename as basename22, dirname as dirname51 } from "node:path";
|
|
182939
183034
|
import { fileURLToPath as fileURLToPath30 } from "node:url";
|
|
182940
183035
|
|
|
182941
183036
|
// ../serve-cli/src/client.ts
|
|
@@ -187164,7 +187259,7 @@ function shellShaDivergenceWarnings(jobs) {
|
|
|
187164
187259
|
}
|
|
187165
187260
|
async function templatePublishName(sourceDir) {
|
|
187166
187261
|
const id = await appId(sourceDir);
|
|
187167
|
-
return IDENTITY_SENTINELS.some((s2) => id.includes(s2)) ?
|
|
187262
|
+
return IDENTITY_SENTINELS.some((s2) => id.includes(s2)) ? basename22(sourceDir) : id;
|
|
187168
187263
|
}
|
|
187169
187264
|
function templateNameError(name, from) {
|
|
187170
187265
|
if (name.startsWith(TEMPLATE_APP_PREFIX)) {
|
|
@@ -187224,7 +187319,7 @@ async function appId(dir) {
|
|
|
187224
187319
|
if (m2.name) return m2.name;
|
|
187225
187320
|
} catch {
|
|
187226
187321
|
}
|
|
187227
|
-
return
|
|
187322
|
+
return basename22(dir);
|
|
187228
187323
|
}
|
|
187229
187324
|
async function contentVisibility(dir) {
|
|
187230
187325
|
try {
|
|
@@ -188547,7 +188642,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
188547
188642
|
try {
|
|
188548
188643
|
const bytes2 = readFileSync110(iconPath);
|
|
188549
188644
|
payload.icon = bytes2.toString("base64");
|
|
188550
|
-
iconHash =
|
|
188645
|
+
iconHash = createHash48("sha256").update(bytes2).digest("hex");
|
|
188551
188646
|
} catch {
|
|
188552
188647
|
}
|
|
188553
188648
|
}
|
|
@@ -189031,7 +189126,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
189031
189126
|
const { openUrl: openUrl2 } = await Promise.resolve().then(() => (init_open_url(), open_url_exports));
|
|
189032
189127
|
openUrl2(url2);
|
|
189033
189128
|
}
|
|
189034
|
-
const handover = { file: out2, hint: `hand ${
|
|
189129
|
+
const handover = { file: out2, hint: `hand ${basename22(out2)} to the owner at the handover \u2014 one self-contained page of their app taking shape; send it beside the preview link, never instead of it` };
|
|
189035
189130
|
const report3 = {
|
|
189036
189131
|
ok: true,
|
|
189037
189132
|
file: out2,
|
|
@@ -190364,7 +190459,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
190364
190459
|
const manifest = outcome.manifest;
|
|
190365
190460
|
const payload = await loadReleaseFromDir(declared, out2);
|
|
190366
190461
|
const { shellQuote: shellQuote3 } = await Promise.resolve().then(() => (init_shell_quote(), shell_quote_exports));
|
|
190367
|
-
const contentRel =
|
|
190462
|
+
const contentRel = relative17(process.cwd(), dir) || ".";
|
|
190368
190463
|
const contentArg2 = shellQuote3(contentRel);
|
|
190369
190464
|
if (onlyRaw !== void 0) {
|
|
190370
190465
|
const onlyDraft = flags.draft === true;
|
|
@@ -190426,7 +190521,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
190426
190521
|
let localSourceHash;
|
|
190427
190522
|
try {
|
|
190428
190523
|
const { collectAppSource: collectAppSource2, zipAppSource: zipAppSource2 } = await Promise.resolve().then(() => (init_app_source(), app_source_exports));
|
|
190429
|
-
localSourceHash =
|
|
190524
|
+
localSourceHash = createHash48("sha256").update(zipAppSource2(collectAppSource2(dir).entries).toString("base64")).digest("hex");
|
|
190430
190525
|
} catch {
|
|
190431
190526
|
}
|
|
190432
190527
|
return runReleasePatch({
|
|
@@ -192115,7 +192210,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
192115
192210
|
});
|
|
192116
192211
|
}
|
|
192117
192212
|
const bytes2 = readFileSync110(file2);
|
|
192118
|
-
const sha2 =
|
|
192213
|
+
const sha2 = createHash48("sha256").update(bytes2).digest("hex");
|
|
192119
192214
|
const forScreens = (str10(flags["for-screen"]) ?? "").split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
192120
192215
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
192121
192216
|
io2.error(JSON.stringify({ ok: false, error: "no_rebind_takes_no_value", message: "--no-rebind is a switch and takes no value; pass it bare.", usage: PATCH_USAGE }));
|