diff --git a/packages/cli/index.mjs b/packages/cli/index.mjs new file mode 100644 index 00000000..147a5877 --- /dev/null +++ b/packages/cli/index.mjs @@ -0,0 +1 @@ +export * from './index.cjs'; diff --git a/packages/cli/package.json b/packages/cli/package.json index 27184018..adcf65ca 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@ag-grid-devtools/cli", - "version": "32.0.2", + "version": "32.0.3", "license": "MIT", "description": "AG Grid developer toolkit", "author": "AG Grid ", @@ -33,7 +33,31 @@ }, "pkg": { "main": "./index.cjs", - "bin": "./index.cjs" + "bin": "./index.cjs", + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.cjs", + "default": "./index.mjs" + }, + "./index": { + "import": "./index.mjs", + "require": "./index.cjs", + "default": "./index.mjs" + }, + "./index.js": "./index.mjs", + "./index.mjs": "./index.mjs", + "./index.cjs": "./index.cjs", + "./user-config": { + "import": "./user-config.mjs", + "require": "./user-config.cjs", + "default": "./user-config.mjs" + }, + "./user-config.js": "./user-config.mjs", + "./user-config.mjs": "./user-config.mjs", + "./user-config.cjs": "./user-config.cjs", + "./package.json": "./package.json" + } }, "types": "./index.d.ts", "bundleDependencies": [ @@ -58,7 +82,8 @@ "graceful-fs": "4.2.11", "ignore": "5.3.1", "semver": "7.6.2", - "vite-plugin-dts": "3.9.1" + "vite-plugin-dts": "3.9.1", + "vite-plugin-static-copy": "1.0.6" }, "peerDependencies": { "eslint": "^8", diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 95f111ab..1e988ec6 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -71,12 +71,7 @@ export async function cli(args: Array, cli: CliOptions): Promise { throw null; } - // Add typescript support by loading tsx - try { - dynamicRequire.require('tsx/cjs', import.meta); - } catch { - // ignore error if tsx could not be loaded - } + dynamicRequire.initialize(); const task = match(options.command, { Migrate: ({ args }) => migrate(args, cli), diff --git a/packages/cli/src/commands/migrate.ts b/packages/cli/src/commands/migrate.ts index d80cb07b..f76d3b81 100644 --- a/packages/cli/src/commands/migrate.ts +++ b/packages/cli/src/commands/migrate.ts @@ -446,29 +446,29 @@ async function migrate( // Create a worker pool to run the codemods in parallel let scriptPath: string | URL = dynamicRequire.resolve(WORKER_PATH, import.meta); - const resolvedCodemodPaths = codemodPaths.map((codemodPath) => - dynamicRequire.resolve(codemodPath, import.meta), - ); + // This will be true if we are trying to run from the codemod repo source code using tsx or vitest + const isTsSourceCodeWorker = scriptPath.endsWith('.ts'); const config: WorkerOptions = { // Pass the list of codemod paths to the worker via workerData workerData: { - codemodPaths: resolvedCodemodPaths, + codemodPaths: isTsSourceCodeWorker + ? codemodPaths.map((codemodPath) => dynamicRequire.resolve(codemodPath, import.meta)) + : codemodPaths, userConfigPath, }, env: process.env, argv: [scriptPath], - eval: true, + eval: isTsSourceCodeWorker, }; + const workerCodeOrPath = isTsSourceCodeWorker + ? `try { require("tsx/cjs"); } catch (_) {} require(${JSON.stringify(scriptPath)});` + : scriptPath; + const workers = Array.from( { length: numWorkers }, - () => - new Worker( - // Try to add typescript support by loading tsx and load the worker script - `try { require("tsx/cjs"); } catch (_) {} require(${JSON.stringify(scriptPath)});`, - config, - ), + () => new Worker(workerCodeOrPath, config), ); const workerPool = new WorkerTaskQueue(workers); return executeCodemodMultiThreaded(workerPool, inputFilePaths, { diff --git a/packages/cli/user-config.mjs b/packages/cli/user-config.mjs new file mode 100644 index 00000000..bda6c062 --- /dev/null +++ b/packages/cli/user-config.mjs @@ -0,0 +1 @@ +export * from './user-config.cjs'; diff --git a/packages/cli/vite.config.mts b/packages/cli/vite.config.mts index 9ce78913..f7408187 100644 --- a/packages/cli/vite.config.mts +++ b/packages/cli/vite.config.mts @@ -1,6 +1,7 @@ import { resolve } from 'path'; import { defineConfig, mergeConfig } from 'vite'; import dts from 'vite-plugin-dts'; +import { viteStaticCopy } from 'vite-plugin-static-copy'; import base from '../build-config/templates/vite/cli.vite.config'; @@ -29,6 +30,12 @@ export default mergeConfig( bundledPackages: ['@ag-grid-devtools/types'], exclude: ['node_modules/**', '*.config.mts', '**/*.test.ts', 'package.json', 'index.ts'], }), + viteStaticCopy({ + targets: [ + { src: 'index.mjs', dest: '.' }, + { src: 'user-config.mjs', dest: '.' }, + ], + }), ], }), ); diff --git a/packages/utils/package.json b/packages/utils/package.json index f7bcb9f0..e285a419 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -43,7 +43,9 @@ "@ag-grid-devtools/types": "workspace:*" }, "devDependencies": { - "@ag-grid-devtools/build-config": "workspace:*" + "@ag-grid-devtools/build-config": "workspace:*", + "@types/app-module-path": "^2.2.2", + "app-module-path": "2.2.0" }, "peerDependencies": { "eslint": "^8", diff --git a/packages/utils/src/module.ts b/packages/utils/src/module.ts index d7a7c05b..0c5ad96e 100644 --- a/packages/utils/src/module.ts +++ b/packages/utils/src/module.ts @@ -1,20 +1,68 @@ -import { createRequire } from 'node:module'; +import { fileURLToPath } from 'node:url'; +import { createRequire, Module } from 'node:module'; +import { existsSync } from 'node:fs'; +import { addPath as addNodeModulePath } from 'app-module-path'; +import { dirname, resolve as pathResolve, join as pathJoin } from 'node:path'; + +let initialized = false; + +const thisDir = pathResolve( + import.meta.url + ? dirname(fileURLToPath(import.meta.url)) + : typeof __dirname !== 'undefined' + ? __dirname + : process.cwd(), +); export const dynamicRequire = { - resolve(path: string, meta: ImportMeta): string { - if (meta.url === undefined && typeof require !== undefined) { - // import.meta not available, maybe running a ts file with tsx? use default cjs require - return require.resolve(path); + initialize() { + if (initialized) { + return; + } + initialized = true; + + // Register node_modules paths + + let currentDir = thisDir; + while (currentDir) { + if (currentDir.endsWith('node_modules')) { + tryAddNodeModulePath(currentDir); + break; + } + tryAddNodeModulePath(pathJoin(currentDir, 'node_modules')); + let parentDir = dirname(currentDir); + if (parentDir === currentDir) { + break; + } + currentDir = parentDir; + } + + // Add typescript support by loading tsx + try { + dynamicRequire.require('tsx/cjs', import.meta); + } catch { + // ignore error if tsx could not be loaded + } + + // Register .cjs and .cts extensions + + const exts = (Module as any)._extensions; + if (exts && !('.cjs' in exts)) { + exts['.cjs'] = exts['.js']; + } + if (exts && !('.cts' in exts) && '.ts' in exts) { + exts['.cts'] = exts['.ts']; } - return createRequire(meta.url).resolve(path); + }, + + resolve(path: string, meta: ImportMeta): string { + dynamicRequire.initialize(); + return createRequire(meta.url || pathResolve(thisDir, 'index.js')).resolve(path); }, require(path: string, meta: ImportMeta): T { - if (meta.url === undefined && typeof require !== undefined) { - // import.meta not available, maybe running a ts file with tsx? use default cjs require - return require(path); - } - return createRequire(meta.url)(path); + dynamicRequire.initialize(); + return createRequire(meta.url || pathResolve(thisDir, 'index.js'))(path); }, /** Like require, but supports modules with a default export transpiled to cjs */ @@ -32,3 +80,13 @@ export const dynamicRequire = { return required; }, }; + +function tryAddNodeModulePath(nodeModulesPath: string) { + try { + if (existsSync(nodeModulesPath)) { + addNodeModulePath(nodeModulesPath); + } + } catch { + // ignore error + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dc2f06e2..e9814387 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -247,6 +247,9 @@ importers: vite-plugin-dts: specifier: 3.9.1 version: 3.9.1(@types/node@20.14.10)(rollup@4.18.0)(typescript@5.2.2)(vite@5.0.11(@types/node@20.14.10)) + vite-plugin-static-copy: + specifier: 1.0.6 + version: 1.0.6(vite@5.0.11(@types/node@20.14.10)) packages/codemod-task-utils: dependencies: @@ -521,6 +524,12 @@ importers: '@ag-grid-devtools/build-config': specifier: workspace:* version: link:../build-config + '@types/app-module-path': + specifier: ^2.2.2 + version: 2.2.2 + app-module-path: + specifier: 2.2.0 + version: 2.2.0 packages/worker-utils: dependencies: @@ -1468,6 +1477,9 @@ packages: '@swc/types@0.1.9': resolution: {integrity: sha512-qKnCno++jzcJ4lM4NTfYifm1EFSCeIfKiAHAfkENZAV5Kl9PjJIyd2yeeVv6c/2CckuLyv2NmRC5pv6pm2WQBg==} + '@types/app-module-path@2.2.2': + resolution: {integrity: sha512-1Mnb53+j2cSmnc+rKxVxcQvfJyPpm7DjHTedaNTXVhj5AIAZpVjb2jbRdwYpguISutIYuVFKWx+U/QDZuOJ8vg==} + '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} @@ -1688,6 +1700,9 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + app-module-path@2.2.0: + resolution: {integrity: sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ==} + arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -4103,6 +4118,8 @@ snapshots: dependencies: '@swc/counter': 0.1.3 + '@types/app-module-path@2.2.2': {} + '@types/argparse@1.0.38': {} '@types/babel__core@7.20.3': @@ -4422,6 +4439,8 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + app-module-path@2.2.0: {} + arg@5.0.2: {} argparse@1.0.10: @@ -6081,6 +6100,14 @@ snapshots: transitivePeerDependencies: - rollup + vite-plugin-static-copy@1.0.6(vite@5.0.11(@types/node@20.14.10)): + dependencies: + chokidar: 3.5.3 + fast-glob: 3.3.1 + fs-extra: 11.2.0 + picocolors: 1.0.1 + vite: 5.0.11(@types/node@20.14.10) + vite-plugin-static-copy@1.0.6(vite@5.3.3(@types/node@20.14.10)): dependencies: chokidar: 3.5.3