@wix/himalaya-cli 0.1458.0 → 0.1459.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.
@@ -1,3 +1,4 @@
1
+ export declare const WIX_API = "https://www.wixapis.com";
1
2
  /** The narrow Wix consumer endpoints allowed to receive credentials for SSE. */
2
3
  export declare function isAllowedConsumerStreamTarget(raw: string): boolean;
3
4
  /** Classify an absolute-URL rejection: an off-gateway Wix account host is a
package/dist/cli.mjs CHANGED
@@ -1059,8 +1059,8 @@ function toBase64(bytes2) {
1059
1059
  function utf8Decode(bytes2) {
1060
1060
  return new TextDecoder("utf-8").decode(bytes2);
1061
1061
  }
1062
- function fromBase64Url(b64url3) {
1063
- const std = b64url3.replace(/-/g, "+").replace(/_/g, "/");
1062
+ function fromBase64Url(b64url4) {
1063
+ const std = b64url4.replace(/-/g, "+").replace(/_/g, "/");
1064
1064
  return fromBase64(std + "=".repeat((4 - std.length % 4) % 4));
1065
1065
  }
1066
1066
  function toBase64Url(bytes2) {
@@ -160096,6 +160096,122 @@ var init_pinned_read = __esm({
160096
160096
  }
160097
160097
  });
160098
160098
 
160099
+ // ../../core/serve-runtime/src/member-exchange.ts
160100
+ function hopAllowed(url, firstHost) {
160101
+ if (url.protocol !== "https:" || url.port !== "" && url.port !== "443" || url.username || url.password) return false;
160102
+ const host = url.hostname.toLowerCase();
160103
+ return host === firstHost || host === "wix.com" || host.endsWith(".wix.com") || host.endsWith(".wixsite.com") || host === "wixapis.com" || host.endsWith(".wixapis.com");
160104
+ }
160105
+ async function exchangeMemberSession(input, fetchImpl = fetch, random = randomBytes6, now = Date.now, redirectUri = REGISTERED_REDIRECT_URI) {
160106
+ const { clientId, sessionToken } = input;
160107
+ if (typeof sessionToken !== "string" || !sessionToken || sessionToken.length > MAX_SESSION_TOKEN_LENGTH) {
160108
+ return { ok: false, code: "bad_request" };
160109
+ }
160110
+ const call = async (url2, init) => {
160111
+ try {
160112
+ return await fetchImpl(url2, { ...init, signal: AbortSignal.timeout(STEP_TIMEOUT_MS) });
160113
+ } catch {
160114
+ return null;
160115
+ }
160116
+ };
160117
+ const json8 = async (res) => {
160118
+ try {
160119
+ const v2 = await res.json();
160120
+ return v2 && typeof v2 === "object" ? v2 : {};
160121
+ } catch {
160122
+ return {};
160123
+ }
160124
+ };
160125
+ let visitor;
160126
+ try {
160127
+ visitor = await mintAnonymousVisitor(clientId, (u2, i2) => call(String(u2), i2 ?? {}).then((r2) => {
160128
+ if (!r2) throw new Error("unreachable");
160129
+ return r2;
160130
+ }));
160131
+ } catch (e2) {
160132
+ return { ok: false, code: e2?.message === "unreachable" ? "unreachable" : "visitor_token_failed" };
160133
+ }
160134
+ const verifier = b64url2(random(32));
160135
+ const challenge = b64url2(sha256(verifier));
160136
+ const state = b64url2(random(8));
160137
+ const rsRes = await call(`${WIX_API}/_api/redirects-api/v1/redirect-session`, {
160138
+ method: "POST",
160139
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${visitor}` },
160140
+ body: JSON.stringify({ auth: { authRequest: {
160141
+ clientId,
160142
+ responseType: "code",
160143
+ responseMode: "fragment",
160144
+ redirectUri,
160145
+ scope: "offline_access",
160146
+ state,
160147
+ nonce: state,
160148
+ codeChallenge: challenge,
160149
+ codeChallengeMethod: "S256",
160150
+ sessionToken
160151
+ }, prompt: "none" } })
160152
+ });
160153
+ if (!rsRes) return { ok: false, code: "unreachable" };
160154
+ const rs2 = await json8(rsRes);
160155
+ const fullUrl = rs2.redirectSession?.fullUrl;
160156
+ if (!rsRes.ok || typeof fullUrl !== "string") return { ok: false, code: "redirect_session_failed", status: rsRes.status };
160157
+ let url;
160158
+ try {
160159
+ url = new URL(fullUrl);
160160
+ } catch {
160161
+ return { ok: false, code: "redirect_session_failed", status: rsRes.status };
160162
+ }
160163
+ const firstHost = url.hostname.toLowerCase();
160164
+ let code;
160165
+ let lastStatus;
160166
+ for (let hop = 0; hop < MAX_HOPS; hop++) {
160167
+ if (!hopAllowed(url, firstHost)) return { ok: false, code: "authorize_host_refused" };
160168
+ const res = await call(url.toString(), { method: "GET", redirect: "manual", headers: { "User-Agent": "Mozilla/5.0" } });
160169
+ if (!res) return { ok: false, code: "unreachable" };
160170
+ lastStatus = res.status;
160171
+ const location = res.headers.get("location");
160172
+ if (!location) return { ok: false, code: res.status >= 400 ? "authorize_refused" : "authorize_no_code", status: res.status };
160173
+ if (location.startsWith(redirectUri)) {
160174
+ const params = new URLSearchParams(location.slice(redirectUri.length).replace(/^[?#]/, ""));
160175
+ if (params.get("state") !== state) return { ok: false, code: "authorize_state_mismatch" };
160176
+ code = params.get("code") ?? void 0;
160177
+ break;
160178
+ }
160179
+ try {
160180
+ url = new URL(location, url);
160181
+ } catch {
160182
+ return { ok: false, code: "authorize_no_code", status: res.status };
160183
+ }
160184
+ }
160185
+ if (!code) return { ok: false, code: "authorize_no_code", ...lastStatus !== void 0 ? { status: lastStatus } : {} };
160186
+ const tokRes = await call(`${WIX_API}/oauth2/token`, {
160187
+ method: "POST",
160188
+ headers: { "Content-Type": "application/json" },
160189
+ body: JSON.stringify({ clientId, grantType: "authorization_code", code, codeVerifier: verifier, redirectUri })
160190
+ });
160191
+ if (!tokRes) return { ok: false, code: "unreachable" };
160192
+ const tok = await json8(tokRes);
160193
+ if (!tokRes.ok || typeof tok.access_token !== "string" || !tok.access_token) return { ok: false, code: "token_exchange_failed", status: tokRes.status };
160194
+ const expiresIn = typeof tok.expires_in === "number" ? tok.expires_in : Number(tok.expires_in);
160195
+ return { ok: true, accessToken: tok.access_token, expiresAt: now() + (Number.isFinite(expiresIn) && expiresIn > 0 ? expiresIn : 3600) * 1e3 };
160196
+ }
160197
+ var REGISTERED_REDIRECT_URI, MAX_HOPS, STEP_TIMEOUT_MS, MAX_SESSION_TOKEN_LENGTH, b64url2, randomBytes6;
160198
+ var init_member_exchange = __esm({
160199
+ "../../core/serve-runtime/src/member-exchange.ts"() {
160200
+ init_sha256();
160201
+ init_wix_bridge();
160202
+ REGISTERED_REDIRECT_URI = "himalaya-appsmith://oauth/callback";
160203
+ MAX_HOPS = 8;
160204
+ STEP_TIMEOUT_MS = 8e3;
160205
+ MAX_SESSION_TOKEN_LENGTH = 4096;
160206
+ b64url2 = (bytes2) => {
160207
+ let s2 = "";
160208
+ for (const b2 of bytes2) s2 += String.fromCharCode(b2);
160209
+ return btoa(s2).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
160210
+ };
160211
+ randomBytes6 = (n2) => globalThis.crypto.getRandomValues(new Uint8Array(n2));
160212
+ }
160213
+ });
160214
+
160099
160215
  // ../../core/serve-runtime/package-share.ts
160100
160216
  function parseStored(bytes2, id) {
160101
160217
  if (!bytes2) return null;
@@ -160930,6 +161046,32 @@ ${releaseId}`;
160930
161046
  }
160931
161047
  return new Response(upstream.body, { status: upstream.status, headers: responseHeaders });
160932
161048
  }
161049
+ if (request.method === "POST" && path2 === "/v1/__webwix/member-exchange") {
161050
+ const noStore = { "cache-control": "no-store" };
161051
+ if (opts.webwixBridge === false) return json5(503, { error: "webwix_bridge_disabled" }, noStore);
161052
+ if (!opts.previewTokenSecret) return json5(503, { error: "preview_token_unavailable" }, noStore);
161053
+ const exchangeApp = resolveApp(request, url);
161054
+ if (!exchangeApp) return json5(400, { error: "app_required" }, noStore);
161055
+ const exchangePin = resolvePin(request, url);
161056
+ if (!exchangePin || !resolvePreviewToken(request, url)) return json5(403, { error: "draft_preview_required" }, noStore);
161057
+ const exchangeCfg = await appConfigFor(request, url, exchangeApp);
161058
+ if (!exchangeCfg.ok) return exchangeCfg.response;
161059
+ if ((await manifest(exchangeApp))?.releaseId === exchangePin || await isRingRelease(exchangeApp, exchangePin)) {
161060
+ return json5(403, { error: "draft_preview_required" }, noStore);
161061
+ }
161062
+ const exchangeClient = wixClientIdOf(utf8Decode(exchangeCfg.bytes));
161063
+ if ("error" in exchangeClient) return json5(501, { error: `member_exchange_${exchangeClient.error}` }, noStore);
161064
+ let exchangeBody;
161065
+ try {
161066
+ exchangeBody = await request.json();
161067
+ } catch {
161068
+ return json5(400, { error: "bad_request" }, noStore);
161069
+ }
161070
+ if (!exchangeBody || typeof exchangeBody !== "object") return json5(400, { error: "bad_request" }, noStore);
161071
+ const exchanged = await exchangeMemberSession({ clientId: exchangeClient.clientId, sessionToken: exchangeBody.sessionToken }, webwixFetch);
161072
+ if (exchanged.ok) return json5(200, { accessToken: exchanged.accessToken, expiresAt: exchanged.expiresAt }, noStore);
161073
+ return json5(exchanged.code === "bad_request" ? 400 : 502, { error: exchanged.code, ...exchanged.status !== void 0 ? { status: exchanged.status } : {} }, noStore);
161074
+ }
160933
161075
  if (request.method === "POST" && path2 === "/v1/__webwix/call") {
160934
161076
  const served = { rung: "none" };
160935
161077
  let status = 500;
@@ -161546,6 +161688,7 @@ var init_server2 = __esm({
161546
161688
  init_base64();
161547
161689
  init_contract();
161548
161690
  init_pinned_read();
161691
+ init_member_exchange();
161549
161692
  init_package_share();
161550
161693
  init_wix_bridge();
161551
161694
  init_account_rung();
@@ -162598,14 +162741,14 @@ var init_embedded_bundles = __esm({
162598
162741
  // ../store-release/register-bundle.ts
162599
162742
  import { readFileSync as readFileSync88 } from "node:fs";
162600
162743
  import { createPrivateKey as createPrivateKey4, sign as sign2 } from "node:crypto";
162601
- function b64url2(b2) {
162744
+ function b64url3(b2) {
162602
162745
  return Buffer.from(b2).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
162603
162746
  }
162604
162747
  function ascJwt(keyId, issuerId, p8, now) {
162605
- const header = b64url2(JSON.stringify({ alg: "ES256", kid: keyId, typ: "JWT" }));
162606
- const payload = b64url2(JSON.stringify({ iss: issuerId, iat: now, exp: now + 1200, aud: "appstoreconnect-v1" }));
162748
+ const header = b64url3(JSON.stringify({ alg: "ES256", kid: keyId, typ: "JWT" }));
162749
+ const payload = b64url3(JSON.stringify({ iss: issuerId, iat: now, exp: now + 1200, aud: "appstoreconnect-v1" }));
162607
162750
  const key3 = createPrivateKey4(p8);
162608
- const sig = b64url2(sign2("sha256", Buffer.from(`${header}.${payload}`), { key: key3, dsaEncoding: "ieee-p1363" }));
162751
+ const sig = b64url3(sign2("sha256", Buffer.from(`${header}.${payload}`), { key: key3, dsaEncoding: "ieee-p1363" }));
162609
162752
  return `${header}.${payload}.${sig}`;
162610
162753
  }
162611
162754
  function bundleIdBody(identifier, name, platform = "IOS") {
@@ -167782,7 +167925,7 @@ var init_connector_token = __esm({
167782
167925
  });
167783
167926
 
167784
167927
  // ../../core/functions-secrets/src/vault.ts
167785
- import { createCipheriv, createDecipheriv as createDecipheriv2, randomBytes as randomBytes6 } from "node:crypto";
167928
+ import { createCipheriv, createDecipheriv as createDecipheriv2, randomBytes as randomBytes7 } from "node:crypto";
167786
167929
  import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
167787
167930
  import { dirname as dirname44 } from "node:path";
167788
167931
  function createJsonSecretStore(filePath) {
@@ -167840,7 +167983,7 @@ function createSecretVault(options) {
167840
167983
  environment: input.environment,
167841
167984
  name: input.name,
167842
167985
  version: input.version,
167843
- iv: randomBytes6(12).toString("base64url"),
167986
+ iv: randomBytes7(12).toString("base64url"),
167844
167987
  ciphertext: "",
167845
167988
  authTag: ""
167846
167989
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1458.0",
3
+ "version": "0.1459.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": "9dd290be2b59a0845d75b156a968a16e615c0d3de4e9dc4a0f01cda6"
74
+ "falconPackageHash": "db96f8e1d9f3f0a55120ae97f89b4211fed249d7a3f98225dc9269b1"
75
75
  }