@nestjs/core 11.1.28 → 11.1.29

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.
@@ -11,6 +11,9 @@ class Barrier {
11
11
  this.promise = new Promise(resolve => {
12
12
  this.resolve = resolve;
13
13
  });
14
+ if (targetCount === 0) {
15
+ this.resolve();
16
+ }
14
17
  }
15
18
  /**
16
19
  * Signal that a participant has reached the barrier.
@@ -19,7 +22,7 @@ class Barrier {
19
22
  */
20
23
  signal() {
21
24
  this.currentCount += 1;
22
- if (this.currentCount === this.targetCount) {
25
+ if (this.currentCount >= this.targetCount) {
23
26
  this.resolve();
24
27
  }
25
28
  }
@@ -328,16 +328,12 @@ class Injector {
328
328
  this.printFoundInModuleLog(name, relatedModule);
329
329
  instanceWrapperRef = providers.get(name);
330
330
  this.addDependencyMetadata(keyOrIndex, wrapper, instanceWrapperRef);
331
- const inquirerId = this.getContextInquirerId(resolutionContext);
332
- const instanceHost = instanceWrapperRef.getInstanceByContextId(this.getContextId(resolutionContext.contextId, instanceWrapperRef), inquirerId);
333
- if (!instanceHost.isResolved && !instanceWrapperRef.forwardRef) {
334
- /*
335
- * Provider will be loaded shortly in resolveComponentHost() once we pass the current
336
- * Barrier. We cannot load it here because doing so could incorrectly evaluate the
337
- * staticity of the dependency tree and lead to undefined / null injection.
338
- */
339
- break;
340
- }
331
+ /*
332
+ * Stop at the first direct export match. Continuing when the provider is
333
+ * already resolved would let a later import (e.g. a global forRoot module)
334
+ * override an explicit forFeature import for the same token.
335
+ */
336
+ break;
341
337
  }
342
338
  return instanceWrapperRef;
343
339
  }
@@ -56,9 +56,9 @@ class ModuleRef extends abstract_instance_resolver_1.AbstractInstanceResolver {
56
56
  isPending: false,
57
57
  });
58
58
  }
59
- return new Promise(async (resolve, reject) => {
60
- try {
61
- const callback = async (instances) => {
59
+ return new Promise((resolve, reject) => {
60
+ const callback = async (instances) => {
61
+ try {
62
62
  const properties = await this.injector.resolveProperties(wrapper, moduleRef, undefined, {
63
63
  contextId: contextId ?? constants_1.STATIC_CONTEXT,
64
64
  inquirer: wrapper,
@@ -66,15 +66,17 @@ class ModuleRef extends abstract_instance_resolver_1.AbstractInstanceResolver {
66
66
  const instance = new type(...instances);
67
67
  this.injector.applyProperties(instance, properties);
68
68
  resolve(instance);
69
- };
70
- await this.injector.resolveConstructorParams(wrapper, moduleRef, undefined, callback, {
71
- contextId: contextId ?? constants_1.STATIC_CONTEXT,
72
- inquirer: wrapper,
73
- });
74
- }
75
- catch (err) {
76
- reject(err);
77
- }
69
+ }
70
+ catch (err) {
71
+ reject(err);
72
+ }
73
+ };
74
+ this.injector
75
+ .resolveConstructorParams(wrapper, moduleRef, undefined, callback, {
76
+ contextId: contextId ?? constants_1.STATIC_CONTEXT,
77
+ inquirer: wrapper,
78
+ })
79
+ .catch(reject);
78
80
  });
79
81
  }
80
82
  }
@@ -73,7 +73,11 @@ MiddlewareBuilder.ConfigProxy = class {
73
73
  .map(route => ({
74
74
  method: route.method,
75
75
  path: route.path,
76
- regex: new RegExp('^(' + route.path.replace(regexMatchParams, wildcard) + ')$', 'g'),
76
+ // No `g` flag: each regex is reused across every route below, and a
77
+ // global regex advances `lastIndex` on a match, so the next `test()`
78
+ // would resume mid-string and fail the `^` anchor. The pattern is
79
+ // anchored and only used with `test()`, so `g` buys nothing anyway.
80
+ regex: new RegExp('^(' + route.path.replace(regexMatchParams, wildcard) + ')$'),
77
81
  }));
78
82
  return routes.filter(route => {
79
83
  const isOverlapped = (item) => {
@@ -104,17 +104,10 @@ class NestApplicationContext extends abstract_instance_resolver_1.AbstractInstan
104
104
  if (this.isInitialized) {
105
105
  return this;
106
106
  }
107
- /* eslint-disable-next-line no-async-promise-executor */
108
- this.initializationPromise = new Promise(async (resolve, reject) => {
109
- try {
110
- await this.callInitHook();
111
- await this.callBootstrapHook();
112
- resolve();
113
- }
114
- catch (err) {
115
- reject(err);
116
- }
117
- });
107
+ this.initializationPromise = (async () => {
108
+ await this.callInitHook();
109
+ await this.callBootstrapHook();
110
+ })();
118
111
  await this.initializationPromise;
119
112
  this.isInitialized = true;
120
113
  return this;
@@ -62,4 +62,5 @@ export declare class NestApplication extends NestApplicationContext<NestApplicat
62
62
  private getProtocol;
63
63
  private registerMiddleware;
64
64
  private applyInstanceDecoratorIfRegistered;
65
+ private applyFunctionDecoratorIfRegistered;
65
66
  }
@@ -151,7 +151,7 @@ class NestApplication extends nest_application_context_1.NestApplicationContext
151
151
  return this;
152
152
  }
153
153
  use(...args) {
154
- this.httpAdapter.use(...args);
154
+ this.httpAdapter.use(...this.applyFunctionDecoratorIfRegistered(args));
155
155
  return this;
156
156
  }
157
157
  useBodyParser(...args) {
@@ -329,5 +329,19 @@ class NestApplication extends nest_application_context_1.NestApplicationContext
329
329
  }
330
330
  return instances;
331
331
  }
332
+ applyFunctionDecoratorIfRegistered(args) {
333
+ if (!this.appOptions.instrument?.instanceDecorator) {
334
+ return args;
335
+ }
336
+ const [firstArg, secondArg] = args;
337
+ return [
338
+ (0, shared_utils_1.isFunction)(firstArg)
339
+ ? this.appOptions.instrument.instanceDecorator(firstArg)
340
+ : firstArg,
341
+ (0, shared_utils_1.isFunction)(secondArg)
342
+ ? this.appOptions.instrument.instanceDecorator(secondArg)
343
+ : secondArg,
344
+ ];
345
+ }
332
346
  }
333
347
  exports.NestApplication = NestApplication;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/core",
3
- "version": "11.1.28",
3
+ "version": "11.1.29",
4
4
  "description": "Nest - modern, fast, powerful node.js web framework (@core)",
5
5
  "author": "Kamil Mysliwiec",
6
6
  "license": "MIT",
@@ -28,7 +28,7 @@
28
28
  "uid": "2.0.2"
29
29
  },
30
30
  "devDependencies": {
31
- "@nestjs/common": "11.1.28"
31
+ "@nestjs/common": "11.1.29"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "@nestjs/common": "^11.0.0",
@@ -49,5 +49,5 @@
49
49
  "optional": true
50
50
  }
51
51
  },
52
- "gitHead": "dfaa376170168d12d9d28bcfe137a9bacce579a3"
52
+ "gitHead": "03587a112ebbbb53a6bc3875afb5a9205aa5a5f1"
53
53
  }
