Home

Awesome

Deno Simple Orm

Build Status GitHub GitHub release (Deno)

dso is a simple ORM Library based on deno_mysql

Example

import {
  BaseModel,
  Defaults,
  dso,
  Field,
  FieldType,
  CharsetType,
  Index,
  IndexType,
  Join,
  Model,
  Where
} from "https://deno.land/x/dso@v1.0.0/mod.ts";

// Define a database model
@Model("users")
class UserModel extends BaseModel {
  // Character set for whole table. UTF-8 is default and is not necessary to define.
  charset: CharsetType.utf8;

  // The ! operator is needed for primary key since it's never null 
  @Field({
    type: FieldType.INT,
    primary: true,
    length: 11,
    autoIncrement: true
  })
  id: number;

  @Field({ type: FieldType.STRING, length: 30 })
  name: string;

  @Field({ type: FieldType.STRING, length: 30 })
  password: string;

  // Charset can be explicitly defined for each column.
  @Field({ type: FieldType.STRING, length: 60, charset: CharsetType.utf8mb4 })
  namespace: string;

  // Index can be created [index/unique/spatial/fulltext] for each field
  @Field({ type: FieldType.STRING, length: 30, unique: true })
  email: string;

  // Multi column index can be defined by decorated @Index
  @Index({ type: IndexType.UNIQUE, columns: ["username","namespace"] })
  public myUniqueIndex!: Index;
}

const userModel = dso.define(UserModel);

async function main() {
  // The database must be created before linking
  await dso.connect({
    hostname: "127.0.0.1",
    port: 3306,
    username: "root",
    password: "",
    db: "dbname"
  });

  /*  
    When installing or initializing a database,
    you can use dso.sync to synchronize the database model to the database.
    Use false as the parameter if you want to sync only newly added models,
    Use true as the parameter if you want to sync the whole defined models
    to the database tables.
    
    == WARNING! ==
    Using true as the parameter will reset your whole database! Use with caution.
  */
  await dso.sync(false);

  // You can add records using insert method
  const insertId = await userModel.insert({
    name: "user1",
    password: "password"
  });

  // You can use the Model.findById method to get a record
  const user = await userModel.findById(1);

  // You can use Where clause too to get a record. For more information on
  // clauses such as join, order, etc. please consult:
  // https://github.com/manyuanrong/sql-builder

  // findOne + Where
  const userWhere = await userModel.findOne(Where.from({ name: "user1" }));
  
  // findAll + Where
  const userAll = await userModel.findAll(Where.from({ name: "user1" }));
  
  // findAll + expr like
  const userLike = await userModel.findAll(Where.expr("name like 'user%'"));

  console.log("Found user by id:", user);
  console.log("Found user by where eq clause:", userWhere);
  console.log("All users by where eq clause:", userAll);
  console.log("All users by where like clause:", userLike);
  console.log("User has these columns in index:", user.myUniqueIndex.columns);
}
main();

Running

Since this library needs to use Typescript Decorators and other features, a custom tsconfig.json needs to be added. Example config file can be found here, or just copy the contents below and create a new tsconfig.json file in your root directory.

tsconfig.json

{
  "compilerOptions": {
    "allowJs": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "esnext",
    "isolatedModules": false
  }
}

To run, use:

deno run --allow-net -c tsconfig.json main.ts

where main.ts is your Typescript file for Deno.

Top Level API

dso.showQueryLog

Set whether query debugging information is displayed

dso.showQueryLog = true;

dso.connect

You need to use this method to link to the database before you can manipulate the database

await dso.connect({
  hostname: "127.0.0.1", // database hostname
  port: 3306, // database port
  username: "root", // database username
  password: "", // database password
  db: "dbname" // database name. (tips: The database must be created before linking)
});

dso.define()

Add an annotated Model instance and return the instance.

@Model("users")
class UserModel extends BaseModel {
  @Field({
    type: FieldType.INT,
    primary: true,
    length: 11,
    autoIncrement: true
  })
  id!: number;

  @Field({ type: FieldType.STRING, length: 30 })
  name?: string;

  @Field({ type: FieldType.STRING, length: 30 })
  password: string;
  
  @Field({ 
    type: FieldType.STRING, 
    unique: true, 
    length: 20})
  phoneNumber?: string;
}
}

export default const userModel = dso.define(UserModel);

// userModel.findById(...)
// userModel.findAll(...)
// userModel.findOne(...)
// userModel.insert(...)
// userModel.update(...)
// userModel.delete(...)

dso.sync

When installing or initializing a database, you can use sync to synchronize the database model to the database.

// If set to FORCE, tables will be deleted before they are created,
// otherwise only new models will be synchronized.
const force = true; // force
await dso.sync(force);

dso.transaction<T>(processor: (transaction: Transaction) => Promise<T>): Promise<T>

Create and start a transaction.

New Model instances must be obtained through getModel(Model). Otherwise, it will not be controlled by transactions.

const result = await dso.transaction<boolean>(async trans => {
  const userModel = trans.getModel(UserModel);
  const topicModel = trans.getModel(TopicModel);

  userId = await userModel.insert({ nickName: "foo", password: "bar", phoneNumber: "08135539123" });
  topicId = await topicModel.insert({ title: "zoo", userId });
  return true;
});

Top Level Types

FieldType

Field

Field type describes the following properties of a field

keytypedefault valuedesc
typeone of the FieldTypesnulltypes of database fields
lengthnumberunfixedfield length
primarybooleanfalsedatabase primary key?
defaultanynulldefault values for fields
autoIncrementbooleanfalseidentify auto-increment fields. It can only be used for INT types
notNullbooleanfalseidentity fields can not be null
autoUpdatebooleanfalseupdated automatically according to the current timestamp. It can only be used for DATE types
uniquebooleanfalsedatabase unique index?
spatialbooleanfalsedatabase spatial index?
fullTextbooleanfalsedatabase fullText index?
indexbooleanfalsedatabase non unique index?

Index

Following types of an index are available

keymulti column
indextrue
uniquetrue
spatialfalse
fulltexttrue

Character sets

list of valid character sets is based on https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html