UNPKG

@nestjs/graphql

Version:

Nest - modern, fast, powerful node.js web framework (@graphql)

77 lines (76 loc) 3.4 kB
import { isFunction } from '@nestjs/common/utils/shared.utils.js'; import { applyIsOptionalDecorator, applyValidateIfDefinedDecorator, inheritPropertyInitializers, inheritTransformationMetadata, inheritValidationMetadata, } from '@nestjs/mapped-types'; import { Field } from '../decorators/index.js'; import { MetadataLoader } from '../plugin/metadata-loader.js'; import { METADATA_FACTORY_NAME } from '../plugin/plugin-constants.js'; import { getFieldsAndDecoratorForType } from '../schema-builder/utils/get-fields-and-decorator.util.js'; import { applyFieldDecorators } from './type-helpers.utils.js'; function isPartialTypeOptions(optionsOrDecorator) { return (optionsOrDecorator && ('decorator' in optionsOrDecorator || 'omitDefaultValues' in optionsOrDecorator || 'skipNullProperties' in optionsOrDecorator)); } export function PartialType(classRef, optionsOrDecorator) { const { fields, decoratorFactory } = getFieldsAndDecoratorForType(classRef); class PartialObjectType { constructor() { inheritPropertyInitializers(this, classRef); } } let decorator; let omitDefaultValues = false; let skipNullProperties = true; if (isPartialTypeOptions(optionsOrDecorator)) { decorator = optionsOrDecorator.decorator; omitDefaultValues = optionsOrDecorator.omitDefaultValues; skipNullProperties = optionsOrDecorator.skipNullProperties ?? true; } else { decorator = optionsOrDecorator; } const applyPartialDecoratorFn = skipNullProperties === false ? applyValidateIfDefinedDecorator : applyIsOptionalDecorator; if (decorator) { decorator({ isAbstract: true })(PartialObjectType); } else { decoratorFactory({ isAbstract: true })(PartialObjectType); } inheritValidationMetadata(classRef, PartialObjectType); inheritTransformationMetadata(classRef, PartialObjectType); function applyFields(fields) { fields.forEach((item) => { if (isFunction(item.typeFn)) { // Execute type function eagerly to update the type options object (before "clone" operation) // when the passed function (e.g., @Field(() => Type)) lazily returns an array. item.typeFn(); } Field(item.typeFn, { ...item.options, nullable: true, defaultValue: omitDefaultValues ? undefined : item.options.defaultValue, })(PartialObjectType.prototype, item.name); applyPartialDecoratorFn(PartialObjectType, item.name); applyFieldDecorators(PartialObjectType, item); }); } applyFields(fields); // Register a refresh hook to update the fields when the serialized metadata // is loaded from file. MetadataLoader.addRefreshHook(() => { const { fields } = getFieldsAndDecoratorForType(classRef, { overrideFields: true, }); applyFields(fields); }); if (PartialObjectType[METADATA_FACTORY_NAME]) { const pluginFields = Object.keys(PartialObjectType[METADATA_FACTORY_NAME]()); pluginFields.forEach((key) => applyPartialDecoratorFn(PartialObjectType, key)); } Object.defineProperty(PartialObjectType, 'name', { value: `Partial${classRef.name}`, }); return PartialObjectType; }