@pmate/cli 0.25.2 → 0.25.4

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 (2) hide show
  1. package/dist/index.js +58 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -22293,7 +22293,13 @@ var AndroidApkReleaseService = class {
22293
22293
  size,
22294
22294
  gitCommit: await this.readGitCommit(repoRoot)
22295
22295
  };
22296
- await this.registry?.createApkArtifact(service.id, artifact);
22296
+ if (this.registry) {
22297
+ try {
22298
+ await this.registry.createApkArtifact(service.id, artifact);
22299
+ } catch (error) {
22300
+ ui.warn("APK uploaded but registry artifact record failed", error instanceof Error ? error.message : String(error));
22301
+ }
22302
+ }
22297
22303
  ui.success(`Released APK ${artifact.downloadUrl}`);
22298
22304
  return artifact;
22299
22305
  }
@@ -22375,13 +22381,14 @@ var AndroidApkReleaseService = class {
22375
22381
  if (!gradlew) {
22376
22382
  throw new Error(`Gradle wrapper not found in ${appDir} or ${repoRoot}`);
22377
22383
  }
22384
+ const gradleCwd = import_node_path24.default.dirname(gradlew);
22378
22385
  const normalizedVariant = variant.toLowerCase();
22379
22386
  const taskSuffix = `assemble${capitalize(normalizedVariant)}`;
22380
22387
  const tasks = [`:app:${taskSuffix}`, taskSuffix];
22381
22388
  let lastError;
22382
22389
  for (const task of tasks) {
22383
22390
  try {
22384
- await runCommand(gradlew, [task], repoRoot);
22391
+ await runCommand(gradlew, [task], gradleCwd);
22385
22392
  return findLatestApk(repoRoot, appDir, normalizedVariant);
22386
22393
  } catch (error) {
22387
22394
  lastError = error;
@@ -22391,8 +22398,11 @@ var AndroidApkReleaseService = class {
22391
22398
  }
22392
22399
  async readApkMetadata(apkPath) {
22393
22400
  const readers = [
22401
+ async () => readGradleOutputMetadata(apkPath),
22394
22402
  async () => parseAaptBadging(await runCommandCapture("aapt", ["dump", "badging", apkPath])),
22395
- async () => parseApkAnalyzerManifest(await runCommandCapture("apkanalyzer", ["manifest", "print", apkPath]))
22403
+ async () => parseApkAnalyzerManifest(await runCommandCapture("apkanalyzer", ["manifest", "print", apkPath])),
22404
+ async () => parseAaptBadging(await runAndroidSdkToolCapture("aapt", ["dump", "badging", apkPath])),
22405
+ async () => parseApkAnalyzerManifest(await runAndroidSdkToolCapture("apkanalyzer", ["manifest", "print", apkPath]))
22396
22406
  ];
22397
22407
  const errors = [];
22398
22408
  for (const reader of readers) {
@@ -22402,7 +22412,9 @@ var AndroidApkReleaseService = class {
22402
22412
  errors.push(error instanceof Error ? error.message : String(error));
22403
22413
  }
22404
22414
  }
22405
- throw new Error(`Cannot read APK metadata. Install Android SDK build-tools. ${errors.join(" | ")}`);
22415
+ throw new Error(
22416
+ `Cannot read APK metadata. Expected Gradle output-metadata.json or Android SDK tools aapt/apkanalyzer. ${errors.join(" | ")}`
22417
+ );
22406
22418
  }
22407
22419
  async findExistingObject(objectKey) {
22408
22420
  const parentPrefix = objectKey.split("/").slice(0, -1).join("/");
@@ -22473,6 +22485,17 @@ function parseApkAnalyzerManifest(output) {
22473
22485
  }
22474
22486
  return { applicationId, versionName, versionCode };
22475
22487
  }
22488
+ function parseGradleOutputMetadata(source, apkFileName) {
22489
+ const payload = JSON.parse(source);
22490
+ const element = (apkFileName ? payload.elements?.find((item) => item.outputFile === apkFileName) : void 0) ?? payload.elements?.find((item) => item.versionName != null && item.versionCode != null);
22491
+ const applicationId = payload.applicationId;
22492
+ const versionName = element?.versionName;
22493
+ const versionCode = Number(element?.versionCode);
22494
+ if (!applicationId || !versionName || !Number.isFinite(versionCode)) {
22495
+ throw new Error("Gradle output metadata is missing applicationId, versionName, or versionCode");
22496
+ }
22497
+ return { applicationId, versionName, versionCode };
22498
+ }
22476
22499
  function bumpAndroidProjectVersion(appDir, bump) {
22477
22500
  const candidates = [
22478
22501
  import_node_path24.default.join(appDir, "app", "build.gradle.kts"),
@@ -22501,6 +22524,13 @@ function findLatestApk(repoRoot, appDir, variant) {
22501
22524
  files.sort((a, b) => (0, import_node_fs20.statSync)(b).mtimeMs - (0, import_node_fs20.statSync)(a).mtimeMs);
22502
22525
  return files[0];
22503
22526
  }
22527
+ function readGradleOutputMetadata(apkPath) {
22528
+ const metadataPath = import_node_path24.default.join(import_node_path24.default.dirname(apkPath), "output-metadata.json");
22529
+ if (!(0, import_node_fs20.existsSync)(metadataPath)) {
22530
+ throw new Error(`Gradle output metadata not found: ${metadataPath}`);
22531
+ }
22532
+ return parseGradleOutputMetadata((0, import_node_fs20.readFileSync)(metadataPath, "utf8"), import_node_path24.default.basename(apkPath));
22533
+ }
22504
22534
  function listApks(dir) {
22505
22535
  if (!(0, import_node_fs20.existsSync)(dir)) return [];
22506
22536
  return (0, import_node_fs20.readdirSync)(dir).filter((entry) => entry.endsWith(".apk")).map((entry) => import_node_path24.default.join(dir, entry)).filter((entry) => (0, import_node_fs20.statSync)(entry).isFile());
@@ -22529,6 +22559,30 @@ function runCommandCapture(command, args, cwd) {
22529
22559
  });
22530
22560
  });
22531
22561
  }
22562
+ async function runAndroidSdkToolCapture(toolName, args) {
22563
+ const toolPath = findAndroidSdkTool(toolName);
22564
+ if (!toolPath) {
22565
+ throw new Error(`Android SDK tool not found: ${toolName}`);
22566
+ }
22567
+ return runCommandCapture(toolPath, args);
22568
+ }
22569
+ function findAndroidSdkTool(toolName) {
22570
+ const sdkRoots = [process.env.ANDROID_HOME, process.env.ANDROID_SDK_ROOT].filter((item) => Boolean(item)).map((item) => import_node_path24.default.resolve(item));
22571
+ for (const sdkRoot of sdkRoots) {
22572
+ const candidates = toolName === "aapt" ? listVersionedToolCandidates(import_node_path24.default.join(sdkRoot, "build-tools"), toolName) : [
22573
+ import_node_path24.default.join(sdkRoot, "cmdline-tools", "latest", "bin", toolName),
22574
+ ...listVersionedToolCandidates(import_node_path24.default.join(sdkRoot, "cmdline-tools"), import_node_path24.default.join("bin", toolName)),
22575
+ import_node_path24.default.join(sdkRoot, "tools", "bin", toolName)
22576
+ ];
22577
+ const match = candidates.find((candidate) => (0, import_node_fs20.existsSync)(candidate));
22578
+ if (match) return match;
22579
+ }
22580
+ return void 0;
22581
+ }
22582
+ function listVersionedToolCandidates(parentDir, relativeToolPath) {
22583
+ if (!(0, import_node_fs20.existsSync)(parentDir)) return [];
22584
+ return (0, import_node_fs20.readdirSync)(parentDir).map((entry) => import_node_path24.default.join(parentDir, entry)).filter((entry) => (0, import_node_fs20.statSync)(entry).isDirectory()).sort((a, b) => import_node_path24.default.basename(b).localeCompare(import_node_path24.default.basename(a), void 0, { numeric: true })).map((entry) => import_node_path24.default.join(entry, relativeToolPath));
22585
+ }
22532
22586
  function sha256File(filePath) {
22533
22587
  return new Promise((resolve, reject) => {
22534
22588
  const hash = (0, import_node_crypto4.createHash)("sha256");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmate/cli",
3
- "version": "0.25.2",
3
+ "version": "0.25.4",
4
4
  "description": "CLI utilities for the pMate project",
5
5
  "license": "MIT",
6
6
  "bin": {