@expo/repack-app 0.1.5 → 0.1.6
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/build/android/apktool.js +11 -7
- package/build/android/build-tools.js +1 -0
- package/build/android/index.js +9 -1
- package/build/expo.d.ts +4 -0
- package/build/expo.js +18 -1
- package/build/ios/index.js +13 -2
- package/package.json +1 -1
package/build/android/apktool.js
CHANGED
|
@@ -73,7 +73,7 @@ async function getApktoolPathAsync() {
|
|
|
73
73
|
}
|
|
74
74
|
return cachedApktoolPath;
|
|
75
75
|
}
|
|
76
|
-
async function addApktoolResourceAsync(decodedApkRoot,
|
|
76
|
+
async function addApktoolResourceAsync(decodedApkRoot, assetMap) {
|
|
77
77
|
const apktoolPublicXmlPath = node_path_1.default.join(decodedApkRoot, 'res/values/public.xml');
|
|
78
78
|
// [0] Retrieve the current max resource ID and the existing drawable names
|
|
79
79
|
const contents = await promises_1.default.readFile(apktoolPublicXmlPath, 'utf8');
|
|
@@ -104,8 +104,12 @@ async function addApktoolResourceAsync(decodedApkRoot, assetSet) {
|
|
|
104
104
|
}
|
|
105
105
|
const drawableResIdBoundary = (maxDrawableResId & 0xffff0000) + 0x10000;
|
|
106
106
|
const rawResIdBoundary = (maxRawResId & 0xffff0000) + 0x10000;
|
|
107
|
-
const
|
|
108
|
-
for (const
|
|
107
|
+
const newAssetNameSet = new Set([...assetMap.keys()].filter((name) => !existingNameSet.has(name)));
|
|
108
|
+
for (const assetName of newAssetNameSet) {
|
|
109
|
+
const asset = assetMap.get(assetName);
|
|
110
|
+
if (asset == null) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
109
113
|
if (asset.type === 'drawable') {
|
|
110
114
|
maxDrawableResId += 1;
|
|
111
115
|
(0, node_assert_1.default)(maxDrawableResId < drawableResIdBoundary, 'Drawable resource ID boundary exceeded.');
|
|
@@ -143,7 +147,7 @@ function getAssetType(name) {
|
|
|
143
147
|
* @param level The current depth level (starts at 0).
|
|
144
148
|
* @param maxLevel The maximum depth level to process.
|
|
145
149
|
*/
|
|
146
|
-
async function copyAssetsAsync(src, dest, level = 0, maxLevel = 2, assetType = undefined,
|
|
150
|
+
async function copyAssetsAsync(src, dest, level = 0, maxLevel = 2, assetType = undefined, assetMap = new Map()) {
|
|
147
151
|
await promises_1.default.mkdir(dest, { recursive: true });
|
|
148
152
|
const entries = await promises_1.default.readdir(src, { withFileTypes: true });
|
|
149
153
|
await Promise.all(entries.map(async (entry) => {
|
|
@@ -152,7 +156,7 @@ async function copyAssetsAsync(src, dest, level = 0, maxLevel = 2, assetType = u
|
|
|
152
156
|
if (entry.isDirectory()) {
|
|
153
157
|
const _assetType = assetType ?? getAssetType(entry.name);
|
|
154
158
|
if (level < maxLevel - 1) {
|
|
155
|
-
await copyAssetsAsync(srcPath, destPath, level + 1, maxLevel, _assetType,
|
|
159
|
+
await copyAssetsAsync(srcPath, destPath, level + 1, maxLevel, _assetType, assetMap);
|
|
156
160
|
}
|
|
157
161
|
else {
|
|
158
162
|
// When the maximum level is reached, copy the directory without further recursion
|
|
@@ -163,9 +167,9 @@ async function copyAssetsAsync(src, dest, level = 0, maxLevel = 2, assetType = u
|
|
|
163
167
|
await promises_1.default.copyFile(srcPath, destPath);
|
|
164
168
|
const { name } = node_path_1.default.parse(entry.name);
|
|
165
169
|
(0, node_assert_1.default)(assetType, 'Asset type must be defined.');
|
|
166
|
-
|
|
170
|
+
assetMap.set(name, { name, type: assetType });
|
|
167
171
|
}
|
|
168
172
|
}));
|
|
169
|
-
return
|
|
173
|
+
return assetMap;
|
|
170
174
|
}
|
|
171
175
|
//#endregion Internals
|
|
@@ -105,6 +105,7 @@ async function searchDexClassesAsync(unzipApkRoot, grepAppIdPattern, options) {
|
|
|
105
105
|
const { stdout } = await spawnAsync(dexdumpPath, ['classes*.dex', '|', 'grep', grepPattern], {
|
|
106
106
|
cwd: unzipApkRoot,
|
|
107
107
|
shell: true,
|
|
108
|
+
stdio: 'pipe',
|
|
108
109
|
});
|
|
109
110
|
const classes = stdout
|
|
110
111
|
.split('\n')
|
package/build/android/index.js
CHANGED
|
@@ -26,7 +26,8 @@ async function repackAppAndroidAsync(_options) {
|
|
|
26
26
|
});
|
|
27
27
|
const decodedApkRoot = await (0, apktool_1.decodeApkAsync)(node_path_1.default.resolve(options.sourceAppPath), options);
|
|
28
28
|
(0, node_assert_1.default)(exp.android?.package, 'Expected app ID (`android.package`) to be defined in app.json');
|
|
29
|
-
const
|
|
29
|
+
const useExpoUpdates = (0, expo_1.isExpoUpdatesInstalled)(options.projectRoot);
|
|
30
|
+
const updatesRuntimeVersion = useExpoUpdates
|
|
30
31
|
? await (0, expo_1.resolveRuntimeVersionAsync)(options, exp)
|
|
31
32
|
: null;
|
|
32
33
|
logger.info(picocolors_1.default.dim(`Resolved runtime version: ${updatesRuntimeVersion}`));
|
|
@@ -41,6 +42,13 @@ async function repackAppAndroidAsync(_options) {
|
|
|
41
42
|
bundleOutputPath,
|
|
42
43
|
});
|
|
43
44
|
logger.timeEnd(`Adding bundled resources`);
|
|
45
|
+
if (useExpoUpdates) {
|
|
46
|
+
logger.time(`Generating 'app.manifest' for expo-updates`);
|
|
47
|
+
const updateManifestFile = await (0, expo_1.generateUpdatesEmbeddedManifestAsync)(options);
|
|
48
|
+
const updateDirectory = node_path_1.default.join(decodedApkRoot, 'assets');
|
|
49
|
+
await promises_1.default.copyFile(updateManifestFile, node_path_1.default.join(updateDirectory, node_path_1.default.basename(updateManifestFile)));
|
|
50
|
+
logger.timeEnd(`Generating 'app.manifest' for expo-updates`);
|
|
51
|
+
}
|
|
44
52
|
}
|
|
45
53
|
logger.time(`Updating Androidmanifest.xml`);
|
|
46
54
|
const androidManiestFilePath = node_path_1.default.join(decodedApkRoot, 'AndroidManifest.xml');
|
package/build/expo.d.ts
CHANGED
|
@@ -4,6 +4,10 @@ import type { NormalizedOptions } from './types';
|
|
|
4
4
|
* Generate the app.config file for the Android app.
|
|
5
5
|
*/
|
|
6
6
|
export declare function generateAppConfigAsync(options: NormalizedOptions, config: ExpoConfig): Promise<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Generate the embedded `app.manifest` for expo-updates
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateUpdatesEmbeddedManifestAsync(options: NormalizedOptions): Promise<string>;
|
|
7
11
|
/**
|
|
8
12
|
* Returns whether expo-updates is installed in the project.
|
|
9
13
|
*/
|
package/build/expo.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.generateAppConfigAsync = generateAppConfigAsync;
|
|
7
|
+
exports.generateUpdatesEmbeddedManifestAsync = generateUpdatesEmbeddedManifestAsync;
|
|
7
8
|
exports.isExpoUpdatesInstalled = isExpoUpdatesInstalled;
|
|
8
9
|
exports.resolveRuntimeVersionAsync = resolveRuntimeVersionAsync;
|
|
9
10
|
exports.getExpoConfig = getExpoConfig;
|
|
@@ -21,6 +22,21 @@ async function generateAppConfigAsync(options, config) {
|
|
|
21
22
|
await promises_1.default.writeFile(appConfigPath, JSON.stringify(config));
|
|
22
23
|
return appConfigPath;
|
|
23
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate the embedded `app.manifest` for expo-updates
|
|
27
|
+
*/
|
|
28
|
+
async function generateUpdatesEmbeddedManifestAsync(options) {
|
|
29
|
+
const { platform, projectRoot, spawnAsync, workingDirectory } = options;
|
|
30
|
+
// [0] Resolve entry point
|
|
31
|
+
const { stdout: entryFile } = await spawnAsync('node', ['-e', "require('expo/scripts/resolveAppEntry')", projectRoot, platform, 'absolute'], { cwd: projectRoot, stdio: 'pipe' });
|
|
32
|
+
// [1] Generate the `app.manifest` file
|
|
33
|
+
const binPath = resolve_from_1.default.silent(options.projectRoot, 'expo-updates/utils/build/createUpdatesResources.js');
|
|
34
|
+
(0, node_assert_1.default)(binPath, 'Failed to resolve `createUpdatesResources.js` within expo-updates package');
|
|
35
|
+
await spawnAsync('node', [binPath, platform, projectRoot, workingDirectory, 'all', entryFile.trim()], {
|
|
36
|
+
cwd: projectRoot,
|
|
37
|
+
});
|
|
38
|
+
return node_path_1.default.join(workingDirectory, 'app.manifest');
|
|
39
|
+
}
|
|
24
40
|
/**
|
|
25
41
|
* Returns whether expo-updates is installed in the project.
|
|
26
42
|
*/
|
|
@@ -40,6 +56,7 @@ async function resolveRuntimeVersionAsync(options, config) {
|
|
|
40
56
|
(0, resolve_from_1.default)(projectRoot, 'expo-updates/bin/cli.js');
|
|
41
57
|
const { stdout } = await spawnAsync(cli, ['runtimeversion:resolve', '--platform', 'android', '--workflow', 'managed'], {
|
|
42
58
|
cwd: projectRoot,
|
|
59
|
+
stdio: 'pipe',
|
|
43
60
|
});
|
|
44
61
|
const runtimeVersion = JSON.parse(stdout).runtimeVersion;
|
|
45
62
|
return runtimeVersion ?? config.version ?? '1.0.0';
|
|
@@ -72,7 +89,7 @@ async function generateBundleAssetsAsync(expoConfig, options) {
|
|
|
72
89
|
const bundleAssetRoot = node_path_1.default.resolve(workingDirectory, 'bundles');
|
|
73
90
|
await promises_1.default.mkdir(bundleAssetRoot, { recursive: true });
|
|
74
91
|
// [0] Resolve entry point
|
|
75
|
-
const { stdout: entryFile } = await spawnAsync('node', ['-e', "require('expo/scripts/resolveAppEntry')", projectRoot, platform, 'absolute'], { cwd: projectRoot });
|
|
92
|
+
const { stdout: entryFile } = await spawnAsync('node', ['-e', "require('expo/scripts/resolveAppEntry')", projectRoot, platform, 'absolute'], { cwd: projectRoot, stdio: 'pipe' });
|
|
76
93
|
// [1] Execute export:embed
|
|
77
94
|
const isEnableHermes = isEnableHermesManaged(expoConfig, platform);
|
|
78
95
|
const bundleFileName = platform === 'android' ? 'index.android.bundle' : 'main.bundle';
|
package/build/ios/index.js
CHANGED
|
@@ -25,10 +25,13 @@ async function repackAppIosAsync(_options) {
|
|
|
25
25
|
skipSDKVersionRequirement: true,
|
|
26
26
|
});
|
|
27
27
|
(0, node_assert_1.default)(exp.ios?.bundleIdentifier, 'Expected app ID (`ios.bundleIdentifier`) to be defined in app.json');
|
|
28
|
-
const
|
|
28
|
+
const useExpoUpdates = (0, expo_1.isExpoUpdatesInstalled)(options.projectRoot);
|
|
29
|
+
const updatesRuntimeVersion = useExpoUpdates
|
|
29
30
|
? await (0, expo_1.resolveRuntimeVersionAsync)(options, exp)
|
|
30
31
|
: null;
|
|
31
|
-
|
|
32
|
+
if (useExpoUpdates) {
|
|
33
|
+
logger.info(picocolors_1.default.dim(`Resolved runtime version: ${updatesRuntimeVersion}`));
|
|
34
|
+
}
|
|
32
35
|
logger.time(`Extracting artifact from ${options.sourceAppPath}`);
|
|
33
36
|
let appWorkingDirectory = await (0, build_tools_1.extractIosArtifactAsync)(options);
|
|
34
37
|
appWorkingDirectory = await (0, build_tools_1.updateFilesAsync)(exp, appWorkingDirectory);
|
|
@@ -46,6 +49,14 @@ async function repackAppIosAsync(_options) {
|
|
|
46
49
|
bundleOutputPath,
|
|
47
50
|
});
|
|
48
51
|
logger.timeEnd(`Adding bundled resources`);
|
|
52
|
+
if (useExpoUpdates) {
|
|
53
|
+
logger.time(`Generating 'app.manifest' for expo-updates`);
|
|
54
|
+
const updateManifestFile = await (0, expo_1.generateUpdatesEmbeddedManifestAsync)(options);
|
|
55
|
+
const updateDirectory = node_path_1.default.join(appWorkingDirectory, 'EXUpdates.bundle');
|
|
56
|
+
(0, node_assert_1.default)(await (0, utils_1.directoryExistsAsync)(updateDirectory), 'Expected EXUpdates.bundle directory to exist');
|
|
57
|
+
await promises_1.default.copyFile(updateManifestFile, node_path_1.default.join(updateDirectory, node_path_1.default.basename(updateManifestFile)));
|
|
58
|
+
logger.timeEnd(`Generating 'app.manifest' for expo-updates`);
|
|
59
|
+
}
|
|
49
60
|
}
|
|
50
61
|
logger.time(`Updating Info.plist`);
|
|
51
62
|
await (0, resources_1.updateInfoPlistAsync)({ config: exp, infoPlistPath, originalAppId, options });
|