testing dynabridge
Some checks failed
Build and push image for doorman-homeassistant / docker (push) Failing after 34s
Build and push image for doorman-homeassistant / deploy-gitainer (push) Has been skipped
Build and push Doorman UI / API / docker (push) Successful in 1m32s

This commit is contained in:
Martin Dimitrov 2025-05-31 13:58:39 -07:00
parent 899d33895a
commit 446942582c
3 changed files with 72 additions and 6 deletions

View File

@ -4,9 +4,10 @@
import { ServerlessEventObject, ServerlessFunctionSignature } from "@twilio-labs/serverless-runtime-types/types"; import { ServerlessEventObject, ServerlessFunctionSignature } from "@twilio-labs/serverless-runtime-types/types";
import { TwilioContext } from "../../../types/TwilioContext"; import { TwilioContext } from "../../../types/TwilioContext";
import { createDDBClient, ddbItemToJSON, getDoorAliasCommand, getDoorConfigCommand, getLockStatusCommand, isLockOpen } from "../../../utils/ddb"; import { createDDBClient, createDynaBridgeClient, ddbItemToJSON, getDoorAliasCommand, getDoorConfigCommand, getLockStatusCommand, isLockOpen } from "../../../utils/ddb";
import { DoorStatus } from "../../../types/DoorStatus"; import { DoorStatus } from "../../../types/DoorStatus";
import { DoorConfig } from "../../../types/DoorConfig"; import { DoorConfig } from "../../../types/DoorConfig";
import { DOOR_CONFIG_SK, getDoorConfigID } from "../../../schema/DoorConfig";
export interface InfoRequest extends ServerlessEventObject { export interface InfoRequest extends ServerlessEventObject {
door?: string; door?: string;
@ -38,6 +39,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequest> =
} }
const client = createDDBClient(context); const client = createDDBClient(context);
const db = createDynaBridgeClient(context);
if (buzzer) { if (buzzer) {
door = await client.send(getDoorAliasCommand(buzzer)) door = await client.send(getDoorAliasCommand(buzzer))
@ -54,9 +56,9 @@ export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequest> =
} }
if (door) { if (door) {
const config = await client.send(getDoorConfigCommand(door)); const config = await db.entities.doorConfig.findById(getDoorConfigID(door));
if (!config.Item) { if (!config) {
response response
.setStatusCode(404) .setStatusCode(404)
.appendHeader('Content-Type', 'application/json') .appendHeader('Content-Type', 'application/json')
@ -70,13 +72,14 @@ export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequest> =
.setBody({ .setBody({
buzzer, buzzer,
door, door,
fallbackNumbers: config.Item.fallbackNumbers.SS, fallbackNumbers: config.fallbackNumbers,
pressKey: config.Item.pressKey.S, pressKey: config.pressKey,
discordUsers: config.Item?.discordUsers?.SS || [], discordUsers: config.discordUsers || [],
}); });
} else { } else {
await client.send(getLockStatusCommand(door)) await client.send(getLockStatusCommand(door))
.then(async (lock) => { .then(async (lock) => {
const config = await client.send(getDoorConfigCommand(door));
const status = isLockOpen(lock) ? DoorStatus.OPEN: DoorStatus.CLOSED; const status = isLockOpen(lock) ? DoorStatus.OPEN: DoorStatus.CLOSED;
const doorConfig: DoorConfig = ddbItemToJSON<DoorConfig>(config); const doorConfig: DoorConfig = ddbItemToJSON<DoorConfig>(config);

View File

@ -0,0 +1,47 @@
import { z } from "zod";
import { DynaBridge, DynaBridgeEntity } from 'dynabridge';
export const DOOR_CONFIG_SK = "config";
export const EDIT_DOOR_CONFIG_SK = "config-update";
export const DoorConfigSchema = z.object({
// keys
PK: z.string().startsWith("door-", "Invalid door key"),
SK: z.literal(DOOR_CONFIG_SK).default(DOOR_CONFIG_SK),
buzzer: z.string(),
buzzerCode: z.string(),
discordUsers: z.array(z.string()),
fallbackNumbers: z.array(z.string()),
pin: z.string(),
pressKey: z.string(),
greeting: z.string(),
timeout: z.number(),
});
export const getDoorConfigID = (doorName: string): string[] => {
return ['door-' + doorName, DOOR_CONFIG_SK];
}
export const EditDoorConfigSchema = DoorConfigSchema.extend({
SK: z.literal(EDIT_DOOR_CONFIG_SK).default(EDIT_DOOR_CONFIG_SK),
approvalId: z.string(),
});
export const getEditDoorConfigID = (doorName: string): string[] => {
return getDoorConfigID(doorName).with(1, EDIT_DOOR_CONFIG_SK);
}
export type DoorConfig = z.infer<typeof DoorConfigSchema>;
export type EditDoorConfig = z.infer<typeof EditDoorConfigSchema>;
export const DoorConfigEntity: DynaBridgeEntity<DoorConfig> = {
tableName: "doorman",
id: ["PK", "SK"],
};
export const EditDoorConfigEntity: DynaBridgeEntity<EditDoorConfig> = {
tableName: "doorman",
id: ["PK", "SK"],
};

View File

@ -2,6 +2,8 @@ import { randomUUID } from "crypto";
import { DynamoDBClient, GetItemCommand, DeleteItemCommand, PutItemCommand, UpdateItemCommand, GetItemOutput } from "@aws-sdk/client-dynamodb"; import { DynamoDBClient, GetItemCommand, DeleteItemCommand, PutItemCommand, UpdateItemCommand, GetItemOutput } from "@aws-sdk/client-dynamodb";
import { TwilioContext } from "../types/TwilioContext"; import { TwilioContext } from "../types/TwilioContext";
import { DoorConfig } from "../types/DoorConfig"; import { DoorConfig } from "../types/DoorConfig";
import { DynaBridge } from "dynabridge";
import { DoorConfigEntity, EditDoorConfigEntity } from "../schema/DoorConfig";
export const createDDBClient = (context: TwilioContext) => { export const createDDBClient = (context: TwilioContext) => {
return new DynamoDBClient({ return new DynamoDBClient({
@ -13,6 +15,20 @@ export const createDDBClient = (context: TwilioContext) => {
}); });
}; };
export const createDynaBridgeClient = (context: TwilioContext) => {
// register all entities here
return new DynaBridge({
doorConfig: DoorConfigEntity,
editDoorConfig: EditDoorConfigEntity,
}, undefined, {
region: "us-east-1" ,
credentials: {
accessKeyId: context.AWS_ACCESS_KEY,
secretAccessKey: context.AWS_SECRET_ACCESS_KEY,
},
});
};
export const getLockStatusCommand = (door: string) => { export const getLockStatusCommand = (door: string) => {
return new GetItemCommand({ return new GetItemCommand({
TableName: "doorman", TableName: "doorman",