@wix/himalaya-cli 0.1071.0 → 0.1073.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.
Files changed (49) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-config.d.ts +18 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/events/src/index.d.ts +21 -3
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-events.mjs +4 -2
  4. package/dist/cli.mjs +114 -42
  5. package/dist/preview-assets.generated.bin +0 -0
  6. package/guides/sdk-reference.json +17 -5
  7. package/package.json +2 -2
  8. package/templates/beauty-salon/dev/index.ts +1 -0
  9. package/templates/beauty-salon-owner/dev/index.ts +64 -0
  10. package/templates/beauty-salon-owner/tier5-src/_shared/owner-rich-guard.ts +64 -0
  11. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-product-form/index.ts +24 -5
  12. package/templates/community-club-owner/dev/index.ts +96 -0
  13. package/templates/community-club-owner/tier5-src/_shared/owner-rich-guard.ts +64 -0
  14. package/templates/community-club-owner/tier5-src/himi-owner-lite-event-form/index.ts +44 -10
  15. package/templates/community-club-owner/tier5-src/himi-owner-lite-product-form/index.ts +24 -5
  16. package/templates/events-meetups-owner/dev/index.ts +32 -0
  17. package/templates/events-meetups-owner/tier5-src/_shared/owner-rich-guard.ts +64 -0
  18. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-event-form/index.ts +44 -10
  19. package/templates/gym-fitness/dev/index.ts +1 -0
  20. package/templates/gym-fitness-owner/dev/index.ts +96 -0
  21. package/templates/gym-fitness-owner/tier5-src/_shared/owner-rich-guard.ts +64 -0
  22. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-event-form/index.ts +44 -10
  23. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-product-form/index.ts +24 -5
  24. package/templates/nonprofit-cause-owner/dev/index.ts +32 -0
  25. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-rich-guard.ts +64 -0
  26. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-event-form/index.ts +44 -10
  27. package/templates/owner-lite/dev/index.ts +192 -0
  28. package/templates/owner-lite/tier5-src/_shared/owner-rich-guard.ts +64 -0
  29. package/templates/owner-lite/tier5-src/himi-owner-lite-event-form/index.ts +44 -10
  30. package/templates/owner-lite/tier5-src/himi-owner-lite-faq-question-form/index.ts +18 -5
  31. package/templates/owner-lite/tier5-src/himi-owner-lite-product-form/index.ts +24 -5
  32. package/templates/podcast-creator-owner/dev/index.ts +96 -0
  33. package/templates/podcast-creator-owner/tier5-src/_shared/owner-rich-guard.ts +64 -0
  34. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-event-form/index.ts +44 -10
  35. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-product-form/index.ts +24 -5
  36. package/templates/portfolio-creative-owner/dev/index.ts +64 -0
  37. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-rich-guard.ts +64 -0
  38. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-product-form/index.ts +24 -5
  39. package/templates/restaurant/dev/index.ts +1 -0
  40. package/templates/restaurant-owner/dev/index.ts +96 -0
  41. package/templates/restaurant-owner/tier5-src/_shared/owner-rich-guard.ts +64 -0
  42. package/templates/restaurant-owner/tier5-src/himi-owner-lite-event-form/index.ts +44 -10
  43. package/templates/restaurant-owner/tier5-src/himi-owner-lite-product-form/index.ts +24 -5
  44. package/templates/retail-store-owner/dev/index.ts +64 -0
  45. package/templates/retail-store-owner/tier5-src/_shared/owner-rich-guard.ts +64 -0
  46. package/templates/retail-store-owner/tier5-src/himi-owner-lite-product-form/index.ts +24 -5
  47. package/templates/yoga-studio-owner/dev/index.ts +32 -0
  48. package/templates/yoga-studio-owner/tier5-src/_shared/owner-rich-guard.ts +64 -0
  49. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-event-form/index.ts +44 -10
@@ -8,7 +8,11 @@
8
8
 
9
9
  import { defineService } from "@himalaya/state";
10
10
  import { getEvent, updateEvent, type WixEvent } from "@himalaya/wix-events";
11
- import { normalizeEvent, eventDescription } from "../_shared/himi-events.js";
11
+ import { normalizeEvent } from "../_shared/himi-events.js";
12
+ import { postBodyText, plainPostBody } from "../_shared/owner-post-content.js";
13
+ // Not owner-post-content's hasRichBody: Events v3 sends default paragraphData on EVERY paragraph
14
+ // (which hasRichBody reads as formatting) and a documentStyle it never looks at.
15
+ import { ricosIsPlain } from "../_shared/owner-rich-guard.js";
12
16
  import { ownerLoadError, isBridgeUnavailable, isOwnerPreviewDemo, shouldQueueOwnerWrite } from "../_shared/owner-load-error.js";
13
17
  import { DEMO_EVENTS, DEMO_NOTE, DEMO_SAVE_NOTE, demoRefusalPatch } from "../_shared/owner-preview-demo.js";
14
18
  import { stashCopy, copyParam } from "../_shared/himi-copy.js";
@@ -35,7 +39,17 @@ interface EventFormState {
35
39
  id: string;
36
40
  heading: string;
37
41
  title: string;
42
+ /** [rico] #3363 — the Events v3 Ricos `description` as text (read with `fields=TEXTS`). While
43
+ * `descriptionProtected`, it is a read-only preview. */
38
44
  description: string;
45
+ /** The description as loaded (or last saved). A save writes `description` only when the
46
+ * submitted value differs from it, so an untouched body is never re-written. */
47
+ originalDescription: string;
48
+ /** A Ricos description with formatting or media the plain field would flatten: it loads locked,
49
+ * the descriptor shows a preview + `descriptionNote`, and an edit is refused. */
50
+ descriptionProtected: boolean;
51
+ descriptionEditable: boolean;
52
+ descriptionNote: string;
39
53
  when: string;
40
54
  location: string;
41
55
  status: "idle" | "loading" | "saving" | "saved" | "error";
@@ -94,6 +108,10 @@ function shape(s: Partial<EventFormState>): EventFormState {
94
108
  heading: s.heading ?? copyParam("ownerEventForm.headingEdit", "Edit event"),
95
109
  title: s.title ?? "",
96
110
  description: s.description ?? "",
111
+ originalDescription: s.originalDescription ?? s.description ?? "",
112
+ descriptionProtected: s.descriptionProtected ?? false,
113
+ descriptionEditable: !(s.descriptionProtected ?? false),
114
+ descriptionNote: s.descriptionProtected ? copyParam("ownerEventForm.richDescriptionNote", "This description has formatting or media. Edit it in your site dashboard to keep that content intact; the title can be changed here.") : "",
97
115
  when: s.when ?? "—",
98
116
  location: s.location ?? "—",
99
117
  status: s.status ?? "idle",
@@ -145,7 +163,8 @@ const svc = defineService<EventFormState, {
145
163
  return shape({ ...s, status: "error", error: "Sample item not found." });
146
164
  }
147
165
  try {
148
- const res = await getEvent(id);
166
+ // `TEXTS` is the v3 fieldset that returns the Ricos `description`; a bare GET omits it.
167
+ const res = await getEvent(id, { fields: ["TEXTS"] });
149
168
  const ev = (res.event ?? res) as WixEvent;
150
169
  if (!ev || !(ev as any).id) {
151
170
  return shape({ ...s, mode, id, status: "error", error: copyParam("ownerEventForm.errorNotFound", "Event not found") });
@@ -157,7 +176,14 @@ const svc = defineService<EventFormState, {
157
176
  id,
158
177
  heading: copyParam("ownerEventForm.headingEdit", "Edit event"),
159
178
  title: ev.title ?? "",
160
- description: (eventDescription(ev) || "").trim(),
179
+ // The v3 Ricos `description` only: `shortDescription` and `about` are separate fields
180
+ // this form never writes, so showing them here would invite an edit that lands elsewhere.
181
+ ...(() => {
182
+ const raw = (ev as unknown as { description?: unknown }).description;
183
+ const doc = raw && typeof raw === "object" && Array.isArray((raw as { nodes?: unknown }).nodes) ? raw as Parameters<typeof postBodyText>[0] : null;
184
+ const text = doc ? postBodyText(doc) : typeof raw === "string" ? raw.trim() : "";
185
+ return { description: text, originalDescription: text, descriptionProtected: doc ? !ricosIsPlain(doc as { nodes?: unknown; documentStyle?: unknown }) : false };
186
+ })(),
161
187
  when: row.dateLine || "—",
162
188
  location: row.location || "—",
163
189
  status: "idle",
@@ -172,6 +198,8 @@ const svc = defineService<EventFormState, {
172
198
  ...s, mode, id, heading: "Edit event",
173
199
  title: String(cached.title ?? cached.name ?? ""),
174
200
  description: String(cached.description ?? ""),
201
+ // An older cached row carries no verdict, so it stays locked: fail closed.
202
+ originalDescription: String(cached.description ?? ""), descriptionProtected: cached.descriptionProtected !== "false",
175
203
  when: String(cached.when ?? cached.dateLine ?? "—"),
176
204
  location: String(cached.location ?? "—"),
177
205
  status: "idle", error: "", savedMessage: "",
@@ -195,18 +223,23 @@ const svc = defineService<EventFormState, {
195
223
  const v = values ?? {};
196
224
  const title = String(v.title ?? s.title).trim();
197
225
  const description = String(v.description ?? s.description).trim();
226
+ // A queue replay boots a FRESH worker (empty baseline), so it carries the original verdict.
227
+ const descriptionEdited = typeof v.descriptionEdited === "string" ? v.descriptionEdited === "true" : description !== s.originalDescription.trim();
228
+ if (descriptionEdited && s.descriptionProtected) return shape({ ...s, status: "error", savedMessage: "", error: copyParam("ownerEventForm.richDescriptionError", "This description has formatting or media. Edit it in your site dashboard to keep that content intact.") });
198
229
  if (!title) return shape({ ...s, status: "error", error: copyParam("ownerEventForm.titleRequired", "Title is required"), savedMessage: "" });
199
230
  if (!s.id) return shape({ ...s, status: "error", error: copyParam("ownerEventForm.errorNoEvent", "No event to edit."), savedMessage: "" });
200
231
 
201
232
  // updateEvent(id, event) wraps the body as { event } internally, so pass the
202
- // event fields directly. Only the text the form can safely edit is written.
203
- const event: any = {
204
- title,
205
- ...(description ? { description } : {}),
233
+ // event fields directly. Only the text the form can safely edit is written: the
234
+ // description only when edited, and always as a Ricos document (never a string).
235
+ // A local structural type, not WixEventWrite: templates compile against the
236
+ // PUBLISHED SDK until its next release.
237
+ const event: { title: string; description?: { nodes: unknown[] } } = {
238
+ title, ...(descriptionEdited ? { description: description ? plainPostBody(description) as { nodes: unknown[] } : { nodes: [] } } : {}),
206
239
  };
207
240
 
208
241
  // Optimistic local write — the detail/list repaint from cache immediately.
209
- const localRow: DbEntity = { id: s.id, name: title, title, description, when: s.when, location: s.location };
242
+ const localRow: DbEntity = { id: s.id, name: title, title, description, descriptionProtected: String(s.descriptionProtected), when: s.when, location: s.location };
210
243
  await cachePut(localRow);
211
244
  try {
212
245
  await updateEvent(s.id, event);
@@ -217,6 +250,7 @@ const svc = defineService<EventFormState, {
217
250
  heading: copyParam("ownerEventForm.headingEdit", "Edit event"),
218
251
  title,
219
252
  description,
253
+ originalDescription: descriptionEdited ? description : s.originalDescription,
220
254
  status: "saved",
221
255
  error: "",
222
256
  savedMessage: copyParam("ownerEventForm.savedMessage", "Event saved."),
@@ -230,10 +264,10 @@ const svc = defineService<EventFormState, {
230
264
  if (s.demoNote) return demoRefusal(s);
231
265
  // Real device offline: the optimistic cache row already shows; queue the
232
266
  // write to replay (WriteQueue, idempotent) when connectivity returns.
233
- await queueWrite("tier5.himiOwnerLiteEventForm.submit", { id: s.id, title, description });
267
+ await queueWrite("tier5.himiOwnerLiteEventForm.submit", { id: s.id, title, description, descriptionEdited: String(descriptionEdited) });
234
268
  return shape({
235
269
  ...s, mode: "edit", id: s.id, heading: copyParam("ownerEventForm.headingEdit", "Edit event"),
236
- title, description, status: "saved", error: "",
270
+ title, description, originalDescription: descriptionEdited ? description : s.originalDescription, status: "saved", error: "",
237
271
  savedMessage: copyParam("ownerEventForm.savedOffline", "Saved offline — will sync when you reconnect."),
238
272
  savedId: s.id,
239
273
  });