@nestjs/core 11.1.5 → 11.1.7

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 CHANGED
@@ -8,7 +8,7 @@
8
8
  <p align="center">A progressive <a href="https://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
9
9
  <p align="center">
10
10
  <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
11
- <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
11
+ <a href="https://github.com/nestjs/nest/blob/master/LICENSE" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
12
12
  <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
13
13
  <a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
14
14
  <a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
@@ -78,10 +78,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
78
78
  </tr>
79
79
  <tr>
80
80
  <td><a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/logos/snyk-logo-black.png" width="185" valign="middle" /></a></td>
81
- <td><a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/logos/fuse-logo.svg" width="105" valign="middle" /></a></td>
82
- <td><a href="https://ridicorp.com/career/" target="_blank"><img src="https://nestjs.com/img/logos/ridi-logo.svg" width="105" valign="middle" /></a></td>
83
81
  <td><a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://nestjs.com/img/logos/movavi-logo.svg" width="105" valign="middle" /></a></td>
84
- <td><a href="https://skunk.team" target="_blank"><img src="https://nestjs.com/img/logos/skunk-logo.png" height="60" valign="middle" /></a></td>
85
82
  </tr>
86
83
  </table>
87
84
 
@@ -91,10 +88,10 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
91
88
  <tr>
92
89
  <td><a href="https://www.mercedes-benz.com/" target="_blank"><img src="https://nestjs.com/img/logos/mercedes-logo.png" width="100" valign="middle" /></a></td>
93
90
  <td><a href="https://www.dinii.jp/" target="_blank"><img src="https://nestjs.com/img/logos/dinii-logo.png" width="65" valign="middle" /></a></td>
94
- <td><a href="https://bloodycase.com/?promocode=NEST" target="_blank"><img src="https://nestjs.com/img/logos/bloodycase-logo.png" width="65" valign="middle" /></a></td>
95
91
  <td><a href="https://handsontable.com/docs/react-data-grid/?utm_source=NestJS_GH&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024" target="_blank"><img src="https://nestjs.com/img/logos/handsontable-dark-logo.svg#2" width="150" valign="middle" /></a></td>
96
92
  <td align="center" valign="middle"><a href="https://www.itflashcards.com/" target="_blank"><img src="https://nestjs.com/img/logos/it_flashcards-logo.png" width="170" valign="middle" /></a></td>
97
93
  <td align="center" valign="middle"><a href="https://arcjet.com/?ref=nestjs" target="_blank"><img src="https://nestjs.com/img/logos/arcjet-logo.svg" width="170" valign="middle" /></a></td>
94
+ <td align="center" valign="middle"><a href="https://crawljobs.com" target="_blank"><img src="https://nestjs.com/img/logos/crawljobs-logo.svg" width="130" valign="middle" /></a></td>
98
95
  </tr>
99
96
  </table>
100
97
 
@@ -118,19 +115,16 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
118
115
  <td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/logos/triplecore-logo.svg" width="50" valign="middle" /></a></td>
119
116
  </tr>
120
117
  <tr>
121
- <td align="center" valign="middle"><a href="https://thecasinowizard.com/bonuses/no-deposit-bonuses/" target="_blank"><img src="https://nestjs.com/img/logos/casinowizard-logo.png" width="120" valign="middle" /></a></td>
122
118
  <td align="center" valign="middle"><a href="https://polygon-software.ch/" target="_blank"><img src="https://nestjs.com/img/logos/polygon-logo.svg" width="120" valign="middle" /></a></td>
123
119
  <td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/logos/boringowl-logo.svg" width="120" valign="middle" /></a></td>
124
120
  <td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/logos/nordbot-logo.png" width="120" valign="middle" /></a></td>
125
121
  <td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/logos/dopiosh-logo.png" width="50" valign="middle" /></a></td>
126
122
  <td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/logos/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
123
+ <td align="center" valign="middle"><a href="https://www.tripoffice.com/" target="_blank"><img src="https://nestjs.com/img/logos/tripoffice-logo.png" width="140" valign="middle" /></a></td>
127
124
  </tr>
128
125
  <tr>
129
- <td align="center" valign="middle"><a href="https://julienferand.dev/" target="_blank"><img src="https://nestjs.com/img/logos/julienferand-logo.jpeg" width="55" valign="middle" /></a></td>
130
- <td align="center" valign="middle"><a href="https://www.tripoffice.com/" target="_blank"><img src="https://nestjs.com/img/logos/tripoffice-logo.png" width="140" valign="middle" /></a></td>
131
126
  <td align="center" valign="middle"><a href="https://solcellsforetag.se/" target="_blank"><img src="https://nestjs.com/img/logos/solcellsforetag-logo.svg" width="140" valign="middle" /></a></td>
