@wix/himalaya-cli 0.1075.0 → 0.1077.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 (41) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/builder.d.ts +2 -2
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +6 -4
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/automations-v1/src/index.d.ts +1 -1
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/billing-tax-v1/src/index.d.ts +1 -1
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/business-tools-v1/src/index.d.ts +27 -10
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/comments-v1/src/index.d.ts +243 -3
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/data-collections-v1/src/index.d.ts +151 -19
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/donations/src/index.d.ts +10 -17
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/email-marketing-v1/src/index.d.ts +136 -20
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/faq-v2/src/index.d.ts +39 -28
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/gift-cards/src/index.d.ts +28 -17
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/redirects-v1/src/index.d.ts +2 -7
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/seo-v1/src/index.d.ts +0 -6
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/workflows-v1/src/index.d.ts +5 -0
  15. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-business-tools.mjs +9 -0
  16. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-comments.mjs +53 -5
  17. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-data-collections.mjs +40 -0
  18. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-donations.mjs +9 -0
  19. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-email-marketing.mjs +90 -0
  20. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-faq.mjs +10 -0
  21. package/dist/cli.mjs +4320 -3210
  22. package/dist/preview-assets.generated.bin +0 -0
  23. package/guides/component-reference.json +7 -8
  24. package/guides/component-reference.md +9 -7
  25. package/guides/headless-loop.md +7 -5
  26. package/guides/himi-mcp.md +120 -0
  27. package/guides/index.json +6 -0
  28. package/guides/sdk-reference.json +744 -391
  29. package/guides/skill.md +4 -3
  30. package/package.json +5 -3
  31. package/templates/beauty-salon-owner/tier5-src/_shared/owner-module-data.ts +6 -2
  32. package/templates/community-club-owner/tier5-src/_shared/owner-module-data.ts +6 -2
  33. package/templates/events-meetups-owner/tier5-src/_shared/owner-module-data.ts +6 -2
  34. package/templates/gym-fitness-owner/tier5-src/_shared/owner-module-data.ts +6 -2
  35. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-module-data.ts +6 -2
  36. package/templates/owner-lite/tier5-src/_shared/owner-module-data.ts +6 -2
  37. package/templates/podcast-creator-owner/tier5-src/_shared/owner-module-data.ts +6 -2
  38. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-module-data.ts +6 -2
  39. package/templates/restaurant-owner/tier5-src/_shared/owner-module-data.ts +6 -2
  40. package/templates/retail-store-owner/tier5-src/_shared/owner-module-data.ts +6 -2
  41. package/templates/yoga-studio-owner/tier5-src/_shared/owner-module-data.ts +6 -2
package/guides/skill.md CHANGED
@@ -49,6 +49,7 @@ A build takes most of an hour. An owner who sees nothing for that long assumes n
49
49
  - **Journal every postcard** with `himi progress "<what changed>" --step <n> --image <png>` when the installed CLI lists `progress` (`himi --help`). It keeps a copy of each image exactly as it was when you sent it, and a bare `himi progress` prints the journal with the current step — the quickest way back to your place. The CLI also journals the first picture of the home screen, every `himi test` crawl and every draft push by itself; your postcards are the ones that say why.
50
50
  - **Give them a board to leave open.** When the installed CLI lists `studio`, run `himi studio` once, right after that first picture, and tell the owner it is there (a current `himi init` has already made the board; this opens it). It opens a local page in their browser that fills itself in — every screen as it renders, the journey step and your latest postcard, each check as it runs — so they can watch between your messages. It is a view of your local work, not the preview of step 7.
51
51
  - **Let them click around while you work.** Once step 4's startup preflight says the app may boot locally, and when the installed CLI's `himi run` accepts `--watch`, keep `himi run --watch` running in the background: it serves the app on this machine, opens it in their browser (no `--browser` flag — that is a different mode, and `--watch` refuses it), and repaints that tab every time you save — and the board frames the same live app. Once the app is bound to their site, the watch preview shows that site's live data, fetched by their own browser as an anonymous visitor. It is a local preview of your working copy, never the owner-private preview, and a save that does not build leaves the last good version on screen while you fix it.
52
+ - **Inside a coding agent, prefer the `himi_*` tools.** When your tool list has them (`himi init` configures the `himi` MCP server for Claude Code, Cursor, Codex and VS Code), call them instead of shelling out: `himi_render` hands you the PNG to show, and `himi_preview_start` returns the live preview's URL. Open that URL in your own built-in browser — Claude Code desktop: start the `himi-preview` launch configuration; Cursor: its Browser tool; Codex in the ChatGPT desktop app: its Browser; VS Code: the integrated browser — so the owner watches the app take shape beside the chat.
52
53
  - **Hand over the story too.** At the handover in step 7, when `himi --help` lists `himi studio reel` (an older CLI can have `studio` without it), run `himi studio reel` and offer the owner the file it writes: one self-contained page of their app taking shape, version by version, with your postcards. It shows how the app was built; it is never a substitute for the preview URL, and it carries the same sample-data captions the postcards did.
53
54
 
54
55
  ## Approval gates
