budibase/packages/server/src/db/dynamoClient.ts

148 lines
3.2 KiB
TypeScript

import merge from "lodash/merge"
import env from "../environment"
export const AWS_REGION = env.AWS_REGION ? env.AWS_REGION : "eu-west-1"
const TableInfo = {
API_KEYS: {
name: "beta-api-key-table",
primary: "pk",
},
USERS: {
name: "prod-budi-table",
primary: "pk",
sort: "sk",
},
}
let docClient: any = null
type GetOpts = {
primary: string
sort?: string
otherProps?: any
}
type UpdateOpts = {
primary: string
sort?: string
expression?: string
condition?: string
names?: string[]
values?: any[]
exists?: boolean
otherProps?: any
}
type PutOpts = {
item: any
otherProps?: any
}
class Table {
_name: string
_primary: string
_sort?: string
constructor(tableInfo: { name: string; primary: string; sort?: string }) {
if (!tableInfo.name || !tableInfo.primary) {
throw "Table info must specify a name and a primary key"
}
this._name = tableInfo.name
this._primary = tableInfo.primary
this._sort = tableInfo.sort
}
async get({ primary, sort, otherProps }: GetOpts) {
let params = {
TableName: this._name,
Key: {
[this._primary]: primary,
},
}
if (this._sort && sort) {
params.Key[this._sort] = sort
}
if (otherProps) {
params = merge(params, otherProps)
}
let response = await docClient.get(params).promise()
return response.Item
}
async update({
primary,
sort,
expression,
condition,
names,
values,
exists,
otherProps,
}: UpdateOpts) {
let params: any = {
TableName: this._name,
Key: {
[this._primary]: primary,
},
ExpressionAttributeNames: names,
ExpressionAttributeValues: values,
UpdateExpression: expression,
}
if (condition) {
params.ConditionExpression = condition
}
if (this._sort && sort) {
params.Key[this._sort] = sort
}
if (exists) {
params.ExpressionAttributeNames["#PRIMARY"] = this._primary
if (params.ConditionExpression) {
params.ConditionExpression += " AND "
}
params.ConditionExpression += "attribute_exists(#PRIMARY)"
}
if (otherProps) {
params = merge(params, otherProps)
}
return docClient.update(params).promise()
}
async put({ item, otherProps }: PutOpts) {
if (
item[this._primary] == null ||
(this._sort && item[this._sort] == null)
) {
throw "Cannot put item without primary and sort key (if required)"
}
let params = {
TableName: this._name,
Item: item,
}
if (otherProps) {
params = merge(params, otherProps)
}
return docClient.put(params).promise()
}
}
export function init(endpoint: string) {
let AWS = require("aws-sdk")
let docClientParams: any = {
correctClockSkew: true,
region: AWS_REGION,
}
if (endpoint) {
docClientParams.endpoint = endpoint
} else if (env.DYNAMO_ENDPOINT) {
docClientParams.endpoint = env.DYNAMO_ENDPOINT
}
docClient = new AWS.DynamoDB.DocumentClient(docClientParams)
}
if (!env.isProd() && !env.isJest()) {
env._set("AWS_ACCESS_KEY_ID", "KEY_ID")
env._set("AWS_SECRET_ACCESS_KEY", "SECRET_KEY")
init("http://localhost:8333")
}