@wix/himalaya-cli 0.844.0 → 0.845.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/cli.mjs +9 -2
- package/guides/release-notes.md +19 -0
- package/package.json +2 -2
- package/templates/beauty-salon-owner/dev/index.ts +858 -0
- package/templates/beauty-salon-owner/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
- package/templates/community-club-owner/dev/index.ts +858 -0
- package/templates/community-club-owner/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/community-club-owner/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/community-club-owner/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
- package/templates/events-meetups-owner/dev/index.ts +858 -0
- package/templates/events-meetups-owner/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
- package/templates/gym-fitness-owner/dev/index.ts +858 -0
- package/templates/gym-fitness-owner/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
- package/templates/nonprofit-cause-owner/dev/index.ts +858 -0
- package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
- package/templates/owner-lite/dev/index.ts +858 -0
- package/templates/owner-lite/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/owner-lite/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
- package/templates/podcast-creator-owner/dev/index.ts +858 -0
- package/templates/podcast-creator-owner/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
- package/templates/portfolio-creative-owner/dev/index.ts +858 -0
- package/templates/portfolio-creative-owner/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
- package/templates/restaurant-owner/dev/index.ts +858 -0
- package/templates/restaurant-owner/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
- package/templates/retail-store-owner/dev/index.ts +858 -0
- package/templates/retail-store-owner/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
- package/templates/yoga-studio-owner/dev/index.ts +858 -0
- package/templates/yoga-studio-owner/tier5-src/_shared/aria-chat.ts +59 -9
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-analytics/index.ts +7 -1
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-analytics/report.ts +690 -0
|
@@ -233,25 +233,69 @@ function linkFieldsOf(raw: string, role: string) {
|
|
|
233
233
|
};
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
-
/**
|
|
236
|
+
/** A syntactically plain hostname: labels of letters, digits and dashes joined
|
|
237
|
+
* by dots, or a bracketed IPv6 literal. Anything else — a backslash, a space,
|
|
238
|
+
* a stray `@`, the empty string — means the parse below did not yield a host,
|
|
239
|
+
* and a non-host must never be matched against the Wix suffixes: `endsWith` is
|
|
240
|
+
* a plain string test, and `evil.example\.wix.com` ends with `.wix.com` while
|
|
241
|
+
* the browser opens `evil.example`. */
|
|
242
|
+
const PLAIN_HOST = /^(?:[a-z0-9-]+(?:\.[a-z0-9-]+)*|\[[0-9a-f:.]+\])$/;
|
|
243
|
+
|
|
244
|
+
/** The host an `https://host/…` url will actually open, lowercased, or "" when
|
|
245
|
+
* that cannot be established.
|
|
246
|
+
*
|
|
237
247
|
* A regex, not `new URL`: the worker runtimes (JSContext, Hermes, QuickJS) do
|
|
238
|
-
* not all ship the URL constructor.
|
|
239
|
-
*
|
|
240
|
-
*
|
|
248
|
+
* not all ship the URL constructor. So this has to imitate the URL standard's
|
|
249
|
+
* authority parsing closely enough that the host it reports is the host the
|
|
250
|
+
* device opens — the entire value of showing a host is that it is the one the
|
|
251
|
+
* tap goes to. Two details earn their keep:
|
|
252
|
+
*
|
|
253
|
+
* - Credentials before an `@` are ignored, so
|
|
254
|
+
* `https://manage.wix.com@evil.example/` reads as `evil.example`.
|
|
255
|
+
* - A BACKSLASH ends the authority, because for http(s) the URL standard
|
|
256
|
+
* treats `\` exactly like `/`. Without that, `https://evil.example\@wix.com/`
|
|
257
|
+
* reads as `wix.com` here while every browser opens `evil.example` with the
|
|
258
|
+
* path `/@wix.com/`. That is exactly the lie this disclosure exists to
|
|
259
|
+
* prevent, so the separator set has to match the URL standard's rather than
|
|
260
|
+
* RFC 3986's.
|
|
261
|
+
*
|
|
262
|
+
* A string that survives parsing but is not a plain hostname returns "", which
|
|
263
|
+
* callers must treat as untrusted rather than as "there is no host here". */
|
|
241
264
|
export function hostOf(url: string): string {
|
|
242
|
-
const m = /^https?:\/\/([
|
|
265
|
+
const m = /^https?:\/\/([^/?#\\]*)/i.exec(url.trim());
|
|
243
266
|
if (!m) return "";
|
|
244
267
|
const authority = m[1];
|
|
245
268
|
const at = authority.lastIndexOf("@");
|
|
246
269
|
const hostPort = at >= 0 ? authority.slice(at + 1) : authority;
|
|
247
|
-
|
|
270
|
+
const host = hostPort.replace(/:\d+$/, "").toLowerCase();
|
|
271
|
+
return PLAIN_HOST.test(host) ? host : "";
|
|
248
272
|
}
|
|
249
273
|
|
|
250
|
-
/** Is this url somewhere Wix itself serves?
|
|
274
|
+
/** Is this url somewhere Wix itself serves?
|
|
275
|
+
*
|
|
276
|
+
* Guarded by `PLAIN_HOST` first. The suffix tests are string operations, so
|
|
277
|
+
* without the guard anything ending in `.wix.com` passes no matter what else
|
|
278
|
+
* it contains. `hostOf` already applies the same guard; this repeats it because
|
|
279
|
+
* a predicate that decides whether to warn somebody should not depend on its
|
|
280
|
+
* caller having sanitized the input. */
|
|
251
281
|
export function isWixHost(host: string): boolean {
|
|
282
|
+
if (!PLAIN_HOST.test(host)) return false;
|
|
252
283
|
return host === "wix.com" || host.endsWith(".wix.com") || host === "wixsite.com" || host.endsWith(".wixsite.com");
|
|
253
284
|
}
|
|
254
285
|
|
|
286
|
+
/** Shown in place of a host when an `http(s)` link's host cannot be
|
|
287
|
+
* established. Deliberately not domain-shaped: it has to read as "this could
|
|
288
|
+
* not be checked", never as a site the owner might think they recognize.
|
|
289
|
+
*
|
|
290
|
+
* KNOWN LIMITATION: this is the one user-facing string here that does not come
|
|
291
|
+
* from the copy pack, so it does not localize. It is a literal for the same
|
|
292
|
+
* reason the `(host)` parenthetical beside it is: both are appended by a PURE
|
|
293
|
+
* function, reached from a pure one, with no copy resolver in scope — and
|
|
294
|
+
* threading one through to reach a safety annotation is a larger change than
|
|
295
|
+
* the annotation. Route it through copy when this file next has a reason to
|
|
296
|
+
* take a resolver, rather than half-threading one now. */
|
|
297
|
+
const UNKNOWN_HOST_LABEL = "unknown site";
|
|
298
|
+
|
|
255
299
|
/** A link row's label, with the destination host appended when the link leaves
|
|
256
300
|
* Wix.
|
|
257
301
|
*
|
|
@@ -269,8 +313,14 @@ export function isWixHost(host: string): boolean {
|
|
|
269
313
|
* is an `/add-sdui-component`-class parity change. */
|
|
270
314
|
export function disclosedLabel(link: { label: string; url: string }): string {
|
|
271
315
|
const host = hostOf(link.url);
|
|
272
|
-
|
|
273
|
-
|
|
316
|
+
// Silence is reserved for a host positively identified as Wix's. Every link
|
|
317
|
+
// reaching here came from `extractLinks`, which accepts `http(s)://` only —
|
|
318
|
+
// so a url whose host cannot be established is a MALFORMED one, not a scheme
|
|
319
|
+
// with nothing to show, and reading that as "nothing to disclose" is how
|
|
320
|
+
// `https:///evil.example/` rendered with no host while opening
|
|
321
|
+
// `evil.example`. Fail closed: unknown is disclosed, never trusted.
|
|
322
|
+
if (isWixHost(host)) return link.label;
|
|
323
|
+
return `${link.label} (${host || UNKNOWN_HOST_LABEL})`;
|
|
274
324
|
}
|
|
275
325
|
|
|
276
326
|
/** Aria replies come back as markdown. There is no native markdown renderer
|
|
@@ -39,6 +39,12 @@ import {
|
|
|
39
39
|
type WixAnalyticsMeasurement,
|
|
40
40
|
type WixMeasure,
|
|
41
41
|
} from "@himalaya/wix-analytics";
|
|
42
|
+
// The REPORTS service — the Semantic Model reporting engine — is the
|
|
43
|
+
// second service in this bundle. Imported for its registration side effect:
|
|
44
|
+
// `defineService` registers at call time and the host resolves
|
|
45
|
+
// `$service:ownerLiteAnalyticsReport` out of that registry. See report.ts for
|
|
46
|
+
// why the two share a bundle and why only this one auto-loads.
|
|
47
|
+
import { svc as reportSvc } from "./report.js";
|
|
42
48
|
|
|
43
49
|
interface CardRow { id: string; label: string; value: string; delta: string; }
|
|
44
50
|
interface StatRow { id: string; label: string; state: string; }
|
|
@@ -549,4 +555,4 @@ const svc = defineService<AnalyticsState, {
|
|
|
549
555
|
});
|
|
550
556
|
|
|
551
557
|
svc.load();
|
|
552
|
-
export { svc };
|
|
558
|
+
export { svc, reportSvc };
|