├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .verdaccio
└── config.yml
├── .vscode
└── extensions.json
├── LICENSE
├── README.md
├── apps
├── demo-e2e
│ ├── .eslintrc.json
│ ├── jest.config.ts
│ ├── project.json
│ ├── src
│ │ ├── demo
│ │ │ └── demo.spec.ts
│ │ └── support
│ │ │ ├── global-setup.ts
│ │ │ ├── global-teardown.ts
│ │ │ └── test-setup.ts
│ ├── tsconfig.json
│ └── tsconfig.spec.json
└── demo
│ ├── .eslintrc.json
│ ├── jest.config.ts
│ ├── project.json
│ ├── src
│ ├── app
│ │ ├── app.controller.spec.ts
│ │ ├── app.controller.ts
│ │ ├── app.module.ts
│ │ ├── app.service.spec.ts
│ │ └── app.service.ts
│ ├── assets
│ │ └── .gitkeep
│ ├── db
│ │ └── schema.ts
│ └── main.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.spec.json
│ └── webpack.config.js
├── demo.db
├── jest.config.ts
├── jest.preset.js
├── migrations.json
├── nx.json
├── package-lock.json
├── package.json
├── packages
├── better-sqlite3
│ ├── .eslintrc.json
│ ├── README.md
│ ├── jest.config.ts
│ ├── package-lock.json
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── index.ts
│ │ ├── sqlite.decorator.ts
│ │ ├── sqlite.definition.ts
│ │ ├── sqlite.interface.ts
│ │ ├── sqlite.module.ts
│ │ ├── sqlite.service.spec.ts
│ │ └── sqlite.service.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
├── mysql2
│ ├── .eslintrc.json
│ ├── README.md
│ ├── jest.config.ts
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── index.ts
│ │ ├── mysql.decorator.ts
│ │ ├── mysql.definition.ts
│ │ ├── mysql.interface.ts
│ │ ├── mysql.module.ts
│ │ ├── mysql.service.spec.ts
│ │ └── mysql.service.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
├── node-postgres
│ ├── .eslintrc.json
│ ├── README.md
│ ├── jest.config.ts
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── index.ts
│ │ ├── node-postgres.decorator.ts
│ │ ├── node-postgres.definition.ts
│ │ ├── node-postgres.interface.ts
│ │ ├── node-postgres.module.ts
│ │ ├── node-postgres.service.spec.ts
│ │ └── node-postgres.service.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
├── planetscale
│ ├── .eslintrc.json
│ ├── README.md
│ ├── jest.config.ts
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── index.ts
│ │ ├── planetscale.decorator.ts
│ │ ├── planetscale.definition.ts
│ │ ├── planetscale.interface.ts
│ │ ├── planetscale.module.ts
│ │ ├── planetscale.service.spec.ts
│ │ └── planetscale.service.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
├── postgres-js
│ ├── .eslintrc.json
│ ├── README.md
│ ├── jest.config.ts
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── index.ts
│ │ ├── postgres-js.decorator.ts
│ │ ├── postgres-js.definition.ts
│ │ ├── postgres-js.interface.ts
│ │ ├── postgres-js.module.ts
│ │ ├── postgres-js.service.spec.ts
│ │ └── postgres-js.service.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
└── turso
│ ├── .eslintrc.json
│ ├── README.md
│ ├── jest.config.ts
│ ├── package.json
│ ├── project.json
│ ├── src
│ ├── index.ts
│ ├── turso.decorator.ts
│ ├── turso.definition.ts
│ ├── turso.interface.ts
│ ├── turso.module.ts
│ ├── turso.service.spec.ts
│ └── turso.service.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
├── project.json
├── tools
└── scripts
│ └── publish.mjs
└── tsconfig.base.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "ignorePatterns": ["**/*"],
4 | "plugins": ["@nx"],
5 | "overrides": [
6 | {
7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
8 | "rules": {
9 | "@nx/enforce-module-boundaries": [
10 | "error",
11 | {
12 | "enforceBuildableLibDependency": true,
13 | "allow": [],
14 | "depConstraints": [
15 | {
16 | "sourceTag": "*",
17 | "onlyDependOnLibsWithTags": ["*"]
18 | }
19 | ]
20 | }
21 | ]
22 | }
23 | },
24 | {
25 | "files": ["*.ts", "*.tsx"],
26 | "extends": ["plugin:@nx/typescript"],
27 | "rules": {
28 | "@typescript-eslint/no-extra-semi": "error",
29 | "no-extra-semi": "off"
30 | }
31 | },
32 | {
33 | "files": ["*.js", "*.jsx"],
34 | "extends": ["plugin:@nx/javascript"],
35 | "rules": {
36 | "@typescript-eslint/no-extra-semi": "error",
37 | "no-extra-semi": "off"
38 | }
39 | },
40 | {
41 | "files": ["*.spec.ts", "*.spec.tsx", "*.spec.js", "*.spec.jsx"],
42 | "env": {
43 | "jest": true
44 | },
45 | "rules": {}
46 | }
47 | ]
48 | }
49 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | dist
5 | tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | !.vscode/settings.json
23 | !.vscode/tasks.json
24 | !.vscode/launch.json
25 | !.vscode/extensions.json
26 |
27 | # misc
28 | /.sass-cache
29 | /connect.lock
30 | /coverage
31 | /libpeerconnection.log
32 | npm-debug.log
33 | yarn-error.log
34 | testem.log
35 | /typings
36 | .env
37 |
38 | # System Files
39 | .DS_Store
40 | Thumbs.db
41 |
42 | .nx/cache
43 | .nx/workspace-data
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # Add files here to ignore them from prettier formatting
2 | /dist
3 | /coverage
4 | /.nx/cache
5 | /.nx/workspace-data
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/.verdaccio/config.yml:
--------------------------------------------------------------------------------
1 | # path to a directory with all packages
2 | storage: ../tmp/local-registry/storage
3 |
4 | # a list of other known repositories we can talk to
5 | uplinks:
6 | npmjs:
7 | url: https://registry.npmjs.org/
8 | maxage: 60m
9 |
10 | packages:
11 | '**':
12 | # give all users (including non-authenticated users) full access
13 | # because it is a local registry
14 | access: $all
15 | publish: $all
16 | unpublish: $all
17 |
18 | # if package is not available locally, proxy requests to npm registry
19 | proxy: npmjs
20 |
21 | # log settings
22 | logs:
23 | type: stdout
24 | format: pretty
25 | level: warn
26 |
27 | publish:
28 | allow_offline: true # set offline to true to allow publish offline
29 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "nrwl.angular-console",
4 | "esbenp.prettier-vscode",
5 | "firsttris.vscode-jest-runner",
6 | "dbaeumer.vscode-eslint"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Knaadh
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | A NestJS module for integrating Drizzle ORM
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | ## Table of Contents
21 |
22 | - [Table of Contents](#table-of-contents)
23 | - [Installation](#installation)
24 | - [Usage](#usage)
25 | - [Documentation](#documentation)
26 | - [License](#license)
27 |
28 | ## Installation
29 |
30 | There is a separate module for each one of the major database drivers supported by the DrizzleORM. You can install them via your preferred package manager.
31 |
32 | ```bash
33 | # PostgresJS
34 | npm install @knaadh/nestjs-drizzle-postgres drizzle-orm postgres
35 |
36 | # Node-Postgres
37 | npm install @knaadh/nestjs-drizzle-pg drizzle-orm pg
38 |
39 | # MySQL2
40 | npm install @knaadh/nestjs-drizzle-mysql2 drizzle-orm mysql2
41 |
42 | # Better-SQLite3
43 | npm install @knaadh/nestjs-drizzle-better-sqlite3 drizzle-orm better-sqlite3
44 |
45 | # Turso
46 | npm install @knaadh/nestjs-drizzle-turso drizzle-orm @libsql/client
47 |
48 | # PlanetScale
49 | npm install @knaadh/nestjs-drizzle-planetscale drizzle-orm @planetscale/database
50 | ```
51 |
52 | ## Usage
53 |
54 | Import the Drizzle module of the respective database driver and pass an `options` object to initialize it as shown in the example below:
55 |
56 | ```typescript
57 | import { Module } from '@nestjs/common';
58 | import { AppController } from './app.controller';
59 | import { AppService } from './app.service';
60 | import * as schema from '../db/schema';
61 | import { DrizzleBetterSQLiteModule } from '@knaadh/nestjs-drizzle-better-sqlite3';
62 | @Module({
63 | imports: [
64 | DrizzleBetterSQLiteModule.register({
65 | tag: 'DB_DEV',
66 | sqlite3: {
67 | filename: 'demo.db',
68 | },
69 | config: { schema: { ...schema } },
70 | }),
71 | ],
72 | controllers: [AppController],
73 | providers: [AppService],
74 | })
75 | export class AppModule {}
76 | ```
77 |
78 | You can inject the Drizzle instances using their respective `tag` specified in the configuration
79 |
80 | ```typescript
81 | import { Inject, Injectable } from '@nestjs/common';
82 | import * as schema from '../db/schema';
83 | import { LibSQLDatabase } from 'drizzle-orm/libsql';
84 | @Injectable()
85 | export class AppService {
86 | constructor(
87 | @Inject('DB_DEV') private drizzleDev: LibSQLDatabase
88 | ) {}
89 | async getData() {
90 | const books = await this.drizzleDev.query.books.findMany();
91 | const authors = await this.drizzleDev.query.authors.findMany();
92 | return {
93 | books: books,
94 | authors: authors,
95 | };
96 | }
97 | }
98 | ```
99 |
100 | In case you need the access to the underlying connection client for tasks such as connection termination or other operations, you must define the session property manually, as Drizzle does not currently expose it. In the following example, we demonstrate how to access the client to close all database connections when our NestJS application is terminated, using the `onApplicationShutdown` hook.
101 |
102 | Note that the specific client type vary depending on the database driver being used, so adjust the type accordingly.
103 |
104 | ```typescript
105 | import { MySql2Client, MySql2Database } from 'drizzle-orm/mysql2';
106 |
107 | import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
108 |
109 | import * as schema from './schema/mysql';
110 |
111 | export type ExtendedMySql2Database> =
112 | MySql2Database & {
113 | session: {
114 | client: MySql2Client;
115 | };
116 | };
117 |
118 | @Injectable()
119 | export class AppService implements OnApplicationShutdown {
120 | constructor(
121 | @Inject('DB')
122 | private drizzleProd: ExtendedMySql2Database,
123 | ) {}
124 |
125 | async getHello() {
126 | const books = await this.drizzleProd.query.books.findMany();
127 | const authors = await this.drizzleProd.query.authors.findMany();
128 | return {
129 | books: books,
130 | authors: authors,
131 | };
132 | }
133 |
134 | async onApplicationShutdown() {
135 | await this.drizzleProd.session.client.end();
136 | }
137 | }
138 | ```
139 |
140 | You can read the detailed documentation of each of the module from the links given below
141 |
142 | ## Documentation
143 |
144 | - [@knaadh/nestjs-drizzle-postgres](https://github.com/knaadh/nestjs-drizzle/blob/main/packages/postgres-js/README.md)
145 | - [@knaadh/nestjs-drizzle-pg](https://github.com/knaadh/nestjs-drizzle/blob/main/packages/node-postgres/README.md)
146 | - [@knaadh/nestjs-drizzle-mysql2](https://github.com/knaadh/nestjs-drizzle/blob/main/packages/mysql2/README.md)
147 | - [@knaadh/nestjs-drizzle-better-sqlite3](https://github.com/knaadh/nestjs-drizzle/blob/main/packages/better-sqlite3/README.md)
148 | - [@knaadh/nestjs-drizzle-turso](https://github.com/knaadh/nestjs-drizzle/blob/main/packages/turso/README.md)
149 | - [@knaadh/nestjs-drizzle-planetscale](https://github.com/knaadh/nestjs-drizzle/blob/main/packages/planetscale/README.md)
150 |
151 | ## License
152 |
153 | This package is [MIT licensed](LICENSE).
154 |
--------------------------------------------------------------------------------
/apps/demo-e2e/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "../../.eslintrc.json"
4 | ],
5 | "ignorePatterns": [
6 | "!**/*"
7 | ],
8 | "overrides": [
9 | {
10 | "files": [
11 | "*.ts",
12 | "*.tsx",
13 | "*.js",
14 | "*.jsx"
15 | ],
16 | "rules": {}
17 | },
18 | {
19 | "files": [
20 | "*.ts",
21 | "*.tsx"
22 | ],
23 | "rules": {}
24 | },
25 | {
26 | "files": [
27 | "*.js",
28 | "*.jsx"
29 | ],
30 | "rules": {}
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/apps/demo-e2e/jest.config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export default {
3 | displayName: 'demo-e2e',
4 | preset: '../../jest.preset.js',
5 | globalSetup: '/src/support/global-setup.ts',
6 | globalTeardown: '/src/support/global-teardown.ts',
7 | setupFiles: ['/src/support/test-setup.ts'],
8 | testEnvironment: 'node',
9 | transform: {
10 | '^.+\\.[tj]s$': ['ts-jest', {
11 | tsconfig: '/tsconfig.spec.json',
12 | }],
13 | },
14 | moduleFileExtensions: ['ts', 'js', 'html'],
15 | coverageDirectory: '../../coverage/demo-e2e',
16 | };
17 |
--------------------------------------------------------------------------------
/apps/demo-e2e/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo-e2e",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "projectType": "application",
5 | "implicitDependencies": ["demo"],
6 | "targets": {
7 | "e2e": {
8 | "executor": "@nx/jest:jest",
9 | "outputs": ["{workspaceRoot}/coverage/{e2eProjectRoot}"],
10 | "options": {
11 | "jestConfig": "apps/demo-e2e/jest.config.ts"
12 | }
13 | },
14 | "lint": {
15 | "executor": "@nx/eslint:lint"
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/apps/demo-e2e/src/demo/demo.spec.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | describe('GET /api', () => {
4 | it('should return a message', async () => {
5 | const res = await axios.get(`/api`);
6 |
7 | expect(res.status).toBe(200);
8 | expect(res.data).toEqual({ message: 'Hello API' });
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/apps/demo-e2e/src/support/global-setup.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | var __TEARDOWN_MESSAGE__: string;
3 |
4 | module.exports = async function() {
5 | // Start services that that the app needs to run (e.g. database, docker-compose, etc.).
6 | console.log('\nSetting up...\n');
7 |
8 | // Hint: Use `globalThis` to pass variables to global teardown.
9 | globalThis.__TEARDOWN_MESSAGE__ = '\nTearing down...\n';
10 | };
11 |
12 |
--------------------------------------------------------------------------------
/apps/demo-e2e/src/support/global-teardown.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 |
3 | module.exports = async function() {
4 | // Put clean up logic here (e.g. stopping services, docker-compose, etc.).
5 | // Hint: `globalThis` is shared between setup and teardown.
6 | console.log(globalThis.__TEARDOWN_MESSAGE__);
7 | };
8 |
--------------------------------------------------------------------------------
/apps/demo-e2e/src/support/test-setup.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 |
3 | import axios from 'axios';
4 |
5 | module.exports = async function() {
6 | // Configure axios for tests to use.
7 | const host = process.env.HOST ?? 'localhost';
8 | const port = process.env.PORT ?? '3000';
9 | axios.defaults.baseURL = `http://${host}:${port}`;
10 | };
11 |
--------------------------------------------------------------------------------
/apps/demo-e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "files": [],
4 | "include": [],
5 | "references": [
6 | {
7 | "path": "./tsconfig.spec.json"
8 | }
9 | ],
10 | "compilerOptions": {
11 | "esModuleInterop": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/apps/demo-e2e/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.ts"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/apps/demo/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "../../.eslintrc.json"
4 | ],
5 | "ignorePatterns": [
6 | "!**/*"
7 | ],
8 | "overrides": [
9 | {
10 | "files": [
11 | "*.ts",
12 | "*.tsx",
13 | "*.js",
14 | "*.jsx"
15 | ],
16 | "rules": {}
17 | },
18 | {
19 | "files": [
20 | "*.ts",
21 | "*.tsx"
22 | ],
23 | "rules": {}
24 | },
25 | {
26 | "files": [
27 | "*.js",
28 | "*.jsx"
29 | ],
30 | "rules": {}
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/apps/demo/jest.config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export default {
3 | displayName: 'demo',
4 | preset: '../../jest.preset.js',
5 | testEnvironment: 'node',
6 | transform: {
7 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }]
8 | },
9 | moduleFileExtensions: ['ts', 'js', 'html'],
10 | coverageDirectory: '../../coverage/apps/demo'
11 | };
12 |
--------------------------------------------------------------------------------
/apps/demo/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "apps/demo/src",
5 | "projectType": "application",
6 | "tags": [],
7 | "targets": {
8 | "build": {
9 | "executor": "@nx/webpack:webpack",
10 | "outputs": ["{options.outputPath}"],
11 | "defaultConfiguration": "production",
12 | "options": {
13 | "target": "node",
14 | "compiler": "tsc",
15 | "outputPath": "dist/apps/demo",
16 | "main": "apps/demo/src/main.ts",
17 | "tsConfig": "apps/demo/tsconfig.app.json",
18 | "assets": ["apps/demo/src/assets"],
19 | "isolatedConfig": true,
20 | "webpackConfig": "apps/demo/webpack.config.js"
21 | },
22 | "configurations": {
23 | "development": {},
24 | "production": {}
25 | }
26 | },
27 | "serve": {
28 | "executor": "@nx/js:node",
29 | "defaultConfiguration": "development",
30 | "options": {
31 | "buildTarget": "demo:build"
32 | },
33 | "configurations": {
34 | "development": {
35 | "buildTarget": "demo:build:development"
36 | },
37 | "production": {
38 | "buildTarget": "demo:build:production"
39 | }
40 | }
41 | },
42 | "lint": {
43 | "executor": "@nx/eslint:lint"
44 | },
45 | "test": {
46 | "executor": "@nx/jest:jest",
47 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
48 | "options": {
49 | "jestConfig": "apps/demo/jest.config.ts"
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/apps/demo/src/app/app.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 |
3 | import { AppController } from './app.controller';
4 | import { AppService } from './app.service';
5 |
6 | describe('AppController', () => {
7 | let app: TestingModule;
8 |
9 | beforeAll(async () => {
10 | app = await Test.createTestingModule({
11 | controllers: [AppController],
12 | providers: [AppService],
13 | }).compile();
14 | });
15 |
16 | describe('getData', () => {
17 | it('should return "Hello API"', () => {
18 | const appController = app.get(AppController);
19 | expect(appController.getData()).toEqual({message: 'Hello API'});
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/apps/demo/src/app/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 |
3 | import { AppService } from './app.service';
4 |
5 | @Controller()
6 | export class AppController {
7 | constructor(private readonly appService: AppService) {}
8 |
9 | @Get()
10 | getData() {
11 | return this.appService.getData();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/apps/demo/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 | import * as schema from '../db/schema';
5 | import { DrizzleBetterSQLiteModule } from '@knaadh/nestjs-drizzle-better-sqlite3';
6 | @Module({
7 | imports: [
8 | DrizzleBetterSQLiteModule.register({
9 | tag: 'DB_DEV',
10 | sqlite3: {
11 | filename: 'demo.db',
12 | },
13 | config: { schema: { ...schema } },
14 | }),
15 | ],
16 | controllers: [AppController],
17 | providers: [AppService],
18 | })
19 | export class AppModule {}
20 |
--------------------------------------------------------------------------------
/apps/demo/src/app/app.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test } from '@nestjs/testing';
2 |
3 | import { AppService } from './app.service';
4 |
5 | describe('AppService', () => {
6 | let service: AppService;
7 |
8 | beforeAll(async () => {
9 | const app = await Test.createTestingModule({
10 | providers: [AppService],
11 | }).compile();
12 |
13 | service = app.get(AppService);
14 | });
15 |
16 | describe('getData', () => {
17 | it('should return "Hello API"', () => {
18 | expect(service.getData()).toEqual({message: 'Hello API'});
19 | });
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/apps/demo/src/app/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Inject, Injectable } from '@nestjs/common';
2 | import * as schema from '../db/schema';
3 | import { LibSQLDatabase } from 'drizzle-orm/libsql';
4 | @Injectable()
5 | export class AppService {
6 | constructor(
7 | @Inject('DB_DEV') private drizzleDev: LibSQLDatabase
8 | ) {}
9 | async getData() {
10 | const books = await this.drizzleDev.query.books.findMany();
11 | const authors = await this.drizzleDev.query.authors.findMany();
12 | return {
13 | books: books,
14 | authors: authors,
15 | };
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/apps/demo/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/knaadh/nestjs-drizzle/5747f2f0600e40d955634324a41c32ad8616c8c6/apps/demo/src/assets/.gitkeep
--------------------------------------------------------------------------------
/apps/demo/src/db/schema.ts:
--------------------------------------------------------------------------------
1 | import { pgTable, serial, varchar } from 'drizzle-orm/pg-core';
2 |
3 | export const books = pgTable('Books', {
4 | id: serial('id').primaryKey(),
5 | name: varchar('name', { length: 256 }),
6 | });
7 |
8 | export const authors = pgTable('Authors', {
9 | id: serial('id').primaryKey(),
10 | name: varchar('name', { length: 256 }),
11 | });
12 |
--------------------------------------------------------------------------------
/apps/demo/src/main.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This is not a production server yet!
3 | * This is only a minimal backend to get started.
4 | */
5 |
6 | import { Logger } from '@nestjs/common';
7 | import { NestFactory } from '@nestjs/core';
8 |
9 | import { AppModule } from './app/app.module';
10 |
11 | async function bootstrap() {
12 | const app = await NestFactory.create(AppModule);
13 | const globalPrefix = 'api';
14 | app.setGlobalPrefix(globalPrefix);
15 | const port = process.env.PORT || 3000;
16 | await app.listen(port);
17 | Logger.log(`🚀 Application is running on: http://localhost:${port}/${globalPrefix}`);
18 | }
19 |
20 | bootstrap();
21 |
--------------------------------------------------------------------------------
/apps/demo/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": [
7 | "node"
8 | ],
9 | "emitDecoratorMetadata": true,
10 | "target": "es2021"
11 | },
12 | "exclude": [
13 | "jest.config.ts",
14 | "src/**/*.spec.ts",
15 | "src/**/*.test.ts"
16 | ],
17 | "include": [
18 | "src/**/*.ts"
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/apps/demo/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "files": [],
4 | "include": [],
5 | "references": [
6 | {
7 | "path": "./tsconfig.app.json"
8 | },
9 | {
10 | "path": "./tsconfig.spec.json"
11 | }
12 | ],
13 | "compilerOptions": {
14 | "esModuleInterop": true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/apps/demo/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/apps/demo/webpack.config.js:
--------------------------------------------------------------------------------
1 | const { composePlugins, withNx} = require('@nx/webpack');
2 |
3 | // Nx plugins for webpack.
4 | module.exports = composePlugins(withNx(), (config) => {
5 | // Update the webpack config as needed here.
6 | // e.g. `config.plugins.push(new MyPlugin())`
7 | return config;
8 | });
9 |
--------------------------------------------------------------------------------
/demo.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/knaadh/nestjs-drizzle/5747f2f0600e40d955634324a41c32ad8616c8c6/demo.db
--------------------------------------------------------------------------------
/jest.config.ts:
--------------------------------------------------------------------------------
1 | import { getJestProjectsAsync } from '@nx/jest';
2 |
3 | export default async () => ({
4 | projects: await getJestProjectsAsync()
5 | });
--------------------------------------------------------------------------------
/jest.preset.js:
--------------------------------------------------------------------------------
1 |
2 | const nxPreset = require('@nx/jest/preset').default;
3 |
4 | module.exports = { ...nxPreset }
--------------------------------------------------------------------------------
/migrations.json:
--------------------------------------------------------------------------------
1 | {
2 | "migrations": [
3 | {
4 | "version": "20.0.0-beta.7",
5 | "description": "Migration for v20.0.0-beta.7",
6 | "implementation": "./src/migrations/update-20-0-0/move-use-daemon-process",
7 | "package": "nx",
8 | "name": "move-use-daemon-process"
9 | },
10 | {
11 | "version": "20.0.1",
12 | "description": "Set `useLegacyCache` to true for migrating workspaces",
13 | "implementation": "./src/migrations/update-20-0-1/use-legacy-cache",
14 | "x-repair-skip": true,
15 | "package": "nx",
16 | "name": "use-legacy-cache"
17 | },
18 | {
19 | "cli": "nx",
20 | "version": "20.0.0-beta.5",
21 | "description": "replace getJestProjects with getJestProjectsAsync",
22 | "implementation": "./src/migrations/update-20-0-0/replace-getJestProjects-with-getJestProjectsAsync",
23 | "package": "@nx/jest",
24 | "name": "replace-getJestProjects-with-getJestProjectsAsync"
25 | },
26 | {
27 | "cli": "nx",
28 | "version": "19.6.3-beta.0",
29 | "description": "Migrate proxy config files to match new format from webpack-dev-server v5.",
30 | "implementation": "./src/migrations/update-19-6-3/proxy-config",
31 | "package": "@nx/webpack",
32 | "name": "update-19-6-3-proxy-config"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/nx.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/nx/schemas/nx-schema.json",
3 | "targetDefaults": {
4 | "build": {
5 | "cache": true,
6 | "dependsOn": ["^build"],
7 | "inputs": ["production", "^production"]
8 | },
9 | "@nx/jest:jest": {
10 | "cache": true,
11 | "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"],
12 | "options": {
13 | "passWithNoTests": true
14 | },
15 | "configurations": {
16 | "ci": {
17 | "ci": true,
18 | "codeCoverage": true
19 | }
20 | }
21 | },
22 | "@nx/eslint:lint": {
23 | "cache": true,
24 | "inputs": [
25 | "default",
26 | "{workspaceRoot}/.eslintrc.json",
27 | "{workspaceRoot}/.eslintignore",
28 | "{workspaceRoot}/eslint.config.js"
29 | ]
30 | }
31 | },
32 | "namedInputs": {
33 | "default": ["{projectRoot}/**/*", "sharedGlobals"],
34 | "production": [
35 | "default",
36 | "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
37 | "!{projectRoot}/tsconfig.spec.json",
38 | "!{projectRoot}/jest.config.[jt]s",
39 | "!{projectRoot}/src/test-setup.[jt]s",
40 | "!{projectRoot}/test-setup.[jt]s",
41 | "!{projectRoot}/.eslintrc.json",
42 | "!{projectRoot}/eslint.config.js"
43 | ],
44 | "sharedGlobals": []
45 | },
46 | "useInferencePlugins": false,
47 | "useLegacyCache": true
48 | }
49 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nestjs-drizzle/source",
3 | "version": "0.0.0",
4 | "license": "MIT",
5 | "scripts": {},
6 | "private": true,
7 | "dependencies": {
8 | "@libsql/client": "^0.3.6",
9 | "@nestjs/common": "^10.0.2",
10 | "@nestjs/core": "^10.0.2",
11 | "@nestjs/platform-express": "^10.0.2",
12 | "@planetscale/database": "^1.11.0",
13 | "axios": "1.7.4",
14 | "better-sqlite3": "^9.0.0",
15 | "drizzle-orm": "^0.28.6",
16 | "mysql2": "^3.6.2",
17 | "pg": "^8.11.3",
18 | "postgres": "3.4.0",
19 | "reflect-metadata": "^0.1.13",
20 | "rxjs": "^7.8.0"
21 | },
22 | "devDependencies": {
23 | "@nestjs/schematics": "^10.0.1",
24 | "@nestjs/testing": "^10.0.2",
25 | "@nx/eslint": "20.0.8",
26 | "@nx/eslint-plugin": "20.0.8",
27 | "@nx/jest": "20.0.8",
28 | "@nx/js": "20.0.8",
29 | "@nx/nest": "20.0.8",
30 | "@nx/node": "20.0.8",
31 | "@nx/webpack": "20.0.8",
32 | "@nx/workspace": "20.0.8",
33 | "@swc-node/register": "1.9.2",
34 | "@swc/core": "1.5.7",
35 | "@types/better-sqlite3": "^7.6.8",
36 | "@types/jest": "29.5.12",
37 | "@types/node": "^18.16.9",
38 | "@types/pg": "^8.10.7",
39 | "@typescript-eslint/eslint-plugin": "7.16.0",
40 | "@typescript-eslint/parser": "7.16.0",
41 | "eslint": "8.57.0",
42 | "eslint-config-prettier": "^9.0.0",
43 | "jest": "29.7.0",
44 | "jest-environment-node": "^29.4.1",
45 | "nx": "20.0.8",
46 | "prettier": "^2.6.2",
47 | "ts-jest": "^29.1.0",
48 | "ts-node": "10.9.1",
49 | "typescript": "5.5.4",
50 | "verdaccio": "^5.0.4"
51 | },
52 | "nx": {
53 | "includedScripts": []
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../.eslintrc.json"],
3 | "ignorePatterns": ["!**/*"],
4 | "overrides": [
5 | {
6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7 | "rules": {}
8 | },
9 | {
10 | "files": ["*.ts", "*.tsx"],
11 | "rules": {}
12 | },
13 | {
14 | "files": ["*.js", "*.jsx"],
15 | "rules": {}
16 | },
17 | {
18 | "files": ["*.json"],
19 | "parser": "jsonc-eslint-parser",
20 | "rules": {
21 | "@nx/dependency-checks": "error"
22 | }
23 | }
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | A NestJS module for integrating Drizzle ORM with Better-SQLite3 driver
7 |
8 |
9 |
10 |
11 |
12 |
13 | ## Table of Contents
14 |
15 | - [Table of Contents](#table-of-contents)
16 | - [Installation](#installation)
17 | - [Usage](#usage)
18 | - [Configuration](#configuration)
19 | - [Documentation](#documentation)
20 | - [License](#license)
21 |
22 | ## Installation
23 |
24 | ```bash
25 | npm install @knaadh/nestjs-drizzle-better-sqlite3 drizzle-orm better-sqlite3
26 | ```
27 |
28 | ## Usage
29 |
30 | Import the DrizzleBetterSQLiteModule module and pass an `options` object to initialize it. You can pass `options` object using the usual methods for [custom providers](https://docs.nestjs.com/fundamentals/custom-providers) as shown below:
31 |
32 | ```typescript
33 | import { Module } from '@nestjs/common';
34 | import { AppController } from './app.controller';
35 | import { AppService } from './app.service';
36 | import * as schema from '../db/schema';
37 | import { DrizzleBetterSQLiteModule } from '@knaadh/nestjs-drizzle-better-sqlite3';
38 |
39 | @Module({
40 | imports: [
41 | // Method #1: Pass options object
42 | DrizzleBetterSQLiteModule.register({
43 | tag: 'DB_DEV',
44 | sqlite3: {
45 | filename: 'demo.db',
46 | },
47 | config: { schema: { ...schema } },
48 | }),
49 |
50 | // Method #2: useFactory()
51 | DrizzleBetterSQLiteModule.registerAsync({
52 | tag: 'DB_PROD',
53 | useFactory() {
54 | return {
55 | sqlite3: {
56 | filename: 'demo.db',
57 | },
58 | config: { schema: { ...schema } },
59 | };
60 | },
61 | }),
62 |
63 | // Method #3: useClass()
64 | DrizzleBetterSQLiteModule.registerAsync({
65 | tag: 'DB_STAGING',
66 | useClass: DBConfigService,
67 | }),
68 | ],
69 | controllers: [AppController],
70 | providers: [AppService],
71 | })
72 | export class AppModule {}
73 | ```
74 |
75 | ```typescript
76 | export class DBConfigService {
77 | create = () => {
78 | return {
79 | sqlite3: {
80 | filename: 'demo.db',
81 | },
82 | config: { schema: { ...schema } },
83 | };
84 | };
85 | }
86 | ```
87 |
88 | You can inject the Drizzle instances using their respective `tag` specified in the configurations
89 |
90 | ```typescript
91 | import { Inject, Injectable } from '@nestjs/common';
92 | import * as schema from '../db/schema';
93 | import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
94 | @Injectable()
95 | export class AppService {
96 | constructor(
97 | @Inject('DB_DEV') private drizzleDev: BetterSQLite3Database,
98 | @Inject('DB_PROD') private drizzleProd: BetterSQLite3Database
99 | ) {}
100 | async getData() {
101 | const books = await this.drizzleDev.query.books.findMany();
102 | const authors = await this.drizzleProd.query.authors.findMany();
103 | return {
104 | books: books,
105 | authors: authors,
106 | };
107 | }
108 | }
109 | ```
110 |
111 | ## Configuration
112 |
113 | A DrizzleBetterSQLiteModule `option` object has the following interface:
114 |
115 | ```typescript
116 | export interface DrizzleBetterSQLiteConfig {
117 | sqlite3: {
118 | filename: string | Buffer;
119 | options?: Database.Options | undefined;
120 | };
121 | config?: DrizzleConfig | undefined;
122 | }
123 | ```
124 |
125 | - `sqlite3.filename:` path to the database file. If the database file does not exist, it is created
126 | - (optional) `sqlite3.options:` BetterSQLite [options](https://github.com/WiseLibs/better-sqlite3/blob/master/docs/api.md#new-databasepath-options)
127 | - (optional `config:` DrizzleORM configuration.
128 |
129 | ## Documentation
130 |
131 | - [NX](https://nx.dev/)
132 | - [DrizzleORM](https://orm.drizzle.team/)
133 | - [Better-SQLit3](https://github.com/WiseLibs/better-sqlite3)
134 |
135 | ## License
136 |
137 | This package is [MIT licensed](https://github.com/knaadh/nestjs-drizzle/blob/main/LICENSE).
138 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/jest.config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export default {
3 | displayName: '@knaadh/nestjs-drizzle-better-sqlite3',
4 | preset: '../../jest.preset.js',
5 | testEnvironment: 'node',
6 | transform: {
7 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
8 | },
9 | moduleFileExtensions: ['ts', 'js', 'html'],
10 | coverageDirectory: '../../coverage/packages/better-sqlite3',
11 | };
12 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-better-sqlite3",
3 | "version": "0.0.1",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "@knaadh/nestjs-drizzle-better-sqlite3",
9 | "version": "0.0.1",
10 | "dependencies": {
11 | "tslib": "^2.3.0"
12 | },
13 | "devDependencies": {
14 | "@types/better-sqlite3": "^7.6.6"
15 | }
16 | },
17 | "node_modules/@types/better-sqlite3": {
18 | "version": "7.6.6",
19 | "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.6.tgz",
20 | "integrity": "sha512-nuFAptzt0hZYBvyLzKQCbuCCK+RN9PHH4ezar5EJLIg2qpVhwQ/uLvLO/K8A9O7N8DafawgFupiyXQSs0U48Ng==",
21 | "dev": true,
22 | "dependencies": {
23 | "@types/node": "*"
24 | }
25 | },
26 | "node_modules/@types/node": {
27 | "version": "20.8.7",
28 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz",
29 | "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==",
30 | "dev": true,
31 | "dependencies": {
32 | "undici-types": "~5.25.1"
33 | }
34 | },
35 | "node_modules/tslib": {
36 | "version": "2.6.2",
37 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
38 | "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
39 | },
40 | "node_modules/undici-types": {
41 | "version": "5.25.3",
42 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz",
43 | "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==",
44 | "dev": true
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-better-sqlite3",
3 | "version": "1.2.0",
4 | "author": "Mithlesh Jasrotia ",
5 | "license": "MIT",
6 | "description": "A NestJS module for integrating Drizzle ORM with BetterSqlite3 driver",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/knaadh/nestjs-drizzle.git",
10 | "directory": "packages/better-sqlite3"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/knaadh/nestjs-drizzle/issues"
14 | },
15 | "homepage": "https://github.com/knaadh/nestjs-drizzle",
16 | "keywords": [
17 | "drizzle",
18 | "better-sqlite3",
19 | "database",
20 | "orm",
21 | "nestjs"
22 | ],
23 | "publishConfig": {
24 | "access": "public"
25 | },
26 | "peerDependencies": {
27 | "@nestjs/common": ">=9.0.0",
28 | "drizzle-orm": ">=0.28.6",
29 | "better-sqlite3": ">=7"
30 | },
31 | "type": "commonjs",
32 | "main": "./src/index.js",
33 | "typings": "./src/index.d.ts"
34 | }
35 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-better-sqlite3",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/better-sqlite3/src",
5 | "projectType": "library",
6 | "tags": [],
7 | "targets": {
8 | "build": {
9 | "executor": "@nx/js:tsc",
10 | "outputs": ["{options.outputPath}"],
11 | "options": {
12 | "outputPath": "dist/packages/better-sqlite3",
13 | "tsConfig": "packages/better-sqlite3/tsconfig.lib.json",
14 | "packageJson": "packages/better-sqlite3/package.json",
15 | "main": "packages/better-sqlite3/src/index.ts",
16 | "assets": ["packages/better-sqlite3/*.md"]
17 | }
18 | },
19 | "publish": {
20 | "command": "node tools/scripts/publish.mjs @knaadh/nestjs-drizzle-better-sqlite3 {args.ver} {args.tag}",
21 | "dependsOn": ["build"]
22 | },
23 | "lint": {
24 | "executor": "@nx/eslint:lint"
25 | },
26 | "test": {
27 | "executor": "@nx/jest:jest",
28 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
29 | "options": {
30 | "jestConfig": "packages/better-sqlite3/jest.config.ts"
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './sqlite.module';
2 | export * from './sqlite.definition';
3 | export * from './sqlite.decorator';
4 | export * from './sqlite.interface';
5 |
6 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/src/sqlite.decorator.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 |
3 | export const InjectDrizzle = (configTag = 'default') => {
4 | return Inject(configTag);
5 | };
--------------------------------------------------------------------------------
/packages/better-sqlite3/src/sqlite.definition.ts:
--------------------------------------------------------------------------------
1 | import { ConfigurableModuleBuilder } from '@nestjs/common';
2 | import { DrizzleBetterSQLiteConfig } from './sqlite.interface';
3 |
4 | export const {
5 | ConfigurableModuleClass,
6 | MODULE_OPTIONS_TOKEN,
7 | OPTIONS_TYPE,
8 | ASYNC_OPTIONS_TYPE,
9 | } = new ConfigurableModuleBuilder()
10 | .setExtras(
11 | {
12 | tag: 'default',
13 | },
14 | (definition, extras) => ({
15 | ...definition,
16 | tag: extras.tag,
17 | })
18 | )
19 | .build();
20 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/src/sqlite.interface.ts:
--------------------------------------------------------------------------------
1 | import * as Database from 'better-sqlite3';
2 | import { DrizzleConfig } from 'drizzle-orm';
3 | export interface DrizzleBetterSQLiteConfig {
4 | sqlite3: {
5 | filename: string | Buffer;
6 | options?: Database.Options | undefined;
7 | };
8 | config?: DrizzleConfig | undefined;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/src/sqlite.module.ts:
--------------------------------------------------------------------------------
1 | import { Global, DynamicModule } from '@nestjs/common';
2 | import {
3 | ASYNC_OPTIONS_TYPE,
4 | ConfigurableModuleClass,
5 | MODULE_OPTIONS_TOKEN,
6 | OPTIONS_TYPE,
7 | } from './sqlite.definition';
8 | import { DrizzleBetterSQLiteService } from './sqlite.service';
9 | import { DrizzleBetterSQLiteConfig } from './sqlite.interface';
10 |
11 | @Global()
12 | export class DrizzleBetterSQLiteModule extends ConfigurableModuleClass {
13 | static register(options: typeof OPTIONS_TYPE): DynamicModule {
14 | const { providers = [], exports = [], ...props } = super.register(options);
15 | return {
16 | ...props,
17 | providers: [
18 | ...providers,
19 | DrizzleBetterSQLiteService,
20 | {
21 | provide: options?.tag || 'default',
22 | useFactory: async (drizzleService: DrizzleBetterSQLiteService) => {
23 | return await drizzleService.getDrizzle(options);
24 | },
25 | inject: [DrizzleBetterSQLiteService],
26 | },
27 | ],
28 | exports: [...exports, options?.tag || 'default'],
29 | };
30 | }
31 | static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule {
32 | const {
33 | providers = [],
34 | exports = [],
35 | ...props
36 | } = super.registerAsync(options);
37 | return {
38 | ...props,
39 | providers: [
40 | ...providers,
41 | DrizzleBetterSQLiteService,
42 | {
43 | provide: options?.tag || 'default',
44 | useFactory: async (
45 | drizzleService: DrizzleBetterSQLiteService,
46 | config: DrizzleBetterSQLiteConfig
47 | ) => {
48 | return await drizzleService.getDrizzle(config);
49 | },
50 | inject: [DrizzleBetterSQLiteService, MODULE_OPTIONS_TOKEN],
51 | },
52 | ],
53 | exports: [...exports, options?.tag || 'default'],
54 | };
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/src/sqlite.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { DrizzleBetterSQLiteService } from './sqlite.service';
3 | describe('DrizzleBetterSQLiteService', () => {
4 | let service: DrizzleBetterSQLiteService;
5 |
6 | beforeEach(async () => {
7 | const module: TestingModule = await Test.createTestingModule({
8 | providers: [DrizzleBetterSQLiteService],
9 | }).compile();
10 |
11 | service = module.get(
12 | DrizzleBetterSQLiteService
13 | );
14 | });
15 |
16 | it('should be defined', () => {
17 | expect(service).toBeDefined();
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/src/sqlite.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { drizzle } from 'drizzle-orm/better-sqlite3';
3 | import Database from 'better-sqlite3';
4 | import { DrizzleBetterSQLiteConfig } from './sqlite.interface';
5 | @Injectable()
6 | export class DrizzleBetterSQLiteService {
7 | public async getDrizzle(options: DrizzleBetterSQLiteConfig) {
8 | const sqlite = new Database(
9 | options.sqlite3.filename,
10 | options.sqlite3.options
11 | );
12 | return drizzle(sqlite, options?.config);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "noImplicitOverride": true,
8 | "noPropertyAccessFromIndexSignature": true,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true,
11 | "esModuleInterop": true
12 | },
13 | "files": [],
14 | "include": [],
15 | "references": [
16 | {
17 | "path": "./tsconfig.lib.json"
18 | },
19 | {
20 | "path": "./tsconfig.spec.json"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"],
7 | "target": "es2021",
8 | "strictNullChecks": true,
9 | "noImplicitAny": true,
10 | "strictBindCallApply": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noFallthroughCasesInSwitch": true
13 | },
14 | "include": ["src/**/*.ts"],
15 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/better-sqlite3/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/mysql2/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../.eslintrc.json"],
3 | "ignorePatterns": ["!**/*"],
4 | "overrides": [
5 | {
6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7 | "rules": {}
8 | },
9 | {
10 | "files": ["*.ts", "*.tsx"],
11 | "rules": {}
12 | },
13 | {
14 | "files": ["*.js", "*.jsx"],
15 | "rules": {}
16 | },
17 | {
18 | "files": ["*.json"],
19 | "parser": "jsonc-eslint-parser",
20 | "rules": {
21 | "@nx/dependency-checks": "error"
22 | }
23 | }
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/mysql2/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | A NestJS module for integrating Drizzle ORM with MySQL2 driver
7 |
8 |
9 |
10 |
11 |
12 |
13 | ## Table of Contents
14 |
15 | - [Table of Contents](#table-of-contents)
16 | - [Installation](#installation)
17 | - [Usage](#usage)
18 | - [Configuration](#configuration)
19 | - [Documentation](#documentation)
20 | - [License](#license)
21 |
22 | ## Installation
23 |
24 | ```bash
25 | npm install @knaadh/nestjs-drizzle-mysql2 drizzle-orm mysql2
26 | ```
27 |
28 | ## Usage
29 |
30 | Import the DrizzleMySqlModule module and pass an `options` object to initialize it. You can pass `options` object using the usual methods for [custom providers](https://docs.nestjs.com/fundamentals/custom-providers) as shown below:
31 |
32 | ```typescript
33 | import { Module } from '@nestjs/common';
34 | import { AppController } from './app.controller';
35 | import { AppService } from './app.service';
36 | import * as schema from '../db/schema';
37 | import { DrizzleMySqlModule } from '@knaadh/nestjs-drizzle-mysql2';
38 |
39 | @Module({
40 | imports: [
41 | // Method #1: Pass options object
42 | DrizzleMySqlModule.register({
43 | tag: 'DB_DEV',
44 | mysql: {
45 | connection: 'client',
46 | config: {
47 | host: '127.0.0.1',
48 | user: 'root',
49 | database: 'drizzleDB',
50 | },
51 | },
52 | config: { schema: { ...schema }, mode: 'default' },
53 | }),
54 |
55 | // Method #2: useFactory()
56 | DrizzleMySqlModule.registerAsync({
57 | tag: 'DB_PROD',
58 | useFactory() {
59 | return {
60 | mysql: {
61 | connection: 'client',
62 | config: {
63 | host: '127.0.0.1',
64 | user: 'root',
65 | database: 'drizzleDB',
66 | },
67 | },
68 | config: { schema: { ...schema }, mode: 'default' },
69 | };
70 | },
71 | }),
72 |
73 | // Method #3: useClass()
74 | DrizzleMySqlModule.registerAsync({
75 | tag: 'DB_STAGING',
76 | useClass: DBConfigService,
77 | }),
78 | ],
79 | controllers: [AppController],
80 | providers: [AppService],
81 | })
82 | export class AppModule {}
83 | ```
84 |
85 | ```typescript
86 | export class DBConfigService {
87 | create = () => {
88 | return {
89 | mysql: {
90 | connection: 'client',
91 | config: {
92 | host: '127.0.0.1',
93 | user: 'root',
94 | database: 'drizzleDB',
95 | },
96 | },
97 | config: { schema: { ...schema }, mode: 'default' },
98 | };
99 | };
100 | }
101 | ```
102 |
103 | You can inject the Drizzle instances using their respective `tag` specified in the configurations
104 |
105 | ```typescript
106 | import { Inject, Injectable } from '@nestjs/common';
107 | import * as schema from '../db/schema';
108 | import { MySql2Database } from 'drizzle-orm/mysql2';
109 | @Injectable()
110 | export class AppService {
111 | constructor(
112 | @Inject('DB_DEV') private drizzleDev: MySql2Database,
113 | @Inject('DB_PROD') private drizzleProd: MySql2Database
114 | ) {}
115 | async getData() {
116 | const books = await this.drizzleDev.query.books.findMany();
117 | const authors = await this.drizzleProd.query.authors.findMany();
118 | return {
119 | books: books,
120 | authors: authors,
121 | };
122 | }
123 | }
124 | ```
125 |
126 | ## Configuration
127 |
128 | A DrizzleMySqlModule `option` object has the following interface:
129 |
130 | ```typescript
131 | export interface DrizzleMySqlConfig {
132 | mysql: {
133 | connection: 'client' | 'pool';
134 | config: ConnectionOptions | PoolOptions | string;
135 | };
136 | config: MySql2DrizzleConfig | undefined;
137 | }
138 | ```
139 |
140 | - `mysql.connection:` single `client` connection or a `pool` as mentioned [here](https://orm.drizzle.team/docs/quick-mysql/mysql2)
141 | - (optional) `mysql.config:` pass [client config](https://github.com/sidorares/node-mysql2#installation) or [pool config](https://github.com/sidorares/node-mysql2#installation) according to the connection
142 | - (required) `config:` DrizzleORM MySQL2 configuration. You need to specify mode as documented [here](https://orm.drizzle.team/docs/rqb#modes)
143 |
144 | ## Documentation
145 |
146 | - [NX](https://nx.dev/)
147 | - [DrizzleORM](https://orm.drizzle.team/)
148 | - [MySQL2](https://github.com/sidorares/node-mysql2)
149 |
150 | ## License
151 |
152 | This package is [MIT licensed](https://github.com/knaadh/nestjs-drizzle/blob/main/LICENSE).
153 |
--------------------------------------------------------------------------------
/packages/mysql2/jest.config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export default {
3 | displayName: '@knaadh/nestjs-drizzle-mysql2',
4 | preset: '../../jest.preset.js',
5 | testEnvironment: 'node',
6 | transform: {
7 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
8 | },
9 | moduleFileExtensions: ['ts', 'js', 'html'],
10 | coverageDirectory: '../../coverage/packages/mysql2',
11 | };
12 |
--------------------------------------------------------------------------------
/packages/mysql2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-mysql2",
3 | "version": "1.2.0",
4 | "author": "Mithlesh Jasrotia ",
5 | "license": "MIT",
6 | "description": "A NestJS module for integrating Drizzle ORM with MySQL2 driver",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/knaadh/nestjs-drizzle.git",
10 | "directory": "packages/mysql2"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/knaadh/nestjs-drizzle/issues"
14 | },
15 | "homepage": "https://github.com/knaadh/nestjs-drizzle",
16 | "keywords": [
17 | "drizzle",
18 | "mysql2",
19 | "database",
20 | "orm",
21 | "nestjs"
22 | ],
23 | "publishConfig": {
24 | "access": "public"
25 | },
26 | "peerDependencies": {
27 | "@nestjs/common": ">=9.0.0",
28 | "drizzle-orm": ">=0.28.6",
29 | "mysql2": ">=2"
30 | },
31 | "type": "commonjs",
32 | "main": "./src/index.js",
33 | "typings": "./src/index.d.ts"
34 | }
35 |
--------------------------------------------------------------------------------
/packages/mysql2/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-mysql2",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/mysql2/src",
5 | "projectType": "library",
6 | "tags": [],
7 | "targets": {
8 | "build": {
9 | "executor": "@nx/js:tsc",
10 | "outputs": ["{options.outputPath}"],
11 | "options": {
12 | "outputPath": "dist/packages/mysql2",
13 | "tsConfig": "packages/mysql2/tsconfig.lib.json",
14 | "packageJson": "packages/mysql2/package.json",
15 | "main": "packages/mysql2/src/index.ts",
16 | "assets": ["packages/mysql2/*.md"]
17 | }
18 | },
19 | "publish": {
20 | "command": "node tools/scripts/publish.mjs @knaadh/nestjs-drizzle-mysql2 {args.ver} {args.tag}",
21 | "dependsOn": ["build"]
22 | },
23 | "lint": {
24 | "executor": "@nx/eslint:lint"
25 | },
26 | "test": {
27 | "executor": "@nx/jest:jest",
28 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
29 | "options": {
30 | "jestConfig": "packages/mysql2/jest.config.ts"
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/mysql2/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './mysql.module';
2 | export * from './mysql.definition';
3 | export * from './mysql.decorator';
4 | export * from './mysql.interface';
5 |
--------------------------------------------------------------------------------
/packages/mysql2/src/mysql.decorator.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 |
3 | export const InjectDrizzle = (configTag = 'default') => {
4 | return Inject(configTag);
5 | };
--------------------------------------------------------------------------------
/packages/mysql2/src/mysql.definition.ts:
--------------------------------------------------------------------------------
1 | import { ConfigurableModuleBuilder } from '@nestjs/common';
2 | import { DrizzleMySqlConfig } from './mysql.interface';
3 |
4 | export const {
5 | ConfigurableModuleClass,
6 | MODULE_OPTIONS_TOKEN,
7 | OPTIONS_TYPE,
8 | ASYNC_OPTIONS_TYPE,
9 | } = new ConfigurableModuleBuilder()
10 | .setExtras(
11 | {
12 | tag: 'default',
13 | },
14 | (definition, extras) => ({
15 | ...definition,
16 | tag: extras.tag,
17 | })
18 | )
19 | .build();
20 |
--------------------------------------------------------------------------------
/packages/mysql2/src/mysql.interface.ts:
--------------------------------------------------------------------------------
1 | import { MySql2DrizzleConfig } from 'drizzle-orm/mysql2';
2 | import { ConnectionOptions, PoolOptions } from 'mysql2';
3 | export interface DrizzleMySqlConfig {
4 | mysql: {
5 | connection: 'client' | 'pool';
6 | config: ConnectionOptions | PoolOptions | string;
7 | };
8 | config: MySql2DrizzleConfig | undefined;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/mysql2/src/mysql.module.ts:
--------------------------------------------------------------------------------
1 | import { Global, DynamicModule } from '@nestjs/common';
2 | import {
3 | ASYNC_OPTIONS_TYPE,
4 | ConfigurableModuleClass,
5 | MODULE_OPTIONS_TOKEN,
6 | OPTIONS_TYPE,
7 | } from './mysql.definition';
8 | import { DrizzleMySqlService } from './mysql.service';
9 | import { DrizzleMySqlConfig } from './mysql.interface';
10 |
11 | @Global()
12 | export class DrizzleMySqlModule extends ConfigurableModuleClass {
13 | static register(options: typeof OPTIONS_TYPE): DynamicModule {
14 | const { providers = [], exports = [], ...props } = super.register(options);
15 | return {
16 | ...props,
17 | providers: [
18 | ...providers,
19 | DrizzleMySqlService,
20 | {
21 | provide: options?.tag || 'default',
22 | useFactory: async (drizzleService: DrizzleMySqlService) => {
23 | return await drizzleService.getDrizzle(options);
24 | },
25 | inject: [DrizzleMySqlService],
26 | },
27 | ],
28 | exports: [...exports, options?.tag || 'default'],
29 | };
30 | }
31 | static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule {
32 | const {
33 | providers = [],
34 | exports = [],
35 | ...props
36 | } = super.registerAsync(options);
37 | return {
38 | ...props,
39 | providers: [
40 | ...providers,
41 | DrizzleMySqlService,
42 | {
43 | provide: options?.tag || 'default',
44 | useFactory: async (
45 | drizzleService: DrizzleMySqlService,
46 | config: DrizzleMySqlConfig
47 | ) => {
48 | return await drizzleService.getDrizzle(config);
49 | },
50 | inject: [DrizzleMySqlService, MODULE_OPTIONS_TOKEN],
51 | },
52 | ],
53 | exports: [...exports, options?.tag || 'default'],
54 | };
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/packages/mysql2/src/mysql.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { DrizzleMySqlService } from './mysql.service';
3 | describe('DrizzleMySqlService', () => {
4 | let service: DrizzleMySqlService;
5 |
6 | beforeEach(async () => {
7 | const module: TestingModule = await Test.createTestingModule({
8 | providers: [DrizzleMySqlService],
9 | }).compile();
10 |
11 | service = module.get(DrizzleMySqlService);
12 | });
13 |
14 | it('should be defined', () => {
15 | expect(service).toBeDefined();
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/packages/mysql2/src/mysql.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import * as mysql from 'mysql2';
3 | import { DrizzleMySqlConfig } from './mysql.interface';
4 | import { drizzle } from 'drizzle-orm/mysql2';
5 | @Injectable()
6 | export class DrizzleMySqlService {
7 | public async getDrizzle(options: DrizzleMySqlConfig) {
8 | if (options.mysql.connection === 'client') {
9 | const client = await mysql.createConnection(options.mysql.config as any);
10 | return drizzle(client, options?.config);
11 | }
12 | const pool = mysql.createPool(options.mysql.config as any);
13 | return drizzle(pool, options?.config);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/mysql2/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "noImplicitOverride": true,
8 | "noPropertyAccessFromIndexSignature": true,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true
11 | },
12 | "files": [],
13 | "include": [],
14 | "references": [
15 | {
16 | "path": "./tsconfig.lib.json"
17 | },
18 | {
19 | "path": "./tsconfig.spec.json"
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/packages/mysql2/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"],
7 | "target": "es2021",
8 | "strictNullChecks": true,
9 | "noImplicitAny": true,
10 | "strictBindCallApply": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noFallthroughCasesInSwitch": true
13 | },
14 | "include": ["src/**/*.ts"],
15 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/mysql2/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/node-postgres/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../.eslintrc.json"],
3 | "ignorePatterns": ["!**/*"],
4 | "overrides": [
5 | {
6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7 | "rules": {}
8 | },
9 | {
10 | "files": ["*.ts", "*.tsx"],
11 | "rules": {}
12 | },
13 | {
14 | "files": ["*.js", "*.jsx"],
15 | "rules": {}
16 | },
17 | {
18 | "files": ["*.json"],
19 | "parser": "jsonc-eslint-parser",
20 | "rules": {
21 | "@nx/dependency-checks": "error"
22 | }
23 | }
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/node-postgres/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | A NestJS module for integrating Drizzle ORM with Node-Postgres driver
7 |
8 |
9 |
10 |
11 |
12 |
13 | ## Table of Contents
14 |
15 | - [Table of Contents](#table-of-contents)
16 | - [Installation](#installation)
17 | - [Usage](#usage)
18 | - [Configuration](#configuration)
19 | - [Documentation](#documentation)
20 | - [License](#license)
21 |
22 | ## Installation
23 |
24 | ```bash
25 | npm install @knaadh/nestjs-drizzle-pg drizzle-orm pg
26 | ```
27 |
28 | ## Usage
29 |
30 | Import the DrizzlePGModule module and pass an `options` object to initialize it. You can pass `options` object using the usual methods for [custom providers](https://docs.nestjs.com/fundamentals/custom-providers) as shown below:
31 |
32 | ```typescript
33 | import { Module } from '@nestjs/common';
34 | import { AppController } from './app.controller';
35 | import { AppService } from './app.service';
36 | import * as schema from '../db/schema';
37 | import { DrizzlePGModule } from '@knaadh/nestjs-drizzle-pg';
38 |
39 | @Module({
40 | imports: [
41 | // Method #1: Pass options object
42 | DrizzlePGModule.register({
43 | tag: 'DB_DEV',
44 | pg: {
45 | connection: 'client',
46 | config: {
47 | connectionString: 'postgres://postgres:@127.0.0.1:5432/drizzleDB',
48 | },
49 | },
50 | config: { schema: { ...schema } },
51 | }),
52 |
53 | // Method #2: useFactory()
54 | DrizzlePGModule.registerAsync({
55 | tag: 'DB_PROD',
56 | useFactory() {
57 | return {
58 | pg: {
59 | connection: 'client',
60 | config: {
61 | connectionString: 'postgres://postgres:@127.0.0.1:5432/drizzleDB',
62 | },
63 | },
64 | config: { schema: { ...schema } },
65 | };
66 | },
67 | }),
68 |
69 | // Method #3: useClass()
70 | DrizzlePGModule.registerAsync({
71 | tag: 'DB_STAGING',
72 | useClass: DBConfigService,
73 | }),
74 | ],
75 | controllers: [AppController],
76 | providers: [AppService],
77 | })
78 | export class AppModule {}
79 | ```
80 |
81 | ```typescript
82 | export class DBConfigService {
83 | create = () => {
84 | return {
85 | pg: {
86 | connection: 'client' as const,
87 | config: {
88 | connectionString: 'postgres://postgres:@127.0.0.1:5432/drizzleDB',
89 | },
90 | },
91 | config: { schema: { ...schema } },
92 | };
93 | };
94 | }
95 | ```
96 | You can inject the Drizzle instances using their respective `tag` specified in the configurations
97 |
98 | ```typescript
99 | import { Inject, Injectable } from '@nestjs/common';
100 | import * as schema from '../db/schema';
101 | import { NodePgDatabase } from 'drizzle-orm/node-postgres';
102 | @Injectable()
103 | export class AppService {
104 | constructor(
105 | @Inject('DB_DEV') private drizzleDev: NodePgDatabase,
106 | @Inject('DB_PROD') private drizzleProd: NodePgDatabase
107 | ) {}
108 | async getData() {
109 | const books = await this.drizzleDev.query.books.findMany();
110 | const authors = await this.drizzleProd.query.authors.findMany();
111 | return {
112 | books: books,
113 | authors: authors,
114 | };
115 | }
116 | }
117 | ```
118 |
119 | ## Configuration
120 |
121 | A DrizzlePGModule `option` object has the following interface:
122 |
123 | ```typescript
124 | export interface DrizzlePGConfig {
125 | pg: {
126 | connection: 'client' | 'pool';
127 | config: ClientConfig | PoolConfig;
128 | };
129 | config?: DrizzleConfig | undefined;
130 | }
131 | ```
132 |
133 | - `pg.connection:` single `client` connection or a `pool` as mentioned [here](https://orm.drizzle.team/docs/quick-postgresql/node-postgres)
134 | - (optional) `postgres.config:` pass [client config](https://node-postgres.com/apis/client) or [pool config](https://node-postgres.com/apis/pool) according to the connection
135 | - (optional) `config:` DrizzleORM configuration
136 |
137 | ## Documentation
138 |
139 | - [NX](https://nx.dev/)
140 | - [DrizzleORM](https://orm.drizzle.team/)
141 | - [Node-PostGres](https://github.com/porsager/postgres)
142 |
143 | ## License
144 |
145 | This package is [MIT licensed](https://github.com/knaadh/nestjs-drizzle/blob/main/LICENSE).
146 |
--------------------------------------------------------------------------------
/packages/node-postgres/jest.config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export default {
3 | displayName: '@knaadh/nestjs-drizzle-pg',
4 | preset: '../../jest.preset.js',
5 | testEnvironment: 'node',
6 | transform: {
7 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
8 | },
9 | moduleFileExtensions: ['ts', 'js', 'html'],
10 | coverageDirectory: '../../coverage/packages/node-postgres',
11 | };
12 |
--------------------------------------------------------------------------------
/packages/node-postgres/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-pg",
3 | "version": "1.2.0",
4 | "author": "Mithlesh Jasrotia ",
5 | "license": "MIT",
6 | "description": "A NestJS module for integrating Drizzle ORM with Node-Postgres driver",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/knaadh/nestjs-drizzle.git",
10 | "directory": "packages/node-postgres"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/knaadh/nestjs-drizzle/issues"
14 | },
15 | "homepage": "https://github.com/knaadh/nestjs-drizzle",
16 | "keywords": [
17 | "drizzle",
18 | "node-postgres",
19 | "database",
20 | "orm",
21 | "nestjs",
22 | "pg"
23 | ],
24 | "publishConfig": {
25 | "access": "public"
26 | },
27 | "peerDependencies": {
28 | "@nestjs/common": ">=9.0.0",
29 | "drizzle-orm": ">=0.28.6",
30 | "pg": ">=8"
31 | },
32 | "type": "commonjs",
33 | "main": "./src/index.js",
34 | "typings": "./src/index.d.ts"
35 | }
36 |
--------------------------------------------------------------------------------
/packages/node-postgres/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-pg",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/node-postgres/src",
5 | "projectType": "library",
6 | "tags": [],
7 | "targets": {
8 | "build": {
9 | "executor": "@nx/js:tsc",
10 | "outputs": ["{options.outputPath}"],
11 | "options": {
12 | "outputPath": "dist/packages/node-postgres",
13 | "tsConfig": "packages/node-postgres/tsconfig.lib.json",
14 | "packageJson": "packages/node-postgres/package.json",
15 | "main": "packages/node-postgres/src/index.ts",
16 | "assets": ["packages/node-postgres/*.md"]
17 | }
18 | },
19 | "publish": {
20 | "command": "node tools/scripts/publish.mjs @knaadh/nestjs-drizzle-pg {args.ver} {args.tag}",
21 | "dependsOn": ["build"]
22 | },
23 | "lint": {
24 | "executor": "@nx/eslint:lint"
25 | },
26 | "test": {
27 | "executor": "@nx/jest:jest",
28 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
29 | "options": {
30 | "jestConfig": "packages/node-postgres/jest.config.ts"
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/node-postgres/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './node-postgres.module';
2 | export * from './node-postgres.definition';
3 | export * from './node-postgres.decorator';
4 | export * from './node-postgres.interface'
5 |
--------------------------------------------------------------------------------
/packages/node-postgres/src/node-postgres.decorator.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 |
3 | export const InjectDrizzle = (configTag = 'default') => {
4 | return Inject(configTag);
5 | };
--------------------------------------------------------------------------------
/packages/node-postgres/src/node-postgres.definition.ts:
--------------------------------------------------------------------------------
1 | import { ConfigurableModuleBuilder } from '@nestjs/common';
2 | import { DrizzlePGConfig } from './node-postgres.interface';
3 |
4 | export const {
5 | ConfigurableModuleClass,
6 | MODULE_OPTIONS_TOKEN,
7 | OPTIONS_TYPE,
8 | ASYNC_OPTIONS_TYPE,
9 | } = new ConfigurableModuleBuilder()
10 | .setExtras(
11 | {
12 | tag: 'default',
13 | },
14 | (definition, extras) => ({
15 | ...definition,
16 | tag: extras.tag,
17 | })
18 | )
19 | .build();
20 |
--------------------------------------------------------------------------------
/packages/node-postgres/src/node-postgres.interface.ts:
--------------------------------------------------------------------------------
1 | import { DrizzleConfig } from 'drizzle-orm';
2 | import { ClientConfig, PoolConfig } from 'pg';
3 | export interface DrizzlePGConfig {
4 | pg: {
5 | connection: 'client' | 'pool';
6 | config: ClientConfig | PoolConfig;
7 | };
8 | config?: DrizzleConfig | undefined;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/node-postgres/src/node-postgres.module.ts:
--------------------------------------------------------------------------------
1 | import { Global, DynamicModule } from '@nestjs/common';
2 | import {
3 | ASYNC_OPTIONS_TYPE,
4 | ConfigurableModuleClass,
5 | MODULE_OPTIONS_TOKEN,
6 | OPTIONS_TYPE,
7 | } from './node-postgres.definition';
8 | import { DrizzlePGService } from './node-postgres.service';
9 | import { DrizzlePGConfig } from './node-postgres.interface';
10 |
11 | @Global()
12 | export class DrizzlePGModule extends ConfigurableModuleClass {
13 | static register(options: typeof OPTIONS_TYPE): DynamicModule {
14 | const { providers = [], exports = [], ...props } = super.register(options);
15 | return {
16 | ...props,
17 | providers: [
18 | ...providers,
19 | DrizzlePGService,
20 | {
21 | provide: options?.tag || 'default',
22 | useFactory: async (drizzleService: DrizzlePGService) => {
23 | return await drizzleService.getDrizzle(options);
24 | },
25 | inject: [DrizzlePGService],
26 | },
27 | ],
28 | exports: [...exports, options?.tag || 'default'],
29 | };
30 | }
31 | static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule {
32 | const {
33 | providers = [],
34 | exports = [],
35 | ...props
36 | } = super.registerAsync(options);
37 | return {
38 | ...props,
39 | providers: [
40 | ...providers,
41 | DrizzlePGService,
42 | {
43 | provide: options?.tag || 'default',
44 | useFactory: async (
45 | drizzleService: DrizzlePGService,
46 | config: DrizzlePGConfig
47 | ) => {
48 | return await drizzleService.getDrizzle(config);
49 | },
50 | inject: [DrizzlePGService, MODULE_OPTIONS_TOKEN],
51 | },
52 | ],
53 | exports: [...exports, options?.tag || 'default'],
54 | };
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/packages/node-postgres/src/node-postgres.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { DrizzlePGService } from './node-postgres.service';
3 |
4 | describe('DrizzlePGService', () => {
5 | let service: DrizzlePGService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [DrizzlePGService],
10 | }).compile();
11 |
12 | service = module.get(DrizzlePGService);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/packages/node-postgres/src/node-postgres.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { drizzle } from 'drizzle-orm/node-postgres';
3 | import { Client, Pool } from 'pg';
4 | import { DrizzlePGConfig } from './node-postgres.interface';
5 | @Injectable()
6 | export class DrizzlePGService {
7 | public async getDrizzle(options: DrizzlePGConfig) {
8 | if (options.pg.connection === 'client') {
9 | const client = new Client(options.pg.config);
10 | await client.connect();
11 | return drizzle(client, options?.config);
12 | }
13 | const pool = new Pool(options.pg.config);
14 | return drizzle(pool, options?.config);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/packages/node-postgres/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "noImplicitOverride": true,
8 | "noPropertyAccessFromIndexSignature": true,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true
11 | },
12 | "files": [],
13 | "include": [],
14 | "references": [
15 | {
16 | "path": "./tsconfig.lib.json"
17 | },
18 | {
19 | "path": "./tsconfig.spec.json"
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/packages/node-postgres/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"],
7 | "target": "es2021",
8 | "strictNullChecks": true,
9 | "noImplicitAny": true,
10 | "strictBindCallApply": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noFallthroughCasesInSwitch": true
13 | },
14 | "include": ["src/**/*.ts"],
15 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/node-postgres/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/planetscale/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../.eslintrc.json"],
3 | "ignorePatterns": ["!**/*"],
4 | "overrides": [
5 | {
6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7 | "rules": {}
8 | },
9 | {
10 | "files": ["*.ts", "*.tsx"],
11 | "rules": {}
12 | },
13 | {
14 | "files": ["*.js", "*.jsx"],
15 | "rules": {}
16 | },
17 | {
18 | "files": ["*.json"],
19 | "parser": "jsonc-eslint-parser",
20 | "rules": {
21 | "@nx/dependency-checks": "error"
22 | }
23 | }
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/planetscale/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | A NestJS module for integrating Drizzle ORM with official PlanetScale driver
7 |
8 |
9 |
10 |
11 |
12 |
13 | ## Table of Contents
14 |
15 | - [Table of Contents](#table-of-contents)
16 | - [Installation](#installation)
17 | - [Usage](#usage)
18 | - [Configuration](#configuration)
19 | - [Documentation](#documentation)
20 | - [License](#license)
21 |
22 | ## Compatibility
23 |
24 | | Package Version | drizzle-orm Version |
25 | | --------------- | ------------------- |
26 | | 1.3.x | ≥0.3.0 |
27 | | ≤1.2.x | <0.3.0 |
28 |
29 | ## Installation
30 |
31 | ```bash
32 | npm install @knaadh/nestjs-drizzle-planetscale drizzle-orm @planetscale/database
33 | ```
34 |
35 | ## Usage
36 |
37 | Import the DrizzlePlanetScaleModule module and pass an `options` object to initialize it. You can pass `options` object using the usual methods for [custom providers](https://docs.nestjs.com/fundamentals/custom-providers) as shown below:
38 |
39 | ```typescript
40 | import { Module } from '@nestjs/common';
41 | import { AppController } from './app.controller';
42 | import { AppService } from './app.service';
43 | import * as schema from '../db/schema';
44 | import { DrizzlePlanetScaleModule } from '@knaadh/nestjs-drizzle-planetscale';
45 |
46 | @Module({
47 | imports: [
48 | // Method #1: Pass options object
49 | DrizzlePlanetScaleModule.register({
50 | tag: 'DB_DEV',
51 | planetscale: {
52 | config: {
53 | username: 'PLANETSCALE_USERNAME',
54 | password: 'PLANETSCALE_PASSWORD',
55 | host: 'PLANETSCALE_HOST',
56 | },
57 | },
58 | config: { schema: { ...schema } },
59 | }),
60 |
61 | // Method #2: useFactory()
62 | DrizzlePlanetScaleModule.registerAsync({
63 | tag: 'DB_PROD',
64 | useFactory() {
65 | return {
66 | planetscale: {
67 | config: {
68 | username: 'PLANETSCALE_USERNAME',
69 | password: 'PLANETSCALE_PASSWORD',
70 | host: 'PLANETSCALE_HOST',
71 | },
72 | },
73 | config: { schema: { ...schema } },
74 | };
75 | },
76 | }),
77 |
78 | // Method #3: useClass()
79 | DrizzlePlanetScaleModule.registerAsync({
80 | tag: 'DB_STAGING',
81 | useClass: DBConfigService,
82 | }),
83 | ],
84 | controllers: [AppController],
85 | providers: [AppService],
86 | })
87 | export class AppModule {}
88 | ```
89 |
90 | ```typescript
91 | export class DBConfigService {
92 | create = () => {
93 | return {
94 | planetscale: {
95 | config: {
96 | username: 'PLANETSCALE_USERNAME',
97 | password: 'PLANETSCALE_PASSWORD',
98 | host: 'PLANETSCALE_HOST',
99 | },
100 | },
101 | config: { schema: { ...schema } },
102 | };
103 | };
104 | }
105 | ```
106 |
107 | You can inject the Drizzle instances using their respective `tag` specified in the configurations
108 |
109 | ```typescript
110 | import { Inject, Injectable } from '@nestjs/common';
111 | import * as schema from '../db/schema';
112 | import { PlanetScaleDatabase } from 'drizzle-orm/planetscale-serverless';
113 | @Injectable()
114 | export class AppService {
115 | constructor(@Inject('DB_DEV') private drizzleDev: PlanetScaleDatabase, @Inject('DB_PROD') private drizzleProd: PlanetScaleDatabase) {}
116 | async getData() {
117 | const books = await this.drizzleDev.query.books.findMany();
118 | const authors = await this.drizzleProd.query.authors.findMany();
119 | return {
120 | books: books,
121 | authors: authors,
122 | };
123 | }
124 | }
125 | ```
126 |
127 | ## Configuration
128 |
129 | A DrizzlePlanetScaleModule `option` object has the following interface:
130 |
131 | ```typescript
132 | export interface DrizzlePlanetScaleConfig {
133 | planetscale: {
134 | config: Config;
135 | };
136 | config?: DrizzleConfig | undefined;
137 | }
138 | ```
139 |
140 | - `planetscale.config:` PlanetScale [config](https://planetscale.com/docs/tutorials/planetscale-serverless-driver)
141 | - (optional) `config:` DrizzleORM configuration
142 |
143 | ## Documentation
144 |
145 | - [NX](https://nx.dev/)
146 | - [DrizzleORM](https://orm.drizzle.team/)
147 | - [PlanetScale](https://planetscale.com/docs/tutorials/planetscale-serverless-driver)
148 |
149 | ## License
150 |
151 | This package is [MIT licensed](https://github.com/knaadh/nestjs-drizzle/blob/main/LICENSE).
152 |
--------------------------------------------------------------------------------
/packages/planetscale/jest.config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export default {
3 | displayName: '@knaadh/nestjs-drizzle-planetscale',
4 | preset: '../../jest.preset.js',
5 | testEnvironment: 'node',
6 | transform: {
7 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
8 | },
9 | moduleFileExtensions: ['ts', 'js', 'html'],
10 | coverageDirectory: '../../coverage/packages/planetscale',
11 | };
12 |
--------------------------------------------------------------------------------
/packages/planetscale/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-planetscale",
3 | "version": "1.3.0",
4 | "author": "Mithlesh Jasrotia ",
5 | "license": "MIT",
6 | "description": "A NestJS module for integrating Drizzle ORM with official PlanetScale driver",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/knaadh/nestjs-drizzle.git",
10 | "directory": "packages/planetscale"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/knaadh/nestjs-drizzle/issues"
14 | },
15 | "homepage": "https://github.com/knaadh/nestjs-drizzle",
16 | "keywords": [
17 | "drizzle",
18 | "planetscale",
19 | "serverless",
20 | "database",
21 | "orm",
22 | "nestjs"
23 | ],
24 | "publishConfig": {
25 | "access": "public"
26 | },
27 | "peerDependencies": {
28 | "@nestjs/common": ">=9.0.0",
29 | "drizzle-orm": ">=0.30.0",
30 | "@planetscale/database": ">=1"
31 | },
32 | "type": "commonjs",
33 | "main": "./src/index.js",
34 | "typings": "./src/index.d.ts"
35 | }
36 |
--------------------------------------------------------------------------------
/packages/planetscale/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-planetscale",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/planetscale/src",
5 | "projectType": "library",
6 | "tags": [],
7 | "targets": {
8 | "build": {
9 | "executor": "@nx/js:tsc",
10 | "outputs": ["{options.outputPath}"],
11 | "options": {
12 | "outputPath": "dist/packages/planetscale",
13 | "tsConfig": "packages/planetscale/tsconfig.lib.json",
14 | "packageJson": "packages/planetscale/package.json",
15 | "main": "packages/planetscale/src/index.ts",
16 | "assets": ["packages/planetscale/*.md"]
17 | }
18 | },
19 | "publish": {
20 | "command": "node tools/scripts/publish.mjs @knaadh/nestjs-drizzle-planetscale {args.ver} {args.tag}",
21 | "dependsOn": ["build"]
22 | },
23 | "lint": {
24 | "executor": "@nx/eslint:lint"
25 | },
26 | "test": {
27 | "executor": "@nx/jest:jest",
28 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
29 | "options": {
30 | "jestConfig": "packages/planetscale/jest.config.ts"
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/planetscale/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './planetscale.module';
2 | export * from './planetscale.definition';
3 | export * from './planetscale.decorator';
4 | export * from './planetscale.interface';
5 |
--------------------------------------------------------------------------------
/packages/planetscale/src/planetscale.decorator.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 |
3 | export const InjectDrizzle = (configTag = 'default') => {
4 | return Inject(configTag);
5 | };
--------------------------------------------------------------------------------
/packages/planetscale/src/planetscale.definition.ts:
--------------------------------------------------------------------------------
1 | import { ConfigurableModuleBuilder } from '@nestjs/common';
2 | import { DrizzlePlanetScaleConfig } from './planetscale.interface';
3 |
4 | export const {
5 | ConfigurableModuleClass,
6 | MODULE_OPTIONS_TOKEN,
7 | OPTIONS_TYPE,
8 | ASYNC_OPTIONS_TYPE,
9 | } = new ConfigurableModuleBuilder()
10 | .setExtras(
11 | {
12 | tag: 'default',
13 | },
14 | (definition, extras) => ({
15 | ...definition,
16 | tag: extras.tag,
17 | })
18 | )
19 | .build();
20 |
--------------------------------------------------------------------------------
/packages/planetscale/src/planetscale.interface.ts:
--------------------------------------------------------------------------------
1 | import { Config } from '@planetscale/database';
2 | import { DrizzleConfig } from 'drizzle-orm';
3 |
4 | export interface DrizzlePlanetScaleConfig {
5 | planetscale: {
6 | config: Config;
7 | };
8 | config?: DrizzleConfig | undefined;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/planetscale/src/planetscale.module.ts:
--------------------------------------------------------------------------------
1 | import { Global, DynamicModule } from '@nestjs/common';
2 | import {
3 | ASYNC_OPTIONS_TYPE,
4 | ConfigurableModuleClass,
5 | MODULE_OPTIONS_TOKEN,
6 | OPTIONS_TYPE,
7 | } from './planetscale.definition';
8 | import { DrizzlePlanetScaleService } from './planetscale.service';
9 | import { DrizzlePlanetScaleConfig } from './planetscale.interface';
10 |
11 | @Global()
12 | export class DrizzlePlanetScaleModule extends ConfigurableModuleClass {
13 | static register(options: typeof OPTIONS_TYPE): DynamicModule {
14 | const { providers = [], exports = [], ...props } = super.register(options);
15 | return {
16 | ...props,
17 | providers: [
18 | ...providers,
19 | DrizzlePlanetScaleService,
20 | {
21 | provide: options?.tag || 'default',
22 | useFactory: async (drizzleService: DrizzlePlanetScaleService) => {
23 | return await drizzleService.getDrizzle(options);
24 | },
25 | inject: [DrizzlePlanetScaleService],
26 | },
27 | ],
28 | exports: [...exports, options?.tag || 'default'],
29 | };
30 | }
31 | static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule {
32 | const {
33 | providers = [],
34 | exports = [],
35 | ...props
36 | } = super.registerAsync(options);
37 | return {
38 | ...props,
39 | providers: [
40 | ...providers,
41 | DrizzlePlanetScaleService,
42 | {
43 | provide: options?.tag || 'default',
44 | useFactory: async (
45 | drizzleService: DrizzlePlanetScaleService,
46 | config: DrizzlePlanetScaleConfig
47 | ) => {
48 | return await drizzleService.getDrizzle(config);
49 | },
50 | inject: [DrizzlePlanetScaleService, MODULE_OPTIONS_TOKEN],
51 | },
52 | ],
53 | exports: [...exports, options?.tag || 'default'],
54 | };
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/packages/planetscale/src/planetscale.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { DrizzlePlanetScaleService } from './planetscale.service';
3 | describe('DrizzlePlanetScaleService', () => {
4 | let service: DrizzlePlanetScaleService;
5 |
6 | beforeEach(async () => {
7 | const module: TestingModule = await Test.createTestingModule({
8 | providers: [DrizzlePlanetScaleService],
9 | }).compile();
10 |
11 | service = module.get(DrizzlePlanetScaleService);
12 | });
13 |
14 | it('should be defined', () => {
15 | expect(service).toBeDefined();
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/packages/planetscale/src/planetscale.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { Client } from '@planetscale/database';
3 | import { drizzle } from 'drizzle-orm/planetscale-serverless';
4 | import { DrizzlePlanetScaleConfig } from './planetscale.interface';
5 | @Injectable()
6 | export class DrizzlePlanetScaleService {
7 | public async getDrizzle(options: DrizzlePlanetScaleConfig) {
8 | const client = new Client(options?.planetscale.config);
9 | return drizzle(client, options?.config);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/planetscale/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "noImplicitOverride": true,
8 | "noPropertyAccessFromIndexSignature": true,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true
11 | },
12 | "files": [],
13 | "include": [],
14 | "references": [
15 | {
16 | "path": "./tsconfig.lib.json"
17 | },
18 | {
19 | "path": "./tsconfig.spec.json"
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/packages/planetscale/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"],
7 | "target": "es2021",
8 | "strictNullChecks": true,
9 | "noImplicitAny": true,
10 | "strictBindCallApply": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noFallthroughCasesInSwitch": true
13 | },
14 | "include": ["src/**/*.ts"],
15 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/planetscale/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/postgres-js/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../.eslintrc.json"],
3 | "ignorePatterns": ["!**/*"],
4 | "overrides": [
5 | {
6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7 | "rules": {}
8 | },
9 | {
10 | "files": ["*.ts", "*.tsx"],
11 | "rules": {}
12 | },
13 | {
14 | "files": ["*.js", "*.jsx"],
15 | "rules": {}
16 | },
17 | {
18 | "files": ["*.json"],
19 | "parser": "jsonc-eslint-parser",
20 | "rules": {
21 | "@nx/dependency-checks": "error"
22 | }
23 | }
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/postgres-js/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | A NestJS module for integrating Drizzle ORM with PostgresJS driver
7 |
8 |
9 |
10 |
11 |
12 |
13 | ## Table of Contents
14 |
15 | - [Table of Contents](#table-of-contents)
16 | - [Installation](#installation)
17 | - [Usage](#usage)
18 | - [Configuration](#configuration)
19 | - [Documentation](#documentation)
20 | - [License](#license)
21 |
22 | ## Installation
23 |
24 | ```bash
25 | npm install @knaadh/nestjs-drizzle-postgres drizzle-orm postgres
26 | ```
27 |
28 | ## Usage
29 |
30 | Import the DrizzlePostgresModule module and pass an `options` object to initialize it. You can pass `options` object using the usual methods for [custom providers](https://docs.nestjs.com/fundamentals/custom-providers) as shown below:
31 |
32 | ```typescript
33 | import { Module } from '@nestjs/common';
34 | import { AppController } from './app.controller';
35 | import { AppService } from './app.service';
36 | import * as schema from '../db/schema';
37 | import { DrizzlePostgresModule } from '@knaadh/nestjs-drizzle-postgres';
38 |
39 | @Module({
40 | imports: [
41 | // Method #1: Pass options object
42 | DrizzlePostgresModule.register({
43 | tag: 'DB_DEV',
44 | postgres: {
45 | url: 'postgres://postgres:@127.0.0.1:5432/drizzleDB',
46 | },
47 | config: { schema: { ...schema } },
48 | }),
49 |
50 | // Method #2: useFactory()
51 | DrizzlePostgresModule.registerAsync({
52 | tag: 'DB_PROD',
53 | useFactory() {
54 | return {
55 | postgres: {
56 | url: 'postgres://postgres:@127.0.0.1:5432/drizzleDB',
57 | },
58 | config: { schema: { ...schema } },
59 | };
60 | },
61 | }),
62 |
63 | // Method #3: useClass()
64 | DrizzlePostgresModule.registerAsync({
65 | tag: 'DB_STAGING',
66 | useClass: DBConfigService,
67 | }),
68 | ],
69 |
70 | controllers: [AppController],
71 | providers: [AppService],
72 | })
73 | export class AppModule {}
74 | ```
75 |
76 | ```typescript
77 | export class DBConfigService {
78 | create = () => {
79 | return {
80 | postgres: {
81 | url: 'postgres://postgres:@127.0.0.1:5432/drizzleDB',
82 | },
83 | config: { schema: { ...schema } },
84 | };
85 | };
86 | }
87 | ```
88 | You can inject the Drizzle instances using their respective `tag` specified in the configurations
89 |
90 | ```typescript
91 | import { Inject, Injectable } from '@nestjs/common';
92 | import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
93 | import * as schema from '../db/schema';
94 | @Injectable()
95 | export class AppService {
96 | constructor(
97 | @Inject('DB_DEV') private drizzleDev: PostgresJsDatabase,
98 | @Inject('DB_PROD') private drizzleProd: PostgresJsDatabase
99 | ) {}
100 | async getData() {
101 | const books = await this.drizzleDev.query.books.findMany();
102 | const authors = await this.drizzleProd.query.authors.findMany();
103 | return {
104 | books: books,
105 | authors: authors,
106 | };
107 | }
108 | }
109 | ```
110 |
111 | ## Configuration
112 |
113 | A DrizzlePostgresModule `option` object has the following interface:
114 |
115 | ```typescript
116 | export interface DrizzlePostgresConfig {
117 | postgres: {
118 | url: string;
119 | config?: Options>> | undefined;
120 | };
121 | config?: DrizzleConfig | undefined;
122 | }
123 | ```
124 |
125 | - `postgres.url:` postgres url connection string
126 | - (optional) `postgres.config:` Postgres.js driver [options](https://github.com/porsager/postgres#connection-details)
127 | - (optional) `config:` DrizzleORM configuration
128 |
129 | ## Documentation
130 |
131 | - [NX](https://nx.dev/)
132 | - [DrizzleORM](https://orm.drizzle.team/)
133 | - [PostgresJS](https://github.com/porsager/postgres)
134 |
135 | ## License
136 |
137 | This package is [MIT licensed](https://github.com/knaadh/nestjs-drizzle/blob/main/LICENSE).
138 |
--------------------------------------------------------------------------------
/packages/postgres-js/jest.config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export default {
3 | displayName: '@knaadh/nestjs-drizzle-postgres',
4 | preset: '../../jest.preset.js',
5 | testEnvironment: 'node',
6 | transform: {
7 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
8 | },
9 | moduleFileExtensions: ['ts', 'js', 'html'],
10 | coverageDirectory: '../../coverage/packages/postgres-js',
11 | };
12 |
--------------------------------------------------------------------------------
/packages/postgres-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-postgres",
3 | "version": "1.2.0",
4 | "author": "Mithlesh Jasrotia ",
5 | "license": "MIT",
6 | "description": "A NestJS module for integrating Drizzle ORM with PostgresJS driver",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/knaadh/nestjs-drizzle.git",
10 | "directory": "packages/postgres-js"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/knaadh/nestjs-drizzle/issues"
14 | },
15 | "homepage": "https://github.com/knaadh/nestjs-drizzle",
16 | "keywords": [
17 | "drizzle",
18 | "postgres.js",
19 | "database",
20 | "orm",
21 | "nestjs"
22 | ],
23 | "publishConfig": {
24 | "access": "public"
25 | },
26 | "peerDependencies": {
27 | "@nestjs/common": ">=9.0.0",
28 | "drizzle-orm": ">=0.28.6",
29 | "postgres": ">=3"
30 | },
31 | "type": "commonjs",
32 | "main": "./src/index.js",
33 | "typings": "./src/index.d.ts"
34 | }
35 |
--------------------------------------------------------------------------------
/packages/postgres-js/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-postgres",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/postgres-js/src",
5 | "projectType": "library",
6 | "tags": [],
7 | "targets": {
8 | "build": {
9 | "executor": "@nx/js:tsc",
10 | "outputs": ["{options.outputPath}"],
11 | "options": {
12 | "outputPath": "dist/packages/postgres-js",
13 | "tsConfig": "packages/postgres-js/tsconfig.lib.json",
14 | "packageJson": "packages/postgres-js/package.json",
15 | "main": "packages/postgres-js/src/index.ts",
16 | "assets": ["packages/postgres-js/*.md"]
17 | }
18 | },
19 | "publish": {
20 | "command": "node tools/scripts/publish.mjs @knaadh/nestjs-drizzle-postgres {args.ver} {args.tag}",
21 | "dependsOn": ["build"]
22 | },
23 | "lint": {
24 | "executor": "@nx/eslint:lint"
25 | },
26 | "test": {
27 | "executor": "@nx/jest:jest",
28 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
29 | "options": {
30 | "jestConfig": "packages/postgres-js/jest.config.ts"
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/postgres-js/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './postgres-js.module';
2 | export * from './postgres-js.definition';
3 | export * from './postgres-js.decorator';
4 | export * from './postgres-js.interface';
5 |
--------------------------------------------------------------------------------
/packages/postgres-js/src/postgres-js.decorator.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 |
3 | export const InjectDrizzle = (configTag = 'default') => {
4 | return Inject(configTag);
5 | };
--------------------------------------------------------------------------------
/packages/postgres-js/src/postgres-js.definition.ts:
--------------------------------------------------------------------------------
1 | import { ConfigurableModuleBuilder } from '@nestjs/common';
2 | import { DrizzlePostgresConfig } from './postgres-js.interface';
3 |
4 | export const {
5 | ConfigurableModuleClass,
6 | MODULE_OPTIONS_TOKEN,
7 | OPTIONS_TYPE,
8 | ASYNC_OPTIONS_TYPE,
9 | } = new ConfigurableModuleBuilder()
10 | .setExtras(
11 | {
12 | tag: 'default',
13 | },
14 | (definition, extras) => ({
15 | ...definition,
16 | tag: extras.tag,
17 | })
18 | )
19 | .build();
20 |
--------------------------------------------------------------------------------
/packages/postgres-js/src/postgres-js.interface.ts:
--------------------------------------------------------------------------------
1 | import { DrizzleConfig } from 'drizzle-orm';
2 | import { Options, PostgresType } from 'postgres';
3 |
4 | export interface DrizzlePostgresConfig {
5 | postgres: {
6 | url: string;
7 | config?: Options>> | undefined;
8 | };
9 | config?: DrizzleConfig | undefined;
10 | }
11 |
--------------------------------------------------------------------------------
/packages/postgres-js/src/postgres-js.module.ts:
--------------------------------------------------------------------------------
1 | import { Global, DynamicModule } from '@nestjs/common';
2 | import {
3 | ASYNC_OPTIONS_TYPE,
4 | ConfigurableModuleClass,
5 | MODULE_OPTIONS_TOKEN,
6 | OPTIONS_TYPE,
7 | } from './postgres-js.definition';
8 | import { DrizzlePostgresService } from './postgres-js.service';
9 | import { DrizzlePostgresConfig } from './postgres-js.interface';
10 |
11 | @Global()
12 | export class DrizzlePostgresModule extends ConfigurableModuleClass {
13 | static register(options: typeof OPTIONS_TYPE): DynamicModule {
14 | const { providers = [], exports = [], ...props } = super.register(options);
15 | return {
16 | ...props,
17 | providers: [
18 | ...providers,
19 | DrizzlePostgresService,
20 | {
21 | provide: options?.tag || 'default',
22 | useFactory: async (drizzleService: DrizzlePostgresService) => {
23 | return await drizzleService.getDrizzle(options);
24 | },
25 | inject: [DrizzlePostgresService],
26 | },
27 | ],
28 | exports: [...exports, options?.tag || 'default'],
29 | };
30 | }
31 | static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule {
32 | const {
33 | providers = [],
34 | exports = [],
35 | ...props
36 | } = super.registerAsync(options);
37 | return {
38 | ...props,
39 | providers: [
40 | ...providers,
41 | DrizzlePostgresService,
42 | {
43 | provide: options?.tag || 'default',
44 | useFactory: async (
45 | drizzleService: DrizzlePostgresService,
46 | config: DrizzlePostgresConfig
47 | ) => {
48 | return await drizzleService.getDrizzle(config);
49 | },
50 | inject: [DrizzlePostgresService, MODULE_OPTIONS_TOKEN],
51 | },
52 | ],
53 | exports: [...exports, options?.tag || 'default'],
54 | };
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/packages/postgres-js/src/postgres-js.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { DrizzlePostgresService } from './postgres-js.service';
3 |
4 | describe('DrizzlePostgresService', () => {
5 | let service: DrizzlePostgresService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [DrizzlePostgresService],
10 | }).compile();
11 |
12 | service = module.get(DrizzlePostgresService);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/packages/postgres-js/src/postgres-js.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import postgres from 'postgres';
3 | import { DrizzlePostgresConfig } from './postgres-js.interface';
4 | import { drizzle } from 'drizzle-orm/postgres-js';
5 |
6 | @Injectable()
7 | export class DrizzlePostgresService {
8 | public getDrizzle(options: DrizzlePostgresConfig) {
9 | const client = postgres(options.postgres.url, options.postgres.config);
10 | return drizzle(client, options?.config);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/postgres-js/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "noImplicitOverride": true,
8 | "noPropertyAccessFromIndexSignature": true,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true,
11 | "esModuleInterop": true
12 | },
13 | "files": [],
14 | "include": [],
15 | "references": [
16 | {
17 | "path": "./tsconfig.lib.json"
18 | },
19 | {
20 | "path": "./tsconfig.spec.json"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/packages/postgres-js/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"],
7 | "target": "es2021",
8 | "strictNullChecks": true,
9 | "noImplicitAny": true,
10 | "strictBindCallApply": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noFallthroughCasesInSwitch": true
13 | },
14 | "include": ["src/**/*.ts"],
15 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/postgres-js/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/turso/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../.eslintrc.json"],
3 | "ignorePatterns": ["!**/*"],
4 | "overrides": [
5 | {
6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7 | "rules": {}
8 | },
9 | {
10 | "files": ["*.ts", "*.tsx"],
11 | "rules": {}
12 | },
13 | {
14 | "files": ["*.js", "*.jsx"],
15 | "rules": {}
16 | },
17 | {
18 | "files": ["*.json"],
19 | "parser": "jsonc-eslint-parser",
20 | "rules": {
21 | "@nx/dependency-checks": "error"
22 | }
23 | }
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/turso/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | A NestJS module for integrating Drizzle ORM with Turso
7 |
8 |
9 |
10 |
11 |
12 |
13 | ## Table of Contents
14 |
15 | - [Table of Contents](#table-of-contents)
16 | - [Installation](#installation)
17 | - [Usage](#usage)
18 | - [Configuration](#configuration)
19 | - [Documentation](#documentation)
20 | - [License](#license)
21 |
22 | ## Installation
23 |
24 | ```bash
25 | npm install @knaadh/nestjs-drizzle-turso drizzle-orm @libsql/client
26 | ```
27 |
28 | ## Usage
29 |
30 | Import the DrizzleTursoModule module and pass an `options` object to initialize it. You can pass `options` object using the usual methods for [custom providers](https://docs.nestjs.com/fundamentals/custom-providers) as shown below:
31 |
32 | ```typescript
33 | import { Module } from '@nestjs/common';
34 | import { AppController } from './app.controller';
35 | import { AppService } from './app.service';
36 | import * as schema from '../db/schema';
37 | import { DrizzleTursoModule } from '@knaadh/nestjs-drizzle-turso';
38 |
39 | @Module({
40 | imports: [
41 | // Method #1: Pass options object
42 | DrizzleTursoModule.register({
43 | tag: 'DB_DEV',
44 | turso: {
45 | config: {
46 | url: 'DATABASE_URL',
47 | authToken: 'DATABASE_AUTH_TOKEN',
48 | },
49 | },
50 | config: { schema: { ...schema } },
51 | }),
52 |
53 | // Method #2: useFactory()
54 | DrizzleTursoModule.registerAsync({
55 | tag: 'DB_PROD',
56 | useFactory() {
57 | return {
58 | turso: {
59 | config: {
60 | url: 'DATABASE_URL',
61 | authToken: 'DATABASE_AUTH_TOKEN',
62 | },
63 | },
64 | config: { schema: { ...schema } },
65 | };
66 | },
67 | }),
68 |
69 | // Method #3: useClass()
70 | DrizzleTursoModule.registerAsync({
71 | tag: 'DB_STAGING',
72 | useClass: DBConfigService,
73 | }),
74 | ],
75 | controllers: [AppController],
76 | providers: [AppService],
77 | })
78 | export class AppModule {}
79 | ```
80 |
81 | ```typescript
82 | export class DBConfigService {
83 | create = () => {
84 | return {
85 | turso: {
86 | config: {
87 | url: 'DATABASE_URL',
88 | authToken: 'DATABASE_AUTH_TOKEN',
89 | },
90 | },
91 | config: { schema: { ...schema } },
92 | };
93 | };
94 | }
95 | ```
96 |
97 | You can inject the Drizzle instances using their respective `tag` specified in the configurations
98 |
99 | ```typescript
100 | import { Inject, Injectable } from '@nestjs/common';
101 | import * as schema from '../db/schema';
102 | import { LibSQLDatabase } from 'drizzle-orm/libsql';
103 | @Injectable()
104 | export class AppService {
105 | constructor(
106 | @Inject('DB_DEV') private drizzleDev: LibSQLDatabase,
107 | @Inject('DB_PROD') private drizzleProd: LibSQLDatabase
108 | ) {}
109 | async getData() {
110 | const books = await this.drizzleDev.query.books.findMany();
111 | const authors = await this.drizzleProd.query.authors.findMany();
112 | return {
113 | books: books,
114 | authors: authors,
115 | };
116 | }
117 | }
118 | ```
119 |
120 | ## Configuration
121 |
122 | A DrizzleTursoModule `option` object has the following interface:
123 |
124 | ```typescript
125 | export interface DrizzleTursoConfig {
126 | turso: {
127 | config: Config;
128 | };
129 | config?: DrizzleConfig | undefined;
130 | }
131 | ```
132 |
133 | - `turso.config:` Turso [config](https://docs.turso.tech/libsql/client-access/javascript-typescript-sdk)
134 | - (optional) `config:` DrizzleORM configuration.
135 |
136 | ## Documentation
137 |
138 | - [NX](https://nx.dev/)
139 | - [DrizzleORM](https://orm.drizzle.team/)
140 | - [Turso](https://docs.turso.tech/)
141 |
142 | ## License
143 |
144 | This package is [MIT licensed](https://github.com/knaadh/nestjs-drizzle/blob/main/LICENSE).
145 |
--------------------------------------------------------------------------------
/packages/turso/jest.config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export default {
3 | displayName: '@knaadh/nestjs-drizzle-turso',
4 | preset: '../../jest.preset.js',
5 | testEnvironment: 'node',
6 | transform: {
7 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
8 | },
9 | moduleFileExtensions: ['ts', 'js', 'html'],
10 | coverageDirectory: '../../coverage/packages/turso',
11 | };
12 |
--------------------------------------------------------------------------------
/packages/turso/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-turso",
3 | "version": "1.2.0",
4 | "author": "Mithlesh Jasrotia ",
5 | "license": "MIT",
6 | "description": "A NestJS module for integrating Drizzle ORM with Turso",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/knaadh/nestjs-drizzle.git",
10 | "directory": "packages/turso"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/knaadh/nestjs-drizzle/issues"
14 | },
15 | "homepage": "https://github.com/knaadh/nestjs-drizzle",
16 | "keywords": [
17 | "drizzle",
18 | "turso",
19 | "database",
20 | "orm",
21 | "nestjs"
22 | ],
23 | "publishConfig": {
24 | "access": "public"
25 | },
26 | "peerDependencies": {
27 | "@nestjs/common": ">=9.0.0",
28 | "drizzle-orm": ">=0.28.6",
29 | "@libsql/client": "*"
30 | },
31 | "type": "commonjs",
32 | "main": "./src/index.js",
33 | "typings": "./src/index.d.ts"
34 | }
35 |
--------------------------------------------------------------------------------
/packages/turso/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@knaadh/nestjs-drizzle-turso",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/turso/src",
5 | "projectType": "library",
6 | "tags": [],
7 | "targets": {
8 | "build": {
9 | "executor": "@nx/js:tsc",
10 | "outputs": ["{options.outputPath}"],
11 | "options": {
12 | "outputPath": "dist/packages/turso",
13 | "tsConfig": "packages/turso/tsconfig.lib.json",
14 | "packageJson": "packages/turso/package.json",
15 | "main": "packages/turso/src/index.ts",
16 | "assets": ["packages/turso/*.md"]
17 | }
18 | },
19 | "publish": {
20 | "command": "node tools/scripts/publish.mjs @knaadh/nestjs-drizzle-turso {args.ver} {args.tag}",
21 | "dependsOn": ["build"]
22 | },
23 | "lint": {
24 | "executor": "@nx/eslint:lint"
25 | },
26 | "test": {
27 | "executor": "@nx/jest:jest",
28 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
29 | "options": {
30 | "jestConfig": "packages/turso/jest.config.ts"
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/turso/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './turso.module';
2 | export * from './turso.definition';
3 | export * from './turso.decorator';
4 | export * from './turso.interface'
5 |
--------------------------------------------------------------------------------
/packages/turso/src/turso.decorator.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 |
3 | export const InjectDrizzle = (configTag = 'default') => {
4 | return Inject(configTag);
5 | };
--------------------------------------------------------------------------------
/packages/turso/src/turso.definition.ts:
--------------------------------------------------------------------------------
1 | import { ConfigurableModuleBuilder } from '@nestjs/common';
2 | import { DrizzleTursoConfig } from './turso.interface';
3 |
4 | export const {
5 | ConfigurableModuleClass,
6 | MODULE_OPTIONS_TOKEN,
7 | OPTIONS_TYPE,
8 | ASYNC_OPTIONS_TYPE,
9 | } = new ConfigurableModuleBuilder()
10 | .setExtras(
11 | {
12 | tag: 'default',
13 | },
14 | (definition, extras) => ({
15 | ...definition,
16 | tag: extras.tag,
17 | })
18 | )
19 | .build();
20 |
--------------------------------------------------------------------------------
/packages/turso/src/turso.interface.ts:
--------------------------------------------------------------------------------
1 | import { Config } from '@libsql/client';
2 | import { DrizzleConfig } from 'drizzle-orm';
3 | export interface DrizzleTursoConfig {
4 | turso: {
5 | config: Config;
6 | };
7 | config?: DrizzleConfig | undefined;
8 | }
9 |
--------------------------------------------------------------------------------
/packages/turso/src/turso.module.ts:
--------------------------------------------------------------------------------
1 | import { Global, DynamicModule } from '@nestjs/common';
2 | import {
3 | ASYNC_OPTIONS_TYPE,
4 | ConfigurableModuleClass,
5 | MODULE_OPTIONS_TOKEN,
6 | OPTIONS_TYPE,
7 | } from './turso.definition';
8 | import { DrizzleTursoService } from './turso.service';
9 | import { DrizzleTursoConfig } from './turso.interface';
10 |
11 | @Global()
12 | export class DrizzleTursoModule extends ConfigurableModuleClass {
13 | static register(options: typeof OPTIONS_TYPE): DynamicModule {
14 | const { providers = [], exports = [], ...props } = super.register(options);
15 | return {
16 | ...props,
17 | providers: [
18 | ...providers,
19 | DrizzleTursoService,
20 | {
21 | provide: options?.tag || 'default',
22 | useFactory: async (drizzleService: DrizzleTursoService) => {
23 | return await drizzleService.getDrizzle(options);
24 | },
25 | inject: [DrizzleTursoService],
26 | },
27 | ],
28 | exports: [...exports, options?.tag || 'default'],
29 | };
30 | }
31 | static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule {
32 | const {
33 | providers = [],
34 | exports = [],
35 | ...props
36 | } = super.registerAsync(options);
37 | return {
38 | ...props,
39 | providers: [
40 | ...providers,
41 | DrizzleTursoService,
42 | {
43 | provide: options?.tag || 'default',
44 | useFactory: async (
45 | drizzleService: DrizzleTursoService,
46 | config: DrizzleTursoConfig
47 | ) => {
48 | return await drizzleService.getDrizzle(config);
49 | },
50 | inject: [DrizzleTursoService, MODULE_OPTIONS_TOKEN],
51 | },
52 | ],
53 | exports: [...exports, options?.tag || 'default'],
54 | };
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/packages/turso/src/turso.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { DrizzleTursoService } from './turso.service';
3 | describe('DrizzleTursoService', () => {
4 | let service: DrizzleTursoService;
5 |
6 | beforeEach(async () => {
7 | const module: TestingModule = await Test.createTestingModule({
8 | providers: [DrizzleTursoService],
9 | }).compile();
10 |
11 | service = module.get(DrizzleTursoService);
12 | });
13 |
14 | it('should be defined', () => {
15 | expect(service).toBeDefined();
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/packages/turso/src/turso.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { drizzle } from 'drizzle-orm/libsql';
3 | import { createClient } from '@libsql/client';
4 | import { DrizzleTursoConfig } from './turso.interface';
5 | @Injectable()
6 | export class DrizzleTursoService {
7 | public async getDrizzle(options: DrizzleTursoConfig) {
8 | const client = createClient(options.turso.config);
9 | return drizzle(client, options?.config);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/turso/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "noImplicitOverride": true,
8 | "noPropertyAccessFromIndexSignature": true,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true
11 | },
12 | "files": [],
13 | "include": [],
14 | "references": [
15 | {
16 | "path": "./tsconfig.lib.json"
17 | },
18 | {
19 | "path": "./tsconfig.spec.json"
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/packages/turso/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"],
7 | "target": "es2021",
8 | "strictNullChecks": true,
9 | "noImplicitAny": true,
10 | "strictBindCallApply": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noFallthroughCasesInSwitch": true
13 | },
14 | "include": ["src/**/*.ts"],
15 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/turso/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nestjs-drizzle/source",
3 | "$schema": "node_modules/nx/schemas/project-schema.json",
4 | "targets": {
5 | "local-registry": {
6 | "executor": "@nx/js:verdaccio",
7 | "options": {
8 | "port": 4873,
9 | "config": ".verdaccio/config.yml",
10 | "storage": "tmp/local-registry/storage"
11 | }
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tools/scripts/publish.mjs:
--------------------------------------------------------------------------------
1 | /**
2 | * This is a minimal script to publish your package to "npm".
3 | * This is meant to be used as-is or customize as you see fit.
4 | *
5 | * This script is executed on "dist/path/to/library" as "cwd" by default.
6 | *
7 | * You might need to authenticate with NPM before running this script.
8 | */
9 |
10 | import { execSync } from 'child_process';
11 | import { readFileSync, writeFileSync } from 'fs';
12 |
13 | import devkit from '@nx/devkit';
14 | const { readCachedProjectGraph } = devkit;
15 |
16 | function invariant(condition, message) {
17 | if (!condition) {
18 | console.error(message);
19 | process.exit(1);
20 | }
21 | }
22 |
23 | // Executing publish script: node path/to/publish.mjs {name} --version {version} --tag {tag}
24 | // Default "tag" to "next" so we won't publish the "latest" tag by accident.
25 | const [, , name, version = '1.0.0', tag = 'latest'] = process.argv;
26 |
27 | // A simple SemVer validation to validate the version
28 | const validVersion = /^\d+\.\d+\.\d+(-\w+\.\d+)?/;
29 | invariant(
30 | version && validVersion.test(version),
31 | `No version provided or version did not match Semantic Versioning, expected: #.#.#-tag.# or #.#.#, got ${version}.`
32 | );
33 |
34 | const graph = readCachedProjectGraph();
35 | const project = graph.nodes[name];
36 |
37 | invariant(
38 | project,
39 | `Could not find project "${name}" in the workspace. Is the project.json configured correctly?`
40 | );
41 |
42 | const outputPath = project.data?.targets?.build?.options?.outputPath;
43 | invariant(
44 | outputPath,
45 | `Could not find "build.options.outputPath" of project "${name}". Is project.json configured correctly?`
46 | );
47 |
48 | process.chdir(outputPath);
49 |
50 | // Updating the version in "package.json" before publishing
51 | try {
52 | const json = JSON.parse(readFileSync(`package.json`).toString());
53 | json.version = version;
54 | writeFileSync(`package.json`, JSON.stringify(json, null, 2));
55 | } catch (e) {
56 | console.error(`Error reading package.json file from library build output.`);
57 | }
58 |
59 | // Execute "npm publish" to publish
60 | execSync(`npm publish --access public --tag ${tag}`);
61 |
--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "rootDir": ".",
5 | "sourceMap": true,
6 | "declaration": false,
7 | "moduleResolution": "node",
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "importHelpers": false,
11 | "target": "es2015",
12 | "module": "esnext",
13 | "lib": ["es2020", "dom"],
14 | "skipLibCheck": true,
15 | "skipDefaultLibCheck": true,
16 | "baseUrl": ".",
17 | "paths": {
18 | "@knaadh/nestjs-drizzle-better-sqlite3": [
19 | "packages/better-sqlite3/src/index.ts"
20 | ],
21 | "@knaadh/nestjs-drizzle-mysql2": ["packages/mysql2/src/index.ts"],
22 | "@knaadh/nestjs-drizzle-pg": ["packages/node-postgres/src/index.ts"],
23 | "@knaadh/nestjs-drizzle-planetscale": [
24 | "packages/planetscale/src/index.ts"
25 | ],
26 | "@knaadh/nestjs-drizzle-postgres": ["packages/postgres-js/src/index.ts"],
27 | "@knaadh/nestjs-drizzle-turso": ["packages/turso/src/index.ts"]
28 | }
29 | },
30 | "exclude": ["node_modules", "tmp"]
31 | }
32 |
--------------------------------------------------------------------------------