Skip to content

Commit

Permalink
chore: re-use invoke api logic
Browse files Browse the repository at this point in the history
  • Loading branch information
svedova committed Oct 12, 2023
1 parent 8c8ebac commit 9cfb85e
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 37 deletions.
37 changes: 14 additions & 23 deletions src/middlewares/express.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Request, Response, Handler } from "express";
import type { AlternativeSyntax } from "~/utils/callbacks";
import type { Request, Response } from "express";
import path from "node:path";
import { invokeApiHandler } from "~/utils/callbacks";
import { matchPath } from "~/router";

interface Options {
Expand Down Expand Up @@ -34,29 +34,20 @@ export default (opts: Options) => async (req: Request, res: Response) => {
`/${path.join(apiDir, route).replace(/^\/+/, "")}`
);

Promise.resolve(handler.default(req, res, () => {})).then(
(r: AlternativeSyntax | void) => {
if (typeof r !== "undefined" && typeof r === "object") {
const isBodyAnObject = typeof r.body === "object";

if (isBodyAnObject) {
res.setHeader("Content-Type", "application/json");
}

Object.keys(r.headers || {}).forEach((key) => {
res.setHeader(key, r.headers![key]);
});
invokeApiHandler(handler, req, res).then((data) => {
if (!data) {
res.status(200);
res.end();
return;
}

res.status(r.status || r.statusCode || 200);
Object.keys(data.headers || {}).forEach((key) => {
res.setHeader(key, data.headers![key]);
});

if (isBodyAnObject) {
res.send(JSON.stringify(r.body));
} else {
res.send(r.body);
}
}
}
);
res.status(data.status || 200);
res.send(data.body);
});

return;
}
Expand Down
47 changes: 33 additions & 14 deletions src/utils/callbacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,37 @@ let cachedFiles: WalkFile[];

export interface AlternativeSyntax {
body?: string;
headers?: Record<string, string>;
headers?: Record<string, string | string[]>;
statusCode?: number;
status?: number; // Alias for statusCode
}

export const invokeApiHandler = (
handler: any,
req: any,
res: any
): Promise<ServerlessResponse | void> => {
const ret = handler?.default ? handler.default(req, res) : handler(req, res);

// Allow function to return a value instead of using `response.end`
return Promise.resolve(ret).then((r: AlternativeSyntax) => {
if (typeof r !== "undefined" && typeof r === "object") {
const isBodyAnObject = typeof r.body === "object";
const headers: Record<string, string | string[]> = {};

if (isBodyAnObject) {
headers["Content-Type"] = "application/json";
}

return {
body: typeof r.body === "string" ? r.body : JSON.stringify(r.body),
headers: { ...headers, ...r.headers },
status: r.statusCode || r.status,
};
}
});
};

export const handleApi = (
event: RequestEvent,
apiDir: string
Expand All @@ -47,7 +73,7 @@ export const handleApi = (
cachedFiles = walkTree(apiDir);
}

return new Promise((resolve) => {
return new Promise(async (resolve) => {
const req = new Request(event);
const res = new Response(req);

Expand All @@ -61,18 +87,11 @@ export const handleApi = (
if (file) {
try {
const mod = require(path.join(file.path, file.name));
const ret = mod.default ? mod.default(req, res) : mod(req, res);

// Allow function to return a value instead of using `response.end`
Promise.resolve(ret).then((r: AlternativeSyntax) => {
if (typeof r !== "undefined" && typeof r === "object") {
resolve({
body: r.body,
headers: r.headers,
status: r.statusCode || r.status,
});
}
});
const ret = await invokeApiHandler(mod, req, res);

if (ret) {
resolve(ret);
}

return;
} catch (e) {
Expand Down

0 comments on commit 9cfb85e

Please sign in to comment.