@elysiumjs/mnemosyne-drizzle

中文文档
0.9.1发布于 2026/11/12Apache-2.0TypeScriptES Module近 30 天下载 3980

Drizzle ORM driver for @elysiumjs/mnemosyne

此软件包已被标记为弃用

Replaced by @elysiumjs/drizzle.

原始使用文档
文档目录5 节
  1. Installation
  2. Usage
  3. Migration hooks
  4. Table markers
  5. License

@elysiumjs/mnemosyne-drizzle

Drizzle ORM driver for @elysiumjs/mnemosyne.

Installation

bun add @elysiumjs/mnemosyne-drizzle

Usage

Add DrizzleModule to your application. It declares the connections as global services, registers the tenancy strategy and provides the migration:generate and migration:run commands.

import { Application } from '@elysiumjs/core';
import { DrizzleModule } from '@elysiumjs/mnemosyne-drizzle';

@Application.register({
    modules: [
        DrizzleModule.with({
            default: 'main',
            connections: {
                main: { connection: process.env.DATABASE_URL! }
            }
        })
    ]
})
export class App extends Application {}

with() also accepts a function, which is called when the module is booted: DrizzleModule.with(() => ({ ... })). Set tenancy to switch between schema (default) and RLS tenancy.

Define models with the enhanced pgTable:

import { DrizzleModel, DrizzleRepository, pgTable } from '@elysiumjs/mnemosyne-drizzle';
import { uuid, varchar } from 'drizzle-orm/pg-core';

const users = pgTable('users', {
    id: uuid().primaryKey().defaultRandom(),
    name: varchar({ length: 255 }).notNull()
});

export class UserModel extends DrizzleModel(users, { supportTenancy: true }) {}
export class UserRepository extends DrizzleRepository(UserModel) {}

The repository finds rows by the table's primary key. A table without an id column, or with a composite primary key, takes the key as an object; key names other columns to use instead:

export class MembershipRepository extends DrizzleRepository(MembershipModel) {}
await memberships.find({ teamId, userId });

export class SessionRepository extends DrizzleRepository(SessionModel, { key: ['token'] }) {}
await sessions.find('abc123');

list(query, scope) and count(query, scope) take a condition the rows must also meet, on top of the filters of the query:

public listFor(userId: string, query: ParsedQuery<'cursor'>) {
    return this.list(query, eq(posts.authorId, userId));
}

Migration hooks

migration:run --tenant <name> applies the pending migrations of a tenant in one transaction, under a lock per tenant. It works on the connection given by --connection (default when omitted), whose driver runs the migrations: bun-sql, postgres-js and node-postgres do, and hyperdrive hands them to the driver it wraps, which needs its binding. A custom driver runs them by implementing migrations(connection), with templateClientMigrations() or nodePostgresMigrations() for clients like those.

A migration hook runs SQL around the migrations, in the same transaction: when a hook fails, the whole run is rolled back. Register it with @Migration.hook() and list it in the services of a module. Every method is optional:

import type { MigrationHook, MigrationRun, MigrationStep } from '@elysiumjs/mnemosyne-drizzle';

import { Migration, sql } from '@elysiumjs/mnemosyne-drizzle';

@Migration.hook()
export class DatabaseHook implements MigrationHook {
    public async before({ db }: MigrationRun) {
        await db.execute(sql`CREATE EXTENSION IF NOT EXISTS pgcrypto`);
    }

    public async beforeEach({ name }: MigrationStep) {}

    public async afterEach({ db, name }: MigrationStep) {
        const [{ count }] = await db.execute<{ count: number }>(
            sql`SELECT count(*)::int AS count FROM pg_constraint WHERE ...`
        );
        if (count > 0) throw new Error(`${name} adds a foreign key across schemas`);
    }

