Skip to content

Instantly share code, notes, and snippets.

@cyberwombat
Created August 4, 2021 17:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cyberwombat/d33d31caa455ce51101278e394d3c8a0 to your computer and use it in GitHub Desktop.
Save cyberwombat/d33d31caa455ce51101278e394d3c8a0 to your computer and use it in GitHub Desktop.
import merge from 'deepmerge'
import {
DispatchAttributes,
WorkflowDefinition,
WorkflowModel
} from 'typings/workflow'
import { ActionEvent } from 'typings/lambda'
import {
APIGatewayProxyWithCognitoAuthorizerEvent,
AttributeValue,
Context,
CustomMessageAdminCreateUserTriggerEvent,
CustomMessageForgotPasswordTriggerEvent,
CustomMessageSignUpTriggerEvent,
CustomMessageUpdateUserAttributeTriggerEvent,
DynamoDBStreamEvent,
PostConfirmationConfirmSignUpTriggerEvent,
PreSignUpEmailTriggerEvent,
S3Event
} from 'aws-lambda'
import { generateId } from 'lib/utils/uidUtils'
import {
ActionContext,
ActionResponseStatus,
ActionType
} from 'typings/actions'
import { CollectionModel } from 'typings/collection'
import { deepMerge } from 'lib/utils/primitiveUtils'
import { ViewModel } from 'typings/view'
import {
InsightInterval,
InsightModel,
InsightQueryData
} from 'typings/insight'
import { ItemModel } from 'typings/item'
import { getTimestamp, getTimeToLive } from 'lib/utils/dateUtils'
import {
DynamoDBImage,
DynamoDBStreamEventType,
DynamoDBStreamViewType,
DynamoDBTable,
PartitionKeys
} from 'typings/dynamo'
import { seedDynamoDBTable } from './dynamoDBMockService'
import { ServiceModel } from 'typings/service'
import { AccountModel } from 'typings/account'
import { AccessModel, UserPermission } from 'typings/access'
import { ParameterModel } from 'typings/parameter'
import { PackageModel, PackageScope } from 'typings/package'
import { ModuleModel, ModuleScope } from 'typings/module'
import { StackUpsertInput } from 'typings/stack'
import { getConfig } from 'src/lib/utils/configUtils'
import { LogModel } from 'typings/log'
import { SocketModel } from 'typings/socket'
import { ThrottleModel } from 'typings/throttle'
import { ObjectLiteral } from 'typings/common'
import { SQSTaskDispatcherEvent } from 'typings/sqs'
import { marshallRecord } from 'lib/aws/dynamoDBService'
import { EventHandlerPayload } from 'typings/events'
type AwsLambdaContextMock = (props?: Record<keyof Context, any>) => Context
export const genericLabel = 'The label'
export const genericSummary = 'The summary'
export const genericDescription =
'Quis magna pariatur laboris cupidatat elit ut do nisi minim dolor labore nostrud aliqua.'
export const genericWorkflowDefinition: WorkflowDefinition = {
startStep: {
type: 'start',
description: 'Start workflow',
parameters: {
next: 'echoStep'
}
},
echoStep: {
type: 'echo',
description: 'Return to sender',
parameters: {
payload: '$.payload.foo',
result: '$'
}
}
}
// Create a new item entry
export const generateInsightModel = async (
payload?: Partial<InsightModel>
): Promise<InsightModel> => {
const model: InsightModel = {
accountId: generateId(),
collectionId: generateId(),
queries: {},
...payload
}
await seedDynamoDBTable<InsightModel>(DynamoDBTable.INSIGHT, [model])
return model
}
// Create a new item entry
export const generateItemModel = async (
payload?: Partial<ItemModel>
): Promise<ItemModel> => {
const model: ItemModel = {
accountId: generateId(),
collectionId: generateId(),
itemId: generateId(),
createdAt: getTimestamp(),
updatedAt: getTimestamp(),
data: {},
...payload
}
await seedDynamoDBTable<ItemModel>(DynamoDBTable.ITEM, [model])
return model
}
// Create a new collection entry
export const generateCollectionModel = async (
payload?: Partial<CollectionModel>
): Promise<CollectionModel> => {
const model: CollectionModel = {
accountId: generateId(),
collectionId: generateId(),
serviceId: generateId(),
createdAt: getTimestamp(),
updatedAt: getTimestamp(),
label: genericLabel,
summary: genericSummary,
options: {},
mapping: {},
triggers: {},
queries: {},
...payload
}
await seedDynamoDBTable<CollectionModel>(DynamoDBTable.COLLECTION, [model])
return model
}
// Create a new workflow entry
export const generateWorkflowModel = async (
payload?: Partial<WorkflowModel>
): Promise<WorkflowModel> => {
const model: WorkflowModel = {
accountId: generateId(),
workflowId: generateId(),
serviceId: generateId(),
createdAt: getTimestamp(),
updatedAt: getTimestamp(),
label: genericLabel,
summary: genericSummary,
definition: {},
...payload
}
await seedDynamoDBTable<WorkflowModel>(DynamoDBTable.WORKFLOW, [model])
return model
}
// Create a new view entry
export const generateViewModel = async (
payload?: Partial<ViewModel>
): Promise<ViewModel> => {
const model: ViewModel = {
accountId: generateId(),
viewId: generateId(),
serviceId: generateId(),
createdAt: getTimestamp(),
updatedAt: getTimestamp(),
label: genericLabel,
summary: genericSummary,
...payload
}
await seedDynamoDBTable<ViewModel>(DynamoDBTable.VIEW, [model])
return model
}
// Create a new service entry
export const generateServiceModel = async (
payload?: Partial<ServiceModel>
): Promise<ServiceModel> => {
const model: ServiceModel = {
accountId: generateId(),
serviceId: generateId(),
createdAt: getTimestamp(),
updatedAt: getTimestamp(),
label: genericLabel,
summary: genericSummary,
description: genericDescription,
settings: {},
domain: `foo.${getConfig('serviceDomain')}`,
...payload
}
await seedDynamoDBTable<ServiceModel>(DynamoDBTable.SERVICE, [model])
return model
}
// Create a new web socket connection entry
export const generateSocketModel = async (
payload?: Partial<SocketModel>
): Promise<SocketModel> => {
const model: SocketModel = {
connectionId: generateId(),
topicId: generateId(),
timeToLive: getTimeToLive(1000),
...payload
}
await seedDynamoDBTable<SocketModel>(DynamoDBTable.SOCKET, [model])
return model
}
// Create a new throtte entry
export const generateThrottleModel = async (
payload?: Partial<ThrottleModel>
): Promise<ThrottleModel> => {
const model: ThrottleModel = {
taskId: generateId(),
createdAt: getTimestamp(),
timeToLive: getTimeToLive(1000),
...payload
}
await seedDynamoDBTable<ThrottleModel>(DynamoDBTable.THROTTLE, [model])
return model
}
// Create a new log entry
export const generateLogModel = async (
payload?: Partial<LogModel>
): Promise<LogModel> => {
const model: LogModel = {
accountId: generateId(),
serviceId: generateId(),
processId: generateId(),
callerId: generateId(),
actionId: generateId(),
workflowId: generateId(),
logId: generateId(),
status: ActionResponseStatus.SUCCESS,
context: generateActionContext(),
result: { foo: 'bar' },
name: 'someAction',
runtime: 2,
execution: 1,
type: ActionType.ECHO,
triggeredAt: getTimestamp(),
timeToLive: getTimeToLive(10000),
watch: false,
...payload
}
await seedDynamoDBTable<LogModel>(DynamoDBTable.LOG, [model])
return model
}
// Create a new access entry
export const generateAccessModel = async (
payload?: Partial<AccessModel>
): Promise<AccessModel> => {
const model: AccessModel = {
accountId: generateId(),
userId: generateId(),
permission: UserPermission.ADMIN,
createdAt: getTimestamp(),
updatedAt: getTimestamp(),
...payload
}
await seedDynamoDBTable<AccessModel>(DynamoDBTable.ACCESS, [model])
return model
}
// Create a new account entry
export const generateAccountModel = async (
payload?: Partial<AccountModel>
): Promise<AccountModel> => {
const model: AccountModel = {
accountId: generateId(),
createdAt: getTimestamp(),
updatedAt: getTimestamp(),
label: genericLabel,
isActive: true,
usage: {
storage: {},
runtime: {},
request: {}
},
...payload
}
await seedDynamoDBTable<AccountModel>(DynamoDBTable.ACCOUNT, [model])
return model
}
// Create a new parameter entry
export const generateParameterModel = async (
payload?: Partial<ParameterModel>
): Promise<ParameterModel> => {
const model: ParameterModel = {
accountId: generateId(),
parameterId: generateId(),
createdAt: getTimestamp(),
updatedAt: getTimestamp(),
key: 'secret',
value: 'password',
summary: 'A secret',
...payload
}
await seedDynamoDBTable<ParameterModel>(DynamoDBTable.PARAMETER, [model])
return model
}
// Create a new package entry
export const generatePackageModel = async (
payload?: Partial<PackageModel>
): Promise<PackageModel> => {
const model: PackageModel = {
accountId: generateId(),
packageId: generateId(),
createdAt: getTimestamp(),
updatedAt: getTimestamp(),
label: genericLabel,
summary: genericSummary,
description: genericDescription,
stack: generateStack(),
scope: PackageScope.PUBLIC,
meta: {},
...payload
}
await seedDynamoDBTable<PackageModel>(DynamoDBTable.PACKAGE, [model])
return model
}
// Create a new moddule entry
export const generateModuleModel = async (
payload?: Partial<ModuleModel>
): Promise<ModuleModel> => {
const model: ModuleModel = {
accountId: generateId(),
moduleId: generateId(),
createdAt: getTimestamp(),
updatedAt: getTimestamp(),
deployedAt: getTimestamp(),
scope: ModuleScope.PUBLIC,
label: genericLabel,
summary: genericSummary,
description: genericDescription,
options: {},
events: {},
hash: '123',
repository: 'foo/bar',
meta: {},
...payload
}
await seedDynamoDBTable<ModuleModel>(DynamoDBTable.MODULE, [model])
return model
}
export const generateStack = (
payload: Partial<StackUpsertInput> = {}
): StackUpsertInput => {
const stack: StackUpsertInput = {
service: {
id: 'myService',
data: {}
},
collections: [],
views: [],
workflows: []
}
return { ...stack, ...payload }
}
// Action context
export const generateActionContext = (
props: Partial<ActionContext> = {}
): ActionContext => {
const defaults: ActionContext = {
payload: {},
query: {},
loops: [],
headers: {},
parameters: {},
config: {
accountId: generateId(),
processId: generateId(),
workflowId: generateId(),
serviceId: generateId()
}
}
return merge(defaults, props)
}
// Generic AWS lambda context
export const generateLambdaContext: AwsLambdaContextMock = (
props?: Record<keyof Context, any>
): Context => ({
callbackWaitsForEmptyEventLoop: false,
functionName: 'viewer-request',
functionVersion: '1234',
invokedFunctionArn: 'fakearn',
memoryLimitInMB: '5000',
awsRequestId: '1234',
logGroupName: 'groupname',
logStreamName: 'streamname',
identity: {
cognitoIdentityId: '12345',
cognitoIdentityPoolId: '45678'
},
clientContext: {
client: {
installationId: '123456',
appTitle: 'app',
appVersionName: 'v2',
appVersionCode: '000',
appPackageName: 'pkg'
},
Custom: { custom: '12345' },
env: {
platformVersion: '12345',
platform: '12345',
make: '12345',
model: '12345',
locale: 'de'
}
},
getRemainingTimeInMillis: () => 500,
done: () => {
return
},
fail: () => {
return
},
succeed: () => {
return
},
...props
})
// This trigger is invoked when admin creates a user
export const generateCognitoCustomMessageAdminCreateUserTriggerEvent =
(): CustomMessageAdminCreateUserTriggerEvent => ({
version: '1',
region: 'us-east-1',
userPoolId: 'us-east-1_bZJX2Eq4j',
userName: '7fea21dd-6bfd-443c-aae0-cf2a16172896',
callerContext: {
awsSdkVersion: 'aws-sdk-js-3.11.0',
clientId: 'CLIENT_ID_NOT_APPLICABLE'
},
triggerSource: 'CustomMessage_AdminCreateUser',
request: {
userAttributes: {
sub: '7fea21dd-6bfd-443c-aae0-cf2a16172896',
'cognito:user_status': 'FORCE_CHANGE_PASSWORD',
email_verified: 'true',
email: 'foo2sws4sqes@enradia.com'
},
codeParameter: '{####}',
//linkParameter: '{##Click Here##}', // Not in TS but we dont need it
usernameParameter: '{username}'
},
response: {
smsMessage: '',
emailMessage: '',
emailSubject: ''
}
})
// This trigger is invoked when user resets their email from dashboard
export const generateCognitoCustomMessageUpdateUserAttributeLambdaEvent =
(): CustomMessageUpdateUserAttributeTriggerEvent => ({
version: '1',
region: 'us-east-1',
userPoolId: 'us-east-1_fzb5VyAM7',
userName: '4fec8342-e5d7-48c1-9773-8938e33e1947',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: '79ljespnt8ackn4neofoujimjr'
},
triggerSource: 'CustomMessage_UpdateUserAttribute',
request: {
userAttributes: {
sub: '4fec8342-e5d7-48c1-9773-8938e33e1947',
'cognito:user_status': 'CONFIRMED',
email_verified: 'false',
email: 'darthvador@example.org'
},
codeParameter: '{####}',
usernameParameter: '4fec8342-e5d7-48c1-9773-8938e33e1947'
},
response: {
smsMessage: '',
emailMessage: '',
emailSubject: ''
}
})
// This trigger is invoked when user resets their password
export const generateCognitoPostConfirmationConfirmForgotPasswordLambdaEvent =
() => ({
version: '1',
region: 'us-east-1',
userPoolId: 'us-east-1_fzb5VyAM7',
userName: '4fec8342-e5d7-48c1-9773-8938e33e1947',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: '79ljespnt8ackn4neofoujimjr'
},
triggerSource: 'PostConfirmation_ConfirmForgotPassword',
request: {
userAttributes: {
sub: '4fec8342-e5d7-48c1-9773-8938e33e1947',
'cognito:email_alias': 'darthvador@example.org',
'cognito:user_status': 'CONFIRMED',
email_verified: 'true',
email: 'darthvador@example.org'
}
},
response: {}
})
// This trigger is invoked when user requests password reset - we use this to create custom confirm email
export const generateCognitoCustomMessageForgotPasswordLambdaEvent =
(): CustomMessageForgotPasswordTriggerEvent => ({
version: '1',
region: 'us-east-1',
userPoolId: 'us-east-1_fzb5VyAM7',
userName: '4fec8342-e5d7-48c1-9773-8938e33e1947',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: '79ljespnt8ackn4neofoujimjr'
},
triggerSource: 'CustomMessage_ForgotPassword',
request: {
userAttributes: {
sub: '4fec8342-e5d7-48c1-9773-8938e33e1947',
email_verified: 'true',
'cognito:user_status': 'CONFIRMED',
'cognito:email_alias': 'darthvador@example.org',
email: 'darthvador@example.org'
},
codeParameter: '{####}',
usernameParameter: ''
},
response: {
smsMessage: '',
emailMessage: '',
emailSubject: ''
}
})
// This trigger is invoked when user submits signup info - we use this to create custom confirm email
export const generateCognitoCustomMessageSignUpLambdaEvent =
(): CustomMessageSignUpTriggerEvent => ({
version: '1',
region: 'us-east-1',
userPoolId: 'us-east-1_fzb5VyAM7',
userName: '4fec8342-e5d7-48c1-9773-8938e33e1947',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: '79ljespnt8ackn4neofoujimjr'
},
triggerSource: 'CustomMessage_SignUp',
request: {
userAttributes: {
sub: '4fec8342-e5d7-48c1-9773-8938e33e1947',
'cognito:user_status': 'UNCONFIRMED',
email_verified: 'false',
'cognito:email_alias': 'darthvador@example.org',
email: 'darthvador@example.org'
},
codeParameter: '{####}',
usernameParameter: ''
},
response: {
smsMessage: '',
emailMessage: '',
emailSubject: ''
}
})
// This trigger is invoked after a user is confirmed, allowing you to send custom messages or to add custom logic, for example for analytics.
export const generateCognitoPostConfirmationConfirmSignUpLambdaEvent =
(): PostConfirmationConfirmSignUpTriggerEvent => ({
version: '1',
region: 'us-east-1',
userPoolId: 'us-east-1_fzb5VyAM7',
userName: 'fbcf1a78-f623-47ae-a6c5-04147507c548',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: '79ljespnt8ackn4neofoujimjr'
},
triggerSource: 'PostConfirmation_ConfirmSignUp',
request: {
userAttributes: {
sub: 'fbcf1a78-f623-47ae-a6c5-04147507c548',
'cognito:email_alias': 'darthvador@example.org',
'cognito:user_status': 'CONFIRMED',
email_verified: 'true',
email: 'darthvador@example.org'
}
},
response: {}
})
// This trigger is invoked when a user submits their information to sign up, allowing you to perform custom validation to accept or deny the sign up request.
export const generateCognitoPreSignUpSignUpLambdaEvent =
(): PreSignUpEmailTriggerEvent => ({
version: '1',
region: 'us-east-1',
userPoolId: 'us-east-1_fzb5VyAM7',
userName: '9132e892-976e-4e38-b6be-ab250adf90c5',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: '79ljespnt8ackn4neofoujimjr'
},
triggerSource: 'PreSignUp_SignUp',
request: {
userAttributes: {
email: 'darthvador@example.org'
},
validationData: {}
},
response: {
autoConfirmUser: false,
autoVerifyEmail: false,
autoVerifyPhone: false
}
})
// This trigger is invoked when a user submits their information to be authenticated, allowing you to perform custom validations to accept or deny the sign in request.
export const generateCognitoPreAuthenticationAuthenticationLambdaEvent =
() => ({
version: '1',
region: 'us-east-1',
userPoolId: 'us-east-1_fzb5VyAM7',
userName: 'fbcf1a78-f623-47ae-a6c5-04147507c548',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: '79ljespnt8ackn4neofoujimjr'
},
triggerSource: 'PreAuthentication_Authentication',
request: {
userAttributes: {
sub: 'fbcf1a78-f623-47ae-a6c5-04147507c548',
email_verified: 'true',
'cognito:user_status': 'CONFIRMED',
'cognito:email_alias': 'darthvador@example.org',
email: 'darthvador@example.org'
},
validationData: {}
},
response: {}
})
// This trigger is invoked after a user is authenticated, allowing you to add custom logic, for example for analytics.
export const generateCognitoPostAuthenticationAuthenticationLambdaEvent =
() => ({
version: '1',
region: 'us-east-1',
userPoolId: 'us-east-1_fzb5VyAM7',
userName: 'fbcf1a78-f623-47ae-a6c5-04147507c548',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: '79ljespnt8ackn4neofoujimjr'
},
triggerSource: 'PostAuthentication_Authentication',
request: {
userAttributes: {
sub: 'fbcf1a78-f623-47ae-a6c5-04147507c548',
email_verified: 'true',
'cognito:user_status': 'CONFIRMED',
'cognito:email_alias': 'darthvador@example.org',
email: 'darthvador@example.org'
},
newDeviceUsed: false
},
response: {}
})
// Event sent to lambda by EventBridge - doesn't do much :)
export const generateEventBridgeLambdaEvent = <
T extends EventHandlerPayload = never, // Require arg: https://stackoverflow.com/a/57683742/856498
U extends T = T
>(
data: U
): U => data
// Generate websocket disconnection event
export const generateWebSocketDisconnectionEvent = () => {
return {
headers: {
Host: 'localhost',
'X-Api-Key': '',
'x-restapi': ''
},
isBase64Encoded: false,
multiValueHeaders: {
Host: ['localhost'],
'X-Api-Key': [''],
'x-restapi': ['']
},
requestContext: {
apiId: 'private',
connectedAt: 1602170789631,
connectionId: 'ckg0z4d8b0000b1yp1uyngc5v',
domainName: 'localhost',
eventType: 'DISCONNECT',
extendedRequestId: 'ckg0z9dip0005b1yp1v1dhb76',
identity: {
accessKey: null,
accountId: null,
caller: null,
cognitoAuthenticationProvider: null,
cognitoAuthenticationType: null,
cognitoIdentityId: null,
cognitoIdentityPoolId: null,
principalOrgId: null,
sourceIp: '127.0.0.1',
user: null,
userAgent: null,
userArn: null
},
messageDirection: 'IN',
messageId: 'ckg0z9dip0006b1ypd1eea0zm',
requestId: 'ckg0z9dip0007b1yp33ywanf7',
requestTime: '08/Oct/2020:08:30:23 -0700',
requestTimeEpoch: 1602171023281,
routeKey: '$disconnect',
stage: 'local'
}
}
}
// Generate websocket message event
export const generateWebSocketMessageEvent = () => {
return {
body: '{ "action": "$trigger", "payload": "boom" }',
isBase64Encoded: false,
requestContext: {
apiId: 'private',
connectedAt: 1602172894830,
connectionId: 'ckg10dhm400009sypbx424rre',
domainName: 'localhost',
eventType: 'MESSAGE',
extendedRequestId: 'ckg10had000109sypc8kh9r0d',
identity: {
accessKey: null,
accountId: null,
caller: null,
cognitoAuthenticationProvider: null,
cognitoAuthenticationType: null,
cognitoIdentityId: null,
cognitoIdentityPoolId: null,
principalOrgId: null,
sourceIp: '127.0.0.1',
user: null,
userAgent: null,
userArn: null
},
messageDirection: 'IN',
messageId: 'ckg10had000119syp51v90a4z',
requestId: 'ckg10had100129sypg55lhlnd',
requestTime: '08/Oct/2020:09:04:32 -0700',
requestTimeEpoch: 1602173072052,
routeKey: '$trigger',
stage: 'local'
}
}
}
// Generate workflow definition
export const generateWorkflowDefinition = (
customDefiniiton?: WorkflowDefinition
): WorkflowDefinition => {
return deepMerge(genericWorkflowDefinition, customDefiniiton || {})
}
// Generate insight query data
export const generateInsightQueryData = (
customData?: Partial<InsightQueryData>
): InsightQueryData => {
return deepMerge(
{
[InsightInterval.YEAR]: [],
[InsightInterval.MONTH]: [],
[InsightInterval.WEEK]: [],
[InsightInterval.DAY]: [],
[InsightInterval.HOUR]: []
},
customData || {}
)
}
// export const generateWorkflowDefinition = (args = {}) => {
// const { triggers, steps, start = 'startStep' } = args
// const definition = {
// start: start,
// triggers: triggers || {
// events: {},
// webhook: {
// throttle: false,
// active: true,
// keys: [],
// origins: ['*']
// }
// },
// steps: steps || {
// [start]: {
// type: 'echo',
// description: 'Return to sender',
// parameters: {
// boom: 'boom'
// }
// }
// }
// }
// return definition
// }
// Generate action dispatch attributes
export const generateDispatchAttributes = (
args: Partial<DispatchAttributes> = {}
): DispatchAttributes => {
const { workflowId, callerId, processId, accountId, serviceId } = args
return {
workflowId: workflowId || generateId(),
callerId: callerId || generateId(),
processId: processId || generateId(),
serviceId: serviceId || generateId(),
accountId: accountId || '00000000-0000-0000-0000-00000000000'
}
}
// Generate action payload
export const generateActionPayload = (args: any = {}) => {
const { payload } = args
return {
stash: {},
payload: payload || { foo: 'bar' }
}
}
// Generate DynamoDB stream event
export const generateDynamoDBStreamEvent = ({
oldImage,
newImage,
partitionKeys,
eventName,
tableName,
streamViewType = DynamoDBStreamViewType.NEW_AND_OLD_IMAGES
}: {
oldImage?: DynamoDBImage
newImage?: DynamoDBImage
partitionKeys?: PartitionKeys
eventName: DynamoDBStreamEventType
tableName: DynamoDBTable
streamViewType?: DynamoDBStreamViewType
}) => {
const event: DynamoDBStreamEvent = {
Records: [
{
eventID: '1',
eventVersion: '1.0',
dynamodb: {
SequenceNumber: '111',
SizeBytes: 26,
StreamViewType: streamViewType
},
awsRegion: 'eu-east-1',
eventName,
eventSourceARN: `arn:aws:dynamodb:${getConfig('awsRegion')}:${getConfig(
'awsAccountId'
)}:table/${tableName}/stream/${getTimestamp()}/`,
eventSource: 'aws:dynamodb'
}
]
}
if (!event.Records || !event.Records[0].dynamodb) return
if (partitionKeys) {
event.Records[0].dynamodb.Keys = marshallRecord(partitionKeys) as {
[key: string]: AttributeValue // Cast as AWSLambda.AttributeValue instead of native aws type to resolve conflict
}
}
if (oldImage)
event.Records[0].dynamodb.OldImage = marshallRecord(oldImage) as {
[key: string]: AttributeValue
}
if (newImage)
event.Records[0].dynamodb.NewImage = marshallRecord(newImage) as {
[key: string]: AttributeValue
}
return event
}
// Generate API gateway proxy event
export const generateLambdaProxyEvent = (
event?: ObjectLiteral
): APIGatewayProxyWithCognitoAuthorizerEvent => {
const base: APIGatewayProxyWithCognitoAuthorizerEvent = {
body: 'eyJ0ZXN0IjoiYm9keSJ9',
resource: '/{proxy+}',
path: '/path/to/resource',
httpMethod: 'POST',
isBase64Encoded: true,
queryStringParameters: {
foo: 'bar'
},
multiValueQueryStringParameters: {
foo: ['bar']
},
pathParameters: {
proxy: '/path/to/resource'
},
stageVariables: {
baz: 'qux'
},
headers: {
Accept:
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'en-US,en;q=0.8',
'Cache-Control': 'max-age=0',
'CloudFront-Forwarded-Proto': 'https',
'CloudFront-Is-Desktop-Viewer': 'true',
'CloudFront-Is-Mobile-Viewer': 'false',
'CloudFront-Is-SmartTV-Viewer': 'false',
'CloudFront-Is-Tablet-Viewer': 'false',
'CloudFront-Viewer-Country': 'US',
Host: '1234567890.execute-api.us-east-1.amazonaws.com',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Custom User Agent String',
Via: '1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)',
'X-Amz-Cf-Id': 'cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==',
'X-Forwarded-For': '127.0.0.1, 127.0.0.2',
'X-Forwarded-Port': '443',
'X-Forwarded-Proto': 'https'
},
multiValueHeaders: {
Accept: [
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
],
'Accept-Encoding': ['gzip, deflate, sdch'],
'Accept-Language': ['en-US,en;q=0.8'],
'Cache-Control': ['max-age=0'],
'CloudFront-Forwarded-Proto': ['https'],
'CloudFront-Is-Desktop-Viewer': ['true'],
'CloudFront-Is-Mobile-Viewer': ['false'],
'CloudFront-Is-SmartTV-Viewer': ['false'],
'CloudFront-Is-Tablet-Viewer': ['false'],
'CloudFront-Viewer-Country': ['US'],
Host: ['0123456789.execute-api.us-east-1.amazonaws.com'],
'Upgrade-Insecure-Requests': ['1'],
'User-Agent': ['Custom User Agent String'],
Via: ['1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)'],
'X-Amz-Cf-Id': [
'cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA=='
],
'X-Forwarded-For': ['127.0.0.1, 127.0.0.2'],
'X-Forwarded-Port': ['443'],
'X-Forwarded-Proto': ['https']
},
requestContext: {
authorizer: {
claims: {}
},
accountId: '123456789012',
resourceId: '123456',
stage: 'prod',
requestId: 'c6af9ac6-7b61-11e6-9a41-93e8deadbeef',
requestTime: '09/Apr/2015:12:34:56 +0000',
requestTimeEpoch: 1428582896000,
identity: {
cognitoIdentityPoolId: null,
accountId: null,
cognitoIdentityId: null,
caller: null,
accessKey: null,
sourceIp: '127.0.0.1',
cognitoAuthenticationType: null,
cognitoAuthenticationProvider: null,
userArn: null,
userAgent: 'Custom User Agent String',
user: null,
apiKey: null,
apiKeyId: null,
principalOrgId: null,
clientCert: null
},
path: '/prod/path/to/resource',
resourcePath: '/{proxy+}',
httpMethod: 'POST',
apiId: '1234567890',
protocol: 'HTTP/1.1'
}
}
return deepMerge(base, event)
}
// Generate API gateway proxy event
export const generateLambdaWebSocketEvent = (
event?: ObjectLiteral
): APIGatewayProxyWithCognitoAuthorizerEvent => {
const base = generateLambdaProxyEvent({
requestContext: {
connectedAt: 1602170789631,
connectionId: 'ckg0z4d8b0000b1yp1uyngc5v',
domainName: 'localhost',
eventType: 'CONNECT'
}
})
return deepMerge(base, event)
}
// Event when calling an AppSync lambda source
export function generateAppSyncLambdaEvent(action: string, payload?: any): any {
return {
field: action,
arguments: payload
}
}
// Event passed from SQS provision handler to invoked tasks
export const generateLambdaSQSTaskInvokeEvent = (
event?: ObjectLiteral
): SQSTaskDispatcherEvent<unknown> => {
const base = {
actionParams: {},
receiptHandle: generateId()
}
return deepMerge(base, event)
}
// Eveent when S3 updated
export const generateLambdaS3PutEvent = (
name: string,
key: string
): S3Event => ({
Records: [
{
eventVersion: '2.0',
eventSource: 'aws:s3',
awsRegion: 'us-east-1',
eventTime: '1970-01-01T00:00:00.000Z',
eventName: 'ObjectCreated:Put',
userIdentity: {
principalId: 'EXAMPLE'
},
requestParameters: {
sourceIPAddress: '127.0.0.1'
},
responseElements: {
'x-amz-request-id': 'EXAMPLE123456789',
'x-amz-id-2':
'EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH'
},
s3: {
s3SchemaVersion: '1.0',
configurationId: 'testConfigRule',
bucket: {
name,
ownerIdentity: {
principalId: 'EXAMPLE'
},
arn: 'arn:aws:s3:::example-bucket'
},
object: {
key,
size: 1024,
eTag: '0123456789abcdef0123456789abcdef',
sequencer: '0A1B2C3D4E5F678901'
}
}
}
]
})
// Workflow action invoke
export const generateWorkflowActionLambdaInvokeEvent = (
workflow: WorkflowDefinition,
action: string,
context?: Partial<ActionContext>
): ActionEvent => {
const attributes = {
accountId: getConfig('mockId'),
workflowId: generateId(),
callerId: generateId(),
processId: generateId(),
serviceId: generateId()
}
return {
action,
workflow,
context: generateActionContext({ config: attributes, ...context }),
attributes
}
}
// Lambda SQS event - sent to recipient of queue event
export const generateSQSActionQueuedEvent = () => ({
Records: [
{
messageId: '9cf06c9b-e919-4ef9-8485-3d13c347a4d1',
receiptHandle: 'AQEBJRZxkQUWQYAwBMPpN4...rVCoU70HTdEVH4eKZXuPUVBw==',
body: '{"fooId":"222c74e3140-f132-11e9-aaae-4b1bd7694168"}',
attributes: {
ApproximateReceiveCount: '1',
SentTimestamp: '1530189332727',
SenderId: 'AROAI62MWIO3S4UBJVPVG:sqs-flooder',
ApproximateFirstReceiveTimestamp: '1530189332728'
},
messageAttributes: {
someId: {
Type: 'String',
Value: 'fb6a1900-acc5-11e9-8742-0d36cbe54355'
}
},
md5OfBody: '7ce3453347fd9bd30281384c304a1f9d',
eventSource: 'aws:sqs',
eventSourceARN: 'arn:aws:sqs:us-east-1:XXXXXXXX:test-sqs-trigger-queue',
awsRegion: 'us-east-1'
}
]
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment