Yuki Takei 1 an în urmă
părinte
comite
3d5b477615

+ 19 - 21
apps/app/src/server/service/config-manager/config-loader.ts

@@ -1,5 +1,4 @@
-import type { IConfigLoader } from '@growi/core/dist/interfaces';
-import * as configUtils from '@growi/core/dist/utils/config-utils';
+import type { IConfigLoader, RawConfigData } from '@growi/core/dist/interfaces';
 import { toBoolean } from '@growi/core/dist/utils/env-utils';
 
 import loggerFactory from '~/utils/logger';
@@ -11,36 +10,32 @@ const logger = loggerFactory('growi:service:ConfigLoader');
 
 export class ConfigLoader implements IConfigLoader<ConfigKey, ConfigValues> {
 
-  async loadFromEnv(): Promise<Record<ConfigKey, ConfigValues[ConfigKey]>> {
-    const envConfig = {} as Record<ConfigKey, ConfigValues[ConfigKey]>;
+  async loadFromEnv(): Promise<RawConfigData<ConfigKey, ConfigValues>> {
+    const envConfig = {} as RawConfigData<ConfigKey, ConfigValues>;
 
     for (const [key, metadata] of Object.entries(CONFIG_DEFINITIONS)) {
-      const configKey = key as ConfigKey;
+      let configValue = metadata.defaultValue;
 
       if (metadata.envVarName != null) {
-        const envValue = process.env[metadata.envVarName];
-        if (envValue !== undefined) {
-          envConfig[configKey] = this.parseEnvValue(
-            envValue,
-            typeof metadata.defaultValue,
-          ) as ConfigValues[ConfigKey];
-          continue;
+        const envVarValue = process.env[metadata.envVarName];
+        if (envVarValue != null) {
+          configValue = this.parseEnvValue(envVarValue, typeof metadata.defaultValue) as ConfigValues[ConfigKey];
         }
       }
-      envConfig[configKey] = metadata.defaultValue;
+
+      envConfig[key as ConfigKey] = {
+        definition: metadata,
+        value: configValue,
+      };
     }
 
     logger.debug('loadFromEnv', envConfig);
+
     return envConfig;
   }
 
-  async loadFromDB(): Promise<Record<ConfigKey, ConfigValues[ConfigKey] | null>> {
-    const dbConfig = {} as Record<ConfigKey, ConfigValues[ConfigKey] | null>;
-
-    // Initialize with null values
-    for (const key of Object.keys(CONFIG_DEFINITIONS)) {
-      dbConfig[key as ConfigKey] = null;
-    }
+  async loadFromDB(): Promise<RawConfigData<ConfigKey, ConfigValues>> {
+    const dbConfig = {} as RawConfigData<ConfigKey, ConfigValues>;
 
     // Dynamic import to avoid loading database modules too early
     const { Config } = await import('../../models/config');
@@ -48,7 +43,10 @@ export class ConfigLoader implements IConfigLoader<ConfigKey, ConfigValues> {
 
     for (const doc of docs) {
       if (doc.key in CONFIG_DEFINITIONS) {
-        dbConfig[doc.key as ConfigKey] = doc.value ? JSON.parse(doc.value) : null;
+        dbConfig[doc.key as ConfigKey] = {
+          definition: CONFIG_DEFINITIONS[doc.key as ConfigKey],
+          value: doc.value ? JSON.parse(doc.value) : null,
+        };
       }
     }
 

+ 10 - 8
apps/app/src/server/service/config-manager/config-manager.ts

@@ -1,4 +1,6 @@
-import type { IConfigManager, ConfigSource, UpdateConfigOptions } from '@growi/core/dist/interfaces';
+import type {
+  IConfigManager, ConfigSource, UpdateConfigOptions, RawConfigData,
+} from '@growi/core/dist/interfaces';
 import { parseISO } from 'date-fns/parseISO';
 
 import loggerFactory from '~/utils/logger';
@@ -20,9 +22,9 @@ export class ConfigManager implements IConfigManager<ConfigKey, ConfigValues>, S
 
   private s2sMessagingService?: S2sMessagingService;
 
-  private envConfig?: Record<ConfigKey, ConfigValues[ConfigKey]>;
+  private envConfig?: RawConfigData<ConfigKey, ConfigValues>;
 
-  private dbConfig?: Record<ConfigKey, ConfigValues[ConfigKey] | null>;
+  private dbConfig?: RawConfigData<ConfigKey, ConfigValues>;
 
   private lastLoadedAt?: Date;
 
@@ -71,10 +73,10 @@ export class ConfigManager implements IConfigManager<ConfigKey, ConfigValues>, S
     }
 
     if (this.shouldUseEnvOnly(key)) {
-      return this.envConfig[key] as ConfigValues[K];
+      return this.envConfig[key].value as ConfigValues[K];
     }
 
-    return (this.dbConfig[key] ?? this.envConfig[key]) as ConfigValues[K];
+    return (this.dbConfig[key] ?? this.envConfig[key]).value as ConfigValues[K];
   }
 
   private shouldUseEnvOnly(key: ConfigKey): boolean {
@@ -87,7 +89,7 @@ export class ConfigManager implements IConfigManager<ConfigKey, ConfigValues>, S
     if (!this.envConfig) {
       throw new Error('Config is not loaded');
     }
-    return this.envConfig[controlKey] === true;
+    return this.envConfig[controlKey].value === true;
   }
 
   async updateConfig<K extends ConfigKey>(key: K, value: ConfigValues[K], options?: UpdateConfigOptions): Promise<void> {
@@ -146,8 +148,8 @@ export class ConfigManager implements IConfigManager<ConfigKey, ConfigValues>, S
   }
 
   getRawConfigData(): {
-    env: Record<ConfigKey, ConfigValues[ConfigKey]>;
-    db: Record<ConfigKey, ConfigValues[ConfigKey] | null>;
+    env: RawConfigData<ConfigKey, ConfigValues>;
+    db: RawConfigData<ConfigKey, ConfigValues>;
     } {
     if (!this.envConfig || !this.dbConfig) {
       throw new Error('Config is not loaded');

+ 10 - 4
packages/core/src/interfaces/config-manager.ts

@@ -26,14 +26,20 @@ export interface IConfigLoader<K extends string, V extends Record<K, any>> {
   /**
    * Load configurations from environment variables
    */
-  loadFromEnv(): Promise<Record<K, V[K]>>;
+  loadFromEnv(): Promise<RawConfigData<K, V>>;
 
   /**
    * Load configurations from database
    */
-  loadFromDB(): Promise<Record<K, V[K] | null>>;
+  loadFromDB(): Promise<RawConfigData<K, V>>;
 }
 
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type RawConfigData<K extends string, V extends Record<K, any>> = Record<K, {
+  definition: ConfigDefinition<V[K]>;
+  value: V[K];
+}>;
+
 export type UpdateConfigOptions = { skipPubsub?: boolean };
 
 /**
@@ -71,8 +77,8 @@ export interface IConfigManager<K extends string, V extends Record<K, any>> {
    * Get raw configuration data for UI display
    */
   getRawConfigData(): {
-    env: Record<K, V[K]>;
-    db: Record<K, V[K] | null>;
+    env: RawConfigData<K, V[K]>;
+    db: RawConfigData<K, V[K]>;
   };
 
   /**