Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

apollo-link-dedup

Package Overview
Dependencies
Maintainers
3
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

apollo-link-dedup - npm Package Compare versions

Comparing version 1.0.0 to 1.0.2

lib/index.d.ts

10

CHANGELOG.md
### vNext
### 1.0.2
- fixed bug where next observable subscription was not deduplicated
- moved to better rollup build
### 1.0.1 [Unpublished]
<!-- This build had a nasty but that was caught by the apollo client test suite -->
- fixed bug where next observable subscription was not deduplicated
### 1.0.0
- moved from default export to named to be consistent with rest of link ecosystem

70

lib/bundle.umd.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('apollo-link')) :
typeof define === 'function' && define.amd ? define(['exports', 'apollo-link'], factory) :
(factory((global.dedupLink = {}),global.apolloLink));
(factory((global.apolloLink = global.apolloLink || {}, global.apolloLink.dedup = {}),global.apolloLink.core));
}(this, (function (exports,apolloLink) { 'use strict';

@@ -20,4 +20,5 @@

function DedupLink() {
var _this = _super.call(this) || this;
_this.inFlightRequestObservables = {};
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.inFlightRequestObservables = new Map();
_this.subscribers = new Map();
return _this;

@@ -31,23 +32,46 @@ }

var key = operation.toKey();
if (!this.inFlightRequestObservables[key]) {
this.inFlightRequestObservables[key] = forward(operation);
var cleanup = function (key) {
_this.inFlightRequestObservables.delete(key);
var prev = _this.subscribers.get(key);
return prev;
};
if (!this.inFlightRequestObservables.get(key)) {
var singleObserver_1 = forward(operation);
var subscription_1;
var sharedObserver = new apolloLink.Observable(function (observer) {
var prev = _this.subscribers.get(key);
if (!prev)
prev = { next: [], error: [], complete: [] };
_this.subscribers.set(key, {
next: prev.next.concat([observer.next.bind(observer)]),
error: prev.error.concat([observer.error.bind(observer)]),
complete: prev.complete.concat([observer.complete.bind(observer)]),
});
if (!subscription_1) {
subscription_1 = singleObserver_1.subscribe({
next: function (result) {
var prev = cleanup(key);
_this.subscribers.delete(key);
if (prev) {
prev.next.forEach(function (next) { return next(result); });
prev.complete.forEach(function (complete) { return complete(); });
}
},
error: function (error) {
var prev = cleanup(key);
_this.subscribers.delete(key);
if (prev)
prev.error.forEach(function (err) { return err(error); });
},
});
}
return function () {
if (subscription_1)
subscription_1.unsubscribe();
_this.inFlightRequestObservables.delete(key);
};
});
this.inFlightRequestObservables.set(key, sharedObserver);
}
return new apolloLink.Observable(function (observer) {
var subscription = _this.inFlightRequestObservables[key].subscribe({
next: function (result) {
delete _this.inFlightRequestObservables[key];
observer.next(result);
},
error: function (error) {
delete _this.inFlightRequestObservables[key];
observer.error(error);
},
complete: observer.complete.bind(observer),
});
return function () {
if (subscription)
subscription.unsubscribe();
delete _this.inFlightRequestObservables[key];
};
});
return this.inFlightRequestObservables.get(key);
};

@@ -54,0 +78,0 @@ return DedupLink;

@@ -5,4 +5,4 @@ /// <reference types="zen-observable" />

private inFlightRequestObservables;
constructor();
private subscribers;
request(operation: Operation, forward: NextLink): Observable<FetchResult>;
}

@@ -15,4 +15,5 @@ var __extends = (this && this.__extends) || (function () {

function DedupLink() {
var _this = _super.call(this) || this;
_this.inFlightRequestObservables = {};
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.inFlightRequestObservables = new Map();
_this.subscribers = new Map();
return _this;

@@ -26,23 +27,46 @@ }

var key = operation.toKey();
if (!this.inFlightRequestObservables[key]) {
this.inFlightRequestObservables[key] = forward(operation);
var cleanup = function (key) {
_this.inFlightRequestObservables.delete(key);
var prev = _this.subscribers.get(key);
return prev;
};
if (!this.inFlightRequestObservables.get(key)) {
var singleObserver_1 = forward(operation);
var subscription_1;
var sharedObserver = new Observable(function (observer) {
var prev = _this.subscribers.get(key);
if (!prev)
prev = { next: [], error: [], complete: [] };
_this.subscribers.set(key, {
next: prev.next.concat([observer.next.bind(observer)]),
error: prev.error.concat([observer.error.bind(observer)]),
complete: prev.complete.concat([observer.complete.bind(observer)]),
});
if (!subscription_1) {
subscription_1 = singleObserver_1.subscribe({
next: function (result) {
var prev = cleanup(key);
_this.subscribers.delete(key);
if (prev) {
prev.next.forEach(function (next) { return next(result); });
prev.complete.forEach(function (complete) { return complete(); });
}
},
error: function (error) {
var prev = cleanup(key);
_this.subscribers.delete(key);
if (prev)
prev.error.forEach(function (err) { return err(error); });
},
});
}
return function () {
if (subscription_1)
subscription_1.unsubscribe();
_this.inFlightRequestObservables.delete(key);
};
});
this.inFlightRequestObservables.set(key, sharedObserver);
}
return new Observable(function (observer) {
var subscription = _this.inFlightRequestObservables[key].subscribe({
next: function (result) {
delete _this.inFlightRequestObservables[key];
observer.next(result);
},
error: function (error) {
delete _this.inFlightRequestObservables[key];
observer.error(error);
},
complete: observer.complete.bind(observer),
});
return function () {
if (subscription)
subscription.unsubscribe();
delete _this.inFlightRequestObservables[key];
};
});
return this.inFlightRequestObservables.get(key);
};

@@ -49,0 +73,0 @@ return DedupLink;

{
"name": "apollo-link-dedup",
"version": "1.0.0",
"version": "1.0.2",
"description": "Deduplicates queries that are currently on the wire",

@@ -14,5 +14,5 @@ "author": "Evans Hauser <evanshauser@gmail.com>",

"main": "./lib/bundle.umd.js",
"module": "./lib/dedupLink.js",
"jsnext:main": "./lib/dedupLink.js",
"typings": "./lib/dedupLink.d.ts",
"module": "./lib/index.js",
"jsnext:main": "./lib/index.js",
"typings": "./lib/index.d.ts",
"repository": {

@@ -44,8 +44,8 @@ "type": "git",

"peerDependencies": {
"apollo-link": "^1.0.0"
"apollo-link": "^1.0.3"
},
"devDependencies": {
"@types/graphql": "0.11.5",
"@types/jest": "21.1.4",
"apollo-link": "^1.0.0",
"@types/graphql": "0.11.6",
"@types/jest": "21.1.6",
"apollo-link": "^1.0.3",
"browserify": "14.5.0",

@@ -56,7 +56,7 @@ "graphql": "0.11.7",

"rimraf": "2.6.1",
"rollup": "0.45.2",
"ts-jest": "21.1.3",
"rollup": "0.51.5",
"ts-jest": "21.2.2",
"tslint": "5.8.0",
"typescript": "2.5.1",
"uglify-js": "3.1.5"
"typescript": "2.6.1",
"uglify-js": "3.1.9"
},

@@ -63,0 +63,0 @@ "jest": {

@@ -1,17 +0,3 @@

export default {
entry: 'lib/dedupLink.js',
dest: 'lib/bundle.umd.js',
format: 'umd',
sourceMap: true,
moduleName: 'dedupLink',
exports: 'named',
onwarn,
};
import build from '../../rollup.config';
function onwarn(message) {
const suppressed = ['UNRESOLVED_IMPORT', 'THIS_IS_UNDEFINED'];
if (!suppressed.find(code => message.code === code)) {
return console.warn(message.message);
}
}
export default build('dedup');

@@ -68,3 +68,3 @@ import {

let error;
const data = { data: { data: 'some data' } };
const data = { data: 'some data' };

@@ -100,16 +100,20 @@ const request: GraphQLRequest = {

execute(deduper, request).subscribe({
error: actualError => {
expect(actualError).toEqual(error);
try {
execute(deduper, request).subscribe({
error: actualError => {
expect(actualError).toEqual(error);
//second query
execute(deduper, request).subscribe({
next: result => {
expect(result).toEqual(data);
expect(called).toBe(2);
done();
},
});
},
});
//second query
execute(deduper, request).subscribe({
next: result => {
expect(result).toEqual(data);
expect(called).toBe(2);
done();
},
});
},
});
} catch (e) {
done.fail(e);
}
});

@@ -142,4 +146,4 @@

new ApolloLink(() => {
called += 1;
return new Observable(observer => {
called += 1;
setTimeout(observer.complete.bind(observer));

@@ -154,3 +158,46 @@ });

});
it(`works for nested queries`, done => {
const document: DocumentNode = gql`
query test1($x: String) {
test(x: $x)
}
`;
const variables1 = { x: 'Hello World' };
const variables2 = { x: 'Hello World' };
const request1: GraphQLRequest = {
query: document,
variables: variables1,
operationName: getOperationName(document),
};
const request2: GraphQLRequest = {
query: document,
variables: variables2,
operationName: getOperationName(document),
};
let called = 0;
const deduper = ApolloLink.from([
new DedupLink(),
new ApolloLink(() => {
return new Observable(observer => {
called += 1;
observer.next({ data: { test: 1 } });
});
}),
]);
execute(deduper, request1).subscribe({
complete: () => {
execute(deduper, request2).subscribe({
complete: () => {
expect(called).toBe(2);
done();
},
});
},
});
});
it(`can bypass deduplication if desired`, () => {

@@ -157,0 +204,0 @@ const document: DocumentNode = gql`

@@ -13,11 +13,8 @@ import {

export class DedupLink extends ApolloLink {
private inFlightRequestObservables: {
[key: string]: Observable<FetchResult>;
};
private inFlightRequestObservables: Map<
string,
Observable<FetchResult>
> = new Map();
private subscribers: Map<string, any> = new Map();
constructor() {
super();
this.inFlightRequestObservables = {};
}
public request(

@@ -33,24 +30,57 @@ operation: Operation,

const key = operation.toKey();
if (!this.inFlightRequestObservables[key]) {
this.inFlightRequestObservables[key] = forward(operation);
}
return new Observable<FetchResult>(observer => {
const subscription = this.inFlightRequestObservables[key].subscribe({
next: result => {
delete this.inFlightRequestObservables[key];
observer.next(result);
},
error: error => {
delete this.inFlightRequestObservables[key];
observer.error(error);
},
complete: observer.complete.bind(observer),
const cleanup = key => {
this.inFlightRequestObservables.delete(key);
const prev = this.subscribers.get(key);
return prev;
};
if (!this.inFlightRequestObservables.get(key)) {
// this is a new request, i.e. we haven't deduplicated it yet
// call the next link
const singleObserver = forward(operation);
let subscription;
const sharedObserver = new Observable(observer => {
// this will still be called by each subscriber regardless of
// deduplication status
let prev = this.subscribers.get(key);
if (!prev) prev = { next: [], error: [], complete: [] };
this.subscribers.set(key, {
next: prev.next.concat([observer.next.bind(observer)]),
error: prev.error.concat([observer.error.bind(observer)]),
complete: prev.complete.concat([observer.complete.bind(observer)]),
});
if (!subscription) {
subscription = singleObserver.subscribe({
next: result => {
const prev = cleanup(key);
this.subscribers.delete(key);
if (prev) {
prev.next.forEach(next => next(result));
prev.complete.forEach(complete => complete());
}
},
error: error => {
const prev = cleanup(key);
this.subscribers.delete(key);
if (prev) prev.error.forEach(err => err(error));
},
});
}
return () => {
if (subscription) subscription.unsubscribe();
this.inFlightRequestObservables.delete(key);
};
});
return () => {
if (subscription) subscription.unsubscribe();
delete this.inFlightRequestObservables[key];
};
});
this.inFlightRequestObservables.set(key, sharedObserver);
}
// return shared Observable
return this.inFlightRequestObservables.get(key);
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc