@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
package/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# @expo-harmony/expo-modules-autolinking
|
|
2
|
+
|
|
3
|
+
[**GitHub 仓库**](https://github.com/renbaoshuo/expo-harmony/tree/master/packages/expo-modules-autolinking)
|
|
4
|
+
|
|
5
|
+
为 HarmonyOS 上的 React Native 应用提供 Expo Modules 和 RNOH 原生模块自动链接能力,与官方同版本的 expo-modules-autolinking 配套使用。
|
|
6
|
+
|
|
7
|
+
## Author
|
|
8
|
+
|
|
9
|
+
**expo-harmony** © [Baoshuo](https://github.com/renbaoshuo), Released under the MIT License.<br>
|
|
10
|
+
Authored and maintained by Baoshuo with help from [contributors](https://github.com/renbaoshuo/expo-harmony/contributors).
|
|
11
|
+
|
|
12
|
+
> [Personal Website](https://baoshuo.ren) · [Blog](https://blog.baoshuo.ren) · GitHub [@renbaoshuo](https://github.com/renbaoshuo) · Twitter [@baoshuo](https://twitter.com/baoshuo)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { runCliAsync } from '../src/commands/cli';
|
|
4
|
+
|
|
5
|
+
runCliAsync(process.argv.slice(2)).then(
|
|
6
|
+
(exitCode) => {
|
|
7
|
+
process.exitCode = exitCode;
|
|
8
|
+
},
|
|
9
|
+
(error) => {
|
|
10
|
+
const message = error instanceof Error ? error.stack || error.message : String(error);
|
|
11
|
+
process.stderr.write(`${message}\n`);
|
|
12
|
+
process.exitCode = 2;
|
|
13
|
+
}
|
|
14
|
+
);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const cli_1 = require("../src/commands/cli");
|
|
5
|
+
(0, cli_1.runCliAsync)(process.argv.slice(2)).then((exitCode) => {
|
|
6
|
+
process.exitCode = exitCode;
|
|
7
|
+
}, (error) => {
|
|
8
|
+
const message = error instanceof Error ? error.stack || error.message : String(error);
|
|
9
|
+
process.stderr.write(`${message}\n`);
|
|
10
|
+
process.exitCode = 2;
|
|
11
|
+
});
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { linkModulesAsync } from './src/autolinking/link';
|
|
2
|
+
import { canonicalizeAutolinkingArtifacts } from './src/harmony/persistence/canonicalize';
|
|
3
|
+
import { resolveModulesAsync } from './src/autolinking/resolve';
|
|
4
|
+
import { searchModulesAsync } from './src/autolinking/search';
|
|
5
|
+
import { verifyModulesAsync } from './src/autolinking/verify';
|
|
6
|
+
import { normalizeHarmonyModuleMetadata } from './src/metadata/schema';
|
|
7
|
+
export { canonicalizeAutolinkingArtifacts, linkModulesAsync, normalizeHarmonyModuleMetadata, resolveModulesAsync, searchModulesAsync, verifyModulesAsync, };
|
|
8
|
+
export type { BuildType, CanonicalizeAutolinkingArtifactsOptions, CanonicalizedAutolinkingArtifacts, Diagnostic, DiagnosticSource, ExpoMetadata, HostMetadata, HarmonyModuleMetadata, LinkOptions, LinkResult, Logger, Manifest, ModuleDescriptor, ModuleArtifactDescriptor, ModuleSource, Platform, ResolveOptions, RnohMetadata, SearchOptions, SearchRecord, SearchResult, VerificationResult, VerifyOptions, } from './src/types';
|
package/build/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.verifyModulesAsync = exports.searchModulesAsync = exports.resolveModulesAsync = exports.normalizeHarmonyModuleMetadata = exports.linkModulesAsync = exports.canonicalizeAutolinkingArtifacts = void 0;
|
|
4
|
+
const link_1 = require("./src/autolinking/link");
|
|
5
|
+
Object.defineProperty(exports, "linkModulesAsync", { enumerable: true, get: function () { return link_1.linkModulesAsync; } });
|
|
6
|
+
const canonicalize_1 = require("./src/harmony/persistence/canonicalize");
|
|
7
|
+
Object.defineProperty(exports, "canonicalizeAutolinkingArtifacts", { enumerable: true, get: function () { return canonicalize_1.canonicalizeAutolinkingArtifacts; } });
|
|
8
|
+
const resolve_1 = require("./src/autolinking/resolve");
|
|
9
|
+
Object.defineProperty(exports, "resolveModulesAsync", { enumerable: true, get: function () { return resolve_1.resolveModulesAsync; } });
|
|
10
|
+
const search_1 = require("./src/autolinking/search");
|
|
11
|
+
Object.defineProperty(exports, "searchModulesAsync", { enumerable: true, get: function () { return search_1.searchModulesAsync; } });
|
|
12
|
+
const verify_1 = require("./src/autolinking/verify");
|
|
13
|
+
Object.defineProperty(exports, "verifyModulesAsync", { enumerable: true, get: function () { return verify_1.verifyModulesAsync; } });
|
|
14
|
+
const schema_1 = require("./src/metadata/schema");
|
|
15
|
+
Object.defineProperty(exports, "normalizeHarmonyModuleMetadata", { enumerable: true, get: function () { return schema_1.normalizeHarmonyModuleMetadata; } });
|
|
@@ -0,0 +1,150 @@
|
|
|
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.linkModulesAsync = linkModulesAsync;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const constants_1 = require("../config/constants");
|
|
9
|
+
const host_1 = require("../harmony/providers/host");
|
|
10
|
+
const generate_1 = require("../harmony/manifest/generate");
|
|
11
|
+
const errors_1 = require("../errors");
|
|
12
|
+
const options_1 = require("../config/options");
|
|
13
|
+
const link_1 = require("../harmony/rnoh/link");
|
|
14
|
+
const stageProject_1 = require("../harmony/transaction/stageProject");
|
|
15
|
+
const publish_1 = require("../harmony/transaction/publish");
|
|
16
|
+
const previousState_1 = require("../harmony/transaction/previousState");
|
|
17
|
+
const verify_1 = require("./verify");
|
|
18
|
+
const values_1 = require("../utilities/values");
|
|
19
|
+
const materialize_1 = require("../harmony/materialize");
|
|
20
|
+
function buildPublishEntries(staging, hostProviderSource, manifest) {
|
|
21
|
+
return [
|
|
22
|
+
...Object.entries(constants_1.RnohArtifacts).map(([name, relative]) => ({
|
|
23
|
+
source: staging.rnohArtifacts[name].path,
|
|
24
|
+
target: node_path_1.default.join(staging.harmonyProjectPath, relative),
|
|
25
|
+
})),
|
|
26
|
+
{
|
|
27
|
+
content: hostProviderSource,
|
|
28
|
+
target: node_path_1.default.join(staging.harmonyProjectPath, constants_1.ExpoArtifacts.hostProvider),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
content: manifest,
|
|
32
|
+
target: node_path_1.default.join(staging.projectRoot, constants_1.ManifestArtifact),
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
async function linkModulesAsync(rawOptions) {
|
|
37
|
+
const options = await (0, options_1.normalizeOptionsAsync)(rawOptions);
|
|
38
|
+
if (typeof rawOptions.harmonyProjectPath !== 'string' || !rawOptions.harmonyProjectPath) {
|
|
39
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_OPTIONS', 'link requires harmonyProjectPath.', { stage: 'link' });
|
|
40
|
+
}
|
|
41
|
+
const verify = await (0, verify_1.verifyModulesAsync)((rawOptions.modules !== undefined
|
|
42
|
+
? { modules: rawOptions.modules }
|
|
43
|
+
: { ...options, searchResult: rawOptions.searchResult }));
|
|
44
|
+
(0, verify_1.assertVerificationSucceeded)(verify, 'link');
|
|
45
|
+
const modules = verify.modules;
|
|
46
|
+
const pendingSource = modules.filter(module => module.artifact.kind === 'local-source');
|
|
47
|
+
if (pendingSource.length > 0) {
|
|
48
|
+
if (pendingSource.some(module => module.source !== 'nativeModulesDir')) {
|
|
49
|
+
throw new errors_1.HarmonyAutolinkingError('SOURCE_ARTIFACT_MATERIALIZATION_REQUIRED', 'Only nativeModulesDir modules may build a local Harmony HAR.', { stage: 'link', details: pendingSource.map(module => module.packageName).sort() });
|
|
50
|
+
}
|
|
51
|
+
await (0, materialize_1.materializeLocalSourcesAsync)(pendingSource, {
|
|
52
|
+
projectRoot: options.projectRoot,
|
|
53
|
+
timeoutMs: rawOptions.timeoutMs,
|
|
54
|
+
outputLimit: rawOptions.outputLimit,
|
|
55
|
+
env: rawOptions.env,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const hostProviderSource = (0, host_1.renderArkTsHostProviderSource)(modules);
|
|
59
|
+
let staging;
|
|
60
|
+
let failure;
|
|
61
|
+
let cleanupWarning;
|
|
62
|
+
const warnings = [];
|
|
63
|
+
try {
|
|
64
|
+
const previous = await (0, previousState_1.readPreviousAutolinkingStateAsync)(options.projectRoot);
|
|
65
|
+
if (previous.warning) {
|
|
66
|
+
warnings.push(previous.warning);
|
|
67
|
+
(0, values_1.emitLog)(rawOptions.logger, 'warn', previous.warning.message, previous.warning);
|
|
68
|
+
}
|
|
69
|
+
staging = await (0, stageProject_1.stageProjectAsync)({
|
|
70
|
+
projectRoot: options.projectRoot,
|
|
71
|
+
harmonyProjectPath: rawOptions.harmonyProjectPath,
|
|
72
|
+
nodeModulesPath: rawOptions.nodeModulesPath,
|
|
73
|
+
modules,
|
|
74
|
+
buildType: options.buildType,
|
|
75
|
+
previousManagedOhpmPackageNames: previous.managedOhpmPackageNames,
|
|
76
|
+
rnohCliPackageJsonPath: rawOptions.rnohCliPackageJsonPath,
|
|
77
|
+
});
|
|
78
|
+
staging.rnohArtifacts = await (0, link_1.linkRnohAsync)({
|
|
79
|
+
...staging,
|
|
80
|
+
modules,
|
|
81
|
+
buildType: options.buildType,
|
|
82
|
+
exclude: staging.rnohRuntimePackages,
|
|
83
|
+
commandNodeModulesPath: staging.sourceNodeModulesPath,
|
|
84
|
+
reactNativeExecutable: rawOptions.reactNativeExecutable,
|
|
85
|
+
rnohCliPackageJsonPath: rawOptions.rnohCliPackageJsonPath,
|
|
86
|
+
timeoutMs: rawOptions.timeoutMs,
|
|
87
|
+
outputLimit: rawOptions.outputLimit,
|
|
88
|
+
env: rawOptions.env,
|
|
89
|
+
});
|
|
90
|
+
const harmonyRoot = node_path_1.default.relative(staging.projectRoot, staging.harmonyProjectPath)
|
|
91
|
+
.split(node_path_1.default.sep).join('/');
|
|
92
|
+
const managed = (0, constants_1.managedArtifactsForHarmonyRoot)(harmonyRoot);
|
|
93
|
+
const manifest = (0, generate_1.serializeManifest)(modules, {
|
|
94
|
+
buildType: options.buildType,
|
|
95
|
+
managedArtifacts: managed,
|
|
96
|
+
});
|
|
97
|
+
const published = await (0, publish_1.publishArtifactsAsync)({
|
|
98
|
+
allowedRoot: staging.projectRoot,
|
|
99
|
+
lockPath: node_path_1.default.join(staging.projectRoot, '.expo/harmony/autolinking.lock'),
|
|
100
|
+
files: buildPublishEntries(staging, hostProviderSource, manifest),
|
|
101
|
+
stale: previous.artifacts.filter(artifact => !managed.some((relative) => {
|
|
102
|
+
return artifact === node_path_1.default.join(staging.projectRoot, ...relative.split('/'));
|
|
103
|
+
})),
|
|
104
|
+
});
|
|
105
|
+
const result = {
|
|
106
|
+
platform: 'harmony',
|
|
107
|
+
modules,
|
|
108
|
+
buildType: options.buildType,
|
|
109
|
+
managedArtifacts: [...managed],
|
|
110
|
+
changedArtifacts: published.changed.map(target => node_path_1.default.relative(staging.projectRoot, target).split(node_path_1.default.sep).join('/')),
|
|
111
|
+
unchangedArtifacts: published.unchanged.map(target => node_path_1.default.relative(staging.projectRoot, target).split(node_path_1.default.sep).join('/')),
|
|
112
|
+
diagnostics: verify.diagnostics,
|
|
113
|
+
warnings,
|
|
114
|
+
};
|
|
115
|
+
(0, values_1.emitLog)(rawOptions.logger, 'info', 'Harmony autolinking completed.', {
|
|
116
|
+
moduleCount: result.modules.length,
|
|
117
|
+
changedArtifactCount: result.changedArtifacts.length,
|
|
118
|
+
});
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
failure = error;
|
|
123
|
+
(0, values_1.emitLog)(rawOptions.logger, 'error', 'Harmony autolinking failed.', {
|
|
124
|
+
code: error.code || 'ERR_EXPO_HARMONY_UNKNOWN',
|
|
125
|
+
stage: error.stage || 'link',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
if (staging) {
|
|
130
|
+
const cleanup = await (0, stageProject_1.cleanupStagingProjectAsync)(staging);
|
|
131
|
+
if (cleanup) {
|
|
132
|
+
const warning = { ...cleanup };
|
|
133
|
+
delete warning.cause;
|
|
134
|
+
warnings.push(warning);
|
|
135
|
+
(0, values_1.emitLog)(rawOptions.logger, 'warn', warning.message, warning);
|
|
136
|
+
if (failure)
|
|
137
|
+
cleanupWarning = warning;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
throw new errors_1.HarmonyAutolinkingError(typeof failure.code === 'string' ? failure.code : 'UNKNOWN', failure.message || 'Harmony autolinking failed.', {
|
|
142
|
+
cause: failure,
|
|
143
|
+
stage: failure.stage || 'link',
|
|
144
|
+
packageName: failure.packageName,
|
|
145
|
+
diagnostics: failure.diagnostics,
|
|
146
|
+
details: cleanupWarning
|
|
147
|
+
? { ...(failure.details || {}), cleanupWarning }
|
|
148
|
+
: failure.details,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ModuleDescriptor, ResolveOptions } from '../types';
|
|
2
|
+
declare function compareModuleDescriptors(left: any, right: any): 1 | -1 | 0;
|
|
3
|
+
declare function resolveModulesAsync(options?: ResolveOptions): Promise<ModuleDescriptor[]>;
|
|
4
|
+
export { compareModuleDescriptors, resolveModulesAsync, };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.compareModuleDescriptors = compareModuleDescriptors;
|
|
4
|
+
exports.resolveModulesAsync = resolveModulesAsync;
|
|
5
|
+
const search_1 = require("./search");
|
|
6
|
+
const descriptor_1 = require("../metadata/descriptor");
|
|
7
|
+
const values_1 = require("../utilities/values");
|
|
8
|
+
function compareModuleDescriptors(left, right) {
|
|
9
|
+
return (0, values_1.compareText)(left.packageName, right.packageName)
|
|
10
|
+
|| (0, values_1.compareText)(left.packageVersion, right.packageVersion)
|
|
11
|
+
|| (0, values_1.compareText)(left.packageRoot, right.packageRoot);
|
|
12
|
+
}
|
|
13
|
+
async function resolveModulesAsync(options = {}) {
|
|
14
|
+
const searchResult = options.searchResult || await (0, search_1.searchModulesAsync)(options);
|
|
15
|
+
const records = [...searchResult.modules].sort(compareModuleDescriptors);
|
|
16
|
+
const descriptors = [];
|
|
17
|
+
for (const record of records) {
|
|
18
|
+
descriptors.push(await (0, descriptor_1.createDescriptorFromSearchRecordAsync)(record, searchResult.options.buildType));
|
|
19
|
+
}
|
|
20
|
+
const result = descriptors.sort(compareModuleDescriptors);
|
|
21
|
+
(0, values_1.emitLog)(options.logger, 'debug', 'Harmony module resolution completed.', {
|
|
22
|
+
moduleCount: descriptors.length,
|
|
23
|
+
});
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.searchModulesAsync = searchModulesAsync;
|
|
40
|
+
const expoAutolinking = __importStar(require("expo-modules-autolinking/exports"));
|
|
41
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
42
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
43
|
+
const node_util_1 = require("node:util");
|
|
44
|
+
const constants_1 = require("../config/constants");
|
|
45
|
+
const errors_1 = require("../errors");
|
|
46
|
+
const options_1 = require("../config/options");
|
|
47
|
+
const values_1 = require("../utilities/values");
|
|
48
|
+
function loadUpstreamAutolinkingApi() {
|
|
49
|
+
const upstreamApi = expoAutolinking;
|
|
50
|
+
for (const name of ['makeCachedDependenciesLinker']) {
|
|
51
|
+
if (typeof upstreamApi[name] !== 'function') {
|
|
52
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_OPTIONS', `expo-modules-autolinking public export ${name} is unavailable.`, { stage: 'search' });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return upstreamApi;
|
|
56
|
+
}
|
|
57
|
+
function supportsHarmony(config) {
|
|
58
|
+
return Array.isArray(config?.platforms) && config.platforms.includes(constants_1.Platform);
|
|
59
|
+
}
|
|
60
|
+
function hasHarmonyExpoMetadata(config) {
|
|
61
|
+
return supportsHarmony(config);
|
|
62
|
+
}
|
|
63
|
+
async function readExpoModuleConfigAsync(packageRoot) {
|
|
64
|
+
const target = node_path_1.default.join(packageRoot, 'expo-module.config.json');
|
|
65
|
+
return await (0, values_1.pathExistsAsync)(target)
|
|
66
|
+
? (0, values_1.readJsonAsync)(target, 'INVALID_METADATA', 'search')
|
|
67
|
+
: null;
|
|
68
|
+
}
|
|
69
|
+
function nodeModulesDepth(originPath) {
|
|
70
|
+
return String(originPath).split(`${node_path_1.default.sep}node_modules${node_path_1.default.sep}`).length;
|
|
71
|
+
}
|
|
72
|
+
function isPreferredRevision(left, right) {
|
|
73
|
+
const leftDepth = Number.isInteger(left.depth) ? left.depth : Number.POSITIVE_INFINITY;
|
|
74
|
+
const rightDepth = Number.isInteger(right.depth) ? right.depth : Number.POSITIVE_INFINITY;
|
|
75
|
+
if (leftDepth !== rightDepth)
|
|
76
|
+
return leftDepth < rightDepth;
|
|
77
|
+
const leftNest = nodeModulesDepth(left.originPath);
|
|
78
|
+
const rightNest = nodeModulesDepth(right.originPath);
|
|
79
|
+
if (leftNest !== rightNest)
|
|
80
|
+
return leftNest < rightNest;
|
|
81
|
+
if (left.source !== right.source)
|
|
82
|
+
return left.source < right.source;
|
|
83
|
+
return (0, values_1.compareText)(left.originPath, right.originPath) < 0;
|
|
84
|
+
}
|
|
85
|
+
function mergeRevisions(resultSets) {
|
|
86
|
+
const merged = Object.create(null);
|
|
87
|
+
for (const results of resultSets) {
|
|
88
|
+
for (const packageName of Object.keys(results)) {
|
|
89
|
+
const incoming = results[packageName];
|
|
90
|
+
if (!incoming)
|
|
91
|
+
continue;
|
|
92
|
+
const current = merged[packageName];
|
|
93
|
+
if (!current) {
|
|
94
|
+
merged[packageName] = {
|
|
95
|
+
...incoming,
|
|
96
|
+
duplicates: [...(incoming.duplicates || [])],
|
|
97
|
+
};
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (current.path === incoming.path) {
|
|
101
|
+
if (!current.version && incoming.version)
|
|
102
|
+
current.version = incoming.version;
|
|
103
|
+
for (const candidate of incoming.duplicates || []) {
|
|
104
|
+
if (candidate.path !== current.path
|
|
105
|
+
&& !current.duplicates.some(item => item.path === candidate.path)) {
|
|
106
|
+
current.duplicates.push(candidate);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
let winner = current;
|
|
112
|
+
let duplicate = incoming;
|
|
113
|
+
if (isPreferredRevision(incoming, current)) {
|
|
114
|
+
winner = { ...incoming, duplicates: [...(incoming.duplicates || [])] };
|
|
115
|
+
duplicate = current;
|
|
116
|
+
merged[packageName] = winner;
|
|
117
|
+
}
|
|
118
|
+
const candidates = [
|
|
119
|
+
{ ...duplicate, duplicates: undefined },
|
|
120
|
+
...(duplicate.duplicates || []),
|
|
121
|
+
];
|
|
122
|
+
for (const candidate of candidates) {
|
|
123
|
+
if (candidate.path !== winner.path
|
|
124
|
+
&& !(winner.duplicates || []).some(item => item.path === candidate.path)) {
|
|
125
|
+
winner.duplicates.push(candidate);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return merged;
|
|
131
|
+
}
|
|
132
|
+
function classifySource(revision, packageRoot, options) {
|
|
133
|
+
if (revision.source === 2) {
|
|
134
|
+
return 'reactNativeProjectConfig';
|
|
135
|
+
}
|
|
136
|
+
if (options.nativeModulesDir
|
|
137
|
+
&& (0, values_1.isPathInside)(options.nativeModulesDir, packageRoot)) {
|
|
138
|
+
return 'nativeModulesDir';
|
|
139
|
+
}
|
|
140
|
+
if (options.searchPaths.some(searchPath => (0, values_1.isPathInside)(searchPath, packageRoot))) {
|
|
141
|
+
return 'searchPath';
|
|
142
|
+
}
|
|
143
|
+
return 'dependency';
|
|
144
|
+
}
|
|
145
|
+
async function resolveDependencyRevisionsAsync(upstreamApi, options) {
|
|
146
|
+
const linker = upstreamApi.makeCachedDependenciesLinker({ projectRoot: options.projectRoot });
|
|
147
|
+
const resultSets = [];
|
|
148
|
+
if (options.includeReactNativeProjectConfig) {
|
|
149
|
+
resultSets.push(await linker.scanDependenciesFromRNProjectConfig());
|
|
150
|
+
}
|
|
151
|
+
if (options.nativeModulesDir && await (0, values_1.pathExistsAsync)(options.nativeModulesDir)) {
|
|
152
|
+
resultSets.push(await linker.scanDependenciesInSearchPath(options.nativeModulesDir));
|
|
153
|
+
}
|
|
154
|
+
for (const searchPath of options.searchPaths) {
|
|
155
|
+
if (await (0, values_1.pathExistsAsync)(searchPath)) {
|
|
156
|
+
resultSets.push(await linker.scanDependenciesInSearchPath(searchPath));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
resultSets.push(await linker.scanDependenciesRecursively());
|
|
160
|
+
return mergeRevisions(resultSets);
|
|
161
|
+
}
|
|
162
|
+
async function loadOverridesAsync(deps) {
|
|
163
|
+
const overrides = Object.create(null);
|
|
164
|
+
const owners = Object.create(null);
|
|
165
|
+
const required = new Set();
|
|
166
|
+
for (const name of Object.keys(deps).sort(values_1.compareText)) {
|
|
167
|
+
const revision = deps[name];
|
|
168
|
+
if (!revision)
|
|
169
|
+
continue;
|
|
170
|
+
let packageRoot;
|
|
171
|
+
let packageJson;
|
|
172
|
+
try {
|
|
173
|
+
packageRoot = await node_fs_1.default.promises.realpath(revision.path);
|
|
174
|
+
packageJson = await (0, values_1.readJsonAsync)(node_path_1.default.join(packageRoot, 'package.json'), 'INVALID_METADATA', 'search');
|
|
175
|
+
}
|
|
176
|
+
catch (_cause) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
const packageName = typeof packageJson.name === 'string' && packageJson.name ? packageJson.name : name;
|
|
180
|
+
const harmony = (0, values_1.isObject)(packageJson.harmony) ? packageJson.harmony : {};
|
|
181
|
+
const declared = (0, options_1.normalizeModuleOverrides)(harmony.modules, {
|
|
182
|
+
code: 'INVALID_METADATA',
|
|
183
|
+
field: `${packageName} package.json#harmony.modules`,
|
|
184
|
+
stage: 'search',
|
|
185
|
+
});
|
|
186
|
+
const dependencies = (0, values_1.isObject)(packageJson.dependencies) ? packageJson.dependencies : {};
|
|
187
|
+
const optional = (0, values_1.isObject)(packageJson.optionalDependencies) ? packageJson.optionalDependencies : {};
|
|
188
|
+
const peers = (0, values_1.isObject)(packageJson.peerDependencies) ? packageJson.peerDependencies : {};
|
|
189
|
+
const peerMeta = (0, values_1.isObject)(packageJson.peerDependenciesMeta) ? packageJson.peerDependenciesMeta : {};
|
|
190
|
+
for (const [target, metadata] of Object.entries(declared)) {
|
|
191
|
+
if (![dependencies, optional, peers].some(group => Object.hasOwn(group, target))) {
|
|
192
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', `${packageName} declares Harmony module ${target} but does not list it in a production dependency field.`, { packageName, stage: 'search' });
|
|
193
|
+
}
|
|
194
|
+
if (Object.hasOwn(dependencies, target)
|
|
195
|
+
|| (Object.hasOwn(peers, target) && peerMeta[target]?.optional !== true)) {
|
|
196
|
+
required.add(target);
|
|
197
|
+
}
|
|
198
|
+
if (overrides[target] !== undefined && !(0, node_util_1.isDeepStrictEqual)(overrides[target], metadata)) {
|
|
199
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', `${packageName} and ${owners[target]} declare conflicting Harmony metadata for ${target}.`, { packageName: target, stage: 'search' });
|
|
200
|
+
}
|
|
201
|
+
overrides[target] = metadata;
|
|
202
|
+
owners[target] = packageName;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
requiredTargets: required,
|
|
207
|
+
overrides: Object.freeze(overrides),
|
|
208
|
+
owners: Object.freeze(owners),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
async function createSearchRecordAsync(revision, options) {
|
|
212
|
+
let packageRoot;
|
|
213
|
+
try {
|
|
214
|
+
packageRoot = await node_fs_1.default.promises.realpath(revision.path);
|
|
215
|
+
}
|
|
216
|
+
catch (_cause) {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
220
|
+
let packageJson = {};
|
|
221
|
+
try {
|
|
222
|
+
packageJson = await (0, values_1.readJsonAsync)(node_path_1.default.join(packageRoot, 'package.json'), 'INVALID_METADATA', 'search');
|
|
223
|
+
}
|
|
224
|
+
catch (_cause) {
|
|
225
|
+
// Expo's search-path scanner tolerates roots without a readable
|
|
226
|
+
// package.json and falls back to the dependency revision name.
|
|
227
|
+
}
|
|
228
|
+
const packageName = typeof packageJson.name === 'string' && packageJson.name
|
|
229
|
+
? packageJson.name
|
|
230
|
+
: revision.name;
|
|
231
|
+
if (options.exclude.includes(revision.name || packageName))
|
|
232
|
+
return null;
|
|
233
|
+
const expo = await readExpoModuleConfigAsync(packageRoot);
|
|
234
|
+
const harmony = hasHarmonyExpoMetadata(expo);
|
|
235
|
+
const metadata = (0, values_1.isObject)(packageJson.harmony) ? packageJson.harmony : null;
|
|
236
|
+
const sidecar = options.moduleOverrides[packageName];
|
|
237
|
+
let rnohMetadata = metadata?.autolinking === undefined ? null : metadata.autolinking;
|
|
238
|
+
if (sidecar !== undefined) {
|
|
239
|
+
const { version: _version, ...metadata } = sidecar;
|
|
240
|
+
rnohMetadata = metadata;
|
|
241
|
+
}
|
|
242
|
+
const included = options.include.includes(revision.name || packageName);
|
|
243
|
+
return {
|
|
244
|
+
packageName,
|
|
245
|
+
packageVersion: typeof packageJson.version === 'string' ? packageJson.version : String(revision.version || ''),
|
|
246
|
+
packageRoot,
|
|
247
|
+
source: classifySource(revision, packageRoot, options),
|
|
248
|
+
supportsHarmony: harmony,
|
|
249
|
+
expoModuleConfig: expo,
|
|
250
|
+
rnohMetadata,
|
|
251
|
+
nativeCandidate: harmony || rnohMetadata != null,
|
|
252
|
+
includedForVerification: included,
|
|
253
|
+
revision: {
|
|
254
|
+
depth: Number.isInteger(revision.depth) ? revision.depth : null,
|
|
255
|
+
originPath: typeof revision.originPath === 'string' ? revision.originPath : packageRoot,
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function compareSearchRecords(left, right) {
|
|
260
|
+
return (0, values_1.compareText)(left.packageName, right.packageName)
|
|
261
|
+
|| (0, values_1.compareText)(left.packageVersion, right.packageVersion)
|
|
262
|
+
|| (0, values_1.compareText)(left.packageRoot, right.packageRoot);
|
|
263
|
+
}
|
|
264
|
+
function findDuplicates(records) {
|
|
265
|
+
const byName = new Map();
|
|
266
|
+
for (const record of records) {
|
|
267
|
+
const revisions = byName.get(record.packageName) || [];
|
|
268
|
+
revisions.push({ version: record.packageVersion, path: record.packageRoot });
|
|
269
|
+
byName.set(record.packageName, revisions);
|
|
270
|
+
}
|
|
271
|
+
return [...byName.entries()]
|
|
272
|
+
.filter(([, revisions]) => new Set(revisions.map(revision => `${revision.version}\0${revision.path}`)).size > 1)
|
|
273
|
+
.map(([packageName, revisions]) => ({
|
|
274
|
+
packageName,
|
|
275
|
+
revisions: revisions.sort((left, right) => (0, values_1.compareText)(left.version, right.version)
|
|
276
|
+
|| (0, values_1.compareText)(left.path, right.path)),
|
|
277
|
+
}))
|
|
278
|
+
.sort((left, right) => (0, values_1.compareText)(left.packageName, right.packageName));
|
|
279
|
+
}
|
|
280
|
+
async function searchModulesAsync(rawOptions = {}) {
|
|
281
|
+
const input = rawOptions;
|
|
282
|
+
const options = {
|
|
283
|
+
...await (0, options_1.normalizeOptionsAsync)(rawOptions),
|
|
284
|
+
includeReactNativeProjectConfig: input.includeReactNativeProjectConfig === true,
|
|
285
|
+
};
|
|
286
|
+
const upstreamApi = loadUpstreamAutolinkingApi();
|
|
287
|
+
const deps = await resolveDependencyRevisionsAsync(upstreamApi, options);
|
|
288
|
+
const overrides = await loadOverridesAsync(deps);
|
|
289
|
+
const modules = Object.freeze({
|
|
290
|
+
...overrides.overrides,
|
|
291
|
+
...options.moduleOverrides,
|
|
292
|
+
});
|
|
293
|
+
const search = { ...options, moduleOverrides: modules };
|
|
294
|
+
const selected = new Map();
|
|
295
|
+
const unique = new Map();
|
|
296
|
+
for (const name of Object.keys(deps).sort(values_1.compareText)) {
|
|
297
|
+
const resolution = deps[name];
|
|
298
|
+
if (!resolution)
|
|
299
|
+
continue;
|
|
300
|
+
const revisions = [
|
|
301
|
+
resolution,
|
|
302
|
+
...(resolution.duplicates || []).map(duplicate => ({
|
|
303
|
+
...resolution,
|
|
304
|
+
...duplicate,
|
|
305
|
+
duplicates: null,
|
|
306
|
+
})),
|
|
307
|
+
];
|
|
308
|
+
const records = (await Promise.all(revisions.map(revision => createSearchRecordAsync(revision, search))))
|
|
309
|
+
.filter(Boolean);
|
|
310
|
+
const winner = records[0];
|
|
311
|
+
let chosen = winner?.nativeCandidate || winner?.includedForVerification ? winner : null;
|
|
312
|
+
if (!chosen && resolution.source === 1) {
|
|
313
|
+
chosen = records.slice(1).find(record => record.nativeCandidate || record.includedForVerification) || null;
|
|
314
|
+
}
|
|
315
|
+
if (!chosen)
|
|
316
|
+
continue;
|
|
317
|
+
if (chosen.nativeCandidate)
|
|
318
|
+
selected.set(chosen.packageName, chosen);
|
|
319
|
+
for (const record of records) {
|
|
320
|
+
const key = `${record.packageName}\0${record.packageVersion}\0${record.packageRoot}`;
|
|
321
|
+
if (!unique.has(key))
|
|
322
|
+
unique.set(key, record);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
326
|
+
for (const [packageName, sidecar] of Object.entries(modules)) {
|
|
327
|
+
const record = selected.get(packageName);
|
|
328
|
+
if (record && sidecar.version !== undefined && sidecar.version !== record.packageVersion) {
|
|
329
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', `Harmony sidecar module ${packageName} targets ${sidecar.version}, but ${record.packageVersion} is installed.`, { packageName, stage: 'search' });
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
const all = [...unique.values()];
|
|
333
|
+
const found = new Set(all.map(record => record.packageName));
|
|
334
|
+
for (const [packageName, owner] of Object.entries(overrides.owners)) {
|
|
335
|
+
if (!found.has(packageName) && overrides.requiredTargets.has(packageName)) {
|
|
336
|
+
throw new errors_1.HarmonyAutolinkingError('INVALID_METADATA', `${owner} declares Harmony module ${packageName}, but that dependency is not installed.`, { packageName, stage: 'search' });
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const verified = all.filter(record => modules[record.packageName] === undefined || selected.get(record.packageName)?.packageRoot === record.packageRoot);
|
|
340
|
+
const records = [...selected.values()].map(({ includedForVerification: _includedForVerification, nativeCandidate: _nativeCandidate, ...record }) => record).sort(compareSearchRecords);
|
|
341
|
+
const result = {
|
|
342
|
+
platform: constants_1.Platform,
|
|
343
|
+
modules: records,
|
|
344
|
+
duplicates: findDuplicates(verified),
|
|
345
|
+
missingIncludes: options.include.filter(name => !found.has(name)).sort(values_1.compareText),
|
|
346
|
+
options: {
|
|
347
|
+
projectRoot: options.projectRoot,
|
|
348
|
+
searchPaths: options.searchPaths,
|
|
349
|
+
nativeModulesDir: options.nativeModulesDir,
|
|
350
|
+
exclude: options.exclude,
|
|
351
|
+
include: options.include,
|
|
352
|
+
buildType: options.buildType,
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
(0, values_1.emitLog)(rawOptions.logger, 'debug', 'Harmony module search completed.', { moduleCount: records.length, duplicateCount: result.duplicates.length });
|
|
356
|
+
return result;
|
|
357
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { VerificationResult, VerifyOptions } from '../types';
|
|
2
|
+
declare function verifyModulesAsync(options?: VerifyOptions): Promise<VerificationResult>;
|
|
3
|
+
declare function assertVerificationSucceeded(result: any, stage?: string): void;
|
|
4
|
+
export { assertVerificationSucceeded, verifyModulesAsync, };
|