Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

leafodm

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

leafodm

MongoDB abstraction layer in TypeScript

  • 1.0.2
  • latest
  • npm
  • Socket score

Version published
Weekly downloads
2
Maintainers
1
Weekly downloads
 
Created
Source

Leaf ODM

npm npm type definitions

Leaf ODM is an abstraction layer for MongoDB on NodeJS. It aims to provide a better class support for MongoDB while keeping it's schema-less feature.

Philosophy

Nowadays the official MongoDB provides really good support and I think we don't really need any ODM/ORM for MongoDB on NodeJS, at least when using JavaScript. When using TypeScript, it's a bit different, most TS users want to use classes to have strong typing and prevent errors, but you can't pass a class instance to MongoDB.

Actual libraries such as TypeORM and Mongoose still have some issues:

  • TypeORM is the best for TypeScript users, but it seems to lose the schema-less feature (if you have a key that is not defined in your class).
  • Mongoose does not support classes and uses a JS object as schema (which does not allow optional and union types).

I was at this time trying to develop an API and I knew that some fields are dynamic and cannot be defined in a schema. As a TypeScript user, I tried TypeORM but lost the schema-less feature, and Mongoose was not adapted for the project.

So, I just decided to create my own abstraction layer on top of MongoDB's official driver.

Quick start

Start by installing the dependency:

# Using NPM:
npm install leafodm

# Using Yarn:
yarn add leafodm

Then, connect your database in your app entry-point:

import { DatabaseManager } from 'leafodm'

await DatabaseManager.init('mongodb://localhost:27017/database')

// With dotenv:
await DatabaseManager.init(process.env.DATABASE_URL)

Note: I highly recommend you to use dotenv here, never let your credentials hardcoded.

Now, you can define a model such as:

import { BaseEntity } from 'leafodm'

class User extends BaseEntity {
  name: string
  email: string
  password: string
}

That's done! You are now able run queries on your model, here are some examples:

Create an object

const user = new User()
user.name = 'John Doe'
user.email = 'jdoe@example.org'
user.password = 'abcd1234'

await user.create()

Find an object

await User.findOne({ email: 'jdoe@example.org' }) // -> Return first document that contains 'jdoe@example.org' as email
await User.findOne('60bbedee3310443e74b495da') // -> Return document by its ID

Find multiple objects

await User.find({ name: 'John Doe' }) // -> Every users with 'John Doe' as name
await User.find() // -> Return the whole collection

// It's also possible to set multiple conditions
await User.find({
  _id: '60bbedee3310443e74b495da',
  admin: true
}) // -> Return a user that correspond to this ID and that is an admin

Note: _id are automatically converted to ObjectId, even nested

Update an object

const user = await User.findOne('60bbedee3310443e74b495da')

user.name = 'John Doe Jr'

await user.update()

Delete an object

const user = await User.findOne('60bbedee3310443e74b495da')

await user.delete()

Sort by

const users = await User.sortBy({
  name: 'DESC'
}).find()

Take/Limit

const users = await User.take(5).find() // Will only return 5 documents

Skip

const users = await User.skip(5).find() // Will skip 5 first documents

Usage tips

This library is very useful when combined with class-transformer and class-validator, no need to instance your model and write data to every fields. Here is an example with the web framework FoalTS:

@Post('/register')
@ValidateBody(User)
async createUser(ctx: Context) {
  const user: User = ctx.request.body

  const exists = User.findOne({
    email: user.email
  })

  if (exists) {
    throw new HttpResponseBadRequest('this email is already taken')
  }

  return new HttpResponseOK({
    status: true,
    message: 'account created',
    data: await user.create(),
  });
}

Roadmap

You can follow and track the work on project.

My goals for future releases are:

  • Improve type support (e.g.: sortBy should suggest only properties)
  • Support more MongoDB methods (mass-insertion, mass-delete, etc.)
  • Add new static implementations such as User.delete(id) to prevent creating an instance before.
  • Add a constructor that takes JSON arguments (directly from requests) like: new User({ name: 'John Doe' }) (inspired from Laravel Eloquent)
  • Improve method chaining (sortBy, take and skip, this works but the code behind is not well maintainable)
  • Improve global structure and code coherence.
  • Provide a documentation

Contribution

Contributing is welcome, you can clone this project and make PR if you want! Just make sure you use same code style and follow ESLint.

If you find any bugs or suggestion, feel free to open an issue. For questions, please uses discussions.

Keywords

FAQs

Package last updated on 09 Jun 2021

Did you know?

Socket

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.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc