This commit is contained in:
2026-03-03 15:23:00 +00:00
parent 5e3726de39
commit 8e223bfbec
3689 changed files with 955330 additions and 1011 deletions

8
node_modules/@tsoa/runtime/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2016 Luke Autry
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

3
node_modules/@tsoa/runtime/README.MD generated vendored Normal file
View File

@@ -0,0 +1,3 @@
This package contains the runtime helpers for tsoa.
For a comprehensive Readme, please refer to [the main readme](https://github.com/lukeautry/tsoa#readme).

240
node_modules/@tsoa/runtime/dist/config.d.ts generated vendored Normal file
View File

@@ -0,0 +1,240 @@
import { Swagger } from './swagger/swagger';
import { Options as MulterOpts } from 'multer';
export interface Config {
/**
* Swagger generation configuration object
*/
spec: SpecConfig;
/**
* Route generation configuration object
*/
routes: RoutesConfig;
/**
* Directories to ignore during TypeScript metadata scan
*/
ignore?: string[];
/**
* The entry point to your API
*/
entryFile: string;
/**
* An array of path globs that point to your route controllers that you would like to have tsoa include.
*/
controllerPathGlobs?: string[];
/**
* Modes that allow you to prevent input data from entering into your API. This will document your decision in the swagger.yaml and it will turn on excess-property validation (at runtime) in your routes.
*/
noImplicitAdditionalProperties?: 'throw-on-extras' | 'silently-remove-extras' | 'ignore';
/**
* Typescript CompilerOptions to be used during generation
*
* @type {Record<string, unknown>}
* @memberof RoutesConfig
*/
compilerOptions?: Record<string, unknown>;
/**
* Multer's options to generate multer's middleware.
* It doesn't support storage option
*
* @example {
* "dest": "/tmp"
* } Allow multer to write to file instead of using Memory's buffer
* @deprecated
* since v6.4.0 instroduces RegisterRoutes can pass multerOptions,
* we will quickly remove this options soon at future version.
* (https://github.com/lukeautry/tsoa/issues/1587#issuecomment-2391291433)
* (https://github.com/lukeautry/tsoa/pull/1638)
*/
multerOpts?: MulterOpts;
defaultNumberType?: 'double' | 'float' | 'integer' | 'long';
}
/**
* these options will be removed in a future version since we would prefer consumers to explicitly state their preference that the tsoa validation throws or removes additional properties
*/
export type DeprecatedOptionForAdditionalPropertiesHandling = true | false;
export interface SpecConfig {
/**
* Generated SwaggerConfig.json will output here
*/
outputDirectory: string;
/**
* API host, expressTemplate.g. localhost:3000 or myapi.com
*/
host?: string;
/**
* API servers, expressTemplate.g. [production.api.com, staging.api.com]
*
* Only available with the specVersion 3
*/
servers?: string[];
/**
* Base-name of swagger.json or swagger.yaml.
*
* @default: "swagger"
*/
specFileBaseName?: string;
/**
* API version number; defaults to npm package version
*/
version?: string;
/**
* Major OpenAPI version to generate; defaults to version 2 when not specified
* Possible values:
* - 2: generates OpenAPI version 2.
* - 3: generates OpenAPI version 3.
* - 3.1: generates OpenAPI version 3.1.
*/
specVersion?: Swagger.SupportedSpecMajorVersion;
/**
* API name; defaults to npm package name
*/
name?: string;
/**
* API description; defaults to npm package description
*/
description?: string;
/**
* Link to the page that describes the terms of service.
* Must be in the URL format.
*/
termsOfService?: string;
/**
* Contact Information
*/
contact?: {
/**
* The identifying name of the contact person/organization.
* @default npm package author
*/
name?: string;
/**
* The email address of the contact person/organization.
* @default npm package author email
*/
email?: string;
/**
* API Info url
* The URL pointing to the contact information.
* @default npm package author url
*/
url?: string;
};
/**
* API license; defaults to npm package license
*/
license?: string;
/**
* Base API path; e.g. the 'v1' in https://myapi.com/v1
*/
basePath?: string;
/**
* Base API prefix slash toggle
* e.g. the 'v1' with toggle true will be https://myapi.comv1
* Otherwise, http://myapi.com/v1
*
* Only available with the specVersion 3
*/
disableBasePathPrefixSlash?: boolean;
/**
* Extend generated swagger spec with this object
* Note that generated properties will always take precedence over what get specified here
*/
spec?: unknown;
/**
* Alter how the spec is merged to generated swagger spec.
* Possible values:
* - 'immediate' is overriding top level elements only thus you can not append a new path or alter an existing value without erasing same level elements.
* - 'recursive' proceed to a deep merge and will concat every branches or override or create new values if needed. @see https://www.npmjs.com/package/merge
* - 'deepmerge' uses `ts-deepmerge` to merge, which will concat object branches and concat arrays as well @see https://www.npmjs.com/package/deepmerge @see https://github.com/voodoocreation/ts-deepmerge
* The default is set to immediate so it is not breaking previous versions.
* @default 'immediate'
*/
specMerging?: 'immediate' | 'recursive' | 'deepmerge';
/**
* Template string for generating operation ids.
* This should be a valid handlebars template and is provided
* with the following context:
* - 'controllerName' - String name of controller class.
* - 'method' - Tsoa.Method object.
*
* @default '{{titleCase method.name}}'
*/
operationIdTemplate?: string;
/**
* Security Definitions Object
* A declaration of the security schemes available to be used in the
* specification. This does not enforce the security schemes on the operations
* and only serves to provide the relevant details for each scheme.
*/
securityDefinitions?: {
[name: string]: Swagger.SecuritySchemes;
};
/**
* Swagger Tags Information for your API
*/
tags?: Swagger.Tag[];
yaml?: boolean;
schemes?: Swagger.Protocol[];
/**
* Enable x-enum-varnames support
* @default false
*/
xEnumVarnames?: boolean;
/**
* Sets a title for inline objects for responses and requestBodies
* This helps to generate more consistent clients
*/
useTitleTagsForInlineObjects?: boolean;
/**
* Applies a default security to the entire API.
* Can be overridden with @Security or @NoSecurity decorators on controllers or methods
*/
rootSecurity?: Swagger.Security[];
}
export interface RoutesConfig {
/**
* Routes directory; generated routes.ts (which contains the generated code wiring up routes using middleware of choice) will be dropped here
*/
routesDir: string;
/**
* Routes filename; the filename of the generated route file ('routes.ts' by default)
*/
routesFileName?: string;
/**
* Avoid writing the generated route file if the existing file is identical (useful to optimize watch processes); false by default
*/
noWriteIfUnchanged?: boolean;
/**
* Base API path; e.g. the '/v1' in https://myapi.com/v1
*/
basePath?: string;
/**
* Middleware provider.
*/
middleware?: 'express' | 'hapi' | 'koa';
/**
* Override the Middleware template
*/
middlewareTemplate?: string;
/**
* IOC module; e.g. './inversify/ioc' where IOC container named `iocContainer` is defined (https://github.com/inversify/InversifyJS)
*/
iocModule?: string;
/**
* Authentication Module for express, hapi and koa
*/
authenticationModule?: string;
/**
* When enabled, the imports in the routes files will have a `.js` extention to support esm.
*
* @default false
*/
esm?: boolean;
bodyCoercion?: boolean;
/**
* When enabled, the imports in the routes files will keep having a `.ts` extention to support the TypeScript 5.7 feature rewriteRelativeImportExtensions.
* @default false
*/
rewriteRelativeImportExtensions?: boolean;
}

3
node_modules/@tsoa/runtime/dist/config.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=config.js.map

1
node_modules/@tsoa/runtime/dist/config.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1 @@
export declare function CustomAttribute(_name: string, _value: string): PropertyDecorator;

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomAttribute = CustomAttribute;
function CustomAttribute(_name, _value) {
return () => {
return;
};
}
//# sourceMappingURL=customAttribute.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"customAttribute.js","sourceRoot":"","sources":["../../src/decorators/customAttribute.ts"],"names":[],"mappings":";;AAAA,0CAIC;AAJD,SAAgB,eAAe,CAAC,KAAa,EAAE,MAAc;IAC3D,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,4 @@
/**
* used to show a method as deprecated on swagger documentation
*/
export declare function Deprecated(): PropertyDecorator & ClassDecorator & ParameterDecorator;

View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Deprecated = Deprecated;
/**
* used to show a method as deprecated on swagger documentation
*/
function Deprecated() {
return () => {
return;
};
}
//# sourceMappingURL=deprecated.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"deprecated.js","sourceRoot":"","sources":["../../src/decorators/deprecated.ts"],"names":[],"mappings":";;AAGA,gCAIC;AAPD;;GAEG;AACH,SAAgB,UAAU;IACxB,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1 @@
export declare function Example<T>(exampleModel: T, exampleLabel?: string): PropertyDecorator;

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Example = Example;
function Example(exampleModel, exampleLabel) {
return () => {
return;
};
}
//# sourceMappingURL=example.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"example.js","sourceRoot":"","sources":["../../src/decorators/example.ts"],"names":[],"mappings":";;AAAA,0BAIC;AAJD,SAAgB,OAAO,CAAI,YAAe,EAAE,YAAqB;IAC/D,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,4 @@
export declare function Extension(_name: string, _value: ExtensionType | ExtensionType[]): PropertyDecorator;
export type ExtensionType = string | number | boolean | null | ExtensionType[] | {
[name: string]: ExtensionType | ExtensionType[];
};

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Extension = Extension;
function Extension(_name, _value) {
return () => {
return;
};
}
//# sourceMappingURL=extension.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../../src/decorators/extension.ts"],"names":[],"mappings":";;AAAA,8BAIC;AAJD,SAAgB,SAAS,CAAC,KAAa,EAAE,MAAuC;IAC9E,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,7 @@
export declare function Options(value?: string): MethodDecorator;
export declare function Get(value?: string): MethodDecorator;
export declare function Post(value?: string): MethodDecorator;
export declare function Put(value?: string): MethodDecorator;
export declare function Patch(value?: string): MethodDecorator;
export declare function Delete(value?: string): MethodDecorator;
export declare function Head(value?: string): MethodDecorator;

45
node_modules/@tsoa/runtime/dist/decorators/methods.js generated vendored Normal file
View File

@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Options = Options;
exports.Get = Get;
exports.Post = Post;
exports.Put = Put;
exports.Patch = Patch;
exports.Delete = Delete;
exports.Head = Head;
function Options(value) {
return () => {
return;
};
}
function Get(value) {
return () => {
return;
};
}
function Post(value) {
return () => {
return;
};
}
function Put(value) {
return () => {
return;
};
}
function Patch(value) {
return () => {
return;
};
}
function Delete(value) {
return () => {
return;
};
}
function Head(value) {
return () => {
return;
};
}
//# sourceMappingURL=methods.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"methods.js","sourceRoot":"","sources":["../../src/decorators/methods.ts"],"names":[],"mappings":";;AAAA,0BAIC;AAED,kBAIC;AAED,oBAIC;AAED,kBAIC;AAED,sBAIC;AAED,wBAIC;AAED,oBAIC;AAxCD,SAAgB,OAAO,CAAC,KAAc;IACpC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,GAAG,CAAC,KAAc;IAChC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,IAAI,CAAC,KAAc;IACjC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,GAAG,CAAC,KAAc;IAChC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,KAAK,CAAC,KAAc;IAClC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,MAAM,CAAC,KAAc;IACnC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,IAAI,CAAC,KAAc;IACjC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,15 @@
type Middleware<T extends CallableFunction | object> = T;
/**
* Install middlewares to the Controller or a specific method.
* @param middlewares
* @returns
*/
export declare function Middlewares<T extends CallableFunction | object>(...mws: Array<Middleware<T>>): ClassDecorator & MethodDecorator;
/**
* Internal function used to retrieve installed middlewares
* in controller and methods (used during routes generation)
* @param target
* @returns list of middlewares
*/
export declare function fetchMiddlewares<T extends CallableFunction | object>(target: any): Array<Middleware<T>>;
export {};

View File

@@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Middlewares = Middlewares;
exports.fetchMiddlewares = fetchMiddlewares;
const TSOA_MIDDLEWARES = Symbol('@tsoa:middlewares');
/**
* Helper function to create a decorator
* that can act as a class and method decorator.
* @param fn a callback function that accepts
* the subject of the decorator
* either the constructor or the
* method
* @returns
*/
function decorator(fn) {
return (...args) => {
// class decorator
if (args.length === 1) {
fn(args[0]);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
}
else if (args.length === 3 && args[2].value) {
// method decorator
const descriptor = args[2];
if (descriptor.value) {
fn(descriptor.value);
}
}
};
}
/**
* Install middlewares to the Controller or a specific method.
* @param middlewares
* @returns
*/
function Middlewares(...mws) {
return decorator(target => {
if (mws) {
const current = fetchMiddlewares(target);
Reflect.defineMetadata(TSOA_MIDDLEWARES, [...current, ...mws], target);
}
});
}
/**
* Internal function used to retrieve installed middlewares
* in controller and methods (used during routes generation)
* @param target
* @returns list of middlewares
*/
function fetchMiddlewares(target) {
return Reflect.getMetadata(TSOA_MIDDLEWARES, target) || [];
}
//# sourceMappingURL=middlewares.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../../src/decorators/middlewares.ts"],"names":[],"mappings":";;AAkCA,kCAOC;AAQD,4CAEC;AAjDD,MAAM,gBAAgB,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAErD;;;;;;;;GAQG;AACH,SAAS,SAAS,CAAC,EAAwB;IACzC,OAAO,CAAC,GAAG,IAAW,EAAE,EAAE;QACxB,kBAAkB;QAClB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACZ,sEAAsE;QACxE,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;YAC9C,mBAAmB;YACnB,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAuB,CAAC;YACjD,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;gBACrB,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,WAAW,CAAsC,GAAG,GAAyB;IAC3F,OAAO,SAAS,CAAC,MAAM,CAAC,EAAE;QACxB,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,OAAO,GAAG,gBAAgB,CAAI,MAAM,CAAC,CAAC;YAC5C,OAAO,CAAC,cAAc,CAAC,gBAAgB,EAAE,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QACzE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAsC,MAAW;IAC/E,OAAO,OAAO,CAAC,WAAW,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;AAC7D,CAAC"}

View File

@@ -0,0 +1 @@
export declare function OperationId(value: string): MethodDecorator;

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OperationId = OperationId;
function OperationId(value) {
return () => {
return;
};
}
//# sourceMappingURL=operationid.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"operationid.js","sourceRoot":"","sources":["../../src/decorators/operationid.ts"],"names":[],"mappings":";;AAAA,kCAIC;AAJD,SAAgB,WAAW,CAAC,KAAa;IACvC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,73 @@
/**
* Inject http Body
* @param {string} [name] properties name in body object
*/
export declare function Body(): ParameterDecorator;
/**
* Inject value from body
*
* @param {string} [name] The name of the body parameter
*/
export declare function BodyProp(name?: string): ParameterDecorator;
/**
* Inject http request
*/
export declare function Request(): ParameterDecorator;
/**
* Inject value from request
*
* @param {name} [name] The name of the request parameter
*/
export declare function RequestProp(name?: string): ParameterDecorator;
/**
* Inject value from Path
*
* @param {string} [name] The name of the path parameter
*/
export declare function Path(name?: string): ParameterDecorator;
/**
* Inject value from query string
*
* @param {string} [name] The name of the query parameter
*/
export declare function Query(name?: string): ParameterDecorator;
/**
* Inject all query values in a single object
*/
export declare function Queries(): ParameterDecorator;
/**
* Inject value from Http header
*
* @param {string} [name] The name of the header parameter
*/
export declare function Header(name?: string): ParameterDecorator;
/**
* Mark parameter as manually injected, which will not be generated
*/
export declare function Inject(): ParameterDecorator;
/**
* Inject uploaded file
*
* @param {string} [name] The name of the uploaded file parameter
*/
export declare function UploadedFile(name?: string): ParameterDecorator;
/**
* Inject uploaded files
*
* @param {string} [name] The name of the uploaded files parameter
*/
export declare function UploadedFiles(name?: string): ParameterDecorator;
/**
* Inject uploaded files
*
* @param {string} [name] The name of the uploaded files parameter
*/
export declare function FormField(name?: string): ParameterDecorator;
/**
* Overrides the default media type of request body.
* Can be used on specific method.
* Can't be used on controller level.
*
* @link https://swagger.io/docs/specification/describing-request-body/
*/
export declare function Consumes(value: string): MethodDecorator;

141
node_modules/@tsoa/runtime/dist/decorators/parameter.js generated vendored Normal file
View File

@@ -0,0 +1,141 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Body = Body;
exports.BodyProp = BodyProp;
exports.Request = Request;
exports.RequestProp = RequestProp;
exports.Path = Path;
exports.Query = Query;
exports.Queries = Queries;
exports.Header = Header;
exports.Inject = Inject;
exports.UploadedFile = UploadedFile;
exports.UploadedFiles = UploadedFiles;
exports.FormField = FormField;
exports.Consumes = Consumes;
/**
* Inject http Body
* @param {string} [name] properties name in body object
*/
function Body() {
return () => {
return;
};
}
/**
* Inject value from body
*
* @param {string} [name] The name of the body parameter
*/
function BodyProp(name) {
return () => {
return;
};
}
/**
* Inject http request
*/
function Request() {
return () => {
return;
};
}
/**
* Inject value from request
*
* @param {name} [name] The name of the request parameter
*/
function RequestProp(name) {
return () => {
return;
};
}
/**
* Inject value from Path
*
* @param {string} [name] The name of the path parameter
*/
function Path(name) {
return () => {
return;
};
}
/**
* Inject value from query string
*
* @param {string} [name] The name of the query parameter
*/
function Query(name) {
return () => {
return;
};
}
/**
* Inject all query values in a single object
*/
function Queries() {
return () => {
return;
};
}
/**
* Inject value from Http header
*
* @param {string} [name] The name of the header parameter
*/
function Header(name) {
return () => {
return;
};
}
/**
* Mark parameter as manually injected, which will not be generated
*/
function Inject() {
return () => {
return;
};
}
/**
* Inject uploaded file
*
* @param {string} [name] The name of the uploaded file parameter
*/
function UploadedFile(name) {
return () => {
return;
};
}
/**
* Inject uploaded files
*
* @param {string} [name] The name of the uploaded files parameter
*/
function UploadedFiles(name) {
return () => {
return;
};
}
/**
* Inject uploaded files
*
* @param {string} [name] The name of the uploaded files parameter
*/
function FormField(name) {
return () => {
return;
};
}
/**
* Overrides the default media type of request body.
* Can be used on specific method.
* Can't be used on controller level.
*
* @link https://swagger.io/docs/specification/describing-request-body/
*/
function Consumes(value) {
return () => {
return;
};
}
//# sourceMappingURL=parameter.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parameter.js","sourceRoot":"","sources":["../../src/decorators/parameter.ts"],"names":[],"mappings":";;AAIA,oBAIC;AAOD,4BAIC;AAKD,0BAIC;AAOD,kCAIC;AAOD,oBAIC;AAOD,sBAIC;AAKD,0BAIC;AAOD,wBAIC;AAKD,wBAIC;AAOD,oCAIC;AAOD,sCAIC;AAOD,8BAIC;AASD,4BAIC;AAxID;;;GAGG;AACH,SAAgB,IAAI;IAClB,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,QAAQ,CAAC,IAAa;IACpC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,OAAO;IACrB,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,WAAW,CAAC,IAAa;IACvC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,IAAI,CAAC,IAAa;IAChC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,KAAK,CAAC,IAAa;IACjC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,OAAO;IACrB,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,MAAM,CAAC,IAAa;IAClC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,MAAM;IACpB,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,YAAY,CAAC,IAAa;IACxC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,aAAa,CAAC,IAAa;IACzC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,SAAS,CAAC,IAAa;IACrC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,QAAQ,CAAC,KAAa;IACpC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,17 @@
import { IsValidHeader } from '../utils/isHeaderType';
import { HttpStatusCodeLiteral, HttpStatusCodeStringLiteral, OtherValidOpenApiHttpStatusCode } from '../interfaces/response';
export declare function SuccessResponse<HeaderType extends IsValidHeader<HeaderType> = object>(name: string | number, description?: string, produces?: string | string[]): MethodDecorator;
export declare function Response<ExampleType, HeaderType extends IsValidHeader<HeaderType> = object>(name: HttpStatusCodeLiteral | HttpStatusCodeStringLiteral | OtherValidOpenApiHttpStatusCode, description?: string, example?: ExampleType, produces?: string | string[]): MethodDecorator & ClassDecorator;
/**
* Inject a library-agnostic responder function that can be used to construct type-checked (usually error-) responses.
*
* The type of the responder function should be annotated `TsoaResponse<Status, Data, Headers>` in order to support OpenAPI documentation.
*/
export declare function Res(): ParameterDecorator;
/**
* Overrides the default media type of response.
* Can be used on controller level or only for specific method
*
* @link https://swagger.io/docs/specification/media-types/
*/
export declare function Produces(value: string): MethodDecorator & ClassDecorator;

38
node_modules/@tsoa/runtime/dist/decorators/response.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SuccessResponse = SuccessResponse;
exports.Response = Response;
exports.Res = Res;
exports.Produces = Produces;
function SuccessResponse(name, description, produces) {
return () => {
return;
};
}
function Response(name, description, example, produces) {
return () => {
return;
};
}
/**
* Inject a library-agnostic responder function that can be used to construct type-checked (usually error-) responses.
*
* The type of the responder function should be annotated `TsoaResponse<Status, Data, Headers>` in order to support OpenAPI documentation.
*/
function Res() {
return () => {
return;
};
}
/**
* Overrides the default media type of response.
* Can be used on controller level or only for specific method
*
* @link https://swagger.io/docs/specification/media-types/
*/
function Produces(value) {
return () => {
return;
};
}
//# sourceMappingURL=response.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/decorators/response.ts"],"names":[],"mappings":";;AAGA,0CAIC;AAED,4BASC;AAOD,kBAIC;AAQD,4BAIC;AAtCD,SAAgB,eAAe,CAAwD,IAAqB,EAAE,WAAoB,EAAE,QAA4B;IAC9J,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,QAAQ,CACtB,IAA2F,EAC3F,WAAoB,EACpB,OAAqB,EACrB,QAA4B;IAE5B,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,GAAG;IACjB,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,QAAQ,CAAC,KAAa;IACpC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,5 @@
export declare function Route(name?: string): ClassDecorator;
/**
* can be used to entirely hide an method from documentation
*/
export declare function Hidden(): ClassDecorator & MethodDecorator & ParameterDecorator;

18
node_modules/@tsoa/runtime/dist/decorators/route.js generated vendored Normal file
View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Route = Route;
exports.Hidden = Hidden;
function Route(name) {
return () => {
return;
};
}
/**
* can be used to entirely hide an method from documentation
*/
function Hidden() {
return () => {
return;
};
}
//# sourceMappingURL=route.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../src/decorators/route.ts"],"names":[],"mappings":";;AAAA,sBAIC;AAKD,wBAIC;AAbD,SAAgB,KAAK,CAAC,IAAa;IACjC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,MAAM;IACpB,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,10 @@
/**
* Can be used to indicate that a method requires no security.
*/
export declare function NoSecurity(): ClassDecorator & MethodDecorator;
/**
* @param {name} security name from securityDefinitions
*/
export declare function Security(name: string | {
[name: string]: string[];
}, scopes?: string[]): ClassDecorator & MethodDecorator;

21
node_modules/@tsoa/runtime/dist/decorators/security.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NoSecurity = NoSecurity;
exports.Security = Security;
/**
* Can be used to indicate that a method requires no security.
*/
function NoSecurity() {
return () => {
return;
};
}
/**
* @param {name} security name from securityDefinitions
*/
function Security(name, scopes) {
return () => {
return;
};
}
//# sourceMappingURL=security.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/decorators/security.ts"],"names":[],"mappings":";;AAGA,gCAIC;AAKD,4BAIC;AAhBD;;GAEG;AACH,SAAgB,UAAU;IACxB,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAC,IAA2C,EAAE,MAAiB;IACrF,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

1
node_modules/@tsoa/runtime/dist/decorators/tags.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export declare function Tags(...values: string[]): ClassDecorator & MethodDecorator;

9
node_modules/@tsoa/runtime/dist/decorators/tags.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Tags = Tags;
function Tags(...values) {
return () => {
return;
};
}
//# sourceMappingURL=tags.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/decorators/tags.ts"],"names":[],"mappings":";;AAAA,oBAIC;AAJD,SAAgB,IAAI,CAAC,GAAG,MAAgB;IACtC,OAAO,GAAG,EAAE;QACV,OAAO;IACT,CAAC,CAAC;AACJ,CAAC"}

24
node_modules/@tsoa/runtime/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import 'reflect-metadata';
export * from './decorators/deprecated';
export * from './decorators/example';
export * from './decorators/parameter';
export * from './decorators/methods';
export * from './decorators/tags';
export * from './decorators/operationid';
export * from './decorators/route';
export * from './decorators/security';
export * from './decorators/extension';
export * from './decorators/middlewares';
export * from './interfaces/controller';
export * from './interfaces/response';
export * from './interfaces/iocModule';
export * from './interfaces/file';
export * from './decorators/response';
export * from './metadataGeneration/tsoa';
export * from './routeGeneration/templates';
export * from './routeGeneration/templateHelpers';
export * from './routeGeneration/tsoa-route';
export * from './utils/assertNever';
export * from './swagger/swagger';
export * from './config';
export * from './routeGeneration/additionalProps';

41
node_modules/@tsoa/runtime/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,41 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
require("reflect-metadata");
__exportStar(require("./decorators/deprecated"), exports);
__exportStar(require("./decorators/example"), exports);
__exportStar(require("./decorators/parameter"), exports);
__exportStar(require("./decorators/methods"), exports);
__exportStar(require("./decorators/tags"), exports);
__exportStar(require("./decorators/operationid"), exports);
__exportStar(require("./decorators/route"), exports);
__exportStar(require("./decorators/security"), exports);
__exportStar(require("./decorators/extension"), exports);
__exportStar(require("./decorators/middlewares"), exports);
__exportStar(require("./interfaces/controller"), exports);
__exportStar(require("./interfaces/response"), exports);
__exportStar(require("./interfaces/iocModule"), exports);
__exportStar(require("./interfaces/file"), exports);
__exportStar(require("./decorators/response"), exports);
__exportStar(require("./metadataGeneration/tsoa"), exports);
__exportStar(require("./routeGeneration/templates"), exports);
__exportStar(require("./routeGeneration/templateHelpers"), exports);
__exportStar(require("./routeGeneration/tsoa-route"), exports);
__exportStar(require("./utils/assertNever"), exports);
__exportStar(require("./swagger/swagger"), exports);
__exportStar(require("./config"), exports);
__exportStar(require("./routeGeneration/additionalProps"), exports);
//# sourceMappingURL=index.js.map

1
node_modules/@tsoa/runtime/dist/index.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4BAA0B;AAC1B,0DAAwC;AACxC,uDAAqC;AACrC,yDAAuC;AACvC,uDAAqC;AACrC,oDAAkC;AAClC,2DAAyC;AACzC,qDAAmC;AACnC,wDAAsC;AACtC,yDAAuC;AACvC,2DAAyC;AACzC,0DAAwC;AACxC,wDAAsC;AACtC,yDAAuC;AACvC,oDAAkC;AAClC,wDAAsC;AACtC,4DAA0C;AAC1C,8DAA4C;AAC5C,oEAAkD;AAClD,+DAA6C;AAC7C,sDAAoC;AACpC,oDAAkC;AAClC,2CAAyB;AACzB,oEAAkD"}

View File

@@ -0,0 +1,16 @@
import type { OutgoingHttpHeaders } from 'node:http';
type HeaderNames = keyof OutgoingHttpHeaders;
type HeaderValue<H extends HeaderNames> = OutgoingHttpHeaders[H];
export declare class Controller {
private statusCode?;
private headers;
setStatus(statusCode: number): void;
getStatus(): number | undefined;
setHeader<H extends HeaderNames>(name: H, value?: HeaderValue<H>): void;
setHeader(name: string, value?: string | string[]): void;
getHeader(name: string): string | string[] | undefined;
getHeaders(): {
[name: string]: string | string[] | undefined;
};
}
export {};

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Controller = void 0;
class Controller {
constructor() {
this.statusCode = undefined;
this.headers = {};
}
setStatus(statusCode) {
this.statusCode = statusCode;
}
getStatus() {
return this.statusCode;
}
setHeader(name, value) {
this.headers[name] = value;
}
getHeader(name) {
return this.headers[name];
}
getHeaders() {
return this.headers;
}
}
exports.Controller = Controller;
//# sourceMappingURL=controller.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/interfaces/controller.ts"],"names":[],"mappings":";;;AAKA,MAAa,UAAU;IAAvB;QACU,eAAU,GAAY,SAAS,CAAC;QAChC,YAAO,GAAG,EAAuD,CAAC;IAwB5E,CAAC;IAtBQ,SAAS,CAAC,UAAkB;QACjC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAEM,SAAS;QACd,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAKM,SAAS,CAAC,IAAY,EAAE,KAAyB;QACtD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IAC7B,CAAC;IAEM,SAAS,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAEM,UAAU;QACf,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AA1BD,gCA0BC"}

31
node_modules/@tsoa/runtime/dist/interfaces/file.d.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
import { Readable } from 'stream';
/** Object containing file metadata and access information. */
export interface File {
/** Name of the form field associated with this file. */
fieldname: string;
/** Name of the file on the uploader's computer. */
originalname: string;
/**
* Value of the `Content-Transfer-Encoding` header for this file.
* @deprecated since July 2015
* @see RFC 7578, Section 4.7
*/
encoding: string;
/** Value of the `Content-Type` header for this file. */
mimetype: string;
/** Size of the file in bytes. */
size: number;
/**
* A readable stream of this file. Only available to the `_handleFile`
* callback for custom `StorageEngine`s.
*/
stream: Readable;
/** `DiskStorage` only: Directory to which this file has been uploaded. */
destination: string;
/** `DiskStorage` only: Name of this file within `destination`. */
filename: string;
/** `DiskStorage` only: Full path to the uploaded file. */
path: string;
/** `MemoryStorage` only: A Buffer containing the entire file. */
buffer: Buffer;
}

3
node_modules/@tsoa/runtime/dist/interfaces/file.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=file.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/interfaces/file.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,7 @@
export type Newable<T = unknown, TArgs extends unknown[] = any[]> = new (...args: TArgs) => T;
export type ServiceIdentifier<T = unknown> = string | symbol | Newable<T> | Function;
export interface IocContainer {
get<T>(controller: ServiceIdentifier<T>): T;
get<T>(controller: ServiceIdentifier<T>): Promise<T>;
}
export type IocContainerFactory<T = any> = (request: T) => IocContainer;

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=iocModule.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"iocModule.js","sourceRoot":"","sources":["../../src/interfaces/iocModule.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,5 @@
import { IsValidHeader } from '../utils/isHeaderType';
export type HttpStatusCodeLiteral = 100 | 101 | 102 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226 | 300 | 301 | 302 | 303 | 304 | 305 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511;
export type HttpStatusCodeStringLiteral = `${HttpStatusCodeLiteral}`;
export type OtherValidOpenApiHttpStatusCode = '1XX' | '2XX' | '3XX' | '4XX' | '5XX' | 'default';
export type TsoaResponse<T extends HttpStatusCodeLiteral, BodyType, HeaderType extends IsValidHeader<HeaderType> = object> = (status: T, data: BodyType, headers?: HeaderType) => any;

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=response.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/interfaces/response.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,216 @@
import { ExtensionType } from '../decorators/extension';
import type { Swagger } from '../swagger/swagger';
import { Validator } from '..';
export declare namespace Tsoa {
export interface Metadata {
controllers: Controller[];
referenceTypeMap: ReferenceTypeMap;
}
export interface Controller {
location: string;
methods: Method[];
name: string;
path: string;
produces?: string[];
}
export interface Method {
extensions: Extension[];
deprecated?: boolean;
description?: string;
method: 'get' | 'post' | 'put' | 'delete' | 'options' | 'head' | 'patch';
name: string;
parameters: Parameter[];
path: string;
produces?: string[];
consumes?: string;
type: Type;
tags?: string[];
responses: Response[];
successStatus?: number;
security: Security[];
summary?: string;
isHidden: boolean;
operationId?: string;
}
export interface Parameter {
parameterName: string;
example?: Array<{
[exampleName: string]: Swagger.Example3;
}>;
description?: string;
in: 'query' | 'queries' | 'header' | 'path' | 'formData' | 'body' | 'body-prop' | 'request' | 'request-prop' | 'res';
name: string;
required?: boolean;
type: Type;
default?: unknown;
validators: Validators;
deprecated: boolean;
exampleLabels?: Array<string | undefined>;
$ref?: Swagger.BaseSchema;
}
export interface ResParameter extends Response, Parameter {
in: 'res';
description: string;
}
export interface ArrayParameter extends Parameter {
type: ArrayType;
collectionFormat?: 'csv' | 'multi' | 'pipes' | 'ssv' | 'tsv';
}
type AllKeys<T> = T extends any ? keyof T : never;
export type ValidatorKey = AllKeys<Validator>;
export type SchemaValidatorKey = Exclude<ValidatorKey, `is${string}` | 'minDate' | 'maxDate'>;
export type Validators = Partial<Record<ValidatorKey, {
value?: unknown;
errorMsg?: string;
}>>;
export interface Security {
[key: string]: string[];
}
export interface Extension {
key: `x-${string}`;
value: ExtensionType | ExtensionType[];
}
export interface Response {
description: string;
name: string;
produces?: string[];
schema?: Type;
examples?: Array<{
[exampleName: string]: Swagger.Example3;
}>;
exampleLabels?: Array<string | undefined>;
headers?: HeaderType;
}
export interface Property {
default?: unknown;
description?: string;
format?: string;
example?: unknown;
name: string;
type: Type;
required: boolean;
validators: Validators;
deprecated: boolean;
extensions?: Extension[];
}
export type TypeStringLiteral = 'string' | 'boolean' | 'double' | 'float' | 'file' | 'integer' | 'long' | 'enum' | 'array' | 'datetime' | 'date' | 'binary' | 'buffer' | 'byte' | 'void' | 'object' | 'any' | 'refEnum' | 'refObject' | 'refAlias' | 'nestedObjectLiteral' | 'union' | 'intersection' | 'undefined' | 'tuple';
export type RefTypeLiteral = 'refObject' | 'refEnum' | 'refAlias';
export type PrimitiveTypeLiteral = Exclude<TypeStringLiteral, RefTypeLiteral | 'enum' | 'array' | 'void' | 'undefined' | 'nestedObjectLiteral' | 'union' | 'intersection' | 'tuple'>;
export interface TypeBase {
dataType: TypeStringLiteral;
}
export type PrimitiveType = StringType | BooleanType | DoubleType | FloatType | IntegerType | LongType | VoidType | UndefinedType;
/**
* This is one of the possible objects that tsoa creates that helps the code store information about the type it found in the code.
*/
export type Type = PrimitiveType | ObjectsNoPropsType | EnumType | ArrayType | FileType | DateTimeType | DateType | BinaryType | BufferType | ByteType | AnyType | RefEnumType | RefObjectType | RefAliasType | NestedObjectLiteralType | UnionType | IntersectionType | TupleType;
export interface StringType extends TypeBase {
dataType: 'string';
}
export interface BooleanType extends TypeBase {
dataType: 'boolean';
}
/**
* This is the type that occurs when a developer writes `const foo: object = {}` since it can no longer have any properties added to it.
*/
export interface ObjectsNoPropsType extends TypeBase {
dataType: 'object';
}
export interface DoubleType extends TypeBase {
dataType: 'double';
}
export interface FloatType extends TypeBase {
dataType: 'float';
}
export interface IntegerType extends TypeBase {
dataType: 'integer';
}
export interface LongType extends TypeBase {
dataType: 'long';
}
/**
* Not to be confused with `RefEnumType` which is a reusable enum which has a $ref name generated for it. This however, is an inline enum.
*/
export interface EnumType extends TypeBase {
dataType: 'enum';
enums: Array<string | number | boolean | null>;
}
export interface ArrayType extends TypeBase {
dataType: 'array';
elementType: Type;
}
export interface DateType extends TypeBase {
dataType: 'date';
}
export interface FileType extends TypeBase {
dataType: 'file';
}
export interface DateTimeType extends TypeBase {
dataType: 'datetime';
}
export interface BinaryType extends TypeBase {
dataType: 'binary';
}
export interface BufferType extends TypeBase {
dataType: 'buffer';
}
export interface ByteType extends TypeBase {
dataType: 'byte';
}
export interface VoidType extends TypeBase {
dataType: 'void';
}
export interface UndefinedType extends TypeBase {
dataType: 'undefined';
}
export interface AnyType extends TypeBase {
dataType: 'any';
}
export interface NestedObjectLiteralType extends TypeBase {
dataType: 'nestedObjectLiteral';
properties: Property[];
additionalProperties?: Type;
}
export interface RefEnumType extends ReferenceTypeBase {
dataType: 'refEnum';
enums: Array<string | number>;
enumVarnames?: string[];
}
export interface RefObjectType extends ReferenceTypeBase {
dataType: 'refObject';
properties: Property[];
additionalProperties?: Type;
}
export interface RefAliasType extends Omit<Property, 'name' | 'required'>, ReferenceTypeBase {
dataType: 'refAlias';
}
export type ReferenceType = RefEnumType | RefObjectType | RefAliasType;
export interface ReferenceTypeBase extends TypeBase {
description?: string;
dataType: RefTypeLiteral;
refName: string;
example?: unknown;
deprecated: boolean;
}
export interface UnionType extends TypeBase {
dataType: 'union';
types: Type[];
}
export interface IntersectionType extends TypeBase {
dataType: 'intersection';
types: Type[];
}
export interface TupleType extends TypeBase {
dataType: 'tuple';
types: Type[];
restType?: Type;
}
export interface ReferenceTypeMap {
[refName: string]: Tsoa.ReferenceType;
}
export interface MethodsSignatureMap {
[signature: string]: string[];
}
export type HeaderType = Tsoa.NestedObjectLiteralType | Tsoa.RefObjectType;
export {};
}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=tsoa.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"tsoa.js","sourceRoot":"","sources":["../../src/metadataGeneration/tsoa.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,6 @@
import { Config, RoutesConfig } from '../config';
export interface AdditionalProps {
noImplicitAdditionalProperties: Exclude<Config['noImplicitAdditionalProperties'], undefined>;
bodyCoercion: Exclude<RoutesConfig['bodyCoercion'], undefined>;
maxValidationErrorSize?: number;
}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=additionalProps.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"additionalProps.js","sourceRoot":"","sources":["../../src/routeGeneration/additionalProps.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,203 @@
import { AdditionalProps } from './additionalProps';
import { TsoaRoute } from './tsoa-route';
export declare function ValidateParam(property: TsoaRoute.PropertySchema, value: any, generatedModels: TsoaRoute.Models, name: string | undefined, fieldErrors: FieldErrors, isBodyParam: boolean, parent: string | undefined, config: AdditionalProps): any;
export declare class ValidationService {
private readonly models;
private readonly config;
private validationStack;
constructor(models: TsoaRoute.Models, config: AdditionalProps);
ValidateParam(property: TsoaRoute.PropertySchema, rawValue: any, name: string | undefined, fieldErrors: FieldErrors, isBodyParam: boolean, parent?: string): any;
hasCorrectJsType(value: any, type: 'object' | 'boolean' | 'number' | 'string', isBodyParam: boolean): boolean;
validateNestedObjectLiteral(name: string, value: any, fieldErrors: FieldErrors, isBodyParam: boolean, nestedProperties: {
[name: string]: TsoaRoute.PropertySchema;
} | undefined, additionalProperties: TsoaRoute.PropertySchema | boolean | undefined, parent: string): any;
validateInt(name: string, value: any, fieldErrors: FieldErrors, isBodyParam: boolean, validators?: IntegerValidator, parent?: string): number | undefined;
validateFloat(name: string, value: any, fieldErrors: FieldErrors, isBodyParam: boolean, validators?: FloatValidator, parent?: string): number | undefined;
validateEnum(name: string, value: unknown, fieldErrors: FieldErrors, members?: Array<string | number | boolean | null>, parent?: string): unknown;
validateDate(name: string, value: any, fieldErrors: FieldErrors, isBodyParam: boolean, validators?: DateValidator, parent?: string): Date | undefined;
validateDateTime(name: string, value: any, fieldErrors: FieldErrors, isBodyParam: boolean, validators?: DateTimeValidator, parent?: string): Date | undefined;
validateString(name: string, value: any, fieldErrors: FieldErrors, validators?: StringValidator, parent?: string): string | undefined;
validateBool(name: string, value: any, fieldErrors: FieldErrors, isBodyParam: boolean, validators?: BooleanValidator, parent?: string): any;
validateUndefined(name: string, value: any, fieldErrors: FieldErrors, parent?: string): undefined;
validateArray(name: string, value: any[], fieldErrors: FieldErrors, isBodyParam: boolean, schema?: TsoaRoute.PropertySchema, validators?: ArrayValidator, parent?: string): any[] | undefined;
validateBuffer(_name: string, value: string): Buffer<ArrayBuffer>;
validateUnion(name: string, value: any, fieldErrors: FieldErrors, isBodyParam: boolean, property: TsoaRoute.PropertySchema, parent?: string): any;
validateIntersection(name: string, value: any, fieldErrors: FieldErrors, isBodyParam: boolean, subSchemas: TsoaRoute.PropertySchema[] | undefined, parent?: string): any;
private toModelLike;
/**
* combine all schemas once, ignoring order ie
* input: [[value1], [value2]] should be [[value1, value2]]
* not [[value1, value2],[value2, value1]]
* and
* input: [[value1, value2], [value3, value4], [value5, value6]] should be [
* [value1, value3, value5],
* [value1, value3, value6],
* [value1, value4, value5],
* [value1, value4, value6],
* [value2, value3, value5],
* [value2, value3, value6],
* [value2, value4, value5],
* [value2, value4, value6],
* ]
* @param modelSchemass
*/
private selfIntersectionCombinations;
private getAllCombinations;
private combineProperties;
private getExcessPropertiesFor;
validateModel(input: {
name: string;
value: any;
modelDefinition: TsoaRoute.ModelSchema;
fieldErrors: FieldErrors;
isBodyParam: boolean;
parent?: string;
}): any;
/**
* Creates a new ValidationService instance with specific configuration
* @param overrides Configuration overrides
* @returns New ValidationService instance
*/
private createChildValidationService;
/**
* Deep clones an object without using JSON.stringify/parse to avoid:
* 1. Loss of undefined values
* 2. Loss of functions
* 3. Conversion of dates to strings
* 4. Exponential escaping issues with nested objects
*/
private deepClone;
/**
* Adds a summarized error to the fieldErrors object
* @param fieldErrors The errors object to add to
* @param errorKey The key for the error
* @param prefix The error message prefix
* @param subErrors Array of sub-errors to summarize
* @param value The value that failed validation
*/
private addSummarizedError;
/**
* Summarizes validation errors to prevent extremely large error messages
* @param errors Array of field errors from union/intersection validation
* @param maxLength Maximum length of the summarized message
* @returns Summarized error message
*/
private summarizeValidationErrors;
}
export interface IntegerValidator {
isInt?: {
errorMsg?: string;
};
isLong?: {
errorMsg?: string;
};
minimum?: {
value: number;
errorMsg?: string;
};
maximum?: {
value: number;
errorMsg?: string;
};
}
export interface FloatValidator {
isFloat?: {
errorMsg?: string;
};
isDouble?: {
errorMsg?: string;
};
minimum?: {
value: number;
errorMsg?: string;
};
maximum?: {
value: number;
errorMsg?: string;
};
}
export interface DateValidator {
isDate?: {
errorMsg?: string;
};
minDate?: {
value: string;
errorMsg?: string;
};
maxDate?: {
value: string;
errorMsg?: string;
};
}
export interface DateTimeValidator {
isDateTime?: {
errorMsg?: string;
};
minDate?: {
value: string;
errorMsg?: string;
};
maxDate?: {
value: string;
errorMsg?: string;
};
}
export interface StringValidator {
isString?: {
errorMsg?: string;
};
minLength?: {
value: number;
errorMsg?: string;
};
maxLength?: {
value: number;
errorMsg?: string;
};
pattern?: {
value: string;
errorMsg?: string;
};
title?: {
value: string;
errorMsg?: string;
};
}
export interface BooleanValidator {
isBoolean?: {
errorMsg?: string;
};
}
export interface ArrayValidator {
isArray?: {
errorMsg?: string;
};
minItems?: {
value: number;
errorMsg?: string;
};
maxItems?: {
value: number;
errorMsg?: string;
};
uniqueItems?: {
errorMsg?: string;
};
}
export type Validator = IntegerValidator | FloatValidator | DateValidator | DateTimeValidator | StringValidator | BooleanValidator | ArrayValidator;
export interface FieldErrors {
[name: string]: {
message: string;
value?: any;
};
}
export interface Exception extends Error {
status: number;
}
export declare class ValidateError extends Error implements Exception {
fields: FieldErrors;
message: string;
status: number;
name: string;
constructor(fields: FieldErrors, message: string);
}

View File

@@ -0,0 +1,855 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidateError = exports.ValidationService = void 0;
exports.ValidateParam = ValidateParam;
const validator_1 = __importDefault(require("validator"));
const assertNever_1 = require("../utils/assertNever");
const tsoa_route_1 = require("./tsoa-route");
// for backwards compatibility with custom templates
function ValidateParam(property, value, generatedModels, name = '', fieldErrors, isBodyParam, parent = '', config) {
return new ValidationService(generatedModels, config).ValidateParam(property, value, name, fieldErrors, isBodyParam, parent);
}
class ValidationService {
constructor(models, config) {
this.models = models;
this.config = config;
this.validationStack = new Set();
}
ValidateParam(property, rawValue, name = '', fieldErrors, isBodyParam, parent = '') {
let value = rawValue;
// If undefined is allowed type, we can move to value validation
if (value === undefined && property.dataType !== 'undefined') {
// If there's either default value or datatype is union with undefined valid, we can just set it and move to validation
if (property.default !== undefined || (property.dataType === 'union' && property.subSchemas?.some(p => p.dataType === 'undefined'))) {
value = property.default;
}
else if (property.required) {
// If value can be typed as undefined, there's no need to check mandatoriness here.
let message = `'${name}' is required`;
if (property.validators) {
const validators = property.validators;
Object.keys(validators).forEach((key) => {
const errorMsg = validators[key]?.errorMsg;
if (key.startsWith('is') && errorMsg) {
message = errorMsg;
}
});
}
fieldErrors[parent + name] = {
message,
value,
};
return;
}
else {
return value;
}
}
switch (property.dataType) {
case 'string':
return this.validateString(name, value, fieldErrors, property.validators, parent);
case 'boolean':
return this.validateBool(name, value, fieldErrors, isBodyParam, property.validators, parent);
case 'integer':
case 'long':
return this.validateInt(name, value, fieldErrors, isBodyParam, property.validators, parent);
case 'float':
case 'double':
return this.validateFloat(name, value, fieldErrors, isBodyParam, property.validators, parent);
case 'enum':
return this.validateEnum(name, value, fieldErrors, property.enums, parent);
case 'array':
return this.validateArray(name, value, fieldErrors, isBodyParam, property.array, property.validators, parent);
case 'date':
return this.validateDate(name, value, fieldErrors, isBodyParam, property.validators, parent);
case 'datetime':
return this.validateDateTime(name, value, fieldErrors, isBodyParam, property.validators, parent);
case 'buffer':
return this.validateBuffer(name, value);
case 'union':
return this.validateUnion(name, value, fieldErrors, isBodyParam, property, parent);
case 'intersection':
return this.validateIntersection(name, value, fieldErrors, isBodyParam, property.subSchemas, parent);
case 'undefined':
return this.validateUndefined(name, value, fieldErrors, parent);
case 'any':
return value;
case 'nestedObjectLiteral':
return this.validateNestedObjectLiteral(name, value, fieldErrors, isBodyParam, property.nestedProperties, property.additionalProperties, parent);
default:
if (property.ref) {
// Detect circular references to prevent stack overflow
const refPath = `${parent}${name}:${property.ref}`;
if (this.validationStack.has(refPath)) {
return value;
}
this.validationStack.add(refPath);
try {
return this.validateModel({ name, value, modelDefinition: this.models[property.ref], fieldErrors, isBodyParam, parent });
}
finally {
this.validationStack.delete(refPath);
}
}
return value;
}
}
hasCorrectJsType(value, type, isBodyParam) {
return !isBodyParam || this.config.bodyCoercion || typeof value === type;
}
validateNestedObjectLiteral(name, value, fieldErrors, isBodyParam, nestedProperties, additionalProperties, parent) {
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
fieldErrors[parent + name] = {
message: `invalid object`,
value,
};
return;
}
const previousErrors = Object.keys(fieldErrors).length;
if (!nestedProperties) {
throw new Error('internal tsoa error: ' +
'the metadata that was generated should have had nested property schemas since its for a nested object,' +
'however it did not. ' +
'Please file an issue with tsoa at https://github.com/lukeautry/tsoa/issues');
}
const propHandling = this.config.noImplicitAdditionalProperties;
if (propHandling !== 'ignore') {
const excessProps = this.getExcessPropertiesFor({ dataType: 'refObject', properties: nestedProperties, additionalProperties }, Object.keys(value));
if (excessProps.length > 0) {
if (propHandling === 'silently-remove-extras') {
excessProps.forEach(excessProp => {
delete value[excessProp];
});
}
if (propHandling === 'throw-on-extras') {
fieldErrors[parent + name] = {
message: `"${excessProps.join(',')}" is an excess property and therefore is not allowed`,
value: excessProps.reduce((acc, propName) => ({ [propName]: value[propName], ...acc }), {}),
};
}
}
}
Object.keys(nestedProperties).forEach(key => {
const validatedProp = this.ValidateParam(nestedProperties[key], value[key], key, fieldErrors, isBodyParam, parent + name + '.');
// Add value from validator if it's not undefined or if value is required and unfedined is valid type
if (validatedProp !== undefined || (nestedProperties[key].dataType === 'undefined' && nestedProperties[key].required)) {
value[key] = validatedProp;
}
});
if (typeof additionalProperties === 'object' && typeof value === 'object') {
const keys = Object.keys(value).filter(key => typeof nestedProperties[key] === 'undefined');
keys.forEach(key => {
const validatedProp = this.ValidateParam(additionalProperties, value[key], key, fieldErrors, isBodyParam, parent + name + '.');
// Add value from validator if it's not undefined or if value is required and unfedined is valid type
if (validatedProp !== undefined || (additionalProperties.dataType === 'undefined' && additionalProperties.required)) {
value[key] = validatedProp;
}
});
}
if (Object.keys(fieldErrors).length > previousErrors) {
return;
}
return value;
}
validateInt(name, value, fieldErrors, isBodyParam, validators, parent = '') {
if (!this.hasCorrectJsType(value, 'number', isBodyParam) || !validator_1.default.isInt(String(value))) {
let message = `invalid integer number`;
if (validators) {
if (validators.isInt && validators.isInt.errorMsg) {
message = validators.isInt.errorMsg;
}
if (validators.isLong && validators.isLong.errorMsg) {
message = validators.isLong.errorMsg;
}
}
fieldErrors[parent + name] = {
message,
value,
};
return;
}
const numberValue = validator_1.default.toInt(String(value), 10);
if (!validators) {
return numberValue;
}
if (validators.minimum && validators.minimum.value !== undefined) {
if (validators.minimum.value > numberValue) {
fieldErrors[parent + name] = {
message: validators.minimum.errorMsg || `min ${validators.minimum.value}`,
value,
};
return;
}
}
if (validators.maximum && validators.maximum.value !== undefined) {
if (validators.maximum.value < numberValue) {
fieldErrors[parent + name] = {
message: validators.maximum.errorMsg || `max ${validators.maximum.value}`,
value,
};
return;
}
}
return numberValue;
}
validateFloat(name, value, fieldErrors, isBodyParam, validators, parent = '') {
if (!this.hasCorrectJsType(value, 'number', isBodyParam) || !validator_1.default.isFloat(String(value))) {
let message = 'invalid float number';
if (validators) {
if (validators.isFloat && validators.isFloat.errorMsg) {
message = validators.isFloat.errorMsg;
}
if (validators.isDouble && validators.isDouble.errorMsg) {
message = validators.isDouble.errorMsg;
}
}
fieldErrors[parent + name] = {
message,
value,
};
return;
}
const numberValue = validator_1.default.toFloat(String(value));
if (!validators) {
return numberValue;
}
if (validators.minimum && validators.minimum.value !== undefined) {
if (validators.minimum.value > numberValue) {
fieldErrors[parent + name] = {
message: validators.minimum.errorMsg || `min ${validators.minimum.value}`,
value,
};
return;
}
}
if (validators.maximum && validators.maximum.value !== undefined) {
if (validators.maximum.value < numberValue) {
fieldErrors[parent + name] = {
message: validators.maximum.errorMsg || `max ${validators.maximum.value}`,
value,
};
return;
}
}
return numberValue;
}
validateEnum(name, value, fieldErrors, members, parent = '') {
if (!members || members.length === 0) {
fieldErrors[parent + name] = {
message: 'no member',
value,
};
return;
}
const enumMatchIndex = members.map(member => String(member)).findIndex(member => validator_1.default.equals(member, String(value)));
if (enumMatchIndex === -1) {
const membersInQuotes = members.map(member => (typeof member === 'string' ? `'${member}'` : String(member)));
fieldErrors[parent + name] = {
message: `should be one of the following; [${membersInQuotes.join(',')}]`,
value,
};
return;
}
return members[enumMatchIndex];
}
validateDate(name, value, fieldErrors, isBodyParam, validators, parent = '') {
if (!this.hasCorrectJsType(value, 'string', isBodyParam) || !validator_1.default.isISO8601(String(value), { strict: true })) {
const message = validators && validators.isDate && validators.isDate.errorMsg ? validators.isDate.errorMsg : `invalid ISO 8601 date format, i.e. YYYY-MM-DD`;
fieldErrors[parent + name] = {
message,
value,
};
return;
}
const dateValue = new Date(String(value));
if (!validators) {
return dateValue;
}
if (validators.minDate && validators.minDate.value) {
const minDate = new Date(validators.minDate.value);
if (minDate.getTime() > dateValue.getTime()) {
fieldErrors[parent + name] = {
message: validators.minDate.errorMsg || `minDate '${validators.minDate.value}'`,
value,
};
return;
}
}
if (validators.maxDate && validators.maxDate.value) {
const maxDate = new Date(validators.maxDate.value);
if (maxDate.getTime() < dateValue.getTime()) {
fieldErrors[parent + name] = {
message: validators.maxDate.errorMsg || `maxDate '${validators.maxDate.value}'`,
value,
};
return;
}
}
return dateValue;
}
validateDateTime(name, value, fieldErrors, isBodyParam, validators, parent = '') {
if (!this.hasCorrectJsType(value, 'string', isBodyParam) || !validator_1.default.isISO8601(String(value), { strict: true })) {
const message = validators && validators.isDateTime && validators.isDateTime.errorMsg ? validators.isDateTime.errorMsg : `invalid ISO 8601 datetime format, i.e. YYYY-MM-DDTHH:mm:ss`;
fieldErrors[parent + name] = {
message,
value,
};
return;
}
const datetimeValue = new Date(String(value));
if (!validators) {
return datetimeValue;
}
if (validators.minDate && validators.minDate.value) {
const minDate = new Date(validators.minDate.value);
if (minDate.getTime() > datetimeValue.getTime()) {
fieldErrors[parent + name] = {
message: validators.minDate.errorMsg || `minDate '${validators.minDate.value}'`,
value,
};
return;
}
}
if (validators.maxDate && validators.maxDate.value) {
const maxDate = new Date(validators.maxDate.value);
if (maxDate.getTime() < datetimeValue.getTime()) {
fieldErrors[parent + name] = {
message: validators.maxDate.errorMsg || `maxDate '${validators.maxDate.value}'`,
value,
};
return;
}
}
return datetimeValue;
}
validateString(name, value, fieldErrors, validators, parent = '') {
if (typeof value !== 'string') {
const message = validators && validators.isString && validators.isString.errorMsg ? validators.isString.errorMsg : `invalid string value`;
fieldErrors[parent + name] = {
message,
value,
};
return;
}
const stringValue = String(value);
if (!validators) {
return stringValue;
}
if (validators.minLength && validators.minLength.value !== undefined) {
if (validators.minLength.value > stringValue.length) {
fieldErrors[parent + name] = {
message: validators.minLength.errorMsg || `minLength ${validators.minLength.value}`,
value,
};
return;
}
}
if (validators.maxLength && validators.maxLength.value !== undefined) {
if (validators.maxLength.value < stringValue.length) {
fieldErrors[parent + name] = {
message: validators.maxLength.errorMsg || `maxLength ${validators.maxLength.value}`,
value,
};
return;
}
}
if (validators.pattern && validators.pattern.value) {
if (!validator_1.default.matches(String(stringValue), validators.pattern.value)) {
fieldErrors[parent + name] = {
message: validators.pattern.errorMsg || `Not match in '${validators.pattern.value}'`,
value,
};
return;
}
}
return stringValue;
}
validateBool(name, value, fieldErrors, isBodyParam, validators, parent = '') {
if (value === true || value === false) {
return value;
}
if (!isBodyParam || this.config.bodyCoercion === true) {
if (value === undefined || value === null) {
return false;
}
if (String(value).toLowerCase() === 'true') {
return true;
}
if (String(value).toLowerCase() === 'false') {
return false;
}
}
const message = validators && validators.isBoolean && validators.isBoolean.errorMsg ? validators.isBoolean.errorMsg : `invalid boolean value`;
fieldErrors[parent + name] = {
message,
value,
};
return;
}
validateUndefined(name, value, fieldErrors, parent = '') {
if (value === undefined) {
return undefined;
}
const message = 'invalid undefined value';
fieldErrors[parent + name] = {
message,
value,
};
return;
}
validateArray(name, value, fieldErrors, isBodyParam, schema, validators, parent = '') {
if ((isBodyParam && this.config.bodyCoercion === false && !Array.isArray(value)) || !schema || value === undefined) {
const message = validators && validators.isArray && validators.isArray.errorMsg ? validators.isArray.errorMsg : `invalid array`;
fieldErrors[parent + name] = {
message,
value,
};
return;
}
let arrayValue = [];
const previousErrors = Object.keys(fieldErrors).length;
if (Array.isArray(value)) {
arrayValue = value.map((elementValue, index) => {
return this.ValidateParam(schema, elementValue, `$${index}`, fieldErrors, isBodyParam, name + '.');
});
}
else {
arrayValue = [this.ValidateParam(schema, value, '$0', fieldErrors, isBodyParam, name + '.')];
}
if (Object.keys(fieldErrors).length > previousErrors) {
return;
}
if (!validators) {
return arrayValue;
}
if (validators.minItems && validators.minItems.value) {
if (validators.minItems.value > arrayValue.length) {
fieldErrors[parent + name] = {
message: validators.minItems.errorMsg || `minItems ${validators.minItems.value}`,
value,
};
return;
}
}
if (validators.maxItems && validators.maxItems.value) {
if (validators.maxItems.value < arrayValue.length) {
fieldErrors[parent + name] = {
message: validators.maxItems.errorMsg || `maxItems ${validators.maxItems.value}`,
value,
};
return;
}
}
if (validators.uniqueItems) {
const unique = arrayValue.some((elem, index, arr) => {
const indexOf = arr.indexOf(elem);
return indexOf > -1 && indexOf !== index;
});
if (unique) {
fieldErrors[parent + name] = {
message: validators.uniqueItems.errorMsg || `required unique array`,
value,
};
return;
}
}
return arrayValue;
}
validateBuffer(_name, value) {
return Buffer.from(value);
}
validateUnion(name, value, fieldErrors, isBodyParam, property, parent = '') {
if (!property.subSchemas) {
throw new Error('internal tsoa error: ' +
'the metadata that was generated should have had sub schemas since its for a union, however it did not. ' +
'Please file an issue with tsoa at https://github.com/lukeautry/tsoa/issues');
}
const subFieldErrors = [];
for (const subSchema of property.subSchemas) {
const subFieldError = {};
// Clean value if it's not undefined or use undefined directly if it's undefined.
// Value can be undefined if undefined is allowed datatype of the union
const validateableValue = value !== undefined ? this.deepClone(value) : value;
const cleanValue = this.ValidateParam({ ...subSchema, validators: { ...property.validators, ...subSchema.validators } }, validateableValue, name, subFieldError, isBodyParam, parent);
subFieldErrors.push(subFieldError);
if (Object.keys(subFieldError).length === 0) {
return cleanValue;
}
}
this.addSummarizedError(fieldErrors, parent + name, 'Could not match the union against any of the items. Issues: ', subFieldErrors, value);
return;
}
validateIntersection(name, value, fieldErrors, isBodyParam, subSchemas, parent = '') {
if (!subSchemas) {
throw new Error('internal tsoa error: ' +
'the metadata that was generated should have had sub schemas since its for a intersection, however it did not. ' +
'Please file an issue with tsoa at https://github.com/lukeautry/tsoa/issues');
}
const subFieldErrors = [];
let cleanValues = {};
subSchemas.forEach(subSchema => {
const subFieldError = {};
const cleanValue = this.createChildValidationService({
noImplicitAdditionalProperties: 'silently-remove-extras',
}).ValidateParam(subSchema, this.deepClone(value), name, subFieldError, isBodyParam, parent);
cleanValues = {
...cleanValues,
...cleanValue,
};
subFieldErrors.push(subFieldError);
});
const filtered = subFieldErrors.filter(subFieldError => Object.keys(subFieldError).length !== 0);
if (filtered.length > 0) {
this.addSummarizedError(fieldErrors, parent + name, 'Could not match the intersection against every type. Issues: ', filtered, value);
return;
}
const schemas = this.selfIntersectionCombinations(subSchemas.map(subSchema => this.toModelLike(subSchema)));
const getRequiredPropError = (schema) => {
const requiredPropError = {};
this.createChildValidationService({
noImplicitAdditionalProperties: 'ignore',
}).validateModel({
name,
value: this.deepClone(value),
modelDefinition: schema,
fieldErrors: requiredPropError,
isBodyParam,
});
return requiredPropError;
};
const schemasWithRequiredProps = schemas.filter(schema => Object.keys(getRequiredPropError(schema)).length === 0);
if (this.config.noImplicitAdditionalProperties === 'ignore') {
return { ...value, ...cleanValues };
}
if (this.config.noImplicitAdditionalProperties === 'silently-remove-extras') {
if (schemasWithRequiredProps.length > 0) {
return cleanValues;
}
else {
fieldErrors[parent + name] = {
message: `Could not match intersection against any of the possible combinations: ${JSON.stringify(schemas.map(s => Object.keys(s.properties)))}`,
value,
};
return;
}
}
if (schemasWithRequiredProps.length > 0 && schemasWithRequiredProps.some(schema => this.getExcessPropertiesFor(schema, Object.keys(value)).length === 0)) {
return cleanValues;
}
else {
fieldErrors[parent + name] = {
message: `Could not match intersection against any of the possible combinations: ${JSON.stringify(schemas.map(s => Object.keys(s.properties)))}`,
value,
};
return;
}
}
toModelLike(schema) {
if (schema.ref) {
const model = this.models[schema.ref];
if (model.dataType === 'refObject') {
return [model];
}
else if (model.dataType === 'refAlias') {
return [...this.toModelLike(model.type)];
}
else if (model.dataType === 'refEnum') {
throw new Error(`Can't transform an enum into a model like structure because it does not have properties.`);
}
else {
return (0, assertNever_1.assertNever)(model);
}
}
else if (schema.nestedProperties) {
return [{ dataType: 'refObject', properties: schema.nestedProperties, additionalProperties: schema.additionalProperties }];
}
else if (schema.subSchemas && schema.dataType === 'intersection') {
const modelss = schema.subSchemas.map(subSchema => this.toModelLike(subSchema));
return this.selfIntersectionCombinations(modelss);
}
else if (schema.subSchemas && schema.dataType === 'union') {
const modelss = schema.subSchemas.map(subSchema => this.toModelLike(subSchema));
return modelss.reduce((acc, models) => [...acc, ...models], []);
}
else {
// There are no properties to check for excess here.
return [{ dataType: 'refObject', properties: {}, additionalProperties: false }];
}
}
/**
* combine all schemas once, ignoring order ie
* input: [[value1], [value2]] should be [[value1, value2]]
* not [[value1, value2],[value2, value1]]
* and
* input: [[value1, value2], [value3, value4], [value5, value6]] should be [
* [value1, value3, value5],
* [value1, value3, value6],
* [value1, value4, value5],
* [value1, value4, value6],
* [value2, value3, value5],
* [value2, value3, value6],
* [value2, value4, value5],
* [value2, value4, value6],
* ]
* @param modelSchemass
*/
selfIntersectionCombinations(modelSchemass) {
const res = [];
// Picks one schema from each sub-array
const combinations = this.getAllCombinations(modelSchemass);
for (const combination of combinations) {
// Combine all schemas of this combination
let currentCollector = { ...combination[0] };
for (let subSchemaIdx = 1; subSchemaIdx < combination.length; subSchemaIdx++) {
currentCollector = { ...this.combineProperties(currentCollector, combination[subSchemaIdx]) };
}
res.push(currentCollector);
}
return res;
}
getAllCombinations(arrays) {
function combine(current, index) {
if (index === arrays.length) {
result.push(current.slice());
return;
}
for (let i = 0; i < arrays[index].length; i++) {
current.push(arrays[index][i]);
combine(current, index + 1);
current.pop();
}
}
const result = [];
combine([], 0);
return result;
}
combineProperties(a, b) {
return { dataType: 'refObject', properties: { ...a.properties, ...b.properties }, additionalProperties: a.additionalProperties || b.additionalProperties || false };
}
getExcessPropertiesFor(modelDefinition, properties) {
const modelProperties = new Set(Object.keys(modelDefinition.properties));
if (modelDefinition.additionalProperties) {
return [];
}
else if (this.config.noImplicitAdditionalProperties === 'ignore') {
return [];
}
else {
return [...properties].filter(property => !modelProperties.has(property));
}
}
validateModel(input) {
const { name, value, modelDefinition, fieldErrors, isBodyParam, parent = '' } = input;
const previousErrors = Object.keys(fieldErrors).length;
if (modelDefinition) {
if (modelDefinition.dataType === 'refEnum') {
return this.validateEnum(name, value, fieldErrors, modelDefinition.enums, parent);
}
if (modelDefinition.dataType === 'refAlias') {
return this.ValidateParam(modelDefinition.type, value, name, fieldErrors, isBodyParam, parent);
}
const fieldPath = parent + name;
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
fieldErrors[fieldPath] = {
message: `invalid object`,
value,
};
return;
}
const properties = modelDefinition.properties || {};
const keysOnPropertiesModelDefinition = new Set(Object.keys(properties));
const allPropertiesOnData = new Set(Object.keys(value));
Object.entries(properties).forEach(([key, property]) => {
const validatedParam = this.ValidateParam(property, value[key], key, fieldErrors, isBodyParam, fieldPath + '.');
// Add value from validator if it's not undefined or if value is required and unfedined is valid type
if (validatedParam !== undefined || (property.dataType === 'undefined' && property.required)) {
value[key] = validatedParam;
}
});
const isAnExcessProperty = (objectKeyThatMightBeExcess) => {
return allPropertiesOnData.has(objectKeyThatMightBeExcess) && !keysOnPropertiesModelDefinition.has(objectKeyThatMightBeExcess);
};
const additionalProperties = modelDefinition.additionalProperties;
if (additionalProperties === true || (0, tsoa_route_1.isDefaultForAdditionalPropertiesAllowed)(additionalProperties)) {
// then don't validate any of the additional properties
}
else if (additionalProperties === false) {
Object.keys(value).forEach((key) => {
if (isAnExcessProperty(key)) {
if (this.config.noImplicitAdditionalProperties === 'throw-on-extras') {
fieldErrors[`${fieldPath}.${key}`] = {
message: `"${key}" is an excess property and therefore is not allowed`,
value: key,
};
}
else if (this.config.noImplicitAdditionalProperties === 'silently-remove-extras') {
delete value[key];
}
else if (this.config.noImplicitAdditionalProperties === 'ignore') {
// then it's okay to have additionalProperties
}
else {
(0, assertNever_1.assertNever)(this.config.noImplicitAdditionalProperties);
}
}
});
}
else {
Object.keys(value).forEach((key) => {
if (isAnExcessProperty(key)) {
const validatedValue = this.ValidateParam(additionalProperties, value[key], key, fieldErrors, isBodyParam, fieldPath + '.');
// Add value from validator if it's not undefined or if value is required and unfedined is valid type
if (validatedValue !== undefined || (additionalProperties.dataType === 'undefined' && additionalProperties.required)) {
value[key] = validatedValue;
}
else {
fieldErrors[`${fieldPath}.${key}`] = {
message: `No matching model found in additionalProperties to validate ${key}`,
value: key,
};
}
}
});
}
}
if (Object.keys(fieldErrors).length > previousErrors) {
return;
}
return value;
}
/**
* Creates a new ValidationService instance with specific configuration
* @param overrides Configuration overrides
* @returns New ValidationService instance
*/
createChildValidationService(overrides = {}) {
return new ValidationService(this.models, {
...this.config,
...overrides,
});
}
/**
* Deep clones an object without using JSON.stringify/parse to avoid:
* 1. Loss of undefined values
* 2. Loss of functions
* 3. Conversion of dates to strings
* 4. Exponential escaping issues with nested objects
*/
deepClone(obj) {
// Fast path for primitives
if (obj === null || obj === undefined) {
return obj;
}
const type = typeof obj;
if (type !== 'object') {
return obj;
}
// Handle built-in object types
if (obj instanceof Date) {
return new Date(obj.getTime());
}
if (obj instanceof RegExp) {
return new RegExp(obj.source, obj.flags);
}
if (obj instanceof Array) {
const cloneArr = new Array(obj.length);
for (let i = 0; i < obj.length; i++) {
cloneArr[i] = this.deepClone(obj[i]);
}
return cloneArr;
}
if (Buffer && obj instanceof Buffer) {
return Buffer.from(obj);
}
// Handle plain objects
const cloneObj = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
cloneObj[key] = this.deepClone(obj[key]);
}
}
return cloneObj;
}
/**
* Adds a summarized error to the fieldErrors object
* @param fieldErrors The errors object to add to
* @param errorKey The key for the error
* @param prefix The error message prefix
* @param subErrors Array of sub-errors to summarize
* @param value The value that failed validation
*/
addSummarizedError(fieldErrors, errorKey, prefix, subErrors, value) {
const maxErrorLength = this.config.maxValidationErrorSize ? this.config.maxValidationErrorSize - prefix.length : undefined;
fieldErrors[errorKey] = {
message: `${prefix}${this.summarizeValidationErrors(subErrors, maxErrorLength)}`,
value,
};
}
/**
* Summarizes validation errors to prevent extremely large error messages
* @param errors Array of field errors from union/intersection validation
* @param maxLength Maximum length of the summarized message
* @returns Summarized error message
*/
summarizeValidationErrors(errors, maxLength) {
const effectiveMaxLength = maxLength || this.config.maxValidationErrorSize || 1000;
// If there are no errors, return empty
if (errors.length === 0) {
return '[]';
}
// Start with a count of total errors
const errorCount = errors.length;
const summary = [];
// Try to include first few errors
let currentLength = 0;
let includedErrors = 0;
// Calculate the size of the suffix if we need to truncate
const truncatedSuffix = `,...and ${errorCount} more errors]`;
const reservedSpace = truncatedSuffix.length + 10; // +10 for safety margin
for (const error of errors) {
const errorStr = JSON.stringify(error);
const projectedLength = currentLength + errorStr.length + (summary.length > 0 ? 1 : 0) + 2; // +1 for comma if not first, +2 for brackets
if (projectedLength + reservedSpace < effectiveMaxLength && includedErrors < 3) {
summary.push(errorStr);
currentLength = projectedLength;
includedErrors++;
}
else {
break;
}
}
// Build final message
if (includedErrors < errorCount) {
const result = `[${summary.join(',')},...and ${errorCount - includedErrors} more errors]`;
// Make sure we don't exceed the limit
if (result.length > effectiveMaxLength) {
// If still too long, remove the last error and try again
if (summary.length > 0) {
summary.pop();
includedErrors--;
return `[${summary.join(',')},...and ${errorCount - includedErrors} more errors]`;
}
}
return result;
}
else {
return `[${summary.join(',')}]`;
}
}
}
exports.ValidationService = ValidationService;
class ValidateError extends Error {
constructor(fields, message) {
super(message);
this.fields = fields;
this.message = message;
this.status = 400;
this.name = 'ValidateError';
Object.setPrototypeOf(this, ValidateError.prototype);
}
}
exports.ValidateError = ValidateError;
//# sourceMappingURL=templateHelpers.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,29 @@
import { Request as ExRequest, Response as ExResponse, NextFunction as ExNext } from 'express';
import { Controller } from '../../../interfaces/controller';
import { TsoaRoute } from '../../tsoa-route';
import { TemplateService } from '../templateService';
type ExpressApiHandlerParameters = {
methodName: string;
controller: Controller | object;
response: ExResponse;
next: ExNext;
validatedArgs: any[];
successStatus?: number;
};
type ExpressValidationArgsParameters = {
args: Record<string, TsoaRoute.ParameterSchema>;
request: ExRequest;
response: ExResponse;
};
type ExpressReturnHandlerParameters = {
response: ExResponse;
headers: any;
statusCode?: number;
data?: any;
};
export declare class ExpressTemplateService extends TemplateService<ExpressApiHandlerParameters, ExpressValidationArgsParameters, ExpressReturnHandlerParameters> {
apiHandler(params: ExpressApiHandlerParameters): Promise<void>;
getValidatedArgs(params: ExpressValidationArgsParameters): any[];
protected returnHandler(params: ExpressReturnHandlerParameters): void;
}
export {};

