From b0fbd4a02789546475209a052e04033f8d5b8216 Mon Sep 17 00:00:00 2001 From: forehalo Date: Fri, 8 Nov 2024 19:55:19 +0800 Subject: [PATCH] feat(server): improve selfhost deployment --- packages/backend/server/.dockerignore | 2 ++ .../server/scripts/self-host-predeploy.js | 17 +++++++++++- .../backend/server/src/config/affine.env.ts | 7 ++++- .../server/src/core/config/resolver.ts | 4 +-- .../backend/server/src/fundamentals/index.ts | 2 +- .../server/src/fundamentals/prisma/config.ts | 27 +++++++++++++++---- .../server/src/fundamentals/prisma/index.ts | 15 ++++++++++- packages/backend/server/src/prelude.ts | 2 +- 8 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 packages/backend/server/.dockerignore diff --git a/packages/backend/server/.dockerignore b/packages/backend/server/.dockerignore new file mode 100644 index 0000000000000..83e7e38aa1185 --- /dev/null +++ b/packages/backend/server/.dockerignore @@ -0,0 +1,2 @@ +# required DATABASE_URL affects app start +schema.prisma \ No newline at end of file diff --git a/packages/backend/server/scripts/self-host-predeploy.js b/packages/backend/server/scripts/self-host-predeploy.js index b5e5d1ff8069d..8588f9a16af09 100644 --- a/packages/backend/server/scripts/self-host-predeploy.js +++ b/packages/backend/server/scripts/self-host-predeploy.js @@ -10,7 +10,6 @@ const SELF_HOST_CONFIG_DIR = '/root/.affine/config'; * @type {Array<{ from: string; to?: string, modifier?: (content: string): string }>} */ const configFiles = [ - { from: './.env.example', to: '.env' }, { from: './dist/config/affine.js', modifier: configCleaner }, { from: './dist/config/affine.env.js', modifier: configCleaner }, ]; @@ -22,8 +21,24 @@ function configCleaner(content) { ); } +const datasource = { + user: process.env.DB_USER || 'affine', + password: process.env.DB_PASSWORD || '', + host: process.env.DB_HOST || 'postgres', + port: process.env.DB_PORT || 5432, + databaseName: process.env.DB_DATABASE_NAME || 'affine', +}; + +function getDatasourceUrl() { + return ( + process.env.DATABASE_URL || + `postgres://${datasource.user}:${datasource.password}@${datasource.host}:${datasource.port}/${datasource.databaseName}` + ); +} + function prepare() { fs.mkdirSync(SELF_HOST_CONFIG_DIR, { recursive: true }); + process.env.DATABASE_URL = getDatasourceUrl(); for (const { from, to, modifier } of configFiles) { const targetFileName = to ?? path.parse(from).base; diff --git a/packages/backend/server/src/config/affine.env.ts b/packages/backend/server/src/config/affine.env.ts index 8fc277c123bf3..5dc9abab12c58 100644 --- a/packages/backend/server/src/config/affine.env.ts +++ b/packages/backend/server/src/config/affine.env.ts @@ -12,7 +12,12 @@ AFFiNE.ENV_MAP = { MAILER_PASSWORD: 'mailer.auth.pass', MAILER_SENDER: 'mailer.from.address', MAILER_SECURE: ['mailer.secure', 'boolean'], - DATABASE_URL: 'database.datasourceUrl', + DATABASE_URL: 'prisma.database.datasourceUrl', + DB_PASSWORD: 'prisma.database.password', + DB_USER: 'prisma.database.user', + DB_HOST: 'prisma.database.host', + DB_PORT: ['prisma.database.port', 'int'], + DB_DATABASE_NAME: 'prisma.database.databaseName', OAUTH_GOOGLE_CLIENT_ID: 'plugins.oauth.providers.google.clientId', OAUTH_GOOGLE_CLIENT_SECRET: 'plugins.oauth.providers.google.clientSecret', OAUTH_GITHUB_CLIENT_ID: 'plugins.oauth.providers.github.clientId', diff --git a/packages/backend/server/src/core/config/resolver.ts b/packages/backend/server/src/core/config/resolver.ts index d3e34629d3186..e0a1de45a925c 100644 --- a/packages/backend/server/src/core/config/resolver.ts +++ b/packages/backend/server/src/core/config/resolver.ts @@ -12,7 +12,7 @@ import { import { RuntimeConfig, RuntimeConfigType } from '@prisma/client'; import { GraphQLJSON, GraphQLJSONObject } from 'graphql-scalars'; -import { Config, URLHelper } from '../../fundamentals'; +import { Config, getDatasourceUrl, URLHelper } from '../../fundamentals'; import { Public } from '../auth'; import { Admin } from '../common'; import { FeatureType } from '../features'; @@ -261,7 +261,7 @@ export class ServerServiceConfigResolver { } database(): ServerDatabaseConfig { - const url = new URL(this.config.database.datasourceUrl); + const url = new URL(getDatasourceUrl(this.config)); return { host: url.hostname, diff --git a/packages/backend/server/src/fundamentals/index.ts b/packages/backend/server/src/fundamentals/index.ts index 75b31ba355cd5..41c10ff79e3e2 100644 --- a/packages/backend/server/src/fundamentals/index.ts +++ b/packages/backend/server/src/fundamentals/index.ts @@ -29,7 +29,7 @@ export { mapSseError, OptionalModule, } from './nestjs'; -export type { PrismaTransaction } from './prisma'; +export { getDatasourceUrl, type PrismaTransaction } from './prisma'; export * from './storage'; export { type StorageProvider, StorageProviderFactory } from './storage'; export { CloudThrottlerGuard, SkipThrottle, Throttle } from './throttler'; diff --git a/packages/backend/server/src/fundamentals/prisma/config.ts b/packages/backend/server/src/fundamentals/prisma/config.ts index 17106e5ab4a68..75515bbc9c6ce 100644 --- a/packages/backend/server/src/fundamentals/prisma/config.ts +++ b/packages/backend/server/src/fundamentals/prisma/config.ts @@ -2,16 +2,33 @@ import type { Prisma } from '@prisma/client'; import { defineStartupConfig, ModuleConfig } from '../config'; -interface PrismaStartupConfiguration extends Prisma.PrismaClientOptions { - datasourceUrl: string; +interface PrismaStartupConfiguration { + options?: Prisma.PrismaClientOptions; + database: + | { + host: string; + port: number; + user: string; + password: string; + databaseName: string; + } + | { + datasourceUrl: string; + }; } declare module '../config' { interface AppConfig { - database: ModuleConfig; + prisma: ModuleConfig; } } -defineStartupConfig('database', { - datasourceUrl: '', +defineStartupConfig('prisma', { + database: { + host: 'localhost', + port: 5432, + user: 'affine', + password: '', + databaseName: 'affine', + }, }); diff --git a/packages/backend/server/src/fundamentals/prisma/index.ts b/packages/backend/server/src/fundamentals/prisma/index.ts index cbaf0b98e8cb3..1c7500f22f8af 100644 --- a/packages/backend/server/src/fundamentals/prisma/index.ts +++ b/packages/backend/server/src/fundamentals/prisma/index.ts @@ -6,6 +6,15 @@ import { PrismaClient } from '@prisma/client'; import { Config } from '../config'; import { PrismaService } from './service'; +export function getDatasourceUrl(config: Config) { + const database = config.prisma.database; + if ('datasourceUrl' in database) { + return database.datasourceUrl; + } + console.log(database.user); + return `postgres://${database.user}:${database.password}@${database.host}:${database.port}/${database.databaseName}`; +} + // only `PrismaClient` can be injected const clientProvider: Provider = { provide: PrismaClient, @@ -13,8 +22,12 @@ const clientProvider: Provider = { if (PrismaService.INSTANCE) { return PrismaService.INSTANCE; } + console.log(getDatasourceUrl(config)); - return new PrismaService(config.database); + return new PrismaService({ + ...config.prisma.options, + datasourceUrl: getDatasourceUrl(config), + }); }, inject: [Config], }; diff --git a/packages/backend/server/src/prelude.ts b/packages/backend/server/src/prelude.ts index 49191969e89aa..cd8cbd74cc8cd 100644 --- a/packages/backend/server/src/prelude.ts +++ b/packages/backend/server/src/prelude.ts @@ -10,7 +10,6 @@ import { applyEnvToConfig, getAFFiNEConfigModifier, } from './fundamentals/config'; -import { enablePlugin } from './plugins'; const PROJECT_CONFIG_PATH = join(fileURLToPath(import.meta.url), '../config'); async function loadRemote(remoteDir: string, file: string) { @@ -46,6 +45,7 @@ async function load() { // 2. generate AFFiNE default config and assign to `globalThis.AFFiNE` globalThis.AFFiNE = getAFFiNEConfigModifier(); + const { enablePlugin } = await import('./plugins/registry'); globalThis.AFFiNE.use = enablePlugin; globalThis.AFFiNE.plugins.use = enablePlugin;