src -> Application main folder.
|_ api -> Server API folder.
| |_ middlewares -> API route middleware folder.
| | |_ [files].ts -> Middleware files.
| |_ models -> Table or document models folder.
| | |_ [databases] -> Specified database.
| | | |_ [files].ts -> Mapped related database table or document.
| |_ repositories -> Bridge for service to interact with a database or other resources.
| | |_ [RouteRepository].ts -> Repository for each route.
| |_ routes -> API routes folder.
| | |_ [routes-name] -> Route name folder.
| | | |_ controller.ts -> Route controller. Handle client request and send feedback to client.
| | | |_ index.ts -> Router for controllers.
| | | |_ schemas.ts -> Route request and response schema.
| | | |_ service.ts -> Route handle logic and process.
| | |_ index.ts -> Every API version entry point. Register API router for each version.
| |_ types -> All defined TypeScript types used in API process.
| | |_ fastify.ts -> Custom fastify type.
| | |_ model.ts -> Database select query type.
| | |_ schema.ts -> Schema type.
| | |_ utils.ts -> Some type used for utility functions.
| |_ utils -> API utilities folder.
| | |_ [files].ts -> Utility files.
| |_ index.ts -> API starting point. Register API version entry point.
|_ config -> Global or server configuration variables.
| |_ app.ts -> Server entry point. Fastify server, plugin registering process, global server hook and decorator, and schema definitions.
| |_ env-setup.ts -> Load .env file.
| |_ validateEnv.ts -> Validation for needed global variable in application.
| |_ [files].ts -> Any config files.
|_ databases -> Databases loader folder.
| |_ [files].ts -> Databases connection configuration.
|_ definitions -> Global JSON-Schema Definition for reusable.
| |_ index.ts -> Defined structured JSON-Schemas definition to use as a responses route.
|_ utils -> Global (server) utility folder.
| |_ [files].ts -> Utility config or utility process files.
|_ index.ts -> Application starting point. Contain Fastify server startup and server options, global process exception, environment variable loader, and another loader such as database connection.
- The
APIfolder is expected to change the most, so this folder will become a hot area, and getting hotter inside. - Naming file using
kebab-casestyle like on Google JavaScript Style Guide - Naming import using
lowerCamelCasestyle like on Google JavaScript Style Guide - Other references airbnb / javascript & google / styleguide. Most of code style follow the Airbnb one
- Using
make-promise-safeon the top of process, refer to Fastify documentation. - Using asynchronous logger, with Pino logger, and handle Log loss prevention and Reopening log files.
- Configure Fastify option on root
index.ts, and other application loader. - Use setNotFoundHandler to give feedback to client if requested route not exist.
- Use setErrorHandler to centralize error handler
- Could use Encapsulation if necessary, could set in global if all server needed or on the specified plugin or scope.
- Always call
done()function after registering custom plugin. - Using schema (
JSON-Schema) as recommended by Fastify on they Core Features. - Preferred using
JSON-Schemarather than using Fluent Schema. - Write schema definition close to another same
schema definition(schema grouping). For example, theschema definitionthat used forParamsis written on thetopof the definition. For example all keys for<prefix>Paramon the top and all keys forGet<postfix>on the bottom, etc. Use key identifier for definition used where,<prefix>Headermean used forheader,<prefix>Queryused forquery,Get<postfix>forresponses, etc, and just<key-name>for shared definition which mean can used onheader,param, etc. - Preferred async function if possible.
- Using Ajv schema validation for validate client request.
- Using ajv-errors to add custom message for client request validation.
- Preferred using arrow function if possible and doesn't need
thiskeyword. Because in Fastify there is several function handler that more good withnormal functionbecause usethisand there is more good usingarrow function. - Preferred using
arrow functionfor function handler on Fastify Hooks - Preferred using
normal functionfor function handler on Fastify Routes. - Authentication route level specified on preValidation route option.
- Use
reply.send()for response - [optional] Declare
import from <dependencies>aboveimport from <custom-module/file> - [optional] Declare
import from <most outer custom-module/file>aboveimport from <closest custom-module/file>. if import different module with the same level, a module with one and only export default or there is export default and used the export default above the sibling. - [optional] Declare
import typeaboveimport
This application structure, architecture, or style reference to this source:
Adopt the following check (for now):
- 1.2 Layer your components, keep the web layer within its boundaries
- 1.3 Wrap common utilities as npm packages
- 1.4 Separate Express 'app' and 'server'
- 1.5 Use environment aware, secure and hierarchical config
- 2.1 Use Async-Await or promises for async error handling
- 2.4 Handle errors centrally, not within a middleware
- 2.5 Document API errors using Swagger or GraphQL
- 2.7 Use a mature logger to increase error visibility
- 2.8 Test error flows using your favorite test framework
- 2.10 Catch unhandled promise rejections
- 2.11 Fail fast, validate arguments using a dedicated library
- 2.12 Always await promises before returning to avoid a partial stacktrace
- 3.11 Use Async Await, avoid callbacks
- 3.12 Use arrow function expressions (=>)
- 4.1 At the very least, write API (component) testing
- 4.2 Include 3 parts in each test name
- 4.3 Structure tests by the AAA pattern
- 4.5 Avoid global test fixtures and seeds, add data per-test
- 4.8 Check your test coverage, it helps to identify wrong test patterns
- 4.13 Test your middlewares in isolation