View File

@@ -0,0 +1,118 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpressTemplateService = void 0;
const templateHelpers_1 = require("../../templateHelpers");
const templateService_1 = require("../templateService");
class ExpressTemplateService extends templateService_1.TemplateService {
async apiHandler(params) {
const { methodName, controller, response, validatedArgs, successStatus, next } = params;
try {
const data = await this.buildPromise(methodName, controller, validatedArgs);
let statusCode = successStatus;
let headers;
if (this.isController(controller)) {
headers = controller.getHeaders();
statusCode = controller.getStatus() || statusCode;
}
this.returnHandler({ response, headers, statusCode, data });
}
catch (error) {
return next(error);
}
}
getValidatedArgs(params) {
const { args, request, response } = params;
const fieldErrors = {};
const values = Object.values(args).map(param => {
const name = param.name;
switch (param.in) {
case 'request':
return request;
case 'request-prop': {
const descriptor = Object.getOwnPropertyDescriptor(request, name);
const value = descriptor ? descriptor.value : undefined;
return this.validationService.ValidateParam(param, value, name, fieldErrors, false, undefined);
}
case 'query':
return this.validationService.ValidateParam(param, request.query[name], name, fieldErrors, false, undefined);
case 'queries':
return this.validationService.ValidateParam(param, request.query, name, fieldErrors, false, undefined);
case 'path':
return this.validationService.ValidateParam(param, request.params[name], name, fieldErrors, false, undefined);
case 'header':
return this.validationService.ValidateParam(param, request.header(name), name, fieldErrors, false, undefined);
case 'body': {
const bodyFieldErrors = {};
const bodyArgs = this.validationService.ValidateParam(param, request.body, name, bodyFieldErrors, true, undefined);
Object.keys(bodyFieldErrors).forEach(key => {
fieldErrors[key] = { message: bodyFieldErrors[key].message };
});
return bodyArgs;
}
case 'body-prop': {
const bodyPropFieldErrors = {};
const bodyPropArgs = this.validationService.ValidateParam(param, request.body?.[name], name, bodyPropFieldErrors, true, 'body.');
Object.keys(bodyPropFieldErrors).forEach(key => {
fieldErrors[key] = { message: bodyPropFieldErrors[key].message };
});
return bodyPropArgs;
}
case 'formData': {
const files = Object.values(args).filter(p => p.dataType === 'file' || (p.dataType === 'array' && p.array && p.array.dataType === 'file'));
if ((param.dataType === 'file' || (param.dataType === 'array' && param.array && param.array.dataType === 'file')) && files.length > 0) {
const requestFiles = request.files;
const fileArgs = this.validationService.ValidateParam(param, requestFiles?.[name], name, fieldErrors, false, undefined);
if (param.dataType === 'array') {
return fileArgs;
}
return Array.isArray(fileArgs) && fileArgs.length === 1 ? fileArgs[0] : fileArgs;
}
return this.validationService.ValidateParam(param, request.body?.[name], name, fieldErrors, false, undefined);
}
case 'res':
return (status, data, headers) => {
this.returnHandler({ response, headers, statusCode: status, data });
};
}
});
if (Object.keys(fieldErrors).length > 0) {
throw new templateHelpers_1.ValidateError(fieldErrors, '');
}
return values;
}
returnHandler(params) {
const { response, statusCode, data } = params;
let { headers } = params;
headers = headers || {};
if (response.headersSent) {
return;
}
Object.keys(headers).forEach((name) => {
response.set(name, headers[name]);
});
// Check if the response is marked to be JSON
const isJsonResponse = response.get('Content-Type')?.includes('json') || false;
if (data && typeof data.pipe === 'function' && data.readable && typeof data._read === 'function') {
response.status(statusCode || 200);
data.pipe(response);
}
else if (data !== undefined && (data !== null || isJsonResponse)) {
// allow null response when it is a json response
if (typeof data === 'number' || isJsonResponse) {
// express treats number data as status code so use the json method instead
// or if the response was marked as json then use the json so for example strings are quoted
response.status(statusCode || 200).json(data);
}
else {
// do not use json for every type since internally the send will invoke json if needed
// but for string data it will not quote it, so we can send string as plain/text data
response.status(statusCode || 200).send(data);
}
}
else {
response.status(statusCode || 204).end();
}
}
}
exports.ExpressTemplateService = ExpressTemplateService;
//# sourceMappingURL=expressTemplateService.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,36 @@
import { Request as HRequest, ResponseToolkit as HResponse } from '@hapi/hapi';
import { Controller } from '../../../interfaces/controller';
import { TsoaRoute } from '../../tsoa-route';
import { TemplateService } from '../templateService';
import { AdditionalProps } from '../../additionalProps';
type HapiApiHandlerParameters = {
methodName: string;
controller: Controller | object;
h: HResponse;
validatedArgs: any[];
successStatus?: number;
};
type HapiValidationArgsParameters = {
args: Record<string, TsoaRoute.ParameterSchema>;
request: HRequest;
h: HResponse;
};
type HapiReturnHandlerParameters = {
h: HResponse;
headers: any;
statusCode?: number;
data?: any;
};
export declare class HapiTemplateService extends TemplateService<HapiApiHandlerParameters, HapiValidationArgsParameters, HapiReturnHandlerParameters> {
protected readonly models: TsoaRoute.Models;
protected readonly config: AdditionalProps;
private readonly hapi;
constructor(models: TsoaRoute.Models, config: AdditionalProps, hapi: {
boomify: CallableFunction;
isBoom: CallableFunction;
});
apiHandler(params: HapiApiHandlerParameters): Promise<any>;
getValidatedArgs(params: HapiValidationArgsParameters): any[];
protected returnHandler(params: HapiReturnHandlerParameters): any;
}
export {};

