### Example Route with Configuration Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md An example demonstrating a GET route with extensive configuration options for Swagger documentation and middleware. ```APIDOC ## GET / ### Description Retrieves demo user information. Requires authentication. ### Method GET ### Endpoint / ### Parameters #### Query Parameters None explicitly defined in this example. #### Request Body None ### Handler demo.user ### Middleware global.isAuthenticated ### Roles None explicitly defined in this example. ### Configuration (Swagger) - **Title**: Demo title - **Description**: Demo description - **Tags**: user, code - **Deprecated**: false - **Version**: false ### Response #### Success Response (200) - **$description**: Successful response - **type**: object - **properties**: - **id** (number) #### Response Example ```json { "id": 123 } ``` ``` -------------------------------- ### Generate Password Hash Example Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Example of how to run the password hash generation script from the command line. ```bash node generate-hash.js 'MyS3cretP@ss' # Password MyS3cretP@ss # Hash $2b$12$.... ``` -------------------------------- ### Full Server Configuration Example Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt A comprehensive example of a server configuration file, including settings for the server, database, authentication, API documentation, and logging. ```properties # --- Server --- NODE_ENV=production HOST=0.0.0.0 PORT=2230 APP_NAME=volcanic-sample-backend HIDE_ERROR_DETAILS=true # --- Database --- START_DB=true DB_HOST=10.0.0.5 DB_PORT=5432 DB_NAME=db_prod DB_USERNAME=admin DB_PASSWORD=secret_password DB_SSL=true DB_SSL_CA_PATH=/usr/src/app/certs/ca.pem # --- Pool & Timeouts --- DB_MAX_CONNECTING=50 DB_MIN_CONNECTING=5 DB_STATEMENT_TIMEOUT=60000 DB_IDLE_TIMEOUT=30000 DB_KEEP_ALIVE=true DB_CONNECTION_TIMEOUT=60000 DB_QUERY_TIMEOUT=65000 # --- Auth & Security --- # Generate with: openssl rand -base64 64 JWT_SECRET=super_secret_key_change_me JWT_EXPIRES_IN=1h JWT_REFRESH=true JWT_REFRESH_SECRET=super_secret_refresh_key_change_me JWT_REFRESH_EXPIRES_IN=30d # MFA MFA_POLICY=OPTIONAL MFA_ADMIN_FORCED_RESET_EMAIL=admin@example.com MFA_ADMIN_FORCED_RESET_UNTIL=2025-01-01T00:00:00.000Z # --- API Documentation --- SWAGGER=true SWAGGER_HOST=localhost:2230 SWAGGER_TITLE=API Documentation SWAGGER_DESCRIPTION=List of available APIs and schemas to use SWAGGER_VERSION=0.1.0 SWAGGER_PREFIX_URL=/api-docs # --- Logging --- LOG_LEVEL=info LOG_COLORIZE=false LOG_TIMESTAMP=true LOG_TIMESTAMP_READABLE=true LOG_FASTIFY=false ``` -------------------------------- ### MFA Setup - Initial Request Source: https://github.com/volcanicminds/volcanic-backend/blob/main/docs/SECURITY_MFA.md Initiate the MFA setup process. This endpoint returns the secret, QR code data, and URI needed for the user's authenticator app. ```json { "secret": "...", "qrCode": "data:image/png;base64,iVBORw0KGgo...", "uri": "otpauth://totp/VolcanicBackend:user@example.com?secret=..." } ``` -------------------------------- ### Start the Backend Server with Decorators Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt This snippet shows the basic usage of the `start()` function from `@volcanicminds/backend`, passing an object of decorators (managers) to initialize the server. The `start()` function registers various Fastify plugins, loads configurations, and decorates the server instance with the provided managers. ```typescript import { start } from '@volcanicminds/backend' const server = await start(decorators) // decorators is an object of managers; returns the Fastify instance ``` -------------------------------- ### Start the Backend Server with Default Managers (Null-Object Pattern) Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt This demonstrates starting the backend server without explicitly providing any managers. The `start()` function will automatically use default null-object implementations for any missing managers. These default managers return `false` from `isImplemented()` and throw a 'Not implemented.' error when their methods are called, preventing startup crashes. ```typescript await start() // 100% valid: the server boots. Public routes work. Any route that NEEDS a manager // (e.g. POST /auth/login needs userManager) returns a "Not implemented" error at call time, // not at boot. Nothing crashes at startup. ``` -------------------------------- ### MFA Setup Initiation Source: https://github.com/volcanicminds/volcanic-backend/blob/main/docs/SECURITY_MFA.md Initiates the MFA setup process by generating the secret, QR code, and URI for the user to scan with their authenticator app. ```APIDOC ## POST /auth/mfa/setup ### Description Initiates the MFA setup flow. This endpoint generates the necessary secret, QR code, and URI for the user to configure their authenticator app. ### Method POST ### Endpoint /auth/mfa/setup ### Parameters #### Headers - **Authorization** (string) - Required - `Bearer ` ### Response #### Success Response (200 OK) - **secret** (string) - The MFA secret key. - **qrCode** (string) - A Data URL for the QR code to be displayed to the user. - **uri** (string) - The OTPAuth URI for manual entry. ### Response Example ```json { "secret": "JBSWY3DPEHPK3PXP", "qrCode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAACMCAMAAAC//8sAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACAUExURQAAAP////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////{ ``` ```APIDOC ## POST /auth/mfa/enable ### Description Enables MFA for the user after they have scanned the QR code and provided a valid TOTP code. This is part of the setup flow. ### Method POST ### Endpoint /auth/mfa/enable ### Parameters #### Headers - **Authorization** (string) - Required - `Bearer ` #### Request Body - **secret** (string) - Required - The MFA secret key obtained from `/auth/mfa/setup`. - **token** (string) - Required - The TOTP code from the user's authenticator app. ### Response #### Success Response (200 OK) Returns the final access token and refresh token, logging the user in immediately. ### Request Example ```json { "secret": "JBSWY3DPEHPK3PXP", "token": "123456" } ``` ``` -------------------------------- ### Core + Database + Tools Setup Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Extends the database setup to include additional tools like Multi-Factor Authentication (MFA) and file transfer capabilities. Requires specific adapter imports for these tools. ```typescript // (c) Core + database + tools (MFA, file upload). (Scenario G) import { mfaAdapter } from './src/services/mfa.adapter.js' // wraps @volcanicminds/tools mfa import { transferManager } from './src/services/transfer.adapter.js' // wraps @volcanicminds/tools transfer await startServer({ userManager, tokenManager, mfaManager: mfaAdapter, transferManager }) ``` -------------------------------- ### Core Volcanic Backend Setup Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Basic setup using only the core Volcanic Backend without database or manager integrations. Suitable for minimal configurations. ```typescript // (a) Core only — no DB, no managers. Public API. (see Part 12 Scenario A) import { start as startServer } from '@volcanicminds/backend' await startServer() ``` -------------------------------- ### Multi-Tenant Setup Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Configures the backend for multi-tenancy by adding a TenantManager and adjusting configuration. This setup is relevant for scenarios involving multiple tenants. ```typescript // (d) Multi-tenant — add the tenantManager and flip the config (Scenario F / Part 3.11 / Part 12.6) import { TenantManager, DataSource } from '@volcanicminds/backend/typeorm' const ds = await startDatabase(database.default) await startServer({ userManager, tokenManager, tenantManager: new TenantManager(ds as DataSource) }) ``` -------------------------------- ### Install Volcanic Backend Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Installs the core Volcanic Backend package using npm. ```sh npm install @volcanicminds/backend ``` -------------------------------- ### Install Docker, Nginx, and Certbot Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Installs Docker and Docker Compose using the official script, and installs Nginx and Certbot with the Nginx plugin for automated SSL certificate management. ```bash # Docker & Compose curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh # Nginx & Certbot sudo apt install nginx certbot python3-certbot-nginx -y ``` -------------------------------- ### Core + Database Setup Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Integrates the core backend with a database for user management, login, and persistence. Requires database configuration and manager imports. ```typescript // (b) Core + database — users, login, persistence. (Scenarios B–F) import { start as startServer } from '@volcanicminds/backend' import { start as startDatabase, userManager, tokenManager } from '@volcanicminds/backend/typeorm' import { database } from './src/config/database.js' await startDatabase(database.default) await startServer({ userManager, tokenManager }) ``` -------------------------------- ### Setup Mocha Global Hook Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt This TypeScript code snippet sets up a global Mocha hook to start the server before running the test suite. It imports necessary functions for starting the server and managing users. ```typescript import { start as startServer } from '@volcanicminds/backend' import { userManager } from '@volcanicminds/backend/typeorm' // Mocha Global Hook export const beforeAll = async () => { // Starts server on test port (e.g. 2231) await startServer({ userManager }) } ``` -------------------------------- ### Importing TypeORM Start Function Source: https://github.com/volcanicminds/volcanic-backend/blob/main/docs/TYPESCRIPT_GUIDE.md Import the necessary functions for starting the database and managing users from the TypeORM data layer. ```typescript import { start as startDatabase, userManager, DataSource } from '@volcanicminds/backend/typeorm' ``` -------------------------------- ### start Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Initializes the TypeORM DataSource, autoloads entities, wires managers, and sets globals. It returns the initialized DataSource. ```APIDOC ## start(options) ### Description Initializes the TypeORM `DataSource`, autoloads entities, wires managers, and sets globals. Returns the `DataSource`. ### Method Not applicable (function call) ### Parameters - **options** (object) - Required - Options for initialization. ``` -------------------------------- ### Run Volcanic Backend Development Server Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Starts the development server for the Volcanic Backend application. ```sh npm run dev ``` -------------------------------- ### Install and Configure UFW Firewall Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Installs UFW, sets default policies to deny incoming and allow outgoing traffic, permits SSH and Nginx traffic, and enables the firewall. Ensure SSH is allowed to prevent lockout. ```bash # 1. Install UFW if not present sudo apt update && sudo apt install ufw -y # 2. Base Policy: Block everything incoming, allow everything outgoing sudo ufw default deny incoming sudo ufw default allow outgoing # 3. CRITICAL: Allow SSH (otherwise you lock yourself out) sudo ufw allow OpenSSH # 4. Allow Standard Web Traffic (HTTP/HTTPS) managed by Nginx sudo ufw allow 'Nginx Full' # 5. Enable firewall sudo ufw enable ``` -------------------------------- ### Pagination, Sorting, and Filtering Examples Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Demonstrates basic usage of pagination, sorting, and filtering parameters in API requests. ```APIDOC ## GET /users ### Description Retrieves a list of users with support for pagination, sorting, and filtering. ### Method GET ### Endpoint /users ### Parameters #### Query Parameters - **page** (integer) - Optional - The page number for pagination (default: 1). - **pageSize** (integer) - Optional - The number of items per page (default: 25). - **sort** (string) - Optional - Field to sort by (e.g., `lastName:asc`, `createdAt:desc`). Repeat for multi-field sorting. - **field:operator=value** (string) - Optional - Filters the results based on the specified field, operator, and value. Operators include `:eq`, `:neq`, `:gt`, `:ge`, `:lt`, `:le`, `:between`, `:nbetween`, `:in`, `:nin`, `:null`, `:notNull`, `:isEmpty`, `:isNotEmpty`, `:contains`, `:ncontains`, `:starts`, `:nstarts`, `:ends`, `:nends`, `:like`, `:nlike`, `:overlap`, `:arrayContains`, `:arrayContainedBy`, `:jsonHasKey`, `:jsonHasAnyKey`, `:jsonHasAllKeys`, `:raw`. ### Request Example ```http GET /users?page=2&pageSize=50 GET /users?sort=lastName:asc&sort=createdAt:desc GET /users?status:in=active,pending&country:eq=IT ``` ### Response #### Success Response (200) - **(structure depends on the resource returned)** #### Response Example ```json { "data": [ { "id": 1, "name": "John Doe", "status": "active" } ], "pagination": { "page": 1, "pageSize": 25, "total": 100 } } ``` ``` -------------------------------- ### Initialize Data Layer with Custom Options Source: https://github.com/volcanicminds/volcanic-backend/blob/main/docs/CONFIGURATION.md Configure the TypeORM data layer by passing an options object to the `start()` function. This example overrides default sensitive fields, sets a custom cache timeout, and disables logging. ```typescript import { start } from '@volcanicminds/backend/typeorm' await start({ type: 'postgres', sensitiveFields: ['password', 'secretKey', 'ssn'], // Overrides default blacklist cacheTimeout: 60000, logging: false }) ``` -------------------------------- ### Example onRequest Hook Implementation Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md An example of how to implement an 'onRequest' hook. This hook is called at the beginning of the request lifecycle. ```typescript // src/hooks/onRequest.ts async function hook(req, reply) { log.debug('onRequest called') } export { hook } ``` -------------------------------- ### Install PGlite Dependencies Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Install the necessary packages for using PGlite with Volcanic Backend. Include `@electric-sql/pglite-pgvector` if vector support is needed. ```bash npm install typeorm-pglite @electric-sql/pglite # + @electric-sql/pglite-pgvector for vector:true ``` -------------------------------- ### Prepare Database with Initial Data Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Securely initializes the database by cleaning existing data and populating it with users, clients, and test orders. Requires a temporary admin token or disabled security for the first start. ```bash curl -X GET http://localhost:2230/api/tools/prepare-database \ -H "Authorization: Bearer " ``` -------------------------------- ### Publishing a Package to NPM Source: https://github.com/volcanicminds/volcanic-backend/blob/main/NPM.md Commands to install the latest NPM version, log in to your NPM account, initialize a scoped package, and publish it publicly. ```bash npm install npm@latest -g ``` ```bash npm login ``` ```bash npm init --scope=volcanicminds ``` ```bash npm publish --access public ``` -------------------------------- ### Minimal Volcanic Backend Server Setup Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Sets up a basic Volcanic Backend server with a database connection and a single endpoint. Assumes a database configuration file 'src/config/database.js' exists. ```typescript // index.ts import { start } from '@volcanicminds/backend' import { start as startDatabase, userManager } from '@volcanicminds/backend/typeorm' import { myDbConfig } from './src/config/database.js' // Assume you have a db config file async function main() { // 1. Initialize the database connection (optional but recommended) await startDatabase(myDbConfig) // 2. Start the Volcanic Backend server // We pass the 'userManager' from the typeorm package to enable authentication await start({ userManager }) } main().catch((err) => { console.error(err) process.exit(1) }) ``` -------------------------------- ### Single Tenant Record Fetch (CLI) Source: https://github.com/volcanicminds/volcanic-backend/blob/main/docs/PGLITE.md Example of fetching products from a single-tenant PGlite instance using curl. No specific tenant header is required. ```shell curl http://localhost:2230/products ``` -------------------------------- ### Define a Route for Hello World Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Defines a GET route at the root path ('/') that will be handled by the 'world.sayHello' controller. ```typescript // src/api/hello/routes.ts export default { routes: [ { method: 'GET', path: '/', handler: 'world.sayHello' } ] } ``` -------------------------------- ### Start Server with Multi-Tenant Support Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Enables multi-tenancy for applications serving isolated tenants, typically using a schema-per-tenant approach in Postgres. Requires a TenantManager and specific configuration. ```typescript import { start as startServer } from '@volcanicminds/backend' import { start as startDatabase, userManager, tokenManager, TenantManager, DataSource } from '@volcanicminds/backend/typeorm' import { database } from './src/config/database.js' const ds = await startDatabase(database.default) await startServer({ userManager, tokenManager, tenantManager: new TenantManager(ds as DataSource) }) ``` -------------------------------- ### Comprehensive Route Configuration Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md An example of a detailed routes.ts file, including global configuration and specific route configurations for Swagger documentation, roles, and middleware. ```typescript // src/api/example/routes.ts export default { config: { title: 'Example of routes.ts', description: 'Example of routes.ts', controller: 'controller', tags: ['user', 'code'], // swagger enable: true, deprecated: false, // swagger version: false // swagger }, routes: [ { method: 'GET', path: '/', roles: [], handler: 'demo.user', middlewares: ['global.isAuthenticated'], config: { enable: true, title: 'Demo title', // swagger summary description: 'Demo description', // swagger tags: ['user', 'code'], // swagger deprecated: false, // swagger version: false, // swagger response: { 200: { $description: 'Successful response', type: 'object', properties: { id: { type: 'number' } } } } // swagger } } ] } ``` -------------------------------- ### Start Server (Pure Public API) Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Use for stateless or public endpoints where authentication is handled upstream. No decorators are needed, and public routes are immediately available. '/health' works out of the box. ```typescript import { start as startServer } from '@volcanicminds/backend' await startServer() // no decorators → Null-Object managers; public routes serve immediately ``` -------------------------------- ### Start Server with Database (Public API) Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Use for serving public data from a database without requiring user login. Controllers can directly use Magic Query for data access. ```typescript import { start as startServer } from '@volcanicminds/backend' import { start as startDatabase } from '@volcanicminds/backend/typeorm' import { database } from './src/config/database.js' await startDatabase(database.default) await startServer() // public routes; controllers use executeFindQuery(req.db.getRepository(X), …) — Part 3 ``` -------------------------------- ### Multi-Tenant Record Fetch (CLI) Source: https://github.com/volcanicminds/volcanic-backend/blob/main/docs/PGLITE.md Examples of fetching products from a multi-tenant PGlite instance using curl. The 'x-tenant-id' header is used to specify which tenant's data to retrieve. ```shell curl -H "x-tenant-id: acme" http://localhost:2230/products # reads tenant_acme curl -H "x-tenant-id: globex" http://localhost:2230/products # reads tenant_globex ``` -------------------------------- ### Environment Variables Example Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md This snippet shows common environment variables used for configuring the application, including database connections, JWT settings, logging levels, and Swagger documentation. ```env NODE_ENV=development HOST=0.0.0.0 PORT=2230 JWT_SECRET=yourSecret JWT_EXPIRES_IN=5d JWT_REFRESH=true JWT_REFRESH_SECRET=yourRefreshSecret JWT_REFRESH_EXPIRES_IN=180d # LOG_LEVEL: trace, debug, info, warn, error, fatal LOG_LEVEL=info LOG_COLORIZE=true LOG_TIMESTAMP=true LOG_TIMESTAMP_READABLE=true LOG_FASTIFY=false SWAGGER=true SWAGGER_HOST=myawesome.backend.com SWAGGER_TITLE=API Documentation SWAGGER_DESCRIPTION=List of available APIs and schemas to use SWAGGER_VERSION=0.1.0 # MFA MFA_POLICY=OPTIONAL ``` -------------------------------- ### Custom User Manager Implementation Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Example of creating a custom user manager by implementing the UserManagement interface. This allows for custom storage solutions like in-memory maps, Prisma, or Mongo. ```typescript import type { UserManagement } from '@volcanicminds/backend' const users = new Map() // demo store export const userManager: UserManagement = { isImplemented: () => true, async retrieveUserByPassword(email, password) { /* verify, return user or null */ }, async retrieveUserByExternalId(externalId /*, db */) { return users.get(externalId) ?? null }, async isValidUser(user) { return !!user && !user.blocked }, async createUser(data) { /* persist, return user */ }, // …implement only what the routes you expose actually call; the rest can throw. } await startServer({ userManager }) ``` -------------------------------- ### Volcanic Backend Architecture Diagram Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Illustrates the separation between the HTTP Core and the optional Data Layer, and how they interact via the start() function and injected managers. ```text ┌─────────────────────────── @volcanicminds/backend ───────────────────────────┐ │ HTTP CORE (always present, DB-agnostic) │ │ Fastify · routes · auth (Bearer/Cookie) · RBAC · MFA · native API · jobs │ │ ▲ start(decorators) │ │ │ injects managers (Null-Object if omitted) │ │ DATA LAYER (optional, subpath /typeorm, optional peer deps) │ │ TypeORM · Magic Query · base entities · multi-tenant · managers │ └───────────────────────────────────────────────────────────────────────────────┘ ``` -------------------------------- ### Run PostgreSQL Container Source: https://github.com/volcanicminds/volcanic-backend/blob/main/DOCKER.md Starts a PostgreSQL container. Use the version with a data mount to persist database data across container restarts. Ensure environment variables for user and password are set. ```zsh docker pull postgres:18 # without data mount docker run -itd -e POSTGRES_USER=vminds -e POSTGRES_PASSWORD=vminds -p 5432:5432 --name vminds-database postgres:18 # with data mount docker run -itd \ --name vminds-database \ -e POSTGRES_USER=vminds \ -e POSTGRES_PASSWORD=vminds \ -p 5432:5432 \ -v ${PWD}/data:/var/lib/postgresql \ postgres:18 ``` -------------------------------- ### Configure PGlite Database Connection Source: https://github.com/volcanicminds/volcanic-backend/blob/main/docs/PGLITE.md Configure your database connection to use the 'pglite' type. This example shows an in-memory database configuration and how to enable pgvector. Data is lost on restart unless 'dataDir' is specified. ```ts // src/config/database.ts import { Database } from '@volcanicminds/backend/typeorm' export const database: Database = { default: { type: 'pglite', // dataDir omitted -> in-memory (data lost on restart) // dataDir: './.pglite' -> persisted on disk vector: true, // optional: enable pgvector synchronize: true } } ``` -------------------------------- ### MFA Adapter Implementation Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt This TypeScript code demonstrates the adapter implementation for MFA, delegating code generation and verification to the '@volcanicminds/tools' library. It includes functions for generating setup details and verifying TOTP tokens. ```typescript import * as mfaTool from '@volcanicminds/tools/mfa' export const mfaAdapter = { // Generates secret and QR Code async generateSetup(appName: string, email: string) { return await mfaTool.generateSetupDetails(appName, email) }, // Verifies code 123456 against secret verify(token: string, secret: string) { return mfaTool.verifyToken(token, secret) } } ``` -------------------------------- ### Configure Per-Route Response Cache Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Declare cache settings per route in `routes.ts`. This example caches a GET request for 1 hour and invalidates the 'public' key-group on a PUT request. ```typescript // cache: true | | { enabled?, ttl?, keyGroup?, invalidates? } routes: [ { method: 'GET', path: '/', roles: [roles.public], handler: 'public.vehicles', cache: { ttl: 3600 } }, // cache this GET for 1h (key-group = api folder) { method: 'PUT', path: '/:id', roles: [roles.admin], handler: 'vehicle.update', cache: { invalidates: ['public'] } } // on 2xx, flush the 'public' key-group ] ``` -------------------------------- ### Install TypeORM Peer Dependencies Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Installs optional peer dependencies for database interactions with @volcanicminds/backend/typeorm. ```sh npm install typeorm bcrypt pluralize reflect-metadata pg ``` -------------------------------- ### Bootstrap Volcanic Backend Application Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt This snippet shows the main entry point of the Volcanic Backend application. It demonstrates how to start the database (conditionally based on environment variables) and the server, injecting necessary dependencies like the user manager and MFA adapter. Ensure environment variables like START_DB are set correctly for database initialization. ```typescript 'use strict' import { start as startServer, yn } from '@volcanicminds/backend' import { start as startDatabase, userManager, DataSource } from '@volcanicminds/backend/typeorm' // Import the MFA adapter from tools (concrete implementation) import { mfaAdapter } from './src/services/mfa.adapter.js' // Import DB config import { database } from './src/config/database.js' const start = async () => { let db: DataSource | null = null // 1. Start Database (Conditional or Mandatory depending on ENV) if (yn(process.env.START_DB, true)) { const options = database?.default || {} // startDatabase initializes TypeORM and populates global.entity / global.connection. // (global.repository is installed as a fail-fast Proxy — any access throws; use service.use(req.db).) db = await startDatabase(options) if (db && log.i) { const opts = db.options as any log.info(`Database attached at ${opts.host}:${opts.port} (${opts.database})`) } } else { if (log.w) log.warn('Database not loaded, check START_DB property on environment') } // 2. Start Server // It is CRUCIAL to pass 'userManager' (from typeorm) and 'mfaManager' (adapter) // This allows the backend framework to handle /auth/* routes (login, refresh, mfa) // using your DB logic without the framework knowing your entities beforehand. await startServer({ userManager: userManager, // Handles user CRUD and password validation mfaManager: mfaAdapter // Handles OTP generation/verification }) } start().catch((err) => { console.error('Fatal Error during startup:', err) process.exit(1) }) ``` -------------------------------- ### Install PGlite Dependencies Source: https://github.com/volcanicminds/volcanic-backend/blob/main/docs/PGLITE.md Install the necessary npm packages for PGlite and optional pgvector support. These are only required when using the embedded engine. ```sh npm install typeorm-pglite @electric-sql/pglite # only if you want pgvector / embeddings: npm install @electric-sql/pglite-pgvector ``` -------------------------------- ### Configure Caching for Storefront GETs Source: https://github.com/volcanicminds/volcanic-backend/blob/main/docs/CACHE.md This snippet shows how to configure caching for all storefront GET requests for 1 hour, using the key-group 'public'. It is applied to the routes configuration file. ```typescript // src/api/public/routes.ts → cache all storefront GETs for 1h (key-group 'public') config: { /* … */ cache: { ttl: 3600 } } ``` -------------------------------- ### Build and Run Backend (Production) Source: https://github.com/volcanicminds/volcanic-backend/blob/main/DOCKER.md Builds a production-ready Docker image using a multi-stage Dockerfile for a slim runtime. Runs the backend application in detached mode, mapping the application port and using environment variables from a .env file. Includes an option for autoremove on stop. ```zsh # prod (multi-stage: tsc build + slim runtime) docker build -f Dockerfile.prod -t volcanic-backend-prod . docker run -dp 2230:2230 --env-file .env -it volcanic-backend-prod # detached with autoremove on stop docker run --rm -dp 2230:2230 --env-file .env -it volcanic-backend-prod ``` -------------------------------- ### Create a Hello World Controller Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Implements the 'sayHello' function to handle incoming requests and send a 'Hello, World!' JSON response. ```typescript // src/api/hello/controller/world.ts import { FastifyReply, FastifyRequest } from '@volcanicminds/backend' export function sayHello(req: FastifyRequest, reply: FastifyReply) { reply.send({ message: 'Hello, World!' }) } ``` -------------------------------- ### MFA Management Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt The MFA Management interface handles the setup and verification of Time-based One-Time Passwords (TOTP). ```APIDOC ## MFA Management (`mfaManager`) ### Description Handles the setup and verification of Time-based One-Time Passwords (TOTP) used in MFA flows. ### Interface `MfaManagement` ### Typical Source `@volcanicminds/tools` (mfa) wrapped in an adapter ### Enables - TOTP setup/verify used by `/auth/mfa/*` ### Key Methods - `generateSetup(appName, email)` - `verify(token, secret)` ``` -------------------------------- ### Adding Middleware to a Route Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Shows how to apply middleware to a GET route to ensure user authentication before executing the controller. ```APIDOC ## GET /:id ### Description Retrieves a product by its ID. Requires the user to be authenticated. ### Method GET ### Endpoint /:id ### Handler product.findOne ### Middleware global.isAuthenticated ``` -------------------------------- ### Build and Run Backend (Development) Source: https://github.com/volcanicminds/volcanic-backend/blob/main/DOCKER.md Builds the Docker image for development and runs the backend application. This configuration uses volume mounts to enable hot-reloading and includes node_modules to avoid conflicts. Ensure the .env file is present for environment variables. ```zsh # dev (hot-reload via tsx watch; mounts the source as a volume) docker build -f Dockerfile -t volcanic-backend:dev . docker run --rm -p 2230:2230 \ -v ${PWD}:/usr/src/app -v /usr/src/app/node_modules \ --env-file .env -it volcanic-backend:dev ``` -------------------------------- ### Enable UUID Extension in PostgreSQL Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Ensures the UUID generation extension is active in your PostgreSQL database. This is a mandatory setup step. ```sql CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; ``` -------------------------------- ### Minimal Route Definition Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Defines a basic GET route at the root path handled by 'myController.test'. This is the simplest way to set up a route. ```typescript export default { routes: [ { method: 'GET', path: '/', handler: 'myController.test' } ] } ``` -------------------------------- ### Specify Route Roles Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Example of how to specify allowed roles for routes. This snippet demonstrates using predefined roles like 'admin' and 'public'. ```typescript roles: [roles.admin, roles.public] ``` -------------------------------- ### Initialize and Use Mailer Source: https://github.com/volcanicminds/volcanic-backend/blob/main/llms.txt Initialize the Mailer wrapper with SMTP configuration. It automatically generates a text/plain version from the provided HTML content. ```typescript import { Mailer } from '@volcanicminds/tools/mailer' const mailer = new Mailer({ host: process.env.SMTP_HOST, port: Number(process.env.SMTP_PORT), auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS }, secure: false }) // Automatically generates text/plain version from HTML await mailer.send({ to: 'client@example.com', subject: 'Order Confirmation', html: '

Your order #123 has been confirmed.

' }) ``` -------------------------------- ### Direct Database Read and Tenant Context Execution Source: https://github.com/volcanicminds/volcanic-backend/blob/main/docs/PGLITE.md Demonstrates reading records directly from 'req.db' within a controller, which remains tenant-safe. Also shows how to explicitly run operations within a specific tenant's context, useful for background jobs. ```typescript // inside a controller — single or multi tenant, identical const products = await req.db.getRepository(Product).find({ where: { active: true } }) // background job — pick the tenant explicitly import { TenantManager } from '@volcanicminds/backend/typeorm' const tm = new TenantManager(global.connection) const acme = await tm.runInTenantContext('acme', (em) => em.getRepository(Product).find()) ``` -------------------------------- ### Documenting a Route with Swagger Config Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Illustrates how to use the `config` object to provide detailed Swagger documentation for a route, including parameter and response schemas. ```APIDOC ## GET /:id ### Description Retrieves a single product by its unique ID. ### Method GET ### Endpoint /:id ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the product. ### Handler product.findOne ### Middleware global.isAuthenticated ### Configuration (Swagger) - **Title**: Find a Product - **Description**: Retrieves a single product by its unique ID. - **Params**: References `onlyIdSchema#` for validation. - **Response**: - **200**: - **Description**: Successful response - **$ref**: `productSchema#` ``` -------------------------------- ### Adding Authentication Middleware Source: https://github.com/volcanicminds/volcanic-backend/blob/main/README.md Applies the 'global.isAuthenticated' middleware to a GET route at '/:id'. This ensures that only authenticated users can access the route, regardless of their role. ```typescript { method: 'GET', path: '/:id', handler: 'product.findOne', middlewares: ['global.isAuthenticated'] // Requires a valid JWT, accessible to any role } ```