npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@topmodel/core

v1.0.4

Published

TopModel Core package

Downloads

6

Readme

@topmodel/core

Modern ORM for minimalist coders

  • 0 dependency !
  • Test driven

Installation

With npm

npm install @topmodel/core

or yarn

yarn add @topmodel/core

Index

Basic

TopModel works as an extend on Javascript Classes

import { Model } from '@topmodel/core'

class User extends Model {
    // ... constructor or other properties
}

const user = new User({ firstname: 'John', lastname: 'Doe' })

// your model is now on steroids 💪

Constructor

TopModel extended classes can activate features by populating options in the constructor super call with the following arguments super(data, options)

  • data - your object data
  • options - TopModel options object

Example

import { Model } from '@topmodel/core'

const options = { /* ... your options */ }

class User extends Model {
    constructor(data){
        super(data, options)
    }
}

const user = new User({ firstname: 'John', lastname: 'Doe' })
// user will now inherit from more powerful features

Options

Options can power your classes with features, plugins etc...

TopModel includes the following options by default:

Database relation

Note: by default topmodel core will attribute a table name related to your model name, for example model User will become user table in SQL or collection in Mongo.

options.db

You can connect a Plugin to allow your model to interact with a distant database. Our first plugin is Mongo

Example

import { Model } from '@topmodel/core'
import { MongoPlugin } from '@topmodel/mongo'

const { MONGO_URL, MONGO_DATABASE } = process.env

const db = new MongoPlugin({
    url: MONGO_URL,
    database: MONGO_DATABASE
})

class User extends Model {
    constructor(data){
        super(data, { db })
    }
}

const user = new User({ /*... data */ })
await user.save() // save to mongo

options.table

This option is forcing your model to work with a specific db table (for example a collection in Mongo or depending then on the db plugin)

For example is you want to force your mongo plugin to work with the collection parents 

const db = new MongoPlugin({
    url: MONGO_URL,
    database: MONGO_DATABASE
})

const table = 'parents'

class User extends Model {
    constructor(data){
        super(data, { db, table })
    }
}

// now User will interact with the 'parents' collection

options.exposer

The exposer feature allows you to display only a part of your object, super useful in API management.

User(id, firstname, lastname, city)
User.expose('public') => User(id)

Example

import { Model } from '@topmodel/core'

const exposer = {
    public: [
        'id'
    ]
}

class User extends Model {
    constructor(data){
        super(data, { exposer })
    }
}

const user = new User({ id: 1234, firstname: 'John', lastname: 'Doe' })

console.log(user.expose('public')) // { id: 1234 }

options.schema

You can add a schema to any TopModel extended class to activate feature such as validation for example. More documentation in the schema section

Example

import { Model, Schema } from '@topmodel/core'

const schema = new Schema({
    firstname: {
        type: String
    }
})

class User extends Model {
    constructor(data){
        super(data, { schema })
    }
}

Schema

Schemas allows you to use TopModel for validation. Properties options are the following :

  • type - data type to be validated (see JS Types)
  • required - boolean, to specify if an object is required or not
  • default - default value when unspecified
const schema = new Schema({
    firstname: {
        type: String,
        required: true
    },
    lastname: {
        type: String,
        required: true
    },
    created_at: {
        type: Date,
        default: new Date()
    }
})

class User extends Model {
    constructor(data){
        super(data, { schema })
    }
}

Nested Schemas

You can also nest schemes, validation will work recursively based on the sub property of each schema element.

const schema = new Schema({
    job: {
        type: Object,
        sub: {
            title: {
                type: String,
                required: true
            }
        }
    },
    created_at: {
        type: Date,
        default: new Date()
    }
})

Validation

Topmodel includes a no-dependency fully integrated validation system

{model}.validation

You can use object schema validation by calling the getter {model}.validation

Example with valid data:

const schema = new Schema({
    firstname: {
        type: String
    }
})

class User extends Model {
    constructor(data){
        super(data, { schema })
    }
}

const user = new User({ firstname: 'John' })

console.log(user.validation)
/*
{
    values: { firstname: 'John' }
}
*/

Invalid data will populate an errors object with the detail of each error

Example with invalid data:

const schema = new Schema({
    firstname: {
        type: String
    }
})

class User extends Model {
    constructor(data){
        super(data, { schema })
    }
}

const user = new User({ hack: 847846 })

console.log(user.validation)
/*
{
    errors: [{
        key: 'hack',
        message: 'not in schema'
    }]
}
*/

{model}.validate()

You can also use the validation method {model}.validate() which has two main differences :

  • validate() will throw if an error occur
  • validate() doesn't return any value if valid, because it's chainable ❤️

Usage :

With valid data & chained :

// model setup
const exposer = {
    public: [
        'id'
    ]
}

const schema = new Schema({
    id : {
        type: Number
    }
    firstname: {
        type: String
    }
})

class User extends Model {
    constructor(data){
        super(data, { schema, exposer })
    }
}

// [...]

const user = new User({ id: 847846, firstname: 'John-Michel' })

const exposed = user.validate().expose('public')
console.log(exposed) // { id: 847846 }

With invalid data :

// model setup
const schema = new Schema({
    firstname: {
        type: String
    }
})

class User extends Model {
    constructor(data){
        super(data, { schema })
    }
}

// [...]

const user = new User({ hack: 847846 })

try {
    user.validate()
} catch (errors){
    console.log(errors) // display validation errors
}