Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/alexa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"ask-sdk-core": "^2.11.0",
"ask-sdk-express-adapter": "^2.14.0",
"ask-sdk-model": "^1.36.1",
"aws-sdk": "^2.950.0",
"date-fns": "4.1.0",
"graphql": "^16.11.0",
"graphql-request": "^7.2.0",
Expand Down
5 changes: 4 additions & 1 deletion packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@
"test": "jest"
},
"dependencies": {
"@aws-sdk/client-dynamodb": "3.864.0",
"@aws-sdk/client-lambda": "3.864.0",
"@aws-sdk/lib-dynamodb": "3.864.0",
"@aws-sdk/util-dynamodb": "3.864.0",
"@graphql-tools/schema": "^10.0.25",
"@lara/api": "^1.0.0",
"apollo-server-lambda": "^3.13.0",
"aws-sdk": "^2.950.0",
"casual": "^1.6.2",
"cors": "^2.8.5",
"date-fns": "4.1.0",
Expand Down
14 changes: 6 additions & 8 deletions packages/backend/src/aws/lambda.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EmailPayload, PrintPayload } from '@lara/api'
import { Lambda } from 'aws-sdk'
import { Lambda } from '@aws-sdk/client-lambda'

const { IS_OFFLINE, PRINT_FUNCTION, EMAIL_FUNCTION } = process.env

