diff --git a/packages/koishi-core/package.json b/packages/koishi-core/package.json index 9819133b0b..ea8562cb35 100644 --- a/packages/koishi-core/package.json +++ b/packages/koishi-core/package.json @@ -34,6 +34,7 @@ "devDependencies": { "@types/debug": "^4.1.5", "@types/ws": "^6.0.4", + "get-port": "^5.1.0", "koishi-database-level": "^1.0.3", "koishi-test-utils": "^1.0.3" }, @@ -41,7 +42,6 @@ "axios": "^0.19.0", "debug": "^4.1.1", "escape-string-regexp": "^2.0.0", - "get-port": "^5.1.0", "koishi-utils": "^1.0.2", "leven": "^3.1.0", "ws": "^7.2.1" diff --git a/packages/koishi-core/src/database.ts b/packages/koishi-core/src/database.ts index c42ae7fb3f..9b17ba8e4c 100644 --- a/packages/koishi-core/src/database.ts +++ b/packages/koishi-core/src/database.ts @@ -153,13 +153,15 @@ export interface AbstractDatabase { stop? (): void | Promise } +const unknownMethods: { [K in SubdatabaseType]?: DatabaseInjections } = {} +const unknownOptions: { [K in SubdatabaseType]?: TableConfig } = {} const subdatabases: { [K in SubdatabaseType]?: Subdatabase } = {} const existingDatabases: { [K in SubdatabaseType]?: DatabaseMap } = {} export function registerDatabase (name: K, subdatabase: Subdatabase) { subdatabases[name] = subdatabase as any - subdatabase._methods = {} - subdatabase._options = {} + subdatabase._methods = unknownMethods[name] ?? {} + subdatabase._options = unknownOptions[name] ?? {} } export type DatabaseInjections = { @@ -175,24 +177,26 @@ export function injectMethods ( options?: TableConfig, ) { const Subdatabase = subdatabases[name] as Subdatabase - if (!Subdatabase) return - if (Subdatabase._manager) { - const config = Subdatabase._manager.config[name] - if (!config) return - if (!Subdatabase._manager.database[name]) { - Subdatabase._manager.createSubdatabase(name, config) - } - Subdatabase._manager.injectMethods(name, table, methods) + let methodMap: Partial>> + let optionMap: Partial>> + + // inject before subdatabase was registered + if (!Subdatabase) { + methodMap = unknownMethods[name] || (unknownMethods[name] = {} as never) + optionMap = unknownOptions[name] || (unknownOptions[name] = {} as never) } else { - Subdatabase._methods[table] = { - ...Subdatabase._methods[table] as any, - ...methods as any, + optionMap = Subdatabase._options + if (Subdatabase._manager) { + // inject after application was created + Subdatabase._manager.injectMethods(name, table, methods) + methodMap = {} as any + } else { + methodMap = Subdatabase._methods } } - Subdatabase._options[table] = { - ...Subdatabase._options[table] as any, - ...options as any, - } + + methodMap[table] = { ...methodMap[table], ...methods } + optionMap[table] = { ...optionMap[table] as any, ...options as any } } class DatabaseManager { diff --git a/packages/koishi-core/tests/database.spec.ts b/packages/koishi-core/tests/database.spec.ts index ffdf03896d..c52d17f236 100644 --- a/packages/koishi-core/tests/database.spec.ts +++ b/packages/koishi-core/tests/database.spec.ts @@ -53,9 +53,6 @@ class BarDatabase { constructor (public options: BarOptions) {} } -registerDatabase('foo', FooDatabase) -registerDatabase('bar', BarDatabase) - injectMethods('foo', 'user', { myUserFunc1 () { return 'my-foo-user-func' @@ -68,6 +65,9 @@ injectMethods('foo', 'user', { }, }) +registerDatabase('foo', FooDatabase) +registerDatabase('bar', BarDatabase) + injectMethods('bar', 'user', { myUserFunc1 () { return 'my-bar-user-func' @@ -117,7 +117,8 @@ describe('multiple databases', () => { expect(() => new App({ database: { foo: { value: 1 }, - bar: {}, + // make coverage happy + bar: { identifier: 'id' }, }, })).toThrow() })