@lynxship/cli 0.1.19 → 0.1.21

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 (193) hide show
  1. package/README.md +66 -5
  2. package/dist/android/signing.d.ts +16 -0
  3. package/dist/android/signing.d.ts.map +1 -0
  4. package/dist/android/signing.js +131 -0
  5. package/dist/android/types.d.ts +12 -0
  6. package/dist/android/types.d.ts.map +1 -0
  7. package/dist/android/types.js +1 -0
  8. package/dist/android-build.d.ts +4 -13
  9. package/dist/android-build.d.ts.map +1 -1
  10. package/dist/android-build.js +14 -133
  11. package/dist/android-toolchain/inspection.d.ts +3 -0
  12. package/dist/android-toolchain/inspection.d.ts.map +1 -0
  13. package/dist/android-toolchain/inspection.js +122 -0
  14. package/dist/android-toolchain/probes.d.ts +23 -0
  15. package/dist/android-toolchain/probes.d.ts.map +1 -0
  16. package/dist/android-toolchain/probes.js +183 -0
  17. package/dist/android-toolchain/types.d.ts +20 -0
  18. package/dist/android-toolchain/types.d.ts.map +1 -0
  19. package/dist/android-toolchain/types.js +1 -0
  20. package/dist/android-toolchain.d.ts +4 -20
  21. package/dist/android-toolchain.d.ts.map +1 -1
  22. package/dist/android-toolchain.js +4 -300
  23. package/dist/app-config.d.ts +25 -0
  24. package/dist/app-config.d.ts.map +1 -0
  25. package/dist/app-config.js +106 -0
  26. package/dist/bundle-build.d.ts.map +1 -1
  27. package/dist/bundle-build.js +11 -0
  28. package/dist/cli.d.ts +3 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +66 -0
  31. package/dist/commands/build-execution.d.ts +41 -0
  32. package/dist/commands/build-execution.d.ts.map +1 -0
  33. package/dist/commands/build-execution.js +182 -0
  34. package/dist/commands/configuration.d.ts +19 -0
  35. package/dist/commands/configuration.d.ts.map +1 -0
  36. package/dist/commands/configuration.js +174 -0
  37. package/dist/commands/development.d.ts +22 -0
  38. package/dist/commands/development.d.ts.map +1 -0
  39. package/dist/commands/development.js +132 -0
  40. package/dist/commands/device.d.ts +3 -0
  41. package/dist/commands/device.d.ts.map +1 -0
  42. package/dist/commands/device.js +86 -0
  43. package/dist/commands/doctor.d.ts +18 -0
  44. package/dist/commands/doctor.d.ts.map +1 -0
  45. package/dist/commands/doctor.js +320 -0
  46. package/dist/commands/help.d.ts +2 -0
  47. package/dist/commands/help.d.ts.map +1 -0
  48. package/dist/commands/help.js +118 -0
  49. package/dist/commands/i18n.d.ts +14 -0
  50. package/dist/commands/i18n.d.ts.map +1 -0
  51. package/dist/commands/i18n.js +88 -0
  52. package/dist/commands/logs.d.ts +3 -0
  53. package/dist/commands/logs.d.ts.map +1 -0
  54. package/dist/commands/logs.js +51 -0
  55. package/dist/commands/metadata.d.ts +3 -0
  56. package/dist/commands/metadata.d.ts.map +1 -0
  57. package/dist/commands/metadata.js +45 -0
  58. package/dist/commands/ota.d.ts +28 -0
  59. package/dist/commands/ota.d.ts.map +1 -0
  60. package/dist/commands/ota.js +203 -0
  61. package/dist/commands/project.d.ts +14 -0
  62. package/dist/commands/project.d.ts.map +1 -0
  63. package/dist/commands/project.js +122 -0
  64. package/dist/commands/remote-build.d.ts +35 -0
  65. package/dist/commands/remote-build.d.ts.map +1 -0
  66. package/dist/commands/remote-build.js +73 -0
  67. package/dist/commands/submit.d.ts +27 -0
  68. package/dist/commands/submit.d.ts.map +1 -0
  69. package/dist/commands/submit.js +92 -0
  70. package/dist/ecosystem.d.ts +9 -0
  71. package/dist/ecosystem.d.ts.map +1 -0
  72. package/dist/ecosystem.js +95 -0
  73. package/dist/frameworks.d.ts.map +1 -1
  74. package/dist/frameworks.js +5 -1
  75. package/dist/guidance/catalog.d.ts +3 -0
  76. package/dist/guidance/catalog.d.ts.map +1 -0
  77. package/dist/guidance/catalog.js +504 -0
  78. package/dist/guidance/types.d.ts +10 -0
  79. package/dist/guidance/types.d.ts.map +1 -0
  80. package/dist/guidance/types.js +1 -0
  81. package/dist/guidance.d.ts +2 -9
  82. package/dist/guidance.d.ts.map +1 -1
  83. package/dist/guidance.js +1 -502
  84. package/dist/i18n/discovery.d.ts +14 -0
  85. package/dist/i18n/discovery.d.ts.map +1 -0
  86. package/dist/i18n/discovery.js +106 -0
  87. package/dist/i18n/plan.d.ts +12 -0
  88. package/dist/i18n/plan.d.ts.map +1 -0
  89. package/dist/i18n/plan.js +95 -0
  90. package/dist/i18n/setup.d.ts +11 -0
  91. package/dist/i18n/setup.d.ts.map +1 -0
  92. package/dist/i18n/setup.js +47 -0
  93. package/dist/i18n/types.d.ts +17 -0
  94. package/dist/i18n/types.d.ts.map +1 -0
  95. package/dist/i18n/types.js +1 -0
  96. package/dist/index.d.ts +1 -1
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +4 -2069
  99. package/dist/ios/assets.d.ts +19 -0
  100. package/dist/ios/assets.d.ts.map +1 -0
  101. package/dist/ios/assets.js +128 -0
  102. package/dist/ios/production-build.d.ts +6 -0
  103. package/dist/ios/production-build.d.ts.map +1 -0
  104. package/dist/ios/production-build.js +200 -0
  105. package/dist/ios/project.d.ts +4 -0
  106. package/dist/ios/project.d.ts.map +1 -0
  107. package/dist/ios/project.js +43 -0
  108. package/dist/ios/simulator-build.d.ts +8 -0
  109. package/dist/ios/simulator-build.d.ts.map +1 -0
  110. package/dist/ios/simulator-build.js +188 -0
  111. package/dist/ios/simulator.d.ts +5 -0
  112. package/dist/ios/simulator.d.ts.map +1 -0
  113. package/dist/ios/simulator.js +60 -0
  114. package/dist/ios/types.d.ts +14 -0
  115. package/dist/ios/types.d.ts.map +1 -0
  116. package/dist/ios/types.js +1 -0
  117. package/dist/ios-build.d.ts +4 -37
  118. package/dist/ios-build.d.ts.map +1 -1
  119. package/dist/ios-build.js +3 -575
  120. package/dist/ios-host.d.ts.map +1 -1
  121. package/dist/ios-toolchain/inspection.d.ts +4 -0
  122. package/dist/ios-toolchain/inspection.d.ts.map +1 -0
  123. package/dist/ios-toolchain/inspection.js +211 -0
  124. package/dist/ios-toolchain/probes.d.ts +24 -0
  125. package/dist/ios-toolchain/probes.d.ts.map +1 -0
  126. package/dist/ios-toolchain/probes.js +127 -0
  127. package/dist/ios-toolchain/types.d.ts +17 -0
  128. package/dist/ios-toolchain/types.d.ts.map +1 -0
  129. package/dist/ios-toolchain/types.js +1 -0
  130. package/dist/ios-toolchain.d.ts +3 -18
  131. package/dist/ios-toolchain.d.ts.map +1 -1
  132. package/dist/ios-toolchain.js +1 -333
  133. package/dist/plugins/contracts.d.ts +28 -0
  134. package/dist/plugins/contracts.d.ts.map +1 -0
  135. package/dist/plugins/contracts.js +1 -0
  136. package/dist/plugins/discovery.d.ts +19 -0
  137. package/dist/plugins/discovery.d.ts.map +1 -0
  138. package/dist/plugins/discovery.js +250 -0
  139. package/dist/plugins/native-operations.d.ts +28 -0
  140. package/dist/plugins/native-operations.d.ts.map +1 -0
  141. package/dist/plugins/native-operations.js +217 -0
  142. package/dist/plugins/operations.d.ts +9 -0
  143. package/dist/plugins/operations.d.ts.map +1 -0
  144. package/dist/plugins/operations.js +76 -0
  145. package/dist/plugins/validation.d.ts +9 -0
  146. package/dist/plugins/validation.d.ts.map +1 -0
  147. package/dist/plugins/validation.js +52 -0
  148. package/dist/plugins.d.ts +3 -34
  149. package/dist/plugins.d.ts.map +1 -1
  150. package/dist/plugins.js +2 -595
  151. package/dist/process-runner.d.ts +4 -0
  152. package/dist/process-runner.d.ts.map +1 -1
  153. package/dist/process-runner.js +14 -0
  154. package/dist/remote.d.ts +22 -1
  155. package/dist/remote.d.ts.map +1 -1
  156. package/dist/remote.js +141 -2
  157. package/dist/rspeedy-app-config.d.ts +4 -0
  158. package/dist/rspeedy-app-config.d.ts.map +1 -0
  159. package/dist/rspeedy-app-config.js +32 -0
  160. package/dist/runtime/args.d.ts +3 -0
  161. package/dist/runtime/args.d.ts.map +1 -0
  162. package/dist/runtime/args.js +11 -0
  163. package/dist/runtime/build-commands.d.ts +3 -0
  164. package/dist/runtime/build-commands.d.ts.map +1 -0
  165. package/dist/runtime/build-commands.js +282 -0
  166. package/dist/runtime/context.d.ts +63 -0
  167. package/dist/runtime/context.d.ts.map +1 -0
  168. package/dist/runtime/context.js +179 -0
  169. package/dist/runtime/early-commands.d.ts +4 -0
  170. package/dist/runtime/early-commands.d.ts.map +1 -0
  171. package/dist/runtime/early-commands.js +284 -0
  172. package/dist/runtime/project.d.ts +8 -0
  173. package/dist/runtime/project.d.ts.map +1 -0
  174. package/dist/runtime/project.js +38 -0
  175. package/dist/runtime/state.d.ts +47 -0
  176. package/dist/runtime/state.d.ts.map +1 -0
  177. package/dist/runtime/state.js +33 -0
  178. package/dist/secure-store/backends.d.ts +20 -0
  179. package/dist/secure-store/backends.d.ts.map +1 -0
  180. package/dist/secure-store/backends.js +248 -0
  181. package/dist/secure-store/types.d.ts +27 -0
  182. package/dist/secure-store/types.d.ts.map +1 -0
  183. package/dist/secure-store/types.js +1 -0
  184. package/dist/secure-store.d.ts +2 -26
  185. package/dist/secure-store.d.ts.map +1 -1
  186. package/dist/secure-store.js +3 -245
  187. package/dist/ui/components.d.ts.map +1 -1
  188. package/dist/ui/components.js +2 -1
  189. package/package.json +7 -4
  190. package/templates/android-host/app/build.gradle +1 -0
  191. package/templates/android-host/app/src/main/java/template/MainActivity.java +98 -3
  192. package/templates/ios-host/__IOS_TARGET_NAME__/DemoLynxProvider.swift +26 -16
  193. package/templates/ios-host/__IOS_TARGET_NAME__/ViewController.swift +107 -19
package/README.md CHANGED
@@ -11,6 +11,33 @@ expiring download URL with a compact terminal QR code.
11
11
  > native hosts; HarmonyOS requires the official Hvigor/DevEco host; Web and
12
12
  > Desktop require the project's official Rspeedy/Lynxtron configuration.
13
13
 
14
+ ## Sparkling-compatible app configuration
15
+
16
+ Projects may use the official Sparkling-style `app.config.ts` (or its JavaScript
17
+ variants) as the single Lynx build entrypoint:
18
+
19
+ ```ts
20
+ import { defineConfig } from "@lynx-js/rspeedy";
21
+
22
+ export default {
23
+ lynxConfig: defineConfig({
24
+ source: { entry: { main: "./src/pages/main/index.tsx" } },
25
+ environments: { lynx: {} },
26
+ }),
27
+ appName: "My Lynx app",
28
+ platform: { android: { packageName: "com.example.myapp" } },
29
+ paths: { android: "android/app/src/main/assets" },
30
+ };
31
+ ```
32
+
33
+ When `lynxship build` finds this file, it loads it only for the explicit build
34
+ operation, validates its routes/plugins and safe project-relative paths, then
35
+ calls the installed project's `createRspeedy` API with `lynxConfig`. Android
36
+ and iOS host generation also reuses the declared identifiers, name, icon and
37
+ asset paths. `lynxship.json` remains the place for LynxShip profiles, signing,
38
+ OTA and cloud settings; projects with a normal `lynx.config.*` keep their
39
+ existing package-manager build workflow.
40
+
14
41
  ## Install
15
42
 
16
43
  ```bash
@@ -25,6 +52,35 @@ npx @lynxship/cli@latest doctor --project-dir ./my-lynx-app
25
52
 
26
53
  The package exposes the `lynxship` executable.
27
54
 
55
+ ## Automatic i18n setup
56
+
57
+ For a Lynx project using i18next, the CLI can perform the repeatable setup in
58
+ one explicit, reviewable command:
59
+
60
+ ```bash
61
+ npx @lynxship/cli@latest init
62
+ npx @lynxship/cli@latest i18n setup --dry-run
63
+ npx @lynxship/cli@latest i18n setup
64
+ ```
65
+
66
+ The setup command detects the entry file and JSON locale catalog, installs
67
+ `@lynxship/i18n`, a compatible i18next major, the LynxShip device-storage
68
+ bridge and only the FormatJS polyfills needed by detected `Intl.*` usage. It
69
+ generates `src/lynxship/i18n-polyfills.ts` with static imports in dependency
70
+ order and adds one import to the detected entry file. Use `--intl all` when a
71
+ library accesses Intl dynamically, `--locales en,fr,ar` to override locale
72
+ discovery, or `--entry src/index.tsx` when the entry file is non-standard. The
73
+ command fails rather than guessing an ambiguous entry file.
74
+
75
+ The adapter restores the last resolved language automatically when the host
76
+ exposes `LynxShipDeviceStorage` (Android, iOS or another linked Lynx host), or
77
+ browser `localStorage` on Web. The lookup is local and best-effort; no network
78
+ request is made and a missing host bridge does not prevent the app from
79
+ starting. Projects with their own storage can inject the `persistence.storage`
80
+ contract. `--no-persistence` skips installation of the device-storage bridge.
81
+ Generated polyfills are static and recorded in the project lockfile: npm
82
+ cannot be downloaded silently from an application bundle at runtime.
83
+
28
84
  ## Plugin ecosystem
29
85
 
30
86
  Install a community plugin as a normal project dependency, list it in
@@ -273,7 +329,7 @@ autolink check Check Lynx native-library wiring
273
329
  autolink codegen Run native-module codegen
274
330
  ota doctor Check native OTA host integration
275
331
  storage configure Configure Cloudflare R2
276
- android host init Create a minimal official Lynx Android host
332
+ android host init Create an official Lynx Android host baseline
277
333
  android configure Configure Android signing
278
334
  store configure Configure store submission credentials
279
335
  ```
@@ -491,9 +547,12 @@ lynxship android host init --application-id com.example.myapp
491
547
 
492
548
  This command never overwrites an existing `android/` directory. It creates a
493
549
  real Gradle application with the official Lynx Android dependencies,
494
- `LynxEnv`, `LynxView`, a bundle loader and a Gradle wrapper. Replace the example
495
- application ID before a store release and add any project-specific native
496
- modules, permissions, services and OTA integration explicitly.
550
+ `LynxEnv`, `LynxView`, a bundle loader and a Gradle wrapper. The generated
551
+ Activity also provides lifecycle-aware loading/error feedback, tap-to-retry,
552
+ the official `onFirstScreen` readiness signal and explicit `LynxView.destroy()`
553
+ cleanup. Replace the example application ID before a store release and add
554
+ any project-specific native modules, permissions, services and OTA integration
555
+ explicitly.
497
556
 
498
557
  For a pure project that targets iOS, create the native Xcode/CocoaPods host
499
558
  with:
@@ -518,7 +577,9 @@ preview only; provide the project icon for an IPA or store release.
518
577
  The command refuses to overwrite an existing `ios/` directory and creates a
519
578
  Swift host based on Lynx's official integration shape: `LynxEnv`, `LynxView`,
520
579
  `LynxTemplateProvider`, `Podfile`, `ExportOptions.plist` and a bundle sync
