├── .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 | Nest Logo 3 |

4 | 5 |

6 | A NestJS module for integrating Drizzle ORM 7 |

8 | 9 |

10 | Nrwl Nx 11 |

12 | 13 |

14 | CodeFactor Grade 15 | NPM 16 | Discord 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 | Nest Logo 3 |

4 | 5 |

6 | A NestJS module for integrating Drizzle ORM with Better-SQLite3 driver 7 |

8 | 9 |

10 | Nrwl Nx 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 | Nest Logo 3 |

4 | 5 |

6 | A NestJS module for integrating Drizzle ORM with MySQL2 driver 7 |

8 | 9 |

10 | Nrwl Nx 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 | Nest Logo 3 |

4 | 5 |

6 | A NestJS module for integrating Drizzle ORM with Node-Postgres driver 7 |

8 | 9 |

10 | Nrwl Nx 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 | Nest Logo 3 |

4 | 5 |

6 | A NestJS module for integrating Drizzle ORM with official PlanetScale driver 7 |

8 | 9 |

10 | Nrwl Nx 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 | Nest Logo 3 |

4 | 5 |

6 | A NestJS module for integrating Drizzle ORM with PostgresJS driver 7 |

8 | 9 |

10 | Nrwl Nx 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 | Nest Logo 3 |

4 | 5 |

6 | A NestJS module for integrating Drizzle ORM with Turso 7 |

8 | 9 |

10 | Nrwl Nx 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 | --------------------------------------------------------------------------------