@loopback/openapi-v3
Version:
Decorators that annotate LoopBack artifacts with OpenAPI v3 metadata and utilities that transform LoopBack metadata to OpenAPI v3 specifications
461 lines • 18 kB
JavaScript
"use strict";
// Copyright IBM Corp. and LoopBack contributors 2018,2020. All Rights Reserved.
// Node module: @loopback/openapi-v3
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
Object.defineProperty(exports, "__esModule", { value: true });
exports.param = exports.PARAMETER_INDEX = void 0;
const core_1 = require("@loopback/core");
const filter_schema_1 = require("../filter-schema");
const generate_schema_1 = require("../generate-schema");
const keys_1 = require("../keys");
const types_1 = require("../types");
exports.PARAMETER_INDEX = 'x-parameter-index';
/**
* Describe an input parameter of a Controller method.
*
* `@param` must be applied to parameters.
*
* @example
* ```ts
* class MyController {
* @get('/')
* list(
* @param(offsetSpec) offset?: number,
* @param(pageSizeSpec) pageSize?: number,
* ) {}
* }
* ```
*
* @param paramSpec - Parameter specification.
*/
function param(paramSpec) {
return function (target, member, index) {
paramSpec = { ...paramSpec };
// Get the design time method parameter metadata
const methodSig = core_1.MetadataInspector.getDesignTypeForMethod(target, member);
const paramTypes = (methodSig === null || methodSig === void 0 ? void 0 : methodSig.parameterTypes) || [];
// Map design-time parameter type to the OpenAPI param type
const paramType = paramTypes[index];
if (paramType) {
if (
// generate schema if `paramSpec` doesn't have it
!paramSpec.schema ||
// generate schema if `paramSpec` has `schema` but without `type`
((0, types_1.isSchemaObject)(paramSpec.schema) && !paramSpec.schema.type)) {
// If content explicitly mentioned do not resolve schema
if (!paramSpec.content) {
// please note `resolveSchema` only adds `type` and `format` for `schema`
paramSpec.schema = (0, generate_schema_1.resolveSchema)(paramType, paramSpec.schema);
}
}
}
if (paramSpec.schema &&
(0, types_1.isSchemaObject)(paramSpec.schema) &&
paramSpec.schema.type === 'array') {
// The design-time type is `Object` for `any`
if (paramType != null && paramType !== Object && paramType !== Array) {
throw new Error(`The parameter type is set to 'array' but the JavaScript type is ${paramType.name}`);
}
}
core_1.ParameterDecoratorFactory.createDecorator(keys_1.OAI3Keys.PARAMETERS_KEY, paramSpec, { decoratorName: '@param' })(target, member, index);
};
}
exports.param = param;
/**
* The `type` and `format` inferred by a common name of OpenAPI 3.0.0 data type
* reference link:
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#data-types
*/
const builtinTypes = {
string: { type: 'string' },
boolean: { type: 'boolean' },
number: { type: 'number' },
integer: { type: 'integer', format: 'int32' },
long: { type: 'integer', format: 'int64' },
float: { type: 'number', format: 'float' },
double: { type: 'number', format: 'double' },
byte: { type: 'string', format: 'byte' },
binary: { type: 'string', format: 'binary' },
date: { type: 'string', format: 'date' },
dateTime: { type: 'string', format: 'date-time' },
password: { type: 'string', format: 'password' },
};
/**
* Namespace for `@param.*` decorators
*/
(function (param) {
/**
* Query parameter decorator
*/
param.query = {
/**
* Define a parameter of "integer" type that's read from the query string.
* Usage: ` @param.query.string('paramName')`
*
* @param name - Parameter name.
*/
string: createParamShortcut('query', builtinTypes.string),
/**
* Define a parameter of "number" type that's read from the query string.
* Usage: ` @param.query.number('paramName')`
*
* @param name - Parameter name.
*/
number: createParamShortcut('query', builtinTypes.number),
/**
* Define a parameter of "boolean" type that's read from the query string.
* Usage: ` @param.query.boolean('paramName')`
*
* @param name - Parameter name.
*/
boolean: createParamShortcut('query', builtinTypes.boolean),
/**
* Define a parameter of "integer" type that's read from the query string.
* Usage: ` @param.query.integer('paramName')`
*
* @param name - Parameter name.
*/
integer: createParamShortcut('query', builtinTypes.integer),
/**
* Define a parameter of "long" type that's read from the query string.
* Usage: ` @param.query.long('paramName')`
*
* @param name - Parameter name.
*/
long: createParamShortcut('query', builtinTypes.long),
/**
* Define a parameter of "float" type that's read from the query string.
* Usage: ` @param.query.float('paramName')`
*
* @param name - Parameter name.
*/
float: createParamShortcut('query', builtinTypes.float),
/**
* Define a parameter of "double" type that's read from the query string.
* Usage: ` @param.query.double('paramName')`
*
* @param name - Parameter name.
*/
double: createParamShortcut('query', builtinTypes.double),
/**
* Define a parameter of "byte" type that's read from the query string.
* Usage: ` @param.query.byte('paramName')`
*
* @param name - Parameter name.
*/
byte: createParamShortcut('query', builtinTypes.byte),
/**
* Define a parameter of "binary" type that's read from the query string.
* Usage: ` @param.query.binary('paramName')`
*
* @param name - Parameter name.
*/
binary: createParamShortcut('query', builtinTypes.binary),
/**
* Define a parameter of "date" type that's read from the query string.
* Usage: ` @param.query.date('paramName')`
*
* @param name - Parameter name.
*/
date: createParamShortcut('query', builtinTypes.date),
/**
* Define a parameter of "dateTime" type that's read from the query string.
* Usage: ` @param.query.dateTime('paramName')`
*
* @param name - Parameter name.
*/
dateTime: createParamShortcut('query', builtinTypes.dateTime),
/**
* Define a parameter of "password" type that's read from the query string.
* Usage: ` @param.query.password('paramName')`
*
* @param name - Parameter name.
*/
password: createParamShortcut('query', builtinTypes.password),
/**
* Define a parameter accepting an object value encoded
* - as a JSON string, e.g. `filter={"where":{"id":1}}`); or
* - in multiple nested keys, e.g. `filter[where][id]=1`
*
* @param name - Parameter name
* @param schema - Optional OpenAPI Schema describing the object value.
*/
object: function (name, schema = {
type: 'object',
additionalProperties: true,
}, spec) {
schema = {
type: 'object',
...schema,
};
return param({
name,
in: 'query',
content: {
'application/json': {
schema,
},
},
...spec,
});
},
};
/**
* Header parameter decorator
*/
param.header = {
/**
* Define a parameter of "string" type that's read from a request header.
* Usage: ` @param.header.string('paramName')`
*
* @param name - Parameter name, it must match the header name
* (e.g. `Content-Type`).
*/
string: createParamShortcut('header', builtinTypes.string),
/**
* Define a parameter of "number" type that's read from a request header.
* Usage: ` @param.header.number('paramName')`
*
* @param name - Parameter name, it must match the header name
* (e.g. `Content-Length`).
*/
number: createParamShortcut('header', builtinTypes.number),
/**
* Define a parameter of "boolean" type that's read from a request header.
* Usage: ` @param.header.boolean('paramName')`
*
* @param name - Parameter name, it must match the header name
* (e.g. `DNT` or `X-Do-Not-Track`).
*/
boolean: createParamShortcut('header', builtinTypes.boolean),
/**
* Define a parameter of "integer" type that's read from a request header.
* Usage: ` @param.header.integer('paramName')`
*
* @param name - Parameter name, it must match the header name
* (e.g. `Content-Length`).
*/
integer: createParamShortcut('header', builtinTypes.integer),
/**
* Define a parameter of "long" type that's read from a request header.
* Usage: ` @param.header.long('paramName')`
*
* @param name - Parameter name, it must match the header name
*/
long: createParamShortcut('header', builtinTypes.long),
/**
* Define a parameter of "float" type that's read from a request header.
* Usage: ` @param.header.float('paramName')`
*
* @param name - Parameter name, it must match the header name
*/
float: createParamShortcut('header', builtinTypes.float),
/**
* Define a parameter of "double" type that's read from a request header.
* Usage: ` @param.header.double('paramName')`
*
* @param name - Parameter name, it must match the header name
*/
double: createParamShortcut('header', builtinTypes.double),
/**
* Define a parameter of "byte" type that's read from a request header.
* Usage: ` @param.header.byte('paramName')`
*
* @param name - Parameter name, it must match the header name
*/
byte: createParamShortcut('header', builtinTypes.byte),
/**
* Define a parameter of "binary" type that's read from a request header.
* Usage: ` @param.header.binary('paramName')`
*
* @param name - Parameter name, it must match the header name
*/
binary: createParamShortcut('header', builtinTypes.binary),
/**
* Define a parameter of "date" type that's read from a request header.
* Usage: ` @param.header.date('paramName')`
*
* @param name - Parameter name, it must match the header name
*/
date: createParamShortcut('header', builtinTypes.date),
/**
* Define a parameter of "dateTime" type that's read from a request header.
* Usage: ` @param.header.dateTime('paramName')`
*
* @param name - Parameter name, it must match the header name
*/
dateTime: createParamShortcut('header', builtinTypes.dateTime),
/**
* Define a parameter of "password" type that's read from a request header.
* Usage: ` @param.header.password('paramName')`
*
* @param name - Parameter name, it must match the header name
*/
password: createParamShortcut('header', builtinTypes.password),
};
/**
* Path parameter decorator
*/
param.path = {
/**
* Define a parameter of "string" type that's read from request path.
* Usage: ` @param.path.string('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
string: createParamShortcut('path', builtinTypes.string),
/**
* Define a parameter of "number" type that's read from request path.
* Usage: ` @param.path.number('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
number: createParamShortcut('path', builtinTypes.number),
/**
* Define a parameter of "boolean" type that's read from request path.
* Usage: ` @param.path.boolean('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
boolean: createParamShortcut('path', builtinTypes.boolean),
/**
* Define a parameter of "integer" type that's read from request path.
* Usage: ` @param.path.integer('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
integer: createParamShortcut('path', builtinTypes.integer),
/**
* Define a parameter of "long" type that's read from request path.
* Usage: ` @param.path.long('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
long: createParamShortcut('path', builtinTypes.long),
/**
* Define a parameter of "float" type that's read from request path.
* Usage: ` @param.path.float('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
float: createParamShortcut('path', builtinTypes.float),
/**
* Define a parameter of "double" type that's read from request path.
* Usage: ` @param.path.double('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
double: createParamShortcut('path', builtinTypes.double),
/**
* Define a parameter of "byte" type that's read from request path.
* Usage: ` @param.path.byte('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
byte: createParamShortcut('path', builtinTypes.byte),
/**
* Define a parameter of "binary" type that's read from request path.
* Usage: ` @param.path.binary('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
binary: createParamShortcut('path', builtinTypes.binary),
/**
* Define a parameter of "date" type that's read from request path.
* Usage: ` @param.path.date('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
date: createParamShortcut('path', builtinTypes.date),
/**
* Define a parameter of "dateTime" type that's read from request path.
* Usage: ` @param.path.dateTime('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
dateTime: createParamShortcut('path', builtinTypes.dateTime),
/**
* Define a parameter of "password" type that's read from request path.
* Usage: ` @param.path.password('paramName')`
*
* @param name - Parameter name matching one of the placeholders in the path
*/
password: createParamShortcut('path', builtinTypes.password),
};
/**
* Define a parameter of `array` type.
*
* @example
* ```ts
* export class MyController {
* @get('/greet')
* greet(@param.array('names', 'query', {type: 'string'}) names: string[]): string {
* return `Hello, ${names}`;
* }
* }
* ```
*
* @param name - Parameter name
* @param source - Source of the parameter value
* @param itemSpec - Item type for the array or the full item object
*/
param.array = function (name, source, itemSpec) {
return param({
name,
in: source,
schema: { type: 'array', items: itemSpec },
});
};
/**
* Sugar decorator for `filter` query parameter
*
* @example
* ```ts
* async find(
* @param.filter(modelCtor)) filter?: Filter<T>,
* ): Promise<(T & Relations)[]> {
* // ...
* }
* ```
* @param modelCtor - Model class
* @param options - Options to customize the parameter name or filter schema
*
*/
function filter(modelCtor, options) {
var _a;
let name = 'filter';
if (typeof options === 'string') {
name = options;
options = {};
}
name = (_a = options === null || options === void 0 ? void 0 : options.name) !== null && _a !== void 0 ? _a : name;
return param.query.object(name, (0, filter_schema_1.getFilterSchemaFor)(modelCtor, options));
}
param.filter = filter;
/**
* Sugar decorator for `where` query parameter
*
* @example
* ```ts
* async count(
* @param.where(modelCtor)) where?: Where<T>,
* ): Promise<Count> {
* // ...
* }
* ```
* @param modelCtor - Model class
* @param name - Custom name for the parameter, default to `where`
*
*/
function where(modelCtor, name = 'where') {
return param.query.object(name, (0, filter_schema_1.getWhereSchemaFor)(modelCtor));
}
param.where = where;
})(param || (exports.param = param = {}));
function createParamShortcut(source, options) {
return (name, spec) => {
return param({ name, in: source, schema: { ...options }, ...spec });
};
}
//# sourceMappingURL=parameter.decorator.js.map