local-expo-build 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/LICENSE +21 -0
  3. package/README.md +372 -0
  4. package/bin/local-expo-build.js +2 -0
  5. package/dist/cli.js +33 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/build.js +121 -0
  8. package/dist/commands/build.js.map +1 -0
  9. package/dist/commands/doctor.js +606 -0
  10. package/dist/commands/doctor.js.map +1 -0
  11. package/dist/commands/init.js +125 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/keystore.js +47 -0
  14. package/dist/commands/keystore.js.map +1 -0
  15. package/dist/core/bumpVersion.js +70 -0
  16. package/dist/core/bumpVersion.js.map +1 -0
  17. package/dist/core/easLink.js +64 -0
  18. package/dist/core/easLink.js.map +1 -0
  19. package/dist/core/expoConfig.js +71 -0
  20. package/dist/core/expoConfig.js.map +1 -0
  21. package/dist/core/gradleRun.js +31 -0
  22. package/dist/core/gradleRun.js.map +1 -0
  23. package/dist/core/keystore/easFetch.js +109 -0
  24. package/dist/core/keystore/easFetch.js.map +1 -0
  25. package/dist/core/keystore/existing.js +135 -0
  26. package/dist/core/keystore/existing.js.map +1 -0
  27. package/dist/core/keystore/generate.js +72 -0
  28. package/dist/core/keystore/generate.js.map +1 -0
  29. package/dist/core/keystore/index.js +62 -0
  30. package/dist/core/keystore/index.js.map +1 -0
  31. package/dist/core/keystore/rehydrate.js +88 -0
  32. package/dist/core/keystore/rehydrate.js.map +1 -0
  33. package/dist/core/pinGradle.js +50 -0
  34. package/dist/core/pinGradle.js.map +1 -0
  35. package/dist/core/prebuild.js +16 -0
  36. package/dist/core/prebuild.js.map +1 -0
  37. package/dist/core/sdkDetect.js +26 -0
  38. package/dist/core/sdkDetect.js.map +1 -0
  39. package/dist/core/setupSigning.js +168 -0
  40. package/dist/core/setupSigning.js.map +1 -0
  41. package/dist/core/syncEasVersion.js +97 -0
  42. package/dist/core/syncEasVersion.js.map +1 -0
  43. package/dist/core/writeCredentialsJson.js +51 -0
  44. package/dist/core/writeCredentialsJson.js.map +1 -0
  45. package/dist/util/ctx.js +17 -0
  46. package/dist/util/ctx.js.map +1 -0
  47. package/dist/util/gitignore.js +23 -0
  48. package/dist/util/gitignore.js.map +1 -0
  49. package/dist/util/log.js +16 -0
  50. package/dist/util/log.js.map +1 -0
  51. package/package.json +64 -0
  52. package/templates/keystore.properties.example +4 -0
  53. package/templates/scripts/build.js +79 -0
  54. package/templates/scripts/bump-version.js +65 -0
  55. package/templates/scripts/pin-gradle.js +45 -0
  56. package/templates/scripts/print-artifact.js +36 -0
  57. package/templates/scripts/setup-signing.js +137 -0
  58. package/templates/scripts/sync-eas-version.js +59 -0
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.importExistingKeystore = importExistingKeystore;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const prompts_1 = require("@inquirer/prompts");
11
+ const setupSigning_1 = require("../setupSigning");
12
+ const log_1 = require("../../util/log");
13
+ /**
14
+ * Looks for an `android.keystore` block in `credentials.json` that describes
15
+ * the same physical `.jks` the user just pointed at. Returns the passwords +
16
+ * alias so we don't have to re-prompt the user for values they already have
17
+ * on disk.
18
+ *
19
+ * Two ways to match:
20
+ * - **same-path:** credentials.json's keystorePath resolves to the same
21
+ * absolute path the user provided.
22
+ * - **same-content:** the bytes match (sha1). Handles the common case where
23
+ * EAS dropped two copies (one at project root, one at credentials/android/)
24
+ * and the user pointed at either.
25
+ *
26
+ * Returns null when credentials.json is missing/incomplete OR the .jks it
27
+ * references doesn't match the one being imported — both are signals that
28
+ * the user may be importing a *different* keystore and the passwords should
29
+ * not be auto-reused.
30
+ */
31
+ function findCredentialsMatchForJks(cwd, absJksPath) {
32
+ const credPath = path_1.default.join(cwd, 'credentials.json');
33
+ if (!fs_1.default.existsSync(credPath))
34
+ return null;
35
+ let cred;
36
+ try {
37
+ cred = JSON.parse(fs_1.default.readFileSync(credPath, 'utf8'));
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ const ks = cred?.android?.keystore;
43
+ if (!ks ||
44
+ typeof ks.keystorePath !== 'string' ||
45
+ typeof ks.keystorePassword !== 'string' ||
46
+ typeof ks.keyAlias !== 'string' ||
47
+ typeof ks.keyPassword !== 'string') {
48
+ return null;
49
+ }
50
+ const credJksAbs = path_1.default.resolve(cwd, ks.keystorePath);
51
+ const build = (matchKind) => ({
52
+ keyAlias: ks.keyAlias,
53
+ storePassword: ks.keystorePassword,
54
+ keyPassword: ks.keyPassword,
55
+ matchKind,
56
+ });
57
+ if (path_1.default.resolve(credJksAbs) === path_1.default.resolve(absJksPath)) {
58
+ return build('same-path');
59
+ }
60
+ if (fs_1.default.existsSync(credJksAbs)) {
61
+ try {
62
+ if (sha1Of(credJksAbs) === sha1Of(absJksPath))
63
+ return build('same-content');
64
+ }
65
+ catch {
66
+ // hashing failed (permission, race) — fall through to prompts
67
+ }
68
+ }
69
+ return null;
70
+ }
71
+ function sha1Of(p) {
72
+ return crypto_1.default.createHash('sha1').update(fs_1.default.readFileSync(p)).digest('hex');
73
+ }
74
+ async function importExistingKeystore(cwd) {
75
+ const srcPath = await (0, prompts_1.input)({
76
+ message: 'Path to your existing .jks file (absolute or relative to project):',
77
+ validate: (v) => (fs_1.default.existsSync(path_1.default.resolve(cwd, v)) ? true : 'File does not exist'),
78
+ });
79
+ const absSrc = path_1.default.resolve(cwd, srcPath);
80
+ const filename = path_1.default.basename(absSrc);
81
+ const dest = path_1.default.join(cwd, 'android', 'app', filename);
82
+ const rootBackup = path_1.default.join(cwd, filename);
83
+ fs_1.default.mkdirSync(path_1.default.dirname(dest), { recursive: true });
84
+ if (path_1.default.resolve(dest) !== absSrc) {
85
+ fs_1.default.copyFileSync(absSrc, dest);
86
+ log_1.log.ok(`Copied keystore → ${path_1.default.relative(cwd, dest).replace(/\\/g, '/')}`);
87
+ }
88
+ // Belt-and-suspenders: keep a copy at project root so the .jks survives
89
+ // `expo prebuild --clean` wiping android/. setupSigning's recovery step
90
+ // looks here as a fallback. Gitignored via the `*.jks` entry.
91
+ if (path_1.default.resolve(rootBackup) !== absSrc) {
92
+ fs_1.default.copyFileSync(absSrc, rootBackup);
93
+ log_1.log.dim(`Backup → ${filename} (project root, gitignored)`);
94
+ }
95
+ let keyAlias;
96
+ let storePassword;
97
+ let keyPassword;
98
+ const credMatch = findCredentialsMatchForJks(cwd, absSrc);
99
+ if (credMatch) {
100
+ log_1.log.ok(`Found credentials.json matching this .jks (${credMatch.matchKind}) — alias=${credMatch.keyAlias}`);
101
+ const usePrefilled = await (0, prompts_1.confirm)({
102
+ message: 'Reuse the passwords + alias from credentials.json (skip prompts)?',
103
+ default: true,
104
+ });
105
+ if (usePrefilled) {
106
+ keyAlias = credMatch.keyAlias;
107
+ storePassword = credMatch.storePassword;
108
+ keyPassword = credMatch.keyPassword;
109
+ }
110
+ else {
111
+ keyAlias = await (0, prompts_1.input)({ message: 'Key alias:', default: credMatch.keyAlias });
112
+ storePassword = await (0, prompts_1.password)({ message: 'Keystore password:', mask: '*' });
113
+ keyPassword = await (0, prompts_1.password)({
114
+ message: 'Key password (often same as keystore password):',
115
+ mask: '*',
116
+ });
117
+ }
118
+ }
119
+ else {
120
+ keyAlias = await (0, prompts_1.input)({ message: 'Key alias:', default: 'release' });
121
+ storePassword = await (0, prompts_1.password)({ message: 'Keystore password:', mask: '*' });
122
+ keyPassword = await (0, prompts_1.password)({
123
+ message: 'Key password (often same as keystore password):',
124
+ mask: '*',
125
+ });
126
+ }
127
+ (0, setupSigning_1.writeKeystoreProps)(cwd, {
128
+ storeFile: filename,
129
+ storePassword,
130
+ keyAlias,
131
+ keyPassword,
132
+ });
133
+ log_1.log.ok('keystore.properties written.');
134
+ }
135
+ //# sourceMappingURL=existing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"existing.js","sourceRoot":"","sources":["../../../src/core/keystore/existing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateKeystore = generateKeystore;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const execa_1 = require("execa");
10
+ const prompts_1 = require("@inquirer/prompts");
11
+ const setupSigning_1 = require("../setupSigning");
12
+ const log_1 = require("../../util/log");
13
+ async function generateKeystore(cwd) {
14
+ const filename = await (0, prompts_1.input)({ message: 'Keystore filename:', default: 'release.jks' });
15
+ const keyAlias = await (0, prompts_1.input)({ message: 'Key alias:', default: 'release' });
16
+ const storePassword = await (0, prompts_1.password)({
17
+ message: 'Keystore password (min 6 chars):',
18
+ mask: '*',
19
+ validate: (v) => (v.length >= 6 ? true : 'At least 6 characters'),
20
+ });
21
+ const keyPassword = await (0, prompts_1.password)({
22
+ message: 'Key password (leave same as keystore):',
23
+ mask: '*',
24
+ validate: (v) => (v.length >= 6 ? true : 'At least 6 characters'),
25
+ });
26
+ const cn = await (0, prompts_1.input)({ message: 'Your name (CN):', default: 'Release Signer' });
27
+ const org = await (0, prompts_1.input)({ message: 'Organization (O):', default: 'Unknown' });
28
+ const country = await (0, prompts_1.input)({ message: 'Country code (C, 2 letters):', default: 'US' });
29
+ const dname = `CN=${cn}, O=${org}, C=${country}`;
30
+ const destDir = path_1.default.join(cwd, 'android', 'app');
31
+ fs_1.default.mkdirSync(destDir, { recursive: true });
32
+ const destPath = path_1.default.join(destDir, filename);
33
+ if (fs_1.default.existsSync(destPath)) {
34
+ throw new Error(`Keystore already exists at ${destPath}. Delete it or choose a new name.`);
35
+ }
36
+ log_1.log.info(`Running keytool to generate ${destPath}...`);
37
+ await (0, execa_1.execa)('keytool', [
38
+ '-genkeypair',
39
+ '-v',
40
+ '-keystore',
41
+ destPath,
42
+ '-alias',
43
+ keyAlias,
44
+ '-keyalg',
45
+ 'RSA',
46
+ '-keysize',
47
+ '2048',
48
+ '-validity',
49
+ '10000',
50
+ '-storepass',
51
+ storePassword,
52
+ '-keypass',
53
+ keyPassword,
54
+ '-dname',
55
+ dname,
56
+ ], { stdio: 'inherit' });
57
+ // Belt-and-suspenders: keep a copy at project root so the .jks survives
58
+ // `expo prebuild --clean` wiping android/. setupSigning's recovery step
59
+ // looks here as a fallback. Gitignored via the `*.jks` entry.
60
+ const rootBackup = path_1.default.join(cwd, filename);
61
+ fs_1.default.copyFileSync(destPath, rootBackup);
62
+ log_1.log.dim(`Backup → ${filename} (project root, gitignored)`);
63
+ (0, setupSigning_1.writeKeystoreProps)(cwd, {
64
+ storeFile: filename,
65
+ storePassword,
66
+ keyAlias,
67
+ keyPassword,
68
+ });
69
+ log_1.log.ok(`Keystore generated and keystore.properties written.`);
70
+ log_1.log.warn(`BACK UP ${destPath} AND YOUR PASSWORDS off-machine. Losing them means you cannot ship updates to your app.`);
71
+ }
72
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/core/keystore/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureKeystore = ensureKeystore;
4
+ const prompts_1 = require("@inquirer/prompts");
5
+ const setupSigning_1 = require("../setupSigning");
6
+ const writeCredentialsJson_1 = require("../writeCredentialsJson");
7
+ const existing_1 = require("./existing");
8
+ const generate_1 = require("./generate");
9
+ const easFetch_1 = require("./easFetch");
10
+ const rehydrate_1 = require("./rehydrate");
11
+ const gitignore_1 = require("../../util/gitignore");
12
+ const log_1 = require("../../util/log");
13
+ async function ensureKeystore(cwd, forceProvider, opts = {}) {
14
+ if (!forceProvider) {
15
+ const existing = (0, setupSigning_1.readKeystoreProps)(cwd);
16
+ if (existing) {
17
+ log_1.log.ok(`keystore.properties already present (alias=${existing.keyAlias}) — skipping.`);
18
+ (0, gitignore_1.ensureGitignoreEntries)(cwd, ['keystore.properties', '*.jks', 'credentials.json']);
19
+ (0, writeCredentialsJson_1.writeCredentialsJson)(cwd, existing);
20
+ return;
21
+ }
22
+ }
23
+ const rehydrateAvailable = forceProvider === 'rehydrate' || !!(0, rehydrate_1.findRehydrateCandidate)(cwd);
24
+ const choices = [];
25
+ if (rehydrateAvailable) {
26
+ choices.push({
27
+ name: 'Rehydrate from credentials.json (recommended — no password re-entry)',
28
+ value: 'rehydrate',
29
+ });
30
+ }
31
+ choices.push({ name: 'Use an existing .jks file', value: 'existing' });
32
+ choices.push({ name: 'Generate a new keystore (keytool)', value: 'generate' });
33
+ choices.push({ name: 'Fetch from EAS credentials', value: 'eas' });
34
+ const provider = forceProvider ??
35
+ (await (0, prompts_1.select)({
36
+ message: 'How would you like to set up the Android signing keystore?',
37
+ choices,
38
+ }));
39
+ switch (provider) {
40
+ case 'rehydrate':
41
+ await (0, rehydrate_1.rehydrateFromCredentialsJson)(cwd, opts.rehydrate);
42
+ break;
43
+ case 'existing':
44
+ await (0, existing_1.importExistingKeystore)(cwd);
45
+ break;
46
+ case 'generate':
47
+ await (0, generate_1.generateKeystore)(cwd);
48
+ break;
49
+ case 'eas':
50
+ await (0, easFetch_1.fetchKeystoreFromEas)(cwd);
51
+ break;
52
+ }
53
+ (0, gitignore_1.ensureGitignoreEntries)(cwd, ['keystore.properties', '*.jks', 'credentials.json']);
54
+ // 'eas' provider only opens the EAS credentials menu; it does NOT populate
55
+ // keystore.properties (user must re-run `keystore import`). For 'existing'
56
+ // and 'generate', keystore.properties is now written — sync credentials.json.
57
+ const finalProps = (0, setupSigning_1.readKeystoreProps)(cwd);
58
+ if (finalProps) {
59
+ (0, writeCredentialsJson_1.writeCredentialsJson)(cwd, finalProps);
60
+ }
61
+ }
62
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/keystore/index.ts"],"names":[],"mappings":";;AAiBA,wCA4DC;AA7ED,+CAA2C;AAC3C,kDAAoD;AACpD,kEAA+D;AAC/D,yCAAoD;AACpD,yCAA8C;AAC9C,yCAAkD;AAClD,2CAAkG;AAClG,oDAA8D;AAC9D,wCAAqC;AAS9B,KAAK,UAAU,cAAc,CAClC,GAAW,EACX,aAAgC,EAChC,OAA2B,EAAE;IAE7B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,IAAA,gCAAiB,EAAC,GAAG,CAAC,CAAC;QACxC,IAAI,QAAQ,EAAE,CAAC;YACb,SAAG,CAAC,EAAE,CAAC,8CAA8C,QAAQ,CAAC,QAAQ,eAAe,CAAC,CAAC;YACvF,IAAA,kCAAsB,EAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC;YAClF,IAAA,2CAAoB,EAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YACpC,OAAO;QACT,CAAC;IACH,CAAC;IAED,MAAM,kBAAkB,GAAG,aAAa,KAAK,WAAW,IAAI,CAAC,CAAC,IAAA,kCAAsB,EAAC,GAAG,CAAC,CAAC;IAG1F,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,sEAAsE;YAC5E,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;IACvE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mCAAmC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;IAC/E,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,4BAA4B,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAEnE,MAAM,QAAQ,GACZ,aAAa;QACb,CAAC,MAAM,IAAA,gBAAM,EAAC;YACZ,OAAO,EAAE,4DAA4D;YACrE,OAAO;SACR,CAAC,CAAC,CAAC;IAEN,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,WAAW;YACd,MAAM,IAAA,wCAA4B,EAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YACxD,MAAM;QACR,KAAK,UAAU;YACb,MAAM,IAAA,iCAAsB,EAAC,GAAG,CAAC,CAAC;YAClC,MAAM;QACR,KAAK,UAAU;YACb,MAAM,IAAA,2BAAgB,EAAC,GAAG,CAAC,CAAC;YAC5B,MAAM;QACR,KAAK,KAAK;YACR,MAAM,IAAA,+BAAoB,EAAC,GAAG,CAAC,CAAC;YAChC,MAAM;IACV,CAAC;IAED,IAAA,kCAAsB,EAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAElF,2EAA2E;IAC3E,2EAA2E;IAC3E,8EAA8E;IAC9E,MAAM,UAAU,GAAG,IAAA,gCAAiB,EAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,UAAU,EAAE,CAAC;QACf,IAAA,2CAAoB,EAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.findRehydrateCandidate = findRehydrateCandidate;
7
+ exports.rehydrateFromCredentialsJson = rehydrateFromCredentialsJson;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const setupSigning_1 = require("../setupSigning");
11
+ const log_1 = require("../../util/log");
12
+ function findRehydrateCandidate(cwd) {
13
+ const credPath = path_1.default.join(cwd, 'credentials.json');
14
+ if (!fs_1.default.existsSync(credPath))
15
+ return null;
16
+ let cred;
17
+ try {
18
+ cred = JSON.parse(fs_1.default.readFileSync(credPath, 'utf8'));
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ const ks = cred?.android?.keystore;
24
+ if (!ks ||
25
+ typeof ks.keystorePath !== 'string' ||
26
+ typeof ks.keystorePassword !== 'string' ||
27
+ typeof ks.keyAlias !== 'string' ||
28
+ typeof ks.keyPassword !== 'string') {
29
+ return null;
30
+ }
31
+ const jksSourceAbs = path_1.default.resolve(cwd, ks.keystorePath);
32
+ if (!fs_1.default.existsSync(jksSourceAbs))
33
+ return null;
34
+ return {
35
+ credPath,
36
+ jksSourceAbs,
37
+ storeFile: path_1.default.basename(jksSourceAbs),
38
+ storePassword: ks.keystorePassword,
39
+ keyAlias: ks.keyAlias,
40
+ keyPassword: ks.keyPassword,
41
+ };
42
+ }
43
+ /**
44
+ * Copies the .jks referenced by credentials.json into android/app/ (if not
45
+ * already there) and writes keystore.properties from the same source.
46
+ *
47
+ * Idempotent: re-running on an already-rehydrated project copies nothing
48
+ * (paths match) and rewrites keystore.properties with the same values.
49
+ */
50
+ async function rehydrateFromCredentialsJson(cwd, opts = {}) {
51
+ const cand = findRehydrateCandidate(cwd);
52
+ if (!cand) {
53
+ throw new Error('Cannot rehydrate: credentials.json is missing/incomplete or the referenced .jks was not found. ' +
54
+ 'Run `local-expo-build keystore fetch` to download credentials from EAS first, ' +
55
+ 'or use `keystore import|create` for a manual flow.');
56
+ }
57
+ const destDir = path_1.default.join(cwd, 'android', 'app');
58
+ const destAbs = path_1.default.join(destDir, cand.storeFile);
59
+ const sourceMatchesDest = path_1.default.resolve(cand.jksSourceAbs) === path_1.default.resolve(destAbs);
60
+ fs_1.default.mkdirSync(destDir, { recursive: true });
61
+ if (!sourceMatchesDest) {
62
+ fs_1.default.copyFileSync(cand.jksSourceAbs, destAbs);
63
+ log_1.log.ok(`Copied ${path_1.default.relative(cwd, cand.jksSourceAbs).replace(/\\/g, '/')} → ` +
64
+ `${path_1.default.relative(cwd, destAbs).replace(/\\/g, '/')}`);
65
+ }
66
+ else {
67
+ log_1.log.dim(`.jks already at ${path_1.default.relative(cwd, destAbs).replace(/\\/g, '/')} — skipped copy.`);
68
+ }
69
+ const props = {
70
+ storeFile: cand.storeFile,
71
+ storePassword: cand.storePassword,
72
+ keyAlias: cand.keyAlias,
73
+ keyPassword: cand.keyPassword,
74
+ };
75
+ (0, setupSigning_1.writeKeystoreProps)(cwd, props);
76
+ log_1.log.ok(`keystore.properties written from credentials.json (alias=${props.keyAlias}).`);
77
+ if (opts.move && !sourceMatchesDest) {
78
+ try {
79
+ fs_1.default.rmSync(cand.jksSourceAbs);
80
+ log_1.log.ok(`Removed source ${path_1.default.relative(cwd, cand.jksSourceAbs).replace(/\\/g, '/')} (--move).`);
81
+ }
82
+ catch (err) {
83
+ log_1.log.warn(`Could not remove source ${path_1.default.relative(cwd, cand.jksSourceAbs)}: ${err?.message || err}. ` +
84
+ `The copy at android/app/ is in place; you can delete the source manually.`);
85
+ }
86
+ }
87
+ }
88
+ //# sourceMappingURL=rehydrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rehydrate.js","sourceRoot":"","sources":["../../../src/core/keystore/rehydrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.GRADLE_PIN = void 0;
7
+ exports.pinGradle = pinGradle;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const log_1 = require("../util/log");
11
+ /**
12
+ * Pinning table. `null` = no pin needed for that SDK.
13
+ *
14
+ * SDK 55: pinned to 8.13 because Gradle 9.0.0 (the default in Expo 55's
15
+ * prebuild template) breaks expo-manifests with:
16
+ * > SoftwareComponent with name 'release' not found.
17
+ * Gradle 8.13 evaluates project configuration in the order expo-modules expect.
18
+ */
19
+ exports.GRADLE_PIN = {
20
+ 50: null,
21
+ 51: null,
22
+ 52: null,
23
+ 53: null,
24
+ 54: null,
25
+ 55: '8.13',
26
+ 56: null,
27
+ };
28
+ function pinGradle({ cwd, sdk }) {
29
+ const pin = exports.GRADLE_PIN[sdk];
30
+ if (!pin) {
31
+ log_1.log.dim(`[pin-gradle] SDK ${sdk}: no pin required, skipping.`);
32
+ return;
33
+ }
34
+ const wrapper = path_1.default.join(cwd, 'android', 'gradle', 'wrapper', 'gradle-wrapper.properties');
35
+ if (!fs_1.default.existsSync(wrapper)) {
36
+ log_1.log.warn(`[pin-gradle] ${wrapper} not found; run prebuild first.`);
37
+ return;
38
+ }
39
+ const raw = fs_1.default.readFileSync(wrapper, 'utf8');
40
+ const reUrl = /^distributionUrl=.*/m;
41
+ const desired = `distributionUrl=https\\://services.gradle.org/distributions/gradle-${pin}-bin.zip`;
42
+ const current = raw.match(reUrl)?.[0] ?? '';
43
+ if (current === desired) {
44
+ log_1.log.ok(`[pin-gradle] already pinned to Gradle ${pin}`);
45
+ return;
46
+ }
47
+ fs_1.default.writeFileSync(wrapper, raw.replace(reUrl, desired), 'utf8');
48
+ log_1.log.ok(`[pin-gradle] pinned Gradle wrapper to ${pin} (was: ${current.split('gradle-')[1] ?? '?'})`);
49
+ }
50
+ //# sourceMappingURL=pinGradle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pinGradle.js","sourceRoot":"","sources":["../../src/core/pinGradle.ts"],"names":[],"mappings":";;;;;;AA2BA,8BAyBC;AApDD,4CAAoB;AACpB,gDAAwB;AACxB,qCAAkC;AAElC;;;;;;;GAOG;AACU,QAAA,UAAU,GAAkC;IACvD,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,MAAM;IACV,EAAE,EAAE,IAAI;CACT,CAAC;AAOF,SAAgB,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAiB;IACnD,MAAM,GAAG,GAAG,kBAAU,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,SAAG,CAAC,GAAG,CAAC,oBAAoB,GAAG,8BAA8B,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,2BAA2B,CAAC,CAAC;IAC5F,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,SAAG,CAAC,IAAI,CAAC,gBAAgB,OAAO,iCAAiC,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,YAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,sBAAsB,CAAC;IACrC,MAAM,OAAO,GAAG,sEAAsE,GAAG,UAAU,CAAC;IACpG,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,SAAG,CAAC,EAAE,CAAC,yCAAyC,GAAG,EAAE,CAAC,CAAC;QACvD,OAAO;IACT,CAAC;IACD,YAAE,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/D,SAAG,CAAC,EAAE,CACJ,yCAAyC,GAAG,UAC1C,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,GACjC,GAAG,CACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.prebuild = prebuild;
4
+ const execa_1 = require("execa");
5
+ const log_1 = require("../util/log");
6
+ async function prebuild({ cwd, clean = false }) {
7
+ const args = ['prebuild', '--platform', 'android', '--non-interactive'];
8
+ if (clean)
9
+ args.push('--clean');
10
+ log_1.log.info(`expo ${args.join(' ')}`);
11
+ await (0, execa_1.execa)('npx', ['--no-install', 'expo', ...args], {
12
+ cwd,
13
+ stdio: 'inherit',
14
+ });
15
+ }
16
+ //# sourceMappingURL=prebuild.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prebuild.js","sourceRoot":"","sources":["../../src/core/prebuild.ts"],"names":[],"mappings":";;AAQA,4BAQC;AAhBD,iCAA8B;AAC9B,qCAAkC;AAO3B,KAAK,UAAU,QAAQ,CAAC,EAAE,GAAG,EAAE,KAAK,GAAG,KAAK,EAAgB;IACjE,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACxE,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChC,SAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACnC,MAAM,IAAA,aAAK,EAAC,KAAK,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE;QACpD,GAAG;QACH,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.detectExpoSdk = detectExpoSdk;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const semver_1 = __importDefault(require("semver"));
10
+ function detectExpoSdk(cwd) {
11
+ const pkgPath = path_1.default.join(cwd, 'package.json');
12
+ if (!fs_1.default.existsSync(pkgPath)) {
13
+ throw new Error(`package.json not found at ${pkgPath}. Is this an Expo project?`);
14
+ }
15
+ const pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf8'));
16
+ const raw = pkg.dependencies?.expo || pkg.devDependencies?.expo;
17
+ if (!raw) {
18
+ throw new Error(`"expo" not found in package.json dependencies at ${pkgPath}`);
19
+ }
20
+ const coerced = semver_1.default.coerce(raw);
21
+ if (!coerced) {
22
+ throw new Error(`Could not parse Expo SDK version from "${raw}"`);
23
+ }
24
+ return { major: coerced.major, raw };
25
+ }
26
+ //# sourceMappingURL=sdkDetect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdkDetect.js","sourceRoot":"","sources":["../../src/core/sdkDetect.ts"],"names":[],"mappings":";;;;;AASA,sCAgBC;AAzBD,4CAAoB;AACpB,gDAAwB;AACxB,oDAA4B;AAO5B,SAAgB,aAAa,CAAC,GAAW;IACvC,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC/C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,4BAA4B,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,MAAM,GAAG,GACP,GAAG,CAAC,YAAY,EAAE,IAAI,IAAI,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC;IACtD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,oDAAoD,OAAO,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,OAAO,GAAG,gBAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,0CAA0C,GAAG,GAAG,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;AACvC,CAAC"}