speexjs 0.2.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.
Files changed (67) hide show
  1. package/README.md +555 -0
  2. package/dist/cli/index.d.ts +1 -0
  3. package/dist/cli/index.js +1017 -0
  4. package/dist/cli/index.js.map +1 -0
  5. package/dist/client/index.d.ts +73 -0
  6. package/dist/client/index.js +927 -0
  7. package/dist/client/index.js.map +1 -0
  8. package/dist/client/signals/index.d.ts +62 -0
  9. package/dist/client/signals/index.js +248 -0
  10. package/dist/client/signals/index.js.map +1 -0
  11. package/dist/client/vdom/index.d.ts +50 -0
  12. package/dist/client/vdom/index.js +540 -0
  13. package/dist/client/vdom/index.js.map +1 -0
  14. package/dist/client/vdom/jsx-runtime.d.ts +9 -0
  15. package/dist/client/vdom/jsx-runtime.js +203 -0
  16. package/dist/client/vdom/jsx-runtime.js.map +1 -0
  17. package/dist/index-CMkhSDh7.d.ts +97 -0
  18. package/dist/index.d.ts +18 -0
  19. package/dist/index.js +6402 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/jsx-DGrnv8QB.d.ts +8 -0
  22. package/dist/response-Ca8KWK5_.d.ts +173 -0
  23. package/dist/rpc/index.d.ts +70 -0
  24. package/dist/rpc/index.js +136 -0
  25. package/dist/rpc/index.js.map +1 -0
  26. package/dist/schema/index.d.ts +231 -0
  27. package/dist/schema/index.js +1160 -0
  28. package/dist/schema/index.js.map +1 -0
  29. package/dist/server/auth/index.d.ts +61 -0
  30. package/dist/server/auth/index.js +462 -0
  31. package/dist/server/auth/index.js.map +1 -0
  32. package/dist/server/cache/index.d.ts +45 -0
  33. package/dist/server/cache/index.js +238 -0
  34. package/dist/server/cache/index.js.map +1 -0
  35. package/dist/server/container/index.d.ts +20 -0
  36. package/dist/server/container/index.js +62 -0
  37. package/dist/server/container/index.js.map +1 -0
  38. package/dist/server/controller/index.d.ts +37 -0
  39. package/dist/server/controller/index.js +139 -0
  40. package/dist/server/controller/index.js.map +1 -0
  41. package/dist/server/database/index.d.ts +461 -0
  42. package/dist/server/database/index.js +1977 -0
  43. package/dist/server/database/index.js.map +1 -0
  44. package/dist/server/events/index.d.ts +29 -0
  45. package/dist/server/events/index.js +159 -0
  46. package/dist/server/events/index.js.map +1 -0
  47. package/dist/server/gate/index.d.ts +36 -0
  48. package/dist/server/gate/index.js +169 -0
  49. package/dist/server/gate/index.js.map +1 -0
  50. package/dist/server/http/index.d.ts +45 -0
  51. package/dist/server/http/index.js +871 -0
  52. package/dist/server/http/index.js.map +1 -0
  53. package/dist/server/index.d.ts +79 -0
  54. package/dist/server/index.js +4185 -0
  55. package/dist/server/index.js.map +1 -0
  56. package/dist/server/middleware/index.d.ts +5 -0
  57. package/dist/server/middleware/index.js +416 -0
  58. package/dist/server/middleware/index.js.map +1 -0
  59. package/dist/server/router/index.d.ts +5 -0
  60. package/dist/server/router/index.js +231 -0
  61. package/dist/server/router/index.js.map +1 -0
  62. package/dist/server/storage/index.d.ts +66 -0
  63. package/dist/server/storage/index.js +244 -0
  64. package/dist/server/storage/index.js.map +1 -0
  65. package/dist/session-guard-CZeN87L9.d.ts +48 -0
  66. package/dist/types-CXH8hPei.d.ts +38 -0
  67. package/package.json +138 -0
@@ -0,0 +1,871 @@
1
+ // src/server/http/status.ts
2
+ var HttpStatus = {
3
+ OK: 200,
4
+ CREATED: 201,
5
+ ACCEPTED: 202,
6
+ NO_CONTENT: 204,
7
+ RESET_CONTENT: 205,
8
+ PARTIAL_CONTENT: 206,
9
+ MOVED_PERMANENTLY: 301,
10
+ FOUND: 302,
11
+ SEE_OTHER: 303,
12
+ NOT_MODIFIED: 304,
13
+ TEMPORARY_REDIRECT: 307,
14
+ PERMANENT_REDIRECT: 308,
15
+ BAD_REQUEST: 400,
16
+ UNAUTHORIZED: 401,
17
+ PAYMENT_REQUIRED: 402,
18
+ FORBIDDEN: 403,
19
+ NOT_FOUND: 404,
20
+ METHOD_NOT_ALLOWED: 405,
21
+ NOT_ACCEPTABLE: 406,
22
+ REQUEST_TIMEOUT: 408,
23
+ CONFLICT: 409,
24
+ GONE: 410,
25
+ LENGTH_REQUIRED: 411,
26
+ PRECONDITION_FAILED: 412,
27
+ PAYLOAD_TOO_LARGE: 413,
28
+ URI_TOO_LONG: 414,
29
+ UNSUPPORTED_MEDIA_TYPE: 415,
30
+ UNPROCESSABLE_ENTITY: 422,
31
+ TOO_MANY_REQUESTS: 429,
32
+ INTERNAL_SERVER_ERROR: 500,
33
+ NOT_IMPLEMENTED: 501,
34
+ BAD_GATEWAY: 502,
35
+ SERVICE_UNAVAILABLE: 503,
36
+ GATEWAY_TIMEOUT: 504,
37
+ HTTP_VERSION_NOT_SUPPORTED: 505
38
+ };
39
+ var statusTextMap = {
40
+ 200: "OK",
41
+ 201: "Created",
42
+ 202: "Accepted",
43
+ 204: "No Content",
44
+ 205: "Reset Content",
45
+ 206: "Partial Content",
46
+ 301: "Moved Permanently",
47
+ 302: "Found",
48
+ 303: "See Other",
49
+ 304: "Not Modified",
50
+ 307: "Temporary Redirect",
51
+ 308: "Permanent Redirect",
52
+ 400: "Bad Request",
53
+ 401: "Unauthorized",
54
+ 402: "Payment Required",
55
+ 403: "Forbidden",
56
+ 404: "Not Found",
57
+ 405: "Method Not Allowed",
58
+ 406: "Not Acceptable",
59
+ 408: "Request Timeout",
60
+ 409: "Conflict",
61
+ 410: "Gone",
62
+ 411: "Length Required",
63
+ 412: "Precondition Failed",
64
+ 413: "Payload Too Large",
65
+ 414: "URI Too Long",
66
+ 415: "Unsupported Media Type",
67
+ 422: "Unprocessable Entity",
68
+ 429: "Too Many Requests",
69
+ 500: "Internal Server Error",
70
+ 501: "Not Implemented",
71
+ 502: "Bad Gateway",
72
+ 503: "Service Unavailable",
73
+ 504: "Gateway Timeout",
74
+ 505: "HTTP Version Not Supported"
75
+ };
76
+ function statusText(code) {
77
+ const text = statusTextMap[code];
78
+ if (text !== void 0) return text;
79
+ if (code >= 100 && code < 200) return "Informational";
80
+ if (code >= 200 && code < 300) return "Success";
81
+ if (code >= 300 && code < 400) return "Redirection";
82
+ if (code >= 400 && code < 500) return "Client Error";
83
+ if (code >= 500 && code < 600) return "Server Error";
84
+ return "Unknown";
85
+ }
86
+
87
+ // src/server/http/headers.ts
88
+ var HeadersMap = class {
89
+ data;
90
+ constructor(initial) {
91
+ this.data = /* @__PURE__ */ new Map();
92
+ if (initial) {
93
+ for (const key of Object.keys(initial)) {
94
+ const value = initial[key];
95
+ if (value !== void 0) {
96
+ this.set(key, Array.isArray(value) ? value.join(", ") : value);
97
+ }
98
+ }
99
+ }
100
+ }
101
+ get(name) {
102
+ const values = this.data.get(name.toLowerCase());
103
+ if (values !== void 0 && values.length > 0) {
104
+ return values[0];
105
+ }
106
+ return void 0;
107
+ }
108
+ getAll(name) {
109
+ const values = this.data.get(name.toLowerCase());
110
+ return values ?? [];
111
+ }
112
+ set(name, value) {
113
+ this.data.set(name.toLowerCase(), [value]);
114
+ }
115
+ append(name, value) {
116
+ const key = name.toLowerCase();
117
+ const existing = this.data.get(key);
118
+ if (existing !== void 0) {
119
+ existing.push(value);
120
+ } else {
121
+ this.data.set(key, [value]);
122
+ }
123
+ }
124
+ has(name) {
125
+ return this.data.has(name.toLowerCase());
126
+ }
127
+ delete(name) {
128
+ this.data.delete(name.toLowerCase());
129
+ }
130
+ *entries() {
131
+ for (const [key, values] of this.data) {
132
+ for (const value of values) {
133
+ yield [key, value];
134
+ }
135
+ }
136
+ }
137
+ *keys() {
138
+ for (const key of this.data.keys()) {
139
+ yield key;
140
+ }
141
+ }
142
+ *values() {
143
+ for (const [, values] of this.data) {
144
+ for (const value of values) {
145
+ yield value;
146
+ }
147
+ }
148
+ }
149
+ toJSON() {
150
+ const result = {};
151
+ for (const [key, values] of this.data) {
152
+ result[key] = values.length === 1 ? values[0] : values;
153
+ }
154
+ return result;
155
+ }
156
+ toNodeHeaders() {
157
+ const result = {};
158
+ for (const [key, values] of this.data) {
159
+ if (key === "set-cookie") {
160
+ result[key] = values;
161
+ } else {
162
+ result[key] = values.join(", ");
163
+ }
164
+ }
165
+ return result;
166
+ }
167
+ get size() {
168
+ return this.data.size;
169
+ }
170
+ [Symbol.iterator]() {
171
+ return this.entries();
172
+ }
173
+ };
174
+
175
+ // src/server/http/cookie.ts
176
+ function parseCookies(header) {
177
+ const result = {};
178
+ if (!header) return result;
179
+ const pairs = header.split(";");
180
+ for (const pair of pairs) {
181
+ const trimmed = pair.trim();
182
+ if (!trimmed) continue;
183
+ const eqIndex = trimmed.indexOf("=");
184
+ if (eqIndex === -1) {
185
+ result[trimmed] = "";
186
+ continue;
187
+ }
188
+ const name = trimmed.slice(0, eqIndex).trim();
189
+ let value = trimmed.slice(eqIndex + 1).trim();
190
+ if (value.startsWith('"') && value.endsWith('"')) {
191
+ value = value.slice(1, -1);
192
+ }
193
+ if (name) {
194
+ result[decodeURIComponent(name)] = decodeURIComponent(value);
195
+ }
196
+ }
197
+ return result;
198
+ }
199
+ function serializeCookieValue(name, value) {
200
+ return `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
201
+ }
202
+ function serializeCookie(name, value, options) {
203
+ const parts = [serializeCookieValue(name, value)];
204
+ if (options) {
205
+ if (options.maxAge !== void 0) {
206
+ parts.push(`Max-Age=${Math.floor(options.maxAge)}`);
207
+ }
208
+ if (options.expires !== void 0) {
209
+ parts.push(`Expires=${options.expires.toUTCString()}`);
210
+ }
211
+ if (options.path !== void 0) {
212
+ parts.push(`Path=${options.path}`);
213
+ } else {
214
+ parts.push("Path=/");
215
+ }
216
+ if (options.domain !== void 0) {
217
+ parts.push(`Domain=${options.domain}`);
218
+ }
219
+ if (options.secure) {
220
+ parts.push("Secure");
221
+ }
222
+ if (options.httpOnly) {
223
+ parts.push("HttpOnly");
224
+ }
225
+ if (options.sameSite !== void 0) {
226
+ parts.push(`SameSite=${options.sameSite}`);
227
+ }
228
+ }
229
+ return parts.join("; ");
230
+ }
231
+ function clearCookie(name, options) {
232
+ return serializeCookie(name, "", {
233
+ ...options,
234
+ maxAge: 0,
235
+ expires: /* @__PURE__ */ new Date(0)
236
+ });
237
+ }
238
+
239
+ // src/server/http/upload.ts
240
+ import { randomUUID } from "crypto";
241
+ import { writeFile, readFile, unlink, mkdir } from "fs/promises";
242
+ import { join, extname, basename, dirname } from "path";
243
+ import { tmpdir } from "os";
244
+ var IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
245
+ "image/jpeg",
246
+ "image/png",
247
+ "image/gif",
248
+ "image/webp",
249
+ "image/svg+xml",
250
+ "image/bmp",
251
+ "image/tiff",
252
+ "image/avif"
253
+ ]);
254
+ var VIDEO_MIME_TYPES = /* @__PURE__ */ new Set([
255
+ "video/mp4",
256
+ "video/mpeg",
257
+ "video/webm",
258
+ "video/ogg",
259
+ "video/quicktime",
260
+ "video/x-msvideo",
261
+ "video/x-matroska"
262
+ ]);
263
+ var SuperUploadedFile = class _SuperUploadedFile {
264
+ fieldName;
265
+ originalName;
266
+ mimeType;
267
+ size;
268
+ path;
269
+ extension;
270
+ buffer;
271
+ constructor(opts) {
272
+ this.fieldName = opts.fieldName;
273
+ this.originalName = opts.originalName;
274
+ this.mimeType = opts.mimeType;
275
+ this.size = opts.size;
276
+ this.path = opts.path;
277
+ this.extension = extname(opts.originalName).toLowerCase();
278
+ this.buffer = opts.buffer ?? null;
279
+ }
280
+ async move(destination, filename) {
281
+ const destName = filename ?? basename(this.path);
282
+ const destPath = join(destination, destName);
283
+ await mkdir(dirname(destPath), { recursive: true });
284
+ const buf = await this.toBuffer();
285
+ await writeFile(destPath, buf);
286
+ return destPath;
287
+ }
288
+ async toBuffer() {
289
+ if (this.buffer !== null) return this.buffer;
290
+ this.buffer = await readFile(this.path);
291
+ return this.buffer;
292
+ }
293
+ toBase64() {
294
+ if (this.buffer === null) {
295
+ throw new Error(
296
+ "Buffer not loaded. Call toBuffer() first or read the file into memory."
297
+ );
298
+ }
299
+ return this.buffer.toString("base64");
300
+ }
301
+ isImage() {
302
+ return IMAGE_MIME_TYPES.has(this.mimeType);
303
+ }
304
+ isVideo() {
305
+ return VIDEO_MIME_TYPES.has(this.mimeType);
306
+ }
307
+ static async createFromBuffer(fieldName, originalName, mimeType, buffer, tempDir) {
308
+ const tmp = tempDir ?? tmpdir();
309
+ const fileName = `${randomUUID()}${extname(originalName)}`;
310
+ const filePath = join(tmp, fileName);
311
+ await writeFile(filePath, buffer);
312
+ return new _SuperUploadedFile({
313
+ fieldName,
314
+ originalName,
315
+ mimeType: mimeType || "application/octet-stream",
316
+ size: buffer.length,
317
+ path: filePath,
318
+ buffer
319
+ });
320
+ }
321
+ async cleanup() {
322
+ try {
323
+ await unlink(this.path);
324
+ } catch {
325
+ }
326
+ }
327
+ };
328
+
329
+ // src/server/http/request.ts
330
+ var SuperRequest = class {
331
+ raw;
332
+ _headers;
333
+ _query;
334
+ _cookies = null;
335
+ _ip;
336
+ _params = {};
337
+ bodyCache = null;
338
+ _bodyReadPromise = null;
339
+ constructor(raw) {
340
+ this.raw = raw;
341
+ this._headers = new HeadersMap(
342
+ raw.headers
343
+ );
344
+ const parsedUrl = new URL(raw.url ?? "/", "http://localhost");
345
+ this._query = parseQueryParams(parsedUrl.searchParams);
346
+ this._ip = parseIp(raw);
347
+ this.path = parsedUrl.pathname;
348
+ this.url = raw.url ?? "/";
349
+ this.method = (raw.method ?? "GET").toUpperCase();
350
+ }
351
+ method;
352
+ url;
353
+ path;
354
+ get headers() {
355
+ return this._headers;
356
+ }
357
+ get query() {
358
+ return this._query;
359
+ }
360
+ get params() {
361
+ return this._params;
362
+ }
363
+ set params(value) {
364
+ this._params = value;
365
+ }
366
+ get ip() {
367
+ return this._ip;
368
+ }
369
+ async ensureBody() {
370
+ if (this.bodyCache !== null) return this.bodyCache;
371
+ if (this._bodyReadPromise === null) {
372
+ this._bodyReadPromise = this.readBodyFromStream();
373
+ }
374
+ this.bodyCache = await this._bodyReadPromise;
375
+ return this.bodyCache;
376
+ }
377
+ async readBodyFromStream() {
378
+ const chunks = [];
379
+ for await (const chunk of this.raw) {
380
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
381
+ }
382
+ const raw = Buffer.concat(chunks);
383
+ const text = raw.toString("utf-8");
384
+ let json = void 0;
385
+ if (this.isContentType("application/json")) {
386
+ try {
387
+ json = JSON.parse(text);
388
+ } catch {
389
+ json = void 0;
390
+ }
391
+ }
392
+ let formData = null;
393
+ let multipartParsed = null;
394
+ let files = null;
395
+ if (this.isContentType("application/x-www-form-urlencoded")) {
396
+ formData = parseUrlEncoded(text);
397
+ } else if (this.isContentType("multipart/form-data")) {
398
+ const boundary = this.getMultipartBoundary();
399
+ if (boundary !== void 0) {
400
+ multipartParsed = parseMultipartBody(raw, boundary);
401
+ formData = {};
402
+ files = {};
403
+ for (const part of multipartParsed) {
404
+ if (part.type === "field") {
405
+ formData[part.name] = part.value;
406
+ } else if (part.type === "file") {
407
+ const uploadedFile = await SuperUploadedFile.createFromBuffer(
408
+ part.name,
409
+ part.filename,
410
+ part.mimeType,
411
+ part.data
412
+ );
413
+ files[part.name] = uploadedFile;
414
+ }
415
+ }
416
+ }
417
+ }
418
+ return {
419
+ raw,
420
+ text,
421
+ json,
422
+ parsed: json ?? text,
423
+ formData,
424
+ files,
425
+ multipartParsed
426
+ };
427
+ }
428
+ isContentType(expected) {
429
+ const ct = this._headers.get("content-type");
430
+ if (ct === void 0) return false;
431
+ return ct.toLowerCase().startsWith(expected);
432
+ }
433
+ getMultipartBoundary() {
434
+ const ct = this._headers.get("content-type");
435
+ if (ct === void 0) return void 0;
436
+ const match = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
437
+ if (match !== null) {
438
+ return match[1] ?? match[2];
439
+ }
440
+ return void 0;
441
+ }
442
+ async body() {
443
+ const cache = await this.ensureBody();
444
+ return cache.parsed;
445
+ }
446
+ async json() {
447
+ const cache = await this.ensureBody();
448
+ if (cache.json !== void 0) return cache.json;
449
+ throw new Error("Request body is not valid JSON");
450
+ }
451
+ async text() {
452
+ const cache = await this.ensureBody();
453
+ return cache.text;
454
+ }
455
+ async formData() {
456
+ const cache = await this.ensureBody();
457
+ if (cache.formData !== null) return cache.formData;
458
+ if (cache.multipartParsed !== null) {
459
+ const result = {};
460
+ for (const part of cache.multipartParsed) {
461
+ if (part.type === "field") {
462
+ result[part.name] = part.value;
463
+ }
464
+ }
465
+ return result;
466
+ }
467
+ return {};
468
+ }
469
+ async file(name) {
470
+ const cache = await this.ensureBody();
471
+ if (cache.files !== null) {
472
+ return cache.files[name];
473
+ }
474
+ return void 0;
475
+ }
476
+ async files() {
477
+ const cache = await this.ensureBody();
478
+ return cache.files ?? {};
479
+ }
480
+ cookie(name) {
481
+ if (this._cookies === null) {
482
+ const cookieHeader = this._headers.get("cookie");
483
+ this._cookies = cookieHeader !== void 0 ? parseCookies(cookieHeader) : {};
484
+ }
485
+ return this._cookies[name];
486
+ }
487
+ async validate(schema) {
488
+ const data = await this.body();
489
+ const result = schema.validate(data);
490
+ if (!result.success) {
491
+ const messages = (result.errors ?? []).map((e) => {
492
+ const path = e.path ?? "";
493
+ return path ? `${path}: ${e.message}` : e.message;
494
+ }).join("; ");
495
+ throw new ValidationError(messages, result.errors ?? []);
496
+ }
497
+ return result.data;
498
+ }
499
+ isAjax() {
500
+ const requestedWith = this._headers.get("x-requested-with");
501
+ return requestedWith?.toLowerCase() === "xmlhttprequest";
502
+ }
503
+ wantsJson() {
504
+ const accept = this._headers.get("accept");
505
+ if (accept !== void 0 && accept.includes("application/json")) {
506
+ return true;
507
+ }
508
+ return this.isAjax();
509
+ }
510
+ bearerToken() {
511
+ const auth = this._headers.get("authorization");
512
+ if (auth === void 0) return void 0;
513
+ const match = auth.match(/^Bearer\s+(.+)$/i);
514
+ return match?.[1];
515
+ }
516
+ get rawRequest() {
517
+ return this.raw;
518
+ }
519
+ };
520
+ var ValidationError = class extends Error {
521
+ constructor(message, errors) {
522
+ super(message);
523
+ this.errors = errors;
524
+ this.name = "ValidationError";
525
+ }
526
+ errors;
527
+ };
528
+ function parseQueryParams(searchParams) {
529
+ const result = {};
530
+ for (const key of searchParams.keys()) {
531
+ const values = searchParams.getAll(key);
532
+ result[key] = values.length === 1 ? values[0] : values;
533
+ }
534
+ return result;
535
+ }
536
+ function parseIp(req) {
537
+ const forwarded = req.headers["x-forwarded-for"];
538
+ if (forwarded !== void 0) {
539
+ const first = Array.isArray(forwarded) ? forwarded[0] : forwarded.split(",")[0];
540
+ if (first !== void 0) return first.trim();
541
+ }
542
+ const realIp = req.headers["x-real-ip"];
543
+ if (realIp !== void 0) {
544
+ return Array.isArray(realIp) ? realIp[0] : realIp;
545
+ }
546
+ const remote = req.socket.remoteAddress;
547
+ if (remote !== void 0) {
548
+ if (remote.startsWith("::ffff:")) return remote.slice(7);
549
+ return remote;
550
+ }
551
+ return "127.0.0.1";
552
+ }
553
+ function parseUrlEncoded(text) {
554
+ const result = {};
555
+ const pairs = text.split("&");
556
+ for (const pair of pairs) {
557
+ if (!pair) continue;
558
+ const eqIndex = pair.indexOf("=");
559
+ if (eqIndex === -1) {
560
+ result[decodeURIComponent(pair)] = "";
561
+ } else {
562
+ const key = decodeURIComponent(pair.slice(0, eqIndex));
563
+ const value = decodeURIComponent(pair.slice(eqIndex + 1));
564
+ result[key] = value;
565
+ }
566
+ }
567
+ return result;
568
+ }
569
+ function parseMultipartBody(body, boundary) {
570
+ const result = [];
571
+ const boundaryBuffer = Buffer.from(`--${boundary}`);
572
+ let start = 0;
573
+ let searchFrom = 0;
574
+ while (true) {
575
+ const boundaryIndex = body.indexOf(boundaryBuffer, searchFrom);
576
+ if (boundaryIndex === -1) break;
577
+ searchFrom = boundaryIndex + boundaryBuffer.length;
578
+ if (searchFrom < body.length && body[searchFrom] === 45 && body[searchFrom + 1] === 45) {
579
+ break;
580
+ }
581
+ if (searchFrom >= body.length) break;
582
+ if (body[searchFrom] === 13) searchFrom++;
583
+ if (body[searchFrom] === 10) searchFrom++;
584
+ start = searchFrom;
585
+ const nextBoundaryIndex = body.indexOf(boundaryBuffer, searchFrom);
586
+ if (nextBoundaryIndex === -1) break;
587
+ let partEnd = nextBoundaryIndex;
588
+ if (partEnd >= 2 && body[partEnd - 2] === 13 && body[partEnd - 1] === 10) {
589
+ partEnd -= 2;
590
+ }
591
+ const partData = body.slice(start, partEnd);
592
+ const headerEndIndex = partData.indexOf(Buffer.from("\r\n\r\n"));
593
+ if (headerEndIndex === -1) {
594
+ searchFrom = nextBoundaryIndex;
595
+ continue;
596
+ }
597
+ const headerSection = partData.slice(0, headerEndIndex).toString("utf-8");
598
+ const contentData = partData.slice(headerEndIndex + 4);
599
+ const disposition = parseDisposition(headerSection);
600
+ if (disposition === void 0) {
601
+ searchFrom = nextBoundaryIndex;
602
+ continue;
603
+ }
604
+ if (disposition.filename !== void 0) {
605
+ const contentType = parseContentType(headerSection);
606
+ result.push({
607
+ type: "file",
608
+ name: disposition.name,
609
+ filename: disposition.filename,
610
+ mimeType: contentType,
611
+ data: Buffer.from(contentData)
612
+ });
613
+ } else {
614
+ result.push({
615
+ type: "field",
616
+ name: disposition.name,
617
+ value: contentData.toString("utf-8").trim()
618
+ });
619
+ }
620
+ searchFrom = nextBoundaryIndex;
621
+ }
622
+ return result;
623
+ }
624
+ function parseDisposition(headerSection) {
625
+ const match = headerSection.match(
626
+ /content-disposition:\s*form-data;\s*(.+)/i
627
+ );
628
+ if (match === null) return void 0;
629
+ const params = match[1];
630
+ const nameMatch = params.match(/name="([^"]*)"/i);
631
+ const filenameMatch = params.match(/filename="([^"]*)"/i);
632
+ if (nameMatch === null) return void 0;
633
+ return {
634
+ name: nameMatch[1],
635
+ filename: filenameMatch?.[1]
636
+ };
637
+ }
638
+ function parseContentType(headerSection) {
639
+ const match = headerSection.match(/content-type:\s*([^\s;]+)/i);
640
+ return match?.[1] ?? "application/octet-stream";
641
+ }
642
+
643
+ // src/server/http/response.ts
644
+ import { createReadStream, stat } from "fs";
645
+ import { basename as basename2, extname as extname2 } from "path";
646
+ import { promisify } from "util";
647
+ var statAsync = promisify(stat);
648
+ var MIME_TYPES = {
649
+ ".html": "text/html",
650
+ ".css": "text/css",
651
+ ".js": "application/javascript",
652
+ ".mjs": "application/javascript",
653
+ ".json": "application/json",
654
+ ".png": "image/png",
655
+ ".jpg": "image/jpeg",
656
+ ".jpeg": "image/jpeg",
657
+ ".gif": "image/gif",
658
+ ".svg": "image/svg+xml",
659
+ ".webp": "image/webp",
660
+ ".ico": "image/x-icon",
661
+ ".pdf": "application/pdf",
662
+ ".txt": "text/plain",
663
+ ".xml": "application/xml",
664
+ ".zip": "application/zip",
665
+ ".woff": "font/woff",
666
+ ".woff2": "font/woff2",
667
+ ".ttf": "font/ttf",
668
+ ".eot": "application/vnd.ms-fontobject",
669
+ ".mp4": "video/mp4",
670
+ ".webm": "video/webm",
671
+ ".mp3": "audio/mpeg",
672
+ ".wav": "audio/wav"
673
+ };
674
+ var SuperResponse = class {
675
+ raw;
676
+ _statusCode = HttpStatus.OK;
677
+ _headers = new HeadersMap();
678
+ _cookies = [];
679
+ _body = null;
680
+ _sent = false;
681
+ _contentTypeSet = false;
682
+ constructor(raw) {
683
+ this.raw = raw;
684
+ }
685
+ status(code) {
686
+ this._statusCode = code;
687
+ return this;
688
+ }
689
+ header(name, value) {
690
+ this._headers.set(name, value);
691
+ return this;
692
+ }
693
+ setHeader(name, value) {
694
+ return this.header(name, value);
695
+ }
696
+ getHeader(name) {
697
+ return this._headers.get(name);
698
+ }
699
+ removeHeader(name) {
700
+ this._headers.delete(name);
701
+ return this;
702
+ }
703
+ hasHeader(name) {
704
+ return this._headers.has(name);
705
+ }
706
+ type(contentType) {
707
+ this._headers.set("content-type", contentType);
708
+ this._contentTypeSet = true;
709
+ return this;
710
+ }
711
+ json(data, status) {
712
+ if (status !== void 0) this._statusCode = status;
713
+ const body = JSON.stringify(data);
714
+ return this.send(body, void 0, "application/json");
715
+ }
716
+ send(body, status, contentType) {
717
+ if (status !== void 0) this._statusCode = status;
718
+ this._body = body;
719
+ if (contentType !== void 0 && !this._contentTypeSet) {
720
+ this._headers.set("content-type", contentType);
721
+ }
722
+ return this;
723
+ }
724
+ html(html, status) {
725
+ return this.send(html, status, "text/html; charset=utf-8");
726
+ }
727
+ redirect(url, status = HttpStatus.FOUND) {
728
+ this._statusCode = status;
729
+ this._headers.set("location", url);
730
+ this._body = null;
731
+ return this;
732
+ }
733
+ stream(stream, status) {
734
+ if (status !== void 0) this._statusCode = status;
735
+ this.flushHeaders();
736
+ this.raw.statusCode = this._statusCode;
737
+ stream.pipe(this.raw);
738
+ stream.on("end", () => {
739
+ this._sent = true;
740
+ });
741
+ stream.on("error", (_err) => {
742
+ if (!this._sent) {
743
+ this._sent = true;
744
+ this.raw.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
745
+ this.raw.end();
746
+ }
747
+ });
748
+ return this;
749
+ }
750
+ async file(filePath, options) {
751
+ const fullPath = options?.root ? joinPath(options.root, filePath) : filePath;
752
+ try {
753
+ const stats = await statAsync(fullPath);
754
+ if (!stats.isFile()) {
755
+ this._statusCode = HttpStatus.NOT_FOUND;
756
+ this._body = null;
757
+ return this;
758
+ }
759
+ const ext = extname2(fullPath);
760
+ const mimeType = MIME_TYPES[ext] ?? "application/octet-stream";
761
+ this._headers.set("content-type", mimeType);
762
+ this._headers.set("content-length", String(stats.size));
763
+ if (options?.cacheControl !== false) {
764
+ const maxAge = options?.maxAge ?? 0;
765
+ this._headers.set("cache-control", `public, max-age=${maxAge}`);
766
+ }
767
+ if (options?.lastModified !== false) {
768
+ this._headers.set("last-modified", stats.mtime.toUTCString());
769
+ }
770
+ if (options?.headers !== void 0) {
771
+ for (const [key, value] of Object.entries(options.headers)) {
772
+ this._headers.set(key, value);
773
+ }
774
+ }
775
+ this.flushHeaders();
776
+ this.raw.statusCode = this._statusCode;
777
+ const readStream = createReadStream(fullPath);
778
+ readStream.pipe(this.raw);
779
+ readStream.on("end", () => {
780
+ this._sent = true;
781
+ });
782
+ readStream.on("error", () => {
783
+ if (!this._sent) {
784
+ this._sent = true;
785
+ this.raw.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
786
+ this.raw.end();
787
+ }
788
+ });
789
+ } catch {
790
+ this._statusCode = HttpStatus.NOT_FOUND;
791
+ this._body = null;
792
+ }
793
+ return this;
794
+ }
795
+ async download(filePath, filename) {
796
+ const downloadName = filename ?? basename2(filePath);
797
+ this._headers.set(
798
+ "content-disposition",
799
+ `attachment; filename="${downloadName}"`
800
+ );
801
+ await this.file(filePath);
802
+ return this;
803
+ }
804
+ attachment(filename) {
805
+ if (filename !== void 0) {
806
+ this._headers.set(
807
+ "content-disposition",
808
+ `attachment; filename="${filename}"`
809
+ );
810
+ } else {
811
+ this._headers.set("content-disposition", "attachment");
812
+ }
813
+ return this;
814
+ }
815
+ cookie(name, value, options) {
816
+ this._cookies.push(serializeCookie(name, value, options));
817
+ return this;
818
+ }
819
+ clearCookie(name, options) {
820
+ this._cookies.push(clearCookie(name, options));
821
+ return this;
822
+ }
823
+ get statusCode() {
824
+ return this._statusCode;
825
+ }
826
+ get headersSent() {
827
+ return this._sent;
828
+ }
829
+ get rawResponse() {
830
+ return this.raw;
831
+ }
832
+ async flush() {
833
+ if (this._sent) return;
834
+ this._sent = true;
835
+ this.flushHeaders();
836
+ this.raw.statusCode = this._statusCode;
837
+ if (this._body !== null) {
838
+ this.raw.end(this._body);
839
+ } else {
840
+ this.raw.end();
841
+ }
842
+ }
843
+ flushHeaders() {
844
+ if (this._cookies.length > 0) {
845
+ this.raw.setHeader("Set-Cookie", this._cookies);
846
+ }
847
+ for (const [name, value] of this._headers.entries()) {
848
+ if (name.toLowerCase() !== "set-cookie") {
849
+ this.raw.setHeader(name, value);
850
+ }
851
+ }
852
+ }
853
+ };
854
+ function joinPath(root, filePath) {
855
+ const normalizedRoot = root.replace(/\\/g, "/").replace(/\/$/, "");
856
+ const normalizedPath = filePath.replace(/\\/g, "/").replace(/^\//, "");
857
+ return `${normalizedRoot}/${normalizedPath}`;
858
+ }
859
+ export {
860
+ HeadersMap,
861
+ HttpStatus,
862
+ SuperRequest,
863
+ SuperResponse,
864
+ SuperUploadedFile,
865
+ ValidationError,
866
+ clearCookie,
867
+ parseCookies,
868
+ serializeCookie,
869
+ statusText
870
+ };
871
+ //# sourceMappingURL=index.js.map