Skip to content

Commit 47cd7fe

Browse files
feat: validate constructor options
1 parent eaed71b commit 47cd7fe

File tree

8 files changed

+120
-0
lines changed

8 files changed

+120
-0
lines changed

packages/aws-lambda-graphql/src/DynamoDBConnectionManager.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import assert from 'assert';
12
import { ApiGatewayManagementApi, DynamoDB } from 'aws-sdk';
23
import { ConnectionNotFoundError } from './errors';
34
import {
@@ -69,6 +70,27 @@ export class DynamoDBConnectionManager implements IConnectionManager {
6970
subscriptions,
7071
ttl = DEFAULT_TTL,
7172
}: DynamoDBConnectionManagerOptions) {
73+
assert.ok(
74+
typeof connectionsTable === 'string',
75+
'Please provide connectionsTable as a string',
76+
);
77+
assert.ok(
78+
typeof subscriptions === 'object',
79+
'Please provide subscriptions to manage subscriptions.',
80+
);
81+
assert.ok(
82+
ttl === false || (typeof ttl === 'number' && ttl > 0),
83+
'Please provide ttl as a number greater than 0 or false to turn it off',
84+
);
85+
assert.ok(
86+
dynamoDbClient == null || typeof dynamoDbClient === 'object',
87+
'Please provide dynamoDbClient as an instance of DynamoDB.DocumentClient',
88+
);
89+
assert.ok(
90+
apiGatewayManager == null || typeof apiGatewayManager === 'object',
91+
'Please provide apiGatewayManager as an instance of ApiGatewayManagementApi',
92+
);
93+
7294
this.apiGatewayManager = apiGatewayManager;
7395
this.connectionsTable = connectionsTable;
7496
this.db = dynamoDbClient || new DynamoDB.DocumentClient();

packages/aws-lambda-graphql/src/DynamoDBEventStore.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import assert from 'assert';
12
import { DynamoDB } from 'aws-sdk';
23
import { ulid } from 'ulid';
34
import { IEventStore, ISubscriptionEvent } from './types';
@@ -50,6 +51,19 @@ export class DynamoDBEventStore implements IEventStore {
5051
eventsTable = 'Events',
5152
ttl = DEFAULT_TTL,
5253
}: DynamoDBEventStoreOptions = {}) {
54+
assert.ok(
55+
ttl === false || (typeof ttl === 'number' && ttl > 0),
56+
'Please provide ttl as a number greater than 0 or false to turn it off',
57+
);
58+
assert.ok(
59+
dynamoDbClient == null || typeof dynamoDbClient === 'object',
60+
'Please provide dynamoDbClient as an instance of DynamoDB.DocumentClient',
61+
);
62+
assert.ok(
63+
typeof eventsTable === 'string',
64+
'Please provide eventsTable as a string',
65+
);
66+
5367
this.db = dynamoDbClient || new DynamoDB.DocumentClient();
5468
this.tableName = eventsTable;
5569
this.ttl = ttl;

packages/aws-lambda-graphql/src/DynamoDBSubscriptionManager.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import assert from 'assert';
12
import { DynamoDB } from 'aws-sdk';
23
import {
34
IConnection,
@@ -78,6 +79,23 @@ export class DynamoDBSubscriptionManager implements ISubscriptionManager {
7879
subscriptionOperationsTableName = 'SubscriptionOperations',
7980
ttl = DEFAULT_TTL,
8081
}: DynamoDBSubscriptionManagerOptions = {}) {
82+
assert.ok(
83+
typeof subscriptionOperationsTableName === 'string',
84+
'Please provide subscriptionOperationsTableName as a string',
85+
);
86+
assert.ok(
87+
typeof subscriptionsTableName === 'string',
88+
'Please provide subscriptionsTableName as a string',
89+
);
90+
assert.ok(
91+
ttl === false || (typeof ttl === 'number' && ttl > 0),
92+
'Please provide ttl as a number greater than 0 or false to turn it off',
93+
);
94+
assert.ok(
95+
dynamoDbClient == null || typeof dynamoDbClient === 'object',
96+
'Please provide dynamoDbClient as an instance of DynamoDB.DocumentClient',
97+
);
98+
8199
this.subscriptionsTableName = subscriptionsTableName;
82100
this.subscriptionOperationsTableName = subscriptionOperationsTableName;
83101
this.db = dynamoDbClient || new DynamoDB.DocumentClient();

packages/aws-lambda-graphql/src/PubSub.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import assert from 'assert';
12
import { IEventStore, OperationRequest, SubcribeResolveFn } from './types';
23

34
interface PubSubOptions {
@@ -17,6 +18,14 @@ export class PubSub {
1718
private serializeEventPayload: boolean;
1819

1920
constructor({ eventStore, serializeEventPayload = true }: PubSubOptions) {
21+
assert.ok(
22+
eventStore && typeof eventStore === 'object',
23+
'Please provide eventStore as an instance implementing IEventStore',
24+
);
25+
assert.ok(
26+
typeof serializeEventPayload === 'boolean',
27+
'Please provide serializeEventPayload as a boolean',
28+
);
2029
this.eventStore = eventStore;
2130
this.serializeEventPayload = serializeEventPayload;
2231
}

packages/aws-lambda-graphql/src/RedisConnectionManager.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import assert from 'assert';
12
import { ApiGatewayManagementApi } from 'aws-sdk';
23
import { Redis } from 'ioredis';
34
import { ConnectionNotFoundError } from './errors';
@@ -42,6 +43,19 @@ export class RedisConnectionManager implements IConnectionManager {
4243
redisClient,
4344
subscriptions,
4445
}: RedisConnectionManagerOptions) {
46+
assert.ok(
47+
typeof subscriptions === 'object',
48+
'Please provide subscriptions to manage subscriptions.',
49+
);
50+
assert.ok(
51+
redisClient == null || typeof redisClient === 'object',
52+
'Please provide redisClient as an instance of ioredis.Redis',
53+
);
54+
assert.ok(
55+
apiGatewayManager == null || typeof apiGatewayManager === 'object',
56+
'Please provide apiGatewayManager as an instance of ApiGatewayManagementApi',
57+
);
58+
4559
this.apiGatewayManager = apiGatewayManager;
4660
this.redisClient = redisClient;
4761
this.subscriptions = subscriptions;

packages/aws-lambda-graphql/src/RedisSubscriptionManager.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import assert from 'assert';
12
import { Redis } from 'ioredis';
23
import {
34
IConnection,
@@ -55,6 +56,11 @@ export class RedisSubscriptionManager implements ISubscriptionManager {
5556
private redisClient: Redis;
5657

5758
constructor({ redisClient }: RedisSubscriptionManagerOptions) {
59+
assert.ok(
60+
redisClient == null || typeof redisClient === 'object',
61+
'Please provide redisClient as an instance of ioredis.Redis',
62+
);
63+
5864
this.redisClient = redisClient;
5965
}
6066

packages/aws-lambda-graphql/src/Server.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
CreateHandlerOptions,
55
GraphQLOptions,
66
} from 'apollo-server-lambda';
7+
import assert from 'assert';
78
import {
89
APIGatewayProxyResult,
910
APIGatewayProxyEvent,
@@ -162,6 +163,27 @@ export class Server<
162163
}),
163164
});
164165

166+
assert.ok(
167+
connectionManager,
168+
'Please provide connectionManager and ensure it implements IConnectionManager',
169+
);
170+
assert.ok(
171+
eventProcessor,
172+
'Please provide eventProcessor and ensure it implements IEventProcessor',
173+
);
174+
assert.ok(
175+
subscriptionManager,
176+
'Please provide subscriptionManager and ensure it implements ISubscriptionManager',
177+
);
178+
assert.ok(
179+
typeof onError === 'function' || onError == null,
180+
'onError must be a function',
181+
);
182+
assert.ok(
183+
subscriptions == null || typeof subscriptions === 'object',
184+
'Property subscriptions must be an object',
185+
);
186+
165187
this.connectionManager = connectionManager;
166188
this.eventProcessor = eventProcessor;
167189
this.onError = onError || ((err) => console.error(err));

packages/aws-lambda-graphql/src/__tests__/Server.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import {
1010
import { formatMessage } from '../formatMessage';
1111
import { SERVER_EVENT_TYPES, CLIENT_EVENT_TYPES } from '../protocol';
1212
import { ConnectionNotFoundError } from '../errors';
13+
import { MemoryEventProcessor } from '../MemoryEventProcessor';
1314

1415
describe('Server', () => {
1516
describe('createHttpHandler()', () => {
1617
const server = new Server({
1718
connectionManager: {} as any,
19+
eventProcessor: new MemoryEventProcessor(),
1820
schema: createSchema(),
1921
subscriptionManager: {} as any,
2022
});
@@ -101,6 +103,7 @@ describe('Server', () => {
101103
describe('connect phase', () => {
102104
const server = new Server({
103105
connectionManager,
106+
eventProcessor: new MemoryEventProcessor(),
104107
schema: createSchema(),
105108
subscriptionManager,
106109
});
@@ -175,6 +178,7 @@ describe('Server', () => {
175178
.mockResolvedValueOnce({ key: 'value1' });
176179
const handlerWithOnWebsocketConnect = new Server({
177180
connectionManager,
181+
eventProcessor: new MemoryEventProcessor(),
178182
schema: createSchema(),
179183
subscriptionManager,
180184
subscriptions: {
@@ -215,6 +219,7 @@ describe('Server', () => {
215219
const onWebsocketConnect = jest.fn().mockResolvedValueOnce(false);
216220
const handlerWithOnWebsocketConnect = new Server({
217221
connectionManager,
222+
eventProcessor: new MemoryEventProcessor(),
218223
schema: createSchema(),
219224
subscriptionManager,
220225
subscriptions: {
@@ -378,6 +383,7 @@ describe('Server', () => {
378383
describe('disconnect phase', () => {
379384
const server = new Server({
380385
connectionManager,
386+
eventProcessor: new MemoryEventProcessor(),
381387
schema: createSchema(),
382388
subscriptionManager,
383389
});
@@ -418,6 +424,7 @@ describe('Server', () => {
418424
const onDisconnect = jest.fn();
419425
const handlerWithOnDisconnect = new Server({
420426
connectionManager,
427+
eventProcessor: new MemoryEventProcessor(),
421428
schema: createSchema(),
422429
subscriptionManager,
423430
subscriptions: {
@@ -454,6 +461,7 @@ describe('Server', () => {
454461
describe('message phase', () => {
455462
const server = new Server({
456463
connectionManager,
464+
eventProcessor: new MemoryEventProcessor(),
457465
schema: createSchema(),
458466
subscriptionManager,
459467
});
@@ -544,6 +552,7 @@ describe('Server', () => {
544552
const onConnect = jest.fn().mockResolvedValueOnce({ key: 'value1' });
545553
const handlerWithOnConnect = new Server({
546554
connectionManager,
555+
eventProcessor: new MemoryEventProcessor(),
547556
schema: createSchema(),
548557
subscriptionManager,
549558
subscriptions: {
@@ -591,6 +600,7 @@ describe('Server', () => {
591600
const contextBuilder = jest.fn();
592601
const handlerWithContext = new Server({
593602
connectionManager,
603+
eventProcessor: new MemoryEventProcessor(),
594604
context: contextBuilder,
595605
schema: createSchema(),
596606
subscriptionManager,
@@ -642,6 +652,7 @@ describe('Server', () => {
642652
const onConnect = jest.fn().mockResolvedValueOnce(false);
643653
const handlerWithOnConnect = new Server({
644654
connectionManager,
655+
eventProcessor: new MemoryEventProcessor(),
645656
schema: createSchema(),
646657
subscriptionManager,
647658
subscriptions: {
@@ -701,6 +712,7 @@ describe('Server', () => {
701712
it('returns http 401 on not initialized connection operation', async () => {
702713
const handlerWithTimeout = new Server({
703714
connectionManager,
715+
eventProcessor: new MemoryEventProcessor(),
704716
schema: createSchema(),
705717
subscriptionManager,
706718
subscriptions: {
@@ -759,6 +771,7 @@ describe('Server', () => {
759771
const onOperationComplete = jest.fn();
760772
const handlerWithOnOperationComplete = new Server({
761773
connectionManager,
774+
eventProcessor: new MemoryEventProcessor(),
762775
schema: createSchema(),
763776
subscriptionManager,
764777
subscriptions: {
@@ -883,6 +896,7 @@ describe('Server', () => {
883896
}));
884897
const handlerWithOnOperation = new Server({
885898
connectionManager,
899+
eventProcessor: new MemoryEventProcessor(),
886900
schema: createSchema(),
887901
subscriptionManager,
888902
subscriptions: {
@@ -941,6 +955,7 @@ describe('Server', () => {
941955
const onOperationComplete = jest.fn();
942956
const handlerWithOnOperation = new Server({
943957
connectionManager,
958+
eventProcessor: new MemoryEventProcessor(),
944959
schema: createSchema(),
945960
subscriptionManager,
946961
subscriptions: {

0 commit comments

Comments
 (0)