Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(resolvers-composition): add support for glob patterns #3132

Merged
5 changes: 3 additions & 2 deletions packages/resolvers-composition/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"license": "MIT",
"sideEffects": false,
"main": "dist/index.js",
"module": "dist/index.mjs",
"exports": {
"module": "dist/index.mjs",
"exports": {
".": {
"require": "./dist/index.js",
"import": "./dist/index.mjs"
Expand All @@ -35,6 +35,7 @@
"dependencies": {
"@graphql-tools/utils": "^7.9.1",
"lodash": "4.17.21",
"micromatch": "^4.0.4",
"tslib": "~2.3.0"
},
"publishConfig": {
Expand Down
99 changes: 41 additions & 58 deletions packages/resolvers-composition/src/resolvers-composition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { chainFunctions } from './chain-functions';
import _ from 'lodash';
import { GraphQLFieldResolver, GraphQLScalarTypeConfig } from 'graphql';
import { asArray } from '@graphql-tools/utils';
import { matcher } from 'micromatch';

export type ResolversComposition<
Resolver extends GraphQLFieldResolver<any, any, any> = GraphQLFieldResolver<any, any>
Expand Down Expand Up @@ -30,85 +31,67 @@ function resolveRelevantMappings<Resolvers extends Record<string, any> = Record<
path: string,
allMappings: ResolversComposerMapping<Resolvers>
): string[] {
const split = path.split('.');
if (!resolvers) {
return [];
}

if (split.length === 2) {
const typeName = split[0];
const [typeNameOrGlob, fieldNameOrGlob] = path.split('.');
const isTypeMatch = matcher(typeNameOrGlob);

if (isScalarTypeConfiguration(resolvers[typeName])) {
return [];
let fixedFieldGlob = fieldNameOrGlob;
// convert single value OR `{singleField}` to `singleField` as matching will fail otherwise
if (fixedFieldGlob.includes('{') && !fixedFieldGlob.includes(',')) {
fixedFieldGlob = fieldNameOrGlob.replace('{', '').replace('}', '');
}
fixedFieldGlob = fixedFieldGlob.replace(', ', ',').trim();

const isFieldMatch = matcher(fixedFieldGlob);

const mappings: string[] = [];
for (const typeName in resolvers) {
if (!isTypeMatch(typeName)) {
continue;
}

const fieldName = split[1];
if (isScalarTypeConfiguration(resolvers[typeName])) {
continue;
}

if (typeName === '*') {
if (!resolvers) {
return [];
}
const mappings: string[] = [];
for (const typeName in resolvers) {
const relevantMappings = resolveRelevantMappings(resolvers, `${typeName}.${fieldName}`, allMappings);
for (const relevantMapping of relevantMappings) {
mappings.push(relevantMapping);
}
}
return mappings;
const fieldMap = resolvers[typeName];
if (!fieldMap) {
return [];
}

if (fieldName === '*') {
const fieldMap = resolvers[typeName];
if (!fieldMap) {
return [];
}
const mappings: string[] = [];
for (const field in fieldMap) {
const relevantMappings = resolveRelevantMappings(resolvers, `${typeName}.${field}`, allMappings);
for (const relevantMapping of relevantMappings) {
if (!allMappings[relevantMapping]) {
mappings.push(relevantMapping);
}
}
for (const field in fieldMap) {
if (!isFieldMatch(field)) {
continue;
}
return mappings;
} else {

const paths = [];

if (resolvers[typeName] && resolvers[typeName][fieldName]) {
if (resolvers[typeName][fieldName].subscribe) {
paths.push(path + '.subscribe');
const resolvedPath = `${typeName}.${field}`;

if (resolvers[typeName] && resolvers[typeName][field]) {
if (resolvers[typeName][field].subscribe) {
paths.push(resolvedPath + '.subscribe');
}

if (resolvers[typeName][fieldName].resolve) {
paths.push(path + '.resolve');
if (resolvers[typeName][field].resolve) {
paths.push(resolvedPath + '.resolve');
}

if (typeof resolvers[typeName][fieldName] === 'function') {
paths.push(path);
if (typeof resolvers[typeName][field] === 'function') {
paths.push(resolvedPath);
}
}

return paths;
}
} else if (split.length === 1) {
const typeName = split[0];

const fieldMap = resolvers[typeName];
if (!fieldMap) {
return [];
}

const mappings: string[] = [];

for (const fieldName in fieldMap) {
const relevantMappings = resolveRelevantMappings(resolvers, `${typeName}.${fieldName}`, allMappings);
for (const relevantMapping of relevantMappings) {
mappings.push(relevantMapping);
for (const path of paths) {
mappings.push(path);
}
}
return mappings;
}

return [];
return mappings;
}

/**
Expand Down
114 changes: 114 additions & 0 deletions packages/resolvers-composition/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@ardatan/[email protected]":
version "0.0.6"
resolved "https://registry.yarnpkg.com/@ardatan/aggregate-error/-/aggregate-error-0.0.6.tgz#fe6924771ea40fc98dc7a7045c2e872dc8527609"
integrity sha512-vyrkEHG1jrukmzTPtyWB4NLPauUw5bQeg4uhn8f+1SSynmrOcyvlb1GKQjjgoBzElLdfXCRYX8UnBlhklOHYRQ==
dependencies:
tslib "~2.0.1"

"@graphql-tools/utils@^7.9.1":
version "7.10.0"
resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-7.10.0.tgz#07a4cb5d1bec1ff1dc1d47a935919ee6abd38699"
integrity sha512-d334r6bo9mxdSqZW6zWboEnnOOFRrAPVQJ7LkU8/6grglrbcu6WhwCLzHb90E94JI3TD3ricC3YGbUqIi9Xg0w==
dependencies:
"@ardatan/aggregate-error" "0.0.6"
camel-case "4.1.2"
tslib "~2.2.0"

"@types/[email protected]":
version "4.14.170"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.170.tgz#0d67711d4bf7f4ca5147e9091b847479b87925d6"
integrity sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==

braces@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
fill-range "^7.0.1"

[email protected]:
version "4.1.2"
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a"
integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==
dependencies:
pascal-case "^3.1.2"
tslib "^2.0.3"

fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
dependencies:
to-regex-range "^5.0.1"

is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==

[email protected]:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

lower-case@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==
dependencies:
tslib "^2.0.3"

micromatch@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
dependencies:
braces "^3.0.1"
picomatch "^2.2.3"

no-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==
dependencies:
lower-case "^2.0.2"
tslib "^2.0.3"

pascal-case@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb"
integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==
dependencies:
no-case "^3.0.4"
tslib "^2.0.3"

picomatch@^2.2.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==

to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
dependencies:
is-number "^7.0.0"

tslib@^2.0.3, tslib@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==

tslib@~2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==

tslib@~2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"
integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==