@wix/himalaya-cli 0.808.0 → 0.809.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 +961 -325
- package/guides/himi-test.md +46 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -1014,7 +1014,7 @@ function sentinelizeIdentity(body, identity) {
|
|
|
1014
1014
|
}
|
|
1015
1015
|
if (identity.name) {
|
|
1016
1016
|
const re = new RegExp(`\\b(${NAME_FIELDS.join("|")})(["']?\\s*[:=]\\s*)(["'])${escapeRe(identity.name)}\\3`, "g");
|
|
1017
|
-
out = out.replace(re, (_m, key2,
|
|
1017
|
+
out = out.replace(re, (_m, key2, sep11, q) => `${key2}${sep11}${q}__HIMI_APP_NAME__${q}`);
|
|
1018
1018
|
}
|
|
1019
1019
|
return out;
|
|
1020
1020
|
}
|
|
@@ -2496,8 +2496,8 @@ var init_splash = __esm({
|
|
|
2496
2496
|
|
|
2497
2497
|
// ../../core/dev-server/tier5-bundles-src/build-lib.mjs
|
|
2498
2498
|
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";
|
|
2499
|
+
import { dirname as dirname8, join as join12, resolve as resolve8, sep as sep2 } from "node:path";
|
|
2500
|
+
import { readdirSync as readdirSync6, existsSync as existsSync8, readFileSync as readFileSync10, realpathSync as realpathSync2, statSync as statSync2 } from "node:fs";
|
|
2501
2501
|
async function loadCompiler() {
|
|
2502
2502
|
try {
|
|
2503
2503
|
const nativeCompiler = ["es", "build"].join("");
|
|
@@ -2530,6 +2530,259 @@ function isOffRepo() {
|
|
|
2530
2530
|
if (process.env.HIMI_OFF_REPO === "1") return true;
|
|
2531
2531
|
return !existsSync8(alias["@himalaya/state"]);
|
|
2532
2532
|
}
|
|
2533
|
+
function buildConfinementRequired() {
|
|
2534
|
+
return _confinementRequired;
|
|
2535
|
+
}
|
|
2536
|
+
function realpathOrSelf(p) {
|
|
2537
|
+
try {
|
|
2538
|
+
return realpathSync2(resolve8(p));
|
|
2539
|
+
} catch {
|
|
2540
|
+
return resolve8(p);
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
function isUnder(p, root) {
|
|
2544
|
+
return p === root || p.startsWith(root + sep2);
|
|
2545
|
+
}
|
|
2546
|
+
function confinementRoots(contentRoot) {
|
|
2547
|
+
const roots = /* @__PURE__ */ new Set();
|
|
2548
|
+
const add = (p) => {
|
|
2549
|
+
if (!p) return;
|
|
2550
|
+
roots.add(realpathOrSelf(p));
|
|
2551
|
+
roots.add(resolve8(p));
|
|
2552
|
+
};
|
|
2553
|
+
const real = realpathOrSelf(contentRoot);
|
|
2554
|
+
add(real);
|
|
2555
|
+
for (let d = real, up; ; d = up) {
|
|
2556
|
+
add(join12(d, "node_modules"));
|
|
2557
|
+
up = dirname8(d);
|
|
2558
|
+
if (up === d) break;
|
|
2559
|
+
}
|
|
2560
|
+
add(process.env.HIMI_AUTHORING_RUNTIME_DIR);
|
|
2561
|
+
add(process.env.HIMI_CLI_RUNTIME_DIR);
|
|
2562
|
+
if (!isOffRepo()) add(REPO_ROOT4);
|
|
2563
|
+
return [...roots];
|
|
2564
|
+
}
|
|
2565
|
+
function confinementMatcher(contentRoot, extraRoots = []) {
|
|
2566
|
+
const roots = [...confinementRoots(contentRoot), ...extraRoots.filter(Boolean).flatMap((r) => [realpathOrSelf(r), resolve8(r)])];
|
|
2567
|
+
let linked;
|
|
2568
|
+
const linkedRoots = () => {
|
|
2569
|
+
if (linked) return linked;
|
|
2570
|
+
linked = [];
|
|
2571
|
+
const scanned = /* @__PURE__ */ new Set();
|
|
2572
|
+
const queue = [...roots];
|
|
2573
|
+
const CAP3 = 4096;
|
|
2574
|
+
const take = (abs) => {
|
|
2575
|
+
const target = realpathOrSelf(abs);
|
|
2576
|
+
if (scanned.has(target) || linked.length >= CAP3) return;
|
|
2577
|
+
linked.push(target);
|
|
2578
|
+
queue.push(target);
|
|
2579
|
+
};
|
|
2580
|
+
while (queue.length && linked.length < CAP3) {
|
|
2581
|
+
const r = queue.shift();
|
|
2582
|
+
for (const nm of [r, join12(r, "node_modules")]) {
|
|
2583
|
+
if (scanned.has(nm)) continue;
|
|
2584
|
+
scanned.add(nm);
|
|
2585
|
+
let entries;
|
|
2586
|
+
try {
|
|
2587
|
+
entries = readdirSync6(nm, { withFileTypes: true });
|
|
2588
|
+
} catch {
|
|
2589
|
+
continue;
|
|
2590
|
+
}
|
|
2591
|
+
for (const e of entries) {
|
|
2592
|
+
const abs = join12(nm, e.name);
|
|
2593
|
+
if (e.isSymbolicLink()) take(abs);
|
|
2594
|
+
else if (e.isDirectory() && e.name.startsWith("@")) {
|
|
2595
|
+
let scoped;
|
|
2596
|
+
try {
|
|
2597
|
+
scoped = readdirSync6(abs, { withFileTypes: true });
|
|
2598
|
+
} catch {
|
|
2599
|
+
continue;
|
|
2600
|
+
}
|
|
2601
|
+
for (const sc of scoped) if (sc.isSymbolicLink()) take(join12(abs, sc.name));
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
return linked;
|
|
2607
|
+
};
|
|
2608
|
+
return (p) => {
|
|
2609
|
+
const direct = resolve8(p);
|
|
2610
|
+
if (roots.some((r) => isUnder(direct, r))) return true;
|
|
2611
|
+
const real = realpathOrSelf(direct);
|
|
2612
|
+
if (real !== direct && roots.some((r) => isUnder(real, r))) return true;
|
|
2613
|
+
return linkedRoots().some((r) => isUnder(real, r) || isUnder(direct, r));
|
|
2614
|
+
};
|
|
2615
|
+
}
|
|
2616
|
+
function confinementPlugin(contentRoot) {
|
|
2617
|
+
const allows = confinementMatcher(contentRoot);
|
|
2618
|
+
return {
|
|
2619
|
+
name: "himalaya-confine-import-graph",
|
|
2620
|
+
setup(b) {
|
|
2621
|
+
b.onResolve({ filter: /^[./]/ }, (args) => {
|
|
2622
|
+
const base = args.path.startsWith("/") ? args.path : args.resolveDir ? resolve8(args.resolveDir, args.path) : void 0;
|
|
2623
|
+
if (!base || allows(base)) return void 0;
|
|
2624
|
+
return {
|
|
2625
|
+
errors: [{
|
|
2626
|
+
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.`
|
|
2627
|
+
}]
|
|
2628
|
+
};
|
|
2629
|
+
});
|
|
2630
|
+
b.onLoad({ filter: /.*/ }, (args) => {
|
|
2631
|
+
if (args.namespace && args.namespace !== "file") return void 0;
|
|
2632
|
+
if (allows(args.path)) return void 0;
|
|
2633
|
+
return {
|
|
2634
|
+
errors: [{
|
|
2635
|
+
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.`
|
|
2636
|
+
}]
|
|
2637
|
+
};
|
|
2638
|
+
});
|
|
2639
|
+
}
|
|
2640
|
+
};
|
|
2641
|
+
}
|
|
2642
|
+
function assertConfinedTsconfig(entry, contentRoot, allows) {
|
|
2643
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2644
|
+
const refuse = (p, why) => {
|
|
2645
|
+
throw new Error(
|
|
2646
|
+
`refused to read ${p}: ${why}. A tsconfig may extend a file from its own package or an installed dependency \u2014 nothing else.`
|
|
2647
|
+
);
|
|
2648
|
+
};
|
|
2649
|
+
const stripJsonc = (text2) => {
|
|
2650
|
+
if (text2.charCodeAt(0) === 65279) text2 = text2.slice(1);
|
|
2651
|
+
let out = "";
|
|
2652
|
+
let inStr = false;
|
|
2653
|
+
let esc = false;
|
|
2654
|
+
for (let i = 0; i < text2.length; i++) {
|
|
2655
|
+
const c = text2[i];
|
|
2656
|
+
if (inStr) {
|
|
2657
|
+
out += c;
|
|
2658
|
+
if (esc) esc = false;
|
|
2659
|
+
else if (c === "\\") esc = true;
|
|
2660
|
+
else if (c === '"') inStr = false;
|
|
2661
|
+
continue;
|
|
2662
|
+
}
|
|
2663
|
+
if (c === '"') {
|
|
2664
|
+
inStr = true;
|
|
2665
|
+
out += c;
|
|
2666
|
+
continue;
|
|
2667
|
+
}
|
|
2668
|
+
if (c === "/" && text2[i + 1] === "/") {
|
|
2669
|
+
while (i < text2.length && text2[i] !== "\n") i++;
|
|
2670
|
+
continue;
|
|
2671
|
+
}
|
|
2672
|
+
if (c === "/" && text2[i + 1] === "*") {
|
|
2673
|
+
i += 2;
|
|
2674
|
+
while (i < text2.length && !(text2[i] === "*" && text2[i + 1] === "/")) i++;
|
|
2675
|
+
i++;
|
|
2676
|
+
continue;
|
|
2677
|
+
}
|
|
2678
|
+
if (c === "}" || c === "]") {
|
|
2679
|
+
const trimmed = out.replace(/\s+$/, "");
|
|
2680
|
+
if (trimmed.endsWith(",")) out = trimmed.slice(0, -1);
|
|
2681
|
+
}
|
|
2682
|
+
out += c;
|
|
2683
|
+
}
|
|
2684
|
+
return out;
|
|
2685
|
+
};
|
|
2686
|
+
const isFile = (p) => {
|
|
2687
|
+
try {
|
|
2688
|
+
return statSync2(p).isFile();
|
|
2689
|
+
} catch {
|
|
2690
|
+
return false;
|
|
2691
|
+
}
|
|
2692
|
+
};
|
|
2693
|
+
const asConfigFile = (t) => {
|
|
2694
|
+
if (isFile(t)) return t;
|
|
2695
|
+
const inDir = join12(t, "tsconfig.json");
|
|
2696
|
+
if (isFile(inDir)) return inDir;
|
|
2697
|
+
if (isFile(`${t}.json`)) return `${t}.json`;
|
|
2698
|
+
return t;
|
|
2699
|
+
};
|
|
2700
|
+
const resolveBare = (spec, fromDir) => {
|
|
2701
|
+
for (let d = fromDir, up; ; d = up) {
|
|
2702
|
+
const base = join12(d, "node_modules", spec);
|
|
2703
|
+
for (const cand of [base, `${base}.json`]) if (isFile(cand)) return cand;
|
|
2704
|
+
const pj = join12(base, "package.json");
|
|
2705
|
+
if (isFile(pj)) {
|
|
2706
|
+
let manifest;
|
|
2707
|
+
try {
|
|
2708
|
+
manifest = JSON.parse(stripJsonc(readFileSync10(pj, "utf8")));
|
|
2709
|
+
} catch {
|
|
2710
|
+
refuse(pj, "its package.json could not be parsed, so its `tsconfig` field cannot be checked");
|
|
2711
|
+
}
|
|
2712
|
+
const field = manifest?.tsconfig;
|
|
2713
|
+
if (typeof field === "string" && field) {
|
|
2714
|
+
return asConfigFile(field.startsWith("/") ? field : resolve8(base, field));
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
if (isFile(join12(base, "tsconfig.json"))) return join12(base, "tsconfig.json");
|
|
2718
|
+
up = dirname8(d);
|
|
2719
|
+
if (up === d) return void 0;
|
|
2720
|
+
}
|
|
2721
|
+
};
|
|
2722
|
+
const follow = (file) => {
|
|
2723
|
+
const real = realpathOrSelf(file);
|
|
2724
|
+
if (seen.has(real)) return;
|
|
2725
|
+
seen.add(real);
|
|
2726
|
+
if (!allows(real)) refuse(file, "it is outside this content package");
|
|
2727
|
+
let raw;
|
|
2728
|
+
try {
|
|
2729
|
+
raw = readFileSync10(real, "utf8");
|
|
2730
|
+
} catch {
|
|
2731
|
+
return;
|
|
2732
|
+
}
|
|
2733
|
+
let parsed;
|
|
2734
|
+
try {
|
|
2735
|
+
parsed = JSON.parse(stripJsonc(raw));
|
|
2736
|
+
} catch {
|
|
2737
|
+
refuse(file, "its tsconfig could not be parsed, so its `extends` cannot be checked");
|
|
2738
|
+
}
|
|
2739
|
+
const ext = parsed?.extends;
|
|
2740
|
+
for (const one of Array.isArray(ext) ? ext : ext ? [ext] : []) {
|
|
2741
|
+
if (typeof one !== "string" || !one) continue;
|
|
2742
|
+
if (one.startsWith(".") || one.startsWith("/")) {
|
|
2743
|
+
const target = asConfigFile(one.startsWith("/") ? one : resolve8(dirname8(real), one));
|
|
2744
|
+
if (target) follow(target);
|
|
2745
|
+
} else {
|
|
2746
|
+
const target = resolveBare(one, dirname8(real));
|
|
2747
|
+
if (target) follow(target);
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
};
|
|
2751
|
+
const scan = (dir) => {
|
|
2752
|
+
let entries;
|
|
2753
|
+
try {
|
|
2754
|
+
entries = readdirSync6(dir, { withFileTypes: true });
|
|
2755
|
+
} catch {
|
|
2756
|
+
return;
|
|
2757
|
+
}
|
|
2758
|
+
for (const e of entries) {
|
|
2759
|
+
const abs = join12(dir, e.name);
|
|
2760
|
+
if (e.isDirectory()) scan(abs);
|
|
2761
|
+
else if (e.name === "tsconfig.json" && e.isFile()) follow(abs);
|
|
2762
|
+
}
|
|
2763
|
+
};
|
|
2764
|
+
scan(realpathOrSelf(contentRoot));
|
|
2765
|
+
for (let d = dirname8(realpathOrSelf(entry)), up; ; d = up) {
|
|
2766
|
+
const cfg = join12(d, "tsconfig.json");
|
|
2767
|
+
if (existsSync8(cfg)) {
|
|
2768
|
+
follow(cfg);
|
|
2769
|
+
return;
|
|
2770
|
+
}
|
|
2771
|
+
up = dirname8(d);
|
|
2772
|
+
if (up === d) return;
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
function confinementFor(contentRoot, where, entry) {
|
|
2776
|
+
if (!_confinementRequired) return void 0;
|
|
2777
|
+
if (!contentRoot) {
|
|
2778
|
+
throw new Error(
|
|
2779
|
+
`${where}: this process compiles untrusted uploads (requireBuildConfinement) but no content root was given, so the import graph would be unconfined. Pass \`confineTo: <content dir>\`.`
|
|
2780
|
+
);
|
|
2781
|
+
}
|
|
2782
|
+
const allows = confinementMatcher(contentRoot);
|
|
2783
|
+
if (entry) assertConfinedTsconfig(entry, contentRoot, allows);
|
|
2784
|
+
return confinementPlugin(contentRoot);
|
|
2785
|
+
}
|
|
2533
2786
|
function umbrellaRewritePlugin({ external = false } = {}) {
|
|
2534
2787
|
return {
|
|
2535
2788
|
name: "himalaya-umbrella-rewrite",
|
|
@@ -2597,7 +2850,8 @@ function importMetaUrlPlugin() {
|
|
|
2597
2850
|
};
|
|
2598
2851
|
}
|
|
2599
2852
|
async function buildBundleFromEntry(entry, outfile, opts = {}) {
|
|
2600
|
-
const { resolution = "source", name = "bundle", absWorkingDir = REPO_ROOT4 } = opts;
|
|
2853
|
+
const { resolution = "source", name = "bundle", absWorkingDir = REPO_ROOT4, confineTo } = opts;
|
|
2854
|
+
const confine = confinementFor(confineTo, "buildBundleFromEntry", entry);
|
|
2601
2855
|
if (!existsSync8(entry)) throw new Error(`no bundle entry: ${entry}`);
|
|
2602
2856
|
const buildOpts = {
|
|
2603
2857
|
entryPoints: [entry],
|
|
@@ -2620,11 +2874,13 @@ async function buildBundleFromEntry(entry, outfile, opts = {}) {
|
|
|
2620
2874
|
else if (isOffRepo()) {
|
|
2621
2875
|
buildOpts.plugins = process.env.HIMI_CLI_RUNTIME_DIR ? [cliRuntimeUmbrellaPlugin()] : [umbrellaRewritePlugin({ external: false })];
|
|
2622
2876
|
}
|
|
2877
|
+
if (confine) buildOpts.plugins = [confine, ...buildOpts.plugins ?? []];
|
|
2623
2878
|
await build(buildOpts);
|
|
2624
2879
|
return outfile;
|
|
2625
2880
|
}
|
|
2626
2881
|
async function buildAppEntry(entry, outfile, opts = {}) {
|
|
2627
|
-
const { umbrella = false, resolveTsExtensions = false, absWorkingDir = REPO_ROOT4 } = opts;
|
|
2882
|
+
const { umbrella = false, resolveTsExtensions = false, absWorkingDir = REPO_ROOT4, confineTo } = opts;
|
|
2883
|
+
const confine = confinementFor(confineTo, "buildAppEntry", entry);
|
|
2628
2884
|
if (!existsSync8(entry)) throw new Error(`unknown app entry: ${entry}`);
|
|
2629
2885
|
await build({
|
|
2630
2886
|
entryPoints: [entry],
|
|
@@ -2648,6 +2904,9 @@ async function buildAppEntry(entry, outfile, opts = {}) {
|
|
|
2648
2904
|
// -- a single global `define` here pinned the whole graph to the entry and broke
|
|
2649
2905
|
// every app whose config.ts reads a file relative to itself.
|
|
2650
2906
|
plugins: [
|
|
2907
|
+
// FIRST, and here it is load-bearing: `importMetaUrlPlugin` registers an onLoad and CLAIMS
|
|
2908
|
+
// every file containing `import.meta.url`, so a confinement behind it would never see them.
|
|
2909
|
+
...confine ? [confine] : [],
|
|
2651
2910
|
importMetaUrlPlugin(),
|
|
2652
2911
|
...resolveTsExtensions ? [tsExtResolvePlugin()] : [],
|
|
2653
2912
|
...process.env.HIMI_CLI_RUNTIME_DIR ? [cliRuntimeUmbrellaPlugin()] : [],
|
|
@@ -2656,7 +2915,7 @@ async function buildAppEntry(entry, outfile, opts = {}) {
|
|
|
2656
2915
|
});
|
|
2657
2916
|
return outfile;
|
|
2658
2917
|
}
|
|
2659
|
-
var _compilerP, __dirname, REPO_ROOT4, SDK, alias, sourceAliases, OUT_DIR, HERMES_SAFE_SUPPORTED, HERMES_UNSAFE_BUNDLES, APP_ENTRY_TARGET;
|
|
2918
|
+
var _compilerP, __dirname, REPO_ROOT4, SDK, alias, sourceAliases, OUT_DIR, HERMES_SAFE_SUPPORTED, HERMES_UNSAFE_BUNDLES, _confinementRequired, APP_ENTRY_TARGET;
|
|
2660
2919
|
var init_build_lib = __esm({
|
|
2661
2920
|
"../../core/dev-server/tier5-bundles-src/build-lib.mjs"() {
|
|
2662
2921
|
"use strict";
|
|
@@ -2805,6 +3064,7 @@ var init_build_lib = __esm({
|
|
|
2805
3064
|
// worker-safe wix-auth showcase pulls ~11 classes from stdlib/auth-providers.
|
|
2806
3065
|
"demo-app-wix-platform"
|
|
2807
3066
|
]);
|
|
3067
|
+
_confinementRequired = false;
|
|
2808
3068
|
APP_ENTRY_TARGET = ["node18"];
|
|
2809
3069
|
}
|
|
2810
3070
|
});
|
|
@@ -2829,7 +3089,7 @@ var init_tier5_dir = __esm({
|
|
|
2829
3089
|
|
|
2830
3090
|
// src/tier5-typecheck.ts
|
|
2831
3091
|
import { existsSync as existsSync9, readFileSync as readFileSync11 } from "node:fs";
|
|
2832
|
-
import { relative as relative2, resolve as resolve10, sep as
|
|
3092
|
+
import { relative as relative2, resolve as resolve10, sep as sep3 } from "node:path";
|
|
2833
3093
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
2834
3094
|
async function loadTypeScript() {
|
|
2835
3095
|
const runtime = process.env.HIMI_AUTHORING_RUNTIME_DIR;
|
|
@@ -2868,7 +3128,7 @@ function pathsFor(options) {
|
|
|
2868
3128
|
return declarationPaths(options.umbrellaDir);
|
|
2869
3129
|
}
|
|
2870
3130
|
function relativeFile(contentDir2, fileName) {
|
|
2871
|
-
return relative2(contentDir2, fileName).split(
|
|
3131
|
+
return relative2(contentDir2, fileName).split(sep3).join("/");
|
|
2872
3132
|
}
|
|
2873
3133
|
function belongsToContentWorkers(contentDir2, diagnostic) {
|
|
2874
3134
|
if (!diagnostic.file) return true;
|
|
@@ -2890,6 +3150,19 @@ function toIssue(ts, contentDir2, diagnostic) {
|
|
|
2890
3150
|
message: ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")
|
|
2891
3151
|
};
|
|
2892
3152
|
}
|
|
3153
|
+
function confinedHost(ts, contentDir2, options) {
|
|
3154
|
+
if (!buildConfinementRequired()) return void 0;
|
|
3155
|
+
const host = ts.createCompilerHost(options);
|
|
3156
|
+
const libDir = resolve10(ts.getDefaultLibFilePath(options), "..");
|
|
3157
|
+
const allows = confinementMatcher(contentDir2, [libDir]);
|
|
3158
|
+
const getSourceFile = host.getSourceFile.bind(host);
|
|
3159
|
+
const readFile3 = host.readFile.bind(host);
|
|
3160
|
+
const fileExists = host.fileExists.bind(host);
|
|
3161
|
+
host.getSourceFile = (fileName, ...rest) => allows(fileName) ? getSourceFile(fileName, ...rest) : void 0;
|
|
3162
|
+
host.readFile = (fileName) => allows(fileName) ? readFile3(fileName) : void 0;
|
|
3163
|
+
host.fileExists = (fileName) => allows(fileName) && fileExists(fileName);
|
|
3164
|
+
return host;
|
|
3165
|
+
}
|
|
2893
3166
|
async function typecheckContentWorkers(contentDir2, options) {
|
|
2894
3167
|
if (!existsSync9(resolve10(contentDir2, "tier5-src"))) return [];
|
|
2895
3168
|
const ts = await compiler2();
|
|
@@ -2907,7 +3180,11 @@ async function typecheckContentWorkers(contentDir2, options) {
|
|
|
2907
3180
|
};
|
|
2908
3181
|
const parsed = ts.parseJsonConfigFileContent(config, ts.sys, contentDir2);
|
|
2909
3182
|
if (parsed.fileNames.length === 0) return [];
|
|
2910
|
-
const program = ts.createProgram({
|
|
3183
|
+
const program = ts.createProgram({
|
|
3184
|
+
rootNames: parsed.fileNames,
|
|
3185
|
+
options: parsed.options,
|
|
3186
|
+
host: confinedHost(ts, contentDir2, parsed.options)
|
|
3187
|
+
});
|
|
2911
3188
|
return [...parsed.errors, ...ts.getPreEmitDiagnostics(program)].filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error && belongsToContentWorkers(contentDir2, diagnostic)).map((diagnostic) => toIssue(ts, contentDir2, diagnostic));
|
|
2912
3189
|
}
|
|
2913
3190
|
var compilerPromise;
|
|
@@ -2936,31 +3213,31 @@ __export(build_exports, {
|
|
|
2936
3213
|
umbrellaVersion: () => umbrellaVersion,
|
|
2937
3214
|
umbrellaVersionIssue: () => umbrellaVersionIssue
|
|
2938
3215
|
});
|
|
2939
|
-
import { existsSync as existsSync10, readdirSync as readdirSync8, mkdirSync as mkdirSync6, statSync as
|
|
2940
|
-
import { resolve as resolve11, join as
|
|
3216
|
+
import { existsSync as existsSync10, readdirSync as readdirSync8, mkdirSync as mkdirSync6, statSync as statSync3, symlinkSync, readFileSync as readFileSync12 } from "node:fs";
|
|
3217
|
+
import { resolve as resolve11, join as join13, dirname as dirname9 } from "node:path";
|
|
2941
3218
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
2942
3219
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
2943
3220
|
function bundledRuntimeDir() {
|
|
2944
3221
|
const configured = process.env.HIMI_CLI_RUNTIME_DIR;
|
|
2945
|
-
if (configured && existsSync10(
|
|
3222
|
+
if (configured && existsSync10(join13(configured, "node_modules", "@wix", "himalaya", "package.json"))) {
|
|
2946
3223
|
return configured;
|
|
2947
3224
|
}
|
|
2948
3225
|
const candidate = resolve11(dirname9(fileURLToPath6(import.meta.url)), "authoring-runtime");
|
|
2949
|
-
if (!existsSync10(
|
|
3226
|
+
if (!existsSync10(join13(candidate, "node_modules", "@wix", "himalaya", "package.json"))) return null;
|
|
2950
3227
|
process.env.HIMI_CLI_RUNTIME_DIR = candidate;
|
|
2951
3228
|
return candidate;
|
|
2952
3229
|
}
|
|
2953
3230
|
function bundledUmbrella() {
|
|
2954
3231
|
const runtime = bundledRuntimeDir();
|
|
2955
|
-
return runtime ?
|
|
3232
|
+
return runtime ? join13(runtime, "node_modules", "@wix", "himalaya") : null;
|
|
2956
3233
|
}
|
|
2957
3234
|
function umbrellaDir(fromDir) {
|
|
2958
3235
|
const bundled = bundledUmbrella();
|
|
2959
3236
|
if (bundled) return bundled;
|
|
2960
3237
|
let d = resolve11(fromDir);
|
|
2961
3238
|
for (; ; ) {
|
|
2962
|
-
const pkg =
|
|
2963
|
-
if (existsSync10(
|
|
3239
|
+
const pkg = join13(d, "node_modules", "@wix", "himalaya");
|
|
3240
|
+
if (existsSync10(join13(pkg, "package.json"))) return pkg;
|
|
2964
3241
|
const parent = dirname9(d);
|
|
2965
3242
|
if (parent === d) return null;
|
|
2966
3243
|
d = parent;
|
|
@@ -2973,8 +3250,8 @@ function globalUmbrella() {
|
|
|
2973
3250
|
try {
|
|
2974
3251
|
const root = execFileSync3("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
2975
3252
|
if (!root) return null;
|
|
2976
|
-
const pkg =
|
|
2977
|
-
return existsSync10(
|
|
3253
|
+
const pkg = join13(root, "@wix", "himalaya");
|
|
3254
|
+
return existsSync10(join13(pkg, "package.json")) ? pkg : null;
|
|
2978
3255
|
} catch {
|
|
2979
3256
|
return null;
|
|
2980
3257
|
}
|
|
@@ -2983,11 +3260,11 @@ function ensureUmbrella(contentDir2, globalPath = globalUmbrella()) {
|
|
|
2983
3260
|
if (umbrellaInstalled(contentDir2)) return true;
|
|
2984
3261
|
if (!globalPath) return false;
|
|
2985
3262
|
try {
|
|
2986
|
-
const scope =
|
|
3263
|
+
const scope = join13(contentDir2, "node_modules", "@wix");
|
|
2987
3264
|
mkdirSync6(scope, { recursive: true });
|
|
2988
|
-
const link =
|
|
3265
|
+
const link = join13(scope, "himalaya");
|
|
2989
3266
|
if (!existsSync10(link)) symlinkSync(globalPath, link, "dir");
|
|
2990
|
-
return existsSync10(
|
|
3267
|
+
return existsSync10(join13(link, "package.json"));
|
|
2991
3268
|
} catch {
|
|
2992
3269
|
return false;
|
|
2993
3270
|
}
|
|
@@ -3005,7 +3282,7 @@ function umbrellaVersion(fromDir) {
|
|
|
3005
3282
|
const dir = umbrellaDir(fromDir);
|
|
3006
3283
|
if (!dir) return null;
|
|
3007
3284
|
try {
|
|
3008
|
-
const v = JSON.parse(readFileSync12(
|
|
3285
|
+
const v = JSON.parse(readFileSync12(join13(dir, "package.json"), "utf8")).version;
|
|
3009
3286
|
return typeof v === "string" && v ? v : null;
|
|
3010
3287
|
} catch {
|
|
3011
3288
|
return null;
|
|
@@ -3026,7 +3303,7 @@ function umbrellaDistIssue(contentDir2) {
|
|
|
3026
3303
|
if (!dir) return null;
|
|
3027
3304
|
let exportsMap;
|
|
3028
3305
|
try {
|
|
3029
|
-
exportsMap = JSON.parse(readFileSync12(
|
|
3306
|
+
exportsMap = JSON.parse(readFileSync12(join13(dir, "package.json"), "utf8")).exports;
|
|
3030
3307
|
} catch {
|
|
3031
3308
|
return null;
|
|
3032
3309
|
}
|
|
@@ -3080,14 +3357,19 @@ async function buildContentBundles(contentDir2, opts = {}) {
|
|
|
3080
3357
|
if (!existsSync10(srcDir)) return { built, outDir, compileErrors, ...sdkVersionIssue ? { sdkVersionIssue } : {} };
|
|
3081
3358
|
mkdirSync6(outDir, { recursive: true });
|
|
3082
3359
|
for (const name of readdirSync8(srcDir).sort()) {
|
|
3083
|
-
const entry =
|
|
3084
|
-
if (!
|
|
3360
|
+
const entry = join13(srcDir, name, "index.ts");
|
|
3361
|
+
if (!statSync3(join13(srcDir, name)).isDirectory() || !existsSync10(entry)) continue;
|
|
3085
3362
|
try {
|
|
3086
|
-
await buildBundleFromEntry(entry,
|
|
3363
|
+
await buildBundleFromEntry(entry, join13(outDir, `${name}.bundle.js`), {
|
|
3087
3364
|
resolution,
|
|
3088
3365
|
name,
|
|
3089
3366
|
// Off-repo, resolve the umbrella from the content package's own node_modules.
|
|
3090
|
-
...offRepo ? { absWorkingDir: contentDir2 } : {}
|
|
3367
|
+
...offRepo ? { absWorkingDir: contentDir2 } : {},
|
|
3368
|
+
// Bounds the import graph in a process that compiles untrusted uploads
|
|
3369
|
+
// (core/serve-authoring); inert everywhere else. Always passed, so the authoring guest
|
|
3370
|
+
// cannot reach this build without a root — build-lib throws rather than compile
|
|
3371
|
+
// unconfined.
|
|
3372
|
+
confineTo: contentDir2
|
|
3091
3373
|
});
|
|
3092
3374
|
built.push(name);
|
|
3093
3375
|
} catch (err) {
|
|
@@ -3125,11 +3407,11 @@ __export(app_config_loader_exports, {
|
|
|
3125
3407
|
loadAppConfigModule: () => loadAppConfigModule
|
|
3126
3408
|
});
|
|
3127
3409
|
import { existsSync as existsSync11, mkdirSync as mkdirSync7 } from "node:fs";
|
|
3128
|
-
import { dirname as dirname10, join as
|
|
3410
|
+
import { dirname as dirname10, join as join14, resolve as resolve12 } from "node:path";
|
|
3129
3411
|
import { pathToFileURL as pathToFileURL4 } from "node:url";
|
|
3130
3412
|
function configEntry(dir) {
|
|
3131
3413
|
for (const f of ["config.ts", "config.js", "config.mjs"]) {
|
|
3132
|
-
const p =
|
|
3414
|
+
const p = join14(dir, f);
|
|
3133
3415
|
if (existsSync11(p)) return p;
|
|
3134
3416
|
}
|
|
3135
3417
|
return null;
|
|
@@ -3141,7 +3423,7 @@ async function buildConfigModuleUrl(entry, dir) {
|
|
|
3141
3423
|
bundledRuntimeDir2();
|
|
3142
3424
|
const out = resolve12(dir, "dist/.himi/config.mjs");
|
|
3143
3425
|
mkdirSync7(dirname10(out), { recursive: true });
|
|
3144
|
-
await buildAppEntry(entry, out, { umbrella: true, resolveTsExtensions: true, absWorkingDir: dir });
|
|
3426
|
+
await buildAppEntry(entry, out, { umbrella: true, resolveTsExtensions: true, absWorkingDir: dir, confineTo: dir });
|
|
3145
3427
|
return pathToFileURL4(out).href;
|
|
3146
3428
|
}
|
|
3147
3429
|
function rememberBuild(key2, pending) {
|
|
@@ -3889,10 +4171,10 @@ var init_app_icon_rules = __esm({
|
|
|
3889
4171
|
|
|
3890
4172
|
// ../../core/dev-server/src/app-icon.ts
|
|
3891
4173
|
import { existsSync as existsSync14, readFileSync as readFileSync17, readdirSync as readdirSync9 } from "node:fs";
|
|
3892
|
-
import { dirname as dirname13, join as
|
|
4174
|
+
import { dirname as dirname13, join as join18, resolve as resolve13 } from "node:path";
|
|
3893
4175
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
3894
4176
|
function findAppIconPath(appDir2) {
|
|
3895
|
-
const iosDir =
|
|
4177
|
+
const iosDir = join18(appDir2, "ios");
|
|
3896
4178
|
let children;
|
|
3897
4179
|
try {
|
|
3898
4180
|
children = readdirSync9(iosDir);
|
|
@@ -3900,7 +4182,7 @@ function findAppIconPath(appDir2) {
|
|
|
3900
4182
|
return null;
|
|
3901
4183
|
}
|
|
3902
4184
|
for (const child of children) {
|
|
3903
|
-
const p =
|
|
4185
|
+
const p = join18(iosDir, child, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
3904
4186
|
if (existsSync14(p)) return p;
|
|
3905
4187
|
}
|
|
3906
4188
|
return null;
|
|
@@ -3908,7 +4190,7 @@ function findAppIconPath(appDir2) {
|
|
|
3908
4190
|
function findContentIconPath(appDir2) {
|
|
3909
4191
|
let rel;
|
|
3910
4192
|
try {
|
|
3911
|
-
rel = JSON.parse(readFileSync17(
|
|
4193
|
+
rel = JSON.parse(readFileSync17(join18(appDir2, "himalaya.content.json"), "utf8")).icon;
|
|
3912
4194
|
} catch {
|
|
3913
4195
|
return null;
|
|
3914
4196
|
}
|
|
@@ -3933,7 +4215,7 @@ function readIconFromDir(appDir2) {
|
|
|
3933
4215
|
function resolveAppDir(appId2) {
|
|
3934
4216
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(appId2)) return null;
|
|
3935
4217
|
for (const base of APP_ROOTS) {
|
|
3936
|
-
const dir =
|
|
4218
|
+
const dir = join18(ROOT, base, appId2);
|
|
3937
4219
|
if (existsSync14(dir)) return dir;
|
|
3938
4220
|
}
|
|
3939
4221
|
return null;
|
|
@@ -4226,11 +4508,11 @@ __export(icon_exports, {
|
|
|
4226
4508
|
summarize: () => summarize
|
|
4227
4509
|
});
|
|
4228
4510
|
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
|
|
4511
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync18, statSync as statSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
4512
|
+
import { basename as basename4, dirname as dirname14, join as join19, resolve as resolve14, sep as sep4 } from "node:path";
|
|
4231
4513
|
function readManifest(dir) {
|
|
4232
4514
|
try {
|
|
4233
|
-
return JSON.parse(readFileSync18(
|
|
4515
|
+
return JSON.parse(readFileSync18(join19(dir, MANIFEST), "utf8"));
|
|
4234
4516
|
} catch {
|
|
4235
4517
|
return null;
|
|
4236
4518
|
}
|
|
@@ -4244,7 +4526,7 @@ function declaredIconName(dir) {
|
|
|
4244
4526
|
function iconDest(dir, name) {
|
|
4245
4527
|
const base = resolve14(dir);
|
|
4246
4528
|
const abs = resolve14(base, name);
|
|
4247
|
-
if (!abs.startsWith(base +
|
|
4529
|
+
if (!abs.startsWith(base + sep4)) {
|
|
4248
4530
|
throw new Error(
|
|
4249
4531
|
`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
4532
|
);
|
|
@@ -4254,9 +4536,9 @@ function iconDest(dir, name) {
|
|
|
4254
4536
|
}
|
|
4255
4537
|
function templateIconMatch(png) {
|
|
4256
4538
|
for (const template of availableTemplates()) {
|
|
4257
|
-
const candidate =
|
|
4539
|
+
const candidate = join19(templateSourceDir(template), DEFAULT_CONTENT_ICON);
|
|
4258
4540
|
try {
|
|
4259
|
-
if (
|
|
4541
|
+
if (statSync4(candidate).size !== png.length) continue;
|
|
4260
4542
|
if (readFileSync18(candidate).equals(png)) return template;
|
|
4261
4543
|
} catch {
|
|
4262
4544
|
}
|
|
@@ -4264,10 +4546,10 @@ function templateIconMatch(png) {
|
|
|
4264
4546
|
return null;
|
|
4265
4547
|
}
|
|
4266
4548
|
function playState(dir) {
|
|
4267
|
-
const p =
|
|
4549
|
+
const p = join19(resolve14(dir), PLAY_LISTING_ICON);
|
|
4268
4550
|
if (!existsSync15(p)) return null;
|
|
4269
4551
|
try {
|
|
4270
|
-
if (!
|
|
4552
|
+
if (!statSync4(p).isFile()) return { path: p, issues: ["is a directory, not a PNG file"] };
|
|
4271
4553
|
return { path: p, issues: playListingIconIssues(readFileSync18(p)) };
|
|
4272
4554
|
} catch (err) {
|
|
4273
4555
|
return { path: p, issues: [`could not be read (${err.message.split("\n")[0]})`] };
|
|
@@ -4294,7 +4576,7 @@ async function iconStatus(dir) {
|
|
|
4294
4576
|
if (!path || !existsSync15(path)) return base;
|
|
4295
4577
|
let png;
|
|
4296
4578
|
try {
|
|
4297
|
-
if (!
|
|
4579
|
+
if (!statSync4(path).isFile()) {
|
|
4298
4580
|
return {
|
|
4299
4581
|
...base,
|
|
4300
4582
|
byteIssues: [`at ${path} is a directory, not a PNG file`],
|
|
@@ -4371,7 +4653,7 @@ function summarize(status) {
|
|
|
4371
4653
|
}
|
|
4372
4654
|
function backdropFromTokens(dir, fallback = "#1F2933") {
|
|
4373
4655
|
try {
|
|
4374
|
-
const tokens = JSON.parse(readFileSync18(
|
|
4656
|
+
const tokens = JSON.parse(readFileSync18(join19(dir, "tokens.json"), "utf8"));
|
|
4375
4657
|
const accent = tokens.colors?.accentPrimary;
|
|
4376
4658
|
const hex2 = typeof accent === "string" ? accent : accent?.light;
|
|
4377
4659
|
return typeof hex2 === "string" && HEX_COLOR2.test(hex2) ? hex2 : fallback;
|
|
@@ -4430,15 +4712,15 @@ function declareIcon(dir, name) {
|
|
|
4430
4712
|
if (k === "name") next.icon = name;
|
|
4431
4713
|
}
|
|
4432
4714
|
next.icon = name;
|
|
4433
|
-
writeFileSync8(
|
|
4434
|
-
return [
|
|
4715
|
+
writeFileSync8(join19(dir, MANIFEST), JSON.stringify(next, null, 2) + "\n");
|
|
4716
|
+
return [join19(dir, MANIFEST)];
|
|
4435
4717
|
}
|
|
4436
4718
|
function siteBookIcon(bookDir) {
|
|
4437
|
-
const p =
|
|
4719
|
+
const p = join19(resolve14(bookDir), SITE_BOOK_ICON_REL);
|
|
4438
4720
|
return existsSync15(p) ? p : null;
|
|
4439
4721
|
}
|
|
4440
4722
|
function siteLogoAbsence(bookDir) {
|
|
4441
|
-
const bookJson =
|
|
4723
|
+
const bookJson = join19(resolve14(bookDir), "book.json");
|
|
4442
4724
|
if (!existsSync15(bookJson)) {
|
|
4443
4725
|
return { reason: "no-book", hint: `no business book at ${bookDir} \u2014 run \`himi site analyze --out <dir>\` first, or pass --book <dir>` };
|
|
4444
4726
|
}
|
|
@@ -4520,7 +4802,7 @@ var init_icon = __esm({
|
|
|
4520
4802
|
// ../fonts/catalog.ts
|
|
4521
4803
|
import { existsSync as existsSync17, readFileSync as readFileSync19 } from "node:fs";
|
|
4522
4804
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
4523
|
-
import { join as
|
|
4805
|
+
import { join as join21 } from "node:path";
|
|
4524
4806
|
function loadCatalog() {
|
|
4525
4807
|
if (cached) return cached;
|
|
4526
4808
|
const path = CATALOG_CANDIDATES.find((p) => existsSync17(p));
|
|
@@ -4589,9 +4871,9 @@ var init_catalog = __esm({
|
|
|
4589
4871
|
"../fonts/catalog.ts"() {
|
|
4590
4872
|
CATALOG_CANDIDATES = [
|
|
4591
4873
|
// in-repo: tools/fonts/catalog.ts → <repo>/stdlib/fonts/catalog.json
|
|
4592
|
-
|
|
4874
|
+
join21(fileURLToPath8(new URL("../..", import.meta.url)), "stdlib", "fonts", "catalog.json"),
|
|
4593
4875
|
// published CLI: <pkg>/dist/cli.mjs → <pkg>/stdlib/fonts/catalog.json
|
|
4594
|
-
|
|
4876
|
+
join21(fileURLToPath8(new URL("..", import.meta.url)), "stdlib", "fonts", "catalog.json")
|
|
4595
4877
|
];
|
|
4596
4878
|
cached = null;
|
|
4597
4879
|
normalizeFamily = (name) => name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
@@ -4696,17 +4978,17 @@ var init_plan_fonts = __esm({
|
|
|
4696
4978
|
import { createHash as createHash6 } from "node:crypto";
|
|
4697
4979
|
import { existsSync as existsSync18, readFileSync as readFileSync20 } from "node:fs";
|
|
4698
4980
|
import { homedir as homedir4 } from "node:os";
|
|
4699
|
-
import { basename as basename5, join as
|
|
4981
|
+
import { basename as basename5, join as join22 } from "node:path";
|
|
4700
4982
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
4701
4983
|
function hasVendoredFloor() {
|
|
4702
4984
|
return existsSync18(VENDORED_DIR);
|
|
4703
4985
|
}
|
|
4704
4986
|
function faceSource(file, sha2565) {
|
|
4705
|
-
const vendored =
|
|
4987
|
+
const vendored = join22(VENDORED_DIR, basename5(file));
|
|
4706
4988
|
if (existsSync18(vendored) && createHash6("sha256").update(readFileSync20(vendored)).digest("hex") === sha2565) {
|
|
4707
4989
|
return vendored;
|
|
4708
4990
|
}
|
|
4709
|
-
const cached3 =
|
|
4991
|
+
const cached3 = join22(CACHE_DIR, sha2565);
|
|
4710
4992
|
if (existsSync18(cached3)) return cached3;
|
|
4711
4993
|
return null;
|
|
4712
4994
|
}
|
|
@@ -4714,8 +4996,8 @@ var REPO_ROOT5, VENDORED_DIR, CACHE_DIR;
|
|
|
4714
4996
|
var init_face_source = __esm({
|
|
4715
4997
|
"../font-bake/face-source.ts"() {
|
|
4716
4998
|
REPO_ROOT5 = fileURLToPath9(new URL("../..", import.meta.url));
|
|
4717
|
-
VENDORED_DIR = process.env.HIMI_FONTS_VENDORED_DIR ||
|
|
4718
|
-
CACHE_DIR =
|
|
4999
|
+
VENDORED_DIR = process.env.HIMI_FONTS_VENDORED_DIR || join22(REPO_ROOT5, "stdlib", "fonts", "vendored", "wix-madefor");
|
|
5000
|
+
CACHE_DIR = join22(process.env.XDG_CACHE_HOME || join22(homedir4(), ".cache"), "himi", "fonts");
|
|
4719
5001
|
}
|
|
4720
5002
|
});
|
|
4721
5003
|
|
|
@@ -4729,7 +5011,7 @@ __export(fonts_exports, {
|
|
|
4729
5011
|
resolveFamilyName: () => resolveFamilyName
|
|
4730
5012
|
});
|
|
4731
5013
|
import { existsSync as existsSync19, readFileSync as readFileSync21 } from "node:fs";
|
|
4732
|
-
import { join as
|
|
5014
|
+
import { join as join23 } from "node:path";
|
|
4733
5015
|
function readJson(path, fallback) {
|
|
4734
5016
|
try {
|
|
4735
5017
|
return JSON.parse(readFileSync21(path, "utf8"));
|
|
@@ -4761,11 +5043,11 @@ function listReport(opts = {}) {
|
|
|
4761
5043
|
return { ok: true, count: families.length, totalBytes, families };
|
|
4762
5044
|
}
|
|
4763
5045
|
function fontFindings(appDir2) {
|
|
4764
|
-
const tokensPath =
|
|
5046
|
+
const tokensPath = join23(appDir2, "tokens.json");
|
|
4765
5047
|
if (!existsSync19(tokensPath)) return null;
|
|
4766
5048
|
const catalog = loadCatalog();
|
|
4767
5049
|
const tokens = readJson(tokensPath, {});
|
|
4768
|
-
const policy = readJson(
|
|
5050
|
+
const policy = readJson(join23(appDir2, "fonts.json"), {});
|
|
4769
5051
|
const plan = planFonts(tokens, policy, catalog);
|
|
4770
5052
|
const findings = [];
|
|
4771
5053
|
for (const family of plan.unresolved) {
|
|
@@ -4851,7 +5133,7 @@ function addReport(appDir2, family) {
|
|
|
4851
5133
|
totalBytes: bytes2,
|
|
4852
5134
|
problems: [],
|
|
4853
5135
|
families: [{ family: resolved, license: fam?.license.id ?? "system", copyright: fam?.license.copyright, kb: Math.round(bytes2 / 1024) }],
|
|
4854
|
-
hint: `add "${resolved}" to ${
|
|
5136
|
+
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
5137
|
};
|
|
4856
5138
|
}
|
|
4857
5139
|
var DEFAULT_ASSET_BUDGET_BYTES;
|
|
@@ -5773,7 +6055,7 @@ var init_src = __esm({
|
|
|
5773
6055
|
// ../app-icons/plan.ts
|
|
5774
6056
|
import { existsSync as existsSync23, readFileSync as readFileSync25, readdirSync as readdirSync12 } from "node:fs";
|
|
5775
6057
|
import { createHash as createHash7 } from "node:crypto";
|
|
5776
|
-
import { dirname as dirname16, join as
|
|
6058
|
+
import { dirname as dirname16, join as join27, resolve as resolve17 } from "node:path";
|
|
5777
6059
|
function stripComments(src) {
|
|
5778
6060
|
let out = "";
|
|
5779
6061
|
let i = 0;
|
|
@@ -5903,10 +6185,10 @@ function rotateHue(hex2, deg) {
|
|
|
5903
6185
|
function resolveTokensPath(app, configTs) {
|
|
5904
6186
|
const literal = /^ {2}designTokensPath\s*:\s*["']([^"']+)["']/m.exec(stripComments(configTs))?.[1];
|
|
5905
6187
|
if (literal) return { path: resolve17(appDir(app), literal), source: "declared" };
|
|
5906
|
-
return { path:
|
|
6188
|
+
return { path: join27(appDir(app), "tokens.json"), source: "assumed" };
|
|
5907
6189
|
}
|
|
5908
6190
|
function resolveToken(app, token, tokensPathOverride) {
|
|
5909
|
-
const tokensPath = tokensPathOverride ??
|
|
6191
|
+
const tokensPath = tokensPathOverride ?? join27(appDir(app), "tokens.json");
|
|
5910
6192
|
if (!existsSync23(tokensPath)) {
|
|
5911
6193
|
throw new Error(`app-icons: ${app} has no tokens.json at ${tokensPath} (needed to resolve "${token}").`);
|
|
5912
6194
|
}
|
|
@@ -5989,17 +6271,17 @@ function iconSpec(app, configTs, id, tokensPathOverride) {
|
|
|
5989
6271
|
};
|
|
5990
6272
|
}
|
|
5991
6273
|
function iosAssetCatalog2(app) {
|
|
5992
|
-
return assetCatalogIn(
|
|
6274
|
+
return assetCatalogIn(join27(appDir(app), "ios"));
|
|
5993
6275
|
}
|
|
5994
6276
|
function assetCatalogIn(platformDir) {
|
|
5995
6277
|
if (!existsSync23(platformDir)) return void 0;
|
|
5996
6278
|
const children = readdirSync12(platformDir).filter((c) => !c.startsWith("build")).sort();
|
|
5997
|
-
const catalogs = children.map((c) =>
|
|
6279
|
+
const catalogs = children.map((c) => join27(platformDir, c, "Assets.xcassets")).filter(existsSync23);
|
|
5998
6280
|
if (catalogs.length === 1) return catalogs[0];
|
|
5999
6281
|
if (catalogs.length > 1) return void 0;
|
|
6000
6282
|
const targets = [];
|
|
6001
6283
|
for (const child of children) {
|
|
6002
|
-
const dir =
|
|
6284
|
+
const dir = join27(platformDir, child);
|
|
6003
6285
|
let entries;
|
|
6004
6286
|
try {
|
|
6005
6287
|
entries = readdirSync12(dir);
|
|
@@ -6007,20 +6289,20 @@ function assetCatalogIn(platformDir) {
|
|
|
6007
6289
|
continue;
|
|
6008
6290
|
}
|
|
6009
6291
|
if (entries.includes("Info.plist") || entries.some((e) => e.endsWith(".swift"))) {
|
|
6010
|
-
targets.push(
|
|
6292
|
+
targets.push(join27(dir, "Assets.xcassets"));
|
|
6011
6293
|
}
|
|
6012
6294
|
}
|
|
6013
6295
|
return targets.length === 1 ? targets[0] : void 0;
|
|
6014
6296
|
}
|
|
6015
6297
|
function androidResDir2(manifestPath) {
|
|
6016
|
-
return
|
|
6298
|
+
return join27(dirname16(manifestPath), "res");
|
|
6017
6299
|
}
|
|
6018
6300
|
function androidManifestPath(app) {
|
|
6019
|
-
const androidDir =
|
|
6301
|
+
const androidDir = join27(appDir(app), "android");
|
|
6020
6302
|
if (!existsSync23(androidDir)) return void 0;
|
|
6021
|
-
const preferred =
|
|
6303
|
+
const preferred = join27(androidDir, `${app}-app`, "src", "main", "AndroidManifest.xml");
|
|
6022
6304
|
if (existsSync23(preferred)) return preferred;
|
|
6023
|
-
const candidates = readdirSync12(androidDir, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.endsWith("-app")).map((d) =>
|
|
6305
|
+
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
6306
|
return candidates.length === 1 ? candidates[0] : void 0;
|
|
6025
6307
|
}
|
|
6026
6308
|
function androidOptedIn2(manifestPath) {
|
|
@@ -6029,7 +6311,7 @@ function androidOptedIn2(manifestPath) {
|
|
|
6029
6311
|
}
|
|
6030
6312
|
function templateIconSha256() {
|
|
6031
6313
|
const cat = iosAssetCatalog2("_template");
|
|
6032
|
-
return cat ? fileSha256(
|
|
6314
|
+
return cat ? fileSha256(join27(cat, "AppIcon.appiconset", "icon_1024.png")) : null;
|
|
6033
6315
|
}
|
|
6034
6316
|
function placeholderHashes() {
|
|
6035
6317
|
const current = templateIconSha256();
|
|
@@ -6048,7 +6330,7 @@ function generationAllowed(app, configTs, opts = {}) {
|
|
|
6048
6330
|
return { allowed: true, reason: "declares an icon block" };
|
|
6049
6331
|
}
|
|
6050
6332
|
const iosCat = iosAssetCatalog2(app);
|
|
6051
|
-
const iosIcon = iosCat ?
|
|
6333
|
+
const iosIcon = iosCat ? join27(iosCat, "AppIcon.appiconset", "icon_1024.png") : void 0;
|
|
6052
6334
|
if (!iosIcon || !existsSync23(iosIcon)) return { allowed: true, reason: "no icon yet" };
|
|
6053
6335
|
const hash = fileSha256(iosIcon);
|
|
6054
6336
|
const placeholders = opts.placeholderHashes ?? placeholderHashes();
|
|
@@ -6074,7 +6356,7 @@ var init_plan2 = __esm({
|
|
|
6074
6356
|
|
|
6075
6357
|
// ../native-config/icon.ts
|
|
6076
6358
|
import { existsSync as existsSync24, readFileSync as readFileSync26 } from "node:fs";
|
|
6077
|
-
import { join as
|
|
6359
|
+
import { join as join28 } from "node:path";
|
|
6078
6360
|
function androidAdaptiveIconXml() {
|
|
6079
6361
|
return [
|
|
6080
6362
|
'<?xml version="1.0" encoding="utf-8"?>',
|
|
@@ -6101,7 +6383,7 @@ function androidIconArtifacts(app, configTs) {
|
|
|
6101
6383
|
if (!androidOptedIn2(manifest)) return [];
|
|
6102
6384
|
if (!generationAllowed(app, configTs).allowed) return [];
|
|
6103
6385
|
const res = androidResDir2(manifest);
|
|
6104
|
-
const foreground =
|
|
6386
|
+
const foreground = join28(res, "mipmap-mdpi", "ic_launcher_foreground.png");
|
|
6105
6387
|
if (!existsSync24(foreground)) {
|
|
6106
6388
|
throw new Error(
|
|
6107
6389
|
`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 +6393,11 @@ function androidIconArtifacts(app, configTs) {
|
|
|
6111
6393
|
const spec = iconSpec(app, configTs, id, resolveTokensPath(app, configTs).path);
|
|
6112
6394
|
return [
|
|
6113
6395
|
...ANDROID_ADAPTIVE_FILES.map((name) => ({
|
|
6114
|
-
path:
|
|
6396
|
+
path: join28(res, "mipmap-anydpi-v26", name),
|
|
6115
6397
|
content: androidAdaptiveIconXml()
|
|
6116
6398
|
})),
|
|
6117
6399
|
{
|
|
6118
|
-
path:
|
|
6400
|
+
path: join28(res, "values", ANDROID_ICON_BACKGROUND_FILE),
|
|
6119
6401
|
content: androidIconBackgroundXml(spec.background)
|
|
6120
6402
|
}
|
|
6121
6403
|
];
|
|
@@ -6350,7 +6632,7 @@ __export(gen_native_config_exports, {
|
|
|
6350
6632
|
watchInfoPlan: () => watchInfoPlan
|
|
6351
6633
|
});
|
|
6352
6634
|
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
|
|
6635
|
+
import { dirname as dirname17, join as join29 } from "node:path";
|
|
6354
6636
|
function parseStringArray(configTs, field) {
|
|
6355
6637
|
const m = new RegExp(`${field}:\\s*\\[([^\\]]*)\\]`).exec(configTs);
|
|
6356
6638
|
if (!m) return [];
|
|
@@ -6422,7 +6704,7 @@ function buildSet(capabilities, envelope = []) {
|
|
|
6422
6704
|
return [...new Set([...capabilities, ...envelope].map(catalogKey))].sort();
|
|
6423
6705
|
}
|
|
6424
6706
|
function loadOverrides(app) {
|
|
6425
|
-
const p =
|
|
6707
|
+
const p = join29(appDir(app), "native-config.overrides.json");
|
|
6426
6708
|
if (!existsSync25(p)) return {};
|
|
6427
6709
|
return JSON.parse(readFileSync27(p, "utf8"));
|
|
6428
6710
|
}
|
|
@@ -6479,14 +6761,14 @@ function endText(kind, label2, indent) {
|
|
|
6479
6761
|
return kind === "yaml" ? `${indent}# <<< ${label2} <<<` : `${indent}<!-- <<< ${label2} <<< -->`;
|
|
6480
6762
|
}
|
|
6481
6763
|
function hostAppliesDeferredWidgetActions(app) {
|
|
6482
|
-
const root =
|
|
6764
|
+
const root = join29(appDir(app), "ios");
|
|
6483
6765
|
if (!existsSync25(root)) return false;
|
|
6484
6766
|
const stack = [root];
|
|
6485
6767
|
while (stack.length) {
|
|
6486
6768
|
const dir = stack.pop();
|
|
6487
6769
|
for (const entry of readdirSync13(dir, { withFileTypes: true })) {
|
|
6488
6770
|
if (entry.name.startsWith(".") || entry.name === "GeneratedLiveActivity") continue;
|
|
6489
|
-
const path =
|
|
6771
|
+
const path = join29(dir, entry.name);
|
|
6490
6772
|
if (entry.isDirectory()) {
|
|
6491
6773
|
if (entry.name.endsWith(".xcodeproj") || entry.name === "build") continue;
|
|
6492
6774
|
stack.push(path);
|
|
@@ -6513,14 +6795,14 @@ function injectBlock(text2, kind, label2, render) {
|
|
|
6513
6795
|
return [...lines.slice(0, beginIdx), ...block, ...lines.slice(endIdx + 1)].join("\n");
|
|
6514
6796
|
}
|
|
6515
6797
|
function androidManifestPath2(app) {
|
|
6516
|
-
const androidDir =
|
|
6517
|
-
const preferred =
|
|
6798
|
+
const androidDir = join29(appDir(app), "android");
|
|
6799
|
+
const preferred = join29(androidDir, `${app}-app`, "src", "main", "AndroidManifest.xml");
|
|
6518
6800
|
if (existsSync25(preferred)) return preferred;
|
|
6519
|
-
const candidates = existsSync25(androidDir) ? readdirSync13(androidDir, { withFileTypes: true }).filter((d) => d.isDirectory() && d.name.endsWith("-app")).map((d) =>
|
|
6801
|
+
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
6802
|
return candidates.length === 1 ? candidates[0] : preferred;
|
|
6521
6803
|
}
|
|
6522
6804
|
function automotiveAppDescPath(app) {
|
|
6523
|
-
return
|
|
6805
|
+
return join29(dirname17(androidManifestPath2(app)), "res", "xml", "automotive_app_desc.xml");
|
|
6524
6806
|
}
|
|
6525
6807
|
function applyToFile(path, kind, label2, render, check) {
|
|
6526
6808
|
if (!existsSync25(path)) return { path, outcome: "skipped" };
|
|
@@ -6619,9 +6901,9 @@ function genNativeConfig(app, opts = {}) {
|
|
|
6619
6901
|
const plan = live2;
|
|
6620
6902
|
files.push(applyToFile(iosYml, "yaml", LABEL_LIVE_TARGET, (i) => plan.target.map((line) => i + line), check));
|
|
6621
6903
|
files.push(applyToFile(iosYml, "yaml", LABEL_LIVE_EMBED, (i) => plan.embed.map((line) => i + line), check));
|
|
6622
|
-
const source =
|
|
6904
|
+
const source = join29(dirname17(iosYml), LIVE_SOURCE_PATH);
|
|
6623
6905
|
files.push(plan.source ? applyWholeFile(source, plan.source, check) : removeWholeFile(source, check));
|
|
6624
|
-
const entitlements =
|
|
6906
|
+
const entitlements = join29(dirname17(iosYml), LIVE_ENTITLEMENTS_PATH);
|
|
6625
6907
|
files.push(plan.entitlements ? applyWholeFile(entitlements, plan.entitlements, check) : removeWholeFile(entitlements, check));
|
|
6626
6908
|
}
|
|
6627
6909
|
const iosSplashManaged = existsSync25(iosYml) && hasMarkers(readFileSync27(iosYml, "utf8"), "yaml", LABEL_IOS_SPLASH);
|
|
@@ -6759,7 +7041,8 @@ async function devModuleUrl(entry, dir) {
|
|
|
6759
7041
|
// intentionally point at `.ts` sources, which are only loadable under tsx.
|
|
6760
7042
|
umbrella: true,
|
|
6761
7043
|
resolveTsExtensions: true,
|
|
6762
|
-
absWorkingDir: dir
|
|
7044
|
+
absWorkingDir: dir,
|
|
7045
|
+
confineTo: dir
|
|
6763
7046
|
});
|
|
6764
7047
|
return pathToFileURL5(out).href;
|
|
6765
7048
|
}
|
|
@@ -6881,8 +7164,8 @@ var init_build_sha = __esm({
|
|
|
6881
7164
|
|
|
6882
7165
|
// ../../core/dev-server/src/app-assets.ts
|
|
6883
7166
|
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
|
|
7167
|
+
import { existsSync as existsSync27, lstatSync as lstatSync3, readFileSync as readFileSync29, readdirSync as readdirSync15, realpathSync as realpathSync3, statSync as statSync6 } from "node:fs";
|
|
7168
|
+
import { join as join30, resolve as resolve19, sep as sep5 } from "node:path";
|
|
6886
7169
|
function contentTypeFor(name) {
|
|
6887
7170
|
const ext = name.includes(".") ? name.slice(name.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
6888
7171
|
return CONTENT_TYPES[ext] ?? "application/octet-stream";
|
|
@@ -6896,19 +7179,19 @@ function assetSha256(bytes2) {
|
|
|
6896
7179
|
function findAssetsDir(appDir2) {
|
|
6897
7180
|
let declared;
|
|
6898
7181
|
try {
|
|
6899
|
-
declared = JSON.parse(readFileSync29(
|
|
7182
|
+
declared = JSON.parse(readFileSync29(join30(appDir2, "himalaya.content.json"), "utf8")).assets;
|
|
6900
7183
|
} catch {
|
|
6901
7184
|
declared = void 0;
|
|
6902
7185
|
}
|
|
6903
7186
|
const rel = typeof declared === "string" && declared ? declared : "assets";
|
|
6904
7187
|
const abs = resolve19(appDir2, rel);
|
|
6905
7188
|
const base = resolve19(appDir2);
|
|
6906
|
-
if (abs !== base && !abs.startsWith(base +
|
|
6907
|
-
return existsSync27(abs) &&
|
|
7189
|
+
if (abs !== base && !abs.startsWith(base + sep5)) return null;
|
|
7190
|
+
return existsSync27(abs) && statSync6(abs).isDirectory() ? abs : null;
|
|
6908
7191
|
}
|
|
6909
7192
|
function readOtaOnlyPatterns(appDir2) {
|
|
6910
7193
|
try {
|
|
6911
|
-
const raw = JSON.parse(readFileSync29(
|
|
7194
|
+
const raw = JSON.parse(readFileSync29(join30(appDir2, "assets.json"), "utf8"));
|
|
6912
7195
|
return Array.isArray(raw.otaOnly) ? raw.otaOnly.filter((p) => typeof p === "string") : [];
|
|
6913
7196
|
} catch {
|
|
6914
7197
|
return [];
|
|
@@ -6926,7 +7209,7 @@ function collectAssets(appDir2) {
|
|
|
6926
7209
|
const walk2 = (abs, prefix) => {
|
|
6927
7210
|
for (const entry of readdirSync15(abs, { withFileTypes: true })) {
|
|
6928
7211
|
if (entry.name.startsWith(".")) continue;
|
|
6929
|
-
const child =
|
|
7212
|
+
const child = join30(abs, entry.name);
|
|
6930
7213
|
const name = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
6931
7214
|
if (entry.isDirectory()) {
|
|
6932
7215
|
walk2(child, name);
|
|
@@ -6935,7 +7218,7 @@ function collectAssets(appDir2) {
|
|
|
6935
7218
|
if (!entry.isFile()) continue;
|
|
6936
7219
|
const ext = name.includes(".") ? name.slice(name.lastIndexOf(".") + 1).toLowerCase() : "";
|
|
6937
7220
|
const baked = !OTA_ONLY_BY_DEFAULT.has(ext) && !otaOnly.some((p) => matchesPattern(name, p));
|
|
6938
|
-
out.push({ name, path: child, bytes:
|
|
7221
|
+
out.push({ name, path: child, bytes: statSync6(child).size, contentType: contentTypeFor(name), baked });
|
|
6939
7222
|
}
|
|
6940
7223
|
};
|
|
6941
7224
|
walk2(dir, "");
|
|
@@ -6944,7 +7227,7 @@ function collectAssets(appDir2) {
|
|
|
6944
7227
|
function collectBrandFonts(appDir2) {
|
|
6945
7228
|
let faces;
|
|
6946
7229
|
try {
|
|
6947
|
-
faces = JSON.parse(readFileSync29(
|
|
7230
|
+
faces = JSON.parse(readFileSync29(join30(appDir2, "media/fonts/faces.json"), "utf8"));
|
|
6948
7231
|
} catch {
|
|
6949
7232
|
return [];
|
|
6950
7233
|
}
|
|
@@ -6957,11 +7240,11 @@ function collectBrandFonts(appDir2) {
|
|
|
6957
7240
|
const rel = typeof raw?.file === "string" ? raw.file : "";
|
|
6958
7241
|
if (!family || !postscriptName || !rel) continue;
|
|
6959
7242
|
if (rel.startsWith("/") || rel.split("/").includes("..")) continue;
|
|
6960
|
-
const path =
|
|
7243
|
+
const path = join30(appDir2, rel);
|
|
6961
7244
|
try {
|
|
6962
7245
|
if (!lstatSync3(path).isFile()) continue;
|
|
6963
|
-
const root =
|
|
6964
|
-
if (!
|
|
7246
|
+
const root = realpathSync3(appDir2);
|
|
7247
|
+
if (!realpathSync3(path).startsWith(root + sep5)) continue;
|
|
6965
7248
|
} catch {
|
|
6966
7249
|
continue;
|
|
6967
7250
|
}
|
|
@@ -8782,7 +9065,7 @@ var init_stable_ids = __esm({
|
|
|
8782
9065
|
// ../../core/dev-server/src/preview.ts
|
|
8783
9066
|
import { spawn as spawn2 } from "node:child_process";
|
|
8784
9067
|
import { createHash as createHash11 } from "node:crypto";
|
|
8785
|
-
import { existsSync as existsSync30, createReadStream, statSync as
|
|
9068
|
+
import { existsSync as existsSync30, createReadStream, statSync as statSync7, readFileSync as readFileSync33, renameSync, unlinkSync as unlinkSync2 } from "node:fs";
|
|
8786
9069
|
import { homedir as homedir5, tmpdir as tmpdir2 } from "node:os";
|
|
8787
9070
|
import { resolve as resolvePath, dirname as dirname20 } from "node:path";
|
|
8788
9071
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
@@ -9480,7 +9763,7 @@ function finalizeRecording(key2, rec) {
|
|
|
9480
9763
|
} catch {
|
|
9481
9764
|
}
|
|
9482
9765
|
}
|
|
9483
|
-
const sizeBytes = existsSync30(rec.localPath) ?
|
|
9766
|
+
const sizeBytes = existsSync30(rec.localPath) ? statSync7(rec.localPath).size : 0;
|
|
9484
9767
|
clips.set(rec.id, { path: rec.localPath, mime: rec.mime });
|
|
9485
9768
|
recordings.delete(key2);
|
|
9486
9769
|
return { sizeBytes };
|
|
@@ -9557,7 +9840,7 @@ async function handlePreviewClip(res, url) {
|
|
|
9557
9840
|
res.setHeader("content-type", "application/json");
|
|
9558
9841
|
return void res.end(JSON.stringify({ error: "clip_not_found", id }));
|
|
9559
9842
|
}
|
|
9560
|
-
const size =
|
|
9843
|
+
const size = statSync7(clip.path).size;
|
|
9561
9844
|
res.statusCode = 200;
|
|
9562
9845
|
res.setHeader("content-type", clip.mime);
|
|
9563
9846
|
res.setHeader("content-length", String(size));
|
|
@@ -14736,8 +15019,8 @@ function ensureCountUpRuntime() {
|
|
|
14736
15019
|
const neg = fixed.startsWith("-");
|
|
14737
15020
|
const body = neg ? fixed.slice(1) : fixed;
|
|
14738
15021
|
const [int, frac] = body.split(".");
|
|
14739
|
-
const
|
|
14740
|
-
return (neg ? "-" : "") +
|
|
15022
|
+
const sep11 = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
15023
|
+
return (neg ? "-" : "") + sep11 + (frac ? "." + frac : "");
|
|
14741
15024
|
};
|
|
14742
15025
|
const animateEl = (el) => {
|
|
14743
15026
|
const node = el;
|
|
@@ -21914,18 +22197,18 @@ var init_motion_flags = __esm({
|
|
|
21914
22197
|
|
|
21915
22198
|
// ../../core/dev-server/src/kits.ts
|
|
21916
22199
|
import { readdirSync as readdirSync16, readFileSync as readFileSync36 } from "node:fs";
|
|
21917
|
-
import { resolve as resolve25, join as
|
|
22200
|
+
import { resolve as resolve25, join as join31 } from "node:path";
|
|
21918
22201
|
import { fileURLToPath as fileURLToPath15 } from "node:url";
|
|
21919
22202
|
function listKits() {
|
|
21920
22203
|
return readdirSync16(CATALOG).filter((f) => f.endsWith(".json")).map((f) => {
|
|
21921
|
-
const { tokens, ...meta } = JSON.parse(readFileSync36(
|
|
22204
|
+
const { tokens, ...meta } = JSON.parse(readFileSync36(join31(CATALOG, f), "utf8"));
|
|
21922
22205
|
return meta;
|
|
21923
22206
|
});
|
|
21924
22207
|
}
|
|
21925
22208
|
function readKit(id) {
|
|
21926
22209
|
if (!/^[a-z0-9-]+$/.test(id)) return null;
|
|
21927
22210
|
try {
|
|
21928
|
-
return JSON.parse(readFileSync36(
|
|
22211
|
+
return JSON.parse(readFileSync36(join31(CATALOG, `${id}.json`), "utf8"));
|
|
21929
22212
|
} catch {
|
|
21930
22213
|
return null;
|
|
21931
22214
|
}
|
|
@@ -21934,7 +22217,7 @@ var ROOT5, CATALOG;
|
|
|
21934
22217
|
var init_kits = __esm({
|
|
21935
22218
|
"../../core/dev-server/src/kits.ts"() {
|
|
21936
22219
|
ROOT5 = resolve25(fileURLToPath15(new URL("../../..", import.meta.url)));
|
|
21937
|
-
CATALOG =
|
|
22220
|
+
CATALOG = join31(ROOT5, "stdlib/design-kits");
|
|
21938
22221
|
}
|
|
21939
22222
|
});
|
|
21940
22223
|
|
|
@@ -24137,7 +24420,7 @@ __export(config_exports, {
|
|
|
24137
24420
|
validateOverlayPatch: () => validateOverlayPatch
|
|
24138
24421
|
});
|
|
24139
24422
|
import { mkdirSync as mkdirSync15, readFileSync as readFileSync38, writeFileSync as writeFileSync12 } from "node:fs";
|
|
24140
|
-
import { dirname as dirname21, join as
|
|
24423
|
+
import { dirname as dirname21, join as join32, resolve as resolve27 } from "node:path";
|
|
24141
24424
|
import { fileURLToPath as fileURLToPath16 } from "node:url";
|
|
24142
24425
|
function strip(line) {
|
|
24143
24426
|
const h = line.indexOf("#");
|
|
@@ -24202,14 +24485,14 @@ function parseRevocationsYaml(text2) {
|
|
|
24202
24485
|
function appConfigPath(app, file, root = REPO_ROOT6) {
|
|
24203
24486
|
assertAppId(app, "appConfigPath");
|
|
24204
24487
|
for (const base of ["apps", "test-apps"]) {
|
|
24205
|
-
const p =
|
|
24488
|
+
const p = join32(root, base, app, file);
|
|
24206
24489
|
try {
|
|
24207
24490
|
readFileSync38(p);
|
|
24208
24491
|
return p;
|
|
24209
24492
|
} catch {
|
|
24210
24493
|
}
|
|
24211
24494
|
}
|
|
24212
|
-
return
|
|
24495
|
+
return join32(root, "apps", app, file);
|
|
24213
24496
|
}
|
|
24214
24497
|
function serializeRolloutYaml(cfg) {
|
|
24215
24498
|
const lines = [`app: ${cfg.app}`, "rings:"];
|
|
@@ -24353,7 +24636,7 @@ var init_config2 = __esm({
|
|
|
24353
24636
|
import { createServer as createServer2 } from "node:http";
|
|
24354
24637
|
import { readFile as readFile2, stat } from "node:fs/promises";
|
|
24355
24638
|
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
|
|
24639
|
+
import { extname, resolve as resolve28, normalize as normalize3, sep as sep6, join as join33 } from "node:path";
|
|
24357
24640
|
import { createHash as createHash15, randomUUID } from "node:crypto";
|
|
24358
24641
|
import { fileURLToPath as fileURLToPath17, pathToFileURL as pathToFileURL6 } from "node:url";
|
|
24359
24642
|
function deepMerge2(base, patch) {
|
|
@@ -24528,7 +24811,7 @@ async function runScreenDiagnostics(state, screenId, descriptor) {
|
|
|
24528
24811
|
}
|
|
24529
24812
|
function servedFontFaces(appDir2, tokens) {
|
|
24530
24813
|
try {
|
|
24531
|
-
const policyPath =
|
|
24814
|
+
const policyPath = join33(appDir2, "fonts.json");
|
|
24532
24815
|
const policy = existsSync33(policyPath) ? JSON.parse(readFileSync39(policyPath, "utf8")) : {};
|
|
24533
24816
|
const plan = planFonts(tokens, policy);
|
|
24534
24817
|
if (plan.families.length === 0) return void 0;
|
|
@@ -25171,7 +25454,7 @@ function startBundleSourceWatcher(state) {
|
|
|
25171
25454
|
try {
|
|
25172
25455
|
const watcher = watch(TIER5_SRC_ROOT, { persistent: false, recursive: true }, (_event, filename) => {
|
|
25173
25456
|
if (!filename || !/\.(ts|tsx)$/.test(filename)) return;
|
|
25174
|
-
const name = filename.split(
|
|
25457
|
+
const name = filename.split(sep6)[0];
|
|
25175
25458
|
if (!name || name.startsWith(".")) return;
|
|
25176
25459
|
pending.add(name);
|
|
25177
25460
|
if (timer) clearTimeout(timer);
|
|
@@ -25201,7 +25484,7 @@ async function reloadAppModule(state, opts) {
|
|
|
25201
25484
|
const outfile = resolve28(HMR_TMP_DIR, `${current.name}-${++appReloadSeq}.mjs`);
|
|
25202
25485
|
try {
|
|
25203
25486
|
const lib = await import(pathToFileURL6(resolve28(TIER5_SRC_ROOT, "build-lib.mjs")).href);
|
|
25204
|
-
await lib.buildAppEntry(entry, outfile);
|
|
25487
|
+
await lib.buildAppEntry(entry, outfile, { confineTo: current.dir });
|
|
25205
25488
|
const mod = await import(pathToFileURL6(outfile).href);
|
|
25206
25489
|
const next = mod.default;
|
|
25207
25490
|
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 +25569,7 @@ function startAppSourceWatcher(state) {
|
|
|
25286
25569
|
try {
|
|
25287
25570
|
const watcher = watch(appDir2, { persistent: false, recursive: true }, (_event, filename) => {
|
|
25288
25571
|
if (!filename) return;
|
|
25289
|
-
const rel = String(filename).split(
|
|
25572
|
+
const rel = String(filename).split(sep6).join("/");
|
|
25290
25573
|
if (!classifyAppPath(rel)) return;
|
|
25291
25574
|
pending.add(rel);
|
|
25292
25575
|
if (timer) clearTimeout(timer);
|
|
@@ -27448,7 +27731,7 @@ __export(build_exports2, {
|
|
|
27448
27731
|
});
|
|
27449
27732
|
import { createHash as createHash18 } from "node:crypto";
|
|
27450
27733
|
import { readFileSync as readFileSync40, readdirSync as readdirSync18, existsSync as existsSync34 } from "node:fs";
|
|
27451
|
-
import { dirname as dirname22, join as
|
|
27734
|
+
import { dirname as dirname22, join as join34, resolve as resolve29 } from "node:path";
|
|
27452
27735
|
import { fileURLToPath as fileURLToPath18 } from "node:url";
|
|
27453
27736
|
import { createRequire as createRequire2 } from "node:module";
|
|
27454
27737
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
@@ -27486,7 +27769,7 @@ function l10nLintOptions(locale, appDir2) {
|
|
|
27486
27769
|
const tags = (locale.translations ?? []).filter((t) => t !== locale.default);
|
|
27487
27770
|
const catalog = /* @__PURE__ */ new Set();
|
|
27488
27771
|
for (const tag of tags) {
|
|
27489
|
-
const path =
|
|
27772
|
+
const path = join34(appDir2, "l10n", `${tag}.json`);
|
|
27490
27773
|
if (!existsSync34(path)) continue;
|
|
27491
27774
|
try {
|
|
27492
27775
|
const parsed = JSON.parse(readFileSync40(path, "utf8"));
|
|
@@ -27583,7 +27866,7 @@ function shellSha(root = REPO_ROOT7) {
|
|
|
27583
27866
|
function isMonorepoCheckout(dir) {
|
|
27584
27867
|
try {
|
|
27585
27868
|
const top = execFileSync4("git", ["rev-parse", "--show-toplevel"], { cwd: dir, stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
27586
|
-
return top.length > 0 && existsSync34(
|
|
27869
|
+
return top.length > 0 && existsSync34(join34(top, "core", "schema", "core.proto"));
|
|
27587
27870
|
} catch {
|
|
27588
27871
|
return false;
|
|
27589
27872
|
}
|
|
@@ -27813,7 +28096,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
27813
28096
|
if (addrCache.has(name)) return addrCache.get(name);
|
|
27814
28097
|
let bytes2;
|
|
27815
28098
|
try {
|
|
27816
|
-
bytes2 = readFileSync40(
|
|
28099
|
+
bytes2 = readFileSync40(join34(tier5Dir, `${name}.bundle.js`));
|
|
27817
28100
|
} catch {
|
|
27818
28101
|
return null;
|
|
27819
28102
|
}
|
|
@@ -27834,7 +28117,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
27834
28117
|
const MAX_AUTHORING_DOC_BYTES = 128 * 1024;
|
|
27835
28118
|
if (store.putDoc) {
|
|
27836
28119
|
for (const [name, file] of [["spec", "SPEC.md"], ["mobile-ux", "MOBILE-UX.md"]]) {
|
|
27837
|
-
const path =
|
|
28120
|
+
const path = join34(preloaded.dir, file);
|
|
27838
28121
|
if (!existsSync34(path)) continue;
|
|
27839
28122
|
const bytes2 = readFileSync40(path);
|
|
27840
28123
|
if (bytes2.length === 0 || bytes2.length > MAX_AUTHORING_DOC_BYTES) {
|
|
@@ -27894,7 +28177,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
27894
28177
|
const canEmitFonts = hasVendoredFloor();
|
|
27895
28178
|
try {
|
|
27896
28179
|
const appTokens = readTokensForLint(preloaded) ?? {};
|
|
27897
|
-
const policy = existsSync34(
|
|
28180
|
+
const policy = existsSync34(join34(preloaded.dir, "fonts.json")) ? JSON.parse(readFileSync40(join34(preloaded.dir, "fonts.json"), "utf8")) : {};
|
|
27898
28181
|
fontPlan = planFonts(appTokens, policy);
|
|
27899
28182
|
} catch (err) {
|
|
27900
28183
|
throw new Error(
|
|
@@ -28359,7 +28642,7 @@ async function buildFunctionsOnlyRelease(preloaded, dest) {
|
|
|
28359
28642
|
await store.reset(app);
|
|
28360
28643
|
const sources = {};
|
|
28361
28644
|
for (const definition of config.functions.functions) {
|
|
28362
|
-
const candidates = [".ts", ".js", ".mts", ".mjs"].map((extension) =>
|
|
28645
|
+
const candidates = [".ts", ".js", ".mts", ".mjs"].map((extension) => join34(preloaded.dir, "functions", `${definition.name}${extension}`));
|
|
28363
28646
|
const source = candidates.find((candidate) => existsSync34(candidate));
|
|
28364
28647
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
28365
28648
|
sources[definition.name] = readFileSync40(source, "utf8");
|
|
@@ -28390,7 +28673,7 @@ async function buildFunctionsOnlyRelease(preloaded, dest) {
|
|
|
28390
28673
|
return { manifest, failedToBuild: [], missingBundles: [], auth: {} };
|
|
28391
28674
|
}
|
|
28392
28675
|
function listBuildableApps() {
|
|
28393
|
-
const appsDir =
|
|
28676
|
+
const appsDir = join34(REPO_ROOT7, "apps");
|
|
28394
28677
|
return readdirSync18(appsDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("_")).map((d) => d.name);
|
|
28395
28678
|
}
|
|
28396
28679
|
var BAKE_OFFLINE_BASE, KNOWN_ICON_NAMES, KNOWN_ICONS, REPO_ROOT7, TIER5_DIR, requireFromHere, SOURCEMAP_ON_DEMAND_PATH, BAKED_SERVER_BASE_URL;
|
|
@@ -28421,9 +28704,9 @@ var init_build3 = __esm({
|
|
|
28421
28704
|
KNOWN_ICON_NAMES = [...ICON_NAMES].sort();
|
|
28422
28705
|
KNOWN_ICONS = new Set(KNOWN_ICON_NAMES);
|
|
28423
28706
|
REPO_ROOT7 = resolve29(dirname22(fileURLToPath18(import.meta.url)), "../..");
|
|
28424
|
-
TIER5_DIR =
|
|
28707
|
+
TIER5_DIR = join34(REPO_ROOT7, "core/dev-server/tier5-bundles");
|
|
28425
28708
|
requireFromHere = createRequire2(import.meta.url);
|
|
28426
|
-
SOURCEMAP_ON_DEMAND_PATH =
|
|
28709
|
+
SOURCEMAP_ON_DEMAND_PATH = join34(REPO_ROOT7, "core/dev-server/tier5-bundles-src/sourcemap-on-demand.mjs");
|
|
28427
28710
|
BAKED_SERVER_BASE_URL = "http://baked.himalaya.invalid";
|
|
28428
28711
|
}
|
|
28429
28712
|
});
|
|
@@ -28470,6 +28753,133 @@ var init_net_scenario = __esm({
|
|
|
28470
28753
|
}
|
|
28471
28754
|
});
|
|
28472
28755
|
|
|
28756
|
+
// ../../core/dev-server/src/crawl-relations.ts
|
|
28757
|
+
function inversePartner(action, declared) {
|
|
28758
|
+
if (/^toggle/i.test(action)) return null;
|
|
28759
|
+
const candidates = [];
|
|
28760
|
+
if (/^un[A-Z_a-z]/.test(action)) {
|
|
28761
|
+
candidates.push(lowerFirst(action.slice(2)), action.slice(2));
|
|
28762
|
+
} else {
|
|
28763
|
+
candidates.push("un" + action, "un" + upperFirst(action));
|
|
28764
|
+
}
|
|
28765
|
+
for (const c of candidates) if (c !== action && declared.includes(c)) return c;
|
|
28766
|
+
for (const [a, b] of PREFIX_PAIRS) {
|
|
28767
|
+
for (const [from, to] of [
|
|
28768
|
+
[a, b],
|
|
28769
|
+
[b, a]
|
|
28770
|
+
]) {
|
|
28771
|
+
if (!action.toLowerCase().startsWith(from)) continue;
|
|
28772
|
+
const rest = action.slice(from.length);
|
|
28773
|
+
for (const c of [to + rest, to + upperFirst(rest), to]) {
|
|
28774
|
+
if (c !== action && declared.includes(c)) return c;
|
|
28775
|
+
}
|
|
28776
|
+
}
|
|
28777
|
+
}
|
|
28778
|
+
return null;
|
|
28779
|
+
}
|
|
28780
|
+
function isUndoAction(action) {
|
|
28781
|
+
if (/^toggle/i.test(action)) return false;
|
|
28782
|
+
if (/^un[A-Z]/.test(action) || /^un[a-z]/.test(action)) return true;
|
|
28783
|
+
return PREFIX_PAIRS.some(([, undo]) => action.toLowerCase().startsWith(undo));
|
|
28784
|
+
}
|
|
28785
|
+
function isOptionSelection(params) {
|
|
28786
|
+
return Object.keys(params).some((k) => /^(selected|tab|segment|mode|scope)/i.test(k) || /Id$/.test(k) || k === "id");
|
|
28787
|
+
}
|
|
28788
|
+
function stripVolatile(value, depth = 0) {
|
|
28789
|
+
if (depth > 8 || value === null || typeof value !== "object") return value;
|
|
28790
|
+
if (Array.isArray(value)) return value.map((v) => stripVolatile(v, depth + 1));
|
|
28791
|
+
const out = {};
|
|
28792
|
+
for (const k of Object.keys(value).sort()) {
|
|
28793
|
+
if (VOLATILE_KEY.test(k)) continue;
|
|
28794
|
+
out[k] = stripVolatile(value[k], depth + 1);
|
|
28795
|
+
}
|
|
28796
|
+
return out;
|
|
28797
|
+
}
|
|
28798
|
+
function relationalSignature(state) {
|
|
28799
|
+
return JSON.stringify(stripVolatile(state));
|
|
28800
|
+
}
|
|
28801
|
+
function listLengths(state, depth = 4) {
|
|
28802
|
+
const out = {};
|
|
28803
|
+
const walk2 = (node, path, left) => {
|
|
28804
|
+
if (left < 0 || node === null || typeof node !== "object") return;
|
|
28805
|
+
if (Array.isArray(node)) {
|
|
28806
|
+
out[path] = node.length;
|
|
28807
|
+
return;
|
|
28808
|
+
}
|
|
28809
|
+
for (const [k, v] of Object.entries(node)) {
|
|
28810
|
+
walk2(v, path ? `${path}.${k}` : k, left - 1);
|
|
28811
|
+
}
|
|
28812
|
+
};
|
|
28813
|
+
walk2(state, "", depth);
|
|
28814
|
+
return out;
|
|
28815
|
+
}
|
|
28816
|
+
function summarizeDiff(aSig, bSig, limit = 3) {
|
|
28817
|
+
let a;
|
|
28818
|
+
let b;
|
|
28819
|
+
try {
|
|
28820
|
+
a = JSON.parse(aSig);
|
|
28821
|
+
b = JSON.parse(bSig);
|
|
28822
|
+
} catch {
|
|
28823
|
+
return aSig === bSig ? "" : "states differ (unparseable signature)";
|
|
28824
|
+
}
|
|
28825
|
+
const diffs = [];
|
|
28826
|
+
const brief = (v) => {
|
|
28827
|
+
const t = JSON.stringify(v);
|
|
28828
|
+
if (t === void 0) return "undefined";
|
|
28829
|
+
return t.length > 80 ? `${t.slice(0, 77)}\u2026` : t;
|
|
28830
|
+
};
|
|
28831
|
+
const walk2 = (x, y, path) => {
|
|
28832
|
+
if (diffs.length >= limit) return;
|
|
28833
|
+
const bothObjects = x !== null && y !== null && typeof x === "object" && typeof y === "object" && !Array.isArray(x) && !Array.isArray(y);
|
|
28834
|
+
if (bothObjects) {
|
|
28835
|
+
for (const k of /* @__PURE__ */ new Set([...Object.keys(x), ...Object.keys(y)])) {
|
|
28836
|
+
walk2(x[k], y[k], path ? `${path}.${k}` : k);
|
|
28837
|
+
}
|
|
28838
|
+
return;
|
|
28839
|
+
}
|
|
28840
|
+
if (Array.isArray(x) && Array.isArray(y)) {
|
|
28841
|
+
if (x.length !== y.length) {
|
|
28842
|
+
diffs.push(`${path || "state"}: ${x.length} \u2192 ${y.length} items`);
|
|
28843
|
+
return;
|
|
28844
|
+
}
|
|
28845
|
+
for (let i = 0; i < x.length && diffs.length < limit; i++) walk2(x[i], y[i], `${path}[${i}]`);
|
|
28846
|
+
return;
|
|
28847
|
+
}
|
|
28848
|
+
const xs = brief(x);
|
|
28849
|
+
const ys = brief(y);
|
|
28850
|
+
if (xs !== ys) diffs.push(`${path || "state"}: ${xs} \u2192 ${ys}`);
|
|
28851
|
+
};
|
|
28852
|
+
walk2(a, b, "");
|
|
28853
|
+
return diffs.slice(0, limit).join("; ");
|
|
28854
|
+
}
|
|
28855
|
+
var PREFIX_PAIRS, upperFirst, lowerFirst, REFRESH_ACTION, LOAD_MORE_ACTION, FILTER_ACTION, VOLATILE_KEY;
|
|
28856
|
+
var init_crawl_relations = __esm({
|
|
28857
|
+
"../../core/dev-server/src/crawl-relations.ts"() {
|
|
28858
|
+
PREFIX_PAIRS = [
|
|
28859
|
+
["add", "remove"],
|
|
28860
|
+
["add", "delete"],
|
|
28861
|
+
// NOT ["start", "stop"]. Measured 2026-09-16: it produced 2 warnings on unmutated, correct code
|
|
28862
|
+
// (voice-journal, `start → stop` and `startBackground → stop`, both leaving
|
|
28863
|
+
// `statusLabel: "Ready" → "Ready — recording stopped"`). start/stop is a LIFECYCLE pair, not an
|
|
28864
|
+
// algebraic inverse: stopping does not unmake the recording that was started, and an app is right
|
|
28865
|
+
// to say so. Only pairs where the undo genuinely restores the prior value belong here.
|
|
28866
|
+
["open", "close"],
|
|
28867
|
+
["show", "hide"],
|
|
28868
|
+
["expand", "collapse"],
|
|
28869
|
+
["select", "deselect"],
|
|
28870
|
+
["increment", "decrement"],
|
|
28871
|
+
["follow", "unfollow"],
|
|
28872
|
+
["save", "unsave"]
|
|
28873
|
+
];
|
|
28874
|
+
upperFirst = (s) => s ? s[0].toUpperCase() + s.slice(1) : s;
|
|
28875
|
+
lowerFirst = (s) => s ? s[0].toLowerCase() + s.slice(1) : s;
|
|
28876
|
+
REFRESH_ACTION = /^(refresh|reload|retry|sync|pullToRefresh)/i;
|
|
28877
|
+
LOAD_MORE_ACTION = /^(loadMore|nextPage|fetchMore)|^more$|More$|NextPage$/;
|
|
28878
|
+
FILTER_ACTION = /^(filter|search|query|sort)|(Filter|Search|Query|Sort)/;
|
|
28879
|
+
VOLATILE_KEY = /^_|^(id|uuid|guid|nonce|seed|token|timestamp|now|revision|etag)$|(Id|ID|Uuid|Guid|Nonce|Seed|Token|At|Timestamp|Ms|Revision|ETag)$/;
|
|
28880
|
+
}
|
|
28881
|
+
});
|
|
28882
|
+
|
|
28473
28883
|
// ../../core/dev-server/src/screen-crawl.ts
|
|
28474
28884
|
var screen_crawl_exports = {};
|
|
28475
28885
|
__export(screen_crawl_exports, {
|
|
@@ -28482,6 +28892,7 @@ __export(screen_crawl_exports, {
|
|
|
28482
28892
|
crawlScreenDeep: () => crawlScreenDeep,
|
|
28483
28893
|
crawlScreenHostile: () => crawlScreenHostile,
|
|
28484
28894
|
crawlScreenJourney: () => crawlScreenJourney,
|
|
28895
|
+
crawlScreenRelations: () => crawlScreenRelations,
|
|
28485
28896
|
crawlSignature: () => crawlSignature,
|
|
28486
28897
|
deepStateSignature: () => deepStateSignature,
|
|
28487
28898
|
emptiedArrays: () => emptiedArrays,
|
|
@@ -28492,6 +28903,7 @@ __export(screen_crawl_exports, {
|
|
|
28492
28903
|
parseWorkerAction: () => parseWorkerAction,
|
|
28493
28904
|
recordScreenTraffic: () => recordScreenTraffic,
|
|
28494
28905
|
rootOnAppear: () => rootOnAppear,
|
|
28906
|
+
snapshot: () => snapshot,
|
|
28495
28907
|
structuralSignature: () => structuralSignature,
|
|
28496
28908
|
unverifiableNodes: () => unverifiableNodes,
|
|
28497
28909
|
workerArgs: () => workerArgs
|
|
@@ -29727,7 +30139,209 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
29727
30139
|
return { findings: dedupe(findings), nodesVisited: visited.size, dispatches, capped };
|
|
29728
30140
|
});
|
|
29729
30141
|
}
|
|
29730
|
-
|
|
30142
|
+
function effectiveSiteForRow(site, row) {
|
|
30143
|
+
const merged = { ...site.params ?? {}, ...site.args ?? {} };
|
|
30144
|
+
const substituted = {};
|
|
30145
|
+
for (const [k, v] of Object.entries(merged)) {
|
|
30146
|
+
substituted[k] = typeof v === "string" && v.startsWith("$item.") ? pathValue(row, v.slice("$item.".length)) : v === "$item" ? row : v;
|
|
30147
|
+
}
|
|
30148
|
+
return { ...site, params: substituted, args: void 0 };
|
|
30149
|
+
}
|
|
30150
|
+
function isRowBound(site) {
|
|
30151
|
+
const payload = { ...site.params ?? {}, ...site.args ?? {} };
|
|
30152
|
+
return Object.values(payload).some((v) => typeof v === "string" && (v === "$item" || v.startsWith("$item.")));
|
|
30153
|
+
}
|
|
30154
|
+
function collectItemsPaths(node, out = /* @__PURE__ */ new Set()) {
|
|
30155
|
+
if (!node || typeof node !== "object") return out;
|
|
30156
|
+
if (Array.isArray(node)) {
|
|
30157
|
+
for (const n of node) collectItemsPaths(n, out);
|
|
30158
|
+
return out;
|
|
30159
|
+
}
|
|
30160
|
+
const rec = node;
|
|
30161
|
+
const body = rec.body;
|
|
30162
|
+
if (body && typeof body === "object" && typeof body.type === "string" && body.props && typeof body.props === "object") {
|
|
30163
|
+
const itemsPath = body.props.itemsPath;
|
|
30164
|
+
if (typeof itemsPath === "string") out.add(itemsPath);
|
|
30165
|
+
}
|
|
30166
|
+
for (const v of Object.values(rec)) collectItemsPaths(v, out);
|
|
30167
|
+
return out;
|
|
30168
|
+
}
|
|
30169
|
+
function newlyAddedRow(before, after, itemsPath) {
|
|
30170
|
+
if (!itemsPath || itemsPath === UNTRACKED_ITEMS) return null;
|
|
30171
|
+
const rowsOf = (s) => {
|
|
30172
|
+
const provider = new FakeServiceProvider(s);
|
|
30173
|
+
const v = resolveSiteRows(itemsPath, (p) => provider.value(p));
|
|
30174
|
+
return Array.isArray(v) ? v.filter((r) => r && typeof r === "object") : [];
|
|
30175
|
+
};
|
|
30176
|
+
const seen = new Set(rowsOf(before).map((r) => relationalSignature(r)));
|
|
30177
|
+
const fresh = rowsOf(after).filter((r) => !seen.has(relationalSignature(r)));
|
|
30178
|
+
return fresh.length === 1 ? fresh[0] : null;
|
|
30179
|
+
}
|
|
30180
|
+
async function crawlScreenRelations(opts) {
|
|
30181
|
+
return withSwallowedRejections(async () => {
|
|
30182
|
+
const { screenId, descriptor, bundleJs } = opts;
|
|
30183
|
+
const findings = [];
|
|
30184
|
+
const byKind = { inverse: 0, refresh: 0, loadMore: 0, filter: 0 };
|
|
30185
|
+
let checked = 0;
|
|
30186
|
+
if (!bundleJs) return { findings, checked, byKind };
|
|
30187
|
+
const layered = layeredTransport({ rules: opts.rules, cmsSeed: opts.cmsSeed, canned: opts.canned });
|
|
30188
|
+
const wixCall = opts.transportWrap ? opts.transportWrap(layered.call) : layered.call;
|
|
30189
|
+
const sites = actionSitesForDescriptor(descriptor).filter(
|
|
30190
|
+
(s) => parseWorkerAction(s.actionId) && !opts.skipAction?.(s.actionId, s.componentId)
|
|
30191
|
+
);
|
|
30192
|
+
const nameOf = (s) => parseWorkerAction(s.actionId).action;
|
|
30193
|
+
const serviceOf = (s) => parseWorkerAction(s.actionId).service;
|
|
30194
|
+
const boot = () => bootScreenWorker({
|
|
30195
|
+
bundleJs,
|
|
30196
|
+
descriptor,
|
|
30197
|
+
wixCall,
|
|
30198
|
+
screenId,
|
|
30199
|
+
inputOverride: opts.inputOverride,
|
|
30200
|
+
budgetMs: opts.budgetMs,
|
|
30201
|
+
clock: opts.clock,
|
|
30202
|
+
seed: opts.seed,
|
|
30203
|
+
localDbSchema: opts.localDbSchema,
|
|
30204
|
+
...opts.evaluator ? { evaluator: opts.evaluator } : {}
|
|
30205
|
+
});
|
|
30206
|
+
const replay = async (path, rowFor = () => null) => {
|
|
30207
|
+
const w = await boot();
|
|
30208
|
+
try {
|
|
30209
|
+
if (w.errors.length) return null;
|
|
30210
|
+
let prev = snapshot(w).state;
|
|
30211
|
+
const bootState = prev;
|
|
30212
|
+
for (const [i, site] of path.entries()) {
|
|
30213
|
+
const parsed = parseWorkerAction(site.actionId);
|
|
30214
|
+
const h = w.handles[parsed.service];
|
|
30215
|
+
if (!h || !h.actionNames().includes(parsed.action)) return null;
|
|
30216
|
+
const pinned = rowFor(i, bootState, prev);
|
|
30217
|
+
if (pinned === UNBINDABLE_ROW) return null;
|
|
30218
|
+
const eff = pinned ? effectiveSiteForRow(site, pinned) : effectiveSiteFor(site, prev);
|
|
30219
|
+
if (!eff) return null;
|
|
30220
|
+
try {
|
|
30221
|
+
await h.dispatch(parsed.action, ...workerArgs(eff));
|
|
30222
|
+
} catch {
|
|
30223
|
+
return null;
|
|
30224
|
+
}
|
|
30225
|
+
for (let k = 0; k < 20; k++) await yieldMacrotask();
|
|
30226
|
+
if (w.errors.length) return null;
|
|
30227
|
+
prev = snapshot(w).state;
|
|
30228
|
+
}
|
|
30229
|
+
return prev;
|
|
30230
|
+
} finally {
|
|
30231
|
+
w.dispose();
|
|
30232
|
+
}
|
|
30233
|
+
};
|
|
30234
|
+
const base = await replay([]);
|
|
30235
|
+
if (!base || Object.values(base).some(hasOwnError)) return { findings, checked, byKind };
|
|
30236
|
+
const baseSig = relationalSignature(base);
|
|
30237
|
+
const baseLens = listLengths(base);
|
|
30238
|
+
const listPathOf = (itemsPath) => {
|
|
30239
|
+
if (!itemsPath || itemsPath === UNTRACKED_ITEMS || itemsPath.includes("[]")) return null;
|
|
30240
|
+
const m = /^\$service:(.+)$/.exec(itemsPath);
|
|
30241
|
+
return m && baseLens[m[1]] !== void 0 ? m[1] : null;
|
|
30242
|
+
};
|
|
30243
|
+
const screenListPaths = [
|
|
30244
|
+
...new Set(
|
|
30245
|
+
[...collectItemsPaths(descriptor)].map(listPathOf).filter((x) => x !== null)
|
|
30246
|
+
)
|
|
30247
|
+
];
|
|
30248
|
+
const trig = (s) => ({ tap: s.componentId, key: s.key, action: s.actionId });
|
|
30249
|
+
for (const s of sites.filter((s2) => REFRESH_ACTION.test(nameOf(s2)) || s2.key === "onPullToRefresh")) {
|
|
30250
|
+
const after = await replay([s]);
|
|
30251
|
+
if (!after) continue;
|
|
30252
|
+
checked++;
|
|
30253
|
+
byKind.refresh++;
|
|
30254
|
+
const sig = relationalSignature(after);
|
|
30255
|
+
if (sig !== baseSig) {
|
|
30256
|
+
findings.push({
|
|
30257
|
+
screen: screenId,
|
|
30258
|
+
trigger: trig(s),
|
|
30259
|
+
invariant: "refresh-not-idempotent",
|
|
30260
|
+
severity: "warning",
|
|
30261
|
+
axis: "relation",
|
|
30262
|
+
message: `${nameOf(s)} from a fresh boot settles on a different state than the boot itself, under identical data: ${summarizeDiff(baseSig, sig)}`,
|
|
30263
|
+
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"
|
|
30264
|
+
});
|
|
30265
|
+
}
|
|
30266
|
+
}
|
|
30267
|
+
for (const s of sites.filter((s2) => LOAD_MORE_ACTION.test(nameOf(s2)) || s2.key === "onLoadMore")) {
|
|
30268
|
+
const target = listPathOf(s.itemsPath);
|
|
30269
|
+
const after = target ? await replay([s]) : null;
|
|
30270
|
+
if (!after) continue;
|
|
30271
|
+
checked++;
|
|
30272
|
+
byKind.loadMore++;
|
|
30273
|
+
for (const [p, n] of Object.entries(listLengths(after))) {
|
|
30274
|
+
if (p === target && baseLens[p] !== void 0 && n < baseLens[p]) {
|
|
30275
|
+
findings.push({
|
|
30276
|
+
screen: screenId,
|
|
30277
|
+
trigger: trig(s),
|
|
30278
|
+
invariant: "list-shrank-on-load-more",
|
|
30279
|
+
severity: "warning",
|
|
30280
|
+
axis: "relation",
|
|
30281
|
+
at: p,
|
|
30282
|
+
actual: `${baseLens[p]} \u2192 ${n}`,
|
|
30283
|
+
message: `${nameOf(s)} shrank ${p} from ${baseLens[p]} to ${n} rows \u2014 a "load more" that replaces the page instead of appending it`,
|
|
30284
|
+
hint: "append the new page to the existing rows (and de-duplicate by id); the user scrolled to see MORE"
|
|
30285
|
+
});
|
|
30286
|
+
}
|
|
30287
|
+
}
|
|
30288
|
+
}
|
|
30289
|
+
for (const s of sites.filter((s2) => FILTER_ACTION.test(nameOf(s2)) && !isOptionSelection({ ...s2.params, ...s2.args }))) {
|
|
30290
|
+
if (screenListPaths.length !== 1) continue;
|
|
30291
|
+
const after = await replay([s]);
|
|
30292
|
+
if (!after) continue;
|
|
30293
|
+
checked++;
|
|
30294
|
+
byKind.filter++;
|
|
30295
|
+
for (const [p, n] of Object.entries(listLengths(after))) {
|
|
30296
|
+
if (screenListPaths.includes(p) && baseLens[p] !== void 0 && n > baseLens[p]) {
|
|
30297
|
+
findings.push({
|
|
30298
|
+
screen: screenId,
|
|
30299
|
+
trigger: trig(s),
|
|
30300
|
+
invariant: "list-grew-on-filter",
|
|
30301
|
+
severity: "warning",
|
|
30302
|
+
axis: "relation",
|
|
30303
|
+
at: p,
|
|
30304
|
+
actual: `${baseLens[p]} \u2192 ${n}`,
|
|
30305
|
+
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`,
|
|
30306
|
+
hint: "filter from the FULL set you keep aside, and assign the narrowed result \u2014 not a concatenation"
|
|
30307
|
+
});
|
|
30308
|
+
}
|
|
30309
|
+
}
|
|
30310
|
+
}
|
|
30311
|
+
const declaredNames = sites.map(nameOf);
|
|
30312
|
+
for (const a of sites) {
|
|
30313
|
+
const partner = inversePartner(nameOf(a), declaredNames);
|
|
30314
|
+
if (!partner) continue;
|
|
30315
|
+
if (isUndoAction(nameOf(a))) continue;
|
|
30316
|
+
const b = sites.find((s) => nameOf(s) === partner && serviceOf(s) === serviceOf(a) && s !== a);
|
|
30317
|
+
if (!b) continue;
|
|
30318
|
+
const undoIsRowBound = isRowBound(b);
|
|
30319
|
+
const after = await replay([a, b], (i, bootState, prev) => {
|
|
30320
|
+
if (i !== 1) return null;
|
|
30321
|
+
const row = newlyAddedRow(bootState, prev, b.itemsPath);
|
|
30322
|
+
if (row) return row;
|
|
30323
|
+
return undoIsRowBound ? UNBINDABLE_ROW : null;
|
|
30324
|
+
});
|
|
30325
|
+
if (!after) continue;
|
|
30326
|
+
checked++;
|
|
30327
|
+
byKind.inverse++;
|
|
30328
|
+
const sig = relationalSignature(after);
|
|
30329
|
+
if (sig !== baseSig) {
|
|
30330
|
+
findings.push({
|
|
30331
|
+
screen: screenId,
|
|
30332
|
+
trigger: trig(b),
|
|
30333
|
+
invariant: "inverse-pair-diverges",
|
|
30334
|
+
severity: "warning",
|
|
30335
|
+
axis: "relation",
|
|
30336
|
+
message: `${nameOf(a)} \u2192 ${nameOf(b)} does not return to the boot state: ${summarizeDiff(baseSig, sig)}`,
|
|
30337
|
+
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`
|
|
30338
|
+
});
|
|
30339
|
+
}
|
|
30340
|
+
}
|
|
30341
|
+
return { findings: dedupe(findings), checked, byKind };
|
|
30342
|
+
});
|
|
30343
|
+
}
|
|
30344
|
+
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
30345
|
var init_screen_crawl = __esm({
|
|
29732
30346
|
"../../core/dev-server/src/screen-crawl.ts"() {
|
|
29733
30347
|
init_validate_descriptor_core();
|
|
@@ -29737,6 +30351,7 @@ var init_screen_crawl = __esm({
|
|
|
29737
30351
|
init_FakeServiceProvider();
|
|
29738
30352
|
init_actionParams();
|
|
29739
30353
|
init_implications();
|
|
30354
|
+
init_crawl_relations();
|
|
29740
30355
|
ACTION_KEYS = [
|
|
29741
30356
|
"action",
|
|
29742
30357
|
"onTap",
|
|
@@ -29760,6 +30375,7 @@ var init_screen_crawl = __esm({
|
|
|
29760
30375
|
Marquee: ["items", "itemsPath", "text"],
|
|
29761
30376
|
MediaPlayer: ["items", "itemsPath"]
|
|
29762
30377
|
};
|
|
30378
|
+
UNBINDABLE_ROW = Symbol("unbindable-row");
|
|
29763
30379
|
}
|
|
29764
30380
|
});
|
|
29765
30381
|
|
|
@@ -30315,8 +30931,8 @@ __export(pack_exports, {
|
|
|
30315
30931
|
});
|
|
30316
30932
|
import { createHash as createHash19 } from "node:crypto";
|
|
30317
30933
|
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
|
|
30934
|
+
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";
|
|
30935
|
+
import { dirname as dirname23, join as join35, resolve as resolve31 } from "node:path";
|
|
30320
30936
|
function writeZip(entries) {
|
|
30321
30937
|
const sorted = entries.slice().sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
30322
30938
|
const total = sorted.reduce((n, e) => n + e.bytes.length, 0);
|
|
@@ -30410,13 +31026,13 @@ function inflateEntry(buf, entry) {
|
|
|
30410
31026
|
return bytes2;
|
|
30411
31027
|
}
|
|
30412
31028
|
function readIf(path) {
|
|
30413
|
-
return existsSync35(path) &&
|
|
31029
|
+
return existsSync35(path) && statSync8(path).isFile() ? readFileSync42(path) : null;
|
|
30414
31030
|
}
|
|
30415
31031
|
function listDir(dir) {
|
|
30416
|
-
return existsSync35(dir) ? readdirSync19(dir).filter((f) =>
|
|
31032
|
+
return existsSync35(dir) ? readdirSync19(dir).filter((f) => statSync8(join35(dir, f)).isFile()) : [];
|
|
30417
31033
|
}
|
|
30418
31034
|
function gatherReleaseEntries(appDir2) {
|
|
30419
|
-
const manifestPath =
|
|
31035
|
+
const manifestPath = join35(appDir2, HIMI_PACKAGE_MANIFEST_PATH);
|
|
30420
31036
|
const manifestBytes = readIf(manifestPath);
|
|
30421
31037
|
if (!manifestBytes) throw new Error(`no ${HIMI_PACKAGE_MANIFEST_PATH} in ${appDir2} \u2014 build a release there first`);
|
|
30422
31038
|
const manifest = JSON.parse(manifestBytes.toString("utf8"));
|
|
@@ -30440,7 +31056,7 @@ function gatherReleaseEntries(appDir2) {
|
|
|
30440
31056
|
}
|
|
30441
31057
|
const missing = [];
|
|
30442
31058
|
for (const rel of wanted) {
|
|
30443
|
-
const bytes2 = readIf(
|
|
31059
|
+
const bytes2 = readIf(join35(appDir2, rel));
|
|
30444
31060
|
if (bytes2) entries.push({ path: rel, bytes: bytes2 });
|
|
30445
31061
|
else missing.push(rel);
|
|
30446
31062
|
}
|
|
@@ -30451,12 +31067,12 @@ function gatherReleaseEntries(appDir2) {
|
|
|
30451
31067
|
);
|
|
30452
31068
|
}
|
|
30453
31069
|
for (const name of SINGLETONS) {
|
|
30454
|
-
const bytes2 = readIf(
|
|
31070
|
+
const bytes2 = readIf(join35(appDir2, name));
|
|
30455
31071
|
if (bytes2) entries.push({ path: name, bytes: bytes2 });
|
|
30456
31072
|
}
|
|
30457
31073
|
const skipped = [];
|
|
30458
31074
|
for (const sub of ["screens", "bundles", "assets", "widgets"]) {
|
|
30459
|
-
for (const f of listDir(
|
|
31075
|
+
for (const f of listDir(join35(appDir2, sub))) {
|
|
30460
31076
|
if (!wanted.has(`${sub}/${f}`)) skipped.push(`${sub}/${f}`);
|
|
30461
31077
|
}
|
|
30462
31078
|
}
|
|
@@ -30487,18 +31103,18 @@ function buildEntries(appDir2, app, opts) {
|
|
|
30487
31103
|
return { all, header, manifest, skipped };
|
|
30488
31104
|
}
|
|
30489
31105
|
function packRelease(releaseRoot, app, out, opts = {}) {
|
|
30490
|
-
const appDir2 =
|
|
31106
|
+
const appDir2 = join35(resolve31(releaseRoot), app);
|
|
30491
31107
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
30492
31108
|
const buf = writeZip(all);
|
|
30493
|
-
const isDir = existsSync35(out) &&
|
|
30494
|
-
const outFile = isDir ?
|
|
31109
|
+
const isDir = existsSync35(out) && statSync8(out).isDirectory();
|
|
31110
|
+
const outFile = isDir ? join35(resolve31(out), packageFileName(app, header.releaseId)) : resolve31(out);
|
|
30495
31111
|
mkdirSync17(dirname23(outFile), { recursive: true });
|
|
30496
31112
|
writeFileSync13(outFile, buf);
|
|
30497
31113
|
return { app, releaseId: header.releaseId, header, out: outFile, bytes: buf.length, entryCount: all.length, skipped };
|
|
30498
31114
|
}
|
|
30499
31115
|
function resolvePackageDirDest(outDir, app, releaseId) {
|
|
30500
31116
|
const packagedApp = (dir) => {
|
|
30501
|
-
const bytes2 = readIf(
|
|
31117
|
+
const bytes2 = readIf(join35(dir, HIMI_PACKAGE_HEADER_PATH));
|
|
30502
31118
|
if (!bytes2) return void 0;
|
|
30503
31119
|
try {
|
|
30504
31120
|
return JSON.parse(bytes2.toString("utf8")).app;
|
|
@@ -30508,14 +31124,14 @@ function resolvePackageDirDest(outDir, app, releaseId) {
|
|
|
30508
31124
|
};
|
|
30509
31125
|
const replaceable = (dir) => {
|
|
30510
31126
|
if (!existsSync35(dir)) return true;
|
|
30511
|
-
if (!
|
|
31127
|
+
if (!statSync8(dir).isDirectory()) return false;
|
|
30512
31128
|
return readdirSync19(dir).length === 0 || packagedApp(dir) === app;
|
|
30513
31129
|
};
|
|
30514
|
-
if (existsSync35(outDir) && !
|
|
31130
|
+
if (existsSync35(outDir) && !statSync8(outDir).isDirectory()) {
|
|
30515
31131
|
throw new Error(`refusing to write a package tree over ${outDir} \u2014 it is a file, not a directory`);
|
|
30516
31132
|
}
|
|
30517
31133
|
if (replaceable(outDir)) return outDir;
|
|
30518
|
-
const child =
|
|
31134
|
+
const child = join35(outDir, packageDirName(app, releaseId));
|
|
30519
31135
|
if (!replaceable(child)) {
|
|
30520
31136
|
throw new Error(
|
|
30521
31137
|
`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 +31140,13 @@ function resolvePackageDirDest(outDir, app, releaseId) {
|
|
|
30524
31140
|
return child;
|
|
30525
31141
|
}
|
|
30526
31142
|
function packReleaseToDir(releaseRoot, app, outDir, opts = {}) {
|
|
30527
|
-
const appDir2 =
|
|
31143
|
+
const appDir2 = join35(resolve31(releaseRoot), app);
|
|
30528
31144
|
const { all, header, skipped } = buildEntries(appDir2, app, opts);
|
|
30529
31145
|
const dest = resolvePackageDirDest(resolve31(outDir), app, header.releaseId);
|
|
30530
31146
|
rmSync5(dest, { recursive: true, force: true });
|
|
30531
31147
|
let bytes2 = 0;
|
|
30532
31148
|
for (const entry of all) {
|
|
30533
|
-
const target =
|
|
31149
|
+
const target = join35(dest, entry.path);
|
|
30534
31150
|
mkdirSync17(dirname23(target), { recursive: true });
|
|
30535
31151
|
writeFileSync13(target, entry.bytes);
|
|
30536
31152
|
bytes2 += entry.bytes.length;
|
|
@@ -30559,11 +31175,11 @@ function openPackageDir(dir) {
|
|
|
30559
31175
|
const root = resolve31(dir);
|
|
30560
31176
|
const entries = /* @__PURE__ */ new Map();
|
|
30561
31177
|
const walk2 = (rel) => {
|
|
30562
|
-
const abs = rel ?
|
|
31178
|
+
const abs = rel ? join35(root, rel) : root;
|
|
30563
31179
|
for (const name of readdirSync19(abs)) {
|
|
30564
31180
|
const childRel = rel ? `${rel}/${name}` : name;
|
|
30565
|
-
const childAbs =
|
|
30566
|
-
if (
|
|
31181
|
+
const childAbs = join35(abs, name);
|
|
31182
|
+
if (statSync8(childAbs).isDirectory()) walk2(childRel);
|
|
30567
31183
|
else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync42(childAbs));
|
|
30568
31184
|
}
|
|
30569
31185
|
};
|
|
@@ -30601,10 +31217,10 @@ function unpackTo(buf, dest, appFallback) {
|
|
|
30601
31217
|
if (!app) throw new Error("package declares no app id (no himi-package.json and no manifest.app)");
|
|
30602
31218
|
if (!isSafeAppId(app)) throw new Error(`package declares an unsafe app id ${JSON.stringify(app)} \u2014 refusing to unpack it`);
|
|
30603
31219
|
const root = resolve31(dest);
|
|
30604
|
-
const appDir2 =
|
|
31220
|
+
const appDir2 = join35(root, app);
|
|
30605
31221
|
rmSync5(appDir2, { recursive: true, force: true });
|
|
30606
31222
|
for (const [rel, bytes2] of entries) {
|
|
30607
|
-
const target =
|
|
31223
|
+
const target = join35(appDir2, rel);
|
|
30608
31224
|
mkdirSync17(dirname23(target), { recursive: true });
|
|
30609
31225
|
writeFileSync13(target, bytes2);
|
|
30610
31226
|
}
|
|
@@ -30636,14 +31252,14 @@ __export(app_source_exports, {
|
|
|
30636
31252
|
zipAppSource: () => zipAppSource
|
|
30637
31253
|
});
|
|
30638
31254
|
import { readdirSync as readdirSync20, lstatSync as lstatSync4, readFileSync as readFileSync43, mkdirSync as mkdirSync18, writeFileSync as writeFileSync14 } from "node:fs";
|
|
30639
|
-
import { join as
|
|
31255
|
+
import { join as join36, dirname as dirname24, sep as sep7 } from "node:path";
|
|
30640
31256
|
function collectAppSource(dir) {
|
|
30641
31257
|
const entries = [];
|
|
30642
31258
|
const skipped = [];
|
|
30643
31259
|
const walk2 = (relDir) => {
|
|
30644
|
-
for (const name of readdirSync20(
|
|
30645
|
-
const rel = relDir ?
|
|
30646
|
-
const st = lstatSync4(
|
|
31260
|
+
for (const name of readdirSync20(join36(dir, relDir))) {
|
|
31261
|
+
const rel = relDir ? join36(relDir, name) : name;
|
|
31262
|
+
const st = lstatSync4(join36(dir, rel));
|
|
30647
31263
|
if (st.isSymbolicLink()) {
|
|
30648
31264
|
skipped.push(rel);
|
|
30649
31265
|
continue;
|
|
@@ -30657,7 +31273,7 @@ function collectAppSource(dir) {
|
|
|
30657
31273
|
skipped.push(rel);
|
|
30658
31274
|
continue;
|
|
30659
31275
|
}
|
|
30660
|
-
entries.push({ path: rel.split(
|
|
31276
|
+
entries.push({ path: rel.split(sep7).join("/"), bytes: readFileSync43(join36(dir, rel)) });
|
|
30661
31277
|
}
|
|
30662
31278
|
};
|
|
30663
31279
|
walk2("");
|
|
@@ -30683,7 +31299,7 @@ function readAppSource(zip) {
|
|
|
30683
31299
|
function writeAppSource(entries, destDir) {
|
|
30684
31300
|
const written = [];
|
|
30685
31301
|
for (const entry of entries) {
|
|
30686
|
-
const target =
|
|
31302
|
+
const target = join36(destDir, ...entry.path.split("/"));
|
|
30687
31303
|
mkdirSync18(dirname24(target), { recursive: true });
|
|
30688
31304
|
writeFileSync14(target, entry.bytes);
|
|
30689
31305
|
written.push(entry.path);
|
|
@@ -30714,7 +31330,7 @@ __export(eject_exports, {
|
|
|
30714
31330
|
ejectModule: () => ejectModule
|
|
30715
31331
|
});
|
|
30716
31332
|
import { existsSync as existsSync36, mkdirSync as mkdirSync19, readFileSync as readFileSync44, writeFileSync as writeFileSync15 } from "node:fs";
|
|
30717
|
-
import { dirname as dirname25, join as
|
|
31333
|
+
import { dirname as dirname25, join as join37, relative as relative4, resolve as resolve32, sep as sep8 } from "node:path";
|
|
30718
31334
|
function locate(repoRootOrCwd, mod) {
|
|
30719
31335
|
const inRepo = resolve32(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
|
|
30720
31336
|
if (existsSync36(inRepo)) return { path: inRepo, form: "source" };
|
|
@@ -30743,7 +31359,7 @@ function ejectModule(opts) {
|
|
|
30743
31359
|
};
|
|
30744
31360
|
}
|
|
30745
31361
|
const ext = found.form === "source" ? "ts" : "mjs";
|
|
30746
|
-
const target =
|
|
31362
|
+
const target = join37(contentDir2, "tier5-src", "_ejected", `${mod}.${ext}`);
|
|
30747
31363
|
mkdirSync19(dirname25(target), { recursive: true });
|
|
30748
31364
|
const banner = `// EJECTED from @wix/himalaya/${mod}. This app owns this file now.
|
|
30749
31365
|
//
|
|
@@ -30767,7 +31383,7 @@ function ejectModule(opts) {
|
|
|
30767
31383
|
if (!existsSync36(f)) continue;
|
|
30768
31384
|
const before = readFileSync44(f, "utf8");
|
|
30769
31385
|
let after = before;
|
|
30770
|
-
let rel = relative4(dirname25(f), target).split(
|
|
31386
|
+
let rel = relative4(dirname25(f), target).split(sep8).join("/").replace(/\.tsx?$/, ".js");
|
|
30771
31387
|
if (!rel.startsWith(".")) rel = `./${rel}`;
|
|
30772
31388
|
for (const spec of specifiersFor(mod)) {
|
|
30773
31389
|
const q = spec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -30814,7 +31430,7 @@ __export(test_exports, {
|
|
|
30814
31430
|
writeRecordedMocks: () => writeRecordedMocks
|
|
30815
31431
|
});
|
|
30816
31432
|
import { existsSync as existsSync37, mkdirSync as mkdirSync20, readFileSync as readFileSync45, writeFileSync as writeFileSync16 } from "node:fs";
|
|
30817
|
-
import { join as
|
|
31433
|
+
import { join as join38, resolve as resolve33 } from "node:path";
|
|
30818
31434
|
function readTestConfig(dir) {
|
|
30819
31435
|
const p = resolve33(dir, TEST_CONFIG_FILE);
|
|
30820
31436
|
if (!existsSync37(p)) return {};
|
|
@@ -30833,8 +31449,8 @@ function readTestConfig(dir) {
|
|
|
30833
31449
|
if (typeof s.reason !== "string" || !s.reason.trim()) {
|
|
30834
31450
|
throw new Error(`${TEST_CONFIG_FILE}: skip[${i}] needs a non-empty "reason" \u2014 suppressions have to stay auditable`);
|
|
30835
31451
|
}
|
|
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 "
|
|
31452
|
+
if (!s.screen && !s.action && !s.component && !s.invariant) {
|
|
31453
|
+
throw new Error(`${TEST_CONFIG_FILE}: skip[${i}] matches everything \u2014 give it a "screen", "action", "component", or "invariant"`);
|
|
30838
31454
|
}
|
|
30839
31455
|
});
|
|
30840
31456
|
}
|
|
@@ -30992,8 +31608,8 @@ function writeRecordedMocks(opts) {
|
|
|
30992
31608
|
mkdir: (p) => mkdirSync20(p, { recursive: true }),
|
|
30993
31609
|
write: (p, s) => writeFileSync16(p, s)
|
|
30994
31610
|
};
|
|
30995
|
-
fs.mkdir(
|
|
30996
|
-
fs.write(
|
|
31611
|
+
fs.mkdir(join38(opts.dir, "dev"));
|
|
31612
|
+
fs.write(join38(opts.dir, "dev", "net-mocks.json"), JSON.stringify(opts.mocks, null, 2) + "\n");
|
|
30997
31613
|
return { ok: true, rules, to: "dev/net-mocks.json" };
|
|
30998
31614
|
}
|
|
30999
31615
|
function scopeDescriptors(descriptors, requestedIds, invalidScreens) {
|
|
@@ -31059,12 +31675,15 @@ async function runCrawl(opts) {
|
|
|
31059
31675
|
const net = opts.offline ? null : opts.netPath ? { rules: readNetRules(resolve33(opts.netPath)), from: opts.netPath } : defaultNetRules(opts.dir);
|
|
31060
31676
|
const suppressions = opts.config?.skip ?? [];
|
|
31061
31677
|
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));
|
|
31678
|
+
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
31679
|
const results = [];
|
|
31064
31680
|
const uncoveredByScreen = /* @__PURE__ */ new Map();
|
|
31065
31681
|
const coverageFns = /* @__PURE__ */ new Map();
|
|
31066
31682
|
const bundleOf = new Map(descriptors.map((d) => [d.screenId, d]));
|
|
31067
31683
|
const hostileFindings = [];
|
|
31684
|
+
const relationFindings = [];
|
|
31685
|
+
let relationsChecked = 0;
|
|
31686
|
+
const relationsByKind = { inverse: 0, refresh: 0, loadMore: 0, filter: 0 };
|
|
31068
31687
|
const deepFindings = [];
|
|
31069
31688
|
const journeyFindings = [];
|
|
31070
31689
|
const journeyResults = [];
|
|
@@ -31134,14 +31753,22 @@ async function runCrawl(opts) {
|
|
|
31134
31753
|
hostileFindings.push(...hs.filter((f) => !already.has(keyOf(f))));
|
|
31135
31754
|
}
|
|
31136
31755
|
}
|
|
31756
|
+
if (deps.crawlScreenRelations && baked.bundleJs) {
|
|
31757
|
+
const rr = await deps.crawlScreenRelations(args);
|
|
31758
|
+
relationsChecked += rr.checked;
|
|
31759
|
+
for (const [k, n] of Object.entries(rr.byKind ?? {})) relationsByKind[k] = (relationsByKind[k] ?? 0) + n;
|
|
31760
|
+
const keyOf = deps.findingKey ?? ((f) => `${f.invariant}|${f.at ?? ""}|${f.screen}|${f.message}`);
|
|
31761
|
+
const already = new Set(r.findings.map(keyOf));
|
|
31762
|
+
for (const f of rr.findings) if (!already.has(keyOf(f))) relationFindings.push(f);
|
|
31763
|
+
}
|
|
31137
31764
|
await finishScreenCoverage();
|
|
31138
31765
|
}
|
|
31139
31766
|
const keep = (f) => {
|
|
31140
31767
|
const actionId = typeof f.trigger === "object" ? f.trigger.action : "boot";
|
|
31141
31768
|
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 });
|
|
31769
|
+
const s = matchSuppression(f.screen, actionId, componentId, f.invariant);
|
|
31770
|
+
if (s && !suppressed.some((x) => x.screen === f.screen && x.action === actionId && x.component === (componentId ?? void 0) && x.invariant === s.invariant)) {
|
|
31771
|
+
suppressed.push({ screen: f.screen, action: actionId, ...componentId ? { component: componentId } : {}, ...s.invariant ? { invariant: s.invariant } : {}, reason: s.reason });
|
|
31145
31772
|
}
|
|
31146
31773
|
return !s;
|
|
31147
31774
|
};
|
|
@@ -31222,7 +31849,7 @@ async function runCrawl(opts) {
|
|
|
31222
31849
|
if (uncovered.length) uncoveredByScreen.set(screen, uncovered);
|
|
31223
31850
|
}
|
|
31224
31851
|
}
|
|
31225
|
-
const all = [...results.flatMap((r) => r.findings), ...hostileFindings, ...deepFindings, ...journeyFindings, ...edgeFindings].filter((f) => {
|
|
31852
|
+
const all = [...results.flatMap((r) => r.findings), ...hostileFindings, ...deepFindings, ...journeyFindings, ...edgeFindings, ...relationFindings].filter((f) => {
|
|
31226
31853
|
if (f.invariant === "no-request-issued" && !f.axis && fetchProven.has(f.screen)) {
|
|
31227
31854
|
const by = fetchProven.get(f.screen);
|
|
31228
31855
|
if (!retired.some((x) => x.screen === f.screen)) retired.push({ screen: f.screen, from: by.from, params: by.params });
|
|
@@ -31242,7 +31869,15 @@ async function runCrawl(opts) {
|
|
|
31242
31869
|
...blockedReasons.length ? { blockedReasons } : {},
|
|
31243
31870
|
app: opts.app,
|
|
31244
31871
|
releaseId: opts.releaseId,
|
|
31245
|
-
|
|
31872
|
+
// Whether the axis RAN, not whether it was injected. The engine is gated on `baked.bundleJs`,
|
|
31873
|
+
// so a run over static or bundle-less screens injects the dependency and replays nothing —
|
|
31874
|
+
// and the label then advertised "+ relations" beside `relations.checked: 0`. This is the
|
|
31875
|
+
// second time this line has overstated itself: it first claimed the axis unconditionally.
|
|
31876
|
+
transport: describeTransport(net, opts, {
|
|
31877
|
+
relations: relationsChecked > 0,
|
|
31878
|
+
hostile: opts.hostile !== false && Boolean(deps.crawlScreenHostile),
|
|
31879
|
+
deep: Boolean(opts.deep && opts.deep >= 2 && deps.crawlScreenDeep)
|
|
31880
|
+
}),
|
|
31246
31881
|
screens: { total: targets.length, clean: targets.length - failedScreens.size, failed: failedScreens.size },
|
|
31247
31882
|
actions: { exercised: results.reduce((n, r) => n + r.actionsExercised, 0) },
|
|
31248
31883
|
counts: { errors: failures.length, warnings: warnings.length },
|
|
@@ -31265,22 +31900,22 @@ async function runCrawl(opts) {
|
|
|
31265
31900
|
...edgesCapped.length ? { edgesCapped } : {},
|
|
31266
31901
|
...retired.length ? { retired } : {},
|
|
31267
31902
|
...opts.deep && opts.deep >= 2 ? { deep: { depth: opts.deep, ...deepTotals } } : {},
|
|
31903
|
+
...deps.crawlScreenRelations ? { relations: { checked: relationsChecked, byKind: relationsByKind } } : {},
|
|
31268
31904
|
...journeyResults.length ? { journeys: journeyResults } : {},
|
|
31269
31905
|
...results.some((r) => r.observations) ? { observations: Object.fromEntries(results.filter((r) => r.observations).map((r) => [r.screen, r.observations])) } : {}
|
|
31270
31906
|
};
|
|
31271
31907
|
}
|
|
31272
|
-
function describeTransport(net, opts) {
|
|
31908
|
+
function describeTransport(net, opts, ran) {
|
|
31273
31909
|
const layers = [];
|
|
31274
31910
|
if (net) layers.push(`mocked (${net.from})`);
|
|
31275
31911
|
const cmsCount = Object.keys(opts.cmsSeed ?? {}).length;
|
|
31276
31912
|
if (cmsCount) layers.push(`cms (${cmsCount} seeded collection${cmsCount === 1 ? "" : "s"})`);
|
|
31277
31913
|
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;
|
|
31914
|
+
const base = layers.length ? layers.join(" + ") : "offline (no net fixture \u2014 screens are crawled against a rejecting transport, which exercises their failure UI)";
|
|
31915
|
+
const hostile = ran.hostile ? " + hostile boot passes (empty-lists, all-500)" : "";
|
|
31916
|
+
const relations = ran.relations ? " + relations" : "";
|
|
31917
|
+
const deep = ran.deep ? ` + deep chains (depth ${opts.deep})` : "";
|
|
31918
|
+
return base + hostile + relations + deep;
|
|
31284
31919
|
}
|
|
31285
31920
|
function formatReport(r) {
|
|
31286
31921
|
const out = [];
|
|
@@ -31415,9 +32050,9 @@ __export(mobile_ux_lint_exports, {
|
|
|
31415
32050
|
mobileUxIssues: () => mobileUxIssues
|
|
31416
32051
|
});
|
|
31417
32052
|
import { existsSync as existsSync38, readFileSync as readFileSync46 } from "node:fs";
|
|
31418
|
-
import { join as
|
|
32053
|
+
import { join as join39 } from "node:path";
|
|
31419
32054
|
function mobileUxIssues(dir, strict) {
|
|
31420
|
-
const file =
|
|
32055
|
+
const file = join39(dir, "MOBILE-UX.md");
|
|
31421
32056
|
if (!existsSync38(file)) return [];
|
|
31422
32057
|
let text2;
|
|
31423
32058
|
try {
|
|
@@ -33081,7 +33716,7 @@ __export(functions_exports, {
|
|
|
33081
33716
|
runRemoteFunctionOperation: () => runRemoteFunctionOperation
|
|
33082
33717
|
});
|
|
33083
33718
|
import { readFileSync as readFileSync47, existsSync as existsSync39 } from "node:fs";
|
|
33084
|
-
import { join as
|
|
33719
|
+
import { join as join40, resolve as resolve34 } from "node:path";
|
|
33085
33720
|
function resolveFunctionsTarget(input) {
|
|
33086
33721
|
const explicitUrl = input.functionsUrl?.trim();
|
|
33087
33722
|
if (explicitUrl) return { mode: "remote", baseUrl: explicitUrl };
|
|
@@ -33100,7 +33735,7 @@ async function loadFunctionsApp(dir) {
|
|
|
33100
33735
|
}
|
|
33101
33736
|
const sources = {};
|
|
33102
33737
|
for (const definition of config.functions.functions) {
|
|
33103
|
-
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) =>
|
|
33738
|
+
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join40(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync39);
|
|
33104
33739
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
33105
33740
|
sources[definition.name] = readFileSync47(source, "utf8");
|
|
33106
33741
|
}
|
|
@@ -33258,7 +33893,7 @@ __export(native_decode_exports, {
|
|
|
33258
33893
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
33259
33894
|
import { existsSync as existsSync40, mkdtempSync as mkdtempSync2, readFileSync as readFileSync48, rmSync as rmSync6, writeFileSync as writeFileSync17 } from "node:fs";
|
|
33260
33895
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
33261
|
-
import { join as
|
|
33896
|
+
import { join as join41 } from "node:path";
|
|
33262
33897
|
import { fileURLToPath as fileURLToPath19 } from "node:url";
|
|
33263
33898
|
function nativeDecodePackageDir() {
|
|
33264
33899
|
return fileURLToPath19(new URL("../../../core/runtime/ios/HimalayaCore/", import.meta.url));
|
|
@@ -33274,7 +33909,7 @@ function detectNativeDecode(options = {}) {
|
|
|
33274
33909
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
33275
33910
|
}
|
|
33276
33911
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
33277
|
-
const packageAvailable = options.packageAvailable ?? existsSync40(
|
|
33912
|
+
const packageAvailable = options.packageAvailable ?? existsSync40(join41(packageDir, "Package.swift"));
|
|
33278
33913
|
if (!packageAvailable) {
|
|
33279
33914
|
return {
|
|
33280
33915
|
platform: "ios",
|
|
@@ -33286,7 +33921,7 @@ function detectNativeDecode(options = {}) {
|
|
|
33286
33921
|
}
|
|
33287
33922
|
function localPropertiesSdk(harnessDir) {
|
|
33288
33923
|
try {
|
|
33289
|
-
const match = readFileSync48(
|
|
33924
|
+
const match = readFileSync48(join41(harnessDir, "local.properties"), "utf8").match(/^sdk\.dir\s*=\s*(.+)$/m);
|
|
33290
33925
|
return match?.[1]?.trim().replace(/\\([ :\\])/g, "$1") ?? null;
|
|
33291
33926
|
} catch {
|
|
33292
33927
|
return null;
|
|
@@ -33294,7 +33929,7 @@ function localPropertiesSdk(harnessDir) {
|
|
|
33294
33929
|
}
|
|
33295
33930
|
function detectAndroidNativeDecode(options = {}) {
|
|
33296
33931
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
33297
|
-
const gradlew =
|
|
33932
|
+
const gradlew = join41(harnessDir, "gradlew");
|
|
33298
33933
|
const gradlewAvailable = options.gradlewAvailable ?? existsSync40(gradlew);
|
|
33299
33934
|
if (!gradlewAvailable) {
|
|
33300
33935
|
return {
|
|
@@ -33377,14 +34012,14 @@ function parseNativeDecodeOutput(stdout, expectedScreenIds, platform = "ios") {
|
|
|
33377
34012
|
return verdicts;
|
|
33378
34013
|
}
|
|
33379
34014
|
function runNativeDecode(options) {
|
|
33380
|
-
const descriptorDir = mkdtempSync2(
|
|
34015
|
+
const descriptorDir = mkdtempSync2(join41(tmpdir3(), "himi-native-decode-"));
|
|
33381
34016
|
const startedAt = Date.now();
|
|
33382
34017
|
try {
|
|
33383
34018
|
for (const descriptor of options.descriptors) {
|
|
33384
34019
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
33385
34020
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
33386
34021
|
}
|
|
33387
|
-
writeFileSync17(
|
|
34022
|
+
writeFileSync17(join41(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
33388
34023
|
}
|
|
33389
34024
|
options.progress?.("building cached Swift oracle");
|
|
33390
34025
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -33396,7 +34031,7 @@ function runNativeDecode(options) {
|
|
|
33396
34031
|
encoding: "utf8"
|
|
33397
34032
|
}).trim();
|
|
33398
34033
|
options.progress?.(`running real Swift decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
33399
|
-
const stdout = execFileSync5(
|
|
34034
|
+
const stdout = execFileSync5(join41(binPath, "himi-decode-oracle"), ["--dir", descriptorDir], {
|
|
33400
34035
|
stdio: ["ignore", "pipe", "pipe"],
|
|
33401
34036
|
encoding: "utf8"
|
|
33402
34037
|
});
|
|
@@ -33414,15 +34049,15 @@ function runNativeDecode(options) {
|
|
|
33414
34049
|
}
|
|
33415
34050
|
}
|
|
33416
34051
|
function runAndroidNativeDecode(options) {
|
|
33417
|
-
const descriptorDir = mkdtempSync2(
|
|
33418
|
-
const outputPath =
|
|
34052
|
+
const descriptorDir = mkdtempSync2(join41(tmpdir3(), "himi-native-decode-android-"));
|
|
34053
|
+
const outputPath = join41(descriptorDir, "verdicts.ndjson");
|
|
33419
34054
|
const startedAt = Date.now();
|
|
33420
34055
|
try {
|
|
33421
34056
|
for (const descriptor of options.descriptors) {
|
|
33422
34057
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
33423
34058
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
33424
34059
|
}
|
|
33425
|
-
writeFileSync17(
|
|
34060
|
+
writeFileSync17(join41(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
33426
34061
|
}
|
|
33427
34062
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
33428
34063
|
execFileSync5(options.gradlew, [
|
|
@@ -33508,23 +34143,23 @@ __export(browser_authoring_exports, {
|
|
|
33508
34143
|
import { createServer as createServer3 } from "node:http";
|
|
33509
34144
|
import { createHash as createHash22, randomBytes as randomBytes5 } from "node:crypto";
|
|
33510
34145
|
import { execFile as execFile2 } from "node:child_process";
|
|
33511
|
-
import { existsSync as existsSync41, readdirSync as readdirSync21, readFileSync as readFileSync49, realpathSync as
|
|
33512
|
-
import { join as
|
|
34146
|
+
import { existsSync as existsSync41, readdirSync as readdirSync21, readFileSync as readFileSync49, realpathSync as realpathSync4, statSync as statSync9 } from "node:fs";
|
|
34147
|
+
import { join as join42, posix, relative as relative5, sep as sep9 } from "node:path";
|
|
33513
34148
|
function humanMs(ms) {
|
|
33514
34149
|
return ms < 1e3 ? `${ms}ms` : `${Math.round(ms / 1e3)}s`;
|
|
33515
34150
|
}
|
|
33516
34151
|
function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
33517
|
-
const root =
|
|
34152
|
+
const root = join42(tier5SrcDir, bundleName);
|
|
33518
34153
|
const files = {};
|
|
33519
34154
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
33520
34155
|
const walk2 = (abs, rel) => {
|
|
33521
|
-
const real =
|
|
34156
|
+
const real = realpathSync4(abs);
|
|
33522
34157
|
if (visitedDirs.has(real)) return;
|
|
33523
34158
|
visitedDirs.add(real);
|
|
33524
34159
|
for (const name of readdirSync21(abs).sort()) {
|
|
33525
|
-
const childAbs =
|
|
34160
|
+
const childAbs = join42(abs, name);
|
|
33526
34161
|
const childRel = posix.join(rel, name);
|
|
33527
|
-
if (
|
|
34162
|
+
if (statSync9(childAbs).isDirectory()) {
|
|
33528
34163
|
walk2(childAbs, childRel);
|
|
33529
34164
|
} else if (/\.(ts|tsx|js|mjs|json)$/.test(name)) {
|
|
33530
34165
|
files[childRel] = readFileSync49(childAbs, "utf8");
|
|
@@ -33548,18 +34183,18 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
33548
34183
|
const spec = m[1];
|
|
33549
34184
|
const virtual = posix.normalize(posix.join(dir, spec));
|
|
33550
34185
|
if (!virtual.startsWith("/tier5-src/")) continue;
|
|
33551
|
-
const onDisk =
|
|
34186
|
+
const onDisk = join42(tier5SrcDir, virtual.slice("/tier5-src/".length));
|
|
33552
34187
|
const candidates = [
|
|
33553
34188
|
onDisk,
|
|
33554
34189
|
`${onDisk}.ts`,
|
|
33555
34190
|
`${onDisk}.js`,
|
|
33556
34191
|
onDisk.replace(/\.js$/, ".ts"),
|
|
33557
|
-
|
|
33558
|
-
|
|
34192
|
+
join42(onDisk, "index.ts"),
|
|
34193
|
+
join42(onDisk, "index.js")
|
|
33559
34194
|
];
|
|
33560
34195
|
for (const abs of candidates) {
|
|
33561
|
-
if (!existsSync41(abs) ||
|
|
33562
|
-
const key2 = `/tier5-src/${relative5(tier5SrcDir, abs).split(
|
|
34196
|
+
if (!existsSync41(abs) || statSync9(abs).isDirectory()) continue;
|
|
34197
|
+
const key2 = `/tier5-src/${relative5(tier5SrcDir, abs).split(sep9).join(posix.sep)}`;
|
|
33563
34198
|
if (key2 in files) break;
|
|
33564
34199
|
files[key2] = readFileSync49(abs, "utf8");
|
|
33565
34200
|
queue.push(key2);
|
|
@@ -33770,7 +34405,7 @@ __export(coverage_exports, {
|
|
|
33770
34405
|
trendAndStore: () => trendAndStore
|
|
33771
34406
|
});
|
|
33772
34407
|
import { existsSync as existsSync42, mkdirSync as mkdirSync21, readFileSync as readFileSync50, writeFileSync as writeFileSync18 } from "node:fs";
|
|
33773
|
-
import { dirname as dirname26, join as
|
|
34408
|
+
import { dirname as dirname26, join as join43 } from "node:path";
|
|
33774
34409
|
function assembleLedger(r) {
|
|
33775
34410
|
const out = [];
|
|
33776
34411
|
for (const c of r.crawled ?? []) {
|
|
@@ -33936,7 +34571,7 @@ function assembleLedger(r) {
|
|
|
33936
34571
|
return out;
|
|
33937
34572
|
}
|
|
33938
34573
|
function trendAndStore(dir, entries) {
|
|
33939
|
-
const p =
|
|
34574
|
+
const p = join43(dir, LEDGER_FILE);
|
|
33940
34575
|
let previous = null;
|
|
33941
34576
|
try {
|
|
33942
34577
|
if (existsSync42(p)) {
|
|
@@ -33977,7 +34612,7 @@ function formatLedger(entries, trend) {
|
|
|
33977
34612
|
return out.join("\n");
|
|
33978
34613
|
}
|
|
33979
34614
|
function diffAndStoreObservations(dir, current) {
|
|
33980
|
-
const p =
|
|
34615
|
+
const p = join43(dir, OBS_FILE);
|
|
33981
34616
|
let previous = null;
|
|
33982
34617
|
try {
|
|
33983
34618
|
if (existsSync42(p)) {
|
|
@@ -34029,8 +34664,8 @@ function formatDelta(delta) {
|
|
|
34029
34664
|
var LEDGER_FILE, OBS_FILE;
|
|
34030
34665
|
var init_coverage = __esm({
|
|
34031
34666
|
"src/coverage.ts"() {
|
|
34032
|
-
LEDGER_FILE =
|
|
34033
|
-
OBS_FILE =
|
|
34667
|
+
LEDGER_FILE = join43(".himi", "test-ledger.json");
|
|
34668
|
+
OBS_FILE = join43(".himi", "test-observations.json");
|
|
34034
34669
|
}
|
|
34035
34670
|
});
|
|
34036
34671
|
|
|
@@ -35234,9 +35869,9 @@ __export(run_exports, {
|
|
|
35234
35869
|
runPackage: () => runPackage,
|
|
35235
35870
|
withoutProdServe: () => withoutProdServe
|
|
35236
35871
|
});
|
|
35237
|
-
import { cpSync, existsSync as existsSync43, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync3, readFileSync as readFileSync52, rmSync as rmSync7, statSync as
|
|
35872
|
+
import { cpSync, existsSync as existsSync43, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync3, readFileSync as readFileSync52, rmSync as rmSync7, statSync as statSync10 } from "node:fs";
|
|
35238
35873
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
35239
|
-
import { join as
|
|
35874
|
+
import { join as join44 } from "node:path";
|
|
35240
35875
|
import { spawn as spawn3 } from "node:child_process";
|
|
35241
35876
|
function makePackageRunHandler(opts) {
|
|
35242
35877
|
return makeRunHandler({
|
|
@@ -35254,8 +35889,8 @@ async function fetchBytes(url) {
|
|
|
35254
35889
|
}
|
|
35255
35890
|
async function resolvePackage(source, workDir) {
|
|
35256
35891
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
35257
|
-
if (!isUrl2 && existsSync43(source) &&
|
|
35258
|
-
const appDirManifest =
|
|
35892
|
+
if (!isUrl2 && existsSync43(source) && statSync10(source).isDirectory()) {
|
|
35893
|
+
const appDirManifest = join44(source, "release-manifest.json");
|
|
35259
35894
|
if (existsSync43(appDirManifest)) {
|
|
35260
35895
|
const opened2 = openPackageDir(source);
|
|
35261
35896
|
if (!opened2.validation.ok) {
|
|
@@ -35265,9 +35900,9 @@ async function resolvePackage(source, workDir) {
|
|
|
35265
35900
|
const app2 = opened2.header?.app ?? opened2.manifest?.app;
|
|
35266
35901
|
if (!app2) throw new Error(`${source} has no app id (no himi-package.json and no manifest.app)`);
|
|
35267
35902
|
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 (
|
|
35903
|
+
const root2 = workDir ?? mkdtempSync3(join44(tmpdir4(), "himi-run-"));
|
|
35904
|
+
const target = join44(root2, app2);
|
|
35905
|
+
if (join44(source) !== target) {
|
|
35271
35906
|
mkdirSync22(root2, { recursive: true });
|
|
35272
35907
|
rmSync7(target, { recursive: true, force: true });
|
|
35273
35908
|
cpSync(source, target, { recursive: true });
|
|
@@ -35285,7 +35920,7 @@ async function resolvePackage(source, workDir) {
|
|
|
35285
35920
|
throw new Error(`${source} is a directory but has no release-manifest.json \u2014 is it a package?`);
|
|
35286
35921
|
}
|
|
35287
35922
|
const bytes2 = isUrl2 ? await fetchBytes(source) : readFileSync52(source);
|
|
35288
|
-
const root = workDir ?? mkdtempSync3(
|
|
35923
|
+
const root = workDir ?? mkdtempSync3(join44(tmpdir4(), "himi-run-"));
|
|
35289
35924
|
const { app, appDir: appDir2 } = unpackTo(bytes2, root);
|
|
35290
35925
|
const opened = openPackageDir(appDir2);
|
|
35291
35926
|
if (!opened.validation.ok) {
|
|
@@ -35994,9 +36629,9 @@ __export(preflight_app_exports, {
|
|
|
35994
36629
|
pngSize: () => pngSize,
|
|
35995
36630
|
preflightApp: () => preflightApp
|
|
35996
36631
|
});
|
|
35997
|
-
import { readFileSync as readFileSync55, existsSync as existsSync46, readdirSync as readdirSync22, statSync as
|
|
36632
|
+
import { readFileSync as readFileSync55, existsSync as existsSync46, readdirSync as readdirSync22, statSync as statSync11 } from "node:fs";
|
|
35998
36633
|
import { createHash as createHash23 } from "node:crypto";
|
|
35999
|
-
import { join as
|
|
36634
|
+
import { join as join45 } from "node:path";
|
|
36000
36635
|
function analyze(projectYml, storeConfig, icon) {
|
|
36001
36636
|
const f = [];
|
|
36002
36637
|
const has = (re, s) => re.test(s);
|
|
@@ -36047,7 +36682,7 @@ async function preflightApp(app) {
|
|
|
36047
36682
|
const projectYml = existsSync46(iosProjectYml(app)) ? readFileSync55(iosProjectYml(app), "utf8") : "";
|
|
36048
36683
|
const storeConfig = existsSync46(storeConfigPath(app)) ? readFileSync55(storeConfigPath(app), "utf8") : "";
|
|
36049
36684
|
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(
|
|
36685
|
+
const findings = analyze(projectYml, storeConfig, await appIconState(join45(appDir(app), "ios")));
|
|
36051
36686
|
findings.push(...analyzeListing(metadataFilesPresent(app), listScreenshots(app)));
|
|
36052
36687
|
findings.push(
|
|
36053
36688
|
...analyzePlayListing(playListingAssets(app)).map((finding) => ({ ...finding, level: "warn" }))
|
|
@@ -36074,16 +36709,16 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
36074
36709
|
return f;
|
|
36075
36710
|
}
|
|
36076
36711
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
36077
|
-
const root =
|
|
36712
|
+
const root = join45(storeDir(app), "metadata");
|
|
36078
36713
|
const out = /* @__PURE__ */ new Set();
|
|
36079
36714
|
if (existsSync46(root)) {
|
|
36080
36715
|
for (const n of readdirSync22(root)) if (n.endsWith(".txt")) out.add(n);
|
|
36081
36716
|
}
|
|
36082
|
-
if (existsSync46(
|
|
36717
|
+
if (existsSync46(join45(root, locale, "privacy_url.txt"))) out.add("privacy_url.txt");
|
|
36083
36718
|
return out;
|
|
36084
36719
|
}
|
|
36085
36720
|
function reviewInfoFiles(app) {
|
|
36086
|
-
const dir =
|
|
36721
|
+
const dir = join45(storeDir(app), "review_information");
|
|
36087
36722
|
if (!existsSync46(dir)) return /* @__PURE__ */ new Set();
|
|
36088
36723
|
return new Set(readdirSync22(dir).filter((n) => n.endsWith(".txt")));
|
|
36089
36724
|
}
|
|
@@ -36194,12 +36829,12 @@ function analyzePlayListing(assets) {
|
|
|
36194
36829
|
return f;
|
|
36195
36830
|
}
|
|
36196
36831
|
function playListingAssets(app, locale = "en-US") {
|
|
36197
|
-
const dir =
|
|
36832
|
+
const dir = join45(storeDir(app), "play", locale, "images");
|
|
36198
36833
|
const read = (names) => {
|
|
36199
36834
|
for (const name of names) {
|
|
36200
|
-
const p =
|
|
36835
|
+
const p = join45(dir, name);
|
|
36201
36836
|
try {
|
|
36202
|
-
if (
|
|
36837
|
+
if (statSync11(p).isFile()) return { name, bytes: readFileSync55(p) };
|
|
36203
36838
|
} catch {
|
|
36204
36839
|
}
|
|
36205
36840
|
}
|
|
@@ -36230,26 +36865,26 @@ function analyzeListing(metaFiles, shots) {
|
|
|
36230
36865
|
return f;
|
|
36231
36866
|
}
|
|
36232
36867
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
36233
|
-
const dir =
|
|
36868
|
+
const dir = join45(storeDir(app), "metadata", locale);
|
|
36234
36869
|
if (!existsSync46(dir)) return /* @__PURE__ */ new Set();
|
|
36235
36870
|
return new Set(readdirSync22(dir).filter((n) => n.endsWith(".txt")));
|
|
36236
36871
|
}
|
|
36237
36872
|
function listScreenshots(app, locale = "en-US") {
|
|
36238
36873
|
const out = [];
|
|
36239
|
-
const flat =
|
|
36874
|
+
const flat = join45(storeDir(app), "screenshots", locale);
|
|
36240
36875
|
if (existsSync46(flat)) {
|
|
36241
36876
|
for (const png of readdirSync22(flat).filter((n) => n.endsWith(".png"))) {
|
|
36242
|
-
const sz = pngSize(readFileSync55(
|
|
36877
|
+
const sz = pngSize(readFileSync55(join45(flat, png)));
|
|
36243
36878
|
if (sz) out.push({ name: png, w: sz.w, h: sz.h });
|
|
36244
36879
|
}
|
|
36245
36880
|
}
|
|
36246
|
-
const legacy =
|
|
36881
|
+
const legacy = join45(storeDir(app), "metadata", locale, "screenshots");
|
|
36247
36882
|
if (existsSync46(legacy)) {
|
|
36248
36883
|
for (const deviceDir of readdirSync22(legacy)) {
|
|
36249
|
-
const d =
|
|
36250
|
-
if (!
|
|
36884
|
+
const d = join45(legacy, deviceDir);
|
|
36885
|
+
if (!statSync11(d).isDirectory()) continue;
|
|
36251
36886
|
for (const png of readdirSync22(d).filter((n) => n.endsWith(".png"))) {
|
|
36252
|
-
const sz = pngSize(readFileSync55(
|
|
36887
|
+
const sz = pngSize(readFileSync55(join45(d, png)));
|
|
36253
36888
|
if (sz) out.push({ name: `${deviceDir}/${png}`, w: sz.w, h: sz.h });
|
|
36254
36889
|
}
|
|
36255
36890
|
}
|
|
@@ -36257,12 +36892,12 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
36257
36892
|
return out;
|
|
36258
36893
|
}
|
|
36259
36894
|
function placeholderHashes2() {
|
|
36260
|
-
const templateIos =
|
|
36895
|
+
const templateIos = join45(appDir("_template"), "ios");
|
|
36261
36896
|
if (!existsSync46(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
36262
36897
|
for (const target of readdirSync22(templateIos)) {
|
|
36263
|
-
const p =
|
|
36898
|
+
const p = join45(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
36264
36899
|
try {
|
|
36265
|
-
if (!
|
|
36900
|
+
if (!statSync11(p).isFile()) continue;
|
|
36266
36901
|
return [LEGACY_PLACEHOLDER_SHA2562, createHash23("sha256").update(readFileSync55(p)).digest("hex")];
|
|
36267
36902
|
} catch {
|
|
36268
36903
|
}
|
|
@@ -36296,9 +36931,9 @@ async function pixelIssues(bytes2) {
|
|
|
36296
36931
|
async function appIconState(iosDir) {
|
|
36297
36932
|
if (!existsSync46(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
36298
36933
|
for (const target of readdirSync22(iosDir)) {
|
|
36299
|
-
const p =
|
|
36934
|
+
const p = join45(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
36300
36935
|
try {
|
|
36301
|
-
if (!
|
|
36936
|
+
if (!statSync11(p).isFile()) continue;
|
|
36302
36937
|
const bytes2 = readFileSync55(p);
|
|
36303
36938
|
const hash = createHash23("sha256").update(bytes2).digest("hex");
|
|
36304
36939
|
const pixels = await pixelIssues(bytes2);
|
|
@@ -36371,12 +37006,12 @@ __export(credential_profile_exports, {
|
|
|
36371
37006
|
});
|
|
36372
37007
|
import { existsSync as existsSync47, readFileSync as readFileSync56 } from "node:fs";
|
|
36373
37008
|
import { homedir as homedir6 } from "node:os";
|
|
36374
|
-
import { join as
|
|
37009
|
+
import { join as join46 } from "node:path";
|
|
36375
37010
|
function credentialsDir(home = homedir6()) {
|
|
36376
|
-
return
|
|
37011
|
+
return join46(home, ".himalaya", "store-credentials");
|
|
36377
37012
|
}
|
|
36378
37013
|
function profilePath(name, home = homedir6()) {
|
|
36379
|
-
return
|
|
37014
|
+
return join46(credentialsDir(home), `${name}.json`);
|
|
36380
37015
|
}
|
|
36381
37016
|
function parseProfile(text2, label2) {
|
|
36382
37017
|
let doc;
|
|
@@ -39889,7 +40524,7 @@ var init_brand_font = __esm({
|
|
|
39889
40524
|
|
|
39890
40525
|
// src/site-analyze/write-artifacts.ts
|
|
39891
40526
|
import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync20 } from "node:fs";
|
|
39892
|
-
import { join as
|
|
40527
|
+
import { join as join47 } from "node:path";
|
|
39893
40528
|
function attachVeloSources(book, sources, put) {
|
|
39894
40529
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
39895
40530
|
for (const f of book.velo.files) {
|
|
@@ -40044,12 +40679,12 @@ async function downloadMedia(book, fetchImpl, put) {
|
|
|
40044
40679
|
}
|
|
40045
40680
|
async function writeBusinessBook(result, opts) {
|
|
40046
40681
|
const out = opts.outDir;
|
|
40047
|
-
mkdirSync23(
|
|
40048
|
-
mkdirSync23(
|
|
40682
|
+
mkdirSync23(join47(out, "evidence/pages"), { recursive: true });
|
|
40683
|
+
mkdirSync23(join47(out, "media/catalog"), { recursive: true });
|
|
40049
40684
|
const files = [];
|
|
40050
40685
|
const put = (rel, body) => {
|
|
40051
|
-
const p =
|
|
40052
|
-
mkdirSync23(
|
|
40686
|
+
const p = join47(out, rel);
|
|
40687
|
+
mkdirSync23(join47(p, ".."), { recursive: true });
|
|
40053
40688
|
writeFileSync20(p, body);
|
|
40054
40689
|
files.push(rel);
|
|
40055
40690
|
};
|
|
@@ -40380,8 +41015,8 @@ var init_home_descriptor = __esm({
|
|
|
40380
41015
|
});
|
|
40381
41016
|
|
|
40382
41017
|
// src/site-analyze/apply.ts
|
|
40383
|
-
import { existsSync as existsSync48, readFileSync as readFileSync60, writeFileSync as writeFileSync21, copyFileSync as copyFileSync3, mkdirSync as mkdirSync24, realpathSync as
|
|
40384
|
-
import { dirname as dirname28, isAbsolute as isAbsolute3, join as
|
|
41018
|
+
import { existsSync as existsSync48, readFileSync as readFileSync60, writeFileSync as writeFileSync21, copyFileSync as copyFileSync3, mkdirSync as mkdirSync24, realpathSync as realpathSync5, statSync as statSync12 } from "node:fs";
|
|
41019
|
+
import { dirname as dirname28, isAbsolute as isAbsolute3, join as join48, resolve as resolve37, sep as sep10 } from "node:path";
|
|
40385
41020
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
40386
41021
|
function unpairedRedirectNote(overlay) {
|
|
40387
41022
|
if (!overlay.wix?.clientId || overlay.wix.redirectUri) return void 0;
|
|
@@ -40396,7 +41031,7 @@ function committedShellProvisioning(path) {
|
|
|
40396
41031
|
function findRepoRoot(cwd) {
|
|
40397
41032
|
let dir = cwd;
|
|
40398
41033
|
for (let i = 0; i < 8; i++) {
|
|
40399
|
-
if (SHELL_NAMES2.some((name) => existsSync48(
|
|
41034
|
+
if (SHELL_NAMES2.some((name) => existsSync48(join48(dir, shellAppDir(name), "package.json")))) return dir;
|
|
40400
41035
|
const next = dirname28(dir);
|
|
40401
41036
|
if (next === dir) break;
|
|
40402
41037
|
dir = next;
|
|
@@ -40464,7 +41099,7 @@ function mergeCustomerOwned(committed, overlay) {
|
|
|
40464
41099
|
}
|
|
40465
41100
|
function buildMergedContract(options) {
|
|
40466
41101
|
const { appDir: appDir2, packageDir, overlay } = options;
|
|
40467
|
-
const committedPath =
|
|
41102
|
+
const committedPath = join48(appDir2, "provisioning.json");
|
|
40468
41103
|
if (!existsSync48(committedPath)) {
|
|
40469
41104
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
40470
41105
|
}
|
|
@@ -40476,23 +41111,23 @@ function buildMergedContract(options) {
|
|
|
40476
41111
|
const contained = (root, rel) => {
|
|
40477
41112
|
if (isAbsolute3(rel)) return void 0;
|
|
40478
41113
|
const full = resolve37(root, rel);
|
|
40479
|
-
return full.startsWith(resolve37(root) +
|
|
41114
|
+
return full.startsWith(resolve37(root) + sep10) ? full : void 0;
|
|
40480
41115
|
};
|
|
40481
41116
|
const stage = (fromRel, toRel) => {
|
|
40482
41117
|
const from = contained(packageDir, fromRel);
|
|
40483
|
-
const to = contained(
|
|
41118
|
+
const to = contained(join48(appDir2, STAGED), toRel.slice(STAGED.length + 1));
|
|
40484
41119
|
if (!from || !to || !existsSync48(from)) return void 0;
|
|
40485
41120
|
let real;
|
|
40486
41121
|
let realRoot;
|
|
40487
41122
|
try {
|
|
40488
|
-
real =
|
|
40489
|
-
realRoot =
|
|
41123
|
+
real = realpathSync5(from);
|
|
41124
|
+
realRoot = realpathSync5(packageDir);
|
|
40490
41125
|
} catch {
|
|
40491
41126
|
return void 0;
|
|
40492
41127
|
}
|
|
40493
|
-
if (!real.startsWith(realRoot +
|
|
41128
|
+
if (!real.startsWith(realRoot + sep10)) return void 0;
|
|
40494
41129
|
try {
|
|
40495
|
-
if (!
|
|
41130
|
+
if (!statSync12(real).isFile()) return void 0;
|
|
40496
41131
|
mkdirSync24(dirname28(to), { recursive: true });
|
|
40497
41132
|
copyFileSync3(real, to);
|
|
40498
41133
|
} catch {
|
|
@@ -40503,7 +41138,7 @@ function buildMergedContract(options) {
|
|
|
40503
41138
|
};
|
|
40504
41139
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
40505
41140
|
if (icon) branding.appIconPath = icon;
|
|
40506
|
-
const facesPath =
|
|
41141
|
+
const facesPath = join48(packageDir, "media/fonts/faces.json");
|
|
40507
41142
|
if (existsSync48(facesPath)) {
|
|
40508
41143
|
let faces = [];
|
|
40509
41144
|
try {
|
|
@@ -40528,9 +41163,9 @@ function buildMergedContract(options) {
|
|
|
40528
41163
|
merged.branding = branding;
|
|
40529
41164
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
40530
41165
|
`;
|
|
40531
|
-
const path =
|
|
41166
|
+
const path = join48(packageDir, "provisioning.contract.json");
|
|
40532
41167
|
writeFileSync21(path, body);
|
|
40533
|
-
const localPath =
|
|
41168
|
+
const localPath = join48(appDir2, LOCAL_CONTRACT_REL);
|
|
40534
41169
|
mkdirSync24(dirname28(localPath), { recursive: true });
|
|
40535
41170
|
writeFileSync21(localPath, body);
|
|
40536
41171
|
staged.push(localPath);
|
|
@@ -40551,7 +41186,7 @@ async function applyOverlays(input) {
|
|
|
40551
41186
|
`shell "${shell}" cannot bake a customer brand \u2014 it ships no prepare:customer script`
|
|
40552
41187
|
);
|
|
40553
41188
|
}
|
|
40554
|
-
const appDir2 =
|
|
41189
|
+
const appDir2 = join48(repoRoot2, shellAppDir(shell));
|
|
40555
41190
|
const packageDir = dirname28(resolve37(input.overlayPath));
|
|
40556
41191
|
const { path: contract, staged } = buildMergedContract({ appDir: appDir2, packageDir, overlay });
|
|
40557
41192
|
wrote.push(...staged);
|
|
@@ -40573,7 +41208,7 @@ async function applyOverlays(input) {
|
|
|
40573
41208
|
note: `prepare:customer --contract with a merged contract (committed provisioning.json untouched)${unpairedInRepo ? ` \xB7 ${unpairedInRepo}` : ""}`
|
|
40574
41209
|
};
|
|
40575
41210
|
}
|
|
40576
|
-
const pkgProv =
|
|
41211
|
+
const pkgProv = join48(cwd, "provisioning.json");
|
|
40577
41212
|
assertNotCommitted(pkgProv, input.forbiddenProvisioning);
|
|
40578
41213
|
if (existsSync48(pkgProv)) {
|
|
40579
41214
|
const cur = JSON.parse(readFileSync60(pkgProv, "utf8"));
|
|
@@ -40584,7 +41219,7 @@ async function applyOverlays(input) {
|
|
|
40584
41219
|
writeFileSync21(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
40585
41220
|
wrote.push(pkgProv);
|
|
40586
41221
|
}
|
|
40587
|
-
const pkgTokens =
|
|
41222
|
+
const pkgTokens = join48(cwd, "tokens.json");
|
|
40588
41223
|
if (existsSync48(pkgTokens) && (tokens.colors || tokens.typography)) {
|
|
40589
41224
|
const cur = JSON.parse(readFileSync60(pkgTokens, "utf8"));
|
|
40590
41225
|
const merged = deepMerge3(cur, tokens);
|
|
@@ -40592,7 +41227,7 @@ async function applyOverlays(input) {
|
|
|
40592
41227
|
wrote.push(pkgTokens);
|
|
40593
41228
|
}
|
|
40594
41229
|
const homeAction = homeRefreshActionId(shell);
|
|
40595
|
-
const homeSrc =
|
|
41230
|
+
const homeSrc = join48(cwd, "dev/index.ts");
|
|
40596
41231
|
if (homeAction && existsSync48(homeSrc)) {
|
|
40597
41232
|
const prev = readFileSync60(homeSrc, "utf8");
|
|
40598
41233
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
@@ -42576,11 +43211,11 @@ var init_site_oauth_client = __esm({
|
|
|
42576
43211
|
});
|
|
42577
43212
|
|
|
42578
43213
|
// src/cli.ts
|
|
42579
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync63, mkdirSync as mkdirSync25, writeFileSync as writeFileSync23, existsSync as existsSync50, rmSync as rmSync8, readdirSync as readdirSync23, statSync as
|
|
43214
|
+
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync63, mkdirSync as mkdirSync25, writeFileSync as writeFileSync23, existsSync as existsSync50, rmSync as rmSync8, readdirSync as readdirSync23, statSync as statSync13 } from "node:fs";
|
|
42580
43215
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
42581
43216
|
import { createHash as createHash24 } from "node:crypto";
|
|
42582
43217
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
42583
|
-
import { join as
|
|
43218
|
+
import { join as join49, resolve as resolve39, basename as basename8, dirname as dirname29 } from "node:path";
|
|
42584
43219
|
import { fileURLToPath as fileURLToPath21 } from "node:url";
|
|
42585
43220
|
|
|
42586
43221
|
// ../serve-cli/src/client.ts
|
|
@@ -45088,10 +45723,10 @@ async function runRemoteSecretsCommand(operation, flags, io, options) {
|
|
|
45088
45723
|
// src/notify.ts
|
|
45089
45724
|
import { chmodSync as chmodSync2, mkdirSync as mkdirSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "node:fs";
|
|
45090
45725
|
import { homedir as homedir3 } from "node:os";
|
|
45091
|
-
import { dirname as dirname12, join as
|
|
45726
|
+
import { dirname as dirname12, join as join15 } from "node:path";
|
|
45092
45727
|
var DEFAULT_ADMIN_URL = "http://127.0.0.1:8888";
|
|
45093
45728
|
function defaultSessionsPath() {
|
|
45094
|
-
return process.env.HIMI_ADMIN_SESSIONS_FILE ??
|
|
45729
|
+
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join15(homedir3(), ".himalaya", "admin-sessions.json");
|
|
45095
45730
|
}
|
|
45096
45731
|
function loadSessionsFile(path = defaultSessionsPath()) {
|
|
45097
45732
|
try {
|
|
@@ -45330,7 +45965,7 @@ NOTE: ${simulated} of those went to the booted iOS Simulator, NOT to the device
|
|
|
45330
45965
|
init_car();
|
|
45331
45966
|
init_preview_surfaces();
|
|
45332
45967
|
import { existsSync as existsSync12, readFileSync as readFileSync15 } from "node:fs";
|
|
45333
|
-
import { join as
|
|
45968
|
+
import { join as join16 } from "node:path";
|
|
45334
45969
|
var VALID_PLATFORM_KEYS = /* @__PURE__ */ new Set([
|
|
45335
45970
|
...PREVIEW_SURFACES.map((s) => s.platformKey).filter((k) => k !== null),
|
|
45336
45971
|
...PREVIEW_EXEMPT_PLATFORM_KEYS
|
|
@@ -45341,7 +45976,7 @@ function surfaceIssues(dir, surfaceNav, strict) {
|
|
|
45341
45976
|
const error = (message) => issues.push({ screen: null, pass: "surfaces", severity: "error", message });
|
|
45342
45977
|
let platforms = {};
|
|
45343
45978
|
let envelopeUnreadable = false;
|
|
45344
|
-
const p =
|
|
45979
|
+
const p = join16(dir, "platforms.json");
|
|
45345
45980
|
if (existsSync12(p)) {
|
|
45346
45981
|
let raw;
|
|
45347
45982
|
try {
|
|
@@ -45374,7 +46009,7 @@ function surfaceIssues(dir, surfaceNav, strict) {
|
|
|
45374
46009
|
});
|
|
45375
46010
|
}
|
|
45376
46011
|
if (envelopeUnreadable) return issues;
|
|
45377
|
-
const configTs =
|
|
46012
|
+
const configTs = join16(dir, "config.ts");
|
|
45378
46013
|
if (existsSync12(configTs)) {
|
|
45379
46014
|
const declared = parseCarConfig(readFileSync15(configTs, "utf8")).category;
|
|
45380
46015
|
const inEnvelope = platforms.androidauto === true;
|
|
@@ -45400,7 +46035,7 @@ function surfaceIssues(dir, surfaceNav, strict) {
|
|
|
45400
46035
|
}
|
|
45401
46036
|
function readLocalPlatforms(dir) {
|
|
45402
46037
|
try {
|
|
45403
|
-
const raw = JSON.parse(readFileSync15(
|
|
46038
|
+
const raw = JSON.parse(readFileSync15(join16(dir, "platforms.json"), "utf8"));
|
|
45404
46039
|
return Object.fromEntries(
|
|
45405
46040
|
Object.entries(raw).filter(([k, v]) => VALID_PLATFORM_KEYS.has(k) && typeof v === "boolean")
|
|
45406
46041
|
);
|
|
@@ -45412,10 +46047,10 @@ function readLocalPlatforms(dir) {
|
|
|
45412
46047
|
// src/token-lint.ts
|
|
45413
46048
|
init_token_colors();
|
|
45414
46049
|
import { existsSync as existsSync13, readFileSync as readFileSync16 } from "node:fs";
|
|
45415
|
-
import { join as
|
|
46050
|
+
import { join as join17 } from "node:path";
|
|
45416
46051
|
function configuredTokensPath(dir) {
|
|
45417
46052
|
for (const name of ["config.ts", "config.js", "himi.config.ts"]) {
|
|
45418
|
-
const f =
|
|
46053
|
+
const f = join17(dir, name);
|
|
45419
46054
|
if (!existsSync13(f)) continue;
|
|
45420
46055
|
const src = readFileSync16(f, "utf8");
|
|
45421
46056
|
const m = /designTokensPath\s*:\s*["'`]([^"'`]+)["'`]/.exec(src);
|
|
@@ -45435,7 +46070,7 @@ function tokenColorIssues(dir, tokensPathOverride) {
|
|
|
45435
46070
|
);
|
|
45436
46071
|
}
|
|
45437
46072
|
const tokensPath = configured.path ?? "tokens.json";
|
|
45438
|
-
const p =
|
|
46073
|
+
const p = join17(dir, tokensPath);
|
|
45439
46074
|
if (!existsSync13(p)) {
|
|
45440
46075
|
if (tokensPath !== "tokens.json") {
|
|
45441
46076
|
warn(`config designTokensPath points at ${tokensPath}, which does not exist -- colour tokens were not checked`);
|
|
@@ -45483,9 +46118,9 @@ function tokenColorIssues(dir, tokensPathOverride) {
|
|
|
45483
46118
|
// src/icon-lint.ts
|
|
45484
46119
|
init_icon();
|
|
45485
46120
|
import { existsSync as existsSync16 } from "node:fs";
|
|
45486
|
-
import { join as
|
|
46121
|
+
import { join as join20 } from "node:path";
|
|
45487
46122
|
async function iconIssues(dir, strict, opts = {}) {
|
|
45488
|
-
if (!existsSync16(
|
|
46123
|
+
if (!existsSync16(join20(dir, "himalaya.content.json"))) return [];
|
|
45489
46124
|
const status = await iconStatus(dir);
|
|
45490
46125
|
const issue2 = (severity, message) => ({
|
|
45491
46126
|
screen: null,
|
|
@@ -45553,13 +46188,13 @@ function fontIssues(dir, strict) {
|
|
|
45553
46188
|
|
|
45554
46189
|
// src/stores-api-lint.ts
|
|
45555
46190
|
import { existsSync as existsSync20, readdirSync as readdirSync10, readFileSync as readFileSync22 } from "node:fs";
|
|
45556
|
-
import { join as
|
|
46191
|
+
import { join as join24 } from "node:path";
|
|
45557
46192
|
function storesV1Issues(contentDir2, strict) {
|
|
45558
|
-
const roots = [
|
|
46193
|
+
const roots = [join24(contentDir2, "tier5-src"), join24(contentDir2, "dev")].filter(existsSync20);
|
|
45559
46194
|
const files = [];
|
|
45560
46195
|
const visit = (dir) => {
|
|
45561
46196
|
for (const entry of readdirSync10(dir, { withFileTypes: true })) {
|
|
45562
|
-
const path =
|
|
46197
|
+
const path = join24(dir, entry.name);
|
|
45563
46198
|
if (entry.isDirectory()) visit(path);
|
|
45564
46199
|
else if (/\.(?:[cm]?[jt]sx?)$/i.test(entry.name)) files.push(path);
|
|
45565
46200
|
}
|
|
@@ -45580,7 +46215,7 @@ init_crawl_layers();
|
|
|
45580
46215
|
init_wix_gateway_rules();
|
|
45581
46216
|
init_mobile_ux_contract();
|
|
45582
46217
|
import { existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync23, readdirSync as readdirSync11, writeFileSync as writeFileSync9 } from "node:fs";
|
|
45583
|
-
import { join as
|
|
46218
|
+
import { join as join25, relative as relative3, resolve as resolve15 } from "node:path";
|
|
45584
46219
|
var EVIDENCE_RELATIVE_PATH = ".himi/ux-audit.json";
|
|
45585
46220
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".json"]);
|
|
45586
46221
|
var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".himi", "coverage"]);
|
|
@@ -45598,12 +46233,12 @@ function walkSource(dir, root = dir) {
|
|
|
45598
46233
|
const found = [];
|
|
45599
46234
|
for (const entry of readdirSync11(dir, { withFileTypes: true })) {
|
|
45600
46235
|
if (entry.isDirectory()) {
|
|
45601
|
-
if (!IGNORED_DIRECTORIES.has(entry.name)) found.push(...walkSource(
|
|
46236
|
+
if (!IGNORED_DIRECTORIES.has(entry.name)) found.push(...walkSource(join25(dir, entry.name), root));
|
|
45602
46237
|
continue;
|
|
45603
46238
|
}
|
|
45604
46239
|
const ext = entry.name.slice(entry.name.lastIndexOf("."));
|
|
45605
46240
|
if (!SOURCE_EXTENSIONS.has(ext)) continue;
|
|
45606
|
-
const absolute =
|
|
46241
|
+
const absolute = join25(dir, entry.name);
|
|
45607
46242
|
const text2 = readText(absolute);
|
|
45608
46243
|
if (text2 !== null) found.push({ path: relative3(root, absolute), text: text2 });
|
|
45609
46244
|
}
|
|
@@ -45633,9 +46268,9 @@ function usesAppNetwork(source) {
|
|
|
45633
46268
|
function auditUx(content, strict = false) {
|
|
45634
46269
|
const dir = resolve15(content);
|
|
45635
46270
|
const issues = [];
|
|
45636
|
-
const evidencePath =
|
|
45637
|
-
const spec = readText(
|
|
45638
|
-
const mobile = readText(
|
|
46271
|
+
const evidencePath = join25(dir, EVIDENCE_RELATIVE_PATH);
|
|
46272
|
+
const spec = readText(join25(dir, "SPEC.md"));
|
|
46273
|
+
const mobile = readText(join25(dir, "MOBILE-UX.md"));
|
|
45639
46274
|
if (!spec) issue(issues, strict, "missing-spec", "SPEC.md is missing; define the customer task before calling this UX-ready.", "SPEC.md");
|
|
45640
46275
|
if (!mobile) {
|
|
45641
46276
|
issue(issues, strict, "missing-mobile-ux", "MOBILE-UX.md is missing; add the mobile state and platform contract.", "MOBILE-UX.md");
|
|
@@ -45674,7 +46309,7 @@ function auditUx(content, strict = false) {
|
|
|
45674
46309
|
const preview = matches(previewControl);
|
|
45675
46310
|
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
46311
|
if (usesAppNetwork(source)) {
|
|
45677
|
-
const mocksPath =
|
|
46312
|
+
const mocksPath = join25(dir, "dev", "net-mocks.json");
|
|
45678
46313
|
if (!existsSync21(mocksPath)) {
|
|
45679
46314
|
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
46315
|
} else {
|
|
@@ -45696,12 +46331,12 @@ function recordNativeAudit(content, platform, status, checks, reason) {
|
|
|
45696
46331
|
if (!normalizedChecks.length) throw new Error("--checks needs at least one comma-separated check (for example: back,keyboard,voiceover)");
|
|
45697
46332
|
if (status === "unavailable" && !reason?.trim()) throw new Error("--reason is required when --status unavailable");
|
|
45698
46333
|
const dir = resolve15(content);
|
|
45699
|
-
const path =
|
|
46334
|
+
const path = join25(dir, EVIDENCE_RELATIVE_PATH);
|
|
45700
46335
|
const parsed = parseEvidence(path);
|
|
45701
46336
|
if (parsed.error) throw new Error(`${EVIDENCE_RELATIVE_PATH} ${parsed.error}`);
|
|
45702
46337
|
const evidence = parsed.evidence ?? { version: 1, platforms: {} };
|
|
45703
46338
|
evidence.platforms[platform] = { status, checks: normalizedChecks, ...reason?.trim() ? { reason: reason.trim() } : {}, recordedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
45704
|
-
mkdirSync10(
|
|
46339
|
+
mkdirSync10(join25(dir, ".himi"), { recursive: true });
|
|
45705
46340
|
writeFileSync9(path, JSON.stringify(evidence, null, 2) + "\n");
|
|
45706
46341
|
return evidence;
|
|
45707
46342
|
}
|
|
@@ -45710,26 +46345,26 @@ function recordNativeAudit(content, platform, status, checks, reason) {
|
|
|
45710
46345
|
init_mobile_ux_contract();
|
|
45711
46346
|
import { readFileSync as readFileSync24, existsSync as existsSync22, mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, copyFileSync as copyFileSync2 } from "node:fs";
|
|
45712
46347
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
45713
|
-
import { dirname as dirname15, join as
|
|
46348
|
+
import { dirname as dirname15, join as join26, resolve as resolve16 } from "node:path";
|
|
45714
46349
|
var GUIDES_DIR = resolve16(dirname15(fileURLToPath10(import.meta.url)), "../guides");
|
|
45715
46350
|
function guidesAvailable() {
|
|
45716
|
-
return existsSync22(
|
|
46351
|
+
return existsSync22(join26(GUIDES_DIR, "index.json"));
|
|
45717
46352
|
}
|
|
45718
46353
|
function loadIndex() {
|
|
45719
|
-
return JSON.parse(readFileSync24(
|
|
46354
|
+
return JSON.parse(readFileSync24(join26(GUIDES_DIR, "index.json"), "utf8"));
|
|
45720
46355
|
}
|
|
45721
46356
|
function readGuide(id) {
|
|
45722
46357
|
const meta = loadIndex().guides.find((g) => g.id === id);
|
|
45723
46358
|
if (!meta) return null;
|
|
45724
|
-
return readFileSync24(
|
|
46359
|
+
return readFileSync24(join26(GUIDES_DIR, meta.file), "utf8");
|
|
45725
46360
|
}
|
|
45726
46361
|
function loadComponentReference() {
|
|
45727
46362
|
const idx = loadIndex();
|
|
45728
|
-
return JSON.parse(readFileSync24(
|
|
46363
|
+
return JSON.parse(readFileSync24(join26(GUIDES_DIR, idx.componentReferenceFile), "utf8"));
|
|
45729
46364
|
}
|
|
45730
46365
|
function loadSdkReference() {
|
|
45731
46366
|
const idx = loadIndex();
|
|
45732
|
-
return JSON.parse(readFileSync24(
|
|
46367
|
+
return JSON.parse(readFileSync24(join26(GUIDES_DIR, idx.sdkReferenceFile), "utf8"));
|
|
45733
46368
|
}
|
|
45734
46369
|
function buildAgentPrimer() {
|
|
45735
46370
|
const idx = loadIndex();
|
|
@@ -45837,19 +46472,19 @@ function writeAgentContext(targetDir) {
|
|
|
45837
46472
|
const idx = loadIndex();
|
|
45838
46473
|
const files = [];
|
|
45839
46474
|
const write2 = (rel, body) => {
|
|
45840
|
-
const p =
|
|
46475
|
+
const p = join26(targetDir, rel);
|
|
45841
46476
|
mkdirSync11(dirname15(p), { recursive: true });
|
|
45842
46477
|
writeFileSync10(p, body);
|
|
45843
46478
|
files.push(rel);
|
|
45844
46479
|
};
|
|
45845
46480
|
const copy = (srcRel, destRel) => {
|
|
45846
|
-
const p =
|
|
46481
|
+
const p = join26(targetDir, destRel);
|
|
45847
46482
|
mkdirSync11(dirname15(p), { recursive: true });
|
|
45848
|
-
copyFileSync2(
|
|
46483
|
+
copyFileSync2(join26(GUIDES_DIR, srcRel), p);
|
|
45849
46484
|
files.push(destRel);
|
|
45850
46485
|
};
|
|
45851
46486
|
const writeIfMissing = (rel, body) => {
|
|
45852
|
-
if (existsSync22(
|
|
46487
|
+
if (existsSync22(join26(targetDir, rel))) return;
|
|
45853
46488
|
write2(rel, body);
|
|
45854
46489
|
};
|
|
45855
46490
|
write2("HIMALAYA.md", buildAgentPrimer());
|
|
@@ -45910,7 +46545,7 @@ var str5 = (v) => typeof v === "string" ? v : void 0;
|
|
|
45910
46545
|
var num = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
45911
46546
|
function embeddedTemplateCatalog() {
|
|
45912
46547
|
return availableTemplates().map((name) => {
|
|
45913
|
-
const path =
|
|
46548
|
+
const path = join49(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
45914
46549
|
const meta = JSON.parse(readFileSync63(path, "utf8"));
|
|
45915
46550
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
45916
46551
|
throw new Error(`${path} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
@@ -46377,7 +47012,7 @@ function packageVersion(path) {
|
|
|
46377
47012
|
function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("./authoring-runtime/node_modules/@wix/himalaya/package.json", import.meta.url)) {
|
|
46378
47013
|
let dir = resolve39(fromDir);
|
|
46379
47014
|
for (; ; ) {
|
|
46380
|
-
const version = packageVersion(
|
|
47015
|
+
const version = packageVersion(join49(dir, "node_modules", "@wix", "himalaya", "package.json"));
|
|
46381
47016
|
if (version) return { version, source: "local" };
|
|
46382
47017
|
const parent = dirname29(dir);
|
|
46383
47018
|
if (parent === dir) break;
|
|
@@ -46387,7 +47022,7 @@ function resolvedSdkVersion(fromDir = process.cwd(), bundledManifest = new URL("
|
|
|
46387
47022
|
if (bundled) return { version: bundled, source: "bundled" };
|
|
46388
47023
|
try {
|
|
46389
47024
|
const root = execFileSync6("npm", ["root", "-g"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
46390
|
-
const version = root ? packageVersion(
|
|
47025
|
+
const version = root ? packageVersion(join49(root, "@wix", "himalaya", "package.json")) : void 0;
|
|
46391
47026
|
return version ? { version, source: "global" } : {};
|
|
46392
47027
|
} catch {
|
|
46393
47028
|
return {};
|
|
@@ -46762,7 +47397,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
46762
47397
|
}
|
|
46763
47398
|
function readConfigSource(dir) {
|
|
46764
47399
|
try {
|
|
46765
|
-
return readFileSync63(
|
|
47400
|
+
return readFileSync63(join49(dir, "config.ts"), "utf8");
|
|
46766
47401
|
} catch {
|
|
46767
47402
|
return null;
|
|
46768
47403
|
}
|
|
@@ -46774,7 +47409,7 @@ function writePngFile(path, base64) {
|
|
|
46774
47409
|
}
|
|
46775
47410
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
46776
47411
|
const dir = resolve39(parentDir, name);
|
|
46777
|
-
if (existsSync50(
|
|
47412
|
+
if (existsSync50(join49(dir, "himalaya.content.json"))) {
|
|
46778
47413
|
throw new Error(`content package already exists at ${dir}`);
|
|
46779
47414
|
}
|
|
46780
47415
|
const r = await c.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -46791,7 +47426,7 @@ function contentDir(flags) {
|
|
|
46791
47426
|
function isHimalayaMonorepoCheckout(start) {
|
|
46792
47427
|
let dir = resolve39(start);
|
|
46793
47428
|
for (; ; ) {
|
|
46794
|
-
if (existsSync50(
|
|
47429
|
+
if (existsSync50(join49(dir, "tools", "himi-cli", "src", "cli.ts")) && existsSync50(join49(dir, "core", "serve", "src", "server.ts"))) return true;
|
|
46795
47430
|
const parent = dirname29(dir);
|
|
46796
47431
|
if (parent === dir) return false;
|
|
46797
47432
|
dir = parent;
|
|
@@ -46822,7 +47457,7 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
46822
47457
|
Object.entries(files).map(([rel, body]) => [rel, rel === "himalaya.content.json" ? substituteIdentity(body, slug) : body])
|
|
46823
47458
|
);
|
|
46824
47459
|
const repoRoot2 = resolve39(fileURLToPath21(new URL("../../..", import.meta.url)));
|
|
46825
|
-
const dest =
|
|
47460
|
+
const dest = join49(repoRoot2, "node_modules", ".cache", "himi-template-preview", slug);
|
|
46826
47461
|
rmSync8(dest, { recursive: true, force: true });
|
|
46827
47462
|
mkdirSync25(dest, { recursive: true });
|
|
46828
47463
|
materializeSource(forBuild, displayName, dest, slug);
|
|
@@ -46831,7 +47466,7 @@ function materializeForPreview(appDir2, slug, displayName) {
|
|
|
46831
47466
|
async function appId(dir) {
|
|
46832
47467
|
try {
|
|
46833
47468
|
const { readFileSync: readFileSync64 } = await import("node:fs");
|
|
46834
|
-
const m = JSON.parse(readFileSync64(
|
|
47469
|
+
const m = JSON.parse(readFileSync64(join49(dir, "himalaya.content.json"), "utf8"));
|
|
46835
47470
|
if (m.name) return m.name;
|
|
46836
47471
|
} catch {
|
|
46837
47472
|
}
|
|
@@ -46840,7 +47475,7 @@ async function appId(dir) {
|
|
|
46840
47475
|
async function contentVisibility(dir) {
|
|
46841
47476
|
try {
|
|
46842
47477
|
const { readFileSync: readFileSync64 } = await import("node:fs");
|
|
46843
|
-
const m = JSON.parse(readFileSync64(
|
|
47478
|
+
const m = JSON.parse(readFileSync64(join49(dir, "himalaya.content.json"), "utf8"));
|
|
46844
47479
|
if (m.visibility === "public" || m.visibility === "unlisted") return m.visibility;
|
|
46845
47480
|
} catch {
|
|
46846
47481
|
}
|
|
@@ -47079,6 +47714,7 @@ async function loadAuthoring() {
|
|
|
47079
47714
|
crawlScreen: crawl.crawlScreen,
|
|
47080
47715
|
crawlScreenJourney: crawl.crawlScreenJourney,
|
|
47081
47716
|
crawlScreenHostile: crawl.crawlScreenHostile,
|
|
47717
|
+
crawlScreenRelations: crawl.crawlScreenRelations,
|
|
47082
47718
|
findingKey: crawl.findingKey,
|
|
47083
47719
|
startWorkerCoverage: cov.startWorkerCoverage,
|
|
47084
47720
|
uncoveredFunctions: cov.uncoveredFunctions,
|
|
@@ -47241,7 +47877,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47241
47877
|
const sourceDir = resolve39(str5(flags["source-dir"]) ?? appDir2);
|
|
47242
47878
|
let meta;
|
|
47243
47879
|
try {
|
|
47244
|
-
meta = JSON.parse(readFileSync63(
|
|
47880
|
+
meta = JSON.parse(readFileSync63(join49(sourceDir, TEMPLATE_META_FILE), "utf8"));
|
|
47245
47881
|
} catch {
|
|
47246
47882
|
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
47883
|
return 2;
|
|
@@ -47251,7 +47887,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47251
47887
|
return 2;
|
|
47252
47888
|
}
|
|
47253
47889
|
try {
|
|
47254
|
-
const appearance = extractTemplateAppearance(JSON.parse(readFileSync63(
|
|
47890
|
+
const appearance = extractTemplateAppearance(JSON.parse(readFileSync63(join49(sourceDir, "tokens.json"), "utf8")));
|
|
47255
47891
|
meta = { ...appearance, ...meta };
|
|
47256
47892
|
} catch {
|
|
47257
47893
|
}
|
|
@@ -47263,7 +47899,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47263
47899
|
const force = flags.force === true;
|
|
47264
47900
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
47265
47901
|
const bres = await buildContentForValidation2(buildDir, { resolution: resolutionFlag(flags) });
|
|
47266
|
-
const out = mkdtempSync4(
|
|
47902
|
+
const out = mkdtempSync4(join49(tmpdir5(), "himi-template-"));
|
|
47267
47903
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
47268
47904
|
const outcome = await buildReleaseFromContent2(buildDir, out, {
|
|
47269
47905
|
...hasWorkers ? { tier5Dir: bundleOutDir2(buildDir) } : {},
|
|
@@ -47422,7 +48058,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47422
48058
|
const { mobileUxIssues: mobileUxIssues2 } = await Promise.resolve().then(() => (init_mobile_ux_lint(), mobile_ux_lint_exports));
|
|
47423
48059
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
47424
48060
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
47425
|
-
const out = mkdtempSync4(
|
|
48061
|
+
const out = mkdtempSync4(join49(tmpdir5(), "himi-validate-"));
|
|
47426
48062
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
47427
48063
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
47428
48064
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -47610,7 +48246,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47610
48246
|
case "test": {
|
|
47611
48247
|
const dir = contentDir(flags);
|
|
47612
48248
|
const structuredOutput = flags.json === true || io.isTTY !== true;
|
|
47613
|
-
if (existsSync50(
|
|
48249
|
+
if (existsSync50(join49(dir, "functions"))) {
|
|
47614
48250
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
47615
48251
|
const loaded = await loadFunctionsApp2(dir);
|
|
47616
48252
|
const results = [];
|
|
@@ -47624,7 +48260,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47624
48260
|
return results.every((result2) => result2.ok) ? 0 : 1;
|
|
47625
48261
|
}
|
|
47626
48262
|
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();
|
|
48263
|
+
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
48264
|
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
48265
|
let config;
|
|
47630
48266
|
try {
|
|
@@ -47697,7 +48333,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47697
48333
|
}
|
|
47698
48334
|
}
|
|
47699
48335
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
47700
|
-
const out = mkdtempSync4(
|
|
48336
|
+
const out = mkdtempSync4(join49(tmpdir5(), "himi-test-"));
|
|
47701
48337
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
47702
48338
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
47703
48339
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -47742,7 +48378,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47742
48378
|
io.error(JSON.stringify({ error: `screen "${screen.screenId}" has no Tier-5 worker, so there is nothing for the browser loop to build` }));
|
|
47743
48379
|
return 2;
|
|
47744
48380
|
}
|
|
47745
|
-
const sources = collectWorkerSources2(
|
|
48381
|
+
const sources = collectWorkerSources2(join49(dir, "tier5-src"), screen.bundleName);
|
|
47746
48382
|
if (!sources) {
|
|
47747
48383
|
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
48384
|
return 2;
|
|
@@ -47862,7 +48498,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47862
48498
|
...deep ? { deep } : {},
|
|
47863
48499
|
...offline ? { offline: true } : {},
|
|
47864
48500
|
...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 }
|
|
48501
|
+
deps: { crawlScreen: crawlScreen2, crawlScreenJourney: crawlScreenJourney2, crawlScreenHostile: crawlScreenHostile2, crawlScreenRelations: crawlScreenRelations2, findingKey: findingKey2, startWorkerCoverage: startWorkerCoverage2, uncoveredFunctions: uncoveredFunctions2, crawlScreenDeep: crawlScreenDeep2, crawlSignature: crawlSignature2 }
|
|
47866
48502
|
});
|
|
47867
48503
|
} catch (e) {
|
|
47868
48504
|
io.error(JSON.stringify({ error: e.message }));
|
|
@@ -47899,7 +48535,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47899
48535
|
const sp = await runShotsPass2({
|
|
47900
48536
|
descriptors: scopeDescriptors2(outcome.descriptors ?? [], pos.slice(1), invalidScreens),
|
|
47901
48537
|
tokens: outcome.tokens,
|
|
47902
|
-
outDir:
|
|
48538
|
+
outDir: join49(dir, ".himi", "shots"),
|
|
47903
48539
|
width: 390,
|
|
47904
48540
|
layers: { rules: shotRules, ...cmsSeed ? { cmsSeed } : {}, ...canned ? { canned: canned.byKey } : {} },
|
|
47905
48541
|
...budgetMs ? { budgetMs } : {},
|
|
@@ -47935,7 +48571,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
47935
48571
|
releaseId: result.releaseId,
|
|
47936
48572
|
releasePayload: release,
|
|
47937
48573
|
descriptors: attestedDescriptors,
|
|
47938
|
-
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""),
|
|
48574
|
+
screenshots: Object.fromEntries(writtenShots.filter((name) => crawledScreens.has(name.replace(/\.png$/, ""))).map((name) => [name.replace(/\.png$/, ""), join49(dir, ".himi", "shots", name)])),
|
|
47939
48575
|
coverage: {
|
|
47940
48576
|
screens: crawledScreens.size,
|
|
47941
48577
|
actionsDispatched: result.actions.exercised,
|
|
@@ -48077,7 +48713,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
48077
48713
|
}
|
|
48078
48714
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
48079
48715
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
48080
|
-
const out = mkdtempSync4(
|
|
48716
|
+
const out = mkdtempSync4(join49(tmpdir5(), "himi-render-"));
|
|
48081
48717
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
48082
48718
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
48083
48719
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -48093,7 +48729,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
48093
48729
|
let attestationPngFile;
|
|
48094
48730
|
if (typeof flags.png === "string" && r.pngBase64) {
|
|
48095
48731
|
pngFile = writePngFile(str5(flags.png), r.pngBase64);
|
|
48096
|
-
attestationPngFile = writePngFile(
|
|
48732
|
+
attestationPngFile = writePngFile(join49(dir, ".himi", "shots", `${screenId}.png`), r.pngBase64);
|
|
48097
48733
|
}
|
|
48098
48734
|
const legacyRender = {
|
|
48099
48735
|
ok: r.renderable,
|
|
@@ -48400,7 +49036,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48400
49036
|
const renamed = str5(flags.name);
|
|
48401
49037
|
const dest = resolve39(str5(flags.out) ?? process.cwd(), renamed ?? wanted);
|
|
48402
49038
|
if (existsSync50(dest)) {
|
|
48403
|
-
if (!
|
|
49039
|
+
if (!statSync13(dest).isDirectory()) {
|
|
48404
49040
|
io.error(JSON.stringify({
|
|
48405
49041
|
error: `${dest} exists and is not a directory`,
|
|
48406
49042
|
hint: "pass --out/--name to land somewhere else, or remove the file"
|
|
@@ -48473,7 +49109,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48473
49109
|
const force = flags.force === true;
|
|
48474
49110
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
48475
49111
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
48476
|
-
const out = mkdtempSync4(
|
|
49112
|
+
const out = mkdtempSync4(join49(tmpdir5(), "himi-push-"));
|
|
48477
49113
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
48478
49114
|
const outcome = await buildReleaseFromContent2(dir, out, {
|
|
48479
49115
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -48765,7 +49401,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48765
49401
|
const force = flags.force === true;
|
|
48766
49402
|
const { buildContentForValidation: buildContentForValidation2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
48767
49403
|
const bres = await buildContentForValidation2(dir, { resolution: resolutionFlag(flags) });
|
|
48768
|
-
const built = mkdtempSync4(
|
|
49404
|
+
const built = mkdtempSync4(join49(tmpdir5(), "himi-pack-"));
|
|
48769
49405
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
48770
49406
|
const outcome = await buildReleaseFromContent2(dir, built, {
|
|
48771
49407
|
...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {},
|
|
@@ -48878,10 +49514,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
48878
49514
|
const app = await appId(dir);
|
|
48879
49515
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
48880
49516
|
const bres = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
48881
|
-
temp = mkdtempSync4(
|
|
49517
|
+
temp = mkdtempSync4(join49(tmpdir5(), "himi-run-build-"));
|
|
48882
49518
|
const hasWorkers = bres.built.length > 0 || bres.compileErrors.length > 0;
|
|
48883
49519
|
await buildReleaseFromContent2(dir, temp, { ...hasWorkers ? { tier5Dir: bundleOutDir2(dir) } : {} });
|
|
48884
|
-
source =
|
|
49520
|
+
source = join49(temp, app);
|
|
48885
49521
|
}
|
|
48886
49522
|
const chromeArg = str5(flags.chrome) ?? "preview";
|
|
48887
49523
|
if (chromeArg !== "preview" && chromeArg !== "app") {
|
|
@@ -49679,7 +50315,7 @@ ${label2}`);
|
|
|
49679
50315
|
const platform = str5(flags.platform)?.split(",").map((p) => p.trim()).filter(Boolean);
|
|
49680
50316
|
{
|
|
49681
50317
|
const distDir = contentDir(flags);
|
|
49682
|
-
if (existsSync50(
|
|
50318
|
+
if (existsSync50(join49(distDir, "himalaya.content.json"))) {
|
|
49683
50319
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
49684
50320
|
const errors = issues.filter((i) => i.severity === "error");
|
|
49685
50321
|
for (const i of issues.filter((i2) => i2.severity === "warning")) {
|