Refactoring 2
This commit is contained in:
parent
dd14dfe72e
commit
e4b78ceec2
76 changed files with 870 additions and 734 deletions
|
|
@ -1,74 +0,0 @@
|
|||
import { Database } from "./database";
|
||||
import { FieldDescription, Entity } from "./service";
|
||||
import {
|
||||
createAction,
|
||||
updateAction,
|
||||
deleteAction,
|
||||
selectAllAction,
|
||||
} from "@/app/_actions/service";
|
||||
|
||||
type GenerateCreateActionArgs = {
|
||||
entity: Entity;
|
||||
table: keyof Database;
|
||||
fields: FieldDescription[];
|
||||
};
|
||||
|
||||
export function generateCreateAction({
|
||||
entity,
|
||||
table,
|
||||
fields,
|
||||
}: GenerateCreateActionArgs) {
|
||||
return async (currentState: any, formData: FormData) => {
|
||||
console.log({ entity, table, fields });
|
||||
console.log({ currentState, 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);
|
||||
};
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import GoogleProvider from "next-auth/providers/google";
|
||||
import { KyselyAdapter } from "@auth/kysely-adapter";
|
||||
import { db } from "./database";
|
||||
import { db } from "bridge-common";
|
||||
|
||||
export const authOptions = {
|
||||
// @ts-ignore
|
||||
|
|
|
|||
|
|
@ -1,147 +0,0 @@
|
|||
import { PostgresDialect, CamelCasePlugin } from "kysely";
|
||||
import type {
|
||||
GeneratedAlways,
|
||||
Generated,
|
||||
ColumnType,
|
||||
Selectable,
|
||||
Insertable,
|
||||
Updateable,
|
||||
} from "kysely";
|
||||
import { Pool, types } from "pg";
|
||||
import { KyselyAuth } from "@auth/kysely-adapter";
|
||||
|
||||
type Timestamp = ColumnType<Date, Date | string>;
|
||||
|
||||
types.setTypeParser(types.builtins.TIMESTAMPTZ, (val) =>
|
||||
new Date(val).toISOString(),
|
||||
);
|
||||
|
||||
type GraphileJob = {
|
||||
taskIdentifier: string;
|
||||
payload: Record<string, any>;
|
||||
priority: number;
|
||||
maxAttempts: number;
|
||||
key: string;
|
||||
queueName: string;
|
||||
};
|
||||
|
||||
export const addGraphileJob = async (jobInfo: GraphileJob) => {
|
||||
// await db.insertInto("graphile_worker.jobs").values(jobInfo).execute();
|
||||
};
|
||||
|
||||
export interface Database {
|
||||
User: {
|
||||
id: string;
|
||||
name: string | null;
|
||||
email: string;
|
||||
emailVerified: Date | null;
|
||||
image: string | null;
|
||||
};
|
||||
|
||||
Account: {
|
||||
id: GeneratedAlways<string>;
|
||||
userId: string;
|
||||
type: "oidc" | "oauth" | "email" | "webauthn";
|
||||
provider: string;
|
||||
providerAccountId: string;
|
||||
refresh_token: string | undefined;
|
||||
access_token: string | undefined;
|
||||
expires_at: number | undefined;
|
||||
token_type: Lowercase<string> | undefined;
|
||||
scope: string | undefined;
|
||||
id_token: string | undefined;
|
||||
session_state: string | undefined;
|
||||
};
|
||||
|
||||
Session: {
|
||||
id: GeneratedAlways<string>;
|
||||
userId: string;
|
||||
sessionToken: string;
|
||||
expires: Date;
|
||||
};
|
||||
|
||||
VerificationToken: {
|
||||
identifier: string;
|
||||
token: string;
|
||||
expires: Date;
|
||||
};
|
||||
|
||||
WhatsappBot: {
|
||||
id: GeneratedAlways<string>;
|
||||
name: string;
|
||||
description: string;
|
||||
phoneNumber: string;
|
||||
createdBy: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
|
||||
FacebookBot: {
|
||||
id: GeneratedAlways<string>;
|
||||
name: string | null;
|
||||
description: string | null;
|
||||
token: string | null;
|
||||
pageAccessToken: string | null;
|
||||
appSecret: string | null;
|
||||
verifyToken: string | null;
|
||||
pageId: string | null;
|
||||
appId: string | null;
|
||||
userId: string | null;
|
||||
isVerified: Generated<boolean>;
|
||||
createdAt: GeneratedAlways<Timestamp>;
|
||||
updatedAt: GeneratedAlways<Timestamp>;
|
||||
};
|
||||
|
||||
VoiceLine: {
|
||||
id: GeneratedAlways<string>;
|
||||
name: string;
|
||||
description: string;
|
||||
createdBy: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
|
||||
SignalBot: {
|
||||
id: GeneratedAlways<string>;
|
||||
name: string;
|
||||
description: string;
|
||||
phoneNumber: string;
|
||||
createdBy: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
|
||||
Webhook: {
|
||||
id: GeneratedAlways<string>;
|
||||
name: string;
|
||||
description: string;
|
||||
backendType: string;
|
||||
backendId: string;
|
||||
endpointUrl: string;
|
||||
httpMethod: "post" | "put";
|
||||
headers: Record<string, any>;
|
||||
createdBy: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
}
|
||||
|
||||
export type FacebookBot = Selectable<Database["FacebookBot"]>;
|
||||
export type SignalBot = Selectable<Database["SignalBot"]>;
|
||||
export type WhatsappBot = Selectable<Database["WhatsappBot"]>;
|
||||
export type VoiceLine = Selectable<Database["VoiceLine"]>;
|
||||
export type Webhook = Selectable<Database["Webhook"]>;
|
||||
export type User = Selectable<Database["User"]>;
|
||||
|
||||
export const db = new KyselyAuth<Database>({
|
||||
dialect: new PostgresDialect({
|
||||
pool: new Pool({
|
||||
host: process.env.DATABASE_HOST,
|
||||
database: process.env.DATABASE_NAME,
|
||||
port: parseInt(process.env.DATABASE_PORT!),
|
||||
user: process.env.DATABASE_USER,
|
||||
password: process.env.DATABASE_PASSWORD,
|
||||
}),
|
||||
}),
|
||||
plugins: [new CamelCasePlugin()],
|
||||
});
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { makeWorkerUtils, WorkerUtils } from "graphile-worker";
|
||||
import { Service } from "./service";
|
||||
import { db } from "./database";
|
||||
|
||||
let workerUtils: WorkerUtils;
|
||||
|
||||
const getWorkerUtils = async () => {
|
||||
if (!workerUtils) {
|
||||
workerUtils = await makeWorkerUtils({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
});
|
||||
}
|
||||
|
||||
return workerUtils;
|
||||
};
|
||||
|
||||
const sendMessage = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
const receiveMessages = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
const handleWebhook = async (req: NextRequest) => {
|
||||
const { searchParams } = req.nextUrl;
|
||||
const submittedToken = searchParams.get("hub.verify_token");
|
||||
|
||||
if (submittedToken) {
|
||||
console.log({ submittedToken });
|
||||
const row = await db
|
||||
.selectFrom("FacebookBot")
|
||||
.selectAll()
|
||||
.where("verifyToken", "=", submittedToken)
|
||||
.executeTakeFirst();
|
||||
|
||||
console.log({ row });
|
||||
|
||||
if (!row) {
|
||||
return NextResponse.error();
|
||||
}
|
||||
|
||||
if (searchParams.get("hub.mode") === "subscribe") {
|
||||
const challenge = searchParams.get("hub.challenge");
|
||||
console.log(submittedToken);
|
||||
console.log(challenge);
|
||||
|
||||
return NextResponse.json(challenge) as any;
|
||||
}
|
||||
}
|
||||
|
||||
const message = await req.json();
|
||||
console.log({ message });
|
||||
const entry = message.entry[0];
|
||||
console.log({ entry });
|
||||
const messaging = entry?.messaging[0];
|
||||
const pageId = messaging?.recipient?.id;
|
||||
console.log({ pageId });
|
||||
const row = await db
|
||||
.selectFrom("FacebookBot")
|
||||
.selectAll()
|
||||
.where("pageId", "=", pageId)
|
||||
.executeTakeFirst();
|
||||
|
||||
console.log({ row });
|
||||
|
||||
const endpoint = `https://graph.facebook.com/v19.0/${pageId}/messages`;
|
||||
const inMessage = messaging?.message?.text;
|
||||
const outgoingMessage = {
|
||||
recipient: { id: messaging?.sender?.id },
|
||||
message: { text: `"${inMessage}", right back at you!` },
|
||||
messaging_type: "RESPONSE",
|
||||
access_token: row?.pageAccessToken,
|
||||
};
|
||||
console.log({ outgoingMessage });
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(outgoingMessage),
|
||||
});
|
||||
|
||||
console.log({ response });
|
||||
|
||||
console.log(message);
|
||||
const wu = await getWorkerUtils();
|
||||
|
||||
await wu.addJob("receive_facebook_message", message);
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
export const Facebook: Service = {
|
||||
sendMessage,
|
||||
receiveMessages,
|
||||
handleWebhook,
|
||||
};
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { getService } from "./utils";
|
||||
|
||||
const notFound = () => new NextResponse(null, { status: 404 });
|
||||
|
||||
export const getOneBot = async (req: NextRequest): Promise<NextResponse> =>
|
||||
notFound();
|
||||
|
||||
export const sendMessage = async (req: NextRequest): Promise<NextResponse> =>
|
||||
getService(req)?.sendMessage(req) ?? notFound();
|
||||
|
||||
export const receiveMessages = async (
|
||||
req: NextRequest,
|
||||
): Promise<NextResponse> => getService(req)?.receiveMessages(req) ?? notFound();
|
||||
|
||||
export const handleWebhook = async (req: NextRequest): Promise<NextResponse> =>
|
||||
getService(req)?.handleWebhook(req) ?? notFound();
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { GridColDef } from "@mui/x-data-grid-pro";
|
||||
import { Database } from "./database";
|
||||
|
||||
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 class Service {
|
||||
sendMessage: (req: NextRequest) => Promise<NextResponse> = async (req) => {
|
||||
return NextResponse.json({ ok: "nice" });
|
||||
};
|
||||
|
||||
receiveMessages: (req: NextRequest) => Promise<NextResponse> = async (
|
||||
req,
|
||||
) => {
|
||||
return NextResponse.json({ ok: "nice" });
|
||||
};
|
||||
|
||||
handleWebhook: (req: NextRequest) => Promise<NextResponse> = async (req) => {
|
||||
return NextResponse.json({ ok: "nice" });
|
||||
};
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { Service } from "./service";
|
||||
|
||||
const sendMessage = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
const receiveMessages = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
const handleWebhook = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
export const Signal: Service = {
|
||||
sendMessage,
|
||||
receiveMessages,
|
||||
handleWebhook,
|
||||
};
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
import { NextRequest } from "next/server";
|
||||
import { Service } from "./service";
|
||||
import { Facebook } from "./facebook";
|
||||
|
||||
const services: Record<string, Service> = {
|
||||
facebook: Facebook,
|
||||
};
|
||||
|
||||
export const getService = (req: NextRequest): Service => {
|
||||
const service = req.nextUrl.pathname.split("/")?.[2] ?? "none";
|
||||
|
||||
return services[service];
|
||||
};
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { Service } from "./service";
|
||||
|
||||
const sendMessage = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
const receiveMessages = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
const handleWebhook = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
export const Voice: Service = {
|
||||
sendMessage,
|
||||
receiveMessages,
|
||||
handleWebhook,
|
||||
};
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { Service } from "./service";
|
||||
|
||||
const sendMessage = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
const receiveMessages = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
const handleWebhook = async (req: NextRequest) => {
|
||||
console.log({ req });
|
||||
|
||||
return NextResponse.json({ response: "ok" });
|
||||
};
|
||||
|
||||
export const Whatsapp: Service = {
|
||||
sendMessage,
|
||||
receiveMessages,
|
||||
handleWebhook,
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue