Skip to the content
OrielDocs
0.1.0-alpha.10GitHub

Getting started

Configuration

Your app's settings live in the config folder, one TypeScript file per part of the framework, with the values that differ per machine in .env.

Introduction#

Each file in config is a TypeScript module whose default export is an object. The file's name is the first part of every key it holds: name in config/app.ts is app.name. A new app has app, auth, cache, database, filesystems, hashing, http, logging, mail, queue, services, session and view, and the Inertia kits add inertia:

config/app.ts
import { env } from '@orieljs/framework'export default {  name: env('APP_NAME', 'Oriel'),  env: env('APP_ENV', 'production'),  debug: env('APP_DEBUG', false),  url: env('APP_URL', 'http://localhost'),  timezone: 'UTC',  locale: env('APP_LOCALE', 'en'),  cipher: 'AES-256-GCM',  key: env('APP_KEY'),  previous_keys: String(env('APP_PREVIOUS_KEYS', '')).split(',').filter(Boolean),}

Oriel imports every .ts, .js and .mjs file directly in config when it creates your app, before any service provider registers. A file is plain code, so it can compute a value, as previous_keys does, or build a path from import.meta.dirname, as config/database.ts does for the SQLite file. Each app gets its own copy of the values, so a value you change in one test never reaches the next.

A file runs once per process. A change to it, or to .env, applies when the process starts again, which node oriel serve --watch does for you.

The about command#

about shows an overview of your app: its name, the Oriel and Node versions, the environment, whether debug mode is on, and its URL:

Terminal
node oriel about

Laravel's --only option and config:show command aren't in Oriel.

Environment configuration#

Some values differ between your machine and your servers: the database's password, the mail server, the debug mode. They go in the .env file at the root of your app, and the config files read them with env(). A new app has a .env.example file listing the variables it uses, and the installer copies it to .env for you.

If you work in a team, keep .env.example in your repository with placeholder values, so the others see which variables your app needs.

Environment file security#

.env is ignored by git in a new app, and should stay out of your repository: each machine has its own, and its secrets would be exposed to anyone who can read the repository. Laravel can encrypt an environment file so that it can be committed (env:encrypt); Oriel can't, so give your servers their values through their environment or their own .env.

Additional environment files#

When APP_ENV is set in the environment before your app starts, and a .env.<APP_ENV> file exists, Oriel loads that file instead of .env, not as well: with APP_ENV=staging, a variable that is only in .env isn't set. When the file doesn't exist, .env is loaded. APP_ENV inside .env doesn't choose a file, and there is no --env option.

Your tests run with APP_ENV=testing, so a .env.testing file, when you add one, replaces .env in your tests.

Environment variable types#

The values in .env are text. env() turns a few words into other values, whatever their case:

.env valueenv() value
true, (true)true
false, (false)false
empty, (empty)''
null, (null)null

Nothing else is converted. A number stays text: with SESSION_LIFETIME=120 in .env, env('SESSION_LIFETIME', 120) is the string '120', and only the default, used when the variable isn't set, is the number. Wrap the call where you need a number, as a new app's config files do: Number(env('SESSION_LIFETIME', 120)). In the same way, debug mode is on only for APP_DEBUG=true: APP_DEBUG=1 is the string '1'.

A value with spaces goes in double quotes:

APP_NAME="My Application"

A value can use another variable, set earlier in the file or in the environment, as ${NAME}. Single quotes keep a value as written on Node; Bun, which reads .env itself, replaces ${NAME} in single quotes too:

MAIL_FROM_NAME="${APP_NAME}"PASSWORD_HINT='${not a variable}'

Retrieving environment configuration#

env() reads a variable, with a default for when it isn't set. The config files call it for most of their values:

const debug = env('APP_DEBUG', false)

A function as the default is called only when the variable isn't set. The result is typed as the default's type, a string, a boolean or null, since the variable could hold any of them.

Call env() in your config files, and read config() everywhere else. A config value can be changed while your app runs, in a test for one, and every part of your app then reads the same value.

Determining the current environment#

The current environment is app.env in your config, which config/app.ts reads from APP_ENV. A new app's .env says local; without the variable, the environment is production. app().environment() returns it, and with names it tells you whether it is one of them:

