├── .eslintrc.json ├── .gitignore ├── .husky └── pre-commit ├── .lintstagedrc.json ├── .prettierignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── src ├── index.ts ├── services │ ├── index.ts │ ├── sample-service.spec.ts │ └── sample-service.ts └── types │ ├── index.ts │ └── sample-interface.ts ├── tsconfig.json └── tsconfig.module.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { "project": "./tsconfig.json" }, 5 | "env": { "es6": true }, 6 | "ignorePatterns": ["node_modules", "build", "coverage"], 7 | "plugins": ["import", "eslint-comments"], 8 | "extends": [ 9 | "eslint:recommended", 10 | "plugin:eslint-comments/recommended", 11 | "plugin:@typescript-eslint/recommended", 12 | "plugin:import/typescript", 13 | "prettier" 14 | ], 15 | "globals": { "BigInt": true, "console": true, "WebAssembly": true }, 16 | "rules": { 17 | "@typescript-eslint/explicit-module-boundary-types": "off", 18 | "eslint-comments/disable-enable-pair": [ 19 | "error", 20 | { "allowWholeFile": true } 21 | ], 22 | "eslint-comments/no-unused-disable": "error", 23 | "import/order": [ 24 | "error", 25 | { "newlines-between": "always", "alphabetize": { "order": "asc" } } 26 | ], 27 | "sort-imports": [ 28 | "error", 29 | { "ignoreDeclarationSort": true, "ignoreCase": true } 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | diff 2 | .idea/* 3 | .nyc_output 4 | build 5 | lib 6 | node_modules 7 | test 8 | src/**.js 9 | coverage 10 | *.log 11 | yarn.lock 12 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npm test 5 | npx lint-staged -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "*": "prettier --ignore-unknown --write", 3 | "*.ts": "eslint --fix" 4 | } 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # package.json is formatted by package managers, so we ignore it here 2 | package.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Amel Spahic 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # typescript-library-template 2 | 3 | A starter template for TypeScript libraries. Use this repository as a starting point for your own TypeScript library. This template includes the following features: 4 | 5 | - Compiles TypeScript code using both the `tsconfig.json` and `tsconfig.module.json` files. 6 | - Formats TypeScript code using [Prettier](https://prettier.io). 7 | - Lints TypeScript code using [ESLint](https://eslint.org). 8 | - Runs unit tests using [AVA](https://github.com/avajs/ava). 9 | - Generates code coverage reports using NYC. 10 | - Generates HTML documentation using [TypeDoc](https://typedoc.org). 11 | - Uses [Husky](https://github.com/typicode/husky) Git hooks and [Lint-staged](https://github.com/okonet/lint-staged) pre-commit hooks. 12 | 13 | ## Installation 14 | 15 | Clone the repository: 16 | 17 | ```bash 18 | git clone https://github.com/amelspahic/typescript-library-template.git 19 | ``` 20 | 21 | Install the dependencies: 22 | 23 | ```bash 24 | npm install 25 | ``` 26 | 27 | There are several scripts available to help you get started: 28 | 29 | --- 30 | 31 | Compile the TypeScript code using both the `tsconfig.json` and `tsconfig.module.json` files. 32 | 33 | ```bash 34 | npm run build 35 | ``` 36 | 37 | --- 38 | 39 | Formats the TypeScript code using Prettier and lints the code using ESLint, fixing any issues found. 40 | 41 | ```bash 42 | npm run fix 43 | ``` 44 | 45 | --- 46 | 47 | Lints the TypeScript code using ESLint, checks the code formatting using Prettier, and runs the unit tests using AVA. 48 | 49 | ```bash 50 | npm run test 51 | ``` 52 | 53 | --- 54 | 55 | Watches for changes in the TypeScript code and recompiles the code using `tsconfig.json`. 56 | 57 | ```bash 58 | npm run watch:build 59 | ``` 60 | 61 | --- 62 | 63 | Watches for changes in the TypeScript code and re-runs the unit tests using AVA. 64 | 65 | ```bash 66 | npm run watch:test 67 | ``` 68 | 69 | --- 70 | 71 | Generates an HTML report of the code coverage using NYC and opens the report in the browser. 72 | 73 | ```bash 74 | npm run cov 75 | ``` 76 | 77 | --- 78 | 79 | Generates HTML documentation of the TypeScript code and opens the documentation in the browser. 80 | 81 | ```bash 82 | npm run doc 83 | ``` 84 | 85 | --- 86 | 87 | The template uses [Husky](https://github.com/typicode/husky) and [Lint-staged](https://github.com/okonet/lint-staged) to run pre-commit hooks that ensure your code is formatted, linted, tested, and documented before committing. 88 | 89 | --- 90 | 91 | For more information on available scripts, see the `Scripts` section of the `package.json` file. 92 | 93 | ## Contributing 94 | 95 | To contribute to the project, please follow the guidelines for submitting issues and pull requests. 96 | 97 | ## License 98 | 99 | This project is licensed under the MIT License. 100 | 101 | ## Acknowledgements 102 | 103 | This project uses Prettier, ESLint, AVA, NYC, Husky, Lint-staged, TypeDoc. 104 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-library-template", 3 | "version": "1.0.0", 4 | "description": "Starter template for TypeScript libraries", 5 | "main": "lib/main/index.js", 6 | "typings": "lib/main/index.d.ts", 7 | "module": "lib/module/index.js", 8 | "repository": "https://github.com/amelspahic/typescript-library-template.git", 9 | "author": "Amel Spahic", 10 | "license": "MIT", 11 | "keywords": [ 12 | "typescript", 13 | "library", 14 | "template", 15 | "starter", 16 | "starter-template", 17 | "starter-template-typescript", 18 | "starter-template-typescript-library", 19 | "tests" 20 | ], 21 | "scripts": { 22 | "build": "run-p build:*", 23 | "build:main": "tsc -p tsconfig.json", 24 | "build:module": "tsc -p tsconfig.module.json", 25 | "fix": "run-s fix:*", 26 | "fix:prettier": "prettier \"src/**/*.ts\" --write", 27 | "fix:lint": "eslint src --ext .ts --fix", 28 | "test": "run-s build test:*", 29 | "test:lint": "eslint src --ext .ts", 30 | "test:prettier": "prettier \"src/**/*.ts\" --list-different", 31 | "test:unit": "nyc --silent ava", 32 | "watch:build": "tsc -p tsconfig.json -w", 33 | "watch:test": "nyc --silent ava --watch", 34 | "cov": "run-s build test:unit cov:html cov:lcov && open-cli coverage/index.html", 35 | "cov:html": "nyc report --reporter=html", 36 | "cov:lcov": "nyc report --reporter=lcov", 37 | "cov:send": "run-s cov:lcov && codecov", 38 | "cov:check": "nyc report && nyc check-coverage --lines 100 --functions 100 --branches 100", 39 | "doc": "run-s doc:html && open-cli lib/docs/index.html", 40 | "doc:html": "typedoc src/ --exclude **/*.spec.ts --out lib/docs", 41 | "doc:json": "typedoc src/ --exclude **/*.spec.ts --json lib/docs/typedoc.json", 42 | "prepare": "husky install" 43 | }, 44 | "devDependencies": { 45 | "@ava/typescript": "^3.0.1", 46 | "@istanbuljs/nyc-config-typescript": "^1.0.2", 47 | "@typescript-eslint/eslint-plugin": "^5.51.0", 48 | "@typescript-eslint/parser": "^5.51.0", 49 | "ava": "^5.2.0", 50 | "codecov": "^3.8.3", 51 | "eslint": "^8.34.0", 52 | "eslint-config-prettier": "^8.5.0", 53 | "eslint-plugin-eslint-comments": "^3.2.0", 54 | "eslint-plugin-import": "^2.26.0", 55 | "husky": "^8.0.3", 56 | "lint-staged": "^13.1.2", 57 | "npm-run-all": "^4.1.5", 58 | "nyc": "^15.1.0", 59 | "open-cli": "^7.0.1", 60 | "prettier": "^2.8.4", 61 | "ts-node": "^10.9.1", 62 | "typedoc": "^0.23.10", 63 | "typescript": "^4.9.5" 64 | }, 65 | "files": [ 66 | "lib/main", 67 | "lib/module", 68 | "!**/*.spec.*", 69 | "!**/*.json", 70 | "CHANGELOG.md", 71 | "LICENSE", 72 | "README.md" 73 | ], 74 | "ava": { 75 | "failFast": true, 76 | "timeout": "60s", 77 | "typescript": { 78 | "rewritePaths": { 79 | "src/": "lib/main/" 80 | }, 81 | "compile": false 82 | }, 83 | "files": [ 84 | "!lib/module/**" 85 | ] 86 | }, 87 | "prettier": { 88 | "singleQuote": true 89 | }, 90 | "nyc": { 91 | "extends": "@istanbuljs/nyc-config-typescript", 92 | "exclude": [ 93 | "**/*.spec.js" 94 | ] 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types'; 2 | export * from './services'; 3 | -------------------------------------------------------------------------------- /src/services/index.ts: -------------------------------------------------------------------------------- 1 | export { SampleService } from './sample-service'; 2 | -------------------------------------------------------------------------------- /src/services/sample-service.spec.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | 3 | import { SampleService } from './sample-service'; 4 | 5 | test('sampleMethod', async (t) => { 6 | // Arrange 7 | const sampleService = new SampleService(); 8 | const input = { 9 | number1: 1, 10 | number2: 2, 11 | }; 12 | 13 | // Act 14 | const result = await sampleService.sampleMethod(input); 15 | 16 | // Assert 17 | t.deepEqual(result, 3); 18 | }); 19 | -------------------------------------------------------------------------------- /src/services/sample-service.ts: -------------------------------------------------------------------------------- 1 | import { SampleInterface } from '../types'; 2 | 3 | export class SampleService { 4 | /** 5 | * Adds two numbers 6 | * 7 | * ### Example (es module) 8 | * ```js 9 | * import { SampleService } from 'typescript-library-template'; 10 | * 11 | * async function add() { 12 | * const sampleService = new SampleService(); 13 | * const res = await sampleService.sampleMethod({ 14 | * number1: 1, 15 | * number2: 2, 16 | * }); 17 | * console.log(res); 18 | * } 19 | * ``` 20 | * 21 | * ### Example (commonjs) 22 | * ```js 23 | * const { SampleService } = require('typescript-library-template'); 24 | * 25 | * async function add() { 26 | * const sampleService = new SampleService(); 27 | * const res = await sampleService.sampleMethod({ 28 | * number1: 1, 29 | * number2: 2, 30 | * }); 31 | * console.log(res); 32 | * } 33 | * ``` 34 | */ 35 | async sampleMethod(numbers: SampleInterface): Promise { 36 | return numbers.number1 + numbers.number2; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sample-interface'; 2 | -------------------------------------------------------------------------------- /src/types/sample-interface.ts: -------------------------------------------------------------------------------- 1 | export interface SampleInterface { 2 | /** 3 | * Sample number 4 | */ 5 | number1: number; 6 | 7 | /** 8 | * Sample number 9 | */ 10 | number2: number; 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "incremental": true, 4 | "target": "es2017", 5 | "outDir": "lib/main", 6 | "rootDir": "src", 7 | "moduleResolution": "node", 8 | "module": "commonjs", 9 | "declaration": true, 10 | "inlineSourceMap": true, 11 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, 12 | "resolveJsonModule": true /* Include modules imported with .json extension. */, 13 | 14 | "strict": true /* Enable all strict type-checking options. */, 15 | 16 | /* Strict Type-Checking Options */ 17 | // "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, 18 | // "strictNullChecks": true /* Enable strict null checks. */, 19 | // "strictFunctionTypes": true /* Enable strict checking of function types. */, 20 | // "strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */, 21 | // "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */, 22 | // "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */, 23 | 24 | /* Additional Checks */ 25 | "noUnusedLocals": true /* Report errors on unused locals. */, 26 | "noUnusedParameters": true /* Report errors on unused parameters. */, 27 | "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, 28 | "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */, 29 | 30 | /* Debugging Options */ 31 | "traceResolution": false /* Report module resolution log messages. */, 32 | "listEmittedFiles": false /* Print names of generated files part of the compilation. */, 33 | "listFiles": false /* Print names of files part of the compilation. */, 34 | "pretty": true /* Stylize errors and messages using color and context. */, 35 | 36 | /* Experimental Options */ 37 | // "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, 38 | // "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, 39 | 40 | "lib": ["es2017"], 41 | "types": ["node"], 42 | "typeRoots": ["node_modules/@types", "src/types"] 43 | }, 44 | "include": ["src/**/*.ts"], 45 | "exclude": ["node_modules/**"], 46 | "compileOnSave": false 47 | } 48 | -------------------------------------------------------------------------------- /tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "outDir": "lib/module", 6 | "module": "esnext" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | --------------------------------------------------------------------------------