@nestjs/graphql
Version:
Nest - modern, fast, powerful node.js web framework (@graphql)
99 lines (98 loc) • 4.15 kB
JavaScript
import { isFunction, isObject, isString, } from '@nestjs/common/utils/shared.utils.js';
import 'reflect-metadata';
import { GqlParamtype } from '../enums/gql-paramtype.enum.js';
import { LazyMetadataStorage } from '../schema-builder/storages/lazy-metadata.storage.js';
import { TypeMetadataStorage } from '../schema-builder/storages/type-metadata.storage.js';
import { ARGS_TYPE_METADATA } from '../graphql.constants.js';
import { isPipe } from '../utils/is-pipe.util.js';
import { reflectTypeFromMetadata } from '../utils/reflection.utilts.js';
import { addPipesMetadata } from './param.utils.js';
/**
* Resolver method parameter decorator. Extracts the arguments
* object from the underlying platform and populates the decorated
* parameter with the value of either all arguments or a single specified argument.
*
* @publicApi
*/
export function Args(propertyOrOptionsOrPipe, optionsOrPipe, ...pipes) {
const [property, argOptions, argPipes] = getArgsOptions(propertyOrOptionsOrPipe, optionsOrPipe, pipes);
return (target, key, index) => {
addPipesMetadata(GqlParamtype.ARGS, property, argPipes, target, key, index);
// Arguments arrive keyed by their schema names. Record what each parameter
// expects so that the resolvers explorer can map them back to the property
// names declared by the `@ArgsType()`/`@InputType()` class before any pipe
// (global ones included) gets to see the value.
const argsTypes = Reflect.getOwnMetadata(ARGS_TYPE_METADATA, target.constructor, key) ?? [];
Reflect.defineMetadata(ARGS_TYPE_METADATA, argsTypes.concat({
index,
property: isString(property) ? property : undefined,
typeFn: argOptions.type,
}), target.constructor, key);
LazyMetadataStorage.store(target.constructor, () => {
const { typeFn: reflectedTypeFn, options } = reflectTypeFromMetadata({
metadataKey: 'design:paramtypes',
prototype: target,
propertyKey: key,
index: index,
explicitTypeFn: argOptions.type,
typeOptions: argOptions,
});
const metadata = {
target: target.constructor,
methodName: key,
typeFn: reflectedTypeFn,
index,
options,
};
if (property && isString(property)) {
TypeMetadataStorage.addMethodParamMetadata({
kind: 'arg',
name: property,
description: argOptions.description,
deprecationReason: argOptions.deprecationReason,
...metadata,
});
}
else {
TypeMetadataStorage.addMethodParamMetadata({
kind: 'args',
...metadata,
});
}
});
};
}
function getArgsOptions(propertyOrOptionsOrPipe, optionsOrPipe, pipes) {
if (!propertyOrOptionsOrPipe || isString(propertyOrOptionsOrPipe)) {
const propertyKey = propertyOrOptionsOrPipe;
let options = {};
let argPipes = [];
if (isPipe(optionsOrPipe)) {
argPipes = [optionsOrPipe].concat(pipes);
}
else {
options = optionsOrPipe || {};
argPipes = pipes;
}
return [propertyKey, options, argPipes];
}
const isArgsOptionsObject = isObject(propertyOrOptionsOrPipe) &&
!isFunction(propertyOrOptionsOrPipe.transform);
if (isArgsOptionsObject) {
const argOptions = propertyOrOptionsOrPipe;
const propertyKey = argOptions.name;
const argPipes = optionsOrPipe ? [optionsOrPipe].concat(pipes) : pipes;
return [
propertyKey,
argOptions,
argPipes,
];
}
// concatenate all pipes
let argPipes = [propertyOrOptionsOrPipe];
if (optionsOrPipe) {
argPipes = argPipes.concat(optionsOrPipe);
}
argPipes = argPipes.concat(pipes);
return [undefined, {}, argPipes];
}