├── .dockerignore ├── .editorconfig ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── biome.json ├── package-lock.json ├── package.json ├── scripts └── update-package-tsconfig.ts ├── services └── service-template │ ├── package.json │ ├── src │ └── index.ts │ ├── test │ └── service-template.test.ts │ └── tsconfig.package.json ├── shared └── shared-template │ ├── package.json │ ├── src │ └── index.ts │ ├── test │ └── shared-template.test.ts │ └── tsconfig.package.json ├── tsconfig.base.json ├── tsconfig.json └── tsconfig.project.json /.dockerignore: -------------------------------------------------------------------------------- 1 | .docker 2 | .git 3 | 4 | node_modules 5 | 6 | scripts 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | indent_style = space 7 | indent_size = 4 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.{yaml,yml}] 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Diagnostic reports (https://nodejs.org/api/report.html) 7 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 8 | 9 | # Dependency directories 10 | node_modules/ 11 | 12 | # TypeScript cache 13 | *.tsbuildinfo 14 | 15 | # dotenv environment variables file 16 | .env 17 | .env.test 18 | 19 | # Build 20 | services/*/lib 21 | shared/*/lib 22 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:22.14.0-bookworm-slim 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y --no-install-recommends\ 5 | git \ 6 | && rm -rf /var/lib/apt/lists/* 7 | 8 | WORKDIR /app 9 | 10 | COPY ["package.json", "package-lock.json", "./"] 11 | 12 | # Shared 13 | COPY shared/shared-template/package.json shared/shared-template/ 14 | 15 | # Services 16 | COPY services/service-template/package.json services/service-template/ 17 | 18 | RUN npm ci 19 | 20 | COPY . . 21 | 22 | RUN npm run build 23 | 24 | # Use docker compose "command" instead of "CMD" here 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2024 Negezor 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 Monorepo Boilerplate 2 | > Pure ESM monorepo using native TypeScript compiler instead of external bundlers 🌟 3 | 4 | ### Requirements 5 | > **[Node.js](https://nodejs.org/) 22.2.0 or newer is required** 6 | 7 | > **[NPM](http://npm.im/npm) 10.8.0 or newer is required** 8 | 9 | ### Initialization 10 | ``` 11 | git clone https://github.com/negezor/typescript-monorepo-boilerplate.git 12 | cd typescript-monorepo-boilerplate 13 | npm install 14 | npm run build 15 | ``` 16 | 17 | ### Configuration 18 | #### Change namespace name 19 | - In `tsconfig.json`, change the `paths` from `@template` to the one you need 20 | - Change the namespace in the `name` property of the` package.json` file of each module 21 | 22 | #### Add or remove packages folder 23 | - In `package.json`, change `workspaces` and path in scripts `lint:biome` & `typescript:clean` 24 | - In `tsconfig.json`, change the `paths` 25 | - In `.gitignore`, change the `# Build` place 26 | - Run `npm run update:tsconfig` for update tsconfig references 27 | 28 | ### Add new package 29 | - Copy template structure 30 | - Run `npm run update:tsconfig` for update tsconfig references 31 | - Run `npm install` for create new symlinks in node_modules 32 | 33 | ### Add internal dependency 34 | - Add to `package.json` dependency in `peerDependencies` 35 | - Run `npm run update:tsconfig` for update tsconfig references 36 | 37 | ### Scripts 38 | 39 | `npm run build` 40 | - Starts the build of all packages in monorepo 41 | 42 | `npm run watch` 43 | - Waits for changes in each package and performs build. Used for development. 44 | 45 | `npm run test` 46 | - Runs tests for packages 47 | 48 | `npm run lint` 49 | - Checks the code with the biome.js linter 50 | 51 | `npm run fmt` 52 | - Formats source code using biome.js 53 | 54 | `npm run clean` 55 | - Cleans the entire TypeScript build cache 56 | 57 | `npm run build --workspaces` 58 | - Run build in all packages. [More info](https://docs.npmjs.com/cli/v8/using-npm/workspaces) 59 | 60 | `npm run build --workspace=name` 61 | - Run build in specific package. [More info](https://docs.npmjs.com/cli/v8/using-npm/workspaces) 62 | 63 | ### FAQ 64 | 65 | #### Why not take Rollup/Esbuild/SWC? 66 | 67 | Because they are external dependencies, yes of course they can faster than the typescript compiler for a build. But we will still check types and it is trivially easier. It's worth noting that now we use tsx which depends on esbuild (will be replaced later with a simpler solution). 68 | 69 | #### Why Biome.js and not Eslint? 70 | 71 | It's very simple, eslint is very slow. Usually the rules that we often need are already available in Biome.js, and those that are not are probably will implemented in the next version. It is also worth noting that eslint pulls a lot of small dependencies, while Biome.js is 1 binary file for your platform, which is much faster when installing and updating dependencies. Also it provides a formatter out of the box, we don't need to install prettier separately. 72 | 73 | #### Why not Jest/Mocha? 74 | 75 | Because these are external dependencies, and `node:test` is available out of the box, plus it's faster. The only thing that may be missing is simpler expect comparison, but you can put a smaller module for that separately. 76 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", 3 | "formatter": { 4 | "indentStyle": "space", 5 | "indentWidth": 4, 6 | "lineWidth": 120, 7 | "lineEnding": "lf" 8 | }, 9 | "javascript": { 10 | "formatter": { 11 | "quoteStyle": "single", 12 | "semicolons": "always", 13 | "arrowParentheses": "asNeeded" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-monorepo-boilerplate", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "workspaces": [ 8 | "services/*", 9 | "shared/*" 10 | ], 11 | "devDependencies": { 12 | "@biomejs/biome": "^1.9.4", 13 | "@types/node": "^22.13.4", 14 | "tsx": "^4.19.2", 15 | "typescript": "^5.7.3" 16 | } 17 | }, 18 | "node_modules/@biomejs/biome": { 19 | "version": "1.9.4", 20 | "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz", 21 | "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", 22 | "dev": true, 23 | "hasInstallScript": true, 24 | "license": "MIT OR Apache-2.0", 25 | "bin": { 26 | "biome": "bin/biome" 27 | }, 28 | "engines": { 29 | "node": ">=14.21.3" 30 | }, 31 | "funding": { 32 | "type": "opencollective", 33 | "url": "https://opencollective.com/biome" 34 | }, 35 | "optionalDependencies": { 36 | "@biomejs/cli-darwin-arm64": "1.9.4", 37 | "@biomejs/cli-darwin-x64": "1.9.4", 38 | "@biomejs/cli-linux-arm64": "1.9.4", 39 | "@biomejs/cli-linux-arm64-musl": "1.9.4", 40 | "@biomejs/cli-linux-x64": "1.9.4", 41 | "@biomejs/cli-linux-x64-musl": "1.9.4", 42 | "@biomejs/cli-win32-arm64": "1.9.4", 43 | "@biomejs/cli-win32-x64": "1.9.4" 44 | } 45 | }, 46 | "node_modules/@biomejs/cli-darwin-arm64": { 47 | "version": "1.9.4", 48 | "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz", 49 | "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==", 50 | "cpu": [ 51 | "arm64" 52 | ], 53 | "dev": true, 54 | "license": "MIT OR Apache-2.0", 55 | "optional": true, 56 | "os": [ 57 | "darwin" 58 | ], 59 | "engines": { 60 | "node": ">=14.21.3" 61 | } 62 | }, 63 | "node_modules/@biomejs/cli-darwin-x64": { 64 | "version": "1.9.4", 65 | "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz", 66 | "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==", 67 | "cpu": [ 68 | "x64" 69 | ], 70 | "dev": true, 71 | "license": "MIT OR Apache-2.0", 72 | "optional": true, 73 | "os": [ 74 | "darwin" 75 | ], 76 | "engines": { 77 | "node": ">=14.21.3" 78 | } 79 | }, 80 | "node_modules/@biomejs/cli-linux-arm64": { 81 | "version": "1.9.4", 82 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz", 83 | "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==", 84 | "cpu": [ 85 | "arm64" 86 | ], 87 | "dev": true, 88 | "license": "MIT OR Apache-2.0", 89 | "optional": true, 90 | "os": [ 91 | "linux" 92 | ], 93 | "engines": { 94 | "node": ">=14.21.3" 95 | } 96 | }, 97 | "node_modules/@biomejs/cli-linux-arm64-musl": { 98 | "version": "1.9.4", 99 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz", 100 | "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==", 101 | "cpu": [ 102 | "arm64" 103 | ], 104 | "dev": true, 105 | "license": "MIT OR Apache-2.0", 106 | "optional": true, 107 | "os": [ 108 | "linux" 109 | ], 110 | "engines": { 111 | "node": ">=14.21.3" 112 | } 113 | }, 114 | "node_modules/@biomejs/cli-linux-x64": { 115 | "version": "1.9.4", 116 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz", 117 | "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==", 118 | "cpu": [ 119 | "x64" 120 | ], 121 | "dev": true, 122 | "license": "MIT OR Apache-2.0", 123 | "optional": true, 124 | "os": [ 125 | "linux" 126 | ], 127 | "engines": { 128 | "node": ">=14.21.3" 129 | } 130 | }, 131 | "node_modules/@biomejs/cli-linux-x64-musl": { 132 | "version": "1.9.4", 133 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz", 134 | "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==", 135 | "cpu": [ 136 | "x64" 137 | ], 138 | "dev": true, 139 | "license": "MIT OR Apache-2.0", 140 | "optional": true, 141 | "os": [ 142 | "linux" 143 | ], 144 | "engines": { 145 | "node": ">=14.21.3" 146 | } 147 | }, 148 | "node_modules/@biomejs/cli-win32-arm64": { 149 | "version": "1.9.4", 150 | "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz", 151 | "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==", 152 | "cpu": [ 153 | "arm64" 154 | ], 155 | "dev": true, 156 | "license": "MIT OR Apache-2.0", 157 | "optional": true, 158 | "os": [ 159 | "win32" 160 | ], 161 | "engines": { 162 | "node": ">=14.21.3" 163 | } 164 | }, 165 | "node_modules/@biomejs/cli-win32-x64": { 166 | "version": "1.9.4", 167 | "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz", 168 | "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==", 169 | "cpu": [ 170 | "x64" 171 | ], 172 | "dev": true, 173 | "license": "MIT OR Apache-2.0", 174 | "optional": true, 175 | "os": [ 176 | "win32" 177 | ], 178 | "engines": { 179 | "node": ">=14.21.3" 180 | } 181 | }, 182 | "node_modules/@esbuild/aix-ppc64": { 183 | "version": "0.23.1", 184 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", 185 | "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", 186 | "cpu": [ 187 | "ppc64" 188 | ], 189 | "dev": true, 190 | "license": "MIT", 191 | "optional": true, 192 | "os": [ 193 | "aix" 194 | ], 195 | "engines": { 196 | "node": ">=18" 197 | } 198 | }, 199 | "node_modules/@esbuild/android-arm": { 200 | "version": "0.23.1", 201 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", 202 | "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", 203 | "cpu": [ 204 | "arm" 205 | ], 206 | "dev": true, 207 | "license": "MIT", 208 | "optional": true, 209 | "os": [ 210 | "android" 211 | ], 212 | "engines": { 213 | "node": ">=18" 214 | } 215 | }, 216 | "node_modules/@esbuild/android-arm64": { 217 | "version": "0.23.1", 218 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", 219 | "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", 220 | "cpu": [ 221 | "arm64" 222 | ], 223 | "dev": true, 224 | "license": "MIT", 225 | "optional": true, 226 | "os": [ 227 | "android" 228 | ], 229 | "engines": { 230 | "node": ">=18" 231 | } 232 | }, 233 | "node_modules/@esbuild/android-x64": { 234 | "version": "0.23.1", 235 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", 236 | "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", 237 | "cpu": [ 238 | "x64" 239 | ], 240 | "dev": true, 241 | "license": "MIT", 242 | "optional": true, 243 | "os": [ 244 | "android" 245 | ], 246 | "engines": { 247 | "node": ">=18" 248 | } 249 | }, 250 | "node_modules/@esbuild/darwin-arm64": { 251 | "version": "0.23.1", 252 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", 253 | "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", 254 | "cpu": [ 255 | "arm64" 256 | ], 257 | "dev": true, 258 | "license": "MIT", 259 | "optional": true, 260 | "os": [ 261 | "darwin" 262 | ], 263 | "engines": { 264 | "node": ">=18" 265 | } 266 | }, 267 | "node_modules/@esbuild/darwin-x64": { 268 | "version": "0.23.1", 269 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", 270 | "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", 271 | "cpu": [ 272 | "x64" 273 | ], 274 | "dev": true, 275 | "license": "MIT", 276 | "optional": true, 277 | "os": [ 278 | "darwin" 279 | ], 280 | "engines": { 281 | "node": ">=18" 282 | } 283 | }, 284 | "node_modules/@esbuild/freebsd-arm64": { 285 | "version": "0.23.1", 286 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", 287 | "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", 288 | "cpu": [ 289 | "arm64" 290 | ], 291 | "dev": true, 292 | "license": "MIT", 293 | "optional": true, 294 | "os": [ 295 | "freebsd" 296 | ], 297 | "engines": { 298 | "node": ">=18" 299 | } 300 | }, 301 | "node_modules/@esbuild/freebsd-x64": { 302 | "version": "0.23.1", 303 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", 304 | "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", 305 | "cpu": [ 306 | "x64" 307 | ], 308 | "dev": true, 309 | "license": "MIT", 310 | "optional": true, 311 | "os": [ 312 | "freebsd" 313 | ], 314 | "engines": { 315 | "node": ">=18" 316 | } 317 | }, 318 | "node_modules/@esbuild/linux-arm": { 319 | "version": "0.23.1", 320 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", 321 | "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", 322 | "cpu": [ 323 | "arm" 324 | ], 325 | "dev": true, 326 | "license": "MIT", 327 | "optional": true, 328 | "os": [ 329 | "linux" 330 | ], 331 | "engines": { 332 | "node": ">=18" 333 | } 334 | }, 335 | "node_modules/@esbuild/linux-arm64": { 336 | "version": "0.23.1", 337 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", 338 | "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", 339 | "cpu": [ 340 | "arm64" 341 | ], 342 | "dev": true, 343 | "license": "MIT", 344 | "optional": true, 345 | "os": [ 346 | "linux" 347 | ], 348 | "engines": { 349 | "node": ">=18" 350 | } 351 | }, 352 | "node_modules/@esbuild/linux-ia32": { 353 | "version": "0.23.1", 354 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", 355 | "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", 356 | "cpu": [ 357 | "ia32" 358 | ], 359 | "dev": true, 360 | "license": "MIT", 361 | "optional": true, 362 | "os": [ 363 | "linux" 364 | ], 365 | "engines": { 366 | "node": ">=18" 367 | } 368 | }, 369 | "node_modules/@esbuild/linux-loong64": { 370 | "version": "0.23.1", 371 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", 372 | "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", 373 | "cpu": [ 374 | "loong64" 375 | ], 376 | "dev": true, 377 | "license": "MIT", 378 | "optional": true, 379 | "os": [ 380 | "linux" 381 | ], 382 | "engines": { 383 | "node": ">=18" 384 | } 385 | }, 386 | "node_modules/@esbuild/linux-mips64el": { 387 | "version": "0.23.1", 388 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", 389 | "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", 390 | "cpu": [ 391 | "mips64el" 392 | ], 393 | "dev": true, 394 | "license": "MIT", 395 | "optional": true, 396 | "os": [ 397 | "linux" 398 | ], 399 | "engines": { 400 | "node": ">=18" 401 | } 402 | }, 403 | "node_modules/@esbuild/linux-ppc64": { 404 | "version": "0.23.1", 405 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", 406 | "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", 407 | "cpu": [ 408 | "ppc64" 409 | ], 410 | "dev": true, 411 | "license": "MIT", 412 | "optional": true, 413 | "os": [ 414 | "linux" 415 | ], 416 | "engines": { 417 | "node": ">=18" 418 | } 419 | }, 420 | "node_modules/@esbuild/linux-riscv64": { 421 | "version": "0.23.1", 422 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", 423 | "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", 424 | "cpu": [ 425 | "riscv64" 426 | ], 427 | "dev": true, 428 | "license": "MIT", 429 | "optional": true, 430 | "os": [ 431 | "linux" 432 | ], 433 | "engines": { 434 | "node": ">=18" 435 | } 436 | }, 437 | "node_modules/@esbuild/linux-s390x": { 438 | "version": "0.23.1", 439 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", 440 | "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", 441 | "cpu": [ 442 | "s390x" 443 | ], 444 | "dev": true, 445 | "license": "MIT", 446 | "optional": true, 447 | "os": [ 448 | "linux" 449 | ], 450 | "engines": { 451 | "node": ">=18" 452 | } 453 | }, 454 | "node_modules/@esbuild/linux-x64": { 455 | "version": "0.23.1", 456 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", 457 | "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", 458 | "cpu": [ 459 | "x64" 460 | ], 461 | "dev": true, 462 | "license": "MIT", 463 | "optional": true, 464 | "os": [ 465 | "linux" 466 | ], 467 | "engines": { 468 | "node": ">=18" 469 | } 470 | }, 471 | "node_modules/@esbuild/netbsd-x64": { 472 | "version": "0.23.1", 473 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", 474 | "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", 475 | "cpu": [ 476 | "x64" 477 | ], 478 | "dev": true, 479 | "license": "MIT", 480 | "optional": true, 481 | "os": [ 482 | "netbsd" 483 | ], 484 | "engines": { 485 | "node": ">=18" 486 | } 487 | }, 488 | "node_modules/@esbuild/openbsd-arm64": { 489 | "version": "0.23.1", 490 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", 491 | "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", 492 | "cpu": [ 493 | "arm64" 494 | ], 495 | "dev": true, 496 | "license": "MIT", 497 | "optional": true, 498 | "os": [ 499 | "openbsd" 500 | ], 501 | "engines": { 502 | "node": ">=18" 503 | } 504 | }, 505 | "node_modules/@esbuild/openbsd-x64": { 506 | "version": "0.23.1", 507 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", 508 | "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", 509 | "cpu": [ 510 | "x64" 511 | ], 512 | "dev": true, 513 | "license": "MIT", 514 | "optional": true, 515 | "os": [ 516 | "openbsd" 517 | ], 518 | "engines": { 519 | "node": ">=18" 520 | } 521 | }, 522 | "node_modules/@esbuild/sunos-x64": { 523 | "version": "0.23.1", 524 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", 525 | "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", 526 | "cpu": [ 527 | "x64" 528 | ], 529 | "dev": true, 530 | "license": "MIT", 531 | "optional": true, 532 | "os": [ 533 | "sunos" 534 | ], 535 | "engines": { 536 | "node": ">=18" 537 | } 538 | }, 539 | "node_modules/@esbuild/win32-arm64": { 540 | "version": "0.23.1", 541 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", 542 | "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", 543 | "cpu": [ 544 | "arm64" 545 | ], 546 | "dev": true, 547 | "license": "MIT", 548 | "optional": true, 549 | "os": [ 550 | "win32" 551 | ], 552 | "engines": { 553 | "node": ">=18" 554 | } 555 | }, 556 | "node_modules/@esbuild/win32-ia32": { 557 | "version": "0.23.1", 558 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", 559 | "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", 560 | "cpu": [ 561 | "ia32" 562 | ], 563 | "dev": true, 564 | "license": "MIT", 565 | "optional": true, 566 | "os": [ 567 | "win32" 568 | ], 569 | "engines": { 570 | "node": ">=18" 571 | } 572 | }, 573 | "node_modules/@esbuild/win32-x64": { 574 | "version": "0.23.1", 575 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", 576 | "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", 577 | "cpu": [ 578 | "x64" 579 | ], 580 | "dev": true, 581 | "license": "MIT", 582 | "optional": true, 583 | "os": [ 584 | "win32" 585 | ], 586 | "engines": { 587 | "node": ">=18" 588 | } 589 | }, 590 | "node_modules/@template/service-template": { 591 | "resolved": "services/service-template", 592 | "link": true 593 | }, 594 | "node_modules/@template/shared-template": { 595 | "resolved": "shared/shared-template", 596 | "link": true 597 | }, 598 | "node_modules/@types/node": { 599 | "version": "22.13.4", 600 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz", 601 | "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==", 602 | "dev": true, 603 | "license": "MIT", 604 | "dependencies": { 605 | "undici-types": "~6.20.0" 606 | } 607 | }, 608 | "node_modules/esbuild": { 609 | "version": "0.23.1", 610 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", 611 | "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", 612 | "dev": true, 613 | "hasInstallScript": true, 614 | "license": "MIT", 615 | "bin": { 616 | "esbuild": "bin/esbuild" 617 | }, 618 | "engines": { 619 | "node": ">=18" 620 | }, 621 | "optionalDependencies": { 622 | "@esbuild/aix-ppc64": "0.23.1", 623 | "@esbuild/android-arm": "0.23.1", 624 | "@esbuild/android-arm64": "0.23.1", 625 | "@esbuild/android-x64": "0.23.1", 626 | "@esbuild/darwin-arm64": "0.23.1", 627 | "@esbuild/darwin-x64": "0.23.1", 628 | "@esbuild/freebsd-arm64": "0.23.1", 629 | "@esbuild/freebsd-x64": "0.23.1", 630 | "@esbuild/linux-arm": "0.23.1", 631 | "@esbuild/linux-arm64": "0.23.1", 632 | "@esbuild/linux-ia32": "0.23.1", 633 | "@esbuild/linux-loong64": "0.23.1", 634 | "@esbuild/linux-mips64el": "0.23.1", 635 | "@esbuild/linux-ppc64": "0.23.1", 636 | "@esbuild/linux-riscv64": "0.23.1", 637 | "@esbuild/linux-s390x": "0.23.1", 638 | "@esbuild/linux-x64": "0.23.1", 639 | "@esbuild/netbsd-x64": "0.23.1", 640 | "@esbuild/openbsd-arm64": "0.23.1", 641 | "@esbuild/openbsd-x64": "0.23.1", 642 | "@esbuild/sunos-x64": "0.23.1", 643 | "@esbuild/win32-arm64": "0.23.1", 644 | "@esbuild/win32-ia32": "0.23.1", 645 | "@esbuild/win32-x64": "0.23.1" 646 | } 647 | }, 648 | "node_modules/fsevents": { 649 | "version": "2.3.3", 650 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 651 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 652 | "dev": true, 653 | "hasInstallScript": true, 654 | "license": "MIT", 655 | "optional": true, 656 | "os": [ 657 | "darwin" 658 | ], 659 | "engines": { 660 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 661 | } 662 | }, 663 | "node_modules/get-tsconfig": { 664 | "version": "4.10.0", 665 | "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", 666 | "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", 667 | "dev": true, 668 | "license": "MIT", 669 | "dependencies": { 670 | "resolve-pkg-maps": "^1.0.0" 671 | }, 672 | "funding": { 673 | "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" 674 | } 675 | }, 676 | "node_modules/resolve-pkg-maps": { 677 | "version": "1.0.0", 678 | "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", 679 | "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", 680 | "dev": true, 681 | "license": "MIT", 682 | "funding": { 683 | "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" 684 | } 685 | }, 686 | "node_modules/tsx": { 687 | "version": "4.19.2", 688 | "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", 689 | "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", 690 | "dev": true, 691 | "license": "MIT", 692 | "dependencies": { 693 | "esbuild": "~0.23.0", 694 | "get-tsconfig": "^4.7.5" 695 | }, 696 | "bin": { 697 | "tsx": "dist/cli.mjs" 698 | }, 699 | "engines": { 700 | "node": ">=18.0.0" 701 | }, 702 | "optionalDependencies": { 703 | "fsevents": "~2.3.3" 704 | } 705 | }, 706 | "node_modules/typescript": { 707 | "version": "5.7.3", 708 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", 709 | "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", 710 | "dev": true, 711 | "license": "Apache-2.0", 712 | "bin": { 713 | "tsc": "bin/tsc", 714 | "tsserver": "bin/tsserver" 715 | }, 716 | "engines": { 717 | "node": ">=14.17" 718 | } 719 | }, 720 | "node_modules/undici-types": { 721 | "version": "6.20.0", 722 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", 723 | "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", 724 | "dev": true, 725 | "license": "MIT" 726 | }, 727 | "services/service-template": { 728 | "name": "@template/service-template", 729 | "version": "0.0.0", 730 | "devDependencies": {}, 731 | "peerDependencies": { 732 | "@template/shared-template": "*" 733 | } 734 | }, 735 | "shared/shared-template": { 736 | "name": "@template/shared-template", 737 | "version": "0.0.0", 738 | "devDependencies": {} 739 | } 740 | } 741 | } 742 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "services/*", 5 | "shared/*" 6 | ], 7 | "type": "module", 8 | "devDependencies": { 9 | "@biomejs/biome": "^1.9.4", 10 | "@types/node": "^22.13.4", 11 | "tsx": "^4.19.2", 12 | "typescript": "^5.7.3" 13 | }, 14 | "scripts": { 15 | "build": "npm run typescript:build", 16 | "watch": "npm run typescript:watch", 17 | "clean": "npm run typescript:clean", 18 | "test": "npm run lint && npm run test:node", 19 | "test:node": "node --import tsx --test {services,shared}/*/test/*.test.ts", 20 | "lint": "npm run lint:biome", 21 | "lint:biome": "biome lint --write {services,shared}/*/src", 22 | "fmt": "biome format --write {services,shared}/*/src", 23 | "typescript:build": "tsc --build ./tsconfig.project.json", 24 | "typescript:watch": "npm run typescript:build -- --watch", 25 | "typescript:clean": "rm -rf ./{services,shared}/*/{lib,*.tsbuildinfo}", 26 | "update:tsconfig": "tsx scripts/update-package-tsconfig.ts" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scripts/update-package-tsconfig.ts: -------------------------------------------------------------------------------- 1 | import { 2 | join as pathJoin, 3 | relative as pathRelative, 4 | } from 'node:path'; 5 | import { 6 | writeFileSync, 7 | readFileSync, 8 | readdirSync, 9 | lstatSync, 10 | } from 'node:fs'; 11 | import { fileURLToPath } from 'node:url'; 12 | 13 | enum ConfigFilename { 14 | PACKAGE = 'package.json', 15 | BASE_TSCONFIG = 'tsconfig.base.json', 16 | PACKAGE_TSCONFIG = 'tsconfig.package.json', 17 | PROJECT_TSCONFIG = 'tsconfig.project.json' 18 | } 19 | 20 | const TSCONFIG_HEADER = '// File generated automatically, use npm run update:tsconfig for update\n'; 21 | 22 | interface IPackageJSON { 23 | name: string; 24 | workspaces: string[]; 25 | dependencies: Record; 26 | devDependencies: Record; 27 | peerDependencies: Record; 28 | } 29 | 30 | const readJSON = (path: string): T => ( 31 | JSON.parse( 32 | readFileSync(path, 'utf8') 33 | ) 34 | ); 35 | 36 | const writeTsconfig = (path: string, data: T): void => { 37 | writeFileSync(path, TSCONFIG_HEADER + JSON.stringify(data, undefined, ' ')); 38 | }; 39 | 40 | const rootPath = fileURLToPath(new URL('..', import.meta.url)); 41 | 42 | const rootPackage = readJSON( 43 | pathJoin(rootPath, ConfigFilename.PACKAGE) 44 | ); 45 | 46 | const workspacePaths = rootPackage.workspaces 47 | .map(workspaceDirectory => ( 48 | workspaceDirectory.replace('/*', '') 49 | )) 50 | .map(workspaceDirectory => ( 51 | pathJoin(rootPath, workspaceDirectory) 52 | )); 53 | 54 | const packageDirectories = workspacePaths 55 | .flatMap(workspacePath => ( 56 | readdirSync(workspacePath) 57 | .map(packageDirectory => ( 58 | pathJoin(workspacePath, packageDirectory) 59 | )) 60 | )) 61 | .filter(packageDirectory => ( 62 | lstatSync(packageDirectory).isDirectory() 63 | )); 64 | 65 | const packagePathMap = new Map(); 66 | const packageJSONMap = new Map(); 67 | 68 | for (const packageDirectory of packageDirectories) { 69 | const packageJSON = readJSON( 70 | pathJoin(packageDirectory, ConfigFilename.PACKAGE) 71 | ); 72 | 73 | const { name: packageName } = packageJSON; 74 | 75 | packagePathMap.set(packageName, packageDirectory); 76 | packageJSONMap.set(packageName, packageJSON); 77 | } 78 | 79 | const internalDependencyMap = new Map(); 80 | 81 | for (const [packageName, packageJSON] of packageJSONMap.entries()) { 82 | const allDependencies = [ 83 | ...Object.keys(packageJSON.dependencies || {}), 84 | ...Object.keys(packageJSON.devDependencies || {}), 85 | ...Object.keys(packageJSON.peerDependencies || {}), 86 | ]; 87 | 88 | const internalDependencies = allDependencies.filter(dependencyName => ( 89 | packageJSONMap.has(dependencyName) 90 | )); 91 | 92 | internalDependencyMap.set(packageName, internalDependencies); 93 | } 94 | 95 | const resolveInternalDependencies = (dependencies: string[]): string[] => ( 96 | [...new Set([ 97 | ...dependencies.flatMap(dependency => { 98 | const internalDependencies = internalDependencyMap.get(dependency)!; 99 | 100 | return resolveInternalDependencies(internalDependencies); 101 | }), 102 | ...dependencies, 103 | ])] 104 | ); 105 | 106 | for (const [packageName, packagePath] of packagePathMap.entries()) { 107 | const tsconfigPath = pathJoin(packagePath, ConfigFilename.PACKAGE_TSCONFIG); 108 | 109 | const internalDependencies = resolveInternalDependencies( 110 | internalDependencyMap.get(packageName)! 111 | ); 112 | 113 | const tsconfigData = { 114 | extends: pathJoin( 115 | pathRelative(packagePath, rootPath), 116 | ConfigFilename.BASE_TSCONFIG 117 | ), 118 | compilerOptions: { 119 | outDir: './lib', 120 | rootDir: './src', 121 | composite: true, 122 | }, 123 | include: ['src'], 124 | exclude: ['test', 'lib'], 125 | references: internalDependencies.map(dependencyName => { 126 | const dependencyPath = packagePathMap.get(dependencyName)!; 127 | 128 | return { 129 | path: pathJoin( 130 | pathRelative(packagePath, dependencyPath), 131 | ConfigFilename.PACKAGE_TSCONFIG 132 | ), 133 | }; 134 | }), 135 | }; 136 | 137 | writeTsconfig(tsconfigPath, tsconfigData); 138 | } 139 | 140 | const tsconfigProjectPath = pathJoin(rootPath, ConfigFilename.PROJECT_TSCONFIG); 141 | 142 | const tsconfigProjectData = { 143 | files: [], 144 | references: resolveInternalDependencies([...packagePathMap.keys()]) 145 | .map(dependencyName => { 146 | const dependencyPath = packagePathMap.get(dependencyName)!; 147 | 148 | return { 149 | path: pathJoin( 150 | pathRelative(rootPath, dependencyPath), 151 | ConfigFilename.PACKAGE_TSCONFIG 152 | ), 153 | }; 154 | }), 155 | }; 156 | 157 | writeTsconfig(tsconfigProjectPath, tsconfigProjectData); 158 | -------------------------------------------------------------------------------- /services/service-template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@template/service-template", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "main": "./lib/index.js", 7 | "exports": { 8 | ".": { 9 | "import": "./lib/index.js", 10 | "types": "./lib/index.d.ts" 11 | } 12 | }, 13 | "dependencies": { 14 | 15 | }, 16 | "devDependencies": { 17 | 18 | }, 19 | "peerDependencies": { 20 | "@template/shared-template": "*" 21 | }, 22 | "scripts": { 23 | "build": "tsc --build ./tsconfig.package.json" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /services/service-template/src/index.ts: -------------------------------------------------------------------------------- 1 | import { hello } from '@template/shared-template'; 2 | 3 | hello(); 4 | -------------------------------------------------------------------------------- /services/service-template/test/service-template.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it } from 'node:test'; 2 | import { strictEqual } from 'node:assert'; 3 | 4 | describe('Shared', (): void => { 5 | it('template', (): void => { 6 | strictEqual(true, true); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /services/service-template/tsconfig.package.json: -------------------------------------------------------------------------------- 1 | // File generated automatically, use npm run update:tsconfig for update 2 | { 3 | "extends": "../../tsconfig.base.json", 4 | "compilerOptions": { 5 | "outDir": "./lib", 6 | "rootDir": "./src", 7 | "composite": true 8 | }, 9 | "include": [ 10 | "src" 11 | ], 12 | "exclude": [ 13 | "test", 14 | "lib" 15 | ], 16 | "references": [ 17 | { 18 | "path": "../../shared/shared-template/tsconfig.package.json" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /shared/shared-template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@template/shared-template", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "main": "./lib/index.js", 7 | "exports": { 8 | ".": { 9 | "import": "./lib/index.js", 10 | "types": "./lib/index.d.ts" 11 | } 12 | }, 13 | "dependencies": { 14 | 15 | }, 16 | "devDependencies": { 17 | 18 | }, 19 | "peerDependencies": { 20 | 21 | }, 22 | "scripts": { 23 | "build": "tsc --build ./tsconfig.package.json" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /shared/shared-template/src/index.ts: -------------------------------------------------------------------------------- 1 | export function hello() { 2 | // eslint-disable-next-line no-console 3 | console.log('Hello!'); 4 | } 5 | -------------------------------------------------------------------------------- /shared/shared-template/test/shared-template.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it } from 'node:test'; 2 | import { strictEqual } from 'node:assert'; 3 | 4 | describe('Shared', (): void => { 5 | it('template', (): void => { 6 | strictEqual(true, true); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /shared/shared-template/tsconfig.package.json: -------------------------------------------------------------------------------- 1 | // File generated automatically, use npm run update:tsconfig for update 2 | { 3 | "extends": "../../tsconfig.base.json", 4 | "compilerOptions": { 5 | "outDir": "./lib", 6 | "rootDir": "./src", 7 | "composite": true 8 | }, 9 | "include": [ 10 | "src" 11 | ], 12 | "exclude": [ 13 | "test", 14 | "lib" 15 | ], 16 | "references": [] 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "Node16", 5 | "moduleResolution": "Node16", 6 | "useDefineForClassFields": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "resolveJsonModule": true, 10 | "isolatedModules": true, 11 | "esModuleInterop": true, 12 | "skipLibCheck": true, 13 | "sourceMap": true, 14 | "declaration": true, 15 | "declarationMap": true, 16 | "strict": true, 17 | "forceConsistentCasingInFileNames": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "noEmit": true, 5 | "baseUrl": ".", 6 | "paths": { 7 | "@template/*": [ 8 | "./shared/*/src", 9 | "./services/*/src" 10 | ] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.project.json: -------------------------------------------------------------------------------- 1 | // File generated automatically, use npm run update:tsconfig for update 2 | { 3 | "files": [], 4 | "references": [ 5 | { 6 | "path": "shared/shared-template/tsconfig.package.json" 7 | }, 8 | { 9 | "path": "services/service-template/tsconfig.package.json" 10 | } 11 | ] 12 | } 13 | --------------------------------------------------------------------------------