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.
- package/README.md +32 -60
- package/dist/cli/index.js +300 -91
- package/dist/cli/index.js.map +1 -1
- package/dist/{index-CMkhSDh7.d.ts → index-C4xilc_E.d.ts} +4 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2989 -1864
- package/dist/index.js.map +1 -1
- package/dist/rpc/index.d.ts +1 -1
- package/dist/schema/index.d.ts +36 -30
- package/dist/schema/index.js +12 -229
- package/dist/schema/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +3 -1
- package/dist/server/auth/index.js +18 -12
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +2 -1
- package/dist/server/controller/index.d.ts +2 -1
- package/dist/server/database/index.d.ts +34 -2
- package/dist/server/database/index.js +1101 -30
- package/dist/server/database/index.js.map +1 -1
- package/dist/server/gate/index.d.ts +2 -1
- package/dist/server/http/index.js +19 -2
- package/dist/server/http/index.js.map +1 -1
- package/dist/server/index.d.ts +58 -4
- package/dist/server/index.js +2058 -716
- package/dist/server/index.js.map +1 -1
- package/dist/server/middleware/index.d.ts +2 -1
- package/dist/server/middleware/index.js +85 -34
- package/dist/server/middleware/index.js.map +1 -1
- package/dist/server/router/index.d.ts +2 -1
- package/dist/server/router/index.js +8 -6
- package/dist/server/router/index.js.map +1 -1
- package/dist/{types-CXH8hPei.d.ts → types-aW38f63o.d.ts} +1 -1
- package/package.json +142 -136
package/dist/server/index.js
CHANGED
|
@@ -1,216 +1,176 @@
|
|
|
1
|
-
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
|
285
|
-
|
|
286
|
-
"
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
)
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
".
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
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
|
-
|
|
730
|
-
|
|
731
|
-
|
|
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
|
-
|
|
734
|
-
return
|
|
938
|
+
if (process.env.NODE_ENV === "production") {
|
|
939
|
+
return new InternalServerErrorException();
|
|
735
940
|
}
|
|
736
|
-
|
|
737
|
-
|
|
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
|
-
|
|
740
|
-
|
|
741
|
-
|
|
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
|
-
|
|
744
|
-
|
|
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
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
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
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
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
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
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
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
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
|
-
|
|
1705
|
+
var identifier = (str) => `"${str.replace(/"/g, '""')}"`;
|
|
1706
|
+
var defer = (x) => () => x;
|
|
789
1707
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
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
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
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 (
|
|
808
|
-
|
|
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 (
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
}
|
|
1767
|
+
if (!addon.isInitialized) {
|
|
1768
|
+
addon.setErrorConstructor(SqliteError);
|
|
1769
|
+
addon.isInitialized = true;
|
|
814
1770
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
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
|
-
|
|
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
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
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
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
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
|
-
|
|
856
|
-
this.
|
|
1815
|
+
singleton(name, factory) {
|
|
1816
|
+
this.bindings.set(name, { factory, singleton: true });
|
|
857
1817
|
return this;
|
|
858
1818
|
}
|
|
859
|
-
|
|
860
|
-
this.
|
|
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
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
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
|
-
|
|
884
|
-
|
|
885
|
-
|
|
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
|
-
|
|
888
|
-
|
|
889
|
-
|
|
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
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
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
|
|
911
|
-
|
|
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((
|
|
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
|
-
|
|
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 {
|
|
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((
|
|
1021
|
-
readStream.on("end", () =>
|
|
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
|
|
3010
|
+
let pool = null;
|
|
2010
3011
|
const dialect = new MysqlDialect();
|
|
2011
3012
|
const driver = {
|
|
2012
3013
|
async connect() {
|
|
2013
|
-
|
|
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 (
|
|
2024
|
-
await
|
|
2025
|
-
|
|
3029
|
+
if (pool !== null) {
|
|
3030
|
+
await pool.end();
|
|
3031
|
+
pool = null;
|
|
2026
3032
|
}
|
|
2027
3033
|
},
|
|
2028
3034
|
isConnected() {
|
|
2029
|
-
return
|
|
3035
|
+
return pool !== null;
|
|
2030
3036
|
},
|
|
2031
3037
|
async raw(sql, bindings) {
|
|
2032
|
-
if (
|
|
3038
|
+
if (pool === null) {
|
|
2033
3039
|
throw new Error("Database not connected. Call connect() first.");
|
|
2034
3040
|
}
|
|
2035
|
-
const [rows, fields] = await
|
|
3041
|
+
const [rows, fields] = await pool.execute(sql, bindings ?? []);
|
|
2036
3042
|
return { rows, fields };
|
|
2037
3043
|
},
|
|
2038
3044
|
async transaction(callback) {
|
|
2039
|
-
if (
|
|
2040
|
-
|
|
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
|
-
|
|
2045
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
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 (
|
|
2467
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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 =
|
|
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((
|
|
5371
|
+
return new Promise((resolve4) => {
|
|
4090
5372
|
const raw = this.serverInstance.raw;
|
|
4091
5373
|
raw.listen(listenPort, listenHost, () => {
|
|
4092
|
-
|
|
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: "
|
|
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
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
await
|
|
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
|
|
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,
|