This commit is contained in:
Tutur33
2023-11-24 22:35:41 +01:00
parent 3c0b507a93
commit 7644b2a0f7
45165 changed files with 4803356 additions and 3 deletions
+9
View File
@@ -0,0 +1,9 @@
# The MIT License
Copyright 2022 Harminder Virk, contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+53
View File
@@ -0,0 +1,53 @@
<div align="center">
<img src="https://res.cloudinary.com/adonisjs/image/upload/q_100/v1558612869/adonis-readme_zscycu.jpg" width="600px">
</div>
<br />
<div align="center">
<h3>AdonisJS Application</h3>
<p>The application instance to know/inspect the state of the Application and make paths to certain known directories.</p>
</div>
<br />
<div align="center">
[![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url] [![synk-image]][synk-url]
</div>
<div align="center">
<h3>
<a href="https://adonisjs.com">
Website
</a>
<span> | </span>
<a href="https://docs.adonisjs.com/guides/application">
Guides
</a>
<span> | </span>
<a href="CONTRIBUTING.md">
Contributing
</a>
</h3>
</div>
<div align="center">
<sub>Built with ❤︎ by <a href="https://twitter.com/AmanVirk1">Harminder Virk</a>
</div>
[gh-workflow-image]: https://img.shields.io/github/workflow/status/adonisjs/application/test?style=for-the-badge
[gh-workflow-url]: https://github.com/adonisjs/application/actions/workflows/test.yml "Github action"
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
[typescript-url]: "typescript"
[npm-image]: https://img.shields.io/npm/v/@adonisjs/application.svg?style=for-the-badge&logo=npm
[npm-url]: https://npmjs.org/package/@adonisjs/application "npm"
[license-image]: https://img.shields.io/npm/l/@adonisjs/application?color=blueviolet&style=for-the-badge
[license-url]: LICENSE.md "license"
[synk-image]: https://img.shields.io/snyk/vulnerabilities/github/adonisjs/application?label=Synk%20Vulnerabilities&style=for-the-badge
[synk-url]: https://snyk.io/test/github/adonisjs/application?targetFile=package.json "synk"
@@ -0,0 +1,336 @@
/// <reference path="index.d.ts" />
declare module '@ioc:Adonis/Core/Application' {
import { IocContract } from '@adonisjs/fold';
import { EnvContract } from '@ioc:Adonis/Core/Env';
import * as Helpers from '@ioc:Adonis/Core/Helpers';
import { ConfigContract } from '@ioc:Adonis/Core/Config';
import { LoggerContract } from '@ioc:Adonis/Core/Logger';
import { ProfilerContract } from '@ioc:Adonis/Core/Profiler';
/**
* The interface that is meant to be extended in
* the user land and other packages
*/
export interface ContainerBindings {
'Adonis/Core/Application': ApplicationContract;
'Adonis/Core/Profiler': ProfilerContract;
'Adonis/Core/Logger': LoggerContract;
'Adonis/Core/Config': ConfigContract;
'Adonis/Core/Env': EnvContract;
'Adonis/Core/Helpers': typeof Helpers;
}
export type ApplicationStates = 'initiated' | 'setup' | 'registered' | 'booted' | 'ready' | 'shutdown';
/**
* Shape of directories object with known and unknown
* directories
*/
export interface DirectoriesNode {
config: string;
public: string;
contracts: string;
providers: string;
database: string;
migrations: string;
seeds: string;
resources: string;
views: string;
start: string;
tmp: string;
tests: string;
[key: string]: string;
}
/**
* Shape of namespaces object with known and unknown
* directories
*/
export interface NamespacesNode {
models: string;
exceptions: string;
middleware: string;
httpControllers: string;
eventListeners: string;
redisListeners: string;
validators: string;
[key: string]: string;
}
/**
* Application environments
*/
export type AppEnvironments = 'web' | 'console' | 'test' | 'repl' | 'unknown';
/**
* Shape of preload files
*/
export type PreloadNode = {
file: string;
environment: Exclude<AppEnvironments, 'unknown'>[];
optional: boolean;
};
/**
* Shape of semver node
*/
export type SemverNode = {
major: number;
minor: number;
patch: number;
prerelease: (string | number)[];
version: string;
toString(): string;
};
/**
* Shape of the meta file inside the `metaFiles` array inside
* `.adonisrc.json` file.
*/
export type MetaFileNode = {
pattern: string;
reloadServer: boolean;
};
/**
* Shape of rc file
*/
export type RcFile = {
typescript: boolean;
exceptionHandlerNamespace?: string;
assetsDriver?: AssetsDriver;
preloads: PreloadNode[];
metaFiles: MetaFileNode[];
commands: string[];
providers: string[];
aceProviders: string[];
testProviders: string[];
directories: DirectoriesNode;
commandsAliases: {
[key: string]: string;
};
aliases: {
[key: string]: string;
};
tests: {
suites: {
name: string;
files: string | string[];
timeout?: number;
}[];
forceExit: boolean;
timeout: number;
};
namespaces: NamespacesNode;
raw: any;
};
export type AssetsDriver = 'vite' | 'encore' | 'fake';
export interface ApplicationContract {
state: ApplicationStates;
/**
* Readonly reference to the parsed rc file
*/
readonly rcFile: RcFile;
/**
* Absolute path to the application root
*/
readonly appRoot: string;
/**
* Absolute path to the current working directory
*/
readonly cliCwd?: string;
/**
* Name of the application defined inside package.json file
*/
readonly appName: string;
/**
* Version of `@adonisjs/core` package
*/
readonly adonisVersion: SemverNode | null;
/**
* Version of the application defined inside package.json file
*/
readonly version: SemverNode | null;
/**
* A boolean to know if application source is written in Typescript.
*/
readonly typescript: boolean;
/**
* Application environment.
*
* - `console` is when running ace commands
* - `web` is when running http server
* - `test` is when running tests
*/
readonly environment: AppEnvironments;
/**
* Global exception handler namespace
*/
exceptionHandlerNamespace?: string;
/**
* The driver to use for assets bundling.
*/
assetsDriver?: AssetsDriver;
/**
* Reference to the IoC container
*/
container: IocContract<ContainerBindings>;
/**
* Available after the [[setup]] call
*/
logger: LoggerContract;
profiler: ProfilerContract;
env: EnvContract;
config: ConfigContract;
helpers: typeof Helpers;
/**
* Reference to preloads defined inside `.adonisrc.json` file
*/
preloads: PreloadNode[];
/**
* Value of `NODE_ENV`. But normalized in certain cases.
*
* - `development` - We normalize `dev`, `develop` to "development"
* - `staging` - We normalize `stage` to "staging"
* - `production` - We normalize `prod` to "production"
* - `testing` - We normalize `test` to "testing"
*
* Rest of the values remains untouched
*/
nodeEnvironment: string;
/**
* A boolean to know if application is ready
*/
readonly isReady: boolean;
/**
* A boolean to know if application is running in production
* mode
*/
inProduction: boolean;
/**
* A boolean to know if application is running in dev mode
*/
inDev: boolean;
/**
* Returns true when `this.nodeEnvironment === 'test'`
*/
inTest: boolean;
/**
* A boolean to know if application is tearing down
*/
isShuttingDown: boolean;
/**
* Reference to the relative paths of conventional and custom directories
* defined inside `.adonisrc.json` file
*/
directoriesMap: Map<string, string>;
/**
* Reference to the alias directories.
*/
aliasesMap: Map<string, string>;
/**
* Reference to the base namespaces for certain pre-defined
* directories
*/
namespacesMap: Map<string, string>;
/**
* Returns path for a given namespace by replacing the base namespace
* with the defined directories map inside the .adonisrc file.
*/
resolveNamespaceDirectory(namespaceFor: string): string | null;
/**
* Make path to a file or directory from the application root
*/
makePath(...paths: string[]): string;
/**
* Switch application environment. Only allowed before the setup
* is called
*/
switchEnvironment(environment: AppEnvironments): this;
/**
* Make path to a file or directory from the application source root
* @deprecated Use `makePath` instead
*/
makePathFromCwd(...paths: string[]): string;
/**
* Make path to a file or directory from the config directory root
*/
configPath(...paths: string[]): string;
/**
* Make path to a file or directory from the public directory root
*/
publicPath(...paths: string[]): string;
/**
* Make path to a file or directory from the database directory root
*/
databasePath(...paths: string[]): string;
/**
* Make path to a file or directory from the migrations directory root
*/
migrationsPath(...paths: string[]): string;
/**
* Make path to a file or directory from the seeds path root
*/
seedsPath(...paths: string[]): string;
/**
* Make path to a file or directory from the resources path root
*/
resourcesPath(...paths: string[]): string;
/**
* Make path to a file or directory from the views path root
*/
viewsPath(...paths: string[]): string;
/**
* Make path to a file or directory from the start path root
*/
startPath(...paths: string[]): string;
/**
* Make path to a file or directory from the tmp path root
*/
tmpPath(...paths: string[]): string;
/**
* Serialized output
*/
toJSON(): {
isReady: boolean;
isShuttingDown: boolean;
environment: AppEnvironments;
nodeEnvironment: string;
appName: string;
version: string | null;
adonisVersion: string | null;
};
/**
* Performs the initial setup. This is the time, when we configure the
* app to be able to boot itself. For example:
*
* - Loading environment variables
* - Loading config
* - Setting up the logger
* - Registering directory aliases
*
* Apart from the providers, most of the app including the container
* is ready at this stage
*/
setup(): Promise<void>;
/**
* Register providers
*/
registerProviders(): Promise<void>;
/**
* Booted providers
*/
bootProviders(): Promise<void>;
/**
* Registers the providers
*/
requirePreloads(): Promise<void>;
/**
* Start the application. At this time we execute the provider's
* ready hooks
*/
start(): Promise<void>;
/**
* Prepare the application for shutdown. At this time we execute the
* provider's shutdown hooks
*/
shutdown(): Promise<void>;
}
const Application: ApplicationContract;
export default Application;
/**
* Export Ioc Container static types
*/
export * from '@adonisjs/fold/build/src/Contracts';
}
@@ -0,0 +1,9 @@
/*
* @adonisjs/application
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// <reference path="./index.ts" />
@@ -0,0 +1,3 @@
declare module '@ioc:Adonis/Core/Helpers' {
export * from '@poppinss/utils/build/helpers';
}
@@ -0,0 +1,8 @@
/*
* @adonisjs/application
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
@@ -0,0 +1,6 @@
/// <reference path="application.d.ts" />
/// <reference path="helpers.d.ts" />
/// <reference types="@adonisjs/config/build/adonis-typings/config" />
/// <reference types="@adonisjs/env/build/adonis-typings/env" />
/// <reference types="@adonisjs/logger/build/adonis-typings/logger" />
/// <reference types="@adonisjs/profiler/build/adonis-typings/profiler" />
+14
View File
@@ -0,0 +1,14 @@
/*
* @adonisjs/application
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// <reference path="../node_modules/@adonisjs/config/build/adonis-typings/config.d.ts" />
/// <reference path="../node_modules/@adonisjs/env/build/adonis-typings/env.d.ts" />
/// <reference path="../node_modules/@adonisjs/logger/build/adonis-typings/logger.d.ts" />
/// <reference path="../node_modules/@adonisjs/profiler/build/adonis-typings/profiler.d.ts" />
/// <reference path="./application.ts" />
/// <reference path="./helpers.ts" />
+4
View File
@@ -0,0 +1,4 @@
export { Ioc, Registrar, inject } from '@adonisjs/fold';
export { Application } from './src/Application';
import * as rcParser from './src/rcParser';
export { rcParser };
+42
View File
@@ -0,0 +1,42 @@
"use strict";
/*
* @adonisjs/application
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.rcParser = exports.Application = exports.inject = exports.Registrar = exports.Ioc = void 0;
var fold_1 = require("@adonisjs/fold");
Object.defineProperty(exports, "Ioc", { enumerable: true, get: function () { return fold_1.Ioc; } });
Object.defineProperty(exports, "Registrar", { enumerable: true, get: function () { return fold_1.Registrar; } });
Object.defineProperty(exports, "inject", { enumerable: true, get: function () { return fold_1.inject; } });
var Application_1 = require("./src/Application");
Object.defineProperty(exports, "Application", { enumerable: true, get: function () { return Application_1.Application; } });
const rcParser = __importStar(require("./src/rcParser"));
exports.rcParser = rcParser;
+313
View File
@@ -0,0 +1,313 @@
/// <reference path="../adonis-typings/application.d.ts" />
import { RcFile, SemverNode, PreloadNode, AppEnvironments, ApplicationStates, ApplicationContract, AssetsDriver } from '@ioc:Adonis/Core/Application';
import { Logger } from '@adonisjs/logger';
import { Config } from '@adonisjs/config';
import { Profiler } from '@adonisjs/profiler';
import { Env } from '@adonisjs/env';
import * as helpers from '@poppinss/utils/build/helpers';
/**
* The main application instance to know about the environment, filesystem
* in which your AdonisJs app is running
*/
export declare class Application implements ApplicationContract {
readonly appRoot: string;
environment: AppEnvironments;
helpers: typeof helpers;
/**
* Available after setup call
*/
logger: Logger;
profiler: Profiler;
env: Env;
config: Config;
/**
* Available after registerProviders call
*/
private registrar;
/**
* An array of providers with ready and shutdown hooks.
*/
private providersWithReadyHook;
private providersWithShutdownHook;
state: ApplicationStates;
/**
* Current working directory for the CLI and not the build directory
* The `ADONIS_CLI_CWD` is set by the cli
*/
readonly cliCwd?: string;
/**
* The name of the application picked from `.adonisrc.json` file. This can
* be used to prefix logs.
*/
readonly appName: string;
/**
* The application version. Again picked from `.adonisrc.json` file
*/
readonly version: SemverNode | null;
/**
* `@adonisjs/core` version
*/
readonly adonisVersion: SemverNode | null;
/**
* Reference to fully parser rcFile
*/
readonly rcFile: RcFile;
/**
* The typescript flag indicates a couple of things, which can help tweak the tooling
* and runtime behavior of the application as well.
*
* 1. When `typescript=true`, it means that the project is written using typescript.
* 2. After compiling to Javascript, AdonisJs will set this value to `false` in the build folder.
* 3. At runtime when `typescript=true`, it means the app is using ts-node to start.
*/
readonly typescript: boolean;
/**
* A boolean to know if application has bootstrapped successfully
*/
get isReady(): boolean;
/**
* A boolean to know if app is preparing to shutdown
*/
isShuttingDown: boolean;
/**
* The namespace of exception handler that will handle exceptions
*/
exceptionHandlerNamespace?: string;
/**
* The driver to use for assets bundling
*/
assetsDriver?: AssetsDriver;
/**
* It is unknown until the `setup` method is called
*/
nodeEnvironment: 'unknown' | 'development' | 'production' | 'test' | string;
/**
* An array of files to be preloaded
*/
preloads: PreloadNode[];
/**
* A map of pre-configured directories
*/
directoriesMap: Map<string, string>;
/**
* A map of directories aliases
*/
aliasesMap: Map<string, string>;
/**
* A map of namespaces that different parts of apps
* can use
*/
namespacesMap: Map<string, string>;
/**
* Reference to the IoC container for the application
*/
container: ApplicationContract['container'];
constructor(appRoot: string, environment: AppEnvironments, rcContents?: any);
/**
* Verify the node version when defined under "engines" object in
* "packages.json" file.
*/
private verifyNodeEngine;
/**
* Resolve a given module from the application root. The callback is invoked
* when the module is missing
*/
private resolveModule;
/**
* Loads the rc file from the application root
*/
private loadRcFile;
/**
* Loads the package.json file from the application root. Swallows
* the exception when file is missing
*/
private loadAppPackageJson;
/**
* Loads the package.json file for the "@adonisjs/core" package. Swallows
* the exception when file is missing
*/
private loadCorePackageJson;
/**
* Parses version string to an object.
*/
private parseVersion;
/**
* Sets env variables based upon the provided application info.
*/
private setEnvVars;
/**
* Setup container globals to easily resolve bindings
*/
private setupGlobals;
/**
* Registering itself to the container
*/
private registerItselfToTheContainer;
/**
* Normalizes node env
*/
private normalizeNodeEnv;
/**
* Registering directory aliases
*/
private registerAliases;
/**
* Loads the environment variables by reading and parsing the
* `.env` and `.env.testing` files.
*/
private loadEnvironmentVariables;
/**
* Load config and define the container binding
*/
private loadConfig;
/**
* Setup logger
*/
private setupLogger;
/**
* Setup profiler
*/
private setupProfiler;
/**
* Setup helpers
*/
private setupHelpers;
/**
* Return true when `this.nodeEnvironment === 'production'`
*/
get inProduction(): boolean;
/**
* Opposite of [[this.isProduction]]
*/
get inDev(): boolean;
/**
* Returns true when `this.nodeEnvironment === 'test'`
*/
get inTest(): boolean;
/**
* Returns path for a given namespace by replacing the base namespace
* with the defined directories map inside the rc file.
*
* The method returns a relative path from the application root. You can
* use join it with the [[this.appRoot]] to make the absolute path
*/
resolveNamespaceDirectory(namespaceFor: string): string | null;
/**
* Make path to a file or directory relative from
* the application path
*/
makePath(...paths: string[]): string;
/**
* Makes the path to a directory from `cliCwd` vs the `appRoot`. This is
* helpful when we want path inside the project root and not the
* build directory
* @deprecated Use `makePath` instead
*/
makePathFromCwd(...paths: string[]): string;
/**
* Make path to a file or directory relative from
* the config directory
*/
configPath(...paths: string[]): string;
/**
* Make path to a file or directory relative from
* the public path
*/
publicPath(...paths: string[]): string;
/**
* Make path to a file or directory relative from
* the providers path
*/
providersPath(...paths: string[]): string;
/**
* Make path to a file or directory relative from
* the database path
*/
databasePath(...paths: string[]): string;
/**
* Make path to a file or directory relative from
* the migrations path
*/
migrationsPath(...paths: string[]): string;
/**
* Make path to a file or directory relative from
* the seeds path
*/
seedsPath(...paths: string[]): string;
/**
* Make path to a file or directory relative from
* the resources path
*/
resourcesPath(...paths: string[]): string;
/**
* Make path to a file or directory relative from
* the views path
*/
viewsPath(...paths: string[]): string;
/**
* Makes path to the start directory
*/
startPath(...paths: string[]): string;
/**
* Makes path to the tests directory
*/
testsPath(...paths: string[]): string;
/**
* Makes path to the tmp directory. Since the tmp path is used for
* writing at the runtime, we use `cwd` path to the write to the
* source and not the build directory.
*/
tmpPath(...paths: string[]): string;
/**
* Serialized output
*/
toJSON(): {
isReady: boolean;
isShuttingDown: boolean;
environment: AppEnvironments;
nodeEnvironment: string;
appName: string;
version: string | null;
adonisVersion: string | null;
};
/**
* Switch application environment. Only allowed before the setup
* is called
*/
switchEnvironment(environment: AppEnvironments): this;
/**
* Performs the initial setup. This is the time, when we configure the
* app to be able to boot itself. For example:
*
* - Loading environment variables
* - Loading config
* - Setting up the logger
* - Registering directory aliases
*
* Apart from the providers, most of the app including the container
* is ready at this stage
*/
setup(): Promise<void>;
/**
* Register providers
*/
registerProviders(): Promise<void>;
/**
* Booted providers
*/
bootProviders(): Promise<void>;
/**
* Require files registered as preloads inside `.adonisrc.json` file
*/
requirePreloads(): Promise<void>;
/**
* Start the application. At this time we execute the provider's
* ready hooks
*/
start(): Promise<void>;
/**
* Prepare the application for shutdown. At this time we execute the
* provider's shutdown hooks
*/
shutdown(): Promise<void>;
}
+622
View File
@@ -0,0 +1,622 @@
"use strict";
/*
* @adonisjs/application
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Application = void 0;
const path_1 = require("path");
const logger_1 = require("@adonisjs/logger");
const config_1 = require("@adonisjs/config");
const profiler_1 = require("@adonisjs/profiler");
const utils_1 = require("@poppinss/utils");
const fold_1 = require("@adonisjs/fold");
const env_1 = require("@adonisjs/env");
const helpers = __importStar(require("@poppinss/utils/build/helpers"));
const semver_1 = require("semver");
const rcParser_1 = require("./rcParser");
/**
* Aliases for different environments
*/
const DEV_ENVS = ['dev', 'develop', 'development'];
const PROD_ENVS = ['prod', 'production'];
const TEST_ENVS = ['test', 'testing'];
/**
* The main application instance to know about the environment, filesystem
* in which your AdonisJs app is running
*/
class Application {
/**
* A boolean to know if application has bootstrapped successfully
*/
get isReady() {
return this.state === 'ready' && !this.isShuttingDown;
}
constructor(appRoot, environment, rcContents) {
this.appRoot = appRoot;
this.environment = environment;
this.helpers = helpers;
/**
* An array of providers with ready and shutdown hooks.
*/
this.providersWithReadyHook = [];
this.providersWithShutdownHook = [];
this.state = 'initiated';
/**
* Current working directory for the CLI and not the build directory
* The `ADONIS_CLI_CWD` is set by the cli
*/
this.cliCwd = process.env.ADONIS_ACE_CWD;
/**
* A boolean to know if app is preparing to shutdown
*/
this.isShuttingDown = false;
/**
* It is unknown until the `setup` method is called
*/
this.nodeEnvironment = 'unknown';
/**
* An array of files to be preloaded
*/
this.preloads = [];
/**
* A map of pre-configured directories
*/
this.directoriesMap = new Map();
/**
* A map of directories aliases
*/
this.aliasesMap = new Map();
/**
* A map of namespaces that different parts of apps
* can use
*/
this.namespacesMap = new Map();
/**
* Reference to the IoC container for the application
*/
this.container = new fold_1.Ioc();
this.rcFile = (0, rcParser_1.parse)(rcContents || this.loadRcFile());
this.typescript = this.rcFile.typescript;
/**
* Loads the package.json files to collect optional
* info about the app.
*/
const pkgFile = this.loadAppPackageJson();
const corePkgFile = this.loadCorePackageJson();
this.verifyNodeEngine(pkgFile.engines);
/**
* Fetching following info from the package file
*/
this.appName = pkgFile.name;
this.version = this.parseVersion(pkgFile.version);
this.adonisVersion = corePkgFile.version ? this.parseVersion(corePkgFile.version) : null;
/**
* Fetching following info from the `.adonisrc.json` file.
*/
this.preloads = this.rcFile.preloads;
this.exceptionHandlerNamespace = this.rcFile.exceptionHandlerNamespace;
this.assetsDriver = this.rcFile.assetsDriver;
this.directoriesMap = new Map(Object.entries(this.rcFile.directories));
this.aliasesMap = new Map(Object.entries(this.rcFile.aliases));
this.namespacesMap = new Map(Object.entries(this.rcFile.namespaces));
this.setEnvVars();
this.setupGlobals();
this.registerItselfToTheContainer();
this.setupHelpers();
}
/**
* Verify the node version when defined under "engines" object in
* "packages.json" file.
*/
verifyNodeEngine(engines) {
const nodeEngine = engines?.node;
if (!nodeEngine) {
return;
}
if (!(0, semver_1.satisfies)(process.version, nodeEngine)) {
throw new utils_1.Exception(`The installed Node.js version "${process.version}" does not satisfy the expected version "${nodeEngine}" defined inside package.json file`, 500);
}
}
/**
* Resolve a given module from the application root. The callback is invoked
* when the module is missing
*/
resolveModule(modulePath, onMissingCallback) {
let filePath;
try {
filePath = helpers.resolveFrom(this.appRoot, modulePath);
return require(filePath);
}
catch (error) {
if (['ENOENT', 'MODULE_NOT_FOUND'].includes(error.code) &&
(!filePath || filePath === error.path)) {
return onMissingCallback(error);
}
else {
throw error;
}
}
}
/**
* Loads the rc file from the application root
*/
loadRcFile() {
return this.resolveModule('./.adonisrc.json', () => {
throw new Error('AdonisJS expects ".adonisrc.json" file to exist in the application root');
});
}
/**
* Loads the package.json file from the application root. Swallows
* the exception when file is missing
*/
loadAppPackageJson() {
const pkgFile = this.resolveModule('./package.json', () => {
return {};
});
return {
name: pkgFile.name || 'adonis-app',
version: pkgFile.version || '0.0.0',
engines: pkgFile.engines,
};
}
/**
* Loads the package.json file for the "@adonisjs/core" package. Swallows
* the exception when file is missing
*/
loadCorePackageJson() {
const pkgFile = this.resolveModule('@adonisjs/core/package.json', () => {
return {};
});
return {
version: pkgFile.version,
};
}
/**
* Parses version string to an object.
*/
parseVersion(version) {
const parsed = (0, semver_1.parse)(version);
if (!parsed) {
return null;
}
return {
major: parsed.major,
minor: parsed.minor,
patch: parsed.patch,
prerelease: parsed.prerelease.map((release) => release),
version: parsed.version,
toString() {
return this.version;
},
};
}
/**
* Sets env variables based upon the provided application info.
*/
setEnvVars() {
process.env.APP_NAME = this.appName;
if (this.version) {
process.env.APP_VERSION = this.version.toString();
}
if (this.adonisVersion) {
process.env.ADONIS_VERSION = this.adonisVersion.toString();
}
}
/**
* Setup container globals to easily resolve bindings
*/
setupGlobals() {
global[Symbol.for('ioc.use')] = this.container.use.bind(this.container);
global[Symbol.for('ioc.make')] = this.container.make.bind(this.container);
global[Symbol.for('ioc.call')] = this.container.call.bind(this.container);
}
/**
* Registering itself to the container
*/
registerItselfToTheContainer() {
this.container.singleton('Adonis/Core/Application', () => this);
}
/**
* Normalizes node env
*/
normalizeNodeEnv(env) {
if (!env || typeof env !== 'string') {
return 'unknown';
}
env = env.toLowerCase();
if (DEV_ENVS.includes(env)) {
return 'development';
}
if (PROD_ENVS.includes(env)) {
return 'production';
}
if (TEST_ENVS.includes(env)) {
return 'test';
}
return env;
}
/**
* Registering directory aliases
*/
registerAliases() {
this.aliasesMap.forEach((toPath, alias) => {
this.container.alias((0, path_1.join)(this.appRoot, toPath), alias);
});
}
/**
* Loads the environment variables by reading and parsing the
* `.env` and `.env.testing` files.
*/
loadEnvironmentVariables() {
/**
* Load `.env` and `.env.testing` files from the application root. The
* env loader handles the additional flags like
*
* ENV_SILENT = 'do not load the .env file'
* ENV_PATH = 'load .env file from given path'
* NODE_ENV = 'testing' will trigger optional loading of `.env.testing` file
*/
const { envContents, testEnvContent } = (0, env_1.envLoader)(this.appRoot);
/**
* Create instance of the Env class
*/
this.env = new env_1.Env([
{ values: new env_1.EnvParser(true).parse(envContents), overwriteExisting: false },
{ values: new env_1.EnvParser(false).parse(testEnvContent), overwriteExisting: true },
]);
this.container.singleton('Adonis/Core/Env', () => this.env);
/**
* Attempt to load `env.(ts|js)` files to setup the validation rules
*/
this.resolveModule('./env', () => { });
/**
* Process environment variables. This will trigger validations as well
*/
this.env.process();
/**
* Update node environment
*/
this.nodeEnvironment = this.normalizeNodeEnv(this.env.get('NODE_ENV'));
}
/**
* Load config and define the container binding
*/
loadConfig() {
this.config = new config_1.Config(helpers.requireAll(this.configPath()));
this.container.singleton('Adonis/Core/Config', () => this.config);
}
/**
* Setup logger
*/
setupLogger() {
const config = this.container.resolveBinding('Adonis/Core/Config').get('app.logger', {});
this.logger = new logger_1.Logger(config);
this.container.singleton('Adonis/Core/Logger', () => this.logger);
}
/**
* Setup profiler
*/
setupProfiler() {
const config = this.container.resolveBinding('Adonis/Core/Config').get('app.profiler', {});
const logger = this.container.resolveBinding('Adonis/Core/Logger');
this.profiler = new profiler_1.Profiler(this.appRoot, logger, config);
this.container.singleton('Adonis/Core/Profiler', () => this.profiler);
}
/**
* Setup helpers
*/
setupHelpers() {
this.container.bind('Adonis/Core/Helpers', () => helpers);
}
/**
* Return true when `this.nodeEnvironment === 'production'`
*/
get inProduction() {
return this.nodeEnvironment === 'production';
}
/**
* Opposite of [[this.isProduction]]
*/
get inDev() {
return !this.inProduction;
}
/**
* Returns true when `this.nodeEnvironment === 'test'`
*/
get inTest() {
return this.nodeEnvironment === 'test';
}
/**
* Returns path for a given namespace by replacing the base namespace
* with the defined directories map inside the rc file.
*
* The method returns a relative path from the application root. You can
* use join it with the [[this.appRoot]] to make the absolute path
*/
resolveNamespaceDirectory(namespaceFor) {
/**
* Return null when rcfile doesn't have a special
* entry for namespaces
*/
if (!this.rcFile.namespaces[namespaceFor]) {
return null;
}
let output = null;
Object.keys(this.rcFile.aliases).forEach((baseNamespace) => {
const autoloadPath = this.rcFile.aliases[baseNamespace];
if (this.rcFile.namespaces[namespaceFor].startsWith(`${baseNamespace}/`) ||
this.rcFile.namespaces[namespaceFor] === baseNamespace) {
output = this.rcFile.namespaces[namespaceFor].replace(baseNamespace, autoloadPath);
}
});
return output;
}
/**
* Make path to a file or directory relative from
* the application path
*/
makePath(...paths) {
return (0, path_1.join)(this.appRoot, ...paths);
}
/**
* Makes the path to a directory from `cliCwd` vs the `appRoot`. This is
* helpful when we want path inside the project root and not the
* build directory
* @deprecated Use `makePath` instead
*/
makePathFromCwd(...paths) {
process.emitWarning('DeprecationWarning', 'application.makePathFromCwd() is deprecated. Use application.makePath() instead');
return (0, path_1.join)(this.cliCwd || this.appRoot, ...paths);
}
/**
* Make path to a file or directory relative from
* the config directory
*/
configPath(...paths) {
return this.makePath(this.directoriesMap.get('config'), ...paths);
}
/**
* Make path to a file or directory relative from
* the public path
*/
publicPath(...paths) {
return this.makePath(this.directoriesMap.get('public'), ...paths);
}
/**
* Make path to a file or directory relative from
* the providers path
*/
providersPath(...paths) {
return this.makePath(this.directoriesMap.get('providers'), ...paths);
}
/**
* Make path to a file or directory relative from
* the database path
*/
databasePath(...paths) {
return this.makePath(this.directoriesMap.get('database'), ...paths);
}
/**
* Make path to a file or directory relative from
* the migrations path
*/
migrationsPath(...paths) {
return this.makePath(this.directoriesMap.get('migrations'), ...paths);
}
/**
* Make path to a file or directory relative from
* the seeds path
*/
seedsPath(...paths) {
return this.makePath(this.directoriesMap.get('seeds'), ...paths);
}
/**
* Make path to a file or directory relative from
* the resources path
*/
resourcesPath(...paths) {
return this.makePath(this.directoriesMap.get('resources'), ...paths);
}
/**
* Make path to a file or directory relative from
* the views path
*/
viewsPath(...paths) {
return this.makePath(this.directoriesMap.get('views'), ...paths);
}
/**
* Makes path to the start directory
*/
startPath(...paths) {
return this.makePath(this.directoriesMap.get('start'), ...paths);
}
/**
* Makes path to the tests directory
*/
testsPath(...paths) {
return this.makePath(this.directoriesMap.get('tests'), ...paths);
}
/**
* Makes path to the tmp directory. Since the tmp path is used for
* writing at the runtime, we use `cwd` path to the write to the
* source and not the build directory.
*/
tmpPath(...paths) {
return this.makePath(this.directoriesMap.get('tmp'), ...paths);
}
/**
* Serialized output
*/
toJSON() {
return {
isReady: this.isReady,
isShuttingDown: this.isShuttingDown,
environment: this.environment,
nodeEnvironment: this.nodeEnvironment,
appName: this.appName,
version: this.version ? this.version.toString() : null,
adonisVersion: this.adonisVersion ? this.adonisVersion.toString() : null,
};
}
/**
* Switch application environment. Only allowed before the setup
* is called
*/
switchEnvironment(environment) {
if (this.state !== 'initiated') {
throw new Error(`Cannot switch application environment in "${this.state}" state`);
}
this.environment = environment;
return this;
}
/**
* Performs the initial setup. This is the time, when we configure the
* app to be able to boot itself. For example:
*
* - Loading environment variables
* - Loading config
* - Setting up the logger
* - Registering directory aliases
*
* Apart from the providers, most of the app including the container
* is ready at this stage
*/
async setup() {
if (this.state !== 'initiated') {
return;
}
this.state = 'setup';
this.registerAliases();
this.loadEnvironmentVariables();
this.loadConfig();
this.setupLogger();
this.setupProfiler();
}
/**
* Register providers
*/
async registerProviders() {
if (this.state !== 'setup') {
return;
}
this.state = 'registered';
await this.profiler.profile('providers:register', {}, async () => {
const providers = this.rcFile.providers
.concat(this.rcFile.aceProviders)
.concat(this.inTest ? this.rcFile.testProviders : []);
this.logger.trace('registering providers', providers);
this.registrar = new fold_1.Registrar([this], this.appRoot);
const registeredProviders = await this.registrar
.useProviders(providers, (provider) => {
return new provider(this);
})
.register();
/**
* Keep reference of providers that are using ready or shutdown hooks
*/
registeredProviders.forEach((provider) => {
if (typeof provider.shutdown === 'function') {
this.providersWithShutdownHook.push(provider);
}
if (typeof provider.ready === 'function') {
this.providersWithReadyHook.push(provider);
}
});
});
}
/**
* Booted providers
*/
async bootProviders() {
if (this.state !== 'registered') {
return;
}
this.state = 'booted';
await this.profiler.profileAsync('providers:boot', {}, async () => {
this.logger.trace('booting providers');
await this.registrar.boot();
});
}
/**
* Require files registered as preloads inside `.adonisrc.json` file
*/
async requirePreloads() {
this.preloads
.filter((node) => {
if (!node.environment || this.environment === 'unknown') {
return true;
}
return node.environment.indexOf(this.environment) > -1;
})
.forEach((node) => {
this.profiler.profile('file:preload', node, () => {
this.logger.trace(node, 'file:preload');
this.resolveModule(node.file, (error) => {
if (!node.optional) {
throw error;
}
});
});
});
}
/**
* Start the application. At this time we execute the provider's
* ready hooks
*/
async start() {
if (this.state !== 'booted') {
return;
}
this.state = 'ready';
await this.profiler.profileAsync('providers:ready', {}, async () => {
this.logger.trace('executing providers ready hook');
await Promise.all(this.providersWithReadyHook.map((provider) => provider.ready()));
});
this.providersWithReadyHook = [];
}
/**
* Prepare the application for shutdown. At this time we execute the
* provider's shutdown hooks
*/
async shutdown() {
if (['initiated', 'setup'].includes(this.state)) {
return;
}
this.isShuttingDown = true;
this.state = 'shutdown';
await this.profiler.profileAsync('providers:shutdown', {}, async () => {
this.logger.trace('executing providers shutdown hook');
await Promise.all(this.providersWithShutdownHook.map((provider) => provider.shutdown()));
});
this.providersWithShutdownHook = [];
}
}
exports.Application = Application;
+9
View File
@@ -0,0 +1,9 @@
/// <reference path="../adonis-typings/application.d.ts" />
import { RcFile } from '@ioc:Adonis/Core/Application';
/**
* Parses the contents of `.adonisrc.json` file and merges it with the
* defaults
*/
export declare function parse(contents: {
[key: string]: any;
}): RcFile;
+138
View File
@@ -0,0 +1,138 @@
"use strict";
/*
* @adonisjs/application
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.parse = void 0;
/// <reference path="../adonis-typings/application.ts" />
const utils_1 = require("@poppinss/utils");
/**
* Default set of directories for AdonisJs
* applications
*/
const DEFAULT_DIRECTORIES = {
config: 'config',
public: 'public',
contracts: 'contracts',
providers: 'providers',
database: 'database',
migrations: 'database/migrations',
seeds: 'database/seeders',
resources: 'resources',
views: 'resources/views',
start: 'start',
tmp: 'tmp',
tests: 'tests',
};
/**
* A list of default namespaces.
*/
const DEFAULT_NAMESPACES = {
models: 'App/Models',
middleware: 'App/Middleware',
exceptions: 'App/Exceptions',
validators: 'App/Validators',
httpControllers: 'App/Controllers/Http',
eventListeners: 'App/Listeners',
redisListeners: 'App/Listeners',
};
/**
* Parses the contents of `.adonisrc.json` file and merges it with the
* defaults
*/
function parse(contents) {
const normalizedContents = Object.assign({
typescript: true,
directories: {},
namespaces: {},
preloads: [],
aliases: {},
commandsAliases: {},
metaFiles: [],
commands: [],
providers: [],
aceProviders: [],
testProviders: [],
tests: {
suites: [],
timeout: 2000,
forceExit: true,
},
}, contents);
/**
* Validate the assetsDriver value
*/
const { assetsDriver } = normalizedContents;
if (assetsDriver && !['vite', 'encore', 'fake'].includes(assetsDriver)) {
throw new utils_1.Exception(`Invalid assets driver "${assetsDriver}" defined in .adonisrc.json file`, 500, 'E_INVALID_ASSETS_DRIVER');
}
return {
typescript: normalizedContents.typescript,
...(assetsDriver ? { assetsDriver } : {}),
directories: Object.assign({}, DEFAULT_DIRECTORIES, normalizedContents.directories),
...(normalizedContents.exceptionHandlerNamespace
? { exceptionHandlerNamespace: normalizedContents.exceptionHandlerNamespace }
: {}),
preloads: normalizedContents.preloads.map((preload, index) => {
if (typeof preload === 'string') {
return {
file: preload,
optional: false,
environment: ['web', 'console', 'test', 'repl'],
};
}
if (!preload.file) {
throw new utils_1.Exception(`Invalid value for preloads[${index}]`, 500, 'E_PRELOAD_MISSING_FILE_PROPERTY');
}
return {
file: preload.file,
optional: preload.optional === undefined ? false : preload.optional,
environment: preload.environment === undefined
? ['web', 'console', 'test', 'repl']
: preload.environment,
};
}),
namespaces: Object.assign({}, DEFAULT_NAMESPACES, normalizedContents.namespaces),
aliases: Object.assign({}, normalizedContents.autoloads, normalizedContents.aliases),
metaFiles: normalizedContents.metaFiles.map((file, index) => {
if (typeof file === 'string') {
return {
pattern: file,
reloadServer: true,
};
}
const { pattern, reloadServer } = file;
if (!pattern) {
throw new utils_1.Exception(`Invalid value for metaFiles[${index}]`, 500, 'E_METAFILE_MISSING_PATTERN');
}
return {
pattern,
reloadServer: !!reloadServer,
};
}),
commands: normalizedContents.commands,
commandsAliases: normalizedContents.commandsAliases,
providers: normalizedContents.providers,
aceProviders: normalizedContents.aceProviders,
testProviders: normalizedContents.testProviders,
tests: {
suites: (normalizedContents.tests.suites || []).map((suite, index) => {
if (!suite.name || !suite.files) {
throw new utils_1.Exception(`Invalid value for "tests.suites[${index}]"`, 500, 'E_MISSING_SUITE_PROPERTIES');
}
return suite;
}),
timeout: normalizedContents.tests.timeout !== undefined ? normalizedContents.tests.timeout : 2000,
forceExit: normalizedContents.tests.forceExit !== undefined
? normalizedContents.tests.forceExit
: true,
},
raw: contents,
};
}
exports.parse = parse;
+148
View File
@@ -0,0 +1,148 @@
{
"name": "@adonisjs/application",
"version": "5.3.0",
"description": "AdonisJS application class to read app related data",
"main": "build/index.js",
"files": [
"build/adonis-typings",
"build/src",
"build/index.d.ts",
"build/index.js"
],
"scripts": {
"mrm": "mrm --preset=@adonisjs/mrm-preset",
"pretest": "npm run lint",
"test": "node -r @adonisjs/require-ts/build/register bin/test.ts",
"clean": "del-cli build",
"compile": "npm run lint && npm run clean && tsc",
"build": "npm run compile",
"commit": "git-cz",
"release": "np --message=\"chore(release): %s\"",
"version": "npm run build",
"prepublishOnly": "npm run build",
"lint": "eslint . --ext=.ts",
"format": "prettier --write .",
"sync-labels": "github-label-sync --labels ./node_modules/@adonisjs/mrm-preset/gh-labels.json adonisjs/application"
},
"keywords": [
"adonisjs",
"app"
],
"author": "virk,adonisjs",
"license": "MIT",
"devDependencies": {
"@adonisjs/mrm-preset": "^5.0.3",
"@adonisjs/require-ts": "^2.0.13",
"@japa/assert": "^1.3.6",
"@japa/run-failed-tests": "^1.1.0",
"@japa/runner": "^2.2.2",
"@japa/spec-reporter": "^1.3.2",
"@poppinss/dev-utils": "^2.0.3",
"@types/node": "^18.11.9",
"@types/semver": "^7.3.13",
"commitizen": "^4.2.5",
"cz-conventional-changelog": "^3.3.0",
"del-cli": "^5.0.0",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-adonis": "^2.1.1",
"eslint-plugin-prettier": "^4.2.1",
"github-label-sync": "^2.2.0",
"husky": "^8.0.2",
"jsonschema": "^1.4.1",
"mrm": "^4.1.13",
"np": "^7.6.2",
"prettier": "^2.7.1",
"typescript": "^4.9.3"
},
"nyc": {
"exclude": [
"test"
],
"extension": [
".ts"
]
},
"husky": {
"hooks": {
"commit-msg": "node ./node_modules/@adonisjs/mrm-preset/validateCommit/conventional/validate.js"
}
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
},
"dependencies": {
"@adonisjs/config": "^3.0.9",
"@adonisjs/env": "^3.0.9",
"@adonisjs/fold": "^8.2.0",
"@adonisjs/logger": "^4.1.5",
"@adonisjs/profiler": "^6.0.9",
"@poppinss/utils": "^5.0.0",
"semver": "^7.3.8"
},
"np": {
"contents": ".",
"anyBranch": false
},
"directories": {
"doc": "docs",
"test": "test"
},
"repository": {
"type": "git",
"url": "git+https://github.com/adonisjs/application.git"
},
"bugs": {
"url": "https://github.com/adonisjs/application/issues"
},
"homepage": "https://github.com/adonisjs/application#readme",
"publishConfig": {
"access": "public",
"tag": "latest"
},
"mrmConfig": {
"core": true,
"license": "MIT",
"services": [
"github-actions"
],
"minNodeVersion": "14.15.4",
"probotApps": [
"stale",
"lock"
],
"runGhActionsOnWindows": false
},
"eslintConfig": {
"extends": [
"plugin:adonis/typescriptPackage",
"prettier"
],
"plugins": [
"prettier"
],
"rules": {
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
]
}
},
"eslintIgnore": [
"build"
],
"prettier": {
"trailingComma": "es5",
"semi": false,
"singleQuote": true,
"useTabs": false,
"quoteProps": "consistent",
"bracketSpacing": true,
"arrowParens": "always",
"printWidth": 100
}
}