aboutsummaryrefslogtreecommitdiff
path: root/examples/discord-interactions/bun_shim/server.js
blob: 5f32852a10fd379301cc5a9ccfc3a07cb99a2ff3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import { Server } from 'slash-create';
import { MultipartData } from 'slash-create/lib/util/multipartData.js';

export default class BunServer extends Server {
  #server = null;
  #handler = null;
  isWebserver = true;

  constructor() {
    super({ alreadyListening: true });
  }

  createEndpoint(path, handler) {
    this.#handler = handler;
  }

  stop() {
    if (this.#server) this.#server.close();
    else throw new Error('BunServer not started');
  }

  listen(port) {
    const getHandler = () => this.#handler;

    this.#server = Bun.serve({
      port,

      async fetch(req) {
        const handler = getHandler();
        if (!handler) return new Response('Server has no handler.', { status: 503 });
        if (req.method !== 'POST') return new Response('Server only supports POST requests.', { status: 405 });

        const reqHeaders = Object.fromEntries(req.headers.entries());
        
        const reqBody = await req.json();

        return await new Promise(async (ok, err) => {
          try {
            await handler({
              request: req,
              body: reqBody,
              response: null,
              headers: reqHeaders,
            }, response => {
              let body = response.body;
              const headers = new Headers();

              if (response.headers) {
                for (const key in response.headers) {
                  headers.set(key, response.headers[key]);
                }
              }

              if ('string' !== typeof body) {
                body = JSON.stringify(body);
                headers.set('content-type', 'application/json');
              }

              if (response.files) {
                const form = new MultipartData();
                headers.set('content-type', `multipart/form-data; boundary=${form.boundary}`);

                form.attach('payload_json', body);
                for (const file of response.files) form.attach(file.name, file.file, file.name);

                body = Buffer.concat(form.finish());
              }

              ok(new Response(body, { headers, status: response.status }));
            });
          } catch (error) {
            err(error);
          }
        });
      },
    });
  }
};