Skip to content

Commit ceed347

Browse files
committed
feat: allow providing custom runner per transform file thru CodeshiftConfig
depends on: - hypermod-io#63 example on how it could be used: - https://github.com/pipedrive/CodeshiftCommunity/pull/22 - though note we might refactor into separate PRs, idk, preferably would use directly from upstream (you). fixes a lot of cases for us: 1. we have a postcss codemod that we want to run, while still utilizing the @codeshift/cli. though, i don't know if these changes will work if we're using a remote package, will they? 2. we'll want to do some global pre-processing on files before running our codemod. though, there's still no way to provide the codemod as a __function__ instead of an __import path__ to jscodeshift, which will force us to do dependency injection instead of just passing the pre-processed results as an argument to a function. this is where the considerations to fork jscodeshift come into play again: - hypermod-io#67 Signed-off-by: Kipras Melnikovas <[email protected]>
1 parent e28a6e6 commit ceed347

File tree

2 files changed

+123
-15
lines changed

2 files changed

+123
-15
lines changed

packages/cli/src/main.ts

Lines changed: 103 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import merge from 'lodash/merge';
66
// @ts-ignore Run transform(s) on path https://github.com/facebook/jscodeshift/issues/398
77
import * as jscodeshift from 'jscodeshift/src/Runner';
88
import { isValidConfig } from '@codeshift/validator';
9-
import { CodeshiftConfig } from '@codeshift/types';
9+
import {
10+
CodeshiftConfig, //
11+
DefaultRunner,
12+
} from '@codeshift/types';
1013

1114
import { Flags } from './types';
1215
import { InvalidUserInputError } from './errors';
@@ -218,20 +221,105 @@ Make sure the package name ${pkgName} has been spelled correctly and exists befo
218221
const resolvedTransformPath = path.resolve(transform);
219222
console.log(chalk.green('Running transform:'), resolvedTransformPath);
220223

221-
await jscodeshift.run(resolvedTransformPath, paths, {
222-
verbose: 0,
223-
dry: flags.dry,
224-
print: true,
225-
babel: true,
226-
extensions: flags.extensions,
227-
ignorePattern: flags.ignorePattern,
228-
cpus: flags.cpus,
229-
ignoreConfig: [],
230-
runInBand: flags.runInBand,
231-
silent: false,
232-
parser: flags.parser,
233-
stdin: false,
234-
});
224+
const defaultRunner: DefaultRunner = (
225+
jscodeshiftOptionOverrides = {},
226+
pathsToModify = paths,
227+
/**
228+
* ideally you'd be able to pass in either the path,
229+
* or the actual transform,
230+
* but jscodeshift doesn't allow this (unless we fork?)
231+
*/
232+
transformerPath: string = resolvedTransformPath,
233+
/**
234+
* i think the jscodeshift.run is synchronous
235+
* so the promise is not needed,
236+
* but if we want to change it in the future,
237+
* making it's return type a promise will help
238+
* to avoid breaking changes for consumers who
239+
* use the defaultRunner.
240+
*/
241+
): Promise<void> =>
242+
jscodeshift.run(transformerPath, pathsToModify, {
243+
verbose: 0,
244+
dry: flags.dry,
245+
print: true,
246+
babel: true,
247+
extensions: flags.extensions,
248+
ignorePattern: flags.ignorePattern,
249+
cpus: flags.cpus,
250+
ignoreConfig: [],
251+
runInBand: flags.runInBand,
252+
silent: false,
253+
parser: flags.parser,
254+
stdin: false,
255+
...jscodeshiftOptionOverrides,
256+
});
257+
258+
let transformImported: any;
259+
try {
260+
/**
261+
* TODO MAINTAINER -- i am not confident that this will work
262+
* if the transform was provided thru an npm package.
263+
*/
264+
265+
// eslint-disable-next-line @typescript-eslint/no-var-requires
266+
transformImported = require(resolvedTransformPath);
267+
} catch (_e) {}
268+
console.log({ transformImported });
269+
270+
const transformHasCustomRunner = (
271+
ti: any,
272+
): ti is {
273+
/**
274+
* ideally, `default` would be the type of the transformer,
275+
* which would be identical to the type of the argument to
276+
* `CustomTransformerConfig`,
277+
*
278+
* but unless we put the transformer itself into the config,
279+
* we cannot ensure that the type is correct.
280+
*
281+
*/
282+
default: unknown; //
283+
codeshiftConfig: CodeshiftConfig<unknown>;
284+
} => {
285+
if (ti && 'codeshiftConfig' in ti) {
286+
return 'runner' in transformImported['codeshiftConfig'];
287+
}
288+
return false;
289+
};
290+
291+
if (transformHasCustomRunner(transformImported)) {
292+
console.info(
293+
'\nusing CUSTOM runner for transform',
294+
resolvedTransformPath,
295+
);
296+
297+
await transformImported.codeshiftConfig.runner(paths, {
298+
defaultRunner,
299+
/**
300+
* providing the `transform`, `resolvedTransformPath`, etc. here
301+
* is quite useless, because it's file-based,
302+
* so in whichever file the config is in,
303+
* that default export will be the transform,
304+
* and the file's path will be the resolved path.
305+
*
306+
* ...unless you have a custom runner defined in a separate file,
307+
* and want it to be able to access the transform,
308+
* esp. if that runner does not take in a path,
309+
* but rather the transform function.
310+
*/
311+
transformInsideFileThatSpecifiesCodeshiftConfig:
312+
transformImported.default,
313+
// resolvedTransformPath
314+
});
315+
} else {
316+
console.info(
317+
'\nusing DEFAULT runner for transform',
318+
resolvedTransformPath,
319+
);
320+
321+
defaultRunner();
322+
}
235323
}
236324

237325
await packageManager.uninstallAll();

packages/types/src/index.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,23 @@ export interface CodeshiftConfig {
55
transforms?: Record<string, string>;
66
presets?: Record<string, string>;
77
}
8+
9+
export type DefaultRunner = (
10+
jscodeshiftOptionOverrides?: object,
11+
pathsToModify?: string[], //
12+
transformerPath?: string,
13+
) => Promise<void>;
14+
15+
export interface CustomRunnerCtx<Transform = unknown> {
16+
transformInsideFileThatSpecifiesCodeshiftConfig: Transform;
17+
defaultRunner: DefaultRunner;
18+
}
19+
20+
export type CustomRunner<Transform = unknown> = (
21+
pathsToModify: string[], //
22+
options: CustomRunnerCtx<Transform>,
23+
) => void | Promise<void>;
24+
25+
export interface CodeshiftConfig<Transform = unknown> {
26+
runner: CustomRunner<Transform>;
27+
}

0 commit comments

Comments
 (0)