(archivePath: string)
| 110 | } |
| 111 | |
| 112 | async function detectAndroidArtifactKind(archivePath: string): Promise<'apk' | 'aab'> { |
| 113 | const extension = path.extname(archivePath).toLowerCase(); |
| 114 | if (extension === '.apk') return 'apk'; |
| 115 | if (extension === '.aab') return 'aab'; |
| 116 | |
| 117 | const entries = await readZipEntries(archivePath); |
| 118 | if (entries?.includes('BundleConfig.pb')) return 'aab'; |
| 119 | if (entries?.includes('AndroidManifest.xml')) return 'apk'; |
| 120 | |
| 121 | throw new AppError( |
| 122 | 'INVALID_ARGS', |
| 123 | `Android artifact URLs must resolve to .apk or .aab files, got "${path.basename(archivePath)}"`, |
| 124 | ); |
| 125 | } |
| 126 | |
| 127 | async function detectIosArtifactKind(archivePath: string): Promise<'app-tar' | 'ipa'> { |
| 128 | if (isTarLikePath(archivePath)) return 'app-tar'; |
no test coverage detected
searching dependent graphs…