expo-harmony-toolkit 1.7.1 → 1.7.3
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.en.md +20 -9
- package/README.md +22 -11
- package/build/core/autolinking.d.ts +10 -0
- package/build/core/autolinking.js +421 -0
- package/build/core/build/commands.d.ts +19 -0
- package/build/core/build/commands.js +61 -0
- package/build/core/build/compatibilityShims.d.ts +1 -0
- package/build/core/build/compatibilityShims.js +272 -0
- package/build/core/build/localHar.d.ts +13 -0
- package/build/core/build/localHar.js +337 -0
- package/build/core/build/reporting.d.ts +19 -0
- package/build/core/build/reporting.js +67 -0
- package/build/core/build/rnohCompatibility.d.ts +1 -0
- package/build/core/build/rnohCompatibility.js +38 -0
- package/build/core/build.d.ts +4 -12
- package/build/core/build.js +70 -762
- package/build/core/constants.d.ts +2 -1
- package/build/core/constants.js +3 -2
- package/build/core/dependencyInspection.d.ts +2 -0
- package/build/core/dependencyInspection.js +112 -0
- package/build/core/env.js +1 -1
- package/build/core/report.js +33 -10
- package/build/core/signing.d.ts +2 -0
- package/build/core/signing.js +30 -0
- package/build/core/template/capabilityRegistry.d.ts +9 -0
- package/build/core/template/capabilityRegistry.js +84 -0
- package/build/core/template/expoModulesCoreShim.d.ts +2 -0
- package/build/core/template/expoModulesCoreShim.js +279 -0
- package/build/core/template/metro.d.ts +2 -0
- package/build/core/template/metro.js +213 -0
- package/build/core/template/nativeFiles.d.ts +8 -0
- package/build/core/template/nativeFiles.js +333 -0
- package/build/core/template/renderers/camera.d.ts +4 -0
- package/build/core/template/renderers/camera.js +612 -0
- package/build/core/template/renderers/fileSystem.d.ts +4 -0
- package/build/core/template/renderers/fileSystem.js +814 -0
- package/build/core/template/renderers/imagePicker.d.ts +4 -0
- package/build/core/template/renderers/imagePicker.js +753 -0
- package/build/core/template/renderers/location.d.ts +4 -0
- package/build/core/template/renderers/location.js +836 -0
- package/build/core/template/runtimeShims.d.ts +2 -0
- package/build/core/template/runtimeShims.js +192 -0
- package/build/core/template/support.d.ts +11 -0
- package/build/core/template/support.js +108 -0
- package/build/core/template.d.ts +2 -6
- package/build/core/template.js +47 -3966
- package/build/data/capabilities.js +45 -19
- package/build/data/dependencyCatalog.js +10 -0
- package/build/data/publicDocs.d.ts +11 -0
- package/build/data/publicDocs.js +28 -0
- package/build/data/validatedMatrices.js +9 -1
- package/build/docs/render.d.ts +9 -0
- package/build/docs/render.js +248 -0
- package/build/types.d.ts +12 -0
- package/docs/cli-build.md +1 -1
- package/docs/npm-release.md +1 -0
- package/docs/official-app-shell-sample.md +2 -1
- package/docs/official-minimal-sample.md +2 -1
- package/docs/official-native-capabilities-sample.md +28 -47
- package/docs/official-ui-stack-sample.md +2 -1
- package/docs/signing-and-release.md +3 -0
- package/docs/support-matrix.md +38 -16
- package/package.json +13 -5
- package/docs/v1.5.1-acceptance.md +0 -385
- package/docs/v1.6.0-acceptance.md +0 -193
- package/docs/v1.7.0-acceptance.md +0 -111
- package/docs/v1.7.1-acceptance.md +0 -111
package/build/core/build.js
CHANGED
|
@@ -3,46 +3,63 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.renderBuildReport = void 0;
|
|
6
7
|
exports.bundleProject = bundleProject;
|
|
7
8
|
exports.buildHapProject = buildHapProject;
|
|
8
|
-
exports.renderBuildReport = renderBuildReport;
|
|
9
9
|
exports.getDesiredHarmonyScripts = getDesiredHarmonyScripts;
|
|
10
|
-
const node_child_process_1 = require("node:child_process");
|
|
11
|
-
const node_util_1 = require("node:util");
|
|
12
10
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
13
|
-
const json5_1 = __importDefault(require("json5"));
|
|
14
|
-
const os_1 = __importDefault(require("os"));
|
|
15
11
|
const path_1 = __importDefault(require("path"));
|
|
16
|
-
const constants_1 = require("./constants");
|
|
17
12
|
const env_1 = require("./env");
|
|
18
13
|
const javascriptDependencies_1 = require("./javascriptDependencies");
|
|
19
14
|
const project_1 = require("./project");
|
|
20
15
|
const template_1 = require("./template");
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
];
|
|
16
|
+
const autolinking_1 = require("./autolinking");
|
|
17
|
+
const localHar_1 = require("./build/localHar");
|
|
18
|
+
const commands_1 = require("./build/commands");
|
|
19
|
+
const reporting_1 = require("./build/reporting");
|
|
20
|
+
const rnohCompatibility_1 = require("./build/rnohCompatibility");
|
|
21
|
+
var reporting_2 = require("./build/reporting");
|
|
22
|
+
Object.defineProperty(exports, "renderBuildReport", { enumerable: true, get: function () { return reporting_2.renderBuildReport; } });
|
|
29
23
|
async function bundleProject(projectRoot, options = {}) {
|
|
30
24
|
const runtimeEnv = options.env ?? process.env;
|
|
31
|
-
const runCommand = options.runner ?? defaultCommandRunner;
|
|
25
|
+
const runCommand = options.runner ?? commands_1.defaultCommandRunner;
|
|
32
26
|
const loadedProject = await (0, project_1.loadProject)(projectRoot);
|
|
33
|
-
const bundleOutputPath =
|
|
34
|
-
const assetsDestPath =
|
|
27
|
+
const bundleOutputPath = (0, reporting_1.getBundleOutputPath)(loadedProject.projectRoot);
|
|
28
|
+
const assetsDestPath = (0, reporting_1.getAssetsOutputPath)(loadedProject.projectRoot);
|
|
35
29
|
const entryFileName = (0, template_1.resolveHarmonyBundleEntryFile)(loadedProject.packageJson);
|
|
36
30
|
const entryFilePath = path_1.default.join(loadedProject.projectRoot, entryFileName);
|
|
37
31
|
const metroConfigPath = path_1.default.join(loadedProject.projectRoot, 'metro.harmony.config.js');
|
|
38
32
|
const reactNativeCliPath = path_1.default.join(loadedProject.projectRoot, 'node_modules', 'react-native', 'cli.js');
|
|
39
33
|
const warnings = [];
|
|
40
34
|
const blockingIssues = [];
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
try {
|
|
36
|
+
const syncResult = await (0, template_1.syncProjectTemplate)(loadedProject.projectRoot, false, {
|
|
37
|
+
forceManagedPaths: template_1.BUILD_REQUIRED_MANAGED_FILE_PATHS,
|
|
38
|
+
skipJavaScriptDependencyNormalization: options.skipTemplateSync,
|
|
39
|
+
});
|
|
40
|
+
warnings.push(...syncResult.warnings);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
44
|
+
return (0, reporting_1.createBuildReport)({
|
|
45
|
+
projectRoot: loadedProject.projectRoot,
|
|
46
|
+
command: 'bundle',
|
|
47
|
+
mode: null,
|
|
48
|
+
status: 'failed',
|
|
49
|
+
entryFile: entryFilePath,
|
|
50
|
+
bundleOutputPath,
|
|
51
|
+
assetsDestPath,
|
|
52
|
+
artifactPaths: [],
|
|
53
|
+
blockingIssues: [
|
|
54
|
+
{
|
|
55
|
+
code: 'build.bundle.failed',
|
|
56
|
+
message,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
warnings,
|
|
60
|
+
steps: [],
|
|
61
|
+
});
|
|
62
|
+
}
|
|
46
63
|
if (!(await fs_extra_1.default.pathExists(reactNativeCliPath))) {
|
|
47
64
|
blockingIssues.push({
|
|
48
65
|
code: 'build.bundle.failed',
|
|
@@ -61,7 +78,7 @@ async function bundleProject(projectRoot, options = {}) {
|
|
|
61
78
|
message: 'metro.harmony.config.js is missing. Run expo-harmony init first.',
|
|
62
79
|
});
|
|
63
80
|
}
|
|
64
|
-
const initialReport = createBuildReport({
|
|
81
|
+
const initialReport = (0, reporting_1.createBuildReport)({
|
|
65
82
|
projectRoot: loadedProject.projectRoot,
|
|
66
83
|
command: 'bundle',
|
|
67
84
|
mode: null,
|
|
@@ -90,7 +107,7 @@ async function bundleProject(projectRoot, options = {}) {
|
|
|
90
107
|
}
|
|
91
108
|
catch (error) {
|
|
92
109
|
const message = error instanceof Error ? error.message : String(error);
|
|
93
|
-
return createBuildReport({
|
|
110
|
+
return (0, reporting_1.createBuildReport)({
|
|
94
111
|
projectRoot: loadedProject.projectRoot,
|
|
95
112
|
command: 'bundle',
|
|
96
113
|
mode: null,
|
|
@@ -124,17 +141,17 @@ async function bundleProject(projectRoot, options = {}) {
|
|
|
124
141
|
'--config',
|
|
125
142
|
metroConfigPath,
|
|
126
143
|
];
|
|
127
|
-
const bundleCommand = buildInvocation(process.execPath, bundleArgs);
|
|
144
|
+
const bundleCommand = (0, commands_1.buildInvocation)(process.execPath, bundleArgs);
|
|
128
145
|
try {
|
|
129
146
|
const bundleResult = await runCommand(bundleCommand.file, bundleCommand.args, {
|
|
130
147
|
cwd: loadedProject.projectRoot,
|
|
131
148
|
env: bundleEnvironment,
|
|
132
149
|
});
|
|
133
150
|
const steps = [
|
|
134
|
-
createStepReport('bundle-harmony', bundleCommand.file, bundleCommand.args, loadedProject.projectRoot, bundleResult.exitCode),
|
|
151
|
+
(0, reporting_1.createStepReport)('bundle-harmony', bundleCommand.file, bundleCommand.args, loadedProject.projectRoot, bundleResult.exitCode),
|
|
135
152
|
];
|
|
136
153
|
if (bundleResult.exitCode !== 0 || !(await fs_extra_1.default.pathExists(bundleOutputPath))) {
|
|
137
|
-
return createBuildReport({
|
|
154
|
+
return (0, reporting_1.createBuildReport)({
|
|
138
155
|
projectRoot: loadedProject.projectRoot,
|
|
139
156
|
command: 'bundle',
|
|
140
157
|
mode: null,
|
|
@@ -155,7 +172,7 @@ async function bundleProject(projectRoot, options = {}) {
|
|
|
155
172
|
steps,
|
|
156
173
|
});
|
|
157
174
|
}
|
|
158
|
-
return createBuildReport({
|
|
175
|
+
return (0, reporting_1.createBuildReport)({
|
|
159
176
|
projectRoot: loadedProject.projectRoot,
|
|
160
177
|
command: 'bundle',
|
|
161
178
|
mode: null,
|
|
@@ -175,14 +192,15 @@ async function bundleProject(projectRoot, options = {}) {
|
|
|
175
192
|
}
|
|
176
193
|
async function buildHapProject(projectRoot, options) {
|
|
177
194
|
const runtimeEnv = options.env ?? process.env;
|
|
178
|
-
const runCommand = options.runner ?? defaultCommandRunner;
|
|
195
|
+
const runCommand = options.runner ?? commands_1.defaultCommandRunner;
|
|
179
196
|
const loadedProject = await (0, project_1.loadProject)(projectRoot);
|
|
180
197
|
const envReport = await (0, env_1.buildEnvReport)(loadedProject.projectRoot, {
|
|
181
198
|
env: runtimeEnv,
|
|
182
199
|
});
|
|
200
|
+
const relevantEnvAdvisories = envReport.advisories.filter((issue) => options.mode === 'release' || issue.code !== 'env.signing.missing');
|
|
183
201
|
const warnings = [
|
|
184
202
|
...envReport.warnings.filter((warning) => !warning.startsWith('Harmony sidecar files are not present yet.')),
|
|
185
|
-
...
|
|
203
|
+
...relevantEnvAdvisories.map((issue) => `${issue.code}: ${issue.message}`),
|
|
186
204
|
];
|
|
187
205
|
const blockingIssues = [];
|
|
188
206
|
if (!envReport.hvigorPath) {
|
|
@@ -200,18 +218,18 @@ async function buildHapProject(projectRoot, options) {
|
|
|
200
218
|
if (options.mode === 'release' && !envReport.signingConfigured) {
|
|
201
219
|
blockingIssues.push({
|
|
202
220
|
code: 'env.signing.missing',
|
|
203
|
-
message: 'Release HAP builds require signingConfigs from .expo-harmony/signing.local.json or harmony/build-profile.json5.',
|
|
221
|
+
message: 'Release HAP builds require signingConfigs from .expo-harmony/signing.local.json or harmony/build-profile.json5. Start from .expo-harmony/signing.local.example.json and replace the placeholder credentials.',
|
|
204
222
|
});
|
|
205
223
|
}
|
|
206
224
|
if (blockingIssues.length > 0) {
|
|
207
|
-
return createBuildReport({
|
|
225
|
+
return (0, reporting_1.createBuildReport)({
|
|
208
226
|
projectRoot: loadedProject.projectRoot,
|
|
209
227
|
command: 'build-hap',
|
|
210
228
|
mode: options.mode,
|
|
211
229
|
status: 'failed',
|
|
212
230
|
entryFile: path_1.default.join(loadedProject.projectRoot, (0, template_1.resolveHarmonyBundleEntryFile)(loadedProject.packageJson)),
|
|
213
|
-
bundleOutputPath: getBundleOutputPath(loadedProject.projectRoot),
|
|
214
|
-
assetsDestPath: getAssetsOutputPath(loadedProject.projectRoot),
|
|
231
|
+
bundleOutputPath: (0, reporting_1.getBundleOutputPath)(loadedProject.projectRoot),
|
|
232
|
+
assetsDestPath: (0, reporting_1.getAssetsOutputPath)(loadedProject.projectRoot),
|
|
215
233
|
artifactPaths: [],
|
|
216
234
|
blockingIssues,
|
|
217
235
|
warnings,
|
|
@@ -224,7 +242,7 @@ async function buildHapProject(projectRoot, options) {
|
|
|
224
242
|
});
|
|
225
243
|
const harmonyProjectRoot = envReport.harmonyProjectRoot ?? path_1.default.join(loadedProject.projectRoot, 'harmony');
|
|
226
244
|
if (bundleReport.status === 'failed') {
|
|
227
|
-
return createBuildReport({
|
|
245
|
+
return (0, reporting_1.createBuildReport)({
|
|
228
246
|
projectRoot: loadedProject.projectRoot,
|
|
229
247
|
command: 'build-hap',
|
|
230
248
|
mode: options.mode,
|
|
@@ -240,7 +258,7 @@ async function buildHapProject(projectRoot, options) {
|
|
|
240
258
|
});
|
|
241
259
|
}
|
|
242
260
|
if (!(await fs_extra_1.default.pathExists(harmonyProjectRoot))) {
|
|
243
|
-
return createBuildReport({
|
|
261
|
+
return (0, reporting_1.createBuildReport)({
|
|
244
262
|
projectRoot: loadedProject.projectRoot,
|
|
245
263
|
command: 'build-hap',
|
|
246
264
|
mode: options.mode,
|
|
@@ -261,7 +279,7 @@ async function buildHapProject(projectRoot, options) {
|
|
|
261
279
|
});
|
|
262
280
|
}
|
|
263
281
|
const steps = [...bundleReport.steps];
|
|
264
|
-
const buildEnvironment = createHarmonyBuildEnvironment(runtimeEnv, envReport);
|
|
282
|
+
const buildEnvironment = (0, commands_1.createHarmonyBuildEnvironment)(runtimeEnv, envReport);
|
|
265
283
|
let normalizedLocalHarPackages = [];
|
|
266
284
|
let restoreNormalizedDependencies = async () => { };
|
|
267
285
|
let restoreNormalizedLocalHarModules = async () => { };
|
|
@@ -269,18 +287,18 @@ async function buildHapProject(projectRoot, options) {
|
|
|
269
287
|
let restoreNormalizedRnohCodegenAlignment = async () => { };
|
|
270
288
|
let restoreNormalizedHarmonyPackageJsons = async () => { };
|
|
271
289
|
try {
|
|
272
|
-
const normalizedLocalHarDependencies = await normalizeLocalHarDependencies(harmonyProjectRoot);
|
|
290
|
+
const normalizedLocalHarDependencies = await (0, localHar_1.normalizeLocalHarDependencies)(harmonyProjectRoot);
|
|
273
291
|
normalizedLocalHarPackages = normalizedLocalHarDependencies.packages;
|
|
274
292
|
restoreNormalizedDependencies = normalizedLocalHarDependencies.restore;
|
|
275
|
-
restoreNormalizedLocalHarModules = await ensureHarmonyBuildProfileSupportsNormalizedLocalDeps(harmonyProjectRoot, normalizedLocalHarDependencies.packages);
|
|
293
|
+
restoreNormalizedLocalHarModules = await (0, localHar_1.ensureHarmonyBuildProfileSupportsNormalizedLocalDeps)(harmonyProjectRoot, normalizedLocalHarDependencies.packages);
|
|
276
294
|
restoreNormalizedRnohCliAutolinkingTemplates =
|
|
277
|
-
await normalizeProjectRnohCliAutolinkingTemplates(loadedProject.projectRoot);
|
|
295
|
+
await (0, rnohCompatibility_1.normalizeProjectRnohCliAutolinkingTemplates)(loadedProject.projectRoot);
|
|
278
296
|
restoreNormalizedHarmonyPackageJsons =
|
|
279
|
-
await (0,
|
|
297
|
+
await (0, autolinking_1.normalizeKnownHarmonyPackageJsons)(loadedProject.projectRoot);
|
|
280
298
|
}
|
|
281
299
|
catch (error) {
|
|
282
300
|
const message = error instanceof Error ? error.message : String(error);
|
|
283
|
-
return createBuildReport({
|
|
301
|
+
return (0, reporting_1.createBuildReport)({
|
|
284
302
|
projectRoot: loadedProject.projectRoot,
|
|
285
303
|
command: 'build-hap',
|
|
286
304
|
mode: options.mode,
|
|
@@ -300,16 +318,16 @@ async function buildHapProject(projectRoot, options) {
|
|
|
300
318
|
steps,
|
|
301
319
|
});
|
|
302
320
|
}
|
|
303
|
-
restoreNormalizedRnohCodegenAlignment = await alignRnohCodegenWithNormalizedLocalPackage(harmonyProjectRoot, normalizedLocalHarPackages);
|
|
304
|
-
const ohpmCommand = buildInvocation(envReport.ohpmPath, ['install', '--all']);
|
|
321
|
+
restoreNormalizedRnohCodegenAlignment = await (0, localHar_1.alignRnohCodegenWithNormalizedLocalPackage)(harmonyProjectRoot, normalizedLocalHarPackages);
|
|
322
|
+
const ohpmCommand = (0, commands_1.buildInvocation)(envReport.ohpmPath, ['install', '--all']);
|
|
305
323
|
try {
|
|
306
324
|
const ohpmResult = await runCommand(ohpmCommand.file, ohpmCommand.args, {
|
|
307
325
|
cwd: harmonyProjectRoot,
|
|
308
326
|
env: buildEnvironment,
|
|
309
327
|
});
|
|
310
|
-
steps.push(createStepReport('ohpm install', ohpmCommand.file, ohpmCommand.args, harmonyProjectRoot, ohpmResult.exitCode));
|
|
328
|
+
steps.push((0, reporting_1.createStepReport)('ohpm install', ohpmCommand.file, ohpmCommand.args, harmonyProjectRoot, ohpmResult.exitCode));
|
|
311
329
|
if (ohpmResult.exitCode !== 0) {
|
|
312
|
-
return createBuildReport({
|
|
330
|
+
return (0, reporting_1.createBuildReport)({
|
|
313
331
|
projectRoot: loadedProject.projectRoot,
|
|
314
332
|
command: 'build-hap',
|
|
315
333
|
mode: options.mode,
|
|
@@ -332,9 +350,9 @@ async function buildHapProject(projectRoot, options) {
|
|
|
332
350
|
});
|
|
333
351
|
}
|
|
334
352
|
if (!normalizedLocalHarPackages.some((localPackage) => localPackage.packageName === '@rnoh/react-native-openharmony')) {
|
|
335
|
-
await ensureRnohGeneratedTsShim(harmonyProjectRoot);
|
|
353
|
+
await (0, localHar_1.ensureRnohGeneratedTsShim)(harmonyProjectRoot);
|
|
336
354
|
}
|
|
337
|
-
const hvigorCommand = buildInvocation(envReport.hvigorPath, [
|
|
355
|
+
const hvigorCommand = (0, commands_1.buildInvocation)(envReport.hvigorPath, [
|
|
338
356
|
'assembleHap',
|
|
339
357
|
'--no-daemon',
|
|
340
358
|
'-p',
|
|
@@ -346,10 +364,10 @@ async function buildHapProject(projectRoot, options) {
|
|
|
346
364
|
cwd: harmonyProjectRoot,
|
|
347
365
|
env: buildEnvironment,
|
|
348
366
|
});
|
|
349
|
-
steps.push(createStepReport('hvigor assembleHap', hvigorCommand.file, hvigorCommand.args, harmonyProjectRoot, hvigorResult.exitCode));
|
|
350
|
-
const artifactPaths = await findHarmonyArtifacts(harmonyProjectRoot);
|
|
367
|
+
steps.push((0, reporting_1.createStepReport)('hvigor assembleHap', hvigorCommand.file, hvigorCommand.args, harmonyProjectRoot, hvigorResult.exitCode));
|
|
368
|
+
const artifactPaths = await (0, localHar_1.findHarmonyArtifacts)(harmonyProjectRoot);
|
|
351
369
|
if (hvigorResult.exitCode !== 0 || artifactPaths.length === 0) {
|
|
352
|
-
return createBuildReport({
|
|
370
|
+
return (0, reporting_1.createBuildReport)({
|
|
353
371
|
projectRoot: loadedProject.projectRoot,
|
|
354
372
|
command: 'build-hap',
|
|
355
373
|
mode: options.mode,
|
|
@@ -371,7 +389,7 @@ async function buildHapProject(projectRoot, options) {
|
|
|
371
389
|
steps,
|
|
372
390
|
});
|
|
373
391
|
}
|
|
374
|
-
return createBuildReport({
|
|
392
|
+
return (0, reporting_1.createBuildReport)({
|
|
375
393
|
projectRoot: loadedProject.projectRoot,
|
|
376
394
|
command: 'build-hap',
|
|
377
395
|
mode: options.mode,
|
|
@@ -394,716 +412,6 @@ async function buildHapProject(projectRoot, options) {
|
|
|
394
412
|
await restoreNormalizedDependencies();
|
|
395
413
|
}
|
|
396
414
|
}
|
|
397
|
-
function renderBuildReport(report) {
|
|
398
|
-
const lines = [
|
|
399
|
-
'Expo Harmony build report',
|
|
400
|
-
`Project: ${report.projectRoot}`,
|
|
401
|
-
`Command: ${report.command}`,
|
|
402
|
-
`Mode: ${report.mode ?? 'n/a'}`,
|
|
403
|
-
`Status: ${report.status}`,
|
|
404
|
-
`Harmony project: ${report.harmonyProjectRoot ?? 'not found'}`,
|
|
405
|
-
`Entry file: ${report.entryFile ?? 'n/a'}`,
|
|
406
|
-
`Bundle output: ${report.bundleOutputPath ?? 'n/a'}`,
|
|
407
|
-
`Artifacts: ${report.artifactPaths.join(', ') || 'none'}`,
|
|
408
|
-
'',
|
|
409
|
-
'Steps:',
|
|
410
|
-
...report.steps.map((step) => `- [${step.exitCode ?? 'n/a'}] ${step.label}: ${step.command} (cwd ${step.cwd})`),
|
|
411
|
-
];
|
|
412
|
-
if (report.blockingIssues.length > 0) {
|
|
413
|
-
lines.push('', 'Blocking issues:', ...report.blockingIssues.map((issue) => `- ${issue.code}: ${issue.message}${issue.subject ? ` (${issue.subject})` : ''}`));
|
|
414
|
-
}
|
|
415
|
-
if (report.warnings.length > 0) {
|
|
416
|
-
lines.push('', 'Warnings:', ...report.warnings.map((warning) => `- ${warning}`));
|
|
417
|
-
}
|
|
418
|
-
return lines.join('\n');
|
|
419
|
-
}
|
|
420
|
-
function getBundleOutputPath(projectRoot) {
|
|
421
|
-
return path_1.default.join(projectRoot, 'harmony', 'entry', 'src', 'main', 'resources', 'rawfile', 'bundle.harmony.js');
|
|
422
|
-
}
|
|
423
|
-
function getAssetsOutputPath(projectRoot) {
|
|
424
|
-
return path_1.default.join(projectRoot, 'harmony', 'entry', 'src', 'main', 'resources', 'rawfile', 'assets');
|
|
425
|
-
}
|
|
426
|
-
function createBuildReport(input) {
|
|
427
|
-
return {
|
|
428
|
-
generatedAt: new Date().toISOString(),
|
|
429
|
-
projectRoot: input.projectRoot,
|
|
430
|
-
toolkitVersion: constants_1.TOOLKIT_VERSION,
|
|
431
|
-
command: input.command,
|
|
432
|
-
mode: input.mode,
|
|
433
|
-
status: input.status,
|
|
434
|
-
harmonyProjectRoot: input.harmonyProjectRoot ?? path_1.default.join(input.projectRoot, 'harmony'),
|
|
435
|
-
entryFile: input.entryFile,
|
|
436
|
-
bundleOutputPath: input.bundleOutputPath,
|
|
437
|
-
assetsDestPath: input.assetsDestPath,
|
|
438
|
-
artifactPaths: input.artifactPaths,
|
|
439
|
-
blockingIssues: input.blockingIssues,
|
|
440
|
-
warnings: input.warnings,
|
|
441
|
-
steps: input.steps,
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
function createStepReport(label, file, args, cwd, exitCode) {
|
|
445
|
-
return {
|
|
446
|
-
label,
|
|
447
|
-
command: [file, ...args].join(' '),
|
|
448
|
-
cwd,
|
|
449
|
-
exitCode,
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
function buildInvocation(file, args) {
|
|
453
|
-
if (file.endsWith('.js')) {
|
|
454
|
-
return {
|
|
455
|
-
file: process.execPath,
|
|
456
|
-
args: [file, ...args],
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
return {
|
|
460
|
-
file,
|
|
461
|
-
args,
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
function createHarmonyBuildEnvironment(runtimeEnv, envReport) {
|
|
465
|
-
const buildEnvironment = {
|
|
466
|
-
...runtimeEnv,
|
|
467
|
-
};
|
|
468
|
-
if (envReport.sdkRoot) {
|
|
469
|
-
buildEnvironment.DEVECO_SDK_HOME = envReport.sdkRoot;
|
|
470
|
-
buildEnvironment.OHOS_BASE_SDK_HOME = envReport.sdkRoot;
|
|
471
|
-
}
|
|
472
|
-
if (envReport.devecoStudioPath) {
|
|
473
|
-
buildEnvironment.NODE_HOME =
|
|
474
|
-
buildEnvironment.NODE_HOME ??
|
|
475
|
-
path_1.default.join(envReport.devecoStudioPath, 'Contents', 'tools', 'node');
|
|
476
|
-
}
|
|
477
|
-
return buildEnvironment;
|
|
478
|
-
}
|
|
479
|
-
async function normalizeLocalHarDependencies(harmonyProjectRoot) {
|
|
480
|
-
const packagePaths = [
|
|
481
|
-
path_1.default.join(harmonyProjectRoot, 'oh-package.json5'),
|
|
482
|
-
path_1.default.join(harmonyProjectRoot, 'entry', 'oh-package.json5'),
|
|
483
|
-
];
|
|
484
|
-
const extractionRoot = path_1.default.join(harmonyProjectRoot, 'expo-harmony-local-deps');
|
|
485
|
-
const archiveCache = new Map();
|
|
486
|
-
const originalContents = new Map();
|
|
487
|
-
const packagesByDirectoryPath = new Map();
|
|
488
|
-
await fs_extra_1.default.ensureDir(extractionRoot);
|
|
489
|
-
for (const packagePath of packagePaths) {
|
|
490
|
-
if (!(await fs_extra_1.default.pathExists(packagePath))) {
|
|
491
|
-
continue;
|
|
492
|
-
}
|
|
493
|
-
const rawContents = await fs_extra_1.default.readFile(packagePath, 'utf8');
|
|
494
|
-
const parsed = json5_1.default.parse(rawContents);
|
|
495
|
-
let didChange = false;
|
|
496
|
-
for (const sectionName of ['dependencies', 'devDependencies', 'overrides']) {
|
|
497
|
-
const section = parsed[sectionName];
|
|
498
|
-
if (!section || typeof section !== 'object' || Array.isArray(section)) {
|
|
499
|
-
continue;
|
|
500
|
-
}
|
|
501
|
-
for (const [packageName, specifier] of Object.entries(section)) {
|
|
502
|
-
if (typeof specifier !== 'string' || !specifier.startsWith('file:') || !specifier.endsWith('.har')) {
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
const archivePath = path_1.default.resolve(harmonyProjectRoot, specifier.slice('file:'.length));
|
|
506
|
-
const normalizedDirectory = archiveCache.get(archivePath) ??
|
|
507
|
-
(await extractHarArchiveToDirectory(archivePath, extractionRoot, packageName));
|
|
508
|
-
archiveCache.set(archivePath, normalizedDirectory);
|
|
509
|
-
if (!packagesByDirectoryPath.has(normalizedDirectory)) {
|
|
510
|
-
packagesByDirectoryPath.set(normalizedDirectory, await readNormalizedLocalHarPackageMetadata(normalizedDirectory, packageName));
|
|
511
|
-
}
|
|
512
|
-
let relativeDirectory = path_1.default.relative(harmonyProjectRoot, normalizedDirectory);
|
|
513
|
-
if (!relativeDirectory.startsWith('.')) {
|
|
514
|
-
relativeDirectory = `./${relativeDirectory}`;
|
|
515
|
-
}
|
|
516
|
-
const nextSpecifier = `file:${relativeDirectory.split(path_1.default.sep).join('/')}`;
|
|
517
|
-
if (nextSpecifier !== specifier) {
|
|
518
|
-
section[packageName] = nextSpecifier;
|
|
519
|
-
didChange = true;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
if (didChange) {
|
|
524
|
-
originalContents.set(packagePath, rawContents);
|
|
525
|
-
await fs_extra_1.default.writeFile(packagePath, JSON.stringify(parsed, null, 2) + '\n');
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
return {
|
|
529
|
-
packages: [...packagesByDirectoryPath.values()],
|
|
530
|
-
restore: async () => {
|
|
531
|
-
for (const [packagePath, rawContents] of originalContents) {
|
|
532
|
-
await fs_extra_1.default.writeFile(packagePath, rawContents);
|
|
533
|
-
}
|
|
534
|
-
},
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
async function extractHarArchiveToDirectory(archivePath, extractionRoot, packageName) {
|
|
538
|
-
if (!(await fs_extra_1.default.pathExists(archivePath))) {
|
|
539
|
-
throw new Error(`Local Harmony archive not found: ${archivePath}`);
|
|
540
|
-
}
|
|
541
|
-
const destinationPath = path_1.default.join(extractionRoot, `${sanitizePackageName(packageName)}-${path_1.default.basename(archivePath, path_1.default.extname(archivePath))}`);
|
|
542
|
-
const stagingRoot = await fs_extra_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'expo-harmony-har-'));
|
|
543
|
-
try {
|
|
544
|
-
await execFileAsync('tar', ['-xzf', archivePath, '-C', stagingRoot], {
|
|
545
|
-
maxBuffer: 20 * 1024 * 1024,
|
|
546
|
-
});
|
|
547
|
-
const packagedRoot = path_1.default.join(stagingRoot, 'package');
|
|
548
|
-
const sourceRoot = (await fs_extra_1.default.pathExists(path_1.default.join(packagedRoot, 'oh-package.json5')))
|
|
549
|
-
? packagedRoot
|
|
550
|
-
: stagingRoot;
|
|
551
|
-
if (!(await fs_extra_1.default.pathExists(path_1.default.join(sourceRoot, 'oh-package.json5')))) {
|
|
552
|
-
throw new Error(`oh-package.json5 not found after extracting ${archivePath}`);
|
|
553
|
-
}
|
|
554
|
-
await fs_extra_1.default.remove(destinationPath);
|
|
555
|
-
await fs_extra_1.default.ensureDir(destinationPath);
|
|
556
|
-
for (const entryName of await fs_extra_1.default.readdir(sourceRoot)) {
|
|
557
|
-
await fs_extra_1.default.move(path_1.default.join(sourceRoot, entryName), path_1.default.join(destinationPath, entryName), {
|
|
558
|
-
overwrite: true,
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
await ensureNormalizedLocalHarCompatibilityShims(destinationPath, packageName);
|
|
562
|
-
return destinationPath;
|
|
563
|
-
}
|
|
564
|
-
catch (error) {
|
|
565
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
566
|
-
throw new Error(`Failed to normalize local Harmony archive ${archivePath}: ${message}`);
|
|
567
|
-
}
|
|
568
|
-
finally {
|
|
569
|
-
await fs_extra_1.default.remove(stagingRoot);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
async function ensureNormalizedLocalHarCompatibilityShims(directoryPath, packageName) {
|
|
573
|
-
if (packageName === '@react-native-oh-tpl/react-native-gesture-handler') {
|
|
574
|
-
const gestureHandlerPackageHeaderPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'RnohReactNativeHarmonyGestureHandlerPackage.h');
|
|
575
|
-
const gestureHandlerPackagePath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'RnohReactNativeHarmonyGestureHandlerPackage.cpp');
|
|
576
|
-
const gestureHandlerTurboModulePath = path_1.default.join(directoryPath, 'src', 'main', 'ets', 'rnoh', 'RNGestureHandlerModule.ts');
|
|
577
|
-
if (await fs_extra_1.default.pathExists(gestureHandlerTurboModulePath)) {
|
|
578
|
-
const gestureHandlerTurboModuleContents = await fs_extra_1.default.readFile(gestureHandlerTurboModulePath, 'utf8');
|
|
579
|
-
let nextGestureHandlerTurboModuleContents = gestureHandlerTurboModuleContents;
|
|
580
|
-
nextGestureHandlerTurboModuleContents = nextGestureHandlerTurboModuleContents.replace(/^import \{ TM \} from ["']@rnoh\/react-native-openharmony\/generated\/ts["'];?\r?\n/m, '');
|
|
581
|
-
nextGestureHandlerTurboModuleContents = nextGestureHandlerTurboModuleContents.replace(/\s+implements TM\.RNGestureHandlerModule\.Spec/, '');
|
|
582
|
-
if (nextGestureHandlerTurboModuleContents !== gestureHandlerTurboModuleContents) {
|
|
583
|
-
await fs_extra_1.default.writeFile(gestureHandlerTurboModulePath, nextGestureHandlerTurboModuleContents);
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
const gestureHandlerGeneratedDirectoryPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'generated');
|
|
587
|
-
await fs_extra_1.default.ensureDir(gestureHandlerGeneratedDirectoryPath);
|
|
588
|
-
await fs_extra_1.default.writeFile(path_1.default.join(gestureHandlerGeneratedDirectoryPath, 'RNGestureHandlerButtonComponentDescriptor.h'), createGestureHandlerCompatibilityDescriptorHeader('RNGestureHandlerButton'));
|
|
589
|
-
await fs_extra_1.default.writeFile(path_1.default.join(gestureHandlerGeneratedDirectoryPath, 'RNGestureHandlerRootViewComponentDescriptor.h'), createGestureHandlerCompatibilityDescriptorHeader('RNGestureHandlerRootView'));
|
|
590
|
-
if (await fs_extra_1.default.pathExists(gestureHandlerPackageHeaderPath)) {
|
|
591
|
-
const gestureHandlerPackageHeaderContents = await fs_extra_1.default.readFile(gestureHandlerPackageHeaderPath, 'utf8');
|
|
592
|
-
const nextGestureHandlerPackageHeaderContents = patchGestureHandlerCompatibilityPackageHeader(gestureHandlerPackageHeaderContents);
|
|
593
|
-
if (nextGestureHandlerPackageHeaderContents !== gestureHandlerPackageHeaderContents) {
|
|
594
|
-
await fs_extra_1.default.writeFile(gestureHandlerPackageHeaderPath, nextGestureHandlerPackageHeaderContents);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
if (!(await fs_extra_1.default.pathExists(gestureHandlerPackagePath))) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
const gestureHandlerPackageContents = await fs_extra_1.default.readFile(gestureHandlerPackagePath, 'utf8');
|
|
601
|
-
const nextGestureHandlerPackageContents = patchGestureHandlerCompatibilityPackageSource(gestureHandlerPackageContents);
|
|
602
|
-
if (nextGestureHandlerPackageContents !== gestureHandlerPackageContents) {
|
|
603
|
-
await fs_extra_1.default.writeFile(gestureHandlerPackagePath, nextGestureHandlerPackageContents);
|
|
604
|
-
}
|
|
605
|
-
if (!nextGestureHandlerPackageContents.includes('<react/renderer/debug/SystraceSection.h>')) {
|
|
606
|
-
return;
|
|
607
|
-
}
|
|
608
|
-
const systraceCompatibilityShimPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'react', 'renderer', 'debug', 'SystraceSection.h');
|
|
609
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(systraceCompatibilityShimPath));
|
|
610
|
-
await fs_extra_1.default.writeFile(systraceCompatibilityShimPath, '#pragma once\n#include <cxxreact/SystraceSection.h>\n');
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
if (packageName === '@react-native-oh-tpl/react-native-reanimated') {
|
|
614
|
-
const reanimatedCmakeListsPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'CMakeLists.txt');
|
|
615
|
-
const reanimatedMountHookHeaderPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'Common', 'cpp', 'Fabric', 'ReanimatedMountHook.h');
|
|
616
|
-
const reanimatedMountHookSourcePath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'Common', 'cpp', 'Fabric', 'ReanimatedMountHook.cpp');
|
|
617
|
-
const nativeReanimatedModuleSourcePath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'Common', 'cpp', 'NativeModules', 'NativeReanimatedModule.cpp');
|
|
618
|
-
if (await fs_extra_1.default.pathExists(reanimatedCmakeListsPath)) {
|
|
619
|
-
const reanimatedCmakeListsContents = await fs_extra_1.default.readFile(reanimatedCmakeListsPath, 'utf8');
|
|
620
|
-
if (reanimatedCmakeListsContents.includes('REACT_NATIVE_MINOR_VERSION=72')) {
|
|
621
|
-
await fs_extra_1.default.writeFile(reanimatedCmakeListsPath, reanimatedCmakeListsContents.replace('REACT_NATIVE_MINOR_VERSION=72', 'REACT_NATIVE_MINOR_VERSION=82'));
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
if (await fs_extra_1.default.pathExists(reanimatedMountHookHeaderPath)) {
|
|
625
|
-
const reanimatedMountHookHeaderContents = await fs_extra_1.default.readFile(reanimatedMountHookHeaderPath, 'utf8');
|
|
626
|
-
if (reanimatedMountHookHeaderContents.includes('double mountTime) noexcept override;')) {
|
|
627
|
-
await fs_extra_1.default.writeFile(reanimatedMountHookHeaderPath, reanimatedMountHookHeaderContents.replace('double mountTime) noexcept override;', 'HighResTimeStamp mountTime) noexcept override;'));
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
if (await fs_extra_1.default.pathExists(reanimatedMountHookSourcePath)) {
|
|
631
|
-
const reanimatedMountHookSourceContents = await fs_extra_1.default.readFile(reanimatedMountHookSourcePath, 'utf8');
|
|
632
|
-
if (reanimatedMountHookSourceContents.includes('double) noexcept {')) {
|
|
633
|
-
await fs_extra_1.default.writeFile(reanimatedMountHookSourcePath, reanimatedMountHookSourceContents.replace('double) noexcept {', 'HighResTimeStamp) noexcept {'));
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
if (await fs_extra_1.default.pathExists(nativeReanimatedModuleSourcePath)) {
|
|
637
|
-
const nativeReanimatedModuleSourceContents = await fs_extra_1.default.readFile(nativeReanimatedModuleSourcePath, 'utf8');
|
|
638
|
-
let nextNativeReanimatedModuleSourceContents = nativeReanimatedModuleSourceContents;
|
|
639
|
-
if (nextNativeReanimatedModuleSourceContents.includes('<react/renderer/core/TraitCast.h>')) {
|
|
640
|
-
nextNativeReanimatedModuleSourceContents = nextNativeReanimatedModuleSourceContents.replace('<react/renderer/core/TraitCast.h>', '<react/renderer/core/LayoutableShadowNode.h>');
|
|
641
|
-
}
|
|
642
|
-
if (nextNativeReanimatedModuleSourceContents.includes('#include <react/utils/CoreFeatures.h>')) {
|
|
643
|
-
nextNativeReanimatedModuleSourceContents = nextNativeReanimatedModuleSourceContents.replace('#include <react/utils/CoreFeatures.h>\n', '');
|
|
644
|
-
nextNativeReanimatedModuleSourceContents = nextNativeReanimatedModuleSourceContents.replace('#include <react/utils/CoreFeatures.h>\r\n', '');
|
|
645
|
-
}
|
|
646
|
-
if (nextNativeReanimatedModuleSourceContents.includes('traitCast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get())')) {
|
|
647
|
-
nextNativeReanimatedModuleSourceContents = nextNativeReanimatedModuleSourceContents.replace('traitCast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get())', 'dynamic_cast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get())');
|
|
648
|
-
}
|
|
649
|
-
if (nextNativeReanimatedModuleSourceContents.includes('shadowNodeFromValue(rt, shadowNodeWrapper)')) {
|
|
650
|
-
nextNativeReanimatedModuleSourceContents =
|
|
651
|
-
nextNativeReanimatedModuleSourceContents.replace(/auto (\w+) = shadowNodeFromValue\(rt, shadowNodeWrapper\);/g, 'auto $1 = Bridging<std::shared_ptr<const ShadowNode>>::fromJs(rt, shadowNodeWrapper);');
|
|
652
|
-
}
|
|
653
|
-
if (nextNativeReanimatedModuleSourceContents.includes('shadowNodeFromValue(rt, shadowNodeValue)')) {
|
|
654
|
-
nextNativeReanimatedModuleSourceContents =
|
|
655
|
-
nextNativeReanimatedModuleSourceContents.replace(/(ShadowNode::Shared|auto) (\w+) = shadowNodeFromValue\(rt, shadowNodeValue\);/g, 'auto $2 = Bridging<std::shared_ptr<const ShadowNode>>::fromJs(rt, shadowNodeValue);');
|
|
656
|
-
}
|
|
657
|
-
if (nextNativeReanimatedModuleSourceContents.includes('bool CoreFeatures::useNativeState;')) {
|
|
658
|
-
nextNativeReanimatedModuleSourceContents = nextNativeReanimatedModuleSourceContents.replace(/#if REACT_NATIVE_MINOR_VERSION >= 73 && defined\(RCT_NEW_ARCH_ENABLED\)\r?\n\/\/ Android can't find the definition of this static field\r?\nbool CoreFeatures::useNativeState;\r?\n#endif\r?\n/m, '');
|
|
659
|
-
}
|
|
660
|
-
if (nextNativeReanimatedModuleSourceContents.includes('/* .shouldYield = */ [this]() {')) {
|
|
661
|
-
nextNativeReanimatedModuleSourceContents =
|
|
662
|
-
nextNativeReanimatedModuleSourceContents.replace(/#if REACT_NATIVE_MINOR_VERSION >= 72\r?\n\s*\/\* \.mountSynchronously = \*\/ true,\r?\n#endif\r?\n\s*\/\* \.shouldYield = \*\/ \[this\]\(\) \{\r?\n\s*return propsRegistry_->shouldReanimatedSkipCommit\(\);\r?\n\s*\}/m, '#if REACT_NATIVE_MINOR_VERSION >= 72\n'
|
|
663
|
-
+ ' /* .mountSynchronously = */ true,\n'
|
|
664
|
-
+ '#endif\n'
|
|
665
|
-
+ ' /* .source = */ ShadowTree::CommitSource::Unknown');
|
|
666
|
-
}
|
|
667
|
-
if (nextNativeReanimatedModuleSourceContents !== nativeReanimatedModuleSourceContents) {
|
|
668
|
-
await fs_extra_1.default.writeFile(nativeReanimatedModuleSourcePath, nextNativeReanimatedModuleSourceContents);
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
|
-
if (packageName !== '@react-native-oh-tpl/react-native-svg') {
|
|
674
|
-
return;
|
|
675
|
-
}
|
|
676
|
-
const svgGeneratedPropsPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'generated', 'react', 'renderer', 'components', 'react_native_svg', 'Props.h');
|
|
677
|
-
const svgPathComponentInstancePath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'componentInstances', 'RNSVGPathComponentInstance.h');
|
|
678
|
-
const svgImageComponentDescriptorPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'svgImage', 'RNSVGImageComponentDescriptor.h');
|
|
679
|
-
const svgImageShadowNodePath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'svgImage', 'RNSVGImageShadowNode.h');
|
|
680
|
-
if (await fs_extra_1.default.pathExists(svgGeneratedPropsPath)) {
|
|
681
|
-
const svgGeneratedPropsContents = await fs_extra_1.default.readFile(svgGeneratedPropsPath, 'utf8');
|
|
682
|
-
if (svgGeneratedPropsContents.includes('butter::map<std::string, RawValue>')) {
|
|
683
|
-
await fs_extra_1.default.writeFile(svgGeneratedPropsPath, svgGeneratedPropsContents.replace(/butter::map<std::string, RawValue>/g, 'std::unordered_map<std::string, RawValue>'));
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
if (await fs_extra_1.default.pathExists(svgImageComponentDescriptorPath)) {
|
|
687
|
-
const svgImageComponentDescriptorContents = await fs_extra_1.default.readFile(svgImageComponentDescriptorPath, 'utf8');
|
|
688
|
-
let nextSvgImageComponentDescriptorContents = svgImageComponentDescriptorContents;
|
|
689
|
-
if (nextSvgImageComponentDescriptorContents.includes('void adopt(ShadowNode::Unshared const &shadowNode) const override {')) {
|
|
690
|
-
nextSvgImageComponentDescriptorContents =
|
|
691
|
-
nextSvgImageComponentDescriptorContents.replace('void adopt(ShadowNode::Unshared const &shadowNode) const override {', 'void adopt(ShadowNode& shadowNode) const override {');
|
|
692
|
-
}
|
|
693
|
-
if (nextSvgImageComponentDescriptorContents.includes('auto imageShadowNode = std::static_pointer_cast<RNSVGImageShadowNode>(shadowNode);')) {
|
|
694
|
-
nextSvgImageComponentDescriptorContents =
|
|
695
|
-
nextSvgImageComponentDescriptorContents.replace('auto imageShadowNode = std::static_pointer_cast<RNSVGImageShadowNode>(shadowNode);', 'auto& imageShadowNode = static_cast<RNSVGImageShadowNode&>(shadowNode);');
|
|
696
|
-
}
|
|
697
|
-
if (nextSvgImageComponentDescriptorContents.includes('imageShadowNode->setImageManager(imageManager_);')) {
|
|
698
|
-
nextSvgImageComponentDescriptorContents =
|
|
699
|
-
nextSvgImageComponentDescriptorContents.replace('imageShadowNode->setImageManager(imageManager_);', 'imageShadowNode.setImageManager(imageManager_);');
|
|
700
|
-
}
|
|
701
|
-
if (nextSvgImageComponentDescriptorContents !== svgImageComponentDescriptorContents) {
|
|
702
|
-
await fs_extra_1.default.writeFile(svgImageComponentDescriptorPath, nextSvgImageComponentDescriptorContents);
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
if (await fs_extra_1.default.pathExists(svgImageShadowNodePath)) {
|
|
706
|
-
const svgImageShadowNodeContents = await fs_extra_1.default.readFile(svgImageShadowNodePath, 'utf8');
|
|
707
|
-
let nextSvgImageShadowNodeContents = svgImageShadowNodeContents;
|
|
708
|
-
const svgImageShadowNodeNewline = svgImageShadowNodeContents.includes('\r\n') ? '\r\n' : '\n';
|
|
709
|
-
if (!nextSvgImageShadowNodeContents.includes('#include <react/renderer/core/ShadowNodeFamily.h>')
|
|
710
|
-
&& nextSvgImageShadowNodeContents.includes('#include <react/renderer/components/view/ConcreteViewShadowNode.h>')) {
|
|
711
|
-
nextSvgImageShadowNodeContents = nextSvgImageShadowNodeContents.replace('#include <react/renderer/components/view/ConcreteViewShadowNode.h>', '#include <react/renderer/components/view/ConcreteViewShadowNode.h>'
|
|
712
|
-
+ `${svgImageShadowNodeNewline}#include <react/renderer/core/ShadowNodeFamily.h>`);
|
|
713
|
-
}
|
|
714
|
-
const svgImageInitialStateSignaturePattern = /static RNSVGImageState initialStateData\(ShadowNodeFragment const &fragment,\r?\n\s*ShadowNodeFamilyFragment const &familyFragment,\r?\n\s*ComponentDescriptor const &componentDescriptor\) \{/m;
|
|
715
|
-
if (svgImageInitialStateSignaturePattern.test(nextSvgImageShadowNodeContents)) {
|
|
716
|
-
nextSvgImageShadowNodeContents = nextSvgImageShadowNodeContents.replace(svgImageInitialStateSignaturePattern, 'static RNSVGImageState initialStateData(const Props::Shared& /*props*/,'
|
|
717
|
-
+ `${svgImageShadowNodeNewline}`
|
|
718
|
-
+ ' const ShadowNodeFamily::Shared& /*family*/,'
|
|
719
|
-
+ `${svgImageShadowNodeNewline}`
|
|
720
|
-
+ ' const ComponentDescriptor& /*componentDescriptor*/) {');
|
|
721
|
-
}
|
|
722
|
-
if (nextSvgImageShadowNodeContents !== svgImageShadowNodeContents) {
|
|
723
|
-
await fs_extra_1.default.writeFile(svgImageShadowNodePath, nextSvgImageShadowNodeContents);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (!(await fs_extra_1.default.pathExists(svgPathComponentInstancePath))) {
|
|
727
|
-
return;
|
|
728
|
-
}
|
|
729
|
-
const svgPathComponentInstanceContents = await fs_extra_1.default.readFile(svgPathComponentInstancePath, 'utf8');
|
|
730
|
-
if (!svgPathComponentInstanceContents.includes('Float m_cacheScale;')) {
|
|
731
|
-
return;
|
|
732
|
-
}
|
|
733
|
-
await fs_extra_1.default.writeFile(svgPathComponentInstancePath, svgPathComponentInstanceContents.replace('Float m_cacheScale;', 'facebook::react::Float m_cacheScale;'));
|
|
734
|
-
}
|
|
735
|
-
function createGestureHandlerCompatibilityDescriptorHeader(componentName) {
|
|
736
|
-
return [
|
|
737
|
-
'#pragma once',
|
|
738
|
-
'',
|
|
739
|
-
'#include <react/renderer/components/view/ConcreteViewShadowNode.h>',
|
|
740
|
-
'#include <react/renderer/core/ConcreteComponentDescriptor.h>',
|
|
741
|
-
'',
|
|
742
|
-
'namespace facebook::react {',
|
|
743
|
-
'',
|
|
744
|
-
`inline constexpr char ${componentName}ComponentName[] = "${componentName}";`,
|
|
745
|
-
'',
|
|
746
|
-
`using ${componentName}ShadowNode = ConcreteViewShadowNode<${componentName}ComponentName>;`,
|
|
747
|
-
`using ${componentName}ComponentDescriptor = ConcreteComponentDescriptor<${componentName}ShadowNode>;`,
|
|
748
|
-
'',
|
|
749
|
-
'} // namespace facebook::react',
|
|
750
|
-
'',
|
|
751
|
-
].join('\n');
|
|
752
|
-
}
|
|
753
|
-
function patchGestureHandlerCompatibilityPackageHeader(contents) {
|
|
754
|
-
if (contents.includes('createComponentDescriptorProviders() override;')) {
|
|
755
|
-
return contents;
|
|
756
|
-
}
|
|
757
|
-
return contents.replace(' std::vector<ArkTSMessageHandler::Shared> createArkTSMessageHandlers() override;\n', [
|
|
758
|
-
' std::vector<facebook::react::ComponentDescriptorProvider> createComponentDescriptorProviders() override;',
|
|
759
|
-
'',
|
|
760
|
-
' ComponentJSIBinderByString createComponentJSIBinderByName() override;',
|
|
761
|
-
'',
|
|
762
|
-
' std::vector<ArkTSMessageHandler::Shared> createArkTSMessageHandlers() override;',
|
|
763
|
-
].join('\n'));
|
|
764
|
-
}
|
|
765
|
-
function patchGestureHandlerCompatibilityPackageSource(contents) {
|
|
766
|
-
let nextContents = contents;
|
|
767
|
-
if (!nextContents.includes('#include "RNOHCorePackage/ComponentBinders/ViewComponentJSIBinder.h"')) {
|
|
768
|
-
nextContents = nextContents.replace('#include "RNOH/RNInstanceCAPI.h"\n', '#include "RNOH/RNInstanceCAPI.h"\n#include "RNOHCorePackage/ComponentBinders/ViewComponentJSIBinder.h"\n');
|
|
769
|
-
}
|
|
770
|
-
if (!nextContents.includes('#include "generated/RNGestureHandlerButtonComponentDescriptor.h"')) {
|
|
771
|
-
nextContents = nextContents.replace('#include "componentInstances/RNGestureHandlerRootViewComponentInstance.h"\n', '#include "componentInstances/RNGestureHandlerRootViewComponentInstance.h"\n#include "generated/RNGestureHandlerButtonComponentDescriptor.h"\n#include "generated/RNGestureHandlerRootViewComponentDescriptor.h"\n');
|
|
772
|
-
}
|
|
773
|
-
if (!nextContents.includes('class RNGestureHandlerComponentJSIBinder')) {
|
|
774
|
-
nextContents = nextContents.replace('using namespace rnoh;\nusing namespace facebook;\n\n', [
|
|
775
|
-
'using namespace rnoh;',
|
|
776
|
-
'using namespace facebook;',
|
|
777
|
-
'',
|
|
778
|
-
'class RNGestureHandlerComponentJSIBinder : public ViewComponentJSIBinder {',
|
|
779
|
-
'protected:',
|
|
780
|
-
' facebook::jsi::Object createNativeProps(facebook::jsi::Runtime &rt) override {',
|
|
781
|
-
' auto nativeProps = ViewComponentJSIBinder::createNativeProps(rt);',
|
|
782
|
-
' nativeProps.setProperty(rt, "exclusive", "boolean");',
|
|
783
|
-
' nativeProps.setProperty(rt, "foreground", "boolean");',
|
|
784
|
-
' nativeProps.setProperty(rt, "borderless", "boolean");',
|
|
785
|
-
' nativeProps.setProperty(rt, "enabled", "boolean");',
|
|
786
|
-
' nativeProps.setProperty(rt, "rippleColor", "Color");',
|
|
787
|
-
' nativeProps.setProperty(rt, "rippleRadius", "number");',
|
|
788
|
-
' nativeProps.setProperty(rt, "touchSoundDisabled", "boolean");',
|
|
789
|
-
' return nativeProps;',
|
|
790
|
-
' }',
|
|
791
|
-
'',
|
|
792
|
-
' facebook::jsi::Object createDirectEventTypes(facebook::jsi::Runtime &rt) override {',
|
|
793
|
-
' auto events = ViewComponentJSIBinder::createDirectEventTypes(rt);',
|
|
794
|
-
' events.setProperty(rt, "onGestureHandlerEvent", createDirectEvent(rt, "onGestureHandlerEvent"));',
|
|
795
|
-
' events.setProperty(',
|
|
796
|
-
' rt,',
|
|
797
|
-
' "onGestureHandlerStateChange",',
|
|
798
|
-
' createDirectEvent(rt, "onGestureHandlerStateChange"));',
|
|
799
|
-
' events.setProperty(rt, "topOnGestureHandlerEvent", createDirectEvent(rt, "onGestureHandlerEvent"));',
|
|
800
|
-
' events.setProperty(',
|
|
801
|
-
' rt,',
|
|
802
|
-
' "topOnGestureHandlerStateChange",',
|
|
803
|
-
' createDirectEvent(rt, "onGestureHandlerStateChange"));',
|
|
804
|
-
' return events;',
|
|
805
|
-
' }',
|
|
806
|
-
'};',
|
|
807
|
-
'',
|
|
808
|
-
].join('\n'));
|
|
809
|
-
}
|
|
810
|
-
if (!nextContents.includes('RnohReactNativeHarmonyGestureHandlerPackage::createComponentDescriptorProviders()')) {
|
|
811
|
-
nextContents = nextContents.replace('EventEmitRequestHandlers RnohReactNativeHarmonyGestureHandlerPackage::createEventEmitRequestHandlers() {\n', [
|
|
812
|
-
'std::vector<facebook::react::ComponentDescriptorProvider>',
|
|
813
|
-
'RnohReactNativeHarmonyGestureHandlerPackage::createComponentDescriptorProviders() {',
|
|
814
|
-
' return {',
|
|
815
|
-
' facebook::react::concreteComponentDescriptorProvider<',
|
|
816
|
-
' facebook::react::RNGestureHandlerButtonComponentDescriptor>(),',
|
|
817
|
-
' facebook::react::concreteComponentDescriptorProvider<',
|
|
818
|
-
' facebook::react::RNGestureHandlerRootViewComponentDescriptor>(),',
|
|
819
|
-
' };',
|
|
820
|
-
'}',
|
|
821
|
-
'',
|
|
822
|
-
'ComponentJSIBinderByString',
|
|
823
|
-
'RnohReactNativeHarmonyGestureHandlerPackage::createComponentJSIBinderByName() {',
|
|
824
|
-
' auto componentJSIBinder = std::make_shared<RNGestureHandlerComponentJSIBinder>();',
|
|
825
|
-
' return {',
|
|
826
|
-
' {"RNGestureHandlerButton", componentJSIBinder},',
|
|
827
|
-
' {"RNGestureHandlerRootView", componentJSIBinder},',
|
|
828
|
-
' };',
|
|
829
|
-
'}',
|
|
830
|
-
'',
|
|
831
|
-
'EventEmitRequestHandlers RnohReactNativeHarmonyGestureHandlerPackage::createEventEmitRequestHandlers() {',
|
|
832
|
-
].join('\n'));
|
|
833
|
-
}
|
|
834
|
-
return nextContents;
|
|
835
|
-
}
|
|
836
|
-
function sanitizePackageName(packageName) {
|
|
837
|
-
return packageName.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
838
|
-
}
|
|
839
|
-
async function readNormalizedLocalHarPackageMetadata(directoryPath, packageName) {
|
|
840
|
-
await ensureNormalizedLocalHarModuleJson5(directoryPath);
|
|
841
|
-
const moduleJsonPaths = [
|
|
842
|
-
path_1.default.join(directoryPath, 'src', 'main', 'module.json5'),
|
|
843
|
-
path_1.default.join(directoryPath, 'src', 'main', 'module.json'),
|
|
844
|
-
];
|
|
845
|
-
let moduleName = sanitizePackageName(packageName);
|
|
846
|
-
for (const moduleJsonPath of moduleJsonPaths) {
|
|
847
|
-
if (!(await fs_extra_1.default.pathExists(moduleJsonPath))) {
|
|
848
|
-
continue;
|
|
849
|
-
}
|
|
850
|
-
try {
|
|
851
|
-
const parsed = json5_1.default.parse(await fs_extra_1.default.readFile(moduleJsonPath, 'utf8'));
|
|
852
|
-
if (typeof parsed?.module?.name === 'string' && parsed.module.name.trim().length > 0) {
|
|
853
|
-
moduleName = parsed.module.name.trim();
|
|
854
|
-
break;
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
catch {
|
|
858
|
-
// Ignore malformed module metadata and fall back to a sanitized package name.
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
return {
|
|
862
|
-
packageName,
|
|
863
|
-
moduleName,
|
|
864
|
-
directoryPath,
|
|
865
|
-
};
|
|
866
|
-
}
|
|
867
|
-
async function ensureNormalizedLocalHarModuleJson5(directoryPath) {
|
|
868
|
-
const moduleJson5Path = path_1.default.join(directoryPath, 'src', 'main', 'module.json5');
|
|
869
|
-
const moduleJsonPath = path_1.default.join(directoryPath, 'src', 'main', 'module.json');
|
|
870
|
-
const sourcePath = (await fs_extra_1.default.pathExists(moduleJsonPath))
|
|
871
|
-
? moduleJsonPath
|
|
872
|
-
: ((await fs_extra_1.default.pathExists(moduleJson5Path)) ? moduleJson5Path : null);
|
|
873
|
-
if (!sourcePath) {
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
const parsed = json5_1.default.parse(await fs_extra_1.default.readFile(sourcePath, 'utf8'));
|
|
877
|
-
const legacyModule = parsed.module && typeof parsed.module === 'object' && !Array.isArray(parsed.module)
|
|
878
|
-
? parsed.module
|
|
879
|
-
: {};
|
|
880
|
-
const normalizedModule = {
|
|
881
|
-
name: typeof legacyModule.name === 'string' && legacyModule.name.trim().length > 0
|
|
882
|
-
? legacyModule.name.trim()
|
|
883
|
-
: path_1.default.basename(directoryPath).replace(/[^a-zA-Z0-9]+/g, '_'),
|
|
884
|
-
type: typeof legacyModule.type === 'string' ? legacyModule.type : 'har',
|
|
885
|
-
deviceTypes: Array.isArray(legacyModule.deviceTypes) && legacyModule.deviceTypes.length > 0
|
|
886
|
-
? legacyModule.deviceTypes
|
|
887
|
-
: ['default'],
|
|
888
|
-
installationFree: typeof legacyModule.installationFree === 'boolean' ? legacyModule.installationFree : false,
|
|
889
|
-
};
|
|
890
|
-
const passthroughKeys = [
|
|
891
|
-
'srcEntrance',
|
|
892
|
-
'srcEntry',
|
|
893
|
-
'description',
|
|
894
|
-
'process',
|
|
895
|
-
'mainElement',
|
|
896
|
-
'uiSyntax',
|
|
897
|
-
'metadata',
|
|
898
|
-
'abilities',
|
|
899
|
-
'extensionAbilities',
|
|
900
|
-
'requestPermissions',
|
|
901
|
-
'definePermissions',
|
|
902
|
-
'testRunner',
|
|
903
|
-
'dependencies',
|
|
904
|
-
'libIsolation',
|
|
905
|
-
'routerMap',
|
|
906
|
-
'appStartup',
|
|
907
|
-
'crossAppSharedConfig',
|
|
908
|
-
];
|
|
909
|
-
for (const key of passthroughKeys) {
|
|
910
|
-
const value = legacyModule[key];
|
|
911
|
-
if (value !== undefined) {
|
|
912
|
-
normalizedModule[key] = value;
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
if (typeof legacyModule.virtualMachine === 'string') {
|
|
916
|
-
normalizedModule.virtualMachine = legacyModule.virtualMachine.includes('ark') ? 'ark' : 'default';
|
|
917
|
-
}
|
|
918
|
-
await fs_extra_1.default.writeFile(moduleJson5Path, JSON.stringify({
|
|
919
|
-
module: normalizedModule,
|
|
920
|
-
}, null, 2) + '\n');
|
|
921
|
-
}
|
|
922
|
-
async function ensureHarmonyBuildProfileSupportsNormalizedLocalDeps(harmonyProjectRoot, localHarPackages) {
|
|
923
|
-
if (localHarPackages.length === 0) {
|
|
924
|
-
return async () => { };
|
|
925
|
-
}
|
|
926
|
-
const buildProfilePath = path_1.default.join(harmonyProjectRoot, 'build-profile.json5');
|
|
927
|
-
if (!(await fs_extra_1.default.pathExists(buildProfilePath))) {
|
|
928
|
-
return async () => { };
|
|
929
|
-
}
|
|
930
|
-
const rawContents = await fs_extra_1.default.readFile(buildProfilePath, 'utf8');
|
|
931
|
-
const parsed = json5_1.default.parse(rawContents);
|
|
932
|
-
let didChange = false;
|
|
933
|
-
const products = Array.isArray(parsed.app?.products) ? parsed.app.products : [];
|
|
934
|
-
for (const product of products) {
|
|
935
|
-
let buildOption = product.buildOption;
|
|
936
|
-
if (!buildOption || typeof buildOption !== 'object' || Array.isArray(buildOption)) {
|
|
937
|
-
buildOption = {};
|
|
938
|
-
product.buildOption = buildOption;
|
|
939
|
-
didChange = true;
|
|
940
|
-
}
|
|
941
|
-
let strictMode = buildOption.strictMode;
|
|
942
|
-
if (!strictMode || typeof strictMode !== 'object' || Array.isArray(strictMode)) {
|
|
943
|
-
strictMode = {};
|
|
944
|
-
buildOption.strictMode = strictMode;
|
|
945
|
-
didChange = true;
|
|
946
|
-
}
|
|
947
|
-
if (strictMode.useNormalizedOHMUrl !== true) {
|
|
948
|
-
strictMode.useNormalizedOHMUrl = true;
|
|
949
|
-
didChange = true;
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
if (!Array.isArray(parsed.modules)) {
|
|
953
|
-
parsed.modules = [];
|
|
954
|
-
didChange = true;
|
|
955
|
-
}
|
|
956
|
-
for (const localHarPackage of localHarPackages) {
|
|
957
|
-
let relativeDirectory = path_1.default.relative(harmonyProjectRoot, localHarPackage.directoryPath);
|
|
958
|
-
relativeDirectory = relativeDirectory.split(path_1.default.sep).join('/');
|
|
959
|
-
if (!relativeDirectory.startsWith('.')) {
|
|
960
|
-
relativeDirectory = `./${relativeDirectory}`;
|
|
961
|
-
}
|
|
962
|
-
const existingModule = parsed.modules.find((moduleEntry) => {
|
|
963
|
-
return (moduleEntry?.srcPath === relativeDirectory ||
|
|
964
|
-
moduleEntry?.name === localHarPackage.moduleName);
|
|
965
|
-
});
|
|
966
|
-
if (existingModule) {
|
|
967
|
-
if (existingModule.srcPath !== relativeDirectory) {
|
|
968
|
-
existingModule.srcPath = relativeDirectory;
|
|
969
|
-
didChange = true;
|
|
970
|
-
}
|
|
971
|
-
continue;
|
|
972
|
-
}
|
|
973
|
-
parsed.modules.push({
|
|
974
|
-
name: localHarPackage.moduleName,
|
|
975
|
-
srcPath: relativeDirectory,
|
|
976
|
-
});
|
|
977
|
-
didChange = true;
|
|
978
|
-
}
|
|
979
|
-
if (!didChange) {
|
|
980
|
-
return async () => { };
|
|
981
|
-
}
|
|
982
|
-
await fs_extra_1.default.writeFile(buildProfilePath, JSON.stringify(parsed, null, 2) + '\n');
|
|
983
|
-
return async () => {
|
|
984
|
-
await fs_extra_1.default.writeFile(buildProfilePath, rawContents);
|
|
985
|
-
};
|
|
986
|
-
}
|
|
987
|
-
async function ensureRnohGeneratedTsShim(harmonyProjectRoot) {
|
|
988
|
-
const shimPath = path_1.default.join(harmonyProjectRoot, RNOH_GENERATED_TS_SHIM_RELATIVE_PATH);
|
|
989
|
-
let relativeTarget = path_1.default.relative(path_1.default.dirname(shimPath), path_1.default.join(harmonyProjectRoot, RNOH_NORMALIZED_TS_TARGET_RELATIVE_PATH));
|
|
990
|
-
relativeTarget = relativeTarget.replace(/\\/g, '/').replace(/\.ts$/, '');
|
|
991
|
-
if (!relativeTarget.startsWith('.')) {
|
|
992
|
-
relativeTarget = `./${relativeTarget}`;
|
|
993
|
-
}
|
|
994
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(shimPath));
|
|
995
|
-
await fs_extra_1.default.writeFile(shimPath, `export * from '${relativeTarget}';\n`);
|
|
996
|
-
}
|
|
997
|
-
async function alignRnohCodegenWithNormalizedLocalPackage(harmonyProjectRoot, localHarPackages) {
|
|
998
|
-
const rnohPackage = localHarPackages.find((localPackage) => localPackage.packageName === '@rnoh/react-native-openharmony');
|
|
999
|
-
if (!rnohPackage) {
|
|
1000
|
-
return async () => { };
|
|
1001
|
-
}
|
|
1002
|
-
const hvigorFilePath = path_1.default.join(harmonyProjectRoot, 'entry', 'hvigorfile.ts');
|
|
1003
|
-
if (!(await fs_extra_1.default.pathExists(hvigorFilePath))) {
|
|
1004
|
-
return async () => { };
|
|
1005
|
-
}
|
|
1006
|
-
const originalHvigorFile = await fs_extra_1.default.readFile(hvigorFilePath, 'utf8');
|
|
1007
|
-
let relativeRnohModulePath = path_1.default.relative(harmonyProjectRoot, rnohPackage.directoryPath);
|
|
1008
|
-
relativeRnohModulePath = relativeRnohModulePath.split(path_1.default.sep).join('/');
|
|
1009
|
-
if (!relativeRnohModulePath.startsWith('.')) {
|
|
1010
|
-
relativeRnohModulePath = `./${relativeRnohModulePath}`;
|
|
1011
|
-
}
|
|
1012
|
-
const updatedHvigorFile = originalHvigorFile.replace(/rnohModulePath:\s*['"][^'"]+['"]/, `rnohModulePath: '${relativeRnohModulePath}'`);
|
|
1013
|
-
if (updatedHvigorFile !== originalHvigorFile) {
|
|
1014
|
-
await fs_extra_1.default.writeFile(hvigorFilePath, updatedHvigorFile);
|
|
1015
|
-
}
|
|
1016
|
-
const generatedModuleRootPath = path_1.default.join(harmonyProjectRoot, RNOH_GENERATED_MODULE_ROOT_RELATIVE_PATH);
|
|
1017
|
-
const backupRootPath = await fs_extra_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'expo-harmony-rnoh-module-'));
|
|
1018
|
-
const backupModuleRootPath = path_1.default.join(backupRootPath, 'react-native-openharmony');
|
|
1019
|
-
let movedGeneratedModuleRoot = false;
|
|
1020
|
-
if (await fs_extra_1.default.pathExists(generatedModuleRootPath)) {
|
|
1021
|
-
await fs_extra_1.default.move(generatedModuleRootPath, backupModuleRootPath, { overwrite: true });
|
|
1022
|
-
movedGeneratedModuleRoot = true;
|
|
1023
|
-
}
|
|
1024
|
-
return async () => {
|
|
1025
|
-
if (updatedHvigorFile !== originalHvigorFile) {
|
|
1026
|
-
await fs_extra_1.default.writeFile(hvigorFilePath, originalHvigorFile);
|
|
1027
|
-
}
|
|
1028
|
-
if (movedGeneratedModuleRoot) {
|
|
1029
|
-
await fs_extra_1.default.remove(generatedModuleRootPath);
|
|
1030
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(generatedModuleRootPath));
|
|
1031
|
-
await fs_extra_1.default.move(backupModuleRootPath, generatedModuleRootPath, { overwrite: true });
|
|
1032
|
-
}
|
|
1033
|
-
await fs_extra_1.default.remove(backupRootPath);
|
|
1034
|
-
};
|
|
1035
|
-
}
|
|
1036
|
-
async function normalizeProjectRnohCliAutolinkingTemplates(projectRoot) {
|
|
1037
|
-
const originalContentsByPath = new Map();
|
|
1038
|
-
for (const relativePath of RNOH_CLI_AUTOLINKING_TEMPLATE_RELATIVE_PATHS) {
|
|
1039
|
-
const targetPath = path_1.default.join(projectRoot, relativePath);
|
|
1040
|
-
if (!(await fs_extra_1.default.pathExists(targetPath))) {
|
|
1041
|
-
continue;
|
|
1042
|
-
}
|
|
1043
|
-
const currentContents = await fs_extra_1.default.readFile(targetPath, 'utf8');
|
|
1044
|
-
const normalizedContents = normalizeRnohCliAutolinkingTemplateContents(currentContents);
|
|
1045
|
-
if (normalizedContents === currentContents) {
|
|
1046
|
-
continue;
|
|
1047
|
-
}
|
|
1048
|
-
originalContentsByPath.set(targetPath, currentContents);
|
|
1049
|
-
await fs_extra_1.default.writeFile(targetPath, normalizedContents);
|
|
1050
|
-
}
|
|
1051
|
-
return async () => {
|
|
1052
|
-
for (const [targetPath, originalContents] of originalContentsByPath.entries()) {
|
|
1053
|
-
await fs_extra_1.default.writeFile(targetPath, originalContents);
|
|
1054
|
-
}
|
|
1055
|
-
};
|
|
1056
|
-
}
|
|
1057
|
-
function normalizeRnohCliAutolinkingTemplateContents(contents) {
|
|
1058
|
-
return contents
|
|
1059
|
-
.replace(/import type \{ RNPackageContext, RNOHPackage \} from '@rnoh\/react-native-openharmony';/g, "import type { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony';")
|
|
1060
|
-
.replace(/export function createRNOHPackages\(ctx: RNPackageContext\): RNOHPackage\[\] \{/g, 'export function createRNOHPackages(ctx: RNPackageContext): RNPackage[] {');
|
|
1061
|
-
}
|
|
1062
|
-
async function findHarmonyArtifacts(harmonyProjectRoot) {
|
|
1063
|
-
const discoveredPaths = [];
|
|
1064
|
-
await walkDirectory(harmonyProjectRoot, async (entryPath) => {
|
|
1065
|
-
if (entryPath.endsWith('.hap') || entryPath.endsWith('.app') || entryPath.endsWith('.hsp')) {
|
|
1066
|
-
discoveredPaths.push(entryPath);
|
|
1067
|
-
}
|
|
1068
|
-
});
|
|
1069
|
-
return discoveredPaths.sort((left, right) => left.localeCompare(right));
|
|
1070
|
-
}
|
|
1071
|
-
async function walkDirectory(currentPath, visitor) {
|
|
1072
|
-
if (!(await fs_extra_1.default.pathExists(currentPath))) {
|
|
1073
|
-
return;
|
|
1074
|
-
}
|
|
1075
|
-
const entries = await fs_extra_1.default.readdir(currentPath, { withFileTypes: true });
|
|
1076
|
-
for (const entry of entries) {
|
|
1077
|
-
const nextPath = path_1.default.join(currentPath, entry.name);
|
|
1078
|
-
if (entry.isDirectory()) {
|
|
1079
|
-
await walkDirectory(nextPath, visitor);
|
|
1080
|
-
continue;
|
|
1081
|
-
}
|
|
1082
|
-
await visitor(nextPath);
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
async function defaultCommandRunner(file, args, options) {
|
|
1086
|
-
try {
|
|
1087
|
-
const result = await execFileAsync(file, args, {
|
|
1088
|
-
cwd: options.cwd,
|
|
1089
|
-
env: options.env,
|
|
1090
|
-
maxBuffer: 20 * 1024 * 1024,
|
|
1091
|
-
});
|
|
1092
|
-
return {
|
|
1093
|
-
exitCode: 0,
|
|
1094
|
-
stdout: result.stdout,
|
|
1095
|
-
stderr: result.stderr,
|
|
1096
|
-
};
|
|
1097
|
-
}
|
|
1098
|
-
catch (error) {
|
|
1099
|
-
const failed = error;
|
|
1100
|
-
return {
|
|
1101
|
-
exitCode: typeof failed.code === 'number' ? failed.code : 1,
|
|
1102
|
-
stdout: failed.stdout ?? '',
|
|
1103
|
-
stderr: failed.stderr ?? failed.message ?? '',
|
|
1104
|
-
};
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
415
|
function getDesiredHarmonyScripts(projectRoot) {
|
|
1108
416
|
return (0, project_1.loadProject)(projectRoot).then((loadedProject) => (0, template_1.buildDesiredPackageScripts)(loadedProject.packageJson));
|
|
1109
417
|
}
|