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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const TOOLKIT_PACKAGE_NAME = "expo-harmony-toolkit";
|
|
2
2
|
export declare const CLI_NAME = "expo-harmony";
|
|
3
|
-
export declare const TOOLKIT_VERSION = "1.
|
|
3
|
+
export declare const TOOLKIT_VERSION = "1.8.0";
|
|
4
4
|
export declare const TEMPLATE_VERSION = "rnoh-0.82.18";
|
|
5
5
|
export declare const RNOH_VERSION = "0.82.18";
|
|
6
6
|
export declare const RNOH_CLI_VERSION = "0.82.18";
|
|
@@ -8,6 +8,7 @@ export declare const SUPPORTED_EXPO_SDKS: number[];
|
|
|
8
8
|
export declare const GENERATED_DIR = ".expo-harmony";
|
|
9
9
|
export declare const GENERATED_SHIMS_DIR = ".expo-harmony/shims";
|
|
10
10
|
export declare const SIGNING_LOCAL_FILENAME = "signing.local.json";
|
|
11
|
+
export declare const SIGNING_LOCAL_EXAMPLE_FILENAME = "signing.local.example.json";
|
|
11
12
|
export declare const MANIFEST_FILENAME = "manifest.json";
|
|
12
13
|
export declare const DOCTOR_REPORT_FILENAME = "doctor-report.json";
|
|
13
14
|
export declare const ENV_REPORT_FILENAME = "env-report.json";
|
package/build/core/constants.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DESIRED_PACKAGE_SCRIPTS = exports.HARMONY_RUNTIME_PRELUDE_RELATIVE_PATH = exports.HARMONY_ROUTER_ENTRY_FILENAME = exports.STRICT_ENV_EXIT_CODE = exports.STRICT_DOCTOR_EXIT_CODE = exports.DEFAULT_HVIGOR_PLUGIN_FILENAME = exports.PREBUILD_METADATA_FILENAME = exports.TOOLKIT_CONFIG_FILENAME = exports.BUILD_REPORT_FILENAME = exports.ENV_REPORT_FILENAME = exports.DOCTOR_REPORT_FILENAME = exports.MANIFEST_FILENAME = exports.SIGNING_LOCAL_FILENAME = exports.GENERATED_SHIMS_DIR = exports.GENERATED_DIR = exports.SUPPORTED_EXPO_SDKS = exports.RNOH_CLI_VERSION = exports.RNOH_VERSION = exports.TEMPLATE_VERSION = exports.TOOLKIT_VERSION = exports.CLI_NAME = exports.TOOLKIT_PACKAGE_NAME = void 0;
|
|
3
|
+
exports.DESIRED_PACKAGE_SCRIPTS = exports.HARMONY_RUNTIME_PRELUDE_RELATIVE_PATH = exports.HARMONY_ROUTER_ENTRY_FILENAME = exports.STRICT_ENV_EXIT_CODE = exports.STRICT_DOCTOR_EXIT_CODE = exports.DEFAULT_HVIGOR_PLUGIN_FILENAME = exports.PREBUILD_METADATA_FILENAME = exports.TOOLKIT_CONFIG_FILENAME = exports.BUILD_REPORT_FILENAME = exports.ENV_REPORT_FILENAME = exports.DOCTOR_REPORT_FILENAME = exports.MANIFEST_FILENAME = exports.SIGNING_LOCAL_EXAMPLE_FILENAME = exports.SIGNING_LOCAL_FILENAME = exports.GENERATED_SHIMS_DIR = exports.GENERATED_DIR = exports.SUPPORTED_EXPO_SDKS = exports.RNOH_CLI_VERSION = exports.RNOH_VERSION = exports.TEMPLATE_VERSION = exports.TOOLKIT_VERSION = exports.CLI_NAME = exports.TOOLKIT_PACKAGE_NAME = void 0;
|
|
4
4
|
exports.TOOLKIT_PACKAGE_NAME = 'expo-harmony-toolkit';
|
|
5
5
|
exports.CLI_NAME = 'expo-harmony';
|
|
6
|
-
exports.TOOLKIT_VERSION = '1.
|
|
6
|
+
exports.TOOLKIT_VERSION = '1.8.0';
|
|
7
7
|
exports.TEMPLATE_VERSION = 'rnoh-0.82.18';
|
|
8
8
|
exports.RNOH_VERSION = '0.82.18';
|
|
9
9
|
exports.RNOH_CLI_VERSION = '0.82.18';
|
|
@@ -11,6 +11,7 @@ exports.SUPPORTED_EXPO_SDKS = [53, 55];
|
|
|
11
11
|
exports.GENERATED_DIR = '.expo-harmony';
|
|
12
12
|
exports.GENERATED_SHIMS_DIR = `${exports.GENERATED_DIR}/shims`;
|
|
13
13
|
exports.SIGNING_LOCAL_FILENAME = 'signing.local.json';
|
|
14
|
+
exports.SIGNING_LOCAL_EXAMPLE_FILENAME = 'signing.local.example.json';
|
|
14
15
|
exports.MANIFEST_FILENAME = 'manifest.json';
|
|
15
16
|
exports.DOCTOR_REPORT_FILENAME = 'doctor-report.json';
|
|
16
17
|
exports.ENV_REPORT_FILENAME = 'env-report.json';
|
|
@@ -0,0 +1,130 @@
|
|
|
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.annotateDependencyBuildability = annotateDependencyBuildability;
|
|
7
|
+
const node_module_1 = require("node:module");
|
|
8
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const NATIVE_DIRECTORY_CANDIDATES = ['android', 'ios', 'harmony'];
|
|
11
|
+
const NATIVE_CONFIG_CANDIDATES = [
|
|
12
|
+
'oh-package.json5',
|
|
13
|
+
'react-native.config.js',
|
|
14
|
+
'react-native.config.cjs',
|
|
15
|
+
'react-native.config.mjs',
|
|
16
|
+
'react-native.config.ts',
|
|
17
|
+
'expo-module.config.json',
|
|
18
|
+
'expo-module.config.js',
|
|
19
|
+
'expo-module.config.cjs',
|
|
20
|
+
'expo-module.config.mjs',
|
|
21
|
+
'expo-module.config.ts',
|
|
22
|
+
];
|
|
23
|
+
const PACKAGE_JSON_NATIVE_HINT_KEYS = [
|
|
24
|
+
'codegenConfig',
|
|
25
|
+
'expo-module',
|
|
26
|
+
'harmony',
|
|
27
|
+
'nativePackageName',
|
|
28
|
+
'podspecPath',
|
|
29
|
+
'react-native',
|
|
30
|
+
'react-native-builder-bob',
|
|
31
|
+
];
|
|
32
|
+
const PACKAGE_NAME_NATIVE_PATTERNS = [
|
|
33
|
+
/^expo(?:-|$)/,
|
|
34
|
+
/^@expo\//,
|
|
35
|
+
/^react-native(?:-|$)/,
|
|
36
|
+
/^@react-native\//,
|
|
37
|
+
/^@react-native-community\//,
|
|
38
|
+
];
|
|
39
|
+
async function annotateDependencyBuildability(projectRoot, dependencies) {
|
|
40
|
+
return Promise.all(dependencies.map(async (dependency) => ({
|
|
41
|
+
...dependency,
|
|
42
|
+
buildabilityRisk: await resolveDependencyBuildabilityRisk(projectRoot, dependency),
|
|
43
|
+
})));
|
|
44
|
+
}
|
|
45
|
+
async function resolveDependencyBuildabilityRisk(projectRoot, dependency) {
|
|
46
|
+
if (dependency.status !== 'unknown') {
|
|
47
|
+
return 'known';
|
|
48
|
+
}
|
|
49
|
+
const packageJsonPath = resolveInstalledDependencyPackageJson(projectRoot, dependency.name, dependency.version);
|
|
50
|
+
if (!packageJsonPath || !(await fs_extra_1.default.pathExists(packageJsonPath))) {
|
|
51
|
+
return 'unresolved';
|
|
52
|
+
}
|
|
53
|
+
const packageRoot = path_1.default.dirname(packageJsonPath);
|
|
54
|
+
const dependencyPackageJson = (await fs_extra_1.default.readJson(packageJsonPath));
|
|
55
|
+
if (looksLikeNativeDependencyByPackageName(dependency.name)) {
|
|
56
|
+
return 'native-risk';
|
|
57
|
+
}
|
|
58
|
+
if (await hasNativeSurface(packageRoot, dependencyPackageJson)) {
|
|
59
|
+
return 'native-risk';
|
|
60
|
+
}
|
|
61
|
+
return 'js-only-unknown';
|
|
62
|
+
}
|
|
63
|
+
function resolveInstalledDependencyPackageJson(projectRoot, dependencyName, dependencyVersion) {
|
|
64
|
+
const localPackageJsonPath = resolveLocalDependencyPackageJson(projectRoot, dependencyVersion);
|
|
65
|
+
if (localPackageJsonPath) {
|
|
66
|
+
return localPackageJsonPath;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const projectRequire = (0, node_module_1.createRequire)(path_1.default.join(projectRoot, 'package.json'));
|
|
70
|
+
return projectRequire.resolve(`${dependencyName}/package.json`);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function resolveLocalDependencyPackageJson(projectRoot, dependencyVersion) {
|
|
77
|
+
const trimmedVersion = dependencyVersion.trim();
|
|
78
|
+
for (const prefix of ['file:', 'link:', 'portal:']) {
|
|
79
|
+
if (!trimmedVersion.startsWith(prefix)) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const relativeTarget = trimmedVersion.slice(prefix.length).trim();
|
|
83
|
+
if (!relativeTarget) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return path_1.default.resolve(projectRoot, relativeTarget, 'package.json');
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
function looksLikeNativeDependencyByPackageName(dependencyName) {
|
|
91
|
+
return PACKAGE_NAME_NATIVE_PATTERNS.some((pattern) => pattern.test(dependencyName));
|
|
92
|
+
}
|
|
93
|
+
async function hasNativeSurface(packageRoot, dependencyPackageJson) {
|
|
94
|
+
for (const directoryName of NATIVE_DIRECTORY_CANDIDATES) {
|
|
95
|
+
if (await fs_extra_1.default.pathExists(path_1.default.join(packageRoot, directoryName))) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
for (const fileName of NATIVE_CONFIG_CANDIDATES) {
|
|
100
|
+
if (await fs_extra_1.default.pathExists(path_1.default.join(packageRoot, fileName))) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (await hasPodspecFile(packageRoot)) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
if (PACKAGE_JSON_NATIVE_HINT_KEYS.some((key) => dependencyPackageJson[key] !== undefined)) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
const files = Array.isArray(dependencyPackageJson.files)
|
|
111
|
+
? dependencyPackageJson.files.filter((entry) => typeof entry === 'string')
|
|
112
|
+
: [];
|
|
113
|
+
if (files.some((entry) => hasNativePathHint(entry))) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
const keywords = Array.isArray(dependencyPackageJson.keywords)
|
|
117
|
+
? dependencyPackageJson.keywords.filter((entry) => typeof entry === 'string')
|
|
118
|
+
: [];
|
|
119
|
+
if (keywords.some((keyword) => keyword === 'react-native' || keyword === 'expo-module')) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
async function hasPodspecFile(packageRoot) {
|
|
125
|
+
const entries = await fs_extra_1.default.readdir(packageRoot);
|
|
126
|
+
return entries.some((entry) => entry.endsWith('.podspec'));
|
|
127
|
+
}
|
|
128
|
+
function hasNativePathHint(value) {
|
|
129
|
+
return /(^|\/)(android|ios|harmony)(\/|$)/.test(value) || value.endsWith('.podspec');
|
|
130
|
+
}
|
package/build/core/env.js
CHANGED
|
@@ -95,7 +95,7 @@ async function buildEnvReport(projectRoot, options = {}) {
|
|
|
95
95
|
else if (!signingConfigured) {
|
|
96
96
|
advisories.push({
|
|
97
97
|
code: 'env.signing.missing',
|
|
98
|
-
message: 'Neither .expo-harmony/signing.local.json nor harmony/build-profile.json5 declares usable signingConfigs yet.
|
|
98
|
+
message: 'Neither .expo-harmony/signing.local.json nor harmony/build-profile.json5 declares usable signingConfigs yet. Copy .expo-harmony/signing.local.example.json to signing.local.json and fill your real release credentials before running release builds.',
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
return {
|
package/build/core/report.js
CHANGED
|
@@ -10,6 +10,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
const semver_1 = __importDefault(require("semver"));
|
|
12
12
|
const constants_1 = require("./constants");
|
|
13
|
+
const dependencyInspection_1 = require("./dependencyInspection");
|
|
13
14
|
const dependencyCatalog_1 = require("../data/dependencyCatalog");
|
|
14
15
|
const validatedMatrices_1 = require("../data/validatedMatrices");
|
|
15
16
|
const capabilities_1 = require("../data/capabilities");
|
|
@@ -22,6 +23,8 @@ const DEFAULT_RECORD = {
|
|
|
22
23
|
supportTier: 'unsupported',
|
|
23
24
|
note: 'This dependency is not in the current compatibility catalog yet.',
|
|
24
25
|
};
|
|
26
|
+
const BARE_WORKFLOW_DIRECTORY_NAMES = ['android', 'ios'];
|
|
27
|
+
const BARE_WORKFLOW_DEPENDENCIES = new Set(['expo-build-properties', 'expo-dev-client']);
|
|
25
28
|
async function buildDoctorReport(projectRoot, options = {}) {
|
|
26
29
|
const loadedProject = await (0, project_1.loadProject)(projectRoot);
|
|
27
30
|
const expoSdkVersion = (0, project_1.detectExpoSdkVersion)(loadedProject.packageJson);
|
|
@@ -39,7 +42,7 @@ async function buildDoctorReport(projectRoot, options = {}) {
|
|
|
39
42
|
dependencyRecords.set(pluginName, createDependencyRecord(pluginName, 'configured', 'expo-plugin'));
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
|
-
const dependencies = [...dependencyRecords.values()].sort((left, right) => left.name.localeCompare(right.name));
|
|
45
|
+
const dependencies = await (0, dependencyInspection_1.annotateDependencyBuildability)(loadedProject.projectRoot, [...dependencyRecords.values()].sort((left, right) => left.name.localeCompare(right.name)));
|
|
43
46
|
const blockingIssues = await collectBlockingIssues(loadedProject.projectRoot, loadedProject.expoConfig, loadedProject.packageJson, expoPlugins, expoSchemes, expoSdkVersion, dependencies, matrix, targetTier);
|
|
44
47
|
const capabilities = (0, capabilities_1.getCapabilityDefinitionsForProject)(loadedProject.packageJson).map((definition) => ({
|
|
45
48
|
id: definition.id,
|
|
@@ -48,6 +51,7 @@ async function buildDoctorReport(projectRoot, options = {}) {
|
|
|
48
51
|
supportTier: definition.supportTier,
|
|
49
52
|
runtimeMode: definition.runtimeMode,
|
|
50
53
|
evidence: { ...definition.evidence },
|
|
54
|
+
evidenceSource: { ...definition.evidenceSource },
|
|
51
55
|
note: definition.note,
|
|
52
56
|
docsUrl: definition.docsUrl,
|
|
53
57
|
nativePackageNames: [...definition.nativePackageNames],
|
|
@@ -55,13 +59,22 @@ async function buildDoctorReport(projectRoot, options = {}) {
|
|
|
55
59
|
sampleRoute: definition.sampleRoute,
|
|
56
60
|
acceptanceChecklist: [...definition.acceptanceChecklist],
|
|
57
61
|
}));
|
|
62
|
+
const coverageProfile = await detectCoverageProfile(loadedProject.projectRoot, loadedProject.packageJson, dependencies);
|
|
58
63
|
const blockingDependencyNames = new Set(blockingIssues
|
|
59
64
|
.filter((issue) => issue.code.startsWith('dependency.') && issue.subject)
|
|
60
65
|
.map((issue) => issue.subject));
|
|
61
66
|
const resolvedDependencies = dependencies.map((dependency) => ({
|
|
62
67
|
...dependency,
|
|
68
|
+
gapCategory: resolveDependencyGapCategory(dependency, coverageProfile),
|
|
63
69
|
blocking: blockingDependencyNames.has(dependency.name),
|
|
64
70
|
}));
|
|
71
|
+
const nextActions = buildNextActions({
|
|
72
|
+
targetTier,
|
|
73
|
+
coverageProfile,
|
|
74
|
+
blockingIssues,
|
|
75
|
+
dependencies: resolvedDependencies,
|
|
76
|
+
capabilities,
|
|
77
|
+
});
|
|
65
78
|
const warnings = buildWarnings(loadedProject.expoConfig, expoSdkVersion, resolvedDependencies);
|
|
66
79
|
const advisories = buildAdvisories(loadedProject.expoConfig);
|
|
67
80
|
return {
|
|
@@ -76,6 +89,7 @@ async function buildDoctorReport(projectRoot, options = {}) {
|
|
|
76
89
|
rnohCliVersion: constants_1.RNOH_CLI_VERSION,
|
|
77
90
|
expoSdkVersion,
|
|
78
91
|
targetTier,
|
|
92
|
+
coverageProfile,
|
|
79
93
|
expoConfig: {
|
|
80
94
|
name: loadedProject.expoConfig.name ?? null,
|
|
81
95
|
slug: loadedProject.expoConfig.slug ?? null,
|
|
@@ -100,6 +114,7 @@ async function buildDoctorReport(projectRoot, options = {}) {
|
|
|
100
114
|
},
|
|
101
115
|
capabilities,
|
|
102
116
|
blockingIssues,
|
|
117
|
+
nextActions,
|
|
103
118
|
advisories,
|
|
104
119
|
warnings,
|
|
105
120
|
};
|
|
@@ -118,6 +133,7 @@ function renderDoctorReport(report) {
|
|
|
118
133
|
`Expo SDK: ${report.expoSdkVersion ?? 'unknown'} (recognized ${constants_1.SUPPORTED_EXPO_SDKS.join(', ')})`,
|
|
119
134
|
`Matrix: ${report.matrixId ?? 'none'}`,
|
|
120
135
|
`Target tier: ${report.targetTier}`,
|
|
136
|
+
`Coverage profile: ${report.coverageProfile}`,
|
|
121
137
|
`Eligibility: ${report.eligibility}`,
|
|
122
138
|
`Schemes: ${report.expoConfig.schemes.join(', ') || 'none'}`,
|
|
123
139
|
`Plugins: ${report.expoConfig.plugins.join(', ') || 'none'}`,
|
|
@@ -129,7 +145,7 @@ function renderDoctorReport(report) {
|
|
|
129
145
|
...report.dependencies.map((dependency) => {
|
|
130
146
|
const replacement = dependency.replacement ? ` | replacement: ${dependency.replacement}` : '';
|
|
131
147
|
const blocking = dependency.blocking ? ' | blocking: yes' : '';
|
|
132
|
-
return `- [${dependency.status}/${dependency.supportTier}] ${dependency.name}@${dependency.version} (${dependency.source}) - ${dependency.note}${replacement}${blocking}`;
|
|
148
|
+
return `- [${dependency.status}/${dependency.supportTier}] ${dependency.name}@${dependency.version} (${dependency.source}) - ${dependency.note} | buildability: ${renderDependencyBuildabilityRisk(dependency.buildabilityRisk)} | gap: ${dependency.gapCategory}${replacement}${blocking}`;
|
|
133
149
|
}),
|
|
134
150
|
];
|
|
135
151
|
if (report.capabilities.length > 0) {
|
|
@@ -138,7 +154,7 @@ function renderDoctorReport(report) {
|
|
|
138
154
|
? ` | permissions: ${capability.harmonyPermissions.join(', ')}`
|
|
139
155
|
: '';
|
|
140
156
|
const missingEvidence = getMissingCapabilityEvidence(capability.evidence);
|
|
141
|
-
const evidence = ` | evidence: ${renderCapabilityEvidence(capability.evidence)}`;
|
|
157
|
+
const evidence = ` | evidence: ${renderCapabilityEvidence(capability.evidence, capability.evidenceSource)}`;
|
|
142
158
|
const promotionGaps = buildCapabilityPromotionGaps(capability.runtimeMode, missingEvidence);
|
|
143
159
|
const gapSuffix = promotionGaps.length > 0
|
|
144
160
|
? ` | verified gaps: ${promotionGaps.join(', ')}`
|
|
@@ -149,6 +165,9 @@ function renderDoctorReport(report) {
|
|
|
149
165
|
if (report.blockingIssues.length > 0) {
|
|
150
166
|
sections.push('', 'Blocking issues:', ...report.blockingIssues.map((issue) => `- ${issue.code}: ${issue.message}${issue.subject ? ` (${issue.subject})` : ''}`));
|
|
151
167
|
}
|
|
168
|
+
if (report.nextActions.length > 0) {
|
|
169
|
+
sections.push('', 'Next actions:', ...report.nextActions.map((action, index) => `${index + 1}. ${action}`));
|
|
170
|
+
}
|
|
152
171
|
if (report.advisories.length > 0) {
|
|
153
172
|
sections.push('', 'Advisories:', ...report.advisories.map((advisory) => `- ${advisory}`));
|
|
154
173
|
}
|
|
@@ -157,12 +176,12 @@ function renderDoctorReport(report) {
|
|
|
157
176
|
}
|
|
158
177
|
return sections.join('\n');
|
|
159
178
|
}
|
|
160
|
-
function renderCapabilityEvidence(evidence) {
|
|
179
|
+
function renderCapabilityEvidence(evidence, evidenceSource) {
|
|
161
180
|
return [
|
|
162
|
-
`bundle=${evidence.bundle ? 'yes' : 'no'}`,
|
|
163
|
-
`debugBuild=${evidence.debugBuild ? 'yes' : 'no'}`,
|
|
164
|
-
`device=${evidence.device ? 'yes' : 'no'}`,
|
|
165
|
-
`release=${evidence.release ? 'yes' : 'no'}`,
|
|
181
|
+
`bundle=${evidence.bundle ? 'yes' : 'no'}[${evidenceSource.bundle}]`,
|
|
182
|
+
`debugBuild=${evidence.debugBuild ? 'yes' : 'no'}[${evidenceSource.debugBuild}]`,
|
|
183
|
+
`device=${evidence.device ? 'yes' : 'no'}[${evidenceSource.device}]`,
|
|
184
|
+
`release=${evidence.release ? 'yes' : 'no'}[${evidenceSource.release}]`,
|
|
166
185
|
].join(', ');
|
|
167
186
|
}
|
|
168
187
|
function getMissingCapabilityEvidence(evidence) {
|
|
@@ -185,6 +204,8 @@ function createDependencyRecord(name, version, source) {
|
|
|
185
204
|
source,
|
|
186
205
|
status: matrixRecord.status,
|
|
187
206
|
supportTier: matrixRecord.supportTier,
|
|
207
|
+
buildabilityRisk: 'known',
|
|
208
|
+
gapCategory: 'matrix-drift',
|
|
188
209
|
blocking: false,
|
|
189
210
|
note: matrixRecord.note,
|
|
190
211
|
replacement: matrixRecord.replacement,
|
|
@@ -332,6 +353,114 @@ async function collectBlockingIssues(projectRoot, expoConfig, packageJson, expoP
|
|
|
332
353
|
}
|
|
333
354
|
return dedupeIssues(issues);
|
|
334
355
|
}
|
|
356
|
+
async function detectCoverageProfile(projectRoot, packageJson, dependencies) {
|
|
357
|
+
for (const directoryName of BARE_WORKFLOW_DIRECTORY_NAMES) {
|
|
358
|
+
if (await fs_extra_1.default.pathExists(path_1.default.join(projectRoot, directoryName))) {
|
|
359
|
+
return 'bare';
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (dependencies.some((dependency) => isThirdPartyNativeGapDependency(dependency))) {
|
|
363
|
+
return 'third-party-native-heavy';
|
|
364
|
+
}
|
|
365
|
+
if ((0, capabilities_1.getCapabilityDefinitionsForProject)(packageJson).length > 0 ||
|
|
366
|
+
dependencies.some((dependency) => isOfficialExpoDependencyName(dependency.name) && dependency.supportTier !== 'verified')) {
|
|
367
|
+
return 'managed-native-heavy';
|
|
368
|
+
}
|
|
369
|
+
return 'managed-core';
|
|
370
|
+
}
|
|
371
|
+
function resolveDependencyGapCategory(dependency, coverageProfile) {
|
|
372
|
+
if (coverageProfile === 'bare' &&
|
|
373
|
+
(BARE_WORKFLOW_DEPENDENCIES.has(dependency.name) ||
|
|
374
|
+
dependency.name === 'expo' ||
|
|
375
|
+
dependency.name === 'react-native')) {
|
|
376
|
+
return 'bare-workflow-gap';
|
|
377
|
+
}
|
|
378
|
+
if (isOfficialExpoDependencyName(dependency.name) || capabilities_1.CAPABILITY_BY_PACKAGE[dependency.name]) {
|
|
379
|
+
return dependency.supportTier === 'verified' && dependency.status === 'supported'
|
|
380
|
+
? 'matrix-drift'
|
|
381
|
+
: 'official-module-gap';
|
|
382
|
+
}
|
|
383
|
+
if (isThirdPartyNativeGapDependency(dependency)) {
|
|
384
|
+
return 'third-party-native-gap';
|
|
385
|
+
}
|
|
386
|
+
if (coverageProfile === 'bare') {
|
|
387
|
+
return 'bare-workflow-gap';
|
|
388
|
+
}
|
|
389
|
+
return 'matrix-drift';
|
|
390
|
+
}
|
|
391
|
+
function isOfficialExpoDependencyName(dependencyName) {
|
|
392
|
+
return dependencyName === 'expo' || dependencyName.startsWith('expo-') || dependencyName.startsWith('@expo/');
|
|
393
|
+
}
|
|
394
|
+
function isThirdPartyNativeGapDependency(dependency) {
|
|
395
|
+
if (dependency.name === 'react-native-gesture-handler' ||
|
|
396
|
+
dependency.name === '@react-native-oh-tpl/react-native-gesture-handler') {
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
if (dependency.buildabilityRisk === 'native-risk') {
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
return (dependency.supportTier !== 'verified' &&
|
|
403
|
+
!isOfficialExpoDependencyName(dependency.name) &&
|
|
404
|
+
dependency.name.startsWith('react-native'));
|
|
405
|
+
}
|
|
406
|
+
function buildNextActions(input) {
|
|
407
|
+
const actions = [];
|
|
408
|
+
const { targetTier, coverageProfile, blockingIssues, dependencies, capabilities } = input;
|
|
409
|
+
const hasPreviewCapabilities = capabilities.some((capability) => capability.supportTier === 'preview');
|
|
410
|
+
const hasRouterBlockingIssues = blockingIssues.some((issue) => [
|
|
411
|
+
'dependency.router_peer_missing',
|
|
412
|
+
'config.router_plugin.missing',
|
|
413
|
+
'config.scheme.missing',
|
|
414
|
+
'config.bundle_script.mismatch',
|
|
415
|
+
].includes(issue.code));
|
|
416
|
+
if (hasBlockingIssueCode(blockingIssues, 'matrix.expo_sdk.unsupported') ||
|
|
417
|
+
hasBlockingIssueCode(blockingIssues, 'dependency.version_mismatch') ||
|
|
418
|
+
hasBlockingIssueCode(blockingIssues, 'dependency.specifier_mismatch') ||
|
|
419
|
+
hasBlockingIssueCode(blockingIssues, 'dependency.required_missing')) {
|
|
420
|
+
actions.push(`Align Expo SDK, React Native, RNOH, and validated adapter versions to ${validatedMatrices_1.DEFAULT_VALIDATED_MATRIX_ID}, then rerun \`expo-harmony doctor --project-root . --strict\`.`);
|
|
421
|
+
}
|
|
422
|
+
if (targetTier === 'verified' && hasPreviewCapabilities) {
|
|
423
|
+
actions.push('Use `expo-harmony doctor --project-root . --target-tier preview` to measure the current preview-capability baseline while keeping `latest` pinned to verified-only releases.');
|
|
424
|
+
}
|
|
425
|
+
if (hasPreviewCapabilities) {
|
|
426
|
+
actions.push('Keep combined sample smoke for regression coverage, but track bundle/debug/device/release evidence separately for each preview capability before promotion.');
|
|
427
|
+
}
|
|
428
|
+
switch (coverageProfile) {
|
|
429
|
+
case 'managed-core':
|
|
430
|
+
actions.push('Stay on the verified lane: rerun `expo-harmony sync-template --project-root .`, `expo-harmony bundle --project-root .`, and `expo-harmony build-hap --project-root . --mode debug` before claiming release readiness.');
|
|
431
|
+
break;
|
|
432
|
+
case 'managed-native-heavy':
|
|
433
|
+
actions.push('After every native-capability change, rerun `expo-harmony sync-template --project-root .`, `expo-harmony bundle --project-root .`, and `expo-harmony build-hap --project-root . --mode debug` to keep the managed sidecar and preview evidence aligned.');
|
|
434
|
+
break;
|
|
435
|
+
case 'bare':
|
|
436
|
+
actions.push('Keep this project on the bare workflow track for now: preserve the native directories, use `expo-harmony doctor --project-root .` for classification, and only claim verified support after bare workflow support lands in the mainline capability catalog.');
|
|
437
|
+
break;
|
|
438
|
+
case 'third-party-native-heavy':
|
|
439
|
+
actions.push('Isolate third-party native packages and onboard them through the mainline capability catalog one by one; start with `react-native-gesture-handler` if it is present, and treat unknown native surfaces as explicit unblockers rather than matrix drift.');
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
if (hasRouterBlockingIssues) {
|
|
443
|
+
actions.push('Add the missing expo-router peers/plugin/scheme or update the Harmony bundle script to use `expo-harmony bundle`, then rerun doctor before trusting router builds.');
|
|
444
|
+
}
|
|
445
|
+
if (blockingIssues.some((issue) => issue.code === 'dependency.not_allowed' &&
|
|
446
|
+
(issue.subject === 'react-native-gesture-handler' ||
|
|
447
|
+
issue.subject === '@react-native-oh-tpl/react-native-gesture-handler'))) {
|
|
448
|
+
actions.push('Keep `react-native-gesture-handler` out of the verified lane until its Harmony adapter path has stable doctor, sample, and build coverage.');
|
|
449
|
+
}
|
|
450
|
+
if (hasBlockingIssueCode(blockingIssues, 'config.native_identifier.missing')) {
|
|
451
|
+
actions.push('Set `android.package` or `ios.bundleIdentifier` in Expo config before expecting a strict Harmony build path.');
|
|
452
|
+
}
|
|
453
|
+
if (dependencies.some((dependency) => dependency.buildabilityRisk === 'native-risk')) {
|
|
454
|
+
actions.push('Inspect unknown native-looking dependencies and either replace them, gate them behind preview work, or onboard them explicitly before promising Harmony portability.');
|
|
455
|
+
}
|
|
456
|
+
if (dependencies.some((dependency) => dependency.buildabilityRisk === 'js-only-unknown')) {
|
|
457
|
+
actions.push('Unknown JavaScript-only packages still sit outside the public matrix; verify bundling manually, but prioritize native gaps first.');
|
|
458
|
+
}
|
|
459
|
+
return dedupeStrings(actions);
|
|
460
|
+
}
|
|
461
|
+
function hasBlockingIssueCode(issues, code) {
|
|
462
|
+
return issues.some((issue) => issue.code === code);
|
|
463
|
+
}
|
|
335
464
|
function buildWarnings(expoConfig, expoSdkVersion, dependencies) {
|
|
336
465
|
const warnings = [];
|
|
337
466
|
const expoSdkWarning = (0, project_1.getExpoSdkWarning)(expoSdkVersion);
|
|
@@ -350,8 +479,14 @@ function buildWarnings(expoConfig, expoSdkVersion, dependencies) {
|
|
|
350
479
|
if (dependencies.some((dependency) => dependency.supportTier === 'experimental')) {
|
|
351
480
|
warnings.push('Experimental-tier dependencies were detected. Expect bridge drift, runtime gaps, or additional manual validation before claiming release readiness.');
|
|
352
481
|
}
|
|
353
|
-
if (dependencies.some((dependency) => dependency.
|
|
354
|
-
warnings.push('
|
|
482
|
+
if (dependencies.some((dependency) => dependency.buildabilityRisk === 'js-only-unknown')) {
|
|
483
|
+
warnings.push('Some unknown dependencies look JavaScript-only. They remain outside the public matrix, but they are less likely to block bundling or a debug HAP build outright.');
|
|
484
|
+
}
|
|
485
|
+
if (dependencies.some((dependency) => dependency.buildabilityRisk === 'native-risk')) {
|
|
486
|
+
warnings.push('Some unknown dependencies appear to carry native surfaces. Treat them as real Harmony portability risks until they are explicitly onboarded.');
|
|
487
|
+
}
|
|
488
|
+
if (dependencies.some((dependency) => dependency.buildabilityRisk === 'unresolved')) {
|
|
489
|
+
warnings.push('Some unknown dependencies could not be inspected because their installed package metadata was unavailable. Install dependencies before treating the doctor report as a buildability signal.');
|
|
355
490
|
}
|
|
356
491
|
return warnings;
|
|
357
492
|
}
|
|
@@ -384,6 +519,20 @@ function matchesVersionRange(rawVersion, range) {
|
|
|
384
519
|
function matchesDependencySpecifier(rawSpecifier, expectedSpecifier) {
|
|
385
520
|
return rawSpecifier.trim() === expectedSpecifier.trim();
|
|
386
521
|
}
|
|
522
|
+
function renderDependencyBuildabilityRisk(buildabilityRisk) {
|
|
523
|
+
switch (buildabilityRisk) {
|
|
524
|
+
case 'known':
|
|
525
|
+
return 'known';
|
|
526
|
+
case 'js-only-unknown':
|
|
527
|
+
return 'unknown-js';
|
|
528
|
+
case 'native-risk':
|
|
529
|
+
return 'unknown-native';
|
|
530
|
+
case 'unresolved':
|
|
531
|
+
return 'unresolved';
|
|
532
|
+
default:
|
|
533
|
+
return buildabilityRisk;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
387
536
|
function dedupeIssues(issues) {
|
|
388
537
|
const seen = new Set();
|
|
389
538
|
return issues.filter((issue) => {
|
|
@@ -395,3 +544,6 @@ function dedupeIssues(issues) {
|
|
|
395
544
|
return true;
|
|
396
545
|
});
|
|
397
546
|
}
|
|
547
|
+
function dedupeStrings(values) {
|
|
548
|
+
return [...new Set(values)];
|
|
549
|
+
}
|
package/build/core/signing.d.ts
CHANGED
|
@@ -4,8 +4,10 @@ type SigningLocalAppFragment = {
|
|
|
4
4
|
products?: JsonRecord[];
|
|
5
5
|
};
|
|
6
6
|
export declare function getSigningLocalPath(projectRoot: string): string;
|
|
7
|
+
export declare function getSigningLocalExamplePath(projectRoot: string): string;
|
|
7
8
|
export declare function readSigningLocalConfig(projectRoot: string): Promise<SigningLocalAppFragment | null>;
|
|
8
9
|
export declare function mergeSigningLocalConfigIntoBuildProfile(rawBuildProfileContents: string, signingLocalConfig: SigningLocalAppFragment | null): string;
|
|
9
10
|
export declare function hasSigningConfiguration(rawBuildProfileContents: string | null, signingLocalConfig?: SigningLocalAppFragment | null): boolean;
|
|
10
11
|
export declare function hasSigningLocalConfiguration(signingLocalConfig: SigningLocalAppFragment | null): boolean;
|
|
12
|
+
export declare function renderSigningLocalExampleConfig(): string;
|
|
11
13
|
export {};
|
package/build/core/signing.js
CHANGED
|
@@ -4,10 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getSigningLocalPath = getSigningLocalPath;
|
|
7
|
+
exports.getSigningLocalExamplePath = getSigningLocalExamplePath;
|
|
7
8
|
exports.readSigningLocalConfig = readSigningLocalConfig;
|
|
8
9
|
exports.mergeSigningLocalConfigIntoBuildProfile = mergeSigningLocalConfigIntoBuildProfile;
|
|
9
10
|
exports.hasSigningConfiguration = hasSigningConfiguration;
|
|
10
11
|
exports.hasSigningLocalConfiguration = hasSigningLocalConfiguration;
|
|
12
|
+
exports.renderSigningLocalExampleConfig = renderSigningLocalExampleConfig;
|
|
11
13
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
12
14
|
const json5_1 = __importDefault(require("json5"));
|
|
13
15
|
const path_1 = __importDefault(require("path"));
|
|
@@ -15,6 +17,9 @@ const constants_1 = require("./constants");
|
|
|
15
17
|
function getSigningLocalPath(projectRoot) {
|
|
16
18
|
return path_1.default.join(projectRoot, constants_1.GENERATED_DIR, constants_1.SIGNING_LOCAL_FILENAME);
|
|
17
19
|
}
|
|
20
|
+
function getSigningLocalExamplePath(projectRoot) {
|
|
21
|
+
return path_1.default.join(projectRoot, constants_1.GENERATED_DIR, constants_1.SIGNING_LOCAL_EXAMPLE_FILENAME);
|
|
22
|
+
}
|
|
18
23
|
async function readSigningLocalConfig(projectRoot) {
|
|
19
24
|
const signingLocalPath = getSigningLocalPath(projectRoot);
|
|
20
25
|
if (!(await fs_extra_1.default.pathExists(signingLocalPath))) {
|
|
@@ -49,6 +54,31 @@ function hasSigningConfiguration(rawBuildProfileContents, signingLocalConfig = n
|
|
|
49
54
|
function hasSigningLocalConfiguration(signingLocalConfig) {
|
|
50
55
|
return hasNonEmptySigningConfigList(signingLocalConfig?.signingConfigs);
|
|
51
56
|
}
|
|
57
|
+
function renderSigningLocalExampleConfig() {
|
|
58
|
+
return (JSON.stringify({
|
|
59
|
+
signingConfigs: [
|
|
60
|
+
{
|
|
61
|
+
name: 'default',
|
|
62
|
+
type: 'HarmonyOS',
|
|
63
|
+
material: {
|
|
64
|
+
storeFile: './signing/release.p12',
|
|
65
|
+
storePassword: '<replace-with-store-password>',
|
|
66
|
+
keyAlias: '<replace-with-key-alias>',
|
|
67
|
+
keyPassword: '<replace-with-key-password>',
|
|
68
|
+
signAlg: 'SHA256withECDSA',
|
|
69
|
+
profile: './signing/release.p7b',
|
|
70
|
+
certpath: './signing/release.cer',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
products: [
|
|
75
|
+
{
|
|
76
|
+
name: 'default',
|
|
77
|
+
signingConfig: 'default',
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
}, null, 2) + '\n');
|
|
81
|
+
}
|
|
52
82
|
function normalizeSigningLocalConfig(rawConfig) {
|
|
53
83
|
const candidate = rawConfig && typeof rawConfig === 'object' && !Array.isArray(rawConfig)
|
|
54
84
|
? 'app' in rawConfig &&
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CapabilityDefinition } from '../../types';
|
|
2
|
+
type ManagedExpoHarmonyModuleRenderer = {
|
|
3
|
+
filename: string;
|
|
4
|
+
render: () => string;
|
|
5
|
+
};
|
|
6
|
+
export declare const MANAGED_EXPO_HARMONY_MODULE_RENDERERS: readonly ManagedExpoHarmonyModuleRenderer[];
|
|
7
|
+
export declare function renderCapabilityModuleShim(capability: CapabilityDefinition): string;
|
|
8
|
+
export declare function renderUnsupportedCapabilityShim(capability: CapabilityDefinition): string;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MANAGED_EXPO_HARMONY_MODULE_RENDERERS = void 0;
|
|
4
|
+
exports.renderCapabilityModuleShim = renderCapabilityModuleShim;
|
|
5
|
+
exports.renderUnsupportedCapabilityShim = renderUnsupportedCapabilityShim;
|
|
6
|
+
const camera_1 = require("./renderers/camera");
|
|
7
|
+
const fileSystem_1 = require("./renderers/fileSystem");
|
|
8
|
+
const imagePicker_1 = require("./renderers/imagePicker");
|
|
9
|
+
const location_1 = require("./renderers/location");
|
|
10
|
+
const CAPABILITY_SHIM_RENDERERS = {
|
|
11
|
+
'expo-file-system': {
|
|
12
|
+
adapter: fileSystem_1.renderExpoFileSystemHarmonyAdapterShim,
|
|
13
|
+
preview: fileSystem_1.renderExpoFileSystemPreviewShim,
|
|
14
|
+
},
|
|
15
|
+
'expo-image-picker': {
|
|
16
|
+
adapter: imagePicker_1.renderExpoImagePickerHarmonyAdapterShim,
|
|
17
|
+
preview: imagePicker_1.renderExpoImagePickerPreviewShim,
|
|
18
|
+
},
|
|
19
|
+
'expo-location': {
|
|
20
|
+
adapter: location_1.renderExpoLocationHarmonyAdapterShim,
|
|
21
|
+
preview: location_1.renderExpoLocationPreviewShim,
|
|
22
|
+
},
|
|
23
|
+
'expo-camera': {
|
|
24
|
+
adapter: camera_1.renderExpoCameraHarmonyAdapterShim,
|
|
25
|
+
preview: camera_1.renderExpoCameraPreviewShim,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
exports.MANAGED_EXPO_HARMONY_MODULE_RENDERERS = [
|
|
29
|
+
{
|
|
30
|
+
filename: 'ExpoHarmonyFileSystemTurboModule.ts',
|
|
31
|
+
render: fileSystem_1.renderExpoHarmonyFileSystemTurboModule,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
filename: 'ExpoHarmonyImagePickerTurboModule.ts',
|
|
35
|
+
render: imagePicker_1.renderExpoHarmonyImagePickerTurboModule,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
filename: 'ExpoHarmonyLocationTurboModule.ts',
|
|
39
|
+
render: location_1.renderExpoHarmonyLocationTurboModule,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
filename: 'ExpoHarmonyCameraTurboModule.ts',
|
|
43
|
+
render: camera_1.renderExpoHarmonyCameraTurboModule,
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
function renderCapabilityModuleShim(capability) {
|
|
47
|
+
const renderer = CAPABILITY_SHIM_RENDERERS[capability.packageName];
|
|
48
|
+
if (!renderer) {
|
|
49
|
+
return renderUnsupportedCapabilityShim(capability);
|
|
50
|
+
}
|
|
51
|
+
return capability.runtimeMode !== 'shim'
|
|
52
|
+
? renderer.adapter(capability)
|
|
53
|
+
: renderer.preview(capability);
|
|
54
|
+
}
|
|
55
|
+
function renderUnsupportedCapabilityShim(capability) {
|
|
56
|
+
return `'use strict';
|
|
57
|
+
|
|
58
|
+
const { CodedError } = require('expo-modules-core');
|
|
59
|
+
|
|
60
|
+
function createPreviewError() {
|
|
61
|
+
return new CodedError(
|
|
62
|
+
'ERR_EXPO_HARMONY_PREVIEW',
|
|
63
|
+
'${capability.packageName} is classified as ${capability.supportTier} for Harmony, but no managed runtime shim has been wired yet.',
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function unavailable() {
|
|
68
|
+
throw createPreviewError();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = new Proxy(
|
|
72
|
+
{},
|
|
73
|
+
{
|
|
74
|
+
get(_target, propertyName) {
|
|
75
|
+
if (propertyName === '__esModule') {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return unavailable;
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
`;
|
|
84
|
+
}
|