speexjs 0.2.3 → 0.4.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.
@@ -1,216 +1,176 @@
1
- // src/server/container/index.ts
2
- var Container = class {
3
- bindings = /* @__PURE__ */ new Map();
4
- resolving = /* @__PURE__ */ new Set();
5
- bind(name, factory) {
6
- this.bindings.set(name, { factory, singleton: false });
7
- return this;
8
- }
9
- singleton(name, factory) {
10
- this.bindings.set(name, { factory, singleton: true });
11
- return this;
12
- }
13
- instance(name, instance) {
14
- this.bindings.set(name, {
15
- factory: () => instance,
16
- singleton: true,
17
- instance
18
- });
19
- return this;
20
- }
21
- resolve(name) {
22
- const binding = this.bindings.get(name);
23
- if (binding === void 0) {
24
- throw new Error(`Binding not found: ${name}`);
25
- }
26
- if (binding.singleton && binding.instance !== void 0) {
27
- return binding.instance;
28
- }
29
- if (this.resolving.has(name)) {
30
- throw new Error(
31
- `Circular dependency detected: ${name} is already being resolved`
32
- );
33
- }
34
- this.resolving.add(name);
35
- try {
36
- const instance = binding.factory();
37
- if (binding.singleton) {
38
- binding.instance = instance;
39
- }
40
- return instance;
41
- } finally {
42
- this.resolving.delete(name);
43
- }
44
- }
45
- has(name) {
46
- return this.bindings.has(name);
47
- }
48
- remove(name) {
49
- this.bindings.delete(name);
50
- }
51
- clear() {
52
- this.bindings.clear();
53
- this.resolving.clear();
54
- }
55
- getBindings() {
56
- return new Map(this.bindings);
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __esm = (fn, res) => function __init() {
14
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
15
+ };
16
+ var __commonJS = (cb, mod) => function __require2() {
17
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
18
+ };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
57
24
  }
25
+ return to;
58
26
  };
27
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
28
+ // If the importer is in node compatibility mode or this is not an ESM
29
+ // file that has been converted to a CommonJS file using a Babel-
30
+ // compatible transform (i.e. "__esModule" has not been set), then set
31
+ // "default" to the CommonJS "module.exports" for node compatibility.
32
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
33
+ mod
34
+ ));
59
35
 
60
36
  // src/server/http/status.ts
61
- var HttpStatus = {
62
- OK: 200,
63
- CREATED: 201,
64
- ACCEPTED: 202,
65
- NO_CONTENT: 204,
66
- RESET_CONTENT: 205,
67
- PARTIAL_CONTENT: 206,
68
- MOVED_PERMANENTLY: 301,
69
- FOUND: 302,
70
- SEE_OTHER: 303,
71
- NOT_MODIFIED: 304,
72
- TEMPORARY_REDIRECT: 307,
73
- PERMANENT_REDIRECT: 308,
74
- BAD_REQUEST: 400,
75
- UNAUTHORIZED: 401,
76
- PAYMENT_REQUIRED: 402,
77
- FORBIDDEN: 403,
78
- NOT_FOUND: 404,
79
- METHOD_NOT_ALLOWED: 405,
80
- NOT_ACCEPTABLE: 406,
81
- REQUEST_TIMEOUT: 408,
82
- CONFLICT: 409,
83
- GONE: 410,
84
- LENGTH_REQUIRED: 411,
85
- PRECONDITION_FAILED: 412,
86
- PAYLOAD_TOO_LARGE: 413,
87
- URI_TOO_LONG: 414,
88
- UNSUPPORTED_MEDIA_TYPE: 415,
89
- UNPROCESSABLE_ENTITY: 422,
90
- TOO_MANY_REQUESTS: 429,
91
- INTERNAL_SERVER_ERROR: 500,
92
- NOT_IMPLEMENTED: 501,
93
- BAD_GATEWAY: 502,
94
- SERVICE_UNAVAILABLE: 503,
95
- GATEWAY_TIMEOUT: 504,
96
- HTTP_VERSION_NOT_SUPPORTED: 505
97
- };
98
-
99
- // src/server/controller/index.ts
100
- var controllerPrefixMap = /* @__PURE__ */ new WeakMap();
101
- var controllerRoutesMap = /* @__PURE__ */ new WeakMap();
102
- function createRouteDecorator(method) {
103
- return (path3) => {
104
- return (target, context) => {
105
- const classTarget = context.static ? target : target.constructor;
106
- const routes = controllerRoutesMap.get(classTarget) ?? [];
107
- routes.push({ method, path: path3, handler: context.name });
108
- controllerRoutesMap.set(classTarget, routes);
37
+ var HttpStatus;
38
+ var init_status = __esm({
39
+ "src/server/http/status.ts"() {
40
+ "use strict";
41
+ HttpStatus = {
42
+ OK: 200,
43
+ CREATED: 201,
44
+ ACCEPTED: 202,
45
+ NO_CONTENT: 204,
46
+ RESET_CONTENT: 205,
47
+ PARTIAL_CONTENT: 206,
48
+ MOVED_PERMANENTLY: 301,
49
+ FOUND: 302,
50
+ SEE_OTHER: 303,
51
+ NOT_MODIFIED: 304,
52
+ TEMPORARY_REDIRECT: 307,
53
+ PERMANENT_REDIRECT: 308,
54
+ BAD_REQUEST: 400,
55
+ UNAUTHORIZED: 401,
56
+ PAYMENT_REQUIRED: 402,
57
+ FORBIDDEN: 403,
58
+ NOT_FOUND: 404,
59
+ METHOD_NOT_ALLOWED: 405,
60
+ NOT_ACCEPTABLE: 406,
61
+ REQUEST_TIMEOUT: 408,
62
+ CONFLICT: 409,
63
+ GONE: 410,
64
+ LENGTH_REQUIRED: 411,
65
+ PRECONDITION_FAILED: 412,
66
+ PAYLOAD_TOO_LARGE: 413,
67
+ URI_TOO_LONG: 414,
68
+ UNSUPPORTED_MEDIA_TYPE: 415,
69
+ UNPROCESSABLE_ENTITY: 422,
70
+ TOO_MANY_REQUESTS: 429,
71
+ INTERNAL_SERVER_ERROR: 500,
72
+ NOT_IMPLEMENTED: 501,
73
+ BAD_GATEWAY: 502,
74
+ SERVICE_UNAVAILABLE: 503,
75
+ GATEWAY_TIMEOUT: 504,
76
+ HTTP_VERSION_NOT_SUPPORTED: 505
109
77
  };
110
- };
111
- }
112
- var get = createRouteDecorator("GET");
113
- var post = createRouteDecorator("POST");
114
- var put = createRouteDecorator("PUT");
115
- var patch = createRouteDecorator("PATCH");
116
- var del = createRouteDecorator("DELETE");
117
- function getControllerPrefix(controllerClass) {
118
- return controllerPrefixMap.get(controllerClass) ?? "";
119
- }
120
- function getControllerRoutes(controllerClass) {
121
- return controllerRoutesMap.get(controllerClass) ?? [];
122
- }
123
-
124
- // src/server/engine/index.ts
125
- import { createServer as createHttpServer } from "http";
78
+ }
79
+ });
126
80
 
127
81
  // src/server/http/headers.ts
128
- var HeadersMap = class {
129
- data;
130
- constructor(initial) {
131
- this.data = /* @__PURE__ */ new Map();
132
- if (initial) {
133
- for (const key of Object.keys(initial)) {
134
- const value = initial[key];
135
- if (value !== void 0) {
136
- this.set(key, Array.isArray(value) ? value.join(", ") : value);
82
+ var HeadersMap;
83
+ var init_headers = __esm({
84
+ "src/server/http/headers.ts"() {
85
+ "use strict";
86
+ HeadersMap = class {
87
+ data;
88
+ constructor(initial) {
89
+ this.data = /* @__PURE__ */ new Map();
90
+ if (initial) {
91
+ for (const key of Object.keys(initial)) {
92
+ const value = initial[key];
93
+ if (value !== void 0) {
94
+ this.set(key, Array.isArray(value) ? value.join(", ") : value);
95
+ }
96
+ }
137
97
  }
138
98
  }
139
- }
140
- }
141
- get(name) {
142
- const values = this.data.get(name.toLowerCase());
143
- if (values !== void 0 && values.length > 0) {
144
- return values[0];
145
- }
146
- return void 0;
147
- }
148
- getAll(name) {
149
- const values = this.data.get(name.toLowerCase());
150
- return values ?? [];
151
- }
152
- set(name, value) {
153
- this.data.set(name.toLowerCase(), [value]);
154
- }
155
- append(name, value) {
156
- const key = name.toLowerCase();
157
- const existing = this.data.get(key);
158
- if (existing !== void 0) {
159
- existing.push(value);
160
- } else {
161
- this.data.set(key, [value]);
162
- }
163
- }
164
- has(name) {
165
- return this.data.has(name.toLowerCase());
166
- }
167
- delete(name) {
168
- this.data.delete(name.toLowerCase());
169
- }
170
- *entries() {
171
- for (const [key, values] of this.data) {
172
- for (const value of values) {
173
- yield [key, value];
99
+ get(name) {
100
+ const values = this.data.get(name.toLowerCase());
101
+ if (values !== void 0 && values.length > 0) {
102
+ return values[0];
103
+ }
104
+ return void 0;
174
105
  }
175
- }
176
- }
177
- *keys() {
178
- for (const key of this.data.keys()) {
179
- yield key;
180
- }
181
- }
182
- *values() {
183
- for (const [, values] of this.data) {
184
- for (const value of values) {
185
- yield value;
106
+ getAll(name) {
107
+ const values = this.data.get(name.toLowerCase());
108
+ return values ?? [];
186
109
  }
187
- }
188
- }
189
- toJSON() {
190
- const result = {};
191
- for (const [key, values] of this.data) {
192
- result[key] = values.length === 1 ? values[0] : values;
193
- }
194
- return result;
195
- }
196
- toNodeHeaders() {
197
- const result = {};
198
- for (const [key, values] of this.data) {
199
- if (key === "set-cookie") {
200
- result[key] = values;
201
- } else {
202
- result[key] = values.join(", ");
110
+ set(name, value) {
111
+ this.data.set(name.toLowerCase(), [value]);
203
112
  }
204
- }
205
- return result;
206
- }
207
- get size() {
208
- return this.data.size;
209
- }
210
- [Symbol.iterator]() {
211
- return this.entries();
113
+ append(name, value) {
114
+ const key = name.toLowerCase();
115
+ const existing = this.data.get(key);
116
+ if (existing !== void 0) {
117
+ existing.push(value);
118
+ } else {
119
+ this.data.set(key, [value]);
120
+ }
121
+ }
122
+ has(name) {
123
+ return this.data.has(name.toLowerCase());
124
+ }
125
+ delete(name) {
126
+ this.data.delete(name.toLowerCase());
127
+ }
128
+ *entries() {
129
+ for (const [key, values] of this.data) {
130
+ for (const value of values) {
131
+ yield [key, value];
132
+ }
133
+ }
134
+ }
135
+ *keys() {
136
+ for (const key of this.data.keys()) {
137
+ yield key;
138
+ }
139
+ }
140
+ *values() {
141
+ for (const [, values] of this.data) {
142
+ for (const value of values) {
143
+ yield value;
144
+ }
145
+ }
146
+ }
147
+ toJSON() {
148
+ const result = {};
149
+ for (const [key, values] of this.data) {
150
+ result[key] = values.length === 1 ? values[0] : values;
151
+ }
152
+ return result;
153
+ }
154
+ toNodeHeaders() {
155
+ const result = {};
156
+ for (const [key, values] of this.data) {
157
+ if (key === "set-cookie") {
158
+ result[key] = values;
159
+ } else {
160
+ result[key] = values.join(", ");
161
+ }
162
+ }
163
+ return result;
164
+ }
165
+ get size() {
166
+ return this.data.size;
167
+ }
168
+ [Symbol.iterator]() {
169
+ return this.entries();
170
+ }
171
+ };
212
172
  }
213
- };
173
+ });
214
174
 
215
175
  // src/server/http/cookie.ts
216
176
  function parseCookies(header) {
@@ -275,296 +235,109 @@ function clearCookie(name, options) {
275
235
  expires: /* @__PURE__ */ new Date(0)
276
236
  });
277
237
  }
238
+ var init_cookie = __esm({
239
+ "src/server/http/cookie.ts"() {
240
+ "use strict";
241
+ }
242
+ });
278
243
 
279
244
  // src/server/http/upload.ts
280
245
  import { randomUUID } from "crypto";
281
246
  import { writeFile, readFile, unlink, mkdir } from "fs/promises";
282
247
  import { join, extname, basename, dirname } from "path";
283
248
  import { tmpdir } from "os";
284
- var IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
285
- "image/jpeg",
286
- "image/png",
287
- "image/gif",
288
- "image/webp",
289
- "image/svg+xml",
290
- "image/bmp",
291
- "image/tiff",
292
- "image/avif"
293
- ]);
294
- var VIDEO_MIME_TYPES = /* @__PURE__ */ new Set([
295
- "video/mp4",
296
- "video/mpeg",
297
- "video/webm",
298
- "video/ogg",
299
- "video/quicktime",
300
- "video/x-msvideo",
301
- "video/x-matroska"
302
- ]);
303
- var SuperUploadedFile = class _SuperUploadedFile {
304
- fieldName;
305
- originalName;
306
- mimeType;
307
- size;
308
- path;
309
- extension;
310
- buffer;
311
- constructor(opts) {
312
- this.fieldName = opts.fieldName;
313
- this.originalName = opts.originalName;
314
- this.mimeType = opts.mimeType;
315
- this.size = opts.size;
316
- this.path = opts.path;
317
- this.extension = extname(opts.originalName).toLowerCase();
318
- this.buffer = opts.buffer ?? null;
319
- }
320
- async move(destination, filename) {
321
- const destName = filename ?? basename(this.path);
322
- const destPath = join(destination, destName);
323
- await mkdir(dirname(destPath), { recursive: true });
324
- const buf = await this.toBuffer();
325
- await writeFile(destPath, buf);
326
- return destPath;
327
- }
328
- async toBuffer() {
329
- if (this.buffer !== null) return this.buffer;
330
- this.buffer = await readFile(this.path);
331
- return this.buffer;
332
- }
333
- toBase64() {
334
- if (this.buffer === null) {
335
- throw new Error(
336
- "Buffer not loaded. Call toBuffer() first or read the file into memory."
337
- );
338
- }
339
- return this.buffer.toString("base64");
340
- }
341
- isImage() {
342
- return IMAGE_MIME_TYPES.has(this.mimeType);
343
- }
344
- isVideo() {
345
- return VIDEO_MIME_TYPES.has(this.mimeType);
346
- }
347
- static async createFromBuffer(fieldName, originalName, mimeType, buffer, tempDir) {
348
- const tmp = tempDir ?? tmpdir();
349
- const fileName = `${randomUUID()}${extname(originalName)}`;
350
- const filePath = join(tmp, fileName);
351
- await writeFile(filePath, buffer);
352
- return new _SuperUploadedFile({
353
- fieldName,
354
- originalName,
355
- mimeType: mimeType || "application/octet-stream",
356
- size: buffer.length,
357
- path: filePath,
358
- buffer
359
- });
360
- }
361
- async cleanup() {
362
- try {
363
- await unlink(this.path);
364
- } catch {
365
- }
366
- }
367
- };
368
-
369
- // src/server/http/request.ts
370
- var SuperRequest = class {
371
- raw;
372
- _headers;
373
- _query;
374
- _cookies = null;
375
- _ip;
376
- _params = {};
377
- bodyCache = null;
378
- _bodyReadPromise = null;
379
- constructor(raw) {
380
- this.raw = raw;
381
- this._headers = new HeadersMap(
382
- raw.headers
383
- );
384
- const parsedUrl = new URL(raw.url ?? "/", "http://localhost");
385
- this._query = parseQueryParams(parsedUrl.searchParams);
386
- this._ip = parseIp(raw);
387
- this.path = parsedUrl.pathname;
388
- this.url = raw.url ?? "/";
389
- this.method = (raw.method ?? "GET").toUpperCase();
390
- }
391
- method;
392
- url;
393
- path;
394
- get headers() {
395
- return this._headers;
396
- }
397
- get query() {
398
- return this._query;
399
- }
400
- get params() {
401
- return this._params;
402
- }
403
- set params(value) {
404
- this._params = value;
405
- }
406
- get ip() {
407
- return this._ip;
408
- }
409
- async ensureBody() {
410
- if (this.bodyCache !== null) return this.bodyCache;
411
- if (this._bodyReadPromise === null) {
412
- this._bodyReadPromise = this.readBodyFromStream();
413
- }
414
- this.bodyCache = await this._bodyReadPromise;
415
- return this.bodyCache;
416
- }
417
- async readBodyFromStream() {
418
- const chunks = [];
419
- for await (const chunk of this.raw) {
420
- chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
421
- }
422
- const raw = Buffer.concat(chunks);
423
- const text = raw.toString("utf-8");
424
- let json = void 0;
425
- if (this.isContentType("application/json")) {
426
- try {
427
- json = JSON.parse(text);
428
- } catch {
429
- json = void 0;
430
- }
431
- }
432
- let formData = null;
433
- let multipartParsed = null;
434
- let files = null;
435
- if (this.isContentType("application/x-www-form-urlencoded")) {
436
- formData = parseUrlEncoded(text);
437
- } else if (this.isContentType("multipart/form-data")) {
438
- const boundary = this.getMultipartBoundary();
439
- if (boundary !== void 0) {
440
- multipartParsed = parseMultipartBody(raw, boundary);
441
- formData = {};
442
- files = {};
443
- for (const part of multipartParsed) {
444
- if (part.type === "field") {
445
- formData[part.name] = part.value;
446
- } else if (part.type === "file") {
447
- const uploadedFile = await SuperUploadedFile.createFromBuffer(
448
- part.name,
449
- part.filename,
450
- part.mimeType,
451
- part.data
452
- );
453
- files[part.name] = uploadedFile;
454
- }
249
+ var IMAGE_MIME_TYPES, VIDEO_MIME_TYPES, SuperUploadedFile;
250
+ var init_upload = __esm({
251
+ "src/server/http/upload.ts"() {
252
+ "use strict";
253
+ IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
254
+ "image/jpeg",
255
+ "image/png",
256
+ "image/gif",
257
+ "image/webp",
258
+ "image/svg+xml",
259
+ "image/bmp",
260
+ "image/tiff",
261
+ "image/avif"
262
+ ]);
263
+ VIDEO_MIME_TYPES = /* @__PURE__ */ new Set([
264
+ "video/mp4",
265
+ "video/mpeg",
266
+ "video/webm",
267
+ "video/ogg",
268
+ "video/quicktime",
269
+ "video/x-msvideo",
270
+ "video/x-matroska"
271
+ ]);
272
+ SuperUploadedFile = class _SuperUploadedFile {
273
+ fieldName;
274
+ originalName;
275
+ mimeType;
276
+ size;
277
+ path;
278
+ extension;
279
+ buffer;
280
+ constructor(opts) {
281
+ this.fieldName = opts.fieldName;
282
+ this.originalName = opts.originalName;
283
+ this.mimeType = opts.mimeType;
284
+ this.size = opts.size;
285
+ this.path = opts.path;
286
+ this.extension = extname(opts.originalName).toLowerCase();
287
+ this.buffer = opts.buffer ?? null;
288
+ }
289
+ async move(destination, filename) {
290
+ const destName = filename ?? basename(this.path);
291
+ const destPath = join(destination, destName);
292
+ await mkdir(dirname(destPath), { recursive: true });
293
+ const buf = await this.toBuffer();
294
+ await writeFile(destPath, buf);
295
+ return destPath;
296
+ }
297
+ async toBuffer() {
298
+ if (this.buffer !== null) return this.buffer;
299
+ this.buffer = await readFile(this.path);
300
+ return this.buffer;
301
+ }
302
+ toBase64() {
303
+ if (this.buffer === null) {
304
+ throw new Error(
305
+ "Buffer not loaded. Call toBuffer() first or read the file into memory."
306
+ );
455
307
  }
308
+ return this.buffer.toString("base64");
456
309
  }
457
- }
458
- return {
459
- raw,
460
- text,
461
- json,
462
- parsed: json ?? text,
463
- formData,
464
- files,
465
- multipartParsed
466
- };
467
- }
468
- isContentType(expected) {
469
- const ct = this._headers.get("content-type");
470
- if (ct === void 0) return false;
471
- return ct.toLowerCase().startsWith(expected);
472
- }
473
- getMultipartBoundary() {
474
- const ct = this._headers.get("content-type");
475
- if (ct === void 0) return void 0;
476
- const match = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
477
- if (match !== null) {
478
- return match[1] ?? match[2];
479
- }
480
- return void 0;
481
- }
482
- async body() {
483
- const cache = await this.ensureBody();
484
- return cache.parsed;
485
- }
486
- async json() {
487
- const cache = await this.ensureBody();
488
- if (cache.json !== void 0) return cache.json;
489
- throw new Error("Request body is not valid JSON");
490
- }
491
- async text() {
492
- const cache = await this.ensureBody();
493
- return cache.text;
494
- }
495
- async formData() {
496
- const cache = await this.ensureBody();
497
- if (cache.formData !== null) return cache.formData;
498
- if (cache.multipartParsed !== null) {
499
- const result = {};
500
- for (const part of cache.multipartParsed) {
501
- if (part.type === "field") {
502
- result[part.name] = part.value;
310
+ isImage() {
311
+ return IMAGE_MIME_TYPES.has(this.mimeType);
312
+ }
313
+ isVideo() {
314
+ return VIDEO_MIME_TYPES.has(this.mimeType);
315
+ }
316
+ static async createFromBuffer(fieldName, originalName, mimeType, buffer, tempDir) {
317
+ const tmp = tempDir ?? tmpdir();
318
+ const fileName = `${randomUUID()}${extname(originalName)}`;
319
+ const filePath = join(tmp, fileName);
320
+ await writeFile(filePath, buffer);
321
+ return new _SuperUploadedFile({
322
+ fieldName,
323
+ originalName,
324
+ mimeType: mimeType || "application/octet-stream",
325
+ size: buffer.length,
326
+ path: filePath,
327
+ buffer
328
+ });
329
+ }
330
+ async cleanup() {
331
+ try {
332
+ await unlink(this.path);
333
+ } catch {
503
334
  }
504
335
  }
505
- return result;
506
- }
507
- return {};
508
- }
509
- async file(name) {
510
- const cache = await this.ensureBody();
511
- if (cache.files !== null) {
512
- return cache.files[name];
513
- }
514
- return void 0;
515
- }
516
- async files() {
517
- const cache = await this.ensureBody();
518
- return cache.files ?? {};
519
- }
520
- cookie(name) {
521
- if (this._cookies === null) {
522
- const cookieHeader = this._headers.get("cookie");
523
- this._cookies = cookieHeader !== void 0 ? parseCookies(cookieHeader) : {};
524
- }
525
- return this._cookies[name];
526
- }
527
- async validate(schema) {
528
- const data = await this.body();
529
- const result = schema.validate(data);
530
- if (!result.success) {
531
- const messages = (result.errors ?? []).map((e) => {
532
- const path3 = e.path ?? "";
533
- return path3 ? `${path3}: ${e.message}` : e.message;
534
- }).join("; ");
535
- throw new ValidationError(messages, result.errors ?? []);
536
- }
537
- return result.data;
538
- }
539
- isAjax() {
540
- const requestedWith = this._headers.get("x-requested-with");
541
- return requestedWith?.toLowerCase() === "xmlhttprequest";
542
- }
543
- wantsJson() {
544
- const accept = this._headers.get("accept");
545
- if (accept !== void 0 && accept.includes("application/json")) {
546
- return true;
547
- }
548
- return this.isAjax();
549
- }
550
- bearerToken() {
551
- const auth = this._headers.get("authorization");
552
- if (auth === void 0) return void 0;
553
- const match = auth.match(/^Bearer\s+(.+)$/i);
554
- return match?.[1];
555
- }
556
- get rawRequest() {
557
- return this.raw;
558
- }
559
- };
560
- var ValidationError = class extends Error {
561
- constructor(message, errors) {
562
- super(message);
563
- this.errors = errors;
564
- this.name = "ValidationError";
336
+ };
565
337
  }
566
- errors;
567
- };
338
+ });
339
+
340
+ // src/server/http/request.ts
568
341
  function parseQueryParams(searchParams) {
569
342
  const result = {};
570
343
  for (const key of searchParams.keys()) {
@@ -679,225 +452,1449 @@ function parseContentType(headerSection) {
679
452
  const match = headerSection.match(/content-type:\s*([^\s;]+)/i);
680
453
  return match?.[1] ?? "application/octet-stream";
681
454
  }
455
+ var SuperRequest, ValidationError;
456
+ var init_request = __esm({
457
+ "src/server/http/request.ts"() {
458
+ "use strict";
459
+ init_headers();
460
+ init_cookie();
461
+ init_upload();
462
+ SuperRequest = class {
463
+ raw;
464
+ _headers;
465
+ _query;
466
+ _cookies = null;
467
+ _ip;
468
+ _params = {};
469
+ bodyCache = null;
470
+ _bodyReadPromise = null;
471
+ constructor(raw) {
472
+ this.raw = raw;
473
+ this._headers = new HeadersMap(
474
+ raw.headers
475
+ );
476
+ const parsedUrl = new URL(raw.url ?? "/", "http://localhost");
477
+ this._query = parseQueryParams(parsedUrl.searchParams);
478
+ this._ip = parseIp(raw);
479
+ this.path = parsedUrl.pathname;
480
+ this.url = raw.url ?? "/";
481
+ this.method = (raw.method ?? "GET").toUpperCase();
482
+ }
483
+ method;
484
+ url;
485
+ path;
486
+ get headers() {
487
+ return this._headers;
488
+ }
489
+ get query() {
490
+ return this._query;
491
+ }
492
+ get params() {
493
+ return this._params;
494
+ }
495
+ set params(value) {
496
+ this._params = value;
497
+ }
498
+ get ip() {
499
+ return this._ip;
500
+ }
501
+ async ensureBody() {
502
+ if (this.bodyCache !== null) return this.bodyCache;
503
+ if (this._bodyReadPromise === null) {
504
+ this._bodyReadPromise = this.readBodyFromStream();
505
+ }
506
+ this.bodyCache = await this._bodyReadPromise;
507
+ return this.bodyCache;
508
+ }
509
+ async readBodyFromStream() {
510
+ const chunks = [];
511
+ const MAX_BODY_SIZE = 10 * 1024 * 1024;
512
+ let totalSize = 0;
513
+ for await (const chunk of this.raw) {
514
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
515
+ totalSize += buf.length;
516
+ if (totalSize > MAX_BODY_SIZE) {
517
+ throw new Error("Request body too large. Maximum size is 10MB.");
518
+ }
519
+ chunks.push(buf);
520
+ }
521
+ const raw = Buffer.concat(chunks);
522
+ const text = raw.toString("utf-8");
523
+ let json = void 0;
524
+ if (this.isContentType("application/json")) {
525
+ try {
526
+ json = JSON.parse(text);
527
+ } catch {
528
+ json = void 0;
529
+ }
530
+ }
531
+ let formData = null;
532
+ let multipartParsed = null;
533
+ let files = null;
534
+ if (this.isContentType("application/x-www-form-urlencoded")) {
535
+ formData = parseUrlEncoded(text);
536
+ } else if (this.isContentType("multipart/form-data")) {
537
+ const boundary = this.getMultipartBoundary();
538
+ if (boundary !== void 0) {
539
+ multipartParsed = parseMultipartBody(raw, boundary);
540
+ formData = {};
541
+ files = {};
542
+ for (const part of multipartParsed) {
543
+ if (part.type === "field") {
544
+ formData[part.name] = part.value;
545
+ } else if (part.type === "file") {
546
+ const uploadedFile = await SuperUploadedFile.createFromBuffer(
547
+ part.name,
548
+ part.filename,
549
+ part.mimeType,
550
+ part.data
551
+ );
552
+ files[part.name] = uploadedFile;
553
+ }
554
+ }
555
+ }
556
+ }
557
+ return {
558
+ raw,
559
+ text,
560
+ json,
561
+ parsed: json ?? text,
562
+ formData,
563
+ files,
564
+ multipartParsed
565
+ };
566
+ }
567
+ isContentType(expected) {
568
+ const ct = this._headers.get("content-type");
569
+ if (ct === void 0) return false;
570
+ return ct.toLowerCase().startsWith(expected);
571
+ }
572
+ getMultipartBoundary() {
573
+ const ct = this._headers.get("content-type");
574
+ if (ct === void 0) return void 0;
575
+ const match = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
576
+ if (match !== null) {
577
+ return match[1] ?? match[2];
578
+ }
579
+ return void 0;
580
+ }
581
+ async body() {
582
+ const cache = await this.ensureBody();
583
+ return cache.parsed;
584
+ }
585
+ async json() {
586
+ const cache = await this.ensureBody();
587
+ if (cache.json !== void 0) return cache.json;
588
+ throw new Error("Request body is not valid JSON");
589
+ }
590
+ async text() {
591
+ const cache = await this.ensureBody();
592
+ return cache.text;
593
+ }
594
+ async formData() {
595
+ const cache = await this.ensureBody();
596
+ if (cache.formData !== null) return cache.formData;
597
+ if (cache.multipartParsed !== null) {
598
+ const result = {};
599
+ for (const part of cache.multipartParsed) {
600
+ if (part.type === "field") {
601
+ result[part.name] = part.value;
602
+ }
603
+ }
604
+ return result;
605
+ }
606
+ return {};
607
+ }
608
+ async file(name) {
609
+ const cache = await this.ensureBody();
610
+ if (cache.files !== null) {
611
+ return cache.files[name];
612
+ }
613
+ return void 0;
614
+ }
615
+ async files() {
616
+ const cache = await this.ensureBody();
617
+ return cache.files ?? {};
618
+ }
619
+ cookie(name) {
620
+ if (this._cookies === null) {
621
+ const cookieHeader = this._headers.get("cookie");
622
+ this._cookies = cookieHeader !== void 0 ? parseCookies(cookieHeader) : {};
623
+ }
624
+ return this._cookies[name];
625
+ }
626
+ async validate(schema) {
627
+ const data = await this.body();
628
+ const result = schema.validate(data);
629
+ if (!result.success) {
630
+ const messages = (result.errors ?? []).map((e) => {
631
+ const path3 = e.path ?? "";
632
+ return path3 ? `${path3}: ${e.message}` : e.message;
633
+ }).join("; ");
634
+ throw new ValidationError(messages, result.errors ?? []);
635
+ }
636
+ return result.data;
637
+ }
638
+ isAjax() {
639
+ const requestedWith = this._headers.get("x-requested-with");
640
+ return requestedWith?.toLowerCase() === "xmlhttprequest";
641
+ }
642
+ wantsJson() {
643
+ const accept = this._headers.get("accept");
644
+ if (accept !== void 0 && accept.includes("application/json")) {
645
+ return true;
646
+ }
647
+ return this.isAjax();
648
+ }
649
+ bearerToken() {
650
+ const auth = this._headers.get("authorization");
651
+ if (auth === void 0) return void 0;
652
+ const match = auth.match(/^Bearer\s+(.+)$/i);
653
+ return match?.[1];
654
+ }
655
+ get rawRequest() {
656
+ return this.raw;
657
+ }
658
+ };
659
+ ValidationError = class extends Error {
660
+ constructor(message, errors) {
661
+ super(message);
662
+ this.errors = errors;
663
+ this.name = "ValidationError";
664
+ }
665
+ errors;
666
+ };
667
+ }
668
+ });
682
669
 
683
670
  // src/server/http/response.ts
684
671
  import { createReadStream, stat } from "fs";
685
- import { basename as basename2, extname as extname2 } from "path";
672
+ import { basename as basename2, extname as extname2, resolve } from "path";
686
673
  import { promisify } from "util";
687
- var statAsync = promisify(stat);
688
- var MIME_TYPES = {
689
- ".html": "text/html",
690
- ".css": "text/css",
691
- ".js": "application/javascript",
692
- ".mjs": "application/javascript",
693
- ".json": "application/json",
694
- ".png": "image/png",
695
- ".jpg": "image/jpeg",
696
- ".jpeg": "image/jpeg",
697
- ".gif": "image/gif",
698
- ".svg": "image/svg+xml",
699
- ".webp": "image/webp",
700
- ".ico": "image/x-icon",
701
- ".pdf": "application/pdf",
702
- ".txt": "text/plain",
703
- ".xml": "application/xml",
704
- ".zip": "application/zip",
705
- ".woff": "font/woff",
706
- ".woff2": "font/woff2",
707
- ".ttf": "font/ttf",
708
- ".eot": "application/vnd.ms-fontobject",
709
- ".mp4": "video/mp4",
710
- ".webm": "video/webm",
711
- ".mp3": "audio/mpeg",
712
- ".wav": "audio/wav"
713
- };
714
- var SuperResponse = class {
715
- raw;
716
- _statusCode = HttpStatus.OK;
717
- _headers = new HeadersMap();
718
- _cookies = [];
719
- _body = null;
720
- _sent = false;
721
- _contentTypeSet = false;
722
- constructor(raw) {
723
- this.raw = raw;
724
- }
725
- status(code) {
726
- this._statusCode = code;
727
- return this;
674
+ function joinPath(root, filePath) {
675
+ const normalizedRoot = root.replace(/\\/g, "/").replace(/\/$/, "");
676
+ const normalizedPath = filePath.replace(/\\/g, "/").replace(/^\//, "");
677
+ return `${normalizedRoot}/${normalizedPath}`;
678
+ }
679
+ var statAsync, MIME_TYPES, SuperResponse;
680
+ var init_response = __esm({
681
+ "src/server/http/response.ts"() {
682
+ "use strict";
683
+ init_cookie();
684
+ init_headers();
685
+ init_status();
686
+ statAsync = promisify(stat);
687
+ MIME_TYPES = {
688
+ ".html": "text/html",
689
+ ".css": "text/css",
690
+ ".js": "application/javascript",
691
+ ".mjs": "application/javascript",
692
+ ".json": "application/json",
693
+ ".png": "image/png",
694
+ ".jpg": "image/jpeg",
695
+ ".jpeg": "image/jpeg",
696
+ ".gif": "image/gif",
697
+ ".svg": "image/svg+xml",
698
+ ".webp": "image/webp",
699
+ ".ico": "image/x-icon",
700
+ ".pdf": "application/pdf",
701
+ ".txt": "text/plain",
702
+ ".xml": "application/xml",
703
+ ".zip": "application/zip",
704
+ ".woff": "font/woff",
705
+ ".woff2": "font/woff2",
706
+ ".ttf": "font/ttf",
707
+ ".eot": "application/vnd.ms-fontobject",
708
+ ".mp4": "video/mp4",
709
+ ".webm": "video/webm",
710
+ ".mp3": "audio/mpeg",
711
+ ".wav": "audio/wav"
712
+ };
713
+ SuperResponse = class {
714
+ raw;
715
+ _statusCode = HttpStatus.OK;
716
+ _headers = new HeadersMap();
717
+ _cookies = [];
718
+ _body = null;
719
+ _sent = false;
720
+ _contentTypeSet = false;
721
+ constructor(raw) {
722
+ this.raw = raw;
723
+ }
724
+ status(code) {
725
+ this._statusCode = code;
726
+ return this;
727
+ }
728
+ header(name, value) {
729
+ this._headers.set(name, value);
730
+ return this;
731
+ }
732
+ setHeader(name, value) {
733
+ return this.header(name, value);
734
+ }
735
+ getHeader(name) {
736
+ return this._headers.get(name);
737
+ }
738
+ removeHeader(name) {
739
+ this._headers.delete(name);
740
+ return this;
741
+ }
742
+ hasHeader(name) {
743
+ return this._headers.has(name);
744
+ }
745
+ type(contentType) {
746
+ this._headers.set("content-type", contentType);
747
+ this._contentTypeSet = true;
748
+ return this;
749
+ }
750
+ json(data, status) {
751
+ if (status !== void 0) this._statusCode = status;
752
+ const body = JSON.stringify(data);
753
+ return this.send(body, void 0, "application/json");
754
+ }
755
+ send(body, status, contentType) {
756
+ if (status !== void 0) this._statusCode = status;
757
+ this._body = body;
758
+ if (contentType !== void 0 && !this._contentTypeSet) {
759
+ this._headers.set("content-type", contentType);
760
+ }
761
+ return this;
762
+ }
763
+ html(html, status) {
764
+ return this.send(html, status, "text/html; charset=utf-8");
765
+ }
766
+ redirect(url2, status = HttpStatus.FOUND) {
767
+ if (url2.includes("\r") || url2.includes("\n")) {
768
+ throw new Error("Invalid redirect URL");
769
+ }
770
+ this._statusCode = status;
771
+ this._headers.set("location", url2);
772
+ this._body = null;
773
+ return this;
774
+ }
775
+ stream(stream, status) {
776
+ if (status !== void 0) this._statusCode = status;
777
+ this.flushHeaders();
778
+ this.raw.statusCode = this._statusCode;
779
+ stream.pipe(this.raw);
780
+ stream.on("end", () => {
781
+ this._sent = true;
782
+ });
783
+ stream.on("error", (_err) => {
784
+ if (!this._sent) {
785
+ this._sent = true;
786
+ this.raw.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
787
+ this.raw.end();
788
+ }
789
+ });
790
+ return this;
791
+ }
792
+ async file(filePath, options) {
793
+ const fullPath = options?.root ? joinPath(options.root, filePath) : filePath;
794
+ const resolved = resolve(fullPath);
795
+ const root = options?.root ? resolve(options.root) : null;
796
+ if (root !== null && !resolved.startsWith(root)) {
797
+ this._statusCode = HttpStatus.FORBIDDEN;
798
+ this._body = null;
799
+ return this;
800
+ }
801
+ try {
802
+ const stats = await statAsync(fullPath);
803
+ if (!stats.isFile()) {
804
+ this._statusCode = HttpStatus.NOT_FOUND;
805
+ this._body = null;
806
+ return this;
807
+ }
808
+ const ext = extname2(fullPath);
809
+ const mimeType = MIME_TYPES[ext] ?? "application/octet-stream";
810
+ this._headers.set("content-type", mimeType);
811
+ this._headers.set("content-length", String(stats.size));
812
+ if (options?.cacheControl !== false) {
813
+ const maxAge = options?.maxAge ?? 0;
814
+ this._headers.set("cache-control", `public, max-age=${maxAge}`);
815
+ }
816
+ if (options?.lastModified !== false) {
817
+ this._headers.set("last-modified", stats.mtime.toUTCString());
818
+ }
819
+ if (options?.headers !== void 0) {
820
+ for (const [key, value] of Object.entries(options.headers)) {
821
+ this._headers.set(key, value);
822
+ }
823
+ }
824
+ this.flushHeaders();
825
+ this.raw.statusCode = this._statusCode;
826
+ const readStream = createReadStream(fullPath);
827
+ readStream.pipe(this.raw);
828
+ readStream.on("end", () => {
829
+ this._sent = true;
830
+ });
831
+ readStream.on("error", () => {
832
+ if (!this._sent) {
833
+ this._sent = true;
834
+ this.raw.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
835
+ this.raw.end();
836
+ }
837
+ });
838
+ } catch {
839
+ this._statusCode = HttpStatus.NOT_FOUND;
840
+ this._body = null;
841
+ }
842
+ return this;
843
+ }
844
+ async download(filePath, filename) {
845
+ const downloadName = filename ?? basename2(filePath);
846
+ this._headers.set(
847
+ "content-disposition",
848
+ `attachment; filename="${downloadName}"`
849
+ );
850
+ await this.file(filePath);
851
+ return this;
852
+ }
853
+ attachment(filename) {
854
+ if (filename !== void 0) {
855
+ this._headers.set(
856
+ "content-disposition",
857
+ `attachment; filename="${filename}"`
858
+ );
859
+ } else {
860
+ this._headers.set("content-disposition", "attachment");
861
+ }
862
+ return this;
863
+ }
864
+ cookie(name, value, options) {
865
+ this._cookies.push(serializeCookie(name, value, options));
866
+ return this;
867
+ }
868
+ clearCookie(name, options) {
869
+ this._cookies.push(clearCookie(name, options));
870
+ return this;
871
+ }
872
+ get statusCode() {
873
+ return this._statusCode;
874
+ }
875
+ get headersSent() {
876
+ return this._sent;
877
+ }
878
+ get rawResponse() {
879
+ return this.raw;
880
+ }
881
+ async flush() {
882
+ if (this._sent) return;
883
+ this._sent = true;
884
+ this.flushHeaders();
885
+ this.raw.statusCode = this._statusCode;
886
+ if (this._body !== null) {
887
+ this.raw.end(this._body);
888
+ } else {
889
+ this.raw.end();
890
+ }
891
+ }
892
+ flushHeaders() {
893
+ if (this._cookies.length > 0) {
894
+ this.raw.setHeader("Set-Cookie", this._cookies);
895
+ }
896
+ for (const [name, value] of this._headers.entries()) {
897
+ if (name.toLowerCase() !== "set-cookie") {
898
+ this.raw.setHeader(name, value);
899
+ }
900
+ }
901
+ }
902
+ };
728
903
  }
729
- header(name, value) {
730
- this._headers.set(name, value);
731
- return this;
904
+ });
905
+
906
+ // src/server/errors.ts
907
+ function registerExceptionHandler(exceptionType, handler) {
908
+ exceptionHandlers.set(exceptionType, handler);
909
+ }
910
+ function getDefaultErrorName(status) {
911
+ const names = {
912
+ 400: "BAD_REQUEST",
913
+ 401: "UNAUTHORIZED",
914
+ 403: "FORBIDDEN",
915
+ 404: "NOT_FOUND",
916
+ 405: "METHOD_NOT_ALLOWED",
917
+ 409: "CONFLICT",
918
+ 422: "UNPROCESSABLE_ENTITY",
919
+ 429: "TOO_MANY_REQUESTS",
920
+ 500: "INTERNAL_SERVER_ERROR",
921
+ 503: "SERVICE_UNAVAILABLE"
922
+ };
923
+ return names[status] ?? "UNKNOWN_ERROR";
924
+ }
925
+ function normalizeError(_err) {
926
+ const err = _err instanceof Error ? _err : new Error(String(_err));
927
+ if (err instanceof HttpException) {
928
+ const handler = exceptionHandlers.get(err.constructor);
929
+ if (handler !== void 0) {
930
+ const result = handler(err);
931
+ if (result instanceof Promise) {
932
+ return result;
933
+ }
934
+ return result;
935
+ }
936
+ return err;
732
937
  }
733
- setHeader(name, value) {
734
- return this.header(name, value);
938
+ if (process.env.NODE_ENV === "production") {
939
+ return new InternalServerErrorException();
735
940
  }
736
- getHeader(name) {
737
- return this._headers.get(name);
941
+ return new InternalServerErrorException(err.message);
942
+ }
943
+ var HttpException, BadRequestException, UnauthorizedException, ForbiddenException, NotFoundException, MethodNotAllowedException, ConflictException, UnprocessableEntityException, TooManyRequestsException, InternalServerErrorException, ServiceUnavailableException, ValidationException, exceptionHandlers;
944
+ var init_errors = __esm({
945
+ "src/server/errors.ts"() {
946
+ "use strict";
947
+ HttpException = class extends Error {
948
+ status;
949
+ error;
950
+ constructor(message, status = 500, error) {
951
+ super(message);
952
+ this.name = "HttpException";
953
+ this.status = status;
954
+ this.error = error ?? getDefaultErrorName(status);
955
+ }
956
+ toJSON() {
957
+ return {
958
+ error: this.error,
959
+ message: this.message,
960
+ statusCode: this.status
961
+ };
962
+ }
963
+ };
964
+ BadRequestException = class extends HttpException {
965
+ constructor(message = "Bad Request") {
966
+ super(message, 400, "BAD_REQUEST");
967
+ }
968
+ };
969
+ UnauthorizedException = class extends HttpException {
970
+ constructor(message = "Unauthorized") {
971
+ super(message, 401, "UNAUTHORIZED");
972
+ }
973
+ };
974
+ ForbiddenException = class extends HttpException {
975
+ constructor(message = "Forbidden") {
976
+ super(message, 403, "FORBIDDEN");
977
+ }
978
+ };
979
+ NotFoundException = class extends HttpException {
980
+ constructor(message = "Not Found") {
981
+ super(message, 404, "NOT_FOUND");
982
+ }
983
+ };
984
+ MethodNotAllowedException = class extends HttpException {
985
+ constructor(message = "Method Not Allowed") {
986
+ super(message, 405, "METHOD_NOT_ALLOWED");
987
+ }
988
+ };
989
+ ConflictException = class extends HttpException {
990
+ constructor(message = "Conflict") {
991
+ super(message, 409, "CONFLICT");
992
+ }
993
+ };
994
+ UnprocessableEntityException = class extends HttpException {
995
+ constructor(message = "Unprocessable Entity") {
996
+ super(message, 422, "UNPROCESSABLE_ENTITY");
997
+ }
998
+ };
999
+ TooManyRequestsException = class extends HttpException {
1000
+ constructor(message = "Too Many Requests") {
1001
+ super(message, 429, "TOO_MANY_REQUESTS");
1002
+ }
1003
+ };
1004
+ InternalServerErrorException = class extends HttpException {
1005
+ constructor(message = "Internal Server Error") {
1006
+ super(message, 500, "INTERNAL_SERVER_ERROR");
1007
+ }
1008
+ };
1009
+ ServiceUnavailableException = class extends HttpException {
1010
+ constructor(message = "Service Unavailable") {
1011
+ super(message, 503, "SERVICE_UNAVAILABLE");
1012
+ }
1013
+ };
1014
+ ValidationException = class extends HttpException {
1015
+ errors;
1016
+ constructor(errors, message = "Validation Failed") {
1017
+ super(message, 422, "VALIDATION_ERROR");
1018
+ this.errors = errors;
1019
+ }
1020
+ toJSON() {
1021
+ return {
1022
+ error: this.error,
1023
+ message: this.message,
1024
+ statusCode: this.status,
1025
+ errors: this.errors
1026
+ };
1027
+ }
1028
+ };
1029
+ exceptionHandlers = /* @__PURE__ */ new Map();
738
1030
  }
739
- removeHeader(name) {
740
- this._headers.delete(name);
741
- return this;
1031
+ });
1032
+
1033
+ // node_modules/better-sqlite3/lib/util.js
1034
+ var require_util = __commonJS({
1035
+ "node_modules/better-sqlite3/lib/util.js"(exports) {
1036
+ "use strict";
1037
+ exports.getBooleanOption = (options, key) => {
1038
+ let value = false;
1039
+ if (key in options && typeof (value = options[key]) !== "boolean") {
1040
+ throw new TypeError(`Expected the "${key}" option to be a boolean`);
1041
+ }
1042
+ return value;
1043
+ };
1044
+ exports.cppdb = /* @__PURE__ */ Symbol();
1045
+ exports.inspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
742
1046
  }
743
- hasHeader(name) {
744
- return this._headers.has(name);
1047
+ });
1048
+
1049
+ // node_modules/better-sqlite3/lib/sqlite-error.js
1050
+ var require_sqlite_error = __commonJS({
1051
+ "node_modules/better-sqlite3/lib/sqlite-error.js"(exports, module) {
1052
+ "use strict";
1053
+ var descriptor = { value: "SqliteError", writable: true, enumerable: false, configurable: true };
1054
+ function SqliteError(message, code) {
1055
+ if (new.target !== SqliteError) {
1056
+ return new SqliteError(message, code);
1057
+ }
1058
+ if (typeof code !== "string") {
1059
+ throw new TypeError("Expected second argument to be a string");
1060
+ }
1061
+ Error.call(this, message);
1062
+ descriptor.value = "" + message;
1063
+ Object.defineProperty(this, "message", descriptor);
1064
+ Error.captureStackTrace(this, SqliteError);
1065
+ this.code = code;
1066
+ }
1067
+ Object.setPrototypeOf(SqliteError, Error);
1068
+ Object.setPrototypeOf(SqliteError.prototype, Error.prototype);
1069
+ Object.defineProperty(SqliteError.prototype, "name", descriptor);
1070
+ module.exports = SqliteError;
745
1071
  }
746
- type(contentType) {
747
- this._headers.set("content-type", contentType);
748
- this._contentTypeSet = true;
749
- return this;
1072
+ });
1073
+
1074
+ // node_modules/file-uri-to-path/index.js
1075
+ var require_file_uri_to_path = __commonJS({
1076
+ "node_modules/file-uri-to-path/index.js"(exports, module) {
1077
+ "use strict";
1078
+ var sep = __require("path").sep || "/";
1079
+ module.exports = fileUriToPath;
1080
+ function fileUriToPath(uri) {
1081
+ if ("string" != typeof uri || uri.length <= 7 || "file://" != uri.substring(0, 7)) {
1082
+ throw new TypeError("must pass in a file:// URI to convert to a file path");
1083
+ }
1084
+ var rest = decodeURI(uri.substring(7));
1085
+ var firstSlash = rest.indexOf("/");
1086
+ var host = rest.substring(0, firstSlash);
1087
+ var path3 = rest.substring(firstSlash + 1);
1088
+ if ("localhost" == host) host = "";
1089
+ if (host) {
1090
+ host = sep + sep + host;
1091
+ }
1092
+ path3 = path3.replace(/^(.+)\|/, "$1:");
1093
+ if (sep == "\\") {
1094
+ path3 = path3.replace(/\//g, "\\");
1095
+ }
1096
+ if (/^.+\:/.test(path3)) {
1097
+ } else {
1098
+ path3 = sep + path3;
1099
+ }
1100
+ return host + path3;
1101
+ }
1102
+ }
1103
+ });
1104
+
1105
+ // node_modules/bindings/bindings.js
1106
+ var require_bindings = __commonJS({
1107
+ "node_modules/bindings/bindings.js"(exports, module) {
1108
+ "use strict";
1109
+ var fs3 = __require("fs");
1110
+ var path3 = __require("path");
1111
+ var fileURLToPath = require_file_uri_to_path();
1112
+ var join5 = path3.join;
1113
+ var dirname4 = path3.dirname;
1114
+ var exists = fs3.accessSync && function(path4) {
1115
+ try {
1116
+ fs3.accessSync(path4);
1117
+ } catch (e) {
1118
+ return false;
1119
+ }
1120
+ return true;
1121
+ } || fs3.existsSync || path3.existsSync;
1122
+ var defaults = {
1123
+ arrow: process.env.NODE_BINDINGS_ARROW || " \u2192 ",
1124
+ compiled: process.env.NODE_BINDINGS_COMPILED_DIR || "compiled",
1125
+ platform: process.platform,
1126
+ arch: process.arch,
1127
+ nodePreGyp: "node-v" + process.versions.modules + "-" + process.platform + "-" + process.arch,
1128
+ version: process.versions.node,
1129
+ bindings: "bindings.node",
1130
+ try: [
1131
+ // node-gyp's linked version in the "build" dir
1132
+ ["module_root", "build", "bindings"],
1133
+ // node-waf and gyp_addon (a.k.a node-gyp)
1134
+ ["module_root", "build", "Debug", "bindings"],
1135
+ ["module_root", "build", "Release", "bindings"],
1136
+ // Debug files, for development (legacy behavior, remove for node v0.9)
1137
+ ["module_root", "out", "Debug", "bindings"],
1138
+ ["module_root", "Debug", "bindings"],
1139
+ // Release files, but manually compiled (legacy behavior, remove for node v0.9)
1140
+ ["module_root", "out", "Release", "bindings"],
1141
+ ["module_root", "Release", "bindings"],
1142
+ // Legacy from node-waf, node <= 0.4.x
1143
+ ["module_root", "build", "default", "bindings"],
1144
+ // Production "Release" buildtype binary (meh...)
1145
+ ["module_root", "compiled", "version", "platform", "arch", "bindings"],
1146
+ // node-qbs builds
1147
+ ["module_root", "addon-build", "release", "install-root", "bindings"],
1148
+ ["module_root", "addon-build", "debug", "install-root", "bindings"],
1149
+ ["module_root", "addon-build", "default", "install-root", "bindings"],
1150
+ // node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch}
1151
+ ["module_root", "lib", "binding", "nodePreGyp", "bindings"]
1152
+ ]
1153
+ };
1154
+ function bindings(opts) {
1155
+ if (typeof opts == "string") {
1156
+ opts = { bindings: opts };
1157
+ } else if (!opts) {
1158
+ opts = {};
1159
+ }
1160
+ Object.keys(defaults).map(function(i2) {
1161
+ if (!(i2 in opts)) opts[i2] = defaults[i2];
1162
+ });
1163
+ if (!opts.module_root) {
1164
+ opts.module_root = exports.getRoot(exports.getFileName());
1165
+ }
1166
+ if (path3.extname(opts.bindings) != ".node") {
1167
+ opts.bindings += ".node";
1168
+ }
1169
+ var requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
1170
+ var tries = [], i = 0, l = opts.try.length, n, b, err;
1171
+ for (; i < l; i++) {
1172
+ n = join5.apply(
1173
+ null,
1174
+ opts.try[i].map(function(p) {
1175
+ return opts[p] || p;
1176
+ })
1177
+ );
1178
+ tries.push(n);
1179
+ try {
1180
+ b = opts.path ? requireFunc.resolve(n) : requireFunc(n);
1181
+ if (!opts.path) {
1182
+ b.path = n;
1183
+ }
1184
+ return b;
1185
+ } catch (e) {
1186
+ if (e.code !== "MODULE_NOT_FOUND" && e.code !== "QUALIFIED_PATH_RESOLUTION_FAILED" && !/not find/i.test(e.message)) {
1187
+ throw e;
1188
+ }
1189
+ }
1190
+ }
1191
+ err = new Error(
1192
+ "Could not locate the bindings file. Tried:\n" + tries.map(function(a) {
1193
+ return opts.arrow + a;
1194
+ }).join("\n")
1195
+ );
1196
+ err.tries = tries;
1197
+ throw err;
1198
+ }
1199
+ module.exports = exports = bindings;
1200
+ exports.getFileName = function getFileName(calling_file) {
1201
+ var origPST = Error.prepareStackTrace, origSTL = Error.stackTraceLimit, dummy = {}, fileName;
1202
+ Error.stackTraceLimit = 10;
1203
+ Error.prepareStackTrace = function(e, st) {
1204
+ for (var i = 0, l = st.length; i < l; i++) {
1205
+ fileName = st[i].getFileName();
1206
+ if (fileName !== __filename) {
1207
+ if (calling_file) {
1208
+ if (fileName !== calling_file) {
1209
+ return;
1210
+ }
1211
+ } else {
1212
+ return;
1213
+ }
1214
+ }
1215
+ }
1216
+ };
1217
+ Error.captureStackTrace(dummy);
1218
+ dummy.stack;
1219
+ Error.prepareStackTrace = origPST;
1220
+ Error.stackTraceLimit = origSTL;
1221
+ var fileSchema = "file://";
1222
+ if (fileName.indexOf(fileSchema) === 0) {
1223
+ fileName = fileURLToPath(fileName);
1224
+ }
1225
+ return fileName;
1226
+ };
1227
+ exports.getRoot = function getRoot(file) {
1228
+ var dir = dirname4(file), prev;
1229
+ while (true) {
1230
+ if (dir === ".") {
1231
+ dir = process.cwd();
1232
+ }
1233
+ if (exists(join5(dir, "package.json")) || exists(join5(dir, "node_modules"))) {
1234
+ return dir;
1235
+ }
1236
+ if (prev === dir) {
1237
+ throw new Error(
1238
+ 'Could not find module root given file: "' + file + '". Do you have a `package.json` file? '
1239
+ );
1240
+ }
1241
+ prev = dir;
1242
+ dir = join5(dir, "..");
1243
+ }
1244
+ };
1245
+ }
1246
+ });
1247
+
1248
+ // node_modules/better-sqlite3/lib/methods/wrappers.js
1249
+ var require_wrappers = __commonJS({
1250
+ "node_modules/better-sqlite3/lib/methods/wrappers.js"(exports) {
1251
+ "use strict";
1252
+ var { cppdb } = require_util();
1253
+ exports.prepare = function prepare(sql) {
1254
+ return this[cppdb].prepare(sql, this, false);
1255
+ };
1256
+ exports.exec = function exec(sql) {
1257
+ this[cppdb].exec(sql);
1258
+ return this;
1259
+ };
1260
+ exports.close = function close() {
1261
+ this[cppdb].close();
1262
+ return this;
1263
+ };
1264
+ exports.loadExtension = function loadExtension(...args) {
1265
+ this[cppdb].loadExtension(...args);
1266
+ return this;
1267
+ };
1268
+ exports.defaultSafeIntegers = function defaultSafeIntegers(...args) {
1269
+ this[cppdb].defaultSafeIntegers(...args);
1270
+ return this;
1271
+ };
1272
+ exports.unsafeMode = function unsafeMode(...args) {
1273
+ this[cppdb].unsafeMode(...args);
1274
+ return this;
1275
+ };
1276
+ exports.getters = {
1277
+ name: {
1278
+ get: function name() {
1279
+ return this[cppdb].name;
1280
+ },
1281
+ enumerable: true
1282
+ },
1283
+ open: {
1284
+ get: function open() {
1285
+ return this[cppdb].open;
1286
+ },
1287
+ enumerable: true
1288
+ },
1289
+ inTransaction: {
1290
+ get: function inTransaction() {
1291
+ return this[cppdb].inTransaction;
1292
+ },
1293
+ enumerable: true
1294
+ },
1295
+ readonly: {
1296
+ get: function readonly() {
1297
+ return this[cppdb].readonly;
1298
+ },
1299
+ enumerable: true
1300
+ },
1301
+ memory: {
1302
+ get: function memory() {
1303
+ return this[cppdb].memory;
1304
+ },
1305
+ enumerable: true
1306
+ }
1307
+ };
1308
+ }
1309
+ });
1310
+
1311
+ // node_modules/better-sqlite3/lib/methods/transaction.js
1312
+ var require_transaction = __commonJS({
1313
+ "node_modules/better-sqlite3/lib/methods/transaction.js"(exports, module) {
1314
+ "use strict";
1315
+ var { cppdb } = require_util();
1316
+ var controllers = /* @__PURE__ */ new WeakMap();
1317
+ module.exports = function transaction(fn) {
1318
+ if (typeof fn !== "function") throw new TypeError("Expected first argument to be a function");
1319
+ const db = this[cppdb];
1320
+ const controller = getController(db, this);
1321
+ const { apply } = Function.prototype;
1322
+ const properties = {
1323
+ default: { value: wrapTransaction(apply, fn, db, controller.default) },
1324
+ deferred: { value: wrapTransaction(apply, fn, db, controller.deferred) },
1325
+ immediate: { value: wrapTransaction(apply, fn, db, controller.immediate) },
1326
+ exclusive: { value: wrapTransaction(apply, fn, db, controller.exclusive) },
1327
+ database: { value: this, enumerable: true }
1328
+ };
1329
+ Object.defineProperties(properties.default.value, properties);
1330
+ Object.defineProperties(properties.deferred.value, properties);
1331
+ Object.defineProperties(properties.immediate.value, properties);
1332
+ Object.defineProperties(properties.exclusive.value, properties);
1333
+ return properties.default.value;
1334
+ };
1335
+ var getController = (db, self) => {
1336
+ let controller = controllers.get(db);
1337
+ if (!controller) {
1338
+ const shared = {
1339
+ commit: db.prepare("COMMIT", self, false),
1340
+ rollback: db.prepare("ROLLBACK", self, false),
1341
+ savepoint: db.prepare("SAVEPOINT ` _bs3. `", self, false),
1342
+ release: db.prepare("RELEASE ` _bs3. `", self, false),
1343
+ rollbackTo: db.prepare("ROLLBACK TO ` _bs3. `", self, false)
1344
+ };
1345
+ controllers.set(db, controller = {
1346
+ default: Object.assign({ begin: db.prepare("BEGIN", self, false) }, shared),
1347
+ deferred: Object.assign({ begin: db.prepare("BEGIN DEFERRED", self, false) }, shared),
1348
+ immediate: Object.assign({ begin: db.prepare("BEGIN IMMEDIATE", self, false) }, shared),
1349
+ exclusive: Object.assign({ begin: db.prepare("BEGIN EXCLUSIVE", self, false) }, shared)
1350
+ });
1351
+ }
1352
+ return controller;
1353
+ };
1354
+ var wrapTransaction = (apply, fn, db, { begin, commit, rollback, savepoint, release, rollbackTo }) => function sqliteTransaction() {
1355
+ let before, after, undo;
1356
+ if (db.inTransaction) {
1357
+ before = savepoint;
1358
+ after = release;
1359
+ undo = rollbackTo;
1360
+ } else {
1361
+ before = begin;
1362
+ after = commit;
1363
+ undo = rollback;
1364
+ }
1365
+ before.run();
1366
+ try {
1367
+ const result = apply.call(fn, this, arguments);
1368
+ if (result && typeof result.then === "function") {
1369
+ throw new TypeError("Transaction function cannot return a promise");
1370
+ }
1371
+ after.run();
1372
+ return result;
1373
+ } catch (ex) {
1374
+ if (db.inTransaction) {
1375
+ undo.run();
1376
+ if (undo !== rollback) after.run();
1377
+ }
1378
+ throw ex;
1379
+ }
1380
+ };
1381
+ }
1382
+ });
1383
+
1384
+ // node_modules/better-sqlite3/lib/methods/pragma.js
1385
+ var require_pragma = __commonJS({
1386
+ "node_modules/better-sqlite3/lib/methods/pragma.js"(exports, module) {
1387
+ "use strict";
1388
+ var { getBooleanOption, cppdb } = require_util();
1389
+ module.exports = function pragma(source, options) {
1390
+ if (options == null) options = {};
1391
+ if (typeof source !== "string") throw new TypeError("Expected first argument to be a string");
1392
+ if (typeof options !== "object") throw new TypeError("Expected second argument to be an options object");
1393
+ const simple = getBooleanOption(options, "simple");
1394
+ const stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true);
1395
+ return simple ? stmt.pluck().get() : stmt.all();
1396
+ };
1397
+ }
1398
+ });
1399
+
1400
+ // node_modules/better-sqlite3/lib/methods/backup.js
1401
+ var require_backup = __commonJS({
1402
+ "node_modules/better-sqlite3/lib/methods/backup.js"(exports, module) {
1403
+ "use strict";
1404
+ var fs3 = __require("fs");
1405
+ var path3 = __require("path");
1406
+ var { promisify: promisify2 } = __require("util");
1407
+ var { cppdb } = require_util();
1408
+ var fsAccess = promisify2(fs3.access);
1409
+ module.exports = async function backup(filename, options) {
1410
+ if (options == null) options = {};
1411
+ if (typeof filename !== "string") throw new TypeError("Expected first argument to be a string");
1412
+ if (typeof options !== "object") throw new TypeError("Expected second argument to be an options object");
1413
+ filename = filename.trim();
1414
+ const attachedName = "attached" in options ? options.attached : "main";
1415
+ const handler = "progress" in options ? options.progress : null;
1416
+ if (!filename) throw new TypeError("Backup filename cannot be an empty string");
1417
+ if (filename === ":memory:") throw new TypeError('Invalid backup filename ":memory:"');
1418
+ if (typeof attachedName !== "string") throw new TypeError('Expected the "attached" option to be a string');
1419
+ if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
1420
+ if (handler != null && typeof handler !== "function") throw new TypeError('Expected the "progress" option to be a function');
1421
+ await fsAccess(path3.dirname(filename)).catch(() => {
1422
+ throw new TypeError("Cannot save backup because the directory does not exist");
1423
+ });
1424
+ const isNewFile = await fsAccess(filename).then(() => false, () => true);
1425
+ return runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);
1426
+ };
1427
+ var runBackup = (backup, handler) => {
1428
+ let rate = 0;
1429
+ let useDefault = true;
1430
+ return new Promise((resolve4, reject) => {
1431
+ setImmediate(function step() {
1432
+ try {
1433
+ const progress = backup.transfer(rate);
1434
+ if (!progress.remainingPages) {
1435
+ backup.close();
1436
+ resolve4(progress);
1437
+ return;
1438
+ }
1439
+ if (useDefault) {
1440
+ useDefault = false;
1441
+ rate = 100;
1442
+ }
1443
+ if (handler) {
1444
+ const ret = handler(progress);
1445
+ if (ret !== void 0) {
1446
+ if (typeof ret === "number" && ret === ret) rate = Math.max(0, Math.min(2147483647, Math.round(ret)));
1447
+ else throw new TypeError("Expected progress callback to return a number or undefined");
1448
+ }
1449
+ }
1450
+ setImmediate(step);
1451
+ } catch (err) {
1452
+ backup.close();
1453
+ reject(err);
1454
+ }
1455
+ });
1456
+ });
1457
+ };
1458
+ }
1459
+ });
1460
+
1461
+ // node_modules/better-sqlite3/lib/methods/serialize.js
1462
+ var require_serialize = __commonJS({
1463
+ "node_modules/better-sqlite3/lib/methods/serialize.js"(exports, module) {
1464
+ "use strict";
1465
+ var { cppdb } = require_util();
1466
+ module.exports = function serialize(options) {
1467
+ if (options == null) options = {};
1468
+ if (typeof options !== "object") throw new TypeError("Expected first argument to be an options object");
1469
+ const attachedName = "attached" in options ? options.attached : "main";
1470
+ if (typeof attachedName !== "string") throw new TypeError('Expected the "attached" option to be a string');
1471
+ if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
1472
+ return this[cppdb].serialize(attachedName);
1473
+ };
1474
+ }
1475
+ });
1476
+
1477
+ // node_modules/better-sqlite3/lib/methods/function.js
1478
+ var require_function = __commonJS({
1479
+ "node_modules/better-sqlite3/lib/methods/function.js"(exports, module) {
1480
+ "use strict";
1481
+ var { getBooleanOption, cppdb } = require_util();
1482
+ module.exports = function defineFunction(name, options, fn) {
1483
+ if (options == null) options = {};
1484
+ if (typeof options === "function") {
1485
+ fn = options;
1486
+ options = {};
1487
+ }
1488
+ if (typeof name !== "string") throw new TypeError("Expected first argument to be a string");
1489
+ if (typeof fn !== "function") throw new TypeError("Expected last argument to be a function");
1490
+ if (typeof options !== "object") throw new TypeError("Expected second argument to be an options object");
1491
+ if (!name) throw new TypeError("User-defined function name cannot be an empty string");
1492
+ const safeIntegers = "safeIntegers" in options ? +getBooleanOption(options, "safeIntegers") : 2;
1493
+ const deterministic = getBooleanOption(options, "deterministic");
1494
+ const directOnly = getBooleanOption(options, "directOnly");
1495
+ const varargs = getBooleanOption(options, "varargs");
1496
+ let argCount = -1;
1497
+ if (!varargs) {
1498
+ argCount = fn.length;
1499
+ if (!Number.isInteger(argCount) || argCount < 0) throw new TypeError("Expected function.length to be a positive integer");
1500
+ if (argCount > 100) throw new RangeError("User-defined functions cannot have more than 100 arguments");
1501
+ }
1502
+ this[cppdb].function(fn, name, argCount, safeIntegers, deterministic, directOnly);
1503
+ return this;
1504
+ };
750
1505
  }
751
- json(data, status) {
752
- if (status !== void 0) this._statusCode = status;
753
- const body = JSON.stringify(data);
754
- return this.send(body, void 0, "application/json");
1506
+ });
1507
+
1508
+ // node_modules/better-sqlite3/lib/methods/aggregate.js
1509
+ var require_aggregate = __commonJS({
1510
+ "node_modules/better-sqlite3/lib/methods/aggregate.js"(exports, module) {
1511
+ "use strict";
1512
+ var { getBooleanOption, cppdb } = require_util();
1513
+ module.exports = function defineAggregate(name, options) {
1514
+ if (typeof name !== "string") throw new TypeError("Expected first argument to be a string");
1515
+ if (typeof options !== "object" || options === null) throw new TypeError("Expected second argument to be an options object");
1516
+ if (!name) throw new TypeError("User-defined function name cannot be an empty string");
1517
+ const start = "start" in options ? options.start : null;
1518
+ const step = getFunctionOption(options, "step", true);
1519
+ const inverse = getFunctionOption(options, "inverse", false);
1520
+ const result = getFunctionOption(options, "result", false);
1521
+ const safeIntegers = "safeIntegers" in options ? +getBooleanOption(options, "safeIntegers") : 2;
1522
+ const deterministic = getBooleanOption(options, "deterministic");
1523
+ const directOnly = getBooleanOption(options, "directOnly");
1524
+ const varargs = getBooleanOption(options, "varargs");
1525
+ let argCount = -1;
1526
+ if (!varargs) {
1527
+ argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);
1528
+ if (argCount > 0) argCount -= 1;
1529
+ if (argCount > 100) throw new RangeError("User-defined functions cannot have more than 100 arguments");
1530
+ }
1531
+ this[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic, directOnly);
1532
+ return this;
1533
+ };
1534
+ var getFunctionOption = (options, key, required) => {
1535
+ const value = key in options ? options[key] : null;
1536
+ if (typeof value === "function") return value;
1537
+ if (value != null) throw new TypeError(`Expected the "${key}" option to be a function`);
1538
+ if (required) throw new TypeError(`Missing required option "${key}"`);
1539
+ return null;
1540
+ };
1541
+ var getLength = ({ length }) => {
1542
+ if (Number.isInteger(length) && length >= 0) return length;
1543
+ throw new TypeError("Expected function.length to be a positive integer");
1544
+ };
755
1545
  }
756
- send(body, status, contentType) {
757
- if (status !== void 0) this._statusCode = status;
758
- this._body = body;
759
- if (contentType !== void 0 && !this._contentTypeSet) {
760
- this._headers.set("content-type", contentType);
1546
+ });
1547
+
1548
+ // node_modules/better-sqlite3/lib/methods/table.js
1549
+ var require_table = __commonJS({
1550
+ "node_modules/better-sqlite3/lib/methods/table.js"(exports, module) {
1551
+ "use strict";
1552
+ var { cppdb } = require_util();
1553
+ module.exports = function defineTable(name, factory) {
1554
+ if (typeof name !== "string") throw new TypeError("Expected first argument to be a string");
1555
+ if (!name) throw new TypeError("Virtual table module name cannot be an empty string");
1556
+ let eponymous = false;
1557
+ if (typeof factory === "object" && factory !== null) {
1558
+ eponymous = true;
1559
+ factory = defer(parseTableDefinition(factory, "used", name));
1560
+ } else {
1561
+ if (typeof factory !== "function") throw new TypeError("Expected second argument to be a function or a table definition object");
1562
+ factory = wrapFactory(factory);
1563
+ }
1564
+ this[cppdb].table(factory, name, eponymous);
1565
+ return this;
1566
+ };
1567
+ function wrapFactory(factory) {
1568
+ return function virtualTableFactory(moduleName, databaseName, tableName, ...args) {
1569
+ const thisObject = {
1570
+ module: moduleName,
1571
+ database: databaseName,
1572
+ table: tableName
1573
+ };
1574
+ const def = apply.call(factory, thisObject, args);
1575
+ if (typeof def !== "object" || def === null) {
1576
+ throw new TypeError(`Virtual table module "${moduleName}" did not return a table definition object`);
1577
+ }
1578
+ return parseTableDefinition(def, "returned", moduleName);
1579
+ };
1580
+ }
1581
+ function parseTableDefinition(def, verb, moduleName) {
1582
+ if (!hasOwnProperty.call(def, "rows")) {
1583
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "rows" property`);
1584
+ }
1585
+ if (!hasOwnProperty.call(def, "columns")) {
1586
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "columns" property`);
1587
+ }
1588
+ const rows = def.rows;
1589
+ if (typeof rows !== "function" || Object.getPrototypeOf(rows) !== GeneratorFunctionPrototype) {
1590
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "rows" property (should be a generator function)`);
1591
+ }
1592
+ let columns = def.columns;
1593
+ if (!Array.isArray(columns) || !(columns = [...columns]).every((x) => typeof x === "string")) {
1594
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "columns" property (should be an array of strings)`);
1595
+ }
1596
+ if (columns.length !== new Set(columns).size) {
1597
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate column names`);
1598
+ }
1599
+ if (!columns.length) {
1600
+ throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with zero columns`);
1601
+ }
1602
+ let parameters;
1603
+ if (hasOwnProperty.call(def, "parameters")) {
1604
+ parameters = def.parameters;
1605
+ if (!Array.isArray(parameters) || !(parameters = [...parameters]).every((x) => typeof x === "string")) {
1606
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "parameters" property (should be an array of strings)`);
1607
+ }
1608
+ } else {
1609
+ parameters = inferParameters(rows);
1610
+ }
1611
+ if (parameters.length !== new Set(parameters).size) {
1612
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate parameter names`);
1613
+ }
1614
+ if (parameters.length > 32) {
1615
+ throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with more than the maximum number of 32 parameters`);
1616
+ }
1617
+ for (const parameter of parameters) {
1618
+ if (columns.includes(parameter)) {
1619
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with column "${parameter}" which was ambiguously defined as both a column and parameter`);
1620
+ }
1621
+ }
1622
+ let safeIntegers = 2;
1623
+ if (hasOwnProperty.call(def, "safeIntegers")) {
1624
+ const bool = def.safeIntegers;
1625
+ if (typeof bool !== "boolean") {
1626
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "safeIntegers" property (should be a boolean)`);
1627
+ }
1628
+ safeIntegers = +bool;
1629
+ }
1630
+ let directOnly = false;
1631
+ if (hasOwnProperty.call(def, "directOnly")) {
1632
+ directOnly = def.directOnly;
1633
+ if (typeof directOnly !== "boolean") {
1634
+ throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "directOnly" property (should be a boolean)`);
1635
+ }
1636
+ }
1637
+ const columnDefinitions = [
1638
+ ...parameters.map(identifier).map((str) => `${str} HIDDEN`),
1639
+ ...columns.map(identifier)
1640
+ ];
1641
+ return [
1642
+ `CREATE TABLE x(${columnDefinitions.join(", ")});`,
1643
+ wrapGenerator(rows, new Map(columns.map((x, i) => [x, parameters.length + i])), moduleName),
1644
+ parameters,
1645
+ safeIntegers,
1646
+ directOnly
1647
+ ];
1648
+ }
1649
+ function wrapGenerator(generator, columnMap, moduleName) {
1650
+ return function* virtualTable(...args) {
1651
+ const output = args.map((x) => Buffer.isBuffer(x) ? Buffer.from(x) : x);
1652
+ for (let i = 0; i < columnMap.size; ++i) {
1653
+ output.push(null);
1654
+ }
1655
+ for (const row of generator(...args)) {
1656
+ if (Array.isArray(row)) {
1657
+ extractRowArray(row, output, columnMap.size, moduleName);
1658
+ yield output;
1659
+ } else if (typeof row === "object" && row !== null) {
1660
+ extractRowObject(row, output, columnMap, moduleName);
1661
+ yield output;
1662
+ } else {
1663
+ throw new TypeError(`Virtual table module "${moduleName}" yielded something that isn't a valid row object`);
1664
+ }
1665
+ }
1666
+ };
761
1667
  }
762
- return this;
763
- }
764
- html(html, status) {
765
- return this.send(html, status, "text/html; charset=utf-8");
766
- }
767
- redirect(url2, status = HttpStatus.FOUND) {
768
- this._statusCode = status;
769
- this._headers.set("location", url2);
770
- this._body = null;
771
- return this;
772
- }
773
- stream(stream, status) {
774
- if (status !== void 0) this._statusCode = status;
775
- this.flushHeaders();
776
- this.raw.statusCode = this._statusCode;
777
- stream.pipe(this.raw);
778
- stream.on("end", () => {
779
- this._sent = true;
780
- });
781
- stream.on("error", (_err) => {
782
- if (!this._sent) {
783
- this._sent = true;
784
- this.raw.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
785
- this.raw.end();
1668
+ function extractRowArray(row, output, columnCount, moduleName) {
1669
+ if (row.length !== columnCount) {
1670
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an incorrect number of columns`);
1671
+ }
1672
+ const offset = output.length - columnCount;
1673
+ for (let i = 0; i < columnCount; ++i) {
1674
+ output[i + offset] = row[i];
1675
+ }
1676
+ }
1677
+ function extractRowObject(row, output, columnMap, moduleName) {
1678
+ let count = 0;
1679
+ for (const key of Object.keys(row)) {
1680
+ const index = columnMap.get(key);
1681
+ if (index === void 0) {
1682
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an undeclared column "${key}"`);
1683
+ }
1684
+ output[index] = row[key];
1685
+ count += 1;
1686
+ }
1687
+ if (count !== columnMap.size) {
1688
+ throw new TypeError(`Virtual table module "${moduleName}" yielded a row with missing columns`);
1689
+ }
1690
+ }
1691
+ function inferParameters({ length }) {
1692
+ if (!Number.isInteger(length) || length < 0) {
1693
+ throw new TypeError("Expected function.length to be a positive integer");
786
1694
  }
1695
+ const params = [];
1696
+ for (let i = 0; i < length; ++i) {
1697
+ params.push(`$${i + 1}`);
1698
+ }
1699
+ return params;
1700
+ }
1701
+ var { hasOwnProperty } = Object.prototype;
1702
+ var { apply } = Function.prototype;
1703
+ var GeneratorFunctionPrototype = Object.getPrototypeOf(function* () {
787
1704
  });
788
- return this;
1705
+ var identifier = (str) => `"${str.replace(/"/g, '""')}"`;
1706
+ var defer = (x) => () => x;
789
1707
  }
790
- async file(filePath, options) {
791
- const fullPath = options?.root ? joinPath(options.root, filePath) : filePath;
792
- try {
793
- const stats = await statAsync(fullPath);
794
- if (!stats.isFile()) {
795
- this._statusCode = HttpStatus.NOT_FOUND;
796
- this._body = null;
797
- return this;
1708
+ });
1709
+
1710
+ // node_modules/better-sqlite3/lib/methods/inspect.js
1711
+ var require_inspect = __commonJS({
1712
+ "node_modules/better-sqlite3/lib/methods/inspect.js"(exports, module) {
1713
+ "use strict";
1714
+ var DatabaseInspection = function Database() {
1715
+ };
1716
+ module.exports = function inspect(depth, opts) {
1717
+ return Object.assign(new DatabaseInspection(), this);
1718
+ };
1719
+ }
1720
+ });
1721
+
1722
+ // node_modules/better-sqlite3/lib/database.js
1723
+ var require_database = __commonJS({
1724
+ "node_modules/better-sqlite3/lib/database.js"(exports, module) {
1725
+ "use strict";
1726
+ var fs3 = __require("fs");
1727
+ var path3 = __require("path");
1728
+ var util = require_util();
1729
+ var SqliteError = require_sqlite_error();
1730
+ var DEFAULT_ADDON;
1731
+ function Database(filenameGiven, options) {
1732
+ if (new.target == null) {
1733
+ return new Database(filenameGiven, options);
798
1734
  }
799
- const ext = extname2(fullPath);
800
- const mimeType = MIME_TYPES[ext] ?? "application/octet-stream";
801
- this._headers.set("content-type", mimeType);
802
- this._headers.set("content-length", String(stats.size));
803
- if (options?.cacheControl !== false) {
804
- const maxAge = options?.maxAge ?? 0;
805
- this._headers.set("cache-control", `public, max-age=${maxAge}`);
1735
+ let buffer;
1736
+ if (Buffer.isBuffer(filenameGiven)) {
1737
+ buffer = filenameGiven;
1738
+ filenameGiven = ":memory:";
806
1739
  }
807
- if (options?.lastModified !== false) {
808
- this._headers.set("last-modified", stats.mtime.toUTCString());
1740
+ if (filenameGiven == null) filenameGiven = "";
1741
+ if (options == null) options = {};
1742
+ if (typeof filenameGiven !== "string") throw new TypeError("Expected first argument to be a string");
1743
+ if (typeof options !== "object") throw new TypeError("Expected second argument to be an options object");
1744
+ if ("readOnly" in options) throw new TypeError('Misspelled option "readOnly" should be "readonly"');
1745
+ if ("memory" in options) throw new TypeError('Option "memory" was removed in v7.0.0 (use ":memory:" filename instead)');
1746
+ const filename = filenameGiven.trim();
1747
+ const anonymous = filename === "" || filename === ":memory:";
1748
+ const readonly = util.getBooleanOption(options, "readonly");
1749
+ const fileMustExist = util.getBooleanOption(options, "fileMustExist");
1750
+ const timeout = "timeout" in options ? options.timeout : 5e3;
1751
+ const verbose = "verbose" in options ? options.verbose : null;
1752
+ const nativeBinding = "nativeBinding" in options ? options.nativeBinding : null;
1753
+ if (readonly && anonymous && !buffer) throw new TypeError("In-memory/temporary databases cannot be readonly");
1754
+ if (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the "timeout" option to be a positive integer');
1755
+ if (timeout > 2147483647) throw new RangeError('Option "timeout" cannot be greater than 2147483647');
1756
+ if (verbose != null && typeof verbose !== "function") throw new TypeError('Expected the "verbose" option to be a function');
1757
+ if (nativeBinding != null && typeof nativeBinding !== "string" && typeof nativeBinding !== "object") throw new TypeError('Expected the "nativeBinding" option to be a string or addon object');
1758
+ let addon;
1759
+ if (nativeBinding == null) {
1760
+ addon = DEFAULT_ADDON || (DEFAULT_ADDON = require_bindings()("better_sqlite3.node"));
1761
+ } else if (typeof nativeBinding === "string") {
1762
+ const requireFunc = typeof __non_webpack_require__ === "function" ? __non_webpack_require__ : __require;
1763
+ addon = requireFunc(path3.resolve(nativeBinding).replace(/(\.node)?$/, ".node"));
1764
+ } else {
1765
+ addon = nativeBinding;
809
1766
  }
810
- if (options?.headers !== void 0) {
811
- for (const [key, value] of Object.entries(options.headers)) {
812
- this._headers.set(key, value);
813
- }
1767
+ if (!addon.isInitialized) {
1768
+ addon.setErrorConstructor(SqliteError);
1769
+ addon.isInitialized = true;
814
1770
  }
815
- this.flushHeaders();
816
- this.raw.statusCode = this._statusCode;
817
- const readStream = createReadStream(fullPath);
818
- readStream.pipe(this.raw);
819
- readStream.on("end", () => {
820
- this._sent = true;
821
- });
822
- readStream.on("error", () => {
823
- if (!this._sent) {
824
- this._sent = true;
825
- this.raw.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
826
- this.raw.end();
827
- }
1771
+ if (!anonymous && !filename.startsWith("file:") && !fs3.existsSync(path3.dirname(filename))) {
1772
+ throw new TypeError("Cannot open database because the directory does not exist");
1773
+ }
1774
+ Object.defineProperties(this, {
1775
+ [util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },
1776
+ ...wrappers.getters
828
1777
  });
829
- } catch {
830
- this._statusCode = HttpStatus.NOT_FOUND;
831
- this._body = null;
832
1778
  }
833
- return this;
1779
+ var wrappers = require_wrappers();
1780
+ Database.prototype.prepare = wrappers.prepare;
1781
+ Database.prototype.transaction = require_transaction();
1782
+ Database.prototype.pragma = require_pragma();
1783
+ Database.prototype.backup = require_backup();
1784
+ Database.prototype.serialize = require_serialize();
1785
+ Database.prototype.function = require_function();
1786
+ Database.prototype.aggregate = require_aggregate();
1787
+ Database.prototype.table = require_table();
1788
+ Database.prototype.loadExtension = wrappers.loadExtension;
1789
+ Database.prototype.exec = wrappers.exec;
1790
+ Database.prototype.close = wrappers.close;
1791
+ Database.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;
1792
+ Database.prototype.unsafeMode = wrappers.unsafeMode;
1793
+ Database.prototype[util.inspect] = require_inspect();
1794
+ module.exports = Database;
834
1795
  }
835
- async download(filePath, filename) {
836
- const downloadName = filename ?? basename2(filePath);
837
- this._headers.set(
838
- "content-disposition",
839
- `attachment; filename="${downloadName}"`
840
- );
841
- await this.file(filePath);
842
- return this;
1796
+ });
1797
+
1798
+ // node_modules/better-sqlite3/lib/index.js
1799
+ var require_lib = __commonJS({
1800
+ "node_modules/better-sqlite3/lib/index.js"(exports, module) {
1801
+ "use strict";
1802
+ module.exports = require_database();
1803
+ module.exports.SqliteError = require_sqlite_error();
843
1804
  }
844
- attachment(filename) {
845
- if (filename !== void 0) {
846
- this._headers.set(
847
- "content-disposition",
848
- `attachment; filename="${filename}"`
849
- );
850
- } else {
851
- this._headers.set("content-disposition", "attachment");
852
- }
1805
+ });
1806
+
1807
+ // src/server/container/index.ts
1808
+ var Container = class {
1809
+ bindings = /* @__PURE__ */ new Map();
1810
+ resolving = /* @__PURE__ */ new Set();
1811
+ bind(name, factory) {
1812
+ this.bindings.set(name, { factory, singleton: false });
853
1813
  return this;
854
1814
  }
855
- cookie(name, value, options) {
856
- this._cookies.push(serializeCookie(name, value, options));
1815
+ singleton(name, factory) {
1816
+ this.bindings.set(name, { factory, singleton: true });
857
1817
  return this;
858
1818
  }
859
- clearCookie(name, options) {
860
- this._cookies.push(clearCookie(name, options));
1819
+ instance(name, instance) {
1820
+ this.bindings.set(name, {
1821
+ factory: () => instance,
1822
+ singleton: true,
1823
+ instance
1824
+ });
861
1825
  return this;
862
1826
  }
863
- get statusCode() {
864
- return this._statusCode;
865
- }
866
- get headersSent() {
867
- return this._sent;
868
- }
869
- get rawResponse() {
870
- return this.raw;
871
- }
872
- async flush() {
873
- if (this._sent) return;
874
- this._sent = true;
875
- this.flushHeaders();
876
- this.raw.statusCode = this._statusCode;
877
- if (this._body !== null) {
878
- this.raw.end(this._body);
879
- } else {
880
- this.raw.end();
1827
+ resolve(name) {
1828
+ const binding = this.bindings.get(name);
1829
+ if (binding === void 0) {
1830
+ throw new Error(`Binding not found: ${name}`);
881
1831
  }
882
- }
883
- flushHeaders() {
884
- if (this._cookies.length > 0) {
885
- this.raw.setHeader("Set-Cookie", this._cookies);
1832
+ if (binding.singleton && binding.instance !== void 0) {
1833
+ return binding.instance;
1834
+ }
1835
+ if (this.resolving.has(name)) {
1836
+ throw new Error(
1837
+ `Circular dependency detected: ${name} is already being resolved`
1838
+ );
886
1839
  }
887
- for (const [name, value] of this._headers.entries()) {
888
- if (name.toLowerCase() !== "set-cookie") {
889
- this.raw.setHeader(name, value);
1840
+ this.resolving.add(name);
1841
+ try {
1842
+ const instance = binding.factory();
1843
+ if (binding.singleton) {
1844
+ binding.instance = instance;
890
1845
  }
1846
+ return instance;
1847
+ } finally {
1848
+ this.resolving.delete(name);
891
1849
  }
892
1850
  }
1851
+ has(name) {
1852
+ return this.bindings.has(name);
1853
+ }
1854
+ remove(name) {
1855
+ this.bindings.delete(name);
1856
+ }
1857
+ clear() {
1858
+ this.bindings.clear();
1859
+ this.resolving.clear();
1860
+ }
1861
+ getBindings() {
1862
+ return new Map(this.bindings);
1863
+ }
893
1864
  };
894
- function joinPath(root, filePath) {
895
- const normalizedRoot = root.replace(/\\/g, "/").replace(/\/$/, "");
896
- const normalizedPath = filePath.replace(/\\/g, "/").replace(/^\//, "");
897
- return `${normalizedRoot}/${normalizedPath}`;
1865
+
1866
+ // src/server/controller/index.ts
1867
+ var controllerPrefixMap = /* @__PURE__ */ new WeakMap();
1868
+ var controllerRoutesMap = /* @__PURE__ */ new WeakMap();
1869
+ function createRouteDecorator(method) {
1870
+ return (path3) => {
1871
+ return (target, context) => {
1872
+ const classTarget = context.static ? target : target.constructor;
1873
+ const routes = controllerRoutesMap.get(classTarget) ?? [];
1874
+ routes.push({ method, path: path3, handler: context.name });
1875
+ controllerRoutesMap.set(classTarget, routes);
1876
+ };
1877
+ };
1878
+ }
1879
+ var get = createRouteDecorator("GET");
1880
+ var post = createRouteDecorator("POST");
1881
+ var put = createRouteDecorator("PUT");
1882
+ var patch = createRouteDecorator("PATCH");
1883
+ var del = createRouteDecorator("DELETE");
1884
+ function getControllerPrefix(controllerClass) {
1885
+ return controllerPrefixMap.get(controllerClass) ?? "";
1886
+ }
1887
+ function getControllerRoutes(controllerClass) {
1888
+ return controllerRoutesMap.get(controllerClass) ?? [];
898
1889
  }
899
1890
 
900
1891
  // src/server/engine/index.ts
1892
+ init_request();
1893
+ init_response();
1894
+ init_errors();
1895
+ import { createServer as createHttpServer } from "http";
1896
+ import { createServer as createHttpsServer } from "https";
1897
+ import { readFileSync } from "fs";
901
1898
  var NodeEngine = class {
902
1899
  async createServer(handler) {
903
1900
  const server = createHttpServer(async (nodeReq, nodeRes) => {
@@ -907,8 +1904,9 @@ var NodeEngine = class {
907
1904
  await handler(req, res);
908
1905
  } catch (_err) {
909
1906
  if (!res.headersSent) {
910
- const message = _err instanceof Error ? _err.message : "Internal Server Error";
911
- res.status(500).json({ error: message });
1907
+ const error = _err instanceof Error ? _err : new Error(String(_err));
1908
+ const httpError = normalizeError(error);
1909
+ res.status(httpError.status).json(httpError.toJSON());
912
1910
  await res.flush();
913
1911
  }
914
1912
  }
@@ -919,12 +1917,12 @@ var NodeEngine = class {
919
1917
  return {
920
1918
  raw: server,
921
1919
  close: () => {
922
- return new Promise((resolve2, reject) => {
1920
+ return new Promise((resolve4, reject) => {
923
1921
  server.close((err) => {
924
1922
  if (err !== void 0 && err !== null) {
925
1923
  reject(err);
926
1924
  } else {
927
- resolve2();
1925
+ resolve4();
928
1926
  }
929
1927
  });
930
1928
  });
@@ -943,11 +1941,15 @@ var NodeEngine = class {
943
1941
  }
944
1942
  };
945
1943
 
1944
+ // src/server/index.ts
1945
+ init_status();
1946
+
946
1947
  // src/server/middleware/index.ts
1948
+ init_status();
947
1949
  import { randomUUID as randomUUID2 } from "crypto";
948
1950
  import { createReadStream as createReadStream2, existsSync, statSync } from "fs";
949
- import { extname as extname3, join as join2 } from "path";
950
- import { createGzip } from "zlib";
1951
+ import { extname as extname3, join as join2, resolve as resolve2 } from "path";
1952
+ import { gzipSync } from "zlib";
951
1953
  function staticFiles(root, options) {
952
1954
  const opts = {
953
1955
  maxAge: 0,
@@ -986,6 +1988,11 @@ function staticFiles(root, options) {
986
1988
  }
987
1989
  }
988
1990
  let fullPath = join2(root, filePath);
1991
+ const resolvedRoot = resolve2(root);
1992
+ const resolvedPath = resolve2(fullPath);
1993
+ if (!resolvedPath.startsWith(resolvedRoot)) {
1994
+ return next();
1995
+ }
989
1996
  if (!existsSync(fullPath)) {
990
1997
  let found = false;
991
1998
  for (const ext2 of opts.extensions) {
@@ -1017,8 +2024,8 @@ function staticFiles(root, options) {
1017
2024
  const readStream = createReadStream2(fullPath);
1018
2025
  readStream.pipe(response.rawResponse);
1019
2026
  response.rawResponse.statusCode = HttpStatus.OK;
1020
- return new Promise((resolve2, reject) => {
1021
- readStream.on("end", () => resolve2());
2027
+ return new Promise((resolve4, reject) => {
2028
+ readStream.on("end", () => resolve4());
1022
2029
  readStream.on("error", (err) => reject(err));
1023
2030
  });
1024
2031
  };
@@ -1275,12 +2282,6 @@ function singularize(word) {
1275
2282
  if (lastChar === "S") return word.slice(0, -1);
1276
2283
  return word;
1277
2284
  }
1278
- function createControllerInstance(controller, ctx) {
1279
- const instance = new controller();
1280
- instance.__ctx = ctx;
1281
- instance.__container = ctx.container;
1282
- return instance;
1283
- }
1284
2285
 
1285
2286
  // src/server/cache/index.ts
1286
2287
  import * as crypto from "crypto";
@@ -2006,47 +3007,66 @@ async function createMysqlDriver(config) {
2006
3007
  "MySQL driver (mysql2) is not installed. Run: npm install mysql2"
2007
3008
  );
2008
3009
  }
2009
- let connection = null;
3010
+ let pool = null;
2010
3011
  const dialect = new MysqlDialect();
2011
3012
  const driver = {
2012
3013
  async connect() {
2013
- connection = await mysqlPackage.createConnection({
3014
+ pool = mysqlPackage.createPool({
2014
3015
  host: config.host ?? "127.0.0.1",
2015
3016
  port: config.port ?? 3306,
2016
3017
  user: config.username,
2017
3018
  password: config.password,
2018
3019
  database: config.database,
2019
- charset: config.charset ?? "utf8mb4"
3020
+ charset: config.charset ?? "utf8mb4",
3021
+ waitForConnections: true,
3022
+ connectionLimit: 10,
3023
+ queueLimit: 0
2020
3024
  });
3025
+ const conn = await pool.getConnection();
3026
+ conn.release();
2021
3027
  },
2022
3028
  async disconnect() {
2023
- if (connection !== null) {
2024
- await connection.end();
2025
- connection = null;
3029
+ if (pool !== null) {
3030
+ await pool.end();
3031
+ pool = null;
2026
3032
  }
2027
3033
  },
2028
3034
  isConnected() {
2029
- return connection !== null;
3035
+ return pool !== null;
2030
3036
  },
2031
3037
  async raw(sql, bindings) {
2032
- if (connection === null) {
3038
+ if (pool === null) {
2033
3039
  throw new Error("Database not connected. Call connect() first.");
2034
3040
  }
2035
- const [rows, fields] = await connection.execute(sql, bindings ?? []);
3041
+ const [rows, fields] = await pool.execute(sql, bindings ?? []);
2036
3042
  return { rows, fields };
2037
3043
  },
2038
3044
  async transaction(callback) {
2039
- if (connection === null) {
2040
- throw new Error("Database not connected. Call connect() first.");
2041
- }
2042
- await connection.beginTransaction();
3045
+ if (pool === null) throw new Error("Database not connected.");
3046
+ const conn = await pool.getConnection();
2043
3047
  try {
2044
- const result = await callback(driver);
2045
- await connection.commit();
3048
+ await conn.beginTransaction();
3049
+ const trxDriver = {
3050
+ ...driver,
3051
+ async raw(sql, bindings) {
3052
+ const [rows, fields] = await conn.execute(sql, bindings ?? []);
3053
+ return { rows, fields };
3054
+ },
3055
+ getDialect() {
3056
+ return dialect;
3057
+ },
3058
+ getDriver() {
3059
+ return "mysql";
3060
+ }
3061
+ };
3062
+ const result = await callback(trxDriver);
3063
+ await conn.commit();
2046
3064
  return result;
2047
3065
  } catch (err) {
2048
- await connection.rollback();
3066
+ await conn.rollback();
2049
3067
  throw err;
3068
+ } finally {
3069
+ conn.release();
2050
3070
  }
2051
3071
  },
2052
3072
  getDialect() {
@@ -2139,7 +3159,7 @@ async function createPostgresqlDriver(config) {
2139
3159
  async function createSqliteDriver(config) {
2140
3160
  let sqlitePackage;
2141
3161
  try {
2142
- sqlitePackage = await import("better-sqlite3");
3162
+ sqlitePackage = await Promise.resolve().then(() => __toESM(require_lib(), 1));
2143
3163
  } catch {
2144
3164
  throw new Error(
2145
3165
  "SQLite driver (better-sqlite3) is not installed. Run: npm install better-sqlite3"
@@ -2186,10 +3206,15 @@ async function createSqliteDriver(config) {
2186
3206
  if (db === null) {
2187
3207
  throw new Error("Database not connected. Call connect() first.");
2188
3208
  }
2189
- const txn = db.transaction(async () => {
2190
- return await callback(driver);
2191
- });
2192
- return txn();
3209
+ db.exec("BEGIN");
3210
+ try {
3211
+ const result = await callback(driver);
3212
+ db.exec("COMMIT");
3213
+ return result;
3214
+ } catch (err) {
3215
+ db.exec("ROLLBACK");
3216
+ throw err;
3217
+ }
2193
3218
  },
2194
3219
  getDialect() {
2195
3220
  return dialect;
@@ -2456,15 +3481,30 @@ var QueryBuilder = class _QueryBuilder {
2456
3481
  async insert(data) {
2457
3482
  const { sql, bindings } = this.compileInsert(data);
2458
3483
  const driverType = this.connection.getDriver();
3484
+ const dialect = this.connection.getDialect();
2459
3485
  if (driverType === "postgresql") {
2460
- const dialect = this.connection.getDialect();
2461
3486
  const returningSQL = dialect.compileInsertReturning(sql, bindings);
2462
3487
  const result2 = await this.connection.raw(returningSQL, bindings);
2463
3488
  return result2.rows.length > 0 ? Number(result2.rows[0].id) ?? 0 : 0;
2464
3489
  }
2465
3490
  const result = await this.connection.raw(sql, bindings);
2466
- if (result.rows && result.rows.length > 0) {
2467
- return Number(result.rows[0].id) ?? result.rows[0].insertId ?? 0;
3491
+ if (driverType === "mysql") {
3492
+ const header = result.rows;
3493
+ if (header && typeof header === "object" && "insertId" in header) {
3494
+ return Number(header.insertId) ?? 0;
3495
+ }
3496
+ if (Array.isArray(result.rows) && result.rows.length > 0) {
3497
+ const row = result.rows[0];
3498
+ return Number(row?.insertId ?? row?.id ?? 0);
3499
+ }
3500
+ return 0;
3501
+ }
3502
+ if (driverType === "sqlite") {
3503
+ const lastIdResult = await this.connection.raw("SELECT last_insert_rowid() as id");
3504
+ if (lastIdResult.rows.length > 0) {
3505
+ return Number(lastIdResult.rows[0].id) ?? 0;
3506
+ }
3507
+ return 0;
2468
3508
  }
2469
3509
  return 0;
2470
3510
  }
@@ -2573,7 +3613,7 @@ var QueryBuilder = class _QueryBuilder {
2573
3613
  const output = `SQL: ${sql}
2574
3614
  Bindings: ${JSON.stringify(bindings)}`;
2575
3615
  console.error(output);
2576
- process.exit(1);
3616
+ return output;
2577
3617
  }
2578
3618
  compileJoins(dialect) {
2579
3619
  if (this.joins.length === 0) return "";
@@ -2595,7 +3635,11 @@ Bindings: ${JSON.stringify(bindings)}`;
2595
3635
  if (sql !== null) parts.push(sql);
2596
3636
  }
2597
3637
  if (parts.length === 0) return "";
2598
- return parts.join(" AND ");
3638
+ return parts.reduce((acc, part, i) => {
3639
+ if (i === 0) return part;
3640
+ const bool = wheres[i]?.boolean ?? "and";
3641
+ return `${acc} ${bool.toUpperCase()} ${part}`;
3642
+ }, "");
2599
3643
  }
2600
3644
  compileSingleWhere(w, dialect, bindings) {
2601
3645
  const col = w.column ? dialect.wrapIdentifier(w.column) : "";
@@ -2644,15 +3688,18 @@ Bindings: ${JSON.stringify(bindings)}`;
2644
3688
  }
2645
3689
  }
2646
3690
  compileNestedWhere(wheres, dialect, bindings) {
3691
+ if (wheres.length === 0) return "";
2647
3692
  const parts = [];
2648
3693
  for (const w of wheres) {
2649
3694
  const sql = this.compileSingleWhere(w, dialect, bindings);
2650
- if (sql !== null) {
2651
- parts.push(sql);
2652
- }
3695
+ if (sql !== null) parts.push(sql);
2653
3696
  }
2654
3697
  if (parts.length === 0) return "";
2655
- return parts.join(" AND ");
3698
+ return parts.reduce((acc, part, i) => {
3699
+ if (i === 0) return part;
3700
+ const bool = wheres[i]?.boolean ?? "and";
3701
+ return `${acc} ${bool.toUpperCase()} ${part}`;
3702
+ }, "");
2656
3703
  }
2657
3704
  compileHavings(dialect, bindings) {
2658
3705
  if (this.havings.length === 0) return "";
@@ -3477,6 +4524,224 @@ var Seeder = class {
3477
4524
  }
3478
4525
  };
3479
4526
 
4527
+ // src/server/database/model.ts
4528
+ var Model = class {
4529
+ /** Primary key */
4530
+ id;
4531
+ static table = "";
4532
+ static connection = null;
4533
+ static queryRunner = null;
4534
+ static relationDefs = /* @__PURE__ */ new Map();
4535
+ static eagerLoads = /* @__PURE__ */ new Map();
4536
+ /** @internal cache for loaded relations on instances */
4537
+ _relations = {};
4538
+ static setConnection(conn) {
4539
+ this.connection = conn;
4540
+ this.queryRunner = conn;
4541
+ }
4542
+ static query() {
4543
+ if (!this.queryRunner) {
4544
+ throw new Error("Database connection not set. Call Model.setConnection() first.");
4545
+ }
4546
+ return new QueryBuilder(this.queryRunner, this.table);
4547
+ }
4548
+ // ─── Relations Definition ──────────────────────────────────
4549
+ static hasOne(relatedModel, foreignKey, localKey) {
4550
+ const key = `hasOne:${relatedModel.table}`;
4551
+ this.relationDefs.set(key, {
4552
+ type: "hasOne",
4553
+ relatedModel,
4554
+ foreignKey: foreignKey ?? `${this.table}_id`,
4555
+ localKey: localKey ?? "id"
4556
+ });
4557
+ }
4558
+ static hasMany(relatedModel, foreignKey, localKey) {
4559
+ const key = `hasMany:${relatedModel.table}`;
4560
+ this.relationDefs.set(key, {
4561
+ type: "hasMany",
4562
+ relatedModel,
4563
+ foreignKey: foreignKey ?? `${this.table}_id`,
4564
+ localKey: localKey ?? "id"
4565
+ });
4566
+ }
4567
+ static belongsTo(relatedModel, foreignKey, ownerKey) {
4568
+ const key = `belongsTo:${relatedModel.table}`;
4569
+ this.relationDefs.set(key, {
4570
+ type: "belongsTo",
4571
+ relatedModel,
4572
+ foreignKey: foreignKey ?? `${relatedModel.table}_id`,
4573
+ localKey: ownerKey ?? "id"
4574
+ });
4575
+ }
4576
+ static belongsToMany(relatedModel, pivotTable, foreignPivotKey, relatedPivotKey) {
4577
+ const tables = [this.table, relatedModel.table].sort();
4578
+ const key = `belongsToMany:${relatedModel.table}`;
4579
+ this.relationDefs.set(key, {
4580
+ type: "belongsToMany",
4581
+ relatedModel,
4582
+ foreignKey: foreignPivotKey ?? `${this.table}_id`,
4583
+ localKey: relatedPivotKey ?? `${relatedModel.table}_id`,
4584
+ pivotTable: pivotTable ?? `${tables[0]}_${tables[1]}`
4585
+ });
4586
+ }
4587
+ static morphMany(relatedModel, morphName) {
4588
+ const key = `morphMany:${morphName}`;
4589
+ this.relationDefs.set(key, {
4590
+ type: "morphMany",
4591
+ relatedModel,
4592
+ foreignKey: `${morphName}_id`,
4593
+ localKey: "id",
4594
+ morphName
4595
+ });
4596
+ }
4597
+ // ─── Eager Loading ─────────────────────────────────────────
4598
+ static with(...relations) {
4599
+ for (const rel of relations) {
4600
+ this.eagerLoads.set(rel, true);
4601
+ }
4602
+ }
4603
+ // ─── Query Shortcuts ───────────────────────────────────────
4604
+ static async all() {
4605
+ const rows = await this.query().get();
4606
+ const instances = rows.map((row) => this.hydrate(row));
4607
+ await this.loadRelations(instances);
4608
+ return instances;
4609
+ }
4610
+ static async find(id) {
4611
+ const row = await this.query().find(id);
4612
+ if (!row) return null;
4613
+ const instance = this.hydrate(row);
4614
+ await this.loadRelations([instance]);
4615
+ return instance;
4616
+ }
4617
+ static async where(column, value) {
4618
+ return this.query().where(column, value);
4619
+ }
4620
+ static async create(data) {
4621
+ const id = await this.query().insert(data);
4622
+ return this.find(id);
4623
+ }
4624
+ static async updateOrCreate(attributes, values) {
4625
+ const qb = this.query();
4626
+ for (const [key, value] of Object.entries(attributes)) {
4627
+ qb.where(key, value);
4628
+ }
4629
+ const existing = await qb.first();
4630
+ if (existing) {
4631
+ const mergeValues = values ?? attributes;
4632
+ const id = existing.id;
4633
+ const updateQb = new QueryBuilder(this.queryRunner, this.table);
4634
+ for (const [key, value] of Object.entries(attributes)) {
4635
+ updateQb.where(key, value);
4636
+ }
4637
+ await updateQb.update(mergeValues);
4638
+ return this.find(id);
4639
+ }
4640
+ return this.create({ ...attributes, ...values });
4641
+ }
4642
+ // ─── Instance Methods ──────────────────────────────────────
4643
+ async save() {
4644
+ const ModelClass = this.constructor;
4645
+ const id = this.id;
4646
+ if (id !== void 0 && id !== null) {
4647
+ await ModelClass.query().where("id", id).update(this.getData());
4648
+ } else {
4649
+ const newId = await ModelClass.query().insert(this.getData());
4650
+ this.id = newId;
4651
+ }
4652
+ }
4653
+ async delete() {
4654
+ const ModelClass = this.constructor;
4655
+ const id = this.id;
4656
+ if (id !== void 0 && id !== null) {
4657
+ await ModelClass.query().where("id", id).delete();
4658
+ }
4659
+ }
4660
+ // ─── Relation Loader ───────────────────────────────────────
4661
+ static async loadRelations(instances) {
4662
+ if (instances.length === 0) return;
4663
+ for (const [key, def] of this.relationDefs) {
4664
+ const shouldLoad = this.eagerLoads.size === 0 || this.eagerLoads.has(key.split(":")[1] ?? key);
4665
+ if (!shouldLoad) continue;
4666
+ const localIds = instances.map((i) => i[def.localKey]).filter(Boolean);
4667
+ if (def.type === "belongsTo") {
4668
+ if (!def.relatedModel.queryRunner) def.relatedModel.setConnection(this.queryRunner);
4669
+ const related = await def.relatedModel.query().whereIn(def.localKey, localIds).get();
4670
+ for (const inst of instances) {
4671
+ inst._relations[key] = related.find((r) => r[def.localKey] === inst[def.foreignKey]) ?? null;
4672
+ }
4673
+ }
4674
+ if (def.type === "hasMany") {
4675
+ if (!def.relatedModel.queryRunner) def.relatedModel.setConnection(this.queryRunner);
4676
+ const related = await def.relatedModel.query().whereIn(def.foreignKey, localIds).get();
4677
+ for (const inst of instances) {
4678
+ inst._relations[key] = related.filter((r) => r[def.foreignKey] === inst[def.localKey]);
4679
+ }
4680
+ }
4681
+ if (def.type === "hasOne") {
4682
+ if (!def.relatedModel.queryRunner) def.relatedModel.setConnection(this.queryRunner);
4683
+ const related = await def.relatedModel.query().whereIn(def.foreignKey, localIds).get();
4684
+ for (const inst of instances) {
4685
+ inst._relations[key] = related.find((r) => r[def.foreignKey] === inst[def.localKey]) ?? null;
4686
+ }
4687
+ }
4688
+ if (def.type === "belongsToMany" && def.pivotTable) {
4689
+ if (!def.relatedModel.queryRunner) def.relatedModel.setConnection(this.queryRunner);
4690
+ const pivotQb = new QueryBuilder(this.queryRunner, def.pivotTable);
4691
+ const pivotRows = await pivotQb.whereIn(def.foreignKey, localIds).get();
4692
+ const relatedIds = pivotRows.map((r) => r[def.localKey]);
4693
+ if (relatedIds.length > 0) {
4694
+ const related = await def.relatedModel.query().whereIn("id", relatedIds).get();
4695
+ for (const inst of instances) {
4696
+ const pivots = pivotRows.filter((p) => p[def.foreignKey] === inst[def.localKey]);
4697
+ inst._relations[key] = pivots.map((p) => related.find((r) => r.id === p[def.localKey])).filter(Boolean);
4698
+ }
4699
+ } else {
4700
+ for (const inst of instances) {
4701
+ inst._relations[key] = [];
4702
+ }
4703
+ }
4704
+ }
4705
+ if (def.type === "morphMany" && def.morphName) {
4706
+ if (!def.relatedModel.queryRunner) def.relatedModel.setConnection(this.queryRunner);
4707
+ const related = await def.relatedModel.query().where(`${def.morphName}_type`, this.name).whereIn(`${def.morphName}_id`, localIds).get();
4708
+ for (const inst of instances) {
4709
+ inst._relations[key] = related.filter((r) => r[`${def.morphName}_id`] === inst[def.localKey]);
4710
+ }
4711
+ }
4712
+ }
4713
+ }
4714
+ // ─── Internal Helpers ──────────────────────────────────────
4715
+ static hydrate(data) {
4716
+ const instance = new this();
4717
+ for (const [key, value] of Object.entries(data)) {
4718
+ instance[key] = value;
4719
+ }
4720
+ return instance;
4721
+ }
4722
+ getData() {
4723
+ const data = {};
4724
+ const instance = this;
4725
+ const prototype = Object.getPrototypeOf(this);
4726
+ const ownKeys = [
4727
+ ...Object.getOwnPropertyNames(instance),
4728
+ ...Object.keys(instance)
4729
+ ];
4730
+ const classKeys = /* @__PURE__ */ new Set([
4731
+ ...Object.getOwnPropertyNames(prototype),
4732
+ "save",
4733
+ "delete",
4734
+ "getData"
4735
+ ]);
4736
+ for (const key of ownKeys) {
4737
+ if (typeof key === "string" && !classKeys.has(key) && key !== "constructor" && !key.startsWith("_")) {
4738
+ data[key] = instance[key];
4739
+ }
4740
+ }
4741
+ return data;
4742
+ }
4743
+ };
4744
+
3480
4745
  // src/server/events/index.ts
3481
4746
  import { EventEmitter } from "events";
3482
4747
  var Event = class {
@@ -3964,6 +5229,7 @@ function storage() {
3964
5229
  }
3965
5230
 
3966
5231
  // src/server/index.ts
5232
+ init_errors();
3967
5233
  var SuperApp = class {
3968
5234
  router;
3969
5235
  container;
@@ -3972,6 +5238,10 @@ var SuperApp = class {
3972
5238
  globalPipeline;
3973
5239
  started = false;
3974
5240
  serverPromise;
5241
+ onErrorHandler = null;
5242
+ onNotFoundHandler = null;
5243
+ shutdownHandlers = [];
5244
+ shuttingDown = false;
3975
5245
  constructor(options = {}) {
3976
5246
  this.container = options.container ?? new Container();
3977
5247
  this.router = new Router();
@@ -4039,7 +5309,7 @@ var SuperApp = class {
4039
5309
  [route.method],
4040
5310
  handlerPath,
4041
5311
  async (ctx) => {
4042
- const instance = createControllerInstance2(ctrl, ctx);
5312
+ const instance = createControllerInstance(ctrl, ctx);
4043
5313
  const handlerFn = instance[handlerName];
4044
5314
  if (typeof handlerFn === "function") {
4045
5315
  await handlerFn.call(instance, ctx);
@@ -4071,6 +5341,18 @@ var SuperApp = class {
4071
5341
  view(_engine) {
4072
5342
  return this;
4073
5343
  }
5344
+ onError(handler) {
5345
+ this.onErrorHandler = handler;
5346
+ return this;
5347
+ }
5348
+ notFound(handler) {
5349
+ this.onNotFoundHandler = handler;
5350
+ return this;
5351
+ }
5352
+ onShutdown(handler) {
5353
+ this.shutdownHandlers.push(handler);
5354
+ return this;
5355
+ }
4074
5356
  getServer() {
4075
5357
  return this.serverInstance;
4076
5358
  }
@@ -4086,17 +5368,38 @@ var SuperApp = class {
4086
5368
  );
4087
5369
  const listenPort = port ?? 3e3;
4088
5370
  const listenHost = host ?? "0.0.0.0";
4089
- return new Promise((resolve2) => {
5371
+ return new Promise((resolve4) => {
4090
5372
  const raw = this.serverInstance.raw;
4091
5373
  raw.listen(listenPort, listenHost, () => {
4092
- resolve2();
5374
+ resolve4();
4093
5375
  });
4094
5376
  });
4095
5377
  }
4096
5378
  listen(port, callback) {
4097
5379
  this.serverPromise = this.start(port).then(() => {
5380
+ const shutdown = async (signal) => {
5381
+ if (this.shuttingDown) return;
5382
+ this.shuttingDown = true;
5383
+ console.log(`
5384
+ \u26A0\uFE0F Received ${signal}. Starting graceful shutdown...`);
5385
+ for (const handler of this.shutdownHandlers) {
5386
+ try {
5387
+ await handler();
5388
+ } catch {
5389
+ }
5390
+ }
5391
+ await this.close();
5392
+ console.log("\u2713 Server shut down gracefully");
5393
+ process.exit(0);
5394
+ };
5395
+ process.on("SIGINT", () => shutdown("SIGINT"));
5396
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
5397
+ if (process.stdin && process.stdin.isTTY) {
5398
+ process.stdin.on("end", () => shutdown("stdin end"));
5399
+ }
4098
5400
  callback?.();
4099
5401
  });
5402
+ return this;
4100
5403
  }
4101
5404
  async close() {
4102
5405
  if (this.serverInstance !== void 0) {
@@ -4113,8 +5416,20 @@ var SuperApp = class {
4113
5416
  async handleRequest(req, res) {
4114
5417
  const resolvedRoute = this.router.resolve(req.method, req.path);
4115
5418
  if (resolvedRoute === null) {
5419
+ if (this.onNotFoundHandler !== null) {
5420
+ const ctx2 = {
5421
+ request: req,
5422
+ response: res,
5423
+ params: {},
5424
+ query: req.query,
5425
+ container: this.container
5426
+ };
5427
+ await this.onNotFoundHandler(ctx2);
5428
+ if (!res.headersSent) await res.flush();
5429
+ return;
5430
+ }
4116
5431
  res.status(HttpStatus.NOT_FOUND).json({
4117
- error: "Not Found",
5432
+ error: "NOT_FOUND",
4118
5433
  message: `Route ${req.method} ${req.path} not found`
4119
5434
  });
4120
5435
  await res.flush();
@@ -4128,15 +5443,26 @@ var SuperApp = class {
4128
5443
  query: req.query,
4129
5444
  container: this.container
4130
5445
  };
4131
- await this.globalPipeline.run(ctx, async () => {
4132
- const routePipeline = new MiddlewarePipeline();
4133
- for (const mw of resolvedRoute.middleware) {
4134
- routePipeline.use(mw);
4135
- }
4136
- await routePipeline.run(ctx, async () => {
4137
- await resolvedRoute.handler(ctx);
5446
+ try {
5447
+ await this.globalPipeline.run(ctx, async () => {
5448
+ const routePipeline = new MiddlewarePipeline();
5449
+ for (const mw of resolvedRoute.middleware) {
5450
+ routePipeline.use(mw);
5451
+ }
5452
+ await routePipeline.run(ctx, async () => {
5453
+ await resolvedRoute.handler(ctx);
5454
+ });
4138
5455
  });
4139
- });
5456
+ } catch (err) {
5457
+ if (this.onErrorHandler !== null) {
5458
+ await this.onErrorHandler(
5459
+ err instanceof Error ? err : new Error(String(err)),
5460
+ ctx
5461
+ );
5462
+ } else {
5463
+ throw err;
5464
+ }
5465
+ }
4140
5466
  if (!res.headersSent) {
4141
5467
  await res.flush();
4142
5468
  }
@@ -4145,37 +5471,53 @@ var SuperApp = class {
4145
5471
  function speexjs(options) {
4146
5472
  return new SuperApp(options);
4147
5473
  }
4148
- function createControllerInstance2(controller, ctx) {
5474
+ function createControllerInstance(controller, ctx) {
4149
5475
  const instance = new controller();
4150
5476
  instance.__ctx = ctx;
4151
5477
  instance.__container = ctx.container;
4152
5478
  return instance;
4153
5479
  }
4154
5480
  export {
5481
+ BadRequestException,
4155
5482
  Cache,
4156
5483
  ColumnDefinition,
5484
+ ConflictException,
4157
5485
  DatabaseConnection,
4158
5486
  Event,
5487
+ ForbiddenException,
4159
5488
  ForeignKeyDefinition,
5489
+ HttpException,
5490
+ InternalServerErrorException,
4160
5491
  LocalDisk,
5492
+ MethodNotAllowedException,
4161
5493
  Migrator,
5494
+ Model,
4162
5495
  MysqlDialect,
5496
+ NotFoundException,
4163
5497
  Pagination,
4164
5498
  PostgresqlDialect,
4165
5499
  QueryBuilder,
4166
5500
  SchemaBuilder,
4167
5501
  Seeder,
5502
+ ServiceUnavailableException,
4168
5503
  SqliteDialect,
4169
5504
  Storage,
4170
5505
  SuperApp,
4171
5506
  TableBlueprint,
5507
+ TooManyRequestsException,
4172
5508
  URLBuilder,
5509
+ UnauthorizedException,
5510
+ UnprocessableEntityException,
5511
+ ValidationException,
4173
5512
  cacheResponse,
5513
+ createControllerInstance,
4174
5514
  createDialect,
4175
5515
  createDriver,
4176
5516
  createEvent,
4177
5517
  createStorage,
4178
5518
  event,
5519
+ normalizeError,
5520
+ registerExceptionHandler,
4179
5521
  registerMacro,
4180
5522
  responseMacros,
4181
5523
  speexjs,