@lenne.tech/nest-server 10.1.1 → 10.2.0

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.
Files changed (30) hide show
  1. package/dist/core/common/interfaces/cron-job-config-with-time-zone.interface.d.ts +6 -0
  2. package/dist/core/common/interfaces/cron-job-config-with-time-zone.interface.js +3 -0
  3. package/dist/core/common/interfaces/cron-job-config-with-time-zone.interface.js.map +1 -0
  4. package/dist/core/common/interfaces/cron-job-config-with-utc-offset.interface.d.ts +6 -0
  5. package/dist/core/common/interfaces/cron-job-config-with-utc-offset.interface.js +3 -0
  6. package/dist/core/common/interfaces/cron-job-config-with-utc-offset.interface.js.map +1 -0
  7. package/dist/core/common/interfaces/cron-job-config.interface.d.ts +9 -11
  8. package/dist/core/common/interfaces/server-options.interface.d.ts +3 -2
  9. package/dist/core/common/services/core-cron-jobs.service.d.ts +4 -3
  10. package/dist/core/common/services/core-cron-jobs.service.js +1 -1
  11. package/dist/core/common/services/core-cron-jobs.service.js.map +1 -1
  12. package/dist/core/common/services/crud.service.d.ts +10 -1
  13. package/dist/core/common/services/crud.service.js +16 -0
  14. package/dist/core/common/services/crud.service.js.map +1 -1
  15. package/dist/core/common/types/array-element.type.d.ts +1 -0
  16. package/dist/core/common/types/array-element.type.js +3 -0
  17. package/dist/core/common/types/array-element.type.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.js +3 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/tsconfig.build.tsbuildinfo +1 -1
  22. package/package.json +37 -38
  23. package/src/core/common/interfaces/cron-job-config-with-time-zone.interface.ts +23 -0
  24. package/src/core/common/interfaces/cron-job-config-with-utc-offset.interface.ts +24 -0
  25. package/src/core/common/interfaces/cron-job-config.interface.ts +10 -11
  26. package/src/core/common/interfaces/server-options.interface.ts +3 -2
  27. package/src/core/common/services/core-cron-jobs.service.ts +10 -7
  28. package/src/core/common/services/crud.service.ts +40 -2
  29. package/src/core/common/types/array-element.type.ts +5 -0
  30. package/src/index.ts +3 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "10.1.1",
3
+ "version": "10.2.0",
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",
@@ -62,21 +62,21 @@
62
62
  "node": ">= 16.13.0"
63
63
  },
