From 6516311268e2ccf1c12a8e22a02315f82c2f7ce2 Mon Sep 17 00:00:00 2001 From: Carson Full Date: Wed, 24 Jul 2024 16:29:35 -0500 Subject: [PATCH 1/2] fix(graphql): avoid partial field declarations from inherited metadata with cli plugin The former logic was accessing the inherited metadata factory, I guess when the current class didn't have one. The parent class could have fields that the plugin cannot determine, and are explicitly declared with `@Field` decorators. The partial info & the type from decorator are merged together for that base type. But here when the subclass was redefining this field it only had partial info, no type. This caused the complication logic to fail, because the `typeFn` would be missing. Instead, we only want to look for the _own_ metadata factory, and ignore if there is none. Just to note: inherited fields are merged elsewhere (in factories), so this doesn't need to try. --- .../lib/schema-builder/storages/type-metadata.storage.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/graphql/lib/schema-builder/storages/type-metadata.storage.ts b/packages/graphql/lib/schema-builder/storages/type-metadata.storage.ts index e73a8221d..4efae88a9 100644 --- a/packages/graphql/lib/schema-builder/storages/type-metadata.storage.ts +++ b/packages/graphql/lib/schema-builder/storages/type-metadata.storage.ts @@ -226,10 +226,13 @@ export class TypeMetadataStorageHost { if (!prototype.constructor) { return; } - if (!prototype.constructor[METADATA_FACTORY_NAME]) { + const metadata = Object.getOwnPropertyDescriptor( + prototype.constructor, + METADATA_FACTORY_NAME, + )?.value?.(); + if (!metadata) { continue; } - const metadata = prototype.constructor[METADATA_FACTORY_NAME](); const properties = Object.keys(metadata); properties.forEach((key) => { if (metadata[key].type) { From 690dfebe32c06b69205791a19b902bff5ff4963d Mon Sep 17 00:00:00 2001 From: Carson Full Date: Wed, 24 Jul 2024 16:33:58 -0500 Subject: [PATCH 2/2] chore(graphql): skip redundant metadata merges for common parents --- .../schema-builder/storages/type-metadata.storage.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/graphql/lib/schema-builder/storages/type-metadata.storage.ts b/packages/graphql/lib/schema-builder/storages/type-metadata.storage.ts index 4efae88a9..29971730d 100644 --- a/packages/graphql/lib/schema-builder/storages/type-metadata.storage.ts +++ b/packages/graphql/lib/schema-builder/storages/type-metadata.storage.ts @@ -216,16 +216,23 @@ export class TypeMetadataStorageHost { } loadClassPluginMetadata(metadata: ClassMetadata[]) { + const loadedClasses = new Set(); metadata .filter((item) => item?.target) - .forEach((item) => this.applyPluginMetadata(item.target.prototype)); + .forEach((item) => this.applyPluginMetadata(item.target.prototype, loadedClasses)); } - applyPluginMetadata(prototype: Function) { + applyPluginMetadata(prototype: Function, loadedClasses = new Set()) { do { if (!prototype.constructor) { return; } + // Skip redundant metadata merges for common parents. + if (loadedClasses.has(prototype.constructor)) { + return; + } + loadedClasses.add(prototype.constructor); + const metadata = Object.getOwnPropertyDescriptor( prototype.constructor, METADATA_FACTORY_NAME,