elit 3.0.1 → 3.0.3

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 (87) hide show
  1. package/dist/build.d.ts +4 -12
  2. package/dist/build.d.ts.map +1 -0
  3. package/dist/chokidar.d.ts +7 -9
  4. package/dist/chokidar.d.ts.map +1 -0
  5. package/dist/cli.d.ts +6 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +250 -21
  8. package/dist/config.d.ts +29 -0
  9. package/dist/config.d.ts.map +1 -0
  10. package/dist/dom.d.ts +7 -14
  11. package/dist/dom.d.ts.map +1 -0
  12. package/dist/el.d.ts +19 -191
  13. package/dist/el.d.ts.map +1 -0
  14. package/dist/fs.d.ts +35 -35
  15. package/dist/fs.d.ts.map +1 -0
  16. package/dist/hmr.d.ts +3 -3
  17. package/dist/hmr.d.ts.map +1 -0
  18. package/dist/http.d.ts +20 -22
  19. package/dist/http.d.ts.map +1 -0
  20. package/dist/https.d.ts +12 -15
  21. package/dist/https.d.ts.map +1 -0
  22. package/dist/index.d.ts +10 -629
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/mime-types.d.ts +9 -9
  25. package/dist/mime-types.d.ts.map +1 -0
  26. package/dist/path.d.ts +22 -19
  27. package/dist/path.d.ts.map +1 -0
  28. package/dist/router.d.ts +10 -17
  29. package/dist/router.d.ts.map +1 -0
  30. package/dist/runtime.d.ts +5 -6
  31. package/dist/runtime.d.ts.map +1 -0
  32. package/dist/server.d.ts +109 -7
  33. package/dist/server.d.ts.map +1 -0
  34. package/dist/server.js +712 -137
  35. package/dist/server.mjs +711 -137
  36. package/dist/state.d.ts +21 -27
  37. package/dist/state.d.ts.map +1 -0
  38. package/dist/style.d.ts +14 -55
  39. package/dist/style.d.ts.map +1 -0
  40. package/dist/types.d.ts +26 -240
  41. package/dist/types.d.ts.map +1 -0
  42. package/dist/ws.d.ts +14 -17
  43. package/dist/ws.d.ts.map +1 -0
  44. package/dist/wss.d.ts +16 -16
  45. package/dist/wss.d.ts.map +1 -0
  46. package/package.json +3 -2
  47. package/src/build.ts +337 -0
  48. package/src/chokidar.ts +401 -0
  49. package/src/cli.ts +638 -0
  50. package/src/config.ts +205 -0
  51. package/src/dom.ts +817 -0
  52. package/src/el.ts +164 -0
  53. package/src/fs.ts +727 -0
  54. package/src/hmr.ts +137 -0
  55. package/src/http.ts +775 -0
  56. package/src/https.ts +411 -0
  57. package/src/index.ts +14 -0
  58. package/src/mime-types.ts +222 -0
  59. package/src/path.ts +493 -0
  60. package/src/router.ts +237 -0
  61. package/src/runtime.ts +97 -0
  62. package/src/server.ts +1593 -0
  63. package/src/state.ts +468 -0
  64. package/src/style.ts +524 -0
  65. package/{dist/types-Du6kfwTm.d.ts → src/types.ts} +58 -141
  66. package/src/ws.ts +506 -0
  67. package/src/wss.ts +241 -0
  68. package/dist/build.d.mts +0 -20
  69. package/dist/chokidar.d.mts +0 -134
  70. package/dist/dom.d.mts +0 -87
  71. package/dist/el.d.mts +0 -207
  72. package/dist/fs.d.mts +0 -255
  73. package/dist/hmr.d.mts +0 -38
  74. package/dist/http.d.mts +0 -163
  75. package/dist/https.d.mts +0 -108
  76. package/dist/index.d.mts +0 -629
  77. package/dist/mime-types.d.mts +0 -48
  78. package/dist/path.d.mts +0 -163
  79. package/dist/router.d.mts +0 -47
  80. package/dist/runtime.d.mts +0 -97
  81. package/dist/server.d.mts +0 -7
  82. package/dist/state.d.mts +0 -111
  83. package/dist/style.d.mts +0 -159
  84. package/dist/types-C0nGi6MX.d.mts +0 -346
  85. package/dist/types.d.mts +0 -452
  86. package/dist/ws.d.mts +0 -195
  87. package/dist/wss.d.mts +0 -108
package/src/https.ts ADDED
@@ -0,0 +1,411 @@
1
+ /**
2
+ * HTTPS module with unified API across runtimes
3
+ * Optimized for maximum performance across Node.js, Bun, and Deno
4
+ */
5
+
6
+ import { EventEmitter } from 'events';
7
+ import type {
8
+ IncomingMessage,
9
+ ServerResponse,
10
+ RequestListener,
11
+ RequestOptions,
12
+ } from './http';
13
+ import { runtime, isNode, isBun, isDeno } from './runtime';
14
+
15
+ /**
16
+ * Helper: Queue callback (eliminates duplication in callback handling)
17
+ */
18
+ function queueCallback(callback?: () => void): void {
19
+ if (callback) queueMicrotask(callback);
20
+ }
21
+
22
+ /**
23
+ * Helper: Create error Response (eliminates duplication in error handling)
24
+ */
25
+ function createErrorResponse(): Response {
26
+ return new Response('Internal Server Error', { status: 500 });
27
+ }
28
+
29
+ /**
30
+ * Helper: Create address object (eliminates duplication in address() method)
31
+ */
32
+ function createAddress(port: number, address: string, family = 'IPv4'): { port: number; family: string; address: string } {
33
+ return { port, family, address };
34
+ }
35
+
36
+ /**
37
+ * Helper: Emit listening and queue callback (eliminates duplication in Bun/Deno listen)
38
+ */
39
+ function emitListeningWithCallback(server: Server, callback?: () => void): void {
40
+ server._listening = true;
41
+ server.emit('listening');
42
+ queueCallback(callback);
43
+ }
44
+
45
+ /**
46
+ * Helper: Close server and emit events (eliminates duplication in Bun/Deno close)
47
+ */
48
+ function closeAndEmit(server: Server, callback?: (err?: Error) => void): void {
49
+ server._listening = false;
50
+ server.emit('close');
51
+ if (callback) queueMicrotask(() => callback());
52
+ }
53
+
54
+ /**
55
+ * Helper: Lazy-load http module classes (eliminates duplication in require('./http'))
56
+ */
57
+ function loadHttpClasses(): { IncomingMessage: any; ServerResponse: any } {
58
+ const httpModule = require('./http');
59
+ return {
60
+ IncomingMessage: httpModule.IncomingMessage,
61
+ ServerResponse: httpModule.ServerResponse
62
+ };
63
+ }
64
+
65
+ // Lazy-load native https module for Node.js
66
+ let https: any;
67
+
68
+ /**
69
+ * HTTPS Server options
70
+ */
71
+ export interface ServerOptions {
72
+ IncomingMessage?: typeof IncomingMessage;
73
+ ServerResponse?: typeof ServerResponse;
74
+ // TLS/SSL options
75
+ key?: string | Buffer | Array<string | Buffer>;
76
+ cert?: string | Buffer | Array<string | Buffer>;
77
+ ca?: string | Buffer | Array<string | Buffer>;
78
+ passphrase?: string;
79
+ pfx?: string | Buffer | Array<string | Buffer>;
80
+ dhparam?: string | Buffer;
81
+ ecdhCurve?: string;
82
+ honorCipherOrder?: boolean;
83
+ requestCert?: boolean;
84
+ rejectUnauthorized?: boolean;
85
+ NPNProtocols?: string[] | Buffer[] | Uint8Array[] | Buffer | Uint8Array;
86
+ ALPNProtocols?: string[] | Buffer[] | Uint8Array[] | Buffer | Uint8Array;
87
+ SNICallback?: (servername: string, cb: (err: Error | null, ctx?: any) => void) => void;
88
+ sessionTimeout?: number;
89
+ ticketKeys?: Buffer;
90
+ // Bun-specific
91
+ tls?: {
92
+ key?: string | Buffer;
93
+ cert?: string | Buffer;
94
+ ca?: string | Buffer;
95
+ passphrase?: string;
96
+ dhParamsFile?: string;
97
+ };
98
+ }
99
+
100
+ /**
101
+ * HTTPS Server - Optimized for each runtime
102
+ */
103
+ export class Server extends EventEmitter {
104
+ private nativeServer?: any;
105
+ private requestListener?: RequestListener;
106
+ public _listening: boolean = false;
107
+ private options: ServerOptions;
108
+
109
+ constructor(options: ServerOptions, requestListener?: RequestListener) {
110
+ super();
111
+ this.options = options;
112
+ this.requestListener = requestListener;
113
+ }
114
+
115
+ listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this;
116
+ listen(port?: number, hostname?: string, listeningListener?: () => void): this;
117
+ listen(port?: number, listeningListener?: () => void): this;
118
+ listen(options?: { port?: number; hostname?: string; backlog?: number }, listeningListener?: () => void): this;
119
+ listen(...args: any[]): this {
120
+ let port = 3000;
121
+ let hostname = '0.0.0.0';
122
+ let callback: (() => void) | undefined;
123
+
124
+ // Optimized argument parsing
125
+ const firstArg = args[0];
126
+ if (typeof firstArg === 'number') {
127
+ port = firstArg;
128
+ const secondArg = args[1];
129
+ if (typeof secondArg === 'string') {
130
+ hostname = secondArg;
131
+ callback = args[2] || args[3];
132
+ } else if (typeof secondArg === 'function') {
133
+ callback = secondArg;
134
+ }
135
+ } else if (firstArg && typeof firstArg === 'object') {
136
+ port = firstArg.port || 3000;
137
+ hostname = firstArg.hostname || '0.0.0.0';
138
+ callback = args[1];
139
+ }
140
+
141
+ const self = this;
142
+
143
+ if (isNode) {
144
+ // Node.js - use native https module
145
+ const { IncomingMessage, ServerResponse } = loadHttpClasses();
146
+ if (!https) https = require('https');
147
+
148
+ this.nativeServer = https.createServer(this.options, (req: any, res: any) => {
149
+ const incomingMessage = new IncomingMessage(req);
150
+ const serverResponse = new ServerResponse(incomingMessage, res);
151
+
152
+ if (self.requestListener) {
153
+ self.requestListener(incomingMessage, serverResponse);
154
+ } else {
155
+ self.emit('request', incomingMessage, serverResponse);
156
+ }
157
+ });
158
+
159
+ this.nativeServer.listen(port, hostname, () => {
160
+ this._listening = true;
161
+ this.emit('listening');
162
+ if (callback) callback();
163
+ });
164
+
165
+ this.nativeServer.on('error', (err: Error) => this.emit('error', err));
166
+ this.nativeServer.on('close', () => {
167
+ this._listening = false;
168
+ this.emit('close');
169
+ });
170
+ } else if (isBun) {
171
+ // Bun - use Bun.serve() with TLS
172
+ const { IncomingMessage, ServerResponse } = loadHttpClasses();
173
+
174
+ const tlsOptions: any = {
175
+ port,
176
+ hostname,
177
+ fetch: (req: Request) => {
178
+ return new Promise<Response>((resolve) => {
179
+ const incomingMessage = new IncomingMessage(req);
180
+ const serverResponse = new ServerResponse();
181
+
182
+ serverResponse._setResolver(resolve);
183
+
184
+ if (self.requestListener) {
185
+ self.requestListener(incomingMessage, serverResponse);
186
+ } else {
187
+ self.emit('request', incomingMessage, serverResponse);
188
+ }
189
+ });
190
+ },
191
+ error: (error: Error) => {
192
+ this.emit('error', error);
193
+ return createErrorResponse();
194
+ },
195
+ };
196
+
197
+ // Add TLS configuration
198
+ if (this.options.key || this.options.cert) {
199
+ tlsOptions.tls = {
200
+ key: this.options.key,
201
+ cert: this.options.cert,
202
+ ca: this.options.ca,
203
+ passphrase: this.options.passphrase,
204
+ };
205
+ } else if (this.options.tls) {
206
+ tlsOptions.tls = this.options.tls;
207
+ }
208
+
209
+ // @ts-ignore
210
+ this.nativeServer = Bun.serve(tlsOptions);
211
+
212
+ emitListeningWithCallback(this, callback);
213
+ } else if (isDeno) {
214
+ // Deno - use Deno.serve() with TLS
215
+ const { IncomingMessage, ServerResponse } = loadHttpClasses();
216
+
217
+ const serveOptions: any = {
218
+ port,
219
+ hostname,
220
+ handler: (req: Request) => {
221
+ return new Promise<Response>((resolve) => {
222
+ const incomingMessage = new IncomingMessage(req);
223
+ const serverResponse = new ServerResponse();
224
+
225
+ serverResponse._setResolver(resolve);
226
+
227
+ if (self.requestListener) {
228
+ self.requestListener(incomingMessage, serverResponse);
229
+ } else {
230
+ self.emit('request', incomingMessage, serverResponse);
231
+ }
232
+ });
233
+ },
234
+ onError: (error: Error) => {
235
+ this.emit('error', error);
236
+ return createErrorResponse();
237
+ },
238
+ };
239
+
240
+ // Add TLS configuration for Deno
241
+ if (this.options.key && this.options.cert) {
242
+ // @ts-ignore
243
+ serveOptions.cert = this.options.cert;
244
+ // @ts-ignore
245
+ serveOptions.key = this.options.key;
246
+ }
247
+
248
+ // @ts-ignore
249
+ this.nativeServer = Deno.serve(serveOptions);
250
+
251
+ emitListeningWithCallback(this, callback);
252
+ }
253
+
254
+ return this;
255
+ }
256
+
257
+ close(callback?: (err?: Error) => void): this {
258
+ if (!this.nativeServer) {
259
+ if (callback) queueMicrotask(() => callback());
260
+ return this;
261
+ }
262
+
263
+ if (isNode) {
264
+ this.nativeServer.close(callback);
265
+ } else if (isBun) {
266
+ this.nativeServer.stop();
267
+ closeAndEmit(this, callback);
268
+ } else if (isDeno) {
269
+ // @ts-ignore
270
+ this.nativeServer.shutdown();
271
+ closeAndEmit(this, callback);
272
+ }
273
+
274
+ return this;
275
+ }
276
+
277
+ address(): { port: number; family: string; address: string } | null {
278
+ if (!this.nativeServer) return null;
279
+
280
+ if (isNode) {
281
+ const addr = this.nativeServer.address();
282
+ if (!addr) return null;
283
+ if (typeof addr === 'string') {
284
+ return createAddress(0, addr, 'unix');
285
+ }
286
+ return addr;
287
+ } else if (isBun) {
288
+ return createAddress(this.nativeServer.port, this.nativeServer.hostname);
289
+ } else if (isDeno) {
290
+ // @ts-ignore
291
+ const addr = this.nativeServer.addr;
292
+ return createAddress(addr.port, addr.hostname);
293
+ }
294
+
295
+ return null;
296
+ }
297
+
298
+ get listening(): boolean {
299
+ return this._listening;
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Client request
305
+ */
306
+ export class ClientRequest extends EventEmitter {
307
+ constructor(_url: string | URL, _options: RequestOptions = {}) {
308
+ super();
309
+ }
310
+
311
+ write(_chunk: any): boolean {
312
+ return true;
313
+ }
314
+
315
+ end(callback?: () => void): void {
316
+ queueCallback(callback);
317
+ }
318
+ }
319
+
320
+ /**
321
+ * HTTPS Agent
322
+ */
323
+ export class Agent {
324
+ constructor(public options?: any) {}
325
+ }
326
+
327
+ /**
328
+ * Create HTTPS server
329
+ */
330
+ export function createServer(options: ServerOptions, requestListener?: RequestListener): Server {
331
+ return new Server(options, requestListener);
332
+ }
333
+
334
+ /**
335
+ * Make HTTPS request - optimized per runtime
336
+ */
337
+ export function request(url: string | URL, options?: RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest {
338
+ const urlString = typeof url === 'string' ? url : url.toString();
339
+ const req = new ClientRequest(urlString, options);
340
+
341
+ if (isNode) {
342
+ const { IncomingMessage } = loadHttpClasses();
343
+ if (!https) https = require('https');
344
+
345
+ const nodeReq = https.request(urlString, {
346
+ method: options?.method || 'GET',
347
+ headers: options?.headers,
348
+ timeout: options?.timeout,
349
+ signal: options?.signal,
350
+ }, (res: any) => {
351
+ const incomingMessage = new IncomingMessage(res);
352
+ if (callback) callback(incomingMessage);
353
+ req.emit('response', incomingMessage);
354
+ });
355
+
356
+ nodeReq.on('error', (error: Error) => req.emit('error', error));
357
+ nodeReq.end();
358
+ } else {
359
+ // Bun/Deno - use fetch (automatically handles HTTPS)
360
+ const { IncomingMessage } = loadHttpClasses();
361
+
362
+ queueMicrotask(async () => {
363
+ try {
364
+ const response = await fetch(urlString, {
365
+ method: options?.method || 'GET',
366
+ headers: options?.headers as HeadersInit,
367
+ signal: options?.signal,
368
+ });
369
+
370
+ const fetchRequest = new Request(urlString);
371
+ const incomingMessage = new IncomingMessage(fetchRequest);
372
+ incomingMessage.statusCode = response.status;
373
+ incomingMessage.statusMessage = response.statusText;
374
+
375
+ if (callback) callback(incomingMessage);
376
+ req.emit('response', incomingMessage);
377
+ } catch (error) {
378
+ req.emit('error', error);
379
+ }
380
+ });
381
+ }
382
+
383
+ return req;
384
+ }
385
+
386
+ /**
387
+ * Make HTTPS GET request
388
+ */
389
+ export function get(url: string | URL, options?: RequestOptions, callback?: (res: IncomingMessage) => void): ClientRequest {
390
+ return request(url, { ...options, method: 'GET' }, callback);
391
+ }
392
+
393
+ /**
394
+ * Get current runtime
395
+ */
396
+ export function getRuntime(): 'node' | 'bun' | 'deno' {
397
+ return runtime;
398
+ }
399
+
400
+ /**
401
+ * Default export
402
+ */
403
+ export default {
404
+ createServer,
405
+ request,
406
+ get,
407
+ Server,
408
+ Agent,
409
+ ClientRequest,
410
+ getRuntime,
411
+ };
package/src/index.ts ADDED
@@ -0,0 +1,14 @@
1
+ // Client-side only exports
2
+ export type * from './types';
3
+ export * from './dom';
4
+ export * from './state';
5
+ export * from './style';
6
+ export * from './el';
7
+
8
+ // Client-side Router
9
+ export { createRouter, createRouterView, routerLink } from './router';
10
+ export type { Router, Route, RouteParams, RouteLocation, RouterOptions } from './router';
11
+
12
+ // HMR Client
13
+ export { default as hmr } from './hmr';
14
+ export type { HMRClient } from './hmr';
@@ -0,0 +1,222 @@
1
+ /**
2
+ * MIME Types module with unified API across runtimes
3
+ * Pure implementation without external dependencies
4
+ * Compatible with 'mime-types' package API
5
+ * Works on Node.js, Bun, and Deno
6
+ */
7
+
8
+ import { runtime } from './runtime';
9
+
10
+ /**
11
+ * Common MIME type mappings (for Bun/Deno)
12
+ * Lightweight version with most common types
13
+ */
14
+ const MIME_TYPES: Record<string, string> = {
15
+ // Text
16
+ 'txt': 'text/plain',
17
+ 'html': 'text/html',
18
+ 'htm': 'text/html',
19
+ 'css': 'text/css',
20
+ 'js': 'text/javascript',
21
+ 'mjs': 'text/javascript',
22
+ 'json': 'application/json',
23
+ 'xml': 'application/xml',
24
+ 'csv': 'text/csv',
25
+ 'md': 'text/markdown',
26
+ 'markdown': 'text/x-markdown',
27
+
28
+ // Images
29
+ 'png': 'image/png',
30
+ 'jpg': 'image/jpeg',
31
+ 'jpeg': 'image/jpeg',
32
+ 'gif': 'image/gif',
33
+ 'svg': 'image/svg+xml',
34
+ 'webp': 'image/webp',
35
+ 'ico': 'image/x-icon',
36
+ 'bmp': 'image/bmp',
37
+ 'tiff': 'image/tiff',
38
+ 'tif': 'image/tiff',
39
+
40
+ // Audio
41
+ 'mp3': 'audio/mpeg',
42
+ 'wav': 'audio/wav',
43
+ 'ogg': 'audio/ogg',
44
+ 'aac': 'audio/aac',
45
+ 'm4a': 'audio/mp4',
46
+ 'flac': 'audio/flac',
47
+
48
+ // Video
49
+ 'mp4': 'video/mp4',
50
+ 'webm': 'video/webm',
51
+ 'avi': 'video/x-msvideo',
52
+ 'mov': 'video/quicktime',
53
+ 'mkv': 'video/x-matroska',
54
+ 'flv': 'video/x-flv',
55
+
56
+ // Application
57
+ 'pdf': 'application/pdf',
58
+ 'zip': 'application/zip',
59
+ 'gz': 'application/gzip',
60
+ 'tar': 'application/x-tar',
61
+ 'rar': 'application/x-rar-compressed',
62
+ '7z': 'application/x-7z-compressed',
63
+
64
+ // Documents
65
+ 'doc': 'application/msword',
66
+ 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
67
+ 'xls': 'application/vnd.ms-excel',
68
+ 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
69
+ 'ppt': 'application/vnd.ms-powerpoint',
70
+ 'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
71
+
72
+ // Fonts
73
+ 'woff': 'font/woff',
74
+ 'woff2': 'font/woff2',
75
+ 'ttf': 'font/ttf',
76
+ 'otf': 'font/otf',
77
+ 'eot': 'application/vnd.ms-fontobject',
78
+
79
+ // Web
80
+ 'wasm': 'application/wasm',
81
+ 'manifest': 'application/manifest+json',
82
+
83
+ // Binary
84
+ 'bin': 'application/octet-stream',
85
+ 'exe': 'application/x-msdownload',
86
+ 'dll': 'application/x-msdownload',
87
+
88
+ // TypeScript/Modern JS
89
+ 'ts': 'text/typescript',
90
+ 'tsx': 'text/tsx',
91
+ 'jsx': 'text/jsx',
92
+ };
93
+
94
+ /**
95
+ * Reverse mapping: MIME type to extensions
96
+ */
97
+ const TYPE_TO_EXTENSIONS: Record<string, string[]> = {};
98
+ for (const ext in MIME_TYPES) {
99
+ const type = MIME_TYPES[ext];
100
+ if (!TYPE_TO_EXTENSIONS[type]) {
101
+ TYPE_TO_EXTENSIONS[type] = [];
102
+ }
103
+ TYPE_TO_EXTENSIONS[type].push(ext);
104
+ }
105
+
106
+ /**
107
+ * Charset mappings
108
+ */
109
+ const CHARSETS: Record<string, string> = {
110
+ 'text/plain': 'UTF-8',
111
+ 'text/html': 'UTF-8',
112
+ 'text/css': 'UTF-8',
113
+ 'text/javascript': 'UTF-8',
114
+ 'application/json': 'UTF-8',
115
+ 'application/xml': 'UTF-8',
116
+ 'text/csv': 'UTF-8',
117
+ 'text/markdown': 'UTF-8',
118
+ 'text/x-markdown': 'UTF-8',
119
+ 'text/typescript': 'UTF-8',
120
+ 'text/tsx': 'UTF-8',
121
+ 'text/jsx': 'UTF-8',
122
+ 'application/javascript': 'UTF-8',
123
+ };
124
+
125
+ /**
126
+ * Get the extension from a path
127
+ */
128
+ function getExtension(path: string): string {
129
+ const match = /\.([^./\\]+)$/.exec(path);
130
+ return match ? match[1].toLowerCase() : '';
131
+ }
132
+
133
+ /**
134
+ * Normalize MIME type (remove parameters)
135
+ */
136
+ function normalizeMimeType(type: string): string {
137
+ const match = /^([^;\s]+)/.exec(type);
138
+ return match ? match[1].toLowerCase() : '';
139
+ }
140
+
141
+ /**
142
+ * Lookup MIME type from file path or extension
143
+ */
144
+ export function lookup(path: string): string | false {
145
+ const ext = getExtension(path) || path.toLowerCase();
146
+ return MIME_TYPES[ext] || false;
147
+ }
148
+
149
+ /**
150
+ * Get the default extension for a MIME type
151
+ */
152
+ export function extension(type: string): string | false {
153
+ const normalized = normalizeMimeType(type);
154
+ const exts = TYPE_TO_EXTENSIONS[normalized];
155
+ return exts && exts.length > 0 ? exts[0] : false;
156
+ }
157
+
158
+ /**
159
+ * Get all extensions for a MIME type
160
+ */
161
+ export function extensions(type: string): string[] | undefined {
162
+ const normalized = normalizeMimeType(type);
163
+ return TYPE_TO_EXTENSIONS[normalized];
164
+ }
165
+
166
+ /**
167
+ * Get the default charset for a MIME type
168
+ */
169
+ export function charset(type: string): string | false {
170
+ const normalized = normalizeMimeType(type);
171
+ return CHARSETS[normalized] || false;
172
+ }
173
+
174
+ /**
175
+ * Create a full Content-Type header value
176
+ */
177
+ export function contentType(typeOrExt: string): string | false {
178
+ // Check if it's a file extension or path
179
+ let type: string | false;
180
+ if (typeOrExt.includes('/')) {
181
+ // Already a MIME type
182
+ type = typeOrExt;
183
+ } else {
184
+ // Lookup MIME type
185
+ type = lookup(typeOrExt);
186
+ if (!type) return false;
187
+ }
188
+
189
+ const normalized = normalizeMimeType(type);
190
+ const charsetValue = CHARSETS[normalized];
191
+
192
+ if (charsetValue) {
193
+ return `${normalized}; charset=${charsetValue.toLowerCase()}`;
194
+ }
195
+
196
+ return normalized;
197
+ }
198
+
199
+ /**
200
+ * Get all MIME types
201
+ */
202
+ export const types = MIME_TYPES;
203
+
204
+ /**
205
+ * Get current runtime
206
+ */
207
+ export function getRuntime(): 'node' | 'bun' | 'deno' {
208
+ return runtime;
209
+ }
210
+
211
+ /**
212
+ * Default export
213
+ */
214
+ export default {
215
+ lookup,
216
+ extension,
217
+ extensions,
218
+ charset,
219
+ contentType,
220
+ types,
221
+ getRuntime,
222
+ };