Skip to content

Commit bd47303

Browse files
committed
chore: improve error handling
1 parent cdef103 commit bd47303

6 files changed

Lines changed: 121 additions & 82 deletions

File tree

src/cli.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { cac } from 'cac';
44
import { readFileSync } from 'fs';
55
import { join } from 'path';
6-
import { processTransform } from './process-transform';
6+
import { perform } from './perform';
77

88
const PACKAGE_PATH = join(__dirname, '../package.json');
99
const PACKAGE_JSON = JSON.parse(readFileSync(PACKAGE_PATH, 'utf8'));
@@ -28,7 +28,7 @@ const run = async () => {
2828
.action(async (files: string, flags) => {
2929
const { transform } = flags;
3030

31-
await processTransform({ files, transform });
31+
await perform({ files, transform });
3232
});
3333

3434
cli.help();

src/files.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import fs from 'fs';
2+
import glob from 'glob';
3+
4+
export interface TransformFileInfo {
5+
/**
6+
* The file path for the current file being transformed.
7+
*/
8+
path: string;
9+
10+
/**
11+
* The file contents for the current file being transformed.
12+
*/
13+
source: string;
14+
}
15+
16+
export const getFileInfo = (file: string): TransformFileInfo => {
17+
try {
18+
const source = fs.readFileSync(file, 'utf8').toString();
19+
return { path: file, source };
20+
} catch (err) {
21+
console.error(`An error occurred trying to read "${file}": ${err}`);
22+
process.exit(1);
23+
}
24+
};
25+
26+
export const writeFile = (file: string, contents: string): void => {
27+
try {
28+
fs.writeFileSync(file, contents);
29+
} catch (err) {
30+
console.error(`An error occurred trying to write "${file}": ${err}`);
31+
}
32+
};
33+
34+
export const getAllFilesToTransform = (files: string) => glob.sync(files);

src/load-transform.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/perform.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { api } from './api';
2+
import { getAllFilesToTransform, getFileInfo, writeFile } from './files';
3+
import { loadTransform } from './transform';
4+
5+
interface ProcessTransformOptions {
6+
/**
7+
* The file path to process and run through the transform.
8+
*/
9+
files: string;
10+
11+
/**
12+
* The transform path to run each file through.
13+
*/
14+
transform: string;
15+
}
16+
17+
/**
18+
* Perform a transformation across a set of files.
19+
*/
20+
export const perform = async (options: ProcessTransformOptions) => {
21+
const transform = await loadTransform(options.transform);
22+
const files = getAllFilesToTransform(options.files);
23+
24+
files.map(file => {
25+
const fileInfo = getFileInfo(file);
26+
27+
try {
28+
const result = transform(fileInfo, api);
29+
30+
if (result !== null) {
31+
writeFile(file, result);
32+
}
33+
} catch (err) {
34+
if (err instanceof Error) {
35+
console.error(
36+
`The following error occurred transforming "${file}":\n ${err.message}`
37+
);
38+
} else {
39+
console.error(
40+
`An unexpected error occurred transforming "${file}": ${err}`
41+
);
42+
}
43+
}
44+
});
45+
};

src/process-transform.ts

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/transform.ts

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,51 @@
1+
import { bundleRequire } from 'bundle-require';
12
import { TransformAPI } from './api';
3+
import { TransformFileInfo } from './files';
24

3-
export interface TransformFileInfo {
4-
/**
5-
* The file path for the current file being transformed.
6-
*/
7-
path: string;
5+
const MINIMUM_TRANSFORM_EXAMPLE = `
6+
import { Transform } from "css-codemod";
87
9-
/**
10-
* The file contents for the current file being transformed.
11-
*/
12-
source: string;
13-
}
8+
export const transform: Transform = (fileInfo, api) => {};
9+
`;
1410

1511
export type Transform = (
1612
/**
1713
* Metadata for the current file being transformed.
1814
*/
1915
fileInfo: TransformFileInfo,
16+
17+
/**
18+
* Helpers injected by css-codemod.
19+
*/
2020
api: TransformAPI
2121
) => null | string;
22+
23+
/**
24+
* Validate the general structure of the transform to catch simple errors.
25+
*/
26+
const validateTransform = (transform: unknown): Transform => {
27+
if (typeof transform === 'function') {
28+
return transform as Transform;
29+
} else {
30+
console.error(
31+
`Transform file must export a valid transform. For example:\n${MINIMUM_TRANSFORM_EXAMPLE}`
32+
);
33+
process.exit(1);
34+
}
35+
};
36+
37+
/**
38+
* Load and validate the transform file given the filepath.
39+
*/
40+
export const loadTransform = async (filepath: string): Promise<Transform> => {
41+
try {
42+
const { mod } = await bundleRequire({ filepath });
43+
const transform = validateTransform(mod.transform || mod.default);
44+
return transform;
45+
} catch (err) {
46+
console.error(
47+
`An error occurred loading the transform file. Verify "${filepath}" exists.`
48+
);
49+
process.exit(1);
50+
}
51+
};

0 commit comments

Comments
 (0)