Skip to content

Commit c4611f5

Browse files
authored
Merge pull request #109 from tlivings/ts-conversion
Ts conversion
2 parents 2cbb86a + b9f3c7e commit c4611f5

File tree

8 files changed

+5770
-12
lines changed

8 files changed

+5770
-12
lines changed

.github/workflows/nodejs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
node-version: [12.x]
13+
node-version: [18.x]
1414
steps:
1515
- uses: actions/checkout@v2
1616
- name: Use Node.js ${{ matrix.node-version }}

.github/workflows/npmpublish.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- uses: actions/checkout@v2
1515
- uses: actions/setup-node@v1
1616
with:
17-
node-version: 12
17+
node-version: 18
1818
- run: npm install
1919
- run: npm run lint
2020
- run: npm run cover
@@ -26,21 +26,20 @@ jobs:
2626
- uses: actions/checkout@v2
2727
- uses: actions/setup-node@v1
2828
with:
29-
node-version: 12
29+
node-version: 18
3030
registry-url: https://registry.npmjs.org/
3131
- run: npm install
3232
- run: npm publish
3333
env:
3434
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
35-
3635
# publish-gpr:
3736
# needs: build
3837
# runs-on: ubuntu-latest
3938
# steps:
4039
# - uses: actions/checkout@v2
4140
# - uses: actions/setup-node@v1
4241
# with:
43-
# node-version: 12
42+
# node-version: 18
4443
# registry-url: https://npm.pkg.github.com/
4544
# - run: npm ci
4645
# - run: npm publish

CHANGELOG.md