132
127
  <td align="center" valign="middle"><a href="https://www.route4me.com/" target="_blank"><img src="https://nestjs.com/img/logos/route4me-logo.svg" width="100" valign="middle" /></a></td>
133
- <td align="center" valign="middle"><a href="https://www.slotsup.com/" target="_blank"><img src="https://nestjs.com/img/logos/slotsup-logo.png" width="60" valign="middle" /></a></td>
134
128
  </tr>
135
129
  </table>
136
130
 
@@ -48,10 +48,31 @@ const UNKNOWN_DEPENDENCIES_MESSAGE = (type, unknownDependencyContext, moduleRef)
48
48
  const { index, name, dependencies, key } = unknownDependencyContext;
49
49
  const moduleName = getModuleName(moduleRef);
50
50
  const dependencyName = getDependencyName(name, 'dependency');
51
- const potentialSolutions =
52
- // If module's name is well defined
53
- moduleName !== 'current'
54
- ? `\n
51
+ const isImportTypeIssue = !(0, shared_utils_1.isNil)(index) &&
52
+ dependencies &&
53
+ (dependencies[index] === undefined ||
54
+ dependencies[index] === Object ||
55
+ (typeof dependencies[index] === 'function' &&
56
+ dependencies[index].name === 'Object'));
57
+ let potentialSolutions;
58
+ if (isImportTypeIssue) {
59
+ potentialSolutions = `\n
60
+ Potential solutions:
61
+ - The dependency at index [${index}] appears to be undefined at runtime
62
+ - This commonly occurs when using 'import type' instead of 'import' for injectable classes
63
+ - Check your imports and change:
64
+ ❌ import type { SomeService } from './some.service';
65
+ ✅ import { SomeService } from './some.service';
66
+ - Ensure the imported class is decorated with @Injectable() or is a valid provider
67
+ - If using dynamic imports, ensure the class is available at runtime, not just for type checking
68
+
69
+ For more common dependency resolution issues, see: https://docs.nestjs.com/faq/common-errors`;
70
+ }
71
+ else {
72
+ potentialSolutions =
73
+ // If module's name is well defined
74
+ moduleName !== 'current'
75
+ ? `\n
55
76
  Potential solutions:
56
77
  - Is ${moduleName} a valid NestJS module?
57
78
  - If ${dependencyName} is a provider, is it part of the current ${moduleName}?
@@ -59,15 +80,18 @@ Potential solutions:
59
80
  @Module({
60
81
  imports: [ /* the Module containing ${dependencyName} */ ]
61
82
  })
62
- `
63
- : `\n
83
+
84
+ For more common dependency resolution issues, see: https://docs.nestjs.com/faq/common-errors`
85
+ : `\n
64
86
  Potential solutions:
65
87
  - If ${dependencyName} is a provider, is it part of the current Module?
66
88
  - If ${dependencyName} is exported from a separate @Module, is that module imported within Module?
67
89
  @Module({
68
90
  imports: [ /* the Module containing ${dependencyName} */ ]
69
91
  })
70
- `;
92
+
93
+ For more common dependency resolution issues, see: https://docs.nestjs.com/faq/common-errors`;
94
+ }
71
95
  let message = `Nest can't resolve dependencies of the ${type.toString()}`;
72
96
  if ((0, shared_utils_1.isNil)(index)) {
73
97
  message += `. Please make sure that the "${key.toString()}" property is available in the current context.${potentialSolutions}`;
@@ -77,7 +101,7 @@ Potential solutions:
77
101
  dependenciesName[index] = '?';
78
102
  message += ` (`;
79
103
  message += dependenciesName.join(', ');
80
- message += `). Please make sure that the argument ${dependencyName} at index [${index}] is available in the ${moduleName} context.`;
104
+ message += `). Please make sure that the argument ${isImportTypeIssue ? 'dependency' : dependencyName} at index [${index}] is available in the ${isImportTypeIssue ? 'current' : moduleName} context.`;
81
105
  message += potentialSolutions;
82
106
  return message;
83
107
  };
