feat: db initial setup

This commit is contained in:
Anthony Potdevin 2026-04-01 13:54:23 -06:00
parent e4b190e690
commit 11178793b9
No known key found for this signature in database
GPG key ID: 4403F1DFBE779457
9 changed files with 1535 additions and 15 deletions

16
.env
View file

@ -66,19 +66,11 @@
# SSO_NODE_TYPE='lnd' # 'lnd' or 'litd'
# -----------
# Litd Account Config (in YAML config file)
# Database Configs
# -----------
# For litd accounts, set type: litd in your YAML config.
#
# Example YAML account entry:
# - name: "My Litd Node"
# type: litd
# serverUrl: "localhost:10009"
# macaroonPath: "/path/to/lit.macaroon"
# certificatePath: "/path/to/tls.cert"
# # OR use litDir to auto-resolve macaroon/cert:
# # litDir: "/path/to/.lit"
# password: "mypassword"
# DB_TYPE='sqlite' # 'sqlite' or 'postgres' (omit to disable database)
# DB_SQLITE_PATH='/path/to/thunderhub.db' # Required when DB_TYPE is 'sqlite'
# DB_POSTGRES_URL='postgres://user:pass@localhost:5432/thunderhub' # Required when DB_TYPE is 'postgres'
# -----------
# SSL Config

21
drizzle.config.ts Normal file
View file

@ -0,0 +1,21 @@
import { defineConfig } from 'drizzle-kit';
const dbType = process.env.DB_TYPE || 'sqlite';
export default dbType === 'postgres'
? defineConfig({
schema: './src/server/modules/database/schema/*',
out: './drizzle',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DB_POSTGRES_URL!,
},
})
: defineConfig({
schema: './src/server/modules/database/schema/*',
out: './drizzle',
dialect: 'sqlite',
dbCredentials: {
url: process.env.DB_SQLITE_PATH!,
},
});

View file

@ -68,4 +68,5 @@ module.exports = defineConfig([{
"**/node_modules",
"**/dist",
"**/*.generated.tsx",
"drizzle.config.ts",
])]);

1431
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -84,6 +84,7 @@
"async": "^3.2.6",
"bcryptjs": "^3.0.3",
"bech32": "^2.0.0",
"better-sqlite3": "^12.8.0",
"big.js": "^7.0.1",
"bip32": "^4.0.0",
"bip39": "^3.1.0",
@ -95,6 +96,7 @@
"d3-time-format": "^4.1.0",
"dataloader": "^2.2.3",
"date-fns": "^4.1.0",
"drizzle-orm": "^0.45.2",
"echarts": "^6.0.0",
"echarts-for-react": "^3.0.6",
"ecpair": "^3.0.1",
@ -110,6 +112,7 @@
"otplib": "^13.4.0",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"postgres": "^3.4.8",
"qrcode.react": "^4.2.0",
"radix-ui": "^1.4.3",
"react": "^18.2.0",
@ -144,6 +147,7 @@
"@nestjs/cli": "^11.0.16",
"@nestjs/schematics": "^11.0.9",
"@types/async": "^3.2.25",
"@types/better-sqlite3": "^7.6.13",
"@types/big.js": "^6.2.2",
"@types/d3-time-format": "^4.0.3",
"@types/jest": "^30.0.0",
@ -159,6 +163,7 @@
"@vitejs/plugin-react": "^5.1.4",
"concurrently": "^9.2.1",
"cross-env": "^10.1.0",
"drizzle-kit": "^0.31.10",
"eslint": "^10.0.3",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.5",

View file

@ -26,6 +26,7 @@ import {
DataloaderTypes,
} from './modules/dataloader/dataloader.service';
import { DataloaderModule } from './modules/dataloader/dataloader.module';
import { DatabaseModule } from './modules/database/database.module';
const { combine, timestamp, prettyPrint, json } = format;
@ -57,6 +58,7 @@ export type JwtObjectType = {
FilesModule,
AccountsModule,
FetchModule,
DatabaseModule,
ScheduleModule.forRoot(),
ConfigModule.forRoot({
isGlobal: true,

View file

@ -70,6 +70,18 @@ export type ClientConfig = {
npmVersion: string;
};
type SqliteConfig = {
type: 'sqlite';
path?: string;
};
type PostgresConfig = {
type: 'postgres';
url?: string;
};
type DatabaseConfig = SqliteConfig | PostgresConfig | undefined;
type ConfigType = {
basePath: string;
isProduction: boolean;
@ -91,6 +103,7 @@ type ConfigType = {
subscriptions: SubscriptionsConfig;
amboss: AmbossConfig;
clientConfig: ClientConfig;
database?: DatabaseConfig;
};
const VALID_NODE_TYPES = ['lnd', 'litd'];
@ -224,6 +237,17 @@ export default (): ConfigType => {
subscriptions,
amboss,
clientConfig,
database: process.env.DB_TYPE
? process.env.DB_TYPE === 'postgres'
? {
type: 'postgres' as const,
url: process.env.DB_POSTGRES_URL,
}
: {
type: 'sqlite' as const,
path: process.env.DB_SQLITE_PATH,
}
: undefined,
};
if (!isProduction) {

View file

@ -0,0 +1,9 @@
import { Global, Module } from '@nestjs/common';
import { DrizzleProvider, DRIZZLE } from './drizzle.provider';
@Global()
@Module({
providers: [DrizzleProvider],
exports: [DRIZZLE],
})
export class DatabaseModule {}

View file

@ -0,0 +1,41 @@
import { FactoryProvider } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { drizzle as drizzleSqlite } from 'drizzle-orm/better-sqlite3';
import { drizzle as drizzlePg } from 'drizzle-orm/postgres-js';
import Database from 'better-sqlite3';
import postgres from 'postgres';
export const DRIZZLE = Symbol('DRIZZLE');
export type DrizzleDB =
| ReturnType<typeof drizzleSqlite>
| ReturnType<typeof drizzlePg>
| null;
export const DrizzleProvider: FactoryProvider = {
provide: DRIZZLE,
inject: [ConfigService],
useFactory: (config: ConfigService): DrizzleDB => {
const dbType = config.get<string>('database.type');
if (!dbType) return null;
if (dbType === 'postgres') {
const url = config.get<string>('database.url');
if (!url) {
throw new Error('DB_POSTGRES_URL is required when DB_TYPE is postgres');
}
return drizzlePg(postgres(url));
}
if (dbType === 'sqlite') {
const path = config.get<string>('database.path');
if (!path) {
throw new Error('DB_SQLITE_PATH is required when DB_TYPE is sqlite');
}
return drizzleSqlite(new Database(path));
}
throw new Error(`Unsupported DB_TYPE: ${dbType}`);
},
};