From cf755bd05e85b23d7dd77f2a65583f39ba57d779 Mon Sep 17 00:00:00 2001 From: Migushthe2nd Date: Mon, 15 Nov 2021 23:29:30 +0100 Subject: [PATCH] Implement select-always decorator --- src/constants/index.ts | 1 + src/constants/select-always.ts | 1 + src/decorators/index.ts | 1 + src/decorators/select-always.ts | 12 ++++++++++++ src/functions/build-query-recursively.ts | 13 ++++++++++++- src/index.ts | 1 + 6 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/constants/select-always.ts create mode 100644 src/decorators/index.ts create mode 100644 src/decorators/select-always.ts diff --git a/src/constants/index.ts b/src/constants/index.ts index dc7855b..2278185 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -5,4 +5,5 @@ export * from './PAGINATE'; export * from './Field'; export * from './fragment-spread'; export * from './inline-fragment'; +export * from './select-always'; export * from './slice'; diff --git a/src/constants/select-always.ts b/src/constants/select-always.ts new file mode 100644 index 0000000..de90f21 --- /dev/null +++ b/src/constants/select-always.ts @@ -0,0 +1 @@ +export const SELECT_ALWAYS = "perch:selectAlways"; diff --git a/src/decorators/index.ts b/src/decorators/index.ts new file mode 100644 index 0000000..7c17355 --- /dev/null +++ b/src/decorators/index.ts @@ -0,0 +1 @@ +export * from './select-always'; diff --git a/src/decorators/select-always.ts b/src/decorators/select-always.ts new file mode 100644 index 0000000..8ebd39c --- /dev/null +++ b/src/decorators/select-always.ts @@ -0,0 +1,12 @@ +import {SELECT_ALWAYS} from "../constants"; + +/** + * @description Force-selects columns, even if they are not in the GraphQL query. Handy if you use e.g. an `@AfterLoad()` that depends on a column. + */ +export function SelectAlways() { + return (target, property) => { + const metadata = Reflect.getMetadata(SELECT_ALWAYS, target) || []; + metadata.push(property); + Reflect.defineMetadata(SELECT_ALWAYS, metadata, target); + }; +} diff --git a/src/functions/build-query-recursively.ts b/src/functions/build-query-recursively.ts index 019b5d2..6d43533 100644 --- a/src/functions/build-query-recursively.ts +++ b/src/functions/build-query-recursively.ts @@ -1,4 +1,4 @@ -import {GraphQLQueryTree, PAGINATE} from "../"; +import {GraphQLQueryTree, SELECT_ALWAYS} from "../"; import {RelationMetadata} from "typeorm/metadata/RelationMetadata"; import {EntityMetadata, SelectQueryBuilder} from "typeorm"; @@ -28,9 +28,20 @@ export function buildQueryRecursively( .keys(tree.properties.args) .map((arg: string) => alias + "." + arg); + // Thirdly, we check the special selectAlways decorator data and force select those columns + let selectAlwaysFields = []; + if (typeof metadata.target == "function") { + const configuredFields = Reflect.getMetadata(SELECT_ALWAYS, metadata.target.prototype) || []; + selectAlwaysFields = configuredFields + // only select fields that are actually columns + .filter((propertyName) => Object.keys(metadata.propertiesMap).includes(propertyName)) + .map((propertyName) => alias + "." + propertyName) + } + // We select all of above qb.addSelect(argFields); qb.addSelect(selectedFields); + qb.addSelect(selectAlwaysFields); // We add order options Object.keys(options.order) diff --git a/src/index.ts b/src/index.ts index dc03bbc..9ded5b4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ export * from './arguments'; export * from './types'; export * from './constants'; export * from './classes'; +export * from './decorators'; export * from './functions'; export * from './interfaces'; export * from './object-types';