feat(server): runtime service config (#7644)

This commit is contained in:
liuyi 2024-07-30 14:58:24 +08:00 committed by GitHub
parent 67248316bd
commit fcf0ecbaa2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 136 additions and 10 deletions

View File

@ -12,6 +12,7 @@ AFFiNE.ENV_MAP = {
MAILER_PASSWORD: 'mailer.auth.pass',
MAILER_SENDER: 'mailer.from.address',
MAILER_SECURE: ['mailer.secure', 'boolean'],
DATABASE_URL: 'database.datasourceUrl',
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',

View File

@ -2,10 +2,18 @@ import './config';
import { Module } from '@nestjs/common';
import { ServerConfigResolver, ServerRuntimeConfigResolver } from './resolver';
import {
ServerConfigResolver,
ServerRuntimeConfigResolver,
ServerServiceConfigResolver,
} from './resolver';
@Module({
providers: [ServerConfigResolver, ServerRuntimeConfigResolver],
providers: [
ServerConfigResolver,
ServerRuntimeConfigResolver,
ServerServiceConfigResolver,
],
})
export class ServerConfigModule {}
export { ADD_ENABLED_FEATURES, ServerConfigType } from './resolver';

View File

@ -175,11 +175,42 @@ export class ServerConfigResolver {
}
}
@ObjectType()
class ServerServiceConfig {
@Field()
name!: string;
@Field(() => GraphQLJSONObject)
config!: any;
}
interface ServerServeConfig {
https: boolean;
host: string;
port: number;
externalUrl: string;
}
interface ServerMailerConfig {
host?: string | null;
port?: number | null;
secure?: boolean | null;
service?: string | null;
sender?: string | null;
}
interface ServerDatabaseConfig {
host: string;
port: number;
user?: string | null;
database: string;
}
@Admin()
@Resolver(() => ServerRuntimeConfigType)
export class ServerRuntimeConfigResolver {
constructor(private readonly config: Config) {}
@Admin()
@Query(() => [ServerRuntimeConfigType], {
description: 'get all server runtime configurable settings',
})
@ -187,7 +218,6 @@ export class ServerRuntimeConfigResolver {
return this.config.runtime.list();
}
@Admin()
@Mutation(() => ServerRuntimeConfigType, {
description: 'update server runtime configurable setting',
})
@ -198,7 +228,6 @@ export class ServerRuntimeConfigResolver {
return await this.config.runtime.set(id as any, value);
}
@Admin()
@Mutation(() => [ServerRuntimeConfigType], {
description: 'update multiple server runtime configurable settings',
})
@ -213,3 +242,57 @@ export class ServerRuntimeConfigResolver {
return results;
}
}
@Admin()
@Resolver(() => ServerServiceConfig)
export class ServerServiceConfigResolver {
constructor(private readonly config: Config) {}
@Query(() => [ServerServiceConfig])
serverServiceConfigs() {
return [
{
name: 'server',
config: this.serve(),
},
{
name: 'mailer',
config: this.mail(),
},
{
name: 'database',
config: this.database(),
},
];
}
serve(): ServerServeConfig {
return this.config.server;
}
mail(): ServerMailerConfig {
const sender =
typeof this.config.mailer.from === 'string'
? this.config.mailer.from
: this.config.mailer.from?.address;
return {
host: this.config.mailer.host,
port: this.config.mailer.port,
secure: this.config.mailer.secure,
service: this.config.mailer.service,
sender,
};
}
database(): ServerDatabaseConfig {
const url = new URL(this.config.database.datasourceUrl);
return {
host: url.hostname,
port: Number(url.port),
user: url.username,
database: url.pathname.slice(1) ?? url.username,
};
}
}

View File

@ -0,0 +1,17 @@
import type { Prisma } from '@prisma/client';
import { defineStartupConfig, ModuleConfig } from '../config';
interface PrismaStartupConfiguration extends Prisma.PrismaClientOptions {
datasourceUrl: string;
}
declare module '../config' {
interface AppConfig {
database: ModuleConfig<PrismaStartupConfiguration>;
}
}
defineStartupConfig('database', {
datasourceUrl: '',
});

View File

@ -1,18 +1,22 @@
import './config';
import { Global, Module, Provider } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import { Config } from '../config';
import { PrismaService } from './service';
// only `PrismaClient` can be injected
const clientProvider: Provider = {
provide: PrismaClient,
useFactory: () => {
useFactory: (config: Config) => {
if (PrismaService.INSTANCE) {
return PrismaService.INSTANCE;
}
return new PrismaService();
return new PrismaService(config.database);
},
inject: [Config],
};
@Global()

View File

@ -1,6 +1,6 @@
import type { OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import { Prisma, PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService
@ -9,8 +9,8 @@ export class PrismaService
{
static INSTANCE: PrismaService | null = null;
constructor() {
super();
constructor(opts: Prisma.PrismaClientOptions) {
super(opts);
PrismaService.INSTANCE = this;
}

View File

@ -541,6 +541,7 @@ type Query {
"""get all server runtime configurable settings"""
serverRuntimeConfig: [ServerRuntimeConfigType!]!
serverServiceConfigs: [ServerServiceConfig!]!
"""Get user by email"""
user(email: String!): UserOrLimitedUser
@ -663,6 +664,11 @@ type ServerRuntimeConfigType {
value: JSON!
}
type ServerServiceConfig {
config: JSONObject!
name: String!
}
type SubscriptionAlreadyExistsDataType {
plan: String!
}

View File

@ -798,6 +798,7 @@ export interface Query {
serverConfig: ServerConfigType;
/** get all server runtime configurable settings */
serverRuntimeConfig: Array<ServerRuntimeConfigType>;
serverServiceConfigs: Array<ServerServiceConfig>;
/** Get user by email */
user: Maybe<UserOrLimitedUser>;
/** Get user by id */
@ -952,6 +953,12 @@ export interface ServerRuntimeConfigType {
value: Scalars['JSON']['output'];
}
export interface ServerServiceConfig {
__typename?: 'ServerServiceConfig';
config: Scalars['JSONObject']['output'];
name: Scalars['String']['output'];
}
export interface SubscriptionAlreadyExistsDataType {
__typename?: 'SubscriptionAlreadyExistsDataType';
plan: Scalars['String']['output'];