Google Cloud Datastore ORM - node.js

Is there some high level ORM for nodejs datastore client library? Because it becoming really hard to maintain relatively small application when entities referencing and objects versioning takes place. Just interested, should I start write my own bicycle or someone already wrote something like that?
If not, maybe there some separate libraries to implemented appropriate referencing mechanism?

Check out gstore-node:
gstore-node is a Google Datastore entities modeling library for Node.js inspired by Mongoose and built on top of the #google-cloud/datastore library.
It is not a replacement of #google-cloud/datastore but a tool built to help modeling Entities through Schemas and to help validating the data saved in the Datastore.

You may try on this one, very well structure, written in Typescript.
https://www.npmjs.com/package/ts-datastore-orm
import {BaseEntity, Column, Entity} from "ts-datastore-orm";
#Entity({kind: "user"})
export class User extends BaseEntity {
#Column({generateId: true})
public id: number = 0;
#Column({index: true})
public total: number = 0;
}
async function main() {
const user = User.create();
await user.save();
const id = user.id;
}

Related

How can I get model reference on the fly nestjs mongoose

So my problem is I have models that is separated by one of our domain's types, and it has a lot of types which each one of em has a dedicated collection. As I know, we can inject the model in the service constructor like this way:
#InjectModel(ModelName.Job) private readonly jobModel: JobModel,
It is a bit messy to me to inject all of those collections in the constructor, and also they are not useful at the same time. So I wonder if I could load mongoose model dynamically inside the service's method using the our domain type as the key, more or less same as the module reference like this:
private getModelReference(reference: any) {
return this.moduleReference.get(ModelName[reference]);
}
But, any other workarounds to load the model dynamically on the fly are appreciated.
It is technically possible to do. Using your code above you can do
private getModelReference(reference: any) {
return this.moduleReference.get(getModelToken(ModelName[reference]));
}
Assuming that ModelName[reference] refers back to a mongoose model name (i.e. Cat.name or just 'Cat')

MongoDB-Mongoose Typescript Generic Requests

I'm creating a helper class for all my database functions with MongoDB. While I'm doing it, I thought if it's possible to create Generic database functions for MongoDB with mongoose.
I tested a little bit, but didn't come to a result.
I'm using like I mentioned MongoDB with mongoose in combination with Typescript.
export async function getByID<T>(id: string): Promise<T> {
const found: T = await T.findById(id);
return found;
}
My codeexample is not working right now, but it should demonstrate what I want to achive. I hope you guys can help me.

What is the best way to organize the code of a nodejs-express project, using TypeScript?

While trying to organize the code of my first NodeJS-express project, I ran into some doubts about the use of namespaces, modules and classes. When to choose one? When another?
For example, my project is structured (simplifying) in.
routers -> controllers -> services -> repositories.
The possibilities I thought of to manage these "entities" are the following:
Classes
Classes with static methods
Singletons
Simple module export
Namespaces
Classes
I thought of avoiding them right away, since the above-mentioned entities do not need to memorize any state. Furthermore, they would complicate the code due to the need to be instantiated.
Classes with static methods
They are correct? Or rather a simple namespace or simple export of the modules?
Class + Singletons
A way of organizing the code in a "nicer" way than the simple class, but which does not convince me, since reading on the net that the singleton in TypeScript is replaceable with the namespace.
Simple module export
The way I thought to implement immediately, for example in this way (file user.repository.ts):
const add = async (user: User): Promise<void> => {
if(await canBeAdded(user)) {
//save user;
} else {
// throw error
}
}
export const UserRepository = {
add
}
It's corrects? Or am I not properly using what TypeScript offers? Being the first time I use this language, I would like to be sure I chose the right path.
Namespaces
Are they a better choice to develop the code published above? Are you advised against?
Thank you in advance for the answers! Any advice is welcome!
P.S. I know that, once the TypeScript is compiled, in Javascript the classes are practically syntactic sugar. What I'm interested in knowing are the best practices for writing good code in TypeScript.

Abstracting class using mongoose

