Skip to content

Commit b7f614e

Browse files
author
Daniel Del Core
committed
checks remote module entrypoints for config files
1 parent f8748bd commit b7f614e

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

.changeset/hot-cars-leave.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@codeshift/fetcher': patch
3+
'@codeshift/cli': patch
4+
---
5+
6+
Correctly checks remote pacakge entrypoints for configs (as opposed to just checking for codeshift.config.js files)

packages/cli/src/list.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ describe('list', () => {
2424
})),
2525
}));
2626
});
27+
2728
afterEach(() => {
2829
jest.resetAllMocks();
2930
});
@@ -37,6 +38,12 @@ describe('list', () => {
3738
├─ transforms
3839
| ├─ 18.0.0
3940
| └─ 19.0.0
41+
└─ presets
42+
└─ sort-imports
43+
${chalk.bold('foobar')}
44+
├─ transforms
45+
| ├─ 18.0.0
46+
| └─ 19.0.0
4047
└─ presets
4148
└─ sort-imports`);
4249
expect(console.warn).not.toHaveBeenCalled();
@@ -51,6 +58,12 @@ describe('list', () => {
5158
├─ transforms
5259
| ├─ 18.0.0
5360
| └─ 19.0.0
61+
└─ presets
62+
└─ sort-imports
63+
${chalk.bold('@foo/bar')}
64+
├─ transforms
65+
| ├─ 18.0.0
66+
| └─ 19.0.0
5467
└─ presets
5568
└─ sort-imports`);
5669
expect(console.warn).not.toHaveBeenCalled();
@@ -65,12 +78,24 @@ describe('list', () => {
6578
├─ transforms
6679
| ├─ 18.0.0
6780
| └─ 19.0.0
81+
└─ presets
82+
└─ sort-imports
83+
${chalk.bold('bar')}
84+
├─ transforms
85+
| ├─ 18.0.0
86+
| └─ 19.0.0
6887
└─ presets
6988
└─ sort-imports
7089
${chalk.bold('@codeshift/mod-foo__bar')}
7190
├─ transforms
7291
| ├─ 18.0.0
7392
| └─ 19.0.0
93+
└─ presets
94+
└─ sort-imports
95+
${chalk.bold('@foo/bar')}
96+
├─ transforms
97+
| ├─ 18.0.0
98+
| └─ 19.0.0
7499
└─ presets
75100
└─ sort-imports`);
76101
expect(console.warn).not.toHaveBeenCalled();
@@ -136,12 +161,24 @@ ${chalk.bold('@codeshift/mod-foo__bar')}
136161
├─ transforms
137162
| ├─ 18.0.0
138163
| └─ 19.0.0
164+
└─ presets
165+
└─ sort-imports
166+
${chalk.bold('found1')}
167+
├─ transforms
168+
| ├─ 18.0.0
169+
| └─ 19.0.0
139170
└─ presets
140171
└─ sort-imports
141172
${chalk.bold('@codeshift/mod-found2')}
142173
├─ transforms
143174
| ├─ 18.0.0
144175
| └─ 19.0.0
176+
└─ presets
177+
└─ sort-imports
178+
${chalk.bold('found2')}
179+
├─ transforms
180+
| ├─ 18.0.0
181+
| └─ 19.0.0
145182
└─ presets
146183
└─ sort-imports`);
147184

packages/fetcher/src/index.spec.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ describe('fetcher', () => {
137137
it('correctly fetches package and returns a config', async () => {
138138
const mockPackageManager = {
139139
install: jest.fn(),
140+
require: jest
141+
.fn()
142+
.mockReturnValueOnce({}) // fail the entrypoint config check
143+
.mockReturnValueOnce(mockConfig),
140144
getInfo: jest.fn().mockReturnValue({
141145
location: mockBasePath,
142146
}),
@@ -166,6 +170,60 @@ describe('fetcher', () => {
166170
).rejects.toEqual('Import error');
167171
});
168172

173+
it('correctly fetches package and returns an entrypoint-based config', async () => {
174+
const mockPackageManager = {
175+
install: jest.fn(),
176+
require: jest.fn().mockReturnValueOnce(mockConfig),
177+
getInfo: jest.fn().mockReturnValue({
178+
location: mockBasePath + '/index.js',
179+
}),
180+
};
181+
182+
const { config, filePath } = await fetchRemotePackage(
183+
'fake-package',
184+
mockPackageManager as unknown as PluginManager,
185+
);
186+
187+
expect(config).toEqual(mockConfig);
188+
expect(filePath).toEqual(mockBasePath + '/index.js');
189+
});
190+
191+
it('throws if entrypoint-based config does not contain a valid config (and there are no config files available elsewhere)', async () => {
192+
const mockPackageManager = {
193+
install: jest.fn(),
194+
require: jest.fn().mockReturnValueOnce({}),
195+
getInfo: jest.fn().mockReturnValue({
196+
location: mockBasePath + '/index.js',
197+
}),
198+
};
199+
200+
(globby as unknown as jest.Mock).mockImplementation(() =>
201+
Promise.resolve([]),
202+
);
203+
204+
const res = await fetchRemotePackage(
205+
'fake-package',
206+
mockPackageManager as unknown as PluginManager,
207+
);
208+
209+
expect(res).toBeUndefined();
210+
});
211+
212+
it('should throw if fetching fails', async () => {
213+
const mockPackageManager = {
214+
install: jest.fn().mockRejectedValue('Import error'),
215+
};
216+
217+
expect.assertions(1);
218+
219+
await expect(
220+
fetchRemotePackage(
221+
'fake-package',
222+
mockPackageManager as unknown as PluginManager,
223+
),
224+
).rejects.toEqual('Import error');
225+
});
226+
169227
it('should throw if package source cannot be retrieved', async () => {
170228
const mockPackageManager = {
171229
install: jest.fn(),

packages/fetcher/src/index.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ export async function fetchConfig(filePath: string): Promise<ConfigMeta> {
3535

3636
export async function fetchConfigs(filePath: string): Promise<ConfigMeta[]> {
3737
const matchedPaths = await globby([
38+
path.join(filePath, 'hypermod.config.(js|ts|tsx)'),
39+
path.join(filePath, 'src', 'hypermod.config.(js|ts|tsx)'),
40+
path.join(filePath, 'codemods', 'hypermod.config.(js|ts|tsx)'),
3841
path.join(filePath, 'codeshift.config.(js|ts|tsx)'),
3942
path.join(filePath, 'src', 'codeshift.config.(js|ts|tsx)'),
4043
path.join(filePath, 'codemods', 'codeshift.config.(js|ts|tsx)'),
@@ -101,5 +104,20 @@ export async function fetchRemotePackage(
101104
);
102105
}
103106

107+
// Search main entrypoint for transform/presets from the default import
108+
try {
109+
const pkg = packageManager.require(packageName);
110+
const configExport = resolveConfigExport(pkg);
111+
112+
if (configExport.transforms || configExport.presets) {
113+
return {
114+
filePath: info.location,
115+
config: resolveConfigExport(pkg),
116+
};
117+
}
118+
} catch (e) {
119+
// Swallow this error
120+
}
121+
104122
return await fetchConfig(info.location);
105123
}

0 commit comments

Comments
 (0)