From 0c40068b82d4a5fa7e1a82593397e6b4fa8adb4c Mon Sep 17 00:00:00 2001 From: Stephen Hanson Date: Tue, 16 May 2023 12:35:10 -0500 Subject: [PATCH] Fix typescript issues, refactor a bit (#4) * Fix TypeScript issues Commander can automatically import files for us by specifying 'executableFile' for commands. This unfortunately doesn't work well with TypeScript, which was why we were using `node -r ts-node` to run the CLI instead of `ts-node`. This setup to get commander working was also causing other issues with file imports. This commit updates so we now manually import files for commands, which enables us to revert the less-conventional TypeScript config. * Refactor file structure, update how commands run Since the tool is only React Native for now, it didn't seem necessary to have the 'react-native' directory. Moved to 'src'. Also created utility for importing commands for commander * Run ts-node with esm loader This fixes the issue where we are unable to run packages that only export ES Modules. It's possible we will still run into some issues with this configuration since ESM support is still experimental on the TypeScript side. Relevant issue: https://github.com/TypeStrong/ts-node/issues/1007 ESM loader docs: https://typestrong.org/ts-node/docs/imports/#native-ecmascript-modules --- bin/belt | 2 +- index.ts | 16 ---------------- package.json | 1 + react-native/eslint.ts | 1 - react-native/prettier.ts | 1 - react-native/react-native.ts | 13 ------------- src/cli.ts | 25 +++++++++++++++++++++++++ src/commands/eslint.ts | 3 +++ src/commands/prettier.ts | 3 +++ src/util/buildAction.ts | 17 +++++++++++++++++ tsconfig.json | 13 +++++++------ 11 files changed, 57 insertions(+), 38 deletions(-) delete mode 100755 index.ts delete mode 100755 react-native/eslint.ts delete mode 100755 react-native/prettier.ts delete mode 100644 react-native/react-native.ts create mode 100644 src/cli.ts create mode 100755 src/commands/eslint.ts create mode 100755 src/commands/prettier.ts create mode 100644 src/util/buildAction.ts diff --git a/bin/belt b/bin/belt index 2770033..f96a09a 100755 --- a/bin/belt +++ b/bin/belt @@ -1,3 +1,3 @@ #!/usr/bin/env bash -node -r ts-node/register ./react-native/react-native.ts "$@" +yarn ts-node ./src/cli.ts "$@" diff --git a/index.ts b/index.ts deleted file mode 100755 index e67520d..0000000 --- a/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { program } from "commander"; - -program - .name("thoughtbelt") - .description( - "Perform project setup and redundant tasks without your pants falling down!" - ) - .command( - "react-native [options]", - "Perform a React Native task", - { executableFile: "react-native/react-native.ts" } - ) - .alias("rn") - .alias("expo") - .showHelpAfterError() - .parse(); diff --git a/package.json b/package.json index f499106..c1a1a44 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "description": "Monorepo for project bootstrapping CLIs", "main": "index.js", + "type": "module", "scripts": { "belt": "bin/belt", "test": "echo \"Error: no test specified\" && exit 1" diff --git a/react-native/eslint.ts b/react-native/eslint.ts deleted file mode 100755 index 22cd7ba..0000000 --- a/react-native/eslint.ts +++ /dev/null @@ -1 +0,0 @@ -console.log('ESLint!') diff --git a/react-native/prettier.ts b/react-native/prettier.ts deleted file mode 100755 index 828c5cf..0000000 --- a/react-native/prettier.ts +++ /dev/null @@ -1 +0,0 @@ -console.log("Prettier!"); diff --git a/react-native/react-native.ts b/react-native/react-native.ts deleted file mode 100644 index 24cbed0..0000000 --- a/react-native/react-native.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { program } from "commander"; - -console.log("React Native 🎉"); - -program - .name("thoughtbelt") - .description( - "Perform React Native and Expo setup and redundant tasks without your pants falling down!" - ) - .command("eslint", "Configure ESLint", { executableFile: "eslint.ts" }) - .command("prettier", "Configure Prettier", { executableFile: "prettier.ts" }) - .showHelpAfterError() - .parse(); diff --git a/src/cli.ts b/src/cli.ts new file mode 100644 index 0000000..ce238e1 --- /dev/null +++ b/src/cli.ts @@ -0,0 +1,25 @@ +import { program } from "commander"; +import buildAction from "./util/buildAction"; + +console.log("React Native 🎉"); + +export default function runCli() { + program + .name("thoughtbelt") + .description( + "Perform React Native and Expo setup and redundant tasks without your pants falling down!" + ) + + .command("eslint") + .description("Configure ESLint") + .action(buildAction(import("./commands/eslint"))); + + program + .command("prettier") + .description("Configure Prettier") + .action(buildAction(import("./commands/prettier"))); + + program.showHelpAfterError().parse(); +} + +runCli(); diff --git a/src/commands/eslint.ts b/src/commands/eslint.ts new file mode 100755 index 0000000..5f8c481 --- /dev/null +++ b/src/commands/eslint.ts @@ -0,0 +1,3 @@ +export default function runEslint() { + console.log("ESLint!"); +} diff --git a/src/commands/prettier.ts b/src/commands/prettier.ts new file mode 100755 index 0000000..5d3bb16 --- /dev/null +++ b/src/commands/prettier.ts @@ -0,0 +1,3 @@ +export default function runPrettier() { + console.log("Prettier!"); +} diff --git a/src/util/buildAction.ts b/src/util/buildAction.ts new file mode 100644 index 0000000..4013fef --- /dev/null +++ b/src/util/buildAction.ts @@ -0,0 +1,17 @@ +type AsyncModule = Promise<{ + default: (...args: unknown[]) => void; +}>; + +/** + * builds the action function that is passed to Commander's + * program.action. + * Eg: program.action( + * buildAction(import('./commands/prettier)) + * ) + */ +export default function buildAction(asyncModule: AsyncModule) { + return async (...args: unknown[]) => { + const module = await asyncModule; + module.default(args); + }; +} diff --git a/tsconfig.json b/tsconfig.json index d2ba263..d945246 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,18 @@ { "compilerOptions": { "allowSyntheticDefaultImports": true, - "lib": ["es2019"], "target": "es2019", - "module": "commonjs", - "strict": true, + "module": "ES2020", "moduleResolution": "node", - "noImplicitThis": true, - "noUnusedLocals": true, + "strict": true, "sourceMap": true, "outDir": "./build", "skipLibCheck": true, "types": ["node"] }, - "include": ["./**/*"], + "ts-node": { + "esm": true, + "experimentalSpecifierResolution": "node" + }, + "include": ["./**/*"] }