expo-harmony-toolkit 1.5.0

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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +197 -0
  3. package/README.md +197 -0
  4. package/app.plugin.js +1 -0
  5. package/bin/expo-harmony.js +9 -0
  6. package/build/cli.d.ts +1 -0
  7. package/build/cli.js +56 -0
  8. package/build/commands/buildHap.d.ts +5 -0
  9. package/build/commands/buildHap.js +26 -0
  10. package/build/commands/bundle.d.ts +4 -0
  11. package/build/commands/bundle.js +18 -0
  12. package/build/commands/doctor.d.ts +7 -0
  13. package/build/commands/doctor.js +24 -0
  14. package/build/commands/env.d.ts +5 -0
  15. package/build/commands/env.js +22 -0
  16. package/build/commands/init.d.ts +5 -0
  17. package/build/commands/init.js +29 -0
  18. package/build/commands/syncTemplate.d.ts +5 -0
  19. package/build/commands/syncTemplate.js +23 -0
  20. package/build/core/build.d.ts +25 -0
  21. package/build/core/build.js +434 -0
  22. package/build/core/constants.d.ts +21 -0
  23. package/build/core/constants.js +32 -0
  24. package/build/core/env.d.ts +8 -0
  25. package/build/core/env.js +185 -0
  26. package/build/core/metadata.d.ts +9 -0
  27. package/build/core/metadata.js +54 -0
  28. package/build/core/project.d.ts +18 -0
  29. package/build/core/project.js +206 -0
  30. package/build/core/report.d.ts +4 -0
  31. package/build/core/report.js +319 -0
  32. package/build/core/template.d.ts +6 -0
  33. package/build/core/template.js +1030 -0
  34. package/build/data/compatibilityMatrix.d.ts +2 -0
  35. package/build/data/compatibilityMatrix.js +99 -0
  36. package/build/data/dependencyCatalog.d.ts +2 -0
  37. package/build/data/dependencyCatalog.js +108 -0
  38. package/build/data/uiStack.d.ts +39 -0
  39. package/build/data/uiStack.js +48 -0
  40. package/build/data/validatedMatrices.d.ts +3 -0
  41. package/build/data/validatedMatrices.js +94 -0
  42. package/build/index.d.ts +4 -0
  43. package/build/index.js +27 -0
  44. package/build/plugin.d.ts +7 -0
  45. package/build/plugin.js +76 -0
  46. package/build/types.d.ts +182 -0
  47. package/build/types.js +2 -0
  48. package/docs/cli-build.md +99 -0
  49. package/docs/npm-release.md +89 -0
  50. package/docs/official-app-shell-sample.md +39 -0
  51. package/docs/official-minimal-sample.md +32 -0
  52. package/docs/official-ui-stack-sample.md +77 -0
  53. package/docs/roadmap.md +67 -0
  54. package/docs/signing-and-release.md +57 -0
  55. package/docs/support-matrix.md +149 -0
  56. package/package.json +78 -0
  57. package/templates/harmony/AppScope/app.json5 +10 -0
  58. package/templates/harmony/AppScope/resources/base/element/string.json +8 -0
  59. package/templates/harmony/AppScope/resources/base/media/app_icon.png +0 -0
  60. package/templates/harmony/README.md +31 -0
  61. package/templates/harmony/build-profile.json5 +37 -0
  62. package/templates/harmony/codelinter.json +19 -0
  63. package/templates/harmony/entry/build-profile.json5 +18 -0
  64. package/templates/harmony/entry/hvigorfile.ts +13 -0
  65. package/templates/harmony/entry/oh-package.json5 +14 -0
  66. package/templates/harmony/entry/src/main/cpp/CMakeLists.txt +55 -0
  67. package/templates/harmony/entry/src/main/cpp/PackageProvider.cpp +12 -0
  68. package/templates/harmony/entry/src/main/ets/PackageProvider.ets +6 -0
  69. package/templates/harmony/entry/src/main/ets/entryability/EntryAbility.ets +11 -0
  70. package/templates/harmony/entry/src/main/ets/pages/Index.ets +42 -0
  71. package/templates/harmony/entry/src/main/ets/workers/RNOHWorker.ets +8 -0
  72. package/templates/harmony/entry/src/main/module.json5 +31 -0
  73. package/templates/harmony/entry/src/main/resources/base/element/color.json +8 -0
  74. package/templates/harmony/entry/src/main/resources/base/element/string.json +16 -0
  75. package/templates/harmony/entry/src/main/resources/base/media/background.png +0 -0
  76. package/templates/harmony/entry/src/main/resources/base/media/foreground.png +0 -0
  77. package/templates/harmony/entry/src/main/resources/base/media/layered_image.json +6 -0
  78. package/templates/harmony/entry/src/main/resources/base/media/startIcon.png +0 -0
  79. package/templates/harmony/entry/src/main/resources/base/profile/main_pages.json +5 -0
  80. package/templates/harmony/entry/src/main/resources/rawfile/.gitkeep +1 -0
  81. package/templates/harmony/hvigor/hvigor-config.json5 +10 -0
  82. package/templates/harmony/hvigorfile.ts +7 -0
  83. package/templates/harmony/oh-package.json5 +13 -0
