Skip to content

Commit

Permalink
Support Vercel's Express in "inngest/express" serve handler (#290)
Browse files Browse the repository at this point in the history
## Summary
<!-- Succinctly describe your change, providing context, what you've
changed, and why. -->

Adds support for Vercel's Node Express server, which has differing
reported types from the `express` package.

## Checklist
<!-- Tick these items off as you progress. -->
<!-- If an item isn't applicable, ideally please strikeout the item by
wrapping it in "~~"" and suffix it with "N/A My reason for skipping
this." -->
<!-- e.g. "- [ ] ~~Added tests~~ N/A Only touches docs" -->

- [ ] ~~Added a [docs PR](https://github.com/inngest/website) that
references this PR~~ N/A Bug fix
- [x] Added unit/integration tests
- [x] Added changesets if applicable

## Related
<!-- A space for any related links, issues, or PRs. -->
<!-- Linear issues are autolinked. -->
<!-- e.g. - INN-123 -->
<!-- GitHub issues/PRs can be linked using shorthand. -->
<!-- e.g. "- inngest/inngest#123" -->
<!-- Feel free to remove this section if there are no applicable related
links.-->
- Supersedes #288
- Closes inngest/inngest#553
  • Loading branch information
jpwilliams authored Aug 15, 2023
1 parent ac2e394 commit b62c88b
Show file tree
Hide file tree
Showing 6 changed files with 615 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-impalas-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"inngest": patch
---

Support Vercel's Express (`@vercel/node`) in `"inngest/express"` serve handler
1 change: 1 addition & 0 deletions packages/inngest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"@types/sha.js": "^2.4.0",
"@typescript-eslint/eslint-plugin": "^5.47.0",
"@typescript-eslint/parser": "^5.47.0",
"@vercel/node": "^2.15.9",
"concurrently": "^7.4.0",
"eslint": "^8.30.0",
"eslint-config-prettier": "^8.5.0",
Expand Down
16 changes: 16 additions & 0 deletions packages/inngest/src/express.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import { InngestCommHandler } from "@local/components/InngestCommHandler";
import * as ExpressHandler from "@local/express";
import { type VercelRequest, type VercelRequestQuery } from "@vercel/node";
import { createClient, testFramework } from "./test/helpers";

testFramework("Express", ExpressHandler);

testFramework("Express (Vercel)", ExpressHandler, {
transformReq: (expressReq, res) => {
const req: Partial<VercelRequest> = {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
body: expressReq.body,
headers: expressReq.headers,
query: expressReq.query as VercelRequestQuery,
method: expressReq.method,
url: expressReq.url,
};

return [req, res];
},
});

describe("InngestCommHandler", () => {
describe("registerBody", () => {
it("Includes correct base URL for functions", () => {
Expand Down
21 changes: 17 additions & 4 deletions packages/inngest/src/express.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { type VercelRequest, type VercelResponse } from "@vercel/node";
import { type Request, type Response } from "express";
import {
InngestCommHandler,
type ServeHandler,
} from "./components/InngestCommHandler";
import { headerKeys, queryKeys } from "./helpers/consts";
import { type Either } from "./helpers/types";
import { type SupportedFrameworkName } from "./types";

export const name: SupportedFrameworkName = "express";
Expand All @@ -20,10 +22,21 @@ export const serve: ServeHandler = (nameOrInngest, fns, opts) => {
nameOrInngest,
fns,
opts,
(req: Request, _res: Response) => {
const hostname = req.get("host") || req.headers["host"];
const protocol = hostname?.includes("://") ? "" : `${req.protocol}://`;
const url = new URL(req.originalUrl, `${protocol}${hostname || ""}`);
(
req: Either<Request, VercelRequest>,
_res: Either<Response, VercelResponse>
) => {
// `req.hostname` can filter out port numbers; beware!
const hostname = req.headers["host"] || opts?.serveHost;

const protocol = hostname?.includes("://")
? ""
: `${req.protocol || "https"}://`;

const url = new URL(
req.originalUrl || req.url || "",
`${protocol}${hostname || ""}`
);

return {
url,
Expand Down
6 changes: 6 additions & 0 deletions packages/inngest/src/helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,9 @@ export type ObjectAssign<TArr, TAcc = {}> = TArr extends [
export type ExclusiveKeys<T, Keys1 extends keyof T, Keys2 extends keyof T> =
| (Omit<T, Keys1> & { [K in Keys1]?: never })
| (Omit<T, Keys2> & { [K in Keys2]?: never });

/**
* A type that represents either `A` or `B`. Shared properties retain their
* types and unique properties are marked as optional.
*/
export type Either<A, B> = Partial<A> & Partial<B> & (A | B);
Loading

0 comments on commit b62c88b

Please sign in to comment.