@wix/himalaya-cli 0.1577.0 → 0.1579.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 (63) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/calendar/src/index.d.ts +42 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/clipboard/src/index.d.ts +32 -1
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/haptic/src/index.d.ts +69 -5
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/sdk-types/src/capabilities.generated.d.ts +3 -3
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/ui/src/index.d.ts +19 -2
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +6 -0
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/audio-record.mjs +3 -3
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calendar.mjs +48 -3
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calls.mjs +3 -3
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/clipboard.mjs +58 -1
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/contacts.mjs +3 -3
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/haptic.mjs +73 -4
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/location.mjs +3 -3
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/motion.mjs +3 -3
  15. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/photos.mjs +3 -3
  16. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdk-types.mjs +3 -3
  17. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/tasks.mjs +3 -3
  18. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/ui.mjs +5 -0
  19. package/dist/cli.mjs +1061 -917
  20. package/dist/preview-assets.generated.bin +0 -0
  21. package/guides/one-app-section-mappings.md +26 -0
  22. package/guides/qa-builds.md +14 -6
  23. package/guides/sdk-reference.json +159 -9
  24. package/guides/web-page-sdk-reference.md +3 -3
  25. package/package.json +2 -2
  26. package/templates/beauty-salon/dev/index.ts +14 -0
  27. package/templates/beauty-salon/tier5-src/_shared/himi-bookings.ts +21 -0
  28. package/templates/beauty-salon/tier5-src/_shared/himi-copy.ts +8 -3
  29. package/templates/beauty-salon/tier5-src/himi-booking-services/index.ts +36 -12
  30. package/templates/beauty-salon-owner/tier5-src/_shared/himi-copy.ts +8 -3
  31. package/templates/branded-lite/dev/index.ts +14 -0
  32. package/templates/branded-lite/tier5-src/_shared/himi-bookings.ts +21 -0
  33. package/templates/branded-lite/tier5-src/_shared/himi-copy.ts +8 -3
  34. package/templates/branded-lite/tier5-src/himi-booking-services/index.ts +36 -12
  35. package/templates/branded-lite/tier5-src/himi-branded-lite-programs/index.ts +40 -2
  36. package/templates/brandy/tier5-src/_shared/himi-copy.ts +8 -3
  37. package/templates/community-club/tier5-src/_shared/himi-copy.ts +8 -3
  38. package/templates/community-club-owner/tier5-src/_shared/himi-copy.ts +8 -3
  39. package/templates/events-meetups/tier5-src/_shared/himi-copy.ts +8 -3
  40. package/templates/events-meetups-owner/tier5-src/_shared/himi-copy.ts +8 -3
  41. package/templates/gym-fitness/dev/index.ts +14 -0
  42. package/templates/gym-fitness/tier5-src/_shared/himi-bookings.ts +21 -0
  43. package/templates/gym-fitness/tier5-src/_shared/himi-copy.ts +8 -3
  44. package/templates/gym-fitness/tier5-src/himi-booking-services/index.ts +36 -12
  45. package/templates/gym-fitness-owner/tier5-src/_shared/himi-copy.ts +8 -3
  46. package/templates/himi-chat/tier5-src/_shared/himi-copy.ts +8 -3
  47. package/templates/nonprofit-cause/tier5-src/_shared/himi-copy.ts +8 -3
  48. package/templates/nonprofit-cause-owner/tier5-src/_shared/himi-copy.ts +8 -3
  49. package/templates/owner-lite/tier5-src/_shared/himi-copy.ts +8 -3
  50. package/templates/podcast-creator/tier5-src/_shared/himi-copy.ts +8 -3
  51. package/templates/podcast-creator-owner/tier5-src/_shared/himi-copy.ts +8 -3
  52. package/templates/portfolio-creative/tier5-src/_shared/himi-copy.ts +8 -3
  53. package/templates/portfolio-creative-owner/tier5-src/_shared/himi-copy.ts +8 -3
  54. package/templates/restaurant/tier5-src/_shared/himi-copy.ts +8 -3
  55. package/templates/restaurant-owner/tier5-src/_shared/himi-copy.ts +8 -3
  56. package/templates/retail-store/tier5-src/_shared/himi-copy.ts +8 -3
  57. package/templates/retail-store-owner/tier5-src/_shared/himi-copy.ts +8 -3
  58. package/templates/yoga-studio/dev/index.ts +14 -0
  59. package/templates/yoga-studio/tier5-src/_shared/himi-bookings.ts +21 -0
  60. package/templates/yoga-studio/tier5-src/_shared/himi-copy.ts +8 -3
  61. package/templates/yoga-studio/tier5-src/himi-booking-services/index.ts +36 -12
  62. package/templates/yoga-studio/tier5-src/himi-branded-lite-programs/index.ts +40 -2
  63. package/templates/yoga-studio-owner/tier5-src/_shared/himi-copy.ts +8 -3
@@ -23,6 +23,8 @@ export declare function getPermissionStatus(): Promise<PermissionStatus>;
23
23
  export declare function requestPermission(access?: CalendarAccess): Promise<PermissionStatus>;
24
24
  /** Events overlapping [start, end) (epoch ms). Requires full access. */
25
25
  export declare function listEvents(start: number, end: number): Promise<CalendarEvent[]>;
26
+ /** Create an event directly. Needs calendar access — to let the user add an event with
27
+ * NO permission prompt, use {@link presentEditor} (the system editor) instead. */
26
28
  export declare function createEvent(event: NewCalendarEvent): Promise<{
27
29
  id: string | null;
28
30
  }>;
@@ -32,4 +34,44 @@ export declare function updateEvent(id: string, patch: Partial<NewCalendarEvent>
32
34
  export declare function deleteEvent(id: string): Promise<{
33
35
  deleted: boolean;
34
36
  }>;
37
+ /** A calendar the user has, from {@link listCalendars}. `color` is `#RRGGBB` ("" if unknown). */
38
+ export interface CalendarInfo {
39
+ id: string;
40
+ title: string;
41
+ color: string;
42
+ allowsModifications: boolean;
43
+ isPrimary: boolean;
44
+ }
45
+ /** What {@link presentEditor} resolved with. `saved` is false on cancel. `id` is the new
46
+ * event's id when the platform can report it — always `null` on Android (ACTION_INSERT
47
+ * returns no id) and on web, and `null` on iOS without full access. On web, `downloaded`
48
+ * is true when an .ics file was handed to the browser (the user imports it themselves,
49
+ * so `saved` stays false). */
50
+ export interface CalendarEditorResult {
51
+ saved: boolean;
52
+ id: string | null;
53
+ downloaded?: boolean;
54
+ }
55
+ /** How the system viewer was closed. Android reports `done` always (ACTION_VIEW has no result). */
56
+ export type CalendarViewerAction = "done" | "responded" | "deleted";
57
+ /**
58
+ * Open the system event editor prefilled with `event`; the user saves or cancels. Needs
59
+ * NO calendar permission (the OS editor writes the event, not the app). Resolves
60
+ * `{ saved: false, id: null }` on cancel. Web downloads an .ics instead; macOS rejects
61
+ * `unavailable` (no system editor there).
62
+ */
63
+ export declare function presentEditor(event?: Partial<NewCalendarEvent>): Promise<CalendarEditorResult>;
64
+ /**
65
+ * Show an existing event in the system viewer (iOS EKEventViewController, Android
66
+ * ACTION_VIEW). Needs full calendar access — rejects `permission_denied` without it, and
67
+ * `not_found` when the id does not resolve. Web and macOS reject `unavailable`.
68
+ */
69
+ export declare function presentViewer(id: string): Promise<{
70
+ action: CalendarViewerAction;
71
+ }>;
72
+ /** The user's calendars. Needs full access — rejects `permission_denied` without it. */
73
+ export declare function listCalendars(): Promise<CalendarInfo[]>;
74
+ /** One event by id, or `null` when it does not resolve. Needs full access — rejects
75
+ * `permission_denied` without it. */
76
+ export declare function getEvent(id: string): Promise<CalendarEvent | null>;
35
77
  export declare const version = 1;
@@ -1,3 +1,5 @@
1
+ import type { FileHandle } from "@wix/himalaya/sdk-types";
2
+ export type { FileHandle } from "@wix/himalaya/sdk-types";
1
3
  /** Copy `text` to the clipboard. */
2
4
  export declare function writeText(text: string): Promise<void>;
3
5
  /** Read the clipboard's text, or null if empty / the read was blocked (no focus,
@@ -7,5 +9,34 @@ export declare function readText(): Promise<string | null>;
7
9
  * web this can't be known without reading, so it returns true pessimistically;
8
10
  * treat it as a hint, not a guarantee. */
9
11
  export declare function hasText(): Promise<boolean>;
12
+ /** Largest image writeImage accepts (20 MB). Hosts enforce it too. */
13
+ export declare const MAX_IMAGE_BYTES: number;
14
+ /** Image MIME types writeImage copies. HEIC is iOS/macOS only (Android and web
15
+ * reject it `unsupported_type`); web accepts PNG only. The host sniffs the file's
16
+ * bytes, so a handle is judged by its content, not its `mimeType` — the binding only
17
+ * refuses up front a handle whose type is plainly not an image (e.g. application/pdf). */
18
+ export declare const IMAGE_MIME_TYPES: readonly string[];
19
+ /** Why writeImage rejected. */
20
+ export type ClipboardImageErrorCode = "unsupported_type" | "too_large" | "not_allowed" | "not_found" | "unavailable";
21
+ /** A writeImage rejection: an `Error` named "ClipboardImageError" carrying a stable
22
+ * `code`. (A plain Error, not a subclass — Tier-5 bundles target an engine without
23
+ * class syntax.) Branch on `isClipboardImageError(e) && e.code === "too_large"`. */
24
+ export interface ClipboardImageError extends Error {
25
+ name: "ClipboardImageError";
26
+ code: ClipboardImageErrorCode;
27
+ }
28
+ /** Build a coded writeImage rejection. */
29
+ export declare function clipboardImageError(code: ClipboardImageErrorCode, message?: string): ClipboardImageError;
30
+ /** Whether `e` is a coded writeImage rejection. */
31
+ export declare function isClipboardImageError(e: unknown): e is ClipboardImageError;
32
+ /** Copy an image file the worker already holds to the clipboard. Accepts a
33
+ * `FileHandle` (from files / camera / photos) or its substrate `uri`. Rejects with a
34
+ * `ClipboardImageError` (see `isClipboardImageError`) whose `code` is `unsupported_type` (not PNG/JPEG/WebP/HEIC, or
35
+ * not supported on this host), `too_large` (over 20 MB), `not_allowed` (outside the
36
+ * app's files substrate), `not_found`, or `unavailable` (no image clipboard here). */
37
+ export declare function writeImage(file: FileHandle | string): Promise<void>;
38
+ /** Whether the clipboard currently holds an image — without reading it (no iOS paste
39
+ * banner). Web cannot know without a permission-gated read, so it answers false. */
40
+ export declare function hasImage(): Promise<boolean>;
10
41
  /** Capability version, for bundles that gate on min binary version. */
11
- export declare const version = 1;
42
+ export declare const version = 2;
@@ -1,9 +1,73 @@
1
- /** Maps to a native impact/notification/selection generator. */
2
- export type HapticPattern = "selection" | "light" | "medium" | "heavy" | "success" | "warning" | "error";
1
+ /**
2
+ * Maps to a native impact/notification/selection generator.
3
+ *
4
+ * - `rigid` / `soft` — iOS `UIImpactFeedbackGenerator.FeedbackStyle.rigid` / `.soft`.
5
+ * Android: `rigid` is a short full-amplitude click (`VibrationEffect.EFFECT_CLICK`-like),
6
+ * `soft` a longer low-amplitude tick (`PRIMITIVE_LOW_TICK`-like); on a device without
7
+ * amplitude control both are plain one-shots of different length.
8
+ */
9
+ export type HapticPattern = "selection" | "light" | "medium" | "heavy" | "rigid" | "soft" | "success" | "warning" | "error";
10
+ export interface PlayOptions {
11
+ /**
12
+ * 0..1, clamped. Scales the strength of an IMPACT style (`light`, `medium`, `heavy`,
13
+ * `rigid`, `soft`): iOS `impactOccurred(intensity:)`, Android amplitude where the
14
+ * vibrator has amplitude control. Ignored for `selection` and the notification styles
15
+ * (`success`, `warning`, `error`) — those have a fixed system strength — and on web.
16
+ */
17
+ intensity?: number;
18
+ }
19
+ export interface HapticStep {
20
+ pattern: HapticPattern;
21
+ /** Milliseconds to wait BEFORE this step plays (≥ 0). */
22
+ delayMs: number;
23
+ /** Same meaning as {@link PlayOptions.intensity}. */
24
+ intensity?: number;
25
+ }
26
+ /**
27
+ * What a verb reports. `ok: false` is honest: `unavailable` (this surface has no haptic
28
+ * hardware/API — web without `navigator.vibrate`, macOS) or `unsupported_binary` (the
29
+ * native app predates the verb; nothing played, nothing broke).
30
+ */
31
+ export type HapticResult = {
32
+ ok: true;
33
+ } | {
34
+ ok: false;
35
+ reason: "unavailable" | "unsupported_binary";
36
+ };
37
+ /** Most steps one {@link sequence} may carry. */
38
+ export declare const MAX_SEQUENCE_STEPS = 32;
39
+ /** Longest a {@link sequence} or {@link vibrate} pattern may run, in milliseconds. */
40
+ export declare const MAX_DURATION_MS = 10000;
41
+ /** Clamp an intensity into 0..1; `undefined` / non-finite → `undefined` (system default). */
42
+ export declare function clampIntensity(intensity: number | undefined): number | undefined;
3
43
  /**
4
44
  * Play a haptic feedback pattern. Fire-and-forget; resolves once handed to the
5
- * platform. A no-op on web and for unknown patterns.
45
+ * platform. Unknown pattern names keep their historical behaviour (the platform's
46
+ * default tap). `intensity` applies to impact styles only — see {@link PlayOptions}.
47
+ */
48
+ export declare function play(pattern?: HapticPattern, options?: PlayOptions): Promise<HapticResult>;
49
+ /**
50
+ * Play `steps` in order, waiting each step's `delayMs` before it plays. Runs natively
51
+ * as ONE bridge call (the timing does not depend on the worker), so a drum roll or a
52
+ * countdown keeps its rhythm. A new `sequence` cancels one still running. Resolves once
53
+ * the sequence has been scheduled.
54
+ *
55
+ * Rejects (`RangeError`) with more than {@link MAX_SEQUENCE_STEPS} steps, a negative or
56
+ * non-finite delay, or delays totalling over {@link MAX_DURATION_MS}. An empty list just
57
+ * cancels a running sequence.
58
+ */
59
+ export declare function sequence(steps: HapticStep[]): Promise<HapticResult>;
60
+ /**
61
+ * Raw vibration: `patternMs` alternates OFF / ON durations in milliseconds, starting
62
+ * with an off gap (`[0, 200, 100, 400]` = buzz 200, pause 100, buzz 400).
63
+ *
64
+ * Android plays it as `VibrationEffect.createWaveform`. iOS approximates: with Core
65
+ * Haptics each ON span is a continuous event (a transient one under 30 ms); without it,
66
+ * each ON span becomes one `heavy` impact at its start. Web uses `navigator.vibrate`.
67
+ *
68
+ * Rejects (`RangeError`) on an empty list, a negative or non-finite duration, or a
69
+ * pattern totalling over {@link MAX_DURATION_MS}.
6
70
  */
7
- export declare function play(pattern?: HapticPattern): Promise<void>;
71
+ export declare function vibrate(patternMs: number[]): Promise<HapticResult>;
8
72
  /** Capability version, for bundles that gate on a min binary version. */
9
- export declare const version = 1;
73
+ export declare const version = 2;
@@ -5,15 +5,15 @@ export declare const CAPABILITY_REGISTRY: {
5
5
  readonly base44: readonly ["authLoginViaEmailPassword", "authLoginViaOtp", "authLoginWithProvider", "authLogout", "authMe", "authRegister", "authResetPassword", "authStatus", "authUpdateMe", "authVerifyOtp", "entitiesBulkCreate", "entitiesCreate", "entitiesDelete", "entitiesFilter", "entitiesGet", "entitiesList", "entitiesUpdate", "functionsInvoke"];
6
6
  readonly biometrics: readonly ["available", "confirm"];
7
7
  readonly browser_auth: readonly ["start"];
8
- readonly calendar: readonly ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"];
8
+ readonly calendar: readonly ["createEvent", "deleteEvent", "getEvent", "getPermissionStatus", "listCalendars", "listEvents", "presentEditor", "presentViewer", "requestPermission", "updateEvent"];
9
9
  readonly calls: readonly ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"];
10
10
  readonly camera: readonly ["capture", "pickDocument", "prepareImage", "scanQR"];
11
- readonly clipboard: readonly ["hasText", "readText", "writeText"];
11
+ readonly clipboard: readonly ["hasImage", "hasText", "readText", "writeImage", "writeText"];
12
12
  readonly contacts: readonly ["getPermissionStatus", "pick", "requestPermission", "search"];
13
13
  readonly file_picker: readonly ["pick", "pickDirectoryForExport"];
14
14
  readonly files: readonly ["list", "readText", "remove", "stat", "write"];
15
15
  readonly godot: readonly ["loadPack", "release", "send"];
16
- readonly haptic: readonly ["play"];
16
+ readonly haptic: readonly ["play", "sequence", "vibrate"];
17
17
  readonly health: readonly ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"];
18
18
  readonly himi_apps: readonly ["canOpen", "current", "hostInfo", "open"];
19
19
  readonly iap: readonly ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"];
@@ -6,8 +6,23 @@ export interface AlertOptions {
6
6
  confirmLabel?: string;
7
7
  /** Cancel button label. OMIT for a single-button alert (no cancel button). */
8
8
  cancelLabel?: string;
9
- /** Style the confirm button with the `danger` token. */
9
+ /** Style the confirm button with the `danger` token. A destructive confirm is not the
10
+ * affirmative button: its `confirm.actionId` still runs, but without gesture credit. */
10
11
  destructive?: boolean;
12
+ /** The affirmative button's ACTION. Pressing it runs `actionId` as a NEW invocation
13
+ * with user-gesture origin (so an app service's `app.<svc>.<action>` may return `_nav` and
14
+ * navigate — the "Ready — View" alert). `label` replaces `confirmLabel`. The id is checked when
15
+ * you set it, against this worker: a `capability.<id>.*` needs `<id>` allowed, an `app.*` from a
16
+ * screen worker needs `app_services` and an exported action, a `tier5.*` must be this worker's
17
+ * own; anything else rejects (`action_not_allowed`). Cancel and dismissal run nothing. */
18
+ confirm?: AlertConfirm;
19
+ }
20
+ /** The affirmative button of an `alert()`: its label and the action its press runs. */
21
+ export interface AlertConfirm {
22
+ label: string;
23
+ actionId: string;
24
+ /** Passed to the action (JSON types kept). */
25
+ args?: Record<string, unknown>;
11
26
  }
12
27
  export interface AlertResult {
13
28
  /** true ⇒ the user tapped confirm; false ⇒ cancel or the alert was dismissed
@@ -16,7 +31,9 @@ export interface AlertResult {
16
31
  }
17
32
  /** Present a modal alert on the current screen. Resolves when the user picks a
18
33
  * button. Rejects with `ui_busy` while another alert() is pending, and with
19
- * `no_ui_host` if the app has no presenter attached. */
34
+ * `no_ui_host` if the app has no presenter attached — or, from an APP SERVICE, when no
35
+ * shell is in the foreground (re-show it from `onForeground`). An app service's alert shows on
36
+ * whatever screen is open. */
20
37
  export declare function alert(options: AlertOptions): Promise<AlertResult>;
21
38
  /** Snackbar tone — maps to the app's tone background tokens (`info` → textPrimary, `success`,
22
39
  * `warning`, `danger`). Use `danger` for errors; the hosts also accept `error` as an alias of it. */
@@ -561,6 +561,12 @@ export interface RichTemplate {
561
561
  export interface PushConfig {
562
562
  /** Ping base family, without an APNs environment suffix. */
563
563
  pingAppName?: string;
564
+ /** Wix Ping registration scope (#4708). "site" (default) filters delivery to the
565
+ * session's metasite and refuses to register without one; "user" registers the
566
+ * device for the signed-in Wix user with NO metasite filter — for an
567
+ * account-level app that is not about any single site. Only the "wix-ping"
568
+ * registrar reads it. */
569
+ pingScope?: "site" | "user";
564
570
  /** Token registrar. "generic" ⇒ POST the token to `registerUrl`; "wix-ping"
565
571
  * ⇒ the native Wix Ping registrar. */
566
572
  registrar: PushRegistrar;
@@ -20,15 +20,15 @@ var CAPABILITY_REGISTRY = {
20
20
  "base44": ["authLoginViaEmailPassword", "authLoginViaOtp", "authLoginWithProvider", "authLogout", "authMe", "authRegister", "authResetPassword", "authStatus", "authUpdateMe", "authVerifyOtp", "entitiesBulkCreate", "entitiesCreate", "entitiesDelete", "entitiesFilter", "entitiesGet", "entitiesList", "entitiesUpdate", "functionsInvoke"],
21
21
  "biometrics": ["available", "confirm"],
22
22
  "browser_auth": ["start"],
23
- "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
23
+ "calendar": ["createEvent", "deleteEvent", "getEvent", "getPermissionStatus", "listCalendars", "listEvents", "presentEditor", "presentViewer", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -20,15 +20,15 @@ var CAPABILITY_REGISTRY = {
20
20
  "base44": ["authLoginViaEmailPassword", "authLoginViaOtp", "authLoginWithProvider", "authLogout", "authMe", "authRegister", "authResetPassword", "authStatus", "authUpdateMe", "authVerifyOtp", "entitiesBulkCreate", "entitiesCreate", "entitiesDelete", "entitiesFilter", "entitiesGet", "entitiesList", "entitiesUpdate", "functionsInvoke"],
21
21
  "biometrics": ["available", "confirm"],
22
22
  "browser_auth": ["start"],
23
- "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
23
+ "calendar": ["createEvent", "deleteEvent", "getEvent", "getPermissionStatus", "listCalendars", "listEvents", "presentEditor", "presentViewer", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -101,12 +101,57 @@ async function deleteEvent(id) {
101
101
  const r = await dispatch("capability.calendar.deleteEvent", { id });
102
102
  return { deleted: r?.deleted === true };
103
103
  }
104
+ function draftParams(event) {
105
+ const params = {};
106
+ if (event.title !== void 0 && event.title !== "") params.title = event.title;
107
+ if (typeof event.start === "number" && Number.isFinite(event.start)) params.start = event.start;
108
+ if (typeof event.end === "number" && Number.isFinite(event.end)) params.end = event.end;
109
+ if (event.allDay) params.allDay = true;
110
+ if (event.location) params.location = event.location;
111
+ if (event.notes) params.notes = event.notes;
112
+ return params;
113
+ }
114
+ async function presentEditor(event = {}) {
115
+ const r = await dispatch("capability.calendar.presentEditor", draftParams(event));
116
+ const out = { saved: r?.saved === true, id: typeof r?.id === "string" && r.id !== "" ? r.id : null };
117
+ if (r?.downloaded === true) out.downloaded = true;
118
+ return out;
119
+ }
120
+ async function presentViewer(id) {
121
+ const r = await dispatch("capability.calendar.presentViewer", { id });
122
+ const action = r?.action === "responded" || r?.action === "deleted" ? r.action : "done";
123
+ return { action };
124
+ }
125
+ async function listCalendars() {
126
+ const r = await dispatch("capability.calendar.listCalendars");
127
+ if (!Array.isArray(r?.items)) return [];
128
+ return r.items.flatMap((raw) => {
129
+ const c = raw;
130
+ if (!c || typeof c.id !== "string" || c.id === "") return [];
131
+ return [{
132
+ id: c.id,
133
+ title: typeof c.title === "string" ? c.title : "",
134
+ color: typeof c.color === "string" ? c.color : "",
135
+ allowsModifications: c.allowsModifications === true,
136
+ isPrimary: c.isPrimary === true
137
+ }];
138
+ });
139
+ }
140
+ async function getEvent(id) {
141
+ const r = await dispatch("capability.calendar.getEvent", { id });
142
+ const e = r?.event;
143
+ return e && typeof e.id === "string" && e.id !== "" ? e : null;
144
+ }
104
145
  var version = 1;
105
146
  export {
106
147
  createEvent,
107
148
  deleteEvent,
149
+ getEvent,
108
150
  getPermissionStatus,
151
+ listCalendars,
109
152
  listEvents,
153
+ presentEditor,
154
+ presentViewer,
110
155
  requestPermission,
111
156
  updateEvent,
112
157
  version
@@ -20,15 +20,15 @@ var CAPABILITY_REGISTRY = {
20
20
  "base44": ["authLoginViaEmailPassword", "authLoginViaOtp", "authLoginWithProvider", "authLogout", "authMe", "authRegister", "authResetPassword", "authStatus", "authUpdateMe", "authVerifyOtp", "entitiesBulkCreate", "entitiesCreate", "entitiesDelete", "entitiesFilter", "entitiesGet", "entitiesList", "entitiesUpdate", "functionsInvoke"],
21
21
  "biometrics": ["available", "confirm"],
22
22
  "browser_auth": ["start"],
23
- "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
23
+ "calendar": ["createEvent", "deleteEvent", "getEvent", "getPermissionStatus", "listCalendars", "listEvents", "presentEditor", "presentViewer", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -26,11 +26,68 @@ async function hasText() {
26
26
  const r = await dispatch("capability.clipboard.hasText");
27
27
  return r?.has === true;
28
28
  }
29
- var version = 1;
29
+ var MAX_IMAGE_BYTES = 20 * 1024 * 1024;
30
+ var IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/heic"];
31
+ var CODES = ["unsupported_type", "too_large", "not_allowed", "not_found", "unavailable"];
32
+ function clipboardImageError(code, message) {
33
+ const text = !message ? code : message.startsWith(code) ? message : `${code}: ${message}`;
34
+ const err = new Error(text);
35
+ err.name = "ClipboardImageError";
36
+ err.code = code;
37
+ return err;
38
+ }
39
+ function isClipboardImageError(e) {
40
+ return e instanceof Error && e.name === "ClipboardImageError" && CODES.includes(e.code);
41
+ }
42
+ function codeOf(err) {
43
+ const msg = err instanceof Error ? err.message : String(err ?? "");
44
+ let best = null;
45
+ for (const c of CODES) {
46
+ const m = new RegExp(`(^|[^a-z_])${c}([^a-z_]|$)`).exec(msg);
47
+ if (!m) continue;
48
+ const at = m.index + m[1].length;
49
+ if (!best || at < best.at) best = { code: c, at };
50
+ }
51
+ return best?.code ?? null;
52
+ }
53
+ function plainlyNotAnImage(mimeType) {
54
+ const mime = (mimeType ?? "").toLowerCase().trim();
55
+ return mime !== "" && mime !== "application/octet-stream" && !mime.startsWith("image/");
56
+ }
57
+ async function writeImage(file) {
58
+ const handle = typeof file === "string" ? null : file;
59
+ const uri = typeof file === "string" ? file : file?.uri;
60
+ if (typeof uri !== "string" || uri.length === 0) throw clipboardImageError("not_allowed", "no file uri");
61
+ if (handle) {
62
+ if (plainlyNotAnImage(handle.mimeType)) throw clipboardImageError("unsupported_type", String(handle.mimeType));
63
+ if (typeof handle.sizeBytes === "number" && handle.sizeBytes > MAX_IMAGE_BYTES) throw clipboardImageError("too_large", `${handle.sizeBytes} bytes`);
64
+ }
65
+ const params = { uri };
66
+ if (handle?.mimeType) params.mimeType = handle.mimeType;
67
+ if (handle?.ownerScope) params.ownerScope = handle.ownerScope;
68
+ try {
69
+ await dispatch("capability.clipboard.writeImage", params);
70
+ } catch (err) {
71
+ const code = codeOf(err);
72
+ if (code) throw clipboardImageError(code, err instanceof Error ? err.message : String(err));
73
+ throw err;
74
+ }
75
+ }
76
+ async function hasImage() {
77
+ const r = await dispatch("capability.clipboard.hasImage");
78
+ return r?.has === true;
79
+ }
80
+ var version = 2;
30
81
  export {
82
+ IMAGE_MIME_TYPES,
83
+ MAX_IMAGE_BYTES,
84
+ clipboardImageError,
85
+ hasImage,
31
86
  hasText,
87
+ isClipboardImageError,
32
88
  readText,
33
89
  version,
90
+ writeImage,
34
91
  writeText
35
92
  };
36
93
  //# sourceMappingURL=clipboard.mjs.map
@@ -20,15 +20,15 @@ var CAPABILITY_REGISTRY = {
20
20
  "base44": ["authLoginViaEmailPassword", "authLoginViaOtp", "authLoginWithProvider", "authLogout", "authMe", "authRegister", "authResetPassword", "authStatus", "authUpdateMe", "authVerifyOtp", "entitiesBulkCreate", "entitiesCreate", "entitiesDelete", "entitiesFilter", "entitiesGet", "entitiesList", "entitiesUpdate", "functionsInvoke"],
21
21
  "biometrics": ["available", "confirm"],
22
22
  "browser_auth": ["start"],
23
- "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
23
+ "calendar": ["createEvent", "deleteEvent", "getEvent", "getPermissionStatus", "listCalendars", "listEvents", "presentEditor", "presentViewer", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -14,12 +14,81 @@ function dispatch(handlerId, params, _options) {
14
14
  }
15
15
 
16
16
  // ../../core/sdk/haptic/src/index.ts
17
- async function play(pattern = "light") {
18
- await dispatch("capability.haptic.play", { pattern });
17
+ var MAX_SEQUENCE_STEPS = 32;
18
+ var MAX_DURATION_MS = 1e4;
19
+ function clampIntensity(intensity) {
20
+ if (intensity === void 0 || typeof intensity !== "number" || !Number.isFinite(intensity)) return void 0;
21
+ return Math.min(1, Math.max(0, intensity));
19
22
  }
20
- var version = 1;
23
+ var UNKNOWN_ACTION = /unknown[_ ]?(action|handler)|ActionError\.unknown|^unknown\(|no handler/i;
24
+ function toResult(payload) {
25
+ const p = payload;
26
+ if (p && p.ok === false) {
27
+ return { ok: false, reason: p.reason === "unsupported_binary" ? "unsupported_binary" : "unavailable" };
28
+ }
29
+ return { ok: true };
30
+ }
31
+ async function settle(pending) {
32
+ try {
33
+ return toResult(await pending);
34
+ } catch (e) {
35
+ if (UNKNOWN_ACTION.test(String(e?.message ?? e))) return { ok: false, reason: "unsupported_binary" };
36
+ throw e;
37
+ }
38
+ }
39
+ async function play(pattern = "light", options = {}) {
40
+ const params = { pattern };
41
+ const intensity = clampIntensity(options.intensity);
42
+ if (intensity !== void 0) params.intensity = intensity;
43
+ return toResult(await dispatch("capability.haptic.play", params));
44
+ }
45
+ async function sequence(steps) {
46
+ if (!Array.isArray(steps)) throw new TypeError("sequence: steps must be an array");
47
+ if (steps.length > MAX_SEQUENCE_STEPS) {
48
+ throw new RangeError(`sequence: at most ${MAX_SEQUENCE_STEPS} steps (got ${steps.length})`);
49
+ }
50
+ let total = 0;
51
+ const wire = steps.map((s, i) => {
52
+ const delayMs = Number(s?.delayMs ?? 0);
53
+ if (!Number.isFinite(delayMs) || delayMs < 0) throw new RangeError(`sequence: step ${i} has an invalid delayMs`);
54
+ total += delayMs;
55
+ const out = {
56
+ pattern: String(s?.pattern ?? "light"),
57
+ delayMs: Math.round(delayMs)
58
+ };
59
+ const intensity = clampIntensity(s?.intensity);
60
+ if (intensity !== void 0) out.intensity = intensity;
61
+ return out;
62
+ });
63
+ if (total > MAX_DURATION_MS) {
64
+ throw new RangeError(`sequence: total delay ${total}ms exceeds ${MAX_DURATION_MS}ms`);
65
+ }
66
+ return settle(dispatch("capability.haptic.sequence", { steps: JSON.stringify(wire) }));
67
+ }
68
+ async function vibrate(patternMs) {
69
+ if (!Array.isArray(patternMs) || patternMs.length === 0) {
70
+ throw new RangeError("vibrate: patternMs must be a non-empty array");
71
+ }
72
+ let total = 0;
73
+ const wire = patternMs.map((ms, i) => {
74
+ const n = Number(ms);
75
+ if (!Number.isFinite(n) || n < 0) throw new RangeError(`vibrate: duration ${i} is invalid`);
76
+ total += n;
77
+ return Math.round(n);
78
+ });
79
+ if (total > MAX_DURATION_MS) {
80
+ throw new RangeError(`vibrate: pattern totals ${total}ms, over ${MAX_DURATION_MS}ms`);
81
+ }
82
+ return settle(dispatch("capability.haptic.vibrate", { pattern: wire.join(",") }));
83
+ }
84
+ var version = 2;
21
85
  export {
86
+ MAX_DURATION_MS,
87
+ MAX_SEQUENCE_STEPS,
88
+ clampIntensity,
22
89
  play,
23
- version
90
+ sequence,
91
+ version,
92
+ vibrate
24
93
  };
25
94
  //# sourceMappingURL=haptic.mjs.map
@@ -20,15 +20,15 @@ var CAPABILITY_REGISTRY = {
20
20
  "base44": ["authLoginViaEmailPassword", "authLoginViaOtp", "authLoginWithProvider", "authLogout", "authMe", "authRegister", "authResetPassword", "authStatus", "authUpdateMe", "authVerifyOtp", "entitiesBulkCreate", "entitiesCreate", "entitiesDelete", "entitiesFilter", "entitiesGet", "entitiesList", "entitiesUpdate", "functionsInvoke"],
21
21
  "biometrics": ["available", "confirm"],
22
22
  "browser_auth": ["start"],
23
- "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
23
+ "calendar": ["createEvent", "deleteEvent", "getEvent", "getPermissionStatus", "listCalendars", "listEvents", "presentEditor", "presentViewer", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -20,15 +20,15 @@ var CAPABILITY_REGISTRY = {
20
20
  "base44": ["authLoginViaEmailPassword", "authLoginViaOtp", "authLoginWithProvider", "authLogout", "authMe", "authRegister", "authResetPassword", "authStatus", "authUpdateMe", "authVerifyOtp", "entitiesBulkCreate", "entitiesCreate", "entitiesDelete", "entitiesFilter", "entitiesGet", "entitiesList", "entitiesUpdate", "functionsInvoke"],
21
21
  "biometrics": ["available", "confirm"],
22
22
  "browser_auth": ["start"],
23
- "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
23
+ "calendar": ["createEvent", "deleteEvent", "getEvent", "getPermissionStatus", "listCalendars", "listEvents", "presentEditor", "presentViewer", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -20,15 +20,15 @@ var CAPABILITY_REGISTRY = {
20
20
  "base44": ["authLoginViaEmailPassword", "authLoginViaOtp", "authLoginWithProvider", "authLogout", "authMe", "authRegister", "authResetPassword", "authStatus", "authUpdateMe", "authVerifyOtp", "entitiesBulkCreate", "entitiesCreate", "entitiesDelete", "entitiesFilter", "entitiesGet", "entitiesList", "entitiesUpdate", "functionsInvoke"],
21
21
  "biometrics": ["available", "confirm"],
22
22
  "browser_auth": ["start"],
23
- "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
23
+ "calendar": ["createEvent", "deleteEvent", "getEvent", "getPermissionStatus", "listCalendars", "listEvents", "presentEditor", "presentViewer", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],