Skip to content

Commit

Permalink
Some improvements and preparation for GraphQL v16 (#3443)
Browse files Browse the repository at this point in the history
* Test GraphQL v16

* Fix tests

* Move collectFields to utils

* v16< support

* More

* Fix tests for v14 and v15

* Fix

* Naming

* Use 15 in resolutions

* Go

* ...

* Cleanup

* Do not import an nested modules from graphql-js

* Fix build

* Changesets and more

* Update graphql-js peerDep range

* More

* Fix

* Improve DX

* Some memoization

* Fix memoize functions

* More

* Fix tests

* Reuse functions

* ???

* Less iterations

* Remove object.assign at all

* More

* ...
  • Loading branch information
ardatan committed Aug 31, 2021
1 parent 593ec9b commit c5b0719
Show file tree
Hide file tree
Showing 122 changed files with 1,090 additions and 1,729 deletions.
2 changes: 1 addition & 1 deletion .changeset/config.json
Expand Up @@ -3,7 +3,7 @@
"changelog": "@changesets/cli/changelog",
"commit": false,
"linked": [],
"access": "restricted",
"access": "public",
"baseBranch": "master",
"updateInternalDependencies": "patch",
"ignore": [
Expand Down
6 changes: 6 additions & 0 deletions .changeset/few-chefs-bow.md
@@ -0,0 +1,6 @@
---
'@graphql-tools/delegate': minor
'@graphql-tools/utils': minor
---

enhance(utils): copy inspect util from graphql-js
36 changes: 36 additions & 0 deletions .changeset/funny-cobras-speak.md
@@ -0,0 +1,36 @@
---
'@graphql-tools/batch-delegate': minor
'@graphql-tools/batch-execute': minor
'@graphql-tools/delegate': minor
'@graphql-tools/graphql-tag-pluck': minor
'graphql-tools': minor
'@graphql-tools/import': minor
'@graphql-tools/jest-transform': minor
'@graphql-tools/links': minor
'@graphql-tools/load': minor
'@graphql-tools/load-files': minor
'@graphql-tools/apollo-engine-loader': minor
'@graphql-tools/code-file-loader': minor
'@graphql-tools/git-loader': minor
'@graphql-tools/github-loader': minor
'@graphql-tools/graphql-file-loader': minor
'@graphql-tools/json-file-loader': minor
'@graphql-tools/module-loader': minor
'@graphql-tools/prisma-loader': minor
'@graphql-tools/url-loader': minor
'@graphql-tools/merge': minor
'@graphql-tools/mock': minor
'@graphql-tools/node-require': minor
'@graphql-tools/optimize': minor
'@graphql-tools/relay-operation-optimizer': minor
'@graphql-tools/resolvers-composition': minor
'@graphql-tools/schema': minor
'@graphql-tools/stitch': minor
'@graphql-tools/stitching-directives': minor
'@graphql-tools/utils': minor
'@graphql-tools/webpack-loader': minor
'@graphql-tools/webpack-loader-runtime': minor
'@graphql-tools/wrap': minor
---

feat: GraphQL v16 support
9 changes: 9 additions & 0 deletions .changeset/mean-coats-laugh.md
@@ -0,0 +1,9 @@
---
'@graphql-tools/batch-delegate': minor
'@graphql-tools/batch-execute': minor
'@graphql-tools/delegate': minor
'@graphql-tools/stitch': minor
'@graphql-tools/utils': minor
---

enhance(utils): move memoize functions to utils
7 changes: 7 additions & 0 deletions .changeset/spotty-queens-sniff.md
@@ -0,0 +1,7 @@
---
'@graphql-tools/delegate': minor
'@graphql-tools/stitch': minor
'@graphql-tools/utils': minor
---

enhance(utils): copy collectFields from graphql-js@16 for backwards compat
5 changes: 5 additions & 0 deletions .changeset/strange-poems-flow.md
@@ -0,0 +1,5 @@
---
'@graphql-tools/utils': patch
---

enhance(utils): memoize root types utility functions
31 changes: 13 additions & 18 deletions .github/workflows/tests.yml
Expand Up @@ -35,7 +35,10 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
graphql_version: [14, 15]
graphql_version:
- 14
- 15
# - 16.0.0-rc.1
steps:
- name: Checkout Master
uses: actions/checkout@v2
Expand Down Expand Up @@ -63,7 +66,10 @@ jobs:
matrix:
os: [ubuntu-latest] # remove windows to speed up the tests
node_version: [12, 16]
graphql_version: [14, 15]
graphql_version:
- 14
- 15
# - 16.0.0-rc.1
include:
- node_version: 14
os: windows-latest
Expand Down Expand Up @@ -98,33 +104,22 @@ jobs:
env:
CI: true
test_esm:
name: ESM Test on Node ${{matrix.node_version}} (${{matrix.os}}) and GraphQL v${{matrix.graphql_version}}
runs-on: ${{matrix.os}}
strategy:
matrix:
os: [ubuntu-latest] # remove windows to speed up the tests
node_version: [12, 16]
graphql_version: [14, 15]
include:
- node_version: 14
os: windows-latest
graphql_version: 15
name: ESM Test
runs-on: ubuntu-latest
steps:
- name: Checkout Master
uses: actions/checkout@v2
- name: Use Node
uses: actions/setup-node@master
with:
node-version: ${{ matrix.node_version }}
node-version: 16
- name: Cache Yarn
uses: actions/cache@v2
with:
path: '**/node_modules'
key: ${{ runner.os }}-${{matrix.node_version}}-${{matrix.graphql_version}}-yarn-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-16-15-yarn-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-${{matrix.node_version}}-${{matrix.graphql_version}}-yarn
- name: Use GraphQL v${{matrix.graphql_version}}
run: node ./scripts/match-graphql.js ${{matrix.graphql_version}}
${{ runner.os }}-16-15-yarn
- name: Install Dependencies using Yarn
run: yarn install --ignore-engines && git checkout yarn.lock
- name: Build Packages
Expand Down
6 changes: 4 additions & 2 deletions .vscode/settings.json
Expand Up @@ -12,11 +12,13 @@
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"node_modules": false,
"**/node_modules": true,
"test-lib": true,
"lib": true,
"coverage": true,
"npm": true
"npm": true,
"**/dist": true,
"**/dist-es5": true
},
"typescript.tsdk": "node_modules/typescript/lib"
}
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -32,7 +32,7 @@ When using `graphql-tools`, you describe the schema as a GraphQL type language s

```js

const typeDefs = `
const typeDefs = /* GraphQL */`
type Author {
id: ID! # the ! means that every author object _must_ have an id
firstName: String
Expand Down
4 changes: 0 additions & 4 deletions package.json
@@ -1,6 +1,5 @@
{
"name": "graphql-tools-monorepo",
"version": "6.2.3",
"description": "Useful tools to create and manipulate GraphQL schemas.",
"private": true,
"scripts": {
Expand Down Expand Up @@ -39,9 +38,6 @@
"url": "https://github.com/ardatan/graphql-tools/issues"
},
"homepage": "https://github.com/ardatan/graphql-tools#readme",
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
},
"devDependencies": {
"@babel/core": "7.15.0",
"@babel/plugin-proposal-class-properties": "7.14.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/batch-delegate/package.json
Expand Up @@ -26,7 +26,7 @@
"definition": "dist/index.d.ts"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
41 changes: 10 additions & 31 deletions packages/batch-delegate/src/getLoader.ts
Expand Up @@ -3,15 +3,10 @@ import { getNamedType, GraphQLOutputType, GraphQLList, GraphQLSchema, FieldNode
import DataLoader from 'dataloader';

import { delegateToSchema, SubschemaConfig } from '@graphql-tools/delegate';
import { relocatedError } from '@graphql-tools/utils';
import { memoize2, relocatedError } from '@graphql-tools/utils';

import { BatchDelegateOptions } from './types';

const cache1 = new WeakMap<
ReadonlyArray<FieldNode>,
WeakMap<GraphQLSchema | SubschemaConfig<any, any, any, any>, Map<string, DataLoader<any, any>>>
>();

function createBatchFn<K = any>(options: BatchDelegateOptions) {
const argsFromKeys = options.argsFromKeys ?? ((keys: ReadonlyArray<K>) => ({ ids: keys }));
const fieldName = options.fieldName ?? options.info.fieldName;
Expand Down Expand Up @@ -58,41 +53,25 @@ function defaultCacheKeyFn(key: any) {
return key;
}

const getLoadersMap = memoize2(function getLoadersMap<K, V, C>(
_fieldNodes: readonly FieldNode[],
_schema: GraphQLSchema | SubschemaConfig<any, any, any, any>
) {
return new Map<string, DataLoader<K, V, C>>();
});

export function getLoader<K = any, V = any, C = K>(options: BatchDelegateOptions<any>): DataLoader<K, V, C> {
const fieldName = options.fieldName ?? options.info.fieldName;
const loaders = getLoadersMap<K, V, C>(options.info.fieldNodes, options.schema);

let cache2 = cache1.get(options.info.fieldNodes);
let loader = loaders.get(fieldName);

// Prevents the keys to be passed with the same structure
const dataLoaderOptions: DataLoader.Options<any, any, any> = {
cacheKeyFn: defaultCacheKeyFn,
...options.dataLoaderOptions,
};

if (cache2 === undefined) {
cache2 = new WeakMap();
cache1.set(options.info.fieldNodes, cache2);
const loaders = new Map();
cache2.set(options.schema, loaders);
const batchFn = createBatchFn(options);
const loader = new DataLoader<K, V, C>(batchFn, dataLoaderOptions);
loaders.set(fieldName, loader);
return loader;
}

let loaders = cache2.get(options.schema);

if (loaders === undefined) {
loaders = new Map();
cache2.set(options.schema, loaders);
const batchFn = createBatchFn(options);
const loader = new DataLoader<K, V, C>(batchFn, dataLoaderOptions);
loaders.set(fieldName, loader);
return loader;
}

let loader = loaders.get(fieldName);

if (loader === undefined) {
const batchFn = createBatchFn(options);
loader = new DataLoader<K, V, C>(batchFn, dataLoaderOptions);
Expand Down
10 changes: 1 addition & 9 deletions packages/batch-delegate/src/types.ts
@@ -1,14 +1,6 @@
import { FieldNode, GraphQLSchema } from 'graphql';

import DataLoader from 'dataloader';

import { IDelegateToSchemaOptions, SubschemaConfig } from '@graphql-tools/delegate';

// TODO: remove in next major release
export type DataLoaderCache<K = any, V = any, C = K> = WeakMap<
ReadonlyArray<FieldNode>,
WeakMap<GraphQLSchema | SubschemaConfig, DataLoader<K, V, C>>
>;
import { IDelegateToSchemaOptions } from '@graphql-tools/delegate';

export type BatchDelegateFn<TContext = Record<string, any>, K = any> = (
batchDelegateOptions: BatchDelegateOptions<TContext, K>
Expand Down
4 changes: 2 additions & 2 deletions packages/batch-delegate/tests/basic.example.test.ts
Expand Up @@ -46,7 +46,7 @@ describe('batch delegation within basic stitching example', () => {
}
});

const linkTypeDefs = `
const linkTypeDefs = /* GraphQL */`
extend type Chirp {
chirpedAtUser: User
}
Expand Down Expand Up @@ -139,7 +139,7 @@ describe('batch delegation within basic stitching example', () => {
}
});

const linkTypeDefs = `
const linkTypeDefs = /* GraphQL */`
extend type User {
posts: [Post]!
}
Expand Down
2 changes: 1 addition & 1 deletion packages/batch-delegate/tests/withTransforms.test.ts
Expand Up @@ -57,7 +57,7 @@ describe('works with complex transforms', () => {
}
});

const linkTypeDefs = `
const linkTypeDefs = /* GraphQL */`
extend type User {
books: [Book!]!
}
Expand Down
2 changes: 1 addition & 1 deletion packages/batch-execute/package.json
Expand Up @@ -26,7 +26,7 @@
"definition": "dist/index.d.ts"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
5 changes: 3 additions & 2 deletions packages/batch-execute/src/createBatchingExecutor.ts
Expand Up @@ -13,8 +13,9 @@ export function createBatchingExecutor(
request: ExecutionRequest
) => Record<string, any> = defaultExtensionsReducer
): Executor {
const loader = new DataLoader(createLoadFn(executor, extensionsReducer), dataLoaderOptions);
return (request: ExecutionRequest) => {
const loadFn = createLoadFn(executor, extensionsReducer);
const loader = new DataLoader(loadFn, dataLoaderOptions);
return function batchingExecutor(request: ExecutionRequest) {
return request.operationType === 'subscription' ? executor(request) : loader.load(request);
};
}
Expand Down
3 changes: 1 addition & 2 deletions packages/batch-execute/src/getBatchingExecutor.ts
@@ -1,8 +1,7 @@
import DataLoader from 'dataloader';

import { ExecutionRequest, Executor } from '@graphql-tools/utils';
import { ExecutionRequest, Executor, memoize2of4 } from '@graphql-tools/utils';
import { createBatchingExecutor } from './createBatchingExecutor';
import { memoize2of4 } from './memoize';

export const getBatchingExecutor = memoize2of4(function getBatchingExecutor(
_context: Record<string, any>,
Expand Down
22 changes: 0 additions & 22 deletions packages/batch-execute/src/memoize.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/delegate/package.json
Expand Up @@ -26,7 +26,7 @@
"definition": "dist/index.d.ts"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"buildOptions": {
"input": "./src/index.ts"
Expand Down
2 changes: 1 addition & 1 deletion packages/delegate/src/defaultMergedResolver.ts
Expand Up @@ -25,7 +25,7 @@ export function defaultMergedResolver(
const responseKey = getResponseKeyFromInfo(info);

// check to see if parent is not a proxied result, i.e. if parent resolver was manually overwritten
// See https://github.com/apollographql/graphql-tools/issues/967
// See https://github.com/ardatan/graphql-tools/issues/967
if (!isExternalObject(parent)) {
return defaultFieldResolver(parent, args, context, info);
}
Expand Down

1 comment on commit c5b0719

@vercel
Copy link

@vercel vercel bot commented on c5b0719 Aug 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.