@@ -125,6 +149,8 @@ const UNKNOWN_EXPORT_MESSAGE = (token = 'item', module) => {
125
149
 
126
150
  Possible Solutions:
127
151
  - Is ${token} part of the relevant providers/imports within ${module}?
152
+
153
+ For more common dependency resolution issues, see: https://docs.nestjs.com/faq/common-errors
128
154
  `;
129
155
  };
130
156
  exports.UNKNOWN_EXPORT_MESSAGE = UNKNOWN_EXPORT_MESSAGE;
@@ -11,11 +11,11 @@ const exceptions_1 = require("../errors/exceptions");
11
11
  const runtime_exception_1 = require("../errors/exceptions/runtime.exception");
12
12
  const undefined_dependency_exception_1 = require("../errors/exceptions/undefined-dependency.exception");
13
13
  const unknown_dependencies_exception_1 = require("../errors/exceptions/unknown-dependencies.exception");
14
+ const barrier_1 = require("../helpers/barrier");
14
15
  const constants_2 = require("./constants");
15
16
  const inquirer_1 = require("./inquirer");
16
17
  const instance_wrapper_1 = require("./instance-wrapper");
17
18
  const settlement_signal_1 = require("./settlement-signal");
18
- const barrier_1 = require("../helpers/barrier");
19
19
  class Injector {
20
20
  constructor(options) {
21
21
  this.options = options;
@@ -111,7 +111,7 @@ class Injector {
111
111
  return settlementSignal;
112
112
  }
113
113
  async resolveConstructorParams(wrapper, moduleRef, inject, callback, contextId = constants_2.STATIC_CONTEXT, inquirer, parentInquirer) {
114
- let inquirerId = this.getInquirerId(inquirer);
114
+ const inquirerId = this.getInquirerId(inquirer);
115
115
  const metadata = wrapper.getCtorMetadata();
116
116
  if (metadata && contextId !== constants_2.STATIC_CONTEXT) {
117
117
  const deps = await this.loadCtorMetadata(metadata, contextId, inquirer, parentInquirer);
@@ -133,8 +133,10 @@ class Injector {
133
133
  return parentInquirer && parentInquirer.instance;
134
134
  }
135
135
  if (inquirer?.isTransient && parentInquirer) {
136
- inquirer = parentInquirer;
137
- inquirerId = this.getInquirerId(parentInquirer);
136
+ // When `inquirer` is transient too, inherit the parent inquirer
137
+ // This is required to ensure that transient providers are only resolved
138
+ // when requested
139
+ inquirer.attachRootInquirer(parentInquirer);
138
140
  }
139
141
  const paramWrapper = await this.resolveSingleParam(wrapper, param, { index, dependencies }, moduleRef, contextId, inquirer, index);
140
142
  /*
@@ -315,8 +317,11 @@ class Injector {
315
317
  const inquirerId = this.getInquirerId(inquirer);
316
318
  const instanceHost = instanceWrapperRef.getInstanceByContextId(this.getContextId(contextId, instanceWrapperRef), inquirerId);
317
319
  if (!instanceHost.isResolved && !instanceWrapperRef.forwardRef) {
318
- wrapper.settlementSignal?.insertRef(instanceWrapperRef.id);
319
- await this.loadProvider(instanceWrapperRef, relatedModule, contextId, wrapper);
320
+ /*
321
+ * Provider will be loaded shortly in resolveComponentHost() once we pass the current
322
+ * Barrier. We cannot load it here because doing so could incorrectly evaluate the
323
+ * staticity of the dependency tree and lead to undefined / null injection.
324
+ */
320
325
  break;
321
326
  }
322
327
  }
@@ -412,11 +417,13 @@ class Injector {
412
417
  ? Object.assign(instanceHost.instance, new metatype(...instances))
413
418
  : new metatype(...instances);
414
419
  instanceHost.instance = this.instanceDecorator(instanceHost.instance);
420
+ instanceHost.isConstructorCalled = true;
415
421
  }
416
422
  else if (isInContext) {
417
423
  const factoryReturnValue = targetMetatype.metatype(...instances);
418
424
  instanceHost.instance = await factoryReturnValue;
419
425
  instanceHost.instance = this.instanceDecorator(instanceHost.instance);
426
+ instanceHost.isConstructorCalled = true;
420
427
  }
421
428
  instanceHost.isResolved = true;
422
429
  return instanceHost.instance;
@@ -25,6 +25,7 @@ export interface InstancePerContext<T> {
25
25
  isResolved?: boolean;
26
26
  isPending?: boolean;
27
27
  donePromise?: Promise<unknown>;
28
+ isConstructorCalled?: boolean;
28
29
  }
29
30
  export interface PropertyMetadata {
30
31
  key: symbol | string;
@@ -51,6 +52,11 @@ export declare class InstanceWrapper<T = any> {
51
52
  private transientMap?;
52
53
  private isTreeStatic;
53
54
  private isTreeDurable;
55
+ /**
56
+ * The root inquirer reference. Present only if child instance wrapper
57
+ * is transient and has a parent inquirer.
58
+ */
59
+ private rootInquirer;
54
60
  constructor(metadata?: Partial<InstanceWrapper<T>> & Partial<InstancePerContext<T>>);
55
61
  get id(): string;
56
62
  set instance(value: T);
@@ -80,6 +86,8 @@ export declare class InstanceWrapper<T = any> {
80
86
  isLazyTransient(contextId: ContextId, inquirer: InstanceWrapper | undefined): boolean;
81
87
  isExplicitlyRequested(contextId: ContextId, inquirer?: InstanceWrapper): boolean;
82
88
  isStatic(contextId: ContextId, inquirer: InstanceWrapper | undefined): boolean;
89
+ attachRootInquirer(inquirer: InstanceWrapper): void;
90
+ getRootInquirer(): InstanceWrapper | undefined;
83
91
  getStaticTransientInstances(): (InstancePerContext<T> | undefined)[];
84
92
  mergeWith(provider: Provider): void;
85
93
  private isNewable;
@@ -242,10 +242,22 @@ class InstanceWrapper {
242
242
  isStatic(contextId, inquirer) {
243
243
  const isInquirerRequestScoped = inquirer && !inquirer.isDependencyTreeStatic();
244
244
  const isStaticTransient = this.isTransient && !isInquirerRequestScoped;
245
+ const rootInquirer = inquirer?.getRootInquirer();
245
246
  return (this.isDependencyTreeStatic() &&
246
247
  contextId === constants_1.STATIC_CONTEXT &&
247
248
  (!this.isTransient ||
248
- (isStaticTransient && !!inquirer && !inquirer.isTransient)));
249
+ (isStaticTransient && !!inquirer && !inquirer.isTransient) ||
250
+ (isStaticTransient && !!rootInquirer && !rootInquirer.isTransient)));
251
+ }
252
+ attachRootInquirer(inquirer) {
253
+ if (!this.isTransient) {
254
+ // Only attach root inquirer if the instance wrapper is transient
255
+ return;
256
+ }
257
+ this.rootInquirer = inquirer.getRootInquirer() ?? inquirer;
258
+ }
259
+ getRootInquirer() {
260
+ return this.rootInquirer;
249
261
  }
250
262
  getStaticTransientInstances() {
251
263
  if (!this.transientMap) {
@@ -254,7 +266,11 @@ class InstanceWrapper {
254
266
  const instances = [...this.transientMap.values()];
255
267
  return (0, iterare_1.iterate)(instances)
256
268
  .map(item => item.get(constants_1.STATIC_CONTEXT))
257
- .filter(item => !!item)
269
+ .filter(item => {
270
+ // Only return items where constructor has been actually called
271
+ // This prevents calling lifecycle hooks on non-instantiated transient services
272
+ return !!(item && item.isConstructorCalled);
273
+ })
258
274
  .toArray();
259
275
  }
260
276
  mergeWith(provider) {
package/nest-factory.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NestFactory = exports.NestFactoryStatic = void 0;
4
+ const console_logger_service_1 = require("@nestjs/common/services/console-logger.service");
4
5
  const logger_service_1 = require("@nestjs/common/services/logger.service");
5
6
  const load_package_util_1 = require("@nestjs/common/utils/load-package.util");
6
7
  const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
@@ -154,10 +155,16 @@ class NestFactoryStatic {
154
155
  if (!options) {
155
156
  return;
156
157
  }
157
- const { logger, bufferLogs, autoFlushLogs } = options;
158
+ const { logger, bufferLogs, autoFlushLogs, forceConsole } = options;
158
159
  if (logger !== true && !(0, shared_utils_1.isNil)(logger)) {
159
160
  logger_service_1.Logger.overrideLogger(logger);
160
161
  }
162
+ else if (forceConsole) {
163
+ // If no custom logger is provided but forceConsole is true,
164
+ // create a ConsoleLogger with forceConsole option
165
+ const consoleLogger = new console_logger_service_1.ConsoleLogger({ forceConsole: true });
166
+ logger_service_1.Logger.overrideLogger(consoleLogger);
167
+ }
161
168
  if (bufferLogs) {
162
169
  logger_service_1.Logger.attachBuffer();
163
170
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/core",
3
- "version": "11.1.5",
3
+ "version": "11.1.7",
4
4
  "description": "Nest - modern, fast, powerful node.js web framework (@core)",
5
5
  "author": "Kamil Mysliwiec",
6
6
  "license": "MIT",
@@ -34,12 +34,12 @@
34
34
  "@nuxt/opencollective": "0.4.1",
35
35
  "fast-safe-stringify": "2.1.1",
36
36
  "iterare": "1.2.1",
37
- "path-to-regexp": "8.2.0",
37
+ "path-to-regexp": "8.3.0",
38
38
  "tslib": "2.8.1",
39
39
  "uid": "2.0.2"
40
40
  },
41
41
  "devDependencies": {
42
- "@nestjs/common": "11.1.5"
42
+ "@nestjs/common": "11.1.7"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "@nestjs/common": "^11.0.0",