521
- script. On macOS, `lynxship build --platform ios` installs CocoaPods before
580
+ script. The generated view also provides adaptive full-screen layout,
581
+ lifecycle-aware loading/error feedback, tap-to-retry and first-screen
582
+ readiness. On macOS, `lynxship build --platform ios` installs CocoaPods before
522
583
  archiving. Xcode, CocoaPods and real Apple signing credentials are still
523
584
  required for a signed IPA; the CLI never fabricates them.
524
585
 
@@ -0,0 +1,16 @@
1
+ import type { BuildProfile } from "../config.js";
2
+ export declare function signingEnvironment(root: string): Promise<NodeJS.ProcessEnv>;
3
+ export declare function createSigningInitScript(): Promise<{
4
+ directory: string;
5
+ file: string;
6
+ }>;
7
+ export declare function verifySignedArtifact(root: string, artifactPath: string, options: {
8
+ quiet: boolean;
9
+ onOutput?: (line: string) => void;
10
+ }): Promise<void>;
11
+ export declare function androidTool(name: string): string | undefined;
12
+ export declare function artifactDetails(root: string, profile: BuildProfile): {
13
+ task: string;
14
+ path: string;
15
+ };
16
+ //# sourceMappingURL=signing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../../src/android/signing.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAQjD,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAoB5B;AAED,wBAAsB,uBAAuB,IAAI,OAAO,CAAC;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAiDD;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GAC7D,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAyB5D;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAkChC"}
@@ -0,0 +1,131 @@
1
+ import { chmod, mkdtemp, writeFile } from "node:fs/promises";
2
+ import { execFileSync } from "node:child_process";
3
+ import { readdirSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { assert } from "@lynxship/contracts";
7
+ import { loadCredentials } from "../secure-store.js";
8
+ import { commandExists, executableExists, runProcess, } from "../process-runner.js";
9
+ export async function signingEnvironment(root) {
10
+ const android = (await loadCredentials(root)).android;
11
+ const values = {
12
+ LYNXSHIP_KEYSTORE_PATH: process.env.LYNXSHIP_KEYSTORE_PATH ?? android?.keystorePath,
13
+ LYNXSHIP_KEY_ALIAS: process.env.LYNXSHIP_KEY_ALIAS ?? android?.keyAlias,
14
+ LYNXSHIP_KEYSTORE_PASSWORD: process.env.LYNXSHIP_KEYSTORE_PASSWORD ?? android?.keystorePassword,
15
+ LYNXSHIP_KEY_PASSWORD: process.env.LYNXSHIP_KEY_PASSWORD ?? android?.keyPassword,
16
+ };
17
+ const missing = Object.entries(values)
18
+ .filter(([, value]) => !value)
19
+ .map(([name]) => name);
20
+ assert(missing.length === 0, "BUILD_SIGNING_REQUIRED", `Signed Android builds require configuration. Missing: ${missing.join(", ")}. Run \`lynxship android configure\`.`);
21
+ return { ...process.env, ...values };
22
+ }
23
+ export async function createSigningInitScript() {
24
+ const directory = await mkdtemp(join(tmpdir(), "lynxship-gradle-"));
25
+ const file = join(directory, "android-signing.init.gradle");
26
+ const script = `
27
+ def keystorePath = System.getenv("LYNXSHIP_KEYSTORE_PATH")
28
+ def keyAlias = System.getenv("LYNXSHIP_KEY_ALIAS")
29
+ def keystorePassword = System.getenv("LYNXSHIP_KEYSTORE_PASSWORD")
30
+ def keyPassword = System.getenv("LYNXSHIP_KEY_PASSWORD")
31
+
32
+ gradle.allprojects { project ->
33
+ project.plugins.withId("com.android.application") {
34
+ def configureSigning = { android ->
35
+ def signing = android.signingConfigs.findByName("release")
36
+ if (signing == null) {
37
+ signing = android.signingConfigs.create("lynxshipRelease")
38
+ }
39
+ signing.storeFile = project.file(keystorePath)
40
+ signing.storePassword = keystorePassword
41
+ signing.keyAlias = keyAlias
42
+ signing.keyPassword = keyPassword
43
+
44
+ def release = android.buildTypes.findByName("release")
45
+ if (release == null) {
46
+ throw new GradleException(
47
+ "LynxShip requires an Android release build type"
48
+ )
49
+ }
50
+ release.signingConfig = signing
51
+ project.logger.lifecycle(
52
+ "[LynxShip] Applied machine signing credentials to \${project.path}:release"
53
+ )
54
+ }
55
+
56
+ def androidComponents = project.extensions.findByName("androidComponents")
57
+ if (androidComponents != null) {
58
+ androidComponents.finalizeDsl { android ->
59
+ configureSigning(android)
60
+ }
61
+ } else {
62
+ project.afterEvaluate {
63
+ configureSigning(project.extensions.findByName("android"))
64
+ }
65
+ }
66
+ }
67
+ }
68
+ `;
69
+ await writeFile(file, script, "utf8");
70
+ await chmod(file, 0o600).catch(() => undefined);
71
+ return { directory, file };
72
+ }
73
+ export async function verifySignedArtifact(root, artifactPath, options) {
74
+ if (artifactPath.endsWith(".apk")) {
75
+ const apksigner = androidTool("apksigner");
76
+ assert(apksigner, "ANDROID_APKSIGNER_REQUIRED", "apksigner was not found in PATH. Install the Android SDK Build Tools.");
77
+ await runProcess(apksigner, ["verify", "--verbose", artifactPath], {
78
+ cwd: root,
79
+ ...options,
80
+ });
81
+ return;
82
+ }
83
+ const jarsigner = commandExists("jarsigner") ? "jarsigner" : undefined;
84
+ assert(jarsigner, "ANDROID_JARSIGNER_REQUIRED", "jarsigner was not found in PATH. Install JDK 17.");
85
+ await runProcess(jarsigner, ["-verify", "-verbose", "-certs", artifactPath], {
86
+ cwd: root,
87
+ ...options,
88
+ });
89
+ }
90
+ export function androidTool(name) {
91
+ if (commandExists(name)) {
92
+ if (process.platform !== "win32")
93
+ return name;
94
+ try {
95
+ return execFileSync("where.exe", [name], { encoding: "utf8" })
96
+ .split(/\r?\n/)
97
+ .map((value) => value.trim())
98
+ .find(Boolean);
99
+ }
100
+ catch {
101
+ return name;
102
+ }
103
+ }
104
+ const sdk = process.env.ANDROID_SDK_ROOT ?? process.env.ANDROID_HOME ?? undefined;
105
+ if (!sdk)
106
+ return undefined;
107
+ const executable = process.platform === "win32" ? `${name}.bat` : name;
108
+ try {
109
+ return readdirSync(join(sdk, "build-tools"))
110
+ .sort()
111
+ .reverse()
112
+ .map((version) => join(sdk, "build-tools", version, executable))
113
+ .find((candidate) => executableExists(candidate));
114
+ }
115
+ catch {
116
+ return undefined;
117
+ }
118
+ }
119
+ export function artifactDetails(root, profile) {
120
+ const artifact = profile.android?.artifact ?? "apk";
121
+ assert(artifact === "apk" || artifact === "aab", "BUILD_ARTIFACT_INVALID", "Android artifact must be apk or aab");
122
+ return artifact === "aab"
123
+ ? {
124
+ task: "bundleRelease",
125
+ path: join(root, "android", "app", "build", "outputs", "bundle", "release", "app-release.aab"),
126
+ }
127
+ : {
128
+ task: "assembleRelease",
129
+ path: join(root, "android", "app", "build", "outputs", "apk", "release", "app-release.apk"),
130
+ };
131
+ }
@@ -0,0 +1,12 @@
1
+ import type { BuildProfile } from "../config.js";
2
+ export interface AndroidBuildOptions {
3
+ root: string;
4
+ profile: BuildProfile;
5
+ uploadArtifacts?: boolean;
6
+ skipBundleBuild?: boolean;
7
+ quiet?: boolean;
8
+ onStep?: (message: string) => void;
9
+ onEvent?: (message: string) => void;
10
+ onProgress?: (value?: number, label?: string) => void;
11
+ }
12
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/android/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1,15 +1,5 @@
1
1
  import { type BuildJob } from "@lynxship/contracts";
2
- import type { BuildProfile } from "./config.js";
3
- interface AndroidBuildOptions {
4
- root: string;
5
- profile: BuildProfile;
6
- uploadArtifacts?: boolean;
7
- skipBundleBuild?: boolean;
8
- quiet?: boolean;
9
- onStep?: (message: string) => void;
10
- onEvent?: (message: string) => void;
11
- onProgress?: (value?: number, label?: string) => void;
12
- }
2
+ import type { AndroidBuildOptions } from "./android/types.js";
13
3
  export declare function hasAndroidHost(root: string): Promise<boolean>;
14
4
  export declare function isSupportedAndroidPlatform(): boolean;
15
5
  /**
@@ -19,7 +9,8 @@ export declare function isSupportedAndroidPlatform(): boolean;
19
9
  * project to carry a helper script. Rspeedy writes bundles and static assets
20
10
  * to `dist`, while the Lynx Android host reads them from `app/src/main/assets`.
21
11
  */
22
- export declare function syncLynxAssets(root: string): Promise<string[]>;
12
+ export declare function syncLynxAssets(root: string, options?: {
13
+ destination?: string;
14
+ }): Promise<string[]>;
23
15
  export declare function runRealAndroidBuild(job: BuildJob, options: AndroidBuildOptions): Promise<BuildJob>;
24
- export {};
25
16
  //# sourceMappingURL=android-build.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"android-build.d.ts","sourceRoot":"","sources":["../src/android-build.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAWhD,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AA8KD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAa7D;AAED,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsCpE;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,QAAQ,EACb,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,QAAQ,CAAC,CAgKnB"}
1
+ {"version":3,"file":"android-build.d.ts","sourceRoot":"","sources":["../src/android-build.ts"],"names":[],"mappings":"AAWA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAQpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAQ9D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAa7D;AAED,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACrC,OAAO,CAAC,MAAM,EAAE,CAAC,CAwCnB;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,QAAQ,EACb,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,QAAQ,CAAC,CAuKnB"}
@@ -1,138 +1,14 @@
1
- import { access, chmod, copyFile, cp, mkdir, mkdtemp, readFile, readdir, rm, writeFile, } from "node:fs/promises";
2
- import { execFileSync } from "node:child_process";
3
- import { constants as fsConstants, existsSync, readdirSync } from "node:fs";
4
- import { tmpdir } from "node:os";
1
+ import { access, copyFile, cp, mkdir, readFile, readdir, rm, } from "node:fs/promises";
2
+ import { constants as fsConstants, existsSync } from "node:fs";
5
3
  import { join } from "node:path";
6
4
  import { assert, sha256 } from "@lynxship/contracts";
7
5
  import { transitionBuild } from "@lynxship/build-orchestrator";
8
6
  import { loadR2, uploadR2Artifact } from "./r2.js";
9
- import { loadCredentials } from "./secure-store.js";
10
7
  import { nativeArtifactName } from "./artifact-name.js";
11
- import { commandExists, executableExists, runProcess, } from "./process-runner.js";
8
+ import { runProcess } from "./process-runner.js";
12
9
  import { buildLynxBundle } from "./bundle-build.js";
13
- async function signingEnvironment(root) {
14
- const android = (await loadCredentials(root)).android;
15
- const values = {
16
- LYNXSHIP_KEYSTORE_PATH: process.env.LYNXSHIP_KEYSTORE_PATH ?? android?.keystorePath,
17
- LYNXSHIP_KEY_ALIAS: process.env.LYNXSHIP_KEY_ALIAS ?? android?.keyAlias,
18
- LYNXSHIP_KEYSTORE_PASSWORD: process.env.LYNXSHIP_KEYSTORE_PASSWORD ?? android?.keystorePassword,
19
- LYNXSHIP_KEY_PASSWORD: process.env.LYNXSHIP_KEY_PASSWORD ?? android?.keyPassword,
20
- };
21
- const missing = Object.entries(values)
22
- .filter(([, value]) => !value)
23
- .map(([name]) => name);
24
- assert(missing.length === 0, "BUILD_SIGNING_REQUIRED", `Signed Android builds require configuration. Missing: ${missing.join(", ")}. Run \`lynxship android configure\`.`);
25
- return { ...process.env, ...values };
26
- }
27
- async function createSigningInitScript() {
28
- const directory = await mkdtemp(join(tmpdir(), "lynxship-gradle-"));
29
- const file = join(directory, "android-signing.init.gradle");
30
- const script = `
31
- def keystorePath = System.getenv("LYNXSHIP_KEYSTORE_PATH")
32
- def keyAlias = System.getenv("LYNXSHIP_KEY_ALIAS")
33
- def keystorePassword = System.getenv("LYNXSHIP_KEYSTORE_PASSWORD")
34
- def keyPassword = System.getenv("LYNXSHIP_KEY_PASSWORD")
35
-
36
- gradle.allprojects { project ->
37
- project.plugins.withId("com.android.application") {
38
- def configureSigning = { android ->
39
- def signing = android.signingConfigs.findByName("release")
40
- if (signing == null) {
41
- signing = android.signingConfigs.create("lynxshipRelease")
42
- }
43
- signing.storeFile = project.file(keystorePath)
44
- signing.storePassword = keystorePassword
45
- signing.keyAlias = keyAlias
46
- signing.keyPassword = keyPassword
47
-
48
- def release = android.buildTypes.findByName("release")
49
- if (release == null) {
50
- throw new GradleException(
51
- "LynxShip requires an Android release build type"
52
- )
53
- }
54
- release.signingConfig = signing
55
- project.logger.lifecycle(
56
- "[LynxShip] Applied machine signing credentials to \${project.path}:release"
57
- )
58
- }
59
-
60
- def androidComponents = project.extensions.findByName("androidComponents")
61
- if (androidComponents != null) {
62
- androidComponents.finalizeDsl { android ->
63
- configureSigning(android)
64
- }
65
- } else {
66
- project.afterEvaluate {
67
- configureSigning(project.extensions.findByName("android"))
68
- }
69
- }
70
- }
71
- }
72
- `;
73
- await writeFile(file, script, "utf8");
74
- await chmod(file, 0o600).catch(() => undefined);
75
- return { directory, file };
76
- }
77
- async function verifySignedArtifact(root, artifactPath, options) {
78
- if (artifactPath.endsWith(".apk")) {
79
- const apksigner = androidTool("apksigner");
80
- assert(apksigner, "ANDROID_APKSIGNER_REQUIRED", "apksigner was not found in PATH. Install the Android SDK Build Tools.");
81
- await runProcess(apksigner, ["verify", "--verbose", artifactPath], {
82
- cwd: root,
83
- ...options,
84
- });
85
- return;
86
- }
87
- const jarsigner = commandExists("jarsigner") ? "jarsigner" : undefined;
88
- assert(jarsigner, "ANDROID_JARSIGNER_REQUIRED", "jarsigner was not found in PATH. Install JDK 17.");
89
- await runProcess(jarsigner, ["-verify", "-verbose", "-certs", artifactPath], {
90
- cwd: root,
91
- ...options,
92
- });
93
- }
94
- function androidTool(name) {
95
- if (commandExists(name)) {
96
- if (process.platform !== "win32")
97
- return name;
98
- try {
99
- return execFileSync("where.exe", [name], { encoding: "utf8" })
100
- .split(/\r?\n/)
101
- .map((value) => value.trim())
102
- .find(Boolean);
103
- }
104
- catch {
105
- return name;
106
- }
107
- }
108
- const sdk = process.env.ANDROID_SDK_ROOT ?? process.env.ANDROID_HOME ?? undefined;
109
- if (!sdk)
110
- return undefined;
111
- const executable = process.platform === "win32" ? `${name}.bat` : name;
112
- try {
113
- return readdirSync(join(sdk, "build-tools"))
114
- .sort()
115
- .reverse()
116
- .map((version) => join(sdk, "build-tools", version, executable))
117
- .find((candidate) => executableExists(candidate));
118
- }
119
- catch {
120
- return undefined;
121
- }
122
- }
123
- function artifactDetails(root, profile) {
124
- const artifact = profile.android?.artifact ?? "apk";
125
- assert(artifact === "apk" || artifact === "aab", "BUILD_ARTIFACT_INVALID", "Android artifact must be apk or aab");
126
- return artifact === "aab"
127
- ? {
128
- task: "bundleRelease",
129
- path: join(root, "android", "app", "build", "outputs", "bundle", "release", "app-release.aab"),
130
- }
131
- : {
132
- task: "assembleRelease",
133
- path: join(root, "android", "app", "build", "outputs", "apk", "release", "app-release.apk"),
134
- };
135
- }
10
+ import { loadAppConfig, resolveAppConfigAssetPath } from "./app-config.js";
11
+ import { artifactDetails, createSigningInitScript, signingEnvironment, verifySignedArtifact, } from "./android/signing.js";
136
12
  export function hasAndroidHost(root) {
137
13
  if (!isSupportedAndroidPlatform())
138
14
  return Promise.resolve(false);
@@ -151,9 +27,10 @@ export function isSupportedAndroidPlatform() {
151
27
  * project to carry a helper script. Rspeedy writes bundles and static assets
152
28
  * to `dist`, while the Lynx Android host reads them from `app/src/main/assets`.
153
29
  */
154
- export async function syncLynxAssets(root) {
30
+ export async function syncLynxAssets(root, options = {}) {
155
31
  const distRoot = join(root, "dist");
156
- const assetsRoot = join(root, "android", "app", "src", "main", "assets");
32
+ const assetsRoot = options.destination ??
33
+ join(root, "android", "app", "src", "main", "assets");
157
34
  let entries;
158
35
  try {
159
36
  entries = await readdir(distRoot, { withFileTypes: true });
@@ -228,9 +105,13 @@ export async function runRealAndroidBuild(job, options) {
228
105
  step("Checking Android SDK and Gradle toolchain…");
229
106
  transitionBuild(job, "installing_dependencies", "syncing Lynx bundle into Android assets");
230
107
  step("Syncing bundle into the Android host…");
231
- const copiedAssets = await syncLynxAssets(options.root);
108
+ const appConfig = await loadAppConfig(options.root);
109
+ const assetsRoot = resolveAppConfigAssetPath(options.root, appConfig, "android", "android/app/src/main/assets");
110
+ const copiedAssets = await syncLynxAssets(options.root, {
111
+ destination: assetsRoot,
112
+ });
232
113
  for (const name of copiedAssets) {
233
- options.onEvent?.(`Synced dist/${name} -> android/app/src/main/assets/${name}`);
114
+ options.onEvent?.(`Synced dist/${name} -> ${assetsRoot}/${name}`);
234
115
  }
235
116
  step("Android host synchronized", 40);
236
117
  transitionBuild(job, "building", `Gradle ${artifact.task}`);
@@ -0,0 +1,3 @@
1
+ import type { AndroidToolchainReport } from "./types.js";
2
+ export declare function inspectAndroidToolchain(root: string): Promise<AndroidToolchainReport>;
3
+ //# sourceMappingURL=inspection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspection.d.ts","sourceRoot":"","sources":["../../src/android-toolchain/inspection.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,sBAAsB,EAAkB,MAAM,YAAY,CAAC;AAczE,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,sBAAsB,CAAC,CA2LjC"}
@@ -0,0 +1,122 @@
1
+ import { platform } from "node:os";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { commandExists, executableExists } from "../process-runner.js";
5
+ import { check, compareVersions, javaCandidates, javaVersion, readAndroidInputs, requiredGradleForAgp, requiredJavaForAgp, sdkCandidates, sdkManagerPath, sdkExecutable, } from "./probes.js";
6
+ export async function inspectAndroidToolchain(root) {
7
+ const inputs = readAndroidInputs(root);
8
+ const checks = [];
9
+ const wrapper = join(root, "android", platform() === "win32" ? "gradlew.bat" : "gradlew");
10
+ const wrapperExists = existsSync(wrapper) &&
11
+ (platform() === "win32" || executableExists(wrapper));
12
+ checks.push(check("gradle-wrapper", wrapperExists ? "pass" : "fail", wrapperExists
13
+ ? inputs.gradleVersion
14
+ ? `Gradle ${inputs.gradleVersion}`
15
+ : "found · version unknown"
16
+ : "missing", wrapperExists
17
+ ? undefined
18
+ : "lynxship android host init --application-id com.example.myapp"));
19
+ const minimumGradle = requiredGradleForAgp(inputs.agpVersion);
20
+ const gradleCompatible = Boolean(inputs.gradleVersion &&
21
+ minimumGradle &&
22
+ compareVersions(inputs.gradleVersion, minimumGradle) >= 0);
23
+ const gradleStatus = !inputs.gradleVersion || !inputs.agpVersion
24
+ ? "warn"
25
+ : gradleCompatible
26
+ ? "pass"
27
+ : "fail";
28
+ checks.push(check("agp-gradle-compatibility", gradleStatus, inputs.agpVersion && inputs.gradleVersion
29
+ ? `AGP ${inputs.agpVersion} · Gradle ${inputs.gradleVersion}${minimumGradle ? ` · minimum Gradle ${minimumGradle}` : ""}`
30
+ : "AGP or wrapper version not detected", gradleStatus === "fail" && minimumGradle
31
+ ? `Update the project wrapper to Gradle ${minimumGradle}; do not use a global Gradle installation`
32
+ : undefined));
33
+ const requiredJava = requiredJavaForAgp(inputs.agpVersion);
34
+ let detectedJava;
35
+ let javaPath;
36
+ for (const candidate of javaCandidates()) {
37
+ const version = await javaVersion(candidate, root);
38
+ if (version !== undefined) {
39
+ detectedJava = version;
40
+ javaPath = candidate;
41
+ break;
42
+ }
43
+ }
44
+ const javaStatus = detectedJava === undefined
45
+ ? "fail"
46
+ : detectedJava >= requiredJava
47
+ ? "pass"
48
+ : "fail";
49
+ checks.push(check("java", javaStatus, detectedJava === undefined
50
+ ? "missing"
51
+ : `JDK ${detectedJava}${javaPath === "java" ? " · PATH" : ""}`, javaStatus === "fail"
52
+ ? `Install/configure JDK ${requiredJava} and set JAVA_HOME, then run lynxship doctor --platform android`
53
+ : undefined));
54
+ const sdkPath = sdkCandidates().find((candidate) => existsSync(candidate));
55
+ const compileSdk = inputs.compileSdk;
56
+ const buildTools = inputs.buildToolsVersion;
57
+ const platformPackage = compileSdk
58
+ ? `platforms;android-${compileSdk}`
59
+ : undefined;
60
+ const buildToolsPackage = buildTools
61
+ ? `build-tools;${buildTools}`
62
+ : undefined;
63
+ const missingPackages = [
64
+ platformPackage &&
65
+ sdkPath &&
66
+ !existsSync(join(sdkPath, "platforms", `android-${compileSdk}`))
67
+ ? platformPackage
68
+ : undefined,
69
+ buildTools &&
70
+ sdkPath &&
71
+ !existsSync(join(sdkPath, "build-tools", buildTools))
72
+ ? buildToolsPackage
73
+ : undefined,
74
+ ].filter((value) => Boolean(value));
75
+ const sdkStatus = !sdkPath
76
+ ? "fail"
77
+ : missingPackages.length
78
+ ? "fail"
79
+ : "pass";
80
+ checks.push(check("android-sdk", sdkStatus, !sdkPath
81
+ ? "missing · set ANDROID_HOME or ANDROID_SDK_ROOT"
82
+ : missingPackages.length
83
+ ? `missing: ${missingPackages.join(", ")}`
84
+ : sdkPath, sdkStatus === "fail"
85
+ ? "Install Android Studio or the Android command-line tools, then run lynxship doctor --platform android --fix"
86
+ : undefined));
87
+ const manager = sdkPath ? sdkManagerPath(sdkPath) : undefined;
88
+ checks.push(check("sdkmanager", manager ? "pass" : sdkPath ? "warn" : "fail", manager
89
+ ? "available"
90
+ : sdkPath
91
+ ? "missing · use Android Studio SDK Manager"
92
+ : "unavailable until Android SDK is installed", manager && missingPackages.length
93
+ ? `sdkmanager ${missingPackages.map((value) => `"${value}"`).join(" ")}`
94
+ : undefined));
95
+ const adb = sdkPath ? sdkExecutable(sdkPath, "adb") : undefined;
96
+ checks.push(check("adb", adb || commandExists("adb") ? "pass" : "warn", adb || commandExists("adb")
97
+ ? "Android Platform-Tools available"
98
+ : "missing · required for lynxship run/logs", !adb && !commandExists("adb")
99
+ ? "Install Android SDK Platform-Tools, then run adb devices"
100
+ : undefined));
101
+ const apksigner = sdkPath ? sdkExecutable(sdkPath, "apksigner") : undefined;
102
+ checks.push(check("apksigner", apksigner || commandExists("apksigner") ? "pass" : "warn", apksigner || commandExists("apksigner")
103
+ ? "Android Build Tools available"
104
+ : "missing · required to verify APK signatures", !apksigner && !commandExists("apksigner")
105
+ ? "Install Android SDK Build Tools, then run lynxship doctor --platform android"
106
+ : undefined));
107
+ checks.push(check("android-sdk-licenses", sdkPath && existsSync(join(sdkPath, "licenses")) ? "pass" : "warn", sdkPath && existsSync(join(sdkPath, "licenses"))
108
+ ? "license directory found"
109
+ : "not verified", sdkPath ? "sdkmanager --licenses" : undefined));
110
+ const failures = checks.filter((item) => item.status === "fail");
111
+ return {
112
+ ok: failures.length === 0,
113
+ checks,
114
+ sdkPath,
115
+ compileSdk,
116
+ buildToolsVersion: buildTools,
117
+ agpVersion: inputs.agpVersion,
118
+ gradleVersion: inputs.gradleVersion,
119
+ javaVersion: detectedJava,
120
+ sdkPackages: missingPackages,
121
+ };
122
+ }
@@ -0,0 +1,23 @@
1
+ import type { ToolchainCheck, ToolchainCheckStatus } from "./types.js";
2
+ interface AndroidProjectInputs {
3
+ agpVersion?: string;
4
+ compileSdk?: number;
5
+ buildToolsVersion?: string;
6
+ gradleVersion?: string;
7
+ }
8
+ export declare function readProjectFiles(root: string): string;
9
+ export declare function readWrapperVersion(root: string): string | undefined;
10
+ export declare function readAndroidInputs(root: string): AndroidProjectInputs;
11
+ export declare function versionParts(version: string): number[];
12
+ export declare function compareVersions(left: string, right: string): number;
13
+ export declare function requiredGradleForAgp(agp?: string): string | undefined;
14
+ export declare function requiredJavaForAgp(agp?: string): number;
15
+ export declare function sdkCandidates(): string[];
16
+ export declare function sdkExecutable(sdkPath: string, name: string): string | undefined;
17
+ export declare function readDirectories(directory: string): string[];
18
+ export declare function sdkManagerPath(sdkPath: string): string | undefined;
19
+ export declare function javaVersion(javaPath: string, cwd: string): Promise<number | undefined>;
20
+ export declare function javaCandidates(): string[];
21
+ export declare function check(name: string, status: ToolchainCheckStatus, value: string, fix?: string): ToolchainCheck;
22
+ export {};
23
+ //# sourceMappingURL=probes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probes.d.ts","sourceRoot":"","sources":["../../src/android-toolchain/probes.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvE,UAAU,oBAAoB;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA2BD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcrD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAanE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CAqBpE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQnE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKrE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAkBxC;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CASpB;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAM3D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAelE;AAED,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAU7B;AAED,wBAAgB,cAAc,IAAI,MAAM,EAAE,CA0DzC;AAED,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,MAAM,EACb,GAAG,CAAC,EAAE,MAAM,GACX,cAAc,CAEhB"}