@wix/himalaya-cli 0.1002.0 → 0.1004.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/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/bookings-v2/src/extensions.d.ts +16 -2
- package/dist/cli.mjs +1204 -761
- package/guides/himi-test.md +1 -0
- package/guides/sdk-reference.json +1 -1
- package/guides/wix-business-context.md +27 -0
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -74,36 +74,36 @@ __export(config_exports, {
|
|
|
74
74
|
import { homedir } from "node:os";
|
|
75
75
|
import { join, dirname } from "node:path";
|
|
76
76
|
import { readFileSync, writeFileSync, mkdirSync, chmodSync } from "node:fs";
|
|
77
|
-
function loadTargetsFile(
|
|
77
|
+
function loadTargetsFile(path2 = defaultTargetsPath()) {
|
|
78
78
|
try {
|
|
79
|
-
return JSON.parse(readFileSync(
|
|
79
|
+
return JSON.parse(readFileSync(path2, "utf8"));
|
|
80
80
|
} catch {
|
|
81
81
|
return {};
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
function saveControlToken(target, token,
|
|
85
|
-
const file = loadTargetsFile(
|
|
84
|
+
function saveControlToken(target, token, path2 = defaultTargetsPath()) {
|
|
85
|
+
const file = loadTargetsFile(path2);
|
|
86
86
|
file.targets = file.targets ?? {};
|
|
87
87
|
file.targets[target] = { ...file.targets[target], controlToken: token };
|
|
88
|
-
writeTargetsFilePrivate(
|
|
89
|
-
return
|
|
88
|
+
writeTargetsFilePrivate(path2, file);
|
|
89
|
+
return path2;
|
|
90
90
|
}
|
|
91
|
-
function writeTargetsFilePrivate(
|
|
92
|
-
mkdirSync(dirname(
|
|
93
|
-
writeFileSync(
|
|
91
|
+
function writeTargetsFilePrivate(path2, file) {
|
|
92
|
+
mkdirSync(dirname(path2), { recursive: true, mode: 448 });
|
|
93
|
+
writeFileSync(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
|
|
94
94
|
try {
|
|
95
|
-
chmodSync(dirname(
|
|
96
|
-
chmodSync(
|
|
95
|
+
chmodSync(dirname(path2), 448);
|
|
96
|
+
chmodSync(path2, 384);
|
|
97
97
|
} catch {
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
-
function clearControlToken(target,
|
|
101
|
-
const file = loadTargetsFile(
|
|
100
|
+
function clearControlToken(target, path2 = defaultTargetsPath()) {
|
|
101
|
+
const file = loadTargetsFile(path2);
|
|
102
102
|
if (file.targets?.[target]?.controlToken) {
|
|
103
103
|
delete file.targets[target].controlToken;
|
|
104
|
-
writeFileSync(
|
|
104
|
+
writeFileSync(path2, JSON.stringify(file, null, 2) + "\n");
|
|
105
105
|
}
|
|
106
|
-
return
|
|
106
|
+
return path2;
|
|
107
107
|
}
|
|
108
108
|
function resolveTargetName(opts = {}) {
|
|
109
109
|
const env = opts.env ?? process.env;
|
|
@@ -2306,6 +2306,17 @@ var init_cms_schema = __esm({
|
|
|
2306
2306
|
});
|
|
2307
2307
|
|
|
2308
2308
|
// src/wix-owner.ts
|
|
2309
|
+
var wix_owner_exports = {};
|
|
2310
|
+
__export(wix_owner_exports, {
|
|
2311
|
+
WixApiError: () => WixApiError,
|
|
2312
|
+
accountToken: () => accountToken,
|
|
2313
|
+
mapLimit: () => mapLimit,
|
|
2314
|
+
ownerTransport: () => ownerTransport,
|
|
2315
|
+
redactForError: () => redactForError,
|
|
2316
|
+
resolveSiteId: () => resolveSiteId,
|
|
2317
|
+
siteToken: () => siteToken,
|
|
2318
|
+
withRetry: () => withRetry
|
|
2319
|
+
});
|
|
2309
2320
|
import { spawn } from "node:child_process";
|
|
2310
2321
|
function resolveSiteId(flag) {
|
|
2311
2322
|
const id = flag?.trim() || process.env.WIX_SITE_ID?.trim();
|
|
@@ -2384,7 +2395,7 @@ function mintHelp(label2, detail) {
|
|
|
2384
2395
|
return `could not run \`${label2}\` (${detail}). Install the Wix CLI and log in (\`npm i -g @wix/cli && wix login\`), or set WIX_TEST_TOKEN.`;
|
|
2385
2396
|
}
|
|
2386
2397
|
function ownerTransport(msid, fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS2) {
|
|
2387
|
-
return async (method,
|
|
2398
|
+
return async (method, path2, body) => {
|
|
2388
2399
|
const headers2 = {
|
|
2389
2400
|
Authorization: await siteToken(msid),
|
|
2390
2401
|
"wix-site-id": msid,
|
|
@@ -2394,7 +2405,7 @@ function ownerTransport(msid, fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS2
|
|
|
2394
2405
|
const started = Date.now();
|
|
2395
2406
|
let res;
|
|
2396
2407
|
try {
|
|
2397
|
-
res = await fetchImpl(`${API_BASE}${
|
|
2408
|
+
res = await fetchImpl(`${API_BASE}${path2}`, {
|
|
2398
2409
|
method,
|
|
2399
2410
|
headers: headers2,
|
|
2400
2411
|
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
@@ -2404,10 +2415,10 @@ function ownerTransport(msid, fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS2
|
|
|
2404
2415
|
const err = e;
|
|
2405
2416
|
if (err?.name === "TimeoutError" || /aborted due to timeout/i.test(err?.message ?? "")) {
|
|
2406
2417
|
throw new Error(
|
|
2407
|
-
`${method} ${
|
|
2418
|
+
`${method} ${path2} timed out after ${Date.now() - started}ms (limit ${timeoutMs}ms). Wix REST over a VPN'd link is slow and a large site's collection list can be ~1MB. Raise the ceiling with HIMI_WIX_TIMEOUT_MS=<ms>, or check the VPN.`
|
|
2408
2419
|
);
|
|
2409
2420
|
}
|
|
2410
|
-
throw new Error(`${method} ${
|
|
2421
|
+
throw new Error(`${method} ${path2} failed: ${err?.message ?? String(e)}`);
|
|
2411
2422
|
}
|
|
2412
2423
|
const text4 = await res.text();
|
|
2413
2424
|
let parsed = text4;
|
|
@@ -2415,7 +2426,7 @@ function ownerTransport(msid, fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS2
|
|
|
2415
2426
|
parsed = text4 ? JSON.parse(text4) : null;
|
|
2416
2427
|
} catch {
|
|
2417
2428
|
}
|
|
2418
|
-
if (!res.ok) throw new WixApiError(res.status, method,
|
|
2429
|
+
if (!res.ok) throw new WixApiError(res.status, method, path2, parsed);
|
|
2419
2430
|
return parsed;
|
|
2420
2431
|
};
|
|
2421
2432
|
}
|
|
@@ -2457,12 +2468,12 @@ var init_wix_owner = __esm({
|
|
|
2457
2468
|
TOKEN_MINT_TIMEOUT_MS = 3e4;
|
|
2458
2469
|
ACCOUNT_TOKEN_KEY = "account:*";
|
|
2459
2470
|
WixApiError = class extends Error {
|
|
2460
|
-
constructor(status, method,
|
|
2471
|
+
constructor(status, method, path2, body) {
|
|
2461
2472
|
const detail = typeof body === "string" ? body.slice(0, 300) : JSON.stringify(body)?.slice(0, 300);
|
|
2462
|
-
super(`${method} ${
|
|
2473
|
+
super(`${method} ${path2} -> ${status}: ${detail}`);
|
|
2463
2474
|
this.status = status;
|
|
2464
2475
|
this.method = method;
|
|
2465
|
-
this.path =
|
|
2476
|
+
this.path = path2;
|
|
2466
2477
|
this.body = body;
|
|
2467
2478
|
this.name = "WixApiError";
|
|
2468
2479
|
}
|
|
@@ -2542,8 +2553,8 @@ function homeRefreshActionId(name) {
|
|
|
2542
2553
|
function committedProvisioningPath(name) {
|
|
2543
2554
|
return `${shellAppDir(name)}/provisioning.json`;
|
|
2544
2555
|
}
|
|
2545
|
-
function committedShellFor(
|
|
2546
|
-
const normalized =
|
|
2556
|
+
function committedShellFor(path2) {
|
|
2557
|
+
const normalized = path2.replace(/\\/g, "/");
|
|
2547
2558
|
return SHELL_NAMES2.find((name) => {
|
|
2548
2559
|
const relative9 = committedProvisioningPath(name);
|
|
2549
2560
|
return normalized === relative9 || normalized.endsWith(`/${relative9}`);
|
|
@@ -3197,9 +3208,9 @@ function umbrellaRewritePlugin({ external = false } = {}) {
|
|
|
3197
3208
|
name: "himalaya-umbrella-rewrite",
|
|
3198
3209
|
setup(b) {
|
|
3199
3210
|
b.onResolve({ filter: /^@himalaya\// }, async (args) => {
|
|
3200
|
-
const
|
|
3201
|
-
if (external) return { path, external: true };
|
|
3202
|
-
return b.resolve(
|
|
3211
|
+
const path2 = args.path.replace(/^@himalaya\//, "@wix/himalaya/");
|
|
3212
|
+
if (external) return { path: path2, external: true };
|
|
3213
|
+
return b.resolve(path2, { resolveDir: args.resolveDir, kind: args.kind });
|
|
3203
3214
|
});
|
|
3204
3215
|
}
|
|
3205
3216
|
};
|
|
@@ -3232,8 +3243,8 @@ function tsExtResolvePlugin() {
|
|
|
3232
3243
|
setup(b) {
|
|
3233
3244
|
b.onResolve({ filter: /\.js$/ }, (args) => {
|
|
3234
3245
|
if (args.kind === "entry-point" || !args.path.startsWith(".")) return void 0;
|
|
3235
|
-
const
|
|
3236
|
-
return existsSync8(
|
|
3246
|
+
const ts2 = resolve8(args.resolveDir, args.path.replace(/\.js$/, ".ts"));
|
|
3247
|
+
return existsSync8(ts2) ? { path: ts2 } : void 0;
|
|
3237
3248
|
});
|
|
3238
3249
|
}
|
|
3239
3250
|
};
|
|
@@ -3949,7 +3960,7 @@ function bundleFor(file) {
|
|
|
3949
3960
|
const match = /^tier5-src\/([^/]+)\//.exec(file);
|
|
3950
3961
|
return match?.[1] ?? "_shared";
|
|
3951
3962
|
}
|
|
3952
|
-
function toIssue(
|
|
3963
|
+
function toIssue(ts2, contentDir2, diagnostic) {
|
|
3953
3964
|
const file = diagnostic.file ? relativeFile(contentDir2, diagnostic.file.fileName) : void 0;
|
|
3954
3965
|
const position = diagnostic.file && diagnostic.start !== void 0 ? diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : void 0;
|
|
3955
3966
|
return {
|
|
@@ -3957,13 +3968,13 @@ function toIssue(ts, contentDir2, diagnostic) {
|
|
|
3957
3968
|
...file ? { file } : {},
|
|
3958
3969
|
...position ? { line: position.line + 1, column: position.character + 1 } : {},
|
|
3959
3970
|
code: `TS${diagnostic.code}`,
|
|
3960
|
-
message:
|
|
3971
|
+
message: ts2.flattenDiagnosticMessageText(diagnostic.messageText, "\n")
|
|
3961
3972
|
};
|
|
3962
3973
|
}
|
|
3963
|
-
function confinedHost(
|
|
3974
|
+
function confinedHost(ts2, contentDir2, options) {
|
|
3964
3975
|
if (!buildConfinementRequired()) return void 0;
|
|
3965
|
-
const host =
|
|
3966
|
-
const libDir = resolve10(
|
|
3976
|
+
const host = ts2.createCompilerHost(options);
|
|
3977
|
+
const libDir = resolve10(ts2.getDefaultLibFilePath(options), "..");
|
|
3967
3978
|
const allows = confinementMatcher(contentDir2, [libDir]);
|
|
3968
3979
|
const getSourceFile = host.getSourceFile.bind(host);
|
|
3969
3980
|
const readFile3 = host.readFile.bind(host);
|
|
@@ -3991,7 +4002,7 @@ function confinedHost(ts, contentDir2, options) {
|
|
|
3991
4002
|
}
|
|
3992
4003
|
async function typecheckContentWorkers(contentDir2, options) {
|
|
3993
4004
|
if (!existsSync9(resolve10(contentDir2, "tier5-src"))) return [];
|
|
3994
|
-
const
|
|
4005
|
+
const ts2 = await compiler2();
|
|
3995
4006
|
const config = {
|
|
3996
4007
|
compilerOptions: {
|
|
3997
4008
|
...CONTENT_WORKER_COMPILER_OPTIONS,
|
|
@@ -4000,18 +4011,18 @@ async function typecheckContentWorkers(contentDir2, options) {
|
|
|
4000
4011
|
// The deployed authoring runtime stages TypeScript 6, which requires an explicit
|
|
4001
4012
|
// acknowledgement for this compatibility `baseUrl`; the repository's TypeScript 5 lane
|
|
4002
4013
|
// rejects that 6.0 value, so keep it specific to the compiler that needs it.
|
|
4003
|
-
...Number.parseInt(
|
|
4014
|
+
...Number.parseInt(ts2.versionMajorMinor, 10) >= 6 ? { ignoreDeprecations: "6.0" } : {}
|
|
4004
4015
|
},
|
|
4005
4016
|
include: ["tier5-src/*/index.ts", "tier5-src/_shared/**/*.ts"]
|
|
4006
4017
|
};
|
|
4007
|
-
const parsed =
|
|
4018
|
+
const parsed = ts2.parseJsonConfigFileContent(config, ts2.sys, contentDir2);
|
|
4008
4019
|
if (parsed.fileNames.length === 0) return [];
|
|
4009
|
-
const program =
|
|
4020
|
+
const program = ts2.createProgram({
|
|
4010
4021
|
rootNames: parsed.fileNames,
|
|
4011
4022
|
options: parsed.options,
|
|
4012
|
-
host: confinedHost(
|
|
4023
|
+
host: confinedHost(ts2, contentDir2, parsed.options)
|
|
4013
4024
|
});
|
|
4014
|
-
return [...parsed.errors, ...
|
|
4025
|
+
return [...parsed.errors, ...ts2.getPreEmitDiagnostics(program)].filter((diagnostic) => diagnostic.category === ts2.DiagnosticCategory.Error && belongsToContentWorkers(contentDir2, diagnostic)).map((diagnostic) => toIssue(ts2, contentDir2, diagnostic));
|
|
4015
4026
|
}
|
|
4016
4027
|
var compilerPromise;
|
|
4017
4028
|
var init_tier5_typecheck = __esm({
|
|
@@ -5267,41 +5278,41 @@ function buildTokenRegistry(tokens) {
|
|
|
5267
5278
|
materials: new Set(Object.keys(tokens.materials ?? {}))
|
|
5268
5279
|
};
|
|
5269
5280
|
}
|
|
5270
|
-
function findTokenViolations(payload, registry,
|
|
5281
|
+
function findTokenViolations(payload, registry, path2 = "$") {
|
|
5271
5282
|
const out = [];
|
|
5272
|
-
walk(payload, registry,
|
|
5283
|
+
walk(payload, registry, path2, out);
|
|
5273
5284
|
return out;
|
|
5274
5285
|
}
|
|
5275
|
-
function walk(node, registry,
|
|
5286
|
+
function walk(node, registry, path2, out) {
|
|
5276
5287
|
if (node === null || typeof node !== "object") return;
|
|
5277
5288
|
if (Array.isArray(node)) {
|
|
5278
|
-
node.forEach((item, i) => walk(item, registry, `${
|
|
5289
|
+
node.forEach((item, i) => walk(item, registry, `${path2}[${i}]`, out));
|
|
5279
5290
|
return;
|
|
5280
5291
|
}
|
|
5281
5292
|
const obj2 = node;
|
|
5282
5293
|
const bg = obj2.background;
|
|
5283
5294
|
if (bg && typeof bg.token === "string" && !registry.colors.has(bg.token)) {
|
|
5284
|
-
out.push({ path: `${
|
|
5295
|
+
out.push({ path: `${path2}.background.token`, kind: "color", name: bg.token });
|
|
5285
5296
|
}
|
|
5286
5297
|
if (obj2.type === "Text") {
|
|
5287
5298
|
const props = obj2.props;
|
|
5288
5299
|
if (props && typeof props.style === "string" && !registry.typography.has(props.style)) {
|
|
5289
5300
|
out.push({
|
|
5290
|
-
path: `${
|
|
5301
|
+
path: `${path2}.props.style`,
|
|
5291
5302
|
kind: "typography",
|
|
5292
5303
|
name: props.style
|
|
5293
5304
|
});
|
|
5294
5305
|
}
|
|
5295
5306
|
if (props && typeof props.color === "string" && !registry.colors.has(props.color)) {
|
|
5296
5307
|
out.push({
|
|
5297
|
-
path: `${
|
|
5308
|
+
path: `${path2}.props.color`,
|
|
5298
5309
|
kind: "color",
|
|
5299
5310
|
name: props.color
|
|
5300
5311
|
});
|
|
5301
5312
|
}
|
|
5302
5313
|
}
|
|
5303
5314
|
for (const [key2, value] of Object.entries(obj2)) {
|
|
5304
|
-
walk(value, registry, `${
|
|
5315
|
+
walk(value, registry, `${path2}.${key2}`, out);
|
|
5305
5316
|
}
|
|
5306
5317
|
}
|
|
5307
5318
|
var SYSTEM_FONT_FAMILY;
|
|
@@ -5346,11 +5357,11 @@ var init_bindings = __esm({
|
|
|
5346
5357
|
// ../../core/ts/src/validator.ts
|
|
5347
5358
|
import Ajv from "ajv";
|
|
5348
5359
|
import addFormats from "ajv-formats";
|
|
5349
|
-
function findUnknownComponents(node, allowed2,
|
|
5360
|
+
function findUnknownComponents(node, allowed2, path2 = "$", out = []) {
|
|
5350
5361
|
if (node === null || typeof node !== "object") return out;
|
|
5351
5362
|
if (Array.isArray(node)) {
|
|
5352
5363
|
node.forEach(
|
|
5353
|
-
(item, i) => findUnknownComponents(item, allowed2, `${
|
|
5364
|
+
(item, i) => findUnknownComponents(item, allowed2, `${path2}[${i}]`, out)
|
|
5354
5365
|
);
|
|
5355
5366
|
return out;
|
|
5356
5367
|
}
|
|
@@ -5359,11 +5370,11 @@ function findUnknownComponents(node, allowed2, path = "$", out = []) {
|
|
|
5359
5370
|
if (body && typeof body.package === "string" && typeof body.type === "string") {
|
|
5360
5371
|
const key2 = `${body.package}.${body.type}`;
|
|
5361
5372
|
if (!allowed2.has(key2)) {
|
|
5362
|
-
out.push({ path, package: body.package, type: body.type });
|
|
5373
|
+
out.push({ path: path2, package: body.package, type: body.type });
|
|
5363
5374
|
}
|
|
5364
5375
|
}
|
|
5365
5376
|
for (const [key2, value] of Object.entries(obj2)) {
|
|
5366
|
-
findUnknownComponents(value, allowed2, `${
|
|
5377
|
+
findUnknownComponents(value, allowed2, `${path2}.${key2}`, out);
|
|
5367
5378
|
}
|
|
5368
5379
|
return out;
|
|
5369
5380
|
}
|
|
@@ -5375,9 +5386,9 @@ function compileWidgetSchema() {
|
|
|
5375
5386
|
}
|
|
5376
5387
|
return widgetValidateFn;
|
|
5377
5388
|
}
|
|
5378
|
-
function validateWidgetActionRef(action,
|
|
5389
|
+
function validateWidgetActionRef(action, path2, intents) {
|
|
5379
5390
|
if (typeof action !== "object" || action === null || Array.isArray(action)) {
|
|
5380
|
-
intents.push({ path, reason: "must be an object { actionId, params? }" });
|
|
5391
|
+
intents.push({ path: path2, reason: "must be an object { actionId, params? }" });
|
|
5381
5392
|
return;
|
|
5382
5393
|
}
|
|
5383
5394
|
const actionId = action.actionId;
|
|
@@ -5386,48 +5397,48 @@ function validateWidgetActionRef(action, path, intents) {
|
|
|
5386
5397
|
const unsupportedFields = Object.keys(action).filter((key2) => !WIDGET_ACTION_FIELDS.has(key2));
|
|
5387
5398
|
if (unsupportedFields.length > 0) {
|
|
5388
5399
|
intents.push({
|
|
5389
|
-
path,
|
|
5400
|
+
path: path2,
|
|
5390
5401
|
reason: `unsupported field(s) on a widget action: ${unsupportedFields.sort().join(", ")} \u2014 a frozen widget action carries only \`actionId\` and literal \`params\``
|
|
5391
5402
|
});
|
|
5392
5403
|
}
|
|
5393
5404
|
const knownAction = typeof actionId === "string" && Object.prototype.hasOwnProperty.call(WIDGET_INTENT_RULES, actionId);
|
|
5394
5405
|
if (typeof actionId !== "string" || actionId.length === 0) {
|
|
5395
|
-
intents.push({ path, reason: "`actionId` must be a non-empty string" });
|
|
5406
|
+
intents.push({ path: path2, reason: "`actionId` must be a non-empty string" });
|
|
5396
5407
|
} else if (!knownAction) {
|
|
5397
|
-
intents.push({ path, reason: `unsupported widget actionId "${actionId}"` });
|
|
5408
|
+
intents.push({ path: path2, reason: `unsupported widget actionId "${actionId}"` });
|
|
5398
5409
|
}
|
|
5399
5410
|
if (params !== void 0 && (typeof params !== "object" || params === null || Array.isArray(params) || !Object.values(params).every((value) => typeof value === "string"))) {
|
|
5400
|
-
intents.push({ path, reason: "`params` must be a { string: string } map of literals" });
|
|
5411
|
+
intents.push({ path: path2, reason: "`params` must be a { string: string } map of literals" });
|
|
5401
5412
|
} else if (knownAction) {
|
|
5402
5413
|
const rule = WIDGET_INTENT_RULES[actionId];
|
|
5403
5414
|
const literalParams = params ?? {};
|
|
5404
5415
|
if (Object.keys(literalParams).length > 8 || utf8ByteLength(JSON.stringify(literalParams)) > 1024 || Object.entries(literalParams).some(([key2, value]) => utf8ByteLength(key2) > 64 || utf8ByteLength(value) > 512)) {
|
|
5405
|
-
intents.push({ path, reason: "parameters exceed the widget action size limit" });
|
|
5416
|
+
intents.push({ path: path2, reason: "parameters exceed the widget action size limit" });
|
|
5406
5417
|
}
|
|
5407
5418
|
const allowed2 = /* @__PURE__ */ new Set([...rule.required, ...rule.optional ?? []]);
|
|
5408
5419
|
const unknown = Object.keys(literalParams).filter((key2) => !allowed2.has(key2));
|
|
5409
5420
|
const missing = rule.required.filter((key2) => !literalParams[key2]);
|
|
5410
5421
|
if (unknown.length > 0) {
|
|
5411
|
-
intents.push({ path, reason: `unsupported parameter(s): ${unknown.join(", ")}` });
|
|
5422
|
+
intents.push({ path: path2, reason: `unsupported parameter(s): ${unknown.join(", ")}` });
|
|
5412
5423
|
}
|
|
5413
5424
|
if (missing.length > 0) {
|
|
5414
|
-
intents.push({ path, reason: `missing required parameter(s): ${missing.join(", ")}` });
|
|
5425
|
+
intents.push({ path: path2, reason: `missing required parameter(s): ${missing.join(", ")}` });
|
|
5415
5426
|
}
|
|
5416
5427
|
for (const [key2, values] of Object.entries(rule.values ?? {})) {
|
|
5417
5428
|
const value = literalParams[key2];
|
|
5418
5429
|
if (value !== void 0 && !values.includes(value)) {
|
|
5419
|
-
intents.push({ path, reason: `invalid ${key2} "${value}"` });
|
|
5430
|
+
intents.push({ path: path2, reason: `invalid ${key2} "${value}"` });
|
|
5420
5431
|
}
|
|
5421
5432
|
}
|
|
5422
5433
|
}
|
|
5423
5434
|
}
|
|
5424
|
-
function scanWidgetPayload(node, family,
|
|
5435
|
+
function scanWidgetPayload(node, family, path2, bindings, disallowed, timeRefs, intents, actionSites2) {
|
|
5425
5436
|
if (typeof node === "string") {
|
|
5426
|
-
if (WIDGET_BINDING.test(node)) bindings.push({ path, value: node });
|
|
5437
|
+
if (WIDGET_BINDING.test(node)) bindings.push({ path: path2, value: node });
|
|
5427
5438
|
return;
|
|
5428
5439
|
}
|
|
5429
5440
|
if (Array.isArray(node)) {
|
|
5430
|
-
node.forEach((item, i) => scanWidgetPayload(item, family, `${
|
|
5441
|
+
node.forEach((item, i) => scanWidgetPayload(item, family, `${path2}[${i}]`, bindings, disallowed, timeRefs, intents, actionSites2));
|
|
5431
5442
|
return;
|
|
5432
5443
|
}
|
|
5433
5444
|
if (node === null || typeof node !== "object") return;
|
|
@@ -5436,46 +5447,46 @@ function scanWidgetPayload(node, family, path, bindings, disallowed, timeRefs, i
|
|
|
5436
5447
|
if (body && typeof body.package === "string" && typeof body.type === "string") {
|
|
5437
5448
|
const key2 = `${body.package}.${body.type}`;
|
|
5438
5449
|
if (family && !isComponentAllowedForFamily(key2, family)) {
|
|
5439
|
-
disallowed.push({ path, package: body.package, type: body.type, family });
|
|
5450
|
+
disallowed.push({ path: path2, package: body.package, type: body.type, family });
|
|
5440
5451
|
}
|
|
5441
5452
|
if (key2 === "himalaya.Button") {
|
|
5442
5453
|
const props = body.props;
|
|
5443
5454
|
if (!props || typeof props !== "object" || Array.isArray(props)) {
|
|
5444
|
-
intents.push({ path: `${
|
|
5455
|
+
intents.push({ path: `${path2}.body.props`, reason: "widget Button props must be an object" });
|
|
5445
5456
|
} else if (family === "ios_home" || family === "android_home") {
|
|
5446
5457
|
const button = props;
|
|
5447
5458
|
if (button.intent !== void 0) {
|
|
5448
|
-
intents.push({ path: `${
|
|
5459
|
+
intents.push({ path: `${path2}.body.props.intent`, reason: "widget Button commands use the required `action` field" });
|
|
5449
5460
|
}
|
|
5450
|
-
validateWidgetActionRef(button.action, `${
|
|
5461
|
+
validateWidgetActionRef(button.action, `${path2}.body.props.action`, intents);
|
|
5451
5462
|
const componentId = obj2.id;
|
|
5452
5463
|
if (typeof componentId !== "string" || !WIDGET_ACTION_IDENTIFIER.test(componentId)) {
|
|
5453
5464
|
intents.push({
|
|
5454
|
-
path: `${
|
|
5465
|
+
path: `${path2}.id`,
|
|
5455
5466
|
reason: "a widget Button carrying an action needs an id matching ^[A-Za-z0-9_.:-]{1,128}$, or the runtimes attach no handler to it"
|
|
5456
5467
|
});
|
|
5457
5468
|
}
|
|
5458
|
-
actionSites2.push(`${
|
|
5469
|
+
actionSites2.push(`${path2}.body.props.action`);
|
|
5459
5470
|
}
|
|
5460
5471
|
}
|
|
5461
5472
|
}
|
|
5462
5473
|
if (obj2.timeRef !== void 0 && obj2.timeRef !== null) {
|
|
5463
5474
|
const tr = obj2.timeRef;
|
|
5464
5475
|
if (typeof tr !== "object" || Array.isArray(tr)) {
|
|
5465
|
-
timeRefs.push({ path: `${
|
|
5476
|
+
timeRefs.push({ path: `${path2}.timeRef`, reason: "must be an object { at, style? }" });
|
|
5466
5477
|
} else {
|
|
5467
5478
|
const at = tr.at;
|
|
5468
5479
|
const style = tr.style;
|
|
5469
5480
|
if (typeof at !== "number" || !Number.isFinite(at)) {
|
|
5470
|
-
timeRefs.push({ path: `${
|
|
5481
|
+
timeRefs.push({ path: `${path2}.timeRef`, reason: "`at` must be a finite epoch-seconds number" });
|
|
5471
5482
|
}
|
|
5472
5483
|
if (style !== void 0 && (typeof style !== "string" || !VALID_TIMEREF_STYLES.has(style))) {
|
|
5473
|
-
timeRefs.push({ path: `${
|
|
5484
|
+
timeRefs.push({ path: `${path2}.timeRef`, reason: `invalid style "${String(style)}" (expected ${[...VALID_TIMEREF_STYLES].join("|")})` });
|
|
5474
5485
|
}
|
|
5475
5486
|
}
|
|
5476
5487
|
}
|
|
5477
5488
|
for (const [k, v] of Object.entries(obj2)) {
|
|
5478
|
-
scanWidgetPayload(v, family, `${
|
|
5489
|
+
scanWidgetPayload(v, family, `${path2}.${k}`, bindings, disallowed, timeRefs, intents, actionSites2);
|
|
5479
5490
|
}
|
|
5480
5491
|
}
|
|
5481
5492
|
function validateWidget(snapshot2) {
|
|
@@ -6392,9 +6403,9 @@ function collectDescriptorStrings(descriptor) {
|
|
|
6392
6403
|
seen.add(key2);
|
|
6393
6404
|
out.push(f);
|
|
6394
6405
|
};
|
|
6395
|
-
const visit = (node,
|
|
6406
|
+
const visit = (node, path2) => {
|
|
6396
6407
|
if (Array.isArray(node)) {
|
|
6397
|
-
node.forEach((n, i) => visit(n, `${
|
|
6408
|
+
node.forEach((n, i) => visit(n, `${path2}[${i}]`));
|
|
6398
6409
|
return;
|
|
6399
6410
|
}
|
|
6400
6411
|
if (!node || typeof node !== "object") return;
|
|
@@ -6407,7 +6418,7 @@ function collectDescriptorStrings(descriptor) {
|
|
|
6407
6418
|
for (const [prop, v] of Object.entries(props)) {
|
|
6408
6419
|
if (typeof v !== "string" || BINDING_SIGIL.test(v)) continue;
|
|
6409
6420
|
if (!isUserVisibleCopy(v)) continue;
|
|
6410
|
-
const at = `${
|
|
6421
|
+
const at = `${path2}.body.props.${prop}`;
|
|
6411
6422
|
if (mapped.includes(prop) || SECONDARY_FIELDS.has(prop)) {
|
|
6412
6423
|
push({ value: v, bucket: "reachable", type, prop, path: at });
|
|
6413
6424
|
} else if (UNREACHED_VISIBLE_FIELDS.has(prop)) {
|
|
@@ -6421,19 +6432,19 @@ function collectDescriptorStrings(descriptor) {
|
|
|
6421
6432
|
bucket: "reachable",
|
|
6422
6433
|
type,
|
|
6423
6434
|
prop: "template.template",
|
|
6424
|
-
path: `${
|
|
6435
|
+
path: `${path2}.body.props.template.template`
|
|
6425
6436
|
});
|
|
6426
6437
|
}
|
|
6427
6438
|
}
|
|
6428
6439
|
for (const [k, v] of Object.entries(obj2)) {
|
|
6429
6440
|
if (k === "body") continue;
|
|
6430
6441
|
if (typeof v === "string" && SECONDARY_FIELDS.has(k) && !BINDING_SIGIL.test(v) && isUserVisibleCopy(v)) {
|
|
6431
|
-
push({ value: v, bucket: "reachable", type, prop: k, path: `${
|
|
6442
|
+
push({ value: v, bucket: "reachable", type, prop: k, path: `${path2}.${k}` });
|
|
6432
6443
|
}
|
|
6433
6444
|
}
|
|
6434
6445
|
for (const [k, v] of Object.entries(obj2)) {
|
|
6435
|
-
if (
|
|
6436
|
-
if (v && typeof v === "object") visit(v,
|
|
6446
|
+
if (path2 === "" && k === "input" && v !== null && typeof v === "object") continue;
|
|
6447
|
+
if (v && typeof v === "object") visit(v, path2 ? `${path2}.${k}` : k);
|
|
6437
6448
|
}
|
|
6438
6449
|
};
|
|
6439
6450
|
visit(descriptor, "");
|
|
@@ -6907,10 +6918,10 @@ async function bootBundleWorker(bundleJs, opts) {
|
|
|
6907
6918
|
// `headers` is forwarded, not swallowed: it is how one call addresses a business other
|
|
6908
6919
|
// than the ambient one (`site.forSite(msid)` → `wix-site-id`), and a wrapper that drops
|
|
6909
6920
|
// it answers for the wrong business while every caller renders the result as correct.
|
|
6910
|
-
call: (method,
|
|
6911
|
-
const label2 = `${String(method)} ${String(
|
|
6921
|
+
call: (method, path2, body, headers2) => {
|
|
6922
|
+
const label2 = `${String(method)} ${String(path2)}`;
|
|
6912
6923
|
calls.push(label2);
|
|
6913
|
-
return Promise.resolve(opts.wixCall(method,
|
|
6924
|
+
return Promise.resolve(opts.wixCall(method, path2, body, headers2)).then((value) => {
|
|
6914
6925
|
const bytes2 = responseBytes(value);
|
|
6915
6926
|
if (bytes2 > MAX_FRAME_MESSAGE_BYTES) {
|
|
6916
6927
|
oversizeWixResponses.push({ call: label2, bytes: bytes2 });
|
|
@@ -7148,11 +7159,11 @@ async function bootBundleWorker(bundleJs, opts) {
|
|
|
7148
7159
|
}
|
|
7149
7160
|
message = typeof asJson === "string" ? asJson : String(raw);
|
|
7150
7161
|
} else message = String(raw);
|
|
7151
|
-
const
|
|
7152
|
-
if (prev.status === "loading")
|
|
7153
|
-
if (prev.loading === true)
|
|
7154
|
-
if (typeof prev.error === "string")
|
|
7155
|
-
def.state =
|
|
7162
|
+
const failed2 = { ...prev, _error: message };
|
|
7163
|
+
if (prev.status === "loading") failed2.status = "error";
|
|
7164
|
+
if (prev.loading === true) failed2.loading = false;
|
|
7165
|
+
if (typeof prev.error === "string") failed2.error = message;
|
|
7166
|
+
def.state = failed2;
|
|
7156
7167
|
};
|
|
7157
7168
|
const runAction = async (def, label2, fn, args) => {
|
|
7158
7169
|
let timer;
|
|
@@ -7349,9 +7360,9 @@ function validateDescriptorAction(action, context) {
|
|
|
7349
7360
|
function validateDescriptorActions(actions, context) {
|
|
7350
7361
|
return actions.map((action) => validateDescriptorAction(action, context)).filter((issue2) => issue2 !== null);
|
|
7351
7362
|
}
|
|
7352
|
-
function pathValue(state,
|
|
7363
|
+
function pathValue(state, path2) {
|
|
7353
7364
|
let cur = state;
|
|
7354
|
-
for (const part of
|
|
7365
|
+
for (const part of path2.replace(/\[(\d+)\]/g, ".$1").split(".")) {
|
|
7355
7366
|
if (cur == null || typeof cur !== "object") return void 0;
|
|
7356
7367
|
if (Array.isArray(cur)) {
|
|
7357
7368
|
const idx = Number(part);
|
|
@@ -7364,9 +7375,9 @@ function pathValue(state, path) {
|
|
|
7364
7375
|
}
|
|
7365
7376
|
return cur;
|
|
7366
7377
|
}
|
|
7367
|
-
function pathResolves(state,
|
|
7378
|
+
function pathResolves(state, path2) {
|
|
7368
7379
|
let cur = state;
|
|
7369
|
-
for (const part of
|
|
7380
|
+
for (const part of path2.replace(/\[(\d+)\]/g, ".$1").split(".")) {
|
|
7370
7381
|
if (cur == null || typeof cur !== "object") return false;
|
|
7371
7382
|
if (Array.isArray(cur)) {
|
|
7372
7383
|
const idx = Number(part);
|
|
@@ -7383,9 +7394,9 @@ function pathResolves(state, path) {
|
|
|
7383
7394
|
}
|
|
7384
7395
|
return true;
|
|
7385
7396
|
}
|
|
7386
|
-
function serviceFieldDeclared(state,
|
|
7397
|
+
function serviceFieldDeclared(state, path2) {
|
|
7387
7398
|
if (state == null || typeof state !== "object" || Array.isArray(state)) return false;
|
|
7388
|
-
const first =
|
|
7399
|
+
const first = path2.replace(/\[(\d+)\]/g, ".$1").split(".")[0];
|
|
7389
7400
|
return first in state;
|
|
7390
7401
|
}
|
|
7391
7402
|
function ellipsis(value, max) {
|
|
@@ -7398,70 +7409,70 @@ function isOpaqueAuthorJson(key2, value, atRoot) {
|
|
|
7398
7409
|
if (value === null || typeof value !== "object") return false;
|
|
7399
7410
|
return key2 === "args" || atRoot && key2 === "input";
|
|
7400
7411
|
}
|
|
7401
|
-
function pathCrossesOpaqueAuthorJson(
|
|
7402
|
-
if (typeof
|
|
7403
|
-
return /^\$\.input(?:[.[]|$)/.test(
|
|
7412
|
+
function pathCrossesOpaqueAuthorJson(path2) {
|
|
7413
|
+
if (typeof path2 !== "string") return false;
|
|
7414
|
+
return /^\$\.input(?:[.[]|$)/.test(path2) || /\.args(?:[.[]|$)/.test(path2);
|
|
7404
7415
|
}
|
|
7405
7416
|
function nativeRequiredFindings(descriptor) {
|
|
7406
7417
|
const out = [];
|
|
7407
7418
|
const shapeOf = (ref) => ref.startsWith("list:") ? "an array" : ref.startsWith("map:") ? "an object keyed by name" : "an object";
|
|
7408
7419
|
const kindOf = (value) => Array.isArray(value) ? "an array" : value === null ? "null" : typeof value === "object" ? "an object" : `a ${typeof value} (${JSON.stringify(value)})`;
|
|
7409
|
-
const reportKind = (ref, value,
|
|
7420
|
+
const reportKind = (ref, value, path2, from) => {
|
|
7410
7421
|
const cls = bareNestedClass(ref);
|
|
7411
7422
|
const got = kindOf(value);
|
|
7412
7423
|
const expected = ref.startsWith("list:") ? "Expected JsonArray" : `Expected JsonObject for type with serial name 'io.himalaya.core.${cls}'`;
|
|
7413
7424
|
out.push({
|
|
7414
|
-
path,
|
|
7425
|
+
path: path2,
|
|
7415
7426
|
message: `${cls} is what the native decoder expects here \u2014 ${shapeOf(ref)} \u2014 but the descriptor has ${got}. Native decode rejects it ("${expected}") and drops the WHOLE screen from the seed, while web renders it fine (reached from ${from})`
|
|
7416
7427
|
});
|
|
7417
7428
|
};
|
|
7418
|
-
const checkNested = (value, cls,
|
|
7429
|
+
const checkNested = (value, cls, path2, from) => {
|
|
7419
7430
|
if (cls.startsWith("map:")) {
|
|
7420
7431
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
7421
|
-
reportKind(cls, value,
|
|
7432
|
+
reportKind(cls, value, path2, from);
|
|
7422
7433
|
return;
|
|
7423
7434
|
}
|
|
7424
7435
|
const of = cls.slice("map:".length);
|
|
7425
7436
|
for (const [key2, v] of Object.entries(value)) {
|
|
7426
|
-
checkNested(v, of, `${
|
|
7437
|
+
checkNested(v, of, `${path2}.${key2}`, from);
|
|
7427
7438
|
}
|
|
7428
7439
|
return;
|
|
7429
7440
|
}
|
|
7430
7441
|
if (cls.startsWith("list:")) {
|
|
7431
7442
|
if (!Array.isArray(value)) {
|
|
7432
|
-
reportKind(cls, value,
|
|
7443
|
+
reportKind(cls, value, path2, from);
|
|
7433
7444
|
return;
|
|
7434
7445
|
}
|
|
7435
7446
|
const of = cls.slice("list:".length);
|
|
7436
|
-
value.forEach((v, i) => checkNested(v, of, `${
|
|
7447
|
+
value.forEach((v, i) => checkNested(v, of, `${path2}[${i}]`, from));
|
|
7437
7448
|
return;
|
|
7438
7449
|
}
|
|
7439
7450
|
const rule = own(NATIVE_NESTED_CLASSES, cls);
|
|
7440
7451
|
if (!rule) return;
|
|
7441
7452
|
if (Array.isArray(value) || !value || typeof value !== "object") {
|
|
7442
|
-
reportKind(cls, value,
|
|
7453
|
+
reportKind(cls, value, path2, from);
|
|
7443
7454
|
return;
|
|
7444
7455
|
}
|
|
7445
7456
|
const bag = value;
|
|
7446
7457
|
for (const name of rule.required) {
|
|
7447
7458
|
if (own(bag, name) !== void 0 && bag[name] !== null) continue;
|
|
7448
7459
|
out.push({
|
|
7449
|
-
path: `${
|
|
7460
|
+
path: `${path2}.${name}`,
|
|
7450
7461
|
message: `${cls}.${name} is REQUIRED by the native decoder but is missing \u2014 native decode rejects it ("Field '${name}' is required for type with serial name 'io.himalaya.core.${cls}', but it was missing") and drops the WHOLE screen from the seed, while web renders it fine (reached from ${from})`
|
|
7451
7462
|
});
|
|
7452
7463
|
}
|
|
7453
7464
|
for (const [name, sub] of Object.entries(rule.nested)) {
|
|
7454
7465
|
const inner = own(bag, name);
|
|
7455
|
-
if (inner !== void 0 && inner !== null) checkNested(inner, sub, `${
|
|
7466
|
+
if (inner !== void 0 && inner !== null) checkNested(inner, sub, `${path2}.${name}`, from);
|
|
7456
7467
|
}
|
|
7457
|
-
if (cls === "Action") checkActionParams(own(bag, "params"), `${
|
|
7468
|
+
if (cls === "Action") checkActionParams(own(bag, "params"), `${path2}.params`, from);
|
|
7458
7469
|
};
|
|
7459
|
-
const checkActionParams = (params,
|
|
7470
|
+
const checkActionParams = (params, path2, from) => {
|
|
7460
7471
|
if (params === void 0 || params === null) return;
|
|
7461
7472
|
const cost = "Native decode rejects it and drops the WHOLE screen from the seed, while web renders it fine";
|
|
7462
7473
|
if (typeof params !== "object" || Array.isArray(params)) {
|
|
7463
7474
|
out.push({
|
|
7464
|
-
path,
|
|
7475
|
+
path: path2,
|
|
7465
7476
|
message: `Action.params must be an object of strings, but the descriptor has ${kindOf(params)} ("Expected JsonObject"). ${cost} (reached from ${from})`
|
|
7466
7477
|
});
|
|
7467
7478
|
return;
|
|
@@ -7469,7 +7480,7 @@ function nativeRequiredFindings(descriptor) {
|
|
|
7469
7480
|
for (const [key2, value] of Object.entries(params)) {
|
|
7470
7481
|
if (typeof value === "string" || value === void 0) continue;
|
|
7471
7482
|
out.push({
|
|
7472
|
-
path: `${
|
|
7483
|
+
path: `${path2}.${key2}`,
|
|
7473
7484
|
message: `Action.params values must be strings, but params.${key2} is ${kindOf(value)} ("Expected JsonPrimitive at ${key2}" on Android, typeMismatch on iOS). ${cost}. Flatten it into string keys of params, or move structured data to Action.args (reached from ${from})`
|
|
7474
7485
|
});
|
|
7475
7486
|
}
|
|
@@ -7552,13 +7563,13 @@ function componentPropFindings(descriptor) {
|
|
|
7552
7563
|
const bag = props;
|
|
7553
7564
|
const base = at ? `${at}.body.props` : "body.props";
|
|
7554
7565
|
for (const name of Object.keys(bag)) {
|
|
7555
|
-
const
|
|
7566
|
+
const path2 = `${base}.${name}`;
|
|
7556
7567
|
const kind = own(declared, name);
|
|
7557
7568
|
if (kind === void 0) {
|
|
7558
7569
|
if (LEGACY_UNSCORED_KEYS.has(`${type}.${name}`)) continue;
|
|
7559
7570
|
const hint = MODIFIER_KEYS.has(name) ? ` \u2014 \`${name}\` is a MODIFIER, not a prop: move it out of \`props\` and into the node's \`modifiers\` bag (\`{ id, body, modifiers: { ${name}: \u2026 } }\`)` : "";
|
|
7560
7571
|
out.push({
|
|
7561
|
-
path,
|
|
7572
|
+
path: path2,
|
|
7562
7573
|
kind: "hygiene",
|
|
7563
7574
|
message: `${type} has no prop \`${name}\` \u2014 the native decoders are built with \`ignoreUnknownKeys = true\`, so this key is SILENTLY DROPPED on iOS and Android and the value never reaches the screen (web, whose props are \`any\`, may still show it). Declared props: ${Object.keys(declared).sort().join(", ") || "(none)"}${hint}`
|
|
7564
7575
|
});
|
|
@@ -7572,7 +7583,7 @@ function componentPropFindings(descriptor) {
|
|
|
7572
7583
|
const twin = own(declared, `${name}Path`) !== void 0 ? `${name}Path` : void 0;
|
|
7573
7584
|
const inArray = IN_ARRAY_BINDING_PROPS.has(`${type}.${name}`) && value.startsWith(SERVICE_SIGIL);
|
|
7574
7585
|
out.push({
|
|
7575
|
-
path,
|
|
7586
|
+
path: path2,
|
|
7576
7587
|
kind: "decode",
|
|
7577
7588
|
...inArray ? { authoringOnly: true } : {},
|
|
7578
7589
|
// TWO different defects share this branch, and they need DIFFERENT prose.
|
|
@@ -7588,7 +7599,7 @@ function componentPropFindings(descriptor) {
|
|
|
7588
7599
|
// copy-pasteable line that silently truncated a long path, so following the advice
|
|
7589
7600
|
// bound to missing state; it stays truncated only in the diagnostic prose, where it
|
|
7590
7601
|
// is describing rather than prescribing.
|
|
7591
|
-
message: inArray ? `${type}.${name} is declared ${kind}, and a bare \`${ellipsis(value, 32)}\` does not satisfy it: the authoring contract types this prop as an array (see core/ts/src/schema.ts and the generated component.schema.json), so a typed author cannot write the scalar even though the native decoders would accept it. Put the sentinel INSIDE the array \u2014 \`${name}: ["${value}"]\` \u2014 which is the form the renderers read and the authoring schema accepts. At ${jsonPointer(
|
|
7602
|
+
message: inArray ? `${type}.${name} is declared ${kind}, and a bare \`${ellipsis(value, 32)}\` does not satisfy it: the authoring contract types this prop as an array (see core/ts/src/schema.ts and the generated component.schema.json), so a typed author cannot write the scalar even though the native decoders would accept it. Put the sentinel INSIDE the array \u2014 \`${name}: ["${value}"]\` \u2014 which is the form the renderers read and the authoring schema accepts. At ${jsonPointer(path2)}` : `${type}.${name} is declared ${kind}, and a binding does NOT satisfy it \u2014 a \`${ellipsis(value, 32)}\` sentinel is a plain STRING on the wire and is resolved AFTER native decode, so kotlinx sees a string where it wants a ${kind}, REJECTS the document and drops the WHOLE screen from the seed (web renders it fine). ` + (twin ? `Bind \`${twin}\` instead \u2014 it is declared string exactly so a sentinel survives decode.` : `Bind this prop's \`\u2026Path\` twin if it has one; a typed slot cannot carry a sentinel.`) + ` At ${jsonPointer(path2)}`
|
|
7592
7603
|
});
|
|
7593
7604
|
continue;
|
|
7594
7605
|
}
|
|
@@ -7597,17 +7608,17 @@ function componentPropFindings(descriptor) {
|
|
|
7597
7608
|
if (actual === kind) {
|
|
7598
7609
|
if (kind === "number" && typeof value === "number" && !Number.isInteger(value) && own(INTEGER_PROPS, type)?.includes(name)) {
|
|
7599
7610
|
out.push({
|
|
7600
|
-
path,
|
|
7611
|
+
path: path2,
|
|
7601
7612
|
kind: "decode",
|
|
7602
|
-
message: `${type}.${name} is declared an INTEGER by the native decoders but this descriptor carries ${value} \u2014 a fraction is not representable in an \`Int\` field, so decode REJECTS the document and drops the WHOLE screen from the seed, while web renders it fine. Round it. At ${jsonPointer(
|
|
7613
|
+
message: `${type}.${name} is declared an INTEGER by the native decoders but this descriptor carries ${value} \u2014 a fraction is not representable in an \`Int\` field, so decode REJECTS the document and drops the WHOLE screen from the seed, while web renders it fine. Round it. At ${jsonPointer(path2)}`
|
|
7603
7614
|
});
|
|
7604
7615
|
}
|
|
7605
7616
|
continue;
|
|
7606
7617
|
}
|
|
7607
7618
|
out.push({
|
|
7608
|
-
path,
|
|
7619
|
+
path: path2,
|
|
7609
7620
|
kind: "decode",
|
|
7610
|
-
message: `${type}.${name} is declared ${kind} but this descriptor carries a ${actual} (${JSON.stringify(value)?.slice(0, 40)}) \u2014 native decode REJECTS the document ("Unexpected JSON token ... expected ${kind}") and drops the WHOLE screen from the seed, while web renders it fine. At ${jsonPointer(
|
|
7621
|
+
message: `${type}.${name} is declared ${kind} but this descriptor carries a ${actual} (${JSON.stringify(value)?.slice(0, 40)}) \u2014 native decode REJECTS the document ("Unexpected JSON token ... expected ${kind}") and drops the WHOLE screen from the seed, while web renders it fine. At ${jsonPointer(path2)}`
|
|
7611
7622
|
});
|
|
7612
7623
|
}
|
|
7613
7624
|
}
|
|
@@ -7870,15 +7881,15 @@ function workerSubtreeAllowed(screenId, allowlist) {
|
|
|
7870
7881
|
}
|
|
7871
7882
|
return false;
|
|
7872
7883
|
}
|
|
7873
|
-
function collectWixMediaReferences(value,
|
|
7884
|
+
function collectWixMediaReferences(value, path2, found, mediaContext = false, bareIdContext = false, componentType = "", atRoot = false) {
|
|
7874
7885
|
const unresolvedMedia = mediaContext && unresolvedWixMediaReference(value, bareIdContext);
|
|
7875
7886
|
if (unresolvedMedia) {
|
|
7876
|
-
found.push({ path, value: unresolvedMedia });
|
|
7887
|
+
found.push({ path: path2, value: unresolvedMedia });
|
|
7877
7888
|
return;
|
|
7878
7889
|
}
|
|
7879
7890
|
if (Array.isArray(value)) {
|
|
7880
7891
|
value.forEach((item, index) => {
|
|
7881
|
-
collectWixMediaReferences(item, `${
|
|
7892
|
+
collectWixMediaReferences(item, `${path2}[${index}]`, found, mediaContext, bareIdContext);
|
|
7882
7893
|
});
|
|
7883
7894
|
return;
|
|
7884
7895
|
}
|
|
@@ -7890,7 +7901,7 @@ function collectWixMediaReferences(value, path, found, mediaContext = false, bar
|
|
|
7890
7901
|
const childComponentType = key2 === "props" && typeof record2.type === "string" ? record2.type : "";
|
|
7891
7902
|
collectWixMediaReferences(
|
|
7892
7903
|
child,
|
|
7893
|
-
|
|
7904
|
+
path2 ? `${path2}.${key2}` : key2,
|
|
7894
7905
|
found,
|
|
7895
7906
|
mediaContext || isComponentMediaValueProperty(componentType, key2),
|
|
7896
7907
|
bareIdContext || isMediaLocationProperty(key2),
|
|
@@ -7936,16 +7947,16 @@ function validateScreenDescriptor(screenId, descriptor, opts = {}) {
|
|
|
7936
7947
|
};
|
|
7937
7948
|
for (const e of v.schemaErrors) {
|
|
7938
7949
|
const err = e;
|
|
7939
|
-
const
|
|
7940
|
-
if (
|
|
7950
|
+
const path2 = err.instancePath;
|
|
7951
|
+
if (path2 === "/logicBundle/integrity" && lbIntegrity === "") continue;
|
|
7941
7952
|
const issue2 = {
|
|
7942
7953
|
severity: hygiene,
|
|
7943
7954
|
pass: "schema",
|
|
7944
|
-
path,
|
|
7955
|
+
path: path2,
|
|
7945
7956
|
message: err.message ?? "schema violation"
|
|
7946
7957
|
};
|
|
7947
7958
|
issues.push(issue2);
|
|
7948
|
-
for (const at of dottedCandidates(
|
|
7959
|
+
for (const at of dottedCandidates(path2 ?? "")) {
|
|
7949
7960
|
if (err.keyword === "required" && err.params?.missingProperty) {
|
|
7950
7961
|
indexIssue(at ? `${at}.${err.params.missingProperty}` : err.params.missingProperty, issue2);
|
|
7951
7962
|
}
|
|
@@ -8355,11 +8366,11 @@ function validateScreenDescriptor(screenId, descriptor, opts = {}) {
|
|
|
8355
8366
|
{
|
|
8356
8367
|
const NAMED_ICON_PROPS = /* @__PURE__ */ new Set(["icon", "selectedIcon", "leadingIcon", "trailingIcon", "badgeIcon"]);
|
|
8357
8368
|
const shape = (v2) => Array.isArray(v2) ? "an array" : typeof v2;
|
|
8358
|
-
const flagNonString = (k, v2,
|
|
8369
|
+
const flagNonString = (k, v2, path2) => {
|
|
8359
8370
|
issues.push({
|
|
8360
8371
|
severity: "error",
|
|
8361
8372
|
pass: "icons",
|
|
8362
|
-
path,
|
|
8373
|
+
path: path2,
|
|
8363
8374
|
message: `icon prop "${k}" is ${shape(v2)} (${JSON.stringify(v2)}) \u2014 IconRef is an icon-name STRING (or a "$service:"/"$item." binding), never an object. The native decoders reject the descriptor and drop the whole screen; web degrades to the unknown-icon marker. Pass the name directly, e.g. ${k}: "cart".`
|
|
8364
8375
|
});
|
|
8365
8376
|
};
|
|
@@ -8390,12 +8401,12 @@ function validateScreenDescriptor(screenId, descriptor, opts = {}) {
|
|
|
8390
8401
|
const normIcon = (n) => n.toLowerCase().replace(/[_.\s-]/g, "");
|
|
8391
8402
|
const ICON_NAME_PROPS = /* @__PURE__ */ new Set(["icon", "selectedIcon", "leadingIcon", "trailingIcon", "badgeIcon"]);
|
|
8392
8403
|
const judgeable = (v2) => typeof v2 === "string" && v2.length > 0 && !v2.startsWith("$") && !v2.includes("/") && !v2.includes(":") && !/\.(png|jpe?g|svg|webp|gif)$/i.test(v2);
|
|
8393
|
-
const flagIcon = (name,
|
|
8404
|
+
const flagIcon = (name, path2) => {
|
|
8394
8405
|
if (allowedIcons.has(name) || allowedIcons.has(normIcon(name))) return;
|
|
8395
8406
|
issues.push({
|
|
8396
8407
|
severity: hygiene,
|
|
8397
8408
|
pass: "icons",
|
|
8398
|
-
path,
|
|
8409
|
+
path: path2,
|
|
8399
8410
|
message: `unknown icon "${name}" \u2014 renders the _unknown marker on device. Run \`himi icons\` for the valid names, or add a row to core/schema/icon-sources.json + \`yarn icons:gen\`. Already an ERROR under --strict; becomes an error by default one release after the catalog ships (docs/icons.md \xA72.6).`
|
|
8400
8411
|
});
|
|
8401
8412
|
};
|
|
@@ -10675,14 +10686,14 @@ function tokenColorProblems(colors) {
|
|
|
10675
10686
|
const problems = [];
|
|
10676
10687
|
for (const [name, value] of Object.entries(colors ?? {})) {
|
|
10677
10688
|
const leaves = typeof value === "object" && value !== null && !Array.isArray(value) ? Object.entries(value).map(([variant, raw]) => [`${name}.${variant}`, raw]) : [[name, value]];
|
|
10678
|
-
for (const [
|
|
10689
|
+
for (const [path2, raw] of leaves) {
|
|
10679
10690
|
if (typeof raw !== "string") {
|
|
10680
|
-
problems.push({ path, value: JSON.stringify(raw) ?? String(raw) });
|
|
10691
|
+
problems.push({ path: path2, value: JSON.stringify(raw) ?? String(raw) });
|
|
10681
10692
|
continue;
|
|
10682
10693
|
}
|
|
10683
10694
|
if (isCanonicalHex(raw)) continue;
|
|
10684
10695
|
const suggestion = canonicalHex(raw);
|
|
10685
|
-
problems.push(suggestion ? { path, value: raw, suggestion } : { path, value: raw });
|
|
10696
|
+
problems.push(suggestion ? { path: path2, value: raw, suggestion } : { path: path2, value: raw });
|
|
10686
10697
|
}
|
|
10687
10698
|
}
|
|
10688
10699
|
return problems;
|
|
@@ -11345,10 +11356,10 @@ function resolveAppDirIcon(appDir2) {
|
|
|
11345
11356
|
return findContentIconPath(appDir2) ?? findAppIconPath(appDir2);
|
|
11346
11357
|
}
|
|
11347
11358
|
function readIconFromDir(appDir2) {
|
|
11348
|
-
const
|
|
11349
|
-
if (!
|
|
11359
|
+
const path2 = resolveAppDirIcon(appDir2);
|
|
11360
|
+
if (!path2) return null;
|
|
11350
11361
|
try {
|
|
11351
|
-
return readFileSync15(
|
|
11362
|
+
return readFileSync15(path2);
|
|
11352
11363
|
} catch {
|
|
11353
11364
|
return null;
|
|
11354
11365
|
}
|
|
@@ -11698,11 +11709,11 @@ function playState(dir) {
|
|
|
11698
11709
|
}
|
|
11699
11710
|
async function iconStatus(dir) {
|
|
11700
11711
|
const declared = declaredIconName(dir);
|
|
11701
|
-
const
|
|
11712
|
+
const path2 = resolveAppDirIcon(dir);
|
|
11702
11713
|
const play = playState(dir);
|
|
11703
11714
|
const base = {
|
|
11704
11715
|
declared,
|
|
11705
|
-
path,
|
|
11716
|
+
path: path2,
|
|
11706
11717
|
play,
|
|
11707
11718
|
bytes: null,
|
|
11708
11719
|
sha256: null,
|
|
@@ -11714,21 +11725,21 @@ async function iconStatus(dir) {
|
|
|
11714
11725
|
verdict: "missing",
|
|
11715
11726
|
policyChecklist: POLICY_CHECKLIST
|
|
11716
11727
|
};
|
|
11717
|
-
if (!
|
|
11728
|
+
if (!path2 || !existsSync15(path2)) return base;
|
|
11718
11729
|
let png;
|
|
11719
11730
|
try {
|
|
11720
|
-
if (!statSync4(
|
|
11731
|
+
if (!statSync4(path2).isFile()) {
|
|
11721
11732
|
return {
|
|
11722
11733
|
...base,
|
|
11723
|
-
byteIssues: [`at ${
|
|
11734
|
+
byteIssues: [`at ${path2} is a directory, not a PNG file`],
|
|
11724
11735
|
verdict: "blocked"
|
|
11725
11736
|
};
|
|
11726
11737
|
}
|
|
11727
|
-
png = readFileSync16(
|
|
11738
|
+
png = readFileSync16(path2);
|
|
11728
11739
|
} catch (err) {
|
|
11729
11740
|
return {
|
|
11730
11741
|
...base,
|
|
11731
|
-
byteIssues: [`at ${
|
|
11742
|
+
byteIssues: [`at ${path2} could not be read (${err.message.split("\n")[0]})`],
|
|
11732
11743
|
verdict: "blocked"
|
|
11733
11744
|
};
|
|
11734
11745
|
}
|
|
@@ -11766,7 +11777,7 @@ async function iconStatus(dir) {
|
|
|
11766
11777
|
...status,
|
|
11767
11778
|
pixelFindings: [{
|
|
11768
11779
|
level: "error",
|
|
11769
|
-
message: `App icon at ${
|
|
11780
|
+
message: `App icon at ${path2} could not be decoded as an image (${err.message.split("\n")[0]}) \u2014 it is not a usable PNG. Replace it with \`himi icon set <file.png>\`.`
|
|
11770
11781
|
}],
|
|
11771
11782
|
pixelsChecked: false,
|
|
11772
11783
|
verdict: "blocked"
|
|
@@ -11951,15 +11962,15 @@ function loadCatalog() {
|
|
|
11951
11962
|
cached = JSON.parse(readFileSync17(override, "utf8"));
|
|
11952
11963
|
return cached;
|
|
11953
11964
|
}
|
|
11954
|
-
const
|
|
11955
|
-
if (!
|
|
11965
|
+
const path2 = CATALOG_CANDIDATES.find((p) => existsSync17(p));
|
|
11966
|
+
if (!path2) {
|
|
11956
11967
|
throw new Error(
|
|
11957
11968
|
`font catalog not found. Looked in:
|
|
11958
11969
|
${CATALOG_CANDIDATES.join("\n ")}
|
|
11959
11970
|
In the repo, run \`npm run fonts:catalog\`. In a published @wix/himalaya-cli this is a packaging bug \u2014 the catalog should ship under the package's stdlib/fonts/.`
|
|
11960
11971
|
);
|
|
11961
11972
|
}
|
|
11962
|
-
cached = JSON.parse(readFileSync17(
|
|
11973
|
+
cached = JSON.parse(readFileSync17(path2, "utf8"));
|
|
11963
11974
|
return cached;
|
|
11964
11975
|
}
|
|
11965
11976
|
function renderableFamilies(catalog = loadCatalog()) {
|
|
@@ -12242,9 +12253,9 @@ async function offRepoFontBytes(plan, opts = {}) {
|
|
|
12242
12253
|
out.hostProvided.push(r.family);
|
|
12243
12254
|
continue;
|
|
12244
12255
|
}
|
|
12245
|
-
const
|
|
12246
|
-
if (
|
|
12247
|
-
out.unavailable.push({ family: r.family, reason:
|
|
12256
|
+
const failed2 = r.faces.find((f) => !f.got.ok);
|
|
12257
|
+
if (failed2 && !failed2.got.ok) {
|
|
12258
|
+
out.unavailable.push({ family: r.family, reason: failed2.got.reason });
|
|
12248
12259
|
continue;
|
|
12249
12260
|
}
|
|
12250
12261
|
out.ready.push({
|
|
@@ -12719,9 +12730,9 @@ __export(fonts_exports, {
|
|
|
12719
12730
|
});
|
|
12720
12731
|
import { existsSync as existsSync19, readFileSync as readFileSync19 } from "node:fs";
|
|
12721
12732
|
import { join as join22 } from "node:path";
|
|
12722
|
-
function readJson(
|
|
12733
|
+
function readJson(path2, fallback) {
|
|
12723
12734
|
try {
|
|
12724
|
-
return JSON.parse(readFileSync19(
|
|
12735
|
+
return JSON.parse(readFileSync19(path2, "utf8"));
|
|
12725
12736
|
} catch {
|
|
12726
12737
|
return fallback;
|
|
12727
12738
|
}
|
|
@@ -12999,22 +13010,22 @@ function lc(h) {
|
|
|
12999
13010
|
for (const [k, v] of Object.entries(h ?? {})) o[k.toLowerCase()] = v;
|
|
13000
13011
|
return o;
|
|
13001
13012
|
}
|
|
13002
|
-
function matchRuleEx(rules, method,
|
|
13013
|
+
function matchRuleEx(rules, method, path2, ctx = {}) {
|
|
13003
13014
|
for (const r of rules) {
|
|
13004
13015
|
if (!r.enabled) continue;
|
|
13005
13016
|
const m = r.matcher;
|
|
13006
13017
|
if (m.method && m.method.toUpperCase() !== method.toUpperCase()) continue;
|
|
13007
13018
|
if (m.host && ctx.host && !globToRegExp(m.host).test(ctx.host)) continue;
|
|
13008
13019
|
if (m.host && !ctx.host) continue;
|
|
13009
|
-
const captures = { path, host: ctx.host ?? "" };
|
|
13020
|
+
const captures = { path: path2, host: ctx.host ?? "" };
|
|
13010
13021
|
if (m.pathRegex) {
|
|
13011
|
-
const mm = new RegExp(m.pathRegex).exec(
|
|
13022
|
+
const mm = new RegExp(m.pathRegex).exec(path2);
|
|
13012
13023
|
if (!mm) continue;
|
|
13013
13024
|
mm.forEach((g, i) => {
|
|
13014
13025
|
captures[String(i)] = g ?? "";
|
|
13015
13026
|
});
|
|
13016
13027
|
} else if (m.pathGlob) {
|
|
13017
|
-
if (!globToRegExp(m.pathGlob).test(
|
|
13028
|
+
if (!globToRegExp(m.pathGlob).test(path2)) continue;
|
|
13018
13029
|
}
|
|
13019
13030
|
if (m.query) {
|
|
13020
13031
|
const q = ctx.query ?? {};
|
|
@@ -13090,15 +13101,15 @@ function isNativePlatform(value) {
|
|
|
13090
13101
|
function isNativeAuditStatus(value) {
|
|
13091
13102
|
return typeof value === "string" && NATIVE_AUDIT_STATUSES.includes(value);
|
|
13092
13103
|
}
|
|
13093
|
-
function readText(
|
|
13104
|
+
function readText(path2) {
|
|
13094
13105
|
try {
|
|
13095
|
-
return existsSync21(
|
|
13106
|
+
return existsSync21(path2) ? readFileSync21(path2, "utf8") : null;
|
|
13096
13107
|
} catch {
|
|
13097
13108
|
return null;
|
|
13098
13109
|
}
|
|
13099
13110
|
}
|
|
13100
|
-
function parseEvidence(
|
|
13101
|
-
const raw = readText(
|
|
13111
|
+
function parseEvidence(path2) {
|
|
13112
|
+
const raw = readText(path2);
|
|
13102
13113
|
if (raw === null) return { evidence: null };
|
|
13103
13114
|
try {
|
|
13104
13115
|
const value = JSON.parse(raw);
|
|
@@ -13126,9 +13137,9 @@ function recordedRenderWidths(content) {
|
|
|
13126
13137
|
const { evidence } = parseEvidence(uxEvidencePath(content));
|
|
13127
13138
|
return renderEvidenceEntries(evidence).map((entry) => entry.width);
|
|
13128
13139
|
}
|
|
13129
|
-
function writeEvidence(
|
|
13130
|
-
mkdirSync10(dirname13(
|
|
13131
|
-
writeFileSync9(
|
|
13140
|
+
function writeEvidence(path2, evidence) {
|
|
13141
|
+
mkdirSync10(dirname13(path2), { recursive: true });
|
|
13142
|
+
writeFileSync9(path2, JSON.stringify(evidence, null, 2) + "\n");
|
|
13132
13143
|
}
|
|
13133
13144
|
function recordedFilePath(dir, file) {
|
|
13134
13145
|
const rel = relative3(dir, resolve15(file));
|
|
@@ -13138,8 +13149,8 @@ function recordRenderWidth(content, entry) {
|
|
|
13138
13149
|
try {
|
|
13139
13150
|
if (!entry.screenId || !Number.isFinite(entry.width) || entry.width <= 0) return null;
|
|
13140
13151
|
const dir = resolve15(content);
|
|
13141
|
-
const
|
|
13142
|
-
const parsed = parseEvidence(
|
|
13152
|
+
const path2 = join24(dir, UX_EVIDENCE_PATH);
|
|
13153
|
+
const parsed = parseEvidence(path2);
|
|
13143
13154
|
if (parsed.error) return null;
|
|
13144
13155
|
const evidence = parsed.evidence ?? { version: 1, platforms: {} };
|
|
13145
13156
|
const width = entry.width;
|
|
@@ -13155,7 +13166,7 @@ function recordRenderWidth(content, entry) {
|
|
|
13155
13166
|
if (at >= 0) renders[at] = written;
|
|
13156
13167
|
else renders.push(written);
|
|
13157
13168
|
evidence.renders = renders;
|
|
13158
|
-
writeEvidence(
|
|
13169
|
+
writeEvidence(path2, evidence);
|
|
13159
13170
|
return written;
|
|
13160
13171
|
} catch {
|
|
13161
13172
|
return null;
|
|
@@ -13168,8 +13179,8 @@ function recordNativeAudit(content, platform, status, checks, reason, release) {
|
|
|
13168
13179
|
}
|
|
13169
13180
|
if (status === "unavailable" && !reason?.trim()) throw new Error("--reason is required when --status unavailable");
|
|
13170
13181
|
const dir = resolve15(content);
|
|
13171
|
-
const
|
|
13172
|
-
const parsed = parseEvidence(
|
|
13182
|
+
const path2 = join24(dir, UX_EVIDENCE_PATH);
|
|
13183
|
+
const parsed = parseEvidence(path2);
|
|
13173
13184
|
if (parsed.error) throw new Error(`${UX_EVIDENCE_PATH} ${parsed.error}`);
|
|
13174
13185
|
const evidence = parsed.evidence ?? { version: 1, platforms: {} };
|
|
13175
13186
|
evidence.platforms[platform] = {
|
|
@@ -13179,12 +13190,12 @@ function recordNativeAudit(content, platform, status, checks, reason, release) {
|
|
|
13179
13190
|
...release?.releaseId && release.releaseHash ? { releaseId: release.releaseId, releaseHash: release.releaseHash } : {},
|
|
13180
13191
|
recordedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13181
13192
|
};
|
|
13182
|
-
writeEvidence(
|
|
13193
|
+
writeEvidence(path2, evidence);
|
|
13183
13194
|
return evidence;
|
|
13184
13195
|
}
|
|
13185
13196
|
function uxEvidenceForRelease(content, release) {
|
|
13186
13197
|
const { releaseId, releaseHash } = release;
|
|
13187
|
-
const
|
|
13198
|
+
const path2 = uxEvidencePath(content);
|
|
13188
13199
|
const base = {
|
|
13189
13200
|
path: UX_EVIDENCE_PATH,
|
|
13190
13201
|
platforms: [],
|
|
@@ -13194,8 +13205,8 @@ function uxEvidenceForRelease(content, release) {
|
|
|
13194
13205
|
inheritedScreens: [],
|
|
13195
13206
|
malformed: []
|
|
13196
13207
|
};
|
|
13197
|
-
if (!existsSync21(
|
|
13198
|
-
const parsed = parseEvidence(
|
|
13208
|
+
if (!existsSync21(path2)) return { ...base, state: "absent" };
|
|
13209
|
+
const parsed = parseEvidence(path2);
|
|
13199
13210
|
if (parsed.error) return { ...base, state: "unreadable", error: parsed.error };
|
|
13200
13211
|
if (!parsed.evidence) return { ...base, state: "absent" };
|
|
13201
13212
|
const recorded = [];
|
|
@@ -14248,9 +14259,9 @@ function placeholderHashes() {
|
|
|
14248
14259
|
const current = templateIconSha256();
|
|
14249
14260
|
return current ? [LEGACY_PLACEHOLDER_SHA256, current] : [LEGACY_PLACEHOLDER_SHA256];
|
|
14250
14261
|
}
|
|
14251
|
-
function fileSha256(
|
|
14262
|
+
function fileSha256(path2) {
|
|
14252
14263
|
try {
|
|
14253
|
-
return createHash7("sha256").update(readFileSync24(
|
|
14264
|
+
return createHash7("sha256").update(readFileSync24(path2)).digest("hex");
|
|
14254
14265
|
} catch {
|
|
14255
14266
|
return null;
|
|
14256
14267
|
}
|
|
@@ -14699,12 +14710,12 @@ function hostAppliesDeferredWidgetActions(app) {
|
|
|
14699
14710
|
const dir = stack.pop();
|
|
14700
14711
|
for (const entry of readdirSync13(dir, { withFileTypes: true })) {
|
|
14701
14712
|
if (entry.name.startsWith(".") || entry.name === "GeneratedLiveActivity") continue;
|
|
14702
|
-
const
|
|
14713
|
+
const path2 = join29(dir, entry.name);
|
|
14703
14714
|
if (entry.isDirectory()) {
|
|
14704
14715
|
if (entry.name.endsWith(".xcodeproj") || entry.name === "build") continue;
|
|
14705
|
-
stack.push(
|
|
14716
|
+
stack.push(path2);
|
|
14706
14717
|
} else if (entry.name.endsWith(".swift")) {
|
|
14707
|
-
if (readFileSync26(
|
|
14718
|
+
if (readFileSync26(path2, "utf8").includes("WidgetActionRelay.drain(")) return true;
|
|
14708
14719
|
}
|
|
14709
14720
|
}
|
|
14710
14721
|
}
|
|
@@ -14735,29 +14746,29 @@ function androidManifestPath2(app) {
|
|
|
14735
14746
|
function automotiveAppDescPath(app) {
|
|
14736
14747
|
return join29(dirname16(androidManifestPath2(app)), "res", "xml", "automotive_app_desc.xml");
|
|
14737
14748
|
}
|
|
14738
|
-
function applyToFile(
|
|
14739
|
-
if (!existsSync26(
|
|
14740
|
-
const before = readFileSync26(
|
|
14741
|
-
if (!hasMarkers(before, kind, label2)) return { path, outcome: "skipped" };
|
|
14749
|
+
function applyToFile(path2, kind, label2, render, check) {
|
|
14750
|
+
if (!existsSync26(path2)) return { path: path2, outcome: "skipped" };
|
|
14751
|
+
const before = readFileSync26(path2, "utf8");
|
|
14752
|
+
if (!hasMarkers(before, kind, label2)) return { path: path2, outcome: "skipped" };
|
|
14742
14753
|
const after = injectBlock(before, kind, label2, render);
|
|
14743
|
-
if (after === before) return { path, outcome: "unchanged" };
|
|
14744
|
-
if (check) return { path, outcome: "drift" };
|
|
14745
|
-
writeFileSync11(
|
|
14746
|
-
return { path, outcome: "written" };
|
|
14747
|
-
}
|
|
14748
|
-
function applyWholeFile(
|
|
14749
|
-
const current = existsSync26(
|
|
14750
|
-
if (current === content) return { path, outcome: "unchanged" };
|
|
14751
|
-
if (check) return { path, outcome: "drift" };
|
|
14752
|
-
mkdirSync12(dirname16(
|
|
14753
|
-
writeFileSync11(
|
|
14754
|
-
return { path, outcome: "written" };
|
|
14755
|
-
}
|
|
14756
|
-
function removeWholeFile(
|
|
14757
|
-
if (!existsSync26(
|
|
14758
|
-
if (check) return { path, outcome: "drift" };
|
|
14759
|
-
rmSync4(
|
|
14760
|
-
return { path, outcome: "removed" };
|
|
14754
|
+
if (after === before) return { path: path2, outcome: "unchanged" };
|
|
14755
|
+
if (check) return { path: path2, outcome: "drift" };
|
|
14756
|
+
writeFileSync11(path2, after);
|
|
14757
|
+
return { path: path2, outcome: "written" };
|
|
14758
|
+
}
|
|
14759
|
+
function applyWholeFile(path2, content, check) {
|
|
14760
|
+
const current = existsSync26(path2) ? readFileSync26(path2, "utf8") : null;
|
|
14761
|
+
if (current === content) return { path: path2, outcome: "unchanged" };
|
|
14762
|
+
if (check) return { path: path2, outcome: "drift" };
|
|
14763
|
+
mkdirSync12(dirname16(path2), { recursive: true });
|
|
14764
|
+
writeFileSync11(path2, content);
|
|
14765
|
+
return { path: path2, outcome: "written" };
|
|
14766
|
+
}
|
|
14767
|
+
function removeWholeFile(path2, check) {
|
|
14768
|
+
if (!existsSync26(path2)) return { path: path2, outcome: "skipped" };
|
|
14769
|
+
if (check) return { path: path2, outcome: "drift" };
|
|
14770
|
+
rmSync4(path2);
|
|
14771
|
+
return { path: path2, outcome: "removed" };
|
|
14761
14772
|
}
|
|
14762
14773
|
function genNativeConfig(app, opts = {}) {
|
|
14763
14774
|
const check = opts.check ?? false;
|
|
@@ -15003,15 +15014,15 @@ function collectBrandFonts(appDir2) {
|
|
|
15003
15014
|
const rel = typeof raw?.file === "string" ? raw.file : "";
|
|
15004
15015
|
if (!family || !postscriptName || !rel) continue;
|
|
15005
15016
|
if (rel.startsWith("/") || rel.split("/").includes("..")) continue;
|
|
15006
|
-
const
|
|
15017
|
+
const path2 = join30(appDir2, rel);
|
|
15007
15018
|
try {
|
|
15008
|
-
if (!lstatSync4(
|
|
15019
|
+
if (!lstatSync4(path2).isFile()) continue;
|
|
15009
15020
|
const root = realpathSync3(appDir2);
|
|
15010
|
-
if (!realpathSync3(
|
|
15021
|
+
if (!realpathSync3(path2).startsWith(root + sep6)) continue;
|
|
15011
15022
|
} catch {
|
|
15012
15023
|
continue;
|
|
15013
15024
|
}
|
|
15014
|
-
out.push({ family, postscriptName, weight, path });
|
|
15025
|
+
out.push({ family, postscriptName, weight, path: path2 });
|
|
15015
15026
|
}
|
|
15016
15027
|
return out;
|
|
15017
15028
|
}
|
|
@@ -15200,7 +15211,7 @@ async function loadContainedDevModule(name, entry, dir) {
|
|
|
15200
15211
|
// Both throw synchronously; `handleWant` awaits them inside its own try, so the guest sees an
|
|
15201
15212
|
// ordinary rejection exactly as it would from any failing transport — while the host keeps the
|
|
15202
15213
|
// record the guest's `catch` cannot erase.
|
|
15203
|
-
wixCall: (method,
|
|
15214
|
+
wixCall: (method, path2) => refuseHost("himalaya.wixApi.call", `${method} ${path2}`),
|
|
15204
15215
|
dispatch: (action) => refuseHost("himalaya.dispatch", action)
|
|
15205
15216
|
});
|
|
15206
15217
|
const session = ran.session;
|
|
@@ -15303,7 +15314,7 @@ async function loadContainedDevModule(name, entry, dir) {
|
|
|
15303
15314
|
createStore: () => storeStub,
|
|
15304
15315
|
...meta.dataRoutes?.length ? {
|
|
15305
15316
|
dataRoutes: Object.fromEntries(
|
|
15306
|
-
meta.dataRoutes.map((
|
|
15317
|
+
meta.dataRoutes.map((path2) => [path2, () => refuse(name, `the app data route ${JSON.stringify(path2)}`)])
|
|
15307
15318
|
)
|
|
15308
15319
|
} : {},
|
|
15309
15320
|
// NOT defaulted. An absent seed crosses as absent and the proxy carries `undefined`, which is
|
|
@@ -16095,8 +16106,8 @@ import { createHash as createHash9, randomBytes as randomBytes3 } from "node:cry
|
|
|
16095
16106
|
function b64url(buf) {
|
|
16096
16107
|
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
16097
16108
|
}
|
|
16098
|
-
async function postJson(
|
|
16099
|
-
const res = await fetch(`${API}${
|
|
16109
|
+
async function postJson(path2, body, auth) {
|
|
16110
|
+
const res = await fetch(`${API}${path2}`, {
|
|
16100
16111
|
method: "POST",
|
|
16101
16112
|
headers: { "Content-Type": "application/json", ...auth ? { Authorization: auth } : {} },
|
|
16102
16113
|
body: JSON.stringify(body)
|
|
@@ -16111,11 +16122,11 @@ async function mintVisitor(clientId) {
|
|
|
16111
16122
|
}
|
|
16112
16123
|
function isRedirectCallback(url, redirectUri) {
|
|
16113
16124
|
if (url.startsWith(redirectUri)) return true;
|
|
16114
|
-
const
|
|
16125
|
+
const path2 = (u) => u.pathname.replace(/\/+$/, "") || "/";
|
|
16115
16126
|
try {
|
|
16116
16127
|
const got = new URL(url);
|
|
16117
16128
|
const want = new URL(redirectUri);
|
|
16118
|
-
return got.protocol === want.protocol && got.host === want.host &&
|
|
16129
|
+
return got.protocol === want.protocol && got.host === want.host && path2(got) === path2(want);
|
|
16119
16130
|
} catch {
|
|
16120
16131
|
return false;
|
|
16121
16132
|
}
|
|
@@ -16205,8 +16216,8 @@ async function memberDirectRegister(clientId, redirectUri, email, password, firs
|
|
|
16205
16216
|
const memberToken = await exchangeSessionToken(clientId, redirectUri, visitorToken, sessionToken);
|
|
16206
16217
|
return { memberToken, visitorToken };
|
|
16207
16218
|
}
|
|
16208
|
-
async function webWixCall(method,
|
|
16209
|
-
const url = /^https?:\/\//i.test(
|
|
16219
|
+
async function webWixCall(method, path2, body, token, cookie, forwardedHeaders = {}) {
|
|
16220
|
+
const url = /^https?:\/\//i.test(path2) ? path2 : `${API}${path2.startsWith("/") ? path2 : "/" + path2}`;
|
|
16210
16221
|
if (!isWixTarget(url)) {
|
|
16211
16222
|
throw new Error(`refusing to send Wix credentials to a non-Wix host (${targetHost(url) || "no host"})`);
|
|
16212
16223
|
}
|
|
@@ -16276,10 +16287,10 @@ function resolveNetMocks(fileMocks, appDeclared) {
|
|
|
16276
16287
|
if (declared.length > 0) return { mocks: { mode: appDeclared?.mode, rules: declared }, source: "app" };
|
|
16277
16288
|
return null;
|
|
16278
16289
|
}
|
|
16279
|
-
function readNetMocksFile(
|
|
16290
|
+
function readNetMocksFile(path2) {
|
|
16280
16291
|
try {
|
|
16281
|
-
if (!existsSync30(
|
|
16282
|
-
const raw = JSON.parse(readFileSync30(
|
|
16292
|
+
if (!existsSync30(path2)) return null;
|
|
16293
|
+
const raw = JSON.parse(readFileSync30(path2, "utf-8"));
|
|
16283
16294
|
if (Array.isArray(raw)) return wixMockRuleErrors(raw).length ? null : { rules: raw };
|
|
16284
16295
|
if (raw && typeof raw === "object") {
|
|
16285
16296
|
const o = raw;
|
|
@@ -16357,20 +16368,20 @@ function parseTarget(target) {
|
|
|
16357
16368
|
});
|
|
16358
16369
|
return { host: u.host, path: u.pathname, query };
|
|
16359
16370
|
} catch {
|
|
16360
|
-
const
|
|
16371
|
+
const path2 = target.split("?")[0];
|
|
16361
16372
|
const query = {};
|
|
16362
16373
|
new URLSearchParams(target.split("?")[1] ?? "").forEach((v, k) => {
|
|
16363
16374
|
query[k] = v;
|
|
16364
16375
|
});
|
|
16365
|
-
return { host: "", path, query };
|
|
16376
|
+
return { host: "", path: path2, query };
|
|
16366
16377
|
}
|
|
16367
16378
|
}
|
|
16368
16379
|
async function handleWixGateway(gw, app, adminUrl, req, res, wixClientId) {
|
|
16369
16380
|
const url = req.url ?? "";
|
|
16370
|
-
const
|
|
16371
|
-
const scope =
|
|
16381
|
+
const path2 = url.split("?")[0];
|
|
16382
|
+
const scope = path2.startsWith("/__dev/wix/") ? "wix" : path2.startsWith("/__dev/net/") ? "net" : null;
|
|
16372
16383
|
if (!scope) return false;
|
|
16373
|
-
const suffix =
|
|
16384
|
+
const suffix = path2.slice(scope === "wix" ? "/__dev/wix/".length : "/__dev/net/".length);
|
|
16374
16385
|
const method = (req.method ?? "GET").toUpperCase();
|
|
16375
16386
|
if (suffix === "events" && method === "GET") {
|
|
16376
16387
|
res.writeHead(200, {
|
|
@@ -16784,17 +16795,17 @@ var init_sha256 = __esm({
|
|
|
16784
16795
|
});
|
|
16785
16796
|
|
|
16786
16797
|
// ../../core/serve-runtime/src/wix-bridge.ts
|
|
16787
|
-
function absoluteUrlRejection(
|
|
16798
|
+
function absoluteUrlRejection(path2) {
|
|
16788
16799
|
let host = "";
|
|
16789
16800
|
try {
|
|
16790
|
-
host = new URL(
|
|
16801
|
+
host = new URL(path2).host;
|
|
16791
16802
|
} catch {
|
|
16792
16803
|
}
|
|
16793
16804
|
return OWNER_SCOPED_WIX_HOST.test(host) ? "owner-only" : "open-proxy";
|
|
16794
16805
|
}
|
|
16795
|
-
async function wixVisitorCall(method,
|
|
16796
|
-
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(
|
|
16797
|
-
const url = `${WIX_API}${
|
|
16806
|
+
async function wixVisitorCall(method, path2, body, token, fetchImpl = fetch, forwardedHeaders = {}) {
|
|
16807
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(path2)) throw new Error("absolute URLs are not allowed");
|
|
16808
|
+
const url = `${WIX_API}${path2.startsWith("/") ? path2 : `/${path2}`}`;
|
|
16798
16809
|
const res = await fetchImpl(url, {
|
|
16799
16810
|
method,
|
|
16800
16811
|
// Same header shape the dev-server bridge has always sent (wixapis accepts the
|
|
@@ -16825,13 +16836,13 @@ function normalizeWixForwardedHeaders(input) {
|
|
|
16825
16836
|
function isSafeMsid(msid) {
|
|
16826
16837
|
return /^[0-9a-fA-F-]{10,64}$/.test(msid);
|
|
16827
16838
|
}
|
|
16828
|
-
function isOwnerSitesPath(
|
|
16829
|
-
return
|
|
16839
|
+
function isOwnerSitesPath(path2) {
|
|
16840
|
+
return path2 === OWNER_SITES_QUERY_PATH || path2 === OWNER_SITES_COUNT_PATH;
|
|
16830
16841
|
}
|
|
16831
|
-
async function wixOwnerSitesCall(
|
|
16832
|
-
if (!isOwnerSitesPath(
|
|
16842
|
+
async function wixOwnerSitesCall(path2, cookieHeader, body, fetchImpl = fetch) {
|
|
16843
|
+
if (!isOwnerSitesPath(path2)) throw new Error("not an owner-sites path");
|
|
16833
16844
|
const xsrf = /(?:^|;\s*)XSRF-TOKEN=([^;]+)/.exec(cookieHeader)?.[1];
|
|
16834
|
-
const res = await fetchImpl(`${WIX_API}${
|
|
16845
|
+
const res = await fetchImpl(`${WIX_API}${path2}`, {
|
|
16835
16846
|
method: "POST",
|
|
16836
16847
|
headers: {
|
|
16837
16848
|
Cookie: cookieHeader,
|
|
@@ -17106,8 +17117,8 @@ import { resolve as resolve24 } from "node:path";
|
|
|
17106
17117
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
17107
17118
|
function loadCatalog2(tag) {
|
|
17108
17119
|
if (catalogCache.has(tag)) return catalogCache.get(tag);
|
|
17109
|
-
const
|
|
17110
|
-
const map = existsSync31(
|
|
17120
|
+
const path2 = resolve24(ROOT4, `tools/l10n/catalog.${tag}.json`);
|
|
17121
|
+
const map = existsSync31(path2) ? sourceMap(parseCatalog(readFileSync31(path2, "utf8"))) : /* @__PURE__ */ new Map();
|
|
17111
17122
|
catalogCache.set(tag, map);
|
|
17112
17123
|
return map;
|
|
17113
17124
|
}
|
|
@@ -17116,8 +17127,8 @@ function pickLocale(acceptLanguage) {
|
|
|
17116
17127
|
const tags = acceptLanguage.split(",").map((s) => s.split(";")[0].trim().toLowerCase()).map((s) => s.split("-")[0]).filter((s) => s.length > 0);
|
|
17117
17128
|
for (const tag of tags) {
|
|
17118
17129
|
if (tag === "en") continue;
|
|
17119
|
-
const
|
|
17120
|
-
if (existsSync31(
|
|
17130
|
+
const path2 = resolve24(ROOT4, `tools/l10n/catalog.${tag}.json`);
|
|
17131
|
+
if (existsSync31(path2)) return tag;
|
|
17121
17132
|
}
|
|
17122
17133
|
return null;
|
|
17123
17134
|
}
|
|
@@ -17213,8 +17224,8 @@ function assignStableIds(descriptor) {
|
|
|
17213
17224
|
used.add(out);
|
|
17214
17225
|
return out;
|
|
17215
17226
|
};
|
|
17216
|
-
const assign2 = (node,
|
|
17217
|
-
const base = node.id && node.id.length > 0 ? node.id :
|
|
17227
|
+
const assign2 = (node, path2) => {
|
|
17228
|
+
const base = node.id && node.id.length > 0 ? node.id : path2;
|
|
17218
17229
|
node.id = uniquify(base);
|
|
17219
17230
|
const typeCounts = {};
|
|
17220
17231
|
forEachChildComponent(node, (child) => {
|
|
@@ -17222,7 +17233,7 @@ function assignStableIds(descriptor) {
|
|
|
17222
17233
|
const n = typeCounts[t] ?? 0;
|
|
17223
17234
|
typeCounts[t] = n + 1;
|
|
17224
17235
|
const seg = n === 0 ? t : `${t}.${n}`;
|
|
17225
|
-
assign2(child, `${
|
|
17236
|
+
assign2(child, `${path2}/${seg}`);
|
|
17226
17237
|
});
|
|
17227
17238
|
};
|
|
17228
17239
|
if (isNode(descriptor.payload)) assign2(descriptor.payload, descriptor.screenId);
|
|
@@ -18142,8 +18153,8 @@ var init_tier4_verifier = __esm({
|
|
|
18142
18153
|
async verifyServedFile(bundleId, relPath, providedBytes) {
|
|
18143
18154
|
const expected = this.expectedSri(bundleId, relPath);
|
|
18144
18155
|
if (!expected) return { ok: true };
|
|
18145
|
-
const
|
|
18146
|
-
const bytes2 = providedBytes ?? (existsSync33(
|
|
18156
|
+
const path2 = resolve25(this.tier4Root, bundleId, relPath);
|
|
18157
|
+
const bytes2 = providedBytes ?? (existsSync33(path2) ? readFileSync33(path2) : null);
|
|
18147
18158
|
if (!bytes2) return { ok: false, reason: "file not found" };
|
|
18148
18159
|
if (computeSri(bytes2) !== expected) return { ok: false, reason: "sri mismatch" };
|
|
18149
18160
|
return { ok: true };
|
|
@@ -18235,9 +18246,9 @@ function targetTenant(url, headers2, hostApp) {
|
|
|
18235
18246
|
const hdr = headers2["x-himalaya-app"];
|
|
18236
18247
|
const headerApp = Array.isArray(hdr) ? hdr[0] : hdr;
|
|
18237
18248
|
let app = headerApp && headerApp.trim() ? headerApp.trim() : void 0;
|
|
18238
|
-
const [
|
|
18249
|
+
const [path2, query] = url.split("?");
|
|
18239
18250
|
if (!app) {
|
|
18240
|
-
const m = /^\/v1\/(?:app-config|action-handlers)\/([^/?]+)/.exec(
|
|
18251
|
+
const m = /^\/v1\/(?:app-config|action-handlers)\/([^/?]+)/.exec(path2);
|
|
18241
18252
|
if (m) app = decodeURIComponent(m[1]);
|
|
18242
18253
|
}
|
|
18243
18254
|
if (!app && query) {
|
|
@@ -18249,9 +18260,9 @@ function targetTenant(url, headers2, hostApp) {
|
|
|
18249
18260
|
return app;
|
|
18250
18261
|
}
|
|
18251
18262
|
function shouldServeFromPlane(url, headers2, hostApp) {
|
|
18252
|
-
const
|
|
18253
|
-
if (
|
|
18254
|
-
if (!
|
|
18263
|
+
const path2 = url.split("?")[0];
|
|
18264
|
+
if (path2 === "/v1/apps" || path2 === "/v1/templates") return true;
|
|
18265
|
+
if (!path2.startsWith("/v1/")) return false;
|
|
18255
18266
|
return targetTenant(url, headers2, hostApp) !== null;
|
|
18256
18267
|
}
|
|
18257
18268
|
async function proxyToServe(base, req, res) {
|
|
@@ -18511,8 +18522,8 @@ var init_FakeServiceProvider = __esm({
|
|
|
18511
18522
|
constructor(services) {
|
|
18512
18523
|
this.services = services;
|
|
18513
18524
|
}
|
|
18514
|
-
value(
|
|
18515
|
-
const raw =
|
|
18525
|
+
value(path2) {
|
|
18526
|
+
const raw = path2.startsWith("$service:") ? path2.slice("$service:".length) : path2;
|
|
18516
18527
|
const dot = raw.indexOf(".");
|
|
18517
18528
|
const name = dot < 0 ? raw : raw.slice(0, dot);
|
|
18518
18529
|
const tail = dot < 0 ? "" : raw.slice(dot + 1);
|
|
@@ -18524,8 +18535,8 @@ var init_FakeServiceProvider = __esm({
|
|
|
18524
18535
|
}
|
|
18525
18536
|
return cur;
|
|
18526
18537
|
}
|
|
18527
|
-
subscribe(
|
|
18528
|
-
cb(this.value(
|
|
18538
|
+
subscribe(path2, cb) {
|
|
18539
|
+
cb(this.value(path2));
|
|
18529
18540
|
return () => {
|
|
18530
18541
|
};
|
|
18531
18542
|
}
|
|
@@ -19025,21 +19036,21 @@ function useResolvedScalar(v, ctx) {
|
|
|
19025
19036
|
return bound ?? void 0;
|
|
19026
19037
|
}
|
|
19027
19038
|
function useBoundValue(ctx, binding2) {
|
|
19028
|
-
const
|
|
19039
|
+
const path2 = servicePath(binding2);
|
|
19029
19040
|
const active = !!ctx.provider && !!binding2;
|
|
19030
19041
|
const [state, setState] = useState(() => ({
|
|
19031
|
-
path,
|
|
19032
|
-
v: active ? ctx.provider.value(
|
|
19042
|
+
path: path2,
|
|
19043
|
+
v: active ? ctx.provider.value(path2) : void 0
|
|
19033
19044
|
}));
|
|
19034
|
-
const current = state.path ===
|
|
19035
|
-
if (state.path !==
|
|
19045
|
+
const current = state.path === path2 ? state.v : active ? ctx.provider.value(path2) : void 0;
|
|
19046
|
+
if (state.path !== path2) setState({ path: path2, v: current });
|
|
19036
19047
|
useEffect(() => {
|
|
19037
19048
|
if (!ctx.provider || !binding2) return;
|
|
19038
19049
|
return ctx.provider.subscribe(
|
|
19039
|
-
|
|
19040
|
-
(nv) => setState((prev) => prev.path ===
|
|
19050
|
+
path2,
|
|
19051
|
+
(nv) => setState((prev) => prev.path === path2 && Object.is(prev.v, nv) ? prev : { path: path2, v: nv })
|
|
19041
19052
|
);
|
|
19042
|
-
}, [ctx.provider,
|
|
19053
|
+
}, [ctx.provider, path2, binding2]);
|
|
19043
19054
|
return active ? current : void 0;
|
|
19044
19055
|
}
|
|
19045
19056
|
function useBoundValues(ctx, bindings) {
|
|
@@ -19050,16 +19061,16 @@ function useBoundValues(ctx, bindings) {
|
|
|
19050
19061
|
[key2]
|
|
19051
19062
|
);
|
|
19052
19063
|
const [values, setValues] = useState(
|
|
19053
|
-
() => paths.map((
|
|
19064
|
+
() => paths.map((path2) => ctx.provider && path2 ? ctx.provider.value(path2) : void 0)
|
|
19054
19065
|
);
|
|
19055
19066
|
useEffect(() => {
|
|
19056
19067
|
if (!ctx.provider) {
|
|
19057
19068
|
setValues(paths.map(() => void 0));
|
|
19058
19069
|
return;
|
|
19059
19070
|
}
|
|
19060
|
-
setValues(paths.map((
|
|
19071
|
+
setValues(paths.map((path2) => path2 ? ctx.provider.value(path2) : void 0));
|
|
19061
19072
|
const disposers = paths.map(
|
|
19062
|
-
(
|
|
19073
|
+
(path2, i) => path2 ? ctx.provider.subscribe(path2, (v) => setValues((prev) => {
|
|
19063
19074
|
const next = prev.slice();
|
|
19064
19075
|
next[i] = v;
|
|
19065
19076
|
return next;
|
|
@@ -19450,7 +19461,6 @@ function shouldRevealError(args) {
|
|
|
19450
19461
|
var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
|
|
19451
19462
|
var init_validation = __esm({
|
|
19452
19463
|
"../../core/ts/src/validation.ts"() {
|
|
19453
|
-
"use strict";
|
|
19454
19464
|
EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
|
|
19455
19465
|
URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
|
|
19456
19466
|
INTEGER_RE = /^[+-]?[0-9]+$/;
|
|
@@ -22623,9 +22633,9 @@ var init_worker_subtree_safe_types_generated = __esm({
|
|
|
22623
22633
|
function isRecord(value) {
|
|
22624
22634
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22625
22635
|
}
|
|
22626
|
-
function valueAtPath(value,
|
|
22636
|
+
function valueAtPath(value, path2) {
|
|
22627
22637
|
let current = value;
|
|
22628
|
-
for (const segment of
|
|
22638
|
+
for (const segment of path2.split(".")) {
|
|
22629
22639
|
if (!isRecord(current)) return void 0;
|
|
22630
22640
|
current = current[segment];
|
|
22631
22641
|
}
|
|
@@ -22839,8 +22849,8 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
|
|
|
22839
22849
|
return;
|
|
22840
22850
|
}
|
|
22841
22851
|
const props = node.body.props;
|
|
22842
|
-
for (const
|
|
22843
|
-
for (const
|
|
22852
|
+
for (const path2 of rule.actions) checkAction(valueAtPath(props, path2));
|
|
22853
|
+
for (const path2 of WORKER_SUBTREE_COMMON_ACTION_PATHS) checkAction(valueAtPath(node, path2));
|
|
22844
22854
|
for (const childRule of rule.children) {
|
|
22845
22855
|
const value = valueAtPath(props, childRule.path);
|
|
22846
22856
|
if (value === void 0 || value === null) {
|
|
@@ -22875,7 +22885,6 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
|
|
|
22875
22885
|
var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
|
|
22876
22886
|
var init_worker_subtree = __esm({
|
|
22877
22887
|
"../../core/ts/src/worker-subtree.ts"() {
|
|
22878
|
-
"use strict";
|
|
22879
22888
|
init_worker_subtree_safe_types_generated();
|
|
22880
22889
|
WORKER_SUBTREE_CEILINGS = Object.freeze({
|
|
22881
22890
|
maxEncodedBytes: 65536,
|
|
@@ -22893,9 +22902,9 @@ var init_worker_subtree = __esm({
|
|
|
22893
22902
|
// ../../core/web-renderer/src/renderNode.tsx
|
|
22894
22903
|
import React5 from "react";
|
|
22895
22904
|
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
22896
|
-
function boundTokenName(
|
|
22897
|
-
if (typeof
|
|
22898
|
-
const r = resolveScalarStatic(
|
|
22905
|
+
function boundTokenName(path2, fallback, ctx) {
|
|
22906
|
+
if (typeof path2 === "string" && path2) {
|
|
22907
|
+
const r = resolveScalarStatic(path2, ctx);
|
|
22899
22908
|
if (typeof r === "string" && r) return r;
|
|
22900
22909
|
}
|
|
22901
22910
|
return fallback;
|
|
@@ -24201,8 +24210,8 @@ function renderNodeInner(node, ctx) {
|
|
|
24201
24210
|
}
|
|
24202
24211
|
}
|
|
24203
24212
|
const bind = {};
|
|
24204
|
-
const addBind = (cssProp,
|
|
24205
|
-
const k = measureKey(
|
|
24213
|
+
const addBind = (cssProp, path2) => {
|
|
24214
|
+
const k = measureKey(path2);
|
|
24206
24215
|
if (k) bind[cssProp] = k;
|
|
24207
24216
|
};
|
|
24208
24217
|
addBind("height", m?.heightPath ?? m?.height_path);
|
|
@@ -24293,9 +24302,9 @@ function renderNodeInner(node, ctx) {
|
|
|
24293
24302
|
}
|
|
24294
24303
|
return out;
|
|
24295
24304
|
}
|
|
24296
|
-
function boundModNumber(
|
|
24297
|
-
if (typeof
|
|
24298
|
-
const r = resolveScalarStatic(
|
|
24305
|
+
function boundModNumber(path2, ctx) {
|
|
24306
|
+
if (typeof path2 !== "string" || !path2 || measureKey(path2) != null || !isBinding(path2)) return void 0;
|
|
24307
|
+
const r = resolveScalarStatic(path2, ctx);
|
|
24299
24308
|
const n = typeof r === "number" ? r : typeof r === "string" && r.trim() !== "" ? Number(r) : NaN;
|
|
24300
24309
|
return Number.isFinite(n) ? n : void 0;
|
|
24301
24310
|
}
|
|
@@ -25242,8 +25251,8 @@ var init_renderNode = __esm({
|
|
|
25242
25251
|
WorkerSubtreeNode = withExtras("WorkerSubtreeNode", ({ props, ctx, wrap, nodeId }) => {
|
|
25243
25252
|
const slotId = nodeId;
|
|
25244
25253
|
const extra = wrap;
|
|
25245
|
-
const
|
|
25246
|
-
const value = useBoundValue(ctx, typeof
|
|
25254
|
+
const path2 = props.treeJsonPath ?? props.tree_json_path;
|
|
25255
|
+
const value = useBoundValue(ctx, typeof path2 === "string" ? path2 : "");
|
|
25247
25256
|
const policy = props.policy;
|
|
25248
25257
|
const catalog = ctx.provider && typeof ctx.provider.listActions === "function" ? ctx.provider : null;
|
|
25249
25258
|
const validation = React5.useMemo(() => {
|
|
@@ -25672,8 +25681,8 @@ var init_renderNode = __esm({
|
|
|
25672
25681
|
this.state = state;
|
|
25673
25682
|
for (const cb of this.listeners) cb(this.value("media"));
|
|
25674
25683
|
}
|
|
25675
|
-
value(
|
|
25676
|
-
const bare =
|
|
25684
|
+
value(path2) {
|
|
25685
|
+
const bare = path2.replace(/^\$service:/, "");
|
|
25677
25686
|
const parts = bare.split(".").filter(Boolean);
|
|
25678
25687
|
if (parts[0] === "media") parts.shift();
|
|
25679
25688
|
let value = this.state;
|
|
@@ -25683,8 +25692,8 @@ var init_renderNode = __esm({
|
|
|
25683
25692
|
}
|
|
25684
25693
|
return value;
|
|
25685
25694
|
}
|
|
25686
|
-
subscribe(
|
|
25687
|
-
const wrapped = () => cb(this.value(
|
|
25695
|
+
subscribe(path2, cb) {
|
|
25696
|
+
const wrapped = () => cb(this.value(path2));
|
|
25688
25697
|
this.listeners.add(wrapped);
|
|
25689
25698
|
wrapped();
|
|
25690
25699
|
return () => this.listeners.delete(wrapped);
|
|
@@ -26935,9 +26944,9 @@ var init_renderNode = __esm({
|
|
|
26935
26944
|
});
|
|
26936
26945
|
AvatarStripNode = withExtras("AvatarStripNode", ({ props, ctx, wrap }) => {
|
|
26937
26946
|
const C = ctx.color;
|
|
26938
|
-
const
|
|
26939
|
-
const bound = useResolvedScalar(
|
|
26940
|
-
const raw =
|
|
26947
|
+
const path2 = props.avatarsPath ?? props.avatars_path;
|
|
26948
|
+
const bound = useResolvedScalar(path2, ctx);
|
|
26949
|
+
const raw = path2 != null ? bound : props.avatars;
|
|
26941
26950
|
const avatars = Array.isArray(raw) ? raw : [];
|
|
26942
26951
|
const size = props.size ?? 36;
|
|
26943
26952
|
const maxVisible = props.maxVisible ?? 4;
|
|
@@ -28568,27 +28577,27 @@ function resolveTreeScalar(v, provider, itemScope) {
|
|
|
28568
28577
|
if (v.startsWith("$service:")) return provider.value(v) ?? void 0;
|
|
28569
28578
|
return v;
|
|
28570
28579
|
}
|
|
28571
|
-
function collectResolvedMediaRecord(record2,
|
|
28572
|
-
if (typeof record2.actionId === "string" ||
|
|
28580
|
+
function collectResolvedMediaRecord(record2, path2, context) {
|
|
28581
|
+
if (typeof record2.actionId === "string" || path2 && typeof record2.body === "object") return;
|
|
28573
28582
|
for (const [key2, child] of Object.entries(record2)) {
|
|
28574
|
-
collectResolvedMediaValues(child,
|
|
28583
|
+
collectResolvedMediaValues(child, path2 ? `${path2}.${key2}` : key2, {
|
|
28575
28584
|
...context,
|
|
28576
28585
|
insideMediaProperty: context.insideMediaProperty || isMediaValueProperty(key2)
|
|
28577
28586
|
});
|
|
28578
28587
|
}
|
|
28579
28588
|
}
|
|
28580
|
-
function collectResolvedMediaValues(value,
|
|
28589
|
+
function collectResolvedMediaValues(value, path2, context) {
|
|
28581
28590
|
const resolved2 = typeof value === "string" ? resolveTreeScalar(value, context.provider, context.itemScope) : value;
|
|
28582
28591
|
if (typeof resolved2 === "string") {
|
|
28583
|
-
if (context.insideMediaProperty) context.values[
|
|
28592
|
+
if (context.insideMediaProperty) context.values[path2] = resolved2;
|
|
28584
28593
|
return;
|
|
28585
28594
|
}
|
|
28586
28595
|
if (Array.isArray(resolved2)) {
|
|
28587
|
-
resolved2.forEach((item, index) => collectResolvedMediaValues(item, `${
|
|
28596
|
+
resolved2.forEach((item, index) => collectResolvedMediaValues(item, `${path2}[${index}]`, context));
|
|
28588
28597
|
return;
|
|
28589
28598
|
}
|
|
28590
28599
|
if (resolved2 && typeof resolved2 === "object") {
|
|
28591
|
-
collectResolvedMediaRecord(resolved2,
|
|
28600
|
+
collectResolvedMediaRecord(resolved2, path2, context);
|
|
28592
28601
|
}
|
|
28593
28602
|
}
|
|
28594
28603
|
function collectComponentMediaValues(type, props, context) {
|
|
@@ -28609,12 +28618,12 @@ function collectNativeOnly(node) {
|
|
|
28609
28618
|
walk2(node);
|
|
28610
28619
|
return [...found].sort();
|
|
28611
28620
|
}
|
|
28612
|
-
function buildRenderTree(node,
|
|
28621
|
+
function buildRenderTree(node, path2 = "$", provider = null, itemScope = void 0, includeRawProps = false, env = null) {
|
|
28613
28622
|
if (!node || typeof node !== "object") return null;
|
|
28614
28623
|
const obj2 = node;
|
|
28615
28624
|
const body = obj2.body ?? {};
|
|
28616
28625
|
const type = typeof body.type === "string" ? body.type : "Unknown";
|
|
28617
|
-
const id = typeof obj2.id === "string" && obj2.id ? obj2.id :
|
|
28626
|
+
const id = typeof obj2.id === "string" && obj2.id ? obj2.id : path2;
|
|
28618
28627
|
const out = { id, type };
|
|
28619
28628
|
if (typeof body.package === "string") out.package = body.package;
|
|
28620
28629
|
const props = body.props ?? {};
|
|
@@ -28723,7 +28732,7 @@ async function renderDescriptorWeb(descriptor, tokens, scheme, wantPng, services
|
|
|
28723
28732
|
const stickyHeader = isSduiNode(desc.stickyHeader) ? desc.stickyHeader : void 0;
|
|
28724
28733
|
const stickyFooter = isSduiNode(desc.stickyFooter) ? desc.stickyFooter : void 0;
|
|
28725
28734
|
const clientEnv = clientEnvFor(scheme, width, isRTL);
|
|
28726
|
-
const treeOf = (node,
|
|
28735
|
+
const treeOf = (node, path2, prov) => buildRenderTree(node, path2, prov, void 0, true, clientEnv);
|
|
28727
28736
|
const renderTree = composeStickyTree(
|
|
28728
28737
|
treeOf(payload, "$", null) ?? void 0,
|
|
28729
28738
|
stickyHeader ? treeOf(stickyHeader, "$.stickyHeader", null) : null,
|
|
@@ -28923,8 +28932,8 @@ function declaredFamilies(tokens) {
|
|
|
28923
28932
|
async function faceBytes(face, catalog, opts) {
|
|
28924
28933
|
try {
|
|
28925
28934
|
if (opts.source) {
|
|
28926
|
-
const
|
|
28927
|
-
return
|
|
28935
|
+
const path2 = opts.source(face.file, face.sha256);
|
|
28936
|
+
return path2 ? readFileSync34(path2) : null;
|
|
28928
28937
|
}
|
|
28929
28938
|
const bytes2 = await catalogFaceBytes(face.sha256, { catalog, ...opts.fetchFace ? { fetchFace: opts.fetchFace } : {} });
|
|
28930
28939
|
return bytes2 ?? null;
|
|
@@ -29431,13 +29440,13 @@ function validateName(name) {
|
|
|
29431
29440
|
if (typeof name !== "string") fail("name must be a string");
|
|
29432
29441
|
if (!/^[a-z][a-z0-9]*(?:[-_.][a-z0-9]+)*$/.test(name)) fail(`name must be lowercase kebab-case: "${name}"`);
|
|
29433
29442
|
}
|
|
29434
|
-
function validateFunctionRoute(method,
|
|
29443
|
+
function validateFunctionRoute(method, path2) {
|
|
29435
29444
|
if (!HTTP_METHODS.includes(method)) fail(`method must be one of ${HTTP_METHODS.join(", ")}`);
|
|
29436
|
-
if (
|
|
29437
|
-
fail(`path must be an absolute, normalized route without query syntax: "${
|
|
29445
|
+
if (path2 !== "/" && (!/^\/[A-Za-z0-9._~!$&'()*+,;=:@%/-]+$/.test(path2) || path2.includes("//") || path2.endsWith("/"))) {
|
|
29446
|
+
fail(`path must be an absolute, normalized route without query syntax: "${path2}"`);
|
|
29438
29447
|
}
|
|
29439
|
-
const params = [...
|
|
29440
|
-
if (new Set(params).size !== params.length) fail(`path contains duplicate parameter names: "${
|
|
29448
|
+
const params = [...path2.matchAll(/:([A-Za-z][A-Za-z0-9_]*)/g)].map((match) => match[1]);
|
|
29449
|
+
if (new Set(params).size !== params.length) fail(`path contains duplicate parameter names: "${path2}"`);
|
|
29441
29450
|
}
|
|
29442
29451
|
function validateFunctionDefinition(definition) {
|
|
29443
29452
|
validateName(definition.name);
|
|
@@ -30846,9 +30855,9 @@ function nativeSourceFiles(directory, extension, buildDirMaxDepth, depth = 1) {
|
|
|
30846
30855
|
return entries.flatMap((entry) => {
|
|
30847
30856
|
if (NATIVE_SCRATCH_DIRS.has(entry.name)) return [];
|
|
30848
30857
|
if (entry.name === BUILD_OUTPUT_DIR && depth <= buildDirMaxDepth) return [];
|
|
30849
|
-
const
|
|
30850
|
-
if (entry.isDirectory()) return nativeSourceFiles(
|
|
30851
|
-
return entry.name.endsWith(extension) ? [
|
|
30858
|
+
const path2 = resolve28(directory, entry.name);
|
|
30859
|
+
if (entry.isDirectory()) return nativeSourceFiles(path2, extension, buildDirMaxDepth, depth + 1);
|
|
30860
|
+
return entry.name.endsWith(extension) ? [path2] : [];
|
|
30852
30861
|
});
|
|
30853
30862
|
}
|
|
30854
30863
|
function registeredActions(source) {
|
|
@@ -31111,10 +31120,10 @@ function readJsonAt(app, file, root) {
|
|
|
31111
31120
|
}
|
|
31112
31121
|
}
|
|
31113
31122
|
function writeJsonAt(app, file, root, value) {
|
|
31114
|
-
const
|
|
31115
|
-
mkdirSync15(dirname20(
|
|
31116
|
-
writeFileSync12(
|
|
31117
|
-
return
|
|
31123
|
+
const path2 = appConfigPath(app, file, root);
|
|
31124
|
+
mkdirSync15(dirname20(path2), { recursive: true });
|
|
31125
|
+
writeFileSync12(path2, JSON.stringify(value, null, 2) + "\n");
|
|
31126
|
+
return path2;
|
|
31118
31127
|
}
|
|
31119
31128
|
function sanitizeOverlay(raw) {
|
|
31120
31129
|
if (!("appIconBadgeSources" in raw)) return raw;
|
|
@@ -31350,8 +31359,8 @@ function handleL10nRequest(req, res, state) {
|
|
|
31350
31359
|
if (!state.app || app !== state.app.name) {
|
|
31351
31360
|
return sendJson(res, 404, { error: "unknown_app", app }, cors);
|
|
31352
31361
|
}
|
|
31353
|
-
const
|
|
31354
|
-
if (!existsSync36(
|
|
31362
|
+
const path2 = resolve30(state.app.dir, "l10n", `${tag}.json`);
|
|
31363
|
+
if (!existsSync36(path2)) {
|
|
31355
31364
|
res.writeHead(204, cors);
|
|
31356
31365
|
res.end();
|
|
31357
31366
|
return;
|
|
@@ -31360,7 +31369,7 @@ function handleL10nRequest(req, res, state) {
|
|
|
31360
31369
|
let messages;
|
|
31361
31370
|
try {
|
|
31362
31371
|
messages = Object.fromEntries(
|
|
31363
|
-
keyMap(parseCatalog(readFileSync39(
|
|
31372
|
+
keyMap(parseCatalog(readFileSync39(path2, "utf8")), { sourceFallback: tag === sourceLocale })
|
|
31364
31373
|
);
|
|
31365
31374
|
} catch {
|
|
31366
31375
|
return sendJson(res, 500, { error: "catalog_unreadable", app, tag }, cors);
|
|
@@ -31590,16 +31599,16 @@ async function handleOwnerSitesRequest(req, res) {
|
|
|
31590
31599
|
async function handleOwnerChatRequest(req, res) {
|
|
31591
31600
|
const cors = { "access-control-allow-origin": "*" };
|
|
31592
31601
|
const u = new URL(req.url ?? "", "http://localhost");
|
|
31593
|
-
const
|
|
31602
|
+
const path2 = u.pathname;
|
|
31594
31603
|
const { resolveMetaSiteId, listChatroomsLive, sendChatMessageLive } = await import("./apps/wix-owner-clone-live.js");
|
|
31595
|
-
if (
|
|
31604
|
+
if (path2 === "/v1/owner-chat/chatrooms" && req.method === "GET") {
|
|
31596
31605
|
const metaSiteId = u.searchParams.get("metaSiteId") || await resolveMetaSiteId();
|
|
31597
31606
|
if (!metaSiteId) return sendJson(res, 400, { error: "no_meta_site" }, cors);
|
|
31598
31607
|
const rooms = await listChatroomsLive(metaSiteId);
|
|
31599
31608
|
if (rooms == null) return sendJson(res, 502, { error: "chatrooms_unavailable" }, cors);
|
|
31600
31609
|
return sendJson(res, 200, { chatrooms: rooms }, cors);
|
|
31601
31610
|
}
|
|
31602
|
-
if (
|
|
31611
|
+
if (path2 === "/v1/owner-chat/send" && req.method === "POST") {
|
|
31603
31612
|
let parsed;
|
|
31604
31613
|
try {
|
|
31605
31614
|
parsed = JSON.parse(await readBody2(req) || "{}");
|
|
@@ -32318,7 +32327,7 @@ function webWixSession(req, res, state) {
|
|
|
32318
32327
|
async function handleWebWix(req, res, state) {
|
|
32319
32328
|
const session = webWixSession(req, res, state);
|
|
32320
32329
|
const auth = resolveWebWixAuth(state.app);
|
|
32321
|
-
const
|
|
32330
|
+
const path2 = new URL(req.url ?? "", "http://localhost").pathname;
|
|
32322
32331
|
const readJson3 = async () => {
|
|
32323
32332
|
const chunks = [];
|
|
32324
32333
|
for await (const c of req) chunks.push(c);
|
|
@@ -32335,7 +32344,7 @@ async function handleWebWix(req, res, state) {
|
|
|
32335
32344
|
res.setHeader("access-control-allow-origin", "*");
|
|
32336
32345
|
res.end(JSON.stringify(obj2));
|
|
32337
32346
|
};
|
|
32338
|
-
if (
|
|
32347
|
+
if (path2 === "/v1/__webwix/login" && req.method === "POST") {
|
|
32339
32348
|
const b = await readJson3();
|
|
32340
32349
|
try {
|
|
32341
32350
|
const { memberToken, visitorToken } = await memberDirectLogin(
|
|
@@ -32352,7 +32361,7 @@ async function handleWebWix(req, res, state) {
|
|
|
32352
32361
|
return reply(200, { ok: false, error: String(e?.message ?? e) });
|
|
32353
32362
|
}
|
|
32354
32363
|
}
|
|
32355
|
-
if (
|
|
32364
|
+
if (path2 === "/v1/__webwix/call" && req.method === "POST") {
|
|
32356
32365
|
const b = await readJson3();
|
|
32357
32366
|
if (b.ownerMsid !== void 0 || b.checkOwnerSession === true) {
|
|
32358
32367
|
const msid = String(b.ownerMsid ?? "");
|
|
@@ -32439,12 +32448,12 @@ async function handleWebWix(req, res, state) {
|
|
|
32439
32448
|
return reply(200, { status: 0, body: JSON.stringify({ error: String(e?.message ?? e) }) });
|
|
32440
32449
|
}
|
|
32441
32450
|
}
|
|
32442
|
-
if (
|
|
32451
|
+
if (path2 === "/v1/__webwix/logout" && req.method === "POST") {
|
|
32443
32452
|
session.memberToken = void 0;
|
|
32444
32453
|
session.email = void 0;
|
|
32445
32454
|
return reply(200, { ok: true });
|
|
32446
32455
|
}
|
|
32447
|
-
if (
|
|
32456
|
+
if (path2 === "/v1/__webwix/identity" && (req.method === "GET" || req.method === "POST")) {
|
|
32448
32457
|
if (!session.memberToken) return reply(200, { authenticated: false, userId: null, email: "" });
|
|
32449
32458
|
let userId = null;
|
|
32450
32459
|
try {
|
|
@@ -32468,7 +32477,7 @@ async function handleWebWix(req, res, state) {
|
|
|
32468
32477
|
} : null
|
|
32469
32478
|
});
|
|
32470
32479
|
}
|
|
32471
|
-
if (
|
|
32480
|
+
if (path2 === "/v1/__webwix/register" && req.method === "POST") {
|
|
32472
32481
|
const b = await readJson3();
|
|
32473
32482
|
try {
|
|
32474
32483
|
const { memberToken, visitorToken } = await memberDirectRegister(
|
|
@@ -32885,8 +32894,8 @@ async function handleDev(req, res, state) {
|
|
|
32885
32894
|
}
|
|
32886
32895
|
async function handleAdminPlayground(req, res, state) {
|
|
32887
32896
|
const url = req.url ?? "";
|
|
32888
|
-
const
|
|
32889
|
-
const sampleMatch = /^\/v1\/admin\/sdui-samples\/([^/]+)$/.exec(
|
|
32897
|
+
const path2 = url.split("?")[0];
|
|
32898
|
+
const sampleMatch = /^\/v1\/admin\/sdui-samples\/([^/]+)$/.exec(path2);
|
|
32890
32899
|
if (sampleMatch && req.method === "GET") {
|
|
32891
32900
|
const name = decodeURIComponent(sampleMatch[1]);
|
|
32892
32901
|
if (!/^[a-zA-Z0-9._-]+$/.test(name)) return sendJson(res, 400, { error: "bad_name" });
|
|
@@ -32897,7 +32906,7 @@ async function handleAdminPlayground(req, res, state) {
|
|
|
32897
32906
|
return sendJson(res, 404, { error: "sample_not_found", name });
|
|
32898
32907
|
}
|
|
32899
32908
|
}
|
|
32900
|
-
if (
|
|
32909
|
+
if (path2 === "/v1/admin/sdui-samples" && req.method === "GET") {
|
|
32901
32910
|
try {
|
|
32902
32911
|
const { readdir } = await import("node:fs/promises");
|
|
32903
32912
|
const files = (await readdir(SAMPLES_ROOT)).filter((f) => f.endsWith(".json"));
|
|
@@ -32906,7 +32915,7 @@ async function handleAdminPlayground(req, res, state) {
|
|
|
32906
32915
|
return sendJson(res, 500, { error: err.message });
|
|
32907
32916
|
}
|
|
32908
32917
|
}
|
|
32909
|
-
if (
|
|
32918
|
+
if (path2 === "/v1/admin/screens" && req.method === "GET") {
|
|
32910
32919
|
const meta = state.app.meta;
|
|
32911
32920
|
const fixedIds = meta.screenIds;
|
|
32912
32921
|
const fixedSet = new Set(fixedIds);
|
|
@@ -32955,12 +32964,12 @@ async function handleAdminPlayground(req, res, state) {
|
|
|
32955
32964
|
templatedPatterns: meta.templatedPatterns
|
|
32956
32965
|
});
|
|
32957
32966
|
}
|
|
32958
|
-
const historyMatch = /^\/v1\/admin\/screens\/(.+?)\/history(?:\?|$)/.exec(
|
|
32967
|
+
const historyMatch = /^\/v1\/admin\/screens\/(.+?)\/history(?:\?|$)/.exec(path2);
|
|
32959
32968
|
if (historyMatch && req.method === "GET") {
|
|
32960
32969
|
const screenId = decodeURIComponent(historyMatch[1]);
|
|
32961
32970
|
return sendJson(res, 200, { screenId, history: state.localOverrideHistory.get(screenId) ?? [] });
|
|
32962
32971
|
}
|
|
32963
|
-
const revertMatch = /^\/v1\/admin\/screens\/(.+?)\/revert(?:\?|$)/.exec(
|
|
32972
|
+
const revertMatch = /^\/v1\/admin\/screens\/(.+?)\/revert(?:\?|$)/.exec(path2);
|
|
32964
32973
|
if (revertMatch && req.method === "POST") {
|
|
32965
32974
|
const screenId = decodeURIComponent(revertMatch[1]);
|
|
32966
32975
|
const historyId = Number(new URLSearchParams(url.split("?")[1] ?? "").get("historyId"));
|
|
@@ -32976,7 +32985,7 @@ async function handleAdminPlayground(req, res, state) {
|
|
|
32976
32985
|
invalidate(state, screenId);
|
|
32977
32986
|
return sendJson(res, 200, { status: "ok", screenId, revertedTo: historyId });
|
|
32978
32987
|
}
|
|
32979
|
-
if (
|
|
32988
|
+
if (path2 === "/v1/admin/tab-badge" && req.method === "POST") {
|
|
32980
32989
|
let body;
|
|
32981
32990
|
try {
|
|
32982
32991
|
body = JSON.parse(await readBody2(req));
|
|
@@ -32995,7 +33004,7 @@ async function handleAdminPlayground(req, res, state) {
|
|
|
32995
33004
|
);
|
|
32996
33005
|
return sendJson(res, 200, { status: "ok", tabId: body.tabId, count: clearing ? null : body.count });
|
|
32997
33006
|
}
|
|
32998
|
-
const validateMatch = /^\/v1\/admin\/screens\/(.+?)\/validate(?:\?|$)/.exec(
|
|
33007
|
+
const validateMatch = /^\/v1\/admin\/screens\/(.+?)\/validate(?:\?|$)/.exec(path2);
|
|
32999
33008
|
if (validateMatch && req.method === "GET") {
|
|
33000
33009
|
const screenId = decodeURIComponent(validateMatch[1]);
|
|
33001
33010
|
const strict = /[?&]strict=1(?:&|$)/.test(url);
|
|
@@ -33023,7 +33032,7 @@ async function handleAdminPlayground(req, res, state) {
|
|
|
33023
33032
|
});
|
|
33024
33033
|
return sendJson(res, report2.ok ? 200 : 422, report2);
|
|
33025
33034
|
}
|
|
33026
|
-
const detailMatch = /^\/v1\/admin\/screens\/([^/]+)$/.exec(
|
|
33035
|
+
const detailMatch = /^\/v1\/admin\/screens\/([^/]+)$/.exec(path2);
|
|
33027
33036
|
if (detailMatch && req.method === "GET") {
|
|
33028
33037
|
const screenId = decodeURIComponent(detailMatch[1]);
|
|
33029
33038
|
const wantBuilt = /[?&]source=built(?:&|$)/.test(url);
|
|
@@ -33060,7 +33069,7 @@ async function handleAdminPlayground(req, res, state) {
|
|
|
33060
33069
|
invalidate(state, screenId);
|
|
33061
33070
|
return sendJson(res, existed ? 200 : 404, { status: existed ? "ok" : "not_found" });
|
|
33062
33071
|
}
|
|
33063
|
-
if (
|
|
33072
|
+
if (path2 === "/v1/admin/app-config" && state.app) {
|
|
33064
33073
|
const built = deriveNavigationConfig(state.app.meta);
|
|
33065
33074
|
if (req.method === "GET") {
|
|
33066
33075
|
const effective = state.appConfigOverride ? deepMerge3(built, state.appConfigOverride) : built;
|
|
@@ -33085,7 +33094,7 @@ async function handleAdminPlayground(req, res, state) {
|
|
|
33085
33094
|
return sendJson(res, existed ? 200 : 404, { status: existed ? "ok" : "not_found" });
|
|
33086
33095
|
}
|
|
33087
33096
|
}
|
|
33088
|
-
if (
|
|
33097
|
+
if (path2 === "/v1/admin/tokens" && state.app) {
|
|
33089
33098
|
const built = readAppTokens(state) ?? {};
|
|
33090
33099
|
if (req.method === "GET") {
|
|
33091
33100
|
const effective = state.tokensOverride ? deepMerge3(built, state.tokensOverride) : built;
|
|
@@ -33110,7 +33119,7 @@ async function handleAdminPlayground(req, res, state) {
|
|
|
33110
33119
|
return sendJson(res, existed ? 200 : 404, { status: existed ? "ok" : "not_found" });
|
|
33111
33120
|
}
|
|
33112
33121
|
}
|
|
33113
|
-
return sendJson(res, 404, { error: "unknown_admin_route", path });
|
|
33122
|
+
return sendJson(res, 404, { error: "unknown_admin_route", path: path2 });
|
|
33114
33123
|
}
|
|
33115
33124
|
function isNavControlPatch(patch) {
|
|
33116
33125
|
if (!patch || typeof patch !== "object") return false;
|
|
@@ -33165,10 +33174,10 @@ async function readBundleFile(name, dir) {
|
|
|
33165
33174
|
resolve30(root, `${name}.js`),
|
|
33166
33175
|
resolve30(root, name)
|
|
33167
33176
|
]);
|
|
33168
|
-
for (const
|
|
33169
|
-
if (!roots.some((root) =>
|
|
33177
|
+
for (const path2 of candidates) {
|
|
33178
|
+
if (!roots.some((root) => path2.startsWith(root))) continue;
|
|
33170
33179
|
try {
|
|
33171
|
-
const bytes2 = await readFile(
|
|
33180
|
+
const bytes2 = await readFile(path2);
|
|
33172
33181
|
const integrity2 = "sha256-" + createHash15("sha256").update(bytes2).digest("base64");
|
|
33173
33182
|
return { bytes: bytes2, integrity: integrity2 };
|
|
33174
33183
|
} catch {
|
|
@@ -33348,10 +33357,10 @@ function handleActionHandlersManifest(res, app) {
|
|
|
33348
33357
|
}
|
|
33349
33358
|
async function handleActionHandlerBundleGet(res, app) {
|
|
33350
33359
|
if (!/^[A-Za-z0-9_.\-]+$/.test(app)) return sendJson(res, 404, { error: "not_found" });
|
|
33351
|
-
const
|
|
33352
|
-
if (!
|
|
33360
|
+
const path2 = resolve30(ACTION_HANDLERS_ROOT, `${app}.handlers.js`);
|
|
33361
|
+
if (!path2.startsWith(ACTION_HANDLERS_ROOT)) return sendJson(res, 404, { error: "not_found" });
|
|
33353
33362
|
try {
|
|
33354
|
-
const bytes2 = await readFile(
|
|
33363
|
+
const bytes2 = await readFile(path2);
|
|
33355
33364
|
const integrity2 = "sha256-" + createHash15("sha256").update(bytes2).digest("base64");
|
|
33356
33365
|
res.setHeader("content-type", "application/javascript; charset=utf-8");
|
|
33357
33366
|
res.setHeader("cache-control", "max-age=300");
|
|
@@ -34125,13 +34134,13 @@ var init_capability_fixtures = __esm({
|
|
|
34125
34134
|
};
|
|
34126
34135
|
MEDIA_EXT = (url) => {
|
|
34127
34136
|
if (typeof url !== "string") return null;
|
|
34128
|
-
let
|
|
34137
|
+
let path2;
|
|
34129
34138
|
try {
|
|
34130
|
-
|
|
34139
|
+
path2 = new URL(url).pathname;
|
|
34131
34140
|
} catch {
|
|
34132
|
-
|
|
34141
|
+
path2 = url.split("#")[0].split("?")[0];
|
|
34133
34142
|
}
|
|
34134
|
-
const segment =
|
|
34143
|
+
const segment = path2.split("/").pop() ?? "";
|
|
34135
34144
|
const m = /\.([a-z0-9]{2,5})$/i.exec(segment);
|
|
34136
34145
|
return m ? m[1].toLowerCase() : null;
|
|
34137
34146
|
};
|
|
@@ -34292,9 +34301,9 @@ var init_capability_fixtures = __esm({
|
|
|
34292
34301
|
// made every write resolve to the same file, and a consumer passing that handle onward (an export
|
|
34293
34302
|
// writing `exports/<id>.gpx`) referenced something that does not exist.
|
|
34294
34303
|
"capability.files.write": (p, ctx) => {
|
|
34295
|
-
const
|
|
34296
|
-
const name =
|
|
34297
|
-
return { uri: `file:///${
|
|
34304
|
+
const path2 = typeof p.path === "string" && p.path ? p.path : "crawl/written.txt";
|
|
34305
|
+
const name = path2.split("/").pop() || path2;
|
|
34306
|
+
return { uri: `file:///${path2.replace(/^\/+/, "")}`, name, mimeType: typeof p.mimeType === "string" ? p.mimeType : "application/octet-stream", sizeBytes: 1024, modifiedAt: ctx.clock };
|
|
34298
34307
|
},
|
|
34299
34308
|
"capability.files.remove": () => ({ removed: true })
|
|
34300
34309
|
};
|
|
@@ -34581,14 +34590,14 @@ function relationalSignature(state) {
|
|
|
34581
34590
|
}
|
|
34582
34591
|
function listLengths(state, depth = 4) {
|
|
34583
34592
|
const out = {};
|
|
34584
|
-
const walk2 = (node,
|
|
34593
|
+
const walk2 = (node, path2, left) => {
|
|
34585
34594
|
if (left < 0 || node === null || typeof node !== "object") return;
|
|
34586
34595
|
if (Array.isArray(node)) {
|
|
34587
|
-
out[
|
|
34596
|
+
out[path2] = node.length;
|
|
34588
34597
|
return;
|
|
34589
34598
|
}
|
|
34590
34599
|
for (const [k, v] of Object.entries(node)) {
|
|
34591
|
-
walk2(v,
|
|
34600
|
+
walk2(v, path2 ? `${path2}.${k}` : k, left - 1);
|
|
34592
34601
|
}
|
|
34593
34602
|
};
|
|
34594
34603
|
walk2(state, "", depth);
|
|
@@ -34609,26 +34618,26 @@ function summarizeDiff(aSig, bSig, limit = 3) {
|
|
|
34609
34618
|
if (t === void 0) return "undefined";
|
|
34610
34619
|
return t.length > 80 ? `${t.slice(0, 77)}\u2026` : t;
|
|
34611
34620
|
};
|
|
34612
|
-
const walk2 = (x, y,
|
|
34621
|
+
const walk2 = (x, y, path2) => {
|
|
34613
34622
|
if (diffs.length >= limit) return;
|
|
34614
34623
|
const bothObjects = x !== null && y !== null && typeof x === "object" && typeof y === "object" && !Array.isArray(x) && !Array.isArray(y);
|
|
34615
34624
|
if (bothObjects) {
|
|
34616
34625
|
for (const k of /* @__PURE__ */ new Set([...Object.keys(x), ...Object.keys(y)])) {
|
|
34617
|
-
walk2(x[k], y[k],
|
|
34626
|
+
walk2(x[k], y[k], path2 ? `${path2}.${k}` : k);
|
|
34618
34627
|
}
|
|
34619
34628
|
return;
|
|
34620
34629
|
}
|
|
34621
34630
|
if (Array.isArray(x) && Array.isArray(y)) {
|
|
34622
34631
|
if (x.length !== y.length) {
|
|
34623
|
-
diffs.push(`${
|
|
34632
|
+
diffs.push(`${path2 || "state"}: ${x.length} \u2192 ${y.length} items`);
|
|
34624
34633
|
return;
|
|
34625
34634
|
}
|
|
34626
|
-
for (let i = 0; i < x.length && diffs.length < limit; i++) walk2(x[i], y[i], `${
|
|
34635
|
+
for (let i = 0; i < x.length && diffs.length < limit; i++) walk2(x[i], y[i], `${path2}[${i}]`);
|
|
34627
34636
|
return;
|
|
34628
34637
|
}
|
|
34629
34638
|
const xs = brief(x);
|
|
34630
34639
|
const ys = brief(y);
|
|
34631
|
-
if (xs !== ys) diffs.push(`${
|
|
34640
|
+
if (xs !== ys) diffs.push(`${path2 || "state"}: ${xs} \u2192 ${ys}`);
|
|
34632
34641
|
};
|
|
34633
34642
|
walk2(a, b, "");
|
|
34634
34643
|
return diffs.slice(0, limit).join("; ");
|
|
@@ -34717,6 +34726,7 @@ function actionSites(payload) {
|
|
|
34717
34726
|
actionId: a.actionId,
|
|
34718
34727
|
params: a.params ?? {},
|
|
34719
34728
|
...a.args ? { args: a.args } : {},
|
|
34729
|
+
...a.presentation ? { presentation: a.presentation } : {},
|
|
34720
34730
|
...ambient ? { itemsPath: ambient } : {},
|
|
34721
34731
|
// `rec` IS the prop bag that carries this callback — for a plain node that is
|
|
34722
34732
|
// `body.props`, and for a FormField variant the nested `text`/`picker`/… object, which
|
|
@@ -34835,8 +34845,8 @@ function sourceOfStack(stack, bundleMap) {
|
|
|
34835
34845
|
return mapBundleFrame(bundleMap, Number(m[1]), Number(m[2]) - 1) ?? void 0;
|
|
34836
34846
|
}
|
|
34837
34847
|
function netTransport(rules) {
|
|
34838
|
-
return async (method,
|
|
34839
|
-
const [bare, search] = String(
|
|
34848
|
+
return async (method, path2, body) => {
|
|
34849
|
+
const [bare, search] = String(path2).split("?", 2);
|
|
34840
34850
|
const query = {};
|
|
34841
34851
|
if (search) for (const [k, v] of new URLSearchParams(search)) query[k] = v;
|
|
34842
34852
|
const res = resolveScenario(rules, {
|
|
@@ -34883,9 +34893,9 @@ function layeredTransport(layers) {
|
|
|
34883
34893
|
const cms = layers.cmsSeed && Object.keys(layers.cmsSeed).length ? layers.cmsSeed : null;
|
|
34884
34894
|
const canned = layers.canned && Object.keys(layers.canned).length ? layers.canned : null;
|
|
34885
34895
|
const label2 = [rules && "mocked", cms && "cms", canned && "canned"].filter(Boolean).join("+") || "offline";
|
|
34886
|
-
const call = async (method,
|
|
34896
|
+
const call = async (method, path2, body) => {
|
|
34887
34897
|
const m = String(method).toUpperCase();
|
|
34888
|
-
const p = String(
|
|
34898
|
+
const p = String(path2);
|
|
34889
34899
|
const [bare, search] = p.split("?", 2);
|
|
34890
34900
|
if (rules) {
|
|
34891
34901
|
const query = {};
|
|
@@ -35364,9 +35374,9 @@ async function crawlScreenInner(opts) {
|
|
|
35364
35374
|
const resolveItem = (v) => {
|
|
35365
35375
|
if (typeof v !== "string" || !v.startsWith("$item")) return v;
|
|
35366
35376
|
if (!row0) return v;
|
|
35367
|
-
const
|
|
35368
|
-
if (!
|
|
35369
|
-
return pathValue(row0,
|
|
35377
|
+
const path2 = v === "$item" ? "" : v.startsWith("$item.") ? v.slice("$item.".length) : "";
|
|
35378
|
+
if (!path2) return v;
|
|
35379
|
+
return pathValue(row0, path2);
|
|
35370
35380
|
};
|
|
35371
35381
|
const target = resolveItem(merged.screenId);
|
|
35372
35382
|
if (typeof target !== "string" || !target || target.includes("$")) continue;
|
|
@@ -35466,6 +35476,23 @@ async function crawlScreenInner(opts) {
|
|
|
35466
35476
|
actionsSkipped.push({ action: s.actionId, why: "embedded-preview" });
|
|
35467
35477
|
return false;
|
|
35468
35478
|
});
|
|
35479
|
+
if (!opts.capabilitySuccess) {
|
|
35480
|
+
for (const site of sites) {
|
|
35481
|
+
if (site.actionId !== "himi.open") continue;
|
|
35482
|
+
if (["back", "dismiss", "alert", "snackbar"].includes(site.presentation ?? "")) continue;
|
|
35483
|
+
const target = site.args?.screenId ?? site.params.screenId;
|
|
35484
|
+
if (target != null && target !== "") continue;
|
|
35485
|
+
findings.push({
|
|
35486
|
+
screen: screenId,
|
|
35487
|
+
trigger: "boot",
|
|
35488
|
+
invariant: "nav-target-absent",
|
|
35489
|
+
severity: "error",
|
|
35490
|
+
at: site.componentId ?? void 0,
|
|
35491
|
+
message: '"himi.open" has no screenId \u2014 the tap opens nothing',
|
|
35492
|
+
hint: 'Pass { screenId: "detail", id: "selected-id" } in params. "screen" is not a routing key; put destination input alongside screenId.'
|
|
35493
|
+
});
|
|
35494
|
+
}
|
|
35495
|
+
}
|
|
35469
35496
|
const boot = (skipAppear = false) => bundleJs ? bootScreenWorker({ bundleJs, descriptor, wixCall, screenId, inputOverride: opts.inputOverride, budgetMs: opts.budgetMs, clock: opts.clock, seed: opts.seed, skipAppear, localDbSchema: opts.localDbSchema, capabilitySuccess: opts.capabilitySuccess === true, ...opts.evaluator ? { evaluator: opts.evaluator } : {} }) : null;
|
|
35470
35497
|
const check = (trigger, state, errors, defects = {}) => {
|
|
35471
35498
|
for (const [svc, paths] of Object.entries(defects)) {
|
|
@@ -35787,8 +35814,8 @@ async function crawlScreenHostileInner(opts, variant) {
|
|
|
35787
35814
|
const base = layeredTransport({ rules: opts.rules, cmsSeed: opts.cmsSeed, canned: opts.canned });
|
|
35788
35815
|
if (base.label === "offline") return [];
|
|
35789
35816
|
const axis = `hostile:${variant}`;
|
|
35790
|
-
const wixCall = variant === "empty" ? async (method,
|
|
35791
|
-
throw new Error(`Wix 500 for ${String(method).toUpperCase()} ${String(
|
|
35817
|
+
const wixCall = variant === "empty" ? async (method, path2, body) => emptiedArrays(await base.call(method, path2, body)) : async (method, path2) => {
|
|
35818
|
+
throw new Error(`Wix 500 for ${String(method).toUpperCase()} ${String(path2).split("?")[0]}`);
|
|
35792
35819
|
};
|
|
35793
35820
|
let w;
|
|
35794
35821
|
try {
|
|
@@ -35991,17 +36018,17 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
35991
36018
|
localDbSchema: opts.localDbSchema,
|
|
35992
36019
|
capabilitySuccess: opts.capabilitySuccess === true
|
|
35993
36020
|
});
|
|
35994
|
-
const pathLabel = (
|
|
36021
|
+
const pathLabel = (path2) => path2.map((i) => sites[i].actionId.replace(/^tier5\./, "")).join(" \u2192 ");
|
|
35995
36022
|
while (queue.length) {
|
|
35996
36023
|
if (visited.size >= maxNodes || dispatches >= maxDispatches) {
|
|
35997
36024
|
capped = true;
|
|
35998
36025
|
break;
|
|
35999
36026
|
}
|
|
36000
|
-
const
|
|
36027
|
+
const path2 = queue.shift();
|
|
36001
36028
|
const w = await boot();
|
|
36002
36029
|
try {
|
|
36003
36030
|
let threwAt = null;
|
|
36004
|
-
for (const [step, siteIdx] of
|
|
36031
|
+
for (const [step, siteIdx] of path2.entries()) {
|
|
36005
36032
|
const site = sites[siteIdx];
|
|
36006
36033
|
const parsed = parseWorkerAction(site.actionId);
|
|
36007
36034
|
const handle = w.handles[parsed.service];
|
|
@@ -36023,7 +36050,7 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
36023
36050
|
try {
|
|
36024
36051
|
await handle.dispatch(parsed.action, ...workerArgs(effective));
|
|
36025
36052
|
} catch (e) {
|
|
36026
|
-
if (step ===
|
|
36053
|
+
if (step === path2.length - 1 && path2.length >= 2) {
|
|
36027
36054
|
const source = sourceOfStack(e.stack, opts.bundleMap);
|
|
36028
36055
|
findings.push({
|
|
36029
36056
|
screen: screenId,
|
|
@@ -36032,7 +36059,7 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
36032
36059
|
severity: "error",
|
|
36033
36060
|
axis: "deep",
|
|
36034
36061
|
...source ? { source } : {},
|
|
36035
|
-
message: `after ${pathLabel(
|
|
36062
|
+
message: `after ${pathLabel(path2)}: ${parsed.action}: ${errText(e)}`,
|
|
36036
36063
|
hint: "this chain of taps crashes the worker \u2014 each step passed alone, the SEQUENCE is the bug"
|
|
36037
36064
|
});
|
|
36038
36065
|
}
|
|
@@ -36046,8 +36073,8 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
36046
36073
|
const hash = deepStateSignature(state, defects);
|
|
36047
36074
|
if (visited.has(hash)) continue;
|
|
36048
36075
|
visited.add(hash);
|
|
36049
|
-
if (
|
|
36050
|
-
const last = sites[
|
|
36076
|
+
if (path2.length >= 2) {
|
|
36077
|
+
const last = sites[path2[path2.length - 1]];
|
|
36051
36078
|
const lastTrigger = { tap: last.componentId, key: last.key, action: last.actionId };
|
|
36052
36079
|
for (const [svc, paths] of Object.entries(defects)) {
|
|
36053
36080
|
for (const p of paths) {
|
|
@@ -36057,7 +36084,7 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
36057
36084
|
invariant: "non-finite-number",
|
|
36058
36085
|
severity: "error",
|
|
36059
36086
|
axis: "deep",
|
|
36060
|
-
message: `after ${pathLabel(
|
|
36087
|
+
message: `after ${pathLabel(path2)}: ${svc} state holds a non-finite number: ${p}`,
|
|
36061
36088
|
at: `${svc}.${p.split(" = ")[0]}`,
|
|
36062
36089
|
hint: "a chain of taps produced the bad arithmetic \u2014 each step alone was fine; check what the SEQUENCE accumulates"
|
|
36063
36090
|
});
|
|
@@ -36071,7 +36098,7 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
36071
36098
|
invariant: d.kind,
|
|
36072
36099
|
severity: "error",
|
|
36073
36100
|
axis: "deep",
|
|
36074
|
-
message: `after ${pathLabel(
|
|
36101
|
+
message: `after ${pathLabel(path2)}: ${resolvedDefectMessage(d)}`,
|
|
36075
36102
|
at,
|
|
36076
36103
|
field,
|
|
36077
36104
|
hint: resolvedDefectHint(d)
|
|
@@ -36079,8 +36106,8 @@ async function crawlScreenDeep(opts, deep) {
|
|
|
36079
36106
|
});
|
|
36080
36107
|
}
|
|
36081
36108
|
}
|
|
36082
|
-
if (
|
|
36083
|
-
for (let i = 0; i < sites.length; i++) queue.push([...
|
|
36109
|
+
if (path2.length < deep.depth) {
|
|
36110
|
+
for (let i = 0; i < sites.length; i++) queue.push([...path2, i]);
|
|
36084
36111
|
}
|
|
36085
36112
|
} finally {
|
|
36086
36113
|
w.dispose();
|
|
@@ -36171,13 +36198,13 @@ async function crawlScreenRelations(opts) {
|
|
|
36171
36198
|
capabilitySuccess: opts.capabilitySuccess === true,
|
|
36172
36199
|
...opts.evaluator ? { evaluator: opts.evaluator } : {}
|
|
36173
36200
|
});
|
|
36174
|
-
const replay = async (
|
|
36201
|
+
const replay = async (path2, rowFor = () => null) => {
|
|
36175
36202
|
const w = await boot();
|
|
36176
36203
|
try {
|
|
36177
36204
|
if (w.errors.length) return null;
|
|
36178
36205
|
let prev = snapshot(w).state;
|
|
36179
36206
|
const bootState = prev;
|
|
36180
|
-
for (const [i, site] of
|
|
36207
|
+
for (const [i, site] of path2.entries()) {
|
|
36181
36208
|
const parsed = parseWorkerAction(site.actionId);
|
|
36182
36209
|
const h = w.handles[parsed.service];
|
|
36183
36210
|
if (!h || !h.actionNames().includes(parsed.action)) return null;
|
|
@@ -36533,9 +36560,9 @@ function routesOverlap(left, right) {
|
|
|
36533
36560
|
return segment.startsWith(":") || other.startsWith(":") || segment === other;
|
|
36534
36561
|
});
|
|
36535
36562
|
}
|
|
36536
|
-
function validateRouteConflicts(
|
|
36563
|
+
function validateRouteConflicts(definitions2) {
|
|
36537
36564
|
const seen = [];
|
|
36538
|
-
for (const definition of
|
|
36565
|
+
for (const definition of definitions2) {
|
|
36539
36566
|
validateFunctionDefinition(definition);
|
|
36540
36567
|
const previous = seen.find((route) => route.method === definition.method && routesOverlap(route.path, definition.path));
|
|
36541
36568
|
if (previous) throw new Error(`duplicate or ambiguous function route: ${definition.name} conflicts with ${previous.name} at ${definition.method} ${definition.path}`);
|
|
@@ -36589,13 +36616,13 @@ function rejectUnsafeSource(name, source) {
|
|
|
36589
36616
|
throw new Error(`function ${name} must export handler`);
|
|
36590
36617
|
}
|
|
36591
36618
|
}
|
|
36592
|
-
async function buildFunctions(
|
|
36593
|
-
validateRouteConflicts(
|
|
36619
|
+
async function buildFunctions(definitions2, sources, options = {}) {
|
|
36620
|
+
validateRouteConflicts(definitions2);
|
|
36594
36621
|
validateDependencyPolicy(options.dependencies ?? [], options.dependencyPolicy);
|
|
36595
36622
|
const sbom = createFunctionSbom(options.dependencies ?? []);
|
|
36596
36623
|
const runBuild = await (_buildP ??= loadBuild());
|
|
36597
36624
|
const built = [];
|
|
36598
|
-
for (const definition of
|
|
36625
|
+
for (const definition of definitions2) {
|
|
36599
36626
|
const source = sources[definition.name];
|
|
36600
36627
|
if (typeof source !== "string") throw new Error(`missing source for function ${definition.name}`);
|
|
36601
36628
|
assertStaticDependencySource(source);
|
|
@@ -36747,10 +36774,10 @@ function l10nLintOptions(locale, appDir2) {
|
|
|
36747
36774
|
const tags = (locale.translations ?? []).filter((t) => t !== locale.default);
|
|
36748
36775
|
const catalog = /* @__PURE__ */ new Set();
|
|
36749
36776
|
for (const tag of tags) {
|
|
36750
|
-
const
|
|
36751
|
-
if (!existsSync37(
|
|
36777
|
+
const path2 = join34(appDir2, "l10n", `${tag}.json`);
|
|
36778
|
+
if (!existsSync37(path2)) continue;
|
|
36752
36779
|
try {
|
|
36753
|
-
const parsed = JSON.parse(readFileSync40(
|
|
36780
|
+
const parsed = JSON.parse(readFileSync40(path2, "utf8"));
|
|
36754
36781
|
for (const m of Object.values(parsed.messages ?? {})) {
|
|
36755
36782
|
if (typeof m?.source === "string" && typeof m.translation === "string" && m.translation.length > 0) {
|
|
36756
36783
|
catalog.add(m.source);
|
|
@@ -37020,8 +37047,8 @@ async function buildRelease(app, dest, opts = {}) {
|
|
|
37020
37047
|
function countingWixCall(base) {
|
|
37021
37048
|
let returned = 0;
|
|
37022
37049
|
return {
|
|
37023
|
-
call: async (method,
|
|
37024
|
-
const out = await base(method,
|
|
37050
|
+
call: async (method, path2, body) => {
|
|
37051
|
+
const out = await base(method, path2, body);
|
|
37025
37052
|
returned += 1;
|
|
37026
37053
|
return out;
|
|
37027
37054
|
},
|
|
@@ -37112,9 +37139,9 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
37112
37139
|
);
|
|
37113
37140
|
}
|
|
37114
37141
|
const token = await mintVisitor(clientId);
|
|
37115
|
-
liveWixCall = async (method,
|
|
37142
|
+
liveWixCall = async (method, path2, body) => {
|
|
37116
37143
|
const bodyStr = body === void 0 ? void 0 : typeof body === "string" ? body : JSON.stringify(body);
|
|
37117
|
-
const r = await webWixCall(method,
|
|
37144
|
+
const r = await webWixCall(method, path2, bodyStr, token);
|
|
37118
37145
|
if (r.status < 200 || r.status >= 300) throw new Error(`HTTP ${r.status}: ${String(r.body).slice(0, 300)}`);
|
|
37119
37146
|
try {
|
|
37120
37147
|
return r.body ? JSON.parse(r.body) : {};
|
|
@@ -37211,9 +37238,9 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
37211
37238
|
const MAX_AUTHORING_DOC_BYTES = 128 * 1024;
|
|
37212
37239
|
if (store.putDoc) {
|
|
37213
37240
|
for (const [name, file] of [["spec", "SPEC.md"], ["mobile-ux", "MOBILE-UX.md"]]) {
|
|
37214
|
-
const
|
|
37215
|
-
if (!existsSync37(
|
|
37216
|
-
const bytes2 = readFileSync40(
|
|
37241
|
+
const path2 = join34(preloaded.dir, file);
|
|
37242
|
+
if (!existsSync37(path2)) continue;
|
|
37243
|
+
const bytes2 = readFileSync40(path2);
|
|
37217
37244
|
if (bytes2.length === 0 || bytes2.length > MAX_AUTHORING_DOC_BYTES) {
|
|
37218
37245
|
throw new Error(`${file} must be non-empty and at most ${MAX_AUTHORING_DOC_BYTES} bytes to ship with a release.`);
|
|
37219
37246
|
}
|
|
@@ -37641,7 +37668,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
37641
37668
|
}
|
|
37642
37669
|
if (store.putWidget) {
|
|
37643
37670
|
const bakedWidgets = await bakeWidgets(
|
|
37644
|
-
(
|
|
37671
|
+
(path2) => devFetch(`${base}${path2}`, { headers: { "X-Himalaya-App": app } }),
|
|
37645
37672
|
(widgetId, json5) => store.putWidget(app, widgetId, json5),
|
|
37646
37673
|
// `opts.tier5Dir`, NOT the `tier5Dir` local — that one falls back to the
|
|
37647
37674
|
// repo-global dir, where this package's widgets cannot be told from anyone
|
|
@@ -38400,8 +38427,8 @@ async function captchaRequest(options) {
|
|
|
38400
38427
|
}
|
|
38401
38428
|
const setup = options.operation === "setup";
|
|
38402
38429
|
const base = options.target.control.replace(/\/+$/, "");
|
|
38403
|
-
const
|
|
38404
|
-
const response = await (options.fetchImpl ?? fetch)(base +
|
|
38430
|
+
const path2 = setup ? "/v1/admin/captcha/setup" : `/v1/admin/captcha?app=${encodeURIComponent(options.input.app)}`;
|
|
38431
|
+
const response = await (options.fetchImpl ?? fetch)(base + path2, {
|
|
38405
38432
|
method: setup ? "POST" : "GET",
|
|
38406
38433
|
redirect: "error",
|
|
38407
38434
|
signal: AbortSignal.timeout(6e4),
|
|
@@ -38453,9 +38480,9 @@ __export(captcha_exports, {
|
|
|
38453
38480
|
});
|
|
38454
38481
|
import { readFileSync as readFileSync41 } from "node:fs";
|
|
38455
38482
|
import { resolve as resolve32 } from "node:path";
|
|
38456
|
-
function readObject(
|
|
38483
|
+
function readObject(path2) {
|
|
38457
38484
|
try {
|
|
38458
|
-
return JSON.parse(readFileSync41(
|
|
38485
|
+
return JSON.parse(readFileSync41(path2, "utf8"));
|
|
38459
38486
|
} catch {
|
|
38460
38487
|
return {};
|
|
38461
38488
|
}
|
|
@@ -38533,11 +38560,11 @@ async function pushSetupRequest(options) {
|
|
|
38533
38560
|
return refuse3("push_setup_body_too_large");
|
|
38534
38561
|
}
|
|
38535
38562
|
const base = options.target.control.replace(/\/+$/, "");
|
|
38536
|
-
let
|
|
38563
|
+
let path2 = "/v1/admin/push/setup";
|
|
38537
38564
|
if (!setup) {
|
|
38538
38565
|
const q = new URLSearchParams({ app: options.query.app, site: options.query.site });
|
|
38539
38566
|
if (options.query.verify) q.set("verify", options.query.verify);
|
|
38540
|
-
|
|
38567
|
+
path2 += `?${q.toString()}`;
|
|
38541
38568
|
}
|
|
38542
38569
|
const headers2 = {
|
|
38543
38570
|
"x-control-token": options.target.controlToken,
|
|
@@ -38548,7 +38575,7 @@ async function pushSetupRequest(options) {
|
|
|
38548
38575
|
...options.previewTag ? { "x-wix-route-serve": options.previewTag } : {}
|
|
38549
38576
|
};
|
|
38550
38577
|
try {
|
|
38551
|
-
const response = await (options.fetchImpl ?? fetch)(base +
|
|
38578
|
+
const response = await (options.fetchImpl ?? fetch)(base + path2, {
|
|
38552
38579
|
method: setup ? "POST" : "GET",
|
|
38553
38580
|
headers: headers2,
|
|
38554
38581
|
redirect: "error",
|
|
@@ -38601,9 +38628,9 @@ var init_push_setup_apple_credentials = __esm({
|
|
|
38601
38628
|
// src/push-onboarding.ts
|
|
38602
38629
|
import { existsSync as existsSync38, mkdirSync as mkdirSync17, readFileSync as readFileSync42, statSync as statSync7, writeFileSync as writeFileSync13, chmodSync as chmodSync2 } from "node:fs";
|
|
38603
38630
|
import { basename as basename9, dirname as dirname22, join as join35, resolve as resolve33 } from "node:path";
|
|
38604
|
-
function readJson2(
|
|
38631
|
+
function readJson2(path2) {
|
|
38605
38632
|
try {
|
|
38606
|
-
const parsed = JSON.parse(readFileSync42(
|
|
38633
|
+
const parsed = JSON.parse(readFileSync42(path2, "utf8"));
|
|
38607
38634
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
38608
38635
|
} catch {
|
|
38609
38636
|
return {};
|
|
@@ -38676,10 +38703,10 @@ function localIdentityRefusal(i) {
|
|
|
38676
38703
|
}
|
|
38677
38704
|
return null;
|
|
38678
38705
|
}
|
|
38679
|
-
function readKeyFile(
|
|
38706
|
+
function readKeyFile(path2) {
|
|
38680
38707
|
let size;
|
|
38681
38708
|
try {
|
|
38682
|
-
size = statSync7(
|
|
38709
|
+
size = statSync7(path2).size;
|
|
38683
38710
|
} catch {
|
|
38684
38711
|
return { ok: false, code: "key_file_unreadable", reason: "cannot read the selected key file; check its path and file permissions" };
|
|
38685
38712
|
}
|
|
@@ -38688,7 +38715,7 @@ function readKeyFile(path) {
|
|
|
38688
38715
|
}
|
|
38689
38716
|
let body;
|
|
38690
38717
|
try {
|
|
38691
|
-
body = readFileSync42(
|
|
38718
|
+
body = readFileSync42(path2, "utf8");
|
|
38692
38719
|
} catch {
|
|
38693
38720
|
return { ok: false, code: "key_file_unreadable", reason: "cannot read the selected key file; check its path and file permissions" };
|
|
38694
38721
|
}
|
|
@@ -38742,20 +38769,20 @@ function buildPushSetupBody(i, keys) {
|
|
|
38742
38769
|
};
|
|
38743
38770
|
}
|
|
38744
38771
|
function readPushOnboarding(dir) {
|
|
38745
|
-
const
|
|
38746
|
-
if (!existsSync38(
|
|
38747
|
-
const parsed = readJson2(
|
|
38772
|
+
const path2 = join35(resolve33(dir), PUSH_ONBOARDING_PATH);
|
|
38773
|
+
if (!existsSync38(path2)) return { version: 1 };
|
|
38774
|
+
const parsed = readJson2(path2);
|
|
38748
38775
|
return { version: 1, ...parsed };
|
|
38749
38776
|
}
|
|
38750
38777
|
function writeFile(dir, file) {
|
|
38751
|
-
const
|
|
38752
|
-
mkdirSync17(dirname22(
|
|
38753
|
-
writeFileSync13(
|
|
38778
|
+
const path2 = join35(resolve33(dir), PUSH_ONBOARDING_PATH);
|
|
38779
|
+
mkdirSync17(dirname22(path2), { recursive: true, mode: 448 });
|
|
38780
|
+
writeFileSync13(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
|
|
38754
38781
|
try {
|
|
38755
|
-
chmodSync2(
|
|
38782
|
+
chmodSync2(path2, 384);
|
|
38756
38783
|
} catch {
|
|
38757
38784
|
}
|
|
38758
|
-
return
|
|
38785
|
+
return path2;
|
|
38759
38786
|
}
|
|
38760
38787
|
function recordPushDeferral(dir, d) {
|
|
38761
38788
|
const identity = {};
|
|
@@ -38777,8 +38804,8 @@ function recordPushDeferral(dir, d) {
|
|
|
38777
38804
|
return push;
|
|
38778
38805
|
}
|
|
38779
38806
|
function clearPushDeferral(dir) {
|
|
38780
|
-
const
|
|
38781
|
-
if (!existsSync38(
|
|
38807
|
+
const path2 = join35(resolve33(dir), PUSH_ONBOARDING_PATH);
|
|
38808
|
+
if (!existsSync38(path2)) return;
|
|
38782
38809
|
const { push: _dropped, ...rest } = readPushOnboarding(dir);
|
|
38783
38810
|
writeFile(dir, { ...rest, version: 1 });
|
|
38784
38811
|
}
|
|
@@ -39405,13 +39432,13 @@ function packagePathFor(pathname) {
|
|
|
39405
39432
|
}
|
|
39406
39433
|
return UNSUPPORTED;
|
|
39407
39434
|
}
|
|
39408
|
-
function parseJson(read,
|
|
39409
|
-
const bytes2 = read(
|
|
39435
|
+
function parseJson(read, path2, errors) {
|
|
39436
|
+
const bytes2 = read(path2);
|
|
39410
39437
|
if (!bytes2) return null;
|
|
39411
39438
|
try {
|
|
39412
39439
|
return JSON.parse(utf82(bytes2));
|
|
39413
39440
|
} catch (e) {
|
|
39414
|
-
errors.push(`${
|
|
39441
|
+
errors.push(`${path2} is not valid JSON: ${e.message}`);
|
|
39415
39442
|
return null;
|
|
39416
39443
|
}
|
|
39417
39444
|
}
|
|
@@ -39832,8 +39859,8 @@ function inflateEntry(buf, entry) {
|
|
|
39832
39859
|
verifyZipEntry(entry, bytes2);
|
|
39833
39860
|
return bytes2;
|
|
39834
39861
|
}
|
|
39835
|
-
function readIf(
|
|
39836
|
-
return existsSync39(
|
|
39862
|
+
function readIf(path2) {
|
|
39863
|
+
return existsSync39(path2) && statSync8(path2).isFile() ? readFileSync43(path2) : null;
|
|
39837
39864
|
}
|
|
39838
39865
|
function listDir(dir) {
|
|
39839
39866
|
return existsSync39(dir) ? readdirSync20(dir).filter((f) => statSync8(join36(dir, f)).isFile()) : [];
|
|
@@ -39969,7 +39996,7 @@ function packReleaseToDir(releaseRoot, app, outDir, opts = {}) {
|
|
|
39969
39996
|
}
|
|
39970
39997
|
function openFromEntries(entries, opts) {
|
|
39971
39998
|
const read = (p) => entries.get(p) ?? null;
|
|
39972
|
-
const contentHash = computeContentHash(Array.from(entries, ([
|
|
39999
|
+
const contentHash = computeContentHash(Array.from(entries, ([path2, bytes2]) => ({ path: path2, bytes: bytes2 })));
|
|
39973
40000
|
const validation = validatePackage(read, { requireHeader: opts.requireHeader, contentHash });
|
|
39974
40001
|
return {
|
|
39975
40002
|
header: validation.header,
|
|
@@ -40140,7 +40167,7 @@ function zipAppSource(entries) {
|
|
|
40140
40167
|
return writeZip(entries.map((e) => ({ path: e.path, bytes: e.bytes })));
|
|
40141
40168
|
}
|
|
40142
40169
|
function readAppSource(zip) {
|
|
40143
|
-
return [...readZip(zip)].map(([
|
|
40170
|
+
return [...readZip(zip)].map(([path2, bytes2]) => ({ path: path2, bytes: bytes2 }));
|
|
40144
40171
|
}
|
|
40145
40172
|
function pathKind(p) {
|
|
40146
40173
|
try {
|
|
@@ -40453,24 +40480,24 @@ function readTestConfig(dir) {
|
|
|
40453
40480
|
}
|
|
40454
40481
|
return { ...skip ? { skip } : {}, ...journeys ? { journeys } : {} };
|
|
40455
40482
|
}
|
|
40456
|
-
function readNetRules(
|
|
40483
|
+
function readNetRules(path2) {
|
|
40457
40484
|
let parsed;
|
|
40458
40485
|
try {
|
|
40459
|
-
parsed = JSON.parse(readFileSync46(
|
|
40486
|
+
parsed = JSON.parse(readFileSync46(path2, "utf8"));
|
|
40460
40487
|
} catch (e) {
|
|
40461
|
-
throw new Error(`--net ${
|
|
40488
|
+
throw new Error(`--net ${path2} could not be read as JSON \u2014 ${e.message}`);
|
|
40462
40489
|
}
|
|
40463
40490
|
const rules = parsed?.rules;
|
|
40464
40491
|
if (!Array.isArray(rules)) {
|
|
40465
|
-
throw new Error(`--net ${
|
|
40492
|
+
throw new Error(`--net ${path2} has no "rules" array \u2014 expected the net-mocks shape { "rules": [ { "matcher": {...}, "response": {...} } ] }`);
|
|
40466
40493
|
}
|
|
40467
40494
|
const active = rules.filter((r) => r.enabled !== false);
|
|
40468
40495
|
const shapeErrors = wixMockRuleErrors(active);
|
|
40469
40496
|
if (shapeErrors.length) {
|
|
40470
|
-
throw new Error(`${
|
|
40497
|
+
throw new Error(`${path2}: invalid net-mocks fixture \u2014 ${shapeErrors.join("; ")}`);
|
|
40471
40498
|
}
|
|
40472
40499
|
if (active.length && !active.some((r) => r.matcher && typeof r.matcher === "object")) {
|
|
40473
|
-
throw new Error(`${
|
|
40500
|
+
throw new Error(`${path2}: none of the ${active.length} rule(s) has a "matcher" \u2014 the net-mocks shape is { "rules": [ { "matcher": {...}, "response": {...} } ] }; a file that matches nothing must not report as "mocked"`);
|
|
40474
40501
|
}
|
|
40475
40502
|
return active;
|
|
40476
40503
|
}
|
|
@@ -40509,21 +40536,21 @@ function makeRecordingWixCall(send2, token, app) {
|
|
|
40509
40536
|
const events = [];
|
|
40510
40537
|
const refused = [];
|
|
40511
40538
|
let id = 0;
|
|
40512
|
-
const call = async (method,
|
|
40539
|
+
const call = async (method, path2, body) => {
|
|
40513
40540
|
const verb = method.toUpperCase();
|
|
40514
|
-
if (/[#\x00-\x1F\x7F]/.test(
|
|
40515
|
-
refused.push(`${verb} ${
|
|
40516
|
-
throw new Error(`--record refused ${verb} ${
|
|
40541
|
+
if (/[#\x00-\x1F\x7F]/.test(path2)) {
|
|
40542
|
+
refused.push(`${verb} ${path2}`);
|
|
40543
|
+
throw new Error(`--record refused ${verb} ${path2}: the path carries a fragment or control character \u2014 not a provable read`);
|
|
40517
40544
|
}
|
|
40518
|
-
const bare =
|
|
40545
|
+
const bare = path2.split("?")[0].replace(/\/+$/, "");
|
|
40519
40546
|
const readShaped = verb === "GET" || verb === "POST" && /\/(query|search|list[^/]*|get[^/]*|count|aggregate|facets|connections)$/i.test(bare);
|
|
40520
40547
|
if (!readShaped) {
|
|
40521
|
-
refused.push(`${verb} ${
|
|
40522
|
-
throw new Error(`--record refused ${verb} ${
|
|
40548
|
+
refused.push(`${verb} ${path2}`);
|
|
40549
|
+
throw new Error(`--record refused ${verb} ${path2}: recording sends only proven reads (GET, or POST ending in /query, /search, /list*, /get*, /count, /aggregate, /facets, /connections) \u2014 if this IS a read, add its rule to dev/net-mocks.json by hand`);
|
|
40523
40550
|
}
|
|
40524
40551
|
const bodyStr = body === void 0 ? void 0 : typeof body === "string" ? body : JSON.stringify(body);
|
|
40525
40552
|
const started = Date.now();
|
|
40526
|
-
const r = await send2(method,
|
|
40553
|
+
const r = await send2(method, path2, bodyStr, token);
|
|
40527
40554
|
events.push({
|
|
40528
40555
|
id: ++id,
|
|
40529
40556
|
ts: started,
|
|
@@ -40531,8 +40558,8 @@ function makeRecordingWixCall(send2, token, app) {
|
|
|
40531
40558
|
source: "observe",
|
|
40532
40559
|
host: "www.wixapis.com",
|
|
40533
40560
|
method,
|
|
40534
|
-
url: `https://www.wixapis.com${
|
|
40535
|
-
path,
|
|
40561
|
+
url: `https://www.wixapis.com${path2}`,
|
|
40562
|
+
path: path2,
|
|
40536
40563
|
status: r.status,
|
|
40537
40564
|
durationMs: Date.now() - started,
|
|
40538
40565
|
...bodyStr !== void 0 ? { reqBody: bodyStr } : {},
|
|
@@ -41079,6 +41106,15 @@ var init_mobile_ux_lint = __esm({
|
|
|
41079
41106
|
}
|
|
41080
41107
|
});
|
|
41081
41108
|
|
|
41109
|
+
// ../../core/serve-runtime/src/site-lease.ts
|
|
41110
|
+
var SITE_CONTROL_TTL_SECONDS, SITE_AUTHORIZATION_TTL_SECONDS;
|
|
41111
|
+
var init_site_lease = __esm({
|
|
41112
|
+
"../../core/serve-runtime/src/site-lease.ts"() {
|
|
41113
|
+
SITE_CONTROL_TTL_SECONDS = 15 * 60;
|
|
41114
|
+
SITE_AUTHORIZATION_TTL_SECONDS = SITE_CONTROL_TTL_SECONDS + 45 * 60;
|
|
41115
|
+
}
|
|
41116
|
+
});
|
|
41117
|
+
|
|
41082
41118
|
// ../../core/serve-runtime/src/preview-token.ts
|
|
41083
41119
|
async function hmacKey(secret) {
|
|
41084
41120
|
return crypto.subtle.importKey("raw", new TextEncoder().encode(secret), SUBTLE_ALGO, false, ["sign"]);
|
|
@@ -41119,6 +41155,7 @@ async function verifyPreviewToken(input) {
|
|
|
41119
41155
|
var SUBTLE_ALGO, PREVIEW_TOKEN_VERSION, DEFAULT_PREVIEW_TOKEN_TTL_SECONDS, WEB_PREVIEW_TOKEN_TTL_SECONDS;
|
|
41120
41156
|
var init_preview_token = __esm({
|
|
41121
41157
|
"../../core/serve-runtime/src/preview-token.ts"() {
|
|
41158
|
+
init_site_lease();
|
|
41122
41159
|
init_base64();
|
|
41123
41160
|
SUBTLE_ALGO = { name: "HMAC", hash: "SHA-256" };
|
|
41124
41161
|
PREVIEW_TOKEN_VERSION = 1;
|
|
@@ -41163,9 +41200,9 @@ var init_auth = __esm({
|
|
|
41163
41200
|
});
|
|
41164
41201
|
|
|
41165
41202
|
// ../../core/functions-runtime/src/wix-transport.ts
|
|
41166
|
-
function rejectSiteOverride(
|
|
41203
|
+
function rejectSiteOverride(path2) {
|
|
41167
41204
|
try {
|
|
41168
|
-
if (new URL(
|
|
41205
|
+
if (new URL(path2, "https://wix.invalid").searchParams.has("msid")) {
|
|
41169
41206
|
throw new Error("request cannot override the bound Wix site identity");
|
|
41170
41207
|
}
|
|
41171
41208
|
} catch (error) {
|
|
@@ -41176,8 +41213,8 @@ function createWixApiCapability(options) {
|
|
|
41176
41213
|
const permissions = [...options.permissions ?? []].sort();
|
|
41177
41214
|
let installation;
|
|
41178
41215
|
return {
|
|
41179
|
-
async call(method,
|
|
41180
|
-
rejectSiteOverride(
|
|
41216
|
+
async call(method, path2, body) {
|
|
41217
|
+
rejectSiteOverride(path2);
|
|
41181
41218
|
let identity;
|
|
41182
41219
|
if (options.identity.kind === "caller") {
|
|
41183
41220
|
identity = { ...options.identity };
|
|
@@ -41188,9 +41225,9 @@ function createWixApiCapability(options) {
|
|
|
41188
41225
|
throw new Error("installation identity is not authorized for the configured Wix site");
|
|
41189
41226
|
}
|
|
41190
41227
|
identity = { kind: "installation", installationId: installation.installationId };
|
|
41191
|
-
options.audit?.({ app: options.app, siteId: options.siteId, identity: "installation", method, path });
|
|
41228
|
+
options.audit?.({ app: options.app, siteId: options.siteId, identity: "installation", method, path: path2 });
|
|
41192
41229
|
}
|
|
41193
|
-
return options.transport.call({ app: options.app, siteId: options.siteId, identity, ...permissions.length ? { permissions } : {}, method, path, ...body === void 0 ? {} : { body } });
|
|
41230
|
+
return options.transport.call({ app: options.app, siteId: options.siteId, identity, ...permissions.length ? { permissions } : {}, method, path: path2, ...body === void 0 ? {} : { body } });
|
|
41194
41231
|
}
|
|
41195
41232
|
};
|
|
41196
41233
|
}
|
|
@@ -41782,11 +41819,11 @@ var init_sandbox = __esm({
|
|
|
41782
41819
|
});
|
|
41783
41820
|
|
|
41784
41821
|
// ../../core/functions-runtime/src/openapi.ts
|
|
41785
|
-
function makeFunctionsOpenApi(manifest,
|
|
41822
|
+
function makeFunctionsOpenApi(manifest, definitions2 = []) {
|
|
41786
41823
|
const paths = {};
|
|
41787
41824
|
for (const record2 of manifest.functions ?? []) {
|
|
41788
41825
|
if (record2.internal) continue;
|
|
41789
|
-
const definition =
|
|
41826
|
+
const definition = definitions2.find((item) => item.name === record2.name);
|
|
41790
41827
|
const method = record2.method.toLowerCase();
|
|
41791
41828
|
paths[record2.path] = {
|
|
41792
41829
|
...paths[record2.path] ?? {},
|
|
@@ -42413,9 +42450,9 @@ function resolveTarget2(pathname) {
|
|
|
42413
42450
|
return null;
|
|
42414
42451
|
}
|
|
42415
42452
|
}
|
|
42416
|
-
function chooseFunction(records, method,
|
|
42453
|
+
function chooseFunction(records, method, path2) {
|
|
42417
42454
|
for (const record2 of records) {
|
|
42418
|
-
const params = routeMatch(record2.path,
|
|
42455
|
+
const params = routeMatch(record2.path, path2);
|
|
42419
42456
|
if (params && record2.method === method) return { record: record2, params };
|
|
42420
42457
|
}
|
|
42421
42458
|
return null;
|
|
@@ -42424,8 +42461,8 @@ async function contentFromBundle(bytes2, record2) {
|
|
|
42424
42461
|
const actual = await integrity(bytes2);
|
|
42425
42462
|
return actual.hash === record2.bundleHash && actual.sri === record2.sri ? utf8Decode(bytes2) : null;
|
|
42426
42463
|
}
|
|
42427
|
-
function definitionFor(
|
|
42428
|
-
return
|
|
42464
|
+
function definitionFor(definitions2, name) {
|
|
42465
|
+
return definitions2?.find((definition) => definition.name === name);
|
|
42429
42466
|
}
|
|
42430
42467
|
async function bodyValue(request, record2) {
|
|
42431
42468
|
const length = Number(request.headers.get("content-length") ?? "0");
|
|
@@ -42468,6 +42505,7 @@ function makeFunctionsHandler(options) {
|
|
|
42468
42505
|
const token = request.headers.get("x-himalaya-preview-token") || new URL(request.url).searchParams.get("pvt");
|
|
42469
42506
|
const verified = token ? await verifyPreviewToken({ token, secret: options.previewTokenSecret, app: target.app, releaseId: pin, nowSeconds: options.nowSeconds }) : { ok: false, error: "malformed" };
|
|
42470
42507
|
if (!verified.ok || verified.claims.source !== "functions") return errorResponse(401, `preview_token_${verified.ok ? "scope_mismatch" : verified.error}`, "a valid function preview token is required", id);
|
|
42508
|
+
if (options.authorizePreview ? !await options.authorizePreview(verified.claims) : !!verified.claims.siteLease) return errorResponse(403, "site_preview_forbidden", "site authorization expired or changed", id);
|
|
42471
42509
|
previewClaims = verified.claims;
|
|
42472
42510
|
}
|
|
42473
42511
|
if (pin) selected = options.store.getManifestById ? await options.store.getManifestById(target.app, pin) : null;
|
|
@@ -42676,8 +42714,8 @@ function makeFunctionsHandler(options) {
|
|
|
42676
42714
|
}
|
|
42677
42715
|
};
|
|
42678
42716
|
}
|
|
42679
|
-
function functionsOpenApi(manifest,
|
|
42680
|
-
return makeFunctionsOpenApi(manifest,
|
|
42717
|
+
function functionsOpenApi(manifest, definitions2 = []) {
|
|
42718
|
+
return makeFunctionsOpenApi(manifest, definitions2);
|
|
42681
42719
|
}
|
|
42682
42720
|
var MAX_LOG_MESSAGE;
|
|
42683
42721
|
var init_gateway = __esm({
|
|
@@ -42743,19 +42781,19 @@ async function loadFunctionsApp(dir) {
|
|
|
42743
42781
|
if (dataErrors.length) throw new Error(`invalid data declaration: ${dataErrors.map((issue2) => issue2.message).join("; ")}`);
|
|
42744
42782
|
return { app: loaded.name, dir: loaded.dir, definitions: config.functions.functions, sources, siteBinding: config.functions.siteBinding, schedules: config.functions.schedules, ...data ? { data } : {} };
|
|
42745
42783
|
}
|
|
42746
|
-
function listFunctions(
|
|
42747
|
-
return
|
|
42784
|
+
function listFunctions(definitions2) {
|
|
42785
|
+
return definitions2.map((definition) => ({ name: definition.name, method: definition.method, path: definition.path, auth: definition.auth, internal: definition.internal, limits: definition.limits }));
|
|
42748
42786
|
}
|
|
42749
|
-
function describeFunction(
|
|
42750
|
-
const definition =
|
|
42787
|
+
function describeFunction(definitions2, name) {
|
|
42788
|
+
const definition = definitions2.find((item) => item.name === name);
|
|
42751
42789
|
return definition ? { ...listFunctions([definition])[0], wixIdentity: definition.wixIdentity, wixPermissions: [...definition.wixPermissions], capabilities: [...definition.capabilities], secrets: [...definition.secrets], outboundHosts: [...definition.outboundHosts], inputSchema: definition.input?.kind ?? null, outputSchema: definition.output?.kind ?? null } : null;
|
|
42752
42790
|
}
|
|
42753
|
-
function materializeFunctionPath(
|
|
42754
|
-
const names = [...
|
|
42791
|
+
function materializeFunctionPath(path2, params = {}) {
|
|
42792
|
+
const names = [...path2.matchAll(/:([A-Za-z][A-Za-z0-9_]*)/g)].map((match) => match[1]);
|
|
42755
42793
|
for (const name of names) {
|
|
42756
42794
|
if (typeof params[name] !== "string" || params[name] === "") throw new Error(`missing route parameter "${name}"; pass --params {"${name}":"value"}`);
|
|
42757
42795
|
}
|
|
42758
|
-
return
|
|
42796
|
+
return path2.replace(/:([A-Za-z][A-Za-z0-9_]*)/g, (_match, name) => encodeURIComponent(params[name]));
|
|
42759
42797
|
}
|
|
42760
42798
|
function memoryStore(manifest, built) {
|
|
42761
42799
|
const bytes2 = new Map(built.map((item) => [item.bundleHash, item.bytes]));
|
|
@@ -42839,8 +42877,8 @@ async function invokeRemoteFunction(input) {
|
|
|
42839
42877
|
});
|
|
42840
42878
|
return { response, url: url.toString() };
|
|
42841
42879
|
}
|
|
42842
|
-
function openApiForFunctions(manifest,
|
|
42843
|
-
return functionsOpenApi(manifest,
|
|
42880
|
+
function openApiForFunctions(manifest, definitions2) {
|
|
42881
|
+
return functionsOpenApi(manifest, definitions2);
|
|
42844
42882
|
}
|
|
42845
42883
|
async function runRemoteFunctionOperation(input) {
|
|
42846
42884
|
const environment2 = input.environment ?? "production";
|
|
@@ -43092,9 +43130,9 @@ function runAndroidNativeDecode(options) {
|
|
|
43092
43130
|
rmSync8(descriptorDir, { recursive: true, force: true });
|
|
43093
43131
|
}
|
|
43094
43132
|
}
|
|
43095
|
-
function fieldAt(
|
|
43096
|
-
if (
|
|
43097
|
-
return
|
|
43133
|
+
function fieldAt(path2) {
|
|
43134
|
+
if (path2 === null) return void 0;
|
|
43135
|
+
return path2.match(/\.([^.[\]]+)$/)?.[1];
|
|
43098
43136
|
}
|
|
43099
43137
|
function mergeNativeDecode(report2, run2) {
|
|
43100
43138
|
const platformLabel = run2.platform === "ios" ? "iOS" : "Android";
|
|
@@ -44084,8 +44122,8 @@ var init_wix_member_auth = __esm({
|
|
|
44084
44122
|
function json3(status, body, headers2 = {}) {
|
|
44085
44123
|
return new Response(JSON.stringify(body), { status, headers: { "content-type": JSON_CT, ...headers2 } });
|
|
44086
44124
|
}
|
|
44087
|
-
function isCookieAuthorizedPath(
|
|
44088
|
-
return
|
|
44125
|
+
function isCookieAuthorizedPath(path2) {
|
|
44126
|
+
return path2 === "/v1/__webwix/call" || path2 === "/v1/owner" || path2.startsWith("/v1/owner/") || path2 === "/v1/__webwix/identity" || path2 === "/v1/__webwix/login" || path2 === "/v1/__webwix/register" || path2 === "/v1/__webwix/logout" || path2 === MEMBER_CALLBACK_PATH;
|
|
44089
44127
|
}
|
|
44090
44128
|
function makeServeHandler(opts) {
|
|
44091
44129
|
let storePromise = null;
|
|
@@ -44214,13 +44252,16 @@ ${releaseId}`;
|
|
|
44214
44252
|
}
|
|
44215
44253
|
async function authorizePinnedRead(request, url, app, releaseId, screenId) {
|
|
44216
44254
|
const secret = opts.previewTokenSecret;
|
|
44217
|
-
if (!secret) return null;
|
|
44255
|
+
if (!secret) return opts.authorizePreview ? json3(503, { error: "preview_token_unavailable" }) : null;
|
|
44218
44256
|
const token = resolvePreviewToken(request, url);
|
|
44219
44257
|
const live2 = await manifest(app);
|
|
44220
44258
|
const isLive = live2?.releaseId === releaseId;
|
|
44221
44259
|
if (!token) return isLive ? null : json3(401, { error: "preview_token_required", app, releaseId });
|
|
44222
44260
|
const verified = await verifyPreviewToken({ token, secret, app, releaseId, screenId });
|
|
44223
|
-
if (verified.ok)
|
|
44261
|
+
if (verified.ok) {
|
|
44262
|
+
if (opts.authorizePreview ? !await opts.authorizePreview(verified.claims) : !!verified.claims.siteLease) return json3(403, { error: "site_preview_forbidden" });
|
|
44263
|
+
return null;
|
|
44264
|
+
}
|
|
44224
44265
|
return json3(verified.error === "scope_mismatch" ? 403 : 401, {
|
|
44225
44266
|
error: `preview_token_${verified.error}`,
|
|
44226
44267
|
app,
|
|
@@ -44265,9 +44306,9 @@ ${releaseId}`;
|
|
|
44265
44306
|
const handle = async (request) => {
|
|
44266
44307
|
try {
|
|
44267
44308
|
const url = new URL(request.url);
|
|
44268
|
-
const
|
|
44309
|
+
const path2 = url.pathname;
|
|
44269
44310
|
if (opts.devControl && request.method === "PUT") {
|
|
44270
|
-
const dcMatch = /^\/v1\/dev-control\/([^/]+)$/.exec(
|
|
44311
|
+
const dcMatch = /^\/v1\/dev-control\/([^/]+)$/.exec(path2);
|
|
44271
44312
|
if (dcMatch) {
|
|
44272
44313
|
const dcApp = dcMatch[1];
|
|
44273
44314
|
let body = {};
|
|
@@ -44283,16 +44324,16 @@ ${releaseId}`;
|
|
|
44283
44324
|
}
|
|
44284
44325
|
}
|
|
44285
44326
|
const memberRungApp = memberAuthOn() ? memberApp(request) : null;
|
|
44286
|
-
if (memberRungApp && (
|
|
44327
|
+
if (memberRungApp && (path2 === "/v1/__webwix/login" || path2 === "/v1/__webwix/register" || path2 === MEMBER_CALLBACK_PATH || path2 === "/v1/__webwix/logout")) {
|
|
44287
44328
|
const store2 = memberSessions();
|
|
44288
44329
|
if (!store2) return json3(503, { error: "member_auth_unconfigured" });
|
|
44289
44330
|
const sessionId = readSessionCookie(request.headers.get("cookie"));
|
|
44290
|
-
if (
|
|
44331
|
+
if (path2 === "/v1/__webwix/logout") {
|
|
44291
44332
|
if (request.method !== "POST") return json3(405, { error: "method_not_allowed" });
|
|
44292
44333
|
if (sessionId) await store2.delete(sessionId);
|
|
44293
44334
|
return json3(200, { ok: true }, { "set-cookie": clearSessionCookie(), "cache-control": "no-store" });
|
|
44294
44335
|
}
|
|
44295
|
-
if (
|
|
44336
|
+
if (path2 === MEMBER_CALLBACK_PATH) {
|
|
44296
44337
|
if (request.method !== "GET") return json3(405, { error: "method_not_allowed" });
|
|
44297
44338
|
const code = url.searchParams.get("code");
|
|
44298
44339
|
const state2 = url.searchParams.get("state");
|
|
@@ -44352,7 +44393,7 @@ ${releaseId}`;
|
|
|
44352
44393
|
try {
|
|
44353
44394
|
const visitor = await webwixTokens.token(resolved2.config.clientId);
|
|
44354
44395
|
authUrl = await hostedAuthUrl(
|
|
44355
|
-
{ ...resolved2.config, mode:
|
|
44396
|
+
{ ...resolved2.config, mode: path2.endsWith("/register") ? "signup" : "login", state, challenge: pkce.challenge },
|
|
44356
44397
|
visitor,
|
|
44357
44398
|
webwixFetch
|
|
44358
44399
|
);
|
|
@@ -44379,7 +44420,7 @@ ${releaseId}`;
|
|
|
44379
44420
|
}
|
|
44380
44421
|
});
|
|
44381
44422
|
}
|
|
44382
|
-
if ((request.method === "GET" || request.method === "HEAD") &&
|
|
44423
|
+
if ((request.method === "GET" || request.method === "HEAD") && path2 === "/v1/__webwix/identity") {
|
|
44383
44424
|
const headers2 = { "content-type": JSON_CT, "cache-control": "no-store" };
|
|
44384
44425
|
if (request.method === "HEAD") return new Response(null, { status: 200, headers: headers2 });
|
|
44385
44426
|
const webwixDirect = opts.webwixBridge !== false;
|
|
@@ -44393,7 +44434,7 @@ ${releaseId}`;
|
|
|
44393
44434
|
}
|
|
44394
44435
|
return json3(200, { authenticated: false, userId: null, email: null, webwixDirect }, { "cache-control": "no-store" });
|
|
44395
44436
|
}
|
|
44396
|
-
if (request.method === "POST" &&
|
|
44437
|
+
if (request.method === "POST" && path2 === "/v1/__webwix/call") {
|
|
44397
44438
|
if (opts.webwixBridge === false) {
|
|
44398
44439
|
return json3(503, { error: "webwix_bridge_disabled" });
|
|
44399
44440
|
}
|
|
@@ -44496,8 +44537,8 @@ ${releaseId}`;
|
|
|
44496
44537
|
}
|
|
44497
44538
|
}
|
|
44498
44539
|
if (request.method !== "GET") return json3(405, { error: "method_not_allowed" });
|
|
44499
|
-
if (
|
|
44500
|
-
const packageShare = /^\/p\/([a-f0-9]{64})$/.exec(
|
|
44540
|
+
if (path2 === "/__health") return json3(200, { ok: true });
|
|
44541
|
+
const packageShare = /^\/p\/([a-f0-9]{64})$/.exec(path2);
|
|
44501
44542
|
if (packageShare) {
|
|
44502
44543
|
const shareId = packageShare[1];
|
|
44503
44544
|
const wantsMetadata = url.searchParams.get("metadata") === "1";
|
|
@@ -44526,7 +44567,7 @@ ${releaseId}`;
|
|
|
44526
44567
|
}
|
|
44527
44568
|
});
|
|
44528
44569
|
}
|
|
44529
|
-
if (
|
|
44570
|
+
if (path2 === "/v1/owner/instance") {
|
|
44530
44571
|
if (opts.webwixBridge === false) return json3(503, { error: "webwix_bridge_disabled" });
|
|
44531
44572
|
if (!webwixOwnerRungOn()) return json3(503, { error: "webwix_owner_disabled" });
|
|
44532
44573
|
const msid = url.searchParams.get("msid") ?? "";
|
|
@@ -44542,7 +44583,7 @@ ${releaseId}`;
|
|
|
44542
44583
|
return json3(403, { error: "webwix_owner_mint_failed" });
|
|
44543
44584
|
}
|
|
44544
44585
|
}
|
|
44545
|
-
if (
|
|
44586
|
+
if (path2 === "/v1/owner/sites") {
|
|
44546
44587
|
if (!webwixOwnerRungOn()) return json3(503, { error: "webwix_owner_disabled" });
|
|
44547
44588
|
const cookie = request.headers.get("cookie") ?? "";
|
|
44548
44589
|
if (!/wixSession2=/.test(cookie)) return json3(200, { sites: [] });
|
|
@@ -44556,7 +44597,7 @@ ${releaseId}`;
|
|
|
44556
44597
|
}
|
|
44557
44598
|
}
|
|
44558
44599
|
const store = await getStore();
|
|
44559
|
-
if (
|
|
44600
|
+
if (path2 === "/v1/apps") {
|
|
44560
44601
|
if (opts.authorizeList && !await opts.authorizeList(request)) {
|
|
44561
44602
|
return json3(401, { error: "unauthorized" });
|
|
44562
44603
|
}
|
|
@@ -44620,7 +44661,7 @@ ${releaseId}`;
|
|
|
44620
44661
|
headers: { "content-type": JSON_CT, ...listHeaders }
|
|
44621
44662
|
});
|
|
44622
44663
|
}
|
|
44623
|
-
if (
|
|
44664
|
+
if (path2 === "/v1/templates") {
|
|
44624
44665
|
if (opts.authorizeList && !await opts.authorizeList(request)) {
|
|
44625
44666
|
return json3(401, { error: "unauthorized" });
|
|
44626
44667
|
}
|
|
@@ -44653,9 +44694,10 @@ ${releaseId}`;
|
|
|
44653
44694
|
templates.sort((a, b) => String(a.name).localeCompare(String(b.name)));
|
|
44654
44695
|
return json3(200, { templates });
|
|
44655
44696
|
}
|
|
44656
|
-
const
|
|
44697
|
+
const cfgMatch = /^\/v1\/app-config\/([^/]+)$/.exec(path2);
|
|
44698
|
+
const app = cfgMatch?.[1] ?? resolveApp(request, url);
|
|
44657
44699
|
const pin = resolvePin(request, url);
|
|
44658
|
-
if (
|
|
44700
|
+
if (path2 === "/v1/template-source") {
|
|
44659
44701
|
if (!app) return json3(400, { error: "missing_app" });
|
|
44660
44702
|
if (!store.getSource) return json3(501, { error: "templates_unsupported" });
|
|
44661
44703
|
const m = pin ? await pinnedManifest(app, pin) : await manifest(app);
|
|
@@ -44675,12 +44717,12 @@ ${releaseId}`;
|
|
|
44675
44717
|
const denied = await authorizePinnedRead(request, url, app, pin);
|
|
44676
44718
|
if (denied) return denied;
|
|
44677
44719
|
}
|
|
44678
|
-
if (
|
|
44720
|
+
if (path2 === "/v1/authoring-docs" || /^\/v1\/authoring-docs\/(spec|mobile-ux)$/.test(path2)) {
|
|
44679
44721
|
if (!app) return json3(400, { error: "missing_app" });
|
|
44680
44722
|
const m = pin ? await pinnedManifest(app, pin) : await manifest(app);
|
|
44681
44723
|
if (!m) return json3(404, { error: pin ? "release_not_found" : "no_release", app });
|
|
44682
44724
|
const docs = m.authoringDocs ?? {};
|
|
44683
|
-
const match = /^\/v1\/authoring-docs\/(spec|mobile-ux)$/.exec(
|
|
44725
|
+
const match = /^\/v1\/authoring-docs\/(spec|mobile-ux)$/.exec(path2);
|
|
44684
44726
|
if (!match) {
|
|
44685
44727
|
return json3(200, {
|
|
44686
44728
|
app,
|
|
@@ -44708,7 +44750,7 @@ ${releaseId}`;
|
|
|
44708
44750
|
}
|
|
44709
44751
|
});
|
|
44710
44752
|
}
|
|
44711
|
-
if (
|
|
44753
|
+
if (path2 === "/v1/release/current") {
|
|
44712
44754
|
if (pin) {
|
|
44713
44755
|
const m2 = app ? await pinnedManifest(app, pin) : null;
|
|
44714
44756
|
if (!m2) return json3(404, { error: "release_not_found", app, releaseId: pin });
|
|
@@ -44718,7 +44760,7 @@ ${releaseId}`;
|
|
|
44718
44760
|
if (!m) return json3(404, { error: "no_release", app });
|
|
44719
44761
|
return json3(200, { releaseId: m.releaseId, app: m.app, ...m.minBinaryVersion ? { minBinaryVersion: m.minBinaryVersion } : {}, ...m.playerRequirements ? { playerRequirements: m.playerRequirements } : {}, ...m.platforms ? { platforms: m.platforms } : {} });
|
|
44720
44762
|
}
|
|
44721
|
-
const bundleMatch = /^\/v1\/bundles\/([a-f0-9]{64})\.bundle\.js$/.exec(
|
|
44763
|
+
const bundleMatch = /^\/v1\/bundles\/([a-f0-9]{64})\.bundle\.js$/.exec(path2);
|
|
44722
44764
|
if (bundleMatch) {
|
|
44723
44765
|
const hash = bundleMatch[1];
|
|
44724
44766
|
const m = app ? pin ? await pinnedManifest(app, pin) : await manifest(app) : null;
|
|
@@ -44735,7 +44777,7 @@ ${releaseId}`;
|
|
|
44735
44777
|
}
|
|
44736
44778
|
});
|
|
44737
44779
|
}
|
|
44738
|
-
if (
|
|
44780
|
+
if (path2 === "/v1/boot") {
|
|
44739
44781
|
if (!app) return json3(400, { error: "missing_app" });
|
|
44740
44782
|
let m;
|
|
44741
44783
|
if (pin) {
|
|
@@ -44804,7 +44846,7 @@ ${releaseId}`;
|
|
|
44804
44846
|
}
|
|
44805
44847
|
return json3(200, { releaseId: mm.releaseId, app, appConfig, tokens, homeScreenId, screen, homeBundle }, { etag, "cache-control": cache, ...vary });
|
|
44806
44848
|
}
|
|
44807
|
-
if (
|
|
44849
|
+
if (path2 === "/v1/tokens") {
|
|
44808
44850
|
if (!app) return json3(400, { error: "missing_app" });
|
|
44809
44851
|
if (pin) {
|
|
44810
44852
|
const m = await pinnedManifest(app, pin);
|
|
@@ -44817,7 +44859,7 @@ ${releaseId}`;
|
|
|
44817
44859
|
if (!bytes2) return json3(404, { error: "tokens_not_found", app });
|
|
44818
44860
|
return sendDoc(request, bytes2);
|
|
44819
44861
|
}
|
|
44820
|
-
if (
|
|
44862
|
+
if (path2 === "/v1/l10n") {
|
|
44821
44863
|
if (!app) return json3(400, { error: "missing_app" });
|
|
44822
44864
|
const tag = (url.searchParams.get("tag") ?? "").trim();
|
|
44823
44865
|
if (!/^[a-z]{2}(-[A-Za-z0-9]+)?$/.test(tag)) {
|
|
@@ -44832,7 +44874,7 @@ ${releaseId}`;
|
|
|
44832
44874
|
if (!bytes2) return new Response(null, { status: 204 });
|
|
44833
44875
|
return sendDoc(request, bytes2, Boolean(pin));
|
|
44834
44876
|
}
|
|
44835
|
-
if (
|
|
44877
|
+
if (path2 === "/v1/app-icon") {
|
|
44836
44878
|
if (!app) return json3(400, { error: "missing_app" });
|
|
44837
44879
|
if (!store.getIcon) return json3(501, { error: "icons_unsupported" });
|
|
44838
44880
|
const m = pin ? await pinnedManifest(app, pin) : await manifest(app);
|
|
@@ -44849,7 +44891,7 @@ ${releaseId}`;
|
|
|
44849
44891
|
headers: { "content-type": "image/png", etag, "cache-control": BUNDLE_CACHE_CONTROL, "x-himalaya-app": app }
|
|
44850
44892
|
});
|
|
44851
44893
|
}
|
|
44852
|
-
const assetMatch = /^\/v1\/asset\/([^/?]+)$/.exec(
|
|
44894
|
+
const assetMatch = /^\/v1\/asset\/([^/?]+)$/.exec(path2);
|
|
44853
44895
|
if (assetMatch) {
|
|
44854
44896
|
if (!app) return json3(400, { error: "missing_app" });
|
|
44855
44897
|
if (!store.getAsset) return json3(501, { error: "assets_unsupported" });
|
|
@@ -44878,7 +44920,7 @@ ${releaseId}`;
|
|
|
44878
44920
|
}
|
|
44879
44921
|
});
|
|
44880
44922
|
}
|
|
44881
|
-
const ahMatch = /^\/v1\/action-handlers\/([^/]+)$/.exec(
|
|
44923
|
+
const ahMatch = /^\/v1\/action-handlers\/([^/]+)$/.exec(path2);
|
|
44882
44924
|
if (ahMatch) {
|
|
44883
44925
|
const ahApp = ahMatch[1];
|
|
44884
44926
|
const m = await manifest(ahApp);
|
|
@@ -44891,7 +44933,6 @@ ${releaseId}`;
|
|
|
44891
44933
|
}));
|
|
44892
44934
|
return json3(200, { handlers });
|
|
44893
44935
|
}
|
|
44894
|
-
const cfgMatch = /^\/v1\/app-config\/([^/]+)$/.exec(path);
|
|
44895
44936
|
if (cfgMatch) {
|
|
44896
44937
|
const cfgApp = cfgMatch[1];
|
|
44897
44938
|
if (pin) {
|
|
@@ -44911,7 +44952,7 @@ ${releaseId}`;
|
|
|
44911
44952
|
}
|
|
44912
44953
|
return sendDoc(request, bytes2);
|
|
44913
44954
|
}
|
|
44914
|
-
const screenMatch = /^\/v1\/screen\/([^/]+)$/.exec(
|
|
44955
|
+
const screenMatch = /^\/v1\/screen\/([^/]+)$/.exec(path2);
|
|
44915
44956
|
if (screenMatch) {
|
|
44916
44957
|
const screenId = screenMatch[1];
|
|
44917
44958
|
if (!app || !isSafeSegment(screenId)) return json3(404, { error: "screen_not_found", screenId });
|
|
@@ -44943,14 +44984,14 @@ ${releaseId}`;
|
|
|
44943
44984
|
headers: { "content-type": JSON_CT, etag, "cache-control": DOC_CACHE_CONTROL, "x-himalaya-app": app }
|
|
44944
44985
|
});
|
|
44945
44986
|
}
|
|
44946
|
-
if (
|
|
44987
|
+
if (path2 === "/v1/widgets") {
|
|
44947
44988
|
if (!app) return json3(400, { error: "missing_app" });
|
|
44948
44989
|
const m = pin ? await pinnedManifest(app, pin) : await manifest(app);
|
|
44949
44990
|
if (!m) return json3(404, { error: pin ? "release_not_found" : "no_release", app });
|
|
44950
44991
|
const widgets = Object.entries(m.widgets ?? {}).map(([widgetId, meta]) => ({ widgetId, contentEtag: meta.contentEtag }));
|
|
44951
44992
|
return json3(200, { widgets });
|
|
44952
44993
|
}
|
|
44953
|
-
const widgetMatch = /^\/v1\/widget\/([^/]+)$/.exec(
|
|
44994
|
+
const widgetMatch = /^\/v1\/widget\/([^/]+)$/.exec(path2);
|
|
44954
44995
|
if (widgetMatch) {
|
|
44955
44996
|
const widgetId = widgetMatch[1];
|
|
44956
44997
|
if (!app || !isSafeSegment(widgetId)) return json3(404, { error: "widget_not_found", widgetId });
|
|
@@ -44980,7 +45021,12 @@ ${releaseId}`;
|
|
|
44980
45021
|
if (request.method === "OPTIONS") {
|
|
44981
45022
|
return new Response(null, { status: 204, headers: { ...corsHeaders(request), "content-length": "0" } });
|
|
44982
45023
|
}
|
|
44983
|
-
|
|
45024
|
+
const response = await handle(request);
|
|
45025
|
+
if (resolvePreviewToken(request, new URL(request.url))) {
|
|
45026
|
+
response.headers.set("cache-control", "private, no-store");
|
|
45027
|
+
response.headers.set("vary", "x-himalaya-preview-token, x-himalaya-release");
|
|
45028
|
+
}
|
|
45029
|
+
return withCors(request, response);
|
|
44984
45030
|
};
|
|
44985
45031
|
}
|
|
44986
45032
|
var JSON_CT;
|
|
@@ -45151,25 +45197,25 @@ function makeRunHandler(opts) {
|
|
|
45151
45197
|
});
|
|
45152
45198
|
return async (request) => {
|
|
45153
45199
|
const url = new URL(request.url);
|
|
45154
|
-
const
|
|
45155
|
-
if (
|
|
45200
|
+
const path2 = url.pathname;
|
|
45201
|
+
if (path2 === "/v1/release/resolve") {
|
|
45156
45202
|
return json4(
|
|
45157
45203
|
200,
|
|
45158
45204
|
{ app: opts.app, releaseId: opts.header?.releaseId ?? null, source: "local" },
|
|
45159
45205
|
{ "cache-control": "no-store" }
|
|
45160
45206
|
);
|
|
45161
45207
|
}
|
|
45162
|
-
if (
|
|
45208
|
+
if (path2 === "/v1/revocations") {
|
|
45163
45209
|
return json4(
|
|
45164
45210
|
200,
|
|
45165
45211
|
{ app: opts.app, revokedIntegrities: [], version: 0, ttlSeconds: 30 },
|
|
45166
45212
|
{ "cache-control": "max-age=30" }
|
|
45167
45213
|
);
|
|
45168
45214
|
}
|
|
45169
|
-
if (
|
|
45215
|
+
if (path2.startsWith("/v1/flags/")) {
|
|
45170
45216
|
return json4(200, { app: opts.app, definitions: {} }, { "cache-control": "no-store" });
|
|
45171
45217
|
}
|
|
45172
|
-
if (
|
|
45218
|
+
if (path2 === "/v1/telemetry/ingest") {
|
|
45173
45219
|
if (request.method !== "POST") return json4(405, { error: "method_not_allowed" });
|
|
45174
45220
|
try {
|
|
45175
45221
|
const body = await request.json();
|
|
@@ -45179,33 +45225,33 @@ function makeRunHandler(opts) {
|
|
|
45179
45225
|
}
|
|
45180
45226
|
return new Response(null, { status: 204 });
|
|
45181
45227
|
}
|
|
45182
|
-
if (
|
|
45228
|
+
if (path2 === "/v1/screen-events") {
|
|
45183
45229
|
return new Response(new ReadableStream({ start() {
|
|
45184
45230
|
} }), {
|
|
45185
45231
|
status: 200,
|
|
45186
45232
|
headers: { "content-type": "text/event-stream", "cache-control": "no-store", connection: "keep-alive" }
|
|
45187
45233
|
});
|
|
45188
45234
|
}
|
|
45189
|
-
if (
|
|
45235
|
+
if (path2.startsWith("/v1/__webwix/") && path2 !== "/v1/__webwix/call" && path2 !== "/v1/__webwix/identity" && !(opts.serve?.webwixMemberAuth === true && opts.serve?.webwixMemberSessions)) {
|
|
45190
45236
|
return json4(501, { error: "webwix_member_auth_unavailable" });
|
|
45191
45237
|
}
|
|
45192
|
-
if (
|
|
45238
|
+
if (path2 === "/v1/app-config" || path2.startsWith("/v1/app-config/")) {
|
|
45193
45239
|
return localizeConfigResponse(await serve(request), "app-config", opts.header ?? null);
|
|
45194
45240
|
}
|
|
45195
|
-
if (
|
|
45241
|
+
if (path2 === "/v1/boot") {
|
|
45196
45242
|
return localizeConfigResponse(await serve(request), "boot", opts.header ?? null);
|
|
45197
45243
|
}
|
|
45198
|
-
if (
|
|
45244
|
+
if (path2 === "/v1" || path2.startsWith("/v1/") || path2 === "/__health") {
|
|
45199
45245
|
return serve(request);
|
|
45200
45246
|
}
|
|
45201
|
-
if (
|
|
45247
|
+
if (path2 === "/" || path2 === "") {
|
|
45202
45248
|
const target = `${mount}/a/${encodeURIComponent(opts.app)}${url.search}`;
|
|
45203
45249
|
return new Response(null, { status: 302, headers: { location: target } });
|
|
45204
45250
|
}
|
|
45205
|
-
if (
|
|
45206
|
-
return previewResponse(
|
|
45251
|
+
if (path2 === mount || path2.startsWith(`${mount}/`)) {
|
|
45252
|
+
return previewResponse(path2, opts.assets, mount);
|
|
45207
45253
|
}
|
|
45208
|
-
return json4(404, { error: "not_found", path });
|
|
45254
|
+
return json4(404, { error: "not_found", path: path2 });
|
|
45209
45255
|
};
|
|
45210
45256
|
}
|
|
45211
45257
|
var json4;
|
|
@@ -45414,9 +45460,9 @@ async function loadPreviewAssets() {
|
|
|
45414
45460
|
join46(here, "../../../packages/serve/src/preview-assets.generated.bin")
|
|
45415
45461
|
// in-repo checkout
|
|
45416
45462
|
];
|
|
45417
|
-
for (const
|
|
45418
|
-
if (!existsSync49(
|
|
45419
|
-
const blob = readFileSync54(
|
|
45463
|
+
for (const path2 of candidates) {
|
|
45464
|
+
if (!existsSync49(path2)) continue;
|
|
45465
|
+
const blob = readFileSync54(path2);
|
|
45420
45466
|
return mod.assemblePreviewAssetsFromBlob(new Uint8Array(blob.buffer, blob.byteOffset, blob.byteLength));
|
|
45421
45467
|
}
|
|
45422
45468
|
return /* @__PURE__ */ new Map();
|
|
@@ -45426,9 +45472,9 @@ async function loadPreviewAssets() {
|
|
|
45426
45472
|
}
|
|
45427
45473
|
function packageUrl(origin, app, opts = {}) {
|
|
45428
45474
|
const mount = opts.chrome === "app" ? "/app" : "/preview";
|
|
45429
|
-
const
|
|
45475
|
+
const path2 = `${mount}/a/${encodeURIComponent(app)}${opts.screen ? `/screen/${encodeURIComponent(opts.screen)}` : ""}`;
|
|
45430
45476
|
const query = opts.surface ? `?surface=${encodeURIComponent(opts.surface)}` : "";
|
|
45431
|
-
return `${origin.replace(/\/$/, "")}${
|
|
45477
|
+
return `${origin.replace(/\/$/, "")}${path2}${query}`;
|
|
45432
45478
|
}
|
|
45433
45479
|
function openBrowser(url) {
|
|
45434
45480
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
@@ -45588,13 +45634,13 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
45588
45634
|
const body = JSON.stringify(payload);
|
|
45589
45635
|
const missed = [];
|
|
45590
45636
|
const server = createServer5((req, res) => {
|
|
45591
|
-
const
|
|
45592
|
-
if (
|
|
45637
|
+
const path2 = (req.url ?? "/").split("?")[0];
|
|
45638
|
+
if (path2 === "/release.json") {
|
|
45593
45639
|
res.writeHead(200, { "content-type": "application/json", "cache-control": "no-store" });
|
|
45594
45640
|
res.end(body);
|
|
45595
45641
|
return;
|
|
45596
45642
|
}
|
|
45597
|
-
const name =
|
|
45643
|
+
const name = path2 === "/" || path2 === "/index.html" ? "host.html" : path2.slice(1);
|
|
45598
45644
|
if (SERVED.has(name)) {
|
|
45599
45645
|
if (!existsSync50(resolve40(stagedDir(), name))) {
|
|
45600
45646
|
const restaged = ensureBrowserPlaneStaged();
|
|
@@ -45621,9 +45667,9 @@ async function runInBrowser(releaseRoot, app, header, opts = {}) {
|
|
|
45621
45667
|
res.end(bytes2);
|
|
45622
45668
|
return;
|
|
45623
45669
|
}
|
|
45624
|
-
missed.push(
|
|
45670
|
+
missed.push(path2);
|
|
45625
45671
|
res.writeHead(404, { "content-type": "application/json" });
|
|
45626
|
-
res.end(JSON.stringify({ error: "reached_the_cli_not_the_worker", path }));
|
|
45672
|
+
res.end(JSON.stringify({ error: "reached_the_cli_not_the_worker", path: path2 }));
|
|
45627
45673
|
});
|
|
45628
45674
|
await new Promise((r) => server.listen(opts.port ?? 0, "127.0.0.1", () => r()));
|
|
45629
45675
|
const port = server.address().port;
|
|
@@ -46833,8 +46879,8 @@ function client(creds) {
|
|
|
46833
46879
|
const env = creds ?? requireEnv(["ASC_KEY_ID", "ASC_ISSUER_ID", "ASC_KEY_PATH"]);
|
|
46834
46880
|
assertCredentialOutsideRepo("ASC_KEY_PATH", env.ASC_KEY_PATH);
|
|
46835
46881
|
const jwt = ascJwt(env.ASC_KEY_ID, env.ASC_ISSUER_ID, readFileSync61(env.ASC_KEY_PATH, "utf8"), Math.floor(Date.now() / 1e3));
|
|
46836
|
-
return async (
|
|
46837
|
-
const r = await fetch(`${ASC}${
|
|
46882
|
+
return async (path2) => {
|
|
46883
|
+
const r = await fetch(`${ASC}${path2}`, { headers: { Authorization: `Bearer ${jwt}` } });
|
|
46838
46884
|
return { status: r.status, json: await r.json().catch(() => ({})) };
|
|
46839
46885
|
};
|
|
46840
46886
|
}
|
|
@@ -47094,24 +47140,24 @@ import { dirname as dirname29, join as join49 } from "node:path";
|
|
|
47094
47140
|
function defaultSessionsPath() {
|
|
47095
47141
|
return process.env.HIMI_ADMIN_SESSIONS_FILE ?? join49(homedir6(), ".himalaya", "admin-sessions.json");
|
|
47096
47142
|
}
|
|
47097
|
-
function loadSessionsFile(
|
|
47143
|
+
function loadSessionsFile(path2 = defaultSessionsPath()) {
|
|
47098
47144
|
try {
|
|
47099
|
-
return JSON.parse(readFileSync63(
|
|
47145
|
+
return JSON.parse(readFileSync63(path2, "utf8"));
|
|
47100
47146
|
} catch {
|
|
47101
47147
|
return {};
|
|
47102
47148
|
}
|
|
47103
47149
|
}
|
|
47104
|
-
function saveAdminSession(adminUrl, session,
|
|
47105
|
-
const file = loadSessionsFile(
|
|
47150
|
+
function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
|
|
47151
|
+
const file = loadSessionsFile(path2);
|
|
47106
47152
|
file.sessions = { ...file.sessions, [adminUrl]: session };
|
|
47107
|
-
mkdirSync24(dirname29(
|
|
47108
|
-
writeFileSync21(
|
|
47153
|
+
mkdirSync24(dirname29(path2), { recursive: true, mode: 448 });
|
|
47154
|
+
writeFileSync21(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
|
|
47109
47155
|
try {
|
|
47110
|
-
chmodSync3(dirname29(
|
|
47111
|
-
chmodSync3(
|
|
47156
|
+
chmodSync3(dirname29(path2), 448);
|
|
47157
|
+
chmodSync3(path2, 384);
|
|
47112
47158
|
} catch {
|
|
47113
47159
|
}
|
|
47114
|
-
return
|
|
47160
|
+
return path2;
|
|
47115
47161
|
}
|
|
47116
47162
|
function resolveAuth(opts = {}) {
|
|
47117
47163
|
const env = opts.env ?? process.env;
|
|
@@ -47417,9 +47463,9 @@ var init_types2 = __esm({
|
|
|
47417
47463
|
});
|
|
47418
47464
|
|
|
47419
47465
|
// src/site-analyze/rest.ts
|
|
47420
|
-
function resolveWixUrl(
|
|
47421
|
-
if (/^https?:\/\//i.test(
|
|
47422
|
-
return `${WIX_API3}${
|
|
47466
|
+
function resolveWixUrl(path2) {
|
|
47467
|
+
if (/^https?:\/\//i.test(path2)) return path2;
|
|
47468
|
+
return `${WIX_API3}${path2}`;
|
|
47423
47469
|
}
|
|
47424
47470
|
function classifyHttp(status, count) {
|
|
47425
47471
|
if (status === 428) return "not-installed";
|
|
@@ -47428,12 +47474,12 @@ function classifyHttp(status, count) {
|
|
|
47428
47474
|
return count > 0 ? "ok" : "empty";
|
|
47429
47475
|
}
|
|
47430
47476
|
function makeTransport(fetchImpl, auth, timeoutMs = DEFAULT_TIMEOUT_MS4) {
|
|
47431
|
-
return async (method,
|
|
47477
|
+
return async (method, path2, body) => {
|
|
47432
47478
|
const headers2 = { Accept: "application/json" };
|
|
47433
47479
|
if (auth?.token) headers2.Authorization = auth.token;
|
|
47434
47480
|
if (auth?.msid) headers2["wix-site-id"] = auth.msid;
|
|
47435
47481
|
if (body !== void 0) headers2["Content-Type"] = "application/json";
|
|
47436
|
-
const res = await fetchImpl(resolveWixUrl(
|
|
47482
|
+
const res = await fetchImpl(resolveWixUrl(path2), {
|
|
47437
47483
|
method,
|
|
47438
47484
|
headers: headers2,
|
|
47439
47485
|
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
@@ -47445,7 +47491,7 @@ function makeTransport(fetchImpl, auth, timeoutMs = DEFAULT_TIMEOUT_MS4) {
|
|
|
47445
47491
|
parsed = text4 ? JSON.parse(text4) : null;
|
|
47446
47492
|
} catch {
|
|
47447
47493
|
}
|
|
47448
|
-
if (!res.ok) throw new WixApiError2(res.status, method,
|
|
47494
|
+
if (!res.ok) throw new WixApiError2(res.status, method, path2, parsed);
|
|
47449
47495
|
return parsed;
|
|
47450
47496
|
};
|
|
47451
47497
|
}
|
|
@@ -47455,9 +47501,9 @@ function ownerTransportFrom(fetchImpl, owner) {
|
|
|
47455
47501
|
function visitorTransportFrom(fetchImpl, token, msid) {
|
|
47456
47502
|
return makeTransport(fetchImpl, { token, msid });
|
|
47457
47503
|
}
|
|
47458
|
-
async function probeCall(call, method,
|
|
47504
|
+
async function probeCall(call, method, path2, body) {
|
|
47459
47505
|
try {
|
|
47460
|
-
return { data: await call(method,
|
|
47506
|
+
return { data: await call(method, path2, body), err: null };
|
|
47461
47507
|
} catch (e) {
|
|
47462
47508
|
if (e instanceof WixApiError2) return { data: null, err: e };
|
|
47463
47509
|
throw e;
|
|
@@ -47519,11 +47565,11 @@ var init_rest = __esm({
|
|
|
47519
47565
|
WIX_API3 = "https://www.wixapis.com";
|
|
47520
47566
|
DEFAULT_TIMEOUT_MS4 = 8e3;
|
|
47521
47567
|
WixApiError2 = class extends Error {
|
|
47522
|
-
constructor(status, method,
|
|
47523
|
-
super(`${method} ${
|
|
47568
|
+
constructor(status, method, path2, body) {
|
|
47569
|
+
super(`${method} ${path2} \u2192 ${status}`);
|
|
47524
47570
|
this.status = status;
|
|
47525
47571
|
this.method = method;
|
|
47526
|
-
this.path =
|
|
47572
|
+
this.path = path2;
|
|
47527
47573
|
this.body = body;
|
|
47528
47574
|
this.name = "WixApiError";
|
|
47529
47575
|
}
|
|
@@ -47731,8 +47777,8 @@ function toItems(def, raw) {
|
|
|
47731
47777
|
description: copyOrDrop(def.descriptionOf ? def.descriptionOf(it) : genericDescription(it), 240) || void 0
|
|
47732
47778
|
}));
|
|
47733
47779
|
}
|
|
47734
|
-
async function runDualProbes(owner, visitor) {
|
|
47735
|
-
const rows = await Promise.all(
|
|
47780
|
+
async function runDualProbes(owner, visitor, definitions2 = ALL) {
|
|
47781
|
+
const rows = await Promise.all(definitions2.map(async (def) => {
|
|
47736
47782
|
const [o, vis] = await Promise.all([side(owner, def), side(visitor, def)]);
|
|
47737
47783
|
const imageless = def.imageOf ? o.items.filter((it) => !def.imageOf(it)).length : void 0;
|
|
47738
47784
|
return {
|
|
@@ -47794,7 +47840,7 @@ function sampleTitle(data) {
|
|
|
47794
47840
|
}
|
|
47795
47841
|
return void 0;
|
|
47796
47842
|
}
|
|
47797
|
-
async function readCms(call) {
|
|
47843
|
+
async function readCms(call, opts = {}) {
|
|
47798
47844
|
if (!call) return { collections: [], status: "skipped" };
|
|
47799
47845
|
const { data, err } = await probeCall(call, "GET", "/data/v2/collections");
|
|
47800
47846
|
if (err) {
|
|
@@ -47819,7 +47865,7 @@ async function readCms(call) {
|
|
|
47819
47865
|
...f.encrypted === true ? { encrypted: true } : {}
|
|
47820
47866
|
})).filter((f) => f.key);
|
|
47821
47867
|
const perms = c.permissions && typeof c.permissions === "object" ? c.permissions : void 0;
|
|
47822
|
-
const q = await probeCall(call, "POST", "/wix-data/v2/items/query", {
|
|
47868
|
+
const q = opts.samples === false ? { data: null, err: null } : await probeCall(call, "POST", "/wix-data/v2/items/query", {
|
|
47823
47869
|
dataCollectionId: id,
|
|
47824
47870
|
query: { paging: { limit: 5 } }
|
|
47825
47871
|
});
|
|
@@ -47856,8 +47902,8 @@ async function readInstalledApps(call) {
|
|
|
47856
47902
|
"/site-apps/v1/apps",
|
|
47857
47903
|
"/devcenter/v1/apps"
|
|
47858
47904
|
];
|
|
47859
|
-
for (const
|
|
47860
|
-
const { data } = await probeCall(call, "GET",
|
|
47905
|
+
for (const path2 of paths) {
|
|
47906
|
+
const { data } = await probeCall(call, "GET", path2);
|
|
47861
47907
|
if (!data) continue;
|
|
47862
47908
|
const raw = asArr(data.apps ?? data.siteApps ?? data.items);
|
|
47863
47909
|
const apps = raw.map((a) => ({
|
|
@@ -47873,8 +47919,8 @@ async function readMemberRoles(call) {
|
|
|
47873
47919
|
const paths = ["/members/v1/roles", "/members/v2/roles", "/authorization/v1/roles"];
|
|
47874
47920
|
let sawAuthError = false;
|
|
47875
47921
|
let sawEmptyPayload = false;
|
|
47876
|
-
for (const
|
|
47877
|
-
const { data, err } = await probeCall(call, "GET",
|
|
47922
|
+
for (const path2 of paths) {
|
|
47923
|
+
const { data, err } = await probeCall(call, "GET", path2);
|
|
47878
47924
|
if (err) {
|
|
47879
47925
|
if (err.status === 401 || err.status === 403 || err.status >= 500) sawAuthError = true;
|
|
47880
47926
|
continue;
|
|
@@ -48345,15 +48391,15 @@ function pagePathForRole(url) {
|
|
|
48345
48391
|
}
|
|
48346
48392
|
}
|
|
48347
48393
|
function classifyPageRole(url, title, _nav = "") {
|
|
48348
|
-
const { path, isHome } = pagePathForRole(url);
|
|
48394
|
+
const { path: path2, isHome } = pagePathForRole(url);
|
|
48349
48395
|
if (isHome) return "home";
|
|
48350
|
-
const hay = `${
|
|
48396
|
+
const hay = `${path2} ${title}`.toLowerCase();
|
|
48351
48397
|
if (/\b(faq|help|support)\b/.test(hay)) return "faq";
|
|
48352
48398
|
if (/\b(pricing|membership|member-plan|plans?)\b/.test(hay)) return "plans";
|
|
48353
48399
|
if (/\b(drill|library|resource|session-builder|session-generator)\b/.test(hay)) return "library";
|
|
48354
48400
|
if (/\b(members?|account|login|profile)\b/.test(hay) && !/\bmembership\b/.test(hay)) return "members";
|
|
48355
48401
|
if (/\b(shop|store|product|cart)\b/.test(hay)) return "shop";
|
|
48356
|
-
if (/(^|\/)(book|book-online|bookings?)(\/|$)/.test(
|
|
48402
|
+
if (/(^|\/)(book|book-online|bookings?)(\/|$)/.test(path2) || /\b(book-online|bookings?|appoint)\b/.test(hay)) return "book";
|
|
48357
48403
|
if (/\b(menu|dining|restaurant)\b/.test(hay)) return "menu";
|
|
48358
48404
|
if (/\b(blog|journal|news|posts?|ebooks?|insight)\b/.test(hay)) return "blog";
|
|
48359
48405
|
if (/\b(about|story|our-story)\b/.test(hay)) return "about";
|
|
@@ -49007,12 +49053,12 @@ function veloListFilesPath(gridAppId, layout) {
|
|
|
49007
49053
|
async function gridAppIdFromSiteHtml(fetchImpl, siteUrl) {
|
|
49008
49054
|
return (await readPublishedHtml(fetchImpl, siteUrl)).gridAppId;
|
|
49009
49055
|
}
|
|
49010
|
-
function assertSafeVeloPath(
|
|
49011
|
-
if (VELO_INVOKE_RE.test(
|
|
49012
|
-
throw new Error(`refusing to call Velo invoke path: ${
|
|
49056
|
+
function assertSafeVeloPath(path2, method = "GET") {
|
|
49057
|
+
if (VELO_INVOKE_RE.test(path2)) {
|
|
49058
|
+
throw new Error(`refusing to call Velo invoke path: ${path2}`);
|
|
49013
49059
|
}
|
|
49014
|
-
if (method !== "GET" && VELO_WRITE_RE.test(
|
|
49015
|
-
throw new Error(`refusing to call Velo write path: ${method} ${
|
|
49060
|
+
if (method !== "GET" && VELO_WRITE_RE.test(path2.split("?")[0] ?? path2)) {
|
|
49061
|
+
throw new Error(`refusing to call Velo write path: ${method} ${path2}`);
|
|
49016
49062
|
}
|
|
49017
49063
|
}
|
|
49018
49064
|
function parseHttpFunctions(source) {
|
|
@@ -49031,8 +49077,8 @@ function parseHttpFunctions(source) {
|
|
|
49031
49077
|
}
|
|
49032
49078
|
return out;
|
|
49033
49079
|
}
|
|
49034
|
-
function classifyVeloFile(
|
|
49035
|
-
const p =
|
|
49080
|
+
function classifyVeloFile(path2) {
|
|
49081
|
+
const p = path2.replace(/\\/g, "/").toLowerCase();
|
|
49036
49082
|
const base = p.split("/").pop() ?? p;
|
|
49037
49083
|
if (base === "http-functions.js" || base === "http-functions.ts") return "http-functions";
|
|
49038
49084
|
if (base === "data.js" || base === "data.ts") return "data-hooks";
|
|
@@ -49044,8 +49090,8 @@ function classifyVeloFile(path) {
|
|
|
49044
49090
|
if (/(^|\/)public\//.test(p)) return "public";
|
|
49045
49091
|
return "other";
|
|
49046
49092
|
}
|
|
49047
|
-
function isSecretVeloPath(
|
|
49048
|
-
const p =
|
|
49093
|
+
function isSecretVeloPath(path2) {
|
|
49094
|
+
const p = path2.replace(/\\/g, "/").toLowerCase();
|
|
49049
49095
|
return /secrets-backend|\/secrets\/|\.env(?:\.|$)/.test(p);
|
|
49050
49096
|
}
|
|
49051
49097
|
function redactSecrets(source) {
|
|
@@ -49075,7 +49121,7 @@ function str4(x) {
|
|
|
49075
49121
|
function asArr2(x) {
|
|
49076
49122
|
return Array.isArray(x) ? x : [];
|
|
49077
49123
|
}
|
|
49078
|
-
function filesFromOwnerPayload(data) {
|
|
49124
|
+
function filesFromOwnerPayload(data, redact = redactSecrets) {
|
|
49079
49125
|
if (!data || typeof data !== "object") return [];
|
|
49080
49126
|
const root = data;
|
|
49081
49127
|
const raw = [
|
|
@@ -49087,17 +49133,17 @@ function filesFromOwnerPayload(data) {
|
|
|
49087
49133
|
for (const item of raw) {
|
|
49088
49134
|
if (!item || typeof item !== "object") continue;
|
|
49089
49135
|
const f = item;
|
|
49090
|
-
const
|
|
49091
|
-
if (!
|
|
49136
|
+
const path2 = str4(f.path || f.relativePath || f.fileName || f.name);
|
|
49137
|
+
if (!path2 || isSecretVeloPath(path2)) continue;
|
|
49092
49138
|
const content = str4(f.content ?? f.source ?? f.code ?? f.body);
|
|
49093
49139
|
const bytes2 = typeof f.bytes === "number" ? f.bytes : typeof f.size === "number" ? f.size : content.length;
|
|
49094
|
-
const redacted = content ?
|
|
49140
|
+
const redacted = content ? redact(content) : "";
|
|
49095
49141
|
const forDisk = redacted.length > VELO_FILE_CAP ? redacted.slice(0, VELO_FILE_CAP) + "\n/* \u2026truncated */" : redacted;
|
|
49096
49142
|
out.push({
|
|
49097
|
-
path,
|
|
49098
|
-
kind: classifyVeloFile(
|
|
49143
|
+
path: path2,
|
|
49144
|
+
kind: classifyVeloFile(path2),
|
|
49099
49145
|
bytes: bytes2,
|
|
49100
|
-
excerpt: content ? redactExcerpt(
|
|
49146
|
+
excerpt: content ? redactExcerpt(redacted) : void 0,
|
|
49101
49147
|
...forDisk ? { content: forDisk } : {}
|
|
49102
49148
|
});
|
|
49103
49149
|
}
|
|
@@ -49140,8 +49186,8 @@ function veloHintFromEval(evaled, page) {
|
|
|
49140
49186
|
pages: [{ url: page.url, title: page.title, hasCode: wixRendered && hasCode, ...pageId ? { pageId } : {} }]
|
|
49141
49187
|
};
|
|
49142
49188
|
}
|
|
49143
|
-
function pageIdFromVeloPath(
|
|
49144
|
-
const m =
|
|
49189
|
+
function pageIdFromVeloPath(path2) {
|
|
49190
|
+
const m = path2.replace(/\\/g, "/").match(/\/pages\/([A-Za-z0-9_-]+)\.(js|ts|jsx|tsx)$/i);
|
|
49145
49191
|
return m?.[1];
|
|
49146
49192
|
}
|
|
49147
49193
|
function bindVeloFiles(files, pages) {
|
|
@@ -49186,13 +49232,13 @@ function gridAppIdsFromPayload(data) {
|
|
|
49186
49232
|
}
|
|
49187
49233
|
return ids;
|
|
49188
49234
|
}
|
|
49189
|
-
async function listFilesForApp(call, gridAppId) {
|
|
49235
|
+
async function listFilesForApp(call, gridAppId, redact) {
|
|
49190
49236
|
for (const layout of VELO_LAYOUTS) {
|
|
49191
|
-
const
|
|
49192
|
-
assertSafeVeloPath(
|
|
49193
|
-
const { data } = await probeCall(call, "GET",
|
|
49237
|
+
const path2 = veloListFilesPath(gridAppId, layout);
|
|
49238
|
+
assertSafeVeloPath(path2, "GET");
|
|
49239
|
+
const { data } = await probeCall(call, "GET", path2);
|
|
49194
49240
|
if (!data) continue;
|
|
49195
|
-
const files = filesFromOwnerPayload(data);
|
|
49241
|
+
const files = filesFromOwnerPayload(data, redact);
|
|
49196
49242
|
if (files.length) return files;
|
|
49197
49243
|
}
|
|
49198
49244
|
return [];
|
|
@@ -49214,7 +49260,7 @@ async function readOwnerVelo(call, opts) {
|
|
|
49214
49260
|
if (probe.path.includes("git-repo") && (data.repo || data.repository || data.gitRepo || data.url)) git2 = true;
|
|
49215
49261
|
}
|
|
49216
49262
|
for (const id of ids) {
|
|
49217
|
-
const listed = await listFilesForApp(call, id);
|
|
49263
|
+
const listed = await listFilesForApp(call, id, opts?.redact);
|
|
49218
49264
|
for (const f of listed) {
|
|
49219
49265
|
if (!files.some((x) => x.path === f.path)) files.push(f);
|
|
49220
49266
|
}
|
|
@@ -49551,14 +49597,14 @@ function parseAuthorizationConfig(source) {
|
|
|
49551
49597
|
const defaultAnonymousInvoke = invokeFlag(starDefault, "anonymous") ?? true;
|
|
49552
49598
|
const defaultSiteMemberInvoke = invokeFlag(starDefault, "siteMember") ?? true;
|
|
49553
49599
|
const modules = [];
|
|
49554
|
-
for (const [
|
|
49555
|
-
if (
|
|
49600
|
+
for (const [path2, entry] of Object.entries(web)) {
|
|
49601
|
+
if (path2 === "*") continue;
|
|
49556
49602
|
const star = methodStar(entry);
|
|
49557
49603
|
const anonymousInvoke = invokeFlag(star, "anonymous") ?? defaultAnonymousInvoke;
|
|
49558
49604
|
const siteMemberInvoke = invokeFlag(star, "siteMember") ?? defaultSiteMemberInvoke;
|
|
49559
|
-
const jsw = /\.(jsw|web\.js)$/i.test(
|
|
49605
|
+
const jsw = /\.(jsw|web\.js)$/i.test(path2);
|
|
49560
49606
|
modules.push({
|
|
49561
|
-
path,
|
|
49607
|
+
path: path2,
|
|
49562
49608
|
anonymousInvoke,
|
|
49563
49609
|
siteMemberInvoke,
|
|
49564
49610
|
...jsw ? { note: "worker-unreachable" } : {}
|
|
@@ -50697,12 +50743,12 @@ function attachVeloSources(book, sources, put) {
|
|
|
50697
50743
|
}
|
|
50698
50744
|
}
|
|
50699
50745
|
function extOf2(url) {
|
|
50700
|
-
const
|
|
50701
|
-
if (/\.png$/i.test(
|
|
50702
|
-
if (/\.webp$/i.test(
|
|
50703
|
-
if (/\.gif$/i.test(
|
|
50704
|
-
if (/\.svg$/i.test(
|
|
50705
|
-
if (/\.ico$/i.test(
|
|
50746
|
+
const path2 = url.split("?")[0] ?? url;
|
|
50747
|
+
if (/\.png$/i.test(path2)) return "png";
|
|
50748
|
+
if (/\.webp$/i.test(path2)) return "webp";
|
|
50749
|
+
if (/\.gif$/i.test(path2)) return "gif";
|
|
50750
|
+
if (/\.svg$/i.test(path2)) return "svg";
|
|
50751
|
+
if (/\.ico$/i.test(path2)) return "ico";
|
|
50706
50752
|
return "jpg";
|
|
50707
50753
|
}
|
|
50708
50754
|
async function readCapped(res, cap) {
|
|
@@ -51273,8 +51319,8 @@ function unpairedRedirectNote(overlay) {
|
|
|
51273
51319
|
function posix2(p) {
|
|
51274
51320
|
return resolve42(p).replace(/\\/g, "/");
|
|
51275
51321
|
}
|
|
51276
|
-
function committedShellProvisioning(
|
|
51277
|
-
return committedShellFor(posix2(
|
|
51322
|
+
function committedShellProvisioning(path2) {
|
|
51323
|
+
return committedShellFor(posix2(path2));
|
|
51278
51324
|
}
|
|
51279
51325
|
function findRepoRoot(cwd) {
|
|
51280
51326
|
let dir = cwd;
|
|
@@ -51298,14 +51344,14 @@ function deepMerge4(a, b) {
|
|
|
51298
51344
|
}
|
|
51299
51345
|
return out;
|
|
51300
51346
|
}
|
|
51301
|
-
function assertNotCommitted(
|
|
51302
|
-
const committed = committedShellProvisioning(
|
|
51347
|
+
function assertNotCommitted(path2, forbidden) {
|
|
51348
|
+
const committed = committedShellProvisioning(path2);
|
|
51303
51349
|
if (committed) {
|
|
51304
51350
|
throw new Error(
|
|
51305
51351
|
`refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 use prepare:customer --contract`
|
|
51306
51352
|
);
|
|
51307
51353
|
}
|
|
51308
|
-
if (forbidden && resolve42(
|
|
51354
|
+
if (forbidden && resolve42(path2) === resolve42(forbidden)) {
|
|
51309
51355
|
const named = committedShellProvisioning(forbidden);
|
|
51310
51356
|
throw new Error(
|
|
51311
51357
|
`refusing to overwrite committed ${named ? committedProvisioningPath(named) : forbidden} \u2014 pass a content-package provisioning.json or use prepare:customer --contract`
|
|
@@ -51411,13 +51457,13 @@ function buildMergedContract(options) {
|
|
|
51411
51457
|
merged.branding = branding;
|
|
51412
51458
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
51413
51459
|
`;
|
|
51414
|
-
const
|
|
51415
|
-
writeFileSync23(
|
|
51460
|
+
const path2 = join51(packageDir, "provisioning.contract.json");
|
|
51461
|
+
writeFileSync23(path2, body);
|
|
51416
51462
|
const localPath = join51(appDir2, LOCAL_CONTRACT_REL);
|
|
51417
51463
|
mkdirSync26(dirname30(localPath), { recursive: true });
|
|
51418
51464
|
writeFileSync23(localPath, body);
|
|
51419
51465
|
staged.push(localPath);
|
|
51420
|
-
return { path, staged };
|
|
51466
|
+
return { path: path2, staged };
|
|
51421
51467
|
}
|
|
51422
51468
|
async function applyOverlays(input) {
|
|
51423
51469
|
const cwd = resolve42(input.cwd);
|
|
@@ -52849,18 +52895,18 @@ function cookieCompare(a, b) {
|
|
|
52849
52895
|
cmp = (a.creationIndex || 0) - (b.creationIndex || 0);
|
|
52850
52896
|
return cmp;
|
|
52851
52897
|
}
|
|
52852
|
-
function defaultPath(
|
|
52853
|
-
if (!
|
|
52898
|
+
function defaultPath(path2) {
|
|
52899
|
+
if (!path2 || path2.slice(0, 1) !== "/") {
|
|
52854
52900
|
return "/";
|
|
52855
52901
|
}
|
|
52856
|
-
if (
|
|
52857
|
-
return
|
|
52902
|
+
if (path2 === "/") {
|
|
52903
|
+
return path2;
|
|
52858
52904
|
}
|
|
52859
|
-
const rightSlash =
|
|
52905
|
+
const rightSlash = path2.lastIndexOf("/");
|
|
52860
52906
|
if (rightSlash === 0) {
|
|
52861
52907
|
return "/";
|
|
52862
52908
|
}
|
|
52863
|
-
return
|
|
52909
|
+
return path2.slice(0, rightSlash);
|
|
52864
52910
|
}
|
|
52865
52911
|
function domainMatch(domain, cookieDomain, canonicalize) {
|
|
52866
52912
|
if (domain == null || cookieDomain == null) {
|
|
@@ -53088,18 +53134,18 @@ var init_dist = __esm({
|
|
|
53088
53134
|
/**
|
|
53089
53135
|
* @internal No doc because this is an overload that supports the implementation
|
|
53090
53136
|
*/
|
|
53091
|
-
findCookie(domain,
|
|
53137
|
+
findCookie(domain, path2, key2, callback) {
|
|
53092
53138
|
const promiseCallback = createPromiseCallback(callback);
|
|
53093
|
-
if (domain == null ||
|
|
53139
|
+
if (domain == null || path2 == null || key2 == null) {
|
|
53094
53140
|
return promiseCallback.resolve(void 0);
|
|
53095
53141
|
}
|
|
53096
|
-
const result = this.idx[domain]?.[
|
|
53142
|
+
const result = this.idx[domain]?.[path2]?.[key2];
|
|
53097
53143
|
return promiseCallback.resolve(result);
|
|
53098
53144
|
}
|
|
53099
53145
|
/**
|
|
53100
53146
|
* @internal No doc because this is an overload that supports the implementation
|
|
53101
53147
|
*/
|
|
53102
|
-
findCookies(domain,
|
|
53148
|
+
findCookies(domain, path2, allowSpecialUseDomain = false, callback) {
|
|
53103
53149
|
if (typeof allowSpecialUseDomain === "function") {
|
|
53104
53150
|
callback = allowSpecialUseDomain;
|
|
53105
53151
|
allowSpecialUseDomain = true;
|
|
@@ -53110,7 +53156,7 @@ var init_dist = __esm({
|
|
|
53110
53156
|
return promiseCallback.resolve([]);
|
|
53111
53157
|
}
|
|
53112
53158
|
let pathMatcher;
|
|
53113
|
-
if (!
|
|
53159
|
+
if (!path2) {
|
|
53114
53160
|
pathMatcher = function matchAll(domainIndex) {
|
|
53115
53161
|
for (const curPath in domainIndex) {
|
|
53116
53162
|
const pathIndex = domainIndex[curPath];
|
|
@@ -53125,7 +53171,7 @@ var init_dist = __esm({
|
|
|
53125
53171
|
} else {
|
|
53126
53172
|
pathMatcher = function matchRFC(domainIndex) {
|
|
53127
53173
|
for (const cookiePath in domainIndex) {
|
|
53128
|
-
if (pathMatch(
|
|
53174
|
+
if (pathMatch(path2, cookiePath)) {
|
|
53129
53175
|
const pathIndex = domainIndex[cookiePath];
|
|
53130
53176
|
for (const key2 in pathIndex) {
|
|
53131
53177
|
const value = pathIndex[key2];
|
|
@@ -53153,14 +53199,14 @@ var init_dist = __esm({
|
|
|
53153
53199
|
*/
|
|
53154
53200
|
putCookie(cookie, callback) {
|
|
53155
53201
|
const promiseCallback = createPromiseCallback(callback);
|
|
53156
|
-
const { domain, path, key: key2 } = cookie;
|
|
53157
|
-
if (domain == null ||
|
|
53202
|
+
const { domain, path: path2, key: key2 } = cookie;
|
|
53203
|
+
if (domain == null || path2 == null || key2 == null) {
|
|
53158
53204
|
return promiseCallback.resolve(void 0);
|
|
53159
53205
|
}
|
|
53160
53206
|
const domainEntry = this.idx[domain] ?? /* @__PURE__ */ Object.create(null);
|
|
53161
53207
|
this.idx[domain] = domainEntry;
|
|
53162
|
-
const pathEntry = domainEntry[
|
|
53163
|
-
domainEntry[
|
|
53208
|
+
const pathEntry = domainEntry[path2] ?? /* @__PURE__ */ Object.create(null);
|
|
53209
|
+
domainEntry[path2] = pathEntry;
|
|
53164
53210
|
pathEntry[key2] = cookie;
|
|
53165
53211
|
return promiseCallback.resolve(void 0);
|
|
53166
53212
|
}
|
|
@@ -53174,20 +53220,20 @@ var init_dist = __esm({
|
|
|
53174
53220
|
/**
|
|
53175
53221
|
* @internal No doc because this is an overload that supports the implementation
|
|
53176
53222
|
*/
|
|
53177
|
-
removeCookie(domain,
|
|
53223
|
+
removeCookie(domain, path2, key2, callback) {
|
|
53178
53224
|
const promiseCallback = createPromiseCallback(callback);
|
|
53179
|
-
delete this.idx[domain]?.[
|
|
53225
|
+
delete this.idx[domain]?.[path2]?.[key2];
|
|
53180
53226
|
return promiseCallback.resolve(void 0);
|
|
53181
53227
|
}
|
|
53182
53228
|
/**
|
|
53183
53229
|
* @internal No doc because this is an overload that supports the implementation
|
|
53184
53230
|
*/
|
|
53185
|
-
removeCookies(domain,
|
|
53231
|
+
removeCookies(domain, path2, callback) {
|
|
53186
53232
|
const promiseCallback = createPromiseCallback(callback);
|
|
53187
53233
|
const domainEntry = this.idx[domain];
|
|
53188
53234
|
if (domainEntry) {
|
|
53189
|
-
if (
|
|
53190
|
-
delete domainEntry[
|
|
53235
|
+
if (path2) {
|
|
53236
|
+
delete domainEntry[path2];
|
|
53191
53237
|
} else {
|
|
53192
53238
|
delete this.idx[domain];
|
|
53193
53239
|
}
|
|
@@ -53213,8 +53259,8 @@ var init_dist = __esm({
|
|
|
53213
53259
|
domains.forEach((domain) => {
|
|
53214
53260
|
const domainEntry = idx[domain] ?? {};
|
|
53215
53261
|
const paths = Object.keys(domainEntry);
|
|
53216
|
-
paths.forEach((
|
|
53217
|
-
const pathEntry = domainEntry[
|
|
53262
|
+
paths.forEach((path2) => {
|
|
53263
|
+
const pathEntry = domainEntry[path2] ?? {};
|
|
53218
53264
|
const keys = Object.keys(pathEntry);
|
|
53219
53265
|
keys.forEach((key2) => {
|
|
53220
53266
|
const keyEntry = pathEntry[key2];
|
|
@@ -53982,7 +54028,7 @@ var init_dist = __esm({
|
|
|
53982
54028
|
return promiseCallback.reject(parameterError);
|
|
53983
54029
|
}
|
|
53984
54030
|
const host = canonicalDomain(context.hostname);
|
|
53985
|
-
const
|
|
54031
|
+
const path2 = context.pathname || "/";
|
|
53986
54032
|
const potentiallyTrustworthy = isPotentiallyTrustworthy(
|
|
53987
54033
|
url,
|
|
53988
54034
|
this.allowSecureOnLocal
|
|
@@ -54013,7 +54059,7 @@ var init_dist = __esm({
|
|
|
54013
54059
|
return false;
|
|
54014
54060
|
}
|
|
54015
54061
|
}
|
|
54016
|
-
if (!allPaths && typeof c.path === "string" && !pathMatch(
|
|
54062
|
+
if (!allPaths && typeof c.path === "string" && !pathMatch(path2, c.path)) {
|
|
54017
54063
|
return false;
|
|
54018
54064
|
}
|
|
54019
54065
|
if (c.secure && !potentiallyTrustworthy) {
|
|
@@ -54045,7 +54091,7 @@ var init_dist = __esm({
|
|
|
54045
54091
|
}
|
|
54046
54092
|
store.findCookies(
|
|
54047
54093
|
host,
|
|
54048
|
-
allPaths ? null :
|
|
54094
|
+
allPaths ? null : path2,
|
|
54049
54095
|
this.allowSpecialUseDomain,
|
|
54050
54096
|
(err, cookies) => {
|
|
54051
54097
|
if (err) {
|
|
@@ -55423,9 +55469,9 @@ function filesFromList(data) {
|
|
|
55423
55469
|
if (!Array.isArray(files)) return [];
|
|
55424
55470
|
return files.flatMap((f) => {
|
|
55425
55471
|
if (!f || typeof f !== "object") return [];
|
|
55426
|
-
const
|
|
55472
|
+
const path2 = String(f.path ?? "");
|
|
55427
55473
|
const content = String(f.content ?? "");
|
|
55428
|
-
return
|
|
55474
|
+
return path2 ? [{ path: path2, content }] : [];
|
|
55429
55475
|
});
|
|
55430
55476
|
}
|
|
55431
55477
|
async function resolveGridAppId(fetchImpl, token, msid, siteUrl) {
|
|
@@ -55852,14 +55898,14 @@ function apiKeyAuth(env = process.env) {
|
|
|
55852
55898
|
return key2 && accountId ? { key: key2, accountId } : void 0;
|
|
55853
55899
|
}
|
|
55854
55900
|
function accountTransport(fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS5, spawnImpl = spawn4) {
|
|
55855
|
-
return async (method,
|
|
55901
|
+
return async (method, path2, body) => {
|
|
55856
55902
|
const viaKey = apiKeyAuth();
|
|
55857
55903
|
const headers2 = viaKey ? { Authorization: viaKey.key, "wix-account-id": viaKey.accountId, Accept: "application/json" } : { Authorization: await accountToken2(spawnImpl), Accept: "application/json" };
|
|
55858
55904
|
if (body !== void 0) headers2["Content-Type"] = "application/json";
|
|
55859
55905
|
const started = Date.now();
|
|
55860
55906
|
let res;
|
|
55861
55907
|
try {
|
|
55862
|
-
res = await fetchImpl(`${API_BASE2}${
|
|
55908
|
+
res = await fetchImpl(`${API_BASE2}${path2}`, {
|
|
55863
55909
|
method,
|
|
55864
55910
|
headers: headers2,
|
|
55865
55911
|
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
@@ -55869,10 +55915,10 @@ function accountTransport(fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS5, sp
|
|
|
55869
55915
|
const err = e;
|
|
55870
55916
|
if (err?.name === "TimeoutError" || /aborted due to timeout/i.test(err?.message ?? "")) {
|
|
55871
55917
|
throw new Error(
|
|
55872
|
-
`${method} ${
|
|
55918
|
+
`${method} ${path2} timed out after ${Date.now() - started}ms (limit ${timeoutMs}ms). Raise the ceiling with HIMI_WIX_TIMEOUT_MS=<ms>, or check the VPN.`
|
|
55873
55919
|
);
|
|
55874
55920
|
}
|
|
55875
|
-
throw new Error(`${method} ${
|
|
55921
|
+
throw new Error(`${method} ${path2} failed: ${err?.message ?? String(e)}`);
|
|
55876
55922
|
}
|
|
55877
55923
|
const text4 = await res.text();
|
|
55878
55924
|
let parsed = text4;
|
|
@@ -55880,7 +55926,7 @@ function accountTransport(fetchImpl = fetch, timeoutMs = DEFAULT_TIMEOUT_MS5, sp
|
|
|
55880
55926
|
parsed = text4 ? JSON.parse(text4) : null;
|
|
55881
55927
|
} catch {
|
|
55882
55928
|
}
|
|
55883
|
-
if (!res.ok) throw new WixApiError(res.status, method,
|
|
55929
|
+
if (!res.ok) throw new WixApiError(res.status, method, path2, parsed);
|
|
55884
55930
|
return parsed;
|
|
55885
55931
|
};
|
|
55886
55932
|
}
|
|
@@ -56159,27 +56205,27 @@ async function runSiteCreate(opts) {
|
|
|
56159
56205
|
}
|
|
56160
56206
|
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync55, readFileSync: readFileSync66, writeFileSync: writeFileSync24 }) {
|
|
56161
56207
|
const msid = binding2.siteId;
|
|
56162
|
-
const
|
|
56163
|
-
const committed = committedShellProvisioning(
|
|
56208
|
+
const path2 = resolvePath2(target);
|
|
56209
|
+
const committed = committedShellProvisioning(path2);
|
|
56164
56210
|
if (committed) {
|
|
56165
56211
|
throw new Error(
|
|
56166
56212
|
`refusing to overwrite committed ${committedProvisioningPath(committed)} \u2014 pass a content-package provisioning.json, or use \`prepare:customer --contract\``
|
|
56167
56213
|
);
|
|
56168
56214
|
}
|
|
56169
|
-
if (!fs.existsSync(
|
|
56215
|
+
if (!fs.existsSync(path2)) {
|
|
56170
56216
|
throw new Error(
|
|
56171
|
-
`no provisioning.json at ${
|
|
56217
|
+
`no provisioning.json at ${path2}. --write-provisioning updates an EXISTING manifest (it needs identity/branding/installedVerticals, which this command cannot invent). Run it from a content package, or pass --write-provisioning <path>.`
|
|
56172
56218
|
);
|
|
56173
56219
|
}
|
|
56174
|
-
const raw = fs.readFileSync(
|
|
56220
|
+
const raw = fs.readFileSync(path2, "utf8");
|
|
56175
56221
|
let manifest;
|
|
56176
56222
|
try {
|
|
56177
56223
|
manifest = JSON.parse(raw);
|
|
56178
56224
|
} catch (e) {
|
|
56179
|
-
throw new Error(`${
|
|
56225
|
+
throw new Error(`${path2} is not valid JSON (${e?.message ?? e}) \u2014 not touching it`);
|
|
56180
56226
|
}
|
|
56181
56227
|
if (manifest === null || typeof manifest !== "object" || Array.isArray(manifest)) {
|
|
56182
|
-
throw new Error(`${
|
|
56228
|
+
throw new Error(`${path2} must contain a JSON object \u2014 not touching it`);
|
|
56183
56229
|
}
|
|
56184
56230
|
if (binding2.siteUrl !== void 0) assertAbsoluteHttpUrl(binding2.siteUrl);
|
|
56185
56231
|
if (binding2.redirectUri !== void 0) assertRedirectUri(binding2.redirectUri);
|
|
@@ -56197,9 +56243,9 @@ function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSyn
|
|
|
56197
56243
|
const indentMatch = /^[ \t]*[{[][\r\n]+([ \t]+)/.exec(raw);
|
|
56198
56244
|
const indent = indentMatch ? indentMatch[1] : " ";
|
|
56199
56245
|
const trailingNewline = /\n$/.test(raw) ? "\n" : "";
|
|
56200
|
-
fs.writeFileSync(
|
|
56246
|
+
fs.writeFileSync(path2, `${JSON.stringify(manifest, null, indent)}${trailingNewline}`, "utf8");
|
|
56201
56247
|
return {
|
|
56202
|
-
path,
|
|
56248
|
+
path: path2,
|
|
56203
56249
|
siteId: msid,
|
|
56204
56250
|
...binding2.clientId ? { clientId: binding2.clientId } : {},
|
|
56205
56251
|
...binding2.siteUrl ? { siteUrl: binding2.siteUrl } : {},
|
|
@@ -56488,9 +56534,350 @@ var init_site_oauth_client = __esm({
|
|
|
56488
56534
|
}
|
|
56489
56535
|
});
|
|
56490
56536
|
|
|
56537
|
+
// src/site-analyze/velo-source.ts
|
|
56538
|
+
import path from "node:path";
|
|
56539
|
+
import ts from "typescript";
|
|
56540
|
+
function applySourceEdits(source, edits) {
|
|
56541
|
+
const chunks = [];
|
|
56542
|
+
let cursor = 0;
|
|
56543
|
+
for (const edit of edits.sort((a, b) => a.start - b.start || b.end - a.end)) {
|
|
56544
|
+
if (edit.start < cursor) continue;
|
|
56545
|
+
chunks.push(source.slice(cursor, edit.start), edit.text);
|
|
56546
|
+
cursor = edit.end;
|
|
56547
|
+
}
|
|
56548
|
+
chunks.push(source.slice(cursor));
|
|
56549
|
+
return chunks.join("");
|
|
56550
|
+
}
|
|
56551
|
+
function redactVeloSource(source, knownSecrets = []) {
|
|
56552
|
+
for (const secret of knownSecrets.filter(Boolean)) source = source.split(secret).join(REDACTED2);
|
|
56553
|
+
source = source.replace(/-----BEGIN [^-]*PRIVATE KEY-----[\s\S]*?-----END [^-]*PRIVATE KEY-----/g, REDACTED2).replace(
|
|
56554
|
+
/\b(?:IST\.[\w.-]+|eyJ[\w-]+\.[\w-]+\.[\w-]+|(?:sk|rk)_(?:live|test)_[\w-]+|gh[pousr]_[\w]+|github_pat_[\w]+|AKIA[A-Z0-9]{16})\b/g,
|
|
56555
|
+
REDACTED2
|
|
56556
|
+
).replace(/\b(?:Bearer|Basic)\s+[A-Za-z0-9._~+/=-]+/gi, REDACTED2).replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^\s/'"`]+:[^\s/'"`]+@/gi, "$1[REDACTED]@").replace(/([?&](?:api[-_]?key|token|secret|password|signature)=)[^&#\s'"`]+/gi, "$1[REDACTED]");
|
|
56557
|
+
const parsed = ts.createSourceFile("backend.ts", source, ts.ScriptTarget.Latest, true);
|
|
56558
|
+
const comments = /* @__PURE__ */ new Map();
|
|
56559
|
+
const visitComments = (node) => {
|
|
56560
|
+
for (const range of [
|
|
56561
|
+
...ts.getLeadingCommentRanges(source, node.pos) ?? [],
|
|
56562
|
+
...ts.getTrailingCommentRanges(source, node.pos) ?? [],
|
|
56563
|
+
...ts.getTrailingCommentRanges(source, node.end) ?? []
|
|
56564
|
+
]) comments.set(range.pos, range.end);
|
|
56565
|
+
for (const child of node.getChildren(parsed)) visitComments(child);
|
|
56566
|
+
};
|
|
56567
|
+
visitComments(parsed);
|
|
56568
|
+
source = applySourceEdits(source, [...comments].map(([start, end]) => ({ start, end, text: " " })));
|
|
56569
|
+
const redactLiteral = (token, offset) => {
|
|
56570
|
+
const before = assignmentContext.slice(Math.max(0, offset - 200), offset);
|
|
56571
|
+
if (/^\s*:/.test(source.slice(offset + token.length)) && /[{,]\s*$/.test(before)) return token;
|
|
56572
|
+
const statement = before.slice(before.lastIndexOf(";") + 1);
|
|
56573
|
+
const sensitiveAssignment = [
|
|
56574
|
+
...statement.matchAll(/([\w$-]+|"[^"\n]+"|'[^'\n]+')\s*(?:\]\s*)?[:=]/g)
|
|
56575
|
+
].some((match) => sensitiveName.test(match[1]));
|
|
56576
|
+
const headerArgument = /(?:set|append)\s*\(\s*["']([^"']+)["']\s*,\s*$/.exec(before);
|
|
56577
|
+
if (sensitiveAssignment || sensitiveName.test(headerArgument?.[1] ?? ""))
|
|
56578
|
+
return JSON.stringify(REDACTED2);
|
|
56579
|
+
if (/^["'`][A-Za-z0-9_+/=-]{24,}["'`]$/.test(token)) return JSON.stringify(REDACTED2);
|
|
56580
|
+
return token;
|
|
56581
|
+
};
|
|
56582
|
+
const clean2 = ts.createSourceFile("backend.ts", source, ts.ScriptTarget.Latest, true);
|
|
56583
|
+
const masks = [];
|
|
56584
|
+
const collectMasks = (node) => {
|
|
56585
|
+
const start = node.getStart(clean2);
|
|
56586
|
+
if (ts.isRegularExpressionLiteral(node)) {
|
|
56587
|
+
masks.push({ start, end: node.end, text: " ".repeat(node.end - start) });
|
|
56588
|
+
} else if (ts.isStringLiteral(node) || ts.isTemplateLiteralToken(node)) {
|
|
56589
|
+
masks.push({ start, end: node.end, text: source.slice(start, node.end).replace(/;/g, " ") });
|
|
56590
|
+
}
|
|
56591
|
+
ts.forEachChild(node, collectMasks);
|
|
56592
|
+
};
|
|
56593
|
+
collectMasks(clean2);
|
|
56594
|
+
const assignmentContext = applySourceEdits(source, masks);
|
|
56595
|
+
const edits = [];
|
|
56596
|
+
const visitLiterals = (node) => {
|
|
56597
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node) || ts.isTemplateExpression(node)) {
|
|
56598
|
+
const start = node.getStart(clean2);
|
|
56599
|
+
const text4 = source.slice(start, node.end);
|
|
56600
|
+
const redacted = redactLiteral(text4, start);
|
|
56601
|
+
if (redacted !== text4) {
|
|
56602
|
+
edits.push({ start, end: node.end, text: redacted });
|
|
56603
|
+
return;
|
|
56604
|
+
}
|
|
56605
|
+
}
|
|
56606
|
+
ts.forEachChild(node, visitLiterals);
|
|
56607
|
+
};
|
|
56608
|
+
visitLiterals(clean2);
|
|
56609
|
+
return applySourceEdits(source, edits);
|
|
56610
|
+
}
|
|
56611
|
+
function backendSourcePath(filename) {
|
|
56612
|
+
const normalized = filename.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
56613
|
+
if (!/^(?:src\/)?backend\//.test(normalized) || normalized.split("/").includes("..")) return;
|
|
56614
|
+
if (/(?:secret|credential|\.env|\.pem|\.key|node_modules|__tests__|\.test\.|\.spec\.)/i.test(
|
|
56615
|
+
normalized
|
|
56616
|
+
))
|
|
56617
|
+
return;
|
|
56618
|
+
return /\.(?:js|ts|jsw)$/.test(normalized) ? normalized : void 0;
|
|
56619
|
+
}
|
|
56620
|
+
function selectVeloSource(files, request, knownSecrets = []) {
|
|
56621
|
+
const candidates = files.flatMap((file) => {
|
|
56622
|
+
const normalized = backendSourcePath(file.path);
|
|
56623
|
+
return normalized && file.content.trim() ? [{ ...file, path: normalized }] : [];
|
|
56624
|
+
});
|
|
56625
|
+
const byPath = new Map(candidates.map((file) => [file.path, file]));
|
|
56626
|
+
const words = [...new Set(request.toLowerCase().match(/[a-z][a-z0-9_]{3,}/g) ?? [])].filter(
|
|
56627
|
+
(word) => !["with", "that", "this", "from", "have", "want", "app", "site", "backend"].includes(word)
|
|
56628
|
+
).slice(0, 80);
|
|
56629
|
+
const score = (file) => {
|
|
56630
|
+
const names = file.path + " " + [...file.content.matchAll(/export\s+(?:async\s+)?(?:function|const)\s+(\w+)/g)].map((m) => m[1]).join(" ");
|
|
56631
|
+
return words.reduce((sum, word) => sum + (names.toLowerCase().includes(word) ? 10 : 0), 0) + (/http-functions\.[jt]s$|\.web\.[jt]s$|\.jsw$/.test(file.path) ? 1 : 0);
|
|
56632
|
+
};
|
|
56633
|
+
const queue = candidates.filter((file) => score(file) > 0).sort((a, b) => score(b) - score(a) || a.path.localeCompare(b.path));
|
|
56634
|
+
const selected = /* @__PURE__ */ new Map();
|
|
56635
|
+
let remaining = MAX_TOTAL_CHARS;
|
|
56636
|
+
while (queue.length && selected.size < MAX_FILES && remaining > 0) {
|
|
56637
|
+
const file = queue.shift();
|
|
56638
|
+
if (!file) break;
|
|
56639
|
+
if (selected.has(file.path)) continue;
|
|
56640
|
+
const redacted = redactVeloSource(file.content, knownSecrets);
|
|
56641
|
+
const excerpt = redacted.slice(0, Math.min(MAX_FILE_CHARS, remaining));
|
|
56642
|
+
selected.set(file.path, { source: excerpt, sourceTruncated: excerpt.length < redacted.length });
|
|
56643
|
+
remaining -= excerpt.length;
|
|
56644
|
+
const dependencies = [];
|
|
56645
|
+
const parsed = ts.createSourceFile(file.path, file.content, ts.ScriptTarget.Latest, true);
|
|
56646
|
+
const specifiers = [];
|
|
56647
|
+
const collectImports = (node) => {
|
|
56648
|
+
let specifier;
|
|
56649
|
+
if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
|
|
56650
|
+
specifier = node.moduleSpecifier;
|
|
56651
|
+
} else if (ts.isImportEqualsDeclaration(node) && ts.isExternalModuleReference(node.moduleReference)) {
|
|
56652
|
+
specifier = node.moduleReference.expression;
|
|
56653
|
+
} else if (ts.isCallExpression(node) && (node.expression.kind === ts.SyntaxKind.ImportKeyword || ts.isIdentifier(node.expression) && node.expression.text === "require")) {
|
|
56654
|
+
specifier = node.arguments[0];
|
|
56655
|
+
}
|
|
56656
|
+
if (specifier && ts.isStringLiteralLike(specifier)) specifiers.push(specifier.text);
|
|
56657
|
+
ts.forEachChild(node, collectImports);
|
|
56658
|
+
};
|
|
56659
|
+
collectImports(parsed);
|
|
56660
|
+
for (const specifier of specifiers) {
|
|
56661
|
+
const target = specifier.startsWith(".") ? path.posix.join(path.posix.dirname(file.path), specifier) : specifier.startsWith("backend/") ? (file.path.startsWith("src/") ? "src/" : "") + specifier : "";
|
|
56662
|
+
const dependency = [
|
|
56663
|
+
target,
|
|
56664
|
+
target + ".js",
|
|
56665
|
+
target + ".ts",
|
|
56666
|
+
target + ".jsw",
|
|
56667
|
+
target + "/index.js",
|
|
56668
|
+
target + "/index.ts"
|
|
56669
|
+
].map((name) => byPath.get(name)).find(Boolean);
|
|
56670
|
+
if (dependency) dependencies.push(dependency);
|
|
56671
|
+
}
|
|
56672
|
+
queue.unshift(...dependencies);
|
|
56673
|
+
}
|
|
56674
|
+
return selected;
|
|
56675
|
+
}
|
|
56676
|
+
var MAX_FILES, MAX_FILE_CHARS, MAX_TOTAL_CHARS, REDACTED2, sensitiveName;
|
|
56677
|
+
var init_velo_source = __esm({
|
|
56678
|
+
"src/site-analyze/velo-source.ts"() {
|
|
56679
|
+
MAX_FILES = 6;
|
|
56680
|
+
MAX_FILE_CHARS = 8e3;
|
|
56681
|
+
MAX_TOTAL_CHARS = 24e3;
|
|
56682
|
+
REDACTED2 = "[REDACTED]";
|
|
56683
|
+
sensitiveName = /(?:secret|password|passwd|token|authorization|cookie|api[-_]?key|private[-_]?key|access[-_]?key|credential)/i;
|
|
56684
|
+
}
|
|
56685
|
+
});
|
|
56686
|
+
|
|
56687
|
+
// src/site-analyze/context.ts
|
|
56688
|
+
var context_exports = {};
|
|
56689
|
+
__export(context_exports, {
|
|
56690
|
+
collectSiteContext: () => collectSiteContext,
|
|
56691
|
+
contextFetch: () => contextFetch
|
|
56692
|
+
});
|
|
56693
|
+
function contextFetch(fetchImpl, signal) {
|
|
56694
|
+
return async (input, init) => {
|
|
56695
|
+
const url = new URL(String(input));
|
|
56696
|
+
const method = init?.method ?? "GET";
|
|
56697
|
+
const apiRead = url.origin === "https://www.wixapis.com" && reads.has(`${method} ${url.pathname}`);
|
|
56698
|
+
const veloRead = url.origin === new URL(VELO_IDE_ORIGIN).origin && method === "GET" && /^\/_api\/wix-code-ide-server-ng\/v1\/apps\/[\w-]+\/files$/.test(url.pathname) && ["ONLINE", "GITHUB"].includes(url.searchParams.get("layout") ?? "");
|
|
56699
|
+
if (!apiRead && !veloRead || url.username || url.password) throw new Error("Not a site-analysis read");
|
|
56700
|
+
if (url.pathname === "/oauth2/token" && JSON.parse(String(init?.body)).grantType !== "anonymous") {
|
|
56701
|
+
throw new Error("Only anonymous visitor authentication is allowed");
|
|
56702
|
+
}
|
|
56703
|
+
const response = await fetchImpl(input, { ...init, redirect: "error", signal });
|
|
56704
|
+
const reader = response.body?.getReader();
|
|
56705
|
+
if (!reader) return response;
|
|
56706
|
+
const chunks = [];
|
|
56707
|
+
let size = 0;
|
|
56708
|
+
for (; ; ) {
|
|
56709
|
+
const chunk = await reader.read();
|
|
56710
|
+
if (chunk.done) break;
|
|
56711
|
+
size += chunk.value.byteLength;
|
|
56712
|
+
if (size > 2e6) {
|
|
56713
|
+
await reader.cancel();
|
|
56714
|
+
throw new Error("Site-analysis response exceeds 2 MB");
|
|
56715
|
+
}
|
|
56716
|
+
chunks.push(chunk.value);
|
|
56717
|
+
}
|
|
56718
|
+
return new Response(Buffer.concat(chunks), { status: response.status, headers: response.headers });
|
|
56719
|
+
};
|
|
56720
|
+
}
|
|
56721
|
+
async function collectSiteContext(opts) {
|
|
56722
|
+
const fetcher = contextFetch(opts.fetchImpl ?? fetch, AbortSignal.timeout(opts.timeoutMs ?? 15e3));
|
|
56723
|
+
const owner = opts.ownerToken ? makeTransport(fetcher, { token: opts.ownerToken, msid: opts.siteId }) : void 0;
|
|
56724
|
+
let visitorToken;
|
|
56725
|
+
let visitorAuth = { status: "skipped" };
|
|
56726
|
+
if (opts.clientId) {
|
|
56727
|
+
try {
|
|
56728
|
+
visitorToken = await mintVisitorToken(fetcher, opts.clientId);
|
|
56729
|
+
visitorAuth = { status: "ok" };
|
|
56730
|
+
} catch (e) {
|
|
56731
|
+
visitorAuth = failed(e);
|
|
56732
|
+
}
|
|
56733
|
+
}
|
|
56734
|
+
const visitor = visitorToken ? makeTransport(fetcher, { token: visitorToken, msid: opts.siteId }) : void 0;
|
|
56735
|
+
const identityRead = async () => {
|
|
56736
|
+
if (!owner) return { status: "skipped" };
|
|
56737
|
+
try {
|
|
56738
|
+
const identity2 = parseSiteProperties(await owner("GET", "/site-properties/v4/properties"), "");
|
|
56739
|
+
return { status: "ok", values: {
|
|
56740
|
+
businessName: identity2.businessName,
|
|
56741
|
+
siteDisplayName: identity2.siteDisplayName,
|
|
56742
|
+
description: identity2.description,
|
|
56743
|
+
logo: identity2.logoUrl,
|
|
56744
|
+
language: identity2.locale.languageCode,
|
|
56745
|
+
currency: identity2.locale.currency
|
|
56746
|
+
} };
|
|
56747
|
+
} catch (e) {
|
|
56748
|
+
return failed(e);
|
|
56749
|
+
}
|
|
56750
|
+
};
|
|
56751
|
+
const cmsRead = async () => {
|
|
56752
|
+
try {
|
|
56753
|
+
let failure;
|
|
56754
|
+
const observed = owner ? async (method, path2, body) => {
|
|
56755
|
+
try {
|
|
56756
|
+
const data = await owner(method, path2, body);
|
|
56757
|
+
if (!Array.isArray(data?.collections)) throw new Error("Malformed CMS inventory");
|
|
56758
|
+
return data;
|
|
56759
|
+
} catch (e) {
|
|
56760
|
+
const code = e instanceof WixApiError2 ? e.body?.details?.applicationError?.code : void 0;
|
|
56761
|
+
failure = code === "WDE0110" ? { status: "unavailable", httpStatus: 400 } : failed(e);
|
|
56762
|
+
throw e;
|
|
56763
|
+
}
|
|
56764
|
+
} : void 0;
|
|
56765
|
+
const cms2 = await readCms(observed, { samples: false });
|
|
56766
|
+
return { ...cms2, ...failure, collections: cms2.collections.map((c) => ({
|
|
56767
|
+
id: c.id,
|
|
56768
|
+
readRole: c.readRole,
|
|
56769
|
+
visitorReadable: c.readRole === "ANYONE",
|
|
56770
|
+
ownership: "existing"
|
|
56771
|
+
})) };
|
|
56772
|
+
} catch {
|
|
56773
|
+
return { status: "error", collections: [] };
|
|
56774
|
+
}
|
|
56775
|
+
};
|
|
56776
|
+
const veloRead = async () => {
|
|
56777
|
+
if (!owner) return { status: "skipped", files: [], sourceIncluded: false };
|
|
56778
|
+
let readFailure;
|
|
56779
|
+
const observed = async (method, path2, body) => {
|
|
56780
|
+
try {
|
|
56781
|
+
return await owner(method, path2, body);
|
|
56782
|
+
} catch (e) {
|
|
56783
|
+
readFailure = failed(e);
|
|
56784
|
+
throw e;
|
|
56785
|
+
}
|
|
56786
|
+
};
|
|
56787
|
+
try {
|
|
56788
|
+
const velo2 = await readOwnerVelo(observed, { redact: (source) => redactVeloSource(source, [opts.ownerToken ?? "", visitorToken ?? ""]) });
|
|
56789
|
+
const files = velo2.files.flatMap((f) => {
|
|
56790
|
+
const normalized = backendSourcePath(f.path);
|
|
56791
|
+
return normalized ? [{ ...f, path: normalized }] : [];
|
|
56792
|
+
});
|
|
56793
|
+
const selected = selectVeloSource(
|
|
56794
|
+
files.map((f) => ({ path: f.path, content: f.content ?? "" })),
|
|
56795
|
+
opts.request ?? "",
|
|
56796
|
+
[opts.ownerToken ?? "", visitorToken ?? ""]
|
|
56797
|
+
);
|
|
56798
|
+
return {
|
|
56799
|
+
...files.length ? { status: "ok" } : readFailure ?? { status: "unavailable" },
|
|
56800
|
+
files: files.map((f) => ({
|
|
56801
|
+
path: f.path,
|
|
56802
|
+
kind: f.kind,
|
|
56803
|
+
exports: [...(f.content ?? "").matchAll(/export\s+(?:async\s+)?(?:function|const)\s+([A-Za-z_$][\w$]*)/g)].slice(0, 20).map((m) => m[1]),
|
|
56804
|
+
...selected.get(f.path)
|
|
56805
|
+
})),
|
|
56806
|
+
sourceIncluded: selected.size > 0,
|
|
56807
|
+
truncated: files.length > selected.size || [...selected.values()].some((f) => f.sourceTruncated)
|
|
56808
|
+
};
|
|
56809
|
+
} catch (e) {
|
|
56810
|
+
return { ...failed(e), files: [], sourceIncluded: false };
|
|
56811
|
+
}
|
|
56812
|
+
};
|
|
56813
|
+
const [identity, cms, velo, probes] = await Promise.all([
|
|
56814
|
+
identityRead(),
|
|
56815
|
+
cmsRead(),
|
|
56816
|
+
veloRead(),
|
|
56817
|
+
runDualProbes(owner, visitor, definitions)
|
|
56818
|
+
]);
|
|
56819
|
+
const probeRead = (p, available, auth) => {
|
|
56820
|
+
if (!available) return auth;
|
|
56821
|
+
if (p.httpStatus) return { ...failed(new WixApiError2(p.httpStatus, "", "", null)), count: p.count };
|
|
56822
|
+
return { status: p.status === "ok" || p.status === "empty" ? p.status : "error", count: p.count };
|
|
56823
|
+
};
|
|
56824
|
+
return {
|
|
56825
|
+
schemaVersion: 1,
|
|
56826
|
+
mode: "read-only",
|
|
56827
|
+
identity,
|
|
56828
|
+
cms,
|
|
56829
|
+
velo,
|
|
56830
|
+
verticals: probes.map((p) => ({
|
|
56831
|
+
name: p.vertical,
|
|
56832
|
+
owner: probeRead(p.owner, !!owner, { status: "skipped" }),
|
|
56833
|
+
visitor: probeRead(p.visitor, !!visitor, visitorAuth)
|
|
56834
|
+
}))
|
|
56835
|
+
};
|
|
56836
|
+
}
|
|
56837
|
+
var responseKeys, definitions, reads, failed;
|
|
56838
|
+
var init_context = __esm({
|
|
56839
|
+
"src/site-analyze/context.ts"() {
|
|
56840
|
+
init_probes();
|
|
56841
|
+
init_rest();
|
|
56842
|
+
init_site_properties();
|
|
56843
|
+
init_visitor_auth();
|
|
56844
|
+
init_velo();
|
|
56845
|
+
init_velo_source();
|
|
56846
|
+
responseKeys = {
|
|
56847
|
+
store: "products",
|
|
56848
|
+
bookings: "services",
|
|
56849
|
+
events: "events",
|
|
56850
|
+
blog: "posts"
|
|
56851
|
+
};
|
|
56852
|
+
definitions = [...CORE_PROBES, ...OPTIONAL_PROBES].filter((p) => p.vertical in responseKeys).map((p) => {
|
|
56853
|
+
const checked = (read, path2) => (data) => {
|
|
56854
|
+
const rows = path2 === "/catalog/v1/products/query" ? data.products ?? data.items : data[responseKeys[p.vertical]];
|
|
56855
|
+
if (!Array.isArray(rows)) throw new Error("Malformed catalog response");
|
|
56856
|
+
return read(data);
|
|
56857
|
+
};
|
|
56858
|
+
return {
|
|
56859
|
+
...p,
|
|
56860
|
+
itemsOf: checked(p.itemsOf, p.path),
|
|
56861
|
+
fallbacks: p.fallbacks?.map((f) => ({ ...f, itemsOf: checked(f.itemsOf ?? p.itemsOf, f.path) }))
|
|
56862
|
+
};
|
|
56863
|
+
});
|
|
56864
|
+
reads = /* @__PURE__ */ new Set([
|
|
56865
|
+
"POST /oauth2/token",
|
|
56866
|
+
"GET /site-properties/v4/properties",
|
|
56867
|
+
"GET /data/v2/collections",
|
|
56868
|
+
...OWNER_VELO_PROBES.map((p) => `${p.method} ${p.path}`),
|
|
56869
|
+
...definitions.flatMap((p) => [p, ...p.fallbacks ?? []].map((a) => `${a.method} ${a.path}`))
|
|
56870
|
+
]);
|
|
56871
|
+
failed = (e) => {
|
|
56872
|
+
const httpStatus = e instanceof WixApiError2 ? e.status : void 0;
|
|
56873
|
+
return { status: httpStatus === 401 ? "unauthorized" : httpStatus === 403 ? "forbidden" : httpStatus === 404 || httpStatus === 428 ? "unavailable" : "error", ...httpStatus ? { httpStatus } : {} };
|
|
56874
|
+
};
|
|
56875
|
+
}
|
|
56876
|
+
});
|
|
56877
|
+
|
|
56491
56878
|
// src/cli.ts
|
|
56492
56879
|
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync67, mkdirSync as mkdirSync27, writeFileSync as writeFileSync25, existsSync as existsSync56, rmSync as rmSync10, readdirSync as readdirSync25, statSync as statSync13, lstatSync as lstatSync6, accessSync, constants } from "node:fs";
|
|
56493
|
-
import { execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn5 } from "node:child_process";
|
|
56880
|
+
import { execFile as execFile4, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn5 } from "node:child_process";
|
|
56494
56881
|
import { createHash as createHash24, randomUUID as randomUUID3 } from "node:crypto";
|
|
56495
56882
|
import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
|
|
56496
56883
|
import { join as join52, resolve as resolve44, relative as relative8, basename as basename12, dirname as dirname31 } from "node:path";
|
|
@@ -56520,11 +56907,11 @@ var ServeCliClient = class {
|
|
|
56520
56907
|
if (!url) throw new Error(`no ${plane} URL configured for this target`);
|
|
56521
56908
|
return url.replace(/\/+$/, "");
|
|
56522
56909
|
}
|
|
56523
|
-
async request(plane, method,
|
|
56910
|
+
async request(plane, method, path2, opts = {}) {
|
|
56524
56911
|
const headers2 = { ...opts.headers };
|
|
56525
56912
|
if (opts.body !== void 0) headers2["content-type"] = "application/json";
|
|
56526
56913
|
const carriesCredential = Object.keys(headers2).some((h2) => CREDENTIAL_HEADERS.has(h2.toLowerCase()));
|
|
56527
|
-
const res = await this.fetchImpl(this.baseFor(plane) +
|
|
56914
|
+
const res = await this.fetchImpl(this.baseFor(plane) + path2, {
|
|
56528
56915
|
method,
|
|
56529
56916
|
headers: headers2,
|
|
56530
56917
|
...carriesCredential ? { redirect: "error" } : {},
|
|
@@ -56737,12 +57124,12 @@ var ServeCliClient = class {
|
|
|
56737
57124
|
if (o.since !== void 0) q.set("since", String(o.since));
|
|
56738
57125
|
if (o.limit) q.set("limit", String(o.limit));
|
|
56739
57126
|
if (o.crashesOnly) q.set("crashesOnly", "1");
|
|
56740
|
-
const
|
|
56741
|
-
return this.request("telemetry", "GET",
|
|
57127
|
+
const path2 = `/v1/telemetry/events?${q}`;
|
|
57128
|
+
return this.request("telemetry", "GET", path2, { headers: this.telHeaders() }).then(async (res) => {
|
|
56742
57129
|
if (res.status !== 404 || this.target.telemetry.replace(/\/+$/, "") === this.target.serve.replace(/\/+$/, "")) {
|
|
56743
57130
|
return res;
|
|
56744
57131
|
}
|
|
56745
|
-
return this.request("serve", "GET",
|
|
57132
|
+
return this.request("serve", "GET", path2, { headers: this.telHeaders() });
|
|
56746
57133
|
});
|
|
56747
57134
|
}
|
|
56748
57135
|
/** Retained worker console lines (oldest first; `since` = seq cursor for tailing). */
|
|
@@ -56752,12 +57139,12 @@ var ServeCliClient = class {
|
|
|
56752
57139
|
if (o.screenId) q.set("screen", o.screenId);
|
|
56753
57140
|
if (o.since !== void 0) q.set("since", String(o.since));
|
|
56754
57141
|
if (o.limit) q.set("limit", String(o.limit));
|
|
56755
|
-
const
|
|
56756
|
-
return this.request("telemetry", "GET",
|
|
57142
|
+
const path2 = `/v1/telemetry/logs?${q}`;
|
|
57143
|
+
return this.request("telemetry", "GET", path2, { headers: this.telHeaders() }).then(async (res) => {
|
|
56757
57144
|
if (res.status !== 404 || this.target.telemetry.replace(/\/+$/, "") === this.target.serve.replace(/\/+$/, "")) {
|
|
56758
57145
|
return res;
|
|
56759
57146
|
}
|
|
56760
|
-
return this.request("serve", "GET",
|
|
57147
|
+
return this.request("serve", "GET", path2, { headers: this.telHeaders() });
|
|
56761
57148
|
});
|
|
56762
57149
|
}
|
|
56763
57150
|
// ---- serve-control (publish / rollout / kill-switch — the mutable plane) ----
|
|
@@ -56815,8 +57202,8 @@ var ServeCliClient = class {
|
|
|
56815
57202
|
}
|
|
56816
57203
|
/** RFC 0012 release history: list the ledger (GET /v1/releases) or one manifest (…/{releaseId}). */
|
|
56817
57204
|
releases(app, releaseId) {
|
|
56818
|
-
const
|
|
56819
|
-
return this.request("control", "GET",
|
|
57205
|
+
const path2 = releaseId ? `/v1/releases/${encodeURIComponent(releaseId)}?app=${encodeURIComponent(app)}` : `/v1/releases?app=${encodeURIComponent(app)}`;
|
|
57206
|
+
return this.request("control", "GET", path2, { headers: this.ctrlHeaders() });
|
|
56820
57207
|
}
|
|
56821
57208
|
/** Select a published releaseId for a ring (POST /v1/admin/promote); optional rollout %. */
|
|
56822
57209
|
promote(app, ring, releaseId, percent, force = false) {
|
|
@@ -57173,8 +57560,8 @@ var VALIDATION_METADATA = /* @__PURE__ */ new Set([
|
|
|
57173
57560
|
".claude/.validation-baseline.json",
|
|
57174
57561
|
".claude/.validation-evidence.json"
|
|
57175
57562
|
]);
|
|
57176
|
-
function isValidationMetadata(
|
|
57177
|
-
return VALIDATION_METADATA.has(
|
|
57563
|
+
function isValidationMetadata(path2) {
|
|
57564
|
+
return VALIDATION_METADATA.has(path2) || /(^|[\\/])\.himi([\\/]|$)/.test(path2);
|
|
57178
57565
|
}
|
|
57179
57566
|
function tryGit(args, root) {
|
|
57180
57567
|
try {
|
|
@@ -57190,10 +57577,10 @@ function committedRecords(raw) {
|
|
|
57190
57577
|
const records = [];
|
|
57191
57578
|
for (let i = 0; i < fields.length; i += 2) {
|
|
57192
57579
|
const metadata2 = fields[i];
|
|
57193
|
-
const
|
|
57194
|
-
if (!metadata2.startsWith(":") ||
|
|
57195
|
-
if (isValidationMetadata(
|
|
57196
|
-
records.push(`${Buffer.byteLength(
|
|
57580
|
+
const path2 = fields[i + 1];
|
|
57581
|
+
if (!metadata2.startsWith(":") || path2 === "") return null;
|
|
57582
|
+
if (isValidationMetadata(path2)) continue;
|
|
57583
|
+
records.push(`${Buffer.byteLength(path2)}:${path2}\0${metadata2}\0`);
|
|
57197
57584
|
}
|
|
57198
57585
|
return records.sort().join("");
|
|
57199
57586
|
}
|
|
@@ -57253,12 +57640,12 @@ function validationDiffHash(cwd = process.cwd()) {
|
|
|
57253
57640
|
trustFilesystemMode = git(["config", "--bool", "--get", "core.fileMode"], { cwd: root }).trim() !== "false";
|
|
57254
57641
|
} catch {
|
|
57255
57642
|
}
|
|
57256
|
-
const paths = [.../* @__PURE__ */ new Set([...staged, ...unstaged, ...untracked])].filter((
|
|
57257
|
-
const identity = paths.map((
|
|
57258
|
-
const absolute = resolve5(root,
|
|
57259
|
-
const headEntry = headEntries.get(
|
|
57260
|
-
const indexEntry = indexEntries.get(
|
|
57261
|
-
const deletedRecord = () => [`${Buffer.byteLength(
|
|
57643
|
+
const paths = [.../* @__PURE__ */ new Set([...staged, ...unstaged, ...untracked])].filter((path2) => !isValidationMetadata(path2)).sort();
|
|
57644
|
+
const identity = paths.map((path2) => {
|
|
57645
|
+
const absolute = resolve5(root, path2);
|
|
57646
|
+
const headEntry = headEntries.get(path2);
|
|
57647
|
+
const indexEntry = indexEntries.get(path2);
|
|
57648
|
+
const deletedRecord = () => [`${Buffer.byteLength(path2)}:${path2}`, "deleted", stagedIdentity(headEntry, indexEntry, void 0), ""].join("\0");
|
|
57262
57649
|
let stat2;
|
|
57263
57650
|
try {
|
|
57264
57651
|
stat2 = lstatSync2(absolute);
|
|
@@ -57272,7 +57659,7 @@ function validationDiffHash(cwd = process.cwd()) {
|
|
|
57272
57659
|
const worktreeEntry = { mode: "120000", oid: blobOid(target, objectAlgorithm) };
|
|
57273
57660
|
const stagedState2 = stagedIdentity(headEntry, indexEntry, worktreeEntry);
|
|
57274
57661
|
return [
|
|
57275
|
-
`${Buffer.byteLength(
|
|
57662
|
+
`${Buffer.byteLength(path2)}:${path2}`,
|
|
57276
57663
|
"symlink",
|
|
57277
57664
|
"120000",
|
|
57278
57665
|
diffHash(target),
|
|
@@ -57283,11 +57670,11 @@ function validationDiffHash(cwd = process.cwd()) {
|
|
|
57283
57670
|
if (stat2.isFile()) {
|
|
57284
57671
|
const filesystemMode = stat2.mode & 73 ? "100755" : "100644";
|
|
57285
57672
|
const worktreeMode = trustFilesystemMode ? filesystemMode : indexEntry?.mode ?? headEntry?.mode ?? "100644";
|
|
57286
|
-
const worktreeOid = git(["hash-object", `--path=${
|
|
57673
|
+
const worktreeOid = git(["hash-object", `--path=${path2}`, "--", path2], { cwd: root }).trim();
|
|
57287
57674
|
const worktreeEntry = { mode: worktreeMode, oid: worktreeOid };
|
|
57288
57675
|
const stagedState2 = stagedIdentity(headEntry, indexEntry, worktreeEntry);
|
|
57289
57676
|
return [
|
|
57290
|
-
`${Buffer.byteLength(
|
|
57677
|
+
`${Buffer.byteLength(path2)}:${path2}`,
|
|
57291
57678
|
"file",
|
|
57292
57679
|
worktreeMode,
|
|
57293
57680
|
diffHash(readFileSync4(absolute)),
|
|
@@ -57306,7 +57693,7 @@ function validationDiffHash(cwd = process.cwd()) {
|
|
|
57306
57693
|
const type = stat2.isDirectory() ? "directory" : "other";
|
|
57307
57694
|
const stagedState = stagedIdentity(headEntry, indexEntry, void 0);
|
|
57308
57695
|
return [
|
|
57309
|
-
`${Buffer.byteLength(
|
|
57696
|
+
`${Buffer.byteLength(path2)}:${path2}`,
|
|
57310
57697
|
type,
|
|
57311
57698
|
stat2.mode.toString(8),
|
|
57312
57699
|
stagedState,
|
|
@@ -57413,7 +57800,7 @@ var SELF_TEST_CASES = [
|
|
|
57413
57800
|
}
|
|
57414
57801
|
];
|
|
57415
57802
|
function runSelfTest() {
|
|
57416
|
-
let
|
|
57803
|
+
let failed2 = 0;
|
|
57417
57804
|
for (const testCase of SELF_TEST_CASES) {
|
|
57418
57805
|
let ok = false;
|
|
57419
57806
|
let thrown = null;
|
|
@@ -57427,20 +57814,20 @@ function runSelfTest() {
|
|
|
57427
57814
|
`);
|
|
57428
57815
|
continue;
|
|
57429
57816
|
}
|
|
57430
|
-
|
|
57817
|
+
failed2++;
|
|
57431
57818
|
process.stderr.write(` \u2717 ${testCase.name}
|
|
57432
57819
|
${thrown ?? testCase.reason}
|
|
57433
57820
|
`);
|
|
57434
57821
|
}
|
|
57435
|
-
return
|
|
57822
|
+
return failed2;
|
|
57436
57823
|
}
|
|
57437
57824
|
if (process.argv[1] && basename(process.argv[1]) === "diff-hash.mjs" && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
57438
57825
|
if (process.argv.slice(2).includes("--self-test")) {
|
|
57439
57826
|
process.stdout.write("\u25B8 diff-hash --self-test: proving the identity can change, and can hold\n");
|
|
57440
|
-
const
|
|
57441
|
-
if (
|
|
57827
|
+
const failed2 = runSelfTest();
|
|
57828
|
+
if (failed2) {
|
|
57442
57829
|
process.stderr.write(
|
|
57443
|
-
`\u2717 diff-hash self-test FAILED (${
|
|
57830
|
+
`\u2717 diff-hash self-test FAILED (${failed2} case(s)) \u2014 the evidence record's diff identity cannot be trusted
|
|
57444
57831
|
`
|
|
57445
57832
|
);
|
|
57446
57833
|
process.exit(1);
|
|
@@ -57533,16 +57920,16 @@ function currentGitUntrackedHash(contentDir2) {
|
|
|
57533
57920
|
maxBuffer: GIT_HASH_MAX_BUFFER
|
|
57534
57921
|
});
|
|
57535
57922
|
const hash = createHash3("sha256");
|
|
57536
|
-
for (const
|
|
57537
|
-
const local = relative(absolute, join6(root,
|
|
57923
|
+
for (const path2 of listed.split("\0").filter(Boolean).sort()) {
|
|
57924
|
+
const local = relative(absolute, join6(root, path2));
|
|
57538
57925
|
if (local.split(/[\\/]/)[0] === ".himi") continue;
|
|
57539
|
-
const full = join6(root,
|
|
57926
|
+
const full = join6(root, path2);
|
|
57540
57927
|
const stats = lstatSync3(full, { throwIfNoEntry: false });
|
|
57541
57928
|
if (!stats) continue;
|
|
57542
57929
|
const kind = stats.isSymbolicLink() ? "link" : stats.isDirectory() ? "dir" : stats.isFile() ? "file" : null;
|
|
57543
57930
|
if (!kind) continue;
|
|
57544
57931
|
const payload = kind === "link" ? Buffer.from(readlinkSync2(full)) : kind === "file" ? readFileSync5(full) : Buffer.alloc(0);
|
|
57545
|
-
const pathBytes = Buffer.from(
|
|
57932
|
+
const pathBytes = Buffer.from(path2);
|
|
57546
57933
|
hash.update(`${kind} ${pathBytes.length} ${payload.length}
|
|
57547
57934
|
`).update(pathBytes).update(payload);
|
|
57548
57935
|
}
|
|
@@ -57553,11 +57940,11 @@ function sourceTreeHash(root) {
|
|
|
57553
57940
|
const visit = (dir) => {
|
|
57554
57941
|
for (const entry of readdirSync3(dir, { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
|
|
57555
57942
|
if (entry.isDirectory() && [".git", ".himi", "node_modules"].includes(entry.name)) continue;
|
|
57556
|
-
const
|
|
57557
|
-
const local = relative(root,
|
|
57558
|
-
if (entry.isDirectory()) visit(
|
|
57559
|
-
else if (entry.isFile()) hash.update(local).update("\0").update(readFileSync5(
|
|
57560
|
-
else if (entry.isSymbolicLink()) hash.update(local).update("\0link\0").update(readlinkSync2(
|
|
57943
|
+
const path2 = join6(dir, entry.name);
|
|
57944
|
+
const local = relative(root, path2);
|
|
57945
|
+
if (entry.isDirectory()) visit(path2);
|
|
57946
|
+
else if (entry.isFile()) hash.update(local).update("\0").update(readFileSync5(path2)).update("\0");
|
|
57947
|
+
else if (entry.isSymbolicLink()) hash.update(local).update("\0link\0").update(readlinkSync2(path2)).update("\0");
|
|
57561
57948
|
}
|
|
57562
57949
|
};
|
|
57563
57950
|
visit(root);
|
|
@@ -57605,9 +57992,9 @@ function readRetainedAttestations(contentDir2) {
|
|
|
57605
57992
|
for (const run2 of parsedRuns) {
|
|
57606
57993
|
if (selfHashFor(run2) !== run2.selfHash) errors.push(`selfHash does not match retained run ${run2.runId}`);
|
|
57607
57994
|
for (const expected of Object.values(run2.screenshots)) {
|
|
57608
|
-
const
|
|
57609
|
-
if (!existsSync3(
|
|
57610
|
-
else if (sha256(readFileSync5(
|
|
57995
|
+
const path2 = screenshotArtifactPath(contentDir2, expected);
|
|
57996
|
+
if (!existsSync3(path2)) errors.push(`missing screenshot for retained run ${run2.runId}: ${basename2(path2)}`);
|
|
57997
|
+
else if (sha256(readFileSync5(path2)) !== expected) errors.push(`screenshot hash does not match retained run ${run2.runId}: ${basename2(path2)}`);
|
|
57611
57998
|
}
|
|
57612
57999
|
}
|
|
57613
58000
|
const runs = [];
|
|
@@ -57668,8 +58055,8 @@ function writeAttestation(input, opts = {}) {
|
|
|
57668
58055
|
const descriptorHashes = Object.fromEntries(
|
|
57669
58056
|
Object.entries(input.descriptors).sort(([a], [b]) => a.localeCompare(b)).map(([screen, bytes2]) => [screen, sha256(bytes2)])
|
|
57670
58057
|
);
|
|
57671
|
-
const screenshotEntries = Object.entries(input.screenshots ?? {}).sort(([a], [b]) => a.localeCompare(b)).filter(([,
|
|
57672
|
-
const bytes2 = readFileSync5(
|
|
58058
|
+
const screenshotEntries = Object.entries(input.screenshots ?? {}).sort(([a], [b]) => a.localeCompare(b)).filter(([, path2]) => existsSync3(path2)).map(([screen, path2]) => {
|
|
58059
|
+
const bytes2 = readFileSync5(path2);
|
|
57673
58060
|
return { screen, bytes: bytes2, hash: sha256(bytes2) };
|
|
57674
58061
|
});
|
|
57675
58062
|
const screenshots = Object.fromEntries(screenshotEntries.map(({ screen, hash }) => [screen, hash]));
|
|
@@ -57796,12 +58183,12 @@ function verifyAttestation(attestation, contentDir2, descriptors, expectedApp, r
|
|
|
57796
58183
|
if (sha256(bytes2) !== expected) errors.push(`descriptor hash does not match for ${screen}`);
|
|
57797
58184
|
}
|
|
57798
58185
|
for (const [screen, expected] of Object.entries(attestation.screenshots)) {
|
|
57799
|
-
const
|
|
57800
|
-
if (!existsSync3(
|
|
57801
|
-
errors.push(`missing screenshot for ${screen}: ${basename2(
|
|
58186
|
+
const path2 = screenshotArtifactPath(contentDir2, expected);
|
|
58187
|
+
if (!existsSync3(path2)) {
|
|
58188
|
+
errors.push(`missing screenshot for ${screen}: ${basename2(path2)}`);
|
|
57802
58189
|
continue;
|
|
57803
58190
|
}
|
|
57804
|
-
if (sha256(readFileSync5(
|
|
58191
|
+
if (sha256(readFileSync5(path2)) !== expected) errors.push(`screenshot hash does not match for ${screen}: ${basename2(path2)}`);
|
|
57805
58192
|
}
|
|
57806
58193
|
return { ok: errors.length === 0, errors };
|
|
57807
58194
|
}
|
|
@@ -58128,9 +58515,9 @@ function dpxSessionTokenPath() {
|
|
|
58128
58515
|
return process.env.HIMI_DPX_TOKEN ?? join7(homedir2(), ".dpx", "session", "token");
|
|
58129
58516
|
}
|
|
58130
58517
|
var DPX_SESSION_PORT = 5151;
|
|
58131
|
-
function dpxSessionPresent(
|
|
58518
|
+
function dpxSessionPresent(path2 = dpxSessionTokenPath()) {
|
|
58132
58519
|
try {
|
|
58133
|
-
return existsSync4(
|
|
58520
|
+
return existsSync4(path2) && readFileSync6(path2, "utf8").trim().length > 0;
|
|
58134
58521
|
} catch {
|
|
58135
58522
|
return false;
|
|
58136
58523
|
}
|
|
@@ -58309,10 +58696,10 @@ async function listCollections(call) {
|
|
|
58309
58696
|
let total;
|
|
58310
58697
|
let reachedEnd = false;
|
|
58311
58698
|
for (let page = 0; page < MAX_COLLECTION_PAGES; page++) {
|
|
58312
|
-
const
|
|
58699
|
+
const path2 = offset ? `/data/v2/collections?paging.offset=${offset}` : "/data/v2/collections";
|
|
58313
58700
|
const r = await withRetry(
|
|
58314
58701
|
"list collections",
|
|
58315
|
-
() => call("GET",
|
|
58702
|
+
() => call("GET", path2)
|
|
58316
58703
|
);
|
|
58317
58704
|
const batch = r.collections ?? [];
|
|
58318
58705
|
const t = r.pagingMetadata?.total;
|
|
@@ -59302,9 +59689,9 @@ function storesV1Issues(contentDir2, strict) {
|
|
|
59302
59689
|
const files = [];
|
|
59303
59690
|
const visit = (dir) => {
|
|
59304
59691
|
for (const entry of readdirSync10(dir, { withFileTypes: true })) {
|
|
59305
|
-
const
|
|
59306
|
-
if (entry.isDirectory()) visit(
|
|
59307
|
-
else if (/\.(?:[cm]?[jt]sx?)$/i.test(entry.name)) files.push(
|
|
59692
|
+
const path2 = join23(dir, entry.name);
|
|
59693
|
+
if (entry.isDirectory()) visit(path2);
|
|
59694
|
+
else if (/\.(?:[cm]?[jt]sx?)$/i.test(entry.name)) files.push(path2);
|
|
59308
59695
|
}
|
|
59309
59696
|
};
|
|
59310
59697
|
roots.forEach(visit);
|
|
@@ -59328,12 +59715,12 @@ import { existsSync as existsSync22, readFileSync as readFileSync22, readdirSync
|
|
|
59328
59715
|
import { join as join25, relative as relative4, resolve as resolve16 } from "node:path";
|
|
59329
59716
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".json"]);
|
|
59330
59717
|
var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".himi", "coverage"]);
|
|
59331
|
-
function issue(issues, strict, code, message,
|
|
59332
|
-
issues.push({ code, message, ...
|
|
59718
|
+
function issue(issues, strict, code, message, path2) {
|
|
59719
|
+
issues.push({ code, message, ...path2 ? { path: path2 } : {}, severity: strict ? "error" : "warning" });
|
|
59333
59720
|
}
|
|
59334
|
-
function readText2(
|
|
59721
|
+
function readText2(path2) {
|
|
59335
59722
|
try {
|
|
59336
|
-
return existsSync22(
|
|
59723
|
+
return existsSync22(path2) ? readFileSync22(path2, "utf8") : null;
|
|
59337
59724
|
} catch {
|
|
59338
59725
|
return null;
|
|
59339
59726
|
}
|
|
@@ -59643,6 +60030,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
59643
60030
|
"json",
|
|
59644
60031
|
"deep",
|
|
59645
60032
|
"quiet",
|
|
60033
|
+
"read-only",
|
|
59646
60034
|
"force",
|
|
59647
60035
|
"replace",
|
|
59648
60036
|
"watch",
|
|
@@ -59770,10 +60158,10 @@ var str5 = (v) => typeof v === "string" ? v : void 0;
|
|
|
59770
60158
|
var num = (v) => typeof v === "string" && v !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
59771
60159
|
function embeddedTemplateCatalog() {
|
|
59772
60160
|
return availableTemplates().map((name) => {
|
|
59773
|
-
const
|
|
59774
|
-
const meta = JSON.parse(readFileSync67(
|
|
60161
|
+
const path2 = join52(templateSourceDir(name), TEMPLATE_META_FILE);
|
|
60162
|
+
const meta = JSON.parse(readFileSync67(path2, "utf8"));
|
|
59775
60163
|
if (!meta || typeof meta.title !== "string" || typeof meta.description !== "string" || !Array.isArray(meta.tags)) {
|
|
59776
|
-
throw new Error(`${
|
|
60164
|
+
throw new Error(`${path2} must be { title: string, description: string, tags: string[], category?: string }`);
|
|
59777
60165
|
}
|
|
59778
60166
|
return { name, ...meta, source: "embedded" };
|
|
59779
60167
|
});
|
|
@@ -60260,6 +60648,7 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
60260
60648
|
also requires a MOBILE applicationType, because ensure
|
|
60261
60649
|
refuses a WEB client \u2014 so a WEB one carrying your
|
|
60262
60650
|
redirect looks right and is not a candidate.
|
|
60651
|
+
himi site analyze --read-only --site <msid> [--client-id <id>] [--json]
|
|
60263
60652
|
himi site analyze --client-id <id> --url <https://\u2026> [--site <msid>] [--out <dir>] [--apply]
|
|
60264
60653
|
[--shell ${SHELL_ENUM}]
|
|
60265
60654
|
collect a Wix business book (APIs + Playwright look) and
|
|
@@ -60373,7 +60762,7 @@ var COMMANDS = [
|
|
|
60373
60762
|
{ name: "login", summary: "obtain a scoped serve-control token from Wix identity and store it in ~/.himalaya/serve-targets.json (so push/promote need no hand-pasted token). Three modes: --browser (your own Wix account, no VPN/BO), --wix (HEADLESS \u2014 the machine's own Wix CLI credential; the mode a CI pod or agent container can satisfy), --dpx (Wix employee, reads ~/.dpx/session/token). RFC 0026 WS3.", required: "[--browser|--wix|--dpx] [--target <t>] [--issue-url <url>]" },
|
|
60374
60763
|
{ name: "logout", summary: "remove the stored control token for a target", required: "[--target <t>]" },
|
|
60375
60764
|
{ name: "notify", summary: "`setup` optionally configures Branded/Ping from local customer key files; `status --refresh` reads live backend readiness. Setup may be deferred while building. These use serve-control and require owner plus Wix account authentication. `send`, `tokens`, `doctor`: send a REAL push notification to registered devices (RFC 0036 WS5) \u2014 APNs .p8 over HTTP/2 for iOS, FCM v1 for Android. `send` targets one device (--token / --device <registry id>) or fans out to the whole app (--all), reporting a per-device result; a token the provider says is uninstalled (APNs 410 Unregistered / FCM UNREGISTERED) is auto-disabled, while a merely wrong one (BadDeviceToken \u2014 usually a sandbox/production mismatch) is recorded and left enabled. `tokens` lists the registry. `doctor` reports which credentials resolve and which sender each platform picks. Talks to the admin-server via --admin-url/HIMALAYA_ADMIN_URL, authenticated with --admin-session/HIMALAYA_ADMIN_SESSION. NOT `himi push`, which publishes a release.", required: "setup|status [--content <dir>] [--target <t>] [--refresh] [--yes] [--no-push-setup] | send|tokens|doctor [--app <a>] [--token <t> | --device <id> | --all] [--title <s>] [--body <s>] [--link <url>] [--platform ios|android] [--badge <n>] [--channel <id>] [--silent] [--dry-run] [--json]" },
|
|
60376
|
-
{ name: "site", summary: "PROVISION a Wix project, then analyze or extend it. `create` is the one door that makes a site instead of adopting one: POST /funnel/projects/v1/create (a WIX site, a HEADLESS backend, a BRANDED_APP, or a VIBE site), and for headless it also mints the OAuth app whose id IS the `WIX_CLIENT_ID` \u2014 with --redirect-uri already registered, because an unregistered redirect makes native signInDirect fail at redirect-session. `--verticals` REQUIRES `--template` and reports only what Wix confirmed: measured, installing onto a project created from the BLANK template returns 200 while the vertical's API answers 428 forever, because there is no site for it to attach to (the install asks for CREATE_SITE). A real template ships its verticals installed and populated, and installing further ones onto it then works. It MUTATES your Wix account and needs --yes; without it you get the payload and nothing is sent. `list` is the read-only site inventory (with each site's premium flag, which is what explains an installed-but-428 vertical). Auth is the account-scoped `wix token` (no --site), falling back to WIX_API_KEY + WIX_ACCOUNT_ID. `client` is the same OAuth step for a site that ALREADY exists \u2014 the one himi adopts rather than makes \u2014 so a clientId no longer means a manual trip to the dashboard: `client ensure` reconciles rather than mints, because a site can already carry a client with NO registered redirect and shipping that one fails signInDirect at runtime; it reuses a client that carries --redirect-uri, PATCHes one that matches --name but lacks it (unioning, so another app's redirect survives), and creates only when there is nothing to reuse (--new forces a fresh one). --name IS the idempotency key. `client` auth is SITE-scoped (`wix token --site <msid>`) because minting is owner-of-that-site, and --yes gates every mutation: a site that already has a usable client resolves WITHOUT it, but --write-provisioning needs --yes even then because it rewrites a manifest on disk (the dry run's planned.provisioning names the file). That query endpoint IGNORES paging (measured: query.paging, cursorPaging and a top-level paging all return the full set at offset 0), so when pagingMetadata reports more clients than came back, `ensure` REFUSES EVERY outcome \u2014 create, patch AND reuse. Reuse is refused too because pickClient breaks ties on the OLDEST createdDate, so an omitted older same-named MOBILE client with the same redirect would win a later complete read and the resolved clientId would MOVE between runs \u2014 and it gets written into provisioning.json; convergence is what makes a stray duplicate untidy rather than harmful. --name cannot narrow the query (no filter is sent; the name is applied to the rows after they arrive), so the recovery is the dashboard; --new skips the query entirely. A `patched` result is verified against what Wix STORED \u2014 the redirect list is read off the PATCH response, and re-read via GET when the response omits it, because falling back to the list himi just sent would make the guard pass vacuously on exactly the silent no-op it exists to catch. `client list` is the read-only inventory of a site's clients: act on its `shippable` column rather than `hasRedirect`, because shippable ALSO requires a MOBILE applicationType and `ensure` refuses a WEB client \u2014 a WEB one carrying your redirect looks right and is not a candidate \u2014 and it sets truncated:true rather than presenting a partial inventory as the whole one. `analyze` reads a site into a business-book folder (REST + Playwright, GET-only); `site function` list/get/put/publish/invokes that site's Velo HTTP functions and is not `himi functions` (serve-plane jobs). `--apply` bakes into a brandable shell; `--shell` takes the same names `himi dist --shell` does and defaults to branded-lite, and a shell that ships no prepare:customer is refused by name rather than half-built. It never overwrites any shell's committed apps/<shell>/provisioning.json.", required: "create <name> [--type wix|headless|branded-app|vibe] [--template <guid>] [--verticals stores,bookings,\u2026] [--folder <guid>] [--redirect-uri <uri>] [--no-oauth-app] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | list | client ensure|list --site <msid> [--name <name>] [--redirect-uri <uri>] [--new] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | analyze --client-id <id> --url <https> [--site <msid>] [--out <dir>] [--redirect-uri <uri>] [--apply] [--shell " + SHELL_ENUM + "] | function list|get|put|publish|invoke [--site <msid>] [--url <https>] [--method GET|POST|PUT|DELETE] [--source <file>] [--body <json>] [--publish] [--invoke]" },
|
|
60765
|
+
{ name: "site", summary: "PROVISION a Wix project, then analyze or extend it. `create` is the one door that makes a site instead of adopting one: POST /funnel/projects/v1/create (a WIX site, a HEADLESS backend, a BRANDED_APP, or a VIBE site), and for headless it also mints the OAuth app whose id IS the `WIX_CLIENT_ID` \u2014 with --redirect-uri already registered, because an unregistered redirect makes native signInDirect fail at redirect-session. `--verticals` REQUIRES `--template` and reports only what Wix confirmed: measured, installing onto a project created from the BLANK template returns 200 while the vertical's API answers 428 forever, because there is no site for it to attach to (the install asks for CREATE_SITE). A real template ships its verticals installed and populated, and installing further ones onto it then works. It MUTATES your Wix account and needs --yes; without it you get the payload and nothing is sent. `list` is the read-only site inventory (with each site's premium flag, which is what explains an installed-but-428 vertical). Auth is the account-scoped `wix token` (no --site), falling back to WIX_API_KEY + WIX_ACCOUNT_ID. `client` is the same OAuth step for a site that ALREADY exists \u2014 the one himi adopts rather than makes \u2014 so a clientId no longer means a manual trip to the dashboard: `client ensure` reconciles rather than mints, because a site can already carry a client with NO registered redirect and shipping that one fails signInDirect at runtime; it reuses a client that carries --redirect-uri, PATCHes one that matches --name but lacks it (unioning, so another app's redirect survives), and creates only when there is nothing to reuse (--new forces a fresh one). --name IS the idempotency key. `client` auth is SITE-scoped (`wix token --site <msid>`) because minting is owner-of-that-site, and --yes gates every mutation: a site that already has a usable client resolves WITHOUT it, but --write-provisioning needs --yes even then because it rewrites a manifest on disk (the dry run's planned.provisioning names the file). That query endpoint IGNORES paging (measured: query.paging, cursorPaging and a top-level paging all return the full set at offset 0), so when pagingMetadata reports more clients than came back, `ensure` REFUSES EVERY outcome \u2014 create, patch AND reuse. Reuse is refused too because pickClient breaks ties on the OLDEST createdDate, so an omitted older same-named MOBILE client with the same redirect would win a later complete read and the resolved clientId would MOVE between runs \u2014 and it gets written into provisioning.json; convergence is what makes a stray duplicate untidy rather than harmful. --name cannot narrow the query (no filter is sent; the name is applied to the rows after they arrive), so the recovery is the dashboard; --new skips the query entirely. A `patched` result is verified against what Wix STORED \u2014 the redirect list is read off the PATCH response, and re-read via GET when the response omits it, because falling back to the list himi just sent would make the guard pass vacuously on exactly the silent no-op it exists to catch. `client list` is the read-only inventory of a site's clients: act on its `shippable` column rather than `hasRedirect`, because shippable ALSO requires a MOBILE applicationType and `ensure` refuses a WEB client \u2014 a WEB one carrying your redirect looks right and is not a candidate \u2014 and it sets truncated:true rather than presenting a partial inventory as the whole one. `analyze --read-only` returns API-only generation context as JSON (identity, access probes, CMS permissions and selected redacted Velo source); it needs no URL/browser and never uploads or applies anything. `analyze` reads a site into a business-book folder (REST + Playwright, GET-only); `site function` list/get/put/publish/invokes that site's Velo HTTP functions and is not `himi functions` (serve-plane jobs). `--apply` bakes into a brandable shell; `--shell` takes the same names `himi dist --shell` does and defaults to branded-lite, and a shell that ships no prepare:customer is refused by name rather than half-built. It never overwrites any shell's committed apps/<shell>/provisioning.json.", required: "create <name> [--type wix|headless|branded-app|vibe] [--template <guid>] [--verticals stores,bookings,\u2026] [--folder <guid>] [--redirect-uri <uri>] [--no-oauth-app] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | list | client ensure|list --site <msid> [--name <name>] [--redirect-uri <uri>] [--new] [--write-provisioning [path]] [--site-url <url>] [--json] --yes | analyze --read-only [--site <msid>] [--client-id <id>] [--json] | analyze --client-id <id> --url <https> [--site <msid>] [--out <dir>] [--redirect-uri <uri>] [--apply] [--shell " + SHELL_ENUM + "] | function list|get|put|publish|invoke [--site <msid>] [--url <https>] [--method GET|POST|PUT|DELETE] [--source <file>] [--body <json>] [--publish] [--invoke]" },
|
|
60377
60766
|
{ name: "doctor", summary: 'off-VPN preflight in one shot: probe the PUBLIC data plane (www.wixapis.com \u2014 reachable off-VPN), the INTERNAL serve/control plane for the selected target (VPN-gated), and report auth state (dpx session on disk + stored control token). --dpx additionally runs a live, EADDRINUSE-safe `dpx whoami`. Machine-readable with --json (an unreachable internal plane carries a stable code:"needs_vpn" so an agent branches on the code, not the prose); human-readable otherwise. Never loads the authoring runtime \u2014 works off-repo.', required: "[--target <t>] [--dpx] [--json] [--data-url <url>] [--timeout <ms>]" },
|
|
60378
60767
|
{ name: "upgrade", summary: "install the newest published CLI (`npm i -g @wix/himalaya-cli@latest`) and report what moved. This is the explicit door: himi also updates itself when the running build is more than a week old \u2014 unattended it just does it and re-runs your command, at a terminal it asks first \u2014 and `HIMI_NO_UPDATE_CHECK=1` turns that off, leaving this command as the way to catch up. Reports `unchanged` rather than claiming success when npm exits 0 without moving the version, which is what a registry mirror serving its own pinned copy looks like.", required: "[--json]" },
|
|
60379
60768
|
{ name: "push", summary: "lint + build + publish a release (default --draft: servable via ?release= but NOT live). REFUSES to publish on any error unless --force; --strict promotes warnings. Prints preview + agent-context links. The published slug is NAMESPACED per owner \u2014 `<ownerPrefix>.<name>`, composed offline from the control token's ownerPrefix claim, so the CLI and the server derive the identical string and himalaya.content.json is NOT rewritten (a legacy token with no ownerPrefix publishes the declared name unchanged). An app claimed BEFORE namespacing is stored under its FLAT slug, so the claim route answers `alreadyYours` naming that slug and the push adopts it \u2014 reported as `adoptedSlug`, since it is the one case where the published `app` differs from what the declared name composes to. `--no-claim` skips the route that knows this, so a pre-namespacing app pushed with it still fails 403. --visibility public|unlisted decides whether /v1/apps + the Himi Player picker LIST the app (also declarable as `visibility` in himalaya.content.json; omitted, a brand-new app defaults to unlisted \u2014 share by link \u2014 and an existing setting is kept). --account-id names which account owns the app when your Wix session resolves to several (the auto-claim of a brand-new slug cannot guess \u2014 without it a multi-account caller is told to name one). An unforced push of a release that carries SCREENS also refuses when `.himi/ux-audit.json` holds no mobile-UX drive recorded against that release id, or holds one that FAILED (#2955) \u2014 a published draft IS the owner-private preview a customer is handed; `himi ux record` clears it and `--force` overrides it, which the success envelope then says out loud. `--only <selector>` publishes ONLY the named items as a release derived from the app's live release (or `--from-release <id>`), running the identical build + lint gate and simply publishing less; it requires an explicit `--draft` or `--live` because a partial publish has no safe default, never claims a slug, and carries neither attestation nor a source archive (both named in the output). Selectors are comma-separated in ONE `--only`: `changed` (every item whose bytes differ from the base), `screen:<id|glob>`, `bundle:<name>`, `tokens`, `app-config` \u2014 a selected screen drags its logic bundle and a selected bundle drags the screens that reference it, or the bytes land under a key nothing reads.", required: "[--content <dir>] [--draft] [--live] [--force] [--strict] [--label] [--notes] [--visibility public|unlisted] [--no-claim] [--account-id <id>] [--only <selector>] [--from-release <id>] [--accept-regressions] [--accept-partial] [--app <slug>] (--control-token)" },
|
|
@@ -60442,30 +60831,48 @@ function trustedConfiguredRegistry(env) {
|
|
|
60442
60831
|
const configured = normalizeRegistry(env.npm_config_registry ?? env.NPM_CONFIG_REGISTRY);
|
|
60443
60832
|
return isTrustedRegistry(configured) ? configured : void 0;
|
|
60444
60833
|
}
|
|
60445
|
-
function createScopedRegistryResolver(exec =
|
|
60834
|
+
function createScopedRegistryResolver(exec = execNpmConfig) {
|
|
60446
60835
|
let resolved2;
|
|
60447
|
-
return () => {
|
|
60836
|
+
return async (budgetMs = SCOPED_REGISTRY_TIMEOUT_MS) => {
|
|
60448
60837
|
if (resolved2) return resolved2.value;
|
|
60449
|
-
|
|
60838
|
+
const deadline = Date.now() + Math.min(budgetMs, SCOPED_REGISTRY_TIMEOUT_MS);
|
|
60450
60839
|
try {
|
|
60451
|
-
const configured = (key2) => {
|
|
60452
|
-
const
|
|
60453
|
-
|
|
60454
|
-
|
|
60455
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
60456
|
-
}).toString().trim();
|
|
60840
|
+
const configured = async (key2) => {
|
|
60841
|
+
const timeout = deadline - Date.now();
|
|
60842
|
+
if (timeout <= 0) throw new Error("npm config: out of budget");
|
|
60843
|
+
const raw = String(await exec("npm", ["config", "get", key2], { cwd: homedir7(), timeout })).trim();
|
|
60457
60844
|
return raw && raw !== "undefined" ? raw : void 0;
|
|
60458
60845
|
};
|
|
60459
|
-
const effective = normalizeRegistry(configured("@wix:registry") ?? configured("registry"));
|
|
60460
|
-
|
|
60846
|
+
const effective = normalizeRegistry(await configured("@wix:registry") ?? await configured("registry"));
|
|
60847
|
+
resolved2 = { value: isTrustedRegistry(effective) ? effective : void 0 };
|
|
60848
|
+
return resolved2.value;
|
|
60461
60849
|
} catch {
|
|
60462
|
-
|
|
60850
|
+
return void 0;
|
|
60463
60851
|
}
|
|
60464
|
-
resolved2 = { value };
|
|
60465
|
-
return value;
|
|
60466
60852
|
};
|
|
60467
60853
|
}
|
|
60854
|
+
var SCOPED_REGISTRY_TIMEOUT_MS = 5e3;
|
|
60855
|
+
function execNpmConfig(file, args, options) {
|
|
60856
|
+
return new Promise((resolve45, reject) => {
|
|
60857
|
+
execFile4(file, args, { ...options, windowsHide: true }, (error, stdout) => error ? reject(error) : resolve45(String(stdout)));
|
|
60858
|
+
});
|
|
60859
|
+
}
|
|
60468
60860
|
var npmScopedWixRegistry = createScopedRegistryResolver();
|
|
60861
|
+
async function scopedRegistryBefore(lookup2, deadline) {
|
|
60862
|
+
let cancel = () => {
|
|
60863
|
+
};
|
|
60864
|
+
const expired = new Promise((resolve45) => {
|
|
60865
|
+
const timer = setTimeout(() => resolve45(void 0), Math.max(0, deadline - Date.now()));
|
|
60866
|
+
cancel = () => clearTimeout(timer);
|
|
60867
|
+
});
|
|
60868
|
+
try {
|
|
60869
|
+
return await Promise.race([Promise.resolve().then(() => lookup2(Math.max(0, deadline - Date.now()))), expired]);
|
|
60870
|
+
} catch {
|
|
60871
|
+
return void 0;
|
|
60872
|
+
} finally {
|
|
60873
|
+
cancel();
|
|
60874
|
+
}
|
|
60875
|
+
}
|
|
60469
60876
|
function registryCandidates(env, scoped) {
|
|
60470
60877
|
const ordered = [isTrustedRegistry(scoped) ? normalizeRegistry(scoped) : void 0, trustedConfiguredRegistry(env), PUBLIC_NPM_REGISTRY];
|
|
60471
60878
|
return [...new Set(ordered.filter((r) => r !== void 0))];
|
|
@@ -60492,7 +60899,8 @@ async function fetchPackumentFrom(registry, fetchImpl, timeoutMs) {
|
|
|
60492
60899
|
}
|
|
60493
60900
|
async function fetchCliPackument(fetchImpl = fetch, timeoutMs = DOCTOR_TIMEOUT_MS, env = process.env, scopedRegistry = npmScopedWixRegistry) {
|
|
60494
60901
|
const deadline = Date.now() + timeoutMs;
|
|
60495
|
-
|
|
60902
|
+
const scoped = await scopedRegistryBefore(scopedRegistry, deadline);
|
|
60903
|
+
for (const registry of registryCandidates(env, scoped)) {
|
|
60496
60904
|
const remaining = deadline - Date.now();
|
|
60497
60905
|
if (remaining <= 0) break;
|
|
60498
60906
|
const packument = await fetchPackumentFrom(registry, fetchImpl, remaining);
|
|
@@ -60506,9 +60914,9 @@ function ageInDays(publishedAt, now = Date.now()) {
|
|
|
60506
60914
|
if (!Number.isFinite(at)) return void 0;
|
|
60507
60915
|
return Math.max(0, (now - at) / 864e5);
|
|
60508
60916
|
}
|
|
60509
|
-
function packageVersion(
|
|
60917
|
+
function packageVersion(path2) {
|
|
60510
60918
|
try {
|
|
60511
|
-
const version2 = JSON.parse(readFileSync67(
|
|
60919
|
+
const version2 = JSON.parse(readFileSync67(path2, "utf8")).version;
|
|
60512
60920
|
return typeof version2 === "string" && version2 ? version2 : void 0;
|
|
60513
60921
|
} catch {
|
|
60514
60922
|
return void 0;
|
|
@@ -60576,18 +60984,18 @@ var UPDATE_REEXEC_ENV = "HIMI_UPDATED_ONCE";
|
|
|
60576
60984
|
function updateCachePath(env = process.env) {
|
|
60577
60985
|
return env.HIMI_UPDATE_CACHE_FILE ?? join52(homedir7(), ".himalaya", "update-check.json");
|
|
60578
60986
|
}
|
|
60579
|
-
function readUpdateCache(
|
|
60987
|
+
function readUpdateCache(path2) {
|
|
60580
60988
|
try {
|
|
60581
|
-
const parsed = JSON.parse(readFileSync67(
|
|
60989
|
+
const parsed = JSON.parse(readFileSync67(path2, "utf8"));
|
|
60582
60990
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
60583
60991
|
} catch {
|
|
60584
60992
|
return {};
|
|
60585
60993
|
}
|
|
60586
60994
|
}
|
|
60587
|
-
function writeUpdateCache(
|
|
60995
|
+
function writeUpdateCache(path2, cache) {
|
|
60588
60996
|
try {
|
|
60589
|
-
mkdirSync27(dirname31(
|
|
60590
|
-
writeFileSync25(
|
|
60997
|
+
mkdirSync27(dirname31(path2), { recursive: true, mode: 448 });
|
|
60998
|
+
writeFileSync25(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
60591
60999
|
} catch {
|
|
60592
61000
|
}
|
|
60593
61001
|
}
|
|
@@ -60695,10 +61103,10 @@ function isAbandoned(content) {
|
|
|
60695
61103
|
return Number.isFinite(owner) && owner > 0 && host === thisHost() && !processAlive(owner);
|
|
60696
61104
|
}
|
|
60697
61105
|
function staleUpdateLockFile(cachePath, now) {
|
|
60698
|
-
for (const
|
|
61106
|
+
for (const path2 of [`${cachePath}.lock.break`, `${cachePath}.lock`]) {
|
|
60699
61107
|
let content;
|
|
60700
61108
|
try {
|
|
60701
|
-
content = readFileSync67(
|
|
61109
|
+
content = readFileSync67(path2, "utf8");
|
|
60702
61110
|
} catch {
|
|
60703
61111
|
continue;
|
|
60704
61112
|
}
|
|
@@ -60706,12 +61114,12 @@ function staleUpdateLockFile(cachePath, now) {
|
|
|
60706
61114
|
let since = stamped;
|
|
60707
61115
|
if (!Number.isFinite(since)) {
|
|
60708
61116
|
try {
|
|
60709
|
-
since = statSync13(
|
|
61117
|
+
since = statSync13(path2).mtimeMs;
|
|
60710
61118
|
} catch {
|
|
60711
61119
|
continue;
|
|
60712
61120
|
}
|
|
60713
61121
|
}
|
|
60714
|
-
if (now - since >= UPDATE_LOCK_REPORT_AFTER_MS) return
|
|
61122
|
+
if (now - since >= UPDATE_LOCK_REPORT_AFTER_MS) return path2;
|
|
60715
61123
|
}
|
|
60716
61124
|
return void 0;
|
|
60717
61125
|
}
|
|
@@ -60719,24 +61127,24 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
60719
61127
|
const lockPath = `${cachePath}.lock`;
|
|
60720
61128
|
const breakPath = `${cachePath}.lock.break`;
|
|
60721
61129
|
const mine = lockStamp(now);
|
|
60722
|
-
const readLock = (
|
|
61130
|
+
const readLock = (path2) => {
|
|
60723
61131
|
try {
|
|
60724
|
-
return readFileSync67(
|
|
61132
|
+
return readFileSync67(path2, "utf8");
|
|
60725
61133
|
} catch {
|
|
60726
61134
|
return void 0;
|
|
60727
61135
|
}
|
|
60728
61136
|
};
|
|
60729
|
-
const tryCreate = (
|
|
61137
|
+
const tryCreate = (path2) => {
|
|
60730
61138
|
try {
|
|
60731
|
-
writeFileSync25(
|
|
61139
|
+
writeFileSync25(path2, mine, { flag: "wx", mode: 384 });
|
|
60732
61140
|
return true;
|
|
60733
61141
|
} catch {
|
|
60734
61142
|
return false;
|
|
60735
61143
|
}
|
|
60736
61144
|
};
|
|
60737
|
-
const removeIfMine = (
|
|
61145
|
+
const removeIfMine = (path2) => {
|
|
60738
61146
|
try {
|
|
60739
|
-
if (readLock(
|
|
61147
|
+
if (readLock(path2) === mine) rmSync10(path2, { force: true });
|
|
60740
61148
|
} catch {
|
|
60741
61149
|
}
|
|
60742
61150
|
};
|
|
@@ -60790,8 +61198,10 @@ async function refreshUpdateCache(opts = {}) {
|
|
|
60790
61198
|
const packument = await fetchCliPackument(opts.fetchImpl ?? fetch, UPDATE_BACKGROUND_BUDGET_MS, env, opts.scopedRegistry);
|
|
60791
61199
|
if (!packument) return false;
|
|
60792
61200
|
const now = opts.now ?? Date.now();
|
|
61201
|
+
const current = readUpdateCache(cachePath);
|
|
61202
|
+
if (supersededInCache(current, packument.latest, now)) return true;
|
|
60793
61203
|
writeUpdateCache(cachePath, {
|
|
60794
|
-
...
|
|
61204
|
+
...current,
|
|
60795
61205
|
running,
|
|
60796
61206
|
latest: packument.latest,
|
|
60797
61207
|
runningPublishedAt: packument.time[running],
|
|
@@ -60799,6 +61209,11 @@ async function refreshUpdateCache(opts = {}) {
|
|
|
60799
61209
|
});
|
|
60800
61210
|
return true;
|
|
60801
61211
|
}
|
|
61212
|
+
function supersededInCache(current, latest, now) {
|
|
61213
|
+
if (!current.latest || !latest || compareVersions2(latest, current.latest) >= 0) return false;
|
|
61214
|
+
const checkedAt = current.checkedAt ? Date.parse(current.checkedAt) : Number.NaN;
|
|
61215
|
+
return Number.isFinite(checkedAt) && now - checkedAt < UPDATE_CHECK_INTERVAL_MS;
|
|
61216
|
+
}
|
|
60802
61217
|
function createUpdateRefreshSpawner(spawnFn = spawn5, execArgv = process.execArgv) {
|
|
60803
61218
|
return () => {
|
|
60804
61219
|
try {
|
|
@@ -60957,9 +61372,9 @@ function helpJson() {
|
|
|
60957
61372
|
}
|
|
60958
61373
|
function previewWebUrl(serveBase, app, release, screenId, surface, previewToken, handover) {
|
|
60959
61374
|
const base = serveBase.replace(/\/$/, "");
|
|
60960
|
-
const
|
|
61375
|
+
const path2 = screenId ? `/preview/a/${app}/screen/${screenId}` : `/preview/a/${app}`;
|
|
60961
61376
|
const query = handover ? `?h=${encodeURIComponent(handover)}` : `?release=${encodeURIComponent(release)}`;
|
|
60962
|
-
return `${base}${
|
|
61377
|
+
return `${base}${path2}${query}${surface ? `&surface=${encodeURIComponent(surface)}` : ""}${!handover && previewToken ? `&pvt=${encodeURIComponent(previewToken)}` : ""}`;
|
|
60963
61378
|
}
|
|
60964
61379
|
function renderDeviceWidths() {
|
|
60965
61380
|
return {
|
|
@@ -61380,10 +61795,10 @@ function readConfigSource(dir) {
|
|
|
61380
61795
|
return null;
|
|
61381
61796
|
}
|
|
61382
61797
|
}
|
|
61383
|
-
function writePngFile(
|
|
61384
|
-
mkdirSync27(dirname31(
|
|
61385
|
-
writeFileSync25(
|
|
61386
|
-
return
|
|
61798
|
+
function writePngFile(path2, base64) {
|
|
61799
|
+
mkdirSync27(dirname31(path2), { recursive: true });
|
|
61800
|
+
writeFileSync25(path2, Buffer.from(base64, "base64"));
|
|
61801
|
+
return path2;
|
|
61387
61802
|
}
|
|
61388
61803
|
async function initFromRemoteTemplate(name, parentDir, template, c) {
|
|
61389
61804
|
const dir = resolve44(parentDir, name);
|
|
@@ -61577,9 +61992,9 @@ async function loadCms(dir) {
|
|
|
61577
61992
|
return data ? { collections: data.collections ?? [], ...data.memberGated ? { memberGated: true } : {} } : void 0;
|
|
61578
61993
|
}
|
|
61579
61994
|
var ConfigLoadError = class extends Error {
|
|
61580
|
-
constructor(
|
|
61581
|
-
super(`could not load ${
|
|
61582
|
-
this.path =
|
|
61995
|
+
constructor(path2, cause) {
|
|
61996
|
+
super(`could not load ${path2}: ${cause.message}`);
|
|
61997
|
+
this.path = path2;
|
|
61583
61998
|
this.cause = cause;
|
|
61584
61999
|
this.name = "ConfigLoadError";
|
|
61585
62000
|
}
|
|
@@ -62553,17 +62968,17 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62553
62968
|
const dir = contentDir(flags);
|
|
62554
62969
|
const { buildContentBundles: buildContentBundles2 } = await loadAuthoring();
|
|
62555
62970
|
const res = await buildContentBundles2(dir, { resolution: resolutionFlag(flags) });
|
|
62556
|
-
const
|
|
62971
|
+
const failed2 = res.compileErrors;
|
|
62557
62972
|
print({
|
|
62558
|
-
ok:
|
|
62973
|
+
ok: failed2.length === 0,
|
|
62559
62974
|
outDir: res.outDir,
|
|
62560
62975
|
built: res.built,
|
|
62561
|
-
...
|
|
62976
|
+
...failed2.length ? { compileErrors: failed2 } : {},
|
|
62562
62977
|
// #642.1b — a stale @wix/himalaya is advisory on `build` (the bundles may
|
|
62563
62978
|
// still compile); `validate --strict` is where it hard-fails.
|
|
62564
62979
|
...res.sdkVersionIssue ? { warnings: [res.sdkVersionIssue] } : {}
|
|
62565
62980
|
});
|
|
62566
|
-
return
|
|
62981
|
+
return failed2.length ? 1 : 0;
|
|
62567
62982
|
}
|
|
62568
62983
|
case "eject": {
|
|
62569
62984
|
const mod = String(pos[1] ?? "");
|
|
@@ -62644,12 +63059,12 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
62644
63059
|
const { buildLocalFunctions: buildLocalFunctions2, describeFunction: describeFunction2, invokeLocalFunction: invokeLocalFunction2, invokeRemoteFunction: invokeRemoteFunction2, listFunctions: listFunctions2, loadFunctionsApp: loadFunctionsApp2, openApiForFunctions: openApiForFunctions2, resolveFunctionsTarget: resolveFunctionsTarget2, runRemoteFunctionOperation: runRemoteFunctionOperation2 } = await Promise.resolve().then(() => (init_functions(), functions_exports));
|
|
62645
63060
|
const remoteTarget = str5(flags.target);
|
|
62646
63061
|
const boCookie = () => {
|
|
62647
|
-
const
|
|
63062
|
+
const path2 = dpxSessionTokenPath();
|
|
62648
63063
|
let raw;
|
|
62649
63064
|
try {
|
|
62650
|
-
raw = readFileSync67(
|
|
63065
|
+
raw = readFileSync67(path2, "utf8");
|
|
62651
63066
|
} catch {
|
|
62652
|
-
throw new Error(`no DPX BO session at ${
|
|
63067
|
+
throw new Error(`no DPX BO session at ${path2}; run dpx auth login, write dpx auth token to that path, then himi login --dpx --target bo`);
|
|
62653
63068
|
}
|
|
62654
63069
|
return dpxCookieHeader(raw);
|
|
62655
63070
|
};
|
|
@@ -63119,7 +63534,7 @@ himi v${cliVersion()} \u2014 run \`himi --version\`. If authoring commands fail
|
|
|
63119
63534
|
bootAndSnapshotState: bootAndSnapshotState2,
|
|
63120
63535
|
renderDescriptorWeb: renderDescriptorWeb2,
|
|
63121
63536
|
renderPngBatch: renderPngBatch2,
|
|
63122
|
-
writePng: (
|
|
63537
|
+
writePng: (path2, base64) => writePngFile(path2, base64),
|
|
63123
63538
|
clearDir: (d) => rmSync10(d, { recursive: true, force: true })
|
|
63124
63539
|
}
|
|
63125
63540
|
});
|
|
@@ -65619,7 +66034,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65619
66034
|
const { iosProjectYml: iosYmlPath, hasRepoCheckout: hasRepoCheckout2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
65620
66035
|
const { ascStatus: ascStatus2 } = await Promise.resolve().then(() => (init_asc_status(), asc_status_exports));
|
|
65621
66036
|
const { readFileSync: rf, readdirSync: rd, existsSync: ex, statSync: st } = await import("node:fs");
|
|
65622
|
-
const { execFile:
|
|
66037
|
+
const { execFile: execFile5 } = await import("node:child_process");
|
|
65623
66038
|
const { homedir: hd } = await import("node:os");
|
|
65624
66039
|
const { join: pj, dirname: pd } = await import("node:path");
|
|
65625
66040
|
const { fileURLToPath: f2p } = await import("node:url");
|
|
@@ -65634,7 +66049,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
65634
66049
|
return ipas[0];
|
|
65635
66050
|
};
|
|
65636
66051
|
const sh = (cmd, args, opts) => new Promise((res) => {
|
|
65637
|
-
const child =
|
|
66052
|
+
const child = execFile5(
|
|
65638
66053
|
cmd,
|
|
65639
66054
|
args,
|
|
65640
66055
|
{ cwd: opts.cwd, env: { ...process.env, ...opts.env }, maxBuffer: 64 * 1024 * 1024 },
|
|
@@ -66405,7 +66820,7 @@ ${label2}`);
|
|
|
66405
66820
|
try {
|
|
66406
66821
|
const scoped = up.scopedRegistry ?? npmScopedWixRegistry;
|
|
66407
66822
|
const answered = await fetchCliPackument(up.fetchImpl ?? fetch, UPDATE_EXPLICIT_BUDGET_MS, env, scoped);
|
|
66408
|
-
const registry = answered?.registry ?? registryCandidates(env, scoped())[0];
|
|
66823
|
+
const registry = answered?.registry ?? registryCandidates(env, await scoped(UPDATE_EXPLICIT_BUDGET_MS))[0];
|
|
66409
66824
|
if (answered?.latest && compareVersions2(answered.latest, before) <= 0) {
|
|
66410
66825
|
if (flags.json) print({ ok: true, running: before, installed: before, changed: false, registry, latest: answered.latest });
|
|
66411
66826
|
else io.log(`himi ${before} (unchanged \u2014 ${registry} has nothing newer; its latest is ${answered.latest})`);
|
|
@@ -66554,12 +66969,12 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
|
|
|
66554
66969
|
return 1;
|
|
66555
66970
|
}
|
|
66556
66971
|
if (secretTarget.mode === "remote") {
|
|
66557
|
-
const
|
|
66972
|
+
const path2 = dpxSessionTokenPath();
|
|
66558
66973
|
let raw;
|
|
66559
66974
|
try {
|
|
66560
|
-
raw = readFileSync67(
|
|
66975
|
+
raw = readFileSync67(path2, "utf8");
|
|
66561
66976
|
} catch {
|
|
66562
|
-
io.error(JSON.stringify({ error: `no DPX BO session at ${
|
|
66977
|
+
io.error(JSON.stringify({ error: `no DPX BO session at ${path2}` }));
|
|
66563
66978
|
return 1;
|
|
66564
66979
|
}
|
|
66565
66980
|
const { runRemoteSecretsCommand: runRemoteSecretsCommand2 } = await Promise.resolve().then(() => (init_secrets2(), secrets_exports));
|
|
@@ -66829,6 +67244,34 @@ ${report2.ok ? "OK \u2014 data + serve plane reachable." : typeof report2.hint =
|
|
|
66829
67244
|
}
|
|
66830
67245
|
const clientId = str5(flags["client-id"]) ?? process.env.WIX_CLIENT_ID;
|
|
66831
67246
|
const siteUrl = str5(flags.url) ?? str5(flags["site-url"]);
|
|
67247
|
+
if (flags["read-only"] === true) {
|
|
67248
|
+
if (flags.apply || flags.out || flags.shell || flags["redirect-uri"]) {
|
|
67249
|
+
io.error(JSON.stringify({ error: "--read-only returns API context only; it cannot be combined with --apply, --out, --shell, or --redirect-uri" }));
|
|
67250
|
+
return 2;
|
|
67251
|
+
}
|
|
67252
|
+
const siteId = str5(flags.site) ?? process.env.WIX_SITE_ID;
|
|
67253
|
+
if (!clientId && !siteId && !process.env.WIX_TEST_TOKEN?.trim()) {
|
|
67254
|
+
io.error(JSON.stringify({ error: "--read-only needs --site, --client-id, or a site-scoped WIX_TEST_TOKEN" }));
|
|
67255
|
+
return 2;
|
|
67256
|
+
}
|
|
67257
|
+
const { collectSiteContext: collectSiteContext2 } = await Promise.resolve().then(() => (init_context(), context_exports));
|
|
67258
|
+
const { siteToken: siteToken2 } = await Promise.resolve().then(() => (init_wix_owner(), wix_owner_exports));
|
|
67259
|
+
let ownerToken = process.env.WIX_TEST_TOKEN?.trim() || void 0;
|
|
67260
|
+
if (!ownerToken && siteId) {
|
|
67261
|
+
try {
|
|
67262
|
+
ownerToken = await siteToken2(siteId);
|
|
67263
|
+
} catch {
|
|
67264
|
+
}
|
|
67265
|
+
}
|
|
67266
|
+
const context = await collectSiteContext2({
|
|
67267
|
+
siteId,
|
|
67268
|
+
clientId,
|
|
67269
|
+
ownerToken,
|
|
67270
|
+
request: process.env.HIMI_ANALYZE_REQUEST
|
|
67271
|
+
});
|
|
67272
|
+
print({ ok: true, context });
|
|
67273
|
+
return 0;
|
|
67274
|
+
}
|
|
66832
67275
|
if (!clientId || !siteUrl) {
|
|
66833
67276
|
io.error(JSON.stringify({
|
|
66834
67277
|
error: "himi site analyze needs --client-id and --url",
|