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

angular-apollo

Package Overview
Dependencies
Maintainers
4
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

angular-apollo - npm Package Compare versions

Comparing version 0.1.1 to 0.2.0

dist/auth-tokens-validator/auth-tokens-validator.d.ts

9

dist/accounts.d.ts

@@ -11,8 +11,7 @@ import { ApiService } from './api/api';

constructor(apiService: ApiService);
private getAuthTokenHeaders(token);
login(details: LoginDetails): Observable<Account>;
spotlight(token: string): Observable<Account>;
lists(token: string): Observable<Account>;
listById(id: number, token: string): Observable<any>;
radios(token: string): Observable<Account>;
spotlight(): Observable<{}>;
lists(): Observable<{}>;
listById(id: number): Observable<{}>;
radios(): Observable<{}>;
}

@@ -19,9 +19,2 @@ "use strict";

}
AccountService.prototype.getAuthTokenHeaders = function (token) {
return {
headers: new http_1.Headers({
'Authorization': "bearer " + token,
})
};
};
AccountService.prototype.login = function (details) {

@@ -33,13 +26,13 @@ var options = {

};
AccountService.prototype.spotlight = function (token) {
return this.apiService.fetch("me/spotlight", this.getAuthTokenHeaders(token));
AccountService.prototype.spotlight = function () {
return this.apiService.authorisedFetch("me/spotlight");
};
AccountService.prototype.lists = function (token) {
return this.apiService.fetch("me/lists", this.getAuthTokenHeaders(token));
AccountService.prototype.lists = function () {
return this.apiService.authorisedFetch("me/lists");
};
AccountService.prototype.listById = function (id, token) {
return this.apiService.fetch("me/lists/" + id, this.getAuthTokenHeaders(token));
AccountService.prototype.listById = function (id) {
return this.apiService.authorisedFetch("me/lists/" + id);
};
AccountService.prototype.radios = function (token) {
return this.apiService.fetch("me/radios", this.getAuthTokenHeaders(token));
AccountService.prototype.radios = function () {
return this.apiService.authorisedFetch("me/radios");
};

@@ -46,0 +39,0 @@ AccountService = __decorate([

@@ -1,13 +0,24 @@

import { Http, Response, RequestOptionsArgs } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { Http, RequestOptionsArgs } from '@angular/http';
import { Observable, Subject } from 'rxjs/Rx';
import { Config } from '../config';
import 'rxjs/Rx';
import { AuthTokensValidator } from '../auth-tokens-validator/auth-tokens-validator';
import 'rxjs/add/operator/map';
export interface ApiTokenStore {
events: Subject<any>;
get(): {
authToken: string;
refreshToken: string;
};
}
export declare class ApiService {
private http;
private config;
constructor(http: Http, config: Config);
getPath(path: string): string;
private apiTokenStore;
private authTokensValidator;
constructor(http: Http, config: Config, apiTokenStore: ApiTokenStore, authTokensValidator: AuthTokensValidator);
fetch(path: string, options?: RequestOptionsArgs): Observable<any>;
authorisedFetch(path: string, options?: RequestOptionsArgs): Observable<{}>;
post(path: string, data: any, options?: RequestOptionsArgs): Observable<any>;
handleResponse(res: Response): any;
private getPath(path);
private handleResponse(res);
}

@@ -14,0 +25,0 @@ export declare class ApiError extends Error {

@@ -18,21 +18,53 @@ "use strict";

var http_1 = require('@angular/http');
var Rx_1 = require('rxjs/Rx');
var config_1 = require('../config');
require('rxjs/Rx');
require('rxjs/add/operator/map');
var ApiAuthorisationError = (function (_super) {
__extends(ApiAuthorisationError, _super);
function ApiAuthorisationError(options) {
_super.call(this, 'API Authorisation error');
Object.assign(this, options);
}
return ApiAuthorisationError;
}(Error));
var ApiService = (function () {
function ApiService(http, config) {
function ApiService(http, config, apiTokenStore, authTokensValidator) {
this.http = http;
this.config = config;
this.apiTokenStore = apiTokenStore;
this.authTokensValidator = authTokensValidator;
}
;
ApiService.prototype.getPath = function (path) {
return this.config.baseUrl + "/" + path;
};
ApiService.prototype.fetch = function (path, options) {
if (options === void 0) { options = {}; }
var url = this.getPath(path);
return this.http.get(url, options)
.map(this.handleResponse);
return this.http.get(url, options).map(this.handleResponse);
};
ApiService.prototype.authorisedFetch = function (path, options) {
var _this = this;
if (options === void 0) { options = {}; }
var tokens = this.apiTokenStore.get();
console.log(tokens);
if (!tokens) {
this.apiTokenStore.events.error(new ApiAuthorisationError({
missingTokens: true
}));
return Rx_1.Observable.empty();
}
return this.authTokensValidator
.validateTokens(tokens.authToken, tokens.refreshToken)
.flatMap(function (validatedTokens) {
options.headers = options.headers || new http_1.Headers();
options.headers.set('Authorization', "bearer " + validatedTokens.authToken);
if (validatedTokens.hasBeenRefreshed) {
_this.apiTokenStore.events.next(validatedTokens);
}
return _this.fetch(path, options);
})
.catch(function (err) {
_this.apiTokenStore.events.error(new ApiAuthorisationError({
invalidAuthToken: true
}));
return Rx_1.Observable.empty();
});
};
ApiService.prototype.post = function (path, data, options) {
if (options === void 0) { options = {}; }
var url = this.getPath(path);

@@ -42,2 +74,5 @@ return this.http.post(url, JSON.stringify(data), options)

};
ApiService.prototype.getPath = function (path) {
return this.config.baseUrl + "/" + path;
};
ApiService.prototype.handleResponse = function (res) {

@@ -51,3 +86,3 @@ if (res.status >= 400) {

core_1.Injectable(),
__metadata('design:paramtypes', [http_1.Http, config_1.Config])
__metadata('design:paramtypes', [http_1.Http, config_1.Config, Object, Object])
], ApiService);

@@ -54,0 +89,0 @@ return ApiService;

@@ -10,5 +10,6 @@ "use strict";

var testing_2 = require('@angular/core/testing');
require('rxjs/Rx');
var Rx_1 = require('rxjs/Rx');
var api_1 = require('./api');
var config_1 = require('../config');
var Rx_2 = require('rxjs/Rx');
var TestConfig = (function (_super) {

@@ -23,4 +24,37 @@ __extends(TestConfig, _super);

testing_2.describe('ApiService', function () {
var apiTokens, apiTokenStore, fakeAuthTokensValidator, fakeAuthTokensValidatorResult;
var FakeApiTokenStore = (function () {
function FakeApiTokenStore() {
this.events = new Rx_1.Subject();
}
FakeApiTokenStore.prototype.get = function () {
return apiTokens;
};
return FakeApiTokenStore;
}());
beforeEach(function () {
fakeAuthTokensValidatorResult = Rx_2.Observable.from([{
authToken: 'validatedAuthToken',
refreshToken: 'validatedRefreshToken',
hasBeenRefreshed: false
}]);
apiTokenStore = new FakeApiTokenStore();
fakeAuthTokensValidator = {
validateTokens: function (authToken, refreshToken) {
return fakeAuthTokensValidatorResult;
}
};
apiTokens = {
authToken: 'authToken',
refreshToken: 'refreshToken'
};
});
testing_2.beforeEachProviders(function () { return [
api_1.ApiService,
{
provide: api_1.ApiService,
deps: [http_1.Http, config_1.Config],
useFactory: function (http, config) {
return new api_1.ApiService(http, config, apiTokenStore, fakeAuthTokensValidator);
}
},
testing_1.MockBackend,

@@ -36,76 +70,198 @@ http_1.BaseRequestOptions,

useClass: TestConfig
}]; });
}
]; });
function makeResponse(response) {
return new http_1.Response(new http_1.ResponseOptions(response));
}
testing_2.it('Uses the baseUrl from the configuration', testing_2.async(testing_2.inject([api_1.ApiService, testing_1.MockBackend], function (api, mockBackEnd) {
var response = {
body: JSON.stringify({ id: 666 }),
status: 200
};
mockBackEnd.connections.subscribe(function (connection) {
testing_2.expect(connection.request.url)
.toEqual('http://www.example.com/lists/666');
connection.mockRespond(makeResponse(response));
});
return api.fetch('lists/666')
.subscribe(function (data) { console.log(); });
})));
testing_2.it('returns the json when response is 200', testing_2.async(testing_2.inject([api_1.ApiService, testing_1.MockBackend], function (api, mockBackEnd) {
var response = {
body: JSON.stringify({ id: 666 }),
status: 200
};
mockBackEnd.connections.subscribe(function (connection) {
connection.mockRespond(makeResponse(response));
});
return api.fetch('lists/666').subscribe(function (data) {
testing_2.expect(data).toEqual({ id: 666 });
});
})));
testing_2.it('throws an error when the body is not valid json', testing_2.async(testing_2.inject([api_1.ApiService, testing_1.MockBackend], function (api, mockBackEnd) {
mockBackEnd.connections
.subscribe(function (connection) {
var response = {
body: '{!"',
status: 200
};
function testApiCall(options) {
return testing_2.async(testing_2.inject([api_1.ApiService, testing_1.MockBackend], function (api, mockBackEnd) {
var response = { body: options.stubbedBody, status: options.stubbedStatusCode || 200 };
mockBackEnd.connections.subscribe(function (connection) {
testing_2.expect(connection.request.url)
.toEqual("http://www.example.com/" + options.expectedPath);
if (options.expectedBody) {
testing_2.expect(JSON.parse(connection.request.getBody()))
.toEqual(options.expectedBody);
}
if (options.expectedHeaders) {
Object.keys(options.expectedHeaders).forEach(function (header) {
testing_2.expect(connection.request.headers.getAll(header))
.toEqual(options.expectedHeaders[header]);
});
}
if (options.stubbedError) {
return connection.mockError(options.stubbedError);
}
connection.mockRespond(makeResponse(response));
});
return options.test(api);
}));
}
testing_2.it('returns the json when response is 200 for post requests', testApiCall({
expectedPath: 'lists/666',
expectedHeaders: { someHeader: ['blah'] },
expectedBody: { bodyData: 'fleh' },
stubbedBody: { id: 123 },
test: function (api) {
var options = {
headers: new http_1.Headers({ someHeader: 'blah' })
};
api.post('lists/666', { bodyData: 'fleh' }, options)
.subscribe(function (data) { return testing_2.expect(data).toEqual({ id: 123 }); });
}
}));
testing_2.it('returns the json when response is 200 for fetch requests', testApiCall({
expectedPath: 'lists/666',
expectedHeaders: { someHeader: ['woo'] },
stubbedBody: { id: 123 },
test: function (api) {
var options = {
headers: new http_1.Headers({ someHeader: 'woo' })
};
api.fetch('lists/666', options)
.subscribe(function (data) { return testing_2.expect(data).toEqual({ id: 123 }); });
}
}));
testing_2.it('returns the json when response is 200 for authorised fetch requests', testApiCall({
expectedPath: 'lists/666',
expectedHeaders: { someHeader: ['wee'] },
stubbedBody: { id: 123 },
test: function (api) {
var options = {
headers: new http_1.Headers({ someHeader: 'wee' })
};
api.authorisedFetch('lists/666', options)
.subscribe(function (data) { return testing_2.expect(data).toEqual({ id: 123 }); });
}
}));
testing_2.it('appends the authorization header to authorised fetch requests', testApiCall({
expectedPath: 'test',
expectedHeaders: { Authorization: ['bearer validatedAuthToken'] },
test: function (api) { return api.authorisedFetch('test').subscribe(); }
}));
testing_2.describe('with an empty api token store', function () {
beforeEach(function () { return apiTokens = undefined; });
testing_2.it('raises unauthorised event when an authorised fetch request is made', testApiCall({
expectedPath: 'test',
test: function (api) {
apiTokenStore.events.subscribe(function () { return fail(new Error('Expected error event')); }, function (err) { return testing_2.expect(err.missingTokens).toEqual(true); });
api.authorisedFetch('test').subscribe();
}
}));
});
testing_2.describe('when api token validation fails', function () {
beforeEach(function () {
fakeAuthTokensValidatorResult = Rx_2.Observable.throw(new Error('plop'));
});
return api.fetch('lists/666').subscribe(function (data) {
testing_2.expect(data).toEqual({ id: 666 });
}, function (err) {
testing_2.expect(err).toEqual(jasmine.any(Error));
testing_2.it('raises unauthorised event when an authorised fetch request is made', testApiCall({
expectedPath: 'test',
test: function (api) {
apiTokenStore.events.subscribe(function () { return fail(new Error('Expected error event')); }, function (err) { return testing_2.expect(err.invalidAuthToken).toEqual(true); });
api.authorisedFetch('test').subscribe();
}
}));
});
testing_2.describe('when the api token has been refreshed', function () {
beforeEach(function () {
fakeAuthTokensValidatorResult = Rx_2.Observable.from([{
authToken: 'new-token',
refreshToken: 'new-refresh-token',
hasBeenRefreshed: true
}]);
});
})));
[404, 500].forEach(function (statusCode) {
testing_2.it("throws an error when response is " + statusCode, testing_2.async(testing_2.inject([api_1.ApiService, testing_1.MockBackend], function (api, mockBackEnd) {
mockBackEnd.connections.subscribe(function (connection) {
connection.mockRespond(new http_1.Response(new http_1.ResponseOptions({
status: statusCode
})));
});
return api.fetch('lists/666')
.subscribe(function (res) {
throw new Error('This test should not get a successful response');
}, function (err) {
testing_2.expect(err).toEqual(jasmine.any(api_1.ApiError));
testing_2.it('emits a refresh event', testApiCall({
expectedPath: 'test',
test: function (api) {
apiTokenStore.events.subscribe(function (evt) { return testing_2.expect(evt).toEqual({
hasBeenRefreshed: true,
authToken: 'new-token',
refreshToken: 'new-refresh-token'
}); }, function (err) { return fail(err); });
api.authorisedFetch('test').subscribe();
}
}));
});
testing_2.describe('when the api token has not been refreshed', function () {
beforeEach(function () {
fakeAuthTokensValidatorResult = Rx_2.Observable.from([{
authToken: 'old-token',
refreshToken: 'old-refresh-token',
hasBeenRefreshed: false
}]);
});
testing_2.it('does not emit a refresh event', testApiCall({
expectedPath: 'test',
test: function (api) {
apiTokenStore.events.subscribe(function (evt) { return fail(new Error('should not emit an event')); }, function (err) { return fail(err); });
api.authorisedFetch('test').subscribe();
}
}));
});
testing_2.it('throws an error when the post response body is not valid json', testApiCall({
expectedPath: 'blah',
stubbedBody: 'not json',
test: function (api) { return api.post('blah', 'request body')
.subscribe(function (data) { }, function (err) { return testing_2.expect(err).toEqual(jasmine.any(Error)); }); }
}));
testing_2.it('throws an error when the fetch response body is not valid json', testApiCall({
expectedPath: 'blah',
stubbedBody: 'not json',
test: function (api) { return api.fetch('blah')
.subscribe(function (data) { }, function (err) { return testing_2.expect(err).toEqual(jasmine.any(Error)); }); }
}));
testing_2.it('throws an error when the authorised fetch response body is not valid json', testApiCall({
expectedPath: 'blah',
stubbedBody: 'not json',
test: function (api) { return api.authorisedFetch('blah')
.subscribe(function () { return fail(new Error('ApiService should error')); }, function (err) { return testing_2.expect(err).toEqual(jasmine.any(Error)); }); }
}));
var errorStatusCodes = [404, 500];
errorStatusCodes.forEach(function (statusCode) {
testing_2.it("throws an error when post response is " + statusCode, testApiCall({
expectedPath: 'blah',
stubbedStatusCode: statusCode,
test: function (api) { return api.post('blah', {})
.subscribe(function () { return fail(new Error('ApiService should error')); }, function (err) {
testing_2.expect(err).toEqual(jasmine.any(Error));
testing_2.expect(err.response.status).toEqual(statusCode);
});
})));
}); }
}));
testing_2.it("throws an error when fetch response is " + statusCode, testApiCall({
expectedPath: 'blah',
stubbedStatusCode: statusCode,
test: function (api) { return api.fetch('blah')
.subscribe(function () { return fail(new Error('ApiService should error')); }, function (err) {
testing_2.expect(err).toEqual(jasmine.any(Error));
testing_2.expect(err.response.status).toEqual(statusCode);
}); }
}));
testing_2.it("throws an error when authorised fetch response is " + statusCode, testApiCall({
expectedPath: 'blah',
stubbedStatusCode: statusCode,
test: function (api) { return api.authorisedFetch('blah')
.subscribe(function () { return fail(new Error('ApiService should error')); }, function (err) {
testing_2.expect(err).toEqual(jasmine.any(Error));
testing_2.expect(err.response.status).toEqual(statusCode);
}); }
}));
});
testing_2.it('fails gracefully when the API is unavailable', testing_2.async(testing_2.inject([api_1.ApiService, testing_1.MockBackend], function (api, mockBackEnd) {
mockBackEnd.connections.subscribe(function (connection) {
connection.mockError(new Error('error'));
});
return api.fetch('lists/666')
.subscribe(function (res) {
throw new Error('This test should not get a successful response');
}, function (err) {
testing_2.expect(err).toEqual(jasmine.any(Error));
});
})));
testing_2.it('fails post requests gracefully when the API is unavailable', testApiCall({
expectedPath: 'blah',
stubbedError: new Error('boom'),
test: function (api) { return api.post('blah', {})
.subscribe(function () { return fail(new Error('ApiService should error')); }, function (err) { return testing_2.expect(err).toEqual(jasmine.any(Error)); }); }
}));
testing_2.it('fails fetch requests gracefully when the API is unavailable', testApiCall({
expectedPath: 'blah',
stubbedError: new Error('boom'),
test: function (api) { return api.fetch('blah')
.subscribe(function () { return fail(new Error('ApiService should error')); }, function (err) { return testing_2.expect(err).toEqual(jasmine.any(Error)); }); }
}));
testing_2.it('fails authorised fetch requests gracefully when the API is unavailable', testApiCall({
expectedPath: 'blah',
stubbedError: new Error('boom'),
test: function (api) { return api.authorisedFetch('blah')
.subscribe(function () { return fail(new Error('ApiService should error')); }, function (err) { return testing_2.expect(err).toEqual(jasmine.any(Error)); }); }
}));
});
//# sourceMappingURL=api.test.js.map

@@ -79,3 +79,3 @@ export interface Type {

offline_id: string;
player_id: string;
play_id: string;
isrc: string;

@@ -82,0 +82,0 @@ release_date: string;

{
"name": "angular-apollo",
"description": "An API client for the 7digital Apollo platform built for Angular 2 projects.",
"version": "0.1.1",
"version": "0.2.0",
"main": "dist/index.js",

@@ -6,0 +6,0 @@ "repository": "https://github.com/7digital/angular-apollo.git",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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