@callstack/brownfield-cli 3.9.0 → 3.11.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/CHANGELOG.md +18 -0
- package/dist/brownfield/commands/packageIos.d.ts +1 -0
- package/dist/brownfield/commands/packageIos.d.ts.map +1 -1
- package/dist/brownfield/commands/packageIos.js +97 -6
- package/dist/brownfield/utils/copyDebugBundleToSimulatorSlice.d.ts +8 -0
- package/dist/brownfield/utils/copyDebugBundleToSimulatorSlice.d.ts.map +1 -0
- package/dist/brownfield/utils/copyDebugBundleToSimulatorSlice.js +21 -0
- package/dist/brownfield/utils/createLocalSpmPackage.d.ts +10 -0
- package/dist/brownfield/utils/createLocalSpmPackage.d.ts.map +1 -0
- package/dist/brownfield/utils/createLocalSpmPackage.js +138 -0
- package/dist/brownfield/utils/prepareLocalSpmArtifacts.d.ts +8 -0
- package/dist/brownfield/utils/prepareLocalSpmArtifacts.d.ts.map +1 -0
- package/dist/brownfield/utils/prepareLocalSpmArtifacts.js +77 -0
- package/dist/brownfield/utils/project.d.ts +1 -0
- package/dist/brownfield/utils/project.d.ts.map +1 -1
- package/dist/brownfield/utils/project.js +8 -0
- package/dist/brownfield/utils/resolvePackagedFrameworkName.d.ts +14 -0
- package/dist/brownfield/utils/resolvePackagedFrameworkName.d.ts.map +1 -0
- package/dist/brownfield/utils/resolvePackagedFrameworkName.js +61 -0
- package/dist/brownfield/utils/supportsPrebuiltRNCore.d.ts +18 -0
- package/dist/brownfield/utils/supportsPrebuiltRNCore.d.ts.map +1 -0
- package/dist/brownfield/utils/supportsPrebuiltRNCore.js +36 -0
- package/package.json +6 -6
- package/src/brownfield/commands/packageIos.ts +288 -129
- package/src/brownfield/utils/copyDebugBundleToSimulatorSlice.ts +58 -0
- package/src/brownfield/utils/createLocalSpmPackage.ts +208 -0
- package/src/brownfield/utils/prepareLocalSpmArtifacts.ts +117 -0
- package/src/brownfield/utils/project.ts +9 -0
- package/src/brownfield/utils/resolvePackagedFrameworkName.ts +98 -0
- package/src/brownfield/utils/supportsPrebuiltRNCore.ts +67 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @callstack/brownfield-cli
|
|
2
2
|
|
|
3
|
+
## 3.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#358](https://github.com/callstack/react-native-brownfield/pull/358) [`3715ac7`](https://github.com/callstack/react-native-brownfield/commit/3715ac7783000756ef1c66ecfe24a85c5e43abab) Thanks [@adamTrz](https://github.com/adamTrz)! - Add `--add-spm-package` to `brownfield package:ios` so packaging can also generate a local Swift Package Manager wrapper around the produced XCFrameworks, including a generated `Package.swift`, `README.md`, and Xcode integration instructions. Fail fast when Debug packaging cannot resolve the app framework name while local SPM output is requested.
|
|
8
|
+
|
|
9
|
+
- [#364](https://github.com/callstack/react-native-brownfield/pull/364) [`05c557d`](https://github.com/callstack/react-native-brownfield/commit/05c557da9e2b6fca02e6e1a0b0fe71a909bab15f) Thanks [@hurali97](https://github.com/hurali97)! - keep only one reference of xcframeworks when spm enabled
|
|
10
|
+
|
|
11
|
+
## 3.10.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- [#323](https://github.com/callstack/react-native-brownfield/pull/323) [`3456d3a`](https://github.com/callstack/react-native-brownfield/commit/3456d3aded18002475def4b79889979e76e1db5e) Thanks [@artus9033](https://github.com/artus9033)! - Support RN prebuilts in Brownfield, by default enabled in RN >= 0.84, opt-in in RN 0.83; or in Expo 55+ (Expo 54 is not supported).
|
|
16
|
+
|
|
17
|
+
Add `--use-prebuilt-rn-core` to `brownfield package:ios` so callers can opt into or out of React Native Apple prebuilt binaries; omitting the flag defers to version-aware defaults handled by Rock. The CLI rejects `--use-prebuilt-rn-core` when React Native is older than 0.81 or when the project is Expo SDK older than 55.
|
|
18
|
+
|
|
19
|
+
Fix brownfield framework dylib install names to use @rpath instead of hardcoded paths.
|
|
20
|
+
|
|
3
21
|
## 3.9.0
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { ExampleUsage } from '../../shared/index.js';
|
|
3
|
+
export declare function parseUsePrebuiltRnCoreArgument(value: string | boolean): boolean;
|
|
3
4
|
export declare const packageIosCommand: Command;
|
|
4
5
|
export declare const packageIosExample: ExampleUsage;
|
|
5
6
|
//# sourceMappingURL=packageIos.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageIos.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/packageIos.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"packageIos.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/packageIos.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAK5C,OAAO,EAGL,YAAY,EACb,MAAM,uBAAuB,CAAC;AAe/B,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,MAAM,GAAG,OAAO,GACtB,OAAO,CAcT;AAqBD,eAAO,MAAM,iBAAiB,SA8P3B,CAAC;AAEJ,eAAO,MAAM,iBAAiB,cAG7B,CAAC"}
|
|
@@ -2,22 +2,69 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { getBuildOptions, mergeFrameworks, } from '@rock-js/platform-apple-helpers';
|
|
4
4
|
import { packageIosAction } from '@rock-js/plugin-brownfield-ios';
|
|
5
|
-
import { colorLink, getReactNativeVersion, logger, relativeToCwd, } from '@rock-js/tools';
|
|
6
|
-
import { Command } from 'commander';
|
|
5
|
+
import { RockError, colorLink, getReactNativeVersion, logger, relativeToCwd, } from '@rock-js/tools';
|
|
6
|
+
import { Command, Option } from 'commander';
|
|
7
7
|
import { runExpoPrebuildIfNeeded } from '../utils/expo.js';
|
|
8
8
|
import { getProjectInfo } from '../utils/project.js';
|
|
9
|
+
import { supportsPrebuiltRNCore } from '../utils/supportsPrebuiltRNCore.js';
|
|
9
10
|
import { actionRunner, curryOptions, ExampleUsage, } from '../../shared/index.js';
|
|
10
11
|
import { runBrownieCodegenIfApplicable } from '../../brownie/helpers/runBrownieCodegenIfApplicable.js';
|
|
11
12
|
import { runNavigationCodegenIfApplicable } from '../../navigation/helpers/runNavigationCodegenIfApplicable.js';
|
|
13
|
+
import { copyDebugBundleToSimulatorSlice } from '../utils/copyDebugBundleToSimulatorSlice.js';
|
|
14
|
+
import { resolvePackagedFrameworkName } from '../utils/resolvePackagedFrameworkName.js';
|
|
12
15
|
import { stripFrameworkBinary } from '../utils/stripFrameworkBinary.js';
|
|
16
|
+
import { createLocalSpmPackage } from '../utils/createLocalSpmPackage.js';
|
|
17
|
+
/** Help text for `--use-prebuilt-rn-core` (keep in sync with docs/docs/docs/getting-started/ios.mdx, "React Native Prebuilts" section). */
|
|
18
|
+
const USE_PREBUILT_RN_CORE_HELP = 'Whether the Xcode build for packaging should use React Native Apple prebuilt binaries (via CocoaPods). ' +
|
|
19
|
+
'If you omit this flag, Brownfield follows version-aware defaults: for React Native 0.84 and newer, prebuilts are enabled by default; for RN 0.83, they are disabled unless you opt in. ' +
|
|
20
|
+
'Pass true or false to force either behavior. Use the flag without a value as shorthand for true (same as `--use-prebuilt-rn-core true`). ' +
|
|
21
|
+
'See the Brownfield iOS guide for details: https://oss.callstack.com/react-native-brownfield/docs/getting-started/ios#react-native-prebuilts';
|
|
22
|
+
export function parseUsePrebuiltRnCoreArgument(value) {
|
|
23
|
+
if (typeof value === 'boolean') {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
const normalized = value.trim().toLowerCase();
|
|
27
|
+
if (normalized === 'true' || normalized === '1') {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
if (normalized === 'false' || normalized === '0') {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
throw new RockError(`Invalid value for --use-prebuilt-rn-core: expected true or false, received "${value}"`);
|
|
34
|
+
}
|
|
35
|
+
function getPackagedFrameworkResolutionFailureMessage({ resolution, candidates, }) {
|
|
36
|
+
return resolution === 'ambiguous'
|
|
37
|
+
? `found multiple bundled framework candidates (${candidates?.join(', ') ?? 'none'}); pass --scheme explicitly`
|
|
38
|
+
: 'could not resolve the packaged framework output automatically; pass --scheme explicitly';
|
|
39
|
+
}
|
|
13
40
|
export const packageIosCommand = curryOptions(new Command('package:ios').description('Build iOS XCFramework'), getBuildOptions({ platformName: 'ios' }).map((option) => option.name.startsWith('--build-folder')
|
|
14
41
|
? {
|
|
15
42
|
...option,
|
|
16
43
|
description: option.description +
|
|
17
44
|
" By default, the '.brownfield/build' path will be used.",
|
|
18
45
|
}
|
|
19
|
-
: option))
|
|
46
|
+
: option))
|
|
47
|
+
.addOption(new Option('--use-prebuilt-rn-core [bool]', USE_PREBUILT_RN_CORE_HELP)
|
|
48
|
+
.preset(true)
|
|
49
|
+
.argParser(parseUsePrebuiltRnCoreArgument))
|
|
50
|
+
.addOption(new Option('--add-spm-package', 'Generate a local Swift Package Manager manifest next to the packaged XCFramework outputs'))
|
|
51
|
+
.action(actionRunner(async (options) => {
|
|
20
52
|
const { projectRoot, platformConfig, userConfig } = getProjectInfo('ios');
|
|
53
|
+
const prebuiltRNCoreSupport = supportsPrebuiltRNCore({ projectRoot });
|
|
54
|
+
// version-aware default when the flag is omitted (see ios.mdx "React Native Prebuilts")
|
|
55
|
+
options.usePrebuiltRnCore ??= prebuiltRNCoreSupport.supported
|
|
56
|
+
? prebuiltRNCoreSupport.enabledByDefault
|
|
57
|
+
: false;
|
|
58
|
+
if (prebuiltRNCoreSupport) {
|
|
59
|
+
logger.info(`${options.usePrebuiltRnCore ? 'Using' : 'Not using'} prebuilt RN core`);
|
|
60
|
+
if (!prebuiltRNCoreSupport.enabledByDefault &&
|
|
61
|
+
!options.usePrebuiltRnCore) {
|
|
62
|
+
logger.info('Your environment supports prebuilt RN Core as an opt-in feature, but it is disabled by default. Pass --use-prebuilt-rn-core to enable it.');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (options.usePrebuiltRnCore && !prebuiltRNCoreSupport.supported) {
|
|
66
|
+
throw new RockError(prebuiltRNCoreSupport.reason);
|
|
67
|
+
}
|
|
21
68
|
await runExpoPrebuildIfNeeded({ projectRoot, platform: 'ios' });
|
|
22
69
|
if (!userConfig.project.ios) {
|
|
23
70
|
throw new Error('iOS project not found.');
|
|
@@ -35,6 +82,7 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
|
|
|
35
82
|
dotBrownfieldDir = path.join(projectRoot, dotBrownfieldDir);
|
|
36
83
|
}
|
|
37
84
|
options.buildFolder ??= path.join(dotBrownfieldDir, 'build');
|
|
85
|
+
options.verbose ??= logger.isVerbose();
|
|
38
86
|
// The new_architecture.rb script scans Info.plist and fails on binary plist files,
|
|
39
87
|
// which is the case for our XCFrameworks.
|
|
40
88
|
// We're reusing the "build" directory which is excluded from the scan.
|
|
@@ -50,10 +98,46 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
|
|
|
50
98
|
// e.g. '0.82' (note the missing patch component),
|
|
51
99
|
// therefore we resolve it manually from RN's package.json using Rock's utils
|
|
52
100
|
reactNativeVersion: getReactNativeVersion(projectRoot),
|
|
53
|
-
usePrebuiltRNCore: false, // for brownfield, it is required to build RN from source
|
|
54
101
|
packageDir, // the output directory for artifacts
|
|
55
102
|
skipCache: true, // cache is dependent on existence of Rock config file
|
|
103
|
+
usePrebuiltRNCore: options.usePrebuiltRnCore,
|
|
56
104
|
}, platformConfig);
|
|
105
|
+
const productsPath = path.join(options.buildFolder, 'Build', 'Products');
|
|
106
|
+
const { frameworkName, resolution, candidates } = resolvePackagedFrameworkName({
|
|
107
|
+
explicitScheme: options.scheme,
|
|
108
|
+
productsPath,
|
|
109
|
+
configuration,
|
|
110
|
+
});
|
|
111
|
+
if (!frameworkName && options.addSpmPackage) {
|
|
112
|
+
throw new RockError(`Cannot generate local SPM package: ${getPackagedFrameworkResolutionFailureMessage({
|
|
113
|
+
resolution,
|
|
114
|
+
candidates,
|
|
115
|
+
})}`);
|
|
116
|
+
}
|
|
117
|
+
if (frameworkName) {
|
|
118
|
+
copyDebugBundleToSimulatorSlice({
|
|
119
|
+
productsPath,
|
|
120
|
+
configuration,
|
|
121
|
+
frameworkName,
|
|
122
|
+
});
|
|
123
|
+
if (configuration.includes('Debug')) {
|
|
124
|
+
// Re-merge only Debug frameworks so the simulator slice includes main.jsbundle.
|
|
125
|
+
await mergeFrameworks({
|
|
126
|
+
sourceDir: userConfig.project.ios.sourceDir,
|
|
127
|
+
frameworkPaths: [
|
|
128
|
+
path.join(productsPath, `${configuration}-iphoneos`, `${frameworkName}.framework`),
|
|
129
|
+
path.join(productsPath, `${configuration}-iphonesimulator`, `${frameworkName}.framework`),
|
|
130
|
+
],
|
|
131
|
+
outputPath: path.join(packageDir, `${frameworkName}.xcframework`),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else if (configuration.includes('Debug')) {
|
|
136
|
+
logger.warn(`Skipping Debug simulator JS bundle copy: ${getPackagedFrameworkResolutionFailureMessage({
|
|
137
|
+
resolution,
|
|
138
|
+
candidates,
|
|
139
|
+
})}`);
|
|
140
|
+
}
|
|
57
141
|
const reactBrownfieldXcframeworkPath = path.join(packageDir, 'ReactBrownfield.xcframework');
|
|
58
142
|
if (fs.existsSync(reactBrownfieldXcframeworkPath)) {
|
|
59
143
|
// Strip the binary from ReactBrownfield.xcframework to make it interface-only.
|
|
@@ -62,7 +146,6 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
|
|
|
62
146
|
stripFrameworkBinary(reactBrownfieldXcframeworkPath);
|
|
63
147
|
}
|
|
64
148
|
if (hasBrownie) {
|
|
65
|
-
const productsPath = path.join(options.buildFolder, 'Build', 'Products');
|
|
66
149
|
const brownieOutputPath = path.join(packageDir, 'Brownie.xcframework');
|
|
67
150
|
await mergeFrameworks({
|
|
68
151
|
sourceDir: userConfig.project.ios.sourceDir,
|
|
@@ -79,7 +162,6 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
|
|
|
79
162
|
logger.success(`Brownie.xcframework created at ${colorLink(relativeToCwd(brownieOutputPath))}`);
|
|
80
163
|
}
|
|
81
164
|
if (hasNavigation) {
|
|
82
|
-
const productsPath = path.join(options.buildFolder, 'Build', 'Products');
|
|
83
165
|
const brownfieldNavigationOutputPath = path.join(packageDir, 'BrownfieldNavigation.xcframework');
|
|
84
166
|
await mergeFrameworks({
|
|
85
167
|
sourceDir: userConfig.project.ios.sourceDir,
|
|
@@ -92,5 +174,14 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
|
|
|
92
174
|
stripFrameworkBinary(brownfieldNavigationOutputPath);
|
|
93
175
|
logger.success(`BrownfieldNavigation.xcframework created at ${colorLink(relativeToCwd(brownfieldNavigationOutputPath))}`);
|
|
94
176
|
}
|
|
177
|
+
if (options.addSpmPackage) {
|
|
178
|
+
const { packageManifestPath } = createLocalSpmPackage({
|
|
179
|
+
packageDir,
|
|
180
|
+
frameworkName: frameworkName ?? undefined,
|
|
181
|
+
});
|
|
182
|
+
logger.success(`Local SPM package manifest created at ${colorLink(relativeToCwd(packageManifestPath))}`);
|
|
183
|
+
logger.info(`Add the local package folder in Xcode: ${colorLink(relativeToCwd(packageDir))}`);
|
|
184
|
+
logger.info("In Xcode, choose File > Add Package Dependencies..., click Add Local..., and select that folder.");
|
|
185
|
+
}
|
|
95
186
|
}));
|
|
96
187
|
export const packageIosExample = new ExampleUsage('package:ios --scheme BrownfieldLib --configuration Release', "Build iOS XCFramework for 'BrownfieldLib' scheme in Release configuration");
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface CopyDebugBundleToSimulatorSliceOptions {
|
|
2
|
+
productsPath: string;
|
|
3
|
+
configuration: string;
|
|
4
|
+
frameworkName: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function copyDebugBundleToSimulatorSlice({ productsPath, configuration, frameworkName, }: CopyDebugBundleToSimulatorSliceOptions): void;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=copyDebugBundleToSimulatorSlice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copyDebugBundleToSimulatorSlice.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/copyDebugBundleToSimulatorSlice.ts"],"names":[],"mappings":"AAKA,UAAU,sCAAsC;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,+BAA+B,CAAC,EAC9C,YAAY,EACZ,aAAa,EACb,aAAa,GACd,EAAE,sCAAsC,QA0CxC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { colorLink, logger, relativeToCwd } from '@rock-js/tools';
|
|
4
|
+
export function copyDebugBundleToSimulatorSlice({ productsPath, configuration, frameworkName, }) {
|
|
5
|
+
if (!configuration.includes('Debug')) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const deviceBundlePath = path.join(productsPath, `${configuration}-iphoneos`, `${frameworkName}.framework`, 'main.jsbundle');
|
|
9
|
+
const simulatorFrameworkPath = path.join(productsPath, `${configuration}-iphonesimulator`, `${frameworkName}.framework`);
|
|
10
|
+
const simulatorBundlePath = path.join(simulatorFrameworkPath, 'main.jsbundle');
|
|
11
|
+
if (!fs.existsSync(deviceBundlePath)) {
|
|
12
|
+
logger.warn(`Skipping simulator JS bundle copy: missing ${relativeToCwd(deviceBundlePath)}`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (!fs.existsSync(simulatorFrameworkPath)) {
|
|
16
|
+
logger.warn(`Skipping simulator JS bundle copy: missing ${relativeToCwd(simulatorFrameworkPath)}`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
fs.copyFileSync(deviceBundlePath, simulatorBundlePath);
|
|
20
|
+
logger.success(`Copied Debug JS bundle to simulator slice at ${colorLink(relativeToCwd(simulatorBundlePath))}`);
|
|
21
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type CreateLocalSpmPackageOptions = {
|
|
2
|
+
packageDir: string;
|
|
3
|
+
frameworkName?: string;
|
|
4
|
+
};
|
|
5
|
+
type CreateLocalSpmPackageResult = {
|
|
6
|
+
packageManifestPath: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function createLocalSpmPackage({ packageDir, frameworkName, }: CreateLocalSpmPackageOptions): CreateLocalSpmPackageResult;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=createLocalSpmPackage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createLocalSpmPackage.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/createLocalSpmPackage.ts"],"names":[],"mappings":"AAQA,KAAK,4BAA4B,GAAG;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAuJF,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,aAAa,GACd,EAAE,4BAA4B,GAAG,2BAA2B,CAsC5D"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { prepareLocalSpmArtifacts, SPM_ARTIFACTS_DIR_NAME, } from './prepareLocalSpmArtifacts.js';
|
|
4
|
+
const RESERVED_FRAMEWORK_NAMES = new Set([
|
|
5
|
+
'hermes',
|
|
6
|
+
'hermesvm',
|
|
7
|
+
'ReactBrownfield',
|
|
8
|
+
'Brownie',
|
|
9
|
+
'BrownfieldNavigation',
|
|
10
|
+
'React',
|
|
11
|
+
'ReactNativeDependencies',
|
|
12
|
+
]);
|
|
13
|
+
function requireXcframework(packageDir, name) {
|
|
14
|
+
const xcframeworkPath = path.join(packageDir, `${name}.xcframework`);
|
|
15
|
+
if (!fs.existsSync(xcframeworkPath)) {
|
|
16
|
+
throw new Error(`Missing required XCFramework: ${name}.xcframework`);
|
|
17
|
+
}
|
|
18
|
+
return name;
|
|
19
|
+
}
|
|
20
|
+
function optionalXcframework(packageDir, name) {
|
|
21
|
+
return fs.existsSync(path.join(packageDir, `${name}.xcframework`))
|
|
22
|
+
? name
|
|
23
|
+
: null;
|
|
24
|
+
}
|
|
25
|
+
function requireHermesXcframework(packageDir) {
|
|
26
|
+
return (optionalXcframework(packageDir, 'hermesvm') ??
|
|
27
|
+
requireXcframework(packageDir, 'hermes'));
|
|
28
|
+
}
|
|
29
|
+
function resolveAppFrameworkName(packageDir, explicitFrameworkName) {
|
|
30
|
+
if (explicitFrameworkName) {
|
|
31
|
+
return requireXcframework(packageDir, explicitFrameworkName);
|
|
32
|
+
}
|
|
33
|
+
const candidates = fs
|
|
34
|
+
.readdirSync(packageDir, { withFileTypes: true })
|
|
35
|
+
.filter((entry) => entry.isDirectory() &&
|
|
36
|
+
entry.name.endsWith('.xcframework') &&
|
|
37
|
+
!RESERVED_FRAMEWORK_NAMES.has(path.basename(entry.name, '.xcframework')))
|
|
38
|
+
.map((entry) => path.basename(entry.name, '.xcframework'))
|
|
39
|
+
.sort();
|
|
40
|
+
if (candidates.length === 1 && candidates[0]) {
|
|
41
|
+
return candidates[0];
|
|
42
|
+
}
|
|
43
|
+
if (candidates.length === 0) {
|
|
44
|
+
throw new Error('Could not resolve the packaged app XCFramework automatically. Pass --scheme explicitly when packaging.');
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`Found multiple packaged app XCFramework candidates (${candidates.join(', ')}). Pass --scheme explicitly when packaging.`);
|
|
47
|
+
}
|
|
48
|
+
function renderPackageSwift({ packageName, libraryName, targetNames, }) {
|
|
49
|
+
const binaryTargets = targetNames
|
|
50
|
+
.map((targetName) => ` .binaryTarget(name: "${targetName}", path: "./${SPM_ARTIFACTS_DIR_NAME}/${targetName}.xcframework")`)
|
|
51
|
+
.join(',\n');
|
|
52
|
+
const targetDependencies = targetNames
|
|
53
|
+
.map((targetName) => `"${targetName}"`)
|
|
54
|
+
.join(', ');
|
|
55
|
+
return `// swift-tools-version: 5.9
|
|
56
|
+
|
|
57
|
+
import PackageDescription
|
|
58
|
+
|
|
59
|
+
let package = Package(
|
|
60
|
+
name: "${packageName}",
|
|
61
|
+
platforms: [
|
|
62
|
+
.iOS(.v14),
|
|
63
|
+
],
|
|
64
|
+
products: [
|
|
65
|
+
.library(name: "${libraryName}", targets: [${targetDependencies}]),
|
|
66
|
+
],
|
|
67
|
+
targets: [
|
|
68
|
+
${binaryTargets}
|
|
69
|
+
]
|
|
70
|
+
)
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
function renderReadme({ packageName, libraryName, targetNames, }) {
|
|
74
|
+
const frameworks = targetNames.map((targetName) => `- \`${targetName}\``).join('\n');
|
|
75
|
+
return `# ${packageName}
|
|
76
|
+
|
|
77
|
+
This is a generated local Swift Package Manager package for the packaged React Native brownfield artifacts.
|
|
78
|
+
|
|
79
|
+
## Product
|
|
80
|
+
|
|
81
|
+
- Library product: \`${libraryName}\`
|
|
82
|
+
|
|
83
|
+
## Included Binary Targets
|
|
84
|
+
|
|
85
|
+
${frameworks}
|
|
86
|
+
|
|
87
|
+
## How To Use
|
|
88
|
+
|
|
89
|
+
1. In Xcode, choose **File > Add Package Dependencies...**
|
|
90
|
+
2. Click **Add Local...**
|
|
91
|
+
3. Select this folder, the one containing \`Package.swift\` and the \`spm-artifacts\` directory
|
|
92
|
+
4. Add the \`${libraryName}\` library product to your app target
|
|
93
|
+
|
|
94
|
+
## Troubleshooting
|
|
95
|
+
|
|
96
|
+
If Xcode builds your host app but the simulator installation fails, check the host app target first:
|
|
97
|
+
|
|
98
|
+
- Make sure the target still includes its app entry point source files, such as \`App.swift\`, \`SceneDelegate\`, \`AppDelegate\`, or equivalent startup files
|
|
99
|
+
- Make sure the host target uses the same React Native module name that the packaged app registers for its brownfield surface. This repo's example apps use \`RNApp\` for both the plain React Native and Expo variants
|
|
100
|
+
- If the install error says the app is "missing its bundle executable", the host app target produced an invalid \`.app\` bundle and the issue is not in this generated SPM package
|
|
101
|
+
- If you are migrating an existing target from direct \`*.xcframework\` linking to local SPM, remove the old direct XCFramework references before building again
|
|
102
|
+
|
|
103
|
+
This folder is generated by \`brownfield package:ios --add-spm-package\`. Re-run that command whenever the packaged XCFrameworks change so this package stays in sync.
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
export function createLocalSpmPackage({ packageDir, frameworkName, }) {
|
|
107
|
+
const resolvedFrameworkName = resolveAppFrameworkName(packageDir, frameworkName);
|
|
108
|
+
const targetNames = [
|
|
109
|
+
resolvedFrameworkName,
|
|
110
|
+
requireHermesXcframework(packageDir),
|
|
111
|
+
requireXcframework(packageDir, 'ReactBrownfield'),
|
|
112
|
+
optionalXcframework(packageDir, 'Brownie'),
|
|
113
|
+
optionalXcframework(packageDir, 'BrownfieldNavigation'),
|
|
114
|
+
optionalXcframework(packageDir, 'React'),
|
|
115
|
+
optionalXcframework(packageDir, 'ReactNativeDependencies'),
|
|
116
|
+
].filter((targetName) => targetName !== null);
|
|
117
|
+
const packageManifestPath = path.join(packageDir, 'Package.swift');
|
|
118
|
+
const readmePath = path.join(packageDir, 'README.md');
|
|
119
|
+
prepareLocalSpmArtifacts({
|
|
120
|
+
packageDir,
|
|
121
|
+
targetNames,
|
|
122
|
+
});
|
|
123
|
+
const manifest = renderPackageSwift({
|
|
124
|
+
packageName: `${resolvedFrameworkName}Package`,
|
|
125
|
+
libraryName: resolvedFrameworkName,
|
|
126
|
+
targetNames,
|
|
127
|
+
});
|
|
128
|
+
const readme = renderReadme({
|
|
129
|
+
packageName: `${resolvedFrameworkName}Package`,
|
|
130
|
+
libraryName: resolvedFrameworkName,
|
|
131
|
+
targetNames,
|
|
132
|
+
});
|
|
133
|
+
fs.writeFileSync(packageManifestPath, manifest, 'utf8');
|
|
134
|
+
fs.writeFileSync(readmePath, readme, 'utf8');
|
|
135
|
+
return {
|
|
136
|
+
packageManifestPath,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type PrepareLocalSpmArtifactsOptions = {
|
|
2
|
+
packageDir: string;
|
|
3
|
+
targetNames: string[];
|
|
4
|
+
};
|
|
5
|
+
export declare const SPM_ARTIFACTS_DIR_NAME = "spm-artifacts";
|
|
6
|
+
export declare function prepareLocalSpmArtifacts({ packageDir, targetNames, }: PrepareLocalSpmArtifactsOptions): string;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=prepareLocalSpmArtifacts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepareLocalSpmArtifacts.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/prepareLocalSpmArtifacts.ts"],"names":[],"mappings":"AAIA,KAAK,+BAA+B,GAAG;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AAyFtD,wBAAgB,wBAAwB,CAAC,EACvC,UAAU,EACV,WAAW,GACZ,EAAE,+BAA+B,UAejC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
export const SPM_ARTIFACTS_DIR_NAME = 'spm-artifacts';
|
|
5
|
+
function removeCodeSignatureArtifacts(dirPath) {
|
|
6
|
+
for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
|
|
7
|
+
const entryPath = path.join(dirPath, entry.name);
|
|
8
|
+
if (entry.isDirectory()) {
|
|
9
|
+
if (entry.name === '_CodeSignature') {
|
|
10
|
+
fs.rmSync(entryPath, { recursive: true, force: true });
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
removeCodeSignatureArtifacts(entryPath);
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (entry.name === 'CodeResources') {
|
|
17
|
+
fs.rmSync(entryPath, { force: true });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function resolveFrameworkExecutablePath(frameworkDir, frameworkName) {
|
|
22
|
+
const directExecutablePath = path.join(frameworkDir, frameworkName);
|
|
23
|
+
if (fs.existsSync(directExecutablePath)) {
|
|
24
|
+
return directExecutablePath;
|
|
25
|
+
}
|
|
26
|
+
const versionedExecutablePath = path.join(frameworkDir, 'Versions', 'Current', frameworkName);
|
|
27
|
+
if (fs.existsSync(versionedExecutablePath)) {
|
|
28
|
+
return versionedExecutablePath;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function removeExecutableSignature(executablePath) {
|
|
33
|
+
try {
|
|
34
|
+
execFileSync('codesign', ['--remove-signature', executablePath], {
|
|
35
|
+
stdio: 'pipe',
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (error instanceof Error &&
|
|
40
|
+
error.message.includes('code object is not signed at all')) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function normalizeCopiedXcframeworkSignature(xcframeworkPath) {
|
|
47
|
+
removeCodeSignatureArtifacts(xcframeworkPath);
|
|
48
|
+
for (const sliceName of fs.readdirSync(xcframeworkPath)) {
|
|
49
|
+
const slicePath = path.join(xcframeworkPath, sliceName);
|
|
50
|
+
if (!fs.statSync(slicePath).isDirectory()) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
for (const entry of fs.readdirSync(slicePath)) {
|
|
54
|
+
if (!entry.endsWith('.framework')) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const frameworkName = path.basename(entry, '.framework');
|
|
58
|
+
const frameworkDir = path.join(slicePath, entry);
|
|
59
|
+
const executablePath = resolveFrameworkExecutablePath(frameworkDir, frameworkName);
|
|
60
|
+
if (executablePath) {
|
|
61
|
+
removeExecutableSignature(executablePath);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function prepareLocalSpmArtifacts({ packageDir, targetNames, }) {
|
|
67
|
+
const spmArtifactsDir = path.join(packageDir, SPM_ARTIFACTS_DIR_NAME);
|
|
68
|
+
fs.rmSync(spmArtifactsDir, { recursive: true, force: true });
|
|
69
|
+
fs.mkdirSync(spmArtifactsDir, { recursive: true });
|
|
70
|
+
for (const targetName of targetNames) {
|
|
71
|
+
const sourcePath = path.join(packageDir, `${targetName}.xcframework`);
|
|
72
|
+
const destinationPath = path.join(spmArtifactsDir, `${targetName}.xcframework`);
|
|
73
|
+
fs.renameSync(sourcePath, destinationPath);
|
|
74
|
+
normalizeCopiedXcframeworkSignature(destinationPath);
|
|
75
|
+
}
|
|
76
|
+
return spmArtifactsDir;
|
|
77
|
+
}
|
|
@@ -14,6 +14,7 @@ export declare function getExpoConfigIfIsExpo(projectRoot: string): ExpoProjectC
|
|
|
14
14
|
* @returns Whether the project is an Expo project
|
|
15
15
|
*/
|
|
16
16
|
export declare function isExpoProject(projectRoot: string): boolean;
|
|
17
|
+
export declare function getExpoSdkMajor(projectRoot: string): number | null;
|
|
17
18
|
/**
|
|
18
19
|
* Fills the RNC CLI project config from the Expo config by mutating the passed in `options.projectConfig` object in place
|
|
19
20
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/project.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,UAAU,EACX,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAKjE,OAAO,EAEL,KAAK,aAAa,IAAI,iBAAiB,EACxC,MAAM,cAAc,CAAC;AAQtB;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,4BAMxD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAc1D;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,EAC9C,aAAa,EACb,UAAU,EAAE,EAAE,GAAG,EAAE,EACnB,WAAW,GACZ,EAAE;IACD,8CAA8C;IAC9C,aAAa,EAAE,aAAa,CAAC;IAE7B,8BAA8B;IAC9B,UAAU,EAAE,iBAAiB,CAAC;IAE9B,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB,QAuBA;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,SAAS,KAAK,GAAG,SAAS,EAC/D,QAAQ,EAAE,QAAQ,GACjB;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,cAAc,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;CACzC,CAeA;AAED,wBAAgB,aAAa,CAAC,EAC5B,WAAW,EACX,QAAQ,GACT,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;CAC7B,GAAG,UAAU,CAuBb;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,eAAe,EACrB,aAAa,EAAE,oBAAoB;;;EAQpC"}
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/project.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,UAAU,EACX,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAKjE,OAAO,EAEL,KAAK,aAAa,IAAI,iBAAiB,EACxC,MAAM,cAAc,CAAC;AAQtB;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,4BAMxD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAc1D;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,EAC9C,aAAa,EACb,UAAU,EAAE,EAAE,GAAG,EAAE,EACnB,WAAW,GACZ,EAAE;IACD,8CAA8C;IAC9C,aAAa,EAAE,aAAa,CAAC;IAE7B,8BAA8B;IAC9B,UAAU,EAAE,iBAAiB,CAAC;IAE9B,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB,QAuBA;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,SAAS,KAAK,GAAG,SAAS,EAC/D,QAAQ,EAAE,QAAQ,GACjB;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,cAAc,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;CACzC,CAeA;AAED,wBAAgB,aAAa,CAAC,EAC5B,WAAW,EACX,QAAQ,GACT,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;CAC7B,GAAG,UAAU,CAuBb;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,eAAe,EACrB,aAAa,EAAE,oBAAoB;;;EAQpC"}
|
|
@@ -36,6 +36,14 @@ export function isExpoProject(projectRoot) {
|
|
|
36
36
|
['dependencies', 'peerDependencies', 'devDependencies'].some((key) => JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))[key]?.expo);
|
|
37
37
|
return hasExpoConfig && dependsOnExpo;
|
|
38
38
|
}
|
|
39
|
+
export function getExpoSdkMajor(projectRoot) {
|
|
40
|
+
const rawExpoVersion = getExpoConfigIfIsExpo(projectRoot)?.exp.sdkVersion;
|
|
41
|
+
if (!rawExpoVersion) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const expoSdkMajor = parseInt(rawExpoVersion.split('.')[0], 10);
|
|
45
|
+
return Number.isFinite(expoSdkMajor) ? expoSdkMajor : null;
|
|
46
|
+
}
|
|
39
47
|
/**
|
|
40
48
|
* Fills the RNC CLI project config from the Expo config by mutating the passed in `options.projectConfig` object in place
|
|
41
49
|
*/
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type Resolution = 'explicit' | 'detected' | 'not_found' | 'ambiguous';
|
|
2
|
+
export interface ResolvePackagedFrameworkNameResult {
|
|
3
|
+
frameworkName: string | null;
|
|
4
|
+
resolution: Resolution;
|
|
5
|
+
candidates?: string[];
|
|
6
|
+
}
|
|
7
|
+
interface ResolvePackagedFrameworkNameOptions {
|
|
8
|
+
explicitScheme?: string;
|
|
9
|
+
productsPath: string;
|
|
10
|
+
configuration: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function resolvePackagedFrameworkName({ explicitScheme, productsPath, configuration, }: ResolvePackagedFrameworkNameOptions): ResolvePackagedFrameworkNameResult;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=resolvePackagedFrameworkName.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolvePackagedFrameworkName.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/resolvePackagedFrameworkName.ts"],"names":[],"mappings":"AAGA,KAAK,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC;AAEtE,MAAM,WAAW,kCAAkC;IACjD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,UAAU,mCAAmC;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AA4CD,wBAAgB,4BAA4B,CAAC,EAC3C,cAAc,EACd,YAAY,EACZ,aAAa,GACd,EAAE,mCAAmC,GAAG,kCAAkC,CAkC1E"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
function collectFrameworkCandidates(configurationProductsPath) {
|
|
4
|
+
if (!fs.existsSync(configurationProductsPath)) {
|
|
5
|
+
return [];
|
|
6
|
+
}
|
|
7
|
+
const discoveredFrameworks = new Set();
|
|
8
|
+
for (const entry of fs.readdirSync(configurationProductsPath, { withFileTypes: true })) {
|
|
9
|
+
const entryPath = path.join(configurationProductsPath, entry.name);
|
|
10
|
+
if (entry.isDirectory() && entry.name.endsWith('.framework')) {
|
|
11
|
+
const frameworkName = path.basename(entry.name, '.framework');
|
|
12
|
+
const bundlePath = path.join(entryPath, 'main.jsbundle');
|
|
13
|
+
if (fs.existsSync(bundlePath)) {
|
|
14
|
+
discoveredFrameworks.add(frameworkName);
|
|
15
|
+
}
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (!entry.isDirectory()) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
for (const nestedEntry of fs.readdirSync(entryPath, { withFileTypes: true })) {
|
|
22
|
+
if (!nestedEntry.isDirectory() || !nestedEntry.name.endsWith('.framework')) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const frameworkName = path.basename(nestedEntry.name, '.framework');
|
|
26
|
+
const bundlePath = path.join(entryPath, nestedEntry.name, 'main.jsbundle');
|
|
27
|
+
if (fs.existsSync(bundlePath)) {
|
|
28
|
+
discoveredFrameworks.add(frameworkName);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return [...discoveredFrameworks].sort();
|
|
33
|
+
}
|
|
34
|
+
export function resolvePackagedFrameworkName({ explicitScheme, productsPath, configuration, }) {
|
|
35
|
+
if (explicitScheme) {
|
|
36
|
+
return {
|
|
37
|
+
frameworkName: explicitScheme,
|
|
38
|
+
resolution: 'explicit',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const configurationProductsPath = path.join(productsPath, `${configuration}-iphoneos`);
|
|
42
|
+
const candidates = collectFrameworkCandidates(configurationProductsPath);
|
|
43
|
+
if (candidates.length === 1) {
|
|
44
|
+
return {
|
|
45
|
+
frameworkName: candidates[0] ?? null,
|
|
46
|
+
resolution: 'detected',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (candidates.length === 0) {
|
|
50
|
+
return {
|
|
51
|
+
frameworkName: null,
|
|
52
|
+
resolution: 'not_found',
|
|
53
|
+
candidates,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
frameworkName: null,
|
|
58
|
+
resolution: 'ambiguous',
|
|
59
|
+
candidates,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Minimum RN version that can opt in to prebuilts via `--use-prebuilt-rn-core`. */
|
|
2
|
+
export declare const MIN_REACT_NATIVE_VERSION_FOR_OPT_IN_PREBUILT_RN_CORE = "0.81.0";
|
|
3
|
+
/** Minimum RN version where Brownfield enables prebuilts by default (vanilla projects). */
|
|
4
|
+
export declare const MIN_REACT_NATIVE_VERSION_FOR_PREBUILT_RN_CORE_BY_DEFAULT = "0.84.0";
|
|
5
|
+
export declare const MIN_EXPO_SDK_MAJOR_FOR_PREBUILT_RN_CORE_BY_DEFAULT = 55;
|
|
6
|
+
export type PrebuiltRNCoreSupportResult = {
|
|
7
|
+
supported: true;
|
|
8
|
+
enabledByDefault: boolean;
|
|
9
|
+
reason?: never;
|
|
10
|
+
} | {
|
|
11
|
+
supported: false;
|
|
12
|
+
enabledByDefault?: never;
|
|
13
|
+
reason: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function supportsPrebuiltRNCore({ projectRoot, }: {
|
|
16
|
+
projectRoot: string;
|
|
17
|
+
}): PrebuiltRNCoreSupportResult;
|
|
18
|
+
//# sourceMappingURL=supportsPrebuiltRNCore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supportsPrebuiltRNCore.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/supportsPrebuiltRNCore.ts"],"names":[],"mappings":"AAIA,oFAAoF;AACpF,eAAO,MAAM,oDAAoD,WAAW,CAAC;AAC7E,2FAA2F;AAC3F,eAAO,MAAM,wDAAwD,WAC3D,CAAC;AACX,eAAO,MAAM,kDAAkD,KAAK,CAAC;AAErE,MAAM,MAAM,2BAA2B,GACnC;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,KAAK,CAAA;CAAE,GAC9D;IAAE,SAAS,EAAE,KAAK,CAAC;IAAC,gBAAgB,CAAC,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,wBAAgB,sBAAsB,CAAC,EACrC,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,2BAA2B,CA+C9B"}
|