@opra/common
Version:
Opra common package
114 lines (113 loc) • 4.36 kB
JavaScript
import { omitUndefined } from '@jsopen/objects';
import { asMutable } from 'ts-gems';
import { DocumentElement } from '../common/document-element.js';
import { DECORATOR } from '../constants.js';
import { ApiFieldDecoratorFactory } from '../decorators/api-field-decorator.js';
import { testScopeMatch } from '../utils/test-scope-match.js';
import { ComplexTypeBase } from './complex-type-base.js';
/**
* @decorator ApiField
*/
export const ApiField = function (...args) {
// Decorator
if (!this) {
const [options] = args;
return ApiField[DECORATOR](options);
}
// Constructor
const [owner, initArgs] = args;
DocumentElement.call(this, owner);
const _this = asMutable(this);
_this.name = initArgs.name;
const origin = initArgs.origin || owner;
/* istanbul ignore next */
if (!(origin instanceof ComplexTypeBase)) {
throw new Error('Field origin should be one of ComplexType, MappedType or MixinType');
}
_this.origin = origin;
_this.scopePattern = initArgs.scopePattern
? Array.isArray(initArgs.scopePattern)
? initArgs.scopePattern
: [initArgs.scopePattern]
: undefined;
_this.type = initArgs.type || owner.node.getDataType('any');
_this.description = initArgs.description;
_this.isArray = initArgs.isArray;
_this.isNestedEntity = initArgs.isNestedEntity;
_this.default = initArgs.default;
_this.fixed = initArgs.fixed;
_this.required = initArgs.required;
_this.exclusive = initArgs.exclusive;
_this.localization = initArgs.localization;
_this.keyField = initArgs.keyField;
_this.deprecated = initArgs.deprecated;
_this.readonly = initArgs.readonly;
_this.writeonly = initArgs.writeonly;
_this.examples = initArgs.examples;
_this.override = initArgs.override;
};
/**
* The ApiFieldClass represents a descriptive metadata structure for API fields,
* supporting features like data type definition, scoping, localization, and constraints.
* This class extends DocumentElement, inheriting base document structure capabilities.
*/
class ApiFieldClass extends DocumentElement {
inScope(scope) {
return testScopeMatch(scope, this.scopePattern);
}
forScope(scope) {
if (!(scope && this.override))
return this;
this._overrideCache = this._overrideCache || {};
let field = this._overrideCache[scope];
if (field)
return field;
if (scope !== '*') {
for (const o of this.override) {
if (testScopeMatch(scope, o.scopePattern)) {
field = omitUndefined({
...o,
id: undefined,
owner: undefined,
node: undefined,
origin: undefined,
name: undefined,
type: undefined,
override: undefined,
_overrideCache: undefined,
scopePattern: o.scopePattern,
});
Object.setPrototypeOf(field, this);
break;
}
}
}
field = field || this;
this._overrideCache[scope] = field;
return field;
}
toJSON(options) {
const typeName = this.type
? this.node.getDataTypeNameWithNs(this.type)
: undefined;
return omitUndefined({
type: typeName ? typeName : this.type?.toJSON(options),
description: this.description,
isArray: this.isArray || undefined,
isNestedEntity: this.isNestedEntity || undefined,
default: this.default,
fixed: this.fixed,
required: this.required || undefined,
exclusive: this.exclusive || undefined,
localization: this.localization || undefined,
keyField: this.keyField || undefined,
deprecated: this.deprecated || undefined,
readonly: this.readonly || undefined,
writeonly: this.writeonly || undefined,
examples: this.examples,
});
}
}
ApiField.prototype = ApiFieldClass.prototype;
Object.assign(ApiField, ApiFieldDecoratorFactory);
ApiField[DECORATOR] = ApiFieldDecoratorFactory;