@react-native-oh/react-native-harmony 0.72.23-3 → 0.72.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/Libraries/Alert/Alert.harmony.js +71 -71
  2. package/Libraries/Alert/AlertManager.ts +35 -35
  3. package/Libraries/Animated/NativeAnimatedHelper.harmony.js +601 -601
  4. package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.harmony.js +445 -426
  5. package/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.harmony.js +30 -0
  6. package/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.harmony.js +26 -0
  7. package/Libraries/Components/Button/Button.harmony.js +450 -450
  8. package/Libraries/Components/Image/Image.flow.harmony.js +53 -0
  9. package/Libraries/Components/Image/Image.harmony.js +299 -0
  10. package/Libraries/Components/Image/NativeImageLoaderHarmony.js +38 -0
  11. package/Libraries/Components/RefreshControl/RefreshControl.harmony.js +210 -210
  12. package/Libraries/Components/SafeAreaView/SafeAreaView.harmony.tsx +76 -75
  13. package/Libraries/Components/ScrollView/ScrollView.harmony.js +1951 -1951
  14. package/Libraries/Components/ScrollView/processDecelerationRate.harmony.js +24 -24
  15. package/Libraries/Components/StatusBar/NativeStatusBarManagerHarmony.js +71 -68
  16. package/Libraries/Components/StatusBar/StatusBar.harmony.js +447 -447
  17. package/Libraries/Components/TextInput/TextInput.harmony.js +1707 -1707
  18. package/Libraries/Components/TextInput/TextInputState.harmony.js +220 -220
  19. package/Libraries/Components/Touchable/TouchableHighlight.harmony.js +396 -396
  20. package/Libraries/Components/Touchable/TouchableNativeFeedback.harmony.js +364 -364
  21. package/Libraries/Components/Touchable/TouchableWithoutFeedback.harmony.js +227 -227
  22. package/Libraries/Components/View/View.harmony.js +149 -149
  23. package/Libraries/Core/setUpReactDevTools.harmony.js +93 -93
  24. package/Libraries/Image/AssetSourceResolver.harmony.ts +78 -78
  25. package/Libraries/NativeComponent/BaseViewConfig.harmony.js +337 -337
  26. package/Libraries/ReactNative/UIManager.harmony.js +210 -210
  27. package/Libraries/Settings/Settings.harmony.js +15 -15
  28. package/Libraries/Share/Share.harmony.js +174 -174
  29. package/Libraries/StyleSheet/NativePlatformColor.ts +8 -8
  30. package/Libraries/StyleSheet/PlatformColorValueTypes.harmony.ts +14 -14
  31. package/Libraries/Utilities/BackHandler.harmony.js +109 -109
  32. package/Libraries/Utilities/{NativePlatformConstantsHarmony.ts → NativePlatformConstants.harmony.ts} +8 -8
  33. package/Libraries/Utilities/Platform.d.ts +117 -117
  34. package/Libraries/Utilities/Platform.harmony.ts +33 -33
  35. package/Libraries/Utilities/createPerformanceLogger.harmony.js +328 -328
  36. package/Libraries/Vibration/Vibration.harmony.js +88 -88
  37. package/index.js +212 -212
  38. package/jest.config.js +5 -5
  39. package/metro.config.js +348 -348
  40. package/package.json +57 -57
  41. package/react-native.config.js +10 -10
  42. package/react_native_openharmony.har +0 -0
  43. package/tsconfig.json +13 -13
  44. package/types/index.d.ts +101 -101
