@nestjs/common 12.1.1 → 12.1.3
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/decorators/core/inject.decorator.js +4 -1
- package/decorators/core/optional.decorator.js +1 -1
- package/decorators/http/create-route-param-metadata.decorator.js +13 -2
- package/file-stream/streamable-file.js +4 -1
- package/interfaces/http/http-server.interface.d.ts +9 -2
- package/interfaces/nest-application-context.interface.d.ts +4 -4
- package/module-utils/utils/get-injection-providers.util.js +4 -3
- package/package.json +2 -2
- package/pipes/file/file-type.validator.js +4 -1
- package/pipes/parse-array.pipe.js +3 -1
- package/pipes/parse-uuid.pipe.d.ts +7 -9
- package/pipes/parse-uuid.pipe.js +5 -1
- package/pipes/validation.pipe.js +8 -6
- package/utils/parameter-decorator-options.util.d.ts +3 -0
- package/utils/parameter-decorator-options.util.js +3 -0
|
@@ -44,7 +44,10 @@ export function Inject(token) {
|
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
46
|
let properties = Reflect.getMetadata(PROPERTY_DEPS_METADATA, target.constructor) || [];
|
|
47
|
-
properties = [
|
|
47
|
+
properties = [
|
|
48
|
+
...properties.filter(property => property.key !== key),
|
|
49
|
+
{ key, type },
|
|
50
|
+
];
|
|
48
51
|
Reflect.defineMetadata(PROPERTY_DEPS_METADATA, properties, target.constructor);
|
|
49
52
|
};
|
|
50
53
|
}
|
|
@@ -20,7 +20,7 @@ export function Optional() {
|
|
|
20
20
|
Reflect.defineMetadata(OPTIONAL_DEPS_METADATA, [...args, index], target);
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
-
const properties = Reflect.
|
|
23
|
+
const properties = Reflect.getMetadata(OPTIONAL_PROPERTY_DEPS_METADATA, target.constructor) || [];
|
|
24
24
|
Reflect.defineMetadata(OPTIONAL_PROPERTY_DEPS_METADATA, [...properties, key], target.constructor);
|
|
25
25
|
};
|
|
26
26
|
}
|
|
@@ -24,8 +24,19 @@ export function createParamDecorator(factory, enhancers = []) {
|
|
|
24
24
|
const hasParamData = isNil(data) || !isPipe(data);
|
|
25
25
|
const paramData = hasParamData ? data : undefined;
|
|
26
26
|
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
|
27
|
-
//
|
|
28
|
-
|
|
27
|
+
// Custom data may also contain schema or pipes properties, so only treat
|
|
28
|
+
// the first argument as options when those are its only keys and their
|
|
29
|
+
// values, if defined, are a Standard Schema and an array of pipes.
|
|
30
|
+
const isDataOptions = hasParamData &&
|
|
31
|
+
!isNil(data) &&
|
|
32
|
+
isParameterDecoratorOptions(data) &&
|
|
33
|
+
Object.keys(data).every(key => key === 'schema' || key === 'pipes') &&
|
|
34
|
+
(data.schema === undefined ||
|
|
35
|
+
isFunction(data.schema?.['~standard']?.validate)) &&
|
|
36
|
+
(data.pipes === undefined ||
|
|
37
|
+
(Array.isArray(data.pipes) &&
|
|
38
|
+
// Falsy entries are allowed, as the pipes context filters them out
|
|
39
|
+
data.pipes.every(pipe => isNil(pipe) || isPipe(pipe))));
|
|
29
40
|
// Check if the last pipe argument is actually an options object
|
|
30
41
|
const lastPipeArg = paramPipes.length > 0 ? paramPipes[paramPipes.length - 1] : undefined;
|
|
31
42
|
const isLastPipeOptions = !isDataOptions && isParameterDecoratorOptions(lastPipeArg);
|
|
@@ -32,7 +32,10 @@ export class StreamableFile {
|
|
|
32
32
|
this.stream = new Readable();
|
|
33
33
|
this.stream.push(bufferOrReadStream);
|
|
34
34
|
this.stream.push(null);
|
|
35
|
-
this.options
|
|
35
|
+
this.options = {
|
|
36
|
+
...this.options,
|
|
37
|
+
length: this.options.length ?? bufferOrReadStream.length,
|
|
38
|
+
};
|
|
36
39
|
}
|
|
37
40
|
else if (bufferOrReadStream.pipe && isFunction(bufferOrReadStream.pipe)) {
|
|
38
41
|
this.stream = bufferOrReadStream;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RequestMethod } from '../../enums/index.js';
|
|
2
|
+
import { RouteInfo } from '../middleware/middleware-configuration.interface.js';
|
|
2
3
|
import { NestApplicationOptions } from '../../interfaces/nest-application-options.interface.js';
|
|
3
4
|
import { VersionValue, VersioningOptions } from '../version-options.interface.js';
|
|
4
5
|
import { CookieSerializeOptions } from './cookie-options.interface.js';
|
|
@@ -419,8 +420,14 @@ export interface HttpServer<TRequest = any, TResponse = any, ServerInstance = an
|
|
|
419
420
|
*
|
|
420
421
|
* @param handler The `(req, res, next)` callback.
|
|
421
422
|
* @param prefix The global prefix (`app.setGlobalPrefix()`), when set.
|
|
422
|
-
|
|
423
|
-
|
|
423
|
+
* @param excludedRoutes The routes `app.setGlobalPrefix()` excluded from the
|
|
424
|
+
* prefix, when any. They live at the root, so an adapter that scopes the
|
|
425
|
+
* handler by `prefix` should also mount it on each of these paths, for
|
|
426
|
+
* every method: with `exclude: ['hello']` and only `GET /hello` declared,
|
|
427
|
+
* `POST /hello` is still an unmatched request for a route Nest owns. Paths
|
|
428
|
+
* arrive already converted to the framework's route syntax.
|
|
429
|
+
*/
|
|
430
|
+
setNotFoundHandler?(handler: Function, prefix?: string, excludedRoutes?: RouteInfo[]): any;
|
|
424
431
|
/**
|
|
425
432
|
* Serves static files; pass-through for `app.useStaticAssets()`. The
|
|
426
433
|
* arguments are platform-specific. When not implemented,
|
|
@@ -57,19 +57,19 @@ export interface INestApplicationContext {
|
|
|
57
57
|
get<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | Function | string | symbol, options?: GetOrResolveOptions): TResult | Array<TResult>;
|
|
58
58
|
/**
|
|
59
59
|
* Resolves transient or request-scoped instance of either injectable or controller, otherwise, throws exception.
|
|
60
|
-
* @returns {
|
|
60
|
+
* @returns {Promise<TResult>}
|
|
61
61
|
*/
|
|
62
62
|
resolve<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | Function | string | symbol): Promise<TResult>;
|
|
63
63
|
/**
|
|
64
64
|
* Resolves transient or request-scoped instance of either injectable or controller, otherwise, throws exception.
|
|
65
|
-
* @returns {
|
|
65
|
+
* @returns {Promise<TResult>}
|
|
66
66
|
*/
|
|
67
67
|
resolve<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | Function | string | symbol, contextId?: {
|
|
68
68
|
id: number;
|
|
69
69
|
}): Promise<TResult>;
|
|
70
70
|
/**
|
|
71
71
|
* Resolves transient or request-scoped instance of either injectable or controller, otherwise, throws exception.
|
|
72
|
-
* @returns {
|
|
72
|
+
* @returns {Promise<TResult>}
|
|
73
73
|
*/
|
|
74
74
|
resolve<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | Function | string | symbol, contextId?: {
|
|
75
75
|
id: number;
|
|
@@ -79,7 +79,7 @@ export interface INestApplicationContext {
|
|
|
79
79
|
}): Promise<TResult>;
|
|
80
80
|
/**
|
|
81
81
|
* Resolves transient or request-scoped instances of either injectables or controllers, otherwise, throws exception.
|
|
82
|
-
* @returns {Array<TResult
|
|
82
|
+
* @returns {Promise<Array<TResult>>}
|
|
83
83
|
*/
|
|
84
84
|
resolve<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | Function | string | symbol, contextId?: {
|
|
85
85
|
id: number;
|
|
@@ -22,10 +22,11 @@ export function getInjectionProviders(providers, tokens) {
|
|
|
22
22
|
const match = (providers ?? []).filter(p => !result.includes(p) && // this prevents circular loops and duplication
|
|
23
23
|
(search.includes(p) || search.includes(p?.provide)));
|
|
24
24
|
result.push(...match);
|
|
25
|
-
//
|
|
25
|
+
// Follow factory dependencies and aliases to existing providers.
|
|
26
26
|
search = match
|
|
27
|
-
.
|
|
28
|
-
|
|
27
|
+
.flatMap(p => p?.useExisting !== undefined
|
|
28
|
+
? [p.useExisting]
|
|
29
|
+
: (p?.inject ?? []))
|
|
29
30
|
.map(mapInjectToTokens);
|
|
30
31
|
}
|
|
31
32
|
return result;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nestjs/common",
|
|
3
|
-
"version": "12.1.
|
|
3
|
+
"version": "12.1.3",
|
|
4
4
|
"description": "Nest - modern, fast, powerful node.js web framework (@common)",
|
|
5
5
|
"author": "Kamil Mysliwiec",
|
|
6
6
|
"homepage": "https://nestjs.com",
|
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
"optional": true
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "4514623279f6087808e3c8f08fbf9f37d3c17482"
|
|
51
51
|
}
|
|
@@ -107,6 +107,9 @@ export class FileTypeValidator extends FileValidator {
|
|
|
107
107
|
if (typeof fileType === 'string' && mimetype === fileType) {
|
|
108
108
|
return true;
|
|
109
109
|
}
|
|
110
|
-
|
|
110
|
+
// Stateful expressions must start at zero for each file, without changing
|
|
111
|
+
// the caller's lastIndex (the validator can be reused across uploads).
|
|
112
|
+
const pattern = typeof fileType === 'string' ? fileType : new RegExp(fileType);
|
|
113
|
+
return !!mimetype.match(pattern);
|
|
111
114
|
}
|
|
112
115
|
}
|
|
@@ -66,7 +66,9 @@ let ParseArrayPipe = class ParseArrayPipe {
|
|
|
66
66
|
};
|
|
67
67
|
const isExpectedTypePrimitive = this.isExpectedTypePrimitive();
|
|
68
68
|
const toClassInstance = (item, index) => {
|
|
69
|
-
|
|
69
|
+
// `JSON.parse` stringifies its argument first, so an array holding a
|
|
70
|
+
// single item (`[1]` becomes `'1'`) would be parsed as that item.
|
|
71
|
+
if (this.options.items !== String && isString(item)) {
|
|
70
72
|
try {
|
|
71
73
|
item = JSON.parse(item);
|
|
72
74
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface.js';
|
|
2
2
|
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util.js';
|
|
3
|
+
/**
|
|
4
|
+
* @publicApi
|
|
5
|
+
*/
|
|
6
|
+
export type UUIDVersion = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 'all';
|
|
3
7
|
/**
|
|
4
8
|
* @publicApi
|
|
5
9
|
*/
|
|
@@ -7,7 +11,7 @@ export interface ParseUUIDPipeOptions {
|
|
|
7
11
|
/**
|
|
8
12
|
* UUID version to validate
|
|
9
13
|
*/
|
|
10
|
-
version?:
|
|
14
|
+
version?: UUIDVersion;
|
|
11
15
|
/**
|
|
12
16
|
* The HTTP status code to be used in the response when the validation fails.
|
|
13
17
|
*/
|
|
@@ -34,16 +38,10 @@ export interface ParseUUIDPipeOptions {
|
|
|
34
38
|
*/
|
|
35
39
|
export declare class ParseUUIDPipe implements PipeTransform {
|
|
36
40
|
protected readonly options?: ParseUUIDPipeOptions | undefined;
|
|
37
|
-
protected static uuidRegExps:
|
|
38
|
-
3: RegExp;
|
|
39
|
-
4: RegExp;
|
|
40
|
-
5: RegExp;
|
|
41
|
-
7: RegExp;
|
|
42
|
-
all: RegExp;
|
|
43
|
-
};
|
|
41
|
+
protected static uuidRegExps: Record<UUIDVersion, RegExp>;
|
|
44
42
|
private readonly version;
|
|
45
43
|
protected exceptionFactory: (errors: string) => any;
|
|
46
44
|
constructor(options?: ParseUUIDPipeOptions | undefined);
|
|
47
45
|
transform(value: unknown, metadata: ArgumentMetadata): Promise<string | undefined | null>;
|
|
48
|
-
protected isUUID(str: unknown, version?:
|
|
46
|
+
protected isUUID(str: unknown, version?: UUIDVersion): boolean;
|
|
49
47
|
}
|
package/pipes/parse-uuid.pipe.js
CHANGED
|
@@ -16,10 +16,14 @@ let ParseUUIDPipe = class ParseUUIDPipe {
|
|
|
16
16
|
static { ParseUUIDPipe_1 = this; }
|
|
17
17
|
options;
|
|
18
18
|
static uuidRegExps = {
|
|
19
|
+
1: /^[0-9A-F]{8}-[0-9A-F]{4}-1[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
|
|
20
|
+
2: /^[0-9A-F]{8}-[0-9A-F]{4}-2[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
|
|
19
21
|
3: /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
|
|
20
22
|
4: /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
|
|
21
23
|
5: /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
|
|
24
|
+
6: /^[0-9A-F]{8}-[0-9A-F]{4}-6[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
|
|
22
25
|
7: /^[0-9A-F]{8}-[0-9A-F]{4}-7[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
|
|
26
|
+
8: /^[0-9A-F]{8}-[0-9A-F]{4}-8[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
|
|
23
27
|
// Versions 1-8 with the RFC variant, or the Nil and Max UUIDs (RFC 9562, sections 5.9, 5.10)
|
|
24
28
|
all: /^(?:[0-9A-F]{8}-[0-9A-F]{4}-[1-8][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}|00000000-0000-0000-0000-000000000000|FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF)$/i,
|
|
25
29
|
};
|
|
@@ -39,7 +43,7 @@ let ParseUUIDPipe = class ParseUUIDPipe {
|
|
|
39
43
|
return value;
|
|
40
44
|
}
|
|
41
45
|
if (!this.isUUID(value, this.version)) {
|
|
42
|
-
throw this.exceptionFactory(`Validation failed (uuid${this.version ? ` v ${this.version}` : ''} is expected)`);
|
|
46
|
+
throw this.exceptionFactory(`Validation failed (uuid${this.version && this.version !== 'all' ? ` v ${this.version}` : ''} is expected)`);
|
|
43
47
|
}
|
|
44
48
|
return value;
|
|
45
49
|
}
|
package/pipes/validation.pipe.js
CHANGED
|
@@ -216,18 +216,20 @@ let ValidationPipe = class ValidationPipe {
|
|
|
216
216
|
return result;
|
|
217
217
|
}
|
|
218
218
|
mapChildrenToValidationErrors(error, parentPath) {
|
|
219
|
+
const currentError = parentPath
|
|
220
|
+
? this.prependConstraintsWithParentProp(parentPath, error)
|
|
221
|
+
: error;
|
|
219
222
|
if (!(error.children && error.children.length)) {
|
|
220
|
-
return [
|
|
223
|
+
return [currentError];
|
|
221
224
|
}
|
|
222
|
-
const validationErrors =
|
|
225
|
+
const validationErrors = error.constraints
|
|
226
|
+
? [currentError]
|
|
227
|
+
: [];
|
|
223
228
|
parentPath = parentPath
|
|
224
229
|
? `${parentPath}.${error.property}`
|
|
225
230
|
: error.property;
|
|
226
231
|
for (const item of error.children) {
|
|
227
|
-
|
|
228
|
-
validationErrors.push(...this.mapChildrenToValidationErrors(item, parentPath));
|
|
229
|
-
}
|
|
230
|
-
validationErrors.push(this.prependConstraintsWithParentProp(parentPath, item));
|
|
232
|
+
validationErrors.push(...this.mapChildrenToValidationErrors(item, parentPath));
|
|
231
233
|
}
|
|
232
234
|
return validationErrors;
|
|
233
235
|
}
|
|
@@ -8,6 +8,9 @@ import type { ParameterDecoratorOptions } from '../decorators/http/route-params.
|
|
|
8
8
|
* arguments identically: a pipe instance that happens to expose a `schema` or
|
|
9
9
|
* `pipes` property must never be mistaken for an options object.
|
|
10
10
|
*
|
|
11
|
+
* `createParamDecorator` applies a stricter check to its first argument, since
|
|
12
|
+
* that argument may also be arbitrary custom data.
|
|
13
|
+
*
|
|
11
14
|
* @internal
|
|
12
15
|
*/
|
|
13
16
|
export declare function isParameterDecoratorOptions(value: unknown): value is ParameterDecoratorOptions;
|
|
@@ -12,6 +12,9 @@ const isPipeLike = (value) => isFunction(value?.transform) ||
|
|
|
12
12
|
* arguments identically: a pipe instance that happens to expose a `schema` or
|
|
13
13
|
* `pipes` property must never be mistaken for an options object.
|
|
14
14
|
*
|
|
15
|
+
* `createParamDecorator` applies a stricter check to its first argument, since
|
|
16
|
+
* that argument may also be arbitrary custom data.
|
|
17
|
+
*
|
|
15
18
|
* @internal
|
|
16
19
|
*/
|
|
17
20
|
export function isParameterDecoratorOptions(value) {
|