Expand Down Expand Up @@ -31,11 +31,9 @@ type LambdaOptions = { functionName: 'email'; payload: EmailPayload } | { functi
* @param functionName Defines between print and email Lambda
*/
export const invokeLambda = async ({ functionName, payload }: LambdaOptions): Promise<void> => {
await lambda
.invoke({
FunctionName: functionNameMapping[functionName],
InvocationType: 'Event',
Payload: JSON.stringify(payload),
})
.promise()
await lambda.invoke({
FunctionName: functionNameMapping[functionName],
InvocationType: 'Event',
Payload: JSON.stringify(payload),
})
}
31 changes: 16 additions & 15 deletions packages/backend/src/aws/s3.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import { S3, Endpoint, AWSError } from 'aws-sdk'
import { PromiseResult } from 'aws-sdk/lib/request'
import { S3Client, PutObjectCommand, PutObjectCommandOutput } from '@aws-sdk/client-s3'

const { IS_OFFLINE, EXPORT_BUCKET } = process.env

if (!EXPORT_BUCKET) {
throw new Error("Missing env Var: 'EXPORT_BUCKET'")
}

const s3Client = new S3(
const s3Client = new S3Client(
IS_OFFLINE
? {
s3ForcePathStyle: true,
accessKeyId: 'S3RVER', // This specific key is required when working offline
secretAccessKey: 'S3RVER',
endpoint: new Endpoint('http://localhost:8181'),
forcePathStyle: true,
credentials: {
accessKeyId: 'S3RVER', // This specific key is required when working offline
secretAccessKey: 'S3RVER',
},
endpoint: 'http://localhost:8181',
}
: { region: 'eu-central-1' }
)

export const saveExport = (key: string, body: string): Promise<PromiseResult<S3.PutObjectOutput, AWSError>> => {
return s3Client
.putObject({
Bucket: EXPORT_BUCKET,
Key: key,
Body: body,
})
.promise()
export const saveExport = async (key: string, body: string): Promise<PutObjectCommandOutput> => {
const command = new PutObjectCommand({
Bucket: EXPORT_BUCKET,
Key: key,
Body: body,
})

return await s3Client.send(command)
}
22 changes: 16 additions & 6 deletions packages/backend/src/db/batch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DocumentClient } from 'aws-sdk/clients/dynamodb'
import { BatchWriteCommand, BatchWriteCommandInput } from '@aws-sdk/lib-dynamodb'

import { dbClient } from './ddb'

Expand All @@ -9,12 +9,22 @@ import { dbClient } from './ddb'
* @param items max. 25 request items
* @returns true if success
*/
export const batchWriteItem = async (items: DocumentClient.BatchWriteItemInput['RequestItems']): Promise<boolean> => {
const res = await dbClient().batchWrite({ RequestItems: items }).promise()
export const batchWriteItem = async (items: BatchWriteCommandInput['RequestItems']): Promise<boolean> => {
const client = dbClient()
try {
const res = await client.send(
new BatchWriteCommand({
RequestItems: items,
})
)

if (res.$response.error) {
if (res.UnprocessedItems && Object.keys(res.UnprocessedItems).length > 0) {
console.warn('Some items were unprocessed:', res.UnprocessedItems)
}

return true
} catch (err) {
console.error('Error batch writing to DB:', err)
throw new Error('Error batch writing to DB')
}

return true
}
13 changes: 7 additions & 6 deletions packages/backend/src/db/ddb.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DocumentClient } from 'aws-sdk/clients/dynamodb'
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'

const { IS_OFFLINE } = process.env

Expand All @@ -11,19 +12,19 @@ const params = IS_OFFLINE
}
: {}

let cacheClient: DocumentClient
let cachedClient: DynamoDBDocumentClient

/**
* Creates a new DB client or returns the
* already created client
* @returns The DB client
*/
export const dbClient = (): DocumentClient => {
if (!cacheClient) {
cacheClient = new DocumentClient(params)
export const dbClient = (): DynamoDBDocumentClient => {
if (!cachedClient) {
cachedClient = DynamoDBDocumentClient.from(new DynamoDBClient(params))
}

return cacheClient
return cachedClient
}

/**
Expand Down
20 changes: 13 additions & 7 deletions packages/backend/src/db/delete.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DocumentClient } from 'aws-sdk/clients/dynamodb'
import { DeleteCommand, DeleteCommandInput } from '@aws-sdk/lib-dynamodb'

import { dbClient } from './ddb'

Expand All @@ -9,12 +9,18 @@ import { dbClient } from './ddb'
* @param key Key of DDB item
* @returns true if success
*/
export const deleteItem = async (tableName: string, key: DocumentClient.Key): Promise<boolean> => {
const res = await dbClient().delete({ TableName: tableName, Key: key }).promise()

if (res.$response.error) {
export const deleteItem = async (tableName: string, key: DeleteCommandInput['Key']): Promise<boolean> => {
const client = dbClient()
try {
await client.send(
new DeleteCommand({
TableName: tableName,
Key: key,
})
)
return true
} catch (err) {
console.error('Error deleting item from DB:', err)
throw new Error('Error deleting item from DB')
}

return true
}
20 changes: 13 additions & 7 deletions packages/backend/src/db/get.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DocumentClient } from 'aws-sdk/clients/dynamodb'
import { GetCommand, GetCommandInput } from '@aws-sdk/lib-dynamodb'

import { dbClient } from './ddb'

Expand All @@ -9,12 +9,18 @@ import { dbClient } from './ddb'
* @param key Identifier of the DDB item
* @returns Item from DB
*/
export const getItem = async <T>(tablename: string, key: DocumentClient.Key): Promise<T | undefined> => {
const res = await dbClient().get({ TableName: tablename, Key: key }).promise()

if (res.$response.error || !res.Item) {
export const getItem = async <T>(tablename: string, key: GetCommandInput['Key']): Promise<T | undefined> => {
const client = dbClient()
try {
const res = await client.send(
new GetCommand({
TableName: tablename,
Key: key,
})
)
return res.Item as T | undefined
} catch (err) {
console.error('Error fetching item from DDB:', err)
return undefined
}

return res.Item as T
}
22 changes: 14 additions & 8 deletions packages/backend/src/db/put.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DocumentClient } from 'aws-sdk/clients/dynamodb'
import { PutCommand } from '@aws-sdk/lib-dynamodb'

import { dbClient } from './ddb'

Expand All @@ -9,12 +9,18 @@ import { dbClient } from './ddb'
* @param input DDB put options
* @returns The input if successfull
*/
export const putItem = async <T>(tableName: string, input: DocumentClient.PutItemInputAttributeMap): Promise<T> => {
const res = await dbClient().put({ TableName: tableName, Item: input }).promise()

if (res.$response.error) {
throw new Error('Error putting into DB')
export const putItem = async <T extends Record<string, unknown>>(tableName: string, input: T): Promise<T> => {
const client = dbClient()
try {
await client.send(
new PutCommand({
TableName: tableName,
Item: input,
})
)
return input
} catch (error) {
console.error('Error putting Item into DB', error)
throw new Error('Error putting Item into DB')
}

return input as T
}
20 changes: 11 additions & 9 deletions packages/backend/src/db/query.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DocumentClient } from 'aws-sdk/clients/dynamodb'
import { QueryCommand, QueryCommandInput } from '@aws-sdk/lib-dynamodb'

import { Keys } from '../utils/object'
import {
Expand All @@ -15,15 +15,17 @@ import {
* @param options DDB Query Options
* @returns Queried items
*/
const queryItems = async <T>(
tablename: string,
options: Omit<DocumentClient.QueryInput, 'TableName'>
): Promise<T[]> => {
const res = await dbClient()
.query({ ...options, TableName: tablename })
.promise()
const queryItems = async <T>(tablename: string, options: Omit<QueryCommandInput, 'TableName'>): Promise<T[]> => {
const client = dbClient()

const res = await client.send(
new QueryCommand({
TableName: tablename,
...options,
})
)

if (res.$response.error || !res.Items) {
if (!res.Items) {
return []
}

Expand Down
40 changes: 25 additions & 15 deletions packages/backend/src/db/scan.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DocumentClient } from 'aws-sdk/clients/dynamodb'
import { ScanCommand, ScanCommandInput } from '@aws-sdk/lib-dynamodb'

import { dbClient } from './ddb'

Expand All @@ -12,23 +12,33 @@ import { dbClient } from './ddb'
*/
export const scanItems = async <T>(
tablename: string,
additionalInput?: Omit<DocumentClient.ScanInput, 'TableName'>
additionalInput?: Omit<ScanCommandInput, 'TableName'>
): Promise<T[]> => {
const res = await dbClient()
.scan({ TableName: tablename, ...additionalInput })
.promise()
const client = dbClient()

if (res.$response.error || !res.Items) {
return []
}

// scan the database until 'LastEvaluatedKey' is empty
const paginatedResults = res.LastEvaluatedKey
? await scanItems<T>(tablename, {
try {
const res = await client.send(
new ScanCommand({
TableName: tablename,
...additionalInput,
ExclusiveStartKey: res.LastEvaluatedKey,
})
: []
)

if (!res.Items) {
return []
}

return [...paginatedResults, ...res.Items] as T[]
// scan the database until 'LastEvaluatedKey' is empty
const paginatedResults = res.LastEvaluatedKey
? await scanItems<T>(tablename, {
...additionalInput,
ExclusiveStartKey: res.LastEvaluatedKey,
})
: []

return [...paginatedResults, ...res.Items] as T[]
} catch (error) {
console.error('Error while scanning the DB:', error)
throw new Error('Error while scanning the DB:')
}
}
27 changes: 15 additions & 12 deletions packages/backend/src/db/update.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DocumentClient } from 'aws-sdk/clients/dynamodb'
import { UpdateCommand, UpdateCommandInput } from '@aws-sdk/lib-dynamodb'

import { Keys } from '../utils/object'
import {
Expand All @@ -15,19 +15,22 @@ import {
* @param input DDB input options
* @returns Boolean if sucess
*/
const updateItem = async (
tableName: string,
input: Omit<DocumentClient.UpdateItemInput, 'TableName'>
): Promise<boolean> => {
const res = await dbClient()
.update({ TableName: tableName, ...input })
.promise()

if (res.$response.error) {
const updateItem = async (tableName: string, input: Omit<UpdateCommandInput, 'TableName'>): Promise<boolean> => {
const client = dbClient()

try {
await client.send(
new UpdateCommand({
TableName: tableName,
...input,
})
)

return true
} catch (error) {
console.error('Error updating into DB:', error)
throw new Error('Error updating into DB')
}

return true
}

/**
Expand Down
Loading