View File

@@ -0,0 +1,117 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HapiTemplateService = void 0;
const templateHelpers_1 = require("../../templateHelpers");
const templateService_1 = require("../templateService");
const hapiTsoaResponsed = Symbol('@tsoa:template_service:hapi:responsed');
class HapiTemplateService extends templateService_1.TemplateService {
constructor(models, config, hapi) {
super(models, config);
this.models = models;
this.config = config;
this.hapi = hapi;
}
async apiHandler(params) {
const { methodName, controller, h, validatedArgs, successStatus } = params;
try {
const data = await this.buildPromise(methodName, controller, validatedArgs);
let statusCode = successStatus;
let headers;
if (this.isController(controller)) {
headers = controller.getHeaders();
statusCode = controller.getStatus() || statusCode;
}
return this.returnHandler({ h, headers, statusCode, data });
}
catch (error) {
if (this.hapi.isBoom(error)) {
throw error;
}
const boomErr = this.hapi.boomify(error instanceof Error ? error : new Error(error.message));
boomErr.output.statusCode = error.status || 500;
boomErr.output.payload = {
name: error.name,
message: error.message,
};
throw boomErr;
}
}
getValidatedArgs(params) {
const { args, request, h } = params;
const errorFields = {};
const values = Object.values(args).map(param => {
const name = param.name;
switch (param.in) {
case 'request':
return request;
case 'request-prop': {
const descriptor = Object.getOwnPropertyDescriptor(request, name);
const value = descriptor ? descriptor.value : undefined;
return this.validationService.ValidateParam(param, value, name, errorFields, false, undefined);
}
case 'query':
return this.validationService.ValidateParam(param, request.query[name], name, errorFields, false, undefined);
case 'queries':
return this.validationService.ValidateParam(param, request.query, name, errorFields, false, undefined);
case 'path':
return this.validationService.ValidateParam(param, request.params[name], name, errorFields, false, undefined);
case 'header':
return this.validationService.ValidateParam(param, request.headers[name], name, errorFields, false, undefined);
case 'body': {
const bodyFieldErrors = {};
const result = this.validationService.ValidateParam(param, request.payload, name, bodyFieldErrors, true, undefined);
Object.keys(bodyFieldErrors).forEach(key => {
errorFields[key] = { message: bodyFieldErrors[key].message };
});
return result;
}
case 'body-prop': {
const descriptor = Object.getOwnPropertyDescriptor(request.payload, name);
const value = descriptor ? descriptor.value : undefined;
const bodyFieldErrors = {};
const result = this.validationService.ValidateParam(param, value, name, bodyFieldErrors, true, 'body.');
Object.keys(bodyFieldErrors).forEach(key => {
errorFields[key] = { message: bodyFieldErrors[key].message };
});
return result;
}
case 'formData': {
const descriptor = Object.getOwnPropertyDescriptor(request.payload, name);
const value = descriptor ? descriptor.value : undefined;
return this.validationService.ValidateParam(param, value, name, errorFields, false, undefined);
}
case 'res':
return (status, data, headers) => {
this.returnHandler({ h, headers, statusCode: status, data });
};
}
});
if (Object.keys(errorFields).length > 0) {
throw new templateHelpers_1.ValidateError(errorFields, '');
}
return values;
}
returnHandler(params) {
const { h, statusCode, data } = params;
let { headers } = params;
headers = headers || {};
const tsoaResponsed = Object.getOwnPropertyDescriptor(h, hapiTsoaResponsed);
if (tsoaResponsed) {
return tsoaResponsed.value;
}
const response = data !== null && data !== undefined ? h.response(data).code(200) : h.response().code(204);
Object.keys(headers).forEach((name) => {
response.header(name, headers[name]);
});
if (statusCode) {
response.code(statusCode);
}
Object.defineProperty(h, hapiTsoaResponsed, {
value: response,
writable: false,
});
return response;
}
}
exports.HapiTemplateService = HapiTemplateService;
//# sourceMappingURL=hapiTemplateService.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
export * from "./templateService";
export * from "./express/expressTemplateService";
export * from "./hapi/hapiTemplateService";
export * from "./koa/koaTemplateService";

