@opra/common
Version:
Opra common package
138 lines (137 loc) • 4.67 kB
JavaScript
import { FilterRules } from '../../filter/filter-rules.js';
import { DATATYPE_METADATA } from '../constants.js';
import { FIELD_PATH_PATTERN } from '../data-type/complex-type-base.js';
import { EnumType } from '../data-type/enum-type.js';
import { FilterType } from '../data-type/extended-types/index.js';
import { HttpOperation } from '../http/http-operation.js';
/** Implementation **/
HttpOperation.Entity = {};
/**
*
* @param typ
*/
export function getDataTypeName(typ) {
if (typeof typ === 'string')
return typ;
const metadata = Reflect.getMetadata(DATATYPE_METADATA, typ);
if (!metadata)
throw new TypeError(`Type (${typ}) is not decorated with any datatype decorators`);
if (metadata?.name)
return metadata.name;
throw new TypeError(`You should provide named data type but embedded one found`);
}
/**
*
*/
export function createKeyParamDecorator(decorator, decoratorChain) {
return (name, prmOptions) => {
const paramMeta = typeof prmOptions === 'string' || typeof prmOptions === 'function'
? {
name,
location: 'path',
type: prmOptions,
keyParam: true,
}
: {
...prmOptions,
name,
location: 'path',
keyParam: true,
};
decorator.PathParam(name, paramMeta);
decoratorChain.push((meta) => {
if (!meta.path?.includes(':' + name))
meta.path = (meta.path || '') + '@:' + name;
meta.mergePath = true;
});
return decorator;
};
}
/**
*
*/
export function createSortFieldsDecorator(decorator, decoratorChain) {
return (...varargs) => {
const defObj = typeof varargs[0] === 'object'
? varargs[0]
: varargs.reduce((acc, k) => {
const a = k.split(':');
acc[a[0]] = a[1] || a[0];
return acc;
}, {});
const fieldsMap = Object.keys(defObj).reduce((acc, k) => {
const m1 = FIELD_PATH_PATTERN.exec(k);
const m2 = FIELD_PATH_PATTERN.exec(defObj[k]);
if (m1 && m2) {
acc[m1[2]] = m2[2];
}
return acc;
}, {});
const prmEnum = Object.keys(defObj).reduce((acc, k) => {
const m = FIELD_PATH_PATTERN.exec(k);
if (m) {
if (m[1] != '-')
acc[m[2]] = m[2];
if (m[1] != '+')
acc['-' + m[2]] = '-' + m[2];
}
return acc;
}, {});
decoratorChain.push((operationMeta) => {
const compositionOptions = (operationMeta.compositionOptions =
operationMeta.compositionOptions || {});
compositionOptions.sortFields = fieldsMap;
});
decorator.QueryParam('sort', {
description: 'Determines sort fields',
type: EnumType(prmEnum),
isArray: true,
arraySeparator: ',',
parser: (v) => v.map(x => {
const m = FIELD_PATH_PATTERN.exec(x);
return m ? (m[1] || '') + fieldsMap[m[2]] : x;
}),
});
return decorator;
};
}
/**
*
*/
export function createFilterDecorator(decorator, decoratorChain, dataType) {
let filterRules = Reflect.getMetadata('FilterRules', decorator);
if (!filterRules) {
filterRules = new FilterRules();
Reflect.defineMetadata('FilterRules', filterRules, decorator);
}
let filterType = Reflect.getMetadata('FilterType', decorator);
if (!filterType) {
filterType = new FilterType({ dataType });
filterType.rules = {};
Reflect.defineMetadata('FilterType', filterType, decorator);
}
return (field, arg0) => {
const filterOptions = (Array.isArray(arg0)
? { operators: arg0 }
: typeof arg0 === 'string'
? {
operators: arg0.split(/\s*,\s*/),
}
: arg0) || {};
filterOptions.operators = filterOptions.operators || ['=', '!='];
if (field.includes(':')) {
const a = field.split(':');
field = a[0];
filterOptions.mappedField = a[1];
}
decoratorChain.push(() => {
filterRules.set(field, filterOptions);
filterType.rules = filterRules.toJSON();
});
decorator.QueryParam('filter', {
type: filterType,
description: 'Determines filter fields',
});
return decorator;
};
}