Skip to content

Commit e5787a9

Browse files
committed
improves validator logic
1 parent 8a8517c commit e5787a9

File tree

8 files changed

+72
-13
lines changed

8 files changed

+72
-13
lines changed

.changeset/cool-clocks-behave.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@codeshift/cli': patch
3+
'@codeshift/fetcher': patch
4+
'@codeshift/validator': patch
5+
---
6+
7+
Updates validator logic to check for invalid properties in config files. Also requires configs via absolute paths to make the validation logic more robust

packages/cli/src/main.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ jest.mock('jscodeshift/src/Runner', () => ({
44
run: jest.fn().mockImplementation(() => Promise.resolve()),
55
}));
66

7+
import fs from 'fs';
78
import path from 'path';
89
// @ts-ignore
910
import * as jscodeshift from 'jscodeshift/src/Runner';
@@ -558,6 +559,7 @@ describe('main', () => {
558559
});
559560

560561
it('should run package transform for single version', async () => {
562+
jest.spyOn(fs, 'existsSync').mockReturnValue(true);
561563
jest.mock(
562564
mockMatchedPath,
563565
() => ({
@@ -589,6 +591,7 @@ describe('main', () => {
589591
});
590592

591593
it('should run single preset', async () => {
594+
jest.spyOn(fs, 'existsSync').mockReturnValue(true);
592595
await main([mockPath], {
593596
packages: 'mylib#update-formatting',
594597
parser: 'babel',

packages/cli/src/validate.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
import { isValidConfigAtPath, isValidPackageJson } from '@codeshift/validator';
22

33
export default async function validate(targetPath: string = '.') {
4-
try {
5-
await isValidConfigAtPath(targetPath);
6-
await isValidPackageJson(targetPath);
7-
} catch (error) {
8-
console.warn(error);
9-
process.exit(1);
10-
}
4+
await isValidConfigAtPath(targetPath);
5+
await isValidPackageJson(targetPath);
116

127
console.log('Valid ✅');
138
}

packages/fetcher/src/index.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
jest.mock('globby');
22

3-
import globby from 'globby';
3+
import fs from 'fs';
44
import path from 'path';
5+
import globby from 'globby';
56
import { PluginManager } from 'live-plugin-manager';
67

78
import { fetchConfig, fetchPackage, fetchRemotePackage } from '.';
@@ -27,6 +28,8 @@ describe('fetcher', () => {
2728
((globby as unknown) as jest.Mock).mockImplementation(() =>
2829
Promise.resolve(mockMatchedPaths),
2930
);
31+
32+
jest.spyOn(fs, 'existsSync').mockReturnValue(true);
3033
});
3134

3235
afterEach(() => {

packages/fetcher/src/index.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import fs from 'fs';
12
import path from 'path';
23
import globby from 'globby';
34
import { PluginManager } from 'live-plugin-manager';
@@ -18,11 +19,20 @@ export async function fetchConfig(
1819
]);
1920

2021
for (const matchedPath of matchedPaths) {
22+
const resolvedMatchedPath = path.resolve(matchedPath);
23+
const exists = fs.existsSync(resolvedMatchedPath);
24+
25+
if (!exists) continue;
26+
2127
try {
2228
// eslint-disable-next-line @typescript-eslint/no-var-requires
23-
const pkg = require(matchedPath);
29+
const pkg = require(resolvedMatchedPath);
2430
return resolveConfigExport(pkg);
25-
} catch (e) {}
31+
} catch (e) {
32+
throw new Error(
33+
`Found config file "${matchedPath}" but was unable to parse it. This can be caused when transform or preset paths are incorrect.`,
34+
);
35+
}
2636
}
2737

2838
return undefined;

packages/validator/src/index.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,28 @@ describe('validator', () => {
125125
expect(result).toEqual(true);
126126
});
127127

128+
it('should error if config contains an invalid property', async () => {
129+
(fetchConfig as jest.Mock).mockResolvedValue({
130+
invalidProperty: 'foo',
131+
});
132+
133+
await expect(isValidConfigAtPath('path/to/')).rejects.toThrowError(
134+
`Invalid transform ids found: invalidProperty`,
135+
);
136+
});
137+
138+
it('should error if config contains multiple invalid properties', async () => {
139+
(fetchConfig as jest.Mock).mockResolvedValue({
140+
invalidProperty: 'foo',
141+
invalidProperty2: 'foo',
142+
invalidProperty3: 'foo',
143+
});
144+
145+
await expect(isValidConfigAtPath('path/to/')).rejects.toThrowError(
146+
`Invalid transform ids found: invalidProperty, invalidProperty2, invalidProperty3`,
147+
);
148+
});
149+
128150
it('should error if config contains invalid transforms', async () => {
129151
(fetchConfig as jest.Mock).mockResolvedValue({
130152
transforms: {

packages/validator/src/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@ function hasValidPresets(config: CodeshiftConfig): boolean {
1919
);
2020
}
2121

22+
function getInvalidProperties(config: CodeshiftConfig) {
23+
const validProperties = [
24+
'maintainers',
25+
'description',
26+
'targets',
27+
'transforms',
28+
'presets',
29+
];
30+
31+
return Object.keys(config).filter(key => !validProperties.includes(key));
32+
}
33+
2234
export function isValidPackageName(dir: string): boolean {
2335
return !!dir.match(/^(@[a-z0-9-~][a-z0-9-._~]*__)?[a-z0-9-~][a-z0-9-._~]*$/);
2436
}
@@ -34,6 +46,13 @@ export async function isValidConfigAtPath(filePath: string) {
3446
throw new Error(`Unable to locate config file at path: ${filePath}`);
3547
}
3648

49+
const invalidProperites = getInvalidProperties(config);
50+
if (invalidProperites.length) {
51+
throw new Error(
52+
`Invalid transform ids found: ${invalidProperites.join(', ')}`,
53+
);
54+
}
55+
3756
if (!hasValidTransforms(config)) {
3857
throw new Error(`Invalid transform ids found for config at "${filePath}".
3958
Please make sure all transforms are identified by a valid semver version. ie 10.0.0`);

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,9 +2463,9 @@ camelcase@^6.0.0:
24632463
integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
24642464

24652465
caniuse-lite@^1.0.30001251:
2466-
version "1.0.30001252"
2467-
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001252.tgz#cb16e4e3dafe948fc4a9bb3307aea054b912019a"
2468-
integrity sha512-I56jhWDGMtdILQORdusxBOH+Nl/KgQSdDmpJezYddnAkVOmnoU8zwjTV9xAjMIYxr0iPreEAVylCGcmHCjfaOw==
2466+
version "1.0.30001332"
2467+
resolved "https://packages.atlassian.com/api/npm/npm-remote/caniuse-lite/-/caniuse-lite-1.0.30001332.tgz"
2468+
integrity sha512-10T30NYOEQtN6C11YGg411yebhvpnC6Z102+B95eAsN0oB6KUs01ivE8u+G6FMIRtIrVlYXhL+LUwQ3/hXwDWw==
24692469

24702470
capture-exit@^2.0.0:
24712471
version "2.0.0"

0 commit comments

Comments
 (0)