Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move populateExchange to a package (#567)

* start moving it out, extract common exchange helpers to commons folder, ...

* correct graphcache imports related to common ast and help

* cleanup and lint

* move shared to a package in /exchanges

* add version to pkg.json

* run linter

* add jest preset to shared

* correct the jest regex

* try adding it to tsconfig

* add build to shared

* make the build work by adding it to the tsconfig rootDirs

* remove gitignore and add readme

* fix import and set version to 0.1.0 for populate

authored by

Jovi De Croock and committed by
GitHub
eb33052a 65e84c5d

+262 -88
-1
exchanges/graphcache/src/ast/index.ts
··· 1 1 export { getFieldArguments, normalizeVariables } from './variables'; 2 2 export * from './traversal'; 3 - export * from './node'; 4 3 export * from './schemaPredicates';
+1 -1
exchanges/graphcache/src/ast/node.test.ts exchanges/shared/src/ast/node.test.ts
··· 1 - import { unwrapType } from './'; 1 + import { unwrapType } from './node'; 2 2 import { GraphQLScalarType, GraphQLNonNull, GraphQLList } from 'graphql'; 3 3 4 4 describe('unwrapType', () => {
+3 -1
exchanges/graphcache/src/ast/node.ts exchanges/shared/src/ast/node.ts
··· 9 9 GraphQLOutputType, 10 10 Kind, 11 11 isWrappingType, 12 + GraphQLWrappingType, 12 13 } from 'graphql'; 13 14 14 - import { SelectionSet, GraphQLFlatType } from '../types'; 15 + export type SelectionSet = ReadonlyArray<SelectionNode>; 16 + export type GraphQLFlatType = Exclude<GraphQLOutputType, GraphQLWrappingType>; 15 17 16 18 /** Returns the name of a given node */ 17 19 export const getName = (node: { name: NameNode }): string => node.name.value;
+1 -1
exchanges/graphcache/src/ast/schemaPredicates.ts
··· 9 9 GraphQLUnionType, 10 10 } from 'graphql'; 11 11 12 - import { invariant, warn } from '../helpers/help'; 12 + import { warn, invariant } from 'shared'; 13 13 14 14 export const isFieldNullable = ( 15 15 schema: GraphQLSchema,
+2 -1
exchanges/graphcache/src/ast/traversal.test.ts
··· 1 1 import gql from 'graphql-tag'; 2 - import { getSelectionSet } from './node'; 2 + import { getSelectionSet } from 'shared'; 3 + 3 4 import { getMainOperation, shouldInclude } from './traversal'; 4 5 5 6 describe('getMainOperation', () => {
+1 -2
exchanges/graphcache/src/ast/traversal.ts
··· 7 7 valueFromASTUntyped, 8 8 Kind, 9 9 } from 'graphql'; 10 + import { invariant, getName } from 'shared'; 10 11 11 - import { invariant } from '../helpers/help'; 12 - import { getName } from './node'; 13 12 import { Fragments, Variables } from '../types'; 14 13 15 14 const isFragmentNode = (node: DefinitionNode): node is FragmentDefinitionNode =>
+1 -1
exchanges/graphcache/src/ast/variables.ts
··· 3 3 OperationDefinitionNode, 4 4 valueFromASTUntyped, 5 5 } from 'graphql'; 6 + import { getName } from 'shared'; 6 7 7 - import { getName } from './node'; 8 8 import { makeDict } from '../helpers/dict'; 9 9 import { Variables } from '../types'; 10 10
+20 -1
exchanges/graphcache/src/helpers/help.ts exchanges/shared/src/helpers/help.ts
··· 4 4 // You can read more about the messages themselves in `docs/help.md` 5 5 6 6 import { Kind, ExecutableDefinitionNode, InlineFragmentNode } from 'graphql'; 7 - import { ErrorCode } from '../types'; 7 + 8 + export type ErrorCode = 9 + | 1 10 + | 2 11 + | 3 12 + | 4 13 + | 5 14 + | 6 15 + | 7 16 + | 8 17 + | 9 18 + | 10 19 + | 11 20 + | 12 21 + | 13 22 + | 15 23 + | 16 24 + | 17 25 + | 18 26 + | 19; 8 27 9 28 type DebugNode = ExecutableDefinitionNode | InlineFragmentNode; 10 29
+1 -1
exchanges/graphcache/src/index.ts
··· 2 2 export * from './types'; 3 3 export { Store, initDataState, clearDataState } from './store'; 4 4 export { cacheExchange } from './cacheExchange'; 5 - export { populateExchange } from './populateExchange'; 5 + export { populateExchange } from '@urql/exchange-populate';
+2 -9
exchanges/graphcache/src/operations/invalidate.ts
··· 1 1 import { FieldNode } from 'graphql'; 2 + import { getSelectionSet, getName, SelectionSet } from 'shared'; 2 3 3 4 import { 4 5 getMainOperation, 5 6 normalizeVariables, 6 7 getFragments, 7 - getSelectionSet, 8 - getName, 9 8 getFieldArguments, 10 9 } from '../ast'; 11 10 12 - import { 13 - EntityField, 14 - OperationRequest, 15 - Variables, 16 - Fragments, 17 - SelectionSet, 18 - } from '../types'; 11 + import { EntityField, OperationRequest, Variables, Fragments } from '../types'; 19 12 20 13 import * as InMemoryData from '../store/data'; 21 14 import { Store, keyOfField } from '../store';
+9 -6
exchanges/graphcache/src/operations/query.ts
··· 1 1 import { FieldNode, DocumentNode, FragmentDefinitionNode } from 'graphql'; 2 + import { 3 + getSelectionSet, 4 + getName, 5 + SelectionSet, 6 + getFragmentTypeName, 7 + getFieldAlias, 8 + warn, 9 + pushDebugNode, 10 + } from 'shared'; 2 11 3 12 import { 4 13 getFragments, 5 14 getMainOperation, 6 - getSelectionSet, 7 15 normalizeVariables, 8 - getName, 9 16 getFieldArguments, 10 - getFieldAlias, 11 - getFragmentTypeName, 12 17 } from '../ast'; 13 18 14 19 import { ··· 17 22 Data, 18 23 DataField, 19 24 Link, 20 - SelectionSet, 21 25 OperationRequest, 22 26 NullArray, 23 27 } from '../types'; ··· 33 37 34 38 import * as InMemoryData from '../store/data'; 35 39 import { makeDict } from '../helpers/dict'; 36 - import { warn, pushDebugNode } from '../helpers/help'; 37 40 import { SelectionIterator, ensureData } from './shared'; 38 41 39 42 import {
+12 -19
exchanges/graphcache/src/operations/shared.ts
··· 1 1 import { FieldNode, InlineFragmentNode, FragmentDefinitionNode } from 'graphql'; 2 + import { 3 + warn, 4 + pushDebugNode, 5 + isInlineFragment, 6 + getTypeCondition, 7 + getSelectionSet, 8 + getName, 9 + SelectionSet, 10 + isFieldNode, 11 + } from 'shared'; 2 12 3 - import { warn, pushDebugNode } from '../helpers/help'; 4 13 import { hasField } from '../store/data'; 5 14 import { Store, keyOfField } from '../store'; 6 15 7 - import { 8 - Fragments, 9 - Variables, 10 - SelectionSet, 11 - DataField, 12 - NullArray, 13 - Data, 14 - } from '../types'; 16 + import { Fragments, Variables, DataField, NullArray, Data } from '../types'; 15 17 16 - import { 17 - getTypeCondition, 18 - getFieldArguments, 19 - shouldInclude, 20 - isInterfaceOfType, 21 - isFieldNode, 22 - isInlineFragment, 23 - getSelectionSet, 24 - getName, 25 - } from '../ast'; 18 + import { getFieldArguments, shouldInclude, isInterfaceOfType } from '../ast'; 26 19 27 20 interface Context { 28 21 store: Store;
+10 -6
exchanges/graphcache/src/operations/write.ts
··· 1 1 import { FieldNode, DocumentNode, FragmentDefinitionNode } from 'graphql'; 2 2 3 3 import { 4 - getFieldAlias, 5 4 getFragments, 6 5 getMainOperation, 7 - getSelectionSet, 8 6 normalizeVariables, 9 - getFragmentTypeName, 10 - getName, 11 7 getFieldArguments, 12 8 isFieldAvailableOnType, 13 9 } from '../ast'; 10 + import { 11 + getSelectionSet, 12 + getName, 13 + SelectionSet, 14 + getFragmentTypeName, 15 + getFieldAlias, 16 + invariant, 17 + warn, 18 + pushDebugNode, 19 + } from 'shared'; 14 20 15 21 import { 16 22 NullArray, ··· 18 24 Variables, 19 25 Data, 20 26 Link, 21 - SelectionSet, 22 27 OperationRequest, 23 28 } from '../types'; 24 29 ··· 33 38 34 39 import * as InMemoryData from '../store/data'; 35 40 import { makeDict } from '../helpers/dict'; 36 - import { invariant, warn, pushDebugNode } from '../helpers/help'; 37 41 import { SelectionIterator, ensureData } from './shared'; 38 42 39 43 export interface WriteResult {
exchanges/graphcache/src/populateExchange.test.ts exchanges/populate/src/populateExchange.test.ts
+3 -4
exchanges/graphcache/src/populateExchange.ts exchanges/populate/src/populateExchange.ts
··· 14 14 Kind, 15 15 visit, 16 16 } from 'graphql'; 17 + import { getName, getSelectionSet, unwrapType, invariant, warn } from 'shared'; 17 18 18 19 import { pipe, tap, map } from 'wonka'; 19 20 import { Exchange, Operation } from '@urql/core'; 20 21 21 - import { getName, getSelectionSet, unwrapType } from './ast'; 22 - import { makeDict } from './helpers/dict'; 23 - import { invariant, warn } from './helpers/help'; 24 - 25 22 interface PopulateExchangeOpts { 26 23 schema: IntrospectionQuery; 27 24 } 25 + 26 + const makeDict = (): any => Object.create(null); 28 27 29 28 /** An exchange for auto-populating mutations with a required response body. */ 30 29 export const populateExchange = ({
+1 -1
exchanges/graphcache/src/store/data.ts
··· 7 7 } from '../types'; 8 8 9 9 import { makeDict } from '../helpers/dict'; 10 - import { invariant, currentDebugStack } from '../helpers/help'; 10 + import { invariant, currentDebugStack } from 'shared'; 11 11 import { fieldInfoOfKey, joinKeys, prefixKey } from './keys'; 12 12 import { defer } from './timing'; 13 13
+1 -1
exchanges/graphcache/src/store/store.ts
··· 20 20 KeyingConfig, 21 21 DataFields, 22 22 } from '../types'; 23 - import { invariant } from '../helpers/help'; 23 + import { invariant } from 'shared'; 24 24 25 25 import { read, readFragment } from '../operations/query'; 26 26 import { writeFragment, startWrite } from '../operations/write';
+1 -30
exchanges/graphcache/src/types.ts
··· 1 - import { 2 - DocumentNode, 3 - FragmentDefinitionNode, 4 - SelectionNode, 5 - GraphQLOutputType, 6 - GraphQLWrappingType, 7 - } from 'graphql'; 1 + import { DocumentNode, FragmentDefinitionNode } from 'graphql'; 8 2 9 3 // Helper types 10 4 export type NullArray<T> = Array<null | T>; 11 5 12 - // GraphQL helper types 13 - export type SelectionSet = ReadonlyArray<SelectionNode>; 14 - export type GraphQLFlatType = Exclude<GraphQLOutputType, GraphQLWrappingType>; 15 6 export interface Fragments { 16 7 [fragmentName: string]: void | FragmentDefinitionNode; 17 8 } ··· 185 176 read(): Promise<SerializedEntries>; 186 177 write(data: SerializedEntries): Promise<void>; 187 178 } 188 - 189 - export type ErrorCode = 190 - | 1 191 - | 2 192 - | 3 193 - | 4 194 - | 5 195 - | 6 196 - | 7 197 - | 8 198 - | 9 199 - | 10 200 - | 11 201 - | 12 202 - | 13 203 - | 15 204 - | 16 205 - | 17 206 - | 18 207 - | 19;
+3 -1
exchanges/graphcache/tsconfig.json
··· 2 2 "extends": "../../tsconfig.json", 3 3 "include": ["src"], 4 4 "compilerOptions": { 5 + "rootDirs": ["./", "../shared", "../populate"], 5 6 "baseUrl": "./", 6 7 "paths": { 7 8 "urql": ["../../node_modules/urql/src"], 8 9 "*-urql": ["../../node_modules/*-urql/src"], 9 - "@urql/*": ["../../node_modules/@urql/*/src"] 10 + "@urql/*": ["../../node_modules/@urql/*/src"], 11 + "shared": ["../../node_modules/shared/src"] 10 12 } 11 13 } 12 14 }
+7
exchanges/populate/CHANGELOG.md
··· 1 + # @urql/exchange-populate 2 + 3 + ## 0.1.0 4 + 5 + ### Initial release 6 + 7 + - Moved the `populateExchange` from `@urql/exchange-graphcache` to its own package.
+77
exchanges/populate/README.md
··· 1 + # @urql/exchange-populate 2 + 3 + `populate` is an exchange for auto-populating fields in your mutations. 4 + 5 + ## Quick Start Guide 6 + 7 + First install `@urql/exchange-populate` alongside `urql`: 8 + 9 + ```sh 10 + yarn add @urql/exchange-populate 11 + # or 12 + npm install --save @urql/exchange-populate 13 + ``` 14 + 15 + You'll then need to add the `populateExchange`, that this package exposes. 16 + 17 + ```js 18 + import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql'; 19 + import { populateExchange } from '@urql/exchange-populate'; 20 + 21 + const client = createClient({ 22 + url: 'http://localhost:1234/graphql', 23 + exchanges: [ 24 + dedupExchange, 25 + populateExchange, 26 + cacheExchange, 27 + fetchExchange, 28 + ], 29 + }); 30 + ``` 31 + 32 + ## Example usage 33 + 34 + Consider the following queries which have been requested in other parts of your application: 35 + 36 + 37 + ```graphql 38 + # Query 1 39 + { 40 + todos { 41 + id 42 + name 43 + } 44 + } 45 + 46 + # Query 2 47 + { 48 + todos { 49 + id 50 + createdAt 51 + } 52 + } 53 + ``` 54 + 55 + Without the `populateExchange` you may write a mutation like the following which returns a newly created todo item: 56 + 57 + ```graphql 58 + # Without populate 59 + mutation addTodo(id: ID!) { 60 + addTodo(id: $id) { 61 + id # To update Query 1 & 2 62 + name # To update Query 1 63 + createdAt # To update Query 2 64 + } 65 + } 66 + ``` 67 + 68 + By using `populateExchange`, you no longer need to manually specify the selection set required to update your other queries. Instead you can just add the `@populate` directive. 69 + 70 + ```graphql 71 + # With populate 72 + mutation addTodo(id: ID!) { 73 + addTodo(id: $id) @populate 74 + } 75 + ``` 76 + 77 + > Note: The above two mutations produce an identical GraphQL request.
+61
exchanges/populate/package.json
··· 1 + { 2 + "name": "@urql/exchange-populate", 3 + "version": "0.1.0", 4 + "description": "An exchange that automaticcally populates the mutation selection body", 5 + "sideEffects": false, 6 + "homepage": "https://formidable.com/open-source/urql/docs/", 7 + "bugs": "https://github.com/FormidableLabs/urql/issues", 8 + "license": "MIT", 9 + "repository": { 10 + "type": "git", 11 + "url": "https://github.com/FormidableLabs/urql.git", 12 + "directory": "exchanges/populate" 13 + }, 14 + "keywords": [ 15 + "urql", 16 + "formidablelabs", 17 + "exchanges" 18 + ], 19 + "main": "dist/urql-exchange-populate.cjs.js", 20 + "module": "dist/urql-exchange-populate.esm.js", 21 + "types": "dist/types/index.d.ts", 22 + "source": "src/index.ts", 23 + "exports": { 24 + ".": { 25 + "import": "dist/urql-exchange-populate.esm.js", 26 + "require": "dist/urql-exchange-populate.cjs.js", 27 + "types": "dist/types/index.d.ts", 28 + "source": "src/index.ts" 29 + } 30 + }, 31 + "files": [ 32 + "LICENSE", 33 + "CHANGELOG.md", 34 + "README.md", 35 + "dist/", 36 + "extras/" 37 + ], 38 + "scripts": { 39 + "test": "jest", 40 + "clean": "rimraf dist extras", 41 + "check": "tsc --noEmit", 42 + "lint": "eslint --ext=js,jsx,ts,tsx .", 43 + "build": "rollup -c ../../scripts/rollup/config.js", 44 + "prepare": "../../scripts/prepare/index.js", 45 + "prepublishOnly": "run-s clean test build" 46 + }, 47 + "jest": { 48 + "preset": "../../scripts/jest/preset" 49 + }, 50 + "dependencies": { 51 + "wonka": "^3.2.1 || ^4.0.0", 52 + "@urql/core": ">=1.9.0" 53 + }, 54 + "peerDependencies": { 55 + "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" 56 + }, 57 + "devDependencies": { 58 + "graphql": "^14.5.8", 59 + "graphql-tag": "^2.10.1" 60 + } 61 + }
+1
exchanges/populate/src/index.ts
··· 1 + export * from './populateExchange';
+14
exchanges/populate/tsconfig.json
··· 1 + { 2 + "extends": "../../tsconfig.json", 3 + "include": ["src"], 4 + "compilerOptions": { 5 + "baseUrl": "./", 6 + "rootDirs": ["./", "../shared", "../populate"], 7 + "paths": { 8 + "urql": ["../../node_modules/urql/src"], 9 + "*-urql": ["../../node_modules/*-urql/src"], 10 + "@urql/*": ["../../node_modules/@urql/*/src"], 11 + "shared": ["../../node_modules/shared/src"] 12 + } 13 + } 14 + }
+11
exchanges/shared/package.json
··· 1 + { 2 + "private": true, 3 + "name": "shared", 4 + "version": "1.0.0", 5 + "scripts": { 6 + "build": "echo 'not building shared'" 7 + }, 8 + "jest": { 9 + "preset": "../../scripts/jest/preset" 10 + } 11 + }
+1
exchanges/shared/src/ast/index.ts
··· 1 + export * from './node';
+1
exchanges/shared/src/helpers/index.ts
··· 1 + export * from './help';
+2
exchanges/shared/src/index.ts
··· 1 + export * from './ast'; 2 + export * from './helpers';
+12
exchanges/shared/tsconfig.json
··· 1 + { 2 + "extends": "../../tsconfig.json", 3 + "include": ["src"], 4 + "compilerOptions": { 5 + "baseUrl": "./", 6 + "paths": { 7 + "urql": ["../../node_modules/urql/src"], 8 + "*-urql": ["../../node_modules/*-urql/src"], 9 + "@urql/*": ["../../node_modules/@urql/*/src"] 10 + } 11 + } 12 + }
+1
scripts/jest/preset.js
··· 10 10 "^urql$": "<rootDir>/../../node_modules/urql/src", 11 11 "^(.*-urql)$": "<rootDir>/../../node_modules/$1/src", 12 12 "^@urql/(.*)$": "<rootDir>/../../node_modules/@urql/$1/src", 13 + "^shared$": "<rootDir>/../../node_modules/shared/src", 13 14 }, 14 15 watchPlugins: ['jest-watch-yarn-workspaces'], 15 16 testRegex: '(src/.*(\\.|/)(test|spec))\\.tsx?$',
+2 -1
tsconfig.json
··· 5 5 "urql": ["packages/react-urql/src"], 6 6 "*-urql": ["packages/*-urql/src"], 7 7 "@urql/exchange-*": ["exchanges/*/src"], 8 - "@urql/*": ["packages/*-urql/src", "packages/*/src"] 8 + "@urql/*": ["packages/*-urql/src", "packages/*/src"], 9 + "shared": ["exchanges/shared/src"] 9 10 }, 10 11 "esModuleInterop": true, 11 12 "forceConsistentCasingInFileNames": true,