Coder Social home page Coder Social logo

nestjs-objection's Introduction

NestJS Objection

NPM Version NPM Downloads Package License

Table of Contents

Description

Integrates Objection.js and Knex with Nest

Installation

$ npm install nestjs-objection knex objection

You can also use the interactive CLI

npx nestjs-modules

Features

  • Decorators @InjectModel, @Table, @Column, @Relation
  • Synchronization synchronize(model, force?)
  • SoftDelete @Table({ softDelete: true })

Table options

Name Type Required Default
tableName string true className
softDelete boolean / string false false

Column options

Name Type Required Default
type columnTypes true ---
default any false ---
columnName string false false
nullable boolean false false
notNullable boolean false false
unique boolean false false
unsigned boolean false false
primary boolean false false

synchronize(model, force?)

Name Type Required Default
model Model true ---
force boolean false false

softDelete

Method Type Options Return
delete function --- QueryBuilder
softDelete function --- QueryBuilder
forceDelete function --- QueryBuilder
withDeleted function --- QueryBuilder
onlyDeleted function --- QueryBuilder
restore function --- QueryBuilder

columnTypes

--- --- --- ---
increments bigIncrements integer bigInteger
text string float decimal
boolean date datetime time
timestamp timestamps binary json
jsonb uuid

Examples

$ npm install nestjs-objection knex objection sqlite3

Models

// app.models.ts
import { 
  Model, Column, Relation, Table, relationTypes, columnTypes, 
} from 'nestjs-objection';

@Table({ tableName: 'posts' })
export class Post extends Model {
  @Column({ type: columnTypes.increments })
  id: number;
  @Column({ type: columnTypes.integer })
  userId: number;
  @Column({ type: columnTypes.string })
  title: string;
  @Column({ type: columnTypes.json })
  json: object;
}

@Table({ tableName: 'users' })
export class User extends Model {
  @Column({ type: columnTypes.increments })
  id: number;
  @Column({ type: columnTypes.string })
  name: string;
  @Relation({ 
    modelClass: Post, 
    relation: relationTypes.HasManyRelation, 
    join: { from: 'users.id', to: 'posts.userId' } 
  })
  posts: Post[];
}

ObjectionModule.forRoot(options, connection?)

// app.module.ts
import { Module } from '@nestjs/common';
import { ObjectionModule, Model } from 'nestjs-objection'
import { AppController } from './app.controller';
import { User, Post } from './app.models';

@Module({
  imports: [
    ObjectionModule.forRoot({
      Model,
      config: {
        client: "sqlite3",
        useNullAsDefault: true,
        connection: ':memory:',
      }
    }),
    ObjectionModule.forFeature([User, Post]),
  ],
  controllers: [AppController],
})
export class AppModule {}

ObjectionModule.forRootAsync(options, connection?)

// app.module.ts
import { Module } from '@nestjs/common';
import { ObjectionModule, Model } from 'nestjs-objection'
import { AppController } from './app.controller';
import { User, Post } from './app.models';

@Module({
  imports: [
    ObjectionModule.forRootAsync({
      useFactory: () => ({
        Model,
        config: {
          client: "sqlite3",
          useNullAsDefault: true,
          connection: ':memory:',
        },
      }),
    }),
    ObjectionModule.forFeature([User, Post]),
  ],
  controllers: [AppController],
})
export class AppModule {}

InjectModel(Model, connection?)

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { 
  InjectModel, 
  synchronize, 
  InjectConnection, 
  Connection, 
} from 'nestjs-objection';
import { User, Post } from './app.models';

@Controller()
export class AppController {
  constructor(
    @InjectModel(User) private readonly userModel: typeof User,
    @InjectModel(Post) private readonly postModel: typeof Post,
    @InjectConnection() private readonly connection: Connection,
  ) {}

  @Get()
  async getHello() {
    await synchronize(User);
    await synchronize(Post);
    await this.userModel.query().insert({ name: 'Name' });
    await this.postModel.query().insert({ title: 'Title', userId: 1 });

    const users = await this.userModel
      .query()
      .select(['users.name'])
      .withGraphJoined('posts')
      .modifyGraph('posts', q => q.select(['posts.title']));

    const posts = await this.connection.table('posts');

    return { users, posts };
  }
}

SoftDeleteModel

import { SoftDeleteModel, columnTypes } from 'nestjs-objection';

@Table({ tableName: 'users', softDelete: true })
export class User extends SoftDeleteModel {
  @Column({ type: columnTypes.increments })
  id: number;
  @Column({ type: columnTypes.datetime })
  deletedAt: Date;
}
ObjectionModule.forRoot({
  Model: SoftDeleteModel,
  config: { /* ... */ }
})
this.userModel.query().where({ id: 1 }).delete(); // or softDelete()
this.userModel.query().where({ id: 1 }).withDeleted();
this.userModel.query().where({ id: 1 }).onlyDeleted();
this.userModel.query().where({ id: 1 }).forceDelete();
this.userModel.query().where({ id: 1 }).restore();

Typescript

// src/index.d.ts
declare module 'objection' {
  interface WhereMethod<QB extends AnyQueryBuilder> {
    <T>(columns: Partial<T>): QB;
    <T>(column: Partial<keyof T>, op: string, value: any): QB;
  }
  interface OrderByMethod<QB extends AnyQueryBuilder> {
    <T>(column: keyof T, order?: 'asc' | 'desc'): QB;
    <T>(columns: (Array<{ column: keyof T; order?: 'asc' | 'desc' }>)): QB;
  }
  interface SelectMethod<QB extends AnyQueryBuilder> {
    <T>(...columnNames: Array<Partial<keyof T>>): QB;
    <T>(columnNames: Array<Partial<keyof T>>): QB;
  }
  interface QueryBuilder<M extends Model, R = M[]> extends Promise<R> {
    forceDelete(): this;
    withDeleted(): this;
    onlyDeleted(): this;
    softDelete(): this;
    restore(): this;
  }
}
// with type-safe
const users = await this.userModel
  .query()
  .select<User>(['name'])
  .where<User>({ name: 'Name' })
  .orderBy<User>('name', 'desc')
  .withGraphFetched('posts')
  .modifyGraph('posts', q => q.select<Post>(['title']));

// without type-safe
const users = await this.userModel
  .query()
  .select(['name'])
  .where({ name: 'Name' })
  .orderBy('name', 'desc')
  .withGraphFetched('posts')
  .modifyGraph('posts', q => q.select(['title']));

License

MIT

nestjs-objection's People

Contributors

svtslv avatar dependabot[bot] avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.