@wix/himalaya-cli 0.808.0 → 0.810.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 +1287 -482
- package/guides/himi-test.md +46 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -807,7 +807,13 @@ var init_source_deny = __esm({
|
|
|
807
807
|
/^\.env\./,
|
|
808
808
|
/^\.DS_Store$/,
|
|
809
809
|
/^id_rsa($|\.)/,
|
|
810
|
-
/\.(pem|p8|p12|keystore|jks|mobileprovision)$/i
|
|
810
|
+
/\.(pem|p8|p12|keystore|jks|mobileprovision)$/i,
|
|
811
|
+
// `.git` IS NOT ALWAYS A DIRECTORY. In a linked worktree or a submodule it is a FILE holding
|
|
812
|
+
// `gitdir: …`, and DENY_DIRS is consulted for directories only — so at a package root it was
|
|
813
|
+
// denied by nothing: `himi push` archived the pointer, and `himi pull --replace` would delete
|
|
814
|
+
// it back out of a checkout whose release predates it (#2437). The guarantee that a restore
|
|
815
|
+
// cannot cost you a git history has to hold for both shapes of `.git`, not just the common one.
|
|
816
|
+
/^\.git$/
|
|
811
817
|
];
|
|
812
818
|
}
|
|
813
819
|
});
|
|
@@ -1014,7 +1020,7 @@ function sentinelizeIdentity(body, identity) {
|
|
|
1014
1020
|
}
|
|
1015
1021
|
if (identity.name) {
|
|
1016
1022
|
const re = new RegExp(`\\b(${NAME_FIELDS.join("|")})(["']?\\s*[:=]\\s*)(["'])${escapeRe(identity.name)}\\3`, "g");
|
|
1017
|
-
out = out.replace(re, (_m, key2,
|
|
1023
|
+
out = out.replace(re, (_m, key2, sep11, q) => `${key2}${sep11}${q}__HIMI_APP_NAME__${q}`);
|
|
1018
1024
|
}
|
|
1019
1025
|
return out;
|
|
1020
1026
|
}
|
|
@@ -1954,7 +1960,7 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
|
|
|
1954
1960
|
tokenCache.set(cacheKey, fromEnv);
|
|
1955
1961
|
return fromEnv;
|
|
1956
1962
|
}
|
|
1957
|
-
const token = await new Promise((
|
|
1963
|
+
const token = await new Promise((resolve41, reject) => {
|
|
1958
1964
|
let child;
|
|
1959
1965
|
try {
|
|
1960
1966
|
child = spawnImpl("wix", [...args]);
|
|
@@ -1983,12 +1989,12 @@ async function mintToken(args, label2, cacheKey, spawnImpl) {
|
|
|
1983
1989
|
child.stdout?.on("data", (d) => {
|
|
1984
1990
|
out += String(d);
|
|
1985
1991
|
const m = out.match(TOKEN_RE);
|
|
1986
|
-
if (m) done(() =>
|
|
1992
|
+
if (m) done(() => resolve41(m[0]));
|
|
1987
1993
|
});
|
|
1988
1994
|
child.stderr?.on("data", (d) => {
|
|
1989
1995
|
out += String(d);
|
|
1990
1996
|
const m = out.match(TOKEN_RE);
|
|
1991
|
-
if (m) done(() =>
|
|
1997
|
+
if (m) done(() => resolve41(m[0]));
|
|
1992
1998
|
});
|
|
1993
1999
|
child.on("error", (e) => done(() => reject(new Error(mintHelp(label2, e.message)))));
|
|
1994
2000
|
child.on("exit", (code) => done(() => reject(new Error(
|
|
@@ -2496,8 +2502,8 @@ var init_splash = __esm({
|
|
|
2496
2502
|
|
|
2497
2503
|
// ../../core/dev-server/tier5-bundles-src/build-lib.mjs
|
|
2498
2504
|
import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
2499
|
-
import { dirname as dirname8, resolve as resolve8 } from "node:path";
|
|
2500
|
-
import { readdirSync as readdirSync6, existsSync as existsSync8, readFileSync as readFileSync10 } from "node:fs";
|
|
2505
|
+
import { dirname as dirname8, join as join12, resolve as resolve8, sep as sep2 } from "node:path";
|
|
2506
|
+
import { readdirSync as readdirSync6, existsSync as existsSync8, readFileSync as readFileSync10, realpathSync as realpathSync2, statSync as statSync2 } from "node:fs";
|
|
2501
2507
|
async function loadCompiler() {
|
|
2502
2508
|
try {
|
|
2503
2509
|
const nativeCompiler = ["es", "build"].join("");
|
|
@@ -2530,6 +2536,259 @@ function isOffRepo() {
|
|
|
2530
2536
|
if (process.env.HIMI_OFF_REPO === "1") return true;
|
|
2531
2537
|
return !existsSync8(alias["@himalaya/state"]);
|
|
2532
2538
|
}
|
|
2539
|
+
function buildConfinementRequired() {
|
|
2540
|
+
return _confinementRequired;
|
|
2541
|
+
}
|
|
2542
|
+
function realpathOrSelf(p) {
|
|
2543
|
+
try {
|
|
2544
|
+
return realpathSync2(resolve8(p));
|
|
2545
|
+
} catch {
|
|
2546
|
+
return resolve8(p);
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
function isUnder(p, root) {
|
|
2550
|
+
return p === root || p.startsWith(root + sep2);
|
|
2551
|
+
}
|
|
2552
|
+
function confinementRoots(contentRoot) {
|
|
2553
|
+
const roots = /* @__PURE__ */ new Set();
|
|
2554
|
+
const add = (p) => {
|
|
2555
|
+
if (!p) return;
|
|
2556
|
+
roots.add(realpathOrSelf(p));
|
|
2557
|
+
roots.add(resolve8(p));
|
|
2558
|
+
};
|
|
2559
|
+
const real = realpathOrSelf(contentRoot);
|
|
2560
|
+
add(real);
|
|
2561
|
+
for (let d = real, up; ; d = up) {
|
|
2562
|
+
add(join12(d, "node_modules"));
|
|
2563
|
+
up = dirname8(d);
|
|
2564
|
+
if (up === d) break;
|
|
2565
|
+
}
|
|
2566
|
+
add(process.env.HIMI_AUTHORING_RUNTIME_DIR);
|
|
2567
|
+
add(process.env.HIMI_CLI_RUNTIME_DIR);
|
|
2568
|
+
if (!isOffRepo()) add(REPO_ROOT4);
|
|
2569
|
+
return [...roots];
|
|
2570
|
+
}
|
|
2571
|
+
function confinementMatcher(contentRoot, extraRoots = []) {
|
|
2572
|
+
const roots = [...confinementRoots(contentRoot), ...extraRoots.filter(Boolean).flatMap((r) => [realpathOrSelf(r), resolve8(r)])];
|
|
2573
|
+
let linked;
|
|
2574
|
+
const linkedRoots = () => {
|
|
2575
|
+
if (linked) return linked;
|
|
2576
|
+
linked = [];
|
|
2577
|
+
const scanned = /* @__PURE__ */ new Set();
|
|
2578
|
+
const queue = [...roots];
|
|
2579
|
+
const CAP3 = 4096;
|
|
2580
|
+
const take = (abs) => {
|
|
2581
|
+
const target = realpathOrSelf(abs);
|
|
2582
|
+
if (scanned.has(target) || linked.length >= CAP3) return;
|
|
2583
|
+
linked.push(target);
|
|
2584
|
+
queue.push(target);
|
|
2585
|
+
};
|
|
2586
|
+
while (queue.length && linked.length < CAP3) {
|
|
2587
|
+
const r = queue.shift();
|
|
2588
|
+
for (const nm of [r, join12(r, "node_modules")]) {
|
|
2589
|
+
if (scanned.has(nm)) continue;
|
|
2590
|
+
scanned.add(nm);
|
|
2591
|
+
let entries;
|
|
2592
|
+
try {
|
|
2593
|
+
entries = readdirSync6(nm, { withFileTypes: true });
|
|
2594
|
+
} catch {
|
|
2595
|
+
continue;
|
|
2596
|
+
}
|
|
2597
|
+
for (const e of entries) {
|
|
2598
|
+
const abs = join12(nm, e.name);
|
|
2599
|
+
if (e.isSymbolicLink()) take(abs);
|
|
2600
|
+
else if (e.isDirectory() && e.name.startsWith("@")) {
|
|
2601
|
+
let scoped;
|
|
2602
|
+
try {
|
|
2603
|
+
scoped = readdirSync6(abs, { withFileTypes: true });
|
|
2604
|
+
} catch {
|
|
2605
|
+
continue;
|
|
2606
|
+
}
|
|
2607
|
+
for (const sc of scoped) if (sc.isSymbolicLink()) take(join12(abs, sc.name));
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
return linked;
|
|
2613
|
+
};
|
|
2614
|
+
return (p) => {
|
|
2615
|
+
const direct = resolve8(p);
|
|
2616
|
+
if (roots.some((r) => isUnder(direct, r))) return true;
|
|
2617
|
+
const real = realpathOrSelf(direct);
|
|
2618
|
+
if (real !== direct && roots.some((r) => isUnder(real, r))) return true;
|
|
2619
|
+
return linkedRoots().some((r) => isUnder(real, r) || isUnder(direct, r));
|
|
2620
|
+
};
|
|
2621
|
+
}
|
|
2622
|
+
function confinementPlugin(contentRoot) {
|
|
2623
|
+
const allows = confinementMatcher(contentRoot);
|
|
2624
|
+
return {
|
|
2625
|
+
name: "himalaya-confine-import-graph",
|
|
2626
|
+
setup(b) {
|
|
2627
|
+
b.onResolve({ filter: /^[./]/ }, (args) => {
|
|
2628
|
+
const base = args.path.startsWith("/") ? args.path : args.resolveDir ? resolve8(args.resolveDir, args.path) : void 0;
|
|
2629
|
+
if (!base || allows(base)) return void 0;
|
|
2630
|
+
return {
|
|
2631
|
+
errors: [{
|
|
2632
|
+
text: `refused to resolve ${args.path}: it is outside this content package. A worker or app config may import files from its own package, the Himalaya SDK, and its installed dependencies \u2014 nothing else.`
|
|
2633
|
+
}]
|
|
2634
|
+
};
|
|
2635
|
+
});
|
|
2636
|
+
b.onLoad({ filter: /.*/ }, (args) => {
|
|
2637
|
+
if (args.namespace && args.namespace !== "file") return void 0;
|
|
2638
|
+
if (allows(args.path)) return void 0;
|
|
2639
|
+
return {
|
|
2640
|
+
errors: [{
|
|
2641
|
+
text: `refused to read ${args.path}: it is outside this content package. A worker or app config may import files from its own package, the Himalaya SDK, and its installed dependencies \u2014 nothing else.`
|
|
2642
|
+
}]
|
|
2643
|
+
};
|
|
2644
|
+
});
|
|
2645
|
+
}
|
|
2646
|
+
};
|
|
2647
|
+
}
|
|
2648
|
+
function assertConfinedTsconfig(entry, contentRoot, allows) {
|
|
2649
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2650
|
+
const refuse = (p, why) => {
|
|
2651
|
+
throw new Error(
|
|
2652
|
+
`refused to read ${p}: ${why}. A tsconfig may extend a file from its own package or an installed dependency \u2014 nothing else.`
|
|
2653
|
+
);
|
|
2654
|
+
};
|
|
2655
|
+
const stripJsonc = (text2) => {
|
|
2656
|
+
if (text2.charCodeAt(0) === 65279) text2 = text2.slice(1);
|
|
2657
|
+
let out = "";
|
|
2658
|
+
let inStr = false;
|
|
2659
|
+
let esc = false;
|
|
2660
|
+
for (let i = 0; i < text2.length; i++) {
|
|
2661
|
+
const c = text2[i];
|
|
2662
|
+
if (inStr) {
|
|
2663
|
+
out += c;
|
|
2664
|
+
if (esc) esc = false;
|
|
2665
|
+
else if (c === "\\") esc = true;
|
|
2666
|
+
else if (c === '"') inStr = false;
|
|
2667
|
+
continue;
|
|
2668
|
+
}
|
|
2669
|
+
if (c === '"') {
|
|
2670
|
+
inStr = true;
|
|
2671
|
+
out += c;
|
|
2672
|
+
continue;
|
|
2673
|
+
}
|
|
2674
|
+
if (c === "/" && text2[i + 1] === "/") {
|
|
2675
|
+
while (i < text2.length && text2[i] !== "\n") i++;
|
|
2676
|
+
continue;
|
|
2677
|
+
}
|
|
2678
|
+
if (c === "/" && text2[i + 1] === "*") {
|
|
2679
|
+
i += 2;
|
|
2680
|
+
while (i < text2.length && !(text2[i] === "*" && text2[i + 1] === "/")) i++;
|
|
2681
|
+
i++;
|
|
2682
|
+
continue;
|
|
2683
|
+
}
|
|
2684
|
+
if (c === "}" || c === "]") {
|
|
2685
|
+
const trimmed = out.replace(/\s+$/, "");
|
|
2686
|
+
if (trimmed.endsWith(",")) out = trimmed.slice(0, -1);
|
|
2687
|
+
}
|
|
2688
|
+
out += c;
|
|
2689
|
+
}
|
|
2690
|
+
return out;
|
|
2691
|
+
};
|
|
2692
|
+
const isFile = (p) => {
|
|
2693
|
+
try {
|
|
2694
|
+
return statSync2(p).isFile();
|
|
2695
|
+
} catch {
|
|
2696
|
+
return false;
|
|
2697
|
+
}
|
|
2698
|
+
};
|
|
2699
|
+
const asConfigFile = (t) => {
|
|
2700
|
+
if (isFile(t)) return t;
|
|
2701
|
+
const inDir = join12(t, "tsconfig.json");
|
|
2702
|
+
if (isFile(inDir)) return inDir;
|
|
2703
|
+
if (isFile(`${t}.json`)) return `${t}.json`;
|
|
2704
|
+
return t;
|
|
2705
|
+
};
|
|
2706
|
+
const resolveBare = (spec, fromDir) => {
|
|
2707
|
+
for (let d = fromDir, up; ; d = up) {
|
|
2708
|
+
const base = join12(d, "node_modules", spec);
|
|
2709
|
+
for (const cand of [base, `${base}.json`]) if (isFile(cand)) return cand;
|
|
2710
|
+
const pj = join12(base, "package.json");
|
|
2711
|
+
if (isFile(pj)) {
|
|
2712
|
+
let manifest;
|
|
2713
|
+
try {
|
|
2714
|
+
manifest = JSON.parse(stripJsonc(readFileSync10(pj, "utf8")));
|
|
2715
|
+
} catch {
|
|
2716
|
+
refuse(pj, "its package.json could not be parsed, so its `tsconfig` field cannot be checked");
|
|
2717
|
+
}
|
|
2718
|
+
const field = manifest?.tsconfig;
|
|
2719
|
+
if (typeof field === "string" && field) {
|
|
2720
|
+
return asConfigFile(field.startsWith("/") ? field : resolve8(base, field));
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
if (isFile(join12(base, "tsconfig.json"))) return join12(base, "tsconfig.json");
|
|
2724
|
+
up = dirname8(d);
|
|
2725
|
+
if (up === d) return void 0;
|
|
2726
|
+
}
|
|
2727
|
+
};
|
|
2728
|
+
const follow = (file) => {
|
|
2729
|
+
const real = realpathOrSelf(file);
|
|
2730
|
+
if (seen.has(real)) return;
|
|
2731
|
+
seen.add(real);
|
|
2732
|
+
if (!allows(real)) refuse(file, "it is outside this content package");
|
|
2733
|
+
let raw;
|
|
2734
|
+
try {
|
|
2735
|
+
raw = readFileSync10(real, "utf8");
|
|
2736
|
+
} catch {
|
|
2737
|
+
return;
|
|
2738
|
+
}
|
|
2739
|
+
let parsed;
|
|
2740
|
+
try {
|
|
2741
|
+
parsed = JSON.parse(stripJsonc(raw));
|
|
2742
|
+
} catch {
|
|
2743
|
+
refuse(file, "its tsconfig could not be parsed, so its `extends` cannot be checked");
|
|
2744
|
+
}
|
|
2745
|
+
const ext = parsed?.extends;
|
|
2746
|
+
for (const one of Array.isArray(ext) ? ext : ext ? [ext] : []) {
|
|
2747
|
+
if (typeof one !== "string" || !one) continue;
|
|
2748
|
+
if (one.startsWith(".") || one.startsWith("/")) {
|
|
2749
|
+
const target = asConfigFile(one.startsWith("/") ? one : resolve8(dirname8(real), one));
|
|
2750
|
+
if (target) follow(target);
|
|
2751
|
+
} else {
|
|
2752
|
+
const target = resolveBare(one, dirname8(real));
|
|
2753
|
+
if (target) follow(target);
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
};
|
|
2757
|
+
const scan = (dir) => {
|
|
2758
|
+
let entries;
|
|
2759
|
+
try {
|
|
2760
|
+
entries = readdirSync6(dir, { withFileTypes: true });
|
|
2761
|
+
} catch {
|
|
2762
|
+
return;
|
|
2763
|
+
}
|
|
2764
|
+
for (const e of entries) {
|
|
2765
|
+
const abs = join12(dir, e.name);
|
|
2766
|
+
if (e.isDirectory()) scan(abs);
|
|
2767
|
+
else if (e.name === "tsconfig.json" && e.isFile()) follow(abs);
|
|
2768
|
+
}
|
|
2769
|
+
};
|
|
2770
|
+
scan(realpathOrSelf(contentRoot));
|
|
2771
|
+
for (let d = dirname8(realpathOrSelf(entry)), up; ; d = up) {
|
|
2772
|
+
const cfg = join12(d, "tsconfig.json");
|
|
2773
|
+
if (existsSync8(cfg)) {
|
|
2774
|
+
follow(cfg);
|
|
2775
|
+
return;
|
|
2776
|
+
}
|
|
2777
|
+
up = dirname8(d);
|
|
2778
|
+
if (up === d) return;
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
function confinementFor(contentRoot, where, entry) {
|
|
2782
|
+
if (!_confinementRequired) return void 0;
|
|
2783
|
+
if (!contentRoot) {
|
|
2784
|
+
throw new Error(
|
|
2785
|
+
`${where}: this process compiles untrusted uploads (requireBuildConfinement) but no content root was given, so the import graph would be unconfined. Pass \`confineTo: <content dir>\`.`
|
|
2786
|
+
);
|
|
2787
|
+
}
|
|
2788
|
+
const allows = confinementMatcher(contentRoot);
|
|
2789
|
+
if (entry) assertConfinedTsconfig(entry, contentRoot, allows);
|
|
2790
|
+
return confinementPlugin(contentRoot);
|
|
2791
|
+
}
|
|
2533
2792
|
function umbrellaRewritePlugin({ external = false } = {}) {
|
|
2534
2793
|
return {
|
|
2535
2794
|
name: "himalaya-umbrella-rewrite",
|
|
@@ -2597,7 +2856,8 @@ function importMetaUrlPlugin() {
|
|
|
2597
2856
|
};
|
|
2598
2857
|
}
|
|
2599
2858
|
async function buildBundleFromEntry(entry, outfile, opts = {}) {
|
|
2600
|
-
const { resolution = "source", name = "bundle", absWorkingDir = REPO_ROOT4 } = opts;
|
|
2859
|
+
const { resolution = "source", name = "bundle", absWorkingDir = REPO_ROOT4, confineTo } = opts;
|
|
2860
|
+
const confine = confinementFor(confineTo, "buildBundleFromEntry", entry);
|
|
2601
2861
|
if (!existsSync8(entry)) throw new Error(`no bundle entry: ${entry}`);
|
|
2602
2862
|
const buildOpts = {
|
|
2603
2863
|
entryPoints: [entry],
|
|
@@ -2620,11 +2880,13 @@ async function buildBundleFromEntry(entry, outfile, opts = {}) {
|
|
|
2620
2880
|
else if (isOffRepo()) {
|
|
2621
2881
|
buildOpts.plugins = process.env.HIMI_CLI_RUNTIME_DIR ? [cliRuntimeUmbrellaPlugin()] : [umbrellaRewritePlugin({ external: false })];
|
|
2622
2882
|
}
|
|
2883
|
+
if (confine) buildOpts.plugins = [confine, ...buildOpts.plugins ?? []];
|
|
2623
2884
|
await build(buildOpts);
|
|
2624
2885
|
return outfile;
|
|
2625
2886
|
}
|
|
2626
2887
|
async function buildAppEntry(entry, outfile, opts = {}) {
|
|
2627
|
-
const { umbrella = false, resolveTsExtensions = false, absWorkingDir = REPO_ROOT4 } = opts;
|
|
2888
|
+
const { umbrella = false, resolveTsExtensions = false, absWorkingDir = REPO_ROOT4, confineTo } = opts;
|
|
2889
|
+
const confine = confinementFor(confineTo, "buildAppEntry", entry);
|
|
2628
2890
|
if (!existsSync8(entry)) throw new Error(`unknown app entry: ${entry}`);
|
|
2629
2891
|
await build({
|
|
2630
2892
|
entryPoints: [entry],
|
|
@@ -2648,6 +2910,9 @@ async function buildAppEntry(entry, outfile, opts = {}) {
|
|
|
2648
2910
|
// -- a single global `define` here pinned the whole graph to the entry and broke
|
|
2649
2911
|
// every app whose config.ts reads a file relative to itself.
|
|
2650
2912
|
plugins: [
|
|
2913
|
+
// FIRST, and here it is load-bearing: `importMetaUrlPlugin` registers an onLoad and CLAIMS
|
|
2914
|
+
// every file containing `import.meta.url`, so a confinement behind it would never see them.
|
|
2915
|
+
...confine ? [confine] : [],
|
|
2651
2916
|
importMetaUrlPlugin(),
|
|
2652
2917
|
...resolveTsExtensions ? [tsExtResolvePlugin()] : [],
|
|
2653
2918
|
...process.env.HIMI_CLI_RUNTIME_DIR ? [cliRuntimeUmbrellaPlugin()] : [],
|
|
@@ -2656,7 +2921,7 @@ async function buildAppEntry(entry, outfile, opts = {}) {
|
|
|
2656
2921
|
});
|
|
2657
2922
|
return outfile;
|
|
2658
2923
|
}
|
|
2659
|
-
var _compilerP, __dirname, REPO_ROOT4, SDK, alias, sourceAliases, OUT_DIR, HERMES_SAFE_SUPPORTED, HERMES_UNSAFE_BUNDLES, APP_ENTRY_TARGET;
|
|
2924
|
+
var _compilerP, __dirname, REPO_ROOT4, SDK, alias, sourceAliases, OUT_DIR, HERMES_SAFE_SUPPORTED, HERMES_UNSAFE_BUNDLES, _confinementRequired, APP_ENTRY_TARGET;
|
|
2660
2925
|
var init_build_lib = __esm({
|
|
2661
2926
|
"../../core/dev-server/tier5-bundles-src/build-lib.mjs"() {
|
|
2662
2927
|
"use strict";
|
|
@@ -2805,6 +3070,7 @@ var init_build_lib = __esm({
|
|
|
2805
3070
|
// worker-safe wix-auth showcase pulls ~11 classes from stdlib/auth-providers.
|
|
2806
3071
|
"demo-app-wix-platform"
|
|
2807
3072
|
]);
|
|
3073
|
+
_confinementRequired = false;
|
|
2808
3074
|
APP_ENTRY_TARGET = ["node18"];
|
|
2809
3075
|
}
|
|
2810
3076
|
});
|
|
@@ -2829,7 +3095,7 @@ var init_tier5_dir = __esm({
|
|
|
2829
3095
|
|
|
2830
3096
|
// src/tier5-typecheck.ts
|
|
2831
3097
|
import { existsSync as existsSync9, readFileSync as readFileSync11 } from "node:fs";
|
|
2832
|
-
import { relative as relative2, resolve as resolve10, sep as
|
|
3098
|
+
import { relative as relative2, resolve as resolve10, sep as sep3 } from "node:path";
|
|
2833
3099
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
2834
3100
|
async function loadTypeScript() {
|
|
2835
3101
|
const runtime = process.env.HIMI_AUTHORING_RUNTIME_DIR;
|
|
@@ -2868,7 +3134,7 @@ function pathsFor(options) {
|
|
|
2868
3134
|
return declarationPaths(options.umbrellaDir);
|
|
2869
3135
|
}
|
|
2870
3136
|
function relativeFile(contentDir2, fileName) {
|
|
2871
|
-
return relative2(contentDir2, fileName).split(
|
|
3137
|
+
return relative2(contentDir2, fileName).split(sep3).join("/");
|
|
2872
3138
|
}
|
|
2873
3139
|
function belongsToContentWorkers(contentDir2, diagnostic) {
|
|
2874
3140
|
if (!diagnostic.file) return true;
|
|
@@ -2890,6 +3156,19 @@ function toIssue(ts, contentDir2, diagnostic) {
|
|
|
2890
3156
|
message: ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")
|
|
2891
3157
|
};
|
|
2892
3158
|
}
|
|
3159
|
+
function confinedHost(ts, contentDir2, options) {
|
|
3160
|
+
if (!buildConfinementRequired()) return void 0;
|
|
3161
|
+
const host = ts.createCompilerHost(options);
|
|
3162
|
+
const libDir = resolve10(ts.getDefaultLibFilePath(options), "..");
|
|
3163
|
+
const allows = confinementMatcher(contentDir2, [libDir]);
|
|
3164
|
+
const getSourceFile = host.getSourceFile.bind(host);
|
|
3165
|
+
const readFile3 = host.readFile.bind(host);
|
|
3166
|
+
const fileExists = host.fileExists.bind(host);
|
|
3167
|
+
host.getSourceFile = (fileName, ...rest) => allows(fileName) ? getSourceFile(fileName, ...rest) : void 0;
|
|
3168
|
+
host.readFile = (fileName) => allows(fileName) ? readFile3(fileName) : void 0;
|
|
3169
|
+
host.fileExists = (fileName) => allows(fileName) && fileExists(fileName);
|
|
3170
|
+
return host;
|
|
3171
|
+
}
|
|
2893
3172
|
async function typecheckContentWorkers(contentDir2, options) {
|
|
2894
3173
|
if (!existsSync9(resolve10(contentDir2, "tier5-src"))) return [];
|
|
2895
3174
|
const ts = await compiler2();
|
|
@@ -2907,7 +3186,11 @@ async function typecheckContentWorkers(contentDir2, options) {
|
|
|
2907
3186
|
};
|
|
2908
3187
|
const parsed = ts.parseJsonConfigFileContent(config, ts.sys, contentDir2);
|
|
2909
3188
|
if (parsed.fileNames.length === 0) return [];
|
|
2910
|
-
const program = ts.createProgram({
|
|
3189
|
+
const program = ts.createProgram({
|
|
3190
|
+
rootNames: parsed.fileNames,
|
|
3191
|
+
options: parsed.options,
|
|
3192
|
+
host: confinedHost(ts, contentDir2, parsed.options)
|
|
3193
|
+
});
|
|
2911
3194
|
return [...parsed.errors, ...ts.getPreEmitDiagnostics(program)].filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error && belongsToContentWorkers(contentDir2, diagnostic)).map((diagnostic) => toIssue(ts, contentDir2, diagnostic));
|
|
2912
3195
|
}
|
|
2913
3196
|
var compilerPromise;
|
|
@@ -2936,31 +3219,31 @@ __export(build_exports, {
|
|
|
2936
3219
|
umbrellaVersion: () => umbrellaVersion,
|
|
2937
3220
|
umbrellaVersionIssue: () => umbrellaVersionIssue
|
|
2938
3221
|
});
|
|
2939
|
-
import { existsSync as existsSync10, readdirSync as readdirSync8, mkdirSync as mkdirSync6, statSync as
|
|
2940
|
-
import { resolve as resolve11, join as
|
|
3222
|
+
import { existsSync as existsSync10, readdirSync as readdirSync8, mkdirSync as mkdirSync6, statSync as statSync3, symlinkSync, readFileSync as readFileSync12 } from "node:fs";
|
|
3223
|
+
import { resolve as resolve11, join as join13, dirname as dirname9 } from "node:path";
|
|
2941
3224
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
2942
3225
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
2943
3226
|
function bundledRuntimeDir() {
|
|
2944
3227
|
const configured = process.env.HIMI_CLI_RUNTIME_DIR;
|
|
2945
|
-
if (configured && existsSync10(
|
|
3228
|
+
if (configured && existsSync10(join13(configured, "node_modules", "@wix", "himalaya", "package.json"))) {
|
|
2946
3229
|
return configured;
|
|
2947
3230
|
}
|
|
2948
3231
|
const candidate = resolve11(dirname9(fileURLToPath6(import.meta.url)), "authoring-runtime");
|
|
2949
|
-
if (!existsSync10(
|
|
3232
|
+
if (!existsSync10(join13(candidate, "node_modules", "@wix", "himalaya", "package.json"))) return null;
|
|
2950
3233
|
process.env.HIMI_CLI_RUNTIME_DIR = candidate;
|
|
2951
3234
|
return candidate;
|
|
2952
3235
|
}
|
|
2953
3236
|
function bundledUmbrella() {
|
|
2954
3237
|
const runtime = bundledRuntimeDir();
|
|
2955
|
-
return runtime ?
|
|
3238
|
+
return runtime ? join13(runtime, "node_modules", "@wix", "himalaya") : null;
|
|
2956
3239
|
}
|
|
2957
3240
|
function umbrellaDir(fromDir) {
|
|
2958
3241
|
const bundled = bundledUmbrella();
|
|
2959
3242
|
if (bundled) return bundled;
|
|
2960
3243
|
let d = resolve11(fromDir);
|
|
2961
3244
|
for (; ; ) {
|
|
2962
|
-
const pkg =
|
|
2963
|
-
if (existsSync10(
|
|
3245
|
+
const pkg = join13(d, "node_modules", "@wix", "himalaya");
|
|
3246
|
+
if (existsSync10(join13(pkg, "package.json"))) return pkg;
|
|
2964
3247
|
const parent = dirname9(d);
|
|
2965
3248
|
if (parent === d) return null;
|
|
2966
3249
|
d = parent;
|
|
@@ -2973,8 +3256,8 @@ function globalUmbrella() {
|
|
|
2973
3256
|
try {
|
|
2974
3257
|
const root = execFileSync3("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
2975
3258
|
if (!root) return null;
|
|
2976
|
-
const pkg =
|
|
2977
|
-
return existsSync10(
|
|
3259
|
+
const pkg = join13(root, "@wix", "himalaya");
|
|
3260
|
+
return existsSync10(join13(pkg, "package.json")) ? pkg : null;
|
|
2978
3261
|
} catch {
|
|
2979
3262
|
return null;
|
|
2980
3263
|
}
|
|
@@ -2983,11 +3266,11 @@ function ensureUmbrella(contentDir2, globalPath = globalUmbrella()) {
|
|
|
2983
3266
|
if (umbrellaInstalled(contentDir2)) return true;
|
|
2984
3267
|
if (!globalPath) return false;
|
|
2985
3268
|
try {
|
|
2986
|
-
const scope =
|
|
3269
|
+
const scope = join13(contentDir2, "node_modules", "@wix");
|
|
2987
3270
|
mkdirSync6(scope, { recursive: true });
|
|
2988
|
-
const link =
|
|
3271
|
+
const link = join13(scope, "himalaya");
|
|
2989
3272
|
if (!existsSync10(link)) symlinkSync(globalPath, link, "dir");
|
|
2990
|
-
return existsSync10(
|
|
3273
|
+
return existsSync10(join13(link, "package.json"));
|
|
2991
3274
|
} catch {
|
|
2992
3275
|
return false;
|
|
2993
3276
|
}
|
|
@@ -3005,7 +3288,7 @@ function umbrellaVersion(fromDir) {
|
|
|
3005
3288
|
const dir = umbrellaDir(fromDir);
|
|
3006
3289
|
if (!dir) return null;
|
|
3007
3290
|
try {
|
|
3008
|
-
const v = JSON.parse(readFileSync12(
|
|
3291
|
+
const v = JSON.parse(readFileSync12(join13(dir, "package.json"), "utf8")).version;
|
|
3009
3292
|
return typeof v === "string" && v ? v : null;
|
|
3010
3293
|
} catch {
|
|
3011
3294
|
return null;
|
|
@@ -3026,7 +3309,7 @@ function umbrellaDistIssue(contentDir2) {
|
|
|
3026
3309
|
if (!dir) return null;
|
|
3027
3310
|
let exportsMap;
|
|
3028
3311
|
try {
|
|
3029
|
-
exportsMap = JSON.parse(readFileSync12(
|
|
3312
|
+
exportsMap = JSON.parse(readFileSync12(join13(dir, "package.json"), "utf8")).exports;
|
|
3030
3313
|
} catch {
|
|
3031
3314
|
return null;
|
|
3032
3315
|
}
|
|
@@ -3080,14 +3363,19 @@ async function buildContentBundles(contentDir2, opts = {}) {
|
|
|
3080
3363
|
if (!existsSync10(srcDir)) return { built, outDir, compileErrors, ...sdkVersionIssue ? { sdkVersionIssue } : {} };
|
|
3081
3364
|
mkdirSync6(outDir, { recursive: true });
|
|
3082
3365
|
for (const name of readdirSync8(srcDir).sort()) {
|
|
3083
|
-
const entry =
|
|
3084
|
-
if (!
|
|
3366
|
+
const entry = join13(srcDir, name, "index.ts");
|
|
3367
|
+
if (!statSync3(join13(srcDir, name)).isDirectory() || !existsSync10(entry)) continue;
|
|
3085
3368
|
try {
|
|
3086
|
-
await buildBundleFromEntry(entry,
|
|
3369
|
+
await buildBundleFromEntry(entry, join13(outDir, `${name}.bundle.js`), {
|
|
3087
3370
|
resolution,
|
|
3088
3371
|
name,
|
|
3089
3372
|
// Off-repo, resolve the umbrella from the content package's own node_modules.
|
|
3090
|
-
...offRepo ? { absWorkingDir: contentDir2 } : {}
|
|
3373
|
+
...offRepo ? { absWorkingDir: contentDir2 } : {},
|
|
3374
|
+
// Bounds the import graph in a process that compiles untrusted uploads
|
|
3375
|
+
// (core/serve-authoring); inert everywhere else. Always passed, so the authoring guest
|
|
3376
|
+
// cannot reach this build without a root — build-lib throws rather than compile
|
|
3377
|
+
// unconfined.
|
|
3378
|
+
confineTo: contentDir2
|
|
3091
3379
|
});
|
|
3092
3380
|
built.push(name);
|
|
3093
3381
|
} catch (err) {
|
|
@@ -3125,11 +3413,11 @@ __export(app_config_loader_exports, {
|
|
|
3125
3413
|
loadAppConfigModule: () => loadAppConfigModule
|
|
3126
3414
|
});
|
|
3127
3415
|
import { existsSync as existsSync11, mkdirSync as mkdirSync7 } from "node:fs";
|
|
3128
|
-
import { dirname as dirname10, join as
|
|
3416
|
+
import { dirname as dirname10, join as join14, resolve as resolve12 } from "node:path";
|
|
3129
3417
|
import { pathToFileURL as pathToFileURL4 } from "node:url";
|
|
3130
3418
|
function configEntry(dir) {
|
|
3131
3419
|
for (const f of ["config.ts", "config.js", "config.mjs"]) {
|
|
3132
|
-
const p =
|
|
3420
|
+
const p = join14(dir, f);
|
|
3133
3421
|
if (existsSync11(p)) return p;
|
|
3134
3422
|
}
|
|
3135
3423
|
return null;
|
|
@@ -3141,7 +3429,7 @@ async function buildConfigModuleUrl(entry, dir) {
|
|
|
3141
3429
|
bundledRuntimeDir2();
|
|
3142
3430
|
const out = resolve12(dir, "dist/.himi/config.mjs");
|
|
3143
3431
|
mkdirSync7(dirname10(out), { recursive: true });
|
|
3144
|
-
await buildAppEntry(entry, out, { umbrella: true, resolveTsExtensions: true, absWorkingDir: dir });
|
|
3432
|
+
await buildAppEntry(entry, out, { umbrella: true, resolveTsExtensions: true, absWorkingDir: dir, confineTo: dir });
|
|
3145
3433
|
return pathToFileURL4(out).href;
|
|
3146
3434
|
}
|
|
3147
3435
|
function rememberBuild(key2, pending) {
|
|
@@ -3889,10 +4177,10 @@ var init_app_icon_rules = __esm({
|
|
|
3889
4177
|
|
|
3890
4178
|
// ../../core/dev-server/src/app-icon.ts
|
|
3891
4179
|
import { existsSync as existsSync14, readFileSync as readFileSync17, readdirSync as readdirSync9 } from "node:fs";
|
|
3892
|
-
import { dirname as dirname13, join as
|
|
4180
|
+
import { dirname as dirname13, join as join18, resolve as resolve13 } from "node:path";
|
|
3893
4181
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
3894
4182
|
function findAppIconPath(appDir2) {
|
|
3895
|
-
const iosDir =
|
|
4183
|
+
const iosDir = join18(appDir2, "ios");
|
|
3896
4184
|
let children;
|
|
3897
4185
|
try {
|
|
3898
4186
|
children = readdirSync9(iosDir);
|
|
@@ -3900,7 +4188,7 @@ function findAppIconPath(appDir2) {
|
|
|
3900
4188
|
return null;
|
|
3901
4189
|
}
|
|
3902
4190
|
for (const child of children) {
|
|
3903
|
-
const p =
|
|
4191
|
+
const p = join18(iosDir, child, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
3904
4192
|
if (existsSync14(p)) return p;
|
|
3905
4193
|
}
|
|
3906
4194
|
return null;
|
|
@@ -3908,7 +4196,7 @@ function findAppIconPath(appDir2) {
|
|
|
3908
4196
|
function findContentIconPath(appDir2) {
|
|
3909
4197
|
let rel;
|
|
3910
4198
|
try {
|
|
3911
|
-
rel = JSON.parse(readFileSync17(
|
|
4199
|
+
rel = JSON.parse(readFileSync17(join18(appDir2, "himalaya.content.json"), "utf8")).icon;
|
|
3912
4200
|
} catch {
|
|
3913
4201
|
return null;
|
|
3914
4202
|
}
|
|
@@ -3933,7 +4221,7 @@ function readIconFromDir(appDir2) {
|
|
|
3933
4221
|
function resolveAppDir(appId2) {
|
|
3934
4222
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(appId2)) return null;
|
|
3935
4223
|
for (const base of APP_ROOTS) {
|
|
3936
|
-
const dir =
|
|
4224
|
+
const dir = join18(ROOT, base, appId2);
|
|
3937
4225
|
if (existsSync14(dir)) return dir;
|
|
3938
4226
|
}
|
|
3939
4227
|
return null;
|
|
@@ -4226,11 +4514,11 @@ __export(icon_exports, {
|
|
|
4226
4514
|
summarize: () => summarize
|
|
4227
4515
|
});
|
|
4228
4516
|
import { createHash as createHash5 } from "node:crypto";
|
|
4229
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync18, statSync as
|
|
4230
|
-
import { basename as basename4, dirname as dirname14, join as
|
|
4517
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync18, statSync as statSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
4518
|
+
import { basename as basename4, dirname as dirname14, join as join19, resolve as resolve14, sep as sep4 } from "node:path";
|
|
4231
4519
|
function readManifest(dir) {
|
|
4232
4520
|
try {
|
|
4233
|
-
return JSON.parse(readFileSync18(
|
|
4521
|
+
return JSON.parse(readFileSync18(join19(dir, MANIFEST), "utf8"));
|
|
4234
4522
|
} catch {
|
|
4235
4523
|
return null;
|
|
4236
4524
|
}
|
|
@@ -4244,7 +4532,7 @@ function declaredIconName(dir) {
|
|
|
4244
4532
|
function iconDest(dir, name) {
|
|
4245
4533
|
const base = resolve14(dir);
|
|
4246
4534
|
const abs = resolve14(base, name);
|
|
4247
|
-
if (!abs.startsWith(base +
|
|
4535
|
+
if (!abs.startsWith(base + sep4)) {
|
|
4248
4536
|
throw new Error(
|
|
4249
4537
|
`himi icon: himalaya.content.json declares "icon": "${name}", which resolves outside the package (${abs}). Declare a path inside it, e.g. "${DEFAULT_CONTENT_ICON}".`
|
|
4250
4538
|
);
|
|
@@ -4254,9 +4542,9 @@ function iconDest(dir, name) {
|
|
|
4254
4542
|
}
|
|
4255
4543
|
function templateIconMatch(png) {
|
|
4256
4544
|
for (const template of availableTemplates()) {
|
|
4257
|
-
const candidate =
|
|
4545
|
+
const candidate = join19(templateSourceDir(template), DEFAULT_CONTENT_ICON);
|
|
4258
4546
|
try {
|
|
4259
|
-
if (
|
|
4547
|
+
if (statSync4(candidate).size !== png.length) continue;
|
|
4260
4548
|
if (readFileSync18(candidate).equals(png)) return template;
|
|
4261
4549
|
} catch {
|
|
4262
4550
|
}
|
|
@@ -4264,10 +4552,10 @@ function templateIconMatch(png) {
|
|
|
4264
4552
|
return null;
|
|
4265
4553
|
}
|
|
4266
4554
|
function playState(dir) {
|
|
4267
|
-
const p =
|
|
4555
|
+
const p = join19(resolve14(dir), PLAY_LISTING_ICON);
|
|
4268
4556
|
if (!existsSync15(p)) return null;
|
|
4269
4557
|
try {
|
|
4270
|
-
if (!
|
|
4558
|
+
if (!statSync4(p).isFile()) return { path: p, issues: ["is a directory, not a PNG file"] };
|
|
4271
4559
|
return { path: p, issues: playListingIconIssues(readFileSync18(p)) };
|
|
4272
4560
|
} catch (err) {
|
|
4273
4561
|
return { path: p, issues: [`could not be read (${err.message.split("\n")[0]})`] };
|
|
@@ -4294,7 +4582,7 @@ async function iconStatus(dir) {
|
|
|
4294
4582
|
if (!path || !existsSync15(path)) return base;
|
|
4295
4583
|
let png;
|
|
4296
4584
|
try {
|
|
4297
|
-
if (!
|
|
4585
|
+
if (!statSync4(path).isFile()) {
|
|
4298
4586
|
return {
|
|
4299
4587
|
...base,
|
|
4300
4588
|
byteIssues: [`at ${path} is a directory, not a PNG file`],
|
|
@@ -4371,7 +4659,7 @@ function summarize(status) {
|
|
|
4371
4659
|
}
|
|
4372
4660
|
function backdropFromTokens(dir, fallback = "#1F2933") {
|
|
4373
4661
|
try {
|
|
4374
|
-
const tokens = JSON.parse(readFileSync18(
|
|
4662
|
+
const tokens = JSON.parse(readFileSync18(join19(dir, "tokens.json"), "utf8"));
|
|
4375
4663
|
const accent = tokens.colors?.accentPrimary;
|
|
4376
4664
|
const hex2 = typeof accent === "string" ? accent : accent?.light;
|
|
4377
4665
|
return typeof hex2 === "string" && HEX_COLOR2.test(hex2) ? hex2 : fallback;
|
|
@@ -4430,15 +4718,15 @@ function declareIcon(dir, name) {
|
|
|
4430
4718
|
if (k === "name") next.icon = name;
|
|
4431
4719
|
}
|
|
4432
4720
|
next.icon = name;
|
|
4433
|
-
writeFileSync8(
|
|
4434
|
-
return [
|
|
4721
|
+
writeFileSync8(join19(dir, MANIFEST), JSON.stringify(next, null, 2) + "\n");
|
|
4722
|
+
return [join19(dir, MANIFEST)];
|
|
4435
4723
|
}
|
|
4436
4724
|
function siteBookIcon(bookDir) {
|
|
4437
|
-
const p =
|
|
4725
|
+
const p = join19(resolve14(bookDir), SITE_BOOK_ICON_REL);
|
|
4438
4726
|
return existsSync15(p) ? p : null;
|
|
4439
4727
|
}
|
|
4440
4728
|
function siteLogoAbsence(bookDir) {
|
|
4441
|
-
const bookJson =
|
|
4729
|
+
const bookJson = join19(resolve14(bookDir), "book.json");
|
|
4442
4730
|
if (!existsSync15(bookJson)) {
|
|
4443
4731
|
return { reason: "no-book", hint: `no business book at ${bookDir} \u2014 run \`himi site analyze --out <dir>\` first, or pass --book <dir>` };
|
|
4444
4732
|
}
|
|
@@ -4520,7 +4808,7 @@ var init_icon = __esm({
|
|
|
4520
4808
|
// ../fonts/catalog.ts
|
|
4521
4809
|
import { existsSync as existsSync17, readFileSync as readFileSync19 } from "node:fs";
|
|
4522
4810
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
4523
|
-
import { join as
|
|
4811
|
+
import { join as join21 } from "node:path";
|
|
4524
4812
|
function loadCatalog() {
|
|
4525
4813
|
if (cached) return cached;
|
|
4526
4814
|
const path = CATALOG_CANDIDATES.find((p) => existsSync17(p));
|
|
@@ -4589,9 +4877,9 @@ var init_catalog = __esm({
|
|
|
4589
4877
|
"../fonts/catalog.ts"() {
|
|
4590
4878
|
CATALOG_CANDIDATES = [
|
|
4591
4879
|
// in-repo: tools/fonts/catalog.ts → <repo>/stdlib/fonts/catalog.json
|
|
4592
|
-
|
|
4880
|
+
join21(fileURLToPath8(new URL("../..", import.meta.url)), "stdlib", "fonts", "catalog.json"),
|
|
4593
4881
|
// published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/fonts/catalog.json
|
|
4594
|
-
|
|
4882
|
+
join21(fileURLToPath8(new URL("..", import.meta.url)), "stdlib", "fonts", "catalog.json")
|
|
4595
4883
|
];
|
|
4596
4884
|
cached = null;
|
|
4597
4885
|
normalizeFamily = (name) => name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
@@ -4696,17 +4984,17 @@ var init_plan_fonts = __esm({
|
|
|
4696
4984
|
import { createHash as createHash6 } from "node:crypto";
|
|
4697
4985
|
import { existsSync as existsSync18, readFileSync as readFileSync20 } from "node:fs";
|
|
4698
4986
|
import { homedir as homedir4 } from "node:os";
|
|
4699
|
-
import { basename as basename5, join as
|
|
4987
|
+
import { basename as basename5, join as join22 } from "node:path";
|
|
4700
4988
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
4701
4989
|
function hasVendoredFloor() {
|
|
4702
4990
|
return existsSync18(VENDORED_DIR);
|
|
4703
4991
|
}
|
|
4704
4992
|
function faceSource(file, sha2565) {
|
|
4705
|
-
const vendored =
|
|
4993
|
+
const vendored = join22(VENDORED_DIR, basename5(file));
|
|
4706
4994
|
if (existsSync18(vendored) && createHash6("sha256").update(readFileSync20(vendored)).digest("hex") === sha2565) {
|
|
4707
4995
|
return vendored;
|
|
4708
4996
|
}
|
|
4709
|
-
const cached3 =
|
|
4997
|
+
const cached3 = join22(CACHE_DIR, sha2565);
|
|
4710
4998
|
if (existsSync18(cached3)) return cached3;
|
|
4711
4999
|
return null;
|
|
4712
5000
|
}
|
|
@@ -4714,8 +5002,8 @@ var REPO_ROOT5, VENDORED_DIR, CACHE_DIR;
|
|
|
4714
5002
|
var init_face_source = __esm({
|
|
4715
5003
|
"../font-bake/face-source.ts"() {
|
|
4716
5004
|
REPO_ROOT5 = fileURLToPath9(new URL("../..", import.meta.url));
|
|
4717
|
-
VENDORED_DIR = process.env.HIMI_FONTS_VENDORED_DIR ||
|
|
4718
|
-
CACHE_DIR =
|
|
5005
|
+
VENDORED_DIR = process.env.HIMI_FONTS_VENDORED_DIR || join22(REPO_ROOT5, "stdlib", "fonts", "vendored", "wix-madefor");
|
|
5006
|
+
CACHE_DIR = join22(process.env.XDG_CACHE_HOME || join22(homedir4(), ".cache"), "himi", "fonts");
|
|
4719
5007
|
}
|
|
4720
5008
|
});
|
|
4721
5009
|
|
|
@@ -4729,7 +5017,7 @@ __export(fonts_exports, {
|
|
|
4729
5017
|
resolveFamilyName: () => resolveFamilyName
|
|
4730
5018
|
});
|
|
4731
5019
|
import { existsSync as existsSync19, readFileSync as readFileSync21 } from "node:fs";
|
|
4732
|
-
import { join as
|
|
5020
|
+
import { join as join23 } from "node:path";
|
|
4733
5021
|
function readJson(path, fallback) {
|
|
4734
5022
|
try {
|
|
4735
5023
|
return JSON.parse(readFileSync21(path, "utf8"));
|
|
@@ -4761,11 +5049,11 @@ function listReport(opts = {}) {
|
|
|
4761
5049
|
return { ok: true, count: families.length, totalBytes, families };
|
|
4762
5050
|
}
|
|
4763
5051
|
function fontFindings(appDir2) {
|
|
4764
|
-
const tokensPath =
|
|
5052
|
+
const tokensPath = join23(appDir2, "tokens.json");
|
|
4765
5053
|
if (!existsSync19(tokensPath)) return null;
|
|
4766
5054
|
const catalog = loadCatalog();
|
|
4767
5055
|
const tokens = readJson(tokensPath, {});
|
|
4768
|
-
const policy = readJson(
|
|
5056
|
+
const policy = readJson(join23(appDir2, "fonts.json"), {});
|
|
4769
5057
|
const plan = planFonts(tokens, policy, catalog);
|
|
4770
5058
|
const findings = [];
|
|
4771
5059
|
for (const family of plan.unresolved) {
|
|
@@ -4851,7 +5139,7 @@ function addReport(appDir2, family) {
|
|
|
4851
5139
|
totalBytes: bytes2,
|
|
4852
5140
|
problems: [],
|
|
4853
5141
|
families: [{ family: resolved, license: fam?.license.id ?? "system", copyright: fam?.license.copyright, kb: Math.round(bytes2 / 1024) }],
|
|
4854
|
-
hint: `add "${resolved}" to ${
|
|
5142
|
+
hint: `add "${resolved}" to ${join23(appDir2, "fonts.json")} under "families" (or name it in tokens.json typography), then run gen.sh. Licence: ${fam?.license.id ?? "system"}${fam?.license.copyright ? ` \u2014 ${fam.license.copyright}` : ""}`
|
|
4855
5143
|
};
|
|
4856
5144
|
}
|
|
4857
5145
|
var DEFAULT_ASSET_BUDGET_BYTES;
|
|
@@ -5773,7 +6061,7 @@ var init_src = __esm({
|
|
|
5773
6061
|
// ../app-icons/plan.ts
|
|
5774
6062
|
import { existsSync as existsSync23, readFileSync as readFileSync25, readdirSync as readdirSync12 } from "node:fs";
|
|
5775
6063
|
import { createHash as createHash7 } from "node:crypto";
|
|
5776
|
-
import { dirname as dirname16, join as
|
|
6064
|
+
import { dirname as dirname16, join as join27, resolve as resolve17 } from "node:path";
|
|
5777
6065
|
function stripComments(src) {
|
|
5778
6066
|
let out = "";
|
|
5779
6067
|
let i = 0;
|
|
@@ -5903,10 +6191,10 @@ function rotateHue(hex2, deg) {
|
|
|
5903
6191
|
function resolveTokensPath(app, configTs) {
|
|
5904
6192
|
const literal = /^ {2}designTokensPath\s*:\s*["']([^"']+)["']/m.exec(stripComments(configTs))?.[1];
|
|
5905
6193
|
if (literal) return { path: resolve17(appDir(app), literal), source: "declared" };
|
|
5906
|
-
return { path:
|
|
6194
|
+
return { path: join27(appDir(app), "tokens.json"), source: "assumed" };
|
|
5907
6195
|
}
|
|
5908
6196
|
function resolveToken(app, token, tokensPathOverride) {
|
|
5909
|
-
const tokensPath = tokensPathOverride ??
|
|
6197
|
+
const tokensPath = tokensPathOverride ?? join27(appDir(app), "tokens.json");
|
|
5910
6198
|
if (!existsSync23(tokensPath)) {
|
|
5911
6199
|
throw new Error(`app-icons: ${app} has no tokens.json at ${tokensPath} (needed to resolve "${token}").`);
|
|
5912
6200
|
}
|
|
@@ -5989,17 +6277,17 @@ function iconSpec(app, configTs, id, tokensPathOverride) {
|
|
|
5989
6277
|
};
|
|
5990
6278
|
}
|
|
5991
6279
|
function iosAssetCatalog2(app) {
|
|
5992
|
-
return assetCatalogIn(
|
|
6280
|
+
return assetCatalogIn(join27(appDir(app), "ios"));
|
|
5993
6281
|
}
|
|
5994
6282
|
function assetCatalogIn(platformDir) {
|
|
5995
6283
|
if (!existsSync23(platformDir)) return void 0;
|
|
5996
6284
|
const children = readdirSync12(platformDir).filter((c) => !c.startsWith("build")).sort();
|
|
5997
|
-
const catalogs = children.map((c) =>
|
|
6285
|
+
const catalogs = children.map((c) => join27(platformDir, c, "Assets.xcassets")).filter(existsSync23);
|
|
5998
6286
|
if (catalogs.length === 1) return catalogs[0];
|
|
5999
6287
|
if (catalogs.length > 1) return void 0;
|
|
6000
6288
|
const targets = [];
|
|
6001
6289
|
for (const child of children) {
|
|
6002
|
-
const dir =
|
|
6290
|
+
const dir = join27(platformDir, child);
|
|
6003
6291
|
let entries;
|
|
6004
6292
|
try {
|
|
6005
6293
|
entries = readdirSync12(dir);
|
|
@@ -6007,20 +6295,20 @@ function assetCatalogIn(platformDir) {
|
|
|
6007
6295
|
continue;
|
|
6008
6296
|
}
|
|
6009
6297
|
if (entries.includes("Info.plist") || entries.some((e) => e.endsWith(".swift"))) {
|
|
6010
|
-
targets.push(
|
|
6298
|
+
targets.push(join27(dir, "Assets.xcassets"));
|
|
6011
6299
|
}
|
|
6012
6300
|
}
|
|
6013
6301
|
return targets.length === 1 ? targets[0] : void 0;
|
|
6014
6302
|
}
|
|
6015
6303
|
function androidResDir2(manifestPath) {
|
|
6016
|
-
return
|
|
6304
|
+
return join27(dirname16(manifestPath), "res");
|
|
6017
6305
|
}
|
|
6018
6306
|
function androidManifestPath(app) {
|
|
6019
|
-
const androidDir =
|
|
6307
|
+
const androidDir = join27(appDir(app), "android");
|
|
6020
6308
|
if (!existsSync23(androidDir)) return void 0;
|
|
6021
|
-
const preferred =
|
|
6309
|
+
const preferred = join27(androidDir, `${app}-app`, "src", "main", "AndroidManifest.xml");
|
|
6022
6310
|
if (existsSync23(preferred)) return preferred;
|
|
6023
|
-
const candidates = readdirSync12(androidDir, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.endsWith("-app")).map((d) =>
|
|
6311
|
+
const candidates = readdirSync12(androidDir, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.endsWith("-app")).map((d) => join27(androidDir, d.name, "src", "main", "AndroidManifest.xml")).filter(existsSync23);
|
|
6024
6312
|
return candidates.length === 1 ? candidates[0] : void 0;
|
|
6025
6313
|
}
|
|
6026
6314
|
function androidOptedIn2(manifestPath) {
|
|
@@ -6029,7 +6317,7 @@ function androidOptedIn2(manifestPath) {
|
|
|
6029
6317
|
}
|
|
6030
6318
|
function templateIconSha256() {
|
|
6031
6319
|
const cat = iosAssetCatalog2("_template");
|
|
6032
|
-
return cat ? fileSha256(
|
|
6320
|
+
return cat ? fileSha256(join27(cat, "AppIcon.appiconset", "icon_1024.png")) : null;
|
|
6033
6321
|
}
|
|
6034
6322
|
function placeholderHashes() {
|
|
6035
6323
|
const current = templateIconSha256();
|
|
@@ -6048,7 +6336,7 @@ function generationAllowed(app, configTs, opts = {}) {
|
|
|
6048
6336
|
return { allowed: true, reason: "declares an icon block" };
|
|
6049
6337
|
}
|
|
6050
6338
|
const iosCat = iosAssetCatalog2(app);
|
|
6051
|
-
const iosIcon = iosCat ?
|
|
6339
|
+
const iosIcon = iosCat ? join27(iosCat, "AppIcon.appiconset", "icon_1024.png") : void 0;
|
|
6052
6340
|
if (!iosIcon || !existsSync23(iosIcon)) return { allowed: true, reason: "no icon yet" };
|
|
6053
6341
|
const hash = fileSha256(iosIcon);
|
|
6054
6342
|
const placeholders = opts.placeholderHashes ?? placeholderHashes();
|
|
@@ -6074,7 +6362,7 @@ var init_plan2 = __esm({
|
|
|
6074
6362
|
|
|
6075
6363
|
// ../native-config/icon.ts
|
|
6076
6364
|
import { existsSync as existsSync24, readFileSync as readFileSync26 } from "node:fs";
|
|
6077
|
-
import { join as
|
|
6365
|
+
import { join as join28 } from "node:path";
|
|
6078
6366
|
function androidAdaptiveIconXml() {
|
|
6079
6367
|
return [
|
|
6080
6368
|
'<?xml version="1.0" encoding="utf-8"?>',
|
|
@@ -6101,7 +6389,7 @@ function androidIconArtifacts(app, configTs) {
|
|
|
6101
6389
|
if (!androidOptedIn2(manifest)) return [];
|
|
6102
6390
|
if (!generationAllowed(app, configTs).allowed) return [];
|
|
6103
6391
|
const res = androidResDir2(manifest);
|
|
6104
|
-
const foreground =
|
|
6392
|
+
const foreground = join28(res, "mipmap-mdpi", "ic_launcher_foreground.png");
|
|
6105
6393
|
if (!existsSync24(foreground)) {
|
|
6106
6394
|
throw new Error(
|
|
6107
6395
|
`native-config icon: ${app} opts into @mipmap/ic_launcher but has no mipmap-*/ic_launcher_foreground.png. Run \`npm run app-icons -- ${app}\` first \u2014 the XML emitted here points at those rasters.`
|
|
@@ -6111,11 +6399,11 @@ function androidIconArtifacts(app, configTs) {
|
|
|
6111
6399
|
const spec = iconSpec(app, configTs, id, resolveTokensPath(app, configTs).path);
|
|
6112
6400
|
return [
|
|
6113
6401
|
...ANDROID_ADAPTIVE_FILES.map((name) => ({
|
|
6114
|
-
path:
|
|
6402
|
+
path: join28(res, "mipmap-anydpi-v26", name),
|
|
6115
6403
|
content: androidAdaptiveIconXml()
|
|
6116
6404
|
})),
|
|
6117
6405
|
{
|
|
6118
|
-
path:
|
|
6406
|
+
path: join28(res, "values", ANDROID_ICON_BACKGROUND_FILE),
|
|
6119
6407
|
content: androidIconBackgroundXml(spec.background)
|
|
6120
6408
|
}
|
|
6121
6409
|
];
|
|
@@ -6350,7 +6638,7 @@ __export(gen_native_config_exports, {
|
|
|
6350
6638
|
watchInfoPlan: () => watchInfoPlan
|
|
6351
6639
|
});
|
|
6352
6640
|
import { existsSync as existsSync25, mkdirSync as mkdirSync12, readFileSync as readFileSync27, readdirSync as readdirSync13, rmSync as rmSync3, writeFileSync as writeFileSync11 } from "node:fs";
|
|
6353
|
-
import { dirname as dirname17, join as
|
|
6641
|
+
import { dirname as dirname17, join as join29 } from "node:path";
|
|
6354
6642
|
function parseStringArray(configTs, field) {
|
|
6355
6643
|
const m = new RegExp(`${field}:\\s*\\[([^\\]]*)\\]`).exec(configTs);
|
|
6356
6644
|
if (!m) return [];
|
|
@@ -6422,7 +6710,7 @@ function buildSet(capabilities, envelope = []) {
|
|
|
6422
6710
|
return [...new Set([...capabilities, ...envelope].map(catalogKey))].sort();
|
|
6423
6711
|
}
|
|
6424
6712
|
function loadOverrides(app) {
|
|
6425
|
-
const p =
|
|
6713
|
+
const p = join29(appDir(app), "native-config.overrides.json");
|
|
6426
6714
|
if (!existsSync25(p)) return {};
|
|
6427
6715
|
return JSON.parse(readFileSync27(p, "utf8"));
|
|
6428
6716
|
}
|
|
@@ -6479,14 +6767,14 @@ function endText(kind, label2, indent) {
|
|
|
6479
6767
|
return kind === "yaml" ? `${indent}# <<< ${label2} <<<` : `${indent}<!-- <<< ${label2} <<< -->`;
|
|
6480
6768
|
}
|
|
6481
6769
|
function hostAppliesDeferredWidgetActions(app) {
|
|
6482
|
-
const root =
|
|
6770
|
+
const root = join29(appDir(app), "ios");
|
|
6483
6771
|
if (!existsSync25(root)) return false;
|
|
6484
6772
|
const stack = [root];
|
|
6485
6773
|
while (stack.length) {
|
|
6486
6774
|
const dir = stack.pop();
|
|
6487
6775
|
for (const entry of readdirSync13(dir, { withFileTypes: true })) {
|
|
6488
6776
|
if (entry.name.startsWith(".") || entry.name === "GeneratedLiveActivity") continue;
|
|
6489
|
-
const path =
|
|
6777
|
+
const path = join29(dir, entry.name);
|
|
6490
6778
|
if (entry.isDirectory()) {
|
|
6491
6779
|
if (entry.name.endsWith(".xcodeproj") || entry.name === "build") continue;
|
|
6492
6780
|
stack.push(path);
|
|
@@ -6513,14 +6801,14 @@ function injectBlock(text2, kind, label2, render) {
|
|
|
6513
6801
|
return [...lines.slice(0, beginIdx), ...block, ...lines.slice(endIdx + 1)].join("\n");
|
|
6514
6802
|
}
|
|
6515
6803
|
function androidManifestPath2(app) {
|
|
6516
|
-
const androidDir =
|
|
6517
|
-
const preferred =
|
|
6804
|
+
const androidDir = join29(appDir(app), "android");
|
|
6805
|
+
const preferred = join29(androidDir, `${app}-app`, "src", "main", "AndroidManifest.xml");
|
|
6518
6806
|
if (existsSync25(preferred)) return preferred;
|
|
6519
|
-
const candidates = existsSync25(androidDir) ? readdirSync13(androidDir, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.endsWith("-app")).map((d) =>
|
|
6807
|
+
const candidates = existsSync25(androidDir) ? readdirSync13(androidDir, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.endsWith("-app")).map((d) => join29(androidDir, d.name, "src", "main", "AndroidManifest.xml")).filter(existsSync25) : [];
|
|
6520
6808
|
return candidates.length === 1 ? candidates[0] : preferred;
|
|
6521
6809
|
}
|
|
6522
6810
|
function automotiveAppDescPath(app) {
|
|
6523
|
-
return
|
|
6811
|
+
return join29(dirname17(androidManifestPath2(app)), "res", "xml", "automotive_app_desc.xml");
|
|
6524
6812
|
}
|
|
6525
6813
|
function applyToFile(path, kind, label2, render, check) {
|
|
6526
6814
|
if (!existsSync25(path)) return { path, outcome: "skipped" };
|
|
@@ -6619,9 +6907,9 @@ function genNativeConfig(app, opts = {}) {
|
|
|
6619
6907
|
const plan = live2;
|
|
6620
6908
|
files.push(applyToFile(iosYml, "yaml", LABEL_LIVE_TARGET, (i) => plan.target.map((line) => i + line), check));
|
|
6621
6909
|
files.push(applyToFile(iosYml, "yaml", LABEL_LIVE_EMBED, (i) => plan.embed.map((line) => i + line), check));
|
|
6622
|
-
const source =
|
|
6910
|
+
const source = join29(dirname17(iosYml), LIVE_SOURCE_PATH);
|
|
6623
6911
|
files.push(plan.source ? applyWholeFile(source, plan.source, check) : removeWholeFile(source, check));
|
|
6624
|
-
const entitlements =
|
|
6912
|
+
const entitlements = join29(dirname17(iosYml), LIVE_ENTITLEMENTS_PATH);
|
|
6625
6913
|
files.push(plan.entitlements ? applyWholeFile(entitlements, plan.entitlements, check) : removeWholeFile(entitlements, check));
|
|
6626
6914
|
}
|
|
6627
6915
|
const iosSplashManaged = existsSync25(iosYml) && hasMarkers(readFileSync27(iosYml, "utf8"), "yaml", LABEL_IOS_SPLASH);
|
|
@@ -6759,7 +7047,8 @@ async function devModuleUrl(entry, dir) {
|
|
|
6759
7047
|
// intentionally point at `.ts` sources, which are only loadable under tsx.
|
|
6760
7048
|
umbrella: true,
|
|
6761
7049
|
resolveTsExtensions: true,
|
|
6762
|
-
absWorkingDir: dir
|
|
7050
|
+
absWorkingDir: dir,
|
|
7051
|
+
confineTo: dir
|
|
6763
7052
|
});
|
|
6764
7053
|
return pathToFileURL5(out).href;
|
|
6765
7054
|
}
|
|
@@ -6881,8 +7170,8 @@ var init_build_sha = __esm({
|
|
|
6881
7170
|
|
|
6882
7171
|
// ../../core/dev-server/src/app-assets.ts
|
|
6883
7172
|
import { createHash as createHash8 } from "node:crypto";
|
|
6884
|
-
import { existsSync as existsSync27, lstatSync as lstatSync3, readFileSync as readFileSync29, readdirSync as readdirSync15, realpathSync as
|
|
6885
|
-
import { join as
|
|
7173
|
+
import { existsSync as existsSync27, lstatSync as lstatSync3, readFileSync as readFileSync29, readdirSync as readdirSync15, realpathSync as realpathSync3, statSync as statSync6 } from "node:fs";
|
|
7174
|
+
import { join as join30, resolve as resolve19, sep as sep5 } from "node:path";
|
|
6886
7175
|
function contentTypeFor(name) {
|
|
6887
7176
|
const ext = name.includes(".") ? name.slice(name.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
6888
7177
|
return CONTENT_TYPES[ext] ?? "application/octet-stream";
|
|
@@ -6896,19 +7185,19 @@ function assetSha256(bytes2) {
|
|
|
6896
7185
|
function findAssetsDir(appDir2) {
|
|
6897
7186
|
let declared;
|
|
6898
7187
|
try {
|
|
6899
|
-
declared = JSON.parse(readFileSync29(
|
|
7188
|
+
declared = JSON.parse(readFileSync29(join30(appDir2, "himalaya.content.json"), "utf8")).assets;
|
|
6900
7189
|
} catch {
|
|
6901
7190
|
declared = void 0;
|
|
6902
7191
|
}
|
|
6903
7192
|
const rel = typeof declared === "string" && declared ? declared : "assets";
|
|
6904
7193
|
const abs = resolve19(appDir2, rel);
|
|
6905
7194
|
const base = resolve19(appDir2);
|
|
6906
|
-
if (abs !== base && !abs.startsWith(base +
|
|
6907
|
-
return existsSync27(abs) &&
|
|
7195
|
+
if (abs !== base && !abs.startsWith(base + sep5)) return null;
|
|
7196
|
+
return existsSync27(abs) && statSync6(abs).isDirectory() ? abs : null;
|
|
6908
7197
|
}
|
|
6909
7198
|
function readOtaOnlyPatterns(appDir2) {
|
|
6910
7199
|
try {
|
|
6911
|
-
const raw = JSON.parse(readFileSync29(
|
|
7200
|
+
const raw = JSON.parse(readFileSync29(join30(appDir2, "assets.json"), "utf8"));
|
|
6912
7201
|
return Array.isArray(raw.otaOnly) ? raw.otaOnly.filter((p) => typeof p === "string") : [];
|
|
6913
7202
|
} catch {
|
|
6914
7203
|
return [];
|
|
@@ -6926,7 +7215,7 @@ function collectAssets(appDir2) {
|
|
|
6926
7215
|
const walk2 = (abs, prefix) => {
|
|
6927
7216
|
for (const entry of readdirSync15(abs, { withFileTypes: true })) {
|
|
6928
7217
|
if (entry.name.startsWith(".")) continue;
|
|
6929
|
-
const child =
|
|
7218
|
+
const child = join30(abs, entry.name);
|
|
6930
7219
|
const name = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
6931
7220
|
if (entry.isDirectory()) {
|
|
6932
7221
|
walk2(child, name);
|
|
@@ -6935,7 +7224,7 @@ function collectAssets(appDir2) {
|
|
|
6935
7224
|
if (!entry.isFile()) continue;
|
|
6936
7225
|
const ext = name.includes(".") ? name.slice(name.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
6937
7226
|
const baked = !OTA_ONLY_BY_DEFAULT.has(ext) && !otaOnly.some((p) => matchesPattern(name, p));
|
|
6938
|
-
out.push({ name, path: child, bytes:
|
|
7227
|
+
out.push({ name, path: child, bytes: statSync6(child).size, contentType: contentTypeFor(name), baked });
|
|
6939
7228
|
}
|
|
6940
7229
|
};
|
|
6941
7230
|
walk2(dir, "");
|
|
@@ -6944,7 +7233,7 @@ function collectAssets(appDir2) {
|
|
|
6944
7233
|
function collectBrandFonts(appDir2) {
|
|
6945
7234
|
let faces;
|
|
6946
7235
|
try {
|
|
6947
|
-
faces = JSON.parse(readFileSync29(
|
|
7236
|
+
faces = JSON.parse(readFileSync29(join30(appDir2, "media/fonts/faces.json"), "utf8"));
|
|
6948
7237
|
} catch {
|
|
6949
7238
|
return [];
|
|
6950
7239
|
}
|
|
@@ -6957,11 +7246,11 @@ function collectBrandFonts(appDir2) {
|
|
|
6957
7246
|
const rel = typeof raw?.file === "string" ? raw.file : "";
|
|
6958
7247
|
if (!family || !postscriptName || !rel) continue;
|
|
6959
7248
|
if (rel.startsWith("/") || rel.split("/").includes("..")) continue;
|
|
6960
|
-
const path =
|
|
7249
|
+
const path = join30(appDir2, rel);
|
|
6961
7250
|
try {
|
|
6962
7251
|
if (!lstatSync3(path).isFile()) continue;
|
|
6963
|
-
const root =
|
|
6964
|
-
if (!
|
|
7252
|
+
const root = realpathSync3(appDir2);
|
|
7253
|
+
if (!realpathSync3(path).startsWith(root + sep5)) continue;
|
|
6965
7254
|
} catch {
|
|
6966
7255
|
continue;
|
|
6967
7256
|
}
|
|
@@ -7067,7 +7356,7 @@ async function injectRequest(listener, request) {
|
|
|
7067
7356
|
req.headers.host ??= url.host;
|
|
7068
7357
|
if (body && body.length > 0) req.push(body);
|
|
7069
7358
|
req.push(null);
|
|
7070
|
-
return await new Promise((
|
|
7359
|
+
return await new Promise((resolve41, reject) => {
|
|
7071
7360
|
const streamed = () => {
|
|
7072
7361
|
queueMicrotask(() => {
|
|
7073
7362
|
req.emit("close");
|
|
@@ -7083,7 +7372,7 @@ async function injectRequest(listener, request) {
|
|
|
7083
7372
|
else headers2.set(name, value);
|
|
7084
7373
|
}
|
|
7085
7374
|
const bodyless = out.status === 204 || out.status === 304 || request.method === "HEAD";
|
|
7086
|
-
|
|
7375
|
+
resolve41(new Response(bodyless ? null : out.body, { status: out.status, headers: headers2 }));
|
|
7087
7376
|
}, streamed);
|
|
7088
7377
|
res.on("inject-error", reject);
|
|
7089
7378
|
try {
|
|
@@ -8782,7 +9071,7 @@ var init_stable_ids = __esm({
|
|
|
8782
9071
|
// ../../core/dev-server/src/preview.ts
|
|
8783
9072
|
import { spawn as spawn2 } from "node:child_process";
|
|
8784
9073
|
import { createHash as createHash11 } from "node:crypto";
|
|
8785
|
-
import { existsSync as existsSync30, createReadStream, statSync as
|
|
9074
|
+
import { existsSync as existsSync30, createReadStream, statSync as statSync7, readFileSync as readFileSync33, renameSync, unlinkSync as unlinkSync2 } from "node:fs";
|
|
8786
9075
|
import { homedir as homedir5, tmpdir as tmpdir2 } from "node:os";
|
|
8787
9076
|
import { resolve as resolvePath, dirname as dirname20 } from "node:path";
|
|
8788
9077
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
@@ -9455,12 +9744,12 @@ function finalizeRecording(key2, rec) {
|
|
|
9455
9744
|
if (rec.finalize) return rec.finalize;
|
|
9456
9745
|
rec.finalize = (async () => {
|
|
9457
9746
|
clearTimeout(rec.autoStop);
|
|
9458
|
-
await new Promise((
|
|
9747
|
+
await new Promise((resolve41) => {
|
|
9459
9748
|
let done = false;
|
|
9460
9749
|
const finish2 = () => {
|
|
9461
9750
|
if (!done) {
|
|
9462
9751
|
done = true;
|
|
9463
|
-
|
|
9752
|
+
resolve41();
|
|
9464
9753
|
}
|
|
9465
9754
|
};
|
|
9466
9755
|
rec.child.once("close", finish2);
|
|
@@ -9480,7 +9769,7 @@ function finalizeRecording(key2, rec) {
|
|
|
9480
9769
|
} catch {
|
|
9481
9770
|
}
|
|
9482
9771
|
}
|
|
9483
|
-
const sizeBytes = existsSync30(rec.localPath) ?
|
|
9772
|
+
const sizeBytes = existsSync30(rec.localPath) ? statSync7(rec.localPath).size : 0;
|
|
9484
9773
|
clips.set(rec.id, { path: rec.localPath, mime: rec.mime });
|
|
9485
9774
|
recordings.delete(key2);
|
|
9486
9775
|
return { sizeBytes };
|
|
@@ -9557,7 +9846,7 @@ async function handlePreviewClip(res, url) {
|
|
|
9557
9846
|
res.setHeader("content-type", "application/json");
|
|
9558
9847
|
return void res.end(JSON.stringify({ error: "clip_not_found", id }));
|
|
9559
9848
|
}
|
|
9560
|
-
const size =
|
|
9849
|
+
const size = statSync7(clip.path).size;
|
|
9561
9850
|
res.statusCode = 200;
|
|
9562
9851
|
res.setHeader("content-type", clip.mime);
|
|
9563
9852
|
res.setHeader("content-length", String(size));
|
|
@@ -9571,7 +9860,7 @@ var init_preview = __esm({
|
|
|
9571
9860
|
DEVICE_LIST_TIMEOUT_MS = 5e3;
|
|
9572
9861
|
defaultRunner2 = {
|
|
9573
9862
|
capture(cmd, args, timeoutMs = DEFAULT_CAPTURE_TIMEOUT_MS) {
|
|
9574
|
-
return new Promise((
|
|
9863
|
+
return new Promise((resolve41, reject) => {
|
|
9575
9864
|
const child = spawn2(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
9576
9865
|
const out = [];
|
|
9577
9866
|
const err = [];
|
|
@@ -9593,7 +9882,7 @@ var init_preview = __esm({
|
|
|
9593
9882
|
child.stderr.on("data", (b) => err.push(b));
|
|
9594
9883
|
child.on("error", (e) => settle(reject, e));
|
|
9595
9884
|
child.on("close", (code) => {
|
|
9596
|
-
if (code === 0) settle(
|
|
9885
|
+
if (code === 0) settle(resolve41, Buffer.concat(out));
|
|
9597
9886
|
else settle(reject, new Error(`${cmd} exited ${code}: ${Buffer.concat(err).toString("utf8")}`));
|
|
9598
9887
|
});
|
|
9599
9888
|
});
|
|
@@ -11170,7 +11459,6 @@ function shouldRevealError(args) {
|
|
|
11170
11459
|
var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
|
|
11171
11460
|
var init_validation = __esm({
|
|
11172
11461
|
"../../core/ts/src/validation.ts"() {
|
|
11173
|
-
"use strict";
|
|
11174
11462
|
EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
|
|
11175
11463
|
URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
|
|
11176
11464
|
INTEGER_RE = /^[+-]?[0-9]+$/;
|
|
@@ -14516,7 +14804,6 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
|
|
|
14516
14804
|
var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
|
|
14517
14805
|
var init_worker_subtree = __esm({
|
|
14518
14806
|
"../../core/ts/src/worker-subtree.ts"() {
|
|
14519
|
-
"use strict";
|
|
14520
14807
|
init_worker_subtree_safe_types_generated();
|
|
14521
14808
|
WORKER_SUBTREE_CEILINGS = Object.freeze({
|
|
14522
14809
|
maxEncodedBytes: 65536,
|
|
@@ -14736,8 +15023,8 @@ function ensureCountUpRuntime() {
|
|
|
14736
15023
|
const neg = fixed.startsWith("-");
|
|
14737
15024
|
const body = neg ? fixed.slice(1) : fixed;
|
|
14738
15025
|
const [int, frac] = body.split(".");
|
|
14739
|
-
const
|
|
14740
|
-
return (neg ? "-" : "") +
|
|
15026
|
+
const sep11 = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
15027
|
+
return (neg ? "-" : "") + sep11 + (frac ? "." + frac : "");
|
|
14741
15028
|
};
|
|
14742
15029
|
const animateEl = (el) => {
|
|
14743
15030
|
const node = el;
|
|
@@ -19902,7 +20189,7 @@ async function stabilizePngPage(page, scheme) {
|
|
|
19902
20189
|
const browser = globalThis;
|
|
19903
20190
|
browser.document.documentElement.style.colorScheme = selected;
|
|
19904
20191
|
await browser.document.fonts?.ready;
|
|
19905
|
-
await new Promise((
|
|
20192
|
+
await new Promise((resolve41) => browser.requestAnimationFrame(() => browser.requestAnimationFrame(() => resolve41())));
|
|
19906
20193
|
}, scheme);
|
|
19907
20194
|
}
|
|
19908
20195
|
async function renderPngBatch(items) {
|
|
@@ -21914,18 +22201,18 @@ var init_motion_flags = __esm({
|
|
|
21914
22201
|
|
|
21915
22202
|
// ../../core/dev-server/src/kits.ts
|
|
21916
22203
|
import { readdirSync as readdirSync16, readFileSync as readFileSync36 } from "node:fs";
|
|
21917
|
-
import { resolve as resolve25, join as
|
|
22204
|
+
import { resolve as resolve25, join as join31 } from "node:path";
|
|
21918
22205
|
import { fileURLToPath as fileURLToPath15 } from "node:url";
|
|
21919
22206
|
function listKits() {
|
|
21920
22207
|
return readdirSync16(CATALOG).filter((f) => f.endsWith(".json")).map((f) => {
|
|
21921
|
-
const { tokens, ...meta } = JSON.parse(readFileSync36(
|
|
22208
|
+
const { tokens, ...meta } = JSON.parse(readFileSync36(join31(CATALOG, f), "utf8"));
|
|
21922
22209
|
return meta;
|
|
21923
22210
|
});
|
|
21924
22211
|
}
|
|
21925
22212
|
function readKit(id) {
|
|
21926
22213
|
if (!/^[a-z0-9-]+$/.test(id)) return null;
|
|
21927
22214
|
try {
|
|
21928
|
-
return JSON.parse(readFileSync36(
|
|
22215
|
+
return JSON.parse(readFileSync36(join31(CATALOG, `${id}.json`), "utf8"));
|
|
21929
22216
|
} catch {
|
|
21930
22217
|
return null;
|
|
21931
22218
|
}
|
|
@@ -21934,7 +22221,7 @@ var ROOT5, CATALOG;
|
|
|
21934
22221
|
var init_kits = __esm({
|
|
21935
22222
|
"../../core/dev-server/src/kits.ts"() {
|
|
21936
22223
|
ROOT5 = resolve25(fileURLToPath15(new URL("../../..", import.meta.url)));
|
|
21937
|
-
CATALOG =
|
|
22224
|
+
CATALOG = join31(ROOT5, "stdlib/design-kits");
|
|
21938
22225
|
}
|
|
21939
22226
|
});
|
|
21940
22227
|
|
|
@@ -24137,7 +24424,7 @@ __export(config_exports, {
|
|
|
24137
24424
|
validateOverlayPatch: () => validateOverlayPatch
|
|
24138
24425
|
});
|
|
24139
24426
|
import { mkdirSync as mkdirSync15, readFileSync as readFileSync38, writeFileSync as writeFileSync12 } from "node:fs";
|
|
24140
|
-
import { dirname as dirname21, join as
|
|
24427
|
+
import { dirname as dirname21, join as join32, resolve as resolve27 } from "node:path";
|
|
24141
24428
|
import { fileURLToPath as fileURLToPath16 } from "node:url";
|
|
24142
24429
|
function strip(line) {
|
|
24143
24430
|
const h = line.indexOf("#");
|
|
@@ -24202,14 +24489,14 @@ function parseRevocationsYaml(text2) {
|
|
|
24202
24489
|
function appConfigPath(app, file, root = REPO_ROOT6) {
|
|
24203
24490
|
assertAppId(app, "appConfigPath");
|
|
24204
24491
|
for (const base of ["apps", "test-apps"]) {
|
|
24205
|
-
const p =
|
|
24492
|
+
const p = join32(root, base, app, file);
|
|
24206
24493
|
try {
|
|
24207
24494
|
readFileSync38(p);
|
|
24208
24495
|
return p;
|
|
24209
24496
|
} catch {
|
|
24210
24497
|
}
|
|
24211
24498
|
}
|
|
24212
|
-
return
|
|
24499
|
+
return join32(root, "apps", app, file);
|
|
24213
24500
|
}
|
|
24214
24501
|
function serializeRolloutYaml(cfg) {
|
|
24215
24502
|
const lines = [`app: ${cfg.app}`, "rings:"];
|
|
@@ -24353,7 +24640,7 @@ var init_config2 = __esm({
|
|
|
24353
24640
|
import { createServer as createServer2 } from "node:http";
|
|
24354
24641
|
import { readFile as readFile2, stat } from "node:fs/promises";
|
|
24355
24642
|
import { readFileSync as readFileSync39, existsSync as existsSync33, watch, mkdirSync as mkdirSync16, rmSync as rmSync4 } from "node:fs";
|
|
24356
|
-
import { extname, resolve as resolve28, normalize as normalize3, sep as
|
|
24643
|
+
import { extname, resolve as resolve28, normalize as normalize3, sep as sep6, join as join33 } from "node:path";
|
|
24357
24644
|
import { createHash as createHash15, randomUUID } from "node:crypto";
|
|
24358
24645
|
import { fileURLToPath as fileURLToPath17, pathToFileURL as pathToFileURL6 } from "node:url";
|
|
24359
24646
|
function deepMerge2(base, patch) {
|
|
@@ -24528,7 +24815,7 @@ async function runScreenDiagnostics(state, screenId, descriptor) {
|
|
|
24528
24815
|
}
|
|
24529
24816
|
function servedFontFaces(appDir2, tokens) {
|
|
24530
24817
|
try {
|
|
24531
|
-
const policyPath =
|
|
24818
|
+
const policyPath = join33(appDir2, "fonts.json");
|
|
24532
24819
|
const policy = existsSync33(policyPath) ? JSON.parse(readFileSync39(policyPath, "utf8")) : {};
|
|
24533
24820
|
const plan = planFonts(tokens, policy);
|
|
24534
24821
|
if (plan.families.length === 0) return void 0;
|
|
@@ -25171,7 +25458,7 @@ function startBundleSourceWatcher(state) {
|
|
|
25171
25458
|
try {
|
|
25172
25459
|
const watcher = watch(TIER5_SRC_ROOT, { persistent: false, recursive: true }, (_event, filename) => {
|
|
25173
25460
|
if (!filename || !/\.(ts|tsx)$/.test(filename)) return;
|
|
25174
|
-
const name = filename.split(
|
|
25461
|
+
const name = filename.split(sep6)[0];
|
|
25175
25462
|
if (!name || name.startsWith(".")) return;
|
|
25176
25463
|
pending.add(name);
|
|
25177
25464
|
if (timer) clearTimeout(timer);
|
|
@@ -25201,7 +25488,7 @@ async function reloadAppModule(state, opts) {
|
|
|
25201
25488
|
const outfile = resolve28(HMR_TMP_DIR, `${current.name}-${++appReloadSeq}.mjs`);
|
|
25202
25489
|
try {
|
|
25203
25490
|
const lib = await import(pathToFileURL6(resolve28(TIER5_SRC_ROOT, "build-lib.mjs")).href);
|
|
25204
|
-
await lib.buildAppEntry(entry, outfile);
|
|
25491
|
+
await lib.buildAppEntry(entry, outfile, { confineTo: current.dir });
|
|
25205
25492
|
const mod = await import(pathToFileURL6(outfile).href);
|
|
25206
25493
|
const next = mod.default;
|
|
25207
25494
|
if (!next || !next.config || typeof next.homeScreenId !== "string" || !next.screens || typeof next.screens.exact !== "object" || Object.keys(next.screens.exact).length === 0 || !Array.isArray(next.actions) || !next.seed) {
|
|
@@ -25286,7 +25573,7 @@ function startAppSourceWatcher(state) {
|
|
|
25286
25573
|
try {
|
|
25287
25574
|
const watcher = watch(appDir2, { persistent: false, recursive: true }, (_event, filename) => {
|
|
25288
25575
|
if (!filename) return;
|
|
25289
|
-
const rel = String(filename).split(
|
|
25576
|
+
const rel = String(filename).split(sep6).join("/");
|
|
25290
25577
|
if (!classifyAppPath(rel)) return;
|
|
25291
25578
|
pending.add(rel);
|
|
25292
25579
|
if (timer) clearTimeout(timer);
|
|
@@ -25468,7 +25755,7 @@ async function handleWebWix(req, res, state) {
|
|
|
25468
25755
|
const match = state.wix.mode === "mock" ? matchRuleEx(state.wix.rules, method, target.pathname, { host: target.host, query, body }) : void 0;
|
|
25469
25756
|
if (match && (match.rule.kind ?? "mock") === "mock") {
|
|
25470
25757
|
const mocked = match.rule.response;
|
|
25471
|
-
if (mocked.delayMs) await new Promise((
|
|
25758
|
+
if (mocked.delayMs) await new Promise((resolve41) => setTimeout(resolve41, mocked.delayMs));
|
|
25472
25759
|
const responseBody = mocked.template ? renderTemplate(mocked.body, match.captures) : mocked.body;
|
|
25473
25760
|
recordWixTraffic(state.wix, state.appName, state.adminUrl, {
|
|
25474
25761
|
ts: started,
|
|
@@ -27448,7 +27735,7 @@ __export(build_exports2, {
|
|
|
27448
27735
|
});
|
|
27449
27736
|
import { createHash as createHash18 } from "node:crypto";
|
|
27450
27737
|
import { readFileSync as readFileSync40, readdirSync as readdirSync18, existsSync as existsSync34 } from "node:fs";
|
|
27451
|
-
import { dirname as dirname22, join as
|
|
27738
|
+
import { dirname as dirname22, join as join34, resolve as resolve29 } from "node:path";
|
|
27452
27739
|
import { fileURLToPath as fileURLToPath18 } from "node:url";
|
|
27453
27740
|
import { createRequire as createRequire2 } from "node:module";
|
|
27454
27741
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
@@ -27486,7 +27773,7 @@ function l10nLintOptions(locale, appDir2) {
|
|
|
27486
27773
|
const tags = (locale.translations ?? []).filter((t) => t !== locale.default);
|
|
27487
27774
|
const catalog = /* @__PURE__ */ new Set();
|
|
27488
27775
|
for (const tag of tags) {
|
|
27489
|
-
const path =
|
|
27776
|
+
const path = join34(appDir2, "l10n", `${tag}.json`);
|
|
27490
27777
|
if (!existsSync34(path)) continue;
|
|
27491
27778
|
try {
|
|
27492
27779
|
const parsed = JSON.parse(readFileSync40(path, "utf8"));
|
|
@@ -27583,7 +27870,7 @@ function shellSha(root = REPO_ROOT7) {
|
|
|
27583
27870
|
function isMonorepoCheckout(dir) {
|
|
27584
27871
|
try {
|
|
27585
27872
|
const top = execFileSync4("git", ["rev-parse", "--show-toplevel"], { cwd: dir, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
27586
|
-
return top.length > 0 && existsSync34(
|
|
27873
|
+
return top.length > 0 && existsSync34(join34(top, "core", "schema", "core.proto"));
|
|
27587
27874
|
} catch {
|
|
27588
27875
|
return false;
|
|
27589
27876
|
}
|
|
@@ -27813,7 +28100,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
27813
28100
|
if (addrCache.has(name)) return addrCache.get(name);
|
|
27814
28101
|
let bytes2;
|
|
27815
28102
|
try {
|
|
27816
|
-
bytes2 = readFileSync40(
|
|
28103
|
+
bytes2 = readFileSync40(join34(tier5Dir, `${name}.bundle.js`));
|
|
27817
28104
|
} catch {
|
|
27818
28105
|
return null;
|
|
27819
28106
|
}
|
|
@@ -27834,7 +28121,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
27834
28121
|
const MAX_AUTHORING_DOC_BYTES = 128 * 1024;
|
|
27835
28122
|
if (store.putDoc) {
|
|
27836
28123
|
for (const [name, file] of [["spec", "SPEC.md"], ["mobile-ux", "MOBILE-UX.md"]]) {
|
|
27837
|
-
const path =
|
|
28124
|
+
const path = join34(preloaded.dir, file);
|
|
27838
28125
|
if (!existsSync34(path)) continue;
|
|
27839
28126
|
const bytes2 = readFileSync40(path);
|
|
27840
28127
|
if (bytes2.length === 0 || bytes2.length > MAX_AUTHORING_DOC_BYTES) {
|
|
@@ -27894,7 +28181,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
27894
28181
|
const canEmitFonts = hasVendoredFloor();
|
|
27895
28182
|
try {
|
|
27896
28183
|
const appTokens = readTokensForLint(preloaded) ?? {};
|
|
27897
|
-
const policy = existsSync34(
|
|
28184
|
+
const policy = existsSync34(join34(preloaded.dir, "fonts.json")) ? JSON.parse(readFileSync40(join34(preloaded.dir, "fonts.json"), "utf8")) : {};
|
|
27898
28185
|
fontPlan = planFonts(appTokens, policy);
|
|
27899
28186
|
} catch (err) {
|
|
27900
28187
|
throw new Error(
|
|
@@ -28359,7 +28646,7 @@ async function buildFunctionsOnlyRelease(preloaded, dest) {
|
|
|
28359
28646
|
await store.reset(app);
|
|
28360
28647
|
const sources = {};
|
|
28361
28648
|
for (const definition of config.functions.functions) {
|
|
28362
|
-
const candidates = [".ts", ".js", ".mts", ".mjs"].map((extension) =>
|
|
28649
|
+
const candidates = [".ts", ".js", ".mts", ".mjs"].map((extension) => join34(preloaded.dir, "functions", `${definition.name}${extension}`));
|
|
28363
28650
|
const source = candidates.find((candidate) => existsSync34(candidate));
|
|
28364
28651
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
28365
28652
|
sources[definition.name] = readFileSync40(source, "utf8");
|
|
@@ -28390,7 +28677,7 @@ async function buildFunctionsOnlyRelease(preloaded, dest) {
|
|
|
28390
28677
|
return { manifest, failedToBuild: [], missingBundles: [], auth: {} };
|
|
28391
28678
|
}
|
|
28392
28679
|
function listBuildableApps() {
|
|
28393
|
-
const appsDir =
|
|
28680
|
+
const appsDir = join34(REPO_ROOT7, "apps");
|
|
28394
28681
|
return readdirSync18(appsDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("_")).map((d) => d.name);
|
|
28395
28682
|
}
|
|
28396
28683
|
var BAKE_OFFLINE_BASE, KNOWN_ICON_NAMES, KNOWN_ICONS, REPO_ROOT7, TIER5_DIR, requireFromHere, SOURCEMAP_ON_DEMAND_PATH, BAKED_SERVER_BASE_URL;
|
|
@@ -28421,9 +28708,9 @@ var init_build3 = __esm({
|
|
|
28421
28708
|
KNOWN_ICON_NAMES = [...ICON_NAMES].sort();
|
|
28422
28709
|
KNOWN_ICONS = new Set(KNOWN_ICON_NAMES);
|
|
28423
28710
|
REPO_ROOT7 = resolve29(dirname22(fileURLToPath18(import.meta.url)), "../..");
|
|
28424
|
-
TIER5_DIR =
|
|
28711
|
+
TIER5_DIR = join34(REPO_ROOT7, "core/dev-server/tier5-bundles");
|
|
28425
28712
|
requireFromHere = createRequire2(import.meta.url);
|
|
28426
|
-
SOURCEMAP_ON_DEMAND_PATH =
|
|
28713
|
+
SOURCEMAP_ON_DEMAND_PATH = join34(REPO_ROOT7, "core/dev-server/tier5-bundles-src/sourcemap-on-demand.mjs");
|
|
28427
28714
|
BAKED_SERVER_BASE_URL = "http://baked.himalaya.invalid";
|
|
28428
28715
|
}
|
|
28429
28716
|
});
|
|
@@ -28470,6 +28757,133 @@ var init_net_scenario = __esm({
|
|
|
28470
28757
|
}
|
|
28471
28758
|
});
|
|
28472
28759
|
|
|
28760
|
+
// ../../core/dev-server/src/crawl-relations.ts
|
|
28761
|
+
function inversePartner(action, declared) {
|
|
28762
|
+
if (/^toggle/i.test(action)) return null;
|
|
28763
|
+
const candidates = [];
|
|
28764
|
+
if (/^un[A-Z_a-z]/.test(action)) {
|
|
28765
|
+
candidates.push(lowerFirst(action.slice(2)), action.slice(2));
|
|
28766
|
+
} else {
|
|
28767
|
+
candidates.push("un" + action, "un" + upperFirst(action));
|
|
28768
|
+
}
|
|
28769
|
+
for (const c of candidates) if (c !== action && declared.includes(c)) return c;
|
|
28770
|
+
for (const [a, b] of PREFIX_PAIRS) {
|
|
28771
|
+
for (const [from, to] of [
|
|
28772
|
+
[a, b],
|
|
28773
|
+
[b, a]
|
|
28774
|
+
]) {
|
|
28775
|
+
if (!action.toLowerCase().startsWith(from)) continue;
|
|
28776
|
+
const rest = action.slice(from.length);
|
|
28777
|
+
for (const c of [to + rest, to + upperFirst(rest), to]) {
|
|
28778
|
+
if (c !== action && declared.includes(c)) return c;
|
|
28779
|
+
}
|
|
28780
|
+
}
|
|
28781
|
+
}
|
|
28782
|
+
return null;
|
|
28783
|
+
}
|
|
28784
|
+
function isUndoAction(action) {
|
|
28785
|
+
if (/^toggle/i.test(action)) return false;
|
|
28786
|
+
if (/^un[A-Z]/.test(action) || /^un[a-z]/.test(action)) return true;
|
|
28787
|
+
return PREFIX_PAIRS.some(([, undo]) => action.toLowerCase().startsWith(undo));
|
|
28788
|
+
}
|
|
28789
|
+
function isOptionSelection(params) {
|
|
28790
|
+
return Object.keys(params).some((k) => /^(selected|tab|segment|mode|scope)/i.test(k) || /Id$/.test(k) || k === "id");
|
|
28791
|
+
}
|
|
28792
|
+
function stripVolatile(value, depth = 0) {
|
|
28793
|
+
if (depth > 8 || value === null || typeof value !== "object") return value;
|
|
28794
|
+
if (Array.isArray(value)) return value.map((v) => stripVolatile(v, depth + 1));
|
|
28795
|
+
const out = {};
|
|
28796
|
+
for (const k of Object.keys(value).sort()) {
|
|
28797
|
+
if (VOLATILE_KEY.test(k)) continue;
|
|
28798
|
+
out[k] = stripVolatile(value[k], depth + 1);
|
|
28799
|
+
}
|
|
28800
|
+
return out;
|
|
28801
|
+
}
|
|
28802
|
+
function relationalSignature(state) {
|
|
28803
|
+
return JSON.stringify(stripVolatile(state));
|
|
28804
|
+
}
|
|
28805
|
+
function listLengths(state, depth = 4) {
|
|
28806
|
+
const out = {};
|
|
28807
|
+
const walk2 = (node, path, left) => {
|
|
28808
|
+
if (left < 0 || node === null || typeof node !== "object") return;
|
|
28809
|
+
if (Array.isArray(node)) {
|
|
28810
|
+
out[path] = node.length;
|
|
28811
|
+
return;
|
|
28812
|
+
}
|
|
28813
|
+
for (const [k, v] of Object.entries(node)) {
|
|
28814
|
+
walk2(v, path ? `${path}.${k}` : k, left - 1);
|
|
28815
|
+
}
|
|
28816
|
+
};
|
|
28817
|
+
walk2(state, "", depth);
|
|
28818
|
+
return out;
|
|
28819
|
+
}
|
|
28820
|
+
function summarizeDiff(aSig, bSig, limit = 3) {
|
|
28821
|
+
let a;
|
|
28822
|
+
let b;
|
|
28823
|
+
try {
|
|
28824
|
+
a = JSON.parse(aSig);
|
|
28825
|
+
b = JSON.parse(bSig);
|
|
28826
|
+
} catch {
|
|
28827
|
+
return aSig === bSig ? "" : "states differ (unparseable signature)";
|
|
28828
|
+
}
|
|
28829
|
+
const diffs = [];
|
|
28830
|
+
const brief = (v) => {
|
|
28831
|
+
const t = JSON.stringify(v);
|
|
28832
|
+
if (t === void 0) return "undefined";
|
|
28833
|
+
return t.length > 80 ? `${t.slice(0, 77)}\u2026` : t;
|
|
28834
|
+
};
|
|
28835
|
+
const walk2 = (x, y, path) => {
|
|
28836
|
+
if (diffs.length >= limit) return;
|
|
28837
|
+
const bothObjects = x !== null && y !== null && typeof x === "object" && typeof y === "object" && !Array.isArray(x) && !Array.isArray(y);
|
|
28838
|
+
if (bothObjects) {
|
|
28839
|
+
for (const k of /* @__PURE__ */ new Set([...Object.keys(x), ...Object.keys(y)])) {
|
|
28840
|
+
walk2(x[k], y[k], path ? `${path}.${k}` : k);
|
|
28841
|
+
}
|
|
28842
|
+
return;
|
|
28843
|
+
}
|
|
28844
|
+
if (Array.isArray(x) && Array.isArray(y)) {
|
|
28845
|
+
if (x.length !== y.length) {
|
|
28846
|
+
diffs.push(`${path || "state"}: ${x.length} \u2192 ${y.length} items`);
|
|
28847
|
+
return;
|
|
28848
|
+
}
|
|
28849
|
+
for (let i = 0; i < x.length && diffs.length < limit; i++) walk2(x[i], y[i], `${path}[${i}]`);
|
|
28850
|
+
return;
|
|
28851
|
+
}
|
|
28852
|
+
const xs = brief(x);
|
|
28853
|
+
const ys = brief(y);
|
|
28854
|
+
if (xs !== ys) diffs.push(`${path || "state"}: ${xs} \u2192 ${ys}`);
|
|
28855
|
+
};
|
|
28856
|
+
walk2(a, b, "");
|
|
28857
|
+
return diffs.slice(0, limit).join("; ");
|
|
28858
|
+
}
|
|
28859
|
+
var PREFIX_PAIRS, upperFirst, lowerFirst, REFRESH_ACTION, LOAD_MORE_ACTION, FILTER_ACTION, VOLATILE_KEY;
|
|
28860
|
+
var init_crawl_relations = __esm({
|
|
28861
|
+
"../../core/dev-server/src/crawl-relations.ts"() {
|
|
28862
|
+
PREFIX_PAIRS = [
|
|
28863
|
+
["add", "remove"],
|
|
28864
|
+
["add", "delete"],
|
|
28865
|
+
// NOT ["start", "stop"]. Measured 2026-09-16: it produced 2 warnings on unmutated, correct code
|
|
28866
|
+
// (voice-journal, `start → stop` and `startBackground → stop`, both leaving
|
|
28867
|
+
// `statusLabel: "Ready" → "Ready — recording stopped"`). start/stop is a LIFECYCLE pair, not an
|
|
28868
|
+
// algebraic inverse: stopping does not unmake the recording that was started, and an app is right
|
|
28869
|
+
// to say so. Only pairs where the undo genuinely restores the prior value belong here.
|
|
28870
|
+
["open", "close"],
|
|
28871
|
+
["show", "hide"],
|
|
28872
|
+
["expand", "collapse"],
|
|
28873
|
+
["select", "deselect"],
|
|
28874
|
+
["increment", "decrement"],
|
|
28875
|
+
["follow", "unfollow"],
|
|
28876
|
+
["save", "unsave"]
|
|
28877
|
+
];
|
|
28878
|
+
upperFirst = (s) => s ? s[0].toUpperCase() + s.slice(1) : s;
|
|
28879
|
+
lowerFirst = (s) => s ? s[0].toLowerCase() + s.slice(1) : s;
|
|
28880
|
+
REFRESH_ACTION = /^(refresh|reload|retry|sync|pullToRefresh)/i;
|
|
28881
|
+
LOAD_MORE_ACTION = /^(loadMore|nextPage|fetchMore)|^more$|More$|NextPage$/;
|
|
28882
|
+
FILTER_ACTION = /^(filter|search|query|sort)|(Filter|Search|Query|Sort)/;
|
|
28883
|
+
VOLATILE_KEY = /^_|^(id|uuid|guid|nonce|seed|token|timestamp|now|revision|etag)$|(Id|ID|Uuid|Guid|Nonce|Seed|Token|At|Timestamp|Ms|Revision|ETag)$/;
|
|
28884
|
+
}
|
|
28885
|
+
});
|
|
28886
|
+
|
|
28473
28887
|
// ../../core/dev-server/src/screen-crawl.ts
|
|
28474
28888
|
var screen_crawl_exports = {};
|
|
28475
28889
|
__export(screen_crawl_exports, {
|
|
@@ -28482,6 +28896,7 @@ __export(screen_crawl_exports, {
|
|
|
28482
28896
|
crawlScreenDeep: () => crawlScreenDeep,
|
|
28483
28897
|
crawlScreenHostile: () => crawlScreenHostile,
|
|
28484
28898
|
crawlScreenJourney: () => crawlScreenJourney,
|
|
28899
|
+
crawlScreenRelations: () => crawlScreenRelations,
|
|
28485
28900
|
crawlSignature: () => crawlSignature,
|
|
28486
28901
|
deepStateSignature: () => deepStateSignature,
|
|
28487
28902
|
emptiedArrays: () => emptiedArrays,
|
|
@@ -28492,6 +28907,7 @@ __export(screen_crawl_exports, {
|
|
|
28492
28907
|
parseWorkerAction: () => parseWorkerAction,
|
|
28493
28908
|
recordScreenTraffic: () => recordScreenTraffic,
|
|
28494
28909
|
rootOnAppear: () => rootOnAppear,
|
|
28910
|
+
snapshot: () => snapshot,
|
|
28495
28911
|
structuralSignature: () => structuralSignature,
|
|
28496
28912
|
unverifiableNodes: () => unverifiableNodes,
|
|
28497
28913
|
workerArgs: () => workerArgs
|
|
@@ -29727,7 +30143,209 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
29727
30143
|
return { findings: dedupe(findings), nodesVisited: visited.size, dispatches, capped };
|
|
29728
30144
|
});
|
|
29729
30145
|
}
|
|
29730
|
-
|
|
30146
|
+
function effectiveSiteForRow(site, row) {
|
|
30147
|
+
const merged = { ...site.params ?? {}, ...site.args ?? {} };
|
|
30148
|
+
const substituted = {};
|
|
30149
|
+
for (const [k, v] of Object.entries(merged)) {
|
|
30150
|
+
substituted[k] = typeof v === "string" && v.startsWith("$item.") ? pathValue(row, v.slice("$item.".length)) : v === "$item" ? row : v;
|
|
30151
|
+
}
|
|
30152
|
+
return { ...site, params: substituted, args: void 0 };
|
|
30153
|
+
}
|
|
30154
|
+
function isRowBound(site) {
|
|
30155
|
+
const payload = { ...site.params ?? {}, ...site.args ?? {} };
|
|
30156
|
+
return Object.values(payload).some((v) => typeof v === "string" && (v === "$item" || v.startsWith("$item.")));
|
|
30157
|
+
}
|
|
30158
|
+
function collectItemsPaths(node, out = /* @__PURE__ */ new Set()) {
|
|
30159
|
+
if (!node || typeof node !== "object") return out;
|
|
30160
|
+
if (Array.isArray(node)) {
|
|
30161
|
+
for (const n of node) collectItemsPaths(n, out);
|
|
30162
|
+
return out;
|
|
30163
|
+
}
|
|
30164
|
+
const rec = node;
|
|
30165
|
+
const body = rec.body;
|
|
30166
|
+
if (body && typeof body === "object" && typeof body.type === "string" && body.props && typeof body.props === "object") {
|
|
30167
|
+
const itemsPath = body.props.itemsPath;
|
|
30168
|
+
if (typeof itemsPath === "string") out.add(itemsPath);
|
|
30169
|
+
}
|
|
30170
|
+
for (const v of Object.values(rec)) collectItemsPaths(v, out);
|
|
30171
|
+
return out;
|
|
30172
|
+
}
|
|
30173
|
+
function newlyAddedRow(before, after, itemsPath) {
|
|
30174
|
+
if (!itemsPath || itemsPath === UNTRACKED_ITEMS) return null;
|
|
30175
|
+
const rowsOf = (s) => {
|
|
30176
|
+
const provider = new FakeServiceProvider(s);
|
|
30177
|
+
const v = resolveSiteRows(itemsPath, (p) => provider.value(p));
|
|
30178
|
+
return Array.isArray(v) ? v.filter((r) => r && typeof r === "object") : [];
|
|
30179
|
+
};
|
|
30180
|
+
const seen = new Set(rowsOf(before).map((r) => relationalSignature(r)));
|
|
30181
|
+
const fresh = rowsOf(after).filter((r) => !seen.has(relationalSignature(r)));
|
|
30182
|
+
return fresh.length === 1 ? fresh[0] : null;
|
|
30183
|
+
}
|
|
30184
|
+
async function crawlScreenRelations(opts) {
|
|
30185
|
+
return withSwallowedRejections(async () => {
|
|
30186
|
+
const { screenId, descriptor, bundleJs } = opts;
|
|
30187
|
+
const findings = [];
|
|
30188
|
+
const byKind = { inverse: 0, refresh: 0, loadMore: 0, filter: 0 };
|
|
30189
|
+
let checked = 0;
|
|
30190
|
+
if (!bundleJs) return { findings, checked, byKind };
|
|
30191
|
+
const layered = layeredTransport({ rules: opts.rules, cmsSeed: opts.cmsSeed, canned: opts.canned });
|
|
30192
|
+
const wixCall = opts.transportWrap ? opts.transportWrap(layered.call) : layered.call;
|
|
30193
|
+
const sites = actionSitesForDescriptor(descriptor).filter(
|
|
30194
|
+
(s) => parseWorkerAction(s.actionId) && !opts.skipAction?.(s.actionId, s.componentId)
|
|
30195
|
+
);
|
|
30196
|
+
const nameOf = (s) => parseWorkerAction(s.actionId).action;
|
|
30197
|
+
const serviceOf = (s) => parseWorkerAction(s.actionId).service;
|
|
30198
|
+
const boot = () => bootScreenWorker({
|
|
30199
|
+
bundleJs,
|
|
30200
|
+
descriptor,
|
|
30201
|
+
wixCall,
|
|
30202
|
+
screenId,
|
|
30203
|
+
inputOverride: opts.inputOverride,
|
|
30204
|
+
budgetMs: opts.budgetMs,
|
|
30205
|
+
clock: opts.clock,
|
|
30206
|
+
seed: opts.seed,
|
|
30207
|
+
localDbSchema: opts.localDbSchema,
|
|
30208
|
+
...opts.evaluator ? { evaluator: opts.evaluator } : {}
|
|
30209
|
+
});
|
|
30210
|
+
const replay = async (path, rowFor = () => null) => {
|
|
30211
|
+
const w = await boot();
|
|
30212
|
+
try {
|
|
30213
|
+
if (w.errors.length) return null;
|
|
30214
|
+
let prev = snapshot(w).state;
|
|
30215
|
+
const bootState = prev;
|
|
30216
|
+
for (const [i, site] of path.entries()) {
|
|
30217
|
+
const parsed = parseWorkerAction(site.actionId);
|
|
30218
|
+
const h = w.handles[parsed.service];
|
|
30219
|
+
if (!h || !h.actionNames().includes(parsed.action)) return null;
|
|
30220
|
+
const pinned = rowFor(i, bootState, prev);
|
|
30221
|
+
if (pinned === UNBINDABLE_ROW) return null;
|
|
30222
|
+
const eff = pinned ? effectiveSiteForRow(site, pinned) : effectiveSiteFor(site, prev);
|
|
30223
|
+
if (!eff) return null;
|
|
30224
|
+
try {
|
|
30225
|
+
await h.dispatch(parsed.action, ...workerArgs(eff));
|
|
30226
|
+
} catch {
|
|
30227
|
+
return null;
|
|
30228
|
+
}
|
|
30229
|
+
for (let k = 0; k < 20; k++) await yieldMacrotask();
|
|
30230
|
+
if (w.errors.length) return null;
|
|
30231
|
+
prev = snapshot(w).state;
|
|
30232
|
+
}
|
|
30233
|
+
return prev;
|
|
30234
|
+
} finally {
|
|
30235
|
+
w.dispose();
|
|
30236
|
+
}
|
|
30237
|
+
};
|
|
30238
|
+
const base = await replay([]);
|
|
30239
|
+
if (!base || Object.values(base).some(hasOwnError)) return { findings, checked, byKind };
|
|
30240
|
+
const baseSig = relationalSignature(base);
|
|
30241
|
+
const baseLens = listLengths(base);
|
|
30242
|
+
const listPathOf = (itemsPath) => {
|
|
30243
|
+
if (!itemsPath || itemsPath === UNTRACKED_ITEMS || itemsPath.includes("[]")) return null;
|
|
30244
|
+
const m = /^\$service:(.+)$/.exec(itemsPath);
|
|
30245
|
+
return m && baseLens[m[1]] !== void 0 ? m[1] : null;
|
|
30246
|
+
};
|
|
30247
|
+
const screenListPaths = [
|
|
30248
|
+
...new Set(
|
|
30249
|
+
[...collectItemsPaths(descriptor)].map(listPathOf).filter((x) => x !== null)
|
|
30250
|
+
)
|
|
30251
|
+
];
|
|
30252
|
+
const trig = (s) => ({ tap: s.componentId, key: s.key, action: s.actionId });
|
|
30253
|
+
for (const s of sites.filter((s2) => REFRESH_ACTION.test(nameOf(s2)) || s2.key === "onPullToRefresh")) {
|
|
30254
|
+
const after = await replay([s]);
|
|
30255
|
+
if (!after) continue;
|
|
30256
|
+
checked++;
|
|
30257
|
+
byKind.refresh++;
|
|
30258
|
+
const sig = relationalSignature(after);
|
|
30259
|
+
if (sig !== baseSig) {
|
|
30260
|
+
findings.push({
|
|
30261
|
+
screen: screenId,
|
|
30262
|
+
trigger: trig(s),
|
|
30263
|
+
invariant: "refresh-not-idempotent",
|
|
30264
|
+
severity: "warning",
|
|
30265
|
+
axis: "relation",
|
|
30266
|
+
message: `${nameOf(s)} from a fresh boot settles on a different state than the boot itself, under identical data: ${summarizeDiff(baseSig, sig)}`,
|
|
30267
|
+
hint: "a refresh that appends instead of replacing, or clears a flag the loader set \u2014 REPLACE collections on refresh; ids, *At and _counters are already ignored by this comparison"
|
|
30268
|
+
});
|
|
30269
|
+
}
|
|
30270
|
+
}
|
|
30271
|
+
for (const s of sites.filter((s2) => LOAD_MORE_ACTION.test(nameOf(s2)) || s2.key === "onLoadMore")) {
|
|
30272
|
+
const target = listPathOf(s.itemsPath);
|
|
30273
|
+
const after = target ? await replay([s]) : null;
|
|
30274
|
+
if (!after) continue;
|
|
30275
|
+
checked++;
|
|
30276
|
+
byKind.loadMore++;
|
|
30277
|
+
for (const [p, n] of Object.entries(listLengths(after))) {
|
|
30278
|
+
if (p === target && baseLens[p] !== void 0 && n < baseLens[p]) {
|
|
30279
|
+
findings.push({
|
|
30280
|
+
screen: screenId,
|
|
30281
|
+
trigger: trig(s),
|
|
30282
|
+
invariant: "list-shrank-on-load-more",
|
|
30283
|
+
severity: "warning",
|
|
30284
|
+
axis: "relation",
|
|
30285
|
+
at: p,
|
|
30286
|
+
actual: `${baseLens[p]} \u2192 ${n}`,
|
|
30287
|
+
message: `${nameOf(s)} shrank ${p} from ${baseLens[p]} to ${n} rows \u2014 a "load more" that replaces the page instead of appending it`,
|
|
30288
|
+
hint: "append the new page to the existing rows (and de-duplicate by id); the user scrolled to see MORE"
|
|
30289
|
+
});
|
|
30290
|
+
}
|
|
30291
|
+
}
|
|
30292
|
+
}
|
|
30293
|
+
for (const s of sites.filter((s2) => FILTER_ACTION.test(nameOf(s2)) && !isOptionSelection({ ...s2.params, ...s2.args }))) {
|
|
30294
|
+
if (screenListPaths.length !== 1) continue;
|
|
30295
|
+
const after = await replay([s]);
|
|
30296
|
+
if (!after) continue;
|
|
30297
|
+
checked++;
|
|
30298
|
+
byKind.filter++;
|
|
30299
|
+
for (const [p, n] of Object.entries(listLengths(after))) {
|
|
30300
|
+
if (screenListPaths.includes(p) && baseLens[p] !== void 0 && n > baseLens[p]) {
|
|
30301
|
+
findings.push({
|
|
30302
|
+
screen: screenId,
|
|
30303
|
+
trigger: trig(s),
|
|
30304
|
+
invariant: "list-grew-on-filter",
|
|
30305
|
+
severity: "warning",
|
|
30306
|
+
axis: "relation",
|
|
30307
|
+
at: p,
|
|
30308
|
+
actual: `${baseLens[p]} \u2192 ${n}`,
|
|
30309
|
+
message: `${nameOf(s)} grew ${p} from ${baseLens[p]} to ${n} rows \u2014 a filter/search/sort can narrow or reorder a list, never enlarge it`,
|
|
30310
|
+
hint: "filter from the FULL set you keep aside, and assign the narrowed result \u2014 not a concatenation"
|
|
30311
|
+
});
|
|
30312
|
+
}
|
|
30313
|
+
}
|
|
30314
|
+
}
|
|
30315
|
+
const declaredNames = sites.map(nameOf);
|
|
30316
|
+
for (const a of sites) {
|
|
30317
|
+
const partner = inversePartner(nameOf(a), declaredNames);
|
|
30318
|
+
if (!partner) continue;
|
|
30319
|
+
if (isUndoAction(nameOf(a))) continue;
|
|
30320
|
+
const b = sites.find((s) => nameOf(s) === partner && serviceOf(s) === serviceOf(a) && s !== a);
|
|
30321
|
+
if (!b) continue;
|
|
30322
|
+
const undoIsRowBound = isRowBound(b);
|
|
30323
|
+
const after = await replay([a, b], (i, bootState, prev) => {
|
|
30324
|
+
if (i !== 1) return null;
|
|
30325
|
+
const row = newlyAddedRow(bootState, prev, b.itemsPath);
|
|
30326
|
+
if (row) return row;
|
|
30327
|
+
return undoIsRowBound ? UNBINDABLE_ROW : null;
|
|
30328
|
+
});
|
|
30329
|
+
if (!after) continue;
|
|
30330
|
+
checked++;
|
|
30331
|
+
byKind.inverse++;
|
|
30332
|
+
const sig = relationalSignature(after);
|
|
30333
|
+
if (sig !== baseSig) {
|
|
30334
|
+
findings.push({
|
|
30335
|
+
screen: screenId,
|
|
30336
|
+
trigger: trig(b),
|
|
30337
|
+
invariant: "inverse-pair-diverges",
|
|
30338
|
+
severity: "warning",
|
|
30339
|
+
axis: "relation",
|
|
30340
|
+
message: `${nameOf(a)} \u2192 ${nameOf(b)} does not return to the boot state: ${summarizeDiff(baseSig, sig)}`,
|
|
30341
|
+
hint: `${nameOf(b)} should undo exactly what ${nameOf(a)} did \u2014 check which row it removes (by the id it was given) and every field ${nameOf(a)} touched; ids, *At and _counters are already ignored`
|
|
30342
|
+
});
|
|
30343
|
+
}
|
|
30344
|
+
}
|
|
30345
|
+
return { findings: dedupe(findings), checked, byKind };
|
|
30346
|
+
});
|
|
30347
|
+
}
|
|
30348
|
+
var ACTION_KEYS, UNTRACKED_ITEMS, NESTED_ITEMS_SEP, REJECT_ALL_MESSAGE, VLQ, WIX_DATA_QUERY, WIX_DATA_ANY, CAPABILITY_ACTION, BLANK_WHEN_BOUND, UNBINDABLE_ROW;
|
|
29731
30349
|
var init_screen_crawl = __esm({
|
|
29732
30350
|
"../../core/dev-server/src/screen-crawl.ts"() {
|
|
29733
30351
|
init_validate_descriptor_core();
|
|
@@ -29737,6 +30355,7 @@ var init_screen_crawl = __esm({
|
|
|
29737
30355
|
init_FakeServiceProvider();
|
|
29738
30356
|
init_actionParams();
|
|
29739
30357
|
init_implications();
|
|
30358
|
+
init_crawl_relations();
|
|
29740
30359
|
ACTION_KEYS = [
|
|
29741
30360
|
"action",
|
|
29742
30361
|
"onTap",
|
|
@@ -29760,6 +30379,7 @@ var init_screen_crawl = __esm({
|
|
|
29760
30379
|
Marquee: ["items", "itemsPath", "text"],
|
|
29761
30380
|
MediaPlayer: ["items", "itemsPath"]
|
|
29762
30381
|
};
|
|
30382
|
+
UNBINDABLE_ROW = Symbol("unbindable-row");
|
|
29763
30383
|
}
|
|
29764
30384
|
});
|
|
29765
30385
|
|
|
@@ -30315,8 +30935,8 @@ __export(pack_exports, {
|
|
|
30315
30935
|
});
|
|
30316
30936
|
import { createHash as createHash19 } from "node:crypto";
|
|
30317
30937
|
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
30318
|
-
import { existsSync as existsSync35, mkdirSync as mkdirSync17, readFileSync as readFileSync42, readdirSync as readdirSync19, rmSync as rmSync5, statSync as
|
|
30319
|
-
import { dirname as dirname23, join as
|
|
30938
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync17, readFileSync as readFileSync42, readdirSync as readdirSync19, rmSync as rmSync5, statSync as statSync8, writeFileSync as writeFileSync13 } from "node:fs";
|
|
30939
|
+
import { dirname as dirname23, join as join35, resolve as resolve31 } from "node:path";
|
|
30320
30940
|
function writeZip(entries) {
|
|
30321
30941
|
const sorted = entries.slice().sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
30322
30942
|
const total = sorted.reduce((n, e) => n + e.bytes.length, 0);
|
|
@@ -30410,13 +31030,13 @@ function inflateEntry(buf, entry) {
|
|
|
30410
31030
|
return bytes2;
|
|
30411
31031
|
}
|
|
30412
31032
|
function readIf(path) {
|
|
30413
|
-
return existsSync35(path) &&
|
|
31033
|
+
return existsSync35(path) && statSync8(path).isFile() ? readFileSync42(path) : null;
|
|
30414
31034
|
}
|
|
30415
31035
|
function listDir(dir) {
|
|
30416
|
-
return existsSync35(dir) ? readdirSync19(dir).filter((f) =>
|
|
31036
|
+
return existsSync35(dir) ? readdirSync19(dir).filter((f) => statSync8(join35(dir, f)).isFile()) : [];
|
|
30417
31037
|
}
|
|
30418
31038
|
function gatherReleaseEntries(appDir2) {
|
|
30419
|
-
const manifestPath =
|
|
31039
|
+
const manifestPath = join35(appDir2, HIMI_PACKAGE_MANIFEST_PATH);
|
|
30420
31040
|
const manifestBytes = readIf(manifestPath);
|
|
30421
31041
|
if (!manifestBytes) throw new Error(`no ${HIMI_PACKAGE_MANIFEST_PATH} in ${appDir2} \u2014 build a release there first`);
|
|
30422
31042
|
const manifest = JSON.parse(manifestBytes.toString("utf8"));
|
|
@@ -30440,7 +31060,7 @@ function gatherReleaseEntries(appDir2) {
|
|
|
30440
31060
|
}
|
|
30441
31061
|
const missing = [];
|
|
30442
31062
|
for (const rel of wanted) {
|
|
30443
|
-
const bytes2 = readIf(
|
|
31063
|
+
const bytes2 = readIf(join35(appDir2, rel));
|
|
30444
31064
|
if (bytes2) entries.push({ path: rel, bytes: bytes2 });
|
|
30445
31065
|
else missing.push(rel);
|
|
30446
31066
|
}
|
|
@@ -30451,12 +31071,12 @@ function gatherReleaseEntries(appDir2) {
|
|
|
30451
31071
|
);
|
|
30452
31072
|
}
|
|
30453
31073
|
for (const name of SINGLETONS) {
|
|
30454
|
-
const bytes2 = readIf(
|
|
31074
|
+
const bytes2 = readIf(join35(appDir2, name));
|
|
30455
31075
|
if (bytes2) entries.push({ path: name, bytes: bytes2 });
|
|
30456
31076
|
}
|
|
30457
31077
|
const skipped = [];
|
|
30458
31078
|
for (const sub of ["screens", "bundles", "assets", "widgets"]) {
|
|
30459
|
-
for (const f of listDir(
|
|
31079
|
+
for (const f of listDir(join35(appDir2, sub))) {
|
|
30460
31080
|
if (!wanted.has(`${sub}/${f}`)) skipped.push(`${sub}/${f}`);
|
|
30461
31081
|
}
|
|
30462
31082
|
}
|
|
@@ -30487,18 +31107,18 @@ function buildEntries(appDir2, app, opts) {
|
|
|
30487
31107
|
return { all, header, manifest, skipped };
|
|
30488
31108
|
}
|
|
30489
31109
|
function packRelease(releaseRoot, app, out, opts = {}) {
|
|
30490
|
-
const appDir2 =
|
|
31110
|
+
const appDir2 = join35(resolve31(releaseRoot), app);
|
|
30491
31111
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
30492
31112
|
const buf = writeZip(all);
|
|
30493
|
-
const isDir = existsSync35(out) &&
|
|
30494
|
-
const outFile = isDir ?
|
|
31113
|
+
const isDir = existsSync35(out) && statSync8(out).isDirectory();
|
|
31114
|
+
const outFile = isDir ? join35(resolve31(out), packageFileName(app, header.releaseId)) : resolve31(out);
|
|
30495
31115
|
mkdirSync17(dirname23(outFile), { recursive: true });
|
|
30496
31116
|
writeFileSync13(outFile, buf);
|
|
30497
31117
|
return { app, releaseId: header.releaseId, header, out: outFile, bytes: buf.length, entryCount: all.length, skipped };
|
|
30498
31118
|
}
|
|
30499
31119
|
function resolvePackageDirDest(outDir, app, releaseId) {
|
|
30500
31120
|
const packagedApp = (dir) => {
|
|
30501
|
-
const bytes2 = readIf(
|
|
31121
|
+
const bytes2 = readIf(join35(dir, HIMI_PACKAGE_HEADER_PATH));
|
|
30502
31122
|
if (!bytes2) return void 0;
|
|
30503
31123
|
try {
|
|
30504
31124
|
return JSON.parse(bytes2.toString("utf8")).app;
|
|
@@ -30508,14 +31128,14 @@ function resolvePackageDirDest(outDir, app, releaseId) {
|
|
|
30508
31128
|
};
|
|
30509
31129
|
const replaceable = (dir) => {
|
|
30510
31130
|
if (!existsSync35(dir)) return true;
|
|
30511
|
-
if (!
|
|
31131
|
+
if (!statSync8(dir).isDirectory()) return false;
|
|
30512
31132
|
return readdirSync19(dir).length === 0 || packagedApp(dir) === app;
|
|
30513
31133
|
};
|
|
30514
|
-
if (existsSync35(outDir) && !
|
|
31134
|
+
if (existsSync35(outDir) && !statSync8(outDir).isDirectory()) {
|
|
30515
31135
|
throw new Error(`refusing to write a package tree over ${outDir} \u2014 it is a file, not a directory`);
|
|
30516
31136
|
}
|
|
30517
31137
|
if (replaceable(outDir)) return outDir;
|
|
30518
|
-
const child =
|
|
31138
|
+
const child = join35(outDir, packageDirName(app, releaseId));
|
|
30519
31139
|
if (!replaceable(child)) {
|
|
30520
31140
|
throw new Error(
|
|
30521
31141
|
`refusing to replace ${child}: it is not empty and is not a ${app} package (no ${HIMI_PACKAGE_HEADER_PATH}). Pass --out to a new or empty directory.`
|
|
@@ -30524,13 +31144,13 @@ function resolvePackageDirDest(outDir, app, releaseId) {
|
|
|
30524
31144
|
return child;
|
|
30525
31145
|
}
|
|
30526
31146
|
function packReleaseToDir(releaseRoot, app, outDir, opts = {}) {
|
|
30527
|
-
const appDir2 =
|
|
31147
|
+
const appDir2 = join35(resolve31(releaseRoot), app);
|
|
30528
31148
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
30529
31149
|
const dest = resolvePackageDirDest(resolve31(outDir), app, header.releaseId);
|
|
30530
31150
|
rmSync5(dest, { recursive: true, force: true });
|
|
30531
31151
|
let bytes2 = 0;
|
|
30532
31152
|
for (const entry of all) {
|
|
30533
|
-
const target =
|
|
31153
|
+
const target = join35(dest, entry.path);
|
|
30534
31154
|
mkdirSync17(dirname23(target), { recursive: true });
|
|
30535
31155
|
writeFileSync13(target, entry.bytes);
|
|
30536
31156
|
bytes2 += entry.bytes.length;
|
|
@@ -30559,11 +31179,11 @@ function openPackageDir(dir) {
|
|
|
30559
31179
|
const root = resolve31(dir);
|
|
30560
31180
|
const entries = /* @__PURE__ */ new Map();
|
|
30561
31181
|
const walk2 = (rel) => {
|
|
30562
|
-
const abs = rel ?
|
|
31182
|
+
const abs = rel ? join35(root, rel) : root;
|
|
30563
31183
|
for (const name of readdirSync19(abs)) {
|
|
30564
31184
|
const childRel = rel ? `${rel}/${name}` : name;
|
|
30565
|
-
const childAbs =
|
|
30566
|
-
if (
|
|
31185
|
+
const childAbs = join35(abs, name);
|
|
31186
|
+
if (statSync8(childAbs).isDirectory()) walk2(childRel);
|
|
30567
31187
|
else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync42(childAbs));
|
|
30568
31188
|
}
|
|
30569
31189
|
};
|
|
@@ -30601,10 +31221,10 @@ function unpackTo(buf, dest, appFallback) {
|
|
|
30601
31221
|
if (!app) throw new Error("package declares no app id (no himi-package.json and no manifest.app)");
|
|
30602
31222
|
if (!isSafeAppId(app)) throw new Error(`package declares an unsafe app id ${JSON.stringify(app)} \u2014 refusing to unpack it`);
|
|
30603
31223
|
const root = resolve31(dest);
|
|
30604
|
-
const appDir2 =
|
|
31224
|
+
const appDir2 = join35(root, app);
|
|
30605
31225
|
rmSync5(appDir2, { recursive: true, force: true });
|
|
30606
31226
|
for (const [rel, bytes2] of entries) {
|
|
30607
|
-
const target =
|
|
31227
|
+
const target = join35(appDir2, rel);
|
|
30608
31228
|
mkdirSync17(dirname23(target), { recursive: true });
|
|
30609
31229
|
writeFileSync13(target, bytes2);
|
|
30610
31230
|
}
|
|
@@ -30629,38 +31249,49 @@ var app_source_exports = {};
|
|
|
30629
31249
|
__export(app_source_exports, {
|
|
30630
31250
|
MAX_APP_SOURCE_BYTES: () => MAX_APP_SOURCE_BYTES,
|
|
30631
31251
|
collectAppSource: () => collectAppSource,
|
|
31252
|
+
deniedArchivePaths: () => deniedArchivePaths,
|
|
30632
31253
|
isDeniedSourcePath: () => isDeniedSourcePath,
|
|
30633
31254
|
readAppSource: () => readAppSource,
|
|
31255
|
+
removeStaleSource: () => removeStaleSource,
|
|
30634
31256
|
secretFindings: () => secretFindings,
|
|
31257
|
+
staleSourcePaths: () => staleSourcePaths,
|
|
30635
31258
|
writeAppSource: () => writeAppSource,
|
|
31259
|
+
writeConflicts: () => writeConflicts,
|
|
30636
31260
|
zipAppSource: () => zipAppSource
|
|
30637
31261
|
});
|
|
30638
|
-
import { readdirSync as readdirSync20, lstatSync as lstatSync4, readFileSync as readFileSync43, mkdirSync as mkdirSync18, writeFileSync as writeFileSync14 } from "node:fs";
|
|
30639
|
-
import { join as
|
|
30640
|
-
function
|
|
30641
|
-
const entries = [];
|
|
30642
|
-
const skipped = [];
|
|
31262
|
+
import { readdirSync as readdirSync20, lstatSync as lstatSync4, readFileSync as readFileSync43, mkdirSync as mkdirSync18, writeFileSync as writeFileSync14, existsSync as existsSync36, rmSync as rmSync6, rmdirSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
31263
|
+
import { join as join36, resolve as resolve32, sep as sep7 } from "node:path";
|
|
31264
|
+
function walkSourceTree(dir, file, skip) {
|
|
30643
31265
|
const walk2 = (relDir) => {
|
|
30644
|
-
for (const name of readdirSync20(
|
|
30645
|
-
const rel = relDir ?
|
|
30646
|
-
const st = lstatSync4(
|
|
31266
|
+
for (const name of readdirSync20(join36(dir, relDir))) {
|
|
31267
|
+
const rel = relDir ? join36(relDir, name) : name;
|
|
31268
|
+
const st = lstatSync4(join36(dir, rel));
|
|
30647
31269
|
if (st.isSymbolicLink()) {
|
|
30648
|
-
|
|
31270
|
+
skip(rel);
|
|
30649
31271
|
continue;
|
|
30650
31272
|
}
|
|
30651
31273
|
if (st.isDirectory()) {
|
|
30652
|
-
if (isDeniedSourceDir(name))
|
|
31274
|
+
if (isDeniedSourceDir(name)) skip(rel);
|
|
30653
31275
|
else walk2(rel);
|
|
30654
31276
|
continue;
|
|
30655
31277
|
}
|
|
30656
31278
|
if (isDeniedSourcePath(rel)) {
|
|
30657
|
-
|
|
31279
|
+
skip(rel);
|
|
30658
31280
|
continue;
|
|
30659
31281
|
}
|
|
30660
|
-
|
|
31282
|
+
file(rel.split(sep7).join("/"), rel);
|
|
30661
31283
|
}
|
|
30662
31284
|
};
|
|
30663
31285
|
walk2("");
|
|
31286
|
+
}
|
|
31287
|
+
function collectAppSource(dir) {
|
|
31288
|
+
const entries = [];
|
|
31289
|
+
const skipped = [];
|
|
31290
|
+
walkSourceTree(
|
|
31291
|
+
dir,
|
|
31292
|
+
(archivePath, hostRel) => entries.push({ path: archivePath, bytes: readFileSync43(join36(dir, hostRel)) }),
|
|
31293
|
+
(hostRel) => skipped.push(hostRel)
|
|
31294
|
+
);
|
|
30664
31295
|
entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
30665
31296
|
skipped.sort();
|
|
30666
31297
|
return { entries, skipped };
|
|
@@ -30680,16 +31311,115 @@ function zipAppSource(entries) {
|
|
|
30680
31311
|
function readAppSource(zip) {
|
|
30681
31312
|
return [...readZip(zip)].map(([path, bytes2]) => ({ path, bytes: bytes2 }));
|
|
30682
31313
|
}
|
|
31314
|
+
function pathKind(p) {
|
|
31315
|
+
try {
|
|
31316
|
+
return lstatSync4(p);
|
|
31317
|
+
} catch {
|
|
31318
|
+
return null;
|
|
31319
|
+
}
|
|
31320
|
+
}
|
|
30683
31321
|
function writeAppSource(entries, destDir) {
|
|
31322
|
+
const root = resolve32(destDir);
|
|
31323
|
+
mkdirSync18(root, { recursive: true });
|
|
30684
31324
|
const written = [];
|
|
30685
31325
|
for (const entry of entries) {
|
|
30686
|
-
|
|
30687
|
-
|
|
31326
|
+
if (isDeniedSourcePath(entry.path)) continue;
|
|
31327
|
+
const segments = entry.path.split("/");
|
|
31328
|
+
let dir = root;
|
|
31329
|
+
for (const segment of segments.slice(0, -1)) {
|
|
31330
|
+
dir = join36(dir, segment);
|
|
31331
|
+
const kind = pathKind(dir);
|
|
31332
|
+
if (kind?.isSymbolicLink()) unlinkSync3(dir);
|
|
31333
|
+
else if (kind) continue;
|
|
31334
|
+
mkdirSync18(dir);
|
|
31335
|
+
}
|
|
31336
|
+
const target = join36(root, ...segments);
|
|
31337
|
+
if (pathKind(target)?.isSymbolicLink()) unlinkSync3(target);
|
|
30688
31338
|
writeFileSync14(target, entry.bytes);
|
|
30689
31339
|
written.push(entry.path);
|
|
30690
31340
|
}
|
|
30691
31341
|
return written;
|
|
30692
31342
|
}
|
|
31343
|
+
function staleSourcePaths(entries, destDir) {
|
|
31344
|
+
if (!existsSync36(destDir)) return [];
|
|
31345
|
+
const archived = new Set(entries.map((e) => e.path));
|
|
31346
|
+
const stale = [];
|
|
31347
|
+
walkSourceTree(destDir, (archivePath) => {
|
|
31348
|
+
if (!archived.has(archivePath)) stale.push(archivePath);
|
|
31349
|
+
}, () => {
|
|
31350
|
+
});
|
|
31351
|
+
return stale.sort();
|
|
31352
|
+
}
|
|
31353
|
+
function deniedArchivePaths(entries) {
|
|
31354
|
+
return entries.filter((e) => isDeniedSourcePath(e.path)).map((e) => e.path).sort();
|
|
31355
|
+
}
|
|
31356
|
+
function writeConflicts(entries, destDir) {
|
|
31357
|
+
const root = resolve32(destDir);
|
|
31358
|
+
const conflicts = [];
|
|
31359
|
+
const seen = /* @__PURE__ */ new Set();
|
|
31360
|
+
const say = (rel, what) => {
|
|
31361
|
+
if (seen.has(rel)) return;
|
|
31362
|
+
seen.add(rel);
|
|
31363
|
+
conflicts.push(`${rel} ${what}`);
|
|
31364
|
+
};
|
|
31365
|
+
for (const entry of entries) {
|
|
31366
|
+
if (isDeniedSourcePath(entry.path)) continue;
|
|
31367
|
+
const segments = entry.path.split("/");
|
|
31368
|
+
let dir = root;
|
|
31369
|
+
let stop = false;
|
|
31370
|
+
for (const [i, segment] of segments.slice(0, -1).entries()) {
|
|
31371
|
+
dir = join36(dir, segment);
|
|
31372
|
+
const kind2 = pathKind(dir);
|
|
31373
|
+
if (!kind2 || kind2.isSymbolicLink()) {
|
|
31374
|
+
stop = true;
|
|
31375
|
+
break;
|
|
31376
|
+
}
|
|
31377
|
+
if (kind2.isDirectory()) continue;
|
|
31378
|
+
say(segments.slice(0, i + 1).join("/"), "is a file here, but the release has a directory at that path");
|
|
31379
|
+
stop = true;
|
|
31380
|
+
break;
|
|
31381
|
+
}
|
|
31382
|
+
if (stop) continue;
|
|
31383
|
+
const kind = pathKind(join36(root, ...segments));
|
|
31384
|
+
if (kind && !kind.isSymbolicLink() && kind.isDirectory()) {
|
|
31385
|
+
say(entry.path, "is a directory here, but the release has a file at that path");
|
|
31386
|
+
}
|
|
31387
|
+
}
|
|
31388
|
+
return conflicts;
|
|
31389
|
+
}
|
|
31390
|
+
function removeStaleSource(entries, destDir) {
|
|
31391
|
+
const root = resolve32(destDir);
|
|
31392
|
+
const removed = staleSourcePaths(entries, root);
|
|
31393
|
+
for (const rel of removed) rmSync6(join36(root, ...rel.split("/")), { force: true });
|
|
31394
|
+
const needed = /* @__PURE__ */ new Set();
|
|
31395
|
+
for (const entry of entries) {
|
|
31396
|
+
if (isDeniedSourcePath(entry.path)) continue;
|
|
31397
|
+
const segments = entry.path.split("/");
|
|
31398
|
+
for (let i = 1; i < segments.length; i++) needed.add(segments.slice(0, i).join("/"));
|
|
31399
|
+
}
|
|
31400
|
+
if (existsSync36(root)) pruneEmptyDirs(root, "", needed, removed);
|
|
31401
|
+
return removed.sort();
|
|
31402
|
+
}
|
|
31403
|
+
function pruneEmptyDirs(root, rel, needed, removed) {
|
|
31404
|
+
let empty = true;
|
|
31405
|
+
for (const name of readdirSync20(rel ? join36(root, rel) : root)) {
|
|
31406
|
+
const childRel = rel ? join36(rel, name) : name;
|
|
31407
|
+
const posix3 = childRel.split(sep7).join("/");
|
|
31408
|
+
const kind = lstatSync4(join36(root, childRel));
|
|
31409
|
+
if (kind.isSymbolicLink() || !kind.isDirectory() || isDeniedSourceDir(name)) {
|
|
31410
|
+
empty = false;
|
|
31411
|
+
continue;
|
|
31412
|
+
}
|
|
31413
|
+
const childEmpty = pruneEmptyDirs(root, childRel, needed, removed);
|
|
31414
|
+
if (!childEmpty || needed.has(posix3)) {
|
|
31415
|
+
empty = false;
|
|
31416
|
+
continue;
|
|
31417
|
+
}
|
|
31418
|
+
rmdirSync(join36(root, childRel));
|
|
31419
|
+
removed.push(`${posix3}/`);
|
|
31420
|
+
}
|
|
31421
|
+
return empty;
|
|
31422
|
+
}
|
|
30693
31423
|
var MAX_APP_SOURCE_BYTES, SECRET_PATTERNS;
|
|
30694
31424
|
var init_app_source = __esm({
|
|
30695
31425
|
"src/app-source.ts"() {
|
|
@@ -30713,13 +31443,13 @@ __export(eject_exports, {
|
|
|
30713
31443
|
EJECTABLE: () => EJECTABLE,
|
|
30714
31444
|
ejectModule: () => ejectModule
|
|
30715
31445
|
});
|
|
30716
|
-
import { existsSync as
|
|
30717
|
-
import { dirname as
|
|
31446
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync19, readFileSync as readFileSync44, writeFileSync as writeFileSync15 } from "node:fs";
|
|
31447
|
+
import { dirname as dirname24, join as join37, relative as relative4, resolve as resolve33, sep as sep8 } from "node:path";
|
|
30718
31448
|
function locate(repoRootOrCwd, mod) {
|
|
30719
|
-
const inRepo =
|
|
30720
|
-
if (
|
|
30721
|
-
const dist =
|
|
30722
|
-
if (
|
|
31449
|
+
const inRepo = resolve33(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
|
|
31450
|
+
if (existsSync37(inRepo)) return { path: inRepo, form: "source" };
|
|
31451
|
+
const dist = resolve33(repoRootOrCwd, `node_modules/@wix/himalaya/dist/${mod}.mjs`);
|
|
31452
|
+
if (existsSync37(dist)) return { path: dist, form: "bundle" };
|
|
30723
31453
|
return null;
|
|
30724
31454
|
}
|
|
30725
31455
|
function specifiersFor(mod) {
|
|
@@ -30743,8 +31473,8 @@ function ejectModule(opts) {
|
|
|
30743
31473
|
};
|
|
30744
31474
|
}
|
|
30745
31475
|
const ext = found.form === "source" ? "ts" : "mjs";
|
|
30746
|
-
const target =
|
|
30747
|
-
mkdirSync19(
|
|
31476
|
+
const target = join37(contentDir2, "tier5-src", "_ejected", `${mod}.${ext}`);
|
|
31477
|
+
mkdirSync19(dirname24(target), { recursive: true });
|
|
30748
31478
|
const banner = `// EJECTED from @wix/himalaya/${mod}. This app owns this file now.
|
|
30749
31479
|
//
|
|
30750
31480
|
// Central fixes to @wix/himalaya/${mod} NO LONGER REACH THIS APP \u2014 including any
|
|
@@ -30764,10 +31494,10 @@ function ejectModule(opts) {
|
|
|
30764
31494
|
writeFileSync15(target, banner + normalized);
|
|
30765
31495
|
const rewired = [];
|
|
30766
31496
|
for (const f of files) {
|
|
30767
|
-
if (!
|
|
31497
|
+
if (!existsSync37(f)) continue;
|
|
30768
31498
|
const before = readFileSync44(f, "utf8");
|
|
30769
31499
|
let after = before;
|
|
30770
|
-
let rel = relative4(
|
|
31500
|
+
let rel = relative4(dirname24(f), target).split(sep8).join("/").replace(/\.tsx?$/, ".js");
|
|
30771
31501
|
if (!rel.startsWith(".")) rel = `./${rel}`;
|
|
30772
31502
|
for (const spec of specifiersFor(mod)) {
|
|
30773
31503
|
const q = spec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -30813,11 +31543,11 @@ __export(test_exports, {
|
|
|
30813
31543
|
scopeDescriptors: () => scopeDescriptors,
|
|
30814
31544
|
writeRecordedMocks: () => writeRecordedMocks
|
|
30815
31545
|
});
|
|
30816
|
-
import { existsSync as
|
|
30817
|
-
import { join as
|
|
31546
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync20, readFileSync as readFileSync45, writeFileSync as writeFileSync16 } from "node:fs";
|
|
31547
|
+
import { join as join38, resolve as resolve34 } from "node:path";
|
|
30818
31548
|
function readTestConfig(dir) {
|
|
30819
|
-
const p =
|
|
30820
|
-
if (!
|
|
31549
|
+
const p = resolve34(dir, TEST_CONFIG_FILE);
|
|
31550
|
+
if (!existsSync38(p)) return {};
|
|
30821
31551
|
let parsed;
|
|
30822
31552
|
try {
|
|
30823
31553
|
parsed = JSON.parse(readFileSync45(p, "utf8"));
|
|
@@ -30833,8 +31563,8 @@ function readTestConfig(dir) {
|
|
|
30833
31563
|
if (typeof s.reason !== "string" || !s.reason.trim()) {
|
|
30834
31564
|
throw new Error(`${TEST_CONFIG_FILE}: skip[${i}] needs a non-empty "reason" \u2014 suppressions have to stay auditable`);
|
|
30835
31565
|
}
|
|
30836
|
-
if (!s.screen && !s.action && !s.component) {
|
|
30837
|
-
throw new Error(`${TEST_CONFIG_FILE}: skip[${i}] matches everything \u2014 give it a "screen", "action", or "
|
|
31566
|
+
if (!s.screen && !s.action && !s.component && !s.invariant) {
|
|
31567
|
+
throw new Error(`${TEST_CONFIG_FILE}: skip[${i}] matches everything \u2014 give it a "screen", "action", "component", or "invariant"`);
|
|
30838
31568
|
}
|
|
30839
31569
|
});
|
|
30840
31570
|
}
|
|
@@ -30883,8 +31613,8 @@ function readNetRules(path) {
|
|
|
30883
31613
|
}
|
|
30884
31614
|
function defaultNetRules(dir) {
|
|
30885
31615
|
for (const rel of ["dev/net-mocks.json", "tests/net-mocks.json"]) {
|
|
30886
|
-
const p =
|
|
30887
|
-
if (
|
|
31616
|
+
const p = resolve34(dir, rel);
|
|
31617
|
+
if (existsSync38(p)) {
|
|
30888
31618
|
const rules = readNetRules(p);
|
|
30889
31619
|
if (rules.length) return { rules, from: rel };
|
|
30890
31620
|
}
|
|
@@ -30992,8 +31722,8 @@ function writeRecordedMocks(opts) {
|
|
|
30992
31722
|
mkdir: (p) => mkdirSync20(p, { recursive: true }),
|
|
30993
31723
|
write: (p, s) => writeFileSync16(p, s)
|
|
30994
31724
|
};
|
|
30995
|
-
fs.mkdir(
|
|
30996
|
-
fs.write(
|
|
31725
|
+
fs.mkdir(join38(opts.dir, "dev"));
|
|
31726
|
+
fs.write(join38(opts.dir, "dev", "net-mocks.json"), JSON.stringify(opts.mocks, null, 2) + "\n");
|
|
30997
31727
|
return { ok: true, rules, to: "dev/net-mocks.json" };
|
|
30998
31728
|
}
|
|
30999
31729
|
function scopeDescriptors(descriptors, requestedIds, invalidScreens) {
|
|
@@ -31056,15 +31786,18 @@ async function runCrawl(opts) {
|
|
|
31056
31786
|
if (list.length > 1) collapsed.push({ representative: rep.screenId, instances: list.length });
|
|
31057
31787
|
}
|
|
31058
31788
|
}
|
|
31059
|
-
const net = opts.offline ? null : opts.netPath ? { rules: readNetRules(
|
|
31789
|
+
const net = opts.offline ? null : opts.netPath ? { rules: readNetRules(resolve34(opts.netPath)), from: opts.netPath } : defaultNetRules(opts.dir);
|
|
31060
31790
|
const suppressions = opts.config?.skip ?? [];
|
|
31061
31791
|
const suppressed = [];
|
|
31062
|
-
const matchSuppression = (screen, actionId, componentId) => suppressions.find((s) => (s.screen === void 0 || s.screen === screen) && (s.action === void 0 || s.action === actionId) && (s.component === void 0 || s.component === componentId));
|
|
31792
|
+
const matchSuppression = (screen, actionId, componentId, invariant) => suppressions.find((s) => (s.screen === void 0 || s.screen === screen) && (s.action === void 0 || s.action === actionId) && (s.component === void 0 || s.component === componentId) && (s.invariant === void 0 || s.invariant === invariant));
|
|
31063
31793
|
const results = [];
|
|
31064
31794
|
const uncoveredByScreen = /* @__PURE__ */ new Map();
|
|
31065
31795
|
const coverageFns = /* @__PURE__ */ new Map();
|
|
31066
31796
|
const bundleOf = new Map(descriptors.map((d) => [d.screenId, d]));
|
|
31067
31797
|
const hostileFindings = [];
|
|
31798
|
+
const relationFindings = [];
|
|
31799
|
+
let relationsChecked = 0;
|
|
31800
|
+
const relationsByKind = { inverse: 0, refresh: 0, loadMore: 0, filter: 0 };
|
|
31068
31801
|
const deepFindings = [];
|
|
31069
31802
|
const journeyFindings = [];
|
|
31070
31803
|
const journeyResults = [];
|
|
@@ -31134,14 +31867,22 @@ async function runCrawl(opts) {
|
|
|
31134
31867
|
hostileFindings.push(...hs.filter((f) => !already.has(keyOf(f))));
|
|
31135
31868
|
}
|
|
31136
31869
|
}
|
|
31870
|
+
if (deps.crawlScreenRelations && baked.bundleJs) {
|
|
31871
|
+
const rr = await deps.crawlScreenRelations(args);
|
|
31872
|
+
relationsChecked += rr.checked;
|
|
31873
|
+
for (const [k, n] of Object.entries(rr.byKind ?? {})) relationsByKind[k] = (relationsByKind[k] ?? 0) + n;
|
|
31874
|
+
const keyOf = deps.findingKey ?? ((f) => `${f.invariant}|${f.at ?? ""}|${f.screen}|${f.message}`);
|
|
31875
|
+
const already = new Set(r.findings.map(keyOf));
|
|
31876
|
+
for (const f of rr.findings) if (!already.has(keyOf(f))) relationFindings.push(f);
|
|
31877
|
+
}
|
|
31137
31878
|
await finishScreenCoverage();
|
|
31138
31879
|
}
|
|
31139
31880
|
const keep = (f) => {
|
|
31140
31881
|
const actionId = typeof f.trigger === "object" ? f.trigger.action : "boot";
|
|
31141
31882
|
const componentId = typeof f.trigger === "object" ? f.trigger.tap : null;
|
|
31142
|
-
const s = matchSuppression(f.screen, actionId, componentId);
|
|
31143
|
-
if (s && !suppressed.some((x) => x.screen === f.screen && x.action === actionId && x.component === (componentId ?? void 0))) {
|
|
31144
|
-
suppressed.push({ screen: f.screen, action: actionId, ...componentId ? { component: componentId } : {}, reason: s.reason });
|
|
31883
|
+
const s = matchSuppression(f.screen, actionId, componentId, f.invariant);
|
|
31884
|
+
if (s && !suppressed.some((x) => x.screen === f.screen && x.action === actionId && x.component === (componentId ?? void 0) && x.invariant === s.invariant)) {
|
|
31885
|
+
suppressed.push({ screen: f.screen, action: actionId, ...componentId ? { component: componentId } : {}, ...s.invariant ? { invariant: s.invariant } : {}, reason: s.reason });
|
|
31145
31886
|
}
|
|
31146
31887
|
return !s;
|
|
31147
31888
|
};
|
|
@@ -31222,7 +31963,7 @@ async function runCrawl(opts) {
|
|
|
31222
31963
|
if (uncovered.length) uncoveredByScreen.set(screen, uncovered);
|
|
31223
31964
|
}
|
|
31224
31965
|
}
|
|
31225
|
-
const all = [...results.flatMap((r) => r.findings), ...hostileFindings, ...deepFindings, ...journeyFindings, ...edgeFindings].filter((f) => {
|
|
31966
|
+
const all = [...results.flatMap((r) => r.findings), ...hostileFindings, ...deepFindings, ...journeyFindings, ...edgeFindings, ...relationFindings].filter((f) => {
|
|
31226
31967
|
if (f.invariant === "no-request-issued" && !f.axis && fetchProven.has(f.screen)) {
|
|
31227
31968
|
const by = fetchProven.get(f.screen);
|
|
31228
31969
|
if (!retired.some((x) => x.screen === f.screen)) retired.push({ screen: f.screen, from: by.from, params: by.params });
|
|
@@ -31242,7 +31983,15 @@ async function runCrawl(opts) {
|
|
|
31242
31983
|
...blockedReasons.length ? { blockedReasons } : {},
|
|
31243
31984
|
app: opts.app,
|
|
31244
31985
|
releaseId: opts.releaseId,
|
|
31245
|
-
|
|
31986
|
+
// Whether the axis RAN, not whether it was injected. The engine is gated on `baked.bundleJs`,
|
|
31987
|
+
// so a run over static or bundle-less screens injects the dependency and replays nothing —
|
|
31988
|
+
// and the label then advertised "+ relations" beside `relations.checked: 0`. This is the
|
|
31989
|
+
// second time this line has overstated itself: it first claimed the axis unconditionally.
|
|
31990
|
+
transport: describeTransport(net, opts, {
|
|
31991
|
+
relations: relationsChecked > 0,
|
|
31992
|
+
hostile: opts.hostile !== false && Boolean(deps.crawlScreenHostile),
|
|
31993
|
+
deep: Boolean(opts.deep && opts.deep >= 2 && deps.crawlScreenDeep)
|
|
31994
|
+
}),
|
|
31246
31995
|
screens: { total: targets.length, clean: targets.length - failedScreens.size, failed: failedScreens.size },
|
|
31247
31996
|
actions: { exercised: results.reduce((n, r) => n + r.actionsExercised, 0) },
|
|
31248
31997
|
counts: { errors: failures.length, warnings: warnings.length },
|
|
@@ -31265,22 +32014,22 @@ async function runCrawl(opts) {
|
|
|
31265
32014
|
...edgesCapped.length ? { edgesCapped } : {},
|
|
31266
32015
|
...retired.length ? { retired } : {},
|
|
31267
32016
|
...opts.deep && opts.deep >= 2 ? { deep: { depth: opts.deep, ...deepTotals } } : {},
|
|
32017
|
+
...deps.crawlScreenRelations ? { relations: { checked: relationsChecked, byKind: relationsByKind } } : {},
|
|
31268
32018
|
...journeyResults.length ? { journeys: journeyResults } : {},
|
|
31269
32019
|
...results.some((r) => r.observations) ? { observations: Object.fromEntries(results.filter((r) => r.observations).map((r) => [r.screen, r.observations])) } : {}
|
|
31270
32020
|
};
|
|
31271
32021
|
}
|
|
31272
|
-
function describeTransport(net, opts) {
|
|
32022
|
+
function describeTransport(net, opts, ran) {
|
|
31273
32023
|
const layers = [];
|
|
31274
32024
|
if (net) layers.push(`mocked (${net.from})`);
|
|
31275
32025
|
const cmsCount = Object.keys(opts.cmsSeed ?? {}).length;
|
|
31276
32026
|
if (cmsCount) layers.push(`cms (${cmsCount} seeded collection${cmsCount === 1 ? "" : "s"})`);
|
|
31277
32027
|
if (opts.canned?.count) layers.push(`canned (${opts.canned.count} frozen endpoints, ${opts.canned.from} \u2014 exercises code paths, not API-contract truth)`);
|
|
31278
|
-
|
|
31279
|
-
|
|
31280
|
-
|
|
31281
|
-
const
|
|
31282
|
-
|
|
31283
|
-
return layers.join(" + ") + hostile + deep;
|
|
32028
|
+
const base = layers.length ? layers.join(" + ") : "offline (no net fixture \u2014 screens are crawled against a rejecting transport, which exercises their failure UI)";
|
|
32029
|
+
const hostile = ran.hostile ? " + hostile boot passes (empty-lists, all-500)" : "";
|
|
32030
|
+
const relations = ran.relations ? " + relations" : "";
|
|
32031
|
+
const deep = ran.deep ? ` + deep chains (depth ${opts.deep})` : "";
|
|
32032
|
+
return base + hostile + relations + deep;
|
|
31284
32033
|
}
|
|
31285
32034
|
function formatReport(r) {
|
|
31286
32035
|
const out = [];
|
|
@@ -31414,11 +32163,11 @@ var mobile_ux_lint_exports = {};
|
|
|
31414
32163
|
__export(mobile_ux_lint_exports, {
|
|
31415
32164
|
mobileUxIssues: () => mobileUxIssues
|
|
31416
32165
|
});
|
|
31417
|
-
import { existsSync as
|
|
31418
|
-
import { join as
|
|
32166
|
+
import { existsSync as existsSync39, readFileSync as readFileSync46 } from "node:fs";
|
|
32167
|
+
import { join as join39 } from "node:path";
|
|
31419
32168
|
function mobileUxIssues(dir, strict) {
|
|
31420
|
-
const file =
|
|
31421
|
-
if (!
|
|
32169
|
+
const file = join39(dir, "MOBILE-UX.md");
|
|
32170
|
+
if (!existsSync39(file)) return [];
|
|
31422
32171
|
let text2;
|
|
31423
32172
|
try {
|
|
31424
32173
|
text2 = readFileSync46(file, "utf8");
|
|
@@ -31700,7 +32449,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
31700
32449
|
const headers2 = Object.fromEntries(new Headers(init.headers).entries());
|
|
31701
32450
|
const request = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
31702
32451
|
const hostname = url.hostname.replace(/^\[|\]$/g, "");
|
|
31703
|
-
return await new Promise((
|
|
32452
|
+
return await new Promise((resolve41, reject) => {
|
|
31704
32453
|
let settled = false;
|
|
31705
32454
|
const finish2 = (fn) => {
|
|
31706
32455
|
if (settled) return;
|
|
@@ -31737,7 +32486,7 @@ async function pinnedFetch(url, init, addresses, maxResponseBytes) {
|
|
|
31737
32486
|
}
|
|
31738
32487
|
const responseHeaders = new Headers();
|
|
31739
32488
|
for (const [key2, value] of Object.entries(response.headers)) if (value !== void 0) responseHeaders.set(key2, Array.isArray(value) ? value.join(", ") : value);
|
|
31740
|
-
|
|
32489
|
+
resolve41(new Response(bytes2, { status: response.statusCode, statusText: response.statusMessage, headers: responseHeaders }));
|
|
31741
32490
|
}));
|
|
31742
32491
|
});
|
|
31743
32492
|
req.once("error", (error) => finish2(() => reject(error)));
|
|
@@ -32037,7 +32786,7 @@ function createLocalTestSandbox() {
|
|
|
32037
32786
|
}
|
|
32038
32787
|
})();
|
|
32039
32788
|
`;
|
|
32040
|
-
return await new Promise((
|
|
32789
|
+
return await new Promise((resolve41, reject) => {
|
|
32041
32790
|
const { port1, port2 } = new MessageChannel();
|
|
32042
32791
|
const serializableContext = {
|
|
32043
32792
|
auth: context.auth,
|
|
@@ -32113,7 +32862,7 @@ function createLocalTestSandbox() {
|
|
|
32113
32862
|
timer = setTimeout(() => finish2(() => reject(new SandboxError("timeout", `execution exceeded ${limits.timeoutMs}ms`))), Math.max(1, limits.timeoutMs));
|
|
32114
32863
|
return;
|
|
32115
32864
|
}
|
|
32116
|
-
if (message.ok) finish2(() =>
|
|
32865
|
+
if (message.ok) finish2(() => resolve41({ value: message.value, durationMs: Date.now() - started }));
|
|
32117
32866
|
else finish2(() => reject(new SandboxError("execution_failed", message.message ?? "handler failed")));
|
|
32118
32867
|
});
|
|
32119
32868
|
worker.once("error", (error) => finish2(() => reject(new SandboxError("execution_failed", error.message))));
|
|
@@ -33080,8 +33829,8 @@ __export(functions_exports, {
|
|
|
33080
33829
|
resolveFunctionsTarget: () => resolveFunctionsTarget,
|
|
33081
33830
|
runRemoteFunctionOperation: () => runRemoteFunctionOperation
|
|
33082
33831
|
});
|
|
33083
|
-
import { readFileSync as readFileSync47, existsSync as
|
|
33084
|
-
import { join as
|
|
33832
|
+
import { readFileSync as readFileSync47, existsSync as existsSync40 } from "node:fs";
|
|
33833
|
+
import { join as join40, resolve as resolve35 } from "node:path";
|
|
33085
33834
|
function resolveFunctionsTarget(input) {
|
|
33086
33835
|
const explicitUrl = input.functionsUrl?.trim();
|
|
33087
33836
|
if (explicitUrl) return { mode: "remote", baseUrl: explicitUrl };
|
|
@@ -33093,14 +33842,14 @@ function resolveFunctionsTarget(input) {
|
|
|
33093
33842
|
return { mode: "local" };
|
|
33094
33843
|
}
|
|
33095
33844
|
async function loadFunctionsApp(dir) {
|
|
33096
|
-
const loaded = await loadContent(
|
|
33845
|
+
const loaded = await loadContent(resolve35(dir));
|
|
33097
33846
|
const config = loaded.module.config;
|
|
33098
33847
|
if (config.kind !== "functions" || !Array.isArray(config.functions?.functions)) {
|
|
33099
33848
|
throw new Error(`content package "${dir}" is not a functions-only app`);
|
|
33100
33849
|
}
|
|
33101
33850
|
const sources = {};
|
|
33102
33851
|
for (const definition of config.functions.functions) {
|
|
33103
|
-
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) =>
|
|
33852
|
+
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join40(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync40);
|
|
33104
33853
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
33105
33854
|
sources[definition.name] = readFileSync47(source, "utf8");
|
|
33106
33855
|
}
|
|
@@ -33256,9 +34005,9 @@ __export(native_decode_exports, {
|
|
|
33256
34005
|
runNativeDecode: () => runNativeDecode
|
|
33257
34006
|
});
|
|
33258
34007
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
33259
|
-
import { existsSync as
|
|
34008
|
+
import { existsSync as existsSync41, mkdtempSync as mkdtempSync2, readFileSync as readFileSync48, rmSync as rmSync7, writeFileSync as writeFileSync17 } from "node:fs";
|
|
33260
34009
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
33261
|
-
import { join as
|
|
34010
|
+
import { join as join41 } from "node:path";
|
|
33262
34011
|
import { fileURLToPath as fileURLToPath19 } from "node:url";
|
|
33263
34012
|
function nativeDecodePackageDir() {
|
|
33264
34013
|
return fileURLToPath19(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
|
|
@@ -33274,7 +34023,7 @@ function detectNativeDecode(options = {}) {
|
|
|
33274
34023
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
33275
34024
|
}
|
|
33276
34025
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
33277
|
-
const packageAvailable = options.packageAvailable ??
|
|
34026
|
+
const packageAvailable = options.packageAvailable ?? existsSync41(join41(packageDir, "Package.swift"));
|
|
33278
34027
|
if (!packageAvailable) {
|
|
33279
34028
|
return {
|
|
33280
34029
|
platform: "ios",
|
|
@@ -33286,7 +34035,7 @@ function detectNativeDecode(options = {}) {
|
|
|
33286
34035
|
}
|
|
33287
34036
|
function localPropertiesSdk(harnessDir) {
|
|
33288
34037
|
try {
|
|
33289
|
-
const match = readFileSync48(
|
|
34038
|
+
const match = readFileSync48(join41(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
|
|
33290
34039
|
return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
|
|
33291
34040
|
} catch {
|
|
33292
34041
|
return null;
|
|
@@ -33294,8 +34043,8 @@ function localPropertiesSdk(harnessDir) {
|
|
|
33294
34043
|
}
|
|
33295
34044
|
function detectAndroidNativeDecode(options = {}) {
|
|
33296
34045
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
33297
|
-
const gradlew =
|
|
33298
|
-
const gradlewAvailable = options.gradlewAvailable ??
|
|
34046
|
+
const gradlew = join41(harnessDir, "gradlew");
|
|
34047
|
+
const gradlewAvailable = options.gradlewAvailable ?? existsSync41(gradlew);
|
|
33299
34048
|
if (!gradlewAvailable) {
|
|
33300
34049
|
return {
|
|
33301
34050
|
platform: "android",
|
|
@@ -33305,7 +34054,7 @@ function detectAndroidNativeDecode(options = {}) {
|
|
|
33305
34054
|
}
|
|
33306
34055
|
const androidHome = options.androidHome ?? process.env.ANDROID_HOME ?? "";
|
|
33307
34056
|
const sdk = androidHome.trim() || (options.localPropertiesSdk !== void 0 ? options.localPropertiesSdk : localPropertiesSdk(harnessDir));
|
|
33308
|
-
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 &&
|
|
34057
|
+
const sdkAvailable = options.sdkAvailable ?? (typeof sdk === "string" && sdk.length > 0 && existsSync41(sdk));
|
|
33309
34058
|
if (!sdkAvailable) {
|
|
33310
34059
|
return {
|
|
33311
34060
|
platform: "android",
|
|
@@ -33377,14 +34126,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
|
|
|
33377
34126
|
return verdicts;
|
|
33378
34127
|
}
|
|
33379
34128
|
function runNativeDecode(options) {
|
|
33380
|
-
const descriptorDir = mkdtempSync2(
|
|
34129
|
+
const descriptorDir = mkdtempSync2(join41(tmpdir3(), "himi-native-decode-"));
|
|
33381
34130
|
const startedAt = Date.now();
|
|
33382
34131
|
try {
|
|
33383
34132
|
for (const descriptor of options.descriptors) {
|
|
33384
34133
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
33385
34134
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
33386
34135
|
}
|
|
33387
|
-
writeFileSync17(
|
|
34136
|
+
writeFileSync17(join41(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
33388
34137
|
}
|
|
33389
34138
|
options.progress?.("building cached Swift oracle");
|
|
33390
34139
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -33396,7 +34145,7 @@ function runNativeDecode(options) {
|
|
|
33396
34145
|
encoding: "utf8"
|
|
33397
34146
|
}).trim();
|
|
33398
34147
|
options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
33399
|
-
const stdout = execFileSync5(
|
|
34148
|
+
const stdout = execFileSync5(join41(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
|
|
33400
34149
|
stdio: ["ignore", "pipe", "pipe"],
|
|
33401
34150
|
encoding: "utf8"
|
|
33402
34151
|
});
|
|
@@ -33410,19 +34159,19 @@ function runNativeDecode(options) {
|
|
|
33410
34159
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
33411
34160
|
throw new Error(`iOS decoder oracle failed: ${failure.message}${stderr}`);
|
|
33412
34161
|
} finally {
|
|
33413
|
-
|
|
34162
|
+
rmSync7(descriptorDir, { recursive: true, force: true });
|
|
33414
34163
|
}
|
|
33415
34164
|
}
|
|
33416
34165
|
function runAndroidNativeDecode(options) {
|
|
33417
|
-
const descriptorDir = mkdtempSync2(
|
|
33418
|
-
const outputPath =
|
|
34166
|
+
const descriptorDir = mkdtempSync2(join41(tmpdir3(), "himi-native-decode-android-"));
|
|
34167
|
+
const outputPath = join41(descriptorDir, "verdicts.ndjson");
|
|
33419
34168
|
const startedAt = Date.now();
|
|
33420
34169
|
try {
|
|
33421
34170
|
for (const descriptor of options.descriptors) {
|
|
33422
34171
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
33423
34172
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
33424
34173
|
}
|
|
33425
|
-
writeFileSync17(
|
|
34174
|
+
writeFileSync17(join41(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
33426
34175
|
}
|
|
33427
34176
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
33428
34177
|
execFileSync5(options.gradlew, [
|
|
@@ -33448,7 +34197,7 @@ function runAndroidNativeDecode(options) {
|
|
|
33448
34197
|
const stderr = failure.stderr ? ` \u2014 ${String(failure.stderr).trim().slice(0, 2e3)}` : "";
|
|
33449
34198
|
throw new Error(`Android decoder oracle failed: ${failure.message}${stderr}`);
|
|
33450
34199
|
} finally {
|
|
33451
|
-
|
|
34200
|
+
rmSync7(descriptorDir, { recursive: true, force: true });
|
|
33452
34201
|
}
|
|
33453
34202
|
}
|
|
33454
34203
|
function fieldAt(path) {
|
|
@@ -33508,30 +34257,30 @@ __export(browser_authoring_exports, {
|
|
|
33508
34257
|
import { createServer as createServer3 } from "node:http";
|
|
33509
34258
|
import { createHash as createHash22, randomBytes as randomBytes5 } from "node:crypto";
|
|
33510
34259
|
import { execFile as execFile2 } from "node:child_process";
|
|
33511
|
-
import { existsSync as
|
|
33512
|
-
import { join as
|
|
34260
|
+
import { existsSync as existsSync42, readdirSync as readdirSync21, readFileSync as readFileSync49, realpathSync as realpathSync4, statSync as statSync9 } from "node:fs";
|
|
34261
|
+
import { join as join42, posix, relative as relative5, sep as sep9 } from "node:path";
|
|
33513
34262
|
function humanMs(ms) {
|
|
33514
34263
|
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
33515
34264
|
}
|
|
33516
34265
|
function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
33517
|
-
const root =
|
|
34266
|
+
const root = join42(tier5SrcDir, bundleName);
|
|
33518
34267
|
const files = {};
|
|
33519
34268
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
33520
34269
|
const walk2 = (abs, rel) => {
|
|
33521
|
-
const real =
|
|
34270
|
+
const real = realpathSync4(abs);
|
|
33522
34271
|
if (visitedDirs.has(real)) return;
|
|
33523
34272
|
visitedDirs.add(real);
|
|
33524
34273
|
for (const name of readdirSync21(abs).sort()) {
|
|
33525
|
-
const childAbs =
|
|
34274
|
+
const childAbs = join42(abs, name);
|
|
33526
34275
|
const childRel = posix.join(rel, name);
|
|
33527
|
-
if (
|
|
34276
|
+
if (statSync9(childAbs).isDirectory()) {
|
|
33528
34277
|
walk2(childAbs, childRel);
|
|
33529
34278
|
} else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
|
|
33530
34279
|
files[childRel] = readFileSync49(childAbs, "utf8");
|
|
33531
34280
|
}
|
|
33532
34281
|
}
|
|
33533
34282
|
};
|
|
33534
|
-
if (!
|
|
34283
|
+
if (!existsSync42(root)) return null;
|
|
33535
34284
|
walk2(root, `/tier5-src/${bundleName}`);
|
|
33536
34285
|
const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p) => p in files);
|
|
33537
34286
|
if (!entry) return null;
|
|
@@ -33548,18 +34297,18 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
33548
34297
|
const spec = m[1];
|
|
33549
34298
|
const virtual = posix.normalize(posix.join(dir, spec));
|
|
33550
34299
|
if (!virtual.startsWith("/tier5-src/")) continue;
|
|
33551
|
-
const onDisk =
|
|
34300
|
+
const onDisk = join42(tier5SrcDir, virtual.slice("/tier5-src/".length));
|
|
33552
34301
|
const candidates = [
|
|
33553
34302
|
onDisk,
|
|
33554
34303
|
`${onDisk}.ts`,
|
|
33555
34304
|
`${onDisk}.js`,
|
|
33556
34305
|
onDisk.replace(/\.js$/, ".ts"),
|
|
33557
|
-
|
|
33558
|
-
|
|
34306
|
+
join42(onDisk, "index.ts"),
|
|
34307
|
+
join42(onDisk, "index.js")
|
|
33559
34308
|
];
|
|
33560
34309
|
for (const abs of candidates) {
|
|
33561
|
-
if (!
|
|
33562
|
-
const key2 = `/tier5-src/${relative5(tier5SrcDir, abs).split(
|
|
34310
|
+
if (!existsSync42(abs) || statSync9(abs).isDirectory()) continue;
|
|
34311
|
+
const key2 = `/tier5-src/${relative5(tier5SrcDir, abs).split(sep9).join(posix.sep)}`;
|
|
33563
34312
|
if (key2 in files) break;
|
|
33564
34313
|
files[key2] = readFileSync49(abs, "utf8");
|
|
33565
34314
|
queue.push(key2);
|
|
@@ -33593,10 +34342,10 @@ function collectSdkModules(files, resolveSubpath) {
|
|
|
33593
34342
|
for (const source of Object.values(files)) visit(source);
|
|
33594
34343
|
return { modules, unsupported };
|
|
33595
34344
|
}
|
|
33596
|
-
function sdkSubpathReader(
|
|
34345
|
+
function sdkSubpathReader(resolve41) {
|
|
33597
34346
|
return (sub) => {
|
|
33598
34347
|
try {
|
|
33599
|
-
return readFileSync49(
|
|
34348
|
+
return readFileSync49(resolve41(`@wix/himalaya/${sub}`), "utf8");
|
|
33600
34349
|
} catch {
|
|
33601
34350
|
return null;
|
|
33602
34351
|
}
|
|
@@ -33677,7 +34426,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
33677
34426
|
const token = mintToken2(payload);
|
|
33678
34427
|
const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
|
|
33679
34428
|
if (unusable) throw new Error(unusable);
|
|
33680
|
-
return await new Promise((
|
|
34429
|
+
return await new Promise((resolve41, reject) => {
|
|
33681
34430
|
let settled = false;
|
|
33682
34431
|
let url = "";
|
|
33683
34432
|
const server = createServer3();
|
|
@@ -33729,7 +34478,7 @@ async function runBrowserAuthoring(opts) {
|
|
|
33729
34478
|
}
|
|
33730
34479
|
res.writeHead(200, { "content-type": "text/plain" }).end("ok");
|
|
33731
34480
|
const report = body.result;
|
|
33732
|
-
finish2(() =>
|
|
34481
|
+
finish2(() => resolve41({ report, url }));
|
|
33733
34482
|
})();
|
|
33734
34483
|
});
|
|
33735
34484
|
server.on("error", (e) => finish2(() => reject(e)));
|
|
@@ -33769,8 +34518,8 @@ __export(coverage_exports, {
|
|
|
33769
34518
|
formatLedger: () => formatLedger,
|
|
33770
34519
|
trendAndStore: () => trendAndStore
|
|
33771
34520
|
});
|
|
33772
|
-
import { existsSync as
|
|
33773
|
-
import { dirname as
|
|
34521
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync21, readFileSync as readFileSync50, writeFileSync as writeFileSync18 } from "node:fs";
|
|
34522
|
+
import { dirname as dirname25, join as join43 } from "node:path";
|
|
33774
34523
|
function assembleLedger(r) {
|
|
33775
34524
|
const out = [];
|
|
33776
34525
|
for (const c of r.crawled ?? []) {
|
|
@@ -33936,10 +34685,10 @@ function assembleLedger(r) {
|
|
|
33936
34685
|
return out;
|
|
33937
34686
|
}
|
|
33938
34687
|
function trendAndStore(dir, entries) {
|
|
33939
|
-
const p =
|
|
34688
|
+
const p = join43(dir, LEDGER_FILE);
|
|
33940
34689
|
let previous = null;
|
|
33941
34690
|
try {
|
|
33942
|
-
if (
|
|
34691
|
+
if (existsSync43(p)) {
|
|
33943
34692
|
const parsed = JSON.parse(readFileSync50(p, "utf8"));
|
|
33944
34693
|
if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k) => typeof k === "string");
|
|
33945
34694
|
}
|
|
@@ -33947,7 +34696,7 @@ function trendAndStore(dir, entries) {
|
|
|
33947
34696
|
}
|
|
33948
34697
|
const current = entries.map((e) => e.key);
|
|
33949
34698
|
try {
|
|
33950
|
-
mkdirSync21(
|
|
34699
|
+
mkdirSync21(dirname25(p), { recursive: true });
|
|
33951
34700
|
writeFileSync18(p, JSON.stringify({ keys: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
33952
34701
|
} catch {
|
|
33953
34702
|
return null;
|
|
@@ -33977,10 +34726,10 @@ function formatLedger(entries, trend) {
|
|
|
33977
34726
|
return out.join("\n");
|
|
33978
34727
|
}
|
|
33979
34728
|
function diffAndStoreObservations(dir, current) {
|
|
33980
|
-
const p =
|
|
34729
|
+
const p = join43(dir, OBS_FILE);
|
|
33981
34730
|
let previous = null;
|
|
33982
34731
|
try {
|
|
33983
|
-
if (
|
|
34732
|
+
if (existsSync43(p)) {
|
|
33984
34733
|
const parsed = JSON.parse(readFileSync50(p, "utf8"));
|
|
33985
34734
|
if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
|
|
33986
34735
|
(v) => Array.isArray(v) && v.every((l) => typeof l === "string")
|
|
@@ -33991,7 +34740,7 @@ function diffAndStoreObservations(dir, current) {
|
|
|
33991
34740
|
} catch {
|
|
33992
34741
|
}
|
|
33993
34742
|
try {
|
|
33994
|
-
mkdirSync21(
|
|
34743
|
+
mkdirSync21(dirname25(p), { recursive: true });
|
|
33995
34744
|
writeFileSync18(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
33996
34745
|
} catch {
|
|
33997
34746
|
return null;
|
|
@@ -34029,8 +34778,8 @@ function formatDelta(delta) {
|
|
|
34029
34778
|
var LEDGER_FILE, OBS_FILE;
|
|
34030
34779
|
var init_coverage = __esm({
|
|
34031
34780
|
"src/coverage.ts"() {
|
|
34032
|
-
LEDGER_FILE =
|
|
34033
|
-
OBS_FILE =
|
|
34781
|
+
LEDGER_FILE = join43(".himi", "test-ledger.json");
|
|
34782
|
+
OBS_FILE = join43(".himi", "test-observations.json");
|
|
34034
34783
|
}
|
|
34035
34784
|
});
|
|
34036
34785
|
|
|
@@ -35234,9 +35983,9 @@ __export(run_exports, {
|
|
|
35234
35983
|
runPackage: () => runPackage,
|
|
35235
35984
|
withoutProdServe: () => withoutProdServe
|
|
35236
35985
|
});
|
|
35237
|
-
import { cpSync, existsSync as
|
|
35986
|
+
import { cpSync, existsSync as existsSync44, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync3, readFileSync as readFileSync52, rmSync as rmSync8, statSync as statSync10 } from "node:fs";
|
|
35238
35987
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
35239
|
-
import { join as
|
|
35988
|
+
import { join as join44 } from "node:path";
|
|
35240
35989
|
import { spawn as spawn3 } from "node:child_process";
|
|
35241
35990
|
function makePackageRunHandler(opts) {
|
|
35242
35991
|
return makeRunHandler({
|
|
@@ -35254,9 +36003,9 @@ async function fetchBytes(url) {
|
|
|
35254
36003
|
}
|
|
35255
36004
|
async function resolvePackage(source, workDir) {
|
|
35256
36005
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
35257
|
-
if (!isUrl2 &&
|
|
35258
|
-
const appDirManifest =
|
|
35259
|
-
if (
|
|
36006
|
+
if (!isUrl2 && existsSync44(source) && statSync10(source).isDirectory()) {
|
|
36007
|
+
const appDirManifest = join44(source, "release-manifest.json");
|
|
36008
|
+
if (existsSync44(appDirManifest)) {
|
|
35260
36009
|
const opened2 = openPackageDir(source);
|
|
35261
36010
|
if (!opened2.validation.ok) {
|
|
35262
36011
|
throw new Error(`package is not valid:
|
|
@@ -35265,11 +36014,11 @@ async function resolvePackage(source, workDir) {
|
|
|
35265
36014
|
const app2 = opened2.header?.app ?? opened2.manifest?.app;
|
|
35266
36015
|
if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
|
|
35267
36016
|
if (!isSafeAppId(app2)) throw new Error(`${source} declares an unsafe app id ${JSON.stringify(app2)} \u2014 refusing to open it`);
|
|
35268
|
-
const root2 = workDir ?? mkdtempSync3(
|
|
35269
|
-
const target =
|
|
35270
|
-
if (
|
|
36017
|
+
const root2 = workDir ?? mkdtempSync3(join44(tmpdir4(), "himi-run-"));
|
|
36018
|
+
const target = join44(root2, app2);
|
|
36019
|
+
if (join44(source) !== target) {
|
|
35271
36020
|
mkdirSync22(root2, { recursive: true });
|
|
35272
|
-
|
|
36021
|
+
rmSync8(target, { recursive: true, force: true });
|
|
35273
36022
|
cpSync(source, target, { recursive: true });
|
|
35274
36023
|
}
|
|
35275
36024
|
return {
|
|
@@ -35285,11 +36034,11 @@ async function resolvePackage(source, workDir) {
|
|
|
35285
36034
|
throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
|
|
35286
36035
|
}
|
|
35287
36036
|
const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync52(source);
|
|
35288
|
-
const root = workDir ?? mkdtempSync3(
|
|
36037
|
+
const root = workDir ?? mkdtempSync3(join44(tmpdir4(), "himi-run-"));
|
|
35289
36038
|
const { app, appDir: appDir2 } = unpackTo(bytes2, root);
|
|
35290
36039
|
const opened = openPackageDir(appDir2);
|
|
35291
36040
|
if (!opened.validation.ok) {
|
|
35292
|
-
|
|
36041
|
+
rmSync8(workDir ? appDir2 : root, { recursive: true, force: true });
|
|
35293
36042
|
throw new Error(`package is not valid:
|
|
35294
36043
|
${opened.validation.errors.join("\n ")}`);
|
|
35295
36044
|
}
|
|
@@ -35328,7 +36077,7 @@ async function runPackage(source, opts = {}) {
|
|
|
35328
36077
|
const resolved = await resolvePackage(source, opts.workDir);
|
|
35329
36078
|
const assets = opts.assets ?? (opts.spa ? /* @__PURE__ */ new Map() : await loadPreviewAssets());
|
|
35330
36079
|
if (!opts.spa && assets.size === 0) {
|
|
35331
|
-
if (resolved.temp)
|
|
36080
|
+
if (resolved.temp) rmSync8(resolved.temp, { recursive: true, force: true });
|
|
35332
36081
|
throw new Error(NO_SPA_MESSAGE);
|
|
35333
36082
|
}
|
|
35334
36083
|
const handler = makePackageRunHandler({
|
|
@@ -35358,7 +36107,7 @@ async function runPackage(source, opts = {}) {
|
|
|
35358
36107
|
warnings: resolved.warnings,
|
|
35359
36108
|
close: () => new Promise((done) => {
|
|
35360
36109
|
server.close(() => {
|
|
35361
|
-
if (resolved.temp)
|
|
36110
|
+
if (resolved.temp) rmSync8(resolved.temp, { recursive: true, force: true });
|
|
35362
36111
|
done();
|
|
35363
36112
|
});
|
|
35364
36113
|
})
|
|
@@ -35385,19 +36134,19 @@ __export(run_browser_exports, {
|
|
|
35385
36134
|
runInBrowser: () => runInBrowser
|
|
35386
36135
|
});
|
|
35387
36136
|
import { createServer as createServer5 } from "node:http";
|
|
35388
|
-
import { existsSync as
|
|
36137
|
+
import { existsSync as existsSync45, readFileSync as readFileSync53 } from "node:fs";
|
|
35389
36138
|
import { spawnSync as spawnSync3, execFile as execFile3 } from "node:child_process";
|
|
35390
|
-
import { dirname as
|
|
36139
|
+
import { dirname as dirname26, resolve as resolve36 } from "node:path";
|
|
35391
36140
|
import { fileURLToPath as fileURLToPath20 } from "node:url";
|
|
35392
36141
|
function stagedDir() {
|
|
35393
|
-
return process.env.HIMI_BROWSER_PLANE_OUT ?
|
|
36142
|
+
return process.env.HIMI_BROWSER_PLANE_OUT ? resolve36(process.env.HIMI_BROWSER_PLANE_OUT) : resolve36(REPO, "packages", "serve", "dist", "browser-plane");
|
|
35394
36143
|
}
|
|
35395
36144
|
function missingStaged() {
|
|
35396
|
-
return [...SERVED].filter((f) => !
|
|
36145
|
+
return [...SERVED].filter((f) => !existsSync45(resolve36(stagedDir(), f))).sort();
|
|
35397
36146
|
}
|
|
35398
36147
|
function ensureBrowserPlaneStaged() {
|
|
35399
36148
|
if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
|
|
35400
|
-
const r = spawnSync3(process.execPath, [
|
|
36149
|
+
const r = spawnSync3(process.execPath, [resolve36(REPO, "core/serve/scripts/stage-browser-plane.mjs")], {
|
|
35401
36150
|
cwd: REPO,
|
|
35402
36151
|
encoding: "utf8"
|
|
35403
36152
|
});
|
|
@@ -35483,7 +36232,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
35483
36232
|
}
|
|
35484
36233
|
const name = path === "/" || path === "/index.html" ? "host.html" : path.slice(1);
|
|
35485
36234
|
if (SERVED.has(name)) {
|
|
35486
|
-
if (!
|
|
36235
|
+
if (!existsSync45(resolve36(stagedDir(), name))) {
|
|
35487
36236
|
const restaged = ensureBrowserPlaneStaged();
|
|
35488
36237
|
if (!restaged.ok) {
|
|
35489
36238
|
res.writeHead(503, { "content-type": "application/json" });
|
|
@@ -35493,7 +36242,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
35493
36242
|
}
|
|
35494
36243
|
let bytes2;
|
|
35495
36244
|
try {
|
|
35496
|
-
bytes2 = readFileSync53(
|
|
36245
|
+
bytes2 = readFileSync53(resolve36(stagedDir(), name));
|
|
35497
36246
|
} catch (e) {
|
|
35498
36247
|
res.writeHead(503, { "content-type": "application/json" });
|
|
35499
36248
|
res.end(JSON.stringify({ error: "browser_plane_unstaged", file: name, detail: String(e) }));
|
|
@@ -35536,8 +36285,8 @@ var HERE, REPO, SERVED;
|
|
|
35536
36285
|
var init_run_browser = __esm({
|
|
35537
36286
|
"src/run-browser.ts"() {
|
|
35538
36287
|
init_file_store();
|
|
35539
|
-
HERE =
|
|
35540
|
-
REPO =
|
|
36288
|
+
HERE = dirname26(fileURLToPath20(import.meta.url));
|
|
36289
|
+
REPO = resolve36(HERE, "..", "..", "..");
|
|
35541
36290
|
SERVED = /* @__PURE__ */ new Set(["host.html", "sw.js", "package-reader.js"]);
|
|
35542
36291
|
}
|
|
35543
36292
|
});
|
|
@@ -35911,10 +36660,10 @@ __export(preflight_exports, {
|
|
|
35911
36660
|
parseStoreConfig: () => parseStoreConfig,
|
|
35912
36661
|
requireEnv: () => requireEnv
|
|
35913
36662
|
});
|
|
35914
|
-
import { existsSync as
|
|
35915
|
-
import { isAbsolute as isAbsolute2, relative as relative6, resolve as
|
|
36663
|
+
import { existsSync as existsSync46, readFileSync as readFileSync54 } from "node:fs";
|
|
36664
|
+
import { isAbsolute as isAbsolute2, relative as relative6, resolve as resolve37 } from "node:path";
|
|
35916
36665
|
function isInsideRepo(p) {
|
|
35917
|
-
const rel = relative6(REPO_ROOT3,
|
|
36666
|
+
const rel = relative6(REPO_ROOT3, resolve37(p));
|
|
35918
36667
|
return rel !== "" && !rel.startsWith("..") && !isAbsolute2(rel);
|
|
35919
36668
|
}
|
|
35920
36669
|
function assertCredentialOutsideRepo(label2, p) {
|
|
@@ -35968,7 +36717,7 @@ function parseStoreConfig(text2) {
|
|
|
35968
36717
|
}
|
|
35969
36718
|
function loadStoreConfig(app) {
|
|
35970
36719
|
const p = storeConfigPath(app);
|
|
35971
|
-
if (!
|
|
36720
|
+
if (!existsSync46(p)) {
|
|
35972
36721
|
throw new Error(`No store config at ${p}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
|
|
35973
36722
|
}
|
|
35974
36723
|
return parseStoreConfig(readFileSync54(p, "utf8"));
|
|
@@ -35994,9 +36743,9 @@ __export(preflight_app_exports, {
|
|
|
35994
36743
|
pngSize: () => pngSize,
|
|
35995
36744
|
preflightApp: () => preflightApp
|
|
35996
36745
|
});
|
|
35997
|
-
import { readFileSync as readFileSync55, existsSync as
|
|
36746
|
+
import { readFileSync as readFileSync55, existsSync as existsSync47, readdirSync as readdirSync22, statSync as statSync11 } from "node:fs";
|
|
35998
36747
|
import { createHash as createHash23 } from "node:crypto";
|
|
35999
|
-
import { join as
|
|
36748
|
+
import { join as join45 } from "node:path";
|
|
36000
36749
|
function analyze(projectYml, storeConfig, icon) {
|
|
36001
36750
|
const f = [];
|
|
36002
36751
|
const has = (re, s) => re.test(s);
|
|
@@ -36044,10 +36793,10 @@ function analyze(projectYml, storeConfig, icon) {
|
|
|
36044
36793
|
return f;
|
|
36045
36794
|
}
|
|
36046
36795
|
async function preflightApp(app) {
|
|
36047
|
-
const projectYml =
|
|
36048
|
-
const storeConfig =
|
|
36796
|
+
const projectYml = existsSync47(iosProjectYml(app)) ? readFileSync55(iosProjectYml(app), "utf8") : "";
|
|
36797
|
+
const storeConfig = existsSync47(storeConfigPath(app)) ? readFileSync55(storeConfigPath(app), "utf8") : "";
|
|
36049
36798
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }];
|
|
36050
|
-
const findings = analyze(projectYml, storeConfig, await appIconState(
|
|
36799
|
+
const findings = analyze(projectYml, storeConfig, await appIconState(join45(appDir(app), "ios")));
|
|
36051
36800
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
36052
36801
|
findings.push(
|
|
36053
36802
|
...analyzePlayListing(playListingAssets(app)).map((finding) => ({ ...finding, level: "warn" }))
|
|
@@ -36074,17 +36823,17 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
36074
36823
|
return f;
|
|
36075
36824
|
}
|
|
36076
36825
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
36077
|
-
const root =
|
|
36826
|
+
const root = join45(storeDir(app), "metadata");
|
|
36078
36827
|
const out = /* @__PURE__ */ new Set();
|
|
36079
|
-
if (
|
|
36828
|
+
if (existsSync47(root)) {
|
|
36080
36829
|
for (const n of readdirSync22(root)) if (n.endsWith(".txt")) out.add(n);
|
|
36081
36830
|
}
|
|
36082
|
-
if (
|
|
36831
|
+
if (existsSync47(join45(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
|
|
36083
36832
|
return out;
|
|
36084
36833
|
}
|
|
36085
36834
|
function reviewInfoFiles(app) {
|
|
36086
|
-
const dir =
|
|
36087
|
-
if (!
|
|
36835
|
+
const dir = join45(storeDir(app), "review_information");
|
|
36836
|
+
if (!existsSync47(dir)) return /* @__PURE__ */ new Set();
|
|
36088
36837
|
return new Set(readdirSync22(dir).filter((n) => n.endsWith(".txt")));
|
|
36089
36838
|
}
|
|
36090
36839
|
function isValidAppStoreSize(w, h) {
|
|
@@ -36194,12 +36943,12 @@ function analyzePlayListing(assets) {
|
|
|
36194
36943
|
return f;
|
|
36195
36944
|
}
|
|
36196
36945
|
function playListingAssets(app, locale = "en-US") {
|
|
36197
|
-
const dir =
|
|
36946
|
+
const dir = join45(storeDir(app), "play", locale, "images");
|
|
36198
36947
|
const read = (names) => {
|
|
36199
36948
|
for (const name of names) {
|
|
36200
|
-
const p =
|
|
36949
|
+
const p = join45(dir, name);
|
|
36201
36950
|
try {
|
|
36202
|
-
if (
|
|
36951
|
+
if (statSync11(p).isFile()) return { name, bytes: readFileSync55(p) };
|
|
36203
36952
|
} catch {
|
|
36204
36953
|
}
|
|
36205
36954
|
}
|
|
@@ -36230,26 +36979,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
36230
36979
|
return f;
|
|
36231
36980
|
}
|
|
36232
36981
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
36233
|
-
const dir =
|
|
36234
|
-
if (!
|
|
36982
|
+
const dir = join45(storeDir(app), "metadata", locale);
|
|
36983
|
+
if (!existsSync47(dir)) return /* @__PURE__ */ new Set();
|
|
36235
36984
|
return new Set(readdirSync22(dir).filter((n) => n.endsWith(".txt")));
|
|
36236
36985
|
}
|
|
36237
36986
|
function listScreenshots(app, locale = "en-US") {
|
|
36238
36987
|
const out = [];
|
|
36239
|
-
const flat =
|
|
36240
|
-
if (
|
|
36988
|
+
const flat = join45(storeDir(app), "screenshots", locale);
|
|
36989
|
+
if (existsSync47(flat)) {
|
|
36241
36990
|
for (const png of readdirSync22(flat).filter((n) => n.endsWith(".png"))) {
|
|
36242
|
-
const sz = pngSize(readFileSync55(
|
|
36991
|
+
const sz = pngSize(readFileSync55(join45(flat, png)));
|
|
36243
36992
|
if (sz) out.push({ name: png, w: sz.w, h: sz.h });
|
|
36244
36993
|
}
|
|
36245
36994
|
}
|
|
36246
|
-
const legacy =
|
|
36247
|
-
if (
|
|
36995
|
+
const legacy = join45(storeDir(app), "metadata", locale, "screenshots");
|
|
36996
|
+
if (existsSync47(legacy)) {
|
|
36248
36997
|
for (const deviceDir of readdirSync22(legacy)) {
|
|
36249
|
-
const d =
|
|
36250
|
-
if (!
|
|
36998
|
+
const d = join45(legacy, deviceDir);
|
|
36999
|
+
if (!statSync11(d).isDirectory()) continue;
|
|
36251
37000
|
for (const png of readdirSync22(d).filter((n) => n.endsWith(".png"))) {
|
|
36252
|
-
const sz = pngSize(readFileSync55(
|
|
37001
|
+
const sz = pngSize(readFileSync55(join45(d, png)));
|
|
36253
37002
|
if (sz) out.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
36254
37003
|
}
|
|
36255
37004
|
}
|
|
@@ -36257,12 +37006,12 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
36257
37006
|
return out;
|
|
36258
37007
|
}
|
|
36259
37008
|
function placeholderHashes2() {
|
|
36260
|
-
const templateIos =
|
|
36261
|
-
if (!
|
|
37009
|
+
const templateIos = join45(appDir("_template"), "ios");
|
|
37010
|
+
if (!existsSync47(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
36262
37011
|
for (const target of readdirSync22(templateIos)) {
|
|
36263
|
-
const p =
|
|
37012
|
+
const p = join45(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
36264
37013
|
try {
|
|
36265
|
-
if (!
|
|
37014
|
+
if (!statSync11(p).isFile()) continue;
|
|
36266
37015
|
return [LEGACY_PLACEHOLDER_SHA2562, createHash23("sha256").update(readFileSync55(p)).digest("hex")];
|
|
36267
37016
|
} catch {
|
|
36268
37017
|
}
|
|
@@ -36294,11 +37043,11 @@ async function pixelIssues(bytes2) {
|
|
|
36294
37043
|
}
|
|
36295
37044
|
}
|
|
36296
37045
|
async function appIconState(iosDir) {
|
|
36297
|
-
if (!
|
|
37046
|
+
if (!existsSync47(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
36298
37047
|
for (const target of readdirSync22(iosDir)) {
|
|
36299
|
-
const p =
|
|
37048
|
+
const p = join45(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
36300
37049
|
try {
|
|
36301
|
-
if (!
|
|
37050
|
+
if (!statSync11(p).isFile()) continue;
|
|
36302
37051
|
const bytes2 = readFileSync55(p);
|
|
36303
37052
|
const hash = createHash23("sha256").update(bytes2).digest("hex");
|
|
36304
37053
|
const pixels = await pixelIssues(bytes2);
|
|
@@ -36369,14 +37118,14 @@ __export(credential_profile_exports, {
|
|
|
36369
37118
|
profilePath: () => profilePath,
|
|
36370
37119
|
resolveStoreCredentials: () => resolveStoreCredentials
|
|
36371
37120
|
});
|
|
36372
|
-
import { existsSync as
|
|
37121
|
+
import { existsSync as existsSync48, readFileSync as readFileSync56 } from "node:fs";
|
|
36373
37122
|
import { homedir as homedir6 } from "node:os";
|
|
36374
|
-
import { join as
|
|
37123
|
+
import { join as join46 } from "node:path";
|
|
36375
37124
|
function credentialsDir(home = homedir6()) {
|
|
36376
|
-
return
|
|
37125
|
+
return join46(home, ".himalaya", "store-credentials");
|
|
36377
37126
|
}
|
|
36378
37127
|
function profilePath(name, home = homedir6()) {
|
|
36379
|
-
return
|
|
37128
|
+
return join46(credentialsDir(home), `${name}.json`);
|
|
36380
37129
|
}
|
|
36381
37130
|
function parseProfile(text2, label2) {
|
|
36382
37131
|
let doc;
|
|
@@ -36404,7 +37153,7 @@ function resolveStoreCredentials(opts) {
|
|
|
36404
37153
|
const env = opts.env ?? process.env;
|
|
36405
37154
|
const home = opts.home ?? homedir6();
|
|
36406
37155
|
const read = opts.readProfile ?? ((p) => readFileSync56(p, "utf8"));
|
|
36407
|
-
const exists = opts.profileExists ??
|
|
37156
|
+
const exists = opts.profileExists ?? existsSync48;
|
|
36408
37157
|
const ios = cfg.ios ?? {};
|
|
36409
37158
|
const flagName = opts.profileFlag?.trim();
|
|
36410
37159
|
const named = flagName || ios.credentialProfile?.trim();
|
|
@@ -39696,10 +40445,10 @@ function isFetchableFontUrl(raw) {
|
|
|
39696
40445
|
return true;
|
|
39697
40446
|
}
|
|
39698
40447
|
function resolveAll(hostname) {
|
|
39699
|
-
return new Promise((
|
|
40448
|
+
return new Promise((resolve41, reject) => {
|
|
39700
40449
|
dnsLookup(hostname, { all: true, verbatim: true }, (err, addresses) => {
|
|
39701
40450
|
if (err) reject(err);
|
|
39702
|
-
else
|
|
40451
|
+
else resolve41(addresses);
|
|
39703
40452
|
});
|
|
39704
40453
|
});
|
|
39705
40454
|
}
|
|
@@ -39707,13 +40456,13 @@ function withAbort(start, signal, what) {
|
|
|
39707
40456
|
if (signal?.aborted) return Promise.reject(new Error(`${what} aborted`));
|
|
39708
40457
|
const work = start();
|
|
39709
40458
|
if (!signal) return work;
|
|
39710
|
-
return new Promise((
|
|
40459
|
+
return new Promise((resolve41, reject) => {
|
|
39711
40460
|
const onAbort = () => reject(new Error(`${what} aborted`));
|
|
39712
40461
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
39713
|
-
work.then(
|
|
40462
|
+
work.then(resolve41, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
39714
40463
|
});
|
|
39715
40464
|
}
|
|
39716
|
-
async function pinAddress(url,
|
|
40465
|
+
async function pinAddress(url, resolve41 = resolveAll, signal) {
|
|
39717
40466
|
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
39718
40467
|
if (ipv4Octets(host)) {
|
|
39719
40468
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
@@ -39723,7 +40472,7 @@ async function pinAddress(url, resolve40 = resolveAll, signal) {
|
|
|
39723
40472
|
if (isBlockedAddress(host)) throw new Error(`${host} is a blocked address`);
|
|
39724
40473
|
return { address: host, family: 6 };
|
|
39725
40474
|
}
|
|
39726
|
-
const addresses = await withAbort(() =>
|
|
40475
|
+
const addresses = await withAbort(() => resolve41(host), signal, `${host} lookup`);
|
|
39727
40476
|
if (!addresses.length) throw new Error(`${host} resolved to no address`);
|
|
39728
40477
|
const blocked = addresses.filter((a) => isBlockedAddress(a.address)).map((a) => a.address);
|
|
39729
40478
|
if (blocked.length) throw new Error(`${host} resolves to a blocked address (${blocked.join(", ")})`);
|
|
@@ -39746,7 +40495,7 @@ function decodedBody(res, hasBody) {
|
|
|
39746
40495
|
return out;
|
|
39747
40496
|
}
|
|
39748
40497
|
function requestOnce(url, pinned, init) {
|
|
39749
|
-
return new Promise((
|
|
40498
|
+
return new Promise((resolve41, reject) => {
|
|
39750
40499
|
const headers2 = { host: url.host, "accept-encoding": "identity" };
|
|
39751
40500
|
new Headers(init.headers ?? {}).forEach((value, key2) => {
|
|
39752
40501
|
if (key2.toLowerCase() !== "host") headers2[key2] = value;
|
|
@@ -39780,7 +40529,7 @@ function requestOnce(url, pinned, init) {
|
|
|
39780
40529
|
reject(err);
|
|
39781
40530
|
return;
|
|
39782
40531
|
}
|
|
39783
|
-
|
|
40532
|
+
resolve41(new Response(body, { status, statusText: res.statusMessage ?? "", headers: out }));
|
|
39784
40533
|
}
|
|
39785
40534
|
);
|
|
39786
40535
|
req.on("error", reject);
|
|
@@ -39889,7 +40638,7 @@ var init_brand_font = __esm({
|
|
|
39889
40638
|
|
|
39890
40639
|
// src/site-analyze/write-artifacts.ts
|
|
39891
40640
|
import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync20 } from "node:fs";
|
|
39892
|
-
import { join as
|
|
40641
|
+
import { join as join47 } from "node:path";
|
|
39893
40642
|
function attachVeloSources(book, sources, put) {
|
|
39894
40643
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
39895
40644
|
for (const f of book.velo.files) {
|
|
@@ -40044,12 +40793,12 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
40044
40793
|
}
|
|
40045
40794
|
async function writeBusinessBook(result, opts) {
|
|
40046
40795
|
const out = opts.outDir;
|
|
40047
|
-
mkdirSync23(
|
|
40048
|
-
mkdirSync23(
|
|
40796
|
+
mkdirSync23(join47(out, "evidence/pages"), { recursive: true });
|
|
40797
|
+
mkdirSync23(join47(out, "media/catalog"), { recursive: true });
|
|
40049
40798
|
const files = [];
|
|
40050
40799
|
const put = (rel, body) => {
|
|
40051
|
-
const p =
|
|
40052
|
-
mkdirSync23(
|
|
40800
|
+
const p = join47(out, rel);
|
|
40801
|
+
mkdirSync23(join47(p, ".."), { recursive: true });
|
|
40053
40802
|
writeFileSync20(p, body);
|
|
40054
40803
|
files.push(rel);
|
|
40055
40804
|
};
|
|
@@ -40380,15 +41129,15 @@ var init_home_descriptor = __esm({
|
|
|
40380
41129
|
});
|
|
40381
41130
|
|
|
40382
41131
|
// src/site-analyze/apply.ts
|
|
40383
|
-
import { existsSync as
|
|
40384
|
-
import { dirname as
|
|
41132
|
+
import { existsSync as existsSync49, readFileSync as readFileSync60, writeFileSync as writeFileSync21, copyFileSync as copyFileSync3, mkdirSync as mkdirSync24, realpathSync as realpathSync5, statSync as statSync12 } from "node:fs";
|
|
41133
|
+
import { dirname as dirname27, isAbsolute as isAbsolute3, join as join48, resolve as resolve38, sep as sep10 } from "node:path";
|
|
40385
41134
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
40386
41135
|
function unpairedRedirectNote(overlay) {
|
|
40387
41136
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
40388
41137
|
return `no OAuth redirect paired with client ${overlay.wix.clientId} \u2014 the app (and prepare:customer) will refuse to start until one is set. Register it with \`himi site client ensure --site ${overlay.siteId?.trim() || "<msid>"} --redirect-uri <uri> --yes\`, then re-run analyze with \`--redirect-uri <uri>\` (or export HIMI_BRANDED_LITE_WIX_REDIRECT_URI)`;
|
|
40389
41138
|
}
|
|
40390
41139
|
function posix2(p) {
|
|
40391
|
-
return
|
|
41140
|
+
return resolve38(p).replace(/\\/g, "/");
|
|
40392
41141
|
}
|
|
40393
41142
|
function committedShellProvisioning(path) {
|
|
40394
41143
|
return committedShellFor(posix2(path));
|
|
@@ -40396,8 +41145,8 @@ function committedShellProvisioning(path) {
|
|
|
40396
41145
|
function findRepoRoot(cwd) {
|
|
40397
41146
|
let dir = cwd;
|
|
40398
41147
|
for (let i = 0; i < 8; i++) {
|
|
40399
|
-
if (SHELL_NAMES2.some((name) =>
|
|
40400
|
-
const next =
|
|
41148
|
+
if (SHELL_NAMES2.some((name) => existsSync49(join48(dir, shellAppDir(name), "package.json")))) return dir;
|
|
41149
|
+
const next = dirname27(dir);
|
|
40401
41150
|
if (next === dir) break;
|
|
40402
41151
|
dir = next;
|
|
40403
41152
|
}
|
|
@@ -40422,7 +41171,7 @@ function assertNotCommitted(path, forbidden) {
|
|
|
40422
41171
|
`refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
|
|
40423
41172
|
);
|
|
40424
41173
|
}
|
|
40425
|
-
if (forbidden &&
|
|
41174
|
+
if (forbidden && resolve38(path) === resolve38(forbidden)) {
|
|
40426
41175
|
const named = committedShellProvisioning(forbidden);
|
|
40427
41176
|
throw new Error(
|
|
40428
41177
|
`refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
|
|
@@ -40464,8 +41213,8 @@ function mergeCustomerOwned(committed, overlay) {
|
|
|
40464
41213
|
}
|
|
40465
41214
|
function buildMergedContract(options) {
|
|
40466
41215
|
const { appDir: appDir2, packageDir, overlay } = options;
|
|
40467
|
-
const committedPath =
|
|
40468
|
-
if (!
|
|
41216
|
+
const committedPath = join48(appDir2, "provisioning.json");
|
|
41217
|
+
if (!existsSync49(committedPath)) {
|
|
40469
41218
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
40470
41219
|
}
|
|
40471
41220
|
const committed = JSON.parse(readFileSync60(committedPath, "utf8"));
|
|
@@ -40475,25 +41224,25 @@ function buildMergedContract(options) {
|
|
|
40475
41224
|
const staged = [];
|
|
40476
41225
|
const contained = (root, rel) => {
|
|
40477
41226
|
if (isAbsolute3(rel)) return void 0;
|
|
40478
|
-
const full =
|
|
40479
|
-
return full.startsWith(
|
|
41227
|
+
const full = resolve38(root, rel);
|
|
41228
|
+
return full.startsWith(resolve38(root) + sep10) ? full : void 0;
|
|
40480
41229
|
};
|
|
40481
41230
|
const stage = (fromRel, toRel) => {
|
|
40482
41231
|
const from = contained(packageDir, fromRel);
|
|
40483
|
-
const to = contained(
|
|
40484
|
-
if (!from || !to || !
|
|
41232
|
+
const to = contained(join48(appDir2, STAGED), toRel.slice(STAGED.length + 1));
|
|
41233
|
+
if (!from || !to || !existsSync49(from)) return void 0;
|
|
40485
41234
|
let real;
|
|
40486
41235
|
let realRoot;
|
|
40487
41236
|
try {
|
|
40488
|
-
real =
|
|
40489
|
-
realRoot =
|
|
41237
|
+
real = realpathSync5(from);
|
|
41238
|
+
realRoot = realpathSync5(packageDir);
|
|
40490
41239
|
} catch {
|
|
40491
41240
|
return void 0;
|
|
40492
41241
|
}
|
|
40493
|
-
if (!real.startsWith(realRoot +
|
|
41242
|
+
if (!real.startsWith(realRoot + sep10)) return void 0;
|
|
40494
41243
|
try {
|
|
40495
|
-
if (!
|
|
40496
|
-
mkdirSync24(
|
|
41244
|
+
if (!statSync12(real).isFile()) return void 0;
|
|
41245
|
+
mkdirSync24(dirname27(to), { recursive: true });
|
|
40497
41246
|
copyFileSync3(real, to);
|
|
40498
41247
|
} catch {
|
|
40499
41248
|
return void 0;
|
|
@@ -40503,8 +41252,8 @@ function buildMergedContract(options) {
|
|
|
40503
41252
|
};
|
|
40504
41253
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
40505
41254
|
if (icon) branding.appIconPath = icon;
|
|
40506
|
-
const facesPath =
|
|
40507
|
-
if (
|
|
41255
|
+
const facesPath = join48(packageDir, "media/fonts/faces.json");
|
|
41256
|
+
if (existsSync49(facesPath)) {
|
|
40508
41257
|
let faces = [];
|
|
40509
41258
|
try {
|
|
40510
41259
|
const parsed = JSON.parse(readFileSync60(facesPath, "utf8"));
|
|
@@ -40528,16 +41277,16 @@ function buildMergedContract(options) {
|
|
|
40528
41277
|
merged.branding = branding;
|
|
40529
41278
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
40530
41279
|
`;
|
|
40531
|
-
const path =
|
|
41280
|
+
const path = join48(packageDir, "provisioning.contract.json");
|
|
40532
41281
|
writeFileSync21(path, body);
|
|
40533
|
-
const localPath =
|
|
40534
|
-
mkdirSync24(
|
|
41282
|
+
const localPath = join48(appDir2, LOCAL_CONTRACT_REL);
|
|
41283
|
+
mkdirSync24(dirname27(localPath), { recursive: true });
|
|
40535
41284
|
writeFileSync21(localPath, body);
|
|
40536
41285
|
staged.push(localPath);
|
|
40537
41286
|
return { path, staged };
|
|
40538
41287
|
}
|
|
40539
41288
|
async function applyOverlays(input) {
|
|
40540
|
-
const cwd =
|
|
41289
|
+
const cwd = resolve38(input.cwd);
|
|
40541
41290
|
const shell = input.shell ?? DEFAULT_BRANDABLE_SHELL;
|
|
40542
41291
|
assertKnownShell(shell);
|
|
40543
41292
|
const overlay = JSON.parse(readFileSync60(input.overlayPath, "utf8"));
|
|
@@ -40551,8 +41300,8 @@ async function applyOverlays(input) {
|
|
|
40551
41300
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
40552
41301
|
);
|
|
40553
41302
|
}
|
|
40554
|
-
const appDir2 =
|
|
40555
|
-
const packageDir =
|
|
41303
|
+
const appDir2 = join48(repoRoot2, shellAppDir(shell));
|
|
41304
|
+
const packageDir = dirname27(resolve38(input.overlayPath));
|
|
40556
41305
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir2, packageDir, overlay });
|
|
40557
41306
|
wrote.push(...staged);
|
|
40558
41307
|
const r = spawnSync4("npm", ["run", "prepare:customer", "--", "--contract", contract], {
|
|
@@ -40573,9 +41322,9 @@ async function applyOverlays(input) {
|
|
|
40573
41322
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
40574
41323
|
};
|
|
40575
41324
|
}
|
|
40576
|
-
const pkgProv =
|
|
41325
|
+
const pkgProv = join48(cwd, "provisioning.json");
|
|
40577
41326
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
40578
|
-
if (
|
|
41327
|
+
if (existsSync49(pkgProv)) {
|
|
40579
41328
|
const cur = JSON.parse(readFileSync60(pkgProv, "utf8"));
|
|
40580
41329
|
const merged = deepMerge3(cur, overlay);
|
|
40581
41330
|
writeFileSync21(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
@@ -40584,16 +41333,16 @@ async function applyOverlays(input) {
|
|
|
40584
41333
|
writeFileSync21(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
40585
41334
|
wrote.push(pkgProv);
|
|
40586
41335
|
}
|
|
40587
|
-
const pkgTokens =
|
|
40588
|
-
if (
|
|
41336
|
+
const pkgTokens = join48(cwd, "tokens.json");
|
|
41337
|
+
if (existsSync49(pkgTokens) && (tokens.colors || tokens.typography)) {
|
|
40589
41338
|
const cur = JSON.parse(readFileSync60(pkgTokens, "utf8"));
|
|
40590
41339
|
const merged = deepMerge3(cur, tokens);
|
|
40591
41340
|
writeFileSync21(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
|
|
40592
41341
|
wrote.push(pkgTokens);
|
|
40593
41342
|
}
|
|
40594
41343
|
const homeAction = homeRefreshActionId(shell);
|
|
40595
|
-
const homeSrc =
|
|
40596
|
-
if (homeAction &&
|
|
41344
|
+
const homeSrc = join48(cwd, "dev/index.ts");
|
|
41345
|
+
if (homeAction && existsSync49(homeSrc)) {
|
|
40597
41346
|
const prev = readFileSync60(homeSrc, "utf8");
|
|
40598
41347
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
40599
41348
|
let next = patched.src;
|
|
@@ -40614,13 +41363,13 @@ async function applyOverlays(input) {
|
|
|
40614
41363
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
40615
41364
|
}
|
|
40616
41365
|
}
|
|
40617
|
-
if (!input.iconPath || !
|
|
40618
|
-
const book = input.iconPath ?
|
|
41366
|
+
if (!input.iconPath || !existsSync49(input.iconPath)) {
|
|
41367
|
+
const book = input.iconPath ? dirname27(dirname27(resolve38(input.iconPath))) : void 0;
|
|
40619
41368
|
notes.push(
|
|
40620
41369
|
book ? `no icon installed \u2014 ${siteLogoAbsence(book).hint}` : "no icon installed and no business book to say why \u2014 `himi icon generate` draws one from the accent, or `himi icon set <file.png>` installs the customer's own mark"
|
|
40621
41370
|
);
|
|
40622
41371
|
}
|
|
40623
|
-
if (input.iconPath &&
|
|
41372
|
+
if (input.iconPath && existsSync49(input.iconPath)) {
|
|
40624
41373
|
try {
|
|
40625
41374
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
40626
41375
|
wrote.push(...installed.wrote);
|
|
@@ -41755,12 +42504,12 @@ __export(cli_exports, {
|
|
|
41755
42504
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
41756
42505
|
});
|
|
41757
42506
|
import { readFileSync as readFileSync61 } from "node:fs";
|
|
41758
|
-
import { resolve as
|
|
42507
|
+
import { resolve as resolve39 } from "node:path";
|
|
41759
42508
|
async function runSiteAnalyze(opts) {
|
|
41760
42509
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
41761
42510
|
const assetFetch = opts.fetchImpl ?? pinnedFetch2;
|
|
41762
42511
|
const cwd = opts.cwd ?? process.cwd();
|
|
41763
|
-
const outDir =
|
|
42512
|
+
const outDir = resolve39(cwd, opts.outDir ?? ".himi/business-book");
|
|
41764
42513
|
let ownerAuth;
|
|
41765
42514
|
let msid;
|
|
41766
42515
|
try {
|
|
@@ -41797,9 +42546,9 @@ async function runSiteAnalyze(opts) {
|
|
|
41797
42546
|
if (opts.apply) {
|
|
41798
42547
|
applied = await applyOverlays({
|
|
41799
42548
|
cwd,
|
|
41800
|
-
overlayPath:
|
|
41801
|
-
tokensPath:
|
|
41802
|
-
iconPath:
|
|
42549
|
+
overlayPath: resolve39(outDir, "provisioning.overlay.json"),
|
|
42550
|
+
tokensPath: resolve39(outDir, "tokens.overlay.json"),
|
|
42551
|
+
iconPath: resolve39(outDir, "media/icon.png"),
|
|
41803
42552
|
shell: opts.shell
|
|
41804
42553
|
});
|
|
41805
42554
|
const note = noteWithWarnings(applied.note, warnings);
|
|
@@ -41835,7 +42584,7 @@ async function runSiteFunctionCli(opts) {
|
|
|
41835
42584
|
const token = opts.token ?? await siteToken(msid);
|
|
41836
42585
|
let source;
|
|
41837
42586
|
if (opts.sourcePath) {
|
|
41838
|
-
const p =
|
|
42587
|
+
const p = resolve39(opts.cwd ?? process.cwd(), opts.sourcePath);
|
|
41839
42588
|
source = readFileSync61(p, "utf8");
|
|
41840
42589
|
}
|
|
41841
42590
|
let body;
|
|
@@ -41887,7 +42636,7 @@ async function accountToken2(spawnImpl = spawn4) {
|
|
|
41887
42636
|
cached2 = fromEnv;
|
|
41888
42637
|
return fromEnv;
|
|
41889
42638
|
}
|
|
41890
|
-
const token = await new Promise((
|
|
42639
|
+
const token = await new Promise((resolve41, reject) => {
|
|
41891
42640
|
let child;
|
|
41892
42641
|
try {
|
|
41893
42642
|
child = spawnImpl("wix", ["token"]);
|
|
@@ -41916,7 +42665,7 @@ async function accountToken2(spawnImpl = spawn4) {
|
|
|
41916
42665
|
const scan = (d) => {
|
|
41917
42666
|
out += String(d);
|
|
41918
42667
|
const m = out.match(TOKEN_RE2);
|
|
41919
|
-
if (m) done(() =>
|
|
42668
|
+
if (m) done(() => resolve41(m[0]));
|
|
41920
42669
|
};
|
|
41921
42670
|
child.stdout?.on("data", scan);
|
|
41922
42671
|
child.stderr?.on("data", scan);
|
|
@@ -42093,7 +42842,7 @@ __export(site_create_exports, {
|
|
|
42093
42842
|
runSiteList: () => runSiteList,
|
|
42094
42843
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
42095
42844
|
});
|
|
42096
|
-
import { existsSync as
|
|
42845
|
+
import { existsSync as existsSync50, readFileSync as readFileSync62, writeFileSync as writeFileSync22 } from "node:fs";
|
|
42097
42846
|
import { resolve as resolvePath2 } from "node:path";
|
|
42098
42847
|
function oauthClientName(projectName) {
|
|
42099
42848
|
return `${projectName} client`;
|
|
@@ -42242,7 +42991,7 @@ async function runSiteCreate(opts) {
|
|
|
42242
42991
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
42243
42992
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
42244
42993
|
}
|
|
42245
|
-
function writeProvisioningBinding(target, binding2, fs = { existsSync:
|
|
42994
|
+
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync50, readFileSync: readFileSync62, writeFileSync: writeFileSync22 }) {
|
|
42246
42995
|
const msid = binding2.siteId;
|
|
42247
42996
|
const path = resolvePath2(target);
|
|
42248
42997
|
const committed = committedShellProvisioning(path);
|
|
@@ -42576,11 +43325,11 @@ var init_site_oauth_client = __esm({
|
|
|
42576
43325
|
});
|
|
42577
43326
|
|
|
42578
43327
|
// src/cli.ts
|
|
42579
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync63, mkdirSync as mkdirSync25, writeFileSync as writeFileSync23, existsSync as
|
|
43328
|
+
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync63, mkdirSync as mkdirSync25, writeFileSync as writeFileSync23, existsSync as existsSync51, rmSync as rmSync9, readdirSync as readdirSync23, statSync as statSync13 } from "node:fs";
|
|
42580
43329
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
42581
43330
|
import { createHash as createHash24 } from "node:crypto";
|
|
42582
43331
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
42583
|
-
import { join as
|
|
43332
|
+
import { join as join49, resolve as resolve40, basename as basename8, dirname as dirname28 } from "node:path";
|
|
42584
43333
|
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
42585
43334
|
|
|
42586
43335
|
// ../serve-cli/src/client.ts
|
|
@@ -44089,7 +44838,7 @@ async function browserLogin(opts) {
|
|
|
44089
44838
|
const log = opts.log ?? (() => {
|
|
44090
44839
|
});
|
|
44091
44840
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
44092
|
-
return await new Promise((
|
|
44841
|
+
return await new Promise((resolve41, reject) => {
|
|
44093
44842
|
let settled = false;
|
|
44094
44843
|
let loginUrl = "";
|
|
44095
44844
|
const server = createServer();
|
|
@@ -44153,7 +44902,7 @@ async function browserLogin(opts) {
|
|
|
44153
44902
|
return;
|
|
44154
44903
|
}
|
|
44155
44904
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", connection: "close" }).end(CLOSE_PAGE);
|
|
44156
|
-
finish2(() =>
|
|
44905
|
+
finish2(() => resolve41({ token, loginUrl }));
|
|
44157
44906
|
});
|
|
44158
44907
|
});
|
|
44159
44908
|
server.on("error", (err) => finish2(() => reject(err)));
|
|
@@ -45088,10 +45837,10 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
|
|
|
45088
45837
|
// src/notify.ts
|
|
45089
45838
|
import { chmodSync as chmodSync2, mkdirSync as mkdirSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "node:fs";
|
|
45090
45839
|
import { homedir as homedir3 } from "node:os";
|
|
45091
|
-
import { dirname as dirname12, join as
|
|
45840
|
+
import { dirname as dirname12, join as join15 } from "node:path";
|
|
45092
45841
|
var DEFAULT_ADMIN_URL = "http://127.0.0.1:8888";
|
|
45093
45842
|
function defaultSessionsPath() {
|
|
45094
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
45843
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join15(homedir3(), ".himalaya", "admin-sessions.json");
|
|
45095
45844
|
}
|
|
45096
45845
|
function loadSessionsFile(path = defaultSessionsPath()) {
|
|
45097
45846
|
try {
|
|
@@ -45330,7 +46079,7 @@ NOTE: ${simulated} of those went to the booted iOS Simulator, NOT to the device
|
|
|
45330
46079
|
init_car();
|
|
45331
46080
|
init_preview_surfaces();
|
|
45332
46081
|
import { existsSync as existsSync12, readFileSync as readFileSync15 } from "node:fs";
|
|
45333
|
-
import { join as
|
|
46082
|
+
import { join as join16 } from "node:path";
|
|
45334
46083
|
var VALID_PLATFORM_KEYS = /* @__PURE__ */ new Set([
|
|
45335
46084
|
...PREVIEW_SURFACES.map((s) => s.platformKey).filter((k) => k !== null),
|
|
45336
46085
|
...PREVIEW_EXEMPT_PLATFORM_KEYS
|
|
@@ -45341,7 +46090,7 @@ function surfaceIssues(dir, surfaceNav, strict) {
|
|
|
45341
46090
|
const error = (message) => issues.push({ screen: null, pass: "surfaces", severity: "error", message });
|
|
45342
46091
|
let platforms = {};
|
|
45343
46092
|
let envelopeUnreadable = false;
|
|
45344
|
-
const p =
|
|
46093
|
+
const p = join16(dir, "platforms.json");
|
|
45345
46094
|
if (existsSync12(p)) {
|
|
45346
46095
|
let raw;
|
|
45347
46096
|
try {
|
|
@@ -45374,7 +46123,7 @@ function surfaceIssues(dir, surfaceNav, strict) {
|
|
|
45374
46123
|
});
|
|
45375
46124
|
}
|
|
45376
46125
|
if (envelopeUnreadable) return issues;
|
|
45377
|
-
const configTs =
|
|
46126
|
+
const configTs = join16(dir, "config.ts");
|
|
45378
46127
|
if (existsSync12(configTs)) {
|
|
45379
46128
|
const declared = parseCarConfig(readFileSync15(configTs, "utf8")).category;
|
|
45380
46129
|
const inEnvelope = platforms.androidauto === true;
|
|
@@ -45400,7 +46149,7 @@ function surfaceIssues(dir, surfaceNav, strict) {
|
|
|
45400
46149
|
}
|
|
45401
46150
|
function readLocalPlatforms(dir) {
|
|
45402
46151
|
try {
|
|
45403
|
-
const raw = JSON.parse(readFileSync15(
|
|
46152
|
+
const raw = JSON.parse(readFileSync15(join16(dir, "platforms.json"), "utf8"));
|
|
45404
46153
|
return Object.fromEntries(
|
|
45405
46154
|
Object.entries(raw).filter(([k, v]) => VALID_PLATFORM_KEYS.has(k) && typeof v === "boolean")
|
|
45406
46155
|
);
|
|
@@ -45412,10 +46161,10 @@ function readLocalPlatforms(dir) {
|
|
|
45412
46161
|
// src/token-lint.ts
|
|
45413
46162
|
init_token_colors();
|
|
45414
46163
|
import { existsSync as existsSync13, readFileSync as readFileSync16 } from "node:fs";
|
|
45415
|
-
import { join as
|
|
46164
|
+
import { join as join17 } from "node:path";
|
|
45416
46165
|
function configuredTokensPath(dir) {
|
|
45417
46166
|
for (const name of ["config.ts", "config.js", "himi.config.ts"]) {
|
|
45418
|
-
const f =
|
|
46167
|
+
const f = join17(dir, name);
|
|
45419
46168
|
if (!existsSync13(f)) continue;
|
|
45420
46169
|
const src = readFileSync16(f, "utf8");
|
|
45421
46170
|
const m = /designTokensPath\s*:\s*["'`]([^"'`]+)["'`]/.exec(src);
|
|
@@ -45435,7 +46184,7 @@ function tokenColorIssues(dir, tokensPathOverride) {
|
|
|
45435
46184
|
);
|
|
45436
46185
|
}
|
|
45437
46186
|
const tokensPath = configured.path ?? "tokens.json";
|
|
45438
|
-
const p =
|
|
46187
|
+
const p = join17(dir, tokensPath);
|
|
45439
46188
|
if (!existsSync13(p)) {
|
|
45440
46189
|
if (tokensPath !== "tokens.json") {
|
|
45441
46190
|
warn(`config designTokensPath points at ${tokensPath}, which does not exist -- colour tokens were not checked`);
|
|
@@ -45483,9 +46232,9 @@ function tokenColorIssues(dir, tokensPathOverride) {
|
|
|
45483
46232
|
// src/icon-lint.ts
|
|
45484
46233
|
init_icon();
|
|
45485
46234
|
import { existsSync as existsSync16 } from "node:fs";
|
|
45486
|
-
import { join as
|
|
46235
|
+
import { join as join20 } from "node:path";
|
|
45487
46236
|
async function iconIssues(dir, strict, opts = {}) {
|
|
45488
|
-
if (!existsSync16(
|
|
46237
|
+
if (!existsSync16(join20(dir, "himalaya.content.json"))) return [];
|
|
45489
46238
|
const status = await iconStatus(dir);
|
|
45490
46239
|
const issue2 = (severity, message) => ({
|
|
45491
46240
|
screen: null,
|
|
@@ -45553,13 +46302,13 @@ function fontIssues(dir, strict) {
|
|
|
45553
46302
|
|
|
45554
46303
|
// src/stores-api-lint.ts
|
|
45555
46304
|
import { existsSync as existsSync20, readdirSync as readdirSync10, readFileSync as readFileSync22 } from "node:fs";
|
|
45556
|
-
import { join as
|
|
46305
|
+
import { join as join24 } from "node:path";
|
|
45557
46306
|
function storesV1Issues(contentDir2, strict) {
|
|
45558
|
-
const roots = [
|
|
46307
|
+
const roots = [join24(contentDir2, "tier5-src"), join24(contentDir2, "dev")].filter(existsSync20);
|
|
45559
46308
|
const files = [];
|
|
45560
46309
|
const visit = (dir) => {
|
|
45561
46310
|
for (const entry of readdirSync10(dir, { withFileTypes: true })) {
|
|
45562
|
-
const path =
|
|
46311
|
+
const path = join24(dir, entry.name);
|
|
45563
46312
|
if (entry.isDirectory()) visit(path);
|
|
45564
46313
|
else if (/\.(?:[cm]?[jt]sx?)$/i.test(entry.name)) files.push(path);
|
|
45565
46314
|
}
|
|
@@ -45580,7 +46329,7 @@ init_crawl_layers();
|
|
|
45580
46329
|
init_wix_gateway_rules();
|
|
45581
46330
|
init_mobile_ux_contract();
|
|
45582
46331
|
import { existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync23, readdirSync as readdirSync11, writeFileSync as writeFileSync9 } from "node:fs";
|
|
45583
|
-
import { join as
|
|
46332
|
+
import { join as join25, relative as relative3, resolve as resolve15 } from "node:path";
|
|
45584
46333
|
var EVIDENCE_RELATIVE_PATH = ".himi/ux-audit.json";
|
|
45585
46334
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".json"]);
|
|
45586
46335
|
var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".himi", "coverage"]);
|
|
@@ -45598,12 +46347,12 @@ function walkSource(dir, root = dir) {
|
|
|
45598
46347
|
const found = [];
|
|
45599
46348
|
for (const entry of readdirSync11(dir, { withFileTypes: true })) {
|
|
45600
46349
|
if (entry.isDirectory()) {
|
|
45601
|
-
if (!IGNORED_DIRECTORIES.has(entry.name)) found.push(...walkSource(
|
|
46350
|
+
if (!IGNORED_DIRECTORIES.has(entry.name)) found.push(...walkSource(join25(dir, entry.name), root));
|
|
45602
46351
|
continue;
|
|
45603
46352
|
}
|
|
45604
46353
|
const ext = entry.name.slice(entry.name.lastIndexOf("."));
|
|
45605
46354
|
if (!SOURCE_EXTENSIONS.has(ext)) continue;
|
|
45606
|
-
const absolute =
|
|
46355
|
+
const absolute = join25(dir, entry.name);
|
|
45607
46356
|
const text2 = readText(absolute);
|
|
45608
46357
|
if (text2 !== null) found.push({ path: relative3(root, absolute), text: text2 });
|
|
45609
46358
|
}
|
|
@@ -45633,9 +46382,9 @@ function usesAppNetwork(source) {
|
|
|
45633
46382
|
function auditUx(content, strict = false) {
|
|
45634
46383
|
const dir = resolve15(content);
|
|
45635
46384
|
const issues = [];
|
|
45636
|
-
const evidencePath =
|
|
45637
|
-
const spec = readText(
|
|
45638
|
-
const mobile = readText(
|
|
46385
|
+
const evidencePath = join25(dir, EVIDENCE_RELATIVE_PATH);
|
|
46386
|
+
const spec = readText(join25(dir, "SPEC.md"));
|
|
46387
|
+
const mobile = readText(join25(dir, "MOBILE-UX.md"));
|
|
45639
46388
|
if (!spec) issue(issues, strict, "missing-spec", "SPEC.md is missing; define the customer task before calling this UX-ready.", "SPEC.md");
|
|
45640
46389
|
if (!mobile) {
|
|
45641
46390
|
issue(issues, strict, "missing-mobile-ux", "MOBILE-UX.md is missing; add the mobile state and platform contract.", "MOBILE-UX.md");
|
|
@@ -45674,7 +46423,7 @@ function auditUx(content, strict = false) {
|
|
|
45674
46423
|
const preview = matches(previewControl);
|
|
45675
46424
|
if (preview) issue(issues, strict, "possible-preview-control", "Possible customer-visible test/demo state control found. Keep scenario controls out of shipping UI, or document a capability-limited fallback.", preview.path);
|
|
45676
46425
|
if (usesAppNetwork(source)) {
|
|
45677
|
-
const mocksPath =
|
|
46426
|
+
const mocksPath = join25(dir, "dev", "net-mocks.json");
|
|
45678
46427
|
if (!existsSync21(mocksPath)) {
|
|
45679
46428
|
issue(issues, strict, "missing-app-mocks", "This package uses a Wix/network client but has no app-specific dev/net-mocks.json. Add fixtures for dynamic, entitlement, or recovery flows.", "dev/net-mocks.json");
|
|
45680
46429
|
} else {
|
|
@@ -45696,12 +46445,12 @@ function recordNativeAudit(content, platform, status, checks, reason) {
|
|
|
45696
46445
|
if (!normalizedChecks.length) throw new Error("--checks needs at least one comma-separated check (for example: back,keyboard,voiceover)");
|
|
45697
46446
|
if (status === "unavailable" && !reason?.trim()) throw new Error("--reason is required when --status unavailable");
|
|
45698
46447
|
const dir = resolve15(content);
|
|
45699
|
-
const path =
|
|
46448
|
+
const path = join25(dir, EVIDENCE_RELATIVE_PATH);
|
|
45700
46449
|
const parsed = parseEvidence(path);
|
|
45701
46450
|
if (parsed.error) throw new Error(`${EVIDENCE_RELATIVE_PATH} ${parsed.error}`);
|
|
45702
46451
|
const evidence = parsed.evidence ?? { version: 1, platforms: {} };
|
|
45703
46452
|
evidence.platforms[platform] = { status, checks: normalizedChecks, ...reason?.trim() ? { reason: reason.trim() } : {}, recordedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
45704
|
-
mkdirSync10(
|
|
46453
|
+
mkdirSync10(join25(dir, ".himi"), { recursive: true });
|
|
45705
46454
|
writeFileSync9(path, JSON.stringify(evidence, null, 2) + "\n");
|
|
45706
46455
|
return evidence;
|
|
45707
46456
|
}
|
|
@@ -45710,26 +46459,26 @@ function recordNativeAudit(content, platform, status, checks, reason) {
|
|
|
45710
46459
|
init_mobile_ux_contract();
|
|
45711
46460
|
import { readFileSync as readFileSync24, existsSync as existsSync22, mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, copyFileSync as copyFileSync2 } from "node:fs";
|
|
45712
46461
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
45713
|
-
import { dirname as dirname15, join as
|
|
46462
|
+
import { dirname as dirname15, join as join26, resolve as resolve16 } from "node:path";
|
|
45714
46463
|
var GUIDES_DIR = resolve16(dirname15(fileURLToPath10(import.meta.url)), "../guides");
|
|
45715
46464
|
function guidesAvailable() {
|
|
45716
|
-
return existsSync22(
|
|
46465
|
+
return existsSync22(join26(GUIDES_DIR, "index.json"));
|
|
45717
46466
|
}
|
|
45718
46467
|
function loadIndex() {
|
|
45719
|
-
return JSON.parse(readFileSync24(
|
|
46468
|
+
return JSON.parse(readFileSync24(join26(GUIDES_DIR, "index.json"), "utf8"));
|
|
45720
46469
|
}
|
|
45721
46470
|
function readGuide(id) {
|
|
45722
46471
|
const meta = loadIndex().guides.find((g) => g.id === id);
|
|
45723
46472
|
if (!meta) return null;
|
|
45724
|
-
return readFileSync24(
|
|
46473
|
+
return readFileSync24(join26(GUIDES_DIR, meta.file), "utf8");
|
|
45725
46474
|
}
|
|
45726
46475
|
function loadComponentReference() {
|
|
45727
46476
|
const idx = loadIndex();
|
|
45728
|
-
return JSON.parse(readFileSync24(
|
|
46477
|
+
return JSON.parse(readFileSync24(join26(GUIDES_DIR, idx.componentReferenceFile), "utf8"));
|
|
45729
46478
|
}
|
|
45730
46479
|
function loadSdkReference() {
|
|
45731
46480
|
const idx = loadIndex();
|
|
45732
|
-
return JSON.parse(readFileSync24(
|
|
46481
|
+
return JSON.parse(readFileSync24(join26(GUIDES_DIR, idx.sdkReferenceFile), "utf8"));
|
|
45733
46482
|
}
|
|
45734
46483
|
function buildAgentPrimer() {
|
|
45735
46484
|
const idx = loadIndex();
|
|
@@ -45837,19 +46586,19 @@ function writeAgentContext(targetDir) {
|
|
|
45837
46586
|
const idx = loadIndex();
|
|
45838
46587
|
const files = [];
|
|
45839
46588
|
const write2 = (rel, body) => {
|
|
45840
|
-
const p =
|
|
46589
|
+
const p = join26(targetDir, rel);
|
|
45841
46590
|
mkdirSync11(dirname15(p), { recursive: true });
|
|
45842
46591
|
writeFileSync10(p, body);
|
|
45843
46592
|
files.push(rel);
|
|
45844
46593
|
};
|
|
45845
46594
|
const copy = (srcRel, destRel) => {
|
|
45846
|
-
const p =
|
|
46595
|
+
const p = join26(targetDir, destRel);
|
|
45847
46596
|
mkdirSync11(dirname15(p), { recursive: true });
|
|
45848
|
-
copyFileSync2(
|
|
46597
|
+
copyFileSync2(join26(GUIDES_DIR, srcRel), p);
|
|
45849
46598
|
files.push(destRel);
|
|
45850
46599
|
};
|
|
45851
46600
|
const writeIfMissing = (rel, body) => {
|
|
45852
|
-
if (existsSync22(
|
|
46601
|
+
if (existsSync22(join26(targetDir, rel))) return;
|
|
45853
46602
|
write2(rel, body);
|
|
45854
46603
|
};
|
|
45855
46604
|
write2("HIMALAYA.md", buildAgentPrimer());
|
|
@@ -45877,7 +46626,7 @@ function writeAgentContext(targetDir) {
|
|
|
45877
46626
|
// src/cli.ts
|
|
45878
46627
|
init_wix_placeholders();
|
|
45879
46628
|
var defaultIO = { log: (l) => console.log(l), error: (l) => console.error(l), isTTY: process.stdout.isTTY === true };
|
|
45880
|
-
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["browser", "no-open", "yes", "json", "deep", "quiet", "force", "watch", "no-claim", "new"]);
|
|
46629
|
+
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["browser", "no-open", "yes", "json", "deep", "quiet", "force", "replace", "watch", "no-claim", "new"]);
|
|
45881
46630
|
var SHELL_ENUM = SHELL_NAMES2.join("|");
|
|
45882
46631
|
function parseFlags(argv) {
|
|
45883
46632
|
const _ = [];
|
|
@@ -45910,7 +46659,7 @@ var str5 = (v) => typeof v === "string" ? v : void 0;
|
|
|
45910
46659
|
var num = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
45911
46660
|
function embeddedTemplateCatalog() {
|
|
45912
46661
|
return availableTemplates().map((name) => {
|
|
45913
|
-
const path =
|
|
46662
|
+
const path = join49(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
45914
46663
|
const meta = JSON.parse(readFileSync63(path, "utf8"));
|
|
45915
46664
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
45916
46665
|
throw new Error(`${path} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
@@ -46066,7 +46815,7 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
46066
46815
|
Never archives .himi/, .env*, node_modules/, dist/ or key
|
|
46067
46816
|
material, and REFUSES the push if a file it would archive
|
|
46068
46817
|
looks like it holds a credential.
|
|
46069
|
-
himi pull <app> [--release <id>] [--out <dir>] [--name <new>] [--force] [--target <t>]
|
|
46818
|
+
himi pull <app> [--release <id>] [--out <dir>] [--name <new>] [--force|--replace] [--target <t>]
|
|
46070
46819
|
restore an app's SOURCE from the serve plane into an editable
|
|
46071
46820
|
content package \u2014 the other half of push, which archives it.
|
|
46072
46821
|
Owner or editor only: a viewer may download the running app,
|
|
@@ -46074,6 +46823,14 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
46074
46823
|
retention window prune() keeps (current + newest ~20).
|
|
46075
46824
|
--name re-substitutes the app identity, so the restored tree is
|
|
46076
46825
|
a NEW app rather than a second copy of the same one.
|
|
46826
|
+
A non-empty destination is refused unless you say which you mean:
|
|
46827
|
+
--force MERGES \u2014 it keeps files the release does not have and
|
|
46828
|
+
NAMES them (left: [...]), so a hybrid tree is never silent.
|
|
46829
|
+
--replace restores exactly what was archived: it removes those
|
|
46830
|
+
files first (removed: [...]) and implies --force. It refuses
|
|
46831
|
+
a directory with no himalaya.content.json, and can only remove
|
|
46832
|
+
what a push would have archived \u2014 .git/, node_modules/, dist/,
|
|
46833
|
+
.env* and key material are never touched.
|
|
46077
46834
|
himi pack [--content <dir>] [--out <file|dir>] [--format zip|dir] [--name <title>] [--snapshot]
|
|
46078
46835
|
write the app as a PORTABLE .himi package \u2014 one self-contained
|
|
46079
46836
|
file (screens, T5 bundles, tokens, assets, app-config) you can
|
|
@@ -46321,7 +47078,7 @@ var COMMANDS = [
|
|
|
46321
47078
|
{ name: "doctor", summary: 'off-VPN preflight in one shot: probe the PUBLIC data plane (www.wixapis.com \u2014 reachable off-VPN), the INTERNAL serve/control plane for the selected target (VPN-gated), and report auth state (dpx session on disk + stored control token). --dpx additionally runs a live, EADDRINUSE-safe `dpx whoami`. Machine-readable with --json (an unreachable internal plane carries a stable code:"needs_vpn" so an agent branches on the code, not the prose); human-readable otherwise. Never loads the authoring runtime \u2014 works off-repo.', required: "[--target <t>] [--dpx] [--json] [--data-url <url>] [--timeout <ms>]" },
|
|
46322
47079
|
{ name: "push", summary: "lint + build + publish a release (default --draft: servable via ?release= but NOT live). REFUSES to publish on any error unless --force; --strict promotes warnings. Prints preview + agent-context links. The published slug is NAMESPACED per owner \u2014 `<ownerPrefix>.<name>`, composed offline from the control token's ownerPrefix claim, so the CLI and the server derive the identical string and himalaya.content.json is NOT rewritten (a legacy token with no ownerPrefix publishes the declared name unchanged). An app claimed BEFORE namespacing is stored under its FLAT slug, so the claim route answers `alreadyYours` naming that slug and the push adopts it \u2014 reported as `adoptedSlug`, since it is the one case where the published `app` differs from what the declared name composes to. `--no-claim` skips the route that knows this, so a pre-namespacing app pushed with it still fails 403. --visibility public|unlisted decides whether /v1/apps + the Himi Player picker LIST the app (also declarable as `visibility` in himalaya.content.json; omitted, a brand-new app defaults to unlisted \u2014 share by link \u2014 and an existing setting is kept). --account-id names which account owns the app when your Wix session resolves to several (the auto-claim of a brand-new slug cannot guess \u2014 without it a multi-account caller is told to name one).", required: "[--content <dir>] [--draft] [--force] [--strict] [--label] [--notes] [--visibility public|unlisted] [--no-claim] [--account-id <id>] (--control-token)" },
|
|
46323
47080
|
{ name: "pack", summary: "write the app as a PORTABLE .himi package \u2014 one self-contained file holding every screen, Tier-5 bundle, token, asset and the app-config. Packages are live by default: they boot bundled content offline, then Himi Player follows its baked-in production ring. `--snapshot` makes a frozen reproducible artifact. Package-supplied origins are never trusted. --format dir writes the same tree unpacked, for static hosting. --release-dir packs a release that is already built on disk (needs --app) instead of rebuilding from source.", required: "[--content <dir>] [--out <file|dir>] [--format zip|dir] [--name <title>] [--snapshot] [--strict] [--force] | --release-dir <dir> --app <a>" },
|
|
46324
|
-
{ name: "pull", summary: "restore an app's SOURCE from the serve plane into an editable content package \u2014 the other half of `himi push`, which archives the content package on every publish. Owner or editor only: a viewer may download the RUNNING app (`/v1/owner/package`), not the codebase it was built from. A PAST release is restorable, not only the live one \u2014 the archive is content-addressed per release, so it has none of the live-single-slot problem that makes `himi pack` current-release-only. Two limits: pruning keeps the current release plus the newest ~20 ledger entries, and a release id identifies OTA content rather than source, so a source-only change republishes under the same id and replaces that id's archive. A release published before source archiving shipped, or pushed with `--no-source`, answers `app_source_not_found` and says to push again. `--name` re-substitutes the app identity through the same machinery `himi init --template` uses, so the restored tree is a NEW app rather than a second copy of the same one, and a name that also appears inside a screen id (`feed` in `feed_home`) is left alone.", required: "<app> [--release <id>] [--out <dir>] [--name <new>] [--force] [--target <t>]" },
|
|
47081
|
+
{ name: "pull", summary: "restore an app's SOURCE from the serve plane into an editable content package \u2014 the other half of `himi push`, which archives the content package on every publish. Owner or editor only: a viewer may download the RUNNING app (`/v1/owner/package`), not the codebase it was built from. A PAST release is restorable, not only the live one \u2014 the archive is content-addressed per release, so it has none of the live-single-slot problem that makes `himi pack` current-release-only. Two limits: pruning keeps the current release plus the newest ~20 ledger entries, and a release id identifies OTA content rather than source, so a source-only change republishes under the same id and replaces that id's archive. A release published before source archiving shipped, or pushed with `--no-source`, answers `app_source_not_found` and says to push again. `--name` re-substitutes the app identity through the same machinery `himi init --template` uses, so the restored tree is a NEW app rather than a second copy of the same one, and a name that also appears inside a screen id (`feed` in `feed_home`) is left alone. A NON-EMPTY destination is refused unless you say which you mean: `--force` merges and reports \u2014 it writes the archive over what is there, keeps files the release does not carry, and NAMES every one of them as `left: [...]` so a tree that matches no release is never silent (#2437); `--replace` restores exactly what was archived, removing those files first (`removed: [...]`) and implying `--force`. `--replace` refuses a directory holding no `himalaya.content.json`, so a mistyped `--out` cannot clear an unrelated tree, and the only paths it can remove are the ones a push would have archived \u2014 `.git/`, `node_modules/`, `dist/`, `.env*` and key material are out of its reach by construction.", required: "<app> [--release <id>] [--out <dir>] [--name <new>] [--force|--replace] [--target <t>]" },
|
|
46325
47082
|
{ name: "share", summary: "publish or revoke a content-addressed `.himi` share link. The package must be a validated archive for an already-published release; the resulting https URL is safe to QR, copy, or open in Himi Player.", required: "--file <package.himi> [--expires-at <ISO>] | revoke --app <app> <shareId>" },
|
|
46326
47083
|
{ name: "run", summary: "serve a .himi package on localhost and open it in a browser \u2014 no serve plane, no dev-server, no setup. Given no argument it builds the current content package first, so `himi run` is the inner loop: edit, run, look at it. The SPA and /v1 are served from ONE origin because Tier-5 bundle fetches on web are same-origin-only. --chrome preview frames the app in a device chassis; --chrome app serves it as a plain web app. Blocks until Ctrl-C, like any dev server. --browser runs the whole plane INSIDE the tab (service worker + in-memory store) so no app code executes in this process or on any pod.", required: "[<package.himi|dir|url>] [--browser] [--content <dir>] [--port <n>] [--chrome preview|app] [--screen <id>] [--surface <id>] [--no-open] [--spa <url>]" },
|
|
46327
47084
|
{ name: "preview", summary: "print the shareable web URL + himi:// deep link + agent /v1/preview JSON URLs for an app+release; --surface frames the web preview as any catalog surface (?surface=)", required: "--app --release [--screen] [--surface]" },
|
|
@@ -46375,11 +47132,11 @@ function packageVersion(path) {
|
|
|
46375
47132
|
}
|
|
46376
47133
|
}
|
|
46377
47134
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
46378
|
-
let dir =
|
|
47135
|
+
let dir = resolve40(fromDir);
|
|
46379
47136
|
for (; ; ) {
|
|
46380
|
-
const version = packageVersion(
|
|
47137
|
+
const version = packageVersion(join49(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
46381
47138
|
if (version) return { version, source: "local" };
|
|
46382
|
-
const parent =
|
|
47139
|
+
const parent = dirname28(dir);
|
|
46383
47140
|
if (parent === dir) break;
|
|
46384
47141
|
dir = parent;
|
|
46385
47142
|
}
|
|
@@ -46387,7 +47144,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
46387
47144
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
46388
47145
|
try {
|
|
46389
47146
|
const root = execFileSync6("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
46390
|
-
const version = root ? packageVersion(
|
|
47147
|
+
const version = root ? packageVersion(join49(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
46391
47148
|
return version ? { version, source: "global" } : {};
|
|
46392
47149
|
} catch {
|
|
46393
47150
|
return {};
|
|
@@ -46748,7 +47505,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
46748
47505
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
46749
47506
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
46750
47507
|
const iosYmlPath = iosProjectYml2(app);
|
|
46751
|
-
const iosYml =
|
|
47508
|
+
const iosYml = existsSync51(iosYmlPath) ? readFileSync63(iosYmlPath, "utf8") : "";
|
|
46752
47509
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
46753
47510
|
if (!optedIn) {
|
|
46754
47511
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -46762,19 +47519,19 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
46762
47519
|
}
|
|
46763
47520
|
function readConfigSource(dir) {
|
|
46764
47521
|
try {
|
|
46765
|
-
return readFileSync63(
|
|
47522
|
+
return readFileSync63(join49(dir, "config.ts"), "utf8");
|
|
46766
47523
|
} catch {
|
|
46767
47524
|
return null;
|
|
46768
47525
|
}
|
|
46769
47526
|
}
|
|
46770
47527
|
function writePngFile(path, base64) {
|
|
46771
|
-
mkdirSync25(
|
|
47528
|
+
mkdirSync25(dirname28(path), { recursive: true });
|
|
46772
47529
|
writeFileSync23(path, Buffer.from(base64, "base64"));
|
|
46773
47530
|
return path;
|
|
46774
47531
|
}
|
|
46775
47532
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
46776
|
-
const dir =
|
|
46777
|
-
if (
|
|
47533
|
+
const dir = resolve40(parentDir, name);
|
|
47534
|
+
if (existsSync51(join49(dir, "himalaya.content.json"))) {
|
|
46778
47535
|
throw new Error(`content package already exists at ${dir}`);
|
|
46779
47536
|
}
|
|
46780
47537
|
const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -46786,13 +47543,13 @@ async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
|
46786
47543
|
return finishScaffold(materializeSource(archive.files, name, dir), template);
|
|
46787
47544
|
}
|
|
46788
47545
|
function contentDir(flags) {
|
|
46789
|
-
return
|
|
47546
|
+
return resolve40(str5(flags.content) ?? process.cwd());
|
|
46790
47547
|
}
|
|
46791
47548
|
function isHimalayaMonorepoCheckout(start) {
|
|
46792
|
-
let dir =
|
|
47549
|
+
let dir = resolve40(start);
|
|
46793
47550
|
for (; ; ) {
|
|
46794
|
-
if (
|
|
46795
|
-
const parent =
|
|
47551
|
+
if (existsSync51(join49(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync51(join49(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
47552
|
+
const parent = dirname28(dir);
|
|
46796
47553
|
if (parent === dir) return false;
|
|
46797
47554
|
dir = parent;
|
|
46798
47555
|
}
|
|
@@ -46821,9 +47578,9 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
46821
47578
|
const forBuild = Object.fromEntries(
|
|
46822
47579
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
46823
47580
|
);
|
|
46824
|
-
const repoRoot2 =
|
|
46825
|
-
const dest =
|
|
46826
|
-
|
|
47581
|
+
const repoRoot2 = resolve40(fileURLToPath21(new URL("../../..", import.meta.url)));
|
|
47582
|
+
const dest = join49(repoRoot2, "node_modules", ".cache", "himi-template-preview", slug);
|
|
47583
|
+
rmSync9(dest, { recursive: true, force: true });
|
|
46827
47584
|
mkdirSync25(dest, { recursive: true });
|
|
46828
47585
|
materializeSource(forBuild, displayName, dest, slug);
|
|
46829
47586
|
return dest;
|
|
@@ -46831,7 +47588,7 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
46831
47588
|
async function appId(dir) {
|
|
46832
47589
|
try {
|
|
46833
47590
|
const { readFileSync: readFileSync64 } = await import("node:fs");
|
|
46834
|
-
const m = JSON.parse(readFileSync64(
|
|
47591
|
+
const m = JSON.parse(readFileSync64(join49(dir, "himalaya.content.json"), "utf8"));
|
|
46835
47592
|
if (m.name) return m.name;
|
|
46836
47593
|
} catch {
|
|
46837
47594
|
}
|
|
@@ -46840,7 +47597,7 @@ async function appId(dir) {
|
|
|
46840
47597
|
async function contentVisibility(dir) {
|
|
46841
47598
|
try {
|
|
46842
47599
|
const { readFileSync: readFileSync64 } = await import("node:fs");
|
|
46843
|
-
const m = JSON.parse(readFileSync64(
|
|
47600
|
+
const m = JSON.parse(readFileSync64(join49(dir, "himalaya.content.json"), "utf8"));
|
|
46844
47601
|
if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
|
|
46845
47602
|
} catch {
|
|
46846
47603
|
}
|
|
@@ -47041,7 +47798,7 @@ Seed your coding agent with \`himi agent-init\`. Portal: ${idx.portalUrl}`);
|
|
|
47041
47798
|
return 0;
|
|
47042
47799
|
}
|
|
47043
47800
|
case "agent-init": {
|
|
47044
|
-
const dir =
|
|
47801
|
+
const dir = resolve40(str5(flags.dir) ?? process.cwd());
|
|
47045
47802
|
const res = writeAgentContext(dir);
|
|
47046
47803
|
print({ ok: true, dir: res.dir, files: res.files, portalUrl: idx.portalUrl });
|
|
47047
47804
|
return 0;
|
|
@@ -47079,6 +47836,7 @@ async function loadAuthoring() {
|
|
|
47079
47836
|
crawlScreen: crawl.crawlScreen,
|
|
47080
47837
|
crawlScreenJourney: crawl.crawlScreenJourney,
|
|
47081
47838
|
crawlScreenHostile: crawl.crawlScreenHostile,
|
|
47839
|
+
crawlScreenRelations: crawl.crawlScreenRelations,
|
|
47082
47840
|
findingKey: crawl.findingKey,
|
|
47083
47841
|
startWorkerCoverage: cov.startWorkerCoverage,
|
|
47084
47842
|
uncoveredFunctions: cov.uncoveredFunctions,
|
|
@@ -47146,7 +47904,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47146
47904
|
return 2;
|
|
47147
47905
|
}
|
|
47148
47906
|
const template = str5(flags.template);
|
|
47149
|
-
const parentDir =
|
|
47907
|
+
const parentDir = resolve40(str5(flags.dir) ?? process.cwd());
|
|
47150
47908
|
if (template && flags.remote === true) {
|
|
47151
47909
|
try {
|
|
47152
47910
|
const res2 = await initFromRemoteTemplate(name, parentDir, template, client3());
|
|
@@ -47237,11 +47995,11 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47237
47995
|
return 0;
|
|
47238
47996
|
}
|
|
47239
47997
|
if (sub === "publish") {
|
|
47240
|
-
const appDir2 =
|
|
47241
|
-
const sourceDir =
|
|
47998
|
+
const appDir2 = resolve40(str5(flags.dir) ?? process.cwd());
|
|
47999
|
+
const sourceDir = resolve40(str5(flags["source-dir"]) ?? appDir2);
|
|
47242
48000
|
let meta;
|
|
47243
48001
|
try {
|
|
47244
|
-
meta = JSON.parse(readFileSync63(
|
|
48002
|
+
meta = JSON.parse(readFileSync63(join49(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
47245
48003
|
} catch {
|
|
47246
48004
|
io.error(JSON.stringify({ error: `no ${TEMPLATE_META_FILE} in ${sourceDir} \u2014 a template must declare { title, description, tags } to be published`, hint: `add ${TEMPLATE_META_FILE} next to himalaya.content.json (or pass --source-dir <dir>)` }));
|
|
47247
48005
|
return 2;
|
|
@@ -47251,7 +48009,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47251
48009
|
return 2;
|
|
47252
48010
|
}
|
|
47253
48011
|
try {
|
|
47254
|
-
const appearance = extractTemplateAppearance(JSON.parse(readFileSync63(
|
|
48012
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync63(join49(sourceDir, "tokens.json"), "utf8")));
|
|
47255
48013
|
meta = { ...appearance, ...meta };
|
|
47256
48014
|
} catch {
|
|
47257
48015
|
}
|
|
@@ -47263,7 +48021,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47263
48021
|
const force = flags.force === true;
|
|
47264
48022
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
47265
48023
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
47266
|
-
const out = mkdtempSync4(
|
|
48024
|
+
const out = mkdtempSync4(join49(tmpdir5(), "himi-template-"));
|
|
47267
48025
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
47268
48026
|
const outcome = await buildReleaseFromContent2(buildDir, out, {
|
|
47269
48027
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
@@ -47292,7 +48050,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47292
48050
|
}));
|
|
47293
48051
|
return 1;
|
|
47294
48052
|
}
|
|
47295
|
-
const iconPath = str5(flags.icon) ?
|
|
48053
|
+
const iconPath = str5(flags.icon) ? resolve40(str5(flags.icon)) : templateIconPath(name);
|
|
47296
48054
|
let iconHash;
|
|
47297
48055
|
if (iconPath) {
|
|
47298
48056
|
try {
|
|
@@ -47422,7 +48180,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47422
48180
|
const { mobileUxIssues: mobileUxIssues2 } = await Promise.resolve().then(() => (init_mobile_ux_lint(), mobile_ux_lint_exports));
|
|
47423
48181
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
47424
48182
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
47425
|
-
const out = mkdtempSync4(
|
|
48183
|
+
const out = mkdtempSync4(join49(tmpdir5(), "himi-validate-"));
|
|
47426
48184
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
47427
48185
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
47428
48186
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -47610,7 +48368,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47610
48368
|
case "test": {
|
|
47611
48369
|
const dir = contentDir(flags);
|
|
47612
48370
|
const structuredOutput = flags.json === true || io.isTTY !== true;
|
|
47613
|
-
if (
|
|
48371
|
+
if (existsSync51(join49(dir, "functions"))) {
|
|
47614
48372
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
47615
48373
|
const loaded = await loadFunctionsApp2(dir);
|
|
47616
48374
|
const results = [];
|
|
@@ -47624,7 +48382,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47624
48382
|
return results.every((result2) => result2.ok) ? 0 : 1;
|
|
47625
48383
|
}
|
|
47626
48384
|
const app = await appId(dir);
|
|
47627
|
-
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2, crawlScreen: crawlScreen2, crawlScreenJourney: crawlScreenJourney2, crawlScreenHostile: crawlScreenHostile2, findingKey: findingKey2, startWorkerCoverage: startWorkerCoverage2, uncoveredFunctions: uncoveredFunctions2, crawlScreenDeep: crawlScreenDeep2, crawlSignature: crawlSignature2, recordScreenTraffic: recordScreenTraffic2, mintVisitor: mintVisitor2, webWixCall: webWixCall2, freezeTrafficToMocks: freezeTrafficToMocks2, bootAndSnapshotState: bootAndSnapshotState2, renderDescriptorWeb: renderDescriptorWeb2, renderPngBatch: renderPngBatch2, pngAvailable: pngAvailable2, crawlBlockingPasses } = await loadAuthoring();
|
|
48385
|
+
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2, crawlScreen: crawlScreen2, crawlScreenJourney: crawlScreenJourney2, crawlScreenHostile: crawlScreenHostile2, crawlScreenRelations: crawlScreenRelations2, findingKey: findingKey2, startWorkerCoverage: startWorkerCoverage2, uncoveredFunctions: uncoveredFunctions2, crawlScreenDeep: crawlScreenDeep2, crawlSignature: crawlSignature2, recordScreenTraffic: recordScreenTraffic2, mintVisitor: mintVisitor2, webWixCall: webWixCall2, freezeTrafficToMocks: freezeTrafficToMocks2, bootAndSnapshotState: bootAndSnapshotState2, renderDescriptorWeb: renderDescriptorWeb2, renderPngBatch: renderPngBatch2, pngAvailable: pngAvailable2, crawlBlockingPasses } = await loadAuthoring();
|
|
47628
48386
|
const { readTestConfig: readTestConfig2, runCrawl: runCrawl2, formatReport: formatReport2, readCannedResponses: readCannedResponses2, makeRecordingWixCall: makeRecordingWixCall2, runRecordPass: runRecordPass2, runShotsPass: runShotsPass2, defaultNetRules: defaultNetRules2, readNetRules: readNetRules2, scopeDescriptors: scopeDescriptors2, writeRecordedMocks: writeRecordedMocks2 } = await Promise.resolve().then(() => (init_test(), test_exports));
|
|
47629
48387
|
let config;
|
|
47630
48388
|
try {
|
|
@@ -47697,7 +48455,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47697
48455
|
}
|
|
47698
48456
|
}
|
|
47699
48457
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
47700
|
-
const out = mkdtempSync4(
|
|
48458
|
+
const out = mkdtempSync4(join49(tmpdir5(), "himi-test-"));
|
|
47701
48459
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
47702
48460
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
47703
48461
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -47742,7 +48500,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47742
48500
|
io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
47743
48501
|
return 2;
|
|
47744
48502
|
}
|
|
47745
|
-
const sources = collectWorkerSources2(
|
|
48503
|
+
const sources = collectWorkerSources2(join49(dir, "tier5-src"), screen.bundleName);
|
|
47746
48504
|
if (!sources) {
|
|
47747
48505
|
io.error(JSON.stringify({ error: `no worker source found at tier5-src/${screen.bundleName} \u2014 the browser loop compiles SOURCE, not the built bundle` }));
|
|
47748
48506
|
return 2;
|
|
@@ -47862,7 +48620,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47862
48620
|
...deep ? { deep } : {},
|
|
47863
48621
|
...offline ? { offline: true } : {},
|
|
47864
48622
|
...offline || flags["no-hostile"] === true ? { hostile: false } : {},
|
|
47865
|
-
deps: { crawlScreen: crawlScreen2, crawlScreenJourney: crawlScreenJourney2, crawlScreenHostile: crawlScreenHostile2, findingKey: findingKey2, startWorkerCoverage: startWorkerCoverage2, uncoveredFunctions: uncoveredFunctions2, crawlScreenDeep: crawlScreenDeep2, crawlSignature: crawlSignature2 }
|
|
48623
|
+
deps: { crawlScreen: crawlScreen2, crawlScreenJourney: crawlScreenJourney2, crawlScreenHostile: crawlScreenHostile2, crawlScreenRelations: crawlScreenRelations2, findingKey: findingKey2, startWorkerCoverage: startWorkerCoverage2, uncoveredFunctions: uncoveredFunctions2, crawlScreenDeep: crawlScreenDeep2, crawlSignature: crawlSignature2 }
|
|
47866
48624
|
});
|
|
47867
48625
|
} catch (e) {
|
|
47868
48626
|
io.error(JSON.stringify({ error: e.message }));
|
|
@@ -47899,7 +48657,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47899
48657
|
const sp = await runShotsPass2({
|
|
47900
48658
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
47901
48659
|
tokens: outcome.tokens,
|
|
47902
|
-
outDir:
|
|
48660
|
+
outDir: join49(dir, ".himi", "shots"),
|
|
47903
48661
|
width: 390,
|
|
47904
48662
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
47905
48663
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -47909,7 +48667,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47909
48667
|
renderDescriptorWeb: renderDescriptorWeb2,
|
|
47910
48668
|
renderPngBatch: renderPngBatch2,
|
|
47911
48669
|
writePng: (path, base64) => writePngFile(path, base64),
|
|
47912
|
-
clearDir: (d) =>
|
|
48670
|
+
clearDir: (d) => rmSync9(d, { recursive: true, force: true })
|
|
47913
48671
|
}
|
|
47914
48672
|
});
|
|
47915
48673
|
writtenShots = sp.written;
|
|
@@ -47935,7 +48693,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47935
48693
|
releaseId: result.releaseId,
|
|
47936
48694
|
releasePayload: release,
|
|
47937
48695
|
descriptors: attestedDescriptors,
|
|
47938
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
48696
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join49(dir, ".himi", "shots", name)])),
|
|
47939
48697
|
coverage: {
|
|
47940
48698
|
screens: crawledScreens.size,
|
|
47941
48699
|
actionsDispatched: result.actions.exercised,
|
|
@@ -48077,7 +48835,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
48077
48835
|
}
|
|
48078
48836
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
48079
48837
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
48080
|
-
const out = mkdtempSync4(
|
|
48838
|
+
const out = mkdtempSync4(join49(tmpdir5(), "himi-render-"));
|
|
48081
48839
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
48082
48840
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
48083
48841
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -48093,7 +48851,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
48093
48851
|
let attestationPngFile;
|
|
48094
48852
|
if (typeof flags.png === "string" && r.pngBase64) {
|
|
48095
48853
|
pngFile = writePngFile(str5(flags.png), r.pngBase64);
|
|
48096
|
-
attestationPngFile = writePngFile(
|
|
48854
|
+
attestationPngFile = writePngFile(join49(dir, ".himi", "shots", `${screenId}.png`), r.pngBase64);
|
|
48097
48855
|
}
|
|
48098
48856
|
const legacyRender = {
|
|
48099
48857
|
ok: r.renderable,
|
|
@@ -48398,17 +49156,27 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48398
49156
|
return 2;
|
|
48399
49157
|
}
|
|
48400
49158
|
const renamed = str5(flags.name);
|
|
48401
|
-
const dest =
|
|
48402
|
-
|
|
48403
|
-
|
|
49159
|
+
const dest = resolve40(str5(flags.out) ?? process.cwd(), renamed ?? wanted);
|
|
49160
|
+
const replace = flags.replace === true;
|
|
49161
|
+
const force = replace || flags.force === true;
|
|
49162
|
+
if (existsSync51(dest)) {
|
|
49163
|
+
if (!statSync13(dest).isDirectory()) {
|
|
48404
49164
|
io.error(JSON.stringify({
|
|
48405
49165
|
error: `${dest} exists and is not a directory`,
|
|
48406
49166
|
hint: "pass --out/--name to land somewhere else, or remove the file"
|
|
48407
49167
|
}));
|
|
48408
49168
|
return 1;
|
|
48409
49169
|
}
|
|
48410
|
-
|
|
48411
|
-
|
|
49170
|
+
const occupied = readdirSync23(dest).length > 0;
|
|
49171
|
+
if (occupied && !force) {
|
|
49172
|
+
io.error(JSON.stringify({ error: `${dest} already exists and is not empty`, hint: "pass --force to write into it anyway (merging, and naming what it keeps), --replace to restore exactly what was archived, or --out/--name to land somewhere else" }));
|
|
49173
|
+
return 1;
|
|
49174
|
+
}
|
|
49175
|
+
if (replace && occupied && !existsSync51(join49(dest, "himalaya.content.json"))) {
|
|
49176
|
+
io.error(JSON.stringify({
|
|
49177
|
+
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
49178
|
+
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
49179
|
+
}));
|
|
48412
49180
|
return 1;
|
|
48413
49181
|
}
|
|
48414
49182
|
}
|
|
@@ -48417,7 +49185,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48417
49185
|
io.error(JSON.stringify({ ok: false, app: wanted, status: pulled.status, ...pulled.json ?? {} }));
|
|
48418
49186
|
return 1;
|
|
48419
49187
|
}
|
|
48420
|
-
const { readAppSource: readAppSource2, writeAppSource: writeAppSource2 } = await Promise.resolve().then(() => (init_app_source(), app_source_exports));
|
|
49188
|
+
const { readAppSource: readAppSource2, writeAppSource: writeAppSource2, staleSourcePaths: staleSourcePaths2, removeStaleSource: removeStaleSource2, deniedArchivePaths: deniedArchivePaths2, writeConflicts: writeConflicts2 } = await Promise.resolve().then(() => (init_app_source(), app_source_exports));
|
|
48421
49189
|
let restored;
|
|
48422
49190
|
try {
|
|
48423
49191
|
restored = readAppSource2(pulled.bytes);
|
|
@@ -48444,6 +49212,31 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48444
49212
|
if (body !== void 0) entry.bytes = Buffer.from(substituteIdentity(body, renamed), "utf8");
|
|
48445
49213
|
}
|
|
48446
49214
|
}
|
|
49215
|
+
if (restored.length === 0) {
|
|
49216
|
+
io.error(JSON.stringify({
|
|
49217
|
+
ok: false,
|
|
49218
|
+
app: wanted,
|
|
49219
|
+
error: "app_source_empty",
|
|
49220
|
+
hint: "the plane returned an archive with no entries \u2014 nothing was changed. Re-push the app, then pull again"
|
|
49221
|
+
}));
|
|
49222
|
+
return 1;
|
|
49223
|
+
}
|
|
49224
|
+
const conflicts = writeConflicts2(restored, dest);
|
|
49225
|
+
if (conflicts.length) {
|
|
49226
|
+
io.error(JSON.stringify({
|
|
49227
|
+
ok: false,
|
|
49228
|
+
app: wanted,
|
|
49229
|
+
error: "destination_shape_conflicts",
|
|
49230
|
+
conflicts,
|
|
49231
|
+
hint: "nothing was changed \u2014 remove or rename those paths, or pass --out/--name to land somewhere else"
|
|
49232
|
+
}));
|
|
49233
|
+
return 1;
|
|
49234
|
+
}
|
|
49235
|
+
let left = [];
|
|
49236
|
+
let removed = [];
|
|
49237
|
+
if (replace) removed = removeStaleSource2(restored, dest);
|
|
49238
|
+
else left = staleSourcePaths2(restored, dest);
|
|
49239
|
+
const refused = deniedArchivePaths2(restored);
|
|
48447
49240
|
const written = writeAppSource2(restored, dest);
|
|
48448
49241
|
print({
|
|
48449
49242
|
ok: true,
|
|
@@ -48451,6 +49244,18 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48451
49244
|
dir: dest,
|
|
48452
49245
|
files: written.length,
|
|
48453
49246
|
...renamed ? { renamedTo: renamed } : {},
|
|
49247
|
+
...removed.length ? { removed } : {},
|
|
49248
|
+
...refused.length ? {
|
|
49249
|
+
refused,
|
|
49250
|
+
refusedNote: "this archive carries paths a restore will not write (the deny-list has grown since it was published) \u2014 they were skipped, not written over"
|
|
49251
|
+
} : {},
|
|
49252
|
+
// EVERY path, not a count and not a sample: the whole failure was that a hybrid tree
|
|
49253
|
+
// looked like a restore, and a list you have to go and generate yourself is the same
|
|
49254
|
+
// silence with extra steps.
|
|
49255
|
+
...left.length ? {
|
|
49256
|
+
left,
|
|
49257
|
+
warning: `${left.length} file(s) already in ${dest} are not in this release and were KEPT \u2014 this tree is a merge of both, and matches no release. Remove them, or re-run with --replace.`
|
|
49258
|
+
} : {},
|
|
48454
49259
|
next: `cd ${dest} && himi validate`
|
|
48455
49260
|
});
|
|
48456
49261
|
return 0;
|
|
@@ -48473,7 +49278,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48473
49278
|
const force = flags.force === true;
|
|
48474
49279
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
48475
49280
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
48476
|
-
const out = mkdtempSync4(
|
|
49281
|
+
const out = mkdtempSync4(join49(tmpdir5(), "himi-push-"));
|
|
48477
49282
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
48478
49283
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
48479
49284
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -48740,7 +49545,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48740
49545
|
return 2;
|
|
48741
49546
|
}
|
|
48742
49547
|
try {
|
|
48743
|
-
const res = writePack(
|
|
49548
|
+
const res = writePack(resolve40(releaseDir), only, resolve40(str5(flags.out) ?? process.cwd()));
|
|
48744
49549
|
print({
|
|
48745
49550
|
ok: true,
|
|
48746
49551
|
app: res.app,
|
|
@@ -48765,7 +49570,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48765
49570
|
const force = flags.force === true;
|
|
48766
49571
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
48767
49572
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
48768
|
-
const built = mkdtempSync4(
|
|
49573
|
+
const built = mkdtempSync4(join49(tmpdir5(), "himi-pack-"));
|
|
48769
49574
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
48770
49575
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
48771
49576
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -48778,12 +49583,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48778
49583
|
...fontIssues(dir, strict)
|
|
48779
49584
|
]);
|
|
48780
49585
|
if (hasErrors && !force) {
|
|
48781
|
-
|
|
49586
|
+
rmSync9(built, { recursive: true, force: true });
|
|
48782
49587
|
print({ ...report, packed: false, hint: "lint found errors \u2014 fix them, or re-run `himi pack --force` to pack anyway" });
|
|
48783
49588
|
return 1;
|
|
48784
49589
|
}
|
|
48785
49590
|
try {
|
|
48786
|
-
const res = writePack(built, app,
|
|
49591
|
+
const res = writePack(built, app, resolve40(str5(flags.out) ?? dir));
|
|
48787
49592
|
print({
|
|
48788
49593
|
ok: true,
|
|
48789
49594
|
app: res.app,
|
|
@@ -48808,7 +49613,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48808
49613
|
io.error(JSON.stringify({ error: e.message }));
|
|
48809
49614
|
return 1;
|
|
48810
49615
|
} finally {
|
|
48811
|
-
|
|
49616
|
+
rmSync9(built, { recursive: true, force: true });
|
|
48812
49617
|
}
|
|
48813
49618
|
}
|
|
48814
49619
|
// ---- himi share — publish/revoke a content-addressed package link ----
|
|
@@ -48836,12 +49641,12 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48836
49641
|
}
|
|
48837
49642
|
try {
|
|
48838
49643
|
const { openPackageFile: openPackageFile2 } = await Promise.resolve().then(() => (init_pack(), pack_exports));
|
|
48839
|
-
const opened = openPackageFile2(
|
|
49644
|
+
const opened = openPackageFile2(resolve40(file));
|
|
48840
49645
|
if (!opened.validation.ok || !opened.header) {
|
|
48841
49646
|
io.error(JSON.stringify({ error: "refusing to share an invalid package", issues: opened.validation.errors }));
|
|
48842
49647
|
return 1;
|
|
48843
49648
|
}
|
|
48844
|
-
const archive = readFileSync63(
|
|
49649
|
+
const archive = readFileSync63(resolve40(file));
|
|
48845
49650
|
const result = await client3().createPackageShare({
|
|
48846
49651
|
app: opened.header.app,
|
|
48847
49652
|
releaseId: opened.header.releaseId,
|
|
@@ -48878,10 +49683,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48878
49683
|
const app = await appId(dir);
|
|
48879
49684
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
48880
49685
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
48881
|
-
temp = mkdtempSync4(
|
|
49686
|
+
temp = mkdtempSync4(join49(tmpdir5(), "himi-run-build-"));
|
|
48882
49687
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
48883
49688
|
await buildReleaseFromContent2(dir, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {} });
|
|
48884
|
-
source =
|
|
49689
|
+
source = join49(temp, app);
|
|
48885
49690
|
}
|
|
48886
49691
|
const chromeArg = str5(flags.chrome) ?? "preview";
|
|
48887
49692
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -48906,9 +49711,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48906
49711
|
open: flags["no-open"] !== true
|
|
48907
49712
|
});
|
|
48908
49713
|
print({ ok: true, app: run2.app, url: run2.url, port: run2.port, plane: "browser" });
|
|
48909
|
-
await new Promise((
|
|
49714
|
+
await new Promise((resolve41) => {
|
|
48910
49715
|
const stop = () => {
|
|
48911
|
-
void run2.close().finally(() =>
|
|
49716
|
+
void run2.close().finally(() => resolve41());
|
|
48912
49717
|
};
|
|
48913
49718
|
process.once("SIGINT", stop);
|
|
48914
49719
|
process.once("SIGTERM", stop);
|
|
@@ -48944,7 +49749,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48944
49749
|
io.error(JSON.stringify({ error: e.message }));
|
|
48945
49750
|
return 1;
|
|
48946
49751
|
} finally {
|
|
48947
|
-
if (temp)
|
|
49752
|
+
if (temp) rmSync9(temp, { recursive: true, force: true });
|
|
48948
49753
|
}
|
|
48949
49754
|
}
|
|
48950
49755
|
case "preview": {
|
|
@@ -49679,7 +50484,7 @@ ${label2}`);
|
|
|
49679
50484
|
const platform = str5(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
|
|
49680
50485
|
{
|
|
49681
50486
|
const distDir = contentDir(flags);
|
|
49682
|
-
if (
|
|
50487
|
+
if (existsSync51(join49(distDir, "himalaya.content.json"))) {
|
|
49683
50488
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
49684
50489
|
const errors = issues.filter((i) => i.severity === "error");
|
|
49685
50490
|
for (const i of issues.filter((i2) => i2.severity === "warning")) {
|