@lenne.tech/nest-server 8.6.18 → 8.6.21
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/dist/config.env.js +4 -2
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/helpers/common.helper.d.ts +2 -0
- package/dist/core/common/helpers/common.helper.js +16 -0
- package/dist/core/common/helpers/common.helper.js.map +1 -0
- package/dist/core/common/helpers/model.helper.js +24 -18
- package/dist/core/common/helpers/model.helper.js.map +1 -1
- package/dist/core/common/interfaces/cron-job-config.interface.d.ts +2 -0
- package/dist/core/common/services/core-cron-jobs.service.d.ts +1 -0
- package/dist/core/common/services/core-cron-jobs.service.js +34 -9
- package/dist/core/common/services/core-cron-jobs.service.js.map +1 -1
- package/dist/core/common/services/module.service.js +4 -1
- package/dist/core/common/services/module.service.js.map +1 -1
- package/dist/core/common/types/remove-methods.type.d.ts +3 -0
- package/dist/core/common/types/remove-methods.type.js +3 -0
- package/dist/core/common/types/remove-methods.type.js.map +1 -0
- package/dist/core/common/types/string-or-object-id.type.d.ts +1 -1
- package/dist/core/modules/file/core-file.service.d.ts +2 -2
- package/dist/core/modules/file/core-file.service.js.map +1 -1
- package/dist/core/modules/file/interfaces/file-service-options.interface.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/server/common/services/cron-jobs.service.d.ts +1 -1
- package/dist/server/common/services/cron-jobs.service.js +4 -1
- package/dist/server/common/services/cron-jobs.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/config.env.ts +4 -2
- package/src/core/common/helpers/common.helper.ts +18 -0
- package/src/core/common/helpers/model.helper.ts +22 -20
- package/src/core/common/interfaces/cron-job-config.interface.ts +15 -2
- package/src/core/common/services/core-cron-jobs.service.ts +48 -9
- package/src/core/common/services/module.service.ts +6 -1
- package/src/core/common/types/plain-input.type.ts +1 -1
- package/src/core/common/types/remove-methods.type.ts +4 -0
- package/src/core/common/types/string-or-object-id.type.ts +4 -1
- package/src/core/modules/file/core-file.service.ts +2 -2
- package/src/core/modules/file/interfaces/file-service-options.interface.ts +1 -0
- package/src/index.ts +2 -0
- package/src/server/common/services/cron-jobs.service.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "8.6.
|
|
3
|
+
"version": "8.6.21",
|
|
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",
|
package/src/config.env.ts
CHANGED
|
@@ -12,9 +12,11 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
12
12
|
local: {
|
|
13
13
|
cronJobs: {
|
|
14
14
|
sayHello: {
|
|
15
|
-
cronTime: CronExpression.
|
|
16
|
-
timeZone: 'Europe/Berlin',
|
|
15
|
+
cronTime: CronExpression.EVERY_10_SECONDS,
|
|
17
16
|
runOnInit: false,
|
|
17
|
+
runParallel: 1,
|
|
18
|
+
timeZone: 'Europe/Berlin',
|
|
19
|
+
throwException: false,
|
|
18
20
|
},
|
|
19
21
|
},
|
|
20
22
|
email: {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wait a certain number of milliseconds
|
|
3
|
+
*/
|
|
4
|
+
export function sleep(ms: number) {
|
|
5
|
+
return new Promise<void>((resolve) => {
|
|
6
|
+
setTimeout(() => {
|
|
7
|
+
resolve();
|
|
8
|
+
}, ms);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Wait a certain number of milliseconds
|
|
14
|
+
* Alias of sleep
|
|
15
|
+
*/
|
|
16
|
+
export function wait(ms: number) {
|
|
17
|
+
return sleep(ms);
|
|
18
|
+
}
|
|
@@ -175,9 +175,10 @@ export function mapClasses<T = Record<string, any>>(
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
// Process input
|
|
178
|
-
for (const [prop,
|
|
179
|
-
if (prop in
|
|
180
|
-
const targetClass =
|
|
178
|
+
for (const [prop, mapTarget] of Object.entries(mapping)) {
|
|
179
|
+
if (prop in input) {
|
|
180
|
+
const targetClass = mapTarget as any;
|
|
181
|
+
const value = input[prop];
|
|
181
182
|
|
|
182
183
|
// Process array
|
|
183
184
|
if (Array.isArray(value)) {
|
|
@@ -185,13 +186,12 @@ export function mapClasses<T = Record<string, any>>(
|
|
|
185
186
|
for (const item of value) {
|
|
186
187
|
if (value instanceof targetClass) {
|
|
187
188
|
arr.push(value);
|
|
188
|
-
}
|
|
189
|
-
if (value instanceof Types.ObjectId) {
|
|
189
|
+
} else if (value instanceof Types.ObjectId) {
|
|
190
190
|
arr.push(value);
|
|
191
191
|
} else if (typeof value === 'object') {
|
|
192
192
|
if (targetClass.map) {
|
|
193
193
|
arr.push(targetClass.map(item));
|
|
194
|
-
} else
|
|
194
|
+
} else {
|
|
195
195
|
arr.push(plainToInstance(targetClass, item));
|
|
196
196
|
}
|
|
197
197
|
} else {
|
|
@@ -210,11 +210,12 @@ export function mapClasses<T = Record<string, any>>(
|
|
|
210
210
|
else if (typeof value === 'object') {
|
|
211
211
|
if (value instanceof targetClass) {
|
|
212
212
|
target[prop] = value as any;
|
|
213
|
-
}
|
|
214
|
-
if (targetClass.map) {
|
|
215
|
-
target[prop] = targetClass.map(value);
|
|
216
213
|
} else {
|
|
217
|
-
|
|
214
|
+
if (targetClass.map) {
|
|
215
|
+
target[prop] = targetClass.map(value);
|
|
216
|
+
} else {
|
|
217
|
+
target[prop] = plainToInstance(targetClass, value) as any;
|
|
218
|
+
}
|
|
218
219
|
}
|
|
219
220
|
}
|
|
220
221
|
|
|
@@ -250,9 +251,10 @@ export async function mapClassesAsync<T = Record<string, any>>(
|
|
|
250
251
|
}
|
|
251
252
|
|
|
252
253
|
// Process input
|
|
253
|
-
for (const [prop,
|
|
254
|
-
if (prop in
|
|
255
|
-
const targetClass =
|
|
254
|
+
for (const [prop, mapTarget] of Object.entries(mapping)) {
|
|
255
|
+
if (prop in input) {
|
|
256
|
+
const targetClass = mapTarget as any;
|
|
257
|
+
const value = input[prop];
|
|
256
258
|
|
|
257
259
|
// Process array
|
|
258
260
|
if (Array.isArray(value)) {
|
|
@@ -260,13 +262,12 @@ export async function mapClassesAsync<T = Record<string, any>>(
|
|
|
260
262
|
for (const item of value) {
|
|
261
263
|
if (value instanceof targetClass) {
|
|
262
264
|
arr.push(value);
|
|
263
|
-
}
|
|
264
|
-
if (value instanceof Types.ObjectId) {
|
|
265
|
+
} else if (value instanceof Types.ObjectId) {
|
|
265
266
|
arr.push(value);
|
|
266
267
|
} else if (typeof value === 'object') {
|
|
267
268
|
if (targetClass.map) {
|
|
268
269
|
arr.push(await targetClass.map(item));
|
|
269
|
-
} else
|
|
270
|
+
} else {
|
|
270
271
|
arr.push(plainToInstance(targetClass, item));
|
|
271
272
|
}
|
|
272
273
|
} else {
|
|
@@ -285,11 +286,12 @@ export async function mapClassesAsync<T = Record<string, any>>(
|
|
|
285
286
|
else if (typeof value === 'object') {
|
|
286
287
|
if (value instanceof targetClass) {
|
|
287
288
|
target[prop] = value as any;
|
|
288
|
-
}
|
|
289
|
-
if (targetClass.map) {
|
|
290
|
-
target[prop] = await targetClass.map(value);
|
|
291
289
|
} else {
|
|
292
|
-
|
|
290
|
+
if (targetClass.map) {
|
|
291
|
+
target[prop] = await targetClass.map(value);
|
|
292
|
+
} else {
|
|
293
|
+
target[prop] = plainToInstance(targetClass, value) as any;
|
|
294
|
+
}
|
|
293
295
|
}
|
|
294
296
|
}
|
|
295
297
|
|
|
@@ -24,11 +24,24 @@ export interface CronJobConfig {
|
|
|
24
24
|
onComplete?: CronCommand | null;
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* This will immediately fire your `onTickfunction as soon as the requisit initialization has happened.
|
|
28
|
-
* This option is set to
|
|
27
|
+
* This will immediately fire your `onTickfunction` as soon as the requisit initialization has happened.
|
|
28
|
+
* This option is set to `true` by default.
|
|
29
29
|
*/
|
|
30
30
|
runOnInit?: boolean;
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Depending on how long the execution of a job takes, it may happen that several executions take place at the
|
|
34
|
+
* same time. This can be prevented with `runParallel = false`.This option is set to `true` by default.
|
|
35
|
+
* If a number is specified, it is used as the number of maximum parallel executions.
|
|
36
|
+
*/
|
|
37
|
+
runParallel?: boolean | number;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Whether an exception is thrown or only acknowledged with a console.error.
|
|
41
|
+
* This option is set to `true` by default.
|
|
42
|
+
*/
|
|
43
|
+
throwException?: boolean;
|
|
44
|
+
|
|
32
45
|
/**
|
|
33
46
|
* Specify the timezone for the execution. This will modify the actual time relative to your timezone.
|
|
34
47
|
* If the timezone is invalid, an error is thrown. Can be any string accepted by luxon's `DateTime.setZone()`
|
|
@@ -15,6 +15,11 @@ export abstract class CoreCronJobs {
|
|
|
15
15
|
log: boolean;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Cron jobs that are currently running
|
|
20
|
+
*/
|
|
21
|
+
runningJobs: Record<string, Date[]> = {};
|
|
22
|
+
|
|
18
23
|
// ===================================================================================================================
|
|
19
24
|
// Initializations
|
|
20
25
|
// ===================================================================================================================
|
|
@@ -51,18 +56,20 @@ export abstract class CoreCronJobs {
|
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
// Prepare config
|
|
54
|
-
let
|
|
55
|
-
if (typeof
|
|
56
|
-
|
|
57
|
-
cronTime:
|
|
59
|
+
let conf: CronExpression | string | Date | Falsy | CronJobConfig = CronExpressionOrConfig;
|
|
60
|
+
if (typeof conf === 'string' || conf instanceof Date) {
|
|
61
|
+
conf = {
|
|
62
|
+
cronTime: conf,
|
|
58
63
|
};
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
// Set defaults
|
|
62
|
-
config = {
|
|
63
|
-
timeZone: 'Europe/Berlin',
|
|
67
|
+
const config: CronJobConfig = {
|
|
64
68
|
runOnInit: true,
|
|
65
|
-
|
|
69
|
+
runParallel: true,
|
|
70
|
+
throwException: true,
|
|
71
|
+
timeZone: 'Europe/Berlin',
|
|
72
|
+
...conf,
|
|
66
73
|
};
|
|
67
74
|
|
|
68
75
|
// Check if cron job should be activated
|
|
@@ -81,8 +88,40 @@ export abstract class CoreCronJobs {
|
|
|
81
88
|
// Init cron job
|
|
82
89
|
const job = new CronJob(
|
|
83
90
|
config.cronTime,
|
|
84
|
-
() => {
|
|
85
|
-
|
|
91
|
+
async () => {
|
|
92
|
+
// Get current processes of cron job
|
|
93
|
+
const dates = this.runningJobs[name];
|
|
94
|
+
|
|
95
|
+
// Check if parallel execution is allowed and if so how many can run in parallel
|
|
96
|
+
if (
|
|
97
|
+
dates?.length &&
|
|
98
|
+
(!config.runParallel || (typeof config.runParallel === 'number' && dates.length >= config.runParallel))
|
|
99
|
+
) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Prepare the acquisition of parallel job executions
|
|
104
|
+
if (!this.runningJobs[name]) {
|
|
105
|
+
this.runningJobs[name] = [];
|
|
106
|
+
}
|
|
107
|
+
const date = new Date();
|
|
108
|
+
this.runningJobs[name].push(date);
|
|
109
|
+
|
|
110
|
+
// Execute the job and wait until job process is done
|
|
111
|
+
try {
|
|
112
|
+
await this[name]();
|
|
113
|
+
} catch (e) {
|
|
114
|
+
// Remove job from running list
|
|
115
|
+
this.runningJobs[name] = this.runningJobs[name].filter((item) => item !== date);
|
|
116
|
+
if (config.throwException) {
|
|
117
|
+
throw e;
|
|
118
|
+
} else {
|
|
119
|
+
console.error(e);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Remove job from running list
|
|
124
|
+
this.runningJobs[name] = this.runningJobs[name].filter((item) => item !== date);
|
|
86
125
|
},
|
|
87
126
|
null,
|
|
88
127
|
true,
|
|
@@ -107,6 +107,11 @@ export abstract class ModuleService<T extends CoreModel = any> {
|
|
|
107
107
|
config.input = await this.prepareInput(config.input, opts);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
// Check rights
|
|
111
|
+
if (config.checkRights && this.checkRights) {
|
|
112
|
+
await this.checkRights(undefined, config.currentUser as any, config);
|
|
113
|
+
}
|
|
114
|
+
|
|
110
115
|
// Get DB object
|
|
111
116
|
if (config.dbObject && config.checkRights && this.checkRights) {
|
|
112
117
|
if (typeof config.dbObject === 'string' || config.dbObject instanceof Types.ObjectId) {
|
|
@@ -144,7 +149,7 @@ export abstract class ModuleService<T extends CoreModel = any> {
|
|
|
144
149
|
}
|
|
145
150
|
|
|
146
151
|
// Check output rights
|
|
147
|
-
if (config.checkRights && this.checkRights) {
|
|
152
|
+
if (config.checkRights && (await this.checkRights(undefined, config.currentUser as any, config))) {
|
|
148
153
|
const opts: any = {
|
|
149
154
|
dbObject: config.dbObject,
|
|
150
155
|
processType: ProcessType.OUTPUT,
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import { Types } from 'mongoose';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Everything which will be used by getStringIds or getObjectIds (see helpers/db.helper.ts)
|
|
5
|
+
*/
|
|
6
|
+
export type StringOrObjectId<T = any> = string | Types.ObjectId | T;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NotFoundException } from '@nestjs/common';
|
|
2
|
-
import { GridFSBucket, GridFSBucketReadStreamOptions } from 'mongodb';
|
|
2
|
+
import { GridFSBucket, GridFSBucketReadStream, GridFSBucketReadStreamOptions } from 'mongodb';
|
|
3
3
|
import { Connection, Types } from 'mongoose';
|
|
4
4
|
import { createBucket, MongoGridFSOptions, MongooseGridFS } from 'mongoose-gridfs';
|
|
5
5
|
import { FilterArgs } from '../../common/args/filter.args';
|
|
@@ -115,7 +115,7 @@ export abstract class CoreFileService {
|
|
|
115
115
|
if (!(await this.checkRights(id, { ...serviceOptions, checkInputType: 'id' }))) {
|
|
116
116
|
return null;
|
|
117
117
|
}
|
|
118
|
-
return this.files.openDownloadStream(getObjectIds(id));
|
|
118
|
+
return this.files.openDownloadStream(getObjectIds(id)) as GridFSBucketReadStream;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/**
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ export * from './core/common/enums/logical-operator.enum';
|
|
|
18
18
|
export * from './core/common/enums/process-type.enum';
|
|
19
19
|
export * from './core/common/enums/role.enum';
|
|
20
20
|
export * from './core/common/enums/sort-order.emum';
|
|
21
|
+
export * from './core/common/helpers/common.helper';
|
|
21
22
|
export * from './core/common/helpers/config.helper';
|
|
22
23
|
export * from './core/common/helpers/context.helper';
|
|
23
24
|
export * from './core/common/helpers/db.helper';
|
|
@@ -61,6 +62,7 @@ export * from './core/common/types/field-selection.type';
|
|
|
61
62
|
export * from './core/common/types/ids.type';
|
|
62
63
|
export * from './core/common/types/maybe-promise.type';
|
|
63
64
|
export * from './core/common/types/plain-input.type';
|
|
65
|
+
export * from './core/common/types/remove-methods.type';
|
|
64
66
|
export * from './core/common/types/require-only-one.type';
|
|
65
67
|
export * from './core/common/types/required-at-least-one.type';
|
|
66
68
|
export * from './core/common/types/string-or-object-id.type';
|
|
@@ -20,7 +20,10 @@ export class CronJobs extends CoreCronJobs {
|
|
|
20
20
|
// Cron jobs
|
|
21
21
|
// ===================================================================================================================
|
|
22
22
|
|
|
23
|
-
protected sayHello() {
|
|
23
|
+
protected async sayHello() {
|
|
24
24
|
console.log('Hello :)');
|
|
25
|
+
await new Promise<void>((resolve) => {
|
|
26
|
+
setTimeout(() => resolve(), 30000);
|
|
27
|
+
});
|
|
25
28
|
}
|
|
26
29
|
}
|