Lines changed: 186 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,189 @@
33
- Converted to TS
44
- BREAKING removed `delegateToComponent`
55
- BREAKING excludes removed as an option in import configuration. Transforms used instead as part of a `SubschemaConfig`.
6-
- BREAKING upgraded to graphql 16.9+ peer
6+
- BREAKING upgraded to graphql 16.9+ peer
7+
8+
===
9+
10+
### v5.0.1
11+
12+
- Update @graphql-tools/utils dependency and fix samples for Apollo server v3.
13+
14+
### v5.0.0
15+
16+
- Update graphql peer-dependency for Apollo server v3.
17+
18+
### v4.0.0
19+
20+
- Updated @apollo/federation dependency for Node 18 compatibility.
21+
- Drop Node 12 compatibility.
22+
23+
### v3.1.0
24+
25+
- Updated graphql-tools dependency to fix security vulnerabilities
26+
27+
### v3.0.4
28+
29+
- Updated schema pruning dependency and TS definitions
30+
31+
### v3.0.3
32+
33+
- [FIXED] - imported components directives are merged into final schema
34+
35+
### v3.0.2
36+
37+
- schema pruning and remove broken makeExecutableSchema override
38+
39+
### v3.0.1
40+
41+
- [FIXED] - if `exclude` is undefined in a component config
42+
43+
### v3.0.0
44+
45+
- Modernized to utilize new graphql-tools
46+
- [BREAKING] - directives are not imported and maintained throughout the tree : top level component is responsible for directive implementations
47+
48+
### v2.2.0
49+
50+
- [FEATURE] - Add "hook" for custom `makeExecutableSchema` function
51+
52+
### v2.1.7
53+
54+
- [FIXED] - Explicitly removed wrapping of the federation `__resolveReference()` resolver which was preventing `__resolveReference()` from running when using `graphql-component` to build federated schemas in seperate graphql services.
55+
56+
### v2.1.6
57+
58+
- [FIXED] - A bug with `graphql-component` being used in a federated schema was brought to our attention and was attributed to the non-root type field resolver wrapping performed to help prevent double execution of resolvers with local delegation. Effectively, the resolver wrapping functionality was causing a null value to be returned (by attempting to return a value from the root arg) when the wrapper should have been calling through to the actual resolver. To fix this, separate wrapper functions are used for fields that begin with `__` (such as `__resolveType()`) versus "normal" non-root type fields. These separated wrapper functions look for similar but slightly different conditions to determine whether to "short circuit" an already computed result which ensures that the wrapper functions are short circuiting or calling through to the actual resolver in the desired situations.
59+
60+
### v2.1.5
61+
62+
- [FIXED] - delegateToComponent()'s second parameter is an options object that supports an `args` key for passing arguments to the target GraphQL operation via JavaScript from the calling resolver. Previously, if you attempted to pass an array (wrapping any form of JavaScript scalar) a type coersion error would surface. delegateToComponent's options.args parameter now supports passing Array like arguments as expected.
63+
64+
### v2.1.4
65+
66+
- [REVERT] - reverting both fixes in [2.1.2](https://github.com/ExpediaGroup/graphql-component/releases/tag/v2.1.2). The change made to unify exclusions and return pre-computed results from non-root resolvers resulted in non-root resolvers not executing when they should have. Being able to exclude non-root resolvers (not their types) is a valid work around in certain situations.
67+
68+
### v2.1.3
69+
70+
- [FIXED] - modified automatic pruning mechanism during delegation to use parent types/parent type fields instead of getFieldDef()
71+
72+
### v2.1.2
73+
74+
- [FIXED] - non-root resolvers being executed twice in certain delegate situations
75+
- [FIXED] - resolver exclusion now works identical to type exclusion. Only root types (`Query`, `Mutation`, `Subscription`) and/or fields on root types can be excluded, which was not the case for resolver functions prior to this fix.
76+
77+
### v2.1.1
78+
79+
- update `@apollo/federation` to `^0.20.4`
80+
81+
### v2.1.0
82+
83+
- [FEATURE] `delegateToComponent()` - automatically prune fields from the delegated document selection set that are not defined in the schema (component) being delegated to. This will reduced potential down stream errors as well as ensures no unintended fields are forwarded and all fields forwarded can be resolved by the schema be delegated to. This feature addresses some edge cases around variable forwarding that were not addressed in prior patch releases `2.0.4` and `2.0.5`.
84+
85+
### v2.0.5
86+
87+
- [FIXED] Reinstated variable passing to the sub-document created by `delegateToComponent()`. All variable values will be forwarded to the delegated operation, but only the variable definitions for input types or types that are in the target schema will be forwarded. This prevents errors in certain delegate situations while also allowing valid resolution of args passed as variables.
88+
89+
### v2.0.4
90+
91+
- [FIXED] the error path on errors surfaced through `delegateToComponent()` calls such that error path takes into account the already traversed path and exclusions
92+
- [FIXED] Variables from an outer operation are no longer forwarded to the sub operation created by `delegateToComponent()` this is to avoid passing along variables for types that dont exist in the schema being delegated to.
93+
94+
### v2.0.3
95+
96+
- [FIXED] individual field exclusions during import - individual field exclusions will no longer modify the original resolver map that is being imported.
97+
- [FIXED] tightened up argument forwarding when using `delegateToComponent()` - only arguments the target field is expecting will be extracted from the calling resolver or from the `args` object provided to `delegateToComponent()` depending on the situation. Previously, there were some unintended argument leakage in certain edge cases.
98+
99+
### v2.0.2
100+
101+
- [FIXED] importing directives
102+
103+
### v2.0.1
104+
105+
- [FIXED] error merging to iteratively consider the merge path to properly merge errors in complex situations such as lists
106+
107+
### v2.0.0
108+
109+
- [BREAKING] removed fragment helpers
110+
- [BREAKING] `schemaDirectives` (which returned merged directives) removed from component api
111+
- [BREAKING] removed `proxyImportedResolvers` feature flag
112+
- [BREAKING] removed `execute`
113+
- [FEATURE] added `delegateToComponent` to replace `execute`
114+
- [FEATURE] args can be overridden/passed via `delegateToComponent`
115+
- [FEATURE] added `targetRootField` option to `delegateToComponent`
116+
- [FIXED] delegation for subscription operations
117+
- [FIXED] Memoizing resolvers didn't take into account aliased requests
118+
- [FIXED] delegating an operation that contains an abstract type
119+
- [DOCS] added documentation for `delegateToComponent`
120+
- [CLEANUP] use fieldNodes to build sub-operation document in delegateToComponent such that the original operation document isn't unintentionally modified
121+
- [CLEANUP] removal of proxy resolvers creation when importing resolvers
122+
- [CLEANUP] Refactor how imports are merged together to be optimized and only run when a schema is requested
123+
- [CLEANUP] Moved tests alongside source code
124+
125+
### v1.3.1
126+
127+
- Fixed exclude mapping in GraphQLComponent constructor - Array.map was erroniously changed to Array.filter
128+
129+
### v1.3.0
130+
131+
- Imported resolvers will delegate to the imported component schema to which they belong.
132+
- Remove `this._context` as default value for context in `execute()` requiring `execute()` users to pass in context from a calling resolver.
133+
- Remove binding of `GraphQLComponent` class context to Subscription resolvers.
134+
- Apply proxyImportedResolvers regardless of how the way a component is imported and whether or not exclusions are provided. proxyImportedResolvers can still be turned off for an imported component if the component is passed via config object.
135+
136+
### v1.2.4
137+
138+
- Execute flag `mergeErrors` allows inline errors to facilitate returning multiple errors from resolvers that use `execute`.
139+
140+
### v1.2.3
141+
142+
- Allow extended properties in federated schema with custom directives
143+
144+
### v1.2.2
145+
146+
- Allow custom directives in federation (#40)
147+
148+
### v1.2.1
149+
150+
- Clean up empty types that were excluded (#38)
151+
- Reduced package size with npmignore
152+
153+
### v1.2.0
154+
155+
- Added federation support
156+
- New license copyright
157+
158+
### v1.1.3
159+
160+
- Fixed data source proxy losing instance binding
161+
- Upgraded to graphql peer ^14
162+
163+
### v1.1.1
164+
165+
- `execute` now supports both document objects and strings.
166+
167+
### v1.1.1
168+
169+
- [BREAKING from 1.1.0 (sorry, but it is 5 minutes later)]: data sources appear by constructor name on context
170+
171+
### v1.1.0
172+
173+
- Added first class data source support and overriding
174+
175+
### v1.0.4
176+
177+
- Fixes #23
178+
179+
### v1.0.3
180+
181+
- Disabling type resolvers from memoization — this doesn't work right for type resolvers.
182+
183+
### v1.0.2
184+
185+
- Outer global context setup occurs only once when `context` is fetched off component.
186+
187+
### v1.0.1
188+
189+
- Fixed .npmignore to not include misc files that added to the package size
190+
191+
### v1.0.0 — promoted from alpha.23

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
# GraphQL schema components.
44

5-
This project is designed to faciliate componentized or modularized development of GraphQL schemas.
5+
This project is designed to facilitate componentized or modularized development of GraphQL schemas.
66

77
Read more about the idea [here](https://medium.com/expedia-group-tech/graphql-component-architecture-principles-homeaway-ede8a58d6fde).
88

9-
`graphql-component` lets you build a schema progressively through a tree (faciliated through `imports`) of GraphQLComponent instances. Each GraphQLComponent instance encapsulates an executable GraphQL schema, specifically a `graphql-js` GraphQLSchema object. See the API below, but the encapsulated schema is accessible through a simple `schema` getter on a given `GraphQLComponent` instance.
9+
`graphql-component` lets you build a schema progressively through a tree (facilitated through `imports`) of GraphQLComponent instances. Each GraphQLComponent instance encapsulates an executable GraphQL schema, specifically a `graphql-js` GraphQLSchema object. See the API below, but the encapsulated schema is accessible through a simple `schema` getter on a given `GraphQLComponent` instance.
1010

1111
Generally speaking, each instance of `GraphQLComponent` has reference to an instance of [`GraphQLSchema`](https://graphql.org/graphql-js/type/#graphqlschema). This instance of `GraphQLSchema` is built in a several ways, depending on the options passed to a given `GraphQLComponent`'s constructor.
1212

@@ -31,7 +31,7 @@ federation (2 subschema services implemented via `GraphQLComponent` and a vanill
3131

3232
### Running examples:
3333
* composition: `npm run start-composition`
34-
* fedration: `npm run start-federation`
34+
* federation: `npm run start-federation`
3535
* go to `localhost:4000/graphql`
3636
* for composition this will bring up the GraphQL Playground for a plain old Apollo Server
3737
* for the federation example this will bring up the GraphQL Playground for an Apollo Federated Gateway
@@ -64,7 +64,7 @@ federation (2 subschema services implemented via `GraphQLComponent` and a vanill
6464
- `args` (`object`, optional) - an object literal whose keys/values are passed as args to the delegatee's target field resolver. By default, the resolver's args from which `delegateToComponent` is called will be passed if the target field has an argument of the same name. Otherwise, arguments passed via the `args` object will override the calling resolver's args of the same name.
6565
- `transforms` (optional `Array<Transform>`): Transform being a valid `graphql-tools` transform
6666

67-
- please see `graphql-tools` [delegateToSchema](https://www.graphql-tools.com/docs/schema-delegation/#delegatetoschema) documentation for more details on available `options` since the delegateToComponent fuctions is simply an adapter for the `GraphQLComponent` API.
67+
- please see `graphql-tools` [delegateToSchema](https://www.graphql-tools.com/docs/schema-delegation/#delegatetoschema) documentation for more details on available `options` since the delegateToComponent functions is simply an adapter for the `GraphQLComponent` API.
6868

6969
A GraphQLComponent instance (ie, `new GraphQLComponent({...})`) has the following API:
7070

@@ -174,7 +174,7 @@ Data sources in `graphql-component` do not extend `apollo-datasource`'s `DataSou
174174
Instead, data sources in components will be injected into the context, but wrapped in a proxy such that the global
175175
context will be injected as the first argument of any function implemented in a data source class.
176176

177-
This allows there to exist one instance of a data source for caching or other statefullness (like circuit breakers),
177+
This allows there to exist one instance of a data source for caching or other statefulness (like circuit breakers),
178178
while still ensuring that a data source will have the current context.
179179

180180
For example, a data source should be implemented like:

examples/federation/reviews-service/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const GraphQLComponent = require('../../../dist').default;
55
const ReviewsDataSource = require('./datasource');
66
const resolvers = require('./resolvers');
77
const types = require('./types');
8+
const toUppercaseDirective = require('./toUppercaseDirective')
89

910
class ReviewsComponent extends GraphQLComponent {
1011
constructor(options) {
@@ -17,6 +18,9 @@ const run = async function () {
1718
types,
1819
resolvers,
1920
dataSources: [new ReviewsDataSource()],
21+
directives: {
22+
toUppercase: toUppercaseDirective
23+
},
2024
federation: true
2125
});
2226

examples/federation/reviews-service/schema.graphql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
directive @toUppercase on FIELD_DEFINITION
2+
13
type Review {
24
id: ID!
3-
content: String!
5+
content: String! @toUppercase
46
}
57

68
extend type Property @key(fields: "id") {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const {getDirective, MapperKind, mapSchema} = require("@graphql-tools/utils");
2+
const {defaultFieldResolver} = require("graphql");
3+
4+
function toUppercaseDirective(directiveName) {
5+
return (schema) => mapSchema(schema, {
6+
[MapperKind.OBJECT_FIELD]: (fieldConfig) => {
7+
const upperDirective = getDirective(schema, fieldConfig, directiveName)?.[0];
8+
if (upperDirective) {
9+
const {resolve = defaultFieldResolver} = fieldConfig;
10+
return {
11+
...fieldConfig,
12+
resolve: async function (source, args, context, info) {
13+
const result = await resolve(source, args, context, info);
14+
if (typeof result === 'string') {
15+
return result.toUpperCase();
16+
}
17+
return result;
18+
}
19+
}
20+
}
21+
}
22+
})
23+
}
24+
25+
module.exports = toUppercaseDirective

0 commit comments

Comments
 (0)