@wix/himalaya-cli 0.1509.0 → 0.1510.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +192 -26
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -22176,7 +22176,6 @@ function resolveIdiom(tokens2, ctx = {}) {
|
|
|
22176
22176
|
var IDIOM_CONTEXTS, UNSAFE_KEYS;
|
|
22177
22177
|
var init_idiom = __esm({
|
|
22178
22178
|
"../../core/ts/src/idiom.ts"() {
|
|
22179
|
-
"use strict";
|
|
22180
22179
|
IDIOM_CONTEXTS = {
|
|
22181
22180
|
ios: { native: ["ios"] },
|
|
22182
22181
|
android: { native: ["material"] },
|
|
@@ -163184,6 +163183,134 @@ var init_member_exchange = __esm({
|
|
|
163184
163183
|
}
|
|
163185
163184
|
});
|
|
163186
163185
|
|
|
163186
|
+
// ../../core/serve-runtime/src/member-forward.ts
|
|
163187
|
+
function matchMemberForward(method, raw, rules = MEMBER_FORWARD_ALLOWLIST) {
|
|
163188
|
+
if (typeof method !== "string" || typeof raw !== "string" || raw.length === 0 || raw.length > 8192) return null;
|
|
163189
|
+
const verb = method.toUpperCase();
|
|
163190
|
+
let url;
|
|
163191
|
+
try {
|
|
163192
|
+
url = new URL(raw);
|
|
163193
|
+
} catch {
|
|
163194
|
+
return null;
|
|
163195
|
+
}
|
|
163196
|
+
if (url.protocol !== "https:" || url.port !== "" || url.username || url.password || url.hash) return null;
|
|
163197
|
+
const rawPath = raw.replace(/^https:\/\/[^/?#]*/i, "").split(/[?#]/, 1)[0];
|
|
163198
|
+
if (rawPath !== url.pathname || /[%\\]|\/\/|\.\./.test(rawPath)) return null;
|
|
163199
|
+
const host = url.hostname.toLowerCase();
|
|
163200
|
+
const rule = rules.find((r3) => r3.method === verb && r3.host === host && r3.path.test(url.pathname));
|
|
163201
|
+
if (!rule) return null;
|
|
163202
|
+
const seen = /* @__PURE__ */ new Set();
|
|
163203
|
+
for (const [key3, value] of url.searchParams) {
|
|
163204
|
+
const allowed2 = Object.hasOwn(rule.query, key3) ? rule.query[key3] : void 0;
|
|
163205
|
+
if (!(allowed2 instanceof RegExp) || seen.has(key3) || !allowed2.test(value)) return null;
|
|
163206
|
+
seen.add(key3);
|
|
163207
|
+
}
|
|
163208
|
+
if ((rule.required ?? []).some((key3) => !seen.has(key3))) return null;
|
|
163209
|
+
return { rule, url };
|
|
163210
|
+
}
|
|
163211
|
+
function matchForwardHeaders(rule, raw) {
|
|
163212
|
+
const allowed2 = rule.headers ?? {};
|
|
163213
|
+
const out2 = {};
|
|
163214
|
+
if (raw !== void 0 && raw !== null) {
|
|
163215
|
+
if (typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
163216
|
+
for (const [name, value] of Object.entries(raw)) {
|
|
163217
|
+
const canonical7 = Object.keys(allowed2).find((k2) => k2.toLowerCase() === name.toLowerCase());
|
|
163218
|
+
if (!canonical7 || typeof value !== "string" || !allowed2[canonical7].test(value) || Object.hasOwn(out2, canonical7)) return null;
|
|
163219
|
+
out2[canonical7] = value;
|
|
163220
|
+
}
|
|
163221
|
+
}
|
|
163222
|
+
if ((rule.requiredHeaders ?? []).some((name) => !Object.hasOwn(out2, name))) return null;
|
|
163223
|
+
return out2;
|
|
163224
|
+
}
|
|
163225
|
+
async function readCapped(res, maxChars) {
|
|
163226
|
+
const declared = Number(res.headers.get("content-length"));
|
|
163227
|
+
if (Number.isFinite(declared) && declared > maxChars * 4) {
|
|
163228
|
+
await res.body?.cancel().catch(() => {
|
|
163229
|
+
});
|
|
163230
|
+
return null;
|
|
163231
|
+
}
|
|
163232
|
+
if (!res.body) {
|
|
163233
|
+
const text12 = await res.text();
|
|
163234
|
+
return text12.length > maxChars ? null : text12;
|
|
163235
|
+
}
|
|
163236
|
+
const reader = res.body.getReader();
|
|
163237
|
+
const decoder = new TextDecoder();
|
|
163238
|
+
let text11 = "";
|
|
163239
|
+
for (; ; ) {
|
|
163240
|
+
const { done, value } = await reader.read();
|
|
163241
|
+
if (done) break;
|
|
163242
|
+
text11 += decoder.decode(value, { stream: true });
|
|
163243
|
+
if (text11.length > maxChars) {
|
|
163244
|
+
await reader.cancel().catch(() => {
|
|
163245
|
+
});
|
|
163246
|
+
return null;
|
|
163247
|
+
}
|
|
163248
|
+
}
|
|
163249
|
+
text11 += decoder.decode();
|
|
163250
|
+
return text11.length > maxChars ? null : text11;
|
|
163251
|
+
}
|
|
163252
|
+
async function memberForwardCall(match, body, memberToken, fetchImpl = fetch, extraHeaders = {}) {
|
|
163253
|
+
const headers2 = { Accept: "application/json", ...extraHeaders };
|
|
163254
|
+
if (body !== void 0) headers2["Content-Type"] = "application/json";
|
|
163255
|
+
if (match.rule.auth === "member") headers2.Authorization = memberToken;
|
|
163256
|
+
try {
|
|
163257
|
+
const res = await fetchImpl(match.url.toString(), {
|
|
163258
|
+
method: match.rule.method,
|
|
163259
|
+
headers: headers2,
|
|
163260
|
+
body,
|
|
163261
|
+
redirect: "manual",
|
|
163262
|
+
credentials: "omit",
|
|
163263
|
+
signal: AbortSignal.timeout(FORWARD_TIMEOUT_MS)
|
|
163264
|
+
});
|
|
163265
|
+
const text11 = await readCapped(res, MAX_RESPONSE_CHARS);
|
|
163266
|
+
if (text11 === null) return { ok: false, code: "forward_too_large" };
|
|
163267
|
+
return { ok: true, status: res.status, body: text11 };
|
|
163268
|
+
} catch {
|
|
163269
|
+
return { ok: false, code: "forward_failed" };
|
|
163270
|
+
}
|
|
163271
|
+
}
|
|
163272
|
+
var BOOL, SMALL_INT, TOKENISH, CURSOR, ROOM, LIST_QUERY, MEMBER_FORWARD_ALLOWLIST, FORWARD_TIMEOUT_MS, MAX_RESPONSE_CHARS;
|
|
163273
|
+
var init_member_forward = __esm({
|
|
163274
|
+
"../../core/serve-runtime/src/member-forward.ts"() {
|
|
163275
|
+
BOOL = /^(true|false)$/;
|
|
163276
|
+
SMALL_INT = /^\d{1,6}$/;
|
|
163277
|
+
TOKENISH = /^[A-Za-z0-9._~-]{1,4096}$/;
|
|
163278
|
+
CURSOR = /^[A-Za-z0-9._~:=+/,-]{1,2048}$/;
|
|
163279
|
+
ROOM = "[A-Za-z0-9-]{1,64}";
|
|
163280
|
+
LIST_QUERY = { chatToken: TOKENISH, nextPointer: CURSOR, pageSize: SMALL_INT, archived: BOOL, onlyUnread: BOOL, lastMessageLimit: SMALL_INT, unreadChatroomLimit: SMALL_INT };
|
|
163281
|
+
MEMBER_FORWARD_ALLOWLIST = [
|
|
163282
|
+
// Chat: mint the chat token with the member token alone.
|
|
163283
|
+
{ method: "POST", host: "manage.wix.com", path: /^\/_api\/wix-chat-tokens-server\/v1\/chat-tokens$/, auth: "member", query: { isForUnifiedList: BOOL } },
|
|
163284
|
+
// Chat: the member's conversation list (all, or one participant type), authorised by the chat token in the query.
|
|
163285
|
+
{ method: "POST", host: "manage.wix.com", path: /^\/_api\/chat-web\/v1\/chatrooms-for-list-view(?:\/(?:business|siteMember))?$/, auth: "none", query: LIST_QUERY, required: ["chatToken"] },
|
|
163286
|
+
{ method: "GET", host: "manage.wix.com", path: /^\/_api\/chat-web\/v2\/chatrooms$/, auth: "none", query: { chatToken: TOKENISH, nextPointer: CURSOR, pageSize: SMALL_INT }, required: ["chatToken"] },
|
|
163287
|
+
// Chat: a conversation's history.
|
|
163288
|
+
{
|
|
163289
|
+
method: "GET",
|
|
163290
|
+
host: "manage.wix.com",
|
|
163291
|
+
path: new RegExp(`^/_api/chat-web/v1/chatrooms/${ROOM}/messages$`),
|
|
163292
|
+
auth: "none",
|
|
163293
|
+
query: { chatToken: TOKENISH, pageSize: SMALL_INT, ordering: /^(?:Asc|Desc)$/, nextPointer: CURSOR },
|
|
163294
|
+
required: ["chatToken"]
|
|
163295
|
+
},
|
|
163296
|
+
// Chat: send a message. The chat token rides the `ChatToken` HEADER here (the query is rejected: probed).
|
|
163297
|
+
{
|
|
163298
|
+
method: "POST",
|
|
163299
|
+
host: "manage.wix.com",
|
|
163300
|
+
path: new RegExp(`^/_api/chat-web/v2/chatrooms/${ROOM}/messages$`),
|
|
163301
|
+
auth: "none",
|
|
163302
|
+
query: {},
|
|
163303
|
+
headers: { ChatToken: TOKENISH },
|
|
163304
|
+
requiredHeaders: ["ChatToken"]
|
|
163305
|
+
},
|
|
163306
|
+
// Chat: the live-update (realtime) token. The answer carries a credential for a third party; it is returned to the caller only.
|
|
163307
|
+
{ method: "POST", host: "manage.wix.com", path: /^\/_api\/chat-web\/v1\/real-time-tokens$/, auth: "none", query: { chatToken: TOKENISH }, required: ["chatToken"] }
|
|
163308
|
+
];
|
|
163309
|
+
FORWARD_TIMEOUT_MS = 15e3;
|
|
163310
|
+
MAX_RESPONSE_CHARS = 1e6;
|
|
163311
|
+
}
|
|
163312
|
+
});
|
|
163313
|
+
|
|
163187
163314
|
// ../../core/serve-runtime/package-share.ts
|
|
163188
163315
|
function parseStored(bytes2, id) {
|
|
163189
163316
|
if (!bytes2) return null;
|
|
@@ -163740,6 +163867,27 @@ ${releaseId}`;
|
|
|
163740
163867
|
}
|
|
163741
163868
|
return new Response(body, { status: 200, headers: { "content-type": JSON_CT3, etag, "cache-control": cache, ...vary } });
|
|
163742
163869
|
}
|
|
163870
|
+
async function draftPreviewOnly(request, url, noStore) {
|
|
163871
|
+
const refuse7 = (status, error) => ({ ok: false, response: json5(status, { error }, noStore) });
|
|
163872
|
+
if (opts.webwixBridge === false) return refuse7(503, "webwix_bridge_disabled");
|
|
163873
|
+
if (!opts.previewTokenSecret) return refuse7(503, "preview_token_unavailable");
|
|
163874
|
+
const app = resolveApp(request, url);
|
|
163875
|
+
if (!app) return refuse7(400, "app_required");
|
|
163876
|
+
const pin = resolvePin(request, url);
|
|
163877
|
+
if (!pin || !resolvePreviewToken(request, url)) return refuse7(403, "draft_preview_required");
|
|
163878
|
+
const cfg = await appConfigFor(request, url, app);
|
|
163879
|
+
if (!cfg.ok) return { ok: false, response: cfg.response };
|
|
163880
|
+
let ringPinned = false;
|
|
163881
|
+
if (opts.ringReleases) {
|
|
163882
|
+
try {
|
|
163883
|
+
ringPinned = new Set(await opts.ringReleases(app)).has(pin);
|
|
163884
|
+
} catch {
|
|
163885
|
+
return refuse7(503, "ring_lookup_unavailable");
|
|
163886
|
+
}
|
|
163887
|
+
}
|
|
163888
|
+
if ((await manifest(app))?.releaseId === pin || ringPinned) return refuse7(403, "draft_preview_required");
|
|
163889
|
+
return { ok: true, app, pin, cfgBytes: cfg.bytes };
|
|
163890
|
+
}
|
|
163743
163891
|
async function authorizePinnedRead(request, url, app, releaseId, screenId) {
|
|
163744
163892
|
const denied2 = await checkPinnedRead({
|
|
163745
163893
|
secret: opts.previewTokenSecret,
|
|
@@ -164020,26 +164168,9 @@ ${releaseId}`;
|
|
|
164020
164168
|
}
|
|
164021
164169
|
if (request.method === "POST" && path2 === "/v1/__webwix/member-exchange") {
|
|
164022
164170
|
const noStore = { "cache-control": "no-store" };
|
|
164023
|
-
|
|
164024
|
-
if (!
|
|
164025
|
-
const
|
|
164026
|
-
if (!exchangeApp) return json5(400, { error: "app_required" }, noStore);
|
|
164027
|
-
const exchangePin = resolvePin(request, url);
|
|
164028
|
-
if (!exchangePin || !resolvePreviewToken(request, url)) return json5(403, { error: "draft_preview_required" }, noStore);
|
|
164029
|
-
const exchangeCfg = await appConfigFor(request, url, exchangeApp);
|
|
164030
|
-
if (!exchangeCfg.ok) return exchangeCfg.response;
|
|
164031
|
-
let ringPinned = false;
|
|
164032
|
-
if (opts.ringReleases) {
|
|
164033
|
-
try {
|
|
164034
|
-
ringPinned = new Set(await opts.ringReleases(exchangeApp)).has(exchangePin);
|
|
164035
|
-
} catch {
|
|
164036
|
-
return json5(503, { error: "ring_lookup_unavailable" }, noStore);
|
|
164037
|
-
}
|
|
164038
|
-
}
|
|
164039
|
-
if ((await manifest(exchangeApp))?.releaseId === exchangePin || ringPinned) {
|
|
164040
|
-
return json5(403, { error: "draft_preview_required" }, noStore);
|
|
164041
|
-
}
|
|
164042
|
-
const exchangeClient = wixClientIdOf(utf8Decode(exchangeCfg.bytes));
|
|
164171
|
+
const gate = await draftPreviewOnly(request, url, noStore);
|
|
164172
|
+
if (!gate.ok) return gate.response;
|
|
164173
|
+
const exchangeClient = wixClientIdOf(utf8Decode(gate.cfgBytes));
|
|
164043
164174
|
if ("error" in exchangeClient) return json5(501, { error: `member_exchange_${exchangeClient.error}` }, noStore);
|
|
164044
164175
|
const headerToken = request.headers.get("x-himalaya-member-session");
|
|
164045
164176
|
let sessionToken = headerToken ?? void 0;
|
|
@@ -164068,6 +164199,40 @@ ${releaseId}`;
|
|
|
164068
164199
|
if (exchanged.code === "bad_request") return json5(400, { error: "invalid_session_token", received }, noStore);
|
|
164069
164200
|
return json5(502, { error: exchanged.code, ...exchanged.status !== void 0 ? { status: exchanged.status } : {} }, noStore);
|
|
164070
164201
|
}
|
|
164202
|
+
if (request.method === "POST" && path2 === "/v1/__webwix/member-forward") {
|
|
164203
|
+
const noStore = { "cache-control": "no-store" };
|
|
164204
|
+
const gate = await draftPreviewOnly(request, url, noStore);
|
|
164205
|
+
if (!gate.ok) return gate.response;
|
|
164206
|
+
let raw;
|
|
164207
|
+
try {
|
|
164208
|
+
raw = await request.text();
|
|
164209
|
+
} catch {
|
|
164210
|
+
return json5(400, { error: "body_unreadable" }, noStore);
|
|
164211
|
+
}
|
|
164212
|
+
if (!raw) return json5(400, { error: "empty_body" }, noStore);
|
|
164213
|
+
if (raw.length > 256e3) return json5(413, { error: "body_too_large" }, noStore);
|
|
164214
|
+
let parsed;
|
|
164215
|
+
try {
|
|
164216
|
+
parsed = JSON.parse(raw);
|
|
164217
|
+
} catch {
|
|
164218
|
+
return json5(400, { error: "invalid_json" }, noStore);
|
|
164219
|
+
}
|
|
164220
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return json5(400, { error: "invalid_body" }, noStore);
|
|
164221
|
+
if (typeof parsed.memberToken !== "string" || !parsed.memberToken || parsed.memberToken.length > 4096) return json5(400, { error: "member_token_required" }, noStore);
|
|
164222
|
+
const match = matchMemberForward(parsed.method, parsed.url);
|
|
164223
|
+
if (!match) return json5(403, { error: "forward_target_refused" }, noStore);
|
|
164224
|
+
const forwardHeaders = matchForwardHeaders(match.rule, parsed.headers);
|
|
164225
|
+
if (!forwardHeaders) return json5(403, { error: "forward_header_refused" }, noStore);
|
|
164226
|
+
let forwardBody;
|
|
164227
|
+
if (parsed.body !== void 0) {
|
|
164228
|
+
if (match.rule.method === "GET" || match.rule.method === "DELETE") return json5(400, { error: "body_not_allowed" }, noStore);
|
|
164229
|
+
forwardBody = typeof parsed.body === "string" ? parsed.body : JSON.stringify(parsed.body);
|
|
164230
|
+
if (forwardBody.length > 64e3) return json5(413, { error: "body_too_large" }, noStore);
|
|
164231
|
+
}
|
|
164232
|
+
const forwarded = await memberForwardCall(match, forwardBody, parsed.memberToken, webwixFetch, forwardHeaders);
|
|
164233
|
+
if (!forwarded.ok) return json5(502, { error: forwarded.code }, noStore);
|
|
164234
|
+
return json5(200, { status: forwarded.status, body: forwarded.body }, noStore);
|
|
164235
|
+
}
|
|
164071
164236
|
if (request.method === "POST" && path2 === "/v1/__webwix/call") {
|
|
164072
164237
|
const served = { rung: "none" };
|
|
164073
164238
|
let status = 500;
|
|
@@ -164693,6 +164858,7 @@ var init_server2 = __esm({
|
|
|
164693
164858
|
init_contract();
|
|
164694
164859
|
init_pinned_read();
|
|
164695
164860
|
init_member_exchange();
|
|
164861
|
+
init_member_forward();
|
|
164696
164862
|
init_package_share();
|
|
164697
164863
|
init_wix_bridge();
|
|
164698
164864
|
init_account_rung();
|
|
@@ -176770,7 +176936,7 @@ function extOf2(url) {
|
|
|
176770
176936
|
if (/\.ico$/i.test(path2)) return "ico";
|
|
176771
176937
|
return "jpg";
|
|
176772
176938
|
}
|
|
176773
|
-
async function
|
|
176939
|
+
async function readCapped2(res, cap) {
|
|
176774
176940
|
const declared = Number(res.headers?.get?.("content-length"));
|
|
176775
176941
|
if (Number.isFinite(declared) && declared > cap) {
|
|
176776
176942
|
await discardBody(res);
|
|
@@ -176806,7 +176972,7 @@ async function fetchBrandFace(family, url, fetchImpl) {
|
|
|
176806
176972
|
await discardBody(res);
|
|
176807
176973
|
return void 0;
|
|
176808
176974
|
}
|
|
176809
|
-
const capped = await
|
|
176975
|
+
const capped = await readCapped2(res, MAX_FONT_BYTES);
|
|
176810
176976
|
if (!capped) return void 0;
|
|
176811
176977
|
woff2 = capped;
|
|
176812
176978
|
} catch {
|
|
@@ -177345,7 +177511,7 @@ function pagesFromRegistry(js2) {
|
|
|
177345
177511
|
return [...m2[1].matchAll(/["']?([A-Z][A-Za-z0-9_]*)["']?\s*:/g)].map((x2) => x2[1]).slice(0, MAX_ROUTES);
|
|
177346
177512
|
}
|
|
177347
177513
|
async function readText3(res, cap) {
|
|
177348
|
-
const buf = await
|
|
177514
|
+
const buf = await readCapped2(res, cap);
|
|
177349
177515
|
if (!buf) throw new Error(`body over the ${cap}-byte cap`);
|
|
177350
177516
|
return buf.toString("utf8");
|
|
177351
177517
|
}
|
|
@@ -180788,7 +180954,7 @@ async function createPlaywrightBrowser(load3 = () => import("playwright"), siteF
|
|
|
180788
180954
|
await route.fulfill({ status: res.status, headers: { location }, body: Buffer.alloc(0) });
|
|
180789
180955
|
return;
|
|
180790
180956
|
}
|
|
180791
|
-
const capped = await
|
|
180957
|
+
const capped = await readCapped2(res, MAX_DOCUMENT_BYTES);
|
|
180792
180958
|
if (!capped) {
|
|
180793
180959
|
await route.abort();
|
|
180794
180960
|
return;
|
|
@@ -181198,7 +181364,7 @@ function projectDownloader(apiFetch, apiBase, token, extract = systemTar) {
|
|
|
181198
181364
|
if (!res.ok) {
|
|
181199
181365
|
throw new Error(res.status === 401 || res.status === 403 ? `refused (${res.status}) \u2014 the signed-in user cannot download this app's code (editor role needed)` : `project download failed: HTTP ${res.status}`);
|
|
181200
181366
|
}
|
|
181201
|
-
const bytes2 = await
|
|
181367
|
+
const bytes2 = await readCapped2(res, MAX_TARBALL_BYTES);
|
|
181202
181368
|
if (!bytes2) throw new Error(`project download is over the ${MAX_TARBALL_BYTES}-byte cap`);
|
|
181203
181369
|
const root = mkdtempSync10(join112(tmpdir11(), "himi-base44-"));
|
|
181204
181370
|
const cleanup = () => rmSync30(root, { recursive: true, force: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1510.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"artifactId": "himalaya-cli"
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
"falconPackageHash": "
|
|
74
|
+
"falconPackageHash": "998b3b056eb19f8b72dbf9d3dfcd78c59ad50f7c4390a381ce6780d1"
|
|
75
75
|
}
|