@wix/himalaya-cli 0.1145.0 → 0.1147.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/stdlib/wix-sdk/comments-v1/src/extensions.d.ts +4 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/forum/src/extensions.d.ts +10 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-comments.mjs +5 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-forum.mjs +13 -0
- package/dist/cli.mjs +75 -19
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/headless-loop.md +34 -0
- package/guides/himi-mcp.md +2 -0
- package/guides/sdk-reference.json +13 -1
- package/guides/tier-5-add-a-screen.md +4 -2
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +62 -3
- package/templates/beauty-salon/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/beauty-salon/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/beauty-salon/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/beauty-salon/tier5-src/himi-store-product/index.ts +35 -4
- package/templates/beauty-salon-owner/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-home/index.ts +6 -1
- package/templates/branded-lite/dev/index.ts +273 -12
- package/templates/branded-lite/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/branded-lite/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/branded-lite/tier5-src/himi-branded-lite-cms-collection/index.ts +43 -3
- package/templates/branded-lite/tier5-src/himi-branded-lite-faq/index.ts +69 -13
- package/templates/branded-lite/tier5-src/himi-branded-lite-feed/index.ts +23 -3
- package/templates/branded-lite/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/branded-lite/tier5-src/himi-events-detail/index.ts +40 -3
- package/templates/branded-lite/tier5-src/himi-store-product/index.ts +35 -4
- package/templates/branded-lite/tier5-src/wix-spaces-forum-post/index.ts +29 -5
- package/templates/community-club/dev/index.ts +135 -5
- package/templates/community-club/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/community-club/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/community-club/tier5-src/himi-branded-lite-cms-collection/index.ts +43 -3
- package/templates/community-club/tier5-src/himi-branded-lite-feed/index.ts +23 -3
- package/templates/community-club/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/community-club/tier5-src/himi-events-detail/index.ts +40 -3
- package/templates/community-club-owner/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/community-club-owner/tier5-src/himi-owner-lite-home/index.ts +6 -1
- package/templates/events-meetups/dev/index.ts +91 -4
- package/templates/events-meetups/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/events-meetups/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/events-meetups/tier5-src/himi-branded-lite-feed/index.ts +23 -3
- package/templates/events-meetups/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/events-meetups/tier5-src/himi-events-detail/index.ts +40 -3
- package/templates/events-meetups-owner/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-home/index.ts +6 -1
- package/templates/gym-fitness/dev/index.ts +92 -4
- package/templates/gym-fitness/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/gym-fitness/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/gym-fitness/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/gym-fitness/tier5-src/himi-events-detail/index.ts +40 -3
- package/templates/gym-fitness/tier5-src/himi-store-product/index.ts +35 -4
- package/templates/gym-fitness-owner/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-home/index.ts +6 -1
- package/templates/nonprofit-cause/dev/index.ts +91 -4
- package/templates/nonprofit-cause/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/nonprofit-cause/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/nonprofit-cause/tier5-src/himi-branded-lite-feed/index.ts +23 -3
- package/templates/nonprofit-cause/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/nonprofit-cause/tier5-src/himi-events-detail/index.ts +40 -3
- package/templates/nonprofit-cause-owner/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-home/index.ts +6 -1
- package/templates/owner-lite/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/owner-lite/tier5-src/himi-owner-lite-home/index.ts +6 -1
- package/templates/podcast-creator/dev/index.ts +91 -4
- package/templates/podcast-creator/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/podcast-creator/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/podcast-creator/tier5-src/himi-branded-lite-feed/index.ts +23 -3
- package/templates/podcast-creator/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/podcast-creator/tier5-src/himi-events-detail/index.ts +40 -3
- package/templates/podcast-creator-owner/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-home/index.ts +6 -1
- package/templates/portfolio-creative/dev/index.ts +92 -4
- package/templates/portfolio-creative/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/portfolio-creative/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/portfolio-creative/tier5-src/himi-events-detail/index.ts +40 -3
- package/templates/portfolio-creative/tier5-src/himi-store-product/index.ts +35 -4
- package/templates/portfolio-creative-owner/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-home/index.ts +6 -1
- package/templates/restaurant/dev/index.ts +60 -2
- package/templates/restaurant/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/restaurant/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/restaurant/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/restaurant/tier5-src/himi-events-detail/index.ts +40 -3
- package/templates/restaurant-owner/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-home/index.ts +6 -1
- package/templates/retail-store/dev/index.ts +62 -3
- package/templates/retail-store/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/retail-store/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/retail-store/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/retail-store/tier5-src/himi-store-product/index.ts +35 -4
- package/templates/retail-store-owner/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-home/index.ts +6 -1
- package/templates/yoga-studio/dev/index.ts +60 -2
- package/templates/yoga-studio/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/yoga-studio/tier5-src/himi-blog-post/index.ts +12 -2
- package/templates/yoga-studio/tier5-src/himi-branded-lite-home/index.ts +6 -1
- package/templates/yoga-studio/tier5-src/himi-events-detail/index.ts +40 -3
- package/templates/yoga-studio-owner/tier5-src/_shared/rich-body.ts +10 -4
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-home/index.ts +6 -1
|
@@ -2,8 +2,12 @@ export declare const BLOG_COMMENTS_APP_ID = "14bcded7-0066-7c35-14d7-466cb3f0910
|
|
|
2
2
|
export type WixBlogCommentRow = {
|
|
3
3
|
id: string;
|
|
4
4
|
authorName: string;
|
|
5
|
+
/** The comment's plain text (every text run, space-joined). */
|
|
5
6
|
text: string;
|
|
6
7
|
createdDate: string;
|
|
8
|
+
/** [rico] #3372 — the comment's Ricos document (`content.richContent`) as the API returned it, for a
|
|
9
|
+
* RichContent row; undefined when the comment has none. */
|
|
10
|
+
richContent?: unknown;
|
|
7
11
|
};
|
|
8
12
|
type BlogCommentLike = {
|
|
9
13
|
id?: string;
|
|
@@ -3,6 +3,16 @@ import type { WixPost } from "./index.js";
|
|
|
3
3
|
export interface WixPostResponse {
|
|
4
4
|
post?: WixPost;
|
|
5
5
|
}
|
|
6
|
+
/** A forum post's Ricos body (`content`). Opaque here: render it with RichContent (`@himalaya/wix-rich-content`
|
|
7
|
+
* prepares it); `contentText` stays the plain-text copy. */
|
|
8
|
+
export interface WixForumRichContent {
|
|
9
|
+
nodes?: unknown[];
|
|
10
|
+
metadata?: unknown;
|
|
11
|
+
documentStyle?: unknown;
|
|
12
|
+
}
|
|
13
|
+
/** [rico] #3372 — the post's Ricos `content` document (an object, or its JSON string), or null when it has none
|
|
14
|
+
* or it is not a document. */
|
|
15
|
+
export declare function forumPostContent(post: WixPost | null | undefined): WixForumRichContent | null;
|
|
6
16
|
/** Delete a post — DELETE /forum/v1/posts/{postId}. Irreversible. */
|
|
7
17
|
export declare function deletePost(id: string): Promise<WixPostResponse>;
|
|
8
18
|
/** Pin a post to the top of its category — PUT /forum/v1/posts/{postId}/pin → { post }. */
|
|
@@ -33,6 +33,7 @@ var commentText = (comment) => {
|
|
|
33
33
|
const text = readRichText(richContent);
|
|
34
34
|
return text || "Comment";
|
|
35
35
|
};
|
|
36
|
+
var commentRichContent = (comment) => comment.content?.richContent;
|
|
36
37
|
var commentAuthor = (comment) => {
|
|
37
38
|
const author = comment.author;
|
|
38
39
|
return author?.name ?? author?.nickname ?? "Member";
|
|
@@ -43,7 +44,8 @@ function blogCommentRow(comment) {
|
|
|
43
44
|
id: c.id ?? "comment",
|
|
44
45
|
authorName: commentAuthor(c),
|
|
45
46
|
text: commentText(c),
|
|
46
|
-
createdDate: c.createdDate ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
47
|
+
createdDate: c.createdDate ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
48
|
+
richContent: commentRichContent(c)
|
|
47
49
|
};
|
|
48
50
|
}
|
|
49
51
|
async function createBlogComment(postId, text) {
|
|
@@ -82,7 +84,8 @@ async function listBlogComments(postId) {
|
|
|
82
84
|
id: comment.id ?? "comment",
|
|
83
85
|
authorName: commentAuthor(comment),
|
|
84
86
|
text: commentText(comment),
|
|
85
|
-
createdDate: comment.createdDate ?? ""
|
|
87
|
+
createdDate: comment.createdDate ?? "",
|
|
88
|
+
richContent: commentRichContent(comment)
|
|
86
89
|
}));
|
|
87
90
|
const instantOf = (row) => {
|
|
88
91
|
if (!row.createdDate) return Number.POSITIVE_INFINITY;
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
// ../../stdlib/wix-sdk/forum/src/extensions.ts
|
|
2
|
+
function forumPostContent(post) {
|
|
3
|
+
let c = post?.content;
|
|
4
|
+
if (typeof c === "string") {
|
|
5
|
+
try {
|
|
6
|
+
c = JSON.parse(c);
|
|
7
|
+
} catch {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const doc = c;
|
|
12
|
+
return doc && typeof doc === "object" && Array.isArray(doc.nodes) ? doc : null;
|
|
13
|
+
}
|
|
2
14
|
function deletePost(id) {
|
|
3
15
|
if (!id) throw new Error("deletePost: id is required");
|
|
4
16
|
return wixCall("DELETE", `/forum/v1/posts/${encodeURIComponent(id)}`);
|
|
@@ -126,6 +138,7 @@ export {
|
|
|
126
138
|
deletePost,
|
|
127
139
|
disablePostCommenting,
|
|
128
140
|
enablePostCommenting,
|
|
141
|
+
forumPostContent,
|
|
129
142
|
getCategory,
|
|
130
143
|
getPost,
|
|
131
144
|
listForumBffCategories,
|
package/dist/cli.mjs
CHANGED
|
@@ -56161,6 +56161,56 @@ ${log}` : ""}`, true);
|
|
|
56161
56161
|
return r.code === 0 && r.json && typeof r.json === "object" && !Array.isArray(r.json) ? { ...res, structuredContent: r.json } : res;
|
|
56162
56162
|
}
|
|
56163
56163
|
},
|
|
56164
|
+
{
|
|
56165
|
+
name: "himi_logs",
|
|
56166
|
+
title: "Worker console logs",
|
|
56167
|
+
description: "What the app's Tier-5 workers printed with `console.log/info/warn/error` at runtime, in the web preview, Himi Player or the native app \u2014 read back from the serve plane. The CONSOLE channel only: failed actions and `error_logged` events are on himi_telemetry. To watch a flow, interact with the preview, then call again with `since` = the last `seq` you saw. A draft release's logs are readable as-is; a live release's need a telemetry token configured for the CLI (`HIMI_TELEMETRY_TOKEN`) \u2014 himi_login does not provide one, so on a 403 tell the user.",
|
|
56168
|
+
annotations: READ_PLANE,
|
|
56169
|
+
inputSchema: z2.object({ app: APP_ID, release: RELEASE_ID.optional(), screen: z2.string().optional().describe("Only lines from this screen id."), level: LOG_LEVEL, since: SINCE, limit: LIMIT }),
|
|
56170
|
+
handler: async (a, d) => fromCli(await d.runCli([
|
|
56171
|
+
"logs",
|
|
56172
|
+
"--app",
|
|
56173
|
+
String(a.app),
|
|
56174
|
+
...opt("--release", a.release),
|
|
56175
|
+
...opt("--screen", a.screen),
|
|
56176
|
+
...opt("--level", a.level),
|
|
56177
|
+
...opt("--since", a.since),
|
|
56178
|
+
...opt("--limit", a.limit),
|
|
56179
|
+
...opt("--target", d.login.target())
|
|
56180
|
+
]))
|
|
56181
|
+
},
|
|
56182
|
+
{
|
|
56183
|
+
name: "himi_telemetry",
|
|
56184
|
+
title: "Runtime telemetry for a release",
|
|
56185
|
+
description: "A release's runtime telemetry from the serve plane: the EVENT stream (screen views, `action_failed`, `error_logged`, `worker_console`, \u2026) plus the worker console lines, each with a `seq` cursor. The first place to look when a screen misbehaves at runtime but validate/test pass. `type` narrows to one event (e.g. `action_failed`); `crashes` adds crash reports. The two channels count separately: to read only what is new, pass the returned `cursor` as `since` and `logCursor` as `logSince`. Same access rule as himi_logs: a draft is readable as-is, a live release needs `HIMI_TELEMETRY_TOKEN`.",
|
|
56186
|
+
annotations: READ_PLANE,
|
|
56187
|
+
inputSchema: z2.object({
|
|
56188
|
+
app: APP_ID,
|
|
56189
|
+
release: RELEASE_ID.min(1),
|
|
56190
|
+
screen: z2.string().optional().describe("Only rows from this screen id."),
|
|
56191
|
+
type: z2.string().optional().describe("Only events of this type, e.g. `action_failed` or `error_logged`."),
|
|
56192
|
+
level: LOG_LEVEL,
|
|
56193
|
+
since: z2.number().int().min(0).optional().describe("Only EVENTS after this `seq` \u2014 the `cursor` a previous call returned."),
|
|
56194
|
+
logSince: z2.number().int().min(0).optional().describe("Only console LINES after this `seq` \u2014 the `logCursor` a previous call returned. Omitted: the console channel is read from `since` too, which only lines up on a first read."),
|
|
56195
|
+
limit: LIMIT,
|
|
56196
|
+
crashes: z2.boolean().optional().describe("Also return crash reports.")
|
|
56197
|
+
}),
|
|
56198
|
+
handler: async (a, d) => fromCli(await d.runCli([
|
|
56199
|
+
"telemetry",
|
|
56200
|
+
"--app",
|
|
56201
|
+
String(a.app),
|
|
56202
|
+
"--release",
|
|
56203
|
+
String(a.release),
|
|
56204
|
+
...opt("--screen", a.screen),
|
|
56205
|
+
...opt("--type", a.type),
|
|
56206
|
+
...opt("--level", a.level),
|
|
56207
|
+
...opt("--since", a.since),
|
|
56208
|
+
...opt("--log-since", a.logSince),
|
|
56209
|
+
...opt("--limit", a.limit),
|
|
56210
|
+
...sw("--crashes", a.crashes),
|
|
56211
|
+
...opt("--target", d.login.target())
|
|
56212
|
+
]))
|
|
56213
|
+
},
|
|
56164
56214
|
{
|
|
56165
56215
|
name: "himi_preview_links",
|
|
56166
56216
|
title: "Preview links for a release",
|
|
@@ -56178,7 +56228,7 @@ ${log}` : ""}`, true);
|
|
|
56178
56228
|
}
|
|
56179
56229
|
];
|
|
56180
56230
|
}
|
|
56181
|
-
var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT, PATH_ARGS;
|
|
56231
|
+
var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, READ_PLANE, APP_ID, RELEASE_ID, LOG_LEVEL, SINCE, LIMIT, PREVIEW_HINT, LOGIN_HINT, PATH_ARGS;
|
|
56182
56232
|
var init_tools = __esm({
|
|
56183
56233
|
"src/mcp/tools.ts"() {
|
|
56184
56234
|
init_file_tools();
|
|
@@ -56194,6 +56244,12 @@ var init_tools = __esm({
|
|
|
56194
56244
|
CHECK = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
56195
56245
|
LOCAL_WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
56196
56246
|
PUBLISH = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
|
|
56247
|
+
READ_PLANE = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true };
|
|
56248
|
+
APP_ID = z2.string().min(1).describe("The app id as published (`himalaya.content.json` `appId`).");
|
|
56249
|
+
RELEASE_ID = z2.string().describe("The release id \u2014 e.g. the draft `himi_push` returned.");
|
|
56250
|
+
LOG_LEVEL = z2.enum(["log", "info", "warn", "error", "debug"]).optional().describe("Keep only console lines at this level.");
|
|
56251
|
+
SINCE = z2.number().int().min(0).optional().describe("Only rows after this `seq` cursor \u2014 pass the last `seq` you saw to read just what is new.");
|
|
56252
|
+
LIMIT = z2.number().int().min(1).max(2e3).optional().describe("At most this many rows.");
|
|
56197
56253
|
PREVIEW_HINT = "The preview is already running: open `url` in your built-in browser \u2014 Claude Code desktop's browser pane, Cursor's Browser tool, the Browser in Codex inside the ChatGPT desktop app, VS Code's integrated browser. Do not also start the `himi-preview` launch configuration: it serves the same port, and is the way to start a preview only when none is running. A terminal-only agent should show the owner `himi_render` PNGs instead. `board` (when present) is the build board on the same origin.";
|
|
56198
56254
|
LOGIN_HINT = "Not signed in to the himi serve plane. Call himi_login: it opens a browser window where the user signs in to Wix (this server never sees the credential). A user with a terminal can run `himi login --browser` instead. Then retry.";
|
|
56199
56255
|
PATH_ARGS = ["dir", "parentDir", "file", "out"];
|
|
@@ -59034,21 +59090,21 @@ var init_preview_assets_generated = __esm({
|
|
|
59034
59090
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
59035
59091
|
init_preview_assets_format();
|
|
59036
59092
|
PREVIEW_ASSET_MANIFEST = [
|
|
59037
|
-
{ key: "assets/index-
|
|
59038
|
-
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset:
|
|
59039
|
-
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset:
|
|
59040
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
59041
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
59042
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
59043
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
59044
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
59045
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
59046
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
59047
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
59048
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
59049
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
59050
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
59051
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
59093
|
+
{ key: "assets/index-MTleSNX5.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1105924, sha256: "cd795ed12abde9ce83261aa3031594c0290b9b939f5d760c183e6eab445037e8" },
|
|
59094
|
+
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 1105932, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
|
|
59095
|
+
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 1110542, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
|
|
59096
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 1599126, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
59097
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 1690050, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
59098
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 1781034, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
59099
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 1872014, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
59100
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 1962886, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
59101
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 2053866, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
59102
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 2162502, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
59103
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 2271586, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
59104
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 2380634, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
59105
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 2488334, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
59106
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 2576442, length: 4947, sha256: "19a6a0d5ddc194f08dcd03c96099db31994445a051fad14a09bcfaa724f51298" },
|
|
59107
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 2581389, length: 17209, sha256: "dffc9718e2faa63ae2cc919e0a842f585ed565aaaa7c53778e90379442c731b6" }
|
|
59052
59108
|
];
|
|
59053
59109
|
}
|
|
59054
59110
|
});
|
|
@@ -64783,7 +64839,7 @@ async function visitorPass(url, siteFetch) {
|
|
|
64783
64839
|
}
|
|
64784
64840
|
return { identity, routes: routes.slice(0, MAX_ROUTES), gaps };
|
|
64785
64841
|
}
|
|
64786
|
-
var MAX_HTML_BYTES, MAX_BUNDLE_BYTES, MAX_BUNDLES, MAX_ROUTES,
|
|
64842
|
+
var MAX_HTML_BYTES, MAX_BUNDLE_BYTES, MAX_BUNDLES, MAX_ROUTES, APP_ID2, attr, decodeEntities;
|
|
64787
64843
|
var init_visitor = __esm({
|
|
64788
64844
|
"src/base44-analyze/visitor.ts"() {
|
|
64789
64845
|
init_write_artifacts();
|
|
@@ -64791,7 +64847,7 @@ var init_visitor = __esm({
|
|
|
64791
64847
|
MAX_BUNDLE_BYTES = 8 * 1024 * 1024;
|
|
64792
64848
|
MAX_BUNDLES = 4;
|
|
64793
64849
|
MAX_ROUTES = 80;
|
|
64794
|
-
|
|
64850
|
+
APP_ID2 = /^[a-f0-9]{24}$/;
|
|
64795
64851
|
attr = (tag, name) => {
|
|
64796
64852
|
const m = new RegExp(`\\b${name}\\s*=\\s*("([^"]*)"|'([^']*)')`, "i").exec(tag);
|
|
64797
64853
|
return m ? m[2] ?? m[3] : void 0;
|
|
@@ -64815,7 +64871,7 @@ async function analyzeBase44(input, ports) {
|
|
|
64815
64871
|
const appId2 = input.appId?.trim() || void 0;
|
|
64816
64872
|
const sample = input.sample ?? DEFAULT_SAMPLE_ROWS;
|
|
64817
64873
|
if (!url && !appId2) throw new Base44InputError("himi base44 analyze needs --url (visitor pass) or --app-id (owner pass)");
|
|
64818
|
-
if (appId2 && !
|
|
64874
|
+
if (appId2 && !APP_ID2.test(appId2)) throw new Base44InputError(`--app-id must be a 24-character hex Base44 app id, got ${JSON.stringify(appId2)}`);
|
|
64819
64875
|
if (!Number.isInteger(sample) || sample < 0 || sample > 100) throw new Base44InputError("--sample must be an integer from 0 to 100");
|
|
64820
64876
|
const owner = !!appId2 && !!ports.token;
|
|
64821
64877
|
if (appId2 && !ports.token) {
|
|
Binary file
|
package/guides/headless-loop.md
CHANGED
|
@@ -432,6 +432,40 @@ navigation/error, crash, and worker-console events from the pinned draft release
|
|
|
432
432
|
screen/type and cursorable with `--since` / `--follow`. `himi logs` remains the narrow
|
|
433
433
|
console-only view for `console.log(...)` output.
|
|
434
434
|
|
|
435
|
+
Over MCP the same two reads are `himi_telemetry` and `himi_logs` (pass the last `seq` you saw
|
|
436
|
+
as `since` to read only what is new).
|
|
437
|
+
|
|
438
|
+
### Logging from a worker
|
|
439
|
+
|
|
440
|
+
There is no logging SDK to import: a worker's plain `console.log/info/warn/error` **is** the log
|
|
441
|
+
channel, on every surface. In the web preview each line lands in the DEV panel's **Console** tab
|
|
442
|
+
(with the worker's boot errors, failed actions and uncaught errors); on every surface it ships as a
|
|
443
|
+
`worker_console` event that `himi logs` / `himi_logs` read back.
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
try {
|
|
447
|
+
products = await loadProducts();
|
|
448
|
+
} catch (e) {
|
|
449
|
+
// The status code only — never String(e): a Wix failure carries part of the response body.
|
|
450
|
+
const status = (e as { status?: unknown } | null)?.status ?? /\bHTTP (\d{3})\b/.exec(String(e))?.[1];
|
|
451
|
+
console.warn("[catalog.load] products failed, showing cached", status !== undefined ? `HTTP ${String(status)}` : "");
|
|
452
|
+
products = cached;
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
- **Prefix with `[service.action]`** so a line names its source when many screens log.
|
|
457
|
+
- **Log decisions, not every step:** a load that failed, a fallback taken, an unexpected shape.
|
|
458
|
+
Native samples console lines and a chatty worker drowns the one that matters.
|
|
459
|
+
- **Never log tokens, emails or other personal data** — the lines are stored on the plane. That
|
|
460
|
+
includes a raw caught error: a Wix failure carries part of the upstream response body, so log a
|
|
461
|
+
status or code (as above), not `String(e)`.
|
|
462
|
+
- **Two channels:** `himi logs` is console lines only. A failed action arrives as
|
|
463
|
+
`action_failed` + `error_logged` on the EVENT stream — read it with
|
|
464
|
+
`himi telemetry --app <app> --release <id> --type action_failed`.
|
|
465
|
+
- **The DEV panel's "N errors" chip** totals every tab (failed network calls, SDK faults, failed
|
|
466
|
+
actions, error telemetry, console errors) and says which; a Console count of 0 next to errors
|
|
467
|
+
means they are on those other tabs.
|
|
468
|
+
|
|
435
469
|
## 7. Promote
|
|
436
470
|
|
|
437
471
|
```sh
|
package/guides/himi-mcp.md
CHANGED
|
@@ -77,6 +77,8 @@ runs a session with it.
|
|
|
77
77
|
| `himi_login` | Open a browser window where the user signs in to Wix, so publishing works with no terminal. It returns the sign-in link at once; call it again to see whether the sign-in finished. |
|
|
78
78
|
| `himi_push` | Publish a **draft**: private to the owner, viewable by preview link and in Himi Player, not live. |
|
|
79
79
|
| `himi_share`, `himi_preview_links` | Share links for a published release. |
|
|
80
|
+
| `himi_logs` | What the app's workers printed with `console.*` at runtime (preview, Himi Player, device) — what `himi logs` shows. Read-only. |
|
|
81
|
+
| `himi_telemetry` | A release's runtime event stream — screen views, `action_failed`, `error_logged`, crashes — plus the console lines. Read-only. |
|
|
80
82
|
| `himi_base44_analyze` | Read a Base44 app into an app book (read-only) and return it as structured content — `himi docs base44-app-context`. |
|
|
81
83
|
|
|
82
84
|
Each tool acts on the agent's workspace folder unless it is given a `dir`.
|
|
@@ -10436,7 +10436,7 @@
|
|
|
10436
10436
|
"name": "WixBlogCommentRow",
|
|
10437
10437
|
"kind": "type",
|
|
10438
10438
|
"jsdoc": "",
|
|
10439
|
-
"decl": "export type WixBlogCommentRow = {\n id: string;\n authorName: string;\n text: string;\n createdDate: string;\n};"
|
|
10439
|
+
"decl": "export type WixBlogCommentRow = {\n id: string;\n authorName: string;\n /** The comment's plain text (every text run, space-joined). */\n text: string;\n createdDate: string;\n /** [rico] #3372 — the comment's Ricos document (`content.richContent`) as the API returned it, for a\n * RichContent row; undefined when the comment has none. */\n richContent?: unknown;\n};"
|
|
10440
10440
|
},
|
|
10441
10441
|
{
|
|
10442
10442
|
"name": "blogCommentRow",
|
|
@@ -17506,6 +17506,18 @@
|
|
|
17506
17506
|
"jsdoc": "/** Response of pin/unpin/delete — the mutated post (may be absent for delete). */",
|
|
17507
17507
|
"decl": "export interface WixPostResponse {\n post?: WixPost;\n}"
|
|
17508
17508
|
},
|
|
17509
|
+
{
|
|
17510
|
+
"name": "WixForumRichContent",
|
|
17511
|
+
"kind": "interface",
|
|
17512
|
+
"jsdoc": "/** A forum post's Ricos body (`content`). Opaque here: render it with RichContent (`@himalaya/wix-rich-content`\n * prepares it); `contentText` stays the plain-text copy. */",
|
|
17513
|
+
"decl": "export interface WixForumRichContent { nodes?: unknown[]; metadata?: unknown; documentStyle?: unknown }"
|
|
17514
|
+
},
|
|
17515
|
+
{
|
|
17516
|
+
"name": "forumPostContent",
|
|
17517
|
+
"kind": "function",
|
|
17518
|
+
"jsdoc": "/** [rico] #3372 — the post's Ricos `content` document (an object, or its JSON string), or null when it has none\n * or it is not a document. */",
|
|
17519
|
+
"decl": "export function forumPostContent(post: WixPost | null | undefined): WixForumRichContent | null;"
|
|
17520
|
+
},
|
|
17509
17521
|
{
|
|
17510
17522
|
"name": "deletePost",
|
|
17511
17523
|
"kind": "function",
|
|
@@ -463,8 +463,10 @@ surface (web, iOS, Android, and the local `himi test` / `himi render --live` loo
|
|
|
463
463
|
`_error`. Nothing is invented.
|
|
464
464
|
2. **It emits `action_failed`** (`{ actionId: "tier5.<service>.<action>", source:
|
|
465
465
|
"worker", error }` — the same payload the dispatcher emits for a failed dispatch)
|
|
466
|
-
plus the `error_logged` central-log line, so the message reaches telemetry
|
|
467
|
-
`himi
|
|
466
|
+
plus the `error_logged` central-log line, so the message reaches the telemetry
|
|
467
|
+
EVENT stream (`himi telemetry --app <app> --release <id> --type action_failed`; not `himi logs`, which is the
|
|
468
|
+
`console.*` channel only) and, in the web preview, the DEV panel's Console tab,
|
|
469
|
+
instead of vanishing.
|
|
468
470
|
3. **It re-throws.** The failure is made *visible*, not caught and continued: an
|
|
469
471
|
awaiting bundle and the host's `unhandledrejection` net keep every signal they had.
|
|
470
472
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1147.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"artifactId": "himalaya-cli"
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
|
-
"falconPackageHash": "
|
|
70
|
+
"falconPackageHash": "6e0244443eef84efe49d5d233a08bbf3819c2286723fe287fe7c1cc8"
|
|
71
71
|
}
|
|
@@ -25845,7 +25845,33 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
25845
25845
|
}
|
|
25846
25846
|
},
|
|
25847
25847
|
{
|
|
25848
|
-
"id": "",
|
|
25848
|
+
"id": "product_body",
|
|
25849
|
+
"body": {
|
|
25850
|
+
"package": "himalaya",
|
|
25851
|
+
"type": "RichContent",
|
|
25852
|
+
"props": {
|
|
25853
|
+
"documentJsonPath": "$service:himiStoreProduct.descriptionJson",
|
|
25854
|
+
"onLink": {
|
|
25855
|
+
"actionId": "tier5.himiStoreProduct.openLink"
|
|
25856
|
+
},
|
|
25857
|
+
"fallback": {
|
|
25858
|
+
"id": "",
|
|
25859
|
+
"body": {
|
|
25860
|
+
"package": "himalaya",
|
|
25861
|
+
"type": "Text",
|
|
25862
|
+
"props": {
|
|
25863
|
+
"text": "$service:himiStoreProduct.description",
|
|
25864
|
+
"style": "body",
|
|
25865
|
+
"color": "textSecondary",
|
|
25866
|
+
"collapseWhenEmpty": true
|
|
25867
|
+
}
|
|
25868
|
+
}
|
|
25869
|
+
}
|
|
25870
|
+
}
|
|
25871
|
+
}
|
|
25872
|
+
},
|
|
25873
|
+
{
|
|
25874
|
+
"id": "product_body_text",
|
|
25849
25875
|
"body": {
|
|
25850
25876
|
"package": "himalaya",
|
|
25851
25877
|
"type": "Text",
|
|
@@ -25855,6 +25881,9 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
25855
25881
|
"color": "textSecondary",
|
|
25856
25882
|
"collapseWhenEmpty": true
|
|
25857
25883
|
}
|
|
25884
|
+
},
|
|
25885
|
+
"modifiers": {
|
|
25886
|
+
"hiddenPath": "$service:himiStoreProduct.hasDescriptionJson"
|
|
25858
25887
|
}
|
|
25859
25888
|
}
|
|
25860
25889
|
]
|
|
@@ -26349,7 +26378,8 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
26349
26378
|
"declaredCapabilities": [
|
|
26350
26379
|
"wix_api",
|
|
26351
26380
|
"share",
|
|
26352
|
-
"local_database"
|
|
26381
|
+
"local_database",
|
|
26382
|
+
"open_url"
|
|
26353
26383
|
],
|
|
26354
26384
|
"minBinaryVersion": "0.1.0",
|
|
26355
26385
|
"bundleVersion": "0.0.1"
|
|
@@ -28860,7 +28890,33 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
28860
28890
|
}
|
|
28861
28891
|
},
|
|
28862
28892
|
{
|
|
28863
|
-
"id": "",
|
|
28893
|
+
"id": "comment_body_$item.id",
|
|
28894
|
+
"body": {
|
|
28895
|
+
"package": "himalaya",
|
|
28896
|
+
"type": "RichContent",
|
|
28897
|
+
"props": {
|
|
28898
|
+
"documentJsonPath": "$item.bodyJson",
|
|
28899
|
+
"onLink": {
|
|
28900
|
+
"actionId": "tier5.himiBlogPost.openLink"
|
|
28901
|
+
},
|
|
28902
|
+
"fallback": {
|
|
28903
|
+
"id": "",
|
|
28904
|
+
"body": {
|
|
28905
|
+
"package": "himalaya",
|
|
28906
|
+
"type": "Text",
|
|
28907
|
+
"props": {
|
|
28908
|
+
"text": "$item.text",
|
|
28909
|
+
"style": "body",
|
|
28910
|
+
"color": "textSecondary",
|
|
28911
|
+
"collapseWhenEmpty": true
|
|
28912
|
+
}
|
|
28913
|
+
}
|
|
28914
|
+
}
|
|
28915
|
+
}
|
|
28916
|
+
}
|
|
28917
|
+
},
|
|
28918
|
+
{
|
|
28919
|
+
"id": "comment_body_text_$item.id",
|
|
28864
28920
|
"body": {
|
|
28865
28921
|
"package": "himalaya",
|
|
28866
28922
|
"type": "Text",
|
|
@@ -28870,6 +28926,9 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
28870
28926
|
"color": "textSecondary",
|
|
28871
28927
|
"collapseWhenEmpty": true
|
|
28872
28928
|
}
|
|
28929
|
+
},
|
|
28930
|
+
"modifiers": {
|
|
28931
|
+
"hiddenPath": "$item.hasBodyJson"
|
|
28873
28932
|
}
|
|
28874
28933
|
}
|
|
28875
28934
|
]
|
|
@@ -14,15 +14,21 @@ export interface RichBody {
|
|
|
14
14
|
bodyText: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/** [rico] #3372 — the media width for a document drawn in a LIST row (a feed post, a comment, a CMS item): the
|
|
18
|
+
* list-image size (WIX_LIST_IMAGE), so a scrolling list never downloads every image at detail size. */
|
|
19
|
+
export const ROW_IMAGE_WIDTH = 1000;
|
|
20
|
+
|
|
17
21
|
/** Prepares `richContent` (a Ricos document, as a Wix API returns it, or its JSON string). No document, or one
|
|
18
22
|
* that is not a document, gives `{ bodyJson: "", bodyText: fallback }`. A document past the viewer's limits
|
|
19
23
|
* gives bodyJson "" and its plain text — except one rejected as too deep, which is not walked again (the
|
|
20
|
-
* plain-text walk has no depth limit), so `fallback` stands in for it.
|
|
21
|
-
|
|
24
|
+
* plain-text walk has no depth limit), so `fallback` stands in for it. `imageWidth` sizes its media (default
|
|
25
|
+
* the 1400 px detail budget). */
|
|
26
|
+
export function richBody(richContent: unknown, fallback = "", imageWidth = 1400): RichBody {
|
|
22
27
|
const doc = parseRicosJson(richContent);
|
|
23
28
|
if (!doc) return { bodyJson: "", bodyText: fallback };
|
|
24
|
-
// 1400 px — the detail-image budget, which is also the encoder's maximum
|
|
25
|
-
|
|
29
|
+
// 1400 px by default — the detail-image budget, which is also the encoder's maximum; list rows pass
|
|
30
|
+
// ROW_IMAGE_WIDTH.
|
|
31
|
+
const { json, rejected } = encodeRichContent(doc, { imageWidth });
|
|
26
32
|
const text = rejected === "too_deep" ? "" : ricosToPlainText(doc);
|
|
27
33
|
return { bodyJson: json, bodyText: text || fallback };
|
|
28
34
|
}
|
|
@@ -8,7 +8,7 @@ import { isSavedId, toggleSavedId } from "../_shared/himi-blog-saved";
|
|
|
8
8
|
import { stashCopy, copyParam, copyTemplate } from "../_shared/himi-copy.js";
|
|
9
9
|
import { formatDateMedium, formatMonthDay } from "../_shared/engine-intl.js";
|
|
10
10
|
import { openRichLink } from "../_shared/rich-content-link.js";
|
|
11
|
-
import { richBody } from "../_shared/rich-body.js";
|
|
11
|
+
import { richBody, ROW_IMAGE_WIDTH } from "../_shared/rich-body.js";
|
|
12
12
|
|
|
13
13
|
// Offline-first (data-offline): the post body is a public read-through — when the
|
|
14
14
|
// live fetch fails (offline) fall back to the last-synced row the feed cached under
|
|
@@ -23,8 +23,14 @@ async function readCachedPost(id: string): Promise<DbEntity | null> {
|
|
|
23
23
|
interface CommentRow {
|
|
24
24
|
id: string;
|
|
25
25
|
authorName: string;
|
|
26
|
+
/** The comment's plain text: the row RichContent's fallback. */
|
|
26
27
|
text: string;
|
|
27
28
|
meta: string;
|
|
29
|
+
/** [rico] #3372 — the comment's Ricos document as ONE string for the row's RichContent; "" when it has none
|
|
30
|
+
* or the encoder rejected it. */
|
|
31
|
+
bodyJson: string;
|
|
32
|
+
/** bodyJson !== "" — gates the row's plain text, because RichContent draws nothing for "". */
|
|
33
|
+
hasBodyJson: boolean;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
interface S {
|
|
@@ -168,11 +174,15 @@ function commentMeta(row: WixBlogCommentRow): string {
|
|
|
168
174
|
}
|
|
169
175
|
|
|
170
176
|
function toCommentRow(row: WixBlogCommentRow): CommentRow {
|
|
177
|
+
// The plain text is the document's own (runs joined as written, not space-separated) when it has one.
|
|
178
|
+
const { bodyJson, bodyText } = richBody(row.richContent, row.text || "Comment", ROW_IMAGE_WIDTH);
|
|
171
179
|
return {
|
|
172
180
|
id: row.id,
|
|
173
181
|
authorName: row.authorName || "Member",
|
|
174
|
-
text:
|
|
182
|
+
text: bodyText,
|
|
175
183
|
meta: commentMeta(row),
|
|
184
|
+
bodyJson,
|
|
185
|
+
hasBodyJson: bodyJson !== "",
|
|
176
186
|
};
|
|
177
187
|
}
|
|
178
188
|
|
|
@@ -508,7 +508,12 @@ async function fetchBookingsSignal(arg: unknown): Promise<BookingsSignal> {
|
|
|
508
508
|
try {
|
|
509
509
|
const response = await queryServices({ query: { paging: { limit: 50 } } });
|
|
510
510
|
return bookingsSignal(response.services ?? []);
|
|
511
|
-
} catch {
|
|
511
|
+
} catch (e) {
|
|
512
|
+
// The block collapses without a word on screen, so say why where an agent looks:
|
|
513
|
+
// the DEV panel's Console tab and `himi logs`. The status only — a Wix failure's
|
|
514
|
+
// message carries part of the upstream body, which may hold personal data.
|
|
515
|
+
const status = (e as { status?: unknown } | null)?.status ?? /\bHTTP (\d{3})\b/.exec(String(e))?.[1];
|
|
516
|
+
console.warn("[home.bookings] services query failed; showcase hidden", status !== undefined ? `HTTP ${String(status)}` : "");
|
|
512
517
|
return emptyBookingsSignal();
|
|
513
518
|
}
|
|
514
519
|
}
|