@leonxin/meetgames 0.1.7 → 0.1.11
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/.agents/skills/meet-sdk-regression/SKILL.md +93 -0
- package/.cursor/mcp.example.json +16 -0
- package/.cursor/mcp.json +11 -0
- package/.cursor/skills/meetgames-mcp/SKILL.md +48 -0
- package/.vite/vitest/results.json +1 -0
- package/README.md +31 -8
- package/dist/aab-converter/aab-entry.d.ts +3 -0
- package/dist/aab-converter/aab-entry.d.ts.map +1 -0
- package/dist/aab-converter/aab-entry.js +49 -0
- package/dist/aab-converter/aab-entry.js.map +1 -0
- package/dist/aab-converter/apksExtractor.d.ts +2 -0
- package/dist/aab-converter/apksExtractor.d.ts.map +1 -0
- package/dist/aab-converter/apksExtractor.js +108 -0
- package/dist/aab-converter/apksExtractor.js.map +1 -0
- package/dist/aab-converter/bundletoolRunner.d.ts +15 -0
- package/dist/aab-converter/bundletoolRunner.d.ts.map +1 -0
- package/dist/aab-converter/bundletoolRunner.js +46 -0
- package/dist/aab-converter/bundletoolRunner.js.map +1 -0
- package/dist/aab-converter/cliArgs.d.ts +27 -0
- package/dist/aab-converter/cliArgs.d.ts.map +1 -0
- package/dist/aab-converter/cliArgs.js +170 -0
- package/dist/aab-converter/cliArgs.js.map +1 -0
- package/dist/aab-converter/convertAabToApk.d.ts +7 -0
- package/dist/aab-converter/convertAabToApk.d.ts.map +1 -0
- package/dist/aab-converter/convertAabToApk.js +69 -0
- package/dist/aab-converter/convertAabToApk.js.map +1 -0
- package/dist/aab-converter/resourcePaths.d.ts +4 -0
- package/dist/aab-converter/resourcePaths.d.ts.map +1 -0
- package/dist/aab-converter/resourcePaths.js +42 -0
- package/dist/aab-converter/resourcePaths.js.map +1 -0
- package/dist/aab-converter/signingOptions.d.ts +9 -0
- package/dist/aab-converter/signingOptions.d.ts.map +1 -0
- package/dist/aab-converter/signingOptions.js +21 -0
- package/dist/aab-converter/signingOptions.js.map +1 -0
- package/dist/aab-converter/types.d.ts +24 -0
- package/dist/aab-converter/types.d.ts.map +1 -0
- package/dist/aab-converter/types.js +2 -0
- package/dist/aab-converter/types.js.map +1 -0
- package/dist/android/adapter.d.ts.map +1 -1
- package/dist/android/adapter.js +2 -2
- package/dist/android/adapter.js.map +1 -1
- package/dist/android/detect.d.ts +2 -2
- package/dist/android/detect.d.ts.map +1 -1
- package/dist/android/detect.js +36 -8
- package/dist/android/detect.js.map +1 -1
- package/dist/android/meetSdkRemoteGradle.d.ts +0 -3
- package/dist/android/meetSdkRemoteGradle.d.ts.map +1 -1
- package/dist/android/meetSdkRemoteGradle.js +13 -20
- package/dist/android/meetSdkRemoteGradle.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +157 -31
- package/dist/cli.js.map +1 -1
- package/dist/config/meetSdkDefaultConfig.d.ts +19 -2
- package/dist/config/meetSdkDefaultConfig.d.ts.map +1 -1
- package/dist/config/meetSdkDefaultConfig.js +67 -5
- package/dist/config/meetSdkDefaultConfig.js.map +1 -1
- package/dist/config/meetSdkIosConfig.d.ts +21 -0
- package/dist/config/meetSdkIosConfig.d.ts.map +1 -0
- package/dist/config/meetSdkIosConfig.js +66 -0
- package/dist/config/meetSdkIosConfig.js.map +1 -0
- package/dist/config/meetSdkRemoteConfig.d.ts +19 -11
- package/dist/config/meetSdkRemoteConfig.d.ts.map +1 -1
- package/dist/config/meetSdkRemoteConfig.js +89 -69
- package/dist/config/meetSdkRemoteConfig.js.map +1 -1
- package/dist/config/topsdkFeatureModules.d.ts +5 -0
- package/dist/config/topsdkFeatureModules.d.ts.map +1 -1
- package/dist/config/topsdkFeatureModules.js +26 -0
- package/dist/config/topsdkFeatureModules.js.map +1 -1
- package/dist/contracts/types.d.ts +19 -6
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/core/doctor.d.ts +17 -0
- package/dist/core/doctor.d.ts.map +1 -0
- package/dist/core/doctor.js +444 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/pipeline.d.ts.map +1 -1
- package/dist/core/pipeline.js +0 -15
- package/dist/core/pipeline.js.map +1 -1
- package/dist/core/platform.d.ts +12 -0
- package/dist/core/platform.d.ts.map +1 -0
- package/dist/core/platform.js +40 -0
- package/dist/core/platform.js.map +1 -0
- package/dist/core/reporter.js +1 -1
- package/dist/core/reporter.js.map +1 -1
- package/dist/core/workspace.d.ts +2 -2
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +4 -5
- package/dist/core/workspace.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/ios/channelConfig.d.ts +1 -0
- package/dist/ios/channelConfig.d.ts.map +1 -1
- package/dist/ios/channelConfig.js +82 -0
- package/dist/ios/channelConfig.js.map +1 -1
- package/dist/ios/codeUtils.d.ts +1 -0
- package/dist/ios/codeUtils.d.ts.map +1 -1
- package/dist/ios/codeUtils.js +11 -2
- package/dist/ios/codeUtils.js.map +1 -1
- package/dist/ios/detect.d.ts +2 -2
- package/dist/ios/detect.d.ts.map +1 -1
- package/dist/ios/detect.js +49 -10
- package/dist/ios/detect.js.map +1 -1
- package/dist/ios/entitlements.d.ts +4 -0
- package/dist/ios/entitlements.d.ts.map +1 -0
- package/dist/ios/entitlements.js +53 -0
- package/dist/ios/entitlements.js.map +1 -0
- package/dist/ios/fileManager.d.ts.map +1 -1
- package/dist/ios/fileManager.js +3 -2
- package/dist/ios/fileManager.js.map +1 -1
- package/dist/ios/infoPlist.d.ts +1 -1
- package/dist/ios/infoPlist.d.ts.map +1 -1
- package/dist/ios/infoPlist.js.map +1 -1
- package/dist/ios/integrate.d.ts.map +1 -1
- package/dist/ios/integrate.js +211 -36
- package/dist/ios/integrate.js.map +1 -1
- package/dist/ios/pbxprojEditor.d.ts +2 -0
- package/dist/ios/pbxprojEditor.d.ts.map +1 -1
- package/dist/ios/pbxprojEditor.js +179 -1
- package/dist/ios/pbxprojEditor.js.map +1 -1
- package/dist/ios/pluginConfig.d.ts +1 -0
- package/dist/ios/pluginConfig.d.ts.map +1 -1
- package/dist/ios/pluginConfig.js +36 -4
- package/dist/ios/pluginConfig.js.map +1 -1
- package/dist/ios/sdkBundle.d.ts +1 -1
- package/dist/ios/sdkBundle.d.ts.map +1 -1
- package/dist/ios/sdkBundle.js +7 -5
- package/dist/ios/sdkBundle.js.map +1 -1
- package/dist/ios/template.d.ts +1 -0
- package/dist/ios/template.d.ts.map +1 -1
- package/dist/ios/template.js +14 -1
- package/dist/ios/template.js.map +1 -1
- package/dist/ios/types.d.ts +2 -2
- package/dist/ios/types.d.ts.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +14 -13
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/service.d.ts +8 -6
- package/dist/mcp/service.d.ts.map +1 -1
- package/dist/mcp/service.js +34 -14
- package/dist/mcp/service.js.map +1 -1
- package/dist/ops/handlers.d.ts.map +1 -1
- package/dist/ops/handlers.js +10 -4
- package/dist/ops/handlers.js.map +1 -1
- package/dist/remote/sdkHomeDownload.d.ts +65 -0
- package/dist/remote/sdkHomeDownload.d.ts.map +1 -0
- package/dist/remote/sdkHomeDownload.js +208 -0
- package/dist/remote/sdkHomeDownload.js.map +1 -0
- package/dist/remote/topsdkDownloadSdkConfig.d.ts.map +1 -1
- package/dist/remote/topsdkDownloadSdkConfig.js +11 -1
- package/dist/remote/topsdkDownloadSdkConfig.js.map +1 -1
- package/dist/shared/errors.d.ts +7 -0
- package/dist/shared/errors.d.ts.map +1 -0
- package/dist/shared/errors.js +16 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/fileUtils.d.ts +5 -0
- package/dist/shared/fileUtils.d.ts.map +1 -0
- package/dist/shared/fileUtils.js +35 -0
- package/dist/shared/fileUtils.js.map +1 -0
- package/dist/shared/logger.d.ts +10 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +37 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/pathUtils.d.ts +4 -0
- package/dist/shared/pathUtils.d.ts.map +1 -0
- package/dist/shared/pathUtils.js +22 -0
- package/dist/shared/pathUtils.js.map +1 -0
- package/dist/shared/processRunner.d.ts +12 -0
- package/dist/shared/processRunner.d.ts.map +1 -0
- package/dist/shared/processRunner.js +31 -0
- package/dist/shared/processRunner.js.map +1 -0
- package/docs/AAB_CONVERTER_CLI_PLAN.md +392 -0
- package/docs/API.md +246 -32
- package/docs/CLI.md +292 -0
- package/docs/INTEGRATION.md +116 -0
- package/docs/MCP.md +86 -0
- package/docs/README.md +19 -10
- package/docs/{api → archive/api}/downloadSDKConfig.md +8 -6
- package/docs/{api → archive/api}/getChannelConfig-meetgames.md +1 -1
- package/docs/archive/ios-migration.md +2139 -0
- package/docs/{ → archive/product/}/346/212/200/346/234/257/346/226/271/346/241/210/350/260/203/347/240/224.md +7 -7
- package/docs/{ → archive/product/}/351/234/200/346/261/202/346/226/207/346/241/243.md +15 -14
- package/logs/convert-20260622-155037.log +5 -0
- package/logs/convert-20260622-155226.log +6 -0
- package/meetsdk-android.json +2 -1
- package/meetsdk-ios.json +15 -0
- package/package.json +10 -35
- package/scripts/package-aab-cli-win.mjs +193 -0
- package/src/aab-converter/aab-entry.ts +48 -0
- package/src/aab-converter/apksExtractor.ts +119 -0
- package/src/aab-converter/bundletoolRunner.ts +63 -0
- package/src/aab-converter/cliArgs.ts +194 -0
- package/src/aab-converter/convertAabToApk.ts +81 -0
- package/src/aab-converter/resourcePaths.ts +43 -0
- package/src/aab-converter/signingOptions.ts +29 -0
- package/src/aab-converter/types.ts +26 -0
- package/src/android/adapter.ts +9 -0
- package/src/android/assembleIntegrationJson.ts +33 -0
- package/src/android/detect.ts +132 -0
- package/src/android/downloadGoogleServicesJson.ts +56 -0
- package/src/android/gradle.ts +116 -0
- package/src/android/manifest.ts +50 -0
- package/src/android/meetSdkRemoteGradle.ts +837 -0
- package/src/cli.ts +488 -0
- package/src/config/fetchConfigWrite.ts +30 -0
- package/src/config/loadAndroidIntegration.ts +41 -0
- package/src/config/loadManifest.ts +40 -0
- package/src/config/meetSdkDefaultConfig.ts +99 -0
- package/src/config/meetSdkIosConfig.ts +87 -0
- package/src/config/meetSdkRemoteConfig.ts +1211 -0
- package/src/config/topsdkFeatureModules.ts +92 -0
- package/src/contracts/types.ts +121 -0
- package/src/core/doctor.ts +485 -0
- package/src/core/patch.ts +64 -0
- package/src/core/pipeline.ts +107 -0
- package/src/core/platform.ts +47 -0
- package/src/core/previewPatches.ts +23 -0
- package/src/core/reporter.ts +24 -0
- package/src/core/workspace.ts +29 -0
- package/src/entry.ts +7 -0
- package/src/index.ts +133 -0
- package/src/ios/channelConfig.ts +128 -0
- package/src/ios/codeUtils.ts +160 -0
- package/src/ios/detect.ts +105 -0
- package/src/ios/entitlements.ts +61 -0
- package/src/ios/fileManager.ts +48 -0
- package/src/ios/infoPlist.ts +55 -0
- package/src/ios/integrate.ts +516 -0
- package/src/ios/pbxprojEditor.ts +383 -0
- package/src/ios/pluginConfig.ts +97 -0
- package/src/ios/reserved.ts +8 -0
- package/src/ios/sdkBundle.ts +36 -0
- package/src/ios/template.ts +36 -0
- package/src/ios/types.ts +65 -0
- package/src/mcp/server.ts +170 -0
- package/src/mcp/service.ts +222 -0
- package/src/mcp-entry.ts +7 -0
- package/src/ops/fileStore.ts +56 -0
- package/src/ops/handlers.ts +304 -0
- package/src/remote/fetchJson.ts +22 -0
- package/src/remote/sdkHomeDownload.ts +274 -0
- package/src/remote/topsdkDownloadSdkConfig.ts +93 -0
- package/src/remote/topsdkGetSdkConfig.ts +122 -0
- package/src/remote/topsdkSign.ts +10 -0
- package/src/shared/errors.ts +16 -0
- package/src/shared/fileUtils.ts +41 -0
- package/src/shared/logger.ts +49 -0
- package/src/shared/pathUtils.ts +24 -0
- package/src/shared/processRunner.ts +43 -0
- package/test-projects/README.md +51 -0
- package/test-projects/_preview/pipeline.patch +281 -0
- package/tests/aab-converter.test.ts +213 -0
- package/tests/assemble.test.ts +12 -0
- package/tests/doctor.test.ts +89 -0
- package/tests/downloadGoogleServicesJson.test.ts +47 -0
- package/tests/fetch-remote.test.ts +23 -0
- package/tests/fetchConfigOverrides.test.ts +28 -0
- package/tests/fetchConfigWrite.test.ts +54 -0
- package/tests/gradle.test.ts +33 -0
- package/tests/integration-json.test.ts +29 -0
- package/tests/ios.codeUtils.test.ts +23 -0
- package/tests/ios.sdkBundle.test.ts +16 -0
- package/tests/loadManifest.test.ts +15 -0
- package/tests/manifest-xml.test.ts +30 -0
- package/tests/mcp.e2e.ts +217 -0
- package/tests/mcp.service.test.ts +53 -0
- package/tests/meetSdkRemoteConfig.test.ts +456 -0
- package/tests/meetSdkRemoteGradle.test.ts +414 -0
- package/tests/pipeline.android.test.ts +96 -0
- package/tests/pipeline.integration-json.test.ts +58 -0
- package/tests/pipeline.ios.test.ts +385 -0
- package/tests/pipeline.preview.patch.test.ts +85 -0
- package/tests/platformSelection.test.ts +77 -0
- package/tests/sdkHomeDownload.test.ts +124 -0
- package/tests/sdkVersionConfig.test.ts +130 -0
- package/tests/test-projects-hosts.test.ts +78 -0
- package/tests/topsdk.test.ts +53 -0
- package/tests/topsdkDownloadSdkConfig.test.ts +81 -0
- package/tests/topsdkFeatureModules.test.ts +116 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +9 -0
- package/vitest.mcp.config.ts +11 -0
- package/bundled/android/sample.txt +0 -1
- package/docs/ANDROID.md +0 -133
- package/docs/CURSOR-MCP-SETUP.md +0 -72
- package/docs/MCP-SKILL.md +0 -63
- package/fixtures/api-samples/getChannelConfig-meetgames.sample.json +0 -123
- package/fixtures/meetsdk-remote-config.download-shape.json +0 -20
- package/fixtures/meetsdk-remote-config.mock.json +0 -69
- package/fixtures/recipes/android-default.fixture.yaml +0 -15
- package/fixtures/recipes/android-integration.fixture.json +0 -29
- package/fixtures/topsdk-config-reference.json +0 -39
- /package/docs/{api → archive/api}/getSDKConfig.md +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topsdkDownloadSdkConfig.js","sourceRoot":"","sources":["../../src/remote/topsdkDownloadSdkConfig.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"topsdkDownloadSdkConfig.js","sourceRoot":"","sources":["../../src/remote/topsdkDownloadSdkConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare class UserFacingError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
readonly details?: string;
|
|
4
|
+
constructor(code: string, message: string, details?: string);
|
|
5
|
+
}
|
|
6
|
+
export declare function errorMessage(error: unknown): string;
|
|
7
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/shared/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;gBAEd,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAM5D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGnD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export class UserFacingError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
details;
|
|
4
|
+
constructor(code, message, details) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "UserFacingError";
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.details = details;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function errorMessage(error) {
|
|
12
|
+
if (error instanceof Error)
|
|
13
|
+
return error.message;
|
|
14
|
+
return String(error);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/shared/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAAS;IACb,OAAO,CAAU;IAE1B,YAAY,IAAY,EAAE,OAAe,EAAE,OAAgB;QACzD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,KAAK,YAAY,KAAK;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IACjD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function assertFileExists(filePath: string, code: string, label: string): void;
|
|
2
|
+
export declare function ensureDirectory(dirPath: string): void;
|
|
3
|
+
export declare function assertWritableDirectory(dirPath: string): void;
|
|
4
|
+
export declare function assertCanWriteFile(filePath: string, overwrite: boolean, label: string): void;
|
|
5
|
+
//# sourceMappingURL=fileUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileUtils.d.ts","sourceRoot":"","sources":["../../src/shared/fileUtils.ts"],"names":[],"mappings":"AAIA,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAOpF;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKrD;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAa7D;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAK5F"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { UserFacingError } from "./errors.js";
|
|
4
|
+
export function assertFileExists(filePath, code, label) {
|
|
5
|
+
if (!fs.existsSync(filePath)) {
|
|
6
|
+
throw new UserFacingError(code, `${label} does not exist: ${filePath}`);
|
|
7
|
+
}
|
|
8
|
+
if (!fs.statSync(filePath).isFile()) {
|
|
9
|
+
throw new UserFacingError(code, `${label} is not a file: ${filePath}`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function ensureDirectory(dirPath) {
|
|
13
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
14
|
+
if (!fs.statSync(dirPath).isDirectory()) {
|
|
15
|
+
throw new UserFacingError("OUTPUT_DIR_INVALID", `Output path is not a directory: ${dirPath}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function assertWritableDirectory(dirPath) {
|
|
19
|
+
ensureDirectory(dirPath);
|
|
20
|
+
try {
|
|
21
|
+
const probe = path.join(dirPath, `.write-test-${Date.now()}-${Math.random().toString(16).slice(2)}`);
|
|
22
|
+
fs.writeFileSync(probe, "");
|
|
23
|
+
fs.unlinkSync(probe);
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
throw new UserFacingError("OUTPUT_DIR_NOT_WRITABLE", `Output directory is not writable: ${dirPath}`, e instanceof Error ? e.message : String(e));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function assertCanWriteFile(filePath, overwrite, label) {
|
|
30
|
+
if (!overwrite && fs.existsSync(filePath)) {
|
|
31
|
+
throw new UserFacingError("OUTPUT_EXISTS", `${label} already exists: ${filePath}`);
|
|
32
|
+
}
|
|
33
|
+
ensureDirectory(path.dirname(filePath));
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=fileUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileUtils.js","sourceRoot":"","sources":["../../src/shared/fileUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,IAAY,EAAE,KAAa;IAC5E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,GAAG,KAAK,oBAAoB,QAAQ,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,GAAG,KAAK,mBAAmB,QAAQ,EAAE,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,eAAe,CAAC,oBAAoB,EAAE,mCAAmC,OAAO,EAAE,CAAC,CAAC;IAChG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAe;IACrD,eAAe,CAAC,OAAO,CAAC,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACrG,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5B,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,eAAe,CACvB,yBAAyB,EACzB,qCAAqC,OAAO,EAAE,EAC9C,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAC3C,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,SAAkB,EAAE,KAAa;IACpF,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,eAAe,CAAC,eAAe,EAAE,GAAG,KAAK,oBAAoB,QAAQ,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface Logger {
|
|
2
|
+
readonly logPath?: string;
|
|
3
|
+
info(message: string): void;
|
|
4
|
+
warn(message: string): void;
|
|
5
|
+
error(message: string): void;
|
|
6
|
+
close(): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function createFileLogger(logDir: string): Logger;
|
|
9
|
+
export declare function createConsoleLogger(verbose: boolean): Logger;
|
|
10
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/shared/logger.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;CACf;AAcD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAcvD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAS5D"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
function timestamp() {
|
|
4
|
+
return new Date().toISOString();
|
|
5
|
+
}
|
|
6
|
+
function logFileName() {
|
|
7
|
+
const d = new Date();
|
|
8
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
9
|
+
return `convert-${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}.log`;
|
|
10
|
+
}
|
|
11
|
+
export function createFileLogger(logDir) {
|
|
12
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
13
|
+
const logPath = path.join(logDir, logFileName());
|
|
14
|
+
const stream = fs.createWriteStream(logPath, { flags: "a", encoding: "utf8" });
|
|
15
|
+
const write = (level, message) => {
|
|
16
|
+
stream.write(`[${timestamp()}] [${level}] ${message}\n`);
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
logPath,
|
|
20
|
+
info: (message) => write("INFO", message),
|
|
21
|
+
warn: (message) => write("WARN", message),
|
|
22
|
+
error: (message) => write("ERROR", message),
|
|
23
|
+
close: () => stream.end(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function createConsoleLogger(verbose) {
|
|
27
|
+
return {
|
|
28
|
+
info: (message) => {
|
|
29
|
+
if (verbose)
|
|
30
|
+
console.log(message);
|
|
31
|
+
},
|
|
32
|
+
warn: (message) => console.warn(message),
|
|
33
|
+
error: (message) => console.error(message),
|
|
34
|
+
close: () => undefined,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/shared/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAU7B,SAAS,SAAS;IAChB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,WAAW;IAClB,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACrB,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,WAAW,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,GAAG,CACrG,CAAC,CAAC,UAAU,EAAE,CACf,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,EAAE,CAAC,iBAAiB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/E,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,OAAe,EAAE,EAAE;QAC/C,MAAM,CAAC,KAAK,CAAC,IAAI,SAAS,EAAE,MAAM,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC;IAC3D,CAAC,CAAC;IACF,OAAO;QACL,OAAO;QACP,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC;QACzC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC;QACzC,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;QAC3C,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE;KAC1B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;QACL,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YAChB,IAAI,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QACxC,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;QAC1C,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;KACvB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function toAbsolutePath(value: string, baseDir?: string): string;
|
|
2
|
+
export declare function baseNameWithoutExt(filePath: string, expectedExt: string): string;
|
|
3
|
+
export declare function validateOutputFileName(fileName: string): string;
|
|
4
|
+
//# sourceMappingURL=pathUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathUtils.d.ts","sourceRoot":"","sources":["../../src/shared/pathUtils.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,SAAgB,GAAG,MAAM,CAE7E;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAMhF;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ/D"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { UserFacingError } from "./errors.js";
|
|
3
|
+
export function toAbsolutePath(value, baseDir = process.cwd()) {
|
|
4
|
+
return path.resolve(baseDir, value);
|
|
5
|
+
}
|
|
6
|
+
export function baseNameWithoutExt(filePath, expectedExt) {
|
|
7
|
+
const parsed = path.parse(filePath);
|
|
8
|
+
if (parsed.ext.toLowerCase() !== expectedExt.toLowerCase()) {
|
|
9
|
+
throw new UserFacingError("INVALID_EXTENSION", `Expected ${expectedExt} file: ${filePath}`);
|
|
10
|
+
}
|
|
11
|
+
return parsed.name;
|
|
12
|
+
}
|
|
13
|
+
export function validateOutputFileName(fileName) {
|
|
14
|
+
if (!fileName.trim()) {
|
|
15
|
+
throw new UserFacingError("INVALID_APK_NAME", "--apk-name cannot be empty");
|
|
16
|
+
}
|
|
17
|
+
if (fileName.includes("/") || fileName.includes("\\") || path.basename(fileName) !== fileName) {
|
|
18
|
+
throw new UserFacingError("INVALID_APK_NAME", "--apk-name must be a file name, not a path");
|
|
19
|
+
}
|
|
20
|
+
return fileName.toLowerCase().endsWith(".apk") ? fileName : `${fileName}.apk`;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=pathUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathUtils.js","sourceRoot":"","sources":["../../src/shared/pathUtils.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE;IACnE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,WAAmB;IACtE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3D,MAAM,IAAI,eAAe,CAAC,mBAAmB,EAAE,YAAY,WAAW,UAAU,QAAQ,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;QACrB,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,4BAA4B,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC9F,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,4CAA4C,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,MAAM,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface RunProcessOptions {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
onStdout?: (chunk: string) => void;
|
|
4
|
+
onStderr?: (chunk: string) => void;
|
|
5
|
+
}
|
|
6
|
+
export interface RunProcessResult {
|
|
7
|
+
exitCode: number;
|
|
8
|
+
stdout: string;
|
|
9
|
+
stderr: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function runProcess(file: string, args: string[], options?: RunProcessOptions): Promise<RunProcessResult>;
|
|
12
|
+
//# sourceMappingURL=processRunner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processRunner.d.ts","sourceRoot":"","sources":["../../src/shared/processRunner.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4BnH"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
export function runProcess(file, args, options = {}) {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
const child = spawn(file, args, {
|
|
5
|
+
cwd: options.cwd,
|
|
6
|
+
windowsHide: true,
|
|
7
|
+
shell: false,
|
|
8
|
+
});
|
|
9
|
+
let stdout = "";
|
|
10
|
+
let stderr = "";
|
|
11
|
+
child.stdout?.on("data", (buf) => {
|
|
12
|
+
const text = buf.toString("utf8");
|
|
13
|
+
stdout += text;
|
|
14
|
+
options.onStdout?.(text);
|
|
15
|
+
});
|
|
16
|
+
child.stderr?.on("data", (buf) => {
|
|
17
|
+
const text = buf.toString("utf8");
|
|
18
|
+
stderr += text;
|
|
19
|
+
options.onStderr?.(text);
|
|
20
|
+
});
|
|
21
|
+
child.on("error", reject);
|
|
22
|
+
child.on("close", (exitCode) => {
|
|
23
|
+
resolve({
|
|
24
|
+
exitCode: exitCode ?? 1,
|
|
25
|
+
stdout,
|
|
26
|
+
stderr,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=processRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processRunner.js","sourceRoot":"","sources":["../../src/shared/processRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAc3C,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,IAAc,EAAE,UAA6B,EAAE;IACtF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE;YAC9B,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,WAAW,EAAE,IAAI;YACjB,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;QACH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,GAAW,EAAE,EAAE;YACvC,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,IAAI,IAAI,CAAC;YACf,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,GAAW,EAAE,EAAE;YACvC,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,IAAI,IAAI,CAAC;YACf,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC7B,OAAO,CAAC;gBACN,QAAQ,EAAE,QAAQ,IAAI,CAAC;gBACvB,MAAM;gBACN,MAAM;aACP,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
# AAB 转 APK 命令行工具方案
|
|
2
|
+
|
|
3
|
+
本文记录 `meet-sdk-tool` 工具集新增 AAB 转 APK 工具的第一版方案。当前结论以本文为准:先做纯命令行绿色版 zip,不做桌面 UI,不做安装包,不内置 ADB。
|
|
4
|
+
|
|
5
|
+
## 目标
|
|
6
|
+
|
|
7
|
+
面向运营人员提供一个 Windows 可直接解压使用的命令行工具,把 Android App Bundle (`.aab`) 转换为可以安装到手机的通用 APK (`universal.apk`)。
|
|
8
|
+
|
|
9
|
+
第一版只覆盖最小闭环:
|
|
10
|
+
|
|
11
|
+
- 输入 `.aab`
|
|
12
|
+
- 输入签名文件路径和签名参数
|
|
13
|
+
- 调用 Google 官方 `bundletool`
|
|
14
|
+
- 生成 `.apks`
|
|
15
|
+
- 从 `.apks` 中提取 `universal.apk`
|
|
16
|
+
- 输出最终 `.apk`
|
|
17
|
+
|
|
18
|
+
## 非目标
|
|
19
|
+
|
|
20
|
+
第一版暂不实现:
|
|
21
|
+
|
|
22
|
+
- Electron 桌面 UI
|
|
23
|
+
- Windows 安装包 `.exe installer`
|
|
24
|
+
- ADB 检测或一键安装手机
|
|
25
|
+
- 自动更新
|
|
26
|
+
- 远程签名服务
|
|
27
|
+
- Android / iOS SDK 接入流程复用
|
|
28
|
+
- 接入现有 `recipe / pipeline / integrate` 机制
|
|
29
|
+
|
|
30
|
+
## 技术选型
|
|
31
|
+
|
|
32
|
+
采用当前仓库已有的 TypeScript / Node 技术栈:
|
|
33
|
+
|
|
34
|
+
| 能力 | 选型 | 说明 |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| CLI 逻辑 | TypeScript + Node.js | 与现有 `meet-sdk-tool` 技术栈一致 |
|
|
37
|
+
| AAB 转 APK | `bundletool.jar` | Google 官方工具 |
|
|
38
|
+
| Java 运行环境 | Windows x64 JRE | 绿色版内置,运营无需安装 Java |
|
|
39
|
+
| Windows 运行环境 | Windows x64 `node.exe` | 绿色版内置,运营无需安装 Node |
|
|
40
|
+
| 打包方式 | macOS 组装 zip | zip 内放 Windows 运行时和资源 |
|
|
41
|
+
| 验收方式 | Windows 实机验收 | macOS 只负责生成 zip,不替代 Windows 验证 |
|
|
42
|
+
|
|
43
|
+
已确认的资源策略:
|
|
44
|
+
|
|
45
|
+
- `bundletool.jar` 使用官方 GitHub Releases 最新稳定版;实现时从 `https://github.com/google/bundletool/releases/latest` 确认并固定版本。
|
|
46
|
+
- 截至 2026-06-22,官方 latest release 为 `1.18.3`。
|
|
47
|
+
- Windows Node 运行时当前固定为 Node.js `v24.17.0`。
|
|
48
|
+
- Windows JRE 当前固定为 Eclipse Temurin JRE `21.0.11+10`。
|
|
49
|
+
- 允许在仓库或 release 资源目录中保存 Windows x64 `node.exe`、Windows x64 JRE、`bundletool.jar`。
|
|
50
|
+
- 第一版强制传入正式签名参数,不支持 debug / default 签名模式。
|
|
51
|
+
|
|
52
|
+
## 交付形态
|
|
53
|
+
|
|
54
|
+
最终产物:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
release/MeetSDKTool-AABConverter-win-x64.zip
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
解压后目录建议:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
MeetSDKTool-AABConverter-win-x64/
|
|
64
|
+
aab2apk.cmd
|
|
65
|
+
app/
|
|
66
|
+
aab-converter/
|
|
67
|
+
aab-entry.js
|
|
68
|
+
shared/
|
|
69
|
+
runtime/
|
|
70
|
+
node/
|
|
71
|
+
node.exe
|
|
72
|
+
jre/
|
|
73
|
+
bin/
|
|
74
|
+
java.exe
|
|
75
|
+
tools/
|
|
76
|
+
bundletool.jar
|
|
77
|
+
logs/
|
|
78
|
+
output/
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`bundletool.jar` 是跨平台 jar;`node.exe` 和 `java.exe` 必须是 Windows x64 版本,不能放 macOS 版本。
|
|
82
|
+
|
|
83
|
+
## 使用方式
|
|
84
|
+
|
|
85
|
+
推荐通过环境变量传密码,避免密码出现在命令历史和进程参数中:
|
|
86
|
+
|
|
87
|
+
```bat
|
|
88
|
+
set KS_PASS=your_keystore_password
|
|
89
|
+
set KEY_PASS=your_key_password
|
|
90
|
+
|
|
91
|
+
aab2apk.cmd convert ^
|
|
92
|
+
--aab "D:\packages\game.aab" ^
|
|
93
|
+
--out-dir "D:\output" ^
|
|
94
|
+
--ks "D:\keys\release.jks" ^
|
|
95
|
+
--ks-key-alias "release" ^
|
|
96
|
+
--ks-pass-env KS_PASS ^
|
|
97
|
+
--key-pass-env KEY_PASS
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
也可以支持直接传密码,但仅用于临时测试:
|
|
101
|
+
|
|
102
|
+
```bat
|
|
103
|
+
aab2apk.cmd convert ^
|
|
104
|
+
--aab "D:\packages\game.aab" ^
|
|
105
|
+
--out-dir "D:\output" ^
|
|
106
|
+
--ks "D:\keys\release.jks" ^
|
|
107
|
+
--ks-key-alias "release" ^
|
|
108
|
+
--ks-pass "your_keystore_password" ^
|
|
109
|
+
--key-pass "your_key_password"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## CLI 参数
|
|
113
|
+
|
|
114
|
+
命令:
|
|
115
|
+
|
|
116
|
+
```text
|
|
117
|
+
aab2apk.cmd convert --aab <file.aab> --out-dir <dir> [options]
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
参数:
|
|
121
|
+
|
|
122
|
+
| 参数 | 必填 | 说明 |
|
|
123
|
+
|---|---:|---|
|
|
124
|
+
| `--aab` | 是 | AAB 文件路径 |
|
|
125
|
+
| `--out-dir` | 是 | APK 输出目录 |
|
|
126
|
+
| `--ks` | 是 | keystore / jks 文件路径 |
|
|
127
|
+
| `--ks-key-alias` | 是 | keystore 中的 key alias |
|
|
128
|
+
| `--ks-pass-env` | 否 | 从指定环境变量读取 keystore 密码,推荐 |
|
|
129
|
+
| `--key-pass-env` | 否 | 从指定环境变量读取 key 密码,推荐 |
|
|
130
|
+
| `--ks-pass` | 否 | 直接传 keystore 密码,不推荐 |
|
|
131
|
+
| `--key-pass` | 否 | 直接传 key 密码,不推荐 |
|
|
132
|
+
| `--apk-name` | 否 | 自定义输出 APK 文件名 |
|
|
133
|
+
| `--keep-apks` | 否 | 保留中间产物 `.apks` |
|
|
134
|
+
| `--no-overwrite` | 否 | 不覆盖已存在的输出 APK |
|
|
135
|
+
| `--verbose` | 否 | 输出详细日志 |
|
|
136
|
+
|
|
137
|
+
密码解析规则:
|
|
138
|
+
|
|
139
|
+
1. 优先读取 `--ks-pass-env` / `--key-pass-env` 指定的环境变量。
|
|
140
|
+
2. 如果未传 env 参数,再读取 `--ks-pass` / `--key-pass`。
|
|
141
|
+
3. 如果签名参数不完整,直接报错,不进入 bundletool 执行阶段。
|
|
142
|
+
4. 不支持缺省签名、debug 签名或无签名转换。
|
|
143
|
+
|
|
144
|
+
输出覆盖规则:
|
|
145
|
+
|
|
146
|
+
- 默认覆盖已存在的同名 APK 和中间 `.apks` 文件。
|
|
147
|
+
- 如需防止覆盖,显式传 `--no-overwrite`。
|
|
148
|
+
|
|
149
|
+
## 核心转换流程
|
|
150
|
+
|
|
151
|
+
内部调用 `bundletool`:
|
|
152
|
+
|
|
153
|
+
```bat
|
|
154
|
+
java.exe -jar bundletool.jar build-apks ^
|
|
155
|
+
--bundle="D:\packages\game.aab" ^
|
|
156
|
+
--output="D:\output\game.apks" ^
|
|
157
|
+
--mode=universal ^
|
|
158
|
+
--ks="D:\keys\release.jks" ^
|
|
159
|
+
--ks-key-alias="release" ^
|
|
160
|
+
--ks-pass=pass:xxx ^
|
|
161
|
+
--key-pass=pass:xxx ^
|
|
162
|
+
--overwrite
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
然后把 `.apks` 当 zip 解压,提取:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
universal.apk
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
默认输出命名:
|
|
172
|
+
|
|
173
|
+
```text
|
|
174
|
+
原AAB文件名_universal.apk
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
示例:
|
|
178
|
+
|
|
179
|
+
```text
|
|
180
|
+
game.aab -> game_universal.apk
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## 模块设计
|
|
184
|
+
|
|
185
|
+
新增独立模块,不耦合现有接入工具:
|
|
186
|
+
|
|
187
|
+
```text
|
|
188
|
+
src/
|
|
189
|
+
aab-converter/
|
|
190
|
+
aab-entry.ts
|
|
191
|
+
cliArgs.ts
|
|
192
|
+
convertAabToApk.ts
|
|
193
|
+
bundletoolRunner.ts
|
|
194
|
+
apksExtractor.ts
|
|
195
|
+
signingOptions.ts
|
|
196
|
+
types.ts
|
|
197
|
+
|
|
198
|
+
shared/
|
|
199
|
+
processRunner.ts
|
|
200
|
+
fileUtils.ts
|
|
201
|
+
pathUtils.ts
|
|
202
|
+
logger.ts
|
|
203
|
+
errors.ts
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
允许的依赖方向:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
aab-converter -> shared
|
|
210
|
+
原接入工具 -> shared
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
禁止的依赖方向:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
aab-converter -> recipe / pipeline / integrate
|
|
217
|
+
recipe / pipeline / integrate -> aab-converter
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
原因:AAB 转 APK 是独立文件转换,原接入工具是宿主工程改造。两者业务模型不同,只能共用基础库,不能共用集成 pipeline。
|
|
221
|
+
|
|
222
|
+
## 与现有工具的关系
|
|
223
|
+
|
|
224
|
+
`meet-sdk-tool` 作为工具集存在,包含多个独立工具:
|
|
225
|
+
|
|
226
|
+
```text
|
|
227
|
+
SDK 接入工具:
|
|
228
|
+
meetgames setup / integrate / doctor
|
|
229
|
+
使用 recipe / pipeline / op handlers
|
|
230
|
+
|
|
231
|
+
AAB 转 APK 工具:
|
|
232
|
+
aab2apk.cmd convert
|
|
233
|
+
使用 aab-converter 独立流程
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
现有 `meetgames` CLI、MCP、SDK 接入逻辑不应因 AAB 转换工具发生行为变化。
|
|
237
|
+
|
|
238
|
+
## 打包方案
|
|
239
|
+
|
|
240
|
+
macOS 负责生成 Windows 绿色版 zip,但只是组装文件,不编译 Windows 原生代码。
|
|
241
|
+
|
|
242
|
+
打包前置条件:
|
|
243
|
+
|
|
244
|
+
- 已完成 TypeScript 编译
|
|
245
|
+
- 已准备 Windows x64 `node.exe`
|
|
246
|
+
- 已准备 Windows x64 JRE
|
|
247
|
+
- 已准备 `bundletool.jar`
|
|
248
|
+
- 运行时依赖不包含 macOS 原生二进制
|
|
249
|
+
|
|
250
|
+
建议脚本:
|
|
251
|
+
|
|
252
|
+
```text
|
|
253
|
+
npm run build:aab
|
|
254
|
+
npm run package:aab-win-zip
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
打包脚本职责:
|
|
258
|
+
|
|
259
|
+
1. 清理临时 release 目录。
|
|
260
|
+
2. 拷贝编译后的 `dist/aab-converter` 和必要的 `dist/shared`。
|
|
261
|
+
3. 拷贝 `runtime/win-x64/node/node.exe`。
|
|
262
|
+
4. 拷贝 `runtime/win-x64/jre`。
|
|
263
|
+
5. 拷贝 `tools/bundletool.jar`。
|
|
264
|
+
6. 生成 `aab2apk.cmd`。
|
|
265
|
+
7. 创建空 `logs/` 和 `output/`。
|
|
266
|
+
8. 压缩为 `MeetSDKTool-AABConverter-win-x64.zip`。
|
|
267
|
+
9. 排除 `.DS_Store`、`__MACOSX/` 等 macOS 文件。
|
|
268
|
+
|
|
269
|
+
## Windows 验收
|
|
270
|
+
|
|
271
|
+
macOS 生成 zip 后,必须在 Windows 机器验收。
|
|
272
|
+
|
|
273
|
+
最小验收命令:
|
|
274
|
+
|
|
275
|
+
```bat
|
|
276
|
+
aab2apk.cmd --help
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
完整验收命令:
|
|
280
|
+
|
|
281
|
+
```bat
|
|
282
|
+
set KS_PASS=your_keystore_password
|
|
283
|
+
set KEY_PASS=your_key_password
|
|
284
|
+
|
|
285
|
+
aab2apk.cmd convert ^
|
|
286
|
+
--aab "D:\test\game.aab" ^
|
|
287
|
+
--out-dir "D:\test\out" ^
|
|
288
|
+
--ks "D:\test\release.jks" ^
|
|
289
|
+
--ks-key-alias "release" ^
|
|
290
|
+
--ks-pass-env KS_PASS ^
|
|
291
|
+
--key-pass-env KEY_PASS ^
|
|
292
|
+
--verbose
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
验收项:
|
|
296
|
+
|
|
297
|
+
- Windows 上解压 zip 后能直接运行。
|
|
298
|
+
- 机器未安装 Node 时也能运行。
|
|
299
|
+
- 机器未安装 Java 时也能运行。
|
|
300
|
+
- 中文路径可用。
|
|
301
|
+
- 带空格路径可用。
|
|
302
|
+
- 输出目录不存在时可创建。
|
|
303
|
+
- 默认覆盖同名输出。
|
|
304
|
+
- 传 `--no-overwrite` 时,同名输出存在则失败并提示。
|
|
305
|
+
- keystore 密码错误时提示清晰。
|
|
306
|
+
- alias 错误时提示清晰。
|
|
307
|
+
- bundletool 失败时保留日志。
|
|
308
|
+
- 成功生成 `*_universal.apk`。
|
|
309
|
+
|
|
310
|
+
## 错误提示
|
|
311
|
+
|
|
312
|
+
需要对常见错误做中文化映射:
|
|
313
|
+
|
|
314
|
+
| 场景 | 提示方向 |
|
|
315
|
+
|---|---|
|
|
316
|
+
| AAB 文件不存在 | 检查 `--aab` 路径 |
|
|
317
|
+
| AAB 后缀不正确 | 只支持 `.aab` 文件 |
|
|
318
|
+
| keystore 文件不存在 | 检查 `--ks` 路径 |
|
|
319
|
+
| 签名参数不完整 | 检查 `--ks-key-alias` 和密码参数 |
|
|
320
|
+
| 环境变量不存在 | 检查 `--ks-pass-env` / `--key-pass-env` |
|
|
321
|
+
| Java 缺失 | 绿色版包损坏或 JRE 未打入 |
|
|
322
|
+
| bundletool 缺失 | 绿色版包损坏或 `bundletool.jar` 未打入 |
|
|
323
|
+
| 密码或 alias 错误 | 检查 keystore 密码、key 密码和 alias |
|
|
324
|
+
| 未找到 `universal.apk` | 检查 bundletool 输出和 `.apks` 内容 |
|
|
325
|
+
| 输出目录不可写 | 更换输出目录或检查权限 |
|
|
326
|
+
|
|
327
|
+
## 测试策略
|
|
328
|
+
|
|
329
|
+
核心单元测试:
|
|
330
|
+
|
|
331
|
+
- CLI 参数解析
|
|
332
|
+
- 签名参数解析
|
|
333
|
+
- bundletool 参数构造
|
|
334
|
+
- 输出文件命名
|
|
335
|
+
- `.apks` 解压与 `universal.apk` 查找
|
|
336
|
+
|
|
337
|
+
集成测试:
|
|
338
|
+
|
|
339
|
+
- 使用测试 AAB 跑通转换
|
|
340
|
+
- 验证输出 APK 存在
|
|
341
|
+
- 验证 `--keep-apks`
|
|
342
|
+
- 验证默认覆盖
|
|
343
|
+
- 验证 `--no-overwrite`
|
|
344
|
+
|
|
345
|
+
测试文件放置目录:
|
|
346
|
+
|
|
347
|
+
```text
|
|
348
|
+
test-assets/aab-converter/
|
|
349
|
+
sample.aab
|
|
350
|
+
sample-release.jks
|
|
351
|
+
README.md 或其他本地 .md
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
注意:
|
|
355
|
+
|
|
356
|
+
- 只放测试包和测试签名文件,不能放生产 keystore。
|
|
357
|
+
- `.aab`、`.apk`、`.apks`、`.jks`、`.keystore`、该目录下的 `.md` 默认不提交到 git。
|
|
358
|
+
- 测试密码和 alias 可以写在同目录的本地 `.md` 中或通过环境变量传入,不要提交真实生产密码。
|
|
359
|
+
|
|
360
|
+
回归测试:
|
|
361
|
+
|
|
362
|
+
- 现有 `npm test` 必须通过
|
|
363
|
+
- 现有 `meetgames setup / integrate / doctor` 行为不变
|
|
364
|
+
|
|
365
|
+
## 实施顺序
|
|
366
|
+
|
|
367
|
+
1. 新增 `src/aab-converter` 核心模块。
|
|
368
|
+
2. 新增必要的 `src/shared` 基础能力。
|
|
369
|
+
3. 新增 `aab-entry.ts` CLI 入口。
|
|
370
|
+
4. 新增测试。
|
|
371
|
+
5. 准备 `bundletool.jar`、Windows Node、Windows JRE。
|
|
372
|
+
6. 新增绿色版 zip 打包脚本。
|
|
373
|
+
7. 在 macOS 生成 zip。
|
|
374
|
+
8. 在 Windows 实机验收。
|
|
375
|
+
9. 补充用户使用说明和常见问题。
|
|
376
|
+
|
|
377
|
+
## 实现注意事项
|
|
378
|
+
|
|
379
|
+
- `.apks` 必须按 ZIP 结构流式读取,不能一次性读入内存。实际测试样本超过 2GB,一次性 `readFile` 会触发 Node 单 Buffer 限制。
|
|
380
|
+
- bundletool 命令日志必须脱敏 `--ks-pass` 和 `--key-pass`。
|
|
381
|
+
- macOS 本地验证时不能自动使用 `runtime/win-x64/jre/bin/java.exe`,应使用系统 `java` 或显式 `AAB2APK_JAVA_PATH`;Windows 绿色版运行时使用包内 `runtime/jre/bin/java.exe`。
|
|
382
|
+
- `test-assets/aab-converter/` 下的 AAB、JKS 和本地密钥说明 `.md` 只能用于本地验证,不能提交。
|
|
383
|
+
|
|
384
|
+
## 最终结论
|
|
385
|
+
|
|
386
|
+
第一版采用纯命令行绿色版:
|
|
387
|
+
|
|
388
|
+
```text
|
|
389
|
+
TypeScript CLI + Windows node.exe + Windows JRE + bundletool.jar
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
macOS 负责生成 zip,Windows 负责验收。AAB 转 APK 工具作为 `meet-sdk-tool` 工具集中的独立工具存在,不复用现有 `recipe / pipeline / integrate` 机制,只在必要时共用基础工具库。
|