@livx.cc/appwrap 0.39.10 → 0.39.12

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livx.cc/appwrap",
3
- "version": "0.39.10",
3
+ "version": "0.39.12",
4
4
  "description": "Wrap any PWA into a native app with native capabilities (appwrap runtime + @livx.cc/native-kit).",
5
5
  "license": "MIT",
6
6
  "author": "Elya Livshitz",
package/src/cli.ts CHANGED
@@ -1259,13 +1259,45 @@ async function dev(cwd: string, flags: Record<string, string>): Promise<void> {
1259
1259
  * install when node_modules is absent — if ns later reinstalls on package.json drift it uses npm
1260
1260
  * (NativeScript has no bun package-manager mode), so trustedDependencies in the shell package.json
1261
1261
  * is what keeps the bun-installed tree behaving like npm's (parcel/watcher, ns CLI hooks). */
1262
+ /** Resolve a usable Android SDK dir: an already-valid ANDROID_HOME/ANDROID_SDK_ROOT, else the first
1263
+ * common install location that actually contains an SDK. Lets `deploy/run android` work without the
1264
+ * user having exported ANDROID_HOME in their shell (the #1 "ns can't find the SDK" foot-gun). */
1265
+ function resolveAndroidSdk(): string | undefined {
1266
+ const env = process.env.ANDROID_HOME || process.env.ANDROID_SDK_ROOT;
1267
+ if (env && existsSync(env)) return env;
1268
+ const home = process.env.HOME || '';
1269
+ const candidates = [
1270
+ join(home, 'Library/Android/sdk'), // macOS (Android Studio default)
1271
+ join(home, 'Library/Android/Sdk'),
1272
+ join(home, 'Android/Sdk'), // Linux (Android Studio default)
1273
+ '/usr/local/share/android-sdk', // homebrew cask
1274
+ '/opt/android-sdk',
1275
+ ];
1276
+ // A usable SDK has platform-tools (adb) or installed platforms; cmdline-tools-only dirs don't count.
1277
+ return candidates.find((d) => existsSync(join(d, 'platform-tools')) || existsSync(join(d, 'platforms')));
1278
+ }
1279
+
1262
1280
  function runNs(outDir: string, args: string[]): void {
1281
+ const env: NodeJS.ProcessEnv = { ...process.env };
1282
+ // Android: inject a discovered SDK so `ns` finds it even when the user's shell never exported
1283
+ // ANDROID_HOME (new terminal not sourced, conda base shell, etc.) — the common deploy blocker.
1284
+ if (args.includes('android')) {
1285
+ const sdk = resolveAndroidSdk();
1286
+ if (sdk) {
1287
+ env.ANDROID_HOME = sdk;
1288
+ env.ANDROID_SDK_ROOT = sdk;
1289
+ env.PATH = [process.env.PATH, join(sdk, 'platform-tools'), join(sdk, 'emulator')].filter(Boolean).join(':');
1290
+ if (!process.env.ANDROID_HOME) console.log(` android SDK ← ${sdk} (ANDROID_HOME not set; auto-detected)`);
1291
+ } else {
1292
+ console.warn(' ⚠ No Android SDK found (set ANDROID_HOME). Install Android Studio or the command-line tools, then `sdkmanager "platform-tools" "platforms;android-35" "build-tools;35.0.0"`.');
1293
+ }
1294
+ }
1263
1295
  if (!existsSync(join(outDir, 'node_modules'))) {
1264
1296
  console.log(`▶ bun install (cwd: ${outDir})`);
1265
- execFileSync('bun', ['install'], { cwd: outDir, stdio: 'inherit' });
1297
+ execFileSync('bun', ['install'], { cwd: outDir, stdio: 'inherit', env });
1266
1298
  }
1267
1299
  console.log(`▶ ns ${args.join(' ')} (cwd: ${outDir})`);
1268
- execFileSync('ns', args, { cwd: outDir, stdio: 'inherit' });
1300
+ execFileSync('ns', args, { cwd: outDir, stdio: 'inherit', env });
1269
1301
  }
1270
1302
 
1271
1303
  /** Read the loader currently stamped into the generated shell (app/shell/config.ts). Used to
@@ -30,17 +30,28 @@ jobs:
30
30
  with: { node-version: 22 }
31
31
  - uses: actions/setup-java@v4
32
32
  with: { distribution: temurin, java-version: 17 }
33
+ # Cache the Gradle distribution + dependency/build caches — the Android build is ~70% of CI time;
34
+ # without this every run re-downloads everything (~4–5 min). Warms on the first run.
35
+ - uses: actions/cache@v4
36
+ with:
37
+ path: |
38
+ ~/.gradle/caches
39
+ ~/.gradle/wrapper
40
+ key: gradle-${{ runner.os }}-${{ hashFiles('bun.lock', 'package.json') }}
41
+ restore-keys: gradle-${{ runner.os }}-
33
42
  - uses: android-actions/setup-android@v3
43
+ - run: sudo apt-get update -qq && sudo apt-get install -y -qq imagemagick # appwrap icon-gen needs an image tool (no sips on Linux) — else the default NS icon ships
34
44
  - run: bun install && bun run build # → dist/ (the PWA bundle the wrapper ships)
35
45
  # Pin global tools — unpinned installs can grab a breaking release mid-flight. Bump deliberately.
36
- - run: npm i -g nativescript@9.0.6
46
+ - run: bun add -g nativescript@9.0.6
37
47
  - run: bunx @livx.cc/appwrap init # native/ is generated (gitignored) — regenerate fresh in CI
38
48
  - working-directory: native
39
- run: npm install
49
+ run: bun install
40
50
  - name: Decode upload keystore
41
51
  run: echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > "$RUNNER_TEMP/upload.keystore"
42
52
  - name: Build signed AAB
43
53
  env:
54
+ GRADLE_OPTS: "-Dorg.gradle.caching=true -Dorg.gradle.parallel=true -Dorg.gradle.daemon=false"
44
55
  APPWRAP_ANDROID_KEYSTORE: ${{ runner.temp }}/upload.keystore
45
56
  APPWRAP_ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
46
57
  APPWRAP_ANDROID_KEYSTORE_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}