Socket
Socket
Sign inDemoInstall

zenorm

Package Overview
Dependencies
8
Maintainers
1
Versions
89
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    zenorm

Easy ORM, easy query. easy typing! Auto generate typescript declaration.


Version published
Weekly downloads
47
decreased by-9.62%
Maintainers
1
Created
Weekly downloads
 

Readme

Source

ZenORM

Node.js 数据库 ORM 框架

ZenWeb 衍生的核心项目,此项目可以独立使用

本框架不主动创建数据库结构,而是根据已有数据库结构来生成操作代码,这么做的原因:

  • 在数据库设计层面直接定义表结构比框架生成的通用结构更细致
  • 对于已有项目想要使用 ORM 支持更加友好

本框架并不是真正的 ORM 系统,而是类 ORM 的数据库操作层,几乎任何复杂查询都可实现(试试强大的 AB 工具类)

本框架诞生之因就是为了解决 SAAS 系统的单实例多租户问题,所以所有设计上都是从如何在一个系统中使用多个数据库服务器以及多个数据库而导向, 当然也支持传统的单体应用方式(配置 @zenorm/generatebindQuery 即可)。 以下样例代码即是单体应用的使用方式

安装

# 生产依赖
npm install zenorm mysql-easy-query

# 开发依赖
npm install @zenorm/generate @zenorm/generate-mysql --save-dev

配置

package.jsonscripts 中增加如下代码,用于执行 dbgen 命令

{
  "scripts": {
    "dbgen": "zenorm-generate .dbgen.js"
  }
}

创建文件 .dbgen.js 用于生成数据库结构代码时连接到指定数据库

提示:运行时并不使用此配置

/** @type {import("@zenorm/generate").GenerateConfig} */
module.exports = {
  host: "localhost",
  port: 3306,
  user: "root",
  password: "",
  bindQuery: "pool@../db",
  database: "test"
};

演示

以下数据库结构为演示用,在数据中创建表结构

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `profile` (
  `id` int(11) NOT NULL,
  `edu` varchar(255) DEFAULT NULL,
  `work` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `message` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `content` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

运行命令开始生成数据库结构代码

npm run dbgen

编辑模型关系

编辑生成的模型文件 src/model/user.ts

import { model, join, many, propset } from 'zenorm';
import { UserTable } from './_tables';
import { Profile } from './profile';
import { Message } from './message';

@model({
  pk: 'id',
  table: 'user',
})
export default class User extends UserTable {
  // 添加以下代码
  // join 描述支持使用文件名,解决互相依赖问题
  @join(__dirname + '/profile', { type: 'OneToMany', asList: false })
  profile?: Profile;

  @join(Message)
  messages?: Message[];

  @many(Message)
  messageList?: Message[];

  @propset(function (v) {
    if (v === undefined) throw new Error('age is undefined');
    if (v === 99) return false;
    const date = new Date();
    date.setFullYear(date.getFullYear() - v, 1, 1);
    this.birthday = date;
    return true;
  })
  age = this.birthday ? ((new Date().getFullYear()) - this.birthday.getFullYear()) : undefined;
  // 结束
}

编辑生成的模型文件 src/model/profile.ts

import { model, join } from 'zenorm';
import { ProfileTable } from './_tables';
import User from './user';

@model({
  pk: 'id',
  table: 'profile',
})
export default class Profile extends ProfileTable {
  // 添加以下代码
  @join(User)
  user?: User;
  // 结束
}

初始化数据库访问层

创建代码 src/db.ts

import { createPoolCompatible } from 'mysql-easy-query';
import { Repositories } from './model';

// 创建数据库连接池
export const pool = createPoolCompatible({
  pools: {
    // 主库
    MASTER: {
      host: '10.0.0.1',
      user: 'root',
      database: 'test',
      password: '',
    },
    // 如果需要读写分离,创建命令规则为 SLAVE* 的只读配置
    /*
    SLAVE1: {
      host: '10.0.0.2'
    },
    */
  }
});

开始使用

常规使用
import { User, Message } from './model';

async function test() {
  // create
  const id = await User.create({ name: 'yf' });
  console.log(id); // 1

  // get and update
  const user = await User.findByPk(id);
  user.name = 'yefei';
  user.age = 20;
  await User.save(user);

  // find all
  const users = await User.find().all();

  // find limit
  const users = await User.find().limit(10).all();

  // find by where
  const users = await User.find({ name: { $like: `%y%` } }).all();

  // get all count
  const count = await User.find().count();

  // page
  const page = await User.find().page();

  // exists
  const exists = await User.find({ name: 'yf' }).exists();

  // update
  const updatedCount = await User.find({ id: 1 }).update({ name: 'yf', age: 11 });

  // delete
  const user = await User.findByPk(1);
  const deletedCount = await user.delete();

  // sql delete
  await User.find({ name: 'aaa' }).delete();

  // join 预定义
  const user = await User.find().join("messages").get();

  // join 模型(未定义的)
  const user = await Message.find().join(User).all();

  // many 独立查询功能
  const userList = await User.find().many("messageList").all();

  // 指定使用主从库
  await User.find().of('MASTER').all();
  await User.find().of('SLAVE*').all();
}
事物支持
import { pool } from './db';
import { User, Message } from './model';

async function test() {
  await pool.transaction(async tx => {
    await User.query(tx).find().update({ some: 'data' });
    await Message.query(tx).find().update({ some: 'data' });
  });
}

mysql-easy-query sql-easy-builder

Keywords

FAQs

Last updated on 01 Apr 2024

Did you know?

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc