@wix/himalaya-cli 0.877.0 → 0.879.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.
|
@@ -37,7 +37,18 @@ export interface WixGetPostRequest {
|
|
|
37
37
|
* filter-by-id — a graceful degrade to the LIST projection (no body) that keeps
|
|
38
38
|
* blog detail + saved screens rendering instead of erroring out. `queryPosts`'s
|
|
39
39
|
* request type has no `fieldsets` field, so that fallback path cannot carry the
|
|
40
|
-
* body.
|
|
40
|
+
* body.
|
|
41
|
+
*
|
|
42
|
+
* When that fallback ALSO finds nothing (#2658) — a deleted post, or one this
|
|
43
|
+
* visitor may not see — we reject rather than resolve. `WixGetPostResponse.post`
|
|
44
|
+
* is non-optional, so returning `{ post: resp.posts?.[0] }` would hand callers an
|
|
45
|
+
* `undefined` the type promises is present, and the `post.title` access that type
|
|
46
|
+
* licenses throws a `TypeError` deep inside the caller — the exact hard error
|
|
47
|
+
* this fallback exists to prevent, and harder to diagnose than a clean rejection.
|
|
48
|
+
* Every call site rides its own rejection path (cached-post state, draft-only
|
|
49
|
+
* `catch`, or an `allSettled` filter), so rejecting is what routes them into the
|
|
50
|
+
* graceful degrade they already implement. The originating failure travels as
|
|
51
|
+
* `cause`, so the 404-vs-network distinction is not lost. */
|
|
41
52
|
export declare function getPost(postId: string, req?: WixGetPostRequest): Promise<WixGetPostResponse>;
|
|
42
53
|
export interface WixBlogCategory {
|
|
43
54
|
id: string;
|
|
@@ -12,9 +12,13 @@ function getPost(postId, req = {}) {
|
|
|
12
12
|
return wixCall(
|
|
13
13
|
"GET",
|
|
14
14
|
`/blog/v3/posts/${encodeURIComponent(postId)}` + query
|
|
15
|
-
).catch(async () => {
|
|
15
|
+
).catch(async (cause) => {
|
|
16
16
|
const resp = await queryPosts({ query: { filter: { id: postId } } });
|
|
17
|
-
|
|
17
|
+
const post = resp.posts?.[0];
|
|
18
|
+
if (!post) {
|
|
19
|
+
throw new Error(`Blog post not found: ${postId}`, { cause });
|
|
20
|
+
}
|
|
21
|
+
return { post };
|
|
18
22
|
});
|
|
19
23
|
}
|
|
20
24
|
function queryCategories(req = {}) {
|
package/dist/cli.mjs
CHANGED
|
@@ -37687,6 +37687,8 @@ var init_kits = __esm({
|
|
|
37687
37687
|
// ../../core/dev-server/src/widgets.ts
|
|
37688
37688
|
var widgets_exports = {};
|
|
37689
37689
|
__export(widgets_exports, {
|
|
37690
|
+
MAX_PRODUCE_CACHE_ENTRIES: () => MAX_PRODUCE_CACHE_ENTRIES,
|
|
37691
|
+
PRODUCE_CACHE_TTL_MS: () => PRODUCE_CACHE_TTL_MS,
|
|
37690
37692
|
WIDGET_BUDGET_MS: () => WIDGET_BUDGET_MS,
|
|
37691
37693
|
buildViewSnapshot: () => buildViewSnapshot,
|
|
37692
37694
|
buildWidgetSnapshot: () => buildWidgetSnapshot,
|
|
@@ -37694,6 +37696,7 @@ __export(widgets_exports, {
|
|
|
37694
37696
|
extractWidgets: () => extractWidgets,
|
|
37695
37697
|
freezeOverrideSnapshot: () => freezeOverrideSnapshot,
|
|
37696
37698
|
frozenViewManifestEntries: () => frozenViewManifestEntries,
|
|
37699
|
+
resetWidgetProduceCache: () => resetWidgetProduceCache,
|
|
37697
37700
|
resetWidgetRealm: () => resetWidgetRealm,
|
|
37698
37701
|
viewWidgetId: () => viewWidgetId,
|
|
37699
37702
|
widgetRealm: () => widgetRealm
|
|
@@ -37722,6 +37725,84 @@ async function widgetRealm() {
|
|
|
37722
37725
|
function resetWidgetRealm() {
|
|
37723
37726
|
realmPromise = null;
|
|
37724
37727
|
}
|
|
37728
|
+
function guestClock(clock) {
|
|
37729
|
+
return clock === void 0 ? void 0 : Math.trunc(clock);
|
|
37730
|
+
}
|
|
37731
|
+
function serializedServices(produced) {
|
|
37732
|
+
try {
|
|
37733
|
+
return JSON.stringify(produced.services) ?? void 0;
|
|
37734
|
+
} catch {
|
|
37735
|
+
return void 0;
|
|
37736
|
+
}
|
|
37737
|
+
}
|
|
37738
|
+
function resetWidgetProduceCache() {
|
|
37739
|
+
produceCacheGeneration++;
|
|
37740
|
+
}
|
|
37741
|
+
function realmProduceCache(evaluator) {
|
|
37742
|
+
const existing = produceCache.get(evaluator);
|
|
37743
|
+
if (!existing) {
|
|
37744
|
+
const fresh = { generation: produceCacheGeneration, entries: /* @__PURE__ */ new Map(), bytes: 0 };
|
|
37745
|
+
produceCache.set(evaluator, fresh);
|
|
37746
|
+
return fresh;
|
|
37747
|
+
}
|
|
37748
|
+
if (existing.generation !== produceCacheGeneration) {
|
|
37749
|
+
existing.entries.clear();
|
|
37750
|
+
existing.bytes = 0;
|
|
37751
|
+
existing.generation = produceCacheGeneration;
|
|
37752
|
+
}
|
|
37753
|
+
return existing;
|
|
37754
|
+
}
|
|
37755
|
+
function dropEntry(cache, key2) {
|
|
37756
|
+
const entry = cache.entries.get(key2);
|
|
37757
|
+
if (!entry) return;
|
|
37758
|
+
cache.entries.delete(key2);
|
|
37759
|
+
cache.bytes -= entry.bytes;
|
|
37760
|
+
}
|
|
37761
|
+
function produceCacheKey(bundleJs, timeoutMs, clock) {
|
|
37762
|
+
const digest2 = createHash14("sha256").update(bundleJs).digest("base64");
|
|
37763
|
+
return `${timeoutMs}|${clock === void 0 ? "live" : Math.trunc(clock)}|${digest2}`;
|
|
37764
|
+
}
|
|
37765
|
+
function cachedProduce(evaluator, key2) {
|
|
37766
|
+
const cache = realmProduceCache(evaluator);
|
|
37767
|
+
const hit = cache.entries.get(key2);
|
|
37768
|
+
if (!hit) return void 0;
|
|
37769
|
+
if (Date.now() >= hit.expiresAt) {
|
|
37770
|
+
dropEntry(cache, key2);
|
|
37771
|
+
return void 0;
|
|
37772
|
+
}
|
|
37773
|
+
cache.entries.delete(key2);
|
|
37774
|
+
cache.entries.set(key2, hit);
|
|
37775
|
+
return { services: JSON.parse(hit.servicesJson), envelope: hit.envelope };
|
|
37776
|
+
}
|
|
37777
|
+
function rememberProduce(evaluator, key2, servicesJson, envelope, expiresAt) {
|
|
37778
|
+
const bytes2 = envelope.length + servicesJson.length;
|
|
37779
|
+
if (bytes2 > MAX_PRODUCE_ENTRY_BYTES) return;
|
|
37780
|
+
const cache = realmProduceCache(evaluator);
|
|
37781
|
+
dropEntry(cache, key2);
|
|
37782
|
+
cache.entries.set(key2, { servicesJson, envelope, expiresAt, bytes: bytes2 });
|
|
37783
|
+
cache.bytes += bytes2;
|
|
37784
|
+
const over = () => cache.entries.size > MAX_PRODUCE_CACHE_ENTRIES || cache.bytes > MAX_PRODUCE_CACHE_BYTES;
|
|
37785
|
+
if (!over()) return;
|
|
37786
|
+
const now = Date.now();
|
|
37787
|
+
for (const [k, entry] of [...cache.entries]) {
|
|
37788
|
+
if (!over()) break;
|
|
37789
|
+
if (k !== key2 && now >= entry.expiresAt) dropEntry(cache, k);
|
|
37790
|
+
}
|
|
37791
|
+
while (over()) {
|
|
37792
|
+
const oldest = cache.entries.keys().next();
|
|
37793
|
+
if (oldest.done || oldest.value === key2) break;
|
|
37794
|
+
dropEntry(cache, oldest.value);
|
|
37795
|
+
}
|
|
37796
|
+
}
|
|
37797
|
+
function reuseWindowMs(parsed) {
|
|
37798
|
+
let window2 = PRODUCE_CACHE_TTL_MS;
|
|
37799
|
+
for (const raw of [...parsed.widgets ?? [], ...parsed.views ?? []]) {
|
|
37800
|
+
const ttl2 = parseJsonField(raw.refresh)?.ttlSeconds;
|
|
37801
|
+
if (typeof ttl2 !== "number" || !Number.isFinite(ttl2) || ttl2 <= 0) continue;
|
|
37802
|
+
window2 = Math.min(window2, ttl2 * 1e3);
|
|
37803
|
+
}
|
|
37804
|
+
return window2;
|
|
37805
|
+
}
|
|
37725
37806
|
function viewRenderModes() {
|
|
37726
37807
|
const out = {};
|
|
37727
37808
|
for (const target of [...SURFACE_GROUPS, ...PREVIEW_SURFACES.map((s) => s.id)]) {
|
|
@@ -37924,7 +38005,30 @@ function parseJsonField(value) {
|
|
|
37924
38005
|
}
|
|
37925
38006
|
}
|
|
37926
38007
|
async function extractWidgets(bundleJs, opts = {}) {
|
|
37927
|
-
const
|
|
38008
|
+
const evaluator = opts.evaluator ?? await widgetRealm();
|
|
38009
|
+
const timeoutMs = opts.timeoutMs ?? WIDGET_BUDGET_MS;
|
|
38010
|
+
const clock = guestClock(opts.clock);
|
|
38011
|
+
const key2 = produceCacheKey(bundleJs, timeoutMs, clock);
|
|
38012
|
+
const cached3 = cachedProduce(evaluator, key2);
|
|
38013
|
+
const produced = cached3 ?? runProduce(evaluator, bundleJs, timeoutMs, clock);
|
|
38014
|
+
let parsed;
|
|
38015
|
+
try {
|
|
38016
|
+
parsed = JSON.parse(produced.envelope);
|
|
38017
|
+
} catch (err) {
|
|
38018
|
+
throw new Error(`the widget producer's realm returned a malformed envelope: ${describeThrown(err)}`);
|
|
38019
|
+
}
|
|
38020
|
+
let services = produced.services;
|
|
38021
|
+
if (!cached3) {
|
|
38022
|
+
const servicesJson = serializedServices(produced);
|
|
38023
|
+
if (servicesJson !== void 0) {
|
|
38024
|
+
services = JSON.parse(servicesJson);
|
|
38025
|
+
rememberProduce(evaluator, key2, servicesJson, produced.envelope, Date.now() + reuseWindowMs(parsed));
|
|
38026
|
+
}
|
|
38027
|
+
}
|
|
38028
|
+
return interpretProduce(services, parsed);
|
|
38029
|
+
}
|
|
38030
|
+
function runProduce(evaluator, bundleJs, timeoutMs, clock) {
|
|
38031
|
+
const services = /* @__PURE__ */ Object.create(null);
|
|
37928
38032
|
let envelope;
|
|
37929
38033
|
const inert = makeInert2();
|
|
37930
38034
|
const himalayaTarget = {
|
|
@@ -37966,21 +38070,17 @@ async function extractWidgets(bundleJs, opts = {}) {
|
|
|
37966
38070
|
}
|
|
37967
38071
|
};
|
|
37968
38072
|
sandbox.globalThis = sandbox;
|
|
37969
|
-
|
|
37970
|
-
|
|
37971
|
-
timeoutMs: opts.timeoutMs ?? WIDGET_BUDGET_MS,
|
|
38073
|
+
evaluator.run(widgetProgram(bundleJs, clock), sandbox, {
|
|
38074
|
+
timeoutMs,
|
|
37972
38075
|
filename: "widget-bundle.js",
|
|
37973
38076
|
captureConsole: false
|
|
37974
38077
|
});
|
|
37975
38078
|
if (envelope === void 0) {
|
|
37976
38079
|
throw new Error("the widget producer's realm returned no registrations envelope");
|
|
37977
38080
|
}
|
|
37978
|
-
|
|
37979
|
-
|
|
37980
|
-
|
|
37981
|
-
} catch (err) {
|
|
37982
|
-
throw new Error(`the widget producer's realm returned a malformed envelope: ${describeThrown(err)}`);
|
|
37983
|
-
}
|
|
38081
|
+
return { services, envelope };
|
|
38082
|
+
}
|
|
38083
|
+
function interpretProduce(services, parsed) {
|
|
37984
38084
|
const widgets = {};
|
|
37985
38085
|
for (const raw of parsed.widgets ?? []) {
|
|
37986
38086
|
widgets[String(raw.id)] = {
|
|
@@ -38239,7 +38339,7 @@ function freezeOverrideSnapshot(input, opts = {}) {
|
|
|
38239
38339
|
}
|
|
38240
38340
|
return snapshot2;
|
|
38241
38341
|
}
|
|
38242
|
-
var MAX_TIMELINE_FRAMES, WIDGET_BUDGET_MS, realmPromise, CAPTURE_SLOT, READBACK_SERVICE;
|
|
38342
|
+
var MAX_TIMELINE_FRAMES, WIDGET_BUDGET_MS, realmPromise, PRODUCE_CACHE_TTL_MS, MAX_PRODUCE_CACHE_ENTRIES, MAX_PRODUCE_ENTRY_BYTES, MAX_PRODUCE_CACHE_BYTES, produceCache, produceCacheGeneration, CAPTURE_SLOT, READBACK_SERVICE;
|
|
38243
38343
|
var init_widgets = __esm({
|
|
38244
38344
|
"../../core/dev-server/src/widgets.ts"() {
|
|
38245
38345
|
init_validator();
|
|
@@ -38247,6 +38347,12 @@ var init_widgets = __esm({
|
|
|
38247
38347
|
MAX_TIMELINE_FRAMES = 48;
|
|
38248
38348
|
WIDGET_BUDGET_MS = 5e3;
|
|
38249
38349
|
realmPromise = null;
|
|
38350
|
+
PRODUCE_CACHE_TTL_MS = 6e4;
|
|
38351
|
+
MAX_PRODUCE_CACHE_ENTRIES = 2048;
|
|
38352
|
+
MAX_PRODUCE_ENTRY_BYTES = 4 * 1024 * 1024;
|
|
38353
|
+
MAX_PRODUCE_CACHE_BYTES = 64 * 1024 * 1024;
|
|
38354
|
+
produceCache = /* @__PURE__ */ new WeakMap();
|
|
38355
|
+
produceCacheGeneration = 0;
|
|
38250
38356
|
CAPTURE_SLOT = "himi.widget.capture";
|
|
38251
38357
|
READBACK_SERVICE = "himi.widget.readback";
|
|
38252
38358
|
}
|
|
@@ -6590,7 +6590,7 @@
|
|
|
6590
6590
|
{
|
|
6591
6591
|
"name": "getPost",
|
|
6592
6592
|
"kind": "function",
|
|
6593
|
-
"jsdoc": "/** Fetch a single PUBLISHED post by id — GET /blog/v3/posts/{id}. The list\n * (queryPosts) returns published posts, so the detail reads them here (draft\n * ids are a different space — getDraftPost is for the edit/create flow).\n *\n * Body fieldsets (#826): Blog v3 `GET /posts/{id}` returns 200 but only the\n * LIST projection (title / excerpt / meta) unless the caller asks for the body —\n * the bare GET has NO `richContent` / `contentText`. So we request\n * RICH_CONTENT + CONTENT_TEXT by default and the article body loads on the happy\n * path; callers can override via `req.fieldsets`. (Supersedes the old #507 note:\n * the 502 this GET once returned for anonymous visitors is gone — it 200s now —\n * but a body-less 200 was never the \"body preserved whenever the backend is\n * healthy\" the earlier comment claimed; the body was simply never requested.)\n *\n * On any rejection (network / backend error) we still fall back to a queryPosts\n * filter-by-id — a graceful degrade to the LIST projection (no body) that keeps\n * blog detail + saved screens rendering instead of erroring out. `queryPosts`'s\n * request type has no `fieldsets` field, so that fallback path cannot carry the\n * body. */",
|
|
6593
|
+
"jsdoc": "/** Fetch a single PUBLISHED post by id — GET /blog/v3/posts/{id}. The list\n * (queryPosts) returns published posts, so the detail reads them here (draft\n * ids are a different space — getDraftPost is for the edit/create flow).\n *\n * Body fieldsets (#826): Blog v3 `GET /posts/{id}` returns 200 but only the\n * LIST projection (title / excerpt / meta) unless the caller asks for the body —\n * the bare GET has NO `richContent` / `contentText`. So we request\n * RICH_CONTENT + CONTENT_TEXT by default and the article body loads on the happy\n * path; callers can override via `req.fieldsets`. (Supersedes the old #507 note:\n * the 502 this GET once returned for anonymous visitors is gone — it 200s now —\n * but a body-less 200 was never the \"body preserved whenever the backend is\n * healthy\" the earlier comment claimed; the body was simply never requested.)\n *\n * On any rejection (network / backend error) we still fall back to a queryPosts\n * filter-by-id — a graceful degrade to the LIST projection (no body) that keeps\n * blog detail + saved screens rendering instead of erroring out. `queryPosts`'s\n * request type has no `fieldsets` field, so that fallback path cannot carry the\n * body.\n *\n * When that fallback ALSO finds nothing (#2658) — a deleted post, or one this\n * visitor may not see — we reject rather than resolve. `WixGetPostResponse.post`\n * is non-optional, so returning `{ post: resp.posts?.[0] }` would hand callers an\n * `undefined` the type promises is present, and the `post.title` access that type\n * licenses throws a `TypeError` deep inside the caller — the exact hard error\n * this fallback exists to prevent, and harder to diagnose than a clean rejection.\n * Every call site rides its own rejection path (cached-post state, draft-only\n * `catch`, or an `allSettled` filter), so rejecting is what routes them into the\n * graceful degrade they already implement. The originating failure travels as\n * `cause`, so the 404-vs-network distinction is not lost. */",
|
|
6594
6594
|
"decl": "export function getPost(\n postId: string,\n req: WixGetPostRequest = {},\n): Promise<WixGetPostResponse>;",
|
|
6595
6595
|
"http": "GET /blog/v3/posts/{…}"
|
|
6596
6596
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.879.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": [
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"artifactId": "himalaya-cli"
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
|
-
"falconPackageHash": "
|
|
66
|
+
"falconPackageHash": "cadb5d525c1bd00dfb5a1b90aeae24a17d6b94eb560176b0cb962516"
|
|
67
67
|
}
|