Skip to content
This repository has been archived by the owner on Oct 23, 2024. It is now read-only.

Commit

Permalink
feat: add support for root value
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Please add the root value as third argument, null or an
empty object are great default values for this.
  • Loading branch information
Daniel Schmidt authored and DanielMSchmidt committed Jan 22, 2019
1 parent 0897945 commit aa6aa0d
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 33 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const query = `
}
`;

const postStream = graphql(query, schema);
const postStream = graphql(schema, query);
const PostsList = componentFromStream(propsStream =>
propsStream.pipe(
combineLatest(postStream, (props, result) => {
Expand Down Expand Up @@ -107,10 +107,11 @@ ReactDOM.render(<App />, rootElement);

- fragments of all kinds
- subscriptions (as everything is treated as a subscription)
- only one top-level operation is supported

## API

The first argument you pass into `reactive-graphql` is an executable schema, the second one a GraphQL query, either parsed or as string. You can pass in the root context as an object as a third parameter. The variables can be passed as 4th parameter.
The 1st argument you pass into `reactive-graphql` is an executable schema, the 2nd one a GraphQL query, either parsed or as string. You can pass in the root value as 3rd and the root context as an object as 4th parameter. The variables can be passed as 5th parameter.

The implementation will always return an Observable.
If any of the resolvers returns an error the implementation will emit the error on the stream.
Expand Down
88 changes: 67 additions & 21 deletions src/__tests__/graphqlObservable-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,24 @@ const typeDefs = `

const mockResolvers = {
Query: {
launched: (_, args, ctx) => {
launched: (parent, args, ctx) => {
const { name } = args;

// act according with the type of filter
if (name === undefined) {
// When no filter is passed
return ctx.query;
if (!parent) {
return ctx.query;
}

return ctx.query.pipe(
map((shuttles: any[]) =>
shuttles.map(shuttle => ({
...shuttle,
name: shuttle.name + parent.shuttleSuffix
}))
)
);
} else if (typeof name === "string") {
// When the filter is a value
return ctx.query.pipe(
Expand Down Expand Up @@ -179,6 +190,10 @@ const itMarbles = (title, test) => {
return it(title, marbles(test));
};

itMarbles.only = (title, test) => {
return it.only(title, marbles(test));
};

describe("graphqlObservable", function() {
describe("Query", function() {
itMarbles("solves listing all fields", function(m) {
Expand All @@ -196,7 +211,7 @@ describe("graphqlObservable", function() {
a: { data: { launched: expectedData } }
});

const result = graphql(schema, query, { query: dataSource });
const result = graphql(schema, query, null, { query: dataSource });

m.expect(result.pipe(take(1))).toBeObservable(expected);
});
Expand All @@ -216,7 +231,7 @@ describe("graphqlObservable", function() {
a: { data: { launched: expectedData } }
});

const result = graphql(schema, query, { query: dataSource });
const result = graphql(schema, query, null, { query: dataSource });

m.expect(result.pipe(take(1))).toBeObservable(expected);
});
Expand All @@ -241,6 +256,7 @@ describe("graphqlObservable", function() {
const result = graphql(
schema,
query,
null,
{
query: dataSource
},
Expand Down Expand Up @@ -268,7 +284,7 @@ describe("graphqlObservable", function() {
a: { data: { launched: [expectedData[0]] } }
});

const result = graphql(schema, query, {
const result = graphql(schema, query, null, {
query: dataSource
});

Expand All @@ -290,7 +306,7 @@ describe("graphqlObservable", function() {
a: { data: { launched: [{ name: "discovery" }] } }
});

const result = graphql(schema, query, {
const result = graphql(schema, query, null, {
query: dataSource
});

Expand All @@ -312,13 +328,42 @@ describe("graphqlObservable", function() {
a: { data: { launched: [{ title: "challenger" }] } }
});

const result = graphql(schema, query, {
const result = graphql(schema, query, null, {
query: dataSource
});

m.expect(result.pipe(take(1))).toBeObservable(expected);
});

itMarbles.only("resolves using root value", function(m) {
const query = gql`
query {
launched {
name
}
}
`;

const expectedData = [{ name: "challenger", firstFlight: 1984 }];
const dataSource = of(expectedData);
const expected = m.cold("(a|)", {
a: { data: { launched: [{ name: "challenger-nasa" }] } }
});

const result = graphql(
schema,
query,
{
shuttleSuffix: "-nasa"
},
{
query: dataSource
}
);

m.expect(result.pipe(take(1))).toBeObservable(expected);
});

describe("Field Resolvers", function() {
describe("Leafs", function() {
itMarbles("defaults to return the property on the object", function(m) {
Expand All @@ -332,7 +377,7 @@ describe("graphqlObservable", function() {
const expected = m.cold("(a|)", {
a: { data: { plain: { noFieldResolver: "Yes" } } }
});
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});

Expand All @@ -347,7 +392,7 @@ describe("graphqlObservable", function() {
const expected = m.cold("(a|)", {
a: { data: { plain: { fieldResolver: "I am a field resolver" } } }
});
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});

Expand All @@ -370,7 +415,7 @@ describe("graphqlObservable", function() {
}
}
});
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});

Expand All @@ -393,7 +438,7 @@ describe("graphqlObservable", function() {
}
}
});
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});

Expand All @@ -414,7 +459,7 @@ describe("graphqlObservable", function() {
}
}
});
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});
});
Expand All @@ -439,7 +484,7 @@ describe("graphqlObservable", function() {
}
}
});
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});

Expand All @@ -466,7 +511,7 @@ describe("graphqlObservable", function() {
}
}
});
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});

Expand All @@ -493,7 +538,7 @@ describe("graphqlObservable", function() {
}
}
});
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});

Expand All @@ -516,7 +561,7 @@ describe("graphqlObservable", function() {
}
}
});
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});
});
Expand Down Expand Up @@ -546,7 +591,7 @@ describe("graphqlObservable", function() {
}
}
});
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});
});
Expand All @@ -564,7 +609,7 @@ describe("graphqlObservable", function() {
"reactive-graphql: resolver 'throwingResolver' throws this error: 'Error: my personal error'"
)
);
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
});

Expand All @@ -583,7 +628,7 @@ describe("graphqlObservable", function() {
"reactive-graphql: field 'youDontKnowMe' was not found on type 'Query'. The only fields found in this Object are: plain,item,nested,throwingResolver."
)
);
const result = graphql(fieldResolverSchema, query, {});
const result = graphql(fieldResolverSchema, query, null, {});
m.expect(result.pipe(take(1))).toBeObservable(expected);
}
);
Expand All @@ -602,7 +647,7 @@ describe("graphqlObservable", function() {
const fakeRequest = { name: "RocketShip" };
const commandContext = of(fakeRequest);

const result = graphql(schema, mutation, {
const result = graphql(schema, mutation, null, {
mutation: commandContext
});

Expand All @@ -626,7 +671,7 @@ describe("graphqlObservable", function() {

const commandContext = of("a request");

const result = graphql(schema, mutation, {
const result = graphql(schema, mutation, null, {
mutation: commandContext
});

Expand Down Expand Up @@ -662,6 +707,7 @@ describe("graphqlObservable", function() {
const result = graphql(
schema,
mutation,
null,
{
mutation: commandContext
},
Expand Down
16 changes: 8 additions & 8 deletions src/__tests__/reference/starWarsQuery-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import { take } from "rxjs/operators";
import StarWarsSchema from "./starWarsSchema";
import { graphql as graphqlObservable } from "../../";

const graphql = (
schema,
query,
_rootValue?,
contextValue?,
variableValues?
) => {
const graphql = (schema, query, rootValue?, contextValue?, variableValues?) => {
return new Promise(resolve => {
const taggedQuery = gql`
${query}
`;
graphqlObservable(schema, taggedQuery, contextValue, variableValues)
graphqlObservable(
schema,
taggedQuery,
rootValue,
contextValue,
variableValues
)
.pipe(take(1))
.subscribe(resolve);
});
Expand Down
5 changes: 3 additions & 2 deletions src/reactive-graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ function isFieldWithResolver(
export default function graphql<T = object>(
schema: Schema,
query: string | DocumentNode,
rootValue?: any,
context: object = {},
variables: object = {}
): Observable<{ data?: T; errors?: string[] }> {
Expand All @@ -94,7 +95,7 @@ export default function graphql<T = object>(

const types = schema._typeMap;

return resolve(doc.definitions[0], context, variables, null, null).pipe(
return resolve(doc.definitions[0], context, variables, rootValue, null).pipe(
map((data: T) => ({
data
}))
Expand All @@ -110,7 +111,7 @@ export default function graphql<T = object>(
if (isOperationDefinition(definition)) {
const nextType = getResultType(type, definition, parent);

return resolveResult(definition, context, variables, null, nextType);
return resolveResult(definition, context, variables, parent, nextType);
}

// The definition gives us the field to resolve
Expand Down

0 comments on commit aa6aa0d

Please sign in to comment.