├── .dockerignore ├── .eslintignore ├── .eslintrc.json ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ └── nodejs.yml ├── .gitignore ├── .husky ├── .gitignore ├── commit-msg └── pre-commit ├── .npmignore ├── .prettierignore ├── .prettierrc ├── .resources └── term.svg ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── MIGRATING.md ├── README.md ├── bin └── typescript-node-scripts.js ├── commitlint.config.js ├── docker-compose.yml ├── docs ├── adding-prettier.md ├── argv-forwarding.md ├── commands.md ├── custom-module-path.md ├── debugging-source.md ├── debugging-webpack.md ├── deployment.md ├── getting-started.md ├── migrating-v2-to-v3.md ├── monorepo.md ├── sourcemaps.md ├── tests.md ├── upgrading.md └── webpack-override.md ├── package.json ├── src ├── injectors │ ├── dev.ts │ └── test.ts ├── lib │ ├── clearConsole.ts │ ├── createWebpackConfig.ts │ ├── formatTsLoaderMessages.ts │ ├── formatWebpackMessages.ts │ ├── jest │ │ ├── babelPreprocessor.ts │ │ └── typescriptPreprocessor.ts │ ├── paths.ts │ ├── processHandler.ts │ └── webpackCompiler.ts ├── scripts │ ├── build.ts │ ├── create.ts │ ├── migration │ │ └── tslint-to-eslint │ │ │ ├── filesystem.ts │ │ │ ├── hash.ts │ │ │ └── index.ts │ ├── start.ts │ ├── test.ts │ └── util │ │ ├── createJestConfig.ts │ │ ├── fileExists.ts │ │ ├── fileSizeReporter.ts │ │ ├── getWebpackConfig.ts │ │ ├── migrationLogger.ts │ │ └── yarnAvailable.ts ├── types │ └── TNS.ts └── util │ ├── env.ts │ └── platform.ts ├── template ├── .eslintrc.json ├── .gitignore ├── gitignore ├── setupTests.ts ├── src │ ├── App.ts │ ├── __tests__ │ │ └── App.ts │ └── index.ts └── tsconfig.json ├── tests ├── e2e.sh ├── sink │ ├── ts-js-integration │ │ ├── __tests__ │ │ │ ├── cjs.js │ │ │ ├── esm.js │ │ │ ├── ts-import-js.ts │ │ │ └── ts.ts │ │ ├── cjs.js │ │ ├── esm.js │ │ ├── index.ts │ │ └── ts.ts │ ├── tsconfig.json │ └── typescript-3.7 │ │ ├── __tests__ │ │ └── index.test.ts │ │ └── index.ts └── verdaccio.yml ├── tsconfig.json ├── vendor ├── @babel │ └── code-frame.d.ts └── pstree.remy.d.ts ├── website ├── README.md ├── core │ └── Footer.js ├── i18n │ └── en.json ├── package.json ├── pages │ └── en │ │ ├── help.js │ │ ├── index.js │ │ └── users.js ├── sidebars.json ├── siteConfig.js ├── static │ ├── css │ │ └── custom.css │ └── img │ │ ├── babel.png │ │ ├── build.png │ │ ├── dev-server-error.png │ │ ├── dev-server.png │ │ ├── favicon.png │ │ ├── favicon │ │ └── favicon.ico │ │ ├── gear.svg │ │ ├── get-started.png │ │ ├── oss_logo.png │ │ ├── test.png │ │ ├── typescript.png │ │ └── webpack.svg └── yarn.lock └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .DS_Store 3 | .gitignore 4 | node_modules/ 5 | .resources 6 | template/build 7 | template/coverage 8 | template/dist 9 | build/ 10 | website/ -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/formatters/**/*.js 2 | template/**/*.js 3 | template/**/*.ts 4 | node_modules/**/*.js 5 | build/**/*.js 6 | website/**/*.js 7 | tests/**/*.ts 8 | tests/**/*.js -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@babel/eslint-parser", 3 | "extends": [ 4 | "eslint:recommended", 5 | "plugin:prettier/recommended" 6 | ], 7 | "plugins": [ 8 | "import" 9 | ], 10 | "env": { 11 | "browser": false, 12 | "node": true, 13 | "jest": true, 14 | "es6": true 15 | }, 16 | "parserOptions": { 17 | "ecmaVersion": 2018, 18 | "sourceType": "module" 19 | }, 20 | "rules": { 21 | "no-prototype-builtins": "off" 22 | }, 23 | "overrides": [ 24 | { 25 | "files": [ 26 | "**/*.ts" 27 | ], 28 | "parser": "@typescript-eslint/parser", 29 | "parserOptions": { 30 | "ecmaVersion": 2018, 31 | "sourceType": "module", 32 | "warnOnUnsupportedTypeScriptVersion": true, 33 | "project": "./tsconfig.json" 34 | }, 35 | "extends": [ 36 | "plugin:@typescript-eslint/recommended", 37 | "plugin:prettier/recommended" 38 | ], 39 | "plugins": [ 40 | "@typescript-eslint" 41 | ], 42 | "rules": { 43 | "default-case": "off", 44 | "no-dupe-class-members": "off", 45 | "no-undef": "off", 46 | "no-array-constructor": "off", 47 | "@typescript-eslint/no-array-constructor": "error", 48 | "no-use-before-define": "off", 49 | "@typescript-eslint/no-use-before-define": [ 50 | "error", 51 | { 52 | "functions": false, 53 | "classes": false, 54 | "variables": false, 55 | "typedefs": false 56 | } 57 | ], 58 | "@typescript-eslint/no-non-null-assertion": "off", 59 | "@typescript-eslint/no-explicit-any": "off", 60 | "@typescript-eslint/no-object-literal-type-assertion": "off", 61 | "@typescript-eslint/explicit-member-accessibility": "off", 62 | "no-unused-vars": "off", 63 | "@typescript-eslint/no-unused-vars": [ 64 | "error", 65 | { 66 | "args": "none", 67 | "ignoreRestSiblings": true 68 | } 69 | ], 70 | "no-useless-constructor": "off", 71 | "@typescript-eslint/no-useless-constructor": "error", 72 | "@typescript-eslint/explicit-function-return-type": "off", 73 | "@typescript-eslint/prefer-interface": "off", 74 | "@typescript-eslint/no-namespace": "off", 75 | "@typescript-eslint/no-var-requires": "off", 76 | "@typescript-eslint/explicit-module-boundary-types": "off" 77 | } 78 | } 79 | ] 80 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=TypeScript -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | ignore: 10 | - dependency-name: webpack 11 | versions: 12 | - 5.35.1 13 | - 5.36.0 14 | - dependency-name: "@types/node" 15 | versions: 16 | - 14.14.37 17 | - 14.14.39 18 | - 14.14.41 19 | - dependency-name: y18n 20 | versions: 21 | - 4.0.1 22 | - 4.0.2 23 | - dependency-name: "@commitlint/cli" 24 | versions: 25 | - 12.1.1 26 | - dependency-name: commitizen 27 | versions: 28 | - 4.2.3 29 | - dependency-name: lint-staged 30 | versions: 31 | - 10.5.4 32 | - dependency-name: pinst 33 | versions: 34 | - 2.1.6 35 | - dependency-name: husky 36 | versions: 37 | - 5.0.8 38 | - 5.0.9 39 | - 5.1.0 40 | - 5.1.1 41 | - 5.1.2 42 | - 5.1.3 43 | - 5.2.0 44 | - 6.0.0 45 | - dependency-name: eslint 46 | versions: 47 | - 7.18.0 48 | - 7.19.0 49 | - 7.20.0 50 | - 7.21.0 51 | - 7.22.0 52 | - 7.23.0 53 | - dependency-name: fork-ts-checker-webpack-plugin 54 | versions: 55 | - 6.1.0 56 | - 6.1.1 57 | - 6.2.0 58 | - dependency-name: typescript 59 | versions: 60 | - 4.1.3 61 | - 4.1.4 62 | - 4.1.5 63 | - 4.2.2 64 | - 4.2.3 65 | - dependency-name: eslint-config-prettier 66 | versions: 67 | - 7.2.0 68 | - 8.0.0 69 | - 8.1.0 70 | - dependency-name: "@babel/code-frame" 71 | versions: 72 | - 7.12.11 73 | - 7.12.13 74 | - dependency-name: webpack-merge 75 | versions: 76 | - 5.7.3 77 | - dependency-name: node-notifier 78 | versions: 79 | - 8.0.1 80 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | node-version: [12.x, 14.x, 16.x] 13 | 14 | steps: 15 | - uses: actions/checkout@v1 16 | - name: Use Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - name: Increase watchers 21 | run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p 22 | - name: Install yarn 23 | run: npm i -g yarn 24 | shell: bash 25 | - name: Install project dependencies 26 | run: yarn install 27 | - name: Run e2e 28 | run: ./tests/e2e.sh 29 | shell: bash 30 | env: 31 | CI: true 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | yarn-error.log 3 | .vscode/ 4 | package-lock.json 5 | .DS_Store 6 | build/ 7 | .scannerwork -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname $0)/_/husky.sh" 3 | 4 | npx --no-install commitlint -e -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname $0)/_/husky.sh" 3 | 4 | npx --no-install lint-staged -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | tests/**/* 2 | Dockerfile 3 | .eslintrc.json 4 | !template/.eslintrc.json 5 | .eslintignore 6 | .prettierrc 7 | .prettierignore 8 | .resources 9 | .dockerignore 10 | commitlint.config.js 11 | template/build/**/* 12 | template/coverage/**/* 13 | template/dist/**/* 14 | vendor/**/* 15 | docs/**/* 16 | website/**/* 17 | docker-compose.yml 18 | .scannerwork 19 | .gitattributes 20 | .travis.yml 21 | sonar-project.properties 22 | website/package.json 23 | website/README.md 24 | yarn-error.log 25 | .vscode 26 | .github 27 | .husky 28 | MIGRATING.md -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | template/**/* 2 | tests/**/* -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "singleQuote": true, 5 | "trailingComma": "es5", 6 | "bracketSpacing": true, 7 | "semi": false 8 | } 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [5.1.0](https://github.com/liangchunn/typescript-node-scripts/compare/v5.0.1...v5.1.0) (2022-01-20) 2 | 3 | 4 | ### Features 5 | 6 | * **config:** update source map support, support fn in custom webpack config ([03fc333](https://github.com/liangchunn/typescript-node-scripts/commit/03fc333a2295635ae7c526766e12d1339ec70f13)) 7 | 8 | 9 | 10 | ## [5.0.1](https://github.com/liangchunn/typescript-node-scripts/compare/v5.0.0-beta.0...v5.0.1) (2021-11-29) 11 | 12 | 13 | 14 | # [5.0.0-beta.0](https://github.com/liangchunn/typescript-node-scripts/compare/v5.0.0...v5.0.0-beta.0) (2021-11-29) 15 | 16 | 17 | ### Features 18 | 19 | * **deps:** upgrade dependencies and fix issues ([0c35752](https://github.com/liangchunn/typescript-node-scripts/commit/0c357524385e6c2b00f52612c5f6ba40ae51985e)) 20 | 21 | 22 | 23 | # [5.0.0](https://github.com/liangchunn/typescript-node-scripts/compare/v4.1.0...v5.0.0) (2021-04-23) 24 | 25 | 26 | ### Bug Fixes 27 | 28 | * **eslint:** upgrade eslint config for prettier ([6b64b84](https://github.com/liangchunn/typescript-node-scripts/commit/6b64b8410da38c8ebcc1ff0fb66ba0e5b7c5c152)) 29 | 30 | 31 | 32 | # [4.1.0](https://github.com/liangchunn/typescript-node-scripts/compare/v4.0.0...v4.1.0) (2021-03-31) 33 | 34 | 35 | ### Features 36 | 37 | * **processhandler:** add void type in promise type ([1031628](https://github.com/liangchunn/typescript-node-scripts/commit/103162809750d1d35938c67f1e4b2875e45ca236)) 38 | * **typescript:** support typescript <4.2.0 ([2998c8e](https://github.com/liangchunn/typescript-node-scripts/commit/2998c8e2395764c0b3d27ee8810406bfedaa1d4f)) 39 | 40 | 41 | 42 | # [4.0.0](https://github.com/liangchunn/typescript-node-scripts/compare/v3.2.0-alpha.10...v4.0.0) (2020-11-20) 43 | 44 | 45 | 46 | # [3.2.0-alpha.10](https://github.com/liangchunn/typescript-node-scripts/compare/v3.2.0-alpha.9...v3.2.0-alpha.10) (2020-11-18) 47 | 48 | 49 | ### Reverts 50 | 51 | * **jest:** revert jesst changes ([1a7c2d3](https://github.com/liangchunn/typescript-node-scripts/commit/1a7c2d3fc29a71870f179561ddb4fdcc9192c5a2)) 52 | 53 | 54 | 55 | # [3.2.0-alpha.9](https://github.com/liangchunn/typescript-node-scripts/compare/v3.2.0-alpha.8...v3.2.0-alpha.9) (2020-11-18) 56 | 57 | 58 | ### Features 59 | 60 | * **jest:** check for baseUrl and paths before mapping modules ([d412be9](https://github.com/liangchunn/typescript-node-scripts/commit/d412be958fcd662e274ebdc5f74c9812711e75d1)) 61 | 62 | 63 | 64 | # [3.2.0-alpha.8](https://github.com/liangchunn/typescript-node-scripts/compare/v3.2.0-alpha.7...v3.2.0-alpha.8) (2020-11-18) 65 | 66 | 67 | ### Features 68 | 69 | * **jest:** use ts-jest's pathsToModuleNameMapper ([b5f6d67](https://github.com/liangchunn/typescript-node-scripts/commit/b5f6d6705ec4eeb2fe6723e89944e583a5c5642c)) 70 | 71 | 72 | 73 | # [3.2.0-alpha.7](https://github.com/liangchunn/typescript-node-scripts/compare/v3.2.0-alpha.6...v3.2.0-alpha.7) (2020-11-17) 74 | 75 | 76 | ### Bug Fixes 77 | 78 | * **jest:** use tsconfig instead of tsConfig ([08e851c](https://github.com/liangchunn/typescript-node-scripts/commit/08e851c60a81f12c92071608ea6c988f64bdf3cf)) 79 | * **prettier:** fix formatting issue and command issue ([ab49b6c](https://github.com/liangchunn/typescript-node-scripts/commit/ab49b6cffec00757fdc8a8b44329f2baf7ca1a5a)) 80 | 81 | 82 | ### Features 83 | 84 | * **actions:** add node 15.x into workflow support ([8a070c8](https://github.com/liangchunn/typescript-node-scripts/commit/8a070c82e27fd2113ea73dc9b50b2a18cc2354a2)) 85 | * **deps:** upgrade dev dependencies ([a25315c](https://github.com/liangchunn/typescript-node-scripts/commit/a25315c9797551124147e125b06db636c3c8d6dd)) 86 | * **eslint:** remove return type requirement rule ([1d1b4c1](https://github.com/liangchunn/typescript-node-scripts/commit/1d1b4c1e1597787021e8862dbc8005165b2d2b4b)) 87 | 88 | 89 | 90 | # [3.2.0-alpha.6](https://github.com/liangchunn/typescript-node-scripts/compare/v3.2.0-alpha.5...v3.2.0-alpha.6) (2020-11-17) 91 | 92 | 93 | ### Bug Fixes 94 | 95 | * **eslint:** fix incorrect usage of configFile for loader ([d24666e](https://github.com/liangchunn/typescript-node-scripts/commit/d24666e9288223a633851c2ea72dcfc30d71aaf8)) 96 | 97 | 98 | 99 | # [3.2.0-alpha.5](https://github.com/liangchunn/typescript-node-scripts/compare/v3.2.0-alpha.4...v3.2.0-alpha.5) (2020-11-17) 100 | 101 | 102 | ### Bug Fixes 103 | 104 | * **eslint:** use configFile and resolvePluginsRelativeTo again ([4b76daa](https://github.com/liangchunn/typescript-node-scripts/commit/4b76daa049421b808773532b8a33db15ec22a9db)) 105 | 106 | 107 | 108 | # [3.2.0-alpha.4](https://github.com/liangchunn/typescript-node-scripts/compare/v3.2.0-alpha.3...v3.2.0-alpha.4) (2020-11-17) 109 | 110 | 111 | ### Features 112 | 113 | * **eslint:** migrate to new webpack eslint plugin ([34f462b](https://github.com/liangchunn/typescript-node-scripts/commit/34f462bd6ebaf3951ec72873a194bf555a55d293)) 114 | 115 | 116 | 117 | # [3.2.0-alpha.3](https://github.com/liangchunn/typescript-node-scripts/compare/v3.2.0-alpha.2...v3.2.0-alpha.3) (2020-11-17) 118 | 119 | 120 | ### Bug Fixes 121 | 122 | * **typescript:** install ~4.x version of typescript on create ([34fa6d4](https://github.com/liangchunn/typescript-node-scripts/commit/34fa6d46bd3cc66564bd2a60e3e98ec9d25339fd)) 123 | 124 | 125 | 126 | # [3.2.0-alpha.2](https://github.com/liangchunn/typescript-node-scripts/compare/v3.2.0-alpha.1...v3.2.0-alpha.2) (2020-11-17) 127 | 128 | 129 | ### Bug Fixes 130 | 131 | * **webpack5:** fix config problem and mitigate typing issue ([292b6a8](https://github.com/liangchunn/typescript-node-scripts/commit/292b6a81a56ac61083b88249537d6e4e3e3dc733)) 132 | 133 | 134 | 135 | # [3.2.0-alpha.1](https://github.com/liangchunn/typescript-node-scripts/compare/v3.1.2...v3.2.0-alpha.1) (2020-11-17) 136 | 137 | 138 | 139 | ## [3.1.2](https://github.com/liangchunn/typescript-node-scripts/compare/v3.1.1...v3.1.2) (2020-03-12) 140 | 141 | 142 | 143 | ## [3.1.1](https://github.com/liangchunn/typescript-node-scripts/compare/v3.1.0...v3.1.1) (2020-03-11) 144 | 145 | 146 | ### Features 147 | 148 | * **create:** install compatible typescript version on create ([a0c6d14](https://github.com/liangchunn/typescript-node-scripts/commit/a0c6d143d30e2a510da13820f9dc0cd29075d4ce)) 149 | * **package:** use tslib to reduce dist size ([1600455](https://github.com/liangchunn/typescript-node-scripts/commit/160045580a86d76a3a7db8750d1a3bc5bc9a6d2e)) 150 | 151 | 152 | 153 | # [3.1.0](https://github.com/liangchunn/typescript-node-scripts/compare/v3.0.0...v3.1.0) (2019-12-13) 154 | 155 | 156 | ### Bug Fixes 157 | 158 | * **package:** move eslint plugins to dependencies ([e838833](https://github.com/liangchunn/typescript-node-scripts/commit/e83883351c1c9c2a2f7ac94c2f57fc43501f110d)) 159 | 160 | 161 | ### Features 162 | 163 | * **eslint:** generate .eslintrc for project ([0794693](https://github.com/liangchunn/typescript-node-scripts/commit/079469347fcb24e9f933097241c9eb981dccd901)) 164 | * **eslint:** use built in eslint ([dcb4896](https://github.com/liangchunn/typescript-node-scripts/commit/dcb4896854c691ecbd5b89ab2f4b2ff897a5bb38)) 165 | * **package:** cleanup, remove usage of mapped paths in template ([4a8050a](https://github.com/liangchunn/typescript-node-scripts/commit/4a8050a31a6aa1f4e3b1c3c9186a151bb0c481dd)) 166 | * **prettier:** integrate prettier into tns ([f9213d7](https://github.com/liangchunn/typescript-node-scripts/commit/f9213d72927498685a22a6cd386b5d47bd75be88)) 167 | * **ts3.7:** try integrating ts3.7 ([10f14e5](https://github.com/liangchunn/typescript-node-scripts/commit/10f14e52ca06fb2db888c97867e5ee52714a8475)) 168 | 169 | 170 | 171 | # [3.0.0](https://github.com/liangchunn/typescript-node-scripts/compare/v3.0.0-alpha.1...v3.0.0) (2019-08-25) 172 | 173 | 174 | ### Bug Fixes 175 | 176 | * **eslint:** don't lint template ([42751cf](https://github.com/liangchunn/typescript-node-scripts/commit/42751cf290a3d75b47985d507c92806764f21310)) 177 | * **eslint:** fix invalid .eslintrc.json in template ([f9c6f57](https://github.com/liangchunn/typescript-node-scripts/commit/f9c6f57fc825c4a741bcfc223104d2684e5a5cc6)) 178 | * **eslint:** lint tests directory, fix lint issue in tests ([3cea4af](https://github.com/liangchunn/typescript-node-scripts/commit/3cea4afcef89c5340ce42d6f19c992e63f6f18c1)) 179 | * **eslint:** try fixing eslint issues ([3aed93a](https://github.com/liangchunn/typescript-node-scripts/commit/3aed93abeb9fc702510c7c4bae5ffda3fef70f2e)) 180 | 181 | 182 | 183 | # [3.0.0-alpha.1](https://github.com/liangchunn/typescript-node-scripts/compare/v3.0.0-alpha.0...v3.0.0-alpha.1) (2019-08-07) 184 | 185 | 186 | ### Features 187 | 188 | * **eslint:** add info for custom tslint.json migration ([f3725fa](https://github.com/liangchunn/typescript-node-scripts/commit/f3725fa4f4d07be77f50aa1706c75a7d5f73420f)) 189 | 190 | 191 | 192 | # [3.0.0-alpha.0](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.6...v3.0.0-alpha.0) (2019-08-07) 193 | 194 | 195 | ### Bug Fixes 196 | 197 | * **package:** update @babel/code-frame to version 7.5.5 ([06c41cd](https://github.com/liangchunn/typescript-node-scripts/commit/06c41cdb34aafbb000ee91dc1c2453525a9f5486)) 198 | * **package:** update @babel/core to version 7.5.0 ([da497fa](https://github.com/liangchunn/typescript-node-scripts/commit/da497fa63d12053fdc588cdbfbad435f482ac4b6)) 199 | * **package:** update @babel/core to version 7.5.5 ([e183737](https://github.com/liangchunn/typescript-node-scripts/commit/e183737445086f637444b2a5c55675cd422ad08a)) 200 | * **package:** update @babel/preset-env to version 7.5.2 ([1ff6d0d](https://github.com/liangchunn/typescript-node-scripts/commit/1ff6d0dccdcebd280ccf1e8424f98964f1456762)), closes [#123](https://github.com/liangchunn/typescript-node-scripts/issues/123) 201 | * **package:** update @babel/preset-env to version 7.5.5 ([ef37659](https://github.com/liangchunn/typescript-node-scripts/commit/ef37659e32bf1ebdcb74586976a7fa1863a37da6)) 202 | * **package:** update webpack to version 4.35.3 ([23461f6](https://github.com/liangchunn/typescript-node-scripts/commit/23461f6c77de9b120b6ebecf93c7f3e5265cc2c6)) 203 | * **webpack:** dont emit hash in output on prod builds ([fe8c397](https://github.com/liangchunn/typescript-node-scripts/commit/fe8c3974ec1f1266adb6dfb2e7135ca19f955f60)) 204 | 205 | 206 | ### Features 207 | 208 | * **eslint:** add migration script ([2ea6a5a](https://github.com/liangchunn/typescript-node-scripts/commit/2ea6a5af0503feac6b376e4dc29738ce7fd1d468)), closes [#96](https://github.com/liangchunn/typescript-node-scripts/issues/96) 209 | * **eslint:** extract utilities ([bac78de](https://github.com/liangchunn/typescript-node-scripts/commit/bac78de86ae7e939eb9540527f16db79b8c693ef)) 210 | * **eslint:** support eslint ([a3f800d](https://github.com/liangchunn/typescript-node-scripts/commit/a3f800ddc8bedb2af9565bc0ed8c61cdd78f5ef0)), closes [#96](https://github.com/liangchunn/typescript-node-scripts/issues/96) 211 | * **webpack:** add clean-webpack-plugin ([b264e23](https://github.com/liangchunn/typescript-node-scripts/commit/b264e23d13279585209da3b09e57b04d04c452f7)) 212 | 213 | 214 | 215 | ## [2.0.6](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.5...v2.0.6) (2019-07-04) 216 | 217 | 218 | ### Bug Fixes 219 | 220 | * **package:** update fork-ts-checker-webpack-plugin to version 1.3.7 ([ee83855](https://github.com/liangchunn/typescript-node-scripts/commit/ee83855dd0a049b18974e9810e1efebeaaa20371)), closes [#117](https://github.com/liangchunn/typescript-node-scripts/issues/117) 221 | * **package:** update fs-extra to version 8.1.0 ([75b4f93](https://github.com/liangchunn/typescript-node-scripts/commit/75b4f93bcb6775d6d2df6e47035bfd677e95ee75)) 222 | * **package:** update webpack to version 4.35.0 ([3d0ae9c](https://github.com/liangchunn/typescript-node-scripts/commit/3d0ae9c22b386383f0d7414fe95715352726a662)), closes [#118](https://github.com/liangchunn/typescript-node-scripts/issues/118) 223 | 224 | 225 | 226 | ## [2.0.5](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.4...v2.0.5) (2019-06-10) 227 | 228 | 229 | ### Features 230 | 231 | * **webpack:** emit only errors for tsconfig-paths-webpack-plugin ([7af2490](https://github.com/liangchunn/typescript-node-scripts/commit/7af249089463c9ec92c95461119fa9e76201e115)) 232 | 233 | 234 | 235 | ## [2.0.4](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.3...v2.0.4) (2019-06-07) 236 | 237 | 238 | ### Bug Fixes 239 | 240 | * **webpack:** add missing webpack overide support in build mode ([1ceaaef](https://github.com/liangchunn/typescript-node-scripts/commit/1ceaaef9e198704359119923fe8a1ecd7a3e2c95)) 241 | 242 | 243 | 244 | ## [2.0.3](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.2...v2.0.3) (2019-06-07) 245 | 246 | 247 | ### Bug Fixes 248 | 249 | * **package:** update fork-ts-checker-webpack-plugin to version 1.3.3 ([ebdbe2f](https://github.com/liangchunn/typescript-node-scripts/commit/ebdbe2f6c9c2d2ff36236b39f2162cc11aaf765f)) 250 | * **package:** update webpack to version 4.32.0 ([574f35e](https://github.com/liangchunn/typescript-node-scripts/commit/574f35e025bd57a037236fd97f32a45f59b6f857)) 251 | * **package:** upgrade and pin docusaurus to 1.11.0 ([7b39236](https://github.com/liangchunn/typescript-node-scripts/commit/7b3923635707cc8415ced7e0794ac3ee4aab443f)) 252 | * **package:** upgrade dependencies ([46c3478](https://github.com/liangchunn/typescript-node-scripts/commit/46c3478aa76ad66555f874a02aecbbd771ee51d3)) 253 | 254 | 255 | 256 | ## [2.0.2](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.1...v2.0.2) (2019-05-16) 257 | 258 | 259 | ### Bug Fixes 260 | 261 | * **package:** update @babel/core to version 7.4.4 ([14d6c86](https://github.com/liangchunn/typescript-node-scripts/commit/14d6c866cbe6230a5b57993b13c6a954e3676795)) 262 | * **package:** update @babel/preset-env to version 7.4.4 ([3d6de68](https://github.com/liangchunn/typescript-node-scripts/commit/3d6de68e36861a7e50abecc470a54c486de33a26)) 263 | * **package:** update babel-loader to version 8.0.6 ([626964a](https://github.com/liangchunn/typescript-node-scripts/commit/626964aeb1c6c27f2a97a4e5e8cd895ccd5e5ae2)) 264 | * **package:** update fork-ts-checker-webpack-plugin to version 1.2.0 ([32b1683](https://github.com/liangchunn/typescript-node-scripts/commit/32b168368e8d5b4aa5795b0a39f8d30b329634f1)), closes [#93](https://github.com/liangchunn/typescript-node-scripts/issues/93) 265 | * **package:** update fork-ts-checker-webpack-plugin to version 1.3.2 ([28403e7](https://github.com/liangchunn/typescript-node-scripts/commit/28403e73b717e00af8c590bd9172d0f056e36360)) 266 | * **package:** update fs-extra to version 8.0.1 ([9cfca52](https://github.com/liangchunn/typescript-node-scripts/commit/9cfca520a9ee33ae1e764168675f0427dd262879)), closes [#102](https://github.com/liangchunn/typescript-node-scripts/issues/102) 267 | * **package:** update webpack to version 4.31.0 ([74bd0d0](https://github.com/liangchunn/typescript-node-scripts/commit/74bd0d09269d7a4e15f17c9e97913da2f2500008)) 268 | 269 | 270 | 271 | ## [2.0.1](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.0...v2.0.1) (2019-04-15) 272 | 273 | 274 | ### Bug Fixes 275 | 276 | * **package:** update fork-ts-checker-webpack-plugin to version 1.0.1 ([cbbe50f](https://github.com/liangchunn/typescript-node-scripts/commit/cbbe50fc099c4b688cece74e524fbb32d7781a7f)) 277 | * **package:** update ts-jest to version 24.0.1 ([eb25ad5](https://github.com/liangchunn/typescript-node-scripts/commit/eb25ad5564013e78d6f9e9f153aafcc99d9ce8ad)) 278 | 279 | 280 | ### Features 281 | 282 | * **process:** extract app runner into a process handler ([8826297](https://github.com/liangchunn/typescript-node-scripts/commit/8826297b732a84e7d7a8fbfe391318e66feac2a7)) 283 | * **webpack:** add case sensitive webpack plugin ([027f926](https://github.com/liangchunn/typescript-node-scripts/commit/027f9262975eaedb05e230bf24dd8e2d762d7f21)) 284 | 285 | 286 | 287 | # [2.0.0-beta.5](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.0-beta.4...v2.0.0-beta.5) (2019-03-26) 288 | 289 | 290 | ### Features 291 | 292 | * **argv:** forward argv to spawned app ([f26d370](https://github.com/liangchunn/typescript-node-scripts/commit/f26d370b27149ca70658878bb75272115a749587)), closes [#76](https://github.com/liangchunn/typescript-node-scripts/issues/76) 293 | 294 | 295 | 296 | # [2.0.0-beta.4](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.0-beta.3...v2.0.0-beta.4) (2019-03-26) 297 | 298 | 299 | ### Features 300 | 301 | * **test:** don't check tests when running run/build ([464a06a](https://github.com/liangchunn/typescript-node-scripts/commit/464a06a08e979a3122fe9f985e9280838b21263c)) 302 | 303 | 304 | 305 | # [2.0.0-beta.3](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.0-beta.2...v2.0.0-beta.3) (2019-03-26) 306 | 307 | 308 | ### Features 309 | 310 | * **webpack:** support config override, fix empty errors ([dbc7186](https://github.com/liangchunn/typescript-node-scripts/commit/dbc71866e637f3ba98a651520fcf5c5865679643)) 311 | 312 | 313 | 314 | # [2.0.0-beta.2](https://github.com/liangchunn/typescript-node-scripts/compare/v2.0.0-beta.1...v2.0.0-beta.2) (2019-03-25) 315 | 316 | 317 | 318 | # [2.0.0-beta.1](https://github.com/liangchunn/typescript-node-scripts/compare/2.0.0-beta.0...v2.0.0-beta.1) (2019-03-25) 319 | 320 | 321 | ### Bug Fixes 322 | 323 | * **formatter:** use colors when tty and not ci ([5e3584f](https://github.com/liangchunn/typescript-node-scripts/commit/5e3584fc65eb5e824b43c2f8e5589fb17e665bd7)) 324 | 325 | 326 | 327 | # [2.0.0-beta.0](https://github.com/liangchunn/typescript-node-scripts/compare/v1.3.0...2.0.0-beta.0) (2019-03-25) 328 | 329 | 330 | ### Bug Fixes 331 | 332 | * **create:** install TNS as a dev dependency ([3978289](https://github.com/liangchunn/typescript-node-scripts/commit/39782899b2d7c5e225f9e3da91a72e44cb5765e5)) 333 | * **package:** update @babel/core to version 7.3.4 ([0332dba](https://github.com/liangchunn/typescript-node-scripts/commit/0332dbaf52355ae5895f4e43a9cdd68dd4676dc1)) 334 | * **package:** update @babel/preset-env to version 7.3.4 ([3a5cd6f](https://github.com/liangchunn/typescript-node-scripts/commit/3a5cd6f76b1ebdbf2aa002af3c9366975f2bdd96)) 335 | * **package:** update webpack to version 4.29.6 ([3f88bb8](https://github.com/liangchunn/typescript-node-scripts/commit/3f88bb83eab0789c031017e475c2b89a5ddecfeb)) 336 | * **vendor:** fix spelling ([ee2eaf8](https://github.com/liangchunn/typescript-node-scripts/commit/ee2eaf834b8f8255a4b466d88e603d022356f448)) 337 | 338 | 339 | ### Features 340 | 341 | * **typescript:** add typescript files ([f8854c2](https://github.com/liangchunn/typescript-node-scripts/commit/f8854c28682d256cbe2ae9ee448696456c73930e)) 342 | * **typescript:** finish up typescript support ([2c5512b](https://github.com/liangchunn/typescript-node-scripts/commit/2c5512b32a0d55b4072429748be2bf2c58fc1e8b)) 343 | 344 | 345 | 346 | # [1.3.0](https://github.com/liangchunn/typescript-node-scripts/compare/v1.2.0...v1.3.0) (2019-02-19) 347 | 348 | 349 | ### Bug Fixes 350 | 351 | * **package:** update @babel/core to version 7.3.3 ([28bad95](https://github.com/liangchunn/typescript-node-scripts/commit/28bad95a2dea896a3e444c82af6918830f0a286c)), closes [#64](https://github.com/liangchunn/typescript-node-scripts/issues/64) 352 | * **package:** update @babel/preset-env to version 7.3.1 ([f7fec24](https://github.com/liangchunn/typescript-node-scripts/commit/f7fec24de3382da52e8710f6fd785560576165e0)), closes [#64](https://github.com/liangchunn/typescript-node-scripts/issues/64) 353 | * **package:** update babel-loader to version 8.0.5 ([2eefbfc](https://github.com/liangchunn/typescript-node-scripts/commit/2eefbfca1ceec3f3d56e93389de6436903f950de)) 354 | * **package:** update chalk to version 2.4.2 ([1c7ffd6](https://github.com/liangchunn/typescript-node-scripts/commit/1c7ffd6fd03a5dcb6db4c3d9ea58365eabbac84c)) 355 | * **package:** update filesize to version 4.1.2 ([a3f0053](https://github.com/liangchunn/typescript-node-scripts/commit/a3f0053cea3c0de678d490feb57962ba0d67ecc5)), closes [#68](https://github.com/liangchunn/typescript-node-scripts/issues/68) 356 | * **package:** update ts-jest to version 24.0.0 ([1a034c8](https://github.com/liangchunn/typescript-node-scripts/commit/1a034c847fe34ca2a6e0fa9ac24553c6ad161dc3)) 357 | * **package:** update webpack to version 4.29.4 ([c072db7](https://github.com/liangchunn/typescript-node-scripts/commit/c072db76c815d323925372ddabea3ec407726354)), closes [#65](https://github.com/liangchunn/typescript-node-scripts/issues/65) 358 | * **package:** update webpack to version 4.29.5 ([c299c65](https://github.com/liangchunn/typescript-node-scripts/commit/c299c65937b247fa221ec366081d291ca15e7bce)) 359 | 360 | 361 | ### Features 362 | 363 | * **package:** upgrade jest, fix filesize, drop node 6 ([bd2e4d7](https://github.com/liangchunn/typescript-node-scripts/commit/bd2e4d76ac6cf3044d87d8b5e5512da38e150e3e)) 364 | 365 | 366 | 367 | # [1.2.0](https://github.com/liangchunn/typescript-node-scripts/compare/v1.1.1...v1.2.0) (2018-12-30) 368 | 369 | 370 | ### Features 371 | 372 | * **monorepo:** add support for monorepo ([6a7384f](https://github.com/liangchunn/typescript-node-scripts/commit/6a7384f8f9c31fb3ea9a540856c855af19ee95da)) 373 | 374 | 375 | 376 | ## [1.1.1](https://github.com/liangchunn/typescript-node-scripts/compare/v1.1.0...v1.1.1) (2018-12-15) 377 | 378 | 379 | ### Bug Fixes 380 | 381 | * **template:** remove build, coverage and dist from npm ([171ee66](https://github.com/liangchunn/typescript-node-scripts/commit/171ee666bac9eba3f8e8f1e7d19af9f6c5be2404)) 382 | 383 | 384 | 385 | # [1.1.0](https://github.com/liangchunn/typescript-node-scripts/compare/v1.0.7...v1.1.0) (2018-12-14) 386 | 387 | 388 | ### Bug Fixes 389 | 390 | * **package:** require typescript 3.x, fix fTCWP on 0.5.x ([24b41ce](https://github.com/liangchunn/typescript-node-scripts/commit/24b41ce3e76ba7dbbbc4401b83b3afe07c83f8b1)) 391 | 392 | 393 | 394 | ## [1.0.7](https://github.com/liangchunn/typescript-node-scripts/compare/v1.0.6...v1.0.7) (2018-12-11) 395 | 396 | 397 | ### Bug Fixes 398 | 399 | * **package:** update fork-ts-checker-webpack-plugin to version 0.5.1 ([2cac59a](https://github.com/liangchunn/typescript-node-scripts/commit/2cac59a9922759c42e9d5f9307c449b07e92bb6a)) 400 | * **package:** update webpack to version 4.27.0 ([5bcee3b](https://github.com/liangchunn/typescript-node-scripts/commit/5bcee3b398b5bc7c4be5346f0cea110e10e0a9e4)) 401 | * **package:** update webpack to version 4.27.1 ([e7ba963](https://github.com/liangchunn/typescript-node-scripts/commit/e7ba9638881fc5e2bbf57c62872946bf721f60b5)) 402 | 403 | 404 | 405 | ## [1.0.6](https://github.com/liangchunn/typescript-node-scripts/compare/v1.0.5...v1.0.6) (2018-12-02) 406 | 407 | 408 | ### Bug Fixes 409 | 410 | * **test:** use tsConfig instead of tsConfigFile for ts-jest ([0169e47](https://github.com/liangchunn/typescript-node-scripts/commit/0169e4730ace3410bb3838cad7b1a7b6713ffe12)) 411 | 412 | 413 | 414 | ## [1.0.5](https://github.com/liangchunn/typescript-node-scripts/compare/v1.0.4...v1.0.5) (2018-12-01) 415 | 416 | 417 | ### Bug Fixes 418 | 419 | * **codeframe:** use new API for @babel/code-frame ([1c93c74](https://github.com/liangchunn/typescript-node-scripts/commit/1c93c74cdd4be0c258983cbf55c9c6b2e0d5c571)) 420 | 421 | 422 | 423 | ## [1.0.4](https://github.com/liangchunn/typescript-node-scripts/compare/v1.0.3...v1.0.4) (2018-12-01) 424 | 425 | 426 | ### Bug Fixes 427 | 428 | * **e2e:** fix env detection for travis ([c501d96](https://github.com/liangchunn/typescript-node-scripts/commit/c501d96875115a38eb262cee168111fc6f2d0108)) 429 | * **package:** update @babel/core to version 7.1.2 ([53f832e](https://github.com/liangchunn/typescript-node-scripts/commit/53f832e7ccaeedd9306c53f4df7cf5ede69d2004)), closes [#25](https://github.com/liangchunn/typescript-node-scripts/issues/25) 430 | * **package:** update @babel/preset-env to version 7.1.0 ([07a38d4](https://github.com/liangchunn/typescript-node-scripts/commit/07a38d4b7293309f88c24165df72a9b1240e2451)), closes [#25](https://github.com/liangchunn/typescript-node-scripts/issues/25) 431 | * **package:** update babel-loader to version 8.0.4 ([e4950e0](https://github.com/liangchunn/typescript-node-scripts/commit/e4950e008f951d7a61accc659b632537d819e9e7)), closes [#23](https://github.com/liangchunn/typescript-node-scripts/issues/23) 432 | * **package:** update fork-ts-checker-webpack-plugin to version 0.4.10 ([c4f956c](https://github.com/liangchunn/typescript-node-scripts/commit/c4f956c1ac8e045b1df1602f91286febe5209e3d)) 433 | * **package:** update strip-ansi to version 5.0.0 ([fc0bf57](https://github.com/liangchunn/typescript-node-scripts/commit/fc0bf5756fb9cd11a00a69094eb5488c1453f72b)) 434 | * **package:** update ts-jest to version 23.10.4 ([6b7d9b6](https://github.com/liangchunn/typescript-node-scripts/commit/6b7d9b69d434ce867a9b4c26443d2b68f4487866)) 435 | * **package:** update webpack to version 4.20.2 ([dfb06d2](https://github.com/liangchunn/typescript-node-scripts/commit/dfb06d2400e7d26a2c60054b6e8d01bb32397361)), closes [#24](https://github.com/liangchunn/typescript-node-scripts/issues/24) 436 | * **spawn:** fix problem where kill wasnt killing subprocesses ([1cc35c0](https://github.com/liangchunn/typescript-node-scripts/commit/1cc35c0156b4e11526de7c64cdeaf8f8f67eba41)) 437 | 438 | 439 | 440 | ## [1.0.3](https://github.com/liangchunn/typescript-node-scripts/compare/v1.0.2...v1.0.3) (2018-09-25) 441 | 442 | 443 | ### Bug Fixes 444 | 445 | * **tslint:** do not check js files with tslint ([f41b01f](https://github.com/liangchunn/typescript-node-scripts/commit/f41b01f633cd7c5a067eba40464cac25a364f868)) 446 | 447 | 448 | 449 | ## [1.0.2](https://github.com/liangchunn/typescript-node-scripts/compare/v0.5.0...v1.0.2) (2018-09-16) 450 | 451 | 452 | ### Bug Fixes 453 | 454 | * **codeframe:** use default export ([4aad562](https://github.com/liangchunn/typescript-node-scripts/commit/4aad56290ed59000acc71e05eef3c0e465dd9184)) 455 | * **ts-jest:** use node module resolution ([531d8fd](https://github.com/liangchunn/typescript-node-scripts/commit/531d8fdf7650f9c14af96f08ba427589257e0ac2)) 456 | 457 | 458 | ### Features 459 | 460 | * **babel:** full support, sink tests, fix warnings ([069a7ff](https://github.com/liangchunn/typescript-node-scripts/commit/069a7ff7cbbd7dad047e935d80a184a85efb9784)) 461 | * **babel:** use babel for js files ([838a12c](https://github.com/liangchunn/typescript-node-scripts/commit/838a12c7d6c2ce75e02daab7a74d4df553c826ad)) 462 | 463 | 464 | 465 | # [0.5.0](https://github.com/liangchunn/typescript-node-scripts/compare/v0.4.4...v0.5.0) (2018-08-08) 466 | 467 | 468 | ### Bug Fixes 469 | 470 | * **package:** update fork-ts-checker-webpack-plugin to version 0.4.4 ([1a0d5fc](https://github.com/liangchunn/typescript-node-scripts/commit/1a0d5fc486424784466dcfd1aade5e93ff00d9cd)) 471 | * **package:** update ts-jest to version 23.1.3 ([08fe6f5](https://github.com/liangchunn/typescript-node-scripts/commit/08fe6f5055c934d094c3184cac5965846e024481)), closes [#12](https://github.com/liangchunn/typescript-node-scripts/issues/12) 472 | * **package:** update webpack to version 4.16.5 ([164efcc](https://github.com/liangchunn/typescript-node-scripts/commit/164efcc56bf052fd6e9b7377f851f0c974058531)), closes [#10](https://github.com/liangchunn/typescript-node-scripts/issues/10) 473 | 474 | 475 | ### Features 476 | 477 | * **typescript:** v3 + use experimentalWatchApi in webpack ([83a9ad2](https://github.com/liangchunn/typescript-node-scripts/commit/83a9ad20747d398c20b2491a1bc80db0378feb1b)) 478 | 479 | 480 | 481 | ## [0.4.4](https://github.com/liangchunn/typescript-node-scripts/compare/v0.4.2...v0.4.4) (2018-08-01) 482 | 483 | 484 | ### Bug Fixes 485 | 486 | * **package:** update webpack to version 4.16.2 ([fe44509](https://github.com/liangchunn/typescript-node-scripts/commit/fe44509272ca93958114a999d65882f56ba73bef)) 487 | 488 | 489 | ### Features 490 | 491 | * **jest:** target only commonjs ([930f5ca](https://github.com/liangchunn/typescript-node-scripts/commit/930f5cade6faf8bb188231a7d9bd23080b9214f0)) 492 | 493 | 494 | 495 | ## [0.4.2](https://github.com/liangchunn/typescript-node-scripts/compare/v0.4.1...v0.4.2) (2018-07-23) 496 | 497 | 498 | 499 | ## [0.4.1](https://github.com/liangchunn/typescript-node-scripts/compare/v0.4.0...v0.4.1) (2018-07-23) 500 | 501 | 502 | 503 | # [0.4.0](https://github.com/liangchunn/typescript-node-scripts/compare/v0.3.0...v0.4.0) (2018-07-21) 504 | 505 | 506 | 507 | # [0.3.0](https://github.com/liangchunn/typescript-node-scripts/compare/v0.2.4...v0.3.0) (2018-07-20) 508 | 509 | 510 | 511 | ## [0.2.4](https://github.com/liangchunn/typescript-node-scripts/compare/v0.2.2...v0.2.4) (2018-07-17) 512 | 513 | 514 | 515 | ## [0.2.2](https://github.com/liangchunn/typescript-node-scripts/compare/v0.2.1...v0.2.2) (2018-06-15) 516 | 517 | 518 | 519 | ## 0.2.1 (2018-06-15) 520 | 521 | 522 | 523 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12 2 | WORKDIR /usr/src/typescript-node-scripts 3 | COPY . . 4 | CMD ["./tests/e2e.sh"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Liang Chun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MIGRATING.md: -------------------------------------------------------------------------------- 1 | Please see the "Migration Guide" in the documentation in http://liangchunn.github.io/typescript-node-scripts -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # typescript-node-scripts 2 | ![](https://github.com/liangchunn/typescript-node-scripts/workflows/Node%20CI/badge.svg) [![npm](https://img.shields.io/npm/v/typescript-node-scripts.svg)](https://www.npmjs.com/package/typescript-node-scripts) [![npm](https://img.shields.io/npm/dt/typescript-node-scripts.svg)](https://www.npmjs.com/package/typescript-node-scripts) [![install size](https://packagephobia.now.sh/badge?p=typescript-node-scripts)](https://packagephobia.now.sh/result?p=typescript-node-scripts) [![Known Vulnerabilities](https://snyk.io/test/github/liangchunn/typescript-node-scripts/badge.svg)](https://snyk.io/test/github/liangchunn/typescript-node-scripts) 3 | 4 | 5 | 6 | Create Node.js applications based on TypeScript with zero-configuration. 7 | 8 |

9 | 11 |

12 | 13 | Inspired by `create-react-app` and Dan Abramov's [The Melting Pot of JavaScript](https://increment.com/development/the-melting-pot-of-javascript/). 14 | 15 | - Supports testing, building, and development in watch mode 16 | - Supports custom TypeScript path mappings, aka `compilerOptions.path` 17 | 18 | ## Quick Start Guide 19 | 20 | ```sh 21 | npx typescript-node-scripts create 22 | cd 23 | yarn start 24 | ``` 25 | 26 | ## Requirements 27 | 28 | - node `>=10.12.0` 29 | 30 | ## Documentation 31 | 32 | Access the documentation here: https://liangchunn.github.io/typescript-node-scripts 33 | -------------------------------------------------------------------------------- /bin/typescript-node-scripts.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // eslint-disable-next-line @typescript-eslint/no-var-requires 3 | const { spawnSync } = require('child_process') 4 | 5 | process.on('unhandledRejection', err => { 6 | throw err 7 | }) 8 | 9 | const args = process.argv.slice(2) 10 | 11 | const scriptIndex = args.findIndex( 12 | x => x === 'start' || x === 'test' || x === 'build' || x === 'create' 13 | ) 14 | 15 | const script = scriptIndex === -1 ? args[0] : args[scriptIndex] 16 | const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : [] 17 | 18 | switch (script) { 19 | case 'migration/tslint-to-eslint': 20 | case 'build': 21 | case 'test': 22 | case 'create': 23 | case 'start': { 24 | const result = spawnSync( 25 | 'node', 26 | nodeArgs 27 | .concat(require.resolve('../build/scripts/' + script)) 28 | .concat(args.slice(scriptIndex + 1)), 29 | { 30 | stdio: 'inherit', 31 | } 32 | ) 33 | if (result.signal) { 34 | if (result.signal === 'SIGKILL') { 35 | console.log( 36 | 'The build failed because the process exited too early. ' + 37 | 'This probably means the system ran out of memory or someone called ' + 38 | '`kill -9` on the process.' 39 | ) 40 | } else if (result.signal === 'SIGTERM') { 41 | console.log( 42 | 'The build failed because the process exited too early. ' + 43 | 'Someone might have called `kill` or `killall`, or the system could ' + 44 | 'be shutting down.' 45 | ) 46 | } 47 | process.exit(1) 48 | } 49 | process.exit(result.status) 50 | break 51 | } 52 | case undefined: { 53 | console.log('No command provided.') 54 | break 55 | } 56 | default: 57 | console.log('Unknown script "' + script + '".') 58 | break 59 | } 60 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] } 2 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | docusaurus: 5 | build: . 6 | ports: 7 | - 3000:3000 8 | - 35729:35729 9 | volumes: 10 | - ./docs:/app/docs 11 | - ./website/blog:/app/website/blog 12 | - ./website/core:/app/website/core 13 | - ./website/i18n:/app/website/i18n 14 | - ./website/pages:/app/website/pages 15 | - ./website/static:/app/website/static 16 | - ./website/sidebars.json:/app/website/sidebars.json 17 | - ./website/siteConfig.js:/app/website/siteConfig.js 18 | working_dir: /app/website 19 | -------------------------------------------------------------------------------- /docs/adding-prettier.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: adding-prettier 3 | title: Adding Prettier 4 | --- 5 | 6 | ## Adding Prettier Into Your Project 7 | 8 | 9 | ### Version `<4.1.0` 10 | > This feature is available starting from version 3 of `typescript-node-scripts` 11 | 12 | 1. In your project folder, install Prettier and the ESLint plugins: 13 | 14 | ```sh 15 | # npm 16 | npm i -D prettier eslint-plugin-prettier eslint-config-prettier 17 | 18 | # yarn 19 | yarn add prettier eslint-plugin-prettier eslint-config-prettier --dev 20 | ``` 21 | 22 | 2. Add the plugins to your `.eslintrc.json` 23 | 24 | ```diff 25 | { 26 | "parser": "babel-eslint", 27 | "extends": [ 28 | "eslint:recommended", 29 | + "plugin:prettier/recommended", 30 | + "prettier" 31 | ], 32 | ... 33 | "overrides": [ 34 | { 35 | ... 36 | "extends": [ 37 | "plugin:@typescript-eslint/recommended", 38 | + "prettier", 39 | + "prettier/@typescript-eslint", 40 | + "plugin:prettier/recommended" 41 | ], 42 | } 43 | ] 44 | } 45 | ``` 46 | 47 | ### Version `>=4.1.0` 48 | 49 | 1. In your project folder, install Prettier and the ESLint plugins: 50 | 51 | ```sh 52 | # npm 53 | npm i -D prettier eslint-plugin-prettier eslint-config-prettier 54 | 55 | # yarn 56 | yarn add prettier eslint-plugin-prettier eslint-config-prettier --dev 57 | ``` 58 | 59 | 2. Add the plugins to your `.eslintrc.json` 60 | 61 | ```diff 62 | { 63 | "parser": "babel-eslint", 64 | "extends": [ 65 | "eslint:recommended", 66 | + "plugin:prettier/recommended" 67 | ], 68 | ... 69 | "overrides": [ 70 | { 71 | ... 72 | "extends": [ 73 | "plugin:@typescript-eslint/recommended", 74 | + "plugin:prettier/recommended" 75 | ], 76 | } 77 | ] 78 | } 79 | ``` -------------------------------------------------------------------------------- /docs/argv-forwarding.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: argv-forwarding 3 | title: Forwarding argv to your App 4 | --- 5 | 6 | When running in development mode, you can specify all the arguments that you want to forward to your app after the `--` separator in your project's `package.json`: 7 | 8 | ```json 9 | { 10 | "scripts": { 11 | "start": "typescript-node-scripts start --no-collapse -- --arg-for-your-app=true" 12 | } 13 | } 14 | ``` 15 | 16 | This is particularly useful when your application needs to read arguments from the command line. -------------------------------------------------------------------------------- /docs/commands.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: commands 3 | title: Commands Reference 4 | --- 5 | 6 | ## `yarn start` 7 | 8 | Starts the development server with watch mode and incremental builds. This command generates a bundle which is located at `build/bundle.js`. 9 | 10 | ### Options 11 | 12 | | Argument | Description | 13 | | ----------------- | -------------------------------------------------------------------------------------------------- | 14 | | `--no-collapse` | Expands all the collapsed errors | 15 | | `--no-auto-start` | Disables auto starting and stopping of the application. By default, it executes `build/bundle.js`. | 16 | | `--monorepo` | Enable support for monorepos | 17 | 18 | ## `yarn build` 19 | 20 | Builds a production ready bundle. This minifies all sources into one simple, distributable `dist/bundle.prod.js` alongside `dist/bundle.prod.js.map` which is ideal for Docker builds. 21 | 22 | **This command does not bundle any dependencies which is `require`-d or `import`-ed from `node_modules`!** 23 | 24 | ### Options 25 | 26 | | Argument | Description | 27 | | ---------------------- | ------------------------------------------- | 28 | | `--no-collapse` | Expands all the collapsed errors | 29 | | `--bypass-ci-warnings` | Bypass CI warnings being treated as errors. | 30 | | `--monorepo` | Enable support for monorepo | 31 | 32 | ## `yarn test` 33 | 34 | Runs the Jest test runners in watch mode by default. You can add in Jest options as usual. 35 | 36 | ### Example commands 37 | 38 | ```sh 39 | yarn test --coverage 40 | 41 | yarn test --watchAll 42 | ``` 43 | -------------------------------------------------------------------------------- /docs/custom-module-path.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: custom-module-path 3 | title: Custom Module Paths 4 | --- 5 | 6 | TNS supports custom module path mapping. You can add a custom path mapping like so in `tsconfig.json`: 7 | 8 | ```json 9 | { 10 | "baseUrl": ".", 11 | "paths": { 12 | "~/*": ["src/*"] 13 | } 14 | } 15 | ``` 16 | 17 | This configuration allows you to import any module which resolves absolutely to `src`. 18 | 19 | ```ts 20 | // src/lib/a/b/Module.ts 21 | 22 | // instead of 23 | import Module from '../../../Module' 24 | 25 | // you can do 26 | import Module from '~/Module' 27 | ``` 28 | 29 | Unlike the TypeScript compiler which does not emit resolved paths, TNS takes care of resolving all custom module paths during build time. 30 | 31 | ## References 32 | 33 | - https://www.typescriptlang.org/docs/handbook/module-resolution.html 34 | -------------------------------------------------------------------------------- /docs/debugging-source.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: debugging-source 3 | title: Debugging your Source 4 | --- 5 | 6 | ## Visual Studio Code 7 | _This method is **NOT** recommended due to ts-node being quite slow at running and compiling your source code._ 8 | 9 | First off, you would need to install `ts-node` and `tsconfig-paths`: 10 | 11 | ```sh 12 | yarn add ts-node tsconfig-paths --dev 13 | ``` 14 | 15 | Then add the following into your configuration: 16 | 17 | ```json 18 | { 19 | "type": "node", 20 | "request": "launch", 21 | "name": "Debug Source (ts-node)", 22 | "protocol": "inspector", 23 | "runtimeArgs": ["-r", "ts-node/register", "-r", "tsconfig-paths/register"], 24 | "args": ["${workspaceFolder}/src/index.ts"], 25 | "env": { 26 | "TS_NODE_PROJECT": "./tsconfig.json", 27 | "TS_NODE_FILES": "true" 28 | } 29 | } 30 | ``` 31 | 32 | Next, add the `files` entry into your `tsconfig.json`: 33 | 34 | ```json 35 | { 36 | "files": ["src"] 37 | } 38 | ``` 39 | 40 | You can now use breakpoints and run the build under debug mode. 41 | -------------------------------------------------------------------------------- /docs/debugging-webpack.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: debugging-webpack 3 | title: Debugging your Webpack Build 4 | --- 5 | 6 | ## Visual Studio Code 7 | 8 | TNS incrementally outputs a single bundle in `build/bundle.js` (via webpack) when running `yarn build`. 9 | To debug the bundle, add the following into the `configurations` array of your `launch.json` file: 10 | 11 | ```json 12 | { 13 | "type": "node", 14 | "request": "launch", 15 | "name": "Debug Webpack Build (via Node)", 16 | "protocol": "inspector", 17 | "program": "${workspaceFolder}/build/bundle.js" 18 | } 19 | ``` 20 | 21 | You can now set breakpoints and run the task in order to debug your build. -------------------------------------------------------------------------------- /docs/deployment.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: deployment 3 | title: Deploying your App 4 | --- 5 | 6 | By default, TNS emits a main entrypoint in `dist/bundle.prod.js` which is built through webpack with the command `yarn build`. 7 | 8 | TNS **does not bundle `node_modules`!** Therefore when you deploy your application, the dependencies of your application should be installed first by including `package.json` and `yarn.lock`! 9 | 10 | > Make sure your runtime dependencies are included under `dependencies` in `package.json` so that they can be installed in the production build 11 | 12 | ## Docker 13 | 14 | ### Quick-start guide 15 | 16 | Before you deploy your application, make sure you run your build first: 17 | 18 | ```sh 19 | yarn build 20 | ``` 21 | 22 | Your bundle (and assets if you have overridden your webpack config) will be emitted in the `dist` folder 23 | 24 | Create a `Dockerfile` in the your project root with the following contents 25 | 26 | ```Dockerfile 27 | FROM node:10 28 | WORKDIR /usr/src/app 29 | # copy package and lockfile 30 | COPY package.json yarn.lock / 31 | RUN yarn install --production 32 | COPY dist dist 33 | # expose your app port if you need it 34 | EXPOSE 8081 35 | # run the app 36 | CMD [ "node", "dist/bundle.prod.js" ] 37 | ``` 38 | 39 | Then, build the Docker image with: 40 | 41 | ```sh 42 | # build and tag the image "my-app" 43 | docker build --tag my-app . 44 | ``` 45 | 46 | Now you can run your Dockerized application: 47 | 48 | ``` 49 | docker run --name my-app my-app 50 | ``` 51 | 52 | ### References 53 | 54 | - `docker run`: https://docs.docker.com/engine/reference/run/ 55 | - `docker build`: https://docs.docker.com/engine/reference/commandline/build/ 56 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: getting-started 3 | title: Getting Started 4 | --- 5 | 6 | Ready to create an application? 7 | 8 | Make sure that your Node version is at least `8.x`. You can run the command below to check if your version of Node is compatible with typescript-node-scripts: 9 | 10 | ```sh 11 | node --version 12 | ``` 13 | 14 | To create an application, run the following below: 15 | 16 | ```sh 17 | npx typescript-node-scripts create 18 | ``` 19 | 20 | After the command has run, you will find the folder `` in your current directory. To get started right away and run the development server, run the following: 21 | 22 | ```sh 23 | # go into the folder 24 | cd 25 | 26 | # start the dev server 27 | yarn start 28 | ``` -------------------------------------------------------------------------------- /docs/migrating-v2-to-v3.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: migrating-v2-to-v3 3 | title: Migrating from v2 to v3 4 | --- 5 | 6 | ## `3.x.x` Breaking Changes 7 | 8 | Versions `1.x.x` up to `2.x.x` of `typescript-node-scripts` used TSLint as the default linter. 9 | However, [TSLint has announced that it will be deprecated sometime in 2019](https://github.com/palantir/tslint/issues/4534), and packages that use TSLint should migrate to use ESLint. 10 | 11 | Version `3.x.x` of `typescript-node-scripts` will now use ESLint instead of TSLint to lint your project. 12 | 13 | ## Automatic Migration via CLI 14 | 15 | We've included a migration script so that you can migrate your TSLint configuration to ESLint configuration without heavylifting, and installs the necessary base packages to make your project ESLint compatible. 16 | 17 | ```sh 18 | # go to your project root 19 | cd 20 | 21 | # install version 3.x.x of `typescript-node-scripts` 22 | yarn upgrade typescript-node-scripts@^3.0.0 23 | 24 | # run the migration script 25 | npx typescript-node-scripts migration/tslint-to-eslint 26 | ``` 27 | 28 | You're done! Be sure to go through the console output so that you can see what potential issues that needs to be addressed. 29 | 30 | ## Gotchas 31 | 32 | Since there is a disparity between ESLint and TSLint rules and plugins, custom added TSLint rules and plugins has to be migrated to ESLint **manually**. 33 | 34 | > If you are using the default `tslint.json` generated with `typescript-node-scripts`, you shouldn't need to do anything more than running the migration script. 35 | 36 | TypeScript support in ESLint is supported by the [`typescript-eslint`](https://github.com/typescript-eslint/typescript-eslint) toolchain, and you should take a look at the repository to find out how to migrate your rules and plugins manually. 37 | 38 | Additionally, tools like [`tslint-to-eslint-config`](https://github.com/typescript-eslint/tslint-to-eslint-config) can aid in converting your custom TSLint rules to ESLint-compatible rules. 39 | 40 | ## Adding Prettier 41 | 42 | A lot of projects use Prettier, and here's a short guide on how to get Prettier up and running with ESLint. 43 | 44 | > Be sure that you have already ran the migration script above, have Prettier installed, and have an existing `.prettierrc` already in your project root. 45 | 46 | 1. Install the ESLint plugins: 47 | ```sh 48 | yarn add eslint-config-prettier eslint-plugin-prettier --dev 49 | ``` 50 | 51 | 2. Modify `extends` in `.eslintrc.json`: 52 | 53 | ```diff 54 | "extends": [ 55 | "eslint:recommended", 56 | + "prettier" 57 | ], 58 | "overrides: [ 59 | { 60 | "extends": [ 61 | "plugin:@typescript-eslint/recommended" 62 | + "prettier", 63 | + "prettier/@typescript-eslint" 64 | ] 65 | } 66 | ] 67 | ``` 68 | 69 | -------------------------------------------------------------------------------- /docs/monorepo.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: monorepo 3 | title: Monorepo Support 4 | --- 5 | 6 | To use `typescript-node-scripts` with a monorepo like lerna with yarn workspaces, you need to add `--monorepo` to the start and build scripts. 7 | 8 | ```json 9 | { 10 | "scripts": { 11 | "start": "typescript-node-scripts start --monorepo" 12 | } 13 | } 14 | ``` 15 | 16 | Then, you can use `lerna run --stream` in your root `package.json`. -------------------------------------------------------------------------------- /docs/sourcemaps.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: sourcemaps 3 | title: Source Maps 4 | --- 5 | 6 | Source maps are emitted by default, and postfixed with `.map` in the `build` and `dist` folders. These files provide accurate source mappings which are helpful when debugging errors and looking at stack traces during runtime. 7 | 8 | In order to tell Node to use these source maps, install the `source-map-support` package. 9 | 10 | ```sh 11 | yarn add source-map-support 12 | ``` 13 | 14 | Then, make sure that you import and register the source map handlers before anything else: 15 | 16 | ```ts 17 | // src/index.ts 18 | import 'source-map-support/register' 19 | // import other things that you need below 20 | import * as fs from 'fs' 21 | ``` -------------------------------------------------------------------------------- /docs/tests.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: tests 3 | title: Testing your Application 4 | --- 5 | 6 | Jest is the main test runner that this package supports. 7 | 8 | ## Test files 9 | 10 | Everything that matches the globs below will be passed to Jest as a test file: 11 | 12 | - `src/**/__tests__/**/*.(j|t)s?(x)` 13 | - `src/**/?(*.)(spec|test|t).(j|t)s?(x)` 14 | 15 | ## Setting up the test framework 16 | 17 | You can use `setupTests.ts` in your project root to set up the testing framework before each test. 18 | 19 | ## Overriding Jest configuration 20 | 21 | You can override the Jest configuration in your `package.json` with the key `jest`. 22 | 23 | The following options can be overriden: 24 | 25 | - `collectCoverageFrom` 26 | - `coverageReporters` 27 | - `coverageThreshold` -------------------------------------------------------------------------------- /docs/upgrading.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: upgrading 3 | title: Upgrading + Changelog 4 | --- 5 | 6 | # Upgrading TNS + Changelog 7 | 8 | ## `3.x.x` to `4.x.x` 9 | 10 | TNS `4.x.x` supports **TypeScript >=3.3.1 <4.1.0** and supports **webpack 5** 11 | 12 | Simply upgrade the package to get all the latest features: 13 | 14 | ```sh 15 | # install version 4.x.x of `typescript-node-scripts` 16 | yarn upgrade typescript-node-scripts@^4.0.0 17 | ``` 18 | 19 | ## `3.0.x` to `3.1.x` 20 | 21 | TNS `3.1.x` supports **TypeScript 3.7** with its new language features. 22 | 23 | Additionally, ESLint packages are now moved internally so you don't have to manage them by yourself. This means that you can remove the following packages in your `package.json` 24 | 25 | - `@typescript-eslint/eslint-plugin` 26 | - `@typescript-eslint/parser` 27 | - `eslint` 28 | - `babel-eslint` 29 | - `eslint-plugin-import` 30 | 31 | ```sh 32 | # npm 33 | npm uninstall @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint babel-eslint eslint-plugin-import 34 | 35 | # yarn 36 | yarn remove @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint babel-eslint eslint-plugin-import 37 | ``` 38 | 39 | Additionally, path mapping is now an opt-in feature and not generated in the initial `create` command. 40 | 41 | ## `2.x.x` to `3.x.x` 42 | 43 | ### `3.x.x` Breaking Changes 44 | 45 | Versions `1.x.x` up to `2.x.x` of `typescript-node-scripts` used TSLint as the default linter. 46 | However, [TSLint has announced that it will be deprecated sometime in 2019](https://github.com/palantir/tslint/issues/4534), and packages that use TSLint should migrate to use ESLint. 47 | 48 | Version `3.x.x` of `typescript-node-scripts` will now use ESLint instead of TSLint to lint your project. 49 | 50 | ### Automatic Migration via CLI 51 | 52 | We've included a migration script so that you can migrate your TSLint configuration to ESLint configuration without heavylifting, and installs the necessary base packages to make your project ESLint compatible. 53 | 54 | ```sh 55 | # go to your project root 56 | cd 57 | 58 | # install version 3.x.x of `typescript-node-scripts` 59 | yarn upgrade typescript-node-scripts@^3.0.0 60 | 61 | # run the migration script 62 | npx typescript-node-scripts migration/tslint-to-eslint 63 | ``` 64 | 65 | You're done! Be sure to go through the console output so that you can see what potential issues that needs to be addressed. 66 | 67 | ### Gotchas 68 | 69 | Since there is a disparity between ESLint and TSLint rules and plugins, custom added TSLint rules and plugins has to be migrated to ESLint **manually**. 70 | 71 | > If you are using the default `tslint.json` generated with `typescript-node-scripts`, you shouldn't need to do anything more than running the migration script. 72 | 73 | TypeScript support in ESLint is supported by the [`typescript-eslint`](https://github.com/typescript-eslint/typescript-eslint) toolchain, and you should take a look at the repository to find out how to migrate your rules and plugins manually. 74 | 75 | Additionally, tools like [`tslint-to-eslint-config`](https://github.com/typescript-eslint/tslint-to-eslint-config) can aid in converting your custom TSLint rules to ESLint-compatible rules. 76 | 77 | ### Adding Prettier 78 | 79 | A lot of projects use Prettier, and here's a short guide on how to get Prettier up and running with ESLint. 80 | 81 | > Be sure that you have already ran the migration script above, have Prettier installed, and have an existing `.prettierrc` already in your project root. 82 | 83 | 1. Install the ESLint plugins: 84 | 85 | ```sh 86 | yarn add eslint-config-prettier eslint-plugin-prettier --dev 87 | ``` 88 | 89 | 2. Modify `extends` in `.eslintrc.json`: 90 | 91 | ```diff 92 | "extends": [ 93 | "eslint:recommended", 94 | + "prettier" 95 | ], 96 | "overrides: [ 97 | { 98 | "extends": [ 99 | "plugin:@typescript-eslint/recommended" 100 | + "prettier", 101 | + "prettier/@typescript-eslint" 102 | ] 103 | } 104 | ] 105 | ``` 106 | -------------------------------------------------------------------------------- /docs/webpack-override.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: webpack-override 3 | title: Overriding Webpack Configuration 4 | --- 5 | 6 | _WARNING: This feature is marked as experimental and should not be used in production, unless you know exactly what you're doing!_ 7 | 8 | To override and merge your custom webpack configuration, create a file called `webpack.config.override.js` in your root folder. 9 | 10 | This file is then used to be merged into the base configuration that TNS provides, for example, forcing the build to always be in production mode: 11 | 12 | ```js 13 | module.exports = { 14 | mode: 'production' // always force production mode 15 | } 16 | ``` 17 | 18 | If you need to conditionally apply changes based on the build environment, simply export a function that takes in `isDev` as the first parameter: 19 | 20 | 21 | ```js 22 | module.exports = (isDev) => { 23 | return { 24 | devtool: isDev ? 'eval-cheap-module-source-map' : 'source-map', 25 | } 26 | } 27 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-node-scripts", 3 | "version": "5.1.0", 4 | "description": "Create Node.js apps based on TypeScript with zero-configuration.", 5 | "main": "bin/typescript-node-scripts.js", 6 | "scripts": { 7 | "watch": "tsc -p . --watch", 8 | "compile": "tsc -p .", 9 | "test": "node bin/typescript-node-scripts.js test", 10 | "start": "node bin/typescript-node-scripts.js start", 11 | "build": "node bin/typescript-node-scripts.js build", 12 | "initApp": "node bin/typescript-node-scripts.js create", 13 | "e2e:ci": "./tests/e2e.sh", 14 | "e2e:local": "docker build -t tns-docker . && docker run tns-docker", 15 | "lint": "eslint --ext .js --ext .ts --ext .jsx --ext .tsx src", 16 | "commit": "git-cz", 17 | "version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md", 18 | "prepublishOnly": "yarn compile", 19 | "prepare": "husky install" 20 | }, 21 | "bin": { 22 | "typescript-node-scripts": "./bin/typescript-node-scripts.js" 23 | }, 24 | "keywords": [], 25 | "author": "Liang Chun Wong", 26 | "repository": "https://github.com/liangchunn/typescript-node-scripts", 27 | "license": "MIT", 28 | "dependencies": { 29 | "@babel/code-frame": "7.16.7", 30 | "@babel/core": "7.16.10", 31 | "@babel/eslint-parser": "^7.16.5", 32 | "@babel/preset-env": "7.16.11", 33 | "@typescript-eslint/eslint-plugin": "5.10.0", 34 | "@typescript-eslint/parser": "5.10.0", 35 | "babel-core": "7.0.0-bridge.0", 36 | "babel-jest": "27.4.6", 37 | "babel-loader": "8.2.3", 38 | "case-sensitive-paths-webpack-plugin": "2.4.0", 39 | "chalk": "4.1.2", 40 | "clean-webpack-plugin": "4.0.0", 41 | "eslint": "8.7.0", 42 | "eslint-plugin-import": "2.25.4", 43 | "eslint-webpack-plugin": "3.1.1", 44 | "filesize": "8.0.7", 45 | "fork-ts-checker-webpack-plugin": "6.5.0", 46 | "fs-extra": "10.0.0", 47 | "jest": "27.4.7", 48 | "pstree.remy": "1.1.8", 49 | "strip-ansi": "7.0.1", 50 | "text-table": "0.2.0", 51 | "ts-jest": "27.1.3", 52 | "ts-loader": "9.2.6", 53 | "tsconfig-paths-webpack-plugin": "3.5.2", 54 | "tslib": "^2.3.1", 55 | "webpack": "5.66.0", 56 | "webpack-merge": "5.8.0", 57 | "webpack-node-externals": "3.0.0" 58 | }, 59 | "devDependencies": { 60 | "@commitlint/cli": "^16.1.0", 61 | "@commitlint/config-conventional": "^16.0.0", 62 | "@types/babel-code-frame": "^6.20.5", 63 | "@types/case-sensitive-paths-webpack-plugin": "^2.1.6", 64 | "@types/eslint": "^8.4.0", 65 | "@types/fs-extra": "^9.0.13", 66 | "@types/jest": "^27.4.0", 67 | "@types/node": "^16.11.0", 68 | "@types/text-table": "^0.2.2", 69 | "@types/webpack-merge": "^5.0.0", 70 | "@types/webpack-node-externals": "^2.5.3", 71 | "commitizen": "^4.2.4", 72 | "conventional-changelog-cli": "^2.2.2", 73 | "cz-conventional-changelog": "^3.3.0", 74 | "eslint-config-prettier": "^8.3.0", 75 | "eslint-plugin-prettier": "^4.0.0", 76 | "husky": "^7.0.4", 77 | "lint-staged": "^12.2.1", 78 | "prettier": "^2.5.1", 79 | "typescript": "4.5.4" 80 | }, 81 | "peerDependencies": { 82 | "typescript": ">=3.3.1 <=4.5" 83 | }, 84 | "engines": { 85 | "node": ">=12" 86 | }, 87 | "lint-staged": { 88 | "*.ts": "prettier --write" 89 | }, 90 | "config": { 91 | "commitizen": { 92 | "path": "cz-conventional-changelog" 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/injectors/dev.ts: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'development' 2 | 3 | process.on('unhandledRejection', (err) => { 4 | throw err 5 | }) 6 | -------------------------------------------------------------------------------- /src/injectors/test.ts: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test' 2 | 3 | process.on('unhandledRejection', (err) => { 4 | throw err 5 | }) 6 | -------------------------------------------------------------------------------- /src/lib/clearConsole.ts: -------------------------------------------------------------------------------- 1 | export function clearConsole() { 2 | process.stdout.write( 3 | process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H' 4 | ) 5 | } 6 | -------------------------------------------------------------------------------- /src/lib/createWebpackConfig.ts: -------------------------------------------------------------------------------- 1 | import * as webpack from 'webpack' 2 | import CaseSensitivePathsWebpackPlugin from 'case-sensitive-paths-webpack-plugin' 3 | import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin' 4 | import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin' 5 | import nodeExternals from 'webpack-node-externals' 6 | import { CleanWebpackPlugin } from 'clean-webpack-plugin' 7 | import ESLintPlugin from 'eslint-webpack-plugin' 8 | 9 | import { formatTsLoaderMessages } from './formatTsLoaderMessages' 10 | import { paths } from './paths' 11 | import { RuntimeOptions } from '../util/env' 12 | 13 | export const createWebpackConfig = ( 14 | environment: 'development' | 'production' 15 | ): webpack.Configuration => { 16 | const isDev = environment === 'development' 17 | 18 | return { 19 | mode: environment, 20 | entry: paths.appIndexJs, 21 | target: 'node', 22 | externals: [ 23 | nodeExternals( 24 | RuntimeOptions.useMonorepo 25 | ? { 26 | modulesFromFile: true, 27 | } 28 | : undefined 29 | ) as any, 30 | ], 31 | devtool: isDev ? 'eval-cheap-module-source-map' : 'source-map', 32 | output: { 33 | path: isDev ? paths.appDevBundlePath : paths.appBuild, 34 | filename: isDev ? 'bundle.js' : 'bundle.prod.js', 35 | libraryTarget: 'commonjs', 36 | }, 37 | resolve: { 38 | extensions: ['.ts', '.js', '.json'], 39 | plugins: [ 40 | new TsconfigPathsPlugin({ 41 | configFile: paths.appTsConfig, 42 | silent: true, 43 | }) as any, 44 | ], 45 | }, 46 | module: { 47 | rules: [ 48 | { 49 | test: /\.jsx?$/, 50 | include: paths.appSrc, 51 | exclude: /node_modules/, 52 | loader: require.resolve('babel-loader'), 53 | options: { 54 | babelrc: false, 55 | presets: [require.resolve('@babel/preset-env')], 56 | compact: true, 57 | }, 58 | }, 59 | { 60 | test: /\.tsx?$/, 61 | include: paths.appSrc, 62 | loader: require.resolve('ts-loader'), 63 | options: { 64 | transpileOnly: true, 65 | errorFormatter: formatTsLoaderMessages, 66 | }, 67 | }, 68 | ], 69 | }, 70 | plugins: [ 71 | new ESLintPlugin({ 72 | eslintPath: require.resolve('eslint'), 73 | extensions: ['js', 'ts', 'jsx', 'tsx'], 74 | formatter: 'stylish', 75 | emitWarning: true, 76 | resolvePluginsRelativeTo: __dirname, 77 | overrideConfigFile: paths.appEslint, 78 | } as any), 79 | new ForkTsCheckerWebpackPlugin({ 80 | async: false, 81 | typescript: { 82 | configFile: paths.appTsConfig, 83 | }, 84 | formatter: 'codeframe', 85 | }), 86 | new CaseSensitivePathsWebpackPlugin(), 87 | new CleanWebpackPlugin(), 88 | ] as webpack.WebpackPluginInstance[], 89 | optimization: { 90 | nodeEnv: false, 91 | }, 92 | node: { 93 | __dirname: false, 94 | __filename: false, 95 | }, 96 | performance: { 97 | hints: false, 98 | }, 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/lib/formatTsLoaderMessages.ts: -------------------------------------------------------------------------------- 1 | import { codeFrameColumns } from '@babel/code-frame' 2 | import { Chalk } from 'chalk' 3 | import * as fs from 'fs' 4 | import * as os from 'os' 5 | import { IS_CI, IS_INTERACTIVE } from '../util/env' 6 | 7 | /** 8 | * Copied from fTCWP's NormalizedMessage.d.ts 9 | */ 10 | interface NormalizedMessageJson { 11 | type: 'diagnostic' | 'lint' 12 | code: string | number 13 | severity: 'error' | 'warning' 14 | content: string 15 | file?: string 16 | line?: number 17 | character?: number 18 | } 19 | 20 | export function formatTsLoaderMessages( 21 | error: NormalizedMessageJson, 22 | colors: Chalk 23 | ): string { 24 | const { file } = error 25 | const source = file && fs.existsSync(file) && fs.readFileSync(file, 'utf-8') 26 | 27 | if (source) { 28 | const frame = codeFrameColumns( 29 | source, 30 | { 31 | start: { 32 | line: error.line, 33 | column: error.character, 34 | }, 35 | }, 36 | { 37 | highlightCode: IS_INTERACTIVE && !IS_CI, 38 | } 39 | ) 40 | return ( 41 | colors.dim(`${error.line}:${error.character} `) + 42 | error.content + 43 | colors.cyan(` (TS${error.code})`) + 44 | os.EOL + 45 | (frame ? os.EOL + frame : '') 46 | ) 47 | } else { 48 | return '' 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/lib/formatWebpackMessages.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import { StatsCompilation } from 'webpack' 3 | 4 | const friendlySyntaxErrorLabel = 'Syntax error:' 5 | 6 | type D = Exclude 7 | type ArrayType = T extends Array ? U : never 8 | // Not exported by webpack 9 | type StatsError = ArrayType 10 | 11 | /** 12 | * Formats webpack messages into a nicer looking, human friendly format. 13 | * Heavily adopted from: 14 | * https://github.com/facebook/create-react-app/blob/master/packages/react-dev-utils/formatWebpackMessages.js 15 | * 16 | * TODO: fix typing of any, could be error from webpack or loader, so we might want to format it differently 17 | * @param message 18 | */ 19 | function formatMessage(rawMessage: StatsError): string { 20 | const fileName = rawMessage.moduleId || rawMessage.file 21 | let message = fileName 22 | ? `${fileName}\n${rawMessage.message}` 23 | : `${rawMessage.message}` 24 | 25 | let lines = message.split('\n') 26 | 27 | // Remove webpack errors/warnings 28 | lines = lines.filter((line) => !/Module [A-z ]+\(from/.test(line)) 29 | 30 | // remove extra file path if exists 31 | // webpack somehow inserts a relative path into the messages, so we 32 | // splice it off here. 33 | if (lines.length > 2 && ~lines[0].indexOf(lines[1].slice(2))) { 34 | lines.splice(1, 1) 35 | } 36 | 37 | // remove webpack @ stack 38 | lines = lines.filter((line) => line.indexOf(' @ ') !== 0) 39 | 40 | // Transform 'Parsing error' to 'Syntax error' 41 | lines = lines.map((line) => { 42 | const parseError = /Line (\d+):(?:(\d+):)?\s*Parsing error: (.+)$/.exec( 43 | line 44 | ) 45 | if (!parseError) { 46 | return line 47 | } 48 | const [, errorLine, errorColumn, errorMessage] = parseError 49 | return `${friendlySyntaxErrorLabel} ${errorMessage} (${errorLine}:${errorColumn})` 50 | }) 51 | 52 | // Strip leading newlines 53 | if (lines.length > 2 && lines[1].trim() === '') { 54 | lines.splice(1, 1) 55 | } 56 | 57 | // Cleans up verbose "module not found" messages for files and packages. 58 | if (lines[1] && lines[1].indexOf('Module not found: ') === 0) { 59 | lines = [ 60 | lines[0], 61 | lines[1] 62 | .replace('Error: ', '') 63 | .replace('Module not found: Cannot find file:', 'Cannot find file:'), 64 | ] 65 | } 66 | 67 | // Underline and bold file name 68 | if (lines[0]) { 69 | lines[0] = chalk.underline.bold(lines[0]) 70 | } 71 | 72 | message = lines.join('\n') 73 | 74 | // Internal stacks are generally useless so we strip them... with the 75 | // exception of stacks containing `webpack:` because they're normally 76 | // from user code generated by Webpack. For more information see 77 | // https://github.com/facebook/create-react-app/pull/1050 78 | message = message.replace( 79 | /^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm, 80 | '' 81 | ) // at ... ...:x:y 82 | message = message.replace(/^\s*at\s(\n|$)/gm, '') // at 83 | lines = message.split('\n') 84 | 85 | // Remove duplicated newlines 86 | lines = lines.filter( 87 | (line, index, arr) => 88 | index === 0 || line.trim() !== '' || line.trim() !== arr[index - 1].trim() 89 | ) 90 | 91 | // Reassemble the message 92 | message = lines.join('\n') 93 | return message.trim() 94 | } 95 | 96 | export function formatWebpackMessages(json: StatsCompilation): { 97 | errors: string[] 98 | warnings: string[] 99 | } { 100 | const errors = 101 | json.errors 102 | ?.map((error) => formatMessage(error)) 103 | .filter((message) => message !== '') ?? [] 104 | const warnings = 105 | json.warnings 106 | ?.map((warning) => formatMessage(warning)) 107 | .filter((message) => message !== '') ?? [] 108 | 109 | return { 110 | errors, 111 | warnings, 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/lib/jest/babelPreprocessor.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-var-requires 2 | const babelJest = require('babel-jest').default 3 | 4 | module.exports = babelJest.createTransformer({ 5 | presets: [ 6 | [ 7 | '@babel/preset-env', 8 | { 9 | targets: { 10 | node: 'current', 11 | }, 12 | }, 13 | ], 14 | ], 15 | babelrc: false, 16 | }) 17 | -------------------------------------------------------------------------------- /src/lib/jest/typescriptPreprocessor.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-var-requires 2 | const tsJestPreprocessor = require('ts-jest') 3 | 4 | module.exports = tsJestPreprocessor 5 | -------------------------------------------------------------------------------- /src/lib/paths.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs' 2 | import * as path from 'path' 3 | 4 | const appDirectory = fs.realpathSync(process.cwd()) 5 | const useTemplate = 6 | appDirectory === fs.realpathSync(path.join(__dirname, '../..')) 7 | 8 | export function resolveApp(relativePath: string): string { 9 | return path.resolve(appDirectory, relativePath) 10 | } 11 | 12 | export function resolveOwn(relativePath: string): string { 13 | return path.resolve(__dirname, '../..', relativePath) 14 | } 15 | 16 | export const paths = useTemplate 17 | ? { 18 | appPackageJson: resolveOwn('package.json'), 19 | appIndexJs: resolveOwn('template/src/index.ts'), 20 | appTsConfig: resolveOwn('template/tsconfig.json'), 21 | appEslint: resolveOwn('template/.eslintrc.json'), 22 | appDevBundlePath: resolveOwn('template/build'), 23 | appSrc: resolveOwn('template/src'), 24 | appBuild: resolveOwn('template/dist'), 25 | testsSetup: resolveOwn('template/setupTests.ts'), 26 | webpackOverride: resolveOwn('template/webpack.config.override.js'), 27 | prodBundle: 'bundle.prod.js', 28 | legacyAppTslint: resolveOwn('template/tslint.json'), 29 | } 30 | : { 31 | appPackageJson: resolveApp('package.json'), 32 | appIndexJs: resolveApp('src/index.ts'), 33 | appTsConfig: resolveApp('tsconfig.json'), 34 | appEslint: resolveApp('.eslintrc.json'), 35 | appDevBundlePath: resolveApp('build'), 36 | appSrc: resolveApp('src'), 37 | appBuild: resolveApp('dist'), 38 | testsSetup: resolveApp('setupTests.ts'), 39 | webpackOverride: resolveApp('webpack.config.override.js'), 40 | prodBundle: 'bundle.prod.js', 41 | legacyAppTslint: resolveApp('tslint.json'), 42 | } 43 | -------------------------------------------------------------------------------- /src/lib/processHandler.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import { ChildProcess, exec, spawn } from 'child_process' 3 | import psTree, { hasPS } from 'pstree.remy' 4 | import { isWindows } from '../util/platform' 5 | 6 | type AppControllerState = 7 | | { 8 | appRunning: true 9 | proc: ChildProcess 10 | pid: string 11 | } 12 | | { 13 | appRunning: false 14 | proc: null 15 | pid: null 16 | } 17 | 18 | function invariant(condition: boolean, message: string): void | never { 19 | if (!condition) { 20 | const err = new Error(message) 21 | err.name = 'Invariant Violation' 22 | throw err 23 | } 24 | } 25 | 26 | export class AppController { 27 | private readonly executablePath: string 28 | private readonly argv: string[] 29 | private state: AppControllerState 30 | 31 | public constructor(executablePath: string, argv: string[]) { 32 | this.state = { 33 | appRunning: false, 34 | proc: null, 35 | pid: null, 36 | } 37 | this.executablePath = executablePath 38 | this.argv = argv 39 | } 40 | 41 | public async stopApp() { 42 | return new Promise((resolve) => { 43 | if (this.state.appRunning) { 44 | console.log('Sending SIGTERM signal to app...') 45 | 46 | const { pid } = this.state 47 | 48 | const closeHandler = (code: number, signal: string) => { 49 | this.setState({ 50 | appRunning: false, 51 | proc: null, 52 | pid: null, 53 | }) 54 | resolve() 55 | } 56 | 57 | if (isWindows()) { 58 | exec('taskkill /pid ' + pid + ' /T /F').on('close', closeHandler) 59 | } else { 60 | // pstree is used to kill the full subtree of a spawned app 61 | psTree(pid, (_, children) => { 62 | if (hasPS) { 63 | // we now send SIGTERM to the spawned process 64 | spawn('kill', ['-s', 'SIGTERM', pid].concat(children)).on( 65 | 'close', 66 | closeHandler 67 | ) 68 | } else { 69 | const pids = children.concat(pid).sort() 70 | pids.forEach((childPid) => { 71 | // 15 is for SIGTERM 72 | exec('kill -15 ' + childPid).on('close', closeHandler) 73 | }) 74 | } 75 | }) 76 | } 77 | } else { 78 | resolve() 79 | } 80 | }) 81 | } 82 | 83 | public runApp() { 84 | invariant( 85 | !this.state.appRunning, 86 | "Can't start app when app is already running!" 87 | ) 88 | 89 | // spawn the process 90 | const proc = spawn('node', [this.executablePath, ...this.argv]) 91 | 92 | // attach event listeners 93 | proc.on('error', (e) => { 94 | console.log(chalk.red('Failed to start app: ' + e.message)) 95 | this.setState({ 96 | appRunning: false, 97 | proc: null, 98 | pid: null, 99 | }) 100 | }) 101 | proc.on('exit', (code, signal) => { 102 | if (code !== null) { 103 | console.log( 104 | code > 0 105 | ? chalk.red('App exited with code ' + code + '.') 106 | : chalk.green('App exited with code ' + code + '.') 107 | ) 108 | } 109 | if (signal !== null) { 110 | console.log( 111 | signal !== 'SIGTERM' 112 | ? chalk.red('App killed with signal ' + signal + '.') 113 | : chalk.green('App killed with signal SIGTERM.') 114 | ) 115 | } 116 | this.setState({ 117 | appRunning: false, 118 | proc: null, 119 | pid: null, 120 | }) 121 | }) 122 | 123 | // pipe spawned output stream to current process's output streams 124 | proc.stdout.pipe(process.stdout) 125 | proc.stderr.pipe(process.stderr) 126 | 127 | if (proc.pid) { 128 | console.log(chalk.green('App started!')) 129 | 130 | this.setState({ 131 | proc, 132 | pid: proc.pid.toString(), 133 | appRunning: true, 134 | }) 135 | } 136 | } 137 | 138 | private setState(state: AppControllerState) { 139 | this.state = state 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/lib/webpackCompiler.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import * as path from 'path' 3 | import webpack from 'webpack' 4 | import { TNSOptions } from '../types/TNS' 5 | import { clearConsole } from './clearConsole' 6 | import { formatWebpackMessages } from './formatWebpackMessages' 7 | import { AppController } from './processHandler' 8 | import { IS_INTERACTIVE } from '../util/env' 9 | 10 | const { argv } = process 11 | const argvSeparatorIndex = argv.indexOf('--') 12 | const appArgs: string[] = ~argvSeparatorIndex 13 | ? process.argv.slice(argvSeparatorIndex + 1, argv.length) 14 | : [] 15 | 16 | export function createCompiler( 17 | config: webpack.Configuration, 18 | options: TNSOptions 19 | ): webpack.Compiler { 20 | let compiler: webpack.Compiler 21 | const controller = new AppController( 22 | path.join(config.output!.path!, config.output!.filename! as string), 23 | appArgs 24 | ) 25 | 26 | try { 27 | compiler = webpack(config) 28 | } catch (err: any) { 29 | console.log(chalk.red('Failed to compile.')) 30 | console.log() 31 | console.log(err.message || err) 32 | console.log() 33 | process.exit(1) 34 | } 35 | 36 | compiler.hooks.invalid.tap('compileInvalidate', async () => { 37 | if (IS_INTERACTIVE) { 38 | clearConsole() 39 | } 40 | console.log('Compiling...') 41 | console.log() 42 | if (!options.noAutoStart) { 43 | await controller.stopApp() 44 | } 45 | }) 46 | 47 | compiler.hooks.done.tap('compileDone', (stats) => { 48 | if (IS_INTERACTIVE) { 49 | clearConsole() 50 | } 51 | const statsJson = stats.toJson({ errors: true, warnings: true }) 52 | const messages = formatWebpackMessages(statsJson) 53 | const isSuccessful = !messages.errors.length && !messages.warnings.length 54 | 55 | if (isSuccessful) { 56 | const successMessage = chalk.green('Compiled successfully!') 57 | const time = chalk.dim(`(${statsJson.time}ms)`) 58 | console.log(`${successMessage} ${time}`) 59 | console.log() 60 | } 61 | 62 | if (messages.errors.length) { 63 | const collapsedErrorLength = messages.errors.length - 1 64 | 65 | if (messages.errors.length > 1 && !options.noCollapse) { 66 | messages.errors.length = 1 67 | } 68 | 69 | console.log(chalk.red('Failed to compile.\n')) 70 | console.log(messages.errors.join('\n\n')) 71 | if (collapsedErrorLength && !options.noCollapse) { 72 | console.log() 73 | console.log( 74 | chalk.red( 75 | collapsedErrorLength + 76 | (collapsedErrorLength > 1 ? ' errors have' : ' error has') + 77 | ' been collapsed.' 78 | ) 79 | ) 80 | } 81 | return 82 | } 83 | 84 | // Show warnings if no errors were found. 85 | if (messages.warnings.length) { 86 | console.log(chalk.yellow('Compiled with warnings.\n')) 87 | console.log(messages.warnings.join('\n\n')) 88 | 89 | console.log( 90 | '\nSearch for the ' + 91 | chalk.cyan('keywords') + 92 | ' to learn more about each warning.' 93 | ) 94 | console.log( 95 | 'To ignore, add ' + 96 | chalk.yellow('// eslint-disable-next-line') + 97 | ' to the line before.\n' 98 | ) 99 | } 100 | 101 | // Start the app if there are no errors 102 | if (!messages.errors.length && !options.noAutoStart) { 103 | controller.runApp() 104 | } 105 | }) 106 | 107 | return compiler 108 | } 109 | -------------------------------------------------------------------------------- /src/scripts/build.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import * as path from 'path' 3 | import * as typescript from 'typescript' 4 | import webpack from 'webpack' 5 | import { formatWebpackMessages } from '../lib/formatWebpackMessages' 6 | import { paths } from '../lib/paths' 7 | import { IS_CI, RuntimeOptions } from '../util/env' 8 | import { diffFileSize, getBundleSize } from './util/fileSizeReporter' 9 | import { getWebpackConfig } from './util/getWebpackConfig' 10 | 11 | const prodBundlePath = path.join(paths.appBuild, paths.prodBundle) 12 | const sizeBeforeBuild = getBundleSize(prodBundlePath) 13 | 14 | const build = (): Promise<{ stats: webpack.Stats; warnings: string[] }> => { 15 | console.log(chalk.cyan('Creating an optimized production build...')) 16 | console.log(chalk.green('Using TypeScript v' + typescript.version)) 17 | console.log() 18 | 19 | const compiler: webpack.Compiler = webpack(getWebpackConfig('production')) 20 | 21 | return new Promise((resolve, reject) => { 22 | compiler.run((err, stats) => { 23 | if (err) { 24 | return reject(err) 25 | } 26 | const messages = formatWebpackMessages(stats!.toJson()) 27 | if (messages.errors.length) { 28 | if (messages.errors.length > 1 && !RuntimeOptions.noCollapse) { 29 | messages.errors.length = 1 30 | } 31 | return reject(new Error(messages.errors.join('\n\n'))) 32 | } 33 | 34 | if (IS_CI && messages.warnings.length) { 35 | if (RuntimeOptions.bypassCiWarnings) { 36 | console.log( 37 | chalk.yellow( 38 | '\nBypassing warnings as CI errors due to --bypass-ci-warnings option.\n' 39 | ) 40 | ) 41 | } else { 42 | console.log( 43 | chalk.yellow( 44 | '\nTreating warnings as errors because process.env.CI = true.\n' + 45 | 'Most CI servers set it automatically.\n' 46 | ) 47 | ) 48 | return reject(new Error(messages.warnings.join('\n\n'))) 49 | } 50 | } 51 | 52 | return resolve({ 53 | stats: stats!, 54 | warnings: messages.warnings, 55 | }) 56 | }) 57 | }) 58 | } 59 | 60 | build() 61 | .then( 62 | ({ warnings }) => { 63 | if (warnings.length) { 64 | console.log(chalk.yellow('Compiled with warnings.\n')) 65 | console.log(warnings.join('\n\n')) 66 | 67 | console.log( 68 | '\nSearch for the ' + 69 | chalk.cyan('keywords') + 70 | ' to learn more about each warning.' 71 | ) 72 | console.log( 73 | 'To ignore, add ' + 74 | chalk.yellow('// eslint-disable-next-line') + 75 | ' to the line before.\n' 76 | ) 77 | } 78 | }, 79 | (err) => { 80 | console.log(chalk.red('Failed to compile.\n')) 81 | console.log(err.message) 82 | console.log() 83 | process.exit(1) 84 | } 85 | ) 86 | .then(() => { 87 | const sizeAfterBuild = getBundleSize(prodBundlePath) 88 | console.log() 89 | console.log(chalk.greenBright('Successfully built bundle.prod.js!')) 90 | console.log( 91 | 'Bundle size: ' + diffFileSize(sizeBeforeBuild!, sizeAfterBuild!) 92 | ) 93 | console.log() 94 | }) 95 | .catch((err) => { 96 | if (err && err.message) { 97 | console.log(err.message) 98 | } 99 | process.exit(1) 100 | }) 101 | -------------------------------------------------------------------------------- /src/scripts/create.ts: -------------------------------------------------------------------------------- 1 | process.on('unhandledRejection', (err) => { 2 | throw err 3 | }) 4 | 5 | import chalk from 'chalk' 6 | import { execSync, spawnSync } from 'child_process' 7 | import * as fs from 'fs-extra' 8 | import * as os from 'os' 9 | import * as path from 'path' 10 | import { yarnAvailable } from './util/yarnAvailable' 11 | 12 | const argv = process.argv.slice(2) 13 | 14 | const createApp = (useYarn: boolean, appName?: string) => { 15 | if (!appName) { 16 | console.error( 17 | 'Please specify the directory you want to create your project:' 18 | ) 19 | console.error( 20 | ` ${chalk.cyan('typescript-node-scripts create')} ${chalk.green( 21 | '' 22 | )}` 23 | ) 24 | return process.exit(1) 25 | } 26 | 27 | const appPath = path.join(process.cwd(), appName) 28 | 29 | console.log('Creating application ' + chalk.cyan(appName) + '\n') 30 | const appPackageJson = { 31 | name: appName, 32 | version: '0.1.0', 33 | main: 'src/index.ts', 34 | private: true, 35 | scripts: { 36 | start: 'typescript-node-scripts start', 37 | build: 'typescript-node-scripts build', 38 | test: 'typescript-node-scripts test', 39 | }, 40 | } 41 | 42 | const packageDevDependencies = [ 43 | '@types/node', 44 | '@types/jest', 45 | 'typescript@~4.5.2', 46 | 'typescript-node-scripts', 47 | ] 48 | 49 | // check if the path exists 50 | if (fs.existsSync(appPath)) { 51 | console.error() 52 | console.error(chalk.red('Failed to create app.')) 53 | console.error(chalk.red('Directory "' + appName + '" exists.')) 54 | console.error() 55 | process.exit(1) 56 | } 57 | 58 | // set up the template 59 | fs.copySync(path.join(__dirname, '../../template'), appPath) 60 | 61 | // create the package json 62 | fs.writeFileSync( 63 | path.join(appPath, 'package.json'), 64 | JSON.stringify(appPackageJson, null, 2) + os.EOL 65 | ) 66 | // copy gitignore 67 | fs.copySync( 68 | path.join(__dirname, '../../template/gitignore'), 69 | path.join(appPath, '.gitignore') 70 | ) 71 | fs.unlinkSync(path.join(appPath, 'gitignore')) 72 | 73 | // install package dependencies 74 | console.log( 75 | 'Installing ' + 76 | [...packageDevDependencies].map((i) => chalk.cyan(i)).join(', ') 77 | ) 78 | 79 | let cmd 80 | let devDependencyArgs 81 | 82 | if (useYarn) { 83 | cmd = 'yarnpkg' 84 | devDependencyArgs = ['add', ...packageDevDependencies, '--dev'] 85 | } else { 86 | cmd = 'npm' 87 | devDependencyArgs = ['install', '--save-dev', ...packageDevDependencies] 88 | } 89 | 90 | // install dev dependencies 91 | const devDependencyProc = spawnSync(cmd, devDependencyArgs, { 92 | stdio: 'inherit', 93 | cwd: appPath, 94 | }) 95 | if (devDependencyProc.status !== 0) { 96 | console.error() 97 | console.error( 98 | chalk.red('Command'), 99 | chalk.redBright(`'${cmd} ${devDependencyArgs.join(' ')}'`), 100 | chalk.red('failed.') 101 | ) 102 | console.error() 103 | process.exit(1) 104 | } 105 | 106 | // initialize git repo 107 | try { 108 | execSync('git init', { 109 | cwd: appPath, 110 | stdio: 'ignore', 111 | }) 112 | execSync('git add -A', { 113 | cwd: appPath, 114 | stdio: 'ignore', 115 | }) 116 | execSync('git commit -m "first commit by typescript-node-scripts"', { 117 | cwd: appPath, 118 | stdio: 'ignore', 119 | }) 120 | } catch (e) { 121 | console.warn( 122 | chalk.yellow( 123 | 'Failed to initialize git repository. You might want to initialize it yourself.' 124 | ) 125 | ) 126 | } 127 | 128 | const displayedCommand = useYarn ? 'yarn' : 'npm' 129 | console.log() 130 | console.log(chalk.green('Successfully created ' + appName + ' at ' + appPath)) 131 | console.log('Inside your project directory, you can run these commands:') 132 | console.log() 133 | console.log(chalk.cyan(` ${displayedCommand} start`)) 134 | console.log(' Starts the development server.') 135 | console.log() 136 | console.log(chalk.cyan(` ${displayedCommand} test`)) 137 | console.log(' Runs the Jest test runner.') 138 | console.log() 139 | console.log(chalk.cyan(` ${displayedCommand} build`)) 140 | console.log(' Bundles your application into a production-ready bundle.') 141 | console.log() 142 | console.log( 143 | chalk.green('To get started right away, we recommend running: \n') 144 | ) 145 | console.log(chalk.cyan(' cd'), appName) 146 | console.log(chalk.cyan(` ${displayedCommand}`), 'start') 147 | console.log() 148 | } 149 | 150 | createApp(yarnAvailable(), argv[0]) 151 | -------------------------------------------------------------------------------- /src/scripts/migration/tslint-to-eslint/filesystem.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs-extra' 2 | 3 | export function loadJson(path: string): Promise { 4 | return new Promise((resolve, reject) => { 5 | fs.readFile(path, { encoding: 'utf-8' }, (err, data) => { 6 | if (err) { 7 | return reject(err) 8 | } 9 | try { 10 | return resolve(JSON.parse(data as any)) 11 | } catch (e) { 12 | return reject(err) 13 | } 14 | }) 15 | }) 16 | } 17 | 18 | export function saveJson(path: string, data: unknown): Promise { 19 | return new Promise((resolve, reject) => { 20 | fs.writeFile(path, JSON.stringify(data, null, 2), (err) => { 21 | if (err) { 22 | return reject(err) 23 | } else { 24 | return resolve(true) 25 | } 26 | }) 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /src/scripts/migration/tslint-to-eslint/hash.ts: -------------------------------------------------------------------------------- 1 | import crypto from 'crypto' 2 | import * as fs from 'fs' 3 | 4 | export function getFileHash(path: string) { 5 | return new Promise((resolve) => { 6 | const hash = crypto.createHash('sha256') 7 | const input = fs.createReadStream(path, { encoding: 'utf-8' }) 8 | input.on('readable', () => { 9 | const data = input.read() 10 | if (data) { 11 | hash.update(data) 12 | } else { 13 | return resolve(hash.digest('hex')) 14 | } 15 | }) 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /src/scripts/migration/tslint-to-eslint/index.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import { paths, resolveOwn, resolveApp } from '../../../lib/paths' 3 | import { getFileHash } from './hash' 4 | import { loadJson, saveJson } from './filesystem' 5 | import * as fs from 'fs-extra' 6 | import { spawnSync } from 'child_process' 7 | import { 8 | createMigrationLogger, 9 | MIGRATION_OP_TYPE, 10 | } from '../../util/migrationLogger' 11 | import { fileExists } from '../../util/fileExists' 12 | 13 | const log = createMigrationLogger() 14 | let loggedInfo = false 15 | 16 | async function handlePackageJson() { 17 | const packageJson = await loadJson(paths.appPackageJson) 18 | 19 | const LEGACY_TSLINT_DEFAULT_COMMAND = 'tslint --project .' 20 | const ESLINT_DEFAULT_COMMAND = "eslint 'src/**/*.{js,ts}'" 21 | 22 | let shouldSave = false 23 | 24 | if ('lint' in packageJson.scripts) { 25 | if (packageJson.scripts.lint === ESLINT_DEFAULT_COMMAND) { 26 | return 27 | } 28 | if (packageJson.scripts.lint === LEGACY_TSLINT_DEFAULT_COMMAND) { 29 | log('Updating lint command in package.json', MIGRATION_OP_TYPE.MODIFY) 30 | packageJson.scripts.lint = ESLINT_DEFAULT_COMMAND 31 | } else { 32 | log( 33 | 'Found custom lint command, renaming script to "lint:legacy" in package.json', 34 | MIGRATION_OP_TYPE.MODIFY 35 | ) 36 | packageJson.scripts['lint:legacy'] = packageJson.scripts.lint 37 | log('Adding new lint command in package.json', MIGRATION_OP_TYPE.MODIFY) 38 | packageJson.scripts.lint = ESLINT_DEFAULT_COMMAND 39 | } 40 | shouldSave = true 41 | } else { 42 | log('Adding lint command to package.json', MIGRATION_OP_TYPE.WRITE) 43 | packageJson.scripts.lint = ESLINT_DEFAULT_COMMAND 44 | shouldSave = true 45 | } 46 | if (shouldSave) { 47 | await saveJson(paths.appPackageJson, packageJson) 48 | } 49 | } 50 | 51 | async function handleLinterConfigs() { 52 | const LEGACY_TSLINT_JSON_HASH = 53 | '3d6715a3490c843940026a410a0b41fa8c95ba468e93a8bab18fe0a44baada9c' 54 | 55 | const hasTslintFile = await fileExists(paths.legacyAppTslint) 56 | const hasEslintFile = await fileExists(paths.appEslint) 57 | const templateEslintrc = resolveOwn('template/.eslintrc.json') 58 | 59 | let shouldAddEslintFile = true 60 | 61 | if (hasEslintFile) { 62 | const sameEslintFile = 63 | (await getFileHash(paths.appEslint)) === 64 | (await getFileHash(templateEslintrc)) 65 | 66 | if (sameEslintFile) { 67 | log('.eslintrc.json is already updated', MIGRATION_OP_TYPE.SKIP) 68 | shouldAddEslintFile = false 69 | } else { 70 | log( 71 | 'Renaming existing .eslintrc.json to .eslintrc.json.legacy', 72 | MIGRATION_OP_TYPE.MODIFY 73 | ) 74 | // TODO: possible collision 75 | fs.moveSync(paths.appEslint, paths.appEslint + '.legacy') 76 | } 77 | } 78 | if (shouldAddEslintFile) { 79 | log('Adding .eslintrc.json', MIGRATION_OP_TYPE.WRITE) 80 | fs.copyFileSync(templateEslintrc, paths.appEslint) 81 | } 82 | 83 | if (hasTslintFile) { 84 | const currentTslintHash = await getFileHash(paths.legacyAppTslint) 85 | if (currentTslintHash === LEGACY_TSLINT_JSON_HASH) { 86 | log('Removing legacy tslint.json', MIGRATION_OP_TYPE.DELETE) 87 | fs.unlinkSync(paths.legacyAppTslint) 88 | } else { 89 | log( 90 | 'Renaming existing tslint.json to tslint.json.legacy', 91 | MIGRATION_OP_TYPE.MODIFY 92 | ) 93 | log( 94 | 'Custom tslint.json detected. You might need to manually port over your configuration, or use a tool like typescript-eslint/tslint-to-eslint-config', 95 | MIGRATION_OP_TYPE.INFO 96 | ) 97 | loggedInfo = true 98 | fs.moveSync(paths.legacyAppTslint, paths.legacyAppTslint + '.legacy') 99 | } 100 | } 101 | } 102 | 103 | async function handleLinterDependencies() { 104 | const packageJson = await loadJson(paths.appPackageJson) 105 | 106 | const { devDependencies = {}, dependenecies = {} } = packageJson 107 | if ('tslint' in devDependencies) { 108 | log('Removing tslint from devDependencies', MIGRATION_OP_TYPE.DELETE) 109 | // @@mutation 110 | delete packageJson.devDependencies['tslint'] 111 | } 112 | if ('tslint' in dependenecies) { 113 | log('Removing tslint from dependencies', MIGRATION_OP_TYPE.DELETE) 114 | // @@mutation 115 | delete packageJson.dependencies['tslint'] 116 | } 117 | 118 | // save changes to package.json 119 | await saveJson(paths.appPackageJson, packageJson) 120 | 121 | const allDependencies = [ 122 | ...Object.keys(devDependencies), 123 | ...Object.keys(dependenecies), 124 | ] 125 | const tslintDependents = [] 126 | for (const dep of allDependencies) { 127 | if (~dep.indexOf('tslint') && dep !== 'tslint') { 128 | tslintDependents.push(dep) 129 | } 130 | } 131 | if (tslintDependents.length) { 132 | log( 133 | 'The following dependencies are related to tslint, but were not removed:', 134 | MIGRATION_OP_TYPE.INFO 135 | ) 136 | for (const dep of tslintDependents) { 137 | log(` ${dep}`, MIGRATION_OP_TYPE.INFO) 138 | } 139 | log( 140 | 'You might want to manually remove them, and add the proper configuration to .eslintrc.json', 141 | MIGRATION_OP_TYPE.INFO 142 | ) 143 | loggedInfo = true 144 | } 145 | } 146 | 147 | async function handleAddDependencies() { 148 | const devDependencies = [ 149 | 'eslint', 150 | 'eslint-plugin-import', 151 | 'babel-eslint', 152 | '@typescript-eslint/eslint-plugin', 153 | '@typescript-eslint/parser', 154 | ] 155 | 156 | const hasYarnLockfile = await fileExists(resolveApp('yarn.lock')) 157 | 158 | let cmd 159 | let devDependencyArgs 160 | 161 | if (hasYarnLockfile) { 162 | cmd = 'yarnpkg' 163 | devDependencyArgs = ['add', '--dev', '--silent', ...devDependencies] 164 | } else { 165 | cmd = 'npm' 166 | devDependencyArgs = [ 167 | 'install', 168 | '--silent', 169 | '--save-dev', 170 | ...devDependencies, 171 | ] 172 | } 173 | 174 | log( 175 | 'Installing ' + [...devDependencies].map((i) => chalk.green(i)).join(', '), 176 | MIGRATION_OP_TYPE.INSTALL 177 | ) 178 | 179 | // install dev dependencies 180 | const devDependencyProc = spawnSync(cmd, devDependencyArgs, { 181 | stdio: 'inherit', 182 | cwd: resolveApp('.'), 183 | }) 184 | 185 | if (devDependencyProc.status !== 0) { 186 | console.error() 187 | console.error( 188 | chalk.red('Command'), 189 | chalk.redBright(`'${cmd} ${devDependencyArgs.join(' ')}'`), 190 | chalk.red('failed.') 191 | ) 192 | console.error() 193 | process.exit(1) 194 | } else { 195 | log('Successfully installed packages', MIGRATION_OP_TYPE.INSTALL) 196 | } 197 | } 198 | 199 | async function main() { 200 | try { 201 | await handlePackageJson() 202 | await handleLinterConfigs() 203 | await handleLinterDependencies() 204 | await handleAddDependencies() 205 | 206 | console.log() 207 | if (loggedInfo) { 208 | log( 209 | 'There are a few info messages logged above which might need to be addressed', 210 | MIGRATION_OP_TYPE.INFO 211 | ) 212 | } 213 | log( 214 | 'Successfully migrated tslint configuration to eslint configuration', 215 | MIGRATION_OP_TYPE.DONE 216 | ) 217 | } catch (e: any) { 218 | console.log() 219 | log( 220 | 'Uh oh, something went wrong. Please open an issue if this problem persists.', 221 | MIGRATION_OP_TYPE.ERROR 222 | ) 223 | log(e.message, MIGRATION_OP_TYPE.ERROR) 224 | log(e.stack, MIGRATION_OP_TYPE.ERROR) 225 | } 226 | } 227 | 228 | main() 229 | -------------------------------------------------------------------------------- /src/scripts/start.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import * as typescript from 'typescript' 3 | import '../injectors/dev' 4 | import { clearConsole } from '../lib/clearConsole' 5 | import { createCompiler } from '../lib/webpackCompiler' 6 | import { RuntimeOptions, IS_INTERACTIVE } from '../util/env' 7 | import { getWebpackConfig } from './util/getWebpackConfig' 8 | 9 | if (IS_INTERACTIVE) { 10 | clearConsole() 11 | } 12 | 13 | console.log(chalk.cyan('Starting the development server...')) 14 | console.log(chalk.green('Using TypeScript v' + typescript.version)) 15 | console.log() 16 | 17 | const compiler = createCompiler(getWebpackConfig('development'), RuntimeOptions) 18 | 19 | // start the webpack watchers 20 | compiler.watch({}, (err) => { 21 | if (err) { 22 | throw err 23 | } 24 | }) 25 | -------------------------------------------------------------------------------- /src/scripts/test.ts: -------------------------------------------------------------------------------- 1 | import * as jest from 'jest' 2 | import * as path from 'path' 3 | import '../injectors/test' 4 | import { paths } from '../lib/paths' 5 | import { createJestConfig } from './util/createJestConfig' 6 | const argv = process.argv.slice(2) 7 | 8 | if ( 9 | !process.env.CI && 10 | argv.indexOf('--coverage') === -1 && 11 | argv.indexOf('--watchAll') === -1 12 | ) { 13 | argv.push('--watch') 14 | } 15 | 16 | argv.push( 17 | '--config', 18 | JSON.stringify( 19 | createJestConfig(path.resolve(paths.appSrc, '..'), (relativePath: string) => 20 | path.resolve(__dirname, '..', relativePath) 21 | ) 22 | ) 23 | ) 24 | 25 | jest.run(argv) 26 | -------------------------------------------------------------------------------- /src/scripts/util/createJestConfig.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import * as fs from 'fs' 3 | import * as path from 'path' 4 | import { paths } from '../../lib/paths' 5 | // eslint-disable-next-line @typescript-eslint/no-var-requires 6 | const appTsConfig = require(paths.appTsConfig) 7 | 8 | /** 9 | * Transform paths from tsconfig.json to Jest compatible path mappings 10 | * Transforms 11 | * "@_util/*": ["src/_util/*"] 12 | * into 13 | * "@_util/(.*)": "/src/_util/$1" 14 | * excluding global * 15 | * @param {json} config 16 | * @returns {object} key:value path mapping for jest 17 | */ 18 | const transformTsPathsToJestPaths = (tsconfig: any) => { 19 | const { paths: tsconfigPaths = {}, baseUrl: tsconfigBaseUrl = '' } = 20 | tsconfig.compilerOptions 21 | const resolvedBase = path.join('', tsconfigBaseUrl) 22 | return Object.keys(tsconfigPaths).reduce( 23 | (acc, key) => 24 | key === '*' 25 | ? acc 26 | : Object.assign({}, acc, { 27 | ['^' + key.replace('*', '(.*)') + '$']: path.join( 28 | resolvedBase, 29 | tsconfigPaths[key][0].replace('*', '$1') 30 | ), 31 | }), 32 | {} 33 | ) 34 | } 35 | 36 | export const createJestConfig = ( 37 | rootDir: string, 38 | resolve: (path: string) => string 39 | ) => { 40 | const setupTests = fs.existsSync(paths.testsSetup) 41 | ? ['/setupTests.ts'] 42 | : [] 43 | 44 | const config = { 45 | collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts'], 46 | testMatch: [ 47 | '/src/**/__tests__/**/*.(j|t)s?(x)', 48 | '/src/**/?(*.)(spec|test|t).(j|t)s?(x)', 49 | ], 50 | transform: { 51 | '^.+\\.jsx?$': resolve('lib/jest/babelPreprocessor.js'), 52 | '^.+\\.tsx?$': resolve('lib/jest/typescriptPreprocessor.js'), 53 | }, 54 | setupFilesAfterEnv: setupTests, 55 | testEnvironment: 'node', 56 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 57 | globals: { 58 | NODE_ENV: 'test', 59 | 'ts-jest': { 60 | tsconfig: paths.appTsConfig, 61 | }, 62 | }, 63 | moduleNameMapper: transformTsPathsToJestPaths(appTsConfig), 64 | } 65 | 66 | if (rootDir) { 67 | ;(config as any).rootDir = rootDir 68 | } 69 | 70 | const overrides = Object.assign({}, require(paths.appPackageJson).jest) 71 | const supportedOverrides = [ 72 | 'collectCoverageFrom', 73 | 'coverageReporters', 74 | 'coverageThreshold', 75 | ] 76 | 77 | if (overrides) { 78 | supportedOverrides.forEach((key) => { 79 | if (overrides.hasOwnProperty(key)) { 80 | ;(config as any)[key] = overrides[key] 81 | delete overrides[key] 82 | } 83 | }) 84 | const leftoverOverrides = Object.keys(overrides) 85 | if (leftoverOverrides.length) { 86 | console.error( 87 | chalk.red( 88 | '\n' + 89 | 'typescript-node-scripts only supports overriding these Jest options: \n\n' + 90 | supportedOverrides.map((key) => ' ' + chalk.bold(key)).join('\n') + 91 | '\n\n' + 92 | 'These Jest options in your package.json are not supported: \n\n' + 93 | leftoverOverrides.map((key) => ' ' + chalk.bold(key)).join('\n') + 94 | '\n\n' 95 | ) 96 | ) 97 | process.exit(1) 98 | } 99 | } 100 | return config 101 | } 102 | -------------------------------------------------------------------------------- /src/scripts/util/fileExists.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs-extra' 2 | 3 | export function fileExists(path: string): Promise { 4 | return new Promise((resolve) => { 5 | fs.access(path, fs.constants.F_OK, (err) => { 6 | if (err) { 7 | return resolve(false) 8 | } else { 9 | return resolve(true) 10 | } 11 | }) 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /src/scripts/util/fileSizeReporter.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import filesize from 'filesize' 3 | import * as fs from 'fs' 4 | 5 | interface FileSizeObjectOutput { 6 | value: number 7 | symbol: string 8 | } 9 | 10 | export const getBundleSize = (fileName: string) => { 11 | try { 12 | const read = fs.statSync(fileName) 13 | return read.size 14 | } catch (e) { 15 | return null 16 | } 17 | } 18 | 19 | export const diffFileSize = ( 20 | sizeBeforeBuild: number, 21 | sizeAfterBuild: number 22 | ) => { 23 | if (!sizeAfterBuild) { 24 | return '' 25 | } 26 | const afterBuildFormatted: FileSizeObjectOutput = filesize(sizeAfterBuild, { 27 | base: 10, 28 | output: 'object', 29 | }) as unknown as FileSizeObjectOutput 30 | if (!sizeBeforeBuild) { 31 | return chalk.green( 32 | `${afterBuildFormatted.value} ${afterBuildFormatted.symbol}` 33 | ) 34 | } 35 | const diff: FileSizeObjectOutput = filesize( 36 | sizeAfterBuild - sizeBeforeBuild, 37 | { 38 | base: 10, 39 | output: 'object', 40 | } 41 | ) as unknown as FileSizeObjectOutput 42 | 43 | if (diff.value === 0) { 44 | return `${afterBuildFormatted.value} ${afterBuildFormatted.symbol} (+0 B)` 45 | } else if (diff.value > 0) { 46 | return chalk.yellow( 47 | `${afterBuildFormatted.value} ${afterBuildFormatted.symbol} (+${diff.value} ${diff.symbol})` 48 | ) 49 | } else { 50 | return chalk.green( 51 | `${afterBuildFormatted.value} ${afterBuildFormatted.symbol} (${diff.value} ${diff.symbol})` 52 | ) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/scripts/util/getWebpackConfig.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs' 2 | import * as webpack from 'webpack' 3 | import chalk from 'chalk' 4 | import merge from 'webpack-merge' 5 | import { paths } from '../../lib/paths' 6 | import { createWebpackConfig } from '../../lib/createWebpackConfig' 7 | 8 | /** 9 | * Gets the webpack configuration depending on the environment being passed in 10 | * 11 | * This also checks for a custom 'webpack.config.override.js' and merges it with the base configuration provided by the library 12 | * @param environment 13 | */ 14 | export function getWebpackConfig( 15 | environment: 'development' | 'production' 16 | ): webpack.Configuration { 17 | const baseConfig = createWebpackConfig(environment) 18 | if (fs.existsSync(paths.webpackOverride)) { 19 | console.log(chalk.cyan('• Using merged webpack.config.override.js')) 20 | const customConfig: (isDev: boolean) => any = require(paths.webpackOverride) 21 | if (typeof customConfig === 'function') { 22 | return merge( 23 | baseConfig as any, 24 | customConfig(environment === 'development') 25 | ) as webpack.Configuration 26 | } else if (typeof customConfig === 'object') { 27 | return merge( 28 | baseConfig as any, 29 | require(paths.webpackOverride) 30 | ) as webpack.Configuration 31 | } else { 32 | console.log(chalk.red('Failed to parse webpack.config.override.js')) 33 | process.exit(1) 34 | } 35 | } else { 36 | return baseConfig 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/scripts/util/migrationLogger.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | 3 | export enum MIGRATION_OP_TYPE { 4 | WRITE = 'write', 5 | MODIFY = 'modify', 6 | DELETE = 'delete', 7 | SKIP = 'skip', 8 | INFO = 'info', 9 | INSTALL = 'install', 10 | DONE = 'done', 11 | ERROR = 'error', 12 | } 13 | 14 | export function createMigrationLogger() { 15 | function log(message: string, type: MIGRATION_OP_TYPE) { 16 | let chalkWrapper 17 | switch (type) { 18 | case MIGRATION_OP_TYPE.DONE: 19 | case MIGRATION_OP_TYPE.INSTALL: 20 | case MIGRATION_OP_TYPE.WRITE: 21 | chalkWrapper = chalk.green 22 | break 23 | case MIGRATION_OP_TYPE.MODIFY: 24 | chalkWrapper = chalk.yellow 25 | break 26 | case MIGRATION_OP_TYPE.ERROR: 27 | case MIGRATION_OP_TYPE.DELETE: 28 | chalkWrapper = chalk.red 29 | break 30 | case MIGRATION_OP_TYPE.SKIP: 31 | chalkWrapper = chalk.dim 32 | break 33 | case MIGRATION_OP_TYPE.INFO: 34 | chalkWrapper = chalk.cyan 35 | break 36 | default: 37 | chalkWrapper = (identity: T) => identity 38 | } 39 | console.log(`${chalkWrapper(type.padStart(7))} ${message}`) 40 | } 41 | return log 42 | } 43 | -------------------------------------------------------------------------------- /src/scripts/util/yarnAvailable.ts: -------------------------------------------------------------------------------- 1 | import { execSync } from 'child_process' 2 | 3 | export function yarnAvailable() { 4 | try { 5 | execSync('yarnpkg --version', { stdio: 'ignore' }) 6 | return true 7 | } catch (e) { 8 | return false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/types/TNS.ts: -------------------------------------------------------------------------------- 1 | export interface TNSOptions { 2 | noCollapse: boolean 3 | noAutoStart: boolean 4 | useMonorepo: boolean 5 | bypassCiWarnings: boolean 6 | } 7 | -------------------------------------------------------------------------------- /src/util/env.ts: -------------------------------------------------------------------------------- 1 | import { TNSOptions } from '../types/TNS' 2 | 3 | const { argv } = process 4 | 5 | export const TNS_ARGUMENTS = { 6 | MONOREPO: '--monorepo', 7 | NO_COLLAPSE: '--no-collapse', 8 | NO_AUTO_STATRT: '--no-auto-start', 9 | BYPASS_CI_WARNINGS: '--bypass-ci-warnings', 10 | } 11 | 12 | export const RuntimeOptions: TNSOptions = { 13 | useMonorepo: !!~argv.indexOf(TNS_ARGUMENTS.MONOREPO), 14 | noCollapse: !!~argv.indexOf(TNS_ARGUMENTS.NO_COLLAPSE), 15 | noAutoStart: !!~argv.indexOf(TNS_ARGUMENTS.NO_AUTO_STATRT), 16 | bypassCiWarnings: !!~argv.indexOf(TNS_ARGUMENTS.BYPASS_CI_WARNINGS), 17 | } 18 | 19 | export const IS_CI = 20 | process.env.CI && 21 | (typeof process.env.CI !== 'string' || 22 | process.env.CI.toLowerCase() !== 'false') 23 | 24 | export const IS_INTERACTIVE = process.stdout.isTTY 25 | -------------------------------------------------------------------------------- /src/util/platform.ts: -------------------------------------------------------------------------------- 1 | import * as os from 'os' 2 | 3 | export function isWindows() { 4 | return os.platform() === 'win32' 5 | } 6 | -------------------------------------------------------------------------------- /template/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@babel/eslint-parser", 3 | "extends": [ 4 | "eslint:recommended" 5 | ], 6 | "plugins": [ 7 | "import" 8 | ], 9 | "env": { 10 | "browser": false, 11 | "node": true, 12 | "jest": true, 13 | "es6": true 14 | }, 15 | "parserOptions": { 16 | "ecmaVersion": 2018, 17 | "sourceType": "module", 18 | "requireConfigFile": false 19 | }, 20 | "overrides": [ 21 | { 22 | "files": [ 23 | "**/*.ts" 24 | ], 25 | "parser": "@typescript-eslint/parser", 26 | "parserOptions": { 27 | "ecmaVersion": 2018, 28 | "sourceType": "module", 29 | "warnOnUnsupportedTypeScriptVersion": true, 30 | "project": "./tsconfig.json" 31 | }, 32 | "extends": [ 33 | "plugin:@typescript-eslint/recommended" 34 | ], 35 | "plugins": [ 36 | "@typescript-eslint" 37 | ], 38 | "rules": { 39 | "default-case": "off", 40 | "no-dupe-class-members": "off", 41 | "no-undef": "off", 42 | "no-array-constructor": "off", 43 | "@typescript-eslint/no-array-constructor": "error", 44 | "no-use-before-define": "off", 45 | "@typescript-eslint/no-use-before-define": [ 46 | "error", 47 | { 48 | "functions": false, 49 | "classes": false, 50 | "variables": false, 51 | "typedefs": false 52 | } 53 | ], 54 | "@typescript-eslint/no-non-null-assertion": "off", 55 | "@typescript-eslint/no-explicit-any": "off", 56 | "@typescript-eslint/no-object-literal-type-assertion": "off", 57 | "@typescript-eslint/explicit-member-accessibility": "off", 58 | "no-unused-vars": "off", 59 | "@typescript-eslint/no-unused-vars": [ 60 | "error", 61 | { 62 | "args": "none", 63 | "ignoreRestSiblings": true 64 | } 65 | ], 66 | "no-useless-constructor": "off", 67 | "@typescript-eslint/no-useless-constructor": "error", 68 | "@typescript-eslint/explicit-function-return-type": "off", 69 | "@typescript-eslint/prefer-interface": "off", 70 | "@typescript-eslint/no-namespace": "off", 71 | "@typescript-eslint/explicit-module-boundary-types": "off" 72 | } 73 | } 74 | ] 75 | } -------------------------------------------------------------------------------- /template/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | /dist 12 | 13 | # misc 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* -------------------------------------------------------------------------------- /template/gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | /dist 12 | 13 | # misc 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* -------------------------------------------------------------------------------- /template/setupTests.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is used to set up the testing framework 3 | * before each test is executed. 4 | * 5 | * For more information, please consult: 6 | * https://facebook.github.io/jest/docs/en/configuration.html#setuptestframeworkscriptfile-string 7 | */ 8 | -------------------------------------------------------------------------------- /template/src/App.ts: -------------------------------------------------------------------------------- 1 | export default () => { 2 | // eslint-disable-next-line 3 | console.log('App is running'); 4 | }; 5 | -------------------------------------------------------------------------------- /template/src/__tests__/App.ts: -------------------------------------------------------------------------------- 1 | import App from "../App"; 2 | 3 | describe("test", () => { 4 | it("runs", () => { 5 | expect(1).toEqual(1); 6 | }); 7 | it("default of App export is a function", () => { 8 | expect(typeof App === "function").toBe(true); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /template/src/index.ts: -------------------------------------------------------------------------------- 1 | import App from "./App"; 2 | 3 | App(); 4 | -------------------------------------------------------------------------------- /template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "build", 4 | "module": "commonjs", 5 | "target": "es6", 6 | "allowJs": true, 7 | "moduleResolution": "node", 8 | "rootDir": "src", 9 | "strict": true, 10 | "noImplicitReturns": true, 11 | "noUnusedLocals": true, 12 | "resolveJsonModule": true, 13 | "sourceMap": true 14 | }, 15 | "exclude": ["node_modules", "build", "coverage", "dist", "setupTests.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /tests/e2e.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" 3 | 4 | # test if in docker or CI environment 5 | # this script should only be running in docker or a CI environment! 6 | if [ -f /.dockerenv ] || [ -n "${CI}" ] ; then 7 | echo "Detected script running in Docker or CI environment." 8 | else 9 | echo "ERR! This script is intended to be used inside Docker or a CI environment." 10 | echo "ERR! Run 'yarn e2e:local' instead." 11 | exit 1 12 | fi 13 | 14 | # start in the directory where the script runs 15 | cd $SCRIPT_DIR 16 | 17 | TEMP_APP_PATH=`mktemp -d` 18 | VERDACCIO_REGISTRY_URL=http://localhost:4873 19 | 20 | function exists { 21 | for f in $*; do 22 | test -e "$f" 23 | done 24 | } 25 | 26 | # exit if any command fails 27 | set -e 28 | # echo every command being executed 29 | set -x 30 | 31 | # go back to root directory 32 | cd .. 33 | 34 | # update npm 35 | npm i -g npm@latest 36 | 37 | # install deps 38 | yarn 39 | 40 | # compile 41 | yarn compile 42 | 43 | # start verdaccio 44 | VERDACCIO_REGISTRY_LOGS=`mktemp` 45 | nohup npx verdaccio@4.3.5 -c tests/verdaccio.yml &>$VERDACCIO_REGISTRY_LOGS & 46 | # wait for verdaccio to boot 47 | grep -q 'http address' <(tail -f $VERDACCIO_REGISTRY_LOGS) 48 | 49 | # set registry to verdaccio registry 50 | npm set registry "$VERDACCIO_REGISTRY_URL" 51 | yarn config set registry "$VERDACCIO_REGISTRY_URL" 52 | 53 | # login to custom registy 54 | (cd && npx npm-auth-to-token@1.0.0 -u user -p password -e user@example.com -r "$VERDACCIO_REGISTRY_URL") 55 | 56 | #==============================# 57 | # Test development environment # 58 | #==============================# 59 | # lint project 60 | yarn lint 61 | # test templates 62 | yarn build 63 | # check for local build files 64 | exists template/dist/*.js 65 | CI=true yarn test 66 | 67 | # force git user (github actions doesn't seem to support this well) 68 | git config --global user.email "actions@github.com" 69 | git config --global user.name "GitHub Actions" 70 | 71 | echo "node_modules/" > .gitignore 72 | git init && git add . && git commit -m "feat(package): fake commit" 73 | 74 | # bump version so that we can 'deploy' to verdaccio 75 | npm version patch --force 76 | # publish to verdaccio 77 | npm publish 78 | 79 | #================================# 80 | # Test end user install from npm # 81 | #================================# 82 | # simulate end user installs 83 | cd $TEMP_APP_PATH 84 | npx typescript-node-scripts create test-app 85 | 86 | cd test-app 87 | exists node_modules/typescript-node-scripts 88 | 89 | #========================# 90 | # Test generated project # 91 | #========================# 92 | # build 93 | yarn build 94 | # check for build files 95 | exists dist/*.js 96 | CI=true yarn test 97 | 98 | #=======================# 99 | # Prepare sink tsconfig # 100 | #=======================# 101 | rm -rf ./tsconfig.json 102 | cp "$SCRIPT_DIR/sink/tsconfig.json" ./tsconfig.json 103 | 104 | #=================================================# 105 | # Run sink/ts-js-integration in generated project # 106 | #=================================================# 107 | # remove src folder 108 | rm -rf src/* 109 | # copy the ts-js-integration files to src 110 | cp -a "$SCRIPT_DIR/sink/ts-js-integration/." ./src 111 | # run the build and execute the bundle 112 | yarn build 113 | node dist/bundle.prod.js 114 | # run the test files 115 | CI=true yarn test 116 | 117 | 118 | #==============================================# 119 | # Run sink/typescript-3.7 in generated project # 120 | #==============================================# 121 | # remove src folder 122 | rm -rf src/* 123 | # copy the ts-js-integration files to src 124 | cp -a "$SCRIPT_DIR/sink/typescript-3.7/." ./src 125 | # run the build and execute the bundle 126 | yarn build 127 | # run the test files 128 | CI=true yarn test -------------------------------------------------------------------------------- /tests/sink/ts-js-integration/__tests__/cjs.js: -------------------------------------------------------------------------------- 1 | import cjs from '../cjs' 2 | import cjsNonDefault, { TEST } from '../cjs' 3 | 4 | describe('cjs', () => { 5 | it('can import star exports', () => { 6 | expect(typeof cjs.TEST === 'number').toBe(true) 7 | expect(typeof cjs.default === 'function').toBe(true) 8 | }) 9 | it('can import named exports', () => { 10 | expect(typeof TEST === 'number').toBe(true) 11 | expect(typeof cjsNonDefault.default === 'function').toBe(true) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /tests/sink/ts-js-integration/__tests__/esm.js: -------------------------------------------------------------------------------- 1 | import * as esm from '../esm' 2 | import esmDefault, { TEST } from '../esm' 3 | 4 | describe('esm', () => { 5 | it('can import star exports', () => { 6 | expect(typeof esm.TEST === 'number').toBe(true) 7 | expect(typeof esm.default === 'function').toBe(true) 8 | }) 9 | it('can import named exports', () => { 10 | expect(typeof TEST === 'number').toBe(true) 11 | expect(typeof esmDefault === 'function').toBe(true) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /tests/sink/ts-js-integration/__tests__/ts-import-js.ts: -------------------------------------------------------------------------------- 1 | import * as cjs from "../cjs"; 2 | import cjsDefault, { 3 | readFileSync as CJS_READ_FILE_SYNC, 4 | TEST as CJS_TEST, 5 | } from "../cjs"; 6 | import * as esm from "../esm"; 7 | import esmDefault, { 8 | readFileSync as ESM_READ_FILE_SYNC, 9 | TEST as ESM_TEST, 10 | } from "../cjs"; 11 | 12 | describe("importing js from ts", () => { 13 | describe("cjs", () => { 14 | it("can import named exports", () => { 15 | expect(typeof cjsDefault === "function").toBe(true); 16 | expect(typeof CJS_READ_FILE_SYNC === "function").toBe(true); 17 | expect(typeof CJS_TEST === "number").toBe(true); 18 | }); 19 | it("can import star imports", () => { 20 | expect(typeof cjs.default === "function").toBe(true); 21 | expect(typeof cjs.readFileSync === "function").toBe(true); 22 | expect(typeof cjs.TEST === "number").toBe(true); 23 | }); 24 | }); 25 | describe("esm", () => { 26 | it("can import named exports", () => { 27 | expect(typeof esmDefault === "function").toBe(true); 28 | expect(typeof ESM_READ_FILE_SYNC === "function").toBe(true); 29 | expect(typeof ESM_TEST === "number").toBe(true); 30 | }); 31 | it("can import star imports", () => { 32 | expect(typeof esm.default === "function").toBe(true); 33 | expect(typeof esm.readFileSync === "function").toBe(true); 34 | expect(typeof esm.TEST === "number").toBe(true); 35 | }); 36 | }); 37 | }); -------------------------------------------------------------------------------- /tests/sink/ts-js-integration/__tests__/ts.ts: -------------------------------------------------------------------------------- 1 | import * as tsRelative from "../ts"; 2 | import * as tsAbsolute from "~/ts"; 3 | 4 | describe("ts: absolute imports", () => { 5 | it("exports variables", () => { 6 | expect(typeof tsRelative.TEST === "number").toBe(true); 7 | }); 8 | it("exports default", () => { 9 | expect(typeof tsRelative.default === "function").toBe(true); 10 | }); 11 | }); 12 | 13 | describe("ts: relative imports", () => { 14 | it("exports variables", () => { 15 | expect(typeof tsAbsolute.TEST === "number").toBe(true); 16 | }); 17 | it("exports default", () => { 18 | expect(typeof tsAbsolute.default === "function").toBe(true); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /tests/sink/ts-js-integration/cjs.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-var-requires 2 | const fs = require("fs"); 3 | 4 | module.exports = { 5 | TEST: 2, 6 | default: () => 1, 7 | readFileSync: fs.readFileSync 8 | }; 9 | -------------------------------------------------------------------------------- /tests/sink/ts-js-integration/esm.js: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | 3 | export const readFileSync = fs.readFileSync; 4 | export const TEST = 2; 5 | export default () => { 6 | // eslint-disable-next-line 7 | console.log('App is running'); 8 | }; 9 | -------------------------------------------------------------------------------- /tests/sink/ts-js-integration/index.ts: -------------------------------------------------------------------------------- 1 | import * as assert from "assert"; 2 | import * as cjs from "./cjs"; 3 | import esmDefault, { 4 | readFileSync as ESM_READ_FILE_SYNC, 5 | TEST as ESM_TEST 6 | } from "./cjs"; 7 | import cjsDefault, { 8 | readFileSync as CJS_READ_FILE_SYNC, 9 | TEST as CJS_TEST 10 | } from "./cjs"; 11 | import * as esm from "./esm"; 12 | 13 | assert(typeof cjsDefault === "function"); 14 | assert(typeof CJS_READ_FILE_SYNC === "function"); 15 | assert(typeof CJS_TEST === "number"); 16 | assert(typeof cjs.default === "function"); 17 | assert(typeof cjs.readFileSync === "function"); 18 | assert(typeof cjs.TEST === "number"); 19 | assert(typeof esmDefault === "function"); 20 | assert(typeof ESM_READ_FILE_SYNC === "function"); 21 | assert(typeof ESM_TEST === "number"); 22 | assert(typeof esm.default === "function"); 23 | assert(typeof esm.readFileSync === "function"); 24 | assert(typeof esm.TEST === "number"); 25 | -------------------------------------------------------------------------------- /tests/sink/ts-js-integration/ts.ts: -------------------------------------------------------------------------------- 1 | export const TEST = 2; 2 | export default () => { 3 | // eslint-disable-next-line 4 | console.log('App is running'); 5 | }; 6 | -------------------------------------------------------------------------------- /tests/sink/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "outDir": "build", 5 | "module": "commonjs", 6 | "target": "es6", 7 | "allowJs": true, 8 | "moduleResolution": "node", 9 | "rootDir": "src", 10 | "strict": true, 11 | "noImplicitReturns": true, 12 | "noUnusedLocals": true, 13 | "resolveJsonModule": true, 14 | "sourceMap": true, 15 | "paths": { 16 | "~/*": ["src/*"] 17 | } 18 | }, 19 | "exclude": ["node_modules", "build", "coverage", "dist", "setupTests.ts"] 20 | } 21 | -------------------------------------------------------------------------------- /tests/sink/typescript-3.7/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import { f, OptChainType } from '../index' 2 | 3 | describe('optional chaining and nullish coalesing', () => { 4 | it('returns Infinity if any of the paths of OptChainType is undefined', () => { 5 | const optChainObject: OptChainType = { 6 | a: {} 7 | } 8 | expect(f(optChainObject)).toEqual(Infinity) 9 | }) 10 | it('returns a.b.c if all of the paths of OptChainType is defined', () => { 11 | const optChainObject: OptChainType = { 12 | a: { 13 | b: { 14 | c: 0 15 | } 16 | } 17 | } 18 | expect(f(optChainObject)).toEqual(optChainObject.a!.b!.c) 19 | }) 20 | }) -------------------------------------------------------------------------------- /tests/sink/typescript-3.7/index.ts: -------------------------------------------------------------------------------- 1 | export type OptChainType = { 2 | a?: { 3 | b?: { 4 | c: number; 5 | }; 6 | }; 7 | } 8 | 9 | export function f(arg: OptChainType) { 10 | return arg.a?.b?.c ?? Infinity 11 | } 12 | -------------------------------------------------------------------------------- /tests/verdaccio.yml: -------------------------------------------------------------------------------- 1 | # 2 | # This is based on verdaccio's default config file. It allows all users 3 | # to do anything, so don't use it on production systems. 4 | # 5 | # Look here for more config file examples: 6 | # https://github.com/verdaccio/verdaccio/tree/master/conf 7 | # 8 | 9 | # path to a directory with all packages 10 | storage: ./storage 11 | 12 | auth: 13 | htpasswd: 14 | file: ./htpasswd 15 | # Maximum amount of users allowed to register, defaults to "+inf". 16 | # You can set this to -1 to disable registration. 17 | #max_users: 1000 18 | 19 | # a list of other known repositories we can talk to 20 | uplinks: 21 | npmjs: 22 | url: https://registry.npmjs.org/ 23 | max_fails: 100 24 | timeout: 60 25 | agent_options: 26 | keepAlive: true 27 | 28 | packages: 29 | '@*/*': 30 | # scoped packages 31 | access: $all 32 | publish: $all 33 | proxy: npmjs 34 | 35 | '**': 36 | # allow all users (including non-authenticated users) to read and 37 | # publish all packages 38 | # 39 | # you can specify usernames/groupnames (depending on your auth plugin) 40 | # and three keywords: "$all", "$anonymous", "$authenticated" 41 | access: $all 42 | 43 | # allow all known users to publish packages 44 | # (anyone can register by default, remember?) 45 | publish: $all 46 | 47 | # if package is not available locally, proxy requests to 'npmjs' registry 48 | proxy: npmjs 49 | 50 | # log settings 51 | logs: 52 | - {type: stdout, format: pretty, level: http} 53 | #- {type: file, path: verdaccio.log, level: info} -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | "allowJs": false, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./build", /* Redirect output structure to the directory. */ 15 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 29 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 30 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 31 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 32 | 33 | /* Additional Checks */ 34 | "noUnusedLocals": true, /* Report errors on unused locals. */ 35 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 36 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 37 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 38 | 39 | /* Module Resolution Options */ 40 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 41 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 42 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 43 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 44 | // "typeRoots": [], /* List of folders to include type definitions from. */ 45 | // "types": [], /* Type declaration files to be included in compilation. */ 46 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 47 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 48 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 49 | 50 | /* Source Map Options */ 51 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 52 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 53 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 54 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 55 | 56 | /* Experimental Options */ 57 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 58 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 59 | "skipLibCheck": true 60 | }, 61 | "include": ["src", "vendor"], 62 | "exclude": ["node_modules"] 63 | } 64 | -------------------------------------------------------------------------------- /vendor/@babel/code-frame.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@babel/code-frame' { 2 | interface BabelCodeFrameOptions { 3 | /** Syntax highlight the code as JavaScript for terminals. default: false */ 4 | highlightCode?: boolean 5 | /** The number of lines to show above the error. default: 2 */ 6 | linesBelow?: number 7 | /** The number of lines to show below the error. default: 3 */ 8 | linesAbove?: number 9 | /** 10 | * Forcibly syntax highlight the code as JavaScript (for non-terminals); 11 | * overrides highlightCode. 12 | * default: false 13 | */ 14 | forceColor?: boolean 15 | } 16 | 17 | interface BabelCodeFrameLineConfiguration { 18 | start?: { 19 | column?: number 20 | line?: number 21 | } 22 | end?: { 23 | column?: number 24 | line?: number 25 | } 26 | } 27 | 28 | /** 29 | * Generate errors that contain a code frame that point to source locations. 30 | * 31 | * @param rawLines Raw lines to frame 32 | * @param lineNumber Line number (1 indexed) 33 | * @param colNumber Column number 34 | * @param options Additional options 35 | * 36 | * @returns Framed code 37 | */ 38 | export function codeFrameColumns( 39 | rawLines: string, 40 | loc: BabelCodeFrameLineConfiguration, 41 | options?: BabelCodeFrameOptions 42 | ): string 43 | } 44 | -------------------------------------------------------------------------------- /vendor/pstree.remy.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'pstree.remy' { 2 | export const hasPS: boolean 3 | export default function main( 4 | pid: string, 5 | callback: (error: Error, children: string[]) => void 6 | ): void 7 | } 8 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | This website was created with [Docusaurus](https://docusaurus.io/). 2 | 3 | # What's In This Document 4 | 5 | * [Get Started in 5 Minutes](#get-started-in-5-minutes) 6 | * [Directory Structure](#directory-structure) 7 | * [Editing Content](#editing-content) 8 | * [Adding Content](#adding-content) 9 | * [Full Documentation](#full-documentation) 10 | 11 | # Get Started in 5 Minutes 12 | 13 | 1. Make sure all the dependencies for the website are installed: 14 | 15 | ```sh 16 | # Install dependencies 17 | $ yarn 18 | ``` 19 | 2. Run your dev server: 20 | 21 | ```sh 22 | # Start the site 23 | $ yarn start 24 | ``` 25 | 26 | ## Directory Structure 27 | 28 | Your project file structure should look something like this 29 | 30 | ``` 31 | my-docusaurus/ 32 | docs/ 33 | doc-1.md 34 | doc-2.md 35 | doc-3.md 36 | website/ 37 | blog/ 38 | 2016-3-11-oldest-post.md 39 | 2017-10-24-newest-post.md 40 | core/ 41 | node_modules/ 42 | pages/ 43 | static/ 44 | css/ 45 | img/ 46 | package.json 47 | sidebar.json 48 | siteConfig.js 49 | ``` 50 | 51 | # Editing Content 52 | 53 | ## Editing an existing docs page 54 | 55 | Edit docs by navigating to `docs/` and editing the corresponding document: 56 | 57 | `docs/doc-to-be-edited.md` 58 | 59 | ```markdown 60 | --- 61 | id: page-needs-edit 62 | title: This Doc Needs To Be Edited 63 | --- 64 | 65 | Edit me... 66 | ``` 67 | 68 | For more information about docs, click [here](https://docusaurus.io/docs/en/navigation) 69 | 70 | ## Editing an existing blog post 71 | 72 | Edit blog posts by navigating to `website/blog` and editing the corresponding post: 73 | 74 | `website/blog/post-to-be-edited.md` 75 | ```markdown 76 | --- 77 | id: post-needs-edit 78 | title: This Blog Post Needs To Be Edited 79 | --- 80 | 81 | Edit me... 82 | ``` 83 | 84 | For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog) 85 | 86 | # Adding Content 87 | 88 | ## Adding a new docs page to an existing sidebar 89 | 90 | 1. Create the doc as a new markdown file in `/docs`, example `docs/newly-created-doc.md`: 91 | 92 | ```md 93 | --- 94 | id: newly-created-doc 95 | title: This Doc Needs To Be Edited 96 | --- 97 | 98 | My new content here.. 99 | ``` 100 | 101 | 1. Refer to that doc's ID in an existing sidebar in `website/sidebar.json`: 102 | 103 | ```javascript 104 | // Add newly-created-doc to the Getting Started category of docs 105 | { 106 | "docs": { 107 | "Getting Started": [ 108 | "quick-start", 109 | "newly-created-doc" // new doc here 110 | ], 111 | ... 112 | }, 113 | ... 114 | } 115 | ``` 116 | 117 | For more information about adding new docs, click [here](https://docusaurus.io/docs/en/navigation) 118 | 119 | ## Adding a new blog post 120 | 121 | 1. Make sure there is a header link to your blog in `website/siteConfig.js`: 122 | 123 | `website/siteConfig.js` 124 | ```javascript 125 | headerLinks: [ 126 | ... 127 | { blog: true, label: 'Blog' }, 128 | ... 129 | ] 130 | ``` 131 | 132 | 2. Create the blog post with the format `YYYY-MM-DD-My-Blog-Post-Title.md` in `website/blog`: 133 | 134 | `website/blog/2018-05-21-New-Blog-Post.md` 135 | 136 | ```markdown 137 | --- 138 | author: Frank Li 139 | authorURL: https://twitter.com/foobarbaz 140 | authorFBID: 503283835 141 | title: New Blog Post 142 | --- 143 | 144 | Lorem Ipsum... 145 | ``` 146 | 147 | For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog) 148 | 149 | ## Adding items to your site's top navigation bar 150 | 151 | 1. Add links to docs, custom pages or external links by editing the headerLinks field of `website/siteConfig.js`: 152 | 153 | `website/siteConfig.js` 154 | ```javascript 155 | { 156 | headerLinks: [ 157 | ... 158 | /* you can add docs */ 159 | { doc: 'my-examples', label: 'Examples' }, 160 | /* you can add custom pages */ 161 | { page: 'help', label: 'Help' }, 162 | /* you can add external links */ 163 | { href: 'https://github.com/facebook/Docusaurus', label: 'GitHub' }, 164 | ... 165 | ], 166 | ... 167 | } 168 | ``` 169 | 170 | For more information about the navigation bar, click [here](https://docusaurus.io/docs/en/navigation) 171 | 172 | ## Adding custom pages 173 | 174 | 1. Docusaurus uses React components to build pages. The components are saved as .js files in `website/pages/en`: 175 | 1. If you want your page to show up in your navigation header, you will need to update `website/siteConfig.js` to add to the `headerLinks` element: 176 | 177 | `website/siteConfig.js` 178 | ```javascript 179 | { 180 | headerLinks: [ 181 | ... 182 | { page: 'my-new-custom-page', label: 'My New Custom Page' }, 183 | ... 184 | ], 185 | ... 186 | } 187 | ``` 188 | 189 | For more information about custom pages, click [here](https://docusaurus.io/docs/en/custom-pages). 190 | 191 | # Full Documentation 192 | 193 | Full documentation can be found on the [website](https://docusaurus.io/). 194 | -------------------------------------------------------------------------------- /website/core/Footer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const React = require('react') 9 | 10 | class Footer extends React.Component { 11 | docUrl(doc, language) { 12 | const baseUrl = this.props.config.baseUrl 13 | const docsUrl = this.props.config.docsUrl 14 | const docsPart = `${docsUrl ? `${docsUrl}/` : ''}` 15 | const langPart = `${language ? `${language}/` : ''}` 16 | return `${baseUrl}${docsPart}${langPart}${doc}` 17 | } 18 | 19 | pageUrl(doc, language) { 20 | const baseUrl = this.props.config.baseUrl 21 | return baseUrl + (language ? `${language}/` : '') + doc 22 | } 23 | 24 | render() { 25 | return ( 26 | 103 | ) 104 | } 105 | } 106 | 107 | module.exports = Footer 108 | -------------------------------------------------------------------------------- /website/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "This file is auto-generated by write-translations.js", 3 | "localized-strings": { 4 | "next": "Next", 5 | "previous": "Previous", 6 | "tagline": "Create Node.js apps based on TypeScript with zero-configuration", 7 | "docs": { 8 | "adding-prettier": { 9 | "title": "Adding Prettier" 10 | }, 11 | "argv-forwarding": { 12 | "title": "Forwarding argv to your App" 13 | }, 14 | "commands": { 15 | "title": "Commands Reference" 16 | }, 17 | "custom-module-path": { 18 | "title": "Custom Module Paths" 19 | }, 20 | "debugging-source": { 21 | "title": "Debugging your Source" 22 | }, 23 | "debugging-webpack": { 24 | "title": "Debugging your Webpack Build" 25 | }, 26 | "deployment": { 27 | "title": "Deploying your App" 28 | }, 29 | "getting-started": { 30 | "title": "Getting Started" 31 | }, 32 | "migrating-v2-to-v3": { 33 | "title": "Migrating from v2 to v3" 34 | }, 35 | "monorepo": { 36 | "title": "Monorepo Support" 37 | }, 38 | "sourcemaps": { 39 | "title": "Source Maps" 40 | }, 41 | "tests": { 42 | "title": "Testing your Application" 43 | }, 44 | "upgrading": { 45 | "title": "Upgrading + Changelog" 46 | }, 47 | "webpack-override": { 48 | "title": "Overriding Webpack Configuration" 49 | } 50 | }, 51 | "links": { 52 | "Docs": "Docs", 53 | "GitHub": "GitHub" 54 | }, 55 | "categories": { 56 | "Quick Start": "Quick Start", 57 | "Guides": "Guides", 58 | "Debugging": "Debugging", 59 | "Advanced": "Advanced", 60 | "Upgrading and Changelog": "Upgrading and Changelog", 61 | "First Category": "First Category" 62 | } 63 | }, 64 | "pages-strings": { 65 | "Help Translate|recruit community translators for your project": "Help Translate", 66 | "Edit this Doc|recruitment message asking to edit the doc source": "Edit", 67 | "Translate this Doc|recruitment message asking to translate the docs": "Translate" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "examples": "docusaurus-examples", 4 | "start": "docusaurus-start", 5 | "build": "docusaurus-build", 6 | "publish-gh-pages": "docusaurus-publish", 7 | "write-translations": "docusaurus-write-translations", 8 | "version": "docusaurus-version", 9 | "rename-version": "docusaurus-rename-version" 10 | }, 11 | "devDependencies": { 12 | "docusaurus": "1.14.6" 13 | }, 14 | "dependencies": {} 15 | } 16 | -------------------------------------------------------------------------------- /website/pages/en/help.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const React = require('react') 9 | 10 | const CompLibrary = require('../../core/CompLibrary.js') 11 | 12 | const Container = CompLibrary.Container 13 | const GridBlock = CompLibrary.GridBlock 14 | 15 | function Help(props) { 16 | const { config: siteConfig, language = '' } = props 17 | const { baseUrl, docsUrl } = siteConfig 18 | const docsPart = `${docsUrl ? `${docsUrl}/` : ''}` 19 | const langPart = `${language ? `${language}/` : ''}` 20 | const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}` 21 | 22 | const supportLinks = [ 23 | { 24 | content: `Learn more using the [documentation on this site.](${docUrl( 25 | 'doc1.html' 26 | )})`, 27 | title: 'Browse Docs', 28 | }, 29 | { 30 | content: 'Ask questions about the documentation and project', 31 | title: 'Join the community', 32 | }, 33 | { 34 | content: "Find out what's new with this project", 35 | title: 'Stay up to date', 36 | }, 37 | ] 38 | 39 | return ( 40 |
41 | 42 |
43 |
44 |

Need help?

45 |
46 |

This project is maintained by a dedicated group of people.

47 | 48 |
49 |
50 |
51 | ) 52 | } 53 | 54 | module.exports = Help 55 | -------------------------------------------------------------------------------- /website/pages/en/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const React = require('react') 9 | 10 | const CompLibrary = require('../../core/CompLibrary.js') 11 | 12 | const MarkdownBlock = CompLibrary.MarkdownBlock /* Used to read markdown */ 13 | const Container = CompLibrary.Container 14 | const GridBlock = CompLibrary.GridBlock 15 | 16 | class HomeSplash extends React.Component { 17 | render() { 18 | const { siteConfig, language = '' } = this.props 19 | const { baseUrl, docsUrl } = siteConfig 20 | const docsPart = `${docsUrl ? `${docsUrl}/` : ''}` 21 | const langPart = `${language ? `${language}/` : ''}` 22 | const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}` 23 | 24 | const SplashContainer = props => ( 25 |
26 |
27 |
{props.children}
28 |
29 |
30 | ) 31 | 32 | const ProjectTitle = () => ( 33 |

34 | {siteConfig.title} 35 | {siteConfig.tagline} 36 |

37 | ) 38 | 39 | const PromoSection = props => ( 40 |
41 |
42 |
{props.children}
43 |
44 |
45 | ) 46 | 47 | const Button = props => ( 48 | 53 | ) 54 | 55 | return ( 56 | 57 |
58 | 59 | 63 | 64 | 65 | 66 | 67 |
68 |
69 | ) 70 | } 71 | } 72 | 73 | class Index extends React.Component { 74 | render() { 75 | const { config: siteConfig, language = '' } = this.props 76 | const { baseUrl } = siteConfig 77 | 78 | const Block = props => ( 79 | 84 | 89 | 90 | ) 91 | 92 | const FeatureCallout = () => ( 93 |
97 |

Create, build, test, and deploy

98 | 99 | {/* TNS makes it easy to create applications with one command, 100 | and provides helpful tools like a development server that incrementally compiles your source code, 101 | making it blazing fast to develop your application. */} 102 | TNS makes it easy to create, build, and test your Node.js applications 103 | with built-in tooling, like a development server that incrementally 104 | compiles your source code and runs your app. 105 | 106 |
107 | ) 108 | 109 | const TryOut = () => ( 110 | 111 | {[ 112 | { 113 | title: 'Try it Out', 114 | content: `Ready to create an app? Run the following command in your terminal: 115 |

116 | \`\`\` 117 | npx typescript-node-scripts create 118 | \`\`\``, 119 | }, 120 | ]} 121 |
122 | ) 123 | 124 | const BuildAndRun = () => ( 125 | 126 | {[ 127 | { 128 | content: 129 | 'TNS provides a development server which compiles your source code incrementally, and then runs your application in the same terminal.', 130 | image: `${baseUrl}img/dev-server.png`, 131 | imageAlign: 'bottom', 132 | title: 'Compile and Run', 133 | }, 134 | ]} 135 | 136 | ) 137 | 138 | const HelpfulErrorMessages = () => ( 139 | 140 | {[ 141 | { 142 | content: 143 | 'TNS outputs a prettified error message along with the source of the error, and silences other errors that cascade from the current error.', 144 | image: `${baseUrl}img/dev-server-error.png`, 145 | imageAlign: 'bottom', 146 | title: 'Distraction-free Error Messages', 147 | }, 148 | ]} 149 | 150 | ) 151 | 152 | const Test = () => ( 153 | 154 | {[ 155 | { 156 | content: 157 | 'Jest ships out of the box. Run your tests and update your snapshots, all in interactive mode. ', 158 | image: `${baseUrl}img/test.png`, 159 | imageAlign: 'bottom', 160 | title: 'Test', 161 | }, 162 | ]} 163 | 164 | ) 165 | 166 | const Build = () => ( 167 | 168 | {[ 169 | { 170 | content: 171 | 'Build a production ready, minified, and optimized bundle with one command', 172 | image: `${baseUrl}img/build.png`, 173 | imageAlign: 'bottom', 174 | title: 'Build', 175 | }, 176 | ]} 177 | 178 | ) 179 | 180 | const Features = () => ( 181 | 182 | {[ 183 | { 184 | content: 'TNS works out of the box, no configuration required', 185 | image: `${baseUrl}img/gear.svg`, 186 | imageAlign: 'top', 187 | title: 'Zero Config', 188 | }, 189 | { 190 | content: 191 | 'TNS supports TypeScript in addition to JavaScript sources', 192 | image: `${baseUrl}img/typescript.png`, 193 | imageAlign: 'top', 194 | title: 'TypeScript + Babel', 195 | }, 196 | { 197 | title: 'Webpack', 198 | content: 199 | 'TNS transforms your source files into a single bundle through Webpack with source maps, which makes it easy to deploy and debug.', 200 | image: `${baseUrl}img/webpack.svg`, 201 | imageAlign: 'top', 202 | }, 203 | ]} 204 | 205 | ) 206 | 207 | // const Showcase = () => { 208 | // if ((siteConfig.users || []).length === 0) { 209 | // return null; 210 | // } 211 | 212 | // const showcase = siteConfig.users 213 | // .filter(user => user.pinned) 214 | // .map(user => ( 215 | // 216 | // {user.caption} 217 | // 218 | // )); 219 | 220 | // const pageUrl = page => baseUrl + (language ? `${language}/` : '') + page; 221 | 222 | // return ( 223 | //
224 | //

Who is Using This?

225 | //

This project is used by all these people

226 | //
{showcase}
227 | // 232 | //
233 | // ); 234 | // }; 235 | 236 | return ( 237 |
238 | 239 |
240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 |
248 |
249 | ) 250 | } 251 | } 252 | 253 | module.exports = Index 254 | -------------------------------------------------------------------------------- /website/pages/en/users.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const React = require('react') 9 | 10 | const CompLibrary = require('../../core/CompLibrary.js') 11 | 12 | const Container = CompLibrary.Container 13 | 14 | class Users extends React.Component { 15 | render() { 16 | const { config: siteConfig } = this.props 17 | if ((siteConfig.users || []).length === 0) { 18 | return null 19 | } 20 | 21 | const editUrl = `${siteConfig.repoUrl}/edit/master/website/siteConfig.js` 22 | const showcase = siteConfig.users.map(user => ( 23 | 24 | {user.caption} 25 | 26 | )) 27 | 28 | return ( 29 |
30 | 31 |
32 |
33 |

Who is Using This?

34 |

This project is used by many folks

35 |
36 |
{showcase}
37 |

Are you using this project?

38 | 39 | Add your company 40 | 41 |
42 |
43 |
44 | ) 45 | } 46 | } 47 | 48 | module.exports = Users 49 | -------------------------------------------------------------------------------- /website/sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs": { 3 | "Quick Start": ["getting-started", "commands"], 4 | "Guides": ["tests", "deployment", "custom-module-path", "sourcemaps", "argv-forwarding", "monorepo", "adding-prettier"], 5 | "Debugging": ["debugging-webpack", "debugging-source"], 6 | "Advanced": ["webpack-override"], 7 | "Upgrading and Changelog": ["upgrading"] 8 | }, 9 | "docs-other": { 10 | "First Category": ["doc4", "doc5"] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /website/siteConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // See https://docusaurus.io/docs/site-config for all the possible 9 | // site configuration options. 10 | 11 | // List of projects/orgs using your project for the users page. 12 | const users = [ 13 | // { 14 | // caption: 'User1', 15 | // // You will need to prepend the image path with your baseUrl 16 | // // if it is not '/', like: '/test-site/img/docusaurus.svg'. 17 | // image: '/img/docusaurus.svg', 18 | // infoLink: 'https://www.facebook.com', 19 | // pinned: true, 20 | // }, 21 | ] 22 | 23 | const siteConfig = { 24 | title: 'typescript-node-scripts', // Title for your website. 25 | tagline: 'Create Node.js apps based on TypeScript with zero-configuration', 26 | url: 'https://liangchunn.github.io/typescript-node-scripts', // Your website URL 27 | baseUrl: '/typescript-node-scripts/', // Base URL for your project */ 28 | // For github.io type URLs, you would set the url and baseUrl like: 29 | // url: 'https://facebook.github.io', 30 | // baseUrl: '/test-site/', 31 | 32 | algolia: { 33 | apiKey: '1d870f4926b03c186f0eeb96ebf9f5ff', 34 | indexName: 'typescript-node-scripts', 35 | }, 36 | 37 | // Used for publishing and more 38 | projectName: 'typescript-node-scripts', 39 | organizationName: 'liangchunn', 40 | // For top-level user or org sites, the organization is still the same. 41 | // e.g., for the https://JoelMarcey.github.io site, it would be set like... 42 | // organizationName: 'JoelMarcey' 43 | 44 | // For no header links in the top nav bar -> headerLinks: [], 45 | headerLinks: [ 46 | { doc: 'getting-started', label: 'Docs' }, 47 | { 48 | href: 'https://github.com/liangchunn/typescript-node-scripts', 49 | label: 'GitHub', 50 | }, 51 | { search: true }, 52 | ], 53 | 54 | // If you have users set above, you add it here: 55 | users, 56 | 57 | /* path to images for header/footer */ 58 | // headerIcon: 'img/docusaurus.svg', 59 | // footerIcon: 'img/docusaurus.svg', 60 | // favicon: 'img/favicon.png', 61 | 62 | /* Colors for website */ 63 | colors: { 64 | primaryColor: '#003153', 65 | secondaryColor: '#005ea0', 66 | }, 67 | 68 | /* Custom fonts for website */ 69 | // fonts: { 70 | // myFont: [ 71 | // "Times New Roman", 72 | // "Serif" 73 | // ], 74 | // myOtherFont: [ 75 | // "-apple-system", 76 | // "system-ui" 77 | // ] 78 | // }, 79 | 80 | // This copyright info is used in /core/Footer.js and blog RSS/Atom feeds. 81 | copyright: `Copyright © ${new Date().getFullYear()} Liang Chun Wong`, 82 | 83 | highlight: { 84 | // Highlight.js theme to use for syntax highlighting in code blocks. 85 | theme: 'default', 86 | }, 87 | 88 | // Add custom scripts here that would be placed in