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.
Files changed (67) hide show
  1. package/README.en.md +20 -9
  2. package/README.md +22 -11
  3. package/build/core/autolinking.d.ts +10 -0
  4. package/build/core/autolinking.js +421 -0
  5. package/build/core/build/commands.d.ts +19 -0
  6. package/build/core/build/commands.js +61 -0
  7. package/build/core/build/compatibilityShims.d.ts +1 -0
  8. package/build/core/build/compatibilityShims.js +272 -0
  9. package/build/core/build/localHar.d.ts +13 -0
  10. package/build/core/build/localHar.js +337 -0
  11. package/build/core/build/reporting.d.ts +19 -0
  12. package/build/core/build/reporting.js +67 -0
  13. package/build/core/build/rnohCompatibility.d.ts +1 -0
  14. package/build/core/build/rnohCompatibility.js +38 -0
  15. package/build/core/build.d.ts +4 -12
  16. package/build/core/build.js +70 -762
  17. package/build/core/constants.d.ts +2 -1
  18. package/build/core/constants.js +3 -2
  19. package/build/core/dependencyInspection.d.ts +2 -0
  20. package/build/core/dependencyInspection.js +112 -0
  21. package/build/core/env.js +1 -1
  22. package/build/core/report.js +33 -10
  23. package/build/core/signing.d.ts +2 -0
  24. package/build/core/signing.js +30 -0
  25. package/build/core/template/capabilityRegistry.d.ts +9 -0
  26. package/build/core/template/capabilityRegistry.js +84 -0
  27. package/build/core/template/expoModulesCoreShim.d.ts +2 -0
  28. package/build/core/template/expoModulesCoreShim.js +279 -0
  29. package/build/core/template/metro.d.ts +2 -0
  30. package/build/core/template/metro.js +213 -0
  31. package/build/core/template/nativeFiles.d.ts +8 -0
  32. package/build/core/template/nativeFiles.js +333 -0
  33. package/build/core/template/renderers/camera.d.ts +4 -0
  34. package/build/core/template/renderers/camera.js +612 -0
  35. package/build/core/template/renderers/fileSystem.d.ts +4 -0
  36. package/build/core/template/renderers/fileSystem.js +814 -0
  37. package/build/core/template/renderers/imagePicker.d.ts +4 -0
  38. package/build/core/template/renderers/imagePicker.js +753 -0
  39. package/build/core/template/renderers/location.d.ts +4 -0
  40. package/build/core/template/renderers/location.js +836 -0
  41. package/build/core/template/runtimeShims.d.ts +2 -0
  42. package/build/core/template/runtimeShims.js +192 -0
  43. package/build/core/template/support.d.ts +11 -0
  44. package/build/core/template/support.js +108 -0
  45. package/build/core/template.d.ts +2 -6
  46. package/build/core/template.js +47 -3966
  47. package/build/data/capabilities.js +45 -19
  48. package/build/data/dependencyCatalog.js +10 -0
  49. package/build/data/publicDocs.d.ts +11 -0
  50. package/build/data/publicDocs.js +28 -0
  51. package/build/data/validatedMatrices.js +9 -1
  52. package/build/docs/render.d.ts +9 -0
  53. package/build/docs/render.js +248 -0
  54. package/build/types.d.ts +12 -0
  55. package/docs/cli-build.md +1 -1
  56. package/docs/npm-release.md +1 -0
  57. package/docs/official-app-shell-sample.md +2 -1
  58. package/docs/official-minimal-sample.md +2 -1
  59. package/docs/official-native-capabilities-sample.md +28 -47
  60. package/docs/official-ui-stack-sample.md +2 -1
  61. package/docs/signing-and-release.md +3 -0
  62. package/docs/support-matrix.md +38 -16
  63. package/package.json +13 -5
  64. package/docs/v1.5.1-acceptance.md +0 -385
  65. package/docs/v1.6.0-acceptance.md +0 -193
  66. package/docs/v1.7.0-acceptance.md +0 -111
  67. package/docs/v1.7.1-acceptance.md +0 -111
