@hestia-earth/data-api 0.0.2-2 → 0.0.2-4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/package.json +3 -2
  2. package/.dockerignore +0 -25
  3. package/.env.test +0 -7
  4. package/.eslintignore +0 -7
  5. package/.eslintrc.js +0 -11
  6. package/.gitlab-ci.yml +0 -125
  7. package/.mocharc.js +0 -8
  8. package/.nvrm +0 -1
  9. package/.nycrc +0 -15
  10. package/Dockerfile +0 -17
  11. package/cleanup-docker.sh +0 -4
  12. package/commitlint.config.js +0 -1
  13. package/database/index.ts +0 -76
  14. package/database/migrations/001.do.init.sql +0 -53
  15. package/database/migrations/002.do.add-aggregated-sites.sql +0 -16
  16. package/database/migrations/003.do.add-generated-period-cols.sql +0 -7
  17. package/database/migrations/index.ts +0 -36
  18. package/database/seed/common.ts +0 -7
  19. package/database/seed/index.ts +0 -55
  20. package/database/seed/local/index.ts +0 -28
  21. package/database/seed/production/index.ts +0 -3
  22. package/database/seed/staging/index.ts +0 -5
  23. package/database/seed/test/index.ts +0 -28
  24. package/dev.ts +0 -3
  25. package/dist/aggregated-nodes/model/index.js +0 -11
  26. package/docker-compose.yml +0 -42
  27. package/envs/.master.env +0 -7
  28. package/envs/.staging.env +0 -7
  29. package/index.js +0 -3
  30. package/run-docker.sh +0 -14
  31. package/run-test.sh +0 -5
  32. package/scripts/run-lambda.ts +0 -10
  33. package/scripts/run-migrations.ts +0 -18
  34. package/scripts/run-resetdb.ts +0 -18
  35. package/scripts/run-seed.ts +0 -18
  36. package/serverless.yml +0 -76
  37. package/src/aggregated-nodes/model/index.ts +0 -37
  38. package/src/aggregated-nodes/routes/pg-get-filters.ts +0 -44
  39. package/src/aggregated-nodes/routes/pg-get.ts +0 -50
  40. package/src/aggregated-nodes/routes.spec.ts +0 -242
  41. package/src/aggregated-nodes/routes.ts +0 -56
  42. package/src/aggregated-nodes/services/pg-get-filters.ts +0 -52
  43. package/src/aggregated-nodes/services/pg-get.ts +0 -77
  44. package/src/app.spec.ts +0 -34
  45. package/src/app.ts +0 -59
  46. package/src/config.ts +0 -21
  47. package/src/cors.spec.ts +0 -32
  48. package/src/cors.ts +0 -7
  49. package/src/errors.spec.ts +0 -114
  50. package/src/errors.ts +0 -121
  51. package/src/index.spec.ts +0 -94
  52. package/src/index.ts +0 -14
  53. package/src/lambdas/sentry.ts +0 -12
  54. package/src/lambdas/update-aggregated-nodes/handler.spec.ts +0 -86
  55. package/src/lambdas/update-aggregated-nodes/handler.ts +0 -141
  56. package/src/logger.spec.ts +0 -20
  57. package/src/logger.ts +0 -45
  58. package/src/maintenance.spec.ts +0 -76
  59. package/src/maintenance.ts +0 -19
  60. package/src/models.ts +0 -1
  61. package/src/routes.ts +0 -8
  62. package/src/settings/model/index.ts +0 -21
  63. package/src/settings/routes/get.spec.ts +0 -33
  64. package/src/settings/routes/get.ts +0 -3
  65. package/src/settings/routes/update.spec.ts +0 -33
  66. package/src/settings/routes/update.ts +0 -5
  67. package/src/settings/routes.spec.ts +0 -75
  68. package/src/settings/routes.ts +0 -21
  69. package/src/settings/services/get.spec.ts +0 -62
  70. package/src/settings/services/get.ts +0 -18
  71. package/src/settings/services/update.spec.ts +0 -118
  72. package/src/settings/services/update.ts +0 -47
  73. package/src/slack.spec.ts +0 -42
  74. package/src/slack.ts +0 -17
  75. package/src/swagger/routes.ts +0 -57
  76. package/src/types/async-express-errors/index.d.ts +0 -1
  77. package/src/types/express/index.d.ts +0 -10
  78. package/src/utils/endpoint-wrapper.spec.ts +0 -80
  79. package/src/utils/endpoint-wrapper.ts +0 -16
  80. package/src/utils/middleware.spec.ts +0 -154
  81. package/src/utils/middleware.ts +0 -33
  82. package/test/Dockerfile +0 -13
  83. package/test/docker-compose.yml +0 -40
  84. package/test/fixtures/aggregated-nodes/get.ts +0 -184
  85. package/test/fixtures/update-aggregated-nodes/abyssinianKaleSeedWhole-cycle_pivoted.csv +0 -5
  86. package/test/fixtures/update-aggregated-nodes/abyssinianKaleSeedWhole-cycle_pivoted.csv.cycle.json +0 -458
  87. package/test/fixtures/update-aggregated-nodes/abyssinianKaleSeedWhole-cycle_pivoted.csv.site.json +0 -182
  88. package/test/fixtures/update-aggregated-nodes/abyssinianKaleSeedWhole-impactassessment_pivoted.csv +0 -3
  89. package/test/fixtures/update-aggregated-nodes/abyssinianKaleSeedWhole-impactassessment_pivoted.csv.impactAssessment.json +0 -988
  90. package/test/fixtures/update-aggregated-nodes/abyssinianKaleStraw-impactassessment_pivoted.csv +0 -3
  91. package/test/fixtures/update-aggregated-nodes/cycle-missing-impactassessment_pivoted.csv +0 -3
  92. package/test/fixtures/update-aggregated-nodes/tomatoFruit-cycle_pivoted.csv +0 -5
  93. package/test/fixtures/update-aggregated-nodes/tomatoFruit-cycle_pivoted.csv.cycle.json +0 -584
  94. package/test/fixtures/update-aggregated-nodes/tomatoFruit-cycle_pivoted.csv.site.json +0 -212
  95. package/test/fixtures/update-aggregated-nodes/tomatoFruit-impactassessment_pivoted.csv +0 -3
  96. package/test/fixtures/update-aggregated-nodes/tomatoFruit-impactassessment_pivoted.csv.impactAssessment.json +0 -1002
  97. package/test/prepare.ts +0 -13
  98. package/test/utils.ts +0 -33
  99. package/tsconfig.build.json +0 -13
  100. package/tsconfig.dist.json +0 -14
  101. package/tsconfig.json +0 -42
  102. package/tsconfig.lambdas.json +0 -13
@@ -1,118 +0,0 @@
1
- import { expect } from 'chai';
2
- import * as sinon from 'sinon';
3
- import 'mocha';
4
-
5
- import * as slack from '../../slack';
6
- import { postMessage } from './update';
7
- import * as model from '../model';
8
- import * as servicesGet from './get';
9
-
10
- let stubs: sinon.SinonStub[] = [];
11
-
12
- describe('settings > services', () => {
13
- beforeEach(() => {
14
- stubs = [];
15
- });
16
-
17
- afterEach(() => {
18
- stubs.forEach((stub) => stub.restore());
19
- });
20
-
21
- describe('update', () => {
22
- describe('postMessage', () => {
23
- const slackThreadTs = 'thread';
24
- let updateStub: sinon.SinonStub;
25
- let sendMessageStub: sinon.SinonStub;
26
- let replyMessageStub: sinon.SinonStub;
27
-
28
- beforeEach(() => {
29
- stubs.push((updateStub = sinon.stub(model, 'setSetting').resolves()));
30
- stubs.push((sendMessageStub = sinon.stub(slack, 'sendMessage').resolves(slackThreadTs)));
31
- stubs.push((replyMessageStub = sinon.stub(slack, 'replyMessage').resolves(slackThreadTs)));
32
- });
33
-
34
- describe('turning setting on', () => {
35
- const key = model.SettingKey.maintenanceEnabled;
36
- const value = true;
37
-
38
- beforeEach(() => {
39
- stubs.push(
40
- sinon.stub(servicesGet, 'get').resolves({
41
- rows: [{ setting: key, active: value, metadata: {} }]
42
- } as any)
43
- );
44
- });
45
-
46
- it('should send the message', async () => {
47
- await postMessage(key, value);
48
- expect(sendMessageStub.called).to.equal(true);
49
- });
50
-
51
- it('should not reply to the message', async () => {
52
- await postMessage(key, value);
53
- expect(replyMessageStub.called).to.equal(false);
54
- });
55
-
56
- it('should set the thread', async () => {
57
- await postMessage(key, value);
58
- expect(updateStub.calledWith({ key, value, metadata: { slackThreadTs } })).to.equal(true);
59
- });
60
- });
61
-
62
- describe('turning setting off', () => {
63
- const key = model.SettingKey.maintenanceEnabled;
64
- const value = false;
65
-
66
- describe('existing thread', () => {
67
- beforeEach(() => {
68
- stubs.push(
69
- sinon.stub(servicesGet, 'get').resolves({
70
- rows: [{ setting: key, active: value, metadata: { slackThreadTs } }]
71
- } as any)
72
- );
73
- });
74
-
75
- it('should not send the message', async () => {
76
- await postMessage(key, value);
77
- expect(sendMessageStub.called).to.equal(false);
78
- });
79
-
80
- it('should reply the message', async () => {
81
- await postMessage(key, value);
82
- expect(replyMessageStub.called).to.equal(true);
83
- });
84
-
85
- it('should remove the thread', async () => {
86
- await postMessage(key, value);
87
- expect(updateStub.calledWith({ key, value, metadata: { slackThreadTs: null } })).to.equal(true);
88
- });
89
- });
90
-
91
- describe('non-existing thread', () => {
92
- beforeEach(() => {
93
- stubs.push(
94
- sinon.stub(servicesGet, 'get').resolves({
95
- rows: [{ setting: key, active: value, metadata: {} }]
96
- } as any)
97
- );
98
- });
99
-
100
- it('should not send the message', async () => {
101
- await postMessage(key, value);
102
- expect(sendMessageStub.called).to.equal(false);
103
- });
104
-
105
- it('should not reply to the message', async () => {
106
- await postMessage(key, value);
107
- expect(replyMessageStub.called).to.equal(false);
108
- });
109
-
110
- it('should remove the thread', async () => {
111
- await postMessage(key, value);
112
- expect(updateStub.calledWith({ key, value, metadata: { slackThreadTs: null } })).to.equal(true);
113
- });
114
- });
115
- });
116
- });
117
- });
118
- });
@@ -1,47 +0,0 @@
1
- import { apiUrl, webappUrl } from '../../config';
2
- import { sendMessage, replyMessage } from '../../slack';
3
- import { get } from './get';
4
- import { SettingKey, setSetting } from '../model/';
5
-
6
- type settingData = { [key in SettingKey]?: any };
7
-
8
- const slackChannel = 'product-team';
9
-
10
- const messageByKey: {
11
- [key in SettingKey]?: (value: any) => string;
12
- } = {
13
- [SettingKey.maintenanceEnabled]: (value: boolean) =>
14
- value ? 'Data API is under maintenance, please do not use the data explorer' : 'Maintenance ended'
15
- };
16
-
17
- export const postMessage = async (key: SettingKey, value: boolean) => {
18
- const { rows } = await get(key);
19
- const setting = rows?.[0];
20
- const message = messageByKey[key](value);
21
- const fullMessage = `
22
- ${messageByKey[key](value)}
23
-
24
- *API*: ${apiUrl}
25
- *Website*: ${webappUrl}
26
- `.trim();
27
- const existingThread = setting ? setting.metadata?.slackThreadTs : null;
28
- const ts = value
29
- ? // setting is turned on, create new thread
30
- await sendMessage({ channel: slackChannel, text: fullMessage })
31
- : existingThread
32
- ? // setting is turned off and thread exists, reply to it
33
- await replyMessage(existingThread, { channel: slackChannel, text: message })
34
- : // setting is turned off and no thread exists, ignore
35
- null;
36
-
37
- return setSetting({ key, value, metadata: { slackThreadTs: value ? ts : null } });
38
- };
39
-
40
- export const updateSingle = async (key: SettingKey, value: any) => {
41
- await setSetting({ key, value });
42
- Object.keys(messageByKey).includes(key) && (await postMessage(key, value));
43
- };
44
-
45
- export const updateAll = (value: settingData) => {
46
- return Promise.all(Object.entries(value).map(([key, v]) => updateSingle(key as SettingKey, v)));
47
- };
package/src/slack.spec.ts DELETED
@@ -1,42 +0,0 @@
1
- import { expect } from 'chai';
2
- import * as sinon from 'sinon';
3
- import 'mocha';
4
- import * as slackApi from '@slack/web-api/dist/WebClient';
5
- import { sendMessage, replyMessage } from './slack';
6
-
7
- let stubs: sinon.SinonStub[] = [];
8
- const postMessageStub: sinon.SinonStub = sinon.stub().returns({ ts: 'ts' });
9
-
10
- const SlackWebClientStub = sinon.createStubInstance(slackApi.WebClient);
11
- (SlackWebClientStub as any).chat = { postMessage: postMessageStub };
12
-
13
- describe('slack', () => {
14
- beforeEach(() => {
15
- stubs = [];
16
- stubs.push(sinon.stub(slackApi, 'WebClient').returns(SlackWebClientStub));
17
- });
18
-
19
- afterEach(() => {
20
- stubs.forEach((stub) => stub.restore());
21
- postMessageStub.resetHistory();
22
- });
23
-
24
- describe('sendMessage', () => {
25
- it('should send a message to a channel', async () => {
26
- await sendMessage({});
27
- expect(postMessageStub.args).to.deep.equal([[{ channel: process.env.SLACK_CHANNEL, link_names: true }]]);
28
- });
29
- });
30
-
31
- describe('replyMessage', () => {
32
- describe('with thread', () => {
33
- it('should send a message to a thread', async () => {
34
- await replyMessage('thread_ts', {});
35
-
36
- expect(postMessageStub.args).to.deep.equal([
37
- [{ channel: process.env.SLACK_CHANNEL, thread_ts: 'thread_ts', link_names: true }]
38
- ]);
39
- });
40
- });
41
- });
42
- });
package/src/slack.ts DELETED
@@ -1,17 +0,0 @@
1
- import { WebClient, ChatPostMessageArguments } from '@slack/web-api';
2
-
3
- import { slackConfig } from './config';
4
-
5
- const channel = slackConfig.channel;
6
-
7
- export const sendMessage = async (args: Partial<ChatPostMessageArguments>) =>
8
- (
9
- await new WebClient(slackConfig.token).chat.postMessage({
10
- channel: args.channel || channel,
11
- link_names: true,
12
- ...args
13
- })
14
- ).ts;
15
-
16
- export const replyMessage = async (thread_ts: string, args: Omit<ChatPostMessageArguments, 'thread_ts'>) =>
17
- thread_ts ? await sendMessage({ thread_ts, ...args }) : null;
@@ -1,57 +0,0 @@
1
- import { Router } from 'express';
2
- import { serve, setup } from 'swagger-ui-express';
3
- import swaggerJSDoc from 'swagger-jsdoc';
4
-
5
- import { apiUrl } from '../config';
6
- import pkg from '../../package.json';
7
-
8
- const options = {
9
- swaggerDefinition: {
10
- openapi: '3.0.1',
11
- info: {
12
- title: pkg.name,
13
- version: pkg.version,
14
- description: 'Hestia Data API documentation.',
15
- license: {
16
- name: 'GPL-3.0-or-later',
17
- url: 'https://choosealicense.com/licenses/gpl-3.0/'
18
- }
19
- },
20
- components: {
21
- securitySchemes: {
22
- AccessToken: {
23
- type: 'apiKey',
24
- in: 'header',
25
- name: 'x-access-token'
26
- }
27
- }
28
- },
29
- servers: [
30
- {
31
- url: apiUrl
32
- }
33
- ]
34
- },
35
- apis: ['src/*.ts', 'src/**/*.ts']
36
- };
37
-
38
- const swaggerSpec = swaggerJSDoc(options);
39
- const swaggerOptions = {
40
- customCss: `
41
- .swagger-ui .topbar {
42
- display: none;
43
- }
44
- `,
45
- customSiteTitle: 'Hestia Data API Explorer',
46
- url: '/swagger.json'
47
- };
48
-
49
- export default () => {
50
- const router = Router();
51
-
52
- router.use('/', serve);
53
- router.get('/', setup(swaggerSpec, swaggerOptions));
54
- router.get('/swagger.json', (req, res) => res.json(swaggerSpec));
55
-
56
- return router;
57
- };
@@ -1 +0,0 @@
1
- declare module 'express-async-errors';
@@ -1,10 +0,0 @@
1
- import { IFilter } from '../../aggregated-nodes/model';
2
-
3
- declare global {
4
- namespace Express {
5
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
6
- interface Request {
7
- filter: IFilter;
8
- }
9
- }
10
- }
@@ -1,80 +0,0 @@
1
- import { expect } from 'chai';
2
- import * as sinon from 'sinon';
3
- import 'mocha';
4
-
5
- import { endpointWrapper } from './endpoint-wrapper';
6
-
7
- class Response {
8
- status(_status: number) {
9
- return this;
10
- }
11
-
12
- json() {}
13
- }
14
-
15
- let stubs: sinon.SinonStub[] = [];
16
-
17
- describe('utils > endpoint-wrapper', () => {
18
- beforeEach(() => {
19
- stubs = [];
20
- });
21
-
22
- afterEach(() => {
23
- stubs.forEach((stub) => stub.restore());
24
- });
25
-
26
- describe('endpointWrapper', () => {
27
- const response = new Response();
28
- let fakeFunction: Function;
29
- let jsonStub: sinon.SinonStub;
30
- let nextStub: sinon.SinonStub;
31
-
32
- beforeEach(() => {
33
- stubs.push((jsonStub = sinon.stub(response, 'json')));
34
- nextStub = sinon.stub();
35
- });
36
-
37
- describe('function fail', () => {
38
- const err = new Error('error');
39
-
40
- beforeEach(() => {
41
- fakeFunction = () => {
42
- throw err;
43
- };
44
- });
45
-
46
- it('should reject', async () => {
47
- const result = endpointWrapper(fakeFunction);
48
- await result(null, response as any, nextStub);
49
- expect(jsonStub.called).to.equal(false);
50
- expect(nextStub.calledWith(err)).to.equal(true);
51
- });
52
- });
53
-
54
- describe('function success', () => {
55
- beforeEach(() => {
56
- fakeFunction = () => 'success';
57
- });
58
-
59
- it('should resolve', async () => {
60
- const result = endpointWrapper(fakeFunction);
61
- await result(null, response as any, nextStub);
62
- expect(jsonStub.calledWith('success')).to.equal(true);
63
- expect(nextStub.called).to.equal(false);
64
- });
65
- });
66
-
67
- describe('without a function', () => {
68
- beforeEach(() => {
69
- fakeFunction = undefined;
70
- });
71
-
72
- it('should resolve', async () => {
73
- const result = endpointWrapper(fakeFunction);
74
- await result(null, response as any, nextStub);
75
- expect(jsonStub.calledWith({})).to.equal(true);
76
- expect(nextStub.called).to.equal(false);
77
- });
78
- });
79
- });
80
- });
@@ -1,16 +0,0 @@
1
- import { Request, Response, NextFunction } from 'express';
2
-
3
- // Until express v5 promises must be coerced to void
4
- // See https://github.com/davidbanham/express-async-errors/issues/36#issuecomment-944954003
5
- export const endpointWrapper =
6
- (originalFunction: Function = () => ({})) =>
7
- (req: Request, res: Response, next: NextFunction) =>
8
- void (async function () {
9
- try {
10
- const output = await Promise.resolve(originalFunction(req, res, next));
11
- return res.status(200).json(output);
12
- }
13
- catch (err) {
14
- return next(err);
15
- }
16
- })();
@@ -1,154 +0,0 @@
1
- import { expect } from 'chai';
2
- import * as sinon from 'sinon';
3
- import 'mocha';
4
-
5
- import { Errors } from '../errors';
6
- import { requireQueryParams, parseArrayQueryParams, parseBooleanQueryParams } from './middleware';
7
- import * as errors from '../errors';
8
-
9
- let stubs: sinon.SinonStub[] = [];
10
-
11
- describe('utils', () => {
12
- beforeEach(() => {
13
- stubs = [];
14
- });
15
-
16
- afterEach(() => {
17
- stubs.forEach((stub) => stub.restore());
18
- });
19
-
20
- describe('middleware', () => {
21
- let nextStub: sinon.SinonStub;
22
- let throwErrorStub: sinon.SinonStub;
23
-
24
- beforeEach(() => {
25
- nextStub = sinon.stub();
26
- stubs.push((throwErrorStub = sinon.stub(errors, 'throwError')));
27
- });
28
-
29
- describe('requireQueryParams', () => {
30
- const req: any = { query: {} };
31
-
32
- describe('with missing params', () => {
33
- beforeEach(() => {
34
- req.query.a = 1;
35
- req.query.b = {};
36
- req.query.c = '';
37
- });
38
-
39
- it('should throw an error', () => {
40
- requireQueryParams('a', 'b', 'c')(req, null, nextStub);
41
- expect(throwErrorStub.calledWith(Errors.MissingQueryParam, { params: ['b', 'c'] })).to.equal(true);
42
- });
43
-
44
- it('should NOT call next', () => {
45
- requireQueryParams('a', 'b', 'c')(req, null, nextStub);
46
- expect(nextStub.called).to.equal(false);
47
- });
48
- });
49
-
50
- describe('with all params', () => {
51
- beforeEach(() => {
52
- req.query.a = 1;
53
- req.query.b = { value: true };
54
- req.query.c = 'test';
55
- });
56
-
57
- it('should NOT throw an error', () => {
58
- requireQueryParams('a', 'b', 'c')(req, null, nextStub);
59
- expect(throwErrorStub.called).to.equal(false);
60
- });
61
-
62
- it('should call next', () => {
63
- requireQueryParams('a', 'b', 'c')(req, null, nextStub);
64
- expect(nextStub.called).to.equal(true);
65
- });
66
- });
67
- });
68
-
69
- describe('parseArrayQueryParams', () => {
70
- const req: any = { query: {} };
71
-
72
- describe('specified param is a string', () => {
73
- beforeEach(() => {
74
- req.query.stringParam = 'param1,param2';
75
- });
76
-
77
- it('should split the search params', () => {
78
- parseArrayQueryParams('stringParam')(req, null, nextStub);
79
- expect(req.query.stringParam).to.deep.equal(['param1', 'param2']);
80
- });
81
-
82
- it('should call next', () => {
83
- parseArrayQueryParams()(req, null, nextStub);
84
- expect(nextStub.called).to.equal(true);
85
- });
86
- });
87
-
88
- describe('specified param is an array', () => {
89
- beforeEach(() => {
90
- req.query.arrayParam = ['param1', 'param2'];
91
- });
92
-
93
- it('should keep the search params', () => {
94
- parseArrayQueryParams('arrayParam')(req, null, nextStub);
95
- expect(req.query.arrayParam).to.deep.equal(['param1', 'param2']);
96
- });
97
-
98
- it('should call next', () => {
99
- parseArrayQueryParams()(req, null, nextStub);
100
- expect(nextStub.called).to.equal(true);
101
- });
102
- });
103
- });
104
-
105
- describe('parseBooleanQueryParams', () => {
106
- let req: any;
107
-
108
- describe('param as "true"', () => {
109
- beforeEach(() => {
110
- req = {
111
- query: {
112
- booleanParam: 'true'
113
- }
114
- };
115
- });
116
-
117
- it('should return true', () => {
118
- parseBooleanQueryParams('booleanParam')(req, null, nextStub);
119
- expect(req.query.booleanParam).to.equal(true);
120
- });
121
- });
122
-
123
- describe('param as "false"', () => {
124
- beforeEach(() => {
125
- req = {
126
- query: {
127
- booleanParam: 'false'
128
- }
129
- };
130
- });
131
-
132
- it('should return false', () => {
133
- parseBooleanQueryParams('booleanParam')(req, null, nextStub);
134
- expect(req.query.booleanParam).to.equal(false);
135
- });
136
- });
137
-
138
- describe('with empty query string', () => {
139
- beforeEach(() => {
140
- req = {
141
- query: {
142
- booleanParam: ''
143
- }
144
- };
145
- });
146
-
147
- it('should return false', () => {
148
- parseBooleanQueryParams('booleanParam')(req, null, nextStub);
149
- expect(req.query.booleanParam).to.equal(false);
150
- });
151
- });
152
- });
153
- });
154
- });
@@ -1,33 +0,0 @@
1
- import { Request, Response, NextFunction } from 'express';
2
-
3
- import { Errors, throwError } from '../errors';
4
-
5
- const undefinedObject = <T>(value: T) => typeof value === 'object' && !Object.keys(value).length;
6
-
7
- const undefinedString = <T>(value: T) => typeof value === 'string' && !value;
8
-
9
- const isUndefined = <T>(value: T) =>
10
- value === null || typeof value === 'undefined' || undefinedObject(value) || undefinedString(value);
11
-
12
- export const requireQueryParams =
13
- (...params: string[]) =>
14
- ({ query }: Request, _r: Response, next: NextFunction) => {
15
- const missingParams = params.filter((param) => isUndefined(query[param]));
16
- return missingParams.length === 0 ? next() : throwError(Errors.MissingQueryParam, { params: missingParams });
17
- };
18
-
19
- export const parseArrayQueryParams =
20
- (...fields: string[]) =>
21
- ({ query }: Request, _r: Response, next: NextFunction) => {
22
- fields.forEach((field) => {
23
- query[field] = typeof query[field] === 'string' ? (query[field] as string).split(',') : query[field];
24
- });
25
- next();
26
- };
27
-
28
- export const parseBooleanQueryParams =
29
- (...fields: string[]) =>
30
- (req: Request, _res: Response, next: NextFunction) => {
31
- fields.forEach((field) => ((req.query as any)[field] = req.query[field] === 'true'));
32
- next();
33
- };
package/test/Dockerfile DELETED
@@ -1,13 +0,0 @@
1
- FROM node:18-slim
2
-
3
- WORKDIR /app
4
-
5
- COPY package.json .
6
- COPY package-lock.json .
7
-
8
- RUN npm ci
9
-
10
- # copy source from context
11
- ADD . .
12
-
13
- CMD npm test
@@ -1,40 +0,0 @@
1
- version: '3'
2
-
3
- services:
4
- test:
5
- env_file: '../.env.test'
6
- image: hestia-data-api:test
7
- build:
8
- context: ../
9
- dockerfile: test/Dockerfile
10
- environment:
11
- - PGHOST=hestia-data-api-test-db
12
- - PGUSER=postgres
13
- - PGDATABASE=postgres
14
- - PGPASSWORD=password
15
- - PGPORT=5432
16
- volumes:
17
- - ../src:/app/src
18
- - ../coverage:/app/coverage
19
- - ./:/app/test
20
- depends_on:
21
- db:
22
- condition: service_healthy
23
-
24
- db:
25
- image: postgres:14
26
- container_name: hestia-data-api-test-db
27
- ports:
28
- - 5432:5432
29
- volumes:
30
- - postgres:/data/postgres
31
- environment:
32
- - POSTGRES_PASSWORD=password
33
- healthcheck:
34
- test: ['CMD', 'pg_isready', '-q', '-d', 'postgres', '-U', 'postgres']
35
- interval: 1s
36
- timeout: 5s
37
- retries: 5
38
-
39
- volumes:
40
- postgres: