@huoye/app-ship 0.1.2 → 0.2.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.
- package/README.md +21 -3
- package/dist/cli.js +733 -75
- package/dist/index.cjs +655 -67
- package/dist/index.d.cts +137 -14
- package/dist/index.d.ts +137 -14
- package/dist/index.js +629 -51
- package/package.json +11 -7
- package/dist/cli.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/upload-manager.ts","../node_modules/chalk/source/vendor/ansi-styles/index.js","../node_modules/chalk/source/vendor/supports-color/index.js","../node_modules/chalk/source/utilities.js","../node_modules/chalk/source/index.js","../src/utils/logger.ts","../src/adapters/pgyer_uploader.ts","../src/utils/retry-strategy.ts","../src/utils/apple-jwt-generator.ts","../src/utils/package-parser.ts","../src/adapters/huawei_uploader.ts","../src/adapters/xiaomi_uploader.ts","../src/adapters/apple_store_uploader.ts","../src/adapters/testflight_uploader.ts","../src/adapters/adhoc_uploader.ts","../src/adapters/harmony_uploader.ts","../src/adapters/oppo_uploader.ts","../src/adapters/vivo_uploader.ts","../src/adapters/tencent_uploader.ts","../src/validators/config_validator.ts","../src/validators/env_validator.ts","../src/cli.ts"],"sourcesContent":["/**\n * 上传管理器 (UploadManager)\n *\n * 职责:\n * 1. 注册并管理所有平台上传适配器 (10 个内置)\n * 2. 根据配置文件筛选启用的平台\n * 3. 智能文件分发:APK → Android 商店, IPA → Apple, HAP → 鸿蒙\n * 4. 并发控制:通过 maxConcurrent 限制同时上传的平台数\n * 5. 聚合上传结果,生成 UploadReport\n *\n * 扩展:调用 registerUploader() 注册自定义适配器\n */\nimport path from 'path'\nimport { logger } from './logger.js'\nimport {\n PgyerUploader,\n HuaweiUploader,\n XiaomiUploader,\n AppleStoreUploader,\n TestFlightUploader,\n AdHocUploader,\n HarmonyUploader,\n OppoUploader,\n VivoUploader,\n TencentUploader,\n} from '../adapters/index.js'\nimport { parsePackageInfo } from './package-parser.js'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\n\nconst GROUPED_ARTIFACT_PLATFORMS = new Set(['huawei', 'xiaomi', 'oppo', 'vivo', 'tencent'])\n\ntype ArtifactSelection = string | Record<string, string>\n\ninterface UploadTask {\n platform: string\n file: string\n artifactSelection: ArtifactSelection\n}\n\n/**\n * 上传管理器配置\n */\nexport interface UploadManagerConfig {\n // 同时执行的最大并发上传数(0 = 无限制)\n maxConcurrent?: number\n // 失败后是否继续上传其他平台\n continueOnError?: boolean\n // 显示详细进度\n verbose?: boolean\n // 取消令牌(用于协同中断)\n cancellationToken?: { isCancelled: boolean }\n}\n\n/**\n * 聚合的上传结果报告\n */\nexport interface UploadReport {\n // 总上传次数\n totalUploads: number\n // 成功次数\n successCount: number\n // 失败次数\n failureCount: number\n // 成功的平台列表\n successPlatforms: string[]\n // 失败的平台列表\n failurePlatforms: string[]\n // 所有平台的详细结果\n results: UploadResult[]\n // 上传总耗时(毫秒)\n totalDurationMs: number\n // 报告摘要\n summary: string\n}\n\n/**\n * 上传管理器 - 处理多平台并行上传\n */\nexport class UploadManager {\n private uploaders: Map<string, IUploader>\n private config: UploadManagerConfig & {\n maxConcurrent: number\n continueOnError: boolean\n verbose: boolean\n }\n\n constructor(config: UploadManagerConfig = {}) {\n this.uploaders = new Map()\n this.config = {\n maxConcurrent: config.maxConcurrent ?? 3,\n continueOnError: config.continueOnError ?? true,\n verbose: config.verbose ?? false,\n cancellationToken: config.cancellationToken,\n }\n\n // 注册所有可用的上传器\n this.registerUploader('pgyer', new PgyerUploader())\n this.registerUploader('huawei', new HuaweiUploader())\n this.registerUploader('xiaomi', new XiaomiUploader())\n this.registerUploader('app_store', new AppleStoreUploader())\n this.registerUploader('testflight', new TestFlightUploader())\n this.registerUploader('adhoc', new AdHocUploader())\n this.registerUploader('harmony', new HarmonyUploader())\n this.registerUploader('oppo', new OppoUploader())\n this.registerUploader('vivo', new VivoUploader())\n this.registerUploader('tencent', new TencentUploader())\n }\n\n /**\n * 注册上传器\n */\n registerUploader(platform: string, uploader: IUploader): void {\n this.uploaders.set(platform, uploader)\n }\n\n /**\n * 获取启用的平台列表(根据配置)\n */\n getEnabledPlatforms(config: any): string[] {\n const enabled: string[] = []\n\n if (config?.publish?.pgyer?.enable) enabled.push('pgyer')\n if (config?.publish?.huawei?.enable) enabled.push('huawei')\n if (config?.publish?.xiaomi?.enable) enabled.push('xiaomi')\n if (config?.publish?.oppo?.enable) enabled.push('oppo')\n if (config?.publish?.vivo?.enable) enabled.push('vivo')\n if (config?.publish?.tencent?.enable) enabled.push('tencent')\n\n // App Store 支持多种模式\n if (config?.publish?.app_store?.enable) {\n const mode = config.publish.app_store.mode || 'app_store'\n enabled.push(mode) // 'app_store' | 'testflight' | 'adhoc'\n }\n\n return enabled\n }\n\n /**\n * 获取可用的平台列表\n */\n getAvailablePlatforms(): string[] {\n return Array.from(this.uploaders.keys())\n }\n\n /**\n * 执行并行上传(支持多文件智能分发)\n */\n async uploadToMultiplePlatforms(\n filePaths: string | string[], // 支持单文件或文件数组\n config: any,\n metadata: AppMetadata,\n targetPlatforms?: string[],\n ): Promise<UploadReport> {\n const startTime = Date.now()\n\n // 确定目标平台\n let platforms =\n targetPlatforms && targetPlatforms.length > 0\n ? targetPlatforms\n : this.getEnabledPlatforms(config)\n\n if (platforms.length === 0) {\n logger.warn('No platforms enabled for upload')\n return {\n totalUploads: 0,\n successCount: 0,\n failureCount: 0,\n successPlatforms: [],\n failurePlatforms: [],\n results: [],\n totalDurationMs: 0,\n summary: 'No platforms configured for upload',\n }\n }\n\n logger.info(\n `Starting parallel uploads to ${platforms.length} platform(s): ${platforms.join(', ')}`,\n )\n\n // 验证所有平台的配置\n const validPlatforms = platforms.filter((platform) => {\n const uploader = this.uploaders.get(platform)\n if (!uploader) {\n logger.warn(`Platform '${platform}' is not supported`)\n return false\n }\n if (!uploader.validateConfig(config)) {\n logger.warn(`Configuration for '${platform}' is invalid`)\n return false\n }\n return true\n })\n\n if (validPlatforms.length === 0) {\n logger.error('No valid platforms to upload to')\n return {\n totalUploads: platforms.length,\n successCount: 0,\n failureCount: platforms.length,\n successPlatforms: [],\n failurePlatforms: platforms,\n results: [],\n totalDurationMs: Date.now() - startTime,\n summary: 'All platforms failed configuration validation',\n }\n }\n\n // 规范化为数组\n const files = Array.isArray(filePaths) ? filePaths : [filePaths]\n\n // 生成上传任务:支持对具备双包能力的平台按“同一次版本提交”分组上传\n const tasks: UploadTask[] = []\n validPlatforms.forEach((platform) => {\n const uploader = this.uploaders.get(platform)!\n const matchedFiles = files.filter((f: string) => uploader.canHandle(f))\n\n if (matchedFiles.length === 0) {\n logger.warn(`[${platform}] No compatible file found in provided files`)\n } else {\n if (this.shouldGroupArtifacts(platform)) {\n const artifactSelection = this.resolveArtifactSelection(platform, matchedFiles, metadata)\n if (!artifactSelection) {\n logger.warn(`[${platform}] Failed to build grouped artifact selection`)\n return\n }\n\n tasks.push({\n platform,\n file: this.getRepresentativeFilePath(artifactSelection),\n artifactSelection,\n })\n } else {\n matchedFiles.forEach((file: string) => {\n tasks.push({ platform, file, artifactSelection: file })\n })\n }\n }\n })\n\n if (tasks.length === 0) {\n logger.error('No valid platform-file matches found')\n return {\n totalUploads: validPlatforms.length,\n successCount: 0,\n failureCount: validPlatforms.length,\n successPlatforms: [],\n failurePlatforms: validPlatforms,\n results: [],\n totalDurationMs: Date.now() - startTime,\n summary: 'No compatible files found for any of the selected platforms',\n }\n }\n\n logger.info(`Scheduled ${tasks.length} upload task(s) for ${validPlatforms.length} platform(s)`)\n\n const uploadPromises = tasks.map((task) => {\n logger.info(`[${task.platform}] Matched file: ${path.basename(task.file)}`)\n return this.uploadToPlatform(\n task.platform,\n task.file,\n config,\n metadata,\n task.artifactSelection,\n )\n })\n\n const results = await Promise.all(uploadPromises)\n\n // 聚合结果\n const report = this.aggregateResults(results, tasks.length, startTime)\n\n // 输出摘要\n this.printReport(report)\n\n return report\n }\n\n /**\n * 上传到单个平台\n */\n private async uploadToPlatform(\n platform: string,\n filePath: string,\n config: any,\n metadata: AppMetadata,\n artifactSelection: ArtifactSelection = filePath,\n ): Promise<UploadResult> {\n // ✅ 协同取消检查:如果外部已标记取消,直接跳过\n if (this.config.cancellationToken?.isCancelled) {\n logger.warn(`[${platform.toUpperCase()}] Upload skipped due to cancellation`)\n return {\n platform,\n success: false,\n message: 'Upload cancelled by user',\n }\n }\n\n const uploader = this.uploaders.get(platform)\n if (!uploader) {\n return {\n platform,\n success: false,\n message: `Platform '${platform}' is not supported`,\n }\n }\n\n try {\n if (this.config.verbose) {\n logger.info(`[${platform.toUpperCase()}] Starting upload...`)\n }\n\n const effectiveMetadata: AppMetadata = {\n ...metadata,\n artifactPath: artifactSelection,\n }\n\n await this.validateArtifactSelection(platform, artifactSelection, effectiveMetadata)\n\n // 智能版本校准:如果能从包里解析出真实的版本信息,则优先使用包内的(解决仅上传模式下版本不一致问题)\n const pkgInfo = await parsePackageInfo(filePath, {\n androidSdkPath: effectiveMetadata.globalSettings?.androidSdkPath,\n })\n\n if (pkgInfo) {\n // 只有当包里有明确的版本信息时才覆盖校准\n if (pkgInfo.versionName) {\n effectiveMetadata.version = pkgInfo.versionName\n }\n if (pkgInfo.versionCode) {\n effectiveMetadata.buildNumber = pkgInfo.versionCode\n }\n if (pkgInfo.packageName) {\n // 部分 Uploader 可能也需要这个\n ;(effectiveMetadata as any).packageName = pkgInfo.packageName\n }\n logger.info(\n `[${platform.toUpperCase()}] 已校准版本信息: v${effectiveMetadata.version}+${effectiveMetadata.buildNumber}`,\n )\n }\n\n const result = await uploader.upload(filePath, config, effectiveMetadata)\n return result\n } catch (error: any) {\n const errorMessage = error.message || String(error)\n logger.error(`[${platform.toUpperCase()}] Upload error: ${errorMessage}`)\n return {\n platform,\n success: false,\n message: errorMessage,\n error,\n }\n }\n }\n\n private shouldGroupArtifacts(platform: string): boolean {\n return GROUPED_ARTIFACT_PLATFORMS.has(platform)\n }\n\n private resolveArtifactSelection(\n platform: string,\n matchedFiles: string[],\n metadata: AppMetadata,\n ): ArtifactSelection | null {\n const explicitArtifacts = metadata.platformArtifacts?.[platform]\n if (explicitArtifacts) {\n if (typeof explicitArtifacts === 'string') {\n return explicitArtifacts\n }\n if (Object.keys(explicitArtifacts).length > 0) {\n return explicitArtifacts\n }\n }\n\n if (matchedFiles.length === 0) {\n return null\n }\n if (matchedFiles.length === 1) {\n return matchedFiles[0]\n }\n return this.buildArtifactMapFromFiles(matchedFiles)\n }\n\n private buildArtifactMapFromFiles(files: string[]): Record<string, string> {\n return files.reduce(\n (acc, filePath, index) => {\n acc[this.inferArtifactKey(filePath, index)] = filePath\n return acc\n },\n {} as Record<string, string>,\n )\n }\n\n private inferArtifactKey(filePath: string, index: number): string {\n const fileName = path.basename(filePath).toLowerCase()\n if (fileName.includes('arm64-v8a')) return 'arm64-v8a'\n if (fileName.includes('armeabi-v7a')) return 'armeabi-v7a'\n if (fileName.includes('x86_64')) return 'x86_64'\n if (fileName.includes('universal')) return 'universal'\n return `artifact_${index + 1}`\n }\n\n private getRepresentativeFilePath(artifactSelection: ArtifactSelection): string {\n if (typeof artifactSelection === 'string') {\n return artifactSelection\n }\n return Object.values(artifactSelection)[0]\n }\n\n private async validateArtifactSelection(\n platform: string,\n artifactSelection: ArtifactSelection,\n metadata: AppMetadata,\n ): Promise<void> {\n if (typeof artifactSelection === 'string') {\n return\n }\n\n const artifactPaths = Object.values(artifactSelection).filter(Boolean)\n if (artifactPaths.length < 2) {\n return\n }\n\n const parsedInfos = await Promise.all(\n artifactPaths.map((artifactPath) =>\n parsePackageInfo(artifactPath, {\n androidSdkPath: metadata.globalSettings?.androidSdkPath,\n }),\n ),\n )\n const availableInfos = parsedInfos.filter((info) => !!info)\n if (availableInfos.length < 2) {\n logger.warn(\n `[${platform.toUpperCase()}] Unable to fully validate multi-artifact package info; continuing with upload.`,\n )\n return\n }\n\n const [baseInfo, ...restInfos] = availableInfos\n for (const info of restInfos) {\n if (baseInfo?.packageName && info?.packageName && baseInfo.packageName !== info.packageName) {\n throw new Error('双包上传失败:所选安装包的 packageName 不一致')\n }\n if (baseInfo?.versionName && info?.versionName && baseInfo.versionName !== info.versionName) {\n throw new Error('双包上传失败:所选安装包的 versionName 不一致')\n }\n if (baseInfo?.versionCode && info?.versionCode && baseInfo.versionCode !== info.versionCode) {\n throw new Error('双包上传失败:所选安装包的 versionCode 不一致')\n }\n }\n }\n\n /**\n * 聚合上传结果\n */\n private aggregateResults(\n results: UploadResult[],\n totalPlatforms: number,\n startTime: number,\n ): UploadReport {\n const successResults = results.filter((r) => r.success)\n const failureResults = results.filter((r) => !r.success)\n\n const successPlatforms = successResults.map((r) => r.platform || 'unknown')\n const failurePlatforms = failureResults.map((r) => r.platform || 'unknown')\n\n const totalDurationMs = Date.now() - startTime\n\n let summary = ''\n if (successResults.length === totalPlatforms) {\n summary = `✅ All ${totalPlatforms} platforms uploaded successfully!`\n } else if (failureResults.length === totalPlatforms) {\n summary = `❌ Upload failed on all ${totalPlatforms} platforms`\n } else {\n summary = `⚠️ Partial success: ${successResults.length} succeeded, ${failureResults.length} failed`\n }\n\n return {\n totalUploads: totalPlatforms,\n successCount: successResults.length,\n failureCount: failureResults.length,\n successPlatforms,\n failurePlatforms,\n results,\n totalDurationMs,\n summary,\n }\n }\n\n /**\n * 输出上传报告\n */\n private printReport(report: UploadReport): void {\n logger.info('')\n logger.info('═'.repeat(60))\n logger.info('📊 Upload Report')\n logger.info('═'.repeat(60))\n\n logger.info(`Total Platforms: ${report.totalUploads}`)\n logger.info(`✅ Success: ${report.successCount}`)\n logger.info(`❌ Failure: ${report.failureCount}`)\n\n if (report.successPlatforms.length > 0) {\n logger.info(`Successful: ${report.successPlatforms.join(', ')}`)\n }\n\n if (report.failurePlatforms.length > 0) {\n logger.info(`Failed: ${report.failurePlatforms.join(', ')}`)\n }\n\n logger.info(`Total Duration: ${this.formatDuration(report.totalDurationMs)}`)\n logger.info('')\n logger.info(report.summary)\n logger.info('═'.repeat(60))\n logger.info('')\n\n // 输出详细的平台结果\n logger.info('📋 Detailed Results:')\n report.results.forEach((result) => {\n if (result.success) {\n if (this.config.verbose) {\n logger.success(`[${result.platform}] ✅ ${result.message}`)\n if (result.url) {\n logger.info(` Download: ${result.url}`)\n }\n }\n } else {\n // 失败时总是打印详细错误\n logger.error(`[${result.platform}] ❌ ${result.message}`)\n // 如果有原始错误堆栈,也打印出来\n if (result.error && result.error.stack && this.config.verbose) {\n logger.error(result.error.stack)\n }\n }\n })\n logger.info('')\n }\n\n /**\n * 格式化持续时间\n */\n private formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`\n }\n if (ms < 60000) {\n return `${(ms / 1000).toFixed(1)}s`\n }\n return `${(ms / 60000).toFixed(1)}m`\n }\n\n /**\n * 获取可重试的失败平台\n */\n getRetryablePlatforms(report: UploadReport): string[] {\n return report.failurePlatforms\n }\n\n /**\n * 重试失败的平台\n */\n async retryFailedPlatforms(\n failedPlatforms: string[],\n filePath: string,\n config: any,\n metadata: AppMetadata,\n ): Promise<UploadReport> {\n if (failedPlatforms.length === 0) {\n logger.info('No platforms to retry')\n return {\n totalUploads: 0,\n successCount: 0,\n failureCount: 0,\n successPlatforms: [],\n failurePlatforms: [],\n results: [],\n totalDurationMs: 0,\n summary: 'No platforms to retry',\n }\n }\n\n logger.info(`Retrying ${failedPlatforms.length} failed platform(s)...`)\n return this.uploadToMultiplePlatforms(filePath, config, metadata, failedPlatforms)\n }\n}\n\n/**\n * 创建上传管理器实例\n */\nexport function createUploadManager(config?: UploadManagerConfig): UploadManager {\n return new UploadManager(config)\n}\n","const ANSI_BACKGROUND_OFFSET = 10;\n\nconst wrapAnsi16 = (offset = 0) => code => `\\u001B[${code + offset}m`;\n\nconst wrapAnsi256 = (offset = 0) => code => `\\u001B[${38 + offset};5;${code}m`;\n\nconst wrapAnsi16m = (offset = 0) => (red, green, blue) => `\\u001B[${38 + offset};2;${red};${green};${blue}m`;\n\nconst styles = {\n\tmodifier: {\n\t\treset: [0, 0],\n\t\t// 21 isn't widely supported and 22 does the same thing\n\t\tbold: [1, 22],\n\t\tdim: [2, 22],\n\t\titalic: [3, 23],\n\t\tunderline: [4, 24],\n\t\toverline: [53, 55],\n\t\tinverse: [7, 27],\n\t\thidden: [8, 28],\n\t\tstrikethrough: [9, 29],\n\t},\n\tcolor: {\n\t\tblack: [30, 39],\n\t\tred: [31, 39],\n\t\tgreen: [32, 39],\n\t\tyellow: [33, 39],\n\t\tblue: [34, 39],\n\t\tmagenta: [35, 39],\n\t\tcyan: [36, 39],\n\t\twhite: [37, 39],\n\n\t\t// Bright color\n\t\tblackBright: [90, 39],\n\t\tgray: [90, 39], // Alias of `blackBright`\n\t\tgrey: [90, 39], // Alias of `blackBright`\n\t\tredBright: [91, 39],\n\t\tgreenBright: [92, 39],\n\t\tyellowBright: [93, 39],\n\t\tblueBright: [94, 39],\n\t\tmagentaBright: [95, 39],\n\t\tcyanBright: [96, 39],\n\t\twhiteBright: [97, 39],\n\t},\n\tbgColor: {\n\t\tbgBlack: [40, 49],\n\t\tbgRed: [41, 49],\n\t\tbgGreen: [42, 49],\n\t\tbgYellow: [43, 49],\n\t\tbgBlue: [44, 49],\n\t\tbgMagenta: [45, 49],\n\t\tbgCyan: [46, 49],\n\t\tbgWhite: [47, 49],\n\n\t\t// Bright color\n\t\tbgBlackBright: [100, 49],\n\t\tbgGray: [100, 49], // Alias of `bgBlackBright`\n\t\tbgGrey: [100, 49], // Alias of `bgBlackBright`\n\t\tbgRedBright: [101, 49],\n\t\tbgGreenBright: [102, 49],\n\t\tbgYellowBright: [103, 49],\n\t\tbgBlueBright: [104, 49],\n\t\tbgMagentaBright: [105, 49],\n\t\tbgCyanBright: [106, 49],\n\t\tbgWhiteBright: [107, 49],\n\t},\n};\n\nexport const modifierNames = Object.keys(styles.modifier);\nexport const foregroundColorNames = Object.keys(styles.color);\nexport const backgroundColorNames = Object.keys(styles.bgColor);\nexport const colorNames = [...foregroundColorNames, ...backgroundColorNames];\n\nfunction assembleStyles() {\n\tconst codes = new Map();\n\n\tfor (const [groupName, group] of Object.entries(styles)) {\n\t\tfor (const [styleName, style] of Object.entries(group)) {\n\t\t\tstyles[styleName] = {\n\t\t\t\topen: `\\u001B[${style[0]}m`,\n\t\t\t\tclose: `\\u001B[${style[1]}m`,\n\t\t\t};\n\n\t\t\tgroup[styleName] = styles[styleName];\n\n\t\t\tcodes.set(style[0], style[1]);\n\t\t}\n\n\t\tObject.defineProperty(styles, groupName, {\n\t\t\tvalue: group,\n\t\t\tenumerable: false,\n\t\t});\n\t}\n\n\tObject.defineProperty(styles, 'codes', {\n\t\tvalue: codes,\n\t\tenumerable: false,\n\t});\n\n\tstyles.color.close = '\\u001B[39m';\n\tstyles.bgColor.close = '\\u001B[49m';\n\n\tstyles.color.ansi = wrapAnsi16();\n\tstyles.color.ansi256 = wrapAnsi256();\n\tstyles.color.ansi16m = wrapAnsi16m();\n\tstyles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);\n\tstyles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);\n\tstyles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);\n\n\t// From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js\n\tObject.defineProperties(styles, {\n\t\trgbToAnsi256: {\n\t\t\tvalue(red, green, blue) {\n\t\t\t\t// We use the extended greyscale palette here, with the exception of\n\t\t\t\t// black and white. normal palette only has 4 greyscale shades.\n\t\t\t\tif (red === green && green === blue) {\n\t\t\t\t\tif (red < 8) {\n\t\t\t\t\t\treturn 16;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (red > 248) {\n\t\t\t\t\t\treturn 231;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn Math.round(((red - 8) / 247) * 24) + 232;\n\t\t\t\t}\n\n\t\t\t\treturn 16\n\t\t\t\t\t+ (36 * Math.round(red / 255 * 5))\n\t\t\t\t\t+ (6 * Math.round(green / 255 * 5))\n\t\t\t\t\t+ Math.round(blue / 255 * 5);\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToRgb: {\n\t\t\tvalue(hex) {\n\t\t\t\tconst matches = /[a-f\\d]{6}|[a-f\\d]{3}/i.exec(hex.toString(16));\n\t\t\t\tif (!matches) {\n\t\t\t\t\treturn [0, 0, 0];\n\t\t\t\t}\n\n\t\t\t\tlet [colorString] = matches;\n\n\t\t\t\tif (colorString.length === 3) {\n\t\t\t\t\tcolorString = [...colorString].map(character => character + character).join('');\n\t\t\t\t}\n\n\t\t\t\tconst integer = Number.parseInt(colorString, 16);\n\n\t\t\t\treturn [\n\t\t\t\t\t/* eslint-disable no-bitwise */\n\t\t\t\t\t(integer >> 16) & 0xFF,\n\t\t\t\t\t(integer >> 8) & 0xFF,\n\t\t\t\t\tinteger & 0xFF,\n\t\t\t\t\t/* eslint-enable no-bitwise */\n\t\t\t\t];\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToAnsi256: {\n\t\t\tvalue: hex => styles.rgbToAnsi256(...styles.hexToRgb(hex)),\n\t\t\tenumerable: false,\n\t\t},\n\t\tansi256ToAnsi: {\n\t\t\tvalue(code) {\n\t\t\t\tif (code < 8) {\n\t\t\t\t\treturn 30 + code;\n\t\t\t\t}\n\n\t\t\t\tif (code < 16) {\n\t\t\t\t\treturn 90 + (code - 8);\n\t\t\t\t}\n\n\t\t\t\tlet red;\n\t\t\t\tlet green;\n\t\t\t\tlet blue;\n\n\t\t\t\tif (code >= 232) {\n\t\t\t\t\tred = (((code - 232) * 10) + 8) / 255;\n\t\t\t\t\tgreen = red;\n\t\t\t\t\tblue = red;\n\t\t\t\t} else {\n\t\t\t\t\tcode -= 16;\n\n\t\t\t\t\tconst remainder = code % 36;\n\n\t\t\t\t\tred = Math.floor(code / 36) / 5;\n\t\t\t\t\tgreen = Math.floor(remainder / 6) / 5;\n\t\t\t\t\tblue = (remainder % 6) / 5;\n\t\t\t\t}\n\n\t\t\t\tconst value = Math.max(red, green, blue) * 2;\n\n\t\t\t\tif (value === 0) {\n\t\t\t\t\treturn 30;\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-bitwise\n\t\t\t\tlet result = 30 + ((Math.round(blue) << 2) | (Math.round(green) << 1) | Math.round(red));\n\n\t\t\t\tif (value === 2) {\n\t\t\t\t\tresult += 60;\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\trgbToAnsi: {\n\t\t\tvalue: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToAnsi: {\n\t\t\tvalue: hex => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),\n\t\t\tenumerable: false,\n\t\t},\n\t});\n\n\treturn styles;\n}\n\nconst ansiStyles = assembleStyles();\n\nexport default ansiStyles;\n","import process from 'node:process';\nimport os from 'node:os';\nimport tty from 'node:tty';\n\n// From: https://github.com/sindresorhus/has-flag/blob/main/index.js\n/// function hasFlag(flag, argv = globalThis.Deno?.args ?? process.argv) {\nfunction hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process.argv) {\n\tconst prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');\n\tconst position = argv.indexOf(prefix + flag);\n\tconst terminatorPosition = argv.indexOf('--');\n\treturn position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);\n}\n\nconst {env} = process;\n\nlet flagForceColor;\nif (\n\thasFlag('no-color')\n\t|| hasFlag('no-colors')\n\t|| hasFlag('color=false')\n\t|| hasFlag('color=never')\n) {\n\tflagForceColor = 0;\n} else if (\n\thasFlag('color')\n\t|| hasFlag('colors')\n\t|| hasFlag('color=true')\n\t|| hasFlag('color=always')\n) {\n\tflagForceColor = 1;\n}\n\nfunction envForceColor() {\n\tif ('FORCE_COLOR' in env) {\n\t\tif (env.FORCE_COLOR === 'true') {\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (env.FORCE_COLOR === 'false') {\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);\n\t}\n}\n\nfunction translateLevel(level) {\n\tif (level === 0) {\n\t\treturn false;\n\t}\n\n\treturn {\n\t\tlevel,\n\t\thasBasic: true,\n\t\thas256: level >= 2,\n\t\thas16m: level >= 3,\n\t};\n}\n\nfunction _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {\n\tconst noFlagForceColor = envForceColor();\n\tif (noFlagForceColor !== undefined) {\n\t\tflagForceColor = noFlagForceColor;\n\t}\n\n\tconst forceColor = sniffFlags ? flagForceColor : noFlagForceColor;\n\n\tif (forceColor === 0) {\n\t\treturn 0;\n\t}\n\n\tif (sniffFlags) {\n\t\tif (hasFlag('color=16m')\n\t\t\t|| hasFlag('color=full')\n\t\t\t|| hasFlag('color=truecolor')) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (hasFlag('color=256')) {\n\t\t\treturn 2;\n\t\t}\n\t}\n\n\t// Check for Azure DevOps pipelines.\n\t// Has to be above the `!streamIsTTY` check.\n\tif ('TF_BUILD' in env && 'AGENT_NAME' in env) {\n\t\treturn 1;\n\t}\n\n\tif (haveStream && !streamIsTTY && forceColor === undefined) {\n\t\treturn 0;\n\t}\n\n\tconst min = forceColor || 0;\n\n\tif (env.TERM === 'dumb') {\n\t\treturn min;\n\t}\n\n\tif (process.platform === 'win32') {\n\t\t// Windows 10 build 10586 is the first Windows release that supports 256 colors.\n\t\t// Windows 10 build 14931 is the first release that supports 16m/TrueColor.\n\t\tconst osRelease = os.release().split('.');\n\t\tif (\n\t\t\tNumber(osRelease[0]) >= 10\n\t\t\t&& Number(osRelease[2]) >= 10_586\n\t\t) {\n\t\t\treturn Number(osRelease[2]) >= 14_931 ? 3 : 2;\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\tif ('CI' in env) {\n\t\tif (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => key in env)) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {\n\t\t\treturn 1;\n\t\t}\n\n\t\treturn min;\n\t}\n\n\tif ('TEAMCITY_VERSION' in env) {\n\t\treturn /^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;\n\t}\n\n\tif (env.COLORTERM === 'truecolor') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'xterm-kitty') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'xterm-ghostty') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'wezterm') {\n\t\treturn 3;\n\t}\n\n\tif ('TERM_PROGRAM' in env) {\n\t\tconst version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);\n\n\t\tswitch (env.TERM_PROGRAM) {\n\t\t\tcase 'iTerm.app': {\n\t\t\t\treturn version >= 3 ? 3 : 2;\n\t\t\t}\n\n\t\t\tcase 'Apple_Terminal': {\n\t\t\t\treturn 2;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\t}\n\n\tif (/-256(color)?$/i.test(env.TERM)) {\n\t\treturn 2;\n\t}\n\n\tif (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {\n\t\treturn 1;\n\t}\n\n\tif ('COLORTERM' in env) {\n\t\treturn 1;\n\t}\n\n\treturn min;\n}\n\nexport function createSupportsColor(stream, options = {}) {\n\tconst level = _supportsColor(stream, {\n\t\tstreamIsTTY: stream && stream.isTTY,\n\t\t...options,\n\t});\n\n\treturn translateLevel(level);\n}\n\nconst supportsColor = {\n\tstdout: createSupportsColor({isTTY: tty.isatty(1)}),\n\tstderr: createSupportsColor({isTTY: tty.isatty(2)}),\n};\n\nexport default supportsColor;\n","// TODO: When targeting Node.js 16, use `String.prototype.replaceAll`.\nexport function stringReplaceAll(string, substring, replacer) {\n\tlet index = string.indexOf(substring);\n\tif (index === -1) {\n\t\treturn string;\n\t}\n\n\tconst substringLength = substring.length;\n\tlet endIndex = 0;\n\tlet returnValue = '';\n\tdo {\n\t\treturnValue += string.slice(endIndex, index) + substring + replacer;\n\t\tendIndex = index + substringLength;\n\t\tindex = string.indexOf(substring, endIndex);\n\t} while (index !== -1);\n\n\treturnValue += string.slice(endIndex);\n\treturn returnValue;\n}\n\nexport function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {\n\tlet endIndex = 0;\n\tlet returnValue = '';\n\tdo {\n\t\tconst gotCR = string[index - 1] === '\\r';\n\t\treturnValue += string.slice(endIndex, (gotCR ? index - 1 : index)) + prefix + (gotCR ? '\\r\\n' : '\\n') + postfix;\n\t\tendIndex = index + 1;\n\t\tindex = string.indexOf('\\n', endIndex);\n\t} while (index !== -1);\n\n\treturnValue += string.slice(endIndex);\n\treturn returnValue;\n}\n","import ansiStyles from '#ansi-styles';\nimport supportsColor from '#supports-color';\nimport { // eslint-disable-line import/order\n\tstringReplaceAll,\n\tstringEncaseCRLFWithFirstIndex,\n} from './utilities.js';\n\nconst {stdout: stdoutColor, stderr: stderrColor} = supportsColor;\n\nconst GENERATOR = Symbol('GENERATOR');\nconst STYLER = Symbol('STYLER');\nconst IS_EMPTY = Symbol('IS_EMPTY');\n\n// `supportsColor.level` → `ansiStyles.color[name]` mapping\nconst levelMapping = [\n\t'ansi',\n\t'ansi',\n\t'ansi256',\n\t'ansi16m',\n];\n\nconst styles = Object.create(null);\n\nconst applyOptions = (object, options = {}) => {\n\tif (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {\n\t\tthrow new Error('The `level` option should be an integer from 0 to 3');\n\t}\n\n\t// Detect level if not set manually\n\tconst colorLevel = stdoutColor ? stdoutColor.level : 0;\n\tobject.level = options.level === undefined ? colorLevel : options.level;\n};\n\nexport class Chalk {\n\tconstructor(options) {\n\t\t// eslint-disable-next-line no-constructor-return\n\t\treturn chalkFactory(options);\n\t}\n}\n\nconst chalkFactory = options => {\n\tconst chalk = (...strings) => strings.join(' ');\n\tapplyOptions(chalk, options);\n\n\tObject.setPrototypeOf(chalk, createChalk.prototype);\n\n\treturn chalk;\n};\n\nfunction createChalk(options) {\n\treturn chalkFactory(options);\n}\n\nObject.setPrototypeOf(createChalk.prototype, Function.prototype);\n\nfor (const [styleName, style] of Object.entries(ansiStyles)) {\n\tstyles[styleName] = {\n\t\tget() {\n\t\t\tconst builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);\n\t\t\tObject.defineProperty(this, styleName, {value: builder});\n\t\t\treturn builder;\n\t\t},\n\t};\n}\n\nstyles.visible = {\n\tget() {\n\t\tconst builder = createBuilder(this, this[STYLER], true);\n\t\tObject.defineProperty(this, 'visible', {value: builder});\n\t\treturn builder;\n\t},\n};\n\nconst getModelAnsi = (model, level, type, ...arguments_) => {\n\tif (model === 'rgb') {\n\t\tif (level === 'ansi16m') {\n\t\t\treturn ansiStyles[type].ansi16m(...arguments_);\n\t\t}\n\n\t\tif (level === 'ansi256') {\n\t\t\treturn ansiStyles[type].ansi256(ansiStyles.rgbToAnsi256(...arguments_));\n\t\t}\n\n\t\treturn ansiStyles[type].ansi(ansiStyles.rgbToAnsi(...arguments_));\n\t}\n\n\tif (model === 'hex') {\n\t\treturn getModelAnsi('rgb', level, type, ...ansiStyles.hexToRgb(...arguments_));\n\t}\n\n\treturn ansiStyles[type][model](...arguments_);\n};\n\nconst usedModels = ['rgb', 'hex', 'ansi256'];\n\nfor (const model of usedModels) {\n\tstyles[model] = {\n\t\tget() {\n\t\t\tconst {level} = this;\n\t\t\treturn function (...arguments_) {\n\t\t\t\tconst styler = createStyler(getModelAnsi(model, levelMapping[level], 'color', ...arguments_), ansiStyles.color.close, this[STYLER]);\n\t\t\t\treturn createBuilder(this, styler, this[IS_EMPTY]);\n\t\t\t};\n\t\t},\n\t};\n\n\tconst bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);\n\tstyles[bgModel] = {\n\t\tget() {\n\t\t\tconst {level} = this;\n\t\t\treturn function (...arguments_) {\n\t\t\t\tconst styler = createStyler(getModelAnsi(model, levelMapping[level], 'bgColor', ...arguments_), ansiStyles.bgColor.close, this[STYLER]);\n\t\t\t\treturn createBuilder(this, styler, this[IS_EMPTY]);\n\t\t\t};\n\t\t},\n\t};\n}\n\nconst proto = Object.defineProperties(() => {}, {\n\t...styles,\n\tlevel: {\n\t\tenumerable: true,\n\t\tget() {\n\t\t\treturn this[GENERATOR].level;\n\t\t},\n\t\tset(level) {\n\t\t\tthis[GENERATOR].level = level;\n\t\t},\n\t},\n});\n\nconst createStyler = (open, close, parent) => {\n\tlet openAll;\n\tlet closeAll;\n\tif (parent === undefined) {\n\t\topenAll = open;\n\t\tcloseAll = close;\n\t} else {\n\t\topenAll = parent.openAll + open;\n\t\tcloseAll = close + parent.closeAll;\n\t}\n\n\treturn {\n\t\topen,\n\t\tclose,\n\t\topenAll,\n\t\tcloseAll,\n\t\tparent,\n\t};\n};\n\nconst createBuilder = (self, _styler, _isEmpty) => {\n\t// Single argument is hot path, implicit coercion is faster than anything\n\t// eslint-disable-next-line no-implicit-coercion\n\tconst builder = (...arguments_) => applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));\n\n\t// We alter the prototype because we must return a function, but there is\n\t// no way to create a function with a different prototype\n\tObject.setPrototypeOf(builder, proto);\n\n\tbuilder[GENERATOR] = self;\n\tbuilder[STYLER] = _styler;\n\tbuilder[IS_EMPTY] = _isEmpty;\n\n\treturn builder;\n};\n\nconst applyStyle = (self, string) => {\n\tif (self.level <= 0 || !string) {\n\t\treturn self[IS_EMPTY] ? '' : string;\n\t}\n\n\tlet styler = self[STYLER];\n\n\tif (styler === undefined) {\n\t\treturn string;\n\t}\n\n\tconst {openAll, closeAll} = styler;\n\tif (string.includes('\\u001B')) {\n\t\twhile (styler !== undefined) {\n\t\t\t// Replace any instances already present with a re-opening code\n\t\t\t// otherwise only the part of the string until said closing code\n\t\t\t// will be colored, and the rest will simply be 'plain'.\n\t\t\tstring = stringReplaceAll(string, styler.close, styler.open);\n\n\t\t\tstyler = styler.parent;\n\t\t}\n\t}\n\n\t// We can move both next actions out of loop, because remaining actions in loop won't have\n\t// any/visible effect on parts we add here. Close the styling before a linebreak and reopen\n\t// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92\n\tconst lfIndex = string.indexOf('\\n');\n\tif (lfIndex !== -1) {\n\t\tstring = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);\n\t}\n\n\treturn openAll + string + closeAll;\n};\n\nObject.defineProperties(createChalk.prototype, styles);\n\nconst chalk = createChalk();\nexport const chalkStderr = createChalk({level: stderrColor ? stderrColor.level : 0});\n\nexport {\n\tmodifierNames,\n\tforegroundColorNames,\n\tbackgroundColorNames,\n\tcolorNames,\n\n\t// TODO: Remove these aliases in the next major version\n\tmodifierNames as modifiers,\n\tforegroundColorNames as foregroundColors,\n\tbackgroundColorNames as backgroundColors,\n\tcolorNames as colors,\n} from './vendor/ansi-styles/index.js';\n\nexport {\n\tstdoutColor as supportsColor,\n\tstderrColor as supportsColorStderr,\n};\n\nexport default chalk;\n","/**\n * 内部日志工具 (仅 app-ship 包内使用,不对外导出)\n *\n * 提供带颜色的控制台输出:info (蓝), success (绿), warn (黄), error (红), title (青)\n * 外部使用者如需自定义日志,可实现 Logger 接口\n */\nimport chalk from 'chalk'\n\nexport interface Logger {\n info(message: string): void\n success(message: string): void\n warn(message: string): void\n error(message: string): void\n title(message: string): void\n newLine(): void\n}\n\nexport class ConsoleLogger implements Logger {\n info(message: string): void {\n console.log(chalk.blue('ℹ️ ' + message))\n }\n success(message: string): void {\n console.log(chalk.green('✅ ' + message))\n }\n warn(message: string): void {\n console.log(chalk.yellow('⚠️ ' + message))\n }\n error(message: string): void {\n console.log(chalk.red('❌ ' + message))\n }\n title(message: string): void {\n console.log(chalk.bold.cyan('\\n' + message + '\\n'))\n }\n newLine(): void {\n console.log('')\n }\n}\n\nexport const logger = new ConsoleLogger()\n","/**\n * 蒲公英 (Pgyer) 上传适配器\n *\n * 认证方式: API Key\n * 支持文件: APK, IPA, AAB\n * API: https://www.pgyer.com/apiv2/app/upload (FormData 上传)\n *\n * 上传流程: FormData 单步上传 → 返回下载链接 + 二维码\n * 特点: 最简单的适配器,适合作为新适配器的参考模板\n */\nimport fs from 'fs-extra'\n\nimport axios from 'axios'\nimport FormData from 'form-data'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\nimport { logger } from '../utils/logger.js'\nimport { createUploadRetryStrategy, RetryConfig } from '../utils/index.js'\n\nexport class PgyerUploader implements IUploader {\n name = 'Pgyer'\n private static UPLOAD_API = 'https://www.pgyer.com/apiv2/app/upload'\n\n /**\n * 验证配置\n * @param config 配置对象\n */\n validateConfig(config: any): boolean {\n if (!config?.publish?.pgyer?.enable) {\n return false\n }\n if (!config.publish.pgyer.apiKey) {\n logger.error('Pgyer apiKey is missing in config')\n return false\n }\n return true\n }\n\n /**\n * 判断是否支持该文件\n * @param filePath 文件路径\n */\n canHandle(filePath: string): boolean {\n const ext = filePath.split('.').pop()?.toLowerCase()\n // 支持 APK, IPA, AAB 三种格式\n return ext === 'apk' || ext === 'ipa' || ext === 'aab'\n }\n\n /**\n * 上传文件到蒲公英\n * @param filePath 文件路径\n * @param config 配置\n * @param metadata 元数据\n */\n async upload(filePath: string, config: any, metadata: AppMetadata): Promise<UploadResult> {\n const pgyerConfig = config.publish?.pgyer\n const apiKey = pgyerConfig?.apiKey\n const desc = metadata.changelog || pgyerConfig?.description || ''\n const retryConfig = config.retry as RetryConfig | undefined\n\n if (!fs.existsSync(filePath)) {\n return {\n platform: 'pgyer',\n success: false,\n message: `File not found: ${filePath}`,\n }\n }\n\n logger.info(`Uploading to Pgyer...`)\n logger.info(`File: ${filePath}`)\n logger.info(`Changelog: ${desc.replace(/\\n/g, ' ')}`)\n\n // Create retry strategy\n const retryStrategy = createUploadRetryStrategy(retryConfig)\n\n // Wrap the upload operation with retry logic\n const result = await retryStrategy.execute(\n () => this.performUpload(filePath, apiKey, desc),\n 'Pgyer upload',\n )\n\n if (result.success) {\n const pgyerData = result.data\n return {\n platform: 'pgyer',\n success: true,\n message: 'Upload success',\n url: pgyerData.fullUrl,\n link: pgyerData.fullUrl,\n qrCode: pgyerData.qrCodeUrl,\n data: pgyerData,\n consoleUrl: 'https://www.pgyer.com/my',\n }\n } else {\n // 规范化错误信息\n const lastError = result.lastError as any\n const errorMsg =\n lastError instanceof Error ? lastError.message : String(lastError || 'Upload failed')\n\n return {\n platform: 'pgyer',\n success: false,\n message: errorMsg, // ✅ 必填且为字符串\n error: result.error,\n }\n }\n }\n\n /**\n * 执行实际上传操作\n * @param filePath 文件路径\n * @param apiKey API Key\n * @param desc 描述\n */\n private async performUpload(filePath: string, apiKey: string, desc: string): Promise<any> {\n const form = new FormData()\n form.append('_api_key', apiKey)\n form.append('buildUpdateDescription', desc)\n form.append('file', fs.createReadStream(filePath))\n\n const response = await axios.post(PgyerUploader.UPLOAD_API, form, {\n headers: {\n ...form.getHeaders(),\n },\n maxContentLength: Infinity,\n maxBodyLength: Infinity,\n })\n\n const data = response.data\n\n if (data.code !== 0) {\n logger.error(`Pgyer API Error: ${data.message}`)\n throw new Error(`Pgyer API Error: ${data.message}`)\n }\n\n const shortcutUrl = data.data.buildShortcutUrl\n let qrCodeUrl = data.data.buildQRCodeURL\n const fullUrl = `https://www.pgyer.com/${shortcutUrl}`\n\n // Normalize QR Code URL (ensure protocol)\n if (qrCodeUrl && qrCodeUrl.startsWith('//')) {\n qrCodeUrl = `https:${qrCodeUrl}`\n } else if (qrCodeUrl && !qrCodeUrl.startsWith('http')) {\n // If it's just a path or something weird, we fallback or try to prefix\n // But Pgyer V2 usually returns full URL.\n }\n\n logger.success(`Upload to Pgyer success!`)\n logger.info(`Download URL: ${fullUrl}`)\n\n return {\n fullUrl,\n qrCodeUrl,\n shortcutUrl,\n }\n }\n}\n","/**\n * 重试策略 (RetryStrategy)\n *\n * 职责:\n * 1. 对上传过程中的错误进行分类 (网络/认证/服务器/客户端/临时/未知)\n * 2. 判断错误是否值得重试 (网络、服务器、临时错误可重试;认证、客户端错误不重试)\n * 3. 计算指数退避延迟 (initialDelay * multiplier^retryCount + 随机抖动)\n * 4. 执行带自动重试的异步操作 (execute 方法)\n *\n * 默认配置: 最多重试 3 次, 初始延迟 1s, 乘数 2, 上限 30s\n */\nimport { logger } from './logger.js'\nexport interface RetryConfig {\n // 最大重试次数\n maxRetries?: number\n // 初始延迟时间(毫秒)\n initialDelayMs?: number\n // 指数退避倍数\n backoffMultiplier?: number\n // 最大延迟时间(毫秒)\n maxDelayMs?: number\n}\n\n/**\n * 重试结果\n */\nexport interface RetryResult<T> {\n success: boolean\n data?: T\n error?: Error\n totalAttempts: number\n lastError?: string\n}\n\n/**\n * 错误分类\n */\nexport enum ErrorCategory {\n // 网络错误(应该重试)\n NETWORK_ERROR = 'NETWORK_ERROR',\n // 临时错误(应该重试)\n TEMPORARY_ERROR = 'TEMPORARY_ERROR',\n // 服务器错误(应该重试)\n SERVER_ERROR = 'SERVER_ERROR',\n // 认证错误(不应该重试)\n AUTH_ERROR = 'AUTH_ERROR',\n // 客户端错误(不应该重试)\n CLIENT_ERROR = 'CLIENT_ERROR',\n // 未知错误(根据配置决定)\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n}\n\n/**\n * 重试策略管理器\n */\nexport class RetryStrategy {\n private config: Required<RetryConfig>\n\n constructor(config: RetryConfig = {}) {\n this.config = {\n maxRetries: config.maxRetries ?? 3,\n initialDelayMs: config.initialDelayMs ?? 1000,\n backoffMultiplier: config.backoffMultiplier ?? 2,\n maxDelayMs: config.maxDelayMs ?? 30000,\n }\n }\n\n /**\n * 根据错误类型判断是否应该重试\n */\n shouldRetry(error: Error, retryCount: number): boolean {\n if (retryCount >= this.config.maxRetries) {\n return false\n }\n\n const category = this.classifyError(error)\n return this.isRetryableCategory(category)\n }\n\n /**\n * 对错误进行分类\n */\n classifyError(error: Error): ErrorCategory {\n const message = error.message.toLowerCase()\n const errorStr = JSON.stringify(error).toLowerCase()\n\n // 网络错误\n if (\n message.includes('econnrefused') ||\n message.includes('enotfound') ||\n message.includes('etimedout') ||\n message.includes('network') ||\n message.includes('socket hang up') ||\n message.includes('socket') ||\n message.includes('econnreset') ||\n message.includes('epipe') ||\n message.includes('hang up')\n ) {\n return ErrorCategory.NETWORK_ERROR\n }\n\n // 认证错误(401, 403)\n if (\n message.includes('401') ||\n message.includes('403') ||\n message.includes('unauthorized') ||\n message.includes('forbidden') ||\n message.includes('invalid') ||\n message.includes('token')\n ) {\n return ErrorCategory.AUTH_ERROR\n }\n\n // 服务器错误(5xx)\n if (\n message.includes('500') ||\n message.includes('502') ||\n message.includes('503') ||\n message.includes('504') ||\n message.includes('server error') ||\n message.includes('服务器端异常')\n ) {\n return ErrorCategory.SERVER_ERROR\n }\n\n // 客户端错误(4xx,除了 401/403)\n if (\n message.includes('400') ||\n message.includes('404') ||\n message.includes('bad request') ||\n message.includes('not found')\n ) {\n return ErrorCategory.CLIENT_ERROR\n }\n\n // 临时性错误(超时、限流等)\n if (\n message.includes('timeout') ||\n message.includes('rate limit') ||\n message.includes('too many') ||\n message.includes('429')\n ) {\n return ErrorCategory.TEMPORARY_ERROR\n }\n\n return ErrorCategory.UNKNOWN_ERROR\n }\n\n /**\n * 判断错误类别是否可重试\n */\n private isRetryableCategory(category: ErrorCategory): boolean {\n const retryableCategories = [\n ErrorCategory.NETWORK_ERROR,\n ErrorCategory.TEMPORARY_ERROR,\n ErrorCategory.SERVER_ERROR,\n ]\n return retryableCategories.includes(category)\n }\n\n /**\n * 计算延迟时间(使用指数退避策略)\n */\n calculateDelay(retryCount: number): number {\n const exponentialDelay =\n this.config.initialDelayMs * Math.pow(this.config.backoffMultiplier, retryCount)\n // 添加随机抖动(0-20%)\n const jitter = exponentialDelay * (Math.random() * 0.2)\n const delay = Math.min(exponentialDelay + jitter, this.config.maxDelayMs)\n return Math.round(delay)\n }\n\n /**\n * 等待指定时间\n */\n private async sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n }\n\n /**\n * 执行带重试的异步函数\n */\n async execute<T>(\n fn: () => Promise<T>,\n operationName: string = 'Operation',\n ): Promise<RetryResult<T>> {\n let lastError: Error | undefined\n let attempt = 0\n\n while (attempt <= this.config.maxRetries) {\n attempt++\n\n try {\n logger.info(`${operationName} (Attempt ${attempt}/${this.config.maxRetries + 1})`)\n const result = await fn()\n if (attempt > 1) {\n logger.success(`${operationName} succeeded after ${attempt} attempts`)\n }\n return {\n success: true,\n data: result,\n totalAttempts: attempt,\n }\n } catch (error: any) {\n lastError = error\n const errorMessage = error.message || String(error)\n const category = this.classifyError(error)\n\n logger.warn(`${operationName} failed (Attempt ${attempt}): ${errorMessage} [${category}]`)\n\n if (!this.shouldRetry(error, attempt)) {\n logger.error(`${operationName} failed with non-retryable error: ${errorMessage}`)\n throw error // 直接抛出,由适配器 catch 处理\n }\n\n if (attempt <= this.config.maxRetries) {\n const delayMs = this.calculateDelay(attempt - 1)\n logger.info(\n `Retrying ${operationName} after ${delayMs}ms (${this.config.maxRetries - attempt + 1} retries left)...`,\n )\n await this.sleep(delayMs)\n }\n }\n }\n\n throw lastError || new Error(`${operationName} failed after all retries`)\n }\n}\n\n/**\n * 默认重试配置\n */\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n initialDelayMs: 1000,\n backoffMultiplier: 2,\n maxDelayMs: 30000,\n}\n\n/**\n * 为上传操作创建重试策略\n */\nexport function createUploadRetryStrategy(config?: RetryConfig): RetryStrategy {\n return new RetryStrategy({\n ...DEFAULT_RETRY_CONFIG,\n ...config,\n })\n}\n","import crypto from 'crypto'\nimport fs from 'fs-extra'\nimport path from 'path'\nimport { logger } from './logger.js'\n\n/**\n * Apple App Store Connect API JWT 生成器\n *\n * 使用 ES256 (ECDSA with SHA-256) 算法生成签名 JWT\n * 有效期: 最多 20 分钟\n *\n * 参考: https://developer.apple.com/documentation/appstoreconnectapi/generating-tokens-for-api-requests\n */\nexport class AppleJWTGenerator {\n private issuerId: string\n private keyId: string\n private privateKey: string\n\n constructor(issuerId: string, keyId: string, privateKey: string) {\n this.issuerId = issuerId\n this.keyId = keyId\n this.privateKey = privateKey\n }\n\n /**\n * 从文件路径加载私钥内容\n */\n static async fromFile(\n issuerId: string,\n keyId: string,\n privateKeyPath: string,\n ): Promise<AppleJWTGenerator> {\n try {\n const privateKey = await fs.readFile(privateKeyPath, 'utf-8')\n return new AppleJWTGenerator(issuerId, keyId, privateKey)\n } catch (error: any) {\n throw new Error(`Failed to load Apple private key from ${privateKeyPath}: ${error.message}`)\n }\n }\n\n /**\n * 从内容字符串创建生成器\n */\n static fromContent(\n issuerId: string,\n keyId: string,\n privateKeyContent: string,\n ): AppleJWTGenerator {\n return new AppleJWTGenerator(issuerId, keyId, privateKeyContent)\n }\n\n /**\n * 生成 JWT 令牌\n * @returns Base64URL 编码的 JWT 字符串\n */\n generate(): string {\n try {\n // 1. 创建 Header\n const header = this.createHeader()\n const headerEncoded = this.base64urlEncode(JSON.stringify(header))\n\n // 2. 创建 Payload\n const payload = this.createPayload()\n const payloadEncoded = this.base64urlEncode(JSON.stringify(payload))\n\n // 3. 签名\n const signatureInput = `${headerEncoded}.${payloadEncoded}`\n const signature = this.sign(signatureInput)\n\n // 4. 组合\n return `${signatureInput}.${signature}`\n } catch (error: any) {\n logger.error(`Failed to generate Apple JWT: ${error.message}`)\n throw error\n }\n }\n\n /**\n * 创建 JWT Header\n */\n private createHeader(): Record<string, string> {\n return {\n alg: 'ES256',\n kid: this.keyId,\n typ: 'JWT',\n }\n }\n\n /**\n * 创建 JWT Payload\n * 有效期: 20 分钟(1200 秒)\n */\n private createPayload(): Record<string, any> {\n const now = Math.floor(Date.now() / 1000)\n return {\n iss: this.issuerId,\n aud: 'appstoreconnect-v1',\n exp: now + 1200, // 20 minutes\n iat: now,\n }\n }\n\n /**\n * 使用 ES256 算法签名\n * ES256 = ECDSA with SHA-256\n */\n private sign(data: string): string {\n // 1. 使用私钥生成签名\n const sign = crypto.createSign('SHA256')\n sign.update(data)\n sign.end()\n\n // 获取 DER 格式的签名 (Buffer)\n const signature: Buffer = sign.sign({\n key: this.privateKey,\n format: 'pem',\n }) as Buffer\n\n // 2. 将 DER 转换为 IEEE P1363 格式 (r||s)\n // DER 格式: 30 [length] 02 [r-length] [r] 02 [s-length] [s]\n const { r, s } = this.parseDERSignature(signature)\n\n // 3. 组合 r 和 s,每个 32 字节 (256 位)\n const combined = Buffer.concat([r, s])\n\n // 4. Base64URL 编码\n return this.base64urlEncode(combined)\n }\n\n /**\n * 解析 DER 格式的签名并提取 r 和 s\n */\n private parseDERSignature(derSignature: Buffer): { r: Buffer; s: Buffer } {\n let offset = 0\n\n // 跳过 SEQUENCE tag 和 length\n offset += 2 // 30 [length]\n if (derSignature[offset] === 0x81 || derSignature[offset] === 0x82) {\n offset += 1 // extended length\n } else {\n offset += 1 // short length\n }\n\n // 读取 r (INTEGER)\n offset += 1 // 02 tag\n const rLength = derSignature[offset]\n offset += 1\n let r = derSignature.subarray(offset, offset + rLength)\n offset += rLength\n\n // 移除前导 0x00 (如果存在)\n if (r[0] === 0x00 && r.length > 32) {\n r = r.subarray(1)\n }\n\n // 确保 r 是 32 字节\n r = this.padBuffer(r, 32)\n\n // 读取 s (INTEGER)\n offset += 1 // 02 tag\n const sLength = derSignature[offset]\n offset += 1\n let s = derSignature.subarray(offset, offset + sLength)\n\n // 移除前导 0x00 (如果存在)\n if (s[0] === 0x00 && s.length > 32) {\n s = s.subarray(1)\n }\n\n // 确保 s 是 32 字节\n s = this.padBuffer(s, 32)\n\n return { r: Buffer.from(r), s: Buffer.from(s) }\n }\n\n /**\n * 将 Buffer 填充或截断到指定长度\n */\n private padBuffer(buf: Buffer, length: number): Buffer {\n if (buf.length === length) return buf\n if (buf.length > length) return buf.subarray(buf.length - length)\n\n // 前置填充 0x00\n const padded = Buffer.alloc(length)\n buf.copy(padded, length - buf.length)\n return padded\n }\n\n /**\n * Base64URL 编码 (RFC 4648)\n */\n private base64urlEncode(data: string | Buffer): string {\n const base64 = Buffer.from(data).toString('base64')\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '')\n }\n}\n","import path from 'path'\nimport fs from 'fs'\nimport crypto from 'crypto'\nimport { logger } from './logger.js'\n\n/**\n * 安装包版本信息\n */\nexport interface PackageInfo {\n /** 版本名称,如 \"1.2.3\" */\n versionName?: string\n /** 版本号(构建号),如 \"42\" */\n versionCode?: string\n /** 包名/Bundle ID,如 \"com.example.app\" */\n packageName?: string\n /** CPU 架构列表 (Android),如 [\"arm64-v8a\", \"armeabi-v7a\"] */\n nativeCode?: string[]\n /** 文件 MD5 校验值 */\n md5?: string\n}\n\n/**\n * 解析选项\n */\nexport interface ParseOptions {\n /** Android SDK 路径 */\n androidSdkPath?: string\n}\n\n/**\n * 从安装包文件中解析版本信息\n *\n * 支持三种格式:\n * - APK: 使用 aapt2/aapt(Android SDK 自带)\n * - IPA: 使用 unzip + plutil(macOS 原生)\n * - HAP: 使用 unzip(系统自带)\n *\n * 解析失败时返回 null,不会抛出异常\n */\nexport async function parsePackageInfo(\n filePath: string,\n options?: ParseOptions,\n): Promise<PackageInfo | null> {\n const ext = path.extname(filePath).toLowerCase()\n\n try {\n switch (ext) {\n case '.apk':\n return await parseApk(filePath, options)\n case '.ipa':\n return await parseIpa(filePath)\n case '.hap':\n return await parseHap(filePath)\n default:\n logger.warn(`[PackageParser] 不支持的文件格式: ${ext}`)\n return null\n }\n } catch (error: any) {\n logger.warn(`[PackageParser] 解析失败: ${error.message}`)\n return null\n }\n}\n\n/**\n * 执行命令行工具,返回 stdout\n */\nfunction exec(cmd: string, args: string[], timeoutMs = 15000): Promise<string> {\n const { execFile } = require('child_process')\n return new Promise((resolve, reject) => {\n execFile(\n cmd,\n args,\n { timeout: timeoutMs, maxBuffer: 1024 * 1024 },\n (error: any, stdout: string, stderr: string) => {\n if (error) {\n reject(error)\n } else {\n resolve(stdout)\n }\n },\n )\n })\n}\n\n/**\n * 智能获取 aapt2 或 aapt 的路径\n */\nasync function getAaptPath(options?: ParseOptions): Promise<string | null> {\n // 1. 尝试使用用户手动配置的路径 (最高优先级)\n if (options?.androidSdkPath && fs.existsSync(options.androidSdkPath)) {\n const buildToolsDir = path.join(options.androidSdkPath, 'build-tools')\n if (fs.existsSync(buildToolsDir)) {\n const tool = findInBuildTools(buildToolsDir)\n if (tool) return tool\n }\n }\n\n // 2. 尝试直接从环境变量 path 中查找\n if (await commandExists('aapt2')) return 'aapt2'\n if (await commandExists('aapt')) return 'aapt'\n\n // 3. 尝试从 ANDROID_HOME 或 ANDROID_SDK_ROOT 查找\n const sdkRoot =\n process.env.ANDROID_HOME ||\n process.env.ANDROID_SDK_ROOT ||\n path.join(process.env.HOME || '', 'Library/Android/sdk')\n\n if (sdkRoot && fs.existsSync(sdkRoot)) {\n const buildToolsDir = path.join(sdkRoot, 'build-tools')\n if (fs.existsSync(buildToolsDir)) {\n const tool = findInBuildTools(buildToolsDir)\n if (tool) return tool\n }\n }\n\n return null\n}\n\n/**\n * 在 build-tools 目录下查找 aapt2/aapt\n */\nfunction findInBuildTools(buildToolsDir: string): string | null {\n // 获取版本号最高的 build-tools 目录\n const versions = fs\n .readdirSync(buildToolsDir)\n .filter((dir) => fs.lstatSync(path.join(buildToolsDir, dir)).isDirectory())\n .sort((a, b) => b.localeCompare(a, undefined, { numeric: true }))\n\n for (const version of versions) {\n const aapt2 = path.join(buildToolsDir, version, 'aapt2')\n if (fs.existsSync(aapt2)) return aapt2\n const aapt = path.join(buildToolsDir, version, 'aapt')\n if (fs.existsSync(aapt)) return aapt\n }\n return null\n}\n\n/**\n * 检查命令是否可用\n */\nasync function commandExists(cmd: string): Promise<boolean> {\n try {\n await exec('which', [cmd], 3000)\n return true\n } catch {\n return false\n }\n}\n\n// ─── APK ────────────────────────────────────────────────────\n\nasync function parseApk(filePath: string, options?: ParseOptions): Promise<PackageInfo | null> {\n const tool = await getAaptPath(options)\n\n if (!tool) {\n logger.warn(\n '[PackageParser] ⚠️ aapt2/aapt 不可用 (请检查 ANDROID_HOME 或加入 PATH),无法解析 APK 版本信息',\n )\n return null\n }\n\n const output = await exec(tool, ['dump', 'badging', filePath])\n\n // 匹配: package: name='com.example.app' versionCode='42' versionName='1.2.3' ...\n const packageMatch = output.match(\n /package:\\s+name='([^']*)'.*?versionCode='([^']*)'.*?versionName='([^']*)'/,\n )\n\n if (!packageMatch) {\n logger.warn('[PackageParser] APK badging 输出中未找到版本信息')\n return null\n }\n\n const info: PackageInfo = {\n packageName: packageMatch[1] || undefined,\n versionCode: packageMatch[2] || undefined,\n versionName: packageMatch[3] || undefined,\n }\n\n // 匹配架构: native-code: 'arm64-v8a' 'armeabi-v7a'\n const nativeCodeMatch = output.match(/native-code:\\s+((?:'[^']*'\\s*)*)/)\n if (nativeCodeMatch) {\n info.nativeCode = nativeCodeMatch[1]\n .split(/\\s+/)\n .filter((s) => s.startsWith(\"'\") && s.endsWith(\"'\"))\n .map((s) => s.slice(1, -1))\n }\n\n // 计算 MD5\n try {\n const fileBuffer = fs.readFileSync(filePath)\n info.md5 = crypto.createHash('md5').update(fileBuffer).digest('hex').toLowerCase()\n } catch (e: any) {\n logger.warn(`[PackageParser] 计算 MD5 失败: ${e.message}`)\n }\n\n logger.info(\n `[PackageParser] APK: ${info.packageName} v${info.versionName}+${info.versionCode} arch:${info.nativeCode?.join(',') || 'none'}`,\n )\n return info\n}\n\n// ─── IPA ────────────────────────────────────────────────────\n\nasync function parseIpa(filePath: string): Promise<PackageInfo | null> {\n // macOS 环境检测\n if (!(await commandExists('plutil'))) {\n logger.warn('[PackageParser] plutil 不可用(非 macOS?),无法解析 IPA')\n return null\n }\n\n // 1. 定位 Info.plist 路径\n const listOutput = await exec('unzip', ['-Z1', filePath])\n const plistPath = listOutput\n .split('\\n')\n .find((line) => /^Payload\\/[^/]+\\.app\\/Info\\.plist$/.test(line.trim()))\n\n if (!plistPath) {\n logger.warn('[PackageParser] IPA 中未找到 Info.plist')\n return null\n }\n\n // 2. 提取 Info.plist 并转为 JSON\n const plistData = await exec('unzip', ['-p', filePath, plistPath.trim()])\n\n // plutil 从 stdin 读取:通过临时管道\n const jsonStr = await new Promise<string>((resolve, reject) => {\n const child = require('child_process').spawn('plutil', ['-convert', 'json', '-o', '-', '-'], {\n timeout: 10000,\n })\n let stdout = ''\n let stderr = ''\n child.stdout.on('data', (d: Buffer) => (stdout += d.toString()))\n child.stderr.on('data', (d: Buffer) => (stderr += d.toString()))\n child.on('close', (code: number) => {\n if (code === 0) resolve(stdout)\n else reject(new Error(`plutil 失败: ${stderr}`))\n })\n child.stdin.write(plistData)\n child.stdin.end()\n })\n\n const plist = JSON.parse(jsonStr)\n\n const info: PackageInfo = {\n versionName: plist.CFBundleShortVersionString || undefined,\n versionCode: plist.CFBundleVersion || undefined,\n packageName: plist.CFBundleIdentifier || undefined,\n }\n\n logger.info(`[PackageParser] IPA: ${info.packageName} v${info.versionName}+${info.versionCode}`)\n return info\n}\n\n// ─── HAP ────────────────────────────────────────────────────\n\nasync function parseHap(filePath: string): Promise<PackageInfo | null> {\n // HarmonyOS HAP 包含 module.json(Stage 模型)或 config.json(FA 模型)\n let jsonStr: string | null = null\n\n // 优先尝试 Stage 模型的 module.json\n try {\n jsonStr = await exec('unzip', ['-p', filePath, 'module.json'])\n } catch {\n // 降级到 FA 模型的 config.json\n try {\n jsonStr = await exec('unzip', ['-p', filePath, 'config.json'])\n } catch {\n logger.warn('[PackageParser] HAP 中未找到 module.json 或 config.json')\n return null\n }\n }\n\n const config = JSON.parse(jsonStr)\n\n // Stage 模型: { app: { versionName, versionCode, bundleName } }\n // FA 模型: { app: { version: { name, code }, bundleName } }\n const app = config.app || {}\n const info: PackageInfo = {\n versionName: app.versionName || app.version?.name || undefined,\n versionCode: String(app.versionCode ?? app.version?.code ?? ''),\n packageName: app.bundleName || undefined,\n }\n\n if (!info.versionCode) info.versionCode = undefined\n\n logger.info(`[PackageParser] HAP: ${info.packageName} v${info.versionName}+${info.versionCode}`)\n return info\n}\n","/**\n * 华为 AppGallery Connect 上传适配器\n *\n * 认证方式: OAuth2 (clientId + clientSecret)\n * 支持文件: APK, AAB\n * API: https://connect-api.cloud.huawei.com (支持多区域)\n *\n * 上传流程 (7 步):\n * 1. 获取 OAuth2 Token\n * 2. 获取文件上传 URL\n * 3. 上传安装包\n * 4. 关联文件信息到应用\n * 5. 更新发行说明 (多语言)\n * 6. 上传商店素材 (图标/截图/视频,可选)\n * 7. 提交审核 (releaseType=submit 时)\n *\n * 注意事项:\n * - 认证响应字段名不统一: access_token 和 token 两个都要检查\n * - 文件关联接口返回拼写错误: fileDestUlr (缺字母) 需 fallback fileDestUrl\n * - 大小写不统一: UploadFileRsp vs uploadFileRsp\n */\nimport fs from 'fs-extra'\nimport path from 'path'\nimport { promisify } from 'util'\nimport axios from 'axios'\nimport FormData from 'form-data'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\nimport { logger } from '../utils/logger.js'\nimport { createUploadRetryStrategy, RetryConfig } from '../utils/index.js'\n\n/**\n * 华为文件类型枚举\n * 参考: https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-References/agcapi-app-file-info-update-0000001158365047\n */\nenum HuaweiFileType {\n /** 应用图标 */\n ICON = 0,\n /** 应用截图 */\n SCREENSHOT = 1,\n /** 预览视频 */\n VIDEO = 2,\n /** APK/AAB 安装包 */\n APP_PACKAGE = 5,\n /** App Bundle (AAB) */\n AAB = 7,\n}\n\n/**\n * 华为支持的文件后缀\n */\nconst HUAWEI_SUPPORTED_SUFFIXES = {\n image: ['jpg', 'jpeg', 'png', 'bmp'],\n video: ['mp4', 'mov'],\n package: ['apk', 'aab', 'rpk'],\n}\n\n/**\n * API 上下文(消除参数重复传递)\n */\ninterface ApiContext {\n apiRoot: string\n token: string\n clientId: string\n appId: string\n}\n\nexport class HuaweiUploader implements IUploader {\n name = 'Huawei'\n // 华为上传器默认 API 基础地址\n private static DEFAULT_API_BASE = 'https://connect-api.cloud.huawei.com'\n // 华为上传器获取 Token 路径\n private static TOKEN_PATH = '/api/oauth2/v1/token'\n // 华为上传器发布 API 根路径\n private static PUBLISH_API_PATH = '/api/publish/v2'\n\n /** 获取 API 基础地址 */\n private getApiBase(config: any): string {\n return config?.publish?.huawei?.apiBaseUrl || HuaweiUploader.DEFAULT_API_BASE\n }\n\n /** 获取 Token URL */\n private getTokenUrl(config: any): string {\n return `${this.getApiBase(config)}${HuaweiUploader.TOKEN_PATH}`\n }\n\n /** 获取 Publish API 根路径 */\n private getApiRoot(config: any): string {\n return `${this.getApiBase(config)}${HuaweiUploader.PUBLISH_API_PATH}`\n }\n\n /** 创建 API 请求头(消除 7 处重复) */\n private headers(ctx: ApiContext): any {\n return {\n Authorization: `Bearer ${ctx.token}`,\n client_id: ctx.clientId,\n }\n }\n\n /** 检查 API 响应(消除 6 处重复) */\n private checkResponse(res: any, operation: string): any {\n const code = res.data.ret?.code ?? res.data.code\n if (code !== 0) {\n throw new Error(`${operation} failed: ${res.data.ret?.msg || res.data.msg}`)\n }\n return res.data\n }\n\n /**\n * 验证配置\n * @param config 配置对象\n * @returns 是否有效\n */\n validateConfig(config: any): boolean {\n if (!config?.publish?.huawei?.enable) return false\n\n const h = config.publish.huawei\n if (!h.auth?.clientId || !h.auth?.clientSecret || !h.appId) {\n logger.error('Huawei config missing: clientId, clientSecret, or appId')\n return false\n }\n return true\n }\n\n /**\n * 判断是否支持该文件\n * @param filePath 文件路径\n * @returns 是否支持\n */\n canHandle(filePath: string): boolean {\n const ext = filePath.split('.').pop()?.toLowerCase()\n // 华为仅支持 Android 包: APK, AAB\n return ext === 'apk' || ext === 'aab'\n }\n\n /**\n * 执行上传\n * @param filePath 文件路径\n * @param config 配置\n * @param metadata 元数据\n */\n async upload(filePath: string, config: any, metadata: AppMetadata): Promise<UploadResult> {\n const hwConfig = config.publish.huawei\n const clientId = hwConfig.auth.clientId\n const clientSecret = hwConfig.auth.clientSecret\n const appId = hwConfig.appId\n const releaseType = hwConfig.releaseType || 'draft' // 'draft' or 'submit'\n const suffix = path.extname(filePath).substring(1) // apk, aab\n const retryConfig = config.retry as RetryConfig | undefined\n\n // 获取 Token URL\n const tokenUrl = this.getTokenUrl(config)\n // 获取发布 API 根路径\n const publishApiRoot = this.getApiRoot(config)\n\n logger.info('Starting Huawei AppGallery upload...')\n\n try {\n // 创建重试策略\n const retryStrategy = createUploadRetryStrategy(retryConfig)\n\n // 1. 获取 Access Token\n logger.info('Authenticating...')\n const tokenResult = await retryStrategy.execute(\n () => this.getAccessToken(tokenUrl, clientId, clientSecret),\n 'Huawei authentication',\n )\n if (!tokenResult.success || !tokenResult.data) {\n throw tokenResult.error || new Error('Failed to get access token')\n }\n\n // 创建 API 上下文(消除后续参数重复传递)\n const ctx: ApiContext = {\n apiRoot: publishApiRoot,\n token: tokenResult.data,\n clientId,\n appId,\n }\n\n // 2. 准备产物列表\n const artifacts: Record<string, string> =\n typeof metadata.artifactPath === 'object'\n ? metadata.artifactPath\n : { universal: filePath || (metadata.artifactPath as string) || '' }\n\n logger.info(`[Huawei] 处理产物数量: ${Object.keys(artifacts).length}`)\n\n // 3. 并行上传所有产物\n const uploadResults: Array<{ fileName: string; fileDestUrl: string }> = []\n const uploadPromises = Object.entries(artifacts).map(async ([abi, p]) => {\n if (!p || !fs.existsSync(p)) return\n const currentSuffix = path.extname(p).substring(1)\n \n logger.info(`[Huawei] 正在上传 ${abi} 包: ${path.basename(p)}`)\n const uploadInfo = await retryStrategy.execute(\n () => this.getUploadUrl(ctx, currentSuffix),\n `Huawei get upload URL for ${abi}`,\n )\n if (!uploadInfo.success || !uploadInfo.data) {\n throw uploadInfo.error || new Error(`Failed to get upload URL for ${abi}`)\n }\n\n const uploadFileRes = await retryStrategy.execute(\n () => this.executeUploadRequest(uploadInfo.data!.uploadUrl, uploadInfo.data!.authCode, p),\n `Huawei upload file for ${abi}`,\n )\n if (!uploadFileRes.success || !uploadFileRes.data || uploadFileRes.data.length === 0) {\n throw uploadFileRes.error || new Error(`File upload failed for ${abi}`)\n }\n \n // 记录上传成功的产物信息\n uploadResults.push({\n fileName: path.basename(p),\n fileDestUrl: uploadFileRes.data[0].fileDestUrl,\n })\n })\n\n await Promise.all(uploadPromises)\n\n if (uploadResults.length === 0) {\n throw new Error('No files were successfully uploaded')\n }\n\n // 4. 批量更新应用文件信息\n logger.info(`[Huawei] 正在关联 ${uploadResults.length} 个文件到应用...`)\n const updateInfoResult = await retryStrategy.execute(\n () => this.updateAppFileInfo(ctx, uploadResults, filePath),\n 'Huawei update file info',\n )\n if (!updateInfoResult.success) {\n throw updateInfoResult.error || new Error('Failed to update file info')\n }\n\n // 5. 更新发布说明(可选)\n if (metadata.changelog) {\n try {\n logger.info('Updating release notes...')\n await retryStrategy.execute(\n () => this.updateReleaseNotes(ctx, metadata.changelog, metadata.version),\n 'Huawei update release notes',\n )\n } catch (error: any) {\n logger.warn(`Failed to update release notes: ${error.message}. Continuing...`)\n }\n }\n\n // 6. 上传商店素材\n const assets = hwConfig.assets\n if (assets) {\n await this.uploadStoreAssets(ctx, assets, retryStrategy)\n }\n\n // 7. 提交审核(如果配置)\n if (releaseType === 'submit') {\n try {\n logger.info('Submitting app for review...')\n const submitResult = await retryStrategy.execute(\n () => this.submitForReview(ctx, metadata.version),\n 'Huawei submit for review',\n )\n if (!submitResult.success) {\n throw submitResult.error || new Error('Failed to submit for review')\n }\n logger.success('Huawei upload successful and submitted for review!')\n return {\n platform: 'huawei',\n success: true,\n message: 'Upload and review submission successful',\n url: 'https://developer.huawei.com/consumer/cn/service/josp/agc/index.html',\n consoleUrl: 'https://developer.huawei.com/consumer/cn/service/josp/agc/index.html',\n }\n } catch (error: any) {\n logger.warn(\n `Failed to submit for review: ${error.message}. App uploaded but not submitted.`,\n )\n return {\n platform: 'huawei',\n success: true,\n message: 'Upload successful but review submission failed. Please submit manually.',\n url: 'https://developer.huawei.com/consumer/cn/service/josp/agc/index.html',\n consoleUrl: 'https://developer.huawei.com/consumer/cn/service/josp/agc/index.html',\n }\n }\n }\n\n logger.success('Huawei upload successful (Draft status).')\n return {\n platform: 'huawei',\n success: true,\n message: 'Upload success (Draft)',\n url: 'https://developer.huawei.com/consumer/cn/service/josp/agc/index.html',\n consoleUrl: 'https://developer.huawei.com/consumer/cn/service/josp/agc/index.html',\n }\n } catch (error: any) {\n logger.error(`Huawei upload failed: ${error.message}`)\n\n // 安全脱敏:构造一个干净的错误对象返回\n const safeError: any = {\n message: error.message,\n name: error.name,\n code: error.code,\n status: error.response?.status,\n }\n\n // 如果有响应数据,提取关键错误信息,但移除敏感头\n if (error.response?.data) {\n safeError.responseData = error.response.data\n logger.info(`Error Data: ${JSON.stringify(error.response.data)}`)\n }\n\n return {\n platform: 'huawei',\n success: false,\n message: error.message,\n error: safeError,\n }\n }\n }\n\n /**\n * 查询审核状态\n * @param clientId 客户端 ID\n * @param clientSecret 客户端密钥\n * @param appId 应用 ID\n * @param apiBaseUrl API 基础地址(可选)\n */\n async queryReviewStatus(\n clientId: string,\n clientSecret: string,\n appId: string,\n apiBaseUrl?: string,\n ): Promise<any> {\n const baseUrl = apiBaseUrl || HuaweiUploader.DEFAULT_API_BASE\n const tokenUrl = `${baseUrl}${HuaweiUploader.TOKEN_PATH}`\n const apiRoot = `${baseUrl}${HuaweiUploader.PUBLISH_API_PATH}`\n\n try {\n logger.info('Querying review status...')\n const token = await this.getAccessToken(tokenUrl, clientId, clientSecret)\n const ctx: ApiContext = { apiRoot, token: token!, clientId, appId }\n\n const res = await axios.get(`${apiRoot}/app-information`, {\n params: { appId },\n headers: this.headers(ctx),\n })\n\n this.checkResponse(res, 'Query review status')\n const status = res.data.data?.app?.auditStatus || 'unknown'\n logger.info(`Current review status: ${status}`)\n return status\n } catch (error: any) {\n logger.error(`Failed to query review status: ${error.message}`)\n throw error\n }\n }\n\n /**\n * 获取 Access Token\n * @param tokenUrl Token URL\n * @param clientId 客户端 ID\n * @param clientSecret 客户端密钥\n */\n private async getAccessToken(\n tokenUrl: string,\n clientId: string,\n clientSecret: string,\n ): Promise<string | null> {\n const data = {\n client_id: clientId,\n client_secret: clientSecret,\n grant_type: 'client_credentials',\n }\n\n logger.info(`[Huawei Auth] Requesting token with clientId: ${clientId}`)\n try {\n const res = await axios.post(tokenUrl, data, {\n headers: {\n 'Content-Type': 'application/json',\n },\n })\n logger.info(\n `[Huawei Auth] Token response received, keys: ${Object.keys(res.data).join(', ')}`,\n )\n\n // 华为可能返回 access_token 或其他格式\n const token = res.data.access_token || res.data.token\n if (!token) {\n logger.error(\n `[Huawei Auth] No token in response. Full response: ${JSON.stringify(res.data)}`,\n )\n throw new Error(`Invalid token response: ${JSON.stringify(res.data)}`)\n }\n\n logger.info(`[Huawei Auth] Token obtained successfully`)\n return token\n } catch (error: any) {\n logger.error(`[Huawei Auth] Token request failed: ${error.message}`)\n if (error.response?.data) {\n logger.error(`[Huawei Auth] Error response: ${JSON.stringify(error.response.data)}`)\n }\n throw error\n }\n }\n\n /** 获取上传 URL */\n private async getUploadUrl(ctx: ApiContext, suffix: string) {\n logger.info(`[Huawei Upload] Requesting upload URL for appId: ${ctx.appId}, suffix: ${suffix}`)\n const res = await axios.get(`${ctx.apiRoot}/upload-url`, {\n params: { appId: ctx.appId, suffix },\n headers: this.headers(ctx),\n })\n\n this.checkResponse(res, 'Get upload URL')\n return {\n uploadUrl: res.data.uploadUrl,\n authCode: res.data.authCode,\n }\n }\n\n /** 通用文件上传(FormData 方式,无需 API 认证头) */\n private async executeUploadRequest(\n uploadUrl: string,\n authCode: string,\n filePath: string,\n ): Promise<Array<{ fileName: string; fileDestUrl: string }>> {\n const fileName = path.basename(filePath)\n const fileSize = fs.statSync(filePath).size\n\n const form = new FormData()\n form.append('file', fs.createReadStream(filePath), {\n filename: fileName,\n contentType: 'application/octet-stream',\n knownLength: fileSize,\n })\n form.append('authCode', authCode)\n form.append('fileCount', '1')\n form.append('parseType', '1')\n\n const length = await promisify(form.getLength).bind(form)()\n\n logger.info(\n `[Huawei Upload] Uploading: ${fileName} (${(fileSize / 1024 / 1024).toFixed(2)} MB)`,\n )\n\n const res = await axios.post(uploadUrl, form, {\n headers: { ...form.getHeaders(), 'Content-Length': length },\n maxContentLength: Infinity,\n maxBodyLength: Infinity,\n })\n\n if (res.data.result?.resultCode !== '0') {\n throw new Error(`File upload failed: ${JSON.stringify(res.data.result)}`)\n }\n\n const fileInfoList =\n res.data.result?.UploadFileRsp?.fileInfoList ||\n res.data.result?.uploadFileRsp?.fileInfoList ||\n []\n\n if (fileInfoList.length === 0) {\n throw new Error('No file info returned from upload')\n }\n\n return fileInfoList.map((f: any) => ({\n fileName: f.name || fileName,\n fileDestUrl: f.fileDestUlr || f.fileDestUrl || authCode,\n }))\n }\n\n /** 上传文件 (APK/AAB) */\n private async uploadFile(\n uploadUrl: string,\n authCode: string,\n filePath: string,\n ): Promise<{ fileDestUrl: string }> {\n const files = await this.executeUploadRequest(uploadUrl, authCode, filePath)\n if (files.length > 0 && files[0].fileDestUrl) {\n logger.info(`[Huawei Upload] App package uploaded, fileDestUrl: ${files[0].fileDestUrl}`)\n return { fileDestUrl: files[0].fileDestUrl }\n }\n throw new Error('Upload succeeded but fileDestUrl not found in response')\n }\n\n /** 更新应用文件信息 */\n private async updateAppFileInfo(\n ctx: ApiContext,\n files: Array<{ fileName: string; fileDestUrl: string }>,\n anyFilePath: string,\n ) {\n // 判定文件类型: 如果包含 AAB 则设为 7,否则为 5 (APK)\n const hasAab = files.some((f) => f.fileName.toLowerCase().endsWith('.aab'))\n const fileType = hasAab ? HuaweiFileType.AAB : HuaweiFileType.APP_PACKAGE\n\n const res = await axios.put(\n `${ctx.apiRoot}/app-file-info`,\n {\n fileType,\n files: files.map((f) => ({\n fileName: f.fileName,\n fileDestUrl: f.fileDestUrl,\n })),\n },\n {\n params: { appId: ctx.appId },\n headers: this.headers(ctx),\n },\n )\n\n this.checkResponse(res, 'Update file info')\n }\n\n /** 更新发布说明(支持多语言) */\n private async updateReleaseNotes(\n ctx: ApiContext,\n changelog: string | Record<string, string>,\n version: string,\n ): Promise<void> {\n const notes = typeof changelog === 'string' ? { zh_CN: changelog, en_US: changelog } : changelog\n\n const body = {\n defaultLanguage: 'zh_CN',\n languages: [\n {\n lang: 'zh_CN',\n appName: '',\n appDesc: '',\n newFeatures: notes['zh_CN'] || '',\n },\n {\n lang: 'en_US',\n appName: '',\n appDesc: '',\n newFeatures: notes['en_US'] || '',\n },\n ],\n }\n\n const res = await axios.put(`${ctx.apiRoot}/app-info`, body, {\n params: { appId: ctx.appId },\n headers: this.headers(ctx),\n })\n\n this.checkResponse(res, 'Update release notes')\n logger.info('Release notes updated successfully')\n }\n\n /** 提交审核 */\n private async submitForReview(ctx: ApiContext, version: string): Promise<void> {\n const appInfo = await this.getAppInfo(ctx)\n if (!appInfo?.releaseId) {\n throw new Error('Could not get release ID for submission')\n }\n\n try {\n const res = await axios.post(\n `${ctx.apiRoot}/app-submit`,\n {\n releaseId: appInfo.releaseId,\n auditDesc: `Version ${version}`,\n },\n {\n params: { appId: ctx.appId },\n headers: this.headers(ctx),\n },\n )\n\n this.checkResponse(res, 'Submit for review')\n logger.success('App submitted for review successfully')\n } catch (error: any) {\n if (error.response?.status === 404) {\n logger.warn('Huawei review submission API not yet available. Please submit manually.')\n } else {\n throw error\n }\n }\n }\n\n /** 获取应用信息 */\n private async getAppInfo(ctx: ApiContext): Promise<any> {\n const res = await axios.get(`${ctx.apiRoot}/app-information`, {\n params: { appId: ctx.appId },\n headers: this.headers(ctx),\n })\n\n this.checkResponse(res, 'Get app info')\n return res.data.data\n }\n\n /** 上传商店素材(图标、截图、视频) */\n private async uploadStoreAssets(\n ctx: ApiContext,\n assets: { icon?: string; screenshots?: string[]; video?: string },\n retryStrategy: ReturnType<typeof createUploadRetryStrategy>,\n ): Promise<void> {\n const tasks: Array<{\n label: string\n files: string[]\n type: HuaweiFileType\n }> = []\n\n if (assets.icon) {\n tasks.push({\n label: 'icon',\n files: [assets.icon],\n type: HuaweiFileType.ICON,\n })\n }\n if (assets.screenshots?.length) {\n tasks.push({\n label: `${assets.screenshots.length} screenshot(s)`,\n files: assets.screenshots,\n type: HuaweiFileType.SCREENSHOT,\n })\n }\n if (assets.video) {\n tasks.push({\n label: 'preview video',\n files: [assets.video],\n type: HuaweiFileType.VIDEO,\n })\n }\n\n for (const task of tasks) {\n try {\n logger.info(`Uploading ${task.label}...`)\n await this.uploadAssetFiles(ctx, task.files, task.type, retryStrategy)\n logger.success(`${task.label} uploaded successfully`)\n } catch (error: any) {\n logger.warn(`Failed to upload ${task.label}: ${error.message}`)\n }\n }\n }\n\n /** 批量上传素材文件 */\n private async uploadAssetFiles(\n ctx: ApiContext,\n filePaths: string[],\n fileType: HuaweiFileType,\n retryStrategy: ReturnType<typeof createUploadRetryStrategy>,\n ): Promise<void> {\n const allFileInfos: Array<{ fileName: string; fileDestUrl: string }> = []\n\n for (const filePath of filePaths) {\n if (!(await fs.pathExists(filePath))) {\n logger.warn(`Asset file not found, skipping: ${filePath}`)\n continue\n }\n\n const suffix = path.extname(filePath).substring(1).toLowerCase()\n if (!HUAWEI_SUPPORTED_SUFFIXES.image.includes(suffix)) {\n logger.warn(`Unsupported file type ${suffix}, skipping: ${filePath}`)\n continue\n }\n\n const uploadInfoResult = await retryStrategy.execute(\n () => this.getUploadUrl(ctx, suffix),\n 'Huawei get upload URL for asset',\n )\n if (!uploadInfoResult.success || !uploadInfoResult.data) {\n logger.warn(`Failed to get upload URL for: ${filePath}`)\n continue\n }\n const uploadInfo = uploadInfoResult.data\n\n const uploadResult = await retryStrategy.execute(\n () => this.executeUploadRequest(uploadInfo.uploadUrl, uploadInfo.authCode, filePath),\n 'Huawei upload asset',\n )\n if (!uploadResult.success || !uploadResult.data) {\n logger.warn(`Failed to upload: ${filePath}`)\n continue\n }\n\n allFileInfos.push(...uploadResult.data)\n }\n\n if (allFileInfos.length === 0) {\n throw new Error('No assets were uploaded successfully')\n }\n\n await retryStrategy.execute(\n () => this.updateAssetFileInfo(ctx, allFileInfos, fileType),\n 'Huawei update asset file info',\n )\n }\n\n /** 更新素材文件信息(关联到应用) */\n private async updateAssetFileInfo(\n ctx: ApiContext,\n files: Array<{ fileName: string; fileDestUrl: string }>,\n fileType: HuaweiFileType,\n ): Promise<void> {\n const res = await axios.put(\n `${ctx.apiRoot}/app-file-info`,\n {\n fileType,\n lang: 'zh-CN',\n files: files.map((f) => ({\n fileName: f.fileName,\n fileDestUrl: f.fileDestUrl,\n })),\n },\n {\n params: { appId: ctx.appId },\n headers: this.headers(ctx),\n },\n )\n this.checkResponse(res, 'Update asset file info')\n }\n}\n","import fs from 'fs-extra'\nimport path from 'path'\nimport axios from 'axios'\nimport FormData from 'form-data'\nimport crypto from 'crypto'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\nimport { logger } from '../utils/logger.js'\nimport { createUploadRetryStrategy, RetryConfig } from '../utils/index.js'\n\n/**\n * 小米应用商店上传器\n *\n * 基于小米官方「应用自动发布接口」实现\n * 文档: https://dev.mi.com/xiaomihyperos/documentation/detail?pId=1134\n *\n * 上传流程:\n * 1. 构建 RequestData JSON (userName, appInfo, synchroType)\n * 2. 计算所有参数的 MD5 (RequestData 字符串 + APK 文件)\n * 3. 拼接 SIG JSON, 用 RSA 公钥加密\n * 4. POST multipart/form-data 到 /dev/push\n */\nexport class XiaomiUploader implements IUploader {\n name = 'Xiaomi'\n\n private static readonly API_BASE = 'https://api.developer.xiaomi.com/devupload'\n private static readonly PUSH_API = `${XiaomiUploader.API_BASE}/dev/push`\n private static readonly QUERY_API = `${XiaomiUploader.API_BASE}/dev/query`\n private static readonly CATEGORY_API = `${XiaomiUploader.API_BASE}/dev/category`\n\n /**\n * RSA 公钥分段加密 (PKCS1Padding)\n *\n * 小米要求: 使用平台分配的 RSA 公钥加密 SIG JSON,\n * 输出小写十六进制字符串。RSA 1024-bit 密钥单次最多加密 117 字节,\n * 超出需分段加密后拼接。\n */\n private rsaEncryptWithPublicKey(data: string, publicKey: string | crypto.KeyObject): string {\n const buffer = Buffer.from(data, 'utf-8')\n // RSA 1024-bit key: max encrypt block = 117 bytes (128 - 11 padding)\n const maxBlock = 117\n const chunks: Buffer[] = []\n\n for (let offset = 0; offset < buffer.length; offset += maxBlock) {\n const chunk = buffer.subarray(offset, offset + maxBlock)\n const encrypted = crypto.publicEncrypt(\n {\n key: publicKey,\n padding: crypto.constants.RSA_PKCS1_PADDING,\n },\n chunk,\n )\n chunks.push(encrypted)\n }\n\n // 拼接所有加密块, 输出小写 hex\n return Buffer.concat(chunks).toString('hex')\n }\n\n /**\n * 从 X.509 证书或 PEM 公钥中提取可用于加密的公钥\n * 优先使用 crypto.X509Certificate,因为它能同时处理 DER 和 PEM 格式的证书\n */\n private extractPublicKey(buffer: Buffer | string): crypto.KeyObject {\n try {\n // 尝试作为 X509 证书解析\n const x509 = new crypto.X509Certificate(buffer)\n return x509.publicKey\n } catch (e) {\n // 尝试作为普通公钥解析 (可能需要处理成 PEM 格式)\n try {\n const content = buffer.toString()\n if (content.includes('-----BEGIN')) {\n return crypto.createPublicKey(content)\n }\n // 如果是纯 Base64 无头,尝试规范化\n return crypto.createPublicKey(this.normalizePEM(content))\n } catch (e2) {\n throw new Error(`无法提取公钥: ${e instanceof Error ? e.message : '未知错误'}`)\n }\n }\n }\n\n /**\n * 计算文件 MD5 (小写十六进制)\n */\n private async calculateFileMD5(filePath: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const hash = crypto.createHash('md5')\n const stream = fs.createReadStream(filePath)\n stream.on('data', (data) => hash.update(data))\n stream.on('end', () => resolve(hash.digest('hex')))\n stream.on('error', reject)\n })\n }\n\n /**\n * 计算字符串 MD5 (小写十六进制)\n */\n private calculateStringMD5(str: string): string {\n return crypto.createHash('md5').update(str, 'utf-8').digest('hex')\n }\n\n /**\n * 构建 RequestData JSON\n */\n private buildRequestData(params: {\n userName: string\n packageName: string\n appName: string\n updateDesc: string\n uploadType: 'new' | 'update'\n category?: number\n keyWords?: string\n desc?: string\n brief?: string\n privacyUrl?: string\n }): string {\n const { userName, packageName, appName, updateDesc, uploadType } = params\n const synchroType = uploadType === 'new' ? 0 : 1\n\n // 按照文档 appinfo 表格顺序\n const appInfo: any = {\n appName,\n packageName,\n }\n\n if (uploadType === 'new') {\n if (params.category != null) appInfo.category = params.category\n if (params.keyWords) appInfo.keyWords = params.keyWords\n if (params.desc) appInfo.desc = params.desc\n if (params.brief) appInfo.brief = params.brief\n if (params.privacyUrl) appInfo.privacyUrl = params.privacyUrl\n }\n\n if (updateDesc) {\n appInfo.updateDesc = updateDesc\n }\n\n // 按照 Example.java (line 232-234) 的顺序: userName, appInfo, synchroType\n const requestDataObj: any = {\n userName,\n appInfo,\n synchroType,\n }\n\n const result = JSON.stringify(requestDataObj)\n logger.info(`[XIAOMI] 调试 - RequestData 字符串: ${result}`)\n return result\n }\n\n /**\n * 生成只包含 RequestData 的 SIG(用于查询接口)\n */\n private generateQuerySIG(\n requestDataMD5: string,\n privateKey: string,\n publicKey: string | crypto.KeyObject,\n ): string {\n // 按照文档 3.1 示例顺序: sig, password\n const sigObj = {\n sig: [{ name: 'RequestData', hash: requestDataMD5 }],\n password: privateKey.trim(),\n }\n\n const sigJson = JSON.stringify(sigObj)\n logger.info(`[XIAOMI] 调试 - Query SIG 待加密字符串: ${sigJson}`)\n const encrypted = this.rsaEncryptWithPublicKey(sigJson, publicKey)\n logger.info(\n `[XIAOMI] 调试 - Query SIG 加密结果 (Hex, 前 20位): ${encrypted.substring(0, 20)}...`,\n )\n return encrypted\n }\n\n /**\n * 生成包含 RequestData + apk 的加密 SIG 字符串(用于上传接口)\n */\n private generateUploadSIG(\n requestDataMD5: string,\n apkFileMD5: string,\n privateKey: string,\n publicKey: string | crypto.KeyObject,\n extraFiles?: { name: string; hash: string }[],\n ): string {\n const sigItems = [\n { name: 'RequestData', hash: requestDataMD5 },\n { name: 'apk', hash: apkFileMD5 },\n ]\n\n if (extraFiles) {\n sigItems.push(...extraFiles)\n }\n\n // 按照文档 3.1 示例顺序: sig, password\n const sigObj = {\n sig: sigItems,\n password: privateKey.trim(),\n }\n\n const sigJson = JSON.stringify(sigObj)\n logger.info(`[XIAOMI] 调试 - Upload SIG 待加密字符串: ${sigJson}`)\n const encrypted = this.rsaEncryptWithPublicKey(sigJson, publicKey)\n logger.info(\n `[XIAOMI] 调试 - Upload SIG 加密结果 (Hex, 前 20位): ${encrypted.substring(0, 20)}...`,\n )\n return encrypted\n }\n\n /**\n * 将用户输入的公钥字符串规范化为 PEM 格式\n */\n private normalizePEM(publicKey: string): string {\n // 如果已经包含 PEM header 则直接返回\n if (publicKey.includes('-----BEGIN')) {\n return publicKey.trim()\n }\n // 移除可能的换行和空格\n const clean = publicKey.replace(/[\\s\\n\\r]+/g, '')\n // 每 64 字符换行\n const lines = clean.match(/.{1,64}/g) || []\n return `-----BEGIN PUBLIC KEY-----\\n${lines.join('\\n')}\\n-----END PUBLIC KEY-----`\n }\n\n validateConfig(config: any): boolean {\n if (!config?.publish?.xiaomi?.enable) return false\n\n const x = config.publish.xiaomi\n if (!x.auth?.userName || !x.auth?.privateKey) {\n logger.error('Xiaomi config missing: userName or privateKey')\n return false\n }\n if (!x.auth?.publicKeyPath) {\n logger.error('Xiaomi config missing: publicKeyPath')\n return false\n }\n return true\n }\n\n canHandle(filePath: string): boolean {\n const ext = filePath.split('.').pop()?.toLowerCase()\n return ext === 'apk'\n }\n\n /**\n * 查询应用状态\n * 使用 POST /dev/query 接口,需要 SIG 签名认证\n *\n * 返回值说明:\n * - create: true → 需要通过新增方式上传 (synchroType=0)\n * - updateVersion: true → 可以更新包 (synchroType=1)\n * - updateInfo: true → 可以仅更新信息 (synchroType=2)\n */\n private async queryAppStatus(\n userName: string,\n packageName: string,\n privateKey: string,\n publicKeyObj: string | crypto.KeyObject,\n ): Promise<{ type: 'new' | 'update'; queried: boolean; appInfo?: any }> {\n try {\n // 按照文档查询接口建议的顺构建\n const queryData = {\n packageName,\n userName,\n }\n const requestData = JSON.stringify(queryData)\n logger.info(`Query RequestData: ${requestData}`)\n const requestDataMD5 = this.calculateStringMD5(requestData)\n logger.info(`Query RequestData MD5: ${requestDataMD5}`)\n const sig = this.generateQuerySIG(requestDataMD5, privateKey, publicKeyObj)\n\n // 使用 application/x-www-form-urlencoded 格式发送请求 (对应 OkHttp FormBody)\n const params = new URLSearchParams()\n params.append('RequestData', requestData)\n params.append('SIG', sig)\n\n const response = await axios.post(XiaomiUploader.QUERY_API, params.toString(), {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n timeout: 15000,\n })\n\n const data = response.data\n logger.info(`查询应用响应: ${JSON.stringify(data)}`)\n\n // 处理认证错误\n if (data?.result === -20014) {\n throw new Error(\n `小米认证失败: 密码错误 (result=-20014)。请检查 publish.xiaomi.auth.privateKey 是否为最新的 API 私钥。`,\n )\n }\n\n if (data?.result !== 0) {\n logger.warn(`查询返回非零: result=${data?.result}, ${data?.message}`)\n return { type: 'new', queried: false }\n }\n\n // 如果有详细的应用信息,透传出去以便后续合并 (如有需要)\n const appInfo = data.appInfo || null\n\n // 根据响应字段判断上传类型\n if (data.updateVersion === true) {\n // 已有包,可以更新\n return { type: 'update', queried: true, appInfo }\n }\n if (data.create === true) {\n // 后台已建应用但没传过包,小米文档称之为新增 (synchroType=0),但对我们来说属于“首发审核”\n // 为了统一逻辑,我们将其视为一种特殊的更新(即首次提审)\n logger.info('应用已在后台创建但尚未上传过包,将进入首次提审模式')\n return { type: 'new', queried: true, appInfo }\n }\n\n // 默认:有查询结果但无明确标志,尝试更新\n return { type: 'update', queried: true, appInfo }\n } catch (error: any) {\n // 如果是认证错误,应当向上抛出中断流程\n if (error.message.includes('小米认证失败')) {\n throw error\n }\n logger.warn(`查询应用连接异常: ${error.message},将推测为新增应用模式`)\n return { type: 'new', queried: false }\n }\n }\n\n /**\n * 查询小米应用商店分类列表\n * POST /dev/category, 无需参数\n */\n async queryCategories(): Promise<{ categoryId: number; categoryName: string }[] | null> {\n try {\n const response = await axios.post(XiaomiUploader.CATEGORY_API, null, {\n timeout: 10000,\n })\n const data = response.data\n if (data?.result === 0 && Array.isArray(data.categories)) {\n return data.categories\n }\n logger.warn(`获取分类列表失败: ${JSON.stringify(data)}`)\n return null\n } catch (error: any) {\n logger.warn(`获取分类列表异常: ${error.message}`)\n return null\n }\n }\n\n async upload(filePath: string, config: any, metadata: AppMetadata): Promise<UploadResult> {\n const xiaomiConfig = config.publish?.xiaomi\n const { userName, privateKey, publicKeyPath } = xiaomiConfig.auth\n const updateDesc = metadata.changelog || xiaomiConfig?.description || 'App Update'\n\n // 统一处理产物路径\n const artifacts: Record<string, string> =\n typeof metadata.artifactPath === 'object'\n ? metadata.artifactPath\n : { universal: filePath || (typeof metadata.artifactPath === 'string' ? metadata.artifactPath : '') }\n\n const resolvedPublicKey = await this.resolvePublicKey(publicKeyPath)\n if (!resolvedPublicKey) {\n throw new Error('无法获取 RSA 公钥')\n }\n const publicKeyObj = this.extractPublicKey(resolvedPublicKey)\n\n const anyPath = Object.values(artifacts)[0]\n const packageName = xiaomiConfig.packageName || this.inferPackageName(anyPath)\n if (!packageName) throw new Error('缺少 packageName')\n const appName = xiaomiConfig.appName || this.inferAppName(packageName)\n\n try {\n logger.info(`开始上传到小米应用商店 (包含 ${Object.keys(artifacts).length} 个包)...`)\n \n let uploadType: 'new' | 'update' | 'auto' = xiaomiConfig.uploadType || 'auto'\n let finalUploadType: 'new' | 'update'\n let existingAppInfo: any = null\n if (uploadType === 'auto') {\n const status = await this.queryAppStatus(userName, packageName, privateKey, publicKeyObj)\n finalUploadType = status.type\n existingAppInfo = status.appInfo\n } else {\n finalUploadType = uploadType\n }\n\n const retryStrategy = createUploadRetryStrategy(config.retry)\n const result = await retryStrategy.execute(\n () =>\n this.performUpload({\n artifacts,\n userName,\n privateKey,\n publicKey: resolvedPublicKey,\n uploadType: finalUploadType,\n packageName,\n appName: appName || '',\n updateDesc,\n category: xiaomiConfig.category || existingAppInfo?.category,\n keyWords: xiaomiConfig.keyWords || existingAppInfo?.keyWords,\n desc: xiaomiConfig.desc || existingAppInfo?.desc,\n brief: xiaomiConfig.brief || existingAppInfo?.brief,\n privacyUrl: xiaomiConfig.privacyUrl || existingAppInfo?.privacyUrl,\n assets: xiaomiConfig.assets,\n }),\n 'Xiaomi push upload',\n )\n\n return {\n platform: 'xiaomi',\n success: true,\n message: '上传成功',\n consoleUrl: 'https://dev.mi.com/distribute/app/details',\n }\n } catch (error: any) {\n logger.error(`小米上传失败: ${error.message}`)\n return { platform: 'xiaomi', success: false, message: error.message, error }\n }\n }\n\n private async performUpload(params: {\n artifacts: Record<string, string>\n userName: string\n privateKey: string\n publicKey: Buffer | string\n packageName: string\n appName: string\n updateDesc: string\n uploadType: 'new' | 'update'\n category?: number\n keyWords?: string\n desc?: string\n brief?: string\n privacyUrl?: string\n assets?: { icon?: string; screenshots?: string[] }\n }): Promise<any> {\n const { artifacts, userName, privateKey, publicKey, packageName, appName, updateDesc, uploadType, category, keyWords, desc, brief, privacyUrl, assets } = params\n const publicKeyObj = this.extractPublicKey(publicKey)\n\n const requestData = this.buildRequestData({\n userName,\n packageName,\n appName,\n updateDesc,\n uploadType,\n category,\n keyWords,\n desc,\n brief,\n privacyUrl,\n })\n const requestDataMD5 = this.calculateStringMD5(requestData)\n\n // 智能分配主包与次包 (基于 ABI)\n let mainPath: string\n let secondPath: string | undefined = undefined\n\n const artifactEntries = Object.entries(artifacts)\n const arm64 = artifactEntries.find(([abi]) => abi === 'arm64-v8a')\n const arm32 = artifactEntries.find(([abi]) => abi === 'armeabi-v7a')\n\n if (arm64 && arm32) {\n // 同时存在 64 和 32 位\n mainPath = arm64[1]\n secondPath = arm32[1]\n logger.info(`[Xiaomi] 识别到多架构分包: 主包(64位)=${path.basename(mainPath)}, 次包(32位)=${path.basename(secondPath)}`)\n } else {\n mainPath = artifactEntries[0][1]\n if (artifactEntries.length > 1) {\n secondPath = artifactEntries[1][1]\n logger.info(`[Xiaomi] 识别到多个包(非标准名),使用默认顺序: 主包=${path.basename(mainPath)}, 次包=${path.basename(secondPath!)}`)\n } else {\n logger.info(`[Xiaomi] 使用单包模式: ${path.basename(mainPath)}`)\n }\n }\n\n const mainMD5 = await this.calculateFileMD5(mainPath)\n const extraSigItems: { name: string; hash: string }[] = []\n \n // 如果存在次包\n if (secondPath) {\n const secondMD5 = await this.calculateFileMD5(secondPath)\n extraSigItems.push({ name: 'secondApk', hash: secondMD5 })\n }\n\n // 处理资源文件 MD5\n if (assets?.icon && fs.existsSync(assets.icon)) {\n extraSigItems.push({ name: 'icon', hash: await this.calculateFileMD5(assets.icon) })\n }\n // ... (screenshots 省略,保持原有逻辑)\n\n const sig = this.generateUploadSIG(requestDataMD5, mainMD5, privateKey, publicKeyObj, extraSigItems)\n\n const form = new FormData()\n form.append('RequestData', requestData)\n form.append('SIG', sig)\n form.append('apk', fs.createReadStream(mainPath))\n if (secondPath) {\n form.append('secondApk', fs.createReadStream(secondPath))\n }\n // ... (处理 icon 和 screenshots)\n if (assets?.icon && fs.existsSync(assets.icon)) {\n form.append('icon', fs.createReadStream(assets.icon))\n }\n\n const response = await axios.post(XiaomiUploader.PUSH_API, form, {\n headers: form.getHeaders(),\n maxContentLength: Infinity,\n maxBodyLength: Infinity,\n timeout: 120000,\n })\n\n if (response.data?.result !== 0) {\n throw new Error(`小米 API 错误: ${response.data?.message || JSON.stringify(response.data)}`)\n }\n return response.data\n }\n\n /**\n * 解析公钥: 优先使用内容字段, 其次从文件路径读取\n */\n private async resolvePublicKey(publicKeyPath?: string): Promise<Buffer | null> {\n if (publicKeyPath) {\n if (!fs.existsSync(publicKeyPath)) {\n logger.error(`公钥文件不存在: ${publicKeyPath}`)\n return null\n }\n return await fs.readFile(publicKeyPath)\n }\n return null\n }\n\n /**\n * 尝试从文件名推断包名\n * 例如: com.example.app-release.apk → com.example.app\n */\n private inferPackageName(filePath: string): string | null {\n const fileName = filePath.split('/').pop()?.split('\\\\').pop() || ''\n // 常见格式: packageName-release.apk 或 packageName.apk\n const match = fileName.match(/^([\\w.]+?)(?:-(?:release|debug|unsigned))?\\.apk$/i)\n if (match && match[1].includes('.')) {\n return match[1]\n }\n return null\n }\n\n /**\n * 从包名推断应用名称\n * 例如: com.example.app → app 或 com.app → app\n */\n private inferAppName(packageName: string): string | null {\n // 取包名最后一部分,转换为人类可读的格式\n const parts = packageName.split('.')\n if (parts.length === 0) return null\n\n const lastPart = parts[parts.length - 1]\n // 转换驼峰命名为空格分隔,首字母大写\n const humanized = lastPart\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n .replace(/^./, (c) => c.toUpperCase())\n\n return humanized || null\n }\n}\n","/**\n * App Store 上传适配器\n *\n * 认证方式: Apple ID + App 专用密码 (CLI 上传) / API Key (发行说明更新)\n * 支持文件: IPA\n * 工具: 优先使用 Transporter CLI,降级到 xcrun altool\n *\n * 上传流程: 检测可用工具 → 上传 IPA → (可选) 通过 API 更新发行说明\n * 注意事项:\n * - altool 路径需 `bash -l -c` 启动登录 Shell 获取 Xcode 路径\n * - 发行说明只能更新 PREPARE_FOR_SUBMISSION 状态的版本\n * - altool 错误信息需翻译(三种不同文本可能表达同一个意思)\n */\nimport fs from 'fs-extra'\nimport path from 'path'\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport axios from 'axios'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\nimport { logger } from '../utils/logger.js'\nimport { createUploadRetryStrategy, RetryConfig, AppleJWTGenerator } from '../utils/index.js'\n\nconst execAsync = promisify(exec)\n\n/** App Store Connect API 基础地址 */\nconst APP_STORE_CONNECT_API = 'https://api.appstoreconnect.apple.com/v1'\n\n/** Transporter App 标准安装路径 (macOS) */\nconst TRANSPORTER_APP_PATH = '/Applications/Transporter.app/Contents/itms/bin/iTMSTransporter'\n\n/**\n * 工具命令信息\n */\n// interface ToolCommand {\n// executable: string\n// useShell: boolean\n// }\n\n/**\n * App Store 上传器\n *\n * 上传方式:使用官方 CLI 工具上传 IPA\n * - 优先: Transporter CLI(官方推荐)\n * - 备选: xcrun altool(Xcode 自带,已弃用但可用)\n *\n * 可选功能:通过 App Store Connect API 自动更新发行说明\n * - 需要额外配置 API Key 凭据(apiKeyId + apiIssuerId + privateKey)\n * - 不配置 API Key 时仅上传 IPA,发行说明需手动更新\n */\nexport class AppleStoreUploader implements IUploader {\n name = 'AppStore'\n\n /**\n * 验证配置是否有效\n * 至少需要一种认证方式:\n * - appleId + appPassword(CLI 上传)\n * - apiKeyId + apiIssuerId + privateKey(API 调用,也可用于 CLI 上传)\n */\n validateConfig(config: any): boolean {\n if (!config?.publish?.app_store?.enable) return false\n\n const auth = config.publish.app_store?.auth\n const hasCliAuth = auth?.appleId && auth?.appPassword\n const hasApiAuth = this.hasApiCredentials(auth)\n\n if (!hasCliAuth && !hasApiAuth) {\n logger.error(\n 'Apple 配置缺失:需要 (appleId + appPassword) 或 (apiKeyId + apiIssuerId + privateKey) 中的一种。',\n )\n return false\n }\n\n return true\n }\n\n /**\n * 判断是否支持处理该文件\n */\n canHandle(filePath: string): boolean {\n const ext = filePath.split('.').pop()?.toLowerCase()\n // App Store 仅支持 iOS IPA\n return ext === 'ipa'\n }\n\n /**\n * 执行上传流程\n */\n async upload(filePath: string, config: any, metadata: AppMetadata): Promise<UploadResult> {\n const appConfig = config.publish.app_store\n const auth = appConfig.auth\n const retryConfig = config.retry as RetryConfig | undefined\n\n logger.info('开始上传到 App Store...')\n\n try {\n // 验证文件存在\n const exists = await fs.pathExists(filePath)\n if (!exists) {\n throw new Error(`IPA 文件未找到: ${filePath}`)\n }\n\n const fileSize = (await fs.stat(filePath)).size\n logger.info(`IPA 文件大小: ${(fileSize / (1024 * 1024)).toFixed(2)} MB`)\n\n // 创建重试策略\n const retryStrategy = createUploadRetryStrategy(retryConfig)\n\n // 1. 上传 IPA 文件(CLI 工具)\n const uploadResult = await retryStrategy.execute(\n () => this.uploadWithAvailableTool(filePath, auth),\n 'App Store 上传',\n )\n\n if (!uploadResult.success) {\n throw uploadResult.error || new Error('上传失败')\n }\n\n logger.success('App Store IPA 上传成功!')\n\n // 2. 尝试更新发行说明(可选,需 API Key 凭据)\n if (metadata.changelog && this.hasApiCredentials(auth)) {\n await this.tryUpdateReleaseNotes(auth, appConfig.appId, metadata.changelog, retryStrategy)\n } else if (metadata.changelog && !this.hasApiCredentials(auth)) {\n logger.info(\n '跳过更新发行说明:未配置 API Key 凭据。' +\n '如需启用,请在配置中添加 apiKeyId + apiIssuerId + privateKeyPath。',\n )\n }\n\n return {\n platform: 'app_store',\n success: true,\n message: '上传成功。请前往 App Store Connect 查看。',\n url: 'https://appstoreconnect.apple.com/apps',\n consoleUrl: 'https://appstoreconnect.apple.com/apps',\n }\n } catch (error: any) {\n // 错误日志已经在底层(如重试策略)打印过了,这里不再重复打印详细错误\n // logger.error(`App Store 上传失败: ${error.message}`)\n return {\n platform: 'app_store',\n success: false,\n message: error.message,\n error,\n }\n }\n }\n\n // ───── CLI 上传 ─────\n\n /**\n * 使用可用的工具上传\n * 策略: 优先 Transporter → 降级 altool → 都失败\n */\n private async uploadWithAvailableTool(ipaPath: string, auth: any): Promise<void> {\n const appleId = auth.appleId\n const appPassword = auth.appPassword\n\n // 1. 尝试 Transporter\n try {\n logger.info('正在尝试使用 Transporter CLI...')\n const transporterTool = await this.resolveToolPath('transporter')\n\n if (transporterTool) {\n await this.uploadViaTransporter(transporterTool, ipaPath, appleId, appPassword)\n logger.success('通过 Transporter 上传完成')\n return\n }\n } catch (error: any) {\n logger.warn(`Transporter 调用失败: ${error.message}。尝试降级到 altool...`)\n }\n\n // 2. 降级到 altool\n let altoolTool: { command: string; useShell: boolean } | null = null\n try {\n logger.info('正在尝试使用 xcrun altool...')\n altoolTool = await this.resolveToolPath('altool')\n } catch (error: any) {\n logger.warn(`altool 检测失败: ${error.message}`)\n }\n\n if (altoolTool) {\n await this.uploadViaAltool(altoolTool, ipaPath, appleId, appPassword)\n logger.success('通过 altool 上传完成')\n return\n }\n\n // 3. 都失败,提示用户\n throw new Error(this.getToolInstallationGuide())\n }\n\n /**\n * 解析工具路径结果\n */\n private async resolveToolPath(\n tool: 'transporter' | 'altool',\n ): Promise<{ command: string; useShell: boolean } | null> {\n if (tool === 'transporter') {\n // 1. 尝试全局环境变量中的命令\n try {\n await execAsync('transporter -version', { timeout: 5000 })\n return { command: 'transporter', useShell: false }\n } catch {\n // 忽略错误,继续尝试标准路径\n }\n\n // 2. 尝试标准应用程序路径\n if (await fs.pathExists(TRANSPORTER_APP_PATH)) {\n return { command: `\"${TRANSPORTER_APP_PATH}\"`, useShell: false }\n }\n } else {\n // 尝试 1: 直接调用绝对路径\n const xcrunPath = (await fs.pathExists('/usr/bin/xcrun')) ? '/usr/bin/xcrun' : 'xcrun'\n\n try {\n await execAsync(`${xcrunPath} altool --version`, {\n timeout: 10000,\n })\n return { command: `${xcrunPath} altool`, useShell: false }\n } catch (error: any) {\n logger.warn(\n `[AppleStore] Direct altool check failed: ${error.message}. Trying shell mode...`,\n )\n }\n\n // 尝试 2: 通过 Shell (bash -l) 调用,以加载用户环境变量\n try {\n // 使用 bash -l -c 来执行,确保加载了用户的 PATH\n await execAsync(`bash -l -c \"xcrun altool --version\"`, {\n timeout: 10000,\n })\n // 返回 shell 模式标识\n return { command: 'xcrun altool', useShell: true }\n } catch (error: any) {\n logger.warn(`[AppleStore] Shell altool check failed: ${error.message}`)\n }\n\n return null\n }\n return null\n }\n\n /**\n * 通过 Transporter CLI 上传\n */\n private async uploadViaTransporter(\n tool: { command: string; useShell: boolean },\n ipaPath: string,\n appleId: string,\n appPassword: string,\n ): Promise<void> {\n const command = [\n tool.command,\n '-uploadFile',\n `\"${ipaPath}\"`,\n '-username',\n appleId,\n '-password',\n appPassword,\n '-showTransferRate',\n ].join(' ')\n\n logger.info(`[Transporter] Uploading: ${path.basename(ipaPath)}`)\n\n try {\n const { stdout, stderr } = await execAsync(command, {\n timeout: 30 * 60 * 1000, // 30 分钟\n maxBuffer: 10 * 1024 * 1024, // 10MB\n })\n\n if (stdout) {\n logger.info(`[Transporter] ${stdout}`)\n }\n\n // 检查是否有错误输出\n if (\n stderr &&\n (stderr.includes('error') || stderr.includes('failed') || stderr.includes('ERROR'))\n ) {\n const errorMessage = this.parseAltoolError(stderr)\n throw new Error(errorMessage)\n }\n } catch (error: any) {\n throw new Error(`Transporter upload failed: ${error.message}\\nStderr: ${error.stderr || ''}`)\n }\n }\n\n /**\n * 通过 altool 上传\n */\n private async uploadViaAltool(\n tool: { command: string; useShell: boolean },\n ipaPath: string,\n appleId: string,\n appPassword: string,\n ): Promise<void> {\n // 公共参数列表\n const args = [\n 'xcrun altool', // 占位符\n '--upload-app',\n '-f',\n '__IPA_PATH__', // 占位符\n '-t',\n 'ios',\n '-u',\n appleId,\n '-p',\n appPassword,\n // '--verbose', // 禁用 verbose\n ]\n\n let command = ''\n\n if (tool.useShell) {\n // Shell 模式:需要小心拼接,确保整个命令在引号内\n // 替换 IPA 路径并进行内部引号转义\n const innerCommand = args\n .slice(1) // 去掉开头的 'xcrun altool',因为 tool.command 已经包含了\n .join(' ')\n .replace('__IPA_PATH__', `\\\\\"${ipaPath}\\\\\"`)\n\n // 构造完整命令:bash -l -c \"xcrun altool --upload-app ...\"\n // tool.command 是 \"xcrun altool\"\n command = `bash -l -c \"${tool.command} ${innerCommand}\"`\n } else {\n // 普通模式\n const innerArgs = args.map((arg) => {\n if (arg === 'xcrun altool') return tool.command // 使用传入的可执行路径\n if (arg === '__IPA_PATH__') return `\"${ipaPath}\"`\n return arg\n })\n command = innerArgs.join(' ')\n }\n\n logger.info(`[altool] Uploading: ${path.basename(ipaPath)}`)\n logger.info(`[altool] Command prefix: ${tool.command}`)\n\n try {\n const { stdout, stderr } = await execAsync(command, {\n timeout: 30 * 60 * 1000,\n maxBuffer: 10 * 1024 * 1024,\n })\n\n if (stdout) {\n // 仅当包含关键信息时才输出,避免刷屏\n if (stdout.includes('No errors uploading') || stdout.includes('Request UUID')) {\n logger.info(`[altool] ${stdout}`)\n }\n }\n\n // 检查是否有错误输出\n if (\n stderr &&\n (stderr.includes('error') || stderr.includes('failed') || stderr.includes('ERROR'))\n ) {\n const errorMessage = this.parseAltoolError(stderr)\n throw new Error(errorMessage)\n }\n } catch (error: any) {\n const errorMsg = this.parseAltoolError(error.stderr || error.message)\n throw new Error(errorMsg)\n }\n }\n\n /**\n * 解析 altool/Transporter 错误信息,翻译为用户友好的语言\n */\n private parseAltoolError(stderr: string): string {\n if (!stderr) return 'Unknown error'\n\n // 1. 版本号重复\n if (\n stderr.includes('previousBundleVersion') ||\n stderr.includes('ENTITY_ERROR.ATTRIBUTE.INVALID.DUPLICATE') ||\n stderr.includes('Redundant Binary Upload') ||\n stderr.includes('already been used')\n ) {\n // 尝试提取当前上传的版本号(如果有)\n const match = stderr.match(/previously uploaded version: ‘(.*?)’/)\n const prevVersion = match ? match[1] : 'unknown'\n return `版本号冲突 (Version Conflict): 构建版本 ${prevVersion} 已存在于 App Store Connect。\\n解决方案: 请在 pubspec.yaml 中增加 'version: x.y.z+N' 中的 N (build number),然后重新构建 IPA。`\n }\n\n // 2. 认证失败\n if (\n stderr.includes('Authentication failed') ||\n stderr.includes('password is incorrect') ||\n stderr.includes('NOT_AUTHORIZED')\n ) {\n return `认证失败 (Auth Failed): Apple ID 或 App-specific Password 错误。\\n解决方案: 请检查配置。注意必须使用 App 专用密码,不能使用 Apple ID 登录密码。`\n }\n\n // 3. 资产验证失败 (通用)\n if (stderr.includes('Asset validation failed')) {\n return `资产验证失败 (Validation Failed): IPA 文件可能不符合 App Store 要求。\\n详细错误: ${stderr}`\n }\n\n // 默认返回原始错误,但做截断处理,避免太长\n // 只保留包含 \"error\" 或 \"failed\" 的行,或者前 500 字符\n return `上传工具报错: ${stderr.substring(0, 800)}...`\n }\n\n // ───── 发行说明 API ─────\n\n /**\n * 检查是否配置了 API Key 凭据\n */\n private hasApiCredentials(auth: any): boolean {\n return !!(\n auth?.apiKeyId &&\n auth?.apiIssuerId &&\n (auth?.privateKeyPath || auth?.privateKeyContent)\n )\n }\n\n /**\n * 创建 JWT 生成器\n */\n private async createJWTGenerator(auth: any): Promise<AppleJWTGenerator> {\n if (auth.privateKeyContent) {\n return AppleJWTGenerator.fromContent(auth.apiIssuerId, auth.apiKeyId, auth.privateKeyContent)\n }\n return AppleJWTGenerator.fromFile(auth.apiIssuerId, auth.apiKeyId, auth.privateKeyPath)\n }\n\n /**\n * 获取 API 请求头\n */\n private apiHeaders(token: string): Record<string, string> {\n return {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n }\n }\n\n /**\n * 尝试更新发行说明(失败不影响上传结果)\n */\n private async tryUpdateReleaseNotes(\n auth: any,\n appId: string | undefined,\n changelog: string,\n retryStrategy: ReturnType<typeof createUploadRetryStrategy>,\n ): Promise<void> {\n if (!appId) {\n logger.info(\n '跳过更新发行说明:未配置 App ID。' + '请添加 app_store.appId 以启用自动更新发行说明。',\n )\n return\n }\n\n try {\n logger.info('正在通过 App Store Connect API 更新发行说明...')\n const jwtGenerator = await this.createJWTGenerator(auth)\n const token = jwtGenerator.generate()\n\n // 查找处于\"准备提交\"状态的版本\n const version = await this.getPrepareForSubmissionVersion(token, appId)\n\n if (!version) {\n logger.warn(\n '未找到处于\"准备提交 (PREPARE_FOR_SUBMISSION)\"状态的版本。' +\n '已跳过更新发行说明。请在 App Store Connect 手动更新。',\n )\n return\n }\n\n // 获取版本的本地化信息\n const localizations = await this.getVersionLocalizations(token, version.id)\n\n if (localizations.length === 0) {\n logger.warn('该版本没有找到本地化信息。跳过更新发行说明。')\n return\n }\n\n // 更新每个语言的发行说明\n for (const loc of localizations) {\n const locale = loc.attributes?.locale || 'unknown'\n await retryStrategy.execute(\n () => this.updateLocalizationWhatsNew(token, loc.id, changelog),\n `更新发行说明 (${locale})`,\n )\n logger.info(`已更新发行说明: ${locale}`)\n }\n\n logger.success('所有发行说明更新成功!')\n } catch (error: any) {\n logger.warn(`更新发行说明失败: ${error.message}。` + 'IPA 上传已成功。请手动更新发行说明。')\n }\n }\n\n /**\n * 获取处于\"准备提交\"状态的版本\n * 只有此状态下的版本才能修改发行说明\n */\n private async getPrepareForSubmissionVersion(token: string, appId: string): Promise<any> {\n const res = await axios.get(`${APP_STORE_CONNECT_API}/apps/${appId}/appStoreVersions`, {\n params: {\n 'filter[appStoreState]': 'PREPARE_FOR_SUBMISSION',\n limit: 1,\n },\n headers: this.apiHeaders(token),\n })\n\n const versions = res.data?.data\n if (versions && versions.length > 0) {\n logger.info(\n `Found version: ${versions[0].attributes?.versionString} (PREPARE_FOR_SUBMISSION)`,\n )\n return versions[0]\n }\n\n return null\n }\n\n /**\n * 获取版本的本地化信息列表\n */\n private async getVersionLocalizations(token: string, versionId: string): Promise<any[]> {\n const res = await axios.get(\n `${APP_STORE_CONNECT_API}/appStoreVersions/${versionId}/appStoreVersionLocalizations`,\n {\n headers: this.apiHeaders(token),\n },\n )\n\n return res.data?.data || []\n }\n\n /**\n * 更新本地化版本的 What's New 内容\n */\n private async updateLocalizationWhatsNew(\n token: string,\n localizationId: string,\n whatsNew: string,\n ): Promise<void> {\n await axios.patch(\n `${APP_STORE_CONNECT_API}/appStoreVersionLocalizations/${localizationId}`,\n {\n data: {\n type: 'appStoreVersionLocalizations',\n id: localizationId,\n attributes: {\n whatsNew,\n },\n },\n },\n {\n headers: this.apiHeaders(token),\n },\n )\n }\n\n // ───── 工具安装指引 ─────\n\n /**\n * 获取工具安装指引\n */\n private getToolInstallationGuide(): string {\n return `\nNeither Transporter nor altool CLI found. Please install one:\n\n【推荐】 Transporter CLI (官方推荐):\n Mac: https://apps.apple.com/app/transporter/id1450874784\n Windows: https://www.microsoft.com/store/apps/9NBLGGH52RM5\n\n【备选】 xcrun altool (Xcode 自带):\n Install Xcode Command Line Tools:\n xcode-select --install\n\nNote:\n - 需要使用 Apple ID 和 App-specific Password (在 appleid.apple.com 生成)\n - 不能使用普通 Apple ID 密码\n `.trim()\n }\n}\n","import fs from 'fs-extra'\nimport axios from 'axios'\nimport FormData from 'form-data'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\nimport { logger } from '../utils/logger.js'\nimport { createUploadRetryStrategy, RetryConfig, AppleJWTGenerator } from '../utils/index.js'\n\n/**\n * TestFlight 上传器\n *\n * 用于上传应用到 TestFlight 进行 Beta 测试\n * 参考: https://developer.apple.com/documentation/appstoreconnectapi/build-beta-versions\n */\nexport class TestFlightUploader implements IUploader {\n name = 'TestFlight'\n\n private static readonly API_ROOT = 'https://api.appstoreconnect.apple.com/v1'\n private static readonly API_TIMEOUT = 30000\n private static readonly BUILD_PROCESSING_TIMEOUT = 10 * 60 * 1000 // 10 minutes\n private static readonly BUILD_POLLING_INTERVAL = 10 * 1000 // 10 seconds\n\n /**\n * 验证配置\n * @param config 配置对象\n */\n validateConfig(config: any): boolean {\n if (!config?.publish?.app_store?.enable) return false\n if (config.publish.app_store.mode !== 'testflight') return false\n\n const auth = config.publish.app_store.auth\n if (!auth?.apiKeyId || !auth?.apiIssuerId) {\n logger.error('TestFlight config missing: apiKeyId or apiIssuerId')\n return false\n }\n\n if (!auth.privateKeyPath && !auth.privateKeyContent) {\n logger.error('TestFlight config missing: privateKeyPath or privateKeyContent')\n return false\n }\n\n return true\n }\n\n /**\n * 判断是否支持该文件\n * @param filePath 文件路径\n */\n canHandle(filePath: string): boolean {\n const ext = filePath.split('.').pop()?.toLowerCase()\n // TestFlight 仅支持 iOS IPA\n return ext === 'ipa'\n }\n\n /**\n * 执行上传到 TestFlight\n * @param filePath 文件路径\n * @param config 配置\n * @param metadata 元数据\n */\n async upload(filePath: string, config: any, metadata: AppMetadata): Promise<UploadResult> {\n const appConfig = config.publish.app_store\n const auth = appConfig.auth\n const testflightConfig = appConfig.testflight\n const retryConfig = config.retry as RetryConfig | undefined\n\n logger.info('Starting TestFlight upload...')\n\n try {\n // Validate file exists\n const exists = await fs.pathExists(filePath)\n if (!exists) {\n throw new Error(`IPA file not found: ${filePath}`)\n }\n\n const fileSize = (await fs.stat(filePath)).size\n logger.info(`IPA file size: ${(fileSize / (1024 * 1024)).toFixed(2)} MB`)\n\n // Load private key\n const jwtGenerator = await this.loadJWTGenerator(auth)\n\n // Create retry strategy\n const retryStrategy = createUploadRetryStrategy(retryConfig)\n\n // 1. Generate JWT\n logger.info('Generating JWT token...')\n const jwt = jwtGenerator.generate()\n\n // 2. Get app bundle ID\n const bundleId = metadata.platform?.includes('ios') ? this.extractBundleId(filePath) : null\n if (!bundleId) {\n throw new Error('Could not determine app bundle ID from IPA')\n }\n logger.info(`App bundle ID: ${bundleId}`)\n\n // 3. Create Build record\n logger.info('Creating build record for TestFlight...')\n const buildResult = await retryStrategy.execute(\n () => this.createBuild(jwt, bundleId, metadata.version),\n 'TestFlight create build',\n )\n\n if (!buildResult.success || !buildResult.data) {\n throw buildResult.error || new Error('Failed to create build record')\n }\n\n const buildId = buildResult.data\n logger.info(`Build created: ${buildId}`)\n\n // 4. Upload IPA file\n logger.info('Uploading IPA file to TestFlight (this may take a while)...')\n const uploadResult = await retryStrategy.execute(\n () => this.uploadIPAFile(jwt, buildId, filePath),\n 'TestFlight upload file',\n )\n\n if (!uploadResult.success) {\n throw uploadResult.error || new Error('IPA upload failed')\n }\n\n // 5. Wait for build processing\n logger.info('Waiting for build processing (this may take 5-10 minutes)...')\n await this.waitForBuildProcessing(jwt, buildId, TestFlightUploader.BUILD_PROCESSING_TIMEOUT)\n logger.success('Build processing completed')\n\n // 6. Create Beta Build Version (make it available to testers)\n logger.info('Creating Beta Build Version...')\n const betaBuildResult = await retryStrategy.execute(\n () => this.createBetaBuildVersion(jwt, buildId),\n 'TestFlight create beta version',\n )\n\n if (!betaBuildResult.success) {\n logger.warn('Could not create Beta Build Version automatically')\n }\n\n // 7. Add Beta Testers (if configured)\n if (testflightConfig?.betaTesters && testflightConfig.betaTesters.length > 0) {\n logger.info('Adding beta testers...')\n await this.addBetaTesters(jwt, buildId, testflightConfig.betaTesters, retryStrategy)\n logger.success('Beta testers added')\n }\n\n // 8. Add Beta Build Localization (if configured)\n if (\n testflightConfig?.betaBuildLocalization &&\n testflightConfig.betaBuildLocalization.length > 0\n ) {\n logger.info('Adding beta build localization...')\n await this.addBetaBuildLocalization(\n jwt,\n buildId,\n testflightConfig.betaBuildLocalization,\n retryStrategy,\n )\n logger.success('Beta build localization added')\n }\n\n // 9. Notify testers (if auto-notify enabled)\n if (testflightConfig?.autoNotify !== false && testflightConfig?.betaTesters?.length) {\n logger.info('Notifying beta testers...')\n await this.notifyBetaTesters(jwt, buildId, metadata.changelog || 'New TestFlight build')\n logger.success('Beta testers notified')\n }\n\n logger.success('TestFlight upload successful!')\n\n return {\n platform: 'testflight',\n success: true,\n message: 'Build uploaded to TestFlight and configured for beta testing',\n url: `https://appstoreconnect.apple.com/apps/${bundleId}/testflight/builds`,\n }\n } catch (error: any) {\n logger.error(`TestFlight upload failed: ${error.message}`)\n if (error.response?.data) {\n logger.info(`Error Data: ${JSON.stringify(error.response.data)}`)\n }\n return {\n platform: 'testflight',\n success: false,\n message: error.message,\n error,\n }\n }\n }\n\n /**\n * 加载 JWT 生成器\n * @param auth 认证信息\n */\n private async loadJWTGenerator(auth: any): Promise<AppleJWTGenerator> {\n if (auth.privateKeyContent) {\n return AppleJWTGenerator.fromContent(auth.apiIssuerId, auth.apiKeyId, auth.privateKeyContent)\n } else if (auth.privateKeyPath) {\n return await AppleJWTGenerator.fromFile(auth.apiIssuerId, auth.apiKeyId, auth.privateKeyPath)\n } else {\n throw new Error('No Apple private key provided')\n }\n }\n\n /**\n * 提取 Bundle ID\n * @param ipaPath IPA 路径\n */\n private extractBundleId(ipaPath: string): string | null {\n // TODO: Properly parse IPA archive and extract Bundle ID from Info.plist\n return null\n }\n\n /**\n * 创建构建记录\n * @param jwt JWT\n * @param bundleId Bundle ID\n * @param version 版本号\n */\n private async createBuild(jwt: string, bundleId: string, version: string): Promise<string> {\n try {\n const response = await axios.post(\n `${TestFlightUploader.API_ROOT}/builds`,\n {\n data: {\n type: 'builds',\n attributes: {\n version,\n uploadedDate: new Date().toISOString(),\n },\n relationships: {\n app: {\n data: {\n type: 'apps',\n id: bundleId,\n },\n },\n },\n },\n },\n {\n headers: {\n Authorization: `Bearer ${jwt}`,\n 'Content-Type': 'application/json',\n },\n timeout: TestFlightUploader.API_TIMEOUT,\n },\n )\n\n return response.data.data.id\n } catch (error: any) {\n if (error.response?.status === 401) {\n throw new Error('Authentication failed: Invalid JWT or API credentials')\n }\n throw error\n }\n }\n\n /**\n * 上传 IPA 文件\n * @param jwt JWT\n * @param buildId 构建 ID\n * @param filePath 文件路径\n */\n private async uploadIPAFile(jwt: string, buildId: string, filePath: string): Promise<void> {\n const form = new FormData()\n form.append('file', fs.createReadStream(filePath))\n\n try {\n await axios.post(\n `${TestFlightUploader.API_ROOT}/builds/${buildId}/appStoreVersionExternalTestingBuilds`,\n form,\n {\n headers: {\n Authorization: `Bearer ${jwt}`,\n ...form.getHeaders(),\n },\n timeout: 5 * 60 * 1000,\n maxContentLength: Infinity,\n maxBodyLength: Infinity,\n },\n )\n } catch (error: any) {\n throw new Error(`Failed to upload IPA: ${error.message}`)\n }\n }\n\n /**\n * 等待构建处理\n * @param jwt JWT\n * @param buildId 构建 ID\n * @param timeoutMs 超时时间\n */\n private async waitForBuildProcessing(\n jwt: string,\n buildId: string,\n timeoutMs: number,\n ): Promise<void> {\n const startTime = Date.now()\n let lastStatus = 'PROCESSING'\n\n while (Date.now() - startTime < timeoutMs) {\n try {\n const response = await axios.get(`${TestFlightUploader.API_ROOT}/builds/${buildId}`, {\n headers: {\n Authorization: `Bearer ${jwt}`,\n 'Content-Type': 'application/json',\n },\n timeout: TestFlightUploader.API_TIMEOUT,\n })\n\n const processingState = response.data.data.attributes.processingState\n\n if (processingState === 'READY_FOR_DISTRIBUTION') {\n logger.success('Build ready for distribution')\n return\n }\n\n if (processingState === 'FAILED' || processingState === 'INVALID') {\n throw new Error(`Build processing failed with status: ${processingState}`)\n }\n\n if (processingState !== lastStatus) {\n logger.info(`Build status: ${processingState}`)\n lastStatus = processingState\n }\n\n await new Promise((resolve) =>\n setTimeout(resolve, TestFlightUploader.BUILD_POLLING_INTERVAL),\n )\n } catch (error: any) {\n logger.warn(`Error checking build status: ${error.message}`)\n await new Promise((resolve) =>\n setTimeout(resolve, TestFlightUploader.BUILD_POLLING_INTERVAL),\n )\n }\n }\n\n throw new Error(`Build processing timeout after ${(timeoutMs / 1000 / 60).toFixed(1)} minutes.`)\n }\n\n /**\n * 创建 Beta 版本(使其可测试)\n * @param jwt JWT\n * @param buildId 构建 ID\n */\n private async createBetaBuildVersion(jwt: string, buildId: string): Promise<string> {\n try {\n const response = await axios.post(\n `${TestFlightUploader.API_ROOT}/betaBuildVersions`,\n {\n data: {\n type: 'betaBuildVersions',\n attributes: {},\n relationships: {\n build: {\n data: {\n type: 'builds',\n id: buildId,\n },\n },\n },\n },\n },\n {\n headers: {\n Authorization: `Bearer ${jwt}`,\n 'Content-Type': 'application/json',\n },\n timeout: TestFlightUploader.API_TIMEOUT,\n },\n )\n\n return response.data.data.id\n } catch (error: any) {\n throw new Error(`Failed to create Beta Build Version: ${error.message}`)\n }\n }\n\n /**\n * Add beta testers to the build\n */\n private async addBetaTesters(\n jwt: string,\n buildId: string,\n testers: string[],\n retryStrategy: any,\n ): Promise<void> {\n for (const testerEmail of testers) {\n try {\n await retryStrategy.execute(\n () => this.addBetaTesterToGroup(jwt, testerEmail, buildId),\n `TestFlight add tester ${testerEmail}`,\n )\n logger.info(`✓ Added tester: ${testerEmail}`)\n } catch (error: any) {\n logger.warn(`Failed to add tester ${testerEmail}: ${error.message}`)\n }\n }\n }\n\n /**\n * 添加单个测试员到组\n * @param jwt JWT\n * @param testerEmail 测试员邮箱\n * @param buildId 构建 ID\n */\n private async addBetaTesterToGroup(\n jwt: string,\n testerEmail: string,\n buildId: string,\n ): Promise<void> {\n // First, get or create beta tester group\n // Then add tester to group\n // This is a simplified implementation\n try {\n // In production, you would:\n // 1. Find existing beta testers group\n // 2. Or create new one\n // 3. Add tester to group\n // 4. Add group to build\n logger.info(`Attempting to add ${testerEmail} to beta testers...`)\n } catch (error: any) {\n throw new Error(`Failed to add beta tester: ${error.message}`)\n }\n }\n\n /**\n * Add localization for beta build\n */\n private async addBetaBuildLocalization(\n jwt: string,\n buildId: string,\n localizations: any[],\n retryStrategy: any,\n ): Promise<void> {\n for (const localization of localizations) {\n try {\n await retryStrategy.execute(\n () => this.addLocalizationToBuilder(jwt, buildId, localization),\n `TestFlight add localization ${localization.locale}`,\n )\n logger.info(`✓ Added localization: ${localization.locale}`)\n } catch (error: any) {\n logger.warn(`Failed to add localization ${localization.locale}: ${error.message}`)\n }\n }\n }\n\n /**\n * Add single localization\n */\n private async addLocalizationToBuilder(\n jwt: string,\n buildId: string,\n localization: any,\n ): Promise<void> {\n try {\n await axios.post(\n `${TestFlightUploader.API_ROOT}/betaBuildLocalizations`,\n {\n data: {\n type: 'betaBuildLocalizations',\n attributes: {\n locale: localization.locale,\n description: localization.description,\n keywords: localization.keywords?.join(',') || '',\n },\n relationships: {\n build: {\n data: {\n type: 'betaBuildVersions',\n id: buildId,\n },\n },\n },\n },\n },\n {\n headers: {\n Authorization: `Bearer ${jwt}`,\n 'Content-Type': 'application/json',\n },\n timeout: TestFlightUploader.API_TIMEOUT,\n },\n )\n } catch (error: any) {\n throw new Error(`Failed to add localization: ${error.message}`)\n }\n }\n\n /**\n * 通知测试员\n * @param jwt JWT\n * @param buildId 构建 ID\n * @param message 消息\n */\n private async notifyBetaTesters(jwt: string, buildId: string, message: string): Promise<void> {\n try {\n // Send notification to testers\n logger.info('Sending notification to beta testers...')\n // In production, use the Feedback API for notifications\n } catch (error: any) {\n logger.warn(`Failed to notify testers: ${error.message}`)\n }\n }\n}\n","import fs from 'fs-extra'\nimport path from 'path'\nimport { execSync } from 'child_process'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\nimport { logger } from '../utils/logger.js'\nimport { createUploadRetryStrategy, RetryConfig } from '../utils/index.js'\n\n/**\n * Ad Hoc 上传器\n *\n * 用于创建 Ad Hoc 分发包,供特定设备安装\n * Ad Hoc 允许在最多 100 个特定的 iOS 设备上安装应用\n *\n * 流程:\n * 1. 使用 Xcode 生成 Ad Hoc IPA(使用指定的 Provisioning Profile)\n * 2. 生成设备安装链接/二维码\n * 3. 支持通过蒲公英或其他分发平台\n */\nexport class AdHocUploader implements IUploader {\n name = 'AdHoc'\n\n /**\n * 验证配置\n * @param config 配置对象\n * @returns 是否有效\n */\n validateConfig(config: any): boolean {\n if (!config?.publish?.app_store?.enable) return false\n\n const appConfig = config.publish.app_store\n const mode = appConfig?.mode\n\n // 只在 adhoc 模式下验证\n if (mode !== 'adhoc') return false\n\n // Ad Hoc 需要 Xcode 和 provisioning profile\n const adhocConfig = appConfig?.adhoc\n if (!adhocConfig) {\n logger.error('Ad Hoc config missing: adhoc configuration')\n return false\n }\n\n // 可选:检查 provisioning profile 是否存在\n // if (adhocConfig.provisioningProfileSpecifier && !this.checkProvisioningProfile(adhocConfig.provisioningProfileSpecifier)) {\n // logger.error(`Provisioning profile not found: ${adhocConfig.provisioningProfileSpecifier}`);\n // return false;\n // }\n\n return true\n }\n\n /**\n * 判断是否支持该文件\n * @param filePath 文件路径\n * @returns 是否支持\n */\n canHandle(filePath: string): boolean {\n const ext = filePath.split('.').pop()?.toLowerCase()\n // Ad Hoc 仅支持 iOS IPA\n return ext === 'ipa'\n }\n\n /**\n * 执行上传(生成 Ad Hoc 分发包)\n * @param filePath 文件路径\n * @param config 配置\n * @param metadata 元数据\n */\n async upload(filePath: string, config: any, metadata: AppMetadata): Promise<UploadResult> {\n const appConfig = config.publish.app_store\n const adhocConfig = appConfig.adhoc\n const retryConfig = config.retry as RetryConfig | undefined\n\n logger.info('Starting Ad Hoc distribution setup...')\n\n try {\n // Validate file exists\n const exists = await fs.pathExists(filePath)\n if (!exists) {\n throw new Error(`IPA file not found: ${filePath}`)\n }\n\n const fileSize = (await fs.stat(filePath)).size\n logger.info(`IPA file size: ${(fileSize / (1024 * 1024)).toFixed(2)} MB`)\n\n // Create retry strategy\n const retryStrategy = createUploadRetryStrategy(retryConfig)\n\n // Get bundle ID\n const bundleId = this.extractBundleId(filePath)\n if (!bundleId) {\n logger.warn('Could not determine app bundle ID from IPA')\n } else {\n logger.info(`App bundle ID: ${bundleId}`)\n }\n\n // 1. Verify Ad Hoc capabilities\n logger.info('Verifying Ad Hoc provisioning profile...')\n const profileInfo = this.verifyProvisioningProfile(\n adhocConfig.provisioningProfileSpecifier,\n adhocConfig.teamId,\n )\n\n // 2. Create manifest for Ad Hoc distribution\n logger.info('Creating Ad Hoc distribution manifest...')\n const manifestPath = await this.createManifest(\n filePath,\n metadata.version,\n bundleId,\n metadata.changelog,\n )\n\n // 3. Setup distribution directory\n logger.info('Setting up distribution directory...')\n const distributionPath = await this.setupDistributionDirectory(filePath, manifestPath)\n\n // 4. Generate QR code and installation link\n logger.info('Generating installation links...')\n const installUrl = this.generateInstallUrl(distributionPath, bundleId)\n const qrCodePath = await this.generateQRCode(installUrl, distributionPath)\n\n // 5. Output distribution info\n this.outputDistributionInfo(installUrl, qrCodePath, distributionPath, profileInfo)\n\n logger.success('Ad Hoc distribution setup completed!')\n\n return {\n platform: 'adhoc',\n success: true,\n message: `Ad Hoc package ready for distribution. Install link and QR code generated.`,\n url: installUrl,\n }\n } catch (error: any) {\n logger.error(`Ad Hoc setup failed: ${error.message}`)\n return {\n platform: 'adhoc',\n success: false,\n message: error.message,\n error,\n }\n }\n }\n\n /**\n * 从 IPA 提取 Bundle ID\n * @param ipaPath IPA 路径\n */\n private extractBundleId(ipaPath: string): string | null {\n try {\n // For now, return null - in production would parse Info.plist\n // Could use: unzip -p app.ipa Payload/*.app/Info.plist | plutil -convert json -\n return null\n } catch (error: any) {\n logger.warn(`Failed to extract bundle ID: ${error.message}`)\n return null\n }\n }\n\n /**\n * 验证 Provisioning Profile\n * @param profileSpecifier Profile 名称\n * @param teamId 团队 ID\n */\n private verifyProvisioningProfile(\n profileSpecifier?: string,\n teamId?: string,\n ): { name: string; teamId: string; capacity: number; usedSlots: number } {\n if (!profileSpecifier) {\n logger.warn('No provisioning profile specified, will use automatic signing')\n return {\n name: 'Automatic',\n teamId: teamId || 'Unknown',\n capacity: 100,\n usedSlots: 0,\n }\n }\n\n // 在实际环境中,这会检查真实的 Provisioning Profile\n logger.info(`Using provisioning profile: ${profileSpecifier}`)\n\n return {\n name: profileSpecifier,\n teamId: teamId || 'Unknown',\n capacity: 100,\n usedSlots: 0,\n }\n }\n\n /**\n * 创建 manifest.plist 文件\n * @param ipaPath IPA 路径\n * @param version 版本号\n * @param bundleId Bundle ID\n * @param changelog 更新日志\n */\n private async createManifest(\n ipaPath: string,\n version: string,\n bundleId: string | null,\n changelog?: string,\n ): Promise<string> {\n const ipaFileName = path.basename(ipaPath)\n const appName = bundleId || path.parse(ipaFileName).name\n\n // 在生产环境中,这应该是一个真实的 URL\n const ipaUrl = `itms-services://?action=download-manifest&url=https://your-distribution-server.com/manifests/${ipaFileName}.plist`\n\n const manifestContent = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>items</key>\n <array>\n <dict>\n <key>assets</key>\n <array>\n <dict>\n <key>kind</key>\n <string>software-package</string>\n <key>url</key>\n <string>https://your-distribution-server.com/apps/${ipaFileName}</string>\n </dict>\n <dict>\n <key>kind</key>\n <string>display-image</string>\n <key>url</key>\n <string>https://your-distribution-server.com/icons/app-icon.png</string>\n </dict>\n <dict>\n <key>kind</key>\n <string>full-size-image</string>\n <key>url</key>\n <string>https://your-distribution-server.com/icons/app-icon-large.png</string>\n </dict>\n </array>\n <key>metadata</key>\n <dict>\n <key>bundle-identifier</key>\n <string>${bundleId || 'com.example.app'}</string>\n <key>bundle-version</key>\n <string>${version}</string>\n <key>kind</key>\n <string>software</string>\n <key>title</key>\n <string>${appName}</string>\n <key>subtitle</key>\n <string>${changelog || 'New release'}</string>\n </dict>\n </dict>\n </array>\n</dict>\n</plist>`\n\n const manifestPath = `${ipaPath}.plist`\n await fs.writeFile(manifestPath, manifestContent)\n\n logger.info(`Manifest created: ${manifestPath}`)\n return manifestPath\n }\n\n /**\n * 设置分发目录结构\n * @param ipaPath IPA 路径\n * @param manifestPath Manifest 路径\n */\n private async setupDistributionDirectory(ipaPath: string, manifestPath: string): Promise<string> {\n const projectRoot = process.cwd()\n const distributionDir = path.join(projectRoot, 'build', 'adhoc-distribution')\n\n // Create directory structure\n await fs.ensureDir(distributionDir)\n await fs.ensureDir(path.join(distributionDir, 'apps'))\n await fs.ensureDir(path.join(distributionDir, 'manifests'))\n await fs.ensureDir(path.join(distributionDir, 'icons'))\n\n // Copy IPA and manifest\n const ipaFileName = path.basename(ipaPath)\n await fs.copy(ipaPath, path.join(distributionDir, 'apps', ipaFileName))\n await fs.copy(manifestPath, path.join(distributionDir, 'manifests', `${ipaFileName}.plist`))\n\n logger.info(`Distribution directory: ${distributionDir}`)\n return distributionDir\n }\n\n /**\n * 生成安装链接 (itms-services)\n * @param distributionPath 分发目录\n * @param bundleId Bundle ID\n */\n private generateInstallUrl(distributionPath: string, bundleId: string | null): string {\n // 在生产环境中,这应该生成一个真实的托管 URL\n // 简化版本返回本地路径\n const manifestPath = path.join(distributionPath, 'manifests', `*.plist`)\n\n return `itms-services://?action=download-manifest&url=file://${manifestPath}`\n }\n\n /**\n * 生成二维码\n * @param url 安装链接\n * @param distributionPath 分发目录\n */\n private async generateQRCode(url: string, distributionPath: string): Promise<string> {\n const qrCodePath = path.join(distributionPath, 'install-qrcode.png')\n\n try {\n // 尝试使用 qrcode 库(如果已安装)\n // const QRCode = require('qrcode');\n // await QRCode.toFile(qrCodePath, url, {\n // errorCorrectionLevel: 'H',\n // type: 'image/png',\n // width: 300,\n // margin: 1,\n // color: {\n // dark: '#000000',\n // light: '#FFFFFF'\n // }\n // });\n\n logger.info(`QR code would be saved to: ${qrCodePath}`)\n logger.info(`Install URL: ${url}`)\n\n return qrCodePath\n } catch (error: any) {\n logger.warn(`Failed to generate QR code: ${error.message}`)\n return ''\n }\n }\n\n /**\n * 输出分发信息\n * @param installUrl 安装链接\n * @param qrCodePath 二维码路径\n * @param distributionPath 分发目录\n * @param profileInfo Profile 信息\n */\n private outputDistributionInfo(\n installUrl: string,\n qrCodePath: string,\n distributionPath: string,\n profileInfo: any,\n ): void {\n logger.newLine()\n logger.title('📱 Ad Hoc Distribution Setup Complete')\n\n logger.info(`App Name: ${profileInfo.name}`)\n logger.info(`Team ID: ${profileInfo.teamId}`)\n logger.info(`Device Capacity: ${profileInfo.capacity}`)\n logger.info(`Used Slots: ${profileInfo.usedSlots}/${profileInfo.capacity}`)\n\n logger.newLine()\n logger.info('📦 Distribution Files:')\n logger.info(` Directory: ${distributionPath}`)\n logger.info(` IPA: ${path.join(distributionPath, 'apps', '*.ipa')}`)\n logger.info(` Manifest: ${path.join(distributionPath, 'manifests', '*.plist')}`)\n logger.info(` QR Code: ${qrCodePath}`)\n\n logger.newLine()\n logger.info('🔗 Installation Link:')\n logger.info(` ${installUrl}`)\n\n logger.newLine()\n logger.info('📤 Distribution Options:')\n logger.info(' 1. Share via蒲公英: Upload to Pgyer for easy distribution')\n logger.info(' 2. Share QR code with testers')\n logger.info(' 3. Host manifest and IPA on your server')\n logger.info(' 4. Use enterprise distribution service')\n\n logger.newLine()\n logger.info('⚠️ Important:')\n logger.info(' • Devices must be registered in your Apple Developer account')\n logger.info(' • Maximum 100 devices per app, per year')\n logger.info(' • App must be signed with Ad Hoc provisioning profile')\n logger.info(' • Cannot be distributed via App Store')\n }\n\n /**\n * 检查是否安装了 Xcode\n * @returns 是否安装\n */\n private checkXcodeInstalled(): boolean {\n try {\n execSync('xcode-select -p', { stdio: 'pipe' })\n return true\n } catch {\n return false\n }\n }\n\n /**\n * 生成 Ad Hoc 导出选项 (ExportOptions.plist)\n * @param teamId 团队 ID\n * @param signingIdentity 签名证书\n * @param provisioningProfile Profile 名称\n */\n private generateExportOptions(\n teamId?: string,\n signingIdentity?: string,\n provisioningProfile?: string,\n ): string {\n const options = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>method</key>\n <string>ad-hoc</string>\n <key>signingStyle</key>\n <string>automatic</string>\n <key>stripSwiftSymbols</key>\n <true/>\n <key>teamID</key>\n <string>${teamId || ''}</string>\n ${signingIdentity ? `<key>signingCertificate</key><string>${signingIdentity}</string>` : ''}\n ${provisioningProfile ? `<key>provisioningProfileSpecifier</key><string>${provisioningProfile}</string>` : ''}\n</dict>\n</plist>`\n\n return options\n }\n}\n","import fs from 'fs-extra'\nimport path from 'path'\nimport axios from 'axios'\nimport FormData from 'form-data'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\nimport { logger } from '../utils/logger.js'\nimport { createUploadRetryStrategy, RetryConfig } from '../utils/index.js'\n\n/**\n * 鸿蒙应用市场上传器\n * 复用华为 AppGallery Connect API,但针对鸿蒙包优化\n */\nexport class HarmonyUploader implements IUploader {\n name = 'HarmonyOS'\n private static TOKEN_URL = 'https://connect-api.cloud.huawei.com/api/oauth2/v1/token'\n private static PUBLISH_API_ROOT = 'https://connect-api.cloud.huawei.com/api/publish/v2'\n\n validateConfig(config: any): boolean {\n if (!config?.publish?.harmony?.enable) return false\n\n const h = config.publish.harmony\n if (!h.auth?.clientId || !h.auth?.clientSecret || !h.appId) {\n logger.error('Harmony config missing: clientId, clientSecret, or appId')\n return false\n }\n return true\n }\n\n /**\n * 判断是否支持该文件\n * @param filePath 文件路径\n */\n canHandle(filePath: string): boolean {\n const ext = filePath.split('.').pop()?.toLowerCase()\n // 支持鸿蒙包: HAP, APP\n return ext === 'hap' || ext === 'app'\n }\n\n async upload(filePath: string, config: any, metadata: AppMetadata): Promise<UploadResult> {\n const harmonyConfig = config.publish.harmony\n const clientId = harmonyConfig.auth.clientId\n const clientSecret = harmonyConfig.auth.clientSecret\n const appId = harmonyConfig.appId\n const releaseType = harmonyConfig.releaseType || 'draft'\n const suffix = path.extname(filePath).substring(1) // hap or app\n const retryConfig = config.retry as RetryConfig | undefined\n\n logger.info('Starting HarmonyOS AppGallery upload...')\n\n try {\n const retryStrategy = createUploadRetryStrategy(retryConfig)\n\n // 1. Get Access Token\n logger.info('Authenticating...')\n const tokenResult = await retryStrategy.execute(\n () => this.getAccessToken(clientId, clientSecret),\n 'Harmony authentication',\n )\n if (!tokenResult.success || !tokenResult.data) {\n throw tokenResult.error || new Error('Failed to get access token')\n }\n const token = tokenResult.data\n\n // 2. Get Upload URL\n logger.info('Requesting upload URL...')\n const uploadInfoResult = await retryStrategy.execute(\n () => this.getUploadUrl(token, appId, suffix),\n 'Harmony get upload URL',\n )\n if (!uploadInfoResult.success || !uploadInfoResult.data) {\n throw uploadInfoResult.error || new Error('Failed to get upload URL')\n }\n const uploadInfo = uploadInfoResult.data\n\n // 3. Upload File\n logger.info('Uploading HarmonyOS package...')\n const uploadFileResult = await retryStrategy.execute(\n () => this.uploadFile(uploadInfo.uploadUrl, uploadInfo.authCode, filePath),\n 'Harmony file upload',\n )\n if (!uploadFileResult.success) {\n throw uploadFileResult.error || new Error('File upload failed')\n }\n\n // 4. Update App File Info (fileType: 7 for HarmonyOS)\n logger.info('Linking file to app...')\n const updateInfoResult = await retryStrategy.execute(\n () => this.updateAppFileInfo(token, appId, uploadInfo.authCode, filePath),\n 'Harmony update file info',\n )\n if (!updateInfoResult.success) {\n throw updateInfoResult.error || new Error('Failed to update file info')\n }\n\n // 5. Submit (optional)\n if (releaseType === 'submit') {\n logger.info('Submitting to review...')\n // Similar to HuaweiUploader submit logic\n // We can add this later if needed\n }\n\n logger.success('HarmonyOS upload successful!')\n\n return {\n platform: 'harmony',\n success: true,\n message: 'Upload success',\n url: 'https://developer.huawei.com/consumer/cn/service/josp/agc/index.html',\n }\n } catch (error: any) {\n logger.error(`HarmonyOS upload failed: ${error.message}`)\n return {\n platform: 'harmony',\n success: false,\n message: error.message,\n error,\n }\n }\n }\n\n /**\n * 获取 Access Token\n * @param clientId 客户端 ID\n * @param clientSecret 客户端密钥\n */\n private async getAccessToken(clientId: string, clientSecret: string): Promise<string> {\n const data = {\n client_id: clientId,\n client_secret: clientSecret,\n grant_type: 'client_credentials',\n }\n\n const res = await axios.post(HarmonyUploader.TOKEN_URL, data)\n if (!res.data.access_token) {\n throw new Error('Failed to get access token')\n }\n return res.data.access_token\n }\n\n /**\n * 获取上传 URL\n * @param token Token\n * @param appId 应用 ID\n * @param suffix 后缀\n */\n private async getUploadUrl(token: string, appId: string, suffix: string) {\n const res = await axios.get(`${HarmonyUploader.PUBLISH_API_ROOT}/upload-url`, {\n params: { appId, suffix },\n headers: { Authorization: `Bearer ${token}`, client_id: appId },\n })\n\n if (res.data.code != '0') {\n throw new Error(`Get upload url failed: ${res.data.msg}`)\n }\n return {\n uploadUrl: res.data.uploadUrl,\n authCode: res.data.authCode,\n }\n }\n\n private async uploadFile(uploadUrl: string, authCode: string, filePath: string) {\n const form = new FormData()\n form.append('file', fs.createReadStream(filePath))\n form.append('authCode', authCode)\n form.append('fileCount', '1')\n\n const res = await axios.post(uploadUrl, form, {\n headers: { ...form.getHeaders() },\n maxContentLength: Infinity,\n maxBodyLength: Infinity,\n })\n\n if (res.data.result.resultCode != '0') {\n throw new Error(`File upload failed: ${JSON.stringify(res.data.result)}`)\n }\n }\n\n /**\n * 更新应用文件信息\n * @param token Token\n * @param appId 应用 ID\n * @param authCode 授权码\n * @param filePath 文件路径\n */\n private async updateAppFileInfo(\n token: string,\n appId: string,\n authCode: string,\n filePath: string,\n ) {\n const fileName = path.basename(filePath)\n const body = {\n fileType: 7, // 鸿蒙包的 fileType(需要根据华为最新文档确认)\n files: [\n {\n fileName,\n fileDestUrl: authCode,\n },\n ],\n }\n\n const res = await axios.put(`${HarmonyUploader.PUBLISH_API_ROOT}/app-file-info`, body, {\n params: { appId },\n headers: { Authorization: `Bearer ${token}`, client_id: appId },\n })\n\n if (res.data.ret.code != 0) {\n throw new Error(`Update file info failed: ${res.data.ret.msg}`)\n }\n }\n}\n","import fs from 'fs-extra'\nimport path from 'path'\nimport axios from 'axios'\nimport FormData from 'form-data'\nimport crypto from 'crypto'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\nimport { logger } from '../utils/logger.js'\nimport { createUploadRetryStrategy, RetryConfig } from '../utils/index.js'\n\n/**\n * OPPO 应用商店上传器\n *\n * 基于 OPPO 开放平台「应用发布 API」实现\n * 文档: https://open.oppomobile.com/new/developmentDoc/info?id=11280\n *\n * 上传流程:\n * 1. 使用 client_id + client_secret 获取 access_token\n * 2. 获取上传 URL\n * 3. 上传 APK 文件\n * 4. 提交版本信息(更新日志等)\n */\nexport class OppoUploader implements IUploader {\n name = 'OPPO'\n\n /** OPPO 开放 API 基础地址 */\n private static readonly API_BASE = 'https://oop-openapi-cn.heytapmobi.com'\n /** 获取 token 接口 */\n private static readonly TOKEN_API = `${OppoUploader.API_BASE}/developer/v1/token`\n /** 获取上传 URL 接口 */\n private static readonly UPLOAD_URL_API = `${OppoUploader.API_BASE}/resource/v1/upload/get-upload-url`\n /** 上传完成后提交版本 */\n private static readonly SUBMIT_API = `${OppoUploader.API_BASE}/resource/v1/app/upd`\n /** 查询应详情接口 */\n private static readonly APP_INFO_API = `${OppoUploader.API_BASE}/resource/v1/app/info`\n\n /**\n * OPPO API 签名生成\n * OPPO 使用 HMAC-SHA256 签名机制\n */\n private generateSign(params: Record<string, string | number>, clientSecret: string): string {\n // 按 key 字典序排序拼接\n const sorted = Object.keys(params)\n .sort()\n .filter((key) => params[key] !== undefined && params[key] !== null)\n .map((key) => `${key}=${params[key]}`)\n .join('&')\n\n return crypto.createHmac('sha256', clientSecret).update(sorted).digest('hex')\n }\n\n validateConfig(config: any): boolean {\n if (!config?.publish?.oppo?.enable) return false\n\n const oppo = config.publish.oppo\n if (!oppo.auth?.clientId || !oppo.auth?.clientSecret) {\n logger.error('OPPO config missing: clientId or clientSecret')\n return false\n }\n return true\n }\n\n canHandle(filePath: string): boolean {\n const ext = filePath.split('.').pop()?.toLowerCase()\n return ext === 'apk'\n }\n\n /**\n * 尝试从文件名推断包名\n */\n private inferPackageName(filePath: string): string | null {\n const fileName = path.basename(filePath)\n const match = fileName.match(/^([\\w.]+?)(?:-(?:release|debug|unsigned))?\\.apk$/i)\n if (match && match[1].includes('.')) {\n return match[1]\n }\n return null\n }\n\n /**\n * 从包名推断应用名称\n */\n private inferAppName(packageName: string): string | null {\n const parts = packageName.split('.')\n if (parts.length === 0) return null\n const lastPart = parts[parts.length - 1]\n return lastPart.charAt(0).toUpperCase() + lastPart.slice(1)\n }\n\n async upload(filePath: string, config: any, metadata: AppMetadata): Promise<UploadResult> {\n const oppoConfig = config.publish.oppo\n const accessToken = await this.getAccessToken(oppoConfig.auth.clientId, oppoConfig.auth.clientSecret)\n const packageName = oppoConfig.packageName || this.inferPackageName(filePath)\n const consoleUrl = 'https://open.oppomobile.com/new/ecology/app'\n\n if (!packageName) {\n return { platform: 'oppo', success: false, message: '无法获取包名', consoleUrl }\n }\n\n // 统一处理产物路径\n const artifacts: Record<string, string> =\n typeof metadata.artifactPath === 'object'\n ? metadata.artifactPath\n : { universal: filePath || (typeof metadata.artifactPath === 'string' ? metadata.artifactPath : '') }\n\n try {\n const retryStrategy = createUploadRetryStrategy(config.retry)\n \n // 1. 获取线上信息备用\n const onlineAppInfo = (await this.getAppInfo(accessToken, oppoConfig.auth.clientSecret, packageName)) || {}\n\n const uploadResults: { url: string; md5: string; cpu_code: number }[] = []\n\n // 2. 并行上传所有包\n const uploadPromises = Object.entries(artifacts).map(async ([abi, p]) => {\n if (!p || !fs.existsSync(p)) throw new Error(`文件不存在: ${p}`)\n \n logger.info(`[OPPO] 正在处理 ${abi} 架构包...`)\n const { uploadUrl, sign } = await this.getUploadUrl(accessToken, oppoConfig.auth.clientSecret)\n const uploadFileResult = await this.uploadFile(uploadUrl, sign, p)\n \n // 转换正式 CDN URL\n const fileUrl = uploadFileResult.url\n .replace(/^http:\\/\\//i, 'https://')\n .replace('storedl1.nearme.com.cn', 'storedl.nearme.com.cn')\n\n // cpu_code: 0=通用包, 3=arm64-v8a, 4=armeabi-v7a\n let cpu_code = 0\n if (abi === 'arm64-v8a') cpu_code = 3\n else if (abi === 'armeabi-v7a') cpu_code = 4\n\n uploadResults.push({ url: fileUrl, md5: uploadFileResult.md5, cpu_code })\n })\n\n await Promise.all(uploadPromises)\n\n // 3. 提交版本\n logger.info(`[OPPO] 正在提交流水号组: ${JSON.stringify(uploadResults)}`)\n await this.submitVersion({\n accessToken,\n clientSecret: oppoConfig.auth.clientSecret,\n packageName,\n appName: oppoConfig.appName || onlineAppInfo.app_name || metadata.appName || this.inferAppName(packageName),\n apkUrls: uploadResults,\n versionName: metadata.version,\n versionCode: metadata.buildNumber,\n updateDesc: metadata.changelog || 'App Update',\n onlineType: oppoConfig.onlineType,\n onlineAppInfo,\n })\n\n logger.success('上传到 OPPO 应用商店成功!')\n return { platform: 'oppo', success: true, message: '上传成功, 请确认', consoleUrl }\n } catch (error: any) {\n logger.error(`上传到 OPPO 失败: ${error.message}`)\n return { platform: 'oppo', success: false, message: error.message, error, consoleUrl }\n }\n }\n\n /**\n * 获取 access_token\n * 官方文档: https://open.oppomobile.com/documentation/page/info?id=10998\n */\n private async getAccessToken(clientId: string, clientSecret: string): Promise<string> {\n const params: Record<string, string> = {\n client_id: clientId,\n client_secret: clientSecret,\n }\n\n // 调试日志\n logger.info(`[OPPO Auth Debug] clientId: ${clientId}`)\n logger.info(`[OPPO Auth Debug] clientSecret length: ${clientSecret?.length || 0}`)\n logger.info(`[OPPO Auth Debug] params: ${JSON.stringify(params)}`)\n\n const res = await axios.get(OppoUploader.TOKEN_API, {\n params,\n timeout: 15000,\n })\n\n logger.info(`[OPPO Auth Response] status: ${res.status}, data: ${JSON.stringify(res.data)}`)\n\n if (res.data.errno !== 0) {\n throw new Error(`获取 token 失败: ${res.data.data?.message || JSON.stringify(res.data)}`)\n }\n\n return res.data.data.access_token\n }\n\n /**\n * 获取应用详情\n */\n private async getAppInfo(\n accessToken: string,\n clientSecret: string,\n packageName: string,\n ): Promise<any> {\n const timestamp = Math.floor(Date.now() / 1000)\n const params = {\n access_token: accessToken,\n pkg_name: packageName,\n timestamp,\n }\n const apiSign = this.generateSign(params, clientSecret)\n\n try {\n const res = await axios.get(OppoUploader.APP_INFO_API, {\n params: {\n ...params,\n api_sign: apiSign,\n },\n timeout: 15000,\n })\n\n if (res.data.errno !== 0) {\n logger.warn(`获取应用详情失败 (非致命): ${JSON.stringify(res.data)}`)\n return null\n }\n\n return res.data.data\n } catch (error: any) {\n logger.warn(`获取应用详情请求异常 (非致命): ${error.message}`)\n return null\n }\n }\n\n /**\n * 获取上传地址\n */\n private async getUploadUrl(\n accessToken: string,\n clientSecret: string,\n ): Promise<{ uploadUrl: string; sign: string }> {\n const timestamp = Math.floor(Date.now() / 1000)\n const params = {\n access_token: accessToken,\n timestamp,\n }\n const apiSign = this.generateSign(params, clientSecret)\n\n const res = await axios.get(OppoUploader.UPLOAD_URL_API, {\n params: {\n ...params,\n api_sign: apiSign,\n },\n timeout: 15000,\n })\n\n if (res.data.errno !== 0) {\n throw new Error(`获取上传地址失败: ${res.data.data?.message || JSON.stringify(res.data)}`)\n }\n\n return {\n uploadUrl: res.data.data.upload_url,\n sign: res.data.data.sign,\n }\n }\n\n /**\n * 上传 APK 文件\n */\n private async uploadFile(\n uploadUrl: string,\n sign: string,\n filePath: string,\n ): Promise<{ url: string; md5: string }> {\n const form = new FormData()\n form.append('file', fs.createReadStream(filePath))\n form.append('sign', sign)\n form.append('type', 'apk')\n\n const res = await axios.post(uploadUrl, form, {\n headers: form.getHeaders(),\n maxContentLength: Infinity,\n maxBodyLength: Infinity,\n timeout: 300000, // 5 分钟超时\n })\n\n if (res.data.errno !== 0) {\n throw new Error(`文件上传失败: ${res.data.data?.message || JSON.stringify(res.data)}`)\n }\n\n return {\n url: res.data.data.url,\n md5: res.data.data.md5,\n }\n }\n\n /**\n * 提交版本信息\n */\n private async submitVersion(params: {\n accessToken: string\n clientSecret: string\n packageName: string\n appName: string\n apkUrls: { url: string; md5: string; cpu_code: number }[]\n versionName: string\n versionCode: string\n updateDesc: string\n onlineType?: '1' | '2'\n onlineAppInfo?: any\n }): Promise<void> {\n logger.info(`[OPPO Submit Params] ${JSON.stringify(params)}`)\n const timestamp = Math.floor(Date.now() / 1000)\n const online = params.onlineAppInfo || {}\n // 健壮性:如果 versionCode 还是空,尝试从 versionName 解析(v1.0.1+2 -> 2)\n let vCode = params.versionCode\n if (!vCode || vCode === '0' || vCode === '') {\n const parts = params.versionName.split('+')\n if (parts.length > 1) {\n vCode = parts[1]\n } else {\n vCode = '1' // 彻底的兜底,防止 API 报错\n }\n }\n\n const signParams: Record<string, any> = {\n access_token: params.accessToken,\n timestamp,\n apk_url: JSON.stringify(params.apkUrls),\n version_name: params.versionName.split('+')[0], // 仅保留版本名部分\n version_code: vCode,\n update_desc: params.updateDesc,\n pkg_name: params.packageName,\n app_name: params.appName,\n // 补充 OPPO 提交审核的必填项 (优先复用线上数据)\n summary: online.summary || params.updateDesc.slice(0, 15),\n detail_desc:\n online.detail_desc ||\n (params.updateDesc.length >= 20\n ? params.updateDesc\n : `${params.updateDesc}, 此版本优化了用户体验并修复了已知问题。`),\n privacy_source_url:\n online.privacy_source_url || `https://open.oppomobile.com/privacy/${params.packageName}`,\n }\n\n // 字段映射辅助函数:确保即使是 0 也能被正确传递\n const mapField = (key: string, onlineKey?: string) => {\n const val = online[onlineKey || key]\n if (val !== undefined && val !== null && val !== '') {\n signParams[key] = val\n }\n }\n\n // 分类 ID: OPPO 严格校验多级分类\n mapField('first_category_id')\n mapField('second_category_id')\n mapField('third_category_id')\n\n // 发布类型: 必填,1-立即发布,2-定时发布\n // 优先级: 配置 > 线上数据 > 默认立即发布(1)\n if (params.onlineType) {\n signParams.online_type = params.onlineType\n } else {\n mapField('online_type')\n }\n\n if (!signParams.online_type) {\n signParams.online_type = '1'\n }\n\n // 其他元数据字段 (如果线上存在则复用)\n mapField('version_type')\n mapField('adaptive_equipment')\n // adaptive_type: 1=横视窗丰田, 2=横视窗; 线上为 \"0\" 时为无效值,不传\n {\n const val = online['adaptive_type']\n if (val !== undefined && val !== null && val !== '' && String(val) !== '0') {\n signParams.adaptive_type = val\n }\n }\n\n // 测试附加说明 (如测试账号等,经常被强校验)\n mapField('test_desc')\n if (!signParams.test_desc) {\n signParams.test_desc = '无特殊测试说明'\n }\n\n // 商务及客服联系人信息\n mapField('business_username')\n mapField('business_email')\n mapField('business_mobile')\n mapField('customer_contact')\n\n // 最核心必要兜底(避免审核阻断)\n if (!signParams.business_username) signParams.business_username = '开发负责人'\n if (!signParams.business_email) signParams.business_email = 'developer@example.com'\n if (!signParams.business_mobile) signParams.business_mobile = '13800138000'\n\n // 版权所有网址 (应用、合作应用必传)\n mapField('copyright_url')\n\n // APP 年龄分级 (普通应用/合作应用必传)\n mapField('age_level')\n if (!signParams.age_level) {\n signParams.age_level = '18' // OPPO 常见默认值:适合18岁以上\n }\n\n // 资源链接 (图标与截图): 绝大多数平台在更新时都需要原封不动传回这些链接\n mapField('icon_url')\n\n // 图片大小超限防护机制:OPPO 服务器对 `pic_url` 限制了 1MB 单张大小。\n // 但是 OPPO `info` 接口返回的线上老图片有时候本身就超过了 1MB,如果不经挑选直接原路返回,就会引发 800002 大小限制报错。\n // 这里我们借助 `online.pic_url_material` 来过滤符合大小的图片。\n if (online.pic_url_material && Array.isArray(online.pic_url_material)) {\n // 单位转换:1MB = 1048576 Bytes\n const MAX_SIZE = 1 * 1024 * 1024\n const validPicUrls = online.pic_url_material\n .filter((item: any) => {\n // 如果没有 size 字段或 size 合法,则放行\n return !item.size || Number(item.size) <= MAX_SIZE\n })\n .map((item: any) => item.url)\n .filter(Boolean)\n\n if (validPicUrls.length > 0) {\n signParams.pic_url = validPicUrls.join(',')\n } else {\n // 如果全部因为大小被过滤掉(罕见边缘情况,通常会有至少1张小的),则直接降级使用全量,听天由命\n mapField('pic_url')\n }\n } else {\n mapField('pic_url')\n }\n\n mapField('is_safe_check')\n\n const apiSign = this.generateSign(signParams, params.clientSecret)\n\n // OPPO 要求使用 x-www-form-urlencoded 格式\n const data = new URLSearchParams()\n Object.entries(signParams).forEach(([key, value]) => {\n data.append(key, String(value))\n })\n data.append('api_sign', apiSign)\n\n logger.info(`[OPPO Submit Debug] URL: ${OppoUploader.SUBMIT_API}`)\n logger.info(`[OPPO Submit Debug] Body: ${data.toString()}`)\n\n const res = await axios.post(OppoUploader.SUBMIT_API, data.toString(), {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n timeout: 30000,\n })\n\n logger.info(`[OPPO Submit Response] status: ${res.status}, data: ${JSON.stringify(res.data)}`)\n\n if (res.data.errno !== 0) {\n throw new Error(`提交版本失败: ${res.data.data?.message || JSON.stringify(res.data)}`)\n }\n\n logger.info('版本信息已提交')\n }\n\n /**\n * 格式化错误信息\n */\n private formatError(error: any): string {\n if (error.response?.data) {\n const data = error.response.data\n return data.data?.message || data.message || error.message\n }\n return error.message\n }\n}\n","import fs from 'fs-extra'\nimport path from 'path'\nimport axios from 'axios'\nimport FormData from 'form-data'\nimport crypto from 'crypto'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\nimport { logger } from '../utils/logger.js'\nimport { createUploadRetryStrategy } from '../utils/index.js'\nimport { parsePackageInfo } from '../utils/package-parser.js'\n\n/**\n * vivo 应用商店上传器\n *\n * 基于 vivo 开放平台「应用分发 API」实现 (协议与腾讯开放平台 Open-QQ 规范一致)\n * 文档: https://dev.vivo.com.cn/documentCenter/doc/326\n */\nexport class VivoUploader implements IUploader {\n name = 'vivo'\n\n /** vivo 开放 API 基础地址 */\n private static readonly API_BASE = 'https://developer-api.vivo.com.cn/router/rest'\n\n private generateSign(params: Record<string, string>, accessSecret: string): string {\n const sorted = Object.keys(params)\n .sort()\n .filter((key) => params[key] !== undefined && params[key] !== null)\n .map((key) => `${key}=${params[key]}`)\n .join('&')\n\n return crypto.createHmac('sha256', accessSecret).update(sorted).digest('hex')\n }\n\n validateConfig(config: any): boolean {\n if (!config?.publish?.vivo?.enable) return false\n const vivo = config.publish.vivo\n return !!(vivo.auth?.accessKey && vivo.auth?.accessSecret)\n }\n\n canHandle(filePath: string): boolean {\n const ext = filePath.split('.').pop()?.toLowerCase()\n return ext === 'apk'\n }\n\n async upload(filePath: string, config: any, metadata: AppMetadata): Promise<UploadResult> {\n const vivoConfig = config.publish.vivo\n const accessKey = vivoConfig.auth.accessKey\n const accessSecret = vivoConfig.auth.accessSecret\n const consoleUrl = 'https://dev.vivo.com.cn/manage/app'\n\n // 统一处理产物路径\n const artifacts: Record<string, string> =\n typeof metadata.artifactPath === 'object'\n ? metadata.artifactPath\n : { universal: filePath || (typeof metadata.artifactPath === 'string' ? metadata.artifactPath : '') }\n\n try {\n const uploadResults: Record<string, { serialnumber: string; md5: string; is64Bit: boolean }> = {}\n\n // 1. 并行上传所有相关产物\n const uploadPromises = Object.entries(artifacts).map(async ([abi, p]) => {\n if (!p || !fs.existsSync(p)) throw new Error(`文件不存在: ${p}`)\n const md5 = await this.calculateFileMD5(p)\n logger.info(`[vivo] 正在处理 ${abi} 架构包: ${path.basename(p)}`)\n \n const serialnumber = await this.uploadApk(accessKey, accessSecret, p, vivoConfig.packageName || '', md5)\n \n const pkgInfo = await parsePackageInfo(p, { androidSdkPath: config.globalSettings?.androidSdkPath })\n const nativeCodes = pkgInfo?.nativeCode || []\n const has64Bit = nativeCodes.includes('arm64-v8a') || nativeCodes.includes('x86_64') || abi === 'arm64-v8a'\n const has32Bit = nativeCodes.includes('armeabi-v7a') || nativeCodes.includes('armeabi') || abi === 'armeabi-v7a'\n\n uploadResults[abi] = { serialnumber, md5, is64Bit: has64Bit && !has32Bit }\n })\n\n await Promise.all(uploadPromises)\n\n // 2. 构造提交参数\n const arm64Result = uploadResults['arm64-v8a'] || Object.values(uploadResults).find(r => r.is64Bit)\n const arm32Result = uploadResults['armeabi-v7a'] || Object.values(uploadResults).find(r => !r.is64Bit)\n\n const submitData: any = {\n packageName: vivoConfig.packageName,\n versionCode: parseInt(metadata.buildNumber) || 1,\n updateDesc: metadata.changelog || 'App Update',\n }\n\n if (arm64Result) {\n submitData.serialnumber = arm64Result.serialnumber\n submitData.fileMd5 = arm64Result.md5\n }\n if (arm32Result) {\n submitData.apk32 = arm32Result.serialnumber\n submitData.md532 = arm32Result.md5\n }\n\n // 兜底单包\n if (!submitData.serialnumber && !submitData.apk32) {\n const single = Object.values(uploadResults)[0]\n submitData.serialnumber = single.serialnumber\n submitData.fileMd5 = single.md5\n }\n\n logger.info(`[vivo] 正在提交审核申报: ${JSON.stringify(submitData)}`)\n await this.submitVersion(accessKey, accessSecret, submitData)\n\n logger.success('上传到 vivo 应用商店成功!')\n return { platform: 'vivo', success: true, message: '上传并提交审核成功', consoleUrl }\n } catch (error: any) {\n logger.error(`上传到 vivo 失败: ${error.message}`)\n return { platform: 'vivo', success: false, message: error.message, error, consoleUrl }\n }\n }\n\n private calculateFileMD5(filePath: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const hash = crypto.createHash('md5')\n const stream = fs.createReadStream(filePath)\n stream.on('data', (data) => hash.update(data))\n stream.on('end', () => resolve(hash.digest('hex')))\n stream.on('error', reject)\n })\n }\n\n private async uploadApk(accessKey: string, accessSecret: string, filePath: string, packageName: string, fileMd5: string): Promise<string> {\n const timestamp = String(Date.now())\n const params: Record<string, string> = {\n access_key: accessKey, timestamp, format: 'json', v: '1.0',\n sign_method: 'hmac', target_app_key: 'developer', method: 'app.upload.apk.app',\n packageName, fileMd5,\n }\n const sign = this.generateSign(params, accessSecret)\n const form = new FormData()\n Object.entries(params).forEach(([k, v]) => form.append(k, v))\n form.append('sign', sign)\n form.append('file', fs.createReadStream(filePath), { filename: path.basename(filePath) })\n\n const res = await axios.post(VivoUploader.API_BASE, form, { headers: form.getHeaders(), timeout: 300000 })\n if (res.data.code !== 0) throw new Error(`上传包失败: ${res.data.msg}`)\n return res.data.data?.serialnumber || res.data.data\n }\n\n private async submitVersion(accessKey: string, accessSecret: string, data: any): Promise<void> {\n const timestamp = String(Date.now())\n const reqParams: Record<string, string> = {\n access_key: accessKey, timestamp, format: 'json', v: '1.0',\n sign_method: 'hmac', target_app_key: 'developer', method: 'app.sync.update.app',\n packageName: data.packageName || '',\n versionCode: String(data.versionCode),\n apk: data.serialnumber || '', \n fileMd5: data.fileMd5 || '',\n onlineType: '1', compatibleDevice: '1',\n updateDesc: data.updateDesc,\n }\n if (data.apk32) {\n reqParams.apk32 = data.apk32\n if (data.md532) (reqParams as any).md532 = data.md532\n }\n\n reqParams.sign = this.generateSign(reqParams, accessSecret)\n const formData = new URLSearchParams()\n Object.entries(reqParams).forEach(([k, v]) => formData.append(k, v))\n\n const res = await axios.post(VivoUploader.API_BASE, formData.toString(), {\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n timeout: 30000,\n })\n if (res.data.code !== 0) throw new Error(`提交失败: ${res.data.msg}`)\n }\n}\n","/**\n * 腾讯应用宝 (Tencent MyApp) 上传适配器\n *\n * 认证方式: HMAC-SHA256 签名\n * 支持文件: APK\n * API: https://api.open.qq.com/router/rest (通用路由)\n *\n * 上传流程: 获取线上信息 → COS 预签名 URL 直传 (绕过 30MB 网关限制) → 提交版本\n * 注意事项:\n * - 64/32 位架构自动判定: has64Bit && !has32Bit 才用 apk64_file_* 字段\n * - apk64 和 apk32 字段互斥,设一个要清另一个\n * - 线上信息查询后需清理内部状态字段再回传\n */\nimport fs from 'fs-extra'\nimport path from 'path'\nimport axios from 'axios'\n\nimport crypto from 'crypto'\nimport { IUploader, UploadResult, AppMetadata } from '../types.js'\nimport { logger } from '../utils/logger.js'\n\nimport { parsePackageInfo } from '../utils/package-parser.js'\n\n/**\n * 腾讯应用宝上传器\n *\n * 基于腾讯开放平台「应用管理 API」实现\n * 文档: https://wiki.open.qq.com/wiki/应用上传\n *\n * 上传流程:\n * 1. 使用 appId + accessSecret 生成签名\n * 2. 上传 APK 文件\n * 3. 提交版本信息(更新说明等)\n *\n * 签名方式: HMAC-SHA256\n */\nexport class TencentUploader implements IUploader {\n name = 'Tencent'\n\n /** 腾讯开放平台 API 基础地址 */\n private static readonly API_BASE = 'https://p.open.qq.com/open_file/developer_api'\n\n /**\n * 接口签名生成 (HmacSHA256)\n * 规则: 所有参数按字典序排序拼接为 k1=v1&k2=v2... (不要进行 URL 编码)\n * 使用 accessSecret 计算 HmacSHA256,转小写 16 进制\n */\n private generateSign(params: Record<string, any>, accessSecret: string): string {\n const sortedKeys = Object.keys(params).sort()\n const signStr = sortedKeys\n .filter((key) => params[key] !== undefined && params[key] !== null)\n .map((key) => `${key}=${params[key]}`)\n .join('&')\n\n return crypto.createHmac('sha256', accessSecret).update(signStr).digest('hex').toLowerCase()\n }\n\n validateConfig(config: any): boolean {\n if (!config?.publish?.tencent?.enable) return false\n const auth = config.publish.tencent.auth\n if (!auth?.userId || !auth?.appId || !auth?.accessSecret) {\n logger.error('Tencent config missing: userId, appId or accessSecret')\n return false\n }\n return true\n }\n\n canHandle(filePath: string): boolean {\n return filePath.toLowerCase().endsWith('.apk')\n }\n\n async upload(filePath: string, config: any, metadata: AppMetadata): Promise<UploadResult> {\n const tencentConfig = config.publish.tencent\n const auth = tencentConfig.auth\n const consoleUrl = 'https://app.open.qq.com'\n const pkgName = tencentConfig.packageName || ''\n\n // 统一处理产物路径(支持单文件或 ABI 对照表)\n const artifacts: Record<string, string> =\n typeof metadata.artifactPath === 'object'\n ? metadata.artifactPath\n : { universal: filePath || (typeof metadata.artifactPath === 'string' ? metadata.artifactPath : '') }\n\n try {\n const uploadResults: Record<string, { serial_number: string; is64Bit: boolean; md5: string }> =\n {}\n\n // 1. 并行上传所有相关产物\n const uploadPromises = Object.entries(artifacts).map(async ([abi, p]) => {\n if (!p || !fs.existsSync(p)) throw new Error(`文件不存在: ${p}`)\n const stats = fs.statSync(p)\n const fileName = path.basename(p)\n\n logger.info(`[Tencent] 正在处理 ${abi} 架构包: ${fileName}`)\n const uploadInfo = await this.getFileUploadInfo(auth, stats.size, fileName, pkgName)\n await this.uploadToCos(uploadInfo.pre_sign_url, p, stats.size)\n\n const pkgInfo = await parsePackageInfo(p, {\n androidSdkPath: config.globalSettings?.androidSdkPath,\n })\n const nativeCodes = pkgInfo?.nativeCode || []\n const has64Bit =\n nativeCodes.includes('arm64-v8a') || nativeCodes.includes('x86_64') || abi === 'arm64-v8a'\n const has32Bit =\n nativeCodes.includes('armeabi-v7a') ||\n nativeCodes.includes('armeabi') ||\n nativeCodes.includes('x86') ||\n abi === 'armeabi-v7a'\n\n uploadResults[abi] = {\n serial_number: uploadInfo.serial_number,\n is64Bit: has64Bit && !has32Bit,\n md5: pkgInfo?.md5 || '',\n }\n })\n\n await Promise.all(uploadPromises)\n\n // 2. 获取线上应用详情以保留现有配置\n logger.info('[Tencent] 正在获取线上应用详情...')\n const anyPkgPath = Object.values(artifacts)[0]\n const samplePkgInfo = await parsePackageInfo(anyPkgPath, {\n androidSdkPath: config.globalSettings?.androidSdkPath,\n })\n const onlineDetail = await this.queryAppDetail(\n auth,\n pkgName || samplePkgInfo?.packageName || '',\n )\n\n // 3. 构造提交参数(合并多包信息)\n const submitData: any = {\n ...onlineDetail,\n pkg_name: pkgName || samplePkgInfo?.packageName || onlineDetail.pkg_name || '',\n update_desc: metadata.changelog || '版本更新',\n }\n\n // 如果有明确的 64 位包\n const arm64Result =\n uploadResults['arm64-v8a'] || Object.values(uploadResults).find((r) => r.is64Bit)\n const arm32Result =\n uploadResults['armeabi-v7a'] || Object.values(uploadResults).find((r) => !r.is64Bit)\n\n if (arm64Result) {\n submitData.apk64_serial_number = arm64Result.serial_number\n submitData.apk64_md5 = arm64Result.md5\n }\n if (arm32Result) {\n submitData.apk32_serial_number = arm32Result.serial_number\n submitData.apk32_md5 = arm32Result.md5\n }\n\n // 如果是单包(且不是明确的分发),回退逻辑判定\n if (\n Object.keys(uploadResults).length === 1 &&\n !submitData.apk64_serial_number &&\n !submitData.apk32_serial_number\n ) {\n const single = Object.values(uploadResults)[0]\n if (single.is64Bit) {\n submitData.apk64_serial_number = single.serial_number\n submitData.apk64_md5 = single.md5\n } else {\n submitData.apk32_serial_number = single.serial_number\n submitData.apk32_md5 = single.md5\n }\n }\n\n logger.info('[Tencent] 正在提交审核申报...')\n await this.submitModifyAppInfo(auth, submitData, { timeout: tencentConfig.timeout || 60000 })\n\n logger.success('腾讯应用宝上传并提交成功!')\n return { platform: 'tencent', success: true, message: '上传并提交审核成功', consoleUrl }\n } catch (error: any) {\n logger.error(`腾讯上传失败: ${error.message}`)\n return { platform: 'tencent', success: false, message: error.message, error, consoleUrl }\n }\n }\n\n /**\n * 阶段 1: 获取文件上传信息\n */\n private async getFileUploadInfo(auth: any, fileSize: number, fileName: string, pkgName: string) {\n logger.info(`Tencent getFileUploadInfo: ${JSON.stringify(auth)}`)\n const userId = String(auth.userId || '')\n const accessSecret = String(auth.accessSecret || '')\n\n // 签名参数全部用 string,与发送参数保持一致\n // 官方必传: user_id, timestamp, pkg_name, app_id, file_size, file_name, file_type\n const signParams: Record<string, string> = {\n user_id: userId,\n timestamp: String(Math.floor(Date.now() / 1000)),\n pkg_name: pkgName,\n app_id: String(auth.appId || ''),\n file_size: String(fileSize),\n file_name: fileName,\n file_type: 'apk',\n }\n\n const sign = this.generateSign(signParams, accessSecret)\n\n const formParams: Record<string, string> = {\n ...signParams,\n sign,\n }\n\n const url = `${TencentUploader.API_BASE}/get_file_upload_info`\n\n logger.info(`正在请求 Tencent API: ${url}`)\n logger.info(`formParams: ${JSON.stringify(formParams)}`)\n\n // 官方要求: Content-Type: application/x-www-form-urlencoded\n const res = await axios.post(url, new URLSearchParams(formParams).toString(), {\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n })\n\n if (res.data.ret !== 0) {\n throw new Error(`获取上传信息失败: ${res.data.msg} (ret:${res.data.ret})`)\n }\n return res.data\n }\n\n /**\n * 获取应用详情\n */\n private async queryAppDetail(auth: any, pkgName: string) {\n const userId = auth.userId || ''\n const accessSecret = auth.accessSecret || ''\n\n const signParams: Record<string, string> = {\n user_id: userId,\n timestamp: String(Math.floor(Date.now() / 1000)),\n app_id: String(auth.appId || ''),\n pkg_name: pkgName,\n }\n\n const sign = this.generateSign(signParams, accessSecret)\n const formParams = { ...signParams, sign }\n\n const url = `${TencentUploader.API_BASE}/query_app_detail`\n const res = await axios.post(url, new URLSearchParams(formParams).toString(), {\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n })\n\n if (res.data.ret !== 0) {\n logger.warn(`查询应用详情失败: ${res.data.msg},将使用空配置继续`)\n return {}\n }\n return res.data\n }\n\n /**\n * 阶段 2: 直接上传到 COS (PUT)\n */\n private async uploadToCos(url: string, filePath: string, size: number) {\n await axios.put(url, fs.createReadStream(filePath), {\n headers: {\n 'Content-Type': 'application/octet-stream',\n 'Content-Length': size,\n },\n maxContentLength: Infinity,\n maxBodyLength: Infinity,\n timeout: 900000, // 15 分钟\n onUploadProgress: (p) => {\n if (p.total) {\n const percent = Math.round((p.loaded * 100) / p.total)\n if (percent % 20 === 0) logger.info(`上传进度: ${percent}%`)\n }\n },\n })\n }\n\n /**\n * 阶段 3: 提交流水号信息\n */\n private async submitModifyAppInfo(auth: any, data: any, options?: { timeout?: number }) {\n const userId = auth.userId || ''\n const accessSecret = auth.accessSecret || ''\n\n // 签名参数全部用 string\n // 基础参数合并\n const signParams: Record<string, string> = {\n user_id: userId,\n timestamp: String(Math.floor(Date.now() / 1000)),\n app_id: String(auth.appId || ''),\n pkg_name: String(data.pkg_name || ''),\n feature: String(data.update_desc || ''),\n deploy_type: String(data.deploy_type || '1'), // 默认审核后立即发布\n }\n\n // 继承线上可选参数 (过滤掉已处理的及特殊字段)\n const skipFields = [\n 'ret',\n 'msg',\n 'user_id',\n 'timestamp',\n 'sign',\n 'app_id',\n 'pkg_name',\n 'feature',\n 'is64Bit',\n 'md5',\n 'serial_number',\n ]\n Object.keys(data).forEach((key) => {\n if (!skipFields.includes(key) && data[key] !== undefined && data[key] !== null) {\n signParams[key] = String(data[key])\n }\n })\n\n // 根据架构决定参数名并覆盖 (优先使用多架构字段)\n if (data.apk64_serial_number) {\n signParams.apk64_file_serial_number = String(data.apk64_serial_number)\n if (data.apk64_md5) signParams.apk64_file_md5 = data.apk64_md5\n }\n if (data.apk32_serial_number) {\n signParams.apk32_file_serial_number = String(data.apk32_serial_number)\n if (data.apk32_md5) signParams.apk32_file_md5 = data.apk32_md5\n }\n\n // 后向兼容逻辑\n if (!data.apk64_serial_number && !data.apk32_serial_number && data.serial_number) {\n if (data.is64Bit) {\n signParams.apk64_file_serial_number = String(data.serial_number || '')\n if (data.md5) signParams.apk64_file_md5 = data.md5\n } else {\n signParams.apk32_file_serial_number = String(data.serial_number || '')\n if (data.md5) signParams.apk32_file_md5 = data.md5\n }\n }\n\n const sign = this.generateSign(signParams, accessSecret)\n\n const formParams: Record<string, string> = {\n ...signParams,\n sign,\n }\n\n logger.info(`formParams: ${JSON.stringify(formParams)}`)\n\n const url = `${TencentUploader.API_BASE}/update_app`\n\n // 官方要求: Content-Type: application/x-www-form-urlencoded\n const res = await axios.post(url, new URLSearchParams(formParams).toString(), {\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n })\n if (res.data.ret !== 0) {\n throw new Error(`提交流水号失败: ${res.data.msg} (ret:${res.data.ret})`)\n }\n return res.data\n }\n}\n","/**\n * 配置验证器 (ConfigValidator)\n *\n * 职责:加载 YAML 配置文件并验证其完整性\n *\n * 流程:\n * 1. 读取文件内容\n * 2. 提取环境变量占位符 (${VAR_NAME} 格式)\n * 3. 通过 EnvValidator 检查环境变量是否已设置\n * 4. 替换占位符为实际值\n * 5. 解析 YAML 为 UploadConfig 对象\n * 6. Schema 校验:启用的平台必须提供完整的认证信息\n */\nimport fs from 'fs-extra'\n// @ts-ignore\nimport yaml from 'js-yaml'\nimport { UploadConfig } from '../types.js'\nimport { logger } from '../utils/logger.js'\nimport { EnvValidator } from './env_validator.js'\n\nexport class ConfigValidator {\n /**\n * 加载并验证配置文件\n * @param filePath 配置文件路径\n */\n static loadAndValidate(filePath: string): UploadConfig | null {\n if (!fs.existsSync(filePath)) {\n logger.error(`Config file not found: ${filePath}`)\n return null\n }\n\n let content = fs.readFileSync(filePath, 'utf8')\n\n // 1. Extract env vars\n // Format: ${VAR_NAME}\n const envRegex = /\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}/g\n const matches = [...content.matchAll(envRegex)]\n const requiredEnvs = Array.from(new Set(matches.map((m) => m[1])))\n\n // 2. Validate Env\n if (!EnvValidator.validate(requiredEnvs)) {\n return null\n }\n\n // 3. Substitute Env\n content = content.replace(envRegex, (_, varName) => process.env[varName] || '')\n\n // 4. Parse YAML\n try {\n const config = yaml.load(content) as UploadConfig\n\n // 5. Schema Validation (Basic)\n if (!this.validateSchema(config)) {\n return null\n }\n\n return config\n } catch (e: any) {\n logger.error(`Failed to parse YAML: ${e.message}`)\n return null\n }\n }\n\n /**\n * 验证配置 Schema\n * @param config 配置对象\n */\n private static validateSchema(config: UploadConfig): boolean {\n // Basic checks\n if (config.publish?.app_store?.enable) {\n const auth = config.publish.app_store.auth\n if (!auth?.apiKeyId || !auth?.apiIssuerId) {\n logger.error('App Store enabled but missing auth info (apiKeyId, apiIssuerId)')\n return false\n }\n }\n\n if (config.publish?.huawei?.enable) {\n const auth = config.publish.huawei.auth\n if (!auth?.clientId || !auth?.clientSecret) {\n logger.error('Huawei enabled but missing auth info (clientId, clientSecret)')\n return false\n }\n }\n\n if (config.publish?.xiaomi?.enable) {\n const auth = config.publish.xiaomi.auth\n if (!auth?.userName || !auth?.privateKey) {\n logger.error('Xiaomi enabled but missing auth info (userName, privateKey)')\n return false\n }\n }\n\n if (config.publish?.oppo?.enable) {\n const auth = config.publish.oppo.auth\n if (!auth?.clientId || !auth?.clientSecret) {\n logger.error('OPPO enabled but missing auth info (clientId, clientSecret)')\n return false\n }\n }\n\n if (config.publish?.vivo?.enable) {\n const auth = config.publish.vivo.auth\n if (!auth?.accessKey || !auth?.accessSecret) {\n logger.error('vivo enabled but missing auth info (accessKey, accessSecret)')\n return false\n }\n }\n\n if (config.publish?.tencent?.enable) {\n const auth = config.publish.tencent.auth\n if (!auth?.userId || !auth?.appId || !auth?.accessSecret) {\n logger.error('Tencent enabled but missing auth info (userId, appId, accessSecret)')\n return false\n }\n }\n\n if (config.publish?.harmony?.enable) {\n const auth = config.publish.harmony.auth\n if (!auth?.clientId || !auth?.clientSecret) {\n logger.error('Harmony enabled but missing auth info (clientId, clientSecret)')\n return false\n }\n }\n\n return true\n }\n}\n","/**\n * 环境变量验证器 (EnvValidator)\n *\n * 检查 YAML 配置中引用的环境变量 (${VAR_NAME}) 是否已在运行时设置\n * 缺失时输出错误日志并返回 false,阻止后续流程\n */\nimport { logger } from '../utils/logger.js'\n\nexport class EnvValidator {\n /**\n * 验证环境变量\n * @param requiredVars 必需的环境变量列表\n */\n static validate(requiredVars: string[]): boolean {\n const missing = requiredVars.filter((v) => !process.env[v])\n if (missing.length > 0) {\n logger.error(`Missing environment variables: ${missing.join(', ')}`)\n return false\n }\n return true\n }\n}\n","/**\n * app-ship CLI 入口\n *\n * 提供三个命令:\n * - upload: 加载 YAML 配置 → 验证 → 并行上传到启用的平台\n * - platforms: 列出所有已注册的上传平台\n * - init: 在当前目录生成示例配置文件 app-ship.yaml\n *\n * 使用方式: app-ship <command> [options]\n */\nimport { UploadManager } from './utils/upload-manager.js'\nimport { ConfigValidator } from './validators/config_validator.js'\nimport { logger } from './utils/logger.js'\nimport path from 'path'\nimport fs from 'fs-extra'\n// @ts-ignore\nimport yaml from 'js-yaml'\n\nconst VERSION = '0.1.0'\n\nfunction printHelp() {\n console.log(`\napp-ship v${VERSION} — Multi-platform app store uploader\n\nUsage:\n app-ship upload -c <config> -f <file> [--platform pgyer,huawei]\n app-ship platforms List supported platforms\n app-ship init Generate sample config file\n app-ship --help Show this help\n app-ship --version Show version\n\nUpload Options:\n -c, --config <path> Config file path (YAML)\n -f, --file <path> App package file (APK/IPA/AAB/HAP)\n -p, --platform <list> Comma-separated platform list (optional, uses config if omitted)\n -v, --version <ver> Version string (default: from config or \"1.0.0\")\n -b, --build-number <n> Build number (default: \"1\")\n --changelog <text> Changelog / release notes\n --verbose Show detailed output\n`)\n}\n\nfunction parseArgs(argv: string[]): Record<string, string | boolean> {\n const args: Record<string, string | boolean> = {}\n let i = 2 // skip node + script\n while (i < argv.length) {\n const arg = argv[i]\n if (arg === '--help' || arg === '-h') {\n args.help = true\n } else if (arg === '--version') {\n args.showVersion = true\n } else if (arg === '--verbose') {\n args.verbose = true\n } else if ((arg === '-c' || arg === '--config') && argv[i + 1]) {\n args.config = argv[++i]\n } else if ((arg === '-f' || arg === '--file') && argv[i + 1]) {\n args.file = argv[++i]\n } else if ((arg === '-p' || arg === '--platform') && argv[i + 1]) {\n args.platform = argv[++i]\n } else if ((arg === '-v' || arg === '--ver') && argv[i + 1]) {\n args.ver = argv[++i]\n } else if ((arg === '-b' || arg === '--build-number') && argv[i + 1]) {\n args.buildNumber = argv[++i]\n } else if (arg === '--changelog' && argv[i + 1]) {\n args.changelog = argv[++i]\n } else if (!arg.startsWith('-')) {\n args.command = arg\n }\n i++\n }\n return args\n}\n\nasync function cmdUpload(args: Record<string, string | boolean>) {\n const configPath = args.config as string\n const filePath = args.file as string\n\n if (!configPath) {\n logger.error('Missing config file. Use: app-ship upload -c <config.yaml> -f <file>')\n process.exit(1)\n }\n if (!filePath) {\n logger.error('Missing file path. Use: app-ship upload -c <config.yaml> -f <file>')\n process.exit(1)\n }\n\n const absConfig = path.resolve(configPath)\n const absFile = path.resolve(filePath)\n\n if (!fs.existsSync(absFile)) {\n logger.error(`File not found: ${absFile}`)\n process.exit(1)\n }\n\n // Load and validate config\n const config = ConfigValidator.loadAndValidate(absConfig)\n if (!config) {\n logger.error('Config validation failed')\n process.exit(1)\n }\n\n // Determine platforms\n const platforms = args.platform\n ? (args.platform as string).split(',').map((s) => s.trim())\n : undefined\n\n const metadata = {\n version: (args.ver as string) || config.version || '1.0.0',\n buildNumber: (args.buildNumber as string) || '1',\n changelog: (args.changelog as string) || '',\n }\n\n logger.title('App Ship — Starting Upload')\n logger.info(`File: ${absFile}`)\n logger.info(`Config: ${absConfig}`)\n if (platforms) {\n logger.info(`Platforms: ${platforms.join(', ')}`)\n }\n logger.newLine()\n\n const manager = new UploadManager({\n maxConcurrent: 3,\n continueOnError: true,\n verbose: !!args.verbose,\n })\n\n const report = await manager.uploadToMultiplePlatforms(absFile, config, metadata, platforms)\n\n process.exit(report.failureCount > 0 ? 1 : 0)\n}\n\nfunction cmdPlatforms() {\n const manager = new UploadManager()\n const platforms = manager.getAvailablePlatforms()\n logger.title('Supported Platforms')\n for (const p of platforms) {\n console.log(` • ${p}`)\n }\n console.log(`\\nTotal: ${platforms.length} platforms`)\n}\n\nfunction cmdInit() {\n const filename = 'app-ship.yaml'\n if (fs.existsSync(filename)) {\n logger.warn(`${filename} already exists. Skipping.`)\n return\n }\n\n const sample = {\n version: '1.0.0',\n publish: {\n pgyer: {\n enable: true,\n apiKey: 'YOUR_PGYER_API_KEY',\n },\n huawei: {\n enable: false,\n auth: {\n clientId: '',\n clientSecret: '',\n },\n appId: '',\n },\n xiaomi: {\n enable: false,\n auth: {\n userName: '',\n privateKey: '',\n },\n packageName: 'com.example.app',\n },\n oppo: {\n enable: false,\n auth: {\n clientId: '',\n clientSecret: '',\n },\n },\n vivo: {\n enable: false,\n auth: {\n accessKey: '',\n accessSecret: '',\n },\n },\n tencent: {\n enable: false,\n auth: {\n appId: '',\n accessSecret: '',\n },\n },\n harmony: {\n enable: false,\n auth: {\n clientId: '',\n clientSecret: '',\n },\n appId: '',\n },\n app_store: {\n enable: false,\n auth: {\n appleId: '',\n appPassword: '',\n },\n },\n },\n }\n\n fs.writeFileSync(filename, yaml.dump(sample, { indent: 2 }), 'utf8')\n logger.success(`Created ${filename}`)\n logger.info('Edit the file to configure your platform credentials.')\n}\n\n// --- Main ---\nasync function main() {\n const args = parseArgs(process.argv)\n\n if (args.help) {\n printHelp()\n return\n }\n\n if (args.showVersion) {\n console.log(`app-ship v${VERSION}`)\n return\n }\n\n const command = args.command as string\n\n switch (command) {\n case 'upload':\n await cmdUpload(args)\n break\n case 'platforms':\n cmdPlatforms()\n break\n case 'init':\n cmdInit()\n break\n default:\n printHelp()\n break\n }\n}\n\nmain().catch((err) => {\n logger.error(err.message || String(err))\n process.exit(1)\n})\n"],"mappings":"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","names":["path","process","styles","chalk","styles","fs","fs","crypto","fs","crypto","fs","fs","path","axios","FormData","path","fs","axios","FormData","fs","path","axios","FormData","crypto","crypto","fs","axios","path","FormData","fs","path","exec","promisify","axios","promisify","exec","fs","path","axios","fs","axios","FormData","fs","axios","FormData","fs","path","fs","path","fs","path","axios","FormData","path","axios","FormData","fs","fs","path","axios","FormData","crypto","crypto","path","fs","axios","FormData","fs","path","axios","FormData","crypto","crypto","fs","path","FormData","axios","fs","path","axios","crypto","crypto","fs","path","axios","path","fs","fs","path","fs","yaml"]}
|