expo-harmony-toolkit 1.7.2 → 1.7.3

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 (68) hide show
  1. package/README.en.md +20 -9
  2. package/README.md +22 -11
  3. package/build/core/autolinking.d.ts +10 -0
  4. package/build/core/autolinking.js +421 -0
  5. package/build/core/build/commands.d.ts +19 -0
  6. package/build/core/build/commands.js +61 -0
  7. package/build/core/build/compatibilityShims.d.ts +1 -0
  8. package/build/core/build/compatibilityShims.js +272 -0
  9. package/build/core/build/localHar.d.ts +13 -0
  10. package/build/core/build/localHar.js +337 -0
  11. package/build/core/build/reporting.d.ts +19 -0
  12. package/build/core/build/reporting.js +67 -0
  13. package/build/core/build/rnohCompatibility.d.ts +1 -0
  14. package/build/core/build/rnohCompatibility.js +38 -0
  15. package/build/core/build.d.ts +4 -12
  16. package/build/core/build.js +70 -762
  17. package/build/core/constants.d.ts +2 -1
  18. package/build/core/constants.js +3 -2
  19. package/build/core/dependencyInspection.d.ts +2 -0
  20. package/build/core/dependencyInspection.js +112 -0
  21. package/build/core/env.js +1 -1
  22. package/build/core/report.js +33 -10
  23. package/build/core/signing.d.ts +2 -0
  24. package/build/core/signing.js +30 -0
  25. package/build/core/template/capabilityRegistry.d.ts +9 -0
  26. package/build/core/template/capabilityRegistry.js +84 -0
  27. package/build/core/template/expoModulesCoreShim.d.ts +2 -0
  28. package/build/core/template/expoModulesCoreShim.js +279 -0
  29. package/build/core/template/metro.d.ts +2 -0
  30. package/build/core/template/metro.js +213 -0
  31. package/build/core/template/nativeFiles.d.ts +8 -0
  32. package/build/core/template/nativeFiles.js +333 -0
  33. package/build/core/template/renderers/camera.d.ts +4 -0
  34. package/build/core/template/renderers/camera.js +612 -0
  35. package/build/core/template/renderers/fileSystem.d.ts +4 -0
  36. package/build/core/template/renderers/fileSystem.js +814 -0
  37. package/build/core/template/renderers/imagePicker.d.ts +4 -0
  38. package/build/core/template/renderers/imagePicker.js +753 -0
  39. package/build/core/template/renderers/location.d.ts +4 -0
  40. package/build/core/template/renderers/location.js +836 -0
  41. package/build/core/template/runtimeShims.d.ts +2 -0
  42. package/build/core/template/runtimeShims.js +192 -0
  43. package/build/core/template/support.d.ts +11 -0
  44. package/build/core/template/support.js +108 -0
  45. package/build/core/template.d.ts +2 -6
  46. package/build/core/template.js +40 -4453
  47. package/build/data/capabilities.js +21 -4
  48. package/build/data/dependencyCatalog.js +10 -0
  49. package/build/data/publicDocs.d.ts +11 -0
  50. package/build/data/publicDocs.js +28 -0
  51. package/build/data/validatedMatrices.js +9 -1
  52. package/build/docs/render.d.ts +9 -0
  53. package/build/docs/render.js +248 -0
  54. package/build/types.d.ts +12 -0
  55. package/docs/cli-build.md +1 -1
  56. package/docs/npm-release.md +1 -0
  57. package/docs/official-app-shell-sample.md +2 -1
  58. package/docs/official-minimal-sample.md +2 -1
  59. package/docs/official-native-capabilities-sample.md +3 -2
  60. package/docs/official-ui-stack-sample.md +2 -1
  61. package/docs/signing-and-release.md +3 -0
  62. package/docs/support-matrix.md +34 -9
  63. package/package.json +13 -5
  64. package/docs/v1.5.1-acceptance.md +0 -385
  65. package/docs/v1.6.0-acceptance.md +0 -193
  66. package/docs/v1.7.0-acceptance.md +0 -111
  67. package/docs/v1.7.1-acceptance.md +0 -111
  68. package/docs/v1.7.2-acceptance.md +0 -37
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderExpoModulesCoreHarmonyShim = renderExpoModulesCoreHarmonyShim;
4
+ function renderExpoModulesCoreHarmonyShim(expoConfig, identifiers) {
5
+ const embeddedExpoConfig = buildExpoConfigForShim(expoConfig, identifiers);
6
+ const serializedExpoConfig = JSON.stringify(embeddedExpoConfig, null, 2);
7
+ const primaryScheme = getPrimarySchemeForShim(embeddedExpoConfig, identifiers);
8
+ const linkingUri = primaryScheme ? `${primaryScheme}://` : null;
9
+ const serializedLinkingUri = JSON.stringify(linkingUri);
10
+ return `'use strict';
11
+
12
+ const { Linking, Platform } = require('react-native');
13
+
14
+ const embeddedExpoConfig = ${serializedExpoConfig};
15
+ const nativeModules = Object.create(null);
16
+
17
+ class EventSubscription {
18
+ constructor(remove) {
19
+ this._remove = remove;
20
+ }
21
+
22
+ remove() {
23
+ if (!this._remove) {
24
+ return;
25
+ }
26
+
27
+ const remove = this._remove;
28
+ this._remove = null;
29
+ remove();
30
+ }
31
+ }
32
+
33
+ class EventEmitter {
34
+ constructor() {
35
+ this._listeners = new Map();
36
+ }
37
+
38
+ addListener(eventName, listener) {
39
+ const listeners = this._listeners.get(eventName) ?? new Set();
40
+ listeners.add(listener);
41
+ this._listeners.set(eventName, listeners);
42
+
43
+ return new EventSubscription(() => {
44
+ listeners.delete(listener);
45
+
46
+ if (listeners.size === 0) {
47
+ this._listeners.delete(eventName);
48
+ }
49
+ });
50
+ }
51
+
52
+ removeAllListeners(eventName) {
53
+ if (typeof eventName === 'string') {
54
+ this._listeners.delete(eventName);
55
+ return;
56
+ }
57
+
58
+ this._listeners.clear();
59
+ }
60
+
61
+ emit(eventName, payload) {
62
+ const listeners = this._listeners.get(eventName);
63
+
64
+ if (!listeners) {
65
+ return;
66
+ }
67
+
68
+ for (const listener of listeners) {
69
+ listener(payload);
70
+ }
71
+ }
72
+ }
73
+
74
+ class LegacyEventEmitter extends EventEmitter {}
75
+
76
+ class NativeModule extends EventEmitter {}
77
+
78
+ class SharedObject {}
79
+
80
+ class SharedRef extends SharedObject {}
81
+
82
+ class CodedError extends Error {
83
+ constructor(code, message) {
84
+ super(message);
85
+ this.code = code;
86
+ this.name = 'CodedError';
87
+ }
88
+ }
89
+
90
+ class UnavailabilityError extends CodedError {
91
+ constructor(moduleName, propertyName) {
92
+ super(
93
+ 'ERR_UNAVAILABLE',
94
+ propertyName
95
+ ? moduleName + '.' + propertyName + ' is not available on Harmony.'
96
+ : moduleName + ' is not available on Harmony.',
97
+ );
98
+ this.name = 'UnavailabilityError';
99
+ }
100
+ }
101
+
102
+ class ExpoLinkingModule extends NativeModule {
103
+ constructor(initialUrl) {
104
+ super();
105
+ this._currentUrl = initialUrl;
106
+ }
107
+
108
+ getLinkingURL() {
109
+ return this._currentUrl;
110
+ }
111
+
112
+ _setCurrentUrl(url) {
113
+ this._currentUrl = url;
114
+ this.emit('onURLReceived', {
115
+ url,
116
+ });
117
+ }
118
+ }
119
+
120
+ const expoLinkingModule = new ExpoLinkingModule(${serializedLinkingUri});
121
+
122
+ if (Linking?.addEventListener) {
123
+ Linking.addEventListener('url', (event) => {
124
+ expoLinkingModule._setCurrentUrl(event?.url ?? null);
125
+ });
126
+ }
127
+
128
+ nativeModules.ExpoLinking = expoLinkingModule;
129
+ nativeModules.ExponentConstants = {
130
+ manifest: embeddedExpoConfig,
131
+ appOwnership: null,
132
+ executionEnvironment: 'standalone',
133
+ experienceUrl: ${serializedLinkingUri},
134
+ linkingUri: ${serializedLinkingUri},
135
+ statusBarHeight: 0,
136
+ systemVersion: 'HarmonyOS',
137
+ platform: {
138
+ android: embeddedExpoConfig.android ?? null,
139
+ ios: embeddedExpoConfig.ios ?? null,
140
+ web: null,
141
+ },
142
+ };
143
+ nativeModules.ExpoAsset = {
144
+ async downloadAsync(url) {
145
+ return url;
146
+ },
147
+ };
148
+ nativeModules.ExpoFetchModule = {
149
+ NativeRequest: class NativeRequest {
150
+ constructor(_response) {
151
+ this._response = _response;
152
+ }
153
+
154
+ async start() {
155
+ throw new UnavailabilityError('ExpoFetchModule', 'NativeRequest.start');
156
+ }
157
+
158
+ cancel() {}
159
+ },
160
+ };
161
+
162
+ function requireOptionalNativeModule(name) {
163
+ return nativeModules[name] ?? null;
164
+ }
165
+
166
+ function requireNativeModule(name) {
167
+ const nativeModule = requireOptionalNativeModule(name);
168
+
169
+ if (nativeModule) {
170
+ return nativeModule;
171
+ }
172
+
173
+ throw new UnavailabilityError(name);
174
+ }
175
+
176
+ function requireNativeViewManager(name) {
177
+ throw new UnavailabilityError(name, 'viewManager');
178
+ }
179
+
180
+ function registerWebModule() {}
181
+
182
+ async function reloadAppAsync() {}
183
+
184
+ function installOnUIRuntime() {}
185
+
186
+ globalThis.expo = {
187
+ ...(globalThis.expo ?? {}),
188
+ EventEmitter,
189
+ LegacyEventEmitter,
190
+ NativeModule,
191
+ SharedObject,
192
+ SharedRef,
193
+ modules: {
194
+ ...(globalThis.expo?.modules ?? {}),
195
+ ...nativeModules,
196
+ },
197
+ };
198
+
199
+ module.exports = {
200
+ Platform,
201
+ CodedError,
202
+ UnavailabilityError,
203
+ EventEmitter,
204
+ LegacyEventEmitter,
205
+ NativeModule,
206
+ SharedObject,
207
+ SharedRef,
208
+ requireNativeModule,
209
+ requireOptionalNativeModule,
210
+ requireNativeViewManager,
211
+ registerWebModule,
212
+ reloadAppAsync,
213
+ installOnUIRuntime,
214
+ };
215
+ `;
216
+ }
217
+ function buildExpoConfigForShim(expoConfig, identifiers) {
218
+ const normalized = toSerializableValue(expoConfig);
219
+ const config = normalized && typeof normalized === 'object' && !Array.isArray(normalized)
220
+ ? { ...normalized }
221
+ : {};
222
+ config.name = config.name ?? identifiers.appName;
223
+ config.slug = config.slug ?? identifiers.slug;
224
+ config.version = config.version ?? '1.0.0';
225
+ if (!config.scheme) {
226
+ config.scheme = getPrimarySchemeForShim(config, identifiers);
227
+ }
228
+ const android = config.android && typeof config.android === 'object' && !Array.isArray(config.android)
229
+ ? { ...config.android }
230
+ : {};
231
+ const ios = config.ios && typeof config.ios === 'object' && !Array.isArray(config.ios)
232
+ ? { ...config.ios }
233
+ : {};
234
+ android.package = android.package ?? identifiers.androidPackage ?? identifiers.bundleName;
235
+ ios.bundleIdentifier =
236
+ ios.bundleIdentifier ?? identifiers.iosBundleIdentifier ?? identifiers.bundleName;
237
+ config.android = android;
238
+ config.ios = ios;
239
+ return config;
240
+ }
241
+ function getPrimarySchemeForShim(expoConfig, identifiers) {
242
+ const scheme = expoConfig.scheme;
243
+ if (typeof scheme === 'string' && scheme.trim().length > 0) {
244
+ return scheme.trim();
245
+ }
246
+ if (Array.isArray(scheme)) {
247
+ const firstScheme = scheme.find((value) => typeof value === 'string' && value.trim().length > 0);
248
+ if (firstScheme) {
249
+ return firstScheme.trim();
250
+ }
251
+ }
252
+ return (identifiers.androidPackage ??
253
+ identifiers.iosBundleIdentifier ??
254
+ identifiers.bundleName);
255
+ }
256
+ function toSerializableValue(value) {
257
+ if (value === null ||
258
+ typeof value === 'string' ||
259
+ typeof value === 'number' ||
260
+ typeof value === 'boolean') {
261
+ return value;
262
+ }
263
+ if (Array.isArray(value)) {
264
+ return value
265
+ .map((entry) => toSerializableValue(entry))
266
+ .filter((entry) => entry !== undefined);
267
+ }
268
+ if (typeof value === 'object') {
269
+ const result = {};
270
+ for (const [key, entry] of Object.entries(value)) {
271
+ const serializedEntry = toSerializableValue(entry);
272
+ if (serializedEntry !== undefined) {
273
+ result[key] = serializedEntry;
274
+ }
275
+ }
276
+ return result;
277
+ }
278
+ return undefined;
279
+ }
@@ -0,0 +1,2 @@
1
+ import { CapabilityDefinition } from '../../types';
2
+ export declare function renderMetroConfig(enabledCapabilities: readonly CapabilityDefinition[]): string;
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderMetroConfig = renderMetroConfig;
4
+ function renderMetroConfig(enabledCapabilities) {
5
+ const previewCapabilityAliases = enabledCapabilities
6
+ .filter((capability) => capability.supportTier === 'preview' ||
7
+ capability.supportTier === 'experimental')
8
+ .map((capability) => ` '${capability.packageName}': path.resolve(__dirname, '.expo-harmony/shims/${capability.packageName}'),`)
9
+ .join('\n');
10
+ return `const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ process.env.EXPO_ROUTER_APP_ROOT = process.env.EXPO_ROUTER_APP_ROOT ?? 'app';
14
+
15
+ const { getDefaultConfig } = require('expo/metro-config');
16
+ const { createHarmonyMetroConfig } = require('@react-native-oh/react-native-harmony/metro.config');
17
+
18
+ const defaultConfig = getDefaultConfig(__dirname);
19
+ const harmonyConfig = createHarmonyMetroConfig({
20
+ reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
21
+ });
22
+ const expoHarmonyShims = {
23
+ 'expo-modules-core': path.resolve(__dirname, '.expo-harmony/shims/expo-modules-core'),
24
+ 'react-native-safe-area-context': path.resolve(
25
+ __dirname,
26
+ '.expo-harmony/shims/react-native-safe-area-context',
27
+ ),
28
+ ${previewCapabilityAliases ? `${previewCapabilityAliases}\n` : ''}};
29
+ const uiStackRootModuleAliases = {
30
+ 'react-native-gesture-handler': path.resolve(__dirname, 'node_modules/react-native-gesture-handler'),
31
+ 'react-native-reanimated': path.resolve(__dirname, 'node_modules/react-native-reanimated'),
32
+ 'react-native-svg': path.resolve(__dirname, 'node_modules/react-native-svg'),
33
+ };
34
+ const resolvePackageAlias = (context, moduleName, platform, aliases) => {
35
+ for (const [aliasedModuleName, aliasedModulePath] of Object.entries(aliases)) {
36
+ if (moduleName === aliasedModuleName) {
37
+ return context.resolveRequest(context, aliasedModulePath, platform);
38
+ }
39
+
40
+ if (moduleName.startsWith(\`\${aliasedModuleName}/\`)) {
41
+ return context.resolveRequest(
42
+ context,
43
+ path.join(aliasedModulePath, moduleName.slice(aliasedModuleName.length + 1)),
44
+ platform,
45
+ );
46
+ }
47
+ }
48
+
49
+ return null;
50
+ };
51
+ const resolveUiStackModuleAlias = (context, moduleName, platform) =>
52
+ resolvePackageAlias(context, moduleName, platform, uiStackRootModuleAliases);
53
+ const resolveExpoHarmonyModuleAlias = (context, moduleName, platform) =>
54
+ resolvePackageAlias(context, moduleName, platform, expoHarmonyShims);
55
+ const reactNativeCompatibilitySourceExts = ['js', 'jsx', 'ts', 'tsx', 'mjs', 'cjs', 'json'];
56
+ const reactNativeCompatibilityPackageMarkers = [
57
+ path.sep + '@react-native-oh' + path.sep + 'react-native-harmony' + path.sep,
58
+ path.sep + 'react-native' + path.sep,
59
+ ];
60
+ const findFirstExistingCompatibilityModule = (candidateBasePath, platforms) => {
61
+ for (const candidatePlatform of platforms) {
62
+ for (const candidateExtension of reactNativeCompatibilitySourceExts) {
63
+ const candidatePath = candidatePlatform
64
+ ? \`\${candidateBasePath}.\${candidatePlatform}.\${candidateExtension}\`
65
+ : \`\${candidateBasePath}.\${candidateExtension}\`;
66
+
67
+ if (fs.existsSync(candidatePath)) {
68
+ return { candidatePath, candidatePlatform };
69
+ }
70
+ }
71
+ }
72
+
73
+ return null;
74
+ };
75
+ const resolveReactNativeCompatibilityWrapper = (context, moduleName, platform) => {
76
+ if (platform !== 'harmony' || !context.originModulePath || !moduleName.startsWith('.')) {
77
+ return null;
78
+ }
79
+
80
+ const originModulePath = context.originModulePath;
81
+ const isReactNativeCompatibilityWrapper = reactNativeCompatibilityPackageMarkers.some((marker) =>
82
+ originModulePath.includes(marker),
83
+ );
84
+
85
+ if (!isReactNativeCompatibilityWrapper) {
86
+ return null;
87
+ }
88
+
89
+ const originExtension = path.extname(originModulePath);
90
+ const originBasename = path.basename(originModulePath, originExtension);
91
+ const candidateModulePath = path.resolve(path.dirname(originModulePath), moduleName);
92
+ const candidateModuleExtension = path.extname(candidateModulePath);
93
+ const candidateBasename = path.basename(candidateModulePath, candidateModuleExtension);
94
+
95
+ const candidateBasePath = candidateModuleExtension
96
+ ? candidateModulePath.slice(0, -candidateModuleExtension.length)
97
+ : candidateModulePath;
98
+
99
+ if (candidateBasename === originBasename) {
100
+ const compatibilityWrapperCandidate = findFirstExistingCompatibilityModule(candidateBasePath, [
101
+ 'harmony',
102
+ 'native',
103
+ 'android',
104
+ 'ios',
105
+ ]);
106
+
107
+ if (compatibilityWrapperCandidate) {
108
+ return context.resolveRequest(
109
+ context,
110
+ compatibilityWrapperCandidate.candidatePath,
111
+ compatibilityWrapperCandidate.candidatePlatform || platform,
112
+ );
113
+ }
114
+
115
+ return null;
116
+ }
117
+
118
+ const standardResolutionCandidate = findFirstExistingCompatibilityModule(candidateBasePath, [
119
+ 'harmony',
120
+ 'native',
121
+ '',
122
+ ]);
123
+
124
+ if (standardResolutionCandidate) {
125
+ return null;
126
+ }
127
+
128
+ const compatibilityFallbackCandidate = findFirstExistingCompatibilityModule(candidateBasePath, [
129
+ 'android',
130
+ 'ios',
131
+ ]);
132
+
133
+ if (compatibilityFallbackCandidate) {
134
+ return context.resolveRequest(
135
+ context,
136
+ compatibilityFallbackCandidate.candidatePath,
137
+ compatibilityFallbackCandidate.candidatePlatform || platform,
138
+ );
139
+ }
140
+
141
+ return null;
142
+ };
143
+ const resolveExpoHarmonyShim = (context, moduleName, platform) => {
144
+ const uiStackModuleAliasResolution = resolveUiStackModuleAlias(context, moduleName, platform);
145
+
146
+ if (uiStackModuleAliasResolution) {
147
+ return uiStackModuleAliasResolution;
148
+ }
149
+
150
+ const expoHarmonyModuleAliasResolution = resolveExpoHarmonyModuleAlias(context, moduleName, platform);
151
+
152
+ if (expoHarmonyModuleAliasResolution) {
153
+ return expoHarmonyModuleAliasResolution;
154
+ }
155
+
156
+ const compatibilityWrapperResolution = resolveReactNativeCompatibilityWrapper(
157
+ context,
158
+ moduleName,
159
+ platform,
160
+ );
161
+
162
+ if (compatibilityWrapperResolution) {
163
+ return compatibilityWrapperResolution;
164
+ }
165
+
166
+ const harmonyResolveRequest = harmonyConfig.resolver?.resolveRequest;
167
+
168
+ if (typeof harmonyResolveRequest === 'function') {
169
+ return harmonyResolveRequest(context, moduleName, platform);
170
+ }
171
+
172
+ return context.resolveRequest(context, moduleName, platform);
173
+ };
174
+
175
+ module.exports = {
176
+ ...defaultConfig,
177
+ ...harmonyConfig,
178
+ projectRoot: __dirname,
179
+ server: {
180
+ ...(defaultConfig.server ?? {}),
181
+ ...(harmonyConfig.server ?? {}),
182
+ unstable_serverRoot: __dirname,
183
+ },
184
+ transformer: {
185
+ ...(defaultConfig.transformer ?? {}),
186
+ ...(harmonyConfig.transformer ?? {}),
187
+ },
188
+ serializer: {
189
+ ...(defaultConfig.serializer ?? {}),
190
+ ...(harmonyConfig.serializer ?? {}),
191
+ },
192
+ resolver: {
193
+ ...(defaultConfig.resolver ?? {}),
194
+ ...(harmonyConfig.resolver ?? {}),
195
+ extraNodeModules: {
196
+ ...((defaultConfig.resolver?.extraNodeModules ?? {})),
197
+ ...((harmonyConfig.resolver?.extraNodeModules ?? {})),
198
+ ...uiStackRootModuleAliases,
199
+ ...expoHarmonyShims,
200
+ },
201
+ resolveRequest: resolveExpoHarmonyShim,
202
+ sourceExts: [
203
+ 'harmony.ts',
204
+ 'harmony.tsx',
205
+ 'harmony.js',
206
+ 'harmony.jsx',
207
+ ...((harmonyConfig.resolver?.sourceExts ??
208
+ defaultConfig.resolver?.sourceExts ?? ['ts', 'tsx', 'js', 'jsx', 'json'])),
209
+ ],
210
+ },
211
+ };
212
+ `;
213
+ }
@@ -0,0 +1,8 @@
1
+ export declare function renderPackageProvider(options: {
2
+ hasManagedExpoHarmonyPackage: boolean;
3
+ }): string;
4
+ export declare function renderPackageProviderCpp(options: {
5
+ hasManagedExpoHarmonyPackage: boolean;
6
+ }): string;
7
+ export declare function renderExpoHarmonyCppPackage(): string;
8
+ export declare function renderExpoHarmonyPackage(): string;