@expo/repack-app 0.0.2 → 0.0.4

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.
@@ -1,4 +1,5 @@
1
+ "use strict";
1
2
  /**
2
3
  * Types mapped from the Resoruces.proto file.
3
4
  */
4
- export {};
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,4 @@
1
- import type { AndroidSigningOptions, NormalizedOptions } from '../types.js';
1
+ import type { AndroidSigningOptions, NormalizedOptions } from '../types';
2
2
  export interface AndroidTools {
3
3
  aapt2Path: string;
4
4
  apksignerPath: string;
@@ -1,62 +1,70 @@
1
- import spawnAsync from '@expo/turtle-spawn';
2
- import { glob } from 'glob';
3
- import assert from 'node:assert';
4
- import fs from 'node:fs/promises';
5
- import path from 'node:path';
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.findLatestBuildToolsDirAsync = exports.createResignedApkAsync = exports.createBinaryBasedResourcesAsync = exports.createProtoBasedResourcesAsync = exports.getAndroidBuildToolsAsync = void 0;
7
+ const spawn_async_1 = __importDefault(require("@expo/spawn-async"));
8
+ const glob_1 = require("glob");
9
+ const node_assert_1 = __importDefault(require("node:assert"));
10
+ const promises_1 = __importDefault(require("node:fs/promises"));
11
+ const node_path_1 = __importDefault(require("node:path"));
6
12
  let cachedAndroidTools = null;
7
13
  /**
8
14
  * Get the paths to the Android build-tools.
9
15
  */
10
- export async function getAndroidBuildToolsAsync(options) {
16
+ async function getAndroidBuildToolsAsync(options) {
11
17
  if (cachedAndroidTools == null) {
12
18
  const androidBuildToolsDir = options?.androidBuildToolsDir ?? (await findLatestBuildToolsDirAsync());
13
- assert(androidBuildToolsDir != null, 'Unable to find the Android build-tools directory.');
19
+ (0, node_assert_1.default)(androidBuildToolsDir != null, 'Unable to find the Android build-tools directory.');
14
20
  cachedAndroidTools = {
15
- aapt2Path: path.join(androidBuildToolsDir, 'aapt2'),
16
- apksignerPath: path.join(androidBuildToolsDir, 'apksigner'),
17
- zipalignPath: path.join(androidBuildToolsDir, 'zipalign'),
21
+ aapt2Path: node_path_1.default.join(androidBuildToolsDir, 'aapt2'),
22
+ apksignerPath: node_path_1.default.join(androidBuildToolsDir, 'apksigner'),
23
+ zipalignPath: node_path_1.default.join(androidBuildToolsDir, 'zipalign'),
18
24
  };
19
25
  }
20
26
  return cachedAndroidTools;
21
27
  }
28
+ exports.getAndroidBuildToolsAsync = getAndroidBuildToolsAsync;
22
29
  /**
23
30
  * Create an APK with proto-based resources.
24
31
  */
25
- export async function createProtoBasedResourcesAsync(options) {
32
+ async function createProtoBasedResourcesAsync(options) {
26
33
  const { sourceAppPath, workingDirectory } = options;
27
34
  const { aapt2Path } = await getAndroidBuildToolsAsync(options);
28
- const protoApkPath = path.join(workingDirectory, 'proto.apk');
29
- await spawnAsync(aapt2Path, ['convert', '-o', protoApkPath, '--output-format', 'proto', '--keep-raw-values', sourceAppPath], {
35
+ const protoApkPath = node_path_1.default.join(workingDirectory, 'proto.apk');
36
+ await (0, spawn_async_1.default)(aapt2Path, ['convert', '-o', protoApkPath, '--output-format', 'proto', '--keep-raw-values', sourceAppPath], {
30
37
  stdio: options.verbose ? 'inherit' : 'ignore',
31
38
  });
32
- await spawnAsync('unzip', [protoApkPath, '-d', workingDirectory], {
39
+ await (0, spawn_async_1.default)('unzip', [protoApkPath, '-d', workingDirectory], {
33
40
  stdio: options.verbose ? 'inherit' : 'ignore',
34
41
  });
35
- const removeFiles = await glob('**/*', {
42
+ const removeFiles = await (0, glob_1.glob)('**/*', {
36
43
  cwd: workingDirectory,
37
44
  maxDepth: 1,
38
45
  ignore: ['resources.pb', 'AndroidManifest.xml', 'res/**'],
39
46
  absolute: true,
40
47
  });
41
- await Promise.all(removeFiles.map((file) => fs.rm(file, { recursive: true })));
48
+ await Promise.all(removeFiles.map((file) => promises_1.default.rm(file, { recursive: true })));
42
49
  return {
43
- androidManiestFilePath: path.join(workingDirectory, 'AndroidManifest.xml'),
44
- resourcesPbFilePath: path.join(workingDirectory, 'resources.pb'),
50
+ androidManiestFilePath: node_path_1.default.join(workingDirectory, 'AndroidManifest.xml'),
51
+ resourcesPbFilePath: node_path_1.default.join(workingDirectory, 'resources.pb'),
45
52
  };
46
53
  }
54
+ exports.createProtoBasedResourcesAsync = createProtoBasedResourcesAsync;
47
55
  /**
48
56
  * Create an APK with binary-based resources.
49
57
  */
50
- export async function createBinaryBasedResourcesAsync(options) {
58
+ async function createBinaryBasedResourcesAsync(options) {
51
59
  const { workingDirectory } = options;
52
60
  const { aapt2Path } = await getAndroidBuildToolsAsync(options);
53
- const protoUpdatedApkPath = path.join(workingDirectory, 'proto-updated.apk');
54
- const binaryApkPath = path.join(workingDirectory, 'binary.apk');
55
- await spawnAsync('zip', ['-r', '-0', protoUpdatedApkPath, 'resources.pb', 'AndroidManifest.xml', 'res'], {
61
+ const protoUpdatedApkPath = node_path_1.default.join(workingDirectory, 'proto-updated.apk');
62
+ const binaryApkPath = node_path_1.default.join(workingDirectory, 'binary.apk');
63
+ await (0, spawn_async_1.default)('zip', ['-r', '-0', protoUpdatedApkPath, 'resources.pb', 'AndroidManifest.xml', 'res'], {
56
64
  cwd: workingDirectory,
57
65
  stdio: options.verbose ? 'inherit' : 'ignore',
58
66
  });
59
- await spawnAsync(aapt2Path, [
67
+ await (0, spawn_async_1.default)(aapt2Path, [
60
68
  'convert',
61
69
  '-o',
62
70
  binaryApkPath,
@@ -69,35 +77,36 @@ export async function createBinaryBasedResourcesAsync(options) {
69
77
  });
70
78
  return binaryApkPath;
71
79
  }
80
+ exports.createBinaryBasedResourcesAsync = createBinaryBasedResourcesAsync;
72
81
  /**
73
82
  * Create a resigned & updated APK.
74
83
  * @param binaryApkPath The path to the binary-based resources APK returned from `createBinaryBasedResourcesAsync()`.
75
84
  * @param appConfigPath The path to the app.config file returned from `generateAppConfigAsync()`.
76
85
  * @returns
77
86
  */
78
- export async function createResignedApkAsync(binaryApkPath, appConfigPath, options, signingOptions) {
87
+ async function createResignedApkAsync(binaryApkPath, appConfigPath, options, signingOptions) {
79
88
  const { workingDirectory } = options;
80
89
  const { apksignerPath, zipalignPath } = await getAndroidBuildToolsAsync(options);
81
- const unzipWorkingDirectory = path.join(workingDirectory, 'unzip');
82
- const resignedApkPath = path.join(workingDirectory, 'resigned.apk');
83
- const resignedApkUnalignedPath = path.join(workingDirectory, 'resigned-unaligned.apk');
84
- await fs.mkdir(unzipWorkingDirectory, { recursive: true });
85
- await spawnAsync('unzip', [options.sourceAppPath, '-d', unzipWorkingDirectory], {
90
+ const unzipWorkingDirectory = node_path_1.default.join(workingDirectory, 'unzip');
91
+ const resignedApkPath = node_path_1.default.join(workingDirectory, 'resigned.apk');
92
+ const resignedApkUnalignedPath = node_path_1.default.join(workingDirectory, 'resigned-unaligned.apk');
93
+ await promises_1.default.mkdir(unzipWorkingDirectory, { recursive: true });
94
+ await (0, spawn_async_1.default)('unzip', [options.sourceAppPath, '-d', unzipWorkingDirectory], {
86
95
  stdio: options.verbose ? 'inherit' : 'ignore',
87
96
  });
88
- await spawnAsync('unzip', ['-o', binaryApkPath, '-d', unzipWorkingDirectory], {
97
+ await (0, spawn_async_1.default)('unzip', ['-o', binaryApkPath, '-d', unzipWorkingDirectory], {
89
98
  stdio: options.verbose ? 'inherit' : 'ignore',
90
99
  });
91
- await fs.copyFile(appConfigPath, path.join(unzipWorkingDirectory, 'assets', 'app.config'));
92
- await spawnAsync('zip', ['-r', '-0', resignedApkUnalignedPath, 'lib', 'resources.arsc'], {
100
+ await promises_1.default.copyFile(appConfigPath, node_path_1.default.join(unzipWorkingDirectory, 'assets', 'app.config'));
101
+ await (0, spawn_async_1.default)('zip', ['-r', '-0', resignedApkUnalignedPath, 'lib', 'resources.arsc'], {
93
102
  cwd: unzipWorkingDirectory,
94
103
  stdio: options.verbose ? 'inherit' : 'ignore',
95
104
  });
96
- await spawnAsync('zip', ['-r', resignedApkUnalignedPath, '.', '-x', 'lib/*', '-x', 'resources.arsc'], {
105
+ await (0, spawn_async_1.default)('zip', ['-r', resignedApkUnalignedPath, '.', '-x', 'lib/*', '-x', 'resources.arsc'], {
97
106
  cwd: unzipWorkingDirectory,
98
107
  stdio: options.verbose ? 'inherit' : 'ignore',
99
108
  });
100
- await spawnAsync(zipalignPath, ['-v', '-p', '4', resignedApkUnalignedPath, resignedApkPath], {
109
+ await (0, spawn_async_1.default)(zipalignPath, ['-v', '-p', '4', resignedApkUnalignedPath, resignedApkPath], {
101
110
  stdio: options.verbose ? 'inherit' : 'ignore',
102
111
  });
103
112
  const signerArgs = [
@@ -114,20 +123,21 @@ export async function createResignedApkAsync(binaryApkPath, appConfigPath, optio
114
123
  signerArgs.push('--key-pass', signingOptions.keyPassword);
115
124
  }
116
125
  signerArgs.push(resignedApkPath);
117
- await spawnAsync(apksignerPath, signerArgs, {
126
+ await (0, spawn_async_1.default)(apksignerPath, signerArgs, {
118
127
  stdio: options.verbose ? 'inherit' : 'ignore',
119
128
  });
120
129
  return resignedApkPath;
121
130
  }
131
+ exports.createResignedApkAsync = createResignedApkAsync;
122
132
  /**
123
133
  * Find the latest build-tools directory in the `ANDROID_SDK_ROOT` directory.
124
134
  */
125
- export async function findLatestBuildToolsDirAsync() {
135
+ async function findLatestBuildToolsDirAsync() {
126
136
  const androidSdkRoot = process.env['ANDROID_SDK_ROOT'];
127
- assert(androidSdkRoot != null, 'ANDROID_SDK_ROOT environment variable is not set');
128
- const buildToolsDir = path.join(androidSdkRoot, 'build-tools');
137
+ (0, node_assert_1.default)(androidSdkRoot != null, 'ANDROID_SDK_ROOT environment variable is not set');
138
+ const buildToolsDir = node_path_1.default.join(androidSdkRoot, 'build-tools');
129
139
  try {
130
- const entries = await fs.readdir(buildToolsDir, { withFileTypes: true });
140
+ const entries = await promises_1.default.readdir(buildToolsDir, { withFileTypes: true });
131
141
  const dirs = entries
132
142
  .filter((entry) => entry.isDirectory())
133
143
  .map((dir) => dir.name)
@@ -143,7 +153,7 @@ export async function findLatestBuildToolsDirAsync() {
143
153
  return versionB.length - versionA.length;
144
154
  });
145
155
  if (dirs.length > 0) {
146
- return path.join(buildToolsDir, dirs[0]);
156
+ return node_path_1.default.join(buildToolsDir, dirs[0]);
147
157
  }
148
158
  else {
149
159
  console.error('No build-tools directories found.');
@@ -155,3 +165,4 @@ export async function findLatestBuildToolsDirAsync() {
155
165
  return null;
156
166
  }
157
167
  }
168
+ exports.findLatestBuildToolsDirAsync = findLatestBuildToolsDirAsync;
@@ -1,4 +1,4 @@
1
- import type { Options } from '../types.js';
1
+ import type { Options } from '../types';
2
2
  /**
3
3
  * Repack an Android app.
4
4
  */
@@ -1,53 +1,62 @@
1
- import { getConfig } from '@expo/config';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import pico from 'picocolors';
5
- import { createBinaryBasedResourcesAsync, createProtoBasedResourcesAsync, createResignedApkAsync, } from './build-tools.js';
6
- import { updateAndroidManifestAsync, updateResourcesAsync } from './resources.js';
7
- import { generateAppConfigAsync, resolveRuntimeVersionAsync } from '../expo.js';
8
- import logger from '../log.js';
9
- import { normalizeOptionAsync } from '../utils.js';
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.repackAppAndroidAsync = void 0;
7
+ const config_1 = require("@expo/config");
8
+ const promises_1 = __importDefault(require("node:fs/promises"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const picocolors_1 = __importDefault(require("picocolors"));
11
+ const build_tools_1 = require("./build-tools");
12
+ const resources_1 = require("./resources");
13
+ const expo_1 = require("../expo");
14
+ const log_1 = __importDefault(require("../log"));
15
+ const utils_1 = require("../utils");
10
16
  /**
11
17
  * Repack an Android app.
12
18
  */
13
- export async function repackAppAndroidAsync(_options) {
14
- const options = await normalizeOptionAsync(_options);
19
+ async function repackAppAndroidAsync(_options) {
20
+ const options = await (0, utils_1.normalizeOptionAsync)(_options);
15
21
  const { workingDirectory } = options;
16
- await fs.mkdir(workingDirectory, { recursive: true });
17
- const { exp } = getConfig(options.projectRoot, {
22
+ await promises_1.default.mkdir(workingDirectory, { recursive: true });
23
+ const { exp } = (0, config_1.getConfig)(options.projectRoot, {
18
24
  isPublicConfig: true,
19
25
  skipSDKVersionRequirement: true,
20
26
  });
21
- const updatesRuntimeVersion = await resolveRuntimeVersionAsync(options, exp);
22
- logger.log(pico.dim(`Resolved runtime version: ${updatesRuntimeVersion}`));
23
- logger.time(`Unzipping APK and creating proto based resources`);
24
- const { androidManiestFilePath, resourcesPbFilePath } = await createProtoBasedResourcesAsync(options);
25
- logger.timeEnd(`Unzipping APK and creating proto based resources`);
26
- logger.time(`Updating Androidmanifest.xml`);
27
- await updateAndroidManifestAsync(exp, androidManiestFilePath, options, updatesRuntimeVersion);
28
- logger.timeEnd(`Updating Androidmanifest.xml`);
29
- logger.time(`Updating resources.pb`);
30
- await updateResourcesAsync(exp, resourcesPbFilePath);
31
- logger.timeEnd(`Updating resources.pb`);
32
- logger.time(`Creating binary based resources`);
33
- const binaryApkPath = await createBinaryBasedResourcesAsync(options);
34
- logger.timeEnd(`Creating binary based resources`);
35
- logger.time(`Generating app.config`);
36
- const appConfigPath = await generateAppConfigAsync(options, exp);
37
- logger.timeEnd(`Generating app.config`);
38
- logger.time(`Creating updated apk`);
39
- const outputApk = await createResignedApkAsync(binaryApkPath, appConfigPath, options, {
27
+ const updatesRuntimeVersion = await (0, expo_1.resolveRuntimeVersionAsync)(options, exp);
28
+ log_1.default.log(picocolors_1.default.dim(`Resolved runtime version: ${updatesRuntimeVersion}`));
29
+ log_1.default.time(`Unzipping APK and creating proto based resources`);
30
+ const { androidManiestFilePath, resourcesPbFilePath } = await (0, build_tools_1.createProtoBasedResourcesAsync)(options);
31
+ log_1.default.timeEnd(`Unzipping APK and creating proto based resources`);
32
+ log_1.default.time(`Updating Androidmanifest.xml`);
33
+ await (0, resources_1.updateAndroidManifestAsync)(exp, androidManiestFilePath, options, updatesRuntimeVersion);
34
+ log_1.default.timeEnd(`Updating Androidmanifest.xml`);
35
+ log_1.default.time(`Updating resources.pb`);
36
+ await (0, resources_1.updateResourcesAsync)(exp, resourcesPbFilePath);
37
+ log_1.default.timeEnd(`Updating resources.pb`);
38
+ log_1.default.time(`Creating binary based resources`);
39
+ const binaryApkPath = await (0, build_tools_1.createBinaryBasedResourcesAsync)(options);
40
+ log_1.default.timeEnd(`Creating binary based resources`);
41
+ log_1.default.time(`Generating app.config`);
42
+ const appConfigPath = await (0, expo_1.generateAppConfigAsync)(options, exp);
43
+ log_1.default.timeEnd(`Generating app.config`);
44
+ log_1.default.time(`Creating updated apk`);
45
+ const outputApk = await (0, build_tools_1.createResignedApkAsync)(binaryApkPath, appConfigPath, options, {
40
46
  keyStorePath: options.androidSigningOptions?.keyStorePath ??
41
- path.resolve(__dirname, '../assets/debug.keystore'),
47
+ node_path_1.default.resolve(__dirname, '../assets/debug.keystore'),
42
48
  keyStorePassword: options.androidSigningOptions?.keyStorePassword ?? 'android',
43
49
  keyAlias: options.androidSigningOptions?.keyAlias,
44
50
  keyPassword: options.androidSigningOptions?.keyPassword,
45
51
  });
46
- logger.timeEnd(`Creating updated apk`);
47
- await fs.rename(outputApk, options.outputPath);
48
- try {
49
- await fs.rmdir(workingDirectory, { recursive: true });
52
+ log_1.default.timeEnd(`Creating updated apk`);
53
+ await promises_1.default.rename(outputApk, options.outputPath);
54
+ if (!options.skipWorkingDirCleanup) {
55
+ try {
56
+ await promises_1.default.rmdir(workingDirectory, { recursive: true });
57
+ }
58
+ catch { }
50
59
  }
51
- catch { }
52
60
  return options.outputPath;
53
61
  }
62
+ exports.repackAppAndroidAsync = repackAppAndroidAsync;
@@ -1,5 +1,5 @@
1
1
  import { type ExpoConfig } from '@expo/config';
2
- import type { NormalizedOptions } from '../types.js';
2
+ import type { NormalizedOptions } from '../types';
3
3
  /**
4
4
  * Update resources inside the **resources.pb** file.
5
5
  */
@@ -1,36 +1,43 @@
1
- import assert from 'node:assert';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import protobuf from 'protobufjs';
5
- import { requireNotNull } from '../utils.js';
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.updateAndroidManifestAsync = exports.updateResourcesAsync = void 0;
7
+ const node_assert_1 = __importDefault(require("node:assert"));
8
+ const promises_1 = __importDefault(require("node:fs/promises"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const protobufjs_1 = __importDefault(require("protobufjs"));
11
+ const utils_1 = require("../utils");
6
12
  /**
7
13
  * Update resources inside the **resources.pb** file.
8
14
  */
9
- export async function updateResourcesAsync(config, resourcesPbFilePath) {
10
- const root = await protobuf.load(path.join(__dirname, '../../assets', 'Resources.proto'));
15
+ async function updateResourcesAsync(config, resourcesPbFilePath) {
16
+ const root = await protobufjs_1.default.load(node_path_1.default.join(__dirname, '../../assets', 'Resources.proto'));
11
17
  const resourceTableType = root.lookupType('aapt.pb.ResourceTable');
12
18
  const resourceTable = await decodeProtoFile(resourceTableType, resourcesPbFilePath);
13
19
  // [0] Update the package name
14
- assert(resourceTable.package.length === 1, 'Expected only one package');
15
- assert(config.android?.package, 'Expected android.package to be defined');
20
+ (0, node_assert_1.default)(resourceTable.package.length === 1, 'Expected only one package');
21
+ (0, node_assert_1.default)(config.android?.package, 'Expected android.package to be defined');
16
22
  resourceTable.package[0].packageName = config.android.package;
17
23
  const stringType = resourceTable.package[0].type.find((type) => type.name === 'string');
18
24
  const stringEntries = stringType?.entry;
19
25
  // [1] Update the `app_name` in **res/values/strings.xml**.
20
26
  const appNameEntry = stringEntries?.find((entry) => entry.name === 'app_name');
21
- assert(appNameEntry?.configValue?.[0].value?.item?.str?.value === 'HelloWorld', 'Expected app_name to be predefined "HelloWorld"');
27
+ (0, node_assert_1.default)(appNameEntry?.configValue?.[0].value?.item?.str?.value === 'HelloWorld', 'Expected app_name to be predefined "HelloWorld"');
22
28
  appNameEntry.configValue[0].value.item.str.value = config.name;
23
29
  await encodeProtoFile(resourceTableType, resourcesPbFilePath, resourceTable);
24
30
  }
31
+ exports.updateResourcesAsync = updateResourcesAsync;
25
32
  /**
26
33
  * Update the proto-based AndroidManiest.xml.
27
34
  */
28
- export async function updateAndroidManifestAsync(config, androidManiestFilePath, options, updatesRuntimeVersion) {
29
- const root = await protobuf.load(path.join(__dirname, '../../assets', 'Resources.proto'));
35
+ async function updateAndroidManifestAsync(config, androidManiestFilePath, options, updatesRuntimeVersion) {
36
+ const root = await protobufjs_1.default.load(node_path_1.default.join(__dirname, '../../assets', 'Resources.proto'));
30
37
  const xmlNodeType = root.lookupType('aapt.pb.XmlNode');
31
38
  const rootNode = await decodeProtoFile(xmlNodeType, androidManiestFilePath);
32
39
  // [0] Update the package name
33
- replaceXmlAttributeValue(rootNode, (value) => value.replace(/dev\.expo\.templatedefault\.appid/g, requireNotNull(config.android?.package)));
40
+ replaceXmlAttributeValue(rootNode, (value) => value.replace(/dev\.expo\.templatedefault\.appid/g, (0, utils_1.requireNotNull)(config.android?.package)));
34
41
  // [1] Update the scheme in the intent-filters
35
42
  const intentFilterViewActionNodes = findXmlNodes(rootNode, (node) => node.element?.name === 'intent-filter' &&
36
43
  findXmlNodes(node, (node) => node.element?.name === 'action' &&
@@ -39,19 +46,20 @@ export async function updateAndroidManifestAsync(config, androidManiestFilePath,
39
46
  for (const node of intentFilterViewActionNodes) {
40
47
  replaceXmlAttributeValue(node, (value) => value
41
48
  // scheme in app.json
42
- .replace(/^myapp$/g, requireNotNull(firstScheme))
49
+ .replace(/^myapp$/g, (0, utils_1.requireNotNull)(firstScheme))
43
50
  // android.package in app.json
44
- .replace(/^dev\.expo\.templatedefault$/g, requireNotNull(config.android?.package))
51
+ .replace(/^dev\.expo\.templatedefault$/g, (0, utils_1.requireNotNull)(config.android?.package))
45
52
  // default scheme generated from slug in app.json
46
- .replace(/^exp\+expo-template-default$/g, `exp+${requireNotNull(config.slug)}`));
53
+ .replace(/^exp\+expo-template-default$/g, `exp+${(0, utils_1.requireNotNull)(config.slug)}`));
47
54
  }
48
55
  // [2] expo-updates configuration
49
56
  const mainApplicationNode = findXmlNodes(rootNode, (node) => node.element?.name === 'application' &&
50
57
  node.element?.attribute.find((attr) => attr.name === 'name' && attr.value.endsWith('.MainApplication')) != null)[0];
51
- assert(mainApplicationNode != null, 'Expected application node to be present');
58
+ (0, node_assert_1.default)(mainApplicationNode != null, 'Expected application node to be present');
52
59
  mutateExpoUpdatesConfigAsync(mainApplicationNode, config, updatesRuntimeVersion);
53
60
  await encodeProtoFile(xmlNodeType, androidManiestFilePath, rootNode);
54
61
  }
62
+ exports.updateAndroidManifestAsync = updateAndroidManifestAsync;
55
63
  //#region Internals
56
64
  /**
57
65
  * Update the `expo-updates` configuration in the Android project.
@@ -59,11 +67,11 @@ export async function updateAndroidManifestAsync(config, androidManiestFilePath,
59
67
  function mutateExpoUpdatesConfigAsync(mainApplicationNode, config, runtimeVersion) {
60
68
  const updateEnabledNodeIndex = mainApplicationNode.element?.child.findIndex((child) => child.element?.name === 'meta-data' &&
61
69
  child.element?.attribute.find((attr) => attr.name === 'name' && attr.value === 'expo.modules.updates.ENABLED'));
62
- assert(updateEnabledNodeIndex != null && updateEnabledNodeIndex >= 0, `Expected 'expo.modules.updates.ENABLED' node to be present`);
63
- const updateEnabledNode = requireNotNull(mainApplicationNode.element?.child[updateEnabledNodeIndex]);
70
+ (0, node_assert_1.default)(updateEnabledNodeIndex != null && updateEnabledNodeIndex >= 0, `Expected 'expo.modules.updates.ENABLED' node to be present`);
71
+ const updateEnabledNode = (0, utils_1.requireNotNull)(mainApplicationNode.element?.child[updateEnabledNodeIndex]);
64
72
  // [0] expo.modules.updates.ENABLED
65
73
  const updateEnabledPrimValue = updateEnabledNode.element?.attribute?.[1]?.compiledItem?.prim;
66
- assert(updateEnabledPrimValue != null, 'Expected updateEnabledPrimValue to be present');
74
+ (0, node_assert_1.default)(updateEnabledPrimValue != null, 'Expected updateEnabledPrimValue to be present');
67
75
  updateEnabledPrimValue.booleanValue = true;
68
76
  // [1] expo.modules.updates.EXPO_RUNTIME_VERSION
69
77
  const updateRuntimeVersionNode = mainApplicationNode.element?.child.find((child) => child.element?.name === 'meta-data' &&
@@ -72,19 +80,19 @@ function mutateExpoUpdatesConfigAsync(mainApplicationNode, config, runtimeVersio
72
80
  mainApplicationNode.element?.child.splice(updateEnabledNodeIndex + 1, 0, createUpdateStringNode(updateEnabledNode, 'expo.modules.updates.EXPO_RUNTIME_VERSION', runtimeVersion));
73
81
  }
74
82
  else {
75
- assert(updateRuntimeVersionNode.element != null);
83
+ (0, node_assert_1.default)(updateRuntimeVersionNode.element != null);
76
84
  updateRuntimeVersionNode.element.attribute[1].value = runtimeVersion;
77
85
  }
78
86
  // [2] expo.modules.updates.EXPO_UPDATE_URL
79
87
  const updateUrlNode = mainApplicationNode.element?.child.find((child) => child.element?.name === 'meta-data' &&
80
88
  child.element?.attribute.find((attr) => attr.name === 'name' && attr.value === 'expo.modules.updates.EXPO_UPDATE_URL'));
81
89
  const updateUrl = config.updates?.url;
82
- assert(updateUrl);
90
+ (0, node_assert_1.default)(updateUrl);
83
91
  if (updateUrlNode == null) {
84
92
  mainApplicationNode.element?.child.splice(updateEnabledNodeIndex + 1, 0, createUpdateStringNode(updateEnabledNode, 'expo.modules.updates.EXPO_UPDATE_URL', updateUrl));
85
93
  }
86
94
  else {
87
- assert(updateUrlNode.element != null);
95
+ (0, node_assert_1.default)(updateUrlNode.element != null);
88
96
  updateUrlNode.element.attribute[1].value = updateUrl;
89
97
  }
90
98
  }
@@ -92,7 +100,7 @@ function mutateExpoUpdatesConfigAsync(mainApplicationNode, config, runtimeVersio
92
100
  * Decode the proto-encoded file from `filePath` with the given `protoTypeString` and return as JSON object.
93
101
  */
94
102
  async function decodeProtoFile(protoType, filePath) {
95
- const buffer = await fs.readFile(filePath);
103
+ const buffer = await promises_1.default.readFile(filePath);
96
104
  const message = await protoType.decode(buffer);
97
105
  const json = protoType.toObject(message, {
98
106
  longs: String,
@@ -108,7 +116,7 @@ async function decodeProtoFile(protoType, filePath) {
108
116
  async function encodeProtoFile(protoType, filePath, json) {
109
117
  const updatedMessage = protoType.fromObject(json);
110
118
  const updatedBuffer = protoType.encode(updatedMessage).finish();
111
- await fs.writeFile(filePath, updatedBuffer);
119
+ await promises_1.default.writeFile(filePath, updatedBuffer);
112
120
  }
113
121
  /**
114
122
  * Recursively find XML nodes that satisfy the given `predicate`.
@@ -145,7 +153,7 @@ function createUpdateStringNode(updateEnabledNode, name, value) {
145
153
  return {
146
154
  ...updateEnabledNode,
147
155
  element: {
148
- ...requireNotNull(updateEnabledNode.element),
156
+ ...(0, utils_1.requireNotNull)(updateEnabledNode.element),
149
157
  attribute: [
150
158
  {
151
159
  namespaceUri: 'http://schemas.android.com/apk/res/android',
package/build/cli.js CHANGED
@@ -1,9 +1,14 @@
1
- import { Command } from 'commander';
2
- import pico from 'picocolors';
3
- import { repackAppAndroidAsync, repackAppIosAsync } from './index.js';
4
- import { resignIpaAsync } from './ios/index.js';
5
- import logger from './log.js';
6
- const program = new Command('repack-app')
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
+ const commander_1 = require("commander");
7
+ const picocolors_1 = __importDefault(require("picocolors"));
8
+ const index_1 = require("./index");
9
+ const index_2 = require("./ios/index");
10
+ const log_1 = __importDefault(require("./log"));
11
+ const program = new commander_1.Command('repack-app')
7
12
  .requiredOption('-p, --platform <platform>', 'Platform to repack the app for')
8
13
  .requiredOption('--source-app <path>', 'Path to the source app file')
9
14
  .option('--android-build-tools-dir <path>', 'Path to the Android build tools directory')
@@ -25,7 +30,7 @@ async function runAsync() {
25
30
  const platform = program.opts().platform;
26
31
  const projectRoot = program.args[0];
27
32
  if (platform === 'android') {
28
- const outputPath = await repackAppAndroidAsync({
33
+ const outputPath = await (0, index_1.repackAppAndroidAsync)({
29
34
  platform: program.opts().platform,
30
35
  projectRoot,
31
36
  verbose: !!program.opts().verbose,
@@ -40,7 +45,7 @@ async function runAsync() {
40
45
  },
41
46
  androidBuildToolsDir: program.opts().androidBuildToolsDir,
42
47
  });
43
- logger.log(pico.green(`Updated APK created at ${outputPath}`));
48
+ log_1.default.log(picocolors_1.default.green(`Updated APK created at ${outputPath}`));
44
49
  }
45
50
  else if (platform === 'ios') {
46
51
  const options = {
@@ -55,12 +60,12 @@ async function runAsync() {
55
60
  provisioningProfile: program.opts().provisioningProfile,
56
61
  },
57
62
  };
58
- const outputPath = await repackAppIosAsync(options);
59
- logger.log(pico.green(`Updated IPA created at ${outputPath}`));
63
+ const outputPath = await (0, index_1.repackAppIosAsync)(options);
64
+ log_1.default.log(picocolors_1.default.green(`Updated IPA created at ${outputPath}`));
60
65
  if (options.iosSigningOptions?.signingIdentity &&
61
66
  options.iosSigningOptions?.provisioningProfile) {
62
- logger.log(pico.green(`Resigning the IPA at ${outputPath}`));
63
- await resignIpaAsync(outputPath, options.iosSigningOptions, options);
67
+ log_1.default.log(picocolors_1.default.green(`Resigning the IPA at ${outputPath}`));
68
+ await (0, index_2.resignIpaAsync)(outputPath, options.iosSigningOptions, options);
64
69
  }
65
70
  }
66
71
  else {
package/build/expo.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type ExpoConfig } from '@expo/config';
2
- import type { NormalizedOptions } from './types.js';
2
+ import type { NormalizedOptions } from './types';
3
3
  /**
4
4
  * Generate the app.config file for the Android app.
5
5
  */
package/build/expo.js CHANGED
@@ -1,26 +1,34 @@
1
- import spawnAsync from '@expo/turtle-spawn';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import resolveFrom from 'resolve-from';
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.resolveRuntimeVersionAsync = exports.generateAppConfigAsync = void 0;
7
+ const spawn_async_1 = __importDefault(require("@expo/spawn-async"));
8
+ const promises_1 = __importDefault(require("node:fs/promises"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const resolve_from_1 = __importDefault(require("resolve-from"));
5
11
  /**
6
12
  * Generate the app.config file for the Android app.
7
13
  */
8
- export async function generateAppConfigAsync(options, config) {
14
+ async function generateAppConfigAsync(options, config) {
9
15
  const { workingDirectory } = options;
10
- const appConfigPath = path.join(workingDirectory, 'app.config');
11
- await fs.writeFile(appConfigPath, JSON.stringify(config));
16
+ const appConfigPath = node_path_1.default.join(workingDirectory, 'app.config');
17
+ await promises_1.default.writeFile(appConfigPath, JSON.stringify(config));
12
18
  return appConfigPath;
13
19
  }
20
+ exports.generateAppConfigAsync = generateAppConfigAsync;
14
21
  /**
15
22
  * Resolve the `runtimeVersion` for expo-updates.
16
23
  */
17
- export async function resolveRuntimeVersionAsync(options, config) {
24
+ async function resolveRuntimeVersionAsync(options, config) {
18
25
  const { projectRoot } = options;
19
- const cli = resolveFrom.silent(projectRoot, 'expo-updates/bin/cli') ??
20
- resolveFrom(projectRoot, 'expo-updates/bin/cli.js');
21
- const proc = await spawnAsync(cli, ['runtimeversion:resolve', '--platform', 'android', '--workflow', 'managed'], {
26
+ const cli = resolve_from_1.default.silent(projectRoot, 'expo-updates/bin/cli') ??
27
+ (0, resolve_from_1.default)(projectRoot, 'expo-updates/bin/cli.js');
28
+ const proc = await (0, spawn_async_1.default)(cli, ['runtimeversion:resolve', '--platform', 'android', '--workflow', 'managed'], {
22
29
  cwd: projectRoot,
23
30
  });
24
31
  const runtimeVersion = JSON.parse(proc.stdout).runtimeVersion;
25
32
  return runtimeVersion ?? config.version ?? '1.0.0';
26
33
  }
34
+ exports.resolveRuntimeVersionAsync = resolveRuntimeVersionAsync;
package/build/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { repackAppAndroidAsync } from './android/index.js';
2
- export { repackAppIosAsync } from './ios/index.js';
1
+ export { repackAppAndroidAsync } from './android';
2
+ export { repackAppIosAsync } from './ios';
package/build/index.js CHANGED
@@ -1,2 +1,7 @@
1
- export { repackAppAndroidAsync } from './android/index.js';
2
- export { repackAppIosAsync } from './ios/index.js';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.repackAppIosAsync = exports.repackAppAndroidAsync = void 0;
4
+ var android_1 = require("./android");
5
+ Object.defineProperty(exports, "repackAppAndroidAsync", { enumerable: true, get: function () { return android_1.repackAppAndroidAsync; } });
6
+ var ios_1 = require("./ios");
7
+ Object.defineProperty(exports, "repackAppIosAsync", { enumerable: true, get: function () { return ios_1.repackAppIosAsync; } });
@@ -1,5 +1,5 @@
1
1
  import { type ExpoConfig } from '@expo/config';
2
- import type { NormalizedOptions } from '../types.js';
2
+ import type { NormalizedOptions } from '../types';
3
3
  /**
4
4
  * Unzip the IPA file.
5
5
  */
@@ -1,43 +1,52 @@
1
- import spawnAsync from '@expo/turtle-spawn';
2
- import assert from 'node:assert';
3
- import fs from 'node:fs/promises';
4
- import path from 'node:path';
5
- import { directoryExistsAsync } from '../utils.js';
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.createIpaAsync = exports.updateFilesAsync = exports.unzipIpaAsync = void 0;
7
+ const spawn_async_1 = __importDefault(require("@expo/spawn-async"));
8
+ const node_assert_1 = __importDefault(require("node:assert"));
9
+ const promises_1 = __importDefault(require("node:fs/promises"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const utils_1 = require("../utils");
6
12
  /**
7
13
  * Unzip the IPA file.
8
14
  */
9
- export async function unzipIpaAsync(options) {
10
- const unzipWorkingDirectory = path.join(options.workingDirectory, 'unzip');
11
- await spawnAsync('unzip', [options.sourceAppPath, '-d', unzipWorkingDirectory], {
15
+ async function unzipIpaAsync(options) {
16
+ const unzipWorkingDirectory = node_path_1.default.join(options.workingDirectory, 'unzip');
17
+ await (0, spawn_async_1.default)('unzip', [options.sourceAppPath, '-d', unzipWorkingDirectory], {
12
18
  stdio: options.verbose ? 'inherit' : 'ignore',
13
19
  });
14
- const appWorkingDirectory = path.join(unzipWorkingDirectory, 'Payload', 'HelloWorld.app');
15
- assert(await directoryExistsAsync(appWorkingDirectory));
20
+ const appWorkingDirectory = node_path_1.default.join(unzipWorkingDirectory, 'Payload', 'HelloWorld.app');
21
+ (0, node_assert_1.default)(await (0, utils_1.directoryExistsAsync)(appWorkingDirectory));
16
22
  return appWorkingDirectory;
17
23
  }
24
+ exports.unzipIpaAsync = unzipIpaAsync;
18
25
  /**
19
26
  * Update some binary files.
20
27
  */
21
- export async function updateFilesAsync(config, appWorkingDirectory) {
22
- const parentDir = path.dirname(appWorkingDirectory);
23
- const newAppWorkingDirectory = path.join(parentDir, `${config.name}.app`);
28
+ async function updateFilesAsync(config, appWorkingDirectory) {
29
+ const parentDir = node_path_1.default.dirname(appWorkingDirectory);
30
+ const newAppWorkingDirectory = node_path_1.default.join(parentDir, `${config.name}.app`);
24
31
  // [0] Update the .app directory
25
- await fs.rename(path.join(parentDir, 'HelloWorld.app'), newAppWorkingDirectory);
32
+ await promises_1.default.rename(node_path_1.default.join(parentDir, 'HelloWorld.app'), newAppWorkingDirectory);
26
33
  // [1] Rename the executable
27
- await fs.rename(path.join(newAppWorkingDirectory, 'HelloWorld'), path.join(newAppWorkingDirectory, config.name));
34
+ await promises_1.default.rename(node_path_1.default.join(newAppWorkingDirectory, 'HelloWorld'), node_path_1.default.join(newAppWorkingDirectory, config.name));
28
35
  return newAppWorkingDirectory;
29
36
  }
37
+ exports.updateFilesAsync = updateFilesAsync;
30
38
  /**
31
39
  * From the given working .app directory, create a new .ipa file.
32
40
  */
33
- export async function createIpaAsync(options, appWorkingDirectory) {
41
+ async function createIpaAsync(options, appWorkingDirectory) {
34
42
  const { workingDirectory } = options;
35
- await fs.mkdir(path.join(workingDirectory, 'Payload'), { recursive: true });
36
- await fs.rename(appWorkingDirectory, path.join(workingDirectory, 'Payload', path.basename(appWorkingDirectory)));
37
- const outputIpaPath = path.join(workingDirectory, 'repacked.ipa');
38
- await spawnAsync('zip', ['-r', outputIpaPath, 'Payload'], {
43
+ await promises_1.default.mkdir(node_path_1.default.join(workingDirectory, 'Payload'), { recursive: true });
44
+ await promises_1.default.rename(appWorkingDirectory, node_path_1.default.join(workingDirectory, 'Payload', node_path_1.default.basename(appWorkingDirectory)));
45
+ const outputIpaPath = node_path_1.default.join(workingDirectory, 'repacked.ipa');
46
+ await (0, spawn_async_1.default)('zip', ['-r', outputIpaPath, 'Payload'], {
39
47
  cwd: workingDirectory,
40
48
  stdio: options.verbose ? 'inherit' : 'ignore',
41
49
  });
42
50
  return outputIpaPath;
43
51
  }
52
+ exports.createIpaAsync = createIpaAsync;
@@ -1,4 +1,4 @@
1
- import type { IosSigningOptions, Options } from '../types.js';
1
+ import type { IosSigningOptions, Options } from '../types';
2
2
  /**
3
3
  * Repack an iOS app.
4
4
  */
@@ -1,54 +1,63 @@
1
- import { getConfig } from '@expo/config';
2
- import spawnAsync from '@expo/turtle-spawn';
3
- import fs from 'node:fs/promises';
4
- import path from 'node:path';
5
- import pico from 'picocolors';
6
- import { createIpaAsync, unzipIpaAsync, updateFilesAsync } from './build-tools.js';
7
- import { updateExpoPlistAsync, updateInfoPlistAsync } from './resources.js';
8
- import { generateAppConfigAsync, resolveRuntimeVersionAsync } from '../expo.js';
9
- import logger from '../log.js';
10
- import { normalizeOptionAsync } from '../utils.js';
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.resignIpaAsync = exports.repackAppIosAsync = void 0;
7
+ const config_1 = require("@expo/config");
8
+ const spawn_async_1 = __importDefault(require("@expo/spawn-async"));
9
+ const promises_1 = __importDefault(require("node:fs/promises"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const picocolors_1 = __importDefault(require("picocolors"));
12
+ const build_tools_1 = require("./build-tools");
13
+ const resources_1 = require("./resources");
14
+ const expo_1 = require("../expo");
15
+ const log_1 = __importDefault(require("../log"));
16
+ const utils_1 = require("../utils");
11
17
  /**
12
18
  * Repack an iOS app.
13
19
  */
14
- export async function repackAppIosAsync(_options) {
15
- const options = await normalizeOptionAsync(_options);
20
+ async function repackAppIosAsync(_options) {
21
+ const options = await (0, utils_1.normalizeOptionAsync)(_options);
16
22
  const { workingDirectory } = options;
17
- await fs.mkdir(workingDirectory, { recursive: true });
18
- const { exp } = getConfig(options.projectRoot, {
23
+ await promises_1.default.mkdir(workingDirectory, { recursive: true });
24
+ const { exp } = (0, config_1.getConfig)(options.projectRoot, {
19
25
  isPublicConfig: true,
20
26
  skipSDKVersionRequirement: true,
21
27
  });
22
- const updatesRuntimeVersion = await resolveRuntimeVersionAsync(options, exp);
23
- logger.log(pico.dim(`Resolved runtime version: ${updatesRuntimeVersion}`));
24
- logger.time(`Unzipping IPA`);
25
- let appWorkingDirectory = await unzipIpaAsync(options);
26
- appWorkingDirectory = await updateFilesAsync(exp, appWorkingDirectory);
27
- logger.timeEnd(`Unzipping IPA`);
28
- logger.time(`Updating Info.plist`);
29
- await updateInfoPlistAsync(exp, path.join(appWorkingDirectory, 'Info.plist'), options);
30
- logger.timeEnd(`Updating Info.plist`);
31
- logger.time(`Updating Expo.plist`);
32
- await updateExpoPlistAsync(exp, path.join(appWorkingDirectory, 'Expo.plist'), updatesRuntimeVersion, options);
33
- logger.timeEnd(`Updating Expo.plist`);
34
- logger.time(`Generating app.config`);
35
- const appConfigPath = await generateAppConfigAsync(options, exp);
36
- await fs.copyFile(appConfigPath, path.join(appWorkingDirectory, 'EXConstants.bundle', 'app.config'));
37
- logger.timeEnd(`Generating app.config`);
38
- logger.time(`Creating updated ipa`);
39
- const outputIpa = await createIpaAsync(options, appWorkingDirectory);
40
- logger.timeEnd(`Creating updated ipa`);
41
- await fs.rename(outputIpa, options.outputPath);
42
- try {
43
- await fs.rmdir(workingDirectory, { recursive: true });
28
+ const updatesRuntimeVersion = await (0, expo_1.resolveRuntimeVersionAsync)(options, exp);
29
+ log_1.default.log(picocolors_1.default.dim(`Resolved runtime version: ${updatesRuntimeVersion}`));
30
+ log_1.default.time(`Unzipping IPA`);
31
+ let appWorkingDirectory = await (0, build_tools_1.unzipIpaAsync)(options);
32
+ appWorkingDirectory = await (0, build_tools_1.updateFilesAsync)(exp, appWorkingDirectory);
33
+ log_1.default.timeEnd(`Unzipping IPA`);
34
+ log_1.default.time(`Updating Info.plist`);
35
+ await (0, resources_1.updateInfoPlistAsync)(exp, node_path_1.default.join(appWorkingDirectory, 'Info.plist'), options);
36
+ log_1.default.timeEnd(`Updating Info.plist`);
37
+ log_1.default.time(`Updating Expo.plist`);
38
+ await (0, resources_1.updateExpoPlistAsync)(exp, node_path_1.default.join(appWorkingDirectory, 'Expo.plist'), updatesRuntimeVersion, options);
39
+ log_1.default.timeEnd(`Updating Expo.plist`);
40
+ log_1.default.time(`Generating app.config`);
41
+ const appConfigPath = await (0, expo_1.generateAppConfigAsync)(options, exp);
42
+ await promises_1.default.copyFile(appConfigPath, node_path_1.default.join(appWorkingDirectory, 'EXConstants.bundle', 'app.config'));
43
+ log_1.default.timeEnd(`Generating app.config`);
44
+ log_1.default.time(`Creating updated ipa`);
45
+ const outputIpa = await (0, build_tools_1.createIpaAsync)(options, appWorkingDirectory);
46
+ log_1.default.timeEnd(`Creating updated ipa`);
47
+ await promises_1.default.rename(outputIpa, options.outputPath);
48
+ if (!options.skipWorkingDirCleanup) {
49
+ try {
50
+ await promises_1.default.rmdir(workingDirectory, { recursive: true });
51
+ }
52
+ catch { }
44
53
  }
45
- catch { }
46
54
  return options.outputPath;
47
55
  }
56
+ exports.repackAppIosAsync = repackAppIosAsync;
48
57
  /**
49
58
  * Resign an IPA by fastlane.
50
59
  */
51
- export async function resignIpaAsync(ipaPath, signingOptions, options) {
60
+ async function resignIpaAsync(ipaPath, signingOptions, options) {
52
61
  const args = [
53
62
  'run',
54
63
  'resign',
@@ -59,7 +68,8 @@ export async function resignIpaAsync(ipaPath, signingOptions, options) {
59
68
  if (signingOptions.keychainPath) {
60
69
  args.push(`keychain_path:${signingOptions.keychainPath}`);
61
70
  }
62
- await spawnAsync('fastlane', args, {
71
+ await (0, spawn_async_1.default)('fastlane', args, {
63
72
  stdio: options.verbose ? 'inherit' : 'ignore',
64
73
  });
65
74
  }
75
+ exports.resignIpaAsync = resignIpaAsync;
@@ -1,5 +1,5 @@
1
1
  import { type ExpoConfig } from '@expo/config';
2
- import type { NormalizedOptions } from '../types.js';
2
+ import type { NormalizedOptions } from '../types';
3
3
  /**
4
4
  * Update the Info.plist file.
5
5
  */
@@ -1,14 +1,20 @@
1
- import plist from '@expo/plist';
2
- import spawnAsync from '@expo/turtle-spawn';
3
- import assert from 'node:assert';
4
- import fs from 'node:fs/promises';
5
- import { requireNotNull } from '../utils.js';
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.updateExpoPlistAsync = exports.updateInfoPlistAsync = void 0;
7
+ const plist_1 = __importDefault(require("@expo/plist"));
8
+ const spawn_async_1 = __importDefault(require("@expo/spawn-async"));
9
+ const node_assert_1 = __importDefault(require("node:assert"));
10
+ const promises_1 = __importDefault(require("node:fs/promises"));
11
+ const utils_1 = require("../utils");
6
12
  /**
7
13
  * Update the Info.plist file.
8
14
  */
9
- export async function updateInfoPlistAsync(config, infoPlistPath, options) {
15
+ async function updateInfoPlistAsync(config, infoPlistPath, options) {
10
16
  const bundleIdentifier = config.ios?.bundleIdentifier;
11
- assert(bundleIdentifier, 'The `bundleIdentifier` must be specified in the `ios` config.');
17
+ (0, node_assert_1.default)(bundleIdentifier, 'The `bundleIdentifier` must be specified in the `ios` config.');
12
18
  const firstScheme = Array.isArray(config.scheme) ? config.scheme[0] : config.scheme;
13
19
  await updateBinaryPlistAsync(infoPlistPath, options, (data) => {
14
20
  const urlTypes = data.CFBundleURLTypes.slice();
@@ -17,11 +23,11 @@ export async function updateInfoPlistAsync(config, infoPlistPath, options) {
17
23
  const schemes = urlType.CFBundleURLSchemes.map((scheme) => {
18
24
  return (scheme
19
25
  // scheme in app.json
20
- .replace(/^myapp$/g, requireNotNull(firstScheme))
26
+ .replace(/^myapp$/g, (0, utils_1.requireNotNull)(firstScheme))
21
27
  // ios.bundleIdentifier in app.json
22
- .replace(/^dev.expo.templatedefault$/g, requireNotNull(bundleIdentifier))
28
+ .replace(/^dev.expo.templatedefault$/g, (0, utils_1.requireNotNull)(bundleIdentifier))
23
29
  // default scheme generated from slug in app.json
24
- .replace(/^exp\+expo-template-default$/g, `exp+${requireNotNull(config.slug)}`));
30
+ .replace(/^exp\+expo-template-default$/g, `exp+${(0, utils_1.requireNotNull)(config.slug)}`));
25
31
  });
26
32
  urlType.CFBundleURLSchemes = schemes;
27
33
  }
@@ -37,13 +43,14 @@ export async function updateInfoPlistAsync(config, infoPlistPath, options) {
37
43
  };
38
44
  });
39
45
  }
46
+ exports.updateInfoPlistAsync = updateInfoPlistAsync;
40
47
  /**
41
48
  * Update the Expo.plist file.
42
49
  */
43
- export async function updateExpoPlistAsync(config, expoPlistPath, runtimeVersion, options) {
50
+ async function updateExpoPlistAsync(config, expoPlistPath, runtimeVersion, options) {
44
51
  await updateBinaryPlistAsync(expoPlistPath, options, (data) => {
45
52
  const updateUrl = config.updates?.url;
46
- assert(updateUrl);
53
+ (0, node_assert_1.default)(updateUrl);
47
54
  return {
48
55
  ...data,
49
56
  EXUpdatesEnabled: true,
@@ -52,17 +59,18 @@ export async function updateExpoPlistAsync(config, expoPlistPath, runtimeVersion
52
59
  };
53
60
  });
54
61
  }
62
+ exports.updateExpoPlistAsync = updateExpoPlistAsync;
55
63
  //#region Internals
56
64
  async function updateBinaryPlistAsync(plistPath, options, updater) {
57
- await spawnAsync('plutil', ['-convert', 'xml1', plistPath], {
65
+ await (0, spawn_async_1.default)('plutil', ['-convert', 'xml1', plistPath], {
58
66
  stdio: options.verbose ? 'inherit' : 'ignore',
59
67
  });
60
- const contents = await fs.readFile(plistPath, 'utf8');
61
- const data = await plist.parse(contents);
68
+ const contents = await promises_1.default.readFile(plistPath, 'utf8');
69
+ const data = await plist_1.default.parse(contents);
62
70
  const updatedData = updater(data);
63
- const updatedContents = plist.build(updatedData);
64
- await fs.writeFile(plistPath, updatedContents);
65
- await spawnAsync('plutil', ['-convert', 'binary1', plistPath], {
71
+ const updatedContents = plist_1.default.build(updatedData);
72
+ await promises_1.default.writeFile(plistPath, updatedContents);
73
+ await (0, spawn_async_1.default)('plutil', ['-convert', 'binary1', plistPath], {
66
74
  stdio: options.verbose ? 'inherit' : 'ignore',
67
75
  });
68
76
  }
package/build/log.js CHANGED
@@ -1,20 +1,31 @@
1
- import pico from 'picocolors';
2
- export function log(...message) {
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.timeEnd = exports.time = exports.error = exports.warn = exports.log = void 0;
7
+ const picocolors_1 = __importDefault(require("picocolors"));
8
+ function log(...message) {
3
9
  console.log(...message);
4
10
  }
5
- export function warn(...message) {
6
- console.warn(...message.map((value) => pico.yellow(value)));
11
+ exports.log = log;
12
+ function warn(...message) {
13
+ console.warn(...message.map((value) => picocolors_1.default.yellow(value)));
7
14
  }
8
- export function error(...message) {
15
+ exports.warn = warn;
16
+ function error(...message) {
9
17
  console.error(...message);
10
18
  }
11
- export function time(label) {
19
+ exports.error = error;
20
+ function time(label) {
12
21
  console.time(label);
13
22
  }
14
- export function timeEnd(label) {
23
+ exports.time = time;
24
+ function timeEnd(label) {
15
25
  console.timeEnd(label);
16
26
  }
17
- export default {
27
+ exports.timeEnd = timeEnd;
28
+ exports.default = {
18
29
  log,
19
30
  warn,
20
31
  error,
package/build/types.d.ts CHANGED
@@ -37,6 +37,10 @@ export interface Options {
37
37
  * The options for signing the ios app.
38
38
  */
39
39
  iosSigningOptions?: IosSigningOptions;
40
+ /**
41
+ * Skip the working directory cleanup.
42
+ */
43
+ skipWorkingDirCleanup?: boolean;
40
44
  }
41
45
  export interface NormalizedOptions extends Options {
42
46
  workingDirectory: NonNullable<Options['workingDirectory']>;
package/build/types.js CHANGED
@@ -1 +1,2 @@
1
- export {};
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/build/utils.js CHANGED
@@ -1,27 +1,36 @@
1
- import assert from 'node:assert';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
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.normalizeOptionAsync = exports.requireNotNull = exports.directoryExistsAsync = void 0;
7
+ const node_assert_1 = __importDefault(require("node:assert"));
8
+ const promises_1 = __importDefault(require("node:fs/promises"));
9
+ const node_path_1 = __importDefault(require("node:path"));
4
10
  /**
5
11
  * Check if a directory exists.
6
12
  */
7
- export async function directoryExistsAsync(file) {
8
- return (await fs.stat(file).catch(() => null))?.isDirectory() ?? false;
13
+ async function directoryExistsAsync(file) {
14
+ return (await promises_1.default.stat(file).catch(() => null))?.isDirectory() ?? false;
9
15
  }
16
+ exports.directoryExistsAsync = directoryExistsAsync;
10
17
  /**
11
18
  * Return the non-null value.
12
19
  */
13
- export function requireNotNull(value) {
14
- assert(value != null, 'Expected value to be non-null');
20
+ function requireNotNull(value) {
21
+ (0, node_assert_1.default)(value != null, 'Expected value to be non-null');
15
22
  return value;
16
23
  }
24
+ exports.requireNotNull = requireNotNull;
17
25
  /**
18
26
  * Normalize the options.
19
27
  */
20
- export async function normalizeOptionAsync(options) {
28
+ async function normalizeOptionAsync(options) {
21
29
  const fileExt = options.platform === 'android' ? '.apk' : '.ipa';
22
30
  return {
23
31
  ...options,
24
- workingDirectory: options.workingDirectory ?? (await fs.mkdtemp(path.join(require('temp-dir'), 'repack-app-'))),
25
- outputPath: options.outputPath ?? path.join(options.projectRoot, `repacked${fileExt}`),
32
+ workingDirectory: options.workingDirectory ?? (await promises_1.default.mkdtemp(node_path_1.default.join(require('temp-dir'), 'repack-app-'))),
33
+ outputPath: options.outputPath ?? node_path_1.default.join(options.projectRoot, `repacked${fileExt}`),
26
34
  };
27
35
  }
36
+ exports.normalizeOptionAsync = normalizeOptionAsync;
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@expo/repack-app",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Repacking tool for Expo apps",
5
5
  "main": "build/index.js",
6
- "module": "build/index.js",
7
6
  "types": "build/index.d.ts",
8
- "type": "module",
7
+ "type": "commonjs",
9
8
  "scripts": {
10
9
  "build": "expo-module build",
11
10
  "clean": "expo-module clean",
@@ -27,7 +26,7 @@
27
26
  "license": "BUSL-1.1",
28
27
  "dependencies": {
29
28
  "@expo/config": "^8.5.6",
30
- "@expo/turtle-spawn": "^1.0.57",
29
+ "@expo/spawn-async": "^1.7.2",
31
30
  "commander": "^12.0.0",
32
31
  "glob": "^10.3.12",
33
32
  "picocolors": "^1.0.0",
@@ -40,5 +39,8 @@
40
39
  "eslint": "^8.57.0",
41
40
  "expo-module-scripts": "^3.4.2",
42
41
  "typescript": "^5.4.5"
42
+ },
43
+ "volta": {
44
+ "node": "22.1.0"
43
45
  }
44
46
  }