├── .gitignore ├── README.md ├── build.ts ├── bun.lockb ├── img └── tweet.png ├── package.json ├── src └── index.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Caches 14 | 15 | .cache 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | 19 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 20 | 21 | # Runtime data 22 | 23 | pids 24 | _.pid 25 | _.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 42 | 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | 47 | bower_components 48 | 49 | # node-waf configuration 50 | 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | 55 | build/Release 56 | 57 | # Dependency directories 58 | 59 | node_modules/ 60 | jspm_packages/ 61 | 62 | # Snowpack dependency directory (https://snowpack.dev/) 63 | 64 | web_modules/ 65 | 66 | # TypeScript cache 67 | 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | 72 | .npm 73 | 74 | # Optional eslint cache 75 | 76 | .eslintcache 77 | 78 | # Optional stylelint cache 79 | 80 | .stylelintcache 81 | 82 | # Microbundle cache 83 | 84 | .rpt2_cache/ 85 | .rts2_cache_cjs/ 86 | .rts2_cache_es/ 87 | .rts2_cache_umd/ 88 | 89 | # Optional REPL history 90 | 91 | .node_repl_history 92 | 93 | # Output of 'npm pack' 94 | 95 | *.tgz 96 | 97 | # Yarn Integrity file 98 | 99 | .yarn-integrity 100 | 101 | # dotenv environment variable files 102 | 103 | .env 104 | .env.development.local 105 | .env.test.local 106 | .env.production.local 107 | .env.local 108 | 109 | # parcel-bundler cache (https://parceljs.org/) 110 | 111 | .parcel-cache 112 | 113 | # Next.js build output 114 | 115 | .next 116 | out 117 | 118 | # Nuxt.js build / generate output 119 | 120 | .nuxt 121 | dist 122 | 123 | # Gatsby files 124 | 125 | # Comment in the public line in if your project uses Gatsby and not Next.js 126 | 127 | # https://nextjs.org/blog/next-9-1#public-directory-support 128 | 129 | # public 130 | 131 | # vuepress build output 132 | 133 | .vuepress/dist 134 | 135 | # vuepress v2.x temp and cache directory 136 | 137 | .temp 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ts-init 2 | 3 | A CLI tool to initialize a tsconfig based on Matt Pocock's [tsconfig cheat sheet](https://www.totaltypescript.com/tsconfig-cheat-sheet). 4 | 5 | made cause of this tweet [here](https://x.com/mattpocockuk/status/1834839649593794566) 6 | 7 | Alt text 8 | 9 | ### Install 10 | 11 | ```bash 12 | npm install -g @bekacru/ts-init 13 | ``` 14 | 15 | ### Usage 16 | 17 | ```bash 18 | npx ts-init 19 | ``` 20 | 21 | ### License 22 | 23 | MIT -------------------------------------------------------------------------------- /build.ts: -------------------------------------------------------------------------------- 1 | await Bun.build({ 2 | entrypoints: ['./src/index.ts'], 3 | outdir: './dist', 4 | target: 'node', 5 | format: 'esm', 6 | external: ['commander', 'prompts'], 7 | minify: true, 8 | }); -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bekacru/ts-init/99cd7eab279622406aee86c1a95ced8d634f3bc3/bun.lockb -------------------------------------------------------------------------------- /img/tweet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bekacru/ts-init/99cd7eab279622406aee86c1a95ced8d634f3bc3/img/tweet.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@bekacru/ts-init", 3 | "module": "dist/index.js", 4 | "version": "0.1.1", 5 | "main": "dist/index.js", 6 | "type": "module", 7 | "bin": "./dist/index.js", 8 | "scripts": { 9 | "dev": "bun run ./src/index.ts", 10 | "watch": "bun build ./src/index.ts --outdir=./dist --watch", 11 | "build": "bun run build.ts", 12 | "release": "bun run build && bumpp && npm publish --access public --no-git-checks" 13 | }, 14 | "devDependencies": { 15 | "@types/bun": "latest", 16 | "@types/prompt": "^1.1.9", 17 | "bumpp": "^9.5.2", 18 | "@types/prompts": "^2.4.9", 19 | "typescript": "^5.0.0" 20 | }, 21 | "dependencies": { 22 | "commander": "^12.1.0", 23 | "prompts": "^2.4.2" 24 | }, 25 | "files": [ 26 | "dist" 27 | ] 28 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { Command } from "commander"; 3 | import prompt from "prompts"; 4 | import fs from 'fs/promises'; 5 | import path from 'path'; 6 | 7 | const init = new Command() 8 | .name("") 9 | .description("Initialize a TypeScript project") 10 | .action(async () => { 11 | let options; 12 | try { 13 | options = await prompt([ 14 | { 15 | type: "text", 16 | name: "projectName", 17 | message: "What is the name of your project?", 18 | initial: ".", 19 | }, 20 | { 21 | type: "select", 22 | name: "strictness", 23 | message: "How strict should the typescript compiler be?", 24 | choices: [ 25 | { title: "Relaxed (Few checks)", value: "off" }, 26 | { title: "Balanced (Recommended)", value: "on" }, 27 | { title: "Rigorous (Maximum safety)", value: "strict" }, 28 | ], 29 | initial: 1, 30 | }, 31 | { 32 | type: "confirm", 33 | name: "isTranspiler", 34 | message: "Are you transpiling using tsc?", 35 | initial: true, 36 | }, 37 | { 38 | type: "confirm", 39 | name: "isLibrary", 40 | message: "Are you building a library?", 41 | initial: false, 42 | }, 43 | { 44 | type: "confirm", 45 | name: "isMonorepo", 46 | message: "Are you building for a library in a monorepo?", 47 | initial: false, 48 | }, 49 | { 50 | type: "confirm", 51 | name: "isDom", 52 | message: "Is your project for a dom (browser) environment?", 53 | initial: false, 54 | }, 55 | ], { 56 | onCancel: () => { 57 | throw new Error('Operation cancelled'); 58 | } 59 | }); 60 | } catch (error) { 61 | console.log('Operation cancelled'); 62 | process.exit(0); 63 | } 64 | 65 | if (!options || Object.keys(options).length === 0) { 66 | console.log('Operation cancelled'); 67 | process.exit(0); 68 | } 69 | 70 | const projectDir = options.projectName === "." ? process.cwd() : path.join(process.cwd(), options.projectName); 71 | 72 | try { 73 | await fs.mkdir(projectDir, { recursive: true }); 74 | 75 | const tsConfig = generateTsConfig(options); 76 | await fs.writeFile(path.join(projectDir, 'tsconfig.json'), JSON.stringify(tsConfig, null, 2)); 77 | console.log(`tsconfig.json has been generated in ${projectDir}`); 78 | } catch (error) { 79 | console.error('Error creating project files:', error); 80 | process.exit(1); 81 | } 82 | }); 83 | 84 | function generateTsConfig(options: { 85 | strictness: "off" | "on" | "strict"; 86 | isTranspiler: boolean; 87 | isLibrary: boolean; 88 | isMonorepo: boolean; 89 | isDom: boolean; 90 | }) { 91 | const config: { compilerOptions: Record } = { 92 | compilerOptions: { 93 | esModuleInterop: true, 94 | skipLibCheck: true, 95 | target: "es2022", 96 | allowJs: true, 97 | resolveJsonModule: true, 98 | moduleDetection: "force", 99 | isolatedModules: true, 100 | verbatimModuleSyntax: true, 101 | } 102 | }; 103 | 104 | // Strictness 105 | if (options.strictness === "strict") { 106 | config.compilerOptions.strict = true; 107 | config.compilerOptions.noUncheckedIndexedAccess = true; 108 | config.compilerOptions.noImplicitOverride = true; 109 | } else if (options.strictness === "on") { 110 | config.compilerOptions.strict = true; 111 | } 112 | 113 | // Transpiling 114 | if (options.isTranspiler) { 115 | config.compilerOptions.module = "NodeNext"; 116 | config.compilerOptions.outDir = "dist"; 117 | config.compilerOptions.sourceMap = true; 118 | } else { 119 | config.compilerOptions.module = "preserve"; 120 | config.compilerOptions.noEmit = true; 121 | } 122 | 123 | // Library 124 | if (options.isLibrary) { 125 | config.compilerOptions.declaration = true; 126 | } 127 | 128 | // Monorepo 129 | if (options.isMonorepo) { 130 | config.compilerOptions.composite = true; 131 | config.compilerOptions.declarationMap = true; 132 | } 133 | 134 | // DOM 135 | if (options.isDom) { 136 | config.compilerOptions.lib = ["es2022", "dom", "dom.iterable"]; 137 | } else { 138 | config.compilerOptions.lib = ["es2022"]; 139 | } 140 | 141 | return config; 142 | } 143 | 144 | function main() { 145 | init.parse(process.argv); 146 | } 147 | 148 | main(); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "skipLibCheck": true, 5 | "target": "es2022", 6 | "allowJs": true, 7 | "resolveJsonModule": true, 8 | "moduleDetection": "force", 9 | "isolatedModules": true, 10 | "verbatimModuleSyntax": true, 11 | "strict": true, 12 | "noUncheckedIndexedAccess": true, 13 | "noImplicitOverride": true, 14 | "module": "preserve", 15 | "noEmit": true, 16 | "declaration": true, 17 | "lib": [ 18 | "es2022" 19 | ] 20 | } 21 | } --------------------------------------------------------------------------------