package/metro.config.js CHANGED
@@ -1,348 +1,348 @@
1
- //@ts-check
2
- const pathUtils = require('path');
3
- const fs = require('fs');
4
- const colors = require('colors/safe');
5
-
6
- let shouldPrintInfoAboutRNRedirection = true;
7
-
8
- /**
9
- * @param msg {string}
10
- */
11
- function info(msg) {
12
- const infoPrefix = '[' + colors.bold(colors.cyan(`INFO`)) + ']';
13
- console.log(infoPrefix, msg);
14
- }
15
-
16
- /**
17
- * @param options {{reactNativeHarmonyPackageName: string} | undefined}
18
- * @returns {import("metro-config").InputConfigT}
19
- */
20
- function createHarmonyMetroConfig(options) {
21
- const reactNativeHarmonyName =
22
- options?.reactNativeHarmonyPackageName ?? 'react-native-harmony';
23
- return {
24
- transformer: {
25
- assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
26
- getTransformOptions: async () => ({
27
- transform: {
28
- experimentalImportSupport: false,
29
- inlineRequires: true,
30
- },
31
- }),
32
- },
33
- resolver: {
34
- blockList: [/third-party(\\\\|\\|\/)hermes/],
35
- resolveRequest: (ctx, moduleName, platform) => {
36
- if (platform === 'harmony') {
37
- if (shouldPrintInfoAboutRNRedirection) {
38
- info(
39
- `Redirected imports from ${colors.bold(
40
- colors.gray('react-native')
41
- )} to ${colors.bold(reactNativeHarmonyName)}`
42
- );
43
- shouldPrintInfoAboutRNRedirection = false;
44
- }
45
- if (moduleName === 'react-native') {
46
- return ctx.resolveRequest(ctx, reactNativeHarmonyName, platform);
47
- } else if (moduleName.startsWith('react-native/')) {
48
- return ctx.resolveRequest(ctx, moduleName, 'ios');
49
- } else if (
50
- isInternalReactNativeRelativeImport(ctx.originModulePath)
51
- ) {
52
- if (moduleName.startsWith('.')) {
53
- const moduleAbsPath = pathUtils.resolve(
54
- pathUtils.dirname(ctx.originModulePath),
55
- moduleName
56
- );
57
- const [_, modulePathRelativeToReactNative] = moduleAbsPath.split(
58
- `${pathUtils.sep}node_modules${pathUtils.sep}react-native${pathUtils.sep}`
59
- );
60
- try {
61
- return ctx.resolveRequest(
62
- ctx,
63
- `${reactNativeHarmonyName}${pathUtils.sep}${modulePathRelativeToReactNative}`,
64
- 'harmony'
65
- );
66
- } catch (err) {}
67
- }
68
- return ctx.resolveRequest(ctx, moduleName, 'ios');
69
- } else if(isHarmonyPackageInternalImport(ctx.originModulePath, moduleName)) {
70
- /**
71
- * Replace internal imports in `react-native-foo` with equivalent files from `react-native-harmony-foo`
72
- * if a package has internal import redirection enabled in its package.json configuration e.g.
73
- *
74
- * react-native-harmony-foo/package.json:
75
- * "harmony": {
76
- * "alias": "react-native-foo"
77
- * "redirectInternalImports": true,
78
- * }
79
- */
80
- const alias = getPackageNameFromOriginModulePath(ctx.originModulePath);
81
- if (alias) {
82
- const harmonyPackage = getHarmonyPackageByAliasMap(".");
83
- const harmonyPackageName = harmonyPackage[alias]?.name;
84
- const redirectInternalImports = harmonyPackage[alias]?.redirectInternalImports;
85
- if (harmonyPackageName && !isRequestFromHarmonyPackage(ctx.originModulePath, harmonyPackageName) && redirectInternalImports) {
86
- const moduleAbsPath = pathUtils.resolve(
87
- pathUtils.dirname(ctx.originModulePath),
88
- moduleName,
89
- );
90
- const [_, modulePathRelativeToOriginalPackage] = moduleAbsPath.split(
91
- `${pathUtils.sep}node_modules${pathUtils.sep}${alias}${pathUtils.sep}`,
92
- );
93
- const backslashes = new RegExp('\\\\', 'g');
94
- const pathToHarmonyModule = `${harmonyPackageName}/${modulePathRelativeToOriginalPackage.replace(backslashes, "/")}`;
95
- try {
96
- return ctx.resolveRequest(
97
- ctx,
98
- pathToHarmonyModule,
99
- 'harmony',
100
- );
101
- } catch (err) {
102
- }
103
- }
104
- }
105
- } else {
106
- /**
107
- * Replace `react-native-foo` with `react-native-harmony-foo` if a package has harmony directory and proper package.json configuration e.g.
108
- *
109
- * react-native-harmony-foo/package.json:
110
- * "harmony": {
111
- * "alias": "react-native-foo"
112
- * }
113
- */
114
- const harmonyPackageByAlias = getHarmonyPackageByAliasMap(".");
115
- const alias = getPackageName(moduleName);
116
- if (alias) {
117
- const harmonyPackageName = harmonyPackageByAlias[alias]?.name;
118
- if (
119
- harmonyPackageName &&
120
- !isRequestFromHarmonyPackage(
121
- ctx.originModulePath,
122
- harmonyPackageName
123
- )
124
- ) {
125
- return ctx.resolveRequest(
126
- ctx,
127
- moduleName.replace(alias, harmonyPackageName),
128
- platform
129
- );
130
- }
131
- }
132
- }
133
- }
134
- return ctx.resolveRequest(ctx, moduleName, platform);
135
- },
136
- },
137
- };
138
- }
139
-
140
- module.exports = {
141
- createHarmonyMetroConfig,
142
- };
143
-
144
- /**
145
- * @param moduleName {string}
146
- * @returns {string | null}
147
- */
148
- function getPackageName(moduleName) {
149
- if (moduleName.startsWith('.')) return null;
150
- if (moduleName.startsWith('@')) {
151
- const segments = moduleName.split('/', 3);
152
- if (segments.length == 2) {
153
- return moduleName;
154
- } else if (segments.length > 2) {
155
- return `${segments[0]}/${segments[1]}`;
156
- }
157
- return null;
158
- }
159
- if (moduleName.includes('/')) {
160
- return moduleName.split('/')[0];
161
- } else {
162
- return moduleName;
163
- }
164
- }
165
-
166
- /**
167
- * @param originModulePath {string}
168
- * @returns {string}
169
- */
170
- function getPackageNameFromOriginModulePath(originModulePath) {
171
- const nodeModulesPosition = originModulePath.search("node_modules");
172
- const pathRelativeToNodeModules = originModulePath.substring(nodeModulesPosition);
173
- const pathSegments = pathRelativeToNodeModules.split(pathUtils.sep);
174
- const module = pathSegments[1];
175
- if (module.startsWith('@')) {
176
- return `${pathSegments[1]}/${pathSegments[2]}`;
177
- }
178
- else {
179
- return pathSegments[1];
180
- }
181
- }
182
-
183
- /**
184
- * @param originModulePath {string}
185
- * @param moduleName {string}
186
- * @returns {boolean}
187
- */
188
- function isHarmonyPackageInternalImport(originModulePath, moduleName) {
189
- if (moduleName.startsWith(".")) {
190
- const alias = getPackageNameFromOriginModulePath(originModulePath);
191
- const slashes = new RegExp('/', 'g');
192
- if (alias && originModulePath.includes(`${pathUtils.sep}node_modules${pathUtils.sep}${alias.replace(slashes, pathUtils.sep)}${pathUtils.sep}`)) {
193
- const harmonyPackage = getHarmonyPackageByAliasMap(".");
194
- const harmonyPackageName = harmonyPackage[alias]?.name;
195
- if (
196
- harmonyPackageName &&
197
- !isRequestFromHarmonyPackage(
198
- originModulePath,
199
- harmonyPackageName,
200
- )
201
- ) {
202
- return true;
203
- }
204
- }
205
- }
206
- return false;
207
- }
208
-
209
- /**
210
- * @param originModulePath {string}
211
- * @returns {boolean}
212
- */
213
- function isInternalReactNativeRelativeImport(originModulePath) {
214
- return originModulePath.includes(
215
- `${pathUtils.sep}node_modules${pathUtils.sep}react-native${pathUtils.sep}`
216
- );
217
- }
218
-
219
- /**
220
- * @param originModulePath {string}
221
- * @param harmonyPackageName {string}
222
- * @returns {boolean}
223
- */
224
- function isRequestFromHarmonyPackage(originModulePath, harmonyPackageName) {
225
- const slashes = new RegExp('/', 'g');
226
- const packagePath = harmonyPackageName.replace(slashes, pathUtils.sep);
227
- return originModulePath.includes(
228
- `${pathUtils.sep}node_modules${pathUtils.sep}${packagePath}${pathUtils.sep}`
229
- );
230
- }
231
-
232
- /**
233
- * @type {Record<string, {name: string, redirectInternalImports: boolean}> | undefined}
234
- */
235
- let cachedHarmonyPackageByAliasMap = undefined;
236
-
237
- /**
238
- * @param projectRootPath {string}
239
- */
240
- function getHarmonyPackageByAliasMap(projectRootPath) {
241
- /**
242
- * @type {Record<string, {name: string, redirectInternalImports: boolean}>}
243
- */
244
- const initialAcc = {};
245
- if (cachedHarmonyPackageByAliasMap) {
246
- return cachedHarmonyPackageByAliasMap;
247
- }
248
- cachedHarmonyPackageByAliasMap = findHarmonyNodeModulePaths(
249
- findHarmonyNodeModuleSearchPaths(projectRootPath),
250
- ).reduce((acc, harmonyNodeModulePath) => {
251
- const harmonyNodeModulePathSegments = harmonyNodeModulePath.split(
252
- pathUtils.sep,
253
- );
254
- let harmonyNodeModuleName =
255
- harmonyNodeModulePathSegments[harmonyNodeModulePathSegments.length - 1];
256
- if (harmonyNodeModulePathSegments.length > 1) {
257
- const harmonyNodeModuleParentDirName =
258
- harmonyNodeModulePathSegments[harmonyNodeModulePathSegments.length - 2];
259
- if (harmonyNodeModuleParentDirName.startsWith('@')) {
260
- harmonyNodeModuleName = `${harmonyNodeModuleParentDirName}/${harmonyNodeModuleName}`;
261
- }
262
- }
263
- const packageJSONPath = `${harmonyNodeModulePath}${pathUtils.sep}package.json`;
264
- const packageJSON = readHarmonyModulePackageJSON(packageJSONPath);
265
- const alias = packageJSON.harmony?.alias;
266
- const redirectInternalImports = packageJSON?.harmony?.redirectInternalImports ?? false;
267
- if (alias) {
268
- acc[alias] ={
269
- name: harmonyNodeModuleName,
270
- redirectInternalImports: redirectInternalImports
271
- }
272
- }
273
- return acc;
274
- }, initialAcc);
275
- const harmonyPackagesCount = Object.keys(
276
- cachedHarmonyPackageByAliasMap,
277
- ).length;
278
- if (harmonyPackagesCount > 0) {
279
- const prettyHarmonyPackagesCount = colors.bold(
280
- harmonyPackagesCount > 0
281
- ? colors.green(harmonyPackagesCount.toString())
282
- : harmonyPackagesCount.toString(),
283
- );
284
- info(
285
- `Redirected imports to ${prettyHarmonyPackagesCount} harmony-specific third-party package(s):`,
286
- );
287
- if (harmonyPackagesCount > 0) {
288
- Object.entries(cachedHarmonyPackageByAliasMap).forEach(
289
- ([original, {name: alias}]) => {
290
- info(
291
- `• ${colors.bold(colors.gray(original))} → ${colors.bold(alias)}`,
292
- );
293
- },
294
- );
295
- }
296
- } else {
297
- info('No harmony-specific third-party packages have been detected');
298
- }
299
- console.log('');
300
- return cachedHarmonyPackageByAliasMap;
301
- }
302
-
303
- /**
304
- * @param projectRootPath {string}
305
- * @returns {string[]}
306
- */
307
- function findHarmonyNodeModuleSearchPaths(projectRootPath) {
308
- const nodeModulesPath = `${projectRootPath}${pathUtils.sep}node_modules`;
309
- const searchPaths = fs
310
- .readdirSync(nodeModulesPath)
311
- .filter((dirName) => dirName.startsWith('@'))
312
- .map((dirName) => `${nodeModulesPath}${pathUtils.sep}${dirName}`);
313
- searchPaths.push(nodeModulesPath);
314
- return searchPaths;
315
- }
316
-
317
- /**
318
- * @param searchPaths {string[]}
319
- * @returns {string[]}
320
- */
321
- function findHarmonyNodeModulePaths(searchPaths) {
322
- return searchPaths
323
- .map((searchPath) => {
324
- return fs
325
- .readdirSync(searchPath)
326
- .map((dirName) => `${searchPath}${pathUtils.sep}${dirName}`)
327
- .filter(hasPackageJSON);
328
- })
329
- .flat();
330
- }
331
-
332
- /**
333
- * @param nodeModulePath {string}
334
- * @returns {boolean}
335
- */
336
- function hasPackageJSON(nodeModulePath) {
337
- if (!fs.lstatSync(nodeModulePath).isDirectory()) return false;
338
- const nodeModuleContentNames = fs.readdirSync(nodeModulePath);
339
- return nodeModuleContentNames.includes('package.json');
340
- }
341
-
342
- /**
343
- * @param packageJSONPath {string}
344
- * @returns {{name: string, harmony?: {alias?: string, redirectInternalImports?: boolean}}}
345
- */
346
- function readHarmonyModulePackageJSON(packageJSONPath) {
347
- return JSON.parse(fs.readFileSync(packageJSONPath).toString());
348
- }
1
+ //@ts-check
2
+ const pathUtils = require('path');
3
+ const fs = require('fs');
4
+ const colors = require('colors/safe');
5
+
6
+ let shouldPrintInfoAboutRNRedirection = true;
7
+
8
+ /**
9
+ * @param msg {string}
10
+ */
11
+ function info(msg) {
12
+ const infoPrefix = '[' + colors.bold(colors.cyan(`INFO`)) + ']';
13
+ console.log(infoPrefix, msg);
14
+ }
15
+
16
+ /**
17
+ * @param options {{reactNativeHarmonyPackageName: string} | undefined}
18
+ * @returns {import("metro-config").InputConfigT}
19
+ */
20
+ function createHarmonyMetroConfig(options) {
21
+ const reactNativeHarmonyName =
22
+ options?.reactNativeHarmonyPackageName ?? 'react-native-harmony';
23
+ return {
24
+ transformer: {
25
+ assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
26
+ getTransformOptions: async () => ({
27
+ transform: {
28
+ experimentalImportSupport: false,
29
+ inlineRequires: true,
30
+ },
31
+ }),
32
+ },
33
+ resolver: {
34
+ blockList: [/third-party(\\\\|\\|\/)hermes/],
35
+ resolveRequest: (ctx, moduleName, platform) => {
36
+ if (platform === 'harmony') {
37
+ if (shouldPrintInfoAboutRNRedirection) {
38
+ info(
39
+ `Redirected imports from ${colors.bold(
40
+ colors.gray('react-native')
41
+ )} to ${colors.bold(reactNativeHarmonyName)}`
42
+ );
43
+ shouldPrintInfoAboutRNRedirection = false;
44
+ }
45
+ if (moduleName === 'react-native') {
46
+ return ctx.resolveRequest(ctx, reactNativeHarmonyName, platform);
47
+ } else if (moduleName.startsWith('react-native/')) {
48
+ return ctx.resolveRequest(ctx, moduleName, 'ios');
49
+ } else if (
50
+ isInternalReactNativeRelativeImport(ctx.originModulePath)
51
+ ) {
52
+ if (moduleName.startsWith('.')) {
53
+ const moduleAbsPath = pathUtils.resolve(
54
+ pathUtils.dirname(ctx.originModulePath),
55
+ moduleName
56
+ );
57
+ const [_, modulePathRelativeToReactNative] = moduleAbsPath.split(
58
+ `${pathUtils.sep}node_modules${pathUtils.sep}react-native${pathUtils.sep}`
59
+ );
60
+ try {
61
+ return ctx.resolveRequest(
62
+ ctx,
63
+ `${reactNativeHarmonyName}${pathUtils.sep}${modulePathRelativeToReactNative}`,
64
+ 'harmony'
65
+ );
66
+ } catch (err) {}
67
+ }
68
+ return ctx.resolveRequest(ctx, moduleName, 'ios');
69
+ } else if(isHarmonyPackageInternalImport(ctx.originModulePath, moduleName)) {
70
+ /**
71
+ * Replace internal imports in `react-native-foo` with equivalent files from `react-native-harmony-foo`
72
+ * if a package has internal import redirection enabled in its package.json configuration e.g.
73
+ *
74
+ * react-native-harmony-foo/package.json:
75
+ * "harmony": {
76
+ * "alias": "react-native-foo"
77
+ * "redirectInternalImports": true,
78
+ * }
79
+ */
80
+ const alias = getPackageNameFromOriginModulePath(ctx.originModulePath);
81
+ if (alias) {
82
+ const harmonyPackage = getHarmonyPackageByAliasMap(".");
83
+ const harmonyPackageName = harmonyPackage[alias]?.name;
84
+ const redirectInternalImports = harmonyPackage[alias]?.redirectInternalImports;
85
+ if (harmonyPackageName && !isRequestFromHarmonyPackage(ctx.originModulePath, harmonyPackageName) && redirectInternalImports) {
86
+ const moduleAbsPath = pathUtils.resolve(
87
+ pathUtils.dirname(ctx.originModulePath),
88
+ moduleName,
89
+ );
90
+ const [_, modulePathRelativeToOriginalPackage] = moduleAbsPath.split(
91
+ `${pathUtils.sep}node_modules${pathUtils.sep}${alias}${pathUtils.sep}`,
92
+ );
93
+ const backslashes = new RegExp('\\\\', 'g');
94
+ const pathToHarmonyModule = `${harmonyPackageName}/${modulePathRelativeToOriginalPackage.replace(backslashes, "/")}`;
95
+ try {
96
+ return ctx.resolveRequest(
97
+ ctx,
98
+ pathToHarmonyModule,
99
+ 'harmony',
100
+ );
101
+ } catch (err) {
102
+ }
103
+ }
104
+ }
105
+ } else {
106
+ /**
107
+ * Replace `react-native-foo` with `react-native-harmony-foo` if a package has harmony directory and proper package.json configuration e.g.
108
+ *
109
+ * react-native-harmony-foo/package.json:
110
+ * "harmony": {
111
+ * "alias": "react-native-foo"
112
+ * }
113
+ */
114
+ const harmonyPackageByAlias = getHarmonyPackageByAliasMap(".");
115
+ const alias = getPackageName(moduleName);
116
+ if (alias) {
117
+ const harmonyPackageName = harmonyPackageByAlias[alias]?.name;
118
+ if (
119
+ harmonyPackageName &&
120
+ !isRequestFromHarmonyPackage(
121
+ ctx.originModulePath,
122
+ harmonyPackageName
123
+ )
124
+ ) {
125
+ return ctx.resolveRequest(
126
+ ctx,
127
+ moduleName.replace(alias, harmonyPackageName),
128
+ platform
129
+ );
130
+ }
131
+ }
132
+ }
133
+ }
134
+ return ctx.resolveRequest(ctx, moduleName, platform);
135
+ },
136
+ },
137
+ };
138
+ }
139
+
140
+ module.exports = {
141
+ createHarmonyMetroConfig,
142
+ };
143
+
144
+ /**
145
+ * @param moduleName {string}
146
+ * @returns {string | null}
147
+ */
148
+ function getPackageName(moduleName) {
149
+ if (moduleName.startsWith('.')) return null;
150
+ if (moduleName.startsWith('@')) {
151
+ const segments = moduleName.split('/', 3);
152
+ if (segments.length == 2) {
153
+ return moduleName;
154
+ } else if (segments.length > 2) {
155
+ return `${segments[0]}/${segments[1]}`;
156
+ }
157
+ return null;
158
+ }
159
+ if (moduleName.includes('/')) {
160
+ return moduleName.split('/')[0];
161
+ } else {
162
+ return moduleName;
163
+ }
164
+ }
165
+
166
+ /**
167
+ * @param originModulePath {string}
168
+ * @returns {string}
169
+ */
170
+ function getPackageNameFromOriginModulePath(originModulePath) {
171
+ const nodeModulesPosition = originModulePath.search("node_modules");
172
+ const pathRelativeToNodeModules = originModulePath.substring(nodeModulesPosition);
173
+ const pathSegments = pathRelativeToNodeModules.split(pathUtils.sep);
174
+ const module = pathSegments[1];
175
+ if (module.startsWith('@')) {
176
+ return `${pathSegments[1]}/${pathSegments[2]}`;
177
+ }
178
+ else {
179
+ return pathSegments[1];
180
+ }
181
+ }
182
+
183
+ /**
184
+ * @param originModulePath {string}
185
+ * @param moduleName {string}
186
+ * @returns {boolean}
187
+ */
188
+ function isHarmonyPackageInternalImport(originModulePath, moduleName) {
189
+ if (moduleName.startsWith(".")) {
190
+ const alias = getPackageNameFromOriginModulePath(originModulePath);
191
+ const slashes = new RegExp('/', 'g');
192
+ if (alias && originModulePath.includes(`${pathUtils.sep}node_modules${pathUtils.sep}${alias.replace(slashes, pathUtils.sep)}${pathUtils.sep}`)) {
193
+ const harmonyPackage = getHarmonyPackageByAliasMap(".");
194
+ const harmonyPackageName = harmonyPackage[alias]?.name;
195
+ if (
196
+ harmonyPackageName &&
197
+ !isRequestFromHarmonyPackage(
198
+ originModulePath,
199
+ harmonyPackageName,
200
+ )
201
+ ) {
202
+ return true;
203
+ }
204
+ }
205
+ }
206
+ return false;
207
+ }
208
+
209
+ /**
210
+ * @param originModulePath {string}
211
+ * @returns {boolean}
212
+ */
213
+ function isInternalReactNativeRelativeImport(originModulePath) {
214
+ return originModulePath.includes(
215
+ `${pathUtils.sep}node_modules${pathUtils.sep}react-native${pathUtils.sep}`
216
+ );
217
+ }
218
+
219
+ /**
220
+ * @param originModulePath {string}
221
+ * @param harmonyPackageName {string}
222
+ * @returns {boolean}
223
+ */
224
+ function isRequestFromHarmonyPackage(originModulePath, harmonyPackageName) {
225
+ const slashes = new RegExp('/', 'g');
226
+ const packagePath = harmonyPackageName.replace(slashes, pathUtils.sep);
227
+ return originModulePath.includes(
228
+ `${pathUtils.sep}node_modules${pathUtils.sep}${packagePath}${pathUtils.sep}`
229
+ );
230
+ }
231
+
232
+ /**
233
+ * @type {Record<string, {name: string, redirectInternalImports: boolean}> | undefined}
234
+ */
235
+ let cachedHarmonyPackageByAliasMap = undefined;
236
+
237
+ /**
238
+ * @param projectRootPath {string}
239
+ */
240
+ function getHarmonyPackageByAliasMap(projectRootPath) {
241
+ /**
242
+ * @type {Record<string, {name: string, redirectInternalImports: boolean}>}
243
+ */
244
+ const initialAcc = {};
245
+ if (cachedHarmonyPackageByAliasMap) {
246
+ return cachedHarmonyPackageByAliasMap;
247
+ }
248
+ cachedHarmonyPackageByAliasMap = findHarmonyNodeModulePaths(
249
+ findHarmonyNodeModuleSearchPaths(projectRootPath),
250
+ ).reduce((acc, harmonyNodeModulePath) => {
251
+ const harmonyNodeModulePathSegments = harmonyNodeModulePath.split(
252
+ pathUtils.sep,
253
+ );
254
+ let harmonyNodeModuleName =
255
+ harmonyNodeModulePathSegments[harmonyNodeModulePathSegments.length - 1];
256
+ if (harmonyNodeModulePathSegments.length > 1) {
257
+ const harmonyNodeModuleParentDirName =
258
+ harmonyNodeModulePathSegments[harmonyNodeModulePathSegments.length - 2];
259
+ if (harmonyNodeModuleParentDirName.startsWith('@')) {
260
+ harmonyNodeModuleName = `${harmonyNodeModuleParentDirName}/${harmonyNodeModuleName}`;
261
+ }
262
+ }
263
+ const packageJSONPath = `${harmonyNodeModulePath}${pathUtils.sep}package.json`;
264
+ const packageJSON = readHarmonyModulePackageJSON(packageJSONPath);
265
+ const alias = packageJSON.harmony?.alias;
266
+ const redirectInternalImports = packageJSON?.harmony?.redirectInternalImports ?? false;
267
+ if (alias) {
268
+ acc[alias] ={
269
+ name: harmonyNodeModuleName,
270
+ redirectInternalImports: redirectInternalImports
271
+ }
272
+ }
273
+ return acc;
274
+ }, initialAcc);
275
+ const harmonyPackagesCount = Object.keys(
276
+ cachedHarmonyPackageByAliasMap,
277
+ ).length;
278
+ if (harmonyPackagesCount > 0) {
279
+ const prettyHarmonyPackagesCount = colors.bold(
280
+ harmonyPackagesCount > 0
281
+ ? colors.green(harmonyPackagesCount.toString())
282
+ : harmonyPackagesCount.toString(),
283
+ );
284
+ info(
285
+ `Redirected imports to ${prettyHarmonyPackagesCount} harmony-specific third-party package(s):`,
286
+ );
287
+ if (harmonyPackagesCount > 0) {
288
+ Object.entries(cachedHarmonyPackageByAliasMap).forEach(
289
+ ([original, {name: alias}]) => {
290
+ info(
291
+ `• ${colors.bold(colors.gray(original))} → ${colors.bold(alias)}`,
292
+ );
293
+ },
294
+ );
295
+ }
296
+ } else {
297
+ info('No harmony-specific third-party packages have been detected');
298
+ }
299
+ console.log('');
300
+ return cachedHarmonyPackageByAliasMap;
301
+ }
302
+
303
+ /**
304
+ * @param projectRootPath {string}
305
+ * @returns {string[]}
306
+ */
307
+ function findHarmonyNodeModuleSearchPaths(projectRootPath) {
308
+ const nodeModulesPath = `${projectRootPath}${pathUtils.sep}node_modules`;
309
+ const searchPaths = fs
310
+ .readdirSync(nodeModulesPath)
311
+ .filter((dirName) => dirName.startsWith('@'))
312
+ .map((dirName) => `${nodeModulesPath}${pathUtils.sep}${dirName}`);
313
+ searchPaths.push(nodeModulesPath);
314
+ return searchPaths;
315
+ }
316
+
317
+ /**
318
+ * @param searchPaths {string[]}
319
+ * @returns {string[]}
320
+ */
321
+ function findHarmonyNodeModulePaths(searchPaths) {
322
+ return searchPaths
323
+ .map((searchPath) => {
324
+ return fs
325
+ .readdirSync(searchPath)
326
+ .map((dirName) => `${searchPath}${pathUtils.sep}${dirName}`)
327
+ .filter(hasPackageJSON);
328
+ })
329
+ .flat();
330
+ }
331
+
332
+ /**
333
+ * @param nodeModulePath {string}
334
+ * @returns {boolean}
335
+ */
336
+ function hasPackageJSON(nodeModulePath) {
337
+ if (!fs.lstatSync(nodeModulePath).isDirectory()) return false;
338
+ const nodeModuleContentNames = fs.readdirSync(nodeModulePath);
339
+ return nodeModuleContentNames.includes('package.json');
340
+ }
341
+
342
+ /**
343
+ * @param packageJSONPath {string}
344
+ * @returns {{name: string, harmony?: {alias?: string, redirectInternalImports?: boolean}}}
345
+ */
346
+ function readHarmonyModulePackageJSON(packageJSONPath) {
347
+ return JSON.parse(fs.readFileSync(packageJSONPath).toString());
348
+ }