-
Notifications
You must be signed in to change notification settings - Fork 10
Node.js sample
This sample requires nodejs.
Start by creating a directory to house your code.
From a command line within your new directory, initialize a new project via:
- yarn:
yarn init
- npm:
npm init
Next, install peasy-js via:
- yarn:
yarn add peasy-js
. - npm:
npm install peasy-js
.
Next create a data proxy by creating a file (personDataProxy.js) with the following content:
// personDataProxy.js
class PersonDataProxy {
constructor() {
this._data = [];
}
getById(id) {
var person = this._findBy(id);
return Promise.resolve(person);
}
getAll() {
return Promise.resolve(this._data);
}
insert(data) {
data.id = this._data.length + 1;
var newPerson = Object.assign({}, data);
this._data.push(newPerson);
return Promise.resolve(data);
}
update(data) {
var person = this._findBy(data.id);
Object.assign(person, data);
return Promise.resolve(data);
}
destroy(id) {
var person = this._findBy(id);
var index = this._data.indexOf(person);
this._data.splice(index, 1);
return Promise.resolve();
}
_findBy(id) {
var person = this._data.filter((function(p) {
return p.id === id;
}))[0];
return person;
}
}
module.exports = PersonDataProxy;
Then, create a business service file (personService.js), which exposes CRUD commands responsible for subjecting data proxy invocations to business rules before execution:
// personService.js
var BusinessService = require('peasy-js').BusinessService;
class PersonService extends BusinessService {
constructor(dataProxy) {
super(dataProxy);
}
}
module.exports = PersonService;
Now let's consume our PersonService by creating a file (example.js) with the following contents:
// example.js
var PersonDataProxy = require('./personDataProxy');
var PersonService = require('./personService');
var personService = new PersonService(new PersonDataProxy());
var command = personService.insertCommand({name: "James Morrison"});
command.execute().then(result => {
if (result.success) {
console.log(result.value); // prints the inserted object with the assigned id
}
});
Testing it out from command line: node example.js
Let's create a business rule file (personNameRule.js) whose execution must be successful before the call to inject dataproxy.insert() function is invoked.
// personNameRule.js
var Rule = require('peasy-js').Rule;
class PersonNameRule extends Rule {
constructor(name) {
super();
this.name = name;
this.association = "name" // optional
}
_onValidate() {
if (this.name === "Jimi Hendrix") {
this._invalidate("Name cannot be Jimi Hendrix");
}
return Promise.resolve();
}
}
module.exports = PersonNameRule;
And wire it up in our PersonService to ensure that it gets fired before inserts:
// personService.js
var BusinessService = require('peasy-js').BusinessService;
var PersonNameRule = require('./personNameRule');
class PersonService extends BusinessService {
constructor(dataProxy) {
super(dataProxy);
}
_getRulesForInsertCommand(person, context) {
return Promise.resolve([
new PersonNameRule(person.name)
]);
}
}
module.exports = PersonService;
Testing it out ...
// example.js
var PersonDataProxy = require('./personDataProxy');
var PersonService = require('./personService');
var dataProxy = new PersonDataProxy();
var personService = new PersonService(dataProxy);
var command = personService.insertCommand({name: "Jimi Hendrix"});
command.execute().then(result => {
if (result.success) {
console.log(result.value);
} else {
console.log(result.errors[0]); // prints {association: "name", message: "Name cannot be Jimi Hendrix"}
}
});
Testing it out from command line: node example.js
Let's create one more rule (validCityRule.js), just for fun:
// validCityRule.js
var Rule = require('peasy-js').Rule;
class ValidCityRule extends Rule {
constructor(city) {
super();
this.city = city;
this.association = "city" // optional
}
_onValidate() {
if (this.city === "Nowhere") {
this._invalidate("Nowhere is not a city");
}
return Promise.resolve();
}
}
module.exports = ValidCityRule;
We'll associate this one with inserts too:
// personService.js
var BusinessService = require('peasy-js').BusinessService;
var PersonNameRule = require('./personNameRule');
var ValidCityRule = require('./validCityRule');
class PersonService extends BusinessService {
constructor(dataProxy) {
super(dataProxy);
}
_getRulesForInsertCommand(person, context) {
return Promise.resolve([
new PersonNameRule(person.name),
new ValidCityRule(person.city)
]);
}
}
module.exports = PersonService;
And test it out ...
// example.js
var PersonDataProxy = require('./personDataProxy');
var PersonService = require('./personService');
var dataProxy = new PersonDataProxy();
var personService = new PersonService(dataProxy);
var command = personService.insertCommand({name: "Jimi Hendrix", city: "Nowhere"});
command.execute().then(result => {
if (result.success) {
console.log(result.value);
} else {
console.log(result.errors[0]); // prints {association: "name", message: "Name cannot be Jimi Hendrix"}
console.log(result.errors[1]); // prints {association: "city", message: "Nowhere is not a city"}
}
});
Testing it out from command line: node example.js
Finally, let's pass in valid data and watch it be a success
// example.js
var PersonDataProxy = require('./personDataProxy');
var PersonService = require('./personService');
var dataProxy = new PersonDataProxy();
var personService = new PersonService(dataProxy);
var command = personService.insertCommand({name: "James Hendrix", city: "Madison"});
command.execute().then(result => {
if (result.success) {
console.log(result.value); // prints the inserted object with the assigned id
} else {
console.log(result.errors);
}
});
Testing it out from command line: node example.js
Want to learn more?
- View this sample in TypeScript.
- View this sample consuming it from a browser.
- You can read in-depth coverage about peasy-js on the wiki.
- An entire business logic implementation using peasy-js can be viewed here. This sample application is an order entry / inventory management system written with peasy-js, react, angular (with TypeScript), mongoDB, nodejs, and express.