swipium 1.0.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/LICENSE +21 -0
- package/README.md +295 -0
- package/dist/appMap/automationLink.js +74 -0
- package/dist/appMap/automationLink.js.map +1 -0
- package/dist/appMap/build.js +193 -0
- package/dist/appMap/build.js.map +1 -0
- package/dist/appMap/codeIndex.js +73 -0
- package/dist/appMap/codeIndex.js.map +1 -0
- package/dist/appMap/featureModel.js +83 -0
- package/dist/appMap/featureModel.js.map +1 -0
- package/dist/appMap/firstRunApply.js +131 -0
- package/dist/appMap/firstRunApply.js.map +1 -0
- package/dist/appMap/fsWalk.js +75 -0
- package/dist/appMap/fsWalk.js.map +1 -0
- package/dist/appMap/issues.js +227 -0
- package/dist/appMap/issues.js.map +1 -0
- package/dist/appMap/migrations.js +87 -0
- package/dist/appMap/migrations.js.map +1 -0
- package/dist/appMap/prelaunch.js +66 -0
- package/dist/appMap/prelaunch.js.map +1 -0
- package/dist/appMap/projectRegistry.js +70 -0
- package/dist/appMap/projectRegistry.js.map +1 -0
- package/dist/appMap/provenance.js +52 -0
- package/dist/appMap/provenance.js.map +1 -0
- package/dist/appMap/query.js +118 -0
- package/dist/appMap/query.js.map +1 -0
- package/dist/appMap/runtimeMerge.js +207 -0
- package/dist/appMap/runtimeMerge.js.map +1 -0
- package/dist/appMap/schema.js +65 -0
- package/dist/appMap/schema.js.map +1 -0
- package/dist/appMap/screenMatch.js +75 -0
- package/dist/appMap/screenMatch.js.map +1 -0
- package/dist/appMap/staticScan.js +614 -0
- package/dist/appMap/staticScan.js.map +1 -0
- package/dist/appMap/store.js +173 -0
- package/dist/appMap/store.js.map +1 -0
- package/dist/appMap/tsAstScan.js +184 -0
- package/dist/appMap/tsAstScan.js.map +1 -0
- package/dist/artifacts/bundletool.js +199 -0
- package/dist/artifacts/bundletool.js.map +1 -0
- package/dist/artifacts/resolve.js +388 -0
- package/dist/artifacts/resolve.js.map +1 -0
- package/dist/automationGen/appiumModel.js +129 -0
- package/dist/automationGen/appiumModel.js.map +1 -0
- package/dist/automationGen/ciEmitter.js +80 -0
- package/dist/automationGen/ciEmitter.js.map +1 -0
- package/dist/automationGen/jsEmitter.js +440 -0
- package/dist/automationGen/jsEmitter.js.map +1 -0
- package/dist/automationGen/packagePatch.js +56 -0
- package/dist/automationGen/packagePatch.js.map +1 -0
- package/dist/automationGen/projectProfile.js +317 -0
- package/dist/automationGen/projectProfile.js.map +1 -0
- package/dist/automationGen/pythonEmitter.js +386 -0
- package/dist/automationGen/pythonEmitter.js.map +1 -0
- package/dist/automationGen/readmeEmitter.js +66 -0
- package/dist/automationGen/readmeEmitter.js.map +1 -0
- package/dist/automationGen/suitePlan.js +94 -0
- package/dist/automationGen/suitePlan.js.map +1 -0
- package/dist/automationGen/validation.js +150 -0
- package/dist/automationGen/validation.js.map +1 -0
- package/dist/build/parseBuildLog.js +119 -0
- package/dist/build/parseBuildLog.js.map +1 -0
- package/dist/build/plan.js +150 -0
- package/dist/build/plan.js.map +1 -0
- package/dist/ci/preflight.js +85 -0
- package/dist/ci/preflight.js.map +1 -0
- package/dist/cli/init.js +105 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/scan.js +85 -0
- package/dist/cli/scan.js.map +1 -0
- package/dist/cli/suite.js +85 -0
- package/dist/cli/suite.js.map +1 -0
- package/dist/cli/verify.js +62 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/consent/consent.js +43 -0
- package/dist/consent/consent.js.map +1 -0
- package/dist/context/detect.js +156 -0
- package/dist/context/detect.js.map +1 -0
- package/dist/context/findApps.js +198 -0
- package/dist/context/findApps.js.map +1 -0
- package/dist/context/projectRoot.js +41 -0
- package/dist/context/projectRoot.js.map +1 -0
- package/dist/context/scan.js +167 -0
- package/dist/context/scan.js.map +1 -0
- package/dist/core/target.js +115 -0
- package/dist/core/target.js.map +1 -0
- package/dist/core/targetPlan.js +140 -0
- package/dist/core/targetPlan.js.map +1 -0
- package/dist/drivers/DirectDriver.js +228 -0
- package/dist/drivers/DirectDriver.js.map +1 -0
- package/dist/drivers/Driver.js +4 -0
- package/dist/drivers/Driver.js.map +1 -0
- package/dist/drivers/SimctlDriver.js +127 -0
- package/dist/drivers/SimctlDriver.js.map +1 -0
- package/dist/drivers/WdaDriver.js +250 -0
- package/dist/drivers/WdaDriver.js.map +1 -0
- package/dist/explore/candidates.js +93 -0
- package/dist/explore/candidates.js.map +1 -0
- package/dist/explore/graph.js +116 -0
- package/dist/explore/graph.js.map +1 -0
- package/dist/explore/memory.js +35 -0
- package/dist/explore/memory.js.map +1 -0
- package/dist/explore/planner.js +105 -0
- package/dist/explore/planner.js.map +1 -0
- package/dist/explore/policy.js +85 -0
- package/dist/explore/policy.js.map +1 -0
- package/dist/explore/runner.js +475 -0
- package/dist/explore/runner.js.map +1 -0
- package/dist/explore/signatures.js +35 -0
- package/dist/explore/signatures.js.map +1 -0
- package/dist/explore/suite.js +55 -0
- package/dist/explore/suite.js.map +1 -0
- package/dist/featureTesting/executionBootstrap.js +140 -0
- package/dist/featureTesting/executionBootstrap.js.map +1 -0
- package/dist/firstRun/authStateMachine.js +83 -0
- package/dist/firstRun/authStateMachine.js.map +1 -0
- package/dist/firstRun/classifyScreen.js +201 -0
- package/dist/firstRun/classifyScreen.js.map +1 -0
- package/dist/firstRun/firstRunPlanner.js +207 -0
- package/dist/firstRun/firstRunPlanner.js.map +1 -0
- package/dist/firstRun/firstRunRunner.js +331 -0
- package/dist/firstRun/firstRunRunner.js.map +1 -0
- package/dist/firstRun/generatedDataPolicy.js +215 -0
- package/dist/firstRun/generatedDataPolicy.js.map +1 -0
- package/dist/firstRun/inputPlanner.js +67 -0
- package/dist/firstRun/inputPlanner.js.map +1 -0
- package/dist/firstRun/onboardingStateMachine.js +46 -0
- package/dist/firstRun/onboardingStateMachine.js.map +1 -0
- package/dist/firstRun/paywallPolicy.js +54 -0
- package/dist/firstRun/paywallPolicy.js.map +1 -0
- package/dist/firstRun/types.js +7 -0
- package/dist/firstRun/types.js.map +1 -0
- package/dist/fixtures/catalog.js +131 -0
- package/dist/fixtures/catalog.js.map +1 -0
- package/dist/flows/discover.js +18 -0
- package/dist/flows/discover.js.map +1 -0
- package/dist/flows/generate.js +211 -0
- package/dist/flows/generate.js.map +1 -0
- package/dist/flows/lint.js +97 -0
- package/dist/flows/lint.js.map +1 -0
- package/dist/flows/pack.js +68 -0
- package/dist/flows/pack.js.map +1 -0
- package/dist/flows/run.js +738 -0
- package/dist/flows/run.js.map +1 -0
- package/dist/flows/schema.js +240 -0
- package/dist/flows/schema.js.map +1 -0
- package/dist/flows/seedExec.js +108 -0
- package/dist/flows/seedExec.js.map +1 -0
- package/dist/flows/templates.js +155 -0
- package/dist/flows/templates.js.map +1 -0
- package/dist/flows/waitGuards.js +12 -0
- package/dist/flows/waitGuards.js.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/ios/signing.js +182 -0
- package/dist/ios/signing.js.map +1 -0
- package/dist/issues/classify.js +186 -0
- package/dist/issues/classify.js.map +1 -0
- package/dist/issues/fingerprint.js +130 -0
- package/dist/issues/fingerprint.js.map +1 -0
- package/dist/issues/index.js +240 -0
- package/dist/issues/index.js.map +1 -0
- package/dist/issues/metrics.js +155 -0
- package/dist/issues/metrics.js.map +1 -0
- package/dist/issues/recurrence.js +193 -0
- package/dist/issues/recurrence.js.map +1 -0
- package/dist/issues/report.js +110 -0
- package/dist/issues/report.js.map +1 -0
- package/dist/issues/reportBridge.js +119 -0
- package/dist/issues/reportBridge.js.map +1 -0
- package/dist/issues/schema.js +90 -0
- package/dist/issues/schema.js.map +1 -0
- package/dist/issues/sourceRevision.js +108 -0
- package/dist/issues/sourceRevision.js.map +1 -0
- package/dist/issues/store.js +155 -0
- package/dist/issues/store.js.map +1 -0
- package/dist/lib/android.js +278 -0
- package/dist/lib/android.js.map +1 -0
- package/dist/lib/commandTemplate.js +55 -0
- package/dist/lib/commandTemplate.js.map +1 -0
- package/dist/lib/coordSpace.js +23 -0
- package/dist/lib/coordSpace.js.map +1 -0
- package/dist/lib/device.js +87 -0
- package/dist/lib/device.js.map +1 -0
- package/dist/lib/gitignore.js +22 -0
- package/dist/lib/gitignore.js.map +1 -0
- package/dist/lib/image.js +97 -0
- package/dist/lib/image.js.map +1 -0
- package/dist/lib/logger.js +8 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/metroState.js +45 -0
- package/dist/lib/metroState.js.map +1 -0
- package/dist/lib/needsInput.js +201 -0
- package/dist/lib/needsInput.js.map +1 -0
- package/dist/lib/png.js +103 -0
- package/dist/lib/png.js.map +1 -0
- package/dist/lib/redact.js +21 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/result.js +87 -0
- package/dist/lib/result.js.map +1 -0
- package/dist/lib/schemaHash.js +65 -0
- package/dist/lib/schemaHash.js.map +1 -0
- package/dist/lib/sensitive.js +13 -0
- package/dist/lib/sensitive.js.map +1 -0
- package/dist/lib/simctl.js +149 -0
- package/dist/lib/simctl.js.map +1 -0
- package/dist/lib/spawn.js +144 -0
- package/dist/lib/spawn.js.map +1 -0
- package/dist/lib/wda.js +347 -0
- package/dist/lib/wda.js.map +1 -0
- package/dist/lib/wdaConfig.js +69 -0
- package/dist/lib/wdaConfig.js.map +1 -0
- package/dist/lib/wdaTune.js +58 -0
- package/dist/lib/wdaTune.js.map +1 -0
- package/dist/oracle/auth.js +22 -0
- package/dist/oracle/auth.js.map +1 -0
- package/dist/oracle/failures.js +193 -0
- package/dist/oracle/failures.js.map +1 -0
- package/dist/oracle/health.js +123 -0
- package/dist/oracle/health.js.map +1 -0
- package/dist/oracle/record.js +36 -0
- package/dist/oracle/record.js.map +1 -0
- package/dist/orchestration/envelope.js +52 -0
- package/dist/orchestration/envelope.js.map +1 -0
- package/dist/orchestration/goal.js +98 -0
- package/dist/orchestration/goal.js.map +1 -0
- package/dist/plan/plan.js +124 -0
- package/dist/plan/plan.js.map +1 -0
- package/dist/prompts/index.js +63 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/report/artifactManifest.js +44 -0
- package/dist/report/artifactManifest.js.map +1 -0
- package/dist/report/coverage.js +60 -0
- package/dist/report/coverage.js.map +1 -0
- package/dist/report/evidence.js +84 -0
- package/dist/report/evidence.js.map +1 -0
- package/dist/report/export.js +447 -0
- package/dist/report/export.js.map +1 -0
- package/dist/report/flake.js +61 -0
- package/dist/report/flake.js.map +1 -0
- package/dist/report/history.js +564 -0
- package/dist/report/history.js.map +1 -0
- package/dist/report/policy.js +98 -0
- package/dist/report/policy.js.map +1 -0
- package/dist/report/qaLevel.js +96 -0
- package/dist/report/qaLevel.js.map +1 -0
- package/dist/report/readiness.js +213 -0
- package/dist/report/readiness.js.map +1 -0
- package/dist/report/summary.js +42 -0
- package/dist/report/summary.js.map +1 -0
- package/dist/report/testCatalog.js +93 -0
- package/dist/report/testCatalog.js.map +1 -0
- package/dist/report/timing.js +37 -0
- package/dist/report/timing.js.map +1 -0
- package/dist/server.js +180 -0
- package/dist/server.js.map +1 -0
- package/dist/services/automationGenerate.js +60 -0
- package/dist/services/automationGenerate.js.map +1 -0
- package/dist/services/build.js +66 -0
- package/dist/services/build.js.map +1 -0
- package/dist/services/preflight.js +51 -0
- package/dist/services/preflight.js.map +1 -0
- package/dist/services/prepareAndroid.js +183 -0
- package/dist/services/prepareAndroid.js.map +1 -0
- package/dist/services/prepareIos.js +162 -0
- package/dist/services/prepareIos.js.map +1 -0
- package/dist/services/report.js +537 -0
- package/dist/services/report.js.map +1 -0
- package/dist/services/smoke.js +120 -0
- package/dist/services/smoke.js.map +1 -0
- package/dist/services/suiteGenerate.js +123 -0
- package/dist/services/suiteGenerate.js.map +1 -0
- package/dist/services/testSuiteKnowledge.js +150 -0
- package/dist/services/testSuiteKnowledge.js.map +1 -0
- package/dist/session/attach.js +47 -0
- package/dist/session/attach.js.map +1 -0
- package/dist/session/progress.js +56 -0
- package/dist/session/progress.js.map +1 -0
- package/dist/session/store.js +329 -0
- package/dist/session/store.js.map +1 -0
- package/dist/snapshot/overlays.js +132 -0
- package/dist/snapshot/overlays.js.map +1 -0
- package/dist/snapshot/parse.js +204 -0
- package/dist/snapshot/parse.js.map +1 -0
- package/dist/snapshot/present.js +12 -0
- package/dist/snapshot/present.js.map +1 -0
- package/dist/snapshot/settle.js +36 -0
- package/dist/snapshot/settle.js.map +1 -0
- package/dist/state/profile.js +318 -0
- package/dist/state/profile.js.map +1 -0
- package/dist/suite/compile.js +176 -0
- package/dist/suite/compile.js.map +1 -0
- package/dist/suite/lint.js +45 -0
- package/dist/suite/lint.js.map +1 -0
- package/dist/suite/pom.js +285 -0
- package/dist/suite/pom.js.map +1 -0
- package/dist/suite/testcase.js +87 -0
- package/dist/suite/testcase.js.map +1 -0
- package/dist/testSuite/generator.js +222 -0
- package/dist/testSuite/generator.js.map +1 -0
- package/dist/testSuite/history.js +44 -0
- package/dist/testSuite/history.js.map +1 -0
- package/dist/testSuite/issueLinks.js +96 -0
- package/dist/testSuite/issueLinks.js.map +1 -0
- package/dist/testSuite/merge.js +190 -0
- package/dist/testSuite/merge.js.map +1 -0
- package/dist/testSuite/schema.js +86 -0
- package/dist/testSuite/schema.js.map +1 -0
- package/dist/testSuite/store.js +116 -0
- package/dist/testSuite/store.js.map +1 -0
- package/dist/testSuite/traceability.js +55 -0
- package/dist/testSuite/traceability.js.map +1 -0
- package/dist/tools/act.js +457 -0
- package/dist/tools/act.js.map +1 -0
- package/dist/tools/agent.js +225 -0
- package/dist/tools/agent.js.map +1 -0
- package/dist/tools/appMap.js +317 -0
- package/dist/tools/appMap.js.map +1 -0
- package/dist/tools/assertVisual.js +74 -0
- package/dist/tools/assertVisual.js.map +1 -0
- package/dist/tools/automationGenerate.js +394 -0
- package/dist/tools/automationGenerate.js.map +1 -0
- package/dist/tools/capabilities.js +114 -0
- package/dist/tools/capabilities.js.map +1 -0
- package/dist/tools/clearOverlay.js +150 -0
- package/dist/tools/clearOverlay.js.map +1 -0
- package/dist/tools/detectContext.js +41 -0
- package/dist/tools/detectContext.js.map +1 -0
- package/dist/tools/doctor.js +116 -0
- package/dist/tools/doctor.js.map +1 -0
- package/dist/tools/explore.js +289 -0
- package/dist/tools/explore.js.map +1 -0
- package/dist/tools/firstRun.js +136 -0
- package/dist/tools/firstRun.js.map +1 -0
- package/dist/tools/flow.js +331 -0
- package/dist/tools/flow.js.map +1 -0
- package/dist/tools/flowGenerate.js +55 -0
- package/dist/tools/flowGenerate.js.map +1 -0
- package/dist/tools/getArtifact.js +39 -0
- package/dist/tools/getArtifact.js.map +1 -0
- package/dist/tools/health.js +41 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/ios.js +492 -0
- package/dist/tools/ios.js.map +1 -0
- package/dist/tools/jobs.js +20 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/network.js +50 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/note.js +69 -0
- package/dist/tools/note.js.map +1 -0
- package/dist/tools/plan.js +49 -0
- package/dist/tools/plan.js.map +1 -0
- package/dist/tools/prepareIosTarget.js +99 -0
- package/dist/tools/prepareIosTarget.js.map +1 -0
- package/dist/tools/prepareTarget.js +257 -0
- package/dist/tools/prepareTarget.js.map +1 -0
- package/dist/tools/report.js +42 -0
- package/dist/tools/report.js.map +1 -0
- package/dist/tools/screenRecord.js +24 -0
- package/dist/tools/screenRecord.js.map +1 -0
- package/dist/tools/screenshot.js +63 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/smoke.js +39 -0
- package/dist/tools/smoke.js.map +1 -0
- package/dist/tools/snapshot.js +129 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/tools/startSession.js +169 -0
- package/dist/tools/startSession.js.map +1 -0
- package/dist/tools/state.js +87 -0
- package/dist/tools/state.js.map +1 -0
- package/dist/tools/suite.js +412 -0
- package/dist/tools/suite.js.map +1 -0
- package/dist/tools/testThis.js +774 -0
- package/dist/tools/testThis.js.map +1 -0
- package/dist/tools/wda.js +477 -0
- package/dist/tools/wda.js.map +1 -0
- package/dist/version.js +62 -0
- package/dist/version.js.map +1 -0
- package/dist/visual/ocr.js +72 -0
- package/dist/visual/ocr.js.map +1 -0
- package/dist/visual/provider.js +75 -0
- package/dist/visual/provider.js.map +1 -0
- package/docs/README.md +19 -0
- package/docs/assets/swipium-lockup-ink-on-light.png +0 -0
- package/docs/mcp-server.md +135 -0
- package/docs/tools.md +130 -0
- package/package.json +70 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// bundletool integration (roadmap §4.3 / hardening P0.2) — an .aab is not installable; it must be
|
|
2
|
+
// converted to a universal APK first. This module detects bundletool (a `bundletool` launcher on
|
|
3
|
+
// PATH, a `$BUNDLETOOL_JAR` run via java, or a jar in common locations), builds a universal APK
|
|
4
|
+
// set with the debug keystore, extracts universal.apk, and caches it under .swipium/artifacts/.
|
|
5
|
+
//
|
|
6
|
+
// Detection + command construction are pure/testable; execution is guarded behind tool presence.
|
|
7
|
+
import { existsSync, mkdirSync, readdirSync, statSync } from 'node:fs';
|
|
8
|
+
import { join, basename } from 'node:path';
|
|
9
|
+
import { homedir } from 'node:os';
|
|
10
|
+
import { which } from '../lib/android.js';
|
|
11
|
+
import { run } from '../lib/spawn.js';
|
|
12
|
+
const JAR_CANDIDATES = () => {
|
|
13
|
+
const home = homedir();
|
|
14
|
+
return [
|
|
15
|
+
process.env.BUNDLETOOL_JAR ?? '',
|
|
16
|
+
join(home, 'bundletool.jar'),
|
|
17
|
+
join(home, 'Downloads', 'bundletool.jar'),
|
|
18
|
+
'/usr/local/bin/bundletool.jar',
|
|
19
|
+
'/opt/homebrew/bin/bundletool.jar',
|
|
20
|
+
].filter(Boolean);
|
|
21
|
+
};
|
|
22
|
+
/** Find a usable bundletool launcher, or null if none is available. */
|
|
23
|
+
export async function findBundletool() {
|
|
24
|
+
if (await which('bundletool')) {
|
|
25
|
+
return { kind: 'bin', cmd: 'bundletool', prefix: [], describe: 'bundletool (PATH)' };
|
|
26
|
+
}
|
|
27
|
+
const hasJava = await which('java');
|
|
28
|
+
if (hasJava) {
|
|
29
|
+
for (const jar of JAR_CANDIDATES()) {
|
|
30
|
+
if (existsSync(jar))
|
|
31
|
+
return { kind: 'jar', cmd: 'java', prefix: ['-jar', jar], describe: `java -jar ${jar}` };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
/** Where the converted universal APK is cached for a given .aab. */
|
|
37
|
+
export function universalApkCachePath(projectRoot, aabPath) {
|
|
38
|
+
const base = basename(aabPath).replace(/\.aab$/i, '');
|
|
39
|
+
return join(projectRoot, '.swipium', 'artifacts', `${base}-universal.apk`);
|
|
40
|
+
}
|
|
41
|
+
/** The bundletool build-apks argv for a universal APK set (pure — for tests + logging). */
|
|
42
|
+
export function buildApksArgs(launcher, aabPath, apksOut) {
|
|
43
|
+
return [...launcher.prefix, 'build-apks', '--bundle', aabPath, '--output', apksOut, '--overwrite', '--mode', 'universal'];
|
|
44
|
+
}
|
|
45
|
+
/** PURE: signing args for build-apks (empty → debug keystore fallback). */
|
|
46
|
+
export function signingArgs(signing) {
|
|
47
|
+
if (!signing)
|
|
48
|
+
return [];
|
|
49
|
+
const out = ['--ks', signing.ks, '--ks-key-alias', signing.ksKeyAlias];
|
|
50
|
+
if (signing.ksPass)
|
|
51
|
+
out.push('--ks-pass', signing.ksPass);
|
|
52
|
+
if (signing.keyPass)
|
|
53
|
+
out.push('--key-pass', signing.keyPass);
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
/** PURE: build-apks argv for a DEVICE-SPECIFIC APK set (--connected-device), optionally targeting one serial + signing. */
|
|
57
|
+
export function buildApksConnectedArgs(launcher, aabPath, apksOut, opts = {}) {
|
|
58
|
+
const args = [...launcher.prefix, 'build-apks', '--bundle', aabPath, '--output', apksOut, '--overwrite', '--connected-device'];
|
|
59
|
+
if (opts.deviceId)
|
|
60
|
+
args.push('--device-id', opts.deviceId);
|
|
61
|
+
args.push(...signingArgs(opts.signing));
|
|
62
|
+
return args;
|
|
63
|
+
}
|
|
64
|
+
/** PURE: install-apks argv for pushing a device-specific APK set to a connected device. */
|
|
65
|
+
export function installApksArgs(launcher, apksPath, opts = {}) {
|
|
66
|
+
const args = [...launcher.prefix, 'install-apks', '--apks', apksPath];
|
|
67
|
+
if (opts.deviceId)
|
|
68
|
+
args.push('--device-id', opts.deviceId);
|
|
69
|
+
return args;
|
|
70
|
+
}
|
|
71
|
+
/** PURE: classify a bundletool stderr/stdout for a given phase into a typed blocker. */
|
|
72
|
+
export function classifyBundletoolError(output, phase) {
|
|
73
|
+
if (/keystore|jarsigner|failed to (?:read|load) key|SigningConfig|password was incorrect|key.*alias/i.test(output))
|
|
74
|
+
return 'ANDROID_SIGNING_FAILED';
|
|
75
|
+
if (phase === 'install') {
|
|
76
|
+
if (/INSTALL_FAILED_UPDATE_INCOMPATIBLE|signatures do not match|INCONSISTENT_CERTIFICATES/i.test(output))
|
|
77
|
+
return 'ANDROID_SIGNATURE_CONFLICT';
|
|
78
|
+
if (/INSTALL_FAILED_OLDER_SDK|INSTALL_FAILED_VERSION_DOWNGRADE/i.test(output))
|
|
79
|
+
return 'ANDROID_MIN_SDK_INCOMPATIBLE';
|
|
80
|
+
if (/INSTALL_FAILED_NO_MATCHING_ABIS/i.test(output))
|
|
81
|
+
return 'APK_ARCH_INCOMPATIBLE';
|
|
82
|
+
return 'AAB_INSTALL_FAILED';
|
|
83
|
+
}
|
|
84
|
+
if (/No connected (?:Android )?device|Unable to connect to (?:adb|device)|connected device/i.test(output))
|
|
85
|
+
return 'AAB_DEVICE_SPEC_FAILED';
|
|
86
|
+
return 'AAB_BUILD_APKS_FAILED';
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Build a DEVICE-SPECIFIC APK set for a connected device and (optionally) install it via
|
|
90
|
+
* bundletool install-apks. This is the first-class .aab path for a real run (vs the universal
|
|
91
|
+
* APK fallback in convertAabToApk). Returns typed blockers + the combined log so the caller can
|
|
92
|
+
* persist it as an artifact. Debug keystore is the default when no release signing is supplied.
|
|
93
|
+
*/
|
|
94
|
+
export async function buildAndInstallApkSet(aabPath, projectRoot, opts = {}) {
|
|
95
|
+
const launcher = await findBundletool();
|
|
96
|
+
if (!launcher) {
|
|
97
|
+
return { ok: false, logText: '', failureCode: 'BUNDLETOOL_MISSING', error: 'bundletool not found (install it, set $BUNDLETOOL_JAR, or build an APK directly).' };
|
|
98
|
+
}
|
|
99
|
+
const base = basename(aabPath).replace(/\.aab$/i, '');
|
|
100
|
+
const apksOut = join(projectRoot, '.swipium', 'artifacts', `${base}-${opts.deviceId ? sanitize(opts.deviceId) : 'device'}.apks`);
|
|
101
|
+
mkdirSync(join(projectRoot, '.swipium', 'artifacts'), { recursive: true });
|
|
102
|
+
const timeoutMs = opts.timeoutMs ?? 5 * 60_000;
|
|
103
|
+
let logText = '';
|
|
104
|
+
if (!opts.force && existsSync(apksOut)) {
|
|
105
|
+
try {
|
|
106
|
+
if (statSync(apksOut).mtimeMs >= statSync(aabPath).mtimeMs && !opts.install) {
|
|
107
|
+
return { ok: true, apksPath: apksOut, logText: 'using cached device APK set\n', installed: false };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch { /* rebuild */ }
|
|
111
|
+
}
|
|
112
|
+
const buildArgs = buildApksConnectedArgs(launcher, aabPath, apksOut, { deviceId: opts.deviceId, signing: opts.signing });
|
|
113
|
+
const buildCommand = `${launcher.cmd} ${buildArgs.join(' ')}`;
|
|
114
|
+
logText += `=== build-apks (connected device) ===\n${buildCommand}\n`;
|
|
115
|
+
const built = await run(launcher.cmd, buildArgs, { signal: opts.signal, timeoutMs });
|
|
116
|
+
logText += built.stdout + built.stderr + '\n';
|
|
117
|
+
if (built.code !== 0) {
|
|
118
|
+
return { ok: false, apksPath: existsSync(apksOut) ? apksOut : undefined, logText, buildCommand, failureCode: classifyBundletoolError(built.stdout + built.stderr, 'build'), error: built.stderr.trim() || built.stdout.trim() || `bundletool build-apks exited ${built.code}` };
|
|
119
|
+
}
|
|
120
|
+
if (!opts.install) {
|
|
121
|
+
return { ok: true, apksPath: apksOut, logText, buildCommand, installed: false };
|
|
122
|
+
}
|
|
123
|
+
const installArgs = installApksArgs(launcher, apksOut, { deviceId: opts.deviceId });
|
|
124
|
+
const installCommand = `${launcher.cmd} ${installArgs.join(' ')}`;
|
|
125
|
+
logText += `=== install-apks ===\n${installCommand}\n`;
|
|
126
|
+
const installed = await run(launcher.cmd, installArgs, { signal: opts.signal, timeoutMs });
|
|
127
|
+
logText += installed.stdout + installed.stderr + '\n';
|
|
128
|
+
if (installed.code !== 0) {
|
|
129
|
+
return { ok: false, apksPath: apksOut, logText, buildCommand, installCommand, failureCode: classifyBundletoolError(installed.stdout + installed.stderr, 'install'), error: installed.stderr.trim() || installed.stdout.trim() || `bundletool install-apks exited ${installed.code}` };
|
|
130
|
+
}
|
|
131
|
+
return { ok: true, apksPath: apksOut, logText, buildCommand, installCommand, installed: true };
|
|
132
|
+
}
|
|
133
|
+
function sanitize(s) {
|
|
134
|
+
return s.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Convert an .aab to an installable universal .apk, caching the result. Returns a typed blocker
|
|
138
|
+
* (AAB_NEEDS_BUNDLETOOL / AAB_BUILD_APKS_FAILED) instead of throwing, so callers can surface it.
|
|
139
|
+
*/
|
|
140
|
+
export async function convertAabToApk(aabPath, projectRoot, opts = {}) {
|
|
141
|
+
const apkPath = universalApkCachePath(projectRoot, aabPath);
|
|
142
|
+
// Cache hit: a fresh universal APK newer than the .aab.
|
|
143
|
+
if (!opts.force && existsSync(apkPath)) {
|
|
144
|
+
try {
|
|
145
|
+
if (statSync(apkPath).mtimeMs >= statSync(aabPath).mtimeMs)
|
|
146
|
+
return { ok: true, apkPath, fromCache: true };
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
/* fall through to rebuild */
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const launcher = await findBundletool();
|
|
153
|
+
if (!launcher) {
|
|
154
|
+
return { ok: false, failureCode: 'AAB_NEEDS_BUNDLETOOL', error: 'bundletool not found (install it, set $BUNDLETOOL_JAR, or build an APK directly).' };
|
|
155
|
+
}
|
|
156
|
+
mkdirSync(join(projectRoot, '.swipium', 'artifacts'), { recursive: true });
|
|
157
|
+
const apksOut = apkPath.replace(/\.apk$/, '.apks');
|
|
158
|
+
const args = buildApksArgs(launcher, aabPath, apksOut);
|
|
159
|
+
const command = `${launcher.cmd} ${args.join(' ')}`;
|
|
160
|
+
const timeoutMs = opts.timeoutMs ?? 5 * 60_000;
|
|
161
|
+
const built = await run(launcher.cmd, args, { signal: opts.signal, timeoutMs });
|
|
162
|
+
if (built.code !== 0) {
|
|
163
|
+
return { ok: false, failureCode: 'AAB_BUILD_APKS_FAILED', error: built.stderr.trim() || built.stdout.trim() || `bundletool exited ${built.code}`, command };
|
|
164
|
+
}
|
|
165
|
+
// The .apks is a zip containing universal.apk — extract it (prefer `unzip`, else bundletool can't).
|
|
166
|
+
const extracted = await extractUniversalApk(apksOut, apkPath, opts.signal);
|
|
167
|
+
if (!extracted) {
|
|
168
|
+
return { ok: false, failureCode: 'AAB_BUILD_APKS_FAILED', error: 'built .apks but could not extract universal.apk (need `unzip` on PATH).', command, apksPath: apksOut };
|
|
169
|
+
}
|
|
170
|
+
return { ok: true, apkPath, apksPath: apksOut, command };
|
|
171
|
+
}
|
|
172
|
+
/** Extract universal.apk from a bundletool .apks zip into `outApk`. Returns success. */
|
|
173
|
+
async function extractUniversalApk(apksPath, outApk, signal) {
|
|
174
|
+
if (!(await which('unzip')))
|
|
175
|
+
return false;
|
|
176
|
+
const dir = join(outApk, '..');
|
|
177
|
+
// unzip the universal apk (named universal.apk inside the .apks) into the artifacts dir.
|
|
178
|
+
const r = await run('unzip', ['-o', '-j', apksPath, 'universal.apk', '-d', dir], { signal, timeoutMs: 60_000 });
|
|
179
|
+
if (r.code !== 0)
|
|
180
|
+
return false;
|
|
181
|
+
const produced = join(dir, 'universal.apk');
|
|
182
|
+
if (!existsSync(produced)) {
|
|
183
|
+
// Some bundletool versions nest it; find any .apk and rename.
|
|
184
|
+
const any = readdirSync(dir).find((f) => f.toLowerCase().endsWith('.apk') && f.includes('universal'));
|
|
185
|
+
if (!any)
|
|
186
|
+
return false;
|
|
187
|
+
return existsSync(join(dir, any));
|
|
188
|
+
}
|
|
189
|
+
// Rename universal.apk → the cache name.
|
|
190
|
+
const { renameSync } = await import('node:fs');
|
|
191
|
+
try {
|
|
192
|
+
renameSync(produced, outApk);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return existsSync(produced);
|
|
196
|
+
}
|
|
197
|
+
return existsSync(outApk);
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=bundletool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundletool.js","sourceRoot":"","sources":["../../src/artifacts/bundletool.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,iGAAiG;AACjG,gGAAgG;AAChG,gGAAgG;AAChG,EAAE;AACF,iGAAiG;AAEjG,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AActC,MAAM,cAAc,GAAG,GAAa,EAAE;IACpC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,OAAO;QACL,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE;QAChC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC;QAC5B,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,gBAAgB,CAAC;QACzC,+BAA+B;QAC/B,kCAAkC;KACnC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACpB,CAAC,CAAC;AAEF,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,MAAM,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IACvF,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,EAAE,CAAC;YACnC,IAAI,UAAU,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,aAAa,GAAG,EAAE,EAAE,CAAC;QAChH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,qBAAqB,CAAC,WAAmB,EAAE,OAAe;IACxE,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,IAAI,gBAAgB,CAAC,CAAC;AAC7E,CAAC;AAYD,2FAA2F;AAC3F,MAAM,UAAU,aAAa,CAAC,QAA4B,EAAE,OAAe,EAAE,OAAe;IAC1F,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AAC5H,CAAC;AAUD,2EAA2E;AAC3E,MAAM,UAAU,WAAW,CAAC,OAAoB;IAC9C,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,gBAAgB,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACvE,IAAI,OAAO,CAAC,MAAM;QAAE,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,OAAO,CAAC,OAAO;QAAE,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,OAAO,GAAG,CAAC;AACb,CAAC;AAED,2HAA2H;AAC3H,MAAM,UAAU,sBAAsB,CAAC,QAA4B,EAAE,OAAe,EAAE,OAAe,EAAE,OAAoD,EAAE;IAC3J,MAAM,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,oBAAoB,CAAC,CAAC;IAC/H,IAAI,IAAI,CAAC,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3D,IAAI,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,eAAe,CAAC,QAA4B,EAAE,QAAgB,EAAE,OAA8B,EAAE;IAC9G,MAAM,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACtE,IAAI,IAAI,CAAC,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,uBAAuB,CAAC,MAAc,EAAE,KAA0B;IAChF,IAAI,iGAAiG,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,wBAAwB,CAAC;IACpJ,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,IAAI,uFAAuF,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,4BAA4B,CAAC;QAC9I,IAAI,4DAA4D,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,8BAA8B,CAAC;QACrH,IAAI,kCAAkC,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,uBAAuB,CAAC;QACpF,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IACD,IAAI,wFAAwF,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,wBAAwB,CAAC;IAC3I,OAAO,uBAAuB,CAAC;AACjC,CAAC;AAcD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAe,EACf,WAAmB,EACnB,OAAkI,EAAE;IAEpI,MAAM,QAAQ,GAAG,MAAM,cAAc,EAAE,CAAC;IACxC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,oBAAoB,EAAE,KAAK,EAAE,mFAAmF,EAAE,CAAC;IACnK,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,CAAC;IACjI,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,GAAG,MAAM,CAAC;IAC/C,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC5E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,+BAA+B,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YACrG,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,SAAS,GAAG,sBAAsB,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACzH,MAAM,YAAY,GAAG,GAAG,QAAQ,CAAC,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9D,OAAO,IAAI,0CAA0C,YAAY,IAAI,CAAC;IACtE,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACrF,OAAO,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;IAC9C,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,uBAAuB,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,gCAAgC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;IAClR,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAClF,CAAC;IAED,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpF,MAAM,cAAc,GAAG,GAAG,QAAQ,CAAC,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAClE,OAAO,IAAI,yBAAyB,cAAc,IAAI,CAAC;IACvD,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3F,OAAO,IAAI,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC;IACtD,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,uBAAuB,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,kCAAkC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;IACxR,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACjG,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAe,EACf,WAAmB,EACnB,OAAsE,EAAE;IAExE,MAAM,OAAO,GAAG,qBAAqB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC5D,wDAAwD;IACxD,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO;gBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAC5G,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;QAC/B,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,cAAc,EAAE,CAAC;IACxC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,KAAK,EAAE,mFAAmF,EAAE,CAAC;IACxJ,CAAC;IAED,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,GAAG,QAAQ,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,GAAG,MAAM,CAAC;IAE/C,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAChF,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,uBAAuB,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,qBAAqB,KAAK,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC;IAC9J,CAAC;IAED,oGAAoG;IACpG,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,uBAAuB,EAAE,KAAK,EAAE,yEAAyE,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC3K,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC3D,CAAC;AAED,wFAAwF;AACxF,KAAK,UAAU,mBAAmB,CAAC,QAAgB,EAAE,MAAc,EAAE,MAAoB;IACvF,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/B,yFAAyF;IACzF,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAChH,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAC5C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,8DAA8D;QAC9D,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;QACtG,IAAI,CAAC,GAAG;YAAE,OAAO,KAAK,CAAC;QACvB,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACpC,CAAC;IACD,yCAAyC;IACzC,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,CAAC;QACH,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
// Artifact Resolver V2 (roadmap §4) — find the build a developer actually has, wherever it
|
|
2
|
+
// lives. detectContext() only looked under the project root and apps/android|ios; most real
|
|
3
|
+
// builds land deep under Gradle/Flutter/Xcode output trees. This module does a bounded
|
|
4
|
+
// recursive walk of the project (plus opt-in DerivedData), classifies every .apk/.aab/.ipa/.app
|
|
5
|
+
// by platform + build type + installability, ranks them, and reports EXACTLY where it looked
|
|
6
|
+
// so a "no artifact" result is explainable rather than a dead end.
|
|
7
|
+
//
|
|
8
|
+
// Split for testability: the filesystem walk + the PURE ranking are separate. Tool-dependent
|
|
9
|
+
// enrichment (aapt2 app id / native ABIs, Info.plist bundle id) is an optional async pass so
|
|
10
|
+
// the core resolution works (and is unit-testable) without any Android/Xcode toolchain.
|
|
11
|
+
import { existsSync, readdirSync, statSync, readFileSync } from 'node:fs';
|
|
12
|
+
import { join, basename, sep } from 'node:path';
|
|
13
|
+
import { homedir } from 'node:os';
|
|
14
|
+
import { apkBadging } from '../lib/android.js';
|
|
15
|
+
import { parseSupportedPlatforms } from '../ios/signing.js';
|
|
16
|
+
const MIN_APK_BYTES = 1024 * 1024; // <1MB .apk is almost always a Git-LFS pointer
|
|
17
|
+
const SKIP_DIRS = new Set(['node_modules', '.git', '.swipium', 'Pods', '.gradle', 'DerivedData', '.expo']);
|
|
18
|
+
const ART_EXT = /\.(apk|aab|ipa|app)$/i;
|
|
19
|
+
function classifyBuildType(path) {
|
|
20
|
+
const p = path.toLowerCase();
|
|
21
|
+
if (/[/\\](release|prod|production)[/\\]/.test(p) || /-release\./.test(p))
|
|
22
|
+
return 'release';
|
|
23
|
+
if (/[/\\](debug|dev|development)[/\\]/.test(p) || /-debug\./.test(p))
|
|
24
|
+
return 'debug';
|
|
25
|
+
return 'unknown';
|
|
26
|
+
}
|
|
27
|
+
/** A .app under an iphonesimulator product dir is simulator-only; iphoneos is device-only. */
|
|
28
|
+
function iosAppInstallTargets(path) {
|
|
29
|
+
const p = path.toLowerCase();
|
|
30
|
+
if (p.includes('iphonesimulator') || p.includes('-simulator') || p.includes('/simulator/')) {
|
|
31
|
+
return { targets: ['ios-simulator'], warnings: [] };
|
|
32
|
+
}
|
|
33
|
+
if (p.includes('iphoneos') || p.includes('-iphoneos')) {
|
|
34
|
+
return { targets: ['ios-real'], warnings: ['device build (.app) — installing on a real device requires signing'] };
|
|
35
|
+
}
|
|
36
|
+
// Unknown destination — assume simulator (the common QA-first case) but warn.
|
|
37
|
+
return { targets: ['ios-simulator'], warnings: ['could not infer simulator vs device from path — assuming simulator'] };
|
|
38
|
+
}
|
|
39
|
+
function baseInstallTargets(type, path) {
|
|
40
|
+
switch (type) {
|
|
41
|
+
case 'apk':
|
|
42
|
+
return { targets: ['android-emulator', 'android-real'], warnings: [] };
|
|
43
|
+
case 'aab':
|
|
44
|
+
// An .aab is NOT directly installable. It must be converted to an APK set (bundletool).
|
|
45
|
+
// installableOn stays [] so it never flows into an install path as if it were ready.
|
|
46
|
+
return { targets: [], warnings: ['.aab is not directly installable — convert to an APK with bundletool first'], convertibleTo: ['apk'], requiresTool: 'bundletool' };
|
|
47
|
+
case 'ipa':
|
|
48
|
+
return { targets: ['ios-real'], warnings: ['.ipa installs only on a real device (with signing) — use a simulator .app for the simulator'] };
|
|
49
|
+
case 'app':
|
|
50
|
+
return iosAppInstallTargets(path);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function makeCandidate(path, type, source, projectRoot) {
|
|
54
|
+
let st;
|
|
55
|
+
try {
|
|
56
|
+
st = statSync(path);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const sizeBytes = type === 'app' ? dirSize(path) : st.size;
|
|
62
|
+
const warnings = [];
|
|
63
|
+
if (type === 'apk' && sizeBytes < MIN_APK_BYTES) {
|
|
64
|
+
warnings.push('APK <1MB — likely a Git-LFS pointer, not a real build');
|
|
65
|
+
}
|
|
66
|
+
const platform = type === 'ipa' || type === 'app' ? 'ios' : 'android';
|
|
67
|
+
const { targets, warnings: instWarn, convertibleTo, requiresTool } = baseInstallTargets(type, path);
|
|
68
|
+
return {
|
|
69
|
+
path,
|
|
70
|
+
type,
|
|
71
|
+
platform,
|
|
72
|
+
sizeBytes,
|
|
73
|
+
mtimeMs: st.mtimeMs,
|
|
74
|
+
buildType: classifyBuildType(path),
|
|
75
|
+
outsideRoot: !path.startsWith(projectRoot + sep) && path !== projectRoot,
|
|
76
|
+
source,
|
|
77
|
+
installableOn: targets,
|
|
78
|
+
convertibleTo,
|
|
79
|
+
requiresTool,
|
|
80
|
+
warnings: [...warnings, ...instWarn],
|
|
81
|
+
score: 0,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** Shallow size of a .app bundle's top-level files (cheap signal that it's a real bundle). */
|
|
85
|
+
function dirSize(dir) {
|
|
86
|
+
try {
|
|
87
|
+
let total = 0;
|
|
88
|
+
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
89
|
+
if (e.isFile()) {
|
|
90
|
+
try {
|
|
91
|
+
total += statSync(join(dir, e.name)).size;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
/* skip */
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return total;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function artifactType(name) {
|
|
105
|
+
const m = name.toLowerCase().match(/\.(apk|aab|ipa|app)$/);
|
|
106
|
+
return m ? m[1] : null;
|
|
107
|
+
}
|
|
108
|
+
/** Label the search location a hit came from, for the "exactly where I looked" report (§3.4). */
|
|
109
|
+
function sourceLabel(relDir, type) {
|
|
110
|
+
const r = relDir.toLowerCase();
|
|
111
|
+
if (r.includes('build/app/outputs/flutter-apk'))
|
|
112
|
+
return 'flutter apk output';
|
|
113
|
+
if (r.includes('outputs/bundle'))
|
|
114
|
+
return 'gradle aab output';
|
|
115
|
+
if (r.includes('outputs/apk'))
|
|
116
|
+
return 'gradle apk output';
|
|
117
|
+
if (r.includes('build/ios/iphonesimulator'))
|
|
118
|
+
return 'flutter/xcode simulator app output';
|
|
119
|
+
if (r.includes('deriveddata'))
|
|
120
|
+
return 'Xcode DerivedData';
|
|
121
|
+
if (r.includes('apps/android') || r.includes('apps/ios'))
|
|
122
|
+
return 'apps/ directory';
|
|
123
|
+
if (relDir === '' || relDir === '.')
|
|
124
|
+
return 'project root';
|
|
125
|
+
return `${type} under ${relDir || 'project'}`;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Bounded recursive walk collecting artifacts. Pure filesystem; no external tools. Records every
|
|
129
|
+
* directory it descends into so the caller can report exact search locations. `.app` is a
|
|
130
|
+
* directory — we record it as a hit and do NOT descend into it.
|
|
131
|
+
*/
|
|
132
|
+
function walk(root, projectRoot, maxDepth, out, searched, depth = 0) {
|
|
133
|
+
if (depth > maxDepth)
|
|
134
|
+
return;
|
|
135
|
+
let entries;
|
|
136
|
+
try {
|
|
137
|
+
entries = readdirSync(root, { withFileTypes: true });
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
searched.add(root);
|
|
143
|
+
for (const e of entries) {
|
|
144
|
+
const full = join(root, e.name);
|
|
145
|
+
const type = artifactType(e.name);
|
|
146
|
+
if (type === 'app' && e.isDirectory()) {
|
|
147
|
+
const c = makeCandidate(full, 'app', sourceLabel(root.slice(projectRoot.length + 1), 'app'), projectRoot);
|
|
148
|
+
if (c)
|
|
149
|
+
out.push(c);
|
|
150
|
+
continue; // don't descend into a .app
|
|
151
|
+
}
|
|
152
|
+
if (e.isDirectory()) {
|
|
153
|
+
if (SKIP_DIRS.has(e.name) || e.name.startsWith('.'))
|
|
154
|
+
continue;
|
|
155
|
+
walk(full, projectRoot, maxDepth, out, searched, depth + 1);
|
|
156
|
+
}
|
|
157
|
+
else if (type && type !== 'app') {
|
|
158
|
+
const c = makeCandidate(full, type, sourceLabel(root.slice(projectRoot.length + 1), type), projectRoot);
|
|
159
|
+
if (c)
|
|
160
|
+
out.push(c);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/** PURE: score + sort candidates against the requested options. Best first. */
|
|
165
|
+
export function rankCandidates(candidates, opts) {
|
|
166
|
+
const platformPref = opts.platform ?? 'any';
|
|
167
|
+
const buildPref = opts.buildType ?? 'any';
|
|
168
|
+
const newest = candidates.reduce((m, c) => Math.max(m, c.mtimeMs), 0);
|
|
169
|
+
const scored = candidates.map((c) => {
|
|
170
|
+
let score = 0;
|
|
171
|
+
// Directly-installable beats archive-only.
|
|
172
|
+
score += c.type === 'apk' || c.type === 'app' ? 40 : 10;
|
|
173
|
+
// Platform preference.
|
|
174
|
+
if (platformPref !== 'any')
|
|
175
|
+
score += c.platform === platformPref ? 30 : -100;
|
|
176
|
+
// Build-type preference (debug is the QA-first default when the caller says 'debug').
|
|
177
|
+
if (buildPref !== 'any' && c.buildType === buildPref)
|
|
178
|
+
score += 20;
|
|
179
|
+
if (buildPref !== 'any' && c.buildType !== 'unknown' && c.buildType !== buildPref)
|
|
180
|
+
score -= 10;
|
|
181
|
+
// Required install target.
|
|
182
|
+
if (opts.requireInstallableOn) {
|
|
183
|
+
score += c.installableOn.includes(opts.requireInstallableOn) ? 50 : -200;
|
|
184
|
+
}
|
|
185
|
+
// Inside the project root beats a stray download/DerivedData hit.
|
|
186
|
+
if (c.outsideRoot)
|
|
187
|
+
score -= 25;
|
|
188
|
+
// Lint-y / pointer warnings push a candidate down.
|
|
189
|
+
score -= c.warnings.length * 5;
|
|
190
|
+
// Recency: up to +20 for the newest, scaled.
|
|
191
|
+
if (newest > 0)
|
|
192
|
+
score += Math.round((c.mtimeMs / newest) * 20);
|
|
193
|
+
return { ...c, score };
|
|
194
|
+
});
|
|
195
|
+
return scored.sort((a, b) => b.score - a.score || b.mtimeMs - a.mtimeMs);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Enrich the top `limit` candidates with toolchain-derived facts (Android app id + native ABIs
|
|
199
|
+
* via aapt2; iOS bundle id from the .app Info.plist). Best-effort: silently leaves fields unset
|
|
200
|
+
* when the tool/file is unavailable. Mutates + returns the same array.
|
|
201
|
+
*/
|
|
202
|
+
export async function enrichCandidates(candidates, limit = 3) {
|
|
203
|
+
for (const c of candidates.slice(0, limit)) {
|
|
204
|
+
try {
|
|
205
|
+
if (c.type === 'apk') {
|
|
206
|
+
// One aapt2 call for all Android metadata (was two: packageId + ABIs).
|
|
207
|
+
const b = await apkBadging(c.path);
|
|
208
|
+
if (b) {
|
|
209
|
+
c.appId = b.packageId;
|
|
210
|
+
c.abis = b.abis;
|
|
211
|
+
c.versionName = b.versionName;
|
|
212
|
+
c.versionCode = b.versionCode;
|
|
213
|
+
c.minSdk = b.minSdk;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
else if (c.type === 'app') {
|
|
217
|
+
const meta = appInfoPlistMeta(c.path);
|
|
218
|
+
c.appId = meta.bundleId;
|
|
219
|
+
c.versionName = meta.versionName;
|
|
220
|
+
c.versionCode = meta.versionCode;
|
|
221
|
+
c.supportedPlatforms = meta.supportedPlatforms;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
/* enrichment is best-effort */
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return candidates;
|
|
229
|
+
}
|
|
230
|
+
/** Read identity + version + supported platforms from a .app's Info.plist (XML plists only). */
|
|
231
|
+
export function appInfoPlistMeta(appDir) {
|
|
232
|
+
const plist = join(appDir, 'Info.plist');
|
|
233
|
+
if (!existsSync(plist))
|
|
234
|
+
return { bundleId: null, versionName: null, versionCode: null, supportedPlatforms: [] };
|
|
235
|
+
try {
|
|
236
|
+
const raw = readFileSync(plist, 'utf8');
|
|
237
|
+
const str = (key) => raw.match(new RegExp(`<key>${key}</key>\\s*<string>([^<]+)</string>`))?.[1]?.trim() ?? null;
|
|
238
|
+
return {
|
|
239
|
+
bundleId: str('CFBundleIdentifier'),
|
|
240
|
+
versionName: str('CFBundleShortVersionString'),
|
|
241
|
+
versionCode: str('CFBundleVersion'),
|
|
242
|
+
supportedPlatforms: parseSupportedPlatforms(raw),
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
return { bundleId: null, versionName: null, versionCode: null, supportedPlatforms: [] };
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/** Read CFBundleIdentifier from a .app's Info.plist (XML plists only; binary plists are skipped). */
|
|
250
|
+
export function bundleIdFromApp(appDir) {
|
|
251
|
+
const plist = join(appDir, 'Info.plist');
|
|
252
|
+
if (!existsSync(plist))
|
|
253
|
+
return null;
|
|
254
|
+
try {
|
|
255
|
+
const raw = readFileSync(plist, 'utf8');
|
|
256
|
+
const m = raw.match(/<key>CFBundleIdentifier<\/key>\s*<string>([^<]+)<\/string>/);
|
|
257
|
+
return m ? m[1].trim() : null;
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** The list of locations Swipium WILL search, for the "where I looked" report even on a miss. */
|
|
264
|
+
export function plannedSearchLocations(projectRoot, allowOutsideRoot) {
|
|
265
|
+
const rel = [
|
|
266
|
+
'android/app/build/outputs/apk/**',
|
|
267
|
+
'android/app/build/outputs/bundle/**',
|
|
268
|
+
'app/build/outputs/**',
|
|
269
|
+
'build/app/outputs/flutter-apk/**',
|
|
270
|
+
'build/ios/iphonesimulator/**',
|
|
271
|
+
'ios/build/**',
|
|
272
|
+
'apps/android/**',
|
|
273
|
+
'apps/ios/**',
|
|
274
|
+
'<project root, recursive>',
|
|
275
|
+
].map((r) => join(projectRoot, r));
|
|
276
|
+
if (allowOutsideRoot)
|
|
277
|
+
rel.push(derivedDataDir());
|
|
278
|
+
return rel;
|
|
279
|
+
}
|
|
280
|
+
function derivedDataDir() {
|
|
281
|
+
return join(homedir(), 'Library', 'Developer', 'Xcode', 'DerivedData');
|
|
282
|
+
}
|
|
283
|
+
function validateExplicit(path, projectRoot) {
|
|
284
|
+
if (!existsSync(path))
|
|
285
|
+
return { error: `Artifact not found: ${path}`, code: 'NO_BUILD_ARTIFACT' };
|
|
286
|
+
const type = artifactType(path);
|
|
287
|
+
if (!type)
|
|
288
|
+
return { error: `Unsupported artifact type: ${basename(path)} (expected .apk/.aab/.ipa/.app)`, code: 'NO_BUILD_ARTIFACT' };
|
|
289
|
+
const c = makeCandidate(path, type, 'explicit path', projectRoot);
|
|
290
|
+
if (!c)
|
|
291
|
+
return { error: `Could not stat artifact: ${path}`, code: 'NO_BUILD_ARTIFACT' };
|
|
292
|
+
return c;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Resolve the best installable artifact for the requested options. Side effects limited to
|
|
296
|
+
* filesystem reads + (when enriching) aapt2/Info.plist; never installs or builds.
|
|
297
|
+
*/
|
|
298
|
+
export async function resolveArtifact(opts, enrich = true) {
|
|
299
|
+
const { projectRoot } = opts;
|
|
300
|
+
const maxDepth = opts.maxDepth ?? 7;
|
|
301
|
+
const warnings = [];
|
|
302
|
+
// Explicit path short-circuit (still classified + validated).
|
|
303
|
+
if (opts.explicitPath && opts.explicitPath.trim()) {
|
|
304
|
+
const v = validateExplicit(opts.explicitPath.trim(), projectRoot);
|
|
305
|
+
if ('error' in v) {
|
|
306
|
+
return { candidates: [], best: null, newest: null, searchedLocations: [opts.explicitPath.trim()], warnings: [v.error], failureCode: v.code };
|
|
307
|
+
}
|
|
308
|
+
const ranked = rankCandidates([v], opts);
|
|
309
|
+
if (enrich)
|
|
310
|
+
await enrichCandidates(ranked, 1);
|
|
311
|
+
return { candidates: ranked, best: ranked[0], newest: ranked[0], searchedLocations: ['explicit: ' + opts.explicitPath.trim()], warnings: ranked[0].warnings };
|
|
312
|
+
}
|
|
313
|
+
const found = [];
|
|
314
|
+
const searched = new Set();
|
|
315
|
+
walk(projectRoot, projectRoot, maxDepth, found, searched);
|
|
316
|
+
// Opt-in: scan Xcode DerivedData (always outside the project root).
|
|
317
|
+
if (opts.allowOutsideRoot && (opts.platform === 'ios' || opts.platform === 'any' || opts.platform == null)) {
|
|
318
|
+
const dd = derivedDataDir();
|
|
319
|
+
if (existsSync(dd))
|
|
320
|
+
walk(dd, projectRoot, 4, found, searched);
|
|
321
|
+
}
|
|
322
|
+
const searchedLocations = [...searched].sort();
|
|
323
|
+
if (found.length === 0) {
|
|
324
|
+
return {
|
|
325
|
+
candidates: [],
|
|
326
|
+
best: null,
|
|
327
|
+
newest: null,
|
|
328
|
+
searchedLocations: plannedSearchLocations(projectRoot, opts.allowOutsideRoot),
|
|
329
|
+
warnings,
|
|
330
|
+
failureCode: 'NO_BUILD_ARTIFACT',
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
let ranked = rankCandidates(found, opts);
|
|
334
|
+
if (enrich)
|
|
335
|
+
await enrichCandidates(ranked);
|
|
336
|
+
// Re-filter by required target now that base installability is known.
|
|
337
|
+
if (opts.requireInstallableOn) {
|
|
338
|
+
const ok = ranked.filter((c) => c.installableOn.includes(opts.requireInstallableOn));
|
|
339
|
+
if (ok.length === 0) {
|
|
340
|
+
return {
|
|
341
|
+
candidates: ranked,
|
|
342
|
+
best: null,
|
|
343
|
+
newest: byNewest(ranked),
|
|
344
|
+
searchedLocations,
|
|
345
|
+
warnings: [`No artifact is installable on ${opts.requireInstallableOn}.`],
|
|
346
|
+
failureCode: failureForRequired(opts.requireInstallableOn, ranked),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
ranked = ok;
|
|
350
|
+
}
|
|
351
|
+
let best = ranked[0] ?? null;
|
|
352
|
+
// Outside-root gate (roadmap §10).
|
|
353
|
+
if (best && best.outsideRoot && !opts.allowOutsideRoot) {
|
|
354
|
+
const inside = ranked.find((c) => !c.outsideRoot);
|
|
355
|
+
if (inside) {
|
|
356
|
+
best = inside;
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
return { candidates: ranked, best: null, newest: byNewest(ranked), searchedLocations, warnings: [`Best artifact is outside the project root: ${ranked[0].path}`], failureCode: 'ARTIFACT_OUTSIDE_ROOT_REQUIRES_APPROVAL' };
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// Ambiguity: several same-platform installable candidates within a hair of each other.
|
|
363
|
+
const topPlat = best?.platform;
|
|
364
|
+
const close = ranked.filter((c) => c.platform === topPlat && best && Math.abs(c.score - best.score) <= 5);
|
|
365
|
+
if (close.length > 1)
|
|
366
|
+
warnings.push(`${close.length} similar ${topPlat} artifacts found — picked the newest/best; pass an explicit path to override.`);
|
|
367
|
+
// A lone .aab with no APK is a precise, common blocker.
|
|
368
|
+
if (best && best.type === 'aab' && !ranked.some((c) => c.type === 'apk')) {
|
|
369
|
+
warnings.push('Only a .aab is available; install needs bundletool conversion or a directly built APK.');
|
|
370
|
+
}
|
|
371
|
+
return { candidates: ranked, best, newest: byNewest(ranked), searchedLocations, warnings };
|
|
372
|
+
}
|
|
373
|
+
function byNewest(cands) {
|
|
374
|
+
return cands.length ? cands.reduce((m, c) => (c.mtimeMs > m.mtimeMs ? c : m)) : null;
|
|
375
|
+
}
|
|
376
|
+
function failureForRequired(target, ranked) {
|
|
377
|
+
if (target === 'ios-simulator') {
|
|
378
|
+
if (ranked.some((c) => c.type === 'ipa'))
|
|
379
|
+
return 'IPA_NEEDS_REAL_DEVICE';
|
|
380
|
+
return 'IOS_SIMULATOR_APP_MISSING';
|
|
381
|
+
}
|
|
382
|
+
if (target === 'android-emulator' || target === 'android-real') {
|
|
383
|
+
if (ranked.some((c) => c.type === 'aab') && !ranked.some((c) => c.type === 'apk'))
|
|
384
|
+
return 'AAB_NEEDS_BUNDLETOOL';
|
|
385
|
+
}
|
|
386
|
+
return 'NO_BUILD_ARTIFACT';
|
|
387
|
+
}
|
|
388
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/artifacts/resolve.ts"],"names":[],"mappings":"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"}
|