    public async after({ db, tenant }: MigrationRun) {
        await db.execute(sql`GRANT USAGE ON SCHEMA ${sql.identifier(tenant)} TO app`);
    }
}
  • before runs once the tenant schema and the migrations table exist, and after at the end. Both also run when no migration is pending, so after fits what must stay in place, such as grants or partitions.
  • beforeEach runs before each migration, and afterEach once it is recorded.
  • A MigrationRun holds the transaction (db), the tenant, the connection, the batch, the pending migrations and the ones applied so far. A MigrationStep holds the transaction, the name and path of the migration, and its run.
  • db.execute(query) runs one statement written with the sql template of Drizzle and returns its rows. db.script(text) runs several statements without parameters.

Hooks run for every tenant, in the order the modules register them: read tenant to act on some tenants only.

Table markers

DrizzleTable.define() marks a table with what migration:generate adds to the migration that creates it. Later migrations are left as they are.

import { DrizzleTable } from '@elysiumjs/mnemosyne-drizzle';
import { pgSchema, primaryKey, text, timestamp, uuid } from 'drizzle-orm/pg-core';

const kernel = pgSchema('kernel');

export const audit = DrizzleTable.define(
    DrizzleTable.partitioned({ range: 'recorded_at' }),
    DrizzleTable.afterCreate(
        ({ qualified }) =>
            `CREATE TRIGGER audit_append_only BEFORE UPDATE OR DELETE ON ${qualified} FOR EACH ROW EXECUTE FUNCTION forbid_change()`
    )
)(
    kernel.table(
        'audit',
        {
            id: uuid('id').notNull().defaultRandom(),
            action: text('action').notNull(),
            recordedAt: timestamp('recorded_at').notNull().defaultNow()
        },
        (t) => [primaryKey({ columns: [t.id, t.recordedAt] })]
    )
);
  • DrizzleTable.partitioned({ range }) adds PARTITION BY RANGE (...) to the CREATE TABLE. range is a column name in the database, a function returning the column ((t) => t.recordedAt), or several of them. The primary key and unique constraints must include those columns.
  • DrizzleTable.afterCreate(build) adds SQL right after the table is created, as its own statement. build receives the schema (undefined for public), the name and the quoted, schema-qualified qualified name, and returns a string or a sql template.
  • DrizzleTable.define() returns the table it marks, so its type is unchanged. Marking a table again adds to its markers.

License

This project is licensed under the Apache License, Version 2.0. See the LICENSE file for more info.

版本与发布记录

@elysiumjs/mnemosyne-drizzle 共发布 26 个版本,首次发布于 2026/02/24;过去 12 个月发布了 26 个版本。

版本发布日期距今
0.9.1latest2026/11/121 天前
0.9.02026/11/121 天前
0.8.02026/11/121 天前
0.7.12026/11/121 天前
0.7.02026/11/112 天前
0.6.32026/11/112 天前

关于 @elysiumjs/mnemosyne-drizzle 的常见问题

@elysiumjs/mnemosyne-drizzle 是什么?

Drizzle ORM driver for @elysiumjs/mnemosyne注意:该包已被作者标记为弃用——Replaced by @elysiumjs/drizzle.

如何安装 @elysiumjs/mnemosyne-drizzle?

在项目目录运行 npm install @elysiumjs/mnemosyne-drizzle,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@elysiumjs/core(^0.24.1)、@elysiumjs/mnemosyne(^0.8.1)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@elysiumjs/mnemosyne-drizzle 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@elysiumjs/mnemosyne-drizzle 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@elysiumjs/mnemosyne-drizzle 可以商用吗?

@elysiumjs/mnemosyne-drizzle 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@elysiumjs/mnemosyne-drizzle 的下载量有多少?

根据 npm 官方下载统计,@elysiumjs/mnemosyne-drizzle 在 2026/10/14 – 2026/11/12 这 30 天内被下载 3,980 次,日均约 133 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@elysiumjs/mnemosyne-drizzle 还在维护吗?

最新版本 0.9.1 发布于 2026/11/12(1 天前);至今共发布 26 个版本,其中过去 12 个月发布了 26 个;首次发布于 2026/02/24。作者已将其标记为弃用,新项目建议寻找替代方案。