@wix/himalaya-cli 0.1533.0 → 0.1535.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 +1228 -542
- package/guides/one-app-to-himi-app.md +17 -0
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -2380,11 +2380,446 @@ var init_app_link = __esm({
|
|
|
2380
2380
|
});
|
|
2381
2381
|
|
|
2382
2382
|
// ../../core/serve-control/src/dist-jobs.ts
|
|
2383
|
-
var
|
|
2383
|
+
var dist_jobs_exports = {};
|
|
2384
|
+
__export(dist_jobs_exports, {
|
|
2385
|
+
ANDROID_FORMATS: () => ANDROID_FORMATS,
|
|
2386
|
+
ANDROID_FORMAT_NOT_BUILT: () => ANDROID_FORMAT_NOT_BUILT,
|
|
2387
|
+
ANDROID_FORMAT_NOT_REQUESTED: () => ANDROID_FORMAT_NOT_REQUESTED,
|
|
2388
|
+
ANDROID_FORMAT_WRONG_SIGNER: () => ANDROID_FORMAT_WRONG_SIGNER,
|
|
2389
|
+
ANDROID_SIGNING_ALIASES: () => ANDROID_SIGNING_ALIASES,
|
|
2390
|
+
ANDROID_SIGNING_POLICIES: () => ANDROID_SIGNING_POLICIES,
|
|
2391
|
+
CUSTOMER_UPLOAD_LEASE_MS: () => CUSTOMER_UPLOAD_LEASE_MS,
|
|
2392
|
+
DEFAULT_ANDROID_FORMAT: () => DEFAULT_ANDROID_FORMAT,
|
|
2393
|
+
DEFAULT_ANDROID_SIGNING: () => DEFAULT_ANDROID_SIGNING,
|
|
2394
|
+
DEFAULT_BORROWABLE_IOS_IDS: () => DEFAULT_BORROWABLE_IOS_IDS,
|
|
2395
|
+
DEFAULT_DIST_SHELL: () => DEFAULT_DIST_SHELL,
|
|
2396
|
+
DEFAULT_DIST_SIGNING: () => DEFAULT_DIST_SIGNING,
|
|
2397
|
+
DEFAULT_GIT_URL: () => DEFAULT_GIT_URL,
|
|
2398
|
+
DIST_PACKAGE_NAME: () => DIST_PACKAGE_NAME,
|
|
2399
|
+
DIST_PARAMS_FLAG: () => DIST_PARAMS_FLAG,
|
|
2400
|
+
DIST_SHELLS: () => DIST_SHELLS,
|
|
2401
|
+
JobServiceBroker: () => JobServiceBroker,
|
|
2402
|
+
JobServiceError: () => JobServiceError,
|
|
2403
|
+
MAX_MEASURABLE_IDENTITY_WINDOW: () => MAX_MEASURABLE_IDENTITY_WINDOW,
|
|
2404
|
+
SCOPE_CANCEL: () => SCOPE_CANCEL,
|
|
2405
|
+
SCOPE_CREATE: () => SCOPE_CREATE,
|
|
2406
|
+
SCOPE_READ: () => SCOPE_READ,
|
|
2407
|
+
WIX_MANAGED_SIGNING_ALIASES: () => WIX_MANAGED_SIGNING_ALIASES,
|
|
2408
|
+
androidFormatSkewFailed: () => androidFormatSkewFailed,
|
|
2409
|
+
borrowableIosIds: () => borrowableIosIds,
|
|
2410
|
+
credsFromConfig: () => credsFromConfig,
|
|
2411
|
+
customerUploadClaimable: () => customerUploadClaimable,
|
|
2412
|
+
distJobSpec: () => distJobSpec,
|
|
2413
|
+
encodeDistParams: () => encodeDistParams,
|
|
2414
|
+
isBorrowableIosId: () => isBorrowableIosId,
|
|
2415
|
+
isSuccess: () => isSuccess,
|
|
2416
|
+
isTerminal: () => isTerminal,
|
|
2417
|
+
isTerminalTestflightStatus: () => isTerminalTestflightStatus,
|
|
2418
|
+
isValidDistAttemptId: () => isValidDistAttemptId,
|
|
2419
|
+
nextCustomerUploadClaim: () => nextCustomerUploadClaim,
|
|
2420
|
+
nextCustomerUploadSettlement: () => nextCustomerUploadSettlement,
|
|
2421
|
+
resolveAndroidFormat: () => resolveAndroidFormat,
|
|
2422
|
+
resolveAndroidSigning: () => resolveAndroidSigning,
|
|
2423
|
+
resolveBorrowedIosId: () => resolveBorrowedIosId,
|
|
2424
|
+
resolveDistSigning: () => resolveDistSigning,
|
|
2425
|
+
testflightStatusRank: () => testflightStatusRank
|
|
2426
|
+
});
|
|
2427
|
+
function isTerminal(status) {
|
|
2428
|
+
return !!status && !IN_FLIGHT.has(status);
|
|
2429
|
+
}
|
|
2430
|
+
function isSuccess(status) {
|
|
2431
|
+
return status === "SUCCESS";
|
|
2432
|
+
}
|
|
2433
|
+
function snapshot(job) {
|
|
2434
|
+
return {
|
|
2435
|
+
id: String(job.id),
|
|
2436
|
+
status: job.status ?? "STATUS_UNKNOWN",
|
|
2437
|
+
...job.buildUrl ? { buildUrl: String(job.buildUrl) } : {},
|
|
2438
|
+
...job.output ? { output: String(job.output) } : {},
|
|
2439
|
+
...typeof job.attemptNumber === "number" ? { attemptNumber: job.attemptNumber } : {}
|
|
2440
|
+
};
|
|
2441
|
+
}
|
|
2442
|
+
function truncate(s2, max = 400) {
|
|
2443
|
+
return s2.length > max ? `${s2.slice(0, max)}\u2026` : s2;
|
|
2444
|
+
}
|
|
2445
|
+
function credsFromConfig(cfg) {
|
|
2446
|
+
const appDefId = cfg("POCO_APP_DEF_ID")?.trim();
|
|
2447
|
+
const appSecret = cfg("POCO_APP_SECRET")?.trim();
|
|
2448
|
+
if (!appDefId || !appSecret) return void 0;
|
|
2449
|
+
return { appDefId, appSecret };
|
|
2450
|
+
}
|
|
2451
|
+
function isValidDistAttemptId(value2) {
|
|
2452
|
+
return typeof value2 === "string" && /^[A-Za-z0-9_-]{1,128}$/.test(value2);
|
|
2453
|
+
}
|
|
2454
|
+
function customerUploadClaimable(pending, now) {
|
|
2455
|
+
if (!pending) return false;
|
|
2456
|
+
if (pending.status === "READY_FOR_UPLOAD") return true;
|
|
2457
|
+
if (pending.status !== "UPLOADING") return false;
|
|
2458
|
+
if (!pending.claimedAt) return true;
|
|
2459
|
+
const claimedAt = Date.parse(pending.claimedAt);
|
|
2460
|
+
const at2 = Date.parse(now);
|
|
2461
|
+
return Number.isFinite(claimedAt) && Number.isFinite(at2) && at2 - claimedAt >= CUSTOMER_UPLOAD_LEASE_MS;
|
|
2462
|
+
}
|
|
2463
|
+
function nextCustomerUploadClaim(record2, now) {
|
|
2464
|
+
if (!record2 || record2.status !== "SUCCESS" || !customerUploadClaimable(record2.customerAppStore, now)) return void 0;
|
|
2465
|
+
return {
|
|
2466
|
+
...record2,
|
|
2467
|
+
customerAppStore: { ...record2.customerAppStore, status: "UPLOADING", claimedAt: now },
|
|
2468
|
+
updatedAt: now
|
|
2469
|
+
};
|
|
2470
|
+
}
|
|
2471
|
+
function nextCustomerUploadSettlement(record2, claimedAt, update, now) {
|
|
2472
|
+
const pending = record2?.customerAppStore;
|
|
2473
|
+
if (!record2 || pending?.status !== "UPLOADING" || pending.claimedAt !== claimedAt) return void 0;
|
|
2474
|
+
return {
|
|
2475
|
+
...record2,
|
|
2476
|
+
customerAppStore: {
|
|
2477
|
+
version: pending.version,
|
|
2478
|
+
mode: pending.mode,
|
|
2479
|
+
claimedAt: pending.claimedAt,
|
|
2480
|
+
status: update.status,
|
|
2481
|
+
...update.error ? { error: update.error } : {},
|
|
2482
|
+
...update.delivery ? { delivery: update.delivery } : {}
|
|
2483
|
+
},
|
|
2484
|
+
updatedAt: now
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2487
|
+
function isTerminalTestflightStatus(status) {
|
|
2488
|
+
return /(?:^|_)(?:COMPLETED|FAILED|NOT_FOUND)$/.test(status?.toUpperCase() ?? "");
|
|
2489
|
+
}
|
|
2490
|
+
function testflightStatusRank(status) {
|
|
2491
|
+
const normalized = status?.toUpperCase() ?? "";
|
|
2492
|
+
if (isTerminalTestflightStatus(normalized)) return 3;
|
|
2493
|
+
if (/(?:^|_)UPLOADING$/.test(normalized)) return 2;
|
|
2494
|
+
if (/(?:^|_)PENDING$/.test(normalized)) return 1;
|
|
2495
|
+
return 0;
|
|
2496
|
+
}
|
|
2497
|
+
function borrowableIosIds(raw) {
|
|
2498
|
+
const parsed = (raw ?? "").split(",").map((s2) => s2.trim().toLowerCase()).filter(Boolean);
|
|
2499
|
+
return parsed.length > 0 ? parsed : DEFAULT_BORROWABLE_IOS_IDS;
|
|
2500
|
+
}
|
|
2501
|
+
function isBorrowableIosId(id, allowed2 = DEFAULT_BORROWABLE_IOS_IDS) {
|
|
2502
|
+
const candidate = id.toLowerCase();
|
|
2503
|
+
return allowed2.some(
|
|
2504
|
+
(pattern) => pattern.endsWith("*") ? candidate.startsWith(pattern.slice(0, -1)) : candidate === pattern
|
|
2505
|
+
);
|
|
2506
|
+
}
|
|
2507
|
+
function resolveBorrowedIosId(opts) {
|
|
2508
|
+
const { requested, platform } = opts;
|
|
2509
|
+
if (requested === void 0 || requested === null || requested === "") return {};
|
|
2510
|
+
if (opts.selfServe || opts.role === "owner") {
|
|
2511
|
+
return {
|
|
2512
|
+
error: {
|
|
2513
|
+
error: "operator_only_borrow_id",
|
|
2514
|
+
message: "borrowIosBundleId is not available to self-serve credentials",
|
|
2515
|
+
hint: "Ship the change over-the-air instead \u2014 OTA needs no rebuild and no borrowed signing identity."
|
|
2516
|
+
}
|
|
2517
|
+
};
|
|
2518
|
+
}
|
|
2519
|
+
if (typeof requested !== "string") {
|
|
2520
|
+
return { error: { error: "invalid_borrow_id", message: "borrowIosBundleId must be a string" } };
|
|
2521
|
+
}
|
|
2522
|
+
const id = requested.trim().toLowerCase();
|
|
2523
|
+
if (platform !== "ios") {
|
|
2524
|
+
return {
|
|
2525
|
+
error: {
|
|
2526
|
+
error: "borrow_id_ios_only",
|
|
2527
|
+
message: `borrowIosBundleId applies to iOS signing only (got platform "${platform}")`,
|
|
2528
|
+
hint: "Android needs no provisioning profile \u2014 drop the flag for android builds."
|
|
2529
|
+
}
|
|
2530
|
+
};
|
|
2531
|
+
}
|
|
2532
|
+
if (!BUNDLE_ID_RE.test(id)) {
|
|
2533
|
+
return {
|
|
2534
|
+
error: {
|
|
2535
|
+
error: "invalid_borrow_id",
|
|
2536
|
+
message: `"${requested}" is not a valid reverse-DNS bundle id`
|
|
2537
|
+
}
|
|
2538
|
+
};
|
|
2539
|
+
}
|
|
2540
|
+
const allowed2 = opts.allowed ?? DEFAULT_BORROWABLE_IOS_IDS;
|
|
2541
|
+
if (!isBorrowableIosId(id, allowed2)) {
|
|
2542
|
+
return {
|
|
2543
|
+
error: {
|
|
2544
|
+
error: "borrow_id_not_allowed",
|
|
2545
|
+
message: `"${id}" is not borrowable; allowed: ${allowed2.join(", ")}`,
|
|
2546
|
+
hint: "Only internal enterprise ids may be borrowed \u2014 a store id would replace the real App Store app on the device. An operator can change this with HIMI_DIST_BORROWABLE_IOS_IDS."
|
|
2547
|
+
}
|
|
2548
|
+
};
|
|
2549
|
+
}
|
|
2550
|
+
return { bundleId: id };
|
|
2551
|
+
}
|
|
2552
|
+
function resolveDistSigning(requested) {
|
|
2553
|
+
if (requested === void 0 || requested === null || requested === "") {
|
|
2554
|
+
return { policy: DEFAULT_DIST_SIGNING };
|
|
2555
|
+
}
|
|
2556
|
+
if (typeof requested !== "string") {
|
|
2557
|
+
return { error: { status: 400, body: { error: "invalid_signing", message: "signing must be a string" } } };
|
|
2558
|
+
}
|
|
2559
|
+
const want = requested.trim().toLowerCase();
|
|
2560
|
+
if (WIX_MANAGED_SIGNING_ALIASES.includes(want)) return { policy: "wix-managed" };
|
|
2561
|
+
if (want === "byo") return { policy: "byo" };
|
|
2562
|
+
return {
|
|
2563
|
+
error: {
|
|
2564
|
+
status: 501,
|
|
2565
|
+
body: {
|
|
2566
|
+
error: "dist_signing_unsupported",
|
|
2567
|
+
message: `signing "${requested}" is not implemented`,
|
|
2568
|
+
supported: [DEFAULT_DIST_SIGNING, "byo"]
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
};
|
|
2572
|
+
}
|
|
2573
|
+
function resolveAndroidSigning(requested) {
|
|
2574
|
+
if (requested === void 0 || requested === null || requested === "") {
|
|
2575
|
+
return { policy: DEFAULT_ANDROID_SIGNING };
|
|
2576
|
+
}
|
|
2577
|
+
if (typeof requested !== "string") {
|
|
2578
|
+
return { error: { status: 400, body: { error: "invalid_android_signing", message: "androidSigning must be a string" } } };
|
|
2579
|
+
}
|
|
2580
|
+
const want = requested.trim().toLowerCase();
|
|
2581
|
+
const policy = Object.hasOwn(ANDROID_SIGNING_ALIASES, want) ? ANDROID_SIGNING_ALIASES[want] : void 0;
|
|
2582
|
+
if (policy) return { policy };
|
|
2583
|
+
return {
|
|
2584
|
+
error: {
|
|
2585
|
+
status: 400,
|
|
2586
|
+
body: {
|
|
2587
|
+
error: "invalid_android_signing",
|
|
2588
|
+
message: `androidSigning "${requested}" is not a known policy`,
|
|
2589
|
+
supported: ["qa-keystore", "wix-keystore", "debug"]
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
};
|
|
2593
|
+
}
|
|
2594
|
+
function androidFormatSkewFailed(record2) {
|
|
2595
|
+
return record2.platform === "android" && typeof record2.error === "string" && [ANDROID_FORMAT_NOT_BUILT, ANDROID_FORMAT_WRONG_SIGNER, ANDROID_FORMAT_NOT_REQUESTED].some((code) => record2.error.includes(`${code}:`));
|
|
2596
|
+
}
|
|
2597
|
+
function resolveAndroidFormat(requested) {
|
|
2598
|
+
if (requested === void 0 || requested === null || requested === "") return { format: DEFAULT_ANDROID_FORMAT };
|
|
2599
|
+
if (typeof requested === "string" && ANDROID_FORMATS.includes(requested)) {
|
|
2600
|
+
return { format: requested };
|
|
2601
|
+
}
|
|
2602
|
+
return {
|
|
2603
|
+
error: {
|
|
2604
|
+
status: 400,
|
|
2605
|
+
body: {
|
|
2606
|
+
error: "invalid_android_format",
|
|
2607
|
+
message: `androidFormat ${typeof requested === "string" ? `"${requested.slice(0, 40)}"` : `of type ${typeof requested}`} is not a known format`,
|
|
2608
|
+
supported: [...ANDROID_FORMATS]
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
};
|
|
2612
|
+
}
|
|
2613
|
+
function encodeDistParams(env) {
|
|
2614
|
+
return Buffer.from(JSON.stringify(env), "utf8").toString("base64url");
|
|
2615
|
+
}
|
|
2616
|
+
function distJobSpec(req) {
|
|
2617
|
+
const envVars = {
|
|
2618
|
+
APP_DIR: req.appDir,
|
|
2619
|
+
// WHICH APP this binary is FOR, as distinct from which shell builds it. Without it the pool
|
|
2620
|
+
// can only infer an app from APP_DIR — i.e. the shell — so it baked the SHELL's content and
|
|
2621
|
+
// resolved the SHELL's OTA app id. A device-verified consequence: `himi dist --app demo-app`
|
|
2622
|
+
// produced a binary rendering himi_branded_home. The shell is the container; this is the app.
|
|
2623
|
+
HIMI_DIST_APP: req.app,
|
|
2624
|
+
// (HIMI_DIST_PROVISIONING_ENV is set at the END of this object, after `req.env` — see there.)
|
|
2625
|
+
// run-dist gates iOS on DIST_ENABLE_IOS / DIST_PROVISIONING_PROFILE / an explicit
|
|
2626
|
+
// `[dist:ios]` IN THE COMMIT MESSAGE. A serve-brokered job has no commit by design, and
|
|
2627
|
+
// `--force` only bypasses the `[dist]` tag gate — so without this an `--platform ios`
|
|
2628
|
+
// request would skip the build and finish as SUCCESS with no install link. Asking for iOS
|
|
2629
|
+
// through the API IS the explicit opt-in that `[dist:ios]` represents.
|
|
2630
|
+
...req.platform === "ios" ? { DIST_ENABLE_IOS: "1" } : {},
|
|
2631
|
+
...req.release ? { HIMI_DIST_RELEASE_PIN: req.release } : {},
|
|
2632
|
+
...req.contractUrl ? { HIMI_DIST_CONTRACT_URL: req.contractUrl } : {},
|
|
2633
|
+
// Where the pool fetches the RELEASE to bake its offline seed from. Its absence is what makes
|
|
2634
|
+
// the classic Falcon `[dist]` path fall back to building the seed from repo source.
|
|
2635
|
+
...req.seedUrl ? { HIMI_DIST_SEED_URL: req.seedUrl } : {},
|
|
2636
|
+
...req.platform === "android" && req.androidConfigUrl ? { HIMI_DIST_ANDROID_CONFIG_URL: req.androidConfigUrl } : {},
|
|
2637
|
+
// Where the pool fetches its SIGNING IDENTITY (profile + p12 + password). A URL, not the
|
|
2638
|
+
// bytes: the envelope is ~20KB of base64 and `command` is capped at MAX_COMMAND_CHARS — the
|
|
2639
|
+
// same reason the brand contract travels this way. It also keeps key material out of the
|
|
2640
|
+
// job params, which the pool echoes into its log.
|
|
2641
|
+
...req.signingUrl ? { HIMI_DIST_SIGNING_URL: req.signingUrl } : {},
|
|
2642
|
+
// WHICH KEYSTORE the Android build signs with. Android only — on an iOS job this would be a
|
|
2643
|
+
// variable nothing reads, and dispatching one implies a decision that was never made.
|
|
2644
|
+
// A bundle dispatches the QA key BY NAME, never `wix-keystore`. `--aab` always means the Wix
|
|
2645
|
+
// production key, and the new run-dist derives that from DIST_ANDROID_FORMAT itself, overriding
|
|
2646
|
+
// this. Naming `wix-keystore` here would reach a run-dist OLDER than `--aab` too (the pool builds
|
|
2647
|
+
// the release's own commit): it ignores the format, builds an installable APK, signs it with the
|
|
2648
|
+
// Wix production key and uploads and announces it — the exact artifact the self-serve 403
|
|
2649
|
+
// withholds. Naming NOTHING is not safe either: a pool machine with DIST_ANDROID_USE_WIX_KEYSTORE=1
|
|
2650
|
+
// then hands that old runner the Wix key anyway. A named QA key outranks that machine setting, so
|
|
2651
|
+
// an old runner signs an ordinary QA APK and the job fails as `android_format_not_built`.
|
|
2652
|
+
...req.platform === "android" && req.androidSigning ? { DIST_ANDROID_SIGNING: req.androidFormat === "aab" ? "qa-keystore" : req.androidSigning } : {},
|
|
2653
|
+
// A Play bundle instead of an APK. Only when asked: the APK default needs no parameter, and a
|
|
2654
|
+
// runner that predates the variable ignores it — which the result callback catches.
|
|
2655
|
+
...req.platform === "android" && req.androidFormat === "aab" ? { DIST_ANDROID_FORMAT: "aab" } : {},
|
|
2656
|
+
...req.previewRoute ? { HIMI_DIST_PREVIEW_ROUTE: req.previewRoute } : {},
|
|
2657
|
+
...req.callbackUrl ? { HIMI_DIST_CALLBACK_URL: req.callbackUrl } : {},
|
|
2658
|
+
...req.callbackToken ? { HIMI_DIST_CALLBACK_TOKEN: req.callbackToken } : {},
|
|
2659
|
+
// The per-job artifact path component. Without it two concurrent jobs for one
|
|
2660
|
+
// app+shell+platform+commit wrote the same ipa, manifest.plist and install.html, and the
|
|
2661
|
+
// loser's install page then handed a tester the other build's binary.
|
|
2662
|
+
...req.jobNonce ? { HIMI_DIST_JOB_NONCE: req.jobNonce } : {},
|
|
2663
|
+
// Who to DM the install link to. See DistJobRequest.requestedBy: the git-history guess the pool
|
|
2664
|
+
// falls back to misroutes brokered builds to an unrelated colleague.
|
|
2665
|
+
...req.requestedBy ? { HIMI_DIST_REQUESTED_BY: req.requestedBy } : {},
|
|
2666
|
+
...req.env,
|
|
2667
|
+
...req.buildOrigin ? { HIMI_DIST_BUILD_ORIGIN: req.buildOrigin } : {},
|
|
2668
|
+
// AFTER `req.env`, deliberately. This one field is the SHELL's declared answer, and it is the
|
|
2669
|
+
// only thing standing between owner-lite and a build that reads the fetched contract under
|
|
2670
|
+
// branded-lite's key — i.e. ignores it and ships unbranded while reporting success. `req.env`
|
|
2671
|
+
// is operator config (`deps.env`), so a stray HIMI_DIST_PROVISIONING_ENV there is a plausible
|
|
2672
|
+
// misconfiguration, and it would silently unbrand EVERY shell at once. Generic overrides do
|
|
2673
|
+
// not get to answer a per-shell question.
|
|
2674
|
+
...req.provisioningEnv ? { HIMI_DIST_PROVISIONING_ENV: req.provisioningEnv } : {}
|
|
2675
|
+
};
|
|
2676
|
+
const command = `dist:${req.platform} ${DIST_PARAMS_FLAG} ${encodeDistParams(envVars)}`;
|
|
2677
|
+
if (command.length > MAX_COMMAND_CHARS) {
|
|
2678
|
+
throw new Error(
|
|
2679
|
+
`dist command is ${command.length} chars (cap ${MAX_COMMAND_CHARS}); shrink the job env \u2014 pass large values as a URL the Mac job fetches, as the brand contract does`
|
|
2680
|
+
);
|
|
2681
|
+
}
|
|
2682
|
+
return {
|
|
2683
|
+
gitUrl: req.gitUrl ?? DEFAULT_GIT_URL,
|
|
2684
|
+
gitCommitSha: req.gitCommitSha,
|
|
2685
|
+
packageName: DIST_PACKAGE_NAME,
|
|
2686
|
+
command,
|
|
2687
|
+
// Job Service renders this metadata in Buildkite's job label. User labels are sanitized,
|
|
2688
|
+
// and the runner also carries buildOrigin so it does not treat them as GitHub PR refs.
|
|
2689
|
+
branchName: req.buildLabel ?? req.branchName ?? "master",
|
|
2690
|
+
envVars,
|
|
2691
|
+
...req.xcodeVersion ? { xcodeVersion: req.xcodeVersion } : {}
|
|
2692
|
+
};
|
|
2693
|
+
}
|
|
2694
|
+
var IN_FLIGHT, SCOPE_CREATE, SCOPE_READ, SCOPE_CANCEL, DEFAULT_BASE_URL, DEFAULT_OAUTH_URL, TOKEN_TTL_MS, JobServiceError, JobServiceBroker, CUSTOMER_UPLOAD_LEASE_MS, MAX_MEASURABLE_IDENTITY_WINDOW, DIST_SHELLS, DEFAULT_DIST_SHELL, DEFAULT_BORROWABLE_IOS_IDS, BUNDLE_ID_RE, DEFAULT_DIST_SIGNING, WIX_MANAGED_SIGNING_ALIASES, DEFAULT_ANDROID_SIGNING, ANDROID_SIGNING_POLICIES, ANDROID_SIGNING_ALIASES, DEFAULT_ANDROID_FORMAT, ANDROID_FORMATS, ANDROID_FORMAT_NOT_BUILT, ANDROID_FORMAT_WRONG_SIGNER, ANDROID_FORMAT_NOT_REQUESTED, DEFAULT_GIT_URL, DIST_PACKAGE_NAME, DIST_PARAMS_FLAG, MAX_COMMAND_CHARS;
|
|
2384
2695
|
var init_dist_jobs = __esm({
|
|
2385
2696
|
"../../core/serve-control/src/dist-jobs.ts"() {
|
|
2697
|
+
IN_FLIGHT = /* @__PURE__ */ new Set(["CREATED", "QUEUED", "WORKING"]);
|
|
2698
|
+
SCOPE_CREATE = "MRE.JOB_CREATE";
|
|
2699
|
+
SCOPE_READ = "MRE.JOB_READ";
|
|
2700
|
+
SCOPE_CANCEL = "MRE.CANCEL_JOB";
|
|
2701
|
+
DEFAULT_BASE_URL = "https://bo.wix.com/job-service";
|
|
2702
|
+
DEFAULT_OAUTH_URL = "https://www.wixapis.com/oauth/access";
|
|
2386
2703
|
TOKEN_TTL_MS = 5 * 60 * 1e3;
|
|
2704
|
+
JobServiceError = class extends Error {
|
|
2705
|
+
constructor(message2, status, body) {
|
|
2706
|
+
super(message2);
|
|
2707
|
+
this.status = status;
|
|
2708
|
+
this.body = body;
|
|
2709
|
+
this.name = "JobServiceError";
|
|
2710
|
+
}
|
|
2711
|
+
};
|
|
2712
|
+
JobServiceBroker = class {
|
|
2713
|
+
baseUrl;
|
|
2714
|
+
oauthUrl;
|
|
2715
|
+
fetchImpl;
|
|
2716
|
+
now;
|
|
2717
|
+
creds;
|
|
2718
|
+
/** scope -> { token, expiresAt } */
|
|
2719
|
+
tokens = /* @__PURE__ */ new Map();
|
|
2720
|
+
constructor(opts) {
|
|
2721
|
+
if (!opts.creds?.appDefId || !opts.creds?.appSecret) {
|
|
2722
|
+
throw new JobServiceError("job service credentials missing (POCO_APP_DEF_ID / POCO_APP_SECRET)");
|
|
2723
|
+
}
|
|
2724
|
+
this.creds = opts.creds;
|
|
2725
|
+
this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
2726
|
+
this.oauthUrl = opts.oauthUrl ?? DEFAULT_OAUTH_URL;
|
|
2727
|
+
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
2728
|
+
this.now = opts.now ?? Date.now;
|
|
2729
|
+
}
|
|
2730
|
+
/** Mint (or reuse) a token for one MRE scope. */
|
|
2731
|
+
async token(scope2) {
|
|
2732
|
+
const cached3 = this.tokens.get(scope2);
|
|
2733
|
+
if (cached3 && cached3.expiresAt > this.now()) return cached3.token;
|
|
2734
|
+
const res = await this.fetchImpl(this.oauthUrl, {
|
|
2735
|
+
method: "POST",
|
|
2736
|
+
headers: { "content-type": "application/json" },
|
|
2737
|
+
body: JSON.stringify({
|
|
2738
|
+
grant_type: "client_credentials",
|
|
2739
|
+
client_id: this.creds.appDefId,
|
|
2740
|
+
client_secret: this.creds.appSecret,
|
|
2741
|
+
scope: scope2
|
|
2742
|
+
})
|
|
2743
|
+
});
|
|
2744
|
+
const text11 = await res.text();
|
|
2745
|
+
if (!res.ok) {
|
|
2746
|
+
throw new JobServiceError(`oauth failed for scope ${scope2}`, res.status, truncate(text11));
|
|
2747
|
+
}
|
|
2748
|
+
let token;
|
|
2749
|
+
try {
|
|
2750
|
+
token = JSON.parse(text11).access_token;
|
|
2751
|
+
} catch {
|
|
2752
|
+
throw new JobServiceError(`oauth returned non-JSON for scope ${scope2}`, res.status, truncate(text11));
|
|
2753
|
+
}
|
|
2754
|
+
if (!token) throw new JobServiceError(`oauth returned no access_token for scope ${scope2}`, res.status);
|
|
2755
|
+
this.tokens.set(scope2, { token, expiresAt: this.now() + TOKEN_TTL_MS });
|
|
2756
|
+
return token;
|
|
2757
|
+
}
|
|
2758
|
+
async call(scope2, method, path2, body) {
|
|
2759
|
+
const token = await this.token(scope2);
|
|
2760
|
+
const res = await this.fetchImpl(`${this.baseUrl}${path2}`, {
|
|
2761
|
+
method,
|
|
2762
|
+
// BARE token, not `Bearer <token>` — matches jobServiceApi's own header.
|
|
2763
|
+
headers: { Authorization: token, ...body ? { "content-type": "application/json" } : {} },
|
|
2764
|
+
...body ? { body: JSON.stringify(body) } : {}
|
|
2765
|
+
});
|
|
2766
|
+
const text11 = await res.text();
|
|
2767
|
+
if (!res.ok) {
|
|
2768
|
+
throw new JobServiceError(`job service ${method} ${path2} failed`, res.status, truncate(text11));
|
|
2769
|
+
}
|
|
2770
|
+
if (!text11) return {};
|
|
2771
|
+
try {
|
|
2772
|
+
return JSON.parse(text11);
|
|
2773
|
+
} catch {
|
|
2774
|
+
throw new JobServiceError(`job service ${method} ${path2} returned non-JSON`, res.status, truncate(text11));
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
/**
|
|
2778
|
+
* Create a NODE_COMMAND job on the Mac (or Linux) pool. Returns as soon as Job Service has
|
|
2779
|
+
* queued it — this never waits for the build.
|
|
2780
|
+
*/
|
|
2781
|
+
async createNodeCommand(spec, os2 = "mac", notify) {
|
|
2782
|
+
for (const key3 of ["gitUrl", "gitCommitSha", "packageName", "command", "branchName"]) {
|
|
2783
|
+
if (!spec[key3]) throw new JobServiceError(`createNodeCommand: missing ${key3}`);
|
|
2784
|
+
}
|
|
2785
|
+
const optionsKey = os2 === "linux" ? "linuxNodeCommandOptions" : "nodeCommandOptions";
|
|
2786
|
+
const type = os2 === "linux" ? "LINUX_NODE_COMMAND" : "NODE_COMMAND";
|
|
2787
|
+
const options = {
|
|
2788
|
+
packageManager: "YARN",
|
|
2789
|
+
// the only value Job Service accepts
|
|
2790
|
+
gitUrl: spec.gitUrl,
|
|
2791
|
+
gitCommitSha: spec.gitCommitSha,
|
|
2792
|
+
packageName: spec.packageName,
|
|
2793
|
+
command: spec.command,
|
|
2794
|
+
branchName: spec.branchName,
|
|
2795
|
+
...spec.envVars ? { envVars: spec.envVars } : {}
|
|
2796
|
+
};
|
|
2797
|
+
if (os2 === "mac" && spec.xcodeVersion) options.xcodeVersion = spec.xcodeVersion;
|
|
2798
|
+
const subscriptions = {
|
|
2799
|
+
...notify?.ownershipTags?.length ? { subscribedOwnershipTags: notify.ownershipTags } : {},
|
|
2800
|
+
...notify?.userIds?.length ? { subscribedUserIds: notify.userIds } : {}
|
|
2801
|
+
};
|
|
2802
|
+
const data = await this.call(SCOPE_CREATE, "POST", "/v1/job", {
|
|
2803
|
+
job: { type, [optionsKey]: options, ...subscriptions }
|
|
2804
|
+
});
|
|
2805
|
+
const job = data?.job;
|
|
2806
|
+
if (!job?.id) throw new JobServiceError("job service create returned no job id");
|
|
2807
|
+
return snapshot(job);
|
|
2808
|
+
}
|
|
2809
|
+
/** Current state of a job. */
|
|
2810
|
+
async read(jobId) {
|
|
2811
|
+
const data = await this.call(SCOPE_READ, "GET", `/v1/job/${encodeURIComponent(jobId)}`);
|
|
2812
|
+
const job = data?.job;
|
|
2813
|
+
if (!job) throw new JobServiceError(`job service read returned no job for ${jobId}`);
|
|
2814
|
+
return snapshot({ id: jobId, ...job });
|
|
2815
|
+
}
|
|
2816
|
+
/** Ask Job Service to cancel a queued/running job. */
|
|
2817
|
+
async cancel(jobId) {
|
|
2818
|
+
await this.call(SCOPE_CANCEL, "POST", `/v1/job/${encodeURIComponent(jobId)}/cancel`);
|
|
2819
|
+
}
|
|
2820
|
+
};
|
|
2387
2821
|
CUSTOMER_UPLOAD_LEASE_MS = 15 * 60 * 1e3;
|
|
2822
|
+
MAX_MEASURABLE_IDENTITY_WINDOW = 100;
|
|
2388
2823
|
DIST_SHELLS = {
|
|
2389
2824
|
"branded-lite": {
|
|
2390
2825
|
appDir: "apps/himi-branded-lite",
|
|
@@ -2437,6 +2872,11 @@ var init_dist_jobs = __esm({
|
|
|
2437
2872
|
}
|
|
2438
2873
|
};
|
|
2439
2874
|
DEFAULT_DIST_SHELL = "branded-lite";
|
|
2875
|
+
DEFAULT_BORROWABLE_IOS_IDS = ["ent.*"];
|
|
2876
|
+
BUNDLE_ID_RE = /^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*)+$/;
|
|
2877
|
+
DEFAULT_DIST_SIGNING = "wix-managed";
|
|
2878
|
+
WIX_MANAGED_SIGNING_ALIASES = ["wix-managed", "wix", "pool-enterprise"];
|
|
2879
|
+
DEFAULT_ANDROID_SIGNING = "qa-keystore";
|
|
2440
2880
|
ANDROID_SIGNING_POLICIES = ["qa-keystore", "wix-keystore", "debug"];
|
|
2441
2881
|
ANDROID_SIGNING_ALIASES = {
|
|
2442
2882
|
// The canonical spellings, derived so the two lists cannot drift apart.
|
|
@@ -2446,6 +2886,15 @@ var init_dist_jobs = __esm({
|
|
|
2446
2886
|
wix: "wix-keystore",
|
|
2447
2887
|
oneapp: "wix-keystore"
|
|
2448
2888
|
};
|
|
2889
|
+
DEFAULT_ANDROID_FORMAT = "apk";
|
|
2890
|
+
ANDROID_FORMATS = ["apk", "aab"];
|
|
2891
|
+
ANDROID_FORMAT_NOT_BUILT = "android_format_not_built";
|
|
2892
|
+
ANDROID_FORMAT_WRONG_SIGNER = "android_format_wrong_signer";
|
|
2893
|
+
ANDROID_FORMAT_NOT_REQUESTED = "android_format_not_requested";
|
|
2894
|
+
DEFAULT_GIT_URL = "https://github.com/wix-private/himalaya";
|
|
2895
|
+
DIST_PACKAGE_NAME = "@himalaya/native-ci";
|
|
2896
|
+
DIST_PARAMS_FLAG = "--himi-dist";
|
|
2897
|
+
MAX_COMMAND_CHARS = 2e3;
|
|
2449
2898
|
}
|
|
2450
2899
|
});
|
|
2451
2900
|
|
|
@@ -9873,16 +10322,16 @@ function scanWidgetPayload(node, family, path2, bindings, disallowed, timeRefs,
|
|
|
9873
10322
|
scanWidgetPayload(v2, family, `${path2}.${k2}`, bindings, disallowed, timeRefs, intents, actionSites2);
|
|
9874
10323
|
}
|
|
9875
10324
|
}
|
|
9876
|
-
function validateWidget(
|
|
10325
|
+
function validateWidget(snapshot3) {
|
|
9877
10326
|
const validate5 = compileWidgetSchema();
|
|
9878
|
-
const schemaOk = validate5(
|
|
10327
|
+
const schemaOk = validate5(snapshot3);
|
|
9879
10328
|
const schemaErrors = schemaOk ? [] : validate5.errors ?? [];
|
|
9880
10329
|
const bindingViolations = [];
|
|
9881
10330
|
const disallowedComponents = [];
|
|
9882
10331
|
const timeRefViolations = [];
|
|
9883
10332
|
const intentViolations = [];
|
|
9884
10333
|
const actionSites2 = [];
|
|
9885
|
-
const snap =
|
|
10334
|
+
const snap = snapshot3 ?? {};
|
|
9886
10335
|
const family = snap.family;
|
|
9887
10336
|
scanWidgetPayload(snap.payload, family, "$.payload", bindingViolations, disallowedComponents, timeRefViolations, intentViolations, actionSites2);
|
|
9888
10337
|
if (snap.placeholderWhenStale !== void 0) {
|
|
@@ -13556,12 +14005,12 @@ function responseBytes(value2) {
|
|
|
13556
14005
|
return 0;
|
|
13557
14006
|
}
|
|
13558
14007
|
}
|
|
13559
|
-
function restoredState(def,
|
|
14008
|
+
function restoredState(def, snapshot3) {
|
|
13560
14009
|
const declared = def?.state ?? {};
|
|
13561
|
-
if (!
|
|
14010
|
+
if (!snapshot3 || typeof snapshot3 !== "object" || Array.isArray(snapshot3)) return declared;
|
|
13562
14011
|
const fresh = [def?.notHydrated, def?.perVisit].flatMap((keys) => Array.isArray(keys) ? keys : []);
|
|
13563
14012
|
const merged = { ...declared };
|
|
13564
|
-
for (const [key3, value2] of Object.entries(
|
|
14013
|
+
for (const [key3, value2] of Object.entries(snapshot3)) {
|
|
13565
14014
|
if (key3 !== "_error" && !fresh.includes(key3)) merged[key3] = value2;
|
|
13566
14015
|
}
|
|
13567
14016
|
return merged;
|
|
@@ -22600,6 +23049,7 @@ function resolveIdiom(tokens2, ctx = {}) {
|
|
|
22600
23049
|
var IDIOM_CONTEXTS, UNSAFE_KEYS;
|
|
22601
23050
|
var init_idiom = __esm({
|
|
22602
23051
|
"../../core/ts/src/idiom.ts"() {
|
|
23052
|
+
"use strict";
|
|
22603
23053
|
IDIOM_CONTEXTS = {
|
|
22604
23054
|
ios: { native: ["ios"] },
|
|
22605
23055
|
android: { native: ["material"] },
|
|
@@ -28061,7 +28511,7 @@ function json(res, status, obj5) {
|
|
|
28061
28511
|
res.setHeader("content-type", "application/json; charset=utf-8");
|
|
28062
28512
|
res.end(body);
|
|
28063
28513
|
}
|
|
28064
|
-
function
|
|
28514
|
+
function truncate2(s2) {
|
|
28065
28515
|
if (s2 === void 0) return void 0;
|
|
28066
28516
|
return s2.length > BODY_CAP ? s2.slice(0, BODY_CAP) + `\u2026[+${s2.length - BODY_CAP}B]` : s2;
|
|
28067
28517
|
}
|
|
@@ -28076,8 +28526,8 @@ function redactHeaders(h2) {
|
|
|
28076
28526
|
}
|
|
28077
28527
|
function recordWixTraffic(gw, app, adminUrl, ev) {
|
|
28078
28528
|
const full = { ...ev, id: ++gw.seq, app };
|
|
28079
|
-
full.reqBody =
|
|
28080
|
-
full.respBody =
|
|
28529
|
+
full.reqBody = truncate2(redactBodyString(full.reqBody));
|
|
28530
|
+
full.respBody = truncate2(redactBodyString(full.respBody));
|
|
28081
28531
|
gw.traffic.push(full);
|
|
28082
28532
|
if (gw.traffic.length > TRAFFIC_CAP) gw.traffic.splice(0, gw.traffic.length - TRAFFIC_CAP);
|
|
28083
28533
|
const text11 = `event: wix.traffic
|
|
@@ -116688,7 +117138,7 @@ function ensureListAnimateRuntime() {
|
|
|
116688
117138
|
listAnimateRuntimeInstalled = true;
|
|
116689
117139
|
const prevRects = /* @__PURE__ */ new WeakMap();
|
|
116690
117140
|
const rowKey = (c2) => c2.dataset?.componentId ?? c2.querySelector("[data-component-id]")?.dataset?.componentId;
|
|
116691
|
-
const
|
|
117141
|
+
const snapshot3 = (host) => {
|
|
116692
117142
|
const m2 = /* @__PURE__ */ new Map();
|
|
116693
117143
|
Array.from(host.children).forEach((c2) => {
|
|
116694
117144
|
const id = rowKey(c2);
|
|
@@ -116700,7 +117150,7 @@ function ensureListAnimateRuntime() {
|
|
|
116700
117150
|
const flip = (host) => {
|
|
116701
117151
|
const prev = prevRects.get(host);
|
|
116702
117152
|
if (!prev) {
|
|
116703
|
-
|
|
117153
|
+
snapshot3(host);
|
|
116704
117154
|
return;
|
|
116705
117155
|
}
|
|
116706
117156
|
const next = /* @__PURE__ */ new Map();
|
|
@@ -116743,7 +117193,7 @@ function ensureListAnimateRuntime() {
|
|
|
116743
117193
|
const scan = () => {
|
|
116744
117194
|
document.querySelectorAll(hostSel).forEach((h2) => {
|
|
116745
117195
|
if (!prevRects.has(h2)) {
|
|
116746
|
-
|
|
117196
|
+
snapshot3(h2);
|
|
116747
117197
|
childObs.observe(h2, { childList: true });
|
|
116748
117198
|
}
|
|
116749
117199
|
});
|
|
@@ -121243,7 +121693,7 @@ var init_renderNode = __esm({
|
|
|
121243
121693
|
}, [startPositionPath, boundStartPosition, status]);
|
|
121244
121694
|
const emit = React12.useCallback((action, extra = {}) => {
|
|
121245
121695
|
if (!action || !ctx.onAction) return;
|
|
121246
|
-
const
|
|
121696
|
+
const snapshot3 = {
|
|
121247
121697
|
sessionId,
|
|
121248
121698
|
state: status,
|
|
121249
121699
|
status,
|
|
@@ -121258,7 +121708,7 @@ var init_renderNode = __esm({
|
|
|
121258
121708
|
artist: String(item?.artist ?? ""),
|
|
121259
121709
|
error
|
|
121260
121710
|
};
|
|
121261
|
-
ctx.onAction({ ...action, args: { ...action.args ?? {}, ...
|
|
121711
|
+
ctx.onAction({ ...action, args: { ...action.args ?? {}, ...snapshot3, ...extra }, params: { ...action.params ?? {}, sessionId, index: String(index), ...Object.fromEntries(Object.entries(extra).map(([k2, v2]) => [k2, String(v2)])) } });
|
|
121262
121712
|
}, [ctx.onAction, sessionId, status, index, position, duration2, item, buffered, rate, props.muted, fullscreen, error]);
|
|
121263
121713
|
React12.useEffect(() => {
|
|
121264
121714
|
if (!isUnsupportedProvider || status === "error") return;
|
|
@@ -127551,15 +128001,15 @@ function interpretProduce(services, parsed) {
|
|
|
127551
128001
|
}
|
|
127552
128002
|
return { services, widgets, views };
|
|
127553
128003
|
}
|
|
127554
|
-
function contentEtag(
|
|
128004
|
+
function contentEtag(snapshot3) {
|
|
127555
128005
|
const canonical7 = JSON.stringify({
|
|
127556
|
-
widgetId:
|
|
127557
|
-
family:
|
|
127558
|
-
size:
|
|
127559
|
-
payload:
|
|
127560
|
-
deepLink:
|
|
128006
|
+
widgetId: snapshot3.widgetId,
|
|
128007
|
+
family: snapshot3.family,
|
|
128008
|
+
size: snapshot3.size,
|
|
128009
|
+
payload: snapshot3.payload,
|
|
128010
|
+
deepLink: snapshot3.deepLink,
|
|
127561
128011
|
// Lever A — a timeline change must bump the etag (frame values/times are content).
|
|
127562
|
-
frames:
|
|
128012
|
+
frames: snapshot3.frames ?? null
|
|
127563
128013
|
});
|
|
127564
128014
|
return "sha256-" + createHash15("sha256").update(canonical7).digest("base64");
|
|
127565
128015
|
}
|
|
@@ -127602,8 +128052,8 @@ function freezeCaptured(def, widgetId, opts = {}) {
|
|
|
127602
128052
|
generatedAt: opts.generatedAt ?? Math.floor(Date.now() / 1e3),
|
|
127603
128053
|
...frames ? { frames } : {}
|
|
127604
128054
|
};
|
|
127605
|
-
const
|
|
127606
|
-
const result = validateWidget(
|
|
128055
|
+
const snapshot3 = { ...base, contentEtag: contentEtag(base) };
|
|
128056
|
+
const result = validateWidget(snapshot3);
|
|
127607
128057
|
if (!result.ok) {
|
|
127608
128058
|
const reasons = [];
|
|
127609
128059
|
if (result.bindingViolations.length) {
|
|
@@ -127625,7 +128075,7 @@ function freezeCaptured(def, widgetId, opts = {}) {
|
|
|
127625
128075
|
}
|
|
127626
128076
|
throw new Error(`widget "${widgetId}" produced an invalid snapshot \u2014 ${reasons.join(" | ")}`);
|
|
127627
128077
|
}
|
|
127628
|
-
return
|
|
128078
|
+
return snapshot3;
|
|
127629
128079
|
}
|
|
127630
128080
|
function viewWidgetId(viewId, family) {
|
|
127631
128081
|
return `${viewId}.${family}`;
|
|
@@ -127725,8 +128175,8 @@ function freezeOverrideSnapshot(input, opts = {}) {
|
|
|
127725
128175
|
...input.placeholderWhenStale !== void 0 ? { placeholderWhenStale: input.placeholderWhenStale } : {},
|
|
127726
128176
|
...input.frames !== void 0 ? { frames: input.frames } : {}
|
|
127727
128177
|
};
|
|
127728
|
-
const
|
|
127729
|
-
const result = validateWidget(
|
|
128178
|
+
const snapshot3 = { ...base, contentEtag: contentEtag(base) };
|
|
128179
|
+
const result = validateWidget(snapshot3);
|
|
127730
128180
|
if (!result.ok) {
|
|
127731
128181
|
const reasons = [];
|
|
127732
128182
|
if (result.bindingViolations.length) {
|
|
@@ -127748,7 +128198,7 @@ function freezeOverrideSnapshot(input, opts = {}) {
|
|
|
127748
128198
|
}
|
|
127749
128199
|
throw new Error(`override snapshot for "${input.widgetId}" is invalid \u2014 ${reasons.join(" | ")}`);
|
|
127750
128200
|
}
|
|
127751
|
-
return
|
|
128201
|
+
return snapshot3;
|
|
127752
128202
|
}
|
|
127753
128203
|
var MAX_TIMELINE_FRAMES, WIDGET_BUDGET_MS, realmPromise, WidgetRealmUnavailableError, PRODUCE_CACHE_TTL_MS, MAX_PRODUCE_CACHE_ENTRIES, MAX_PRODUCE_ENTRY_BYTES, MAX_PRODUCE_CACHE_BYTES, produceCache, produceCacheGeneration, CAPTURE_SLOT, READBACK_SERVICE;
|
|
127754
128204
|
var init_widgets = __esm({
|
|
@@ -130386,9 +130836,9 @@ async function buildSnapshotForId(widgetId, dir) {
|
|
|
130386
130836
|
try {
|
|
130387
130837
|
const js2 = loaded.bytes.toString("utf8");
|
|
130388
130838
|
if (entry.view) {
|
|
130389
|
-
const
|
|
130390
|
-
if (!
|
|
130391
|
-
return { ok: true, snapshot:
|
|
130839
|
+
const snapshot3 = await buildViewSnapshot(js2, entry.view.viewId, entry.view.surfaceId);
|
|
130840
|
+
if (!snapshot3) return { ok: false, status: 404, error: "widget_not_found" };
|
|
130841
|
+
return { ok: true, snapshot: snapshot3 };
|
|
130392
130842
|
}
|
|
130393
130843
|
return { ok: true, snapshot: await buildWidgetSnapshot(js2, widgetId) };
|
|
130394
130844
|
} catch (err) {
|
|
@@ -133649,7 +134099,7 @@ __export(screen_crawl_exports, {
|
|
|
133649
134099
|
recordScreenTraffic: () => recordScreenTraffic,
|
|
133650
134100
|
renderedNameGaps: () => renderedNameGaps,
|
|
133651
134101
|
rootOnAppear: () => rootOnAppear,
|
|
133652
|
-
snapshot: () =>
|
|
134102
|
+
snapshot: () => snapshot2,
|
|
133653
134103
|
structuralSignature: () => structuralSignature,
|
|
133654
134104
|
unverifiableNodes: () => unverifiableNodes,
|
|
133655
134105
|
workerArgs: () => workerArgs
|
|
@@ -134387,7 +134837,7 @@ function hasOwnError(state) {
|
|
|
134387
134837
|
}
|
|
134388
134838
|
return false;
|
|
134389
134839
|
}
|
|
134390
|
-
function
|
|
134840
|
+
function snapshot2(w2) {
|
|
134391
134841
|
const state = {};
|
|
134392
134842
|
const defects = {};
|
|
134393
134843
|
for (const [name, h2] of Object.entries(w2.handles)) {
|
|
@@ -134453,7 +134903,7 @@ async function bootScreenWorker(opts) {
|
|
|
134453
134903
|
}
|
|
134454
134904
|
}
|
|
134455
134905
|
for (let i2 = 0; i2 < 20; i2++) await yieldMacrotask();
|
|
134456
|
-
const { state, defects } =
|
|
134906
|
+
const { state, defects } = snapshot2(w2);
|
|
134457
134907
|
return { ...w2, hostCalls, deniedCapabilities, state: Object.keys(state).length ? state : w2.services, defects, ...deadLifecycle ? { deadLifecycle } : {} };
|
|
134458
134908
|
}
|
|
134459
134909
|
function effectSince(w2, mark, action, componentId) {
|
|
@@ -134575,7 +135025,7 @@ async function crawlScreenJourney(opts) {
|
|
|
134575
135025
|
fail6(`journey "${opts.journey.name}" cannot find ${step.component ? `${step.component} \u2192 ` : ""}${step.action} in this screen`, step);
|
|
134576
135026
|
continue;
|
|
134577
135027
|
}
|
|
134578
|
-
const state =
|
|
135028
|
+
const state = snapshot2(worker).state;
|
|
134579
135029
|
const site = effectiveSiteFor(declared, state);
|
|
134580
135030
|
if (!site) {
|
|
134581
135031
|
fail6(`journey "${opts.journey.name}" cannot dispatch ${step.action}: its list has no rendered row`, step);
|
|
@@ -134602,7 +135052,7 @@ async function crawlScreenJourney(opts) {
|
|
|
134602
135052
|
const stepEffect = effectSince(worker, mark, site.actionId, site.componentId);
|
|
134603
135053
|
if (stepEffect) effects.push(stepEffect);
|
|
134604
135054
|
}
|
|
134605
|
-
const settled =
|
|
135055
|
+
const settled = snapshot2(worker);
|
|
134606
135056
|
if (worker.errors.length) {
|
|
134607
135057
|
for (const error of worker.errors) fail6(`journey "${opts.journey.name}" worker error: ${error.service}: ${error.message}`);
|
|
134608
135058
|
}
|
|
@@ -135023,7 +135473,7 @@ async function crawlScreenInner(opts) {
|
|
|
135023
135473
|
continue;
|
|
135024
135474
|
}
|
|
135025
135475
|
const trigger = { tap: site.componentId, key: site.key, action: site.actionId };
|
|
135026
|
-
const preState =
|
|
135476
|
+
const preState = snapshot2(w2).state;
|
|
135027
135477
|
const effective = effectiveSiteFor(site, preState);
|
|
135028
135478
|
if (!effective) {
|
|
135029
135479
|
actionsSkipped.push({ action: site.actionId, why: "no-row-value" });
|
|
@@ -135042,7 +135492,7 @@ async function crawlScreenInner(opts) {
|
|
|
135042
135492
|
errors.push({ service: parsed.service, message: `${parsed.action}: ${errText(e2)}`, ...e2.stack ? { stack: e2.stack } : {}, argless: workerArgs(dispatched).length === 0 });
|
|
135043
135493
|
}
|
|
135044
135494
|
exercised += 1;
|
|
135045
|
-
const { state, defects } =
|
|
135495
|
+
const { state, defects } = snapshot2(w2);
|
|
135046
135496
|
check(trigger, state, errors, defects);
|
|
135047
135497
|
reportDenied(w2.deniedCapabilities.slice(deniedBefore), trigger);
|
|
135048
135498
|
const navCountBefore = navEdges.length;
|
|
@@ -135301,7 +135751,7 @@ async function bootAndSnapshotState(opts) {
|
|
|
135301
135751
|
}
|
|
135302
135752
|
try {
|
|
135303
135753
|
for (let i2 = 0; i2 < 20; i2++) await yieldMacrotask();
|
|
135304
|
-
return
|
|
135754
|
+
return snapshot2(w2).state;
|
|
135305
135755
|
} finally {
|
|
135306
135756
|
w2.dispose();
|
|
135307
135757
|
}
|
|
@@ -135376,7 +135826,7 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
135376
135826
|
threwAt = "unreachable";
|
|
135377
135827
|
break;
|
|
135378
135828
|
}
|
|
135379
|
-
const effective = effectiveSiteFor(site,
|
|
135829
|
+
const effective = effectiveSiteFor(site, snapshot2(w2).state);
|
|
135380
135830
|
if (!effective) {
|
|
135381
135831
|
threwAt = "unreachable";
|
|
135382
135832
|
break;
|
|
@@ -135415,7 +135865,7 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
135415
135865
|
}
|
|
135416
135866
|
for (let i2 = 0; i2 < 20; i2++) await yieldMacrotask();
|
|
135417
135867
|
flushStep();
|
|
135418
|
-
const { state, defects } =
|
|
135868
|
+
const { state, defects } = snapshot2(w2);
|
|
135419
135869
|
const hash2 = deepStateSignature(state, defects);
|
|
135420
135870
|
if (visited.has(hash2)) continue;
|
|
135421
135871
|
visited.add(hash2);
|
|
@@ -135549,7 +135999,7 @@ async function crawlScreenRelations(opts) {
|
|
|
135549
135999
|
const w2 = await boot();
|
|
135550
136000
|
try {
|
|
135551
136001
|
if (w2.errors.length) return null;
|
|
135552
|
-
let prev =
|
|
136002
|
+
let prev = snapshot2(w2).state;
|
|
135553
136003
|
const bootState = prev;
|
|
135554
136004
|
for (const [i2, site] of path2.entries()) {
|
|
135555
136005
|
const parsed = parseWorkerAction(site.actionId);
|
|
@@ -135566,7 +136016,7 @@ async function crawlScreenRelations(opts) {
|
|
|
135566
136016
|
}
|
|
135567
136017
|
for (let k2 = 0; k2 < 20; k2++) await yieldMacrotask();
|
|
135568
136018
|
if (w2.errors.length) return null;
|
|
135569
|
-
prev =
|
|
136019
|
+
prev = snapshot2(w2).state;
|
|
135570
136020
|
}
|
|
135571
136021
|
return prev;
|
|
135572
136022
|
} finally {
|
|
@@ -136773,7 +137223,7 @@ async function liveRenderServices(bundleJs, opts) {
|
|
|
136773
137223
|
}
|
|
136774
137224
|
}
|
|
136775
137225
|
if (opts.host) await settleUnawaitedWork();
|
|
136776
|
-
return { services:
|
|
137226
|
+
return { services: snapshot2(w2).state, calls: w2.calls, errors: w2.errors };
|
|
136777
137227
|
} finally {
|
|
136778
137228
|
w2.dispose();
|
|
136779
137229
|
}
|
|
@@ -136788,7 +137238,7 @@ async function loadAndSettle(bundleJs, options) {
|
|
|
136788
137238
|
const w2 = await bootBundleWorker(bundleJs, options);
|
|
136789
137239
|
try {
|
|
136790
137240
|
await settleUnawaitedWork();
|
|
136791
|
-
return { services:
|
|
137241
|
+
return { services: snapshot2(w2).state, calls: w2.calls, errors: w2.errors };
|
|
136792
137242
|
} finally {
|
|
136793
137243
|
w2.dispose();
|
|
136794
137244
|
}
|
|
@@ -137492,7 +137942,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
137492
137942
|
}
|
|
137493
137943
|
}
|
|
137494
137944
|
}
|
|
137495
|
-
const
|
|
137945
|
+
const snapshot3 = await snapshotTokens(
|
|
137496
137946
|
app,
|
|
137497
137947
|
base,
|
|
137498
137948
|
async () => {
|
|
@@ -137522,10 +137972,10 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
137522
137972
|
},
|
|
137523
137973
|
(text11) => store.putTokens(app, text11)
|
|
137524
137974
|
);
|
|
137525
|
-
if (
|
|
137526
|
-
if (
|
|
137527
|
-
tokensSnapshotFailure =
|
|
137528
|
-
console.error(
|
|
137975
|
+
if (snapshot3.hash) tokensHash = snapshot3.hash;
|
|
137976
|
+
if (snapshot3.failure) {
|
|
137977
|
+
tokensSnapshotFailure = snapshot3.failure;
|
|
137978
|
+
console.error(snapshot3.failure.message);
|
|
137529
137979
|
}
|
|
137530
137980
|
Object.assign(catalogs, await bakeCatalogs(
|
|
137531
137981
|
app,
|
|
@@ -140159,13 +140609,237 @@ var init_wix_owner = __esm({
|
|
|
140159
140609
|
}
|
|
140160
140610
|
});
|
|
140161
140611
|
|
|
140612
|
+
// src/captcha-auth.ts
|
|
140613
|
+
function captchaAuthFinding(auth, siteId, platforms) {
|
|
140614
|
+
const login = auth;
|
|
140615
|
+
if (login?.providerId !== "wix-consumer") return void 0;
|
|
140616
|
+
const inline = login.config?.captcha;
|
|
140617
|
+
const hasInline = typeof inline === "object" && inline !== null;
|
|
140618
|
+
const inlineFor = (platform) => hasInline && !!inline[platform];
|
|
140619
|
+
const inlineKeys = platforms?.length ? platforms.every(inlineFor) : inlineFor("ios") || inlineFor("android");
|
|
140620
|
+
const site = siteId?.trim().toLowerCase();
|
|
140621
|
+
const bound2 = typeof login.config?.siteId === "string" ? login.config.siteId : "";
|
|
140622
|
+
const uncovered = hasInline ? (platforms ?? []).filter((platform) => !inlineFor(platform)) : [];
|
|
140623
|
+
if (bound2 && uncovered.length) return {
|
|
140624
|
+
code: "captcha_auth_inline_key_missing",
|
|
140625
|
+
keyless: true,
|
|
140626
|
+
message: `auth (WixConsumerAuthProvider) declares inline captcha keys but none for ${uncovered.join(" and ")}, and the inline block replaces the baked key file on device \u2014 a native ${uncovered.join("/")} build ships with no member CAPTCHA key. Add captcha.${uncovered[0]} (or remove the captcha block to use the baked key), push a new release, and build from it.`
|
|
140627
|
+
};
|
|
140628
|
+
if (!bound2) return {
|
|
140629
|
+
code: "captcha_auth_site_missing",
|
|
140630
|
+
keyless: true,
|
|
140631
|
+
message: `auth (WixConsumerAuthProvider) names no siteId, so a native build cannot carry a member CAPTCHA key: the build drops the key file and the device refuses the key \u2014 member sign-in on a CAPTCHA-protected site fails with "Complete verification to continue". Add siteId: "${site ?? "<the site's metaSiteId, lower case>"}" to WixConsumerAuthProvider in config.ts, push a new release, and build from it.`
|
|
140632
|
+
};
|
|
140633
|
+
if (bound2 !== bound2.trim().toLowerCase() && !inlineKeys) return {
|
|
140634
|
+
code: "captcha_auth_site_case",
|
|
140635
|
+
keyless: true,
|
|
140636
|
+
message: `auth (WixConsumerAuthProvider) names siteId "${bound2}", but member CAPTCHA keys are stored and matched under the lower-case id, exactly, so a native build would ship without one. Write siteId: "${bound2.trim().toLowerCase()}", push a new release, and build from it.`
|
|
140637
|
+
};
|
|
140638
|
+
if (site && bound2.trim().toLowerCase() !== site) return {
|
|
140639
|
+
code: "captcha_auth_site_mismatch",
|
|
140640
|
+
keyless: false,
|
|
140641
|
+
message: `auth (WixConsumerAuthProvider) names siteId "${bound2}", not ${site}, so a member CAPTCHA key for ${site} cannot bind to this app's login and native member sign-in on a CAPTCHA-protected site fails. Bind the login and the build to the same site.`
|
|
140642
|
+
};
|
|
140643
|
+
return void 0;
|
|
140644
|
+
}
|
|
140645
|
+
var init_captcha_auth = __esm({
|
|
140646
|
+
"src/captcha-auth.ts"() {
|
|
140647
|
+
}
|
|
140648
|
+
});
|
|
140649
|
+
|
|
140650
|
+
// ../../stdlib/auth-providers/wix/src/member-captcha-policy.ts
|
|
140651
|
+
function acceptsClientSiteKeyToken(option) {
|
|
140652
|
+
return CLIENT_SITE_KEY_OPTIONS.includes(option);
|
|
140653
|
+
}
|
|
140654
|
+
function asOption(value2) {
|
|
140655
|
+
return value2 === "ALWAYS" || value2 === "SUSPECTED_BOTS_ONLY" || value2 === "NEVER" ? value2 : "UNKNOWN";
|
|
140656
|
+
}
|
|
140657
|
+
function parseMemberCaptchaPolicy(raw) {
|
|
140658
|
+
const settings = raw?.settings ?? {};
|
|
140659
|
+
return {
|
|
140660
|
+
login: asOption(settings.loginRecaptchaOption),
|
|
140661
|
+
signup: asOption(settings.signupRecaptchaOption)
|
|
140662
|
+
};
|
|
140663
|
+
}
|
|
140664
|
+
var MEMBER_SITE_SETTINGS_URL, CLIENT_SITE_KEY_OPTIONS;
|
|
140665
|
+
var init_member_captcha_policy = __esm({
|
|
140666
|
+
"../../stdlib/auth-providers/wix/src/member-captcha-policy.ts"() {
|
|
140667
|
+
MEMBER_SITE_SETTINGS_URL = "https://manage.wix.com/_api/wix-sm-webapp/v1/collection/settings";
|
|
140668
|
+
CLIENT_SITE_KEY_OPTIONS = ["ALWAYS", "SUSPECTED_BOTS_ONLY"];
|
|
140669
|
+
}
|
|
140670
|
+
});
|
|
140671
|
+
|
|
140672
|
+
// src/site-analyze/rest.ts
|
|
140673
|
+
var rest_exports = {};
|
|
140674
|
+
__export(rest_exports, {
|
|
140675
|
+
WIX_API: () => WIX_API2,
|
|
140676
|
+
WixApiError: () => WixApiError2,
|
|
140677
|
+
classifyHttp: () => classifyHttp,
|
|
140678
|
+
compactWixstaticUrl: () => compactWixstaticUrl,
|
|
140679
|
+
isGenericWixFavicon: () => isGenericWixFavicon,
|
|
140680
|
+
makeTransport: () => makeTransport,
|
|
140681
|
+
mediaUrlFromLogo: () => mediaUrlFromLogo,
|
|
140682
|
+
ownerTransportFrom: () => ownerTransportFrom,
|
|
140683
|
+
probeCall: () => probeCall,
|
|
140684
|
+
resolveWixUrl: () => resolveWixUrl,
|
|
140685
|
+
uploadMediaBytes: () => uploadMediaBytes,
|
|
140686
|
+
visitorTransportFrom: () => visitorTransportFrom,
|
|
140687
|
+
wixMediaFileId: () => wixMediaFileId
|
|
140688
|
+
});
|
|
140689
|
+
function resolveWixUrl(path2) {
|
|
140690
|
+
if (/^https?:\/\//i.test(path2)) return path2;
|
|
140691
|
+
return `${WIX_API2}${path2}`;
|
|
140692
|
+
}
|
|
140693
|
+
function classifyHttp(status, count2) {
|
|
140694
|
+
if (status === 428) return "not-installed";
|
|
140695
|
+
if (status === 404) return "wrong-path";
|
|
140696
|
+
if (status && status >= 400) return "error";
|
|
140697
|
+
return count2 > 0 ? "ok" : "empty";
|
|
140698
|
+
}
|
|
140699
|
+
function makeTransport(fetchImpl, auth, timeoutMs = DEFAULT_TIMEOUT_MS2) {
|
|
140700
|
+
return async (method, path2, body) => {
|
|
140701
|
+
const headers2 = { Accept: "application/json" };
|
|
140702
|
+
if (auth?.token) headers2.Authorization = auth.token;
|
|
140703
|
+
if (auth?.msid) headers2["wix-site-id"] = auth.msid;
|
|
140704
|
+
if (body !== void 0) headers2["Content-Type"] = "application/json";
|
|
140705
|
+
const res = await fetchImpl(resolveWixUrl(path2), {
|
|
140706
|
+
method,
|
|
140707
|
+
headers: headers2,
|
|
140708
|
+
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
140709
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
140710
|
+
});
|
|
140711
|
+
const text11 = await res.text();
|
|
140712
|
+
let parsed = text11;
|
|
140713
|
+
try {
|
|
140714
|
+
parsed = text11 ? JSON.parse(text11) : null;
|
|
140715
|
+
} catch {
|
|
140716
|
+
}
|
|
140717
|
+
if (!res.ok) throw new WixApiError2(res.status, method, path2, parsed);
|
|
140718
|
+
return parsed;
|
|
140719
|
+
};
|
|
140720
|
+
}
|
|
140721
|
+
function ownerTransportFrom(fetchImpl, owner) {
|
|
140722
|
+
return makeTransport(fetchImpl, { token: owner.token, msid: owner.msid });
|
|
140723
|
+
}
|
|
140724
|
+
function visitorTransportFrom(fetchImpl, token, msid) {
|
|
140725
|
+
return makeTransport(fetchImpl, { token, msid });
|
|
140726
|
+
}
|
|
140727
|
+
async function probeCall(call, method, path2, body) {
|
|
140728
|
+
try {
|
|
140729
|
+
return { data: await call(method, path2, body), err: null };
|
|
140730
|
+
} catch (e2) {
|
|
140731
|
+
if (e2 instanceof WixApiError2) return { data: null, err: e2 };
|
|
140732
|
+
throw e2;
|
|
140733
|
+
}
|
|
140734
|
+
}
|
|
140735
|
+
function mediaUrlFromLogo(logo) {
|
|
140736
|
+
const s2 = (logo ?? "").trim();
|
|
140737
|
+
if (!s2) return null;
|
|
140738
|
+
if (/^https?:\/\//i.test(s2)) return s2;
|
|
140739
|
+
const id = s2.replace(/^wix:image:\/\/v1\//, "").split("/")[0].split("#")[0];
|
|
140740
|
+
if (!id) return null;
|
|
140741
|
+
if (/^https?:\/\//i.test(id)) return id;
|
|
140742
|
+
return `https://static.wixstatic.com/media/${id}`;
|
|
140743
|
+
}
|
|
140744
|
+
function isGenericWixFavicon(url) {
|
|
140745
|
+
try {
|
|
140746
|
+
const h2 = new URL(url).hostname.toLowerCase();
|
|
140747
|
+
return h2 === "wix.com" || h2.endsWith(".wix.com");
|
|
140748
|
+
} catch {
|
|
140749
|
+
return false;
|
|
140750
|
+
}
|
|
140751
|
+
}
|
|
140752
|
+
function wixMediaFileId(url) {
|
|
140753
|
+
const m2 = url.match(/static\.wixstatic\.com\/media\/([^/?#]+)/i);
|
|
140754
|
+
return m2?.[1] ? decodeURIComponent(m2[1]) : void 0;
|
|
140755
|
+
}
|
|
140756
|
+
function compactWixstaticUrl(url, maxEdge = 800) {
|
|
140757
|
+
if (!/static\.wixstatic\.com\/media\//i.test(url)) return url;
|
|
140758
|
+
if (/\.(svg|ico)(\?|#|$)/i.test(url.split("?")[0] ?? url)) return url;
|
|
140759
|
+
const w2 = url.match(/(?:\/|,)w_(\d+)/)?.[1];
|
|
140760
|
+
if (w2 && Number(w2) <= maxEdge) return url;
|
|
140761
|
+
const id = wixMediaFileId(url);
|
|
140762
|
+
if (!id) return url;
|
|
140763
|
+
return `https://static.wixstatic.com/media/${id}/v1/fill/w_${maxEdge},h_${maxEdge},al_c,q_80,enc_auto/file.jpg`;
|
|
140764
|
+
}
|
|
140765
|
+
async function uploadMediaBytes(call, fetchImpl, bytes2, fileName, mimeType) {
|
|
140766
|
+
const { uploadUrl } = await call(
|
|
140767
|
+
"POST",
|
|
140768
|
+
"/site-media/v1/files/generate-upload-url",
|
|
140769
|
+
{ mimeType, fileName: `himi-business-book/${fileName}` }
|
|
140770
|
+
);
|
|
140771
|
+
const put = await fetchImpl(`${uploadUrl}?filename=${encodeURIComponent(fileName)}`, {
|
|
140772
|
+
method: "PUT",
|
|
140773
|
+
headers: { "Content-Type": mimeType },
|
|
140774
|
+
body: bytes2,
|
|
140775
|
+
signal: AbortSignal.timeout(12e4)
|
|
140776
|
+
});
|
|
140777
|
+
if (!put.ok) throw new Error(`media upload PUT failed: ${put.status}`);
|
|
140778
|
+
const payload = await put.json();
|
|
140779
|
+
const file2 = payload.file ?? payload;
|
|
140780
|
+
const id = file2?.id ?? file2?.fileId;
|
|
140781
|
+
const url = file2?.url ?? (id ? `https://static.wixstatic.com/media/${id}` : void 0);
|
|
140782
|
+
if (!id || !url) throw new Error("media upload returned no file id");
|
|
140783
|
+
return { id, url };
|
|
140784
|
+
}
|
|
140785
|
+
var WIX_API2, DEFAULT_TIMEOUT_MS2, WixApiError2;
|
|
140786
|
+
var init_rest = __esm({
|
|
140787
|
+
"src/site-analyze/rest.ts"() {
|
|
140788
|
+
WIX_API2 = "https://www.wixapis.com";
|
|
140789
|
+
DEFAULT_TIMEOUT_MS2 = 8e3;
|
|
140790
|
+
WixApiError2 = class extends Error {
|
|
140791
|
+
constructor(status, method, path2, body) {
|
|
140792
|
+
super(`${method} ${path2} \u2192 ${status}`);
|
|
140793
|
+
this.status = status;
|
|
140794
|
+
this.method = method;
|
|
140795
|
+
this.path = path2;
|
|
140796
|
+
this.body = body;
|
|
140797
|
+
this.name = "WixApiError";
|
|
140798
|
+
}
|
|
140799
|
+
};
|
|
140800
|
+
}
|
|
140801
|
+
});
|
|
140802
|
+
|
|
140803
|
+
// src/site-analyze/visitor-auth.ts
|
|
140804
|
+
var visitor_auth_exports = {};
|
|
140805
|
+
__export(visitor_auth_exports, {
|
|
140806
|
+
mintVisitorToken: () => mintVisitorToken
|
|
140807
|
+
});
|
|
140808
|
+
async function mintVisitorToken(fetchImpl, clientId) {
|
|
140809
|
+
const res = await fetchImpl(`${WIX_API2}/oauth2/token`, {
|
|
140810
|
+
method: "POST",
|
|
140811
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
140812
|
+
body: JSON.stringify({ clientId, grantType: "anonymous" }),
|
|
140813
|
+
signal: AbortSignal.timeout(8e3)
|
|
140814
|
+
});
|
|
140815
|
+
const text11 = await res.text();
|
|
140816
|
+
let parsed = text11;
|
|
140817
|
+
try {
|
|
140818
|
+
parsed = text11 ? JSON.parse(text11) : null;
|
|
140819
|
+
} catch {
|
|
140820
|
+
}
|
|
140821
|
+
if (!res.ok) throw new WixApiError2(res.status, "POST", "/oauth2/token", parsed);
|
|
140822
|
+
const token = parsed?.access_token ?? parsed?.accessToken;
|
|
140823
|
+
if (!token) throw new Error("visitor mint returned no access_token");
|
|
140824
|
+
return token;
|
|
140825
|
+
}
|
|
140826
|
+
var init_visitor_auth = __esm({
|
|
140827
|
+
"src/site-analyze/visitor-auth.ts"() {
|
|
140828
|
+
init_rest();
|
|
140829
|
+
}
|
|
140830
|
+
});
|
|
140831
|
+
|
|
140162
140832
|
// src/captcha.ts
|
|
140163
140833
|
var captcha_exports = {};
|
|
140164
140834
|
__export(captcha_exports, {
|
|
140835
|
+
captchaAuthFinding: () => captchaAuthFinding,
|
|
140165
140836
|
captchaContentInput: () => captchaContentInput,
|
|
140166
|
-
|
|
140837
|
+
captchaDistGate: () => captchaDistGate,
|
|
140838
|
+
contentCaptchaAuthFinding: () => contentCaptchaAuthFinding,
|
|
140839
|
+
runCaptcha: () => runCaptcha,
|
|
140840
|
+
siteMemberCaptchaPolicy: () => siteMemberCaptchaPolicy
|
|
140167
140841
|
});
|
|
140168
|
-
import { readFileSync as readFileSync40 } from "node:fs";
|
|
140842
|
+
import { existsSync as existsSync36, readFileSync as readFileSync40 } from "node:fs";
|
|
140169
140843
|
import { resolve as resolve34 } from "node:path";
|
|
140170
140844
|
function readObject(path2) {
|
|
140171
140845
|
try {
|
|
@@ -140184,6 +140858,64 @@ function captchaContentInput(dir) {
|
|
|
140184
140858
|
androidApplicationId: text2(provisioning.native?.androidApplicationId)
|
|
140185
140859
|
};
|
|
140186
140860
|
}
|
|
140861
|
+
async function contentAuth(dir, app) {
|
|
140862
|
+
if (!existsSync36(resolve34(dir, "himalaya.content.json"))) return void 0;
|
|
140863
|
+
if (app !== void 0 && captchaContentInput(dir).app !== app) return void 0;
|
|
140864
|
+
try {
|
|
140865
|
+
const { loadAppConfigModule: loadAppConfigModule2 } = await Promise.resolve().then(() => (init_app_config_loader(), app_config_loader_exports));
|
|
140866
|
+
return (await loadAppConfigModule2(dir))?.auth;
|
|
140867
|
+
} catch {
|
|
140868
|
+
return void 0;
|
|
140869
|
+
}
|
|
140870
|
+
}
|
|
140871
|
+
async function contentCaptchaAuthFinding(dir, siteId, app, platforms) {
|
|
140872
|
+
const auth = await contentAuth(dir, app);
|
|
140873
|
+
return auth === void 0 ? void 0 : captchaAuthFinding(auth, siteId, platforms);
|
|
140874
|
+
}
|
|
140875
|
+
async function siteMemberCaptchaPolicy(clientId, fetchImpl = fetch) {
|
|
140876
|
+
const { mintVisitorToken: mintVisitorToken2 } = await Promise.resolve().then(() => (init_visitor_auth(), visitor_auth_exports));
|
|
140877
|
+
const token = await mintVisitorToken2(fetchImpl, clientId);
|
|
140878
|
+
const res = await fetchImpl(MEMBER_SITE_SETTINGS_URL, {
|
|
140879
|
+
headers: { Authorization: token, Accept: "application/json" },
|
|
140880
|
+
signal: AbortSignal.timeout(8e3)
|
|
140881
|
+
});
|
|
140882
|
+
if (!res.ok) throw new Error(`the member settings read answered HTTP ${res.status}`);
|
|
140883
|
+
return parseMemberCaptchaPolicy(await res.json());
|
|
140884
|
+
}
|
|
140885
|
+
async function releaseAuth(client2, app, release2) {
|
|
140886
|
+
try {
|
|
140887
|
+
let previewToken;
|
|
140888
|
+
if (release2) {
|
|
140889
|
+
const minted = await client2.previewToken(app, release2);
|
|
140890
|
+
previewToken = minted.json?.previewToken;
|
|
140891
|
+
if (!minted.ok || typeof previewToken !== "string") return { error: `no preview token for release ${release2} (HTTP ${minted.status})` };
|
|
140892
|
+
}
|
|
140893
|
+
const read = await client2.fetchAppConfig(app, release2, previewToken);
|
|
140894
|
+
if (!read.ok) return { error: `its app-config read answered HTTP ${read.status}` };
|
|
140895
|
+
return { auth: read.json?.authConfig ?? null };
|
|
140896
|
+
} catch (error) {
|
|
140897
|
+
return { error: error?.message ?? String(error) };
|
|
140898
|
+
}
|
|
140899
|
+
}
|
|
140900
|
+
async function captchaDistGate(options) {
|
|
140901
|
+
const { auth, error } = await releaseAuth(options.client, options.app, options.release);
|
|
140902
|
+
if (error) return { advisory: `member CAPTCHA check skipped: the release's login could not be read (${error}). If the login names no siteId and the site requires a member CAPTCHA, member sign-in in this build will fail.` };
|
|
140903
|
+
const finding2 = captchaAuthFinding(auth, options.requestedSite, options.platforms);
|
|
140904
|
+
if (!finding2) return {};
|
|
140905
|
+
if (!finding2.keyless) return { advisory: `${finding2.code}: ${finding2.message}` };
|
|
140906
|
+
const clientId = auth.config?.clientId;
|
|
140907
|
+
const unasked = (why) => ({ advisory: `${finding2.code}: ${finding2.message} Not refused: ${why}, so whether the site requires a member CAPTCHA is unknown \u2014 if it does, member sign-in in this build will fail.` });
|
|
140908
|
+
if (typeof clientId !== "string" || !clientId || clientId === PLACEHOLDER_CLIENT_ID) return unasked("the login has no Wix client to ask with");
|
|
140909
|
+
let policy;
|
|
140910
|
+
try {
|
|
140911
|
+
policy = await siteMemberCaptchaPolicy(clientId, options.fetchImpl ?? fetch);
|
|
140912
|
+
} catch (error2) {
|
|
140913
|
+
return unasked(`the site's member settings could not be read (${error2?.message ?? String(error2)})`);
|
|
140914
|
+
}
|
|
140915
|
+
const demands = ["login", "signup"].filter((source) => acceptsClientSiteKeyToken(policy[source]));
|
|
140916
|
+
if (demands.length === 0) return {};
|
|
140917
|
+
return { refuse: { code: finding2.code, captchaPolicy: policy, message: `${finding2.message} The site requires a CAPTCHA for member ${demands.map((source) => `${source} (${policy[source]})`).join(" and ")}. The key is baked only for a build bound to the site (--site, provisioning.json, or the app's own site binding).` } };
|
|
140918
|
+
}
|
|
140187
140919
|
async function runCaptcha(pos, flags, io2, deps = {}) {
|
|
140188
140920
|
const operation = pos[1];
|
|
140189
140921
|
if (operation !== "setup" && operation !== "status") {
|
|
@@ -140213,6 +140945,14 @@ async function runCaptcha(pos, flags, io2, deps = {}) {
|
|
|
140213
140945
|
fetchImpl: deps.fetchImpl
|
|
140214
140946
|
});
|
|
140215
140947
|
io2.log(JSON.stringify(result.body));
|
|
140948
|
+
const anyReady = (result.body.records ?? []).some((record2) => record2?.status === "ready");
|
|
140949
|
+
const finding2 = operation === "setup" && anyReady ? await contentCaptchaAuthFinding(
|
|
140950
|
+
text2(flags.content) ?? process.cwd(),
|
|
140951
|
+
input.siteId,
|
|
140952
|
+
input.app,
|
|
140953
|
+
[...input.iosBundleId ? ["ios"] : [], ...input.androidApplicationId ? ["android"] : []]
|
|
140954
|
+
) : void 0;
|
|
140955
|
+
if (finding2) io2.error(`\u26A0 ${finding2.code}: ${finding2.message}`);
|
|
140216
140956
|
return result.ok ? 0 : 1;
|
|
140217
140957
|
} catch {
|
|
140218
140958
|
io2.error(JSON.stringify({ error: "captcha_service_unavailable", complete: false }));
|
|
@@ -140226,6 +140966,9 @@ var init_captcha2 = __esm({
|
|
|
140226
140966
|
init_captcha();
|
|
140227
140967
|
init_captcha_service();
|
|
140228
140968
|
init_wix_owner();
|
|
140969
|
+
init_captcha_auth();
|
|
140970
|
+
init_wix_placeholders();
|
|
140971
|
+
init_member_captcha_policy();
|
|
140229
140972
|
text2 = (value2) => typeof value2 === "string" ? value2 : void 0;
|
|
140230
140973
|
}
|
|
140231
140974
|
});
|
|
@@ -140239,7 +140982,7 @@ __export(preflight_exports, {
|
|
|
140239
140982
|
parseStoreConfig: () => parseStoreConfig,
|
|
140240
140983
|
requireEnv: () => requireEnv
|
|
140241
140984
|
});
|
|
140242
|
-
import { existsSync as
|
|
140985
|
+
import { existsSync as existsSync37, readFileSync as readFileSync41 } from "node:fs";
|
|
140243
140986
|
import { isAbsolute as isAbsolute2, relative as relative7, resolve as resolve35 } from "node:path";
|
|
140244
140987
|
function isInsideRepo(p2) {
|
|
140245
140988
|
const rel = relative7(REPO_ROOT, resolve35(p2));
|
|
@@ -140296,7 +141039,7 @@ function parseStoreConfig(text11) {
|
|
|
140296
141039
|
}
|
|
140297
141040
|
function loadStoreConfig(app) {
|
|
140298
141041
|
const p2 = storeConfigPath(app);
|
|
140299
|
-
if (!
|
|
141042
|
+
if (!existsSync37(p2)) {
|
|
140300
141043
|
throw new Error(`No store config at ${p2}. Create apps/${app}/store/store.config.yaml first (see /setup-store-signing).`);
|
|
140301
141044
|
}
|
|
140302
141045
|
return parseStoreConfig(readFileSync41(p2, "utf8"));
|
|
@@ -143987,10 +144730,10 @@ var init_Matcher = __esm({
|
|
|
143987
144730
|
* Restore state from snapshot.
|
|
143988
144731
|
* @param {Object} snapshot
|
|
143989
144732
|
*/
|
|
143990
|
-
restore(
|
|
144733
|
+
restore(snapshot3) {
|
|
143991
144734
|
this._pathStringCache = null;
|
|
143992
|
-
this.path =
|
|
143993
|
-
this.siblingStacks =
|
|
144735
|
+
this.path = snapshot3.path.map((node) => ({ ...node }));
|
|
144736
|
+
this.siblingStacks = snapshot3.siblingStacks.map((map) => new Map(map));
|
|
143994
144737
|
}
|
|
143995
144738
|
/**
|
|
143996
144739
|
* Return the read-only {@link MatcherView} for this matcher.
|
|
@@ -147028,7 +147771,7 @@ var init_customer_signing_inspect = __esm({
|
|
|
147028
147771
|
});
|
|
147029
147772
|
|
|
147030
147773
|
// src/push-onboarding.ts
|
|
147031
|
-
import { existsSync as
|
|
147774
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync19, readFileSync as readFileSync42, statSync as statSync9, writeFileSync as writeFileSync13, chmodSync as chmodSync2 } from "node:fs";
|
|
147032
147775
|
import { basename as basename11, dirname as dirname24, join as join32, resolve as resolve36 } from "node:path";
|
|
147033
147776
|
function readJson4(path2) {
|
|
147034
147777
|
try {
|
|
@@ -147040,7 +147783,7 @@ function readJson4(path2) {
|
|
|
147040
147783
|
}
|
|
147041
147784
|
function pushInputsFromContent(dir) {
|
|
147042
147785
|
const root = resolve36(dir);
|
|
147043
|
-
if (!
|
|
147786
|
+
if (!existsSync38(join32(root, "himalaya.content.json"))) return { initialized: false };
|
|
147044
147787
|
const content = readJson4(join32(root, "himalaya.content.json"));
|
|
147045
147788
|
const provisioning = readJson4(join32(root, "provisioning.json"));
|
|
147046
147789
|
const native = provisioning.native ?? {};
|
|
@@ -147172,7 +147915,7 @@ function buildPushSetupBody(i2, keys) {
|
|
|
147172
147915
|
}
|
|
147173
147916
|
function readPushOnboarding(dir) {
|
|
147174
147917
|
const path2 = join32(resolve36(dir), PUSH_ONBOARDING_PATH);
|
|
147175
|
-
if (!
|
|
147918
|
+
if (!existsSync38(path2)) return { version: 1 };
|
|
147176
147919
|
const parsed = readJson4(path2);
|
|
147177
147920
|
return { version: 1, ...parsed };
|
|
147178
147921
|
}
|
|
@@ -147207,7 +147950,7 @@ function recordPushDeferral(dir, d2) {
|
|
|
147207
147950
|
}
|
|
147208
147951
|
function clearPushDeferral(dir) {
|
|
147209
147952
|
const path2 = join32(resolve36(dir), PUSH_ONBOARDING_PATH);
|
|
147210
|
-
if (!
|
|
147953
|
+
if (!existsSync38(path2)) return;
|
|
147211
147954
|
const { push: _dropped, ...rest } = readPushOnboarding(dir);
|
|
147212
147955
|
writeFile(dir, { ...rest, version: 1 });
|
|
147213
147956
|
}
|
|
@@ -147275,7 +148018,7 @@ var signing_inspect_exports = {};
|
|
|
147275
148018
|
__export(signing_inspect_exports, {
|
|
147276
148019
|
runSigningInspect: () => runSigningInspect
|
|
147277
148020
|
});
|
|
147278
|
-
import { existsSync as
|
|
148021
|
+
import { existsSync as existsSync39, readFileSync as readFileSync43, statSync as statSync10 } from "node:fs";
|
|
147279
148022
|
import { isAbsolute as isAbsolute3, resolve as resolve37 } from "node:path";
|
|
147280
148023
|
function fail4(io2, code, fields = {}) {
|
|
147281
148024
|
io2.error(JSON.stringify({ ok: false, code, ...fields }));
|
|
@@ -147365,7 +148108,7 @@ async function runSigningInspect(pos, flags, io2, deps = {}) {
|
|
|
147365
148108
|
} catch (error) {
|
|
147366
148109
|
return fail4(io2, "signing_inspect_key_inside_repo", { error: error.message });
|
|
147367
148110
|
}
|
|
147368
|
-
if (!
|
|
148111
|
+
if (!existsSync39(certPath) || !existsSync39(profilePath2)) {
|
|
147369
148112
|
return fail4(io2, "signing_inspect_local_assets_unreadable", { error: "cannot read --cert-file or --profile-file" });
|
|
147370
148113
|
}
|
|
147371
148114
|
if (statSync10(certPath).size > 1048576 || statSync10(profilePath2).size > 1048576) {
|
|
@@ -147899,7 +148642,7 @@ __export(template_trim_exports, {
|
|
|
147899
148642
|
routeMatcher: () => routeMatcher,
|
|
147900
148643
|
runTemplateTrim: () => runTemplateTrim
|
|
147901
148644
|
});
|
|
147902
|
-
import { cpSync, existsSync as
|
|
148645
|
+
import { cpSync, existsSync as existsSync40, mkdirSync as mkdirSync20, readdirSync as readdirSync21, readFileSync as readFileSync45, renameSync as renameSync8, rmSync as rmSync11, statSync as statSync11, writeFileSync as writeFileSync15 } from "node:fs";
|
|
147903
148646
|
import { dirname as dirname25, join as join34 } from "node:path";
|
|
147904
148647
|
function routeMatcher(pattern) {
|
|
147905
148648
|
const detail = /^\^([A-Za-z0-9_]+)\(\?:\[_\/\]\(\.\+\)\)\?\$$/.exec(pattern);
|
|
@@ -148644,7 +149387,7 @@ function homeModulesPass(app, kept, edited) {
|
|
|
148644
149387
|
}
|
|
148645
149388
|
function listWorkers(dir) {
|
|
148646
149389
|
const root = join34(dir, "tier5-src");
|
|
148647
|
-
if (!
|
|
149390
|
+
if (!existsSync40(root)) return { dirs: [], files: {} };
|
|
148648
149391
|
const dirs = readdirSync21(root).filter((n2) => statSync11(join34(root, n2)).isDirectory()).sort();
|
|
148649
149392
|
const files = {};
|
|
148650
149393
|
const walk2 = (abs, rel) => {
|
|
@@ -148681,7 +149424,7 @@ async function runTemplateTrim(req, deps) {
|
|
|
148681
149424
|
const dir = req.dir;
|
|
148682
149425
|
const devPath = join34(dir, "dev/index.ts");
|
|
148683
149426
|
const configPath = join34(dir, "config.ts");
|
|
148684
|
-
if (!
|
|
149427
|
+
if (!existsSync40(devPath) || !existsSync40(configPath)) {
|
|
148685
149428
|
return refuse3(new TrimRefusal(`${dir} has no dev/index.ts + config.ts \u2014 point --content at an app scaffolded with \`himi init --template\``));
|
|
148686
149429
|
}
|
|
148687
149430
|
if (isTemplateSourceTree(dir)) {
|
|
@@ -148728,7 +149471,7 @@ async function runTemplateTrim(req, deps) {
|
|
|
148728
149471
|
}
|
|
148729
149472
|
}
|
|
148730
149473
|
if (req.dryRun) return { code: 0, result: { ok: true, dryRun: true, ...plan.report, validate: null } };
|
|
148731
|
-
const hadHimi =
|
|
149474
|
+
const hadHimi = existsSync40(join34(dir, ".himi"));
|
|
148732
149475
|
const backupRel = join34(".himi", "trim-backup", (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"));
|
|
148733
149476
|
const backup = join34(dir, backupRel);
|
|
148734
149477
|
const originals = [[devPath, "dev/index.ts"], [configPath, "config.ts"], ...trimmedContent !== void 0 ? [[contentPath, "himalaya.content.json"]] : []];
|
|
@@ -148737,7 +149480,7 @@ async function runTemplateTrim(req, deps) {
|
|
|
148737
149480
|
for (const [path2, rel] of originals) {
|
|
148738
149481
|
if (rel === "himalaya.content.json") contentManifestPath(dir);
|
|
148739
149482
|
const original = readFileSync45(join34(backup, rel));
|
|
148740
|
-
if (!
|
|
149483
|
+
if (!existsSync40(path2) || !readFileSync45(path2).equals(original)) {
|
|
148741
149484
|
if (rel === "himalaya.content.json") writeContentManifest(dir, original);
|
|
148742
149485
|
else writeFileSync15(path2, original);
|
|
148743
149486
|
}
|
|
@@ -149094,17 +149837,17 @@ __export(template_adopt_exports, {
|
|
|
149094
149837
|
workerReach: () => workerReach,
|
|
149095
149838
|
writeInventory: () => writeInventory
|
|
149096
149839
|
});
|
|
149097
|
-
import { existsSync as
|
|
149840
|
+
import { existsSync as existsSync41, lstatSync as lstatSync11, mkdirSync as mkdirSync21, readdirSync as readdirSync22, readFileSync as readFileSync46, renameSync as renameSync9, statSync as statSync12, writeFileSync as writeFileSync16 } from "node:fs";
|
|
149098
149841
|
import { dirname as dirname26, join as join35, posix as posix2 } from "node:path";
|
|
149099
149842
|
function readAppSources(dir) {
|
|
149100
149843
|
const devPath = join35(dir, "dev", "index.ts");
|
|
149101
149844
|
const configPath = join35(dir, "config.ts");
|
|
149102
|
-
if (!
|
|
149845
|
+
if (!existsSync41(devPath) || !existsSync41(configPath)) {
|
|
149103
149846
|
throw new TrimRefusal(`no dev/index.ts + config.ts under ${dir} \u2014 run this in (or point --content at) an app \`himi init --template\` scaffolded`);
|
|
149104
149847
|
}
|
|
149105
149848
|
const workers = /* @__PURE__ */ new Map();
|
|
149106
149849
|
const root = join35(dir, "tier5-src");
|
|
149107
|
-
if (
|
|
149850
|
+
if (existsSync41(root)) {
|
|
149108
149851
|
for (const name of readdirSync22(root).sort()) {
|
|
149109
149852
|
const abs = join35(root, name);
|
|
149110
149853
|
if (!statSync12(abs).isDirectory()) continue;
|
|
@@ -149344,7 +150087,7 @@ function inventoryOf(dir, src, app) {
|
|
|
149344
150087
|
sampleCopy: copyHits(dir, SAMPLE_COPY, 50),
|
|
149345
150088
|
matrix,
|
|
149346
150089
|
journeys,
|
|
149347
|
-
netMocks:
|
|
150090
|
+
netMocks: existsSync41(join35(dir, "dev", "net-mocks.json"))
|
|
149348
150091
|
};
|
|
149349
150092
|
}
|
|
149350
150093
|
function matrixMarkdown(rows) {
|
|
@@ -149380,9 +150123,9 @@ function inventorySummary(inv) {
|
|
|
149380
150123
|
function writeNoFollow(dir, rel, body) {
|
|
149381
150124
|
const p2 = join35(dir, rel);
|
|
149382
150125
|
const parent = dirname26(p2);
|
|
149383
|
-
if (
|
|
150126
|
+
if (existsSync41(parent) && lstatSync11(parent).isSymbolicLink()) throw new TrimRefusal(`${dirname26(rel)} is a symlink \u2014 refusing to write through it`);
|
|
149384
150127
|
mkdirSync21(parent, { recursive: true });
|
|
149385
|
-
if (
|
|
150128
|
+
if (existsSync41(p2) && lstatSync11(p2).isSymbolicLink()) throw new TrimRefusal(`${rel} is a symlink \u2014 refusing to write through it`);
|
|
149386
150129
|
const tmp = `${p2}.${process.pid}.${Date.now()}.tmp`;
|
|
149387
150130
|
writeFileSync16(tmp, body, { flag: "wx" });
|
|
149388
150131
|
renameSync9(tmp, p2);
|
|
@@ -149391,7 +150134,7 @@ function writeInventory(dir, inv, opts = {}) {
|
|
|
149391
150134
|
const written = [];
|
|
149392
150135
|
const keep = opts.companions === "if-missing";
|
|
149393
150136
|
const put = (rel, body, companion) => {
|
|
149394
|
-
if (companion && keep &&
|
|
150137
|
+
if (companion && keep && existsSync41(join35(dir, rel))) return;
|
|
149395
150138
|
writeNoFollow(dir, rel, body);
|
|
149396
150139
|
written.push(rel);
|
|
149397
150140
|
};
|
|
@@ -149497,7 +150240,7 @@ function addScreen(dir, id, entry, opts = {}) {
|
|
|
149497
150240
|
}
|
|
149498
150241
|
for (const rel of ["dev", "dev/index.ts", ...config !== src.config ? ["config.ts"] : [], ...contentWithView !== void 0 ? ["himalaya.content.json"] : []]) {
|
|
149499
150242
|
const p2 = join35(dir, rel);
|
|
149500
|
-
if (
|
|
150243
|
+
if (existsSync41(p2) && lstatSync11(p2).isSymbolicLink()) throw new TrimRefusal(`${rel} is a symlink \u2014 refusing to write through it (nothing written)`);
|
|
149501
150244
|
}
|
|
149502
150245
|
writeNoFollow(dir, "dev/index.ts", dev);
|
|
149503
150246
|
if (config !== src.config) writeNoFollow(dir, "config.ts", config);
|
|
@@ -149520,7 +150263,7 @@ function specScreens(spec) {
|
|
|
149520
150263
|
return [...new Set(out2)];
|
|
149521
150264
|
}
|
|
149522
150265
|
function keepFromSpec(dir, specPath) {
|
|
149523
|
-
if (!
|
|
150266
|
+
if (!existsSync41(specPath)) throw new TrimRefusal(`no ${specPath} \u2014 --from-spec reads the approved plan's \`## Screen catalogue\``);
|
|
149524
150267
|
const ids = specScreens(readFileSync46(specPath, "utf8"));
|
|
149525
150268
|
if (!ids.length) {
|
|
149526
150269
|
throw new TrimRefusal("SPEC.md's `## Screen catalogue` names no screen ids \u2014 put each screen's id (`himi template screens` lists them) in the first column, in backticks");
|
|
@@ -150273,7 +151016,7 @@ __export(pack_exports, {
|
|
|
150273
151016
|
});
|
|
150274
151017
|
import { createHash as createHash24 } from "node:crypto";
|
|
150275
151018
|
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
150276
|
-
import { existsSync as
|
|
151019
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync22, readFileSync as readFileSync48, readdirSync as readdirSync23, rmSync as rmSync12, statSync as statSync13, writeFileSync as writeFileSync17 } from "node:fs";
|
|
150277
151020
|
import { dirname as dirname27, join as join37, resolve as resolve39 } from "node:path";
|
|
150278
151021
|
function writeZip(entries) {
|
|
150279
151022
|
const sorted2 = entries.slice().sort((a2, b2) => a2.path < b2.path ? -1 : a2.path > b2.path ? 1 : 0);
|
|
@@ -150368,10 +151111,10 @@ function inflateEntry(buf, entry) {
|
|
|
150368
151111
|
return bytes2;
|
|
150369
151112
|
}
|
|
150370
151113
|
function readIf(path2) {
|
|
150371
|
-
return
|
|
151114
|
+
return existsSync42(path2) && statSync13(path2).isFile() ? readFileSync48(path2) : null;
|
|
150372
151115
|
}
|
|
150373
151116
|
function listDir(dir) {
|
|
150374
|
-
return
|
|
151117
|
+
return existsSync42(dir) ? readdirSync23(dir).filter((f2) => statSync13(join37(dir, f2)).isFile()) : [];
|
|
150375
151118
|
}
|
|
150376
151119
|
function gatherReleaseEntries(appDir3) {
|
|
150377
151120
|
const manifestPath = join37(appDir3, HIMI_PACKAGE_MANIFEST_PATH);
|
|
@@ -150450,7 +151193,7 @@ function packRelease(releaseRoot, app, out2, opts = {}) {
|
|
|
150450
151193
|
const appDir3 = join37(resolve39(releaseRoot), app);
|
|
150451
151194
|
const { all, header, skipped } = buildEntries(appDir3, app, opts);
|
|
150452
151195
|
const buf = writeZip(all);
|
|
150453
|
-
const isDir2 =
|
|
151196
|
+
const isDir2 = existsSync42(out2) && statSync13(out2).isDirectory();
|
|
150454
151197
|
const outFile = isDir2 ? join37(resolve39(out2), packageFileName(app, header.releaseId)) : resolve39(out2);
|
|
150455
151198
|
mkdirSync22(dirname27(outFile), { recursive: true });
|
|
150456
151199
|
writeFileSync17(outFile, buf);
|
|
@@ -150467,11 +151210,11 @@ function resolvePackageDirDest(outDir, app, releaseId) {
|
|
|
150467
151210
|
}
|
|
150468
151211
|
};
|
|
150469
151212
|
const replaceable = (dir) => {
|
|
150470
|
-
if (!
|
|
151213
|
+
if (!existsSync42(dir)) return true;
|
|
150471
151214
|
if (!statSync13(dir).isDirectory()) return false;
|
|
150472
151215
|
return readdirSync23(dir).length === 0 || packagedApp(dir) === app;
|
|
150473
151216
|
};
|
|
150474
|
-
if (
|
|
151217
|
+
if (existsSync42(outDir) && !statSync13(outDir).isDirectory()) {
|
|
150475
151218
|
throw new Error(`refusing to write a package tree over ${outDir} \u2014 it is a file, not a directory`);
|
|
150476
151219
|
}
|
|
150477
151220
|
if (replaceable(outDir)) return outDir;
|
|
@@ -150532,7 +151275,7 @@ function openPackageDir(dir) {
|
|
|
150532
151275
|
else if (isSafeEntryName(childRel)) entries.set(childRel, readFileSync48(childAbs));
|
|
150533
151276
|
}
|
|
150534
151277
|
};
|
|
150535
|
-
if (!
|
|
151278
|
+
if (!existsSync42(root)) throw new Error(`no such package directory: ${root}`);
|
|
150536
151279
|
walk2("");
|
|
150537
151280
|
const manifestBytes = entries.get(HIMI_PACKAGE_MANIFEST_PATH);
|
|
150538
151281
|
if (manifestBytes) {
|
|
@@ -150617,7 +151360,7 @@ __export(app_source_exports, {
|
|
|
150617
151360
|
zipAppSource: () => zipAppSource
|
|
150618
151361
|
});
|
|
150619
151362
|
import { createHash as createHash25 } from "node:crypto";
|
|
150620
|
-
import { readdirSync as readdirSync24, lstatSync as lstatSync13, readFileSync as readFileSync49, mkdirSync as mkdirSync23, writeFileSync as writeFileSync18, existsSync as
|
|
151363
|
+
import { readdirSync as readdirSync24, lstatSync as lstatSync13, readFileSync as readFileSync49, mkdirSync as mkdirSync23, writeFileSync as writeFileSync18, existsSync as existsSync43, rmSync as rmSync13, rmdirSync as rmdirSync2, unlinkSync as unlinkSync3 } from "node:fs";
|
|
150621
151364
|
import { join as join38, resolve as resolve40, sep as sep13 } from "node:path";
|
|
150622
151365
|
import { createRequire as createRequire3 } from "node:module";
|
|
150623
151366
|
import { deflateRawSync as deflateRawSync2 } from "node:zlib";
|
|
@@ -150633,7 +151376,7 @@ function walkSourceTree(dir, file2, skip, enter = () => {
|
|
|
150633
151376
|
continue;
|
|
150634
151377
|
}
|
|
150635
151378
|
if (st2.isDirectory()) {
|
|
150636
|
-
if (isDeniedSourceDir(name, relDir) ||
|
|
151379
|
+
if (isDeniedSourceDir(name, relDir) || existsSync43(join38(dir, rel, PACKAGE_DIR_MARKER))) skip(rel);
|
|
150637
151380
|
else walk2(rel);
|
|
150638
151381
|
continue;
|
|
150639
151382
|
}
|
|
@@ -150801,7 +151544,7 @@ function writeAppSource(entries, destDir) {
|
|
|
150801
151544
|
return written;
|
|
150802
151545
|
}
|
|
150803
151546
|
function staleSourcePaths(entries, destDir) {
|
|
150804
|
-
if (!
|
|
151547
|
+
if (!existsSync43(destDir)) return [];
|
|
150805
151548
|
const archived = new Set(entries.map((e2) => e2.path));
|
|
150806
151549
|
const stale = [];
|
|
150807
151550
|
walkSourceTree(destDir, (archivePath) => {
|
|
@@ -150857,7 +151600,7 @@ function removeStaleSource(entries, destDir) {
|
|
|
150857
151600
|
const segments = entry.path.split("/");
|
|
150858
151601
|
for (let i2 = 1; i2 < segments.length; i2++) needed.add(segments.slice(0, i2).join("/"));
|
|
150859
151602
|
}
|
|
150860
|
-
if (
|
|
151603
|
+
if (existsSync43(root)) pruneEmptyDirs(root, "", needed, removed);
|
|
150861
151604
|
return removed.sort();
|
|
150862
151605
|
}
|
|
150863
151606
|
function pruneEmptyDirs(root, rel, needed, removed) {
|
|
@@ -150946,7 +151689,7 @@ __export(run_watch_exports, {
|
|
|
150946
151689
|
watchedContentDir: () => watchedContentDir,
|
|
150947
151690
|
writeRunRecord: () => writeRunRecord
|
|
150948
151691
|
});
|
|
150949
|
-
import { closeSync as closeSync4, constants as constants3, existsSync as
|
|
151692
|
+
import { closeSync as closeSync4, constants as constants3, existsSync as existsSync44, fstatSync, lstatSync as lstatSync14, statSync as statSync14, readdirSync as readdirSync25, mkdirSync as mkdirSync24, openSync as openSync4, readFileSync as readFileSync50, realpathSync as realpathSync8, renameSync as renameSync10, rmSync as rmSync14, writeFileSync as writeFileSync19, watch as fsWatch } from "node:fs";
|
|
150950
151693
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
150951
151694
|
import { extname as extname4, join as join39, relative as relative8, resolve as resolve41, sep as sep14 } from "node:path";
|
|
150952
151695
|
function diffReleases(prev, next) {
|
|
@@ -151014,7 +151757,7 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
151014
151757
|
}, debounceMs);
|
|
151015
151758
|
};
|
|
151016
151759
|
let watcher2, polling;
|
|
151017
|
-
const
|
|
151760
|
+
const snapshot3 = () => {
|
|
151018
151761
|
const files = /* @__PURE__ */ new Map();
|
|
151019
151762
|
const visit = (directory, prefix = "") => {
|
|
151020
151763
|
let entries;
|
|
@@ -151037,12 +151780,12 @@ function watchContent(dir, onChange, opts = {}) {
|
|
|
151037
151780
|
visit(dir);
|
|
151038
151781
|
return files;
|
|
151039
151782
|
};
|
|
151040
|
-
let before =
|
|
151783
|
+
let before = snapshot3();
|
|
151041
151784
|
const fallback = () => {
|
|
151042
151785
|
if (polling) return;
|
|
151043
151786
|
watcher2?.close();
|
|
151044
151787
|
polling = setInterval(() => {
|
|
151045
|
-
const after =
|
|
151788
|
+
const after = snapshot3();
|
|
151046
151789
|
for (const path2 of /* @__PURE__ */ new Set([...before.keys(), ...after.keys()])) if (before.get(path2) !== after.get(path2)) changed("change", path2);
|
|
151047
151790
|
before = after;
|
|
151048
151791
|
}, opts.pollMs ?? 500);
|
|
@@ -151065,7 +151808,7 @@ function watchedContentDir(source) {
|
|
|
151065
151808
|
if (!source || /^https?:\/\//i.test(source)) return null;
|
|
151066
151809
|
const dir = resolve41(source);
|
|
151067
151810
|
try {
|
|
151068
|
-
return statSync14(dir).isDirectory() &&
|
|
151811
|
+
return statSync14(dir).isDirectory() && existsSync44(join39(dir, "himalaya.content.json")) ? dir : null;
|
|
151069
151812
|
} catch {
|
|
151070
151813
|
return null;
|
|
151071
151814
|
}
|
|
@@ -151721,7 +152464,7 @@ __export(milestones_exports, {
|
|
|
151721
152464
|
});
|
|
151722
152465
|
import { createHash as createHash28, randomUUID as randomUUID8 } from "node:crypto";
|
|
151723
152466
|
import { spawn as spawn4 } from "node:child_process";
|
|
151724
|
-
import { closeSync as closeSync5, existsSync as
|
|
152467
|
+
import { closeSync as closeSync5, existsSync as existsSync45, lstatSync as lstatSync17, readFileSync as readFileSync54, statSync as statSync15 } from "node:fs";
|
|
151725
152468
|
import { createServer as createServer3 } from "node:net";
|
|
151726
152469
|
import { basename as basename14, dirname as dirname28, isAbsolute as isAbsolute4, join as join43, relative as relative9, resolve as resolve42, sep as sep15 } from "node:path";
|
|
151727
152470
|
function homeShotPath(dir, home) {
|
|
@@ -151834,7 +152577,7 @@ function autoPictureGate(dir) {
|
|
|
151834
152577
|
}
|
|
151835
152578
|
async function homePictureAtValidate(dir, opts) {
|
|
151836
152579
|
if (!opts.ok) return { skipped: "validate found errors, so the picture was left as it is" };
|
|
151837
|
-
if (!
|
|
152580
|
+
if (!existsSync45(join43(dir, "himalaya.content.json"))) return { skipped: "not a content package" };
|
|
151838
152581
|
const env = opts.env ?? process.env;
|
|
151839
152582
|
if (ciSet(env)) return { skipped: "the CI environment variable is set" };
|
|
151840
152583
|
if (env.NODE_TEST_CONTEXT) return { skipped: "running under `node --test`" };
|
|
@@ -151904,7 +152647,7 @@ function stillBuilding(dir, image, now) {
|
|
|
151904
152647
|
}
|
|
151905
152648
|
}
|
|
151906
152649
|
function firstLookBeforeOwnPostcard(dir, image, now) {
|
|
151907
|
-
if (!image || !
|
|
152650
|
+
if (!image || !existsSync45(image) || initDivergence(dir).state !== "diverged") return void 0;
|
|
151908
152651
|
return journal(dir, "first-look", withHomeCaveat(yourFirstLookMessage(dir), homeCaveat(dir, image)), { image, ...now ? { now } : {} });
|
|
151909
152652
|
}
|
|
151910
152653
|
function afterRenderPng(dir, input) {
|
|
@@ -151969,13 +152712,13 @@ function testChangeNote(headline2, change) {
|
|
|
151969
152712
|
}
|
|
151970
152713
|
function afterTestRun(dir, input) {
|
|
151971
152714
|
const firstLook = firstLookBeforeOwnPostcard(dir, input.homeShot, input.now);
|
|
151972
|
-
const shot = input.homeShot &&
|
|
152715
|
+
const shot = input.homeShot && existsSync45(input.homeShot) ? input.homeShot : void 0;
|
|
151973
152716
|
const caveat = shot ? homeCaveat(dir, shot) : void 0;
|
|
151974
152717
|
const counts = testPostcardMessage(input);
|
|
151975
152718
|
const headline2 = caveat ? `${counts} But ${caveat}.` : counts;
|
|
151976
152719
|
const postcard = journal(dir, "test", headline2, {
|
|
151977
152720
|
ref: input.runId,
|
|
151978
|
-
...input.homeShot &&
|
|
152721
|
+
...input.homeShot && existsSync45(input.homeShot) ? { image: input.homeShot } : {},
|
|
151979
152722
|
...input.now ? { now: input.now } : {},
|
|
151980
152723
|
unlessUnchanged: true,
|
|
151981
152724
|
changeNote: (change) => testChangeNote(headline2, change)
|
|
@@ -152018,7 +152761,7 @@ function draftPictureGap(input) {
|
|
|
152018
152761
|
if (!input.home) return { reason: "the app's dev/index.ts names no literal homeScreenId, so there is no home screen to picture" };
|
|
152019
152762
|
if (!input.homeShot) return { reason: "the homeScreenId does not name a file under .himi/shots" };
|
|
152020
152763
|
const render = `himi render ${shellQuote(input.home)} --png${contentArg(input.content)}`;
|
|
152021
|
-
if (!
|
|
152764
|
+
if (!existsSync45(input.homeShot)) return { reason: "there is no home shot yet", render };
|
|
152022
152765
|
if (input.sourceChangedAtMs === void 0) return { reason: "the source's last change could not be read, so the home shot cannot be shown to be current", render };
|
|
152023
152766
|
if (!shotIsCurrent(input.homeShot, input.sourceChangedAtMs)) return { reason: "the home shot is older than the last source edit, so it is not a picture of this draft", render };
|
|
152024
152767
|
return null;
|
|
@@ -152096,7 +152839,7 @@ function draftChangeNote(dir, input) {
|
|
|
152096
152839
|
if (!previous) return void 0;
|
|
152097
152840
|
const shaOf = (i2) => i2 && typeof i2 === "object" && typeof i2.sha256 === "string" ? i2.sha256 : void 0;
|
|
152098
152841
|
const had = Array.isArray(previous.images) ? previous.images.map(shaOf).find(Boolean) : void 0;
|
|
152099
|
-
const has = input.picture &&
|
|
152842
|
+
const has = input.picture && existsSync45(input.picture) ? sha256Of2(input.picture) : void 0;
|
|
152100
152843
|
if (had && has) parts.push(had === has ? "the home screen looks the same" : "the home screen changed");
|
|
152101
152844
|
else if (has) parts.push("a home picture this time");
|
|
152102
152845
|
else return void 0;
|
|
@@ -152162,7 +152905,7 @@ function homeShotForPostcard(dir, opts = {}) {
|
|
|
152162
152905
|
const shot = homeShotPath(dir, home);
|
|
152163
152906
|
if (!shot) return { skipped: "the homeScreenId does not name a file under .himi/shots" };
|
|
152164
152907
|
const render = `\`himi render ${shellQuote(home)} --png\``;
|
|
152165
|
-
if (!
|
|
152908
|
+
if (!existsSync45(shot)) return { skipped: `no home shot yet \u2014 ${render} makes one, and the next postcard carries it` };
|
|
152166
152909
|
let changed;
|
|
152167
152910
|
try {
|
|
152168
152911
|
changed = newestSourceChangeMs(dir);
|
|
@@ -152242,7 +152985,7 @@ function liveWatchRunning(dir, isAlive = pidAlive, now) {
|
|
|
152242
152985
|
}
|
|
152243
152986
|
function watchReminder(dir, opts = {}) {
|
|
152244
152987
|
try {
|
|
152245
|
-
if (!
|
|
152988
|
+
if (!existsSync45(join43(dir, "himalaya.content.json"))) return void 0;
|
|
152246
152989
|
const nowDate = opts.now ?? /* @__PURE__ */ new Date();
|
|
152247
152990
|
const live3 = liveWatch(dir, opts.isAlive, nowDate);
|
|
152248
152991
|
const now = nowDate.getTime();
|
|
@@ -152917,12 +153660,12 @@ var init_brand_color_math = __esm({
|
|
|
152917
153660
|
});
|
|
152918
153661
|
|
|
152919
153662
|
// src/token-lint.ts
|
|
152920
|
-
import { existsSync as
|
|
153663
|
+
import { existsSync as existsSync48, readFileSync as readFileSync56 } from "node:fs";
|
|
152921
153664
|
import { join as join46 } from "node:path";
|
|
152922
153665
|
function configuredTokensPath(dir) {
|
|
152923
153666
|
for (const name of ["config.ts", "config.js", "himi.config.ts"]) {
|
|
152924
153667
|
const f2 = join46(dir, name);
|
|
152925
|
-
if (!
|
|
153668
|
+
if (!existsSync48(f2)) continue;
|
|
152926
153669
|
const src = readFileSync56(f2, "utf8");
|
|
152927
153670
|
const m2 = /designTokensPath\s*:\s*["'`]([^"'`]+)["'`]/.exec(src);
|
|
152928
153671
|
if (m2) return { path: m2[1].replace(/^\.\//, "") };
|
|
@@ -153000,7 +153743,7 @@ function tokenColorIssues(dir, tokensPathOverride) {
|
|
|
153000
153743
|
}
|
|
153001
153744
|
const tokensPath = configured.path ?? "tokens.json";
|
|
153002
153745
|
const p2 = join46(dir, tokensPath);
|
|
153003
|
-
if (!
|
|
153746
|
+
if (!existsSync48(p2)) {
|
|
153004
153747
|
if (tokensPath !== "tokens.json") {
|
|
153005
153748
|
warn3(`config designTokensPath points at ${tokensPath}, which does not exist -- colour tokens were not checked`);
|
|
153006
153749
|
}
|
|
@@ -153322,7 +154065,7 @@ __export(fonts_exports, {
|
|
|
153322
154065
|
listReport: () => listReport,
|
|
153323
154066
|
resolveFamilyName: () => resolveFamilyName
|
|
153324
154067
|
});
|
|
153325
|
-
import { existsSync as
|
|
154068
|
+
import { existsSync as existsSync49, readFileSync as readFileSync57 } from "node:fs";
|
|
153326
154069
|
import { join as join47 } from "node:path";
|
|
153327
154070
|
function readJson6(path2, fallback) {
|
|
153328
154071
|
try {
|
|
@@ -153356,7 +154099,7 @@ function listReport(opts = {}) {
|
|
|
153356
154099
|
}
|
|
153357
154100
|
async function fontFindings(appDir3, opts = {}) {
|
|
153358
154101
|
const tokensPath = join47(appDir3, configuredTokensPath(appDir3).path ?? "tokens.json");
|
|
153359
|
-
if (!
|
|
154102
|
+
if (!existsSync49(tokensPath)) return null;
|
|
153360
154103
|
const catalog4 = loadCatalog2();
|
|
153361
154104
|
const tokens2 = readJson6(tokensPath, {});
|
|
153362
154105
|
const policy = readJson6(join47(appDir3, "fonts.json"), {});
|
|
@@ -153864,17 +154607,17 @@ __export(template_recommend_exports, {
|
|
|
153864
154607
|
recommendTemplates: () => recommendTemplates,
|
|
153865
154608
|
verticalsFromBook: () => verticalsFromBook
|
|
153866
154609
|
});
|
|
153867
|
-
import { existsSync as
|
|
154610
|
+
import { existsSync as existsSync51, readFileSync as readFileSync60 } from "node:fs";
|
|
153868
154611
|
import { join as join50 } from "node:path";
|
|
153869
154612
|
function verticalsFromBook(path2) {
|
|
153870
|
-
const dir =
|
|
154613
|
+
const dir = existsSync51(join50(path2, "book.json")) || existsSync51(join50(path2, "provisioning.overlay.json")) ? path2 : join50(path2, ".himi", "business-book");
|
|
153871
154614
|
const overlay = join50(dir, "provisioning.overlay.json");
|
|
153872
|
-
if (
|
|
154615
|
+
if (existsSync51(overlay)) {
|
|
153873
154616
|
const v2 = JSON.parse(readFileSync60(overlay, "utf8")).installedVerticals;
|
|
153874
154617
|
if (Array.isArray(v2) && v2.length) return v2.filter((x2) => typeof x2 === "string");
|
|
153875
154618
|
}
|
|
153876
154619
|
const book = join50(dir, "book.json");
|
|
153877
|
-
if (
|
|
154620
|
+
if (existsSync51(book)) {
|
|
153878
154621
|
const probes = JSON.parse(readFileSync60(book, "utf8")).probes;
|
|
153879
154622
|
if (Array.isArray(probes)) return installedFromProbes(probes);
|
|
153880
154623
|
}
|
|
@@ -154489,7 +155232,7 @@ var init_glyphs = __esm({
|
|
|
154489
155232
|
});
|
|
154490
155233
|
|
|
154491
155234
|
// ../app-icons/plan.ts
|
|
154492
|
-
import { existsSync as
|
|
155235
|
+
import { existsSync as existsSync52, readFileSync as readFileSync61, readdirSync as readdirSync27 } from "node:fs";
|
|
154493
155236
|
import { createHash as createHash29 } from "node:crypto";
|
|
154494
155237
|
import { dirname as dirname29, join as join51, resolve as resolve44 } from "node:path";
|
|
154495
155238
|
function stripComments(src) {
|
|
@@ -154625,7 +155368,7 @@ function resolveTokensPath(app, configTs) {
|
|
|
154625
155368
|
}
|
|
154626
155369
|
function resolveToken(app, token, tokensPathOverride) {
|
|
154627
155370
|
const tokensPath = tokensPathOverride ?? join51(appDir(app), "tokens.json");
|
|
154628
|
-
if (!
|
|
155371
|
+
if (!existsSync52(tokensPath)) {
|
|
154629
155372
|
throw new Error(`app-icons: ${app} has no tokens.json at ${tokensPath} (needed to resolve "${token}").`);
|
|
154630
155373
|
}
|
|
154631
155374
|
const tokens2 = JSON.parse(readFileSync61(tokensPath, "utf8"));
|
|
@@ -154670,7 +155413,7 @@ function iconSpec(app, configTs, id, tokensPathOverride) {
|
|
|
154670
155413
|
const tokens2 = tokensPathOverride ?? resolveTokensPath(app, configTs).path;
|
|
154671
155414
|
if (cfg.source) {
|
|
154672
155415
|
const abs = resolve44(appDir(app), cfg.source);
|
|
154673
|
-
if (!
|
|
155416
|
+
if (!existsSync52(abs)) {
|
|
154674
155417
|
throw new Error(`app-icons: ${app} declares icon.source "${cfg.source}" but ${abs} does not exist.`);
|
|
154675
155418
|
}
|
|
154676
155419
|
return {
|
|
@@ -154710,9 +155453,9 @@ function iosAssetCatalog2(app) {
|
|
|
154710
155453
|
return assetCatalogIn(join51(appDir(app), "ios"));
|
|
154711
155454
|
}
|
|
154712
155455
|
function assetCatalogIn(platformDir) {
|
|
154713
|
-
if (!
|
|
155456
|
+
if (!existsSync52(platformDir)) return void 0;
|
|
154714
155457
|
const children = readdirSync27(platformDir).filter((c2) => !c2.startsWith("build")).sort();
|
|
154715
|
-
const catalogs = children.map((c2) => join51(platformDir, c2, "Assets.xcassets")).filter(
|
|
155458
|
+
const catalogs = children.map((c2) => join51(platformDir, c2, "Assets.xcassets")).filter(existsSync52);
|
|
154716
155459
|
if (catalogs.length === 1) return catalogs[0];
|
|
154717
155460
|
if (catalogs.length > 1) return void 0;
|
|
154718
155461
|
const targets = [];
|
|
@@ -154735,14 +155478,14 @@ function androidResDir2(manifestPath) {
|
|
|
154735
155478
|
}
|
|
154736
155479
|
function androidManifestPath(app) {
|
|
154737
155480
|
const androidDir = join51(appDir(app), "android");
|
|
154738
|
-
if (!
|
|
155481
|
+
if (!existsSync52(androidDir)) return void 0;
|
|
154739
155482
|
const preferred = join51(androidDir, `${app}-app`, "src", "main", "AndroidManifest.xml");
|
|
154740
|
-
if (
|
|
154741
|
-
const candidates = readdirSync27(androidDir, { withFileTypes: true }).filter((d2) => d2.isDirectory() && d2.name.endsWith("-app")).map((d2) => join51(androidDir, d2.name, "src", "main", "AndroidManifest.xml")).filter(
|
|
155483
|
+
if (existsSync52(preferred)) return preferred;
|
|
155484
|
+
const candidates = readdirSync27(androidDir, { withFileTypes: true }).filter((d2) => d2.isDirectory() && d2.name.endsWith("-app")).map((d2) => join51(androidDir, d2.name, "src", "main", "AndroidManifest.xml")).filter(existsSync52);
|
|
154742
155485
|
return candidates.length === 1 ? candidates[0] : void 0;
|
|
154743
155486
|
}
|
|
154744
155487
|
function androidOptedIn2(manifestPath) {
|
|
154745
|
-
if (!manifestPath || !
|
|
155488
|
+
if (!manifestPath || !existsSync52(manifestPath)) return false;
|
|
154746
155489
|
return readFileSync61(manifestPath, "utf8").includes("@mipmap/ic_launcher");
|
|
154747
155490
|
}
|
|
154748
155491
|
function templateIconSha256() {
|
|
@@ -154767,7 +155510,7 @@ function generationAllowed(app, configTs, opts = {}) {
|
|
|
154767
155510
|
}
|
|
154768
155511
|
const iosCat = iosAssetCatalog2(app);
|
|
154769
155512
|
const iosIcon = iosCat ? join51(iosCat, "AppIcon.appiconset", "icon_1024.png") : void 0;
|
|
154770
|
-
if (!iosIcon || !
|
|
155513
|
+
if (!iosIcon || !existsSync52(iosIcon)) return { allowed: true, reason: "no icon yet" };
|
|
154771
155514
|
const hash2 = fileSha256(iosIcon);
|
|
154772
155515
|
const placeholders = opts.placeholderHashes ?? placeholderHashes();
|
|
154773
155516
|
if (app === "_template") return { allowed: true, reason: "the template itself" };
|
|
@@ -154791,7 +155534,7 @@ var init_plan2 = __esm({
|
|
|
154791
155534
|
});
|
|
154792
155535
|
|
|
154793
155536
|
// ../native-config/icon.ts
|
|
154794
|
-
import { existsSync as
|
|
155537
|
+
import { existsSync as existsSync53, readFileSync as readFileSync62 } from "node:fs";
|
|
154795
155538
|
import { join as join52 } from "node:path";
|
|
154796
155539
|
function androidAdaptiveIconXml() {
|
|
154797
155540
|
return [
|
|
@@ -154820,7 +155563,7 @@ function androidIconArtifacts(app, configTs) {
|
|
|
154820
155563
|
if (!generationAllowed(app, configTs).allowed) return [];
|
|
154821
155564
|
const res = androidResDir2(manifest2);
|
|
154822
155565
|
const foreground = join52(res, "mipmap-mdpi", "ic_launcher_foreground.png");
|
|
154823
|
-
if (!
|
|
155566
|
+
if (!existsSync53(foreground)) {
|
|
154824
155567
|
throw new Error(
|
|
154825
155568
|
`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.`
|
|
154826
155569
|
);
|
|
@@ -155122,7 +155865,7 @@ var init_localweb = __esm({
|
|
|
155122
155865
|
});
|
|
155123
155866
|
|
|
155124
155867
|
// ../native-config/capability-registrations.ts
|
|
155125
|
-
import { existsSync as
|
|
155868
|
+
import { existsSync as existsSync54, readdirSync as readdirSync28, readFileSync as readFileSync63, statSync as statSync16 } from "node:fs";
|
|
155126
155869
|
import { dirname as dirname30, join as join53, resolve as resolve45 } from "node:path";
|
|
155127
155870
|
import { fileURLToPath as fileURLToPath22 } from "node:url";
|
|
155128
155871
|
function registrarClasses(path2, re2) {
|
|
@@ -155166,7 +155909,7 @@ function renderKotlinRegistrations(ids, appIdExpr = "APP_NAME", classes = androi
|
|
|
155166
155909
|
];
|
|
155167
155910
|
}
|
|
155168
155911
|
function filesWithRegisterMarkers(root, ext) {
|
|
155169
|
-
if (!
|
|
155912
|
+
if (!existsSync54(root)) return [];
|
|
155170
155913
|
const out2 = [];
|
|
155171
155914
|
const stack = [[root, 0, ext === ".kt" ? "project" : "main"]];
|
|
155172
155915
|
while (stack.length) {
|
|
@@ -155358,7 +156101,7 @@ __export(gen_native_config_exports, {
|
|
|
155358
156101
|
xmlAttr: () => xmlAttr,
|
|
155359
156102
|
yamlScalar: () => yamlScalar
|
|
155360
156103
|
});
|
|
155361
|
-
import { existsSync as
|
|
156104
|
+
import { existsSync as existsSync55, mkdirSync as mkdirSync25, readFileSync as readFileSync64, readdirSync as readdirSync29, rmSync as rmSync15, statSync as statSync17, writeFileSync as writeFileSync21 } from "node:fs";
|
|
155362
156105
|
import { dirname as dirname31, join as join54 } from "node:path";
|
|
155363
156106
|
import { fileURLToPath as fileURLToPath23 } from "node:url";
|
|
155364
156107
|
function parseStringArray(configTs, field) {
|
|
@@ -155436,7 +156179,7 @@ function buildSet(capabilities, envelope = []) {
|
|
|
155436
156179
|
}
|
|
155437
156180
|
function loadOverrides(app) {
|
|
155438
156181
|
const p2 = join54(appDir(app), "native-config.overrides.json");
|
|
155439
|
-
if (!
|
|
156182
|
+
if (!existsSync55(p2)) return {};
|
|
155440
156183
|
return JSON.parse(readFileSync64(p2, "utf8"));
|
|
155441
156184
|
}
|
|
155442
156185
|
function needsQuote(s2) {
|
|
@@ -155663,7 +156406,7 @@ function genCoreModuleInstallers(check) {
|
|
|
155663
156406
|
}
|
|
155664
156407
|
function swiftFilesWithModuleMarkers(app) {
|
|
155665
156408
|
const root = join54(appDir(app), "ios");
|
|
155666
|
-
if (!
|
|
156409
|
+
if (!existsSync55(root)) return [];
|
|
155667
156410
|
const out2 = [];
|
|
155668
156411
|
const stack = [root];
|
|
155669
156412
|
while (stack.length) {
|
|
@@ -155685,7 +156428,7 @@ function kotlinFilesWithModuleInstall(app) {
|
|
|
155685
156428
|
return kotlinBootSourcesUnder(join54(appDir(app), "android"));
|
|
155686
156429
|
}
|
|
155687
156430
|
function kotlinBootSourcesUnder(root) {
|
|
155688
|
-
if (!
|
|
156431
|
+
if (!existsSync55(root)) return [];
|
|
155689
156432
|
const out2 = [];
|
|
155690
156433
|
const stack = [[root, 0, "project"]];
|
|
155691
156434
|
while (stack.length) {
|
|
@@ -155756,7 +156499,7 @@ function endText(kind, label3, indent) {
|
|
|
155756
156499
|
}
|
|
155757
156500
|
function hostAppliesDeferredWidgetActions(app) {
|
|
155758
156501
|
const root = join54(appDir(app), "ios");
|
|
155759
|
-
if (!
|
|
156502
|
+
if (!existsSync55(root)) return false;
|
|
155760
156503
|
const stack = [root];
|
|
155761
156504
|
while (stack.length) {
|
|
155762
156505
|
const dir = stack.pop();
|
|
@@ -155814,15 +156557,15 @@ function androidAppGradle(app) {
|
|
|
155814
156557
|
function androidManifestPath2(app) {
|
|
155815
156558
|
const androidDir = join54(appDir(app), "android");
|
|
155816
156559
|
const preferred = join54(androidDir, `${app}-app`, "src", "main", "AndroidManifest.xml");
|
|
155817
|
-
if (
|
|
155818
|
-
const candidates =
|
|
156560
|
+
if (existsSync55(preferred)) return preferred;
|
|
156561
|
+
const candidates = existsSync55(androidDir) ? readdirSync29(androidDir, { withFileTypes: true }).filter((d2) => d2.isDirectory() && d2.name.endsWith("-app")).map((d2) => join54(androidDir, d2.name, "src", "main", "AndroidManifest.xml")).filter(existsSync55) : [];
|
|
155819
156562
|
return candidates.length === 1 ? candidates[0] : preferred;
|
|
155820
156563
|
}
|
|
155821
156564
|
function automotiveAppDescPath(app) {
|
|
155822
156565
|
return join54(dirname31(androidManifestPath2(app)), "res", "xml", "automotive_app_desc.xml");
|
|
155823
156566
|
}
|
|
155824
156567
|
function applyToFile(path2, kind, label3, render, check) {
|
|
155825
|
-
if (!
|
|
156568
|
+
if (!existsSync55(path2)) return { path: path2, outcome: "skipped" };
|
|
155826
156569
|
const before = readFileSync64(path2, "utf8");
|
|
155827
156570
|
assertSingleMarkerPair(before, kind, label3, path2);
|
|
155828
156571
|
if (!hasMarkers(before, kind, label3)) return { path: path2, outcome: "skipped" };
|
|
@@ -155834,7 +156577,7 @@ function applyToFile(path2, kind, label3, render, check) {
|
|
|
155834
156577
|
}
|
|
155835
156578
|
function assertModuleFlagsMarkers(paths2) {
|
|
155836
156579
|
for (const path2 of paths2) {
|
|
155837
|
-
if (!
|
|
156580
|
+
if (!existsSync55(path2)) continue;
|
|
155838
156581
|
const text11 = readFileSync64(path2, "utf8");
|
|
155839
156582
|
if (hasMarkers(text11, "yaml", LABEL_MODULES_IOS_LINK) && !hasMarkers(text11, "yaml", LABEL_MODULES_IOS_FLAGS)) {
|
|
155840
156583
|
throw new Error(`${path2} links modules (${LABEL_MODULES_IOS_LINK}) but has no ${LABEL_MODULES_IOS_FLAGS} block under its project-level settings:, so no module would install. Add the markers (see apps/_template).`);
|
|
@@ -155846,7 +156589,7 @@ function applyModuleFlags(path2, products, check) {
|
|
|
155846
156589
|
return applyToFile(path2, "yaml", LABEL_MODULES_IOS_FLAGS, (i2) => renderModulesIosFlags(products, i2), check);
|
|
155847
156590
|
}
|
|
155848
156591
|
function applyWholeFile(path2, content, check) {
|
|
155849
|
-
const current =
|
|
156592
|
+
const current = existsSync55(path2) ? readFileSync64(path2, "utf8") : null;
|
|
155850
156593
|
if (current === content) return { path: path2, outcome: "unchanged" };
|
|
155851
156594
|
if (check) return { path: path2, outcome: "drift" };
|
|
155852
156595
|
mkdirSync25(dirname31(path2), { recursive: true });
|
|
@@ -155854,7 +156597,7 @@ function applyWholeFile(path2, content, check) {
|
|
|
155854
156597
|
return { path: path2, outcome: "written" };
|
|
155855
156598
|
}
|
|
155856
156599
|
function removeWholeFile(path2, check) {
|
|
155857
|
-
if (!
|
|
156600
|
+
if (!existsSync55(path2)) return { path: path2, outcome: "skipped" };
|
|
155858
156601
|
if (check) return { path: path2, outcome: "drift" };
|
|
155859
156602
|
rmSync15(path2);
|
|
155860
156603
|
return { path: path2, outcome: "removed" };
|
|
@@ -155893,7 +156636,7 @@ function genCapabilityRegistrations(root, declared, check) {
|
|
|
155893
156636
|
}
|
|
155894
156637
|
function buildSetOfAppDir(root) {
|
|
155895
156638
|
const configPath = join54(root, "config.ts");
|
|
155896
|
-
const configTs =
|
|
156639
|
+
const configTs = existsSync55(configPath) ? readFileSync64(configPath, "utf8") : "";
|
|
155897
156640
|
return buildSet(parseStringArray(configTs, "capabilities"), parseStringArray(configTs, "capabilityEnvelope"));
|
|
155898
156641
|
}
|
|
155899
156642
|
function genNativeConfig(app, opts = {}) {
|
|
@@ -155902,7 +156645,7 @@ function genNativeConfig(app, opts = {}) {
|
|
|
155902
156645
|
assertSingleModuleInstall(app, kotlinFilesWithModuleInstall(app));
|
|
155903
156646
|
assertModuleFlagsMarkers([iosProjectYml(app), macosProjectYml(app)]);
|
|
155904
156647
|
const configPath = appConfigTs(app);
|
|
155905
|
-
const configTs =
|
|
156648
|
+
const configTs = existsSync55(configPath) ? readFileSync64(configPath, "utf8") : "";
|
|
155906
156649
|
const capabilities = parseStringArray(configTs, "capabilities");
|
|
155907
156650
|
const envelope = parseStringArray(configTs, "capabilityEnvelope");
|
|
155908
156651
|
const ownIds = buildSet(capabilities, envelope);
|
|
@@ -155911,7 +156654,7 @@ function genNativeConfig(app, opts = {}) {
|
|
|
155911
156654
|
const ids = dist ? dist.build : ownIds;
|
|
155912
156655
|
const healthLinked = ids.includes("health");
|
|
155913
156656
|
const distJsonPath = join54(appDir(app), "distribution.json");
|
|
155914
|
-
const distJsonText =
|
|
156657
|
+
const distJsonText = existsSync55(distJsonPath) ? readFileSync64(distJsonPath, "utf8") : void 0;
|
|
155915
156658
|
const optIns = distributionOptIns(distJsonText);
|
|
155916
156659
|
const binaryCore = isBinaryCore(configTs, distJsonText);
|
|
155917
156660
|
const modules = modulesFor(ids, optIns);
|
|
@@ -155927,7 +156670,7 @@ function genNativeConfig(app, opts = {}) {
|
|
|
155927
156670
|
if (!v2) throw new Error(`${app}: a binary-core app that links native modules (${modules.gradle.join(", ")}) needs distribution.json coreVersion`);
|
|
155928
156671
|
return v2;
|
|
155929
156672
|
},
|
|
155930
|
-
corePackage: () =>
|
|
156673
|
+
corePackage: () => existsSync55(iosProjectYml(app)) ? binaryCorePackage(readFileSync64(iosProjectYml(app), "utf8")) : void 0
|
|
155931
156674
|
} : void 0
|
|
155932
156675
|
);
|
|
155933
156676
|
if (binaryCore) {
|
|
@@ -155946,9 +156689,9 @@ function genNativeConfig(app, opts = {}) {
|
|
|
155946
156689
|
const iosBundleId = watchConfig.iosBundleId ?? parseIosBundleId(configTs);
|
|
155947
156690
|
const watch2 = watchInfoPlan(watchConfig, iosBundleId);
|
|
155948
156691
|
const watchYml = watchosProjectYml(app);
|
|
155949
|
-
const watchYmlText =
|
|
156692
|
+
const watchYmlText = existsSync55(watchYml) ? readFileSync64(watchYml, "utf8") : "";
|
|
155950
156693
|
const watchSettings = watchSettingsPlan(watchMode(watchConfig.mode), iosBundleId, watchTargetBundleId(watchYmlText));
|
|
155951
|
-
const watchName =
|
|
156694
|
+
const watchName = existsSync55(watchYml) ? watchProjectName(readFileSync64(watchYml, "utf8")) : void 0;
|
|
155952
156695
|
const watchEmbedFor = (lines) => (indent) => {
|
|
155953
156696
|
const mode = watchMode(watchConfig.mode);
|
|
155954
156697
|
if (mode === "standalone") return [];
|
|
@@ -155962,7 +156705,7 @@ function genNativeConfig(app, opts = {}) {
|
|
|
155962
156705
|
const carBlock = applyToFile(carManifestPath, "xml", LABEL_CAR, (i2) => renderCarManifestXml(carCategory, i2), check);
|
|
155963
156706
|
assertCarBlockLanded(app, carCategory, carManifestPath, carBlock.outcome, LABEL_CAR);
|
|
155964
156707
|
const iosYml = iosProjectYml(app);
|
|
155965
|
-
const project =
|
|
156708
|
+
const project = existsSync55(iosYml) ? readFileSync64(iosYml, "utf8") : "";
|
|
155966
156709
|
const targetManaged = hasMarkers(project, "yaml", LABEL_LIVE_TARGET);
|
|
155967
156710
|
const embedManaged = hasMarkers(project, "yaml", LABEL_LIVE_EMBED);
|
|
155968
156711
|
if (targetManaged !== embedManaged) throw new Error(`${app}: Live Activity target and embedding markers must be installed together`);
|
|
@@ -156046,7 +156789,7 @@ function genNativeConfig(app, opts = {}) {
|
|
|
156046
156789
|
];
|
|
156047
156790
|
if (dist) {
|
|
156048
156791
|
const manifestPath = androidManifestPath2(app);
|
|
156049
|
-
const marked = (path2, kind, label3) => !
|
|
156792
|
+
const marked = (path2, kind, label3) => !existsSync55(path2) || hasMarkers(readFileSync64(path2, "utf8"), kind, label3);
|
|
156050
156793
|
if (!marked(iosYml, "yaml", LABEL_IOS_INFO)) throw new Error(`${app}: dist capabilities need the ${LABEL_IOS_INFO} markers in ${iosYml}`);
|
|
156051
156794
|
if (!marked(manifestPath, "xml", LABEL_ANDROID_SERVICES)) {
|
|
156052
156795
|
throw new Error(`${app}: dist capabilities need the ${LABEL_ANDROID_SERVICES} markers inside <application> in ${manifestPath}`);
|
|
@@ -156057,7 +156800,7 @@ function genNativeConfig(app, opts = {}) {
|
|
|
156057
156800
|
const addsGradle = added.gradle.some((p2) => !ownModules.gradle.includes(p2));
|
|
156058
156801
|
if (addsSpm || addsGradle) {
|
|
156059
156802
|
const requireMarkers = (path2, kind, label3) => {
|
|
156060
|
-
if (!
|
|
156803
|
+
if (!existsSync55(path2) || !hasMarkers(readFileSync64(path2, "utf8"), kind, label3)) {
|
|
156061
156804
|
throw new Error(`${app}: dist added ${dist.added.join(", ")} but ${path2} has no ${label3} markers \u2014 the module would stay unlinked and every verb would answer module_not_linked`);
|
|
156062
156805
|
}
|
|
156063
156806
|
};
|
|
@@ -156082,9 +156825,9 @@ function genNativeConfig(app, opts = {}) {
|
|
|
156082
156825
|
files.push(...genCapabilityRegistrations(appDir(app), ids, check));
|
|
156083
156826
|
const rce = declaresRichContentEditor(configTs);
|
|
156084
156827
|
for (const yml of [iosYml, macosProjectYml(app)]) {
|
|
156085
|
-
const text11 =
|
|
156828
|
+
const text11 = existsSync55(yml) ? readFileSync64(yml, "utf8") : "";
|
|
156086
156829
|
const r3 = applyToFile(yml, "yaml", LABEL_LOCALWEB, renderLocalWebYaml(resourcesDirOf(text11), rce), check);
|
|
156087
|
-
if (
|
|
156830
|
+
if (existsSync55(yml)) assertLocalWebBlockLanded(app, rce, yml, r3.outcome);
|
|
156088
156831
|
files.push(r3);
|
|
156089
156832
|
}
|
|
156090
156833
|
if (targetManaged) {
|
|
@@ -156096,7 +156839,7 @@ function genNativeConfig(app, opts = {}) {
|
|
|
156096
156839
|
const entitlements = join54(dirname31(iosYml), LIVE_ENTITLEMENTS_PATH);
|
|
156097
156840
|
files.push(plan.entitlements ? applyWholeFile(entitlements, plan.entitlements, check) : removeWholeFile(entitlements, check));
|
|
156098
156841
|
}
|
|
156099
|
-
const iosSplashManaged =
|
|
156842
|
+
const iosSplashManaged = existsSync55(iosYml) && hasMarkers(readFileSync64(iosYml, "utf8"), "yaml", LABEL_IOS_SPLASH);
|
|
156100
156843
|
const manifest2 = androidManifestPath2(app);
|
|
156101
156844
|
const splash = splashPlan(app, configTs, manifest2, iosSplashManaged);
|
|
156102
156845
|
for (const artifact of splash.artifacts) files.push(applyWholeFile(artifact.path, artifact.content, check));
|
|
@@ -156189,7 +156932,7 @@ __export(capabilities_exports, {
|
|
|
156189
156932
|
shellSupport: () => shellSupport,
|
|
156190
156933
|
writeLastDist: () => writeLastDist
|
|
156191
156934
|
});
|
|
156192
|
-
import { existsSync as
|
|
156935
|
+
import { existsSync as existsSync56, lstatSync as lstatSync18, readFileSync as readFileSync65 } from "node:fs";
|
|
156193
156936
|
import { join as join55 } from "node:path";
|
|
156194
156937
|
function declareHintFor(id) {
|
|
156195
156938
|
return catalogKey(id) === "app_services" ? "each calling screen's `logicBundle.declaredCapabilities` (the runtime gate) \u2014 an app need not list app_services in config.ts `capabilities`, which only a shell that hosts app services must (an HHP app declares it there, since HHP copies that list onto every screen)" : DECLARE_HINT;
|
|
@@ -156271,7 +157014,7 @@ function allCapabilities(sdkRef = []) {
|
|
|
156271
157014
|
function contentShell(dir, flag) {
|
|
156272
157015
|
if (flag) return flag;
|
|
156273
157016
|
const path2 = join55(dir, "himalaya.content.json");
|
|
156274
|
-
if (!
|
|
157017
|
+
if (!existsSync56(path2)) return null;
|
|
156275
157018
|
try {
|
|
156276
157019
|
const shell = JSON.parse(readFileSync65(path2, "utf8")).shell;
|
|
156277
157020
|
return typeof shell === "string" && shell ? shell : null;
|
|
@@ -156569,7 +157312,7 @@ function envelopeSubsetIssues(app, envelope) {
|
|
|
156569
157312
|
function capabilityConfigFindings(sourceDir, builtDir) {
|
|
156570
157313
|
const out2 = [];
|
|
156571
157314
|
const configPath = join55(sourceDir, "config.ts");
|
|
156572
|
-
if (
|
|
157315
|
+
if (existsSync56(configPath)) {
|
|
156573
157316
|
const configSrc = readFileSync65(configPath, "utf8");
|
|
156574
157317
|
const declared = parseStringArray(configSrc, "capabilities");
|
|
156575
157318
|
for (const id of new Set(declared)) {
|
|
@@ -156738,6 +157481,9 @@ async function navIssues(dir, strict) {
|
|
|
156738
157481
|
pushScreenMapIssues(cfg.push, provisioning, warn3);
|
|
156739
157482
|
pushAuthIssues(cfg.push, cfg.auth, provisioning, warn3);
|
|
156740
157483
|
pushFamilyIssues(cfg.push, warn3);
|
|
157484
|
+
const captcha = provisioning.siteId && !placeholderLogin(cfg.auth) ? captchaAuthFinding(cfg.auth, provisioning.siteId) : void 0;
|
|
157485
|
+
if (captcha && captcha.code !== "captcha_auth_site_case" && !issues.some((i2) => i2.ruleCode === "push-auth-site"))
|
|
157486
|
+
push("warning", "auth-captcha-site", captcha.message);
|
|
156741
157487
|
if (nav === void 0 || nav === null) return issues;
|
|
156742
157488
|
if (!isPlainObject2(nav)) {
|
|
156743
157489
|
error("nav-not-an-object", `navigation must be an object (got ${Array.isArray(nav) ? "array" : typeof nav}).`);
|
|
@@ -156875,6 +157621,9 @@ function pushAuthIssues(push, auth, provisioning, warn3) {
|
|
|
156875
157621
|
`push.registrar is "wix-ping", which registers a signed-in member's device with Wix Ping, but ${problem}. Use auth: WixConsumerAuthProvider({ siteId: "${provisioning.siteId ?? "<metaSiteId>"}", \u2026 }).`
|
|
156876
157622
|
);
|
|
156877
157623
|
}
|
|
157624
|
+
function placeholderLogin(auth) {
|
|
157625
|
+
return isPlainObject2(auth) && isPlainObject2(auth.config) && auth.config.clientId === PLACEHOLDER_CLIENT_ID;
|
|
157626
|
+
}
|
|
156878
157627
|
function pushFamilyIssues(push, warn3) {
|
|
156879
157628
|
if (!isPlainObject2(push) || push.registrar !== "wix-ping" || typeof push.pingAppName !== "string") return;
|
|
156880
157629
|
const replacement = replacementPingFamily(push.pingAppName);
|
|
@@ -156937,6 +157686,8 @@ var init_nav_lint = __esm({
|
|
|
156937
157686
|
init_nav_slots();
|
|
156938
157687
|
init_home_screen_id();
|
|
156939
157688
|
init_wix_push_links();
|
|
157689
|
+
init_captcha_auth();
|
|
157690
|
+
init_wix_placeholders();
|
|
156940
157691
|
NAVIGATION_KEYS = /* @__PURE__ */ new Set([
|
|
156941
157692
|
"tabBar",
|
|
156942
157693
|
"drawer",
|
|
@@ -157017,7 +157768,7 @@ __export(base44_types_exports, {
|
|
|
157017
157768
|
renderBase44Types: () => renderBase44Types,
|
|
157018
157769
|
writeBase44Types: () => writeBase44Types
|
|
157019
157770
|
});
|
|
157020
|
-
import { existsSync as
|
|
157771
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync26, readFileSync as readFileSync66, writeFileSync as writeFileSync22 } from "node:fs";
|
|
157021
157772
|
import { dirname as dirname32, join as join56 } from "node:path";
|
|
157022
157773
|
function logicalName(spec) {
|
|
157023
157774
|
return (isAdoptedEntity(spec) ? spec.base44Name : spec.name) ?? "";
|
|
@@ -157097,7 +157848,7 @@ async function writeBase44Types(dir, app) {
|
|
|
157097
157848
|
if (!list2?.length) throw new Base44TypesError("no_base44_entities", "config.ts declares no base44.entities \u2014 nothing to type. Declare them (or run `himi base44 adopt`) first.");
|
|
157098
157849
|
const text11 = renderBase44Types(list2, app);
|
|
157099
157850
|
const path2 = join56(dir, BASE44_TYPES_PATH);
|
|
157100
|
-
const changed = !
|
|
157851
|
+
const changed = !existsSync57(path2) || readFileSync66(path2, "utf8") !== text11;
|
|
157101
157852
|
if (changed) {
|
|
157102
157853
|
mkdirSync26(dirname32(path2), { recursive: true });
|
|
157103
157854
|
writeFileSync22(path2, text11);
|
|
@@ -157106,7 +157857,7 @@ async function writeBase44Types(dir, app) {
|
|
|
157106
157857
|
}
|
|
157107
157858
|
async function base44TypesIssues(dir, app, strict) {
|
|
157108
157859
|
const path2 = join56(dir, BASE44_TYPES_PATH);
|
|
157109
|
-
if (!
|
|
157860
|
+
if (!existsSync57(path2)) return [];
|
|
157110
157861
|
let list2;
|
|
157111
157862
|
try {
|
|
157112
157863
|
list2 = await declaredEntities(dir);
|
|
@@ -157249,13 +158000,13 @@ __export(eject_exports, {
|
|
|
157249
158000
|
EJECTABLE: () => EJECTABLE,
|
|
157250
158001
|
ejectModule: () => ejectModule
|
|
157251
158002
|
});
|
|
157252
|
-
import { existsSync as
|
|
158003
|
+
import { existsSync as existsSync59, mkdirSync as mkdirSync27, readFileSync as readFileSync68, writeFileSync as writeFileSync23 } from "node:fs";
|
|
157253
158004
|
import { dirname as dirname33, join as join58, relative as relative10, resolve as resolve47, sep as sep16 } from "node:path";
|
|
157254
158005
|
function locate(repoRootOrCwd, mod) {
|
|
157255
158006
|
const inRepo = resolve47(repoRootOrCwd, `stdlib/flows/${mod}/src/index.ts`);
|
|
157256
|
-
if (
|
|
158007
|
+
if (existsSync59(inRepo)) return { path: inRepo, form: "source" };
|
|
157257
158008
|
const dist = resolve47(repoRootOrCwd, `node_modules/@wix/himalaya/dist/${mod}.mjs`);
|
|
157258
|
-
if (
|
|
158009
|
+
if (existsSync59(dist)) return { path: dist, form: "bundle" };
|
|
157259
158010
|
return null;
|
|
157260
158011
|
}
|
|
157261
158012
|
function specifiersFor(mod) {
|
|
@@ -157300,7 +158051,7 @@ function ejectModule(opts) {
|
|
|
157300
158051
|
writeFileSync23(target, banner + normalized);
|
|
157301
158052
|
const rewired = [];
|
|
157302
158053
|
for (const f2 of files) {
|
|
157303
|
-
if (!
|
|
158054
|
+
if (!existsSync59(f2)) continue;
|
|
157304
158055
|
const before = readFileSync68(f2, "utf8");
|
|
157305
158056
|
let after = before;
|
|
157306
158057
|
let rel = relative10(dirname33(f2), target).split(sep16).join("/").replace(/\.tsx?$/, ".js");
|
|
@@ -157479,7 +158230,7 @@ __export(icon_exports, {
|
|
|
157479
158230
|
summarize: () => summarize3
|
|
157480
158231
|
});
|
|
157481
158232
|
import { createHash as createHash31 } from "node:crypto";
|
|
157482
|
-
import { existsSync as
|
|
158233
|
+
import { existsSync as existsSync60, mkdirSync as mkdirSync28, readFileSync as readFileSync69, statSync as statSync18, writeFileSync as writeFileSync24 } from "node:fs";
|
|
157483
158234
|
import { basename as basename16, dirname as dirname34, join as join59, resolve as resolve48, sep as sep17 } from "node:path";
|
|
157484
158235
|
function readManifest(dir) {
|
|
157485
158236
|
try {
|
|
@@ -157518,7 +158269,7 @@ function templateIconMatch(png) {
|
|
|
157518
158269
|
}
|
|
157519
158270
|
function playState(dir) {
|
|
157520
158271
|
const p2 = join59(resolve48(dir), PLAY_LISTING_ICON);
|
|
157521
|
-
if (!
|
|
158272
|
+
if (!existsSync60(p2)) return null;
|
|
157522
158273
|
try {
|
|
157523
158274
|
if (!statSync18(p2).isFile()) return { path: p2, issues: ["is a directory, not a PNG file"] };
|
|
157524
158275
|
return { path: p2, issues: playListingIconIssues(readFileSync69(p2)) };
|
|
@@ -157544,7 +158295,7 @@ async function iconStatus(dir) {
|
|
|
157544
158295
|
verdict: "missing",
|
|
157545
158296
|
policyChecklist: POLICY_CHECKLIST
|
|
157546
158297
|
};
|
|
157547
|
-
if (!path2 || !
|
|
158298
|
+
if (!path2 || !existsSync60(path2)) return base;
|
|
157548
158299
|
let png;
|
|
157549
158300
|
try {
|
|
157550
158301
|
if (!statSync18(path2).isFile()) {
|
|
@@ -157634,7 +158385,7 @@ function backdropFromTokens(dir, fallback = "#1F2933") {
|
|
|
157634
158385
|
}
|
|
157635
158386
|
async function installIcon(dir, sourcePath, opts = {}) {
|
|
157636
158387
|
const src = resolve48(sourcePath);
|
|
157637
|
-
if (!
|
|
158388
|
+
if (!existsSync60(src)) throw new Error(`himi icon: no such file: ${src}`);
|
|
157638
158389
|
const name = declaredIconName(dir) ?? DEFAULT_CONTENT_ICON;
|
|
157639
158390
|
const dest = iconDest(dir, name);
|
|
157640
158391
|
const wrote = [];
|
|
@@ -157688,11 +158439,11 @@ function declareIcon(dir, name) {
|
|
|
157688
158439
|
}
|
|
157689
158440
|
function siteBookIcon(bookDir) {
|
|
157690
158441
|
const p2 = join59(resolve48(bookDir), SITE_BOOK_ICON_REL);
|
|
157691
|
-
return
|
|
158442
|
+
return existsSync60(p2) ? p2 : null;
|
|
157692
158443
|
}
|
|
157693
158444
|
function siteLogoAbsence(bookDir) {
|
|
157694
158445
|
const bookJson = join59(resolve48(bookDir), "book.json");
|
|
157695
|
-
if (!
|
|
158446
|
+
if (!existsSync60(bookJson)) {
|
|
157696
158447
|
return { reason: "no-book", hint: `no business book at ${bookDir} \u2014 run \`himi site analyze --out <dir>\` first, or pass --book <dir>` };
|
|
157697
158448
|
}
|
|
157698
158449
|
let logoUrl;
|
|
@@ -157976,7 +158727,7 @@ var init_crawl_layers = __esm({
|
|
|
157976
158727
|
});
|
|
157977
158728
|
|
|
157978
158729
|
// src/wix-writes.ts
|
|
157979
|
-
import { existsSync as
|
|
158730
|
+
import { existsSync as existsSync62, readFileSync as readFileSync71 } from "node:fs";
|
|
157980
158731
|
import { join as join62 } from "node:path";
|
|
157981
158732
|
function isProvenRead(method, path2) {
|
|
157982
158733
|
if (/[#\x00-\x1F\x7F]/.test(path2)) return false;
|
|
@@ -158096,7 +158847,7 @@ function parseDataAccess(text11, from) {
|
|
|
158096
158847
|
function readDataAccess(dir) {
|
|
158097
158848
|
for (const name of ["SPEC.md", "MOBILE-UX.md"]) {
|
|
158098
158849
|
const p2 = join62(dir, name);
|
|
158099
|
-
if (!
|
|
158850
|
+
if (!existsSync62(p2)) continue;
|
|
158100
158851
|
let text11;
|
|
158101
158852
|
try {
|
|
158102
158853
|
text11 = readFileSync71(p2, "utf8");
|
|
@@ -158215,11 +158966,11 @@ __export(test_exports, {
|
|
|
158215
158966
|
scopeDescriptors: () => scopeDescriptors,
|
|
158216
158967
|
writeRecordedMocks: () => writeRecordedMocks
|
|
158217
158968
|
});
|
|
158218
|
-
import { existsSync as
|
|
158969
|
+
import { existsSync as existsSync63, mkdirSync as mkdirSync29, readFileSync as readFileSync72, writeFileSync as writeFileSync25 } from "node:fs";
|
|
158219
158970
|
import { join as join63, resolve as resolve49 } from "node:path";
|
|
158220
158971
|
function readTestConfig(dir) {
|
|
158221
158972
|
const p2 = resolve49(dir, TEST_CONFIG_FILE);
|
|
158222
|
-
if (!
|
|
158973
|
+
if (!existsSync63(p2)) return {};
|
|
158223
158974
|
let parsed;
|
|
158224
158975
|
try {
|
|
158225
158976
|
parsed = JSON.parse(readFileSync72(p2, "utf8"));
|
|
@@ -158290,7 +159041,7 @@ function readNetRules(path2) {
|
|
|
158290
159041
|
function defaultNetRules(dir) {
|
|
158291
159042
|
for (const rel of ["dev/net-mocks.json", "tests/net-mocks.json"]) {
|
|
158292
159043
|
const p2 = resolve49(dir, rel);
|
|
158293
|
-
if (
|
|
159044
|
+
if (existsSync63(p2)) {
|
|
158294
159045
|
const rules = readNetRules(p2);
|
|
158295
159046
|
if (rules.length) return { rules, from: rel };
|
|
158296
159047
|
}
|
|
@@ -159382,7 +160133,7 @@ var init_release_payload_hash = __esm({
|
|
|
159382
160133
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
159383
160134
|
import { createHash as createHash35, randomBytes as randomBytes2 } from "node:crypto";
|
|
159384
160135
|
import {
|
|
159385
|
-
existsSync as
|
|
160136
|
+
existsSync as existsSync64,
|
|
159386
160137
|
lstatSync as lstatSync20,
|
|
159387
160138
|
mkdirSync as mkdirSync31,
|
|
159388
160139
|
realpathSync as realpathSync9,
|
|
@@ -159512,7 +160263,7 @@ function readLatestAttestation(contentDir2) {
|
|
|
159512
160263
|
}
|
|
159513
160264
|
function readRetainedAttestations(contentDir2) {
|
|
159514
160265
|
const dir = join66(resolve53(contentDir2), ".himi", "attestations");
|
|
159515
|
-
if (!
|
|
160266
|
+
if (!existsSync64(dir)) return { runs: [], errors: [] };
|
|
159516
160267
|
try {
|
|
159517
160268
|
const names2 = readdirSync30(dir).filter((name) => name.endsWith(".json") && name !== "latest.json");
|
|
159518
160269
|
const parsedRuns = [];
|
|
@@ -159529,7 +160280,7 @@ function readRetainedAttestations(contentDir2) {
|
|
|
159529
160280
|
} else errors.push(`attestation history contains malformed retained run ${name}`);
|
|
159530
160281
|
}
|
|
159531
160282
|
const latest = readLatestAttestation(contentDir2);
|
|
159532
|
-
if (
|
|
160283
|
+
if (existsSync64(join66(dir, "latest.json")) && !latest) errors.push("attestation history has no valid latest.json");
|
|
159533
160284
|
else if (names2.length > 0 && !latest) errors.push("attestation history has no latest.json");
|
|
159534
160285
|
const byHash = new Map(parsedRuns.map((run2) => [run2.selfHash, run2]));
|
|
159535
160286
|
if (byHash.size !== parsedRuns.length) errors.push("attestation history contains duplicate self hashes");
|
|
@@ -159537,7 +160288,7 @@ function readRetainedAttestations(contentDir2) {
|
|
|
159537
160288
|
if (selfHashFor(run2) !== run2.selfHash) errors.push(`selfHash does not match retained run ${run2.runId}`);
|
|
159538
160289
|
for (const expected of Object.values(run2.screenshots)) {
|
|
159539
160290
|
const path2 = screenshotArtifactPath(contentDir2, expected);
|
|
159540
|
-
if (!
|
|
160291
|
+
if (!existsSync64(path2)) errors.push(`missing screenshot for retained run ${run2.runId}: ${basename18(path2)}`);
|
|
159541
160292
|
else if (sha2565(readFileSync74(path2)) !== expected) errors.push(`screenshot hash does not match retained run ${run2.runId}: ${basename18(path2)}`);
|
|
159542
160293
|
}
|
|
159543
160294
|
}
|
|
@@ -159608,7 +160359,7 @@ function writeAttestation(input, opts = {}) {
|
|
|
159608
160359
|
const descriptorHashes = Object.fromEntries(
|
|
159609
160360
|
Object.entries(input.descriptors).sort(([a2], [b2]) => a2.localeCompare(b2)).map(([screen, bytes2]) => [screen, sha2565(bytes2)])
|
|
159610
160361
|
);
|
|
159611
|
-
const screenshotEntries = Object.entries(input.screenshots ?? {}).sort(([a2], [b2]) => a2.localeCompare(b2)).filter(([, path2]) =>
|
|
160362
|
+
const screenshotEntries = Object.entries(input.screenshots ?? {}).sort(([a2], [b2]) => a2.localeCompare(b2)).filter(([, path2]) => existsSync64(path2)).map(([screen, path2]) => {
|
|
159612
160363
|
const bytes2 = readFileSync74(path2);
|
|
159613
160364
|
return { screen, bytes: bytes2, hash: sha2565(bytes2) };
|
|
159614
160365
|
});
|
|
@@ -159616,7 +160367,7 @@ function writeAttestation(input, opts = {}) {
|
|
|
159616
160367
|
for (const { bytes: bytes2, hash: hash2 } of screenshotEntries) {
|
|
159617
160368
|
const artifact = screenshotArtifactPath(contentDir2, hash2);
|
|
159618
160369
|
mkdirSync31(join66(dir, "artifacts"), { recursive: true });
|
|
159619
|
-
if (!
|
|
160370
|
+
if (!existsSync64(artifact)) writeFileSync27(artifact, bytes2);
|
|
159620
160371
|
}
|
|
159621
160372
|
const unsigned = {
|
|
159622
160373
|
attestation: 2,
|
|
@@ -159661,7 +160412,7 @@ function writeAttestation(input, opts = {}) {
|
|
|
159661
160412
|
retainedRuns.flatMap((run2) => Object.values(run2.screenshots))
|
|
159662
160413
|
);
|
|
159663
160414
|
const artifactDir = join66(dir, "artifacts");
|
|
159664
|
-
if (
|
|
160415
|
+
if (existsSync64(artifactDir)) {
|
|
159665
160416
|
for (const name of readdirSync30(artifactDir).filter((candidate) => candidate.endsWith(".png"))) {
|
|
159666
160417
|
if (!retainedScreenshotHashes.has(name.slice(0, -4))) unlinkSync4(join66(artifactDir, name));
|
|
159667
160418
|
}
|
|
@@ -159737,7 +160488,7 @@ function verifyAttestation(attestation, contentDir2, descriptors, expectedApp, r
|
|
|
159737
160488
|
}
|
|
159738
160489
|
for (const [screen, expected] of Object.entries(attestation.screenshots)) {
|
|
159739
160490
|
const path2 = screenshotArtifactPath(contentDir2, expected);
|
|
159740
|
-
if (!
|
|
160491
|
+
if (!existsSync64(path2)) {
|
|
159741
160492
|
errors.push(`missing screenshot for ${screen}: ${basename18(path2)}`);
|
|
159742
160493
|
continue;
|
|
159743
160494
|
}
|
|
@@ -159761,7 +160512,7 @@ var init_attestation = __esm({
|
|
|
159761
160512
|
});
|
|
159762
160513
|
|
|
159763
160514
|
// src/ux-evidence.ts
|
|
159764
|
-
import { existsSync as
|
|
160515
|
+
import { existsSync as existsSync65, mkdirSync as mkdirSync32, readFileSync as readFileSync75, writeFileSync as writeFileSync28 } from "node:fs";
|
|
159765
160516
|
import { dirname as dirname38, isAbsolute as isAbsolute6, join as join67, relative as relative12, resolve as resolve54 } from "node:path";
|
|
159766
160517
|
function isNativePlatform(value2) {
|
|
159767
160518
|
return typeof value2 === "string" && NATIVE_PLATFORMS.includes(value2);
|
|
@@ -159771,7 +160522,7 @@ function isNativeAuditStatus(value2) {
|
|
|
159771
160522
|
}
|
|
159772
160523
|
function readText(path2) {
|
|
159773
160524
|
try {
|
|
159774
|
-
return
|
|
160525
|
+
return existsSync65(path2) ? readFileSync75(path2, "utf8") : null;
|
|
159775
160526
|
} catch {
|
|
159776
160527
|
return null;
|
|
159777
160528
|
}
|
|
@@ -159873,7 +160624,7 @@ function uxEvidenceForRelease(content, release2) {
|
|
|
159873
160624
|
inheritedScreens: [],
|
|
159874
160625
|
malformed: []
|
|
159875
160626
|
};
|
|
159876
|
-
if (!
|
|
160627
|
+
if (!existsSync65(path2)) return { ...base, state: "absent" };
|
|
159877
160628
|
const parsed = parseEvidence(path2);
|
|
159878
160629
|
if (parsed.error) return { ...base, state: "unreadable", error: parsed.error };
|
|
159879
160630
|
if (!parsed.evidence) return { ...base, state: "absent" };
|
|
@@ -159944,11 +160695,11 @@ var mobile_ux_lint_exports = {};
|
|
|
159944
160695
|
__export(mobile_ux_lint_exports, {
|
|
159945
160696
|
mobileUxIssues: () => mobileUxIssues
|
|
159946
160697
|
});
|
|
159947
|
-
import { existsSync as
|
|
160698
|
+
import { existsSync as existsSync66, readFileSync as readFileSync76 } from "node:fs";
|
|
159948
160699
|
import { join as join68 } from "node:path";
|
|
159949
160700
|
function mobileUxIssues(dir, strict) {
|
|
159950
160701
|
const file2 = join68(dir, "MOBILE-UX.md");
|
|
159951
|
-
if (!
|
|
160702
|
+
if (!existsSync66(file2)) return [];
|
|
159952
160703
|
let text11;
|
|
159953
160704
|
try {
|
|
159954
160705
|
text11 = readFileSync76(file2, "utf8");
|
|
@@ -161632,7 +162383,7 @@ __export(functions_exports, {
|
|
|
161632
162383
|
resolveFunctionsTarget: () => resolveFunctionsTarget,
|
|
161633
162384
|
runRemoteFunctionOperation: () => runRemoteFunctionOperation
|
|
161634
162385
|
});
|
|
161635
|
-
import { readFileSync as readFileSync79, existsSync as
|
|
162386
|
+
import { readFileSync as readFileSync79, existsSync as existsSync69 } from "node:fs";
|
|
161636
162387
|
import { join as join71, resolve as resolve55 } from "node:path";
|
|
161637
162388
|
function resolveFunctionsTarget(input) {
|
|
161638
162389
|
const explicitUrl = input.functionsUrl?.trim();
|
|
@@ -161652,7 +162403,7 @@ async function loadFunctionsApp(dir) {
|
|
|
161652
162403
|
}
|
|
161653
162404
|
const sources = {};
|
|
161654
162405
|
for (const definition of config.functions.functions) {
|
|
161655
|
-
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join71(loaded.dir, "functions", `${definition.name}${extension}`)).find(
|
|
162406
|
+
const source = [".ts", ".js", ".mts", ".mjs"].map((extension) => join71(loaded.dir, "functions", `${definition.name}${extension}`)).find(existsSync69);
|
|
161656
162407
|
if (!source) throw new Error(`missing source for function ${definition.name}; expected functions/${definition.name}.ts`);
|
|
161657
162408
|
sources[definition.name] = readFileSync79(source, "utf8");
|
|
161658
162409
|
}
|
|
@@ -161842,7 +162593,7 @@ var init_cli_bridge = __esm({
|
|
|
161842
162593
|
});
|
|
161843
162594
|
|
|
161844
162595
|
// src/mcp/file-tools.ts
|
|
161845
|
-
import { closeSync as closeSync6, constants as constants4, lstatSync as lstatSync21, mkdirSync as mkdirSync33, openSync as openSync5, readdirSync as readdirSync31, readFileSync as readFileSync81, realpathSync as realpathSync10, renameSync as renameSync11, rmSync as rmSync18, statSync as statSync19, writeSync, existsSync as
|
|
162596
|
+
import { closeSync as closeSync6, constants as constants4, lstatSync as lstatSync21, mkdirSync as mkdirSync33, openSync as openSync5, readdirSync as readdirSync31, readFileSync as readFileSync81, realpathSync as realpathSync10, renameSync as renameSync11, rmSync as rmSync18, statSync as statSync19, writeSync, existsSync as existsSync70 } from "node:fs";
|
|
161846
162597
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
161847
162598
|
import { dirname as dirname39, isAbsolute as isAbsolute7, join as join72, relative as relative13, resolve as resolve56, sep as sep18 } from "node:path";
|
|
161848
162599
|
import * as z2 from "zod";
|
|
@@ -161852,7 +162603,7 @@ function within(root, p2) {
|
|
|
161852
162603
|
function realish(p2) {
|
|
161853
162604
|
let cur = p2;
|
|
161854
162605
|
const tail = [];
|
|
161855
|
-
while (!
|
|
162606
|
+
while (!existsSync70(cur)) {
|
|
161856
162607
|
const up = dirname39(cur);
|
|
161857
162608
|
if (up === cur) break;
|
|
161858
162609
|
tail.unshift(cur.slice(up.length + (up.endsWith(sep18) ? 0 : 1)));
|
|
@@ -161875,7 +162626,7 @@ function symlinkComponent(base, abs) {
|
|
|
161875
162626
|
function workspaceRefusal(root, target) {
|
|
161876
162627
|
const r3 = resolve56(root);
|
|
161877
162628
|
const t2 = resolve56(r3, target);
|
|
161878
|
-
if (!
|
|
162629
|
+
if (!existsSync70(r3)) return `the workspace folder ${r3} does not exist`;
|
|
161879
162630
|
if (!within(r3, t2) || !within(realpathSync10(r3), realish(t2))) return `"${target}" is outside the workspace folder ${r3}`;
|
|
161880
162631
|
const link = symlinkComponent(r3, t2);
|
|
161881
162632
|
if (link) return `"${link}" is a symlink \u2014 paths must stay in real folders inside the workspace`;
|
|
@@ -161884,13 +162635,13 @@ function workspaceRefusal(root, target) {
|
|
|
161884
162635
|
async function confinedAppDir(args, deps) {
|
|
161885
162636
|
const root = resolve56(await deps.defaultDir());
|
|
161886
162637
|
const dir = typeof args.dir === "string" && args.dir ? resolve56(root, args.dir) : root;
|
|
161887
|
-
if (!
|
|
162638
|
+
if (!existsSync70(root)) return refuse5("no_workspace", `the workspace folder ${root} does not exist`);
|
|
161888
162639
|
if (!within(root, dir) || !within(realpathSync10(root), realish(dir))) return refuse5("outside_workspace", `"${String(args.dir)}" is outside the workspace folder`);
|
|
161889
162640
|
const link = symlinkComponent(root, dir);
|
|
161890
162641
|
if (link) return refuse5("outside_workspace", `"${link}" is a symlink \u2014 the app folder must be a real folder in the workspace`);
|
|
161891
162642
|
const rel = relative13(root, dir);
|
|
161892
162643
|
if (rel && (isDeniedSourcePath(`${rel}/x`) || isDeniedSourcePath(`${rel.toLowerCase()}/x`))) return refuse5("denied", `"${rel}" is a folder this tool does not touch`);
|
|
161893
|
-
if (!
|
|
162644
|
+
if (!existsSync70(join72(dir, CONTENT_MARKER))) {
|
|
161894
162645
|
return refuse5("not_an_app", `"${rel || "."}" is not an app folder (no ${CONTENT_MARKER}) \u2014 see himi_list_apps, or create one with himi_init`);
|
|
161895
162646
|
}
|
|
161896
162647
|
return dir;
|
|
@@ -161898,7 +162649,7 @@ async function confinedAppDir(args, deps) {
|
|
|
161898
162649
|
function onDiskSpelling(abs) {
|
|
161899
162650
|
let cur = abs;
|
|
161900
162651
|
const tail = [];
|
|
161901
|
-
while (!
|
|
162652
|
+
while (!existsSync70(cur)) {
|
|
161902
162653
|
const up = dirname39(cur);
|
|
161903
162654
|
if (up === cur) break;
|
|
161904
162655
|
tail.unshift(cur.slice(up.length + (up.endsWith(sep18) ? 0 : 1)));
|
|
@@ -161922,7 +162673,7 @@ function confinedPath(appDir3, rel) {
|
|
|
161922
162673
|
const abs = resolve56(appDir3, rel);
|
|
161923
162674
|
if (!within(appDir3, abs) || abs === appDir3) return { error: `"${rel}" is outside the app folder` };
|
|
161924
162675
|
const real = realish(abs);
|
|
161925
|
-
const base =
|
|
162676
|
+
const base = existsSync70(appDir3) ? realpathSync10(appDir3) : realish(appDir3);
|
|
161926
162677
|
if (!within(base, real) || real === base) return { error: `"${rel}" is outside the app folder` };
|
|
161927
162678
|
const link = symlinkComponent(appDir3, abs);
|
|
161928
162679
|
if (link) return { error: `"${link}" is a symlink, which this tool does not follow` };
|
|
@@ -161979,11 +162730,11 @@ function fileTools() {
|
|
|
161979
162730
|
inputSchema: z2.object({}),
|
|
161980
162731
|
handler: async (_a3, d2) => {
|
|
161981
162732
|
const root = resolve56(await d2.defaultDir());
|
|
161982
|
-
if (!
|
|
162733
|
+
if (!existsSync70(root)) return ok({ ok: true, workspace: root, apps: [] });
|
|
161983
162734
|
const apps = [];
|
|
161984
|
-
if (
|
|
162735
|
+
if (existsSync70(join72(root, CONTENT_MARKER))) apps.push(".");
|
|
161985
162736
|
for (const e2 of readdirSync31(root, { withFileTypes: true })) {
|
|
161986
|
-
if (e2.isDirectory() && !e2.name.startsWith(".") &&
|
|
162737
|
+
if (e2.isDirectory() && !e2.name.startsWith(".") && existsSync70(join72(root, e2.name, CONTENT_MARKER))) apps.push(e2.name);
|
|
161987
162738
|
}
|
|
161988
162739
|
return ok({ ok: true, workspace: root, apps: apps.sort() });
|
|
161989
162740
|
}
|
|
@@ -161997,7 +162748,7 @@ function fileTools() {
|
|
|
161997
162748
|
handler: async (a2, d2) => {
|
|
161998
162749
|
const app = await confinedAppDir(a2, d2);
|
|
161999
162750
|
if (typeof app !== "string") return app;
|
|
162000
|
-
if (!
|
|
162751
|
+
if (!existsSync70(app) || !statSync19(app).isDirectory()) return refuse5("no_app", `no folder at ${app}`);
|
|
162001
162752
|
return ok({ ok: true, dir: app, ...listFiles(app) });
|
|
162002
162753
|
}
|
|
162003
162754
|
},
|
|
@@ -162012,7 +162763,7 @@ function fileTools() {
|
|
|
162012
162763
|
if (typeof app !== "string") return app;
|
|
162013
162764
|
const p2 = confinedPath(app, a2.path);
|
|
162014
162765
|
if (typeof p2 !== "string") return refuse5("bad_path", p2.error);
|
|
162015
|
-
if (!
|
|
162766
|
+
if (!existsSync70(p2) || !lstatSync21(p2).isFile()) return refuse5("not_found", `no file "${String(a2.path)}"`);
|
|
162016
162767
|
const size = statSync19(p2).size;
|
|
162017
162768
|
if (size > MAX_FILE_BYTES) return refuse5("too_large", `"${String(a2.path)}" is ${size} bytes \u2014 over the ${MAX_FILE_BYTES}-byte read limit`);
|
|
162018
162769
|
return ok({ ok: true, path: a2.path, bytes: size, content: readFileSync81(p2, "utf8") });
|
|
@@ -162039,7 +162790,7 @@ function fileTools() {
|
|
|
162039
162790
|
if (typeof p2 !== "string") refused2.push({ path: f2.path, error: p2.error });
|
|
162040
162791
|
else if (typeof f2.content !== "string") refused2.push({ path: f2.path, error: "content must be text" });
|
|
162041
162792
|
else if (Buffer.byteLength(f2.content) > MAX_FILE_BYTES) refused2.push({ path: f2.path, error: `over the ${MAX_FILE_BYTES}-byte limit` });
|
|
162042
|
-
else if (
|
|
162793
|
+
else if (existsSync70(p2) && !lstatSync21(p2).isFile()) refused2.push({ path: f2.path, error: "not a regular file" });
|
|
162043
162794
|
else if (planned2.some((q2) => q2.abs === p2)) refused2.push({ path: f2.path, error: "the same file twice in one call" });
|
|
162044
162795
|
else planned2.push({ abs: p2, rel: String(f2.path), content: f2.content });
|
|
162045
162796
|
}
|
|
@@ -162072,7 +162823,7 @@ function fileTools() {
|
|
|
162072
162823
|
for (const rel of paths2) {
|
|
162073
162824
|
const p2 = confinedPath(app, rel);
|
|
162074
162825
|
if (typeof p2 !== "string") refused2.push({ path: rel, error: p2.error });
|
|
162075
|
-
else if (!
|
|
162826
|
+
else if (!existsSync70(p2)) refused2.push({ path: rel, error: "no such file" });
|
|
162076
162827
|
else if (!lstatSync21(p2).isFile()) refused2.push({ path: rel, error: "not a regular file" });
|
|
162077
162828
|
else if (!planned2.includes(p2)) {
|
|
162078
162829
|
planned2.push(p2);
|
|
@@ -162867,14 +163618,14 @@ var init_open_url = __esm({
|
|
|
162867
163618
|
});
|
|
162868
163619
|
|
|
162869
163620
|
// src/ux-audit.ts
|
|
162870
|
-
import { existsSync as
|
|
163621
|
+
import { existsSync as existsSync73, readFileSync as readFileSync83, readdirSync as readdirSync32 } from "node:fs";
|
|
162871
163622
|
import { join as join76, relative as relative15, resolve as resolve61 } from "node:path";
|
|
162872
163623
|
function issue(issues, strict, code, message2, path2) {
|
|
162873
163624
|
issues.push({ code, message: message2, ...path2 ? { path: path2 } : {}, severity: strict ? "error" : "warning" });
|
|
162874
163625
|
}
|
|
162875
163626
|
function readText2(path2) {
|
|
162876
163627
|
try {
|
|
162877
|
-
return
|
|
163628
|
+
return existsSync73(path2) ? readFileSync83(path2, "utf8") : null;
|
|
162878
163629
|
} catch {
|
|
162879
163630
|
return null;
|
|
162880
163631
|
}
|
|
@@ -162974,7 +163725,7 @@ function auditUx(content, strict = false) {
|
|
|
162974
163725
|
}
|
|
162975
163726
|
if (usesAppNetwork(source)) {
|
|
162976
163727
|
const mocksPath = join76(dir, "dev", "net-mocks.json");
|
|
162977
|
-
if (!
|
|
163728
|
+
if (!existsSync73(mocksPath)) {
|
|
162978
163729
|
issue(issues, strict, "missing-app-mocks", "This package uses a Wix/network client but has no app-specific dev/net-mocks.json. `himi test --record` writes one from the live responses it sees; then add fixtures for dynamic, entitlement, or recovery flows.", "dev/net-mocks.json");
|
|
162979
163730
|
} else {
|
|
162980
163731
|
try {
|
|
@@ -163022,7 +163773,7 @@ __export(native_decode_exports, {
|
|
|
163022
163773
|
runNativeDecode: () => runNativeDecode
|
|
163023
163774
|
});
|
|
163024
163775
|
import { execFileSync as execFileSync6, spawnSync as spawnSync4 } from "node:child_process";
|
|
163025
|
-
import { existsSync as
|
|
163776
|
+
import { existsSync as existsSync74, mkdirSync as mkdirSync37, mkdtempSync as mkdtempSync5, readFileSync as readFileSync84, rmSync as rmSync20, writeFileSync as writeFileSync31 } from "node:fs";
|
|
163026
163777
|
import { homedir as homedir10, tmpdir as tmpdir6 } from "node:os";
|
|
163027
163778
|
import { join as join78 } from "node:path";
|
|
163028
163779
|
import { fileURLToPath as fileURLToPath27 } from "node:url";
|
|
@@ -163034,8 +163785,8 @@ function nativeDecodeAndroidHarnessDir() {
|
|
|
163034
163785
|
}
|
|
163035
163786
|
function nativeOracleShipped() {
|
|
163036
163787
|
return {
|
|
163037
|
-
ios:
|
|
163038
|
-
android:
|
|
163788
|
+
ios: existsSync74(join78(nativeDecodePackageDir(), "Package.swift")),
|
|
163789
|
+
android: existsSync74(join78(nativeDecodeAndroidHarnessDir(), "gradlew"))
|
|
163039
163790
|
};
|
|
163040
163791
|
}
|
|
163041
163792
|
function detectNativeDecode(options = {}) {
|
|
@@ -163046,7 +163797,7 @@ function detectNativeDecode(options = {}) {
|
|
|
163046
163797
|
return { platform: "ios", available: false, reason: `the iOS decoder oracle requires macOS (darwin); this host is ${hostPlatform}` };
|
|
163047
163798
|
}
|
|
163048
163799
|
if (!swiftAvailable) return { platform: "ios", available: false, reason: "swift is not on PATH" };
|
|
163049
|
-
const packageAvailable = options.packageAvailable ??
|
|
163800
|
+
const packageAvailable = options.packageAvailable ?? existsSync74(join78(packageDir, "Package.swift"));
|
|
163050
163801
|
if (!packageAvailable) {
|
|
163051
163802
|
return {
|
|
163052
163803
|
platform: "ios",
|
|
@@ -163072,7 +163823,7 @@ function defaultAndroidSdkDir(hostPlatform, home) {
|
|
|
163072
163823
|
function detectAndroidNativeDecode(options = {}) {
|
|
163073
163824
|
const harnessDir = options.harnessDir ?? nativeDecodeAndroidHarnessDir();
|
|
163074
163825
|
const gradlew = join78(harnessDir, "gradlew");
|
|
163075
|
-
const gradlewAvailable = options.gradlewAvailable ??
|
|
163826
|
+
const gradlewAvailable = options.gradlewAvailable ?? existsSync74(gradlew);
|
|
163076
163827
|
if (!gradlewAvailable) {
|
|
163077
163828
|
return {
|
|
163078
163829
|
platform: "android",
|
|
@@ -163080,7 +163831,7 @@ function detectAndroidNativeDecode(options = {}) {
|
|
|
163080
163831
|
reason: "the in-repo Android Gradle harness is unavailable (off-repo installs do not ship the decoder oracle)"
|
|
163081
163832
|
};
|
|
163082
163833
|
}
|
|
163083
|
-
const exists = typeof options.sdkAvailable === "function" ? options.sdkAvailable : typeof options.sdkAvailable === "boolean" ? /* @__PURE__ */ ((answer) => () => answer)(options.sdkAvailable) :
|
|
163834
|
+
const exists = typeof options.sdkAvailable === "function" ? options.sdkAvailable : typeof options.sdkAvailable === "boolean" ? /* @__PURE__ */ ((answer) => () => answer)(options.sdkAvailable) : existsSync74;
|
|
163084
163835
|
const defaultDir = defaultAndroidSdkDir(options.hostPlatform ?? process.platform, options.homeDir ?? homedir10());
|
|
163085
163836
|
const candidates = [
|
|
163086
163837
|
options.androidHome ?? process.env.ANDROID_HOME,
|
|
@@ -163342,7 +164093,7 @@ __export(browser_authoring_exports, {
|
|
|
163342
164093
|
});
|
|
163343
164094
|
import { createServer as createServer4 } from "node:http";
|
|
163344
164095
|
import { createHash as createHash38, randomBytes as randomBytes4 } from "node:crypto";
|
|
163345
|
-
import { existsSync as
|
|
164096
|
+
import { existsSync as existsSync75, readdirSync as readdirSync33, readFileSync as readFileSync85, realpathSync as realpathSync11, statSync as statSync20 } from "node:fs";
|
|
163346
164097
|
import { join as join79, posix as posix3, relative as relative16, sep as sep19 } from "node:path";
|
|
163347
164098
|
function humanMs(ms2) {
|
|
163348
164099
|
return ms2 < 1e3 ? `${ms2}ms` : `${Math.round(ms2 / 1e3)}s`;
|
|
@@ -163365,7 +164116,7 @@ function collectWorkerSources(tier5SrcDir, bundleName) {
|
|
|
163365
164116
|
}
|
|
163366
164117
|
}
|
|
163367
164118
|
};
|
|
163368
|
-
if (!
|
|
164119
|
+
if (!existsSync75(root)) return null;
|
|
163369
164120
|
walk2(root, `/tier5-src/${bundleName}`);
|
|
163370
164121
|
const entry = [`/tier5-src/${bundleName}/index.ts`, `/tier5-src/${bundleName}/index.js`].find((p2) => p2 in files);
|
|
163371
164122
|
if (!entry) return null;
|
|
@@ -163392,7 +164143,7 @@ function collectRelativeSiblings(files, tier5SrcDir) {
|
|
|
163392
164143
|
join79(onDisk, "index.js")
|
|
163393
164144
|
];
|
|
163394
164145
|
for (const abs of candidates) {
|
|
163395
|
-
if (!
|
|
164146
|
+
if (!existsSync75(abs) || statSync20(abs).isDirectory()) continue;
|
|
163396
164147
|
const key3 = `/tier5-src/${relative16(tier5SrcDir, abs).split(sep19).join(posix3.sep)}`;
|
|
163397
164148
|
if (key3 in files) break;
|
|
163398
164149
|
files[key3] = readFileSync85(abs, "utf8");
|
|
@@ -163503,7 +164254,7 @@ async function readBody3(req) {
|
|
|
163503
164254
|
async function runBrowserAuthoring(opts) {
|
|
163504
164255
|
const log = opts.log ?? (() => {
|
|
163505
164256
|
});
|
|
163506
|
-
const timeoutMs = opts.timeoutMs ??
|
|
164257
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
163507
164258
|
const payload = encodeJob(opts.job);
|
|
163508
164259
|
const token = mintToken2(payload);
|
|
163509
164260
|
const unusable = await probeAuthoringPage(opts.authoringBase, opts.fetchImpl, opts.probeTimeoutMs);
|
|
@@ -163579,11 +164330,11 @@ async function runBrowserAuthoring(opts) {
|
|
|
163579
164330
|
});
|
|
163580
164331
|
});
|
|
163581
164332
|
}
|
|
163582
|
-
var
|
|
164333
|
+
var DEFAULT_TIMEOUT_MS3, PROBE_TIMEOUT_MS, POINT_ELSEWHERE, NO_SUCH_ROUTE, NOT_STAGED, MAX_CALLBACK_BYTES;
|
|
163583
164334
|
var init_browser_authoring = __esm({
|
|
163584
164335
|
"src/browser-authoring.ts"() {
|
|
163585
164336
|
init_open_url();
|
|
163586
|
-
|
|
164337
|
+
DEFAULT_TIMEOUT_MS3 = 5 * 60 * 1e3;
|
|
163587
164338
|
PROBE_TIMEOUT_MS = 5e3;
|
|
163588
164339
|
POINT_ELSEWHERE = "Point --serve-url at a plane that mounts /v1/authoring/* (the local serve stack does NOT: core/serve-authoring is a separate service), or pass --target to select a deployed one.";
|
|
163589
164340
|
NO_SUCH_ROUTE = /* @__PURE__ */ new Set([404, 410]);
|
|
@@ -163602,7 +164353,7 @@ __export(coverage_exports, {
|
|
|
163602
164353
|
suppressedNativeKeys: () => suppressedNativeKeys,
|
|
163603
164354
|
trendAndStore: () => trendAndStore
|
|
163604
164355
|
});
|
|
163605
|
-
import { existsSync as
|
|
164356
|
+
import { existsSync as existsSync76, mkdirSync as mkdirSync38, readFileSync as readFileSync86, writeFileSync as writeFileSync32 } from "node:fs";
|
|
163606
164357
|
import { dirname as dirname43, join as join80 } from "node:path";
|
|
163607
164358
|
function suppressedNativeKeys(oracle) {
|
|
163608
164359
|
return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
|
|
@@ -163786,7 +164537,7 @@ function trendAndStore(dir, entries, suppressed) {
|
|
|
163786
164537
|
const p2 = join80(dir, LEDGER_FILE);
|
|
163787
164538
|
let previous = null;
|
|
163788
164539
|
try {
|
|
163789
|
-
if (
|
|
164540
|
+
if (existsSync76(p2)) {
|
|
163790
164541
|
const parsed = JSON.parse(readFileSync86(p2, "utf8"));
|
|
163791
164542
|
if (Array.isArray(parsed.keys)) previous = parsed.keys.filter((k2) => typeof k2 === "string");
|
|
163792
164543
|
}
|
|
@@ -163829,7 +164580,7 @@ function diffAndStoreObservations(dir, current) {
|
|
|
163829
164580
|
const p2 = join80(dir, OBS_FILE);
|
|
163830
164581
|
let previous = null;
|
|
163831
164582
|
try {
|
|
163832
|
-
if (
|
|
164583
|
+
if (existsSync76(p2)) {
|
|
163833
164584
|
const parsed = JSON.parse(readFileSync86(p2, "utf8"));
|
|
163834
164585
|
if (parsed.screens && typeof parsed.screens === "object" && !Array.isArray(parsed.screens) && Object.values(parsed.screens).every(
|
|
163835
164586
|
(v2) => Array.isArray(v2) && v2.every((l2) => typeof l2 === "string")
|
|
@@ -164202,11 +164953,11 @@ __export(design_kits_exports, {
|
|
|
164202
164953
|
kitsDir: () => kitsDir,
|
|
164203
164954
|
listKits: () => listKits2
|
|
164204
164955
|
});
|
|
164205
|
-
import { existsSync as
|
|
164956
|
+
import { existsSync as existsSync78, readFileSync as readFileSync88, readdirSync as readdirSync34 } from "node:fs";
|
|
164206
164957
|
import { join as join83, basename as basename20 } from "node:path";
|
|
164207
164958
|
import { fileURLToPath as fileURLToPath28 } from "node:url";
|
|
164208
164959
|
function kitsDir() {
|
|
164209
|
-
return KIT_DIR_CANDIDATES.find((p2) =>
|
|
164960
|
+
return KIT_DIR_CANDIDATES.find((p2) => existsSync78(p2));
|
|
164210
164961
|
}
|
|
164211
164962
|
function listKits2() {
|
|
164212
164963
|
const dir = kitsDir();
|
|
@@ -164701,7 +165452,7 @@ __export(coverage_exports2, {
|
|
|
164701
165452
|
verifyNativeProof: () => verifyNativeProof
|
|
164702
165453
|
});
|
|
164703
165454
|
import { createHash as createHash39 } from "node:crypto";
|
|
164704
|
-
import { existsSync as
|
|
165455
|
+
import { existsSync as existsSync80, readFileSync as readFileSync90, writeFileSync as writeFileSync33 } from "node:fs";
|
|
164705
165456
|
import { isAbsolute as isAbsolute8, join as join85, resolve as resolve64 } from "node:path";
|
|
164706
165457
|
function verifiedEvidence(evidenceDir) {
|
|
164707
165458
|
const manifest2 = obj3(JSON.parse(readFileSync90(join85(evidenceDir, "manifest.json"), "utf8")));
|
|
@@ -164797,7 +165548,7 @@ function deriveRequirements(evidenceDir) {
|
|
|
164797
165548
|
function verifyNativeProof(contentDir2, releaseHash, requirementIds) {
|
|
164798
165549
|
const root = resolve64(contentDir2);
|
|
164799
165550
|
const path2 = join85(root, NATIVE_PROOF_FILE);
|
|
164800
|
-
if (!
|
|
165551
|
+
if (!existsSync80(path2)) return { ok: false, issues: [`${NATIVE_PROOF_FILE} is absent.`] };
|
|
164801
165552
|
let proof;
|
|
164802
165553
|
try {
|
|
164803
165554
|
proof = obj3(JSON.parse(readFileSync90(path2, "utf8")));
|
|
@@ -164819,7 +165570,7 @@ function verifyNativeProof(contentDir2, releaseHash, requirementIds) {
|
|
|
164819
165570
|
continue;
|
|
164820
165571
|
}
|
|
164821
165572
|
const artifact = record2.artifact;
|
|
164822
|
-
if (typeof artifact !== "string" || !artifact.trim() || isAbsolute8(artifact) || artifact.split(/[\\/]/).includes("..") || !
|
|
165573
|
+
if (typeof artifact !== "string" || !artifact.trim() || isAbsolute8(artifact) || artifact.split(/[\\/]/).includes("..") || !existsSync80(join85(root, artifact))) {
|
|
164823
165574
|
issues.push(`Native walkthrough check ${id} needs a reviewable artifact file.`);
|
|
164824
165575
|
}
|
|
164825
165576
|
}
|
|
@@ -164828,7 +165579,7 @@ function verifyNativeProof(contentDir2, releaseHash, requirementIds) {
|
|
|
164828
165579
|
function syncCoverage(evidenceDir, contentDir2, write2 = true) {
|
|
164829
165580
|
const current = deriveRequirements(evidenceDir);
|
|
164830
165581
|
const path2 = join85(resolve64(contentDir2), COVERAGE_FILE);
|
|
164831
|
-
const existed =
|
|
165582
|
+
const existed = existsSync80(path2);
|
|
164832
165583
|
const old = existed ? obj3(JSON.parse(readFileSync90(path2, "utf8"))) : {};
|
|
164833
165584
|
const hashesChanged = existed && JSON.stringify(old.sourceHashes) !== JSON.stringify(current.sourceHashes);
|
|
164834
165585
|
const prior = Array.isArray(old.requirements) ? old.requirements : [];
|
|
@@ -164869,7 +165620,7 @@ function verifyCoverage(evidenceDir, contentDir2, releaseHash, builtScreenIds) {
|
|
|
164869
165620
|
const saved = result.existed ? obj3(JSON.parse(readFileSync90(join85(resolve64(contentDir2), COVERAGE_FILE), "utf8"))) : {};
|
|
164870
165621
|
const rows = Array.isArray(saved.requirements) ? saved.requirements.map(obj3) : [];
|
|
164871
165622
|
const contentManifest = join85(resolve64(contentDir2), "himalaya.content.json");
|
|
164872
|
-
const declaredScreens =
|
|
165623
|
+
const declaredScreens = existsSync80(contentManifest) ? obj3(obj3(JSON.parse(readFileSync90(contentManifest, "utf8"))).screens) : void 0;
|
|
164873
165624
|
const availableScreens = builtScreenIds ? new Set(builtScreenIds) : declaredScreens && Object.keys(declaredScreens).length ? new Set(Object.keys(declaredScreens)) : void 0;
|
|
164874
165625
|
for (const row2 of rows) {
|
|
164875
165626
|
const id = typeof row2.id === "string" ? row2.id : void 0;
|
|
@@ -164905,7 +165656,7 @@ function verifyCoverage(evidenceDir, contentDir2, releaseHash, builtScreenIds) {
|
|
|
164905
165656
|
const path2 = check.evidence;
|
|
164906
165657
|
if (typeof path2 !== "string" || !path2.trim() || isAbsolute8(path2) || path2.split(/[\\/]/).includes("..")) {
|
|
164907
165658
|
issues.push({ id, message: `Check ${required3} needs a safe relative evidence path.` });
|
|
164908
|
-
} else if (!
|
|
165659
|
+
} else if (!existsSync80(join85(resolve64(contentDir2), path2))) {
|
|
164909
165660
|
issues.push({ id, message: `Check ${required3} evidence file is absent: ${path2}.` });
|
|
164910
165661
|
} else {
|
|
164911
165662
|
try {
|
|
@@ -164916,7 +165667,7 @@ function verifyCoverage(evidenceDir, contentDir2, releaseHash, builtScreenIds) {
|
|
|
164916
165667
|
issues.push({ id, message: `Check ${required3} has no latest passed record for this requirement and target.` });
|
|
164917
165668
|
} else {
|
|
164918
165669
|
const artifact = record2.artifact;
|
|
164919
|
-
if (typeof artifact !== "string" || !artifact.trim() || isAbsolute8(artifact) || artifact.split(/[\\/]/).includes("..") || !
|
|
165670
|
+
if (typeof artifact !== "string" || !artifact.trim() || isAbsolute8(artifact) || artifact.split(/[\\/]/).includes("..") || !existsSync80(join85(resolve64(contentDir2), artifact))) {
|
|
164920
165671
|
issues.push({ id, message: `Check ${required3} needs a reviewable artifact file.` });
|
|
164921
165672
|
}
|
|
164922
165673
|
}
|
|
@@ -164956,7 +165707,7 @@ __export(validate_topbar_exports, {
|
|
|
164956
165707
|
runOneAppTopBarValidation: () => runOneAppTopBarValidation
|
|
164957
165708
|
});
|
|
164958
165709
|
import { createHash as createHash40 } from "node:crypto";
|
|
164959
|
-
import { existsSync as
|
|
165710
|
+
import { existsSync as existsSync81, readFileSync as readFileSync91, statSync as statSync22 } from "node:fs";
|
|
164960
165711
|
import { resolve as resolve65, join as join86 } from "node:path";
|
|
164961
165712
|
import ts8 from "typescript";
|
|
164962
165713
|
function enrichedControls(raw, views) {
|
|
@@ -165165,7 +165916,7 @@ function configActions(configPath) {
|
|
|
165165
165916
|
}
|
|
165166
165917
|
function screenActions2(contentDir2) {
|
|
165167
165918
|
const path2 = join86(contentDir2, "dev", "index.ts");
|
|
165168
|
-
if (!
|
|
165919
|
+
if (!existsSync81(path2)) return /* @__PURE__ */ new Map();
|
|
165169
165920
|
const source = ts8.createSourceFile(path2, readFileSync91(path2, "utf8"), ts8.ScriptTarget.Latest, true, ts8.ScriptKind.TS);
|
|
165170
165921
|
if (source.parseDiagnostics.length) throw Error("dev/index.ts could not be parsed.");
|
|
165171
165922
|
const declaration = source.statements.filter(ts8.isVariableStatement).flatMap((statement) => [...statement.declarationList.declarations]).find((item) => ts8.isIdentifier(item.name) && item.name.text === "SCREENS");
|
|
@@ -165266,7 +166017,7 @@ function validate3(evidenceDir, contentDir2) {
|
|
|
165266
166017
|
}
|
|
165267
166018
|
const mappings = /* @__PURE__ */ new Map();
|
|
165268
166019
|
const coveragePath = join86(contentDir2, "ONE-APP-COVERAGE.json");
|
|
165269
|
-
if (
|
|
166020
|
+
if (existsSync81(coveragePath)) {
|
|
165270
166021
|
try {
|
|
165271
166022
|
const coverage = readJson7(coveragePath);
|
|
165272
166023
|
for (const row2 of Array.isArray(coverage.requirements) ? coverage.requirements : []) {
|
|
@@ -166132,7 +166883,7 @@ async function generatePkce() {
|
|
|
166132
166883
|
return { verifier, challenge: base64url(new Uint8Array(digest2)) };
|
|
166133
166884
|
}
|
|
166134
166885
|
async function hostedAuthUrl(req, visitorToken, fetchImpl = fetch) {
|
|
166135
|
-
const res = await fetchImpl(`${
|
|
166886
|
+
const res = await fetchImpl(`${WIX_API3}${REDIRECT_SESSION_PATH}`, {
|
|
166136
166887
|
method: "POST",
|
|
166137
166888
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${visitorToken}` },
|
|
166138
166889
|
body: JSON.stringify({
|
|
@@ -166175,7 +166926,7 @@ async function hostedAuthUrl(req, visitorToken, fetchImpl = fetch) {
|
|
|
166175
166926
|
return fullUrl;
|
|
166176
166927
|
}
|
|
166177
166928
|
async function exchangeAuthCode(cfg, code, verifier, fetchImpl = fetch) {
|
|
166178
|
-
const res = await fetchImpl(`${
|
|
166929
|
+
const res = await fetchImpl(`${WIX_API3}${TOKEN_PATH}`, {
|
|
166179
166930
|
method: "POST",
|
|
166180
166931
|
headers: { "Content-Type": "application/json" },
|
|
166181
166932
|
body: JSON.stringify({
|
|
@@ -166224,10 +166975,10 @@ function safeReturnPath(value2, fallback) {
|
|
|
166224
166975
|
if (/[-]/.test(value2)) return fallback;
|
|
166225
166976
|
return value2;
|
|
166226
166977
|
}
|
|
166227
|
-
var
|
|
166978
|
+
var WIX_API3, REDIRECT_SESSION_PATH, TOKEN_PATH, MEMBER_SESSION_COOKIE, MEMBER_SESSION_TTL_MS, PENDING_LOGIN_TTL_MS, MEMBER_CALLBACK_PATH;
|
|
166228
166979
|
var init_wix_member_auth = __esm({
|
|
166229
166980
|
"../../core/serve-runtime/src/wix-member-auth.ts"() {
|
|
166230
|
-
|
|
166981
|
+
WIX_API3 = "https://www.wixapis.com";
|
|
166231
166982
|
REDIRECT_SESSION_PATH = "/_api/redirects-api/v1/redirect-session";
|
|
166232
166983
|
TOKEN_PATH = "/oauth2/token";
|
|
166233
166984
|
MEMBER_SESSION_COOKIE = "himi_wm_sid";
|
|
@@ -168099,7 +168850,7 @@ __export(run_exports, {
|
|
|
168099
168850
|
runPackage: () => runPackage,
|
|
168100
168851
|
withoutProdServe: () => withoutProdServe
|
|
168101
168852
|
});
|
|
168102
|
-
import { cpSync as cpSync2, existsSync as
|
|
168853
|
+
import { cpSync as cpSync2, existsSync as existsSync84, mkdirSync as mkdirSync39, mkdtempSync as mkdtempSync7, readFileSync as readFileSync93, rmSync as rmSync23, statSync as statSync24 } from "node:fs";
|
|
168103
168854
|
import { networkInterfaces as osNetworkInterfaces, tmpdir as tmpdir8 } from "node:os";
|
|
168104
168855
|
import { dirname as dirname44, join as join89 } from "node:path";
|
|
168105
168856
|
import { fileURLToPath as fileURLToPath29 } from "node:url";
|
|
@@ -168129,9 +168880,9 @@ async function fetchBytes(url) {
|
|
|
168129
168880
|
}
|
|
168130
168881
|
async function resolvePackage(source, workDir) {
|
|
168131
168882
|
const isUrl2 = /^https?:\/\//i.test(source);
|
|
168132
|
-
if (!isUrl2 &&
|
|
168883
|
+
if (!isUrl2 && existsSync84(source) && statSync24(source).isDirectory()) {
|
|
168133
168884
|
const appDirManifest = join89(source, "release-manifest.json");
|
|
168134
|
-
if (
|
|
168885
|
+
if (existsSync84(appDirManifest)) {
|
|
168135
168886
|
const opened2 = openPackageDir(source);
|
|
168136
168887
|
if (!opened2.validation.ok) {
|
|
168137
168888
|
throw new Error(`package is not valid:
|
|
@@ -168189,7 +168940,7 @@ async function loadPreviewAssets() {
|
|
|
168189
168940
|
// in-repo checkout
|
|
168190
168941
|
];
|
|
168191
168942
|
for (const path2 of candidates) {
|
|
168192
|
-
if (!
|
|
168943
|
+
if (!existsSync84(path2)) continue;
|
|
168193
168944
|
const blob = readFileSync93(path2);
|
|
168194
168945
|
return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
|
|
168195
168946
|
}
|
|
@@ -168328,7 +169079,7 @@ __export(run_browser_exports, {
|
|
|
168328
169079
|
runInBrowser: () => runInBrowser
|
|
168329
169080
|
});
|
|
168330
169081
|
import { createServer as createServer6 } from "node:http";
|
|
168331
|
-
import { existsSync as
|
|
169082
|
+
import { existsSync as existsSync85, readFileSync as readFileSync94 } from "node:fs";
|
|
168332
169083
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
168333
169084
|
import { dirname as dirname45, resolve as resolve69 } from "node:path";
|
|
168334
169085
|
import { fileURLToPath as fileURLToPath30 } from "node:url";
|
|
@@ -168336,7 +169087,7 @@ function stagedDir() {
|
|
|
168336
169087
|
return process.env.HIMI_BROWSER_PLANE_OUT ? resolve69(process.env.HIMI_BROWSER_PLANE_OUT) : resolve69(REPO2, "packages", "serve", "dist", "browser-plane");
|
|
168337
169088
|
}
|
|
168338
169089
|
function missingStaged() {
|
|
168339
|
-
return [...SERVED].filter((f2) => !
|
|
169090
|
+
return [...SERVED].filter((f2) => !existsSync85(resolve69(stagedDir(), f2))).sort();
|
|
168340
169091
|
}
|
|
168341
169092
|
function ensureBrowserPlaneStaged() {
|
|
168342
169093
|
if (missingStaged().length === 0) return { ok: true, detail: "already staged" };
|
|
@@ -168426,7 +169177,7 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
168426
169177
|
}
|
|
168427
169178
|
const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
|
|
168428
169179
|
if (SERVED.has(name)) {
|
|
168429
|
-
if (!
|
|
169180
|
+
if (!existsSync85(resolve69(stagedDir(), name))) {
|
|
168430
169181
|
const restaged = ensureBrowserPlaneStaged();
|
|
168431
169182
|
if (!restaged.ok) {
|
|
168432
169183
|
res.writeHead(503, { "content-type": "application/json" });
|
|
@@ -168489,14 +169240,14 @@ var hhp_preview_exports = {};
|
|
|
168489
169240
|
__export(hhp_preview_exports, {
|
|
168490
169241
|
hhpPreviewResponse: () => hhpPreviewResponse
|
|
168491
169242
|
});
|
|
168492
|
-
import { existsSync as
|
|
169243
|
+
import { existsSync as existsSync86, readFileSync as readFileSync95 } from "node:fs";
|
|
168493
169244
|
import { join as join90 } from "node:path";
|
|
168494
169245
|
function hhpPreviewResponse(root, request) {
|
|
168495
|
-
if (new URL(request.url).pathname !== "/__himi/hhp-preview" || !
|
|
169246
|
+
if (new URL(request.url).pathname !== "/__himi/hhp-preview" || !existsSync86(join90(root, "hhp.json"))) return null;
|
|
168496
169247
|
if (request.method !== "GET") return new Response(null, { status: 405 });
|
|
168497
169248
|
try {
|
|
168498
169249
|
const file2 = localPath(root, ".himi/hhp-preview.json");
|
|
168499
|
-
const authored2 =
|
|
169250
|
+
const authored2 = existsSync86(file2) ? JSON.parse(readFileSync95(file2, "utf8")) : {};
|
|
168500
169251
|
if (authored2.mockCapabilities && (!Array.isArray(authored2.mockCapabilities) || authored2.mockCapabilities.some((v2) => typeof v2 !== "string"))) throw new Error("mockCapabilities must be a string array.");
|
|
168501
169252
|
const fixtures = authored2.fixtures ?? {};
|
|
168502
169253
|
if (typeof fixtures !== "object" || Array.isArray(fixtures) || fixtures === null) throw new Error("fixtures must be an object.");
|
|
@@ -171193,7 +171944,7 @@ __export(credential_profile_exports, {
|
|
|
171193
171944
|
profilePath: () => profilePath,
|
|
171194
171945
|
resolveStoreCredentials: () => resolveStoreCredentials
|
|
171195
171946
|
});
|
|
171196
|
-
import { existsSync as
|
|
171947
|
+
import { existsSync as existsSync88, readFileSync as readFileSync101 } from "node:fs";
|
|
171197
171948
|
import { homedir as homedir11 } from "node:os";
|
|
171198
171949
|
import { join as join93 } from "node:path";
|
|
171199
171950
|
function credentialsDir(home = homedir11()) {
|
|
@@ -171237,7 +171988,7 @@ function resolveStoreCredentials(opts) {
|
|
|
171237
171988
|
const env = opts.env ?? process.env;
|
|
171238
171989
|
const home = opts.home ?? homedir11();
|
|
171239
171990
|
const read = opts.readProfile ?? ((p2) => readFileSync101(p2, "utf8"));
|
|
171240
|
-
const exists = opts.profileExists ??
|
|
171991
|
+
const exists = opts.profileExists ?? existsSync88;
|
|
171241
171992
|
const ios = cfg.ios ?? {};
|
|
171242
171993
|
const flagName = opts.profileFlag?.trim();
|
|
171243
171994
|
const named = namedProfile(cfg, opts.profileFlag);
|
|
@@ -171303,7 +172054,7 @@ var init_credential_profile = __esm({
|
|
|
171303
172054
|
|
|
171304
172055
|
// ../store-release/iap-credentials.ts
|
|
171305
172056
|
import { createHash as createHash45 } from "node:crypto";
|
|
171306
|
-
import { existsSync as
|
|
172057
|
+
import { existsSync as existsSync89, readFileSync as readFileSync102, realpathSync as realpathSync12 } from "node:fs";
|
|
171307
172058
|
import { homedir as homedir12 } from "node:os";
|
|
171308
172059
|
function accountFingerprint(keyId, issuerId) {
|
|
171309
172060
|
return `sha256:${createHash45("sha256").update(`${issuerId}:${keyId}`).digest("hex").slice(0, 16)}`;
|
|
@@ -171350,7 +172101,7 @@ function resolveIapCredentials(options) {
|
|
|
171350
172101
|
env: {},
|
|
171351
172102
|
home,
|
|
171352
172103
|
readProfile: readFile3,
|
|
171353
|
-
profileExists: options.exists ??
|
|
172104
|
+
profileExists: options.exists ?? existsSync89
|
|
171354
172105
|
});
|
|
171355
172106
|
assertCredentialOutsideRepo(`credential profile "${profile}"`, realpath(profilePath(profile, home)));
|
|
171356
172107
|
assertCredentialOutsideRepo(`credential profile "${profile}" ascKeyPath`, canonicalKeyPath(creds.ascKeyPath, profile, realpath));
|
|
@@ -171855,7 +172606,7 @@ var init_store_spec = __esm({
|
|
|
171855
172606
|
});
|
|
171856
172607
|
|
|
171857
172608
|
// src/iap-config-edit.ts
|
|
171858
|
-
import { existsSync as
|
|
172609
|
+
import { existsSync as existsSync90, readFileSync as readFileSync104 } from "node:fs";
|
|
171859
172610
|
import { basename as basename24, join as join94 } from "node:path";
|
|
171860
172611
|
import ts9 from "typescript";
|
|
171861
172612
|
function bindPurchasesAppInConfig(source, options) {
|
|
@@ -171936,7 +172687,7 @@ function capabilityFinding(app, fileName) {
|
|
|
171936
172687
|
function withStoreBundle(dir, options) {
|
|
171937
172688
|
if (options.storeBundleId) return options;
|
|
171938
172689
|
const path2 = join94(dir, "store", "store.config.yaml");
|
|
171939
|
-
if (!
|
|
172690
|
+
if (!existsSync90(path2)) return options;
|
|
171940
172691
|
const storeBundleId = parseStoreConfig(readFileSync104(path2, "utf8")).ios?.bundleId;
|
|
171941
172692
|
return storeBundleId ? { ...options, storeBundleId } : options;
|
|
171942
172693
|
}
|
|
@@ -172676,7 +173427,7 @@ var init_store_iap_screenshots = __esm({
|
|
|
172676
173427
|
});
|
|
172677
173428
|
|
|
172678
173429
|
// src/store-iap-screenshot-render.ts
|
|
172679
|
-
import { existsSync as
|
|
173430
|
+
import { existsSync as existsSync91, mkdtempSync as mkdtempSync9, readFileSync as readFileSync105, rmSync as rmSync25 } from "node:fs";
|
|
172680
173431
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
172681
173432
|
import { join as join96 } from "node:path";
|
|
172682
173433
|
function renderProblems(render, entityId) {
|
|
@@ -172739,7 +173490,7 @@ function createReviewScreenRenderer() {
|
|
|
172739
173490
|
async capture(html, contentDir2) {
|
|
172740
173491
|
const { pngPageHtml: pngPageHtml2, stabilizePngPage: stabilizePngPage2 } = await Promise.resolve().then(() => (init_render_descriptor(), render_descriptor_exports));
|
|
172741
173492
|
const tokensPath = join96(contentDir2, "tokens.json");
|
|
172742
|
-
const tokens2 =
|
|
173493
|
+
const tokens2 = existsSync91(tokensPath) ? JSON.parse(readFileSync105(tokensPath, "utf8")) : null;
|
|
172743
173494
|
const { width, height, scale } = REVIEW_SCREENSHOT_FRAME;
|
|
172744
173495
|
const page = await (await (browser ??= launch())).newPage({ viewport: { width, height }, deviceScaleFactor: scale, colorScheme: "light" });
|
|
172745
173496
|
try {
|
|
@@ -172810,166 +173561,6 @@ var init_serve_preview = __esm({
|
|
|
172810
173561
|
}
|
|
172811
173562
|
});
|
|
172812
173563
|
|
|
172813
|
-
// src/site-analyze/rest.ts
|
|
172814
|
-
var rest_exports = {};
|
|
172815
|
-
__export(rest_exports, {
|
|
172816
|
-
WIX_API: () => WIX_API3,
|
|
172817
|
-
WixApiError: () => WixApiError2,
|
|
172818
|
-
classifyHttp: () => classifyHttp,
|
|
172819
|
-
compactWixstaticUrl: () => compactWixstaticUrl,
|
|
172820
|
-
isGenericWixFavicon: () => isGenericWixFavicon,
|
|
172821
|
-
makeTransport: () => makeTransport,
|
|
172822
|
-
mediaUrlFromLogo: () => mediaUrlFromLogo,
|
|
172823
|
-
ownerTransportFrom: () => ownerTransportFrom,
|
|
172824
|
-
probeCall: () => probeCall,
|
|
172825
|
-
resolveWixUrl: () => resolveWixUrl,
|
|
172826
|
-
uploadMediaBytes: () => uploadMediaBytes,
|
|
172827
|
-
visitorTransportFrom: () => visitorTransportFrom,
|
|
172828
|
-
wixMediaFileId: () => wixMediaFileId
|
|
172829
|
-
});
|
|
172830
|
-
function resolveWixUrl(path2) {
|
|
172831
|
-
if (/^https?:\/\//i.test(path2)) return path2;
|
|
172832
|
-
return `${WIX_API3}${path2}`;
|
|
172833
|
-
}
|
|
172834
|
-
function classifyHttp(status, count2) {
|
|
172835
|
-
if (status === 428) return "not-installed";
|
|
172836
|
-
if (status === 404) return "wrong-path";
|
|
172837
|
-
if (status && status >= 400) return "error";
|
|
172838
|
-
return count2 > 0 ? "ok" : "empty";
|
|
172839
|
-
}
|
|
172840
|
-
function makeTransport(fetchImpl, auth, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
172841
|
-
return async (method, path2, body) => {
|
|
172842
|
-
const headers2 = { Accept: "application/json" };
|
|
172843
|
-
if (auth?.token) headers2.Authorization = auth.token;
|
|
172844
|
-
if (auth?.msid) headers2["wix-site-id"] = auth.msid;
|
|
172845
|
-
if (body !== void 0) headers2["Content-Type"] = "application/json";
|
|
172846
|
-
const res = await fetchImpl(resolveWixUrl(path2), {
|
|
172847
|
-
method,
|
|
172848
|
-
headers: headers2,
|
|
172849
|
-
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
172850
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
172851
|
-
});
|
|
172852
|
-
const text11 = await res.text();
|
|
172853
|
-
let parsed = text11;
|
|
172854
|
-
try {
|
|
172855
|
-
parsed = text11 ? JSON.parse(text11) : null;
|
|
172856
|
-
} catch {
|
|
172857
|
-
}
|
|
172858
|
-
if (!res.ok) throw new WixApiError2(res.status, method, path2, parsed);
|
|
172859
|
-
return parsed;
|
|
172860
|
-
};
|
|
172861
|
-
}
|
|
172862
|
-
function ownerTransportFrom(fetchImpl, owner) {
|
|
172863
|
-
return makeTransport(fetchImpl, { token: owner.token, msid: owner.msid });
|
|
172864
|
-
}
|
|
172865
|
-
function visitorTransportFrom(fetchImpl, token, msid) {
|
|
172866
|
-
return makeTransport(fetchImpl, { token, msid });
|
|
172867
|
-
}
|
|
172868
|
-
async function probeCall(call, method, path2, body) {
|
|
172869
|
-
try {
|
|
172870
|
-
return { data: await call(method, path2, body), err: null };
|
|
172871
|
-
} catch (e2) {
|
|
172872
|
-
if (e2 instanceof WixApiError2) return { data: null, err: e2 };
|
|
172873
|
-
throw e2;
|
|
172874
|
-
}
|
|
172875
|
-
}
|
|
172876
|
-
function mediaUrlFromLogo(logo) {
|
|
172877
|
-
const s2 = (logo ?? "").trim();
|
|
172878
|
-
if (!s2) return null;
|
|
172879
|
-
if (/^https?:\/\//i.test(s2)) return s2;
|
|
172880
|
-
const id = s2.replace(/^wix:image:\/\/v1\//, "").split("/")[0].split("#")[0];
|
|
172881
|
-
if (!id) return null;
|
|
172882
|
-
if (/^https?:\/\//i.test(id)) return id;
|
|
172883
|
-
return `https://static.wixstatic.com/media/${id}`;
|
|
172884
|
-
}
|
|
172885
|
-
function isGenericWixFavicon(url) {
|
|
172886
|
-
try {
|
|
172887
|
-
const h2 = new URL(url).hostname.toLowerCase();
|
|
172888
|
-
return h2 === "wix.com" || h2.endsWith(".wix.com");
|
|
172889
|
-
} catch {
|
|
172890
|
-
return false;
|
|
172891
|
-
}
|
|
172892
|
-
}
|
|
172893
|
-
function wixMediaFileId(url) {
|
|
172894
|
-
const m2 = url.match(/static\.wixstatic\.com\/media\/([^/?#]+)/i);
|
|
172895
|
-
return m2?.[1] ? decodeURIComponent(m2[1]) : void 0;
|
|
172896
|
-
}
|
|
172897
|
-
function compactWixstaticUrl(url, maxEdge = 800) {
|
|
172898
|
-
if (!/static\.wixstatic\.com\/media\//i.test(url)) return url;
|
|
172899
|
-
if (/\.(svg|ico)(\?|#|$)/i.test(url.split("?")[0] ?? url)) return url;
|
|
172900
|
-
const w2 = url.match(/(?:\/|,)w_(\d+)/)?.[1];
|
|
172901
|
-
if (w2 && Number(w2) <= maxEdge) return url;
|
|
172902
|
-
const id = wixMediaFileId(url);
|
|
172903
|
-
if (!id) return url;
|
|
172904
|
-
return `https://static.wixstatic.com/media/${id}/v1/fill/w_${maxEdge},h_${maxEdge},al_c,q_80,enc_auto/file.jpg`;
|
|
172905
|
-
}
|
|
172906
|
-
async function uploadMediaBytes(call, fetchImpl, bytes2, fileName, mimeType) {
|
|
172907
|
-
const { uploadUrl } = await call(
|
|
172908
|
-
"POST",
|
|
172909
|
-
"/site-media/v1/files/generate-upload-url",
|
|
172910
|
-
{ mimeType, fileName: `himi-business-book/${fileName}` }
|
|
172911
|
-
);
|
|
172912
|
-
const put = await fetchImpl(`${uploadUrl}?filename=${encodeURIComponent(fileName)}`, {
|
|
172913
|
-
method: "PUT",
|
|
172914
|
-
headers: { "Content-Type": mimeType },
|
|
172915
|
-
body: bytes2,
|
|
172916
|
-
signal: AbortSignal.timeout(12e4)
|
|
172917
|
-
});
|
|
172918
|
-
if (!put.ok) throw new Error(`media upload PUT failed: ${put.status}`);
|
|
172919
|
-
const payload = await put.json();
|
|
172920
|
-
const file2 = payload.file ?? payload;
|
|
172921
|
-
const id = file2?.id ?? file2?.fileId;
|
|
172922
|
-
const url = file2?.url ?? (id ? `https://static.wixstatic.com/media/${id}` : void 0);
|
|
172923
|
-
if (!id || !url) throw new Error("media upload returned no file id");
|
|
172924
|
-
return { id, url };
|
|
172925
|
-
}
|
|
172926
|
-
var WIX_API3, DEFAULT_TIMEOUT_MS3, WixApiError2;
|
|
172927
|
-
var init_rest = __esm({
|
|
172928
|
-
"src/site-analyze/rest.ts"() {
|
|
172929
|
-
WIX_API3 = "https://www.wixapis.com";
|
|
172930
|
-
DEFAULT_TIMEOUT_MS3 = 8e3;
|
|
172931
|
-
WixApiError2 = class extends Error {
|
|
172932
|
-
constructor(status, method, path2, body) {
|
|
172933
|
-
super(`${method} ${path2} \u2192 ${status}`);
|
|
172934
|
-
this.status = status;
|
|
172935
|
-
this.method = method;
|
|
172936
|
-
this.path = path2;
|
|
172937
|
-
this.body = body;
|
|
172938
|
-
this.name = "WixApiError";
|
|
172939
|
-
}
|
|
172940
|
-
};
|
|
172941
|
-
}
|
|
172942
|
-
});
|
|
172943
|
-
|
|
172944
|
-
// src/site-analyze/visitor-auth.ts
|
|
172945
|
-
var visitor_auth_exports = {};
|
|
172946
|
-
__export(visitor_auth_exports, {
|
|
172947
|
-
mintVisitorToken: () => mintVisitorToken
|
|
172948
|
-
});
|
|
172949
|
-
async function mintVisitorToken(fetchImpl, clientId) {
|
|
172950
|
-
const res = await fetchImpl(`${WIX_API3}/oauth2/token`, {
|
|
172951
|
-
method: "POST",
|
|
172952
|
-
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
172953
|
-
body: JSON.stringify({ clientId, grantType: "anonymous" }),
|
|
172954
|
-
signal: AbortSignal.timeout(8e3)
|
|
172955
|
-
});
|
|
172956
|
-
const text11 = await res.text();
|
|
172957
|
-
let parsed = text11;
|
|
172958
|
-
try {
|
|
172959
|
-
parsed = text11 ? JSON.parse(text11) : null;
|
|
172960
|
-
} catch {
|
|
172961
|
-
}
|
|
172962
|
-
if (!res.ok) throw new WixApiError2(res.status, "POST", "/oauth2/token", parsed);
|
|
172963
|
-
const token = parsed?.access_token ?? parsed?.accessToken;
|
|
172964
|
-
if (!token) throw new Error("visitor mint returned no access_token");
|
|
172965
|
-
return token;
|
|
172966
|
-
}
|
|
172967
|
-
var init_visitor_auth = __esm({
|
|
172968
|
-
"src/site-analyze/visitor-auth.ts"() {
|
|
172969
|
-
init_rest();
|
|
172970
|
-
}
|
|
172971
|
-
});
|
|
172972
|
-
|
|
172973
173564
|
// src/store-iap.ts
|
|
172974
173565
|
var store_iap_exports = {};
|
|
172975
173566
|
__export(store_iap_exports, {
|
|
@@ -174181,7 +174772,7 @@ __export(preflight_app_exports, {
|
|
|
174181
174772
|
profileAccount: () => profileAccount,
|
|
174182
174773
|
readXcconfigVars: () => readXcconfigVars
|
|
174183
174774
|
});
|
|
174184
|
-
import { readFileSync as readFileSync107, existsSync as
|
|
174775
|
+
import { readFileSync as readFileSync107, existsSync as existsSync92, readdirSync as readdirSync38, statSync as statSync25 } from "node:fs";
|
|
174185
174776
|
import { createHash as createHash47 } from "node:crypto";
|
|
174186
174777
|
import { dirname as dirname48, join as join98 } from "node:path";
|
|
174187
174778
|
function analyze(projectYml, storeConfig, icon, account) {
|
|
@@ -174308,7 +174899,7 @@ function readXcconfigVars(iosDir, projectYml) {
|
|
|
174308
174899
|
const vars = {};
|
|
174309
174900
|
const seen = /* @__PURE__ */ new Set();
|
|
174310
174901
|
const read = (path2) => {
|
|
174311
|
-
if (seen.has(path2) || !
|
|
174902
|
+
if (seen.has(path2) || !existsSync92(path2)) return;
|
|
174312
174903
|
seen.add(path2);
|
|
174313
174904
|
for (const raw of readFileSync107(path2, "utf8").split("\n")) {
|
|
174314
174905
|
const inc = /^\s*#include\??\s+"([^"]+)"/.exec(raw);
|
|
@@ -174337,8 +174928,8 @@ function profileAccount(app, storeConfig, opts = {}) {
|
|
|
174337
174928
|
}
|
|
174338
174929
|
}
|
|
174339
174930
|
async function preflightApp(app, opts = {}) {
|
|
174340
|
-
const projectYml =
|
|
174341
|
-
const storeConfig =
|
|
174931
|
+
const projectYml = existsSync92(iosProjectYml(app)) ? readFileSync107(iosProjectYml(app), "utf8") : "";
|
|
174932
|
+
const storeConfig = existsSync92(storeConfigPath(app)) ? readFileSync107(storeConfigPath(app), "utf8") : "";
|
|
174342
174933
|
const identity = projectYml ? analyzeStoreIdentity(projectYml, storeConfig, readXcconfigVars(join98(appDir(app), "ios"), projectYml)) : [];
|
|
174343
174934
|
if (!storeConfig) return [{ level: "error", message: `no apps/${app}/store/store.config.yaml \u2014 run /setup-store-signing first.` }, ...identity];
|
|
174344
174935
|
const findings = analyze(
|
|
@@ -174376,15 +174967,15 @@ function analyzeSubmissionRecord(appLevel, review, opts) {
|
|
|
174376
174967
|
function appLevelMetadataFiles(app, locale = "en-US") {
|
|
174377
174968
|
const root = join98(storeDir(app), "metadata");
|
|
174378
174969
|
const out2 = /* @__PURE__ */ new Set();
|
|
174379
|
-
if (
|
|
174970
|
+
if (existsSync92(root)) {
|
|
174380
174971
|
for (const n2 of readdirSync38(root)) if (n2.endsWith(".txt")) out2.add(n2);
|
|
174381
174972
|
}
|
|
174382
|
-
if (
|
|
174973
|
+
if (existsSync92(join98(root, locale, "privacy_url.txt"))) out2.add("privacy_url.txt");
|
|
174383
174974
|
return out2;
|
|
174384
174975
|
}
|
|
174385
174976
|
function reviewInfoFiles(app) {
|
|
174386
174977
|
const dir = join98(storeDir(app), "review_information");
|
|
174387
|
-
if (!
|
|
174978
|
+
if (!existsSync92(dir)) return /* @__PURE__ */ new Set();
|
|
174388
174979
|
return new Set(readdirSync38(dir).filter((n2) => n2.endsWith(".txt")));
|
|
174389
174980
|
}
|
|
174390
174981
|
function isValidAppStoreSize(w2, h2) {
|
|
@@ -174531,20 +175122,20 @@ function analyzeListing(metaFiles, shots) {
|
|
|
174531
175122
|
}
|
|
174532
175123
|
function metadataFilesPresent(app, locale = "en-US") {
|
|
174533
175124
|
const dir = join98(storeDir(app), "metadata", locale);
|
|
174534
|
-
if (!
|
|
175125
|
+
if (!existsSync92(dir)) return /* @__PURE__ */ new Set();
|
|
174535
175126
|
return new Set(readdirSync38(dir).filter((n2) => n2.endsWith(".txt")));
|
|
174536
175127
|
}
|
|
174537
175128
|
function listScreenshots(app, locale = "en-US") {
|
|
174538
175129
|
const out2 = [];
|
|
174539
175130
|
const flat = join98(storeDir(app), "screenshots", locale);
|
|
174540
|
-
if (
|
|
175131
|
+
if (existsSync92(flat)) {
|
|
174541
175132
|
for (const png of readdirSync38(flat).filter((n2) => n2.endsWith(".png"))) {
|
|
174542
175133
|
const sz = pngSize2(readFileSync107(join98(flat, png)));
|
|
174543
175134
|
if (sz) out2.push({ name: png, w: sz.w, h: sz.h });
|
|
174544
175135
|
}
|
|
174545
175136
|
}
|
|
174546
175137
|
const legacy = join98(storeDir(app), "metadata", locale, "screenshots");
|
|
174547
|
-
if (
|
|
175138
|
+
if (existsSync92(legacy)) {
|
|
174548
175139
|
for (const deviceDir of readdirSync38(legacy)) {
|
|
174549
175140
|
const d2 = join98(legacy, deviceDir);
|
|
174550
175141
|
if (!statSync25(d2).isDirectory()) continue;
|
|
@@ -174558,7 +175149,7 @@ function listScreenshots(app, locale = "en-US") {
|
|
|
174558
175149
|
}
|
|
174559
175150
|
function placeholderHashes2() {
|
|
174560
175151
|
const templateIos = join98(appDir("_template"), "ios");
|
|
174561
|
-
if (!
|
|
175152
|
+
if (!existsSync92(templateIos)) return [LEGACY_PLACEHOLDER_SHA2562];
|
|
174562
175153
|
for (const target of readdirSync38(templateIos)) {
|
|
174563
175154
|
const p2 = join98(templateIos, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
174564
175155
|
try {
|
|
@@ -174594,7 +175185,7 @@ async function pixelIssues(bytes2) {
|
|
|
174594
175185
|
}
|
|
174595
175186
|
}
|
|
174596
175187
|
async function appIconState(iosDir) {
|
|
174597
|
-
if (!
|
|
175188
|
+
if (!existsSync92(iosDir)) return { exists: false, isPlaceholder: false, storeIssues: [] };
|
|
174598
175189
|
for (const target of readdirSync38(iosDir)) {
|
|
174599
175190
|
const p2 = join98(iosDir, target, "Assets.xcassets", "AppIcon.appiconset", "icon_1024.png");
|
|
174600
175191
|
try {
|
|
@@ -174730,6 +175321,19 @@ var init_asc_status = __esm({
|
|
|
174730
175321
|
}
|
|
174731
175322
|
});
|
|
174732
175323
|
|
|
175324
|
+
// ../../core/serve-control/src/captcha-bindable.ts
|
|
175325
|
+
var captcha_bindable_exports = {};
|
|
175326
|
+
__export(captcha_bindable_exports, {
|
|
175327
|
+
captchaBindable: () => captchaBindable
|
|
175328
|
+
});
|
|
175329
|
+
function captchaBindable(shell, externalContract) {
|
|
175330
|
+
return !externalContract && ["branded-lite", "owner-lite"].includes(shell);
|
|
175331
|
+
}
|
|
175332
|
+
var init_captcha_bindable = __esm({
|
|
175333
|
+
"../../core/serve-control/src/captcha-bindable.ts"() {
|
|
175334
|
+
}
|
|
175335
|
+
});
|
|
175336
|
+
|
|
174733
175337
|
// src/browser-login.ts
|
|
174734
175338
|
import { createServer as createServer7 } from "node:http";
|
|
174735
175339
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
@@ -175661,7 +176265,7 @@ function headers(session) {
|
|
|
175661
176265
|
...session ? { "X-Admin-Session": session } : {}
|
|
175662
176266
|
};
|
|
175663
176267
|
}
|
|
175664
|
-
function
|
|
176268
|
+
function truncate3(token) {
|
|
175665
176269
|
return token.length <= 20 ? token : `${token.slice(0, 8)}\u2026${token.slice(-8)}`;
|
|
175666
176270
|
}
|
|
175667
176271
|
function parseDataFlag(raw) {
|
|
@@ -175787,7 +176391,7 @@ async function runNotify(pos, flags, io2, deps = {}) {
|
|
|
175787
176391
|
const bits = [
|
|
175788
176392
|
String(t2.id).padStart(4),
|
|
175789
176393
|
t2.platform.padEnd(8),
|
|
175790
|
-
|
|
176394
|
+
truncate3(t2.token).padEnd(19),
|
|
175791
176395
|
(t2.environment ?? "-").padEnd(11),
|
|
175792
176396
|
(t2.appVersion ?? "-").padEnd(10),
|
|
175793
176397
|
t2.lastSeen,
|
|
@@ -175999,7 +176603,7 @@ __export(base44_adopt_exports, {
|
|
|
175999
176603
|
renderAdoptModule: () => renderAdoptModule,
|
|
176000
176604
|
runBase44Adopt: () => runBase44Adopt
|
|
176001
176605
|
});
|
|
176002
|
-
import { existsSync as
|
|
176606
|
+
import { existsSync as existsSync96, readFileSync as readFileSync114, writeFileSync as writeFileSync38 } from "node:fs";
|
|
176003
176607
|
import { join as join104, resolve as resolve74 } from "node:path";
|
|
176004
176608
|
function prop(entity, key3) {
|
|
176005
176609
|
const props = entity.schema?.properties;
|
|
@@ -176108,7 +176712,7 @@ function runBase44Adopt(opts) {
|
|
|
176108
176712
|
const issues = validateBase44Entities({ entities: result.entities, functions: result.functions }, opts.app);
|
|
176109
176713
|
if (opts.write === void 0 || opts.write === false || issues.some((i2) => i2.severity === "error")) return { result, module, issues };
|
|
176110
176714
|
const target = typeof opts.write === "string" ? resolve74(opts.cwd, opts.write) : join104(opts.cwd, ADOPT_MODULE_FILENAME);
|
|
176111
|
-
if (
|
|
176715
|
+
if (existsSync96(target)) {
|
|
176112
176716
|
throw new AdoptError("adopt_target_exists", `${target} already exists \u2014 adopt never overwrites. Delete or rename it, or pass --write <other path>.`, 1, { path: target });
|
|
176113
176717
|
}
|
|
176114
176718
|
writeFileSync38(target, module);
|
|
@@ -176357,7 +176961,7 @@ __export(generate_exports, {
|
|
|
176357
176961
|
writeGenerated: () => writeGenerated
|
|
176358
176962
|
});
|
|
176359
176963
|
import { createHash as createHash50 } from "node:crypto";
|
|
176360
|
-
import { existsSync as
|
|
176964
|
+
import { existsSync as existsSync97, mkdirSync as mkdirSync42, readdirSync as readdirSync39, readFileSync as readFileSync115, writeFileSync as writeFileSync39 } from "node:fs";
|
|
176361
176965
|
import { dirname as dirname51, join as join105 } from "node:path";
|
|
176362
176966
|
function withHeader(body) {
|
|
176363
176967
|
return `${GENERATED_HEADER}${sha2566(body)}
|
|
@@ -176484,7 +177088,7 @@ function writeGenerated(dir, files, opts = {}) {
|
|
|
176484
177088
|
const abs = join105(dir, f2.path);
|
|
176485
177089
|
const next = withHeader(f2.body);
|
|
176486
177090
|
let outcome;
|
|
176487
|
-
if (!
|
|
177091
|
+
if (!existsSync97(abs)) outcome = "written";
|
|
176488
177092
|
else {
|
|
176489
177093
|
const cur = readFileSync115(abs, "utf8");
|
|
176490
177094
|
if (cur === next) outcome = "unchanged";
|
|
@@ -176503,14 +177107,14 @@ function orphanedFiles(dir, current) {
|
|
|
176503
177107
|
const keep = new Set(current.map((f2) => f2.path));
|
|
176504
177108
|
const found = [];
|
|
176505
177109
|
const t5 = join105(dir, "tier5-src");
|
|
176506
|
-
if (!
|
|
177110
|
+
if (!existsSync97(t5)) return found;
|
|
176507
177111
|
const candidates = readdirSync39(t5).filter((d2) => d2.startsWith("b44-")).map((d2) => `tier5-src/${d2}/index.ts`);
|
|
176508
177112
|
const shared = join105(t5, "_shared");
|
|
176509
|
-
if (
|
|
177113
|
+
if (existsSync97(shared)) {
|
|
176510
177114
|
for (const f2 of readdirSync39(shared)) if (/^b44-.*-plan\.ts$/.test(f2)) candidates.push(`tier5-src/_shared/${f2}`);
|
|
176511
177115
|
}
|
|
176512
177116
|
for (const rel of candidates.sort()) {
|
|
176513
|
-
if (keep.has(rel) || !
|
|
177117
|
+
if (keep.has(rel) || !existsSync97(join105(dir, rel))) continue;
|
|
176514
177118
|
if (readFileSync115(join105(dir, rel), "utf8").startsWith(GENERATED_HEADER)) found.push(rel);
|
|
176515
177119
|
}
|
|
176516
177120
|
return found;
|
|
@@ -176549,7 +177153,7 @@ __export(base44_auth_exports, {
|
|
|
176549
177153
|
usableBase44Auth: () => usableBase44Auth,
|
|
176550
177154
|
writeBase44Session: () => writeBase44Session
|
|
176551
177155
|
});
|
|
176552
|
-
import { chmodSync as chmodSync4, existsSync as
|
|
177156
|
+
import { chmodSync as chmodSync4, existsSync as existsSync98, mkdirSync as mkdirSync43, readFileSync as readFileSync116, rmSync as rmSync27, writeFileSync as writeFileSync40 } from "node:fs";
|
|
176553
177157
|
import { homedir as homedir15 } from "node:os";
|
|
176554
177158
|
import { dirname as dirname52, join as join106 } from "node:path";
|
|
176555
177159
|
function base44ApiBase(env = process.env) {
|
|
@@ -176560,7 +177164,7 @@ function base44SessionPath(home = homedir15()) {
|
|
|
176560
177164
|
}
|
|
176561
177165
|
function readBase44Session(home) {
|
|
176562
177166
|
const p2 = base44SessionPath(home);
|
|
176563
|
-
if (!
|
|
177167
|
+
if (!existsSync98(p2)) return void 0;
|
|
176564
177168
|
try {
|
|
176565
177169
|
const s2 = JSON.parse(readFileSync116(p2, "utf8"));
|
|
176566
177170
|
return typeof s2.accessToken === "string" && s2.accessToken ? s2 : void 0;
|
|
@@ -176578,7 +177182,7 @@ function writeBase44Session(session, home) {
|
|
|
176578
177182
|
}
|
|
176579
177183
|
function deleteBase44Session(home) {
|
|
176580
177184
|
const p2 = base44SessionPath(home);
|
|
176581
|
-
if (!
|
|
177185
|
+
if (!existsSync98(p2)) return false;
|
|
176582
177186
|
rmSync27(p2, { force: true });
|
|
176583
177187
|
return true;
|
|
176584
177188
|
}
|
|
@@ -176681,7 +177285,7 @@ function hasBase44WriteScope(auth) {
|
|
|
176681
177285
|
}
|
|
176682
177286
|
function importBase44CliSession(home = homedir15(), env = process.env) {
|
|
176683
177287
|
const src = join106(home, ".base44", "auth", "auth.json");
|
|
176684
|
-
if (!
|
|
177288
|
+
if (!existsSync98(src)) throw new Error(`no Base44 CLI session at ${src} \u2014 run \`npx base44 login\` first, or use \`himi base44 login\``);
|
|
176685
177289
|
const a2 = JSON.parse(readFileSync116(src, "utf8"));
|
|
176686
177290
|
if (typeof a2.accessToken !== "string" || !a2.accessToken) throw new Error(`${src} holds no access token`);
|
|
176687
177291
|
const session = {
|
|
@@ -176779,11 +177383,11 @@ __export(seed_exports, {
|
|
|
176779
177383
|
seedBase44Entities: () => seedBase44Entities,
|
|
176780
177384
|
writeBase44SeedRows: () => writeBase44SeedRows
|
|
176781
177385
|
});
|
|
176782
|
-
import { existsSync as
|
|
177386
|
+
import { existsSync as existsSync99, readFileSync as readFileSync117, writeFileSync as writeFileSync41 } from "node:fs";
|
|
176783
177387
|
import { join as join107 } from "node:path";
|
|
176784
177388
|
function readBase44SeedFile(dir) {
|
|
176785
177389
|
const file2 = join107(dir, BASE44_SEED_FILE);
|
|
176786
|
-
if (!
|
|
177390
|
+
if (!existsSync99(file2)) return {};
|
|
176787
177391
|
let parsed;
|
|
176788
177392
|
try {
|
|
176789
177393
|
parsed = JSON.parse(readFileSync117(file2, "utf8"));
|
|
@@ -176943,7 +177547,7 @@ function writeBase44SeedRows(opts) {
|
|
|
176943
177547
|
return { ok: false, path: path2, entities: {}, agentPrompt: "", next: [], note: opts.only ? `--only ${opts.only.join(",")} matched no owned entity` : `no owned Base44 entities declared \u2014 add one with \`name\` (physically ${base44Prefix(app)}<Name>). Adopted entities are never seeded.` };
|
|
176944
177548
|
}
|
|
176945
177549
|
let existing = {};
|
|
176946
|
-
if (
|
|
177550
|
+
if (existsSync99(path2)) {
|
|
176947
177551
|
let parsed;
|
|
176948
177552
|
try {
|
|
176949
177553
|
parsed = JSON.parse(readFileSync117(path2, "utf8"));
|
|
@@ -177298,7 +177902,7 @@ __export(functions_exports2, {
|
|
|
177298
177902
|
markerContent: () => markerContent,
|
|
177299
177903
|
readFunctionSource: () => readFunctionSource
|
|
177300
177904
|
});
|
|
177301
|
-
import { existsSync as
|
|
177905
|
+
import { existsSync as existsSync100, lstatSync as lstatSync22 } from "node:fs";
|
|
177302
177906
|
import { join as join108 } from "node:path";
|
|
177303
177907
|
function markerContent(app) {
|
|
177304
177908
|
return `${JSON.stringify({ app, by: "himi" })}
|
|
@@ -177307,7 +177911,7 @@ function markerContent(app) {
|
|
|
177307
177911
|
function readFunctionSource(appDir3, name, app) {
|
|
177308
177912
|
const rel = `base44/functions/${name}/`;
|
|
177309
177913
|
const folder = join108(appDir3, "base44", "functions", name);
|
|
177310
|
-
if (!
|
|
177914
|
+
if (!existsSync100(folder) || !lstatSync22(folder).isDirectory()) throw new FunctionSourceError("function_source_missing", `no source folder at ${rel}`);
|
|
177311
177915
|
const { entries, skipped } = collectAppSource(folder);
|
|
177312
177916
|
if (skipped.length) throw new FunctionSourceError("function_source_unsafe", `${rel} holds paths himi will not upload (symlinks or denied names): ${skipped.join(", ")} \u2014 remove them`);
|
|
177313
177917
|
const secrets = secretFindings(entries);
|
|
@@ -177462,9 +178066,9 @@ function propsOf2(schema) {
|
|
|
177462
178066
|
function isOwnedPhysical(name, app) {
|
|
177463
178067
|
return name.startsWith(base44Prefix(app));
|
|
177464
178068
|
}
|
|
177465
|
-
function foreignGuard(
|
|
178069
|
+
function foreignGuard(snapshot3, next, owned) {
|
|
177466
178070
|
const out2 = [];
|
|
177467
|
-
for (const e2 of
|
|
178071
|
+
for (const e2 of snapshot3) {
|
|
177468
178072
|
if (owned.has(e2.name)) continue;
|
|
177469
178073
|
if (!Object.prototype.hasOwnProperty.call(next, e2.name)) {
|
|
177470
178074
|
out2.push({ code: "would_delete_foreign_entity", entity: e2.name, detail: `"${e2.name}" is not himi's and would be left out of the full-set sync \u2014 Base44 would delete it and its rows` });
|
|
@@ -177501,20 +178105,20 @@ function inheritUndeclaredPermissions(desired, remote, spec) {
|
|
|
177501
178105
|
if (f2.rls === void 0 && remoteProps[f2.key]?.rls !== void 0) desiredProps[f2.key].rls = remoteProps[f2.key].rls;
|
|
177502
178106
|
}
|
|
177503
178107
|
}
|
|
177504
|
-
function planEntitySync(declared,
|
|
178108
|
+
function planEntitySync(declared, snapshot3, opts) {
|
|
177505
178109
|
const { app, allowDestructive = false, applyPermissions = false, emptyAppOk = false } = opts;
|
|
177506
178110
|
const plan = { next: {}, actions: [], refusals: [], warnings: [], owned: [] };
|
|
177507
|
-
if (
|
|
178111
|
+
if (snapshot3.length === 0 && !emptyAppOk) {
|
|
177508
178112
|
plan.refusals.push({ code: "schema_snapshot_empty", detail: "the project download holds no entity schemas \u2014 if the Base44 app really has no entities, pass --empty-app-ok" });
|
|
177509
178113
|
}
|
|
177510
178114
|
const specs = declared.filter((s2) => !!s2 && typeof s2 === "object");
|
|
177511
178115
|
const owned = new Map(specs.filter(isOwnedEntity).map((s2) => [physicalEntityName(s2, app), s2]));
|
|
177512
178116
|
const adopted = new Set(specs.filter(isAdoptedEntity).map((s2) => physicalEntityName(s2, app)));
|
|
177513
|
-
const live3 = new Map(
|
|
178117
|
+
const live3 = new Map(snapshot3.map((e2) => [e2.name, e2]));
|
|
177514
178118
|
const provisioned = new Set((opts.provisioned ?? []).filter((n2) => isOwnedPhysical(n2, app)));
|
|
177515
|
-
const ownedHere = /* @__PURE__ */ new Set([...
|
|
178119
|
+
const ownedHere = /* @__PURE__ */ new Set([...snapshot3.map((e2) => e2.name).filter((n2) => provisioned.has(n2)), ...[...owned.keys()].filter((n2) => !live3.has(n2))]);
|
|
177516
178120
|
plan.owned = [...ownedHere].sort();
|
|
177517
|
-
for (const e2 of
|
|
178121
|
+
for (const e2 of snapshot3) {
|
|
177518
178122
|
if (!ownedHere.has(e2.name)) {
|
|
177519
178123
|
plan.next[e2.name] = e2.schema;
|
|
177520
178124
|
if (owned.has(e2.name)) {
|
|
@@ -177578,7 +178182,7 @@ function planEntitySync(declared, snapshot2, opts) {
|
|
|
177578
178182
|
for (const name of adopted) {
|
|
177579
178183
|
if (!live3.has(name)) plan.warnings.push(`adopted entity "${name}" is not on the live app \u2014 himi never creates an entity it does not own`);
|
|
177580
178184
|
}
|
|
177581
|
-
plan.refusals.push(...foreignGuard(
|
|
178185
|
+
plan.refusals.push(...foreignGuard(snapshot3, plan.next, ownedHere));
|
|
177582
178186
|
return plan;
|
|
177583
178187
|
}
|
|
177584
178188
|
var BUILTINS2;
|
|
@@ -177645,12 +178249,12 @@ __export(apply_exports, {
|
|
|
177645
178249
|
createBase44Entities: () => createBase44Entities,
|
|
177646
178250
|
fileLedger: () => fileLedger
|
|
177647
178251
|
});
|
|
177648
|
-
import { existsSync as
|
|
178252
|
+
import { existsSync as existsSync101, readFileSync as readFileSync118, writeFileSync as writeFileSync42 } from "node:fs";
|
|
177649
178253
|
import { join as join109 } from "node:path";
|
|
177650
178254
|
function fileLedger(dir, appId2) {
|
|
177651
178255
|
const path2 = join109(dir, LEDGER_FILE2);
|
|
177652
178256
|
const load3 = () => {
|
|
177653
|
-
if (!
|
|
178257
|
+
if (!existsSync101(path2)) return {};
|
|
177654
178258
|
let v2;
|
|
177655
178259
|
try {
|
|
177656
178260
|
v2 = JSON.parse(readFileSync118(path2, "utf8"));
|
|
@@ -180695,7 +181299,7 @@ var init_analyze = __esm({
|
|
|
180695
181299
|
});
|
|
180696
181300
|
|
|
180697
181301
|
// src/base44-analyze/write-artifacts.ts
|
|
180698
|
-
import { existsSync as
|
|
181302
|
+
import { existsSync as existsSync102, mkdirSync as mkdirSync45, readFileSync as readFileSync119, rmSync as rmSync29, writeFileSync as writeFileSync44 } from "node:fs";
|
|
180699
181303
|
import { dirname as dirname53, join as join111, resolve as resolve75, sep as sep20 } from "node:path";
|
|
180700
181304
|
function isBookFolder(dir) {
|
|
180701
181305
|
try {
|
|
@@ -180786,7 +181390,7 @@ function writeBase44Book(result, outDir, opts = {}) {
|
|
|
180786
181390
|
const md = renderBookMd(book);
|
|
180787
181391
|
assertNoSecrets(json8);
|
|
180788
181392
|
assertNoSecrets(md);
|
|
180789
|
-
const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) =>
|
|
181393
|
+
const owned = ["book.json", "BOOK.md", "source", "screenshots"].filter((n2) => existsSync102(join111(out2, n2)));
|
|
180790
181394
|
if (owned.length) {
|
|
180791
181395
|
if (!isBookFolder(out2)) throw new Error(`refusing to write the app book into ${out2}: it already has ${owned.join(", ")} that ${owned.length === 1 ? "is" : "are"} not from an app book \u2014 pick an empty --out`);
|
|
180792
181396
|
for (const d2 of ["source", "screenshots"]) rmSync29(join111(out2, d2), { recursive: true, force: true });
|
|
@@ -184675,12 +185279,19 @@ async function collectOneApp(input, deps = {}) {
|
|
|
184675
185279
|
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
184676
185280
|
const maxBytes = boundedSetting(deps.maxResponseBytes, MAX_RESPONSE_BYTES);
|
|
184677
185281
|
const timeoutMs = boundedSetting(deps.timeoutMs, TIMEOUT_MS3);
|
|
185282
|
+
const credentials = /* @__PURE__ */ new Set([input.authorization]);
|
|
185283
|
+
let internalBusinessRead = false;
|
|
184678
185284
|
function redact(value2) {
|
|
185285
|
+
const secrets = [...credentials].sort((a2, b2) => b2.length - a2.length);
|
|
185286
|
+
const redactString = (value3) => {
|
|
185287
|
+
for (const credential of secrets) value3 = value3.split(credential).join("[REDACTED]");
|
|
185288
|
+
return value3;
|
|
185289
|
+
};
|
|
184679
185290
|
const visit = (item) => {
|
|
184680
|
-
if (typeof item === "string") return item
|
|
185291
|
+
if (typeof item === "string") return redactString(item);
|
|
184681
185292
|
if (Array.isArray(item)) return item.map(visit);
|
|
184682
185293
|
if (isObject2(item)) return Object.fromEntries(Object.entries(item).map(([key3, child]) => [
|
|
184683
|
-
key3
|
|
185294
|
+
redactString(key3),
|
|
184684
185295
|
visit(child)
|
|
184685
185296
|
]));
|
|
184686
185297
|
return item;
|
|
@@ -184695,19 +185306,23 @@ async function collectOneApp(input, deps = {}) {
|
|
|
184695
185306
|
throw new OneAppError("artifact_write_failed", "Could not save the collected source evidence.", { stage });
|
|
184696
185307
|
}
|
|
184697
185308
|
}
|
|
184698
|
-
async function request(url, stage, body,
|
|
185309
|
+
async function request(url, stage, body, context = {}) {
|
|
185310
|
+
const { platform, instance } = context;
|
|
184699
185311
|
const controller = new AbortController();
|
|
184700
185312
|
let timedOut = false;
|
|
184701
185313
|
let timer;
|
|
184702
185314
|
const headers2 = {
|
|
184703
|
-
Authorization: input.authorization,
|
|
184704
|
-
"wix-site-id": input.metaSiteId,
|
|
185315
|
+
Authorization: context.authorization ?? input.authorization,
|
|
184705
185316
|
Accept: "application/json"
|
|
184706
185317
|
};
|
|
185318
|
+
if (context.siteScoped !== false) headers2["wix-site-id"] = input.metaSiteId;
|
|
184707
185319
|
if (body !== void 0) headers2["Content-Type"] = "application/json";
|
|
185320
|
+
if (instance && !platform) {
|
|
185321
|
+
headers2["x-wix-mobile-app-version"] = `${sourceApp(instance)}/1.0.0`;
|
|
185322
|
+
}
|
|
184708
185323
|
if (platform) {
|
|
184709
185324
|
headers2.isAndroid = String(platform === "android");
|
|
184710
|
-
headers2.isVisitor =
|
|
185325
|
+
headers2.isVisitor = String(context.visitor ?? false);
|
|
184711
185326
|
headers2.os = platform;
|
|
184712
185327
|
headers2.mobile_app_type = instance === "branded" ? "branded" : "places";
|
|
184713
185328
|
}
|
|
@@ -184780,6 +185395,38 @@ async function collectOneApp(input, deps = {}) {
|
|
|
184780
185395
|
clearTimeout(timer);
|
|
184781
185396
|
}
|
|
184782
185397
|
}
|
|
185398
|
+
async function readBusiness(url, instance) {
|
|
185399
|
+
try {
|
|
185400
|
+
return await request(url.href, "business");
|
|
185401
|
+
} catch (error) {
|
|
185402
|
+
if (!input.allowInternalBusinessRead || !(error instanceof OneAppError) || error.code !== "source_forbidden") throw error;
|
|
185403
|
+
try {
|
|
185404
|
+
const info4 = await request(TOKEN_INFO, "business_authorization", { token: input.authorization });
|
|
185405
|
+
if (!isObject2(info4) || info4.active !== true || info4.subjectType !== "USER" || typeof info4.subjectId !== "string" || !info4.subjectId.trim() || typeof info4.siteId !== "string" || info4.siteId.toLowerCase() !== input.metaSiteId.toLowerCase()) throw error;
|
|
185406
|
+
const contexts = [
|
|
185407
|
+
{ organizationContext: {} },
|
|
185408
|
+
{ siteContext: { metasiteId: input.metaSiteId } }
|
|
185409
|
+
];
|
|
185410
|
+
for (const resourceContext of contexts) {
|
|
185411
|
+
const permission = await request(IS_PERMITTED, "business_authorization", { permission: INTERNAL_PERMISSION, resourceContext });
|
|
185412
|
+
if (!isObject2(permission) || permission.isPermitted !== true) throw error;
|
|
185413
|
+
}
|
|
185414
|
+
} catch {
|
|
185415
|
+
throw error;
|
|
185416
|
+
}
|
|
185417
|
+
const visitorUrl = new URL(url);
|
|
185418
|
+
visitorUrl.pathname = visitorUrl.pathname.replace("/user/businesses/", "/visitor/businesses/");
|
|
185419
|
+
internalBusinessRead = true;
|
|
185420
|
+
return request(visitorUrl.href, "business", void 0, { instance });
|
|
185421
|
+
}
|
|
185422
|
+
}
|
|
185423
|
+
async function enrichmentAuthorization() {
|
|
185424
|
+
if (!internalBusinessRead) return input.authorization;
|
|
185425
|
+
const session = await request(`${VISITOR_SESSION}${input.metaSiteId}/signed-instance?signed_instance_type=Visitor`, "enrichment_session", void 0, { siteScoped: false });
|
|
185426
|
+
if (!isObject2(session) || session.signedInstanceType !== "Visitor" || typeof session.signedInstance !== "string" || !session.signedInstance.trim() || /[\r\n]/.test(session.signedInstance) || typeof session.validUntil !== "string" || !Number.isFinite(Date.parse(session.validUntil)) || Date.parse(session.validUntil) <= (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime()) throw invalidResponse("enrichment_session");
|
|
185427
|
+
credentials.add(session.signedInstance);
|
|
185428
|
+
return session.signedInstance;
|
|
185429
|
+
}
|
|
184783
185430
|
const rawUrl = structureUrl("published-structure", input.metaSiteId, requested);
|
|
184784
185431
|
const originalRaw = validateStructure(await request(rawUrl, "published", {}), "published");
|
|
184785
185432
|
const baseline = semanticFingerprint(originalRaw);
|
|
@@ -184791,7 +185438,7 @@ async function collectOneApp(input, deps = {}) {
|
|
|
184791
185438
|
await progress("raw-structure", rawStructure);
|
|
184792
185439
|
const businessUrl = new URL(`${BUSINESS}${input.metaSiteId}`);
|
|
184793
185440
|
businessUrl.searchParams.set("forApp", sourceApp(resolved2));
|
|
184794
|
-
const projected = businessProjection(await
|
|
185441
|
+
const projected = businessProjection(await readBusiness(businessUrl, resolved2), input.metaSiteId);
|
|
184795
185442
|
const businessContext = redact(projected.context);
|
|
184796
185443
|
await progress("business-context", businessContext);
|
|
184797
185444
|
const enrichBody = {
|
|
@@ -184800,8 +185447,14 @@ async function collectOneApp(input, deps = {}) {
|
|
|
184800
185447
|
...projected.title ? { businessTitle: redact(projected.title) } : {}
|
|
184801
185448
|
};
|
|
184802
185449
|
const enrichUrl = structureUrl("v2/structure-enriched", input.metaSiteId, resolved2);
|
|
185450
|
+
const authorization = await enrichmentAuthorization();
|
|
184803
185451
|
const enrich = async (platform) => {
|
|
184804
|
-
const structure = validateStructure(await request(enrichUrl, `enriched_${platform}`, enrichBody,
|
|
185452
|
+
const structure = validateStructure(await request(enrichUrl, `enriched_${platform}`, enrichBody, {
|
|
185453
|
+
platform,
|
|
185454
|
+
instance: resolved2,
|
|
185455
|
+
authorization,
|
|
185456
|
+
visitor: internalBusinessRead
|
|
185457
|
+
}), `enriched_${platform}`, true);
|
|
184805
185458
|
if (structure.appInstance !== rawStructure.appInstance) {
|
|
184806
185459
|
throw new OneAppError("source_changed", "The source app changed during collection. Run the command again.", { stage: `enriched_${platform}` });
|
|
184807
185460
|
}
|
|
@@ -184813,11 +185466,11 @@ async function collectOneApp(input, deps = {}) {
|
|
|
184813
185466
|
const enriched = {};
|
|
184814
185467
|
const contextWarnings = [];
|
|
184815
185468
|
for (const [index, platform] of ["ios", "android"].entries()) {
|
|
184816
|
-
const
|
|
184817
|
-
if (
|
|
184818
|
-
enriched[platform] =
|
|
185469
|
+
const snapshot3 = snapshots[index];
|
|
185470
|
+
if (snapshot3.status === "fulfilled") {
|
|
185471
|
+
enriched[platform] = snapshot3.value;
|
|
184819
185472
|
} else {
|
|
184820
|
-
const error =
|
|
185473
|
+
const error = snapshot3.reason;
|
|
184821
185474
|
if (!(error instanceof OneAppError) || ![
|
|
184822
185475
|
"source_not_found",
|
|
184823
185476
|
"source_request_failed",
|
|
@@ -184845,24 +185498,28 @@ async function collectOneApp(input, deps = {}) {
|
|
|
184845
185498
|
sourceApp: sourceApp(resolved2),
|
|
184846
185499
|
fallback: requested !== resolved2,
|
|
184847
185500
|
fetchedAt: (deps.now ?? (() => /* @__PURE__ */ new Date()))().toISOString(),
|
|
184848
|
-
context: { locale: "en", shell: resolved2 === "branded" ? "branded" : "places", platforms: ["ios", "android"], identity: "user", productionRules: "not-collected" }
|
|
185501
|
+
context: { locale: "en", shell: resolved2 === "branded" ? "branded" : "places", platforms: ["ios", "android"], identity: internalBusinessRead ? "visitor" : "user", productionRules: "not-collected" }
|
|
184849
185502
|
},
|
|
184850
185503
|
rawStructure,
|
|
184851
185504
|
enriched,
|
|
184852
185505
|
businessContext,
|
|
184853
185506
|
warnings: [
|
|
184854
185507
|
{ code: "runtime_rules_unavailable", message: "Engine production rules were not collected. Empty rule input does not establish that the source has no restrictions." },
|
|
184855
|
-
{ code: "viewer_context", message: "Enrichment shows English iOS and Android views for a Wix user. Preserve authored raw access rules; this view does not establish visitor or member access." },
|
|
185508
|
+
{ code: "viewer_context", message: internalBusinessRead ? "Enrichment shows English iOS and Android visitor views. Preserve authored raw access rules; this view does not establish member or manager access." : "Enrichment shows English iOS and Android views for a Wix user. Preserve authored raw access rules; this view does not establish visitor or member access." },
|
|
184856
185509
|
...contextWarnings
|
|
184857
185510
|
]
|
|
184858
185511
|
};
|
|
184859
185512
|
}
|
|
184860
|
-
var MIDDLEWARE, BUSINESS, MAX_RESPONSE_BYTES, TIMEOUT_MS3, UUID, LIFECYCLE_FIELDS;
|
|
185513
|
+
var MIDDLEWARE, BUSINESS, TOKEN_INFO, IS_PERMITTED, INTERNAL_PERMISSION, VISITOR_SESSION, MAX_RESPONSE_BYTES, TIMEOUT_MS3, UUID, LIFECYCLE_FIELDS;
|
|
184861
185514
|
var init_collect = __esm({
|
|
184862
185515
|
"src/one-app/collect.ts"() {
|
|
184863
185516
|
init_errors2();
|
|
184864
185517
|
MIDDLEWARE = "https://manage.wix.com/_serverless/mobile-apps-editor-middleware";
|
|
184865
185518
|
BUSINESS = "https://apps.wix.com/_api/app-state/v1/user/businesses/";
|
|
185519
|
+
TOKEN_INFO = "https://www.wixapis.com/oauth2/token-info";
|
|
185520
|
+
IS_PERMITTED = "https://www.wixapis.com/authorization-server/v1/authorization/is_permitted";
|
|
185521
|
+
INTERNAL_PERMISSION = "BRANDED_APPS.MANAGE_INTERNAL";
|
|
185522
|
+
VISITOR_SESSION = "https://apps.wix.com/_api/one-app-session-web/v3/businesses/";
|
|
184866
185523
|
MAX_RESPONSE_BYTES = 8e6;
|
|
184867
185524
|
TIMEOUT_MS3 = 3e4;
|
|
184868
185525
|
UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -185222,7 +185879,8 @@ validate-topbar checks authored source top-bar controls against the migrated con
|
|
|
185222
185879
|
const collected = await (deps.collect ?? collectOneApp)({
|
|
185223
185880
|
metaSiteId: options.metaSiteId,
|
|
185224
185881
|
appInstance: options.appInstance,
|
|
185225
|
-
authorization: token
|
|
185882
|
+
authorization: token,
|
|
185883
|
+
allowInternalBusinessRead: true
|
|
185226
185884
|
}, {
|
|
185227
185885
|
fetchImpl: deps.fetchImpl,
|
|
185228
185886
|
onProgress: (completedStage, value2) => {
|
|
@@ -187293,7 +187951,7 @@ var init_customer_build = __esm({
|
|
|
187293
187951
|
});
|
|
187294
187952
|
|
|
187295
187953
|
// src/site-analyze/apply.ts
|
|
187296
|
-
import { existsSync as
|
|
187954
|
+
import { existsSync as existsSync104, readFileSync as readFileSync121, writeFileSync as writeFileSync47, copyFileSync as copyFileSync2, mkdirSync as mkdirSync48, realpathSync as realpathSync15, statSync as statSync27 } from "node:fs";
|
|
187297
187955
|
import { dirname as dirname55, isAbsolute as isAbsolute9, join as join115, resolve as resolve79, sep as sep21 } from "node:path";
|
|
187298
187956
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
187299
187957
|
function unpairedRedirectNote(overlay) {
|
|
@@ -187309,7 +187967,7 @@ function committedShellProvisioning(path2) {
|
|
|
187309
187967
|
function findRepoRoot(cwd) {
|
|
187310
187968
|
let dir = cwd;
|
|
187311
187969
|
for (let i2 = 0; i2 < 8; i2++) {
|
|
187312
|
-
if (SHELL_NAMES.some((name) =>
|
|
187970
|
+
if (SHELL_NAMES.some((name) => existsSync104(join115(dir, shellAppDir(name), "package.json")))) return dir;
|
|
187313
187971
|
const next = dirname55(dir);
|
|
187314
187972
|
if (next === dir) break;
|
|
187315
187973
|
dir = next;
|
|
@@ -187413,7 +188071,7 @@ function sameKnownSite(previous, next) {
|
|
|
187413
188071
|
function buildMergedContract(options) {
|
|
187414
188072
|
const { appDir: appDir3, packageDir, overlay } = options;
|
|
187415
188073
|
const committedPath = join115(appDir3, "provisioning.json");
|
|
187416
|
-
if (!
|
|
188074
|
+
if (!existsSync104(committedPath)) {
|
|
187417
188075
|
throw new Error(`shell has no committed provisioning.json at ${committedPath} to build a contract from`);
|
|
187418
188076
|
}
|
|
187419
188077
|
const committed = JSON.parse(readFileSync121(committedPath, "utf8"));
|
|
@@ -187429,7 +188087,7 @@ function buildMergedContract(options) {
|
|
|
187429
188087
|
const stage = (fromRel, toRel) => {
|
|
187430
188088
|
const from = contained(packageDir, fromRel);
|
|
187431
188089
|
const to2 = contained(join115(appDir3, STAGED), toRel.slice(STAGED.length + 1));
|
|
187432
|
-
if (!from || !to2 || !
|
|
188090
|
+
if (!from || !to2 || !existsSync104(from)) return void 0;
|
|
187433
188091
|
let real;
|
|
187434
188092
|
let realRoot;
|
|
187435
188093
|
try {
|
|
@@ -187452,7 +188110,7 @@ function buildMergedContract(options) {
|
|
|
187452
188110
|
const icon = stage("media/icon.png", `${STAGED}/icon.png`);
|
|
187453
188111
|
if (icon) branding.appIconPath = icon;
|
|
187454
188112
|
const facesPath = join115(packageDir, "media/fonts/faces.json");
|
|
187455
|
-
if (
|
|
188113
|
+
if (existsSync104(facesPath)) {
|
|
187456
188114
|
let faces = [];
|
|
187457
188115
|
try {
|
|
187458
188116
|
const parsed = JSON.parse(readFileSync121(facesPath, "utf8"));
|
|
@@ -187514,7 +188172,7 @@ function staticFaqFor(overlay, overlayPath) {
|
|
|
187514
188172
|
const own6 = overlay.faq;
|
|
187515
188173
|
if (own6 !== void 0) return deriveStaticFaq(own6);
|
|
187516
188174
|
const bookPath = join115(dirname55(resolve79(overlayPath)), "book.json");
|
|
187517
|
-
if (!
|
|
188175
|
+
if (!existsSync104(bookPath)) return void 0;
|
|
187518
188176
|
try {
|
|
187519
188177
|
const book = JSON.parse(readFileSync121(bookPath, "utf8"));
|
|
187520
188178
|
const copy = book?.copy;
|
|
@@ -187531,7 +188189,7 @@ function staticGalleriesFor(overlay, overlayPath) {
|
|
|
187531
188189
|
overlay.galleries.map((gallery) => ({ role: "gallery", title: gallery.title, galleryImageUrls: gallery.photos }))
|
|
187532
188190
|
);
|
|
187533
188191
|
const bookPath = join115(dirname55(resolve79(overlayPath)), "book.json");
|
|
187534
|
-
if (!
|
|
188192
|
+
if (!existsSync104(bookPath)) return void 0;
|
|
187535
188193
|
try {
|
|
187536
188194
|
const book = JSON.parse(readFileSync121(bookPath, "utf8"));
|
|
187537
188195
|
if (!book.look || book.look.unavailable || !Array.isArray(book.look.pages)) return void 0;
|
|
@@ -187565,7 +188223,7 @@ async function applyOverlays(input) {
|
|
|
187565
188223
|
}
|
|
187566
188224
|
const appDir3 = join115(repoRoot2, shellAppDir(shell));
|
|
187567
188225
|
const committedPath = join115(appDir3, "provisioning.json");
|
|
187568
|
-
const committedSite =
|
|
188226
|
+
const committedSite = existsSync104(committedPath) ? JSON.parse(readFileSync121(committedPath, "utf8")).site : void 0;
|
|
187569
188227
|
if (committedSite !== void 0 && overlay.site === void 0) {
|
|
187570
188228
|
throw new Error(
|
|
187571
188229
|
`shell "${shell}" is a site shell: its contract names the customer's website (a \`site\` block), and this overlay has none. Re-run \`himi site analyze --url <site> --shell ${shell}\` to derive the site's page map (edit \`site.pages\` in provisioning.overlay.json if needed), then --apply.`
|
|
@@ -187606,7 +188264,7 @@ async function applyOverlays(input) {
|
|
|
187606
188264
|
};
|
|
187607
188265
|
let packageFaq = faq;
|
|
187608
188266
|
let packageGalleries = galleries;
|
|
187609
|
-
if (
|
|
188267
|
+
if (existsSync104(pkgProv)) {
|
|
187610
188268
|
const cur = JSON.parse(readFileSync121(pkgProv, "utf8"));
|
|
187611
188269
|
if (galleries === void 0 && !sameKnownSite(cur, overlay)) overlay.galleries = [];
|
|
187612
188270
|
const merged = deepMerge4(cur, overlay);
|
|
@@ -187624,7 +188282,7 @@ async function applyOverlays(input) {
|
|
|
187624
188282
|
overlay.installedVerticals.push("galleries");
|
|
187625
188283
|
}
|
|
187626
188284
|
const pkgTokens = join115(cwd, "tokens.json");
|
|
187627
|
-
if (
|
|
188285
|
+
if (existsSync104(pkgTokens) && (tokens2.colors || tokens2.typography)) {
|
|
187628
188286
|
const cur = JSON.parse(readFileSync121(pkgTokens, "utf8"));
|
|
187629
188287
|
let tokensIn = tokens2;
|
|
187630
188288
|
if (tokens2.typography) {
|
|
@@ -187651,7 +188309,7 @@ async function applyOverlays(input) {
|
|
|
187651
188309
|
}
|
|
187652
188310
|
const homeAction = homeRefreshActionId(shell);
|
|
187653
188311
|
const homeSrc = join115(cwd, "dev/index.ts");
|
|
187654
|
-
if (homeAction &&
|
|
188312
|
+
if (homeAction && existsSync104(homeSrc)) {
|
|
187655
188313
|
const prev = readFileSync121(homeSrc, "utf8");
|
|
187656
188314
|
const patched = patchBrandParams(prev, overlay, homeAction);
|
|
187657
188315
|
let next = patched.src;
|
|
@@ -187687,13 +188345,13 @@ async function applyOverlays(input) {
|
|
|
187687
188345
|
notes.push(`${patched.unparsed} onAppear params block(s) in ${homeSrc} could not be read \u2014 any brand values inside them were not applied`);
|
|
187688
188346
|
}
|
|
187689
188347
|
}
|
|
187690
|
-
if (!input.iconPath || !
|
|
188348
|
+
if (!input.iconPath || !existsSync104(input.iconPath)) {
|
|
187691
188349
|
const book = input.iconPath ? dirname55(dirname55(resolve79(input.iconPath))) : void 0;
|
|
187692
188350
|
notes.push(
|
|
187693
188351
|
book ? `no icon installed \u2014 ${siteLogoAbsence(book).hint}` : "no icon installed and no business book to say why \u2014 `himi icon generate` draws one from the accent, or `himi icon set <file.png>` installs the customer's own mark"
|
|
187694
188352
|
);
|
|
187695
188353
|
}
|
|
187696
|
-
if (input.iconPath &&
|
|
188354
|
+
if (input.iconPath && existsSync104(input.iconPath)) {
|
|
187697
188355
|
try {
|
|
187698
188356
|
const installed = await installIcon(cwd, input.iconPath, { derivePlay: true });
|
|
187699
188357
|
wrote.push(...installed.wrote);
|
|
@@ -188652,7 +189310,7 @@ __export(cli_exports3, {
|
|
|
188652
189310
|
runSiteAnalyze: () => runSiteAnalyze,
|
|
188653
189311
|
runSiteFunctionCli: () => runSiteFunctionCli
|
|
188654
189312
|
});
|
|
188655
|
-
import { existsSync as
|
|
189313
|
+
import { existsSync as existsSync105, readFileSync as readFileSync122 } from "node:fs";
|
|
188656
189314
|
import { resolve as resolve80 } from "node:path";
|
|
188657
189315
|
function applyNeedsClient(shell) {
|
|
188658
189316
|
if (shell === void 0 || !SHELL_NAMES.includes(shell)) return true;
|
|
@@ -188720,7 +189378,7 @@ async function runSiteAnalyze(opts) {
|
|
|
188720
189378
|
if (book?.skipped) result.warnings = [...result.warnings ?? [], book.skipped];
|
|
188721
189379
|
const derived = deriveSiteShell({ siteUrl: result.book.input.siteUrl, look: result.book.look, kind, routes });
|
|
188722
189380
|
const prevOverlayPath = resolve80(outDir, "provisioning.overlay.json");
|
|
188723
|
-
const prevSite =
|
|
189381
|
+
const prevSite = existsSync105(prevOverlayPath) ? (() => {
|
|
188724
189382
|
try {
|
|
188725
189383
|
return JSON.parse(readFileSync122(prevOverlayPath, "utf8")).site;
|
|
188726
189384
|
} catch {
|
|
@@ -188741,7 +189399,7 @@ async function runSiteAnalyze(opts) {
|
|
|
188741
189399
|
}
|
|
188742
189400
|
const previousOverlay = resolve80(outDir, "provisioning.overlay.json");
|
|
188743
189401
|
carryOverGoals(
|
|
188744
|
-
|
|
189402
|
+
existsSync105(previousOverlay) ? readFileSync122(previousOverlay, "utf8") : void 0,
|
|
188745
189403
|
result.provisioningOverlay
|
|
188746
189404
|
);
|
|
188747
189405
|
const ownerCall = ownerAuth ? ownerTransportFrom(fetchImpl, ownerAuth) : void 0;
|
|
@@ -188827,7 +189485,7 @@ async function runSiteFunctionCli(opts) {
|
|
|
188827
189485
|
});
|
|
188828
189486
|
}
|
|
188829
189487
|
function base44BookRoutes(bookPath, siteUrl) {
|
|
188830
|
-
if (!
|
|
189488
|
+
if (!existsSync105(bookPath)) return void 0;
|
|
188831
189489
|
try {
|
|
188832
189490
|
const book = JSON.parse(readFileSync122(bookPath, "utf8"));
|
|
188833
189491
|
if (book.kind !== "base44-app-book" || !Array.isArray(book.routes)) return void 0;
|
|
@@ -189084,7 +189742,7 @@ __export(site_create_exports, {
|
|
|
189084
189742
|
runSiteList: () => runSiteList,
|
|
189085
189743
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
189086
189744
|
});
|
|
189087
|
-
import { existsSync as
|
|
189745
|
+
import { existsSync as existsSync106, readFileSync as readFileSync123, writeFileSync as writeFileSync48 } from "node:fs";
|
|
189088
189746
|
import { resolve as resolvePath2 } from "node:path";
|
|
189089
189747
|
function oauthClientName(projectName) {
|
|
189090
189748
|
return `${projectName} client`;
|
|
@@ -189233,7 +189891,7 @@ async function runSiteCreate(opts) {
|
|
|
189233
189891
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
189234
189892
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
189235
189893
|
}
|
|
189236
|
-
function writeProvisioningBinding(target, binding2, fs2 = { existsSync:
|
|
189894
|
+
function writeProvisioningBinding(target, binding2, fs2 = { existsSync: existsSync106, readFileSync: readFileSync123, writeFileSync: writeFileSync48 }) {
|
|
189237
189895
|
const msid = binding2.siteId;
|
|
189238
189896
|
const path2 = resolvePath2(target);
|
|
189239
189897
|
const committed = committedShellProvisioning(path2);
|
|
@@ -190012,7 +190670,7 @@ __export(capture_exports, {
|
|
|
190012
190670
|
nativeNotConfigured: () => nativeNotConfigured,
|
|
190013
190671
|
variantWidth: () => variantWidth
|
|
190014
190672
|
});
|
|
190015
|
-
import { existsSync as
|
|
190673
|
+
import { existsSync as existsSync107, mkdirSync as mkdirSync49, rmSync as rmSync31, writeFileSync as writeFileSync49 } from "node:fs";
|
|
190016
190674
|
import { join as join116 } from "node:path";
|
|
190017
190675
|
import { pathToFileURL as pathToFileURL8 } from "node:url";
|
|
190018
190676
|
function variantWidth(variant) {
|
|
@@ -190025,7 +190683,7 @@ function frameFile(outDir, screen, variant, surface) {
|
|
|
190025
190683
|
async function captureMockup(root, screen, entry, variant, outDir, session) {
|
|
190026
190684
|
if (!entry.mockup) throw new MockupMissingError(`screen ${screen} declares no mockup in hhp.json`);
|
|
190027
190685
|
const file2 = localPath(root, entry.mockup);
|
|
190028
|
-
if (!
|
|
190686
|
+
if (!existsSync107(file2)) throw new MockupMissingError(`screen ${screen}: mockup ${entry.mockup} does not exist`);
|
|
190029
190687
|
const own6 = session ?? new MockupSession();
|
|
190030
190688
|
try {
|
|
190031
190689
|
const png = await own6.shoot(file2, variant);
|
|
@@ -190333,8 +190991,8 @@ var init_score = __esm({
|
|
|
190333
190991
|
});
|
|
190334
190992
|
|
|
190335
190993
|
// ../visual-proof/evidence.mjs
|
|
190336
|
-
import { existsSync as
|
|
190337
|
-
function resolveCaptionFont({ exists =
|
|
190994
|
+
import { existsSync as existsSync108, rmSync as rmSync34 } from "node:fs";
|
|
190995
|
+
function resolveCaptionFont({ exists = existsSync108, env = process.env } = {}) {
|
|
190338
190996
|
if (env?.VISUAL_PROOF_FONT) return env.VISUAL_PROOF_FONT;
|
|
190339
190997
|
return CAPTION_FONT_CANDIDATES.find((p2) => exists(p2)) ?? null;
|
|
190340
190998
|
}
|
|
@@ -190587,7 +191245,7 @@ __export(fidelity_exports, {
|
|
|
190587
191245
|
himalayaRepoRoot: () => himalayaRepoRoot
|
|
190588
191246
|
});
|
|
190589
191247
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
190590
|
-
import { existsSync as
|
|
191248
|
+
import { existsSync as existsSync109, realpathSync as realpathSync16 } from "node:fs";
|
|
190591
191249
|
import { join as join121, relative as relative19, sep as sep22 } from "node:path";
|
|
190592
191250
|
function himalayaRepoRoot(dir) {
|
|
190593
191251
|
let top;
|
|
@@ -190596,7 +191254,7 @@ function himalayaRepoRoot(dir) {
|
|
|
190596
191254
|
} catch {
|
|
190597
191255
|
return null;
|
|
190598
191256
|
}
|
|
190599
|
-
if (!
|
|
191257
|
+
if (!existsSync109(join121(top, "tools/judges/fidelity/JUDGE.md"))) return null;
|
|
190600
191258
|
const rel = relative19(realpathSync16(top), realpathSync16(dir));
|
|
190601
191259
|
return rel.startsWith(`..${sep22}`) || rel === ".." ? null : top;
|
|
190602
191260
|
}
|
|
@@ -190606,7 +191264,7 @@ function fidelityEnvelope(report3) {
|
|
|
190606
191264
|
async function fidelityCommand(ctx) {
|
|
190607
191265
|
const { io: io2, flags, print } = ctx;
|
|
190608
191266
|
const dir = contentDir(flags);
|
|
190609
|
-
if (!
|
|
191267
|
+
if (!existsSync109(dir)) {
|
|
190610
191268
|
io2.error(failure("fidelity_bad_flag", `content dir ${dir} does not exist`));
|
|
190611
191269
|
return 2;
|
|
190612
191270
|
}
|
|
@@ -190780,8 +191438,11 @@ var ServeCliClient = class {
|
|
|
190780
191438
|
fetchTokens(app, release2) {
|
|
190781
191439
|
return this.request("serve", "GET", `/v1/tokens?app=${encodeURIComponent(app)}${this.pinQ(release2)}`);
|
|
190782
191440
|
}
|
|
190783
|
-
|
|
190784
|
-
|
|
191441
|
+
/** A pinned non-live [release] on a deployed plane needs [previewToken] (see `fetchScreen`). */
|
|
191442
|
+
fetchAppConfig(app, release2, previewToken) {
|
|
191443
|
+
return this.request("serve", "GET", `/v1/app-config/${encodeURIComponent(app)}${release2 ? `?release=${encodeURIComponent(release2)}` : ""}`, {
|
|
191444
|
+
...previewToken ? { headers: { "x-himalaya-preview-token": previewToken } } : {}
|
|
191445
|
+
});
|
|
190785
191446
|
}
|
|
190786
191447
|
fetchBundle(app, hash2) {
|
|
190787
191448
|
return this.request("serve", "GET", `/v1/bundles/${hash2}.bundle.js?app=${encodeURIComponent(app)}`);
|
|
@@ -191322,7 +191983,8 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
191322
191983
|
"empty-app-ok",
|
|
191323
191984
|
"aab",
|
|
191324
191985
|
"managed",
|
|
191325
|
-
"source-hash"
|
|
191986
|
+
"source-hash",
|
|
191987
|
+
"skip-captcha-check"
|
|
191326
191988
|
]);
|
|
191327
191989
|
var SWITCH_FLAGS = new Set([...BOOLEAN_FLAGS].filter((name) => name !== "deep"));
|
|
191328
191990
|
var SWITCH_CONSEQUENCE = {
|
|
@@ -192232,7 +192894,7 @@ var COMMANDS = [
|
|
|
192232
192894
|
{ name: "patch", summary: 'change ONE item of a published app \u2014 a screen descriptor, a Tier-5 bundle, tokens, or the app-config baseline \u2014 from a RAW FILE, with no content package and no build. The low-level door: it does not lint your package, because there is no package here; `himi push --only <selector>` is the same edit with the full build + lint gate and is what to reach for when the package is in hand. Derives a new release from the app\'s current LIVE release, or from `--from-release <id>`. An explicit `--draft` or `--live` is REQUIRED \u2014 a patch has no default blast radius \u2014 and `--notes` is required with `--live` on a screen or app-config patch, because off-repo `gitSha` is "dev" and the ledger notes are then the only durable record of bytes that correspond to no commit. A branch does not merge: activating one derived from an older release reverts every item the patch does not move, so that case is refused until `--accept-regressions`. A bundle patch must repoint a screen (`--for-screen`) or the bytes land under a manifest key nothing reads. It cannot ADD a screen (screens are git-only, RFC 0012), never claims a slug \u2014 the app must already be published \u2014 and carries no attestation, source archive, assets, icon or minBinaryVersion, each named in the output.', required: "screen <id> --file <descriptor.json> [--bundle <sha256|none>] | bundle --file <bundle.js> (--for-screen <id>[,<id>] | --no-rebind) | tokens --file <tokens.json> | app-config --file <app-config.json> ; (--draft|--live) --app <a> [--from-release <id>] [--accept-regressions] [--label <n>] [--notes <t>] [--force] [--allow-binary-gap] [--target <t>] (--control-token)" },
|
|
192233
192895
|
{ name: "flags", summary: "read and change the app's OPERATIONAL flags (RFC 0013) \u2014 `list` prints what the DEVICE door serves, `set <key> --definition` creates or replaces one, `ramp <key>` moves its rollout share or kills it, `rm <key>` deletes it and echoes the definition back so the removal is reversible. Every write is followed by a read of the same door the device uses, and the answer is reported as `servedNow`: flags are stored in the app's git-committed flags.json, so a control plane with no checkout accepts a write it will never serve.", required: "list|set|ramp|rm [<key>] [--definition <json|@file>] [--percent 0-100] [--enabled true|false] [--app <a>] (--control-token)" },
|
|
192234
192896
|
{ name: "visibility", summary: "read (no value) or set whether the public registry (/v1/apps + the Himi Player picker) LISTS the app. `public` lists it for everyone; `unlisted` hides it from listings while direct reads by app id \u2014 deep links, previews \u2014 keep working. App from --app or the content dir. Setting it needs no republish.", required: "[public|unlisted] [--app <a>] [--content <dir>] (--control-token)" },
|
|
192235
|
-
{ name: "dist", summary: "build an INSTALLABLE QA binary (signed IPA / APK) on the Wix Job Service Mac pool and return an install link \u2014 the serve plane brokers the job, the pool builds it. WAITS for the build by default (~4 min) and prints the install link; `--no-wait` returns a jobId immediately instead. Omitting `--release` builds whatever is LIVE for the app. A named draft is refused unless `--allow-draft` makes that exceptional build explicit. `status <jobId>` / `watch <jobId>` / `list --app <a>` / `cancel <jobId>` inspect and stop builds (`watch` reports up front whether the job mints its own signing identity or borrows one, so a doomed iOS build is cancellable in seconds rather than after the archive). Off-repo, name a target \u2014 `--target wix` for a self-serve Wix login or `--target bo` for the internal employee path (the in-repo default is a local dev plane that isn't reachable off-repo); self-serve callers may build their OWN apps under a tighter budget (2 in flight / 5 per 24h), while a manage-only owner-role credential is refused. `--shell` picks the native host to sign into (branded-lite | owner-lite | brandy | base44 | player | demo-app) and defaults to the content package's himalaya.content.json `shell` (templates carry the one they were written for), else branded-lite. The per-app shells ADD the release's declared capabilities to the binary, while Himi Player and demo-app refuse a release declaring one they lack; `--plan` previews it without building; `brandy` is the site shell \u2014 the customer's own website as native-framed tabs. `--signing` defaults to `wix-managed` \u2014 the Wix Apple account mints a per-app signing identity for the build, so the caller provisions no Apple credentials of their own; `--signing byo --site <id>` reuses an existing customer ad-hoc profile and certificate for iOS; requires an owned site and a completed personal signing binding. `--android-signing` is the Android counterpart and a SEPARATE axis (a keystore, not an Apple account): `qa-keystore` (default \u2014 the repo's committed QA key, identical on every pool machine, so a build installs over the previous one), `wix-keystore` (the Wix key the pool machine carries; the build FAILS naming the paths searched if it carries none, rather than quietly signing with something else), or `debug` (the old per-machine key \u2014 QA must uninstall any previous build first). `--aab` builds an Android App Bundle (.aab) for the owner to upload to Google Play AND an APK from the same build \u2014 a download link for the .aab, an install link and QR for the APK; Android only; the bundle is signed with the Wix production key (`wix-keystore`, the upload key Branded apps use) \u2014 any other `--android-signing` is refused \u2014 and the APK with the committed QA key; a self-serve caller gets one only as the store build of its own Containers app (it must own the app's site, and `--aab` sends your Wix login); any other self-serve `--aab` gets 403 android_format_not_allowed. NOT the normal way to ship: screens, Tier-5 bundles, tokens and app-config all go over the air with `himi push` in seconds \u2014 a binary trip is only needed for a NATIVE delta (a new SDUI component, a new declared capability/entitlement, a new bundle id, or a minBinaryVersion floor bump). Refuses to build an app whose launcher icon is missing, a placeholder, or one a store would reject \u2014 the one thing a binary carries that no later OTA push can fix; `--force` builds anyway", required: "[--app <a>] [--platform ios,android] [--release <id>] [--allow-draft] [--target <t>] [--shell branded-lite|owner-lite|brandy|base44|player|demo-app] [--signing wix-managed|byo] [--site <id>] [--android-signing qa-keystore|wix-keystore|debug] [--aab] [--borrow-ios-id <bundleId>] [--no-wait] [--force] [--plan] | status <jobId> [--target <t>] | watch <jobId> [--target <t>] [--interval <ms>] | list --app <a> [--target <t>] | cancel <jobId> [--target <t>]" },
|
|
192897
|
+
{ name: "dist", summary: "build an INSTALLABLE QA binary (signed IPA / APK) on the Wix Job Service Mac pool and return an install link \u2014 the serve plane brokers the job, the pool builds it. WAITS for the build by default (~4 min) and prints the install link; `--no-wait` returns a jobId immediately instead. Omitting `--release` builds whatever is LIVE for the app. A named draft is refused unless `--allow-draft` makes that exceptional build explicit. `status <jobId>` / `watch <jobId>` / `list --app <a>` / `cancel <jobId>` inspect and stop builds (`watch` reports up front whether the job mints its own signing identity or borrows one, so a doomed iOS build is cancellable in seconds rather than after the archive). Off-repo, name a target \u2014 `--target wix` for a self-serve Wix login or `--target bo` for the internal employee path (the in-repo default is a local dev plane that isn't reachable off-repo); self-serve callers may build their OWN apps under a tighter budget (2 in flight / 5 per 24h), while a manage-only owner-role credential is refused. `--shell` picks the native host to sign into (branded-lite | owner-lite | brandy | base44 | player | demo-app) and defaults to the content package's himalaya.content.json `shell` (templates carry the one they were written for), else branded-lite. The per-app shells ADD the release's declared capabilities to the binary, while Himi Player and demo-app refuse a release declaring one they lack; `--plan` previews it without building; `brandy` is the site shell \u2014 the customer's own website as native-framed tabs. `--signing` defaults to `wix-managed` \u2014 the Wix Apple account mints a per-app signing identity for the build, so the caller provisions no Apple credentials of their own; `--signing byo --site <id>` reuses an existing customer ad-hoc profile and certificate for iOS; requires an owned site and a completed personal signing binding. `--android-signing` is the Android counterpart and a SEPARATE axis (a keystore, not an Apple account): `qa-keystore` (default \u2014 the repo's committed QA key, identical on every pool machine, so a build installs over the previous one), `wix-keystore` (the Wix key the pool machine carries; the build FAILS naming the paths searched if it carries none, rather than quietly signing with something else), or `debug` (the old per-machine key \u2014 QA must uninstall any previous build first). `--aab` builds an Android App Bundle (.aab) for the owner to upload to Google Play AND an APK from the same build \u2014 a download link for the .aab, an install link and QR for the APK; Android only; the bundle is signed with the Wix production key (`wix-keystore`, the upload key Branded apps use) \u2014 any other `--android-signing` is refused \u2014 and the APK with the committed QA key; a self-serve caller gets one only as the store build of its own Containers app (it must own the app's site, and `--aab` sends your Wix login); any other self-serve `--aab` gets 403 android_format_not_allowed. NOT the normal way to ship: screens, Tier-5 bundles, tokens and app-config all go over the air with `himi push` in seconds \u2014 a binary trip is only needed for a NATIVE delta (a new SDUI component, a new declared capability/entitlement, a new bundle id, or a minBinaryVersion floor bump). Refuses to build an app whose launcher icon is missing, a placeholder, or one a store would reject \u2014 the one thing a binary carries that no later OTA push can fix; `--force` builds anyway. Also refuses a release whose member login (WixConsumerAuthProvider) names no siteId, or not in lower case, when Wix says its site requires a member CAPTCHA \u2014 such a binary ships without the CAPTCHA key and every member sign-in fails; whatever it cannot read (the release, the site's setting) only warns and builds; `--skip-captcha-check` builds anyway", required: "[--app <a>] [--platform ios,android] [--release <id>] [--allow-draft] [--target <t>] [--shell branded-lite|owner-lite|brandy|base44|player|demo-app] [--signing wix-managed|byo] [--site <id>] [--android-signing qa-keystore|wix-keystore|debug] [--aab] [--borrow-ios-id <bundleId>] [--no-wait] [--force] [--skip-captcha-check] [--plan] | status <jobId> [--target <t>] | watch <jobId> [--target <t>] [--interval <ms>] | list --app <a> [--target <t>] | cancel <jobId> [--target <t>]" },
|
|
192236
192898
|
{ name: "testflight", summary: 'build, sign and upload an app to TestFlight (internal testers \u2014 no Beta App Review), then WAIT until App Store Connect finishes processing it. Sugar for `store upload --track testflight`. Prompts first: a build number is consumed permanently on a real Apple account and cannot be reused \u2014 `--yes` for CI, `--dry-run` to see the plan without touching anything. The wait is the real check, not a nicety: fastlane prints "Successfully uploaded" for a binary App Store Connect then rejects in processing, and a rejected binary leaves NO build record at all (the reason is emailed). Public App Store review is deliberately NOT automatable here \u2014 `--track appstore` is refused; use /submit-ios-app when you mean to go public', required: "<app> [--track testflight|internal] [--profile <name>] [--yes] [--dry-run] [--skip-build] [--no-wait] [--json]" },
|
|
192237
192899
|
{ name: "store", summary: "the App Store Connect group behind `testflight`. `preflight <app>` checks readiness offline (icon, entitlements, encryption flag, version, store.config ids, listing + review record); `upload <app>` is what `testflight` runs; `status <app>` reads live build + processing state. `--profile` selects WHICH App Store Connect account: an app built for a Wix customer ships under the CUSTOMER's Apple team (Apple guideline 4.2.6 forbids an app-generation service submitting on a client's behalf), declared per-app as ios.credentialProfile in store.config.yaml and resolved from ~/.himalaya/store-credentials/<name>.json \u2014 the .p8 itself never enters the repo. `iap draft|plan|apply|status|connect|screenshots|check|mappings` registers an app owner's digital products as in-app purchases (non-consumables, or consumable price tiers): draft reads the Wix catalog and writes the manifest, plan and status only read, apply is the one App Store mutation boundary, connect readies the Wix site to sell them (purchases app, In-App Purchase key, appleIAP provider, product mappings; --preview-tag routes only its Serve calls to a deploy preview), legacy screenshots --profile renders each product's purchase screen from the app (--content) as a bound iPhone shows it to a signed-in member and names the 1290\xD72796 PNG as the item's App Review screenshot, and none of them builds, signs or needs a checkout (`himi docs iap-products`) IAP provisioning defaults to Catalog; managed apply generates screenshots on the server with no local .p8 or profile fallback; --managed is optional and --profile selects legacy mode; --catalog-route or HIMI_IAP_CATALOG_ROUTE has no default.", required: "preflight <app> [--profile <n>] | upload <app> [--track <t>] [--profile <n>] [--yes] [--dry-run] | status <app> [--profile <n>] | iap draft --site <msid> " + IAP_CREDENTIAL_OPTIONS + " --apple-app <id> --bundle <id> --base-territory <t> --out <f> [--territories <a,b>] [--locale <l>] [--mode per-item|tiers] [--merge <f>] [--report <f>] [--json] | iap plan --manifest <f> " + IAP_CREDENTIAL_OPTIONS + " --out <f> [--json] | iap apply --plan <f> " + IAP_CREDENTIAL_OPTIONS + " --out <f> [--yes] [--limit <n>] [--no-submit] [--json] | iap status --manifest <f> " + IAP_CREDENTIAL_OPTIONS + " [--out <f>] [--json] | iap connect --manifest <f> [--profile <n>] [--catalog-route <prefix>] [--iap-key <AuthKey.p8> --iap-key-id <id>] [--content <dir>] [--preview-tag dp-<tag>] [--dry-run] [--yes] [--out <f>] [--json] | iap screenshots --manifest <f> --content <dir> --profile <n> [--out-dir <d>] [--only <id,\u2026>] [--force] [--dry-run] [--json] | iap check --manifest <f> --catalog-route <prefix> [--purchases-app <id>] [--content <dir>] [--plist <file>] [--visitor-client <id>] [--json] | iap mappings --site <msid> --purchases-app <id> --catalog-route <prefix> [--product <id> --active true|false --yes] [--json]" },
|
|
192238
192900
|
{ name: "guide", summary: "print the Himalaya overview + headless dev loop + available topics (offline)", required: "[--json]" },
|
|
@@ -192843,7 +193505,7 @@ async function hhpCommand(ctx) {
|
|
|
192843
193505
|
// src/commands/init.ts
|
|
192844
193506
|
init_scaffold();
|
|
192845
193507
|
init_store();
|
|
192846
|
-
import { existsSync as
|
|
193508
|
+
import { existsSync as existsSync46 } from "node:fs";
|
|
192847
193509
|
import { join as join44, resolve as resolve43 } from "node:path";
|
|
192848
193510
|
init_cli_shared();
|
|
192849
193511
|
async function adoptAtInit(dir) {
|
|
@@ -192870,7 +193532,7 @@ var NoBase44SlotError = class extends Error {
|
|
|
192870
193532
|
};
|
|
192871
193533
|
async function initFromRemoteTemplate(name, parentDir, template, c2, opts = {}) {
|
|
192872
193534
|
const dir = resolve43(parentDir, name);
|
|
192873
|
-
if (
|
|
193535
|
+
if (existsSync46(join44(dir, "himalaya.content.json"))) {
|
|
192874
193536
|
throw new Error(`content package already exists at ${dir}`);
|
|
192875
193537
|
}
|
|
192876
193538
|
const r3 = await c2.fetchTemplateSource(TEMPLATE_APP_PREFIX + template);
|
|
@@ -192946,7 +193608,7 @@ async function initCommand(ctx) {
|
|
|
192946
193608
|
const owed = openApprovals2(readApprovals2(dir).events).length;
|
|
192947
193609
|
next.push(`carried the planning journal into the app (${carried.join(", ")}${owed ? `; ${owed} approval${owed === 1 ? "" : "s"} still owed` : ""}) \u2014 \`himi progress --brief\` there shows it`);
|
|
192948
193610
|
}
|
|
192949
|
-
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) =>
|
|
193611
|
+
const planInParent = ["SPEC.md", "MOBILE-UX.md"].filter((f2) => existsSync46(join44(parentDir, f2)));
|
|
192950
193612
|
if (planInParent.length) {
|
|
192951
193613
|
next.push(`${planInParent.join(" and ")} in ${parentDir} ${planInParent.length > 1 ? "are" : "is"} not the app's \u2014 if that is the approved plan, move it over the template's boilerplate in ${dir}`);
|
|
192952
193614
|
}
|
|
@@ -193013,7 +193675,7 @@ ${doNow.map((l2) => ` ${l2}`).join("\n")}`);
|
|
|
193013
193675
|
}
|
|
193014
193676
|
|
|
193015
193677
|
// src/commands/template.ts
|
|
193016
|
-
import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync67, existsSync as
|
|
193678
|
+
import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync67, existsSync as existsSync58, rmSync as rmSync16 } from "node:fs";
|
|
193017
193679
|
import { createHash as createHash30 } from "node:crypto";
|
|
193018
193680
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
193019
193681
|
import { join as join57, resolve as resolve46, basename as basename15 } from "node:path";
|
|
@@ -193080,7 +193742,7 @@ async function cmsIssues(dir, app, strict, opts) {
|
|
|
193080
193742
|
// src/surface-lint.ts
|
|
193081
193743
|
init_car();
|
|
193082
193744
|
init_preview_surfaces();
|
|
193083
|
-
import { existsSync as
|
|
193745
|
+
import { existsSync as existsSync47, readFileSync as readFileSync55 } from "node:fs";
|
|
193084
193746
|
import { join as join45 } from "node:path";
|
|
193085
193747
|
var VALID_PLATFORM_KEYS2 = /* @__PURE__ */ new Set([
|
|
193086
193748
|
...PREVIEW_SURFACES.map((s2) => s2.platformKey).filter((k2) => k2 !== null),
|
|
@@ -193093,7 +193755,7 @@ function surfaceIssues(dir, surfaceNav, strict) {
|
|
|
193093
193755
|
let platforms = {};
|
|
193094
193756
|
let envelopeUnreadable = false;
|
|
193095
193757
|
const p2 = join45(dir, "platforms.json");
|
|
193096
|
-
if (
|
|
193758
|
+
if (existsSync47(p2)) {
|
|
193097
193759
|
let raw;
|
|
193098
193760
|
try {
|
|
193099
193761
|
raw = JSON.parse(readFileSync55(p2, "utf8"));
|
|
@@ -193126,7 +193788,7 @@ function surfaceIssues(dir, surfaceNav, strict) {
|
|
|
193126
193788
|
}
|
|
193127
193789
|
if (envelopeUnreadable) return issues;
|
|
193128
193790
|
const configTs = join45(dir, "config.ts");
|
|
193129
|
-
if (
|
|
193791
|
+
if (existsSync47(configTs)) {
|
|
193130
193792
|
const declared = parseCarConfig(readFileSync55(configTs, "utf8")).category;
|
|
193131
193793
|
const inEnvelope = platforms.androidauto === true;
|
|
193132
193794
|
if (inEnvelope && !declared) {
|
|
@@ -193186,10 +193848,10 @@ async function fontIssues(dir, strict, opts = {}) {
|
|
|
193186
193848
|
}
|
|
193187
193849
|
|
|
193188
193850
|
// src/stores-api-lint.ts
|
|
193189
|
-
import { existsSync as
|
|
193851
|
+
import { existsSync as existsSync50, readdirSync as readdirSync26, readFileSync as readFileSync58 } from "node:fs";
|
|
193190
193852
|
import { join as join48 } from "node:path";
|
|
193191
193853
|
function storesV1Issues(contentDir2, strict) {
|
|
193192
|
-
const roots2 = [join48(contentDir2, "tier5-src"), join48(contentDir2, "dev")].filter(
|
|
193854
|
+
const roots2 = [join48(contentDir2, "tier5-src"), join48(contentDir2, "dev")].filter(existsSync50);
|
|
193193
193855
|
const files = [];
|
|
193194
193856
|
const visit = (dir) => {
|
|
193195
193857
|
for (const entry of readdirSync26(dir, { withFileTypes: true })) {
|
|
@@ -193462,7 +194124,7 @@ async function templateCommand(ctx) {
|
|
|
193462
194124
|
const result = { ...outcome.result, ...fromSpec };
|
|
193463
194125
|
const adoptDir = contentDir(flags);
|
|
193464
194126
|
const kept = flags["dry-run"] !== true && (outcome.code === 0 || outcome.result.forcedKeep === true);
|
|
193465
|
-
if (kept &&
|
|
194127
|
+
if (kept && existsSync58(join57(adoptDir, adoptBits.ADOPT_FILE))) {
|
|
193466
194128
|
try {
|
|
193467
194129
|
const inv = adoptBits.inspectApp(adoptDir);
|
|
193468
194130
|
adoptBits.writeInventory(adoptDir, inv, { companions: "if-missing" });
|
|
@@ -193847,16 +194509,16 @@ async function ejectCommand(ctx) {
|
|
|
193847
194509
|
// src/commands/validate.ts
|
|
193848
194510
|
init_wix_placeholders();
|
|
193849
194511
|
init_lint_report();
|
|
193850
|
-
import { readFileSync as readFileSync77, existsSync as
|
|
194512
|
+
import { readFileSync as readFileSync77, existsSync as existsSync67 } from "node:fs";
|
|
193851
194513
|
import { join as join69 } from "node:path";
|
|
193852
194514
|
init_token_lint();
|
|
193853
194515
|
|
|
193854
194516
|
// src/icon-lint.ts
|
|
193855
194517
|
init_icon2();
|
|
193856
|
-
import { existsSync as
|
|
194518
|
+
import { existsSync as existsSync61 } from "node:fs";
|
|
193857
194519
|
import { join as join60 } from "node:path";
|
|
193858
194520
|
async function iconIssues(dir, strict, opts = {}) {
|
|
193859
|
-
if (!
|
|
194521
|
+
if (!existsSync61(join60(dir, "himalaya.content.json"))) return [];
|
|
193860
194522
|
const status = await iconStatus(dir);
|
|
193861
194523
|
const issue2 = (severity, message2) => ({
|
|
193862
194524
|
screen: null,
|
|
@@ -193919,7 +194581,7 @@ async function nativeConfigAdvisories(app, configSource) {
|
|
|
193919
194581
|
const { iosProjectYml: iosProjectYml2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
193920
194582
|
const { androidOptedIn: androidOptedIn3, LABEL_IOS_SPLASH: LABEL_IOS_SPLASH2 } = await Promise.resolve().then(() => (init_splash(), splash_exports));
|
|
193921
194583
|
const iosYmlPath = iosProjectYml2(app);
|
|
193922
|
-
const iosYml =
|
|
194584
|
+
const iosYml = existsSync67(iosYmlPath) ? readFileSync77(iosYmlPath, "utf8") : "";
|
|
193923
194585
|
let optedIn = iosYml.includes(LABEL_IOS_SPLASH2);
|
|
193924
194586
|
if (!optedIn) {
|
|
193925
194587
|
const { androidManifestPath: androidManifestPath3 } = await Promise.resolve().then(() => (init_gen_native_config(), gen_native_config_exports));
|
|
@@ -194009,7 +194671,7 @@ import { readFileSync as readFileSync80 } from "node:fs";
|
|
|
194009
194671
|
|
|
194010
194672
|
// src/dpx.ts
|
|
194011
194673
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
194012
|
-
import { existsSync as
|
|
194674
|
+
import { existsSync as existsSync68, readFileSync as readFileSync78 } from "node:fs";
|
|
194013
194675
|
import { homedir as homedir9 } from "node:os";
|
|
194014
194676
|
import { join as join70 } from "node:path";
|
|
194015
194677
|
var BO_COOKIE = "WixBoAuthentication_1_19_0";
|
|
@@ -194037,7 +194699,7 @@ function dpxSessionTokenPath() {
|
|
|
194037
194699
|
var DPX_SESSION_PORT = 5151;
|
|
194038
194700
|
function dpxSessionPresent(path2 = dpxSessionTokenPath()) {
|
|
194039
194701
|
try {
|
|
194040
|
-
return
|
|
194702
|
+
return existsSync68(path2) && readFileSync78(path2, "utf8").trim().length > 0;
|
|
194041
194703
|
} catch {
|
|
194042
194704
|
return false;
|
|
194043
194705
|
}
|
|
@@ -194272,13 +194934,13 @@ async function mcpCommand(ctx) {
|
|
|
194272
194934
|
|
|
194273
194935
|
// src/commands/studio.ts
|
|
194274
194936
|
init_cli_shared();
|
|
194275
|
-
import { mkdirSync as mkdirSync36, writeFileSync as writeFileSync30, existsSync as
|
|
194937
|
+
import { mkdirSync as mkdirSync36, writeFileSync as writeFileSync30, existsSync as existsSync71 } from "node:fs";
|
|
194276
194938
|
import { join as join74, resolve as resolve60, basename as basename19, dirname as dirname42 } from "node:path";
|
|
194277
194939
|
async function studioCommand(ctx) {
|
|
194278
194940
|
const { io: io2, pos, flags, print } = ctx;
|
|
194279
194941
|
const { openStudio: openStudio2 } = await Promise.resolve().then(() => (init_studio(), studio_exports));
|
|
194280
194942
|
const dir = contentDir(flags);
|
|
194281
|
-
if (!
|
|
194943
|
+
if (!existsSync71(join74(dir, "himalaya.content.json"))) {
|
|
194282
194944
|
io2.error(JSON.stringify({ ok: false, error: "not_a_content_package", dir, hint: "run from the app directory (or pass --content <dir>) \u2014 the board reads that package's .himi/" }));
|
|
194283
194945
|
return 2;
|
|
194284
194946
|
}
|
|
@@ -194338,7 +195000,7 @@ ${handover.hint[0].toUpperCase()}${handover.hint.slice(1)}.`);
|
|
|
194338
195000
|
|
|
194339
195001
|
// src/commands/progress.ts
|
|
194340
195002
|
init_cli_shared();
|
|
194341
|
-
import { existsSync as
|
|
195003
|
+
import { existsSync as existsSync72 } from "node:fs";
|
|
194342
195004
|
import { join as join75 } from "node:path";
|
|
194343
195005
|
async function progressCommand2(ctx) {
|
|
194344
195006
|
const { io: io2, pos, flags, print } = ctx;
|
|
@@ -194362,7 +195024,7 @@ async function progressCommand2(ctx) {
|
|
|
194362
195024
|
} = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
194363
195025
|
const dir = contentDir(flags);
|
|
194364
195026
|
const journal2 = journalPath2(dir);
|
|
194365
|
-
const isContentPackage =
|
|
195027
|
+
const isContentPackage = existsSync72(join75(dir, "himalaya.content.json"));
|
|
194366
195028
|
const hint = isContentPackage ? {} : { hint: "no himalaya.content.json here \u2014 run from the app directory (or pass --content <dir>) so the build board finds this journal" };
|
|
194367
195029
|
const message2 = pos.slice(1).join(" ").trim();
|
|
194368
195030
|
const approvalFlags = ["approve", "done", "drop"].filter((f2) => flags[f2] !== void 0);
|
|
@@ -194552,7 +195214,7 @@ init_himi_report();
|
|
|
194552
195214
|
init_attestation();
|
|
194553
195215
|
init_wix_placeholders();
|
|
194554
195216
|
init_lint_report();
|
|
194555
|
-
import { existsSync as
|
|
195217
|
+
import { existsSync as existsSync77, rmSync as rmSync21 } from "node:fs";
|
|
194556
195218
|
import { join as join81 } from "node:path";
|
|
194557
195219
|
init_crawl_layers();
|
|
194558
195220
|
init_cli_shared();
|
|
@@ -194575,7 +195237,7 @@ async function testCommand(ctx) {
|
|
|
194575
195237
|
const { io: io2, deps, pos, flags, print, serveBase } = ctx;
|
|
194576
195238
|
const dir = contentDir(flags);
|
|
194577
195239
|
const structuredOutput = flags.json === true || io2.isTTY !== true;
|
|
194578
|
-
if (
|
|
195240
|
+
if (existsSync77(join81(dir, "functions"))) {
|
|
194579
195241
|
const { invokeLocalFunction: invokeLocalFunction2, loadFunctionsApp: loadFunctionsApp2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
194580
195242
|
const loaded = await loadFunctionsApp2(dir);
|
|
194581
195243
|
const results = [];
|
|
@@ -195240,7 +195902,7 @@ async function iconsCommand(ctx) {
|
|
|
195240
195902
|
|
|
195241
195903
|
// src/commands/pull.ts
|
|
195242
195904
|
init_cli_shared();
|
|
195243
|
-
import { existsSync as
|
|
195905
|
+
import { existsSync as existsSync79, readdirSync as readdirSync35, statSync as statSync21 } from "node:fs";
|
|
195244
195906
|
import { join as join84, resolve as resolve63 } from "node:path";
|
|
195245
195907
|
async function pullCommand(ctx) {
|
|
195246
195908
|
const { io: io2, pos, flags, print, client: client2 } = ctx;
|
|
@@ -195258,7 +195920,7 @@ async function pullCommand(ctx) {
|
|
|
195258
195920
|
io2.error(JSON.stringify(linked));
|
|
195259
195921
|
return 1;
|
|
195260
195922
|
}
|
|
195261
|
-
if (
|
|
195923
|
+
if (existsSync79(dest)) {
|
|
195262
195924
|
if (!statSync21(dest).isDirectory()) {
|
|
195263
195925
|
io2.error(JSON.stringify({
|
|
195264
195926
|
error: `${dest} exists and is not a directory`,
|
|
@@ -195271,7 +195933,7 @@ async function pullCommand(ctx) {
|
|
|
195271
195933
|
io2.error(JSON.stringify({ error: `${dest} already exists and is not empty`, hint: "pass --force to write into it anyway (merging, and naming what it keeps), --replace to restore exactly what was archived, or --out/--name to land somewhere else" }));
|
|
195272
195934
|
return 1;
|
|
195273
195935
|
}
|
|
195274
|
-
if (replace && occupied && !
|
|
195936
|
+
if (replace && occupied && !existsSync79(join84(dest, "himalaya.content.json"))) {
|
|
195275
195937
|
io2.error(JSON.stringify({
|
|
195276
195938
|
error: `${dest} is not a content package \u2014 refusing to --replace it`,
|
|
195277
195939
|
hint: "--replace only clears a directory that holds himalaya.content.json. Check --out/--name, or pass --force to merge into it instead."
|
|
@@ -195352,7 +196014,7 @@ async function pullCommand(ctx) {
|
|
|
195352
196014
|
|
|
195353
196015
|
// src/commands/push.ts
|
|
195354
196016
|
import { createHash as createHash41 } from "node:crypto";
|
|
195355
|
-
import { existsSync as
|
|
196017
|
+
import { existsSync as existsSync82 } from "node:fs";
|
|
195356
196018
|
import { join as join87, relative as relative17 } from "node:path";
|
|
195357
196019
|
init_config();
|
|
195358
196020
|
init_release();
|
|
@@ -195520,7 +196182,7 @@ async function pushCommand(ctx) {
|
|
|
195520
196182
|
const payload = await loadReleaseFromDir(declared, out2);
|
|
195521
196183
|
const oneAppEvidence = join87(dir, ".himi", "one-app");
|
|
195522
196184
|
const oneAppCoverage = join87(dir, "ONE-APP-COVERAGE.json");
|
|
195523
|
-
const oneAppMarked =
|
|
196185
|
+
const oneAppMarked = existsSync82(join87(oneAppEvidence, "manifest.json")) || existsSync82(oneAppCoverage);
|
|
195524
196186
|
let oneAppCoverageCount = 0;
|
|
195525
196187
|
let oneAppCoverageReady = false;
|
|
195526
196188
|
let oneAppNativeProof;
|
|
@@ -196188,12 +196850,12 @@ async function packCommand(ctx) {
|
|
|
196188
196850
|
|
|
196189
196851
|
// src/commands/import.ts
|
|
196190
196852
|
init_cli_shared();
|
|
196191
|
-
import { existsSync as
|
|
196853
|
+
import { existsSync as existsSync83, readdirSync as readdirSync36, statSync as statSync23 } from "node:fs";
|
|
196192
196854
|
import { resolve as resolve67 } from "node:path";
|
|
196193
196855
|
function restoreDestinationIssue(dest, force) {
|
|
196194
196856
|
const link = symlinkDestinationIssue(dest);
|
|
196195
196857
|
if (link) return link;
|
|
196196
|
-
if (!
|
|
196858
|
+
if (!existsSync83(dest)) return null;
|
|
196197
196859
|
if (!statSync23(dest).isDirectory()) {
|
|
196198
196860
|
return { error: `${dest} exists and is not a directory`, hint: "pass --out/--name to land somewhere else, or remove the file" };
|
|
196199
196861
|
}
|
|
@@ -197385,7 +198047,7 @@ async function promoteCommand(ctx) {
|
|
|
197385
198047
|
// src/commands/patch.ts
|
|
197386
198048
|
init_lint_report();
|
|
197387
198049
|
init_cli_shared();
|
|
197388
|
-
import { readFileSync as readFileSync98, existsSync as
|
|
198050
|
+
import { readFileSync as readFileSync98, existsSync as existsSync87 } from "node:fs";
|
|
197389
198051
|
import { createHash as createHash42 } from "node:crypto";
|
|
197390
198052
|
var PATCH_HELP = `himi patch \u2014 change ONE item of a published app, from a raw file, on a machine
|
|
197391
198053
|
that does not have the content package.
|
|
@@ -197464,7 +198126,7 @@ async function patchCommand(ctx) {
|
|
|
197464
198126
|
io2.error(JSON.stringify({ error: `patch ${kind} needs --file`, usage: PATCH_USAGE }));
|
|
197465
198127
|
return 2;
|
|
197466
198128
|
}
|
|
197467
|
-
if (!
|
|
198129
|
+
if (!existsSync87(file2)) {
|
|
197468
198130
|
io2.error(JSON.stringify({ error: `no such file: ${file2}` }));
|
|
197469
198131
|
return 2;
|
|
197470
198132
|
}
|
|
@@ -198025,7 +198687,7 @@ async function testflightCommand(ctx) {
|
|
|
198025
198687
|
}
|
|
198026
198688
|
|
|
198027
198689
|
// src/commands/dist.ts
|
|
198028
|
-
import { existsSync as
|
|
198690
|
+
import { existsSync as existsSync93 } from "node:fs";
|
|
198029
198691
|
import { join as join99 } from "node:path";
|
|
198030
198692
|
init_wix_owner();
|
|
198031
198693
|
init_cli_shared();
|
|
@@ -198065,7 +198727,7 @@ async function distCommand(ctx) {
|
|
|
198065
198727
|
const rememberLastDist = async (jobs2) => {
|
|
198066
198728
|
try {
|
|
198067
198729
|
const dir = contentDir(flags);
|
|
198068
|
-
if (!
|
|
198730
|
+
if (!existsSync93(join99(dir, "himalaya.content.json"))) return;
|
|
198069
198731
|
const { lastDistFromJob: lastDistFromJob2, writeLastDist: writeLastDist2 } = await Promise.resolve().then(() => (init_capabilities(), capabilities_exports));
|
|
198070
198732
|
const own6 = await appId(dir);
|
|
198071
198733
|
for (const job of jobs2) {
|
|
@@ -198309,9 +198971,35 @@ ${label3}`);
|
|
|
198309
198971
|
return 0;
|
|
198310
198972
|
}
|
|
198311
198973
|
const platform = str3(flags.platform)?.split(",").map((p2) => p2.trim()).filter(Boolean);
|
|
198974
|
+
const { captchaContentInput: captchaContentInput2, captchaDistGate: captchaDistGate2 } = await Promise.resolve().then(() => (init_captcha2(), captcha_exports));
|
|
198975
|
+
const captchaSiteId = str3(flags.site) ?? (await appId(contentDir(flags)) === app ? captchaContentInput2(contentDir(flags)).siteId : void 0);
|
|
198976
|
+
const { captchaBindable: captchaBindable2 } = await Promise.resolve().then(() => (init_captcha_bindable(), captcha_bindable_exports));
|
|
198977
|
+
const { DEFAULT_DIST_SHELL: DEFAULT_DIST_SHELL2 } = await Promise.resolve().then(() => (init_dist_jobs(), dist_jobs_exports));
|
|
198978
|
+
if (flags.force !== true && flags["skip-captcha-check"] !== true && captchaBindable2(distShell ?? DEFAULT_DIST_SHELL2, false)) {
|
|
198979
|
+
const verdict = await captchaDistGate2({
|
|
198980
|
+
client: c2,
|
|
198981
|
+
app,
|
|
198982
|
+
release: str3(flags.release),
|
|
198983
|
+
requestedSite: captchaSiteId,
|
|
198984
|
+
// The plane's own default when --platform is absent: Android (iOS for a customer TestFlight build).
|
|
198985
|
+
platforms: platform?.length ? platform : str3(flags.destination) === "testflight" ? ["ios"] : ["android"]
|
|
198986
|
+
});
|
|
198987
|
+
if (verdict.refuse) {
|
|
198988
|
+
print({
|
|
198989
|
+
ok: false,
|
|
198990
|
+
code: verdict.refuse.code,
|
|
198991
|
+
error: verdict.refuse.code,
|
|
198992
|
+
message: verdict.refuse.message,
|
|
198993
|
+
captchaPolicy: verdict.refuse.captchaPolicy,
|
|
198994
|
+
hint: "fix config.ts and `himi push`, then build that release: `himi dist --release <its id> --allow-draft` (a draft), or promote it first \u2014 or `himi dist --skip-captcha-check` to build without the member CAPTCHA key"
|
|
198995
|
+
});
|
|
198996
|
+
return 1;
|
|
198997
|
+
}
|
|
198998
|
+
if (verdict.advisory) (flags.json === true ? io2.error : io2.log)(`\u26A0 ${verdict.advisory}`);
|
|
198999
|
+
}
|
|
198312
199000
|
{
|
|
198313
199001
|
const distDir = contentDir(flags);
|
|
198314
|
-
if (
|
|
199002
|
+
if (existsSync93(join99(distDir, "himalaya.content.json"))) {
|
|
198315
199003
|
const issues = await iconIssues(distDir, flags.strict === true, { requireDeclared: true, requireVerified: true });
|
|
198316
199004
|
const errors = issues.filter((i2) => i2.severity === "error");
|
|
198317
199005
|
for (const i2 of issues.filter((i3) => i3.severity === "warning")) {
|
|
@@ -198328,8 +199016,6 @@ ${label3}`);
|
|
|
198328
199016
|
}
|
|
198329
199017
|
}
|
|
198330
199018
|
}
|
|
198331
|
-
const { captchaContentInput: captchaContentInput2 } = await Promise.resolve().then(() => (init_captcha2(), captcha_exports));
|
|
198332
|
-
const captchaSiteId = str3(flags.site) ?? captchaContentInput2(contentDir(flags)).siteId;
|
|
198333
199019
|
let wixAuthorization;
|
|
198334
199020
|
const customerTestflight = str3(flags.signing)?.trim().toLowerCase() === "byo" && str3(flags.destination) === "testflight";
|
|
198335
199021
|
if (str3(flags.signing)?.trim().toLowerCase() === "byo") {
|
|
@@ -199321,7 +200007,7 @@ ${report3.ok ? "OK \u2014 data + serve plane reachable." : typeof report3.hint =
|
|
|
199321
200007
|
// src/commands/guide.ts
|
|
199322
200008
|
init_guides();
|
|
199323
200009
|
init_cli_shared();
|
|
199324
|
-
import { existsSync as
|
|
200010
|
+
import { existsSync as existsSync94 } from "node:fs";
|
|
199325
200011
|
import { join as join101, resolve as resolve72 } from "node:path";
|
|
199326
200012
|
async function runGuideCommand(command, pos, flags, io2, print) {
|
|
199327
200013
|
const { referenceCache: referenceCache2, referenceIdentity: referenceIdentity2 } = await Promise.resolve().then(() => (init_guides(), guides_exports));
|
|
@@ -199549,7 +200235,7 @@ Seed your coding agent with \`himi agent-init\`. Guides: ${idx.portalUrl}`);
|
|
|
199549
200235
|
...res.removed.length ? { removed: res.removed, note: "older copies at the app root, moved to .himi/legacy-agent-files/ (a backup, in case one became app code) \u2014 the current ones live in .agents/skills/himalaya/" } : {},
|
|
199550
200236
|
// In a git repo the refresh moves the diff identity an earlier `himi test` attested (that
|
|
199551
200237
|
// hash is shared with the repo gates and deliberately exempts nothing but its own metadata).
|
|
199552
|
-
...
|
|
200238
|
+
...existsSync94(join101(dir, ".himi", "attestations", "latest.json")) ? { next: "if `himi push` then refuses the attestation as stale, re-run `himi test` \u2014 in a git checkout this refresh changed the tree it covered" } : {},
|
|
199553
200239
|
...res.skipped.length ? { skipped: res.skipped } : {},
|
|
199554
200240
|
portalUrl: idx.portalUrl
|
|
199555
200241
|
});
|
|
@@ -199617,7 +200303,7 @@ init_schema2();
|
|
|
199617
200303
|
// src/cms.ts
|
|
199618
200304
|
init_cms_schema();
|
|
199619
200305
|
init_wix_owner();
|
|
199620
|
-
import { existsSync as
|
|
200306
|
+
import { existsSync as existsSync95, readFileSync as readFileSync112, writeFileSync as writeFileSync36 } from "node:fs";
|
|
199621
200307
|
import { join as join102 } from "node:path";
|
|
199622
200308
|
var FOREIGN_DETAIL_LIMIT = 25;
|
|
199623
200309
|
var MAX_COLLECTION_PAGES = 40;
|
|
@@ -200050,7 +200736,7 @@ async function seedCms(opts) {
|
|
|
200050
200736
|
}
|
|
200051
200737
|
function readSeedFile(dir) {
|
|
200052
200738
|
const file2 = join102(dir, "cms-seed.json");
|
|
200053
|
-
if (!
|
|
200739
|
+
if (!existsSync95(file2)) return {};
|
|
200054
200740
|
let parsed;
|
|
200055
200741
|
try {
|
|
200056
200742
|
parsed = JSON.parse(readFileSync112(file2, "utf8"));
|
|
@@ -200112,7 +200798,7 @@ async function writeSeedRows(opts) {
|
|
|
200112
200798
|
};
|
|
200113
200799
|
}
|
|
200114
200800
|
let existing = {};
|
|
200115
|
-
if (
|
|
200801
|
+
if (existsSync95(file2)) {
|
|
200116
200802
|
let parsed;
|
|
200117
200803
|
try {
|
|
200118
200804
|
parsed = JSON.parse(readFileSync112(file2, "utf8"));
|
|
@@ -200427,7 +201113,7 @@ async function cmsCommand(ctx) {
|
|
|
200427
201113
|
|
|
200428
201114
|
// src/commands/base44.ts
|
|
200429
201115
|
init_cli_shared();
|
|
200430
|
-
import { existsSync as
|
|
201116
|
+
import { existsSync as existsSync103 } from "node:fs";
|
|
200431
201117
|
import { join as join113, resolve as resolve77 } from "node:path";
|
|
200432
201118
|
async function base44Command(ctx) {
|
|
200433
201119
|
const { io: io2, pos, flags, print } = ctx;
|
|
@@ -200499,7 +201185,7 @@ async function base44Command(ctx) {
|
|
|
200499
201185
|
return 1;
|
|
200500
201186
|
};
|
|
200501
201187
|
const gen = await Promise.resolve().then(() => (init_generate(), generate_exports));
|
|
200502
|
-
const missing3 = gen.ENGINE_FILES.filter((f2) => !
|
|
201188
|
+
const missing3 = gen.ENGINE_FILES.filter((f2) => !existsSync103(join113(dir, f2)));
|
|
200503
201189
|
if (missing3.length) {
|
|
200504
201190
|
return fail6("content_dir_not_base44_starter", `${dir} is not a base44-starter content package: the generated screens import a shared engine it does not have (${missing3.join(", ")})`, { missing: missing3, hint: "scaffold one with `himi init <name> --template base44-starter --base44-app-id <id>`" });
|
|
200505
201191
|
}
|
|
@@ -200585,7 +201271,7 @@ async function base44Command(ctx) {
|
|
|
200585
201271
|
if (!provisioning || str3(flags.content) !== void 0 || !slug) return contentDir(flags);
|
|
200586
201272
|
if (!/^[a-z0-9][a-z0-9-]*$/.test(slug)) return void 0;
|
|
200587
201273
|
const dir = resolve77("apps", slug);
|
|
200588
|
-
return
|
|
201274
|
+
return existsSync103(join113(dir, "config.ts")) || existsSync103(join113(dir, "config.mjs")) ? dir : void 0;
|
|
200589
201275
|
};
|
|
200590
201276
|
if (sub === "entities" || sub === "functions") {
|
|
200591
201277
|
if (sub === "entities" && !["query", "create", "seed"].includes(pos[2] ?? "")) {
|