@nest-yalc-2/app 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +49 -0
- package/package.json +33 -0
- package/src/__tests__/app-bootstrap-base.helper.spec.ts +38 -0
- package/src/__tests__/app-bootstrap-standalone.helper.spec.ts +35 -0
- package/src/__tests__/app-bootstrap.helper.spec.ts +98 -0
- package/src/__tests__/app-config.service.spec.ts +55 -0
- package/src/__tests__/app-context.service.spec.ts +28 -0
- package/src/__tests__/app.events.spec.ts +12 -0
- package/src/__tests__/app.helper.spec.ts +204 -0
- package/src/__tests__/base-app-module.helper.spec.ts +231 -0
- package/src/__tests__/base-app.controller.spec.ts +72 -0
- package/src/__tests__/base-app.service.spec.ts +39 -0
- package/src/__tests__/cls.module.spec.ts +33 -0
- package/src/__tests__/life-cycle-handler.service.spec.ts +48 -0
- package/src/__tests__/tsconfig.json +3 -0
- package/src/__tests__/unwrap-result.interceptor.spec.ts +52 -0
- package/src/app-bootstrap-base.helper.d.ts +41 -0
- package/src/app-bootstrap-base.helper.js +108 -0
- package/src/app-bootstrap-base.helper.js.map +1 -0
- package/src/app-bootstrap-base.helper.ts +199 -0
- package/src/app-bootstrap-standalone.helper.d.ts +15 -0
- package/src/app-bootstrap-standalone.helper.js +45 -0
- package/src/app-bootstrap-standalone.helper.js.map +1 -0
- package/src/app-bootstrap-standalone.helper.ts +60 -0
- package/src/app-bootstrap.helper.d.ts +43 -0
- package/src/app-bootstrap.helper.js +164 -0
- package/src/app-bootstrap.helper.js.map +1 -0
- package/src/app-bootstrap.helper.ts +263 -0
- package/src/app-config.service.d.ts +14 -0
- package/src/app-config.service.js +45 -0
- package/src/app-config.service.js.map +1 -0
- package/src/app-config.service.ts +61 -0
- package/src/app-context.module.d.ts +2 -0
- package/src/app-context.module.js +19 -0
- package/src/app-context.module.js.map +1 -0
- package/src/app-context.module.ts +6 -0
- package/src/app-context.service.d.ts +7 -0
- package/src/app-context.service.js +26 -0
- package/src/app-context.service.js.map +1 -0
- package/src/app-context.service.ts +16 -0
- package/src/app-imports.factory.d.ts +19 -0
- package/src/app-imports.factory.js +223 -0
- package/src/app-imports.factory.js.map +1 -0
- package/src/app-imports.factory.ts +320 -0
- package/src/app.events.d.ts +5 -0
- package/src/app.events.js +10 -0
- package/src/app.events.js.map +1 -0
- package/src/app.events.ts +8 -0
- package/src/app.helper.d.ts +17 -0
- package/src/app.helper.js +26 -0
- package/src/app.helper.js.map +1 -0
- package/src/app.helper.ts +73 -0
- package/src/base-app-module.helper.d.ts +24 -0
- package/src/base-app-module.helper.js +326 -0
- package/src/base-app-module.helper.js.map +1 -0
- package/src/base-app-module.helper.ts +447 -0
- package/src/base-app.controller.d.ts +9 -0
- package/src/base-app.controller.js +56 -0
- package/src/base-app.controller.js.map +1 -0
- package/src/base-app.controller.ts +43 -0
- package/src/base-app.interface.d.ts +33 -0
- package/src/base-app.interface.js +3 -0
- package/src/base-app.interface.js.map +1 -0
- package/src/base-app.interface.ts +55 -0
- package/src/base-app.service.d.ts +7 -0
- package/src/base-app.service.js +78 -0
- package/src/base-app.service.js.map +1 -0
- package/src/base-app.service.ts +29 -0
- package/src/cls.module.d.ts +15 -0
- package/src/cls.module.js +51 -0
- package/src/cls.module.js.map +1 -0
- package/src/cls.module.ts +68 -0
- package/src/conf.type.d.ts +21 -0
- package/src/conf.type.js +3 -0
- package/src/conf.type.js.map +1 -0
- package/src/conf.type.ts +22 -0
- package/src/db-conf.helper.ts-off +93 -0
- package/src/def.const.d.ts +10 -0
- package/src/def.const.js +14 -0
- package/src/def.const.js.map +1 -0
- package/src/def.const.ts +33 -0
- package/src/global.enum.d.ts +6 -0
- package/src/global.enum.js +11 -0
- package/src/global.enum.js.map +1 -0
- package/src/global.enum.ts +6 -0
- package/src/index.d.ts +0 -0
- package/src/index.js +2 -0
- package/src/index.js.map +1 -0
- package/src/index.ts +0 -0
- package/src/life-cycle-handler.service.d.ts +13 -0
- package/src/life-cycle-handler.service.js +47 -0
- package/src/life-cycle-handler.service.js.map +1 -0
- package/src/life-cycle-handler.service.ts +58 -0
- package/src/unwrap-result.interceptor.d.ts +5 -0
- package/src/unwrap-result.interceptor.js +36 -0
- package/src/unwrap-result.interceptor.js.map +1 -0
- package/src/unwrap-result.interceptor.ts +32 -0
- package/src/yalc-controller.interface.d.ts +3 -0
- package/src/yalc-controller.interface.js +3 -0
- package/src/yalc-controller.interface.js.map +1 -0
- package/src/yalc-controller.interface.ts +6 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DynamicModule,
|
|
3
|
+
INestApplicationContext,
|
|
4
|
+
Logger,
|
|
5
|
+
LoggerService,
|
|
6
|
+
Type,
|
|
7
|
+
} from '@nestjs/common';
|
|
8
|
+
import { ConfigService } from '@nestjs/config';
|
|
9
|
+
// import { GqlExceptionFilter } from '@nestjs/graphql';
|
|
10
|
+
import { NestFastifyApplication } from '@nestjs/platform-fastify';
|
|
11
|
+
import type { IServiceConf } from './conf.type.js';
|
|
12
|
+
import { SYSTEM_LOGGER_SERVICE } from './def.const.js';
|
|
13
|
+
import { YalcDefaultAppModule } from './base-app-module.helper.js';
|
|
14
|
+
import { ICreateOptions, INestCreateOptions } from './app-bootstrap.helper.js';
|
|
15
|
+
import { EventModule } from '@nest-yalc-2/event-manager/event.module.js';
|
|
16
|
+
import { LoggerServiceFactory } from '@nest-yalc-2/logger/logger.service.js';
|
|
17
|
+
import { FastifyInstance } from 'fastify';
|
|
18
|
+
import { getEnvLoggerLevels } from '@nest-yalc-2/logger/logger.helper.js';
|
|
19
|
+
import { globalPromiseTracker } from '@nest-yalc-2/utils/promise.helper.js';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Side effect to be executed as soon as the module is imported
|
|
23
|
+
*/
|
|
24
|
+
Logger.overrideLogger(getEnvLoggerLevels());
|
|
25
|
+
|
|
26
|
+
export interface IGlobalOptions {
|
|
27
|
+
extraImports?: NonNullable<DynamicModule['imports']>;
|
|
28
|
+
eventModuleClass?: typeof EventModule;
|
|
29
|
+
logger?: typeof LoggerServiceFactory;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* This is used to avoid bootstrapping a multi-server app
|
|
33
|
+
*/
|
|
34
|
+
skipMultiServerCheck?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const bootstrappedApps: Set<any> = new Set();
|
|
38
|
+
|
|
39
|
+
export const getBootstrappedApps = () => {
|
|
40
|
+
return bootstrappedApps;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const getMainBootstrappedApp = <
|
|
44
|
+
TApp extends BaseAppBootstrap<
|
|
45
|
+
NestFastifyApplication | INestApplicationContext
|
|
46
|
+
>,
|
|
47
|
+
>(): TApp | null => {
|
|
48
|
+
if (getBootstrappedApps().size === 0) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return getBootstrappedApps().values().next().value;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export abstract class BaseAppBootstrap<
|
|
56
|
+
TAppType extends NestFastifyApplication | INestApplicationContext,
|
|
57
|
+
> {
|
|
58
|
+
protected app?: TAppType;
|
|
59
|
+
protected loggerService!: LoggerService;
|
|
60
|
+
protected module: Type<any> | DynamicModule;
|
|
61
|
+
protected isClosed = false;
|
|
62
|
+
|
|
63
|
+
constructor(
|
|
64
|
+
protected appAlias: string,
|
|
65
|
+
protected readonly appModule: Type<any>,
|
|
66
|
+
options?: { globalsOptions?: IGlobalOptions },
|
|
67
|
+
) {
|
|
68
|
+
this.module = YalcDefaultAppModule.forRoot(
|
|
69
|
+
this.appAlias,
|
|
70
|
+
[appModule, ...(options?.globalsOptions?.extraImports ?? [])],
|
|
71
|
+
options?.globalsOptions,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const bootstrappedApp = getMainBootstrappedApp();
|
|
75
|
+
|
|
76
|
+
if (
|
|
77
|
+
bootstrappedApp &&
|
|
78
|
+
!options?.globalsOptions?.skipMultiServerCheck &&
|
|
79
|
+
process.env.APP_SKIP_MULTISERVER_CHECK !== 'true'
|
|
80
|
+
) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`You are trying to bootstrap multiple servers (${bootstrappedApp.appAlias}) in the same process. This is not allowed. Use a different process for each server`,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getBootstrappedApps().add(this);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async initApp(options?: {
|
|
90
|
+
createOptions?: INestCreateOptions;
|
|
91
|
+
fastifyInstance?: FastifyInstance;
|
|
92
|
+
}): Promise<this> {
|
|
93
|
+
options; // extend this method in the child class
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
setApp(app: TAppType) {
|
|
98
|
+
this.app = app;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Monkey patch the close method to set the isClosed flag
|
|
102
|
+
*/
|
|
103
|
+
const originalCloseFn = this.app.close.bind(this.app);
|
|
104
|
+
this.app.close = async () => {
|
|
105
|
+
const closeRes = await originalCloseFn();
|
|
106
|
+
this.closeCleanup();
|
|
107
|
+
return closeRes;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Monkey patch the init method to set the isClosed flag
|
|
112
|
+
*/
|
|
113
|
+
const originalInitFn = this.app.init.bind(this.app);
|
|
114
|
+
this.app.init = async () => {
|
|
115
|
+
this.isClosed = false;
|
|
116
|
+
getBootstrappedApps().add(this);
|
|
117
|
+
let initRes;
|
|
118
|
+
try {
|
|
119
|
+
initRes = await originalInitFn();
|
|
120
|
+
} catch (error) {
|
|
121
|
+
this.closeCleanup();
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
return initRes;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
return this;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* This method is used to cleanup the app and remove it from the global set of bootstrapped apps
|
|
132
|
+
*/
|
|
133
|
+
closeCleanup() {
|
|
134
|
+
this.isClosed = true;
|
|
135
|
+
getBootstrappedApps().delete(this);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
isAppClosed() {
|
|
139
|
+
return this.isClosed;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
getAppAlias() {
|
|
143
|
+
return this.appAlias;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
getConf() {
|
|
147
|
+
const configService = this.getApp().get<ConfigService>(ConfigService);
|
|
148
|
+
return configService.get<IServiceConf>(this.appAlias);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
getApp() {
|
|
152
|
+
if (!this.app) {
|
|
153
|
+
throw new Error('This app is not initialized yet');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return this.app;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async closeApp() {
|
|
160
|
+
await this.cleanup();
|
|
161
|
+
|
|
162
|
+
await this.app?.close();
|
|
163
|
+
|
|
164
|
+
this.closeCleanup();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async cleanup() {
|
|
168
|
+
/**
|
|
169
|
+
* When running behind a lambda, we have to await for all the promises that have been added to the global promise tracker
|
|
170
|
+
* to avoid them being killed by the lambda
|
|
171
|
+
* @see - https://stackoverflow.com/questions/64688812/running-tasks-in-aws-lambda-background
|
|
172
|
+
*/
|
|
173
|
+
await globalPromiseTracker.waitForAll();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
*
|
|
178
|
+
* @returns The main module of the business logic (the one that is passed in the constructor)
|
|
179
|
+
*/
|
|
180
|
+
getAppModule() {
|
|
181
|
+
return this.appModule;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
*
|
|
186
|
+
* @returns The global module that is used to bootstrap the app (YalcDefaultAppModule)
|
|
187
|
+
*/
|
|
188
|
+
getModule() {
|
|
189
|
+
return this.module;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async applyBootstrapGlobals(_options?: ICreateOptions) {
|
|
193
|
+
this.loggerService = this.getApp().get(SYSTEM_LOGGER_SERVICE);
|
|
194
|
+
this.loggerService.debug?.('Setting logger service...');
|
|
195
|
+
this.getApp().useLogger(this.loggerService);
|
|
196
|
+
Logger.overrideLogger(this.loggerService);
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { INestApplicationContext } from '@nestjs/common';
|
|
2
|
+
import { FastifyInstance } from 'fastify';
|
|
3
|
+
import { BaseAppBootstrap, IGlobalOptions } from './app-bootstrap-base.helper.js';
|
|
4
|
+
import { INestCreateOptions } from './app-bootstrap.helper.js';
|
|
5
|
+
export declare class StandaloneAppBootstrap<TGlobalOptions extends IGlobalOptions = IGlobalOptions> extends BaseAppBootstrap<INestApplicationContext> {
|
|
6
|
+
constructor(appAlias: string, module: any, options?: TGlobalOptions);
|
|
7
|
+
initApp(options?: {
|
|
8
|
+
createOptions?: INestCreateOptions;
|
|
9
|
+
fastifyInstance?: FastifyInstance;
|
|
10
|
+
}): Promise<this>;
|
|
11
|
+
createApp(_options?: {
|
|
12
|
+
createOptions?: INestCreateOptions;
|
|
13
|
+
fastifyInstance?: FastifyInstance;
|
|
14
|
+
}): Promise<this>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.StandaloneAppBootstrap = void 0;
|
|
7
|
+
const core_1 = require("@nestjs/core");
|
|
8
|
+
const env_helper_js_1 = require("@nest-yalc-2/utils/env.helper.js");
|
|
9
|
+
const cli_color_1 = __importDefault(require("cli-color"));
|
|
10
|
+
const app_bootstrap_base_helper_js_1 = require("./app-bootstrap-base.helper.js");
|
|
11
|
+
const logger_helper_js_1 = require("@nest-yalc-2/logger/logger.helper.js");
|
|
12
|
+
class StandaloneAppBootstrap extends app_bootstrap_base_helper_js_1.BaseAppBootstrap {
|
|
13
|
+
constructor(appAlias, module, options) {
|
|
14
|
+
super(appAlias, module, { globalsOptions: options });
|
|
15
|
+
}
|
|
16
|
+
async initApp(options) {
|
|
17
|
+
await this.createApp({
|
|
18
|
+
createOptions: options?.createOptions,
|
|
19
|
+
});
|
|
20
|
+
await this.applyBootstrapGlobals(options?.createOptions);
|
|
21
|
+
await this.getApp().init();
|
|
22
|
+
if ((0, env_helper_js_1.envIsTrue)(process.env.APP_DRY_RUN) === true) {
|
|
23
|
+
this.loggerService?.log('Dry run, exiting...');
|
|
24
|
+
await this.getApp().close();
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
async createApp(_options) {
|
|
30
|
+
let app;
|
|
31
|
+
try {
|
|
32
|
+
app = await core_1.NestFactory.createApplicationContext(this.module, {
|
|
33
|
+
logger: (0, logger_helper_js_1.getEnvLoggerLevels)(),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
this.closeCleanup();
|
|
38
|
+
console.error(cli_color_1.default.red('Failed to create app'), cli_color_1.default.red(err));
|
|
39
|
+
throw new Error('Process aborted');
|
|
40
|
+
}
|
|
41
|
+
return this.setApp(app);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.StandaloneAppBootstrap = StandaloneAppBootstrap;
|
|
45
|
+
//# sourceMappingURL=app-bootstrap-standalone.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-bootstrap-standalone.helper.js","sourceRoot":"","sources":["app-bootstrap-standalone.helper.ts"],"names":[],"mappings":";;;;;;AACA,uCAA2C;AAG3C,oEAA6D;AAC7D,0DAA4B;AAC5B,iFAGwC;AAExC,2EAA0E;AAE1E,MAAa,sBAEX,SAAQ,+CAAyC;IACjD,YAAY,QAAgB,EAAE,MAAW,EAAE,OAAwB;QACjE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAGb;QACC,MAAM,IAAI,CAAC,SAAS,CAAC;YACnB,aAAa,EAAE,OAAO,EAAE,aAAa;SACtC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,qBAAqB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAEzD,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;QAE3B,IAAI,IAAA,yBAAS,EAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE,CAAC;YAChD,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,qBAAqB,CAAC,CAAC;YAC/C,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,QAGf;QACC,IAAI,GAA4B,CAAC;QACjC,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,kBAAW,CAAC,wBAAwB,CAAC,IAAI,CAAC,MAAM,EAAE;gBAC5D,MAAM,EAAE,IAAA,qCAAkB,GAAE;aAC7B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,YAAY,EAAE,CAAC;YAEpB,OAAO,CAAC,KAAK,CAAC,mBAAG,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,mBAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;CACF;AA9CD,wDA8CC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { INestApplicationContext } from '@nestjs/common';
|
|
2
|
+
import { NestFactory } from '@nestjs/core';
|
|
3
|
+
// import { GqlExceptionFilter } from '@nestjs/graphql';
|
|
4
|
+
import { FastifyInstance } from 'fastify';
|
|
5
|
+
import { envIsTrue } from '@nest-yalc-2/utils/env.helper.js';
|
|
6
|
+
import clc from 'cli-color';
|
|
7
|
+
import {
|
|
8
|
+
BaseAppBootstrap,
|
|
9
|
+
IGlobalOptions,
|
|
10
|
+
} from './app-bootstrap-base.helper.js';
|
|
11
|
+
import { INestCreateOptions } from './app-bootstrap.helper.js';
|
|
12
|
+
import { getEnvLoggerLevels } from '@nest-yalc-2/logger/logger.helper.js';
|
|
13
|
+
|
|
14
|
+
export class StandaloneAppBootstrap<
|
|
15
|
+
TGlobalOptions extends IGlobalOptions = IGlobalOptions,
|
|
16
|
+
> extends BaseAppBootstrap<INestApplicationContext> {
|
|
17
|
+
constructor(appAlias: string, module: any, options?: TGlobalOptions) {
|
|
18
|
+
super(appAlias, module, { globalsOptions: options });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async initApp(options?: {
|
|
22
|
+
createOptions?: INestCreateOptions;
|
|
23
|
+
fastifyInstance?: FastifyInstance;
|
|
24
|
+
}) {
|
|
25
|
+
await this.createApp({
|
|
26
|
+
createOptions: options?.createOptions,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
await this.applyBootstrapGlobals(options?.createOptions);
|
|
30
|
+
|
|
31
|
+
await this.getApp().init();
|
|
32
|
+
|
|
33
|
+
if (envIsTrue(process.env.APP_DRY_RUN) === true) {
|
|
34
|
+
this.loggerService?.log('Dry run, exiting...');
|
|
35
|
+
await this.getApp().close();
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async createApp(_options?: {
|
|
43
|
+
createOptions?: INestCreateOptions;
|
|
44
|
+
fastifyInstance?: FastifyInstance;
|
|
45
|
+
}) {
|
|
46
|
+
let app: INestApplicationContext;
|
|
47
|
+
try {
|
|
48
|
+
app = await NestFactory.createApplicationContext(this.module, {
|
|
49
|
+
logger: getEnvLoggerLevels(),
|
|
50
|
+
});
|
|
51
|
+
} catch (err) {
|
|
52
|
+
this.closeCleanup();
|
|
53
|
+
// eslint-disable-next-line no-console
|
|
54
|
+
console.error(clc.red('Failed to create app'), clc.red(err));
|
|
55
|
+
throw new Error('Process aborted');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return this.setApp(app);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ExceptionFilter, NestApplicationOptions, ValidationPipeOptions } from '@nestjs/common';
|
|
2
|
+
import { NestFastifyApplication } from '@nestjs/platform-fastify';
|
|
3
|
+
import { DocumentBuilder } from '@nestjs/swagger';
|
|
4
|
+
import { FastifyInstance } from 'fastify';
|
|
5
|
+
import { BaseAppBootstrap, IGlobalOptions } from './app-bootstrap-base.helper.js';
|
|
6
|
+
export interface ICreateOptions {
|
|
7
|
+
enableSwagger?: boolean;
|
|
8
|
+
swaggerPath?: string;
|
|
9
|
+
filters?: ExceptionFilter[];
|
|
10
|
+
validationPipeOptions?: ValidationPipeOptions;
|
|
11
|
+
apiPrefix?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface INestCreateOptions extends ICreateOptions, NestApplicationOptions {
|
|
14
|
+
}
|
|
15
|
+
export declare class AppBootstrap<TGlobalOptions extends IGlobalOptions = IGlobalOptions> extends BaseAppBootstrap<NestFastifyApplication> {
|
|
16
|
+
private fastifyInstance?;
|
|
17
|
+
protected isSwaggerEnabled: boolean;
|
|
18
|
+
protected swaggerPath: string;
|
|
19
|
+
constructor(appAlias: string, module: any, options?: TGlobalOptions);
|
|
20
|
+
startServer(options?: {
|
|
21
|
+
createOptions?: INestCreateOptions;
|
|
22
|
+
fastifyInstance?: FastifyInstance;
|
|
23
|
+
}): Promise<this>;
|
|
24
|
+
initApp(options?: {
|
|
25
|
+
createOptions?: INestCreateOptions;
|
|
26
|
+
fastifyInstance?: FastifyInstance;
|
|
27
|
+
}): Promise<this>;
|
|
28
|
+
initSetup(options?: {
|
|
29
|
+
createOptions?: ICreateOptions;
|
|
30
|
+
fastifyInstance?: FastifyInstance;
|
|
31
|
+
}): Promise<this>;
|
|
32
|
+
createApp(options?: {
|
|
33
|
+
createOptions?: INestCreateOptions;
|
|
34
|
+
fastifyInstance?: FastifyInstance;
|
|
35
|
+
}): Promise<this>;
|
|
36
|
+
getFastifyInstance(): FastifyInstance<import("fastify").RawServerDefault, import("node:http").IncomingMessage, import("node:http").ServerResponse<import("node:http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault> | undefined;
|
|
37
|
+
setSwaggerEnabled(enabled: boolean): void;
|
|
38
|
+
applyBootstrapGlobals(options?: ICreateOptions): Promise<this>;
|
|
39
|
+
buildSwaggerConfig(): DocumentBuilder;
|
|
40
|
+
listen(callback?: {
|
|
41
|
+
(port: number, host: string, domain: string): void;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AppBootstrap = void 0;
|
|
7
|
+
const index_js_1 = require("@nest-yalc-2/errors/filters/index.js");
|
|
8
|
+
const common_1 = require("@nestjs/common");
|
|
9
|
+
const core_1 = require("@nestjs/core");
|
|
10
|
+
const platform_fastify_1 = require("@nestjs/platform-fastify");
|
|
11
|
+
const cookie_1 = __importDefault(require("@fastify/cookie"));
|
|
12
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
13
|
+
const fastify_1 = require("fastify");
|
|
14
|
+
const env_helper_js_1 = require("@nest-yalc-2/utils/env.helper.js");
|
|
15
|
+
const class_validator_1 = require("class-validator");
|
|
16
|
+
const cli_color_1 = __importDefault(require("cli-color"));
|
|
17
|
+
const app_bootstrap_base_helper_js_1 = require("./app-bootstrap-base.helper.js");
|
|
18
|
+
const logger_helper_js_1 = require("@nest-yalc-2/logger/logger.helper.js");
|
|
19
|
+
const unwrap_result_interceptor_js_1 = require("./unwrap-result.interceptor.js");
|
|
20
|
+
class AppBootstrap extends app_bootstrap_base_helper_js_1.BaseAppBootstrap {
|
|
21
|
+
constructor(appAlias, module, options) {
|
|
22
|
+
super(appAlias, module, { globalsOptions: options });
|
|
23
|
+
this.isSwaggerEnabled = false;
|
|
24
|
+
this.swaggerPath = 'api';
|
|
25
|
+
}
|
|
26
|
+
async startServer(options) {
|
|
27
|
+
await this.initApp(options);
|
|
28
|
+
if ((0, env_helper_js_1.envIsTrue)(process.env.APP_DRY_RUN) === true) {
|
|
29
|
+
await this.closeApp();
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
this.listen();
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
async initApp(options) {
|
|
36
|
+
await this.createApp({
|
|
37
|
+
fastifyInstance: this.fastifyInstance,
|
|
38
|
+
createOptions: options?.createOptions,
|
|
39
|
+
});
|
|
40
|
+
return this.initSetup({
|
|
41
|
+
fastifyInstance: this.fastifyInstance,
|
|
42
|
+
createOptions: options?.createOptions,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async initSetup(options) {
|
|
46
|
+
try {
|
|
47
|
+
await this.applyBootstrapGlobals(options?.createOptions);
|
|
48
|
+
await this.getApp().init();
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
console.error('App init failed:', err);
|
|
52
|
+
this.closeCleanup();
|
|
53
|
+
throw new Error('Process aborted');
|
|
54
|
+
}
|
|
55
|
+
if ((0, env_helper_js_1.envIsTrue)(process.env.APP_DRY_RUN) === true) {
|
|
56
|
+
this.loggerService?.log('Dry run, exiting...');
|
|
57
|
+
await this.closeApp();
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
async createApp(options) {
|
|
63
|
+
this.fastifyInstance = options?.fastifyInstance ?? (0, fastify_1.fastify)();
|
|
64
|
+
let app;
|
|
65
|
+
try {
|
|
66
|
+
app = await core_1.NestFactory.create(this.module, new platform_fastify_1.FastifyAdapter(this.fastifyInstance), {
|
|
67
|
+
bufferLogs: false,
|
|
68
|
+
abortOnError: options?.createOptions?.abortOnError ?? false,
|
|
69
|
+
logger: (0, logger_helper_js_1.getEnvLoggerLevels)(),
|
|
70
|
+
...(options?.createOptions ?? {}),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
this.closeCleanup();
|
|
75
|
+
console.error(cli_color_1.default.red('Failed to create app'), cli_color_1.default.red(err));
|
|
76
|
+
throw new Error('Process aborted');
|
|
77
|
+
}
|
|
78
|
+
return this.setApp(app);
|
|
79
|
+
}
|
|
80
|
+
getFastifyInstance() {
|
|
81
|
+
return this.fastifyInstance;
|
|
82
|
+
}
|
|
83
|
+
setSwaggerEnabled(enabled) {
|
|
84
|
+
this.isSwaggerEnabled = enabled;
|
|
85
|
+
}
|
|
86
|
+
async applyBootstrapGlobals(options) {
|
|
87
|
+
await super.applyBootstrapGlobals(options);
|
|
88
|
+
this.getApp().useGlobalPipes(new common_1.ValidationPipe({
|
|
89
|
+
transform: true,
|
|
90
|
+
transformOptions: { enableImplicitConversion: false },
|
|
91
|
+
validateCustomDecorators: true,
|
|
92
|
+
exceptionFactory: (errors) => {
|
|
93
|
+
const errorMessages = {};
|
|
94
|
+
errors.forEach((error) => {
|
|
95
|
+
errorMessages[error.property] = error;
|
|
96
|
+
});
|
|
97
|
+
return new common_1.BadRequestException(errorMessages);
|
|
98
|
+
},
|
|
99
|
+
...(options?.validationPipeOptions ?? {}),
|
|
100
|
+
}));
|
|
101
|
+
this.getApp().setGlobalPrefix(options?.apiPrefix ?? (this.getConf()?.apiPrefix || ''));
|
|
102
|
+
await this.getApp().register(cookie_1.default, {});
|
|
103
|
+
this.getApp().useGlobalInterceptors(new unwrap_result_interceptor_js_1.UnwrapResultInterceptor());
|
|
104
|
+
const filters = [
|
|
105
|
+
new index_js_1.SystemExceptionFilter(this.loggerService),
|
|
106
|
+
...(options?.filters ?? []),
|
|
107
|
+
];
|
|
108
|
+
this.getApp().useGlobalFilters(...filters);
|
|
109
|
+
if (options?.enableSwagger) {
|
|
110
|
+
const swaggerPath = sanitizeSwaggerPath(options.swaggerPath);
|
|
111
|
+
this.swaggerPath = swaggerPath;
|
|
112
|
+
this.setSwaggerEnabled(true);
|
|
113
|
+
const document = swagger_1.SwaggerModule.createDocument(this.getApp(), this.buildSwaggerConfig().build());
|
|
114
|
+
swagger_1.SwaggerModule.setup(swaggerPath, this.getApp(), document, {
|
|
115
|
+
jsonDocumentUrl: `/${swaggerPath}/json`,
|
|
116
|
+
useGlobalPrefix: true,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
(0, class_validator_1.useContainer)(this.getApp().select(this.getModule()), {
|
|
120
|
+
fallbackOnErrors: true,
|
|
121
|
+
});
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
buildSwaggerConfig() {
|
|
125
|
+
return new swagger_1.DocumentBuilder()
|
|
126
|
+
.setTitle(this.appAlias)
|
|
127
|
+
.setDescription(`${this.appAlias} rest api`);
|
|
128
|
+
}
|
|
129
|
+
async listen(callback) {
|
|
130
|
+
const port = this.getConf()?.port || 0;
|
|
131
|
+
const host = this.getConf()?.host || '0.0.0.0';
|
|
132
|
+
let apiPrefix = this.getConf()?.apiPrefix;
|
|
133
|
+
apiPrefix = apiPrefix ? `/${apiPrefix}` : '';
|
|
134
|
+
const domain = this.getConf()?.domain || 'localhost';
|
|
135
|
+
await this.getApp().listen(port, host, async (_err, address) => {
|
|
136
|
+
console.debug(`Server ${this.appAlias} listening on
|
|
137
|
+
http://localhost:${port}${apiPrefix}/
|
|
138
|
+
http://127.0.0.1:${port}${apiPrefix}/
|
|
139
|
+
http://${domain}:${port}${apiPrefix}/
|
|
140
|
+
${address}`);
|
|
141
|
+
if (this.isSwaggerEnabled) {
|
|
142
|
+
console.debug(`Swagger ${this.appAlias} listening on
|
|
143
|
+
http://localhost:${port}${apiPrefix}/${this.swaggerPath}
|
|
144
|
+
http://127.0.0.1:${port}${apiPrefix}/${this.swaggerPath}
|
|
145
|
+
http://${domain}:${port}${apiPrefix}/${this.swaggerPath}
|
|
146
|
+
${address}/${this.swaggerPath}
|
|
147
|
+
JSON: http://localhost:${port}${apiPrefix}/${this.swaggerPath}/json`);
|
|
148
|
+
}
|
|
149
|
+
callback?.(port, host, domain);
|
|
150
|
+
});
|
|
151
|
+
const hmr = typeof module !== 'undefined' ? module.hot : undefined;
|
|
152
|
+
if (hmr) {
|
|
153
|
+
console.debug('Hot reload enabled. Reloading...');
|
|
154
|
+
hmr.accept();
|
|
155
|
+
hmr.dispose(() => this.closeApp());
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.AppBootstrap = AppBootstrap;
|
|
160
|
+
function sanitizeSwaggerPath(path) {
|
|
161
|
+
const normalized = (path ?? 'api').replace(/^\/+/, '').replace(/\/+$/, '');
|
|
162
|
+
return normalized || 'api';
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=app-bootstrap.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-bootstrap.helper.js","sourceRoot":"","sources":["app-bootstrap.helper.ts"],"names":[],"mappings":"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"}
|