View File

@@ -0,0 +1,21 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./templateService"), exports);
__exportStar(require("./express/expressTemplateService"), exports);
__exportStar(require("./hapi/hapiTemplateService"), exports);
__exportStar(require("./koa/koaTemplateService"), exports);
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/routeGeneration/templates/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,mEAAiD;AACjD,6DAA2C;AAC3C,2DAAyC"}

View File

@@ -0,0 +1,29 @@
import type { Context, Next } from 'koa';
import { Controller } from '../../../interfaces/controller';
import { TsoaRoute } from '../../tsoa-route';
import { TemplateService } from '../templateService';
type KoaApiHandlerParameters = {
methodName: string;
controller: Controller | object;
context: Context;
validatedArgs: any[];
successStatus?: number;
};
type KoaValidationArgsParameters = {
args: Record<string, TsoaRoute.ParameterSchema>;
context: Context;
next: Next;
};
type KoaReturnHandlerParameters = {
context: Context;
next?: Next;
headers: any;
statusCode?: number;
data?: any;
};
export declare class KoaTemplateService extends TemplateService<KoaApiHandlerParameters, KoaValidationArgsParameters, KoaReturnHandlerParameters> {
apiHandler(params: KoaApiHandlerParameters): Promise<any>;
getValidatedArgs(params: KoaValidationArgsParameters): any[];
protected returnHandler(params: KoaReturnHandlerParameters): Promise<any> | Context | undefined;
}
export {};