@@ -22,6 +22,7 @@ export type HeaderStream = WritableHeaderStream & ReadHeaders;
22
22
  * - type
23
23
  * - id
24
24
  * - retry
25
+ * - comment
25
26
  *
26
27
  * If constructed with a HTTP Request, it will optimise the socket for streaming.
27
28
  * If this stream is piped to an HTTP Response, it will set appropriate headers.
@@ -3,14 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SseStream = void 0;
4
4
  const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
5
5
  const stream_1 = require("stream");
6
+ function serializeSseLines(value, prefix) {
7
+ return value
8
+ .split(/\r\n|\r|\n/)
9
+ .map(line => `${prefix}${line}\n`)
10
+ .join('');
11
+ }
6
12
  function toDataString(data) {
7
13
  if ((0, shared_utils_1.isObject)(data)) {
8
14
  return toDataString(JSON.stringify(data));
9
15
  }
10
- return data
11
- .split(/\r\n|\r|\n/)
12
- .map(line => `data: ${line}\n`)
13
- .join('');
16
+ return serializeSseLines(data, 'data: ');
17
+ }
18
+ function toCommentString(comment) {
19
+ return serializeSseLines(comment, ': ');
20
+ }
21
+ function isCommentOnly(message) {
22
+ return (!(0, shared_utils_1.isNil)(message.comment) &&
23
+ (0, shared_utils_1.isUndefined)(message.data) &&
24
+ (0, shared_utils_1.isUndefined)(message.type) &&
25
+ (0, shared_utils_1.isUndefined)(message.retry));
14
26
  }
15
27
  /**
16
28
  * Adapted from https://raw.githubusercontent.com/EventSource/node-ssestream
@@ -21,6 +33,7 @@ function toDataString(data) {
21
33
  * - type
22
34
  * - id
23
35
  * - retry
36
+ * - comment
24
37
  *
25
38
  * If constructed with a HTTP Request, it will optimise the socket for streaming.
26
39
  * If this stream is piped to an HTTP Response, it will set appropriate headers.
@@ -84,12 +97,10 @@ class SseStream extends stream_1.Transform {
84
97
  this.commitHeaders();
85
98
  const sanitize = (val) => String(val).replace(/[\r\n]/g, '');
86
99
  let data = message.type ? `event: ${sanitize(message.type)}\n` : '';
87
- data +=
88
- message.id !== undefined && message.id !== null
89
- ? `id: ${sanitize(message.id)}\n`
90
- : '';
91
- data += message.retry ? `retry: ${sanitize(message.retry)}\n` : '';
92
- data += message.data ? toDataString(message.data) : '';
100
+ data += !(0, shared_utils_1.isNil)(message.id) ? `id: ${sanitize(message.id)}\n` : '';
101
+ data += !(0, shared_utils_1.isNil)(message.retry) ? `retry: ${sanitize(message.retry)}\n` : '';
102
+ data += !(0, shared_utils_1.isNil)(message.comment) ? toCommentString(message.comment) : '';
103
+ data += !(0, shared_utils_1.isNil)(message.data) ? toDataString(message.data) : '';
93
104
  data += '\n';
94
105
  this.push(data);
95
106
  callback();
@@ -98,7 +109,7 @@ class SseStream extends stream_1.Transform {
98
109
  * Calls `.write` but handles the drain if needed
99
110
  */
100
111
  writeMessage(message, cb) {
101
- if (message.id === undefined || message.id === null) {
112
+ if ((0, shared_utils_1.isNil)(message.id) && !isCommentOnly(message)) {
102
113
  this.lastEventId++;
103
114
  message.id = this.lastEventId.toString();
104
115
  }