Skip to content

Commit 520f04b

Browse files
committed
small refactoring
1 parent 8c1e700 commit 520f04b

File tree

8 files changed

+135
-90
lines changed

8 files changed

+135
-90
lines changed

src/AwsApiParser.js

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { TypeComposer } from 'graphql-compose';
44
import type { GraphQLObjectType, GraphQLFieldConfig } from 'graphql-compose/lib/graphql';
55
import AwsService, { type ServiceConfig } from './AwsService';
6+
import AwsConfigITC from './types/AwsConfigITC';
67

78
export type AwsSDK = any;
89

@@ -15,22 +16,41 @@ export default class AwsApiParser {
1516
name: string;
1617
awsSDK: AwsSDK;
1718
tc: TypeComposer;
19+
_serviceMap: { [serviceIdentifier: string]: string };
1820

1921
constructor(opts: AwsOpts) {
2022
this.name = opts.name || 'Aws';
2123
this.awsSDK = opts.awsSDK;
24+
25+
this._serviceMap = {};
26+
this.getServicesNames();
2227
}
2328

2429
getServicesNames(): string[] {
25-
const serviceNames = Object.keys(this.awsSDK.apiLoader.services);
30+
const serviceNames = Object.keys(this.awsSDK).reduce((res, name) => {
31+
if (this.awsSDK[name].serviceIdentifier) {
32+
this._serviceMap[this.awsSDK[name].serviceIdentifier] = name;
33+
res.push(name);
34+
}
35+
return res;
36+
}, []);
2637
serviceNames.sort();
2738
return serviceNames;
2839
}
2940

41+
getServiceIdentifier(name: string): string {
42+
if (this._serviceMap[name]) return name;
43+
44+
if (!this.awsSDK[name]) {
45+
throw new Error(`Service with name '${name}' does not exist. Run AwsApiParser.`);
46+
}
47+
return this.awsSDK[name].serviceIdentifier;
48+
}
49+
3050
getServiceConfig(name: string): ServiceConfig {
31-
const cfg = this.awsSDK.apiLoader.services[name];
51+
const cfg = this.awsSDK.apiLoader.services[this.getServiceIdentifier(name)];
3252
if (!cfg) {
33-
throw new Error(`Service with name ${name} does not exist.`);
53+
throw new Error(`Service with name '${name}' does not exist.`);
3454
}
3555
const versions = Object.keys(cfg);
3656
if (versions.length === 1) {
@@ -42,18 +62,20 @@ export default class AwsApiParser {
4262
}
4363

4464
getService(name: string): AwsService {
65+
const config = this.getServiceConfig(name);
66+
// console.log(config);
4567
return new AwsService({
46-
serviceId: name,
68+
serviceId: this._serviceMap[name] || name,
4769
prefix: this.name,
48-
config: this.getServiceConfig(name),
70+
config,
4971
awsSDK: this.awsSDK,
5072
});
5173
}
5274

5375
getTypeComposer(): TypeComposer {
5476
if (!this.tc) {
5577
const fields = this.getServicesNames().reduce((res, name) => {
56-
res[name] = this.getService(name).getTypeComposer();
78+
res[this.getServiceIdentifier(name)] = this.getService(name).getFieldConfig();
5779
return res;
5880
}, {});
5981

@@ -73,6 +95,15 @@ export default class AwsApiParser {
7395
getFieldConfig(): GraphQLFieldConfig<any, any> {
7496
return {
7597
type: this.getType(),
98+
args: {
99+
config: {
100+
type: AwsConfigITC.getType(),
101+
description: 'Will override default configs for aws-sdk.',
102+
},
103+
},
104+
resolve: (source, args) => ({
105+
awsConfig: { ...(source && source.awsConfig), ...(args && args.config) },
106+
}),
76107
description: this.getTypeComposer().getDescription(),
77108
};
78109
}

src/AwsService.js

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/* @flow */
22

33
import { TypeComposer, upperFirst } from 'graphql-compose';
4-
import type { GraphQLObjectType } from 'graphql-compose/lib/graphql';
4+
import type { GraphQLObjectType, GraphQLFieldConfig } from 'graphql-compose/lib/graphql';
55
import AwsServiceMetadata, { type ServiceMetadataConfig } from './AwsServiceMetadata';
66
import AwsServiceOperation, { type ServiceOperationConfig } from './AwsServiceOperation';
77
import AwsShapes, { type ShapesMap } from './AwsShapes';
88
import type { AwsSDK } from './AwsApiParser';
9+
import AwsConfigITC from './types/AwsConfigITC';
910

1011
export type ServiceConfig = {
1112
version: string,
@@ -48,6 +49,10 @@ export default class AwsService {
4849
return `${this.prefix}${upperFirst(this.serviceId)}`;
4950
}
5051

52+
static lowerFirst(name: string) {
53+
return name.charAt(0).toLowerCase() + name.slice(1);
54+
}
55+
5156
getOperationNames(): string[] {
5257
return Object.keys(this.config.operations);
5358
}
@@ -59,7 +64,7 @@ export default class AwsService {
5964
}
6065
return new AwsServiceOperation({
6166
serviceId: this.serviceId,
62-
name,
67+
name: this.constructor.lowerFirst(name),
6368
prefix: this.prefix,
6469
config: operConfig,
6570
shapes: this.shapes,
@@ -70,7 +75,7 @@ export default class AwsService {
7075
getTypeComposer(): TypeComposer {
7176
if (!this.tc) {
7277
const fields = this.getOperationNames().reduce((res, name) => {
73-
res[name] = this.getOperation(name).getFieldConfig();
78+
res[this.constructor.lowerFirst(name)] = this.getOperation(name).getFieldConfig();
7479
return res;
7580
}, {});
7681

@@ -86,4 +91,19 @@ export default class AwsService {
8691
getType(): GraphQLObjectType {
8792
return this.getTypeComposer().getType();
8893
}
94+
95+
getFieldConfig(): GraphQLFieldConfig<any, any> {
96+
return {
97+
type: this.getType(),
98+
args: {
99+
config: {
100+
type: AwsConfigITC.getType(),
101+
description: 'Will override default configs for aws-sdk.',
102+
},
103+
},
104+
resolve: (source, args) => ({
105+
awsConfig: { ...(source && source.awsConfig), ...(args && args.config) },
106+
}),
107+
};
108+
}
89109
}

src/AwsServiceOperation.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
import AwsParam, { type ParamStructure } from './AwsParam';
1111
import type AwsShapes from './AwsShapes';
1212
import type { AwsSDK } from './AwsApiParser';
13+
import AwsConfigITC from './types/AwsConfigITC';
1314

1415
export type ServiceOperationConfig = {
1516
http?: {
@@ -97,6 +98,10 @@ export default class AwsServiceOperation {
9798
},
9899
};
99100
}
101+
102+
this.args.config = {
103+
type: AwsConfigITC.getType(),
104+
};
100105
}
101106

102107
return this.args;
@@ -105,7 +110,12 @@ export default class AwsServiceOperation {
105110
getResolve(): GraphQLFieldResolver<any, any> {
106111
return ((source: any, args: { [argument: string]: any }) => {
107112
return new Promise((resolve, reject) => {
108-
this.awsSDK[this.serviceId][this.name](args, (err, data) => {
113+
const awsConfig = {
114+
...(source && source.awsConfig),
115+
...(args && args.config),
116+
};
117+
const service = new this.awsSDK[this.serviceId](awsConfig);
118+
service[this.name](args.input, (err, data) => {
109119
if (err) {
110120
reject(err);
111121
}
@@ -120,7 +130,6 @@ export default class AwsServiceOperation {
120130
type: this.getType(),
121131
args: this.getArgs(),
122132
resolve: this.getResolve(),
123-
description: `${this.serviceId}.${this.name}`,
124133
};
125134
}
126135
}

src/__mocks__/elasticClient.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/__tests__/AwsApiParser-test.js

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import awsSDK from 'aws-sdk';
44
import AwsApiParser from '../AwsApiParser';
55
import AwsService from '../AwsService';
6+
import AwsConfigITC from '../types/AwsConfigITC';
67

78
describe('AwsApiParser', () => {
89
const aws = new AwsApiParser({
@@ -11,14 +12,20 @@ describe('AwsApiParser', () => {
1112

1213
it('getServicesNames()', () => {
1314
const names = aws.getServicesNames();
14-
expect(names).toContain('s3');
15-
expect(names).toContain('ec2');
16-
expect(names).toContain('route53');
17-
expect(names).toContain('sqs');
15+
expect(names).toContain('S3');
16+
expect(names).toContain('EC2');
17+
expect(names).toContain('Route53');
18+
expect(names).toContain('SQS');
19+
});
20+
21+
it('getServiceIdentifier()', () => {
22+
expect(aws.getServiceIdentifier('S3')).toBe('s3');
23+
// also should work if provided serviceIdentifier
24+
expect(aws.getServiceIdentifier('s3')).toBe('s3');
1825
});
1926

2027
it('getServiceConfig()', () => {
21-
const cfg = aws.getServiceConfig('s3');
28+
const cfg = aws.getServiceConfig('S3');
2229
expect(Object.keys(cfg)).toEqual([
2330
'version',
2431
'metadata',
@@ -27,24 +34,37 @@ describe('AwsApiParser', () => {
2734
'paginators',
2835
'waiters',
2936
]);
37+
38+
// get config by serviceIdentifier
39+
const cfg2 = aws.getServiceConfig('s3');
40+
expect(Object.keys(cfg2)).toEqual([
41+
'version',
42+
'metadata',
43+
'operations',
44+
'shapes',
45+
'paginators',
46+
'waiters',
47+
]);
3048
});
3149

3250
it('getService()', () => {
33-
const service = aws.getService('s3');
51+
const service = aws.getService('S3');
3452
expect(service).toBeInstanceOf(AwsService);
53+
54+
// get service by serviceIdentifier
55+
const service2 = aws.getService('s3');
56+
expect(service2).toBeInstanceOf(AwsService);
3557
});
3658

3759
it('getType()', () => {
3860
const type = aws.getType();
3961
expect(type.name).toBe('Aws');
4062
});
41-
});
4263

43-
// export default class Aws {
44-
// constructor(opts: AwsOpts) {
45-
// getServicesNames(): string[] {
46-
// getServiceConfig(name: string): ServiceConfig {
47-
// getService(name: string): AwsService {
48-
// getTypeComposer(): TypeComposer {
49-
// getType(): GraphQLObjectType {
50-
// }
64+
it('getFieldConfig()', () => {
65+
const fc: any = aws.getFieldConfig();
66+
expect(fc.type).toBe(aws.getType());
67+
expect(fc.args.config.type).toBe(AwsConfigITC.getType());
68+
expect(fc.resolve()).toEqual({ awsConfig: {} });
69+
});
70+
});

src/__tests__/AwsService-test.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import AwsService from '../AwsService';
44
import AwsServiceOperation from '../AwsServiceOperation';
55
import s3Cfg from '../__mocks__/s3-2006-03-01.json';
6+
import AwsConfigITC from '../types/AwsConfigITC';
67

78
describe('AwsService', () => {
89
const s3 = new AwsService({
@@ -30,11 +31,19 @@ describe('AwsService', () => {
3031
it('getTypeComposer()', () => {
3132
const tc = s3.getTypeComposer();
3233
expect(tc.getTypeName()).toBe('AwsS3');
33-
expect(tc.getFieldNames()).toContain('CreateBucket');
34+
expect(tc.getFieldNames()).toContain('createBucket');
35+
expect(tc.getFieldNames()).toContain('deleteObject');
3436
});
3537

3638
it('getType()', () => {
3739
const type = s3.getType();
3840
expect(type.name).toBe('AwsS3');
3941
});
42+
43+
it('getFieldConfig()', () => {
44+
const fc: any = s3.getFieldConfig();
45+
expect(fc.type).toBe(s3.getType());
46+
expect(fc.args.config.type).toBe(AwsConfigITC.getType());
47+
expect(fc.resolve()).toEqual({ awsConfig: {} });
48+
});
4049
});

src/__tests__/AwsServiceOperation-test.js

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* @flow */
2+
/* eslint-disable class-methods-use-this */
23

34
import {
45
GraphQLInputObjectType,
@@ -7,6 +8,7 @@ import {
78
isOutputType,
89
} from 'graphql-compose/lib/graphql';
910
import AwsServiceOperation from '../AwsServiceOperation';
11+
import AwsConfigITC from '../types/AwsConfigITC';
1012

1113
const operations = {
1214
CreateBucket: {
@@ -73,9 +75,9 @@ const operations = {
7375
};
7476

7577
describe('AwsJsonParserOperation', () => {
76-
const AWSMock = {
77-
S3: {
78-
CreateBucket: jest.fn(),
78+
const AWSMock: any = {
79+
S3: class S3 {
80+
CreateBucket(args, cb) {} // eslint-disable-line
7981
},
8082
};
8183

@@ -114,32 +116,35 @@ describe('AwsJsonParserOperation', () => {
114116
});
115117

116118
it('resolves', async () => {
117-
AWSMock.S3.CreateBucket = jest.fn((args, cb) => {
118-
cb(undefined, { payload: args });
119-
});
120-
const res = await resolve({}, { arg: 123 }, ({}: any), ({}: any));
119+
AWSMock.S3 = class S3WithPayload {
120+
CreateBucket(args, cb) {
121+
cb(undefined, { payload: args });
122+
}
123+
};
124+
const res = await resolve({}, { input: { arg: 123 } }, ({}: any), ({}: any));
121125
expect(res).toEqual({ payload: { arg: 123 } });
122126
});
123127

124128
it('rejects', async () => {
125-
AWSMock.S3.CreateBucket = jest.fn((args, cb) => {
126-
cb('err');
127-
});
129+
AWSMock.S3 = class S3WithError {
130+
CreateBucket(args, cb) {
131+
cb('err');
132+
}
133+
};
128134

129135
expect.assertions(1);
130136
try {
131-
await resolve({}, { arg: 123 }, ({}: any), ({}: any));
137+
await resolve({}, {}, ({}: any), ({}: any));
132138
} catch (e) {
133139
expect(e).toBe('err');
134140
}
135141
});
136142
});
137143

138144
it('getFieldConfig()', () => {
139-
const fc = oper.getFieldConfig();
145+
const fc: any = oper.getFieldConfig();
140146
expect(fc.type).toBeInstanceOf(GraphQLObjectType);
141-
expect(fc.args).toBeDefined();
147+
expect(fc.args.config.type).toBe(AwsConfigITC.getType());
142148
expect((fc.resolve: any).call).toBeDefined();
143-
expect(fc.description).toBe('S3.CreateBucket');
144149
});
145150
});

0 commit comments

Comments
 (0)