@opra/common
Version:
Opra common package
217 lines (216 loc) • 8.08 kB
JavaScript
import typeIs from '@browsery/type-is';
import { isConstructor } from '@jsopen/objects';
import { MimeTypes } from '../../enums/index.js';
import { OpraSchema } from '../../schema/index.js';
import { HTTP_CONTROLLER_METADATA } from '../constants.js';
export function HttpOperationDecoratorFactory(decoratorChain, options) {
/**
*
*/
const decorator = ((target, propertyKey) => {
if (typeof propertyKey !== 'string')
throw new TypeError(`Symbol properties can not be decorated`);
const operationMetadata = {
...options,
kind: OpraSchema.HttpOperation.Kind,
};
const controllerMetadata = (Reflect.getOwnMetadata(HTTP_CONTROLLER_METADATA, target.constructor) || {});
controllerMetadata.operations = controllerMetadata.operations || {};
controllerMetadata.operations[propertyKey] = operationMetadata;
for (const fn of decoratorChain)
fn(operationMetadata);
Reflect.defineMetadata(HTTP_CONTROLLER_METADATA, controllerMetadata, target.constructor);
});
/**
*
*/
decorator.Cookie = (name, arg1) => {
decoratorChain.push((meta) => {
const paramMeta = typeof arg1 === 'string' || typeof arg1 === 'function'
? {
name,
location: 'cookie',
type: arg1,
}
: { ...arg1, name, location: 'cookie' };
if (isConstructor(paramMeta.type))
paramMeta.designType = paramMeta.type;
if (meta.parameters) {
meta.parameters = meta.parameters.filter(p => !(p.location === 'cookie' && String(p.name) === String(name)));
}
else
meta.parameters = [];
meta.parameters.push(paramMeta);
});
return decorator;
};
/**
*
*/
decorator.Header = (name, arg1) => {
decoratorChain.push((meta) => {
const paramMeta = typeof arg1 === 'string' || typeof arg1 === 'function'
? {
name,
location: 'header',
type: arg1,
}
: { ...arg1, name, location: 'header' };
if (isConstructor(paramMeta.type))
paramMeta.designType = paramMeta.type;
if (meta.parameters) {
meta.parameters = meta.parameters.filter(p => !(p.location === 'header' && String(p.name) === String(name)));
}
else
meta.parameters = [];
meta.parameters.push(paramMeta);
});
return decorator;
};
/**
*
*/
decorator.QueryParam = (name, arg1) => {
decoratorChain.push((meta) => {
const paramMeta = typeof arg1 === 'string' || typeof arg1 === 'function'
? {
name,
location: 'query',
type: arg1,
}
: { ...arg1, name, location: 'query' };
if (isConstructor(paramMeta.type))
paramMeta.designType = paramMeta.type;
if (meta.parameters) {
meta.parameters = meta.parameters.filter(p => !(p.location === 'query' && String(p.name) === String(name)));
}
else
meta.parameters = [];
meta.parameters.push(paramMeta);
});
return decorator;
};
/**
*
*/
decorator.PathParam = (name, arg1) => {
decoratorChain.push((meta) => {
const paramMeta = typeof arg1 === 'string' || typeof arg1 === 'function'
? {
name,
location: 'path',
type: arg1,
}
: { ...arg1, name, location: 'path' };
if (isConstructor(paramMeta.type))
paramMeta.designType = paramMeta.type;
if (meta.parameters) {
meta.parameters = meta.parameters.filter(p => !(p.location === 'path' && String(p.name) === String(name)));
}
else
meta.parameters = [];
meta.parameters.push(paramMeta);
});
return decorator;
};
/**
*
*/
decorator.Response = (statusCode, responseOptions) => {
const responseMeta = {
...responseOptions,
statusCode,
};
if (responseMeta.type) {
responseMeta.contentType = responseMeta.contentType ?? MimeTypes.json;
}
const contentTypes = responseMeta.contentType
? Array.isArray(responseMeta.contentType)
? responseMeta.contentType
: [responseMeta.contentType]
: [];
if (contentTypes.find(type => type.endsWith('+json') ||
type.endsWith('+xml') ||
typeIs.is(type, 'json', 'html', 'text', 'xml'))) {
responseMeta.contentEncoding = responseMeta.contentEncoding ?? 'utf-8';
}
if (isConstructor(responseMeta.type))
responseMeta.designType = responseMeta.type;
decoratorChain.push((meta) => {
meta.responses = meta.responses || [];
meta.responses.push(responseMeta);
});
return decorator;
};
decorator.RequestContent = function (arg0) {
const contentMeta = typeof arg0 === 'object' ? arg0 : { type: arg0 };
if (contentMeta.type) {
contentMeta.contentType = contentMeta.contentType || MimeTypes.json;
contentMeta.contentEncoding = contentMeta.contentEncoding || 'utf-8';
if (isConstructor(contentMeta.type))
contentMeta.designType = contentMeta.type;
}
decoratorChain.push((operationMetadata) => {
operationMetadata.requestBody = operationMetadata.requestBody || {
required: true,
content: [],
};
operationMetadata.requestBody.content =
operationMetadata.requestBody.content || [];
operationMetadata.requestBody.content.push(contentMeta);
});
return decorator;
};
decorator.MultipartContent = function (contentOpts, subInit) {
const contentMetadata = {
...contentOpts,
contentType: contentOpts?.contentType || 'multipart/form-data',
};
decoratorChain.push((operationMetadata) => {
operationMetadata.requestBody = operationMetadata.requestBody || {
required: true,
content: [],
};
operationMetadata.requestBody.content =
operationMetadata.requestBody.content || [];
operationMetadata.requestBody.content.push(contentMetadata);
});
if (subInit) {
const configScope = {
Field(fieldName, opts) {
contentMetadata.multipartFields =
contentMetadata.multipartFields || [];
contentMetadata.multipartFields.push({
fieldName,
fieldType: 'field',
...opts,
});
return configScope;
},
File(fieldName, opts) {
contentMetadata.multipartFields =
contentMetadata.multipartFields || [];
contentMetadata.multipartFields.push({
fieldName,
fieldType: 'file',
...opts,
});
return configScope;
},
};
subInit(configScope);
}
return decorator;
};
/**
*
*/
decorator.UseType = (...type) => {
decoratorChain.push((meta) => {
meta.types = meta.types || [];
meta.types.push(...type);
});
return decorator;
};
return decorator;
}