@expo-harmony/expo-modules-autolinking 55.0.25-harmony.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/bin/expo-harmony-autolinking.ts +14 -0
- package/build/bin/expo-harmony-autolinking.d.ts +2 -0
- package/build/bin/expo-harmony-autolinking.js +11 -0
- package/build/index.d.ts +8 -0
- package/build/index.js +15 -0
- package/build/src/autolinking/link.d.ts +3 -0
- package/build/src/autolinking/link.js +150 -0
- package/build/src/autolinking/resolve.d.ts +4 -0
- package/build/src/autolinking/resolve.js +25 -0
- package/build/src/autolinking/search.d.ts +3 -0
- package/build/src/autolinking/search.js +357 -0
- package/build/src/autolinking/verify.d.ts +4 -0
- package/build/src/autolinking/verify.js +366 -0
- package/build/src/commands/autolinkingOptions.d.ts +12 -0
- package/build/src/commands/autolinkingOptions.js +35 -0
- package/build/src/commands/cli.d.ts +2 -0
- package/build/src/commands/cli.js +50 -0
- package/build/src/commands/link.d.ts +2 -0
- package/build/src/commands/link.js +27 -0
- package/build/src/commands/output.d.ts +3 -0
- package/build/src/commands/output.js +33 -0
- package/build/src/commands/resolve.d.ts +2 -0
- package/build/src/commands/resolve.js +13 -0
- package/build/src/commands/search.d.ts +2 -0
- package/build/src/commands/search.js +13 -0
- package/build/src/commands/verify.d.ts +2 -0
- package/build/src/commands/verify.js +17 -0
- package/build/src/config/constants.d.ts +17 -0
- package/build/src/config/constants.js +40 -0
- package/build/src/config/options.d.ts +13 -0
- package/build/src/config/options.js +202 -0
- package/build/src/errors.d.ts +18 -0
- package/build/src/errors.js +35 -0
- package/build/src/harmony/manifest/generate.d.ts +4 -0
- package/build/src/harmony/manifest/generate.js +55 -0
- package/build/src/harmony/manifest/index.d.ts +7 -0
- package/build/src/harmony/manifest/index.js +64 -0
- package/build/src/harmony/materialize.d.ts +12 -0
- package/build/src/harmony/materialize.js +278 -0
- package/build/src/harmony/ohpm/dependencies.d.ts +7 -0
- package/build/src/harmony/ohpm/dependencies.js +52 -0
- package/build/src/harmony/persistence/canonicalize.d.ts +15 -0
- package/build/src/harmony/persistence/canonicalize.js +108 -0
- package/build/src/harmony/providers/host.d.ts +3 -0
- package/build/src/harmony/providers/host.js +88 -0
- package/build/src/harmony/rnoh/cli.d.ts +2 -0
- package/build/src/harmony/rnoh/cli.js +55 -0
- package/build/src/harmony/rnoh/link.d.ts +2 -0
- package/build/src/harmony/rnoh/link.js +419 -0
- package/build/src/harmony/rnoh/packageMetadata.d.ts +12 -0
- package/build/src/harmony/rnoh/packageMetadata.js +125 -0
- package/build/src/harmony/transaction/previousState.d.ts +15 -0
- package/build/src/harmony/transaction/previousState.js +96 -0
- package/build/src/harmony/transaction/publish.d.ts +6 -0
- package/build/src/harmony/transaction/publish.js +272 -0
- package/build/src/harmony/transaction/stageProject.d.ts +18 -0
- package/build/src/harmony/transaction/stageProject.js +313 -0
- package/build/src/metadata/descriptor.d.ts +19 -0
- package/build/src/metadata/descriptor.js +306 -0
- package/build/src/metadata/host.d.ts +5 -0
- package/build/src/metadata/host.js +37 -0
- package/build/src/metadata/schema.d.ts +10 -0
- package/build/src/metadata/schema.js +171 -0
- package/build/src/types.d.ts +194 -0
- package/build/src/types.js +2 -0
- package/build/src/utilities/values.d.ts +17 -0
- package/build/src/utilities/values.js +205 -0
- package/harmony-module.schema.json +28 -0
- package/index.ts +41 -0
- package/package.json +66 -0
- package/src/autolinking/link.ts +170 -0
- package/src/autolinking/resolve.ts +33 -0
- package/src/autolinking/search.ts +369 -0
- package/src/autolinking/verify.ts +415 -0
- package/src/commands/autolinkingOptions.ts +38 -0
- package/src/commands/cli.ts +56 -0
- package/src/commands/link.ts +28 -0
- package/src/commands/output.ts +36 -0
- package/src/commands/resolve.ts +14 -0
- package/src/commands/search.ts +14 -0
- package/src/commands/verify.ts +17 -0
- package/src/config/constants.ts +45 -0
- package/src/config/options.ts +195 -0
- package/src/errors.ts +48 -0
- package/src/harmony/manifest/generate.ts +65 -0
- package/src/harmony/manifest/index.ts +81 -0
- package/src/harmony/materialize.ts +382 -0
- package/src/harmony/ohpm/dependencies.ts +59 -0
- package/src/harmony/persistence/canonicalize.ts +156 -0
- package/src/harmony/providers/host.ts +147 -0
- package/src/harmony/rnoh/cli.ts +59 -0
- package/src/harmony/rnoh/link.ts +481 -0
- package/src/harmony/rnoh/packageMetadata.ts +105 -0
- package/src/harmony/transaction/previousState.ts +71 -0
- package/src/harmony/transaction/publish.ts +287 -0
- package/src/harmony/transaction/stageProject.ts +345 -0
- package/src/metadata/descriptor.ts +324 -0
- package/src/metadata/host.ts +41 -0
- package/src/metadata/schema.ts +184 -0
- package/src/types.ts +220 -0
- package/src/utilities/values.ts +190 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,366 @@
|
|
|
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.assertVerificationSucceeded = assertVerificationSucceeded;
|
|
7
|
+
exports.verifyModulesAsync = verifyModulesAsync;
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const errors_1 = require("../errors");
|
|
11
|
+
const host_1 = require("../metadata/host");
|
|
12
|
+
const descriptor_1 = require("../metadata/descriptor");
|
|
13
|
+
const search_1 = require("./search");
|
|
14
|
+
const resolve_1 = require("./resolve");
|
|
15
|
+
const packageMetadata_1 = require("../harmony/rnoh/packageMetadata");
|
|
16
|
+
const host_2 = require("../harmony/providers/host");
|
|
17
|
+
const values_1 = require("../utilities/values");
|
|
18
|
+
function diagnosticFromError(error, fallback) {
|
|
19
|
+
const normalized = error instanceof errors_1.HarmonyAutolinkingError
|
|
20
|
+
? error
|
|
21
|
+
: new errors_1.HarmonyAutolinkingError('INVALID_METADATA', error.message || String(error), { cause: error, packageName: fallback, stage: 'verify' });
|
|
22
|
+
return {
|
|
23
|
+
severity: 'error',
|
|
24
|
+
code: normalized.code,
|
|
25
|
+
message: normalized.message,
|
|
26
|
+
...(normalized.packageName || fallback ? { packageName: normalized.packageName || fallback } : {}),
|
|
27
|
+
stage: normalized.stage,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function compareDiagnostics(left, right) {
|
|
31
|
+
const order = { error: 0, warning: 1 };
|
|
32
|
+
return (order[left.severity] - order[right.severity])
|
|
33
|
+
|| (0, values_1.compareText)(left.code, right.code)
|
|
34
|
+
|| (0, values_1.compareText)(left.packageName || '', right.packageName || '')
|
|
35
|
+
|| (0, values_1.compareText)(left.message, right.message)
|
|
36
|
+
|| (0, values_1.compareText)(JSON.stringify(left.sources || []), JSON.stringify(right.sources || []));
|
|
37
|
+
}
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
+
function diagnosticSource(descriptor, extra = {}) {
|
|
40
|
+
return {
|
|
41
|
+
packageName: descriptor.packageName,
|
|
42
|
+
packageVersion: descriptor.packageVersion,
|
|
43
|
+
packageRoot: descriptor.packageRoot,
|
|
44
|
+
...extra,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function conflictDiagnostic(code, label, value, entries, packageName, severity = 'error') {
|
|
48
|
+
return {
|
|
49
|
+
severity,
|
|
50
|
+
code: `ERR_EXPO_HARMONY_${code}`,
|
|
51
|
+
message: `${label} "${value}" is declared more than once.`,
|
|
52
|
+
packageName,
|
|
53
|
+
stage: 'verify',
|
|
54
|
+
sources: entries.map(entry => entry.source).sort((left, right) => {
|
|
55
|
+
return (0, values_1.compareText)(left.packageName, right.packageName)
|
|
56
|
+
|| (0, values_1.compareText)(left.packageRoot, right.packageRoot)
|
|
57
|
+
|| (0, values_1.compareText)(left.field || '', right.field || '');
|
|
58
|
+
}),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function collectDescriptorConflicts(descriptors) {
|
|
62
|
+
const diagnostics = [];
|
|
63
|
+
const registrations = new Map();
|
|
64
|
+
const oh = new Map();
|
|
65
|
+
const rnohCmakeTargets = new Map();
|
|
66
|
+
const rnohEtsSymbols = new Map();
|
|
67
|
+
const rnohCppSymbols = new Map();
|
|
68
|
+
function push(map, key, source, value = key) {
|
|
69
|
+
const entries = map.get(key) || [];
|
|
70
|
+
entries.push({ value, source });
|
|
71
|
+
map.set(key, entries);
|
|
72
|
+
}
|
|
73
|
+
for (const descriptor of descriptors) {
|
|
74
|
+
if (descriptor.arkTs) {
|
|
75
|
+
const arkTs = descriptor.arkTs;
|
|
76
|
+
push(oh, arkTs.ohPackageName, diagnosticSource(descriptor, {
|
|
77
|
+
field: `HAR:${arkTs.harPath}`,
|
|
78
|
+
}), `${descriptor.packageRoot}\0${arkTs.harPath}`);
|
|
79
|
+
for (const moduleClass of descriptor.harmony.modules) {
|
|
80
|
+
const registrationId = (0, host_2.moduleRegistrationId)(arkTs.ohPackageName, moduleClass);
|
|
81
|
+
push(registrations, registrationId, diagnosticSource(descriptor, {
|
|
82
|
+
field: `module:${moduleClass}`,
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (descriptor.rnoh.harPaths.length > 0) {
|
|
87
|
+
const rnohMetadata = (0, packageMetadata_1.resolveRnohMetadata)(descriptor);
|
|
88
|
+
const packageSource = `${descriptor.packageRoot}\0${rnohMetadata.harMappings
|
|
89
|
+
.map(mapping => mapping.harPath)
|
|
90
|
+
.join('\0')}`;
|
|
91
|
+
for (const mapping of rnohMetadata.harMappings) {
|
|
92
|
+
push(oh, mapping.ohPackageName, diagnosticSource(descriptor, {
|
|
93
|
+
field: `HAR:${mapping.harPath}`,
|
|
94
|
+
}), `${descriptor.packageRoot}\0${mapping.harPath}`);
|
|
95
|
+
}
|
|
96
|
+
push(rnohEtsSymbols, rnohMetadata.etsPackageClassName, diagnosticSource(descriptor, {
|
|
97
|
+
field: 'etsPackageClassName',
|
|
98
|
+
}), packageSource);
|
|
99
|
+
push(rnohCppSymbols, rnohMetadata.cppPackageClassName, diagnosticSource(descriptor, {
|
|
100
|
+
field: 'cppPackageClassName',
|
|
101
|
+
}), packageSource);
|
|
102
|
+
push(rnohCmakeTargets, rnohMetadata.cmakeLibraryTargetName, diagnosticSource(descriptor, {
|
|
103
|
+
field: 'cmakeLibraryTargetName',
|
|
104
|
+
}), packageSource);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const [value, entries] of registrations) {
|
|
108
|
+
if (entries.length > 1) {
|
|
109
|
+
diagnostics.push(conflictDiagnostic('DUPLICATE_MODULE', 'ArkTS module registration', value, entries));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
for (const [value, entries] of rnohCmakeTargets) {
|
|
113
|
+
if (new Set(entries.map(entry => entry.value)).size > 1) {
|
|
114
|
+
diagnostics.push(conflictDiagnostic('DUPLICATE_MODULE', 'CMake target', value, entries));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
for (const [value, entries] of rnohEtsSymbols) {
|
|
118
|
+
if (new Set(entries.map(entry => entry.value)).size > 1) {
|
|
119
|
+
diagnostics.push(conflictDiagnostic('DUPLICATE_MODULE', 'ETS Package class', value, entries));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (const [value, entries] of rnohCppSymbols) {
|
|
123
|
+
if (new Set(entries.map(entry => entry.value)).size > 1) {
|
|
124
|
+
diagnostics.push(conflictDiagnostic('DUPLICATE_MODULE', 'C++ Package class', value, entries));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
for (const [value, entries] of oh) {
|
|
128
|
+
if (new Set(entries.map(entry => entry.value)).size > 1) {
|
|
129
|
+
diagnostics.push(conflictDiagnostic('DUPLICATE_MODULE', 'OH package', value, entries));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return diagnostics;
|
|
133
|
+
}
|
|
134
|
+
function normalizeDescriptorHarPaths(descriptor) {
|
|
135
|
+
if (!Array.isArray(descriptor.rnoh.harPaths)) {
|
|
136
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', 'descriptor.rnoh.harPaths must be an array.', {
|
|
137
|
+
packageName: descriptor.packageName,
|
|
138
|
+
stage: 'verify',
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
const harPaths = descriptor.rnoh.harPaths.map((harPath, index) => {
|
|
142
|
+
if (typeof harPath !== 'string' || !harPath.trim() || harPath.includes('\0')
|
|
143
|
+
|| node_path_1.default.win32.isAbsolute(harPath)) {
|
|
144
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', `descriptor.rnoh.harPaths[${index}] must be a non-empty package-relative HAR path.`, { packageName: descriptor.packageName, stage: 'verify' });
|
|
145
|
+
}
|
|
146
|
+
const normalized = node_path_1.default.posix.normalize(harPath.replace(/\\/g, '/'));
|
|
147
|
+
if (node_path_1.default.posix.isAbsolute(normalized) || normalized === '..' || normalized.startsWith('../')
|
|
148
|
+
|| node_path_1.default.posix.extname(normalized) !== '.har') {
|
|
149
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', `descriptor.rnoh.harPaths[${index}] must be a package-relative .har file.`, { packageName: descriptor.packageName, stage: 'verify' });
|
|
150
|
+
}
|
|
151
|
+
return normalized;
|
|
152
|
+
});
|
|
153
|
+
return (0, values_1.sortedUniqueStrings)(harPaths);
|
|
154
|
+
}
|
|
155
|
+
function harRoot(harPaths) {
|
|
156
|
+
const directories = harPaths.map(harPath => node_path_1.default.posix.dirname(harPath).split('/'));
|
|
157
|
+
const common = [];
|
|
158
|
+
for (let index = 0; index < directories[0].length; index += 1) {
|
|
159
|
+
const segment = directories[0][index];
|
|
160
|
+
if (directories.every(parts => parts[index] === segment))
|
|
161
|
+
common.push(segment);
|
|
162
|
+
else
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
return common.length === 0 ? '.' : common.join('/');
|
|
166
|
+
}
|
|
167
|
+
function searchRecordFromDescriptor(descriptor, declared) {
|
|
168
|
+
if (!(0, values_1.isObject)(descriptor)) {
|
|
169
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', 'Harmony module descriptor must be an object.', {
|
|
170
|
+
stage: 'verify',
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (!(0, values_1.isObject)(descriptor.expo) || !(0, values_1.isObject)(descriptor.harmony)) {
|
|
174
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', 'descriptor.expo and descriptor.harmony must be objects.', {
|
|
175
|
+
packageName: descriptor.packageName,
|
|
176
|
+
stage: 'verify',
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
if (!(0, values_1.isObject)(descriptor.rnoh)) {
|
|
180
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', 'descriptor.rnoh must be an object.', {
|
|
181
|
+
packageName: descriptor.packageName,
|
|
182
|
+
stage: 'verify',
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
const host = host_1.HostMetadataFields.some(field => descriptor.expo[field]?.length > 0);
|
|
186
|
+
const modules = Array.isArray(descriptor.harmony.modules)
|
|
187
|
+
? [...descriptor.harmony.modules]
|
|
188
|
+
: [];
|
|
189
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
190
|
+
const rnoh = {};
|
|
191
|
+
if (descriptor.rnoh.ohPackageName !== undefined) {
|
|
192
|
+
rnoh.ohPackageName = Array.isArray(descriptor.rnoh.ohPackageName)
|
|
193
|
+
? descriptor.rnoh.ohPackageName.map(mapping => ({ ...mapping }))
|
|
194
|
+
: descriptor.rnoh.ohPackageName;
|
|
195
|
+
}
|
|
196
|
+
if (descriptor.rnoh.mainHarPath !== undefined)
|
|
197
|
+
rnoh.mainHarPath = descriptor.rnoh.mainHarPath;
|
|
198
|
+
else if (declared.length > 0)
|
|
199
|
+
rnoh.mainHarPath = harRoot(declared);
|
|
200
|
+
if (descriptor.rnoh.etsPackageImport !== undefined) {
|
|
201
|
+
rnoh.etsPackageImport = descriptor.rnoh.etsPackageImport;
|
|
202
|
+
}
|
|
203
|
+
if (descriptor.rnoh.etsPackageClassName !== undefined) {
|
|
204
|
+
rnoh.etsPackageClassName = descriptor.rnoh.etsPackageClassName;
|
|
205
|
+
}
|
|
206
|
+
if (descriptor.rnoh.cppPackageClassName !== undefined) {
|
|
207
|
+
rnoh.cppPackageClassName = descriptor.rnoh.cppPackageClassName;
|
|
208
|
+
}
|
|
209
|
+
if (descriptor.rnoh.cmakeLibraryTargetName !== undefined) {
|
|
210
|
+
rnoh.cmakeLibraryTargetName = descriptor.rnoh.cmakeLibraryTargetName;
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
packageName: descriptor.packageName,
|
|
214
|
+
packageVersion: descriptor.packageVersion,
|
|
215
|
+
packageRoot: descriptor.packageRoot,
|
|
216
|
+
source: descriptor.source,
|
|
217
|
+
supportsHarmony: modules.length > 0 || host,
|
|
218
|
+
expoModuleConfig: modules.length > 0 || host
|
|
219
|
+
? {
|
|
220
|
+
platforms: ['harmony'],
|
|
221
|
+
harmony: {
|
|
222
|
+
modules,
|
|
223
|
+
...Object.fromEntries(host_1.HostMetadataFields.map(field => [
|
|
224
|
+
field,
|
|
225
|
+
[...(descriptor.expo[field] || [])],
|
|
226
|
+
])),
|
|
227
|
+
},
|
|
228
|
+
}
|
|
229
|
+
: null,
|
|
230
|
+
rnohMetadata: Object.keys(rnoh).length > 0 ? rnoh : null,
|
|
231
|
+
revision: {
|
|
232
|
+
originPath: descriptor.packageLinkPath || descriptor.packageRoot,
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
async function validateDescriptorAsync(descriptor, buildType) {
|
|
237
|
+
if (!(0, values_1.isObject)(descriptor) || !(0, values_1.isObject)(descriptor.rnoh)) {
|
|
238
|
+
return (0, descriptor_1.createDescriptorFromSearchRecordAsync)(searchRecordFromDescriptor(descriptor, []), buildType);
|
|
239
|
+
}
|
|
240
|
+
const declared = normalizeDescriptorHarPaths(descriptor);
|
|
241
|
+
const normalized = await (0, descriptor_1.createDescriptorFromSearchRecordAsync)(searchRecordFromDescriptor(descriptor, declared), buildType);
|
|
242
|
+
if (normalized.rnoh.harPaths.length !== declared.length
|
|
243
|
+
|| normalized.rnoh.harPaths.some((harPath, index) => harPath !== declared[index])) {
|
|
244
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', 'descriptor.rnoh.harPaths must exactly list the HAR files selected by descriptor.rnoh.mainHarPath.', {
|
|
245
|
+
packageName: descriptor.packageName,
|
|
246
|
+
stage: 'verify',
|
|
247
|
+
details: { declared, discovered: normalized.rnoh.harPaths },
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
const packageRoot = await node_fs_1.default.promises.realpath(descriptor.packageRoot);
|
|
251
|
+
if (packageRoot !== descriptor.packageRoot) {
|
|
252
|
+
normalized.packageRoot = packageRoot;
|
|
253
|
+
}
|
|
254
|
+
return normalized;
|
|
255
|
+
}
|
|
256
|
+
async function verifyModulesAsync(options = {}) {
|
|
257
|
+
let searchResult = options.searchResult;
|
|
258
|
+
const inputs = options.modules;
|
|
259
|
+
if (inputs !== undefined && !Array.isArray(inputs)) {
|
|
260
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_OPTIONS', 'modules must be an array when provided.', { stage: 'verify' });
|
|
261
|
+
}
|
|
262
|
+
if (!searchResult && inputs === undefined) {
|
|
263
|
+
const runtime = [
|
|
264
|
+
'@react-native-oh/react-native-harmony',
|
|
265
|
+
'react-native',
|
|
266
|
+
'react-native-tvos',
|
|
267
|
+
].filter((packageName) => {
|
|
268
|
+
try {
|
|
269
|
+
(0, values_1.resolvePackageFromProject)(options.projectRoot || process.cwd(), `${packageName}/package.json`);
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
catch (_cause) {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
searchResult = await (0, search_1.searchModulesAsync)({
|
|
277
|
+
...options,
|
|
278
|
+
include: [...(options.include || []), ...runtime],
|
|
279
|
+
includeReactNativeProjectConfig: true,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
const descriptors = [];
|
|
283
|
+
const diagnostics = [];
|
|
284
|
+
const buildType = searchResult?.options.buildType || options.buildType || 'debug';
|
|
285
|
+
if (inputs !== undefined) {
|
|
286
|
+
for (const input of inputs) {
|
|
287
|
+
try {
|
|
288
|
+
descriptors.push(await validateDescriptorAsync(input, buildType));
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
diagnostics.push(diagnosticFromError(error, input?.packageName));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
const records = [...searchResult.modules].sort((left, right) => {
|
|
297
|
+
return (0, values_1.compareText)(left.packageName, right.packageName)
|
|
298
|
+
|| (0, values_1.compareText)(left.packageVersion, right.packageVersion)
|
|
299
|
+
|| (0, values_1.compareText)(left.packageRoot, right.packageRoot);
|
|
300
|
+
});
|
|
301
|
+
for (const record of records) {
|
|
302
|
+
try {
|
|
303
|
+
descriptors.push(await (0, descriptor_1.createDescriptorFromSearchRecordAsync)(record, buildType));
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
diagnostics.push(diagnosticFromError(error, record.packageName));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
for (const packageName of (0, values_1.sortedUniqueStrings)(searchResult.missingIncludes || [])) {
|
|
310
|
+
diagnostics.push({
|
|
311
|
+
severity: 'warning',
|
|
312
|
+
code: 'ERR_EXPO_HARMONY_INCLUDED_MODULE_NOT_FOUND',
|
|
313
|
+
message: `Included package "${packageName}" was not found.`,
|
|
314
|
+
packageName,
|
|
315
|
+
stage: 'verify',
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
descriptors.sort(resolve_1.compareModuleDescriptors);
|
|
320
|
+
diagnostics.push(...collectDescriptorConflicts(descriptors));
|
|
321
|
+
if (searchResult) {
|
|
322
|
+
const seen = new Map();
|
|
323
|
+
for (const descriptor of descriptors) {
|
|
324
|
+
const set = seen.get(descriptor.packageName) || new Set();
|
|
325
|
+
set.add(`${descriptor.packageVersion}\0${descriptor.packageRoot}`);
|
|
326
|
+
seen.set(descriptor.packageName, set);
|
|
327
|
+
}
|
|
328
|
+
for (const duplicate of searchResult.duplicates || []) {
|
|
329
|
+
const list = [...new Map(duplicate.revisions.map(revision => [
|
|
330
|
+
`${revision.version}\0${revision.path}`, revision,
|
|
331
|
+
])).values()];
|
|
332
|
+
if (list.length < 2 || (seen.get(duplicate.packageName)?.size || 0) >= list.length) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
diagnostics.push(conflictDiagnostic('DUPLICATE_MODULE', 'npm package', duplicate.packageName, list.map(revision => ({
|
|
336
|
+
source: {
|
|
337
|
+
packageName: duplicate.packageName,
|
|
338
|
+
packageVersion: revision.version,
|
|
339
|
+
packageRoot: revision.path,
|
|
340
|
+
},
|
|
341
|
+
})), duplicate.packageName, 'warning'));
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
diagnostics.sort(compareDiagnostics);
|
|
345
|
+
const result = {
|
|
346
|
+
valid: diagnostics.every(diagnostic => diagnostic.severity !== 'error'),
|
|
347
|
+
diagnostics,
|
|
348
|
+
modules: descriptors,
|
|
349
|
+
};
|
|
350
|
+
(0, values_1.emitLog)(options.logger, result.valid ? 'debug' : 'warn', 'Harmony module verification completed.', {
|
|
351
|
+
valid: result.valid,
|
|
352
|
+
diagnosticCount: diagnostics.length,
|
|
353
|
+
moduleCount: descriptors.length,
|
|
354
|
+
});
|
|
355
|
+
return result;
|
|
356
|
+
}
|
|
357
|
+
function assertVerificationSucceeded(result, stage = 'verify') {
|
|
358
|
+
if (result.valid)
|
|
359
|
+
return;
|
|
360
|
+
const first = result.diagnostics.find(diagnostic => diagnostic.severity === 'error');
|
|
361
|
+
throw new errors_1.HarmonyAutolinkingError(first?.code || 'INVALID_METADATA', 'Harmony module verification failed.', {
|
|
362
|
+
diagnostics: result.diagnostics,
|
|
363
|
+
packageName: first?.packageName,
|
|
364
|
+
stage,
|
|
365
|
+
});
|
|
366
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare function parsePositiveInt(value: any): number;
|
|
2
|
+
declare function addCommonOptions(command: any): any;
|
|
3
|
+
declare function toApiOptions(options: any, searchPaths?: any): {
|
|
4
|
+
buildType?: any;
|
|
5
|
+
include?: any;
|
|
6
|
+
exclude?: any;
|
|
7
|
+
nativeModulesDir?: any;
|
|
8
|
+
searchPaths?: any;
|
|
9
|
+
platform: any;
|
|
10
|
+
projectRoot: any;
|
|
11
|
+
};
|
|
12
|
+
export { addCommonOptions, parsePositiveInt, toApiOptions };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addCommonOptions = addCommonOptions;
|
|
4
|
+
exports.parsePositiveInt = parsePositiveInt;
|
|
5
|
+
exports.toApiOptions = toApiOptions;
|
|
6
|
+
const commander_1 = require("commander");
|
|
7
|
+
const constants_1 = require("../config/constants");
|
|
8
|
+
function parsePositiveInt(value) {
|
|
9
|
+
const parsed = Number(value);
|
|
10
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
11
|
+
throw new commander_1.InvalidOptionArgumentError('Expected a positive integer.');
|
|
12
|
+
}
|
|
13
|
+
return parsed;
|
|
14
|
+
}
|
|
15
|
+
function addCommonOptions(command) {
|
|
16
|
+
command
|
|
17
|
+
.option('-e, --exclude <exclude...>', 'package names to exclude when looking up for modules', (value, previous = []) => previous.concat(value))
|
|
18
|
+
.option('-p, --platform [platform]', 'the platform that the resulting modules must support. Available options: "harmony"', constants_1.Platform)
|
|
19
|
+
.option('--project-root <projectRoot>', 'the path to the root of the project. Defaults to current working directory', process.cwd())
|
|
20
|
+
.option('--native-modules-dir <path>', 'replace configured local native modules directory')
|
|
21
|
+
.option('--include <include...>', 'package names to verify for duplicate revisions', (value, previous = []) => previous.concat(value))
|
|
22
|
+
.option('--build-type <type>', 'debug or release');
|
|
23
|
+
return command;
|
|
24
|
+
}
|
|
25
|
+
function toApiOptions(options, searchPaths = undefined) {
|
|
26
|
+
return {
|
|
27
|
+
platform: options.platform,
|
|
28
|
+
projectRoot: options.projectRoot,
|
|
29
|
+
...(searchPaths !== undefined && searchPaths !== null ? { searchPaths } : {}),
|
|
30
|
+
...(options.nativeModulesDir !== undefined ? { nativeModulesDir: options.nativeModulesDir } : {}),
|
|
31
|
+
...(options.exclude !== undefined ? { exclude: options.exclude } : {}),
|
|
32
|
+
...(options.include !== undefined ? { include: options.include } : {}),
|
|
33
|
+
...(options.buildType !== undefined ? { buildType: options.buildType } : {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runCliAsync = runCliAsync;
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
const constants_1 = require("../config/constants");
|
|
7
|
+
const values_1 = require("../utilities/values");
|
|
8
|
+
const link_1 = require("./link");
|
|
9
|
+
const resolve_1 = require("./resolve");
|
|
10
|
+
const search_1 = require("./search");
|
|
11
|
+
const verify_1 = require("./verify");
|
|
12
|
+
function createProgram(io, state) {
|
|
13
|
+
const program = new commander_1.Command();
|
|
14
|
+
program
|
|
15
|
+
.name('expo-harmony-autolinking')
|
|
16
|
+
.description('Expo Modules and RNOH autolinking for HarmonyOS')
|
|
17
|
+
.version(constants_1.ToolVersion)
|
|
18
|
+
.exitOverride()
|
|
19
|
+
.configureOutput({
|
|
20
|
+
writeOut: value => io.stdout(value),
|
|
21
|
+
writeErr: () => { },
|
|
22
|
+
});
|
|
23
|
+
(0, search_1.registerSearchCommand)(program, io);
|
|
24
|
+
(0, resolve_1.registerResolveCommand)(program, io);
|
|
25
|
+
(0, verify_1.registerVerifyCommand)(program, io, state);
|
|
26
|
+
(0, link_1.registerLinkCommand)(program, io);
|
|
27
|
+
return program;
|
|
28
|
+
}
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
+
async function runCliAsync(argv, io = {}) {
|
|
31
|
+
const streams = {
|
|
32
|
+
stdout: io.stdout || (value => process.stdout.write(value)),
|
|
33
|
+
stderr: io.stderr || (value => process.stderr.write(value)),
|
|
34
|
+
};
|
|
35
|
+
const state = { exitCode: 0 };
|
|
36
|
+
const program = createProgram(streams, state);
|
|
37
|
+
try {
|
|
38
|
+
await program.parseAsync(argv, { from: 'user' });
|
|
39
|
+
return state.exitCode;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error instanceof commander_1.CommanderError && error.exitCode === 0)
|
|
43
|
+
return 0;
|
|
44
|
+
const normalized = error instanceof errors_1.HarmonyAutolinkingError
|
|
45
|
+
? error
|
|
46
|
+
: new errors_1.HarmonyAutolinkingError('INVALID_OPTIONS', error.message || String(error), { cause: error, stage: 'cli' });
|
|
47
|
+
streams.stderr((0, values_1.stringifyJson)(normalized.toJSON()));
|
|
48
|
+
return error instanceof commander_1.CommanderError ? Math.max(1, error.exitCode || 2) : 2;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerLinkCommand = registerLinkCommand;
|
|
4
|
+
const link_1 = require("../autolinking/link");
|
|
5
|
+
const autolinkingOptions_1 = require("./autolinkingOptions");
|
|
6
|
+
const output_1 = require("./output");
|
|
7
|
+
function registerLinkCommand(program, io) {
|
|
8
|
+
(0, autolinkingOptions_1.addCommonOptions)(program.command('link [searchPaths...]').description('transactionally link Expo and RNOH modules'))
|
|
9
|
+
.requiredOption('--harmony-project-path <path>', 'Harmony project root')
|
|
10
|
+
.option('--node-modules-path <path>', 'node_modules directory')
|
|
11
|
+
.option('--react-native-executable <path>', 'explicit project-local react-native executable')
|
|
12
|
+
.option('--rnoh-cli-package-json <path>', 'explicit RNOH CLI package.json')
|
|
13
|
+
.option('--timeout-ms <milliseconds>', 'RNOH command timeout', autolinkingOptions_1.parsePositiveInt)
|
|
14
|
+
.option('--output-limit <bytes>', 'per-stream output capture limit', autolinkingOptions_1.parsePositiveInt)
|
|
15
|
+
.option('-j, --json', 'output results in the plain JSON format', false)
|
|
16
|
+
.action(async (searchPaths, options) => {
|
|
17
|
+
(0, output_1.writeResult)(io, await (0, link_1.linkModulesAsync)({
|
|
18
|
+
...(0, autolinkingOptions_1.toApiOptions)(options, searchPaths),
|
|
19
|
+
harmonyProjectPath: options.harmonyProjectPath,
|
|
20
|
+
nodeModulesPath: options.nodeModulesPath,
|
|
21
|
+
reactNativeExecutable: options.reactNativeExecutable,
|
|
22
|
+
rnohCliPackageJsonPath: options.rnohCliPackageJson,
|
|
23
|
+
timeoutMs: options.timeoutMs,
|
|
24
|
+
outputLimit: options.outputLimit,
|
|
25
|
+
}), options);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.writeResult = writeResult;
|
|
4
|
+
exports.writeVerifyResult = writeVerifyResult;
|
|
5
|
+
const node_util_1 = require("node:util");
|
|
6
|
+
const values_1 = require("../utilities/values");
|
|
7
|
+
function formatResult(value) {
|
|
8
|
+
return (0, node_util_1.inspect)(value, { depth: null, colors: false });
|
|
9
|
+
}
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
+
function writeResult(io, value, options = {}) {
|
|
12
|
+
io.stdout(options.json ? (0, values_1.stringifyJson)(value) : `${formatResult(value)}\n`);
|
|
13
|
+
}
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
function writeVerifyResult(io, result, options = {}) {
|
|
16
|
+
if (options.json) {
|
|
17
|
+
writeResult(io, result, options);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (result.diagnostics.length === 0) {
|
|
21
|
+
io.stdout('✅ Everything is fine!\n');
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
for (const diagnostic of result.diagnostics) {
|
|
25
|
+
const icon = diagnostic.severity === 'error' ? '❌' : '⚠️';
|
|
26
|
+
const suffix = diagnostic.packageName ? ` (${diagnostic.packageName})` : '';
|
|
27
|
+
io.stdout(`${icon} [${diagnostic.code}] ${diagnostic.message}${suffix}\n`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (options.verbose) {
|
|
31
|
+
io.stdout(`${formatResult({ modules: result.modules })}\n`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerResolveCommand = registerResolveCommand;
|
|
4
|
+
const resolve_1 = require("../autolinking/resolve");
|
|
5
|
+
const autolinkingOptions_1 = require("./autolinkingOptions");
|
|
6
|
+
const output_1 = require("./output");
|
|
7
|
+
function registerResolveCommand(program, io) {
|
|
8
|
+
(0, autolinkingOptions_1.addCommonOptions)(program.command('resolve [searchPaths...]').description('resolve Harmony module metadata'))
|
|
9
|
+
.option('-j, --json', 'output results in the plain JSON format', false)
|
|
10
|
+
.action(async (searchPaths, options) => {
|
|
11
|
+
(0, output_1.writeResult)(io, await (0, resolve_1.resolveModulesAsync)((0, autolinkingOptions_1.toApiOptions)(options, searchPaths)), options);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerSearchCommand = registerSearchCommand;
|
|
4
|
+
const search_1 = require("../autolinking/search");
|
|
5
|
+
const autolinkingOptions_1 = require("./autolinkingOptions");
|
|
6
|
+
const output_1 = require("./output");
|
|
7
|
+
function registerSearchCommand(program, io) {
|
|
8
|
+
(0, autolinkingOptions_1.addCommonOptions)(program.command('search [searchPaths...]').description('discover Harmony native module candidates'))
|
|
9
|
+
.option('-j, --json', 'output results in the plain JSON format', false)
|
|
10
|
+
.action(async (searchPaths, options) => {
|
|
11
|
+
(0, output_1.writeResult)(io, await (0, search_1.searchModulesAsync)((0, autolinkingOptions_1.toApiOptions)(options, searchPaths)), options);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerVerifyCommand = registerVerifyCommand;
|
|
4
|
+
const verify_1 = require("../autolinking/verify");
|
|
5
|
+
const autolinkingOptions_1 = require("./autolinkingOptions");
|
|
6
|
+
const output_1 = require("./output");
|
|
7
|
+
function registerVerifyCommand(program, io, state) {
|
|
8
|
+
(0, autolinkingOptions_1.addCommonOptions)(program.command('verify').description('verify Harmony module metadata and conflicts'))
|
|
9
|
+
.option('-v, --verbose', 'output all verification details', false)
|
|
10
|
+
.option('-j, --json', 'output results in the plain JSON format', false)
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
const result = await (0, verify_1.verifyModulesAsync)((0, autolinkingOptions_1.toApiOptions)(options));
|
|
13
|
+
(0, output_1.writeVerifyResult)(io, result, options);
|
|
14
|
+
if (!result.valid)
|
|
15
|
+
state.exitCode = 1;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare const Platform = "harmony";
|
|
2
|
+
declare const RnohCliPackage = "@react-native-oh/react-native-harmony-cli";
|
|
3
|
+
declare const ToolVersion: any;
|
|
4
|
+
declare const ManifestSchemaVersion = 3;
|
|
5
|
+
declare const RnohArtifacts: Readonly<{
|
|
6
|
+
etsFactory: "entry/src/main/ets/RNOHPackagesFactory.ets";
|
|
7
|
+
cppFactory: "entry/src/main/cpp/RNOHPackagesFactory.h";
|
|
8
|
+
cmake: "entry/src/main/cpp/autolinking.cmake";
|
|
9
|
+
ohPackage: "oh-package.json5";
|
|
10
|
+
}>;
|
|
11
|
+
declare const ExpoArtifacts: Readonly<{
|
|
12
|
+
hostProvider: "entry/src/main/ets/generated/ExpoHarmonyHostProvider.ets";
|
|
13
|
+
}>;
|
|
14
|
+
declare const ManifestArtifact = ".expo/harmony/autolinking.json";
|
|
15
|
+
declare function managedArtifactsForHarmonyRoot(harmonyRoot: any): readonly string[];
|
|
16
|
+
declare const ManagedArtifacts: readonly string[];
|
|
17
|
+
export { ExpoArtifacts, ManagedArtifacts, ManifestArtifact, ManifestSchemaVersion, managedArtifactsForHarmonyRoot, Platform, RnohArtifacts, RnohCliPackage, ToolVersion, };
|
|
@@ -0,0 +1,40 @@
|
|
|
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.ToolVersion = exports.RnohCliPackage = exports.RnohArtifacts = exports.Platform = exports.ManifestSchemaVersion = exports.ManifestArtifact = exports.ManagedArtifacts = exports.ExpoArtifacts = void 0;
|
|
7
|
+
exports.managedArtifactsForHarmonyRoot = managedArtifactsForHarmonyRoot;
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const Platform = 'harmony';
|
|
11
|
+
exports.Platform = Platform;
|
|
12
|
+
const RnohCliPackage = '@react-native-oh/react-native-harmony-cli';
|
|
13
|
+
exports.RnohCliPackage = RnohCliPackage;
|
|
14
|
+
const ToolVersion = JSON.parse((0, node_fs_1.readFileSync)(node_path_1.default.resolve(__dirname, '../../../package.json'), 'utf8')).version;
|
|
15
|
+
exports.ToolVersion = ToolVersion;
|
|
16
|
+
const ManifestSchemaVersion = 3;
|
|
17
|
+
exports.ManifestSchemaVersion = ManifestSchemaVersion;
|
|
18
|
+
const RnohArtifacts = Object.freeze({
|
|
19
|
+
etsFactory: 'entry/src/main/ets/RNOHPackagesFactory.ets',
|
|
20
|
+
cppFactory: 'entry/src/main/cpp/RNOHPackagesFactory.h',
|
|
21
|
+
cmake: 'entry/src/main/cpp/autolinking.cmake',
|
|
22
|
+
ohPackage: 'oh-package.json5',
|
|
23
|
+
});
|
|
24
|
+
exports.RnohArtifacts = RnohArtifacts;
|
|
25
|
+
const ExpoArtifacts = Object.freeze({
|
|
26
|
+
hostProvider: 'entry/src/main/ets/generated/ExpoHarmonyHostProvider.ets',
|
|
27
|
+
});
|
|
28
|
+
exports.ExpoArtifacts = ExpoArtifacts;
|
|
29
|
+
const ManifestArtifact = '.expo/harmony/autolinking.json';
|
|
30
|
+
exports.ManifestArtifact = ManifestArtifact;
|
|
31
|
+
function managedArtifactsForHarmonyRoot(harmonyRoot) {
|
|
32
|
+
const prefix = String(harmonyRoot).replace(/\\/g, '/').replace(/^\.\//, '').replace(/\/$/, '');
|
|
33
|
+
const withinHarmony = [
|
|
34
|
+
...Object.values(RnohArtifacts),
|
|
35
|
+
...Object.values(ExpoArtifacts),
|
|
36
|
+
].map(relative => prefix ? `${prefix}/${relative}` : relative);
|
|
37
|
+
return Object.freeze([...withinHarmony, ManifestArtifact]);
|
|
38
|
+
}
|
|
39
|
+
const ManagedArtifacts = managedArtifactsForHarmonyRoot('harmony');
|
|
40
|
+
exports.ManagedArtifacts = ManagedArtifacts;
|