From ea20de1ffa4450f3295de0b21822572098b15eee Mon Sep 17 00:00:00 2001 From: Daniel Del Core Date: Wed, 7 Feb 2024 14:52:07 +1100 Subject: [PATCH 1/2] rename CodeshiftConfig type to Config --- .changeset/stupid-mice-lay.md | 8 ++++++++ packages/cli/src/main.ts | 4 ++-- packages/cli/src/prompt.ts | 6 +++--- packages/fetcher/src/index.ts | 10 ++++------ packages/types/src/index.ts | 4 +++- packages/validator/src/index.ts | 16 ++++++++-------- 6 files changed, 28 insertions(+), 20 deletions(-) create mode 100644 .changeset/stupid-mice-lay.md diff --git a/.changeset/stupid-mice-lay.md b/.changeset/stupid-mice-lay.md new file mode 100644 index 000000000..94403e46d --- /dev/null +++ b/.changeset/stupid-mice-lay.md @@ -0,0 +1,8 @@ +--- +'@hypermod/validator': patch +'@hypermod/fetcher': patch +'@hypermod/types': patch +'@hypermod/cli': patch +--- + +Renames type `CodeshiftConfig` to `Config` (with backwards compatible alias) diff --git a/packages/cli/src/main.ts b/packages/cli/src/main.ts index 61b044598..f1ebf3741 100644 --- a/packages/cli/src/main.ts +++ b/packages/cli/src/main.ts @@ -8,7 +8,7 @@ import { PluginManager, PluginManagerOptions } from 'live-plugin-manager'; import { installPackage } from '@antfu/install-pkg'; import * as core from '@hypermod/core'; -import { CodeshiftConfig } from '@hypermod/types'; +import { Config } from '@hypermod/types'; import { fetchConfigAtPath, fetchConfigs } from '@hypermod/fetcher'; import { InvalidUserInputError } from './errors'; @@ -78,7 +78,7 @@ export default async function main( if (rootPackageJson && rootPackageJson.workspaces) { const configs = await (rootPackageJson.workspaces as string[]).reduce< - Promise<{ filePath: string; config: CodeshiftConfig }[]> + Promise<{ filePath: string; config: Config }[]> >(async (accum, filePath) => { const configs = await fetchConfigs(filePath); if (!configs.length) return accum; diff --git a/packages/cli/src/prompt.ts b/packages/cli/src/prompt.ts index 38d879cf1..3750c1ac0 100644 --- a/packages/cli/src/prompt.ts +++ b/packages/cli/src/prompt.ts @@ -1,8 +1,8 @@ import inquirer from 'inquirer'; -import { CodeshiftConfig } from '@hypermod/types'; +import { Config } from '@hypermod/types'; -export const getConfigPrompt = (config: CodeshiftConfig) => { +export const getConfigPrompt = (config: Config) => { const transforms = Object.keys(config.transforms || {}); const presets = Object.keys(config.presets || {}); @@ -22,7 +22,7 @@ export const getConfigPrompt = (config: CodeshiftConfig) => { }; export const getMultiConfigPrompt = ( - configs: { filePath: string; config: CodeshiftConfig }[], + configs: { filePath: string; config: Config }[], ) => { const choices = configs.reduce((accum, { filePath, config }) => { function mapToConfig(codemods: Record = {}) { diff --git a/packages/fetcher/src/index.ts b/packages/fetcher/src/index.ts index 7155a62cd..0862458aa 100644 --- a/packages/fetcher/src/index.ts +++ b/packages/fetcher/src/index.ts @@ -3,14 +3,14 @@ import path from 'path'; import globby from 'globby'; import { PluginManager } from 'live-plugin-manager'; -import { CodeshiftConfig } from '@hypermod/types'; +import { Config } from '@hypermod/types'; export interface ConfigMeta { filePath: string; - config: CodeshiftConfig; + config: Config; } -function resolveConfigExport(pkg: any): CodeshiftConfig { +function resolveConfigExport(pkg: any): Config { return pkg.default ? pkg.default : pkg; } @@ -62,9 +62,7 @@ export async function fetchConfigs(filePath: string): Promise { return configs; } -export async function fetchConfigAtPath( - filePath: string, -): Promise { +export async function fetchConfigAtPath(filePath: string): Promise { const resolvedFilePath = path.resolve(filePath); const exists = fs.existsSync(resolvedFilePath); diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index a9be9570e..cb8bf1374 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -1,7 +1,9 @@ -export interface CodeshiftConfig { +export interface Config { targets?: string[]; maintainers?: string[]; description?: string; transforms?: Record; presets?: Record; } + +export type CodeshiftConfig = Config; diff --git a/packages/validator/src/index.ts b/packages/validator/src/index.ts index 9e16abf0d..1e279f7fd 100644 --- a/packages/validator/src/index.ts +++ b/packages/validator/src/index.ts @@ -1,15 +1,15 @@ import semver from 'semver'; -import { CodeshiftConfig } from '@hypermod/types'; +import { Config } from '@hypermod/types'; import { fetchConfig } from '@hypermod/fetcher'; -function hasValidTransforms(config: CodeshiftConfig) { +function hasValidTransforms(config: Config) { if (!config.transforms) return true; return Object.entries(config.transforms).every(([key]) => semver.valid(key)); } -function hasValidPresets(config: CodeshiftConfig): boolean { +function hasValidPresets(config: Config): boolean { if (!config.presets) return true; return Object.entries(config.presets).every(([key]) => @@ -17,7 +17,7 @@ function hasValidPresets(config: CodeshiftConfig): boolean { ); } -function getInvalidProperties(config: CodeshiftConfig) { +function getInvalidProperties(config: Config) { const validProperties = [ 'maintainers', 'description', @@ -33,7 +33,7 @@ export function isValidPackageName(dir: string): boolean { return !!dir.match(/^(@[a-z0-9-~][a-z0-9-._~]*__)?[a-z0-9-~][a-z0-9-._~]*$/); } -export function isValidConfig(config: CodeshiftConfig) { +export function isValidConfig(config: Config) { return hasValidTransforms(config) && hasValidPresets(config); } @@ -44,10 +44,10 @@ export async function isValidConfigAtPath(filePath: string) { throw new Error(`Unable to locate config file at path: ${filePath}`); } - const invalidProperites = getInvalidProperties(configMeta.config); - if (invalidProperites.length) { + const invalidProperties = getInvalidProperties(configMeta.config); + if (invalidProperties.length) { throw new Error( - `Invalid transform ids found: ${invalidProperites.join(', ')}`, + `Invalid transform ids found: ${invalidProperties.join(', ')}`, ); } From 401823f75e28d11d7d94ace069fe4794812b474c Mon Sep 17 00:00:00 2001 From: Daniel Del Core Date: Wed, 7 Feb 2024 14:53:02 +1100 Subject: [PATCH 2/2] Fixes fetcher with typescript safe imports via configs --- .changeset/fair-flowers-sing.md | 5 +++++ .changeset/spotty-parrots-move.md | 5 +++++ packages/cli/src/main.ts | 6 ++++-- packages/fetcher/package.json | 10 +++++++++ packages/fetcher/src/index.ts | 34 +++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 .changeset/fair-flowers-sing.md create mode 100644 .changeset/spotty-parrots-move.md diff --git a/.changeset/fair-flowers-sing.md b/.changeset/fair-flowers-sing.md new file mode 100644 index 000000000..c6b8c9b16 --- /dev/null +++ b/.changeset/fair-flowers-sing.md @@ -0,0 +1,5 @@ +--- +'@hypermod/cli': patch +--- + +Patches selection of transform via local config prompt diff --git a/.changeset/spotty-parrots-move.md b/.changeset/spotty-parrots-move.md new file mode 100644 index 000000000..81c3d4cf8 --- /dev/null +++ b/.changeset/spotty-parrots-move.md @@ -0,0 +1,5 @@ +--- +'@hypermod/fetcher': minor +--- + +Adds typescript support for config requires. Now a config can be in TS/TSX etc. diff --git a/packages/cli/src/main.ts b/packages/cli/src/main.ts index f1ebf3741..beab93c85 100644 --- a/packages/cli/src/main.ts +++ b/packages/cli/src/main.ts @@ -164,9 +164,11 @@ export default async function main( if (config.transforms && config.transforms[answers.codemod]) { Object.entries(config.transforms) .filter(([key]) => semver.satisfies(key, `>=${answers.codemod}`)) - .forEach(([, path]) => transforms.push(path)); + .forEach(([, codemod]) => + transforms.push(`${configFilePath}@${codemod}`), + ); } else if (config.presets && config.presets[answers.codemod]) { - transforms.push(config.presets[answers.codemod]); + transforms.push(`${configFilePath}#${answers.codemod}`); } } } diff --git a/packages/fetcher/package.json b/packages/fetcher/package.json index 5092571c0..1ce18a7b3 100644 --- a/packages/fetcher/package.json +++ b/packages/fetcher/package.json @@ -7,7 +7,17 @@ "license": "MIT", "repository": "https://github.com/hypermod-io/hypermod-community/tree/main/packages/fetcher", "dependencies": { + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.16", + "@babel/register": "^7.13.16", "@hypermod/types": "*", + "babel-core": "^7.0.0-bridge.0", "chalk": "^4.1.0", "fs-extra": "^9.1.0", "globby": "^11.1.0", diff --git a/packages/fetcher/src/index.ts b/packages/fetcher/src/index.ts index 0862458aa..d1d1e1c87 100644 --- a/packages/fetcher/src/index.ts +++ b/packages/fetcher/src/index.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ import fs from 'fs'; import path from 'path'; import globby from 'globby'; @@ -5,6 +6,39 @@ import { PluginManager } from 'live-plugin-manager'; import { Config } from '@hypermod/types'; +// This configuration allows us to require TypeScript config files directly +const { DEFAULT_EXTENSIONS } = require('@babel/core'); +const presets = []; + +let presetEnv; +try { + presetEnv = require('@babel/preset-env'); + presets.push([presetEnv.default, { targets: { node: true } }]); +} catch (_) {} + +require('@babel/register')({ + configFile: false, + babelrc: false, + presets: [...presets, require('@babel/preset-typescript').default], + plugins: [ + require('@babel/plugin-transform-class-properties').default, + require('@babel/plugin-transform-nullish-coalescing-operator').default, + require('@babel/plugin-transform-optional-chaining').default, + require('@babel/plugin-transform-modules-commonjs').default, + require('@babel/plugin-transform-private-methods').default, + ], + extensions: [...DEFAULT_EXTENSIONS, '.ts', '.tsx'], + // By default, babel register only compiles things inside the current working directory. + // https://github.com/babel/babel/blob/2a4f16236656178e84b05b8915aab9261c55782c/packages/babel-register/src/node.js#L140-L157 + ignore: [ + // Ignore parser related files + /@babel\/parser/, + /\/flow-parser\//, + /\/recast\//, + /\/ast-types\//, + ], +}); + export interface ConfigMeta { filePath: string; config: Config;