Skip to content

Commit

Permalink
feat: switch Storage errors to use http-errors
Browse files Browse the repository at this point in the history
  • Loading branch information
JakubMatejka committed Aug 28, 2018
1 parent 6575642 commit 0458672
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 150 deletions.
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@keboola/storage-api-js-client",
"version": "1.0.5",
"version": "2.0.0",
"description": "Javascript client for Keboola Storage API",
"main": "src/Storage.js",
"repository": "https://github.com/keboola/storage-api-js-client",
Expand All @@ -15,17 +15,18 @@
"axios-retry": "^3.1.0",
"bluebird": "^3.5.1",
"csv-string": "^3.1.2",
"http-errors": "^1.7.0",
"lodash": "^4.17.10",
"querystring": "^0.2.0",
"sleep-promise": "^6.0.0"
"sleep-promise": "^8.0.1"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1",
"eslint": "^4.19.1",
"eslint-config-airbnb-base": "^12.1.0",
"eslint": "^5.4.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-plugin-import": "^2.11.0",
"mocha": "^5.1.1",
"unexpected": "^10.37.7"
Expand Down
1 change: 1 addition & 0 deletions src/Files.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class Files {

prepare(name, options = {}) {
const data = _.merge({ name }, options);
data.federationToken = true;
return this.storage.request('post', 'files/prepare', data);
}

Expand Down
7 changes: 3 additions & 4 deletions src/Jobs.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
const _ = require('lodash');
const createError = require('http-errors');
const sleep = require('sleep-promise');

const StorageError = require('./StorageError');

class Jobs {
constructor(storage) {
this.storage = storage;
}

wait(id, repeat = 1) {
if (repeat > 20) {
throw new StorageError(`Storage job ${id} has not finished even after 10 minutes, try again later.`);
throw createError(400, `Storage job ${id} has not finished even after 10 minutes, try again later.`);
}
return this.storage.request('get', `jobs/${id}`)
.then((res) => {
Expand All @@ -21,7 +20,7 @@ class Jobs {
if (_.get(res, 'status') === 'success') {
return res;
}
throw new StorageError(`Storage job ${id} failed with error ${JSON.stringify(res)}`);
throw createError(400, `Storage job ${id} failed with error ${JSON.stringify(res)}`);
});
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/Storage.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const _ = require('lodash');
const axios = require('axios');
const createError = require('http-errors');
const Promise = require('bluebird');
const QueryString = require('querystring');

const Buckets = require('./Buckets');
const Files = require('./Files');
const Jobs = require('./Jobs');
const StorageError = require('./StorageError');
const Tables = require('./Tables');

class Storage {
Expand All @@ -32,13 +32,13 @@ class Storage {
return axios(params)
.catch((err) => {
if (_.get(err, 'response.status', null) === 401) {
throw StorageError.unauthorized('Invalid access token');
throw createError(401, 'Invalid access token');
}
const message = _.get(err, 'response.data.error', err.message);
const code = _.get(err, 'response.status', 0);
throw StorageError.error(
`Storage request ${method} ${url} failed with code ${code} and message: ${message}`,
code
throw createError(
code,
`Storage request ${method} ${url} failed with code ${code} and message: ${message}`
);
})
.then(res => res.data);
Expand All @@ -52,7 +52,7 @@ class Storage {
return this.verifyToken()
.then(auth => new Promise((resolve, reject) => {
if (!_.has(auth, 'admin')) {
reject(StorageError.error('You need a master Storage token', 403));
reject(createError(403, 'You need a master Storage token'));
}
resolve();
}).then(() => auth));
Expand Down
20 changes: 0 additions & 20 deletions src/StorageError.js

This file was deleted.

49 changes: 23 additions & 26 deletions test/Buckets.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,33 @@ describe('Storage.Buckets', () => {

const bucketName1 = `bucket1-${_.random(1000, 2000)}`;
const bucketId1 = `in.c-${bucketName1}`;
it('create', () =>
expect(() => storage.request('get', `buckets/${bucketId1}`), 'to be rejected')
.then(() => expect(() => storage.Buckets.create('in', bucketName1, { description: bucketName1 }), 'to be fulfilled'))
.then(() => storage.request('get', `buckets/${bucketId1}`))
.then((res) => {
expect(res, 'to have key', 'description');
expect(res.description, 'to be', bucketName1);
})
.then(() => storage.request('delete', `buckets/${bucketId1}`)));
it('create', () => expect(() => storage.request('get', `buckets/${bucketId1}`), 'to be rejected')
.then(() => expect(() => storage.Buckets.create('in', bucketName1, { description: bucketName1 }), 'to be fulfilled'))
.then(() => storage.request('get', `buckets/${bucketId1}`))
.then((res) => {
expect(res, 'to have key', 'description');
expect(res.description, 'to be', bucketName1);
})
.then(() => storage.request('delete', `buckets/${bucketId1}`)));

const bucketName2 = `bucket2-${_.random(1000, 2000)}`;
const bucketId2 = `in.c-${bucketName2}`;
it('get', () =>
expect(() => storage.Buckets.get(bucketId2), 'to be rejected')
.then(() => storage.request('post', 'buckets', { stage: 'in', name: bucketName2 }))
.then(() => storage.Buckets.get(bucketId2))
.then((res) => {
expect(res, 'to have key', 'id');
expect(res.id, 'to be', bucketId2);
expect(res, 'to have key', 'name');
expect(res.name, 'to be', `c-${bucketName2}`);
})
.then(() => storage.request('delete', `buckets/${bucketId2}`))
.then(() => expect(() => storage.Buckets.get(bucketId2), 'to be rejected')));
it('get', () => expect(() => storage.Buckets.get(bucketId2), 'to be rejected')
.then(() => storage.request('post', 'buckets', { stage: 'in', name: bucketName2 }))
.then(() => storage.Buckets.get(bucketId2))
.then((res) => {
expect(res, 'to have key', 'id');
expect(res.id, 'to be', bucketId2);
expect(res, 'to have key', 'name');
expect(res.name, 'to be', `c-${bucketName2}`);
})
.then(() => storage.request('delete', `buckets/${bucketId2}`))
.then(() => expect(() => storage.Buckets.get(bucketId2), 'to be rejected')));

const bucketName3 = `bucket3-${_.random(1000, 2000)}`;
const bucketId3 = `in.c-${bucketName3}`;
it('delete', () =>
expect(() => storage.Buckets.delete(bucketId3), 'to be rejected')
.then(() => storage.request('post', 'buckets', { stage: 'in', name: bucketName3 }))
.then(() => expect(() => storage.Buckets.delete(bucketId3), 'to be fulfilled'))
.then(() => expect(() => storage.request('get', `buckets/${bucketId3}`), 'to be rejected')));
it('delete', () => expect(() => storage.Buckets.delete(bucketId3), 'to be rejected')
.then(() => storage.request('post', 'buckets', { stage: 'in', name: bucketName3 }))
.then(() => expect(() => storage.Buckets.delete(bucketId3), 'to be fulfilled'))
.then(() => expect(() => storage.request('get', `buckets/${bucketId3}`), 'to be rejected')));
});
52 changes: 25 additions & 27 deletions test/Files.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,30 @@ aws.config.setPromisesDependency(Promise);
describe('Storage.Files', () => {
const storage = new Storage(process.env.KBC_URL, process.env.KBC_TOKEN);

it('prepare', () =>
storage.Files.prepare('test.csv', true)
.then((res) => {
expect(res, 'to have key', 'id');
expect(res, 'to have key', 'name');
expect(res, 'to have key', 'url');
expect(res.name, 'to be', 'test.csv');
return res.id;
})
.then(id => storage.request('delete', `files/${id}`)));
it('prepare', () => storage.Files.prepare('test.csv', true)
.then((res) => {
expect(res, 'to have key', 'id');
expect(res, 'to have key', 'name');
expect(res, 'to have key', 'url');
expect(res.name, 'to be', 'test.csv');
return res.id;
})
.then(id => storage.request('delete', `files/${id}`)));

it('get', () =>
storage.request('post', 'files/prepare', { name: 'test.txt', federationToken: 1 })
.then((file) => {
const s3 = new aws.S3({
accessKeyId: file.uploadParams.credentials.AccessKeyId,
secretAccessKey: file.uploadParams.credentials.SecretAccessKey,
sessionToken: file.uploadParams.credentials.SessionToken,
});
return s3.putObject({
Bucket: file.uploadParams.bucket,
Key: file.uploadParams.key,
Body: Buffer.from('abcdefgh'),
}).promise()
.then(() => file.id);
})
.then(id => storage.Files.get(id, true)
.then(() => storage.request('delete', `files/${id}`))));
it('get', () => storage.request('post', 'files/prepare', { name: 'test.txt', federationToken: 1 })
.then((file) => {
const s3 = new aws.S3({
accessKeyId: file.uploadParams.credentials.AccessKeyId,
secretAccessKey: file.uploadParams.credentials.SecretAccessKey,
sessionToken: file.uploadParams.credentials.SessionToken,
});
return s3.putObject({
Bucket: file.uploadParams.bucket,
Key: file.uploadParams.key,
Body: Buffer.from('abcdefgh'),
}).promise()
.then(() => file.id);
})
.then(id => storage.Files.get(id, true)
.then(() => storage.request('delete', `files/${id}`))));
});
45 changes: 21 additions & 24 deletions test/Storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,27 @@ const expect = require('unexpected');

describe('Storage', () => {
const storage = new Storage(process.env.KBC_URL, process.env.KBC_TOKEN);
it('request', () =>
storage.request('get', 'tokens/verify')
.then((res) => {
expect(res, 'to have key', 'id');
expect(res, 'to have key', 'token');
expect(res, 'to have key', 'owner');
expect(res.token, 'to be', process.env.KBC_TOKEN);
}));
it('request', () => storage.request('get', 'tokens/verify')
.then((res) => {
expect(res, 'to have key', 'id');
expect(res, 'to have key', 'token');
expect(res, 'to have key', 'owner');
expect(res.token, 'to be', process.env.KBC_TOKEN);
}));

it('verifyToken', () =>
storage.verifyToken()
.then((res) => {
expect(res, 'to have key', 'id');
expect(res, 'to have key', 'token');
expect(res, 'to have key', 'owner');
expect(res.token, 'to be', process.env.KBC_TOKEN);
}));
it('verifyToken', () => storage.verifyToken()
.then((res) => {
expect(res, 'to have key', 'id');
expect(res, 'to have key', 'token');
expect(res, 'to have key', 'owner');
expect(res.token, 'to be', process.env.KBC_TOKEN);
}));

it('verifyTokenAdmin', () =>
storage.verifyTokenAdmin()
.then((res) => {
expect(res, 'to have key', 'id');
expect(res, 'to have key', 'token');
expect(res, 'to have key', 'owner');
expect(res.token, 'to be', process.env.KBC_TOKEN);
}));
it('verifyTokenAdmin', () => storage.verifyTokenAdmin()
.then((res) => {
expect(res, 'to have key', 'id');
expect(res, 'to have key', 'token');
expect(res, 'to have key', 'owner');
expect(res.token, 'to be', process.env.KBC_TOKEN);
}));
});
74 changes: 35 additions & 39 deletions test/Tables.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,46 +47,42 @@ describe('Storage.Tables', () => {

afterEach(() => storage.request('delete', `buckets/${bucketId}?force=1`));

it('create', () =>
storage.Tables.create(bucketId, 'table', `${__dirname}/sample.csv`, { primaryKey: 'id' })
.then((res) => {
expect(res, 'to have key', 'results');
expect(res.results, 'to have key', 'id');
expect(res.results.id, 'to be', `${bucketId}.table`);
expect(res.results, 'to have key', 'primaryKey');
expect(res.results.primaryKey, 'to equal', ['id']);
expect(res.results, 'to have key', 'columns');
expect(res.results.columns, 'to equal', ['id', 'name', 'price', 'date', 'info', 'category']);
expect(res.results, 'to have key', 'rowsCount');
expect(res.results.rowsCount, 'to be', 5);
}));
it('create', () => storage.Tables.create(bucketId, 'table', `${__dirname}/sample.csv`, { primaryKey: 'id' })
.then((res) => {
expect(res, 'to have key', 'results');
expect(res.results, 'to have key', 'id');
expect(res.results.id, 'to be', `${bucketId}.table`);
expect(res.results, 'to have key', 'primaryKey');
expect(res.results.primaryKey, 'to equal', ['id']);
expect(res.results, 'to have key', 'columns');
expect(res.results.columns, 'to equal', ['id', 'name', 'price', 'date', 'info', 'category']);
expect(res.results, 'to have key', 'rowsCount');
expect(res.results.rowsCount, 'to be', 5);
}));

it('get', () =>
createTestTable(storage, bucketId, tableName)
.then(() => storage.Tables.get(tableId))
.then((res) => {
expect(res, 'to have key', 'id');
expect(res.id, 'to be', tableId);
expect(res, 'to have key', 'columns');
expect(res.columns, 'to equal', ['id', 'name', 'price', 'date', 'info', 'category']);
expect(res, 'to have key', 'rowsCount');
expect(res.rowsCount, 'to be', 5);
}));
it('get', () => createTestTable(storage, bucketId, tableName)
.then(() => storage.Tables.get(tableId))
.then((res) => {
expect(res, 'to have key', 'id');
expect(res.id, 'to be', tableId);
expect(res, 'to have key', 'columns');
expect(res.columns, 'to equal', ['id', 'name', 'price', 'date', 'info', 'category']);
expect(res, 'to have key', 'rowsCount');
expect(res.rowsCount, 'to be', 5);
}));

it('export', () =>
createTestTable(storage, bucketId, tableName)
.then(() => expect(() => storage.request('get', `tables/${tableId}`), 'to be fulfilled'))
.then(() => storage.Tables.export(tableId))
.then((res) => {
expect(res, 'to be a', 'array');
expect(res, 'to have length', 5);
expect(res[0], 'to be a', 'array');
expect(res[0], 'to have length', 6);
}));
it('export', () => createTestTable(storage, bucketId, tableName)
.then(() => expect(() => storage.request('get', `tables/${tableId}`), 'to be fulfilled'))
.then(() => storage.Tables.export(tableId))
.then((res) => {
expect(res, 'to be a', 'array');
expect(res, 'to have length', 5);
expect(res[0], 'to be a', 'array');
expect(res[0], 'to have length', 6);
}));

it('delete', () =>
createTestTable(storage, bucketId, tableName)
.then(() => expect(() => storage.request('get', `tables/${tableId}`), 'to be fulfilled'))
.then(() => storage.Tables.delete(tableId))
.then(() => expect(() => storage.request('get', `tables/${tableId}`), 'to be rejected')));
it('delete', () => createTestTable(storage, bucketId, tableName)
.then(() => expect(() => storage.request('get', `tables/${tableId}`), 'to be fulfilled'))
.then(() => storage.Tables.delete(tableId))
.then(() => expect(() => storage.request('get', `tables/${tableId}`), 'to be rejected')));
});

0 comments on commit 0458672

Please sign in to comment.