@callstack/brownfield-cli 3.13.1 → 3.14.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/brownfield/commands/packageAndroid.d.ts.map +1 -1
  3. package/dist/brownfield/commands/packageAndroid.js +3 -1
  4. package/dist/brownfield/commands/packageIos.d.ts +1 -0
  5. package/dist/brownfield/commands/packageIos.d.ts.map +1 -1
  6. package/dist/brownfield/commands/packageIos.js +37 -4
  7. package/dist/brownfield/commands/publishAndroid.d.ts.map +1 -1
  8. package/dist/brownfield/commands/publishAndroid.js +3 -1
  9. package/dist/brownfield/utils/createLocalSpmPackage.d.ts +2 -1
  10. package/dist/brownfield/utils/createLocalSpmPackage.d.ts.map +1 -1
  11. package/dist/brownfield/utils/createLocalSpmPackage.js +8 -2
  12. package/dist/brownfield/utils/emitExpoSupportXcframeworks.d.ts +9 -0
  13. package/dist/brownfield/utils/emitExpoSupportXcframeworks.d.ts.map +1 -0
  14. package/dist/brownfield/utils/emitExpoSupportXcframeworks.js +70 -0
  15. package/dist/brownfield/utils/normalizeCopiedXcframework.d.ts +3 -0
  16. package/dist/brownfield/utils/normalizeCopiedXcframework.d.ts.map +1 -0
  17. package/dist/brownfield/utils/normalizeCopiedXcframework.js +64 -0
  18. package/dist/brownfield/utils/prepareLocalSpmArtifacts.d.ts.map +1 -1
  19. package/dist/brownfield/utils/prepareLocalSpmArtifacts.js +2 -63
  20. package/dist/brownfield/utils/project.d.ts.map +1 -1
  21. package/dist/brownfield/utils/project.js +20 -9
  22. package/dist/brownfield/utils/supportsPrebuiltExpo.d.ts +14 -0
  23. package/dist/brownfield/utils/supportsPrebuiltExpo.d.ts.map +1 -0
  24. package/dist/brownfield/utils/supportsPrebuiltExpo.js +20 -0
  25. package/dist/brownie/config.js +1 -1
  26. package/dist/config.d.ts +4 -1
  27. package/dist/config.d.ts.map +1 -1
  28. package/dist/config.js +10 -7
  29. package/dist/expoPluginConfig.d.ts +74 -0
  30. package/dist/expoPluginConfig.d.ts.map +1 -0
  31. package/dist/expoPluginConfig.js +103 -0
  32. package/dist/types.d.ts +94 -3
  33. package/dist/types.d.ts.map +1 -1
  34. package/package.json +12 -6
  35. package/schema.json +98 -9
  36. package/src/brownfield/commands/packageAndroid.ts +4 -1
  37. package/src/brownfield/commands/packageIos.ts +53 -4
  38. package/src/brownfield/commands/publishAndroid.ts +4 -1
  39. package/src/brownfield/utils/createLocalSpmPackage.ts +15 -1
  40. package/src/brownfield/utils/emitExpoSupportXcframeworks.ts +132 -0
  41. package/src/brownfield/utils/normalizeCopiedXcframework.ts +90 -0
  42. package/src/brownfield/utils/prepareLocalSpmArtifacts.ts +7 -90
  43. package/src/brownfield/utils/project.ts +33 -14
  44. package/src/brownfield/utils/supportsPrebuiltExpo.ts +34 -0
  45. package/src/brownie/config.ts +1 -1
  46. package/src/config.ts +12 -8
  47. package/src/expoPluginConfig.ts +195 -0
  48. package/src/types.ts +112 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @callstack/brownfield-cli
2
2
 
