Refactoring 2

This commit is contained in:
Darren Clarke 2024-04-30 11:39:16 +02:00
parent dd14dfe72e
commit e4b78ceec2
76 changed files with 870 additions and 734 deletions

View file

@ -0,0 +1,72 @@
import { Database } from "bridge-common";
import {
createAction,
updateAction,
deleteAction,
selectAllAction,
} from "../actions/service";
import { FieldDescription, Entity } from "./service";
type GenerateCreateActionArgs = {
entity: Entity;
table: keyof Database;
fields: FieldDescription[];
};
export function generateCreateAction({
entity,
table,
fields,
}: GenerateCreateActionArgs) {
return async (currentState: any, formData: FormData) => {
return createAction({
entity,
table,
fields,
currentState,
formData,
});
};
}
type GenerateUpdateActionArgs = {
entity: Entity;
table: keyof Database;
fields: FieldDescription[];
};
export function generateUpdateAction({
entity,
table,
fields,
}: GenerateUpdateActionArgs) {
return async (currentState: any, formData: FormData) => {
return updateAction({
entity,
table,
fields,
currentState,
formData,
});
};
}
type GenerateDeleteActionArgs = {
entity: Entity;
table: keyof Database;
};
export function generateDeleteAction({
entity,
table,
}: GenerateDeleteActionArgs) {
return async (id: string) => {
return deleteAction({ entity, table, id });
};
}
export function generateSelectAllAction(table: keyof Database) {
return async () => {
return selectAllAction(table);
};
}

View file

@ -0,0 +1,32 @@
import { NextRequest, NextResponse } from "next/server";
import { Service } from "./service";
import { db, getWorkerUtils } from "bridge-common";
export class Facebook extends Service {
async handleWebhook(req: NextRequest) {
const { searchParams } = req.nextUrl;
const submittedToken = searchParams.get("hub.verify_token");
if (submittedToken) {
await db
.selectFrom("FacebookBot")
.selectAll()
.where("verifyToken", "=", submittedToken)
.executeTakeFirstOrThrow();
if (searchParams.get("hub.mode") === "subscribe") {
const challenge = searchParams.get("hub.challenge");
return NextResponse.json(challenge) as any;
} else {
return NextResponse.error();
}
}
const message = await req.json();
const worker = await getWorkerUtils();
await worker.addJob("receive_facebook_message", message);
return NextResponse.json({ response: "ok" });
}
}

View file

@ -0,0 +1,18 @@
import { NextRequest, NextResponse } from "next/server";
import { ServiceParams } from "./service";
import { getService } from "./utils";
export const getBot = async (
_req: NextRequest,
params: ServiceParams,
): Promise<NextResponse> => getService(params)?.getBot(params);
export const sendMessage = async (
req: NextRequest,
params: ServiceParams,
): Promise<NextResponse> => getService(params)?.sendMessage(req, params);
export const handleWebhook = async (
req: NextRequest,
params: ServiceParams,
): Promise<NextResponse> => getService(params)?.handleWebhook(req);

View file

@ -0,0 +1,81 @@
import { NextRequest, NextResponse } from "next/server";
import { GridColDef } from "@mui/x-data-grid-pro";
import { Database, db, getWorkerUtils } from "bridge-common";
import { getServiceTable } from "../config/config";
const entities = [
"facebook",
"whatsapp",
"signal",
"voice",
"webhooks",
"users",
] as const;
export type Entity = (typeof entities)[number];
export type SelectOption = {
value: string;
label: string;
};
export type FieldDescription = {
name: string;
label: string;
kind?: "text" | "phone" | "select" | "multi";
getOptions?: (formState: any) => Promise<SelectOption[]>;
autogenerated?: "token";
hidden?: boolean;
type?: string;
lines?: number;
copyable?: boolean;
refreshable?: boolean;
defaultValue?: string;
required?: boolean;
disabled?: boolean;
size?: number;
helperText?: string;
};
export type ServiceConfig = {
entity: Entity;
table: keyof Database;
displayName: string;
createFields: FieldDescription[];
updateFields: FieldDescription[];
displayFields: FieldDescription[];
listColumns: GridColDef[];
};
export type ServiceParams = {
service: string;
token?: string;
};
export class Service {
async getBot({ service, token }: ServiceParams): Promise<NextResponse> {
const table = getServiceTable(service);
const row = await db
.selectFrom(table)
.selectAll()
.where("token", "=", token ?? "NEVER_MATCH")
.executeTakeFirstOrThrow();
return NextResponse.json(row);
}
async sendMessage(
req: NextRequest,
{ service, token }: ServiceParams,
): Promise<NextResponse> {
const message = await req.json();
const worker = await getWorkerUtils();
await worker.addJob(`send_${service}_message`, { token, message });
return NextResponse.json({ response: "ok" });
}
async handleWebhook(_req: NextRequest): Promise<NextResponse> {
return NextResponse.error() as any;
}
}

View file

@ -0,0 +1,3 @@
import { Service } from "./service";
export class Signal extends Service {}

View file

@ -0,0 +1,16 @@
import { Service, ServiceParams } from "./service";
import { Facebook } from "./facebook";
import { Signal } from "./signal";
import { Whatsapp } from "./whatsapp";
export const getService = ({ service }: ServiceParams): Service => {
if (service === "facebook") {
return new Facebook();
} else if (service === "signal") {
return new Signal();
} else if (service === "whatsapp") {
return new Whatsapp();
}
throw new Error("Service not found");
};

View file

@ -0,0 +1,3 @@
import { Service } from "./service";
export class Voice extends Service {}

View file

@ -0,0 +1,3 @@
import { Service } from "./service";
export class Whatsapp extends Service {}