AdonisJS
repository·7.x·Indexed 12 days ago
https://github.com/adonisjs/coreA fullstack MVC framework for Node.js that prioritizes developer ergonomics and speed. Version 7.4.0 provides a stable API for building web applications and microservices, featuring the Ace CLI for package installation, production builds, environment variable management, and scaffolding generation via make commands.
What's inside AdonisJS
- AdonisJS is a fullstack MVC (Model-View-Controller) framework for Node.js designed with a focus on ergonomics and speed. It provides a clean and stable API to handle common web development complexities, making it suitable for building both full-scale web applications and microservices.
Extend EncryptorsList to register custom encryptors
7.xTo register multiple encryption configurations (e.g., a primary and a secondary encryptor), extend the
EncryptorsListinterface. This enables theEncryptionServiceto manage multiple encryption keys or configurations.// Extending EncryptorsList in user code declare module '@adonisjs/core' { interface EncryptorsList { default: EncryptionConfig secondary: EncryptionConfig } }How HttpServerProcess manages server lifecycle
7.xThe
HttpServerProcessimplements several lifecycle management patterns to ensure stability:- Initialization: It triggers the application's
init()andboot()phases before the server starts listening. - Graceful Shutdown: It listens for the application's
terminatingevent. When triggered, it calls the underlying Node.js server's.close()method to stop accepting new connections. - Error Monitoring: It monitors the Node.js server for
'error'events. If the server crashes, it logs a fatal error, sets the process exit code to1, and callsapp.terminate()to shut down the application. - Startup Notification: Once the server is listening, it notifies the system via:
- The application's
notifymethod (withisAdonisJS: trueandenvironment: 'web'). - The
loggerservice. - The
emitterservice via thehttp:server_readyevent.
- The application's
- Initialization: It triggers the application's
Extend LoggersList to register custom loggers
7.xTo register custom loggers that are available via the
loggerservice, extend theLoggersListinterface using module augmentation. This allows theLoggerServiceto provide type-safe access to your specific logger configurations.// Extending LoggersList in user code declare module '@adonisjs/core' { interface LoggersList { default: LoggerConfig file: LoggerConfig } }Extend HashersList to register custom hashers
7.xTo add custom hashing algorithms (drivers) to the
hashservice, extend theHashersListinterface. This allows you to use different hashing strategies defined in your configuration.// Extending HashersList in user code declare module '@adonisjs/core' { interface HashersList { scrypt: ManagerDriverFactory argon: ManagerDriverFactory } }Behavioral notes for `make:controller` flags
7.xWhen using
make:controller, certain flags have precedence or conflicts:- Custom Actions vs Resource Flags: If you provide custom method names via
actions, the--resourceand--apiflags are ignored. The command will log a warning and use theactionsstub instead. - API vs Resource: The
--apiflag and--resourceflag cannot be used together. If both are provided,--apitakes precedence and--resourceis ignored. The command will log a warning.
- Custom Actions vs Resource Flags: If you provide custom method names via
How configuration providers work
7.xConfiguration providers are an abstraction used to defer the resolution of configuration until the application is fully booted. This pattern is essential when configuration depends on other application services (like environment variables or other providers) that are not available during the initial module loading phase.
Instead of passing a static object, you pass a
ConfigProviderwhich contains aresolverfunction. The lifecycle involves:- Creation: Defining the provider using
configProvider.create(). - Resolution: Calling
configProvider.resolve(app, provider)during the application boot process to transform the provider into the final configuration object.
- Creation: Defining the provider using
Extend EventsList to register custom events
7.xAdonisJS uses a type-safe event system. To add your own custom events and define their payload types, you must extend the
EventsListinterface using TypeScript module augmentation. This ensures that when you use theemitterservice, your custom events are recognized and type-checked.// Extending EventsList in user code declare module '@adonisjs/core' { interface EventsList { 'user:created': { user: User } 'order:placed': { orderId: string, amount: number } } }Install and configure AdonisJS packages with `ace add`
7.xThe
ace addcommand automates the process of installing one or more packages and immediately running their configuration hooks. This replaces the manual two-step process of runningnpm installfollowed bynode ace configure.Key Features:
- Shorthand Names: You can use shorthand names for common packages:
vinejsresolves to@vinejs/vineedgeresolves toedge.js
- Batch Installation: You can pass multiple package names in a single command.
- Automatic Configuration: After successful installation, the command automatically invokes the
configurecommand for each package.
# Install a single package ace add @adonisjs/lucid # Install multiple packages at once ace add @adonisjs/lucid @adonisjs/auth @adonisjs/session # Install a package as a dev dependency ace add @adonisjs/session --dev # Forcefully overwrite existing configuration files ace add vinejs --force # Specify a specific package manager (e.g., pnpm) ace add edge --package-manager=pnpm- Shorthand Names: You can use shorthand names for common packages:
Create a new CLI command
7.xWhen using the AdonisJS CLI to generate a new command, the resulting file follows a specific structure based on the
BaseCommandclass. A generated command includes a staticcommandNamefor the CLI entrypoint, adescription, and anoptionsobject for defining flags and arguments.Note that the generator uses placeholders like
{{ commandName }}and{{ commandTerminalName }}which are resolved during the scaffolding process to create the class name and the CLI command string respectively.import { BaseCommand } from '@adonisjs/core/ace' import type { CommandOptions } from '@adonisjs/core/types/ace' export default class MyCommand extends BaseCommand { static commandName = 'my:command' static description = 'A description of what this command does' static options: CommandOptions = {} async run() { this.logger.info('Hello world from "MyCommand"') } }Configure ESLint with @adonisjs/eslint-config
7.xTo use the recommended ESLint configuration for AdonisJS projects, import
configPkgfrom@adonisjs/eslint-configand export it as the default configuration in youreslint.config.jsfile. You can pass an options object toconfigPkgto define global ignores for the linting process.import { configPkg } from '@adonisjs/eslint-config' export default configPkg({ ignores: ['coverage'], })Configure IndexEntities via IndexEntitiesConfig
7.xThe
IndexEntitiesConfigtype is used to configure the automatic generation of barrel files for various application entities like controllers, listeners, events, and transformers. This helps in maintaining clean imports.Configuration Options
- controllers: Configures indexing for controllers.
- listeners: Configures indexing for event listeners.
- events: Configures indexing for event files.
- transformers: Configures indexing for transformers (e.g., for Inertia).
- manifest: Configures manifest generation settings.
Each entity group (controllers, listeners, etc.) supports the following sub-options:
enabled: Boolean to toggle indexing.source: The directory where files are located.importAlias: The alias used for imports (e.g.,#controllers).glob: Array of glob patterns to match files.skipSegments: Array of path segments to exclude from generated keys.
// Basic configuration const config: IndexEntitiesConfig = { controllers: { enabled: true }, events: { source: 'app/custom-events' } } // Detailed configuration with custom paths const config: IndexEntitiesConfig = { controllers: { enabled: true, source: 'app/http/controllers', importAlias: '#controllers', glob: ['**/*_controller.ts'] }, listeners: { enabled: false } }