diff --git a/bun.lockb b/bun.lockb index 44db4f8..3e694fd 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/packages/doorman-api/.env.example b/packages/doorman-api/.env.example index 7971b45..b88411b 100644 --- a/packages/doorman-api/.env.example +++ b/packages/doorman-api/.env.example @@ -5,6 +5,7 @@ AUTH_TOKEN= # aws stuff AWS_ACCESS_KEY= AWS_SECRET_ACCESS_KEY= +# AWS_ENDPOINT for local dev # discord notifs DISCORD_BOT_TOKEN= diff --git a/packages/doorman-api/package.json b/packages/doorman-api/package.json index df280a5..ab42150 100644 --- a/packages/doorman-api/package.json +++ b/packages/doorman-api/package.json @@ -8,6 +8,8 @@ "start-twilio": "twilio-run --load-local-env --live --port 8080", "watch-build": "bun run --watch src/index.ts", "start": "concurrently \"bun run watch-build\" \"bun run start-twilio\"", + "local-db": "bun run --watch src/local/localDdb.ts", + "start:local-db": "concurrently \"bun run local-db\" \"bun run start\"", "build": "bun run src/index.ts", "deploy": "twilio-run promote --from=staging --to=prod --load-system-env --env .env.example", "deploy:staging": "twilio-run deploy --load-system-env --env .env.example --service-name doorman --environment=staging --override-existing-project" @@ -30,8 +32,9 @@ "zod_utilz": "^0.8.4" }, "devDependencies": { - "twilio-run": "^3.5.4", - "concurrently": "^9.1.2" + "concurrently": "^9.1.2", + "dynamodb-local": "^0.0.35", + "twilio-run": "^3.5.4" }, "engines": { "node": "22" diff --git a/packages/doorman-api/src/local/localDdb.ts b/packages/doorman-api/src/local/localDdb.ts new file mode 100644 index 0000000..34f0a9c --- /dev/null +++ b/packages/doorman-api/src/local/localDdb.ts @@ -0,0 +1,91 @@ +import { CreateTableCommand, DynamoDBClient, KeyType, PutItemCommand, ScalarAttributeType } from "@aws-sdk/client-dynamodb"; +import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb"; +import { DoorAlias, DoorAliasEntity, DoorAliasSchema, getDoorAliasID } from "../schema/DoorAlias"; +import { DoorConfig } from "../schema/DoorConfig"; + +import DynamoDbLocal from "dynamodb-local"; +import { sleep } from "bun"; + +console.log("starting local DDB"); + +const localDdb = await DynamoDbLocal.launch(5000, null, [], true, true); + +process.on("SIGINT", async code => { + console.log("exiting DDB local"); + await DynamoDbLocal.stopChild(localDdb); +}); + +// wait 5s so we are available +await sleep(5_000); + +// seed ddb +const client = new DynamoDBClient({ + endpoint: 'http://localhost:5000', +}); + +const tableName = "doorman"; + +const createTableCommand = new CreateTableCommand({ + TableName: tableName, + KeySchema: [ + { AttributeName: 'PK', KeyType: KeyType.HASH }, + { AttributeName: 'SK', KeyType: KeyType.RANGE } + ], + AttributeDefinitions: [ + { AttributeName: 'PK', AttributeType: ScalarAttributeType.S }, + { AttributeName: 'SK', AttributeType: ScalarAttributeType.S } + ], + ProvisionedThroughput: { + ReadCapacityUnits: 5, + WriteCapacityUnits: 5 + }, +}); + +try { + await client.send(createTableCommand); +} catch (e) { + console.error("failed creating table", e); +} + +const document = DynamoDBDocument.from(client, { + marshallOptions: { + removeUndefinedValues: true, + } +}); + +const testDoorBuzzer = "6133163433"; +const testDoorName = "test"; +const testDoorPin = "1234"; + +const doorAlias: DoorAlias = { + PK: testDoorBuzzer, + SK: "alias", + name: testDoorName, +}; + +const doorConfig: DoorConfig = { + PK: "door-test", + SK: "config", + buzzer: testDoorBuzzer, + pressKey: "4", + discordUsers: [], + fallbackNumbers: [], + pin: testDoorPin, + buzzerCode: testDoorPin, + timeout: 60, + greeting: "test door", +}; + +try { + await document.put({ + TableName: tableName, + Item: doorConfig, + }); + + await document.put({ + TableName: tableName, + Item: doorAlias, + }); +} catch (e) { + console.error("failed seeding table", e); +} diff --git a/packages/doorman-api/src/utils/ddb.ts b/packages/doorman-api/src/utils/ddb.ts index d23c970..b8d5854 100644 --- a/packages/doorman-api/src/utils/ddb.ts +++ b/packages/doorman-api/src/utils/ddb.ts @@ -3,8 +3,24 @@ import { DynaBridge } from "dynabridge"; import { DoorConfigEntity, EditDoorConfigEntity, OnboardDoorConfigEntity } from "../schema/DoorConfig"; import { DoorAliasEntity } from "../schema/DoorAlias"; import { LockStatusEntity } from "../schema/LockStatus"; +import { DynamoDBClientConfig } from "@aws-sdk/client-dynamodb"; export const createDynaBridgeClient = (context: TwilioContext) => { + let config: DynamoDBClientConfig = { + region: "us-east-1", + credentials: { + accessKeyId: context.AWS_ACCESS_KEY, + secretAccessKey: context.AWS_SECRET_ACCESS_KEY, + }, + }; + + // for local DDB + if (context.AWS_ENDPOINT) { + config = { + endpoint: context.AWS_ENDPOINT, + } + } + // register all entities here return new DynaBridge({ doorConfig: DoorConfigEntity, @@ -26,11 +42,5 @@ export const createDynaBridgeClient = (context: TwilioContext) => { ); return convertedObj; } - }, { - region: "us-east-1" , - credentials: { - accessKeyId: context.AWS_ACCESS_KEY, - secretAccessKey: context.AWS_SECRET_ACCESS_KEY, - }, - }); + }, config); };