This commit is contained in:
2025-12-22 07:18:57 +01:00
parent 0d9f313dc0
commit cfcd08680f
46 changed files with 1338 additions and 98 deletions
@@ -0,0 +1,26 @@
import { APIPathsCrudParams, APIResponseObject } from "../../types";
import dsqlCrud from "../../utils/data-fetching/crud";
export default async function <
T extends { [k: string]: any } = { [k: string]: any }
>({
table,
body,
targetId,
}: APIPathsCrudParams<T>): Promise<APIResponseObject> {
if (!targetId && !body?.searchQuery) {
throw new Error(
`Target ID or \`searchQuery\` field is required to delete Data.`
);
}
const DELETE_RESLT = await dsqlCrud({
...body?.crudParams,
action: "delete",
table,
query: body?.searchQuery,
targetId,
});
return DELETE_RESLT;
}
@@ -0,0 +1,29 @@
import { APIPathsCrudParams, APIResponseObject } from "../../types";
import dsqlCrud from "../../utils/data-fetching/crud";
export default async function <
T extends { [k: string]: any } = { [k: string]: any }
>({
table,
query,
allowedTable,
url,
}: APIPathsCrudParams<T>): Promise<APIResponseObject> {
if (
(allowedTable?.allowedFields || allowedTable?.disallowedFields) &&
!query?.searchQuery?.selectFields?.[0]
) {
throw new Error(
`Please specify fields to select! Use the \`selectFields\` option in the query object`
);
}
const GET_RESULT = await dsqlCrud({
...query?.crudParams,
action: "get",
table,
query: query?.searchQuery,
});
return GET_RESULT;
}
@@ -0,0 +1,15 @@
import { APIPathsCrudParams, APIResponseObject } from "../../types";
import dsqlCrud from "../../utils/data-fetching/crud";
export default async function <
T extends { [k: string]: any } = { [k: string]: any }
>({ table, body }: APIPathsCrudParams<T>): Promise<APIResponseObject> {
const POST_RESULT = await dsqlCrud({
...body?.crudParams,
action: "insert",
table,
data: body?.data,
});
return POST_RESULT;
}
@@ -0,0 +1,27 @@
import { APIPathsCrudParams, APIResponseObject } from "../../types";
import dsqlCrud from "../../utils/data-fetching/crud";
export default async function <
T extends { [k: string]: any } = { [k: string]: any }
>({
table,
body,
targetId,
}: APIPathsCrudParams<T>): Promise<APIResponseObject> {
if (!targetId && !body?.searchQuery) {
throw new Error(
`Target ID or \`searchQuery\` field is required to update Data.`
);
}
const PUT_RESULT = await dsqlCrud({
...body?.crudParams,
action: "update",
table,
data: body?.data,
query: body?.searchQuery,
targetId,
});
return PUT_RESULT;
}
+74
View File
@@ -0,0 +1,74 @@
import _ from "lodash";
import {
APIPathsCrudParams,
APIPathsParams,
APIResponseObject,
} from "../types";
import getResult from "./functions/get-result";
import { grabPathData } from "./utils/grab-path-data";
import checks from "./utils/checks";
import postResult from "./functions/post-result";
import putResult from "./functions/put-result";
import deleteResult from "./functions/delete-result";
export default async function apiCrudHandler<
T extends { [k: string]: any } = { [k: string]: any }
>(params: APIPathsParams<T>): Promise<APIResponseObject> {
try {
const { auth, method } = params;
const isAuthorized = await auth?.();
const { table, targetId, url, query } = grabPathData<T>(params);
const crudParams: APIPathsCrudParams<T> = {
...params,
isAuthorized,
table,
targetId,
};
const checkedObj = await checks<T>({
...crudParams,
query: _.merge(params.query || {}, query),
});
crudParams.query = checkedObj.query;
crudParams.body = checkedObj.body;
crudParams.allowedTable = checkedObj.allowedTable;
crudParams.url = url;
if (targetId) {
if (crudParams.query) {
if (crudParams.query.crudParams) {
crudParams.query.crudParams.targetId = targetId;
} else {
crudParams.query.crudParams = {
targetId,
};
}
}
}
switch (method) {
case "GET":
return await getResult(crudParams);
case "POST":
return await postResult(crudParams);
case "PUT":
return await putResult(crudParams);
case "DELETE":
return await deleteResult(crudParams);
}
return {
success: false,
msg: `Unhandled`,
};
} catch (error: any) {
return {
success: false,
msg: error.message,
};
}
}
+166
View File
@@ -0,0 +1,166 @@
import _ from "lodash";
import { APIPathsCrudParams, APIPathsParamsAllowedTable } from "../../types";
export default async function checks<
T extends { [k: string]: any } = { [k: string]: any }
>({
table,
allowedTables,
query,
body,
method,
getMiddleware,
postMiddleware,
putMiddleware,
deleteMiddleware,
crudMiddleware,
}: APIPathsCrudParams<T>): Promise<
Pick<APIPathsCrudParams<T>, "query" | "body"> & {
allowedTable: APIPathsParamsAllowedTable;
}
> {
const allowedTable = allowedTables.find((tbl) => tbl.table == table);
if (!allowedTable) {
throw new Error(`Can't Access this table: \`${table}\``);
}
let newQuery = _.cloneDeep(query);
let newBody = _.cloneDeep(body);
const searchFields = Object.keys(newQuery?.searchQuery?.query || {});
const selectFields = (
newQuery?.searchQuery?.selectFields
? newQuery.searchQuery.selectFields.map((f) =>
typeof f == "string"
? f
: typeof f == "object"
? f.fieldName
: undefined
)
: undefined
)?.filter((f) => typeof f == "string");
const targetFields = [...(searchFields || []), ...(selectFields || [])];
if (method == "GET" && allowedTable.allowedFields) {
for (let i = 0; i < targetFields.length; i++) {
const fld = targetFields[i];
const allowedFld = allowedTable.allowedFields.find((f) =>
typeof f == "string" ? f == fld : fld.match(f)
);
if (!allowedFld) {
throw new Error(`\`${allowedFld}\` field not allowed`);
}
}
}
if (method == "GET" && allowedTable.disallowedFields) {
for (let i = 0; i < targetFields.length; i++) {
const fld = targetFields[i];
const disallowedFld = allowedTable.disallowedFields.find((f) =>
typeof f == "string" ? f == fld : fld.match(f)
);
if (disallowedFld) {
throw new Error(`\`${disallowedFld}\` field not allowed`);
}
}
}
if (method == "GET" && getMiddleware) {
newQuery = await getMiddleware({ query: newQuery || ({} as any) });
}
if (method !== "GET" && crudMiddleware) {
const middRes = await crudMiddleware({
body: newBody || ({} as any),
query: newQuery || {},
});
newBody = _.merge(newBody, middRes);
}
if (method == "POST" && postMiddleware) {
const middRes = await postMiddleware({
body: newBody || ({} as any),
query: newQuery || {},
});
newBody = _.merge(newBody, middRes);
}
if (method == "PUT" && putMiddleware) {
const middRes = await putMiddleware({
body: newBody || ({} as any),
query: newQuery || {},
});
newBody = _.merge(newBody, middRes);
}
if (method == "DELETE" && deleteMiddleware) {
const middRes = await deleteMiddleware({
body: newBody || ({} as any),
query: newQuery || {},
});
newBody = _.merge(newBody, middRes);
}
if (newQuery?.searchQuery?.join) {
for (let i = 0; i < newQuery.searchQuery.join.length; i++) {
const join = newQuery.searchQuery.join[i];
const joinTableName = join.tableName;
const selectFields = join.selectFields;
if (allowedTables?.[0]) {
const allowedJoinTable = allowedTables.find(
(t) => t.table == joinTableName
);
if (!allowedJoinTable?.table) {
throw new Error(`Can't joint \`${joinTableName}\` table`);
}
const allowedFields = allowedJoinTable.allowedFields;
const disallowedFields = allowedJoinTable.disallowedFields;
if (selectFields?.[0]) {
for (let j = 0; j < selectFields.length; j++) {
const selectField = selectFields[j];
const selectFieldName =
typeof selectField == "object"
? selectField.field
: String(selectField);
if (
allowedFields?.[0] &&
!allowedFields.find(
(f) => String(f) == selectFieldName
)
) {
throw new Error(`Can't Select this Field!`);
}
if (
disallowedFields?.[0] &&
disallowedFields.find(
(f) => String(f) == selectFieldName
)
) {
throw new Error(`Disallowed Field Selected!`);
}
}
}
}
}
}
return {
query: newQuery,
body: newBody,
allowedTable,
};
}
@@ -0,0 +1,34 @@
import { APIPathsData, APIPathsParams, APIPathsQuery } from "../../types";
import deserializeQuery from "../../utils/deserialize-query";
export function grabPathData<
T extends { [k: string]: any } = { [k: string]: any }
>({ href, basePath }: APIPathsParams<T>): APIPathsData<T> {
const urlObj = new URL(href);
const pathname = basePath
? urlObj.pathname.replace(basePath, "")
: urlObj.pathname;
const urlArray = pathname.split("/").filter((u) => Boolean(u.match(/./)));
const table = urlArray[0];
const targetId = urlArray[1];
let query = (
urlObj?.searchParams
? deserializeQuery(Object.fromEntries(urlObj.searchParams))
: undefined
) as APIPathsQuery<T> | undefined;
if (!table) {
throw new Error(`No Table Found`);
}
return {
table,
targetId,
query,
url: urlObj,
};
}