@@ -113,9 +114,9 @@ If a gate is not implied (no credentials, no draft instruction, no site URL for
113
114
 
114
115
  **Keep the owner watching, headless too.** Whoever watches the board while you work, or reads the run afterwards, sees only what reached the journal. Do these in the session that builds the app — not at the end, and not in a later session — each one when `himi --help` lists the command:
115
116
 
116
- 1. **The board opens at init.** `himi init` creates the build board (`.himi/studio/index.html`) and its `next[]` starts with this session's first steps: run them now. When the installed `init` prints no `board`, run `himi studio --no-open` once in the app folder.
117
- 2. **Keep the live preview running.** Once journey step 4's startup preflight clears the app to boot locally, start `himi run --watch &` in the app folder and leave it up until the handover: it repaints on every save and serves the board at `<url>/__himi/studio/`.
118
- 3. **Make the first picture right after init:** `himi render <homeScreenId> --png --device iphone`. The CLI journals that first look itself.
117
+ 1. **The board opens at init.** `himi init` creates the build board (`.himi/studio/index.html`) and its `next[]` starts with this session's first steps: run them now, in order: the first picture and its postcard, the consent preflight, then the live preview — for every template. The preflight costs nothing on an app that makes no startup request: if no worker or config can make a Wix or external request at boot, go straight on. When the installed `init` prints no `board`, run `himi studio --no-open` once in the app folder.
118
+ 2. **Make the first picture right after init:** `himi render <homeScreenId> --png --device iphone`. It is offline — it never calls Wix — so it needs no preflight. The CLI journals that first look itself.
119
+ 3. **Then keep the live preview running.** Only once the consent preflight (journey step 4) clears the app to boot locally, start `himi run --watch &` in the app folder and leave it up until the handover: it repaints on every save and serves the board at `<url>/__himi/studio/`.
119
120
  4. **A postcard with a picture at every journey step:** `himi progress "<what changed>" --step <n> --image .himi/shots/<screenId>.png`. `himi test` and `himi push --draft` journal their own results too; your postcards say what changed and why it matters.
120
121
  5. **At the handover, the making-of:** run `himi studio reel` and name the file it writes in your final report.
121
122
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1075.0",
3
+ "version": "0.1077.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": [
@@ -34,6 +34,7 @@
34
34
  "test": "node ../../tools/ci/run-tests.mjs --package tools/himi-cli"
35
35
  },
36
36
  "dependencies": {
37
+ "@modelcontextprotocol/server": "^2.0.0",
37
38
  "@rive-app/canvas": "^2.21.0",
38
39
  "ajv": "^8.17.1",
39
40
  "ajv-formats": "^3.0.1",
@@ -45,7 +46,8 @@
45
46
  "react-dom": "^18.2.0",
46
47
  "tough-cookie": "^6.0.1",
47
48
  "typescript": "^5.6.3",
48
- "wawoff2": "^2.0.1"
49
+ "wawoff2": "^2.0.1",
50
+ "zod": "^4.2.0"
49
51
  },
50
52
  "optionalDependencies": {
51
53
  "playwright": "^1.40.0",
@@ -65,5 +67,5 @@
65
67
  "artifactId": "himalaya-cli"
66
68
  }
67
69
  },
68
- "falconPackageHash": "ad0a3581ccf724b635a440ebda4b0d2c9baa1fd6aa192133590cc47b"
70
+ "falconPackageHash": "f05f26ed8fab307cde555efea47651788f996fd6d20bb908d209e946"
69
71
  }
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];
@@ -193,11 +193,15 @@ export function ownerRecord(module: OwnerModuleId, raw: unknown): OwnerRecord {
193
193
  image = field(raw, 'description.image.url') || field(raw, 'coverImage'); statusLabel = words(field(raw, 'status') || field(raw, 'state'));
194
194
  details = [['Participants', field(raw, 'participantsCount') || field(raw, 'participants.count')], ['Steps', field(raw, 'contentSummary.stepCount')]];
195
195
  break;
196
- case 'badges':
196
+ case 'badges': {
197
197
  title = field(raw, 'title'); subtitle = field(raw, 'description');
198
- statusLabel = typeof at(raw, 'permissionsEnabled') === 'boolean' ? at(raw, 'permissionsEnabled') ? 'Access enabled' : 'Recognition only' : '';
198
+ // The V4 badges API (/badges/v4/badges) names the flag `permissionsEnabled`. The newer
199
+ // /v2/badges service calls it `hasPermissions`; read it only as a fallback.
200
+ const permissionsEnabled = at(raw, 'permissionsEnabled') ?? at(raw, 'hasPermissions');
201
+ statusLabel = typeof permissionsEnabled === 'boolean' ? permissionsEnabled ? 'Access enabled' : 'Recognition only' : '';
199
202
  details = [['Slug', field(raw, 'slug')], ['Background color', field(raw, 'backgroundColor')], ['Text color', field(raw, 'textColor')]];
200
203
  break;
204
+ }
201
205
  case 'reservations':
202
206
  title = name(raw, 'reservee.firstName', 'reservee.lastName'); subtitle = field(raw, 'details.startDate'); statusLabel = words(field(raw, 'status'));
203
207
  details = [['Arrival', subtitle], ['Party size', field(raw, 'details.partySize')], ['Email', field(raw, 'reservee.email')], ['Phone', field(raw, 'reservee.phone')]];