Reusable models for the Node server and browsers
I like the idea of Transfer Objects within application. In my applications I use Entities (simple TO but with some additional functions like data validation, type casting, etc). Because I planned to write modern one-page-apps I decided to have Entities on the front-end as well.
That is how the idea of Gleam was born. And now I am able to write Entity once and use it on the NodeJS side and on the browser side. Every entity is automatically serialized to JSON and deserialized on front-end to correct objects. Gleam is for now on the very early stage, it is more like "proof of concept". I still need to build some real projects based on it.
expect(Gleam).to.throw('Root');expect(gleam).to.have.property('_root', root);expect(Gleam).to.respondTo('entity');
expect(Gleam).to.respondTo('fromJson');expect(Gleam).itself.to.respondTo('is');
expect(Gleam).itself.to.respondTo('buildSync');function createNotExistingEntity() {
return gleam.entity('wrongSchema');
}
expect(createNotExistingEntity).to.throw(Error);function createEntityWithWrongSchema() {
return gleam.entity('wrongSchema');
}
expect(createEntityWithWrongSchema).to.throw('Entity must be an object');function createEntityWithFaultySchema() {
return gleam.entity('schemaWithProperties');
}
expect(createEntityWithFaultySchema).to.throw('Entity schema must not have any properties');var entity = gleam.entity('user');
expect(entity).to.be.an('object');
expect(entity).to.have.keys('id', 'name', 'email');
expect(entity.id).to.be.a('function');
expect(entity.name).to.be.a('function');
expect(entity.email).to.be.a('function');
expect(Gleam.is(entity, 'user')).to.be.true;var entity = gleam.entity('user/test');
expect(entity).to.be.an('object');
expect(entity).to.have.keys('id');
expect(entity.id).to.be.a('function');
expect(Gleam.is(entity, 'user/test')).to.be.true;var entity = gleam.entity('user', userData);
expect(entity.id()).to.equal(userData.id);
expect(entity.name()).to.equal(userData.name);
expect(entity.email()).to.equal(userData.email);function createEntityWithWrongData() {
return gleam.entity('user', 'not an object');
}
expect(createEntityWithWrongData).to.throw('Values must be an object');var entity = gleam.entity('user', userData);
expect(entity.modified().id).to.be.false;
expect(entity.modified().name).to.be.false;
expect(entity.modified().email).to.be.false;var entity = gleam.entity('user', userData);
expect(entity.initial().id).to.equal(userData.id);
expect(entity.initial().name).to.equal(userData.name);
expect(entity.initial().email).to.equal(userData.email);var entity = gleam.fromJson(userJson);
expect(entity).to.be.an('object');
expect(Gleam.is(entity, 'user')).to.be.true;
expect(entity.id()).to.equal(1);var list = gleam.fromJson(userListJson);
expect(list).to.be.an('array');
expect(list).to.have.length(2);
expect(Gleam.is(list[0], 'user')).to.be.true;
expect(list[0].id()).to.equal(1);
expect(Gleam.is(list[1], 'user')).to.be.true;
expect(list[1].id()).to.equal(2);expect(Gleam.is(entity, 'user')).to.be.true;expect(Gleam.is(entity, 'not/user')).to.be.false;expect(Gleam.is('Not an object', 'user')).to.be.false;expect(jsOut).to.be.a('string');expect(spaceFix(jsOut)).to.be.equal(spaceFix(jsIn));expect(function () {
return entity.set({id: 1});
}).to.not.throw(Error);
expect(function () {
return entity.set('Hello, world!');
}).to.throw('Values must be an object');
expect(function () {
return entity.set(['hello', 'world']);
}).to.throw('Values must be an object');
expect(function () {
return entity.set(function () {
});
}).to.throw('Values must be an object');entity.set(userData);
expect(entity.id()).to.equal(userData.id);
expect(entity.name()).to.equal(userData.name);
expect(entity.email()).to.equal(userData.email);expect(function () {
entity.set({email: 'wrong-email'});
}).to.throw('Value [wrong-email] is not valid for [user.email]');var entity = gleam.entity('setterGetter', {email: 'nik@butenko.me'});
expect(entity.email()).to.equal('always@email.com');var entity = gleam.entity('setterGetter', {password: 'test', password2: 'test2'});
expect(entity.password()).to.equal('test2');var entity = gleam.entity('setterGetter', {id: 1});
expect(entity.id()).to.equal(43);var entity = gleam.entity('user', userData);
expect(entity.get()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me"});var entity = gleam.fromJson(userWithTestJson);
expect(entity.get()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me", test: {id: 2}});var entity = gleam.fromJson(requireText('./fixtures/user-with-arrays.json'));
expect(entity.get()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me", tests: [
{id: 2},
{id: 3}
], messages: ["Message 1", "Message 2"]});var entity = gleam.entity('setterGetter');
entity.name('Me');
expect(entity.name()).to.equal('Always');var entity = gleam.entity('setterGetter');
entity.address('Address');
expect(entity.address()).to.equal('Always');expect(entity.isValid('email', 'nik@butenko.me')).to.be.true;expect(entity.isValid('email', 'wrong@email')).to.be.false;expect(entity.getProperty('id')).to.equal(1);expect(function () {
entity.getProperty('wrong');
}).to.throw('Accessing undefined property [user.wrong]');var entity = gleam.fromJson(userWithTestJson);
expect(entity.getFlat()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me"});var entity = gleam.fromJson(requireText('./fixtures/user-with-arrays.json'));
expect(entity.getFlat()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me", tests: [], messages: ["Message 1", "Message 2"]});var entity = gleam.entity('user');
expect(entity.initial()).to.deep.equal({id: undefined, name: undefined, email: undefined});var entity = gleam.entity('user', userData);
expect(entity.initial()).to.deep.equal({id: 1, name: "Nik", email: "nik@butenko.me"});var entity = gleam.entity('user');
entity.set({id: 1});
expect(entity.initial().id).to.be.undefined;var entity = gleam.entity('user');
expect(entity.modified()).to.deep.equal({id: false, name: false, email: false});var entity = gleam.entity('user');
entity.set({id: 1});
expect(entity.modified().id).to.be.true;
expect(entity.modified().email).to.be.false;expect(entity.is('user')).to.be.true;expect(entity.is('not/user')).to.be.false;var entity = gleam.fromJson(userJson);
expect(entity.toJSON()).to.deep.equal(userData);var entity = gleam.fromJson(userWithTestJson);
expect(entity.toJSON()).to.deep.equal(userWithTestData);var entity = gleam.fromJson(userJson);
expect(spaceFix(JSON.stringify(entity))).to.equal(spaceFix(userJson));var entity = gleam.fromJson(userWithTestJson);
expect(spaceFix(JSON.stringify(entity))).to.equal(spaceFix(userWithTestJson));var json = requireText('./fixtures/user-with-arrays.json'),
entity = gleam.fromJson(json);
expect(spaceFix(JSON.stringify(entity))).to.equal(spaceFix(json));var entity = gleam.entity('user');
expect(entity.toString()).to.equal('[object Gleam:user]');var entity = gleam.entity('user/test');
expect(['', entity].join('')).to.equal('[object Gleam:user/test]');