View File

@@ -0,0 +1,116 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KoaTemplateService = void 0;
const templateHelpers_1 = require("../../templateHelpers");
const templateService_1 = require("../templateService");
const koaTsoaResponsed = Symbol('@tsoa:template_service:koa:is_responsed');
class KoaTemplateService extends templateService_1.TemplateService {
async apiHandler(params) {
const { methodName, controller, context, validatedArgs, successStatus } = params;
try {
const data = await this.buildPromise(methodName, controller, validatedArgs);
let statusCode = successStatus;
let headers;
if (this.isController(controller)) {
headers = controller.getHeaders();
statusCode = controller.getStatus() || statusCode;
}
return this.returnHandler({ context, headers, statusCode, data });
}
catch (error) {
context.status = error.status || 500;
context.throw(context.status, error.message, error);
}
}
getValidatedArgs(params) {
const { args, context, next } = params;
const errorFields = {};
const values = Object.values(args).map(param => {
const name = param.name;
switch (param.in) {
case 'request':
return context.request;
case 'request-prop': {
const descriptor = Object.getOwnPropertyDescriptor(context.request, name);
const value = descriptor ? descriptor.value : undefined;
return this.validationService.ValidateParam(param, value, name, errorFields, false, undefined);
}
case 'query':
return this.validationService.ValidateParam(param, context.request.query[name], name, errorFields, false, undefined);
case 'queries':
return this.validationService.ValidateParam(param, context.request.query, name, errorFields, false, undefined);
case 'path':
return this.validationService.ValidateParam(param, context.params[name], name, errorFields, false, undefined);
case 'header':
return this.validationService.ValidateParam(param, context.request.headers[name], name, errorFields, false, undefined);
case 'body': {
const descriptor = Object.getOwnPropertyDescriptor(context.request, 'body');
const value = descriptor ? descriptor.value : undefined;
const bodyFieldErrors = {};
const result = this.validationService.ValidateParam(param, value, name, bodyFieldErrors, true, undefined);
Object.keys(bodyFieldErrors).forEach((key) => {
errorFields[key] = { message: bodyFieldErrors[key].message };
});
return result;
}
case 'body-prop': {
const descriptor = Object.getOwnPropertyDescriptor(context.request, 'body');
const value = descriptor ? descriptor.value[name] : undefined;
const bodyFieldErrors = {};
const result = this.validationService.ValidateParam(param, value, name, bodyFieldErrors, true, 'body.');
Object.keys(bodyFieldErrors).forEach((key) => {
errorFields[key] = { message: bodyFieldErrors[key].message };
});
return result;
}
case 'formData': {
const files = Object.values(args).filter(p => p.dataType === 'file' || (p.dataType === 'array' && p.array && p.array.dataType === 'file'));
const contextRequest = context.request;
if ((param.dataType === 'file' || (param.dataType === 'array' && param.array && param.array.dataType === 'file')) && files.length > 0) {
const fileArgs = this.validationService.ValidateParam(param, contextRequest.files?.[name], name, errorFields, false, undefined);
if (param.dataType === 'array') {
return fileArgs;
}
return Array.isArray(fileArgs) && fileArgs.length === 1 ? fileArgs[0] : fileArgs;
}
return this.validationService.ValidateParam(param, contextRequest.body?.[name], name, errorFields, false, undefined);
}
case 'res':
return async (status, data, headers) => {
await this.returnHandler({ context, headers, statusCode: status, data, next });
};
}
});
if (Object.keys(errorFields).length > 0) {
throw new templateHelpers_1.ValidateError(errorFields, '');
}
return values;
}
returnHandler(params) {
const { context, next, statusCode, data } = params;
let { headers } = params;
headers = headers || {};
const isResponsed = Object.getOwnPropertyDescriptor(context.response, koaTsoaResponsed);
if (!context.headerSent && !isResponsed) {
if (data !== null && data !== undefined) {
context.body = data;
context.status = 200;
}
else {
context.status = 204;
}
if (statusCode) {
context.status = statusCode;
}
context.set(headers);
Object.defineProperty(context.response, koaTsoaResponsed, {
value: true,
writable: false,
});
return next ? next() : context;
}
return undefined;
}
}
exports.KoaTemplateService = KoaTemplateService;
//# sourceMappingURL=koaTemplateService.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
import { Controller } from '../../interfaces/controller';
import { TsoaRoute } from '../tsoa-route';
import { ValidationService } from '../templateHelpers';
import { AdditionalProps } from '../additionalProps';
export declare abstract class TemplateService<ApiHandlerParameters, ValidationArgsParameters, ReturnHandlerParameters> {
protected readonly models: TsoaRoute.Models;
protected readonly config: AdditionalProps;
protected validationService: ValidationService;
constructor(models: TsoaRoute.Models, config: AdditionalProps);
abstract apiHandler(params: ApiHandlerParameters): Promise<any>;
abstract getValidatedArgs(params: ValidationArgsParameters): any[];
protected abstract returnHandler(params: ReturnHandlerParameters): any;
protected isController(object: Controller | object): object is Controller;
protected buildPromise(methodName: string, controller: Controller | object, validatedArgs: any): Promise<PropertyDescriptor>;
}

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemplateService = void 0;
const templateHelpers_1 = require("../templateHelpers");
class TemplateService {
constructor(models, config) {
this.models = models;
this.config = config;
this.validationService = new templateHelpers_1.ValidationService(models, config);
}
isController(object) {
return 'getHeaders' in object && 'getStatus' in object && 'setStatus' in object;
}
buildPromise(methodName, controller, validatedArgs) {
const prototype = Object.getPrototypeOf(controller);
const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
return descriptor.value.apply(controller, validatedArgs);
}
}
exports.TemplateService = TemplateService;
//# sourceMappingURL=templateService.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"templateService.js","sourceRoot":"","sources":["../../../src/routeGeneration/templates/templateService.ts"],"names":[],"mappings":";;;AAEA,wDAAuD;AAGvD,MAAsB,eAAe;IAGnC,YACqB,MAAwB,EACxB,MAAuB;QADvB,WAAM,GAAN,MAAM,CAAkB;QACxB,WAAM,GAAN,MAAM,CAAiB;QAE1C,IAAI,CAAC,iBAAiB,GAAG,IAAI,mCAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC;IAQS,YAAY,CAAC,MAA2B;QAChD,OAAO,YAAY,IAAI,MAAM,IAAI,WAAW,IAAI,MAAM,IAAI,WAAW,IAAI,MAAM,CAAC;IAClF,CAAC;IAES,YAAY,CAAC,UAAkB,EAAE,UAA+B,EAAE,aAAkB;QAC5F,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAC1E,OAAQ,UAAW,CAAC,KAA2C,CAAC,KAAK,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACnG,CAAC;CACF;AAzBD,0CAyBC"}

View File

@@ -0,0 +1,56 @@
import { Tsoa } from './../metadataGeneration/tsoa';
/**
* For Swagger, additionalProperties is implicitly allowed. So use this function to clarify that undefined should be associated with allowing additional properties
* @param test if this is undefined then you should interpret it as a "yes"
*/
export declare function isDefaultForAdditionalPropertiesAllowed(test: TsoaRoute.RefObjectModelSchema['additionalProperties']): test is undefined;
export declare namespace TsoaRoute {
interface Models {
[name: string]: ModelSchema;
}
/**
* This is a convenience type so you can check .properties on the items in the Record without having TypeScript throw a compiler error. That's because this Record can't have enums in it. If you want that, then just use the base interface
*/
interface RefObjectModels extends TsoaRoute.Models {
[refNames: string]: TsoaRoute.RefObjectModelSchema;
}
interface RefEnumModelSchema {
dataType: 'refEnum';
enums: Array<string | number>;
}
interface RefObjectModelSchema {
dataType: 'refObject';
properties: {
[name: string]: PropertySchema;
};
additionalProperties?: boolean | PropertySchema;
}
interface RefTypeAliasModelSchema {
dataType: 'refAlias';
type: PropertySchema;
}
type ModelSchema = RefEnumModelSchema | RefObjectModelSchema | RefTypeAliasModelSchema;
type ValidatorSchema = Tsoa.Validators;
interface PropertySchema {
dataType?: Tsoa.TypeStringLiteral;
ref?: string;
required?: boolean;
array?: PropertySchema;
enums?: Array<string | number | boolean | null>;
type?: PropertySchema;
subSchemas?: PropertySchema[];
validators?: ValidatorSchema;
default?: unknown;
additionalProperties?: boolean | PropertySchema;
nestedProperties?: {
[name: string]: PropertySchema;
};
}
interface ParameterSchema extends PropertySchema {
name: string;
in: string;
}
interface Security {
[key: string]: string[];
}
}

View File

@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isDefaultForAdditionalPropertiesAllowed = isDefaultForAdditionalPropertiesAllowed;
/**
* For Swagger, additionalProperties is implicitly allowed. So use this function to clarify that undefined should be associated with allowing additional properties
* @param test if this is undefined then you should interpret it as a "yes"
*/
function isDefaultForAdditionalPropertiesAllowed(test) {
return test === undefined;
}
//# sourceMappingURL=tsoa-route.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"tsoa-route.js","sourceRoot":"","sources":["../../src/routeGeneration/tsoa-route.ts"],"names":[],"mappings":";;AAMA,0FAEC;AAND;;;GAGG;AACH,SAAgB,uCAAuC,CAAC,IAA4D;IAClH,OAAO,IAAI,KAAK,SAAS,CAAC;AAC5B,CAAC"}

550
node_modules/@tsoa/runtime/dist/swagger/swagger.d.ts generated vendored Normal file
View File

