GithubHelp home page GithubHelp logo

dso's Introduction

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/[email protected]/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(processor: (transaction: Transaction) => Promise): Promise

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

  • DATE
  • INT
  • TEXT
  • STRING
  • BOOLEAN

Field

Field type describes the following properties of a field

key type default value desc
type one of the FieldTypes null types of database fields
length number unfixed field length
primary boolean false database primary key?
default any null default values for fields
autoIncrement boolean false identify auto-increment fields. It can only be used for INT types
notNull boolean false identity fields can not be null
autoUpdate boolean false updated automatically according to the current timestamp. It can only be used for DATE types
unique boolean false database unique index?
spatial boolean false database spatial index?
fullText boolean false database fullText index?
index boolean false database non unique index?

Index

Following types of an index are available

key multi column
index true
unique true
spatial false
fulltext true

Character sets

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

dso's People

Contributors

afinch7 avatar cadente-nd avatar delwiv avatar edlnr avatar jax-p avatar magichim avatar manyuanrong avatar tksilicon avatar vmasdani avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

dso's Issues

deno 1.5.1 isolatedModules breaking change

Hi, Deno 1.5.1 has a breaking change which outputs error in compilation if isolatedModules: false is not provided in tsconfig.json while compiling the example in readme

error: TS1205 [ERROR]: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'.
  Deferred,
  ~~~~~~~~
    at https://deno.land/x/[email protected]/deps.ts:3:3

TS1205 [ERROR]: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'.
export { Client, ClientConfig } from "./src/client.ts";
                 ~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/mod.ts:1:18

TS1205 [ERROR]: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'.
  ClientConfig,
  ~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/deps.ts:8:3

TS1205 [ERROR]: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'.
  ClientConfig,
  ~~~~~~~~~~~~
    at https://deno.land/x/[email protected]/mod.ts:3:3

TS1205 [ERROR]: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'.
export { LogLevels, LevelName } from "./levels.ts";
                    ~~~~~~~~~
    at https://deno.land/[email protected]/log/mod.ts:13:21

Found 5 errors.

I'll send a PR of the new tsconfig.json in readme and in the root dir if needed

model optional chaining operator, tsconfig, & where clause in documentation

Hi. There are a few things I want to address here about the documentation in README, maybe I can help with adding to the documentation.

  • Adding optional chaining operator to model fields
  • Defining tsconfig for decorators
  • Where clause

Adding optional chaining operator to model fields
I get an error when I follow the README by defining models like this:

@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;
}

I have to define the optional chaining operator (? and !) in order to make it work

@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;
}

Defining tsconfig for decorators
In older issue I found that a tsconfig.json must be added

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

and deno must be run in such a way in order for it to work: #6

deno run -A -c tsconfig.json main.ts

But it's not included in the documentation.

Where clause documentation
I couldn't find example using the Where clause in dso API functions for instance findAll and findOne, maybe if you give me an example code I can help write in the documentation.

In summary

I can help adding to the documentation by making PR regarding adding optional chaining operator to models and also regarding tsconfig, but I need examples regarding Where clause since I can't figure it out and I can't find any example codes in tests etc.

doesn't work at all on deno 0.30.0

I have been totally unable to use this module. With even just the import it crashes.

// test.ts

import {
  BaseModel,
  Defaults,
  dso,
  Field,
  FieldType,
  Join,
  Model,
  Where
} from "https://deno.land/x/[email protected]/mod.ts";
deno run --allow-all ./test.ts
error TS2769: No overload matches this call.
  Overload 1 of 3, '(callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string', gave the following error.
    Argument of type '(acc: Options, k: "printFunctionName" | "escapeRegex" | "escapeString" | "min" | "callToJSON" | "indent" | "maxDepth") => { callToJSON: boolean; escapeRegex: boolean; escapeString: boolean; indent: number; maxDepth: number; min: boolean; printFunctionName: boolean; }' is not assignable to parameter of type '(previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string'.
      Types of parameters 'acc' and 'previousValue' are incompatible.
        Type 'string' is not assignable to type 'Options'.
  Overload 2 of 3, '(callbackfn: (previousValue: { callToJSON: boolean; escapeRegex: boolean; escapeString: boolean; indent: number; maxDepth: number; min: boolean; printFunctionName: boolean; }, currentValue: string, currentIndex: number, array: string[]) => { ...; }, initialValue: { ...; }): { ...; }', gave the following error.
    Argument of type '{}' is not assignable to parameter of type '{ callToJSON: boolean; escapeRegex: boolean; escapeString: boolean; indent: number; maxDepth: number; min: boolean; printFunctionName: boolean; }'.
      Type '{}' is missing the following properties from type '{ callToJSON: boolean; escapeRegex: boolean; escapeString: boolean; indent: number; maxDepth: number; min: boolean; printFunctionName: boolean; }': callToJSON, escapeRegex, escapeString, indent, and 3 more.

► https://deno.land/std/testing/format.ts:526:16

526   const opts = Object.keys(DEFAULT_OPTIONS).reduce(

My deno --version shows

deno 0.30.0
v8 8.1.108
typescript 3.7.2

Possibility to create an index other than Primary

I would like to be able to create indexes like "UNIQUE, FULLTEXT, INDEX, SPATIAL" not only "PRIMARY".

As long as I think it's not possible at this moment - is there possibility to create custom query from string? Didn't find it neither.

Make the create_at and update_at fields optional

Is there a possibility to create table without created_at and updated_at?
I don't want it in every table and also I would like to rename it and move at the end of the table. Currently these are the first columns in created table.

I extend BaseModel

@Model("users")
class UserModel extends BaseModel {
    //....
}

Import 'https://deno.land/[email protected]/testing/asserts.ts' failed: 404 Not Found

When i try to run

deno run -c tsconfig.json --allow-net --allow-env ./app.ts;

Show Error:

error: Import 'https://deno.land/[email protected]/testing/asserts.ts' failed: 404 Not Found at https://deno.land/x/[email protected]/deps.ts:1:0

My tsconfig.json

{
  "compilerOptions": {
    "strictNullChecks": true,
    "strictPropertyInitialization": false,
    "strictBindCallApply": true,
    "strictFunctionTypes": true,
    "strict": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "isolatedModules": false,
    "allowSyntheticDefaultImports": true
  }
}

I can't seem to find Association for Models

One-to-one – Each row in one table is linked (or related) to a single row in another table using a “key” column.
One-to-many – Each row in one table is linked (or related) to one, or more, rows in another table using a “key”
column.
Many-to-many – One, or more, rows in one table is linked (or related) to one, or more, rows in another table using a
“key” column.

Future Plans

What are your future plans with this project? Do you plan on continuing to maintain this in the future?

Examples from the readme file do not work.

The Example of the readme use CharsetType & Index which are not part of @v.1.0.0 ("https://deno.land/x/[email protected]/mod.ts").
It should be

import {
  BaseModel,
  Defaults,
  dso,
  Field,
  FieldType,
  CharsetType,
  Index,
  IndexType,
  Join,
  Model,
  Where
} from "https://raw.githubusercontent.com/manyuanrong/dso/master/mod.ts";

instead of

import {
  BaseModel,
  Defaults,
  dso,
  Field,
  FieldType,
  CharsetType,
  Index,
  IndexType,
  Join,
  Model,
  Where
} from "https://deno.land/x/[email protected]/mod.ts";

Multiple database driver adaptations to do list

In order to achieve multiple database driven adaptation, we need to implement the following

  • src/drivers/base.ts Unified interface definition
  • src/drivers/mysql.ts MySQL adapter based on base.ts
  • src/drivers/postgres.ts Postgres adapter based on base.ts
  • src/dso.ts Do not import any driver, dynamically import the driver through the parameter of connect
  • mysql.ts At the same level as mod.ts, the export directly imports dso of MySQL driver
  • postgres.ts At the same level as mod.ts, the export directly imports dso of Postgress driver

When create table, how about changing sequence base modelfield(created, updated)?

When I create table, I often place time column(like create_at, deleted_at..etc)at the end of table

example)
--------------------------------------------------
id | name | updated_at | created_at | deleted_at ....
--------------------------------------------------

current default)
--------------------------------------------------
| updated_at | created_at | id | name|deleted_at ....
--------------------------------------------------

How about changing column sequence as example style?

Github Actions/Docker for Postgres and Sqlite

Github actions is needed for Postgres and Sqlite. Please @afinch7 could you help out. Because of Sqlite, run test becomes:

deno test --allow-net --allow-read --allow-write -c tsconfig.json

Test passes for MySQL but the added drivers are failing. @manyuanrong.

See Pull Request Test.

This is Postgres configuration.

const config2 = { user: "thankgodukachukwu", database: "test_orm", hostname: "127.0.0.1", password: "", port: 5432, };

Could you explain more about example?

Whenever I follow readme example and execute test.ts code, I got much message like this

error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning.

In dso repo, already exsist tsconfig.json and key, value(experimentalDecorators: true).
however, It's not easy to test. still keep this message on terminal.

What should I do to solve this problem?

NOT NULL not working

Hi

First, thanks for you work it's a very useful and well builded tool.

When i use a model with for example

@Model("user")
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 })
  familyName!: string;

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

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

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

  @Field({ type: FieldType.BOOLEAN })
  isValid!: boolean;
}

And i insert the object

payload = {
      name: 'toto'
}

connectDb();
const id = await model.insert(payload);

Error isn't throwed instead fields like secret, token are required with the !

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.