@@ -0,0 +1,337 @@
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.normalizeLocalHarDependencies = normalizeLocalHarDependencies;
7
+ exports.ensureHarmonyBuildProfileSupportsNormalizedLocalDeps = ensureHarmonyBuildProfileSupportsNormalizedLocalDeps;
8
+ exports.ensureRnohGeneratedTsShim = ensureRnohGeneratedTsShim;
9
+ exports.alignRnohCodegenWithNormalizedLocalPackage = alignRnohCodegenWithNormalizedLocalPackage;
10
+ exports.findHarmonyArtifacts = findHarmonyArtifacts;
11
+ const node_child_process_1 = require("node:child_process");
12
+ const json5_1 = __importDefault(require("json5"));
13
+ const fs_extra_1 = __importDefault(require("fs-extra"));
14
+ const os_1 = __importDefault(require("os"));
15
+ const path_1 = __importDefault(require("path"));
16
+ const node_util_1 = require("node:util");
17
+ const compatibilityShims_1 = require("./compatibilityShims");
18
+ const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
19
+ const RNOH_GENERATED_TS_SHIM_RELATIVE_PATH = path_1.default.join('oh_modules', '@rnoh', 'react-native-openharmony', 'ts.ts');
20
+ const RNOH_GENERATED_MODULE_ROOT_RELATIVE_PATH = path_1.default.join('oh_modules', '@rnoh', 'react-native-openharmony');
21
+ const RNOH_NORMALIZED_TS_TARGET_RELATIVE_PATH = path_1.default.join('expo-harmony-local-deps', 'rnoh-react-native-openharmony-react_native_openharmony', 'ts.ts');
22
+ async function normalizeLocalHarDependencies(harmonyProjectRoot) {
23
+ const packagePaths = [
24
+ path_1.default.join(harmonyProjectRoot, 'oh-package.json5'),
25
+ path_1.default.join(harmonyProjectRoot, 'entry', 'oh-package.json5'),
26
+ ];
27
+ const extractionRoot = path_1.default.join(harmonyProjectRoot, 'expo-harmony-local-deps');
28
+ const archiveCache = new Map();
29
+ const originalContents = new Map();
30
+ const packagesByDirectoryPath = new Map();
31
+ await fs_extra_1.default.ensureDir(extractionRoot);
32
+ for (const packagePath of packagePaths) {
33
+ if (!(await fs_extra_1.default.pathExists(packagePath))) {
34
+ continue;
35
+ }
36
+ const rawContents = await fs_extra_1.default.readFile(packagePath, 'utf8');
37
+ const parsed = json5_1.default.parse(rawContents);
38
+ let didChange = false;
39
+ for (const sectionName of ['dependencies', 'devDependencies', 'overrides']) {
40
+ const section = parsed[sectionName];
41
+ if (!section || typeof section !== 'object' || Array.isArray(section)) {
42
+ continue;
43
+ }
44
+ for (const [packageName, specifier] of Object.entries(section)) {
45
+ if (typeof specifier !== 'string' || !specifier.startsWith('file:') || !specifier.endsWith('.har')) {
46
+ continue;
47
+ }
48
+ const archivePath = path_1.default.resolve(harmonyProjectRoot, specifier.slice('file:'.length));
49
+ const normalizedDirectory = archiveCache.get(archivePath) ??
50
+ (await extractHarArchiveToDirectory(archivePath, extractionRoot, packageName));
51
+ archiveCache.set(archivePath, normalizedDirectory);
52
+ if (!packagesByDirectoryPath.has(normalizedDirectory)) {
53
+ packagesByDirectoryPath.set(normalizedDirectory, await readNormalizedLocalHarPackageMetadata(normalizedDirectory, packageName));
54
+ }
55
+ let relativeDirectory = path_1.default.relative(harmonyProjectRoot, normalizedDirectory);
56
+ if (!relativeDirectory.startsWith('.')) {
57
+ relativeDirectory = `./${relativeDirectory}`;
58
+ }
59
+ const nextSpecifier = `file:${relativeDirectory.split(path_1.default.sep).join('/')}`;
60
+ if (nextSpecifier !== specifier) {
61
+ section[packageName] = nextSpecifier;
62
+ didChange = true;
63
+ }
64
+ }
65
+ }
66
+ if (didChange) {
67
+ originalContents.set(packagePath, rawContents);
68
+ await fs_extra_1.default.writeFile(packagePath, JSON.stringify(parsed, null, 2) + '\n');
69
+ }
70
+ }
71
+ return {
72
+ packages: [...packagesByDirectoryPath.values()],
73
+ restore: async () => {
74
+ for (const [packagePath, rawContents] of originalContents) {
75
+ await fs_extra_1.default.writeFile(packagePath, rawContents);
76
+ }
77
+ },
78
+ };
79
+ }
80
+ async function extractHarArchiveToDirectory(archivePath, extractionRoot, packageName) {
81
+ if (!(await fs_extra_1.default.pathExists(archivePath))) {
82
+ throw new Error(`Local Harmony archive not found: ${archivePath}`);
83
+ }
84
+ const destinationPath = path_1.default.join(extractionRoot, `${sanitizePackageName(packageName)}-${path_1.default.basename(archivePath, path_1.default.extname(archivePath))}`);
85
+ const stagingRoot = await fs_extra_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'expo-harmony-har-'));
86
+ try {
87
+ await execFileAsync('tar', ['-xzf', archivePath, '-C', stagingRoot], {
88
+ maxBuffer: 20 * 1024 * 1024,
89
+ });
90
+ const packagedRoot = path_1.default.join(stagingRoot, 'package');
91
+ const sourceRoot = (await fs_extra_1.default.pathExists(path_1.default.join(packagedRoot, 'oh-package.json5')))
92
+ ? packagedRoot
93
+ : stagingRoot;
94
+ if (!(await fs_extra_1.default.pathExists(path_1.default.join(sourceRoot, 'oh-package.json5')))) {
95
+ throw new Error(`oh-package.json5 not found after extracting ${archivePath}`);
96
+ }
97
+ await fs_extra_1.default.remove(destinationPath);
98
+ await fs_extra_1.default.ensureDir(destinationPath);
99
+ for (const entryName of await fs_extra_1.default.readdir(sourceRoot)) {
100
+ await fs_extra_1.default.move(path_1.default.join(sourceRoot, entryName), path_1.default.join(destinationPath, entryName), {
101
+ overwrite: true,
102
+ });
103
+ }
104
+ await (0, compatibilityShims_1.ensureNormalizedLocalHarCompatibilityShims)(destinationPath, packageName);
105
+ return destinationPath;
106
+ }
107
+ catch (error) {
108
+ const message = error instanceof Error ? error.message : String(error);
109
+ throw new Error(`Failed to normalize local Harmony archive ${archivePath}: ${message}`);
110
+ }
111
+ finally {
112
+ await fs_extra_1.default.remove(stagingRoot);
113
+ }
114
+ }
115
+ function sanitizePackageName(packageName) {
116
+ return packageName.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
117
+ }
118
+ async function readNormalizedLocalHarPackageMetadata(directoryPath, packageName) {
119
+ await ensureNormalizedLocalHarModuleJson5(directoryPath);
120
+ const moduleJsonPaths = [
121
+ path_1.default.join(directoryPath, 'src', 'main', 'module.json5'),
122
+ path_1.default.join(directoryPath, 'src', 'main', 'module.json'),
123
+ ];
124
+ let moduleName = sanitizePackageName(packageName);
125
+ for (const moduleJsonPath of moduleJsonPaths) {
126
+ if (!(await fs_extra_1.default.pathExists(moduleJsonPath))) {
127
+ continue;
128
+ }
129
+ try {
130
+ const parsed = json5_1.default.parse(await fs_extra_1.default.readFile(moduleJsonPath, 'utf8'));
131
+ if (typeof parsed?.module?.name === 'string' && parsed.module.name.trim().length > 0) {
132
+ moduleName = parsed.module.name.trim();
133
+ break;
134
+ }
135
+ }
136
+ catch {
137
+ // Ignore malformed module metadata and fall back to a sanitized package name.
138
+ }
139
+ }
140
+ return {
141
+ packageName,
142
+ moduleName,
143
+ directoryPath,
144
+ };
145
+ }
146
+ async function ensureNormalizedLocalHarModuleJson5(directoryPath) {
147
+ const moduleJson5Path = path_1.default.join(directoryPath, 'src', 'main', 'module.json5');
148
+ const moduleJsonPath = path_1.default.join(directoryPath, 'src', 'main', 'module.json');
149
+ const sourcePath = (await fs_extra_1.default.pathExists(moduleJsonPath))
150
+ ? moduleJsonPath
151
+ : ((await fs_extra_1.default.pathExists(moduleJson5Path)) ? moduleJson5Path : null);
152
+ if (!sourcePath) {
153
+ return;
154
+ }
155
+ const parsed = json5_1.default.parse(await fs_extra_1.default.readFile(sourcePath, 'utf8'));
156
+ const legacyModule = parsed.module && typeof parsed.module === 'object' && !Array.isArray(parsed.module)
157
+ ? parsed.module
158
+ : {};
159
+ const normalizedModule = {
160
+ name: typeof legacyModule.name === 'string' && legacyModule.name.trim().length > 0
161
+ ? legacyModule.name.trim()
162
+ : path_1.default.basename(directoryPath).replace(/[^a-zA-Z0-9]+/g, '_'),
163
+ type: typeof legacyModule.type === 'string' ? legacyModule.type : 'har',
164
+ deviceTypes: Array.isArray(legacyModule.deviceTypes) && legacyModule.deviceTypes.length > 0
165
+ ? legacyModule.deviceTypes
166
+ : ['default'],
167
+ installationFree: typeof legacyModule.installationFree === 'boolean' ? legacyModule.installationFree : false,
168
+ };
169
+ const passthroughKeys = [
170
+ 'srcEntrance',
171
+ 'srcEntry',
172
+ 'description',
173
+ 'process',
174
+ 'mainElement',
175
+ 'uiSyntax',
176
+ 'metadata',
177
+ 'abilities',
178
+ 'extensionAbilities',
179
+ 'requestPermissions',
180
+ 'definePermissions',
181
+ 'testRunner',
182
+ 'dependencies',
183
+ 'libIsolation',
184
+ 'routerMap',
185
+ 'appStartup',
186
+ 'crossAppSharedConfig',
187
+ ];
188
+ for (const key of passthroughKeys) {
189
+ const value = legacyModule[key];
190
+ if (value !== undefined) {
191
+ normalizedModule[key] = value;
192
+ }
193
+ }
194
+ if (typeof legacyModule.virtualMachine === 'string') {
195
+ normalizedModule.virtualMachine = legacyModule.virtualMachine.includes('ark') ? 'ark' : 'default';
196
+ }
197
+ await fs_extra_1.default.writeFile(moduleJson5Path, JSON.stringify({
198
+ module: normalizedModule,
199
+ }, null, 2) + '\n');
200
+ }
201
+ async function ensureHarmonyBuildProfileSupportsNormalizedLocalDeps(harmonyProjectRoot, localHarPackages) {
202
+ if (localHarPackages.length === 0) {
203
+ return async () => { };
204
+ }
205
+ const buildProfilePath = path_1.default.join(harmonyProjectRoot, 'build-profile.json5');
206
+ if (!(await fs_extra_1.default.pathExists(buildProfilePath))) {
207
+ return async () => { };
208
+ }
209
+ const rawContents = await fs_extra_1.default.readFile(buildProfilePath, 'utf8');
210
+ const parsed = json5_1.default.parse(rawContents);
211
+ let didChange = false;
212
+ const products = Array.isArray(parsed.app?.products) ? parsed.app.products : [];
213
+ for (const product of products) {
214
+ let buildOption = product.buildOption;
215
+ if (!buildOption || typeof buildOption !== 'object' || Array.isArray(buildOption)) {
216
+ buildOption = {};
217
+ product.buildOption = buildOption;
218
+ didChange = true;
219
+ }
220
+ let strictMode = buildOption.strictMode;
221
+ if (!strictMode || typeof strictMode !== 'object' || Array.isArray(strictMode)) {
222
+ strictMode = {};
223
+ buildOption.strictMode = strictMode;
224
+ didChange = true;
225
+ }
226
+ if (strictMode.useNormalizedOHMUrl !== true) {
227
+ strictMode.useNormalizedOHMUrl = true;
228
+ didChange = true;
229
+ }
230
+ }
231
+ if (!Array.isArray(parsed.modules)) {
232
+ parsed.modules = [];
233
+ didChange = true;
234
+ }
235
+ for (const localHarPackage of localHarPackages) {
236
+ let relativeDirectory = path_1.default.relative(harmonyProjectRoot, localHarPackage.directoryPath);
237
+ relativeDirectory = relativeDirectory.split(path_1.default.sep).join('/');
238
+ if (!relativeDirectory.startsWith('.')) {
239
+ relativeDirectory = `./${relativeDirectory}`;
240
+ }
241
+ const existingModule = parsed.modules.find((moduleEntry) => {
242
+ return (moduleEntry?.srcPath === relativeDirectory ||
243
+ moduleEntry?.name === localHarPackage.moduleName);
244
+ });
245
+ if (existingModule) {
246
+ if (existingModule.srcPath !== relativeDirectory) {
247
+ existingModule.srcPath = relativeDirectory;
248
+ didChange = true;
249
+ }
250
+ continue;
251
+ }
252
+ parsed.modules.push({
253
+ name: localHarPackage.moduleName,
254
+ srcPath: relativeDirectory,
255
+ });
256
+ didChange = true;
257
+ }
258
+ if (!didChange) {
259
+ return async () => { };
260
+ }
261
+ await fs_extra_1.default.writeFile(buildProfilePath, JSON.stringify(parsed, null, 2) + '\n');
262
+ return async () => {
263
+ await fs_extra_1.default.writeFile(buildProfilePath, rawContents);
264
+ };
265
+ }
266
+ async function ensureRnohGeneratedTsShim(harmonyProjectRoot) {
267
+ const shimPath = path_1.default.join(harmonyProjectRoot, RNOH_GENERATED_TS_SHIM_RELATIVE_PATH);
268
+ let relativeTarget = path_1.default.relative(path_1.default.dirname(shimPath), path_1.default.join(harmonyProjectRoot, RNOH_NORMALIZED_TS_TARGET_RELATIVE_PATH));
269
+ relativeTarget = relativeTarget.replace(/\\/g, '/').replace(/\.ts$/, '');
270
+ if (!relativeTarget.startsWith('.')) {
271
+ relativeTarget = `./${relativeTarget}`;
272
+ }
273
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(shimPath));
274
+ await fs_extra_1.default.writeFile(shimPath, `export * from '${relativeTarget}';\n`);
275
+ }
276
+ async function alignRnohCodegenWithNormalizedLocalPackage(harmonyProjectRoot, localHarPackages) {
277
+ const rnohPackage = localHarPackages.find((localPackage) => localPackage.packageName === '@rnoh/react-native-openharmony');
278
+ if (!rnohPackage) {
279
+ return async () => { };
280
+ }
281
+ const hvigorFilePath = path_1.default.join(harmonyProjectRoot, 'entry', 'hvigorfile.ts');
282
+ if (!(await fs_extra_1.default.pathExists(hvigorFilePath))) {
283
+ return async () => { };
284
+ }
285
+ const originalHvigorFile = await fs_extra_1.default.readFile(hvigorFilePath, 'utf8');
286
+ let relativeRnohModulePath = path_1.default.relative(harmonyProjectRoot, rnohPackage.directoryPath);
287
+ relativeRnohModulePath = relativeRnohModulePath.split(path_1.default.sep).join('/');
288
+ if (!relativeRnohModulePath.startsWith('.')) {
289
+ relativeRnohModulePath = `./${relativeRnohModulePath}`;
290
+ }
291
+ const updatedHvigorFile = originalHvigorFile.replace(/rnohModulePath:\s*['"][^'"]+['"]/, `rnohModulePath: '${relativeRnohModulePath}'`);
292
+ if (updatedHvigorFile !== originalHvigorFile) {
293
+ await fs_extra_1.default.writeFile(hvigorFilePath, updatedHvigorFile);
294
+ }
295
+ const generatedModuleRootPath = path_1.default.join(harmonyProjectRoot, RNOH_GENERATED_MODULE_ROOT_RELATIVE_PATH);
296
+ const backupRootPath = await fs_extra_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'expo-harmony-rnoh-module-'));
297
+ const backupModuleRootPath = path_1.default.join(backupRootPath, 'react-native-openharmony');
298
+ let movedGeneratedModuleRoot = false;
299
+ if (await fs_extra_1.default.pathExists(generatedModuleRootPath)) {
300
+ await fs_extra_1.default.move(generatedModuleRootPath, backupModuleRootPath, { overwrite: true });
301
+ movedGeneratedModuleRoot = true;
302
+ }
303
+ return async () => {
304
+ if (updatedHvigorFile !== originalHvigorFile) {
305
+ await fs_extra_1.default.writeFile(hvigorFilePath, originalHvigorFile);
306
+ }
307
+ if (movedGeneratedModuleRoot) {
308
+ await fs_extra_1.default.remove(generatedModuleRootPath);
309
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(generatedModuleRootPath));
310
+ await fs_extra_1.default.move(backupModuleRootPath, generatedModuleRootPath, { overwrite: true });
311
+ }
312
+ await fs_extra_1.default.remove(backupRootPath);
313
+ };
314
+ }
315
+ async function findHarmonyArtifacts(harmonyProjectRoot) {
316
+ const discoveredPaths = [];
317
+ await walkDirectory(harmonyProjectRoot, async (entryPath) => {
318
+ if (entryPath.endsWith('.hap') || entryPath.endsWith('.app') || entryPath.endsWith('.hsp')) {
319
+ discoveredPaths.push(entryPath);
320
+ }
321
+ });
322
+ return discoveredPaths.sort((left, right) => left.localeCompare(right));
323
+ }
324
+ async function walkDirectory(currentPath, visitor) {
325
+ if (!(await fs_extra_1.default.pathExists(currentPath))) {
326
+ return;
327
+ }
328
+ const entries = await fs_extra_1.default.readdir(currentPath, { withFileTypes: true });
329
+ for (const entry of entries) {
330
+ const nextPath = path_1.default.join(currentPath, entry.name);
331
+ if (entry.isDirectory()) {
332
+ await walkDirectory(nextPath, visitor);
333
+ continue;
334
+ }
335
+ await visitor(nextPath);
336
+ }
337
+ }
@@ -0,0 +1,19 @@
1
+ import { BlockingIssue, BuildReport, BuildStepReport } from '../../types';
2
+ export declare function renderBuildReport(report: BuildReport): string;
3
+ export declare function getBundleOutputPath(projectRoot: string): string;
4
+ export declare function getAssetsOutputPath(projectRoot: string): string;
5
+ export declare function createBuildReport(input: {
6
+ projectRoot: string;
7
+ command: BuildReport['command'];
8
+ mode: BuildReport['mode'];
9
+ status: BuildReport['status'];
10
+ harmonyProjectRoot?: string | null;
11
+ entryFile: string | null;
12
+ bundleOutputPath: string | null;
13
+ assetsDestPath: string | null;
14
+ artifactPaths: string[];
15
+ blockingIssues: BlockingIssue[];
16
+ warnings: string[];
17
+ steps: BuildStepReport[];
18
+ }): BuildReport;
19
+ export declare function createStepReport(label: string, file: string, args: string[], cwd: string, exitCode: number | null): BuildStepReport;
@@ -0,0 +1,67 @@
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.renderBuildReport = renderBuildReport;
7
+ exports.getBundleOutputPath = getBundleOutputPath;
8
+ exports.getAssetsOutputPath = getAssetsOutputPath;
9
+ exports.createBuildReport = createBuildReport;
10
+ exports.createStepReport = createStepReport;
11
+ const path_1 = __importDefault(require("path"));
12
+ const constants_1 = require("../constants");
13
+ function renderBuildReport(report) {
14
+ const lines = [
15
+ 'Expo Harmony build report',
16
+ `Project: ${report.projectRoot}`,
17
+ `Command: ${report.command}`,
18
+ `Mode: ${report.mode ?? 'n/a'}`,
19
+ `Status: ${report.status}`,
20
+ `Harmony project: ${report.harmonyProjectRoot ?? 'not found'}`,
21
+ `Entry file: ${report.entryFile ?? 'n/a'}`,
22
+ `Bundle output: ${report.bundleOutputPath ?? 'n/a'}`,
23
+ `Artifacts: ${report.artifactPaths.join(', ') || 'none'}`,
24
+ '',
25
+ 'Steps:',
26
+ ...report.steps.map((step) => `- [${step.exitCode ?? 'n/a'}] ${step.label}: ${step.command} (cwd ${step.cwd})`),
27
+ ];
28
+ if (report.blockingIssues.length > 0) {
29
+ lines.push('', 'Blocking issues:', ...report.blockingIssues.map((issue) => `- ${issue.code}: ${issue.message}${issue.subject ? ` (${issue.subject})` : ''}`));
30
+ }
31
+ if (report.warnings.length > 0) {
32
+ lines.push('', 'Warnings:', ...report.warnings.map((warning) => `- ${warning}`));
33
+ }
34
+ return lines.join('\n');
35
+ }
36
+ function getBundleOutputPath(projectRoot) {
37
+ return path_1.default.join(projectRoot, 'harmony', 'entry', 'src', 'main', 'resources', 'rawfile', 'bundle.harmony.js');
38
+ }
39
+ function getAssetsOutputPath(projectRoot) {
40
+ return path_1.default.join(projectRoot, 'harmony', 'entry', 'src', 'main', 'resources', 'rawfile', 'assets');
41
+ }
42
+ function createBuildReport(input) {
43
+ return {
44
+ generatedAt: new Date().toISOString(),
45
+ projectRoot: input.projectRoot,
46
+ toolkitVersion: constants_1.TOOLKIT_VERSION,
47
+ command: input.command,
48
+ mode: input.mode,
49
+ status: input.status,
50
+ harmonyProjectRoot: input.harmonyProjectRoot ?? path_1.default.join(input.projectRoot, 'harmony'),
51
+ entryFile: input.entryFile,
52
+ bundleOutputPath: input.bundleOutputPath,
53
+ assetsDestPath: input.assetsDestPath,
54
+ artifactPaths: input.artifactPaths,
55
+ blockingIssues: input.blockingIssues,
56
+ warnings: input.warnings,
57
+ steps: input.steps,
58
+ };
59
+ }
60
+ function createStepReport(label, file, args, cwd, exitCode) {
61
+ return {
62
+ label,
63
+ command: [file, ...args].join(' '),
64
+ cwd,
65
+ exitCode,
66
+ };
67
+ }
@@ -0,0 +1 @@
1
+ export declare function normalizeProjectRnohCliAutolinkingTemplates(projectRoot: string): Promise<() => Promise<void>>;
@@ -0,0 +1,38 @@
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.normalizeProjectRnohCliAutolinkingTemplates = normalizeProjectRnohCliAutolinkingTemplates;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const RNOH_CLI_AUTOLINKING_TEMPLATE_RELATIVE_PATHS = [
10
+ path_1.default.join('node_modules', '@react-native-oh', 'react-native-harmony-cli', 'dist', 'autolinking', 'Autolinking.js'),
11
+ path_1.default.join('node_modules', '@react-native-oh', 'react-native-harmony-cli', 'src', 'autolinking', 'Autolinking.ts'),
12
+ ];
13
+ async function normalizeProjectRnohCliAutolinkingTemplates(projectRoot) {
14
+ const originalContentsByPath = new Map();
15
+ for (const relativePath of RNOH_CLI_AUTOLINKING_TEMPLATE_RELATIVE_PATHS) {
16
+ const targetPath = path_1.default.join(projectRoot, relativePath);
17
+ if (!(await fs_extra_1.default.pathExists(targetPath))) {
18
+ continue;
19
+ }
20
+ const currentContents = await fs_extra_1.default.readFile(targetPath, 'utf8');
21
+ const normalizedContents = normalizeRnohCliAutolinkingTemplateContents(currentContents);
22
+ if (normalizedContents === currentContents) {
23
+ continue;
24
+ }
25
+ originalContentsByPath.set(targetPath, currentContents);
26
+ await fs_extra_1.default.writeFile(targetPath, normalizedContents);
27
+ }
28
+ return async () => {
29
+ for (const [targetPath, originalContents] of originalContentsByPath.entries()) {
30
+ await fs_extra_1.default.writeFile(targetPath, originalContents);
31
+ }
32
+ };
33
+ }
34
+ function normalizeRnohCliAutolinkingTemplateContents(contents) {
35
+ return contents
36
+ .replace(/import type \{ RNPackageContext, RNOHPackage \} from '@rnoh\/react-native-openharmony';/g, "import type { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony';")
37
+ .replace(/export function createRNOHPackages\(ctx: RNPackageContext\): RNOHPackage\[\] \{/g, 'export function createRNOHPackages(ctx: RNPackageContext): RNPackage[] {');
38
+ }
@@ -1,13 +1,7 @@
1
- import { BuildReport } from '../types';
2
- export interface CommandRunnerResult {
3
- exitCode: number;
4
- stdout: string;
5
- stderr: string;
6
- }
7
- export type CommandRunner = (file: string, args: string[], options: {
8
- cwd: string;
9
- env: NodeJS.ProcessEnv;
10
- }) => Promise<CommandRunnerResult>;
1
+ import type { BuildReport } from '../types';
2
+ import type { CommandRunner } from './build/commands';
3
+ export type { CommandRunner, CommandRunnerResult } from './build/commands';
4
+ export { renderBuildReport } from './build/reporting';
11
5
  interface BundleProjectOptions {
12
6
  env?: NodeJS.ProcessEnv;
13
7
  runner?: CommandRunner;
@@ -20,6 +14,4 @@ interface BuildHapProjectOptions {
20
14
  }
21
15
  export declare function bundleProject(projectRoot: string, options?: BundleProjectOptions): Promise<BuildReport>;
22
16
  export declare function buildHapProject(projectRoot: string, options: BuildHapProjectOptions): Promise<BuildReport>;
23
- export declare function renderBuildReport(report: BuildReport): string;
24
17
  export declare function getDesiredHarmonyScripts(projectRoot: string): Promise<Record<string, string>>;
25
- export {};