@wix/himalaya-cli 0.1116.0 → 0.1118.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 +587 -108
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/himi-mcp.md +7 -2
- 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,
|
|
@@ -24718,6 +24719,7 @@ function shouldRevealError(args) {
|
|
|
24718
24719
|
var EMAIL_RE, URL_HOST_RE, INTEGER_RE, NUMBER_RE;
|
|
24719
24720
|
var init_validation = __esm({
|
|
24720
24721
|
"../../core/ts/src/validation.ts"() {
|
|
24722
|
+
"use strict";
|
|
24721
24723
|
EMAIL_RE = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
|
|
24722
24724
|
URL_HOST_RE = /^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(:[0-9]+)?$/;
|
|
24723
24725
|
INTEGER_RE = /^[+-]?[0-9]+$/;
|
|
@@ -29118,6 +29120,7 @@ function validateWorkerSubtree(raw, slotId, policy, actionCatalog) {
|
|
|
29118
29120
|
var WORKER_SUBTREE_CEILINGS, ID_PART, ACTION_ID;
|
|
29119
29121
|
var init_worker_subtree = __esm({
|
|
29120
29122
|
"../../core/ts/src/worker-subtree.ts"() {
|
|
29123
|
+
"use strict";
|
|
29121
29124
|
init_worker_subtree_safe_types_generated();
|
|
29122
29125
|
WORKER_SUBTREE_CEILINGS = Object.freeze({
|
|
29123
29126
|
maxEncodedBytes: 65536,
|
|
@@ -36087,24 +36090,172 @@ var init_render_fonts = __esm({
|
|
|
36087
36090
|
}
|
|
36088
36091
|
});
|
|
36089
36092
|
|
|
36093
|
+
// ../../core/dev-server/src/wix-cache-defaults.generated.ts
|
|
36094
|
+
var PLATFORM_DEFAULT_WIX_CACHE_RULES;
|
|
36095
|
+
var init_wix_cache_defaults_generated = __esm({
|
|
36096
|
+
"../../core/dev-server/src/wix-cache-defaults.generated.ts"() {
|
|
36097
|
+
PLATFORM_DEFAULT_WIX_CACHE_RULES = [
|
|
36098
|
+
{ method: "POST", pathPrefix: "/_api/bookings/v2/services/search", cacheable: true, ttl: 60, swr: 86400, tag: "bookings/services" },
|
|
36099
|
+
{ method: "POST", pathPrefix: "/blog/v3/categories/query", cacheable: true, ttl: 60, swr: 86400, tag: "blog" },
|
|
36100
|
+
{ method: "GET", pathPrefix: "/blog/v3/posts/", cacheable: true, ttl: 60, swr: 86400, tag: "blog" },
|
|
36101
|
+
{ method: "POST", pathPrefix: "/blog/v3/posts/query", cacheable: true, ttl: 60, swr: 86400, tag: "blog" },
|
|
36102
|
+
{ method: "GET", pathPrefix: "/bookings/v2/services/", cacheable: true, ttl: 60, swr: 86400, tag: "bookings/services" },
|
|
36103
|
+
{ method: "POST", pathPrefix: "/bookings/v2/services/query", cacheable: true, ttl: 60, swr: 86400, tag: "bookings/services" },
|
|
36104
|
+
{ method: "GET", pathPrefix: "/donation-campaigns/v2/donation-campaigns/", cacheable: true, ttl: 60, swr: 86400, tag: "donations" },
|
|
36105
|
+
{ method: "POST", pathPrefix: "/donation-campaigns/v2/donation-campaigns/query", cacheable: true, ttl: 60, swr: 86400, tag: "donations" },
|
|
36106
|
+
{ method: "GET", pathPrefix: "/events/v3/events/", cacheable: true, ttl: 60, swr: 86400, tag: "events" },
|
|
36107
|
+
{ method: "GET", pathPrefix: "/events/v3/events/category/", cacheable: true, ttl: 60, swr: 86400, tag: "events" },
|
|
36108
|
+
{ method: "POST", pathPrefix: "/events/v3/events/query", cacheable: true, ttl: 60, swr: 86400, tag: "events" },
|
|
36109
|
+
{ method: "GET", pathPrefix: "/events/v3/events/slug/", cacheable: true, ttl: 60, swr: 86400, tag: "events" },
|
|
36110
|
+
{ method: "GET", pathPrefix: "/faq/v2/categories", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36111
|
+
{ method: "GET", pathPrefix: "/faq/v2/categories/", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36112
|
+
{ method: "POST", pathPrefix: "/faq/v2/categories/query", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36113
|
+
{ method: "GET", pathPrefix: "/faq/v2/question-entries", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36114
|
+
{ method: "GET", pathPrefix: "/faq/v2/question-entries/", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36115
|
+
{ method: "POST", pathPrefix: "/faq/v2/question-entries/query", cacheable: true, ttl: 60, swr: 86400, tag: "faq" },
|
|
36116
|
+
{ method: "POST", pathPrefix: "/online-programs/v3/programs/query", cacheable: true, ttl: 60, swr: 86400, tag: "online-programs" },
|
|
36117
|
+
{ method: "GET", pathPrefix: "/portfolio/v1/collections", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36118
|
+
{ method: "GET", pathPrefix: "/portfolio/v1/collections/", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36119
|
+
{ method: "POST", pathPrefix: "/portfolio/v1/collections/query", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36120
|
+
{ method: "GET", pathPrefix: "/portfolio/v1/projects", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36121
|
+
{ method: "GET", pathPrefix: "/portfolio/v1/projects/", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36122
|
+
{ method: "POST", pathPrefix: "/portfolio/v1/projects/collections/query", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36123
|
+
{ method: "POST", pathPrefix: "/portfolio/v1/projects/query", cacheable: true, ttl: 60, swr: 86400, tag: "portfolio" },
|
|
36124
|
+
{ method: "GET", pathPrefix: "/pricing-plans/v2/plans/public", cacheable: true, ttl: 60, swr: 86400, tag: "pricing-plans" },
|
|
36125
|
+
{ method: "POST", pathPrefix: "/pricing-plans/v2/plans/public/query", cacheable: true, ttl: 60, swr: 86400, tag: "pricing-plans" },
|
|
36126
|
+
{ method: "GET", pathPrefix: "/restaurants/menus/v1/items/", cacheable: true, ttl: 60, swr: 86400, tag: "restaurants/menus" },
|
|
36127
|
+
{ method: "POST", pathPrefix: "/restaurants/menus/v1/items/query", cacheable: true, ttl: 60, swr: 86400, tag: "restaurants/menus" },
|
|
36128
|
+
{ method: "GET", pathPrefix: "/restaurants/menus/v1/menus/", cacheable: true, ttl: 60, swr: 86400, tag: "restaurants/menus" },
|
|
36129
|
+
{ method: "POST", pathPrefix: "/restaurants/menus/v1/menus/query", cacheable: true, ttl: 60, swr: 86400, tag: "restaurants/menus" },
|
|
36130
|
+
{ method: "POST", pathPrefix: "/restaurants/menus/v1/sections/query", cacheable: true, ttl: 60, swr: 86400, tag: "restaurants/menus" },
|
|
36131
|
+
{ method: "GET", pathPrefix: "/reviews/v1/reviews/", cacheable: true, ttl: 60, swr: 86400, tag: "reviews" },
|
|
36132
|
+
{ method: "POST", pathPrefix: "/reviews/v1/reviews/query", cacheable: true, ttl: 60, swr: 86400, tag: "reviews" },
|
|
36133
|
+
{ method: "GET", pathPrefix: "/stores/v1/products/", cacheable: true, ttl: 60, swr: 86400, tag: "stores/products" },
|
|
36134
|
+
{ method: "POST", pathPrefix: "/stores/v1/products/query", cacheable: true, ttl: 60, swr: 86400, tag: "stores/products" },
|
|
36135
|
+
{ method: "POST", pathPrefix: "/stores/v3/categories/query", cacheable: true, ttl: 60, swr: 86400, tag: "stores/categories" },
|
|
36136
|
+
{ method: "GET", pathPrefix: "/stores/v3/products/", cacheable: true, ttl: 60, swr: 86400, tag: "stores/products" },
|
|
36137
|
+
{ method: "POST", pathPrefix: "/stores/v3/products/query", cacheable: true, ttl: 60, swr: 86400, tag: "stores/products" },
|
|
36138
|
+
{ method: "POST", pathPrefix: "/stores/v3/products/search", cacheable: true, ttl: 60, swr: 86400, tag: "stores/products" },
|
|
36139
|
+
{ method: "DELETE", pathPrefix: "/blog/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36140
|
+
{ method: "PATCH", pathPrefix: "/blog/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36141
|
+
{ method: "POST", pathPrefix: "/blog/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36142
|
+
{ method: "DELETE", pathPrefix: "/blog/v3/posts", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36143
|
+
{ method: "PATCH", pathPrefix: "/blog/v3/posts", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36144
|
+
{ method: "POST", pathPrefix: "/blog/v3/posts", cacheable: false, ttl: 0, swr: 0, tag: "blog" },
|
|
36145
|
+
{ method: "DELETE", pathPrefix: "/bookings/v1/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36146
|
+
{ method: "POST", pathPrefix: "/bookings/v1/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36147
|
+
{ method: "PUT", pathPrefix: "/bookings/v1/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36148
|
+
{ method: "DELETE", pathPrefix: "/bookings/v2/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36149
|
+
{ method: "PATCH", pathPrefix: "/bookings/v2/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36150
|
+
{ method: "POST", pathPrefix: "/bookings/v2/services", cacheable: false, ttl: 0, swr: 0, tag: "bookings/services" },
|
|
36151
|
+
{ method: "PATCH", pathPrefix: "/donation-campaigns/v2/donation-campaigns", cacheable: false, ttl: 0, swr: 0, tag: "donations" },
|
|
36152
|
+
{ method: "POST", pathPrefix: "/donation-campaigns/v2/donation-campaigns", cacheable: false, ttl: 0, swr: 0, tag: "donations" },
|
|
36153
|
+
{ method: "PATCH", pathPrefix: "/events/v1/events", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36154
|
+
{ method: "POST", pathPrefix: "/events/v1/events", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36155
|
+
{ method: "POST", pathPrefix: "/events/v1/events/orders", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36156
|
+
{ method: "DELETE", pathPrefix: "/events/v3/events", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36157
|
+
{ method: "POST", pathPrefix: "/events/v3/events", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36158
|
+
{ method: "POST", pathPrefix: "/events/v3/events/count-by-status", cacheable: false, ttl: 0, swr: 0, tag: "events" },
|
|
36159
|
+
{ method: "DELETE", pathPrefix: "/faq/v2/categories", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36160
|
+
{ method: "PATCH", pathPrefix: "/faq/v2/categories", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36161
|
+
{ method: "POST", pathPrefix: "/faq/v2/categories", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36162
|
+
{ method: "DELETE", pathPrefix: "/faq/v2/question-entries", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36163
|
+
{ method: "PATCH", pathPrefix: "/faq/v2/question-entries", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36164
|
+
{ method: "POST", pathPrefix: "/faq/v2/question-entries", cacheable: false, ttl: 0, swr: 0, tag: "faq" },
|
|
36165
|
+
{ method: "DELETE", pathPrefix: "/online-programs/v3/programs", cacheable: false, ttl: 0, swr: 0, tag: "online-programs" },
|
|
36166
|
+
{ method: "PATCH", pathPrefix: "/online-programs/v3/programs", cacheable: false, ttl: 0, swr: 0, tag: "online-programs" },
|
|
36167
|
+
{ method: "POST", pathPrefix: "/online-programs/v3/programs", cacheable: false, ttl: 0, swr: 0, tag: "online-programs" },
|
|
36168
|
+
{ method: "DELETE", pathPrefix: "/portfolio/v1/collections", cacheable: false, ttl: 0, swr: 0, tag: "portfolio" },
|
|
36169
|
+
{ method: "POST", pathPrefix: "/portfolio/v1/collections", cacheable: false, ttl: 0, swr: 0, tag: "portfolio" },
|
|
36170
|
+
{ method: "DELETE", pathPrefix: "/portfolio/v1/projects", cacheable: false, ttl: 0, swr: 0, tag: "portfolio" },
|
|
36171
|
+
{ method: "PATCH", pathPrefix: "/portfolio/v1/projects", cacheable: false, ttl: 0, swr: 0, tag: "portfolio" },
|
|
36172
|
+
{ method: "DELETE", pathPrefix: "/pricing-plans/v2/plans", cacheable: false, ttl: 0, swr: 0, tag: "pricing-plans" },
|
|
36173
|
+
{ method: "PATCH", pathPrefix: "/pricing-plans/v2/plans", cacheable: false, ttl: 0, swr: 0, tag: "pricing-plans" },
|
|
36174
|
+
{ method: "POST", pathPrefix: "/pricing-plans/v2/plans", cacheable: false, ttl: 0, swr: 0, tag: "pricing-plans" },
|
|
36175
|
+
{ method: "DELETE", pathPrefix: "/restaurants/menus/v1/sections", cacheable: false, ttl: 0, swr: 0, tag: "restaurants/menus" },
|
|
36176
|
+
{ method: "PATCH", pathPrefix: "/restaurants/menus/v1/sections", cacheable: false, ttl: 0, swr: 0, tag: "restaurants/menus" },
|
|
36177
|
+
{ method: "POST", pathPrefix: "/restaurants/menus/v1/sections", cacheable: false, ttl: 0, swr: 0, tag: "restaurants/menus" },
|
|
36178
|
+
{ method: "DELETE", pathPrefix: "/reviews/v1/reviews", cacheable: false, ttl: 0, swr: 0, tag: "reviews" },
|
|
36179
|
+
{ method: "PATCH", pathPrefix: "/reviews/v1/reviews", cacheable: false, ttl: 0, swr: 0, tag: "reviews" },
|
|
36180
|
+
{ method: "POST", pathPrefix: "/reviews/v1/reviews", cacheable: false, ttl: 0, swr: 0, tag: "reviews" },
|
|
36181
|
+
{ method: "POST", pathPrefix: "/reviews/v1/reviews/count", cacheable: false, ttl: 0, swr: 0, tag: "reviews" },
|
|
36182
|
+
{ method: "DELETE", pathPrefix: "/stores/v1/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" },
|
|
36183
|
+
{ method: "PATCH", pathPrefix: "/stores/v1/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" },
|
|
36184
|
+
{ method: "POST", pathPrefix: "/stores/v1/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" },
|
|
36185
|
+
{ method: "DELETE", pathPrefix: "/stores/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "stores/categories" },
|
|
36186
|
+
{ method: "PATCH", pathPrefix: "/stores/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "stores/categories" },
|
|
36187
|
+
{ method: "POST", pathPrefix: "/stores/v3/categories", cacheable: false, ttl: 0, swr: 0, tag: "stores/categories" },
|
|
36188
|
+
{ method: "DELETE", pathPrefix: "/stores/v3/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" },
|
|
36189
|
+
{ method: "PATCH", pathPrefix: "/stores/v3/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" },
|
|
36190
|
+
{ method: "POST", pathPrefix: "/stores/v3/products", cacheable: false, ttl: 0, swr: 0, tag: "stores/products" }
|
|
36191
|
+
];
|
|
36192
|
+
}
|
|
36193
|
+
});
|
|
36194
|
+
|
|
36090
36195
|
// ../../core/dev-server/src/wix-cache-policy.ts
|
|
36091
36196
|
function clampRule(rule, denyPrefixes, maxTTL) {
|
|
36092
|
-
const
|
|
36197
|
+
const denied2 = denyPrefixes.some((p) => rule.pathPrefix.startsWith(p));
|
|
36093
36198
|
return {
|
|
36094
36199
|
...rule,
|
|
36095
|
-
cacheable: rule.cacheable && !
|
|
36200
|
+
cacheable: rule.cacheable && !denied2,
|
|
36096
36201
|
ttl: Math.min(rule.ttl, maxTTL)
|
|
36097
36202
|
};
|
|
36098
36203
|
}
|
|
36099
|
-
function
|
|
36100
|
-
const
|
|
36101
|
-
|
|
36102
|
-
return { rules, defaultCacheable: false };
|
|
36204
|
+
function shadows(own3, dflt) {
|
|
36205
|
+
const methodCovers = own3.method === null || own3.method.toUpperCase() === (dflt.method ?? "").toUpperCase();
|
|
36206
|
+
return methodCovers && dflt.pathPrefix.startsWith(own3.pathPrefix);
|
|
36103
36207
|
}
|
|
36104
|
-
|
|
36208
|
+
function resolveWixCachePolicy(appName2, declared) {
|
|
36209
|
+
const own3 = (declared?.rules ?? []).map((r) => ({
|
|
36210
|
+
method: r.method ?? null,
|
|
36211
|
+
pathPrefix: r.pathPrefix,
|
|
36212
|
+
cacheable: r.cacheable,
|
|
36213
|
+
ttl: r.ttl,
|
|
36214
|
+
swr: r.swr ?? 0,
|
|
36215
|
+
tag: r.tag ?? null
|
|
36216
|
+
}));
|
|
36217
|
+
const legacy = CACHE_OVERRIDES[appName2] ?? [];
|
|
36218
|
+
const appLevel = [...own3, ...legacy];
|
|
36219
|
+
const defaults = declared?.platformDefaults === false ? [] : PLATFORM_DEFAULT_WIX_CACHE_RULES.filter((d) => !appLevel.some((a) => shadows(a, d)));
|
|
36220
|
+
const denies = [
|
|
36221
|
+
...[...PLATFORM_DENY_PREFIXES, ...PERSONAL_DATA_PREFIXES].map((pathPrefix) => ({ method: null, pathPrefix, cacheable: false, ttl: 0, swr: 0, tag: null })),
|
|
36222
|
+
...PERSONAL_DATA_READS.map(([method, pathPrefix]) => ({ method, pathPrefix, cacheable: false, ttl: 0, swr: 0, tag: null }))
|
|
36223
|
+
];
|
|
36224
|
+
const rules = [...appLevel, ...defaults, ...denies].map((r) => clampRule(r, PLATFORM_DENY_PREFIXES, PLATFORM_MAX_TTL));
|
|
36225
|
+
return { rules, defaultCacheable: declared?.defaultCacheable ?? false };
|
|
36226
|
+
}
|
|
36227
|
+
var PLATFORM_DENY_PREFIXES, PERSONAL_DATA_PREFIXES, PERSONAL_DATA_READS, PLATFORM_MAX_TTL, CACHE_OVERRIDES;
|
|
36105
36228
|
var init_wix_cache_policy = __esm({
|
|
36106
36229
|
"../../core/dev-server/src/wix-cache-policy.ts"() {
|
|
36230
|
+
init_wix_cache_defaults_generated();
|
|
36107
36231
|
PLATFORM_DENY_PREFIXES = ["/stores/v2/orders", "/stores/v3/orders"];
|
|
36232
|
+
PERSONAL_DATA_PREFIXES = [
|
|
36233
|
+
"/ecom/v1/carts",
|
|
36234
|
+
"/ecom/v1/checkouts",
|
|
36235
|
+
"/ecom/v1/orders",
|
|
36236
|
+
"/members/",
|
|
36237
|
+
"/contacts/",
|
|
36238
|
+
"/invoices/",
|
|
36239
|
+
"/bookings/v1/bookings",
|
|
36240
|
+
"/bookings/v2/bookings",
|
|
36241
|
+
"/events/v1/orders",
|
|
36242
|
+
"/events/v1/tickets",
|
|
36243
|
+
"/events/v2/rsvps",
|
|
36244
|
+
"/gift-cards/",
|
|
36245
|
+
"/loyalty/",
|
|
36246
|
+
"/inbox/",
|
|
36247
|
+
"/pricing-plans/v2/orders",
|
|
36248
|
+
// Every answer below depends on who is asking, like the ones above — the generator's
|
|
36249
|
+
// NEVER_CACHED set (codegen/wix/scripts/gen-cache-defaults.ts), which the platform-defaults
|
|
36250
|
+
// fixture pins. Denied HERE so an app opting into `defaultCacheable` cannot cache them either
|
|
36251
|
+
// (tests/wix-cache-policy.test.ts walks that fixture against the fallback).
|
|
36252
|
+
"/social-groups-proxy/",
|
|
36253
|
+
"/stores/v2/coupons",
|
|
36254
|
+
"/analytics/",
|
|
36255
|
+
"/site-list/",
|
|
36256
|
+
"/blog/v3/draft-posts"
|
|
36257
|
+
];
|
|
36258
|
+
PERSONAL_DATA_READS = [["GET", "/events/v1/events/"]];
|
|
36108
36259
|
PLATFORM_MAX_TTL = 3600;
|
|
36109
36260
|
CACHE_OVERRIDES = {
|
|
36110
36261
|
// The reference fixture exercises the cache-policy contract (products cacheable).
|
|
@@ -36255,7 +36406,7 @@ function deriveNavigationConfig(app, bundleCtx) {
|
|
|
36255
36406
|
scheme: app.urlScheme,
|
|
36256
36407
|
deepLinkPatterns: app.deepLinkPatterns ?? ov?.deepLinkPatterns ?? [],
|
|
36257
36408
|
linkableScreens,
|
|
36258
|
-
wixCachePolicy: resolveWixCachePolicy(appName2),
|
|
36409
|
+
wixCachePolicy: resolveWixCachePolicy(appName2, app.cache),
|
|
36259
36410
|
// Fail-open baseline; tightened OTA via the admin app-config override. The
|
|
36260
36411
|
// DESTINATION(s) are derived generically from the app's config (no app-name
|
|
36261
36412
|
// special-casing) so the app chooses where telemetry goes via OTA:
|
|
@@ -53854,7 +54005,8 @@ var init_cli_bridge = __esm({
|
|
|
53854
54005
|
});
|
|
53855
54006
|
|
|
53856
54007
|
// src/mcp/file-tools.ts
|
|
53857
|
-
import { lstatSync as lstatSync12, mkdirSync as mkdirSync26, readdirSync as readdirSync27, readFileSync as readFileSync59, realpathSync as realpathSync7, rmSync as rmSync12, statSync as statSync13,
|
|
54008
|
+
import { closeSync as closeSync4, constants, lstatSync as lstatSync12, mkdirSync as mkdirSync26, openSync as openSync3, readdirSync as readdirSync27, readFileSync as readFileSync59, realpathSync as realpathSync7, renameSync as renameSync6, rmSync as rmSync12, statSync as statSync13, writeSync, existsSync as existsSync54 } from "node:fs";
|
|
54009
|
+
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
53858
54010
|
import { dirname as dirname30, isAbsolute as isAbsolute5, join as join53, relative as relative11, resolve as resolve45, sep as sep14 } from "node:path";
|
|
53859
54011
|
import * as z from "zod";
|
|
53860
54012
|
function within(root, p) {
|
|
@@ -53871,37 +54023,99 @@ function realish(p) {
|
|
|
53871
54023
|
}
|
|
53872
54024
|
return join53(realpathSync7(cur), ...tail);
|
|
53873
54025
|
}
|
|
54026
|
+
function symlinkComponent(base, abs) {
|
|
54027
|
+
let cur = base;
|
|
54028
|
+
for (const part of relative11(base, abs).split(sep14).filter(Boolean)) {
|
|
54029
|
+
cur = join53(cur, part);
|
|
54030
|
+
try {
|
|
54031
|
+
if (lstatSync12(cur).isSymbolicLink()) return relative11(base, cur);
|
|
54032
|
+
} catch {
|
|
54033
|
+
return void 0;
|
|
54034
|
+
}
|
|
54035
|
+
}
|
|
54036
|
+
return void 0;
|
|
54037
|
+
}
|
|
53874
54038
|
async function confinedAppDir(args, deps) {
|
|
53875
54039
|
const root = resolve45(await deps.defaultDir());
|
|
53876
54040
|
const dir = typeof args.dir === "string" && args.dir ? resolve45(root, args.dir) : root;
|
|
53877
54041
|
if (!existsSync54(root)) return refuse4("no_workspace", `the workspace folder ${root} does not exist`);
|
|
53878
|
-
if (!within(realpathSync7(root), realish(dir))) return refuse4("outside_workspace", `"${String(args.dir)}" is outside the workspace folder`);
|
|
54042
|
+
if (!within(root, dir) || !within(realpathSync7(root), realish(dir))) return refuse4("outside_workspace", `"${String(args.dir)}" is outside the workspace folder`);
|
|
54043
|
+
const link = symlinkComponent(root, dir);
|
|
54044
|
+
if (link) return refuse4("outside_workspace", `"${link}" is a symlink \u2014 the app folder must be a real folder in the workspace`);
|
|
54045
|
+
const rel = relative11(root, dir);
|
|
54046
|
+
if (rel && (isDeniedSourcePath(`${rel}/x`) || isDeniedSourcePath(`${rel.toLowerCase()}/x`))) return refuse4("denied", `"${rel}" is a folder this tool does not touch`);
|
|
54047
|
+
if (!existsSync54(join53(dir, CONTENT_MARKER))) {
|
|
54048
|
+
return refuse4("not_an_app", `"${rel || "."}" is not an app folder (no ${CONTENT_MARKER}) \u2014 see himi_list_apps, or create one with himi_init`);
|
|
54049
|
+
}
|
|
53879
54050
|
return dir;
|
|
53880
54051
|
}
|
|
54052
|
+
function onDiskSpelling(abs) {
|
|
54053
|
+
let cur = abs;
|
|
54054
|
+
const tail = [];
|
|
54055
|
+
while (!existsSync54(cur)) {
|
|
54056
|
+
const up = dirname30(cur);
|
|
54057
|
+
if (up === cur) break;
|
|
54058
|
+
tail.unshift(cur.slice(up.length + (up.endsWith(sep14) ? 0 : 1)));
|
|
54059
|
+
cur = up;
|
|
54060
|
+
}
|
|
54061
|
+
return join53(realpathSync7.native(cur), ...tail);
|
|
54062
|
+
}
|
|
54063
|
+
function denied(appDir3, abs) {
|
|
54064
|
+
const rel = relative11(appDir3, abs);
|
|
54065
|
+
if (isDeniedSourcePath(rel) || isDeniedSourcePath(rel.toLowerCase())) return true;
|
|
54066
|
+
try {
|
|
54067
|
+
return isDeniedSourcePath(relative11(realpathSync7.native(appDir3), onDiskSpelling(abs)));
|
|
54068
|
+
} catch {
|
|
54069
|
+
return true;
|
|
54070
|
+
}
|
|
54071
|
+
}
|
|
53881
54072
|
function confinedPath(appDir3, rel) {
|
|
53882
54073
|
if (typeof rel !== "string" || !rel.trim()) return { error: "a path is required" };
|
|
53883
54074
|
if (rel.includes("\0")) return { error: "a path may not contain NUL" };
|
|
53884
54075
|
if (isAbsolute5(rel)) return { error: `"${rel}" is absolute \u2014 give a path inside the app folder` };
|
|
53885
54076
|
const abs = resolve45(appDir3, rel);
|
|
54077
|
+
if (!within(appDir3, abs) || abs === appDir3) return { error: `"${rel}" is outside the app folder` };
|
|
53886
54078
|
const real = realish(abs);
|
|
53887
54079
|
const base = existsSync54(appDir3) ? realpathSync7(appDir3) : realish(appDir3);
|
|
53888
54080
|
if (!within(base, real) || real === base) return { error: `"${rel}" is outside the app folder` };
|
|
53889
|
-
const
|
|
53890
|
-
if (
|
|
54081
|
+
const link = symlinkComponent(appDir3, abs);
|
|
54082
|
+
if (link) return { error: `"${link}" is a symlink, which this tool does not follow` };
|
|
54083
|
+
if (denied(appDir3, abs)) return { error: `"${rel}" is on the deny-list (secrets, credentials, build output), which this tool does not touch` };
|
|
53891
54084
|
return abs;
|
|
53892
54085
|
}
|
|
54086
|
+
function writeNoFollow(appDir3, abs, content) {
|
|
54087
|
+
mkdirSync26(dirname30(abs), { recursive: true });
|
|
54088
|
+
const before = symlinkComponent(appDir3, abs);
|
|
54089
|
+
if (before) throw new Error(`"${before}" became a symlink`);
|
|
54090
|
+
const tmp = join53(dirname30(abs), `.himi-write-${process.pid}-${randomBytes4(6).toString("hex")}.tmp`);
|
|
54091
|
+
const fd = openSync3(tmp, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 420);
|
|
54092
|
+
try {
|
|
54093
|
+
writeSync(fd, content);
|
|
54094
|
+
} finally {
|
|
54095
|
+
closeSync4(fd);
|
|
54096
|
+
}
|
|
54097
|
+
const link = symlinkComponent(appDir3, abs);
|
|
54098
|
+
if (link || !within(realpathSync7(appDir3), realpathSync7(dirname30(abs)))) {
|
|
54099
|
+
rmSync12(tmp, { force: true });
|
|
54100
|
+
throw new Error(`"${link ?? relative11(appDir3, dirname30(abs))}" changed into a link while writing`);
|
|
54101
|
+
}
|
|
54102
|
+
renameSync6(tmp, abs);
|
|
54103
|
+
}
|
|
53893
54104
|
function listFiles(appDir3) {
|
|
53894
54105
|
const files = [];
|
|
53895
54106
|
const walk2 = (d) => {
|
|
54107
|
+
const parentRel = relative11(appDir3, d);
|
|
53896
54108
|
for (const e of readdirSync27(d, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
53897
|
-
if (RESERVED.has(e.name)) continue;
|
|
53898
54109
|
if (e.isSymbolicLink()) continue;
|
|
53899
54110
|
const p = join53(d, e.name);
|
|
53900
54111
|
if (e.isDirectory()) {
|
|
54112
|
+
if (isDeniedSourceDir(e.name, parentRel) || isDeniedSourceDir(e.name.toLowerCase(), parentRel)) continue;
|
|
53901
54113
|
if (!walk2(p)) return false;
|
|
53902
54114
|
} else if (e.isFile()) {
|
|
54115
|
+
const rel = relative11(appDir3, p);
|
|
54116
|
+
if (isDeniedSourcePath(rel) || isDeniedSourcePath(rel.toLowerCase())) continue;
|
|
53903
54117
|
if (files.length >= MAX_LISTED) return false;
|
|
53904
|
-
files.push({ path:
|
|
54118
|
+
files.push({ path: rel.split(sep14).join("/"), bytes: statSync13(p).size });
|
|
53905
54119
|
}
|
|
53906
54120
|
}
|
|
53907
54121
|
return true;
|
|
@@ -53931,7 +54145,7 @@ function fileTools() {
|
|
|
53931
54145
|
{
|
|
53932
54146
|
name: "himi_list_files",
|
|
53933
54147
|
title: "List app files",
|
|
53934
|
-
description: `Every file in an app folder with its size
|
|
54148
|
+
description: `Every file in an app folder with its size \u2014 at most ${MAX_LISTED}, skipping symlinks and what the source deny-list keeps off the machine (secrets, credentials, build output).`,
|
|
53935
54149
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
53936
54150
|
inputSchema: z.object({ dir: DIR }),
|
|
53937
54151
|
handler: async (a, d) => {
|
|
@@ -53980,14 +54194,20 @@ function fileTools() {
|
|
|
53980
54194
|
else if (typeof f.content !== "string") refused2.push({ path: f.path, error: "content must be text" });
|
|
53981
54195
|
else if (Buffer.byteLength(f.content) > MAX_FILE_BYTES) refused2.push({ path: f.path, error: `over the ${MAX_FILE_BYTES}-byte limit` });
|
|
53982
54196
|
else if (existsSync54(p) && !lstatSync12(p).isFile()) refused2.push({ path: f.path, error: "not a regular file" });
|
|
54197
|
+
else if (planned.some((q) => q.abs === p)) refused2.push({ path: f.path, error: "the same file twice in one call" });
|
|
53983
54198
|
else planned.push({ abs: p, rel: String(f.path), content: f.content });
|
|
53984
54199
|
}
|
|
53985
54200
|
if (refused2.length) return { ...ok({ ok: false, error: "refused", written: [], refused: refused2 }), isError: true };
|
|
54201
|
+
const written = [];
|
|
53986
54202
|
for (const f of planned) {
|
|
53987
|
-
|
|
53988
|
-
|
|
54203
|
+
try {
|
|
54204
|
+
writeNoFollow(app, f.abs, f.content);
|
|
54205
|
+
written.push(f.rel);
|
|
54206
|
+
} catch (e) {
|
|
54207
|
+
return { ...ok({ ok: false, error: "write_failed", message: e.message, written }), isError: true };
|
|
54208
|
+
}
|
|
53989
54209
|
}
|
|
53990
|
-
return ok({ ok: true, dir: app, written
|
|
54210
|
+
return ok({ ok: true, dir: app, written });
|
|
53991
54211
|
}
|
|
53992
54212
|
},
|
|
53993
54213
|
{
|
|
@@ -54001,28 +54221,32 @@ function fileTools() {
|
|
|
54001
54221
|
if (typeof app !== "string") return app;
|
|
54002
54222
|
const paths = Array.isArray(a.paths) ? a.paths : [];
|
|
54003
54223
|
const planned = [];
|
|
54224
|
+
const deleted = [];
|
|
54004
54225
|
const refused2 = [];
|
|
54005
54226
|
for (const rel of paths) {
|
|
54006
54227
|
const p = confinedPath(app, rel);
|
|
54007
54228
|
if (typeof p !== "string") refused2.push({ path: rel, error: p.error });
|
|
54008
54229
|
else if (!existsSync54(p)) refused2.push({ path: rel, error: "no such file" });
|
|
54009
54230
|
else if (!lstatSync12(p).isFile()) refused2.push({ path: rel, error: "not a regular file" });
|
|
54010
|
-
else planned.
|
|
54231
|
+
else if (!planned.includes(p)) {
|
|
54232
|
+
planned.push(p);
|
|
54233
|
+
deleted.push(rel);
|
|
54234
|
+
}
|
|
54011
54235
|
}
|
|
54012
54236
|
if (refused2.length) return { ...ok({ ok: false, error: "refused", deleted: [], refused: refused2 }), isError: true };
|
|
54013
54237
|
for (const p of planned) rmSync12(p);
|
|
54014
|
-
return ok({ ok: true, dir: app, deleted
|
|
54238
|
+
return ok({ ok: true, dir: app, deleted });
|
|
54015
54239
|
}
|
|
54016
54240
|
}
|
|
54017
54241
|
];
|
|
54018
54242
|
}
|
|
54019
|
-
var MAX_FILE_BYTES, MAX_FILES_PER_WRITE, MAX_LISTED,
|
|
54243
|
+
var MAX_FILE_BYTES, MAX_FILES_PER_WRITE, MAX_LISTED, CONTENT_MARKER, ok, refuse4, DIR, WRITE_ANN;
|
|
54020
54244
|
var init_file_tools = __esm({
|
|
54021
54245
|
"src/mcp/file-tools.ts"() {
|
|
54246
|
+
init_source_deny();
|
|
54022
54247
|
MAX_FILE_BYTES = 1024 * 1024;
|
|
54023
54248
|
MAX_FILES_PER_WRITE = 100;
|
|
54024
54249
|
MAX_LISTED = 2e3;
|
|
54025
|
-
RESERVED = /* @__PURE__ */ new Set([".git", "node_modules", "dist"]);
|
|
54026
54250
|
CONTENT_MARKER = "himalaya.content.json";
|
|
54027
54251
|
ok = (o) => ({ content: [{ type: "text", text: JSON.stringify(o, null, 2) }] });
|
|
54028
54252
|
refuse4 = (error, message) => ({ content: [{ type: "text", text: JSON.stringify({ ok: false, error, message }, null, 2) }], isError: true });
|
|
@@ -54533,7 +54757,7 @@ __export(native_decode_exports, {
|
|
|
54533
54757
|
runNativeDecode: () => runNativeDecode
|
|
54534
54758
|
});
|
|
54535
54759
|
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
54536
|
-
import { existsSync as existsSync55, mkdtempSync as mkdtempSync2, readFileSync as readFileSync61, rmSync as rmSync13, writeFileSync as
|
|
54760
|
+
import { existsSync as existsSync55, mkdtempSync as mkdtempSync2, readFileSync as readFileSync61, rmSync as rmSync13, writeFileSync as writeFileSync21 } from "node:fs";
|
|
54537
54761
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
54538
54762
|
import { join as join54 } from "node:path";
|
|
54539
54763
|
import { fileURLToPath as fileURLToPath22 } from "node:url";
|
|
@@ -54667,7 +54891,7 @@ function runNativeDecode(options) {
|
|
|
54667
54891
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
54668
54892
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
54669
54893
|
}
|
|
54670
|
-
|
|
54894
|
+
writeFileSync21(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
54671
54895
|
}
|
|
54672
54896
|
options.progress?.("building cached Swift oracle");
|
|
54673
54897
|
execFileSync5("swift", ["build", "--package-path", options.packageDir, "--product", "himi-decode-oracle"], {
|
|
@@ -54705,7 +54929,7 @@ function runAndroidNativeDecode(options) {
|
|
|
54705
54929
|
if (typeof descriptor.descriptorJson !== "string") {
|
|
54706
54930
|
throw new Error(`native decode cannot judge ${descriptor.screenId}: the release builder did not return its exact baked JSON bytes`);
|
|
54707
54931
|
}
|
|
54708
|
-
|
|
54932
|
+
writeFileSync21(join54(descriptorDir, `${encodeURIComponent(descriptor.screenId)}.json`), descriptor.descriptorJson);
|
|
54709
54933
|
}
|
|
54710
54934
|
options.progress?.(`running real Kotlin decoder over ${options.descriptors.length} screen${options.descriptors.length === 1 ? "" : "s"}`);
|
|
54711
54935
|
execFileSync5(options.gradlew, [
|
|
@@ -54789,7 +55013,7 @@ __export(browser_authoring_exports, {
|
|
|
54789
55013
|
sdkSubpathReader: () => sdkSubpathReader
|
|
54790
55014
|
});
|
|
54791
55015
|
import { createServer as createServer5 } from "node:http";
|
|
54792
|
-
import { createHash as createHash29, randomBytes as
|
|
55016
|
+
import { createHash as createHash29, randomBytes as randomBytes5 } from "node:crypto";
|
|
54793
55017
|
import { existsSync as existsSync56, readdirSync as readdirSync28, readFileSync as readFileSync62, realpathSync as realpathSync8, statSync as statSync14 } from "node:fs";
|
|
54794
55018
|
import { join as join55, posix as posix2, relative as relative12, sep as sep15 } from "node:path";
|
|
54795
55019
|
function humanMs(ms) {
|
|
@@ -54887,7 +55111,7 @@ function sdkSubpathReader(resolve54) {
|
|
|
54887
55111
|
function encodeJob(job) {
|
|
54888
55112
|
return Buffer.from(JSON.stringify(job), "utf8").toString("base64");
|
|
54889
55113
|
}
|
|
54890
|
-
function mintToken2(payload, nonce =
|
|
55114
|
+
function mintToken2(payload, nonce = randomBytes5(16).toString("hex")) {
|
|
54891
55115
|
const digest2 = createHash29("sha256").update(payload, "utf8").digest("base64url");
|
|
54892
55116
|
return `${nonce}.${digest2}`;
|
|
54893
55117
|
}
|
|
@@ -55050,7 +55274,7 @@ __export(coverage_exports, {
|
|
|
55050
55274
|
suppressedNativeKeys: () => suppressedNativeKeys,
|
|
55051
55275
|
trendAndStore: () => trendAndStore
|
|
55052
55276
|
});
|
|
55053
|
-
import { existsSync as existsSync57, mkdirSync as mkdirSync27, readFileSync as readFileSync63, writeFileSync as
|
|
55277
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync27, readFileSync as readFileSync63, writeFileSync as writeFileSync22 } from "node:fs";
|
|
55054
55278
|
import { dirname as dirname31, join as join56 } from "node:path";
|
|
55055
55279
|
function suppressedNativeKeys(oracle) {
|
|
55056
55280
|
return [...oracle.ios ? [] : ["native-decode|ios"], ...oracle.android ? [] : ["native-decode|android"]];
|
|
@@ -55244,7 +55468,7 @@ function trendAndStore(dir, entries, suppressed) {
|
|
|
55244
55468
|
const stored = [.../* @__PURE__ */ new Set([...current, ...(previous ?? []).filter((key2) => (suppressed ?? []).includes(key2))])];
|
|
55245
55469
|
try {
|
|
55246
55470
|
mkdirSync27(dirname31(p), { recursive: true });
|
|
55247
|
-
|
|
55471
|
+
writeFileSync22(p, JSON.stringify({ keys: stored, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
55248
55472
|
} catch {
|
|
55249
55473
|
return null;
|
|
55250
55474
|
}
|
|
@@ -55289,7 +55513,7 @@ function diffAndStoreObservations(dir, current) {
|
|
|
55289
55513
|
}
|
|
55290
55514
|
try {
|
|
55291
55515
|
mkdirSync27(dirname31(p), { recursive: true });
|
|
55292
|
-
|
|
55516
|
+
writeFileSync22(p, JSON.stringify({ screens: current, ts: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
55293
55517
|
} catch {
|
|
55294
55518
|
return null;
|
|
55295
55519
|
}
|
|
@@ -55900,8 +56124,8 @@ ${releaseId}`;
|
|
|
55900
56124
|
const pin = resolvePin(request, url);
|
|
55901
56125
|
let bytes2 = null;
|
|
55902
56126
|
if (pin) {
|
|
55903
|
-
const
|
|
55904
|
-
if (
|
|
56127
|
+
const denied2 = await authorizePinnedRead(request, url, app, pin);
|
|
56128
|
+
if (denied2) return { ok: false, response: denied2 };
|
|
55905
56129
|
const m = await pinnedManifest(app, pin);
|
|
55906
56130
|
if (!m) return { ok: false, response: json4(404, { error: "release_not_found", app, releaseId: pin }) };
|
|
55907
56131
|
bytes2 = m.appConfigHash ? await pinnedBody(app, m.appConfigHash, () => store.getAppConfig(app)) : null;
|
|
@@ -55924,7 +56148,7 @@ ${releaseId}`;
|
|
|
55924
56148
|
return new Response(body, { status: 200, headers: { "content-type": JSON_CT2, etag, "cache-control": cache, ...vary } });
|
|
55925
56149
|
}
|
|
55926
56150
|
async function authorizePinnedRead(request, url, app, releaseId, screenId) {
|
|
55927
|
-
const
|
|
56151
|
+
const denied2 = await checkPinnedRead({
|
|
55928
56152
|
secret: opts.previewTokenSecret,
|
|
55929
56153
|
token: resolvePreviewToken(request, url),
|
|
55930
56154
|
app,
|
|
@@ -55934,7 +56158,7 @@ ${releaseId}`;
|
|
|
55934
56158
|
authorizePreview: opts.authorizePreview,
|
|
55935
56159
|
authorizeFollow: opts.authorizeFollow
|
|
55936
56160
|
});
|
|
55937
|
-
return
|
|
56161
|
+
return denied2 && json4(denied2.status, denied2.body);
|
|
55938
56162
|
}
|
|
55939
56163
|
async function honourRingPin(request) {
|
|
55940
56164
|
const kept = { request, dropped: false };
|
|
@@ -56385,8 +56609,8 @@ ${releaseId}`;
|
|
|
56385
56609
|
const app = cfgMatch?.[1] ?? resolveApp(request, url);
|
|
56386
56610
|
const pin = resolvePin(request, url);
|
|
56387
56611
|
if (app && pin) {
|
|
56388
|
-
const
|
|
56389
|
-
if (
|
|
56612
|
+
const denied2 = await authorizePinnedRead(request, url, app, pin);
|
|
56613
|
+
if (denied2) return denied2;
|
|
56390
56614
|
}
|
|
56391
56615
|
if (path2 === "/v1/template-source") {
|
|
56392
56616
|
if (!app) return json4(400, { error: "missing_app" });
|
|
@@ -56469,8 +56693,8 @@ ${releaseId}`;
|
|
|
56469
56693
|
if (!app) return json4(400, { error: "missing_app" });
|
|
56470
56694
|
let m;
|
|
56471
56695
|
if (pin) {
|
|
56472
|
-
const
|
|
56473
|
-
if (
|
|
56696
|
+
const denied2 = await authorizePinnedRead(request, url, app, pin);
|
|
56697
|
+
if (denied2) return denied2;
|
|
56474
56698
|
m = await pinnedManifest(app, pin);
|
|
56475
56699
|
if (!m) return json4(404, { error: "release_not_found", app, releaseId: pin });
|
|
56476
56700
|
} else {
|
|
@@ -56656,8 +56880,8 @@ ${releaseId}`;
|
|
|
56656
56880
|
const screenId = screenMatch[1];
|
|
56657
56881
|
if (!app || !isSafeSegment(screenId)) return json4(404, { error: "screen_not_found", screenId });
|
|
56658
56882
|
if (pin) {
|
|
56659
|
-
const
|
|
56660
|
-
if (
|
|
56883
|
+
const denied2 = await authorizePinnedRead(request, url, app, pin, screenId);
|
|
56884
|
+
if (denied2) return denied2;
|
|
56661
56885
|
const m2 = await pinnedManifest(app, pin);
|
|
56662
56886
|
if (!m2) return json4(404, { error: "release_not_found", app, releaseId: pin });
|
|
56663
56887
|
const meta2 = m2.screens[screenId];
|
|
@@ -57180,21 +57404,21 @@ var init_preview_assets_generated = __esm({
|
|
|
57180
57404
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
57181
57405
|
init_preview_assets_format();
|
|
57182
57406
|
PREVIEW_ASSET_MANIFEST = [
|
|
57183
|
-
{ key: "assets/index-
|
|
57184
|
-
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset:
|
|
57185
|
-
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset:
|
|
57186
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
57187
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
57188
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
57189
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
57190
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
57191
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
57192
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
57193
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
57194
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
57195
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
57196
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
57197
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
57407
|
+
{ key: "assets/index-nG7b3MPu.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1104209, sha256: "88839c5eb15058f706e50664752a75646d690de5148f8b504eb82c0f87a70a15" },
|
|
57408
|
+
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 1104217, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
|
|
57409
|
+
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 1108827, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
|
|
57410
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1597411, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
57411
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1688335, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
57412
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1779319, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
57413
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1870299, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
57414
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1961171, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
57415
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 2052151, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
57416
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 2160787, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
57417
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 2269871, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
57418
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 2378919, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
57419
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 2486619, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
57420
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 2574727, length: 4947, sha256: "5c0a3e1b1d5bda7b6bc8cc2a025321bf6d0aa74d1f14b073861f188fd7b13a8b" },
|
|
57421
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 2579674, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
|
|
57198
57422
|
];
|
|
57199
57423
|
}
|
|
57200
57424
|
});
|
|
@@ -57450,7 +57674,7 @@ __export(run_watch_exports, {
|
|
|
57450
57674
|
watchedContentDir: () => watchedContentDir,
|
|
57451
57675
|
writeRunRecord: () => writeRunRecord
|
|
57452
57676
|
});
|
|
57453
|
-
import { closeSync as
|
|
57677
|
+
import { closeSync as closeSync5, constants as constants2, existsSync as existsSync60, fstatSync, lstatSync as lstatSync13, statSync as statSync16, mkdirSync as mkdirSync29, openSync as openSync4, readFileSync as readFileSync67, realpathSync as realpathSync9, renameSync as renameSync7, rmSync as rmSync15, writeFileSync as writeFileSync23, watch as fsWatch } from "node:fs";
|
|
57454
57678
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
57455
57679
|
import { extname as extname4, join as join59, resolve as resolve47, sep as sep16 } from "node:path";
|
|
57456
57680
|
function diffReleases(prev, next) {
|
|
@@ -57585,9 +57809,9 @@ function writeRunRecord(dir, record2) {
|
|
|
57585
57809
|
if (!root) return false;
|
|
57586
57810
|
const tmp = join59(root, `.run.json.${process.pid}.${randomUUID4()}.tmp`);
|
|
57587
57811
|
try {
|
|
57588
|
-
|
|
57812
|
+
writeFileSync23(tmp, `${JSON.stringify(record2, null, 2)}
|
|
57589
57813
|
`, { flag: "wx" });
|
|
57590
|
-
|
|
57814
|
+
renameSync7(tmp, join59(root, "run.json"));
|
|
57591
57815
|
} catch (e) {
|
|
57592
57816
|
rmSync15(tmp, { force: true });
|
|
57593
57817
|
throw e;
|
|
@@ -57644,12 +57868,12 @@ function readConfined(root, rel) {
|
|
|
57644
57868
|
}
|
|
57645
57869
|
const canonicalRoot = realpathSync9(root);
|
|
57646
57870
|
if (!realpathSync9(at2).startsWith(canonicalRoot + sep16)) return null;
|
|
57647
|
-
const fd =
|
|
57871
|
+
const fd = openSync4(at2, constants2.O_RDONLY | (constants2.O_NOFOLLOW ?? 0));
|
|
57648
57872
|
try {
|
|
57649
57873
|
if (!fstatSync(fd).isFile()) return null;
|
|
57650
57874
|
return readFileSync67(fd);
|
|
57651
57875
|
} finally {
|
|
57652
|
-
|
|
57876
|
+
closeSync5(fd);
|
|
57653
57877
|
}
|
|
57654
57878
|
} catch {
|
|
57655
57879
|
return null;
|
|
@@ -58871,7 +59095,7 @@ __export(version_exports, {
|
|
|
58871
59095
|
setAndroidVersion: () => setAndroidVersion,
|
|
58872
59096
|
setIosVersion: () => setIosVersion
|
|
58873
59097
|
});
|
|
58874
|
-
import { readFileSync as readFileSync72, writeFileSync as
|
|
59098
|
+
import { readFileSync as readFileSync72, writeFileSync as writeFileSync24 } from "node:fs";
|
|
58875
59099
|
function readIosVersion(projectYml) {
|
|
58876
59100
|
const marketing = matchScalar(projectYml, "CFBundleShortVersionString");
|
|
58877
59101
|
const build2 = matchScalar(projectYml, "CFBundleVersion");
|
|
@@ -58936,8 +59160,8 @@ function bumpVersion(app, opts) {
|
|
|
58936
59160
|
marketing: opts.marketing ?? current.marketing,
|
|
58937
59161
|
build: opts.build === "increment" || opts.build === void 0 ? current.build + (opts.build === "increment" ? 1 : 0) : opts.build
|
|
58938
59162
|
};
|
|
58939
|
-
|
|
58940
|
-
|
|
59163
|
+
writeFileSync24(iosPath, setIosVersion(iosYml, next));
|
|
59164
|
+
writeFileSync24(gradlePath, setAndroidVersion(gradle, next));
|
|
58941
59165
|
return next;
|
|
58942
59166
|
}
|
|
58943
59167
|
var init_version = __esm({
|
|
@@ -59080,7 +59304,7 @@ var init_asc_status = __esm({
|
|
|
59080
59304
|
});
|
|
59081
59305
|
|
|
59082
59306
|
// ../../core/functions-secrets/src/vault.ts
|
|
59083
|
-
import { createCipheriv, createDecipheriv, randomBytes as
|
|
59307
|
+
import { createCipheriv, createDecipheriv, randomBytes as randomBytes6 } from "node:crypto";
|
|
59084
59308
|
import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "node:fs/promises";
|
|
59085
59309
|
import { dirname as dirname34 } from "node:path";
|
|
59086
59310
|
function createJsonSecretStore(filePath) {
|
|
@@ -59138,7 +59362,7 @@ function createSecretVault(options) {
|
|
|
59138
59362
|
environment: input.environment,
|
|
59139
59363
|
name: input.name,
|
|
59140
59364
|
version: input.version,
|
|
59141
|
-
iv:
|
|
59365
|
+
iv: randomBytes6(12).toString("base64url"),
|
|
59142
59366
|
ciphertext: "",
|
|
59143
59367
|
authTag: ""
|
|
59144
59368
|
};
|
|
@@ -59339,7 +59563,7 @@ var init_push_send = __esm({
|
|
|
59339
59563
|
});
|
|
59340
59564
|
|
|
59341
59565
|
// ../../core/serve-control/src/push-send-service.ts
|
|
59342
|
-
var PUSH_SEND_ERROR_CODES;
|
|
59566
|
+
var PUSH_SEND_ERROR_CODES, PushSendError;
|
|
59343
59567
|
var init_push_send_service = __esm({
|
|
59344
59568
|
"../../core/serve-control/src/push-send-service.ts"() {
|
|
59345
59569
|
PUSH_SEND_ERROR_CODES = [
|
|
@@ -59381,6 +59605,160 @@ var init_push_send_service = __esm({
|
|
|
59381
59605
|
"ping_rate_limited",
|
|
59382
59606
|
"send_outcome_unknown"
|
|
59383
59607
|
];
|
|
59608
|
+
PushSendError = class extends Error {
|
|
59609
|
+
constructor(code, status, retryAfterSec) {
|
|
59610
|
+
super(code);
|
|
59611
|
+
this.code = code;
|
|
59612
|
+
this.status = status;
|
|
59613
|
+
this.retryAfterSec = retryAfterSec;
|
|
59614
|
+
}
|
|
59615
|
+
};
|
|
59616
|
+
}
|
|
59617
|
+
});
|
|
59618
|
+
|
|
59619
|
+
// ../../core/serve-control/src/site-member.ts
|
|
59620
|
+
async function assertOwnerSiteToken(input, fetchImpl = input.fetch ?? fetch) {
|
|
59621
|
+
const info2 = await upstreamJson(fetchImpl, {
|
|
59622
|
+
path: "/oauth2/token-info",
|
|
59623
|
+
body: { token: input.siteToken },
|
|
59624
|
+
unavailable: "site_token_unverifiable",
|
|
59625
|
+
// An expired, revoked or malformed token is answered with a 4xx: the caller's to fix, not an outage.
|
|
59626
|
+
rejected: { code: "site_token_invalid", when: (status) => status >= 400 && status < 500 }
|
|
59627
|
+
});
|
|
59628
|
+
const owned = info2.active === true && info2.subjectType === "USER" && info2.siteId === input.site && info2.accountId === input.ownerAccountId;
|
|
59629
|
+
if (!owned) throw new PushSendError("site_token_invalid", 403);
|
|
59630
|
+
}
|
|
59631
|
+
async function upstreamJson(fetchImpl, call) {
|
|
59632
|
+
let response;
|
|
59633
|
+
try {
|
|
59634
|
+
response = await fetchImpl(`${WIXAPIS}${call.path}`, {
|
|
59635
|
+
method: "POST",
|
|
59636
|
+
redirect: "error",
|
|
59637
|
+
signal: AbortSignal.timeout(TIMEOUT_MS2),
|
|
59638
|
+
headers: {
|
|
59639
|
+
"content-type": "application/json",
|
|
59640
|
+
accept: "application/json",
|
|
59641
|
+
...call.authorization ? { Authorization: call.authorization } : {},
|
|
59642
|
+
...call.siteId ? { "wix-site-id": call.siteId } : {}
|
|
59643
|
+
},
|
|
59644
|
+
body: JSON.stringify(call.body)
|
|
59645
|
+
});
|
|
59646
|
+
} catch {
|
|
59647
|
+
throw new PushSendError(call.unavailable, 503);
|
|
59648
|
+
}
|
|
59649
|
+
if (call.rejected?.when(response.status)) throw new PushSendError(call.rejected.code, 403);
|
|
59650
|
+
if (!response.ok) throw new PushSendError(call.unavailable, 503);
|
|
59651
|
+
try {
|
|
59652
|
+
return await response.json();
|
|
59653
|
+
} catch {
|
|
59654
|
+
throw new PushSendError(call.unavailable, 503);
|
|
59655
|
+
}
|
|
59656
|
+
}
|
|
59657
|
+
var WIXAPIS, TIMEOUT_MS2;
|
|
59658
|
+
var init_site_member = __esm({
|
|
59659
|
+
"../../core/serve-control/src/site-member.ts"() {
|
|
59660
|
+
init_push_send_service();
|
|
59661
|
+
WIXAPIS = "https://www.wixapis.com";
|
|
59662
|
+
TIMEOUT_MS2 = 1e4;
|
|
59663
|
+
}
|
|
59664
|
+
});
|
|
59665
|
+
|
|
59666
|
+
// src/notify-ping-all.ts
|
|
59667
|
+
import { createHash as createHash31 } from "node:crypto";
|
|
59668
|
+
async function listApprovedMembers(input) {
|
|
59669
|
+
const first = await scanMembers(input);
|
|
59670
|
+
const second = await scanMembers(input);
|
|
59671
|
+
if (JSON.stringify(first.fingerprint) !== JSON.stringify(second.fingerprint)) throw new Error("member_roster_unstable");
|
|
59672
|
+
return second.recipients;
|
|
59673
|
+
}
|
|
59674
|
+
async function scanMembers(input) {
|
|
59675
|
+
const recipients = [];
|
|
59676
|
+
const fingerprint = [];
|
|
59677
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
59678
|
+
const seenEmails = /* @__PURE__ */ new Set();
|
|
59679
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
59680
|
+
for (let offset = 0; ; ) {
|
|
59681
|
+
let response;
|
|
59682
|
+
try {
|
|
59683
|
+
response = await fetchImpl(`${WIXAPIS2}/members/v1/members/query`, {
|
|
59684
|
+
method: "POST",
|
|
59685
|
+
headers: { Authorization: input.siteToken, "wix-site-id": input.site, "content-type": "application/json", accept: "application/json" },
|
|
59686
|
+
redirect: "error",
|
|
59687
|
+
signal: AbortSignal.timeout(1e4),
|
|
59688
|
+
body: JSON.stringify({ query: { paging: { limit: PAGE_SIZE, offset } }, fieldsets: ["FULL"] })
|
|
59689
|
+
});
|
|
59690
|
+
} catch {
|
|
59691
|
+
throw new Error("member_lookup_unavailable");
|
|
59692
|
+
}
|
|
59693
|
+
if (!response.ok) throw new Error("member_lookup_unavailable");
|
|
59694
|
+
let raw;
|
|
59695
|
+
try {
|
|
59696
|
+
raw = await response.json();
|
|
59697
|
+
} catch {
|
|
59698
|
+
throw new Error("member_lookup_unavailable");
|
|
59699
|
+
}
|
|
59700
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) throw new Error("member_lookup_unavailable");
|
|
59701
|
+
const result = raw;
|
|
59702
|
+
if (!Array.isArray(result.members)) throw new Error("member_lookup_unavailable");
|
|
59703
|
+
if (result.members.length === 0) return { recipients, fingerprint };
|
|
59704
|
+
if (result.members.length > PAGE_SIZE) throw new Error("member_roster_unstable");
|
|
59705
|
+
for (const member of result.members) {
|
|
59706
|
+
if (member === null || typeof member !== "object" || Array.isArray(member)) throw new Error("member_lookup_unavailable");
|
|
59707
|
+
if (typeof member.id !== "string" || !member.id || seenIds.has(member.id)) throw new Error("member_roster_unstable");
|
|
59708
|
+
seenIds.add(member.id);
|
|
59709
|
+
fingerprint.push(JSON.stringify([member.id, member.loginEmail, member.contactId, member.status]));
|
|
59710
|
+
if (member.status !== "APPROVED") continue;
|
|
59711
|
+
if (typeof member.loginEmail !== "string" || !member.loginEmail || typeof member.contactId !== "string" || !member.contactId) throw new Error("member_roster_incomplete");
|
|
59712
|
+
const email = member.loginEmail.toLowerCase();
|
|
59713
|
+
if (seenEmails.has(email)) throw new Error("member_ambiguous");
|
|
59714
|
+
seenEmails.add(email);
|
|
59715
|
+
recipients.push({ id: member.id, email: member.loginEmail });
|
|
59716
|
+
}
|
|
59717
|
+
offset += result.members.length;
|
|
59718
|
+
}
|
|
59719
|
+
}
|
|
59720
|
+
function campaignRequestId(campaignId, memberId) {
|
|
59721
|
+
const bytes2 = createHash31("sha256").update(JSON.stringify(["himi-push-campaign", campaignId, memberId])).digest().subarray(0, 16);
|
|
59722
|
+
bytes2[6] = bytes2[6] & 15 | 80;
|
|
59723
|
+
bytes2[8] = bytes2[8] & 63 | 128;
|
|
59724
|
+
const hex2 = bytes2.toString("hex");
|
|
59725
|
+
return `${hex2.slice(0, 8)}-${hex2.slice(8, 12)}-${hex2.slice(12, 16)}-${hex2.slice(16, 20)}-${hex2.slice(20)}`;
|
|
59726
|
+
}
|
|
59727
|
+
async function sendCampaign(input) {
|
|
59728
|
+
let accepted = 0;
|
|
59729
|
+
let deduplicated = 0;
|
|
59730
|
+
for (const [index, recipient] of input.recipients.entries()) {
|
|
59731
|
+
if (index > 0) await input.wait(6100);
|
|
59732
|
+
const requestId2 = campaignRequestId(input.campaignId, recipient.id);
|
|
59733
|
+
let outcome = await input.send(recipient, requestId2);
|
|
59734
|
+
let retries = 0;
|
|
59735
|
+
while (outcome.state === "rate_limited" && outcome.retryAfterSec > 0 && retries < 3) {
|
|
59736
|
+
retries += 1;
|
|
59737
|
+
await input.wait(outcome.retryAfterSec * 1e3);
|
|
59738
|
+
outcome = await input.send(recipient, requestId2);
|
|
59739
|
+
}
|
|
59740
|
+
if (outcome.state !== "accepted") {
|
|
59741
|
+
throw new CampaignFailure(outcome.state === "failed" ? outcome.code : "rate_limited", index, recipient.email);
|
|
59742
|
+
}
|
|
59743
|
+
if (outcome.deduplicated) deduplicated += 1;
|
|
59744
|
+
else accepted += 1;
|
|
59745
|
+
input.onProgress?.(index + 1);
|
|
59746
|
+
}
|
|
59747
|
+
return { accepted, deduplicated };
|
|
59748
|
+
}
|
|
59749
|
+
var CampaignFailure, PAGE_SIZE, WIXAPIS2;
|
|
59750
|
+
var init_notify_ping_all = __esm({
|
|
59751
|
+
"src/notify-ping-all.ts"() {
|
|
59752
|
+
CampaignFailure = class extends Error {
|
|
59753
|
+
constructor(code, completed, memberEmail) {
|
|
59754
|
+
super(code);
|
|
59755
|
+
this.code = code;
|
|
59756
|
+
this.completed = completed;
|
|
59757
|
+
this.memberEmail = memberEmail;
|
|
59758
|
+
}
|
|
59759
|
+
};
|
|
59760
|
+
PAGE_SIZE = 100;
|
|
59761
|
+
WIXAPIS2 = "https://www.wixapis.com";
|
|
59384
59762
|
}
|
|
59385
59763
|
});
|
|
59386
59764
|
|
|
@@ -59398,8 +59776,11 @@ function refuse5(io, error, hint, exit = 2, extra = {}) {
|
|
|
59398
59776
|
async function runNotifyPing(flags, io, deps = {}) {
|
|
59399
59777
|
const flagError = flagRefusal(flags);
|
|
59400
59778
|
if (flagError) return refuse5(io, flagError);
|
|
59779
|
+
const allMembers = flags["all-members"] === true;
|
|
59780
|
+
if (allMembers && text7(flags["member-email"])) return refuse5(io, "recipient_conflict", "Choose --all-members or --member-email.");
|
|
59781
|
+
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.");
|
|
59401
59782
|
const input = mergePushInputs(pushInputsFromContent(resolve50(text7(flags.content) ?? process.cwd())), flags);
|
|
59402
|
-
const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !text7(flags[f]))];
|
|
59783
|
+
const missing = [...input.app ? [] : ["app"], ...input.site ? [] : ["site"], ...REQUIRED_FLAGS.filter((f) => !(allMembers && f === "member-email") && !text7(flags[f]))];
|
|
59403
59784
|
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 });
|
|
59404
59785
|
const requestId2 = text7(flags["request-id"]) ?? (deps.newRequestId ?? randomUUID5)();
|
|
59405
59786
|
if (!UUID_RE.test(requestId2)) return refuse5(io, "invalid_request_id", "Reuse the requestId a previous send printed.");
|
|
@@ -59414,6 +59795,7 @@ async function runNotifyPing(flags, io, deps = {}) {
|
|
|
59414
59795
|
} catch {
|
|
59415
59796
|
return refuse5(io, "wix_site_token_required", "Run wix login as the site owner; the site token reads this site's members.", 1);
|
|
59416
59797
|
}
|
|
59798
|
+
if (allMembers) return runAllMembers({ input: { app: ownership.slug, site: input.site }, siteToken: siteToken2, session, requestId: requestId2, flags, io, deps });
|
|
59417
59799
|
const body = {
|
|
59418
59800
|
app: ownership.slug,
|
|
59419
59801
|
site: input.site,
|
|
@@ -59427,6 +59809,88 @@ async function runNotifyPing(flags, io, deps = {}) {
|
|
|
59427
59809
|
const http = await pushSendRequest({ target: session.target, wixToken: session.wixToken, siteToken: siteToken2, body, previewTag: session.previewTag, fetchImpl: deps.fetchImpl });
|
|
59428
59810
|
return report2(http, body, flags, io);
|
|
59429
59811
|
}
|
|
59812
|
+
async function runAllMembers(args) {
|
|
59813
|
+
const { input, siteToken: siteToken2, session, requestId: requestId2, flags, io, deps } = args;
|
|
59814
|
+
const ownerAccountId = decodeControlTokenClaims(session.controlToken)?.sub;
|
|
59815
|
+
if (!ownerAccountId) return refuse5(io, "owner_login_required");
|
|
59816
|
+
const readiness = await pushSetupRequest({
|
|
59817
|
+
target: session.target,
|
|
59818
|
+
wixToken: session.wixToken,
|
|
59819
|
+
operation: "status",
|
|
59820
|
+
query: input,
|
|
59821
|
+
previewTag: session.previewTag,
|
|
59822
|
+
fetchImpl: deps.fetchImpl
|
|
59823
|
+
});
|
|
59824
|
+
if (!readiness.ok) {
|
|
59825
|
+
const reported = String(readiness.body?.error ?? "");
|
|
59826
|
+
const code = KNOWN_CODES.has(reported) ? reported : "push_setup_unavailable";
|
|
59827
|
+
return refuse5(io, code, HINTS[code], 1);
|
|
59828
|
+
}
|
|
59829
|
+
if (readiness.body?.app !== input.app || readiness.body?.site !== input.site || readiness.body?.state !== "ready") {
|
|
59830
|
+
return refuse5(io, "push_not_ready", HINTS.push_not_ready, 1);
|
|
59831
|
+
}
|
|
59832
|
+
let recipients;
|
|
59833
|
+
try {
|
|
59834
|
+
await assertOwnerSiteToken({
|
|
59835
|
+
site: input.site,
|
|
59836
|
+
siteToken: siteToken2,
|
|
59837
|
+
ownerAccountId,
|
|
59838
|
+
fetch: deps.fetchImpl
|
|
59839
|
+
});
|
|
59840
|
+
recipients = await listApprovedMembers({ site: input.site, siteToken: siteToken2, fetchImpl: deps.fetchImpl });
|
|
59841
|
+
} catch (error) {
|
|
59842
|
+
const code = error instanceof PushSendError ? error.code : error instanceof Error && ROSTER_CODES.has(error.message) ? error.message : "member_lookup_unavailable";
|
|
59843
|
+
return refuse5(io, code, void 0, 1);
|
|
59844
|
+
}
|
|
59845
|
+
const base = { app: input.app, site: input.site, title: text7(flags.title), ...text7(flags.body) ? { body: text7(flags.body) } : {}, link: text7(flags.link) };
|
|
59846
|
+
const send2 = (recipient, memberRequestId, dryRun = false) => pushSendRequest({
|
|
59847
|
+
target: session.target,
|
|
59848
|
+
wixToken: session.wixToken,
|
|
59849
|
+
siteToken: siteToken2,
|
|
59850
|
+
previewTag: session.previewTag,
|
|
59851
|
+
fetchImpl: deps.fetchImpl,
|
|
59852
|
+
body: { ...base, memberEmail: recipient.email, requestId: memberRequestId, ...dryRun ? { dryRun: true } : {} }
|
|
59853
|
+
});
|
|
59854
|
+
if (flags["dry-run"] === true) {
|
|
59855
|
+
if (recipients.length) {
|
|
59856
|
+
const result = await send2(recipients[0], requestId2, true);
|
|
59857
|
+
const code = refusalCode(result);
|
|
59858
|
+
if (code) return refuse5(io, code, HINTS[code], 1);
|
|
59859
|
+
}
|
|
59860
|
+
io.log(JSON.stringify({ ok: true, state: "dry_run", campaignId: requestId2, recipients: recipients.length, sent: false }));
|
|
59861
|
+
return 0;
|
|
59862
|
+
}
|
|
59863
|
+
io.log(JSON.stringify({ ok: true, state: "started", campaignId: requestId2, recipients: recipients.length }));
|
|
59864
|
+
try {
|
|
59865
|
+
const result = await sendCampaign({
|
|
59866
|
+
recipients,
|
|
59867
|
+
campaignId: requestId2,
|
|
59868
|
+
wait: deps.wait ?? ((ms) => new Promise((resolve54) => setTimeout(resolve54, ms))),
|
|
59869
|
+
onProgress: (completed) => {
|
|
59870
|
+
if (completed % 10 === 0 || completed === recipients.length) {
|
|
59871
|
+
io.log(JSON.stringify({ ok: true, state: "progress", campaignId: requestId2, completed, recipients: recipients.length }));
|
|
59872
|
+
}
|
|
59873
|
+
},
|
|
59874
|
+
send: async (recipient, memberRequestId) => {
|
|
59875
|
+
const response = await send2(recipient, memberRequestId);
|
|
59876
|
+
const code = refusalCode(response);
|
|
59877
|
+
if (code === "rate_limited" && response.retryAfterSec) return { state: "rate_limited", retryAfterSec: response.retryAfterSec };
|
|
59878
|
+
if (code) return { state: "failed", code };
|
|
59879
|
+
return { state: "accepted", deduplicated: response.body?.deduplicated === true };
|
|
59880
|
+
}
|
|
59881
|
+
});
|
|
59882
|
+
io.log(JSON.stringify({ ok: true, state: "completed", campaignId: requestId2, recipients: recipients.length, ...result }));
|
|
59883
|
+
return 0;
|
|
59884
|
+
} catch (error) {
|
|
59885
|
+
if (!(error instanceof CampaignFailure)) return refuse5(io, "send_outcome_unknown", void 0, 1, { campaignId: requestId2 });
|
|
59886
|
+
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];
|
|
59887
|
+
return refuse5(io, error.code, hint, 1, {
|
|
59888
|
+
campaignId: requestId2,
|
|
59889
|
+
completed: error.completed,
|
|
59890
|
+
memberEmail: error.memberEmail
|
|
59891
|
+
});
|
|
59892
|
+
}
|
|
59893
|
+
}
|
|
59430
59894
|
function flagRefusal(flags) {
|
|
59431
59895
|
if (LOCAL_SENDER_FLAGS.some((f) => flags[f] !== void 0)) return "flag_not_supported_with_ping";
|
|
59432
59896
|
if (SWITCHES.some((f) => flags[f] !== void 0 && typeof flags[f] !== "boolean")) return "invalid_boolean_flag";
|
|
@@ -59461,20 +59925,24 @@ function summary(result, sent) {
|
|
|
59461
59925
|
}
|
|
59462
59926
|
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.`;
|
|
59463
59927
|
}
|
|
59464
|
-
var LOCAL_SENDER_FLAGS, SWITCHES, REQUIRED_FLAGS, UUID_RE, KNOWN_CODES, HINTS, text7;
|
|
59928
|
+
var LOCAL_SENDER_FLAGS, SWITCHES, REQUIRED_FLAGS, UUID_RE, KNOWN_CODES, ROSTER_CODES, HINTS, text7;
|
|
59465
59929
|
var init_notify_ping = __esm({
|
|
59466
59930
|
"src/notify-ping.ts"() {
|
|
59467
59931
|
init_push_send();
|
|
59932
|
+
init_push_setup();
|
|
59933
|
+
init_site_member();
|
|
59468
59934
|
init_push_send_service();
|
|
59469
59935
|
init_hosted_owner();
|
|
59936
|
+
init_notify_ping_all();
|
|
59470
59937
|
init_owner_claim();
|
|
59471
59938
|
init_push_onboarding();
|
|
59472
59939
|
init_wix_owner();
|
|
59473
59940
|
LOCAL_SENDER_FLAGS = ["token", "device", "all", "admin-url", "admin-session", "silent", "badge", "data", "category", "channel", "platform", "bundle-id"];
|
|
59474
|
-
SWITCHES = ["json", "dry-run"];
|
|
59941
|
+
SWITCHES = ["json", "dry-run", "all-members"];
|
|
59475
59942
|
REQUIRED_FLAGS = ["member-email", "title", "link"];
|
|
59476
59943
|
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
59477
59944
|
KNOWN_CODES = new Set(PUSH_SEND_ERROR_CODES);
|
|
59945
|
+
ROSTER_CODES = /* @__PURE__ */ new Set(["member_lookup_unavailable", "member_roster_unstable", "member_roster_incomplete", "member_ambiguous"]);
|
|
59478
59946
|
HINTS = {
|
|
59479
59947
|
push_not_ready: "Run himi notify setup for this app and site first; status must be ready.",
|
|
59480
59948
|
member_not_found: "Use the login email of an approved member of this site.",
|
|
@@ -59500,7 +59968,7 @@ __export(notify_exports, {
|
|
|
59500
59968
|
runNotify: () => runNotify,
|
|
59501
59969
|
saveAdminSession: () => saveAdminSession
|
|
59502
59970
|
});
|
|
59503
|
-
import { chmodSync as chmodSync3, mkdirSync as mkdirSync30, readFileSync as readFileSync76, writeFileSync as
|
|
59971
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync30, readFileSync as readFileSync76, writeFileSync as writeFileSync25 } from "node:fs";
|
|
59504
59972
|
import { homedir as homedir6 } from "node:os";
|
|
59505
59973
|
import { dirname as dirname35, join as join62 } from "node:path";
|
|
59506
59974
|
function defaultSessionsPath() {
|
|
@@ -59517,7 +59985,7 @@ function saveAdminSession(adminUrl, session, path2 = defaultSessionsPath()) {
|
|
|
59517
59985
|
const file = loadSessionsFile(path2);
|
|
59518
59986
|
file.sessions = { ...file.sessions, [adminUrl]: session };
|
|
59519
59987
|
mkdirSync30(dirname35(path2), { recursive: true, mode: 448 });
|
|
59520
|
-
|
|
59988
|
+
writeFileSync25(path2, JSON.stringify(file, null, 2) + "\n", { mode: 384 });
|
|
59521
59989
|
try {
|
|
59522
59990
|
chmodSync3(dirname35(path2), 448);
|
|
59523
59991
|
chmodSync3(path2, 384);
|
|
@@ -63276,7 +63744,7 @@ var init_brand_font = __esm({
|
|
|
63276
63744
|
});
|
|
63277
63745
|
|
|
63278
63746
|
// src/site-analyze/write-artifacts.ts
|
|
63279
|
-
import { mkdirSync as mkdirSync31, writeFileSync as
|
|
63747
|
+
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync26 } from "node:fs";
|
|
63280
63748
|
import { join as join63 } from "node:path";
|
|
63281
63749
|
function attachVeloSources(book, sources, put) {
|
|
63282
63750
|
const byPath = new Map((sources ?? []).map((s) => [s.path, s.text]));
|
|
@@ -63438,7 +63906,7 @@ async function writeBusinessBook(result, opts) {
|
|
|
63438
63906
|
const put = (rel, body) => {
|
|
63439
63907
|
const p = join63(out2, rel);
|
|
63440
63908
|
mkdirSync31(join63(p, ".."), { recursive: true });
|
|
63441
|
-
|
|
63909
|
+
writeFileSync26(p, body);
|
|
63442
63910
|
files.push(rel);
|
|
63443
63911
|
};
|
|
63444
63912
|
const book = result.book;
|
|
@@ -63531,7 +63999,7 @@ var init_customer_build = __esm({
|
|
|
63531
63999
|
});
|
|
63532
64000
|
|
|
63533
64001
|
// src/site-analyze/apply.ts
|
|
63534
|
-
import { existsSync as existsSync65, readFileSync as readFileSync77, writeFileSync as
|
|
64002
|
+
import { existsSync as existsSync65, readFileSync as readFileSync77, writeFileSync as writeFileSync27, copyFileSync as copyFileSync3, mkdirSync as mkdirSync32, realpathSync as realpathSync10, statSync as statSync18 } from "node:fs";
|
|
63535
64003
|
import { dirname as dirname36, isAbsolute as isAbsolute7, join as join64, resolve as resolve51, sep as sep17 } from "node:path";
|
|
63536
64004
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
63537
64005
|
function unpairedRedirectNote(overlay) {
|
|
@@ -63683,10 +64151,10 @@ function buildMergedContract(options) {
|
|
|
63683
64151
|
const body = `${JSON.stringify(merged, null, 2)}
|
|
63684
64152
|
`;
|
|
63685
64153
|
const path2 = join64(packageDir, "provisioning.contract.json");
|
|
63686
|
-
|
|
64154
|
+
writeFileSync27(path2, body);
|
|
63687
64155
|
const localPath = join64(appDir3, LOCAL_CONTRACT_REL);
|
|
63688
64156
|
mkdirSync32(dirname36(localPath), { recursive: true });
|
|
63689
|
-
|
|
64157
|
+
writeFileSync27(localPath, body);
|
|
63690
64158
|
staged.push(localPath);
|
|
63691
64159
|
return { path: path2, staged };
|
|
63692
64160
|
}
|
|
@@ -63785,10 +64253,10 @@ async function applyOverlays(input) {
|
|
|
63785
64253
|
const cur = JSON.parse(readFileSync77(pkgProv, "utf8"));
|
|
63786
64254
|
const merged = deepMerge4(cur, overlay);
|
|
63787
64255
|
packageFaq = merged.faq;
|
|
63788
|
-
|
|
64256
|
+
writeFileSync27(pkgProv, JSON.stringify(merged, null, 2) + "\n");
|
|
63789
64257
|
wrote.push(pkgProv);
|
|
63790
64258
|
} else {
|
|
63791
|
-
|
|
64259
|
+
writeFileSync27(pkgProv, JSON.stringify(overlay, null, 2) + "\n");
|
|
63792
64260
|
wrote.push(pkgProv);
|
|
63793
64261
|
}
|
|
63794
64262
|
const pkgTokens = join64(cwd, "tokens.json");
|
|
@@ -63809,12 +64277,12 @@ async function applyOverlays(input) {
|
|
|
63809
64277
|
if (bringsBrand) {
|
|
63810
64278
|
const accent = tokens.colors?.accentPrimary;
|
|
63811
64279
|
const primary = typeof accent === "string" ? accent : accent?.light;
|
|
63812
|
-
const
|
|
63813
|
-
const glow =
|
|
64280
|
+
const shadows2 = merged.shadows;
|
|
64281
|
+
const glow = shadows2 && typeof shadows2 === "object" && !Array.isArray(shadows2) ? shadows2[BRAND_GLOW_SHADOW] : void 0;
|
|
63814
64282
|
if (primary && glow && typeof glow.color === "string") glow.color = primary;
|
|
63815
64283
|
stripBrandFromIdiom(merged);
|
|
63816
64284
|
}
|
|
63817
|
-
|
|
64285
|
+
writeFileSync27(pkgTokens, JSON.stringify(merged, null, 2) + "\n");
|
|
63818
64286
|
wrote.push(pkgTokens);
|
|
63819
64287
|
}
|
|
63820
64288
|
const homeAction = homeRefreshActionId(shell);
|
|
@@ -63844,7 +64312,7 @@ async function applyOverlays(input) {
|
|
|
63844
64312
|
}
|
|
63845
64313
|
}
|
|
63846
64314
|
if (next !== prev) {
|
|
63847
|
-
|
|
64315
|
+
writeFileSync27(homeSrc, next);
|
|
63848
64316
|
wrote.push(homeSrc);
|
|
63849
64317
|
}
|
|
63850
64318
|
if (patched.unparsed) {
|
|
@@ -68600,7 +69068,7 @@ __export(site_create_exports, {
|
|
|
68600
69068
|
runSiteList: () => runSiteList,
|
|
68601
69069
|
writeProvisioningBinding: () => writeProvisioningBinding
|
|
68602
69070
|
});
|
|
68603
|
-
import { existsSync as existsSync66, readFileSync as readFileSync79, writeFileSync as
|
|
69071
|
+
import { existsSync as existsSync66, readFileSync as readFileSync79, writeFileSync as writeFileSync28 } from "node:fs";
|
|
68604
69072
|
import { resolve as resolvePath2 } from "node:path";
|
|
68605
69073
|
function oauthClientName(projectName) {
|
|
68606
69074
|
return `${projectName} client`;
|
|
@@ -68749,7 +69217,7 @@ async function runSiteCreate(opts) {
|
|
|
68749
69217
|
if (!wantOauthApp) return { ...base, nextSteps: nextSteps(metaSiteId) };
|
|
68750
69218
|
return { ...base, clientId, redirectUri, nextSteps: nextSteps(metaSiteId, clientId) };
|
|
68751
69219
|
}
|
|
68752
|
-
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync66, readFileSync: readFileSync79, writeFileSync:
|
|
69220
|
+
function writeProvisioningBinding(target, binding2, fs = { existsSync: existsSync66, readFileSync: readFileSync79, writeFileSync: writeFileSync28 }) {
|
|
68753
69221
|
const msid = binding2.siteId;
|
|
68754
69222
|
const path2 = resolvePath2(target);
|
|
68755
69223
|
const committed = committedShellProvisioning(path2);
|
|
@@ -69422,10 +69890,10 @@ var init_context = __esm({
|
|
|
69422
69890
|
});
|
|
69423
69891
|
|
|
69424
69892
|
// src/cli.ts
|
|
69425
|
-
import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync80, mkdirSync as mkdirSync33, writeFileSync as
|
|
69893
|
+
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";
|
|
69426
69894
|
import { execFile, execFileSync as execFileSync7, spawnSync as spawnSync5, spawn as spawn7 } from "node:child_process";
|
|
69427
69895
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
69428
|
-
import { createHash as
|
|
69896
|
+
import { createHash as createHash32, randomUUID as randomUUID7 } from "node:crypto";
|
|
69429
69897
|
import { tmpdir as tmpdir5, homedir as homedir7, hostname } from "node:os";
|
|
69430
69898
|
import { join as join65, resolve as resolve53, relative as relative14, basename as basename17, dirname as dirname37 } from "node:path";
|
|
69431
69899
|
import { fileURLToPath as fileURLToPath26 } from "node:url";
|
|
@@ -71447,6 +71915,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
71447
71915
|
"allow-destructive",
|
|
71448
71916
|
"allow-draft",
|
|
71449
71917
|
"all",
|
|
71918
|
+
"all-members",
|
|
71450
71919
|
"all-screens",
|
|
71451
71920
|
"ai",
|
|
71452
71921
|
"binary",
|
|
@@ -71481,6 +71950,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
71481
71950
|
"wait",
|
|
71482
71951
|
"wix",
|
|
71483
71952
|
"silent",
|
|
71953
|
+
"with-files",
|
|
71484
71954
|
"include-disabled",
|
|
71485
71955
|
"skip-build",
|
|
71486
71956
|
"refresh",
|
|
@@ -71872,9 +72342,12 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
71872
72342
|
file is not the plane's per-release archive.
|
|
71873
72343
|
himi share --file <package.himi> [--expires-at <ISO>] | revoke --app <app> <shareId>
|
|
71874
72344
|
publish a content-addressed package link for a released app
|
|
71875
|
-
himi mcp [plugin --out <dir>]
|
|
72345
|
+
himi mcp [plugin --out <dir>] [--with-files]
|
|
72346
|
+
the himi tools as a local MCP server over stdio, for coding
|
|
71876
72347
|
agents (Claude Code, Cursor, Codex, VS Code). \`himi init\`
|
|
71877
|
-
configures each; see \`himi docs himi-mcp\`.
|
|
72348
|
+
configures each; see \`himi docs himi-mcp\`. --with-files
|
|
72349
|
+
adds file tools confined to the workspace, for a host that
|
|
72350
|
+
cannot edit files (Claude Desktop chat).
|
|
71878
72351
|
himi run [<package.himi|dir|url>] [--browser] [--watch [--idle-exit <min>]] [--lan] [--port <n>] [--chrome preview|app] [--screen <id>] [--surface <id>] [--no-open]
|
|
71879
72352
|
serve a package on localhost + open it in a browser. No serve
|
|
71880
72353
|
plane, no dev-server. With no argument it packs the current
|
|
@@ -72044,6 +72517,12 @@ var USAGE = `himi \u2014 the Himalaya authoring CLI (remote dev loop)
|
|
|
72044
72517
|
wix login as the site owner, and a ready notify setup. Acceptance is not delivery.
|
|
72045
72518
|
--dry-run checks ownership, member, link and readiness without sending. After an unknown
|
|
72046
72519
|
outcome, re-run the same command with the printed --request-id; Ping never runs it twice.
|
|
72520
|
+
himi notify send --provider ping --target wix --app <a> --site <msid> --all-members
|
|
72521
|
+
--title <s> [--body <s>] --link <scheme>://screen/<id>[?\u2026] [--dry-run | --yes] [--request-id <uuid>]
|
|
72522
|
+
Sends to every approved site member with a login email. --dry-run counts recipients and
|
|
72523
|
+
checks one member's server gates; --yes is required to send. The CLI paces sends for the
|
|
72524
|
+
owner's 10/minute limit. Reuse the campaign ID with --request-id after an interrupted run
|
|
72525
|
+
within Ping's 24-hour deduplication window. Acceptance is not delivery.
|
|
72047
72526
|
himi notify send --app <a> (--token <t> | --device <id> | --all) --title <s> [--body <s>] [--link <url>]
|
|
72048
72527
|
deliver a REAL push notification to registered devices \u2014
|
|
72049
72528
|
APNs (.p8) for iOS, FCM v1 for Android. --all fans out to
|
|
@@ -72236,7 +72715,7 @@ var COMMANDS = [
|
|
|
72236
72715
|
{ 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]" },
|
|
72237
72716
|
{ 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>]" },
|
|
72238
72717
|
{ name: "logout", summary: "remove the stored control token for a target", required: "[--target <t>]" },
|
|
72239
|
-
{ 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
|
|
72718
|
+
{ 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]" },
|
|
72240
72719
|
{ 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]" },
|
|
72241
72720
|
{ 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>]" },
|
|
72242
72721
|
{ 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]" },
|
|
@@ -72475,7 +72954,7 @@ function readUpdateCache(path2) {
|
|
|
72475
72954
|
function writeUpdateCache(path2, cache) {
|
|
72476
72955
|
try {
|
|
72477
72956
|
mkdirSync33(dirname37(path2), { recursive: true, mode: 448 });
|
|
72478
|
-
|
|
72957
|
+
writeFileSync29(path2, JSON.stringify(cache, null, 2) + "\n", { mode: 384 });
|
|
72479
72958
|
} catch {
|
|
72480
72959
|
}
|
|
72481
72960
|
}
|
|
@@ -72506,7 +72985,7 @@ function globalPrefixWritable() {
|
|
|
72506
72985
|
const root = globalNodeModulesRoot();
|
|
72507
72986
|
if (!root) return false;
|
|
72508
72987
|
try {
|
|
72509
|
-
accessSync(root,
|
|
72988
|
+
accessSync(root, constants3.W_OK);
|
|
72510
72989
|
return true;
|
|
72511
72990
|
} catch {
|
|
72512
72991
|
return false;
|
|
@@ -72617,7 +73096,7 @@ function acquireUpdateLock(cachePath, now, hooks = {}) {
|
|
|
72617
73096
|
};
|
|
72618
73097
|
const tryCreate = (path2) => {
|
|
72619
73098
|
try {
|
|
72620
|
-
|
|
73099
|
+
writeFileSync29(path2, mine, { flag: "wx", mode: 384 });
|
|
72621
73100
|
return true;
|
|
72622
73101
|
} catch {
|
|
72623
73102
|
return false;
|
|
@@ -73205,7 +73684,7 @@ function executableOnPath(name, env = process.env) {
|
|
|
73205
73684
|
const candidate = join65(dir, `${name}${suffix}`);
|
|
73206
73685
|
try {
|
|
73207
73686
|
if (!statSync19(candidate).isFile()) continue;
|
|
73208
|
-
if (process.platform !== "win32") accessSync(candidate,
|
|
73687
|
+
if (process.platform !== "win32") accessSync(candidate, constants3.X_OK);
|
|
73209
73688
|
return true;
|
|
73210
73689
|
} catch {
|
|
73211
73690
|
}
|
|
@@ -73332,7 +73811,7 @@ function readConfigSource(dir) {
|
|
|
73332
73811
|
}
|
|
73333
73812
|
function writePngFile(path2, base64) {
|
|
73334
73813
|
mkdirSync33(dirname37(path2), { recursive: true });
|
|
73335
|
-
|
|
73814
|
+
writeFileSync29(path2, Buffer.from(base64, "base64"));
|
|
73336
73815
|
return path2;
|
|
73337
73816
|
}
|
|
73338
73817
|
async function seedAgentFilesFor(dir, flags, mode = "init") {
|
|
@@ -74535,7 +75014,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74535
75014
|
try {
|
|
74536
75015
|
const bytes2 = readFileSync80(iconPath);
|
|
74537
75016
|
payload.icon = bytes2.toString("base64");
|
|
74538
|
-
iconHash =
|
|
75017
|
+
iconHash = createHash32("sha256").update(bytes2).digest("hex");
|
|
74539
75018
|
} catch {
|
|
74540
75019
|
}
|
|
74541
75020
|
}
|
|
@@ -74955,7 +75434,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74955
75434
|
const files = himiPluginFiles2(skills.skillMd);
|
|
74956
75435
|
for (const f of files) {
|
|
74957
75436
|
mkdirSync33(dirname37(join65(dir, f.path)), { recursive: true });
|
|
74958
|
-
|
|
75437
|
+
writeFileSync29(join65(dir, f.path), f.text);
|
|
74959
75438
|
}
|
|
74960
75439
|
print({ ok: true, dir, files: files.map((f) => f.path), next: [`claude plugin validate ${dir}`, `claude --plugin-dir ${dir}`] });
|
|
74961
75440
|
return 0;
|
|
@@ -74981,7 +75460,7 @@ ${doNow.map((l) => ` ${l}`).join("\n")}`);
|
|
|
74981
75460
|
const out2 = resolve53(str8(flags.out) ?? join65(dir, ".himi", "making-of.html"));
|
|
74982
75461
|
const { html, plan } = buildReel2(dir);
|
|
74983
75462
|
mkdirSync33(dirname37(out2), { recursive: true });
|
|
74984
|
-
|
|
75463
|
+
writeFileSync29(out2, html);
|
|
74985
75464
|
const { pathToFileURL: pathToFileURL9 } = await import("node:url");
|
|
74986
75465
|
const url2 = pathToFileURL9(out2).href;
|
|
74987
75466
|
const open2 = flags["no-open"] !== true;
|
|
@@ -76325,7 +76804,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
76325
76804
|
let localSourceHash;
|
|
76326
76805
|
try {
|
|
76327
76806
|
const { collectAppSource: collectAppSource2, zipAppSource: zipAppSource2 } = await Promise.resolve().then(() => (init_app_source(), app_source_exports));
|
|
76328
|
-
localSourceHash =
|
|
76807
|
+
localSourceHash = createHash32("sha256").update(zipAppSource2(collectAppSource2(dir).entries).toString("base64")).digest("hex");
|
|
76329
76808
|
} catch {
|
|
76330
76809
|
}
|
|
76331
76810
|
return runReleasePatch({
|
|
@@ -77201,9 +77680,9 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77201
77680
|
const { describeChanges: describeChanges2, headline: headline2 } = await Promise.resolve().then(() => (init_build_changes(), build_changes_exports));
|
|
77202
77681
|
const changes = describeChanges2(live2, join65(next, running.app), diff);
|
|
77203
77682
|
const retired = `${live2}.retired-${Date.now()}`;
|
|
77204
|
-
|
|
77683
|
+
renameSync8(live2, retired);
|
|
77205
77684
|
try {
|
|
77206
|
-
|
|
77685
|
+
renameSync8(join65(next, running.app), live2);
|
|
77207
77686
|
} catch {
|
|
77208
77687
|
cpSync3(join65(next, running.app), live2, { recursive: true });
|
|
77209
77688
|
}
|
|
@@ -77941,7 +78420,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77941
78420
|
});
|
|
77942
78421
|
}
|
|
77943
78422
|
const bytes2 = readFileSync80(file);
|
|
77944
|
-
const sha =
|
|
78423
|
+
const sha = createHash32("sha256").update(bytes2).digest("hex");
|
|
77945
78424
|
const forScreens = (str8(flags["for-screen"]) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
77946
78425
|
if (flags["no-rebind"] !== void 0 && flags["no-rebind"] !== true) {
|
|
77947
78426
|
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 }));
|