Skip to main content

AthennaRC File

Understand what is the purpose of the .athennarc.json file.

Introduction

Inside the root directory of your project, there is a file called .athennarc.json which is responsible for configuring the workspace and certain runtime settings of your Athenna application.

RC file vs Configurations

The responsible for the RC file is configuring the workspace and certain runtime settings to bootstrap your Athenna application properly. Also, when working with .json files is very easy to manipulate the values of it, making it possible to make changes on the file in runtime. Let's see an example where Athenna manipulates your RC file:

node artisan make:service UserService

Athenna will create the service file in your project but also register it inside your .athennarc.json file:

{
"services": [
"#app/services/UserService"
]
}

Custom RC file path

You can change the name and the path of your RC file or even create customized ones for each environement (.athennarc.dev.json, .athennarc.prod.json). To do that you need to set the new path to Ignite::load() static method:

Path.bootstrap('dev.ts')
import { Ignite } from '@athenna/core'

const ignite = await new Ignite().load(import.meta.url, {
athennaRcPath: './bootstrap/athennadevrc.json' 👈
})

await ignite.httpServer()
tip

Always remember that when using relative paths to set something in Athenna, you need to use your project root path as reference, just like in the example above.

Using RC file in package.json

You can also use the RC file inside package.json. By default, If you don't specify the path of your RC file, and the default .athennarc.json cannot be found in the root path of your application, Athenna will check if the athenna property exists in your package.json:

package.json
{
"athenna": {
"providers": [
"@athenna/core/providers/CoreProvider",
"@athenna/http/providers/HttpRouteProvider",
"@athenna/http/providers/HttpServerProvider"
],
"directories": {
"bootstrap": "bin"
}
}
}

The preloads property

An array of files that will be loaded when your application is bootstrapping. The files are loaded after booting the service providers. You can do anything you want in preload files. Check the example bellow:

say-hello.ts
import { Log } from '@athenna/logger'
import { Config } from '@athenna/core'

Log.info(`Hello from ${Config.get('app.name')} application!`)
{
"preloads": [
"./bootstrap/preloads/say-hello.js"
]
}

The providers property

An array of service providers to load when the application is bootstrapping:

{
"providers": [
"@athenna/core/providers/CoreProvider",
"@athenna/http/providers/HttpRouteProvider",
"@athenna/http/providers/HttpServerProvider"
]
}
tip

More information about service providers could be found at service providers documentation section.

The services property

This property is responsible to register your application services or from some library inside the service container. In most cases, it is better to simply instantiate your services, but in others you might have different implementations for some interface, using inversion of control in these cases could be an exceptional idea to register your services in the container:

{
"services": [
"#app/services/AppService",
"./app/services/OtherService.js"
]
}

The commands property

An object that is responsible to register your application commands and their respective settings. The key of the commands object needs to be exactly your command signature without any arguments, flags or spaces. Also, the value of it could be the command path or an object with the "path" key inside:

{
"commands": {
"make:exception": "@athenna/core/commands/MakeExceptionCommand",
"make:facade": {
"path": "@athenna/core/commands/MakeFacadeCommand",
"env": "local",
"destination": "./src/providers/facades",
"loadApp": false,
"stayAlive": false,
"loadAllCommands": false,
"environments": ["console"]
}
}
}

Depending on the command you are running, it got their own configurations. Commands like make:... for example, reads the destination property to the file generated for a different path from it default.

There are properties that you can define whatever your command. Let's see who they are and what they do:

  • path - Defines the path to your command, this field is mandatory if you are using an object to define your command.
  • loadApp - If true, the Ignite.fire() method will be called until running your command. The Ignite.fire() method is responsible to load your env file and configuration files and also boot your service providers.
  • env - Defines which env file will be used to run your command. This field is not required and it will only be relevant when the loadApp property is true.
  • stayAlive - If true, your command will stay running until the event loop is not in use anymore. Very useful for keep running background tasks from commands.
  • loadAllCommands - If true, all the commands inside the commands property will be loaded. Useful when you command needs to call other command programmatically.
  • environments - Only relevant when loadApp is true. The environments set will be used as parameter for Ignite.fire() method and will help Athenna to select the service providers that should or shouldn't be booted.