64
64
  "dependencies": {
65
- "@apollo/gateway": "2.5.6",
65
+ "@apollo/gateway": "2.5.7",
66
66
  "@lenne.tech/mongoose-gridfs": "1.4.2",
67
67
  "@lenne.tech/multer-gridfs-storage": "5.0.6",
68
- "@nestjs/apollo": "12.0.9",
69
- "@nestjs/common": "10.2.7",
70
- "@nestjs/core": "10.2.7",
71
- "@nestjs/graphql": "12.0.9",
72
- "@nestjs/jwt": "10.1.1",
73
- "@nestjs/mongoose": "10.0.1",
68
+ "@nestjs/apollo": "12.0.11",
69
+ "@nestjs/common": "10.2.9",
70
+ "@nestjs/core": "10.2.9",
71
+ "@nestjs/graphql": "12.0.11",
72
+ "@nestjs/jwt": "10.2.0",
73
+ "@nestjs/mongoose": "10.0.2",
74
74
  "@nestjs/passport": "10.0.2",
75
- "@nestjs/platform-express": "10.2.7",
76
- "@nestjs/schedule": "3.0.4",
75
+ "@nestjs/platform-express": "10.2.9",
76
+ "@nestjs/schedule": "4.0.0",
77
77
  "@nestjs/terminus": "10.1.1",
78
- "apollo-server-core": "3.12.1",
79
- "apollo-server-express": "3.11.1",
78
+ "apollo-server-core": "3.13.0",
79
+ "apollo-server-express": "3.13.0",
80
80
  "bcrypt": "5.1.1",
81
81
  "class-transformer": "0.5.1",
82
82
  "class-validator": "0.14.0",
@@ -91,11 +91,11 @@
91
91
  "json-to-graphql-query": "2.2.5",
92
92
  "light-my-request": "5.11.0",
93
93
  "lodash": "4.17.21",
94
- "mongodb": "6.2.0",
95
- "mongoose": "7.6.3",
94
+ "mongodb": "6.3.0",
95
+ "mongoose": "7.6.5",
96
96
  "multer": "1.4.5-lts.1",
97
97
  "node-mailjet": "6.0.4",
98
- "nodemailer": "6.9.6",
98
+ "nodemailer": "6.9.7",
99
99
  "nodemon": "3.0.1",
100
100
  "passport": "0.6.0",
101
101
  "passport-jwt": "4.0.1",
@@ -109,28 +109,27 @@
109
109
  "@babel/plugin-proposal-private-methods": "7.18.6",
110
110
  "@compodoc/compodoc": "1.1.22",
111
111
  "@lenne.tech/eslint-config-ts": "0.0.10",
112
- "@nestjs/cli": "10.1.18",
113
- "@nestjs/schematics": "10.0.2",
114
- "@nestjs/testing": "10.2.7",
115
- "@swc/cli": "0.1.62",
116
- "@swc/core": "1.3.93",
112
+ "@nestjs/cli": "10.2.1",
113
+ "@nestjs/schematics": "10.0.3",
114
+ "@nestjs/testing": "10.2.9",
115
+ "@swc/cli": "0.1.63",
116
+ "@swc/core": "1.3.96",
117
117
  "@swc/jest": "0.2.29",
118
- "@types/compression": "1.7.4",
119
- "@types/cookie-parser": "1.4.5",
120
- "@types/cron": "2.0.1",
121
- "@types/ejs": "3.1.4",
122
- "@types/express": "4.17.20",
123
- "@types/jest": "29.5.6",
124
- "@types/lodash": "4.14.200",
125
- "@types/multer": "1.4.9",
126
- "@types/node": "20.8.7",
127
- "@types/nodemailer": "6.4.13",
128
- "@types/passport": "1.0.14",
129
- "@types/supertest": "2.0.15",
130
- "@typescript-eslint/eslint-plugin": "6.8.0",
131
- "@typescript-eslint/parser": "6.8.0",
118
+ "@types/compression": "1.7.5",
119
+ "@types/cookie-parser": "1.4.6",
120
+ "@types/ejs": "3.1.5",
121
+ "@types/express": "4.17.21",
122
+ "@types/jest": "29.5.8",
123
+ "@types/lodash": "4.14.201",
124
+ "@types/multer": "1.4.10",
125
+ "@types/node": "20.9.1",
126
+ "@types/nodemailer": "6.4.14",
127
+ "@types/passport": "1.0.15",
128
+ "@types/supertest": "2.0.16",
129
+ "@typescript-eslint/eslint-plugin": "6.11.0",
130
+ "@typescript-eslint/parser": "6.11.0",
132
131
  "coffeescript": "2.7.0",
133
- "eslint": "8.51.0",
132
+ "eslint": "8.54.0",
134
133
  "eslint-config-prettier": "9.0.0",
135
134
  "eslint-plugin-unused-imports": "3.0.0",
136
135
  "find-file-up": "2.0.1",
@@ -143,12 +142,12 @@
143
142
  "jest": "29.7.0",
144
143
  "npm-watch": "0.11.0",
145
144
  "pm2": "5.3.0",
146
- "prettier": "3.0.3",
145
+ "prettier": "3.1.0",
147
146
  "pretty-quick": "3.1.3",
148
147
  "supertest": "6.3.3",
149
148
  "ts-jest": "29.1.1",
150
- "ts-loader": "9.5.0",
151
- "ts-morph": "19.0.0",
149
+ "ts-loader": "9.5.1",
150
+ "ts-morph": "20.0.0",
152
151
  "ts-node": "10.9.1",
153
152
  "tsconfig-paths": "4.2.0",
154
153
  "typescript": "5.2.2",
@@ -0,0 +1,23 @@
1
+ import { CronJobParams, CronOnCompleteCommand } from 'cron';
2
+ import { CronJobConfig } from './cron-job-config.interface';
3
+
4
+ /**
5
+ * Interface for cron job configuration
6
+ *
7
+ * This config can define timezone but not utcOffset,
8
+ * if you want to use utcOffset, you have to use the CronJobConfigWithUtcOffset
9
+ */
10
+ export interface CronJobConfigWithTimeZone<OC extends CronOnCompleteCommand | null = null, C = null> extends CronJobConfig {
11
+ /**
12
+ * Specify the timezone for the execution. This will modify the actual time relative to your timezone.
13
+ * If the timezone is invalid, an error is thrown. Can be any string accepted by luxon's `DateTime.setZone()`
14
+ * (https://moment.github.io/luxon/api-docs/index.html#datetimesetzone).
15
+ */
16
+ timeZone?: CronJobParams<OC, C>['timeZone'];
17
+
18
+ /**
19
+ * This allows you to specify the offset of the timezone rather than using the `timeZone` parameter.
20
+ * Probably don't use both `timeZone` and `utcOffset` together or weird things may happen.
21
+ */
22
+ utcOffset?: null;
23
+ }
@@ -0,0 +1,24 @@
1
+ import { CronJobParams, CronOnCompleteCommand } from 'cron';
2
+ import { CronJobConfig } from './cron-job-config.interface';
3
+
4
+ /**
5
+ * Interface for cron job configuration
6
+ *
7
+ * This config can define utcOffset but not timezone,
8
+ * if you want to use timezone, you have to use the CronJobConfigWithTimezone
9
+ */
10
+ export interface CronJobConfigWithUtcOffset<OC extends CronOnCompleteCommand | null = null, C = null> extends CronJobConfig {
11
+
12
+ /**
13
+ * Specify the timezone for the execution. This will modify the actual time relative to your timezone.
14
+ * If the timezone is invalid, an error is thrown. Can be any string accepted by luxon's `DateTime.setZone()`
15
+ * (https://moment.github.io/luxon/api-docs/index.html#datetimesetzone).
16
+ */
17
+ timeZone?: null;
18
+
19
+ /**
20
+ * This allows you to specify the offset of the timezone rather than using the `timeZone` parameter.
21
+ * Probably don't use both `timeZone` and `utcOffset` together or weird things may happen.
22
+ */
23
+ utcOffset?: CronJobParams<OC, C>['unrefTimeout'];
24
+ }
@@ -1,22 +1,21 @@
1
- import { CronExpression } from '@nestjs/schedule';
2
- import { CronCommand } from 'cron';
3
- import { Falsy } from '../types/falsy.type';
1
+ import { CronJobParams, CronOnCompleteCommand } from 'cron';
4
2
 
5
3
  /**
6
4
  * Interface for cron job configuration
5
+ * @deprecated Use CronJobConfigWithTimeZone or CronJobConfigWithUtcOffset instead
7
6
  */
8
- export interface CronJobConfig {
7
+ export interface CronJobConfig<OC extends CronOnCompleteCommand | null = null, C = null> {
9
8
  /**
10
9
  * The context within which to execute the onTick method. This defaults to the cronjob itself allowing you to call
11
10
  * `this.stop()`. However, if you change this you'll have access to the functions and values within your context
12
11
  * object.
13
12
  */
14
- context?: any;
13
+ context?: CronJobParams<OC, C>['context'];
15
14
 
16
15
  /**
17
16
  * The time to fire off your job. This can be in the form of cron syntax or a JS `Date` object.
18
17
  */
19
- cronTime: CronExpression | string | Date | Falsy;
18
+ cronTime: CronJobParams<OC, C>['cronTime'];
20
19
 
21
20
  /**
22
21
  * Whether the cron job is disabled or not.
@@ -27,13 +26,13 @@ export interface CronJobConfig {
27
26
  /**
28
27
  * A function that will fire when the job is complete, when it is stopped.
29
28
  */
30
- onComplete?: CronCommand | null;
29
+ onComplete?: CronJobParams<OC, C>['onComplete'];
31
30
 
32
31
  /**
33
32
  * This will immediately fire the `onTick` function as soon as the requisite initialization has happened.
34
33
  * This option is set to `true` by default.
35
34
  */
36
- runOnInit?: boolean;
35
+ runOnInit?: CronJobParams<OC, C>['runOnInit'];
37
36
 
38
37
  /**
39
38
  * Depending on how long the execution of a job takes, it may happen that several executions take place at the
@@ -53,7 +52,7 @@ export interface CronJobConfig {
53
52
  * If the timezone is invalid, an error is thrown. Can be any string accepted by luxon's `DateTime.setZone()`
54
53
  * (https://moment.github.io/luxon/api-docs/index.html#datetimesetzone).
55
54
  */
56
- timeZone?: string;
55
+ timeZone?: CronJobParams<OC, C>['timeZone'] | null;
57
56
 
58
57
  /**
59
58
  * If you have code that keeps the event loop running and want to stop the node process when that finishes
@@ -61,11 +60,11 @@ export interface CronJobConfig {
61
60
  * cron will run as if it needs to control the event loop. For more information take a look at
62
61
  * timers#timers_timeout_unref from the NodeJS docs.
63
62
  */
64
- unrefTimeout?: boolean;
63
+ unrefTimeout?: CronJobParams<OC, C>['unrefTimeout'];
65
64
 
66
65
  /**
67
66
  * This allows you to specify the offset of the timezone rather than using the `timeZone` parameter.
68
67
  * Probably don't use both `timeZone` and `utcOffset` together or weird things may happen.
69
68
  */
70
- utcOffset?: string | number;
69
+ utcOffset?: CronJobParams<OC, C>['unrefTimeout'] | null;
71
70
  }
@@ -11,7 +11,8 @@ import * as SMTPTransport from 'nodemailer/lib/smtp-transport';
11
11
  import { MongoosePingCheckSettings } from '@nestjs/terminus/dist/health-indicator/database/mongoose.health';
12
12
  import { DiskHealthIndicatorOptions } from '@nestjs/terminus/dist/health-indicator/disk/disk-health-options.type';
13
13
  import { Falsy } from '../types/falsy.type';
14
- import { CronJobConfig } from './cron-job-config.interface';
14
+ import { CronJobConfigWithTimeZone } from './cron-job-config-with-time-zone.interface';
15
+ import { CronJobConfigWithUtcOffset } from './cron-job-config-with-utc-offset.interface';
15
16
  import { MailjetOptions } from './mailjet-options.interface';
16
17
 
17
18
  /**
@@ -85,7 +86,7 @@ export interface IServerOptions {
85
86
  * Cron jobs configuration object with the name of the cron job function as key
86
87
  * and the cron expression or config as value
87
88
  */
88
- cronJobs?: Record<string, CronExpression | string | Date | Falsy | CronJobConfig>;
89
+ cronJobs?: Record<string, CronExpression | string | Date | Falsy | CronJobConfigWithTimeZone | CronJobConfigWithUtcOffset>;
89
90
 
90
91
  /**
91
92
  * SMTP and template configuration for sending emails
@@ -1,7 +1,8 @@
1
1
  import { OnApplicationBootstrap } from '@nestjs/common';
2
2
  import { CronExpression, SchedulerRegistry } from '@nestjs/schedule';
3
3
  import { CronJob } from 'cron';
4
- import { CronJobConfig } from '../interfaces/cron-job-config.interface';
4
+ import { CronJobConfigWithTimeZone } from '../interfaces/cron-job-config-with-time-zone.interface';
5
+ import { CronJobConfigWithUtcOffset } from '../interfaces/cron-job-config-with-utc-offset.interface';
5
6
  import { Falsy } from '../types/falsy.type';
6
7
 
7
8
  /**
@@ -30,7 +31,7 @@ export abstract class CoreCronJobs implements OnApplicationBootstrap {
30
31
  */
31
32
  protected constructor(
32
33
  protected schedulerRegistry: SchedulerRegistry,
33
- protected cronJobs: Record<string, CronExpression | string | Date | Falsy | CronJobConfig>,
34
+ protected cronJobs: Record<string, CronExpression | string | Date | Falsy | CronJobConfigWithTimeZone | CronJobConfigWithUtcOffset>,
34
35
  options?: { log?: boolean },
35
36
  ) {
36
37
  this.config = {
@@ -64,13 +65,14 @@ export abstract class CoreCronJobs implements OnApplicationBootstrap {
64
65
  // Check config
65
66
  if (
66
67
  !CronExpressionOrConfig
67
- || (typeof CronExpressionOrConfig === 'object' && (CronExpressionOrConfig as CronJobConfig).disabled)
68
+ || (typeof CronExpressionOrConfig === 'object' && (CronExpressionOrConfig as CronJobConfigWithTimeZone).disabled)
68
69
  ) {
69
70
  continue;
70
71
  }
71
72
 
72
73
  // Prepare config
73
- let conf: CronJobConfig = (CronExpressionOrConfig as CronJobConfig);
74
+ let conf: CronJobConfigWithTimeZone | CronJobConfigWithUtcOffset
75
+ = CronExpressionOrConfig as CronJobConfigWithTimeZone | CronJobConfigWithUtcOffset;
74
76
  if (typeof CronExpressionOrConfig === 'string' || CronExpressionOrConfig instanceof Date) {
75
77
  conf = {
76
78
  cronTime: CronExpressionOrConfig as string | Date,
@@ -78,13 +80,14 @@ export abstract class CoreCronJobs implements OnApplicationBootstrap {
78
80
  }
79
81
 
80
82
  // Set defaults
81
- const config: CronJobConfig = {
83
+ // Declared as CronJobConfigWithTimeZone to avoid type errors, but it can also be CronJobConfigWithUtcOffset
84
+ const config: CronJobConfigWithTimeZone = {
82
85
  runOnInit: true,
83
86
  runParallel: true,
84
87
  throwException: true,
85
- timeZone: 'Europe/Berlin',
88
+ timeZone: conf.utcOffset ? null : 'Europe/Berlin',
86
89
  ...conf,
87
- };
90
+ } as unknown as CronJobConfigWithTimeZone;
88
91
 
89
92
  // Check if cron job should be activated
90
93
  if (!config?.cronTime) {
@@ -1,11 +1,13 @@
1
1
  import { NotFoundException } from '@nestjs/common';
2
- import { FilterQuery, PipelineStage, QueryOptions } from 'mongoose';
2
+ import { Document, FilterQuery, Model as MongooseModel, PipelineStage, Query, QueryOptions } from 'mongoose';
3
3
  import { FilterArgs } from '../args/filter.args';
4
- import { getStringIds } from '../helpers/db.helper';
4
+ import { getStringIds, popAndMap } from '../helpers/db.helper';
5
5
  import { convertFilterArgsToQuery } from '../helpers/filter.helper';
6
6
  import { mergePlain, prepareServiceOptionsForCreate } from '../helpers/input.helper';
7
7
  import { ServiceOptions } from '../interfaces/service-options.interface';
8
8
  import { CoreModel } from '../models/core-model.model';
9
+ import { ArrayElement } from '../types/array-element.type';
10
+ import { FieldSelection } from '../types/field-selection.type';
9
11
  import { PlainObject } from '../types/plain-object.type';
10
12
  import { ConfigService } from './config.service';
11
13
  import { ModuleService } from './module.service';
@@ -474,4 +476,40 @@ export abstract class CrudService<
474
476
  serviceOptions.prepareOutput = null;
475
477
  return this.deleteForce(id, serviceOptions);
476
478
  }
479
+
480
+ /**
481
+ * Populate, exec and map Mongoose query or document(s) with serviceOptions
482
+ * Generic T is the type of the returned object(s)
483
+ *
484
+ * @example const user = await this.populateAndProcessQuery<User>(User.findById(id), serviceOptions);
485
+ * @example const users = await this.populateAndProcessQuery<User[]>(User.find({name: {'$regex': 'ma'}}), serviceOptions);
486
+ */
487
+ async populateAndProcessQuery<T extends CoreModel | CoreModel[] = CoreModel>(
488
+ queryOrDocument: Query<unknown, unknown> | Document | Document[],
489
+ options?: {
490
+ fieldSelection?: FieldSelection;
491
+ ignoreSelections?: boolean;
492
+ modelClass?: new (...args: any[]) => ArrayElement<T>;
493
+ populate?: FieldSelection;
494
+ mongooseModel?: MongooseModel<any>;
495
+ },
496
+ ): Promise<T> {
497
+ const config = {
498
+ modelClass: this.mainModelConstructor,
499
+ mongooseModel: this.mainDbModel,
500
+ ...options,
501
+ };
502
+ let result: T;
503
+ if (config.fieldSelection || config.populate) {
504
+ result = (await popAndMap<ArrayElement<T>>(
505
+ queryOrDocument,
506
+ config.populate || config.fieldSelection,
507
+ config.modelClass as new (...args: any[]) => ArrayElement<T>,
508
+ config.mongooseModel)
509
+ ) as T;
510
+ } else if (queryOrDocument instanceof Query) {
511
+ result = (await queryOrDocument.exec()) as T;
512
+ }
513
+ return result;
514
+ }
477
515
  }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Get type of array elements
3
+ */
4
+ export type ArrayElement<ArrayType extends (unknown | unknown[])> =
5
+ ArrayType extends readonly (infer ElementType)[] ? ElementType : ArrayType;
package/src/index.ts CHANGED
@@ -42,6 +42,8 @@ export * from './core/common/interceptors/check-response.interceptor';
42
42
  export * from './core/common/interceptors/check-security.interceptor';
43
43
  export * from './core/common/interfaces/core-persistence-model.interface';
44
44
  export * from './core/common/interfaces/cron-job-config.interface';
45
+ export * from './core/common/interfaces/cron-job-config-with-time-zone.interface';
46
+ export * from './core/common/interfaces/cron-job-config-with-utc-offset.interface';
45
47
  export * from './core/common/interfaces/mailjet-options.interface';
46
48
  export * from './core/common/interfaces/prepare-input-options.interface';
47
49
  export * from './core/common/interfaces/prepare-output-options.interface';
@@ -67,6 +69,7 @@ export * from './core/common/services/mailjet.service';
67
69
  export * from './core/common/services/model-doc.service';
68
70
  export * from './core/common/services/module.service';
69
71
  export * from './core/common/services/template.service';
72
+ export * from './core/common/types/array-element.type';
70
73
  export * from './core/common/types/core-model-constructor.type';
71
74
  export * from './core/common/types/falsy.type';
72
75
  export * from './core/common/types/field-selection.type';