Skip to content

Commit e8c9da7

Browse files
authored
refactor: internal plugins (#329)
* refactor: internal plugins * add missing file * changeset * revert * fix test
1 parent 531ca1b commit e8c9da7

File tree

7 files changed

+177
-87
lines changed

7 files changed

+177
-87
lines changed

.changeset/unlucky-bikes-think.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@rnef/config': patch
3+
'@rnef/cli': patch
4+
---
5+
6+
refactor: internal plugins

packages/cli/src/lib/cli.ts

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { fileURLToPath } from 'node:url';
44
import { type CommandType, getConfig } from '@rnef/config';
55
import { color, logger, resolveFilenameUp, RnefError } from '@rnef/tools';
66
import { Command } from 'commander';
7-
import { logConfig } from '../config.js';
87
import { checkDeprecatedOptions } from './checkDeprecatedOptions.js';
9-
import { nativeFingerprintCommand } from './commands/fingerprint.js';
8+
import { fingerprintPlugin } from './plugins/fingerprint.js';
9+
import { logConfigPlugin } from './plugins/logConfig.js';
1010

1111
const require = createRequire(import.meta.url);
1212
const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -31,22 +31,9 @@ export const cli = async ({ cwd, argv }: CliOptions) => {
3131
.option('--verbose', 'enable verbose logging')
3232
.version(version);
3333

34+
const internalPlugins = [logConfigPlugin, fingerprintPlugin];
3435
// Register commands from the config
35-
const config = await getConfig(cwd);
36-
37-
program
38-
.command('config')
39-
.option('-p, --platform <string>', 'Select platform, e.g. ios or android')
40-
.action((args) => logConfig(args, config));
41-
42-
program
43-
.command('fingerprint [path]')
44-
.option('-p, --platform <string>', 'Select platform, e.g. ios or android')
45-
.option('--raw', 'Output the raw fingerprint hash for piping')
46-
.action(async (path, options) => {
47-
const fingerprintOptions = config.getFingerprintOptions();
48-
await nativeFingerprintCommand(path, fingerprintOptions, options);
49-
});
36+
const config = await getConfig(cwd, internalPlugins);
5037

5138
ensureUniqueCommands(config.commands);
5239

packages/cli/src/lib/commands/fingerprint.ts

Lines changed: 0 additions & 52 deletions
This file was deleted.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { performance } from 'node:perf_hooks';
2+
import type { PluginApi } from '@rnef/config';
3+
import {
4+
intro,
5+
isInteractive,
6+
logger,
7+
nativeFingerprint,
8+
outro,
9+
RnefError,
10+
spinner,
11+
} from '@rnef/tools';
12+
13+
type NativeFingerprintCommandOptions = {
14+
platform: 'ios' | 'android';
15+
raw?: boolean;
16+
};
17+
18+
type ConfigFingerprintOptions = {
19+
extraSources: string[];
20+
ignorePaths: string[];
21+
};
22+
23+
export async function nativeFingerprintCommand(
24+
path = '.',
25+
{ extraSources, ignorePaths }: ConfigFingerprintOptions,
26+
options: NativeFingerprintCommandOptions
27+
) {
28+
validateOptions(options);
29+
const platform = options.platform;
30+
const readablePlatformName = platform === 'ios' ? 'iOS' : 'Android';
31+
32+
if (options?.raw || !isInteractive()) {
33+
const fingerprint = await nativeFingerprint(path, {
34+
platform,
35+
extraSources,
36+
ignorePaths,
37+
});
38+
console.log(fingerprint.hash);
39+
return;
40+
}
41+
42+
intro(`${readablePlatformName} Fingerprint`);
43+
44+
const loader = spinner();
45+
loader.start("Calculating fingerprint for the project's native parts");
46+
47+
const start = performance.now();
48+
const fingerprint = await nativeFingerprint(path, {
49+
platform,
50+
extraSources,
51+
ignorePaths,
52+
});
53+
const duration = performance.now() - start;
54+
55+
loader.stop(`Fingerprint calculated: ${fingerprint.hash}`);
56+
57+
logger.debug('Sources:', JSON.stringify(fingerprint.sources, null, 2));
58+
logger.debug(`Duration: ${(duration / 1000).toFixed(1)}s`);
59+
60+
outro('Success 🎉.');
61+
}
62+
63+
function validateOptions(options: NativeFingerprintCommandOptions) {
64+
if (!options.platform) {
65+
throw new RnefError(
66+
'The --platform flag is required. Please specify either "ios" or "android".'
67+
);
68+
}
69+
if (options.platform !== 'ios' && options.platform !== 'android') {
70+
throw new RnefError(
71+
`Unsupported platform "${options.platform}". Please specify either "ios" or "android".`
72+
);
73+
}
74+
}
75+
76+
export const fingerprintPlugin = () => (api: PluginApi) => {
77+
api.registerCommand({
78+
name: 'fingerprint',
79+
description: 'Calculate fingerprint for given platform',
80+
action: async (path, options) => {
81+
const fingerprintOptions = api.getFingerprintOptions();
82+
await nativeFingerprintCommand(path, fingerprintOptions, options);
83+
},
84+
options: [
85+
{
86+
name: '-p, --platform <string>',
87+
description: 'Select platform, e.g. ios or android',
88+
},
89+
{
90+
name: '--raw',
91+
description: 'Output the raw fingerprint hash for piping',
92+
},
93+
],
94+
args: [
95+
{ name: '[path]', description: 'Directory to calculate fingerprint for' },
96+
],
97+
});
98+
99+
return {
100+
name: 'internal_fingerprint',
101+
description: 'Fingerprint plugin',
102+
};
103+
};

packages/cli/src/config.ts renamed to packages/cli/src/lib/plugins/logConfig.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type {
22
Config,
33
DependencyConfig,
44
} from '@react-native-community/cli-types';
5-
import type { ConfigOutput } from '@rnef/config';
5+
import type { ConfigOutput, PluginApi } from '@rnef/config';
66

77
function isValidRNDependency(config: DependencyConfig) {
88
return (
@@ -28,7 +28,10 @@ function filterConfig(config: Config) {
2828

2929
export const logConfig = async (
3030
args: { platform?: string },
31-
ownConfig: ConfigOutput
31+
ownConfig: {
32+
platforms: ConfigOutput['platforms'];
33+
root: ConfigOutput['root'];
34+
}
3235
) => {
3336
const { loadConfigAsync } = await import(
3437
'@react-native-community/cli-config'
@@ -49,3 +52,29 @@ export const logConfig = async (
4952

5053
console.log(JSON.stringify(filterConfig(config), null, 2));
5154
};
55+
56+
export const logConfigPlugin =
57+
(ownConfig: {
58+
platforms: ConfigOutput['platforms'];
59+
root: ConfigOutput['root'];
60+
}) =>
61+
(api: PluginApi) => {
62+
api.registerCommand({
63+
name: 'config',
64+
description: 'Output autolinking config',
65+
action: async (args) => {
66+
await logConfig(args, ownConfig);
67+
},
68+
options: [
69+
{
70+
name: '-p, --platform <string>',
71+
description: 'Select platform, e.g. ios or android',
72+
},
73+
],
74+
});
75+
76+
return {
77+
name: 'internal_config',
78+
description: 'Configuration plugin',
79+
};
80+
};

packages/config/src/lib/__tests__/config.test.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ test.each([['.js'], ['.mjs'], ['.ts']])(
2727
plugins: [],
2828
}`,
2929
});
30-
const config = await getConfig(DIR);
30+
const config = await getConfig(DIR, []);
3131
expect(config).toMatchObject({ commands: [] });
3232
}
3333
);
@@ -52,7 +52,7 @@ module.exports = {
5252
};
5353
`,
5454
});
55-
const config = await getConfig(DIR);
55+
const config = await getConfig(DIR, []);
5656
expect(config).toMatchObject({
5757
commands: [
5858
{
@@ -67,15 +67,11 @@ module.exports = {
6767
test('should load plugin that registers a command', async () => {
6868
const __dirname = dirname(fileURLToPath(import.meta.url));
6969
const config = await getConfig(
70-
join(__dirname, './__fixtures__/config-with-sample-plugin')
70+
join(__dirname, './__fixtures__/config-with-sample-plugin'),
71+
[]
7172
);
7273
expect(config).toMatchObject({
7374
commands: [
74-
{
75-
action: expect.any(Function),
76-
description: 'Test command',
77-
name: 'test-command',
78-
},
7975
{
8076
action: expect.any(Function),
8177
description: 'Build android',
@@ -108,6 +104,11 @@ test('should load plugin that registers a command', async () => {
108104
},
109105
],
110106
},
107+
{
108+
action: expect.any(Function),
109+
description: 'Test command',
110+
name: 'test-command',
111+
},
111112
],
112113
});
113114
});

packages/config/src/lib/config.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,15 @@ const importUp = async (
117117
return importUp(parentDir, name);
118118
};
119119

120-
export async function getConfig(dir: string): Promise<ConfigOutput> {
120+
export async function getConfig(
121+
dir: string,
122+
internalPlugins: Array<
123+
(ownConfig: {
124+
platforms: ConfigOutput['platforms'];
125+
root: ConfigOutput['root'];
126+
}) => PluginType
127+
>
128+
): Promise<ConfigOutput> {
121129
const { config, filePathWithExt, configDir } = await importUp(
122130
dir,
123131
'rnef.config'
@@ -167,13 +175,6 @@ export async function getConfig(dir: string): Promise<ConfigOutput> {
167175
},
168176
};
169177

170-
if (validatedConfig.plugins) {
171-
// plugins register commands
172-
for (const plugin of validatedConfig.plugins) {
173-
assignOriginToCommand(plugin, api, validatedConfig);
174-
}
175-
}
176-
177178
const platforms: Record<string, PlatformOutput> = {};
178179
if (validatedConfig.platforms) {
179180
// platforms register commands and custom platform functionality (TBD)
@@ -183,10 +184,25 @@ export async function getConfig(dir: string): Promise<ConfigOutput> {
183184
}
184185
}
185186

187+
if (validatedConfig.plugins) {
188+
// plugins register commands
189+
for (const plugin of validatedConfig.plugins) {
190+
assignOriginToCommand(plugin, api, validatedConfig);
191+
}
192+
}
193+
186194
if (validatedConfig.bundler) {
187195
assignOriginToCommand(validatedConfig.bundler, api, validatedConfig);
188196
}
189197

198+
for (const internalPlugin of internalPlugins) {
199+
assignOriginToCommand(
200+
internalPlugin({ root: projectRoot, platforms }),
201+
api,
202+
validatedConfig
203+
);
204+
}
205+
190206
const outputConfig: ConfigOutput = {
191207
root: projectRoot,
192208
commands: validatedConfig.commands ?? [],

0 commit comments

Comments
 (0)