@lenne.tech/nest-server 10.0.3 → 10.0.5
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/README.md +38 -0
- package/dist/config.env.js +18 -0
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/helpers/filter.helper.js +14 -7
- package/dist/core/common/helpers/filter.helper.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +6 -4
- package/dist/core/common/services/model-doc.service.d.ts +16 -0
- package/dist/core/common/services/model-doc.service.js +107 -0
- package/dist/core/common/services/model-doc.service.js.map +1 -0
- package/dist/core/modules/health-check/core-health-check.service.js +6 -6
- package/dist/core/modules/health-check/core-health-check.service.js.map +1 -1
- package/dist/core/modules/user/core-user.model.js +1 -1
- package/dist/core/modules/user/core-user.model.js.map +1 -1
- package/dist/core.module.js +6 -0
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +20 -17
- package/src/config.env.ts +18 -0
- package/src/core/common/helpers/filter.helper.ts +18 -9
- package/src/core/common/interfaces/server-options.interface.ts +99 -5
- package/src/core/common/services/model-doc.service.ts +140 -0
- package/src/core/modules/health-check/core-health-check.service.ts +8 -6
- package/src/core/modules/user/core-user.model.ts +1 -1
- package/src/core.module.ts +13 -2
- package/src/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "10.0.
|
|
3
|
+
"version": "10.0.5",
|
|
4
4
|
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"build": "rimraf dist && nest build",
|
|
18
18
|
"build:pack": "npm pack && echo 'use file:/ROOT_PATH_TO_TGZ_FILE to integrate the package'",
|
|
19
19
|
"build:dev": "npm run build && yalc push --private",
|
|
20
|
-
"docs": "npm run docs:ci && open ./public/index.html",
|
|
20
|
+
"docs": "npm run docs:ci && open http://127.0.0.1:8080/ && open ./public/index.html && compodoc -p tsconfig.json -s ",
|
|
21
21
|
"docs:bootstrap": "node extras/update-spectaql-version.mjs && npx -y spectaql ./spectaql.yml",
|
|
22
|
-
"docs:ci": "ts-node ./scripts/init-server.ts && npm run docs:bootstrap",
|
|
22
|
+
"docs:ci": "ts-node ./scripts/init-server.ts && npm run docs:bootstrap && compodoc -p tsconfig.json",
|
|
23
23
|
"format": "prettier --write 'src/**/*.ts'",
|
|
24
24
|
"format:staged": "pretty-quick --staged",
|
|
25
25
|
"lint": "eslint \"{src,tests}/**/*.ts\" --fix",
|
|
@@ -71,8 +71,8 @@
|
|
|
71
71
|
"@nestjs/mongoose": "10.0.1",
|
|
72
72
|
"@nestjs/passport": "10.0.0",
|
|
73
73
|
"@nestjs/platform-express": "10.1.3",
|
|
74
|
-
"@nestjs/schedule": "3.0.
|
|
75
|
-
"@nestjs/terminus": "
|
|
74
|
+
"@nestjs/schedule": "3.0.2",
|
|
75
|
+
"@nestjs/terminus": "10.0.1",
|
|
76
76
|
"apollo-server-core": "3.11.1",
|
|
77
77
|
"apollo-server-express": "3.11.1",
|
|
78
78
|
"bcrypt": "5.1.0",
|
|
@@ -102,34 +102,37 @@
|
|
|
102
102
|
"reflect-metadata": "0.1.13",
|
|
103
103
|
"rfdc": "1.3.0",
|
|
104
104
|
"rimraf": "5.0.1",
|
|
105
|
-
"rxjs": "7.8.1"
|
|
105
|
+
"rxjs": "7.8.1",
|
|
106
|
+
"yuml-diagram": "1.2.0"
|
|
106
107
|
},
|
|
107
108
|
"devDependencies": {
|
|
108
|
-
"@
|
|
109
|
+
"@babel/plugin-proposal-private-methods": "7.18.6",
|
|
110
|
+
"@compodoc/compodoc": "1.1.21",
|
|
111
|
+
"@lenne.tech/eslint-config-ts": "0.0.9",
|
|
109
112
|
"@nestjs/cli": "10.1.11",
|
|
110
|
-
"@nestjs/schematics": "10.0.
|
|
113
|
+
"@nestjs/schematics": "10.0.2",
|
|
111
114
|
"@nestjs/testing": "10.1.3",
|
|
112
115
|
"@swc/cli": "0.1.62",
|
|
113
|
-
"@swc/core": "1.3.
|
|
114
|
-
"@swc/jest": "0.2.
|
|
116
|
+
"@swc/core": "1.3.76",
|
|
117
|
+
"@swc/jest": "0.2.28",
|
|
115
118
|
"@types/compression": "1.7.2",
|
|
116
119
|
"@types/cookie-parser": "1.4.3",
|
|
117
120
|
"@types/cron": "2.0.1",
|
|
118
121
|
"@types/ejs": "3.1.2",
|
|
119
122
|
"@types/express": "4.17.17",
|
|
120
123
|
"@types/jest": "29.5.3",
|
|
121
|
-
"@types/lodash": "4.14.
|
|
124
|
+
"@types/lodash": "4.14.197",
|
|
122
125
|
"@types/multer": "1.4.7",
|
|
123
|
-
"@types/node": "20.4.
|
|
126
|
+
"@types/node": "20.4.9",
|
|
124
127
|
"@types/nodemailer": "6.4.9",
|
|
125
128
|
"@types/passport": "1.0.12",
|
|
126
129
|
"@types/supertest": "2.0.12",
|
|
127
|
-
"@typescript-eslint/eslint-plugin": "6.
|
|
128
|
-
"@typescript-eslint/parser": "6.
|
|
130
|
+
"@typescript-eslint/eslint-plugin": "6.3.0",
|
|
131
|
+
"@typescript-eslint/parser": "6.3.0",
|
|
129
132
|
"coffeescript": "2.7.0",
|
|
130
133
|
"eslint": "8.46.0",
|
|
131
|
-
"eslint-config-prettier": "
|
|
132
|
-
"eslint-plugin-unused-imports": "
|
|
134
|
+
"eslint-config-prettier": "9.0.0",
|
|
135
|
+
"eslint-plugin-unused-imports": "3.0.0",
|
|
133
136
|
"find-file-up": "2.0.1",
|
|
134
137
|
"grunt": "1.6.1",
|
|
135
138
|
"grunt-bg-shell": "2.3.3",
|
|
@@ -140,7 +143,7 @@
|
|
|
140
143
|
"jest": "29.6.2",
|
|
141
144
|
"npm-watch": "0.11.0",
|
|
142
145
|
"pm2": "5.3.0",
|
|
143
|
-
"prettier": "3.0.
|
|
146
|
+
"prettier": "3.0.1",
|
|
144
147
|
"pretty-quick": "3.1.3",
|
|
145
148
|
"supertest": "6.3.3",
|
|
146
149
|
"ts-jest": "29.1.1",
|
package/src/config.env.ts
CHANGED
|
@@ -57,6 +57,11 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
57
57
|
},
|
|
58
58
|
healthCheck: {
|
|
59
59
|
enabled: true,
|
|
60
|
+
configs: {
|
|
61
|
+
database: {
|
|
62
|
+
enabled: true,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
60
65
|
},
|
|
61
66
|
ignoreSelectionsForPopulate: true,
|
|
62
67
|
jwt: {
|
|
@@ -78,6 +83,7 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
78
83
|
collation: {
|
|
79
84
|
locale: 'de',
|
|
80
85
|
},
|
|
86
|
+
modelDocumentation: true,
|
|
81
87
|
uri: 'mongodb://127.0.0.1/nest-server-local',
|
|
82
88
|
},
|
|
83
89
|
port: 3000,
|
|
@@ -133,6 +139,11 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
133
139
|
},
|
|
134
140
|
healthCheck: {
|
|
135
141
|
enabled: true,
|
|
142
|
+
configs: {
|
|
143
|
+
database: {
|
|
144
|
+
enabled: true,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
136
147
|
},
|
|
137
148
|
ignoreSelectionsForPopulate: true,
|
|
138
149
|
jwt: {
|
|
@@ -154,6 +165,7 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
154
165
|
collation: {
|
|
155
166
|
locale: 'de',
|
|
156
167
|
},
|
|
168
|
+
modelDocumentation: false,
|
|
157
169
|
uri: 'mongodb://127.0.0.1/nest-server-dev',
|
|
158
170
|
},
|
|
159
171
|
port: 3000,
|
|
@@ -209,6 +221,11 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
209
221
|
},
|
|
210
222
|
healthCheck: {
|
|
211
223
|
enabled: true,
|
|
224
|
+
configs: {
|
|
225
|
+
database: {
|
|
226
|
+
enabled: true,
|
|
227
|
+
},
|
|
228
|
+
},
|
|
212
229
|
},
|
|
213
230
|
ignoreSelectionsForPopulate: true,
|
|
214
231
|
jwt: {
|
|
@@ -230,6 +247,7 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
230
247
|
collation: {
|
|
231
248
|
locale: 'de',
|
|
232
249
|
},
|
|
250
|
+
modelDocumentation: false,
|
|
233
251
|
uri: 'mongodb://127.0.0.1/nest-server-prod',
|
|
234
252
|
},
|
|
235
253
|
port: 3000,
|
|
@@ -90,8 +90,10 @@ export function findFilter(options?: {
|
|
|
90
90
|
|
|
91
91
|
// Optimizations
|
|
92
92
|
if (!filterOptions[config.type].length) {
|
|
93
|
+
// If there are no conditions, return an empty object
|
|
93
94
|
filterOptions = {};
|
|
94
95
|
} else if (filterOptions[config.type].length === 1) {
|
|
96
|
+
// if there is only one condition, integrate it directly into the filter options
|
|
95
97
|
const additionalProperties = filterOptions[config.type][0];
|
|
96
98
|
delete filterOptions[config.type];
|
|
97
99
|
assignPlain(filterOptions, additionalProperties);
|
|
@@ -150,22 +152,29 @@ export function generateFilterQuery<T = any>(
|
|
|
150
152
|
// Process single filter
|
|
151
153
|
if (filter.singleFilter) {
|
|
152
154
|
// Init variables
|
|
153
|
-
const { not, options,
|
|
155
|
+
const { not, options, convertToObjectId, isReference } = filter.singleFilter;
|
|
156
|
+
let field = filter.singleFilter.field;
|
|
154
157
|
let value = filter.singleFilter.value;
|
|
155
158
|
|
|
156
|
-
// Convert value to object ID(s)
|
|
159
|
+
// Convert value to object ID(s), but don't change the name or the filter itself
|
|
157
160
|
if (convertToObjectId || isReference) {
|
|
158
161
|
value = getObjectIds(value);
|
|
159
162
|
|
|
160
163
|
// Check if value is a string ID and automatic ObjectID filtering is activated
|
|
161
164
|
} else if (config.automaticObjectIdFiltering && checkStringIds(value)) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
if (field === 'id') {
|
|
166
|
+
// Replace field name id field with _id and convert value to ObjectId
|
|
167
|
+
field = '_id';
|
|
168
|
+
value = getObjectIds(value);
|
|
169
|
+
} else {
|
|
170
|
+
// For every other fields set both the string filter and the ObjectID filtering in an OR construction
|
|
171
|
+
const alternativeQuery = clone(filter.singleFilter, { circles: false });
|
|
172
|
+
alternativeQuery.value = getObjectIds(value);
|
|
173
|
+
const conf = Object.assign({}, config, { automaticObjectIdFiltering: false });
|
|
174
|
+
return {
|
|
175
|
+
$or: [generateFilterQuery(filter, conf), generateFilterQuery({ singleFilter: alternativeQuery }, conf)],
|
|
176
|
+
};
|
|
177
|
+
}
|
|
169
178
|
}
|
|
170
179
|
|
|
171
180
|
// Convert filter
|
|
@@ -60,7 +60,9 @@ export interface IJwt {
|
|
|
60
60
|
export interface IServerOptions {
|
|
61
61
|
/**
|
|
62
62
|
* Automatically detect ObjectIds in string values in FilterQueries
|
|
63
|
-
* and expand them as OR query with string and ObjectId
|
|
63
|
+
* and expand them as OR query with string and ObjectId.
|
|
64
|
+
* Fields with the name "id" are renamed to "_id" and the value is converted to ObjectId,
|
|
65
|
+
* without changing the filter into an OR combined filter.
|
|
64
66
|
* See generateFilterQuery in Filter helper (src/core/common/helpers/filter.helper.ts)
|
|
65
67
|
*/
|
|
66
68
|
automaticObjectIdFiltering?: boolean;
|
|
@@ -176,26 +178,98 @@ export interface IServerOptions {
|
|
|
176
178
|
* Whether to activate health check endpoints
|
|
177
179
|
*/
|
|
178
180
|
healthCheck?: {
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Whether health check is enabled
|
|
184
|
+
*/
|
|
179
185
|
enabled?: boolean;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Configuration of single health checks
|
|
189
|
+
*/
|
|
180
190
|
configs?: {
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Configuration for database health check
|
|
194
|
+
*/
|
|
181
195
|
database?: {
|
|
182
|
-
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Whether to enable the database health check
|
|
199
|
+
*/
|
|
200
|
+
enabled?: boolean;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Key in result JSON
|
|
204
|
+
*/
|
|
183
205
|
key?: string;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Database health check options
|
|
209
|
+
*/
|
|
184
210
|
options?: MongoosePingCheckSettings;
|
|
185
211
|
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Configuration for memory heap health check
|
|
215
|
+
*/
|
|
186
216
|
memoryHeap?: {
|
|
187
|
-
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Whether to enable the memory heap health check
|
|
220
|
+
*/
|
|
221
|
+
enabled?: boolean;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Key in result JSON
|
|
225
|
+
*/
|
|
188
226
|
key?: string;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Memory limit in bytes
|
|
230
|
+
*/
|
|
189
231
|
heapUsedThreshold?: number;
|
|
190
232
|
};
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Configuration for memory resident set size health check
|
|
236
|
+
*/
|
|
191
237
|
memoryRss?: {
|
|
192
|
-
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Whether to enable the memory resident set size health check
|
|
241
|
+
*/
|
|
242
|
+
enabled?: boolean;
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Key in result JSON
|
|
246
|
+
*/
|
|
193
247
|
key?: string;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Memory limit in bytes
|
|
251
|
+
*/
|
|
194
252
|
rssThreshold?: number;
|
|
195
253
|
};
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Configuration for disk space health check
|
|
257
|
+
*/
|
|
196
258
|
storage?: {
|
|
197
|
-
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Whether to enable the disk space health check
|
|
262
|
+
*/
|
|
263
|
+
enabled?: boolean;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Key in result JSON
|
|
267
|
+
*/
|
|
198
268
|
key?: string;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Disk health indicator options
|
|
272
|
+
*/
|
|
199
273
|
options?: DiskHealthIndicatorOptions;
|
|
200
274
|
};
|
|
201
275
|
};
|
|
@@ -247,8 +321,19 @@ export interface IServerOptions {
|
|
|
247
321
|
* Configuration for Mongoose
|
|
248
322
|
*/
|
|
249
323
|
mongoose?: {
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Collation allows users to specify language-specific rules for string comparison,
|
|
327
|
+
* such as rules for letter-case and accent marks.
|
|
328
|
+
*/
|
|
250
329
|
collation?: CollationOptions;
|
|
251
330
|
|
|
331
|
+
/**
|
|
332
|
+
* Whether to create SVG-Diagrams of mongoose models
|
|
333
|
+
* @beta
|
|
334
|
+
*/
|
|
335
|
+
modelDocumentation?: boolean;
|
|
336
|
+
|
|
252
337
|
/**
|
|
253
338
|
* Mongoose connection string
|
|
254
339
|
*/
|
|
@@ -258,6 +343,15 @@ export interface IServerOptions {
|
|
|
258
343
|
* Mongoose module options
|
|
259
344
|
*/
|
|
260
345
|
options?: MongooseModuleOptions;
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Mongoose supports a separate strictQuery option to avoid strict mode for query filters.
|
|
349
|
+
* This is because empty query filters cause Mongoose to return all documents in the model, which can cause issues.
|
|
350
|
+
* See: https://github.com/Automattic/mongoose/issues/10763
|
|
351
|
+
* and: https://mongoosejs.com/docs/guide.html#strictQuery
|
|
352
|
+
* default: false
|
|
353
|
+
*/
|
|
354
|
+
strictQuery?: boolean;
|
|
261
355
|
};
|
|
262
356
|
|
|
263
357
|
/**
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import fs = require('fs');
|
|
2
|
+
import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
|
|
3
|
+
import { InjectConnection } from '@nestjs/mongoose';
|
|
4
|
+
import { Connection } from 'mongoose';
|
|
5
|
+
import YumlDiagram = require('yuml-diagram');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Schema config for yUml creation
|
|
9
|
+
*/
|
|
10
|
+
export interface ModelDocSchemaConfig {
|
|
11
|
+
isArray: boolean;
|
|
12
|
+
name: string;
|
|
13
|
+
ref: string;
|
|
14
|
+
type: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Model documentation as yUML-SVG
|
|
19
|
+
*/
|
|
20
|
+
@Injectable()
|
|
21
|
+
export class ModelDocService implements OnApplicationBootstrap {
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
@InjectConnection() private readonly connection: Connection,
|
|
25
|
+
) {
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Lifecycle hook that is called right after the application has started.
|
|
30
|
+
*/
|
|
31
|
+
async onApplicationBootstrap() {
|
|
32
|
+
const schemaJson = this.getSchemaJson();
|
|
33
|
+
const yUml = this.jsonToYuml(schemaJson);
|
|
34
|
+
this.yUmlToSvg(yUml);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Analyse the mongoose database models and create JSON
|
|
39
|
+
* @protected
|
|
40
|
+
*/
|
|
41
|
+
protected getSchemaJson(): Record<string, Record<string, ModelDocSchemaConfig>> {
|
|
42
|
+
|
|
43
|
+
// Prepare results
|
|
44
|
+
const results: Record<string, Record<string, ModelDocSchemaConfig>> = {};
|
|
45
|
+
|
|
46
|
+
// Process models
|
|
47
|
+
const models = this.connection.modelNames();
|
|
48
|
+
for (const modelName of models) {
|
|
49
|
+
results[modelName] = {};
|
|
50
|
+
|
|
51
|
+
// Process schema
|
|
52
|
+
const schema = this.connection.model(modelName).schema;
|
|
53
|
+
Object.keys(schema.paths).forEach((key) => {
|
|
54
|
+
const obj: any = schema.obj[key] || {};
|
|
55
|
+
const path = schema.paths[key];
|
|
56
|
+
|
|
57
|
+
results[modelName][key] = {
|
|
58
|
+
isArray: path.instance === 'Array',
|
|
59
|
+
name: path.path,
|
|
60
|
+
ref: Array.isArray(obj) ? undefined : obj.ref,
|
|
61
|
+
type: path.instance === 'Array'
|
|
62
|
+
? Array.isArray(obj)
|
|
63
|
+
? obj[0]() === '' ? 'String' : obj[0]()
|
|
64
|
+
: typeof obj.type === 'function' ? obj.type.name : obj.type
|
|
65
|
+
: path.instance,
|
|
66
|
+
};
|
|
67
|
+
if (results[modelName][key].type === 'Mixed') {
|
|
68
|
+
results[modelName][key].type = 'JSON';
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Return results
|
|
74
|
+
return results;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Convert JSON to yUML
|
|
79
|
+
* @param json
|
|
80
|
+
* @protected
|
|
81
|
+
*/
|
|
82
|
+
protected jsonToYuml(json: Record<string, Record<string, ModelDocSchemaConfig>>) {
|
|
83
|
+
// Convert JSON to yUML
|
|
84
|
+
let yumlText = '// {type:class}';
|
|
85
|
+
for (const [modelName, properties] of Object.entries(json)) {
|
|
86
|
+
yumlText += `\n[${modelName} | `;
|
|
87
|
+
const refs = [];
|
|
88
|
+
let subYumlText = '';
|
|
89
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
90
|
+
let type = value.type;
|
|
91
|
+
if (value.isArray) {
|
|
92
|
+
type = `Array<${type}>`;
|
|
93
|
+
}
|
|
94
|
+
if (value.ref) {
|
|
95
|
+
refs.push(`[${modelName}]-${key}>[${value.ref}]`);
|
|
96
|
+
}
|
|
97
|
+
if (key.startsWith('__')) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (key === '_id') {
|
|
101
|
+
subYumlText = `id: ObjectId; ${subYumlText}`;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
subYumlText += `${key}: ${type}; `;
|
|
105
|
+
}
|
|
106
|
+
yumlText += `${subYumlText}]\n`;
|
|
107
|
+
for (const ref of refs) {
|
|
108
|
+
yumlText += `${ref}\n`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return yumlText;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Convert yUML to SVG
|
|
116
|
+
* @param yUmlText
|
|
117
|
+
* @protected
|
|
118
|
+
*/
|
|
119
|
+
protected yUmlToSvg(yUmlText: String) {
|
|
120
|
+
|
|
121
|
+
// Create diagrams
|
|
122
|
+
// see https://github.com/jaime-olivares/yuml-diagram
|
|
123
|
+
// and https://yuml.me/diagram/scruffy/class/samples
|
|
124
|
+
const yuml = new YumlDiagram();
|
|
125
|
+
const svgLightBg = yuml.processYumlDocument(yUmlText, false);
|
|
126
|
+
const svgDarkBg = yuml.processYumlDocument(yUmlText, true);
|
|
127
|
+
|
|
128
|
+
// Save diagrams
|
|
129
|
+
fs.writeFile('model-doc-light.svg', svgLightBg, (err) => {
|
|
130
|
+
if (err) {
|
|
131
|
+
console.error(err);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
fs.writeFile('model-doc-dark.svg', svgDarkBg, (err) => {
|
|
135
|
+
if (err) {
|
|
136
|
+
console.error(err);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -27,26 +27,28 @@ export class CoreHealthCheckService {
|
|
|
27
27
|
|
|
28
28
|
healthCheck(): Promise<HealthCheckResult> {
|
|
29
29
|
const healthIndicatorFunctions = [];
|
|
30
|
-
if (
|
|
30
|
+
if (this.config.get<boolean>('healthCheck.configs.database.enabled')) {
|
|
31
31
|
healthIndicatorFunctions.push(() =>
|
|
32
32
|
this.db.pingCheck(
|
|
33
33
|
this.config.get<string>('healthCheck.configs.database.key') ?? 'database',
|
|
34
34
|
this.config.get<MongoosePingCheckSettings>('healthCheck.configs.database.options') ?? { timeout: 300 },
|
|
35
35
|
));
|
|
36
36
|
}
|
|
37
|
-
if (
|
|
37
|
+
if (this.config.get<boolean>('healthCheck.configs.memoryHeap.enabled')) {
|
|
38
38
|
healthIndicatorFunctions.push(() => this.memory.checkHeap(
|
|
39
39
|
this.config.get<string>('healthCheck.configs.memoryHeap.key') ?? 'memoryHeap',
|
|
40
|
-
|
|
40
|
+
// memory in bytes (4GB default)
|
|
41
|
+
this.config.get<number>('healthCheck.configs.memoryHeap.heapUsedThreshold') ?? 4 * 1024 * 1024 * 1024,
|
|
41
42
|
));
|
|
42
43
|
}
|
|
43
|
-
if (
|
|
44
|
+
if (this.config.get<boolean>('healthCheck.configs.memoryRss.enabled')) {
|
|
44
45
|
healthIndicatorFunctions.push(() => this.memory.checkRSS(
|
|
45
46
|
this.config.get<string>('healthCheck.configs.memoryRss.key') ?? 'memoryRss',
|
|
46
|
-
|
|
47
|
+
// memory in bytes (4GB default)
|
|
48
|
+
this.config.get<number>('healthCheck.configs.memoryRss.rssThreshold') ?? 4 * 1024 * 1024 * 1024,
|
|
47
49
|
));
|
|
48
50
|
}
|
|
49
|
-
if (
|
|
51
|
+
if (this.config.get<boolean>('healthCheck.configs.storage.enabled')) {
|
|
50
52
|
healthIndicatorFunctions.push(() => this.disk.checkStorage(
|
|
51
53
|
this.config.get<string>('healthCheck.configs.storage.key') ?? 'storage',
|
|
52
54
|
this.config.get<DiskHealthIndicatorOptions>('healthCheck.configs.storage.options') ?? {
|
package/src/core.module.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { GraphQLModule } from '@nestjs/graphql';
|
|
|
5
5
|
import { MongooseModule } from '@nestjs/mongoose';
|
|
6
6
|
import { Context } from 'apollo-server-core';
|
|
7
7
|
import graphqlUploadExpress = require('graphql-upload/graphqlUploadExpress.js');
|
|
8
|
+
import mongoose from 'mongoose';
|
|
8
9
|
import { merge } from './core/common/helpers/config.helper';
|
|
9
10
|
import { IServerOptions } from './core/common/interfaces/server-options.interface';
|
|
10
11
|
import { MapAndValidatePipe } from './core/common/pipes/map-and-validate.pipe';
|
|
@@ -14,6 +15,7 @@ import { EmailService } from './core/common/services/email.service';
|
|
|
14
15
|
import { MailjetService } from './core/common/services/mailjet.service';
|
|
15
16
|
import { TemplateService } from './core/common/services/template.service';
|
|
16
17
|
import { CoreHealthCheckModule } from './core/modules/health-check/core-health-check.module';
|
|
18
|
+
import { ModelDocService } from './core/common/services/model-doc.service';
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
21
|
* Core module (dynamic)
|
|
@@ -127,14 +129,14 @@ export class CoreModule implements NestModule {
|
|
|
127
129
|
);
|
|
128
130
|
|
|
129
131
|
// Set providers
|
|
130
|
-
const providers = [
|
|
132
|
+
const providers: any[] = [
|
|
131
133
|
// The ConfigService provides access to the current configuration of the module
|
|
132
134
|
{
|
|
133
135
|
provide: ConfigService,
|
|
134
136
|
useValue: new ConfigService(config),
|
|
135
137
|
},
|
|
136
138
|
|
|
137
|
-
// [Global] Map plain objects to
|
|
139
|
+
// [Global] Map plain objects to meta-type and validate
|
|
138
140
|
{
|
|
139
141
|
provide: APP_PIPE,
|
|
140
142
|
useClass: MapAndValidatePipe,
|
|
@@ -149,6 +151,15 @@ export class CoreModule implements NestModule {
|
|
|
149
151
|
ComplexityPlugin,
|
|
150
152
|
];
|
|
151
153
|
|
|
154
|
+
if (config.mongoose?.modelDocumentation) {
|
|
155
|
+
providers.push(ModelDocService);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Set strict query to false by default
|
|
159
|
+
// See: https://github.com/Automattic/mongoose/issues/10763
|
|
160
|
+
// and: https://mongoosejs.com/docs/guide.html#strictQuery
|
|
161
|
+
mongoose.set('strictQuery', config.mongoose.strictQuery || false);
|
|
162
|
+
|
|
152
163
|
const imports: any[] = [
|
|
153
164
|
MongooseModule.forRoot(config.mongoose.uri, config.mongoose.options),
|
|
154
165
|
GraphQLModule.forRootAsync<ApolloDriverConfig>(
|
package/src/index.ts
CHANGED
|
@@ -64,6 +64,7 @@ export * from './core/common/services/core-cron-jobs.service';
|
|
|
64
64
|
export * from './core/common/services/crud.service';
|
|
65
65
|
export * from './core/common/services/email.service';
|
|
66
66
|
export * from './core/common/services/mailjet.service';
|
|
67
|
+
export * from './core/common/services/model-doc.service';
|
|
67
68
|
export * from './core/common/services/module.service';
|
|
68
69
|
export * from './core/common/services/template.service';
|
|
69
70
|
export * from './core/common/types/core-model-constructor.type';
|