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

zenorm

v4.1.0

Published

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

Downloads

1,784

Readme

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} */
export default {
  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' });
  });
}

Related projects

mysql-easy-query sql-easy-builder