expo-harmony-toolkit 1.7.2 → 1.8.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.
- package/README.en.md +25 -11
- package/README.md +27 -13
- package/build/core/autolinking.d.ts +10 -0
- package/build/core/autolinking.js +421 -0
- package/build/core/build/commands.d.ts +19 -0
- package/build/core/build/commands.js +61 -0
- package/build/core/build/compatibilityShims.d.ts +1 -0
- package/build/core/build/compatibilityShims.js +272 -0
- package/build/core/build/localHar.d.ts +13 -0
- package/build/core/build/localHar.js +337 -0
- package/build/core/build/reporting.d.ts +19 -0
- package/build/core/build/reporting.js +67 -0
- package/build/core/build/rnohCompatibility.d.ts +1 -0
- package/build/core/build/rnohCompatibility.js +38 -0
- package/build/core/build.d.ts +4 -12
- package/build/core/build.js +70 -762
- package/build/core/constants.d.ts +2 -1
- package/build/core/constants.js +3 -2
- package/build/core/dependencyInspection.d.ts +2 -0
- package/build/core/dependencyInspection.js +130 -0
- package/build/core/env.js +1 -1
- package/build/core/report.js +162 -10
- package/build/core/signing.d.ts +2 -0
- package/build/core/signing.js +30 -0
- package/build/core/template/capabilityRegistry.d.ts +9 -0
- package/build/core/template/capabilityRegistry.js +84 -0
- package/build/core/template/expoModulesCoreShim.d.ts +2 -0
- package/build/core/template/expoModulesCoreShim.js +279 -0
- package/build/core/template/metro.d.ts +2 -0
- package/build/core/template/metro.js +213 -0
- package/build/core/template/nativeFiles.d.ts +8 -0
- package/build/core/template/nativeFiles.js +333 -0
- package/build/core/template/renderers/camera.d.ts +4 -0
- package/build/core/template/renderers/camera.js +612 -0
- package/build/core/template/renderers/fileSystem.d.ts +4 -0
- package/build/core/template/renderers/fileSystem.js +814 -0
- package/build/core/template/renderers/imagePicker.d.ts +4 -0
- package/build/core/template/renderers/imagePicker.js +753 -0
- package/build/core/template/renderers/location.d.ts +4 -0
- package/build/core/template/renderers/location.js +836 -0
- package/build/core/template/runtimeShims.d.ts +2 -0
- package/build/core/template/runtimeShims.js +192 -0
- package/build/core/template/support.d.ts +11 -0
- package/build/core/template/support.js +108 -0
- package/build/core/template.d.ts +3 -6
- package/build/core/template.js +49 -4457
- package/build/data/capabilities.js +21 -4
- package/build/data/dependencyCatalog.js +10 -0
- package/build/data/publicDocs.d.ts +11 -0
- package/build/data/publicDocs.js +28 -0
- package/build/data/validatedMatrices.js +9 -1
- package/build/docs/render.d.ts +9 -0
- package/build/docs/render.js +250 -0
- package/build/types.d.ts +19 -0
- package/docs/cli-build.md +1 -1
- package/docs/npm-release.md +1 -0
- package/docs/official-app-shell-sample.md +2 -1
- package/docs/official-minimal-sample.md +2 -1
- package/docs/official-native-capabilities-sample.md +12 -2
- package/docs/official-ui-stack-sample.md +2 -1
- package/docs/roadmap.md +146 -51
- package/docs/signing-and-release.md +3 -0
- package/docs/support-matrix.md +59 -13
- package/package.json +13 -5
- package/docs/v1.5.1-acceptance.md +0 -385
- package/docs/v1.6.0-acceptance.md +0 -193
- package/docs/v1.7.0-acceptance.md +0 -111
- package/docs/v1.7.1-acceptance.md +0 -111
- package/docs/v1.7.2-acceptance.md +0 -37
|
@@ -0,0 +1,272 @@
|
|
|
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.ensureNormalizedLocalHarCompatibilityShims = ensureNormalizedLocalHarCompatibilityShims;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
async function ensureNormalizedLocalHarCompatibilityShims(directoryPath, packageName) {
|
|
10
|
+
if (packageName === '@react-native-oh-tpl/react-native-gesture-handler') {
|
|
11
|
+
const gestureHandlerPackageHeaderPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'RnohReactNativeHarmonyGestureHandlerPackage.h');
|
|
12
|
+
const gestureHandlerPackagePath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'RnohReactNativeHarmonyGestureHandlerPackage.cpp');
|
|
13
|
+
const gestureHandlerTurboModulePath = path_1.default.join(directoryPath, 'src', 'main', 'ets', 'rnoh', 'RNGestureHandlerModule.ts');
|
|
14
|
+
if (await fs_extra_1.default.pathExists(gestureHandlerTurboModulePath)) {
|
|
15
|
+
const gestureHandlerTurboModuleContents = await fs_extra_1.default.readFile(gestureHandlerTurboModulePath, 'utf8');
|
|
16
|
+
let nextGestureHandlerTurboModuleContents = gestureHandlerTurboModuleContents;
|
|
17
|
+
nextGestureHandlerTurboModuleContents = nextGestureHandlerTurboModuleContents.replace(/^import \{ TM \} from ["']@rnoh\/react-native-openharmony\/generated\/ts["'];?\r?\n/m, '');
|
|
18
|
+
nextGestureHandlerTurboModuleContents = nextGestureHandlerTurboModuleContents.replace(/\s+implements TM\.RNGestureHandlerModule\.Spec/, '');
|
|
19
|
+
if (nextGestureHandlerTurboModuleContents !== gestureHandlerTurboModuleContents) {
|
|
20
|
+
await fs_extra_1.default.writeFile(gestureHandlerTurboModulePath, nextGestureHandlerTurboModuleContents);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const gestureHandlerGeneratedDirectoryPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'generated');
|
|
24
|
+
await fs_extra_1.default.ensureDir(gestureHandlerGeneratedDirectoryPath);
|
|
25
|
+
await fs_extra_1.default.writeFile(path_1.default.join(gestureHandlerGeneratedDirectoryPath, 'RNGestureHandlerButtonComponentDescriptor.h'), createGestureHandlerCompatibilityDescriptorHeader('RNGestureHandlerButton'));
|
|
26
|
+
await fs_extra_1.default.writeFile(path_1.default.join(gestureHandlerGeneratedDirectoryPath, 'RNGestureHandlerRootViewComponentDescriptor.h'), createGestureHandlerCompatibilityDescriptorHeader('RNGestureHandlerRootView'));
|
|
27
|
+
if (await fs_extra_1.default.pathExists(gestureHandlerPackageHeaderPath)) {
|
|
28
|
+
const gestureHandlerPackageHeaderContents = await fs_extra_1.default.readFile(gestureHandlerPackageHeaderPath, 'utf8');
|
|
29
|
+
const nextGestureHandlerPackageHeaderContents = patchGestureHandlerCompatibilityPackageHeader(gestureHandlerPackageHeaderContents);
|
|
30
|
+
if (nextGestureHandlerPackageHeaderContents !== gestureHandlerPackageHeaderContents) {
|
|
31
|
+
await fs_extra_1.default.writeFile(gestureHandlerPackageHeaderPath, nextGestureHandlerPackageHeaderContents);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (!(await fs_extra_1.default.pathExists(gestureHandlerPackagePath))) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const gestureHandlerPackageContents = await fs_extra_1.default.readFile(gestureHandlerPackagePath, 'utf8');
|
|
38
|
+
const nextGestureHandlerPackageContents = patchGestureHandlerCompatibilityPackageSource(gestureHandlerPackageContents);
|
|
39
|
+
if (nextGestureHandlerPackageContents !== gestureHandlerPackageContents) {
|
|
40
|
+
await fs_extra_1.default.writeFile(gestureHandlerPackagePath, nextGestureHandlerPackageContents);
|
|
41
|
+
}
|
|
42
|
+
if (!nextGestureHandlerPackageContents.includes('<react/renderer/debug/SystraceSection.h>')) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const systraceCompatibilityShimPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'react', 'renderer', 'debug', 'SystraceSection.h');
|
|
46
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(systraceCompatibilityShimPath));
|
|
47
|
+
await fs_extra_1.default.writeFile(systraceCompatibilityShimPath, '#pragma once\n#include <cxxreact/SystraceSection.h>\n');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (packageName === '@react-native-oh-tpl/react-native-reanimated') {
|
|
51
|
+
const reanimatedCmakeListsPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'CMakeLists.txt');
|
|
52
|
+
const reanimatedMountHookHeaderPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'Common', 'cpp', 'Fabric', 'ReanimatedMountHook.h');
|
|
53
|
+
const reanimatedMountHookSourcePath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'Common', 'cpp', 'Fabric', 'ReanimatedMountHook.cpp');
|
|
54
|
+
const nativeReanimatedModuleSourcePath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'Common', 'cpp', 'NativeModules', 'NativeReanimatedModule.cpp');
|
|
55
|
+
if (await fs_extra_1.default.pathExists(reanimatedCmakeListsPath)) {
|
|
56
|
+
const reanimatedCmakeListsContents = await fs_extra_1.default.readFile(reanimatedCmakeListsPath, 'utf8');
|
|
57
|
+
if (reanimatedCmakeListsContents.includes('REACT_NATIVE_MINOR_VERSION=72')) {
|
|
58
|
+
await fs_extra_1.default.writeFile(reanimatedCmakeListsPath, reanimatedCmakeListsContents.replace('REACT_NATIVE_MINOR_VERSION=72', 'REACT_NATIVE_MINOR_VERSION=82'));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (await fs_extra_1.default.pathExists(reanimatedMountHookHeaderPath)) {
|
|
62
|
+
const reanimatedMountHookHeaderContents = await fs_extra_1.default.readFile(reanimatedMountHookHeaderPath, 'utf8');
|
|
63
|
+
if (reanimatedMountHookHeaderContents.includes('double mountTime) noexcept override;')) {
|
|
64
|
+
await fs_extra_1.default.writeFile(reanimatedMountHookHeaderPath, reanimatedMountHookHeaderContents.replace('double mountTime) noexcept override;', 'HighResTimeStamp mountTime) noexcept override;'));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (await fs_extra_1.default.pathExists(reanimatedMountHookSourcePath)) {
|
|
68
|
+
const reanimatedMountHookSourceContents = await fs_extra_1.default.readFile(reanimatedMountHookSourcePath, 'utf8');
|
|
69
|
+
if (reanimatedMountHookSourceContents.includes('double) noexcept {')) {
|
|
70
|
+
await fs_extra_1.default.writeFile(reanimatedMountHookSourcePath, reanimatedMountHookSourceContents.replace('double) noexcept {', 'HighResTimeStamp) noexcept {'));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (await fs_extra_1.default.pathExists(nativeReanimatedModuleSourcePath)) {
|
|
74
|
+
const nativeReanimatedModuleSourceContents = await fs_extra_1.default.readFile(nativeReanimatedModuleSourcePath, 'utf8');
|
|
75
|
+
let nextNativeReanimatedModuleSourceContents = nativeReanimatedModuleSourceContents;
|
|
76
|
+
if (nextNativeReanimatedModuleSourceContents.includes('<react/renderer/core/TraitCast.h>')) {
|
|
77
|
+
nextNativeReanimatedModuleSourceContents = nextNativeReanimatedModuleSourceContents.replace('<react/renderer/core/TraitCast.h>', '<react/renderer/core/LayoutableShadowNode.h>');
|
|
78
|
+
}
|
|
79
|
+
if (nextNativeReanimatedModuleSourceContents.includes('#include <react/utils/CoreFeatures.h>')) {
|
|
80
|
+
nextNativeReanimatedModuleSourceContents = nextNativeReanimatedModuleSourceContents.replace('#include <react/utils/CoreFeatures.h>\n', '');
|
|
81
|
+
nextNativeReanimatedModuleSourceContents = nextNativeReanimatedModuleSourceContents.replace('#include <react/utils/CoreFeatures.h>\r\n', '');
|
|
82
|
+
}
|
|
83
|
+
if (nextNativeReanimatedModuleSourceContents.includes('traitCast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get())')) {
|
|
84
|
+
nextNativeReanimatedModuleSourceContents = nextNativeReanimatedModuleSourceContents.replace('traitCast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get())', 'dynamic_cast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get())');
|
|
85
|
+
}
|
|
86
|
+
if (nextNativeReanimatedModuleSourceContents.includes('shadowNodeFromValue(rt, shadowNodeWrapper)')) {
|
|
87
|
+
nextNativeReanimatedModuleSourceContents =
|
|
88
|
+
nextNativeReanimatedModuleSourceContents.replace(/auto (\w+) = shadowNodeFromValue\(rt, shadowNodeWrapper\);/g, 'auto $1 = Bridging<std::shared_ptr<const ShadowNode>>::fromJs(rt, shadowNodeWrapper);');
|
|
89
|
+
}
|
|
90
|
+
if (nextNativeReanimatedModuleSourceContents.includes('shadowNodeFromValue(rt, shadowNodeValue)')) {
|
|
91
|
+
nextNativeReanimatedModuleSourceContents =
|
|
92
|
+
nextNativeReanimatedModuleSourceContents.replace(/(ShadowNode::Shared|auto) (\w+) = shadowNodeFromValue\(rt, shadowNodeValue\);/g, 'auto $2 = Bridging<std::shared_ptr<const ShadowNode>>::fromJs(rt, shadowNodeValue);');
|
|
93
|
+
}
|
|
94
|
+
if (nextNativeReanimatedModuleSourceContents.includes('bool CoreFeatures::useNativeState;')) {
|
|
95
|
+
nextNativeReanimatedModuleSourceContents = nextNativeReanimatedModuleSourceContents.replace(/#if REACT_NATIVE_MINOR_VERSION >= 73 && defined\(RCT_NEW_ARCH_ENABLED\)\r?\n\/\/ Android can't find the definition of this static field\r?\nbool CoreFeatures::useNativeState;\r?\n#endif\r?\n/m, '');
|
|
96
|
+
}
|
|
97
|
+
if (nextNativeReanimatedModuleSourceContents.includes('/* .shouldYield = */ [this]() {')) {
|
|
98
|
+
nextNativeReanimatedModuleSourceContents =
|
|
99
|
+
nextNativeReanimatedModuleSourceContents.replace(/#if REACT_NATIVE_MINOR_VERSION >= 72\r?\n\s*\/\* \.mountSynchronously = \*\/ true,\r?\n#endif\r?\n\s*\/\* \.shouldYield = \*\/ \[this\]\(\) \{\r?\n\s*return propsRegistry_->shouldReanimatedSkipCommit\(\);\r?\n\s*\}/m, '#if REACT_NATIVE_MINOR_VERSION >= 72\n'
|
|
100
|
+
+ ' /* .mountSynchronously = */ true,\n'
|
|
101
|
+
+ '#endif\n'
|
|
102
|
+
+ ' /* .source = */ ShadowTree::CommitSource::Unknown');
|
|
103
|
+
}
|
|
104
|
+
if (nextNativeReanimatedModuleSourceContents !== nativeReanimatedModuleSourceContents) {
|
|
105
|
+
await fs_extra_1.default.writeFile(nativeReanimatedModuleSourcePath, nextNativeReanimatedModuleSourceContents);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (packageName !== '@react-native-oh-tpl/react-native-svg') {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const svgGeneratedPropsPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'generated', 'react', 'renderer', 'components', 'react_native_svg', 'Props.h');
|
|
114
|
+
const svgPathComponentInstancePath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'componentInstances', 'RNSVGPathComponentInstance.h');
|
|
115
|
+
const svgImageComponentDescriptorPath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'svgImage', 'RNSVGImageComponentDescriptor.h');
|
|
116
|
+
const svgImageShadowNodePath = path_1.default.join(directoryPath, 'src', 'main', 'cpp', 'svgImage', 'RNSVGImageShadowNode.h');
|
|
117
|
+
if (await fs_extra_1.default.pathExists(svgGeneratedPropsPath)) {
|
|
118
|
+
const svgGeneratedPropsContents = await fs_extra_1.default.readFile(svgGeneratedPropsPath, 'utf8');
|
|
119
|
+
if (svgGeneratedPropsContents.includes('butter::map<std::string, RawValue>')) {
|
|
120
|
+
await fs_extra_1.default.writeFile(svgGeneratedPropsPath, svgGeneratedPropsContents.replace(/butter::map<std::string, RawValue>/g, 'std::unordered_map<std::string, RawValue>'));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (await fs_extra_1.default.pathExists(svgImageComponentDescriptorPath)) {
|
|
124
|
+
const svgImageComponentDescriptorContents = await fs_extra_1.default.readFile(svgImageComponentDescriptorPath, 'utf8');
|
|
125
|
+
let nextSvgImageComponentDescriptorContents = svgImageComponentDescriptorContents;
|
|
126
|
+
if (nextSvgImageComponentDescriptorContents.includes('void adopt(ShadowNode::Unshared const &shadowNode) const override {')) {
|
|
127
|
+
nextSvgImageComponentDescriptorContents =
|
|
128
|
+
nextSvgImageComponentDescriptorContents.replace('void adopt(ShadowNode::Unshared const &shadowNode) const override {', 'void adopt(ShadowNode& shadowNode) const override {');
|
|
129
|
+
}
|
|
130
|
+
if (nextSvgImageComponentDescriptorContents.includes('auto imageShadowNode = std::static_pointer_cast<RNSVGImageShadowNode>(shadowNode);')) {
|
|
131
|
+
nextSvgImageComponentDescriptorContents =
|
|
132
|
+
nextSvgImageComponentDescriptorContents.replace('auto imageShadowNode = std::static_pointer_cast<RNSVGImageShadowNode>(shadowNode);', 'auto& imageShadowNode = static_cast<RNSVGImageShadowNode&>(shadowNode);');
|
|
133
|
+
}
|
|
134
|
+
if (nextSvgImageComponentDescriptorContents.includes('imageShadowNode->setImageManager(imageManager_);')) {
|
|
135
|
+
nextSvgImageComponentDescriptorContents =
|
|
136
|
+
nextSvgImageComponentDescriptorContents.replace('imageShadowNode->setImageManager(imageManager_);', 'imageShadowNode.setImageManager(imageManager_);');
|
|
137
|
+
}
|
|
138
|
+
if (nextSvgImageComponentDescriptorContents !== svgImageComponentDescriptorContents) {
|
|
139
|
+
await fs_extra_1.default.writeFile(svgImageComponentDescriptorPath, nextSvgImageComponentDescriptorContents);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (await fs_extra_1.default.pathExists(svgImageShadowNodePath)) {
|
|
143
|
+
const svgImageShadowNodeContents = await fs_extra_1.default.readFile(svgImageShadowNodePath, 'utf8');
|
|
144
|
+
let nextSvgImageShadowNodeContents = svgImageShadowNodeContents;
|
|
145
|
+
const svgImageShadowNodeNewline = svgImageShadowNodeContents.includes('\r\n') ? '\r\n' : '\n';
|
|
146
|
+
if (!nextSvgImageShadowNodeContents.includes('#include <react/renderer/core/ShadowNodeFamily.h>')
|
|
147
|
+
&& nextSvgImageShadowNodeContents.includes('#include <react/renderer/components/view/ConcreteViewShadowNode.h>')) {
|
|
148
|
+
nextSvgImageShadowNodeContents = nextSvgImageShadowNodeContents.replace('#include <react/renderer/components/view/ConcreteViewShadowNode.h>', '#include <react/renderer/components/view/ConcreteViewShadowNode.h>'
|
|
149
|
+
+ `${svgImageShadowNodeNewline}#include <react/renderer/core/ShadowNodeFamily.h>`);
|
|
150
|
+
}
|
|
151
|
+
const svgImageInitialStateSignaturePattern = /static RNSVGImageState initialStateData\(ShadowNodeFragment const &fragment,\r?\n\s*ShadowNodeFamilyFragment const &familyFragment,\r?\n\s*ComponentDescriptor const &componentDescriptor\) \{/m;
|
|
152
|
+
if (svgImageInitialStateSignaturePattern.test(nextSvgImageShadowNodeContents)) {
|
|
153
|
+
nextSvgImageShadowNodeContents = nextSvgImageShadowNodeContents.replace(svgImageInitialStateSignaturePattern, 'static RNSVGImageState initialStateData(const Props::Shared& /*props*/,'
|
|
154
|
+
+ `${svgImageShadowNodeNewline}`
|
|
155
|
+
+ ' const ShadowNodeFamily::Shared& /*family*/,'
|
|
156
|
+
+ `${svgImageShadowNodeNewline}`
|
|
157
|
+
+ ' const ComponentDescriptor& /*componentDescriptor*/) {');
|
|
158
|
+
}
|
|
159
|
+
if (nextSvgImageShadowNodeContents !== svgImageShadowNodeContents) {
|
|
160
|
+
await fs_extra_1.default.writeFile(svgImageShadowNodePath, nextSvgImageShadowNodeContents);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (!(await fs_extra_1.default.pathExists(svgPathComponentInstancePath))) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const svgPathComponentInstanceContents = await fs_extra_1.default.readFile(svgPathComponentInstancePath, 'utf8');
|
|
167
|
+
if (!svgPathComponentInstanceContents.includes('Float m_cacheScale;')) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
await fs_extra_1.default.writeFile(svgPathComponentInstancePath, svgPathComponentInstanceContents.replace('Float m_cacheScale;', 'facebook::react::Float m_cacheScale;'));
|
|
171
|
+
}
|
|
172
|
+
function createGestureHandlerCompatibilityDescriptorHeader(componentName) {
|
|
173
|
+
return [
|
|
174
|
+
'#pragma once',
|
|
175
|
+
'',
|
|
176
|
+
'#include <react/renderer/components/view/ConcreteViewShadowNode.h>',
|
|
177
|
+
'#include <react/renderer/core/ConcreteComponentDescriptor.h>',
|
|
178
|
+
'',
|
|
179
|
+
'namespace facebook::react {',
|
|
180
|
+
'',
|
|
181
|
+
`inline constexpr char ${componentName}ComponentName[] = "${componentName}";`,
|
|
182
|
+
'',
|
|
183
|
+
`using ${componentName}ShadowNode = ConcreteViewShadowNode<${componentName}ComponentName>;`,
|
|
184
|
+
`using ${componentName}ComponentDescriptor = ConcreteComponentDescriptor<${componentName}ShadowNode>;`,
|
|
185
|
+
'',
|
|
186
|
+
'} // namespace facebook::react',
|
|
187
|
+
'',
|
|
188
|
+
].join('\n');
|
|
189
|
+
}
|
|
190
|
+
function patchGestureHandlerCompatibilityPackageHeader(contents) {
|
|
191
|
+
if (contents.includes('createComponentDescriptorProviders() override;')) {
|
|
192
|
+
return contents;
|
|
193
|
+
}
|
|
194
|
+
return contents.replace(' std::vector<ArkTSMessageHandler::Shared> createArkTSMessageHandlers() override;\n', [
|
|
195
|
+
' std::vector<facebook::react::ComponentDescriptorProvider> createComponentDescriptorProviders() override;',
|
|
196
|
+
'',
|
|
197
|
+
' ComponentJSIBinderByString createComponentJSIBinderByName() override;',
|
|
198
|
+
'',
|
|
199
|
+
' std::vector<ArkTSMessageHandler::Shared> createArkTSMessageHandlers() override;',
|
|
200
|
+
].join('\n'));
|
|
201
|
+
}
|
|
202
|
+
function patchGestureHandlerCompatibilityPackageSource(contents) {
|
|
203
|
+
let nextContents = contents;
|
|
204
|
+
if (!nextContents.includes('#include "RNOHCorePackage/ComponentBinders/ViewComponentJSIBinder.h"')) {
|
|
205
|
+
nextContents = nextContents.replace('#include "RNOH/RNInstanceCAPI.h"\n', '#include "RNOH/RNInstanceCAPI.h"\n#include "RNOHCorePackage/ComponentBinders/ViewComponentJSIBinder.h"\n');
|
|
206
|
+
}
|
|
207
|
+
if (!nextContents.includes('#include "generated/RNGestureHandlerButtonComponentDescriptor.h"')) {
|
|
208
|
+
nextContents = nextContents.replace('#include "componentInstances/RNGestureHandlerRootViewComponentInstance.h"\n', '#include "componentInstances/RNGestureHandlerRootViewComponentInstance.h"\n#include "generated/RNGestureHandlerButtonComponentDescriptor.h"\n#include "generated/RNGestureHandlerRootViewComponentDescriptor.h"\n');
|
|
209
|
+
}
|
|
210
|
+
if (!nextContents.includes('class RNGestureHandlerComponentJSIBinder')) {
|
|
211
|
+
nextContents = nextContents.replace('using namespace rnoh;\nusing namespace facebook;\n\n', [
|
|
212
|
+
'using namespace rnoh;',
|
|
213
|
+
'using namespace facebook;',
|
|
214
|
+
'',
|
|
215
|
+
'class RNGestureHandlerComponentJSIBinder : public ViewComponentJSIBinder {',
|
|
216
|
+
'protected:',
|
|
217
|
+
' facebook::jsi::Object createNativeProps(facebook::jsi::Runtime &rt) override {',
|
|
218
|
+
' auto nativeProps = ViewComponentJSIBinder::createNativeProps(rt);',
|
|
219
|
+
' nativeProps.setProperty(rt, "exclusive", "boolean");',
|
|
220
|
+
' nativeProps.setProperty(rt, "foreground", "boolean");',
|
|
221
|
+
' nativeProps.setProperty(rt, "borderless", "boolean");',
|
|
222
|
+
' nativeProps.setProperty(rt, "enabled", "boolean");',
|
|
223
|
+
' nativeProps.setProperty(rt, "rippleColor", "Color");',
|
|
224
|
+
' nativeProps.setProperty(rt, "rippleRadius", "number");',
|
|
225
|
+
' nativeProps.setProperty(rt, "touchSoundDisabled", "boolean");',
|
|
226
|
+
' return nativeProps;',
|
|
227
|
+
' }',
|
|
228
|
+
'',
|
|
229
|
+
' facebook::jsi::Object createDirectEventTypes(facebook::jsi::Runtime &rt) override {',
|
|
230
|
+
' auto events = ViewComponentJSIBinder::createDirectEventTypes(rt);',
|
|
231
|
+
' events.setProperty(rt, "onGestureHandlerEvent", createDirectEvent(rt, "onGestureHandlerEvent"));',
|
|
232
|
+
' events.setProperty(',
|
|
233
|
+
' rt,',
|
|
234
|
+
' "onGestureHandlerStateChange",',
|
|
235
|
+
' createDirectEvent(rt, "onGestureHandlerStateChange"));',
|
|
236
|
+
' events.setProperty(rt, "topOnGestureHandlerEvent", createDirectEvent(rt, "onGestureHandlerEvent"));',
|
|
237
|
+
' events.setProperty(',
|
|
238
|
+
' rt,',
|
|
239
|
+
' "topOnGestureHandlerStateChange",',
|
|
240
|
+
' createDirectEvent(rt, "onGestureHandlerStateChange"));',
|
|
241
|
+
' return events;',
|
|
242
|
+
' }',
|
|
243
|
+
'};',
|
|
244
|
+
'',
|
|
245
|
+
].join('\n'));
|
|
246
|
+
}
|
|
247
|
+
if (!nextContents.includes('RnohReactNativeHarmonyGestureHandlerPackage::createComponentDescriptorProviders()')) {
|
|
248
|
+
nextContents = nextContents.replace('EventEmitRequestHandlers RnohReactNativeHarmonyGestureHandlerPackage::createEventEmitRequestHandlers() {\n', [
|
|
249
|
+
'std::vector<facebook::react::ComponentDescriptorProvider>',
|
|
250
|
+
'RnohReactNativeHarmonyGestureHandlerPackage::createComponentDescriptorProviders() {',
|
|
251
|
+
' return {',
|
|
252
|
+
' facebook::react::concreteComponentDescriptorProvider<',
|
|
253
|
+
' facebook::react::RNGestureHandlerButtonComponentDescriptor>(),',
|
|
254
|
+
' facebook::react::concreteComponentDescriptorProvider<',
|
|
255
|
+
' facebook::react::RNGestureHandlerRootViewComponentDescriptor>(),',
|
|
256
|
+
' };',
|
|
257
|
+
'}',
|
|
258
|
+
'',
|
|
259
|
+
'ComponentJSIBinderByString',
|
|
260
|
+
'RnohReactNativeHarmonyGestureHandlerPackage::createComponentJSIBinderByName() {',
|
|
261
|
+
' auto componentJSIBinder = std::make_shared<RNGestureHandlerComponentJSIBinder>();',
|
|
262
|
+
' return {',
|
|
263
|
+
' {"RNGestureHandlerButton", componentJSIBinder},',
|
|
264
|
+
' {"RNGestureHandlerRootView", componentJSIBinder},',
|
|
265
|
+
' };',
|
|
266
|
+
'}',
|
|
267
|
+
'',
|
|
268
|
+
'EventEmitRequestHandlers RnohReactNativeHarmonyGestureHandlerPackage::createEventEmitRequestHandlers() {',
|
|
269
|
+
].join('\n'));
|
|
270
|
+
}
|
|
271
|
+
return nextContents;
|
|
272
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface NormalizedLocalHarPackage {
|
|
2
|
+
packageName: string;
|
|
3
|
+
moduleName: string;
|
|
4
|
+
directoryPath: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function normalizeLocalHarDependencies(harmonyProjectRoot: string): Promise<{
|
|
7
|
+
restore: () => Promise<void>;
|
|
8
|
+
packages: NormalizedLocalHarPackage[];
|
|
9
|
+
}>;
|
|
10
|
+
export declare function ensureHarmonyBuildProfileSupportsNormalizedLocalDeps(harmonyProjectRoot: string, localHarPackages: NormalizedLocalHarPackage[]): Promise<() => Promise<void>>;
|
|
11
|
+
export declare function ensureRnohGeneratedTsShim(harmonyProjectRoot: string): Promise<void>;
|
|
12
|
+
export declare function alignRnohCodegenWithNormalizedLocalPackage(harmonyProjectRoot: string, localHarPackages: NormalizedLocalHarPackage[]): Promise<() => Promise<void>>;
|
|
13
|
+
export declare function findHarmonyArtifacts(harmonyProjectRoot: string): Promise<string[]>;
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.normalizeLocalHarDependencies = normalizeLocalHarDependencies;
|
|
7
|
+
exports.ensureHarmonyBuildProfileSupportsNormalizedLocalDeps = ensureHarmonyBuildProfileSupportsNormalizedLocalDeps;
|
|
8
|
+
exports.ensureRnohGeneratedTsShim = ensureRnohGeneratedTsShim;
|
|
9
|
+
exports.alignRnohCodegenWithNormalizedLocalPackage = alignRnohCodegenWithNormalizedLocalPackage;
|
|
10
|
+
exports.findHarmonyArtifacts = findHarmonyArtifacts;
|
|
11
|
+
const node_child_process_1 = require("node:child_process");
|
|
12
|
+
const json5_1 = __importDefault(require("json5"));
|
|
13
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
14
|
+
const os_1 = __importDefault(require("os"));
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const node_util_1 = require("node:util");
|
|
17
|
+
const compatibilityShims_1 = require("./compatibilityShims");
|
|
18
|
+
const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
19
|
+
const RNOH_GENERATED_TS_SHIM_RELATIVE_PATH = path_1.default.join('oh_modules', '@rnoh', 'react-native-openharmony', 'ts.ts');
|
|
20
|
+
const RNOH_GENERATED_MODULE_ROOT_RELATIVE_PATH = path_1.default.join('oh_modules', '@rnoh', 'react-native-openharmony');
|
|
21
|
+
const RNOH_NORMALIZED_TS_TARGET_RELATIVE_PATH = path_1.default.join('expo-harmony-local-deps', 'rnoh-react-native-openharmony-react_native_openharmony', 'ts.ts');
|
|
22
|
+
async function normalizeLocalHarDependencies(harmonyProjectRoot) {
|
|
23
|
+
const packagePaths = [
|
|
24
|
+
path_1.default.join(harmonyProjectRoot, 'oh-package.json5'),
|
|
25
|
+
path_1.default.join(harmonyProjectRoot, 'entry', 'oh-package.json5'),
|
|
26
|
+
];
|
|
27
|
+
const extractionRoot = path_1.default.join(harmonyProjectRoot, 'expo-harmony-local-deps');
|
|
28
|
+
const archiveCache = new Map();
|
|
29
|
+
const originalContents = new Map();
|
|
30
|
+
const packagesByDirectoryPath = new Map();
|
|
31
|
+
await fs_extra_1.default.ensureDir(extractionRoot);
|
|
32
|
+
for (const packagePath of packagePaths) {
|
|
33
|
+
if (!(await fs_extra_1.default.pathExists(packagePath))) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const rawContents = await fs_extra_1.default.readFile(packagePath, 'utf8');
|
|
37
|
+
const parsed = json5_1.default.parse(rawContents);
|
|
38
|
+
let didChange = false;
|
|
39
|
+
for (const sectionName of ['dependencies', 'devDependencies', 'overrides']) {
|
|
40
|
+
const section = parsed[sectionName];
|
|
41
|
+
if (!section || typeof section !== 'object' || Array.isArray(section)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
for (const [packageName, specifier] of Object.entries(section)) {
|
|
45
|
+
if (typeof specifier !== 'string' || !specifier.startsWith('file:') || !specifier.endsWith('.har')) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const archivePath = path_1.default.resolve(harmonyProjectRoot, specifier.slice('file:'.length));
|
|
49
|
+
const normalizedDirectory = archiveCache.get(archivePath) ??
|
|
50
|
+
(await extractHarArchiveToDirectory(archivePath, extractionRoot, packageName));
|
|
51
|
+
archiveCache.set(archivePath, normalizedDirectory);
|
|
52
|
+
if (!packagesByDirectoryPath.has(normalizedDirectory)) {
|
|
53
|
+
packagesByDirectoryPath.set(normalizedDirectory, await readNormalizedLocalHarPackageMetadata(normalizedDirectory, packageName));
|
|
54
|
+
}
|
|
55
|
+
let relativeDirectory = path_1.default.relative(harmonyProjectRoot, normalizedDirectory);
|
|
56
|
+
if (!relativeDirectory.startsWith('.')) {
|
|
57
|
+
relativeDirectory = `./${relativeDirectory}`;
|
|
58
|
+
}
|
|
59
|
+
const nextSpecifier = `file:${relativeDirectory.split(path_1.default.sep).join('/')}`;
|
|
60
|
+
if (nextSpecifier !== specifier) {
|
|
61
|
+
section[packageName] = nextSpecifier;
|
|
62
|
+
didChange = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (didChange) {
|
|
67
|
+
originalContents.set(packagePath, rawContents);
|
|
68
|
+
await fs_extra_1.default.writeFile(packagePath, JSON.stringify(parsed, null, 2) + '\n');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
packages: [...packagesByDirectoryPath.values()],
|
|
73
|
+
restore: async () => {
|
|
74
|
+
for (const [packagePath, rawContents] of originalContents) {
|
|
75
|
+
await fs_extra_1.default.writeFile(packagePath, rawContents);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async function extractHarArchiveToDirectory(archivePath, extractionRoot, packageName) {
|
|
81
|
+
if (!(await fs_extra_1.default.pathExists(archivePath))) {
|
|
82
|
+
throw new Error(`Local Harmony archive not found: ${archivePath}`);
|
|
83
|
+
}
|
|
84
|
+
const destinationPath = path_1.default.join(extractionRoot, `${sanitizePackageName(packageName)}-${path_1.default.basename(archivePath, path_1.default.extname(archivePath))}`);
|
|
85
|
+
const stagingRoot = await fs_extra_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'expo-harmony-har-'));
|
|
86
|
+
try {
|
|
87
|
+
await execFileAsync('tar', ['-xzf', archivePath, '-C', stagingRoot], {
|
|
88
|
+
maxBuffer: 20 * 1024 * 1024,
|
|
89
|
+
});
|
|
90
|
+
const packagedRoot = path_1.default.join(stagingRoot, 'package');
|
|
91
|
+
const sourceRoot = (await fs_extra_1.default.pathExists(path_1.default.join(packagedRoot, 'oh-package.json5')))
|
|
92
|
+
? packagedRoot
|
|
93
|
+
: stagingRoot;
|
|
94
|
+
if (!(await fs_extra_1.default.pathExists(path_1.default.join(sourceRoot, 'oh-package.json5')))) {
|
|
95
|
+
throw new Error(`oh-package.json5 not found after extracting ${archivePath}`);
|
|
96
|
+
}
|
|
97
|
+
await fs_extra_1.default.remove(destinationPath);
|
|
98
|
+
await fs_extra_1.default.ensureDir(destinationPath);
|
|
99
|
+
for (const entryName of await fs_extra_1.default.readdir(sourceRoot)) {
|
|
100
|
+
await fs_extra_1.default.move(path_1.default.join(sourceRoot, entryName), path_1.default.join(destinationPath, entryName), {
|
|
101
|
+
overwrite: true,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
await (0, compatibilityShims_1.ensureNormalizedLocalHarCompatibilityShims)(destinationPath, packageName);
|
|
105
|
+
return destinationPath;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
109
|
+
throw new Error(`Failed to normalize local Harmony archive ${archivePath}: ${message}`);
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
await fs_extra_1.default.remove(stagingRoot);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function sanitizePackageName(packageName) {
|
|
116
|
+
return packageName.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
117
|
+
}
|
|
118
|
+
async function readNormalizedLocalHarPackageMetadata(directoryPath, packageName) {
|
|
119
|
+
await ensureNormalizedLocalHarModuleJson5(directoryPath);
|
|
120
|
+
const moduleJsonPaths = [
|
|
121
|
+
path_1.default.join(directoryPath, 'src', 'main', 'module.json5'),
|
|
122
|
+
path_1.default.join(directoryPath, 'src', 'main', 'module.json'),
|
|
123
|
+
];
|
|
124
|
+
let moduleName = sanitizePackageName(packageName);
|
|
125
|
+
for (const moduleJsonPath of moduleJsonPaths) {
|
|
126
|
+
if (!(await fs_extra_1.default.pathExists(moduleJsonPath))) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const parsed = json5_1.default.parse(await fs_extra_1.default.readFile(moduleJsonPath, 'utf8'));
|
|
131
|
+
if (typeof parsed?.module?.name === 'string' && parsed.module.name.trim().length > 0) {
|
|
132
|
+
moduleName = parsed.module.name.trim();
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// Ignore malformed module metadata and fall back to a sanitized package name.
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
packageName,
|
|
142
|
+
moduleName,
|
|
143
|
+
directoryPath,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async function ensureNormalizedLocalHarModuleJson5(directoryPath) {
|
|
147
|
+
const moduleJson5Path = path_1.default.join(directoryPath, 'src', 'main', 'module.json5');
|
|
148
|
+
const moduleJsonPath = path_1.default.join(directoryPath, 'src', 'main', 'module.json');
|
|
149
|
+
const sourcePath = (await fs_extra_1.default.pathExists(moduleJsonPath))
|
|
150
|
+
? moduleJsonPath
|
|
151
|
+
: ((await fs_extra_1.default.pathExists(moduleJson5Path)) ? moduleJson5Path : null);
|
|
152
|
+
if (!sourcePath) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const parsed = json5_1.default.parse(await fs_extra_1.default.readFile(sourcePath, 'utf8'));
|
|
156
|
+
const legacyModule = parsed.module && typeof parsed.module === 'object' && !Array.isArray(parsed.module)
|
|
157
|
+
? parsed.module
|
|
158
|
+
: {};
|
|
159
|
+
const normalizedModule = {
|
|
160
|
+
name: typeof legacyModule.name === 'string' && legacyModule.name.trim().length > 0
|
|
161
|
+
? legacyModule.name.trim()
|
|
162
|
+
: path_1.default.basename(directoryPath).replace(/[^a-zA-Z0-9]+/g, '_'),
|
|
163
|
+
type: typeof legacyModule.type === 'string' ? legacyModule.type : 'har',
|
|
164
|
+
deviceTypes: Array.isArray(legacyModule.deviceTypes) && legacyModule.deviceTypes.length > 0
|
|
165
|
+
? legacyModule.deviceTypes
|
|
166
|
+
: ['default'],
|
|
167
|
+
installationFree: typeof legacyModule.installationFree === 'boolean' ? legacyModule.installationFree : false,
|
|
168
|
+
};
|
|
169
|
+
const passthroughKeys = [
|
|
170
|
+
'srcEntrance',
|
|
171
|
+
'srcEntry',
|
|
172
|
+
'description',
|
|
173
|
+
'process',
|
|
174
|
+
'mainElement',
|
|
175
|
+
'uiSyntax',
|
|
176
|
+
'metadata',
|
|
177
|
+
'abilities',
|
|
178
|
+
'extensionAbilities',
|
|
179
|
+
'requestPermissions',
|
|
180
|
+
'definePermissions',
|
|
181
|
+
'testRunner',
|
|
182
|
+
'dependencies',
|
|
183
|
+
'libIsolation',
|
|
184
|
+
'routerMap',
|
|
185
|
+
'appStartup',
|
|
186
|
+
'crossAppSharedConfig',
|
|
187
|
+
];
|
|
188
|
+
for (const key of passthroughKeys) {
|
|
189
|
+
const value = legacyModule[key];
|
|
190
|
+
if (value !== undefined) {
|
|
191
|
+
normalizedModule[key] = value;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (typeof legacyModule.virtualMachine === 'string') {
|
|
195
|
+
normalizedModule.virtualMachine = legacyModule.virtualMachine.includes('ark') ? 'ark' : 'default';
|
|
196
|
+
}
|
|
197
|
+
await fs_extra_1.default.writeFile(moduleJson5Path, JSON.stringify({
|
|
198
|
+
module: normalizedModule,
|
|
199
|
+
}, null, 2) + '\n');
|
|
200
|
+
}
|
|
201
|
+
async function ensureHarmonyBuildProfileSupportsNormalizedLocalDeps(harmonyProjectRoot, localHarPackages) {
|
|
202
|
+
if (localHarPackages.length === 0) {
|
|
203
|
+
return async () => { };
|
|
204
|
+
}
|
|
205
|
+
const buildProfilePath = path_1.default.join(harmonyProjectRoot, 'build-profile.json5');
|
|
206
|
+
if (!(await fs_extra_1.default.pathExists(buildProfilePath))) {
|
|
207
|
+
return async () => { };
|
|
208
|
+
}
|
|
209
|
+
const rawContents = await fs_extra_1.default.readFile(buildProfilePath, 'utf8');
|
|
210
|
+
const parsed = json5_1.default.parse(rawContents);
|
|
211
|
+
let didChange = false;
|
|
212
|
+
const products = Array.isArray(parsed.app?.products) ? parsed.app.products : [];
|
|
213
|
+
for (const product of products) {
|
|
214
|
+
let buildOption = product.buildOption;
|
|
215
|
+
if (!buildOption || typeof buildOption !== 'object' || Array.isArray(buildOption)) {
|
|
216
|
+
buildOption = {};
|
|
217
|
+
product.buildOption = buildOption;
|
|
218
|
+
didChange = true;
|
|
219
|
+
}
|
|
220
|
+
let strictMode = buildOption.strictMode;
|
|
221
|
+
if (!strictMode || typeof strictMode !== 'object' || Array.isArray(strictMode)) {
|
|
222
|
+
strictMode = {};
|
|
223
|
+
buildOption.strictMode = strictMode;
|
|
224
|
+
didChange = true;
|
|
225
|
+
}
|
|
226
|
+
if (strictMode.useNormalizedOHMUrl !== true) {
|
|
227
|
+
strictMode.useNormalizedOHMUrl = true;
|
|
228
|
+
didChange = true;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (!Array.isArray(parsed.modules)) {
|
|
232
|
+
parsed.modules = [];
|
|
233
|
+
didChange = true;
|
|
234
|
+
}
|
|
235
|
+
for (const localHarPackage of localHarPackages) {
|
|
236
|
+
let relativeDirectory = path_1.default.relative(harmonyProjectRoot, localHarPackage.directoryPath);
|
|
237
|
+
relativeDirectory = relativeDirectory.split(path_1.default.sep).join('/');
|
|
238
|
+
if (!relativeDirectory.startsWith('.')) {
|
|
239
|
+
relativeDirectory = `./${relativeDirectory}`;
|
|
240
|
+
}
|
|
241
|
+
const existingModule = parsed.modules.find((moduleEntry) => {
|
|
242
|
+
return (moduleEntry?.srcPath === relativeDirectory ||
|
|
243
|
+
moduleEntry?.name === localHarPackage.moduleName);
|
|
244
|
+
});
|
|
245
|
+
if (existingModule) {
|
|
246
|
+
if (existingModule.srcPath !== relativeDirectory) {
|
|
247
|
+
existingModule.srcPath = relativeDirectory;
|
|
248
|
+
didChange = true;
|
|
249
|
+
}
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
parsed.modules.push({
|
|
253
|
+
name: localHarPackage.moduleName,
|
|
254
|
+
srcPath: relativeDirectory,
|
|
255
|
+
});
|
|
256
|
+
didChange = true;
|
|
257
|
+
}
|
|
258
|
+
if (!didChange) {
|
|
259
|
+
return async () => { };
|
|
260
|
+
}
|
|
261
|
+
await fs_extra_1.default.writeFile(buildProfilePath, JSON.stringify(parsed, null, 2) + '\n');
|
|
262
|
+
return async () => {
|
|
263
|
+
await fs_extra_1.default.writeFile(buildProfilePath, rawContents);
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
async function ensureRnohGeneratedTsShim(harmonyProjectRoot) {
|
|
267
|
+
const shimPath = path_1.default.join(harmonyProjectRoot, RNOH_GENERATED_TS_SHIM_RELATIVE_PATH);
|
|
268
|
+
let relativeTarget = path_1.default.relative(path_1.default.dirname(shimPath), path_1.default.join(harmonyProjectRoot, RNOH_NORMALIZED_TS_TARGET_RELATIVE_PATH));
|
|
269
|
+
relativeTarget = relativeTarget.replace(/\\/g, '/').replace(/\.ts$/, '');
|
|
270
|
+
if (!relativeTarget.startsWith('.')) {
|
|
271
|
+
relativeTarget = `./${relativeTarget}`;
|
|
272
|
+
}
|
|
273
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(shimPath));
|
|
274
|
+
await fs_extra_1.default.writeFile(shimPath, `export * from '${relativeTarget}';\n`);
|
|
275
|
+
}
|
|
276
|
+
async function alignRnohCodegenWithNormalizedLocalPackage(harmonyProjectRoot, localHarPackages) {
|
|
277
|
+
const rnohPackage = localHarPackages.find((localPackage) => localPackage.packageName === '@rnoh/react-native-openharmony');
|
|
278
|
+
if (!rnohPackage) {
|
|
279
|
+
return async () => { };
|
|
280
|
+
}
|
|
281
|
+
const hvigorFilePath = path_1.default.join(harmonyProjectRoot, 'entry', 'hvigorfile.ts');
|
|
282
|
+
if (!(await fs_extra_1.default.pathExists(hvigorFilePath))) {
|
|
283
|
+
return async () => { };
|
|
284
|
+
}
|
|
285
|
+
const originalHvigorFile = await fs_extra_1.default.readFile(hvigorFilePath, 'utf8');
|
|
286
|
+
let relativeRnohModulePath = path_1.default.relative(harmonyProjectRoot, rnohPackage.directoryPath);
|
|
287
|
+
relativeRnohModulePath = relativeRnohModulePath.split(path_1.default.sep).join('/');
|
|
288
|
+
if (!relativeRnohModulePath.startsWith('.')) {
|
|
289
|
+
relativeRnohModulePath = `./${relativeRnohModulePath}`;
|
|
290
|
+
}
|
|
291
|
+
const updatedHvigorFile = originalHvigorFile.replace(/rnohModulePath:\s*['"][^'"]+['"]/, `rnohModulePath: '${relativeRnohModulePath}'`);
|
|
292
|
+
if (updatedHvigorFile !== originalHvigorFile) {
|
|
293
|
+
await fs_extra_1.default.writeFile(hvigorFilePath, updatedHvigorFile);
|
|
294
|
+
}
|
|
295
|
+
const generatedModuleRootPath = path_1.default.join(harmonyProjectRoot, RNOH_GENERATED_MODULE_ROOT_RELATIVE_PATH);
|
|
296
|
+
const backupRootPath = await fs_extra_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'expo-harmony-rnoh-module-'));
|
|
297
|
+
const backupModuleRootPath = path_1.default.join(backupRootPath, 'react-native-openharmony');
|
|
298
|
+
let movedGeneratedModuleRoot = false;
|
|
299
|
+
if (await fs_extra_1.default.pathExists(generatedModuleRootPath)) {
|
|
300
|
+
await fs_extra_1.default.move(generatedModuleRootPath, backupModuleRootPath, { overwrite: true });
|
|
301
|
+
movedGeneratedModuleRoot = true;
|
|
302
|
+
}
|
|
303
|
+
return async () => {
|
|
304
|
+
if (updatedHvigorFile !== originalHvigorFile) {
|
|
305
|
+
await fs_extra_1.default.writeFile(hvigorFilePath, originalHvigorFile);
|
|
306
|
+
}
|
|
307
|
+
if (movedGeneratedModuleRoot) {
|
|
308
|
+
await fs_extra_1.default.remove(generatedModuleRootPath);
|
|
309
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(generatedModuleRootPath));
|
|
310
|
+
await fs_extra_1.default.move(backupModuleRootPath, generatedModuleRootPath, { overwrite: true });
|
|
311
|
+
}
|
|
312
|
+
await fs_extra_1.default.remove(backupRootPath);
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
async function findHarmonyArtifacts(harmonyProjectRoot) {
|
|
316
|
+
const discoveredPaths = [];
|
|
317
|
+
await walkDirectory(harmonyProjectRoot, async (entryPath) => {
|
|
318
|
+
if (entryPath.endsWith('.hap') || entryPath.endsWith('.app') || entryPath.endsWith('.hsp')) {
|
|
319
|
+
discoveredPaths.push(entryPath);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
return discoveredPaths.sort((left, right) => left.localeCompare(right));
|
|
323
|
+
}
|
|
324
|
+
async function walkDirectory(currentPath, visitor) {
|
|
325
|
+
if (!(await fs_extra_1.default.pathExists(currentPath))) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const entries = await fs_extra_1.default.readdir(currentPath, { withFileTypes: true });
|
|
329
|
+
for (const entry of entries) {
|
|
330
|
+
const nextPath = path_1.default.join(currentPath, entry.name);
|
|
331
|
+
if (entry.isDirectory()) {
|
|
332
|
+
await walkDirectory(nextPath, visitor);
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
await visitor(nextPath);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BlockingIssue, BuildReport, BuildStepReport } from '../../types';
|
|
2
|
+
export declare function renderBuildReport(report: BuildReport): string;
|
|
3
|
+
export declare function getBundleOutputPath(projectRoot: string): string;
|
|
4
|
+
export declare function getAssetsOutputPath(projectRoot: string): string;
|
|
5
|
+
export declare function createBuildReport(input: {
|
|
6
|
+
projectRoot: string;
|
|
7
|
+
command: BuildReport['command'];
|
|
8
|
+
mode: BuildReport['mode'];
|
|
9
|
+
status: BuildReport['status'];
|
|
10
|
+
harmonyProjectRoot?: string | null;
|
|
11
|
+
entryFile: string | null;
|
|
12
|
+
bundleOutputPath: string | null;
|
|
13
|
+
assetsDestPath: string | null;
|
|
14
|
+
artifactPaths: string[];
|
|
15
|
+
blockingIssues: BlockingIssue[];
|
|
16
|
+
warnings: string[];
|
|
17
|
+
steps: BuildStepReport[];
|
|
18
|
+
}): BuildReport;
|
|
19
|
+
export declare function createStepReport(label: string, file: string, args: string[], cwd: string, exitCode: number | null): BuildStepReport;
|