- Node
v16
- yarn as pacakge manager
^1.20
Name | Description |
---|---|
build | Builds app from typescript sources to ES2020 |
start | Starts production app |
dev | Starts app in development mode with "live reload" on changes |
check-types | Checks TypeScript types |
lint | Runs eslint with prettier on codebase (see ESLint / Prettier section) |
test | Runs jest tests with coverage reporter |
test:watch | Runs jest tests in watch mode |
App includes swagger documentation avialable after start in /documentation
path
You can also take a look at autogenerated JSON schema in ./openapi.json
See more in JSON Schema / Open API section
App seed some users during startup (see ./src/main.ts).
Password | |
---|---|
[email protected] | S0m3P@ssw0rd |
[email protected] | S0m3P@ssw0rd2 |
Entire project is written using TypeScript 4. No JS files should be necessary.
Eslint and Prettier are configured in the project using predefinied @hypedevs/eslint-config library. You can adjust them to your liking by modifying the eslint
section in package.json
.
Fastify is the core framework used for HTTP in this project.
As Fastify supports JSON Schema out of the box each request is described in as much detail as possible. Check out *.ctrl.ts
files to see how to endpoint are provided with dedicated OpenAPI definition.
After any change in routes JSON Schema definition with api started up, the ./openapi.json file will be reconstructed, transforming and combining JSON Schemas from controllers into a single JSON. It's commited to the repo and serve as reference for current API interface.
Server provide swagger panel for documentation browsing: http://localhost:3000/documentation
A util library that allows type inference from JSON Schemas directly into route handler is present in this project. I built this library some time ago but didn't publish it yet cause it miss tests - the plan is to make it public when I have time - currently it's available in the lib/fastify-typed-route directory if you want to get git log for this one I can also share access to repository with you.
- in src, all files should be named with either
strictCamelCase
orStrictPascalCase
(only class modules and decorators) - in lib, all files should be named with
kebab-case
. The difference versussrc
is deliberate and not only enforces the distinction between these two directories purposes, but also prepares these small packages for proper functioning with npm and potential of being extracted to a separate module.
- variables and constants scoped in a single module -
strictCamelCase
- exported constants -
UPPER_CASE
- enums, enum members -
UPPER_CASE
- functions -
strictCamelCase
- decorators -
StrictPascalCase
- classes, interfaces, type aliases -
StrictPascalCase
- generic type parameters -
PascalCase
Throughout the codebase, many uses of dependency injection can be found. They are done by currying the dependencies in the top level function, followed by function logic arguments placed in the returned callback.
// declare function with DI as const
const getKeyPairForEmail =
// introduce dependencies in top level function
({ keysStorage, log }: { keysStorage: InternalKeysStorage, log: FastifyLoggerInstance }) =>
// introduce logic arguments in the returned function
async ({ email }: { email: string }) => {
const privKey = keysStorage.getPrivateKey(email)?.value;
const pubKey = keysStorage.getPublicKey(email)?.value;
if (!privKey || !pubKey) {
log.fatal('Missing rsa key pair for user', { user: { email } });
throw new Error('Missing key pair for user');
}
return { privKey, pubKey };
};
In most cases, only a single level of currying is required. This allows reuse of these functions in the same scope.