Entity attributes initialization refactoring

This commit is contained in:
barsdeveloper
2023-04-01 15:57:08 +02:00
parent 9d6b498709
commit 275b58dcf0
3 changed files with 228 additions and 246 deletions

238
dist/ueblueprint.js vendored
View File

@@ -916,127 +916,6 @@ class IEntity {
}
constructor(values = {}, suppressWarns = false) {
/**
* @param {Object} target
* @param {Object} attributes
* @param {Object} values
* @param {String} prefix
*/
const defineAllAttributes = (target, attributes, values = {}, prefix = "") => {
const valuesNames = Object.keys(values);
const attributesNames = Object.keys(attributes);
const allAttributesNames = Utility.mergeArrays(attributesNames, valuesNames);
for (let attributeName of allAttributesNames) {
let value = values[attributeName];
/** @type {AttributeInformation} */
let attribute = attributes[attributeName];
if (!suppressWarns) {
if (!(attributeName in attributes)) {
console.warn(
`UEBlueprint: Attribute ${prefix}${attributeName} in the serialized data is not defined in `
+ `${this.constructor.name}.attributes`
);
} else if (
valuesNames.length > 0
&& !(attributeName in values)
&& !(!attribute.showDefault || attribute.ignored)
) {
console.warn(
`UEBlueprint: ${this.constructor.name} will add attribute ${prefix}${attributeName} not `
+ "defined in the serialized data"
);
}
}
if (!attribute) {
// Remember attributeName can come from the values and be not defined in the attributes
// In that case just assign it and skip the rest
target[attributeName] = value;
continue
}
let defaultValue = attribute.value;
let defaultType = attribute.type;
if (defaultType instanceof ComputedType) {
defaultType = defaultType.compute(this);
}
if (defaultType instanceof Array) {
defaultType = Array;
}
if (defaultValue instanceof Function) {
defaultValue = defaultValue(this);
}
if (defaultType === undefined) {
defaultType = Utility.getType(defaultValue);
}
const assignAttribute = !attribute.predicate
? v => target[attributeName] = v
: v => {
Object.defineProperties(target, {
["#" + attributeName]: {
writable: true,
enumerable: false,
},
[attributeName]: {
enumerable: true,
get() {
return this["#" + attributeName]
},
set(v) {
if (!attribute.predicate?.(v)) {
console.warn(
`UEBlueprint: Tried to assign attribute ${prefix}${attributeName} to `
+ `${this.constructor.name} not satisfying the predicate`
);
return
}
this["#" + attributeName] = v;
}
},
});
this[attributeName] = v;
};
if (value !== undefined) {
// Remember value can still be null
if (value?.constructor === String && attribute.serialized && defaultType !== String) {
value = SerializerFactory
.getSerializer(/** @type {AnyValueConstructor<*>} */(defaultType))
.deserialize(/** @type {String} */(value));
}
assignAttribute(Utility.sanitize(value, /** @type {AnyValueConstructor<*>} */(defaultType)));
continue // We have a value, need nothing more
}
if (defaultType instanceof UnionType) {
if (defaultValue != undefined) {
defaultType = defaultType.types.find(
type => defaultValue instanceof type || defaultValue.constructor == type
) ?? defaultType.getFirstType();
} else {
defaultType = defaultType.getFirstType();
}
}
if (defaultValue === undefined) {
defaultValue = Utility.sanitize(new /** @type {AnyValueConstructor<*>} */(defaultType)());
}
if (!attribute.showDefault) {
assignAttribute(undefined); // Declare undefined to preserve the order of attributes
continue
}
if (attribute.serialized) {
if (defaultType !== String && defaultValue.constructor === String) {
defaultValue = SerializerFactory
.getSerializer(/** @type {AnyValueConstructor<*>} */(defaultType))
.deserialize(defaultValue);
}
}
assignAttribute(Utility.sanitize(
/** @type {AnyValue} */(defaultValue),
/** @type {AnyValueConstructor<AnyValue>} */(defaultType)
));
}
};
const attributes = /** @type {typeof IEntity} */(this.constructor).attributes;
if (values.constructor !== Object && Object.keys(attributes).length === 1) {
// Where there is just one attribute, option can be the value of that attribute
@@ -1044,7 +923,118 @@ class IEntity {
[Object.keys(attributes)[0]]: values
};
}
defineAllAttributes(this, attributes, values);
const valuesNames = Object.keys(values);
const attributesNames = Object.keys(attributes);
const allAttributesNames = Utility.mergeArrays(attributesNames, valuesNames);
for (let attributeName of allAttributesNames) {
let value = values[attributeName];
let attribute = /** @type {AttributeInformation} */(attributes[attributeName]);
if (!suppressWarns) {
if (!(attributeName in attributes)) {
console.warn(
`UEBlueprint: Attribute ${attributeName} in the serialized data is not defined in `
+ `${this.constructor.name}.attributes`
);
} else if (
valuesNames.length > 0
&& !(attributeName in values)
&& !(!attribute.showDefault || attribute.ignored)
) {
console.warn(
`UEBlueprint: ${this.constructor.name} will add attribute ${attributeName} not `
+ "defined in the serialized data"
);
}
}
if (!attribute) {
// Remember attributeName can come from the values and be not defined in the attributes
// In that case just assign it and skip the rest
this[attributeName] = value;
continue
}
let defaultValue = attribute.value;
let defaultType = attribute.type;
if (defaultType instanceof ComputedType) {
defaultType = defaultType.compute(this);
}
if (defaultType instanceof Array) {
defaultType = Array;
}
if (defaultValue instanceof Function) {
defaultValue = defaultValue(this);
}
if (defaultType === undefined) {
defaultType = Utility.getType(defaultValue);
}
const assignAttribute = !attribute.predicate
? v => this[attributeName] = v
: v => {
Object.defineProperties(this, {
["#" + attributeName]: {
writable: true,
enumerable: false,
},
[attributeName]: {
enumerable: true,
get() {
return this["#" + attributeName]
},
set(v) {
if (!attribute.predicate?.(v)) {
console.warn(
`UEBlueprint: Tried to assign attribute ${attributeName} to `
+ `${this.constructor.name} not satisfying the predicate`
);
return
}
this["#" + attributeName] = v;
}
},
});
this[attributeName] = v;
};
if (value !== undefined) {
// Remember value can still be null
if (value?.constructor === String && attribute.serialized && defaultType !== String) {
value = SerializerFactory
.getSerializer(/** @type {AnyValueConstructor<*>} */(defaultType))
.deserialize(/** @type {String} */(value));
}
assignAttribute(Utility.sanitize(value, /** @type {AnyValueConstructor<*>} */(defaultType)));
continue // We have a value, need nothing more
}
if (defaultType instanceof UnionType) {
if (defaultValue != undefined) {
defaultType = defaultType.types.find(
type => defaultValue instanceof type || defaultValue.constructor == type
) ?? defaultType.getFirstType();
} else {
defaultType = defaultType.getFirstType();
}
}
if (defaultValue === undefined) {
defaultValue = Utility.sanitize(new /** @type {AnyValueConstructor<*>} */(defaultType)());
}
if (!attribute.showDefault) {
assignAttribute(undefined); // Declare undefined to preserve the order of attributes
continue
}
if (attribute.serialized) {
if (defaultType !== String && defaultValue.constructor === String) {
defaultValue = SerializerFactory
.getSerializer(/** @type {AnyValueConstructor<*>} */(defaultType))
.deserialize(defaultValue);
}
}
assignAttribute(Utility.sanitize(
/** @type {AnyValue} */(defaultValue),
/** @type {AnyValueConstructor<AnyValue>} */(defaultType)
));
}
}
/** @param {AttributeDeclarations} attributes */
@@ -3121,10 +3111,10 @@ var Parsimmon = /*@__PURE__*/getDefaultExportFromCjs(parsimmon_umd_min.exports);
class UnknownKeysEntity extends IEntity {
static attributes = {
lookbehind:
{
lookbehind: {
value: "",
showDefault: false,
ignore: true,
},
}

File diff suppressed because one or more lines are too long

View File

@@ -43,126 +43,7 @@ export default class IEntity {
}
constructor(values = {}, suppressWarns = false) {
/**
* @param {Object} target
* @param {Object} attributes
* @param {Object} values
* @param {String} prefix
*/
const defineAllAttributes = (target, attributes, values = {}, prefix = "") => {
const valuesNames = Object.keys(values)
const attributesNames = Object.keys(attributes)
const allAttributesNames = Utility.mergeArrays(attributesNames, valuesNames)
for (let attributeName of allAttributesNames) {
let value = values[attributeName]
/** @type {AttributeInformation} */
let attribute = attributes[attributeName]
if (!suppressWarns) {
if (!(attributeName in attributes)) {
console.warn(
`UEBlueprint: Attribute ${prefix}${attributeName} in the serialized data is not defined in `
+ `${this.constructor.name}.attributes`
)
} else if (
valuesNames.length > 0
&& !(attributeName in values)
&& !(!attribute.showDefault || attribute.ignored)
) {
console.warn(
`UEBlueprint: ${this.constructor.name} will add attribute ${prefix}${attributeName} not `
+ "defined in the serialized data"
)
}
}
if (!attribute) {
// Remember attributeName can come from the values and be not defined in the attributes
// In that case just assign it and skip the rest
target[attributeName] = value
continue
}
let defaultValue = attribute.value
let defaultType = attribute.type
if (defaultType instanceof ComputedType) {
defaultType = defaultType.compute(this)
}
if (defaultType instanceof Array) {
defaultType = Array
}
if (defaultValue instanceof Function) {
defaultValue = defaultValue(this)
}
if (defaultType === undefined) {
defaultType = Utility.getType(defaultValue)
}
const assignAttribute = !attribute.predicate
? v => target[attributeName] = v
: v => {
Object.defineProperties(target, {
["#" + attributeName]: {
writable: true,
enumerable: false,
},
[attributeName]: {
enumerable: true,
get() {
return this["#" + attributeName]
},
set(v) {
if (!attribute.predicate?.(v)) {
console.warn(
`UEBlueprint: Tried to assign attribute ${prefix}${attributeName} to `
+ `${this.constructor.name} not satisfying the predicate`
)
return
}
this["#" + attributeName] = v
}
},
})
this[attributeName] = v
}
if (value !== undefined) {
// Remember value can still be null
if (value?.constructor === String && attribute.serialized && defaultType !== String) {
value = SerializerFactory
.getSerializer(/** @type {AnyValueConstructor<*>} */(defaultType))
.deserialize(/** @type {String} */(value))
}
assignAttribute(Utility.sanitize(value, /** @type {AnyValueConstructor<*>} */(defaultType)))
continue // We have a value, need nothing more
}
if (defaultType instanceof UnionType) {
if (defaultValue != undefined) {
defaultType = defaultType.types.find(
type => defaultValue instanceof type || defaultValue.constructor == type
) ?? defaultType.getFirstType()
} else {
defaultType = defaultType.getFirstType()
}
}
if (defaultValue === undefined) {
defaultValue = Utility.sanitize(new /** @type {AnyValueConstructor<*>} */(defaultType)())
}
if (!attribute.showDefault) {
assignAttribute(undefined) // Declare undefined to preserve the order of attributes
continue
}
if (attribute.serialized) {
if (defaultType !== String && defaultValue.constructor === String) {
defaultValue = SerializerFactory
.getSerializer(/** @type {AnyValueConstructor<*>} */(defaultType))
.deserialize(defaultValue)
}
}
assignAttribute(Utility.sanitize(
/** @type {AnyValue} */(defaultValue),
/** @type {AnyValueConstructor<AnyValue>} */(defaultType)
))
}
const defineAllAttributes = (target, attributes, values = {}) => {
}
const attributes = /** @type {typeof IEntity} */(this.constructor).attributes
if (values.constructor !== Object && Object.keys(attributes).length === 1) {
@@ -171,7 +52,118 @@ export default class IEntity {
[Object.keys(attributes)[0]]: values
}
}
defineAllAttributes(this, attributes, values)
const valuesNames = Object.keys(values)
const attributesNames = Object.keys(attributes)
const allAttributesNames = Utility.mergeArrays(attributesNames, valuesNames)
for (let attributeName of allAttributesNames) {
let value = values[attributeName]
let attribute = /** @type {AttributeInformation} */(attributes[attributeName])
if (!suppressWarns) {
if (!(attributeName in attributes)) {
console.warn(
`UEBlueprint: Attribute ${attributeName} in the serialized data is not defined in `
+ `${this.constructor.name}.attributes`
)
} else if (
valuesNames.length > 0
&& !(attributeName in values)
&& !(!attribute.showDefault || attribute.ignored)
) {
console.warn(
`UEBlueprint: ${this.constructor.name} will add attribute ${attributeName} not `
+ "defined in the serialized data"
)
}
}
if (!attribute) {
// Remember attributeName can come from the values and be not defined in the attributes
// In that case just assign it and skip the rest
this[attributeName] = value
continue
}
let defaultValue = attribute.value
let defaultType = attribute.type
if (defaultType instanceof ComputedType) {
defaultType = defaultType.compute(this)
}
if (defaultType instanceof Array) {
defaultType = Array
}
if (defaultValue instanceof Function) {
defaultValue = defaultValue(this)
}
if (defaultType === undefined) {
defaultType = Utility.getType(defaultValue)
}
const assignAttribute = !attribute.predicate
? v => this[attributeName] = v
: v => {
Object.defineProperties(this, {
["#" + attributeName]: {
writable: true,
enumerable: false,
},
[attributeName]: {
enumerable: true,
get() {
return this["#" + attributeName]
},
set(v) {
if (!attribute.predicate?.(v)) {
console.warn(
`UEBlueprint: Tried to assign attribute ${attributeName} to `
+ `${this.constructor.name} not satisfying the predicate`
)
return
}
this["#" + attributeName] = v
}
},
})
this[attributeName] = v
}
if (value !== undefined) {
// Remember value can still be null
if (value?.constructor === String && attribute.serialized && defaultType !== String) {
value = SerializerFactory
.getSerializer(/** @type {AnyValueConstructor<*>} */(defaultType))
.deserialize(/** @type {String} */(value))
}
assignAttribute(Utility.sanitize(value, /** @type {AnyValueConstructor<*>} */(defaultType)))
continue // We have a value, need nothing more
}
if (defaultType instanceof UnionType) {
if (defaultValue != undefined) {
defaultType = defaultType.types.find(
type => defaultValue instanceof type || defaultValue.constructor == type
) ?? defaultType.getFirstType()
} else {
defaultType = defaultType.getFirstType()
}
}
if (defaultValue === undefined) {
defaultValue = Utility.sanitize(new /** @type {AnyValueConstructor<*>} */(defaultType)())
}
if (!attribute.showDefault) {
assignAttribute(undefined) // Declare undefined to preserve the order of attributes
continue
}
if (attribute.serialized) {
if (defaultType !== String && defaultValue.constructor === String) {
defaultValue = SerializerFactory
.getSerializer(/** @type {AnyValueConstructor<*>} */(defaultType))
.deserialize(defaultValue)
}
}
assignAttribute(Utility.sanitize(
/** @type {AnyValue} */(defaultValue),
/** @type {AnyValueConstructor<AnyValue>} */(defaultType)
))
}
}
/** @param {AttributeDeclarations} attributes */