mirror of
https://github.com/docmost/docmost.git
synced 2026-05-07 06:23:06 +08:00
refactor(db): migrate from node-postgres to postgres.js (#1846)
* refactor(db): migrate from node-postgres to postgres.js * ignore schema param
This commit is contained in:
@@ -74,6 +74,7 @@
|
||||
"jsonwebtoken": "^9.0.3",
|
||||
"kysely": "^0.28.2",
|
||||
"kysely-migration-cli": "^0.4.2",
|
||||
"kysely-postgres-js": "^3.0.0",
|
||||
"ldapts": "^7.4.0",
|
||||
"mammoth": "^1.11.0",
|
||||
"mime-types": "^2.1.35",
|
||||
@@ -87,9 +88,9 @@
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"pdfjs-dist": "^5.4.394",
|
||||
"pg": "^8.16.3",
|
||||
"pg-tsquery": "^8.4.2",
|
||||
"pgvector": "^0.2.1",
|
||||
"postgres": "^3.4.8",
|
||||
"pino-http": "^11.0.0",
|
||||
"pino-pretty": "^13.1.3",
|
||||
"postmark": "^4.0.5",
|
||||
@@ -119,7 +120,6 @@
|
||||
"@types/nodemailer": "^6.4.17",
|
||||
"@types/passport-google-oauth20": "^2.0.16",
|
||||
"@types/passport-jwt": "^4.0.1",
|
||||
"@types/pg": "^8.11.11",
|
||||
"@types/supertest": "^6.0.2",
|
||||
"@types/ws": "^8.5.14",
|
||||
"@types/yauzl": "^2.10.3",
|
||||
|
||||
@@ -98,3 +98,23 @@ export function hasLicenseOrEE(opts: {
|
||||
const { licenseKey, plan, isCloud } = opts;
|
||||
return Boolean(licenseKey) || (isCloud && plan === 'business');
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a database URL for postgres.js compatibility.
|
||||
* - Removes `sslmode=no-verify` (not supported by postgres.js), keeps other sslmode values
|
||||
* - Removes `schema` parameter (has no effect via connection string)
|
||||
* Note: If we don't strip them, the connection will fail
|
||||
*/
|
||||
export function normalizePostgresUrl(url: string): string {
|
||||
const parsed = new URL(url);
|
||||
const newParams = new URLSearchParams();
|
||||
|
||||
for (const [key, value] of parsed.searchParams) {
|
||||
if (key === 'sslmode' && value === 'no-verify') continue;
|
||||
if (key === 'schema') continue;
|
||||
newParams.append(key, value);
|
||||
}
|
||||
|
||||
parsed.search = newParams.toString();
|
||||
return parsed.toString();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { InjectKysely, KyselyModule } from 'nestjs-kysely';
|
||||
import { EnvironmentService } from '../integrations/environment/environment.service';
|
||||
import { CamelCasePlugin, LogEvent, PostgresDialect, sql } from 'kysely';
|
||||
import { Pool, types } from 'pg';
|
||||
import { CamelCasePlugin, LogEvent, sql } from 'kysely';
|
||||
import { GroupRepo } from '@docmost/db/repos/group/group.repo';
|
||||
import { WorkspaceRepo } from '@docmost/db/repos/workspace/workspace.repo';
|
||||
import { UserRepo } from '@docmost/db/repos/user/user.repo';
|
||||
@@ -26,9 +25,9 @@ import { UserTokenRepo } from './repos/user-token/user-token.repo';
|
||||
import { BacklinkRepo } from '@docmost/db/repos/backlink/backlink.repo';
|
||||
import { ShareRepo } from '@docmost/db/repos/share/share.repo';
|
||||
import { PageListener } from '@docmost/db/listeners/page.listener';
|
||||
|
||||
// https://github.com/brianc/node-postgres/issues/811
|
||||
types.setTypeParser(types.builtins.INT8, (val) => Number(val));
|
||||
import { PostgresJSDialect } from 'kysely-postgres-js';
|
||||
import * as postgres from 'postgres';
|
||||
import { normalizePostgresUrl } from '../common/helpers';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
@@ -37,26 +36,30 @@ types.setTypeParser(types.builtins.INT8, (val) => Number(val));
|
||||
imports: [],
|
||||
inject: [EnvironmentService],
|
||||
useFactory: (environmentService: EnvironmentService) => ({
|
||||
dialect: new PostgresDialect({
|
||||
pool: new Pool({
|
||||
connectionString: environmentService.getDatabaseURL(),
|
||||
dialect: new PostgresJSDialect({
|
||||
postgres: postgres(
|
||||
normalizePostgresUrl(environmentService.getDatabaseURL()),
|
||||
{
|
||||
max: environmentService.getDatabaseMaxPool(),
|
||||
}).on('error', (err) => {
|
||||
console.error('Database error:', err.message);
|
||||
}),
|
||||
onnotice: () => {},
|
||||
types: {
|
||||
bigint: {
|
||||
to: 20,
|
||||
from: [20, 1700],
|
||||
serialize: (value: number) => value.toString(),
|
||||
parse: (value: string) => Number.parseInt(value),
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
}),
|
||||
plugins: [new CamelCasePlugin()],
|
||||
log: (event: LogEvent) => {
|
||||
if (environmentService.getNodeEnv() !== 'development') return;
|
||||
const logger = new Logger(DatabaseModule.name);
|
||||
if (event.level) {
|
||||
if (process.env.DEBUG_DB?.toLowerCase() === 'true') {
|
||||
logger.debug(event.query.sql);
|
||||
logger.debug('query time: ' + event.queryDurationMillis + ' ms');
|
||||
//if (event.query.parameters.length > 0) {
|
||||
// logger.debug('parameters: ' + event.query.parameters);
|
||||
//}
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
import * as path from 'path';
|
||||
import { promises as fs } from 'fs';
|
||||
import pg from 'pg';
|
||||
import {
|
||||
Kysely,
|
||||
Migrator,
|
||||
PostgresDialect,
|
||||
FileMigrationProvider,
|
||||
} from 'kysely';
|
||||
import { Kysely, Migrator, FileMigrationProvider } from 'kysely';
|
||||
import { run } from 'kysely-migration-cli';
|
||||
import * as dotenv from 'dotenv';
|
||||
import { envPath } from '../common/helpers/utils';
|
||||
import { envPath, normalizePostgresUrl } from '../common/helpers';
|
||||
import { PostgresJSDialect } from 'kysely-postgres-js';
|
||||
import postgres from 'postgres';
|
||||
|
||||
dotenv.config({ path: envPath });
|
||||
|
||||
const migrationFolder = path.join(__dirname, './migrations');
|
||||
|
||||
const db = new Kysely<any>({
|
||||
dialect: new PostgresDialect({
|
||||
pool: new pg.Pool({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
}) as any,
|
||||
dialect: new PostgresJSDialect({
|
||||
postgres: postgres(normalizePostgresUrl(process.env.DATABASE_URL)),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
Generated
+44
-80
@@ -566,6 +566,9 @@ importers:
|
||||
kysely-migration-cli:
|
||||
specifier: ^0.4.2
|
||||
version: 0.4.2
|
||||
kysely-postgres-js:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0(kysely@0.28.2)(postgres@3.4.8)
|
||||
ldapts:
|
||||
specifier: ^7.4.0
|
||||
version: 7.4.0
|
||||
@@ -605,15 +608,15 @@ importers:
|
||||
pdfjs-dist:
|
||||
specifier: ^5.4.394
|
||||
version: 5.4.394
|
||||
pg:
|
||||
specifier: ^8.16.3
|
||||
version: 8.16.3
|
||||
pg-tsquery:
|
||||
specifier: ^8.4.2
|
||||
version: 8.4.2
|
||||
pgvector:
|
||||
specifier: ^0.2.1
|
||||
version: 0.2.1
|
||||
postgres:
|
||||
specifier: ^3.4.8
|
||||
version: 3.4.8
|
||||
pino-http:
|
||||
specifier: ^11.0.0
|
||||
version: 11.0.0
|
||||
@@ -696,9 +699,6 @@ importers:
|
||||
'@types/passport-jwt':
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
'@types/pg':
|
||||
specifier: ^8.11.11
|
||||
version: 8.11.11
|
||||
'@types/supertest':
|
||||
specifier: ^6.0.2
|
||||
version: 6.0.2
|
||||
@@ -4801,9 +4801,6 @@ packages:
|
||||
'@types/passport@1.0.17':
|
||||
resolution: {integrity: sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==}
|
||||
|
||||
'@types/pg@8.11.11':
|
||||
resolution: {integrity: sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==}
|
||||
|
||||
'@types/prop-types@15.7.11':
|
||||
resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==}
|
||||
|
||||
@@ -7560,6 +7557,16 @@ packages:
|
||||
resolution: {integrity: sha512-904MSUdzkdxl+k3C67ogvP6ogPOEr0D6ZZDtxAmDeIHEJxZAA+eC+TLAcJt3HQABTPetwsW3pj6y1MPmaveQUg==}
|
||||
hasBin: true
|
||||
|
||||
kysely-postgres-js@3.0.0:
|
||||
resolution: {integrity: sha512-o2t/xNSYJQDW6rVGGFPXKmZ0BEz2dGn66c2B+cO/k9ZNcU2qPWPycQPQ+B+P2MBXbKYq0xV9BZmFIvkUrmFWAQ==}
|
||||
engines: {bun: '>=1.2', node: '>=20'}
|
||||
peerDependencies:
|
||||
kysely: '>= 0.24.0 < 1'
|
||||
postgres: ^3.4.0
|
||||
peerDependenciesMeta:
|
||||
postgres:
|
||||
optional: true
|
||||
|
||||
kysely@0.28.2:
|
||||
resolution: {integrity: sha512-4YAVLoF0Sf0UTqlhgQMFU9iQECdah7n+13ANkiuVfRvlK+uI0Etbgd7bVP36dKlG+NXWbhGua8vnGt+sdhvT7A==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
@@ -8206,9 +8213,6 @@ packages:
|
||||
resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
obuf@1.1.2:
|
||||
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
|
||||
|
||||
oidc-token-hash@5.0.3:
|
||||
resolution: {integrity: sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==}
|
||||
engines: {node: ^10.13.0 || >=12.0.0}
|
||||
@@ -8437,10 +8441,6 @@ packages:
|
||||
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
|
||||
pg-numeric@1.0.2:
|
||||
resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
pg-pool@3.10.1:
|
||||
resolution: {integrity: sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==}
|
||||
peerDependencies:
|
||||
@@ -8449,9 +8449,6 @@ packages:
|
||||
pg-protocol@1.10.3:
|
||||
resolution: {integrity: sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==}
|
||||
|
||||
pg-protocol@1.7.0:
|
||||
resolution: {integrity: sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==}
|
||||
|
||||
pg-tsquery@8.4.2:
|
||||
resolution: {integrity: sha512-waJSlBIKE+shDhuDpuQglTH6dG5zakDhnrnxu8XB8V5c7yoDSuy4pOxY6t2dyoxTjaKMcMmlByJN7n9jx9eqMA==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -8460,10 +8457,6 @@ packages:
|
||||
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
pg-types@4.0.2:
|
||||
resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
pg@8.16.3:
|
||||
resolution: {integrity: sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==}
|
||||
engines: {node: '>= 16.0.0'}
|
||||
@@ -8621,37 +8614,22 @@ packages:
|
||||
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
postgres-array@3.0.2:
|
||||
resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
postgres-bytea@1.0.0:
|
||||
resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
postgres-bytea@3.0.0:
|
||||
resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
postgres-date@1.0.7:
|
||||
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
postgres-date@2.1.0:
|
||||
resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
postgres-interval@1.2.0:
|
||||
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
postgres-interval@3.0.0:
|
||||
resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==}
|
||||
postgres@3.4.8:
|
||||
resolution: {integrity: sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
postgres-range@1.1.4:
|
||||
resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==}
|
||||
|
||||
posthog-js@1.255.1:
|
||||
resolution: {integrity: sha512-KMh0o9MhORhEZVjXpktXB5rJ8PfDk+poqBoTSoLzWgNjhJf6D8jcyB9jUMA6vVPfn4YeepVX5NuclDRqOwr5Mw==}
|
||||
peerDependencies:
|
||||
@@ -15299,12 +15277,6 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/express': 4.17.23
|
||||
|
||||
'@types/pg@8.11.11':
|
||||
dependencies:
|
||||
'@types/node': 22.19.1
|
||||
pg-protocol: 1.7.0
|
||||
pg-types: 4.0.2
|
||||
|
||||
'@types/prop-types@15.7.11': {}
|
||||
|
||||
'@types/qrcode@1.5.5':
|
||||
@@ -18705,6 +18677,12 @@ snapshots:
|
||||
'@commander-js/extra-typings': 11.1.0(commander@11.1.0)
|
||||
commander: 11.1.0
|
||||
|
||||
kysely-postgres-js@3.0.0(kysely@0.28.2)(postgres@3.4.8):
|
||||
dependencies:
|
||||
kysely: 0.28.2
|
||||
optionalDependencies:
|
||||
postgres: 3.4.8
|
||||
|
||||
kysely@0.28.2: {}
|
||||
|
||||
langium@3.3.1:
|
||||
@@ -19466,8 +19444,6 @@ snapshots:
|
||||
define-properties: 1.2.1
|
||||
es-object-atoms: 1.0.0
|
||||
|
||||
obuf@1.1.2: {}
|
||||
|
||||
oidc-token-hash@5.0.3: {}
|
||||
|
||||
ollama@0.6.3:
|
||||
@@ -19694,19 +19670,19 @@ snapshots:
|
||||
pg-cloudflare@1.2.7:
|
||||
optional: true
|
||||
|
||||
pg-connection-string@2.9.1: {}
|
||||
pg-connection-string@2.9.1:
|
||||
optional: true
|
||||
|
||||
pg-int8@1.0.1: {}
|
||||
|
||||
pg-numeric@1.0.2: {}
|
||||
pg-int8@1.0.1:
|
||||
optional: true
|
||||
|
||||
pg-pool@3.10.1(pg@8.16.3):
|
||||
dependencies:
|
||||
pg: 8.16.3
|
||||
optional: true
|
||||
|
||||
pg-protocol@1.10.3: {}
|
||||
|
||||
pg-protocol@1.7.0: {}
|
||||
pg-protocol@1.10.3:
|
||||
optional: true
|
||||
|
||||
pg-tsquery@8.4.2: {}
|
||||
|
||||
@@ -19717,16 +19693,7 @@ snapshots:
|
||||
postgres-bytea: 1.0.0
|
||||
postgres-date: 1.0.7
|
||||
postgres-interval: 1.2.0
|
||||
|
||||
pg-types@4.0.2:
|
||||
dependencies:
|
||||
pg-int8: 1.0.1
|
||||
pg-numeric: 1.0.2
|
||||
postgres-array: 3.0.2
|
||||
postgres-bytea: 3.0.0
|
||||
postgres-date: 2.1.0
|
||||
postgres-interval: 3.0.0
|
||||
postgres-range: 1.1.4
|
||||
optional: true
|
||||
|
||||
pg@8.16.3:
|
||||
dependencies:
|
||||
@@ -19737,10 +19704,12 @@ snapshots:
|
||||
pgpass: 1.0.5
|
||||
optionalDependencies:
|
||||
pg-cloudflare: 1.2.7
|
||||
optional: true
|
||||
|
||||
pgpass@1.0.5:
|
||||
dependencies:
|
||||
split2: 4.2.0
|
||||
optional: true
|
||||
|
||||
pgvector@0.2.1: {}
|
||||
|
||||
@@ -19909,27 +19878,21 @@ snapshots:
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
postgres-array@2.0.0: {}
|
||||
postgres-array@2.0.0:
|
||||
optional: true
|
||||
|
||||
postgres-array@3.0.2: {}
|
||||
postgres-bytea@1.0.0:
|
||||
optional: true
|
||||
|
||||
postgres-bytea@1.0.0: {}
|
||||
|
||||
postgres-bytea@3.0.0:
|
||||
dependencies:
|
||||
obuf: 1.1.2
|
||||
|
||||
postgres-date@1.0.7: {}
|
||||
|
||||
postgres-date@2.1.0: {}
|
||||
postgres-date@1.0.7:
|
||||
optional: true
|
||||
|
||||
postgres-interval@1.2.0:
|
||||
dependencies:
|
||||
xtend: 4.0.2
|
||||
optional: true
|
||||
|
||||
postgres-interval@3.0.0: {}
|
||||
|
||||
postgres-range@1.1.4: {}
|
||||
postgres@3.4.8: {}
|
||||
|
||||
posthog-js@1.255.1:
|
||||
dependencies:
|
||||
@@ -21622,7 +21585,8 @@ snapshots:
|
||||
|
||||
xpath@0.0.34: {}
|
||||
|
||||
xtend@4.0.2: {}
|
||||
xtend@4.0.2:
|
||||
optional: true
|
||||
|
||||
y-indexeddb@9.0.12(yjs@13.6.27):
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user