Typescript Service Starter
Yet another (opinionated) typescript service starter template.
Opinions and limitations
- Tries to follow Domain Driven Development and 3 Layers architecture
- As little of externalities requirements as possible (outputs to stdout/stderr, no auth management, etc.)
- No dependency on node_modules folder and filesystem at runtime, to allow bundling & small Docker image
- Config should not default to either development or production (link)
And extends the ones from typescript-library-starter
- Relies as much as possible on each included library's defaults
- Only rely on GitHub Actions
- Do not include documentation generation
Getting started
npx degit gjuchault/typescript-service-starter my-project
or click on Use this template
button on GitHub!cd my-project
npm install
git init
(if you used degit)npm run setup
To enable deployment, you will need to:
- Setup
NPM_TOKEN
secret in GitHub actions (Settings > Secrets > Actions) - Give
GITHUB_TOKEN
write permissions for GitHub releases (Settings > Actions > General > Workflow permissions)
Features
Ecosystem
This template is based on Fastify with some nice defaults (circuit breaker, redis rate limit, etc.). trpc is used to have nice routes & automatic client generations with zod and typescript.
It leverages PostgreSQL as a storage (through slonik), Redis as a cache through ioredis).
For the logging & telemetry part, it uses pino and OpenTelemetry (for both prometheus-like metrics & tracing). To handle distributed tracing, it expects W3C's traceparent header to carry trace id & parent span id.
To run tasks & crons, this package leverages BullMQ.
This template also tries to be easy to deploy through esbuild's bundling. This means you can not leverage node_modules and file system at runtime: reading static files from node_modules, hooking require
, etc. ill not be possible. This implies to be mindful on libraries (that would read static files from there older), or automatic instrumentation (that hook require
). Yet it comes with super small Docker images hat are fast to deploy.
Layers & folder structure
migrations # database migrations (.sql files, no rollback)
src/
├── application # service code
├── domain # pure functions & typescript models of your entities
├── presentation # communication layer (http)
├── repository # storage of your entities
├── infrastructure # technical components (cache, database connection, etc.)
├── helpers # utilities functions & non-domain code
└── test-helpers # test utilities (starting default port, resetting database, etc.)
Client generation
You can check trpc's documentation to have an automatic client with typing. AppRouter
is exported on the index file. If you wish to use your own client, remember that nested routers in trpc are using dot instead of slash (eg.: GET http://localhost:8080/api/healthcheck.healthcheck
).
Node.js, npm version
Typescript Service Starter relies on volta to ensure node version to be consistent across developers. It's also used in the GitHub workflow file.
Typescript
Leverages esbuild for blazing fast builds, but keeps tsc
to generate .d.ts
files.
Generates a single ESM build.
Commands:
build
: runs typechecking then ESM and d.ts
files in the build/
directoryclean
: removes the build/
directorytype:dts
: only generates d.ts
type:check
: only run typecheckingtype:build
: only generates ESM
Tests
typescript-service-starter uses vitest. The coverage is done through vitest, using c8.
Commands:
test
: runs vitest test runnertest:watch
: runs vitest test runner in watch modetest:coverage
: runs vitest test runner and generates coverage reports
Format & lint
This template relies on the combination of eslint — through typescript-eslint for linting and prettier for formatting.
It also uses cspell to ensure spelling
Commands:
format
: runs prettier with automatic fixingformat:check
: runs prettier without automatic fixing (used in CI)lint
: runs eslint with automatic fixinglint:check
: runs eslint without automatic fixing (used in CI)spell:check
: runs spellchecking
Releasing
Under the hood, this service uses semantic-release and commitizen.
The goal is to avoid manual release process. Using semantic-release
will automatically create a github release (hence tags) as well as an npm release.
Based on your commit history, semantic-release
will automatically create a patch, feature or breaking release.
Commands:
cz
: interactive CLI that helps you generate a proper git commit message, using commitizensemantic-release
: triggers a release (used in CI)