Skip to content

Commit 7284dfd

Browse files
huntiefacebook-github-bot
authored andcommitted
Move codegen and spm command wrappers into community-cli-plugin (#57652)
Summary: Migrate the `codegen` and `spm` command implementations out of `react-native.config.js` and into the `react-native/community-cli-plugin` package, alongside the existing `bundleCommand` and `startCommand`. This continues moving command definitions into the plugin so `react-native.config.js` becomes a thin routing layer, as the file's own comment already calls for. **Changes** - Add `src/commands/spm/index.js` and `src/commands/codegen/index.js`, each defining and default-exporting its command (unchanged `name`, `description`, and `options`) plus an exported args type — mirroring the `bundle`/`start` command structure. - Export `spmCommand` and `codegenCommand` from `src/index.flow.js`. - Drop the inline `spmCommand` and `codegenCommand` definitions from `react-native.config.js`. Changelog: [Internal] Differential Revision: D113412987
1 parent 7a12a8d commit 7284dfd

4 files changed

Lines changed: 201 additions & 122 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict-local
8+
* @format
9+
*/
10+
11+
import type {Command, Config} from '@react-native-community/cli-types';
12+
13+
export type CodegenCommandArgs = {
14+
path: string,
15+
platform: string,
16+
outputPath?: string,
17+
source: string,
18+
};
19+
20+
const codegenCommand: Command = {
21+
name: 'codegen',
22+
options: [
23+
{
24+
name: '--path <path>',
25+
description: 'Path to the React Native project root.',
26+
default: process.cwd(),
27+
},
28+
{
29+
name: '--platform <string>',
30+
description:
31+
'Target platform. Supported values: "android", "ios", "all".',
32+
default: 'all',
33+
},
34+
{
35+
name: '--outputPath <path>',
36+
description: 'Path where generated artifacts will be output to.',
37+
},
38+
{
39+
name: '--source <string>',
40+
description: 'Whether the script is invoked from an `app` or a `library`',
41+
default: 'app',
42+
},
43+
],
44+
func: (
45+
argv: Array<string>,
46+
config: Config,
47+
args: CodegenCommandArgs,
48+
): void => {
49+
// `react-native` is not a dependency of this package (that would be a
50+
// circular dependency, since react-native depends on it). Resolve the
51+
// script from the host project root at runtime, mirroring how
52+
// `react-native/setup-env` is resolved in `utils/loadMetroConfig.js`.
53+
const generateArtifactsExecutor = require.resolve(
54+
'react-native/scripts/codegen/generate-artifacts-executor',
55+
{paths: [config.root]},
56+
);
57+
// $FlowFixMe[unsupported-syntax] dynamic require of a resolved path
58+
require(generateArtifactsExecutor).execute(
59+
args.path,
60+
args.platform,
61+
args.outputPath,
62+
args.source,
63+
);
64+
},
65+
};
66+
67+
export default codegenCommand;
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict-local
8+
* @format
9+
*/
10+
11+
import type {Command, Config} from '@react-native-community/cli-types';
12+
13+
export type SpmCommandArgs = {
14+
version?: string,
15+
yes?: boolean,
16+
xcodeproj?: string,
17+
productName?: string,
18+
deintegrate?: boolean,
19+
artifacts?: string,
20+
download?: string,
21+
skipCodegen?: boolean,
22+
};
23+
24+
const spmCommand: Command = {
25+
name: 'spm [action]',
26+
description:
27+
'Set up or maintain Swift Package Manager support for the iOS/macOS app. ' +
28+
'Actions: add, update, deinit, scaffold. With no action: add (or update ' +
29+
'if SPM is already set up).',
30+
options: [
31+
{
32+
name: '--version <string>',
33+
description:
34+
'React Native version (e.g. 0.80.0). Defaults to the version in node_modules/react-native/package.json.',
35+
},
36+
{
37+
name: '--yes',
38+
description: 'Skip the dirty-pbxproj confirmation prompt.',
39+
},
40+
{
41+
name: '--xcodeproj <path>',
42+
description:
43+
'[add] Path to the .xcodeproj to inject SPM packages into ' +
44+
'(disambiguates when several exist).',
45+
},
46+
{
47+
name: '--productName <string>',
48+
description:
49+
'[add] App target to inject into (disambiguates when several exist).',
50+
},
51+
{
52+
name: '--deintegrate',
53+
description:
54+
'[add] Run `pod deintegrate` and strip React Native from the Podfile ' +
55+
'before injecting (CocoaPods → SwiftPM migration).',
56+
},
57+
{
58+
name: '--artifacts <path>',
59+
description:
60+
'[advanced] Local artifact root containing complete debug/ and release/ slots.',
61+
},
62+
{
63+
name: '--download <string>',
64+
description:
65+
'[advanced] Artifact download policy: auto (default), skip, or force.',
66+
},
67+
{
68+
name: '--skipCodegen',
69+
description: '[advanced] Skip the react-native codegen step.',
70+
},
71+
],
72+
func: async (
73+
argv: Array<string>,
74+
config: Config,
75+
args: SpmCommandArgs,
76+
): Promise<void> => {
77+
const passthrough: Array<string> = [];
78+
if (argv[0] != null) {
79+
passthrough.push(argv[0]);
80+
}
81+
const stringOpts: Array<
82+
[
83+
'version' | 'productName' | 'xcodeproj' | 'artifacts' | 'download',
84+
string,
85+
],
86+
> = [
87+
['version', '--version'],
88+
['productName', '--product-name'],
89+
['xcodeproj', '--xcodeproj'],
90+
['artifacts', '--artifacts'],
91+
['download', '--download'],
92+
];
93+
for (const [key, flag] of stringOpts) {
94+
const value = args[key];
95+
if (value != null) {
96+
passthrough.push(flag, String(value));
97+
}
98+
}
99+
const boolOpts: Array<['skipCodegen' | 'deintegrate' | 'yes', string]> = [
100+
['skipCodegen', '--skip-codegen'],
101+
['deintegrate', '--deintegrate'],
102+
['yes', '--yes'],
103+
];
104+
for (const [key, flag] of boolOpts) {
105+
if (args[key] === true) {
106+
passthrough.push(flag);
107+
}
108+
}
109+
// `react-native` is not a dependency of this package (that would be a
110+
// circular dependency, since react-native depends on it). Resolve the
111+
// script from the host project root at runtime, mirroring how
112+
// `react-native/setup-env` is resolved in `utils/loadMetroConfig.js`.
113+
const setupAppleSpm = require.resolve(
114+
'react-native/scripts/setup-apple-spm',
115+
{paths: [config.root]},
116+
);
117+
// $FlowFixMe[unsupported-syntax] dynamic require of a resolved path
118+
await require(setupAppleSpm).main(passthrough);
119+
},
120+
};
121+
122+
export default spmCommand;

packages/community-cli-plugin/src/index.flow.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export {
1212
default as bundleCommand,
1313
unstable_createBundleCommandParser,
1414
} from './commands/bundle';
15+
export {default as codegenCommand} from './commands/codegen';
16+
export {default as spmCommand} from './commands/spm';
1517
export {default as startCommand} from './commands/start';
1618

1719
export {unstable_buildBundleWithConfig} from './commands/bundle/buildBundle';

packages/react-native/react-native.config.js

Lines changed: 10 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@
1414
import type {Command} from '@react-native-community/cli-types';
1515
*/
1616

17-
// React Native shouldn't be exporting itself like this, the Community Template should be be directly
18-
// depending on and injecting:
17+
// IMPORTANT: This is a routing file only. Do NOT add new command
18+
// definitions or implementations here.
19+
//
20+
// New CLI commands belong in @react-native/community-cli-plugin, and
21+
// may (temporarily) be imported and registered here.
22+
//
23+
// Future state: The Community Template should directly depend on and inject:
1924
// - @react-native-community/cli-platform-android
2025
// - @react-native-community/cli-platform-ios
2126
// - @react-native/community-cli-plugin
22-
// - codegen command should be inhoused into @react-native-community/cli
23-
//
24-
// This is a temporary workaround.
2527

2628
const verbose = Boolean(process.env.DEBUG?.includes('react-native'));
2729

@@ -72,126 +74,12 @@ const commands /*: Array<Command> */ = [];
7274

7375
const {
7476
bundleCommand,
77+
codegenCommand,
78+
spmCommand,
7579
startCommand,
7680
} = require('@react-native/community-cli-plugin');
7781

78-
commands.push(bundleCommand, startCommand);
79-
80-
const codegenCommand /*: Command */ = {
81-
name: 'codegen',
82-
options: [
83-
{
84-
name: '--path <path>',
85-
description: 'Path to the React Native project root.',
86-
default: process.cwd(),
87-
},
88-
{
89-
name: '--platform <string>',
90-
description:
91-
'Target platform. Supported values: "android", "ios", "all".',
92-
default: 'all',
93-
},
94-
{
95-
name: '--outputPath <path>',
96-
description: 'Path where generated artifacts will be output to.',
97-
},
98-
{
99-
name: '--source <string>',
100-
description: 'Whether the script is invoked from an `app` or a `library`',
101-
default: 'app',
102-
},
103-
],
104-
func: (argv, config, args) =>
105-
require('./scripts/codegen/generate-artifacts-executor').execute(
106-
args.path,
107-
args.platform,
108-
args.outputPath,
109-
args.source,
110-
),
111-
};
112-
113-
commands.push(codegenCommand);
114-
115-
const spmCommand /*: Command */ = {
116-
name: 'spm [action]',
117-
description:
118-
'Set up or maintain Swift Package Manager support for the iOS/macOS app. ' +
119-
'Actions: add, update, deinit, scaffold. With no action: add (or update ' +
120-
'if SPM is already set up).',
121-
options: [
122-
{
123-
name: '--version <string>',
124-
description:
125-
'React Native version (e.g. 0.80.0). Defaults to the version in node_modules/react-native/package.json.',
126-
},
127-
{
128-
name: '--yes',
129-
description: 'Skip the dirty-pbxproj confirmation prompt.',
130-
},
131-
{
132-
name: '--xcodeproj <path>',
133-
description:
134-
'[add] Path to the .xcodeproj to inject SPM packages into ' +
135-
'(disambiguates when several exist).',
136-
},
137-
{
138-
name: '--productName <string>',
139-
description:
140-
'[add] App target to inject into (disambiguates when several exist).',
141-
},
142-
{
143-
name: '--deintegrate',
144-
description:
145-
'[add] Run `pod deintegrate` and strip React Native from the Podfile ' +
146-
'before injecting (CocoaPods → SwiftPM migration).',
147-
},
148-
{
149-
name: '--artifacts <path>',
150-
description:
151-
'[advanced] Local artifact root containing complete debug/ and release/ slots.',
152-
},
153-
{
154-
name: '--download <string>',
155-
description:
156-
'[advanced] Artifact download policy: auto (default), skip, or force.',
157-
},
158-
{
159-
name: '--skipCodegen',
160-
description: '[advanced] Skip the react-native codegen step.',
161-
},
162-
],
163-
func: async (argv, _config, args) => {
164-
const passthrough /*: Array<string> */ = [];
165-
if (argv[0] != null) {
166-
passthrough.push(argv[0]);
167-
}
168-
const stringOpts /*: Array<[string, string]> */ = [
169-
['version', '--version'],
170-
['productName', '--product-name'],
171-
['xcodeproj', '--xcodeproj'],
172-
['artifacts', '--artifacts'],
173-
['download', '--download'],
174-
];
175-
for (const [key, flag] of stringOpts) {
176-
if (args[key] != null) {
177-
passthrough.push(flag, String(args[key]));
178-
}
179-
}
180-
const boolOpts /*: Array<[string, string]> */ = [
181-
['skipCodegen', '--skip-codegen'],
182-
['deintegrate', '--deintegrate'],
183-
['yes', '--yes'],
184-
];
185-
for (const [key, flag] of boolOpts) {
186-
if (args[key]) {
187-
passthrough.push(flag);
188-
}
189-
}
190-
await require('./scripts/setup-apple-spm').main(passthrough);
191-
},
192-
};
193-
194-
commands.push(spmCommand);
82+
commands.push(bundleCommand, startCommand, spmCommand, codegenCommand);
19583

19684
const config = {
19785
commands,

0 commit comments

Comments
 (0)