From 9b2f1c9e3aaafd42ab078414ed5eebf2261231aa Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 13:57:41 +0800 Subject: [PATCH 01/18] docs: update readme to be more concise Details will be moved under `docs/`. --- README.md | 71 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 5338bad..03eab14 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,67 @@ # USThing Template API -The template repository for USThing backend services, powered by Fastify. +A concise Fastify + TypeScript starter used by USThing backend services. This repository provides a minimal, well-tested scaffold with recommended scripts, linting, and CI configuration. -## Available Scripts +## Quickstart -In the project directory, you can run: +Run the following to get started (single command block; brief comments explain each step): -### `yarn run dev` +```bash +# Install dependencies +yarn install -To start the app in dev mode. -Open [http://localhost:3000](http://localhost:3000) to view it in the browser. +# Run in development (watch + fastify) +yarn run dev -### `yarn run start` +# Build TypeScript to `dist` +yarn run build -For production mode +# Start production server (uses `dist`) +yarn run start -### `yarn run test` +# Run tests +yarn run test +``` -Run the test cases. +## Key scripts -### `yarn run lint` +- `dev` — start in development (watch + fastify) +- `build` — compile TypeScript +- `start` — run production server (from `dist`) +- `test` — build and run tests +- `lint`, `lint:fix` — ESLint checks and fixes +- `commitlint` — validate commit messages -Run the linter. +## Project layout -Note that the format of the code will also be checked. +- `src/` — application code (routes, plugins, utils) +- `src/app.ts` — Fastify app and plugin registration +- `routes/` — route modules +- `test/` — tests and helpers +- `docs/` — human-authored docs (Quickstart, guides, migration) +- `.env.example` — example env variables -### `yarn run lint:fix` +## Docs and API reference -Run the linter and fix the issues. +Human-facing guides belong in `docs/`. API specs (generated from code via Fastify+Swagger or TypeDoc) should be produced by CI and published to your docs site rather than frequently committing generated files. -Note that the format of the code will also be checked and fixed. +## Environment -## Environment Variables +See `.env.example` for application-level variables. Fastify CLI options are documented at the `fastify-cli` project. -For Fastify-level environment variables, please refer to the [fastify-cli documentation](https://github.com/fastify/fastify-cli). +## Contributing -For the application-level environment variables, please refer to the `.env.example` file. +Please follow `CONTRIBUTING.md`. Use the configured commitlint rules and run lint/tests before opening a PR. -## CI / CD +## Support -This template supports GitHub Actions for CI / CD. The available workflows are: +Open an issue on GitHub using the provided templates for bugs or feature requests. -- Checks / eslint: Run ES Lint to check problems and the format of the code. -- Checks / commitlint: Run Commitlint to check the format of the commit messages. -- Checks / tests: Run unit tests of the project. -- Docker CI / docker: Build the Docker image and push it to the GitHub Container Registry. -- Release Please / release-please: Automatic releasing. See also [release-please](https://github.com/googleapis/release-please). +## License -## Learn More +MIT -To learn Fastify, check out the [Fastify documentation](https://fastify.dev/docs/latest/). +## Learn more + +- Fastify: +- Docs folder: `docs/` (detailed guides and examples) From e5f0685275a8f7f6b625c8575e448035baa05d64 Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 14:32:53 +0800 Subject: [PATCH 02/18] docs: add quickstart and development setup --- README.md | 14 ++++++--- docs/dev-setup.md | 70 +++++++++++++++++++++++++++++++++++++++++++ docs/quickstart.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 docs/dev-setup.md create mode 100644 docs/quickstart.md diff --git a/README.md b/README.md index 03eab14..aa5cc6d 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,9 @@ Run the following to get started (single command block; brief comments explain e # Install dependencies yarn install +# Prepare Husky git hooks (if present) +yarn run prepare + # Run in development (watch + fastify) yarn run dev @@ -23,6 +26,13 @@ yarn run start yarn run test ``` +Note: this repository expects Yarn managed via Corepack. If Corepack is not enabled on your machine, enable it first: + +```bash +corepack enable +# after enabling, use `yarn ...` as usual (no need for `corepack` prefix) +``` + ## Key scripts - `dev` — start in development (watch + fastify) @@ -57,10 +67,6 @@ Please follow `CONTRIBUTING.md`. Use the configured commitlint rules and run lin Open an issue on GitHub using the provided templates for bugs or feature requests. -## License - -MIT - ## Learn more - Fastify: diff --git a/docs/dev-setup.md b/docs/dev-setup.md new file mode 100644 index 0000000..cb84428 --- /dev/null +++ b/docs/dev-setup.md @@ -0,0 +1,70 @@ +# Developer setup + +This file documents the minimal developer setup for the template-api project. + +## Prerequisites + +- Node.js >= 24 (LTS or newer recommended) +- Corepack (bundled with modern Node.js releases) + + + +## Enable Corepack + +Enable corepack if not already enabled: + +```bash +# enables Corepack globally +corepack enable +``` + +## Verify setup + +Verify Yarn is available and the expected version + +```bash +# Yarn should be available after enabling Corepack +yarn -v +``` + +## Installation + +Install dependencies and prepare hooks + +```bash +# install dependencies +yarn install + +# prepare Husky git hooks (if present) +yarn run prepare +``` + +## Notes + +- After enabling Corepack you can use `yarn` directly — there is no need to prefix commands with `corepack`. +- If the repository sets a Yarn version via `.yarnrc.yml`/`yarn.lock`, Corepack will select the correct Yarn release automatically. +- Keep your Node toolchain up-to-date for security and compatibility. + +## Troubleshooting + +- If `yarn` is not found after enabling Corepack, restart your shell or open a new terminal. +- If you need a specific Yarn release, run `corepack prepare yarn@ --activate`. + +## Further reading + +- Corepack: +- Yarn (Berry) docs: + +## Optional: Node version management + +If you choose to use a Node version manager, pin a version in the repo (for example add a `.nvmrc` with `24`) so contributors and CI pick the same Node. Minimal examples: + +```bash +# nvm +nvm install 24 && nvm use 24 + +# fnm +fnm install 24 && fnm use 24 +``` + +This is optional but recommended for reproducible local builds and CI. diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 0000000..ef2cc98 --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,74 @@ +# Quickstart + +This page expands the brief Quickstart in the project README. Keep this short and focused — detailed guides belong elsewhere in `docs/`. + +## Prerequisites + +- Node.js >= 24 +- Yarn 3+ (the repository uses Yarn; `npm` may also work but commands below use `yarn`) + +This project expects Yarn managed via Corepack. On modern Node.js releases Corepack is included — enable it with: + +```bash +corepack enable +``` + +## Install + +```bash +# Install dependencies (after enabling Corepack, use `yarn`) +yarn install + +# Prepare Husky git hooks (if present) +yarn run prepare +``` + +## Development + +```bash +# start in development (watch + fastify) +yarn run dev +``` + +The server listens on the port configured in your environment (default Fastify port is typically 3000). Check logs for the bound address. + +## Build & production run + +```bash +# compile the TypeScript output to dist +yarn run build + +# start the production server (reads compiled files from dist) +yarn run start +``` + +## Environment + +Application-level variables are documented in `.env.example` at the repository root. Don't commit secrets — use environment management for CI/production. + +## Example requests + +This template includes an example route. When running locally, try: + +```bash +# Basic example (expected response: "this is an example") +curl -sS http://localhost:3000/example/ + +# Example that returns a bad request error (demonstrates error handling) +curl -sS http://localhost:3000/example/error +``` + +Notes: + +- The example routes are implemented under `src/routes/example/`. The folder name is used as the route prefix by autoload (so the endpoints above are `/example/` and `/example/error`). +- If your project config mounts routes differently, adjust the path accordingly. + +## API docs + +When Swagger/UI is enabled (see `src/plugins`), an interactive API UI is typically available at `/documentation` (or the path configured in the plugin). Generated specs should be published by CI rather than committed frequently to avoid merge conflicts. + +## Next steps + +- Read `docs/routes.md` (TODO) for a high-level route map and plugin responsibilities. +- Add environment values to `.env` based on `.env.example`. +- Open `CONTRIBUTING.md` before making the first PR. From c0866a9037611487ef662a1560703187acfa77ad Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 14:48:13 +0800 Subject: [PATCH 03/18] docs: migrate and add plugins and routes docs --- docs/plugins.md | 41 +++++++++++++++++++++++++++++++++++++++++ docs/routes.md | 40 ++++++++++++++++++++++++++++++++++++++++ src/plugins/README.md | 16 ---------------- src/routes/README.md | 29 ----------------------------- 4 files changed, 81 insertions(+), 45 deletions(-) create mode 100644 docs/plugins.md create mode 100644 docs/routes.md delete mode 100644 src/plugins/README.md delete mode 100644 src/routes/README.md diff --git a/docs/plugins.md b/docs/plugins.md new file mode 100644 index 0000000..a3bfed6 --- /dev/null +++ b/docs/plugins.md @@ -0,0 +1,41 @@ +# Plugins + +This file summarizes the plugins provided in the template and how they are loaded. + +## Loading + +- Plugins live under `src/plugins/` and are autoloaded by `@fastify/autoload` in `src/app.ts`. +- Plugins run before routes are registered so they can provide decorators, hooks, and shared schemas used by routes. + +## About plugins + +Plugins define cross-cutting behavior for your application (auth, DB, caching, helpers). Files in `src/plugins/` typically use `fastify-plugin` so they can expose decorators and hooks to the outer scope. + +See also: + +- The hitchhiker's guide to plugins: +- Fastify decorators: +- Fastify lifecycle: + +## Key plugins + +- `sensible.ts` + - Registers `@fastify/sensible` and exposes a shared schema id `HttpError` used in route schemas. + - Provides convenience reply helpers such as `reply.badRequest()`. + +- `auth.ts` + - Adds authentication support via OpenID Connect discovery and JWT verification. + - Exposes a decorator `fastify.authPlugin(request, reply)` to validate requests; also sets `request.user` after successful auth. + - Options: `authDiscoveryURL`, `authClientID`, and optional `authSkip` to disable in local/testing. + +- `init-mongo.ts` (optional) + - Placeholder plugin for MongoDB initialization (indexes, migrations). The actual MongoDB registration is commented out in `src/app.ts` and is optional. + +- `support.ts` + - Example plugin demonstrating `fastify.decorate()` (adds `someSupport()` decorator returning a string). + +## Extending plugins + +- Add a new plugin under `src/plugins/` and export it as a Fastify plugin (use `fastify-plugin` to expose decorators). +- Keep plugin responsibilities narrow and reusable (auth, DB setup, metrics, tracing, etc.). +- Document plugin options and side effects in `docs/plugins.md` or inline plugin README comments. diff --git a/docs/routes.md b/docs/routes.md new file mode 100644 index 0000000..5b95a32 --- /dev/null +++ b/docs/routes.md @@ -0,0 +1,40 @@ +# Routes and plugins (overview) + +This file gives a short, human-oriented map of the routes and plugins in this template. Keep it brief — full API specs are generated from code (use CI to publish generated docs). + +## Route loading + +- The project uses `@fastify/autoload` in `src/app.ts` to load all files under `src/routes/`. +- Each folder under `src/routes//` is mounted at the prefix `/` (e.g. `src/routes/example/` => `/example`). + +## About routes + +Routes define the endpoints of your application. Prefer organizing related endpoints in the same folder (e.g. `src/routes/users/`) and keep each route file a Fastify plugin (autoload will mount it automatically). + +If a single route file grows large, split it into a folder with an `index.ts` plugin and helper modules. Use `plugins/` for shared functionality exposed via decorators. + +See Fastify's route patterns and promise-resolution behavior for async handlers: + +## Example routes + +`src/routes/example/index.ts` exposes two endpoints: + +- GET /example/ + - Response: 200, plain string + - Example: `this is an example` +- GET /example/error + - Response: 400 (Bad Request) with JSON error body produced via `fastify-sensible` + - Example: returns a bad request with message `this is an error example` + +Use these endpoints for quick smoke tests while developing. + +## How to extend + +- Add route modules under `src/routes//` — autoload will mount them automatically. +- Add plugins to `src/plugins/` for shared functionality (auth, DB init, logging, etc.). +- When adding config-driven plugins, ensure options are declared in `AppOptions` in `src/app.ts` or passed via `--options` to Fastify start. + +## Where to find generated API docs + +- The project registers `@fastify/swagger` and `@fastify/swagger-ui` in `src/app.ts`. The interactive UI is typically served at `/documentation` unless configured otherwise. +- Prefer generating and publishing the OpenAPI/TypeDoc output in CI rather than committing generated artifacts to the repository. diff --git a/src/plugins/README.md b/src/plugins/README.md deleted file mode 100644 index 1e61ee5..0000000 --- a/src/plugins/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Plugins Folder - -Plugins define behavior that is common to all the routes in your -application. Authentication, caching, templates, and all the other cross -cutting concerns should be handled by plugins placed in this folder. - -Files in this folder are typically defined through the -[`fastify-plugin`](https://github.com/fastify/fastify-plugin) module, -making them non-encapsulated. They can define decorators and set hooks -that will then be used in the rest of your application. - -Check out: - -* [The hitchhiker's guide to plugins](https://fastify.dev/docs/latest/Guides/Plugins-Guide/) -* [Fastify decorators](https://fastify.dev/docs/latest/Reference/Decorators/). -* [Fastify lifecycle](https://fastify.dev/docs/latest/Reference/Lifecycle/). diff --git a/src/routes/README.md b/src/routes/README.md deleted file mode 100644 index 75b5658..0000000 --- a/src/routes/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Routes Folder - -Routes define the pathways within your application. -Fastify's structure supports the modular monolith approach, where your -application is organized into distinct, self-contained modules. -This facilitates easier scaling and future transition to a microservice architecture. -In the future you might want to independently deploy some of those. - -In this folder you should define all the routes that define the endpoints -of your web application. -Each service is a [Fastify -plugin](https://fastify.dev/docs/latest/Reference/Plugins/), it is -encapsulated (it can have its own independent plugins) and it is -typically stored in a file; be careful to group your routes logically, -e.g. all `/users` routes in a `users.js` file. We have added -a `root.js` file for you with a '/' root added. - -If a single file becomes too large, create a folder and add a `index.js` file there: -this file must be a Fastify plugin, and it will be loaded automatically -by the application. You can now add as many files as you want inside that folder. -In this way you can create complex routes within a single monolith, -and eventually extract them. - -If you need to share functionality between routes, place that -functionality into the `plugins` folder, and share it via -[decorators](https://fastify.dev/docs/latest/Reference/Decorators/). - -If you're a bit confused about using `async/await` to write routes, you would -better take a look at [Promise resolution](https://fastify.dev/docs/latest/Reference/Routes/#promise-resolution) for more details. From c4b7cc92accf8d7f140afa45e97988a160f25e8d Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 14:55:58 +0800 Subject: [PATCH 04/18] docs: deduplicate docs --- README.md | 32 +++++--------------------------- docs/plugins.md | 2 +- docs/quickstart.md | 6 +----- docs/routes.md | 2 +- 4 files changed, 8 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index aa5cc6d..362e70f 100644 --- a/README.md +++ b/README.md @@ -2,36 +2,14 @@ A concise Fastify + TypeScript starter used by USThing backend services. This repository provides a minimal, well-tested scaffold with recommended scripts, linting, and CI configuration. -## Quickstart +## Quickstart & developer setup -Run the following to get started (single command block; brief comments explain each step): +See the detailed guides in `docs/`: -```bash -# Install dependencies -yarn install +- `docs/quickstart.md` — quick start commands and example requests +- `docs/dev-setup.md` — Corepack, Node setup, and developer tips -# Prepare Husky git hooks (if present) -yarn run prepare - -# Run in development (watch + fastify) -yarn run dev - -# Build TypeScript to `dist` -yarn run build - -# Start production server (uses `dist`) -yarn run start - -# Run tests -yarn run test -``` - -Note: this repository expects Yarn managed via Corepack. If Corepack is not enabled on your machine, enable it first: - -```bash -corepack enable -# after enabling, use `yarn ...` as usual (no need for `corepack` prefix) -``` +Note: this repository expects Yarn managed via Corepack. If Corepack is not enabled on your machine, enable it with `corepack enable`. ## Key scripts diff --git a/docs/plugins.md b/docs/plugins.md index a3bfed6..b8326da 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -38,4 +38,4 @@ See also: - Add a new plugin under `src/plugins/` and export it as a Fastify plugin (use `fastify-plugin` to expose decorators). - Keep plugin responsibilities narrow and reusable (auth, DB setup, metrics, tracing, etc.). -- Document plugin options and side effects in `docs/plugins.md` or inline plugin README comments. +- Document plugin options and side effects inline in the plugin and in `docs/plugins.md` when needed. diff --git a/docs/quickstart.md b/docs/quickstart.md index ef2cc98..30b1d33 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -7,11 +7,7 @@ This page expands the brief Quickstart in the project README. Keep this short an - Node.js >= 24 - Yarn 3+ (the repository uses Yarn; `npm` may also work but commands below use `yarn`) -This project expects Yarn managed via Corepack. On modern Node.js releases Corepack is included — enable it with: - -```bash -corepack enable -``` +Corepack / Node setup: see `docs/dev-setup.md` for enabling Corepack and node version manager tips. ## Install diff --git a/docs/routes.md b/docs/routes.md index 5b95a32..157292e 100644 --- a/docs/routes.md +++ b/docs/routes.md @@ -1,4 +1,4 @@ -# Routes and plugins (overview) +# Routes (overview) This file gives a short, human-oriented map of the routes and plugins in this template. Keep it brief — full API specs are generated from code (use CI to publish generated docs). From 6ab94cc48db1ce64185845fb3cb66849789d3e3c Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 15:26:39 +0800 Subject: [PATCH 05/18] docs: add testing, linting, and CI --- docs/ci.md | 11 ++++++++ docs/testing-and-linting.md | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 docs/ci.md create mode 100644 docs/testing-and-linting.md diff --git a/docs/ci.md b/docs/ci.md new file mode 100644 index 0000000..2b9b3c9 --- /dev/null +++ b/docs/ci.md @@ -0,0 +1,11 @@ +# CI workflows (overview) + +The repository uses GitHub Actions. The active workflows are in `.github/workflows/` — check those files for exact steps. High-level: + +- `check.yml` — runs lint, commitlint, and the test suite on pushes and PRs. +- `docker.yml` — builds and pushes container images for PRs and pushes. +- `release.yml` — run by `release-please` on `main` to automate releases and production image publishing. + +When a check fails, open the corresponding workflow run in GitHub (Actions tab) to see job logs. + +Avoid committing generated artifacts — have CI produce and publish them instead. diff --git a/docs/testing-and-linting.md b/docs/testing-and-linting.md new file mode 100644 index 0000000..4001c92 --- /dev/null +++ b/docs/testing-and-linting.md @@ -0,0 +1,53 @@ +# Testing & Linting + +This document covers how to run tests and linting locally for this project. + +## Run tests locally + +From the repository root: + +```bash +# install dependencies +yarn install + +# compile TypeScript +yarn run build + +# run tests +yarn run test +``` + +Notes + +- The `test` script compiles tests with `tsc -p test/tsconfig.json` and runs the compiled tests from `dist/test/` using Node's test runner. + +## Test structure + +- `test/` contains unit and integration tests and a `helper.ts` for shared utilities. +- Keep fixtures under `test/fixtures/` and helpers under `test/helpers/`. +- Prefer small, deterministic tests. Use environment flags (e.g. `AUTH_SKIP`) to avoid external dependencies in unit tests. + +## Linting and pre-commit + +Run lint locally: + +```bash +yarn run lint +``` + +To fix common lint issues: + +```bash +yarn run lint:fix +``` + +Husky may be configured to run checks on commit; run `yarn run prepare` to install hooks locally. + +## Troubleshooting + +- If TypeScript compilation for tests fails, run `tsc -p test/tsconfig.json` to inspect errors. +- If tests are slow or flaky, isolate and run them individually and add timeouts or mocks where appropriate. + +## Further reading + +- Node.js test runner: From e6938b323dd2b8554a6f84c05e6167bee3790897 Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 15:32:56 +0800 Subject: [PATCH 06/18] docs: add Docker and deployment --- docs/docker-and-deployment.md | 54 +++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 docs/docker-and-deployment.md diff --git a/docs/docker-and-deployment.md b/docs/docker-and-deployment.md new file mode 100644 index 0000000..a32429b --- /dev/null +++ b/docs/docker-and-deployment.md @@ -0,0 +1,54 @@ +# Docker & Deployment + +This guide explains how to build and run the project's Docker image and where CI builds/publishes images. + +## Provided Dockerfile + +A `Dockerfile` exists at the repository root. It is used by the CI workflow `.github/workflows/docker.yml` to build multi-tag images and push them to the configured registry (default: `ghcr.io`). + +## Local build & run + +Build the image locally (from repo root): + +```bash +# build +docker build -t template-api:local . + +# run (expose port 3000) +docker run --rm -p 3000:3000 --env-file .env example template-api:local +``` + +Replace `--env-file .env.example` with your `.env` file or explicit `-e` flags for required environment variables. + +## CI image publishing + +The repository's `docker.yml` workflow builds and pushes images to the registry. The workflow: + +- sets up QEMU and Buildx +- logs into the registry using the workflow token +- generates metadata tags (sha, branch/ref, test) +- builds and pushes the image(s) + +If you need to change the target registry or image name, update the `REGISTRY` and `IMAGE_NAME` environment variables in the workflow. + +## Deployment notes + +- Use environment variables (do not bake secrets into images). +- Prefer a runtime secret manager (Kubernetes Secrets, cloud secret manager) rather than `.env` in production. +- For Kubernetes, build image tags in CI (sha or semver) and deploy via your CD system pointing to those tags. + +## Debugging + +- To inspect a container locally: + +```bash +docker logs +docker exec -it /bin/sh +``` + +- If the app fails to start in the container, check the `NODE_ENV` and required env variables, and run the same start command from within the container to reproduce. + +## Further reading + +- Docker Docs: +- GitHub Actions docker/build-push-action: From 59ecb02939ab3d4646c08193e522d02b3381d31f Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 15:33:15 +0800 Subject: [PATCH 07/18] docs: fix typo --- docs/docker-and-deployment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docker-and-deployment.md b/docs/docker-and-deployment.md index a32429b..2f56e80 100644 --- a/docs/docker-and-deployment.md +++ b/docs/docker-and-deployment.md @@ -15,7 +15,7 @@ Build the image locally (from repo root): docker build -t template-api:local . # run (expose port 3000) -docker run --rm -p 3000:3000 --env-file .env example template-api:local +docker run --rm -p 3000:3000 --env-file .env.example template-api:local ``` Replace `--env-file .env.example` with your `.env` file or explicit `-e` flags for required environment variables. From 3bbb5e656ff33fb4d4390217dfdb6777ec1e083a Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 15:44:40 +0800 Subject: [PATCH 08/18] docs: improve `.env.example` and add env var docs --- .env.example | 19 ++++++++++++++++--- docs/env-vars.md | 29 +++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 docs/env-vars.md diff --git a/.env.example b/.env.example index d098d10..fb48752 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,21 @@ -# Description: Example of .env file +# Example .env file for local development and tests -# MongoDB URI +# MongoDB (optional) MONGO_URI=mongodb://localhost:27017/your-database-name -# Auth Plugin +# OpenID Connect (used by the auth plugin) +# AUTH_DISCOVERY_URL should point to the provider's discovery document (/.well-known/openid-configuration) AUTH_DISCOVERY_URL=https://login.microsoftonline.com/c917f3e2-9322-4926-9bb3-daca730413ca/v2.0/.well-known/openid-configuration AUTH_CLIENT_ID=b4bc4b9a-7162-44c5-bb50-fe935dce1f5a + +# When true, the auth plugin skips remote discovery and verification (useful for local testing) +AUTH_SKIP=true + +# Optional runtime controls +NODE_ENV=development +PORT=3000 + +# Test helpers (optional) +# Provide these only when running integration tests that require a real token/user. +TEST_AUTH_TOKEN= +TEST_AUTH_USER= diff --git a/docs/env-vars.md b/docs/env-vars.md new file mode 100644 index 0000000..5ec536e --- /dev/null +++ b/docs/env-vars.md @@ -0,0 +1,29 @@ +# Environment variables + +This project reads configuration from environment variables. A plain-text example file is provided at `.env.example` (copy it to `.env` for local development). + +Recommended variables: + +- MONGO_URI: MongoDB connection string (optional). +- AUTH_DISCOVERY_URL: OpenID Connect discovery URL (used by the auth plugin). +- AUTH_CLIENT_ID: OpenID Connect client id. +- AUTH_SKIP: When `true`, the auth plugin will skip external verification (useful for local tests). +- NODE_ENV: `development` / `production`. +- PORT: Port the Fastify server listens on (default 3000). + +Test helpers (optional): + +- TEST_AUTH_TOKEN: Bearer token used by integration tests (set only in CI or local secure env). +- TEST_AUTH_USER: Expected username for the test token. + +How to use + +Copy the example to a working `.env` file and modify values as needed: + +```bash +cp .env.example .env +``` + +Notes + +- Never commit real secrets. Use your cloud provider's secret manager or CI secrets for production deployments. From 97229002271fa8c459818d373613d7b69853e3c3 Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 16:02:10 +0800 Subject: [PATCH 09/18] docs: document `.env` ignore policy in `env-vars.md` --- docs/env-vars.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/env-vars.md b/docs/env-vars.md index 5ec536e..fee88a1 100644 --- a/docs/env-vars.md +++ b/docs/env-vars.md @@ -27,3 +27,4 @@ cp .env.example .env Notes - Never commit real secrets. Use your cloud provider's secret manager or CI secrets for production deployments. +- Git: the repository ignores any file starting with `.env` (for example `.env`, `.env.local`, `.env.development`) — only the `.env.example` file is tracked. This keeps local or sensitive environment files out of version control while providing an example to copy from. From b9feace9698822966a2f56709d2fd58255283cd7 Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 16:17:30 +0800 Subject: [PATCH 10/18] docs: format `CONTRIBUTING.md` --- CONTRIBUTING.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 17820df..bee104c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -64,16 +64,12 @@ During the PR review process, we make use of GitHub comments to track suggestion The general principles are the following: - If the comment is a change suggestion... - - - If it's clear and uncontroversial how to apply the suggestion, you should resolve the comment after you have made + - If it's clear and uncontroversial how to apply the suggestion, you should resolve the comment after you have made the corresponding changes to the PR. - - - If you are not 100% sure that you have applied the suggestion correctly, leave a comment asking it. Do not resolve + - If you are not 100% sure that you have applied the suggestion correctly, leave a comment asking it. Do not resolve the comment in this case. - - - If you don't fully understand or agree with the suggestion, reply to the comment with your questions and + - If you don't fully understand or agree with the suggestion, reply to the comment with your questions and rebuttals. Do not resolve the comment in this case. - - If the comment is a clarification request, answer it. Do not resolve the comment in this case. We will either come back with further questions or suggestions, or close the comment ourselves if we find your answer satisfactory. @@ -89,5 +85,3 @@ tests is a waste of time for everyone involved. During code review, it is not supposed to happen that we have to keep coming back to your PR, continually finding more problems more unpolished changes, and having to go through lots of back-and-forth interactions this way. This will only lead to growing frustration on both ends. - - From ef23851db20ae2a3d95c513dfc6fb121d067da52 Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 16:23:16 +0800 Subject: [PATCH 11/18] docs: edit `CONTRIBUTING.md` for wording --- CONTRIBUTING.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bee104c..8ed6f78 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,16 +1,15 @@ # How to Contribute -Thanks for reading this, because we really need everyone to follow some collaboration guidelines to make our codebase -maintainable, clean and concise. +Thanks for taking a moment to read this. Following these collaboration guidelines helps keep the codebase maintainable, +clean, and easy to review. The standard workflow to contribute to the project is as follows: 1. Create an issue to track the things (feature, bug or something else) you are working on. This also allows other contributors to know what you are working on, and to potentially offer suggestions or help. -2. On the right hand side of the issue page, there is a button that allows you to create a new branch for the issue. - This will automatically create a new branch with the issue number and title. I strongly recommend you to use this - feature instead of creating a branch manually, because it will make it easier to track the issue that you are working - on. +2. On the right hand side of an issue page there is a button to create a branch for that issue. It will create a branch + named from the issue number and title. We recommend using that feature (rather than creating branches manually) to + make it easier to track work against the originating issue. 3. Make your changes in the new branch. Ideally, your commit messages should follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. We will rebase your PR later if your commits are well-organized and the messages are well-formatted. Otherwise, we may ask you to fix them, @@ -34,8 +33,8 @@ but we will try our best to achieve the following goals: - Use iterative methods on collections instead of loops whenever possible. - Avoid side effects in a function as much as possible. -That's not only because functional programming is cool, but also because it reduces the complexity of the code, and -makes it easier to reason about the code. For example, you should _never_ do: +Apart from functional programming being cool, this reduces complexity and +makes code easier to reason about. For example, you should _avoid_: ```typescript const numbers = [1, 2, 3] @@ -82,6 +81,5 @@ Please make sure your code passes all automated CI tests (unless under special c You may trigger them by simply pushing your commits to a branch, or by opening a PR. Reviewing a PR that doesn't pass tests is a waste of time for everyone involved. -During code review, it is not supposed to happen that we have to keep coming back to your PR, continually finding more -problems more unpolished changes, and having to go through lots of back-and-forth interactions this way. This will only -lead to growing frustration on both ends. +During code review, please try to address issues thoroughly before requesting another round of review. This reduces +unnecessary back-and-forth and speeds up the process for everyone. From 521e57a3688987f11e0712b12a32cb68dcaea0e3 Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 18 Jan 2026 17:37:53 +0800 Subject: [PATCH 12/18] docs: add release automation docs --- docs/release.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 docs/release.md diff --git a/docs/release.md b/docs/release.md new file mode 100644 index 0000000..6749bd1 --- /dev/null +++ b/docs/release.md @@ -0,0 +1,12 @@ +# Release automation (summary) + +Releases are produced by `googleapis/release-please-action` in `.github/workflows/release.yml`. + +- Trigger: push to `main`. +- Behavior: `googleapis/release-please-action` parses Conventional Commits and will open/update Release PRs or create a release when appropriate; it also generates/updates the changelog (`CHANGELOG.md`) and exposes outputs such as `release_created`, `major`, `minor`, `patch`, `tag_name`, and `body`. +- CI integration: the workflow uses those outputs to tag versions and to build/push container images (see the repo's workflow for the exact steps). + +## Notes for maintainers + +- Review the draft release or Release PR produced by the action, add concise highlights or migration notes, then publish/merge. +- Do not commit a handwritten `CHANGELOG.md` to the repository; rely on per-release notes generated by the action. From 752a14eca9150c6e15e5d479bed4b4b91c170937 Mon Sep 17 00:00:00 2001 From: William So Date: Mon, 19 Jan 2026 18:15:41 +0800 Subject: [PATCH 13/18] docs(ci): document reusable workflows and hosted-first self-hosted fallback (PR #48) --- docs/ci.md | 16 +++++++++++----- docs/docker-and-deployment.md | 8 +++++--- docs/release.md | 7 ++++--- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/docs/ci.md b/docs/ci.md index 2b9b3c9..39853bf 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -1,11 +1,17 @@ # CI workflows (overview) -The repository uses GitHub Actions. The active workflows are in `.github/workflows/` — check those files for exact steps. High-level: +The repository uses GitHub Actions. The active workflows live in `.github/workflows/` — check those files for exact steps. Recent CI changes extract common logic into reusable workflows to allow a hosted-first runner strategy with a self-hosted fallback. High-level: -- `check.yml` — runs lint, commitlint, and the test suite on pushes and PRs. -- `docker.yml` — builds and pushes container images for PRs and pushes. -- `release.yml` — run by `release-please` on `main` to automate releases and production image publishing. +- `check.yml` — top-level caller that invokes the reusable workflow in `check-reusable.yml`; runs lint, commitlint, and the test suite on pushes and PRs. The caller prefers GitHub-hosted runners and will fall back to a self-hosted runner only if the hosted job fails. +- `docker.yml` — top-level caller that invokes `docker-reusable.yml` to build and push container images. +- `release.yml` — caller for `release-reusable.yml`; invoked by `release-please` on `main` to automate releases and image publishing. -When a check fails, open the corresponding workflow run in GitHub (Actions tab) to see job logs. +Key notes about the hosted-first / self-hosted fallback: + +- The top-level workflow will try a hosted runner first and, if that job fails, run a fallback job targeting `self-hosted` runners. This improves reliability when hosted runners are unavailable or hit capacity. +- The fallback uses a `failure()` condition so it only runs when the primary (hosted) job fails; this can cause duplicated checks to appear in the PR UI and may show cosmetic failures for the fallback run — this is expected and documented in the workflow comments. +- `continue_on_error` is exposed as an input and applied at the reusable workflow job level when requested. + +When a check fails, open the corresponding workflow run in GitHub (Actions tab) to see job logs. Prefer inspecting the primary (hosted) job logs first. Avoid committing generated artifacts — have CI produce and publish them instead. diff --git a/docs/docker-and-deployment.md b/docs/docker-and-deployment.md index 2f56e80..e455e81 100644 --- a/docs/docker-and-deployment.md +++ b/docs/docker-and-deployment.md @@ -1,10 +1,11 @@ # Docker & Deployment + This guide explains how to build and run the project's Docker image and where CI builds/publishes images. ## Provided Dockerfile -A `Dockerfile` exists at the repository root. It is used by the CI workflow `.github/workflows/docker.yml` to build multi-tag images and push them to the configured registry (default: `ghcr.io`). +A `Dockerfile` exists at the repository root. CI image build/publish logic has been extracted into a reusable workflow (`.github/workflows/docker-reusable.yml`) and is invoked by a small top-level caller (`.github/workflows/docker.yml`) that prefers hosted runners and falls back to `self-hosted` when the hosted job fails. ## Local build & run @@ -22,14 +23,15 @@ Replace `--env-file .env.example` with your `.env` file or explicit `-e` flags f ## CI image publishing -The repository's `docker.yml` workflow builds and pushes images to the registry. The workflow: + +The repository's `docker.yml` top-level caller invokes the reusable workflow to build and push images to the registry. The reusable workflow: - sets up QEMU and Buildx - logs into the registry using the workflow token - generates metadata tags (sha, branch/ref, test) - builds and pushes the image(s) -If you need to change the target registry or image name, update the `REGISTRY` and `IMAGE_NAME` environment variables in the workflow. +If you need to change the target registry or image name, update the `REGISTRY` and `IMAGE_NAME` environment variables in the reusable workflow or the top-level caller as appropriate. ## Deployment notes diff --git a/docs/release.md b/docs/release.md index 6749bd1..e0944ee 100644 --- a/docs/release.md +++ b/docs/release.md @@ -1,10 +1,11 @@ # Release automation (summary) -Releases are produced by `googleapis/release-please-action` in `.github/workflows/release.yml`. -- Trigger: push to `main`. +Releases are produced by `googleapis/release-please-action`. The release workflow now uses a reusable workflow (`.github/workflows/release-reusable.yml`) and a small top-level caller (`.github/workflows/release.yml`) that prefers GitHub-hosted runners and falls back to a `self-hosted` runner when necessary. + +- Trigger: push to `main` (via `release-please` outputs). - Behavior: `googleapis/release-please-action` parses Conventional Commits and will open/update Release PRs or create a release when appropriate; it also generates/updates the changelog (`CHANGELOG.md`) and exposes outputs such as `release_created`, `major`, `minor`, `patch`, `tag_name`, and `body`. -- CI integration: the workflow uses those outputs to tag versions and to build/push container images (see the repo's workflow for the exact steps). +- CI integration: the reusable workflow consumes those outputs to tag versions and to build/push container images (see the repository workflows for exact steps). The hosted-first / self-hosted fallback may cause duplicate PR checks to appear when the fallback runs — this is cosmetic. ## Notes for maintainers From aa5582589256884f6f5f00f521a31c36b6150db5 Mon Sep 17 00:00:00 2001 From: William So Date: Wed, 21 Jan 2026 11:20:41 +0800 Subject: [PATCH 14/18] =?UTF-8?q?docs(ci):=20update=20workflow=20docs=20fo?= =?UTF-8?q?r=20shared-step=20try=E2=86=92fallback=20pattern=20and=20runner?= =?UTF-8?q?=20defaults?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ci.md | 16 ++++++++-------- docs/docker-and-deployment.md | 10 +++++----- docs/release.md | 7 +++---- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/docs/ci.md b/docs/ci.md index 39853bf..07c6161 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -1,16 +1,16 @@ # CI workflows (overview) -The repository uses GitHub Actions. The active workflows live in `.github/workflows/` — check those files for exact steps. Recent CI changes extract common logic into reusable workflows to allow a hosted-first runner strategy with a self-hosted fallback. High-level: +The repository uses GitHub Actions. The active workflows live in `.github/workflows/` — check those files for exact steps. CI logic has been refactored into local shared-step workflows (named `*-shared-steps.yml`) that are invoked via `workflow_call` by small top-level callers. This implements a hosted-first → self-hosted fallback pattern. -- `check.yml` — top-level caller that invokes the reusable workflow in `check-reusable.yml`; runs lint, commitlint, and the test suite on pushes and PRs. The caller prefers GitHub-hosted runners and will fall back to a self-hosted runner only if the hosted job fails. -- `docker.yml` — top-level caller that invokes `docker-reusable.yml` to build and push container images. -- `release.yml` — caller for `release-reusable.yml`; invoked by `release-please` on `main` to automate releases and image publishing. +- `check.yml` — top-level caller that invokes `.github/workflows/check-shared-steps.yml` and runs lint, commitlint, and the test suite on pushes and PRs. The caller uses `ubuntu-22.04` for the primary try job and falls back to `self-hosted` only when the try job fails. +- `docker.yml` — caller that invokes `.github/workflows/docker-shared-steps.yml` to build and push container images (primary: `ubuntu-latest`, fallback: `self-hosted`). +- `release.yml` — caller that invokes `.github/workflows/release-shared-steps.yml` (primary: `ubuntu-latest`, fallback: `self-hosted`). -Key notes about the hosted-first / self-hosted fallback: +Notes about the shared-step / fallback pattern: -- The top-level workflow will try a hosted runner first and, if that job fails, run a fallback job targeting `self-hosted` runners. This improves reliability when hosted runners are unavailable or hit capacity. -- The fallback uses a `failure()` condition so it only runs when the primary (hosted) job fails; this can cause duplicated checks to appear in the PR UI and may show cosmetic failures for the fallback run — this is expected and documented in the workflow comments. -- `continue_on_error` is exposed as an input and applied at the reusable workflow job level when requested. +- The shared-step files are internal to this repository (named `*-shared-steps.yml`) and are not intended as cross-repo reusable workflows; they expose inputs such as `runs_on` and `continue_on_error` to the caller. +- Each top-level caller runs a primary job on a hosted runner and conditionally runs a fallback job on `self-hosted` using `if: ${{ failure() }}`. This makes CI more resilient but can cause duplicated or expanded sections in the GitHub PR UI when the fallback executes — this is cosmetic and documented in the workflow comments. +- `continue_on_error` is passed from the caller into the shared-step workflow and applied at the job level inside the shared workflow. When a check fails, open the corresponding workflow run in GitHub (Actions tab) to see job logs. Prefer inspecting the primary (hosted) job logs first. diff --git a/docs/docker-and-deployment.md b/docs/docker-and-deployment.md index e455e81..8579214 100644 --- a/docs/docker-and-deployment.md +++ b/docs/docker-and-deployment.md @@ -1,11 +1,10 @@ # Docker & Deployment - This guide explains how to build and run the project's Docker image and where CI builds/publishes images. ## Provided Dockerfile -A `Dockerfile` exists at the repository root. CI image build/publish logic has been extracted into a reusable workflow (`.github/workflows/docker-reusable.yml`) and is invoked by a small top-level caller (`.github/workflows/docker.yml`) that prefers hosted runners and falls back to `self-hosted` when the hosted job fails. +A `Dockerfile` exists at the repository root. CI image build/publish logic has been extracted into an internal shared-step workflow (`.github/workflows/docker-shared-steps.yml`) and is invoked by a small top-level caller (`.github/workflows/docker.yml`) that prefers hosted runners and falls back to `self-hosted` when the hosted job fails. ## Local build & run @@ -23,15 +22,16 @@ Replace `--env-file .env.example` with your `.env` file or explicit `-e` flags f ## CI image publishing - -The repository's `docker.yml` top-level caller invokes the reusable workflow to build and push images to the registry. The reusable workflow: +The repository's `docker.yml` top-level caller invokes the internal shared-step workflow to build and push images to the registry. The shared-step workflow: - sets up QEMU and Buildx - logs into the registry using the workflow token - generates metadata tags (sha, branch/ref, test) - builds and pushes the image(s) -If you need to change the target registry or image name, update the `REGISTRY` and `IMAGE_NAME` environment variables in the reusable workflow or the top-level caller as appropriate. +If you need to change the target registry or image name, update the `REGISTRY` and `IMAGE_NAME` environment variables in the shared-step workflow or the top-level caller as appropriate. + +Note: the top-level caller uses `ubuntu-latest` for the primary try job; when that job fails the fallback runs on `self-hosted`. This is intended to improve reliability while keeping hosted runner usage first. ## Deployment notes diff --git a/docs/release.md b/docs/release.md index e0944ee..08b00b8 100644 --- a/docs/release.md +++ b/docs/release.md @@ -1,11 +1,10 @@ # Release automation (summary) +Releases are produced by `googleapis/release-please-action`. The release workflow has been refactored so release steps are defined in `.github/workflows/release-shared-steps.yml` and invoked by a small top-level caller (`.github/workflows/release.yml`) which prefers hosted runners and falls back to `self-hosted` when the top-level try job fails. -Releases are produced by `googleapis/release-please-action`. The release workflow now uses a reusable workflow (`.github/workflows/release-reusable.yml`) and a small top-level caller (`.github/workflows/release.yml`) that prefers GitHub-hosted runners and falls back to a `self-hosted` runner when necessary. - -- Trigger: push to `main` (via `release-please` outputs). +- Trigger: push to `main`. - Behavior: `googleapis/release-please-action` parses Conventional Commits and will open/update Release PRs or create a release when appropriate; it also generates/updates the changelog (`CHANGELOG.md`) and exposes outputs such as `release_created`, `major`, `minor`, `patch`, `tag_name`, and `body`. -- CI integration: the reusable workflow consumes those outputs to tag versions and to build/push container images (see the repository workflows for exact steps). The hosted-first / self-hosted fallback may cause duplicate PR checks to appear when the fallback runs — this is cosmetic. +- CI integration: the shared-step workflow consumes those outputs to tag versions and to build/push container images (see the repository workflows for exact steps). The hosted-first / self-hosted fallback may cause duplicate PR checks to appear when the fallback runs — this is cosmetic. ## Notes for maintainers From 78a26d15eb3457f29bec15cce433757f93c421f8 Mon Sep 17 00:00:00 2001 From: William So Date: Wed, 21 Jan 2026 21:59:46 +0800 Subject: [PATCH 15/18] docs(ci): update workflow docs - detect-quota, hosted-first fallback, docker metadata, release-please behavior --- docs/ci.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/ci.md b/docs/ci.md index 07c6161..841b327 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -1,17 +1,16 @@ -# CI workflows (overview) +# CI workflows -The repository uses GitHub Actions. The active workflows live in `.github/workflows/` — check those files for exact steps. CI logic has been refactored into local shared-step workflows (named `*-shared-steps.yml`) that are invoked via `workflow_call` by small top-level callers. This implements a hosted-first → self-hosted fallback pattern. +The repository uses three primary GitHub Actions workflows in `.github/workflows/`: -- `check.yml` — top-level caller that invokes `.github/workflows/check-shared-steps.yml` and runs lint, commitlint, and the test suite on pushes and PRs. The caller uses `ubuntu-22.04` for the primary try job and falls back to `self-hosted` only when the try job fails. -- `docker.yml` — caller that invokes `.github/workflows/docker-shared-steps.yml` to build and push container images (primary: `ubuntu-latest`, fallback: `self-hosted`). -- `release.yml` — caller that invokes `.github/workflows/release-shared-steps.yml` (primary: `ubuntu-latest`, fallback: `self-hosted`). +- `check.yml` — runs on push and pull_request. It probes runner availability (a small `detect-quota` job) and then runs ESLint, commitlint, and tests. Each job uses a hosted-first → self-hosted fallback by selecting `runs-on` based on the probe result. +- `docker.yml` — builds and pushes container images (Buildx). It also probes runner availability and uses a hosted-first fallback. The workflow prepares Docker metadata (tags include sha, branch/ref, and PR tags) and pushes images to `REGISTRY`/`IMAGE_NAME`. +- `release.yml` — runs `googleapis/release-please-action@v4` on pushes to `main`. When a release is created the workflow tags versions and (optionally) builds/pushes images. See `release.yml` for the exact tagging and build steps. -Notes about the shared-step / fallback pattern: +## Key notes -- The shared-step files are internal to this repository (named `*-shared-steps.yml`) and are not intended as cross-repo reusable workflows; they expose inputs such as `runs_on` and `continue_on_error` to the caller. -- Each top-level caller runs a primary job on a hosted runner and conditionally runs a fallback job on `self-hosted` using `if: ${{ failure() }}`. This makes CI more resilient but can cause duplicated or expanded sections in the GitHub PR UI when the fallback executes — this is cosmetic and documented in the workflow comments. -- `continue_on_error` is passed from the caller into the shared-step workflow and applied at the job level inside the shared workflow. +- Hosted-first fallback: jobs use a small probe job (`detect-quota`) and set `runs-on` dynamically so CI prefers `ubuntu-latest` but can fall back to `self-hosted` when needed. +- Docker workflow permissions: the docker workflow requests permissions to push packages and to request an `id-token` for registry login; it logs into the registry using the workflow token by default. +- Release workflow: `release-please` creates release PRs or releases and exposes outputs such as `release_created`, `major`, `minor`, `patch`, `tag_name`, and `body` that downstream steps use. +- Tokens: the action uses the default `GITHUB_TOKEN` unless configured to use a PAT; if you need CI checks to run on Release PRs, configure a PAT as described in the action docs. -When a check fails, open the corresponding workflow run in GitHub (Actions tab) to see job logs. Prefer inspecting the primary (hosted) job logs first. - -Avoid committing generated artifacts — have CI produce and publish them instead. +If a run fails, open the workflow run in GitHub Actions and inspect the primary (hosted) job logs first. Avoid committing generated artifacts; let CI produce and publish them. From 68fd3e0a6603780de7d02edd813c53835370e1ee Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 25 Jan 2026 12:03:17 +0800 Subject: [PATCH 16/18] docs(ci): add TypeDoc generation and publishing; update README, .gitignore, workflows --- .github/workflows/docs.yml | 39 ++++++++++ .gitignore | 4 + README.md | 60 +++++++++----- package.json | 5 +- scripts/clean-docs.js | 16 ++++ typedoc.json | 13 ++++ yarn.lock | 156 ++++++++++++++++++++++++++++++++++++- 7 files changed, 270 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 scripts/clean-docs.js create mode 100644 typedoc.json diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..db4ed16 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,39 @@ +name: docs + +on: + push: + branches: + - main + workflow_dispatch: {} + +permissions: + contents: read + pages: write + id-token: write + +jobs: + build-and-publish: + runs-on: ubuntu-slim + steps: + - uses: actions/checkout@v4 + - name: Use Node + uses: actions/setup-node@v4 + with: + node-version: "24" + cache: "yarn" + - name: Install dependencies + run: yarn install --frozen-lockfile + - name: Build project + run: yarn build + - name: Generate TypeDoc + run: yarn docs:typedoc + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: api-docs + path: docs/api + - name: Publish to GitHub Pages + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs/api diff --git a/.gitignore b/.gitignore index 67f48cf..3f1c7de 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,7 @@ dist !.yarn/releases !.yarn/sdks !.yarn/versions + +# Generated TypeDoc output (do not commit generated API docs) +docs/api/ +docs/api/** diff --git a/README.md b/README.md index 362e70f..09625ef 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,46 @@ -# USThing Template API +# template-api + + +[![CI](https://github.com/USThing/template-api/actions/workflows/check.yml/badge.svg)](https://github.com/USThing/template-api/actions/workflows/check.yml) [![Docs](https://github.com/USThing/template-api/actions/workflows/docs-publish.yml/badge.svg)](https://github.com/USThing/template-api/actions/workflows/docs-publish.yml) [![Release](https://github.com/USThing/template-api/actions/workflows/release.yml/badge.svg)](https://github.com/USThing/template-api/actions/workflows/release.yml) [![Docs site](https://img.shields.io/badge/docs-site-blue)](./docs/api/index.html) A concise Fastify + TypeScript starter used by USThing backend services. This repository provides a minimal, well-tested scaffold with recommended scripts, linting, and CI configuration. -## Quickstart & developer setup +## Prerequisites + +- Node.js (see `engines` in `package.json`) +- Yarn via Corepack + +Enable Corepack (recommended) and the Yarn version used by this repo: + +```bash +corepack enable +corepack prepare yarn@stable --activate +``` + +## Quickstart (local) -See the detailed guides in `docs/`: +```bash +corepack enable +yarn install +yarn build +yarn start +``` -- `docs/quickstart.md` — quick start commands and example requests -- `docs/dev-setup.md` — Corepack, Node setup, and developer tips +## Developer workflow -Note: this repository expects Yarn managed via Corepack. If Corepack is not enabled on your machine, enable it with `corepack enable`. +- Start dev mode (watch + Fastify): `yarn dev` +- Run tests: `yarn test` +- Lint: `yarn lint` (fix: `yarn lint:fix`) -## Key scripts +## Automatic API docs -- `dev` — start in development (watch + fastify) -- `build` — compile TypeScript -- `start` — run production server (from `dist`) -- `test` — build and run tests -- `lint`, `lint:fix` — ESLint checks and fixes -- `commitlint` — validate commit messages +API docs are generated from source by TypeDoc and published by CI. To generate locally: + +```bash +yarn docs:typedoc +``` + +Generated docs are placed under `docs/api` (CI publishes these artifacts — do not commit generated files). ## Project layout @@ -26,20 +48,16 @@ Note: this repository expects Yarn managed via Corepack. If Corepack is not enab - `src/app.ts` — Fastify app and plugin registration - `routes/` — route modules - `test/` — tests and helpers -- `docs/` — human-authored docs (Quickstart, guides, migration) -- `.env.example` — example env variables - -## Docs and API reference - -Human-facing guides belong in `docs/`. API specs (generated from code via Fastify+Swagger or TypeDoc) should be produced by CI and published to your docs site rather than frequently committing generated files. +- `docs/` — human-authored guides and docs +- `.env.example` — example environment variables ## Environment -See `.env.example` for application-level variables. Fastify CLI options are documented at the `fastify-cli` project. +Tests and some dev helpers reference `TEST_AUTH_TOKEN` / `TEST_AUTH_USER`. See `docs/env-vars.md` for recommended env variables and CI secret usage. Keep secrets out of the repo and use your CI's secret manager. ## Contributing -Please follow `CONTRIBUTING.md`. Use the configured commitlint rules and run lint/tests before opening a PR. +Follow `CONTRIBUTING.md` (commitlint, lint, tests). The project uses Conventional Commits for releases. ## Support diff --git a/package.json b/package.json index 1d436c2..23eb2db 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,9 @@ "lint": "eslint", "lint:fix": "eslint --fix", "commitlint": "commitlint --last --strict --verbose", - "prepare": "husky" + "prepare": "husky", + "docs:typedoc": "typedoc --options typedoc.json", + "docs:clean": "node ./scripts/clean-docs.js" }, "engines": { "node": ">= 24" @@ -60,6 +62,7 @@ "husky": "^9.1.7", "prettier": "^3.7.4", "prettier-plugin-jsdoc": "^1.7.0", + "typedoc": "^0.28.16", "typescript": "^5.9.3", "typescript-eslint": "^8.48.1" }, diff --git a/scripts/clean-docs.js b/scripts/clean-docs.js new file mode 100644 index 0000000..f2b64a3 --- /dev/null +++ b/scripts/clean-docs.js @@ -0,0 +1,16 @@ +import { rm } from "fs/promises"; + +async function main() { + try { + await rm(new URL("../docs/api", import.meta.url), { + recursive: true, + force: true, + }); + console.log("docs/api removed"); + } catch (err) { + console.error("failed to remove docs/api:", err); + process.exit(1); + } +} + +main(); diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 0000000..75da7d4 --- /dev/null +++ b/typedoc.json @@ -0,0 +1,13 @@ +{ + "entryPointStrategy": "expand", + "entryPoints": [ + "src" + ], + "exclude": [ + "**/test/**", + "**/__tests__/**" + ], + "hideGenerator": true, + "out": "docs/api", + "tsconfig": "tsconfig.json" +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 79913db..57ecf96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -576,6 +576,19 @@ __metadata: languageName: node linkType: hard +"@gerrit0/mini-shiki@npm:^3.17.0": + version: 3.21.0 + resolution: "@gerrit0/mini-shiki@npm:3.21.0" + dependencies: + "@shikijs/engine-oniguruma": "npm:^3.21.0" + "@shikijs/langs": "npm:^3.21.0" + "@shikijs/themes": "npm:^3.21.0" + "@shikijs/types": "npm:^3.21.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + checksum: 10c0/4045d19854abfa4515381a04af07096c1de07471b029ee090375652d0199ed3fed6165a22bd9f8e8250c609124d8c05f5d4604eb6de87cf13513aa89cfb8d14e + languageName: node + linkType: hard + "@humanfs/core@npm:^0.19.1": version: 0.19.1 resolution: "@humanfs/core@npm:0.19.1" @@ -785,6 +798,51 @@ __metadata: languageName: node linkType: hard +"@shikijs/engine-oniguruma@npm:^3.21.0": + version: 3.21.0 + resolution: "@shikijs/engine-oniguruma@npm:3.21.0" + dependencies: + "@shikijs/types": "npm:3.21.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + checksum: 10c0/cb17c034b04e1333f90f267081b7fac0b53e56031f7d067723363a72cdbdf79e567dea216bbcae38a6d4b910570c2dd60a953ca941f4834768c0bb721131af5f + languageName: node + linkType: hard + +"@shikijs/langs@npm:^3.21.0": + version: 3.21.0 + resolution: "@shikijs/langs@npm:3.21.0" + dependencies: + "@shikijs/types": "npm:3.21.0" + checksum: 10c0/79cfc2b8ac1f5c938bfb18db6233f86ca96948970068c2cc94559e30abac2036c35a2ae52015d07f72b6decfd6b2ae86321f9547ae0f994b6131e362781fbf1f + languageName: node + linkType: hard + +"@shikijs/themes@npm:^3.21.0": + version: 3.21.0 + resolution: "@shikijs/themes@npm:3.21.0" + dependencies: + "@shikijs/types": "npm:3.21.0" + checksum: 10c0/f128a874231d84d93e16f347557e844c2b6493b41196b52e36a79874598abe2dbf3ee981dfe52dd09f8d7e21ed4ff41ab03c28de7a21313d9a0b691fbd3690c0 + languageName: node + linkType: hard + +"@shikijs/types@npm:3.21.0, @shikijs/types@npm:^3.21.0": + version: 3.21.0 + resolution: "@shikijs/types@npm:3.21.0" + dependencies: + "@shikijs/vscode-textmate": "npm:^10.0.2" + "@types/hast": "npm:^3.0.4" + checksum: 10c0/a86038c7ad10bb8104ea07cfa0dddf1e0646cf3b70a382978939c6144b21e5891395f5e705b7393476320f6196d86c6d8cd7ad6b3e1b356eb6a7e40c298c98f3 + languageName: node + linkType: hard + +"@shikijs/vscode-textmate@npm:^10.0.2": + version: 10.0.2 + resolution: "@shikijs/vscode-textmate@npm:10.0.2" + checksum: 10c0/36b682d691088ec244de292dc8f91b808f95c89466af421cf84cbab92230f03c8348649c14b3251991b10ce632b0c715e416e992dd5f28ff3221dc2693fd9462 + languageName: node + linkType: hard + "@sinclair/typebox@npm:^0.34.41": version: 0.34.41 resolution: "@sinclair/typebox@npm:0.34.41" @@ -886,6 +944,15 @@ __metadata: languageName: node linkType: hard +"@types/hast@npm:^3.0.4": + version: 3.0.4 + resolution: "@types/hast@npm:3.0.4" + dependencies: + "@types/unist": "npm:*" + checksum: 10c0/3249781a511b38f1d330fd1e3344eed3c4e7ea8eff82e835d35da78e637480d36fad37a78be5a7aed8465d237ad0446abc1150859d0fde395354ea634decf9f7 + languageName: node + linkType: hard + "@types/http-errors@npm:*": version: 2.0.5 resolution: "@types/http-errors@npm:2.0.5" @@ -1730,6 +1797,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^4.4.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250 + languageName: node + linkType: hard + "env-paths@npm:^2.2.1": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -2789,6 +2863,15 @@ __metadata: languageName: node linkType: hard +"linkify-it@npm:^5.0.0": + version: 5.0.0 + resolution: "linkify-it@npm:5.0.0" + dependencies: + uc.micro: "npm:^2.0.0" + checksum: 10c0/ff4abbcdfa2003472fc3eb4b8e60905ec97718e11e33cca52059919a4c80cc0e0c2a14d23e23d8c00e5402bc5a885cdba8ca053a11483ab3cc8b3c7a52f88e2d + languageName: node + linkType: hard + "locate-path@npm:^3.0.0": version: 3.0.0 resolution: "locate-path@npm:3.0.0" @@ -2962,6 +3045,13 @@ __metadata: languageName: node linkType: hard +"lunr@npm:^2.3.9": + version: 2.3.9 + resolution: "lunr@npm:2.3.9" + checksum: 10c0/77d7dbb4fbd602aac161e2b50887d8eda28c0fa3b799159cee380fbb311f1e614219126ecbbd2c3a9c685f1720a8109b3c1ca85cc893c39b6c9cc6a62a1d8a8b + languageName: node + linkType: hard + "makeerror@npm:1.0.12": version: 1.0.12 resolution: "makeerror@npm:1.0.12" @@ -2971,6 +3061,22 @@ __metadata: languageName: node linkType: hard +"markdown-it@npm:^14.1.0": + version: 14.1.0 + resolution: "markdown-it@npm:14.1.0" + dependencies: + argparse: "npm:^2.0.1" + entities: "npm:^4.4.0" + linkify-it: "npm:^5.0.0" + mdurl: "npm:^2.0.0" + punycode.js: "npm:^2.3.1" + uc.micro: "npm:^2.1.0" + bin: + markdown-it: bin/markdown-it.mjs + checksum: 10c0/9a6bb444181d2db7016a4173ae56a95a62c84d4cbfb6916a399b11d3e6581bf1cc2e4e1d07a2f022ae72c25f56db90fbe1e529fca16fbf9541659dc53480d4b4 + languageName: node + linkType: hard + "mdast-util-from-markdown@npm:^2.0.0": version: 2.0.1 resolution: "mdast-util-from-markdown@npm:2.0.1" @@ -3000,6 +3106,13 @@ __metadata: languageName: node linkType: hard +"mdurl@npm:^2.0.0": + version: 2.0.0 + resolution: "mdurl@npm:2.0.0" + checksum: 10c0/633db522272f75ce4788440669137c77540d74a83e9015666a9557a152c02e245b192edc20bc90ae953bbab727503994a53b236b4d9c99bdaee594d0e7dd2ce0 + languageName: node + linkType: hard + "media-typer@npm:^1.1.0": version: 1.1.0 resolution: "media-typer@npm:1.1.0" @@ -3300,7 +3413,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.4": +"minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -3820,6 +3933,13 @@ __metadata: languageName: node linkType: hard +"punycode.js@npm:^2.3.1": + version: 2.3.1 + resolution: "punycode.js@npm:2.3.1" + checksum: 10c0/1d12c1c0e06127fa5db56bd7fdf698daf9a78104456a6b67326877afc21feaa821257b171539caedd2f0524027fa38e67b13dd094159c8d70b6d26d2bea4dfdb + languageName: node + linkType: hard + "punycode@npm:^2.1.0, punycode@npm:^2.3.0": version: 2.3.1 resolution: "punycode@npm:2.3.1" @@ -4194,6 +4314,7 @@ __metadata: openid-client: "npm:^6.8.1" prettier: "npm:^3.7.4" prettier-plugin-jsdoc: "npm:^1.7.0" + typedoc: "npm:^0.28.16" typescript: "npm:^5.9.3" typescript-eslint: "npm:^8.48.1" languageName: unknown @@ -4323,6 +4444,23 @@ __metadata: languageName: node linkType: hard +"typedoc@npm:^0.28.16": + version: 0.28.16 + resolution: "typedoc@npm:0.28.16" + dependencies: + "@gerrit0/mini-shiki": "npm:^3.17.0" + lunr: "npm:^2.3.9" + markdown-it: "npm:^14.1.0" + minimatch: "npm:^9.0.5" + yaml: "npm:^2.8.1" + peerDependencies: + typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x + bin: + typedoc: bin/typedoc + checksum: 10c0/ae444913068088e88be6319a017a3a18f69cbd91dbb5b959fbdd0cf87d1a2a07f3a0d4ab29c957a83dd72808ff35bdd6ceec3ad1803fa412ddceffb78fa60ebb + languageName: node + linkType: hard + "typescript-eslint@npm:^8.48.1": version: 8.48.1 resolution: "typescript-eslint@npm:8.48.1" @@ -4358,6 +4496,13 @@ __metadata: languageName: node linkType: hard +"uc.micro@npm:^2.0.0, uc.micro@npm:^2.1.0": + version: 2.1.0 + resolution: "uc.micro@npm:2.1.0" + checksum: 10c0/8862eddb412dda76f15db8ad1c640ccc2f47cdf8252a4a30be908d535602c8d33f9855dfcccb8b8837855c1ce1eaa563f7fa7ebe3c98fd0794351aab9b9c55fa + languageName: node + linkType: hard + "undici-types@npm:~6.21.0": version: 6.21.0 resolution: "undici-types@npm:6.21.0" @@ -4516,6 +4661,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.8.1": + version: 2.8.2 + resolution: "yaml@npm:2.8.2" + bin: + yaml: bin.mjs + checksum: 10c0/703e4dc1e34b324aa66876d63618dcacb9ed49f7e7fe9b70f1e703645be8d640f68ab84f12b86df8ac960bac37acf5513e115de7c970940617ce0343c8c9cd96 + languageName: node + linkType: hard + "yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" From a587459f7a4217ee535092eaffa25cae3135549e Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 25 Jan 2026 13:25:13 +0800 Subject: [PATCH 17/18] docs(ci): add docs-publish workflow; generate & publish TypeDoc; update README and .gitignore --- .github/workflows/docs-publish.yml | 59 ++++++++++++++++++++++++++++++ .github/workflows/docs.yml | 28 ++++++++------ 2 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/docs-publish.yml diff --git a/.github/workflows/docs-publish.yml b/.github/workflows/docs-publish.yml new file mode 100644 index 0000000..3153e44 --- /dev/null +++ b/.github/workflows/docs-publish.yml @@ -0,0 +1,59 @@ +name: docs:publish + +on: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +jobs: + detect-quota: + # Probe the hosted runner so we can decide whether to use hosted or self-hosted. + runs-on: ubuntu-slim + steps: + - name: Quota probe + id: quota_probe + run: | + echo "probe" + + build-and-publish: + needs: detect-quota + # NOTE: do not set continue-on-error on detect-quota (see docs) + runs-on: ${{ needs.detect-quota.result == 'success' && 'ubuntu-slim' || 'self-hosted' }} + steps: + - uses: actions/checkout@v4 + + - name: Use Node + uses: actions/setup-node@v4 + with: + node-version: "24" + cache: "yarn" + + - name: Install dependencies (Corepack + Yarn) + run: | + corepack enable + corepack prepare yarn@stable --activate + corepack yarn install --frozen-lockfile + + - name: Build project + run: corepack yarn build + + - name: Generate TypeDoc + run: corepack yarn docs:typedoc + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: api-docs + path: docs/api + + - name: Publish to GitHub Pages + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs/api diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index db4ed16..2737015 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -2,18 +2,29 @@ name: docs on: push: - branches: - - main - workflow_dispatch: {} + pull_request: + workflow_dispatch: permissions: contents: read - pages: write - id-token: write jobs: - build-and-publish: + detect-quota: + # Probe the hosted runner so we can decide whether to use a hosted + # runner or fall back to self-hosted. The job should fail if quota is exhausted. runs-on: ubuntu-slim + steps: + - name: Quota probe + id: quota_probe + run: | + echo "probe" + + build: + needs: detect-quota + # NOTE: Do not set `continue-on-error: true` on the `detect-quota` job. + # If `continue-on-error` is enabled the job result will always be + # 'success', which defeats detection (we rely on `needs.detect-quota.result`). + runs-on: ${{ needs.detect-quota.result == 'success' && 'ubuntu-slim' || 'self-hosted' }} steps: - uses: actions/checkout@v4 - name: Use Node @@ -32,8 +43,3 @@ jobs: with: name: api-docs path: docs/api - - name: Publish to GitHub Pages - uses: peaceiris/actions-gh-pages@v4 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/api From 615ba34a00695ec373f45c3f51805334dbf40637 Mon Sep 17 00:00:00 2001 From: William So Date: Sun, 25 Jan 2026 14:10:55 +0800 Subject: [PATCH 18/18] ci(workflows): enable Corepack, use numeric node-version and add Node cache for docs workflows Use numeric node-version (24) in `.github/workflows/docs.yml` and `.github/workflows/docs-publish.yml` Enable Corepack and run `corepack install` before installing dependencies Split node/cache setup to a dedicated `setup-node` step with `cache: yarn` Reorder and consolidate dependency install steps (Corepack prepare + yarn install --frozen-lockfile) Minor comment formatting fix in `docs-publish.yml` --- .github/workflows/docs-publish.yml | 16 ++++++++++++---- .github/workflows/docs.yml | 27 ++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/.github/workflows/docs-publish.yml b/.github/workflows/docs-publish.yml index 3153e44..bdc15b1 100644 --- a/.github/workflows/docs-publish.yml +++ b/.github/workflows/docs-publish.yml @@ -23,7 +23,7 @@ jobs: build-and-publish: needs: detect-quota - # NOTE: do not set continue-on-error on detect-quota (see docs) + # NOTE: do not set `continue-on-error` on detect-quota (see docs) runs-on: ${{ needs.detect-quota.result == 'success' && 'ubuntu-slim' || 'self-hosted' }} steps: - uses: actions/checkout@v4 @@ -31,12 +31,20 @@ jobs: - name: Use Node uses: actions/setup-node@v4 with: - node-version: "24" - cache: "yarn" + node-version: 24 - - name: Install dependencies (Corepack + Yarn) + - name: Enable Corepack run: | corepack enable + corepack install + + - name: Enable Node cache + uses: actions/setup-node@v4 + with: + cache: yarn + + - name: Install dependencies (Corepack + Yarn) + run: | corepack prepare yarn@stable --activate corepack yarn install --frozen-lockfile diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 2737015..23cd5f5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -27,17 +27,34 @@ jobs: runs-on: ${{ needs.detect-quota.result == 'success' && 'ubuntu-slim' || 'self-hosted' }} steps: - uses: actions/checkout@v4 + - name: Use Node uses: actions/setup-node@v4 with: - node-version: "24" - cache: "yarn" + node-version: 24 + + - name: Enable Corepack + run: | + corepack enable + corepack install + + - name: Enable Node cache + uses: actions/setup-node@v4 + with: + cache: yarn + - name: Install dependencies - run: yarn install --frozen-lockfile + run: | + yarn install --frozen-lockfile + - name: Build project - run: yarn build + run: | + yarn build + - name: Generate TypeDoc - run: yarn docs:typedoc + run: | + yarn docs:typedoc + - name: Upload artifact uses: actions/upload-artifact@v4 with: