Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

Commit

Permalink
initial apollo-link-dedup implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
evans committed Aug 4, 2017
1 parent 5800e11 commit 4ac780b
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 0 deletions.
68 changes: 68 additions & 0 deletions packages/apollo-link-dedup/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"name": "apollo-link-dedup",
"version": "0.0.0",
"description": "Deduplicates queries that are currently on the wire",
"author": "Evans Hauser <evanshauser@gmail.com>",
"contributors": [
"James Baxley <james@meteor.com>",
"Jonas Helfer <jonas@helfer.email>",
"jon wong <j@jnwng.com>",
"Sashko Stubailo <sashko@stubailo.com>"
],
"license": "MIT",
"main": "./lib/dedupLink.js",
"typings": "./lib/dedupLink.d.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/apollographql/apollo-link.git"
},
"bugs": {
"url": "https://github.com/apollographql/apollo-link/issues"
},
"homepage": "https://github.com/apollographql/apollo-link#readme",
"scripts": {
"pretest": "npm run build",
"test": "npm run test-only --",
"posttest": "npm run lint",
"test-only": "mocha --reporter spec --full-trace dist/tests/tests.js",
"test-watch": "mocha --reporter spec --full-trace dist/tests/tests.js --watch",
"coverage": "istanbul cover ./node_modules/mocha/bin/_mocha -- --reporter dot --full-trace dist/tests/tests.js",
"postcoverage": "remap-istanbul --input coverage/coverage.json --type lcovonly --output coverage/lcov.info",
"lint": "tslint --type-check -p tsconfig.json src/*.ts && tslint --type-check -p tsconfig.json tests/*.ts",
"prebuild": "npm run clean:dist",
"build": "tsc -p .",
"postbuild": "cp -R ./dist/src/. ./lib",
"watch": "tsc -w -p .",
"clean": "npm run clean:dist && npm run clean:coverage",
"clean:dist": "rimraf dist/* && rimraf lib/*",
"clean:coverage": "rimraf coverage/*",
"prepublishOnly": "npm run clean && npm run build"
},
"dependencies": {
"apollo-fetch": "^0.6.0",
"apollo-link-core": "^0.1.1",
"graphql": "^0.10.5"
},
"devDependencies": {
"@types/chai": "^4.0.0",
"@types/chai-as-promised": "0.0.31",
"@types/mocha": "^2.2.31",
"@types/sinon": "^2.3.2",
"chai": "^4.0.2",
"chai-as-promised": "^7.0.0",
"fetch-mock": "^5.11.0",
"graphql-tag": "^2.2.2",
"istanbul": "^0.4.4",
"lodash": "^4.17.4",
"mocha": "^3.2.0",
"remap-istanbul": "^0.9.0",
"rimraf": "^2.5.4",
"sinon": "^2.3.4",
"source-map-support": "^0.4.5",
"tslint": "^5.0.0",
"typescript": "^2.2.1"
},
"optionalDependencies": {
"@types/graphql": "~0.9.0"
}
}
57 changes: 57 additions & 0 deletions packages/apollo-link-dedup/src/dedupLink.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {
ApolloLink,
Operation,
NextLink,
FetchResult,
Observable,
} from 'apollo-link-core';

import { print } from 'graphql/language/printer';

/*
* Expects context to contain the deduplicate field
*/
export class DedupLink extends ApolloLink {
private inFlightRequestPromises: { [key: string]: Observable<FetchResult> };

constructor() {
super();
this.inFlightRequestPromises = {};
}

public request(
operation: Operation,
forward: NextLink,
): Observable<FetchResult> {
// sometimes we might not want to deduplicate a request, for example when we want to force fetch it.
if (!operation.context.deduplicate) {
return forward(operation);
}

const key = this.getKey(operation);
if (!this.inFlightRequestPromises[key]) {
this.inFlightRequestPromises[key] = forward(operation);
}
return new Observable<FetchResult>(observer => {
this.inFlightRequestPromises[key].subscribe({
next: observer.next.bind(observer),
error: error => {
observer.error(error);
delete this.inFlightRequestPromises[key];
},
complete: () => {
observer.complete();
delete this.inFlightRequestPromises[key];
},
});
});
}

private getKey(operation: Operation) {
// XXX we're assuming here that variables will be serialized in the same order.
// that might not always be true
return `${print(operation.query)}|${JSON.stringify(
operation.variables,
)}|${operation.operationName}`;
}
}
14 changes: 14 additions & 0 deletions packages/apollo-link-dedup/tests/dedupLink.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { assert, expect } from 'chai';
import * as sinon from 'sinon';
import DedupLink from '../src/dedupLink';

import * as Links from 'apollo-link-core';
import { ApolloLink, execute } from 'apollo-link-core';

import { createApolloFetch } from 'apollo-fetch';

import { print } from 'graphql';
import gql from 'graphql-tag';
import * as fetchMock from 'fetch-mock';

describe('DedupLink', () => {});
1 change: 1 addition & 0 deletions packages/apollo-link-dedup/tests/tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './*';
18 changes: 18 additions & 0 deletions packages/apollo-link-dedup/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["es6", "dom"],
"module": "commonjs",
"moduleResolution": "node",
"removeComments": true,
"sourceMap": true,
"declaration": true,
"rootDir": ".",
"outDir": "dist",
"noImplicitAny": false,
"noUnusedParameters": false,
"noUnusedLocals": true,
"skipLibCheck": true
},
"include": ["src/**/*.ts", "tests/**/*.ts"]
}
107 changes: 107 additions & 0 deletions packages/apollo-link-dedup/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
{
"rules": {
"align": [false, "parameters", "arguments", "statements"],
"ban": false,
"class-name": true,
"curly": true,
"eofline": true,
"forin": true,
"indent": [true, "spaces", 2],
"interface-name": false,
"jsdoc-format": true,
"label-position": true,
"max-line-length": [true, 140],
"member-access": true,
"member-ordering": [
true,
"public-before-private",
"static-before-instance",
"variables-before-functions"
],
"no-any": false,
"no-arg": true,
"no-bitwise": true,
"no-conditional-assignment": true,
"no-consecutive-blank-lines": false,
"no-console": [true, "log", "debug", "info", "time", "timeEnd", "trace"],
"no-construct": true,
"no-debugger": true,
"no-duplicate-variable": true,
"no-empty": true,
"no-eval": true,
"no-inferrable-types": false,
"no-internal-module": true,
"no-null-keyword": false,
"no-parameter-properties": false,
"no-require-imports": false,
"no-shadowed-variable": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unused-expression": true,
"no-use-before-declare": false,
"no-var-keyword": true,
"no-var-requires": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-finally",
"check-whitespace"
],
"quotemark": [true, "single", "avoid-escape"],
"radix": true,
"semicolon": [true, "always"],
"switch-default": true,
"trailing-comma": [
true,
{
"multiline": "always",
"singleline": "never"
}
],
"triple-equals": [true, "allow-null-check"],
"typedef": [
false,
"call-signature",
"parameter",
"arrow-parameter",
"property-declaration",
"variable-declaration",
"member-variable-declaration"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
},
{
"call-signature": "space",
"index-signature": "space",
"parameter": "space",
"property-declaration": "space",
"variable-declaration": "space"
}
],
"variable-name": [
true,
"check-format",
"allow-pascal-case",
"allow-leading-underscore",
"ban-keywords"
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}
}

0 comments on commit 4ac780b

Please sign in to comment.