-
Notifications
You must be signed in to change notification settings - Fork 8
/
knex-core.module.ts
113 lines (96 loc) · 3.31 KB
/
knex-core.module.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { Global, Module, DynamicModule, Provider, Type, OnApplicationShutdown, Inject } from '@nestjs/common';
import { KnexModuleAsyncOptions, KnexModuleOptions, KnexOptionsFactory } from './interfaces';
import { getConnectionToken, handleRetry } from './common/knex.utils'
import { KNEX_MODULE_OPTIONS } from './knex.constants';
import { knex, Knex } from 'knex';
import { ModuleRef } from '@nestjs/core';
import { defer, lastValueFrom } from 'rxjs';
@Global()
@Module({})
export class KnexCoreModule implements OnApplicationShutdown {
constructor(
@Inject(KNEX_MODULE_OPTIONS)
private readonly options: KnexModuleOptions,
private readonly moduleRef: ModuleRef,
) {}
public static forRoot(options: KnexModuleOptions, connection?: string): DynamicModule {
const knexModuleOptions = {
provide: KNEX_MODULE_OPTIONS,
useValue: options,
};
const connectionProvider: Provider = {
provide: getConnectionToken(connection),
useFactory: async () => await this.createConnectionFactory(options),
};
return {
module: KnexCoreModule,
providers: [connectionProvider, knexModuleOptions],
exports: [connectionProvider],
};
}
public static forRootAsync(options: KnexModuleAsyncOptions, connection: string): DynamicModule {
const connectionProvider: Provider = {
provide: getConnectionToken(connection),
useFactory: async (options: KnexModuleOptions) => {
return await this.createConnectionFactory(options);
},
inject: [KNEX_MODULE_OPTIONS],
};
return {
module: KnexCoreModule,
imports: options.imports,
providers: [...this.createAsyncProviders(options), connectionProvider],
exports: [connectionProvider],
};
}
async onApplicationShutdown(): Promise<any> {
const connection = this.moduleRef.get<Knex>(
getConnectionToken(this.options as KnexModuleOptions) as Type<Knex>,
);
connection && (await connection.destroy());
}
public static createAsyncProviders(options: KnexModuleAsyncOptions): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncOptionsProvider(options)];
}
const useClass = options.useClass as Type<KnexOptionsFactory>;
return [
this.createAsyncOptionsProvider(options),
{
provide: useClass,
useClass,
},
];
}
public static createAsyncOptionsProvider(options: KnexModuleAsyncOptions): Provider {
if (options.useFactory) {
return {
provide: KNEX_MODULE_OPTIONS,
useFactory: options.useFactory,
inject: options.inject || [],
};
}
// `as Type<KnexOptionsFactory>` is a workaround for microsoft/TypeScript#31603
const inject = [
(options.useClass || options.useExisting) as Type<
KnexOptionsFactory
>,
];
return {
provide: KNEX_MODULE_OPTIONS,
useFactory: async (optionsFactory: KnexOptionsFactory): Promise<KnexModuleOptions> => {
return await optionsFactory.createKnexOptions();
},
inject
};
}
private static async createConnectionFactory(
options: KnexModuleOptions,
): Promise<Knex> {
return lastValueFrom(
defer(async () => {
return knex(options.config);
}).pipe(handleRetry(options.retryAttempts, options.retryDelay)),
);
}
}