3
+ ## 3.14.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#360](https://github.com/callstack/react-native-brownfield/pull/360) [`10ff597`](https://github.com/callstack/react-native-brownfield/commit/10ff597c057c04aa093b4e5ae8c5334b169d3d56) Thanks [@adamTrz](https://github.com/adamTrz)! - Expo SDK 56 support
8
+
9
+ ## 3.13.2
10
+
11
+ ### Patch Changes
12
+
13
+ - [#398](https://github.com/callstack/react-native-brownfield/pull/398) [`8e90842`](https://github.com/callstack/react-native-brownfield/commit/8e90842291348dcb0542a6787f5cfbb1017532dd) Thanks [@artus9033](https://github.com/artus9033)! - feat: support brownfield unified config file in Expo
14
+
15
+ - [#402](https://github.com/callstack/react-native-brownfield/pull/402) [`3475c3d`](https://github.com/callstack/react-native-brownfield/commit/3475c3db375988ebd63ce01bfd93f4dbb1a55e8d) Thanks [@artus9033](https://github.com/artus9033)! - feat: support local BGP in Expo config plugin
16
+
17
+ - [#397](https://github.com/callstack/react-native-brownfield/pull/397) [`4088c01`](https://github.com/callstack/react-native-brownfield/commit/4088c01a069306565dd3e279d9132f5dbe861d0b) Thanks [@artus9033](https://github.com/artus9033)! - fix: generate config schema with descriptions, add more descriptions
18
+
3
19
  ## 3.13.1
4
20
 
5
21
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"packageAndroid.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/packageAndroid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,OAAO,EACL,YAAY,EAGb,MAAM,uBAAuB,CAAC;AAO/B,eAAO,MAAM,qBAAqB,SAuBjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,cAGjC,CAAC"}
1
+ {"version":3,"file":"packageAndroid.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/packageAndroid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,OAAO,EACL,YAAY,EAGb,MAAM,uBAAuB,CAAC;AAQ/B,eAAO,MAAM,qBAAqB,SAyBjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,cAGjC,CAAC"}
@@ -3,17 +3,19 @@ import { packageAarOptions, } from '@rock-js/platform-android';
3
3
  import { packageAarAction } from '@rock-js/plugin-brownfield-android';
4
4
  import { ExampleUsage, actionRunner, curryOptions, } from '../../shared/index.js';
5
5
  import { runExpoPrebuildIfNeeded } from '../utils/expo.js';
6
+ import { findProjectRoot } from '../utils/paths.js';
6
7
  import { getProjectInfo } from '../utils/project.js';
7
8
  import { runBrownieCodegenIfApplicable } from '../../brownie/helpers/runBrownieCodegenIfApplicable.js';
8
9
  import { runNavigationCodegenIfApplicable } from '../../navigation/helpers/runNavigationCodegenIfApplicable.js';
9
10
  import { mergeBrownfieldConfigWithOptions } from '../../config.js';
10
11
  export const packageAndroidCommand = curryOptions(new Command('package:android').description('Build Android AAR'), packageAarOptions).action(actionRunner(async (cliOptions) => {
11
12
  const options = mergeBrownfieldConfigWithOptions(cliOptions, 'android');
12
- const { projectRoot, platformConfig } = getProjectInfo('android');
13
+ const projectRoot = findProjectRoot();
13
14
  await runExpoPrebuildIfNeeded({
14
15
  projectRoot,
15
16
  platform: 'android',
16
17
  });
18
+ const { platformConfig } = getProjectInfo('android');
17
19
  await runBrownieCodegenIfApplicable(projectRoot, 'kotlin');
18
20
  await runNavigationCodegenIfApplicable(projectRoot);
19
21
  await packageAarAction({
@@ -1,6 +1,7 @@
1
1
  import { Command } from 'commander';
2
2
  import { ExampleUsage } from '../../shared/index.js';
3
3
  export declare function parseUsePrebuiltRnCoreArgument(value: string | boolean): boolean;
4
+ export declare function parseUsePrebuiltExpoArgument(value: string | boolean): boolean;
4
5
  export declare const packageIosCommand: Command;
5
6
  export declare const packageIosExample: ExampleUsage;
6
7
  //# sourceMappingURL=packageIos.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageIos.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/packageIos.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAK5C,OAAO,EAGL,YAAY,EACb,MAAM,uBAAuB,CAAC;AAiB/B,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,MAAM,GAAG,OAAO,GACtB,OAAO,CAcT;AAcD,eAAO,MAAM,iBAAiB,SAoQ3B,CAAC;AAEJ,eAAO,MAAM,iBAAiB,cAG7B,CAAC"}
1
+ {"version":3,"file":"packageIos.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/packageIos.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAO5C,OAAO,EAGL,YAAY,EACb,MAAM,uBAAuB,CAAC;AA4C/B,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,MAAM,GAAG,OAAO,GACtB,OAAO,CAET;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,GAAG,OAAO,GACtB,OAAO,CAET;AAcD,eAAO,MAAM,iBAAiB,SA8R3B,CAAC;AAEJ,eAAO,MAAM,iBAAiB,cAG7B,CAAC"}
@@ -5,7 +5,9 @@ import { packageIosAction } from '@rock-js/plugin-brownfield-ios';
5
5
  import { RockError, colorLink, getReactNativeVersion, logger, relativeToCwd, } from '@rock-js/tools';
6
6
  import { Command, Option } from 'commander';
7
7
  import { runExpoPrebuildIfNeeded } from '../utils/expo.js';
8
+ import { findProjectRoot } from '../utils/paths.js';
8
9
  import { getProjectInfo } from '../utils/project.js';
10
+ import { supportsPrebuiltExpo } from '../utils/supportsPrebuiltExpo.js';
9
11
  import { supportsPrebuiltRNCore } from '../utils/supportsPrebuiltRNCore.js';
10
12
  import { actionRunner, curryOptions, ExampleUsage, } from '../../shared/index.js';
11
13
  import { runBrownieCodegenIfApplicable } from '../../brownie/helpers/runBrownieCodegenIfApplicable.js';
@@ -14,13 +16,19 @@ import { copyDebugBundleToSimulatorSlice } from '../utils/copyDebugBundleToSimul
14
16
  import { resolvePackagedFrameworkName } from '../utils/resolvePackagedFrameworkName.js';
15
17
  import { stripFrameworkBinary } from '../utils/stripFrameworkBinary.js';
16
18
  import { createLocalSpmPackage } from '../utils/createLocalSpmPackage.js';
19
+ import { emitExpoSupportXcframeworks } from '../utils/emitExpoSupportXcframeworks.js';
17
20
  import { mergeBrownfieldConfigWithOptions } from '../../config.js';
21
+ import { removeCodeSignatureArtifacts } from '../utils/normalizeCopiedXcframework.js';
18
22
  /** Help text for `--use-prebuilt-rn-core` (keep in sync with docs/docs/docs/getting-started/ios.mdx, "React Native Prebuilts" section). */
19
23
  const USE_PREBUILT_RN_CORE_HELP = 'Whether the Xcode build for packaging should use React Native Apple prebuilt binaries (via CocoaPods). ' +
20
24
  '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. ' +
21
25
  '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`). ' +
22
26
  'See the Brownfield iOS guide for details: https://oss.callstack.com/react-native-brownfield/docs/getting-started/ios#react-native-prebuilts';
23
- export function parseUsePrebuiltRnCoreArgument(value) {
27
+ /** Help text for `--use-prebuilt-expo`. */
28
+ const USE_PREBUILT_EXPO_HELP = 'Whether the Xcode build for packaging should use prebuilt Expo support XCFrameworks. ' +
29
+ 'If you omit this flag, Brownfield follows version-aware defaults for supported Expo projects. ' +
30
+ 'Pass true or false to force either behavior. Use the flag without a value as shorthand for true (same as `--use-prebuilt-expo true`).';
31
+ function parseBooleanOptionArgument(flagName, value) {
24
32
  if (typeof value === 'boolean') {
25
33
  return value;
26
34
  }
@@ -31,7 +39,13 @@ export function parseUsePrebuiltRnCoreArgument(value) {
31
39
  if (normalized === 'false' || normalized === '0') {
32
40
  return false;
33
41
  }
34
- throw new RockError(`Invalid value for --use-prebuilt-rn-core: expected true or false, received "${value}"`);
42
+ throw new RockError(`Invalid value for ${flagName}: expected true or false, received "${value}"`);
43
+ }
44
+ export function parseUsePrebuiltRnCoreArgument(value) {
45
+ return parseBooleanOptionArgument('--use-prebuilt-rn-core', value);
46
+ }
47
+ export function parseUsePrebuiltExpoArgument(value) {
48
+ return parseBooleanOptionArgument('--use-prebuilt-expo', value);
35
49
  }
36
50
  function getPackagedFrameworkResolutionFailureMessage({ resolution, candidates, }) {
37
51
  return resolution === 'ambiguous'
@@ -48,15 +62,25 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
48
62
  .addOption(new Option('--use-prebuilt-rn-core [bool]', USE_PREBUILT_RN_CORE_HELP)
49
63
  .preset(true)
50
64
  .argParser(parseUsePrebuiltRnCoreArgument))
65
+ .addOption(new Option('--use-prebuilt-expo [bool]', USE_PREBUILT_EXPO_HELP)
66
+ .preset(true)
67
+ .argParser(parseUsePrebuiltExpoArgument))
51
68
  .addOption(new Option('--add-spm-package', 'Generate a local Swift Package Manager manifest next to the packaged XCFramework outputs'))
52
69
  .action(actionRunner(async (cliOptions) => {
53
70
  const options = mergeBrownfieldConfigWithOptions(cliOptions, 'ios');
54
- const { projectRoot, platformConfig, userConfig } = getProjectInfo('ios');
71
+ const projectRoot = findProjectRoot();
72
+ await runExpoPrebuildIfNeeded({ projectRoot, platform: 'ios' });
73
+ const { platformConfig, userConfig } = getProjectInfo('ios');
55
74
  const prebuiltRNCoreSupport = supportsPrebuiltRNCore({ projectRoot });
75
+ const prebuiltExpoSupport = supportsPrebuiltExpo({ projectRoot });
56
76
  // version-aware default when the flag is omitted (see ios.mdx "React Native Prebuilts")
57
77
  options.usePrebuiltRnCore ??= prebuiltRNCoreSupport.supported
58
78
  ? prebuiltRNCoreSupport.enabledByDefault
59
79
  : false;
80
+ // version-aware default when the flag is omitted
81
+ options.usePrebuiltExpo ??= prebuiltExpoSupport.supported
82
+ ? prebuiltExpoSupport.enabledByDefault
83
+ : false;
60
84
  if (prebuiltRNCoreSupport) {
61
85
  logger.info(`${options.usePrebuiltRnCore ? 'Using' : 'Not using'} prebuilt RN core`);
62
86
  if (!prebuiltRNCoreSupport.enabledByDefault &&
@@ -67,7 +91,9 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
67
91
  if (options.usePrebuiltRnCore && !prebuiltRNCoreSupport.supported) {
68
92
  throw new RockError(prebuiltRNCoreSupport.reason);
69
93
  }
70
- await runExpoPrebuildIfNeeded({ projectRoot, platform: 'ios' });
94
+ if (options.usePrebuiltExpo && !prebuiltExpoSupport.supported) {
95
+ throw new RockError(prebuiltExpoSupport.reason);
96
+ }
71
97
  if (!userConfig.project.ios) {
72
98
  throw new Error('iOS project not found.');
73
99
  }
@@ -104,6 +130,11 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
104
130
  skipCache: true, // cache is dependent on existence of Rock config file
105
131
  usePrebuiltRNCore: options.usePrebuiltRnCore,
106
132
  }, platformConfig);
133
+ emitExpoSupportXcframeworks({
134
+ projectRoot,
135
+ packageDir,
136
+ usePrebuiltExpo: options.usePrebuiltExpo,
137
+ });
107
138
  const productsPath = path.join(options.buildFolder, 'Build', 'Products');
108
139
  const { frameworkName, resolution, candidates } = resolvePackagedFrameworkName({
109
140
  explicitScheme: options.scheme,
@@ -176,10 +207,12 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
176
207
  stripFrameworkBinary(brownfieldNavigationOutputPath);
177
208
  logger.success(`BrownfieldNavigation.xcframework created at ${colorLink(relativeToCwd(brownfieldNavigationOutputPath))}`);
178
209
  }
210
+ removeCodeSignatureArtifacts(packageDir);
179
211
  if (options.addSpmPackage) {
180
212
  const { packageManifestPath } = createLocalSpmPackage({
181
213
  packageDir,
182
214
  frameworkName: frameworkName ?? undefined,
215
+ usePrebuiltExpo: options.usePrebuiltExpo,
183
216
  });
184
217
  logger.success(`Local SPM package manifest created at ${colorLink(relativeToCwd(packageManifestPath))}`);
185
218
  logger.info(`Add the local package folder in Xcode: ${colorLink(relativeToCwd(packageDir))}`);
@@ -1 +1 @@
1
- {"version":3,"file":"publishAndroid.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/publishAndroid.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAGL,YAAY,EACb,MAAM,uBAAuB,CAAC;AAO/B,eAAO,MAAM,qBAAqB,SAwBjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,cAGjC,CAAC"}
1
+ {"version":3,"file":"publishAndroid.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/publishAndroid.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAGL,YAAY,EACb,MAAM,uBAAuB,CAAC;AAQ/B,eAAO,MAAM,qBAAqB,SA0BjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,cAGjC,CAAC"}
@@ -3,17 +3,19 @@ import { publishLocalAarOptions, } from '@rock-js/platform-android';
3
3
  import { Command } from 'commander';
4
4
  import { actionRunner, curryOptions, ExampleUsage, } from '../../shared/index.js';
5
5
  import { getProjectInfo } from '../utils/project.js';
6
+ import { findProjectRoot } from '../utils/paths.js';
6
7
  import { runExpoPrebuildIfNeeded } from '../utils/expo.js';
7
8
  import { runBrownieCodegenIfApplicable } from '../../brownie/helpers/runBrownieCodegenIfApplicable.js';
8
9
  import { runNavigationCodegenIfApplicable } from '../../navigation/helpers/runNavigationCodegenIfApplicable.js';
9
10
  import { mergeBrownfieldConfigWithOptions } from '../../config.js';
10
11
  export const publishAndroidCommand = curryOptions(new Command('publish:android').description('Publish Android package to Maven local'), publishLocalAarOptions).action(actionRunner(async (cliOptions) => {
11
12
  const options = mergeBrownfieldConfigWithOptions(cliOptions, 'android');
12
- const { projectRoot, platformConfig } = getProjectInfo('android');
13
+ const projectRoot = findProjectRoot();
13
14
  await runExpoPrebuildIfNeeded({
14
15
  projectRoot,
15
16
  platform: 'android',
16
17
  });
18
+ const { platformConfig } = getProjectInfo('android');
17
19
  await runBrownieCodegenIfApplicable(projectRoot, 'kotlin');
18
20
  await runNavigationCodegenIfApplicable(projectRoot);
19
21
  await publishLocalAarAction({
@@ -1,10 +1,11 @@
1
1
  type CreateLocalSpmPackageOptions = {
2
2
  packageDir: string;
3
3
  frameworkName?: string;
4
+ usePrebuiltExpo?: boolean;
4
5
  };
5
6
  type CreateLocalSpmPackageResult = {
6
7
  packageManifestPath: string;
7
8
  };
8
- export declare function createLocalSpmPackage({ packageDir, frameworkName, }: CreateLocalSpmPackageOptions): CreateLocalSpmPackageResult;
9
+ export declare function createLocalSpmPackage({ packageDir, frameworkName, usePrebuiltExpo, }: CreateLocalSpmPackageOptions): CreateLocalSpmPackageResult;
9
10
  export {};
10
11
  //# sourceMappingURL=createLocalSpmPackage.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"createLocalSpmPackage.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/createLocalSpmPackage.ts"],"names":[],"mappings":"AAYA,KAAK,4BAA4B,GAAG;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AA0JF,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,aAAa,EACb,eAAsB,GACvB,EAAE,4BAA4B,GAAG,2BAA2B,CA2C5D"}
@@ -1,6 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { prepareLocalSpmArtifacts, SPM_ARTIFACTS_DIR_NAME, } from './prepareLocalSpmArtifacts.js';
4
+ import { ALL_EXPO_SUPPORT_XCFRAMEWORK_NAMES, getExpoSupportXcframeworkNames, } from './emitExpoSupportXcframeworks.js';
4
5
  const RESERVED_FRAMEWORK_NAMES = new Set([
5
6
  'hermes',
6
7
  'hermesvm',
@@ -9,6 +10,7 @@ const RESERVED_FRAMEWORK_NAMES = new Set([
9
10
  'BrownfieldNavigation',
10
11
  'React',
11
12
  'ReactNativeDependencies',
13
+ ...ALL_EXPO_SUPPORT_XCFRAMEWORK_NAMES,
12
14
  ]);
13
15
  function requireXcframework(packageDir, name) {
14
16
  const xcframeworkPath = path.join(packageDir, `${name}.xcframework`);
@@ -71,7 +73,9 @@ ${binaryTargets}
71
73
  `;
72
74
  }
73
75
  function renderReadme({ packageName, libraryName, targetNames, }) {
74
- const frameworks = targetNames.map((targetName) => `- \`${targetName}\``).join('\n');
76
+ const frameworks = targetNames
77
+ .map((targetName) => `- \`${targetName}\``)
78
+ .join('\n');
75
79
  return `# ${packageName}
76
80
 
77
81
  This is a generated local Swift Package Manager package for the packaged React Native brownfield artifacts.
@@ -103,14 +107,16 @@ If Xcode builds your host app but the simulator installation fails, check the ho
103
107
  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
108
  `;
105
109
  }
106
- export function createLocalSpmPackage({ packageDir, frameworkName, }) {
110
+ export function createLocalSpmPackage({ packageDir, frameworkName, usePrebuiltExpo = true, }) {
107
111
  const resolvedFrameworkName = resolveAppFrameworkName(packageDir, frameworkName);
112
+ const expoSupportXcframeworkNames = getExpoSupportXcframeworkNames(usePrebuiltExpo);
108
113
  const targetNames = [
109
114
  resolvedFrameworkName,
110
115
  requireHermesXcframework(packageDir),
111
116
  requireXcframework(packageDir, 'ReactBrownfield'),
112
117
  optionalXcframework(packageDir, 'Brownie'),
113
118
  optionalXcframework(packageDir, 'BrownfieldNavigation'),
119
+ ...expoSupportXcframeworkNames.map((frameworkName) => optionalXcframework(packageDir, frameworkName)),
114
120
  optionalXcframework(packageDir, 'React'),
115
121
  optionalXcframework(packageDir, 'ReactNativeDependencies'),
116
122
  ].filter((targetName) => targetName !== null);
@@ -0,0 +1,9 @@
1
+ export declare const EXPO_SUPPORT_XCFRAMEWORK_NAMES: readonly ["ExpoModulesJSI", "ExpoFileSystem", "ExpoFont", "ExpoModulesCore", "ExpoImage", "ExpoModulesWorklets"];
2
+ export declare const ALL_EXPO_SUPPORT_XCFRAMEWORK_NAMES: readonly ["ExpoModulesJSI", "ExpoFileSystem", "ExpoFont", "ExpoModulesCore", "ExpoImage", "ExpoModulesWorklets", "SDWebImage", "SDWebImageSVGCoder", "SDWebImageWebPCoder", "SDWebImageAVIFCoder", "libavif"];
3
+ export declare function getExpoSupportXcframeworkNames(usePrebuiltExpo: boolean): readonly ["ExpoModulesJSI", "ExpoFileSystem", "ExpoFont", "ExpoModulesCore", "ExpoImage", "ExpoModulesWorklets", "SDWebImage", "SDWebImageSVGCoder", "SDWebImageWebPCoder", "SDWebImageAVIFCoder", "libavif"] | readonly ["ExpoModulesJSI"];
4
+ export declare function emitExpoSupportXcframeworks({ projectRoot, packageDir, usePrebuiltExpo, }: {
5
+ projectRoot: string;
6
+ packageDir: string;
7
+ usePrebuiltExpo?: boolean;
8
+ }): boolean;
9
+ //# sourceMappingURL=emitExpoSupportXcframeworks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitExpoSupportXcframeworks.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/emitExpoSupportXcframeworks.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,8BAA8B,kHAOjC,CAAC;AAEX,eAAO,MAAM,kCAAkC,+MAGrC,CAAC;AAEX,wBAAgB,8BAA8B,CAAC,eAAe,EAAE,OAAO,+OAItE;AA8CD,wBAAgB,2BAA2B,CAAC,EAC1C,WAAW,EACX,UAAU,EACV,eAAsB,GACvB,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,WAkCA"}
@@ -0,0 +1,70 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { RockError } from '@rock-js/tools';
4
+ import { normalizeCopiedXcframework } from './normalizeCopiedXcframework.js';
5
+ import { getExpoSdkMajor, isExpoProject } from './project.js';
6
+ import { MIN_EXPO_SDK_MAJOR_FOR_PREBUILT_EXPO } from './supportsPrebuiltExpo.js';
7
+ /**
8
+ * Swift support XCFrameworks
9
+ *
10
+ * These are required for the Expo Image module to work.
11
+ *
12
+ * TODO: This needs investigation and maybe a discussion with the Expo team.
13
+ */
14
+ const SWIFT_SUPPORT_XCFRAMEWORK_NAMES = [
15
+ 'SDWebImage',
16
+ 'SDWebImageSVGCoder',
17
+ 'SDWebImageWebPCoder',
18
+ 'SDWebImageAVIFCoder',
19
+ 'libavif',
20
+ ];
21
+ export const EXPO_SUPPORT_XCFRAMEWORK_NAMES = [
22
+ 'ExpoModulesJSI',
23
+ 'ExpoFileSystem',
24
+ 'ExpoFont',
25
+ 'ExpoModulesCore',
26
+ 'ExpoImage',
27
+ 'ExpoModulesWorklets'
28
+ ];
29
+ export const ALL_EXPO_SUPPORT_XCFRAMEWORK_NAMES = [
30
+ ...EXPO_SUPPORT_XCFRAMEWORK_NAMES,
31
+ ...SWIFT_SUPPORT_XCFRAMEWORK_NAMES,
32
+ ];
33
+ export function getExpoSupportXcframeworkNames(usePrebuiltExpo) {
34
+ return usePrebuiltExpo
35
+ ? ALL_EXPO_SUPPORT_XCFRAMEWORK_NAMES
36
+ : ['ExpoModulesJSI'];
37
+ }
38
+ function resolveExpoFrameworkSourcePath(projectRoot, frameworkName) {
39
+ if (frameworkName === 'ExpoModulesJSI') {
40
+ return path.join(projectRoot, 'node_modules', 'expo-modules-jsi', 'apple', 'Products', 'ExpoModulesJSI.xcframework');
41
+ }
42
+ if (SWIFT_SUPPORT_XCFRAMEWORK_NAMES.includes(frameworkName)) {
43
+ return path.join(projectRoot, 'ios', 'Pods', 'ExpoImage', `${frameworkName}.xcframework`);
44
+ }
45
+ if (EXPO_SUPPORT_XCFRAMEWORK_NAMES.includes(frameworkName)) {
46
+ return path.join(projectRoot, 'ios', 'Pods', frameworkName, `${frameworkName}.xcframework`);
47
+ }
48
+ throw new RockError(`Unsupported Expo XCFramework: ${frameworkName}`);
49
+ }
50
+ export function emitExpoSupportXcframeworks({ projectRoot, packageDir, usePrebuiltExpo = true, }) {
51
+ if (!isExpoProject(projectRoot)) {
52
+ return false;
53
+ }
54
+ const expoSdkMajor = getExpoSdkMajor(projectRoot);
55
+ if (expoSdkMajor === null ||
56
+ expoSdkMajor < MIN_EXPO_SDK_MAJOR_FOR_PREBUILT_EXPO) {
57
+ return false;
58
+ }
59
+ for (const frameworkName of getExpoSupportXcframeworkNames(usePrebuiltExpo)) {
60
+ const sourcePath = resolveExpoFrameworkSourcePath(projectRoot, frameworkName);
61
+ if (!fs.existsSync(sourcePath)) {
62
+ throw new RockError(`Expected Expo SDK ${MIN_EXPO_SDK_MAJOR_FOR_PREBUILT_EXPO}+ XCFramework not found: ${frameworkName}.xcframework at ${path.relative(projectRoot, sourcePath)}`);
63
+ }
64
+ const destinationPath = path.join(packageDir, `${frameworkName}.xcframework`);
65
+ fs.rmSync(destinationPath, { recursive: true, force: true });
66
+ fs.cpSync(sourcePath, destinationPath, { recursive: true });
67
+ normalizeCopiedXcframework(destinationPath);
68
+ }
69
+ return true;
70
+ }
@@ -0,0 +1,3 @@
1
+ export declare function removeCodeSignatureArtifacts(dirPath: string): void;
2
+ export declare function normalizeCopiedXcframework(xcframeworkPath: string): void;
3
+ //# sourceMappingURL=normalizeCopiedXcframework.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeCopiedXcframework.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/normalizeCopiedXcframework.ts"],"names":[],"mappings":"AAIA,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,QAkB3D;AAyCD,wBAAgB,0BAA0B,CAAC,eAAe,EAAE,MAAM,QA0BjE"}
@@ -0,0 +1,64 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { execFileSync } from 'node:child_process';
4
+ export function removeCodeSignatureArtifacts(dirPath) {
5
+ for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
6
+ const entryPath = path.join(dirPath, entry.name);
7
+ if (entry.isDirectory()) {
8
+ if (entry.name === '_CodeSignature') {
9
+ fs.rmSync(entryPath, { recursive: true, force: true });
10
+ continue;
11
+ }
12
+ removeCodeSignatureArtifacts(entryPath);
13
+ continue;
14
+ }
15
+ if (entry.name === 'CodeResources') {
16
+ fs.rmSync(entryPath, { force: true });
17
+ }
18
+ }
19
+ }
20
+ function resolveFrameworkExecutablePath(frameworkDir, frameworkName) {
21
+ const directExecutablePath = path.join(frameworkDir, frameworkName);
22
+ if (fs.existsSync(directExecutablePath)) {
23
+ return directExecutablePath;
24
+ }
25
+ const versionedExecutablePath = path.join(frameworkDir, 'Versions', 'Current', frameworkName);
26
+ if (fs.existsSync(versionedExecutablePath)) {
27
+ return versionedExecutablePath;
28
+ }
29
+ return null;
30
+ }
31
+ function removeExecutableSignature(executablePath) {
32
+ try {
33
+ execFileSync('codesign', ['--remove-signature', executablePath], {
34
+ stdio: 'pipe',
35
+ });
36
+ }
37
+ catch (error) {
38
+ if (error instanceof Error &&
39
+ error.message.includes('code object is not signed at all')) {
40
+ return;
41
+ }
42
+ throw error;
43
+ }
44
+ }
45
+ export function normalizeCopiedXcframework(xcframeworkPath) {
46
+ removeCodeSignatureArtifacts(xcframeworkPath);
47
+ for (const sliceName of fs.readdirSync(xcframeworkPath)) {
48
+ const slicePath = path.join(xcframeworkPath, sliceName);
49
+ if (!fs.statSync(slicePath).isDirectory()) {
50
+ continue;
51
+ }
52
+ for (const entry of fs.readdirSync(slicePath)) {
53
+ if (!entry.endsWith('.framework')) {
54
+ continue;
55
+ }
56
+ const frameworkName = path.basename(entry, '.framework');
57
+ const frameworkDir = path.join(slicePath, entry);
58
+ const executablePath = resolveFrameworkExecutablePath(frameworkDir, frameworkName);
59
+ if (executablePath) {
60
+ removeExecutableSignature(executablePath);
61
+ }
62
+ }
63
+ }
64
+ }
@@ -1 +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"}
1
+ {"version":3,"file":"prepareLocalSpmArtifacts.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/prepareLocalSpmArtifacts.ts"],"names":[],"mappings":"AAKA,KAAK,+BAA+B,GAAG;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AAEtD,wBAAgB,wBAAwB,CAAC,EACvC,UAAU,EACV,WAAW,GACZ,EAAE,+BAA+B,UAkBjC"}
@@ -1,68 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { execFileSync } from 'node:child_process';
3
+ import { normalizeCopiedXcframework } from './normalizeCopiedXcframework.js';
4
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
5
  export function prepareLocalSpmArtifacts({ packageDir, targetNames, }) {
67
6
  const spmArtifactsDir = path.join(packageDir, SPM_ARTIFACTS_DIR_NAME);
68
7
  fs.rmSync(spmArtifactsDir, { recursive: true, force: true });
@@ -71,7 +10,7 @@ export function prepareLocalSpmArtifacts({ packageDir, targetNames, }) {
71
10
  const sourcePath = path.join(packageDir, `${targetName}.xcframework`);
72
11
  const destinationPath = path.join(spmArtifactsDir, `${targetName}.xcframework`);
73
12
  fs.renameSync(sourcePath, destinationPath);
74
- normalizeCopiedXcframeworkSignature(destinationPath);
13
+ normalizeCopiedXcframework(destinationPath);
75
14
  }
76
15
  return spmArtifactsDir;
77
16
  }
@@ -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,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"}
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;AAiCtB;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,4BAYxD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE1D;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"}
@@ -7,16 +7,34 @@ const cliConfig = typeof cliConfigImport === 'function'
7
7
  ? cliConfigImport
8
8
  : // @ts-expect-error: interop default
9
9
  cliConfigImport.default;
10
+ function hasExpoAppConfig(projectRoot) {
11
+ return (fs.existsSync(path.join(projectRoot, 'app.json')) ||
12
+ fs.existsSync(path.join(projectRoot, 'app.config.js')) ||
13
+ fs.existsSync(path.join(projectRoot, 'app.config.ts')) ||
14
+ fs.existsSync(path.join(projectRoot, 'app.config.mjs')));
15
+ }
16
+ function projectDependsOnExpo(projectRoot) {
17
+ const packageJsonPath = path.join(projectRoot, 'package.json');
18
+ if (!fs.existsSync(packageJsonPath)) {
19
+ return false;
20
+ }
21
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
22
+ return ['dependencies', 'peerDependencies', 'devDependencies'].some((key) => packageJson[key]?.expo);
23
+ }
10
24
  /**
11
25
  * Gets the Expo config if the project is an Expo project
12
26
  * @param projectRoot The project root path
13
27
  * @returns The Expo config if the project is an Expo project, null otherwise
14
28
  */
15
29
  export function getExpoConfigIfIsExpo(projectRoot) {
30
+ const hasAppConfig = hasExpoAppConfig(projectRoot);
16
31
  try {
17
32
  return getConfig(projectRoot, { skipSDKVersionRequirement: true });
18
33
  }
19
- catch {
34
+ catch (error) {
35
+ if (hasAppConfig) {
36
+ throw error;
37
+ }
20
38
  return null;
21
39
  }
22
40
  }
@@ -27,14 +45,7 @@ export function getExpoConfigIfIsExpo(projectRoot) {
27
45
  * @returns Whether the project is an Expo project
28
46
  */
29
47
  export function isExpoProject(projectRoot) {
30
- const hasExpoConfig = getExpoConfigIfIsExpo(projectRoot) !== null;
31
- // additionally, it is needed to check if the project depends on Expo packages explicitly
32
- // to prevent false positives in a monorepo setup
33
- const rnProjectRoot = findProjectRoot();
34
- const packageJsonPath = path.join(rnProjectRoot, 'package.json');
35
- const dependsOnExpo = fs.existsSync(packageJsonPath) &&
36
- ['dependencies', 'peerDependencies', 'devDependencies'].some((key) => JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))[key]?.expo);
37
- return hasExpoConfig && dependsOnExpo;
48
+ return hasExpoAppConfig(projectRoot) && projectDependsOnExpo(projectRoot);
38
49
  }
39
50
  export function getExpoSdkMajor(projectRoot) {
40
51
  const rawExpoVersion = getExpoConfigIfIsExpo(projectRoot)?.exp.sdkVersion;
@@ -0,0 +1,14 @@
1
+ export declare const MIN_EXPO_SDK_MAJOR_FOR_PREBUILT_EXPO = 56;
2
+ export type PrebuiltExpoSupportResult = {
3
+ supported: true;
4
+ enabledByDefault: boolean;
5
+ reason?: never;
6
+ } | {
7
+ supported: false;
8
+ enabledByDefault?: never;
9
+ reason: string;
10
+ };
11
+ export declare function supportsPrebuiltExpo({ projectRoot, }: {
12
+ projectRoot: string;
13
+ }): PrebuiltExpoSupportResult;
14
+ //# sourceMappingURL=supportsPrebuiltExpo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supportsPrebuiltExpo.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/supportsPrebuiltExpo.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oCAAoC,KAAK,CAAC;AAEvD,MAAM,MAAM,yBAAyB,GACjC;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,oBAAoB,CAAC,EACnC,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,yBAAyB,CAqB5B"}
@@ -0,0 +1,20 @@
1
+ import { getExpoSdkMajor, isExpoProject } from './project.js';
2
+ export const MIN_EXPO_SDK_MAJOR_FOR_PREBUILT_EXPO = 56;
3
+ export function supportsPrebuiltExpo({ projectRoot, }) {
4
+ if (!isExpoProject(projectRoot)) {
5
+ return { supported: true, enabledByDefault: false };
6
+ }
7
+ const expoSdkMajor = getExpoSdkMajor(projectRoot);
8
+ if (expoSdkMajor === null ||
9
+ expoSdkMajor < MIN_EXPO_SDK_MAJOR_FOR_PREBUILT_EXPO) {
10
+ const sdkLabel = expoSdkMajor === null ? 'unknown' : String(expoSdkMajor);
11
+ return {
12
+ supported: false,
13
+ reason: `--use-prebuilt-expo is unsupported in Expo SDK ${sdkLabel}: packaging brownfield with Expo prebuilts requires Expo SDK ${MIN_EXPO_SDK_MAJOR_FOR_PREBUILT_EXPO} or newer.`,
14
+ };
15
+ }
16
+ return {
17
+ supported: true,
18
+ enabledByDefault: true,
19
+ };
20
+ }
@@ -66,7 +66,7 @@ export function resolveBrownieCodegenConfig({ brownie, projectRoot = findProject
66
66
  const legacyConfig = hasLegacyConfig(projectRoot)
67
67
  ? loadConfig(projectRoot)
68
68
  : undefined;
69
- const brownfieldBrownie = loadBrownfieldConfig(projectRoot).brownie;
69
+ const brownfieldBrownie = loadBrownfieldConfig(projectRoot)?.brownie;
70
70
  if (legacyConfig !== undefined && (brownie ?? brownfieldBrownie)) {
71
71
  throw new Error(LEGACY_AND_NEW_BROWNIE_CONFIG_ERROR);
72
72
  }
package/dist/config.d.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  import type { BrownfieldConfig } from './types.js';
2
+ export declare const CONFIG_BASE_NAME = "brownfield";
3
+ export declare const JS_CONFIG_FILE_NAME = "brownfield.config.js";
4
+ export declare const JSON_CONFIG_FILE_NAME = "brownfield.config.json";
2
5
  export declare function validateBrownfieldCLIConfig(config: unknown): void;
3
- export declare function loadBrownfieldConfig(projectRoot?: string): BrownfieldConfig;
6
+ export declare function loadBrownfieldConfig(projectRoot?: string): BrownfieldConfig | null;
4
7
  type BrownfieldPlatform = 'android' | 'ios';
5
8
  export declare function mergeBrownfieldConfigWithOptions<T extends object>(options: T, platform: BrownfieldPlatform): T;
6
9
  export {};