Skip to content

Commit

Permalink
feat: initial WHERE support
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Jackson committed Feb 2, 2019
1 parent fbb7873 commit 5271b5a
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 121 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,29 @@ const { posts: postsWithAuthorAndComments } = await firegraph.resolve(firestore,
`)
```

### Filtering Results

One of our primary goals is to wrap the Firestore API in its entirety. Filtering
is one of the areas where GraphQL query syntax will really shine:

``` typescript
const authorId = 'sZOgUC33ijsGSzX17ybT';
const { posts: postsBySomeAuthor } = await firegraph.resolve(firestore, gql`
query {
posts(where: {
author: ${authorId},
}) {
id
message
author(matchesKeyFromCollection: "users") {
id
}
}
}
`);
```


# Roadmap

- [x] Querying values from collections
Expand Down
18 changes: 0 additions & 18 deletions examples/queries/references.graphql

This file was deleted.

13 changes: 0 additions & 13 deletions examples/queries/types.graphql

This file was deleted.

28 changes: 0 additions & 28 deletions examples/references.ts

This file was deleted.

23 changes: 0 additions & 23 deletions examples/types.ts

This file was deleted.

16 changes: 0 additions & 16 deletions examples/where.ts

This file was deleted.

15 changes: 14 additions & 1 deletion src/firegraph/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,26 @@ import { resolveDocument } from './Document';
export async function resolveCollection(
store: firebase.firestore.Firestore,
collectionName: string,
collectionArgs: { [key:string]: any },
selectionSet: GraphQLSelectionSet
): Promise<FiregraphCollectionResult> {
let collectionQuery: any = store.collection(collectionName);
let collectionResult: FiregraphCollectionResult = {
name: collectionName,
docs: []
};
const collectionSnapshot = await store.collection(collectionName).get();
if (collectionArgs) {
if (collectionArgs['where']) {
const where = collectionArgs['where'];
where.forEach((filter: any) => {
collectionQuery = collectionQuery.where(
filter['key'], '==', filter['value']
);
});
}
}

const collectionSnapshot = await collectionQuery.get();
if (selectionSet && selectionSet.selections) {
for (let doc of collectionSnapshot.docs) {
const documentPath = `${collectionName}/${doc.id}`;
Expand Down
5 changes: 5 additions & 0 deletions src/firegraph/Document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export async function resolveDocument(
if (selectionSet && selectionSet.selections) {
let nestedPath: string;
const { matchesKeyFromCollection } = args;

// Document reference.
if (matchesKeyFromCollection) {
const docId = data[fieldName];
nestedPath = `${matchesKeyFromCollection}/${docId}`;
Expand All @@ -42,11 +44,14 @@ export async function resolveDocument(
selectionSet
);
docResult[fieldName] = nestedResult;

// Nested collection.
} else {
nestedPath = `${documentPath}/${fieldName}`;
const nestedResult = await resolveCollection(
store,
nestedPath,
args,
selectionSet
);
docResult[fieldName] = nestedResult.docs;
Expand Down
9 changes: 9 additions & 0 deletions src/firegraph/Where.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const parseObjectValue = (objectFields: any): any => {
return objectFields.map((field: any) => {
const { name, value } = field;
return {
key: name.value,
value: value.value
};
});
}
14 changes: 13 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import firebase from 'firebase/app';
import 'firebase/firestore';

// Top-level imports related to Firegraph.
import { parseObjectValue } from './firegraph/Where';
import { resolveCollection } from './firegraph/Collection';
import { FiregraphResult } from './types/Firegraph';

Expand Down Expand Up @@ -30,15 +31,26 @@ async function resolve(
for (let collection of targetCollections) {
const {
name: { value: collectionName },
selectionSet
selectionSet,
arguments: collectionArguments,
} = collection;

// Parse the GraphQL argument AST into something we can use.
const parsedArgs: any = {};
collectionArguments.forEach((arg: any) => {
if (arg.value.kind === 'ObjectValue') {
const { fields } = arg.value;
parsedArgs[arg.name.value] = parseObjectValue(fields);
}
});

// Now we begin to recursively fetch values defined in GraphQL
// selection sets. We pass our `firestore` instance to ensure
// all selections are done from the same database.
const result = await resolveCollection(
firestore,
collectionName,
parsedArgs,
selectionSet
);

Expand Down
42 changes: 21 additions & 21 deletions test/firegraph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ describe('firegraph', () => {
}
`);

expect(posts).toHaveLength(1);
posts.map((post: any) => {
expect(post).toHaveProperty('id');
expect(post).toHaveProperty('message');
Expand Down Expand Up @@ -70,24 +69,25 @@ describe('firegraph', () => {
});
});

// it('can filter results with WHERE clause', async () => {
// const { posts } = await firegraph.resolve(firestore, gql`
// query {
// posts(where: {
// author: "sZOgUC33ijsGSzX17ybT"
// }) {
// id
// message
// author(matchesKeyFromCollection: "users") {
// id
// }
// }
// }
// `);
// posts.forEach((post: any) => {
// expect(post).toHaveProperty('author');
// expect(post.author).toHaveProperty('id');
// expect(post.author.id).toEqual('sZOgUC33ijsGSzX17ybT');
// });
// });
it('can filter results with WHERE clause', async () => {
const authorId = 'sZOgUC33ijsGSzX17ybT';
const { posts } = await firegraph.resolve(firestore, gql`
query {
posts(where: {
author: ${authorId},
}) {
id
message
author(matchesKeyFromCollection: "users") {
id
}
}
}
`);
posts.forEach((post: any) => {
expect(post).toHaveProperty('author');
expect(post.author).toHaveProperty('id');
expect(post.author.id).toEqual('sZOgUC33ijsGSzX17ybT');
});
});
});

0 comments on commit 5271b5a

Please sign in to comment.