Skip to content

Commit

Permalink
feat: allow providing custom runner per transform file thru Codeshift…
Browse files Browse the repository at this point in the history
…Config

depends on: hypermod-io#63

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]>
  • Loading branch information
kiprasmel committed Jan 24, 2022
1 parent 2821bdb commit 582322d
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 14 deletions.
93 changes: 79 additions & 14 deletions packages/cli/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import chalk from 'chalk';
import { PluginManager } from 'live-plugin-manager';
// @ts-ignore Run transform(s) on path https://github.com/facebook/jscodeshift/issues/398
import * as jscodeshift from 'jscodeshift/src/Runner';
import {
CodeshiftConfig, //
DefaultRunner,
} from '@codeshift/types';

import { Flags } from './types';
import { InvalidUserInputError } from './errors';
Expand Down Expand Up @@ -130,20 +134,81 @@ export default async function main(paths: string[], flags: Flags) {
const resolvedTransformPath = path.resolve(transform);
console.log(chalk.green('Running transform:'), resolvedTransformPath);

await jscodeshift.run(resolvedTransformPath, paths, {
verbose: 0,
dry: flags.dry,
print: true,
babel: true,
extensions: flags.extensions,
ignorePattern: flags.ignorePattern,
cpus: flags.cpus,
ignoreConfig: [],
runInBand: flags.runInBand,
silent: false,
parser: flags.parser,
stdin: false,
});
const defaultRunner: DefaultRunner = (
/**
* ideally you'd be able to pass in either the path,
* or the actual transform,
* but jscodeshift doesn't allow this (unless we fork?)
*/
jscodeshiftOptionOverrides = {},
pathsToModify = paths,
transformerPath: string = resolvedTransformPath,
): Promise<void> =>
jscodeshift.run(transformerPath, pathsToModify, {
verbose: 0,
dry: flags.dry,
print: true,
babel: true,
extensions: flags.extensions,
ignorePattern: flags.ignorePattern,
cpus: flags.cpus,
ignoreConfig: [],
runInBand: flags.runInBand,
silent: false,
parser: flags.parser,
stdin: false,
...jscodeshiftOptionOverrides,
});

let transformImported: any;
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
transformImported = require(resolvedTransformPath);
} catch (_e) {}
console.log({ transformImported });

const transformHasCustomRunner = (
ti: any,
): ti is {
/**
* ideally, `default` would be the type of the transformer,
* which would be identical to the type of the argument to
* `CustomTransformerConfig`,
*
* but unless we put the transformer itself into the config,
* we cannot ensure that the type is correct.
*
*/
default: unknown; //
codeshiftConfig: CodeshiftConfig<unknown>;
} => {
if (ti && 'codeshiftConfig' in ti) {
return 'runner' in transformImported['codeshiftConfig'];
}
return false;
};

if (transformHasCustomRunner(transformImported)) {
await transformImported.codeshiftConfig.runner(paths, {
defaultRunner,
/**
* providing the `transform`, `resolvedTransformPath`, etc. here
* is quite useless, because it's file-based,
* so in whichever file the config is in,
* that default export will be the transform,
* and the file's path will be the resolved path.
*
* ...unless you have a custom runner defined in a separate file,
* and want it to be able to access the transform,
* esp. if that runner does not take in a path,
* but rather the transform function.
*/
transform: transformImported.default,
// resolvedTransformPath
});
} else {
defaultRunner();
}
}

await packageManager.uninstallAll();
Expand Down
27 changes: 27 additions & 0 deletions packages/types/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export interface CodeshiftConfig {
target?: string[];
maintainers?: string[];
description?: string;
transforms?: Record<string, string>;
presets?: Record<string, string>;
}

export type DefaultRunner = (
jscodeshiftOptionOverrides?: object,
pathsToModify?: string[], //
transformerPath?: string,
) => Promise<void>;

export interface CustomRunnerCtx<Transform = unknown> {
transform: Transform;
defaultRunner: DefaultRunner;
}

export type CustomRunner<Transform = unknown> = (
pathsToModify: string[], //
options: CustomRunnerCtx<Transform>,
) => void | Promise<void>;

export interface CodeshiftConfig<Transform = unknown> {
runner: CustomRunner<Transform>;
}

0 comments on commit 582322d

Please sign in to comment.