@lingxia/types 0.15.0 → 0.16.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 (47) hide show
  1. package/dist/automation/index.d.ts +15 -1
  2. package/dist/automation/index.d.ts.map +1 -1
  3. package/dist/error.d.ts +4 -3
  4. package/dist/error.d.ts.map +1 -1
  5. package/dist/error.js +2 -2
  6. package/dist/error.js.map +1 -1
  7. package/dist/esm/automation/index.js +12 -0
  8. package/dist/esm/automation/index.js.map +1 -0
  9. package/dist/esm/error.js +148 -0
  10. package/dist/esm/error.js.map +1 -0
  11. package/dist/esm/generated/error.js +44 -0
  12. package/dist/esm/generated/error.js.map +1 -0
  13. package/dist/esm/generated/i18n.js +167 -0
  14. package/dist/esm/generated/i18n.js.map +1 -0
  15. package/dist/esm/generated/logic.js +4 -0
  16. package/dist/esm/generated/logic.js.map +1 -0
  17. package/dist/esm/index.js +11 -0
  18. package/dist/esm/index.js.map +1 -0
  19. package/dist/esm/package.json +4 -0
  20. package/dist/esm/process.js +9 -0
  21. package/dist/esm/process.js.map +1 -0
  22. package/dist/{testing/public-api.mjs → esm/testing/public-api.js} +79 -20
  23. package/dist/esm/testing/public-api.js.map +1 -0
  24. package/dist/generated/error.d.ts +1 -1
  25. package/dist/generated/error.d.ts.map +1 -1
  26. package/dist/generated/logic-web.d.ts +124 -0
  27. package/dist/generated/logic.d.ts +320 -142
  28. package/dist/generated/logic.d.ts.map +1 -1
  29. package/dist/index.d.ts +20 -10
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +5 -6
  32. package/dist/index.js.map +1 -1
  33. package/dist/process.d.ts +2 -2
  34. package/dist/process.js +2 -2
  35. package/dist/testing/public-api.d.ts +66 -15
  36. package/dist/testing/public-api.d.ts.map +1 -1
  37. package/dist/testing/public-api.js +78 -20
  38. package/dist/testing/public-api.js.map +1 -1
  39. package/package.json +9 -93
  40. package/src/automation/index.ts +17 -1
  41. package/src/error.ts +4 -3
  42. package/src/generated/error.ts +1 -1
  43. package/src/generated/logic-web.d.ts +124 -0
  44. package/src/generated/logic.ts +348 -150
  45. package/src/index.ts +32 -11
  46. package/src/process.ts +2 -2
  47. package/src/testing/public-api.ts +90 -20
@@ -8,8 +8,46 @@ export interface PageConfig<TData extends Record<string, unknown> = Record<strin
8
8
  onHide?: () => void | Promise<void>;
9
9
  onUnload?: () => void | Promise<void>;
10
10
  onPullDownRefresh?: () => void | Promise<void>;
11
- [key: string]: unknown;
12
11
  }
12
+ /** Lifecycle hook names a `Page({...})` config may declare. */
13
+ export type PageLifecycleName = Exclude<keyof PageConfig, 'data'>;
14
+ /** Lifecycle hook names an `App({...})` config may declare. */
15
+ export type AppLifecycleName = Exclude<keyof AppConfig, 'globalData'>;
16
+ /**
17
+ * What a key that differs from a lifecycle hook only in case resolves to, so
18
+ * the compiler names the mistake instead of silently accepting a new method.
19
+ */
20
+ export type MisspelledLifecycle<K extends string> = {
21
+ 'LingXia type error': `'${K}' differs only in case from a lifecycle hook`;
22
+ };
23
+ /**
24
+ * Applied to the custom half of a `Page`/`App` config. `onload` and `onShow`
25
+ * are one keystroke apart from real hooks and the runtime would simply never
26
+ * call the misspelling, so the closest case-insensitive match is rejected.
27
+ * Genuinely different names stay ordinary methods.
28
+ */
29
+ export type NoLifecycleTypos<TCustom, TNames extends string> = {
30
+ [K in keyof TCustom]: K extends TNames ? TCustom[K] : Lowercase<K & string> extends Lowercase<TNames> ? MisspelledLifecycle<K & string> : TCustom[K];
31
+ };
32
+ /**
33
+ * A `setData` key that addresses inside `data` — `'a.b'` or `'rows[0].name'`.
34
+ * Values behind a path stay `unknown`: the runtime resolves the path, so the
35
+ * type cannot.
36
+ */
37
+ export type PageDataPath = `${string}.${string}` | `${string}[${number}]${string}`;
38
+ /**
39
+ * A field initialized to `null` or `[]` states nothing about what will fill it
40
+ * later, so it stays open. Annotate it (`null as Profile | null`) to have the
41
+ * fill checked.
42
+ */
43
+ export type LazyInitField<T> = [T] extends [null | undefined] ? unknown : [T] extends [never[]] ? unknown[] : T;
44
+ /**
45
+ * Top-level keys are checked against `data`; only path-shaped keys stay open.
46
+ * A misspelled or wrongly typed top-level key is a compile error.
47
+ */
48
+ export type SetDataPatch<TData> = {
49
+ [K in keyof TData]?: LazyInitField<TData[K]>;
50
+ } & Partial<Record<PageDataPath, unknown>>;
13
51
  export interface PageInstance<TData extends Record<string, unknown> = Record<string, unknown>> {
14
52
  data: TData;
15
53
  route: string;
@@ -22,7 +60,7 @@ export interface PageInstance<TData extends Record<string, unknown> = Record<str
22
60
  * Available when this page was opened by `lx.navigateTo(...)`.
23
61
  */
24
62
  opener?: PageMessagePort;
25
- setData(data: Partial<TData> | Record<string, unknown>, callback?: () => void): void;
63
+ setData(data: SetDataPatch<TData>, callback?: () => void): void;
26
64
  }
