-
Notifications
You must be signed in to change notification settings - Fork 10
TypeScript Node.js sample
This sample requires nodejs and TypeScript.
Start by creating a directory to house your code.
From a command line within your new directory, initialize a new project via:
npm init
Next, install and initialize TypeScript via:
npm i typescript --save-dev
tsc --init --target es6
Finally, install peasy-js via:
- npm:
npm install peasy-js
.
Now let's write some code. Create a file (person.ts) with the following content:
// person.ts
export interface IPerson {
id: number;
name: string;
city: string;
}
Next create a data proxy by creating a file (personDataProxy.ts) with the following content:
// personDataProxy.ts
declare const Promise: any;
import { IDataProxy } from 'peasy-js';
import { IPerson } from './person';
export class PersonDataProxy implements IDataProxy<IPerson, number> {
private _data: IPerson[] = [];
public getById(id: number): Promise<IPerson> {
const person = this._findBy(id);
return Promise.resolve(person);
}
public getAll(): Promise<IPerson[]> {
return Promise.resolve(this._data);
}
public insert(data: IPerson): Promise<IPerson> {
data.id = this._data.length + 1;
const newPerson = Object.assign({} as IPerson, data);
this._data.push(newPerson);
return Promise.resolve(data);
}
public update(data: IPerson): Promise<IPerson> {
const person = this._findBy(data.id);
Object.assign(person, data);
return Promise.resolve(data);
}
public destroy(id: number): Promise<void> {
const person = this._findBy(id);
const index = this._data.indexOf(person);
this._data.splice(index, 1);
return Promise.resolve();
}
private _findBy(id: number): IPerson {
const person = this._data.filter(p => {
return p.id === id;
})[0];
return person;
}
}
Then, create a business service file (personService.ts), which exposes CRUD commands responsible for subjecting data proxy invocations to business rules before execution:
// personService.ts
import { BusinessService, IDataProxy } from "peasy-js";
import { IPerson } from "./person";
export class PersonService extends BusinessService<IPerson, number> {
constructor(dataProxy: IDataProxy<IPerson, number>) {
super(dataProxy);
}
}
Now let's consume our PersonService by creating a file (example.ts) with the following contents:
// example.ts
import { PersonService } from "./personService";
import { PersonDataProxy } from "./personDataProxy";
import { IPerson } from "./person";
const personService = new PersonService(new PersonDataProxy());
const command = personService.insertCommand({name: "James Morrison"} as IPerson);
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: tsc && node example.js
Let's create a business rule file (personNameRule.ts) whose execution must be successful before the call to inject dataproxy.insert() function is invoked.
// personNameRule.ts
declare const Promise: any;
import { Rule } from "peasy-js";
export class PersonNameRule extends Rule {
constructor(private name: string) {
super();
this.association = "name"; // optional
}
protected _onValidate(): Promise<void> {
if (this.name === "Jimi Hendrix") {
this._invalidate("Name cannot be Jimi Hendrix");
}
return Promise.resolve();
}
}
And wire it up in our PersonService to ensure that it gets fired before inserts:
// personService.ts
declare const Promise: any;
import { BusinessService, IDataProxy, IRule } from "peasy-js";
import { IPerson } from "./person";
import { PersonNameRule } from "./personNameRule";
export class PersonService extends BusinessService<IPerson, number> {
constructor(dataProxy: IDataProxy<IPerson, number>) {
super(dataProxy);
}
protected _getRulesForInsertCommand(person: IPerson, context: any): Promise<IRule[]> {
return Promise.resolve([
new PersonNameRule(person.name)
]);
}
}
Testing it out ...
// example.ts
import { PersonService } from "./personService";
import { PersonDataProxy } from "./personDataProxy";
import { IPerson } from "./person";
const personService = new PersonService(new PersonDataProxy());
const command = personService.insertCommand({name: "Jimi Hendrix"} as IPerson);
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: tsc && node example.js
Let's create one more rule (validCityRule.ts), just for fun:
// validCityRule.ts
declare const Promise: any;
import { Rule } from "peasy-js";
export class ValidCityRule extends Rule {
constructor(private city: string) {
super();
this.association = "city"; // optional
}
protected _onValidate(): Promise<void> {
if (this.city === "Nowhere") {
this._invalidate("Nowhere is not a city");
}
return Promise.resolve();
}
}
We'll associate this one with inserts too:
// personService.ts
declare const Promise: any;
import { BusinessService, IDataProxy, IRule } from "peasy-js";
import { IPerson } from "./person";
import { PersonNameRule } from "./personNameRule";
import { ValidCityRule } from "./validCityRule";
export class PersonService extends BusinessService<IPerson, number> {
constructor(dataProxy: IDataProxy<IPerson, number>) {
super(dataProxy);
}
protected _getRulesForInsertCommand(person: IPerson, context: any): Promise<IRule[]> {
return Promise.resolve([
new PersonNameRule(person.name),
new ValidCityRule(person.city)
]);
}
}
And test it out ...
// example.ts
import { PersonService } from "./personService";
import { PersonDataProxy } from "./personDataProxy";
import { IPerson } from "./person";
const personService = new PersonService(new PersonDataProxy());
const command = personService.insertCommand({name: "Jimi Hendrix", city: "Nowhere"} as IPerson);
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: tsc && node example.js
Finally, let's pass in valid data and watch it be a success
// example.ts
import { PersonService } from "./personService";
import { PersonDataProxy } from "./personDataProxy";
import { IPerson } from "./person";
const personService = new PersonService(new PersonDataProxy());
const command = personService.insertCommand({name: "James Hendrix", city: "Madison"} as IPerson);
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: tsc && node example.js
Want to learn more?