@@ -0,0 +1,550 @@
export declare namespace Swagger {
export type DataType = 'integer' | 'number' | 'boolean' | 'string' | 'array' | 'object' | 'file' | 'undefined';
export type DataFormat = 'int32' | 'int64' | 'float' | 'double' | 'byte' | 'binary' | 'date' | 'date-time' | 'password';
export type Protocol = 'http' | 'https' | 'ws' | 'wss';
export type SupportedSpecMajorVersion = 2 | 3 | 3.1;
export interface Spec {
info: Info;
tags?: Tag[];
externalDocs?: ExternalDocs;
}
export interface Spec2 extends Spec {
swagger: '2.0';
host?: string;
basePath?: string;
schemes?: Protocol[];
consumes?: string[];
produces?: string[];
paths: {
[name: string]: Path;
};
definitions?: {
[name: string]: Schema2;
};
parameters?: {
[name: string]: Parameter2;
};
responses?: {
[name: string]: Response;
};
security?: Security[];
securityDefinitions?: {
[name: string]: SecuritySchemes;
};
}
/**
* Base interface for all OpenAPI 3.x specifications
* Contains fields shared across all 3.x versions
*/
export interface Spec3x extends Spec {
servers: Server[];
}
/**
* OpenAPI 3.0.x specification
*/
export interface Spec30 extends Spec3x {
openapi: '3.0.0';
components: Components;
paths: {
[name: string]: Path3;
};
}
/**
* OpenAPI 3.1.x specification
*/
export interface Spec31 extends Spec3x {
openapi: '3.1.0';
components: Components31;
paths: {
[name: string]: Path31;
};
}
/**
* Union type representing any OpenAPI 3.x specification (3.0 or 3.1)
* Use Spec30 or Spec31 when you know the specific version
*/
export type Spec3 = Spec30 | Spec31;
export interface Path31 {
$ref?: string;
get?: Operation31;
put?: Operation31;
post?: Operation31;
delete?: Operation31;
options?: Operation31;
head?: Operation31;
patch?: Operation31;
parameters?: Parameter31[];
}
export interface Components {
callbacks?: {
[name: string]: unknown;
};
examples?: {
[name: string]: Example3 | string;
};
headers?: {
[name: string]: unknown;
};
links?: {
[name: string]: unknown;
};
parameters?: {
[name: string]: Parameter3;
};
requestBodies?: {
[name: string]: unknown;
};
responses?: {
[name: string]: Response;
};
schemas?: {
[name: string]: Schema3;
};
securitySchemes?: {
[name: string]: SecuritySchemes;
};
}
export interface Components31 extends Omit<Components, 'schemas'> {
schemas?: {
[name: string]: Schema31;
};
}
export interface Server {
url: string;
}
export interface Info {
title: string;
version?: string;
description?: string;
termsOfService?: string;
contact?: Contact;
license?: License;
}
export interface Contact {
name?: string;
email?: string;
url?: string;
}
export interface License {
name: string;
url?: string;
}
export interface ExternalDocs {
url: string;
description?: string;
}
export interface Tag {
name: string;
description?: string;
externalDocs?: ExternalDocs;
}
export interface Example3 {
value: unknown;
summary?: string;
description?: string;
}
export type BaseParameter = {
name: string;
in: 'query' | 'header' | 'path' | 'formData' | 'body' | 'cookie';
required?: boolean;
description?: string;
deprecated?: boolean;
[ext: `x-${string}`]: unknown;
} & Pick<BaseSchema, 'type' | 'items' | 'enum' | 'format' | 'minimum' | 'maximum' | 'minLength' | 'maxLength' | 'pattern'>;
export type BodyParameter = BaseParameter & {
in: 'body';
};
export type FormDataParameter = BaseParameter & {
in: 'formData';
type: DataType;
format?: DataFormat;
collectionFormat?: 'csv' | 'ssv' | 'tsv' | 'pipes' | 'multi';
default?: unknown;
};
type QueryParameter = BaseParameter & {
in: 'query';
type: DataType;
format?: DataFormat;
collectionFormat?: 'csv' | 'ssv' | 'tsv' | 'pipes' | 'multi';
default?: unknown;
};
type PathParameter = BaseParameter & {
in: 'path';
type: DataType;
format?: DataFormat;
default?: unknown;
};
type HeaderParameter = BaseParameter & {
in: 'header';
type: DataType;
format?: DataFormat;
default?: unknown;
};
type Swagger2BaseParameter = BaseParameter & {
schema: Schema2;
};
export type Swagger2BodyParameter = Swagger2BaseParameter & BodyParameter;
export type Swagger2FormDataParameter = Swagger2BaseParameter & FormDataParameter;
export type Swagger2QueryParameter = Swagger2BaseParameter & QueryParameter;
export type Swagger2PathParameter = Swagger2BaseParameter & PathParameter;
export type Swagger2HeaderParameter = Swagger2BaseParameter & HeaderParameter;
export type Parameter2 = Swagger2BodyParameter | Swagger2FormDataParameter | Swagger2QueryParameter | Swagger2PathParameter | Swagger2HeaderParameter;
export function isQueryParameter(parameter: unknown): parameter is Swagger2QueryParameter;
export interface Parameter3 extends BaseParameter {
in: 'query' | 'header' | 'path' | 'cookie';
schema: Schema3;
style?: string;
explode?: boolean;
allowReserved?: boolean;
example?: unknown;
examples?: {
[name: string]: Example3 | string;
};
}
export interface Parameter31 extends Omit<Parameter3, 'schema'> {
schema: Schema31;
}
export interface Path {
$ref?: string;
get?: Operation;
put?: Operation;
post?: Operation;
delete?: Operation;
options?: Operation;
head?: Operation;
patch?: Operation;
parameters?: Parameter2[];
}
export interface Path3 {
$ref?: string;
get?: Operation3;
put?: Operation3;
post?: Operation3;
delete?: Operation3;
options?: Operation3;
head?: Operation3;
patch?: Operation3;
parameters?: Parameter3[];
}
export interface Operation {
tags?: string[];
summary?: string;
description?: string;
externalDocs?: ExternalDocs;
operationId: string;
consumes?: string[];
produces?: string[];
parameters?: Parameter2[];
responses: {
[name: string]: Response;
};
schemes?: Protocol[];
deprecated?: boolean;
security?: Security[];
[key: string]: unknown;
}
export interface Operation3 {
tags?: string[];
summary?: string;
description?: string;
externalDocs?: ExternalDocs;
operationId: string;
consumes?: string[];
parameters?: Parameter3[];
responses: {
[name: string]: Response3;
};
schemes?: Protocol[];
deprecated?: boolean;
security?: Security[];
requestBody?: RequestBody;
[ext: `x-${string}`]: unknown;
}
export interface Operation31 extends Omit<Operation3, 'responses' | 'requestBody' | 'parameters'> {
parameters?: Parameter31[];
requestBody?: RequestBody31;
responses: {
[name: string]: Response31;
};
}
export interface RequestBody {
content: {
[requestMediaType: string]: MediaType;
};
description?: string;
required?: boolean;
}
export interface RequestBody31 {
content: {
[requestMediaType: string]: MediaType31;
};
description?: string;
required?: boolean;
$ref?: string;
summary?: string;
examples?: {
[media: string]: Example3 | string;
};
[ext: `x-${string}`]: unknown;
}
export interface MediaType {
schema?: Schema3;
example?: unknown;
examples?: {
[name: string]: Example3 | string;
};
encoding?: {
[name: string]: unknown;
};
}
export interface MediaType31 {
schema?: Schema31;
example?: unknown;
examples?: {
[name: string]: Example3 | string;
};
encoding?: {
[name: string]: unknown;
};
}
export interface Response {
description: string;
schema?: BaseSchema;
headers?: {
[name: string]: Header;
};
examples?: {
[responseMediaType: string]: {
[exampleName: string]: Example3 | string;
};
};
}
export interface Response3 {
description: string;
content?: {
[responseMediaType: string]: {
schema: Schema3;
examples?: {
[name: string]: Example3 | string;
};
};
};
headers?: {
[name: string]: Header3;
};
}
export interface Response31 {
description: string;
content?: {
[responseMediaType: string]: {
schema?: Schema31;
examples?: {
[name: string]: Example3 | string;
};
example?: unknown;
encoding?: {
[name: string]: unknown;
};
};
};
headers?: {
[name: string]: Header3;
};
links?: {
[name: string]: unknown;
};
}
export interface BaseSchema<P = unknown> {
type?: string;
format?: DataFormat;
$ref?: string;
title?: string;
description?: string;
default?: string | boolean | number | unknown;
multipleOf?: number;
maximum?: number;
exclusiveMaximum?: number;
minimum?: number;
exclusiveMinimum?: number;
maxLength?: number;
minLength?: number;
pattern?: string;
maxItems?: number;
minItems?: number;
uniqueItems?: boolean;
maxProperties?: number;
minProperties?: number;
enum?: Array<boolean | string | number | null>;
'x-enum-varnames'?: string[];
[ext: `x-${string}`]: unknown;
additionalProperties?: boolean | BaseSchema;
properties?: {
[propertyName: string]: P;
};
discriminator?: string;
readOnly?: boolean;
xml?: XML;
externalDocs?: ExternalDocs;
example?: unknown;
required?: string[];
items?: BaseSchema;
}
export interface Schema31 extends Omit<Schema3, 'items' | 'properties' | 'additionalProperties' | 'discriminator' | 'anyOf' | 'allOf'> {
examples?: unknown[];
properties?: {
[key: string]: Schema31;
};
additionalProperties?: boolean | Schema31;
items?: Schema31 | false;
prefixItems?: Schema31[];
contains?: Schema31;
allOf?: Schema31[];
anyOf?: Schema31[];
oneOf?: Schema31[];
not?: Schema31;
propertyNames?: Schema31;
discriminator?: {
propertyName: string;
mapping?: Record<string, string>;
};
}
export interface Schema3 extends Omit<BaseSchema, 'type'> {
type?: DataType;
nullable?: boolean;
anyOf?: BaseSchema[];
allOf?: BaseSchema[];
deprecated?: boolean;
properties?: {
[propertyName: string]: Schema3;
};
}
export interface Schema2 extends BaseSchema {
type?: DataType;
properties?: {
[propertyName: string]: Schema2;
};
['x-nullable']?: boolean;
['x-deprecated']?: boolean;
}
export interface Header {
description?: string;
type: 'string' | 'number' | 'integer' | 'boolean' | 'array';
format?: string;
items?: BaseSchema;
collectionFormat?: 'csv' | 'ssv' | 'tsv' | 'pipes' | 'multi';
default?: string | boolean | number | unknown;
maximum?: number;
exclusiveMaximum?: boolean;
minimum?: number;
exclusiveMinimum?: boolean;
maxLength?: number;
minLength?: number;
pattern?: string;
maxItems?: number;
minItems?: number;
uniqueItems?: boolean;
enum?: Array<string | number | null>;
multipleOf?: number;
}
export interface Header3 {
description?: string;
required?: boolean;
deprecated?: boolean;
allowEmptyValue?: boolean;
style?: string;
explode?: boolean;
allowReserved?: boolean;
schema?: Schema3 | Schema31;
example?: unknown;
examples?: {
[media: string]: Example3 | string;
};
content?: {
[media: string]: {
schema?: Schema3 | Schema31;
example?: unknown;
examples?: {
[name: string]: Example3 | string;
};
};
};
[ext: `x-${string}`]: unknown;
}
export interface XML {
type?: string;
namespace?: string;
prefix?: string;
attribute?: string;
wrapped?: boolean;
}
interface BaseSecurity {
description?: string;
}
export interface ApiKeySecurity extends BaseSecurity {
type: 'apiKey';
name: string;
in: 'query' | 'header';
}
interface BaseOAuthSecurity extends BaseSecurity {
scopes?: OAuthScope;
}
export interface BasicSecurity3 extends BaseSecurity {
type: 'http';
scheme: 'basic';
}
export interface BasicSecurity extends BaseSecurity {
type: 'basic';
}
export interface BearerSecurity3 extends BaseSecurity {
type: 'http';
scheme: 'bearer';
bearerFormat?: string;
}
export interface OpenIDSecurity extends BaseSecurity {
type: 'openIdConnect';
openIdConnectUrl: string;
}
export interface OAuth2Security3 extends BaseSecurity {
type: 'oauth2';
flows: OAuthFlow;
}
export interface OAuth2SecurityFlow3 extends BaseSecurity {
tokenUrl?: string;
authorizationUrl?: string;
scopes?: OAuthScope;
}
export interface OAuth2ImplicitSecurity extends BaseOAuthSecurity {
type: 'oauth2';
description?: string;
flow: 'implicit';
authorizationUrl: string;
}
export interface OAuth2PasswordSecurity extends BaseOAuthSecurity {
type: 'oauth2';
flow: 'password';
tokenUrl: string;
}
export interface OAuth2ApplicationSecurity extends BaseOAuthSecurity {
type: 'oauth2';
flow: 'application';
tokenUrl: string;
}
export interface OAuth2AccessCodeSecurity extends BaseOAuthSecurity {
type: 'oauth2';
flow: 'accessCode';
tokenUrl: string;
authorizationUrl: string;
}
export interface OAuthScope {
[scopeName: string]: string;
}
export type OAuthFlow = {
[flowName in OAuth2FlowTypes]?: OAuth2SecurityFlow3;
};
export type OAuth2FlowTypes = 'authorizationCode' | 'implicit' | 'password' | 'clientCredentials';
export type SecuritySchemes = ApiKeySecurity | BasicSecurity | BasicSecurity3 | BearerSecurity3 | OpenIDSecurity | OAuth2AccessCodeSecurity | OAuth2ApplicationSecurity | OAuth2ImplicitSecurity | OAuth2PasswordSecurity | OAuth2Security3;
export interface Security {
[key: string]: string[];
}
export {};
}

12
node_modules/@tsoa/runtime/dist/swagger/swagger.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Swagger = void 0;
// eslint-disable-next-line @typescript-eslint/no-namespace
var Swagger;
(function (Swagger) {
function isQueryParameter(parameter) {
return typeof parameter === 'object' && parameter !== null && 'in' in parameter && parameter.in === 'query';
}
Swagger.isQueryParameter = isQueryParameter;
})(Swagger || (exports.Swagger = Swagger = {}));
//# sourceMappingURL=swagger.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"swagger.js","sourceRoot":"","sources":["../../src/swagger/swagger.ts"],"names":[],"mappings":";;;AAAA,2DAA2D;AAC3D,IAAiB,OAAO,CA2iBvB;AA3iBD,WAAiB,OAAO;IA0LtB,SAAgB,gBAAgB,CAAC,SAAkB;QACjD,OAAO,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,SAAS,CAAC,EAAE,KAAK,OAAO,CAAC;IAC9G,CAAC;IAFe,wBAAgB,mBAE/B,CAAA;AA+WH,CAAC,EA3iBgB,OAAO,uBAAP,OAAO,QA2iBvB"}

View File

@@ -0,0 +1,4 @@
/**
* This function does exhaustiveness checking to ensure that you have discriminated a union so that no type remains. Use this to get the typescript compiler to help discover cases that were not considered.
*/
export declare function assertNever(value: never): never;

10
node_modules/@tsoa/runtime/dist/utils/assertNever.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.assertNever = assertNever;
/**
* This function does exhaustiveness checking to ensure that you have discriminated a union so that no type remains. Use this to get the typescript compiler to help discover cases that were not considered.
*/
function assertNever(value) {
throw new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);
}
//# sourceMappingURL=assertNever.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"assertNever.js","sourceRoot":"","sources":["../../src/utils/assertNever.ts"],"names":[],"mappings":";;AAGA,kCAEC;AALD;;GAEG;AACH,SAAgB,WAAW,CAAC,KAAY;IACtC,MAAM,IAAI,KAAK,CAAC,yCAAyC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACpF,CAAC"}

View File

