Skip to content

Commit

Permalink
feat: Add Vercel Serverless Hosting Support (#121)
Browse files Browse the repository at this point in the history
* feat: Vercel Server Support

* Add Docs
  • Loading branch information
KitsuneDev authored Sep 13, 2021
1 parent a1d4796 commit 1b2272a
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 1 deletion.
52 changes: 52 additions & 0 deletions docs/examples/vercel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
**➡️ Please note that a working templatereference can be found [here](https://github.com/GabrielTK/VercelSlashCreate).**

The most important thing is to:
1. Export the VercelServer instance:
```ts
const { VercelServer } = require('slash-create');
const vercelServer = new VercelServer();
creator
.withServer(vercelServer)
.registerCommandsIn(path.join(__dirname, 'commands'))
//.syncCommands()

export const vercel = vercelServer;
export const slash = creator;
```
2. Then, create a directory called `api`, with the two following files:

* `interactions.ts`
```ts
import { vercel } from ".."; //This is the VercelServer we exported from the previous step.


export default vercel.vercelEndpoint;
```

* `resync.ts` - This file can be renamed, and will be used to resync the interactions with Discord API. I recommend you use this as a post-deploy hook.

```ts
import { VercelRequest, VercelResponse } from "@vercel/node";
import { slash } from "..";

const api = async (req: VercelRequest, res: VercelResponse) => {
//I do recommend you add secret verification here, or some security check.
slash.syncCommands();
//This basically waits until the sync is done
let awaiter = new Promise((resolve,reject) => {
slash.on('synced', () => {
console.log("Elapsed Sync")
resolve(true);
});
});
slash.syncCommands();
await awaiter;
res.status(200).send(JSON.stringify(slash.commands.map(c => [{name: c.commandName, description: c.description}])));
}
export default api;
```

Now, just push it to Vercel! Be sure to verify that the source files are not exposed, and that `/api/interactions` results in a response such as `Server only supports POST requests.` - That's the URL you'll use as your `INTERACTIONS ENDPOINT URL` on your [Discord Developers Page](https://discord.com/developers/)



2 changes: 2 additions & 0 deletions docs/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@
path: lambda.md
- name: Azure Functions
path: azure.md
- name: Vercel
path: vercel.md
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"@types/sinonjs__fake-timers": "6.0.1",
"@typescript-eslint/eslint-plugin": "^4.29.1",
"@typescript-eslint/parser": "^4.29.1",
"@vercel/node": "^1.12.1",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"chai-nock": "^1.3.0",
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export * from './servers/express';
export * from './servers/fastify';
export * from './servers/gateway';
export * from './servers/gcf';
export * from './servers/vercel';

export * from './structures/member';
export * from './structures/message';
Expand Down
44 changes: 44 additions & 0 deletions src/servers/vercel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Server, ServerRequestHandler } from '../server';
// @ts-ignore
import { VercelRequest, VercelResponse } from '@vercel/node';

/**
* A server for Vercel.
* @see https://vercel.com/
* @see https://vercel.com/guides/handling-node-request-body
*/
export class VercelServer extends Server {
private _handler?: ServerRequestHandler;

/**
* @param moduleExports The exports for your module, must be `module.exports`
* @param target The name of the exported function
*/
constructor() {
super({ alreadyListening: true });
// moduleExports = this._onRequest.bind(this);
}

vercelEndpoint = (req: VercelRequest, res: VercelResponse) => {
if (!this._handler) return res.status(503).send('Server has no handler.');
if (req.method !== 'POST') return res.status(405).send('Server only supports POST requests.');
this._handler(
{
headers: req.headers,
body: req.body,
request: req,
response: res
},
async (response) => {
res.status(response.status || 200);
if (response.headers) for (const key in response.headers) res.setHeader(key, response.headers[key] as string);
res.send(response.body);
}
);
};

/** @private */
createEndpoint(path: string, handler: ServerRequestHandler) {
this._handler = handler;
}
}
45 changes: 44 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.0.0.tgz#3205bcd15ada9bc681ac20bef64e9e6df88fd297"
integrity sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA==

"@types/node@*":
version "16.7.13"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.7.13.tgz#86fae356b03b5a12f2506c6cf6cd9287b205973f"
integrity sha512-pLUPDn+YG3FYEt/pHI74HmnJOWzeR+tOIQzUx93pi9M7D8OE7PSLr97HboXwk5F+JS+TLtWuzCOW97AHjmOXXA==

"@types/node@^16.4.14":
version "16.7.10"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.7.10.tgz#7aa732cc47341c12a16b7d562f519c2383b6d4fc"
Expand Down Expand Up @@ -290,6 +295,15 @@
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==

"@vercel/node@^1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@vercel/node/-/node-1.12.1.tgz#15f42f64690f904f8a52a387123ce0958657060f"
integrity sha512-NcawIY05BvVkWlsowaxF2hl/hJg475U8JvT2FnGykFPMx31q1/FtqyTw/awSrKfOSRXR0InrbEIDIelmS9NzPA==
dependencies:
"@types/node" "*"
ts-node "8.9.1"
typescript "4.3.4"

abstract-logging@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839"
Expand Down Expand Up @@ -474,6 +488,11 @@ browser-stdout@1.3.1:
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==

buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==

call-bind@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
Expand Down Expand Up @@ -2143,7 +2162,15 @@ sonic-boom@^1.0.2:
atomic-sleep "^1.0.0"
flatstr "^1.0.12"

source-map@^0.6.1:
source-map-support@^0.5.17:
version "0.5.19"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"

source-map@^0.6.0, source-map@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
Expand Down Expand Up @@ -2292,6 +2319,17 @@ to-regex-range@^5.0.1:
typedoc "^0.20.29"
typedoc-plugin-as-member-of "^1.0.2"

ts-node@8.9.1:
version "8.9.1"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.9.1.tgz#2f857f46c47e91dcd28a14e052482eb14cfd65a5"
integrity sha512-yrq6ODsxEFTLz0R3BX2myf0WBCSQh9A+py8PBo1dCzWIOcvisbyH6akNKqDHMgXePF2kir5mm5JXJTH3OUJYOQ==
dependencies:
arg "^4.1.0"
diff "^4.0.1"
make-error "^1.1.1"
source-map-support "^0.5.17"
yn "3.1.1"

ts-node@^10.2.0:
version "10.2.1"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.2.1.tgz#4cc93bea0a7aba2179497e65bb08ddfc198b3ab5"
Expand Down Expand Up @@ -2398,6 +2436,11 @@ typedoc@^0.20.29:
shiki "^0.9.3"
typedoc-default-themes "^0.12.10"

typescript@4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.4.tgz#3f85b986945bcf31071decdd96cf8bfa65f9dcbc"
integrity sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==

typescript@4.3.5:
version "4.3.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4"
Expand Down

0 comments on commit 1b2272a

Please sign in to comment.