@wix/himalaya-cli 0.1442.0 → 0.1443.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/sdk/state/src/index.d.ts +7 -0
- package/dist/cli.mjs +33 -26
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/sdk-reference.json +1 -1
- package/package.json +2 -2
- package/templates/beauty-salon/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/beauty-salon/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/beauty-salon-owner/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/beauty-salon-owner/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/beauty-salon-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
- package/templates/branded-lite/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/branded-lite/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/community-club/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/community-club/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/community-club-owner/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/community-club-owner/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/community-club-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/community-club-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
- package/templates/community-club-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
- package/templates/community-club-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/community-club-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/community-club-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/community-club-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
- package/templates/community-club-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
- package/templates/community-club-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/community-club-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/events-meetups/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/events-meetups/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/events-meetups-owner/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/events-meetups-owner/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/events-meetups-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/gym-fitness/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/gym-fitness/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/gym-fitness-owner/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/gym-fitness-owner/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/gym-fitness-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
- package/templates/nonprofit-cause/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/nonprofit-cause/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
- package/templates/owner-lite/dev/index.ts +8 -2
- package/templates/owner-lite/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/owner-lite/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/owner-lite/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/owner-lite/tier5-src/himi-owner-lite-event/index.ts +2 -0
- package/templates/owner-lite/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-faq-category-form/index.ts +5 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-faq-question-form/index.ts +9 -3
- package/templates/owner-lite/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/owner-lite/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/owner-lite/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/owner-lite/tier5-src/himi-owner-lite-product/index.ts +2 -0
- package/templates/owner-lite/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
- package/templates/owner-lite/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/owner-lite/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
- package/templates/podcast-creator/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/podcast-creator/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/podcast-creator-owner/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/podcast-creator-owner/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/podcast-creator-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/portfolio-creative/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/portfolio-creative/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/portfolio-creative-owner/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/portfolio-creative-owner/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/portfolio-creative-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
- package/templates/restaurant/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/restaurant/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/restaurant-owner/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/restaurant-owner/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/restaurant-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
- package/templates/retail-store/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/retail-store/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/retail-store-owner/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/retail-store-owner/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/retail-store-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-product/index.ts +2 -0
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-product-form/index.ts +10 -4
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/yoga-studio/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/yoga-studio/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/yoga-studio-owner/tier5-src/_shared/collection-query.ts +32 -5
- package/templates/yoga-studio-owner/tier5-src/_shared/collection-service.ts +2 -1
- package/templates/yoga-studio-owner/tier5-src/_shared/owner-editor-value.ts +10 -0
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-event/index.ts +2 -0
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-event-form/index.ts +4 -1
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-manage/index.ts +18 -3
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-post/index.ts +2 -0
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-post-form/index.ts +10 -4
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-search/index.ts +11 -0
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-search/logic.ts +35 -1
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-service-form/index.ts +2 -1
package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/state/src/index.d.ts
CHANGED
|
@@ -15,6 +15,13 @@ export interface ServiceDefinition<S> {
|
|
|
15
15
|
* Runtimes that honour it set `himalaya.hydrationOptOut`; an older one ignores the option.
|
|
16
16
|
*/
|
|
17
17
|
notHydrated?: readonly (keyof S & string)[];
|
|
18
|
+
/**
|
|
19
|
+
* Keys that start each VISIT from `state`: when a cached embed shows the screen again (its warm worker
|
|
20
|
+
* reclaimed), these go back to their declared values before the screen reloads. For the same kind of
|
|
21
|
+
* per-run UI state as `notHydrated` (an editor's one-shot seed, an open sheet); never data a returning
|
|
22
|
+
* screen should keep showing. A full app's own screens and an uncached embed ignore it.
|
|
23
|
+
*/
|
|
24
|
+
perVisit?: readonly (keyof S & string)[];
|
|
18
25
|
}
|
|
19
26
|
export interface ServiceHandle<S> {
|
|
20
27
|
/** Snapshot of the current state. Cheap; safe to call from anywhere. */
|
package/dist/cli.mjs
CHANGED
|
@@ -8115,6 +8115,7 @@ function resolveTranslation(value, catalog3, sourceCatalog) {
|
|
|
8115
8115
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
8116
8116
|
var init_bindings = __esm({
|
|
8117
8117
|
"../../core/ts/src/bindings.ts"() {
|
|
8118
|
+
"use strict";
|
|
8118
8119
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
8119
8120
|
BINDING_SIGIL_RE = new RegExp(
|
|
8120
8121
|
`^\\$(?:${BINDING_SIGILS.filter((s2) => s2 !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -11358,9 +11359,15 @@ async function bootBundleWorker(bundleJs, opts) {
|
|
|
11358
11359
|
});
|
|
11359
11360
|
}
|
|
11360
11361
|
def.state = clearRuntimeError({ ...def.state, ...stripped });
|
|
11362
|
+
published(def);
|
|
11361
11363
|
return;
|
|
11362
11364
|
}
|
|
11363
11365
|
def.state = clearRuntimeError({ ...def.state, ...rec });
|
|
11366
|
+
published(def);
|
|
11367
|
+
};
|
|
11368
|
+
const published = (def) => {
|
|
11369
|
+
if (!opts.onPublish) return;
|
|
11370
|
+
opts.onPublish(captured.find(({ def: d2 }) => d2 === def)?.name ?? "", clone(def.state));
|
|
11364
11371
|
};
|
|
11365
11372
|
function clearRuntimeError(state) {
|
|
11366
11373
|
delete state._error;
|
|
@@ -161506,32 +161513,32 @@ var init_preview_assets_generated = __esm({
|
|
|
161506
161513
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
161507
161514
|
init_preview_assets_format();
|
|
161508
161515
|
PREVIEW_ASSET_MANIFEST = [
|
|
161509
|
-
{ key: "assets/DashboardHost-
|
|
161510
|
-
{ key: "assets/DevDrawer-
|
|
161511
|
-
{ key: "assets/IdiomCompare-
|
|
161512
|
-
{ key: "assets/LightboxViewer-
|
|
161513
|
-
{ key: "assets/PhonePreviewControl-
|
|
161514
|
-
{ key: "assets/SchemeCompare-
|
|
161515
|
-
{ key: "assets/index-
|
|
161516
|
-
{ key: "assets/pdf-
|
|
161517
|
-
{ key: "assets/pdf.worker.min-BQa_JDET.js", contentType: "application/javascript; charset=utf-8", offset:
|
|
161518
|
-
{ key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/javascript; charset=utf-8", offset:
|
|
161519
|
-
{ key: "assets/pdfDocument-
|
|
161520
|
-
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset:
|
|
161521
|
-
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset:
|
|
161522
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
161523
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
161524
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
161525
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
161526
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
161527
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
161528
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
161529
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
161530
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
161531
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
161532
|
-
{ key: "himi-sw.js", contentType: "application/javascript; charset=utf-8", offset:
|
|
161533
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
161534
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
161516
|
+
{ key: "assets/DashboardHost-CWbeef06.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 2916, sha256: "9ab72647e78bee902e76c4672f3d22b18d9b7a79892e0e64ae80ffb574417911" },
|
|
161517
|
+
{ key: "assets/DevDrawer-mM0I8ALw.js", contentType: "application/javascript; charset=utf-8", offset: 2924, length: 16744, sha256: "9bbb22f0ee24b6782c4645da75788028c942122748f0149d00e9039cdd09f0b1" },
|
|
161518
|
+
{ key: "assets/IdiomCompare-SDHU6iNa.js", contentType: "application/javascript; charset=utf-8", offset: 19668, length: 1892, sha256: "2af535cb7bb80d6f90d99bbb67470e4f9754949b62e08f4767a977a3414ae43e" },
|
|
161519
|
+
{ key: "assets/LightboxViewer-YV8gCISo.js", contentType: "application/javascript; charset=utf-8", offset: 21560, length: 8132, sha256: "e3c873007b6790042640966c3fb0d19f16d2f0ca4c41276838d38e90c852391a" },
|
|
161520
|
+
{ key: "assets/PhonePreviewControl-Dl_3aZaI.js", contentType: "application/javascript; charset=utf-8", offset: 29692, length: 37729, sha256: "f8d15085d2b83522584fd3a30bc5bead6d68c885e2987e7df12035c45d1aa003" },
|
|
161521
|
+
{ key: "assets/SchemeCompare-VEnYs5jY.js", contentType: "application/javascript; charset=utf-8", offset: 67421, length: 1824, sha256: "9f51da5008d043106847efb01ab675ae9c4ed58e6745cba03b1fd0b5f173a520" },
|
|
161522
|
+
{ key: "assets/index-zKquXoS4.js", contentType: "application/javascript; charset=utf-8", offset: 69245, length: 1268324, sha256: "4d6fe8fe1939fbc4a50b528233ff482afc6f615a0df92b54847386d0557b837a" },
|
|
161523
|
+
{ key: "assets/pdf-ipblMaD0.js", contentType: "application/javascript; charset=utf-8", offset: 1337569, length: 488199, sha256: "f103cd80a3f9a971e1be6162886350314c28bd42c1cb998210147e4a5a23a947" },
|
|
161524
|
+
{ key: "assets/pdf.worker.min-BQa_JDET.js", contentType: "application/javascript; charset=utf-8", offset: 1825768, length: 73, sha256: "41bcfda4f3c8c0a81c785ea87c69afc8e7d0ed8c333324aee94c273d881bb6aa" },
|
|
161525
|
+
{ key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/javascript; charset=utf-8", offset: 1825841, length: 1317034, sha256: "a33cfe728c584fdba4fcc1fd54bcdc2f9f2f13889ddbb5b2bd1d0f8cbe49b84e" },
|
|
161526
|
+
{ key: "assets/pdfDocument-BLnEEkur.js", contentType: "application/javascript; charset=utf-8", offset: 3142875, length: 2868, sha256: "3913f6a2cc3e3eda95617b848a6240dfd132d2da9629fc429b144b722401e2f0" },
|
|
161527
|
+
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 3145743, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
|
|
161528
|
+
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 3150353, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
|
|
161529
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 3638937, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
161530
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 3729861, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
161531
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 3820845, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
161532
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 3911825, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
161533
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 4002697, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
161534
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 4093677, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
161535
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 4202313, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
161536
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 4311397, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
161537
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 4420445, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
161538
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 4528145, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
161539
|
+
{ key: "himi-sw.js", contentType: "application/javascript; charset=utf-8", offset: 4616253, length: 6748, sha256: "4a92459977d7cefa1a6a7e020c3a63509737f083b3f2773557c1a5771665811a" },
|
|
161540
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 4623001, length: 4947, sha256: "ac12b463d6c2a4195ff7f6fb911b79c7e14de48488493bf6480b660866f833f9" },
|
|
161541
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 4627948, length: 17786, sha256: "084107ca997628c248f1b0ba3a7494744850df39fad813546ab8bdb82a6058da" }
|
|
161535
161542
|
];
|
|
161536
161543
|
}
|
|
161537
161544
|
});
|
|
Binary file
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"name": "ServiceDefinition",
|
|
9
9
|
"kind": "interface",
|
|
10
10
|
"jsdoc": "",
|
|
11
|
-
"decl": "export interface ServiceDefinition<S> {\n /** Initial state for the service. Must be JSON-serializable. */\n state: S;\n\n /**\n * Actions: pure functions of `(state, ...args) → newState` (or async). The\n * platform wraps each action so calling it from JS or from `__invokeAction`\n * (native side) updates the service's state and notifies subscribers.\n */\n actions?: Record<\n string,\n // `never[]`, not `unknown[]` — same reason as defineService's constraint below:\n // parameters are contravariant, so `unknown[]` rejects every handler that narrows\n // its payload. Leaving this one loose would reintroduce the same TS2344 for anyone\n // who annotates a `ServiceDefinition<S>` explicitly instead of inferring it.\n (state: S, ...args: never[]) => S | undefined | Promise<S | undefined>\n >;\n\n /**\n * Keys a cold boot takes from `state`, never from the persisted snapshot (cold-boot\n * hydration). For UI state that must describe THIS run — an editor's one-shot seed, a\n * \"still loading\" gate, an open sheet — where last run's value would be wrong, not just stale.\n * Runtimes that honour it set `himalaya.hydrationOptOut`; an older one ignores the option.\n */\n notHydrated?: readonly (keyof S & string)[];\n}"
|
|
11
|
+
"decl": "export interface ServiceDefinition<S> {\n /** Initial state for the service. Must be JSON-serializable. */\n state: S;\n\n /**\n * Actions: pure functions of `(state, ...args) → newState` (or async). The\n * platform wraps each action so calling it from JS or from `__invokeAction`\n * (native side) updates the service's state and notifies subscribers.\n */\n actions?: Record<\n string,\n // `never[]`, not `unknown[]` — same reason as defineService's constraint below:\n // parameters are contravariant, so `unknown[]` rejects every handler that narrows\n // its payload. Leaving this one loose would reintroduce the same TS2344 for anyone\n // who annotates a `ServiceDefinition<S>` explicitly instead of inferring it.\n (state: S, ...args: never[]) => S | undefined | Promise<S | undefined>\n >;\n\n /**\n * Keys a cold boot takes from `state`, never from the persisted snapshot (cold-boot\n * hydration). For UI state that must describe THIS run — an editor's one-shot seed, a\n * \"still loading\" gate, an open sheet — where last run's value would be wrong, not just stale.\n * Runtimes that honour it set `himalaya.hydrationOptOut`; an older one ignores the option.\n */\n notHydrated?: readonly (keyof S & string)[];\n\n /**\n * Keys that start each VISIT from `state`: when a cached embed shows the screen again (its warm worker\n * reclaimed), these go back to their declared values before the screen reloads. For the same kind of\n * per-run UI state as `notHydrated` (an editor's one-shot seed, an open sheet); never data a returning\n * screen should keep showing. A full app's own screens and an uncached embed ignore it.\n */\n perVisit?: readonly (keyof S & string)[];\n}"
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
"name": "ServiceHandle",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1443.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": [
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"artifactId": "himalaya-cli"
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
"falconPackageHash": "
|
|
74
|
+
"falconPackageHash": "8a70f3bc09b20693d0d5f9f3f9412dc5cdbd20ee62407d59ff646f7f"
|
|
75
75
|
}
|
|
@@ -27,7 +27,9 @@ export interface CollectionQuerySource<Row> {
|
|
|
27
27
|
cached?(criteria: CollectionQuery): Promise<CollectionPage<Row> | undefined>;
|
|
28
28
|
id(row: Row): string;
|
|
29
29
|
errorMessage?(error: unknown): string;
|
|
30
|
-
/** Private collections must discard prior rows when access or identity changes.
|
|
30
|
+
/** Private collections must discard prior rows when access or identity changes. A revalidation keeps the
|
|
31
|
+
* rows it shows through any other failure: safe because one worker never serves two identities (its pool
|
|
32
|
+
* key carries the account, and a purge tears parked workers down). */
|
|
31
33
|
clearOnError?(error: unknown): boolean;
|
|
32
34
|
}
|
|
33
35
|
const normalize = (q: Partial<CollectionQuery>): CollectionQuery => ({
|
|
@@ -46,8 +48,17 @@ export function createCollectionQuery<Row>(source: CollectionQuerySource<Row>, p
|
|
|
46
48
|
let generation = 0, disposed = false;
|
|
47
49
|
let loadedPages = 0, restoringPages = 0;
|
|
48
50
|
let state: CollectionQueryState<Row> = { criteria: normalize({}), items: [], nextCursor: '', status: 'idle', loadingMore: false, pageError: false, complete: false, error: '' };
|
|
51
|
+
/** The query a revalidation is running under: its snapshots are held back until it is done. */
|
|
52
|
+
let revalidating = -1;
|
|
53
|
+
/** What the screen shows: the last published state, restored when a revalidation fails. */
|
|
54
|
+
let shown: { state: CollectionQueryState<Row>; loadedPages: number } | undefined;
|
|
55
|
+
let clearedByError = false;
|
|
49
56
|
const snapshot = (): CollectionQueryState<Row> => ({ ...state, criteria: copyQuery(state.criteria), items: [...state.items] });
|
|
50
|
-
const emit = () => {
|
|
57
|
+
const emit = () => {
|
|
58
|
+
if (disposed || revalidating === generation) return;
|
|
59
|
+
shown = { state: snapshot(), loadedPages };
|
|
60
|
+
publish(snapshot());
|
|
61
|
+
};
|
|
51
62
|
const merge = (old: Row[], page: Row[]): Row[] => {
|
|
52
63
|
const positions = new Map<string, number>(), result: Row[] = [];
|
|
53
64
|
for (const item of [...old, ...page]) {
|
|
@@ -88,6 +99,8 @@ export function createCollectionQuery<Row>(source: CollectionQuerySource<Row>, p
|
|
|
88
99
|
} catch (error) {
|
|
89
100
|
if (disposed || generation !== revision) return;
|
|
90
101
|
const clear = source.clearOnError?.(error) === true;
|
|
102
|
+
// Revoked access always ends what a revalidation showed, whether or not the source clears its rows.
|
|
103
|
+
clearedByError = clear || /HTTP 40[13]\b/.test(String(error));
|
|
91
104
|
if (clear) loadedPages = 0;
|
|
92
105
|
state = { ...state, ...(clear ? { items: [], nextCursor: '', total: undefined, metadata: undefined } : {}),
|
|
93
106
|
status: append && !clear ? 'ready' : 'error', loadingMore: false, pageError: append && !clear, complete: false,
|
|
@@ -97,13 +110,18 @@ export function createCollectionQuery<Row>(source: CollectionQuerySource<Row>, p
|
|
|
97
110
|
};
|
|
98
111
|
return {
|
|
99
112
|
getState: snapshot,
|
|
100
|
-
|
|
113
|
+
/** [revalidate]: a screen coming back re-queries the rows it shows. They stay on screen until every
|
|
114
|
+
* page is in, and a failure keeps them; revoked access still clears them, and other criteria reset. */
|
|
115
|
+
async query(criteria: Partial<CollectionQuery>, restorePages = false, revalidate = false): Promise<void> {
|
|
101
116
|
if (disposed) return Promise.resolve();
|
|
102
117
|
const next = normalize(criteria);
|
|
103
|
-
const
|
|
104
|
-
|
|
118
|
+
const same = JSON.stringify(next) === JSON.stringify(state.criteria);
|
|
119
|
+
const count = restorePages && same ? Math.max(loadedPages, restoringPages, 1) : 1;
|
|
120
|
+
const showing = shown && shown.state.status === 'ready' && shown.state.items.length > 0 && !shown.state.pageError
|
|
121
|
+
&& !shown.state.loadingMore && JSON.stringify(shown.state.criteria) === JSON.stringify(next) ? shown : undefined;
|
|
105
122
|
restoringPages = count;
|
|
106
123
|
state = { ...state, criteria: next };
|
|
124
|
+
if (revalidate && showing) { revalidating = generation + 1; clearedByError = false; }
|
|
107
125
|
const pending = fetch(false);
|
|
108
126
|
const revision = generation;
|
|
109
127
|
await pending;
|
|
@@ -112,6 +130,15 @@ export function createCollectionQuery<Row>(source: CollectionQuerySource<Row>, p
|
|
|
112
130
|
while (!disposed && generation === revision && loadedPages < count && state.status === 'ready'
|
|
113
131
|
&& !state.pageError && !state.loadingMore && state.nextCursor) await fetch(true);
|
|
114
132
|
if (generation === revision) restoringPages = 0;
|
|
133
|
+
if (revalidating === revision) {
|
|
134
|
+
revalidating = -1;
|
|
135
|
+
if (generation !== revision) return;
|
|
136
|
+
if ((state.status !== 'ready' || state.pageError) && showing && !clearedByError) {
|
|
137
|
+
state = { ...showing.state, criteria: next };
|
|
138
|
+
loadedPages = showing.loadedPages;
|
|
139
|
+
}
|
|
140
|
+
emit();
|
|
141
|
+
}
|
|
115
142
|
},
|
|
116
143
|
refresh: () => { restoringPages = 0; return fetch(false); },
|
|
117
144
|
loadMore: () => fetch(true),
|
|
@@ -299,7 +299,8 @@ export function decorateCollection(name: string, def: { state: State; actions?:
|
|
|
299
299
|
actions.load = (_s, arg) => {
|
|
300
300
|
stashCopy(arg); syncSaved(); applyNavigationCriteria(arg, _s);
|
|
301
301
|
backend.onLoad?.(arg);
|
|
302
|
-
|
|
302
|
+
// A load of what the screen already shows is the screen coming back: it revalidates behind its rows.
|
|
303
|
+
return backend.controller.query(criteria(), backend.restorePagesOnLoad, true).then(() => undefined);
|
|
303
304
|
};
|
|
304
305
|
actions.refresh = (_s, arg) => {
|
|
305
306
|
stashCopy(arg); syncSaved();
|
|
@@ -27,7 +27,9 @@ export interface CollectionQuerySource<Row> {
|
|
|
27
27
|
cached?(criteria: CollectionQuery): Promise<CollectionPage<Row> | undefined>;
|
|
28
28
|
id(row: Row): string;
|
|
29
29
|
errorMessage?(error: unknown): string;
|
|
30
|
-
/** Private collections must discard prior rows when access or identity changes.
|
|
30
|
+
/** Private collections must discard prior rows when access or identity changes. A revalidation keeps the
|
|
31
|
+
* rows it shows through any other failure: safe because one worker never serves two identities (its pool
|
|
32
|
+
* key carries the account, and a purge tears parked workers down). */
|
|
31
33
|
clearOnError?(error: unknown): boolean;
|
|
32
34
|
}
|
|
33
35
|
const normalize = (q: Partial<CollectionQuery>): CollectionQuery => ({
|
|
@@ -46,8 +48,17 @@ export function createCollectionQuery<Row>(source: CollectionQuerySource<Row>, p
|
|
|
46
48
|
let generation = 0, disposed = false;
|
|
47
49
|
let loadedPages = 0, restoringPages = 0;
|
|
48
50
|
let state: CollectionQueryState<Row> = { criteria: normalize({}), items: [], nextCursor: '', status: 'idle', loadingMore: false, pageError: false, complete: false, error: '' };
|
|
51
|
+
/** The query a revalidation is running under: its snapshots are held back until it is done. */
|
|
52
|
+
let revalidating = -1;
|
|
53
|
+
/** What the screen shows: the last published state, restored when a revalidation fails. */
|
|
54
|
+
let shown: { state: CollectionQueryState<Row>; loadedPages: number } | undefined;
|
|
55
|
+
let clearedByError = false;
|
|
49
56
|
const snapshot = (): CollectionQueryState<Row> => ({ ...state, criteria: copyQuery(state.criteria), items: [...state.items] });
|
|
50
|
-
const emit = () => {
|
|
57
|
+
const emit = () => {
|
|
58
|
+
if (disposed || revalidating === generation) return;
|
|
59
|
+
shown = { state: snapshot(), loadedPages };
|
|
60
|
+
publish(snapshot());
|
|
61
|
+
};
|
|
51
62
|
const merge = (old: Row[], page: Row[]): Row[] => {
|
|
52
63
|
const positions = new Map<string, number>(), result: Row[] = [];
|
|
53
64
|
for (const item of [...old, ...page]) {
|
|
@@ -88,6 +99,8 @@ export function createCollectionQuery<Row>(source: CollectionQuerySource<Row>, p
|
|
|
88
99
|
} catch (error) {
|
|
89
100
|
if (disposed || generation !== revision) return;
|
|
90
101
|
const clear = source.clearOnError?.(error) === true;
|
|
102
|
+
// Revoked access always ends what a revalidation showed, whether or not the source clears its rows.
|
|
103
|
+
clearedByError = clear || /HTTP 40[13]\b/.test(String(error));
|
|
91
104
|
if (clear) loadedPages = 0;
|
|
92
105
|
state = { ...state, ...(clear ? { items: [], nextCursor: '', total: undefined, metadata: undefined } : {}),
|
|
93
106
|
status: append && !clear ? 'ready' : 'error', loadingMore: false, pageError: append && !clear, complete: false,
|
|
@@ -97,13 +110,18 @@ export function createCollectionQuery<Row>(source: CollectionQuerySource<Row>, p
|
|
|
97
110
|
};
|
|
98
111
|
return {
|
|
99
112
|
getState: snapshot,
|
|
100
|
-
|
|
113
|
+
/** [revalidate]: a screen coming back re-queries the rows it shows. They stay on screen until every
|
|
114
|
+
* page is in, and a failure keeps them; revoked access still clears them, and other criteria reset. */
|
|
115
|
+
async query(criteria: Partial<CollectionQuery>, restorePages = false, revalidate = false): Promise<void> {
|
|
101
116
|
if (disposed) return Promise.resolve();
|
|
102
117
|
const next = normalize(criteria);
|
|
103
|
-
const
|
|
104
|
-
|
|
118
|
+
const same = JSON.stringify(next) === JSON.stringify(state.criteria);
|
|
119
|
+
const count = restorePages && same ? Math.max(loadedPages, restoringPages, 1) : 1;
|
|
120
|
+
const showing = shown && shown.state.status === 'ready' && shown.state.items.length > 0 && !shown.state.pageError
|
|
121
|
+
&& !shown.state.loadingMore && JSON.stringify(shown.state.criteria) === JSON.stringify(next) ? shown : undefined;
|
|
105
122
|
restoringPages = count;
|
|
106
123
|
state = { ...state, criteria: next };
|
|
124
|
+
if (revalidate && showing) { revalidating = generation + 1; clearedByError = false; }
|
|
107
125
|
const pending = fetch(false);
|
|
108
126
|
const revision = generation;
|
|
109
127
|
await pending;
|
|
@@ -112,6 +130,15 @@ export function createCollectionQuery<Row>(source: CollectionQuerySource<Row>, p
|
|
|
112
130
|
while (!disposed && generation === revision && loadedPages < count && state.status === 'ready'
|
|
113
131
|
&& !state.pageError && !state.loadingMore && state.nextCursor) await fetch(true);
|
|
114
132
|
if (generation === revision) restoringPages = 0;
|
|
133
|
+
if (revalidating === revision) {
|
|
134
|
+
revalidating = -1;
|
|
135
|
+
if (generation !== revision) return;
|
|
136
|
+
if ((state.status !== 'ready' || state.pageError) && showing && !clearedByError) {
|
|
137
|
+
state = { ...showing.state, criteria: next };
|
|
138
|
+
loadedPages = showing.loadedPages;
|
|
139
|
+
}
|
|
140
|
+
emit();
|
|
141
|
+
}
|
|
115
142
|
},
|
|
116
143
|
refresh: () => { restoringPages = 0; return fetch(false); },
|
|
117
144
|
loadMore: () => fetch(true),
|
|
@@ -299,7 +299,8 @@ export function decorateCollection(name: string, def: { state: State; actions?:
|
|
|
299
299
|
actions.load = (_s, arg) => {
|
|
300
300
|
stashCopy(arg); syncSaved(); applyNavigationCriteria(arg, _s);
|
|
301
301
|
backend.onLoad?.(arg);
|
|
302
|
-
|
|
302
|
+
// A load of what the screen already shows is the screen coming back: it revalidates behind its rows.
|
|
303
|
+
return backend.controller.query(criteria(), backend.restorePagesOnLoad, true).then(() => undefined);
|
|
303
304
|
};
|
|
304
305
|
actions.refresh = (_s, arg) => {
|
|
305
306
|
stashCopy(arg); syncSaved();
|
|
@@ -91,6 +91,16 @@ export function editorRunKeys<K extends string>(key: K): [`${K}Json`, `${K}Pendi
|
|
|
91
91
|
return [`${key}Json`, `${key}Pending`, `${key}Dirty`, `${key}Edits`];
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
/** Does the form already hold `target` with its editor run in progress? A `load` for it then keeps the form as
|
|
95
|
+
* it is: on the way back to a warm worker (its refresh and onAppear) a re-read would race an edit in flight and
|
|
96
|
+
* reset the reported edit, and the editor, which seeds once, would show another document than the state holds.
|
|
97
|
+
* An edit form holds its record once the editor loaded; a create form holds a draft once the owner edited. */
|
|
98
|
+
export function holdsLoadedForm(state: object, target: { id: string; mode: string }, key: string): boolean {
|
|
99
|
+
const s = state as Record<string, unknown>;
|
|
100
|
+
if (s.status === 'error' || s.error || s.mode !== target.mode || (s.id ?? '') !== target.id) return false;
|
|
101
|
+
return target.mode === 'create' ? s[`${key}Dirty`] === true || Number(s[`${key}Edits`] ?? 0) > 0 : s[`${key}Pending`] === false;
|
|
102
|
+
}
|
|
103
|
+
|
|
94
104
|
/** The same keys on a runtime that ignores `notHydrated` (a binary from before #3644, still served new
|
|
95
105
|
* bundles over the air): reset them in place, before any action runs. A no-op where the runtime
|
|
96
106
|
* honours the option (`himalaya.hydrationOptOut`). */
|
|
@@ -214,6 +214,22 @@ let loadGeneration = 0;
|
|
|
214
214
|
let newestStarted: State | undefined;
|
|
215
215
|
let newestSettled: { generation: number; state: State } | undefined;
|
|
216
216
|
|
|
217
|
+
/** A hub already showing its areas re-reads their summaries behind them, never back under the skeleton: the
|
|
218
|
+
* screen coming back (a warm worker's refresh and its onAppear, at once) keeps what it shows until they land. */
|
|
219
|
+
function revalidating(state: State, areas: State['areas'] = state.areas): State {
|
|
220
|
+
// The areas as delivered now (labels, routes), each still showing the summary it showed.
|
|
221
|
+
const shown = new Map(state.areas.map(area => [area.id, area]));
|
|
222
|
+
const next = areas.map(area => {
|
|
223
|
+
const was = shown.get(area.id);
|
|
224
|
+
return was ? { ...area, metricText: was.metricText, statusText: was.statusText, unavailable: was.unavailable } : area;
|
|
225
|
+
});
|
|
226
|
+
return derive({ ...state, areas: next, businessName: currentBusinessName, handoffError: '' }, next);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function sameAreas(shown: State['areas'], next: State['areas']): boolean {
|
|
230
|
+
return shown.length === next.length && shown.every((area, i) => area.id === next[i].id && area.metricKey === next[i].metricKey);
|
|
231
|
+
}
|
|
232
|
+
|
|
217
233
|
async function loadMetrics(state: State): Promise<State> {
|
|
218
234
|
const generation = ++loadGeneration;
|
|
219
235
|
newestStarted = state;
|
|
@@ -292,12 +308,11 @@ const svc = defineService<State, {
|
|
|
292
308
|
// it must not settle (that derived "0 business areas" and painted the
|
|
293
309
|
// filtered-empty state); once they are, it re-reads their summaries.
|
|
294
310
|
if (!('areas' in read(arg))) {
|
|
295
|
-
return state.status === 'ready'
|
|
296
|
-
? loadMetrics(derive({ ...state, isLoading: true, notLoading: false, summaryNote: '', handoffError: '' }))
|
|
297
|
-
: { ...state, businessName: currentBusinessName };
|
|
311
|
+
return state.status === 'ready' ? loadMetrics(revalidating(state)) : { ...state, businessName: currentBusinessName };
|
|
298
312
|
}
|
|
299
313
|
const parsed = (() => { try { return JSON.parse(str(arg, 'areas') || '[]'); } catch { return []; } })();
|
|
300
314
|
const areas = parseAreas(parsed);
|
|
315
|
+
if (state.status === 'ready' && sameAreas(state.areas, areas)) return loadMetrics(revalidating(state, areas));
|
|
301
316
|
return loadMetrics(derive({ ...state, status: 'ready', areas, isLoading: true, notLoading: false, summaryNote: '', handoffError: '' }, areas));
|
|
302
317
|
},
|
|
303
318
|
// Refresh re-reads summaries for KNOWN areas. Before the descriptor has
|
|
@@ -340,6 +340,8 @@ const svc = defineService<PostState, {
|
|
|
340
340
|
}>("himiOwnerLitePost", {
|
|
341
341
|
state: shape({ status: "loading" }),
|
|
342
342
|
notHydrated: [...DELETE_RUN_KEYS],
|
|
343
|
+
// perVisit: a cached embed's warm return starts this run fresh, as a cold boot does (`__resetRunState`).
|
|
344
|
+
perVisit: [...DELETE_RUN_KEYS],
|
|
343
345
|
actions: {
|
|
344
346
|
load: async (s0, arg) => {
|
|
345
347
|
const s = disarm(s0);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// screen (himiOwnerLitePost.publish). Bound by buildForm ($service:himiOwnerLitePostForm.*).
|
|
5
5
|
|
|
6
6
|
import { postBodyText, plainPostBody, postCoverUrl } from "../_shared/owner-post-content.js";
|
|
7
|
-
import { editorSubmitValue, queuedDocument, editorChanged, editorRunKeys, resetHydratedEditorOnOlderRuntime, editorAfterSave, liveState, settleOverLive } from "../_shared/owner-editor-value.js";
|
|
7
|
+
import { editorSubmitValue, queuedDocument, editorChanged, editorRunKeys, resetHydratedEditorOnOlderRuntime, editorAfterSave, liveState, settleOverLive, holdsLoadedForm } from "../_shared/owner-editor-value.js";
|
|
8
8
|
import { ricosUploadService } from "@himalaya/wix-rich-content-editor";
|
|
9
9
|
import { wixCall } from "@himalaya/wix-site-media";
|
|
10
10
|
import { wixMediaUrl, WIX_DETAIL_IMAGE } from "../_shared/himi-store.js";
|
|
@@ -165,18 +165,24 @@ const svc = defineService<PostFormState, {
|
|
|
165
165
|
bodyChanged: (s: PostFormState, arg?: unknown) => PostFormState;
|
|
166
166
|
submit: (s: PostFormState, values?: Record<string, unknown>) => Promise<PostFormState>;
|
|
167
167
|
}>("himiOwnerLitePostForm", {
|
|
168
|
-
|
|
168
|
+
// The editor stays hidden until this run's load lands, however the form was opened (an id as input or in the params).
|
|
169
|
+
state: shape({ mode: startMode, id: initialInput.id ?? "", bodyPending: true }),
|
|
169
170
|
// [rico] #3644 — this run's editor state and UI: a cold boot takes these from `state`, never from
|
|
170
171
|
// the persisted snapshot (the editor seeds once; last run's sheet is not this run's).
|
|
171
172
|
notHydrated: [...editorRunKeys("body"), "detailsOpen"],
|
|
173
|
+
// perVisit: a cached embed's warm return starts this run fresh, as a cold boot does (`__resetRunState`).
|
|
174
|
+
perVisit: [...editorRunKeys("body"), "detailsOpen"],
|
|
172
175
|
actions: {
|
|
173
176
|
load: async (s, arg) => {
|
|
174
177
|
stashCopy(arg); // absorb the descriptor's onAppear copy-pack param
|
|
175
178
|
// WS-C — nav-param input is PRIMARY (the canonical create-or-edit shell
|
|
176
179
|
// bakes no id/mode); the onAppear `id` param is the #570 suffixed-build
|
|
177
180
|
// fallback. An id ⇒ edit; no id anywhere ⇒ the create shell.
|
|
178
|
-
|
|
179
|
-
|
|
181
|
+
// The held id is for the host's bare refresh only (no argument): an onAppear without an id is a create screen.
|
|
182
|
+
const id = navInputId() || idFrom(arg, arg === undefined ? s.id : "");
|
|
183
|
+
if (holdsLoadedForm(s, { id, mode: id ? "edit" : "create" }, "body")) return s;
|
|
184
|
+
// A form that held a record (the one just saved) opens blank.
|
|
185
|
+
if (!id) return shape({ ...(s.id ? {} : s), ...BODY_LOADED, mode: "create", id: "", bodyJson: "", status: "idle", error: "", demoNote: isOwnerPreviewDemo() ? copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) : "" });
|
|
180
186
|
if (isOwnerPreviewDemo()) {
|
|
181
187
|
const d = DEMO_POSTS.find((x) => x.id === id);
|
|
182
188
|
if (d) {
|
|
@@ -305,6 +305,8 @@ const svc = defineService<ProductState, {
|
|
|
305
305
|
}>("himiOwnerLiteProduct", {
|
|
306
306
|
state: shape({ status: "loading" }),
|
|
307
307
|
notHydrated: [...DELETE_RUN_KEYS],
|
|
308
|
+
// perVisit: a cached embed's warm return starts this run fresh, as a cold boot does (`__resetRunState`).
|
|
309
|
+
perVisit: [...DELETE_RUN_KEYS],
|
|
308
310
|
actions: {
|
|
309
311
|
load: async (s0, arg) => {
|
|
310
312
|
const s = disarm(s0);
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
import { get as dbGet, upsert as dbUpsert, remove as dbRemove, type DbEntity } from "../_shared/owner-local-db.js";
|
|
19
19
|
import { htmlIsTrivial, htmlPreviewText } from "../_shared/owner-rich-guard.js";
|
|
20
20
|
import { postBodyText, plainPostBody } from "../_shared/owner-post-content.js";
|
|
21
|
-
import { editorSubmitValue, queuedDocument, editorChanged, cachedRichVerdict, editorRunKeys, resetHydratedEditorOnOlderRuntime, editorAfterSave, liveState, settleOverLive } from "../_shared/owner-editor-value.js";
|
|
21
|
+
import { editorSubmitValue, queuedDocument, editorChanged, cachedRichVerdict, editorRunKeys, resetHydratedEditorOnOlderRuntime, editorAfterSave, liveState, settleOverLive, holdsLoadedForm } from "../_shared/owner-editor-value.js";
|
|
22
22
|
import { parseRicosJson } from "@himalaya/wix-rich-content";
|
|
23
23
|
import { ricosUploadService } from "@himalaya/wix-rich-content-editor";
|
|
24
24
|
import { ownerLoadError, isOwnerPreviewDemo, ownerDemoFallback, ownerWriteError } from "../_shared/owner-load-error.js";
|
|
@@ -195,17 +195,23 @@ const svc = defineService<ProductFormState, {
|
|
|
195
195
|
submit: (s: ProductFormState, values?: Record<string, unknown>) => Promise<ProductFormState>;
|
|
196
196
|
remove: (s: ProductFormState) => Promise<ProductFormState>;
|
|
197
197
|
}>("himiOwnerLiteProductForm", {
|
|
198
|
-
|
|
198
|
+
// The editor stays hidden until this run's load lands, however the form was opened (an id as input or in the params).
|
|
199
|
+
state: shape({ mode: startMode, id: initialInput.id ?? "", descriptionPending: true }),
|
|
199
200
|
// [rico] #3644 — this run's editor state: a cold boot takes it from `state`, never the snapshot.
|
|
200
201
|
notHydrated: editorRunKeys("description"),
|
|
202
|
+
// perVisit: a cached embed's warm return starts this run fresh, as a cold boot does (`__resetRunState`).
|
|
203
|
+
perVisit: editorRunKeys("description"),
|
|
201
204
|
actions: {
|
|
202
205
|
load: async (s, arg) => {
|
|
203
206
|
stashCopy(arg); // absorb the descriptor's onAppear copy-pack param
|
|
204
207
|
// WS-C — nav-param input is PRIMARY (the canonical create-or-edit shell
|
|
205
208
|
// bakes no id/mode); the onAppear `id` param is the #570 suffixed-build
|
|
206
209
|
// fallback. An id ⇒ edit; no id anywhere ⇒ the create shell.
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
// The held id is for the host's bare refresh only (no argument): an onAppear without an id is a create screen.
|
|
211
|
+
const id = navInputId() || idFrom(arg, arg === undefined ? s.id : "");
|
|
212
|
+
if (holdsLoadedForm(s, { id, mode: id ? "edit" : "create" }, "description")) return s;
|
|
213
|
+
// A form that held a record (the one just saved) opens blank.
|
|
214
|
+
if (!id) return shape({ ...(s.id ? {} : s), ...DESCRIPTION_LOADED, mode: "create", id: "", descriptionMode: "plain", descriptionJson: "", status: "idle", error: "", demoNote: isOwnerPreviewDemo() ? copyParam("ownerCommon.demoSaveNote", DEMO_SAVE_NOTE) : "" });
|
|
209
215
|
if (isOwnerPreviewDemo()) {
|
|
210
216
|
const d = DEMO_PRODUCTS.find((p) => p.id === id);
|
|
211
217
|
if (d) {
|
|
@@ -254,6 +254,8 @@ const IDLE: State = {
|
|
|
254
254
|
|
|
255
255
|
/** Rebuilt on `load`, because the allowlist arrives with the descriptor. */
|
|
256
256
|
let coordinator: ReturnType<typeof createGroupedSearch> | undefined;
|
|
257
|
+
/** The allowlist the coordinator was built for. */
|
|
258
|
+
let coordinatorSources = "";
|
|
257
259
|
let published: State = IDLE;
|
|
258
260
|
const memory = localPreferences("ownerSearch", normalizeMemory);
|
|
259
261
|
|
|
@@ -279,6 +281,15 @@ const svc = defineService<State, {
|
|
|
279
281
|
actions: {
|
|
280
282
|
load: async (_state, arg) => {
|
|
281
283
|
stashCopy(arg);
|
|
284
|
+
// The screen coming back re-runs its search behind what it shows: a warm worker's refresh calls `load` bare (no allowlist),
|
|
285
|
+
// and its onAppear repeats the allowlist the coordinator was built for.
|
|
286
|
+
const sources = str(arg, "sources");
|
|
287
|
+
if (coordinator && (!sources || sources === coordinatorSources)) {
|
|
288
|
+
await coordinator.revalidate();
|
|
289
|
+
remember();
|
|
290
|
+
return published;
|
|
291
|
+
}
|
|
292
|
+
coordinatorSources = sources;
|
|
282
293
|
const allowed = (() => {
|
|
283
294
|
try {
|
|
284
295
|
return JSON.parse(str(arg, "sources") || "[]");
|
|
@@ -446,7 +446,13 @@ export function createGroupedSearch(
|
|
|
446
446
|
};
|
|
447
447
|
};
|
|
448
448
|
|
|
449
|
-
|
|
449
|
+
/** The revalidation running behind the shown rows (0: none): its snapshots are held back until it is done. */
|
|
450
|
+
let holding = 0, holds = 0;
|
|
451
|
+
/** The depth the running revalidation restores, so one that overlaps it starts from the owner's depth, not
|
|
452
|
+
* from its reset; and the revalidation itself, which a "look further" tapped meanwhile waits for. */
|
|
453
|
+
let heldDepth: Record<string, number> = {};
|
|
454
|
+
let revalidation: Promise<void> | undefined;
|
|
455
|
+
const emit = () => { if (!disposed && !holding) publish(snapshot()); };
|
|
450
456
|
|
|
451
457
|
/** Identity merge: a re-fetched row REPLACES its predecessor in place, so a
|
|
452
458
|
* refresh cannot reorder the list under the user's finger or duplicate a row
|
|
@@ -604,6 +610,7 @@ export function createGroupedSearch(
|
|
|
604
610
|
* the wrong result set. */
|
|
605
611
|
async search(raw: unknown): Promise<void> {
|
|
606
612
|
if (disposed) return;
|
|
613
|
+
holding = 0;
|
|
607
614
|
const next = normalizeQuery(raw);
|
|
608
615
|
query = next;
|
|
609
616
|
for (const id of order) {
|
|
@@ -627,6 +634,7 @@ export function createGroupedSearch(
|
|
|
627
634
|
*/
|
|
628
635
|
async restore(raw: unknown, depth: Record<string, number> = {}): Promise<void> {
|
|
629
636
|
if (disposed) return;
|
|
637
|
+
holding = 0;
|
|
630
638
|
const next = normalizeQuery(raw);
|
|
631
639
|
query = next;
|
|
632
640
|
for (const id of order) {
|
|
@@ -637,8 +645,34 @@ export function createGroupedSearch(
|
|
|
637
645
|
if (!next) return;
|
|
638
646
|
await fanOut(order, depth);
|
|
639
647
|
},
|
|
648
|
+
/** A returning screen (a cached embed's warm worker): the same search re-run to the depth each group
|
|
649
|
+
* shows, behind the rows it shows, and published once. Rows are a live claim about records, so they
|
|
650
|
+
* are re-fetched, never repainted; a search typed meanwhile takes over at once. */
|
|
651
|
+
async revalidate(): Promise<void> {
|
|
652
|
+
if (disposed || !query) return;
|
|
653
|
+
const depth: Record<string, number> = holding ? { ...heldDepth } : {};
|
|
654
|
+
for (const id of order) { const pages = groups.get(id)?.pages ?? 0; if (pages > Math.max(1, depth[id] ?? 0)) depth[id] = pages; }
|
|
655
|
+
heldDepth = depth;
|
|
656
|
+
const held = ++holds;
|
|
657
|
+
holding = held;
|
|
658
|
+
for (const id of order) {
|
|
659
|
+
groups.set(id, idleGroup(byId.get(id)!));
|
|
660
|
+
sourceGeneration.set(id, (sourceGeneration.get(id) ?? 0) + 1);
|
|
661
|
+
}
|
|
662
|
+
const run = (async () => {
|
|
663
|
+
try {
|
|
664
|
+
await fanOut(order, depth);
|
|
665
|
+
} finally {
|
|
666
|
+
if (holding === held) { holding = 0; heldDepth = {}; emit(); }
|
|
667
|
+
}
|
|
668
|
+
})();
|
|
669
|
+
revalidation = run;
|
|
670
|
+
await run;
|
|
671
|
+
},
|
|
640
672
|
/** One group's next page. */
|
|
641
673
|
async loadMore(id: unknown): Promise<void> {
|
|
674
|
+
// Tapped while a revalidation re-fetches behind the shown rows: page on from what it lands.
|
|
675
|
+
while (holding && revalidation) await revalidation;
|
|
642
676
|
const adapter = typeof id === "string" ? byId.get(id) : undefined;
|
|
643
677
|
if (!adapter || disposed || !query) return;
|
|
644
678
|
await runSource(adapter, true);
|
|
@@ -117,7 +117,8 @@ const svc = defineService<ServiceFormState, {
|
|
|
117
117
|
stashCopy(arg); // absorb the descriptor's onAppear copy-pack param
|
|
118
118
|
// WS-C — nav-param input is PRIMARY (the canonical form bakes no id); the
|
|
119
119
|
// onAppear `id` param is the #570 suffixed-build fallback.
|
|
120
|
-
|
|
120
|
+
// The held id is for the host's bare refresh only (no argument): an onAppear without an id is a create screen.
|
|
121
|
+
const id = navInputId() || idFrom(arg, arg === undefined ? s.id : "");
|
|
121
122
|
if (!id) return shape({ ...s, status: "error", error: copyParam("ownerServiceForm.errorNoService", "No service to edit.") });
|
|
122
123
|
if (isOwnerPreviewDemo()) {
|
|
123
124
|
const d = DEMO_SERVICES.find((x) => x.id === id);
|