@@ -0,0 +1,5 @@
/**
* Checks for a supported header type
* key types can be `number` to support string indexed access types
*/
export type IsValidHeader<Header> = keyof Header extends string | number ? Header[keyof Header] extends string | string[] | undefined ? object : 'Header values must be string or string[]' : 'Header names must be of type string';

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=isHeaderType.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"isHeaderType.js","sourceRoot":"","sources":["../../src/utils/isHeaderType.ts"],"names":[],"mappings":""}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,24 @@
(The MIT License)
Copyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca>
Copyright (c) 2013-2014 Roman Shtylman <shtylman+expressjs@gmail.com>
Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,260 @@
[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/)
**Fast, unopinionated, minimalist web framework for [Node.js](http://nodejs.org).**
**This project has a [Code of Conduct][].**
## Table of contents
* [Installation](#Installation)
* [Features](#Features)
* [Docs & Community](#docs--community)
* [Quick Start](#Quick-Start)
* [Running Tests](#Running-Tests)
* [Philosophy](#Philosophy)
* [Examples](#Examples)
* [Contributing to Express](#Contributing)
* [TC (Technical Committee)](#tc-technical-committee)
* [Triagers](#triagers)
* [License](#license)
[![NPM Version][npm-version-image]][npm-url]
[![NPM Install Size][npm-install-size-image]][npm-install-size-url]
[![NPM Downloads][npm-downloads-image]][npm-downloads-url]
[![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer]
```js
const express = require('express')
const app = express()
app.get('/', function (req, res) {
res.send('Hello World')
})
app.listen(3000)
```
## Installation
This is a [Node.js](https://nodejs.org/en/) module available through the
[npm registry](https://www.npmjs.com/).
Before installing, [download and install Node.js](https://nodejs.org/en/download/).
Node.js 0.10 or higher is required.
If this is a brand new project, make sure to create a `package.json` first with
the [`npm init` command](https://docs.npmjs.com/creating-a-package-json-file).
Installation is done using the
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
```console
$ npm install express
```
Follow [our installing guide](http://expressjs.com/en/starter/installing.html)
for more information.
## Features
* Robust routing
* Focus on high performance
* Super-high test coverage
* HTTP helpers (redirection, caching, etc)
* View system supporting 14+ template engines
* Content negotiation
* Executable for generating applications quickly
## Docs & Community
* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)]
* [#express](https://web.libera.chat/#express) on [Libera Chat](https://libera.chat) IRC
* [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules
* Visit the [Wiki](https://github.com/expressjs/express/wiki)
* [Google Group](https://groups.google.com/group/express-js) for discussion
* [Gitter](https://gitter.im/expressjs/express) for support and discussion
**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x).
## Quick Start
The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below:
Install the executable. The executable's major version will match Express's:
```console
$ npm install -g express-generator@4
```
Create the app:
```console
$ express /tmp/foo && cd /tmp/foo
```
Install dependencies:
```console
$ npm install
```
Start the server:
```console
$ npm start
```
View the website at: http://localhost:3000
## Philosophy
The Express philosophy is to provide small, robust tooling for HTTP servers, making
it a great solution for single page applications, websites, hybrids, or public
HTTP APIs.
Express does not force you to use any specific ORM or template engine. With support for over
14 template engines via [Consolidate.js](https://github.com/tj/consolidate.js),
you can quickly craft your perfect framework.
## Examples
To view the examples, clone the Express repo and install the dependencies:
```console
$ git clone https://github.com/expressjs/express.git --depth 1
$ cd express
$ npm install
```
Then run whichever example you want:
```console
$ node examples/content-negotiation
```
## Contributing
[![Linux Build][github-actions-ci-image]][github-actions-ci-url]
[![Windows Build][appveyor-image]][appveyor-url]
[![Test Coverage][coveralls-image]][coveralls-url]
The Express.js project welcomes all constructive contributions. Contributions take many forms,
from code for bug fixes and enhancements, to additions and fixes to documentation, additional
tests, triaging incoming pull requests and issues, and more!
See the [Contributing Guide](Contributing.md) for more technical details on contributing.
### Security Issues
If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md).
### Running Tests
To run the test suite, first install the dependencies, then run `npm test`:
```console
$ npm install
$ npm test
```
## People
The original author of Express is [TJ Holowaychuk](https://github.com/tj)
[List of all contributors](https://github.com/expressjs/express/graphs/contributors)
### TC (Technical Committee)
* [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him)
* [jonchurch](https://github.com/jonchurch) - **Jon Church**
* [wesleytodd](https://github.com/wesleytodd) - **Wes Todd**
* [LinusU](https://github.com/LinusU) - **Linus Unnebäck**
* [blakeembrey](https://github.com/blakeembrey) - **Blake Embrey**
* [sheplu](https://github.com/sheplu) - **Jean Burellier**
* [crandmck](https://github.com/crandmck) - **Rand McKinney**
* [ctcpip](https://github.com/ctcpip) - **Chris de Almeida**
<details>
<summary>TC emeriti members</summary>
#### TC emeriti members
* [dougwilson](https://github.com/dougwilson) - **Douglas Wilson**
* [hacksparrow](https://github.com/hacksparrow) - **Hage Yaapa**
* [jonathanong](https://github.com/jonathanong) - **jongleberry**
* [niftylettuce](https://github.com/niftylettuce) - **niftylettuce**
* [troygoode](https://github.com/troygoode) - **Troy Goode**
</details>
### Triagers
* [aravindvnair99](https://github.com/aravindvnair99) - **Aravind Nair**
* [carpasse](https://github.com/carpasse) - **Carlos Serrano**
* [CBID2](https://github.com/CBID2) - **Christine Belzie**
* [enyoghasim](https://github.com/enyoghasim) - **David Enyoghasim**
* [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him)
* [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin**
* [0ss](https://github.com/0ss) - **Salah**
* [import-brain](https://github.com/import-brain) - **Eric Cheng** (he/him)
* [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi**
* [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him)
* [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego**
* [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him)
* [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger**
<details>
<summary>Triagers emeriti members</summary>
#### Emeritus Triagers
* [AuggieH](https://github.com/AuggieH) - **Auggie Hudak**
* [G-Rath](https://github.com/G-Rath) - **Gareth Jones**
* [MohammadXroid](https://github.com/MohammadXroid) - **Mohammad Ayashi**
* [NawafSwe](https://github.com/NawafSwe) - **Nawaf Alsharqi**
* [NotMoni](https://github.com/NotMoni) - **Moni**
* [VigneshMurugan](https://github.com/VigneshMurugan) - **Vignesh Murugan**
* [davidmashe](https://github.com/davidmashe) - **David Ashe**
* [digitaIfabric](https://github.com/digitaIfabric) - **David**
* [e-l-i-s-e](https://github.com/e-l-i-s-e) - **Elise Bonner**
* [fed135](https://github.com/fed135) - **Frederic Charette**
* [firmanJS](https://github.com/firmanJS) - **Firman Abdul Hakim**
* [getspooky](https://github.com/getspooky) - **Yasser Ameur**
* [ghinks](https://github.com/ghinks) - **Glenn**
* [ghousemohamed](https://github.com/ghousemohamed) - **Ghouse Mohamed**
* [gireeshpunathil](https://github.com/gireeshpunathil) - **Gireesh Punathil**
* [jake32321](https://github.com/jake32321) - **Jake Reed**
* [jonchurch](https://github.com/jonchurch) - **Jon Church**
* [lekanikotun](https://github.com/lekanikotun) - **Troy Goode**
* [marsonya](https://github.com/marsonya) - **Lekan Ikotun**
* [mastermatt](https://github.com/mastermatt) - **Matt R. Wilson**
* [maxakuru](https://github.com/maxakuru) - **Max Edell**
* [mlrawlings](https://github.com/mlrawlings) - **Michael Rawlings**
* [rodion-arr](https://github.com/rodion-arr) - **Rodion Abdurakhimov**
* [sheplu](https://github.com/sheplu) - **Jean Burellier**
* [tarunyadav1](https://github.com/tarunyadav1) - **Tarun yadav**
* [tunniclm](https://github.com/tunniclm) - **Mike Tunnicliffe**
</details>
## License
[MIT](LICENSE)
[appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/express/master?label=windows
[appveyor-url]: https://ci.appveyor.com/project/dougwilson/express
[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/express/master
[coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master
[github-actions-ci-image]: https://badgen.net/github/checks/expressjs/express/master?label=linux
[github-actions-ci-url]: https://github.com/expressjs/express/actions/workflows/ci.yml
[npm-downloads-image]: https://badgen.net/npm/dm/express
[npm-downloads-url]: https://npmcharts.com/compare/express?minimal=true
[npm-install-size-image]: https://badgen.net/packagephobia/install/express
[npm-install-size-url]: https://packagephobia.com/result?p=express
[npm-url]: https://npmjs.org/package/express
[npm-version-image]: https://badgen.net/npm/v/express
[ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/express/badge
[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/express
[Code of Conduct]: https://github.com/expressjs/express/blob/master/Code-Of-Conduct.md

View File

@@ -0,0 +1,11 @@
/*!
* express
* Copyright(c) 2009-2013 TJ Holowaychuk
* Copyright(c) 2013 Roman Shtylman
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict';
module.exports = require('./lib/express');

View File

@@ -0,0 +1,661 @@
/*!
* express
* Copyright(c) 2009-2013 TJ Holowaychuk
* Copyright(c) 2013 Roman Shtylman
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict';
/**
* Module dependencies.
* @private
*/
var finalhandler = require('finalhandler');
var Router = require('./router');
var methods = require('methods');
var middleware = require('./middleware/init');
var query = require('./middleware/query');
var debug = require('debug')('express:application');
var View = require('./view');
var http = require('http');
var compileETag = require('./utils').compileETag;
var compileQueryParser = require('./utils').compileQueryParser;
var compileTrust = require('./utils').compileTrust;
var deprecate = require('depd')('express');
var flatten = require('array-flatten');
var merge = require('utils-merge');
var resolve = require('path').resolve;
var setPrototypeOf = require('setprototypeof')
/**
* Module variables.
* @private
*/
var hasOwnProperty = Object.prototype.hasOwnProperty
var slice = Array.prototype.slice;
/**
* Application prototype.
*/
var app = exports = module.exports = {};
/**
* Variable for trust proxy inheritance back-compat
* @private
*/
var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default';
/**
* Initialize the server.
*
* - setup default configuration
* - setup default middleware
* - setup route reflection methods
*
* @private
*/
app.init = function init() {
this.cache = {};
this.engines = {};
this.settings = {};
this.defaultConfiguration();
};
/**
* Initialize application configuration.
* @private
*/
app.defaultConfiguration = function defaultConfiguration() {
var env = process.env.NODE_ENV || 'development';
// default settings
this.enable('x-powered-by');
this.set('etag', 'weak');
this.set('env', env);
this.set('query parser', 'extended');
this.set('subdomain offset', 2);
this.set('trust proxy', false);
// trust proxy inherit back-compat
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
configurable: true,
value: true
});
debug('booting in %s mode', env);
this.on('mount', function onmount(parent) {
// inherit trust proxy
if (this.settings[trustProxyDefaultSymbol] === true
&& typeof parent.settings['trust proxy fn'] === 'function') {
delete this.settings['trust proxy'];
delete this.settings['trust proxy fn'];
}
// inherit protos
setPrototypeOf(this.request, parent.request)
setPrototypeOf(this.response, parent.response)
setPrototypeOf(this.engines, parent.engines)
setPrototypeOf(this.settings, parent.settings)
});
// setup locals
this.locals = Object.create(null);
// top-most app is mounted at /
this.mountpath = '/';
// default locals
this.locals.settings = this.settings;
// default configuration
this.set('view', View);
this.set('views', resolve('views'));
this.set('jsonp callback name', 'callback');
if (env === 'production') {
this.enable('view cache');
}
Object.defineProperty(this, 'router', {
get: function() {
throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.');
}
});
};
/**
* lazily adds the base router if it has not yet been added.
*
* We cannot add the base router in the defaultConfiguration because
* it reads app settings which might be set after that has run.
*
* @private
*/
app.lazyrouter = function lazyrouter() {
if (!this._router) {
this._router = new Router({
caseSensitive: this.enabled('case sensitive routing'),
strict: this.enabled('strict routing')
});
this._router.use(query(this.get('query parser fn')));
this._router.use(middleware.init(this));
}
};
/**
* Dispatch a req, res pair into the application. Starts pipeline processing.
*
* If no callback is provided, then default error handlers will respond
* in the event of an error bubbling through the stack.
*
* @private
*/
app.handle = function handle(req, res, callback) {
var router = this._router;
// final handler
var done = callback || finalhandler(req, res, {
env: this.get('env'),
onerror: logerror.bind(this)
});
// no routes
if (!router) {
debug('no routes defined on app');
done();
return;
}
router.handle(req, res, done);
};
/**
* Proxy `Router#use()` to add middleware to the app router.
* See Router#use() documentation for details.
*
* If the _fn_ parameter is an express app, then it will be
* mounted at the _route_ specified.
*
* @public
*/
app.use = function use(fn) {
var offset = 0;
var path = '/';
// default path to '/'
// disambiguate app.use([fn])
if (typeof fn !== 'function') {
var arg = fn;
while (Array.isArray(arg) && arg.length !== 0) {
arg = arg[0];
}
// first arg is the path
if (typeof arg !== 'function') {
offset = 1;
path = fn;
}
}
var fns = flatten(slice.call(arguments, offset));
if (fns.length === 0) {
throw new TypeError('app.use() requires a middleware function')
}
// setup router
this.lazyrouter();
var router = this._router;
fns.forEach(function (fn) {
// non-express app
if (!fn || !fn.handle || !fn.set) {
return router.use(path, fn);
}
debug('.use app under %s', path);
fn.mountpath = path;
fn.parent = this;
// restore .app property on req and res
router.use(path, function mounted_app(req, res, next) {
var orig = req.app;
fn.handle(req, res, function (err) {
setPrototypeOf(req, orig.request)
setPrototypeOf(res, orig.response)
next(err);
});
});
// mounted an app
fn.emit('mount', this);
}, this);
return this;
};
/**
* Proxy to the app `Router#route()`
* Returns a new `Route` instance for the _path_.
*
* Routes are isolated middleware stacks for specific paths.
* See the Route api docs for details.
*
* @public
*/
app.route = function route(path) {
this.lazyrouter();
return this._router.route(path);
};
/**
* Register the given template engine callback `fn`
* as `ext`.
*
* By default will `require()` the engine based on the
* file extension. For example if you try to render
* a "foo.ejs" file Express will invoke the following internally:
*
* app.engine('ejs', require('ejs').__express);
*
* For engines that do not provide `.__express` out of the box,
* or if you wish to "map" a different extension to the template engine
* you may use this method. For example mapping the EJS template engine to
* ".html" files:
*
* app.engine('html', require('ejs').renderFile);
*
* In this case EJS provides a `.renderFile()` method with
* the same signature that Express expects: `(path, options, callback)`,
* though note that it aliases this method as `ejs.__express` internally
* so if you're using ".ejs" extensions you don't need to do anything.
*
* Some template engines do not follow this convention, the
* [Consolidate.js](https://github.com/tj/consolidate.js)
* library was created to map all of node's popular template
* engines to follow this convention, thus allowing them to
* work seamlessly within Express.
*
* @param {String} ext
* @param {Function} fn
* @return {app} for chaining
* @public
*/
app.engine = function engine(ext, fn) {
if (typeof fn !== 'function') {
throw new Error('callback function required');
}
// get file extension
var extension = ext[0] !== '.'
? '.' + ext
: ext;
// store engine
this.engines[extension] = fn;
return this;
};
/**
* Proxy to `Router#param()` with one added api feature. The _name_ parameter
* can be an array of names.
*
* See the Router#param() docs for more details.
*
* @param {String|Array} name
* @param {Function} fn
* @return {app} for chaining
* @public
*/
app.param = function param(name, fn) {
this.lazyrouter();
if (Array.isArray(name)) {
for (var i = 0; i < name.length; i++) {
this.param(name[i], fn);
}
return this;
}
this._router.param(name, fn);
return this;
};
/**
* Assign `setting` to `val`, or return `setting`'s value.
*
* app.set('foo', 'bar');
* app.set('foo');
* // => "bar"
*
* Mounted servers inherit their parent server's settings.
*
* @param {String} setting
* @param {*} [val]
* @return {Server} for chaining
* @public
*/
app.set = function set(setting, val) {
if (arguments.length === 1) {
// app.get(setting)
var settings = this.settings
while (settings && settings !== Object.prototype) {
if (hasOwnProperty.call(settings, setting)) {
return settings[setting]
}
settings = Object.getPrototypeOf(settings)
}
return undefined
}
debug('set "%s" to %o', setting, val);
// set value
this.settings[setting] = val;
// trigger matched settings
switch (setting) {
case 'etag':
this.set('etag fn', compileETag(val));
break;
case 'query parser':
this.set('query parser fn', compileQueryParser(val));
break;
case 'trust proxy':
this.set('trust proxy fn', compileTrust(val));
// trust proxy inherit back-compat
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
configurable: true,
value: false
});
break;
}
return this;
};
/**
* Return the app's absolute pathname
* based on the parent(s) that have
* mounted it.
*
* For example if the application was
* mounted as "/admin", which itself
* was mounted as "/blog" then the
* return value would be "/blog/admin".
*
* @return {String}
* @private
*/
app.path = function path() {
return this.parent
? this.parent.path() + this.mountpath
: '';
};
/**
* Check if `setting` is enabled (truthy).
*
* app.enabled('foo')
* // => false
*
* app.enable('foo')
* app.enabled('foo')
* // => true
*
* @param {String} setting
* @return {Boolean}
* @public
*/
app.enabled = function enabled(setting) {
return Boolean(this.set(setting));
};
/**
* Check if `setting` is disabled.
*
* app.disabled('foo')
* // => true
*
* app.enable('foo')
* app.disabled('foo')
* // => false
*
* @param {String} setting
* @return {Boolean}
* @public
*/
app.disabled = function disabled(setting) {
return !this.set(setting);
};
/**
* Enable `setting`.
*
* @param {String} setting
* @return {app} for chaining
* @public
*/
app.enable = function enable(setting) {
return this.set(setting, true);
};
/**
* Disable `setting`.
*
* @param {String} setting
* @return {app} for chaining
* @public
*/
app.disable = function disable(setting) {
return this.set(setting, false);
};
/**
* Delegate `.VERB(...)` calls to `router.VERB(...)`.
*/
methods.forEach(function(method){
app[method] = function(path){
if (method === 'get' && arguments.length === 1) {
// app.get(setting)
return this.set(path);
}
this.lazyrouter();
var route = this._router.route(path);
route[method].apply(route, slice.call(arguments, 1));
return this;
};
});
/**
* Special-cased "all" method, applying the given route `path`,
* middleware, and callback to _every_ HTTP method.
*
* @param {String} path
* @param {Function} ...
* @return {app} for chaining
* @public
*/
app.all = function all(path) {
this.lazyrouter();
var route = this._router.route(path);
var args = slice.call(arguments, 1);
for (var i = 0; i < methods.length; i++) {
route[methods[i]].apply(route, args);
}
return this;
};
// del -> delete alias
app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead');
/**
* Render the given view `name` name with `options`
* and a callback accepting an error and the
* rendered template string.
*
* Example:
*
* app.render('email', { name: 'Tobi' }, function(err, html){
* // ...
* })
*
* @param {String} name
* @param {Object|Function} options or fn
* @param {Function} callback
* @public
*/
app.render = function render(name, options, callback) {
var cache = this.cache;
var done = callback;
var engines = this.engines;
var opts = options;
var renderOptions = {};
var view;
// support callback function as second arg
if (typeof options === 'function') {
done = options;
opts = {};
}
// merge app.locals
merge(renderOptions, this.locals);
// merge options._locals
if (opts._locals) {
merge(renderOptions, opts._locals);
}
// merge options
merge(renderOptions, opts);
// set .cache unless explicitly provided
if (renderOptions.cache == null) {
renderOptions.cache = this.enabled('view cache');
}
// primed cache
if (renderOptions.cache) {
view = cache[name];
}
// view
if (!view) {
var View = this.get('view');
view = new View(name, {
defaultEngine: this.get('view engine'),
root: this.get('views'),
engines: engines
});
if (!view.path) {
var dirs = Array.isArray(view.root) && view.root.length > 1
? 'directories "' + view.root.slice(0, -1).join('", "') + '" or "' + view.root[view.root.length - 1] + '"'
: 'directory "' + view.root + '"'
var err = new Error('Failed to lookup view "' + name + '" in views ' + dirs);
err.view = view;
return done(err);
}
// prime the cache
if (renderOptions.cache) {
cache[name] = view;
}
}
// render
tryRender(view, renderOptions, done);
};
/**
* Listen for connections.
*
* A node `http.Server` is returned, with this
* application (which is a `Function`) as its
* callback. If you wish to create both an HTTP
* and HTTPS server you may do so with the "http"
* and "https" modules as shown here:
*
* var http = require('http')
* , https = require('https')
* , express = require('express')
* , app = express();
*
* http.createServer(app).listen(80);
* https.createServer({ ... }, app).listen(443);
*
* @return {http.Server}
* @public
*/
app.listen = function listen() {
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
/**
* Log error using console.error.
*
* @param {Error} err
* @private
*/
function logerror(err) {
/* istanbul ignore next */
if (this.get('env') !== 'test') console.error(err.stack || err.toString());
}
/**
* Try rendering a view.
* @private
*/
function tryRender(view, options, callback) {
try {
view.render(options, callback);
} catch (err) {
callback(err);
}
}

View File

@@ -0,0 +1,116 @@
/*!
* express
* Copyright(c) 2009-2013 TJ Holowaychuk
* Copyright(c) 2013 Roman Shtylman
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict';
/**
* Module dependencies.
*/
var bodyParser = require('body-parser')
var EventEmitter = require('events').EventEmitter;
var mixin = require('merge-descriptors');
var proto = require('./application');
var Route = require('./router/route');
var Router = require('./router');
var req = require('./request');
var res = require('./response');
/**
* Expose `createApplication()`.
*/
exports = module.exports = createApplication;
/**
* Create an express application.
*
* @return {Function}
* @api public
*/
function createApplication() {
var app = function(req, res, next) {
app.handle(req, res, next);
};
mixin(app, EventEmitter.prototype, false);
mixin(app, proto, false);
// expose the prototype that will get set on requests
app.request = Object.create(req, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
// expose the prototype that will get set on responses
app.response = Object.create(res, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
app.init();
return app;
}
/**
* Expose the prototypes.
*/
exports.application = proto;
exports.request = req;
exports.response = res;
/**
* Expose constructors.
*/
exports.Route = Route;
exports.Router = Router;
/**
* Expose middleware
*/
exports.json = bodyParser.json
exports.query = require('./middleware/query');
exports.raw = bodyParser.raw
exports.static = require('serve-static');
exports.text = bodyParser.text
exports.urlencoded = bodyParser.urlencoded
/**
* Replace removed middleware with an appropriate error message.
*/
var removedMiddlewares = [
'bodyParser',
'compress',
'cookieSession',
'session',
'logger',
'cookieParser',
'favicon',
'responseTime',
'errorHandler',
'timeout',
'methodOverride',
'vhost',
'csrf',
'directory',
'limit',
'multipart',
'staticCache'
]
removedMiddlewares.forEach(function (name) {
Object.defineProperty(exports, name, {
get: function () {
throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.');
},
configurable: true
});
});

View File

@@ -0,0 +1,43 @@
/*!
* express
* Copyright(c) 2009-2013 TJ Holowaychuk
* Copyright(c) 2013 Roman Shtylman
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict';
/**
* Module dependencies.
* @private
*/
var setPrototypeOf = require('setprototypeof')
/**
* Initialization middleware, exposing the
* request and response to each other, as well
* as defaulting the X-Powered-By header field.
*
* @param {Function} app
* @return {Function}
* @api private
*/
exports.init = function(app){
return function expressInit(req, res, next){
if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express');
req.res = res;
res.req = req;
req.next = next;
setPrototypeOf(req, app.request)
setPrototypeOf(res, app.response)
res.locals = res.locals || Object.create(null);
next();
};
};

View File

@@ -0,0 +1,47 @@
/*!
* express
* Copyright(c) 2009-2013 TJ Holowaychuk
* Copyright(c) 2013 Roman Shtylman
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict';
/**
* Module dependencies.
*/
var merge = require('utils-merge')
var parseUrl = require('parseurl');
var qs = require('qs');
/**
* @param {Object} options
* @return {Function}
* @api public
*/
module.exports = function query(options) {
var opts = merge({}, options)
var queryparse = qs.parse;
if (typeof options === 'function') {
queryparse = options;
opts = undefined;
}
if (opts !== undefined && opts.allowPrototypes === undefined) {
// back-compat for qs module
opts.allowPrototypes = true;
}
return function query(req, res, next){
if (!req.query) {
var val = parseUrl(req).query;
req.query = queryparse(val, opts);
}
next();
};
};

Some files were not shown because too many files have changed in this diff Show More