yedra 0.14.5 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,16 @@ declare class Context {
11
11
  constructor(server: Server, wss: WebSocketServer, counter: Counter);
12
12
  stop(): Promise<void>;
13
13
  }
14
+ type ServeResponse = {
15
+ status?: number;
16
+ body: Uint8Array | string;
17
+ headers?: Record<string, string>;
18
+ };
19
+ type ServeFallback = () => ServeResponse | Promise<ServeResponse>;
20
+ type ServeConfig = {
21
+ dir: string;
22
+ fallback?: string | ServeFallback;
23
+ };
14
24
  type ConnectMiddleware = (req: IncomingMessage, res: ServerResponse, next: () => void) => void;
15
25
  export declare class Yedra {
16
26
  private restRoutes;
@@ -32,7 +42,7 @@ export declare class Yedra {
32
42
  url: string;
33
43
  }[];
34
44
  }): object;
35
- private static loadStatic;
45
+ private static loadServe;
36
46
  private performRequest;
37
47
  private middlewareNext;
38
48
  listen(port: number, options?: {
@@ -45,10 +55,7 @@ export declare class Yedra {
45
55
  path: string;
46
56
  get?: () => Promise<string> | string;
47
57
  };
48
- static?: {
49
- dir: string;
50
- fallback?: string;
51
- };
58
+ serve?: ServeConfig;
52
59
  /**
53
60
  * Prevents all normal output from Yedra. Mostly useful for tests.
54
61
  */
@@ -3,6 +3,7 @@ import { createServer as createHttpServer } from 'node:http';
3
3
  import { createServer as createHttpsServer } from 'node:https';
4
4
  import { extname, join } from 'node:path';
5
5
  import { URL } from 'node:url';
6
+ import { isUint8Array } from 'node:util/types';
6
7
  import mime from 'mime';
7
8
  import { WebSocketServer } from 'ws';
8
9
  import { Counter } from '../util/counter.js';
@@ -82,14 +83,17 @@ export class Yedra {
82
83
  paths,
83
84
  };
84
85
  }
85
- static async loadStatic(options) {
86
- if (options === undefined) {
87
- return new Map();
86
+ static async loadServe(config) {
87
+ if (config === undefined) {
88
+ return {
89
+ files: new Map(),
90
+ fallback: undefined,
91
+ };
88
92
  }
89
93
  const staticFiles = new Map();
90
- const files = await readdir(options.dir, { recursive: true });
94
+ const files = await readdir(config.dir, { recursive: true });
91
95
  await Promise.all(files.map(async (file) => {
92
- const absolute = join(options.dir, file);
96
+ const absolute = join(config.dir, file);
93
97
  if (!(await stat(absolute)).isFile()) {
94
98
  return;
95
99
  }
@@ -99,16 +103,30 @@ export class Yedra {
99
103
  mime: mime.getType(extname(file)) ?? 'application/octet-stream',
100
104
  });
101
105
  }));
102
- if (options.fallback) {
103
- const data = await readFile(options.fallback);
104
- staticFiles.set('__fallback', {
105
- data,
106
- mime: mime.getType(extname(options.fallback)) ?? 'application/octet-stream',
107
- });
106
+ if (config.fallback) {
107
+ if (typeof config.fallback === 'string') {
108
+ const data = await readFile(config.fallback);
109
+ staticFiles.set('__fallback', {
110
+ data,
111
+ mime: mime.getType(extname(config.fallback)) ??
112
+ 'application/octet-stream',
113
+ });
114
+ return {
115
+ files: staticFiles,
116
+ fallback: undefined,
117
+ };
118
+ }
119
+ return {
120
+ files: staticFiles,
121
+ fallback: config.fallback,
122
+ };
108
123
  }
109
- return staticFiles;
124
+ return {
125
+ files: staticFiles,
126
+ fallback: undefined,
127
+ };
110
128
  }
111
- async performRequest(staticFiles, req) {
129
+ async performRequest(serveData, req) {
112
130
  if (req.method !== 'GET' &&
113
131
  req.method !== 'POST' &&
114
132
  req.method !== 'PUT' &&
@@ -120,7 +138,8 @@ export class Yedra {
120
138
  // no matching route found
121
139
  if (req.method === 'GET') {
122
140
  // look for a static file
123
- const staticFile = staticFiles.get(req.url.pathname) ?? staticFiles.get('__fallback');
141
+ const staticFile = serveData.files.get(req.url.pathname) ??
142
+ serveData.files.get('__fallback');
124
143
  if (staticFile !== undefined) {
125
144
  return {
126
145
  status: 200,
@@ -130,6 +149,16 @@ export class Yedra {
130
149
  },
131
150
  };
132
151
  }
152
+ if (serveData.fallback !== undefined) {
153
+ const response = await serveData.fallback();
154
+ return {
155
+ status: response.status ?? 200,
156
+ body: isUint8Array(response.body)
157
+ ? response.body
158
+ : Buffer.from(response.body, 'utf-8'),
159
+ headers: response.headers,
160
+ };
161
+ }
133
162
  }
134
163
  if (match.invalidMethod) {
135
164
  // we found a route, but it did not match the request method
@@ -168,7 +197,7 @@ export class Yedra {
168
197
  }
169
198
  }
170
199
  async listen(port, options) {
171
- const staticFiles = await Yedra.loadStatic(options?.static);
200
+ const serveData = await Yedra.loadServe(options?.serve);
172
201
  const server = options?.tls === undefined
173
202
  ? createHttpServer()
174
203
  : createHttpsServer({
@@ -183,7 +212,7 @@ export class Yedra {
183
212
  counter.increment();
184
213
  const url = new URL(req.url, 'http://localhost');
185
214
  const begin = Date.now();
186
- const response = await this.performRequest(staticFiles, {
215
+ const response = await this.performRequest(serveData, {
187
216
  method: req.method ?? 'GET',
188
217
  url,
189
218
  body: req,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yedra",
3
- "version": "0.14.5",
3
+ "version": "0.15.0",
4
4
  "repository": "github:0codekit/yedra",
5
5
  "main": "dist/index.js",
6
6
  "devDependencies": {