Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Remote objects - Create backends for one page web apps with ease. Uses mongo and express.
Create backends for one page web apps with ease. Uses mongo and express.
Reob is an opinionated framework to create backends for one page web apps. It combines object mapping, networking and a webserver. You write domain object classes and service classes and use them from the client. You can call functions on an object that causes an http request to the server which loads the object there, invokes the function on it and transmits the result back to the client. Reob takes care of the database and network specifics. It is written in typescript and makes heavy use of decorators.
In order to get an overview of how reob works let's look at an example. Imagine you want to write a tool for a club of garden owners.
In our example we create two classes. Garden and Plant. A garden that has an array of plants.
Here is the simple class Plant
which will be used as part of a garden.
import * as reob from "reob"
@reob.Entity
export class Plant{
height:number = 1;
type:string;
constructor( theType:string ){
this.type = theType;
}
@reob.RemoteCollectionUpdate
grow( n:number ){
this.height += n;
}
}
This class contains two decorators. @reob.Entity
let's reob know that it is an entity. An Entity is a term used in
datamodelling that describes something that is separated from other things, has data and behaviour. The term is a bit
unwieldy. It boils down to: Entities are the data-things that matter in a project.
Entities can be saved and loaded from the database and transmitted over the network.
@reob.RemoteCollectionUpdate
combines the core features of reob and we'll get to it later. So much for now: It allows you
to call the function from the server through the server and the changes made on the object are persisted into the database.
import * as reob from "reob"
import {Plant} from "./Plant"
@reob.Entity
export class Garden{
_id:string;
bees:number;
@reob.ArrayType("Plant")
plants:Array<Plant> = [ new Plant( "Rose") ];
constructor( initialBeeCount:number ){
this.bees = initialBees;
}
The decorator @reob.ArrayType
tells reob what type of objects the array contains. Omm can now save and load Gardens from the mongo
database and transmit them over the network and the objects inside the plants
array will be instances of Plant
.
Now that we've created the domain objects, it is time to think about how they are loaded and saved to the mongo collection.
import * as reob from "reob"
import {Garden} from "./Garden"
export class GardenCollection extends Collection<Garden>{
constructor(){
super( Garden, 'gardens' ); // 'gardens' is the name of the collection in the mongo db
}
}
The class is a representation of the mongo collection that adds the reob behaviour on top of it. The original mongo collection
can be accessed using getMongoCollection()
.
This class deals with all things related to the garden that are not internal to the garden. There is one class for the client and one for the server. The client version is just a stub to call the functions on. Omm monkey patches the functions and routes them to the server. This is mostly needed to keep tools like browserify from including i.E mongo in the bundle that is used on the client.
import * as reob from "reob"
import {GardenCollection} from "./GardenCollection"
import {Garden} from "./Garden"
export class GardenService{
constructor(){
}
@reob.Remote
countPlants(bees:number):Promise<number>{
return undefined; // never called
}
@reob.Remote
createGarden( initialBees:number ):Promise<string>{
return undefined; // replaced with result from the server
}
@reob.Remote
getGarden(id:string):Promise<Garden>{
return undefined; // replaced with result from the server
}
}
The version of the service that's used on the server. It contains the implementations of the functions.
import * as reob from "reob"
import {GardenCollection} from "./GardenCollection"
import {Garden} from "./Garden"
export class GardenServiceServer{
constructor( private gardenCollection:GardenCollection){
}
@reob.Remote
countPlants(bees:number):Promise<number>{
return this.gardenCollection.find({
"bees" : bees
}).then( (gardens:Array<Garden>) => {
var sum = 0;
gardens.forEach((g:Garden)=>{
sum += g.plants.length;
});
return sum;
});
}
@reob.Remote
createGarden( initialBees:number ):Promise<string>{
var g:Garden = new Garden( initialBees );
return this.gardenCollection.insert(garden);
}
@reob.Remote
getGardens():Promise<Array<Garden>>{
return this.gardenCollection.getAll(); // this should be limited in the real world
}
@reob.Remote
getGarden( id:string ):Promise<Garden>{
return this.gardenCollection.getByIdOrFail( id );
}
}
The @reob.Remote
decorator tells reob that the functions can be called from the client.
This far we've not written a single line of code that concerns itself too much with network or database access. Let's keep it that way. This is the file that is run in the node server.
import {Server} from "reob/server"
import {GardenCollection} from "./GardenCollection"
import {GardenServiceServer} from "./GardenServiceServer"
var server = new Server("mongodb://localhost/test");
var gardenCollection = new GardenCollection();
server.addCollection( gardenCollection );
var gardenServiceServer = new GardenServiceServer( gardenCollection );
server.addService( gardenServiceServer );
server.serveStatic("./webroot");
server.start(8080).then(()=>{
console.log("Server is running");
});
Use your tool of choice to convert the client creobonjs module to code that runs on the client.
import * as reob from "reob"
import {GardenService} from "./GardenService"
var client = new reob.Client(window.location.origin, 8080);
var gardenService = new GardenService();
client.addService( gardenServie );
window.gardenService = gardenService;
<html>
<head>
<!-- load bundled javascript based on main_client.ts here -->
</head>
<body>
<span id="result"></span>
<hr/>
<button id="createGarden">Create Garden</button>
<button id="grow">grow Plant</button>
<!-- hook up buttons to javascript. use jquery. -->
</body>
<html>
Perform collection altering operations anywhere on the object graph
Strengthens encapsulation of objects by removing persistence logic from the domain logic
Atomicity over complex operations within one document
Client & Server components that bring mongo collection access to the client
... still need to figure out what the most fitting license is. Any suggestions? Open an issue!
FAQs
Remote objects - Create backends for one page web apps with ease. Uses mongo and express.
The npm package reob receives a total of 2 weekly downloads. As such, reob popularity was classified as not popular.
We found that reob demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.