@wix/himalaya-cli 0.1117.0 → 0.1119.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/core/dev-server/src/app-module.d.ts +2 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/wix-cache-defaults.generated.d.ts +2 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/wix-cache-policy.d.ts +21 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +9 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +1 -0
- package/dist/cli.mjs +513 -43
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/himi-mcp.md +3 -1
- package/guides/push-cli-onboarding.md +33 -0
- package/package.json +2 -2
- package/templates/beauty-salon/tier5-src/himi-store-product/index.ts +112 -39
- package/templates/branded-lite/tier5-src/himi-store-product/index.ts +112 -39
- package/templates/gym-fitness/tier5-src/himi-store-product/index.ts +112 -39
- package/templates/portfolio-creative/tier5-src/himi-store-product/index.ts +112 -39
- package/templates/retail-store/tier5-src/himi-store-product/index.ts +112 -39
package/dist/cli.mjs
CHANGED
|
@@ -13266,12 +13266,12 @@ function stripBrandFromIdiom(tokens) {
|
|
|
13266
13266
|
for (const key2 of BRAND_COLOR_TOKENS) delete colors[key2];
|
|
13267
13267
|
if (Object.keys(colors).length === 0) delete o.colors;
|
|
13268
13268
|
}
|
|
13269
|
-
const
|
|
13270
|
-
const glow =
|
|
13269
|
+
const shadows2 = o.shadows;
|
|
13270
|
+
const glow = shadows2 && typeof shadows2 === "object" && !Array.isArray(shadows2) ? shadows2[BRAND_GLOW_SHADOW] : void 0;
|
|
13271
13271
|
if (glow && typeof glow === "object" && !Array.isArray(glow) && "color" in glow) {
|
|
13272
13272
|
delete glow.color;
|
|
13273
|
-
if (Object.keys(glow).length === 0) delete
|
|
13274
|
-
if (Object.keys(
|
|
13273
|
+
if (Object.keys(glow).length === 0) delete shadows2[BRAND_GLOW_SHADOW];
|
|
13274
|
+
if (Object.keys(shadows2).length === 0) delete o.shadows;
|
|
13275
13275
|
}
|
|
13276
13276
|
}
|
|
13277
13277
|
}
|
|
@@ -13363,9 +13363,9 @@ function tokenColorIssues(dir, tokensPathOverride) {
|
|
|
13363
13363
|
error(`${tokensPath}: must be an object`);
|
|
13364
13364
|
return issues;
|
|
13365
13365
|
}
|
|
13366
|
-
const
|
|
13367
|
-
if (
|
|
13368
|
-
for (const [name, token] of Object.entries(
|
|
13366
|
+
const shadows2 = raw.shadows;
|
|
13367
|
+
if (shadows2 !== null && typeof shadows2 === "object" && !Array.isArray(shadows2)) {
|
|
13368
|
+
for (const [name, token] of Object.entries(shadows2)) {
|
|
13369
13369
|
const value = token?.color;
|
|
13370
13370
|
if (value === void 0) continue;
|
|
13371
13371
|
if (typeof value === "string" && isCanonicalHex(value)) continue;
|
|
@@ -19946,6 +19946,7 @@ function deriveAppMeta(name, m, platforms = {}) {
|
|
|
19946
19946
|
drawer: config.navigation?.drawer,
|
|
19947
19947
|
navKind: config.navigation?.navKind,
|
|
19948
19948
|
orientation: config.navigation?.orientation,
|
|
19949
|
+
cache: config.cache,
|
|
19949
19950
|
sidebar: config.navigation?.sidebar,
|
|
19950
19951
|
navLogicBundle: config.navigation?.navLogicBundle,
|
|
19951
19952
|
appIconBadgeSources: config.navigation?.appIconBadgeSources,
|
|
@@ -36087,6 +36088,108 @@ var init_render_fonts = __esm({
|
|
|
36087
36088
|
}
|
|
36088
36089
|
});
|
|
36089
36090
|
|
|
36091
|
+
// ../../core/dev-server/src/wix-cache-defaults.generated.ts
|
|
36092
|
+
var PLATFORM_DEFAULT_WIX_CACHE_RULES;
|
|
36093
|
+
var init_wix_cache_defaults_generated = __esm({
|
|
36094
|
+
"../../core/dev-server/src/wix-cache-defaults.generated.ts"() {
|
|
36095
|
+
PLATFORM_DEFAULT_WIX_CACHE_RULES = [
|
|
36096
|
+
{ method: "POST", pathPrefix: "/_api/bookings/v2/services/search", cacheable: true, ttl: 60, swr: 86400, tag: "bookings/services" },
|
|
36097
|
+
{ method: "POST", pathPrefix: "/blog/v3/categories/query", cacheable: true, ttl: 60, swr: 86400, tag: "blog" },
|
|
36098
|
+
{ method: "GET", pathPrefix: "/blog/v3/posts/", cacheable: true, ttl: 60, swr: 86400, tag: "blog" },
|
|
36099
|
+
{ method: "POST", pathPrefix: "/blog/v3/posts/query", cacheable: true, ttl: 60, swr: 86400, tag: "blog" },
|
|
36100
|
+
{ method: "GET", pathPrefix: "/bookings/v2/services/", cacheable: true, ttl: 60, swr: 86400, tag: "bookings/services" },
|
|
36101
|
+
{ method: "POST", pathPrefix: "/bookings/v2/services/query", cacheable: true, ttl: 60, swr: 86400, tag: "bookings/services" },
|
|
36102
|
+
{ method: "GET", pathPrefix: "/donation-campaigns/v2/donation-campaigns/", cacheable: true, ttl: 60, swr: 86400, tag: "donations" },
|
|
36103
|
+
{ method: "POST", pathPrefix: "/donation-campaigns/v2/donation-campaigns/query", cacheable: true, ttl: 60, swr: 86400, tag: "donations" },
|
|
36104
|
+
{ method: "GET", pathPrefix: "/events/v3/events/", cacheable: true, ttl: 60, swr: 86400, tag: "events" },
|
|
36105
|
+
{ method: "GET", pathPrefix: "/events/v3/events/category/", cacheable: true, ttl: 60, swr: 86400, tag: "events" },
|
|
36106
|
+
{ method: "POST", pathPrefix: "/events/v3/events/query", cacheable: true, ttl: 60, swr: 86400, tag: "events" },
|
|
36107
|
+
{ method: "GET", pathPrefix: "/events/v3/events/slug/", cacheable: true, ttl: 60, swr: 86400, tag: "events" },
|
|
36108
|
+
{ method: "GET", pathPrefix: "/faq/v2/categories", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36109
|
+
{ method: "GET", pathPrefix: "/faq/v2/categories/", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36110
|
+
{ method: "POST", pathPrefix: "/faq/v2/categories/query", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36111
|
+
{ method: "GET", pathPrefix: "/faq/v2/question-entries", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36112
|
+
{ method: "GET", pathPrefix: "/faq/v2/question-entries/", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36113
|
+
{ method: "POST", pathPrefix: "/faq/v2/question-entries/query", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36114
|
+
{ method: "POST", pathPrefix: "/online-programs/v3/programs/query", cacheable: true, ttl: 60, swr: 86400, tag: "online-programs" },
|
|
36115
|
+
{ method: "GET", pathPrefix: "/portfolio/v1/collections", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36116
|
+
{ method: "GET", pathPrefix: "/portfolio/v1/collections/", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36117
|
+
{ method: "POST", pathPrefix: "/portfolio/v1/collections/query", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36118
|
+
{ method: "GET", pathPrefix: "/portfolio/v1/projects", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36119
|
+
{ method: "GET", pathPrefix: "/portfolio/v1/projects/", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36120
|
+
{ method: "POST", pathPrefix: "/portfolio/v1/projects/collections/query", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36121
|
+
{ method: "POST", pathPrefix: "/portfolio/v1/projects/query", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36122
|
+
{ method: "GET", pathPrefix: "/pricing-plans/v2/plans/public", cacheable: true, ttl: 60, swr: 86400, tag: "pricing-plans" },
|
|
36123
|
+
{ method: "POST", pathPrefix: "/pricing-plans/v2/plans/public/query", cacheable: true, ttl: 60, swr: 86400, tag: "pricing-plans" },
|
|
36124
|
+
{ method: "GET", pathPrefix: "/restaurants/menus/v1/items/", cacheable: true, ttl: 60, swr: 86400, tag: "restaurants/menus" },
|
|
36125
|
+
{ method: "POST", pathPrefix: "/restaurants/menus/v1/items/query", cacheable: true, ttl: 60, swr: 86400, tag: "restaurants/menus" },
|
|
36126
|
+
{ method: "GET", pathPrefix: "/restaurants/menus/v1/menus/", cacheable: true, ttl: 60, swr: 86400, tag: "restaurants/menus" },
|
|
36127
|
+
{ method: "POST", pathPrefix: "/restaurants/menus/v1/menus/query", cacheable: true, ttl: 60, swr: 86400, tag: "restaurants/menus" },
|
|
36128
|
+
{ method: "POST", pathPrefix: "/restaurants/menus/v1/sections/query", cacheable: true, ttl: 60, swr: 86400, tag: "restaurants/menus" },
|
|
36129
|
+
{ method: "GET", pathPrefix: "/reviews/v1/reviews/", cacheable: true, ttl: 60, swr: 86400, tag: "reviews" },
|
|
36130
|
+
{ method: "POST", pathPrefix: "/reviews/v1/reviews/query", cacheable: true, ttl: 60, swr: 86400, tag: "reviews" },
|
|
36131
|
+
{ method: "GET", pathPrefix: "/stores/v1/products/", cacheable: true, ttl: 60, swr: 86400, tag: "stores/products" },
|
|
36132
|
+
{ method: "POST", pathPrefix: "/stores/v1/products/query", cacheable: true, ttl: 60, swr: 86400, tag: "stores/products" },
|
|
36133
|
+
{ method: "POST", pathPrefix: "/stores/v3/categories/query", cacheable: true, ttl: 60, swr: 86400, tag: "stores/categories" },
|
|
36134
|
+
{ method: "GET", pathPrefix: "/stores/v3/products/", cacheable: true, ttl: 60, swr: 86400, tag: "stores/products" },
|
|
36135
|
+
{ method: "POST", pathPrefix: "/stores/v3/products/query", cacheable: true, ttl: 60, swr: 86400, tag: "stores/products" },
|
|
36136
|
+
{ method: "POST", pathPrefix: "/stores/v3/products/search", cacheable: true, ttl: 60, swr: 86400, tag: "stores/products" },
|
|
36137
|
+
{ method: "DELETE", pathPrefix: "/blog/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36138
|
+
{ method: "PATCH", pathPrefix: "/blog/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36139
|
+
{ method: "POST", pathPrefix: "/blog/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36140
|
+
{ method: "DELETE", pathPrefix: "/blog/v3/posts", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36141
|
+
{ method: "PATCH", pathPrefix: "/blog/v3/posts", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36142
|
+
{ method: "POST", pathPrefix: "/blog/v3/posts", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36143
|
+
{ method: "DELETE", pathPrefix: "/bookings/v1/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36144
|
+
{ method: "POST", pathPrefix: "/bookings/v1/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36145
|
+
{ method: "PUT", pathPrefix: "/bookings/v1/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36146
|
+
{ method: "DELETE", pathPrefix: "/bookings/v2/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36147
|
+
{ method: "PATCH", pathPrefix: "/bookings/v2/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36148
|
+
{ method: "POST", pathPrefix: "/bookings/v2/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36149
|
+
{ method: "PATCH", pathPrefix: "/donation-campaigns/v2/donation-campaigns", cacheable: false, ttl: 0, swr: 0, tag: "donations" },
|
|
36150
|
+
{ method: "POST", pathPrefix: "/donation-campaigns/v2/donation-campaigns", cacheable: false, ttl: 0, swr: 0, tag: "donations" },
|
|
36151
|
+
{ method: "PATCH", pathPrefix: "/events/v1/events", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36152
|
+
{ method: "POST", pathPrefix: "/events/v1/events", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36153
|
+
{ method: "POST", pathPrefix: "/events/v1/events/orders", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36154
|
+
{ method: "DELETE", pathPrefix: "/events/v3/events", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36155
|
+
{ method: "POST", pathPrefix: "/events/v3/events", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36156
|
+
{ method: "POST", pathPrefix: "/events/v3/events/count-by-status", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36157
|
+
{ method: "DELETE", pathPrefix: "/faq/v2/categories", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36158
|
+
{ method: "PATCH", pathPrefix: "/faq/v2/categories", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36159
|
+
{ method: "POST", pathPrefix: "/faq/v2/categories", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36160
|
+
{ method: "DELETE", pathPrefix: "/faq/v2/question-entries", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36161
|
+
{ method: "PATCH", pathPrefix: "/faq/v2/question-entries", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36162
|
+
{ method: "POST", pathPrefix: "/faq/v2/question-entries", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36163
|
+
{ method: "DELETE", pathPrefix: "/online-programs/v3/programs", cacheable: false, ttl: 0, swr: 0, tag: "online-programs" },
|
|
36164
|
+
{ method: "PATCH", pathPrefix: "/online-programs/v3/programs", cacheable: false, ttl: 0, swr: 0, tag: "online-programs" },
|
|
36165
|
+
{ method: "POST", pathPrefix: "/online-programs/v3/programs", cacheable: false, ttl: 0, swr: 0, tag: "online-programs" },
|
|
36166
|
+
{ method: "DELETE", pathPrefix: "/portfolio/v1/collections", cacheable: false, ttl: 0, swr: 0, tag: "portfolio" },
|
|
36167
|
+
{ method: "POST", pathPrefix: "/portfolio/v1/collections", cacheable: false, ttl: 0, swr: 0, tag: "portfolio" },
|
|
36168
|
+
{ method: "DELETE", pathPrefix: "/portfolio/v1/projects", cacheable: false, ttl: 0, swr: 0, tag: "portfolio" },
|
|
36169
|
+
{ method: "PATCH", pathPrefix: "/portfolio/v1/projects", cacheable: false, ttl: 0, swr: 0, tag: "portfolio" },
|
|
36170
|
+
{ method: "DELETE", pathPrefix: "/pricing-plans/v2/plans", cacheable: false, ttl: 0, swr: 0, tag: "pricing-plans" },
|
|
36171
|
+
{ method: "PATCH", pathPrefix: "/pricing-plans/v2/plans", cacheable: false, ttl: 0, swr: 0, tag: "pricing-plans" },
|
|
36172
|
+
{ method: "POST", pathPrefix: "/pricing-plans/v2/plans", cacheable: false, ttl: 0, swr: 0, tag: "pricing-plans" },
|
|
36173
|
+
{ method: "DELETE", pathPrefix: "/restaurants/menus/v1/sections", cacheable: false, ttl: 0, swr: 0, tag: "restaurants/menus" },
|
|
36174
|
+
{ method: "PATCH", pathPrefix: "/restaurants/menus/v1/sections", cacheable: false, ttl: 0, swr: 0, tag: "restaurants/menus" },
|
|
36175
|
+
{ method: "POST", pathPrefix: "/restaurants/menus/v1/sections", cacheable: false, ttl: 0, swr: 0, tag: "restaurants/menus" },
|
|
36176
|
+
{ method: "DELETE", pathPrefix: "/reviews/v1/reviews", cacheable: false, ttl: 0, swr: 0, tag: "reviews" },
|
|
36177
|
+
{ method: "PATCH", pathPrefix: "/reviews/v1/reviews", cacheable: false, ttl: 0, swr: 0, tag: "reviews" },
|
|
36178
|
+
{ method: "POST", pathPrefix: "/reviews/v1/reviews", cacheable: false, ttl: 0, swr: 0, tag: "reviews" },
|
|
36179
|
+
{ method: "POST", pathPrefix: "/reviews/v1/reviews/count", cacheable: false, ttl: 0, swr: 0, tag: "reviews" },
|
|
36180
|
+
{ method: "DELETE", pathPrefix: "/stores/v1/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" },
|
|
36181
|
+
{ method: "PATCH", pathPrefix: "/stores/v1/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" },
|
|
36182
|
+
{ method: "POST", pathPrefix: "/stores/v1/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" },
|
|
36183
|
+
{ method: "DELETE", pathPrefix: "/stores/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "stores/categories" },
|
|
36184
|
+
{ method: "PATCH", pathPrefix: "/stores/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "stores/categories" },
|
|
36185
|
+
{ method: "POST", pathPrefix: "/stores/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "stores/categories" },
|
|
36186
|
+
{ method: "DELETE", pathPrefix: "/stores/v3/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" },
|
|
36187
|
+
{ method: "PATCH", pathPrefix: "/stores/v3/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" },
|
|
36188
|
+
{ method: "POST", pathPrefix: "/stores/v3/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" }
|
|
36189
|
+
];
|
|
36190
|
+
}
|
|
36191
|
+
});
|
|
36192
|
+
|
|
36090
36193
|
// ../../core/dev-server/src/wix-cache-policy.ts
|
|
36091
36194
|
function clampRule(rule, denyPrefixes, maxTTL) {
|
|
36092
36195
|
const denied2 = denyPrefixes.some((p) => rule.pathPrefix.startsWith(p));
|
|
@@ -36096,15 +36199,61 @@ function clampRule(rule, denyPrefixes, maxTTL) {
|
|
|
36096
36199
|
ttl: Math.min(rule.ttl, maxTTL)
|
|
36097
36200
|
};
|
|
36098
36201
|
}
|
|
36099
|
-
function
|
|
36100
|
-
const
|
|
36101
|
-
|
|
36102
|
-
return { rules, defaultCacheable: false };
|
|
36202
|
+
function shadows(own3, dflt) {
|
|
36203
|
+
const methodCovers = own3.method === null || own3.method.toUpperCase() === (dflt.method ?? "").toUpperCase();
|
|
36204
|
+
return methodCovers && dflt.pathPrefix.startsWith(own3.pathPrefix);
|
|
36103
36205
|
}
|
|
36104
|
-
|
|
36206
|
+
function resolveWixCachePolicy(appName2, declared) {
|
|
36207
|
+
const own3 = (declared?.rules ?? []).map((r) => ({
|
|
36208
|
+
method: r.method ?? null,
|
|
36209
|
+
pathPrefix: r.pathPrefix,
|
|
36210
|
+
cacheable: r.cacheable,
|
|
36211
|
+
ttl: r.ttl,
|
|
36212
|
+
swr: r.swr ?? 0,
|
|
36213
|
+
tag: r.tag ?? null
|
|
36214
|
+
}));
|
|
36215
|
+
const legacy = CACHE_OVERRIDES[appName2] ?? [];
|
|
36216
|
+
const appLevel = [...own3, ...legacy];
|
|
36217
|
+
const defaults = declared?.platformDefaults === false ? [] : PLATFORM_DEFAULT_WIX_CACHE_RULES.filter((d) => !appLevel.some((a) => shadows(a, d)));
|
|
36218
|
+
const denies = [
|
|
36219
|
+
...[...PLATFORM_DENY_PREFIXES, ...PERSONAL_DATA_PREFIXES].map((pathPrefix) => ({ method: null, pathPrefix, cacheable: false, ttl: 0, swr: 0, tag: null })),
|
|
36220
|
+
...PERSONAL_DATA_READS.map(([method, pathPrefix]) => ({ method, pathPrefix, cacheable: false, ttl: 0, swr: 0, tag: null }))
|
|
36221
|
+
];
|
|
36222
|
+
const rules = [...appLevel, ...defaults, ...denies].map((r) => clampRule(r, PLATFORM_DENY_PREFIXES, PLATFORM_MAX_TTL));
|
|
36223
|
+
return { rules, defaultCacheable: declared?.defaultCacheable ?? false };
|
|
36224
|
+
}
|
|
36225
|
+
var PLATFORM_DENY_PREFIXES, PERSONAL_DATA_PREFIXES, PERSONAL_DATA_READS, PLATFORM_MAX_TTL, CACHE_OVERRIDES;
|
|
36105
36226
|
var init_wix_cache_policy = __esm({
|
|
36106
36227
|
"../../core/dev-server/src/wix-cache-policy.ts"() {
|
|
36228
|
+
init_wix_cache_defaults_generated();
|
|
36107
36229
|
PLATFORM_DENY_PREFIXES = ["/stores/v2/orders", "/stores/v3/orders"];
|
|
36230
|
+
PERSONAL_DATA_PREFIXES = [
|
|
36231
|
+
"/ecom/v1/carts",
|
|
36232
|
+
"/ecom/v1/checkouts",
|
|
36233
|
+
"/ecom/v1/orders",
|
|
36234
|
+
"/members/",
|
|
36235
|
+
"/contacts/",
|
|
36236
|
+
"/invoices/",
|
|
36237
|
+
"/bookings/v1/bookings",
|
|
36238
|
+
"/bookings/v2/bookings",
|
|
36239
|
+
"/events/v1/orders",
|
|
36240
|
+
"/events/v1/tickets",
|
|
36241
|
+
"/events/v2/rsvps",
|
|
36242
|
+
"/gift-cards/",
|
|
36243
|
+
"/loyalty/",
|
|
36244
|
+
"/inbox/",
|
|
36245
|
+
"/pricing-plans/v2/orders",
|
|
36246
|
+
// Every answer below depends on who is asking, like the ones above — the generator's
|
|
36247
|
+
// NEVER_CACHED set (codegen/wix/scripts/gen-cache-defaults.ts), which the platform-defaults
|
|
36248
|
+
// fixture pins. Denied HERE so an app opting into `defaultCacheable` cannot cache them either
|
|
36249
|
+
// (tests/wix-cache-policy.test.ts walks that fixture against the fallback).
|
|
36250
|
+
"/social-groups-proxy/",
|
|
36251
|
+
"/stores/v2/coupons",
|
|
36252
|
+
"/analytics/",
|
|
36253
|
+
"/site-list/",
|
|
36254
|
+
"/blog/v3/draft-posts"
|
|
36255
|
+
];
|
|
36256
|
+
PERSONAL_DATA_READS = [["GET", "/events/v1/events/"]];
|
|
36108
36257
|
PLATFORM_MAX_TTL = 3600;
|
|
36109
36258
|
CACHE_OVERRIDES = {
|
|
36110
36259
|
// The reference fixture exercises the cache-policy contract (products cacheable).
|
|
@@ -36255,7 +36404,7 @@ function deriveNavigationConfig(app, bundleCtx) {
|
|
|
36255
36404
|
scheme: app.urlScheme,
|
|
36256
36405
|
deepLinkPatterns: app.deepLinkPatterns ?? ov?.deepLinkPatterns ?? [],
|
|
36257
36406
|
linkableScreens,
|
|
36258
|
-
wixCachePolicy: resolveWixCachePolicy(appName2),
|
|
36407
|
+
wixCachePolicy: resolveWixCachePolicy(appName2, app.cache),
|
|
36259
36408
|
// Fail-open baseline; tightened OTA via the admin app-config override. The
|
|
36260
36409
|
// DESTINATION(s) are derived generically from the app's config (no app-name
|
|
36261
36410
|
// special-casing) so the app chooses where telemetry goes via OTA:
|
|
@@ -49076,6 +49225,7 @@ function readInitWatch(dir) {
|
|
|
49076
49225
|
const r = JSON.parse(readFileSync52(file, "utf8"));
|
|
49077
49226
|
if (r.v !== 1 || typeof r.pid !== "number" || !Number.isInteger(r.pid) || r.pid < 1) return null;
|
|
49078
49227
|
if (typeof r.url !== "string" || !/^http:\/\/127\.0\.0\.1:\d+\//.test(r.url) || typeof r.board !== "string" || typeof r.log !== "string" || typeof r.startedAt !== "string") return null;
|
|
49228
|
+
if (r.root !== runRootId(dir)) return null;
|
|
49079
49229
|
return r;
|
|
49080
49230
|
} catch {
|
|
49081
49231
|
return null;
|
|
@@ -49173,7 +49323,7 @@ async function startWatchAtInit(dir, opts) {
|
|
|
49173
49323
|
});
|
|
49174
49324
|
child.unref();
|
|
49175
49325
|
if (!child.pid) return { skipped: "the live preview did not start (no process) \u2014 start it yourself: `himi run --watch --content <dir> &`" };
|
|
49176
|
-
const record2 = { v: 1, pid: child.pid, url, board, log: WATCH_LOG, startedAt: now.toISOString() };
|
|
49326
|
+
const record2 = { v: 1, pid: child.pid, root: runRootId(dir), url, board, log: WATCH_LOG, startedAt: now.toISOString() };
|
|
49177
49327
|
if (realDirIn(dir, ".himi")) writeFileAtomic(join46(dir, INIT_WATCH_FILE), `${JSON.stringify(record2, null, 2)}
|
|
49178
49328
|
`);
|
|
49179
49329
|
return { started: true, pid: child.pid, url, board, log: WATCH_LOG };
|
|
@@ -49233,6 +49383,7 @@ var init_milestones = __esm({
|
|
|
49233
49383
|
"src/milestones.ts"() {
|
|
49234
49384
|
init_app_source();
|
|
49235
49385
|
init_preview();
|
|
49386
|
+
init_run_identity();
|
|
49236
49387
|
init_progress();
|
|
49237
49388
|
init_shell_quote();
|
|
49238
49389
|
init_studio_reel();
|
|
@@ -53884,6 +54035,15 @@ function symlinkComponent(base, abs) {
|
|
|
53884
54035
|
}
|
|
53885
54036
|
return void 0;
|
|
53886
54037
|
}
|
|
54038
|
+
function workspaceRefusal(root, target) {
|
|
54039
|
+
const r = resolve45(root);
|
|
54040
|
+
const t = resolve45(r, target);
|
|
54041
|
+
if (!existsSync54(r)) return `the workspace folder ${r} does not exist`;
|
|
54042
|
+
if (!within(r, t) || !within(realpathSync7(r), realish(t))) return `"${target}" is outside the workspace folder ${r}`;
|
|
54043
|
+
const link = symlinkComponent(r, t);
|
|
54044
|
+
if (link) return `"${link}" is a symlink \u2014 paths must stay in real folders inside the workspace`;
|
|
54045
|
+
return null;
|
|
54046
|
+
}
|
|
53887
54047
|
async function confinedAppDir(args, deps) {
|
|
53888
54048
|
const root = resolve45(await deps.defaultDir());
|
|
53889
54049
|
const dir = typeof args.dir === "string" && args.dir ? resolve45(root, args.dir) : root;
|
|
@@ -54154,6 +54314,15 @@ function guarded(h) {
|
|
|
54154
54314
|
return async (args, deps) => {
|
|
54155
54315
|
const bad2 = flagShapedInputs(args);
|
|
54156
54316
|
if (bad2.length) return text6(`refused: ${bad2.join(", ")} may not start with "-" (it would be read as a himi flag)`, true);
|
|
54317
|
+
if (deps.workspaceBoundary) {
|
|
54318
|
+
const base = await deps.defaultDir();
|
|
54319
|
+
for (const k of PATH_ARGS) {
|
|
54320
|
+
const v = args[k];
|
|
54321
|
+
if (typeof v !== "string" || !v) continue;
|
|
54322
|
+
const why = workspaceRefusal(deps.workspaceBoundary, resolve46(base, v));
|
|
54323
|
+
if (why) return text6(`refused: ${k} ${why}`, true);
|
|
54324
|
+
}
|
|
54325
|
+
}
|
|
54157
54326
|
return h(args, deps);
|
|
54158
54327
|
};
|
|
54159
54328
|
}
|
|
@@ -54406,7 +54575,7 @@ ${log}` : ""}`, true);
|
|
|
54406
54575
|
}
|
|
54407
54576
|
];
|
|
54408
54577
|
}
|
|
54409
|
-
var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
|
|
54578
|
+
var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT, PATH_ARGS;
|
|
54410
54579
|
var init_tools = __esm({
|
|
54411
54580
|
"src/mcp/tools.ts"() {
|
|
54412
54581
|
init_file_tools();
|
|
@@ -54424,6 +54593,7 @@ var init_tools = __esm({
|
|
|
54424
54593
|
PUBLISH = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
|
|
54425
54594
|
PREVIEW_HINT = "The preview is already running: open `url` in your built-in browser \u2014 Claude Code desktop's browser pane, Cursor's Browser tool, the Browser in Codex inside the ChatGPT desktop app, VS Code's integrated browser. Do not also start the `himi-preview` launch configuration: it serves the same port, and is the way to start a preview only when none is running. A terminal-only agent should show the owner `himi_render` PNGs instead. `board` (when present) is the build board on the same origin.";
|
|
54426
54595
|
LOGIN_HINT = "Not signed in to the himi serve plane. Call himi_login: it opens a browser window where the user signs in to Wix (this server never sees the credential). A user with a terminal can run `himi login --browser` instead. Then retry.";
|
|
54596
|
+
PATH_ARGS = ["dir", "parentDir", "file"];
|
|
54427
54597
|
}
|
|
54428
54598
|
});
|
|
54429
54599
|
|
|
@@ -54564,7 +54734,8 @@ async function startMcpServer(opts) {
|
|
|
54564
54734
|
stop: (dir) => stopPreview(dir, previewDeps)
|
|
54565
54735
|
},
|
|
54566
54736
|
readFile: (p) => readFileSync60(p),
|
|
54567
|
-
login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login })
|
|
54737
|
+
login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login }),
|
|
54738
|
+
...opts.workspace ? { workspaceBoundary: opts.workspace } : {}
|
|
54568
54739
|
};
|
|
54569
54740
|
const closed = new Promise((resolve54) => {
|
|
54570
54741
|
stdin.once("end", resolve54);
|
|
@@ -57253,21 +57424,21 @@ var init_preview_assets_generated = __esm({
|
|
|
57253
57424
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
57254
57425
|
init_preview_assets_format();
|
|
57255
57426
|
PREVIEW_ASSET_MANIFEST = [
|
|
57256
|
-
{ key: "assets/index-
|
|
57257
|
-
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset:
|
|
57258
|
-
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset:
|
|
57259
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
57260
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
57261
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
57262
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
57263
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
57264
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
57265
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
57266
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
57267
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
57268
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
57269
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
57270
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
57427
|
+
{ key: "assets/index-nG7b3MPu.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1104209, sha256: "88839c5eb15058f706e50664752a75646d690de5148f8b504eb82c0f87a70a15" },
|
|
57428
|
+
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 1104217, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
|
|
57429
|
+
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 1108827, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
|
|
57430
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1597411, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
57431
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1688335, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
57432
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1779319, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
57433
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1870299, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
57434
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1961171, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
57435
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 2052151, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
57436
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 2160787, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
57437
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 2269871, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
57438
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 2378919, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
57439
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 2486619, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
57440
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 2574727, length: 4947, sha256: "5c0a3e1b1d5bda7b6bc8cc2a025321bf6d0aa74d1f14b073861f188fd7b13a8b" },
|
|
57441
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 2579674, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
|
|
57271
57442
|
];
|
|
57272
57443
|
}
|
|
57273
57444
|
});
|
|
@@ -57516,6 +57687,7 @@ __export(run_watch_exports, {
|
|
|
57516
57687
|
isEmptyDiff: () => isEmptyDiff,
|
|
57517
57688
|
rebuildBlocker: () => rebuildBlocker,
|
|
57518
57689
|
reloadEvents: () => reloadEvents,
|
|
57690
|
+
removeInitWatchRecord: () => removeInitWatchRecord,
|
|
57519
57691
|
removeRunRecord: () => removeRunRecord,
|
|
57520
57692
|
serialize: () => serialize,
|
|
57521
57693
|
watchContent: () => watchContent,
|
|
@@ -57685,6 +57857,24 @@ function removeRunRecord(dir, owner) {
|
|
|
57685
57857
|
}
|
|
57686
57858
|
rmSync15(join59(root, "run.json"), { force: true });
|
|
57687
57859
|
}
|
|
57860
|
+
function removeInitWatchRecord(dir, owner) {
|
|
57861
|
+
const root = join59(dir, ".himi");
|
|
57862
|
+
try {
|
|
57863
|
+
if (!lstatSync13(root).isDirectory()) return;
|
|
57864
|
+
} catch {
|
|
57865
|
+
return;
|
|
57866
|
+
}
|
|
57867
|
+
const bytes2 = readConfined(root, "watch.json");
|
|
57868
|
+
if (!bytes2) return;
|
|
57869
|
+
let pid;
|
|
57870
|
+
try {
|
|
57871
|
+
pid = JSON.parse(bytes2.toString("utf8")).pid;
|
|
57872
|
+
} catch {
|
|
57873
|
+
return;
|
|
57874
|
+
}
|
|
57875
|
+
if (pid !== owner) return;
|
|
57876
|
+
rmSync15(join59(root, "watch.json"), { force: true });
|
|
57877
|
+
}
|
|
57688
57878
|
function boardFile(dir, pathname) {
|
|
57689
57879
|
if (pathname === RUN_IDENTITY_PATH) {
|
|
57690
57880
|
return new Response(JSON.stringify(runIdentity(dir)), { status: 200, headers: { "content-type": "application/json", "cache-control": "no-store" } });
|
|
@@ -59412,7 +59602,7 @@ var init_push_send = __esm({
|
|
|
59412
59602
|
});
|
|
59413
59603
|
|
|
59414
59604
|
// ../../core/serve-control/src/push-send-service.ts
|
|
59415
|
-
var PUSH_SEND_ERROR_CODES;
|
|
59605
|
+
var PUSH_SEND_ERROR_CODES, PushSendError;
|
|
59416
59606
|
var init_push_send_service = __esm({
|
|
59417
59607
|
"../../core/serve-control/src/push-send-service.ts"() {
|
|
59418
59608
|
PUSH_SEND_ERROR_CODES = [
|
|
@@ -59454,6 +59644,160 @@ var init_push_send_service = __esm({
|
|
|
59454
59644
|
"ping_rate_limited",
|
|
59455
59645
|
"send_outcome_unknown"
|
|
59456
59646
|
];
|
|
59647
|
+
PushSendError = class extends Error {
|
|
59648
|
+
constructor(code, status, retryAfterSec) {
|
|
59649
|
+
super(code);
|
|
59650
|
+
this.code = code;
|
|
59651
|
+
this.status = status;
|
|
59652
|
+
this.retryAfterSec = retryAfterSec;
|
|
59653
|
+
}
|
|
59654
|
+
};
|
|
59655
|
+
}
|
|
59656
|
+
});
|
|
59657
|
+
|
|
59658
|
+
// ../../core/serve-control/src/site-member.ts
|
|
59659
|
+
async function assertOwnerSiteToken(input, fetchImpl = input.fetch ?? fetch) {
|
|
59660
|
+
const info2 = await upstreamJson(fetchImpl, {
|
|
59661
|
+
path: "/oauth2/token-info",
|
|
59662
|
+
body: { token: input.siteToken },
|
|
59663
|
+
unavailable: "site_token_unverifiable",
|
|
59664
|
+
// An expired, revoked or malformed token is answered with a 4xx: the caller's to fix, not an outage.
|
|
59665
|
+
rejected: { code: "site_token_invalid", when: (status) => status >= 400 && status < 500 }
|
|
59666
|
+
});
|
|
59667
|
+
const owned = info2.active === true && info2.subjectType === "USER" && info2.siteId === input.site && info2.accountId === input.ownerAccountId;
|
|
59668
|
+
if (!owned) throw new PushSendError("site_token_invalid", 403);
|
|
59669
|
+
}
|
|
59670
|
+
async function upstreamJson(fetchImpl, call) {
|
|
59671
|
+
let response;
|
|
59672
|
+
try {
|
|
59673
|
+
response = await fetchImpl(`${WIXAPIS}${call.path}`, {
|
|
59674
|
+
method: "POST",
|
|
59675
|
+
redirect: "error",
|
|
59676
|
+
signal: AbortSignal.timeout(TIMEOUT_MS2),
|
|
59677
|
+
headers: {
|
|
59678
|
+
"content-type": "application/json",
|
|
59679
|
+
accept: "application/json",
|
|
59680
|
+
...call.authorization ? { Authorization: call.authorization } : {},
|
|
59681
|
+
...call.siteId ? { "wix-site-id": call.siteId } : {}
|
|
59682
|
+
},
|
|
59683
|
+
body: JSON.stringify(call.body)
|
|
59684
|
+
});
|
|
59685
|
+
} catch {
|
|
59686
|
+
throw new PushSendError(call.unavailable, 503);
|
|
59687
|
+
}
|
|
59688
|
+
if (call.rejected?.when(response.status)) throw new PushSendError(call.rejected.code, 403);
|
|
59689
|
+
if (!response.ok) throw new PushSendError(call.unavailable, 503);
|
|
59690
|
+
try {
|
|
59691
|
+
return await response.json();
|
|
59692
|
+
} catch {
|
|
59693
|
+
throw new PushSendError(call.unavailable, 503);
|
|
59694
|
+
}
|
|
59695
|
+
}
|
|
59696
|
+
var WIXAPIS, TIMEOUT_MS2;
|
|
59697
|
+
var init_site_member = __esm({
|
|
59698
|
+
"../../core/serve-control/src/site-member.ts"() {
|
|
59699
|
+
init_push_send_service();
|
|
59700
|
+
WIXAPIS = "https://www.wixapis.com";
|
|
59701
|
+
TIMEOUT_MS2 = 1e4;
|
|
59702
|
+
}
|
|
59703
|
+
});
|
|
59704
|
+
|
|
59705
|
+
// src/notify-ping-all.ts
|
|
59706
|
+
import { createHash as createHash31 } from "node:crypto";
|
|
59707
|
+
async function listApprovedMembers(input) {
|
|
59708
|
+
const first = await scanMembers(input);
|
|
59709
|
+
const second = await scanMembers(input);
|
|
59710
|
+
if (JSON.stringify(first.fingerprint) !== JSON.stringify(second.fingerprint)) throw new Error("member_roster_unstable");
|
|
59711
|
+
return second.recipients;
|
|
59712
|
+
}
|
|
59713
|
+
async function scanMembers(input) {
|
|
59714
|
+
const recipients = [];
|
|
59715
|
+
const fingerprint = [];
|
|
59716
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
59717
|
+
const seenEmails = /* @__PURE__ */ new Set();
|
|
59718
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
59719
|
+
for (let offset = 0; ; ) {
|
|
59720
|
+
let response;
|
|
59721
|
+
try {
|
|
59722
|
+
response = await fetchImpl(`${WIXAPIS2}/members/v1/members/query`, {
|
|
59723
|
+
method: "POST",
|
|
59724
|
+
headers: { Authorization: input.siteToken, "wix-site-id": input.site, "content-type": "application/json", accept: "application/json" },
|
|
59725
|
+
redirect: "error",
|
|
59726
|
+
signal: AbortSignal.timeout(1e4),
|
|
59727
|
+
body: JSON.stringify({ query: { paging: { limit: PAGE_SIZE, offset } }, fieldsets: ["FULL"] })
|
|
59728
|
+
});
|
|
59729
|
+
} catch {
|
|
59730
|
+
throw new Error("member_lookup_unavailable");
|
|
59731
|
+
}
|
|
59732
|
+
if (!response.ok) throw new Error("member_lookup_unavailable");
|
|
59733
|
+
let raw;
|
|
59734
|
+
try {
|
|
59735
|
+
raw = await response.json();
|
|
59736
|
+
} catch {
|
|
59737
|
+
throw new Error("member_lookup_unavailable");
|
|
59738
|
+
}
|
|
59739
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) throw new Error("member_lookup_unavailable");
|
|
59740
|
+
const result = raw;
|
|
59741
|
+
if (!Array.isArray(result.members)) throw new Error("member_lookup_unavailable");
|
|
59742
|
+
if (result.members.length === 0) return { recipients, fingerprint };
|
|
59743
|
+
if (result.members.length > PAGE_SIZE) throw new Error("member_roster_unstable");
|
|
59744
|
+
for (const member of result.members) {
|
|
59745
|
+
if (member === null || typeof member !== "object" || Array.isArray(member)) throw new Error("member_lookup_unavailable");
|
|
59746
|
+
if (typeof member.id !== "string" || !member.id || seenIds.has(member.id)) throw new Error("member_roster_unstable");
|
|
59747
|
+
seenIds.add(member.id);
|
|
59748
|
+
fingerprint.push(JSON.stringify([member.id, member.loginEmail, member.contactId, member.status]));
|
|
59749
|
+
if (member.status !== "APPROVED") continue;
|
|
59750
|
+
if (typeof member.loginEmail !== "string" || !member.loginEmail || typeof member.contactId !== "string" || !member.contactId) throw new Error("member_roster_incomplete");
|
|
59751
|
+
const email = member.loginEmail.toLowerCase();
|
|
59752
|
+
if (seenEmails.has(email)) throw new Error("member_ambiguous");
|
|
59753
|
+
seenEmails.add(email);
|
|
59754
|
+
recipients.push({ id: member.id, email: member.loginEmail });
|
|
59755
|
+
}
|
|
59756
|
+
offset += result.members.length;
|
|
59757
|
+
}
|
|
59758
|
+
}
|
|
59759
|
+
function campaignRequestId(campaignId, memberId) {
|
|
59760
|
+
const bytes2 = createHash31("sha256").update(JSON.stringify(["himi-push-campaign", campaignId, memberId])).digest().subarray(0, 16);
|
|
59761
|
+
bytes2[6] = bytes2[6] & 15 | 80;
|
|
59762
|
+
bytes2[8] = bytes2[8] & 63 | 128;
|
|
59763
|
+
const hex2 = bytes2.toString("hex");
|
|
59764
|
+
return `${hex2.slice(0, 8)}-${hex2.slice(8, 12)}-${hex2.slice(12, 16)}-${hex2.slice(16, 20)}-${hex2.slice(20)}`;
|
|
59765
|
+
}
|
|
59766
|
+
async function sendCampaign(input) {
|
|
59767
|
+
let accepted = 0;
|
|
59768
|
+
let deduplicated = 0;
|
|
59769
|
+
for (const [index, recipient] of input.recipients.entries()) {
|
|
59770
|
+
if (index > 0) await input.wait(6100);
|
|
59771
|
+
const requestId2 = campaignRequestId(input.campaignId, recipient.id);
|
|
59772
|
+
let outcome = await input.send(recipient, requestId2);
|
|
59773
|
+
let retries = 0;
|
|
59774
|
+
while (outcome.state === "rate_limited" && outcome.retryAfterSec > 0 && retries < 3) {
|
|
59775
|
+
retries += 1;
|
|
59776
|
+
await input.wait(outcome.retryAfterSec * 1e3);
|
|
59777
|
+
outcome = await input.send(recipient, requestId2);
|
|
59778
|
+
}
|
|
59779
|
+
if (outcome.state !== "accepted") {
|
|
59780
|
+
throw new CampaignFailure(outcome.state === "failed" ? outcome.code : "rate_limited", index, recipient.email);
|
|
59781
|
+
}
|
|
59782
|
+
if (outcome.deduplicated) deduplicated += 1;
|
|
59783
|
+
else accepted += 1;
|
|
59784
|
+
input.onProgress?.(index + 1);
|
|
59785
|
+
}
|
|
59786
|
+
return { accepted, deduplicated };
|
|
59787
|
+
}
|
|
59788
|
+
var CampaignFailure, PAGE_SIZE, WIXAPIS2;
|
|
59789
|
+
var init_notify_ping_all = __esm({
|
|
59790
|
+
"src/notify-ping-all.ts"() {
|
|
59791
|
+
CampaignFailure = class extends Error {
|
|
59792
|
+
constructor(code, completed, memberEmail) {
|
|
59793
|
+
super(code);
|
|
59794
|
+
this.code = code;
|
|
59795
|
+
this.completed = completed;
|
|
59796
|
+
this.memberEmail = memberEmail;
|
|
59797
|
+
}
|
|
59798
|
+
};
|
|
59799
|
+
PAGE_SIZE = 100;
|
|
59800
|
+
WIXAPIS2 = "https://www.wixapis.com";
|
|
59457
59801
|
}
|
|
59458
59802
|
});
|
|
59459
59803
|
|
|
@@ -59471,8 +59815,11 @@ function refuse5(io, error, hint, exit = 2, extra = {}) {
|
|
|
59471
59815
|
async function runNotifyPing(flags, io, deps = {}) {
|
|
59472
59816
|
const flagError = flagRefusal(flags);
|
|
59473
59817
|
if (flagError) return refuse5(io, flagError);
|
|
59818
|
+
const allMembers = flags["all-members"] === true;
|
|
59819
|
+
if (allMembers && text7(flags["member-email"])) return refuse5(io, "recipient_conflict", "Choose --all-members or --member-email.");
|
|
59820
|
+
if (allMembers && flags["dry-run"] !== true && flags.yes !== true) return refuse5(io, "confirmation_required", "Preview with --dry-run, then add --yes to send to every approved member.");
|
|
59474
59821
|
const input = mergePushInputs(pushInputsFromContent(resolve50(text7(flags.content) ?? process.cwd())), flags);
|
|
59475
|
-
const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !text7(flags[f]))];
|
|
59822
|
+
const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !(allMembers && f === "member-email") && !text7(flags[f]))];
|
|
59476
59823
|
if (missing.length) return refuse5(io, "needs_input", "Name the app and site (or --content), the member's login email, a title and a link.", 2, { missing });
|
|
59477
59824
|
const requestId2 = text7(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID5)();
|
|
59478
59825
|
if (!UUID_RE.test(requestId2)) return refuse5(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
|
|
@@ -59487,6 +59834,7 @@ async function runNotifyPing(flags, io, deps = {}) {
|
|
|
59487
59834
|
} catch {
|
|
59488
59835
|
return refuse5(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
|
|
59489
59836
|
}
|
|
59837
|
+
if (allMembers) return runAllMembers({ input: { app: ownership.slug, site: input.site }, siteToken: siteToken2, session, requestId: requestId2, flags, io, deps });
|
|
59490
59838
|
const body = {
|
|
59491
59839
|
app: ownership.slug,
|
|
59492
59840
|
site: input.site,
|
|
@@ -59500,6 +59848,88 @@ async function runNotifyPing(flags, io, deps = {}) {
|
|
|
59500
59848
|
const http = await pushSendRequest({ target: session.target, wixToken: session.wixToken, siteToken: siteToken2, body, previewTag: session.previewTag, fetchImpl: deps.fetchImpl });
|
|
59501
59849
|
return report2(http, body, flags, io);
|
|
59502
59850
|
}
|
|
59851
|
+
async function runAllMembers(args) {
|
|
59852
|
+
const { input, siteToken: siteToken2, session, requestId: requestId2, flags, io, deps } = args;
|
|
59853
|
+
const ownerAccountId = decodeControlTokenClaims(session.controlToken)?.sub;
|
|
59854
|
+
if (!ownerAccountId) return refuse5(io, "owner_login_required");
|
|
59855
|
+
const readiness = await pushSetupRequest({
|
|
59856
|
+
target: session.target,
|
|
59857
|
+
wixToken: session.wixToken,
|
|
59858
|
+
operation: "status",
|
|
59859
|
+
query: input,
|
|
59860
|
+
previewTag: session.previewTag,
|
|
59861
|
+
fetchImpl: deps.fetchImpl
|
|
59862
|
+
});
|
|
59863
|
+
if (!readiness.ok) {
|
|
59864
|
+
const reported = String(readiness.body?.error ?? "");
|
|
59865
|
+
const code = KNOWN_CODES.has(reported) ? reported : "push_setup_unavailable";
|
|
59866
|
+
return refuse5(io, code, HINTS[code], 1);
|
|
59867
|
+
}
|
|
59868
|
+
if (readiness.body?.app !== input.app || readiness.body?.site !== input.site || readiness.body?.state !== "ready") {
|
|
59869
|
+
return refuse5(io, "push_not_ready", HINTS.push_not_ready, 1);
|
|
59870
|
+
}
|
|
59871
|
+
let recipients;
|
|
59872
|
+
try {
|
|
59873
|
+
await assertOwnerSiteToken({
|
|
59874
|
+
site: input.site,
|
|
59875
|
+
siteToken: siteToken2,
|
|
59876
|
+
ownerAccountId,
|
|
59877
|
+
fetch: deps.fetchImpl
|
|
59878
|
+
});
|
|
59879
|
+
recipients = await listApprovedMembers({ site: input.site, siteToken: siteToken2, fetchImpl: deps.fetchImpl });
|
|
59880
|
+
} catch (error) {
|
|
59881
|
+
const code = error instanceof PushSendError ? error.code : error instanceof Error && ROSTER_CODES.has(error.message) ? error.message : "member_lookup_unavailable";
|
|
59882
|
+
return refuse5(io, code, void 0, 1);
|
|
59883
|
+
}
|
|
59884
|
+
const base = { app: input.app, site: input.site, title: text7(flags.title), ...text7(flags.body) ? { body: text7(flags.body) } : {}, link: text7(flags.link) };
|
|
59885
|
+
const send2 = (recipient, memberRequestId, dryRun = false) => pushSendRequest({
|
|
59886
|
+
target: session.target,
|
|
59887
|
+
wixToken: session.wixToken,
|
|
59888
|
+
siteToken: siteToken2,
|
|
59889
|
+
previewTag: session.previewTag,
|
|
59890
|
+
fetchImpl: deps.fetchImpl,
|
|
59891
|
+
body: { ...base, memberEmail: recipient.email, requestId: memberRequestId, ...dryRun ? { dryRun: true } : {} }
|
|
59892
|
+
});
|
|
59893
|
+
if (flags["dry-run"] === true) {
|
|
59894
|
+
if (recipients.length) {
|
|
59895
|
+
const result = await send2(recipients[0], requestId2, true);
|
|
59896
|
+
const code = refusalCode(result);
|
|
59897
|
+
if (code) return refuse5(io, code, HINTS[code], 1);
|
|
59898
|
+
}
|
|
59899
|
+
io.log(JSON.stringify({ ok: true, state: "dry_run", campaignId: requestId2, recipients: recipients.length, sent: false }));
|
|
59900
|
+
return 0;
|
|
59901
|
+
}
|
|
59902
|
+
io.log(JSON.stringify({ ok: true, state: "started", campaignId: requestId2, recipients: recipients.length }));
|
|
59903
|
+
try {
|
|
59904
|
+
const result = await sendCampaign({
|
|
59905
|
+
recipients,
|
|
59906
|
+
campaignId: requestId2,
|
|
59907
|
+
wait: deps.wait ?? ((ms) => new Promise((resolve54) => setTimeout(resolve54, ms))),
|
|
59908
|
+
onProgress: (completed) => {
|
|
59909
|
+
if (completed % 10 === 0 || completed === recipients.length) {
|
|
59910
|
+
io.log(JSON.stringify({ ok: true, state: "progress", campaignId: requestId2, completed, recipients: recipients.length }));
|
|
59911
|
+
}
|
|
59912
|
+
},
|
|
59913
|
+
send: async (recipient, memberRequestId) => {
|
|
59914
|
+
const response = await send2(recipient, memberRequestId);
|
|
59915
|
+
const code = refusalCode(response);
|
|
59916
|
+
if (code === "rate_limited" && response.retryAfterSec) return { state: "rate_limited", retryAfterSec: response.retryAfterSec };
|
|
59917
|
+
if (code) return { state: "failed", code };
|
|
59918
|
+
return { state: "accepted", deduplicated: response.body?.deduplicated === true };
|
|
59919
|
+
}
|
|
59920
|
+
});
|
|
59921
|
+
io.log(JSON.stringify({ ok: true, state: "completed", campaignId: requestId2, recipients: recipients.length, ...result }));
|
|
59922
|
+
return 0;
|
|
59923
|
+
} catch (error) {
|
|
59924
|
+
if (!(error instanceof CampaignFailure)) return refuse5(io, "send_outcome_unknown", void 0, 1, { campaignId: requestId2 });
|
|
59925
|
+
const hint = error.code === "send_outcome_unknown" || error.code === "rate_limited" ? `Re-run the same command with --request-id ${requestId2} within Ping's 24-hour deduplication window.` : HINTS[error.code];
|
|
59926
|
+
return refuse5(io, error.code, hint, 1, {
|
|
59927
|
+
campaignId: requestId2,
|
|
59928
|
+
completed: error.completed,
|
|
59929
|
+
memberEmail: error.memberEmail
|
|
59930
|
+
});
|
|
59931
|
+
}
|
|
59932
|
+
}
|
|
59503
59933
|
function flagRefusal(flags) {
|
|
59504
59934
|
if (LOCAL_SENDER_FLAGS.some((f) => flags[f] !== void 0)) return "flag_not_supported_with_ping";
|
|
59505
59935
|
if (SWITCHES.some((f) => flags[f] !== void 0 && typeof flags[f] !== "boolean")) return "invalid_boolean_flag";
|
|
@@ -59534,20 +59964,24 @@ function summary(result, sent) {
|
|
|
59534
59964
|
}
|
|
59535
59965
|
return `Ping accepted request ${sent.requestId} for ${sent.memberEmail}. Ping does not confirm delivery: it reaches the member's signed-in devices with notifications allowed.`;
|
|
59536
59966
|
}
|
|
59537
|
-
var LOCAL_SENDER_FLAGS, SWITCHES, REQUIRED_FLAGS, UUID_RE, KNOWN_CODES, HINTS, text7;
|
|
59967
|
+
var LOCAL_SENDER_FLAGS, SWITCHES, REQUIRED_FLAGS, UUID_RE, KNOWN_CODES, ROSTER_CODES, HINTS, text7;
|
|
59538
59968
|
var init_notify_ping = __esm({
|
|
59539
59969
|
"src/notify-ping.ts"() {
|
|
59540
59970
|
init_push_send();
|
|
59971
|
+
init_push_setup();
|
|
59972
|
+
init_site_member();
|
|
59541
59973
|
init_push_send_service();
|
|
59542
59974
|
init_hosted_owner();
|
|
59975
|
+
init_notify_ping_all();
|
|
59543
59976
|
init_owner_claim();
|
|
59544
59977
|
init_push_onboarding();
|
|
59545
59978
|
init_wix_owner();
|
|
59546
59979
|
LOCAL_SENDER_FLAGS = ["token", "device", "all", "admin-url", "admin-session", "silent", "badge", "data", "category", "channel", "platform", "bundle-id"];
|
|
59547
|
-
SWITCHES = ["json", "dry-run"];
|
|
59980
|
+
SWITCHES = ["json", "dry-run", "all-members"];
|
|
59548
59981
|
REQUIRED_FLAGS = ["member-email", "title", "link"];
|
|
59549
59982
|
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
59550
59983
|
KNOWN_CODES = new Set(PUSH_SEND_ERROR_CODES);
|
|
59984
|
+
ROSTER_CODES = /* @__PURE__ */ new Set(["member_lookup_unavailable", "member_roster_unstable", "member_roster_incomplete", "member_ambiguous"]);
|
|
59551
59985
|
HINTS = {
|
|
59552
59986
|
push_not_ready: "Run himi notify setup for this app and site first; status must be ready.",
|
|
59553
59987
|
member_not_found: "Use the login email of an approved member of this site.",
|
|
@@ -63882,8 +64316,8 @@ async function applyOverlays(input) {
|
|
|
63882
64316
|
if (bringsBrand) {
|
|
63883
64317
|
const accent = tokens.colors?.accentPrimary;
|
|
63884
64318
|
const primary = typeof accent === "string" ? accent : accent?.light;
|
|
63885
|
-
const
|
|
63886
|
-
const glow =
|
|
64319
|
+
const shadows2 = merged.shadows;
|
|
64320
|
+
const glow = shadows2 && typeof shadows2 === "object" && !Array.isArray(shadows2) ? shadows2[BRAND_GLOW_SHADOW] : void 0;
|
|
63887
64321
|
if (primary && glow && typeof glow.color === "string") glow.color = primary;
|
|
63888
64322
|
stripBrandFromIdiom(merged);
|
|
63889
64323
|
}
|
|
@@ -69498,7 +69932,7 @@ var init_context = __esm({
|
|
|
69498
69932
|
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync80, mkdirSync as mkdirSync33, writeFileSync as writeFileSync29, existsSync as existsSync67, rmSync as rmSync16, readdirSync as readdirSync31, statSync as statSync19, lstatSync as lstatSync14, accessSync, constants as constants3, renameSync as renameSync8, cpSync as cpSync3 } from "node:fs";
|
|
69499
69933
|
import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
|
|
69500
69934
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
69501
|
-
import { createHash as
|
|
69935
|
+
import { createHash as createHash32, randomUUID as randomUUID7 } from "node:crypto";
|
|
69502
69936
|
import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
|
|
69503
69937
|
import { join as join65, resolve as resolve53, relative as relative14, basename as basename17, dirname as dirname37 } from "node:path";
|
|
69504
69938
|
import { fileURLToPath as fileURLToPath26 } from "node:url";
|
|
@@ -71520,6 +71954,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
71520
71954
|
"allow-destructive",
|
|
71521
71955
|
"allow-draft",
|
|
71522
71956
|
"all",
|
|
71957
|
+
"all-members",
|
|
71523
71958
|
"all-screens",
|
|
71524
71959
|
"ai",
|
|
71525
71960
|
"binary",
|
|
@@ -71554,6 +71989,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
71554
71989
|
"wait",
|
|
71555
71990
|
"wix",
|
|
71556
71991
|
"silent",
|
|
71992
|
+
"with-files",
|
|
71557
71993
|
"include-disabled",
|
|
71558
71994
|
"skip-build",
|
|
71559
71995
|
"refresh",
|
|
@@ -72120,6 +72556,12 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
72120
72556
|
wix login as the site owner, and a ready notify setup. Acceptance is not delivery.
|
|
72121
72557
|
--dry-run checks ownership, member, link and readiness without sending. After an unknown
|
|
72122
72558
|
outcome, re-run the same command with the printed --request-id; Ping never runs it twice.
|
|
72559
|
+
himi notify send --provider ping --target wix --app <a> --site <msid> --all-members
|
|
72560
|
+
--title <s> [--body <s>] --link <scheme>://screen/<id>[?\u2026] [--dry-run | --yes] [--request-id <uuid>]
|
|
72561
|
+
Sends to every approved site member with a login email. --dry-run counts recipients and
|
|
72562
|
+
checks one member's server gates; --yes is required to send. The CLI paces sends for the
|
|
72563
|
+
owner's 10/minute limit. Reuse the campaign ID with --request-id after an interrupted run
|
|
72564
|
+
within Ping's 24-hour deduplication window. Acceptance is not delivery.
|
|
72123
72565
|
himi notify send --app <a> (--token <t> | --device <id> | --all) --title <s> [--body <s>] [--link <url>]
|
|
72124
72566
|
deliver a REAL push notification to registered devices \u2014
|
|
72125
72567
|
APNs (.p8) for iOS, FCM v1 for Android. --all fans out to
|
|
@@ -72312,7 +72754,7 @@ var COMMANDS = [
|
|
|
72312
72754
|
{ name: "icon", summary: "the app's LAUNCHER icon \u2014 the home-screen / store mark, which is BINARY-floor and never over-the-air (distinct from `himi icons`, the in-screen glyph vocabulary). `status`/`check` report what this app would actually ship and validate it against both stores: exact 1024x1024, no tRNS chunk, non-interlaced, and \u2014 when the optional image toolchain is installed \u2014 no transparent regions (Apple permits an alpha channel but not transparent pixels: ITMS-90717), no pre-masked corners, no letterboxed wordmark; they also print the store-policy checklist no checker can decide. `set <file.png>` installs supplied art, `from-site` installs the logo `himi site analyze` downloaded, and `generate` makes a gradient tile + glyph \u2014 all three trim, flatten onto the app's accent, write the 1024 opaque master plus the 512 Play listing icon (Play wants 32-bit WITH alpha, so it is a separate file), and DECLARE it in himalaya.content.json, without which the release bakes no icon at all", required: "[status|check] | set <file.png> | from-site [--book <dir>] | generate [--glyph <g>] [--accent <hex>] | glyphs [--content <dir>] [--json]" },
|
|
72313
72755
|
{ 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>]" },
|
|
72314
72756
|
{ name: "logout", summary: "remove the stored control token for a target", required: "[--target <t>]" },
|
|
72315
|
-
{ 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. `send --provider ping` is the hosted alternative: the serve plane sends
|
|
72757
|
+
{ name: "notify", summary: "Hosted --all-members requires --yes for a live send; --dry-run checks ownership/readiness and counts approved recipients without sending. `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. `send --provider ping` is the hosted alternative: the serve plane sends to one site member (--member-email) or all approved members (--all-members) through Ping as Himalaya, with owner login instead of provider keys, and reports acceptance, never delivery. NOT `himi push`, which publishes a release.", required: "setup|status [--content <dir>] [--target <t>] [--refresh] [--yes] [--no-push-setup] | send --provider ping [--content <dir>] [--app <a>] [--site <msid>] (--member-email <email> | --all-members (--dry-run | --yes)) --title <s> [--body <s>] --link <url> [--request-id <uuid>] [--dry-run] [--json] | 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]" },
|
|
72316
72758
|
{ 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); `--url` alone is the visitor-only pass over the published pages, and `--client-id` adds the vertical probes and the app binding `--apply` requires; `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 (a site shell needs no `--client-id`: it is visitor-only and binds no client); `--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. `--shell brandy` (the site shell, RFC 0062) also derives the site's page map from its published pages and header menu \u2014 Home first, up to four tabs for the pages a visitor returns to, the rest in the drawer \u2014 into the overlay's `site` block, so it can be edited before `--apply`; only a site shell ever receives that block. 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 --url <https> [--client-id <id>] [--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]" },
|
|
72317
72759
|
{ 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>]" },
|
|
72318
72760
|
{ 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]" },
|
|
@@ -74611,7 +75053,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74611
75053
|
try {
|
|
74612
75054
|
const bytes2 = readFileSync80(iconPath);
|
|
74613
75055
|
payload.icon = bytes2.toString("base64");
|
|
74614
|
-
iconHash =
|
|
75056
|
+
iconHash = createHash32("sha256").update(bytes2).digest("hex");
|
|
74615
75057
|
} catch {
|
|
74616
75058
|
}
|
|
74617
75059
|
}
|
|
@@ -76401,7 +76843,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76401
76843
|
let localSourceHash;
|
|
76402
76844
|
try {
|
|
76403
76845
|
const { collectAppSource: collectAppSource2, zipAppSource: zipAppSource2 } = await Promise.resolve().then(() => (init_app_source(), app_source_exports));
|
|
76404
|
-
localSourceHash =
|
|
76846
|
+
localSourceHash = createHash32("sha256").update(zipAppSource2(collectAppSource2(dir).entries).toString("base64")).digest("hex");
|
|
76405
76847
|
} catch {
|
|
76406
76848
|
}
|
|
76407
76849
|
return runReleasePatch({
|
|
@@ -77134,9 +77576,30 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77134
77576
|
let browserCopy = null;
|
|
77135
77577
|
let servedMissing = [];
|
|
77136
77578
|
const fromContent = !source;
|
|
77579
|
+
let dropEarlySignals;
|
|
77580
|
+
let dropInitRecord;
|
|
77137
77581
|
try {
|
|
77138
77582
|
if (!source) {
|
|
77139
77583
|
const dir2 = contentDir(flags);
|
|
77584
|
+
if (watch2) {
|
|
77585
|
+
const { removeInitWatchRecord: removeInitWatchRecord2 } = await Promise.resolve().then(() => (init_run_watch(), run_watch_exports));
|
|
77586
|
+
dropInitRecord = () => removeInitWatchRecord2(dir2, process.pid);
|
|
77587
|
+
const onExit = () => dropInitRecord?.();
|
|
77588
|
+
process.once("exit", onExit);
|
|
77589
|
+
const early = [["SIGINT", 130], ["SIGTERM", 143], ["SIGHUP", 129]].map(([sig, code]) => {
|
|
77590
|
+
const onEarly = () => {
|
|
77591
|
+
dropInitRecord?.();
|
|
77592
|
+
process.exit(code);
|
|
77593
|
+
};
|
|
77594
|
+
process.once(sig, onEarly);
|
|
77595
|
+
return [sig, onEarly];
|
|
77596
|
+
});
|
|
77597
|
+
dropEarlySignals = () => {
|
|
77598
|
+
for (const [sig, onEarly] of early) process.removeListener(sig, onEarly);
|
|
77599
|
+
process.removeListener("exit", onExit);
|
|
77600
|
+
dropEarlySignals = void 0;
|
|
77601
|
+
};
|
|
77602
|
+
}
|
|
77140
77603
|
const app = await appId(dir2);
|
|
77141
77604
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
77142
77605
|
const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
|
|
@@ -77170,7 +77633,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77170
77633
|
let startedAt = "";
|
|
77171
77634
|
const record2 = (served2, build2) => {
|
|
77172
77635
|
try {
|
|
77173
|
-
if (recordKit?.writeRunRecord(dir, { url: served2.url, port: served2.port, ...served2.lanUrl ? { lanUrl: served2.lanUrl } : {}, pid: process.pid, startedAt, watching: watch2, build: build2 }))
|
|
77636
|
+
if (recordKit?.writeRunRecord(dir, { url: served2.url, port: served2.port, ...served2.lanUrl ? { lanUrl: served2.lanUrl } : {}, pid: process.pid, startedAt, watching: watch2, build: build2 })) {
|
|
77637
|
+
recorded = true;
|
|
77638
|
+
if (watch2) recordKit.removeInitWatchRecord(dir, process.pid);
|
|
77639
|
+
}
|
|
77174
77640
|
return null;
|
|
77175
77641
|
} catch (e) {
|
|
77176
77642
|
return e.message;
|
|
@@ -77207,6 +77673,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77207
77673
|
const stop = () => {
|
|
77208
77674
|
void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve54()));
|
|
77209
77675
|
};
|
|
77676
|
+
dropEarlySignals?.();
|
|
77210
77677
|
process.once("SIGINT", stop);
|
|
77211
77678
|
process.once("SIGTERM", stop);
|
|
77212
77679
|
});
|
|
@@ -77352,6 +77819,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77352
77819
|
}
|
|
77353
77820
|
};
|
|
77354
77821
|
const onSignal = () => void stop();
|
|
77822
|
+
dropEarlySignals?.();
|
|
77355
77823
|
for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) process.once(sig, onSignal);
|
|
77356
77824
|
stopNow = (why) => void stop(why);
|
|
77357
77825
|
armIdle();
|
|
@@ -77361,6 +77829,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77361
77829
|
io.error(JSON.stringify({ error: e.message }));
|
|
77362
77830
|
return 1;
|
|
77363
77831
|
} finally {
|
|
77832
|
+
dropEarlySignals?.();
|
|
77833
|
+
dropInitRecord?.();
|
|
77364
77834
|
if (temp) rmSync16(temp, { recursive: true, force: true });
|
|
77365
77835
|
if (served) rmSync16(served, { recursive: true, force: true });
|
|
77366
77836
|
if (browserCopy) rmSync16(browserCopy, { recursive: true, force: true });
|
|
@@ -78017,7 +78487,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
78017
78487
|
});
|
|
78018
78488
|
}
|
|
78019
78489
|
const bytes2 = readFileSync80(file);
|
|
78020
|
-
const sha =
|
|
78490
|
+
const sha = createHash32("sha256").update(bytes2).digest("hex");
|
|
78021
78491
|
const forScreens = (str8(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
78022
78492
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
78023
78493
|
io.error(JSON.stringify({ ok: false, error: "no_rebind_takes_no_value", message: "--no-rebind is a switch and takes no value; pass it bare.", usage: PATCH_USAGE }));
|