@wix/himalaya-cli 0.1574.0 → 0.1576.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-config.d.ts +16 -5
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +6 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/telemetry/wix-bi/src/index.d.ts +15 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/telemetry/wix-bi/src/oneapp.d.ts +90 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-bi.mjs +165 -5
- package/dist/cli.mjs +3489 -2601
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/designing-himi-screens.md +7 -1
- package/guides/hhp.md +2 -2
- package/guides/himi-json-output.md +20 -0
- package/guides/push-cli-onboarding.md +10 -0
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +74 -127
- package/templates/beauty-salon/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/beauty-salon/tier5-src/himi-branded-lite-cart/index.ts +18 -5
- package/templates/beauty-salon-owner/dev/index.ts +5 -0
- package/templates/beauty-salon-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/branded-lite/dev/index.ts +114 -136
- package/templates/branded-lite/l10n/en.json +570 -0
- package/templates/branded-lite/l10n/he.json +200 -0
- package/templates/branded-lite/tier5-src/_shared/business-chat-copy.ts +40 -0
- package/templates/branded-lite/tier5-src/_shared/business-chat-message-model.ts +1 -1
- package/templates/branded-lite/tier5-src/_shared/business-chat-model.ts +3 -2
- package/templates/branded-lite/tier5-src/_shared/business-chat-presenter.ts +26 -21
- package/templates/branded-lite/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/branded-lite/tier5-src/business-chat/index.ts +184 -63
- package/templates/branded-lite/tier5-src/himi-branded-lite-cart/index.ts +18 -5
- package/templates/community-club-owner/dev/index.ts +5 -0
- package/templates/community-club-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/community-club-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/community-club-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/community-club-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/events-meetups-owner/dev/index.ts +3 -0
- package/templates/events-meetups-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/gym-fitness/dev/index.ts +74 -127
- package/templates/gym-fitness/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/gym-fitness/tier5-src/himi-branded-lite-cart/index.ts +18 -5
- package/templates/gym-fitness-owner/dev/index.ts +6 -0
- package/templates/gym-fitness-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/nonprofit-cause-owner/dev/index.ts +4 -0
- package/templates/nonprofit-cause-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/owner-lite/dev/index.ts +6 -0
- package/templates/owner-lite/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/owner-lite/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/owner-lite/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/podcast-creator-owner/dev/index.ts +5 -0
- package/templates/podcast-creator-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/portfolio-creative/dev/index.ts +74 -127
- package/templates/portfolio-creative/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-cart/index.ts +18 -5
- package/templates/portfolio-creative-owner/dev/index.ts +5 -0
- package/templates/portfolio-creative-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/restaurant-owner/dev/index.ts +6 -0
- package/templates/restaurant-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
- package/templates/retail-store/dev/index.ts +74 -127
- package/templates/retail-store/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/retail-store/tier5-src/himi-branded-lite-cart/index.ts +18 -5
- package/templates/retail-store-owner/dev/index.ts +4 -0
- package/templates/retail-store-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/retail-store-owner/tier5-src/himi-owner-lite-product-form/index.ts +5 -1
- package/templates/yoga-studio-owner/dev/index.ts +4 -0
- package/templates/yoga-studio-owner/tier5-src/_shared/exclusive-writes.ts +66 -0
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-event-form/index.ts +5 -1
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-post-form/index.ts +5 -1
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-service-form/index.ts +5 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { defineService as register, type ServiceDefinition } from '@himalaya/state';
|
|
2
|
+
|
|
3
|
+
/** Reject repeated taps until the accepted write's result is committed. A promise
|
|
4
|
+
* queue alone releases before the host applies the reducer result, so the next
|
|
5
|
+
* write can still read an old revision/id. The private synchronous reducer below
|
|
6
|
+
* publishes busy and commits completion through the ordinary service handle;
|
|
7
|
+
* awaiting that handle guarantees the host has stored the result before unlock.
|
|
8
|
+
* Skipped actions return undefined, so they cannot roll back the accepted write.
|
|
9
|
+
*/
|
|
10
|
+
export function withExclusiveWrites<S extends object = Record<string, unknown>>(
|
|
11
|
+
registerService: typeof register, names: readonly string[],
|
|
12
|
+
options: { prepare?: (action: string, args: readonly unknown[]) => void; coalesce?: readonly string[]; settle?: (before: S, next: S, live: S) => S } = {},
|
|
13
|
+
): typeof register {
|
|
14
|
+
return ((name: string, definition: ServiceDefinition<Record<string, unknown>>) => {
|
|
15
|
+
let busy = false;
|
|
16
|
+
let activeAction = "";
|
|
17
|
+
let completion = Promise.resolve();
|
|
18
|
+
let complete = () => {};
|
|
19
|
+
let handle: { getState(): Record<string, unknown>; exclusiveWriteState(next: Record<string, unknown>): Promise<unknown> };
|
|
20
|
+
const wrapped: ServiceDefinition<Record<string, unknown>> = {
|
|
21
|
+
...definition,
|
|
22
|
+
state: { ...definition.state, writeBusy: false },
|
|
23
|
+
notHydrated: [...(definition.notHydrated ?? []), 'writeBusy'],
|
|
24
|
+
actions: {
|
|
25
|
+
...Object.fromEntries(Object.entries(definition.actions ?? {}).map(([action, reduce]) => [action,
|
|
26
|
+
names.includes(action) ? async (state: Record<string, unknown>, ...args: never[]) => {
|
|
27
|
+
// Intake request metadata even when its state replacement is skipped.
|
|
28
|
+
options.prepare?.(action, args);
|
|
29
|
+
if (busy) {
|
|
30
|
+
// Repeated initial loads must await the accepted load, so callers
|
|
31
|
+
// observe its committed rows rather than the initial skeleton.
|
|
32
|
+
if (activeAction === action && options.coalesce?.includes(action)) await completion;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
busy = true;
|
|
36
|
+
activeAction = action;
|
|
37
|
+
completion = new Promise<void>(resolve => { complete = resolve; });
|
|
38
|
+
try {
|
|
39
|
+
await handle.exclusiveWriteState({ ...handle.getState(), writeBusy: true });
|
|
40
|
+
const next = await reduce(state, ...args);
|
|
41
|
+
const live = handle.getState();
|
|
42
|
+
// Non-write actions (for example editing a draft field) can still run
|
|
43
|
+
// during I/O. Let the owning service preserve those newer edits.
|
|
44
|
+
const settled = options.settle ? options.settle(state as S, (next ?? live) as S, live as S) : next ?? live;
|
|
45
|
+
await handle.exclusiveWriteState({ ...settled, writeBusy: false });
|
|
46
|
+
} catch (error) {
|
|
47
|
+
await handle.exclusiveWriteState({ ...handle.getState(), writeBusy: false });
|
|
48
|
+
throw error;
|
|
49
|
+
} finally {
|
|
50
|
+
busy = false;
|
|
51
|
+
complete();
|
|
52
|
+
}
|
|
53
|
+
} : reduce,
|
|
54
|
+
])),
|
|
55
|
+
exclusiveWriteState: (_state, next: Record<string, unknown>) => next,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
const registered = registerService(name, wrapped);
|
|
59
|
+
// Registration preserves this private action, but the dynamic action map
|
|
60
|
+
// cannot express its payload to the generic service handle.
|
|
61
|
+
handle = registered as unknown as typeof handle;
|
|
62
|
+
// Older hosts ignore notHydrated. A fresh worker has no pending write.
|
|
63
|
+
handle.getState().writeBusy = false;
|
|
64
|
+
return registered;
|
|
65
|
+
}) as typeof register;
|
|
66
|
+
}
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
// form can't safely collect — so this form only edits an existing event's text
|
|
7
7
|
// (title + description). Bound by buildForm ($service:himiOwnerLiteEventForm.*).
|
|
8
8
|
|
|
9
|
-
import { defineService } from "@himalaya/state";
|
|
9
|
+
import { defineService as registerService } from "@himalaya/state";
|
|
10
|
+
import { withExclusiveWrites } from "../_shared/exclusive-writes.js";
|
|
11
|
+
const defineService = withExclusiveWrites(registerService, ["submit"]);
|
|
10
12
|
import { getEvent, updateEvent, type WixEvent } from "@himalaya/wix-events";
|
|
11
13
|
import { normalizeEvent } from "../_shared/himi-events.js";
|
|
12
14
|
import { postBodyText, plainPostBody } from "../_shared/owner-post-content.js";
|
|
@@ -66,6 +68,7 @@ interface EventFormState {
|
|
|
66
68
|
when: string;
|
|
67
69
|
location: string;
|
|
68
70
|
status: "idle" | "loading" | "saving" | "saved" | "error";
|
|
71
|
+
writeBusy: boolean;
|
|
69
72
|
error: string;
|
|
70
73
|
savedMessage: string;
|
|
71
74
|
/** WS-C — canonical detail target (`himi_owner_lite_event`); `savedId` rides
|
|
@@ -140,6 +143,7 @@ function shape(s: Partial<EventFormState>): EventFormState {
|
|
|
140
143
|
when: s.when ?? "—",
|
|
141
144
|
location: s.location ?? "—",
|
|
142
145
|
status: s.status ?? "idle",
|
|
146
|
+
writeBusy: s.writeBusy ?? false,
|
|
143
147
|
error: s.error ?? "",
|
|
144
148
|
savedMessage: s.savedMessage ?? "",
|
|
145
149
|
// WS-C — canonical detail target + the saved entity's id as a separate nav
|
|
@@ -8,7 +8,9 @@ import { editorSubmitValue, queuedDocument, editorChanged, editorRunKeys, resetH
|
|
|
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";
|
|
11
|
-
import { defineService } from "@himalaya/state";
|
|
11
|
+
import { defineService as registerService } from "@himalaya/state";
|
|
12
|
+
import { withExclusiveWrites } from "../_shared/exclusive-writes.js";
|
|
13
|
+
const defineService = withExclusiveWrites(registerService, ["submit"]);
|
|
12
14
|
import { getDraftPost, createDraftPost, updateDraftPost, type WixDraftPostWrite, type WixRichContent } from "@himalaya/wix-blog";
|
|
13
15
|
import { ownerLoadError, isOwnerPreviewDemo, ownerDemoFallback, ownerWriteError } from "../_shared/owner-load-error.js";
|
|
14
16
|
import { DEMO_POSTS, DEMO_NOTE, DEMO_SAVE_NOTE, demoRefusalPatch } from "../_shared/owner-preview-demo.js";
|
|
@@ -53,6 +55,7 @@ interface PostFormState {
|
|
|
53
55
|
noCover: boolean;
|
|
54
56
|
isFeatured: string;
|
|
55
57
|
status: "idle" | "loading" | "saving" | "saved" | "error";
|
|
58
|
+
writeBusy: boolean;
|
|
56
59
|
error: string;
|
|
57
60
|
savedMessage: string;
|
|
58
61
|
/** WS-C — canonical detail target (`himi_owner_lite_post`); `savedId` rides
|
|
@@ -128,6 +131,7 @@ function shape(s: Partial<PostFormState>): PostFormState {
|
|
|
128
131
|
noCover: !s.coverUrl,
|
|
129
132
|
isFeatured: s.isFeatured ?? "false",
|
|
130
133
|
status: s.status ?? "idle",
|
|
134
|
+
writeBusy: s.writeBusy ?? false,
|
|
131
135
|
error: s.error ?? "",
|
|
132
136
|
savedMessage: s.savedMessage ?? "",
|
|
133
137
|
// WS-C — canonical detail target + the saved entity's id as a separate nav
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
// updateService. Bound by buildForm ($service:himiOwnerLiteServiceForm.*).
|
|
6
6
|
|
|
7
7
|
import { landsOnLive } from "../_shared/owner-editor-value.js";
|
|
8
|
-
import { defineService } from "@himalaya/state";
|
|
8
|
+
import { defineService as registerService } from "@himalaya/state";
|
|
9
|
+
import { withExclusiveWrites } from "../_shared/exclusive-writes.js";
|
|
10
|
+
const defineService = withExclusiveWrites(registerService, ["submit"]);
|
|
9
11
|
import { getService, updateService, type WixService } from "@himalaya/wix-bookings";
|
|
10
12
|
import { ownerLoadError, isOwnerPreviewDemo, ownerDemoFallback, ownerWriteError } from "../_shared/owner-load-error.js";
|
|
11
13
|
import { DEMO_SERVICES, DEMO_NOTE, DEMO_SAVE_NOTE, demoRefusalPatch } from "../_shared/owner-preview-demo.js";
|
|
@@ -31,6 +33,7 @@ interface ServiceFormState {
|
|
|
31
33
|
description: string;
|
|
32
34
|
category: string;
|
|
33
35
|
status: "idle" | "loading" | "saving" | "saved" | "error";
|
|
36
|
+
writeBusy: boolean;
|
|
34
37
|
error: string;
|
|
35
38
|
savedMessage: string;
|
|
36
39
|
/** WS-C — canonical detail target (`himi_owner_lite_service`); `savedId` rides
|
|
@@ -88,6 +91,7 @@ function shape(s: Partial<ServiceFormState>): ServiceFormState {
|
|
|
88
91
|
description: s.description ?? "",
|
|
89
92
|
category: s.category ?? "",
|
|
90
93
|
status: s.status ?? "idle",
|
|
94
|
+
writeBusy: s.writeBusy ?? false,
|
|
91
95
|
error: s.error ?? "",
|
|
92
96
|
savedMessage: s.savedMessage ?? "",
|
|
93
97
|
// WS-C — canonical detail target + the saved entity's id as a separate nav
|