I'm developing an application in which I need to have some abstraction.
I mean there, that I would like to "simulate" an interface behaviour like creating a contract inside of my concrete classes.
Actually, dealing with Users, I'm having a UserMongoRepository class with the contract implemented :
getAll() returns the full list of users by promise
getById(id) returns the user concerned by promise
save(user) saves the user by promise
... etc
I have the same methods implemented inside of the UserMysqlRepository (allowing me to switch behaviour when a change is needed.
Problem
My problem is that I'm dealing with Mongoose that doesn't act like a datamapper, but more like an active record.
It means that my implementation of save(user) would be a bit weird like following :
save(user){
let mongooseUser = this.convert(user);
return user.save();
}
The convert method allows me to switch from a standard Model to a specific Mongoose model. It allows me, again, to have some abstraction and to don't have to rewrite my full application data access.
My real problem is when I try to unit test my full class :
import MongooseUser from '../../auth/mongooseModel/MongooseUser';
/**
* UserMongoRepositoryclass
*/
export default class UserMongoRepository{
/**
* Create an UserMongoRepository
*/
constructor(){
}
/**
* Convert a User to a MongooseUser
*/
convert(user){
return new MongooseUser({email:user.mail,password:user.password,firstname:user.firstName, lastname:user.lastName});
}
findById(id){
return MongooseUser.find({id:id});
}
save(user){
return user.save();
}
}
In a standard way, I would inject my DAO inside of my constructor, and being able to mock it.
In the case of mongoose, it's a bit disturbing, because the element that makes the job isn't an instantiated object (so that I can mock it) but a class definition imported at the top of the document.
Solutions
Should I pass the MongooseUser class definition as a parameter inside of the constructor ?
Implying that I will have this code inside of the convert method :
let user = new this.MongooseUser({})
Have you got a better idea, to abstract mongoose behaviour in data mapper way ?
I don't want to use another module, it's, in my sense, the most advanced one with NodeJS...
I'm not familiar with the import syntax (nor EMCASCRIPT-6), though you say you're using node.js, so I'd recommend using the proxquire package. The idea is that the package allows you to require an external package, while stubbing the requirements that that package would use. So in your case, you could do something like:
proxyquire('../my/class/that/uses/mongoose', {
mongoose: MyTestMongooseImplementation
})
Which would allow you to use your own mongoose implementation while still using your MongooseUser as you have defined it in your package. Alternatively, you could just override the the MongooseUser class (path relative to the the file whose requirements you are stubbing:
proxyquire('/path/to/UserMongooseRepository', {
'../../auth/mongooseModel/MongooseUser': MyTestMongooseUser
})
Documentation: https://www.npmjs.com/package/proxyquire

OOP with MVC using Mongoose & Express.js

I'm creating an Express.js app in which I want to use the MVC pattern and Mongoose for the document mapping to a MongoDB database. I've created a folder for models and I want to derive everything from (Javascript's version of) abstract classes for better code organization.
I'm confused about what the best way is to organize the abstract classes and set default values that each instance of the models should be. For example, one way is to use Mongoose Schemas for abstract classes, and then use Mongoose models for the models themselves:
Feline.js:
var mongoose = require('mongoose');
var Feline = mongoose.Schema({
size: 'Number'
});
Feline.methods.getSize = function () {
return this.size;
}
module.exports = Feline;
HouseCat.js:
var mongoose = require('mongoose')
, FelineSchema = require('./Feline.js');
var HouseCatModel = mongoose.model('HouseCat', FelineSchema)
, HouseCat = new HouseCatModel({
size: 1 //Domesticated cats are small
});
module.exports = HouseCat;
There are a few problems with this design. For one, I would think there must be a better way to set specific properties for the each model without instantiating a new model object each time the client wants to create a new instance of a model type. For another, using this scheme, Mongoose has to be required in every model file, and the code is custom-tailored to use mongoose, which means it will be difficult to switch to another ODM if we want to do that in the future.
Is there any better way of coding this? And is there any design pattern which is easy enough to implement in Node that will allow for easy changing of the ODM?
As mongoose is specific to mongodb, this will be a hard task to abstract its behaviour.
The easiest way to do it is to set an interface for all ODMs and use an adapter pattern where mongoose is an "adaptee". Then, you can use a module providing some dependency injection to replace the used ODM.
As it is a really long task, I cannot give you some code. Moreover, it may be a pain to implement that kind of thing in javascript because it does not provide strong OOP natively. However, I can suggest you to take a look at some frameworks which can help you to do that like Danf for instance which provides a strong OOP paradigm with interfaces, classes, inheritance and a powerful dependency injection.

Resources