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
+4
View File
@@ -0,0 +1,4 @@
export * from './src/Contracts';
export { Ioc } from './src/Ioc';
export { inject } from './src/decorators';
export { Registrar } from './src/Registrar';
+32
View File
@@ -0,0 +1,32 @@
"use strict";
/*
* @adonisjs/fold
*
* (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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Registrar = exports.inject = exports.Ioc = void 0;
__exportStar(require("./src/Contracts"), exports);
var Ioc_1 = require("./src/Ioc");
Object.defineProperty(exports, "Ioc", { enumerable: true, get: function () { return Ioc_1.Ioc; } });
var decorators_1 = require("./src/decorators");
Object.defineProperty(exports, "inject", { enumerable: true, get: function () { return decorators_1.inject; } });
var Registrar_1 = require("./src/Registrar");
Object.defineProperty(exports, "Registrar", { enumerable: true, get: function () { return Registrar_1.Registrar; } });
+252
View File
@@ -0,0 +1,252 @@
declare type Function = (...args: any[]) => any;
export declare type ExtractFunctions<T> = {
[P in keyof T]: T[P] extends Function ? P : never;
}[keyof T];
/**
* Unwraps the promise
*/
declare type UnWrapPromise<T> = T extends Promise<infer U> ? U : T;
/**
* Shape of the bind callback method
*/
export declare type BindCallback<ReturnValue extends any, Container extends IocContract> = (container: Container) => ReturnValue;
/**
* Shape of the fake callback method
*/
export declare type FakeCallback<ReturnValue extends any, Container extends IocContract> = (container: Container, originalValue: ReturnValue) => ReturnValue;
/**
* Shape of resolved lookup node, resolved using `getResolver().resolve()`
* method.
*/
export declare type IocResolverLookupNode<Namespace extends string> = {
namespace: Namespace;
type: 'binding' | 'alias';
method: string;
};
/**
* Shape of class constructor
*/
export declare type Constructor<T> = new (...args: any[]) => T;
/**
* Shape of class constructor with `makePlain` property
*/
export declare type PlainConstructor = {
makePlain: true;
};
/**
* Type of the "withBindings" method
*/
export interface WithBindings<ContainerBindings extends any> {
<Bindings extends (keyof ContainerBindings)[]>(namespaces: [...Bindings], cb: (...args: {
[M in keyof Bindings]: Bindings[M] extends keyof ContainerBindings ? ContainerBindings[Bindings[M]] : any;
}) => void): void;
<Namespace extends (keyof ContainerBindings | string)[]>(namespaces: readonly [...Namespace], cb: (...args: {
[M in keyof Namespace]: Namespace[M] extends keyof ContainerBindings ? ContainerBindings[Namespace[M]] : any;
}) => void): void;
}
/**
* Finding return type of the `ioc.make` method based upon the
* input argument.
*
* - String and LookupNode = Returns any
* - Class constructor with "makePlain" are returned as it is
* - Otherwise an instance of the class constructor is returned
* - All other values are returned as it is
*/
export declare type InferMakeType<T> = T extends string | LookupNode<string> ? any : T extends PlainConstructor ? T : T extends Constructor<infer A> ? A : T;
/**
* Shape of lookup node pulled using `ioc.lookup` method. This node
* can be passed to `ioc.use`, or `ioc.make` to skip many checks
* and resolve the binding right away.
*/
export declare type LookupNode<Namespace extends string> = {
namespace: Namespace;
type: 'binding' | 'alias';
};
/**
* Ioc container interface
*/
export interface IocContract<ContainerBindings extends any = any> {
/**
* Registered aliases. The key is the alias and value is the
* absolute directory path
*/
importAliases: {
[alias: string]: string;
};
/**
* Enable/disable proxies. Proxies are mainly required for fakes to
* work
*/
useProxies(enable?: boolean): this;
/**
* Define the module type for resolving auto import aliases. Defaults
* to `cjs`
*/
module: 'cjs' | 'esm';
/**
* Register a binding with a callback. The callback return value will be
* used when binding is resolved
*/
bind<Binding extends keyof ContainerBindings>(binding: Binding, callback: BindCallback<ContainerBindings[Binding], this>): this;
bind<Binding extends string>(binding: Binding, callback: BindCallback<Binding extends keyof ContainerBindings ? ContainerBindings[Binding] : any, this>): this;
/**
* Same as the [[bind]] method, but registers a singleton only. Singleton's callback
* is invoked only for the first time and then the cached value is used
*/
singleton<Binding extends keyof ContainerBindings>(binding: Binding, callback: BindCallback<ContainerBindings[Binding], this>): this;
singleton<Binding extends string>(binding: Binding, callback: BindCallback<Binding extends keyof ContainerBindings ? ContainerBindings[Binding] : any, this>): this;
/**
* Define an import alias
*/
alias(absolutePath: string, alias: string): this;
/**
* Register a fake for a namespace. Fakes works both for "bindings" and "import aliases".
* Fakes only work when proxies are enabled using "useProxies".
*/
fake<Namespace extends keyof ContainerBindings>(namespace: Namespace, callback: FakeCallback<ContainerBindings[Namespace], this>): this;
fake<Namespace extends string>(namespace: Namespace, callback: FakeCallback<Namespace extends keyof ContainerBindings ? ContainerBindings[Namespace] : any, this>): this;
/**
* Clear selected or all the fakes. Calling the method with no arguments
* will clear all the fakes
*/
restore<Namespace extends keyof ContainerBindings>(namespace?: Namespace): this;
restore(namespace?: string): this;
/**
* Find if a fake has been registered for a given namespace
*/
hasFake<Namespace extends keyof ContainerBindings>(namespace: Namespace): boolean;
hasFake(namespace: string): boolean;
/**
* Find if a binding exists for a given namespace
*/
hasBinding<Binding extends keyof ContainerBindings>(namespace: Binding): boolean;
hasBinding(namespace: string): boolean;
/**
* Find if a namespace is part of the auto import aliases. Returns false, when namespace
* is an alias path but has an explicit binding too
*/
isAliasPath(namespace: string): boolean;
/**
* Lookup a namespace. The output contains the complete namespace,
* along with its type. The type is an "alias" or a "binding".
*
* Null is returned when unable to lookup the namespace inside the container
*
* Note: This method just checks if a namespace is registered or binding
* or can be it resolved from auto import aliases or not. However,
* it doesn't check for the module existence on the disk.
*
* Optionally you can define a prefix namespace
* to be used to build the complete namespace. For example:
*
* - namespace: UsersController
* - prefixNamespace: App/Controllers/Http
* - Output: App/Controllers/Http/UsersController
*
* Prefix namespace is ignored for absolute namespaces. For example:
*
* - namespace: /App/UsersController
* - prefixNamespace: App/Controllers/Http
* - Output: App/UsersController
*/
lookup<Namespace extends Extract<keyof ContainerBindings, string>>(namespace: Namespace | LookupNode<Namespace>, prefixNamespace?: string): LookupNode<Namespace>;
lookup<Namespace extends string>(namespace: Namespace | LookupNode<Namespace>, prefixNamespace?: string): Namespace extends keyof ContainerBindings ? LookupNode<Namespace> : LookupNode<string> | null;
/**
* Same as [[lookup]]. But raises exception instead of returning null
*/
lookupOrFail<Namespace extends Extract<keyof ContainerBindings, string>>(namespace: Namespace | LookupNode<Namespace>, prefixNamespace?: string): LookupNode<Namespace>;
lookupOrFail<Namespace extends string>(namespace: Namespace | LookupNode<Namespace>, prefixNamespace?: string): Namespace extends keyof ContainerBindings ? LookupNode<Namespace> : LookupNode<string>;
/**
* Resolve a binding by invoking the binding factory function. An exception
* is raised, if the binding namespace is unregistered.
*/
resolveBinding<Binding extends Extract<keyof ContainerBindings, string>>(binding: Binding): ContainerBindings[Binding];
resolveBinding<Binding extends string>(namespace: Binding): Binding extends keyof ContainerBindings ? ContainerBindings[Binding] : any;
/**
* Import namespace from the auto import aliases. This method assumes you are
* using native ES modules
*/
import(namespace: string): Promise<any>;
/**
* Same as the "import" method, but uses CJS for requiring the module from its
* path
*/
require(namespace: string): any;
/**
* The use method looks up a namespace inside both the bindings and the
* auto import aliases
*/
use<Binding extends Extract<keyof ContainerBindings, string>>(lookupNode: Binding | LookupNode<Binding>): ContainerBindings[Binding];
use<Binding extends string>(lookupNode: Binding | LookupNode<Binding>): Binding extends keyof ContainerBindings ? ContainerBindings[Binding] : any;
/**
* Same as the [[use]] method, but instead uses ES modules for resolving
* the auto import aliases
*/
useAsync<Binding extends Extract<keyof ContainerBindings, string>>(lookupNode: Binding | LookupNode<Binding>): Promise<ContainerBindings[Binding]>;
useAsync<Binding extends string>(lookupNode: Binding | LookupNode<Binding>): Promise<Binding extends keyof ContainerBindings ? ContainerBindings[Binding] : any>;
/**
* Makes an instance of the class by first resolving it.
*/
make<Binding extends Extract<keyof ContainerBindings, string>>(lookupNode: Binding | LookupNode<Binding>, args?: any[]): ContainerBindings[Binding];
make<T extends any>(value: T | LookupNode<string>, args?: any[]): T extends keyof ContainerBindings ? ContainerBindings[T] : InferMakeType<T>;
/**
* Same as the [[make]] method, but instead uses ES modules for resolving
* the auto import aliases
*/
makeAsync<Binding extends Extract<keyof ContainerBindings, string>>(lookupNode: Binding | LookupNode<Binding>, args?: any[]): Promise<ContainerBindings[Binding]>;
makeAsync<T extends any>(value: T | LookupNode<string>, args?: any[]): Promise<T extends keyof ContainerBindings ? ContainerBindings[T] : InferMakeType<T>>;
/**
* The "withBindings" method invokes the defined callback when it is
* able to resolve all the mentioned bindings.
*/
withBindings: WithBindings<ContainerBindings>;
/**
* @deprecated: Use "withBindings" instead
*/
with: WithBindings<ContainerBindings>;
/**
* Call a method on an object and automatically inject its depdencies
*/
call<T extends any, Method extends ExtractFunctions<T>>(target: T, method: Method, args?: any[]): T[Method] extends Function ? ReturnType<T[Method]> : any;
/**
* Call a method on an object and automatically inject its depdencies
*/
callAsync<T extends any, Method extends ExtractFunctions<T>>(target: T, method: Method, args?: any[]): T[Method] extends Function ? Promise<UnWrapPromise<ReturnType<T[Method]>>> : Promise<any>;
/**
* Trap container lookup calls. It includes
*
* - Ioc.use
* - Ioc.useAsync
* - Ioc.make
* - Ioc.makeAsync
* - Ioc.require
* - Ioc.import
* - Ioc.resolveBinding
*/
trap(callback: (namespace: string) => any): this;
/**
* Returns the resolver instance to resolve Ioc container bindings with
* little ease. Since, the IocResolver uses an in-memory cache to
* improve the lookup speed, we suggest keeping a reference to
* the output of this method to leverage caching
*/
getResolver(fallbackMethod?: string, rcNamespaceKey?: string, fallbackNamespace?: string): IocResolverContract<ContainerBindings>;
}
/**
* IoC resolver allows resolving IoC container bindings by defining
* prefix namespaces
*/
export interface IocResolverContract<ContainerBindings extends any> {
/**
* Resolve IoC container binding
*/
resolve<Namespace extends Extract<keyof ContainerBindings, string>>(namespace: Namespace, prefixNamespace?: string): IocResolverLookupNode<Namespace>;
resolve<Namespace extends string>(namespace: Namespace, prefixNamespace?: string): Namespace extends keyof ContainerBindings ? IocResolverLookupNode<Namespace> : IocResolverLookupNode<string>;
/**
* Call method on an IoC container binding
*/
call<Namespace extends Extract<keyof ContainerBindings, string>>(namespace: Namespace | string, prefixNamespace?: string, args?: any[] | ((instance: any) => any[])): Promise<any>;
call<Namespace extends Extract<keyof ContainerBindings, string>>(namespace: IocResolverLookupNode<Namespace | string>, prefixNamespace: undefined, args?: any[] | ((instance: any) => any[])): Promise<any>;
}
export {};
+10
View File
@@ -0,0 +1,10 @@
"use strict";
/*
* @adonisjs/fold
*
* (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 });
@@ -0,0 +1,8 @@
import { Exception } from '@poppinss/utils';
/**
* Raised when trying to inject a primitive value like "StringConstructor"
* to a class constructor or method
*/
export declare class InvalidInjectionException extends Exception {
static invoke(value: any, parentName: string, index: number): InvalidInjectionException;
}
@@ -0,0 +1,23 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.InvalidInjectionException = void 0;
const utils_1 = require("@poppinss/utils");
/**
* Raised when trying to inject a primitive value like "StringConstructor"
* to a class constructor or method
*/
class InvalidInjectionException extends utils_1.Exception {
static invoke(value, parentName, index) {
const primitiveName = `{${value.name} Constructor}`;
return new this(`Cannot inject "${primitiveName}" to "${parentName}" at position "${index + 1}"`);
}
}
exports.InvalidInjectionException = InvalidInjectionException;
@@ -0,0 +1,15 @@
import { Exception } from '@poppinss/utils';
/**
* Raised when unable to lookup a namespace
*/
export declare class IocLookupException extends Exception {
static lookupFailed(namespace: string): IocLookupException;
/**
* Invalid namespace type
*/
static invalidNamespace(): IocLookupException;
/**
* Fake is missing and yet resolved
*/
static missingFake(namespace: string): IocLookupException;
}
+33
View File
@@ -0,0 +1,33 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.IocLookupException = void 0;
const utils_1 = require("@poppinss/utils");
/**
* Raised when unable to lookup a namespace
*/
class IocLookupException extends utils_1.Exception {
static lookupFailed(namespace) {
return new this(`Cannot resolve "${namespace}" namespace from the IoC Container`, 500, 'E_IOC_LOOKUP_FAILED');
}
/**
* Invalid namespace type
*/
static invalidNamespace() {
return new this('"Ioc.lookup" accepts a namespace string or a lookup node', 500, 'E_INVALID_IOC_NAMESPACE');
}
/**
* Fake is missing and yet resolved
*/
static missingFake(namespace) {
return new this(`Cannot resolve fake for "${namespace}" namespace`, 500, 'E_MISSING_IOC_FAKE');
}
}
exports.IocLookupException = IocLookupException;
+24
View File
@@ -0,0 +1,24 @@
import { IocContract, BindCallback } from '../Contracts';
/**
* Manages the IoC container bindings
*/
export declare class Bindings {
private container;
/**
* Registered bindings
*/
private list;
constructor(container: IocContract);
/**
* Find if namespace is a binding
*/
has(namespace: string): boolean;
/**
* Define a binding
*/
register(binding: string, callback: BindCallback<any, IocContract>, singleton: boolean): this;
/**
* Resolve a binding. An exception is raised, if the binding is missing
*/
resolve(binding: string): any;
}
+56
View File
@@ -0,0 +1,56 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.Bindings = void 0;
const IocLookupException_1 = require("../Exceptions/IocLookupException");
/**
* Manages the IoC container bindings
*/
class Bindings {
constructor(container) {
this.container = container;
/**
* Registered bindings
*/
this.list = new Map();
}
/**
* Find if namespace is a binding
*/
has(namespace) {
return this.list.has(namespace);
}
/**
* Define a binding
*/
register(binding, callback, singleton) {
this.list.set(binding, { callback, singleton });
return this;
}
/**
* Resolve a binding. An exception is raised, if the binding is missing
*/
resolve(binding) {
const bindingNode = this.list.get(binding);
if (!bindingNode) {
throw IocLookupException_1.IocLookupException.lookupFailed(binding);
}
let resolvedValue;
if (bindingNode.singleton) {
bindingNode.cachedValue = bindingNode.cachedValue ?? bindingNode.callback(this.container);
resolvedValue = bindingNode.cachedValue;
}
else {
resolvedValue = bindingNode.callback(this.container);
}
return resolvedValue;
}
}
exports.Bindings = Bindings;
+33
View File
@@ -0,0 +1,33 @@
import { FakeCallback, IocContract } from '../Contracts';
/**
* Manages the container fakes
*/
export declare class Fakes {
private container;
/**
* Registered fakes
*/
private list;
constructor(container: IocContract);
/**
* Register a fake for a given namespace
*/
register(namespace: string, callback: FakeCallback<any, IocContract>): this;
/**
* Find if namespace has a fake registered
*/
has(namespace: string): boolean;
/**
* Clear all fakes
*/
clear(): void;
/**
* Delete fake for a given namespace
*/
delete(namespace: string): boolean;
/**
* Resolve the fake for a given namespace. An exception is raised if
* not fake is defined
*/
resolve(namespace: string, originalValue: any): boolean;
}
+62
View File
@@ -0,0 +1,62 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.Fakes = void 0;
const IocLookupException_1 = require("../Exceptions/IocLookupException");
/**
* Manages the container fakes
*/
class Fakes {
constructor(container) {
this.container = container;
/**
* Registered fakes
*/
this.list = new Map();
}
/**
* Register a fake for a given namespace
*/
register(namespace, callback) {
this.list.set(namespace, { callback });
return this;
}
/**
* Find if namespace has a fake registered
*/
has(namespace) {
return this.list.has(namespace);
}
/**
* Clear all fakes
*/
clear() {
return this.list.clear();
}
/**
* Delete fake for a given namespace
*/
delete(namespace) {
return this.list.delete(namespace);
}
/**
* Resolve the fake for a given namespace. An exception is raised if
* not fake is defined
*/
resolve(namespace, originalValue) {
const fake = this.list.get(namespace);
if (!fake) {
throw IocLookupException_1.IocLookupException.missingFake(namespace);
}
fake.cachedValue = fake.cachedValue ?? fake.callback(this.container, originalValue);
return fake.cachedValue;
}
}
exports.Fakes = Fakes;
+43
View File
@@ -0,0 +1,43 @@
import { IocContract } from '../Contracts';
/**
* Manages the import aliases
*/
export declare class ImportAliases {
private container;
/**
* Registered aliases
*/
list: {
[alias: string]: string;
};
/**
* In-memory require cache to speed up lookup calls. Yes, "require"
* is slow. Check "perf/require.js"
*/
private requireCache;
constructor(container: IocContract);
/**
* Returns the matching alias for the given namespace
*/
private getPathAlias;
/**
* Returns path for a given alias
*/
private makeAliasPath;
/**
* Register an import alias
*/
register(absolutePath: string, alias: string): this;
/**
* Find if a namespace is part of the import aliases
*/
has(namespace: string): boolean;
/**
* Import the namespace from the registered import aliases.
*/
resolve(namespace: string): any;
/**
* Same as [[resolve]] but uses ES modules
*/
resolveAsync(namespace: string): Promise<any>;
}
+130
View File
@@ -0,0 +1,130 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.ImportAliases = void 0;
const path_1 = require("path");
const IocLookupException_1 = require("../Exceptions/IocLookupException");
/**
* Manages the import aliases
*/
class ImportAliases {
constructor(container) {
this.container = container;
/**
* Registered aliases
*/
this.list = {};
/**
* In-memory require cache to speed up lookup calls. Yes, "require"
* is slow. Check "perf/require.js"
*/
this.requireCache = new Map();
}
/**
* Returns the matching alias for the given namespace
*/
getPathAlias(namespace) {
return Object.keys(this.list).find((alias) => {
return namespace.startsWith(`${alias}/`);
});
}
/**
* Returns path for a given alias
*/
makeAliasPath(namespace, alias) {
return (0, path_1.normalize)(namespace.replace(alias, this.list[alias]));
}
/**
* Register an import alias
*/
register(absolutePath, alias) {
this.list[alias] = absolutePath;
return this;
}
/**
* Find if a namespace is part of the import aliases
*/
has(namespace) {
return !!this.getPathAlias(namespace);
}
/**
* Import the namespace from the registered import aliases.
*/
resolve(namespace) {
const alias = this.getPathAlias(namespace);
if (!alias) {
throw IocLookupException_1.IocLookupException.lookupFailed(namespace);
}
const cacheItem = this.requireCache.get(namespace);
if (cacheItem) {
return cacheItem.value;
}
/**
* Absolute path to the module
*/
const diskPath = this.makeAliasPath(namespace, alias);
/**
* Require the module
*/
const value = require(diskPath);
/**
* Cache the output
*/
this.requireCache.set(namespace, { diskPath, value });
/**
* Return the value
*/
return value;
}
/**
* Same as [[resolve]] but uses ES modules
*/
async resolveAsync(namespace) {
/**
* Piggy back on resolve when using cjs module system
*/
if (this.container.module === 'cjs') {
return this.resolve(namespace);
}
const alias = this.getPathAlias(namespace);
if (!alias) {
throw IocLookupException_1.IocLookupException.lookupFailed(namespace);
}
/**
* Import the module. The following code will only compile to esm
* when the output of this build is esm
*/
return Promise.resolve().then(() => __importStar(require(this.makeAliasPath(namespace, alias))));
}
}
exports.ImportAliases = ImportAliases;
+42
View File
@@ -0,0 +1,42 @@
import { IocContract } from '../Contracts';
/**
* Exposes the API to injecting dependencies to a class or a method
*/
export declare class Injector {
private container;
constructor(container: IocContract);
/**
* Resolves the injections to be injected to a method or the
* class constructor
*/
private resolve;
/**
* Resolves the injections to be injected to a method or the
* class constructor
*/
private resolveAsync;
/**
* Find if the value can be instantiated
*/
private isNewable;
/**
* Get injections for a given property from the target
*/
private getInjections;
/**
* Inject dependencies to the constructor of the class
*/
make(target: any, runtimeValues: any[]): any;
/**
* Inject dependencies asynchronously to the constructor of the class
*/
makeAsync(target: any, runtimeValues: any[]): Promise<any>;
/**
* Injects dependencies to the class method
*/
call(target: any, method: string, runtimeValues: any[]): any;
/**
* Injects dependencies asynchronously to the class method
*/
callAsync(target: any, method: string, runtimeValues: any[]): Promise<any>;
}
+127
View File
@@ -0,0 +1,127 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.Injector = void 0;
const helpers_1 = require("../helpers");
const helpers_2 = require("@poppinss/utils/build/helpers");
const InvalidInjectionException_1 = require("../Exceptions/InvalidInjectionException");
/**
* Exposes the API to injecting dependencies to a class or a method
*/
class Injector {
constructor(container) {
this.container = container;
}
/**
* Resolves the injections to be injected to a method or the
* class constructor
*/
resolve(targetName, injections, runtimeValues) {
/**
* If the runtime values length is greater or same as the length
* of injections, then we treat them as the source of truth
* and inject them as it is
*/
if (runtimeValues.length >= injections.length) {
return runtimeValues;
}
/**
* Loop over all the injections and give preference to runtime value
* for a given index, otherwise fallback to `container.make`.
*/
return injections.map((injection, index) => {
if (runtimeValues[index] !== undefined) {
return runtimeValues[index];
}
/**
* Disallow object and primitive constructors
*/
if ((0, helpers_1.isPrimtiveConstructor)(injection)) {
throw InvalidInjectionException_1.InvalidInjectionException.invoke(injections[index], targetName, index);
}
return this.container.make(injection);
});
}
/**
* Resolves the injections to be injected to a method or the
* class constructor
*/
async resolveAsync(targetName, injections, runtimeValues) {
/**
* If the runtime values length is greater or same as the length
* of injections, then we treat them as the source of truth
* and inject them as it is
*/
if (runtimeValues.length >= injections.length) {
return runtimeValues;
}
/**
* Loop over all the injections and give preference to runtime value
* for a given index, otherwise fallback to `container.makeAsync`.
*/
return Promise.all(injections.map((injection, index) => {
if (runtimeValues[index] !== undefined) {
return runtimeValues[index];
}
/**
* Disallow object and primitive constructors
*/
if ((0, helpers_1.isPrimtiveConstructor)(injection)) {
throw InvalidInjectionException_1.InvalidInjectionException.invoke(injections[index], targetName, index);
}
return this.container.makeAsync(injection);
}));
}
/**
* Find if the value can be instantiated
*/
isNewable(target) {
return (helpers_2.types.isFunction(target) || helpers_2.types.isClass(target)) && target.makePlain !== true;
}
/**
* Get injections for a given property from the target
*/
getInjections(target, prop) {
return target.hasOwnProperty('inject') ? target.inject[prop] || [] : [];
}
/**
* Inject dependencies to the constructor of the class
*/
make(target, runtimeValues) {
if (!this.isNewable(target)) {
return target;
}
return new target(...this.resolve(target.name, this.getInjections(target, 'instance'), runtimeValues));
}
/**
* Inject dependencies asynchronously to the constructor of the class
*/
async makeAsync(target, runtimeValues) {
if (!this.isNewable(target)) {
return target;
}
return new target(...(await this.resolveAsync(target.name, this.getInjections(target, 'instance'), runtimeValues)));
}
/**
* Injects dependencies to the class method
*/
call(target, method, runtimeValues) {
const constructor = target.constructor;
return target[method](...this.resolve(`${constructor.name}.${method}`, this.getInjections(constructor, method), runtimeValues));
}
/**
* Injects dependencies asynchronously to the class method
*/
async callAsync(target, method, runtimeValues) {
const constructor = target.constructor;
return target[method](...(await this.resolveAsync(`${constructor.name}.${method}`, this.getInjections(constructor, method), runtimeValues)));
}
}
exports.Injector = Injector;
+14
View File
@@ -0,0 +1,14 @@
import type { Fakes } from './Fakes';
/**
* Proxies the objects to fallback to fake, when it exists.
*/
export declare class IocProxyObject {
namespace: string;
value: any;
options: Fakes;
constructor(namespace: string, value: any, options: Fakes);
}
/**
* Proxies the class constructor to fallback to fake, when it exists.
*/
export declare function IocProxyClass(namespace: string, value: any, options: Fakes): any;
+105
View File
@@ -0,0 +1,105 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.IocProxyClass = exports.IocProxyObject = void 0;
function getBindingValue(handler) {
return handler.options.has(handler.namespace)
? handler.options.resolve(handler.namespace, handler.value)
: handler.value;
}
/**
* Proxy handler to handle objects
*/
const objectHandler = (options) => {
return {
get(_, key, receiver) {
const descriptor = Object.getOwnPropertyDescriptor(options.value, key);
/**
* Handling the proxy invariants use case. Learn more
*
* https://262.ecma-international.org/8.0/#sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver
*
* Check the following "get" trap
* https://github.com/kpruden/on-change/blob/5b80da1f5f7ac80c37d7bd19122188acb7ad0b19/index.js#L44-L66
*/
if (descriptor && !descriptor.configurable) {
if (descriptor.set && !descriptor.get) {
return undefined;
}
if (descriptor.writable === false) {
return Reflect.get(options.value, key, receiver);
}
}
return Reflect.get(getBindingValue(options), key, receiver);
},
apply(_, thisArgument, args) {
return Reflect.apply(getBindingValue(options), thisArgument, args);
},
defineProperty(_, propertyKey, attributes) {
return Reflect.defineProperty(getBindingValue(options), propertyKey, attributes);
},
deleteProperty(_, propertyKey) {
return Reflect.deleteProperty(getBindingValue(options), propertyKey);
},
getOwnPropertyDescriptor(_, propertyKey) {
return Reflect.getOwnPropertyDescriptor(getBindingValue(options), propertyKey);
},
getPrototypeOf(_) {
return Reflect.getPrototypeOf(getBindingValue(options));
},
has(_, propertyKey) {
return Reflect.has(getBindingValue(options), propertyKey);
},
isExtensible(_) {
return Reflect.isExtensible(getBindingValue(options));
},
ownKeys(_) {
return Reflect.ownKeys(getBindingValue(options));
},
preventExtensions() {
throw new Error('Cannot prevent extensions during a fake');
},
set(_, propertyKey, value, receiver) {
return Reflect.set(getBindingValue(options), propertyKey, value, receiver);
},
setPrototypeOf(_, proto) {
return Reflect.setPrototypeOf(getBindingValue(options), proto);
},
};
};
/**
* Proxy handler to handle classes and functions
*/
const classHandler = (options) => {
return Object.assign({}, objectHandler(options), {
construct(_, args, newTarget) {
return Reflect.construct(getBindingValue(options), args, newTarget);
},
});
};
/**
* Proxies the objects to fallback to fake, when it exists.
*/
class IocProxyObject {
constructor(namespace, value, options) {
this.namespace = namespace;
this.value = value;
this.options = options;
return new Proxy(value, objectHandler({ namespace, value, options }));
}
}
exports.IocProxyObject = IocProxyObject;
/**
* Proxies the class constructor to fallback to fake, when it exists.
*/
function IocProxyClass(namespace, value, options) {
return new Proxy(value, classHandler({ namespace, value, options }));
}
exports.IocProxyClass = IocProxyClass;
+192
View File
@@ -0,0 +1,192 @@
import { IocContract, BindCallback, FakeCallback, LookupNode } from '../Contracts';
import { IocResolver } from '../Resolver';
export declare class Ioc implements IocContract {
private fakes;
private bindings;
private injector;
private aliases;
/**
* The current state of using proxies
*/
private usingProxies;
/**
* A custom method to trap `ioc.use` and `ioc.make` statements
*/
private trapCallback;
/**
* Define the module type for resolving auto import aliases. Defaults
* to `cjs`
*/
module: 'cjs' | 'esm';
/**
* Registered aliases. The key is the alias and value is the
* absolute directory path
*/
get importAliases(): IocContract['importAliases'];
/**
* Detect if the module export value is an esm module
*/
private isEsm;
/**
* Wraps object and class to a proxy to enable the fakes
* API
*/
private wrapAsProxy;
/**
* Wrap value inside proxy by also inspecting for esm
* default exports
*/
private wrapEsmModuleAsProxy;
/**
* Makes an instance of a class by injecting dependencies
*/
private makeRaw;
/**
* Makes an instance of a class asynchronously by injecting dependencies
*/
private makeRawAsync;
/**
* Enable/disable proxies. Proxies are mainly required for fakes to
* work
*/
useProxies(enable?: boolean): this;
/**
* Register a binding with a callback. The callback return value will be
* used when binding is resolved
*/
bind(binding: string, callback: BindCallback<any, this>): this;
/**
* Same as the [[bind]] method, but registers a singleton only. Singleton's callback
* is invoked only for the first time and then the cached value is used
*/
singleton(binding: string, callback: BindCallback<any, this>): this;
/**
* Define an import alias
*/
alias(absolutePath: string, alias: string): this;
/**
* Register a fake for a namespace. Fakes works both for "bindings" and "import aliases".
* Fakes only work when proxies are enabled using "useProxies".
*/
fake(namespace: string, callback: FakeCallback<any, this>): this;
/**
* Clear selected or all the fakes. Calling the method with no arguments
* will clear all the fakes
*/
restore(namespace?: string): this;
/**
* Find if a fake has been registered for a given namespace
*/
hasFake(namespace: string): boolean;
/**
* Find if a binding exists for a given namespace
*/
hasBinding(namespace: string): boolean;
/**
* Find if a namespace is part of the auto import aliases. Returns false, when namespace
* is an alias path but has an explicit binding too
*/
isAliasPath(namespace: string): boolean;
/**
* Lookup a namespace. The output contains the complete namespace,
* along with its type. The type is an "alias" or a "binding".
*
* Null is returned when unable to lookup the namespace inside the container
*
* Note: This method just checks if a namespace is registered or binding
* or can be it resolved from auto import aliases or not. However,
* it doesn't check for the module existence on the disk.
*
* Optionally you can define a prefix namespace
* to be used to build the complete namespace. For example:
*
* - namespace: UsersController
* - prefixNamespace: App/Controllers/Http
* - Output: App/Controllers/Http/UsersController
*
* Prefix namespace is ignored for absolute namespaces. For example:
*
* - namespace: /App/UsersController
* - prefixNamespace: App/Controllers/Http
* - Output: App/UsersController
*/
lookup(namespace: string | LookupNode<string>, prefixNamespace?: string): null | any;
/**
* Same as [[lookup]]. But raises exception instead of returning null
*/
lookupOrFail(namespace: string | LookupNode<string>, prefixNamespace?: string): LookupNode<string>;
/**
* Resolve a binding by invoking the binding factory function. An exception
* is raised, if the binding namespace is unregistered.
*/
resolveBinding(binding: string): any;
/**
* Import namespace from the auto import aliases. This method assumes you are
* using native ES modules
*/
import(namespace: string): Promise<any>;
/**
* Same as the "import" method, but uses CJS for requiring the module from its
* path
*/
require(namespace: string): any;
/**
* The use method looks up a namespace inside both the bindings and the
* auto import aliases
*/
use(namespace: string | LookupNode<string>): any;
/**
* Same as the [[use]] method, but instead uses ES modules for resolving
* the auto import aliases
*/
useAsync(namespace: string | LookupNode<string>): Promise<any>;
/**
* Makes an instance of the class by first resolving it.
*/
make(namespace: LookupNode<string> | any, args?: any[]): any;
/**
* Same as the [[make]] method, but instead uses ES modules for resolving
* the auto import aliases
*/
makeAsync(namespace: LookupNode<string> | any, args?: any[]): Promise<any>;
/**
* Define a callback to be called when all of the container
* bindings are available.
*
* Note: This method is exclusive for bindings and doesn't resolve
* auto import aliases
*/
withBindings(namespaces: readonly any[], cb: (...args: any) => void): void;
/**
* @deprecated: Use "withBindings" instead
*/
with(namespaces: readonly any[], cb: (...args: any) => void): void;
/**
* Call method on an object and automatically resolve its depdencies
*/
call(target: any, method: any, args?: any[]): any;
/**
* Same as [[call]], but uses ES modules for resolving the auto
* import aliases
*/
callAsync(target: any, method: any, args?: any[]): Promise<any>;
/**
* Trap container lookup calls. It includes
*
* - Ioc.use
* - Ioc.useAsync
* - Ioc.make
* - Ioc.makeAsync
* - Ioc.require
* - Ioc.import
* - Ioc.resolveBinding
*/
trap(callback: (namespace: string) => any): this;
/**
* Returns the resolver instance to resolve Ioc container bindings with
* little ease. Since, the IocResolver uses an in-memory cache to
* improve the lookup speed, we suggest keeping a reference to
* the output of this method to leverage caching
*/
getResolver(fallbackMethod?: string, rcNamespaceKey?: string, fallbackNamespace?: string): IocResolver;
}
+468
View File
@@ -0,0 +1,468 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.Ioc = void 0;
const utils_1 = require("@poppinss/utils");
const helpers_1 = require("@poppinss/utils/build/helpers");
const Fakes_1 = require("./Fakes");
const Bindings_1 = require("./Bindings");
const Injector_1 = require("./Injector");
const Resolver_1 = require("../Resolver");
const ImportAliases_1 = require("./ImportAliases");
const helpers_2 = require("../helpers");
const IocProxy_1 = require("./IocProxy");
const IocLookupException_1 = require("../Exceptions/IocLookupException");
class Ioc {
constructor() {
this.fakes = new Fakes_1.Fakes(this);
this.bindings = new Bindings_1.Bindings(this);
this.injector = new Injector_1.Injector(this);
this.aliases = new ImportAliases_1.ImportAliases(this);
/**
* The current state of using proxies
*/
this.usingProxies = false;
/**
* Define the module type for resolving auto import aliases. Defaults
* to `cjs`
*/
this.module = 'cjs';
}
/**
* Registered aliases. The key is the alias and value is the
* absolute directory path
*/
get importAliases() {
return this.aliases.list;
}
/**
* Detect if the module export value is an esm module
*/
isEsm(value) {
return this.module === 'esm' ? true : (0, helpers_2.isEsm)(value);
}
/**
* Wraps object and class to a proxy to enable the fakes
* API
*/
wrapAsProxy(namespace, value) {
/**
* Wrap objects inside proxy
*/
if (helpers_1.types.isObject(value)) {
return new IocProxy_1.IocProxyObject(namespace, value, this.fakes);
}
/**
* Wrap class inside proxy
*/
if (helpers_1.types.isClass(value)) {
return (0, IocProxy_1.IocProxyClass)(namespace, value, this.fakes);
}
return value;
}
/**
* Wrap value inside proxy by also inspecting for esm
* default exports
*/
wrapEsmModuleAsProxy(namespace, value) {
/**
* Wrap the default export of esm modules inside in a proxy and
* not the entire module
*/
if (this.isEsm(value)) {
if (value.default) {
/**
* We should never mutate the actual ESM module object and always clone it first
* for abvious reasons that objects are shared by reference
*/
const clonedModule = Object.getOwnPropertyNames(value).reduce((result, key) => {
result[key] = value[key];
return result;
}, {});
clonedModule.default = this.wrapAsProxy(namespace, clonedModule.default);
return clonedModule;
}
/**
* We don't proxy named exports as we don't have a good story on what to proxy
*
* - Should we proxy the whole module?
* - Or should be expose api to allow proxying a selected set of modules
*/
return value;
}
return this.wrapAsProxy(namespace, value);
}
/**
* Makes an instance of a class by injecting dependencies
*/
makeRaw(value, args) {
return this.injector.make(value, args || []);
}
/**
* Makes an instance of a class asynchronously by injecting dependencies
*/
async makeRawAsync(value, args) {
return this.injector.makeAsync(value, args || []);
}
/**
* Enable/disable proxies. Proxies are mainly required for fakes to
* work
*/
useProxies(enable = true) {
this.usingProxies = !!enable;
return this;
}
/**
* Register a binding with a callback. The callback return value will be
* used when binding is resolved
*/
bind(binding, callback) {
(0, helpers_2.ensureIsFunction)(callback, '"ioc.bind" expect 2nd argument to be a function');
this.bindings.register(binding, callback, false);
return this;
}
/**
* Same as the [[bind]] method, but registers a singleton only. Singleton's callback
* is invoked only for the first time and then the cached value is used
*/
singleton(binding, callback) {
(0, helpers_2.ensureIsFunction)(callback, '"ioc.singleton" expect 2nd argument to be a function');
this.bindings.register(binding, callback, true);
return this;
}
/**
* Define an import alias
*/
alias(absolutePath, alias) {
this.aliases.register(absolutePath, alias);
return this;
}
/**
* Register a fake for a namespace. Fakes works both for "bindings" and "import aliases".
* Fakes only work when proxies are enabled using "useProxies".
*/
fake(namespace, callback) {
(0, helpers_2.ensureIsFunction)(callback, '"ioc.fake" expect 2nd argument to be a function');
this.fakes.register(namespace, callback);
return this;
}
/**
* Clear selected or all the fakes. Calling the method with no arguments
* will clear all the fakes
*/
restore(namespace) {
namespace ? this.fakes.delete(namespace) : this.fakes.clear();
return this;
}
/**
* Find if a fake has been registered for a given namespace
*/
hasFake(namespace) {
return this.fakes.has(namespace);
}
/**
* Find if a binding exists for a given namespace
*/
hasBinding(namespace) {
return this.bindings.has(namespace);
}
/**
* Find if a namespace is part of the auto import aliases. Returns false, when namespace
* is an alias path but has an explicit binding too
*/
isAliasPath(namespace) {
if (this.bindings.has(namespace)) {
return false;
}
return this.aliases.has(namespace);
}
/**
* Lookup a namespace. The output contains the complete namespace,
* along with its type. The type is an "alias" or a "binding".
*
* Null is returned when unable to lookup the namespace inside the container
*
* Note: This method just checks if a namespace is registered or binding
* or can be it resolved from auto import aliases or not. However,
* it doesn't check for the module existence on the disk.
*
* Optionally you can define a prefix namespace
* to be used to build the complete namespace. For example:
*
* - namespace: UsersController
* - prefixNamespace: App/Controllers/Http
* - Output: App/Controllers/Http/UsersController
*
* Prefix namespace is ignored for absolute namespaces. For example:
*
* - namespace: /App/UsersController
* - prefixNamespace: App/Controllers/Http
* - Output: App/UsersController
*/
lookup(namespace, prefixNamespace) {
if (typeof namespace !== 'string' && namespace['namespace'] && namespace['type']) {
return namespace;
}
/**
* Ensure namespace is defined as a string only
*/
if (typeof namespace !== 'string') {
throw IocLookupException_1.IocLookupException.invalidNamespace();
}
/**
* Build complete namespace
*/
if (namespace.startsWith('/')) {
namespace = namespace.substr(1);
}
else if (prefixNamespace) {
namespace = `${prefixNamespace.replace(/\/$/, '')}/${namespace}`;
}
/**
* Namespace is a binding
*/
if (this.hasBinding(namespace)) {
return {
type: 'binding',
namespace: namespace,
};
}
/**
* Namespace is an alias
*/
if (this.isAliasPath(namespace)) {
return {
type: 'alias',
namespace: namespace,
};
}
return null;
}
/**
* Same as [[lookup]]. But raises exception instead of returning null
*/
lookupOrFail(namespace, prefixNamespace) {
const lookupNode = this.lookup(namespace, prefixNamespace);
if (!lookupNode) {
throw IocLookupException_1.IocLookupException.lookupFailed(namespace);
}
return lookupNode;
}
/**
* Resolve a binding by invoking the binding factory function. An exception
* is raised, if the binding namespace is unregistered.
*/
resolveBinding(binding) {
if (this.trapCallback) {
return this.trapCallback(binding);
}
const value = this.bindings.resolve(binding);
if (this.usingProxies) {
return this.wrapAsProxy(binding, value);
}
return value;
}
/**
* Import namespace from the auto import aliases. This method assumes you are
* using native ES modules
*/
async import(namespace) {
if (this.trapCallback) {
return this.trapCallback(namespace);
}
const value = await this.aliases.resolveAsync(namespace);
if (this.usingProxies) {
return this.wrapEsmModuleAsProxy(namespace, value);
}
return value;
}
/**
* Same as the "import" method, but uses CJS for requiring the module from its
* path
*/
require(namespace) {
if (this.trapCallback) {
return this.trapCallback(namespace);
}
const value = this.aliases.resolve(namespace);
if (this.usingProxies) {
return this.wrapEsmModuleAsProxy(namespace, value);
}
return value;
}
/**
* The use method looks up a namespace inside both the bindings and the
* auto import aliases
*/
use(namespace) {
if (this.trapCallback) {
return this.trapCallback(typeof namespace === 'string' ? namespace : namespace['namespace']);
}
const lookupNode = this.lookupOrFail(namespace);
if (lookupNode.type === 'alias') {
return this.require(lookupNode.namespace);
}
return this.resolveBinding(lookupNode.namespace);
}
/**
* Same as the [[use]] method, but instead uses ES modules for resolving
* the auto import aliases
*/
async useAsync(namespace) {
if (this.trapCallback) {
return this.trapCallback(typeof namespace === 'string' ? namespace : namespace['namespace']);
}
const lookupNode = this.lookupOrFail(namespace);
if (lookupNode.type === 'alias') {
return this.import(lookupNode.namespace);
}
return this.resolveBinding(lookupNode.namespace);
}
/**
* Makes an instance of the class by first resolving it.
*/
make(namespace, args) {
const isContainerNamespace = typeof namespace === 'string' || (namespace['namespace'] && namespace['type']);
/**
* Value is not a container namespace or a lookup
* node
*/
if (!isContainerNamespace) {
return this.makeRaw(namespace, args);
}
/**
* Invoke trap callback (if registered)
*/
if (this.trapCallback) {
return this.trapCallback(typeof namespace === 'string' ? namespace : namespace['namespace']);
}
const lookupNode = this.lookupOrFail(namespace);
/**
* We do not touch bindings at all. The factory function
* return value is used as it is
*/
if (lookupNode.type === 'binding') {
return this.resolveBinding(lookupNode.namespace);
}
const value = this.require(lookupNode.namespace);
/**
* We attempt to make an instance of only the export
* default of a ES module
*/
if (this.isEsm(value) && value.default) {
return this.makeRaw(value.default, args || []);
}
return this.makeRaw(value, args);
}
/**
* Same as the [[make]] method, but instead uses ES modules for resolving
* the auto import aliases
*/
async makeAsync(namespace, args) {
const isContainerNamespace = typeof namespace === 'string' || (namespace['namespace'] && namespace['type']);
/**
* Value is not a container namespace or a lookup
* node
*/
if (!isContainerNamespace) {
return this.makeRawAsync(namespace, args);
}
/**
* Invoke trap callback (if registered)
*/
if (this.trapCallback) {
return this.trapCallback(typeof namespace === 'string' ? namespace : namespace['namespace']);
}
const lookupNode = this.lookupOrFail(namespace);
/**
* We do not touch bindings at all. The factory function
* return value is used as it is
*/
if (lookupNode.type === 'binding') {
return this.resolveBinding(lookupNode.namespace);
}
const value = await this.import(lookupNode.namespace);
/**
* We attempt to make an instance of only the export
* default of a ES module
*/
if (this.isEsm(value) && value.default) {
return this.makeRawAsync(value.default, args || []);
}
return this.makeRawAsync(value, args);
}
/**
* Define a callback to be called when all of the container
* bindings are available.
*
* Note: This method is exclusive for bindings and doesn't resolve
* auto import aliases
*/
withBindings(namespaces, cb) {
if (namespaces.every((namespace) => this.hasBinding(namespace))) {
/**
* The callback accepts a tuple, whereas map returns an array. So we
* need to cast the value to any by hand
*/
cb(...namespaces.map((namespace) => this.resolveBinding(namespace)));
}
}
/**
* @deprecated: Use "withBindings" instead
*/
with(namespaces, cb) {
process.emitWarning('DeprecationWarning', 'container.with() is deprecated. Use container.withBindings() instead');
return this.withBindings(namespaces, cb);
}
/**
* Call method on an object and automatically resolve its depdencies
*/
call(target, method, args) {
if (typeof target[method] !== 'function') {
throw new utils_1.Exception(`Missing method "${method}" on "${target.constructor.name}"`);
}
return this.injector.call(target, method, args || []);
}
/**
* Same as [[call]], but uses ES modules for resolving the auto
* import aliases
*/
async callAsync(target, method, args) {
if (typeof target[method] !== 'function') {
throw new utils_1.Exception(`Missing method "${method}" on "${target.constructor.name}"`);
}
return this.injector.callAsync(target, method, args || []);
}
/**
* Trap container lookup calls. It includes
*
* - Ioc.use
* - Ioc.useAsync
* - Ioc.make
* - Ioc.makeAsync
* - Ioc.require
* - Ioc.import
* - Ioc.resolveBinding
*/
trap(callback) {
this.trapCallback = callback;
return this;
}
/**
* Returns the resolver instance to resolve Ioc container bindings with
* little ease. Since, the IocResolver uses an in-memory cache to
* improve the lookup speed, we suggest keeping a reference to
* the output of this method to leverage caching
*/
getResolver(fallbackMethod, rcNamespaceKey, fallbackNamespace) {
return new Resolver_1.IocResolver(this, fallbackMethod, rcNamespaceKey, fallbackNamespace);
}
}
exports.Ioc = Ioc;
+62
View File
@@ -0,0 +1,62 @@
import { Constructor } from '../Contracts';
/**
* Registrar is used to register and boot the providers
*/
export declare class Registrar {
private providerConstructorParams;
private basePath?;
/**
* The first level of provider paths provided to the registrar
*/
private providersPaths;
/**
* An array of loaded providers. Their can be more providers than the
* `_providersPaths` array, since each provider can provide it's
* own sub providers
*/
private providers;
/**
* Method to instantiate provider instances. One can also defined
* a custom instantiater function
*/
private providersInstantiater;
/**
* Whether or not the providers can be collected
*/
private collected;
constructor(providerConstructorParams: any[], basePath?: string | undefined);
/**
* Load the provider by requiring the file from the disk
* and instantiate it. If ioc container is using ES6
* imports, then default exports are handled
* automatically.
*/
private loadProvider;
/**
* Loop's over an array of provider paths and pushes them to the
* `providers` collection. This collection is later used to
* register and boot providers
*/
private collect;
/**
* Register an array of provider paths
*/
useProviders(providersPaths: string[], callback?: <T extends Constructor<any>>(provider: T) => InstanceType<T>): this;
/**
* Register all the providers by instantiating them and
* calling the `register` method.
*
* The provider instance will be returned, which can be used
* to boot them as well.
*/
register(): Promise<any[]>;
/**
* Boot all the providers by calling the `boot` method.
* Boot methods are called in series.
*/
boot(): Promise<void>;
/**
* Register an boot providers together.
*/
registerAndBoot(): Promise<any[]>;
}
+129
View File
@@ -0,0 +1,129 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.Registrar = void 0;
const path_1 = require("path");
const utils_1 = require("@poppinss/utils");
const helpers_1 = require("@poppinss/utils/build/helpers");
/**
* Registrar is used to register and boot the providers
*/
class Registrar {
constructor(providerConstructorParams, basePath) {
this.providerConstructorParams = providerConstructorParams;
this.basePath = basePath;
/**
* The first level of provider paths provided to the registrar
*/
this.providersPaths = [];
/**
* An array of loaded providers. Their can be more providers than the
* `_providersPaths` array, since each provider can provide it's
* own sub providers
*/
this.providers = [];
/**
* Method to instantiate provider instances. One can also defined
* a custom instantiater function
*/
this.providersInstantiater = (provider) => new provider(...this.providerConstructorParams);
/**
* Whether or not the providers can be collected
*/
this.collected = false;
}
/**
* Load the provider by requiring the file from the disk
* and instantiate it. If ioc container is using ES6
* imports, then default exports are handled
* automatically.
*/
async loadProvider(providerPath, basePath) {
providerPath = this.basePath
? (0, helpers_1.resolveFrom)(basePath || this.basePath, providerPath)
: providerPath;
const provider = (0, utils_1.esmRequire)(providerPath);
if (typeof provider !== 'function') {
throw new utils_1.Exception(`"${providerPath}" provider must use export default statement`);
}
return {
provider: this.providersInstantiater(provider),
resolvedPath: (0, path_1.dirname)(providerPath),
};
}
/**
* Loop's over an array of provider paths and pushes them to the
* `providers` collection. This collection is later used to
* register and boot providers
*/
async collect(providerPaths, basePath) {
for (let providerPath of providerPaths) {
const { provider, resolvedPath } = await this.loadProvider(providerPath, basePath);
this.providers.push(provider);
if (provider.provides) {
await this.collect(provider.provides, resolvedPath);
}
}
}
/**
* Register an array of provider paths
*/
useProviders(providersPaths, callback) {
this.providersPaths = providersPaths;
if (typeof callback === 'function') {
this.providersInstantiater = callback;
}
return this;
}
/**
* Register all the providers by instantiating them and
* calling the `register` method.
*
* The provider instance will be returned, which can be used
* to boot them as well.
*/
async register() {
if (this.collected) {
return this.providers;
}
this.collected = true;
await this.collect(this.providersPaths);
/**
* Register collected providers
*/
this.providers.forEach((provider) => {
if (typeof provider.register === 'function') {
provider.register();
}
});
return this.providers;
}
/**
* Boot all the providers by calling the `boot` method.
* Boot methods are called in series.
*/
async boot() {
const providers = await this.register();
for (let provider of providers) {
if (typeof provider.boot === 'function') {
await provider.boot();
}
}
}
/**
* Register an boot providers together.
*/
async registerAndBoot() {
const providers = await this.register();
await this.boot();
return providers;
}
}
exports.Registrar = Registrar;
+32
View File
@@ -0,0 +1,32 @@
import { IocContract, IocResolverLookupNode, IocResolverContract } from '../Contracts';
/**
* Exposes the API to resolve and call bindings from the IoC container. The resolver
* internally caches the IoC container lookup nodes to boost performance.
*/
export declare class IocResolver implements IocResolverContract<any> {
private container;
private fallbackMethod?;
private rcNamespaceKey?;
private fallbackNamespace?;
private lookupCache;
/**
* The namespace that will be used as a prefix when resolving
* bindings
*/
private prefixNamespace;
constructor(container: IocContract, fallbackMethod?: string | undefined, rcNamespaceKey?: string | undefined, fallbackNamespace?: string | undefined);
/**
* Returns the prefix namespace by giving preference to the
* `.adonisrc.json` file
*/
private getPrefixNamespace;
/**
* Resolves the namespace and returns it's lookup node
*/
resolve(namespace: string, prefixNamespace?: string | undefined): IocResolverLookupNode<string>;
/**
* Calls the namespace.method expression with any arguments that needs to
* be passed. Also supports type-hinting dependencies.
*/
call(namespace: string | IocResolverLookupNode<string>, prefixNamespace?: string, args?: any[] | ((instance: any) => any[])): Promise<any>;
}
+95
View File
@@ -0,0 +1,95 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.IocResolver = void 0;
/**
* Exposes the API to resolve and call bindings from the IoC container. The resolver
* internally caches the IoC container lookup nodes to boost performance.
*/
class IocResolver {
constructor(container, fallbackMethod, rcNamespaceKey, fallbackNamespace) {
this.container = container;
this.fallbackMethod = fallbackMethod;
this.rcNamespaceKey = rcNamespaceKey;
this.fallbackNamespace = fallbackNamespace;
this.lookupCache = {};
/**
* The namespace that will be used as a prefix when resolving
* bindings
*/
this.prefixNamespace = this.getPrefixNamespace();
}
/**
* Returns the prefix namespace by giving preference to the
* `.adonisrc.json` file
*/
getPrefixNamespace() {
/**
* Use fallback namespace, when lookup inside rcFile is not required
*/
if (!this.rcNamespaceKey) {
return this.fallbackNamespace;
}
/**
* If container doesn't have `Application` binding, then there is no
* way for us to read rcFile namespaces and hence we use the fallback
* namespace
*/
if (!this.container.hasBinding('Adonis/Core/Application')) {
return this.fallbackNamespace;
}
/**
* Attempt to resolve the rcNamespace key from the rcFile
* For example: The rc file has following namespaces
* {
* "controllers": "App/Controllers/Http"
* }
* We will use the value next to the `controllers` key
*/
const application = this.container.use('Adonis/Core/Application');
return application.namespacesMap.get(this.rcNamespaceKey) || this.fallbackNamespace;
}
/**
* Resolves the namespace and returns it's lookup node
*/
resolve(namespace, prefixNamespace = this.prefixNamespace) {
const cacheKey = prefixNamespace ? `${prefixNamespace}/${namespace}` : namespace;
/**
* Return from cache, when the node exists
*/
const cacheNode = this.lookupCache[cacheKey];
if (cacheNode) {
return cacheNode;
}
let method = this.fallbackMethod || 'handle';
/**
* Split the namespace to lookup the method on it. If method isn't
* defined, we will use the conventional `handle` method.
*/
const tokens = namespace.split('.');
if (tokens.length > 1) {
method = tokens.pop();
}
const lookupNode = this.container.lookupOrFail(tokens.join('.'), prefixNamespace);
this.lookupCache[cacheKey] = { ...lookupNode, method };
return this.lookupCache[cacheKey];
}
/**
* Calls the namespace.method expression with any arguments that needs to
* be passed. Also supports type-hinting dependencies.
*/
async call(namespace, prefixNamespace, args) {
const lookupNode = typeof namespace === 'string' ? this.resolve(namespace, prefixNamespace) : namespace;
const instance = await this.container.makeAsync(lookupNode.namespace);
args = typeof args === 'function' ? args(instance) : args;
return this.container.callAsync(instance, lookupNode.method, args);
}
}
exports.IocResolver = IocResolver;
+7
View File
@@ -0,0 +1,7 @@
/**
* Injects bindings to the class constructor
*/
export declare function inject(value?: any): {
(target: any, propertyKey: string): void;
(target: any): void;
};
+64
View File
@@ -0,0 +1,64 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.inject = void 0;
/**
* Injects bindings to the class constructor
*/
function inject(value) {
// eslint-disable-next-line no-redeclare
function decorator(target, propertyKey) {
/**
* Consturctor injections
*/
if (!propertyKey) {
if (!target.hasOwnProperty('inject')) {
Object.defineProperty(target, 'inject', {
value: {},
});
}
target.inject.instance = target.inject.instance || [];
const constructorParams = Reflect.getMetadata('design:paramtypes', target);
if (constructorParams) {
constructorParams.forEach((param, index) => {
if (value && value[index]) {
target.inject.instance.push(value[index]);
}
else {
target.inject.instance.push(param);
}
});
}
return;
}
/**
* Parameter injections
*/
if (!target.constructor.hasOwnProperty('inject')) {
Object.defineProperty(target.constructor, 'inject', {
value: {},
});
}
target.constructor.inject[propertyKey] = target.constructor.inject[propertyKey] || [];
const methodParams = Reflect.getMetadata('design:paramtypes', target, propertyKey);
if (methodParams) {
methodParams.forEach((param, index) => {
if (value && value[index]) {
target.constructor.inject[propertyKey].push(value[index]);
}
else {
target.constructor.inject[propertyKey].push(param);
}
});
}
}
return decorator;
}
exports.inject = inject;
+14
View File
@@ -0,0 +1,14 @@
/**
* Returns a boolean telling if value is an esm module
* with `export default`.
*/
export declare function isEsm(value: any): boolean;
/**
* Returns a boolean telling if value is a primitive or object constructor.
*/
export declare function isPrimtiveConstructor(value: any): boolean;
/**
* Raises error with a message when callback is not
* a function.
*/
export declare function ensureIsFunction(callback: Function, message: string): void;
+37
View File
@@ -0,0 +1,37 @@
"use strict";
/*
* @adonisjs/fold
*
* (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.ensureIsFunction = exports.isPrimtiveConstructor = exports.isEsm = void 0;
const utils_1 = require("@poppinss/utils");
/**
* Returns a boolean telling if value is an esm module
* with `export default`.
*/
function isEsm(value) {
return value && value.__esModule;
}
exports.isEsm = isEsm;
/**
* Returns a boolean telling if value is a primitive or object constructor.
*/
function isPrimtiveConstructor(value) {
return [String, Function, Object, Date, Number, Boolean].indexOf(value) > -1;
}
exports.isPrimtiveConstructor = isPrimtiveConstructor;
/**
* Raises error with a message when callback is not
* a function.
*/
function ensureIsFunction(callback, message) {
if (typeof callback !== 'function') {
throw new utils_1.Exception(message, 500, 'E_RUNTIME_EXCEPTION');
}
}
exports.ensureIsFunction = ensureIsFunction;