@wix/himalaya-cli 0.1597.0 → 0.1599.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 (27) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/legacy-import/src/index.d.ts +30 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/sdk-types/src/capabilities.generated.d.ts +2 -1
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/webview-page/src/capabilities.generated.d.ts +2 -0
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +12 -1
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/legacy-import.d.ts +134 -0
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/audio-record.mjs +1 -0
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calendar.mjs +1 -0
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calls.mjs +1 -0
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/contacts.mjs +1 -0
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +184 -16
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/legacy-import.mjs +40 -0
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/location.mjs +1 -0
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/motion.mjs +1 -0
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/photos.mjs +1 -0
  15. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdk-types.mjs +1 -0
  16. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/tasks.mjs +1 -0
  17. package/dist/authoring-runtime/node_modules/@wix/himalaya/package.json +4 -0
  18. package/dist/cli.mjs +641 -510
  19. package/dist/preview-assets.generated.bin +0 -0
  20. package/guides/app-config.md +1 -1
  21. package/guides/capabilities.md +1 -0
  22. package/guides/importable-sdks.md +1 -0
  23. package/guides/qa-builds.md +43 -1
  24. package/guides/sdk-reference.json +43 -0
  25. package/guides/web-page-native-sdk.md +1 -1
  26. package/guides/web-page-sdk-reference.md +1 -0
  27. package/package.json +2 -2