tip

More information about commands could be found at cli commands documentation section.

The templates property

Map your application commands templates with their respective path. The templates mapped in this object will be used by your make commands to generate the resource with some specific code template:

{
"templates": {
"exception": "node_modules/@athenna/core/templates/exception.edge",
"facade": "node_modules/@athenna/core/templates/facade.edge"
}
}

The directories property

Map your application directories with their respective base path. The Path class will use the directories mapped in this object to resolve the paths of your application:

{
"directories": {
"bin": "bin",
"src": "src",
"app": "app",
"models": "app/models",
"services": "app/services",
"exceptions": "app/exceptions",
"repositories": "app/repositories",
"console": "app/console",
"commands": "app/console/commands",
"http": "app/http",
"controllers": "app/http/controllers",
"middlewares": "app/http/middlewares",
"interceptors": "app/http/interceptors",
"terminators": "app/http/terminators",
"bootstrap": "bootstrap",
"config": "config",
"database": "database",
"seeders": "database/seeders",
"migrations": "database/migrations",
"lang": "lang",
"resources": "resources",
"views": "resources/views",
"locales": "resources/locales",
"nodeModules": "node_modules",
"nodeModulesBin": "node_modules/.bin",
"providers": "providers",
"facades": "providers/facades",
"public": "public",
"static": "public/static",
"assets": "public/assets",
"routes": "routes",
"storage": "storage",
"logs": "storage/logs",
"tests": "tests",
"stubs": "tests/stubs",
"fixtures": "tests/fixtures"
}
}

The paths above are the default ones used by Athenna to resolve your application paths. You can change one of them or many if you want, your directories defined in directories property will always be merged with the defaults.

Athenna always rely on Path class methods to find files and directories that are used internally by the framework, like configuration file, route files, entry points and many others. Changing the directories property could be very useful when you are building your own project structure.

The controllers property

An array with the controllers of your application. The controllers registered in this array will be registered in the service container to be accessed easily by your Route facade:

{
"controllers": [
"#app/http/controllers/AppController",
"./app/http/controllers/OtherController.js"
]
}

The middlewares property

An array with the middlewares of your application. The middlewares registered in this array will be registered in the service container to be accessed easily by your Route facade:

{
"middlewares": [
"#app/http/middlewares/AppMiddleware",
"./app/http/interceptors/AppInterceptor.js"
]
}

Athenna expects that the middlewares set in this property to be annotated with @Middleware(), @Interceptor() or @Terminator() annotations, this is not mandatory, but you will only be able to set the name of the middleware or if it is global or not using the annotations.

If you are not using TypeScript in your application, you can use the namedMiddlewares property to register named middlewares and the globalMiddlewares property to register global middlewares.

tip

More information about middlewares could be found at http middlewares documentation section.

The namedMiddlewares property

Map the named middlewares of your application. Named middlewares could be configured using the @Middleware annotation, but if you are not using TypeScript in your application, you can use this object to map your named middlewares. Named middlewares are very useful to be used in your route declaration:

{
"namedMiddlewares": {
"app": "#app/http/middlewares/AppMiddleware",
"intercept": "./app/http/interceptors/AppInterceptor.js"
}
}

The globalMiddlewares property

An array with the global middlewares of your application. Global middlewares could be configured using the @Middleware annotation, but if you are not using TypeScript in your application, you can use this object to map your named middlewares. Global middlewares are executed every time in any request of your application:

{
"globalMiddlewares": [
"#app/http/middlewares/AppMiddleware",
"./app/http/interceptors/AppInterceptor.js"
]
}

The artisan property

An object with a variety of Artisan configurations. At this point the only configurations accepted are artisan.child.executor and artisan.child.path. Both configurations are used to define how the Artisan.callInChild() method will behave when no options are set to it as second argument:

{
"artisan": {
"child": {
"executor": "node --inspect",
"path": "./bin/artisan.ts"
}
}
}
tip

Athenna will automatically parse the artisan.child.path using the Path.ext() method, so you don't need to worry about if the extension is .js or .ts.