Generalize WIP

This commit is contained in:
Darren Clarke 2024-04-26 14:31:33 +02:00
parent a3e8b89128
commit cb7a3a08dc
31 changed files with 657 additions and 106 deletions

View file

@ -1,93 +1,65 @@
"use server";
import { Database } from "./database";
import { FieldDescription, Entity } from "./service";
import {
createAction,
updateAction,
deleteAction,
} from "@/app/_actions/service";
import { revalidatePath } from "next/cache";
import { db, Database } from "./database";
type AddActionArgs = {
entity: string;
type GenerateCreateActionArgs = {
entity: Entity;
table: keyof Database;
fields: string[];
currentState: any;
formData: FormData;
fields: FieldDescription[];
};
export const addAction = async ({
export function generateCreateAction({
entity,
table,
fields,
currentState,
formData,
}: AddActionArgs) => {
const newRecord = fields.reduce(
(acc: Record<string, string>, field: string) => {
// @ts-expect-error
acc[field] = formData.get(field)?.toString() ?? null;
return acc;
},
{},
);
await db.insertInto(table).values(newRecord).execute();
revalidatePath(`/${entity}`);
return {
...currentState,
values: newRecord,
success: true,
}: GenerateCreateActionArgs) {
return async (currentState: any, formData: FormData) => {
return createAction({
entity,
table,
fields,
currentState,
formData,
});
};
};
}
type UpdateActionArgs = {
entity: string;
type GenerateUpdateActionArgs = {
entity: Entity;
table: keyof Database;
fields: string[];
currentState: any;
formData: FormData;
fields: FieldDescription[];
};
export const updateAction = async ({
export function generateUpdateAction({
entity,
table,
fields,
currentState,
formData,
}: UpdateActionArgs) => {
const id = currentState.values.id;
const updatedRecord = fields.reduce(
(acc: Record<string, string>, field: string) => {
// @ts-expect-error
acc[field] = formData.get(field)?.toString() ?? null;
return acc;
},
{},
);
await db
.updateTable(table)
.set(updatedRecord)
.where("id", "=", id)
.executeTakeFirst();
revalidatePath(`/${entity}/${id}`);
return {
...currentState,
values: updatedRecord,
success: true,
}: GenerateUpdateActionArgs) {
return async (currentState: any, formData: FormData) => {
return updateAction({
entity,
table,
fields,
currentState,
formData,
});
};
};
}
type DeleteActionArgs = {
entity: string;
type GenerateDeleteActionArgs = {
entity: Entity;
table: keyof Database;
id: string;
};
export const deleteAction = async ({ entity, table, id }: DeleteActionArgs) => {
await db.deleteFrom(table).where("id", "=", id).execute();
revalidatePath(`/${entity}`);
return true;
};
export function generateDeleteAction({
entity,
table,
}: GenerateDeleteActionArgs) {
return async (id: string) => {
return deleteAction({ entity, table, id });
};
}

View file

@ -0,0 +1,6 @@
import type { ServiceConfig } from "./service";
import { facebookConfig as facebook } from "./facebook";
export const serviceConfig: Record<string, ServiceConfig> = {
facebook,
};

View file

@ -1,5 +1,83 @@
import { NextRequest, NextResponse } from "next/server";
import { Service } from "./service";
import { Service, ServiceConfig } from "./service";
export const facebookConfig: ServiceConfig = {
entity: "facebook",
table: "FacebookBot",
displayName: "Facebook Connections",
createFields: [
{ name: "name", type: "text", label: "Name", required: true },
{
name: "description",
type: "text",
label: "Description",
required: true,
},
{ name: "appId", type: "text", label: "App ID", required: true },
{ name: "appSecret", type: "text", label: "App Secret", required: true },
{ name: "pageId", type: "text", label: "Page ID", required: true },
{
name: "pageAccessToken",
type: "text",
label: "Page Access Token",
required: true,
},
],
updateFields: [
{ name: "name", type: "text", label: "Name", required: true },
{
name: "description",
type: "text",
label: "Description",
required: true,
},
{ name: "appId", type: "text", label: "App ID", required: true },
{ name: "appSecret", type: "text", label: "App Secret", required: true },
{ name: "pageId", type: "text", label: "Page ID", required: true },
{
name: "pageAccessToken",
type: "text",
label: "Page Access Token",
required: true,
},
],
displayFields: [
{ name: "name", type: "text", label: "Name", required: true },
{
name: "description",
type: "text",
label: "Description",
required: true,
},
{ name: "appId", type: "text", label: "App ID", required: true },
{ name: "appSecret", type: "text", label: "App Secret", required: true },
{ name: "pageId", type: "text", label: "Page ID", required: true },
{
name: "pageAccessToken",
type: "text",
label: "Page Access Token",
required: true,
},
],
listColumns: [
{
field: "name",
headerName: "Name",
flex: 1,
},
{
field: "description",
headerName: "Description",
flex: 2,
},
{
field: "updatedAt",
headerName: "Updated At",
valueGetter: (value: any) => new Date(value).toLocaleString(),
flex: 1,
},
],
};
const getAllBots = async (req: NextRequest) => {
console.log({ req });

View file

@ -1,6 +1,42 @@
import { NextRequest, NextResponse } from "next/server";
import { GridColDef } from "@mui/x-data-grid-pro";
import { Database } from "./database";
export interface Service {
const entities = [
"facebook",
"whatsapp",
"signal",
"voice",
"webhook",
"user",
] as const;
export type Entity = (typeof entities)[number];
export type FieldDescription = {
name: string;
type: string;
label: string;
lines?: number;
copyable?: 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 Service = {
getAllBots: (req: NextRequest) => Promise<NextResponse>;
getOneBot: (req: NextRequest) => Promise<NextResponse>;
sendMessage: (req: NextRequest) => Promise<NextResponse>;
@ -13,4 +49,4 @@ export interface Service {
createBot: (req: NextRequest) => Promise<NextResponse>;
deleteBot: (req: NextRequest) => Promise<NextResponse>;
handleWebhook: (req: NextRequest) => Promise<NextResponse>;
}
};