@@ -0,0 +1,30 @@
1
+ export interface LegacyImportSourceReport {
2
+ id: string;
3
+ /** `done` | `empty` | `incomplete` | `failed` | `unregistered_kind` | `invalid_options` */
4
+ status: string;
5
+ /** Item counts — `items`, plus one per sink the source's items went to. */
6
+ counts: Record<string, number>;
7
+ error?: string;
8
+ }
9
+ export interface LegacyImportReportItem {
10
+ key: string;
11
+ /** The item's value — UTF-8 text, or base64 when `meta.encoding === "base64"`. */
12
+ value: string;
13
+ meta?: Record<string, string>;
14
+ }
15
+ export interface LegacyImportReport {
16
+ /** The `legacyImport.id` that produced it. */
17
+ id: string;
18
+ /** Epoch ms the import ran. */
19
+ extractedAt: number;
20
+ sources: LegacyImportSourceReport[];
21
+ /** Only the `report` sink's items. */
22
+ items: LegacyImportReportItem[];
23
+ }
24
+ /** The import report for the signed-in principal, or null — none ran, it was acknowledged, it
25
+ * belongs to another account, or this host has nothing to import (web). */
26
+ export declare function read(): Promise<LegacyImportReport | null>;
27
+ /** Delete the report. Idempotent: acknowledging twice (or with nothing to acknowledge) is fine. */
28
+ export declare function ack(): Promise<void>;
29
+ /** Capability version, for bundles that gate on min binary version. */
30
+ export declare const version = 1;
@@ -18,6 +18,7 @@ export declare const CAPABILITY_REGISTRY: {
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"];
20
20
  readonly keyboard: readonly ["dismiss"];
21
+ readonly legacy_import: readonly ["ack", "read"];
21
22
  readonly live_activity: readonly ["end", "start", "update"];
22
23
  readonly local_database: readonly ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"];
23
24
  readonly location: readonly ["backgroundStart", "backgroundStop", "getCurrent", "getPermissionStatus", "regionAdd", "regionClear", "regionList", "regionNext", "regionRemove", "regionSupport", "requestPermission", "watchNext", "watchStart", "watchStop"];
@@ -44,7 +45,7 @@ export declare const CAPABILITY_REGISTRY: {
44
45
  readonly wix_chat: readonly ["getRealtimeStatus", "subscribeRealtime", "unsubscribeRealtime"];
45
46
  };
46
47
  /** A capability id backed by an @himalaya/* SDK binding. */
47
- export type SdkCapability = "app_info" | "audio_record" | "base44" | "biometrics" | "browser_auth" | "calendar" | "calls" | "camera" | "clipboard" | "contacts" | "file_picker" | "files" | "godot" | "haptic" | "health" | "himi_apps" | "iap" | "keyboard" | "live_activity" | "local_database" | "location" | "media_playback" | "motion" | "network" | "on_device_ai" | "open_url" | "pdf" | "photos" | "presigned_upload" | "push" | "release_control" | "secure_storage" | "share" | "speaker_diarization" | "speech" | "system_intents" | "tasks" | "theme" | "torch" | "ui" | "wix_cashier" | "wix_chat";
48
+ export type SdkCapability = "app_info" | "audio_record" | "base44" | "biometrics" | "browser_auth" | "calendar" | "calls" | "camera" | "clipboard" | "contacts" | "file_picker" | "files" | "godot" | "haptic" | "health" | "himi_apps" | "iap" | "keyboard" | "legacy_import" | "live_activity" | "local_database" | "location" | "media_playback" | "motion" | "network" | "on_device_ai" | "open_url" | "pdf" | "photos" | "presigned_upload" | "push" | "release_control" | "secure_storage" | "share" | "speaker_diarization" | "speech" | "system_intents" | "tasks" | "theme" | "torch" | "ui" | "wix_cashier" | "wix_chat";
48
49
  /** All `capability.<id>.<verb>` action ids, flattened (the worker-bridge wire vocabulary). */
49
50
  export declare const CAPABILITY_ACTION_IDS: readonly string[];
50
51
  /** Capability id → the @himalaya/* package(s) a worker imports to reach it — every dispatch
@@ -16,6 +16,7 @@ import type * as HealthSdk from "@wix/himalaya/health";
16
16
  import type * as HimiAppsSdk from "@wix/himalaya/himi-apps";
17
17
  import type * as IapSdk from "@wix/himalaya/iap";
18
18
  import type * as KeyboardSdk from "@wix/himalaya/keyboard";
19
+ import type * as LegacyImportSdk from "@wix/himalaya/legacy-import";
19
20
  import type * as LiveActivitySdk from "@wix/himalaya/live-activity";
20
21
  import type * as LocalDatabaseSdk from "@wix/himalaya/local-db";
21
22
  import type * as LocationSdk from "@wix/himalaya/location";
@@ -70,6 +71,7 @@ export interface HimalayaPageCapabilities {
70
71
  readonly "himi_apps": PageModule<typeof HimiAppsSdk> & PageEvents;
71
72
  readonly "iap": PageModule<typeof IapSdk> & PageEvents;
72
73
  readonly "keyboard": PageModule<typeof KeyboardSdk> & PageEvents;
74
+ readonly "legacy_import": PageModule<typeof LegacyImportSdk> & PageEvents;
73
75
  readonly "live_activity": PageModule<typeof LiveActivitySdk> & PageEvents;
74
76
  readonly "local_database": PageModule<typeof LocalDatabaseSdk> & PageEvents;
75
77
  readonly "location": PageModule<typeof LocationSdk> & PageEvents;
@@ -7,6 +7,7 @@ import { type LocaleConfig } from "./locale.js";
7
7
  import { type DistributionConfig } from "./distribution.js";
8
8
  import { type StoreConfig } from "./store-adopt.js";
9
9
  import type { CmsConfig } from "./cms.js";
10
+ import { type LegacyImportConfig } from "./legacy-import.js";
10
11
  import { type DataResourcesConfig } from "@wix/himalaya/data-resources";
11
12
  import { type Base44EntitySpec, type Base44FunctionSpec } from "./base44-entities.js";
12
13
  import type { FunctionDefinition, FunctionScheduleRecord } from "@himalaya/functions";
@@ -14,6 +15,8 @@ export type { CmsConfig, CmsCollectionSpec, CmsFieldSpec, WixFieldType } from ".
14
15
  export type { PushRoute, PushPayloadAdapter, PushScreenMapEntry };
15
16
  export type { DataResourcesConfig, KvSpec, ResourceEnvironment, ResourceScope } from "@wix/himalaya/data-resources";
16
17
  export { WIX_FIELD_TYPES } from "./cms.js";
18
+ export type { BakedLegacyImport, LegacyImportConfig, LegacyImportFileRoot, LegacyImportFilesSource, LegacyImportIdFrom, LegacyImportMapRule, LegacyImportPrincipal, LegacyImportSink, LegacyImportSinkName, LegacyImportSourceConfig, LegacyImportSourceKind, } from "./legacy-import.js";
19
+ export { LEGACY_IMPORT_SINKS, LEGACY_IMPORT_SOURCE_KINDS, bakeLegacyImport, legacyImportProblems } from "./legacy-import.js";
17
20
  export type { Base44EntitySpec, Base44FieldSpec, Base44FieldType, Base44FunctionSpec, Base44Issue, Base44RuleCode, Base44StringFormat } from "./base44-entities.js";
18
21
  export { BASE44_BUILTIN_FIELDS, BASE44_FIELD_TYPES, BASE44_STRING_FORMATS, physicalEntityName, validateBase44Entities } from "./base44-entities.js";
19
22
  /** Wix site/environment binding used by the server-function surface. */
@@ -288,6 +291,14 @@ export interface AppConfig {
288
291
  * Absent ⇒ the app uses no CMS collections. See docs/cms-collections.md.
289
292
  */
290
293
  cms?: CmsConfig;
294
+ /**
295
+ * #4653 — a one-time, first-launch import of the data a PREVIOUS store app (same bundle id /
296
+ * applicationId) left on the device: declared sources (`files`, …) mapped item by item to
297
+ * sinks (`localDatabase`, `state`, `files`, `report`, `installationId`, `drop`). Baked into the
298
+ * binary as `legacy-import.json` and run natively before auth bootstrap; never served OTA — a
299
+ * release cannot change what a binary imports. See docs/legacy-import.md.
300
+ */
301
+ legacyImport?: LegacyImportConfig;
291
302
  /**
292
303
  * The Base44 app this app's Tier-5 workers talk to through `@himalaya/base44`
293
304
  * (requires the `base44` capability). Workers never pass the app id: the web host
@@ -848,7 +859,7 @@ export interface OrientationEnvelope {
848
859
  export declare const DEFAULT_ORIENTATION_ENVELOPE: Required<OrientationEnvelope>;
849
860
  /** Fill in the absent families. Total, so callers never branch on `undefined`. */
850
861
  export declare function resolveOrientationEnvelope(env?: OrientationEnvelope): Required<OrientationEnvelope>;
851
- export type Capability = "camera" | "barcode_scanner" | "biometrics" | "secure_storage" | "share" | "push" | "file_picker" | "files" | "open_url" | "pdf" | "clipboard" | "theme" | "l10n" | "photos" | "presigned_upload" | "ui" | "calendar" | "contacts" | "tasks" | "audio_record" | "audio_record_background" | "calls" | "location" | "location_background" | "motion" | "health" | "media_playback" | "webview" | "browser_auth" | "haptic" | "himi_apps" | "iap" | "keyboard" | "torch" | "network" | "wix_cashier" | "wix_chat" | "live_activity" | "local_database" | "speech" | "speaker_diarization" | "system_intents" | "on_device_ai" | "app_info" | "release_control" | "godot" | "base44" | "animation";
862
+ export type Capability = "camera" | "barcode_scanner" | "biometrics" | "secure_storage" | "share" | "push" | "file_picker" | "files" | "open_url" | "pdf" | "clipboard" | "theme" | "l10n" | "photos" | "presigned_upload" | "ui" | "calendar" | "contacts" | "tasks" | "audio_record" | "audio_record_background" | "calls" | "location" | "location_background" | "motion" | "health" | "media_playback" | "webview" | "browser_auth" | "haptic" | "himi_apps" | "iap" | "keyboard" | "torch" | "network" | "wix_cashier" | "wix_chat" | "live_activity" | "local_database" | "speech" | "speaker_diarization" | "system_intents" | "on_device_ai" | "app_info" | "release_control" | "legacy_import" | "godot" | "base44" | "animation";
852
863
  /** `defineApp({ wixIap })` — the purchases-service app a build binds this app to. */
853
864
  export interface WixIapConfig {
854
865
  /** The purchases service's app UUID, registered on the app's own auth site. Not a secret. */
@@ -0,0 +1,134 @@
1
+ /** Source kinds a baked config may name. A kind a binary does not register is skipped and
2
+ * reported at runtime, never a crash — but `defineApp` only accepts kinds the contract knows. */
3
+ export declare const LEGACY_IMPORT_SOURCE_KINDS: readonly ["files"];
4
+ export type LegacyImportSourceKind = (typeof LEGACY_IMPORT_SOURCE_KINDS)[number];
5
+ /** Sinks an item can be mapped to. */
6
+ export declare const LEGACY_IMPORT_SINKS: readonly ["localDatabase", "state", "files", "report", "installationId", "drop"];
7
+ export type LegacyImportSinkName = (typeof LEGACY_IMPORT_SINKS)[number];
8
+ /** The container roots a `files` source may read under (the OLD app's container, which an
9
+ * update shares). */
10
+ export declare const LEGACY_IMPORT_FILE_ROOTS: readonly ["documents", "library", "caches"];
11
+ export type LegacyImportFileRoot = (typeof LEGACY_IMPORT_FILE_ROOTS)[number];
12
+ /** Every file under `<root>/<path>`. An item's key is its path relative to that directory,
13
+ * with `/` separators (e.g. `notes/a.json`); its value is the file. */
14
+ export interface LegacyImportFilesSource {
15
+ id: string;
16
+ kind: "files";
17
+ root: LegacyImportFileRoot;
18
+ /** Relative directory under `root` — no leading `/`, no `..`. */
19
+ path: string;
20
+ }
21
+ export type LegacyImportSourceConfig = LegacyImportFilesSource;
22
+ /** How a `localDatabase` row gets its `id`:
23
+ * - `key` — the item key;
24
+ * - `keySuffix` — the key minus the rule's literal prefix (the text before the first `*` of
25
+ * `match`; the whole key for an exact `key` rule), with a trailing file extension removed;
26
+ * - `jsonPath:<p>` — a dotted path into the item's JSON value; a numeric segment indexes an array
27
+ * (`rows.0.id`). */
28
+ export type LegacyImportIdFrom = "key" | "keySuffix" | `jsonPath:${string}`;
29
+ export type LegacyImportSink =
30
+ /** Rows written through the local-database store (the item value must be a JSON object). */
31
+ {
32
+ sink: "localDatabase";
33
+ entity: string;
34
+ idFrom: LegacyImportIdFrom;
35
+ }
36
+ /** Merged into an app service's / worker's state snapshot at `path` (dotted) before hydration. */
37
+ | {
38
+ sink: "state";
39
+ service: string;
40
+ path: string;
41
+ }
42
+ /** Moved into the files capability's own root, under `dir` (relative). */
43
+ | {
44
+ sink: "files";
45
+ dir: string;
46
+ }
47
+ /** Kept for the worker to read once through `@himalaya/legacy-import`. */
48
+ | {
49
+ sink: "report";
50
+ }
51
+ /** The device-scoped push installation id override (the value push registration sends
52
+ * instead of a fresh id). The only sink that is NOT principal-scoped. */
53
+ | {
54
+ sink: "installationId";
55
+ }
56
+ /** Read (so the source can be deleted) and discarded. */
57
+ | {
58
+ sink: "drop";
59
+ };
60
+ /** One mapping rule: items of source `from` whose key equals `key`, or matches the simple `*`
61
+ * glob `match` (`*` matches any run of characters, `/` included), go to `to`. Exactly one of
62
+ * `key` / `match`. The FIRST rule that matches an item wins. */
63
+ export interface LegacyImportMapRule {
64
+ from: string;
65
+ match?: string;
66
+ key?: string;
67
+ to: LegacyImportSink;
68
+ }
69
+ /** Where the legacy principal (the account the old app was signed in as) is read from: the
70
+ * item `key` of source `from`, optionally a dotted `jsonPath` into its JSON value. */
71
+ export interface LegacyImportPrincipal {
72
+ from: string;
73
+ key: string;
74
+ jsonPath?: string;
75
+ }
76
+ export interface LegacyImportConfig {
77
+ /** Stable id of this import — names the run-once marker `legacy-import.<id>`. Changing it
78
+ * makes a new binary run a NEW import. */
79
+ id: string;
80
+ sources: LegacyImportSourceConfig[];
81
+ map: LegacyImportMapRule[];
82
+ /** What happens to an item no rule maps: kept for the worker (`report`) or discarded. */
83
+ unmapped: "report" | "drop";
84
+ /** Absent ⇒ the principal of a session the auth provider reports as adopted from the legacy
85
+ * store (H12d); with neither, principal-scoped data is held and purged after `retainDays`. */
86
+ principal?: LegacyImportPrincipal;
87
+ /** Days unapplied staging is kept before it is purged (default 30). */
88
+ retainDays?: number;
89
+ }
90
+ /** The normalised shape written to `legacy-import.json` — defaults filled, version stamped. */
91
+ export interface BakedLegacyImport {
92
+ version: 1;
93
+ id: string;
94
+ sources: LegacyImportSourceConfig[];
95
+ map: LegacyImportMapRule[];
96
+ unmapped: "report" | "drop";
97
+ principal?: LegacyImportPrincipal;
98
+ retainDays: number;
99
+ /** Run budget the native runner gets, in ms. */
100
+ budgetMs: number;
101
+ /** Attempts before the runner records `gave_up`. */
102
+ maxAttempts: number;
103
+ }
104
+ export declare const LEGACY_IMPORT_DEFAULT_RETAIN_DAYS = 30;
105
+ export declare const LEGACY_IMPORT_BUDGET_MS = 3000;
106
+ export declare const LEGACY_IMPORT_MAX_ATTEMPTS = 3;
107
+ /** A simple `*` glob: any characters except the glob metacharacters `? [ ] { } !`, no `**`,
108
+ * and not empty. */
109
+ export declare function isSimpleGlob(pattern: string): boolean;
110
+ /** Whether `key` matches the simple glob `pattern` (`*` = any run of characters, `/` included). */
111
+ export declare function matchesSimpleGlob(pattern: string, key: string): boolean;
112
+ /** Names the native importer uses for its own entries beside each import's staging directory
113
+ * (`<Application Support>/himalaya-legacy-import/<id>/`): the state-seed store and the carried-over
114
+ * push installation id. An import with one of these ids would overwrite or delete them. */
115
+ export declare const LEGACY_IMPORT_RESERVED_IDS: readonly string[];
116
+ /** May a files source read `<root>/<path>`? A retry re-reads its source, so one covering Himi's
117
+ * storage would delete what Himi wrote since. `library` holds Himi's and the system's own stores
118
+ * (WebKit, Preferences, Caches, …), so a source there is a folder of the old app's under
119
+ * `Application Support`; that folder, and a `caches` source's first folder, is never a Himi-owned
120
+ * one, never bundle-id shaped (`Caches/<bundleId>` is this bundle's URL cache), and never a system
121
+ * cache folder. Mirror of `FilesLegacyImportSource.mayRead` on iOS. */
122
+ export declare function mayReadLegacyFiles(root: string, path: string): boolean;
123
+ /** Every problem with a `legacyImport` block, each prefixed with its field path. Empty ⇒ valid. */
124
+ export declare function legacyImportProblems(cfg: unknown, at?: string): string[];
125
+ /** Throw on the first problems (all of them, joined) — what `defineApp` calls. */
126
+ export declare function validateLegacyImport(cfg: unknown, at?: string): asserts cfg is LegacyImportConfig;
127
+ /** The normalised `legacy-import.json` body for a VALID block (validates first). */
128
+ export declare function bakeLegacyImport(cfg: LegacyImportConfig): BakedLegacyImport;
129
+ /** The first rule that maps `key` of source `sourceId`, or null (the item is `unmapped`). The
130
+ * native runners implement the same rule; this is the reference the shared fixture pins. */
131
+ export declare function ruleFor(cfg: Pick<LegacyImportConfig, "map">, sourceId: string, key: string): LegacyImportMapRule | null;
132
+ /** The `keySuffix` of `key` under `rule`: the key minus the literal text before the first `*`
133
+ * (the whole key for a `key` rule), with a trailing `.ext` removed. */
134
+ export declare function keySuffix(rule: LegacyImportMapRule, key: string): string;
@@ -33,6 +33,7 @@ var CAPABILITY_REGISTRY = {
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
35
35
  "keyboard": ["dismiss"],
36
+ "legacy_import": ["ack", "read"],
36
37
  "live_activity": ["end", "start", "update"],
37
38
  "local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
38
39
  "location": ["backgroundStart", "backgroundStop", "getCurrent", "getPermissionStatus", "regionAdd", "regionClear", "regionList", "regionNext", "regionRemove", "regionSupport", "requestPermission", "watchNext", "watchStart", "watchStop"],
@@ -33,6 +33,7 @@ var CAPABILITY_REGISTRY = {
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
35
35
  "keyboard": ["dismiss"],
36
+ "legacy_import": ["ack", "read"],
36
37
  "live_activity": ["end", "start", "update"],
37
38
  "local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
38
39
  "location": ["backgroundStart", "backgroundStop", "getCurrent", "getPermissionStatus", "regionAdd", "regionClear", "regionList", "regionNext", "regionRemove", "regionSupport", "requestPermission", "watchNext", "watchStart", "watchStop"],
@@ -33,6 +33,7 @@ var CAPABILITY_REGISTRY = {
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
35
35
  "keyboard": ["dismiss"],
36
+ "legacy_import": ["ack", "read"],
36
37
  "live_activity": ["end", "start", "update"],
37
38
  "local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
38
39
  "location": ["backgroundStart", "backgroundStop", "getCurrent", "getPermissionStatus", "regionAdd", "regionClear", "regionList", "regionNext", "regionRemove", "regionSupport", "requestPermission", "watchNext", "watchStart", "watchStop"],
@@ -33,6 +33,7 @@ var CAPABILITY_REGISTRY = {
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
35
35
  "keyboard": ["dismiss"],
36
+ "legacy_import": ["ack", "read"],
36
37
  "live_activity": ["end", "start", "update"],
37
38
  "local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
38
39
  "location": ["backgroundStart", "backgroundStop", "getCurrent", "getPermissionStatus", "regionAdd", "regionClear", "regionList", "regionNext", "regionRemove", "regionSupport", "requestPermission", "watchNext", "watchStart", "watchStop"],
@@ -7443,6 +7443,149 @@ function gateScreenIdShapeProblem(id) {
7443
7443
  return null;
7444
7444
  }
7445
7445
 
7446
+ // ../../core/ts/src/legacy-import.ts
7447
+ var LEGACY_IMPORT_SOURCE_KINDS = ["files"];
7448
+ var LEGACY_IMPORT_SINKS = ["localDatabase", "state", "files", "report", "installationId", "drop"];
7449
+ var LEGACY_IMPORT_FILE_ROOTS = ["documents", "library", "caches"];
7450
+ var LEGACY_IMPORT_DEFAULT_RETAIN_DAYS = 30;
7451
+ var LEGACY_IMPORT_BUDGET_MS = 3e3;
7452
+ var LEGACY_IMPORT_MAX_ATTEMPTS = 3;
7453
+ var ID_RE = /^[a-z0-9][a-z0-9_.-]{0,63}$/;
7454
+ var DOTTED_RE = /^[A-Za-z0-9_$-]+(\.[A-Za-z0-9_$-]+)*$/;
7455
+ function isSimpleGlob(pattern) {
7456
+ return typeof pattern === "string" && pattern.length > 0 && !/[?[\]{}!]/.test(pattern) && !pattern.includes("**");
7457
+ }
7458
+ function isSafeRelativePath(p) {
7459
+ if (typeof p !== "string" || p.length === 0 || p.startsWith("/") || p.includes("\\")) return false;
7460
+ return p.split("/").every((s) => s.length > 0 && s !== "." && s !== "..");
7461
+ }
7462
+ var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
7463
+ var nonEmpty = (v) => typeof v === "string" && v.trim().length > 0;
7464
+ var LEGACY_IMPORT_RESERVED_IDS = ["state-seeds", "installation-id"];
7465
+ var isHimiOwned = (segment) => /^(himalaya|himi|io\.himalaya)/i.test(segment);
7466
+ var SYSTEM_CACHE_FOLDERS = /* @__PURE__ */ new Set(["WebKit", "Snapshots", "fsCachedData"]);
7467
+ function mayReadLegacyFiles(root, path) {
7468
+ const segs = path.split("/");
7469
+ const appFolder = (s) => !isHimiOwned(s) && !s.includes(".") && !SYSTEM_CACHE_FOLDERS.has(s);
7470
+ if (root === "library") return segs.length >= 2 && segs[0] === "Application Support" && appFolder(segs[1]);
7471
+ if (root === "caches") return appFolder(segs[0]);
7472
+ return true;
7473
+ }
7474
+ function legacyImportProblems(cfg, at = "legacyImport") {
7475
+ const out = [];
7476
+ if (!isObj(cfg)) return [`${at}: must be an object`];
7477
+ if (typeof cfg.id !== "string" || !ID_RE.test(cfg.id)) out.push(`${at}.id: must match ${ID_RE} (got ${JSON.stringify(cfg.id)})`);
7478
+ else if (LEGACY_IMPORT_RESERVED_IDS.includes(cfg.id)) out.push(`${at}.id: "${cfg.id}" is reserved (the importer's own storage uses it)`);
7479
+ const sourceIds = /* @__PURE__ */ new Set();
7480
+ if (!Array.isArray(cfg.sources) || cfg.sources.length === 0) {
7481
+ out.push(`${at}.sources: must be a non-empty array`);
7482
+ } else {
7483
+ cfg.sources.forEach((s, i) => {
7484
+ const p = `${at}.sources[${i}]`;
7485
+ if (!isObj(s)) {
7486
+ out.push(`${p}: must be an object`);
7487
+ return;
7488
+ }
7489
+ if (typeof s.id !== "string" || !ID_RE.test(s.id)) out.push(`${p}.id: must match ${ID_RE} (got ${JSON.stringify(s.id)})`);
7490
+ else if (sourceIds.has(s.id)) out.push(`${p}.id: duplicate source id "${s.id}"`);
7491
+ else sourceIds.add(s.id);
7492
+ if (!LEGACY_IMPORT_SOURCE_KINDS.includes(s.kind)) {
7493
+ out.push(`${p}.kind: unknown source kind ${JSON.stringify(s.kind)} (known: ${LEGACY_IMPORT_SOURCE_KINDS.join(", ")})`);
7494
+ return;
7495
+ }
7496
+ if (s.kind === "files") {
7497
+ if (!LEGACY_IMPORT_FILE_ROOTS.includes(s.root)) {
7498
+ out.push(`${p}.root: must be one of ${LEGACY_IMPORT_FILE_ROOTS.join(", ")} (got ${JSON.stringify(s.root)})`);
7499
+ }
7500
+ if (!isSafeRelativePath(s.path)) out.push(`${p}.path: must be a relative path with no "..", "." or empty segment (got ${JSON.stringify(s.path)})`);
7501
+ else if (!mayReadLegacyFiles(s.root, s.path)) {
7502
+ out.push(`${p}.path: ${JSON.stringify(s.path)} could cover Himi's own storage under ${JSON.stringify(s.root)} \u2014 under "library" name the old app's folder under "Application Support" (e.g. "Application Support/OldApp"); that folder, and a "caches" source's first folder, may not be a himalaya/himi folder, contain a "." (a bundle id's) or be WebKit / Snapshots / fsCachedData`);
7503
+ }
7504
+ }
7505
+ });
7506
+ }
7507
+ if (!Array.isArray(cfg.map)) {
7508
+ out.push(`${at}.map: must be an array`);
7509
+ } else {
7510
+ cfg.map.forEach((r, i) => {
7511
+ const p = `${at}.map[${i}]`;
7512
+ if (!isObj(r)) {
7513
+ out.push(`${p}: must be an object`);
7514
+ return;
7515
+ }
7516
+ if (typeof r.from !== "string" || !sourceIds.has(r.from)) out.push(`${p}.from: names no declared source (got ${JSON.stringify(r.from)})`);
7517
+ const hasMatch = r.match !== void 0;
7518
+ const hasKey = r.key !== void 0;
7519
+ if (hasMatch === hasKey) out.push(`${p}: exactly one of "match" or "key" is required`);
7520
+ if (hasMatch && (typeof r.match !== "string" || !isSimpleGlob(r.match))) {
7521
+ out.push(`${p}.match: must be a simple "*" glob (no ? [ ] { } ! or **) (got ${JSON.stringify(r.match)})`);
7522
+ }
7523
+ if (hasKey && !nonEmpty(r.key)) out.push(`${p}.key: must be a non-empty string`);
7524
+ out.push(...sinkProblems(r.to, `${p}.to`));
7525
+ });
7526
+ }
7527
+ if (cfg.unmapped !== "report" && cfg.unmapped !== "drop") out.push(`${at}.unmapped: must be "report" or "drop" (got ${JSON.stringify(cfg.unmapped)})`);
7528
+ if (cfg.principal !== void 0) {
7529
+ const pr = cfg.principal;
7530
+ if (!isObj(pr)) out.push(`${at}.principal: must be an object`);
7531
+ else {
7532
+ if (typeof pr.from !== "string" || !sourceIds.has(pr.from)) out.push(`${at}.principal.from: names no declared source (got ${JSON.stringify(pr.from)})`);
7533
+ if (!nonEmpty(pr.key)) out.push(`${at}.principal.key: must be a non-empty string`);
7534
+ if (pr.jsonPath !== void 0 && (typeof pr.jsonPath !== "string" || !DOTTED_RE.test(pr.jsonPath))) {
7535
+ out.push(`${at}.principal.jsonPath: must be a dotted path (got ${JSON.stringify(pr.jsonPath)})`);
7536
+ }
7537
+ }
7538
+ }
7539
+ if (cfg.retainDays !== void 0 && (!Number.isInteger(cfg.retainDays) || cfg.retainDays < 1 || cfg.retainDays > 365)) {
7540
+ out.push(`${at}.retainDays: must be an integer in [1, 365] (got ${JSON.stringify(cfg.retainDays)})`);
7541
+ }
7542
+ return out;
7543
+ }
7544
+ function sinkProblems(to, p) {
7545
+ if (!isObj(to)) return [`${p}: must be an object with a "sink"`];
7546
+ if (!LEGACY_IMPORT_SINKS.includes(to.sink)) {
7547
+ return [`${p}.sink: unknown sink ${JSON.stringify(to.sink)} (known: ${LEGACY_IMPORT_SINKS.join(", ")})`];
7548
+ }
7549
+ const out = [];
7550
+ switch (to.sink) {
7551
+ case "localDatabase": {
7552
+ out.push(`${p}.sink: "localDatabase" is not supported yet \u2014 no shell pins the importing account (import rows as "files" or "report" for now)`);
7553
+ if (!nonEmpty(to.entity)) out.push(`${p}.entity: must be a non-empty string`);
7554
+ const idFrom = to.idFrom;
7555
+ const ok = idFrom === "key" || idFrom === "keySuffix" || typeof idFrom === "string" && idFrom.startsWith("jsonPath:") && DOTTED_RE.test(idFrom.slice("jsonPath:".length));
7556
+ if (!ok) out.push(`${p}.idFrom: must be "key", "keySuffix" or "jsonPath:<dotted.path>" (got ${JSON.stringify(idFrom)})`);
7557
+ break;
7558
+ }
7559
+ case "state":
7560
+ if (!nonEmpty(to.service)) out.push(`${p}.service: must be a non-empty string`);
7561
+ if (typeof to.path !== "string" || !DOTTED_RE.test(to.path)) out.push(`${p}.path: must be a dotted path (got ${JSON.stringify(to.path)})`);
7562
+ break;
7563
+ case "files":
7564
+ if (!isSafeRelativePath(to.dir)) out.push(`${p}.dir: must be a relative path with no "..", "." or empty segment (got ${JSON.stringify(to.dir)})`);
7565
+ break;
7566
+ }
7567
+ return out;
7568
+ }
7569
+ function validateLegacyImport(cfg, at = "legacyImport") {
7570
+ const problems = legacyImportProblems(cfg, at);
7571
+ if (problems.length > 0) throw new Error(`defineApp: ${problems.join("; ")}`);
7572
+ }
7573
+ function bakeLegacyImport(cfg) {
7574
+ validateLegacyImport(cfg);
7575
+ const baked = {
7576
+ version: 1,
7577
+ id: cfg.id,
7578
+ sources: cfg.sources.map((s) => ({ ...s })),
7579
+ map: cfg.map.map((r) => ({ ...r, to: { ...r.to } })),
7580
+ unmapped: cfg.unmapped,
7581
+ retainDays: cfg.retainDays ?? LEGACY_IMPORT_DEFAULT_RETAIN_DAYS,
7582
+ budgetMs: LEGACY_IMPORT_BUDGET_MS,
7583
+ maxAttempts: LEGACY_IMPORT_MAX_ATTEMPTS
7584
+ };
7585
+ if (cfg.principal) baked.principal = { ...cfg.principal };
7586
+ return baked;
7587
+ }
7588
+
7446
7589
  // ../../core/data-resources/src/base44/schema.ts
7447
7590
  var BASE44_FIELD_TYPES = ["string", "number", "integer", "boolean", "array", "object"];
7448
7591
  var BASE44_STRING_FORMATS = ["date", "date-time", "time", "email", "uri", "uuid", "file", "richtext"];
@@ -7453,21 +7596,21 @@ function base44Prefix(app) {
7453
7596
  const runs = app.match(/[A-Za-z0-9]+/g) ?? [];
7454
7597
  return `Himi${runs.map((r) => r.charAt(0).toUpperCase() + r.slice(1)).join("")}`;
7455
7598
  }
7456
- function nonEmpty(value) {
7599
+ function nonEmpty2(value) {
7457
7600
  return typeof value === "string" && value.trim() !== "";
7458
7601
  }
7459
7602
  function isAdoptedEntity(spec) {
7460
- return nonEmpty(spec.base44Name);
7603
+ return nonEmpty2(spec.base44Name);
7461
7604
  }
7462
7605
  function physicalEntityName(spec, app) {
7463
7606
  if (isAdoptedEntity(spec)) return spec.base44Name;
7464
- return nonEmpty(spec.name) ? `${base44Prefix(app)}${spec.name}` : "";
7607
+ return nonEmpty2(spec.name) ? `${base44Prefix(app)}${spec.name}` : "";
7465
7608
  }
7466
7609
  var ENTITY_NAME = /^[A-Za-z][A-Za-z0-9]*$/;
7467
7610
  var FUNCTION_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
7468
7611
  function label(spec) {
7469
- if (nonEmpty(spec.base44Name)) return spec.base44Name;
7470
- if (nonEmpty(spec.name)) return spec.name;
7612
+ if (nonEmpty2(spec.base44Name)) return spec.base44Name;
7613
+ if (nonEmpty2(spec.name)) return spec.name;
7471
7614
  return "<unnamed>";
7472
7615
  }
7473
7616
  function userScoped(rule) {
@@ -8035,6 +8178,27 @@ function validateConfigShape(config) {
8035
8178
  validateLadderConfig(config);
8036
8179
  validateAuthGateScreen(config.auth);
8037
8180
  validateAppInfoConfig(config.appInfo);
8181
+ if (config.legacyImport !== void 0) {
8182
+ validateLegacyImport(config.legacyImport);
8183
+ const providerId = config.auth?.providerId?.trim() ?? "";
8184
+ if (providerId === "" || providerId === "none") {
8185
+ const scoped = config.legacyImport.map.findIndex((r) => r.to.sink !== "installationId" && r.to.sink !== "drop");
8186
+ if (scoped >= 0) throw new Error(`defineApp: legacyImport.map[${scoped}].to.sink: "${config.legacyImport.map[scoped].to.sink}" is applied only to a signed-in principal, and this app has no auth provider (auth.providerId "${providerId || "(none)"}")`);
8187
+ if (config.legacyImport.unmapped === "report") throw new Error(`defineApp: legacyImport.unmapped: "report" is applied only to a signed-in principal, and this app has no auth provider \u2014 use "drop"`);
8188
+ }
8189
+ const principalScoped = config.legacyImport.map.some((r) => r.to.sink !== "installationId" && r.to.sink !== "drop") || config.legacyImport.unmapped === "report";
8190
+ if (principalScoped && config.legacyImport.principal === void 0) {
8191
+ throw new Error(`defineApp: legacyImport.principal: required while the import has principal-scoped sinks \u2014 no auth provider adopts a legacy session yet (#4655), so without it nothing would ever be applied`);
8192
+ }
8193
+ if (config.dataSchema) {
8194
+ const declared = new Set(config.dataSchema.entities.map((e) => e.name));
8195
+ config.legacyImport.map.forEach((r, i) => {
8196
+ if (r.to.sink === "localDatabase" && !declared.has(r.to.entity)) {
8197
+ throw new Error(`defineApp: legacyImport.map[${i}].to.entity: "${r.to.entity}" is not declared in dataSchema.entities (${[...declared].map((n) => JSON.stringify(n)).join(", ") || "none"})`);
8198
+ }
8199
+ });
8200
+ }
8201
+ }
8038
8202
  const appBundleConflict = appLogicBundleConflict(config);
8039
8203
  if (appBundleConflict) throw new Error(`defineApp: ${appBundleConflict}`);
8040
8204
  if (config.tier5Cap) {
@@ -8403,7 +8567,7 @@ function tonalElevationAlpha(level) {
8403
8567
  var BUTTON_SIZES = ["sm", "md", "lg"];
8404
8568
  var BUTTON_MIN_HIT_TARGET = 44;
8405
8569
  var nonNegative = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : void 0;
8406
- var nonEmpty2 = (v) => typeof v === "string" && v !== "" ? v : void 0;
8570
+ var nonEmpty3 = (v) => typeof v === "string" && v !== "" ? v : void 0;
8407
8571
  var own = (o, k) => o && typeof o === "object" && Object.prototype.hasOwnProperty.call(o, k) ? o[k] : void 0;
8408
8572
  function resolveButtonTokens(tokens, size, style) {
8409
8573
  const button = own(own(tokens, "controls"), "button");
@@ -8417,12 +8581,12 @@ function resolveButtonTokens(tokens, size, style) {
8417
8581
  set("height", nonNegative(own(s, "height")));
8418
8582
  set("paddingH", nonNegative(own(s, "paddingH")));
8419
8583
  set("paddingV", nonNegative(own(s, "paddingV")));
8420
- set("text", nonEmpty2(own(s, "text")));
8584
+ set("text", nonEmpty3(own(s, "text")));
8421
8585
  set("icon", nonNegative(own(s, "icon")));
8422
8586
  set("radius", nonNegative(own(v, "radius")) ?? nonNegative(own(s, "radius")));
8423
- set("fill", nonEmpty2(own(v, "fill")));
8424
- set("label", nonEmpty2(own(v, "label")));
8425
- set("border", nonEmpty2(own(v, "border")));
8587
+ set("fill", nonEmpty3(own(v, "fill")));
8588
+ set("label", nonEmpty3(own(v, "label")));
8589
+ set("border", nonEmpty3(own(v, "border")));
8426
8590
  set("borderWidth", nonNegative(own(v, "borderWidth")));
8427
8591
  return out;
8428
8592
  }
@@ -10153,16 +10317,16 @@ function shouldRevealError(args) {
10153
10317
  return args.touched && !args.focused;
10154
10318
  }
10155
10319
  }
10156
- var nonEmpty3 = (type) => (v) => typeof v === "string" && v.length > 0 && isValid({ type }, v);
10320
+ var nonEmpty4 = (type) => (v) => typeof v === "string" && v.length > 0 && isValid({ type }, v);
10157
10321
  var validators = {
10158
10322
  // validates: these are top-level CALLS, which esbuild otherwise has to assume
10159
10323
  // might have side effects — and keeping them retained `validate` and every
10160
10324
  // predicate behind it, DOUBLING a Tier-5 bundle that does no validation at all.
10161
- email: /* @__PURE__ */ nonEmpty3("email"),
10162
- phone: /* @__PURE__ */ nonEmpty3("phone"),
10163
- url: /* @__PURE__ */ nonEmpty3("url"),
10164
- number: /* @__PURE__ */ nonEmpty3("number"),
10165
- integer: /* @__PURE__ */ nonEmpty3("integer")
10325
+ email: /* @__PURE__ */ nonEmpty4("email"),
10326
+ phone: /* @__PURE__ */ nonEmpty4("phone"),
10327
+ url: /* @__PURE__ */ nonEmpty4("url"),
10328
+ number: /* @__PURE__ */ nonEmpty4("number"),
10329
+ integer: /* @__PURE__ */ nonEmpty4("integer")
10166
10330
  };
10167
10331
  function validateAll(rules, values, catalog) {
10168
10332
  const errors = {};
@@ -14989,6 +15153,8 @@ export {
14989
15153
  IDIOM_CONTEXTS,
14990
15154
  LAUNCH_MANIFEST_SCHEMA,
14991
15155
  LAUNCH_NAMESPACE,
15156
+ LEGACY_IMPORT_SINKS,
15157
+ LEGACY_IMPORT_SOURCE_KINDS,
14992
15158
  LINK_MOUNT_PATHS,
14993
15159
  LOCALE_NATIVE_NAMES,
14994
15160
  LOCALE_SYSTEM,
@@ -15049,6 +15215,7 @@ export {
15049
15215
  appServicesAllowed,
15050
15216
  assertSiteShellConfig,
15051
15217
  availableLocales,
15218
+ bakeLegacyImport,
15052
15219
  baselineMediaCapabilities,
15053
15220
  bucket,
15054
15221
  buildHimiPreviewUrl,
@@ -15102,6 +15269,7 @@ export {
15102
15269
  isWidgetFamilySurface,
15103
15270
  isWixAbsoluteCachePrefix,
15104
15271
  layoutDirection,
15272
+ legacyImportProblems,
15105
15273
  localeChoiceSource,
15106
15274
  mergeIdiomOverlay,
15107
15275
  mergeSiteMenu,
@@ -0,0 +1,40 @@
1
+ // ../../core/sdk/dispatch/src/index.ts
2
+ function dispatch(handlerId, params, _options) {
3
+ const himalaya = globalThis.himalaya;
4
+ if (!himalaya) {
5
+ return Promise.reject(
6
+ new Error("@himalaya/dispatch: called outside a Himalaya runtime. This bundle must run inside a JSWorker (Tier 5).")
7
+ );
8
+ }
9
+ const stringParams = {};
10
+ if (params) {
11
+ for (const [k, v] of Object.entries(params)) stringParams[k] = String(v);
12
+ }
13
+ return himalaya.dispatch(handlerId, stringParams);
14
+ }
15
+
16
+ // ../../core/sdk/legacy-import/src/index.ts
17
+ function asReport(v) {
18
+ if (!v || typeof v !== "object") return null;
19
+ const r = v;
20
+ if (typeof r.id !== "string" || !Array.isArray(r.items) || !Array.isArray(r.sources)) return null;
21
+ return {
22
+ id: r.id,
23
+ extractedAt: typeof r.extractedAt === "number" ? r.extractedAt : 0,
24
+ sources: r.sources.filter((s) => !!s && typeof s === "object" && typeof s.id === "string"),
25
+ items: r.items.filter((i) => !!i && typeof i === "object" && typeof i.key === "string")
26
+ };
27
+ }
28
+ async function read() {
29
+ return asReport(await dispatch("capability.legacy_import.read"));
30
+ }
31
+ async function ack() {
32
+ await dispatch("capability.legacy_import.ack");
33
+ }
34
+ var version = 1;
35
+ export {
36
+ ack,
37
+ read,
38
+ version
39
+ };
40
+ //# sourceMappingURL=legacy-import.mjs.map
@@ -33,6 +33,7 @@ var CAPABILITY_REGISTRY = {
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
35
35
  "keyboard": ["dismiss"],
36
+ "legacy_import": ["ack", "read"],
36
37
  "live_activity": ["end", "start", "update"],
37
38
  "local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
38
39
  "location": ["backgroundStart", "backgroundStop", "getCurrent", "getPermissionStatus", "regionAdd", "regionClear", "regionList", "regionNext", "regionRemove", "regionSupport", "requestPermission", "watchNext", "watchStart", "watchStop"],
@@ -33,6 +33,7 @@ var CAPABILITY_REGISTRY = {
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
35
35
  "keyboard": ["dismiss"],
36
+ "legacy_import": ["ack", "read"],
36
37
  "live_activity": ["end", "start", "update"],
37
38
  "local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
38
39
  "location": ["backgroundStart", "backgroundStop", "getCurrent", "getPermissionStatus", "regionAdd", "regionClear", "regionList", "regionNext", "regionRemove", "regionSupport", "requestPermission", "watchNext", "watchStart", "watchStop"],
@@ -33,6 +33,7 @@ var CAPABILITY_REGISTRY = {
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
35
35
  "keyboard": ["dismiss"],
36
+ "legacy_import": ["ack", "read"],
36
37
  "live_activity": ["end", "start", "update"],
37
38
  "local_database": ["availability", "count", "get", "getAll", "purge", "query", "queueDepth", "queueDrain", "queueEnqueue", "remove", "upsert"],
38
39
  "location": ["backgroundStart", "backgroundStop", "getCurrent", "getPermissionStatus", "regionAdd", "regionClear", "regionList", "regionNext", "regionRemove", "regionSupport", "requestPermission", "watchNext", "watchStart", "watchStop"],