Skip to content

Commit

Permalink
Merge 47ae676 into f368b8a
Browse files Browse the repository at this point in the history
  • Loading branch information
talyssonoc authored Mar 21, 2019
2 parents f368b8a + 47ae676 commit 997e446
Show file tree
Hide file tree
Showing 11 changed files with 358 additions and 315 deletions.
399 changes: 250 additions & 149 deletions dist/structure.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/attributes/decorator.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const Schema = require('../schema');
const Serialization = require('../serialization');
const Validation = require('../validation');
const Initialization = require('../initialization');
const Errors = require('../errors');
const { SCHEMA } = require('../symbols');
const Initializer = require('./initializer');
const {
attributeDescriptorFor,
attributesDescriptorFor
Expand All @@ -22,7 +22,7 @@ function attributesDecorator(schema, schemaOptions = {}) {
const instance = Reflect.construct(target, constructorArgs, newTarget);
const passedAttributes = Object.assign({}, constructorArgs[0]);

Initializer.initialize(passedAttributes, schema, instance);
Initialization.initialize(schema, passedAttributes, instance);

return instance;
}
Expand Down
46 changes: 0 additions & 46 deletions src/attributes/initializer.js

This file was deleted.

4 changes: 4 additions & 0 deletions src/initialization/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
forSchema: require('./initialization'),
initialize: require('./initialize')
};
28 changes: 28 additions & 0 deletions src/initialization/initialization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const { ATTRIBUTES } = require('../symbols');
const initializationOrderFor = require('./initializationOrder');

function initializedValue(attrPassedValue, attrInitializer, attrDescriptor, instance) {
if(attrPassedValue !== undefined) {
return attrPassedValue;
}

return attrInitializer(attrDescriptor, instance);
}

module.exports = function forSchema(schema) {
const initializationOrder = initializationOrderFor(schema);

return {
initialize(attributes, instance) {
instance[ATTRIBUTES] = Object.create(null);

for(let i = 0; i < initializationOrder.length; i++) {
const [ attrName, attrInitializer ] = initializationOrder[i];
const attrDescriptor = schema[attrName];
const attrPassedValue = attributes[attrName];

instance[attrName] = initializedValue(attrPassedValue, attrInitializer, attrDescriptor, instance);
}
}
};
};
30 changes: 30 additions & 0 deletions src/initialization/initializationOrder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const { isFunction } = require('lodash');

function isStaticInitialization(attrDescriptor) {
return !isFunction(attrDescriptor.default);
}

function staticInitialization(attrDescriptor) {
return attrDescriptor.default;
}

function derivedInitialization(attrDescriptor, instance) {
return attrDescriptor.default(instance);
}

module.exports = function initializationOrderFor(schema) {
const staticInitializations = [];
const derivedInitializations = [];

for(let attrName in schema) {
const attributeDescriptor = schema[attrName];

if(isStaticInitialization(attributeDescriptor)) {
staticInitializations.push([attrName, staticInitialization]);
} else {
derivedInitializations.push([attrName, derivedInitialization]);
}
}

return [...staticInitializations, ...derivedInitializations];
};
5 changes: 5 additions & 0 deletions src/initialization/initialize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const { INITIALIZE } = require('../symbols');

module.exports = function initialize(schema, attributes, instance) {
schema[INITIALIZE].initialize(attributes, instance);
};
9 changes: 8 additions & 1 deletion src/schema/normalization.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Validation = require('../validation');
const Initialization = require('../initialization');
const TypeDescriptor = require('../typeDescriptor');
const { VALIDATE } = require('../symbols');
const { VALIDATE, INITIALIZE } = require('../symbols');

module.exports = function normalizeSchema(rawSchema, schemaOptions) {
const schema = Object.create(null);
Expand All @@ -15,5 +16,11 @@ module.exports = function normalizeSchema(rawSchema, schemaOptions) {
value: schemaValidation
});

const initialization = Initialization.forSchema(schema);

Object.defineProperty(schema, INITIALIZE, {
value: initialization
});

return schema;
};
3 changes: 2 additions & 1 deletion src/symbols.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
SCHEMA: Symbol('schema'),
ATTRIBUTES: Symbol('attributes'),
VALIDATE: Symbol('validate')
VALIDATE: Symbol('validate'),
INITIALIZE: Symbol('initialize')
};
114 changes: 0 additions & 114 deletions test/unit/attributes/initializer.spec.js

This file was deleted.

31 changes: 29 additions & 2 deletions test/unit/instanceAndUpdate.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ describe('instantiating a structure', () => {
name: {
type: String,
default: 'Name'
},
uuid: {
type: String,
default: (instance) => instance.getUuid()
}
})(class User {
constructor() {
Expand All @@ -18,6 +22,10 @@ describe('instantiating a structure', () => {
userMethod() {
return 'I am a user';
}

getUuid() {
return 10;
}
});
});

Expand Down Expand Up @@ -48,9 +56,8 @@ describe('instantiating a structure', () => {
it('does not mutate the attributes object passed to the constructor', () => {
const attributesObject = {};

const user = new User(attributesObject);
new User(attributesObject);

expect(user.name).to.equal('Name');
expect(attributesObject).to.be.empty;
});

Expand All @@ -71,6 +78,26 @@ describe('instantiating a structure', () => {
expect(user.name).to.equal('Self');
expect(user.attributes.name).to.equal('Self');
});

describe('attributes initialization', () => {
describe('default value', () => {
context('when attribute default value is a static value', () => {
it('defaults to the static value', () => {
const user = new User();

expect(user.name).to.equal('Name');
});
});

context('when attribute default value is a function', () => {
it('calls the function using the instance of the object as parameter and perform coercion', () => {
const user = new User();

expect(user.uuid).to.equal('10');
});
});
});
});
});

describe('instantiating a structure with dynamic attribute types', () => {
Expand Down

0 comments on commit 997e446

Please sign in to comment.