@wix/himalaya-cli 0.1045.0 → 0.1046.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.
@@ -19,7 +19,7 @@ export interface ExperimentResult {
19
19
  variant: string;
20
20
  }
21
21
  export declare const experiments: {
22
- /** Conduct a Petri experiment; returns the resolved variant (or `fallback`). */
22
+ /** The app's served variant for `spec` (`himi flags`), or `fallback` when none is assigned. */
23
23
  conduct(spec: string, fallback?: string): Promise<ExperimentResult>;
24
24
  /** Boolean convenience — true when the variant is exactly "true". */
25
25
  isEnabled(spec: string): Promise<boolean>;
@@ -32,7 +32,7 @@ export declare const experiments: {
32
32
  }>;
33
33
  };
34
34
  export declare const flags: {
35
- /** Whether a Petri feature-toggle spec is ON. */
35
+ /** Whether the app's served flag `spec` is ON (variant `on`/`true`/`new`), else `fallback`. */
36
36
  isEnabled(spec: string, fallback?: boolean): Promise<boolean>;
37
37
  /** A toggle's raw value (variant string) for non-boolean specs. */
38
38
  value(spec: string, fallback?: string): Promise<string>;
@@ -62,40 +62,15 @@ function flights() {
62
62
  function dropConductFlights() {
63
63
  flights()?.inflight.clear();
64
64
  }
65
- var conductedReal = (value) => ({ value, cacheable: true });
66
- var conductedSeam = (value) => ({ value, cacheable: false });
67
- async function l2Get(ns, spec) {
68
- try {
69
- const r = await call("conductedGet", { door: ns, spec });
70
- return {
71
- value: r?.hit && typeof r.value === "string" && r.value.length > 0 ? r.value : null,
72
- scope: typeof r?.scope === "string" && r.scope.length > 0 ? r.scope : null
73
- };
74
- } catch {
75
- return { value: null, scope: null };
76
- }
77
- }
78
- async function l2Put(ns, spec, value, scope) {
79
- try {
80
- await call("conductedPut", { door: ns, spec, value, scope });
81
- } catch {
82
- }
83
- }
84
65
  async function conductCached(ns, spec, fallback, resolve) {
85
66
  const f = flights();
86
- if (!f) return (await resolve()).value;
67
+ if (!f) return resolve();
87
68
  const flightKey = JSON.stringify([ns, spec, fallback]);
88
69
  const pending = f.inflight.get(flightKey);
89
70
  if (pending) return pending;
90
71
  const task = (async () => {
91
72
  try {
92
- const { value: cached, scope } = await l2Get(ns, spec);
93
- if (cached !== null) return cached;
94
- const { value, cacheable } = await resolve();
95
- if (cacheable && value !== null && value.length > 0 && scope !== null) {
96
- await l2Put(ns, spec, value, scope);
97
- }
98
- return value;
73
+ return await resolve();
99
74
  } finally {
100
75
  f.inflight.delete(flightKey);
101
76
  }
@@ -103,31 +78,16 @@ async function conductCached(ns, spec, fallback, resolve) {
103
78
  f.inflight.set(flightKey, task);
104
79
  return task;
105
80
  }
106
- var PETRI_CONDUCT = "/_api/wix-petri-webapp/v1/conductExperiment";
107
81
  async function resolveExperiment(spec, fallback) {
108
- if (isMemberReal("experiments")) {
109
- try {
110
- const r2 = await realWix("POST", PETRI_CONDUCT, { key: spec, fallbackValue: fallback });
111
- if (typeof r2?.value === "string") return conductedReal(r2.value);
112
- } catch {
113
- }
114
- }
115
82
  const r = await call("experimentsConduct", { spec, fallback });
116
- return conductedSeam(typeof r?.variant === "string" ? r.variant : null);
83
+ return typeof r?.variant === "string" ? r.variant : null;
117
84
  }
118
85
  async function resolveFlag(spec, fallback) {
119
- if (isMemberReal("flags")) {
120
- try {
121
- const r2 = await realWix("POST", PETRI_CONDUCT, { key: spec, fallbackValue: String(fallback) });
122
- if (typeof r2?.value === "string") return conductedReal(r2.value);
123
- } catch {
124
- }
125
- }
126
86
  const r = await call("flagsIsEnabled", { spec, fallback });
127
- return conductedSeam(typeof r?.enabled === "boolean" ? String(r.enabled) : null);
87
+ return typeof r?.enabled === "boolean" ? String(r.enabled) : null;
128
88
  }
129
89
  var experiments = {
130
- /** Conduct a Petri experiment; returns the resolved variant (or `fallback`). */
90
+ /** The app's served variant for `spec` (`himi flags`), or `fallback` when none is assigned. */
131
91
  async conduct(spec, fallback = "false") {
132
92
  const resolved = await conductCached("experiments", spec, fallback, () => resolveExperiment(spec, fallback));
133
93
  return { spec, variant: resolved ?? fallback };
@@ -146,7 +106,7 @@ var experiments = {
146
106
  }
147
107
  };
148
108
  var flags = {
149
- /** Whether a Petri feature-toggle spec is ON. */
109
+ /** Whether the app's served flag `spec` is ON (variant `on`/`true`/`new`), else `fallback`. */
150
110
  async isEnabled(spec, fallback = false) {
151
111
  const resolved = await conductCached("flags", spec, String(fallback), () => resolveFlag(spec, fallback));
152
112
  if (resolved === null) return fallback;
@@ -186,25 +146,11 @@ var i18n = {
186
146
  var ping = {
187
147
  /** Register the device's push token with Wix Ping. */
188
148
  async register() {
189
- if (isMemberReal("ping")) {
190
- try {
191
- const r2 = await realWix("POST", "/_api/ping-webapp/v1/registrations", {});
192
- if (r2 && typeof r2.registered === "boolean") return { registered: r2.registered, token: r2.token ?? "" };
193
- } catch {
194
- }
195
- }
196
149
  const r = await call("pingRegister");
197
150
  return { registered: r?.registered ?? false, token: r?.token ?? "" };
198
151
  },
199
152
  /** Current Ping registration status (no network). */
200
153
  async status() {
201
- if (isMemberReal("ping")) {
202
- try {
203
- const r2 = await realWix("GET", "/_api/ping-webapp/v1/registrations");
204
- if (r2 && typeof r2.registered === "boolean") return { registered: r2.registered, token: r2.token ?? "" };
205
- } catch {
206
- }
207
- }
208
154
  const r = await call("pingStatus");
209
155
  return { registered: r?.registered ?? false, token: r?.token ?? "" };
210
156
  }
@@ -212,13 +158,6 @@ var ping = {
212
158
  var deeplink = {
213
159
  /** Resolve a deferred (post-install) deep link via Wix Jot. Null when none. */
214
160
  async resolveDeferred() {
215
- if (isMemberReal("deeplink")) {
216
- try {
217
- const r2 = await realWix("GET", "/_api/app-link-server/v1/deferred-deep-link");
218
- if (r2) return { link: r2.link && r2.link.length > 0 ? r2.link : null };
219
- } catch {
220
- }
221
- }
222
161
  const r = await call("deeplinkResolveDeferred");
223
162
  return { link: r?.link && r.link.length > 0 ? r.link : null };
224
163
  }
package/dist/cli.mjs CHANGED
@@ -18830,6 +18830,204 @@ ${cookieHeader}`);
18830
18830
  }
18831
18831
  });
18832
18832
 
18833
+ // ../../core/ts/src/flags-engine.ts
18834
+ function bucket(key2) {
18835
+ const digest2 = sha1(key2);
18836
+ const n = (digest2[0] << 24 | digest2[1] << 16 | digest2[2] << 8 | digest2[3]) >>> 0;
18837
+ return n % 1e4;
18838
+ }
18839
+ function attrValue(ctx, attribute) {
18840
+ switch (attribute) {
18841
+ case "platform":
18842
+ return ctx.platform;
18843
+ case "appVersion":
18844
+ return ctx.appVersion;
18845
+ case "locale":
18846
+ return ctx.locale;
18847
+ case "appId":
18848
+ return ctx.appId;
18849
+ case "userId":
18850
+ return ctx.userId;
18851
+ default:
18852
+ return ctx.custom?.[attribute];
18853
+ }
18854
+ }
18855
+ function clauseMatches(ctx, c) {
18856
+ const v = attrValue(ctx, c.attribute);
18857
+ switch (c.op) {
18858
+ case "eq":
18859
+ return v !== void 0 && c.values.includes(v);
18860
+ case "neq":
18861
+ return v === void 0 || !c.values.includes(v);
18862
+ case "in":
18863
+ return v !== void 0 && c.values.includes(v);
18864
+ case "contains":
18865
+ return v !== void 0 && c.values.some((needle) => v.includes(needle));
18866
+ default:
18867
+ return false;
18868
+ }
18869
+ }
18870
+ function ruleMatches(ctx, rule) {
18871
+ return rule.clauses.length > 0 && rule.clauses.every((c) => clauseMatches(ctx, c));
18872
+ }
18873
+ function variantForBucket(def, b) {
18874
+ const total = def.variants.reduce((s, v) => s + Math.max(0, v.weight), 0);
18875
+ if (total <= 0) return def.defaultVariant;
18876
+ const target = b / 1e4 * total;
18877
+ let acc = 0;
18878
+ for (const v of def.variants) {
18879
+ acc += Math.max(0, v.weight);
18880
+ if (target < acc) return v.key;
18881
+ }
18882
+ return def.variants[def.variants.length - 1].key;
18883
+ }
18884
+ function evaluate(def, ctx, override) {
18885
+ const base = { key: def.key, experimentId: def.experiment?.id };
18886
+ if (override) return { ...base, variant: override, reason: "override" };
18887
+ if (!def.enabled) return { ...base, variant: def.defaultVariant, reason: "disabled" };
18888
+ for (const rule of def.targeting ?? []) {
18889
+ if (ruleMatches(ctx, rule)) return { ...base, variant: rule.variant, reason: "targeting" };
18890
+ }
18891
+ const id = ctx.userId ?? ctx.sessionId;
18892
+ const seed2 = def.seed ?? def.key;
18893
+ const rollout = def.rolloutPercentage ?? 100;
18894
+ if (rollout < 100) {
18895
+ const gate = bucket(`${id}:${seed2}:rollout`);
18896
+ if (gate >= rollout * 100) return { ...base, variant: def.defaultVariant, reason: "default" };
18897
+ }
18898
+ const variant = variantForBucket(def, bucket(`${id}:${seed2}`));
18899
+ return { ...base, variant, reason: "rollout" };
18900
+ }
18901
+ function evaluateAll(defs, ctx, overrides) {
18902
+ const out = {};
18903
+ for (const def of defs) out[def.key] = evaluate(def, ctx, overrides?.[def.key]);
18904
+ return out;
18905
+ }
18906
+ function utf8(input) {
18907
+ return new TextEncoder().encode(input);
18908
+ }
18909
+ function sha1(input) {
18910
+ const bytes2 = typeof input === "string" ? utf8(input) : input;
18911
+ const bitLen = bytes2.length * 8;
18912
+ const padded = new Uint8Array(((bytes2.length + 9 + 63) / 64 | 0) * 64);
18913
+ padded.set(bytes2);
18914
+ padded[bytes2.length] = 128;
18915
+ const view = new DataView(padded.buffer);
18916
+ view.setUint32(padded.length - 8, Math.floor(bitLen / 4294967296));
18917
+ view.setUint32(padded.length - 4, bitLen >>> 0);
18918
+ let h0 = 1732584193, h1 = 4023233417, h2 = 2562383102, h3 = 271733878, h4 = 3285377520;
18919
+ const w = new Uint32Array(80);
18920
+ for (let off = 0; off < padded.length; off += 64) {
18921
+ for (let i = 0; i < 16; i++) w[i] = view.getUint32(off + i * 4);
18922
+ for (let i = 16; i < 80; i++) {
18923
+ const v = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16];
18924
+ w[i] = (v << 1 | v >>> 31) >>> 0;
18925
+ }
18926
+ let a = h0, b = h1, c = h2, d = h3, e = h4;
18927
+ for (let i = 0; i < 80; i++) {
18928
+ let f;
18929
+ let k;
18930
+ if (i < 20) {
18931
+ f = b & c | ~b & d;
18932
+ k = 1518500249;
18933
+ } else if (i < 40) {
18934
+ f = b ^ c ^ d;
18935
+ k = 1859775393;
18936
+ } else if (i < 60) {
18937
+ f = b & c | b & d | c & d;
18938
+ k = 2400959708;
18939
+ } else {
18940
+ f = b ^ c ^ d;
18941
+ k = 3395469782;
18942
+ }
18943
+ const t = ((a << 5 | a >>> 27) >>> 0) + (f >>> 0) + e + k + w[i] >>> 0;
18944
+ e = d;
18945
+ d = c;
18946
+ c = (b << 30 | b >>> 2) >>> 0;
18947
+ b = a;
18948
+ a = t;
18949
+ }
18950
+ h0 = h0 + a >>> 0;
18951
+ h1 = h1 + b >>> 0;
18952
+ h2 = h2 + c >>> 0;
18953
+ h3 = h3 + d >>> 0;
18954
+ h4 = h4 + e >>> 0;
18955
+ }
18956
+ const out = new Uint8Array(20);
18957
+ const outView = new DataView(out.buffer);
18958
+ outView.setUint32(0, h0);
18959
+ outView.setUint32(4, h1);
18960
+ outView.setUint32(8, h2);
18961
+ outView.setUint32(12, h3);
18962
+ outView.setUint32(16, h4);
18963
+ return out;
18964
+ }
18965
+ var init_flags_engine = __esm({
18966
+ "../../core/ts/src/flags-engine.ts"() {
18967
+ }
18968
+ });
18969
+
18970
+ // ../../core/serve-runtime/src/flag-assignments.ts
18971
+ function bad(error) {
18972
+ return new Response(JSON.stringify({ error }), { status: 400, headers: { "content-type": JSON_CT, "cache-control": "no-store" } });
18973
+ }
18974
+ function flagAssignmentsBody(app, defs, ctx, overrides, ttlSeconds = FLAG_ASSIGNMENTS_TTL_SECONDS) {
18975
+ const evalCtx = {
18976
+ sessionId: ctx.id,
18977
+ appId: app,
18978
+ ...ctx.platform ? { platform: ctx.platform } : {},
18979
+ ...ctx.appVersion ? { appVersion: ctx.appVersion } : {},
18980
+ ...ctx.locale ? { locale: ctx.locale } : {}
18981
+ };
18982
+ const byKey = new Map(defs.map((d) => [d.key, d]));
18983
+ const assignments = {};
18984
+ for (const [key2, a] of Object.entries(evaluateAll(defs, evalCtx, overrides))) {
18985
+ const value = byKey.get(key2)?.variants.find((v) => v.key === a.variant)?.value;
18986
+ assignments[key2] = {
18987
+ variant: a.variant,
18988
+ reason: a.reason,
18989
+ ...a.experimentId ? { experimentId: a.experimentId } : {},
18990
+ ...value !== void 0 ? { value } : {}
18991
+ };
18992
+ }
18993
+ return { app, id: ctx.id, assignments, ttlSeconds };
18994
+ }
18995
+ function flagAssignmentsResponse(request, app, defs, overrides, ttlSeconds = FLAG_ASSIGNMENTS_TTL_SECONDS) {
18996
+ if (request.method !== "GET" && request.method !== "HEAD") {
18997
+ return new Response(JSON.stringify({ error: "method_not_allowed" }), { status: 405, headers: { "content-type": JSON_CT } });
18998
+ }
18999
+ const url = new URL(request.url);
19000
+ const id = url.searchParams.get("id") ?? "";
19001
+ if (!id) return bad("missing_id");
19002
+ if (id.length > MAX_ID_LENGTH) return bad("id_too_long");
19003
+ const q = (k) => url.searchParams.get(k) || void 0;
19004
+ const body = JSON.stringify(flagAssignmentsBody(app, defs.filter(isEvaluable), {
19005
+ id,
19006
+ platform: q("platform"),
19007
+ appVersion: q("appVersion"),
19008
+ locale: q("locale")
19009
+ }, overrides, ttlSeconds));
19010
+ const etag = strongEtag(body);
19011
+ const headers2 = { "content-type": JSON_CT, etag, "cache-control": `private, max-age=${Math.min(ttlSeconds, 60)}` };
19012
+ if (request.headers.get("if-none-match") === etag) return new Response(null, { status: 304, headers: headers2 });
19013
+ return new Response(request.method === "HEAD" ? null : body, { status: 200, headers: headers2 });
19014
+ }
19015
+ function isEvaluable(d) {
19016
+ const x = d;
19017
+ return !!x && typeof x.key === "string" && Array.isArray(x.variants) && typeof x.defaultVariant === "string";
19018
+ }
19019
+ var FLAG_ASSIGNMENTS_PATH, FLAG_ASSIGNMENTS_TTL_SECONDS, MAX_ID_LENGTH, JSON_CT;
19020
+ var init_flag_assignments = __esm({
19021
+ "../../core/serve-runtime/src/flag-assignments.ts"() {
19022
+ init_flags_engine();
19023
+ init_contract();
19024
+ FLAG_ASSIGNMENTS_PATH = /^\/v1\/flags\/([^/]+)\/assignments$/;
19025
+ FLAG_ASSIGNMENTS_TTL_SECONDS = 300;
19026
+ MAX_ID_LENGTH = 256;
19027
+ JSON_CT = "application/json; charset=utf-8";
19028
+ }
19029
+ });
19030
+
18833
19031
  // ../../core/dev-server/src/images.ts
18834
19032
  import { createHash as createHash11 } from "node:crypto";
18835
19033
  function svgFor(productId, title, sku) {
@@ -32031,143 +32229,6 @@ var init_flags = __esm({
32031
32229
  }
32032
32230
  });
32033
32231
 
32034
- // ../../core/ts/src/flags-engine.ts
32035
- function bucket(key2) {
32036
- const digest2 = sha1(key2);
32037
- const n = (digest2[0] << 24 | digest2[1] << 16 | digest2[2] << 8 | digest2[3]) >>> 0;
32038
- return n % 1e4;
32039
- }
32040
- function attrValue(ctx, attribute) {
32041
- switch (attribute) {
32042
- case "platform":
32043
- return ctx.platform;
32044
- case "appVersion":
32045
- return ctx.appVersion;
32046
- case "locale":
32047
- return ctx.locale;
32048
- case "appId":
32049
- return ctx.appId;
32050
- case "userId":
32051
- return ctx.userId;
32052
- default:
32053
- return ctx.custom?.[attribute];
32054
- }
32055
- }
32056
- function clauseMatches(ctx, c) {
32057
- const v = attrValue(ctx, c.attribute);
32058
- switch (c.op) {
32059
- case "eq":
32060
- return v !== void 0 && c.values.includes(v);
32061
- case "neq":
32062
- return v === void 0 || !c.values.includes(v);
32063
- case "in":
32064
- return v !== void 0 && c.values.includes(v);
32065
- case "contains":
32066
- return v !== void 0 && c.values.some((needle) => v.includes(needle));
32067
- default:
32068
- return false;
32069
- }
32070
- }
32071
- function ruleMatches(ctx, rule) {
32072
- return rule.clauses.length > 0 && rule.clauses.every((c) => clauseMatches(ctx, c));
32073
- }
32074
- function variantForBucket(def, b) {
32075
- const total = def.variants.reduce((s, v) => s + Math.max(0, v.weight), 0);
32076
- if (total <= 0) return def.defaultVariant;
32077
- const target = b / 1e4 * total;
32078
- let acc = 0;
32079
- for (const v of def.variants) {
32080
- acc += Math.max(0, v.weight);
32081
- if (target < acc) return v.key;
32082
- }
32083
- return def.variants[def.variants.length - 1].key;
32084
- }
32085
- function evaluate(def, ctx, override) {
32086
- const base = { key: def.key, experimentId: def.experiment?.id };
32087
- if (override) return { ...base, variant: override, reason: "override" };
32088
- if (!def.enabled) return { ...base, variant: def.defaultVariant, reason: "disabled" };
32089
- for (const rule of def.targeting ?? []) {
32090
- if (ruleMatches(ctx, rule)) return { ...base, variant: rule.variant, reason: "targeting" };
32091
- }
32092
- const id = ctx.userId ?? ctx.sessionId;
32093
- const seed2 = def.seed ?? def.key;
32094
- const rollout = def.rolloutPercentage ?? 100;
32095
- if (rollout < 100) {
32096
- const gate = bucket(`${id}:${seed2}:rollout`);
32097
- if (gate >= rollout * 100) return { ...base, variant: def.defaultVariant, reason: "default" };
32098
- }
32099
- const variant = variantForBucket(def, bucket(`${id}:${seed2}`));
32100
- return { ...base, variant, reason: "rollout" };
32101
- }
32102
- function evaluateAll(defs, ctx, overrides) {
32103
- const out = {};
32104
- for (const def of defs) out[def.key] = evaluate(def, ctx, overrides?.[def.key]);
32105
- return out;
32106
- }
32107
- function utf8(input) {
32108
- return new TextEncoder().encode(input);
32109
- }
32110
- function sha1(input) {
32111
- const bytes2 = typeof input === "string" ? utf8(input) : input;
32112
- const bitLen = bytes2.length * 8;
32113
- const padded = new Uint8Array(((bytes2.length + 9 + 63) / 64 | 0) * 64);
32114
- padded.set(bytes2);
32115
- padded[bytes2.length] = 128;
32116
- const view = new DataView(padded.buffer);
32117
- view.setUint32(padded.length - 8, Math.floor(bitLen / 4294967296));
32118
- view.setUint32(padded.length - 4, bitLen >>> 0);
32119
- let h0 = 1732584193, h1 = 4023233417, h2 = 2562383102, h3 = 271733878, h4 = 3285377520;
32120
- const w = new Uint32Array(80);
32121
- for (let off = 0; off < padded.length; off += 64) {
32122
- for (let i = 0; i < 16; i++) w[i] = view.getUint32(off + i * 4);
32123
- for (let i = 16; i < 80; i++) {
32124
- const v = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16];
32125
- w[i] = (v << 1 | v >>> 31) >>> 0;
32126
- }
32127
- let a = h0, b = h1, c = h2, d = h3, e = h4;
32128
- for (let i = 0; i < 80; i++) {
32129
- let f;
32130
- let k;
32131
- if (i < 20) {
32132
- f = b & c | ~b & d;
32133
- k = 1518500249;
32134
- } else if (i < 40) {
32135
- f = b ^ c ^ d;
32136
- k = 1859775393;
32137
- } else if (i < 60) {
32138
- f = b & c | b & d | c & d;
32139
- k = 2400959708;
32140
- } else {
32141
- f = b ^ c ^ d;
32142
- k = 3395469782;
32143
- }
32144
- const t = ((a << 5 | a >>> 27) >>> 0) + (f >>> 0) + e + k + w[i] >>> 0;
32145
- e = d;
32146
- d = c;
32147
- c = (b << 30 | b >>> 2) >>> 0;
32148
- b = a;
32149
- a = t;
32150
- }
32151
- h0 = h0 + a >>> 0;
32152
- h1 = h1 + b >>> 0;
32153
- h2 = h2 + c >>> 0;
32154
- h3 = h3 + d >>> 0;
32155
- h4 = h4 + e >>> 0;
32156
- }
32157
- const out = new Uint8Array(20);
32158
- const outView = new DataView(out.buffer);
32159
- outView.setUint32(0, h0);
32160
- outView.setUint32(4, h1);
32161
- outView.setUint32(8, h2);
32162
- outView.setUint32(12, h3);
32163
- outView.setUint32(16, h4);
32164
- return out;
32165
- }
32166
- var init_flags_engine = __esm({
32167
- "../../core/ts/src/flags-engine.ts"() {
32168
- }
32169
- });
32170
-
32171
32232
  // ../../core/ts/src/launch-manifest.ts
32172
32233
  import Ajv2 from "ajv";
32173
32234
  var directiveObject, LAUNCH_MANIFEST_SCHEMA;
@@ -36233,6 +36294,23 @@ function createDevServer(opts = {}) {
36233
36294
  const k = readKit(kitM[1]);
36234
36295
  return k ? sendJson(res, 200, k, { "access-control-allow-origin": "*" }) : sendJson(res, 404, { error: "unknown_kit", id: kitM[1] }, { "access-control-allow-origin": "*" });
36235
36296
  }
36297
+ const flagAssignM = /^\/v1\/flags\/([^/?]+)\/assignments(?:\?|$)/.exec(url);
36298
+ if (flagAssignM && (req.method === "GET" || req.method === "HEAD")) {
36299
+ await state.flagSync.refresh(state.app?.dir, state.flagStore, Date.now());
36300
+ const ours = flagAssignM[1] === state.appName;
36301
+ const answer = flagAssignmentsResponse(
36302
+ new Request(`http://dev-server${url}`, {
36303
+ method: req.method,
36304
+ headers: typeof req.headers["if-none-match"] === "string" ? { "if-none-match": req.headers["if-none-match"] } : {}
36305
+ }),
36306
+ flagAssignM[1],
36307
+ ours ? state.flagStore.list() : [],
36308
+ ours ? currentFlagConfig(state)?.overrides : void 0
36309
+ );
36310
+ res.writeHead(answer.status, { ...Object.fromEntries(answer.headers), "access-control-allow-origin": "*" });
36311
+ res.end(answer.status === 200 && req.method === "GET" ? await answer.text() : void 0);
36312
+ return;
36313
+ }
36236
36314
  if (url.startsWith("/v1/revocations") && req.method === "GET") {
36237
36315
  let revoked = [];
36238
36316
  if (state.app) {
@@ -36455,6 +36533,7 @@ var init_src6 = __esm({
36455
36533
  init_wix_gateway();
36456
36534
  init_wix_member_login();
36457
36535
  init_wix_bridge();
36536
+ init_flag_assignments();
36458
36537
  init_images();
36459
36538
  init_l10n();
36460
36539
  init_l10n_catalog();
@@ -49467,7 +49546,7 @@ var init_wix_member_auth = __esm({
49467
49546
 
49468
49547
  // ../../core/serve/src/server.ts
49469
49548
  function json3(status, body, headers2 = {}) {
49470
- return new Response(JSON.stringify(body), { status, headers: { "content-type": JSON_CT, ...headers2 } });
49549
+ return new Response(JSON.stringify(body), { status, headers: { "content-type": JSON_CT2, ...headers2 } });
49471
49550
  }
49472
49551
  function isCookieAuthorizedPath(path2) {
49473
49552
  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;
@@ -49627,7 +49706,7 @@ ${releaseId}`;
49627
49706
  if (request.headers.get("if-none-match") === etag) {
49628
49707
  return new Response(null, { status: 304, headers: { etag, "cache-control": cache, ...vary } });
49629
49708
  }
49630
- return new Response(body, { status: 200, headers: { "content-type": JSON_CT, etag, "cache-control": cache, ...vary } });
49709
+ return new Response(body, { status: 200, headers: { "content-type": JSON_CT2, etag, "cache-control": cache, ...vary } });
49631
49710
  }
49632
49711
  async function authorizePinnedRead(request, url, app, releaseId, screenId) {
49633
49712
  const denied = await checkPinnedRead({
@@ -49822,7 +49901,7 @@ ${releaseId}`;
49822
49901
  });
49823
49902
  }
49824
49903
  if ((request.method === "GET" || request.method === "HEAD") && path2 === "/v1/__webwix/identity") {
49825
- const headers2 = { "content-type": JSON_CT, "cache-control": "no-store" };
49904
+ const headers2 = { "content-type": JSON_CT2, "cache-control": "no-store" };
49826
49905
  if (request.method === "HEAD") return new Response(null, { status: 200, headers: headers2 });
49827
49906
  const webwixDirect = opts.webwixDirect ? await opts.webwixDirect() === true : opts.webwixBridge !== false;
49828
49907
  if (memberAuthOn()) {
@@ -50050,7 +50129,7 @@ ${releaseId}`;
50050
50129
  }
50051
50130
  return new Response(listBody, {
50052
50131
  status: 200,
50053
- headers: { "content-type": JSON_CT, ...listHeaders }
50132
+ headers: { "content-type": JSON_CT2, ...listHeaders }
50054
50133
  });
50055
50134
  }
50056
50135
  if (path2 === "/v1/templates") {
@@ -50107,7 +50186,7 @@ ${releaseId}`;
50107
50186
  }
50108
50187
  return new Response(bytes2, {
50109
50188
  status: 200,
50110
- headers: { "content-type": JSON_CT, etag, ...cache, "x-himalaya-app": app }
50189
+ headers: { "content-type": JSON_CT2, etag, ...cache, "x-himalaya-app": app }
50111
50190
  });
50112
50191
  }
50113
50192
  if (path2 === "/v1/authoring-docs" || /^\/v1\/authoring-docs\/(spec|mobile-ux)$/.test(path2)) {
@@ -50372,7 +50451,7 @@ ${releaseId}`;
50372
50451
  if (request.headers.get("if-none-match") === etag2) return new Response(null, { status: 304, headers: headers2 });
50373
50452
  const body2 = await pinnedBody(app, meta2.descriptorHash, () => store.getScreen(app, screenId));
50374
50453
  if (!body2) return json3(404, { error: "screen_not_found", screenId });
50375
- return new Response(body2, { status: 200, headers: { "content-type": JSON_CT, ...headers2, "x-himalaya-app": app } });
50454
+ return new Response(body2, { status: 200, headers: { "content-type": JSON_CT2, ...headers2, "x-himalaya-app": app } });
50376
50455
  }
50377
50456
  const m = await manifest(app);
50378
50457
  const meta = m?.screens[screenId];
@@ -50385,7 +50464,7 @@ ${releaseId}`;
50385
50464
  if (!body) return json3(404, { error: "screen_not_found", screenId });
50386
50465
  return new Response(body, {
50387
50466
  status: 200,
50388
- headers: { "content-type": JSON_CT, etag, "cache-control": DOC_CACHE_CONTROL, "x-himalaya-app": app }
50467
+ headers: { "content-type": JSON_CT2, etag, "cache-control": DOC_CACHE_CONTROL, "x-himalaya-app": app }
50389
50468
  });
50390
50469
  }
50391
50470
  if (path2 === "/v1/widgets") {
@@ -50413,7 +50492,7 @@ ${releaseId}`;
50413
50492
  if (!body) return json3(404, { error: "widget_not_found", widgetId });
50414
50493
  return new Response(body, {
50415
50494
  status: 200,
50416
- headers: { "content-type": JSON_CT, etag, "cache-control": cache, ...vary, "x-himalaya-app": app }
50495
+ headers: { "content-type": JSON_CT2, etag, "cache-control": cache, ...vary, "x-himalaya-app": app }
50417
50496
  });
50418
50497
  }
50419
50498
  return json3(404, { error: "not_found" });
@@ -50440,7 +50519,7 @@ ${releaseId}`;
50440
50519
  return withCors(request, response);
50441
50520
  };
50442
50521
  }
50443
- var JSON_CT;
50522
+ var JSON_CT2;
50444
50523
  var init_server = __esm({
50445
50524
  "../../core/serve/src/server.ts"() {
50446
50525
  init_sha256();
@@ -50451,7 +50530,7 @@ var init_server = __esm({
50451
50530
  init_package_share();
50452
50531
  init_wix_bridge();
50453
50532
  init_wix_member_auth();
50454
- JSON_CT = "application/json; charset=utf-8";
50533
+ JSON_CT2 = "application/json; charset=utf-8";
50455
50534
  }
50456
50535
  });
50457
50536
 
@@ -50632,6 +50711,8 @@ function makeRunHandler(opts) {
50632
50711
  { "cache-control": "max-age=30" }
50633
50712
  );
50634
50713
  }
50714
+ const flagAssign = FLAG_ASSIGNMENTS_PATH.exec(path2);
50715
+ if (flagAssign) return flagAssignmentsResponse(request, flagAssign[1], []);
50635
50716
  if (path2.startsWith("/v1/flags/")) {
50636
50717
  return json4(200, { app: opts.app, definitions: {} }, { "cache-control": "no-store" });
50637
50718
  }
@@ -50703,6 +50784,7 @@ var json4;
50703
50784
  var init_run_handler = __esm({
50704
50785
  "../../core/serve/src/run-handler.ts"() {
50705
50786
  init_server();
50787
+ init_flag_assignments();
50706
50788
  init_preview2();
50707
50789
  init_himi_package();
50708
50790
  json4 = (status, body, headers2 = {}) => new Response(JSON.stringify(body), {
@@ -50841,21 +50923,21 @@ var init_preview_assets_generated = __esm({
50841
50923
  "../../packages/serve/src/preview-assets.generated.ts"() {
50842
50924
  init_preview_assets_format();
50843
50925
  PREVIEW_ASSET_MANIFEST = [
50844
- { key: "assets/index-C8FaHVmV.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1052014, sha256: "607f0eff78c1f286d1d94f6d6c08868e2deec8d39ace8176b374f0117026998a" },
50845
- { key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 1052022, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
50846
- { key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 1056632, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
50847
- { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1545216, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
50848
- { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1636140, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
50849
- { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1727124, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
50850
- { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1818104, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
50851
- { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1908976, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
50852
- { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 1999956, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
50853
- { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 2108592, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
50854
- { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 2217676, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
50855
- { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 2326724, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
50856
- { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 2434424, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
50857
- { key: "index.html", contentType: "text/html; charset=utf-8", offset: 2522532, length: 4947, sha256: "3fd26f396a5b472e603185fb99d5b905f37b98615b2bf95456e4e9b03ae05429" },
50858
- { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 2527479, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
50926
+ { key: "assets/index-DT6bRpY_.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1055972, sha256: "3a52c8395a6509cfe2cae8036024b987cd3361095ff5450bfd7a9efa0123850b" },
50927
+ { key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 1055980, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
50928
+ { key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 1060590, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
50929
+ { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1549174, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
50930
+ { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1640098, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
50931
+ { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1731082, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
50932
+ { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1822062, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
50933
+ { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1912934, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
50934
+ { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 2003914, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
50935
+ { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 2112550, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
50936
+ { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 2221634, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
50937
+ { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 2330682, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
50938
+ { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 2438382, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
50939
+ { key: "index.html", contentType: "text/html; charset=utf-8", offset: 2526490, length: 4947, sha256: "a9dcd2ec33b7ea5cee46b0a1f37f926678dd6939b442e3d50bff0101f0fe63ba" },
50940
+ { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 2531437, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
50859
50941
  ];
50860
50942
  }
50861
50943
  });
Binary file
@@ -3463,13 +3463,13 @@
3463
3463
  "name": "experiments",
3464
3464
  "kind": "const",
3465
3465
  "jsdoc": "",
3466
- "decl": "export const experiments = {\n /** Conduct a Petri experiment; returns the resolved variant (or `fallback`). */\n async conduct(spec: string, fallback = \"false\"): Promise<ExperimentResult> {\n const resolved = await conductCached(\"experiments\", spec, fallback, () => resolveExperiment(spec, fallback));\n return { spec, variant: resolved ?? fallback };\n },\n /** Boolean convenience — true when the variant is exactly \"true\". */\n async isEnabled(spec: string): Promise<boolean> {\n return (await experiments.conduct(spec, \"false\")).variant === \"true\";\n },\n /** Report A/B exposure for `spec`/`variant` — emits the platform's\n * `experiment_exposed` telemetry so outcome events attribute to the variant.\n * (Symphony relies on server-side conduction; this is the generalized app-side\n * exposure hook.) */\n async exposure(spec: string, variant: string): Promise<{ ok: boolean }> {\n const r = await call<{ ok?: boolean }>(\"experimentsExposure\", { spec, variant });\n return { ok: r?.ok ?? false };\n },\n};"
3466
+ "decl": "export const experiments = {\n /** The app's served variant for `spec` (`himi flags`), or `fallback` when none is assigned. */\n async conduct(spec: string, fallback = \"false\"): Promise<ExperimentResult> {\n const resolved = await conductCached(\"experiments\", spec, fallback, () => resolveExperiment(spec, fallback));\n return { spec, variant: resolved ?? fallback };\n },\n /** Boolean convenience — true when the variant is exactly \"true\". */\n async isEnabled(spec: string): Promise<boolean> {\n return (await experiments.conduct(spec, \"false\")).variant === \"true\";\n },\n /** Report A/B exposure for `spec`/`variant` — emits the platform's\n * `experiment_exposed` telemetry so outcome events attribute to the variant.\n * (Symphony relies on server-side conduction; this is the generalized app-side\n * exposure hook.) */\n async exposure(spec: string, variant: string): Promise<{ ok: boolean }> {\n const r = await call<{ ok?: boolean }>(\"experimentsExposure\", { spec, variant });\n return { ok: r?.ok ?? false };\n },\n};"
3467
3467
  },
3468
3468
  {
3469
3469
  "name": "flags",
3470
3470
  "kind": "const",
3471
3471
  "jsdoc": "",
3472
- "decl": "export const flags = {\n /** Whether a Petri feature-toggle spec is ON. */\n async isEnabled(spec: string, fallback = false): Promise<boolean> {\n const resolved = await conductCached(\"flags\", spec, String(fallback), () => resolveFlag(spec, fallback));\n if (resolved === null) return fallback;\n return resolved === \"true\" || resolved === \"new\";\n },\n /** A toggle's raw value (variant string) for non-boolean specs. */\n async value(spec: string, fallback = \"\"): Promise<string> {\n const r = await call<{ value?: string }>(\"flagsValue\", { spec, fallback });\n return r?.value ?? fallback;\n },\n /** All known toggle states (dev/diagnostic). */\n async all(): Promise<Record<string, string>> {\n const r = await call<{ flags?: Record<string, string> }>(\"flagsAll\");\n return r?.flags && typeof r.flags === \"object\" ? r.flags : {};\n },\n};"
3472
+ "decl": "export const flags = {\n /** Whether the app's served flag `spec` is ON (variant `on`/`true`/`new`), else `fallback`. */\n async isEnabled(spec: string, fallback = false): Promise<boolean> {\n const resolved = await conductCached(\"flags\", spec, String(fallback), () => resolveFlag(spec, fallback));\n if (resolved === null) return fallback;\n return resolved === \"true\" || resolved === \"new\";\n },\n /** A toggle's raw value (variant string) for non-boolean specs. */\n async value(spec: string, fallback = \"\"): Promise<string> {\n const r = await call<{ value?: string }>(\"flagsValue\", { spec, fallback });\n return r?.value ?? fallback;\n },\n /** All known toggle states (dev/diagnostic). */\n async all(): Promise<Record<string, string>> {\n const r = await call<{ flags?: Record<string, string> }>(\"flagsAll\");\n return r?.flags && typeof r.flags === \"object\" ? r.flags : {};\n },\n};"
3473
3473
  },
3474
3474
  {
3475
3475
  "name": "i18n",
@@ -3487,13 +3487,13 @@
3487
3487
  "name": "ping",
3488
3488
  "kind": "const",
3489
3489
  "jsdoc": "",
3490
- "decl": "export const ping = {\n /** Register the device's push token with Wix Ping. */\n async register(): Promise<PingRegistration> {\n if (isMemberReal(\"ping\")) {\n try {\n const r = await realWix<{ registered?: boolean; token?: string }>(\"POST\", \"/_api/ping-webapp/v1/registrations\", {});\n if (r && typeof r.registered === \"boolean\") return { registered: r.registered, token: r.token ?? \"\" };\n } catch { /* fall through to the dev seam */ }\n }\n const r = await call<{ registered?: boolean; token?: string }>(\"pingRegister\");\n return { registered: r?.registered ?? false, token: r?.token ?? \"\" };\n },\n /** Current Ping registration status (no network). */\n async status(): Promise<PingRegistration> {\n if (isMemberReal(\"ping\")) {\n try {\n const r = await realWix<{ registered?: boolean; token?: string }>(\"GET\", \"/_api/ping-webapp/v1/registrations\");\n if (r && typeof r.registered === \"boolean\") return { registered: r.registered, token: r.token ?? \"\" };\n } catch { /* fall through to the dev seam */ }\n }\n const r = await call<{ registered?: boolean; token?: string }>(\"pingStatus\");\n return { registered: r?.registered ?? false, token: r?.token ?? \"\" };\n },\n};"
3490
+ "decl": "export const ping = {\n /** Register the device's push token with Wix Ping. */\n async register(): Promise<PingRegistration> {\n const r = await call<{ registered?: boolean; token?: string }>(\"pingRegister\");\n return { registered: r?.registered ?? false, token: r?.token ?? \"\" };\n },\n /** Current Ping registration status (no network). */\n async status(): Promise<PingRegistration> {\n const r = await call<{ registered?: boolean; token?: string }>(\"pingStatus\");\n return { registered: r?.registered ?? false, token: r?.token ?? \"\" };\n },\n};"
3491
3491
  },
3492
3492
  {
3493
3493
  "name": "deeplink",
3494
3494
  "kind": "const",
3495
3495
  "jsdoc": "",
3496
- "decl": "export const deeplink = {\n /** Resolve a deferred (post-install) deep link via Wix Jot. Null when none. */\n async resolveDeferred(): Promise<{ link: string | null }> {\n if (isMemberReal(\"deeplink\")) {\n try {\n const r = await realWix<{ link?: string }>(\"GET\", \"/_api/app-link-server/v1/deferred-deep-link\");\n if (r) return { link: r.link && r.link.length > 0 ? r.link : null };\n } catch { /* fall through to the dev seam */ }\n }\n const r = await call<{ link?: string }>(\"deeplinkResolveDeferred\");\n return { link: r?.link && r.link.length > 0 ? r.link : null };\n },\n};"
3496
+ "decl": "export const deeplink = {\n /** Resolve a deferred (post-install) deep link via Wix Jot. Null when none. */\n async resolveDeferred(): Promise<{ link: string | null }> {\n const r = await call<{ link?: string }>(\"deeplinkResolveDeferred\");\n return { link: r?.link && r.link.length > 0 ? r.link : null };\n },\n};"
3497
3497
  },
3498
3498
  {
3499
3499
  "name": "SignedInstanceStatus",
@@ -26,7 +26,7 @@ import { bi, experiments, flags, i18n, auth, monitoring } from "@himalaya/wix-pl
26
26
  await bi.pageView("home");
27
27
  await bi.click("cta_start", "home");
28
28
 
29
- // experiments (Petri) / flags
29
+ // experiments / flags — the app's served flags (`himi flags`), never Wix Petri
30
30
  const variant = await experiments.conduct("specs.ai", "false"); // → { spec, variant }
31
31
  if (await flags.isEnabled("specs.newCheckout")) { /* … */ }
32
32
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1045.0",
3
+ "version": "0.1046.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": [
@@ -65,5 +65,5 @@
65
65
  "artifactId": "himalaya-cli"
66
66
  }
67
67
  },
68
- "falconPackageHash": "0a575418cdf281d15de4e62af6654a6d47a91cf26467dad0a437484b"
68
+ "falconPackageHash": "920a07437cf238c0bf1e34b799a4fe38573b57c6da92541fc2836079"
69
69
  }