Socket
Socket
Sign inDemoInstall

@foal/core

Package Overview
Dependencies
Maintainers
1
Versions
98
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@foal/core - npm Package Compare versions

Comparing version 1.11.1 to 2.0.0-beta.0

lib/common/hooks/user-required.hook.d.ts

5

lib/common/hooks/index.d.ts
export { Log, LogOptions } from './log.hook';
export { UserRequired } from './user-required.hook';
export { ValidateBody } from './validate-body.hook';
export { ValidateCookie } from './validate-cookie.hook';
export { ValidateCookies } from './validate-cookies.hook';
export { ValidateHeader } from './validate-header.hook';
export { ValidateHeaders } from './validate-headers.hook';
export { ValidatePathParam } from './validate-path-param.hook';
export { ValidateParams } from './validate-params.hook';
export { ValidateQueryParam } from './validate-query-param.hook';
export { ValidateQuery } from './validate-query.hook';

23

lib/common/hooks/index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidateQueryParam = exports.ValidatePathParam = exports.ValidateHeader = exports.ValidateCookie = exports.ValidateBody = exports.UserRequired = exports.Log = void 0;
var log_hook_1 = require("./log.hook");
exports.Log = log_hook_1.Log;
Object.defineProperty(exports, "Log", { enumerable: true, get: function () { return log_hook_1.Log; } });
var user_required_hook_1 = require("./user-required.hook");
Object.defineProperty(exports, "UserRequired", { enumerable: true, get: function () { return user_required_hook_1.UserRequired; } });
var validate_body_hook_1 = require("./validate-body.hook");
exports.ValidateBody = validate_body_hook_1.ValidateBody;
Object.defineProperty(exports, "ValidateBody", { enumerable: true, get: function () { return validate_body_hook_1.ValidateBody; } });
var validate_cookie_hook_1 = require("./validate-cookie.hook");
exports.ValidateCookie = validate_cookie_hook_1.ValidateCookie;
var validate_cookies_hook_1 = require("./validate-cookies.hook");
exports.ValidateCookies = validate_cookies_hook_1.ValidateCookies;
Object.defineProperty(exports, "ValidateCookie", { enumerable: true, get: function () { return validate_cookie_hook_1.ValidateCookie; } });
var validate_header_hook_1 = require("./validate-header.hook");
exports.ValidateHeader = validate_header_hook_1.ValidateHeader;
var validate_headers_hook_1 = require("./validate-headers.hook");
exports.ValidateHeaders = validate_headers_hook_1.ValidateHeaders;
Object.defineProperty(exports, "ValidateHeader", { enumerable: true, get: function () { return validate_header_hook_1.ValidateHeader; } });
var validate_path_param_hook_1 = require("./validate-path-param.hook");
exports.ValidatePathParam = validate_path_param_hook_1.ValidatePathParam;
var validate_params_hook_1 = require("./validate-params.hook");
exports.ValidateParams = validate_params_hook_1.ValidateParams;
Object.defineProperty(exports, "ValidatePathParam", { enumerable: true, get: function () { return validate_path_param_hook_1.ValidatePathParam; } });
var validate_query_param_hook_1 = require("./validate-query-param.hook");
exports.ValidateQueryParam = validate_query_param_hook_1.ValidateQueryParam;
var validate_query_hook_1 = require("./validate-query.hook");
exports.ValidateQuery = validate_query_hook_1.ValidateQuery;
Object.defineProperty(exports, "ValidateQueryParam", { enumerable: true, get: function () { return validate_query_param_hook_1.ValidateQueryParam; } });
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isFunction = void 0;
function isFunction(schema) {

@@ -4,0 +5,0 @@ return typeof schema === 'function';

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Log = void 0;
const core_1 = require("../../core");

@@ -4,0 +5,0 @@ /**

@@ -7,3 +7,3 @@ import { HookDecorator } from '../../core';

* @param {(object | ((controller: any) => object))} schema - Schema used to validate the body request.
* @param {{ openapi?: boolean }} [options={}] - Options to add openapi metadata
* @param {{ openapi?: boolean }} [options] - Options to add openapi metadata
* @returns {HookDecorator} - The hook.

@@ -10,0 +10,0 @@ */

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidateBody = void 0;
// FoalTS
const core_1 = require("../../core");
const openapi_1 = require("../../openapi");
const utils_1 = require("../utils");

@@ -13,37 +13,30 @@ const is_function_util_1 = require("./is-function.util");

* @param {(object | ((controller: any) => object))} schema - Schema used to validate the body request.
* @param {{ openapi?: boolean }} [options={}] - Options to add openapi metadata
* @param {{ openapi?: boolean }} [options] - Options to add openapi metadata
* @returns {HookDecorator} - The hook.
*/
function ValidateBody(schema, options = {}) {
const ajv = utils_1.getAjvInstance();
function validate(ctx) {
const ajvSchema = is_function_util_1.isFunction(schema) ? schema(this) : schema;
if (!ajv.validate(ajvSchema, ctx.request.body)) {
return new core_1.HttpResponseBadRequest({ body: ajv.errors });
function ValidateBody(schema, options) {
let validateSchema;
function validate(ctx, services) {
if (!validateSchema) {
const ajvSchema = is_function_util_1.isFunction(schema) ? schema(this) : schema;
const components = services.get(core_1.OpenApi).getComponents(this);
validateSchema = utils_1.getAjvInstance().compile(Object.assign(Object.assign({}, ajvSchema), { components }));
}
if (!validateSchema(ctx.request.body)) {
return new core_1.HttpResponseBadRequest({ body: validateSchema.errors });
}
}
return (target, propertyKey) => {
core_1.Hook(validate)(target, propertyKey);
if (options.openapi === false ||
(options.openapi === undefined && !core_1.Config.get2('settings.openapi.useHooks', 'boolean'))) {
return;
}
function makeRequestBody(schema) {
return {
content: {
'application/json': { schema }
},
required: true
};
}
const requestBody = is_function_util_1.isFunction(schema) ? (c) => makeRequestBody(schema(c)) : makeRequestBody(schema);
if (propertyKey) {
openapi_1.ApiRequestBody(requestBody)(target, propertyKey);
}
else {
openapi_1.ApiRequestBody(requestBody)(target);
}
openapi_1.ApiResponse(400, { description: 'Bad request.' })(target, propertyKey);
};
const openapi = [
core_1.ApiRequestBody((c) => ({
content: {
'application/json': {
schema: is_function_util_1.isFunction(schema) ? schema(c) : schema
}
},
required: true
})),
core_1.ApiResponse(400, { description: 'Bad request.' })
];
return core_1.Hook(validate, openapi, options);
}
exports.ValidateBody = ValidateBody;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidateCookie = void 0;
// FoalTS
const core_1 = require("../../core");
const openapi_1 = require("../../openapi");
const utils_1 = require("../utils");

@@ -21,34 +21,33 @@ const is_function_util_1 = require("./is-function.util");

function ValidateCookie(name, schema = { type: 'string' }, options = {}) {
const ajv = utils_1.getAjvInstance();
const required = options.required !== false;
function validate(ctx) {
const cookiesSchema = {
properties: {
[name]: is_function_util_1.isFunction(schema) ? schema(this) : schema
},
required: required ? [name] : [],
type: 'object',
};
if (!ajv.validate(cookiesSchema, ctx.request.cookies)) {
return new core_1.HttpResponseBadRequest({ cookies: ajv.errors });
var _a;
// tslint:disable-next-line
const required = (_a = options.required) !== null && _a !== void 0 ? _a : true;
let validateSchema;
function validate(ctx, services) {
if (!validateSchema) {
const ajvSchema = is_function_util_1.isFunction(schema) ? schema(this) : schema;
const components = services.get(core_1.OpenApi).getComponents(this);
validateSchema = utils_1.getAjvInstance().compile({
components,
properties: {
[name]: ajvSchema
},
required: required ? [name] : [],
type: 'object',
});
}
if (!validateSchema(ctx.request.cookies)) {
return new core_1.HttpResponseBadRequest({ cookies: validateSchema.errors });
}
}
return (target, propertyKey) => {
core_1.Hook(validate)(target, propertyKey);
if (options.openapi === false ||
(options.openapi === undefined && !core_1.Config.get2('settings.openapi.useHooks', 'boolean'))) {
return;
}
function makeParameter(schema) {
const result = { in: 'cookie', name, schema };
if (required) {
result.required = required;
}
return result;
}
const apiCookieParameter = is_function_util_1.isFunction(schema) ? (c) => makeParameter(schema(c)) : makeParameter(schema);
openapi_1.ApiParameter(apiCookieParameter)(target, propertyKey);
openapi_1.ApiResponse(400, { description: 'Bad request.' })(target, propertyKey);
};
const param = { in: 'cookie', name };
if (required) {
param.required = required;
}
const openapi = [
core_1.ApiParameter((c) => (Object.assign(Object.assign({}, param), { schema: is_function_util_1.isFunction(schema) ? schema(c) : schema }))),
core_1.ApiResponse(400, { description: 'Bad request.' })
];
return core_1.Hook(validate, openapi, options);
}
exports.ValidateCookie = ValidateCookie;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// FoalTS
exports.ValidateHeader = void 0;
const core_1 = require("../../core");
const openapi_1 = require("../../openapi");
const utils_1 = require("../utils");

@@ -21,35 +20,34 @@ const is_function_util_1 = require("./is-function.util");

function ValidateHeader(name, schema = { type: 'string' }, options = {}) {
const ajv = utils_1.getAjvInstance();
const required = options.required !== false;
var _a;
// tslint:disable-next-line
const required = (_a = options.required) !== null && _a !== void 0 ? _a : true;
name = name.toLowerCase();
function validate(ctx) {
const headersSchema = {
properties: {
[name]: is_function_util_1.isFunction(schema) ? schema(this) : schema
},
required: required ? [name] : [],
type: 'object',
};
if (!ajv.validate(headersSchema, ctx.request.headers)) {
return new core_1.HttpResponseBadRequest({ headers: ajv.errors });
let validateSchema;
function validate(ctx, services) {
if (!validateSchema) {
const ajvSchema = is_function_util_1.isFunction(schema) ? schema(this) : schema;
const components = services.get(core_1.OpenApi).getComponents(this);
validateSchema = utils_1.getAjvInstance().compile({
components,
properties: {
[name]: ajvSchema
},
required: required ? [name] : [],
type: 'object',
});
}
if (!validateSchema(ctx.request.headers)) {
return new core_1.HttpResponseBadRequest({ headers: validateSchema.errors });
}
}
return (target, propertyKey) => {
core_1.Hook(validate)(target, propertyKey);
if (options.openapi === false ||
(options.openapi === undefined && !core_1.Config.get2('settings.openapi.useHooks', 'boolean'))) {
return;
}
function makeParameter(schema) {
const result = { in: 'header', name, schema };
if (required) {
result.required = required;
}
return result;
}
const apiHeaderParameter = is_function_util_1.isFunction(schema) ? (c) => makeParameter(schema(c)) : makeParameter(schema);
openapi_1.ApiParameter(apiHeaderParameter)(target, propertyKey);
openapi_1.ApiResponse(400, { description: 'Bad request.' })(target, propertyKey);
};
const param = { in: 'header', name };
if (required) {
param.required = required;
}
const openapi = [
core_1.ApiParameter((c) => (Object.assign(Object.assign({}, param), { schema: is_function_util_1.isFunction(schema) ? schema(c) : schema }))),
core_1.ApiResponse(400, { description: 'Bad request.' })
];
return core_1.Hook(validate, openapi, options);
}
exports.ValidateHeader = ValidateHeader;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidatePathParam = void 0;
// FoalTS
const core_1 = require("../../core");
const openapi_1 = require("../../openapi");
const utils_1 = require("../utils");

@@ -20,29 +20,31 @@ const is_function_util_1 = require("./is-function.util");

function ValidatePathParam(name, schema, options = {}) {
const ajv = utils_1.getAjvInstance();
function validate(ctx) {
const paramsSchema = {
properties: {
[name]: is_function_util_1.isFunction(schema) ? schema(this) : schema
},
required: [name],
type: 'object',
};
if (!ajv.validate(paramsSchema, ctx.request.params)) {
return new core_1.HttpResponseBadRequest({ pathParams: ajv.errors });
let validateSchema;
function validate(ctx, services) {
if (!validateSchema) {
const ajvSchema = is_function_util_1.isFunction(schema) ? schema(this) : schema;
const components = services.get(core_1.OpenApi).getComponents(this);
validateSchema = utils_1.getAjvInstance().compile({
components,
properties: {
[name]: ajvSchema
},
required: [name],
type: 'object',
});
}
if (!validateSchema(ctx.request.params)) {
return new core_1.HttpResponseBadRequest({ pathParams: validateSchema.errors });
}
}
return (target, propertyKey) => {
core_1.Hook(validate)(target, propertyKey);
if (options.openapi === false ||
(options.openapi === undefined && !core_1.Config.get2('settings.openapi.useHooks', 'boolean'))) {
return;
}
function makeParameter(schema) {
return { in: 'path', name, required: true, schema };
}
const apiPathParameter = is_function_util_1.isFunction(schema) ? (c) => makeParameter(schema(c)) : makeParameter(schema);
openapi_1.ApiParameter(apiPathParameter)(target, propertyKey);
openapi_1.ApiResponse(400, { description: 'Bad request.' })(target, propertyKey);
};
const openapi = [
core_1.ApiParameter((c) => ({
in: 'path',
name,
required: true,
schema: is_function_util_1.isFunction(schema) ? schema(c) : schema,
})),
core_1.ApiResponse(400, { description: 'Bad request.' })
];
return core_1.Hook(validate, openapi, options);
}
exports.ValidatePathParam = ValidatePathParam;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidateQueryParam = void 0;
// FoalTS
const core_1 = require("../../core");
const openapi_1 = require("../../openapi");
const utils_1 = require("../utils");

@@ -21,34 +21,33 @@ const is_function_util_1 = require("./is-function.util");

function ValidateQueryParam(name, schema = { type: 'string' }, options = {}) {
const ajv = utils_1.getAjvInstance();
const required = options.required !== false;
function validate(ctx) {
const querySchema = {
properties: {
[name]: is_function_util_1.isFunction(schema) ? schema(this) : schema
},
required: required ? [name] : [],
type: 'object',
};
if (!ajv.validate(querySchema, ctx.request.query)) {
return new core_1.HttpResponseBadRequest({ query: ajv.errors });
var _a;
// tslint:disable-next-line
const required = (_a = options.required) !== null && _a !== void 0 ? _a : true;
let validateSchema;
function validate(ctx, services) {
if (!validateSchema) {
const ajvSchema = is_function_util_1.isFunction(schema) ? schema(this) : schema;
const components = services.get(core_1.OpenApi).getComponents(this);
validateSchema = utils_1.getAjvInstance().compile({
components,
properties: {
[name]: ajvSchema
},
required: required ? [name] : [],
type: 'object',
});
}
if (!validateSchema(ctx.request.query)) {
return new core_1.HttpResponseBadRequest({ query: validateSchema.errors });
}
}
return (target, propertyKey) => {
core_1.Hook(validate)(target, propertyKey);
if (options.openapi === false ||
(options.openapi === undefined && !core_1.Config.get2('settings.openapi.useHooks', 'boolean'))) {
return;
}
function makeParameter(schema) {
const result = { in: 'query', name, schema };
if (required) {
result.required = required;
}
return result;
}
const apiQueryParameter = is_function_util_1.isFunction(schema) ? (c) => makeParameter(schema(c)) : makeParameter(schema);
openapi_1.ApiParameter(apiQueryParameter)(target, propertyKey);
openapi_1.ApiResponse(400, { description: 'Bad request.' })(target, propertyKey);
};
const param = { in: 'query', name };
if (required) {
param.required = required;
}
const openapi = [
core_1.ApiParameter((c) => (Object.assign(Object.assign({}, param), { schema: is_function_util_1.isFunction(schema) ? schema(c) : schema }))),
core_1.ApiResponse(400, { description: 'Bad request.' })
];
return core_1.Hook(validate, openapi, options);
}
exports.ValidateQueryParam = ValidateQueryParam;

@@ -1,4 +0,3 @@

export * from './errors';
export * from './hooks';
export * from './tokens';
export * from './utils';
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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 });
__export(require("./errors"));
__export(require("./hooks"));
__export(require("./tokens"));
__export(require("./utils"));
__exportStar(require("./hooks"), exports);
__exportStar(require("./tokens"), exports);
__exportStar(require("./utils"), exports);
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertBase64ToBase64url = void 0;
/**

@@ -4,0 +5,0 @@ * Convert a base64-encode string into a base64url-encode string with no equals.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateSignedToken = void 0;
const generate_token_util_1 = require("./generate-token.util");

@@ -4,0 +5,0 @@ const sign_token_util_1 = require("./sign-token.util");

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateToken = void 0;
// std

@@ -4,0 +5,0 @@ const crypto_1 = require("crypto");

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifySignedToken = exports.signToken = exports.generateToken = exports.generateSignedToken = exports.convertBase64ToBase64url = void 0;
var convert_base64_to_base64_url_util_1 = require("./convert-base64-to-base64-url.util");
exports.convertBase64ToBase64url = convert_base64_to_base64_url_util_1.convertBase64ToBase64url;
Object.defineProperty(exports, "convertBase64ToBase64url", { enumerable: true, get: function () { return convert_base64_to_base64_url_util_1.convertBase64ToBase64url; } });
var generate_signed_token_util_1 = require("./generate-signed-token.util");
exports.generateSignedToken = generate_signed_token_util_1.generateSignedToken;
Object.defineProperty(exports, "generateSignedToken", { enumerable: true, get: function () { return generate_signed_token_util_1.generateSignedToken; } });
var generate_token_util_1 = require("./generate-token.util");
exports.generateToken = generate_token_util_1.generateToken;
Object.defineProperty(exports, "generateToken", { enumerable: true, get: function () { return generate_token_util_1.generateToken; } });
var sign_token_util_1 = require("./sign-token.util");
exports.signToken = sign_token_util_1.signToken;
Object.defineProperty(exports, "signToken", { enumerable: true, get: function () { return sign_token_util_1.signToken; } });
var verify_signed_token_util_1 = require("./verify-signed-token.util");
exports.verifySignedToken = verify_signed_token_util_1.verifySignedToken;
Object.defineProperty(exports, "verifySignedToken", { enumerable: true, get: function () { return verify_signed_token_util_1.verifySignedToken; } });
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.signToken = exports.sign = void 0;
// std

@@ -4,0 +5,0 @@ const crypto_1 = require("crypto");

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifySignedToken = void 0;
// std

@@ -4,0 +5,0 @@ const crypto_1 = require("crypto");

@@ -8,6 +8,7 @@ import 'reflect-metadata';

* @export
* @template T
* @param {string} path - The HTTP path.
* @param {Class} controllerClass - The controller class.
* @returns {Class} The controller class.
* @param {Class<T>} controllerClass - The controller class.
* @returns {Class<T>} The controller class.
*/
export declare function controller(path: string, controllerClass: Class): Class;
export declare function controller<T>(path: string, controllerClass: Class<T>): Class<T>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.controller = void 0;
// 3p

@@ -10,5 +11,6 @@ require("reflect-metadata");

* @export
* @template T
* @param {string} path - The HTTP path.
* @param {Class} controllerClass - The controller class.
* @returns {Class} The controller class.
* @param {Class<T>} controllerClass - The controller class.
* @returns {Class<T>} The controller class.
*/

@@ -15,0 +17,0 @@ function controller(path, controllerClass) {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.escapeProp = void 0;
const escape_1 = require("./escape");

@@ -4,0 +5,0 @@ /**

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.escape = void 0;
const escapeMap = {

@@ -4,0 +5,0 @@ '"': '&quot;',

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAjvInstance = exports._instanceWrapper = void 0;
// 3p

@@ -26,7 +27,7 @@ const Ajv = require("ajv");

exports._instanceWrapper.instance = new Ajv({
allErrors: core_1.Config.get2('settings.ajv.allErrors', 'boolean'),
coerceTypes: core_1.Config.get2('settings.ajv.coerceTypes', 'boolean', true),
nullable: core_1.Config.get2('settings.ajv.nullable', 'boolean'),
removeAdditional: core_1.Config.get2('settings.ajv.removeAdditional', 'boolean|string', true),
useDefaults: core_1.Config.get2('settings.ajv.useDefaults', 'boolean|string', true),
allErrors: core_1.Config.get('settings.ajv.allErrors', 'boolean'),
coerceTypes: core_1.Config.get('settings.ajv.coerceTypes', 'boolean', true),
nullable: core_1.Config.get('settings.ajv.nullable', 'boolean'),
removeAdditional: core_1.Config.get('settings.ajv.removeAdditional', 'boolean|string', true),
useDefaults: core_1.Config.get('settings.ajv.useDefaults', 'boolean|string', true),
});

@@ -33,0 +34,0 @@ }

@@ -5,3 +5,3 @@ /**

* Configured to use PBKDF2 + HMAC + SHA256.
* The result is a 64 byte binary string (or hex if the legacy option is true).
* The result is a 64 byte binary string.
*

@@ -14,7 +14,4 @@ * The random salt is 16 bytes long.

* @param {string} plainTextPassword - The password to hash.
* @param {{ legacy?: boolean }} [options={}]
* @returns {Promise<string>} The derived key with the algorithm name, the number of iterations and the salt.
*/
export declare function hashPassword(plainTextPassword: string, options?: {
legacy?: boolean;
}): Promise<string>;
export declare function hashPassword(plainTextPassword: string): Promise<string>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hashPassword = void 0;
const crypto_1 = require("crypto");
const util_1 = require("util");
/**
* Legacy function to hash passwords. Only kept for backward compatibility.
* @param password
*/
async function parsePassword(password) {
const salt = (await util_1.promisify(crypto_1.randomBytes)(16)).toString('hex');
const iterations = 100000;
const keylen = 64;
const digest = 'sha256';
const derivedKey = await util_1.promisify(crypto_1.pbkdf2)(password, salt, iterations, keylen, digest);
return `pbkdf2_${digest}$${iterations}$${salt}$${derivedKey.toString('hex')}`;
}
/**
* Hash a password using the PBKDF2 algorithm.
*
* Configured to use PBKDF2 + HMAC + SHA256.
* The result is a 64 byte binary string (or hex if the legacy option is true).
* The result is a 64 byte binary string.
*

@@ -29,9 +18,5 @@ * The random salt is 16 bytes long.

* @param {string} plainTextPassword - The password to hash.
* @param {{ legacy?: boolean }} [options={}]
* @returns {Promise<string>} The derived key with the algorithm name, the number of iterations and the salt.
*/
async function hashPassword(plainTextPassword, options = {}) {
if (options.legacy) {
return parsePassword(plainTextPassword);
}
async function hashPassword(plainTextPassword) {
const saltBuffer = await util_1.promisify(crypto_1.randomBytes)(16);

@@ -38,0 +23,0 @@ const iterations = 150000;

@@ -9,3 +9,2 @@ export { controller } from './controller.util';

export { render } from './render.util';
export { validate } from './validate.util';
export { verifyPassword } from './verify-password.util';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifyPassword = exports.render = exports.renderError = exports.isInFile = exports.hashPassword = exports.getAjvInstance = exports.escape = exports.escapeProp = exports.controller = void 0;
var controller_util_1 = require("./controller.util");
exports.controller = controller_util_1.controller;
Object.defineProperty(exports, "controller", { enumerable: true, get: function () { return controller_util_1.controller; } });
var escape_prop_1 = require("./escape-prop");
exports.escapeProp = escape_prop_1.escapeProp;
Object.defineProperty(exports, "escapeProp", { enumerable: true, get: function () { return escape_prop_1.escapeProp; } });
var escape_1 = require("./escape");
exports.escape = escape_1.escape;
Object.defineProperty(exports, "escape", { enumerable: true, get: function () { return escape_1.escape; } });
var get_ajv_instance_1 = require("./get-ajv-instance");
exports.getAjvInstance = get_ajv_instance_1.getAjvInstance;
Object.defineProperty(exports, "getAjvInstance", { enumerable: true, get: function () { return get_ajv_instance_1.getAjvInstance; } });
var hash_password_util_1 = require("./hash-password.util");
exports.hashPassword = hash_password_util_1.hashPassword;
Object.defineProperty(exports, "hashPassword", { enumerable: true, get: function () { return hash_password_util_1.hashPassword; } });
var is_in_file_util_1 = require("./is-in-file.util");
exports.isInFile = is_in_file_util_1.isInFile;
Object.defineProperty(exports, "isInFile", { enumerable: true, get: function () { return is_in_file_util_1.isInFile; } });
var render_error_util_1 = require("./render-error.util");
exports.renderError = render_error_util_1.renderError;
Object.defineProperty(exports, "renderError", { enumerable: true, get: function () { return render_error_util_1.renderError; } });
var render_util_1 = require("./render.util");
exports.render = render_util_1.render;
var validate_util_1 = require("./validate.util");
exports.validate = validate_util_1.validate;
Object.defineProperty(exports, "render", { enumerable: true, get: function () { return render_util_1.render; } });
var verify_password_util_1 = require("./verify-password.util");
exports.verifyPassword = verify_password_util_1.verifyPassword;
Object.defineProperty(exports, "verifyPassword", { enumerable: true, get: function () { return verify_password_util_1.verifyPassword; } });
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isInFile = void 0;
// std

@@ -4,0 +5,0 @@ const fs_1 = require("fs");

import { Context, HttpResponseInternalServerError } from '../../core';
/**
* Render the default HTML page when an error is thrown or rejected in the application.
* Renders the default HTML page when an error is thrown or rejected in the application.
*

@@ -10,5 +10,5 @@ * The page is different depending on if the configuration key `settings.debug` is

* @param {Error} error - The error thrown or rejected.
* @param {Context} ctx - The Context. object.
* @param {Context} ctx - The Context object.
* @returns {Promise<HttpResponseInternalServerError>} The HTTP response.
*/
export declare function renderError(error: Error, ctx: Context): Promise<HttpResponseInternalServerError>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderError = void 0;
// std

@@ -10,6 +11,4 @@ const fs_1 = require("fs");

const render_util_1 = require("./render.util");
const page500 = '<html><head><title>INTERNAL SERVER ERROR</title></head><body>'
+ '<h1>500 - INTERNAL SERVER ERROR</h1></body></html>';
/**
* Render the default HTML page when an error is thrown or rejected in the application.
* Renders the default HTML page when an error is thrown or rejected in the application.
*

@@ -21,16 +20,18 @@ * The page is different depending on if the configuration key `settings.debug` is

* @param {Error} error - The error thrown or rejected.
* @param {Context} ctx - The Context. object.
* @param {Context} ctx - The Context object.
* @returns {Promise<HttpResponseInternalServerError>} The HTTP response.
*/
async function renderError(error, ctx) {
const template = await util_1.promisify(fs_1.readFile)(path_1.join(__dirname, '500.debug.html'), 'utf8');
if (!core_1.Config.get2('settings.debug', 'boolean')) {
return new core_1.HttpResponseInternalServerError(page500);
let body = '<html><head><title>INTERNAL SERVER ERROR</title></head><body>'
+ '<h1>500 - INTERNAL SERVER ERROR</h1></body></html>';
if (core_1.Config.get('settings.debug', 'boolean')) {
const template = await util_1.promisify(fs_1.readFile)(path_1.join(__dirname, '500.debug.html'), 'utf8');
body = render_util_1.renderToString(template, {
message: error.message,
name: error.name,
stack: error.stack
});
}
return new core_1.HttpResponseInternalServerError(render_util_1.renderToString(template, {
message: error.message,
name: error.name,
stack: error.stack
}));
return new core_1.HttpResponseInternalServerError(body, { ctx, error });
}
exports.renderError = renderError;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.render = exports.renderToString = void 0;
// std

@@ -42,5 +43,5 @@ const fs_1 = require("fs");

const template = await util_1.promisify(fs_1.readFile)(path, 'utf8');
const templateEngine = core_1.Config.get2('settings.templateEngine', 'string');
const templateEngine = core_1.Config.get('settings.templateEngine', 'string');
if (templateEngine) {
const { renderToString, __express } = require(templateEngine);
const { __express } = require(templateEngine);
if (__express) {

@@ -56,5 +57,2 @@ return new Promise((resolve, reject) => {

}
if (renderToString) {
return new core_1.HttpResponseOK(renderToString(template, locals));
}
throw new Error(`${templateEngine} is not a template engine compatible with FoalTS.`);

@@ -61,0 +59,0 @@ }

@@ -7,7 +7,4 @@ /**

* @param {string} passwordHash - The password hash generated by the `hashPassword` function.
* @param {{ legacy?: boolean }} [options={}]
* @returns {Promise<boolean>} True if the hash and the password match. False otherwise.
*/
export declare function verifyPassword(plainTextPassword: string, passwordHash: string, options?: {
legacy?: boolean;
}): Promise<boolean>;
export declare function verifyPassword(plainTextPassword: string, passwordHash: string): Promise<boolean>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifyPassword = void 0;
const assert_1 = require("assert");

@@ -12,7 +13,5 @@ const crypto_1 = require("crypto");

* @param {string} passwordHash - The password hash generated by the `hashPassword` function.
* @param {{ legacy?: boolean }} [options={}]
* @returns {Promise<boolean>} True if the hash and the password match. False otherwise.
*/
async function verifyPassword(plainTextPassword, passwordHash, options = {}) {
const legacy = options.legacy || false;
async function verifyPassword(plainTextPassword, passwordHash) {
const [algorithm, iterations, salt, derivedKey] = passwordHash.split('$');

@@ -24,8 +23,8 @@ assert_1.strictEqual(algorithm, 'pbkdf2_sha256', 'Invalid algorithm.');

assert_1.strictEqual(isNaN(parseInt(iterations, 10)), false, 'Invalid password format.');
const saltBuffer = Buffer.from(salt, legacy ? 'hex' : 'base64');
const derivedKeyBuffer = Buffer.from(derivedKey, legacy ? 'hex' : 'base64');
const saltBuffer = Buffer.from(salt, 'base64');
const derivedKeyBuffer = Buffer.from(derivedKey, 'base64');
const digest = 'sha256'; // TODO: depends on the algorthim var
const password = await util_1.promisify(crypto_1.pbkdf2)(plainTextPassword, legacy ? saltBuffer.toString('hex') : saltBuffer, parseInt(iterations, 10), derivedKeyBuffer.length, digest);
const password = await util_1.promisify(crypto_1.pbkdf2)(plainTextPassword, saltBuffer, parseInt(iterations, 10), derivedKeyBuffer.length, digest);
return crypto_1.timingSafeEqual(password, derivedKeyBuffer);
}
exports.verifyPassword = verifyPassword;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigNotFoundError = void 0;
const utils_1 = require("./utils");
class ConfigNotFoundError extends Error {
constructor(key, msg) {
super(`No value found for the configuration key "${key}".\n\n`
+ (msg ? `${msg}\n\n` : '')
+ 'To pass a value, you can use:\n'
+ `- the environment variable ${utils_1.dotToUnderscore(key)},\n`
+ `- the ".env" file with the variable ${utils_1.dotToUnderscore(key)},\n`
+ `- the JSON file "config/${process.env.NODE_ENV || 'development'}.json" with the path "${key}",\n`
+ `- the YAML file "config/${process.env.NODE_ENV || 'development'}.yml" with the path "${key}",\n`
+ `- the JSON file "config/default.json" with the path "${key}", or\n`
+ `- the YAML file "config/default.yml" with the path "${key}".`);
super();
this.key = key;
this.msg = msg;
this.name = 'ConfigNotFoundError';
const keywords = key.split('.');
function generateContent(type) {
const lines = [];
if (type === 'JS') {
lines.push(' const { Env } = require(\'@foal/core\');');
lines.push('');
}
if (type !== 'YAML') {
lines.push(' {');
}
keywords.forEach((keyword, index) => {
if (type === 'JSON') {
keyword = `"${keyword}"`;
}
const spaces = ' '.repeat(index + (type === 'YAML' ? 1 : 2));
if (index === keywords.length - 1) {
lines.push(spaces + keyword + ': <your_value>');
if (type === 'YAML') {
lines.push(spaces + '# OR with an environment variable: ');
}
else {
lines.push(spaces + '// OR with an environment variable: ');
}
let envValue = '';
switch (type) {
case 'JS':
envValue = 'Env.get(\'<YOUR_ENVIRONMENT_VARIABLE>\')';
break;
case 'JSON':
envValue = '"env(<YOUR_ENVIRONMENT_VARIABLE>)"';
break;
case 'YAML':
envValue = 'env(<YOUR_ENVIRONMENT_VARIABLE>)';
break;
}
lines.push(spaces + keyword + ': ' + envValue);
}
else {
if (type === 'YAML') {
lines.push(spaces + keyword + ':');
}
else {
lines.push(spaces + keyword + ': {');
}
}
});
if (type !== 'YAML') {
keywords.forEach((_, index) => {
if (index === keywords.length - 1) {
return;
}
const spaces = ' '.repeat(keywords.length - index);
lines.push(spaces + '}');
});
lines.push(' }');
}
return lines;
}
this.message = '\n\n'
+ utils_1.makeBox('JSON file (config/default.json, config/test.json, ...)', generateContent('JSON'))
+ '\n'
+ utils_1.makeBox('YAML file (config/default.yml, config/test.yml, ...)', generateContent('YAML'))
+ '\n'
+ utils_1.makeBox('JS file (config/default.js, config/test.js, ...)', generateContent('JS'))
+ '\n'
+ `No value found for the configuration key "${key}".\n`
+ (msg === undefined ? '' : `\n${msg}\n`)
+ '\n'
+ `To pass a value, use one of the examples above.\n`;
}
}
exports.ConfigNotFoundError = ConfigNotFoundError;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigTypeError = void 0;
const utils_1 = require("./utils");
class ConfigTypeError extends Error {
constructor(key, expected, actual) {
super(`The value of the configuration key "${key}" has an invalid type.\n`
+ '\n'
+ `Expected a "${expected}", but got a "${actual}".`);
super();
this.key = key;

@@ -12,4 +12,30 @@ this.expected = expected;

this.name = 'ConfigTypeError';
const keywords = key.split('.');
const lines = [];
lines.push(' {');
keywords.forEach((keyword, index) => {
const spaces = ' '.repeat(index + 1);
if (index === keywords.length - 1) {
lines.push('->' + spaces + keyword + ': *************');
}
else {
lines.push(' ' + spaces + keyword + ': {');
}
});
keywords.forEach((_, index) => {
if (index === keywords.length - 1) {
return;
}
const spaces = ' '.repeat(keywords.length - index);
lines.push(spaces + '}');
});
lines.push(' }');
this.message = '\n\n'
+ utils_1.makeBox('Configuration file', lines)
+ '\n'
+ `The value of the configuration key "${key}" has an invalid type.\n`
+ '\n'
+ `Expected a "${expected}", but got a "${actual}".\n`;
}
}
exports.ConfigTypeError = ConfigTypeError;

@@ -13,28 +13,2 @@ declare type ValueStringType = 'string' | 'number' | 'boolean' | 'boolean|string' | 'number|string' | 'any';

/**
* Access environment variables and configuration files.
*
* For example, if it is called with the string `settings.session.secret`,
* the method will go through these steps:
*
* 1. If the environment variable `SETTINGS_SESSION_SECRET` exists, then return its value.
* 2. If `.env` exists and has a line `SETTINGS_SESSION_SECRET=`, then return its value.
* 3. If `config/${NODE_ENV}.json` exists and the property `config['settings']['session']['secret']`
* does too, then return its value.
* 4. Same with `config/${NODE_ENV}.yml`.
* 5. If `config/default.json` exists and the property `config['settings']['session']['secret']`
* does too, then return its value.
* 6. Same with `config/default.yml`.
*
* If none value is found, then the method returns the default value provided as second argument
* to the function. If none was given, it returns undefined.
*
* @static
* @template T - TypeScript type of the returned value. Default is `any`.
* @param {string} key - Name of the config key using dots and camel case.
* @param {T} [defaultValue] - Default value to return if no configuration is found with that key.
* @returns {T} The configuration value.
* @memberof Config
*/
static get<T = any>(key: string, defaultValue?: T): T;
/**
* Read the configuration value associated with the given key. Optionaly check its type.

@@ -50,4 +24,4 @@ *

*/
static get2<T extends ValueStringType>(key: string, type: T, defaultValue: ValueType<T>): ValueType<T>;
static get2<T extends ValueStringType>(key: string, type?: T): ValueType<T> | undefined;
static get<T extends ValueStringType>(key: string, type: T, defaultValue: ValueType<T>): ValueType<T>;
static get<T extends ValueStringType>(key: string, type?: T): ValueType<T> | undefined;
/**

@@ -74,37 +48,14 @@ * Read the configuration value associated with the given key. Optionaly check its type.

static clearCache(): void;
static set(key: string, value: string | number | boolean): void;
static remove(key: string): void;
private static yaml;
private static cache;
private static config;
private static testConfig;
private static readJSON;
private static readYAML;
private static readJS;
private static readConfigValue;
private static readDotEnvValue;
private static readJSONValue;
private static readYAMLValue;
private static mergeDeep;
private static getYAMLInstance;
private static convertType;
private static getValue;
/**
* Access environment variables and configuration files.
*
* For example, if it is called with the string `settings.session.secret`,
* the method will go through these steps:
*
* 1. If the environment variable `SETTINGS_SESSION_SECRET` exists, then return its value.
* 2. If `.env` exists and has a line `SETTINGS_SESSION_SECRET=`, then return its value.
* 3. If `config/${NODE_ENV}.json` exists and the property `config['settings']['session']['secret']`
* does too, then return its value.
* 4. Same with `config/${NODE_ENV}.yml`.
* 5. If `config/default.json` exists and the property `config['settings']['session']['secret']`
* does too, then return its value.
* 6. Same with `config/default.yml`.
*
* If none value is found, then the method returns the default value provided as second argument
* to the function. If none was given, it returns undefined.
*
* @template T - TypeScript type of the returned value. Default is `any`.
* @param {string} key - Name of the config key using dots and camel case.
* @param {T} [defaultValue] - Default value to return if no configuration is found with that key.
* @returns {T} The configuration value.
* @memberof Config
*/
get<T = any>(key: string, defaultValue?: T): T;
}
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Config = void 0;
// 3p
const fs_1 = require("fs");
const path_1 = require("path");
// FoalTS
const config_not_found_error_1 = require("./config-not-found.error");
const config_type_error_1 = require("./config-type.error");
const utils_1 = require("./utils");
const env_1 = require("./env");
/**

@@ -18,38 +20,3 @@ * Static class to access environment variables and configuration files.

class Config {
/**
* Access environment variables and configuration files.
*
* For example, if it is called with the string `settings.session.secret`,
* the method will go through these steps:
*
* 1. If the environment variable `SETTINGS_SESSION_SECRET` exists, then return its value.
* 2. If `.env` exists and has a line `SETTINGS_SESSION_SECRET=`, then return its value.
* 3. If `config/${NODE_ENV}.json` exists and the property `config['settings']['session']['secret']`
* does too, then return its value.
* 4. Same with `config/${NODE_ENV}.yml`.
* 5. If `config/default.json` exists and the property `config['settings']['session']['secret']`
* does too, then return its value.
* 6. Same with `config/default.yml`.
*
* If none value is found, then the method returns the default value provided as second argument
* to the function. If none was given, it returns undefined.
*
* @static
* @template T - TypeScript type of the returned value. Default is `any`.
* @param {string} key - Name of the config key using dots and camel case.
* @param {T} [defaultValue] - Default value to return if no configuration is found with that key.
* @returns {T} The configuration value.
* @memberof Config
*/
static get(key, defaultValue) {
let value = this.readConfigValue(key);
if (typeof value === 'string') {
value = this.convertType(value);
}
if (value !== undefined) {
return value;
}
return defaultValue;
}
static get2(key, type, defaultValue) {
static get(key, type, defaultValue) {
const value = this.readConfigValue(key);

@@ -59,3 +26,6 @@ if (value === undefined) {

}
if (type === 'boolean|string' && typeof value !== 'boolean') {
if (type === 'string' && typeof value !== 'string') {
throw new config_type_error_1.ConfigTypeError(key, 'string', typeof value);
}
if (type === 'boolean' && typeof value !== 'boolean') {
if (value === 'true') {

@@ -67,20 +37,4 @@ return true;

}
if (typeof value !== 'string') {
throw new config_type_error_1.ConfigTypeError(key, 'boolean|string', typeof value);
}
throw new config_type_error_1.ConfigTypeError(key, 'boolean', typeof value);
}
if (type === 'number|string' && typeof value !== 'number') {
if (typeof value !== 'string') {
throw new config_type_error_1.ConfigTypeError(key, 'number|string', typeof value);
}
if (value.replace(/ /g, '') !== '') {
const n = Number(value);
if (!isNaN(n)) {
return n;
}
}
}
if (type === 'string' && typeof value !== 'string') {
throw new config_type_error_1.ConfigTypeError(key, 'string', typeof value);
}
if (type === 'number' && typeof value !== 'number') {

@@ -95,3 +49,3 @@ if (typeof value === 'string' && value.replace(/ /g, '') !== '') {

}
if (type === 'boolean' && typeof value !== 'boolean') {
if (type === 'boolean|string' && typeof value !== 'boolean') {
if (value === 'true') {

@@ -103,4 +57,17 @@ return true;

}
throw new config_type_error_1.ConfigTypeError(key, 'boolean', typeof value);
if (typeof value !== 'string') {
throw new config_type_error_1.ConfigTypeError(key, 'boolean|string', typeof value);
}
}
if (type === 'number|string' && typeof value !== 'number') {
if (typeof value !== 'string') {
throw new config_type_error_1.ConfigTypeError(key, 'number|string', typeof value);
}
if (value.replace(/ /g, '') !== '') {
const n = Number(value);
if (!isNaN(n)) {
return n;
}
}
}
return value;

@@ -122,3 +89,3 @@ }

static getOrThrow(key, type, msg) {
const value = this.get2(key, type);
const value = this.get(key, type);
if (value === undefined) {

@@ -136,80 +103,81 @@ throw new config_not_found_error_1.ConfigNotFoundError(key, msg);

static clearCache() {
this.cache = {
dotEnv: undefined,
json: {},
yaml: {},
};
this.config = null;
this.testConfig.clear();
}
static readConfigValue(key) {
const underscoreName = utils_1.dotToUnderscore(key);
const envValue = process.env[underscoreName];
if (envValue !== undefined) {
return envValue;
static set(key, value) {
this.testConfig.set(key, value);
}
static remove(key) {
this.testConfig.delete(key);
}
static readJSON(path) {
if (!fs_1.existsSync(path)) {
return {};
}
const dotEnvValue = this.readDotEnvValue(underscoreName);
if (dotEnvValue !== undefined) {
return dotEnvValue;
const fileContent = fs_1.readFileSync(path, 'utf8');
return JSON.parse(fileContent);
}
static readYAML(path) {
if (!fs_1.existsSync(path)) {
return {};
}
const envJSONFilePath = `config/${process.env.NODE_ENV || 'development'}.json`;
const envJSONValue = this.readJSONValue(envJSONFilePath, key);
if (envJSONValue !== undefined) {
return envJSONValue;
const yaml = this.getYAMLInstance();
if (!yaml) {
console.log(`Impossible to read ${path}. The package "yamljs" is not installed.`);
return {};
}
const envYamlFilePath = `config/${process.env.NODE_ENV || 'development'}.yml`;
const envYAMLValue = this.readYAMLValue(envYamlFilePath, key);
if (envYAMLValue !== undefined) {
return envYAMLValue;
const fileContent = fs_1.readFileSync(path, 'utf8');
return yaml.parse(fileContent);
}
static readJS(path) {
if (!fs_1.existsSync(path)) {
return {};
}
const defaultJSONValue = this.readJSONValue('config/default.json', key);
if (defaultJSONValue !== undefined) {
return defaultJSONValue;
return require(path_1.join(process.cwd(), path));
}
static readConfigValue(key) {
if (this.testConfig.has(key)) {
return this.testConfig.get(key);
}
const defaultYAMLValue = this.readYAMLValue('config/default.yml', key);
if (defaultYAMLValue !== undefined) {
return defaultYAMLValue;
if (this.config === null) {
this.config = [
this.readJS('config/default.js'),
this.readYAML('config/default.yml'),
this.readJSON('config/default.json'),
this.readJS(`config/${process.env.NODE_ENV || 'development'}.js`),
this.readYAML(`config/${process.env.NODE_ENV || 'development'}.yml`),
this.readJSON(`config/${process.env.NODE_ENV || 'development'}.json`),
].reduce((config1, config2) => this.mergeDeep(config1, config2));
}
}
static readDotEnvValue(name) {
if (!this.cache.dotEnv) {
if (!fs_1.existsSync('.env')) {
return;
const properties = key.split('.');
let result = this.config;
for (const property of properties) {
result = result[property];
if (result === undefined) {
break;
}
const envFileContent = fs_1.readFileSync('.env', 'utf8');
this.cache.dotEnv = {};
envFileContent.replace(/\r\n/g, '\n').split('\n').forEach(line => {
const [key, ...values] = line.split('=');
const value = values.join('=');
this.cache.dotEnv[key] = value;
});
}
if (this.cache.dotEnv[name] !== undefined) {
return this.cache.dotEnv[name];
if (typeof result === 'string' && result.startsWith('env(') && result.endsWith(')')) {
const envVarName = result.substr(4, result.length - 5);
return env_1.Env.get(envVarName);
}
return result;
}
static readJSONValue(path, key) {
if (!this.cache.json[path]) {
if (!fs_1.existsSync(path)) {
return;
}
const fileContent = fs_1.readFileSync(path, 'utf8');
this.cache.json[path] = JSON.parse(fileContent);
static mergeDeep(target, source) {
// TODO: improve the tests of this function.
function isObject(o) {
return typeof o === 'object' && o !== null;
}
return this.getValue(this.cache.json[path], key);
}
static readYAMLValue(path, key) {
if (!this.cache.yaml[path]) {
if (!fs_1.existsSync(path)) {
return;
for (const key in source) {
if (isObject(target[key]) && isObject(source[key])) {
this.mergeDeep(target[key], source[key]);
}
const yaml = this.getYAMLInstance();
if (!yaml) {
console.log(`Impossible to read ${path}. The package "yamljs" is not installed.`);
return;
else {
target[key] = source[key];
}
const fileContent = fs_1.readFileSync(path, 'utf8');
this.cache.yaml[path] = yaml.parse(fileContent);
}
return this.getValue(this.cache.yaml[path], key);
return target;
}
static getYAMLInstance() {
// TODO: test this method (hard).
if (this.yaml === false) {

@@ -229,62 +197,5 @@ return false;

}
static convertType(value) {
if (value === 'true') {
return true;
}
if (value === 'false') {
return false;
}
if (value.replace(/ /g, '') === '') {
return value;
}
const n = Number(value);
if (!isNaN(n)) {
return n;
}
return value;
}
static getValue(config, propertyPath) {
const properties = propertyPath.split('.');
let result = config;
for (const property of properties) {
result = result[property];
if (result === undefined) {
break;
}
}
return result;
}
/**
* Access environment variables and configuration files.
*
* For example, if it is called with the string `settings.session.secret`,
* the method will go through these steps:
*
* 1. If the environment variable `SETTINGS_SESSION_SECRET` exists, then return its value.
* 2. If `.env` exists and has a line `SETTINGS_SESSION_SECRET=`, then return its value.
* 3. If `config/${NODE_ENV}.json` exists and the property `config['settings']['session']['secret']`
* does too, then return its value.
* 4. Same with `config/${NODE_ENV}.yml`.
* 5. If `config/default.json` exists and the property `config['settings']['session']['secret']`
* does too, then return its value.
* 6. Same with `config/default.yml`.
*
* If none value is found, then the method returns the default value provided as second argument
* to the function. If none was given, it returns undefined.
*
* @template T - TypeScript type of the returned value. Default is `any`.
* @param {string} key - Name of the config key using dots and camel case.
* @param {T} [defaultValue] - Default value to return if no configuration is found with that key.
* @returns {T} The configuration value.
* @memberof Config
*/
get(key, defaultValue) {
return Config.get(key, defaultValue);
}
}
Config.cache = {
dotEnv: undefined,
json: {},
yaml: {},
};
exports.Config = Config;
Config.config = null;
Config.testConfig = new Map();

@@ -1,4 +0,4 @@

export { ConfigMock } from './config-mock';
export { ConfigNotFoundError } from './config-not-found.error';
export { ConfigTypeError } from './config-type.error';
export { Config } from './config';
export { Env } from './env';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var config_mock_1 = require("./config-mock");
exports.ConfigMock = config_mock_1.ConfigMock;
exports.Env = exports.Config = exports.ConfigTypeError = exports.ConfigNotFoundError = void 0;
var config_not_found_error_1 = require("./config-not-found.error");
exports.ConfigNotFoundError = config_not_found_error_1.ConfigNotFoundError;
Object.defineProperty(exports, "ConfigNotFoundError", { enumerable: true, get: function () { return config_not_found_error_1.ConfigNotFoundError; } });
var config_type_error_1 = require("./config-type.error");
exports.ConfigTypeError = config_type_error_1.ConfigTypeError;
Object.defineProperty(exports, "ConfigTypeError", { enumerable: true, get: function () { return config_type_error_1.ConfigTypeError; } });
var config_1 = require("./config");
exports.Config = config_1.Config;
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_1.Config; } });
var env_1 = require("./env");
Object.defineProperty(exports, "Env", { enumerable: true, get: function () { return env_1.Env; } });

@@ -1,1 +0,1 @@

export declare function dotToUnderscore(str: string): string;
export declare function makeBox(title: string, content: string[]): string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function dotToUnderscore(str) {
return str
.replace(/([A-Z])/g, letter => `_${letter}`)
.replace(/\./g, '_')
.toUpperCase();
exports.makeBox = void 0;
function makeLine(str) {
const length = 58;
const spacesAfter = length - str.length;
if (spacesAfter <= 0) {
return str;
}
return '|' + str + ' '.repeat(spacesAfter) + '|\n';
}
exports.dotToUnderscore = dotToUnderscore;
function makeBox(title, content) {
return ' --------------------------------------------------------\n'
+ '| |\n'
+ makeLine(' ' + title)
+ '| |\n'
+ '| -------------------------------------------------------- |\n'
+ '| |\n'
+ content.map(line => makeLine(line)).join('')
+ '| |\n'
+ ' --------------------------------------------------------\n';
}
exports.makeBox = makeBox;
import 'reflect-metadata';
import { Class } from './class.interface';
import { ServiceManager } from './service-manager';
/**

@@ -10,6 +9,5 @@ * Create a new controller with its dependencies.

* @param {Class<Controller>} controllerClass - The controller class.
* @param {(object|ServiceManager)} [dependencies] - Either a ServiceManager or an
* object which key/values are the controller properties/instances.
* @param {object} [dependencies] - An object which key/values are the controller properties/instances.
* @returns {Controller} - The created controller.
*/
export declare function createController<Controller>(controllerClass: Class<Controller>, dependencies?: object | ServiceManager): Controller;
export declare function createController<Controller>(controllerClass: Class<Controller>, dependencies?: object): Controller;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createController = void 0;
// 3p

@@ -12,4 +13,3 @@ require("reflect-metadata");

* @param {Class<Controller>} controllerClass - The controller class.
* @param {(object|ServiceManager)} [dependencies] - Either a ServiceManager or an
* object which key/values are the controller properties/instances.
* @param {object} [dependencies] - An object which key/values are the controller properties/instances.
* @returns {Controller} - The created controller.

@@ -16,0 +16,0 @@ */

import 'reflect-metadata';
import { Context, HttpResponse } from './http';
import { OpenApiDecorator } from './openapi';
import { ServiceManager } from './service-manager';

@@ -27,6 +28,8 @@ /**

* @export
* @param {...HookFunction[]} hookFunctions - The function(s) from which the hook should be created.
* @param {HookFunction[]} hookFunction - The function from which the hook should be created.
* @returns {HookDecorator} - The hook decorator.
*/
export declare function Hook(...hookFunctions: HookFunction[]): HookDecorator;
export declare function Hook(hookFunction: HookFunction, openApiDecorators?: OpenApiDecorator[], options?: {
openapi?: boolean;
}): HookDecorator;
/**

@@ -33,0 +36,0 @@ * Get the function from which the hook was made.

@@ -9,4 +9,7 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.MergeHooks = exports.getHookFunctions = exports.getHookFunction = exports.Hook = void 0;
// 3p
require("reflect-metadata");
// FoalTS
const config_1 = require("./config");
/**

@@ -16,11 +19,19 @@ * Create a hook from one or several functions.

* @export
* @param {...HookFunction[]} hookFunctions - The function(s) from which the hook should be created.
* @param {HookFunction[]} hookFunction - The function from which the hook should be created.
* @returns {HookDecorator} - The hook decorator.
*/
function Hook(...hookFunctions) {
function Hook(hookFunction, openApiDecorators = [], options = {}) {
return (target, propertyKey) => {
var _a;
// Note that propertyKey can be undefined as it's an optional parameter in getMetadata.
const hooks = Reflect.getOwnMetadata('hooks', target, propertyKey) || [];
hooks.unshift(...hookFunctions);
hooks.unshift(hookFunction);
Reflect.defineMetadata('hooks', hooks, target, propertyKey);
// tslint:disable-next-line
if (!((_a = options.openapi) !== null && _a !== void 0 ? _a : config_1.Config.get('settings.openapi.useHooks', 'boolean', true))) {
return;
}
for (const openApiDecorator of openApiDecorators.reverse()) {
openApiDecorator(target, propertyKey);
}
};

@@ -69,8 +80,8 @@ }

function MergeHooks(...hookDecorators) {
const hookFunctions = [];
for (const hook of hookDecorators) {
hookFunctions.push(...getHookFunctions(hook));
}
return Hook(...hookFunctions);
return (target, propertyKey) => {
for (const hookDecorator of hookDecorators.reverse()) {
hookDecorator(target, propertyKey);
}
};
}
exports.MergeHooks = MergeHooks;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Context = void 0;
/**

@@ -4,0 +5,0 @@ * Class instantiated on each request. It includes:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Delete = exports.Patch = exports.Put = exports.Post = exports.Get = exports.Options = exports.Head = void 0;
// 3p

@@ -4,0 +5,0 @@ require("reflect-metadata");

@@ -0,1 +1,2 @@

import { Context } from './contexts';
/**

@@ -224,23 +225,2 @@ * Cookie options of the HttpResponse.setCookie method.

/**
* Create an HttpResponseOK whose content is the specified file. If returned in a controller,
* the server sends the file in streaming.
*
* @param {Object} options - The options used to create the HttpResponseOK.
* @param {string} options.directory - Directory where the file is located.
* @param {string} options.file - Name of the file with its extension. If a path is given,
* only the basename is kept.
* @param {boolean} [options.forceDownload=false] - Indicate if the browser should download
* the file directly without trying to display it in the window.
* @param {filename} [options.string=options.file] - Default name used by the browser when
* saving the file to the disk.
* @deprecated
* @returns {Promise<HttpResponseOK>}
*/
export declare function createHttpResponseFile(options: {
directory: string;
file: string;
forceDownload?: boolean;
filename?: string;
}): Promise<HttpResponseOK>;
/**
* Represent an HTTP response with the status 201 - CREATED.

@@ -803,2 +783,4 @@ *

readonly isHttpResponseInternalServerError = true;
readonly error?: Error;
readonly ctx?: Context;
statusCode: number;

@@ -813,2 +795,4 @@ statusMessage: string;

stream?: boolean;
error?: Error;
ctx?: Context;
});

@@ -815,0 +799,0 @@ }

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// std
const fs_1 = require("fs");
const path_1 = require("path");
const util_1 = require("util");
// 3p
const mime_1 = require("mime");
exports.isHttpResponseNotImplemented = exports.HttpResponseNotImplemented = exports.isHttpResponseInternalServerError = exports.HttpResponseInternalServerError = exports.isHttpResponseServerError = exports.HttpResponseServerError = exports.isHttpResponseTooManyRequests = exports.HttpResponseTooManyRequests = exports.isHttpResponseConflict = exports.HttpResponseConflict = exports.isHttpResponseMethodNotAllowed = exports.HttpResponseMethodNotAllowed = exports.isHttpResponseNotFound = exports.HttpResponseNotFound = exports.isHttpResponseForbidden = exports.HttpResponseForbidden = exports.isHttpResponseUnauthorized = exports.HttpResponseUnauthorized = exports.isHttpResponseBadRequest = exports.HttpResponseBadRequest = exports.isHttpResponseClientError = exports.HttpResponseClientError = exports.isHttpResponseRedirect = exports.HttpResponseRedirect = exports.isHttpResponseMovedPermanently = exports.HttpResponseMovedPermanently = exports.isHttpResponseRedirection = exports.HttpResponseRedirection = exports.isHttpResponseNoContent = exports.HttpResponseNoContent = exports.isHttpResponseCreated = exports.HttpResponseCreated = exports.isHttpResponseOK = exports.HttpResponseOK = exports.isHttpResponseSuccess = exports.HttpResponseSuccess = exports.isHttpResponse = exports.HttpResponse = void 0;
/**

@@ -227,40 +222,2 @@ * Represent an HTTP response. This class must be extended.

/**
* Create an HttpResponseOK whose content is the specified file. If returned in a controller,
* the server sends the file in streaming.
*
* @param {Object} options - The options used to create the HttpResponseOK.
* @param {string} options.directory - Directory where the file is located.
* @param {string} options.file - Name of the file with its extension. If a path is given,
* only the basename is kept.
* @param {boolean} [options.forceDownload=false] - Indicate if the browser should download
* the file directly without trying to display it in the window.
* @param {filename} [options.string=options.file] - Default name used by the browser when
* saving the file to the disk.
* @deprecated
* @returns {Promise<HttpResponseOK>}
*/
async function createHttpResponseFile(options) {
const file = path_1.basename(options.file);
const filePath = path_1.join(options.directory, file);
if (!await new Promise(resolve => fs_1.exists(filePath, resolve))) {
throw new Error(`The file "${filePath}" does not exist.`);
}
const stats = await util_1.promisify(fs_1.stat)(filePath);
if (stats.isDirectory()) {
throw new Error(`The directory "${filePath}" is not a file.`);
}
const stream = fs_1.createReadStream(filePath);
const response = new HttpResponseOK(stream, { stream: true });
const mimeType = mime_1.getType(options.file);
if (mimeType) {
response.setHeader('Content-Type', mimeType);
}
response
.setHeader('Content-Length', stats.size.toString())
.setHeader('Content-Disposition', (options.forceDownload ? 'attachment' : 'inline')
+ `; filename="${options.filename || file}"`);
return response;
}
exports.createHttpResponseFile = createHttpResponseFile;
/**
* Represent an HTTP response with the status 201 - CREATED.

@@ -910,2 +867,4 @@ *

this.statusMessage = 'INTERNAL SERVER ERROR';
this.error = options.error;
this.ctx = options.ctx;
}

@@ -912,0 +871,0 @@ }

"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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 });
__export(require("./contexts"));
__export(require("./http-methods"));
__export(require("./http-responses"));
__exportStar(require("./contexts"), exports);
__exportStar(require("./http-methods"), exports);
__exportStar(require("./http-responses"), exports);

@@ -0,4 +1,6 @@

export * from './app.controller.interface';
export * from './class.interface';
export { createController } from './controllers';
export * from './http';
export * from './openapi';
export * from './hooks';

@@ -5,0 +7,0 @@ export * from './routes';

"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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.ServiceManager = exports.Dependency = exports.dependency = exports.createService = exports.createController = void 0;
__exportStar(require("./app.controller.interface"), exports);
__exportStar(require("./class.interface"), exports);
var controllers_1 = require("./controllers");
exports.createController = controllers_1.createController;
__export(require("./http"));
__export(require("./hooks"));
__export(require("./routes"));
__export(require("./config"));
Object.defineProperty(exports, "createController", { enumerable: true, get: function () { return controllers_1.createController; } });
__exportStar(require("./http"), exports);
__exportStar(require("./openapi"), exports);
__exportStar(require("./hooks"), exports);
__exportStar(require("./routes"), exports);
__exportStar(require("./config"), exports);
var service_manager_1 = require("./service-manager");
exports.createService = service_manager_1.createService;
exports.dependency = service_manager_1.dependency;
exports.Dependency = service_manager_1.Dependency;
exports.ServiceManager = service_manager_1.ServiceManager;
Object.defineProperty(exports, "createService", { enumerable: true, get: function () { return service_manager_1.createService; } });
Object.defineProperty(exports, "dependency", { enumerable: true, get: function () { return service_manager_1.dependency; } });
Object.defineProperty(exports, "Dependency", { enumerable: true, get: function () { return service_manager_1.Dependency; } });
Object.defineProperty(exports, "ServiceManager", { enumerable: true, get: function () { return service_manager_1.ServiceManager; } });

@@ -1,3 +0,3 @@

export * from './route.interface';
export * from './get-response';
export { makeControllerRoutes } from './make-controller-routes';
export { getPath, getHttpMethod } from './utils';
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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.getHttpMethod = exports.getPath = exports.makeControllerRoutes = void 0;
__exportStar(require("./get-response"), exports);
var make_controller_routes_1 = require("./make-controller-routes");
exports.makeControllerRoutes = make_controller_routes_1.makeControllerRoutes;
Object.defineProperty(exports, "makeControllerRoutes", { enumerable: true, get: function () { return make_controller_routes_1.makeControllerRoutes; } });
var utils_1 = require("./utils");
exports.getPath = utils_1.getPath;
exports.getHttpMethod = utils_1.getHttpMethod;
Object.defineProperty(exports, "getPath", { enumerable: true, get: function () { return utils_1.getPath; } });
Object.defineProperty(exports, "getHttpMethod", { enumerable: true, get: function () { return utils_1.getHttpMethod; } });
import { Class } from '../class.interface';
import { HookFunction } from '../hooks';
import { IApiComponents, IApiOperation, IApiTag } from '../openapi';
import { ServiceManager } from '../service-manager';

@@ -23,2 +23,7 @@ import { Route } from './route.interface';

*/
export declare function makeControllerRoutes(parentPath: string, parentHooks: HookFunction[], controllerClass: Class, services: ServiceManager): Route[];
export declare function makeControllerRoutes(controllerClass: Class, services: ServiceManager, openapi?: boolean, documentControllers?: object[]): Generator<{
route: Route;
components: IApiComponents;
operation: IApiOperation;
tags?: IApiTag[];
}>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeControllerRoutes = exports.getMethods = void 0;
const openapi_1 = require("../openapi");
const utils_1 = require("./utils");

@@ -17,2 +19,29 @@ /**

exports.getMethods = getMethods;
function normalizePath(path) {
return (path.startsWith('/') ? path : `/${path}`)
.replace(/\:\w*/g, $1 => `{${$1.slice(1)}}`);
}
function throwErrorIfDuplicatePaths(paths) {
const originalPaths = [];
const convertedPaths = [];
for (const path in paths) {
const convertedPath = path.replace(/{.*}/g, () => '#');
const index = convertedPaths.indexOf(convertedPath);
if (index !== -1) {
throw new Error('[OpenAPI] Templated paths with the same hierarchy but different templated names'
+ ' MUST NOT exist as they are identical.'
+ `\n Path 1: ${originalPaths[index]}`
+ `\n Path 2: ${path}`);
}
originalPaths.push(path);
convertedPaths.push(convertedPath);
}
}
function getPath(controllerClass, propertyKey) {
return utils_1.getMetadata('path', controllerClass, propertyKey) || '';
}
function getHooks(controllerClass, controller, propertyKey) {
return (utils_1.getMetadata('hooks', controllerClass, propertyKey) || [])
.map(hook => hook.bind(controller));
}
/**

@@ -29,28 +58,102 @@ * Recursively create the routes of a controller and its subcontrollers from the

*/
function makeControllerRoutes(parentPath, parentHooks, controllerClass, services) {
const routes = [];
const controllerHooks = utils_1.getMetadata('hooks', controllerClass) || [];
const controllerPath = utils_1.getMetadata('path', controllerClass);
function* makeControllerRoutes(controllerClass, services, openapi = false, documentControllers) {
// FoalTS stores as well the controllers in the service manager.
const controller = services.get(controllerClass);
const leftPath = utils_1.join(parentPath, controllerPath);
const leftHooks = parentHooks.concat(controllerHooks.map(hook => hook.bind(controller)));
const controllerPath = getPath(controllerClass);
const controllerHooks = getHooks(controllerClass, controller);
/* OpenAPI */
const info = openapi_1.getApiInfo(controllerClass);
// Check if the controller is inside an OpenAPI api. If not, components, operations and tags are discarded.
openapi = !!info || openapi;
/* OpenAPI */
const controllerComponents = openapi ? openapi_1.getApiComponents(controllerClass, controller) : {};
const controllerOperation = openapi ? openapi_1.getApiCompleteOperation(controllerClass, controller) : { responses: {} };
const controllerTags = openapi ? openapi_1.getApiTags(controllerClass) : undefined;
if (openapi) {
delete controllerOperation.servers;
delete controllerOperation.externalDocs;
delete controllerOperation.security;
}
/* OpenAPI */
const openApi = services.get(openapi_1.OpenApi);
let document;
/* OpenAPI */
if (info) {
document = {
info: typeof info === 'function' ? info(controller) : info,
openapi: '3.0.0',
paths: {}
};
const operation = openapi_1.getApiCompleteOperation(controllerClass, controller);
if (operation.servers) {
document.servers = operation.servers;
}
if (operation.security) {
document.security = operation.security;
}
if (operation.externalDocs) {
document.externalDocs = operation.externalDocs;
}
document.components = controllerComponents;
document.tags = controllerTags;
}
documentControllers = document ? [] : documentControllers;
if (documentControllers) {
documentControllers.push(controller);
}
function processRoute(route, components, operation, tags) {
/* OpenAPI */
if (document) {
const normalizedPath = normalizePath(route.path);
document.paths[normalizedPath] = Object.assign(Object.assign({}, document.paths[normalizedPath]), { [route.httpMethod.toLowerCase()]: openapi_1.mergeOperations(controllerOperation, operation) });
document.tags = Array.from(new Set(openapi_1.mergeTags(document.tags, tags)));
document.components = openapi_1.mergeComponents(document.components || {}, components);
}
return {
// OpenAPI
components: openapi ? openapi_1.mergeComponents(controllerComponents, components) : {},
// OpenAPI
operation: openapi ? openapi_1.mergeOperations(controllerOperation, operation) : { responses: {} },
route: {
controller: route.controller,
hooks: controllerHooks.concat(route.hooks),
httpMethod: route.httpMethod,
path: utils_1.join(controllerPath, route.path),
propertyKey: route.propertyKey,
},
// OpenAPI
tags: openapi ? openapi_1.mergeTags(controllerTags, tags) : undefined
};
}
for (const controllerClass of controller.subControllers || []) {
routes.push(...makeControllerRoutes(leftPath, leftHooks, controllerClass, services));
for (const { route, components, operation, tags } of makeControllerRoutes(controllerClass, services, openapi, documentControllers)) {
yield processRoute(route, components, operation, tags);
}
}
getMethods(controllerClass.prototype).forEach(propertyKey => {
if (propertyKey === 'constructor') {
return;
}
for (const propertyKey of getMethods(controllerClass.prototype)) {
const httpMethod = utils_1.getMetadata('httpMethod', controllerClass, propertyKey);
if (httpMethod) {
const methodPath = utils_1.getMetadata('path', controllerClass, propertyKey);
const methodHooks = utils_1.getMetadata('hooks', controllerClass, propertyKey) || [];
const path = utils_1.join(leftPath, methodPath);
const hooks = [...leftHooks, ...methodHooks.map(hook => hook.bind(controller))];
routes.push({ controller, hooks, httpMethod, path, propertyKey });
if (!httpMethod) {
continue;
}
});
return routes;
const path = getPath(controllerClass, propertyKey);
const hooks = getHooks(controllerClass, controller, propertyKey);
const route = { controller, hooks, httpMethod, path, propertyKey };
/* OpenAPI */
const components = openapi ? openapi_1.getApiComponents(controllerClass, controller, propertyKey) : {};
const operation = openapi ? openapi_1.getApiCompleteOperation(controllerClass, controller, propertyKey) : { responses: {} };
const tags = openapi ? openapi_1.getApiTags(controllerClass, propertyKey) : undefined;
yield processRoute(route, components, operation, tags);
}
/* OpenAPI */
if (document) {
if (document.components && Object.keys(document.components).length === 0) {
delete document.components;
}
if (document.tags && Object.keys(document.tags).length === 0) {
delete document.tags;
}
throwErrorIfDuplicatePaths(document.paths);
openApi.addDocument(controllerClass, document, documentControllers);
}
}
exports.makeControllerRoutes = makeControllerRoutes;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.join = exports.getPath = exports.getHttpMethod = exports.getMetadata = void 0;
// 3p

@@ -4,0 +5,0 @@ require("reflect-metadata");

@@ -5,3 +5,3 @@ import 'reflect-metadata';

propertyKey: string;
serviceClass: string | Class;
serviceClassOrID: string | Class;
}

@@ -26,8 +26,7 @@ /**

* @param {ClassOrAbstractClass<Service>} serviceClass - The service class.
* @param {(object|ServiceManager)} [dependencies] - Either a ServiceManager or an
* object which key/values are the service properties/instances.
* @param {object} [dependencies] - An object which key/values are the service properties/instances.
* @returns {Service} - The created service.
*/
export declare function createService<Service>(serviceClass: ClassOrAbstractClass<Service>, dependencies?: object | ServiceManager): Service;
export declare function createControllerOrService<T>(serviceClass: ClassOrAbstractClass<T>, dependencies?: object | ServiceManager): T;
export declare function createService<Service>(serviceClass: ClassOrAbstractClass<Service>, dependencies?: object): Service;
export declare function createControllerOrService<T>(serviceClass: ClassOrAbstractClass<T>, dependencies?: object): T;
/**

@@ -34,0 +33,0 @@ * Identity Mapper that instantiates and returns service singletons.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceManager = exports.createControllerOrService = exports.createService = exports.dependency = exports.Dependency = void 0;
// std

@@ -16,3 +17,3 @@ const path_1 = require("path");

const dependencies = [...(Reflect.getMetadata('dependencies', target) || [])];
dependencies.push({ propertyKey, serviceClass: id });
dependencies.push({ propertyKey, serviceClassOrID: id });
Reflect.defineMetadata('dependencies', dependencies, target);

@@ -30,3 +31,3 @@ };

const dependencies = [...(Reflect.getMetadata('dependencies', target) || [])];
dependencies.push({ propertyKey, serviceClass });
dependencies.push({ propertyKey, serviceClassOrID: serviceClass });
Reflect.defineMetadata('dependencies', dependencies, target);

@@ -41,4 +42,3 @@ }

* @param {ClassOrAbstractClass<Service>} serviceClass - The service class.
* @param {(object|ServiceManager)} [dependencies] - Either a ServiceManager or an
* object which key/values are the service properties/instances.
* @param {object} [dependencies] - An object which key/values are the service properties/instances.
* @returns {Service} - The created service.

@@ -52,11 +52,8 @@ */

const metadata = Reflect.getMetadata('dependencies', serviceClass.prototype) || [];
let serviceManager = new ServiceManager();
if (dependencies instanceof ServiceManager) {
serviceManager = dependencies;
}
else if (typeof dependencies === 'object') {
const serviceManager = new ServiceManager();
if (dependencies) {
metadata.forEach(dep => {
const serviceMock = dependencies[dep.propertyKey];
if (serviceMock) {
serviceManager.set(dep.serviceClass, serviceMock);
serviceManager.set(dep.serviceClassOrID, serviceMock);
}

@@ -144,3 +141,3 @@ });

for (const dependency of dependencies) {
service[dependency.propertyKey] = this.get(dependency.serviceClass);
service[dependency.propertyKey] = this.get(dependency.serviceClassOrID);
}

@@ -165,3 +162,3 @@ // Save the service.

if (cls.hasOwnProperty('defaultConcreteClassPath')) {
concreteClassPath = config_1.Config.get2(concreteClassConfigPath, 'string', 'local');
concreteClassPath = config_1.Config.get(concreteClassConfigPath, 'string', 'local');
}

@@ -168,0 +165,0 @@ else {

@@ -1,3 +0,3 @@

import { Class, ServiceManager } from '../core';
export declare type ExpressApplication = any;
import { Class, IAppController, ServiceManager } from '../core';
export declare const OPENAPI_SERVICE_ID = "OPENAPI_SERVICE_ID_a5NWKbBNBxVVZ";
declare type Middleware = (req: any, res: any, next: (err?: any) => any) => any;

@@ -7,5 +7,2 @@ declare type ErrorMiddleware = (err: any, req: any, res: any, next: (err?: any) => any) => any;

expressInstance?: any;
methods?: {
handleError?: boolean;
};
serviceManager?: ServiceManager;

@@ -19,38 +16,18 @@ preMiddlewares?: (Middleware | ErrorMiddleware)[];

* @export
* @param {Class} AppController - The root controller, usually called `AppController` and located in `src/app`.
* @param {(any|CreateAppOptions)} [expressInstanceOrOptions] - Express instance or options containaining
* Express middlewares or other settings.
* @param {any} [expressInstanceOrOptions.expressInstance] - Express instance to be used as base for the
* @param {Class<IAppController>} AppController - The root controller, usually called `AppController`
* and located in `src/app`.
* @param {CreateAppOptions} [options] - Options containaining Express middlewares or other settings.
* @param {any} [options.expressInstance] - Express instance to be used as base for the
* returned application.
* @param {boolean} [expressInstanceOrOptions.methods.handleError] - Specifies if AppController.handleError should be
* @param {boolean} [options.methods.handleError] - Specifies if AppController.handleError should be
* used to handle errors.
* @param {ServiceManager} [expressInstanceOrOptions.serviceManager] - Prebuilt and configured Service Manager for
* @param {ServiceManager} [options.serviceManager] - Prebuilt and configured Service Manager for
* optionally overriding the mapped identities.
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express
* @param {(RequestHandler | ErrorRequestHandler)[]} [options.preMiddlewares] Express
* middlewares to be executed before the controllers and hooks.
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express
* @param {(RequestHandler | ErrorRequestHandler)[]} [options.postMiddlewares] Express
* middlewares to be executed after the controllers and hooks, but before the 500 or 404 handler get called.
* @returns {any} The express application.
*/
export declare function createApp(AppController: Class, expressInstanceOrOptions?: any | CreateAppOptions): any;
/**
* Create an Express application from the root controller and call its "init" method if it exists.
*
* @export
* @param {Class} AppController - The root controller, usually called `AppController` and located in `src/app`.
* @param {(any|CreateAppOptions)} [expressInstanceOrOptions] - Express instance or options containaining
* Express middlewares or other settings.
* @param {any} [expressInstanceOrOptions.expressInstance] - Express instance to be used as base for the
* returned application.
* @param {boolean} [expressInstanceOrOptions.methods.handleError] - Specifies if AppController.handleError should be
* used to handle errors.
* @param {ServiceManager} [expressInstanceOrOptions.serviceManager] - Prebuilt and configured Service Manager for
* optionally overriding the mapped identities.
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express
* middlewares to be executed before the controllers and hooks.
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express
* middlewares to be executed after the controllers and hooks, but before the 500 or 404 handler get called.
* @returns {Promise<any>} The express application.
*/
export declare function createAndInitApp(AppController: Class, expressInstanceOrOptions?: any | CreateAppOptions): Promise<any>;
export declare function createApp(AppController: Class<IAppController>, options?: CreateAppOptions): Promise<any>;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createApp = exports.OPENAPI_SERVICE_ID = void 0;
// 3p

@@ -9,5 +10,4 @@ const cookieParser = require("cookie-parser");

const core_1 = require("../core");
const create_middleware_1 = require("./create-middleware");
const handle_errors_1 = require("./handle-errors");
const not_found_1 = require("./not-found");
const send_response_1 = require("./send-response");
exports.OPENAPI_SERVICE_ID = 'OPENAPI_SERVICE_ID_a5NWKbBNBxVVZ';
function handleJsonErrors(err, req, res, next) {

@@ -26,4 +26,2 @@ if (err.type !== 'entity.parse.failed') {

res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-DNS-Prefetch-Control', 'off');
res.setHeader('X-Download-Options', 'noopen');
res.setHeader('X-Frame-Options', 'SAMEORIGIN');

@@ -34,11 +32,2 @@ res.setHeader('X-XSS-Protection', '1; mode=block');

}
function getOptions(expressInstanceOrOptions) {
if (!expressInstanceOrOptions) {
return {};
}
if (typeof expressInstanceOrOptions === 'function') {
return { expressInstance: expressInstanceOrOptions };
}
return expressInstanceOrOptions;
}
/**

@@ -48,19 +37,18 @@ * Create an Express application from the root controller.

* @export
* @param {Class} AppController - The root controller, usually called `AppController` and located in `src/app`.
* @param {(any|CreateAppOptions)} [expressInstanceOrOptions] - Express instance or options containaining
* Express middlewares or other settings.
* @param {any} [expressInstanceOrOptions.expressInstance] - Express instance to be used as base for the
* @param {Class<IAppController>} AppController - The root controller, usually called `AppController`
* and located in `src/app`.
* @param {CreateAppOptions} [options] - Options containaining Express middlewares or other settings.
* @param {any} [options.expressInstance] - Express instance to be used as base for the
* returned application.
* @param {boolean} [expressInstanceOrOptions.methods.handleError] - Specifies if AppController.handleError should be
* @param {boolean} [options.methods.handleError] - Specifies if AppController.handleError should be
* used to handle errors.
* @param {ServiceManager} [expressInstanceOrOptions.serviceManager] - Prebuilt and configured Service Manager for
* @param {ServiceManager} [options.serviceManager] - Prebuilt and configured Service Manager for
* optionally overriding the mapped identities.
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express
* @param {(RequestHandler | ErrorRequestHandler)[]} [options.preMiddlewares] Express
* middlewares to be executed before the controllers and hooks.
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express
* @param {(RequestHandler | ErrorRequestHandler)[]} [options.postMiddlewares] Express
* middlewares to be executed after the controllers and hooks, but before the 500 or 404 handler get called.
* @returns {any} The express application.
* @returns {Promise<any>} The express application.
*/
function createApp(AppController, expressInstanceOrOptions) {
const options = getOptions(expressInstanceOrOptions);
async function createApp(AppController, options = {}) {
const app = options.expressInstance || express();

@@ -72,3 +60,3 @@ // Add optional pre-middlewares.

// Log requests.
const loggerFormat = core_1.Config.get2('settings.loggerFormat', 'string', '[:date] ":method :url HTTP/:http-version" :status - :response-time ms');
const loggerFormat = core_1.Config.get('settings.loggerFormat', 'string', '[:date] ":method :url HTTP/:http-version" :status - :response-time ms');
if (loggerFormat !== 'none') {

@@ -79,5 +67,5 @@ app.use(logger(loggerFormat));

// Serve static files.
app.use(core_1.Config.get2('settings.staticPathPrefix', 'string', ''), express.static(core_1.Config.get2('settings.staticPath', 'string', 'public')));
app.use(core_1.Config.get('settings.staticPathPrefix', 'string', ''), express.static(core_1.Config.get('settings.staticPath', 'string', 'public')));
// Parse request body.
const limit = core_1.Config.get2('settings.bodyParser.limit', 'number|string');
const limit = core_1.Config.get('settings.bodyParser.limit', 'number|string');
app.use(express.json({ limit }));

@@ -92,6 +80,25 @@ app.use(handleJsonErrors);

app.foal = { services };
// Inject the OpenAPI service with an ID string to avoid duplicated singletons
// across several npm packages.
services.set(exports.OPENAPI_SERVICE_ID, services.get(core_1.OpenApi));
// Retrieve the AppController instance.
const appController = services.get(AppController);
// Resolve the controllers and hooks and add them to the express instance.
const routes = core_1.makeControllerRoutes('', [], AppController, services);
for (const route of routes) {
app[route.httpMethod.toLowerCase()](route.path, create_middleware_1.createMiddleware(route, services));
const routes = core_1.makeControllerRoutes(AppController, services);
for (const { route } of routes) {
app[route.httpMethod.toLowerCase()](route.path, async (req, res, next) => {
try {
const ctx = new core_1.Context(req);
// TODO: better test this line.
const response = await core_1.getResponse(route, ctx, services, appController);
send_response_1.sendResponse(response, res);
}
catch (error) {
// This try/catch will never be called: the `getResponse` function catches any errors
// thrown or rejected in the application and converts it into a response.
// However, for more security, this line has been added to avoid crashing the server
// in case the function is badly implemented.
next(error);
}
});
}

@@ -102,36 +109,8 @@ // Add optional post-middlewares.

}
// Handle errors.
app.use(not_found_1.notFound());
const controller = app.foal.services.get(AppController);
app.use(handle_errors_1.handleErrors(options, controller));
await services.boot();
if (appController.init) {
await appController.init();
}
return app;
}
exports.createApp = createApp;
/**
* Create an Express application from the root controller and call its "init" method if it exists.
*
* @export
* @param {Class} AppController - The root controller, usually called `AppController` and located in `src/app`.
* @param {(any|CreateAppOptions)} [expressInstanceOrOptions] - Express instance or options containaining
* Express middlewares or other settings.
* @param {any} [expressInstanceOrOptions.expressInstance] - Express instance to be used as base for the
* returned application.
* @param {boolean} [expressInstanceOrOptions.methods.handleError] - Specifies if AppController.handleError should be
* used to handle errors.
* @param {ServiceManager} [expressInstanceOrOptions.serviceManager] - Prebuilt and configured Service Manager for
* optionally overriding the mapped identities.
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.preMiddlewares] Express
* middlewares to be executed before the controllers and hooks.
* @param {(RequestHandler | ErrorRequestHandler)[]} [expressInstanceOrOptions.postMiddlewares] Express
* middlewares to be executed after the controllers and hooks, but before the 500 or 404 handler get called.
* @returns {Promise<any>} The express application.
*/
async function createAndInitApp(AppController, expressInstanceOrOptions) {
const app = createApp(AppController, expressInstanceOrOptions);
const controller = app.foal.services.get(AppController);
if (controller.init) {
await controller.init();
}
return app;
}
exports.createAndInitApp = createAndInitApp;

@@ -1,1 +0,1 @@

export { createApp, createAndInitApp, ExpressApplication } from './create-app';
export { createApp, OPENAPI_SERVICE_ID } from './create-app';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OPENAPI_SERVICE_ID = exports.createApp = void 0;
var create_app_1 = require("./create-app");
exports.createApp = create_app_1.createApp;
exports.createAndInitApp = create_app_1.createAndInitApp;
Object.defineProperty(exports, "createApp", { enumerable: true, get: function () { return create_app_1.createApp; } });
Object.defineProperty(exports, "OPENAPI_SERVICE_ID", { enumerable: true, get: function () { return create_app_1.OPENAPI_SERVICE_ID; } });
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// 3p
const pump = require("pump");
exports.sendResponse = void 0;
// std
const stream_1 = require("stream");
// FoalTS

@@ -35,3 +36,7 @@ const core_1 = require("../core");

if (response.stream === true) {
pump(response.body, res);
stream_1.pipeline(response.body, res, err => {
if (err) {
console.log(err);
}
});
return;

@@ -38,0 +43,0 @@ }

@@ -6,6 +6,5 @@ /**

*/
export * from './common';
export * from './core';
export * from './express';
export * from './openapi';
export * from './sessions';
export { Log, LogOptions, UserRequired, ValidateBody, ValidateCookie, ValidateHeader, ValidatePathParam, ValidateQueryParam, controller, convertBase64ToBase64url, escape, escapeProp, generateSignedToken, generateToken, getAjvInstance, hashPassword, isInFile, render, renderError, signToken, verifyPassword, verifySignedToken, } from './common';
export { ApiCallback, ApiDefineCallback, ApiDefineExample, ApiDefineHeader, ApiDefineLink, ApiDefineParameter, ApiDefineRequestBody, ApiDefineResponse, ApiDefineSchema, ApiDefineSecurityScheme, ApiDefineTag, ApiDeprecated, ApiExternalDoc, ApiInfo, ApiOperation, ApiOperationDescription, ApiOperationId, ApiOperationSummary, ApiParameter, ApiRequestBody, ApiResponse, ApiSecurityRequirement, ApiServer, ApiUseTag, Class, ClassOrAbstractClass, Config, ConfigNotFoundError, ConfigTypeError, Context, CookieOptions, Delete, Dependency, Env, Get, Head, Hook, HookDecorator, HookFunction, HookPostFunction, HttpMethod, HttpResponse, HttpResponseBadRequest, HttpResponseClientError, HttpResponseConflict, HttpResponseCreated, HttpResponseForbidden, HttpResponseInternalServerError, HttpResponseMethodNotAllowed, HttpResponseMovedPermanently, HttpResponseNoContent, HttpResponseNotFound, HttpResponseNotImplemented, HttpResponseOK, HttpResponseRedirect, HttpResponseRedirection, HttpResponseServerError, HttpResponseSuccess, HttpResponseTooManyRequests, HttpResponseUnauthorized, IApiAbstractParameter, IApiAbstractSecurityScheme, IApiApiKeySecurityScheme, IApiAuthorizationCodeOAuthFlow, IApiCallback, IApiClientCredentialsOAuthFlow, IApiComponents, IApiContact, IApiCookieParameter, IApiDiscriminator, IApiEncoding, IApiExample, IApiExternalDocumentation, IApiHeader, IApiHeaderParameter, IApiHttpSecurityScheme, IApiImplicitOAuthFlow, IApiInfo, IApiLicense, IApiLink, IApiMediaType, IApiOAuth2SecurityScheme, IApiOAuthFlow, IApiOAuthFlows, IApiOpenIdConnectSecurityScheme, IApiOperation, IApiParameter, IApiPasswordOAuthFlow, IApiPathItem, IApiPathParameter, IApiPaths, IApiQueryParameter, IApiReference, IApiRequestBody, IApiResponse, IApiResponses, IApiSchema, IApiSecurityRequirement, IApiSecurityScheme, IApiServer, IApiServerVariable, IApiTag, IApiXML, IAppController, IController, IOpenAPI, MergeHooks, OpenApi, OpenApiDecorator, Options, Patch, Post, Put, ServiceManager, createController, createOpenApiDocument, createService, dependency, getApiCallbacks, getApiCompleteOperation, getApiComponents, getApiDeprecated, getApiExternalDocs, getApiInfo, getApiOperation, getApiOperationDescription, getApiOperationId, getApiOperationSummary, getApiParameters, getApiRequestBody, getApiResponses, getApiSecurity, getApiServers, getApiTags, getApiUsedTags, getHookFunction, getHookFunctions, getHttpMethod, getPath, isHttpResponse, isHttpResponseBadRequest, isHttpResponseClientError, isHttpResponseConflict, isHttpResponseCreated, isHttpResponseForbidden, isHttpResponseInternalServerError, isHttpResponseMethodNotAllowed, isHttpResponseMovedPermanently, isHttpResponseNoContent, isHttpResponseNotFound, isHttpResponseNotImplemented, isHttpResponseOK, isHttpResponseRedirect, isHttpResponseRedirection, isHttpResponseServerError, isHttpResponseSuccess, isHttpResponseTooManyRequests, isHttpResponseUnauthorized, } from './core';
export { OPENAPI_SERVICE_ID, createApp, } from './express';
export { Session, SessionAlreadyExists, SessionState, SessionStore, Store, UseSessions, createSession, readSession, } from './sessions';

@@ -7,10 +7,149 @@ "use strict";

*/
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
Object.defineProperty(exports, "__esModule", { value: true });
exports.readSession = exports.createSession = exports.UseSessions = exports.Store = exports.SessionStore = exports.SessionAlreadyExists = exports.Session = exports.createApp = exports.OPENAPI_SERVICE_ID = exports.isHttpResponseUnauthorized = exports.isHttpResponseTooManyRequests = exports.isHttpResponseSuccess = exports.isHttpResponseServerError = exports.isHttpResponseRedirection = exports.isHttpResponseRedirect = exports.isHttpResponseOK = exports.isHttpResponseNotImplemented = exports.isHttpResponseNotFound = exports.isHttpResponseNoContent = exports.isHttpResponseMovedPermanently = exports.isHttpResponseMethodNotAllowed = exports.isHttpResponseInternalServerError = exports.isHttpResponseForbidden = exports.isHttpResponseCreated = exports.isHttpResponseConflict = exports.isHttpResponseClientError = exports.isHttpResponseBadRequest = exports.isHttpResponse = exports.getPath = exports.getHttpMethod = exports.getHookFunctions = exports.getHookFunction = exports.getApiUsedTags = exports.getApiTags = exports.getApiServers = exports.getApiSecurity = exports.getApiResponses = exports.getApiRequestBody = exports.getApiParameters = exports.getApiOperationSummary = exports.getApiOperationId = exports.getApiOperationDescription = exports.getApiOperation = exports.getApiInfo = exports.getApiExternalDocs = exports.getApiDeprecated = exports.getApiComponents = exports.getApiCompleteOperation = exports.getApiCallbacks = exports.dependency = exports.createService = exports.createOpenApiDocument = exports.createController = exports.ServiceManager = exports.Put = exports.Post = exports.Patch = exports.Options = exports.OpenApi = exports.MergeHooks = exports.HttpResponseUnauthorized = exports.HttpResponseTooManyRequests = exports.HttpResponseSuccess = exports.HttpResponseServerError = exports.HttpResponseRedirection = exports.HttpResponseRedirect = exports.HttpResponseOK = exports.HttpResponseNotImplemented = exports.HttpResponseNotFound = exports.HttpResponseNoContent = exports.HttpResponseMovedPermanently = exports.HttpResponseMethodNotAllowed = exports.HttpResponseInternalServerError = exports.HttpResponseForbidden = exports.HttpResponseCreated = exports.HttpResponseConflict = exports.HttpResponseClientError = exports.HttpResponseBadRequest = exports.HttpResponse = exports.Hook = exports.Head = exports.Get = exports.Env = exports.Dependency = exports.Delete = exports.Context = exports.ConfigTypeError = exports.ConfigNotFoundError = exports.Config = exports.ApiUseTag = exports.ApiServer = exports.ApiSecurityRequirement = exports.ApiResponse = exports.ApiRequestBody = exports.ApiParameter = exports.ApiOperationSummary = exports.ApiOperationId = exports.ApiOperationDescription = exports.ApiOperation = exports.ApiInfo = exports.ApiExternalDoc = exports.ApiDeprecated = exports.ApiDefineTag = exports.ApiDefineSecurityScheme = exports.ApiDefineSchema = exports.ApiDefineResponse = exports.ApiDefineRequestBody = exports.ApiDefineParameter = exports.ApiDefineLink = exports.ApiDefineHeader = exports.ApiDefineExample = exports.ApiDefineCallback = exports.ApiCallback = exports.verifySignedToken = exports.verifyPassword = exports.signToken = exports.renderError = exports.render = exports.isInFile = exports.hashPassword = exports.getAjvInstance = exports.generateToken = exports.generateSignedToken = exports.escapeProp = exports.escape = exports.convertBase64ToBase64url = exports.controller = exports.ValidateQueryParam = exports.ValidatePathParam = exports.ValidateHeader = exports.ValidateCookie = exports.ValidateBody = exports.UserRequired = exports.Log = void 0;
try {
const version = process.versions.node;
const NODE_MAJOR_VERSION = parseInt(version.split('.')[0], 10);
if (NODE_MAJOR_VERSION < 10) {
console.warn(`[Warning] You are using version ${version} of Node. FoalTS requires at least version 10.`);
}
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./common"));
__export(require("./core"));
__export(require("./express"));
__export(require("./openapi"));
__export(require("./sessions"));
finally { }
var common_1 = require("./common");
Object.defineProperty(exports, "Log", { enumerable: true, get: function () { return common_1.Log; } });
Object.defineProperty(exports, "UserRequired", { enumerable: true, get: function () { return common_1.UserRequired; } });
Object.defineProperty(exports, "ValidateBody", { enumerable: true, get: function () { return common_1.ValidateBody; } });
Object.defineProperty(exports, "ValidateCookie", { enumerable: true, get: function () { return common_1.ValidateCookie; } });
Object.defineProperty(exports, "ValidateHeader", { enumerable: true, get: function () { return common_1.ValidateHeader; } });
Object.defineProperty(exports, "ValidatePathParam", { enumerable: true, get: function () { return common_1.ValidatePathParam; } });
Object.defineProperty(exports, "ValidateQueryParam", { enumerable: true, get: function () { return common_1.ValidateQueryParam; } });
Object.defineProperty(exports, "controller", { enumerable: true, get: function () { return common_1.controller; } });
Object.defineProperty(exports, "convertBase64ToBase64url", { enumerable: true, get: function () { return common_1.convertBase64ToBase64url; } });
Object.defineProperty(exports, "escape", { enumerable: true, get: function () { return common_1.escape; } });
Object.defineProperty(exports, "escapeProp", { enumerable: true, get: function () { return common_1.escapeProp; } });
Object.defineProperty(exports, "generateSignedToken", { enumerable: true, get: function () { return common_1.generateSignedToken; } });
Object.defineProperty(exports, "generateToken", { enumerable: true, get: function () { return common_1.generateToken; } });
Object.defineProperty(exports, "getAjvInstance", { enumerable: true, get: function () { return common_1.getAjvInstance; } });
Object.defineProperty(exports, "hashPassword", { enumerable: true, get: function () { return common_1.hashPassword; } });
Object.defineProperty(exports, "isInFile", { enumerable: true, get: function () { return common_1.isInFile; } });
Object.defineProperty(exports, "render", { enumerable: true, get: function () { return common_1.render; } });
Object.defineProperty(exports, "renderError", { enumerable: true, get: function () { return common_1.renderError; } });
Object.defineProperty(exports, "signToken", { enumerable: true, get: function () { return common_1.signToken; } });
Object.defineProperty(exports, "verifyPassword", { enumerable: true, get: function () { return common_1.verifyPassword; } });
Object.defineProperty(exports, "verifySignedToken", { enumerable: true, get: function () { return common_1.verifySignedToken; } });
var core_1 = require("./core");
Object.defineProperty(exports, "ApiCallback", { enumerable: true, get: function () { return core_1.ApiCallback; } });
Object.defineProperty(exports, "ApiDefineCallback", { enumerable: true, get: function () { return core_1.ApiDefineCallback; } });
Object.defineProperty(exports, "ApiDefineExample", { enumerable: true, get: function () { return core_1.ApiDefineExample; } });
Object.defineProperty(exports, "ApiDefineHeader", { enumerable: true, get: function () { return core_1.ApiDefineHeader; } });
Object.defineProperty(exports, "ApiDefineLink", { enumerable: true, get: function () { return core_1.ApiDefineLink; } });
Object.defineProperty(exports, "ApiDefineParameter", { enumerable: true, get: function () { return core_1.ApiDefineParameter; } });
Object.defineProperty(exports, "ApiDefineRequestBody", { enumerable: true, get: function () { return core_1.ApiDefineRequestBody; } });
Object.defineProperty(exports, "ApiDefineResponse", { enumerable: true, get: function () { return core_1.ApiDefineResponse; } });
Object.defineProperty(exports, "ApiDefineSchema", { enumerable: true, get: function () { return core_1.ApiDefineSchema; } });
Object.defineProperty(exports, "ApiDefineSecurityScheme", { enumerable: true, get: function () { return core_1.ApiDefineSecurityScheme; } });
Object.defineProperty(exports, "ApiDefineTag", { enumerable: true, get: function () { return core_1.ApiDefineTag; } });
Object.defineProperty(exports, "ApiDeprecated", { enumerable: true, get: function () { return core_1.ApiDeprecated; } });
Object.defineProperty(exports, "ApiExternalDoc", { enumerable: true, get: function () { return core_1.ApiExternalDoc; } });
Object.defineProperty(exports, "ApiInfo", { enumerable: true, get: function () { return core_1.ApiInfo; } });
Object.defineProperty(exports, "ApiOperation", { enumerable: true, get: function () { return core_1.ApiOperation; } });
Object.defineProperty(exports, "ApiOperationDescription", { enumerable: true, get: function () { return core_1.ApiOperationDescription; } });
Object.defineProperty(exports, "ApiOperationId", { enumerable: true, get: function () { return core_1.ApiOperationId; } });
Object.defineProperty(exports, "ApiOperationSummary", { enumerable: true, get: function () { return core_1.ApiOperationSummary; } });
Object.defineProperty(exports, "ApiParameter", { enumerable: true, get: function () { return core_1.ApiParameter; } });
Object.defineProperty(exports, "ApiRequestBody", { enumerable: true, get: function () { return core_1.ApiRequestBody; } });
Object.defineProperty(exports, "ApiResponse", { enumerable: true, get: function () { return core_1.ApiResponse; } });
Object.defineProperty(exports, "ApiSecurityRequirement", { enumerable: true, get: function () { return core_1.ApiSecurityRequirement; } });
Object.defineProperty(exports, "ApiServer", { enumerable: true, get: function () { return core_1.ApiServer; } });
Object.defineProperty(exports, "ApiUseTag", { enumerable: true, get: function () { return core_1.ApiUseTag; } });
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return core_1.Config; } });
Object.defineProperty(exports, "ConfigNotFoundError", { enumerable: true, get: function () { return core_1.ConfigNotFoundError; } });
Object.defineProperty(exports, "ConfigTypeError", { enumerable: true, get: function () { return core_1.ConfigTypeError; } });
Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return core_1.Context; } });
Object.defineProperty(exports, "Delete", { enumerable: true, get: function () { return core_1.Delete; } });
Object.defineProperty(exports, "Dependency", { enumerable: true, get: function () { return core_1.Dependency; } });
Object.defineProperty(exports, "Env", { enumerable: true, get: function () { return core_1.Env; } });
Object.defineProperty(exports, "Get", { enumerable: true, get: function () { return core_1.Get; } });
Object.defineProperty(exports, "Head", { enumerable: true, get: function () { return core_1.Head; } });
Object.defineProperty(exports, "Hook", { enumerable: true, get: function () { return core_1.Hook; } });
Object.defineProperty(exports, "HttpResponse", { enumerable: true, get: function () { return core_1.HttpResponse; } });
Object.defineProperty(exports, "HttpResponseBadRequest", { enumerable: true, get: function () { return core_1.HttpResponseBadRequest; } });
Object.defineProperty(exports, "HttpResponseClientError", { enumerable: true, get: function () { return core_1.HttpResponseClientError; } });
Object.defineProperty(exports, "HttpResponseConflict", { enumerable: true, get: function () { return core_1.HttpResponseConflict; } });
Object.defineProperty(exports, "HttpResponseCreated", { enumerable: true, get: function () { return core_1.HttpResponseCreated; } });
Object.defineProperty(exports, "HttpResponseForbidden", { enumerable: true, get: function () { return core_1.HttpResponseForbidden; } });
Object.defineProperty(exports, "HttpResponseInternalServerError", { enumerable: true, get: function () { return core_1.HttpResponseInternalServerError; } });
Object.defineProperty(exports, "HttpResponseMethodNotAllowed", { enumerable: true, get: function () { return core_1.HttpResponseMethodNotAllowed; } });
Object.defineProperty(exports, "HttpResponseMovedPermanently", { enumerable: true, get: function () { return core_1.HttpResponseMovedPermanently; } });
Object.defineProperty(exports, "HttpResponseNoContent", { enumerable: true, get: function () { return core_1.HttpResponseNoContent; } });
Object.defineProperty(exports, "HttpResponseNotFound", { enumerable: true, get: function () { return core_1.HttpResponseNotFound; } });
Object.defineProperty(exports, "HttpResponseNotImplemented", { enumerable: true, get: function () { return core_1.HttpResponseNotImplemented; } });
Object.defineProperty(exports, "HttpResponseOK", { enumerable: true, get: function () { return core_1.HttpResponseOK; } });
Object.defineProperty(exports, "HttpResponseRedirect", { enumerable: true, get: function () { return core_1.HttpResponseRedirect; } });
Object.defineProperty(exports, "HttpResponseRedirection", { enumerable: true, get: function () { return core_1.HttpResponseRedirection; } });
Object.defineProperty(exports, "HttpResponseServerError", { enumerable: true, get: function () { return core_1.HttpResponseServerError; } });
Object.defineProperty(exports, "HttpResponseSuccess", { enumerable: true, get: function () { return core_1.HttpResponseSuccess; } });
Object.defineProperty(exports, "HttpResponseTooManyRequests", { enumerable: true, get: function () { return core_1.HttpResponseTooManyRequests; } });
Object.defineProperty(exports, "HttpResponseUnauthorized", { enumerable: true, get: function () { return core_1.HttpResponseUnauthorized; } });
Object.defineProperty(exports, "MergeHooks", { enumerable: true, get: function () { return core_1.MergeHooks; } });
Object.defineProperty(exports, "OpenApi", { enumerable: true, get: function () { return core_1.OpenApi; } });
Object.defineProperty(exports, "Options", { enumerable: true, get: function () { return core_1.Options; } });
Object.defineProperty(exports, "Patch", { enumerable: true, get: function () { return core_1.Patch; } });
Object.defineProperty(exports, "Post", { enumerable: true, get: function () { return core_1.Post; } });
Object.defineProperty(exports, "Put", { enumerable: true, get: function () { return core_1.Put; } });
Object.defineProperty(exports, "ServiceManager", { enumerable: true, get: function () { return core_1.ServiceManager; } });
Object.defineProperty(exports, "createController", { enumerable: true, get: function () { return core_1.createController; } });
Object.defineProperty(exports, "createOpenApiDocument", { enumerable: true, get: function () { return core_1.createOpenApiDocument; } });
Object.defineProperty(exports, "createService", { enumerable: true, get: function () { return core_1.createService; } });
Object.defineProperty(exports, "dependency", { enumerable: true, get: function () { return core_1.dependency; } });
Object.defineProperty(exports, "getApiCallbacks", { enumerable: true, get: function () { return core_1.getApiCallbacks; } });
Object.defineProperty(exports, "getApiCompleteOperation", { enumerable: true, get: function () { return core_1.getApiCompleteOperation; } });
Object.defineProperty(exports, "getApiComponents", { enumerable: true, get: function () { return core_1.getApiComponents; } });
Object.defineProperty(exports, "getApiDeprecated", { enumerable: true, get: function () { return core_1.getApiDeprecated; } });
Object.defineProperty(exports, "getApiExternalDocs", { enumerable: true, get: function () { return core_1.getApiExternalDocs; } });
Object.defineProperty(exports, "getApiInfo", { enumerable: true, get: function () { return core_1.getApiInfo; } });
Object.defineProperty(exports, "getApiOperation", { enumerable: true, get: function () { return core_1.getApiOperation; } });
Object.defineProperty(exports, "getApiOperationDescription", { enumerable: true, get: function () { return core_1.getApiOperationDescription; } });
Object.defineProperty(exports, "getApiOperationId", { enumerable: true, get: function () { return core_1.getApiOperationId; } });
Object.defineProperty(exports, "getApiOperationSummary", { enumerable: true, get: function () { return core_1.getApiOperationSummary; } });
Object.defineProperty(exports, "getApiParameters", { enumerable: true, get: function () { return core_1.getApiParameters; } });
Object.defineProperty(exports, "getApiRequestBody", { enumerable: true, get: function () { return core_1.getApiRequestBody; } });
Object.defineProperty(exports, "getApiResponses", { enumerable: true, get: function () { return core_1.getApiResponses; } });
Object.defineProperty(exports, "getApiSecurity", { enumerable: true, get: function () { return core_1.getApiSecurity; } });
Object.defineProperty(exports, "getApiServers", { enumerable: true, get: function () { return core_1.getApiServers; } });
Object.defineProperty(exports, "getApiTags", { enumerable: true, get: function () { return core_1.getApiTags; } });
Object.defineProperty(exports, "getApiUsedTags", { enumerable: true, get: function () { return core_1.getApiUsedTags; } });
Object.defineProperty(exports, "getHookFunction", { enumerable: true, get: function () { return core_1.getHookFunction; } });
Object.defineProperty(exports, "getHookFunctions", { enumerable: true, get: function () { return core_1.getHookFunctions; } });
Object.defineProperty(exports, "getHttpMethod", { enumerable: true, get: function () { return core_1.getHttpMethod; } });
Object.defineProperty(exports, "getPath", { enumerable: true, get: function () { return core_1.getPath; } });
Object.defineProperty(exports, "isHttpResponse", { enumerable: true, get: function () { return core_1.isHttpResponse; } });
Object.defineProperty(exports, "isHttpResponseBadRequest", { enumerable: true, get: function () { return core_1.isHttpResponseBadRequest; } });
Object.defineProperty(exports, "isHttpResponseClientError", { enumerable: true, get: function () { return core_1.isHttpResponseClientError; } });
Object.defineProperty(exports, "isHttpResponseConflict", { enumerable: true, get: function () { return core_1.isHttpResponseConflict; } });
Object.defineProperty(exports, "isHttpResponseCreated", { enumerable: true, get: function () { return core_1.isHttpResponseCreated; } });
Object.defineProperty(exports, "isHttpResponseForbidden", { enumerable: true, get: function () { return core_1.isHttpResponseForbidden; } });
Object.defineProperty(exports, "isHttpResponseInternalServerError", { enumerable: true, get: function () { return core_1.isHttpResponseInternalServerError; } });
Object.defineProperty(exports, "isHttpResponseMethodNotAllowed", { enumerable: true, get: function () { return core_1.isHttpResponseMethodNotAllowed; } });
Object.defineProperty(exports, "isHttpResponseMovedPermanently", { enumerable: true, get: function () { return core_1.isHttpResponseMovedPermanently; } });
Object.defineProperty(exports, "isHttpResponseNoContent", { enumerable: true, get: function () { return core_1.isHttpResponseNoContent; } });
Object.defineProperty(exports, "isHttpResponseNotFound", { enumerable: true, get: function () { return core_1.isHttpResponseNotFound; } });
Object.defineProperty(exports, "isHttpResponseNotImplemented", { enumerable: true, get: function () { return core_1.isHttpResponseNotImplemented; } });
Object.defineProperty(exports, "isHttpResponseOK", { enumerable: true, get: function () { return core_1.isHttpResponseOK; } });
Object.defineProperty(exports, "isHttpResponseRedirect", { enumerable: true, get: function () { return core_1.isHttpResponseRedirect; } });
Object.defineProperty(exports, "isHttpResponseRedirection", { enumerable: true, get: function () { return core_1.isHttpResponseRedirection; } });
Object.defineProperty(exports, "isHttpResponseServerError", { enumerable: true, get: function () { return core_1.isHttpResponseServerError; } });
Object.defineProperty(exports, "isHttpResponseSuccess", { enumerable: true, get: function () { return core_1.isHttpResponseSuccess; } });
Object.defineProperty(exports, "isHttpResponseTooManyRequests", { enumerable: true, get: function () { return core_1.isHttpResponseTooManyRequests; } });
Object.defineProperty(exports, "isHttpResponseUnauthorized", { enumerable: true, get: function () { return core_1.isHttpResponseUnauthorized; } });
var express_1 = require("./express");
Object.defineProperty(exports, "OPENAPI_SERVICE_ID", { enumerable: true, get: function () { return express_1.OPENAPI_SERVICE_ID; } });
Object.defineProperty(exports, "createApp", { enumerable: true, get: function () { return express_1.createApp; } });
var sessions_1 = require("./sessions");
Object.defineProperty(exports, "Session", { enumerable: true, get: function () { return sessions_1.Session; } });
Object.defineProperty(exports, "SessionAlreadyExists", { enumerable: true, get: function () { return sessions_1.SessionAlreadyExists; } });
Object.defineProperty(exports, "SessionStore", { enumerable: true, get: function () { return sessions_1.SessionStore; } });
Object.defineProperty(exports, "Store", { enumerable: true, get: function () { return sessions_1.Store; } });
Object.defineProperty(exports, "UseSessions", { enumerable: true, get: function () { return sessions_1.UseSessions; } });
Object.defineProperty(exports, "createSession", { enumerable: true, get: function () { return sessions_1.createSession; } });
Object.defineProperty(exports, "readSession", { enumerable: true, get: function () { return sessions_1.readSession; } });

@@ -7,3 +7,6 @@ /**

export declare const SESSION_DEFAULT_COOKIE_NAME: string;
export declare const SESSION_DEFAULT_CSRF_COOKIE_NAME: string;
export declare const SESSION_DEFAULT_SAME_SITE_ON_CSRF_ENABLED: 'strict' | 'lax' | 'none';
export declare const SESSION_DEFAULT_INACTIVITY_TIMEOUT: number;
export declare const SESSION_DEFAULT_ABSOLUTE_TIMEOUT: number;
export declare const SESSION_DEFAULT_GARBAGE_COLLECTOR_PERIODICITY = 50;

@@ -6,7 +6,11 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.SESSION_DEFAULT_GARBAGE_COLLECTOR_PERIODICITY = exports.SESSION_DEFAULT_ABSOLUTE_TIMEOUT = exports.SESSION_DEFAULT_INACTIVITY_TIMEOUT = exports.SESSION_DEFAULT_SAME_SITE_ON_CSRF_ENABLED = exports.SESSION_DEFAULT_CSRF_COOKIE_NAME = exports.SESSION_DEFAULT_COOKIE_NAME = exports.SESSION_DEFAULT_COOKIE_HTTP_ONLY = exports.SESSION_DEFAULT_COOKIE_PATH = void 0;
exports.SESSION_DEFAULT_COOKIE_PATH = '/';
exports.SESSION_DEFAULT_COOKIE_HTTP_ONLY = true;
exports.SESSION_DEFAULT_COOKIE_NAME = 'sessionID';
exports.SESSION_DEFAULT_CSRF_COOKIE_NAME = 'XSRF-TOKEN';
exports.SESSION_DEFAULT_SAME_SITE_ON_CSRF_ENABLED = 'lax';
// Expiration timeouts in seconds
exports.SESSION_DEFAULT_INACTIVITY_TIMEOUT = 15 * 60; // 15 minutes
exports.SESSION_DEFAULT_ABSOLUTE_TIMEOUT = 7 * 24 * 60 * 60; // 1 week
exports.SESSION_DEFAULT_GARBAGE_COLLECTOR_PERIODICITY = 50;

@@ -1,6 +0,6 @@

export { removeSessionCookie } from './remove-session-cookie';
export { Store, SessionStore, SessionOptions } from './session-store';
export { createSession } from './create-session';
export { readSession } from './read-session';
export { Store, SessionStore, SessionAlreadyExists } from './session-store';
export { Session } from './session';
export { setSessionCookie } from './set-session-cookie';
export { TokenOptional } from './token-optional.hook';
export { TokenRequired } from './token-required.hook';
export { SessionState } from './session-state.interface';
export { UseSessions } from './use-sessions.hook';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var remove_session_cookie_1 = require("./remove-session-cookie");
exports.removeSessionCookie = remove_session_cookie_1.removeSessionCookie;
exports.UseSessions = exports.Session = exports.SessionAlreadyExists = exports.SessionStore = exports.Store = exports.readSession = exports.createSession = void 0;
var create_session_1 = require("./create-session");
Object.defineProperty(exports, "createSession", { enumerable: true, get: function () { return create_session_1.createSession; } });
var read_session_1 = require("./read-session");
Object.defineProperty(exports, "readSession", { enumerable: true, get: function () { return read_session_1.readSession; } });
var session_store_1 = require("./session-store");
exports.Store = session_store_1.Store;
exports.SessionStore = session_store_1.SessionStore;
Object.defineProperty(exports, "Store", { enumerable: true, get: function () { return session_store_1.Store; } });
Object.defineProperty(exports, "SessionStore", { enumerable: true, get: function () { return session_store_1.SessionStore; } });
Object.defineProperty(exports, "SessionAlreadyExists", { enumerable: true, get: function () { return session_store_1.SessionAlreadyExists; } });
var session_1 = require("./session");
exports.Session = session_1.Session;
var set_session_cookie_1 = require("./set-session-cookie");
exports.setSessionCookie = set_session_cookie_1.setSessionCookie;
var token_optional_hook_1 = require("./token-optional.hook");
exports.TokenOptional = token_optional_hook_1.TokenOptional;
var token_required_hook_1 = require("./token-required.hook");
exports.TokenRequired = token_required_hook_1.TokenRequired;
Object.defineProperty(exports, "Session", { enumerable: true, get: function () { return session_1.Session; } });
var use_sessions_hook_1 = require("./use-sessions.hook");
Object.defineProperty(exports, "UseSessions", { enumerable: true, get: function () { return use_sessions_hook_1.UseSessions; } });
import { HttpResponse } from '../core';
/**
* Delete the browser cookie containing the session token.
* Deletes the browser cookie containing the session token.
*
* If the CSRF protection is enabled, it also deletes the CSRF cookie containing the CSRF token.
*
* @export

@@ -6,0 +8,0 @@ * @param {HttpResponse} response - The HTTP response

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.removeSessionCookie = void 0;
// FoalTS

@@ -7,4 +8,6 @@ const core_1 = require("../core");

/**
* Delete the browser cookie containing the session token.
* Deletes the browser cookie containing the session token.
*
* If the CSRF protection is enabled, it also deletes the CSRF cookie containing the CSRF token.
*
* @export

@@ -14,13 +17,21 @@ * @param {HttpResponse} response - The HTTP response

function removeSessionCookie(response) {
const cookieName = core_1.Config.get2('settings.session.cookie.name', 'string', constants_1.SESSION_DEFAULT_COOKIE_NAME);
const cookieName = core_1.Config.get('settings.session.cookie.name', 'string', constants_1.SESSION_DEFAULT_COOKIE_NAME);
const csrfEnabled = core_1.Config.get('settings.session.csrf.enabled', 'boolean', false);
let sameSite = core_1.Config.get('settings.session.cookie.sameSite', 'string');
if (csrfEnabled && sameSite === undefined) {
sameSite = constants_1.SESSION_DEFAULT_SAME_SITE_ON_CSRF_ENABLED;
}
const options = {
domain: core_1.Config.get2('settings.session.cookie.domain', 'string'),
httpOnly: core_1.Config.get2('settings.session.cookie.httpOnly', 'boolean', constants_1.SESSION_DEFAULT_COOKIE_HTTP_ONLY),
domain: core_1.Config.get('settings.session.cookie.domain', 'string'),
maxAge: 0,
path: core_1.Config.get2('settings.session.cookie.path', 'string', constants_1.SESSION_DEFAULT_COOKIE_PATH),
sameSite: core_1.Config.get2('settings.session.cookie.sameSite', 'string'),
secure: core_1.Config.get2('settings.session.cookie.secure', 'boolean')
path: core_1.Config.get('settings.session.cookie.path', 'string', constants_1.SESSION_DEFAULT_COOKIE_PATH),
sameSite,
secure: core_1.Config.get('settings.session.cookie.secure', 'boolean'),
};
response.setCookie(cookieName, '', options);
response.setCookie(cookieName, '', Object.assign(Object.assign({}, options), { httpOnly: core_1.Config.get('settings.session.cookie.httpOnly', 'boolean', constants_1.SESSION_DEFAULT_COOKIE_HTTP_ONLY) }));
if (csrfEnabled) {
const csrfCookieName = core_1.Config.get('settings.session.csrf.cookie.name', 'string', constants_1.SESSION_DEFAULT_CSRF_COOKIE_NAME);
response.setCookie(csrfCookieName, '', Object.assign(Object.assign({}, options), { httpOnly: false }));
}
}
exports.removeSessionCookie = removeSessionCookie;

@@ -1,12 +0,13 @@

import { Session } from './session';
export interface SessionOptions {
csrfToken?: boolean;
import { SessionState } from './session-state.interface';
export declare class SessionAlreadyExists extends Error {
readonly name = "SessionAlreadyExists";
}
/**
* Abstract class to be override when creating a session storage service.
* Store used to create, read, update and delete sessions.
*
* A session store peforms CRUD operations on sessions and can store them in
* a database, file system, memory, etc.
* All session stores must inherit this abstract class.
*
* Examples of Store: TypeORMStore, RedisStore, MongoDBStore.
* When this class is used with the `@dependency` decorator,
* it returns the `ConcreteSessionStore` class from the file or the package specified
* with the configuration key "settings.session.store".
*

@@ -21,94 +22,49 @@ * @export

/**
* Read session expiration timeouts from the configuration.
* Saves the session for the first time.
*
* The values are in seconds.
* If a session already exists with the given ID, a SessionAlreadyExists error MUST be thrown.
*
* Default values are:
* - 15 min for inactivity timeout
* - 1 week for absolute timeout
*
* This method throws an error if one of the following is true:
* - The given inactivity timeout is negative.
* - The given absolute timeout is negative.
* - The given inactivity timeout is greater than the absolute timeout.
*
* @static
* @returns {{ inactivity: number , absolute: number }} The expiration timeouts
* @abstract
* @param {SessionState} state - The state of the session.
* @param {number} maxInactivity - The maximum idle activity of the session (useful for cache stores).
* @returns {Promise<void>}
* @memberof Store
*/
static getExpirationTimeouts(): {
inactivity: number;
absolute: number;
};
abstract save(state: SessionState, maxInactivity: number): Promise<void>;
/**
* Create and save an new session from a user.
* Reads a session.
*
* @param {({ id: string|number })} user - User id.
* @param {SessionOptions} options - Session options.
* @param {boolean} [options.csrfToken] - Generate and add a `csrfToken` to the sessionContent.
* @returns {Promise<Session>} The created session.
* @memberof Store
*/
createAndSaveSessionFromUser(user: {
id: string | number;
}, options?: SessionOptions): Promise<Session>;
/**
* Create and save a new session.
* If the session does not exist, the value `null` MUST be returned.
*
* This method *MUST* call the `generateSessionID` method to generate the session ID.
* This method *MUST* call the `applySessionOptions` method to extend the sessionContent.
*
* @abstract
* @param {object} sessionContent - The content of the session (often includes the user ID).
* @param {SessionOptions} options - Session options.
* @param {boolean} [options.csrfToken] - Generate and add a `csrfToken` to the sessionContent.
* @returns {Promise<Session>} The created session.
* @param {string} id - The ID of the session.
* @returns {(Promise<SessionState|null>)} The state of the session.
* @memberof Store
*/
abstract createAndSaveSession(sessionContent: object, options?: SessionOptions): Promise<Session>;
abstract read(id: string): Promise<SessionState | null>;
/**
* Update and extend the lifetime of a session.
* Updates and extends the lifetime of a session.
*
* Depending on the implementation, the internal behavior can be similar to "update" or "upsert".
* If the session no longer exists (i.e. has expired or been destroyed), the session MUST still be saved.
*
* @abstract
* @param {Session} session - The session containaing the updated content.
* @param {SessionState} state - The state of the session.
* @param {number} maxInactivity - The maximum idle activity of the session (useful for cache stores).
* @returns {Promise<void>}
* @memberof Store
*/
abstract update(session: Session): Promise<void>;
abstract update(state: SessionState, maxInactivity: number): Promise<void>;
/**
* Delete a session, whether it exists or not.
* Deletes a session.
*
* @abstract
* @param {string} sessionID - The ID of the session.
* @returns {Promise<void>}
* @memberof Store
*/
abstract destroy(sessionID: string): Promise<void>;
/**
* Read a session from its ID.
* If the session does not exist, NO error MUST be thrown.
*
* Returns `undefined` if the session does not exist or has expired.
*
* @abstract
* @param {string} sessionID - The ID of the session.
* @returns {(Promise<Session|undefined>)} The Session object.
* @memberof Store
*/
abstract read(sessionID: string): Promise<Session | undefined>;
/**
* Extend the lifetime of a session from its ID. The duration is
* the inactivity timeout.
*
* If the session does not exist, the method does not throw an error.
*
* @abstract
* @param {string} sessionID - The ID of the session.
* @param {string} id - The ID of the session.
* @returns {Promise<void>}
* @memberof Store
*/
abstract extendLifeTime(sessionID: string): Promise<void>;
abstract destroy(id: string): Promise<void>;
/**
* Clear all sessions.
* Clears all sessions.
*

@@ -125,27 +81,13 @@ * @abstract

*
* If the store manages a cache database, then this method can remain empty but it must NOT throw an error.
*
* @abstract
* @param {number} maxInactivity - The maximum idle activity of a session.
* @param {number} maxLifeTime - The maximum absolute life time of a session.
* @returns {Promise<void>}
* @memberof Store
*/
abstract cleanUpExpiredSessions(): Promise<void>;
/**
* Generate a 128-bit base64url-encoded session ID.
*
* @protected
* @returns {Promise<string>} - The session ID.
* @memberof Store
*/
protected generateSessionID(): Promise<string>;
/**
* Apply session options to the given session content.
*
* @protected
* @param {object} content - Session content.
* @param {SessionOptions} options - Session options.
* @param {boolean} [options.csrfToken] - Generate and add a `csrfToken` to the sessionContent.
* @returns {Promise<void>}
* @memberof Store
*/
protected applySessionOptions(content: object, options: SessionOptions): Promise<void>;
abstract cleanUpExpiredSessions(maxInactivity: number, maxLifeTime: number): Promise<void>;
boot(): void | Promise<void>;
}
export { Store as SessionStore };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// FoalTS
const common_1 = require("../common");
const core_1 = require("../core");
const constants_1 = require("./constants");
exports.SessionStore = exports.Store = exports.SessionAlreadyExists = void 0;
class SessionAlreadyExists extends Error {
constructor() {
super(...arguments);
this.name = 'SessionAlreadyExists';
}
}
exports.SessionAlreadyExists = SessionAlreadyExists;
/**
* Abstract class to be override when creating a session storage service.
* Store used to create, read, update and delete sessions.
*
* A session store peforms CRUD operations on sessions and can store them in
* a database, file system, memory, etc.
* All session stores must inherit this abstract class.
*
* Examples of Store: TypeORMStore, RedisStore, MongoDBStore.
* When this class is used with the `@dependency` decorator,
* it returns the `ConcreteSessionStore` class from the file or the package specified
* with the configuration key "settings.session.store".
*

@@ -20,77 +25,7 @@ * @export

class Store {
/**
* Read session expiration timeouts from the configuration.
*
* The values are in seconds.
*
* Default values are:
* - 15 min for inactivity timeout
* - 1 week for absolute timeout
*
* This method throws an error if one of the following is true:
* - The given inactivity timeout is negative.
* - The given absolute timeout is negative.
* - The given inactivity timeout is greater than the absolute timeout.
*
* @static
* @returns {{ inactivity: number , absolute: number }} The expiration timeouts
* @memberof Store
*/
static getExpirationTimeouts() {
const result = {
absolute: core_1.Config.get2('settings.session.expirationTimeouts.absolute', 'number', constants_1.SESSION_DEFAULT_ABSOLUTE_TIMEOUT),
inactivity: core_1.Config.get2('settings.session.expirationTimeouts.inactivity', 'number', constants_1.SESSION_DEFAULT_INACTIVITY_TIMEOUT),
};
if (result.absolute < 0) {
throw new Error('[CONFIG] The value of settings.session.expirationTimeouts.absolute must be a positive number.');
}
if (result.inactivity < 0) {
throw new Error('[CONFIG] The value of settings.session.expirationTimeouts.inactivity must be a positive number.');
}
if (result.absolute < result.inactivity) {
throw new Error('[CONFIG] The value of settings.session.expirationTimeouts.absolute must be greater than *.inactivity.');
}
return result;
}
/**
* Create and save an new session from a user.
*
* @param {({ id: string|number })} user - User id.
* @param {SessionOptions} options - Session options.
* @param {boolean} [options.csrfToken] - Generate and add a `csrfToken` to the sessionContent.
* @returns {Promise<Session>} The created session.
* @memberof Store
*/
createAndSaveSessionFromUser(user, options) {
return this.createAndSaveSession({ userId: user.id }, options);
}
/**
* Generate a 128-bit base64url-encoded session ID.
*
* @protected
* @returns {Promise<string>} - The session ID.
* @memberof Store
*/
async generateSessionID() {
return common_1.generateToken();
}
/**
* Apply session options to the given session content.
*
* @protected
* @param {object} content - Session content.
* @param {SessionOptions} options - Session options.
* @param {boolean} [options.csrfToken] - Generate and add a `csrfToken` to the sessionContent.
* @returns {Promise<void>}
* @memberof Store
*/
async applySessionOptions(content, options) {
if (options.csrfToken) {
content.csrfToken = await common_1.generateToken();
}
}
boot() { }
}
exports.Store = Store;
exports.SessionStore = Store;
Store.concreteClassConfigPath = 'settings.session.store';
Store.concreteClassName = 'ConcreteSessionStore';
exports.Store = Store;
exports.SessionStore = Store;

@@ -0,3 +1,5 @@

import { SessionState } from './session-state.interface';
import { SessionStore } from './session-store';
/**
* Representation of a server/database session.
* Representation of a server/database/file session.
*

@@ -8,18 +10,18 @@ * @export

export declare class Session {
readonly sessionID: string;
private sessionContent;
readonly createdAt: number;
private readonly store;
private readonly state;
private readonly oldFlash;
private oldId;
private status;
/**
* Verify a session token and return the sessionID if the token is valid.
* Retuns the user ID. If the session is anonymous, the value is null.
*
* @static
* @param {string} token - The session token to verify.
* @returns {(string|false)} False if the token is invalid. Otherwise, the returned value is the session ID.
* @readonly
* @type {(string|number|null)}
* @memberof Session
*/
static verifyTokenAndGetId(token: string): string | false;
private modified;
constructor(sessionID: string, sessionContent: any, createdAt: number);
get userId(): string | number | null;
/**
* Return true if an element was added/replaced in the session
* Returns true if the session has expired due to inactivity
* or because it reached the maximum lifetime allowed.
*

@@ -30,18 +32,44 @@ * @readonly

*/
readonly isModified: boolean;
get isExpired(): boolean;
/**
* Add/replace an element in the session. This operation is not saved
* in the saved unless you call SessionStore.update(session).
* Returns the session expiration time in seconds.
*
* @param {string} key
* @param {*} value
* @readonly
* @type {number}
* @memberof Session
*/
set(key: string, value: any): void;
get expirationTime(): number;
constructor(store: SessionStore, state: SessionState, options: {
exists: boolean;
});
/**
* The value of an element in the session content.
* Sets or replaces the userId associated with the session.
*
* @param {({ id: number|string })} user - The user containing the ID.
* @memberof Session
*/
setUser(user: {
id: number | string | object;
} | {
_id: number | string | object;
}): void;
/**
* Adds or replaces an element in the session. This operation is not saved
* in the saved unless you call the "commit" function.
*
* @param {string} key - The property key.
* @param {*} value - The property value.
* @param {{ flash?: boolean }} [options={}] If flash is true, the key/value
* will be erased at the end of the next request.
* @memberof Session
*/
set(key: string, value: any, options?: {
flash?: boolean;
}): void;
/**
* Gets the value of a key in the session content.
*
* @template T
* @param {string} key - The property key
* @returns {(T | undefined)} The property valye
* @param {string} key - The property key.
* @returns {(T | undefined)} The property value.
* @memberof Session

@@ -52,6 +80,5 @@ */

/**
* Get the session token. This token is used by `@TokenRequired` and `@TokenOptional` to retreive
* the session and the authenticated user if she/he exists.
* Gets the session ID.
*
* @returns {string} - The session token.
* @returns {string} - The session ID.
* @memberof Session

@@ -61,8 +88,48 @@ */

/**
* Get a copy of the session content.
* Regenerates the session with a new ID. It is recommended
* to regenerate the session ID after any privilege level change
* within the associated user session.
*
* @returns {object} - The session content copy.
* Common scenario: an anonymous user is authenticated.
*
* @returns {Promise<void>}
* @memberof Session
*/
getContent(): object;
regenerateID(): Promise<void>;
/**
* Destroys the session.
*
* @returns {Promise<void>}
* @memberof Session
*/
destroy(): Promise<void>;
/**
* Returns true if the method `destroy` has previously been called.
*
* @readonly
* @type {boolean}
* @memberof Session
*/
get isDestroyed(): boolean;
/**
* Saves or updates the session and extends its lifetime.
*
* If the session has already been destroyed, an error is thrown.
*
* This function calls periodically the store method "cleanUpExpiredSessions".
*
* @returns {Promise<void>}
* @memberof Session
*/
commit(): Promise<void>;
/**
* Returns the current time in seconds.
*
* @private
* @returns {number} The current time.
* @memberof Session
*/
private getTime;
private shouldCleanUpExpiredSessions;
private getTimeouts;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Session = void 0;
// FoalTS
const common_1 = require("../common");
const core_1 = require("../core");
const constants_1 = require("./constants");
/**
* Representation of a server/database session.
* Representation of a server/database/file session.
*

@@ -13,25 +15,23 @@ * @export

class Session {
constructor(sessionID, sessionContent, createdAt) {
this.sessionID = sessionID;
this.sessionContent = sessionContent;
this.createdAt = createdAt;
this.modified = false;
if (sessionID.includes('.')) {
throw new Error('A session ID cannot include dots.');
}
constructor(store, state, options) {
this.store = store;
this.state = state;
this.oldId = '';
this.status = options.exists ? 'exists' : 'new';
this.oldFlash = state.flash;
state.flash = {};
}
/**
* Verify a session token and return the sessionID if the token is valid.
* Retuns the user ID. If the session is anonymous, the value is null.
*
* @static
* @param {string} token - The session token to verify.
* @returns {(string|false)} False if the token is invalid. Otherwise, the returned value is the session ID.
* @readonly
* @type {(string|number|null)}
* @memberof Session
*/
static verifyTokenAndGetId(token) {
const secret = core_1.Config.getOrThrow('settings.session.secret', 'string', 'You must provide a secret when using sessions.');
return common_1.verifySignedToken(token, secret);
get userId() {
return this.state.userId;
}
/**
* Return true if an element was added/replaced in the session
* Returns true if the session has expired due to inactivity
* or because it reached the maximum lifetime allowed.
*

@@ -42,44 +42,175 @@ * @readonly

*/
get isModified() {
return this.modified;
get isExpired() {
const { absoluteTimeout, inactivityTimeout } = this.getTimeouts();
const now = this.getTime();
if (now - this.state.updatedAt >= inactivityTimeout) {
return true;
}
if (now - this.state.createdAt >= absoluteTimeout) {
return true;
}
return false;
}
/**
* Add/replace an element in the session. This operation is not saved
* in the saved unless you call SessionStore.update(session).
* Returns the session expiration time in seconds.
*
* @param {string} key
* @param {*} value
* @readonly
* @type {number}
* @memberof Session
*/
set(key, value) {
this.sessionContent[key] = value;
this.modified = true;
get expirationTime() {
const { absoluteTimeout, inactivityTimeout } = this.getTimeouts();
return Math.min(this.state.updatedAt + inactivityTimeout, this.state.createdAt + absoluteTimeout);
}
/**
* Sets or replaces the userId associated with the session.
*
* @param {({ id: number|string })} user - The user containing the ID.
* @memberof Session
*/
setUser(user) {
var _a;
// tslint:disable-next-line
const id = (_a = user.id) !== null && _a !== void 0 ? _a : user._id;
if (typeof id === 'object') {
this.state.userId = id.toString();
return;
}
this.state.userId = id;
}
/**
* Adds or replaces an element in the session. This operation is not saved
* in the saved unless you call the "commit" function.
*
* @param {string} key - The property key.
* @param {*} value - The property value.
* @param {{ flash?: boolean }} [options={}] If flash is true, the key/value
* will be erased at the end of the next request.
* @memberof Session
*/
set(key, value, options = {}) {
if (options.flash) {
this.state.flash[key] = value;
}
else {
this.state.content[key] = value;
}
}
get(key, defaultValue) {
if (!this.sessionContent.hasOwnProperty(key)) {
return defaultValue;
if (this.oldFlash.hasOwnProperty(key)) {
return this.oldFlash[key];
}
return this.sessionContent[key];
if (this.state.content.hasOwnProperty(key)) {
return this.state.content[key];
}
return defaultValue;
}
/**
* Get the session token. This token is used by `@TokenRequired` and `@TokenOptional` to retreive
* the session and the authenticated user if she/he exists.
* Gets the session ID.
*
* @returns {string} - The session token.
* @returns {string} - The session ID.
* @memberof Session
*/
getToken() {
const secret = core_1.Config.getOrThrow('settings.session.secret', 'string', 'You must provide a secret when using sessions.');
return common_1.signToken(this.sessionID, secret);
return this.state.id;
}
/**
* Get a copy of the session content.
* Regenerates the session with a new ID. It is recommended
* to regenerate the session ID after any privilege level change
* within the associated user session.
*
* @returns {object} - The session content copy.
* Common scenario: an anonymous user is authenticated.
*
* @returns {Promise<void>}
* @memberof Session
*/
getContent() {
return Object.assign({}, this.sessionContent);
async regenerateID() {
this.oldId = this.state.id;
this.state.id = await common_1.generateToken();
this.status = 'regenerated';
}
/**
* Destroys the session.
*
* @returns {Promise<void>}
* @memberof Session
*/
async destroy() {
await this.store.destroy(this.state.id);
this.status = 'destroyed';
}
/**
* Returns true if the method `destroy` has previously been called.
*
* @readonly
* @type {boolean}
* @memberof Session
*/
get isDestroyed() {
return this.status === 'destroyed';
}
/**
* Saves or updates the session and extends its lifetime.
*
* If the session has already been destroyed, an error is thrown.
*
* This function calls periodically the store method "cleanUpExpiredSessions".
*
* @returns {Promise<void>}
* @memberof Session
*/
async commit() {
const { absoluteTimeout, inactivityTimeout } = this.getTimeouts();
if (this.shouldCleanUpExpiredSessions()) {
await this.store.cleanUpExpiredSessions(inactivityTimeout, absoluteTimeout);
}
this.state.updatedAt = this.getTime();
switch (this.status) {
case 'regenerated':
await this.store.destroy(this.oldId);
await this.store.save(this.state, inactivityTimeout);
this.status = 'exists';
break;
case 'new':
await this.store.save(this.state, inactivityTimeout);
this.status = 'exists';
break;
case 'exists':
await this.store.update(this.state, inactivityTimeout);
break;
case 'destroyed':
throw new Error('Impossible to commit the session. Session already destroyed.');
default:
break;
}
}
/**
* Returns the current time in seconds.
*
* @private
* @returns {number} The current time.
* @memberof Session
*/
getTime() {
return Math.trunc(Date.now() / 1000);
}
shouldCleanUpExpiredSessions() {
const periodicity = core_1.Config.get('settings.session.garbageCollector.periodicity', 'number', constants_1.SESSION_DEFAULT_GARBAGE_COLLECTOR_PERIODICITY);
return Math.trunc(Math.random() * periodicity) === 0;
}
getTimeouts() {
const inactivityTimeout = core_1.Config.get('settings.session.expirationTimeouts.inactivity', 'number', constants_1.SESSION_DEFAULT_INACTIVITY_TIMEOUT);
if (inactivityTimeout < 0) {
throw new Error('[CONFIG] The value of settings.session.expirationTimeouts.inactivity must be a positive number.');
}
const absoluteTimeout = core_1.Config.get('settings.session.expirationTimeouts.absolute', 'number', constants_1.SESSION_DEFAULT_ABSOLUTE_TIMEOUT);
if (absoluteTimeout < 0) {
throw new Error('[CONFIG] The value of settings.session.expirationTimeouts.absolute must be a positive number.');
}
if (absoluteTimeout < inactivityTimeout) {
throw new Error('[CONFIG] The value of settings.session.expirationTimeouts.absolute must be greater than *.inactivity.');
}
return { absoluteTimeout, inactivityTimeout };
}
}
exports.Session = Session;
import { HttpResponse } from '../core';
import { Session } from './session';
/**
* Send the session token in a cookie.
* Sends the session token in a cookie.
*
* If the CSRF protection is enabled, it also sends the CSRF token in a CSRF cookie.
*
* @export
* @param {HttpResponse} response - The HTTP response
* @param {string} token - The session token
* @param {HttpResponse} response - The HTTP response.
* @param {Session} session - The session object.
*/
export declare function setSessionCookie(response: HttpResponse, token: string): void;
export declare function setSessionCookie(response: HttpResponse, session: Session): void;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setSessionCookie = void 0;
// FoalTS
const core_1 = require("../core");
const constants_1 = require("./constants");
const session_store_1 = require("./session-store");
/**
* Send the session token in a cookie.
* Sends the session token in a cookie.
*
* If the CSRF protection is enabled, it also sends the CSRF token in a CSRF cookie.
*
* @export
* @param {HttpResponse} response - The HTTP response
* @param {string} token - The session token
* @param {HttpResponse} response - The HTTP response.
* @param {Session} session - The session object.
*/
function setSessionCookie(response, token) {
const cookieName = core_1.Config.get2('settings.session.cookie.name', 'string', constants_1.SESSION_DEFAULT_COOKIE_NAME);
function setSessionCookie(response, session) {
const cookieName = core_1.Config.get('settings.session.cookie.name', 'string', constants_1.SESSION_DEFAULT_COOKIE_NAME);
const csrfEnabled = core_1.Config.get('settings.session.csrf.enabled', 'boolean', false);
let sameSite = core_1.Config.get('settings.session.cookie.sameSite', 'string');
if (csrfEnabled && sameSite === undefined) {
sameSite = constants_1.SESSION_DEFAULT_SAME_SITE_ON_CSRF_ENABLED;
}
const options = {
domain: core_1.Config.get2('settings.session.cookie.domain', 'string'),
httpOnly: core_1.Config.get2('settings.session.cookie.httpOnly', 'boolean', constants_1.SESSION_DEFAULT_COOKIE_HTTP_ONLY),
maxAge: session_store_1.SessionStore.getExpirationTimeouts().inactivity,
path: core_1.Config.get2('settings.session.cookie.path', 'string', constants_1.SESSION_DEFAULT_COOKIE_PATH),
sameSite: core_1.Config.get2('settings.session.cookie.sameSite', 'string'),
secure: core_1.Config.get2('settings.session.cookie.secure', 'boolean')
domain: core_1.Config.get('settings.session.cookie.domain', 'string'),
expires: new Date(session.expirationTime * 1000),
path: core_1.Config.get('settings.session.cookie.path', 'string', constants_1.SESSION_DEFAULT_COOKIE_PATH),
sameSite,
secure: core_1.Config.get('settings.session.cookie.secure', 'boolean')
};
response.setCookie(cookieName, token, options);
response.setCookie(cookieName, session.getToken(), Object.assign(Object.assign({}, options), { httpOnly: core_1.Config.get('settings.session.cookie.httpOnly', 'boolean', constants_1.SESSION_DEFAULT_COOKIE_HTTP_ONLY) }));
if (csrfEnabled) {
const csrfCookieName = core_1.Config.get('settings.session.csrf.cookie.name', 'string', constants_1.SESSION_DEFAULT_CSRF_COOKIE_NAME);
response.setCookie(csrfCookieName, session.get('csrfToken') || '', Object.assign(Object.assign({}, options), { httpOnly: false }));
}
}
exports.setSessionCookie = setSessionCookie;
{
"name": "@foal/core",
"version": "1.11.1",
"version": "2.0.0-beta.0",
"description": "A Node.js and TypeScript framework, all-inclusive.",

@@ -9,11 +9,11 @@ "main": "./lib/index.js",

"docs": "typedoc --out ../../docs/api/core src/index.ts --readme none --theme markdown",
"test": "nyc --reporter=json --reporter=text mocha --require ts-node/register --require source-map-support/register \"./src/**/*.spec.ts\"",
"dev:test": "mocha --require ts-node/register --watch --watch-extensions ts \"./src/**/*.spec.ts\"",
"dev:test:auth": "mocha --require ts-node/register --watch --watch-extensions ts \"./src/auth/**/*.spec.ts\"",
"dev:test:common": "mocha --require ts-node/register --watch --watch-extensions ts \"./src/common/**/*.spec.ts\"",
"test": "nyc --reporter=json --reporter=text mocha --parallel --require ts-node/register --require source-map-support/register \"./src/**/*.spec.ts\"",
"dev:test": "mocha --require ts-node/register --watch --extension ts \"./src/**/*.spec.ts\"",
"dev:test:auth": "mocha --require ts-node/register --watch --extension ts \"./src/auth/**/*.spec.ts\"",
"dev:test:common": "mocha --require ts-node/register --watch --extension ts \"./src/common/**/*.spec.ts\"",
"test:common": "mocha --require ts-node/register \"./src/common/**/*.spec.ts\"",
"dev:test:core": "mocha --require ts-node/register --watch --watch-extensions ts \"./src/core/**/*.spec.ts\"",
"dev:test:express": "mocha --require ts-node/register --watch --watch-extensions ts \"./src/express/**/*.spec.ts\"",
"dev:test:openapi": "mocha --require ts-node/register --watch --watch-extensions ts \"./src/openapi/**/*.spec.ts\"",
"dev:test:sessions": "mocha --require ts-node/register --watch --watch-extensions ts \"./src/sessions/**/*.spec.ts\"",
"dev:test:core": "mocha --require ts-node/register --watch --extension ts \"./src/core/**/*.spec.ts\"",
"dev:test:express": "mocha --require ts-node/register --watch --extension ts \"./src/express/**/*.spec.ts\"",
"dev:test:openapi": "mocha --require ts-node/register --watch --extension ts \"./src/openapi/**/*.spec.ts\"",
"dev:test:sessions": "mocha --require ts-node/register --watch --extension ts \"./src/sessions/**/*.spec.ts\"",
"build": "rimraf lib && copy-cli \"./src/**/500.debug.html\" lib && tsc -p tsconfig-build.json",

@@ -26,3 +26,3 @@ "prepublish": "npm run build"

"engines": {
"node": ">=8"
"node": ">=10"
},

@@ -87,31 +87,25 @@ "publishConfig": {

"express": "~4.17.1",
"mime": "~2.4.4",
"morgan": "~1.10.0",
"pump": "~3.0.0",
"reflect-metadata": "~0.1.13"
},
"devDependencies": {
"@foal/ejs": "^1.11.1",
"@foal/internal-test": "^1.11.1",
"@types/mocha": "~2.2.43",
"@types/node": "~10.1.2",
"@types/supertest": "~2.0.5",
"@foal/internal-test": "^2.0.0-beta.0",
"@types/mocha": "7.0.2",
"@types/node": "10.17.24",
"@types/supertest": "2.0.10",
"copy": "~0.3.2",
"ejs": "~2.6.2",
"mocha": "~5.2.0",
"mysql": "~2.15.0",
"node-mocks-http": "~1.7.0",
"mocha": "~8.2.0",
"nyc": "~12.0.2",
"pg": "~7.4.3",
"rimraf": "~2.6.2",
"source-map-support": "~0.5.6",
"supertest": "~3.1.0",
"ts-node": "~3.3.0",
"source-map-support": "~0.5.19",
"supertest": "~6.0.0",
"ts-node": "~9.0.0",
"twig": "~1.13.3",
"typedoc": "~0.14.2",
"typedoc-plugin-markdown": "~1.2.0",
"typescript": "~3.5.3",
"typedoc": "~0.19.0",
"typedoc-plugin-markdown": "~3.0.0",
"typescript": "~4.0.2",
"yamljs": "~0.3.0"
},
"gitHead": "3dec926f141773926de45e44457216146647e48f"
"gitHead": "5d8941fbd4765812b6c965f4a36a860a50f61d30"
}
<p align="center">
<a href="https://foalts.org" target="blank">
<img src="https://raw.githubusercontent.com/FoalTS/foal/master/docs/logo_title.png" height="160px" alt="Logo" />
<img src="https://raw.githubusercontent.com/FoalTS/foal/master/docs/images/logo_title.png" height="160px" alt="Logo" />
</a>

@@ -15,3 +15,3 @@ <br>

</a>
<img src="https://img.shields.io/badge/node-%3E%3D8-brightgreen.svg" alt="node version">
<img src="https://img.shields.io/badge/node-%3E%3D10-brightgreen.svg" alt="node version">
<a href="https://badge.fury.io/js/%40foal%2Fcore">

@@ -18,0 +18,0 @@ <img src="https://badge.fury.io/js/%40foal%2Fcore.svg" alt="npm version">

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc