WIP - 21.08.31

This commit is contained in:
Daniel Garcia 2021-08-31 22:35:42 +02:00
parent 7ea0be8551
commit b095bed5ca
19 changed files with 2648 additions and 2338 deletions

View file

@ -1,10 +1,10 @@
module.exports = { module.exports = {
'plugins': ['jest'], // 'plugins': ['jest'],
'env': { 'env': {
'commonjs': true, 'commonjs': true,
'es6': true, 'es6': true,
'node': true, 'node': true,
'jest/globals': true, // 'jest/globals': true,
}, },
'extends': 'eslint:recommended', 'extends': 'eslint:recommended',
'globals': { 'globals': {

View file

@ -1,6 +1,6 @@
# MCF-Objects # MCF-Objects
Se trata de una librería para la gestión de objetos que añade tipos estáticos y objetos basados en clases. Se trata de una librería para la gestión de objetos que añade tipos estáticos y verificaciones.
Admite los siguientes tipos básicos: Admite los siguientes tipos básicos:
- String - String
@ -11,21 +11,15 @@ Admite los siguientes tipos básicos:
Mediante la definición de los objetos estáticos se pueden establecer límites a los valores, listas de valores permitidos... Mediante la definición de los objetos estáticos se pueden establecer límites a los valores, listas de valores permitidos...
## Entorno de desarrollo ## Entorno de desarrollo
La bibioteca se transpila usando `babel` y se compila con `webpack`. La bibioteca se transpila usando `babel` y se compila con `webpack`.
El entorno de desarrollo se levanta ejecutando `npm run start` y se puede acceder a él en http://localhost:9000 para ver el funcionamiento durante el desarrollo.
## Despliegue
Para el despliege a producción, debe subirse el proyecto a un repositorio `git`. Para poder trabajar con diferentes versiones de la biblioteca se emplean tags de git, por lo que una vez que se considera terminada una nueva versión de la misma sería necesario generar un nuevo tag de git con el número de la versión:
```sh
v0.1.3
```
## Arquitectura ## Arquitectura
El código de la aplicación se encuentra condensado en el archivo `index.js`, el cual exporta la clase definedObject. En el archivo `index.js`, se exporta la clase definedObject.
El constructor de clase lee la definición pasada como argumento cuando crea una instancia de clase y efectúa las verificaciones necesarias antes de devolver dicha instancia. El constructor de clase lee la definición pasada como argumento cuando crea una instancia de clase y efectúa las verificaciones necesarias antes de devolver dicha instancia.
Cuando se asignan valores a los campos del objeto también se realizar las verificaciones indicadas sobre estos.

2
dist/mcf-objects.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4268
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{ {
"name": "mcf-objects", "name": "mcf-objects",
"version": "0.1.4", "version": "0.2.0",
"description": "Library to create custom typed objects with custom types", "description": "Library to create typed objects",
"main": "dist/mcf-objects.js", "main": "dist/mcf-objects.js",
"scripts": { "scripts": {
"start": "webpack-dev-server --open --config webpack.dev.js", "start": "webpack-dev-server --open --config webpack.dev.js",
@ -10,16 +10,16 @@
"test:watch": "jest --watch" "test:watch": "jest --watch"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.11.6", "@babel/core": "^7.14.6",
"@babel/plugin-proposal-class-properties": "^7.10.4", "@babel/plugin-proposal-class-properties": "^7.14.5",
"@babel/preset-env": "^7.11.5", "@babel/preset-env": "^7.14.7",
"@babel/preset-react": "^7.10.4", "@babel/preset-react": "^7.14.5",
"babel-loader": "^8.1.0", "babel-loader": "^8.2.2",
"eslint": "^7.8.1", "eslint": "^7.29.0",
"jest": "^24.9.0", "jest": "^24.9.0",
"webpack": "^4.44.2", "webpack": "^4.46.0",
"webpack-cli": "^3.3.12", "webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0", "webpack-dev-server": "^3.11.2",
"webpack-merge": "^4.2.2" "webpack-merge": "^4.2.2"
}, },
"dependencies": {} "dependencies": {}

65
src/definedObject.js Normal file
View file

@ -0,0 +1,65 @@
import MCF_TypeFactory from './types/typeFactory'
export default class MCF_DefinedObject {
constructor(definition) {
this.definition = definition
this.validations = {}
this.fields = MCF_TypeFactory.buildDefinedObject(this)
this.validateValue(definition.values)
this.setValue(definition.values)
}
getDefinition() {
return this.definition
}
getValue() {
const value = {}
for (const field in this.fields) {
value[field] = this.fields[field].value
}
return value
}
validateValue(value) {
for (const field in this.definition.fields) {
if (value[field] === undefined || value === null) {
if (this.definition.fields[field].required === true) {
throw new Error(`The field ${field} is required`)
}
if (this.definition.fields[field].defaultValue !== undefined) {
value[field] = this.definition.fields[field].defaultValue
}
if (this.definition.fields[field].null === false) {
throw new Error(`The field ${field} can't be undefined`)
}
}
}
}
setValue(value) {
for (const valueKey in value) {
if (value[valueKey] === undefined) {
this.fields[valueKey].value = undefined
} else {
if (this.fields[valueKey] === undefined) {
throw new Error(`The field ${valueKey} doesn't exist in the current DefinedObject: ${JSON.stringify(Object.keys(this.fields), null, 2)}`)
}
this.fields[valueKey].setValue(value[valueKey])
}
}
}
updateArrayField(field, arrayItem, mustBeIncluded) {
const fieldArray = this.getValue()[field] || []
if (!fieldArray.includes(arrayItem) && mustBeIncluded) {
fieldArray.push(arrayItem)
}
if (fieldArray.includes(arrayItem) && !mustBeIncluded) {
fieldArray.splice(fieldArray.indexOf(arrayItem), 1)
}
const newValue = {}
newValue[field] = fieldArray
this.setValue(newValue)
}
}

View file

@ -8,263 +8,10 @@
//TODO: Hacer una función que permita cambiar un atributo de un mcf_component a partir del id del componente, el nombre del atributo y el nuevo valor del atributo //TODO: Hacer una función que permita cambiar un atributo de un mcf_component a partir del id del componente, el nombre del atributo y el nuevo valor del atributo
//TODO: Hacer una función que permita encontrar un mcf_component a partir de su id //TODO: Hacer una función que permita encontrar un mcf_component a partir de su id
// --== OBJECTS LIBRARY ==-- import MCF_DefinedObject from './definedObject'
// ======================================== import MCF_File from './objects/file'
class MCF_Type {
constructor(definition) {
this.definition = definition;
this.validations = {};
}
setValue(value) {
this.validate(value);
this.value = value;
}
getValue() {
return this.value;
}
validate(value) {
for (let validation in this.validations) {
this.validations[validation](value, this.definition);
}
}
}
class MCF_String extends MCF_Type {
constructor(definition) {
super(definition);
this.addValidations();
}
addValidations() {
this.validations.type = function(value) {
if (typeof(value) !== "string") {
throw new Error(`MCF_String creation: the type of ${value} isn't "string"`);
}
};
for (let param in this.definition) {
switch (param) {
case 'maxLength':
this.validations.maxLength = function(value, definition) {
if (value.length > definition.maxLength) {
throw new Error(`MCF_String creation: the length of the string "${value}" is higher than the maximum defined: ${definition.maxLength}`);
}
};
break;
case 'minLength':
this.validations.minLength = function(value, definition) {
if (value.length < definition.minLength) {
throw new Error(`MCF_String creation: the length of the string "${value}" is lower than the minimum defined: ${definition.minLength}`);
}
};
break;
}
}
}
}
class MCF_Number extends MCF_Type {
constructor(definition) {
super(definition);
this.addValidations();
}
addValidations() {
this.validations.type = function(value) {
if (typeof(value) !== "number") {
throw new Error(`MCF_Number creation: the type of the value ${value} isn't "number"`);
}
};
for (let param in this.definition) {
switch (param) {
case 'max':
this.validations.max = function(value, definition) {
if (value > definition.max) {
throw new Error(`MCF_Number creation: the value ${value} is higher than the maximum defined: ${definition.max}`);
}
};
break;
case 'min':
this.validations.min = function(value, definition) {
if (value < definition.min) {
throw new Error(`MCF_Number creation: the value ${value} is lower than the minimum defined: ${definition.min}`);
}
};
break;
}
}
}
}
class MCF_Boolean extends MCF_Type {
constructor(definition) {
super(definition);
this.addValidations();
}
addValidations() {
this.validations.type = function(value) {
if (typeof(value) !== "boolean") {
throw new Error(`MCF_Boolean creation: the type of the value ${value} isn't "boolean"`);
}
};
}
}
class MCF_Array extends MCF_Type {
constructor(definition) {
super(definition);
this.addValidations();
}
addValidations() {
this.validations.type = function(value) {
if (!Array.isArray(value)) {
throw new Error(`MCF_Array creation: the type of ${value} isn't "array"`);
}
};
for (let param in this.definition) {
switch (param) {
case 'maxLength':
this.validations.maxLength = function(value, definition) {
if (value.length > definition.maxLength) {
throw new Error(`MCF_Array creation: the length of the array "${value}" is higher than the maximum defined: ${definition.maxLength}`);
}
};
break;
case 'minLength':
this.validations.minLength = function(value, definition) {
if (value.length < definition.minLength) {
throw new Error(`MCF_Array creation: the length of the array "${value}" is lower than the minimum defined: ${definition.minLength}`);
}
};
break;
}
}
}
}
class MCF_Enum extends MCF_Type {
constructor(definition) {
super(definition);
this.addValidations();
}
addValidations() {
this.validations.isAvailable = function(value, definition) {
const valueIsAvailable = definition.availableValues.reduce(function(isAvailable, availableValue) {
if (value === availableValue) return true;
return isAvailable;
}, false);
if (!valueIsAvailable) {
throw new Error(`MCF_Enum creation: the value "${value}" isn't one of the next values, included in the field definition: ${definition.availableValues.toString()}`);
}
}
}
}
class MCF_TypeFactory {
static buildDefinedObject(definedObject) {
const objectDefinition = definedObject.getDefinition();
let fields = objectDefinition.fields;
let dictionary = {};
for (let field in fields) {
switch (fields[field]['TYPE']) {
case 'string':
dictionary[field] = new MCF_String(fields[field]);
break;
case 'number':
dictionary[field] = new MCF_Number(fields[field]);
break;
case 'boolean':
dictionary[field] = new MCF_Boolean(fields[field]);
break;
case 'enum':
dictionary[field] = new MCF_Enum(fields[field]);
break;
case 'array':
dictionary[field] = new MCF_Array(fields[field]);
break;
}
}
return dictionary;
}
}
class MCF_DefinedObject {
constructor(definition) {
this.definition = definition;
this.validations = {};
this.fields = MCF_TypeFactory.buildDefinedObject(this);
this.validateValue(definition.value)
this.setValue(definition.value)
}
getDefinition() {
return this.definition;
}
getValue() {
let value = {};
for (let field in this.fields) {
value[field] = this.fields[field].value;
}
return value;
}
validateValue(value) {
for (let field in this.definition.fields) {
if (value[field] === undefined || value === null) {
if (this.definition.fields[field].required === true) {
throw new Error(`The field ${field} is required`);
}
if (this.definition.fields[field].defaultValue !== undefined) {
value[field] = this.definition.fields[field].defaultValue;
}
if (this.definition.fields[field].null === false) {
throw new Error(`The field ${field} can't be undefined`);
}
}
}
}
setValue(value) {
for (let valueKey in value) {
if (value[valueKey] === undefined) {
this.fields[valueKey].value = undefined;
} else {
this.fields[valueKey].setValue(value[valueKey]);
}
}
}
setPropertiesValue(value) {
for (let field in value) {
this.fields[field].setValue(value[field]);
}
}
}
const fileDefinition = {
filename: { TYPE: 'string' },
extension: { TYPE: 'string' },
mimeType: { TYPE: 'string' },
path: { TYPE: 'string' },
content: { TYPE: 'string' },
}
class MCF_File extends MCF_DefinedObject {
constructor(params) {
const fields = (params.fields) ? params.fields : {}
const value = (params.value) ? params.value : params
super({
fields: {...fileDefinition, ...fields },
value: value,
})
}
}
export { export {
MCF_DefinedObject as definedObject, MCF_DefinedObject as DefinedObject,
MCF_File as mcfFile, MCF_File as File,
}; }

17
src/objects/file.js Normal file
View file

@ -0,0 +1,17 @@
import MCF_DefinedObject from '../definedObject'
const fileFields = {
name: { TYPE: 'string', required: true },
extension: { TYPE: 'string' },
mimeType: { TYPE: 'string' },
content: { TYPE: 'string', defaultValue: '' },
}
export default class MCF_File extends MCF_DefinedObject {
constructor(definition) {
super({
fields: { ...fileFields, ...definition.fields },
values: definition.values ? definition.values : definition,
})
}
}

35
src/types/array.js Normal file
View file

@ -0,0 +1,35 @@
import MCF_BaseType from './base'
export default class MCF_Array extends MCF_BaseType {
constructor(definition) {
super(definition)
this.addValidations()
}
addValidations() {
this.validations.type = function(value) {
if (!Array.isArray(value)) {
throw new Error(`MCF-Objects ==> MCF_Array creation: the type of ${value} isn't "array"`)
}
}
for (const param in this.definition) {
switch (param) {
case 'maxLength':
this.validations.maxLength = function(value, definition) {
if (value.length > definition.maxLength) {
throw new Error(`MCF-Objects ==> MCF_Array creation: the length of the array "${value}" is higher than the maximum defined: ${definition.maxLength}`)
}
}
break
case 'minLength':
this.validations.minLength = function(value, definition) {
if (value.length < definition.minLength) {
throw new Error(`MCF-Objects ==> MCF_Array creation: the length of the array "${value}" is lower than the minimum defined: ${definition.minLength}`)
}
}
break
}
}
}
}

22
src/types/base.js Normal file
View file

@ -0,0 +1,22 @@
export default class MCF_BaseType {
constructor(definition) {
this.definition = definition
this.validations = {}
}
setValue(value) {
this.validate(value)
this.value = value
}
getValue() {
return this.value
}
validate(value) {
for (const validation in this.validations) {
this.validations[validation](value, this.definition)
}
}
}

16
src/types/boolean.js Normal file
View file

@ -0,0 +1,16 @@
import MCF_BaseType from './base'
export default class MCF_Boolean extends MCF_BaseType {
constructor(definition) {
super(definition)
this.addValidations()
}
addValidations() {
this.validations.type = function(value) {
if (typeof(value) !== 'boolean') {
throw new Error(`MCF-Objects ==> MCF_Boolean creation: the type of the value ${value} isn't "boolean"`)
}
}
}
}

20
src/types/enum.js Normal file
View file

@ -0,0 +1,20 @@
import MCF_BaseType from './base'
export default class MCF_Enum extends MCF_BaseType {
constructor(definition) {
super(definition)
this.addValidations()
}
addValidations() {
this.validations.isAvailable = function(value, definition) {
const valueIsAvailable = definition.availableValues.reduce(function(isAvailable, availableValue) {
if (value === availableValue) return true
return isAvailable
}, false)
if (!valueIsAvailable) {
throw new Error(`MCF-Objects ==> MCF_Enum creation: the value "${value}" isn't one of the next values, included in the field definition: ${definition.availableValues.toString()}`)
}
}
}
}

34
src/types/number.js Normal file
View file

@ -0,0 +1,34 @@
import MCF_BaseType from './base'
export default class MCF_Number extends MCF_BaseType {
constructor(definition) {
super(definition)
this.addValidations()
}
addValidations() {
this.validations.type = function(value) {
if (typeof(value) !== 'number') {
throw new Error(`MCF-Objects ==> MCF_Number creation: the type of the value ${value} isn't "number"`)
}
}
for (const param in this.definition) {
switch (param) {
case 'max':
this.validations.max = function(value, definition) {
if (value > definition.max) {
throw new Error(`MCF-Objects ==> MCF_Number creation: the value ${value} is higher than the maximum defined: ${definition.max}`)
}
}
break
case 'min':
this.validations.min = function(value, definition) {
if (value < definition.min) {
throw new Error(`MCF-Objects ==> MCF_Number creation: the value ${value} is lower than the minimum defined: ${definition.min}`)
}
}
break
}
}
}
}

35
src/types/string.js Normal file
View file

@ -0,0 +1,35 @@
import MCF_BaseType from './base'
export default class MCF_String extends MCF_BaseType {
constructor(definition) {
super(definition)
this.addValidations()
}
addValidations() {
this.validations.type = function(value) {
if (typeof(value) !== 'string') {
throw new Error(`MCF-Objects ==> MCF_String creation: the type of ${value} isn't "string"`)
}
}
for (const param in this.definition) {
switch (param) {
case 'maxLength':
this.validations.maxLength = function(value, definition) {
if (value.length > definition.maxLength) {
throw new Error(`MCF-Objects ==> MCF_String creation: the length of the string "${value}" is higher than the maximum defined: ${definition.maxLength}`)
}
}
break
case 'minLength':
this.validations.minLength = function(value, definition) {
if (value.length < definition.minLength) {
throw new Error(`MCF-Objects ==> MCF_String creation: the length of the string "${value}" is lower than the minimum defined: ${definition.minLength}`)
}
}
break
}
}
}
}

36
src/types/typeFactory.js Normal file
View file

@ -0,0 +1,36 @@
import MCF_String from './string'
import MCF_Number from './number'
import MCF_Boolean from './boolean'
import MCF_Array from './array'
import MCF_Enum from './enum'
export default class MCF_TypeFactory {
static buildDefinedObject(definedObject) {
const objectDefinition = definedObject.getDefinition()
const fields = objectDefinition.fields
const dictionary = {}
for (const field in fields) {
switch (fields[field]['TYPE']) {
case 'string':
dictionary[field] = new MCF_String(fields[field])
break
case 'number':
dictionary[field] = new MCF_Number(fields[field])
break
case 'boolean':
dictionary[field] = new MCF_Boolean(fields[field])
break
case 'enum':
dictionary[field] = new MCF_Enum(fields[field])
break
case 'array':
dictionary[field] = new MCF_Array(fields[field])
break
default:
throw new Error(`MCF-Objects ==> The object type ${fields[field]['TYPE']} does not exist. Check the field definition in the object definition ${objectDefinition}`)
}
}
return dictionary
}
}

View file

@ -1,4 +1,4 @@
const path = require('path'); const path = require('path')
module.exports = { module.exports = {
entry: './src/index.js', entry: './src/index.js',
@ -6,7 +6,7 @@ module.exports = {
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'),
filename: 'mcf-objects.js', filename: 'mcf-objects.js',
library: 'mcfObjects', library: 'mcfObjects',
libraryTarget: 'umd' libraryTarget: 'umd',
}, },
module: { module: {
rules: [ rules: [
@ -19,4 +19,4 @@ module.exports = {
}, },
], ],
}, },
}; }

View file

@ -1,5 +1,5 @@
const merge = require('webpack-merge'); const merge = require('webpack-merge')
const common = require('./webpack.common.js'); const common = require('./webpack.common.js')
module.exports = merge(common, { module.exports = merge(common, {
mode: 'development', mode: 'development',
@ -7,4 +7,4 @@ module.exports = merge(common, {
devServer: { devServer: {
contentBase: './dist', contentBase: './dist',
}, },
}); })

View file

@ -1,7 +1,7 @@
const merge = require('webpack-merge'); const merge = require('webpack-merge')
const common = require('./webpack.common.js'); const common = require('./webpack.common.js')
module.exports = merge(common, { module.exports = merge(common, {
mode: 'production', mode: 'production',
devtool: 'source-map', devtool: 'source-map',
}); })