const environment = app().environment()if (app().environment('local')) {  // The environment is local}if (app().environment('local', 'staging')) {  // The environment is either local OR staging...}

A name may use * as a wildcard: app().environment('stag*'). Where Laravel takes a list, pass the names as separate arguments. The application has shortcuts too:

MethodIs true when
app().isLocal()The environment is local
app().isProduction()The environment is production
app().runningUnitTests()The environment is testing, as in your tests
app().runningInConsole()The app was started by an oriel command, oriel serve included, or by your tests

Since a variable set in the environment wins over .env, your server can set APP_ENV=production even when its .env says local.

Accessing configuration values#

Read a value with config(), anywhere in your app. A key is the file's name, then the keys inside it, with dots. A second argument is the default, returned when the key doesn't exist:

const timezone = config('app.timezone')// Retrieve a default value if the configuration value does not exist...const fallback = config('app.timezone', 'Asia/Seoul')

A value is typed unknown, unless you give it a type, which TypeScript takes on trust, config<string>('app.name'), or a default, whose type it takes: config('app.name', 'Oriel').

To set values while your app runs, pass an object to config(). A value you set lasts as long as the app:

config({ 'app.timezone': 'America/Chicago' })

With no arguments, config() returns the configuration itself, with get(), set(), has(), push() and all().

The Config facade#

The Config facade reaches the same values:

const timezone = Config.get('app.timezone')Config.set('app.timezone', 'America/Chicago')if (Config.has('services.stripe')) {  // ...}

It also has getMany(), which reads several keys at once, push() and prepend(), which add a value at the end or the start of a list, and typed getters. A typed getter returns the value as its type, or throws a TypeError when the value isn't of that type:

const name = Config.string('app.name')const debug = Config.boolean('app.debug')const maxBodySize = Config.integer('http.max_body_size')const proxies = Config.array('http.trusted_proxies')

float() takes any number, as JavaScript has one number type, and array() takes a list or an object, such as a config section. Each typed getter takes a default for a missing key. Laravel's collection() getter isn't in Oriel.

A typed getter checks the value it reads: Config.integer() on a value read from .env as text throws "Configuration value for key [session.lifetime] must be an integer, string given.". A new app's config files wrap their numeric settings in Number(), as Laravel's cast them, so its own values read as numbers; do the same for a setting of yours.

Third-party services#

config/services.ts holds the credentials of the services your app talks to, such as a payment gateway or a mail provider, so your code and your packages find them in one place. A new app's file is empty. Add a section per service, with its values from .env:

config/services.ts
import { env } from '@orieljs/framework'export default {  stripe: { key: env('STRIPE_KEY'), secret: env('STRIPE_SECRET') },}

Read them as any other value: config('services.stripe.key'), or Config.string('services.stripe.key'), which throws when the variable isn't set.

The HTTP settings#

config/http.ts holds settings of the HTTP layer that Laravel sets in bootstrap/app.php or in PHP's own configuration:

config/http.ts
export default {  trusted_proxies: [],  csrf_except: [],  redirect_guests_to: '/login',  max_body_size: 8 * 1024 * 1024,}

The limit is 8 MB, and it holds for every route, uploads included. A Live component accepts uploads of up to 12 MB, so to take a file larger than 8 MB, raise max_body_size above the largest file you accept, with room for the rest of the form:

config/http.ts
export default {  trusted_proxies: [],  csrf_except: [],  redirect_guests_to: '/login',  max_body_size: 16 * 1024 * 1024,}

With the default limit, a Live upload of 9 MB gets a 413, and the field shows "The photo failed to upload.", with your property's name in place of photo.

Configuration caching#

Configuration publishing#

The framework's packages merge their defaults with your config files, so a key you leave out still has its value: config/http.ts has no max_json_depth, and config('http.max_json_depth') is 512. A package of your own does the same with mergeConfigFrom(), in its service provider's register():

app/Providers/CourierServiceProvider.ts
import { ServiceProvider } from '@orieljs/framework'export class CourierServiceProvider extends ServiceProvider {  override register(): void {    this.mergeConfigFrom({ channel: 'mail', timeout: 30, options: { retries: 3 } }, 'courier')  }}

The merge is shallow, as in Laravel: each top-level key of the app's config/courier.ts wins over the default, and an object such as options is replaced whole, not merged key by key.

Debug mode#

debug in config/app.ts decides how much an error response shows. It reads APP_DEBUG, which a new app's .env sets to true: a server error then shows the debug page, with your code around the error and its stack. Error handling describes what it shows.

The application key#

APP_KEY in .env is your app's secret key. It encrypts your cookies, your sessions when session.encrypt is on and what you encrypt with Crypt, and it signs signed URLs, such as the email verification links, and the state of your Live components. The installer sets it. To set a new one, run key:generate:

Terminal
node oriel key:generate

It writes a random key for the cipher in config/app.ts, AES-256-GCM, into the APP_KEY= line of .env, as base64: and the key's bytes. .env needs that line: without it, the command stops with "Unable to set application key. No APP_KEY variable was found in the .env file.". --show prints a key and changes nothing. In production, the command refuses to replace a key that is set, unless you pass --force.

A new key can't decrypt what the old one encrypted, so signed-in users are signed out. To keep reading the old values, list the old keys in APP_PREVIOUS_KEYS, separated by commas: Oriel then decrypts with them too, and accepts the signed URLs they signed, but encrypts and signs with the new key only. An app with no key fails the first time it needs one, with "No application encryption key has been specified.".

Maintenance mode#

Privacy policy ·

esc