├── .gitignore ├── tslint.json ├── src ├── foo │ ├── foo.ts │ └── foo.test.ts └── index.ts ├── .vscode ├── settings.json ├── tasks.json └── launch.json ├── .editorconfig ├── tsconfig.json ├── Dockerfile ├── LICENSE ├── .all-contributorsrc ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint-config-acamica" 3 | } 4 | 5 | -------------------------------------------------------------------------------- /src/foo/foo.ts: -------------------------------------------------------------------------------- 1 | export function add (a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "tslint.autoFixOnSave": true, 4 | "tslint.run": "onType" 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | insert_final_newline = true 9 | charset = utf-8 10 | -------------------------------------------------------------------------------- /src/foo/foo.test.ts: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | import 'mocha'; 3 | import { add } from './foo'; 4 | 5 | describe('add:', () => { 6 | it('add(1 + 1) = 2', () => { 7 | assert.deepEqual(add(1, 1), 2); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2015", 5 | "outDir": "dist", 6 | "strict": true, 7 | "noUnusedLocals": false, 8 | "sourceMap": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:6.10.2-alpine 2 | 3 | # First copy the yarn.lock to install stuff and benefit from the layer cache 4 | COPY ["package.json", "package-lock.json", "/usr/src/"] 5 | 6 | # Run all the code from here 7 | WORKDIR /usr/src 8 | 9 | # Install dependencies 10 | RUN npm install 11 | 12 | # Copy the code 13 | COPY [".", "/usr/src/"] 14 | 15 | # Build the project 16 | RUN npm run -q build 17 | 18 | # Tell docker what to run as default 19 | CMD ["npm", "start", "-s"] 20 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { readFile } from 'fs'; 2 | import * as os from 'os'; 3 | import { add } from './foo/foo'; 4 | 5 | readFile('./package.json', (err, packageStr) => { 6 | if (err) { 7 | console.error('There was a problem reading package json', err); 8 | return; 9 | } 10 | 11 | const json = JSON.parse(packageStr.toString()); 12 | 13 | console.log(`Running typescript-node-starter version ${json.version}`); 14 | console.info(`Running on ${os.hostname()} with ${os.cpus().length} CPU's and ${os.totalmem()} mem`); 15 | console.info(`1 + 1 = ${add(1, 1)}`); 16 | }); 17 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "command": "npm", 6 | "isShellCommand": true, 7 | "showOutput": "always", 8 | "suppressTaskName": true, 9 | "tasks": [ 10 | { 11 | "taskName": "install", 12 | "args": ["install"] 13 | }, 14 | { 15 | "taskName": "update", 16 | "args": ["update"] 17 | }, 18 | { 19 | "taskName": "build", 20 | "args": ["run", "build"], 21 | "showOutput": "silent", 22 | "problemMatcher": "$tsc" 23 | }, 24 | { 25 | "taskName": "docker-build", 26 | "args": ["run", "docker:build"] 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2017 Acamica 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "typescript-node-starter", 3 | "projectOwner": "acamica", 4 | "files": [ 5 | "README.md" 6 | ], 7 | "imageSize": 100, 8 | "commit": true, 9 | "contributors": [ 10 | { 11 | "login": "hrajchert", 12 | "name": "Hernan Rajchert", 13 | "avatar_url": "https://avatars0.githubusercontent.com/u/2634059?v=4", 14 | "profile": "https://github.com/hrajchert", 15 | "contributions": [ 16 | "code", 17 | "doc", 18 | "bug" 19 | ] 20 | }, 21 | { 22 | "login": "facurubin", 23 | "name": "Facundo Rubin", 24 | "avatar_url": "https://avatars2.githubusercontent.com/u/824445?v=4", 25 | "profile": "https://github.com/facurubin", 26 | "contributions": [ 27 | "code", 28 | "doc", 29 | "bug" 30 | ] 31 | }, 32 | { 33 | "login": "durancristhian", 34 | "name": "Cristhian Duran", 35 | "avatar_url": "https://avatars0.githubusercontent.com/u/4248944?v=4", 36 | "profile": "https://durancristhian.github.io/", 37 | "contributions": [ 38 | "bug" 39 | ] 40 | }, 41 | { 42 | "login": "nhsz", 43 | "name": "Nicolás Quiroz", 44 | "avatar_url": "https://avatars0.githubusercontent.com/u/948922?v=4", 45 | "profile": "https://nicolasquiroz.com", 46 | "contributions": [ 47 | "code", 48 | "doc" 49 | ] 50 | }, 51 | { 52 | "login": "dggluz", 53 | "name": "Gonzalo Gluzman", 54 | "avatar_url": "https://avatars1.githubusercontent.com/u/1573956?v=4", 55 | "profile": "https://github.com/dggluz", 56 | "contributions": [ 57 | "code" 58 | ] 59 | } 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-node-starter", 3 | "version": "0.0.4", 4 | "description": "Bare bones project with all that you need to start a node app", 5 | "main": "dist/index.js", 6 | "author": "Hernan Rajchert ", 7 | "license": "MIT", 8 | "scripts": { 9 | "start": "tsns run", 10 | "test": "run-s build-and:test", 11 | "tdd": "run-p watch:*", 12 | "build": "tsns build", 13 | "docker:build": "docker build -t ${npm_package_name}:${npm_package_version} .", 14 | "docker:run": "docker run --rm ${npm_package_name}:${npm_package_version}", 15 | "commitmsg": "validate-commit-msg", 16 | "precommit": "run-s lint:* build", 17 | "prepush": "run-s build-and:test", 18 | "postinstall": "npm run -s build && tsns init", 19 | "lint:ts": "tslint --project tsconfig.json", 20 | "lint-and-fix:-ts": "tslint --project tsconfig.json --fix", 21 | "build-and:test": "run-s build test-once", 22 | "build-and:start": "run-s build start", 23 | "watch:ts": "tsc -w", 24 | "watch:test": "mocha dist/**/*.test.js -w --colors --inspect --growl", 25 | "test-once": "mocha dist/**/*.test.js --inspect --colors", 26 | "contributors-add": "all-contributors add", 27 | "contributors-generate": "all-contributors generate" 28 | }, 29 | "dependencies": { 30 | "tsns": "0.0.18", 31 | "typescript": "3.6.4" 32 | }, 33 | "devDependencies": { 34 | "@types/chai": "4.1.4", 35 | "@types/mocha": "5.2.5", 36 | "@types/node": "^12.12.5", 37 | "all-contributors-cli": "^6.4.0", 38 | "chai": "4.1.2", 39 | "husky": "0.14.3", 40 | "mocha": "5.2.0", 41 | "npm-run-all": "4.1.3", 42 | "sinon": "6.1.5", 43 | "tslint": "5.11.0", 44 | "tslint-config-acamica": "2.0.0", 45 | "validate-commit-msg": "2.14.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible Node.js debug attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | 8 | { 9 | "type": "node", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | "name": "Run tests", 13 | "outFiles": ["${workspaceRoot}/dist/**/*.js"], 14 | "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", 15 | "args": [ 16 | "-u", 17 | "tdd", 18 | "--timeout", 19 | "999999", 20 | "--colors", 21 | "${workspaceRoot}/dist/**/*.test.js" 22 | ], 23 | "sourceMaps": true, 24 | "internalConsoleOptions": "openOnSessionStart" 25 | }, 26 | { 27 | "type": "node", 28 | "request": "launch", 29 | "preLaunchTask": "build", 30 | "name": "Launch Program", 31 | "outFiles": ["${workspaceRoot}/dist/**/*.js"], 32 | "program": "${workspaceRoot}/dist/index.js", 33 | "sourceMaps": true 34 | }, 35 | { 36 | "type": "node", 37 | "request": "launch", 38 | "name": "Build and Launch Docker", 39 | "preLaunchTask": "docker-build", 40 | "runtimeExecutable": "npm", 41 | "windows": { 42 | "runtimeExecutable": "npm.cmd" 43 | }, 44 | "runtimeArgs": [ 45 | "run-script", 46 | "docker:run", 47 | "-s" 48 | ], 49 | "port": 5858 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TypeScript Node App Starter 2 | [![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors) 3 | =========================== 4 | 5 | Create bare bones NodeJS apps using TypeScript 🎉 6 | 7 | Quick Start: 8 | ------------ 9 | 10 | ### Clone, cd and Install 11 | 12 | ```bash 13 | $ git clone https://github.com/acamica/typescript-node-starter.git myapp 14 | $ cd myapp 15 | # Install and follow the questions. 16 | $ npm install 17 | ``` 18 | ℹ️ Remember to replace `myapp` with your application name 19 | 20 | ℹ️ You can use yarn or npm. 21 | 22 | ### Edit and Run 23 | Write your program using `src/index.ts` as the entry point, and run it. 24 | 25 | ```bash 26 | $ npm run start 27 | ``` 28 | 29 | Features 30 | -------- 31 | * 🛡 TypeScript configuration 32 | * 🛡 Unit testing and tdd/bdd workflow 33 | * ☁️ Homogeneous environment using [Docker](https://www.docker.com/) 🐳 34 | * 👮 TSlint before commit 35 | * 👮 Git [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog/blob/v0.5.3/conventions/angular.md) messages validation 36 | * 🔐 Reliable package management using package.locks 37 | * 🎉 Visual Studio Code goodies 38 | * 📝 [Editor config](http://editorconfig.org/) for editors that supports it 39 | 40 | ### 🛡 TypeScript Configuration 41 | The project comes with TypeScript v2.3 already configured. You can see and tweak the compiler options with the [tsconfig.json](https://www.typescriptlang.org/docs/handbook/compiler-options.html) file. 42 | 43 | By default, the [strict master option](https://github.com/Microsoft/TypeScript/pull/14486) and `noUnusedLocals` are enabled, if you are new to typescript you may want to lay back on the strictness by disabling it, and as you get more accustomed you can enable it again. 44 | 45 | 👮 Your files should follow the conventions set in `tslint.json` in order to make a `git commit`. 46 | 47 | ### 🛡 Unit Testing & TDD 48 | 49 | Both your code and your test files are in TypeScript. This way if a test fails it's easier to see if its due to a change in the contract or an actual bug. 50 | 51 | The project comes with these tools already configured: 52 | 53 | * [Mocha](https://mochajs.org/): is the test framework that knows how to run your tests. 54 | * [Chai](http://chaijs.com/api/): is an assertion library with different flavours of API. 55 | * [Sinon](http://sinonjs.org/): is a library that helps `spying` on functions to see if they where called and how, and creating mocks and stubs for simulating API's. 56 | 57 | 👮 All the test need to pass in order to make a `git push`. 58 | 59 | #### Why mocha + chai + sinon: 60 | * ✅ It's been proven over and over / Well known in the community. 61 | * ✅ Decoupled test runner from the assertion and or mock library. 62 | * 🚫 By default it runs all the test sequentially (so it may be slower than others) 63 | 64 | #### How to Use: 65 | 66 | Create a test file next to the file you want to test, using the nomenclature `.test.ts`. 67 | 68 | You can run your test in a single run by doing: 69 | 70 | ```bash 71 | $ npm t 72 | # or 73 | # npm run test 74 | ``` 75 | 76 | Or you can enter in a `Test Driven Development` mode, so whenever you change a file it gets compiled and the test are executed. 77 | 78 | ```bash 79 | $ npm run tdd 80 | ``` 81 | 82 | 🌟 You can install a terminal notifier to receive growl messages with the test execution results. 83 | 84 | ```bash 85 | # How to install growl messages on your platform 86 | # Mac OS X (Darwin): 87 | $ sudo gem install terminal-notifier 88 | 89 | # Ubuntu (Linux): 90 | $ sudo apt-get install libnotify-bin 91 | ``` 92 | 93 | #### How to Remove: 94 | 95 | ```bash 96 | $ npm remove -D mocha @types/mocha chai @types/chai sinon 97 | ``` 98 | 99 | In the `package.json` remove the scripts "test", "watch:test" and "tdd" and if no other script uses it, remove `npm-run-all` as a dependency. 100 | 101 | ### 🐳 Docker 102 | 103 | If the node app you are trying to build is intended to be a service of some sort (micro or monolithic) you may want to guarantee that it runs in reliable environment. Using Docker we can specify the version of `os`, `node` and others to reduce the difference between dev, prod and ci environments. 104 | 105 | If you want to learn more about Docker you can try [this course (in spanish)](https://www.acamica.com/cursos/128/introduccion-a-docker). To remove docker from the project just delete the `Dockerfile`. 106 | 107 | You can build your docker images using the command 108 | 109 | ```bash 110 | $ npm run docker:build 111 | ``` 112 | 113 | The images created by the build will be tagged with the name and version of your project as specified in the package.json. You can run the image using docker directly or you can run it as an `npm script`. 114 | 115 | ```bash 116 | $ npm run docker:run 117 | ``` 118 | 119 | If you need to modify the way your image is built, runned or published, you can edit the `docker:*` scripts 120 | located in the package.json. 121 | 122 | Notice that the `Dockerfile` takes advantage of the `layers cache`, if you modify the code in the `src` folder it won't run `npm install`, it will only build the typescript code. If you change the `package.json` it will install deps and then build. 123 | 124 | ### 🎉 Visual Studio Code Goodies 125 | 126 | If you are using [Visual Studio Code](https://code.visualstudio.com/) you have some things pre-configured under the `.vscode` folder: 127 | 128 | * You can [run or debug your *tests*](https://code.visualstudio.com/docs/editor/debugging) by selecting the `Run tests` [launch configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations). 129 | * You can [run or debug your *program*](https://code.visualstudio.com/docs/editor/debugging) by selecting the `Launch Program` [launch configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations). 130 | * You can replay the run by pressing F5. 131 | * When editing typescript files you get `fix lint on save`. 132 | * You can build the project by doing `⌘⇧B`. 133 | * Build and tag a docker image using the `docker-build` [task](https://code.visualstudio.com/docs/editor/tasks). 134 | * Build, tag and run a docker image using the `Build and Launch Docker` [launch configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations). 135 | 136 | TODO: 137 | ----- 138 | * Add package deps upgrade tool 139 | * Add automatic Changelog 140 | * Add automatic semver 141 | * Add CI 142 | * Add doc generation 143 | * Add testing coverage 144 | * Add readme badges 145 | * Improve docker integration to build faster 146 | * Improve tdd watch mode 147 | * Maybe: Create branch with FRP using rx and ramda 148 | * Maybe: Create branch with express and knex 149 | * Maybe: Create branch with CLI using commander or similar 150 | * Add a gif of growl messages 151 | * See if we can add a way to create test in a `test` directory as well. 152 | * Video of tdd with zen mode 153 | * add reference for an english course on docker 154 | * Implement docker:push 155 | 156 | ## Contributors 157 | 158 | Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)): 159 | 160 | 161 | | [
Hernan Rajchert](https://github.com/hrajchert)
[💻](https://github.com/acamica/typescript-node-starter/commits?author=hrajchert "Code") [📖](https://github.com/acamica/typescript-node-starter/commits?author=hrajchert "Documentation") [🐛](https://github.com/acamica/typescript-node-starter/issues?q=author%3Ahrajchert "Bug reports") | [
Facundo Rubin](https://github.com/facurubin)
[💻](https://github.com/acamica/typescript-node-starter/commits?author=facurubin "Code") [📖](https://github.com/acamica/typescript-node-starter/commits?author=facurubin "Documentation") [🐛](https://github.com/acamica/typescript-node-starter/issues?q=author%3Afacurubin "Bug reports") | [
Cristhian Duran](https://durancristhian.github.io/)
[🐛](https://github.com/acamica/typescript-node-starter/issues?q=author%3Adurancristhian "Bug reports") | [
Nicolás Quiroz](https://nicolasquiroz.com)
[💻](https://github.com/acamica/typescript-node-starter/commits?author=nhsz "Code") [📖](https://github.com/acamica/typescript-node-starter/commits?author=nhsz "Documentation") | [
Gonzalo Gluzman](https://github.com/dggluz)
[💻](https://github.com/acamica/typescript-node-starter/commits?author=dggluz "Code") | 162 | | :---: | :---: | :---: | :---: | :---: | 163 | 164 | 165 | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! 166 | 167 | ## License 168 | 169 | MIT 170 | --------------------------------------------------------------------------------