@foal/core
Advanced tools
Comparing version 1.7.1 to 1.8.0
@@ -1,2 +0,2 @@ | ||
import { Request } from 'express'; | ||
import { Request } from 'express-serve-static-core'; | ||
import { Session } from '../../sessions'; | ||
@@ -3,0 +3,0 @@ /** |
@@ -7,2 +7,2 @@ export * from './class.interface'; | ||
export * from './config'; | ||
export { createService, dependency, ServiceManager } from './service-manager'; | ||
export { createService, dependency, Dependency, ServiceManager } from './service-manager'; |
@@ -15,2 +15,3 @@ "use strict"; | ||
exports.dependency = service_manager_1.dependency; | ||
exports.Dependency = service_manager_1.Dependency; | ||
exports.ServiceManager = service_manager_1.ServiceManager; |
import 'reflect-metadata'; | ||
import { Class } from './class.interface'; | ||
export interface Dependency { | ||
export interface IDependency { | ||
propertyKey: string; | ||
serviceClass: Class; | ||
serviceClass: string | Class; | ||
} | ||
@@ -10,2 +10,8 @@ /** | ||
* | ||
* @param id {string} - The service ID. | ||
*/ | ||
export declare function Dependency(id: string): (target: any, propertyKey: string) => void; | ||
/** | ||
* Decorator injecting a service inside a controller or another service. | ||
* | ||
* @export | ||
@@ -25,3 +31,3 @@ */ | ||
export declare function createService<Service>(serviceClass: Class<Service>, dependencies?: object | ServiceManager): Service; | ||
export declare function createControllerOrService<ControllerOrService>(controllerOrServiceClass: Class<ControllerOrService>, dependencies?: object | ServiceManager): ControllerOrService; | ||
export declare function createControllerOrService<T>(serviceClass: Class<T>, dependencies?: object | ServiceManager): T; | ||
/** | ||
@@ -34,22 +40,38 @@ * Identity Mapper that instantiates and returns service singletons. | ||
export declare class ServiceManager { | ||
readonly map: Map<Class<any>, any>; | ||
private readonly map; | ||
/** | ||
* Add manually a service to the identity mapper. This function is | ||
* useful during tests to inject mocks. | ||
* Boot all services : call the method "boot" of each service if it exists. | ||
* | ||
* @template Service | ||
* @param {Class<Service>} serviceClass - The service class representing the key. | ||
* @param {*} service - The service object (or mock) representing the value. | ||
* If a service identifier is provided, only this service will be booted. | ||
* | ||
* Services are only booted once. | ||
* | ||
* @param {(string|Class)} [identifier] - The service ID or the service class. | ||
* @returns {Promise<void>} | ||
* @memberof ServiceManager | ||
*/ | ||
set<Service>(serviceClass: Class<Service>, service: any): void; | ||
boot(identifier?: string | Class): Promise<void>; | ||
/** | ||
* Add manually a service to the identity mapper. | ||
* | ||
* @param {string|Class} identifier - The service ID or the service class. | ||
* @param {*} service - The service object (or mock). | ||
* @param {{ boot: boolean }} [options={ boot: false }] If `boot` is true, the service method "boot" | ||
* will be executed when calling `ServiceManager.boot` is called. | ||
* @returns {this} The service manager. | ||
* @memberof ServiceManager | ||
*/ | ||
set(identifier: string | Class, service: any, options?: { | ||
boot: boolean; | ||
}): this; | ||
/** | ||
* Get (and create if necessary) the service singleton. | ||
* | ||
* @template Service | ||
* @param {Class<Service>} serviceClass - The service class. | ||
* @returns {Service} - The service instance. | ||
* @param {string|Class} identifier - The service ID or the service class. | ||
* @returns {*} - The service instance. | ||
* @memberof ServiceManager | ||
*/ | ||
get<Service>(serviceClass: Class<Service>): Service; | ||
get<T>(identifier: Class<T>): T; | ||
get(identifier: string): any; | ||
private bootService; | ||
} |
@@ -7,2 +7,15 @@ "use strict"; | ||
* | ||
* @param id {string} - The service ID. | ||
*/ | ||
function Dependency(id) { | ||
return (target, propertyKey) => { | ||
const dependencies = [...(Reflect.getMetadata('dependencies', target) || [])]; | ||
dependencies.push({ propertyKey, serviceClass: id }); | ||
Reflect.defineMetadata('dependencies', dependencies, target); | ||
}; | ||
} | ||
exports.Dependency = Dependency; | ||
/** | ||
* Decorator injecting a service inside a controller or another service. | ||
* | ||
* @export | ||
@@ -31,6 +44,5 @@ */ | ||
exports.createService = createService; | ||
function createControllerOrService(controllerOrServiceClass, dependencies) { | ||
const controllerOrServiceDependencies = Reflect.getMetadata('dependencies', controllerOrServiceClass.prototype) || []; | ||
function createControllerOrService(serviceClass, dependencies) { | ||
const metadata = Reflect.getMetadata('dependencies', serviceClass.prototype) || []; | ||
let serviceManager = new ServiceManager(); | ||
const service = new controllerOrServiceClass(); | ||
if (dependencies instanceof ServiceManager) { | ||
@@ -40,3 +52,3 @@ serviceManager = dependencies; | ||
else if (typeof dependencies === 'object') { | ||
controllerOrServiceDependencies.forEach(dep => { | ||
metadata.forEach(dep => { | ||
const serviceMock = dependencies[dep.propertyKey]; | ||
@@ -48,6 +60,3 @@ if (serviceMock) { | ||
} | ||
controllerOrServiceDependencies.forEach(dep => { | ||
service[dep.propertyKey] = serviceManager.get(dep.serviceClass); | ||
}); | ||
return service; | ||
return serviceManager.get(serviceClass); | ||
} | ||
@@ -66,25 +75,46 @@ exports.createControllerOrService = createControllerOrService; | ||
/** | ||
* Add manually a service to the identity mapper. This function is | ||
* useful during tests to inject mocks. | ||
* Boot all services : call the method "boot" of each service if it exists. | ||
* | ||
* @template Service | ||
* @param {Class<Service>} serviceClass - The service class representing the key. | ||
* @param {*} service - The service object (or mock) representing the value. | ||
* If a service identifier is provided, only this service will be booted. | ||
* | ||
* Services are only booted once. | ||
* | ||
* @param {(string|Class)} [identifier] - The service ID or the service class. | ||
* @returns {Promise<void>} | ||
* @memberof ServiceManager | ||
*/ | ||
set(serviceClass, service) { | ||
this.map.set(serviceClass, service); | ||
async boot(identifier) { | ||
if (typeof identifier !== 'undefined') { | ||
const value = this.map.get(identifier); | ||
if (!value) { | ||
throw new Error(`No service was found with the identifier "${identifier}".`); | ||
} | ||
return this.bootService(value); | ||
} | ||
const promises = []; | ||
for (const value of this.map.values()) { | ||
promises.push(this.bootService(value)); | ||
} | ||
await Promise.all(promises); | ||
} | ||
/** | ||
* Get (and create if necessary) the service singleton. | ||
* Add manually a service to the identity mapper. | ||
* | ||
* @template Service | ||
* @param {Class<Service>} serviceClass - The service class. | ||
* @returns {Service} - The service instance. | ||
* @param {string|Class} identifier - The service ID or the service class. | ||
* @param {*} service - The service object (or mock). | ||
* @param {{ boot: boolean }} [options={ boot: false }] If `boot` is true, the service method "boot" | ||
* will be executed when calling `ServiceManager.boot` is called. | ||
* @returns {this} The service manager. | ||
* @memberof ServiceManager | ||
*/ | ||
get(serviceClass) { | ||
// The ts-ignores fix TypeScript bugs. | ||
set(identifier, service, options = { boot: false }) { | ||
this.map.set(identifier, { | ||
boot: options.boot, | ||
service, | ||
}); | ||
return this; | ||
} | ||
get(identifier) { | ||
// @ts-ignore : Type 'ServiceManager' is not assignable to type 'Service'. | ||
if (serviceClass === ServiceManager || serviceClass.isServiceManager === true) { | ||
if (identifier === ServiceManager || identifier.isServiceManager === true) { | ||
// @ts-ignore : Type 'ServiceManager' is not assignable to type 'Service'. | ||
@@ -94,12 +124,31 @@ return this; | ||
// Get the service if it exists. | ||
if (this.map.get(serviceClass)) { | ||
return this.map.get(serviceClass); | ||
const value = this.map.get(identifier); | ||
if (value) { | ||
return value.service; | ||
} | ||
// Throw an error if the identifier is a string and no service was found in the map. | ||
if (typeof identifier === 'string') { | ||
throw new Error(`No service was found with the identifier "${identifier}".`); | ||
} | ||
// If the service has not been instantiated yet then do it. | ||
const service = createControllerOrService(serviceClass, this); | ||
// Save and return the service. | ||
this.map.set(serviceClass, service); | ||
const dependencies = Reflect.getMetadata('dependencies', identifier.prototype) || []; | ||
// identifier is a class here. | ||
const service = new identifier(); | ||
for (const dependency of dependencies) { | ||
service[dependency.propertyKey] = this.get(dependency.serviceClass); | ||
} | ||
// Save the service. | ||
this.map.set(identifier, { | ||
boot: true, | ||
service, | ||
}); | ||
return service; | ||
} | ||
async bootService(value) { | ||
if (value.boot && value.service.boot) { | ||
value.boot = false; | ||
await value.service.boot(); | ||
} | ||
} | ||
} | ||
exports.ServiceManager = ServiceManager; |
@@ -1,4 +0,4 @@ | ||
import * as express from 'express'; | ||
import { ErrorRequestHandler, Express, RequestHandler } from 'express-serve-static-core'; | ||
import { Class, ServiceManager } from '../core'; | ||
export interface ExpressApplication extends express.Express { | ||
export interface ExpressApplication extends Express { | ||
[name: string]: any; | ||
@@ -12,4 +12,4 @@ } | ||
serviceManager?: ServiceManager; | ||
preMiddlewares?: (express.RequestHandler | express.ErrorRequestHandler)[]; | ||
postMiddlewares?: (express.RequestHandler | express.ErrorRequestHandler)[]; | ||
preMiddlewares?: (RequestHandler | ErrorRequestHandler)[]; | ||
postMiddlewares?: (RequestHandler | ErrorRequestHandler)[]; | ||
} | ||
@@ -29,5 +29,5 @@ /** | ||
* optionally overriding the mapped identities. | ||
* @param {(express.RequestHandler | express.ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express | ||
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express | ||
* middlewares to be executed before the controllers and hooks. | ||
* @param {(express.RequestHandler | express.ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express | ||
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express | ||
* middlewares to be executed after the controllers and hooks, but before the 500 or 404 handler get called. | ||
@@ -50,5 +50,5 @@ * @returns {ExpressApplication} The express application. | ||
* optionally overriding the mapped identities. | ||
* @param {(express.RequestHandler | express.ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express | ||
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express | ||
* middlewares to be executed before the controllers and hooks. | ||
* @param {(express.RequestHandler | express.ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express | ||
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express | ||
* middlewares to be executed after the controllers and hooks, but before the 500 or 404 handler get called. | ||
@@ -55,0 +55,0 @@ * @returns {Promise<ExpressApplication>} The express application. |
@@ -54,5 +54,5 @@ "use strict"; | ||
* optionally overriding the mapped identities. | ||
* @param {(express.RequestHandler | express.ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express | ||
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express | ||
* middlewares to be executed before the controllers and hooks. | ||
* @param {(express.RequestHandler | express.ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express | ||
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express | ||
* middlewares to be executed after the controllers and hooks, but before the 500 or 404 handler get called. | ||
@@ -116,5 +116,5 @@ * @returns {ExpressApplication} The express application. | ||
* optionally overriding the mapped identities. | ||
* @param {(express.RequestHandler | express.ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express | ||
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express | ||
* middlewares to be executed before the controllers and hooks. | ||
* @param {(express.RequestHandler | express.ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express | ||
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express | ||
* middlewares to be executed after the controllers and hooks, but before the 500 or 404 handler get called. | ||
@@ -121,0 +121,0 @@ * @returns {Promise<ExpressApplication>} The express application. |
@@ -1,2 +0,2 @@ | ||
import { RequestHandler } from 'express'; | ||
import { RequestHandler } from 'express-serve-static-core'; | ||
import { Route, ServiceManager } from '../core'; | ||
@@ -3,0 +3,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
import { ErrorRequestHandler } from 'express'; | ||
import { ErrorRequestHandler } from 'express-serve-static-core'; | ||
import { CreateAppOptions } from './create-app'; | ||
@@ -3,0 +3,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
import { RequestHandler } from 'express'; | ||
import { RequestHandler } from 'express-serve-static-core'; | ||
/** | ||
@@ -3,0 +3,0 @@ * Create an express middleware to display a 404 HTML page. |
@@ -1,2 +0,2 @@ | ||
import { Response } from 'express'; | ||
import { Response } from 'express-serve-static-core'; | ||
import { HttpResponse } from '../core'; | ||
@@ -3,0 +3,0 @@ /** |
{ | ||
"name": "@foal/core", | ||
"version": "1.7.1", | ||
"version": "1.8.0", | ||
"description": "A Node.js and TypeScript framework, all-inclusive.", | ||
@@ -21,2 +21,5 @@ "main": "./lib/index.js", | ||
}, | ||
"funding": { | ||
"url": "https://github.com/sponsors/LoicPoullain" | ||
}, | ||
"engines": { | ||
@@ -80,3 +83,3 @@ "node": ">=8" | ||
"dependencies": { | ||
"@types/express": "~4.17.2", | ||
"@types/express-serve-static-core": "4.17.0", | ||
"ajv": "~6.12.0", | ||
@@ -91,3 +94,3 @@ "cookie-parser": "~1.4.4", | ||
"devDependencies": { | ||
"@foal/ejs": "^1.7.1", | ||
"@foal/ejs": "^1.8.0", | ||
"@types/mocha": "~2.2.43", | ||
@@ -113,3 +116,3 @@ "@types/node": "~10.1.2", | ||
}, | ||
"gitHead": "1de8445fbadbb556433c6df47449064fe8a79e83" | ||
"gitHead": "524cf80c6b16885e3488c0583f32475bb9e47cab" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
345487
8725
+ Added@types/express-serve-static-core@4.17.0(transitive)
- Removed@types/express@~4.17.2
- Removed@types/body-parser@1.19.5(transitive)
- Removed@types/connect@3.4.38(transitive)
- Removed@types/express@4.17.21(transitive)
- Removed@types/express-serve-static-core@4.19.6(transitive)
- Removed@types/http-errors@2.0.4(transitive)
- Removed@types/mime@1.3.5(transitive)
- Removed@types/qs@6.9.16(transitive)
- Removed@types/send@0.17.4(transitive)
- Removed@types/serve-static@1.15.7(transitive)