@expo-harmony/cli 55.0.26-harmony.1 → 55.0.26-harmony.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -38
- package/build/args.d.ts +19 -0
- package/build/args.js +27 -0
- package/build/bin/expo-harmony.d.ts +2 -0
- package/build/bin/expo-harmony.js +1 -1
- package/build/buildHap/build.d.ts +18 -0
- package/build/buildHap/build.js +38 -0
- package/build/buildHap/index.d.ts +2 -0
- package/build/buildHap/index.js +19 -0
- package/build/buildHap/options.d.ts +7 -0
- package/build/buildHap/options.js +30 -0
- package/build/cli.d.ts +3 -0
- package/build/cli.js +40 -0
- package/build/command.d.ts +9 -0
- package/build/command.js +20 -0
- package/build/development/manifest.d.ts +1 -0
- package/build/development/manifest.js +121 -0
- package/build/development/protocol.d.ts +3 -0
- package/build/development/protocol.js +33 -0
- package/build/development/session.d.ts +5 -0
- package/build/development/session.js +66 -0
- package/build/doctor/doctor.d.ts +20 -0
- package/build/doctor/doctor.js +226 -0
- package/build/doctor/index.d.ts +2 -0
- package/build/doctor/index.js +16 -0
- package/build/doctor/options.d.ts +5 -0
- package/build/doctor/options.js +15 -0
- package/build/entry.d.ts +2 -0
- package/build/entry.js +47 -0
- package/build/errors.d.ts +12 -0
- package/build/errors.js +16 -0
- package/build/expo.d.ts +19 -0
- package/build/expo.js +53 -0
- package/build/exportEmbed/export.d.ts +18 -0
- package/build/exportEmbed/export.js +124 -0
- package/build/exportEmbed/index.d.ts +2 -0
- package/build/exportEmbed/index.js +19 -0
- package/build/exportEmbed/manifest.d.ts +44 -0
- package/build/exportEmbed/manifest.js +171 -0
- package/build/exportEmbed/options.d.ts +7 -0
- package/build/exportEmbed/options.js +22 -0
- package/build/file.d.ts +10 -0
- package/build/file.js +110 -0
- package/build/help.d.ts +1 -0
- package/build/help.js +44 -0
- package/build/index.d.ts +14 -0
- package/build/index.js +6 -5
- package/build/internal/development.d.ts +1 -0
- package/build/internal/development.js +8 -0
- package/build/internal/export.d.ts +1 -0
- package/build/internal/export.js +80 -0
- package/build/internal/prebuild.d.ts +3 -0
- package/build/internal/prebuild.js +9 -0
- package/build/log.d.ts +4 -0
- package/build/log.js +6 -0
- package/build/modules/index.d.ts +2 -0
- package/build/modules/index.js +16 -0
- package/build/modules/modules.d.ts +42 -0
- package/build/modules/modules.js +84 -0
- package/build/modules/options.d.ts +10 -0
- package/build/modules/options.js +45 -0
- package/build/native/bare.d.ts +4 -0
- package/build/native/bare.js +130 -0
- package/build/native/build.d.ts +15 -0
- package/build/native/build.js +69 -0
- package/build/native/cache.d.ts +11 -0
- package/build/native/cache.js +73 -0
- package/build/native/hvigor.d.ts +3 -0
- package/build/native/hvigor.js +83 -0
- package/build/native/install.d.ts +5 -0
- package/build/native/install.js +13 -0
- package/build/native/prepareProject.d.ts +11 -0
- package/build/native/prepareProject.js +68 -0
- package/build/native/project.d.ts +8 -0
- package/build/native/project.js +58 -0
- package/build/native/toolchain.d.ts +16 -0
- package/build/native/toolchain.js +172 -0
- package/build/native/types.d.ts +47 -0
- package/build/native/types.js +2 -0
- package/build/path.d.ts +4 -0
- package/build/path.js +27 -0
- package/build/prebuild/check.d.ts +10 -0
- package/build/prebuild/check.js +151 -0
- package/build/prebuild/clean.d.ts +2 -0
- package/build/prebuild/clean.js +50 -0
- package/build/prebuild/index.d.ts +2 -0
- package/build/prebuild/index.js +51 -0
- package/build/prebuild/options.d.ts +10 -0
- package/build/prebuild/options.js +50 -0
- package/build/prebuild/prebuild.d.ts +6 -0
- package/build/prebuild/prebuild.js +70 -0
- package/build/prebuild/template.d.ts +8 -0
- package/build/prebuild/template.js +86 -0
- package/build/process.d.ts +41 -0
- package/build/process.js +324 -0
- package/build/profile.d.ts +1 -0
- package/build/profile.js +12 -0
- package/build/project.d.ts +2 -0
- package/build/project.js +23 -0
- package/build/projectLock.d.ts +2 -0
- package/build/projectLock.js +185 -0
- package/build/run/devices.d.ts +29 -0
- package/build/run/devices.js +223 -0
- package/build/run/emulators.d.ts +13 -0
- package/build/run/emulators.js +82 -0
- package/build/run/index.d.ts +2 -0
- package/build/run/index.js +25 -0
- package/build/run/metro.d.ts +21 -0
- package/build/run/metro.js +162 -0
- package/build/run/options.d.ts +14 -0
- package/build/run/options.js +62 -0
- package/build/run/run.d.ts +46 -0
- package/build/run/run.js +135 -0
- package/build/runtime/config.d.ts +37 -0
- package/build/runtime/config.js +169 -0
- package/build/runtime/contract.d.ts +5 -0
- package/build/runtime/contract.js +109 -0
- package/build/runtime/fingerprint.d.ts +1 -0
- package/build/runtime/fingerprint.js +49 -0
- package/build/runtime/index.d.ts +2 -0
- package/build/runtime/index.js +50 -0
- package/build/start/index.d.ts +2 -0
- package/build/start/index.js +38 -0
- package/build/start/options.d.ts +9 -0
- package/build/start/options.js +38 -0
- package/build/updates/export.d.ts +14 -0
- package/build/updates/export.js +46 -0
- package/build/updates/index.d.ts +2 -0
- package/build/updates/index.js +96 -0
- package/build/upstream.d.ts +9 -0
- package/build/upstream.js +17 -0
- package/package.json +21 -5
- package/src/bin/expo-harmony.ts +2 -2
- package/src/buildHap/build.ts +13 -105
- package/src/buildHap/index.ts +19 -0
- package/src/cli.ts +27 -225
- package/src/command.ts +24 -0
- package/src/development/manifest.ts +127 -0
- package/src/development/protocol.ts +42 -0
- package/src/development/session.ts +83 -0
- package/src/doctor/doctor.ts +67 -62
- package/src/doctor/index.ts +16 -0
- package/src/exportEmbed/export.ts +73 -72
- package/src/exportEmbed/index.ts +17 -0
- package/src/file.ts +20 -11
- package/src/help.ts +41 -0
- package/src/index.ts +5 -3
- package/src/internal/development.ts +8 -0
- package/src/internal/export.ts +82 -0
- package/src/internal/prebuild.ts +3 -0
- package/src/log.ts +5 -0
- package/src/modules/index.ts +16 -0
- package/src/native/bare.ts +145 -0
- package/src/native/build.ts +83 -0
- package/src/{run → native}/cache.ts +10 -9
- package/src/native/hvigor.ts +88 -0
- package/src/native/install.ts +17 -0
- package/src/native/prepareProject.ts +99 -0
- package/src/native/project.ts +88 -0
- package/src/{tools.ts → native/toolchain.ts} +38 -140
- package/src/native/types.ts +44 -0
- package/src/prebuild/check.ts +56 -31
- package/src/prebuild/clean.ts +3 -3
- package/src/prebuild/index.ts +56 -0
- package/src/prebuild/prebuild.ts +11 -1
- package/src/prebuild/template.ts +2 -2
- package/src/process.ts +175 -64
- package/src/profile.ts +13 -0
- package/src/projectLock.ts +9 -1
- package/src/run/devices.ts +24 -11
- package/src/run/emulators.ts +4 -6
- package/src/run/index.ts +25 -0
- package/src/run/metro.ts +10 -1
- package/src/run/options.ts +2 -0
- package/src/run/run.ts +63 -129
- package/src/runtime/config.ts +207 -0
- package/src/runtime/contract.ts +167 -0
- package/src/runtime/fingerprint.ts +49 -0
- package/src/runtime/index.ts +54 -0
- package/src/start/index.ts +37 -0
- package/src/start/options.ts +12 -0
- package/src/updates/export.ts +60 -0
- package/src/updates/index.ts +89 -0
- package/src/buildHap/common.ts +0 -145
- package/src/run/install.ts +0 -41
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseStartArgs = parseStartArgs;
|
|
4
|
+
const args_1 = require("../args");
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
const StartOptions = {
|
|
7
|
+
...args_1.CommonOptions,
|
|
8
|
+
'clear': { short: 'c', type: 'boolean' },
|
|
9
|
+
'host': { type: 'string' },
|
|
10
|
+
'port': { type: 'string' },
|
|
11
|
+
'private-key-path': { type: 'string' },
|
|
12
|
+
'reset-cache': { type: 'boolean' },
|
|
13
|
+
};
|
|
14
|
+
function parseStartArgs(argv) {
|
|
15
|
+
const { positionals, values } = (0, args_1.parseArgs)(StartOptions, argv);
|
|
16
|
+
if (positionals.length > 1) {
|
|
17
|
+
throw new errors_1.HarmonyCliError('ERR_HARMONY_CONFIG_INVALID', `Unexpected start positional argument: ${positionals[1]}`, {
|
|
18
|
+
operation: 'parse-arguments',
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const port = values.port === undefined ? 8081 : Number(values.port);
|
|
22
|
+
if (!Number.isInteger(port) || port < 1 || port > 65_535) {
|
|
23
|
+
throw new errors_1.HarmonyCliError('ERR_HARMONY_CONFIG_INVALID', '--port must be an integer between 1 and 65535.', {
|
|
24
|
+
operation: 'parse-arguments',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
if (values.host !== undefined && !/^[A-Za-z0-9.-]+$/.test(values.host)) {
|
|
28
|
+
throw new errors_1.HarmonyCliError('ERR_HARMONY_CONFIG_INVALID', '--host must be a hostname or IPv4 address without a port or scheme.', { operation: 'parse-arguments' });
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
help: Boolean(values.help),
|
|
32
|
+
host: values.host,
|
|
33
|
+
port,
|
|
34
|
+
privateKeyPath: values['private-key-path'],
|
|
35
|
+
project: positionals[0],
|
|
36
|
+
resetCache: Boolean(values['reset-cache'] || values.clear),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ExpoConfigWithHarmony } from '@expo-harmony/config-plugins';
|
|
2
|
+
export interface UpdateAsset {
|
|
3
|
+
key: string;
|
|
4
|
+
hash: string;
|
|
5
|
+
contentType: string;
|
|
6
|
+
fileExtension: string;
|
|
7
|
+
embeddedAssetFilename: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function publishUpdatesConfigurationAsync(root: string, directory: string, config: ExpoConfigWithHarmony, runtime: string): Promise<void>;
|
|
10
|
+
export declare function publishEmbeddedUpdateAsync(root: string, paths: {
|
|
11
|
+
rawfileRoot: string;
|
|
12
|
+
bundle: string;
|
|
13
|
+
metadataRoot: string;
|
|
14
|
+
}, assets: UpdateAsset[]): Promise<void>;
|
|
@@ -0,0 +1,46 @@
|
|
|
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.publishUpdatesConfigurationAsync = publishUpdatesConfigurationAsync;
|
|
7
|
+
exports.publishEmbeddedUpdateAsync = publishEmbeddedUpdateAsync;
|
|
8
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
9
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const file_1 = require("../file");
|
|
12
|
+
const errors_1 = require("../errors");
|
|
13
|
+
const config_1 = require("../runtime/config");
|
|
14
|
+
async function publishUpdatesConfigurationAsync(root, directory, config, runtime) {
|
|
15
|
+
const updates = { ...config.updates, runtimeVersion: runtime };
|
|
16
|
+
if (updates.url) {
|
|
17
|
+
const url = new URL(updates.url);
|
|
18
|
+
if (!['http:', 'https:'].includes(url.protocol))
|
|
19
|
+
throw new errors_1.HarmonyCliError('ERR_HARMONY_UPDATES_CONFIG', 'Updates URL must use HTTP or HTTPS.', { operation: 'updates-config' });
|
|
20
|
+
}
|
|
21
|
+
if (updates.codeSigningCertificate) {
|
|
22
|
+
const certificate = await promises_1.default.readFile(node_path_1.default.resolve(root, updates.codeSigningCertificate), 'utf8');
|
|
23
|
+
new node_crypto_1.default.X509Certificate(certificate);
|
|
24
|
+
updates.codeSigningCertificate = certificate;
|
|
25
|
+
}
|
|
26
|
+
await (0, file_1.atomicWriteJson)(updates, node_path_1.default.join(directory, 'expo-updates/config.json'), directory);
|
|
27
|
+
}
|
|
28
|
+
async function publishEmbeddedUpdateAsync(root, paths, assets) {
|
|
29
|
+
const project = await (0, config_1.readProjectRuntimeAsync)(root);
|
|
30
|
+
const bundle = await promises_1.default.readFile(paths.bundle);
|
|
31
|
+
const hash = node_crypto_1.default.createHash('sha256').update(Uint8Array.from(bundle)).digest('base64url');
|
|
32
|
+
const directory = node_path_1.default.join(paths.rawfileRoot, 'expo-updates');
|
|
33
|
+
const id = node_crypto_1.default.randomUUID();
|
|
34
|
+
const manifest = {
|
|
35
|
+
id, commitTime: Date.now(),
|
|
36
|
+
launchAsset: { packagerHash: `bundle-${id}`, hash, type: 'hbc',
|
|
37
|
+
embeddedAssetFilename: node_path_1.default.relative(paths.rawfileRoot, paths.bundle).split(node_path_1.default.sep).join('/') },
|
|
38
|
+
assets: [...new Map(assets.map(asset => [asset.key, asset])).values()].map(asset => ({
|
|
39
|
+
packagerHash: asset.key, hash: asset.hash, type: asset.fileExtension.replace(/^\./, ''),
|
|
40
|
+
embeddedAssetFilename: asset.embeddedAssetFilename,
|
|
41
|
+
})),
|
|
42
|
+
};
|
|
43
|
+
await publishUpdatesConfigurationAsync(root, paths.rawfileRoot, project.config, project.runtimeVersion);
|
|
44
|
+
await (0, file_1.atomicWriteJson)(manifest, node_path_1.default.join(directory, 'manifest.json'), paths.rawfileRoot);
|
|
45
|
+
await (0, file_1.atomicWriteJson)(manifest, node_path_1.default.join(paths.metadataRoot, 'update.json'), paths.metadataRoot);
|
|
46
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
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.command = void 0;
|
|
7
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
8
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
9
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
10
|
+
const node_module_1 = require("node:module");
|
|
11
|
+
const config_1 = require("@expo/config");
|
|
12
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
13
|
+
const args_1 = require("../args");
|
|
14
|
+
const command_1 = require("../command");
|
|
15
|
+
const export_1 = require("../exportEmbed/export");
|
|
16
|
+
const errors_1 = require("../errors");
|
|
17
|
+
const file_1 = require("../file");
|
|
18
|
+
const path_1 = require("../path");
|
|
19
|
+
const expo_1 = require("../expo");
|
|
20
|
+
const config_2 = require("../runtime/config");
|
|
21
|
+
const command = async (argv, io) => {
|
|
22
|
+
const args = (0, command_1.parseCommandArgs)((values) => {
|
|
23
|
+
const { values: options, positionals } = (0, args_1.parseArgs)({ ...args_1.CommonOptions,
|
|
24
|
+
'output-dir': { type: 'string' }, 'asset-url': { type: 'string' },
|
|
25
|
+
'private-key-path': { type: 'string' }, 'reset-cache': { type: 'boolean' },
|
|
26
|
+
}, values);
|
|
27
|
+
if (positionals.length > 1)
|
|
28
|
+
throw new errors_1.HarmonyCliError('ERR_HARMONY_EXPORT_ARGUMENTS', 'Expected at most one project directory.', { operation: 'export' });
|
|
29
|
+
return { ...options, project: positionals[0], help: Boolean(options.help) };
|
|
30
|
+
}, argv, io);
|
|
31
|
+
if (!args)
|
|
32
|
+
return 0;
|
|
33
|
+
const { projectRoot: root, options } = args;
|
|
34
|
+
const base = options['asset-url'];
|
|
35
|
+
if (!base || !['http:', 'https:'].includes(new URL(base).protocol)) {
|
|
36
|
+
throw new errors_1.HarmonyCliError('ERR_HARMONY_EXPORT_ARGUMENTS', 'OTA export requires --asset-url with the HTTP(S) directory that will host its assets.', { operation: 'export' });
|
|
37
|
+
}
|
|
38
|
+
const output = node_path_1.default.resolve(root, options['output-dir'] ?? 'dist');
|
|
39
|
+
const temporary = await promises_1.default.mkdtemp(node_path_1.default.join(node_os_1.default.tmpdir(), 'expo-harmony-update-'));
|
|
40
|
+
try {
|
|
41
|
+
await (0, export_1.exportEmbedAsync)(root, { outputDirectory: temporary, resetCache: options['reset-cache'] });
|
|
42
|
+
const embedded = JSON.parse(await promises_1.default.readFile(node_path_1.default.join(temporary, 'update.json'), 'utf8'));
|
|
43
|
+
const project = await (0, config_2.readProjectRuntimeAsync)(root);
|
|
44
|
+
const { exp } = (0, config_1.getConfig)(root, { isPublicConfig: true });
|
|
45
|
+
const require = (0, node_module_1.createRequire)((0, expo_1.resolveExpoCli)(root).cliPath);
|
|
46
|
+
const upstream = (0, node_module_1.createRequire)(require.resolve('@expo/cli/package.json'));
|
|
47
|
+
const mime = upstream('mime-types');
|
|
48
|
+
const assets = [embedded.launchAsset, ...embedded.assets].map(asset => ({
|
|
49
|
+
key: asset.packagerHash, hash: asset.hash,
|
|
50
|
+
contentType: asset.type === 'hbc' ? 'application/javascript' : mime.lookup(asset.type) || 'application/octet-stream',
|
|
51
|
+
fileExtension: asset.type ? '.' + asset.type : '', embeddedAssetFilename: asset.embeddedAssetFilename,
|
|
52
|
+
}));
|
|
53
|
+
const manifest = {
|
|
54
|
+
id: embedded.id, createdAt: new Date(embedded.commitTime).toISOString(), runtimeVersion: project.runtimeVersion,
|
|
55
|
+
launchAsset: assets[0], assets: assets.slice(1), metadata: {},
|
|
56
|
+
extra: { expoClient: exp, eas: { projectId: exp.extra?.eas?.projectId },
|
|
57
|
+
scopeKey: exp.originalFullName ?? `@${exp.owner ?? 'anonymous'}/${exp.slug}` },
|
|
58
|
+
};
|
|
59
|
+
const metadata = [];
|
|
60
|
+
for (const asset of assets) {
|
|
61
|
+
const relative = `assets/${asset.hash}${asset.fileExtension}`;
|
|
62
|
+
await (0, file_1.atomicCopy)(node_path_1.default.join(temporary, 'embedded', (0, path_1.assertSafeRelative)(asset.embeddedAssetFilename, 'Embedded update asset')), node_path_1.default.join(output, relative), output);
|
|
63
|
+
Object.assign(asset, { url: new URL(relative, base.endsWith('/') ? base : base + '/').href });
|
|
64
|
+
delete asset.embeddedAssetFilename;
|
|
65
|
+
if (asset !== manifest.launchAsset)
|
|
66
|
+
metadata.push({ path: relative, ext: asset.fileExtension.replace(/^\./, '') });
|
|
67
|
+
}
|
|
68
|
+
await (0, file_1.atomicCopy)(node_path_1.default.join(temporary, 'hermes_bundle.hbc.map'), node_path_1.default.join(output, 'bundle.hbc.map'), output);
|
|
69
|
+
await (0, file_1.atomicWriteJson)({ version: 0, bundler: 'metro', fileMetadata: { harmony: {
|
|
70
|
+
bundle: `assets/${manifest.launchAsset.hash}.hbc`, assets: metadata,
|
|
71
|
+
} } }, node_path_1.default.join(output, 'metadata.json'), output);
|
|
72
|
+
await (0, file_1.atomicWriteJson)(manifest, node_path_1.default.join(output, 'manifest.json'), output);
|
|
73
|
+
if (options['private-key-path']) {
|
|
74
|
+
const key = await promises_1.default.readFile(node_path_1.default.resolve(root, options['private-key-path']), 'utf8');
|
|
75
|
+
if (node_crypto_1.default.createPrivateKey(key).asymmetricKeyType !== 'rsa')
|
|
76
|
+
throw new errors_1.HarmonyCliError('ERR_HARMONY_UPDATES_SIGNING', 'Expo Updates signing requires an RSA private key.', { operation: 'export' });
|
|
77
|
+
const body = await promises_1.default.readFile(node_path_1.default.join(output, 'manifest.json'));
|
|
78
|
+
const signature = node_crypto_1.default.sign('RSA-SHA256', Uint8Array.from(body), key).toString('base64');
|
|
79
|
+
const id = exp.updates?.codeSigningMetadata?.keyid ?? 'root';
|
|
80
|
+
const { serializeDictionary } = upstream('structured-headers');
|
|
81
|
+
await promises_1.default.writeFile(node_path_1.default.join(temporary, 'signature.txt'), serializeDictionary(new Map([
|
|
82
|
+
['sig', [signature, new Map()]], ['keyid', [id, new Map()]], ['alg', ['rsa-v1_5-sha256', new Map()]],
|
|
83
|
+
])));
|
|
84
|
+
await (0, file_1.atomicCopy)(node_path_1.default.join(temporary, 'signature.txt'), node_path_1.default.join(output, 'signature.txt'), output);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
await promises_1.default.rm(node_path_1.default.join(output, 'signature.txt'), { force: true });
|
|
88
|
+
}
|
|
89
|
+
io.log(`Exported Harmony update ${manifest.id} for runtime ${manifest.runtimeVersion} to ${output}.`);
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
await promises_1.default.rm(temporary, { recursive: true, force: true });
|
|
93
|
+
}
|
|
94
|
+
return 0;
|
|
95
|
+
};
|
|
96
|
+
exports.command = command;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const ProjectPackages: Readonly<{
|
|
2
|
+
expo: "expo";
|
|
3
|
+
expoAutolinking: "@expo-harmony/expo-modules-autolinking";
|
|
4
|
+
reactNative: "react-native";
|
|
5
|
+
rnohCli: "@react-native-oh/react-native-harmony-cli";
|
|
6
|
+
rnohRuntime: "@react-native-oh/react-native-harmony";
|
|
7
|
+
}>;
|
|
8
|
+
declare const RequiredProjectPackages: readonly ("@react-native-oh/react-native-harmony" | "@expo-harmony/expo-modules-autolinking" | "@react-native-oh/react-native-harmony-cli")[];
|
|
9
|
+
export { ProjectPackages, RequiredProjectPackages, };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RequiredProjectPackages = exports.ProjectPackages = void 0;
|
|
4
|
+
const ProjectPackages = Object.freeze({
|
|
5
|
+
expo: 'expo',
|
|
6
|
+
expoAutolinking: '@expo-harmony/expo-modules-autolinking',
|
|
7
|
+
reactNative: 'react-native',
|
|
8
|
+
rnohCli: '@react-native-oh/react-native-harmony-cli',
|
|
9
|
+
rnohRuntime: '@react-native-oh/react-native-harmony',
|
|
10
|
+
});
|
|
11
|
+
exports.ProjectPackages = ProjectPackages;
|
|
12
|
+
const RequiredProjectPackages = Object.freeze([
|
|
13
|
+
ProjectPackages.rnohRuntime,
|
|
14
|
+
ProjectPackages.rnohCli,
|
|
15
|
+
ProjectPackages.expoAutolinking,
|
|
16
|
+
]);
|
|
17
|
+
exports.RequiredProjectPackages = RequiredProjectPackages;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo-harmony/cli",
|
|
3
|
-
"version": "55.0.26-harmony.
|
|
3
|
+
"version": "55.0.26-harmony.11",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"react-native",
|
|
6
6
|
"expo",
|
|
@@ -30,16 +30,32 @@
|
|
|
30
30
|
"require": "./build/index.js",
|
|
31
31
|
"default": "./build/index.js"
|
|
32
32
|
},
|
|
33
|
-
"./bin/expo-harmony": "./build/bin/expo-harmony.js"
|
|
33
|
+
"./bin/expo-harmony": "./build/bin/expo-harmony.js",
|
|
34
|
+
"./native-build": {
|
|
35
|
+
"types": "./build/native/hvigor.d.ts",
|
|
36
|
+
"require": "./build/native/hvigor.js",
|
|
37
|
+
"default": "./build/native/hvigor.js"
|
|
38
|
+
},
|
|
39
|
+
"./internal/prebuild": {
|
|
40
|
+
"types": "./build/internal/prebuild.d.ts",
|
|
41
|
+
"require": "./build/internal/prebuild.js",
|
|
42
|
+
"default": "./build/internal/prebuild.js"
|
|
43
|
+
},
|
|
44
|
+
"./internal/development": {
|
|
45
|
+
"types": "./build/internal/development.d.ts",
|
|
46
|
+
"require": "./build/internal/development.js",
|
|
47
|
+
"default": "./build/internal/development.js"
|
|
48
|
+
}
|
|
34
49
|
},
|
|
35
50
|
"bin": {
|
|
36
51
|
"expo-harmony": "build/bin/expo-harmony.js"
|
|
37
52
|
},
|
|
38
53
|
"dependencies": {
|
|
39
|
-
"@expo-harmony/config-plugins": "55.0.10-harmony.
|
|
40
|
-
"@expo-harmony/expo-modules-autolinking": "55.0.25-harmony.
|
|
41
|
-
"@expo-harmony/prebuild-config": "55.0.0-harmony.
|
|
54
|
+
"@expo-harmony/config-plugins": "55.0.10-harmony.5",
|
|
55
|
+
"@expo-harmony/expo-modules-autolinking": "55.0.25-harmony.5",
|
|
56
|
+
"@expo-harmony/prebuild-config": "55.0.0-harmony.9",
|
|
42
57
|
"@expo/config": "55.0.17",
|
|
58
|
+
"@expo/fingerprint": "0.16.7",
|
|
43
59
|
"cross-spawn": "^7.0.6",
|
|
44
60
|
"json5": "2.2.3"
|
|
45
61
|
},
|
package/src/bin/expo-harmony.ts
CHANGED
package/src/buildHap/build.ts
CHANGED
|
@@ -1,39 +1,16 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
|
|
3
|
-
import { HarmonyCliError } from '../errors';
|
|
4
|
-
import { exportEmbedAsync } from '../exportEmbed/export';
|
|
5
|
-
import type { HarmonyExportManifest } from '../exportEmbed/manifest';
|
|
6
|
-
import { toPosixPath } from '../path';
|
|
7
1
|
import { withHarmonyProjectLockAsync } from '../projectLock';
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from '../run/cache';
|
|
12
|
-
import { installHarmonyDependenciesAsync } from '../run/install';
|
|
13
|
-
import {
|
|
14
|
-
resolveHarmonyBuildPlanAsync,
|
|
15
|
-
resolveHarmonyToolchain,
|
|
16
|
-
} from '../tools';
|
|
17
|
-
import {
|
|
18
|
-
ensureGeneratedProjectAsync,
|
|
19
|
-
isNonEmptyRegularFile,
|
|
20
|
-
progress,
|
|
21
|
-
runCheckedAsync,
|
|
22
|
-
timed,
|
|
23
|
-
} from './common';
|
|
2
|
+
import { buildNativeAsync, type NativeBuildResult } from '../native/build';
|
|
3
|
+
import { prepareNativeProjectAsync } from '../native/prepareProject';
|
|
4
|
+
import { resolveHarmonyToolchain } from '../native/toolchain';
|
|
24
5
|
|
|
25
6
|
export interface HarmonyBuildOptions {
|
|
26
7
|
io?: Pick<Console, 'error' | 'log' | 'warn'>;
|
|
27
|
-
/** @internal For release verification after a successful isolated prebuild check. */
|
|
28
|
-
skipGeneratedProjectCheck?: boolean;
|
|
29
8
|
sync?: boolean;
|
|
30
9
|
variant?: 'debug' | 'release';
|
|
31
10
|
}
|
|
32
11
|
|
|
33
|
-
export interface HarmonyBuildResult {
|
|
12
|
+
export interface HarmonyBuildResult extends NativeBuildResult {
|
|
34
13
|
bundleName: string;
|
|
35
|
-
export: null | { assetCount: number; bundleSha256: string; sourceMapSha256: string };
|
|
36
|
-
hapPath: string;
|
|
37
14
|
headless: true;
|
|
38
15
|
installed: false;
|
|
39
16
|
launched: false;
|
|
@@ -48,13 +25,12 @@ type NormalizedBuildOptions = Required<HarmonyBuildOptions> & {
|
|
|
48
25
|
};
|
|
49
26
|
|
|
50
27
|
async function buildHarmonyUnlockedAsync(
|
|
51
|
-
|
|
28
|
+
root: string,
|
|
52
29
|
options: HarmonyBuildOptions = {}
|
|
53
30
|
): Promise<HarmonyBuildResult> {
|
|
54
|
-
const
|
|
31
|
+
const settings: NormalizedBuildOptions = {
|
|
55
32
|
io: options.io || console,
|
|
56
33
|
requireDeviceTools: false,
|
|
57
|
-
skipGeneratedProjectCheck: Boolean(options.skipGeneratedProjectCheck),
|
|
58
34
|
sync: Boolean(options.sync),
|
|
59
35
|
variant: options.variant || 'debug',
|
|
60
36
|
};
|
|
@@ -66,98 +42,30 @@ async function buildHarmonyUnlockedAsync(
|
|
|
66
42
|
metroPort: 0,
|
|
67
43
|
};
|
|
68
44
|
|
|
69
|
-
await
|
|
70
|
-
|
|
71
|
-
const plan = await timed(steps, 'buildPlan', () => resolveHarmonyBuildPlanAsync(
|
|
72
|
-
projectRoot,
|
|
73
|
-
{ buildMode: normalizedOptions.variant }
|
|
74
|
-
));
|
|
75
|
-
const toolchain = resolveHarmonyToolchain();
|
|
76
|
-
|
|
77
|
-
let exportManifest: HarmonyExportManifest | null = null;
|
|
78
|
-
if (normalizedOptions.variant === 'release') {
|
|
79
|
-
progress(normalizedOptions, 'Exporting the release Hermes bundle');
|
|
80
|
-
exportManifest = await timed(steps, 'export', () => exportEmbedAsync(
|
|
81
|
-
projectRoot,
|
|
82
|
-
{ skipDoctor: true }
|
|
83
|
-
));
|
|
84
|
-
} else {
|
|
85
|
-
steps.export = 0;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
progress(normalizedOptions, 'Installing Harmony project dependencies');
|
|
89
|
-
await timed(steps, 'ohpm', () => installHarmonyDependenciesAsync(plan, toolchain));
|
|
90
|
-
|
|
91
|
-
progress(normalizedOptions, 'Checking Harmony native dependency cache');
|
|
92
|
-
const nativeBuildCache = await timed(steps, 'nativeCache', () => (
|
|
93
|
-
prepareHarmonyNativeBuildCacheAsync(projectRoot, plan)
|
|
94
|
-
));
|
|
95
|
-
|
|
96
|
-
if (nativeBuildCache.changed) {
|
|
97
|
-
progress(normalizedOptions, 'Invalidated stale Harmony native build objects');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
progress(normalizedOptions, `Building the ${normalizedOptions.variant} HAP without a device`);
|
|
101
|
-
const buildEnv = {
|
|
102
|
-
...process.env,
|
|
103
|
-
EXPO_HARMONY_NODE: process.env.EXPO_HARMONY_NODE || process.execPath,
|
|
104
|
-
EXPO_METRO_TARGET: 'harmony',
|
|
105
|
-
HERMES_V1_ENABLED: 'true',
|
|
106
|
-
...(normalizedOptions.variant === 'release' ? { EXPO_HARMONY_BUNDLE_PREBUILT: '1' } : {}),
|
|
107
|
-
...(toolchain.sdkHome && !process.env.DEVECO_SDK_HOME
|
|
108
|
-
? { DEVECO_SDK_HOME: toolchain.sdkHome }
|
|
109
|
-
: {}),
|
|
110
|
-
};
|
|
111
|
-
await timed(steps, 'build', () => runCheckedAsync(toolchain.hvigor.command, [
|
|
112
|
-
...toolchain.hvigor.args,
|
|
113
|
-
...plan.hvigorArgs,
|
|
114
|
-
], {
|
|
115
|
-
code: 'ERR_HARMONY_BUILD_FAILED',
|
|
116
|
-
cwd: plan.harmonyRoot,
|
|
117
|
-
env: buildEnv,
|
|
118
|
-
message: 'Hvigor build',
|
|
119
|
-
operation: 'hvigor-build',
|
|
120
|
-
timeoutMs: 15 * 60_000,
|
|
121
|
-
}));
|
|
122
|
-
|
|
123
|
-
if (!isNonEmptyRegularFile(plan.expectedHap)) {
|
|
124
|
-
throw new HarmonyCliError(
|
|
125
|
-
'ERR_HARMONY_HAP_MISSING',
|
|
126
|
-
'Hvigor completed without producing the expected non-empty regular HAP.',
|
|
127
|
-
{ operation: 'verify-hap' }
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
await timed(steps, 'nativeCacheCommit', () => commitHarmonyNativeBuildCacheAsync(nativeBuildCache));
|
|
45
|
+
const plan = await prepareNativeProjectAsync(root, settings, steps);
|
|
46
|
+
const built = await buildNativeAsync(root, plan, resolveHarmonyToolchain(), settings, steps);
|
|
132
47
|
|
|
133
48
|
return {
|
|
134
49
|
bundleName: plan.bundleName,
|
|
135
|
-
|
|
136
|
-
? {
|
|
137
|
-
assetCount: exportManifest.assets.length,
|
|
138
|
-
bundleSha256: exportManifest.bundle.sha256,
|
|
139
|
-
sourceMapSha256: exportManifest.sourceMap.sha256,
|
|
140
|
-
}
|
|
141
|
-
: null,
|
|
142
|
-
hapPath: toPosixPath(path.relative(projectRoot, plan.expectedHap)),
|
|
50
|
+
...built,
|
|
143
51
|
headless: true,
|
|
144
52
|
installed: false,
|
|
145
53
|
launched: false,
|
|
146
54
|
ok: true,
|
|
147
55
|
schemaVersion: 1,
|
|
148
56
|
steps,
|
|
149
|
-
variant:
|
|
57
|
+
variant: settings.variant,
|
|
150
58
|
};
|
|
151
59
|
}
|
|
152
60
|
|
|
153
61
|
async function buildHarmonyAsync(
|
|
154
|
-
|
|
62
|
+
root: string,
|
|
155
63
|
options: HarmonyBuildOptions = {}
|
|
156
64
|
): Promise<HarmonyBuildResult> {
|
|
157
65
|
return withHarmonyProjectLockAsync(
|
|
158
|
-
|
|
66
|
+
root,
|
|
159
67
|
'build',
|
|
160
|
-
() => buildHarmonyUnlockedAsync(
|
|
68
|
+
() => buildHarmonyUnlockedAsync(root, options)
|
|
161
69
|
);
|
|
162
70
|
}
|
|
163
71
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { parseCommandArgs, type Command } from '../command';
|
|
2
|
+
import { parseBuildArgs } from './options';
|
|
3
|
+
|
|
4
|
+
export const command: Command = async (argv, io) => {
|
|
5
|
+
const args = parseCommandArgs(parseBuildArgs, argv, io);
|
|
6
|
+
if (!args) return 0;
|
|
7
|
+
|
|
8
|
+
const { projectRoot: root, options } = args;
|
|
9
|
+
const { buildHarmonyAsync } = await import('./build.js');
|
|
10
|
+
|
|
11
|
+
const result = await buildHarmonyAsync(root, {
|
|
12
|
+
...options,
|
|
13
|
+
io,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
io.log(`Built ${result.variant} HAP at ${result.hapPath}; no device actions were performed.`);
|
|
17
|
+
|
|
18
|
+
return 0;
|
|
19
|
+
};
|