@@ -0,0 +1,23 @@
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.runSyncTemplateCommand = runSyncTemplateCommand;
7
+ const path_1 = __importDefault(require("path"));
8
+ const template_1 = require("../core/template");
9
+ async function runSyncTemplateCommand(options) {
10
+ const projectRoot = path_1.default.resolve(options.projectRoot ?? process.cwd());
11
+ const result = await (0, template_1.syncProjectTemplate)(projectRoot, Boolean(options.force));
12
+ const lines = [
13
+ `Template sync completed for ${projectRoot}`,
14
+ `- written: ${result.writtenFiles.length}`,
15
+ `- unchanged: ${result.unchangedFiles.length}`,
16
+ `- skipped: ${result.skippedFiles.length}`,
17
+ `- manifest: ${result.manifestPath}`,
18
+ ];
19
+ if (result.warnings.length > 0) {
20
+ lines.push('', 'Warnings:', ...result.warnings.map((warning) => `- ${warning}`));
21
+ }
22
+ process.stdout.write(lines.join('\n') + '\n');
23
+ }
@@ -0,0 +1,25 @@
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>;
11
+ interface BundleProjectOptions {
12
+ env?: NodeJS.ProcessEnv;
13
+ runner?: CommandRunner;
14
+ skipTemplateSync?: boolean;
15
+ }
16
+ interface BuildHapProjectOptions {
17
+ mode: 'debug' | 'release';
18
+ env?: NodeJS.ProcessEnv;
19
+ runner?: CommandRunner;
20
+ }
21
+ export declare function bundleProject(projectRoot: string, options?: BundleProjectOptions): Promise<BuildReport>;
22
+ export declare function buildHapProject(projectRoot: string, options: BuildHapProjectOptions): Promise<BuildReport>;
23
+ export declare function renderBuildReport(report: BuildReport): string;
24
+ export declare function getDesiredHarmonyScripts(projectRoot: string): Promise<Record<string, string>>;
25
+ export {};
@@ -0,0 +1,434 @@
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.bundleProject = bundleProject;
7
+ exports.buildHapProject = buildHapProject;
8
+ exports.renderBuildReport = renderBuildReport;
9
+ exports.getDesiredHarmonyScripts = getDesiredHarmonyScripts;
10
+ const node_child_process_1 = require("node:child_process");
11
+ const node_util_1 = require("node:util");
12
+ const fs_extra_1 = __importDefault(require("fs-extra"));
13
+ const path_1 = __importDefault(require("path"));
14
+ const constants_1 = require("./constants");
15
+ const env_1 = require("./env");
16
+ const project_1 = require("./project");
17
+ const template_1 = require("./template");
18
+ const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
19
+ async function bundleProject(projectRoot, options = {}) {
20
+ const runtimeEnv = options.env ?? process.env;
21
+ const runCommand = options.runner ?? defaultCommandRunner;
22
+ const loadedProject = await (0, project_1.loadProject)(projectRoot);
23
+ const bundleOutputPath = path_1.default.join(loadedProject.projectRoot, 'harmony', 'entry', 'src', 'main', 'resources', 'rawfile', 'bundle.harmony.js');
24
+ const assetsDestPath = path_1.default.join(loadedProject.projectRoot, 'harmony', 'entry', 'src', 'main', 'resources', 'rawfile', 'assets');
25
+ const entryFileName = (0, template_1.resolveHarmonyBundleEntryFile)(loadedProject.packageJson);
26
+ const entryFilePath = path_1.default.join(loadedProject.projectRoot, entryFileName);
27
+ const metroConfigPath = path_1.default.join(loadedProject.projectRoot, 'metro.harmony.config.js');
28
+ const reactNativeCliPath = path_1.default.join(loadedProject.projectRoot, 'node_modules', 'react-native', 'cli.js');
29
+ const warnings = [];
30
+ const blockingIssues = [];
31
+ if (!options.skipTemplateSync) {
32
+ const syncResult = await (0, template_1.syncProjectTemplate)(loadedProject.projectRoot, false);
33
+ warnings.push(...syncResult.warnings);
34
+ }
35
+ if (!(await fs_extra_1.default.pathExists(reactNativeCliPath))) {
36
+ blockingIssues.push({
37
+ code: 'build.bundle.failed',
38
+ message: `React Native CLI was not found at ${reactNativeCliPath}. Run your package manager install first.`,
39
+ });
40
+ }
41
+ if (!(await fs_extra_1.default.pathExists(entryFilePath))) {
42
+ blockingIssues.push({
43
+ code: 'build.bundle.failed',
44
+ message: `Expected Harmony entry file ${entryFileName} does not exist yet. Run expo-harmony init first.`,
45
+ });
46
+ }
47
+ if (!(await fs_extra_1.default.pathExists(metroConfigPath))) {
48
+ blockingIssues.push({
49
+ code: 'build.bundle.failed',
50
+ message: 'metro.harmony.config.js is missing. Run expo-harmony init first.',
51
+ });
52
+ }
53
+ const initialReport = createBuildReport({
54
+ projectRoot: loadedProject.projectRoot,
55
+ command: 'bundle',
56
+ mode: null,
57
+ status: blockingIssues.length === 0 ? 'succeeded' : 'failed',
58
+ entryFile: entryFilePath,
59
+ bundleOutputPath,
60
+ assetsDestPath,
61
+ artifactPaths: [],
62
+ blockingIssues,
63
+ warnings,
64
+ steps: [],
65
+ });
66
+ if (blockingIssues.length > 0) {
67
+ initialReport.status = 'failed';
68
+ return initialReport;
69
+ }
70
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(bundleOutputPath));
71
+ await fs_extra_1.default.ensureDir(assetsDestPath);
72
+ const bundleEnvironment = { ...runtimeEnv };
73
+ if ((0, template_1.usesExpoRouter)(loadedProject.packageJson)) {
74
+ bundleEnvironment.EXPO_ROUTER_APP_ROOT = bundleEnvironment.EXPO_ROUTER_APP_ROOT ?? 'app';
75
+ }
76
+ const bundleArgs = [
77
+ reactNativeCliPath,
78
+ 'bundle-harmony',
79
+ '--reset-cache',
80
+ '--dev',
81
+ 'false',
82
+ '--entry-file',
83
+ entryFilePath,
84
+ '--bundle-output',
85
+ bundleOutputPath,
86
+ '--assets-dest',
87
+ assetsDestPath,
88
+ '--config',
89
+ metroConfigPath,
90
+ ];
91
+ const bundleCommand = buildInvocation(process.execPath, bundleArgs);
92
+ const bundleResult = await runCommand(bundleCommand.file, bundleCommand.args, {
93
+ cwd: loadedProject.projectRoot,
94
+ env: bundleEnvironment,
95
+ });
96
+ const steps = [
97
+ createStepReport('bundle-harmony', bundleCommand.file, bundleCommand.args, loadedProject.projectRoot, bundleResult.exitCode),
98
+ ];
99
+ if (bundleResult.exitCode !== 0 || !(await fs_extra_1.default.pathExists(bundleOutputPath))) {
100
+ return createBuildReport({
101
+ projectRoot: loadedProject.projectRoot,
102
+ command: 'bundle',
103
+ mode: null,
104
+ status: 'failed',
105
+ entryFile: entryFilePath,
106
+ bundleOutputPath,
107
+ assetsDestPath,
108
+ artifactPaths: [],
109
+ blockingIssues: [
110
+ {
111
+ code: 'build.bundle.failed',
112
+ message: bundleResult.stderr.trim() ||
113
+ bundleResult.stdout.trim() ||
114
+ 'react-native bundle-harmony failed before bundle.harmony.js was produced.',
115
+ },
116
+ ],
117
+ warnings,
118
+ steps,
119
+ });
120
+ }
121
+ return createBuildReport({
122
+ projectRoot: loadedProject.projectRoot,
123
+ command: 'bundle',
124
+ mode: null,
125
+ status: 'succeeded',
126
+ entryFile: entryFilePath,
127
+ bundleOutputPath,
128
+ assetsDestPath,
129
+ artifactPaths: [bundleOutputPath],
130
+ blockingIssues: [],
131
+ warnings,
132
+ steps,
133
+ });
134
+ }
135
+ async function buildHapProject(projectRoot, options) {
136
+ const runtimeEnv = options.env ?? process.env;
137
+ const runCommand = options.runner ?? defaultCommandRunner;
138
+ const loadedProject = await (0, project_1.loadProject)(projectRoot);
139
+ const envReport = await (0, env_1.buildEnvReport)(loadedProject.projectRoot, {
140
+ env: runtimeEnv,
141
+ });
142
+ const warnings = [
143
+ ...envReport.warnings.filter((warning) => !warning.startsWith('Harmony sidecar files are not present yet.')),
144
+ ...envReport.advisories.map((issue) => `${issue.code}: ${issue.message}`),
145
+ ];
146
+ const blockingIssues = [];
147
+ if (!envReport.hvigorPath) {
148
+ blockingIssues.push({
149
+ code: 'build.hap.failed',
150
+ message: 'Hvigor is not available. Run expo-harmony env to inspect the local DevEco setup.',
151
+ });
152
+ }
153
+ if (!envReport.ohpmPath) {
154
+ blockingIssues.push({
155
+ code: 'build.hap.failed',
156
+ message: 'ohpm is not available. CLI HAP builds require the DevEco package manager.',
157
+ });
158
+ }
159
+ if (options.mode === 'release' && !envReport.signingConfigured) {
160
+ blockingIssues.push({
161
+ code: 'env.signing.missing',
162
+ message: 'Release HAP builds require signingConfigs in harmony/build-profile.json5.',
163
+ });
164
+ }
165
+ if (blockingIssues.length > 0) {
166
+ return createBuildReport({
167
+ projectRoot: loadedProject.projectRoot,
168
+ command: 'build-hap',
169
+ mode: options.mode,
170
+ status: 'failed',
171
+ entryFile: path_1.default.join(loadedProject.projectRoot, (0, template_1.resolveHarmonyBundleEntryFile)(loadedProject.packageJson)),
172
+ bundleOutputPath: getBundleOutputPath(loadedProject.projectRoot),
173
+ assetsDestPath: getAssetsOutputPath(loadedProject.projectRoot),
174
+ artifactPaths: [],
175
+ blockingIssues,
176
+ warnings,
177
+ steps: [],
178
+ });
179
+ }
180
+ const bundleReport = await bundleProject(loadedProject.projectRoot, {
181
+ env: runtimeEnv,
182
+ runner: runCommand,
183
+ });
184
+ const harmonyProjectRoot = envReport.harmonyProjectRoot ?? path_1.default.join(loadedProject.projectRoot, 'harmony');
185
+ if (bundleReport.status === 'failed') {
186
+ return createBuildReport({
187
+ projectRoot: loadedProject.projectRoot,
188
+ command: 'build-hap',
189
+ mode: options.mode,
190
+ status: 'failed',
191
+ harmonyProjectRoot,
192
+ entryFile: bundleReport.entryFile,
193
+ bundleOutputPath: bundleReport.bundleOutputPath,
194
+ assetsDestPath: bundleReport.assetsDestPath,
195
+ artifactPaths: [],
196
+ blockingIssues: bundleReport.blockingIssues,
197
+ warnings: [...warnings, ...bundleReport.warnings],
198
+ steps: bundleReport.steps,
199
+ });
200
+ }
201
+ if (!(await fs_extra_1.default.pathExists(harmonyProjectRoot))) {
202
+ return createBuildReport({
203
+ projectRoot: loadedProject.projectRoot,
204
+ command: 'build-hap',
205
+ mode: options.mode,
206
+ status: 'failed',
207
+ harmonyProjectRoot,
208
+ entryFile: bundleReport.entryFile,
209
+ bundleOutputPath: bundleReport.bundleOutputPath,
210
+ assetsDestPath: bundleReport.assetsDestPath,
211
+ artifactPaths: [],
212
+ blockingIssues: [
213
+ {
214
+ code: 'build.hap.failed',
215
+ message: 'Harmony sidecar files are still missing after bundle sync. Run expo-harmony init --force to inspect template drift.',
216
+ },
217
+ ],
218
+ warnings: [...warnings, ...bundleReport.warnings],
219
+ steps: bundleReport.steps,
220
+ });
221
+ }
222
+ const steps = [...bundleReport.steps];
223
+ const buildEnvironment = createHarmonyBuildEnvironment(runtimeEnv, envReport);
224
+ const ohpmCommand = buildInvocation(envReport.ohpmPath, ['install', '--all']);
225
+ const ohpmResult = await runCommand(ohpmCommand.file, ohpmCommand.args, {
226
+ cwd: harmonyProjectRoot,
227
+ env: buildEnvironment,
228
+ });
229
+ steps.push(createStepReport('ohpm install', ohpmCommand.file, ohpmCommand.args, harmonyProjectRoot, ohpmResult.exitCode));
230
+ if (ohpmResult.exitCode !== 0) {
231
+ return createBuildReport({
232
+ projectRoot: loadedProject.projectRoot,
233
+ command: 'build-hap',
234
+ mode: options.mode,
235
+ status: 'failed',
236
+ harmonyProjectRoot,
237
+ entryFile: bundleReport.entryFile,
238
+ bundleOutputPath: bundleReport.bundleOutputPath,
239
+ assetsDestPath: bundleReport.assetsDestPath,
240
+ artifactPaths: [],
241
+ blockingIssues: [
242
+ {
243
+ code: 'build.hap.failed',
244
+ message: ohpmResult.stderr.trim() ||
245
+ ohpmResult.stdout.trim() ||
246
+ 'ohpm install failed before the HAP build could start.',
247
+ },
248
+ ],
249
+ warnings: [...warnings, ...bundleReport.warnings],
250
+ steps,
251
+ });
252
+ }
253
+ const hvigorCommand = buildInvocation(envReport.hvigorPath, [
254
+ 'assembleHap',
255
+ '--no-daemon',
256
+ '-p',
257
+ 'product=default',
258
+ '-p',
259
+ `buildMode=${options.mode}`,
260
+ ]);
261
+ const hvigorResult = await runCommand(hvigorCommand.file, hvigorCommand.args, {
262
+ cwd: harmonyProjectRoot,
263
+ env: buildEnvironment,
264
+ });
265
+ steps.push(createStepReport('hvigor assembleHap', hvigorCommand.file, hvigorCommand.args, harmonyProjectRoot, hvigorResult.exitCode));
266
+ const artifactPaths = await findHarmonyArtifacts(harmonyProjectRoot);
267
+ if (hvigorResult.exitCode !== 0 || artifactPaths.length === 0) {
268
+ return createBuildReport({
269
+ projectRoot: loadedProject.projectRoot,
270
+ command: 'build-hap',
271
+ mode: options.mode,
272
+ status: 'failed',
273
+ harmonyProjectRoot,
274
+ entryFile: bundleReport.entryFile,
275
+ bundleOutputPath: bundleReport.bundleOutputPath,
276
+ assetsDestPath: bundleReport.assetsDestPath,
277
+ artifactPaths,
278
+ blockingIssues: [
279
+ {
280
+ code: 'build.hap.failed',
281
+ message: hvigorResult.stderr.trim() ||
282
+ hvigorResult.stdout.trim() ||
283
+ 'Hvigor finished without producing any HAP artifacts.',
284
+ },
285
+ ],
286
+ warnings: [...warnings, ...bundleReport.warnings],
287
+ steps,
288
+ });
289
+ }
290
+ return createBuildReport({
291
+ projectRoot: loadedProject.projectRoot,
292
+ command: 'build-hap',
293
+ mode: options.mode,
294
+ status: 'succeeded',
295
+ harmonyProjectRoot,
296
+ entryFile: bundleReport.entryFile,
297
+ bundleOutputPath: bundleReport.bundleOutputPath,
298
+ assetsDestPath: bundleReport.assetsDestPath,
299
+ artifactPaths,
300
+ blockingIssues: [],
301
+ warnings: [...warnings, ...bundleReport.warnings],
302
+ steps,
303
+ });
304
+ }
305
+ function renderBuildReport(report) {
306
+ const lines = [
307
+ 'Expo Harmony build report',
308
+ `Project: ${report.projectRoot}`,
309
+ `Command: ${report.command}`,
310
+ `Mode: ${report.mode ?? 'n/a'}`,
311
+ `Status: ${report.status}`,
312
+ `Harmony project: ${report.harmonyProjectRoot ?? 'not found'}`,
313
+ `Entry file: ${report.entryFile ?? 'n/a'}`,
314
+ `Bundle output: ${report.bundleOutputPath ?? 'n/a'}`,
315
+ `Artifacts: ${report.artifactPaths.join(', ') || 'none'}`,
316
+ '',
317
+ 'Steps:',
318
+ ...report.steps.map((step) => `- [${step.exitCode ?? 'n/a'}] ${step.label}: ${step.command} (cwd ${step.cwd})`),
319
+ ];
320
+ if (report.blockingIssues.length > 0) {
321
+ lines.push('', 'Blocking issues:', ...report.blockingIssues.map((issue) => `- ${issue.code}: ${issue.message}${issue.subject ? ` (${issue.subject})` : ''}`));
322
+ }
323
+ if (report.warnings.length > 0) {
324
+ lines.push('', 'Warnings:', ...report.warnings.map((warning) => `- ${warning}`));
325
+ }
326
+ return lines.join('\n');
327
+ }
328
+ function getBundleOutputPath(projectRoot) {
329
+ return path_1.default.join(projectRoot, 'harmony', 'entry', 'src', 'main', 'resources', 'rawfile', 'bundle.harmony.js');
330
+ }
331
+ function getAssetsOutputPath(projectRoot) {
332
+ return path_1.default.join(projectRoot, 'harmony', 'entry', 'src', 'main', 'resources', 'rawfile', 'assets');
333
+ }
334
+ function createBuildReport(input) {
335
+ return {
336
+ generatedAt: new Date().toISOString(),
337
+ projectRoot: input.projectRoot,
338
+ toolkitVersion: constants_1.TOOLKIT_VERSION,
339
+ command: input.command,
340
+ mode: input.mode,
341
+ status: input.status,
342
+ harmonyProjectRoot: input.harmonyProjectRoot ?? path_1.default.join(input.projectRoot, 'harmony'),
343
+ entryFile: input.entryFile,
344
+ bundleOutputPath: input.bundleOutputPath,
345
+ assetsDestPath: input.assetsDestPath,
346
+ artifactPaths: input.artifactPaths,
347
+ blockingIssues: input.blockingIssues,
348
+ warnings: input.warnings,
349
+ steps: input.steps,
350
+ };
351
+ }
352
+ function createStepReport(label, file, args, cwd, exitCode) {
353
+ return {
354
+ label,
355
+ command: [file, ...args].join(' '),
356
+ cwd,
357
+ exitCode,
358
+ };
359
+ }
360
+ function buildInvocation(file, args) {
361
+ if (file.endsWith('.js')) {
362
+ return {
363
+ file: process.execPath,
364
+ args: [file, ...args],
365
+ };
366
+ }
367
+ return {
368
+ file,
369
+ args,
370
+ };
371
+ }
372
+ function createHarmonyBuildEnvironment(runtimeEnv, envReport) {
373
+ const buildEnvironment = {
374
+ ...runtimeEnv,
375
+ };
376
+ if (envReport.sdkRoot) {
377
+ buildEnvironment.DEVECO_SDK_HOME = envReport.sdkRoot;
378
+ buildEnvironment.OHOS_BASE_SDK_HOME = envReport.sdkRoot;
379
+ }
380
+ if (envReport.devecoStudioPath) {
381
+ buildEnvironment.NODE_HOME =
382
+ buildEnvironment.NODE_HOME ??
383
+ path_1.default.join(envReport.devecoStudioPath, 'Contents', 'tools', 'node');
384
+ }
385
+ return buildEnvironment;
386
+ }
387
+ async function findHarmonyArtifacts(harmonyProjectRoot) {
388
+ const discoveredPaths = [];
389
+ await walkDirectory(harmonyProjectRoot, async (entryPath) => {
390
+ if (entryPath.endsWith('.hap') || entryPath.endsWith('.app') || entryPath.endsWith('.hsp')) {
391
+ discoveredPaths.push(entryPath);
392
+ }
393
+ });
394
+ return discoveredPaths.sort((left, right) => left.localeCompare(right));
395
+ }
396
+ async function walkDirectory(currentPath, visitor) {
397
+ if (!(await fs_extra_1.default.pathExists(currentPath))) {
398
+ return;
399
+ }
400
+ const entries = await fs_extra_1.default.readdir(currentPath, { withFileTypes: true });
401
+ for (const entry of entries) {
402
+ const nextPath = path_1.default.join(currentPath, entry.name);
403
+ if (entry.isDirectory()) {
404
+ await walkDirectory(nextPath, visitor);
405
+ continue;
406
+ }
407
+ await visitor(nextPath);
408
+ }
409
+ }
410
+ async function defaultCommandRunner(file, args, options) {
411
+ try {
412
+ const result = await execFileAsync(file, args, {
413
+ cwd: options.cwd,
414
+ env: options.env,
415
+ maxBuffer: 20 * 1024 * 1024,
416
+ });
417
+ return {
418
+ exitCode: 0,
419
+ stdout: result.stdout,
420
+ stderr: result.stderr,
421
+ };
422
+ }
423
+ catch (error) {
424
+ const failed = error;
425
+ return {
426
+ exitCode: typeof failed.code === 'number' ? failed.code : 1,
427
+ stdout: failed.stdout ?? '',
428
+ stderr: failed.stderr ?? failed.message ?? '',
429
+ };
430
+ }
431
+ }
432
+ function getDesiredHarmonyScripts(projectRoot) {
433
+ return (0, project_1.loadProject)(projectRoot).then((loadedProject) => (0, template_1.buildDesiredPackageScripts)(loadedProject.packageJson));
434
+ }
@@ -0,0 +1,21 @@
1
+ export declare const TOOLKIT_PACKAGE_NAME = "expo-harmony-toolkit";
2
+ export declare const CLI_NAME = "expo-harmony";
3
+ export declare const TOOLKIT_VERSION = "1.5.0";
4
+ export declare const TEMPLATE_VERSION = "rnoh-0.82.18";
5
+ export declare const RNOH_VERSION = "0.82.18";
6
+ export declare const RNOH_CLI_VERSION = "0.82.18";
7
+ export declare const SUPPORTED_EXPO_SDKS: number[];
8
+ export declare const GENERATED_DIR = ".expo-harmony";
9
+ export declare const GENERATED_SHIMS_DIR = ".expo-harmony/shims";
10
+ export declare const MANIFEST_FILENAME = "manifest.json";
11
+ export declare const DOCTOR_REPORT_FILENAME = "doctor-report.json";
12
+ export declare const ENV_REPORT_FILENAME = "env-report.json";
13
+ export declare const BUILD_REPORT_FILENAME = "build-report.json";
14
+ export declare const TOOLKIT_CONFIG_FILENAME = "toolkit-config.json";
15
+ export declare const PREBUILD_METADATA_FILENAME = "prebuild-metadata.json";
16
+ export declare const DEFAULT_HVIGOR_PLUGIN_FILENAME = "rnoh-hvigor-plugin-0.82.18.tgz";
17
+ export declare const STRICT_DOCTOR_EXIT_CODE = 2;
18
+ export declare const STRICT_ENV_EXIT_CODE = 3;
19
+ export declare const HARMONY_ROUTER_ENTRY_FILENAME = "index.harmony.js";
20
+ export declare const HARMONY_RUNTIME_PRELUDE_RELATIVE_PATH = ".expo-harmony/shims/runtime-prelude.js";
21
+ export declare const DESIRED_PACKAGE_SCRIPTS: Record<string, string>;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DESIRED_PACKAGE_SCRIPTS = exports.HARMONY_RUNTIME_PRELUDE_RELATIVE_PATH = exports.HARMONY_ROUTER_ENTRY_FILENAME = exports.STRICT_ENV_EXIT_CODE = exports.STRICT_DOCTOR_EXIT_CODE = exports.DEFAULT_HVIGOR_PLUGIN_FILENAME = exports.PREBUILD_METADATA_FILENAME = exports.TOOLKIT_CONFIG_FILENAME = exports.BUILD_REPORT_FILENAME = exports.ENV_REPORT_FILENAME = exports.DOCTOR_REPORT_FILENAME = exports.MANIFEST_FILENAME = exports.GENERATED_SHIMS_DIR = exports.GENERATED_DIR = exports.SUPPORTED_EXPO_SDKS = exports.RNOH_CLI_VERSION = exports.RNOH_VERSION = exports.TEMPLATE_VERSION = exports.TOOLKIT_VERSION = exports.CLI_NAME = exports.TOOLKIT_PACKAGE_NAME = void 0;
4
+ exports.TOOLKIT_PACKAGE_NAME = 'expo-harmony-toolkit';
5
+ exports.CLI_NAME = 'expo-harmony';
6
+ exports.TOOLKIT_VERSION = '1.5.0';
7
+ exports.TEMPLATE_VERSION = 'rnoh-0.82.18';
8
+ exports.RNOH_VERSION = '0.82.18';
9
+ exports.RNOH_CLI_VERSION = '0.82.18';
10
+ exports.SUPPORTED_EXPO_SDKS = [53, 55];
11
+ exports.GENERATED_DIR = '.expo-harmony';
12
+ exports.GENERATED_SHIMS_DIR = `${exports.GENERATED_DIR}/shims`;
13
+ exports.MANIFEST_FILENAME = 'manifest.json';
14
+ exports.DOCTOR_REPORT_FILENAME = 'doctor-report.json';
15
+ exports.ENV_REPORT_FILENAME = 'env-report.json';
16
+ exports.BUILD_REPORT_FILENAME = 'build-report.json';
17
+ exports.TOOLKIT_CONFIG_FILENAME = 'toolkit-config.json';
18
+ exports.PREBUILD_METADATA_FILENAME = 'prebuild-metadata.json';
19
+ exports.DEFAULT_HVIGOR_PLUGIN_FILENAME = `rnoh-hvigor-plugin-${exports.RNOH_CLI_VERSION}.tgz`;
20
+ exports.STRICT_DOCTOR_EXIT_CODE = 2;
21
+ exports.STRICT_ENV_EXIT_CODE = 3;
22
+ exports.HARMONY_ROUTER_ENTRY_FILENAME = 'index.harmony.js';
23
+ exports.HARMONY_RUNTIME_PRELUDE_RELATIVE_PATH = `${exports.GENERATED_SHIMS_DIR}/runtime-prelude.js`;
24
+ exports.DESIRED_PACKAGE_SCRIPTS = {
25
+ 'harmony:doctor': 'expo-harmony doctor',
26
+ 'harmony:init': 'expo-harmony init',
27
+ 'harmony:sync-template': 'expo-harmony sync-template',
28
+ 'harmony:env': 'expo-harmony env',
29
+ 'harmony:bundle': 'expo-harmony bundle',
30
+ 'harmony:build:debug': 'expo-harmony build-hap --mode debug',
31
+ 'harmony:build:release': 'expo-harmony build-hap --mode release',
32
+ };
@@ -0,0 +1,8 @@
1
+ import { EnvReport } from '../types';
2
+ interface BuildEnvReportOptions {
3
+ env?: NodeJS.ProcessEnv;
4
+ }
5
+ export declare function buildEnvReport(projectRoot: string, options?: BuildEnvReportOptions): Promise<EnvReport>;
6
+ export declare function renderEnvReport(report: EnvReport): string;
7
+ export declare function getStrictEnvExitCode(): number;
8
+ export {};