Last active
March 27, 2023 07:18
-
-
Save andrestone/278ef74b3f2775a4d13abc472f3ea0b2 to your computer and use it in GitHub Desktop.
`create` with `SetAttribute` with no client results in `DynamoDBSet` being passed as param.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as AWS from "@aws-sdk/client-dynamodb"; | |
import { Entity, Service } from "../../"; | |
const table = "your_table_name"; | |
export const configuration = { | |
endpoint: "http://localhost:8000", | |
region: "us-east-1" | |
}; | |
const client = new AWS.DynamoDB(configuration); | |
const dynamodb = client; | |
const definition = { | |
"KeySchema":[ | |
{ | |
"AttributeName":"pk", | |
"KeyType":"HASH" | |
}, | |
{ | |
"AttributeName":"sk", | |
"KeyType":"RANGE" | |
} | |
], | |
"AttributeDefinitions":[ | |
{ | |
"AttributeName":"pk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"sk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"gsi1pk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"gsi1sk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"gsi2pk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"gsi2sk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"gsi3pk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"gsi3sk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"gsi4pk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"gsi4sk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"gsi5pk", | |
"AttributeType":"S" | |
}, | |
{ | |
"AttributeName":"gsi5sk", | |
"AttributeType":"S" | |
} | |
], | |
"GlobalSecondaryIndexes":[ | |
{ | |
"IndexName":"gsi1pk-gsi1sk-index", | |
"KeySchema":[ | |
{ | |
"AttributeName":"gsi1pk", | |
"KeyType":"HASH" | |
}, | |
{ | |
"AttributeName":"gsi1sk", | |
"KeyType":"RANGE" | |
} | |
], | |
"Projection":{ | |
"ProjectionType":"ALL" | |
} | |
}, | |
{ | |
"IndexName":"gsi2pk-gsi2sk-index", | |
"KeySchema":[ | |
{ | |
"AttributeName":"gsi2pk", | |
"KeyType":"HASH" | |
}, | |
{ | |
"AttributeName":"gsi2sk", | |
"KeyType":"RANGE" | |
} | |
], | |
"Projection":{ | |
"ProjectionType":"ALL" | |
} | |
}, | |
{ | |
"IndexName":"gsi3pk-gsi3sk-index", | |
"KeySchema":[ | |
{ | |
"AttributeName":"gsi3pk", | |
"KeyType":"HASH" | |
}, | |
{ | |
"AttributeName":"gsi3sk", | |
"KeyType":"RANGE" | |
} | |
], | |
"Projection":{ | |
"ProjectionType":"ALL" | |
} | |
}, | |
{ | |
"IndexName":"gsi4pk-gsi4sk-index", | |
"KeySchema":[ | |
{ | |
"AttributeName":"gsi4pk", | |
"KeyType":"HASH" | |
}, | |
{ | |
"AttributeName":"gsi4sk", | |
"KeyType":"RANGE" | |
} | |
], | |
"Projection":{ | |
"ProjectionType":"ALL" | |
} | |
}, | |
{ | |
"IndexName":"gsi5pk-gsi5sk-index", | |
"KeySchema":[ | |
{ | |
"AttributeName":"gsi5pk", | |
"KeyType":"HASH" | |
}, | |
{ | |
"AttributeName":"gsi5sk", | |
"KeyType":"RANGE" | |
} | |
], | |
"Projection":{ | |
"ProjectionType":"ALL" | |
} | |
} | |
], | |
"BillingMode":"PAY_PER_REQUEST" | |
} | |
export function createTableManager() { | |
return { | |
async exists() { | |
let tables = await dynamodb.listTables({}); | |
return !!tables.TableNames?.includes(table); | |
}, | |
async drop() { | |
return dynamodb.deleteTable({TableName: table}); | |
}, | |
async create() { | |
return dynamodb.createTable({...definition, TableName: table}); | |
} | |
} | |
} | |
async function initializeTable() { | |
const tableManager = createTableManager(); | |
const exists = await tableManager.exists(); | |
if (exists) { | |
await tableManager.drop(); | |
} | |
await tableManager.create(); | |
} | |
/* Users Entity */ | |
const users = new Entity( | |
{ | |
model: { | |
entity: "user", | |
service: "taskapp", | |
version: "1" | |
}, | |
attributes: { | |
team: { | |
type: "string" | |
}, | |
user: { | |
type: "string" | |
}, | |
role: { | |
type: ["dev", "senior", "staff", "principal"] as const, | |
set: (title: string) => { | |
// save as index for comparison | |
return [ | |
"dev", | |
"senior", | |
"staff", | |
"principal" | |
].indexOf(title); | |
}, | |
get: (index: number) => { | |
return [ | |
"dev", | |
"senior", | |
"staff", | |
"principal" | |
][index] || "other"; | |
} | |
}, | |
manager: { | |
type: "set", | |
items: ["frank", "jane", "joe", "sally"] as const, | |
}, | |
firstName: { | |
type: "string" | |
}, | |
lastName: { | |
type: "string" | |
}, | |
fullName: { | |
type: "string", | |
// never set value to the database | |
set: () => undefined, | |
// calculate full name on retrieval | |
get: (_, {firstName, lastName}) => { | |
return `${firstName ?? ""} ${lastName ?? ""}`.trim(); | |
} | |
}, | |
profile: { | |
type: "map", | |
properties: { | |
photo: { | |
type: "string" | |
}, | |
bio: { | |
type: "string" | |
}, | |
location: { | |
type: "string" | |
} | |
} | |
}, | |
pinned: { | |
type: "any" | |
}, | |
following: { | |
type: "set", | |
items: "string" | |
}, | |
followers: { | |
type: "set", | |
items: "string" | |
}, | |
createdAt: { | |
type: "number", | |
default: () => Date.now(), | |
readOnly: true | |
}, | |
updatedAt: { | |
type: "number", | |
watch: "*", | |
set: () => Date.now(), | |
readOnly: true | |
} | |
}, | |
indexes: { | |
members: { | |
collection: "organization", | |
pk: { | |
composite: ["team"], | |
field: "pk" | |
}, | |
sk: { | |
composite: ["user"], | |
field: "sk" | |
} | |
}, | |
user: { | |
collection: "assignments", | |
index: "gsi1pk-gsi1sk-index", | |
pk: { | |
composite: ["user"], | |
field: "gsi1pk" | |
}, | |
sk: { | |
field: "gsi1sk", | |
composite: [] | |
} | |
} | |
} | |
}, | |
{ table } | |
); | |
new Service({ users }, { table, client, }); | |
/* Write queries to generate parameters on the right */ | |
const run = async () => { | |
await initializeTable(); | |
// `create` is like `put` except it uses "attribute_not_exists" | |
// to ensure you do not overwrite a record that already exists | |
users.create({ | |
team: "purple", | |
user: "t.walch", | |
role: "senior", | |
lastName: "walch", | |
firstName: "tyler", | |
manager: ["jane", "frank"], // This fails if Entity is instantiated without a client | |
profile: { | |
bio: "makes things", | |
photo: "selfie.jpg", | |
location: "atlanta" | |
}, | |
// interact with DynamoDB sets like arrays | |
following: ["d.purdy"] | |
}).go(); | |
}; | |
run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment