remove separate info response

This commit is contained in:
Martin Dimitrov 2025-10-24 17:43:27 -07:00
parent 4bbfdbd7ce
commit 6cc92a3ffb
5 changed files with 27 additions and 44 deletions

View File

@ -26,15 +26,11 @@ export const InfoRequestSchema = z.object({
export type InfoRequest = z.infer<typeof InfoRequestSchema>; export type InfoRequest = z.infer<typeof InfoRequestSchema>;
export type InfoRequestTwilio = ServerlessEventObject<InfoRequest, UserAgentHeader> & BaseEvent; export type InfoRequestTwilio = ServerlessEventObject<InfoRequest, UserAgentHeader> & BaseEvent;
export const InfoResponseClientSchema = DoorConfigSchema export const InfoResponseSchema = DoorConfigSchema
.omit({ PK: true, SK: true, pin: true }) .omit({ PK: true, SK: true, pin: true })
.extend({ door: z.string() }); .extend({ door: z.string(), status: z.nativeEnum(DoorStatus), id: z.string() });
export type InfoResponseClient = z.infer<typeof InfoResponseClientSchema>; export type InfoResponse = z.infer<typeof InfoResponseSchema>;
export const InfoResponseUISchema = InfoResponseClientSchema.extend({ id: z.string(), status: z.nativeEnum(DoorStatus) });
export type InfoResponseUI = z.infer<typeof InfoResponseUISchema>;
export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequestTwilio> = withMetrics("info", async (context, event, callback, metricsRegistry) => { export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequestTwilio> = withMetrics("info", async (context, event, callback, metricsRegistry) => {
const response = new Twilio.Response(); const response = new Twilio.Response();
@ -66,29 +62,17 @@ export const handler: ServerlessFunctionSignature<TwilioContext, InfoRequestTwil
msg: "This buzzer is not registered", msg: "This buzzer is not registered",
}); });
} else { } else {
if (buzzer) { const lock = await db.entities.lockStatus.findById(getLockStatusID(door));
// respond to twilio CLIENT const status = isLockOpen(lock) ? DoorStatus.OPEN : DoorStatus.CLOSED;
const body: InfoResponseClient = InfoResponseClientSchema.parse({
...config,
buzzer,
door,
});
setResponseJson(response, 200, body); const body: InfoResponse = InfoResponseSchema.parse({
} else { ...config,
const lock = await db.entities.lockStatus.findById(getLockStatusID(door)); id: door,
const status = isLockOpen(lock) ? DoorStatus.OPEN : DoorStatus.CLOSED; door,
status,
});
const body: InfoResponseUI = InfoResponseUISchema.parse({ setResponseJson(response, 200, body);
...config,
id: door,
door,
status,
})
// respond to UI
setResponseJson(response, 200, body);
}
} }
} }

View File

@ -1,7 +1,7 @@
import { describe, test, expect } from "bun:test"; import { describe, test, expect } from "bun:test";
import { buzzerUrl, buzzerNumber, baseUrl, doorName, key } from "./testCommon"; import { buzzerUrl, buzzerNumber, baseUrl, doorName, key } from "./testCommon";
import { DoorStatus } from "../src/types/DoorStatus"; import { DoorStatus } from "../src/types/DoorStatus";
import { InfoResponseUI } from "../src/functions/api/door/info"; import { InfoResponse } from "../src/functions/api/door/info";
import { ONBOARDING_DOOR_NAME, ONBOARDING_DOOR_PIN } from "../src/schema/DoorConfig"; import { ONBOARDING_DOOR_NAME, ONBOARDING_DOOR_PIN } from "../src/schema/DoorConfig";
import { StatusResponse } from "../src/functions/api/door/status"; import { StatusResponse } from "../src/functions/api/door/status";
@ -36,7 +36,7 @@ describe("buzzer client works", () => {
expect(buzzerActivatedResp).not.toContain("fail fast callback"); expect(buzzerActivatedResp).not.toContain("fail fast callback");
// door should now be closed // door should now be closed
const infoResp = await fetch(baseUrl + `/api/door/info?door=${doorName}`).then(res => res.json()) as InfoResponseUI; const infoResp = await fetch(baseUrl + `/api/door/info?door=${doorName}`).then(res => res.json()) as InfoResponse;
expect(infoResp.status).toBe(DoorStatus.CLOSED); expect(infoResp.status).toBe(DoorStatus.CLOSED);
}); });
}); });
@ -48,7 +48,7 @@ describe("onboardingflag door should exist", () => {
const authResp = await fetch(baseUrl + `/api/door/info?door=${ONBOARDING_DOOR_NAME}`); const authResp = await fetch(baseUrl + `/api/door/info?door=${ONBOARDING_DOOR_NAME}`);
expect(authResp.status).toBe(200); expect(authResp.status).toBe(200);
const door = (await authResp.json()) as InfoResponseUI; const door = (await authResp.json()) as InfoResponse;
expect(door.timeout).toBe(15 * 60); expect(door.timeout).toBe(15 * 60);
// this may be flaky, it would fail when a user is onboarding and we are deploying // this may be flaky, it would fail when a user is onboarding and we are deploying
@ -59,11 +59,11 @@ describe("onboardingflag door should exist", () => {
let authResp = await fetch(baseUrl + `/api/door/auth?door=${ONBOARDING_DOOR_NAME}&key=${ONBOARDING_DOOR_PIN}`); let authResp = await fetch(baseUrl + `/api/door/auth?door=${ONBOARDING_DOOR_NAME}&key=${ONBOARDING_DOOR_PIN}`);
expect(authResp.status).toBe(200); expect(authResp.status).toBe(200);
let statusResp = await fetch(baseUrl + `/api/door/info?door=${ONBOARDING_DOOR_NAME}`).then(res => res.json()) as InfoResponseUI; let statusResp = await fetch(baseUrl + `/api/door/info?door=${ONBOARDING_DOOR_NAME}`).then(res => res.json()) as InfoResponse;
expect(statusResp.status).toBe(DoorStatus.OPEN); expect(statusResp.status).toBe(DoorStatus.OPEN);
// open again // open again
statusResp = await fetch(baseUrl + `/api/door/info?door=${ONBOARDING_DOOR_NAME}`).then(res => res.json()) as InfoResponseUI; statusResp = await fetch(baseUrl + `/api/door/info?door=${ONBOARDING_DOOR_NAME}`).then(res => res.json()) as InfoResponse;
expect(statusResp.status).toBe(DoorStatus.OPEN); expect(statusResp.status).toBe(DoorStatus.OPEN);
// close it // close it
@ -71,7 +71,7 @@ describe("onboardingflag door should exist", () => {
expect(authResp.status).toBe(200); expect(authResp.status).toBe(200);
// door should now be closed // door should now be closed
const infoResp = await fetch(baseUrl + `/api/door/info?door=${ONBOARDING_DOOR_NAME}`).then(res => res.json()) as InfoResponseUI; const infoResp = await fetch(baseUrl + `/api/door/info?door=${ONBOARDING_DOOR_NAME}`).then(res => res.json()) as InfoResponse;
expect(infoResp.status).toBe(DoorStatus.CLOSED); expect(infoResp.status).toBe(DoorStatus.CLOSED);
}) })
}); });

View File

@ -14,7 +14,7 @@ import { TwilioContext } from '../types/TwilioContext';
import VoiceResponse from 'twilio/lib/twiml/VoiceResponse'; import VoiceResponse from 'twilio/lib/twiml/VoiceResponse';
import { DoorStatus } from '../../../doorman-api/src/types/DoorStatus'; import { DoorStatus } from '../../../doorman-api/src/types/DoorStatus';
import { StatusResponse } from '../../../doorman-api/src/functions/api/door/status'; import { StatusResponse } from '../../../doorman-api/src/functions/api/door/status';
import { InfoResponseClient } from '../../../doorman-api/src/functions/api/door/info'; import { InfoResponse } from '../../../doorman-api/src/functions/api/door/info';
import { getMetricFromRegistry, withMetrics } from '../../../doorman-api/src/common/DoormanHandler'; import { getMetricFromRegistry, withMetrics } from '../../../doorman-api/src/common/DoormanHandler';
import { Counter, Summary } from 'prom-client'; import { Counter, Summary } from 'prom-client';
import { BuzzerActivatedMetrics, registerMetrics } from '../metrics/BuzzerActivatedMetrics'; import { BuzzerActivatedMetrics, registerMetrics } from '../metrics/BuzzerActivatedMetrics';
@ -27,7 +27,7 @@ export const handler: ServerlessFunctionSignature<TwilioContext, BuzzerDialEvent
let invokeId = `[${randomUUID()}]`; let invokeId = `[${randomUUID()}]`;
let configString = event.config; let configString = event.config;
let config: InfoResponseClient | undefined; let config: InfoResponse | undefined;
console.log(invokeId + " starting execution"); console.log(invokeId + " starting execution");
// get by api or parse it out from query // get by api or parse it out from query

View File

@ -1,17 +1,17 @@
import { register, Registry, Summary } from "prom-client"; import { register, Registry, Summary } from "prom-client";
import { InfoResponseClient, InfoResponseUI } from "../../../doorman-api/src/functions/api/door/info"; import { InfoResponse } from "../../../doorman-api/src/functions/api/door/info";
import { TwilioContext } from "../types/TwilioContext"; import { TwilioContext } from "../types/TwilioContext";
import { lambdaFastHttp } from "./LambdaUtils"; import { lambdaFastHttp } from "./LambdaUtils";
import { BuzzerActivatedMetrics } from "../metrics/BuzzerActivatedMetrics"; import { BuzzerActivatedMetrics } from "../metrics/BuzzerActivatedMetrics";
import { ONBOARDING_DOOR_NAME } from "../../../doorman-api/src/schema/DoorConfig"; import { ONBOARDING_DOOR_NAME } from "../../../doorman-api/src/schema/DoorConfig";
import { LogCallResponse } from "../../../doorman-api/src/functions/api/door/logCall"; import { LogCallResponse } from "../../../doorman-api/src/functions/api/door/logCall";
export async function getConfig(context: TwilioContext, buzzer: string): Promise<InfoResponseClient | undefined> { export async function getConfig(context: TwilioContext, buzzer: string): Promise<InfoResponse | undefined> {
return await fetch(context.DOORMAN_URL + `/api/door/info?buzzer=${buzzer}`) return await fetch(context.DOORMAN_URL + `/api/door/info?buzzer=${buzzer}`)
.then(res => res.json()) .then(res => res.json())
.catch(err => { .catch(err => {
return undefined; return undefined;
}) as InfoResponseClient; }) as InfoResponse;
} }
export async function tryLogCallerForOnboarding(context: TwilioContext, caller: string): Promise<LogCallResponse> { export async function tryLogCallerForOnboarding(context: TwilioContext, caller: string): Promise<LogCallResponse> {
@ -31,6 +31,6 @@ export async function notifyDiscord(context: TwilioContext, msg: string[], u: st
return res; return res;
} }
export async function notifyAllDiscord(context: TwilioContext, config: InfoResponseClient, msg: string, metricsRegistry: Registry, optionalJsonStr: string = "") { export async function notifyAllDiscord(context: TwilioContext, config: InfoResponse, msg: string, metricsRegistry: Registry, optionalJsonStr: string = "") {
return notifyDiscord(context, config.discordUsers.map(() => msg), config.discordUsers, config.discordUsers.map(() => optionalJsonStr), metricsRegistry); return notifyDiscord(context, config.discordUsers.map(() => msg), config.discordUsers, config.discordUsers.map(() => optionalJsonStr), metricsRegistry);
} }

View File

@ -1,7 +1,7 @@
import VoiceResponse from 'twilio/lib/twiml/VoiceResponse'; import VoiceResponse from 'twilio/lib/twiml/VoiceResponse';
import { InfoResponseClient } from '../../../doorman-api/src/functions/api/door/info'; import { InfoResponse } from '../../../doorman-api/src/functions/api/door/info';
export function doorOpenTwiml(config: InfoResponseClient): VoiceResponse { export function doorOpenTwiml(config: InfoResponse): VoiceResponse {
const twiml = new Twilio.twiml.VoiceResponse(); const twiml = new Twilio.twiml.VoiceResponse();
// play audio // play audio
@ -20,7 +20,7 @@ export function doorOpenTwiml(config: InfoResponseClient): VoiceResponse {
return twiml; return twiml;
} }
export function dialFallbackTwiml(config: InfoResponseClient): VoiceResponse { export function dialFallbackTwiml(config: InfoResponse): VoiceResponse {
const twiml = new Twilio.twiml.VoiceResponse(); const twiml = new Twilio.twiml.VoiceResponse();
let dial = twiml.dial({ let dial = twiml.dial({
@ -67,4 +67,3 @@ export function doorOnboardTwiml(otp: string): VoiceResponse {
// @ts-ignore // @ts-ignore
return twiml; return twiml;
} }