Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"@babel/preset-env",
{
"targets": {
"node": "8"
"node": "10"
}
}
],
Expand Down
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
examples/swapi/swapi-loaders.js linguist-generated=true
18 changes: 0 additions & 18 deletions __tests__/fixtures/config.yaml

This file was deleted.

191 changes: 112 additions & 79 deletions __tests__/implementation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import _ from 'lodash';
import codegen from '../src/codegen';
import { getConfig } from '../src/config';

const CONFIG_PATH = path.join(__dirname, 'fixtures', 'config.yaml');
const BABEL_CONFIG = {
presets: [
'@babel/preset-flow',
Expand Down Expand Up @@ -338,19 +337,13 @@ test('batch endpoint (multiple requests, error handling)', async () => {
await createDataLoaders(config, async getLoaders => {
const loaders = getLoaders(resources);

// .loadMany will tank the whole batch load if there's any errors
// @see https://github.com/graphql/dataloader/issues/41
const results = await Promise.all(
[
{ foo_id: 1, include_extra_info: false },
{ foo_id: 2, include_extra_info: true },
{ foo_id: 3, include_extra_info: false },
{ foo_id: 4, include_extra_info: true },
{ foo_id: 5, include_extra_info: true },
].map(key => {
return loaders.foo.load(key).catch(err => err);
}),
);
const results = await loaders.foo.loadMany([
{ foo_id: 1, include_extra_info: false },
{ foo_id: 2, include_extra_info: true },
{ foo_id: 3, include_extra_info: false },
{ foo_id: 4, include_extra_info: true },
{ foo_id: 5, include_extra_info: true },
]);

expect(results).toMatchObject([
expect.toBeError(/yikes/),
Expand Down Expand Up @@ -411,19 +404,13 @@ test('batch endpoint (multiple requests, error handling, nestedPath)', async ()
await createDataLoaders(config, async getLoaders => {
const loaders = getLoaders(resources);

// .loadMany will tank the whole batch load if there's any errors
// @see https://github.com/graphql/dataloader/issues/41
const results = await Promise.all(
[
{ foo_id: 1, include_extra_info: false },
{ foo_id: 2, include_extra_info: true },
{ foo_id: 3, include_extra_info: false },
{ foo_id: 4, include_extra_info: true },
{ foo_id: 5, include_extra_info: true },
].map(key => {
return loaders.foo.load(key).catch(err => err);
}),
);
const results = await loaders.foo.loadMany([
{ foo_id: 1, include_extra_info: false },
{ foo_id: 2, include_extra_info: true },
{ foo_id: 3, include_extra_info: false },
{ foo_id: 4, include_extra_info: true },
{ foo_id: 5, include_extra_info: true },
]);

expect(results).toMatchObject([
expect.toBeError(/yikes/),
Expand Down Expand Up @@ -468,19 +455,13 @@ test('batch endpoint (multiple requests, error handling - non array response)',
await createDataLoaders(config, async getLoaders => {
const loaders = getLoaders(resources);

// .loadMany will tank the whole batch load if there's any errors
// @see https://github.com/graphql/dataloader/issues/41
const results = await Promise.all(
[
{ foo_id: 1, include_extra_info: false },
{ foo_id: 2, include_extra_info: true },
{ foo_id: 3, include_extra_info: false },
{ foo_id: 4, include_extra_info: true },
{ foo_id: 5, include_extra_info: true },
].map(key => {
return loaders.foo.load(key).catch(err => err);
}),
);
const results = await loaders.foo.loadMany([
{ foo_id: 1, include_extra_info: false },
{ foo_id: 2, include_extra_info: true },
{ foo_id: 3, include_extra_info: false },
{ foo_id: 4, include_extra_info: true },
{ foo_id: 5, include_extra_info: true },
]);

expect(results).toMatchObject([
expect.toBeError('yikes'),
Expand Down Expand Up @@ -539,19 +520,13 @@ test('batch endpoint (multiple requests, error handling, with reordering)', asyn
await createDataLoaders(config, async getLoaders => {
const loaders = getLoaders(resources);

// .loadMany will tank the whole batch load if there's any errors
// @see https://github.com/graphql/dataloader/issues/41
const results = await Promise.all(
[
{ foo_id: 1, include_extra_info: false },
{ foo_id: 2, include_extra_info: true },
{ foo_id: 3, include_extra_info: false },
{ foo_id: 4, include_extra_info: true },
{ foo_id: 5, include_extra_info: true },
].map(key => {
return loaders.foo.load(key).catch(err => err);
}),
);
const results = await loaders.foo.loadMany([
{ foo_id: 1, include_extra_info: false },
{ foo_id: 2, include_extra_info: true },
{ foo_id: 3, include_extra_info: false },
{ foo_id: 4, include_extra_info: true },
{ foo_id: 5, include_extra_info: true },
]);

expect(results).toMatchObject([
expect.toBeError(/yikes/),
Expand Down Expand Up @@ -602,7 +577,6 @@ test('batch endpoint without reorderResultsByKey throws error for response with
{
foo_id: 4,
foo_value: 'greetings',
extra_stuff: 'lorem ipsum',
},
]);
}
Expand All @@ -612,24 +586,18 @@ test('batch endpoint without reorderResultsByKey throws error for response with
await createDataLoaders(config, async getLoaders => {
const loaders = getLoaders(resources);

// .loadMany will tank the whole batch load if there's any errors
// @see https://github.com/graphql/dataloader/issues/41
const results = await Promise.all(
[
{ foo_id: 1, bar: true },
{ foo_id: 2, bar: true },
{ foo_id: 3, bar: true },
{ foo_id: 4, bar: false },
].map(key => {
return loaders.foo.load(key).catch(err => err);
}),
);
const results = await loaders.foo.loadMany([
{ foo_id: 1, include_extra_info: true },
{ foo_id: 2, include_extra_info: true },
{ foo_id: 3, include_extra_info: true },
{ foo_id: 4, include_extra_info: false },
]);

expect(results).toMatchObject([
expect.toBeError('[dataloader-codegen :: foo] Resource returned 2 items, but we requested 3 items'),
expect.toBeError('[dataloader-codegen :: foo] Resource returned 2 items, but we requested 3 items'),
expect.toBeError('[dataloader-codegen :: foo] Resource returned 2 items, but we requested 3 items'),
{ foo_id: 4, foo_value: 'greetings', extra_stuff: 'lorem ipsum' },
{ foo_id: 4, foo_value: 'greetings' },
]);
});
});
Expand Down Expand Up @@ -678,18 +646,12 @@ test('batch endpoint with reorderResultsByKey handles response with non existant
await createDataLoaders(config, async getLoaders => {
const loaders = getLoaders(resources);

// .loadMany will tank the whole batch load if there's any errors
// @see https://github.com/graphql/dataloader/issues/41
const results = await Promise.all(
[
{ foo_id: 1, bar: true },
{ foo_id: 2, bar: true },
{ foo_id: 3, bar: true },
{ foo_id: 4, bar: false },
].map(key => {
return loaders.foo.load(key).catch(err => err);
}),
);
const results = await loaders.foo.loadMany([
{ foo_id: 1, bar: true },
{ foo_id: 2, bar: true },
{ foo_id: 3, bar: true },
{ foo_id: 4, bar: false },
]);

expect(results).toMatchObject([
{ foo_id: 1, foo_value: 'greetings', extra_stuff: 'lorem ipsum' },
Expand All @@ -699,3 +661,74 @@ test('batch endpoint with reorderResultsByKey handles response with non existant
]);
});
});

test('batch endpoint with isResponseDictionary handles a response that returns a dictionary', async () => {
const config = {
resources: {
foo: {
isBatchResource: true,
docsLink: 'example.com/docs/foos',
batchKey: 'foo_ids',
newKey: 'foo_id',
isResponseDictionary: true,
},
},
};

const resources = {
foo: ({ foo_ids }) => {
expect(foo_ids).toEqual([1, 2, 3]);
return Promise.resolve({
2: { foo_id: 2, foo_value: 'world' },
'1': { foo_id: 1, foo_value: 'hello' },
3: { foo_id: 3, foo_value: '!' },
});
},
};

await createDataLoaders(config, async getLoaders => {
const loaders = getLoaders(resources);

const results = await loaders.foo.loadMany([{ foo_id: 1 }, { foo_id: 2 }, { foo_id: 3 }]);
expect(results).toEqual([
{ foo_id: 1, foo_value: 'hello' },
{ foo_id: 2, foo_value: 'world' },
{ foo_id: 3, foo_value: '!' },
]);
});
});

test('batch endpoint with isResponseDictionary handles a response that returns a dictionary, with a missing item', async () => {
const config = {
resources: {
foo: {
isBatchResource: true,
docsLink: 'example.com/docs/foos',
batchKey: 'foo_ids',
newKey: 'foo_id',
isResponseDictionary: true,
},
},
};

const resources = {
foo: ({ foo_ids }) => {
expect(foo_ids).toEqual([1, 2, 3]);
return Promise.resolve({
'1': { foo_id: 1, foo_value: 'hello' },
3: { foo_id: 3, foo_value: '!' },
});
},
};

await createDataLoaders(config, async getLoaders => {
const loaders = getLoaders(resources);

const results = await loaders.foo.loadMany([{ foo_id: 1 }, { foo_id: 2 }, { foo_id: 3 }]);
expect(results).toEqual([
{ foo_id: 1, foo_value: 'hello' },
expect.toBeError('[dataloader-codegen :: foo] Could not find key = "2" in the response dict'),
{ foo_id: 3, foo_value: '!' },
]);
});
});
1 change: 1 addition & 0 deletions examples/swapi/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
6 changes: 5 additions & 1 deletion examples/swapi/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
node_modules: package.json
yarn

.PHONY: swapi-loaders.js
swapi-loaders.js:
node ../../lib/index.js --config swapi.dataloader-config.yaml --output swapi-loaders.js

flow-typed: node_modules
node_modules/.bin/flow-typed install
yarn flow-typed install

build: node_modules
yarn babel *.js -d build
32 changes: 32 additions & 0 deletions examples/swapi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# dataloader-codegen Example: Star Wars API (SWAPI)

Shows an example of a GraphQL Server using dataloader-codegen. Prints data from https://swapi.co/.

## Try it out locally!

Clone dataloader-codegen and build locally:

```sh
$ git clone git@github.com:Yelp/dataloader-codegen.git
$ cd dataloader-codegen
$ make build
$ yarn link
```

Build the example:

```sh
$ cd examples/swapi
$ yarn
$ yarn link dataloader-codegen
$ make swapi-loaders.js
$ make build
# Prints out a GraphQL query result:
$ node build/swapi-server.js
```

## File Layout:

- `swapi-loaders.js`: An autogenerated file by dataloader-codegen. Contains the codegen'd dataloaders. (Checked in to git so folks can easily see an example of the generated code).
- `swapi.js`: A set of functions to fetch data from https://swapi.co/. This is analogous to a library generated by openapi-generator/swagger-codegen.
- `swapi-server.js`: The dummy GraphQL server! This imports the dataloaders from swapi-loaders.js. At present, it just prints the result of a query to stdout.
1 change: 1 addition & 0 deletions examples/swapi/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/node": "^7.7.0",
"@babel/preset-flow": "^7.0.0",
"flow-bin": "0.111.3",
Expand Down
Loading