27
65
  /**
28
66
  * Injected by the runtime into methods listed in `stream_handlers` page metadata.
@@ -62,8 +100,8 @@ export interface ChannelHandle<TSend = unknown, TReceive = unknown> {
62
100
  *
63
101
  * - `app`: app-owned temporary output, or durable `lx://userdata` output when
64
102
  * `filePath` is set
65
- * - `downloads`: user-visible system Downloads output, requiring
66
- * `security.privileges: ["downloads"]` in `lxapp.json`
103
+ * - `downloads`: user-visible system Downloads output, requiring a host
104
+ * privilege grant and a native Downloads grant
67
105
  *
68
106
  * Default: `app`.
69
107
  */
@@ -95,18 +133,46 @@ export interface DownloadTask<TDownloadResult extends DownloadResult = DownloadR
95
133
  wait(): Promise<TDownloadResult>;
96
134
  }
97
135
  declare global {
136
+ /**
137
+ * The lxapp's configured page names, one key per page.
138
+ *
139
+ * Empty here on purpose. `lingxia dev` / `lingxia build` generates the
140
+ * project's own names into this interface; until then `ConfiguredPageName`
141
+ * stays `string` and every navigation call compiles exactly as before.
142
+ */
143
+ interface LxAppPages {
144
+ }
98
145
  interface HostAppApi {
99
146
  /**
100
- * The build environment from `app.json::envVersion`. It is fixed at boot
101
- * and defaults to `release` for older artifacts.
147
+ * The host deployment environment from `app.json::env` (`dev` | `prod`).
148
+ * It is fixed at boot and defaults to `prod` for older artifacts.
149
+ * Not the lxapp publish channel (`release` | `preview` | `draft`).
102
150
  */
103
- readonly envVersion: HostAppEnvVersion;
151
+ readonly env: HostAppEnv;
104
152
  /**
105
153
  * Launch-at-startup control. Absent where the host cannot register a
106
154
  * startup item; its presence and `lx.supports({ capability: 'autostart' })` always
107
155
  * agree, so `lx.app.autostart?.…` and the query are interchangeable.
108
156
  */
109
157
  autostart?: AutostartApi;
158
+ /** The language this lxapp renders in. Every lxapp follows it. */
159
+ readonly displayLanguage: DisplayLanguageApi;
160
+ /** The light/dark scheme this lxapp renders in. */
161
+ readonly appearance: AppearanceApi;
162
+ /**
163
+ * Product-wide settings, and their single writer. Present only in the
164
+ * Control app the host sealed at build time; its presence and
165
+ * `lx.supports({ capability: 'control' })` always agree, so
166
+ * `lx.app.control?.…` and the query are interchangeable.
167
+ */
168
+ readonly control?: ControlApi;
169
+ /**
170
+ * Product-wide cache reporting and clearing for a settings screen.
171
+ * Present only in the Control app; its presence and
172
+ * `lx.supports({ capability: 'control' })` always agree, so
173
+ * `lx.app.cache?.…` and the query are interchangeable.
174
+ */
175
+ cache?: AppCacheApi;
110
176
  }
111
177
  /** Runtime environment constants backed by abstract `lx://` paths. */
112
178
  interface LxEnv {
@@ -156,6 +222,7 @@ type StorageEntry<S extends object> = {
156
222
  export type TypedStorage<S extends object> = {
157
223
  get<K extends StorageKey<S>>(key: K): Promise<S[K] | undefined>;
158
224
  set(...entry: StorageEntry<S>): Promise<void>;
225
+ has(key: StorageKey<S>): Promise<boolean>;
159
226
  delete(key: StorageKey<S>): Promise<void>;
160
227
  clear(): Promise<void>;
161
228
  list(prefix?: string): Promise<string[]>;
@@ -172,13 +239,36 @@ export type ActionSheetResult = {
172
239
  } | CanceledResult;
173
240
  /** Every surface handle, narrowable by `kind`. */
174
241
  export type AnySurface = PageSurface | DeclaredSurface | AppSurface | TabSurface | BuiltinSurface;
242
+ /**
243
+ * The product-wide cache a settings screen reports and clears.
244
+ * App-scoped, not lxapp-scoped: the figure covers every lxapp the host
245
+ * has run. Injected only into the Control app, same gate as
246
+ * `lx.app.control` — guests do not have the member.
247
+ */
248
+ export type AppCacheApi = {
249
+ /** Estimated reclaimable managed bytes; excludes live session storage and WebView cache. */
250
+ size(): Promise<number>;
251
+ /**
252
+ * Clear reclaimable host caches. Control app only. Live session usercache and
253
+ * temp are preserved, including the caller's. Does not restart any lxapp.
254
+ * Userdata, KV, Downloads, cookies, valid installs and host components survive.
255
+ * Per-category failures are reported; setup/worker failures reject the call.
256
+ */
257
+ clear(): Promise<{
258
+ /** Estimated file bytes successfully removed; excludes WebView cache. */
259
+ freedBytes: number;
260
+ /** Protected usercache/session paths skipped, not a count of apps. */
261
+ skippedActivePaths: number;
262
+ webview: 'cleared' | 'unsupported' | 'failed';
263
+ failures: string[];
264
+ }>;
265
+ };
175
266
  export type AppConfig = {
176
267
  globalData?: Record<string, unknown>;
177
268
  onLaunch?: (options?: AppLaunchOptions) => void | Promise<void>;
178
269
  onShow?: (args?: AppLifecycleEventArgs) => void | Promise<void>;
179
270
  onHide?: (args?: AppLifecycleEventArgs) => void | Promise<void>;
180
271
  onUserCaptureScreen?: () => void | Promise<void>;
181
- [key: string]: unknown;
182
272
  };
183
273
  /** Runtime-managed app download path, usually under `lx://userdata`. */
184
274
  export type AppDownloadFilePath = string & {
@@ -224,15 +314,32 @@ export type AppInstance = AppConfig & {
224
314
  export type AppLaunchOptions = {
225
315
  path?: string;
226
316
  query?: Record<string, string>;
227
- scene?: number;
317
+ /** `8003` = AppLink (cold: onLaunch; warm: onShow). */
318
+ scene?: AppLaunchScene;
319
+ /**
320
+ * Inbound link exactly as the OS delivered it, fragment included. Present
321
+ * only with `scene: 8003`. Untrusted: route from an allowlist of paths.
322
+ */
323
+ url?: string;
228
324
  referrerInfo?: {
229
325
  appId?: string;
230
326
  extraData?: Record<string, unknown>;
231
327
  };
232
328
  };
329
+ /**
330
+ * Launch scene. `8003` is AppLink (cold: `onLaunch`; warm: `onShow`).
331
+ * Other numeric scenes stay valid; completion offers `8003`.
332
+ */
333
+ export type AppLaunchScene = 8003 | (number & {});
233
334
  export type AppLifecycleEventArgs = {
234
335
  source: 'host' | 'lxapp';
235
336
  reason: 'foreground' | 'background' | 'screenshot' | 'open' | 'close' | 'switch_back' | 'switch_away';
337
+ path?: string;
338
+ query?: Record<string, string>;
339
+ /** `8003` = AppLink. */
340
+ scene?: AppLaunchScene;
341
+ /** Inbound link, present only with `scene: 8003`. */
342
+ url?: string;
236
343
  };
237
344
  export type AppScreenshotOptions = {
238
345
  /**
@@ -254,7 +361,25 @@ export type AppSurface = SurfaceBase & SurfaceShowable & {
254
361
  readonly kind: 'app';
255
362
  readonly realized: 'main' | 'aside';
256
363
  };
257
- export type AppearanceApi = globalThis.AppearanceApi;
364
+ /** `lx.app.appearance` — the scheme this lxapp renders in. */
365
+ export type AppearanceApi = {
366
+ /**
367
+ * The scheme this lxapp is rendering in. An lxapp that pinned one in its
368
+ * `lxapp.json` reports that; every other lxapp reports the product's.
369
+ */
370
+ get(): ResolvedAppearance;
371
+ /**
372
+ * Follow it, starting with the current value. Returns an unsubscribe.
373
+ *
374
+ * The first callback runs synchronously, before `watch` returns, so the
375
+ * unsubscribe is not yet bound inside it.
376
+ */
377
+ watch(callback: (resolved: ResolvedAppearance) => void): () => void;
378
+ };
379
+ /**
380
+ * What the product's light/dark scheme is set to. `'auto'` follows
381
+ * the system.
382
+ */
258
383
  export type AppearancePreference = 'auto' | 'light' | 'dark';
259
384
  /**
260
385
  * Launch-at-startup control for the host app.
@@ -272,8 +397,8 @@ export type AppearancePreference = 'auto' | 'light' | 'dark';
272
397
  * is called, so the decision stays with the user (typically a settings-page
273
398
  * toggle, default off).
274
399
  * Host-app-level capability: like `checkUpdate` and `screenshot`, the methods
275
- * are available only to the home lxapp; other lxapps receive a permission
276
- * error.
400
+ * are available only to the native-assigned Control app; other lxapps receive
401
+ * a permission error.
277
402
  */
278
403
  export type AutostartApi = {
279
404
  /**
@@ -294,11 +419,11 @@ export type AutostartApi = {
294
419
  export type BinaryFileData = ArrayBuffer | ArrayBufferView;
295
420
  /**
296
421
  * Built-in browser product page. Opening one requires
297
- * `capabilities.browser` and is restricted to the home lxapp.
422
+ * `capabilities.browser` and is restricted to the native-assigned Control app.
298
423
  */
299
- export type BuiltinShellPage = 'settings' | 'downloads';
424
+ export type BuiltinShellPage = 'downloads';
300
425
  /**
301
- * A host builtin page such as settings or downloads. The shell owns
426
+ * A host builtin page such as downloads. The shell owns
302
427
  * its lifetime and its visibility, so this handle reports identity:
303
428
  * there is no `show` / `hide`, and the inherited `close()` rejects
304
429
  * with `unsupported_placement`.
@@ -452,10 +577,68 @@ export type CompressVideoTask = PromiseLike<CompressVideoResult> & AsyncIterable
452
577
  cancel(): void;
453
578
  wait(): Promise<CompressVideoResult>;
454
579
  };
580
+ /**
581
+ * Configured page name from `lxapp.json` / `lingxia.yaml`. JavaScript
582
+ * navigation accepts only this name; full routes such as
583
+ * `/pages/home/index` are internal runtime details. Discover names
584
+ * with `lxdev lxapp pages`.
585
+ * Narrows to the project's own names once `lingxia dev` or
586
+ * `lingxia build` has generated them; plain `string` before that, so
587
+ * a project that never ran a build still compiles.
588
+ */
589
+ export type ConfiguredPageName = keyof LxAppPages extends never ? string : keyof LxAppPages;
455
590
  export type ConnectWifiOptions = {
456
591
  SSID: string;
457
592
  password?: string;
458
593
  };
594
+ /**
595
+ * `lx.app.control` — product-wide settings, and their single writer.
596
+ * Present only in the Control app. Bind it once rather than repeating
597
+ * `lx.app.control!`:
598
+ * ```js
599
+ * const control = lx.app.control;
600
+ * if (!control) return; // not the Control app
601
+ * await control.appearance.setPreference('dark');
602
+ * ```
603
+ */
604
+ export type ControlApi = {
605
+ readonly displayLanguage: ControlDisplayLanguageApi;
606
+ readonly appearance: ControlAppearanceApi;
607
+ };
608
+ /** `lx.app.control.appearance` — the product's own light/dark setting. */
609
+ export type ControlAppearanceApi = {
610
+ /** What the user chose for the whole product. */
611
+ getPreference(): AppearancePreference;
612
+ /**
613
+ * Pin the product to `'light'` or `'dark'`, or follow the system with
614
+ * `'auto'`. An lxapp that pinned a scheme in its manifest keeps it.
615
+ */
616
+ setPreference(preference: AppearancePreference): Promise<void>;
617
+ /**
618
+ * Follow the choice, not what it resolves to: a system flip under `'auto'`
619
+ * moves `lx.app.appearance.watch` and leaves this quiet. Starts with the
620
+ * current value; that first callback runs synchronously, before
621
+ * `watchPreference` returns.
622
+ */
623
+ watchPreference(callback: (preference: AppearancePreference) => void): () => void;
624
+ };
625
+ /**
626
+ * `lx.app.control.displayLanguage` — the preference behind that
627
+ * language, for the one surface that edits it.
628
+ */
629
+ export type ControlDisplayLanguageApi = {
630
+ /** What the user chose: `'auto'`, or a canonical BCP-47 tag. */
631
+ getPreference(): DisplayLanguagePreference;
632
+ /** Persist the product's language. Rejects a tag that is not valid BCP-47. */
633
+ setPreference(preference: DisplayLanguagePreference): Promise<void>;
634
+ /**
635
+ * Follow the choice, not what it resolves to: a system locale change under
636
+ * `'auto'` moves the language without moving the preference. Starts with
637
+ * the current value and returns an unsubscribe; that first callback runs
638
+ * synchronously, before `watchPreference` returns.
639
+ */
640
+ watchPreference(callback: (preference: DisplayLanguagePreference) => void): () => void;
641
+ };
459
642
  /** A surface declared by the host in `lingxia.yaml`. */
460
643
  export type DeclaredSurface = SurfaceBase & SurfaceShowable & {
461
644
  readonly kind: 'declared';
@@ -465,8 +648,33 @@ export type DeviceOrientation = "portrait" | "landscape";
465
648
  export type DeviceOrientationChangeEvent = {
466
649
  value: DeviceOrientation;
467
650
  };
468
- /** Host display-language setting. `"auto"` follows the system locale. */
469
- export type DisplayLanguageSetting = 'auto' | 'en-US' | 'zh-CN';
651
+ /** `lx.app.displayLanguage` — the language this lxapp renders in. */
652
+ export type DisplayLanguageApi = {
653
+ /**
654
+ * The language in effect right now, as a canonical BCP-47 tag. Map it to
655
+ * the catalogs this lxapp actually ships and fall back where it has none;
656
+ * that narrowing is yours, and is not a language setting of its own.
657
+ */
658
+ get(): string;
659
+ /**
660
+ * Follow the language, starting with the current value. Returns an
661
+ * unsubscribe.
662
+ *
663
+ * Logic needs this because the strings it hands to native chrome —
664
+ * navigation bar titles, tab bar labels, modal and action-sheet text — are
665
+ * the app's own, and nothing re-renders them on its behalf.
666
+ *
667
+ * The first callback runs synchronously, before `watch` returns, so the
668
+ * unsubscribe is not yet bound inside it.
669
+ */
670
+ watch(callback: (language: string) => void): () => void;
671
+ };
672
+ /**
673
+ * What the product's language is set to: `'auto'` follows the system,
674
+ * or any canonical BCP-47 tag. `string & {}` keeps `'auto'` in
675
+ * autocomplete while still accepting a tag.
676
+ */
677
+ export type DisplayLanguagePreference = 'auto' | (string & {});
470
678
  export type DownloadDestination = 'app' | 'downloads';
471
679
  export type DownloadOptionsBase = {
472
680
  /** HTTP(S) source URL. */
@@ -498,6 +706,12 @@ export type DownloadsDownloadResult = {
498
706
  mimeType?: string;
499
707
  size: number;
500
708
  };
709
+ /**
710
+ * Configured page name belonging to *another* lxapp. This app's own
711
+ * page union cannot check it, so it stays a plain string and the
712
+ * target runtime rejects a name it does not have.
713
+ */
714
+ export type ExternalPageName = string;
501
715
  export type ExtractVideoThumbnailOptions = {
502
716
  /**
503
717
  * Source video path or `lx://` URI.
@@ -594,15 +808,17 @@ export type GetVideoInfoOptions = {
594
808
  };
595
809
  export type HostAppApi = globalThis.HostAppApi;
596
810
  /**
597
- * Build-time environment version of the host app.
598
- * Surfaced via {@link HostAppApi.envVersion}. Mirrors the
599
- * `crates/lingxia-update::ReleaseType` enum and the `envVersion` field in the
600
- * generated `app.json`. Pre-envVersion app artifacts are treated as `'release'`.
601
- * Note: this is *separate* from `LxAppEnvVersion` in the navigator module,
602
- * which encodes lxapp release channels for cross-app navigation URLs —
603
- * same three names, different axis.
811
+ * Build-time deployment environment of the host app (`dev` | `prod`).
812
+ * Surfaced via {@link HostAppApi.env}. Taken from the `env` field in
813
+ * the generated `app.json`. Missing `env` is treated as `'prod'`.
814
+ * This is the host build axis: which server, package-id suffix, publish
815
+ * token, and self-update endpoint the host uses. It is **not** the
816
+ * lxapp publish channel (`LxAppEnvVersion` / `LxAppReleaseType`:
817
+ * `'release' | 'preview' | 'draft'`). Default channel is derived
818
+ * from env (`dev` → `draft`, `prod` → `release`) and can be
819
+ * overridden when opening an lxapp.
604
820
  */
605
- export type HostAppEnvVersion = 'developer' | 'preview' | 'release';
821
+ export type HostAppEnv = 'dev' | 'prod';
606
822
  export type HostAppUpdateApplyStage = 'download' | 'install';
607
823
  export type HostAppUpdateCheckResult = {
608
824
  hasUpdate: false;
@@ -656,6 +872,11 @@ export type HostAppUpdateTask = PromiseLike<HostAppUpdateResult> & AsyncIterable
656
872
  finally(onfinally?: (() => void) | null): Promise<HostAppUpdateResult>;
657
873
  wait(): Promise<HostAppUpdateResult>;
658
874
  };
875
+ /**
876
+ * Canonical platform-family label shared by `lx.app.getBaseInfo().os`
877
+ * and `lx.getDeviceInfo().osName`. `"unknown"` is a non-product build.
878
+ */
879
+ export type HostOs = 'iOS' | 'macOS' | 'Android' | 'Windows' | 'Harmony' | 'unknown';
659
880
  export type InstalledTerminalFont = {
660
881
  family: string;
661
882
  monospace: boolean;
@@ -678,11 +899,11 @@ export type KeyEvent = {
678
899
  repeat?: boolean;
679
900
  };
680
901
  export type KeyEventCallback = (event: KeyEvent) => void;
681
- export type LxAppEnvVersion = 'release' | 'preview' | 'developer';
902
+ export type LxAppEnvVersion = 'release' | 'preview' | 'draft';
682
903
  /** LxApp metadata APIs. */
683
- export type LxAppReleaseType = 'release' | 'preview' | 'developer';
904
+ export type LxAppReleaseType = 'release' | 'preview' | 'draft';
684
905
  /** Boolean capability names accepted by `lx.supports`. */
685
- export type LxCapabilityFlag = 'terminal' | 'autostart' | 'notifications' | 'browser' | 'proxy' | 'selfUpdate' | 'process' | 'appUse' | 'computerUse' | 'browserUse' | 'mediaCapture';
906
+ export type LxCapabilityFlag = 'control' | 'terminal' | 'autostart' | 'notifications' | 'browser' | 'proxy' | 'selfUpdate' | 'process' | 'appUse' | 'computerUse' | 'browserUse' | 'mediaCapture';
686
907
  /**
687
908
  * One capability question per call. The catalog is closed, so
688
909
  * completion enumerates it and a typo is a type error. `capability`
@@ -755,9 +976,13 @@ export type NavigateToAppOptions = {
755
976
  * open the target app's initial page. Full routes such as
756
977
  * `/pages/home/index` are not supported.
757
978
  */
758
- page?: string;
979
+ page?: ExternalPageName;
759
980
  query?: PageQuery;
760
- envVersion?: LxAppEnvVersion;
981
+ /**
982
+ * Lxapp publish channel. Defaults from the host env
983
+ * (`dev` → `draft`, `prod` → `release`).
984
+ */
985
+ channel?: LxAppEnvVersion;
761
986
  targetVersion?: string;
762
987
  };
763
988
  export type NavigateToOptions = PageTargetOptions;
@@ -832,7 +1057,7 @@ export type OpenPageShared = {
832
1057
  */
833
1058
  size?: OverlaySurfaceSize;
834
1059
  interaction?: SurfaceInteraction;
835
- query?: Record<string, unknown>;
1060
+ query?: PageQuery;
836
1061
  /** Caller-owned identity, for `lx.surface.get(key)` later. */
837
1062
  key?: string;
838
1063
  };
@@ -881,7 +1106,7 @@ export type PageSurface = SurfaceBase & SurfaceShowable & SurfaceMessaging & {
881
1106
  */
882
1107
  export type PageTargetOptions = {
883
1108
  /** Configured page name from `lingxia.yaml` / `lxapp.json`. */
884
- page: string;
1109
+ page: ConfiguredPageName;
885
1110
  query?: PageQuery;
886
1111
  };
887
1112
  export type PreviewMediaAdvance = 'manual' | 'next' | 'loop';
@@ -1009,7 +1234,11 @@ export type PreviewMediaSingleOptions = PreviewMediaSource & {
1009
1234
  export type PreviewMediaSource = {
1010
1235
  /**
1011
1236
  * Media source path.
1012
- * Recommended: `lx://` path (for example `lx://usercache/...`) or a sandbox-local path
1237
+ *
1238
+ * Accepts an `https://` (or `http://`) URL for a remote image or video —
1239
+ * the host loads it directly, so no prior `lx.downloadFile` is required,
1240
+ * and its domain must be permitted by the app's network policy — an
1241
+ * `lx://` path (for example `lx://usercache/...`), or a sandbox-local path
1013
1242
  * that can be resolved by runtime access rules.
1014
1243
  */
1015
1244
  path: string;
@@ -1132,8 +1361,8 @@ export type ShareTitleOptions = {
1132
1361
  title?: string;
1133
1362
  };
1134
1363
  /**
1135
- * App-owned host-shell chrome. Mutations are available only to the home
1136
- * lxapp's Logic context; other lxapps receive a permission error.
1364
+ * App-owned host-shell chrome. Mutations are available only to the
1365
+ * Control app's Logic context; other lxapps receive a permission error.
1137
1366
  */
1138
1367
  export type ShellApi = {
1139
1368
  /**
@@ -1144,7 +1373,7 @@ export type ShellApi = {
1144
1373
  sidebarActions: ShellSidebarActionsApi;
1145
1374
  /** Compose another lxapp into a shell slot. */
1146
1375
  openApp(appId: string, options: ShellOpenAppOptions): Promise<AppSurface>;
1147
- /** Open a host builtin page such as settings or downloads. */
1376
+ /** Open a host builtin page such as downloads. */
1148
1377
  openBuiltin(page: BuiltinShellPage): Promise<BuiltinSurface>;
1149
1378
  /**
1150
1379
  * Open a declared surface with shell privileges — the same declaration
@@ -1164,16 +1393,19 @@ export type ShellOpenAppOptions = {
1164
1393
  * Configured page name from the target lxapp's `lxapp.json`. Omit it to
1165
1394
  * open that app's initial page. Full page routes are not supported.
1166
1395
  */
1167
- page?: string;
1396
+ page?: ExternalPageName;
1168
1397
  query?: PageQuery;
1169
- /** Defaults to 'release'. */
1170
- envVersion?: LxAppEnvVersion;
1398
+ /**
1399
+ * Lxapp publish channel. Defaults from the host env
1400
+ * (`dev` → `draft`, `prod` → `release`).
1401
+ */
1402
+ channel?: LxAppEnvVersion;
1171
1403
  targetVersion?: string;
1172
1404
  /** Stable identity for `lx.surface.get(key)`. */
1173
1405
  key?: string;
1174
1406
  };
1175
1407
  /**
1176
- * The declared-surface options only the home lxapp may use.
1408
+ * The declared-surface options only the native-assigned Control app may use.
1177
1409
  * Creating an extra instance and overriding a placement both mutate
1178
1410
  * shared shell composition, so they live here and not on
1179
1411
  * `lx.surface.openDeclared` — which consumes a declaration exactly as
@@ -1268,7 +1500,7 @@ export type ShellSidebarActionUpdate = {
1268
1500
  disabled?: boolean;
1269
1501
  };
1270
1502
  /**
1271
- * Role and edge overrides the home lxapp may apply to a live declared
1503
+ * Role and edge overrides the native-assigned Control app may apply to a live declared
1272
1504
  * surface. A stable root rejects non-main roles.
1273
1505
  */
1274
1506
  export type ShellSurfacePatch = {
@@ -1312,6 +1544,12 @@ export type Storage = {
1312
1544
  */
1313
1545
  get<T = unknown>(key: string): Promise<T | undefined>;
1314
1546
  set(key: string, value: unknown): Promise<void>;
1547
+ /**
1548
+ * Resolves whether an exact key exists, without reading its value. Prefer
1549
+ * it over comparing `get` against `undefined`: presence is a key lookup,
1550
+ * while `get` also reads and deserializes the stored value.
1551
+ */
1552
+ has(key: string): Promise<boolean>;
1315
1553
  delete(key: string): Promise<void>;
1316
1554
  clear(): Promise<void>;
1317
1555
  /** Resolves every key, optionally filtered by prefix. */
@@ -1336,7 +1574,7 @@ export type StreamSourceOptions = {
1336
1574
  */
1337
1575
  export type SurfaceApi = {
1338
1576
  /** Open one of this lxapp's own pages as a float or a window. */
1339
- openPage(page: string, options?: OpenPageOptions): Promise<PageSurface>;
1577
+ openPage(page: ConfiguredPageName, options?: OpenPageOptions): Promise<PageSurface>;
1340
1578
  /** Open external content in the in-app browser. */
1341
1579
  openUrl(url: string, options?: OpenUrlOptions): Promise<TabSurface>;
1342
1580
  /**
@@ -1442,7 +1680,7 @@ export type SurfaceError = Error & {
1442
1680
  * `SurfaceError`, so no caller has to match on message text.
1443
1681
  */
1444
1682
  export type SurfaceErrorCode = /** The placement cannot be realized by this host build. */ 'unsupported_placement'
1445
- /** A privileged operation was called by an lxapp other than the home lxapp. */
1683
+ /** A privileged operation was called by an lxapp other than the native-assigned Control app. */
1446
1684
  | 'denied'
1447
1685
  /** No such declared surface, lxapp, or builtin page. */
1448
1686
  | 'not_declared'
@@ -1657,8 +1895,7 @@ export type TerminalSettingsSnapshot = {
1657
1895
  /** Resolved configuration after all valid layers. */
1658
1896
  value: TerminalSettingsValue;
1659
1897
  effective: {
1660
- /** Host appearance before applying terminal.theme.mode. */
1661
- systemAppearance: 'light' | 'dark';
1898
+ /** The scheme the product is in, and therefore the terminal too. */
1662
1899
  appearance: 'light' | 'dark';
1663
1900
  colorScheme: string | null;
1664
1901
  font: {
@@ -1677,9 +1914,11 @@ export type TerminalSettingsWarning = {
1677
1914
  code: 'invalidUserFile' | 'missingColorScheme';
1678
1915
  message: string;
1679
1916
  };
1680
- export type TerminalThemeMode = 'system' | 'light' | 'dark';
1917
+ /**
1918
+ * A light scheme and a dark one. Which is in use follows the
1919
+ * product's light/dark setting; the terminal has no switch of its own.
1920
+ */
1681
1921
  export type TerminalThemeSettings = {
1682
- mode: TerminalThemeMode;
1683
1922
  light: string;
1684
1923
  dark: string;
1685
1924
  };
@@ -1708,7 +1947,7 @@ export type UpdateFailedInfo = UpdateReadyInfo & {
1708
1947
  };
1709
1948
  /**
1710
1949
  * Callback-based updates for this lxapp's bundle. Available to every
1711
- * lxapp. To update the native host app, the home lxapp uses the
1950
+ * lxapp. To update the native host app, the Control app uses the
1712
1951
  * task-based `lx.app.checkUpdate()` API instead.
1713
1952
  */
1714
1953
  export type UpdateManager = {
@@ -1721,7 +1960,7 @@ export type UpdateManager = {
1721
1960
  export type UpdateReadyInfo = {
1722
1961
  version?: string;
1723
1962
  isForceUpdate?: boolean;
1724
- channel?: "release" | "preview" | "developer" | string;
1963
+ channel?: "release" | "preview" | "draft" | string;
1725
1964
  };
1726
1965
  export type UploadIteratorResult = {
1727
1966
  done: boolean;
@@ -1942,38 +2181,27 @@ export type WindowsTerminalInlineImageStatus = {
1942
2181
  bytes: number;
1943
2182
  };
1944
2183
  };
1945
- /** Host app base information. */
2184
+ /**
2185
+ * Host app identity. Everything here is fixed for the life of the process;
2186
+ * the language the app renders in is not, and lives on
2187
+ * `lx.app.displayLanguage`.
2188
+ */
1946
2189
  export interface AppBaseInfo {
1947
- /**
1948
- * Raw system locale, unaffected by a saved in-app language override.
1949
- * For the language the UI should actually render in, use
1950
- * `display_language` instead.
1951
- */
1952
- locale: string;
1953
- /**
1954
- * Effective display language: a saved user override when set, else
1955
- * `locale`. This is what native chrome and `lx.*` i18n strings follow.
1956
- */
1957
- displayLanguage: string;
1958
2190
  /**
1959
2191
  * Platform family: `"iOS"` / `"macOS"` / `"Android"` / `"Windows"` /
1960
2192
  * `"Harmony"`. Matches the View-side `usePlatform().os` value.
1961
2193
  */
1962
- os: string;
2194
+ os: HostOs;
1963
2195
  productName: string;
1964
2196
  version: string;
1965
2197
  SDKVersion: string;
1966
2198
  }
1967
- export interface AppearanceState {
1968
- preference: AppearancePreference;
1969
- resolved: ResolvedAppearance;
1970
- }
1971
2199
  /** Device info APIs. */
1972
2200
  export interface DeviceInfo {
1973
2201
  brand: string;
1974
2202
  model: string;
1975
2203
  marketName: string;
1976
- osName: string;
2204
+ osName: HostOs;
1977
2205
  osVersion: string;
1978
2206
  }
1979
2207
  export interface FileStats {
@@ -2012,7 +2240,7 @@ export interface LxAppInfo {
2012
2240
  appId: string;
2013
2241
  appName: string;
2014
2242
  version: string;
2015
- releaseType: LxAppReleaseType;
2243
+ channel: LxAppReleaseType;
2016
2244
  }
2017
2245
  export interface ScreenInfo {
2018
2246
  width: number;
@@ -2045,37 +2273,6 @@ export declare class DirEntry {
2045
2273
  readonly isDirectory: boolean;
2046
2274
  readonly isSymlink: boolean;
2047
2275
  }
2048
- export declare class JSMessagePort {
2049
- constructor();
2050
- static postMessage(payload: any): void;
2051
- static onMessage(handler: (...args: any[]) => any): (...args: any[]) => any;
2052
- }
2053
- export declare class JSSurface {
2054
- constructor();
2055
- close(): Promise<void>;
2056
- postMessage(payload: any): void;
2057
- onMessage(handler: (...args: any[]) => any): (...args: any[]) => any;
2058
- static onClose(handler: (...args: any[]) => any): (...args: any[]) => any;
2059
- }
2060
- export declare class JSUpdateManager {
2061
- constructor();
2062
- /** Apply update by restarting the app */
2063
- applyUpdate(): void;
2064
- /** Subscribes to a ready update and returns the unsubscribe fn. */
2065
- onUpdateReady(cb: (...args: any[]) => any): (...args: any[]) => any;
2066
- /** Subscribes to a failed update and returns the unsubscribe fn. */
2067
- onUpdateFailed(cb: (...args: any[]) => any): (...args: any[]) => any;
2068
- }
2069
- export declare class JSVideoContext {
2070
- constructor();
2071
- play(): void;
2072
- pause(): void;
2073
- stop(): void;
2074
- seek(position: number): void;
2075
- requestFullScreen(): void;
2076
- exitFullScreen(): void;
2077
- setStreamSource(options: StreamSourceOptions): void;
2078
- }
2079
2276
  export declare class LxFile {
2080
2277
  private constructor();
2081
2278
  /** The path supplied to `lx.fs.file`. */
@@ -2100,14 +2297,6 @@ export declare class LxFile {
2100
2297
  /** Read metadata for this managed path. */
2101
2298
  stat(): Promise<FileStats>;
2102
2299
  }
2103
- declare global {
2104
- interface AppearanceApi {
2105
- /** Read the appearance preference and the light/dark value it resolves to. */
2106
- get(): AppearanceState;
2107
- /** Set the appearance preference to `auto`, `light`, or `dark`. */
2108
- set(preference: AppearancePreference): Promise<void>;
2109
- }
2110
- }
2111
2300
  declare global {
2112
2301
  interface FileSystemApi {
2113
2302
  /**
@@ -2142,33 +2331,27 @@ declare global {
2142
2331
  * is what the user sees of the whole app — host-drawn navigation chrome,
2143
2332
  * native overlays, and every composited WebView, not just this lxapp's web
2144
2333
  * content. Because that view can include other lxapps' UI, the API is
2145
- * restricted to the home lxapp, like the other host-level APIs on `lx.app`.
2334
+ * restricted to the Control app, like the other host-level APIs on `lx.app`.
2146
2335
  */
2147
2336
  screenshot(options?: AppScreenshotOptions): Promise<AppScreenshotResult>;
2148
2337
  /**
2149
2338
  * Check whether the host app has an update.
2150
- * This host-level capability is restricted to the home lxapp. Calling it opts
2339
+ * This host-level capability is restricted to the Control app. Calling it opts
2151
2340
  * the process into custom update handling. Incompatible updates are hidden as
2152
2341
  * `hasUpdate: false`; platforms that cannot apply a package may still return
2153
2342
  * metadata and reject when `update.apply()` is invoked.
2154
2343
  */
2155
2344
  checkUpdate(): Promise<HostAppUpdateCheckResult>;
2156
- readonly envVersion: HostAppEnvVersion;
2345
+ readonly env: HostAppEnv;
2157
2346
  /**
2158
- * Read the host app's identity: locale, display language, OS, product name,
2159
- * product version, and SDK runtime version.
2347
+ * Read the host app's identity: OS, product name, product version, and SDK
2348
+ * runtime version.
2160
2349
  */
2161
2350
  getBaseInfo(): AppBaseInfo;
2162
- /**
2163
- * Follow the host's effective display language.
2164
- * `getBaseInfo().displayLanguage` answers what it is now; this answers when it
2165
- * changes. Logic needs both because the strings it hands to native chrome —
2166
- * navigation bar titles, tab bar labels, modal and action-sheet text — are the
2167
- * app's own, and nothing re-renders them on its behalf.
2168
- */
2169
- onDisplayLanguageChange(callback: (language: string) => void): () => void;
2170
2351
  /**
2171
2352
  * Exit the host app immediately without a confirmation dialog.
2353
+ * Control app only: quitting the product is not an lxapp's decision. Other
2354
+ * lxapps get a permission error.
2172
2355
  * If the user should confirm first, call `lx.showModal(...)` and invoke this
2173
2356
  * only after confirmation.
2174
2357
  */
@@ -2176,16 +2359,11 @@ declare global {
2176
2359
  /**
2177
2360
  * Set the app-icon badge, for example an unread count.
2178
2361
  * This targets the dock on macOS, taskbar on Windows, and home/launcher icon
2179
- * on mobile. Null or an empty string clears it. Unsupported platforms treat
2180
- * the call as a no-op.
2362
+ * on mobile — the product's own icon, not the calling lxapp's, so it is
2363
+ * Control app only and other lxapps get a permission error. Null or an empty
2364
+ * string clears it. Unsupported platforms treat the call as a no-op.
2181
2365
  */
2182
2366
  setBadge(value: string | number | null): void;
2183
- /**
2184
- * Set the host display language. `"auto"` follows the system locale;
2185
- * `"en-US"` and `"zh-CN"` pin the product. Every lxapp inherits the resolved
2186
- * tag from `getBaseInfo().displayLanguage`. Restricted to the home lxapp.
2187
- */
2188
- setDisplayLanguage(language: DisplayLanguageSetting): void;
2189
2367
  }
2190
2368
  }
2191
2369
  declare global {
@@ -2279,7 +2457,7 @@ declare global {
2279
2457
  onKeyUp(callback: KeyEventCallback): () => void;
2280
2458
  /** Get location function */
2281
2459
  getLocation(options?: GetLocationOptions): Promise<LocationInfo>;
2282
- /** Identify the running lxapp: its id, display name, version, and release type. */
2460
+ /** Identify the running lxapp: its id, display name, version, and channel. */
2283
2461
  getLxAppInfo(): LxAppInfo;
2284
2462
  /** Read an image's dimensions, type, and orientation without decoding it into a view. */
2285
2463
  getImageInfo(options: GetImageInfoOptions): Promise<ImageInfo>;
@@ -2374,7 +2552,6 @@ declare global {
2374
2552
  * an invalid selection.
2375
2553
  */
2376
2554
  showActionSheet(options: ShowActionSheetOptions): Promise<ActionSheetResult>;
2377
- readonly appearance: AppearanceApi;
2378
2555
  /**
2379
2556
  * Shows a confirmation modal.
2380
2557
  * Resolves `{ canceled: false }` when the user confirms and `{ canceled: true }`
@@ -2441,7 +2618,7 @@ declare global {
2441
2618
  readonly tray: TrayApi;
2442
2619
  /**
2443
2620
  * Return the callback-based update manager for this lxapp's bundle. This is
2444
- * available to every lxapp and is distinct from the home-only
2621
+ * available to every lxapp and is distinct from the Control-app-only
2445
2622
  * `lx.app.checkUpdate()`, which updates the native host app.
2446
2623
  */
2447
2624
  getUpdateManager(): UpdateManager;
@@ -2463,27 +2640,28 @@ declare global {
2463
2640
  interface ShellApi {
2464
2641
  /**
2465
2642
  * `lx.shell.openApp(appId, options)` — compose another lxapp into a shell
2466
- * slot. Home-lxapp only; the namespace is the privilege.
2643
+ * slot. Control-app only; the namespace is the privilege.
2467
2644
  */
2468
2645
  openApp(appId: string, options: ShellOpenAppOptions): Promise<AppSurface>;
2469
- /** `lx.shell.openBuiltin(page)` — a host builtin page. Home-lxapp only. */
2646
+ /** `lx.shell.openBuiltin(page)` — a host builtin page. Control-app only. */
2470
2647
  openBuiltin(page: BuiltinShellPage): Promise<BuiltinSurface>;
2471
2648
  /**
2472
2649
  * `lx.shell.openDeclared(id, options?)` — the declared surface, plus the
2473
- * keyed multi-instance form and placement overrides. Home-lxapp only.
2650
+ * keyed multi-instance form and placement overrides. Control-app only.
2474
2651
  */
2475
2652
  openDeclared(id: string, options?: ShellOpenDeclaredOptions): Promise<DeclaredSurface>;
2476
2653
  /** `lx.shell.reconfigure(id, patch)` — re-place a live declared surface. */
2477
2654
  reconfigure(id: string, patch: ShellSurfacePatch): Promise<void>;
2655
+ readonly sidebarActions: ShellSidebarActionsApi;
2478
2656
  }
2479
2657
  }
2480
2658
  declare global {
2481
2659
  interface ShellSidebarActionsApi {
2482
2660
  /**
2483
2661
  * Atomically replaces the complete desktop sidebar action declaration. Only the
2484
- * home lxapp may call this API. Ids must be non-empty and unique across both
2662
+ * Control app may call this API. Ids must be non-empty and unique across both
2485
2663
  * placements; header accepts at most two entries. Icons must be bundled relative
2486
- * paths or runtime-managed `lx://` paths accessible to the home lxapp.
2664
+ * paths or runtime-managed `lx://` paths accessible to the Control app.
2487
2665
  * Every entry is bound to its generation-scoped callback. The shell invokes that
2488
2666
  * callback but never infers navigation or selected state. Validation or host
2489
2667
  * projection failure leaves the previous generation active. `replace([])` clears
@@ -2493,21 +2671,21 @@ declare global {
2493
2671
  replace(items: ShellSidebarAction[]): void;
2494
2672
  /**
2495
2673
  * Atomically updates the icon, label, and/or disabled state of one stable id.
2496
- * Only the home lxapp may call this API. The patch must be non-empty; unknown
2674
+ * Only the Control app may call this API. The patch must be non-empty; unknown
2497
2675
  * fields are rejected. The callback and placement stay unchanged. Throws
2498
2676
  * `E_NOT_FOUND` when `id` is not in the current declaration.
2499
2677
  */
2500
2678
  update(id: string, patch: ShellSidebarActionUpdate): void;
2501
2679
  /**
2502
2680
  * Atomically removes one stable id and its generation-scoped callback. Only the
2503
- * home lxapp may call this API. Throws `E_NOT_FOUND` when `id` is not in the
2681
+ * Control app may call this API. Throws `E_NOT_FOUND` when `id` is not in the
2504
2682
  * current declaration.
2505
2683
  */
2506
2684
  remove(id: string): void;
2507
2685
  /**
2508
- * Atomically clears every runtime sidebar action and callback. Only the home
2509
- * lxapp may call this API. Equivalent to `replace([])` and safe when already
2510
- * empty; the home lxapp must still redeclare actions after the next Logic launch.
2686
+ * Atomically clears every runtime sidebar action and callback. Only the
2687
+ * Control app may call this API. Equivalent to `replace([])` and safe when already
2688
+ * empty; the Control app must still redeclare actions after the next Logic launch.
2511
2689
  */
2512
2690
  clear(): void;
2513
2691
  }
@@ -2519,7 +2697,7 @@ declare global {
2519
2697
  * float or a window. A page can never be an aside: asides carry external
2520
2698
  * content only, which is why that member does not exist on this signature.
2521
2699
  */
2522
- openPage(page: string, options?: OpenPageOptions): Promise<PageSurface>;
2700
+ openPage(page: ConfiguredPageName, options?: OpenPageOptions): Promise<PageSurface>;
2523
2701
  /**
2524
2702
  * `lx.surface.openUrl(url, options?)` — external content in the in-app
2525
2703
  * browser, as a tab or docked as an aside.