elit 3.0.0 → 3.0.2
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/dist/build.d.ts +4 -12
- package/dist/build.d.ts.map +1 -0
- package/dist/chokidar.d.ts +7 -9
- package/dist/chokidar.d.ts.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +17 -4
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/dom.d.ts +7 -14
- package/dist/dom.d.ts.map +1 -0
- package/dist/el.d.ts +19 -191
- package/dist/el.d.ts.map +1 -0
- package/dist/fs.d.ts +35 -35
- package/dist/fs.d.ts.map +1 -0
- package/dist/hmr.d.ts +3 -3
- package/dist/hmr.d.ts.map +1 -0
- package/dist/http.d.ts +20 -22
- package/dist/http.d.ts.map +1 -0
- package/dist/https.d.ts +12 -15
- package/dist/https.d.ts.map +1 -0
- package/dist/index.d.ts +10 -629
- package/dist/index.d.ts.map +1 -0
- package/dist/mime-types.d.ts +9 -9
- package/dist/mime-types.d.ts.map +1 -0
- package/dist/path.d.ts +22 -19
- package/dist/path.d.ts.map +1 -0
- package/dist/router.d.ts +10 -17
- package/dist/router.d.ts.map +1 -0
- package/dist/runtime.d.ts +5 -6
- package/dist/runtime.d.ts.map +1 -0
- package/dist/server.d.ts +105 -7
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +14 -2
- package/dist/server.mjs +14 -2
- package/dist/state.d.ts +21 -27
- package/dist/state.d.ts.map +1 -0
- package/dist/style.d.ts +14 -55
- package/dist/style.d.ts.map +1 -0
- package/dist/types.d.ts +26 -240
- package/dist/types.d.ts.map +1 -0
- package/dist/ws.d.ts +14 -17
- package/dist/ws.d.ts.map +1 -0
- package/dist/wss.d.ts +16 -16
- package/dist/wss.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/build.ts +337 -0
- package/src/chokidar.ts +401 -0
- package/src/cli.ts +638 -0
- package/src/config.ts +205 -0
- package/src/dom.ts +817 -0
- package/src/el.ts +164 -0
- package/src/fs.ts +727 -0
- package/src/hmr.ts +137 -0
- package/src/http.ts +775 -0
- package/src/https.ts +411 -0
- package/src/index.ts +14 -0
- package/src/mime-types.ts +222 -0
- package/src/path.ts +493 -0
- package/src/router.ts +237 -0
- package/src/runtime.ts +97 -0
- package/src/server.ts +1290 -0
- package/src/state.ts +468 -0
- package/src/style.ts +524 -0
- package/{dist/types-Du6kfwTm.d.ts → src/types.ts} +58 -141
- package/src/ws.ts +506 -0
- package/src/wss.ts +241 -0
- package/dist/build.d.mts +0 -20
- package/dist/chokidar.d.mts +0 -134
- package/dist/dom.d.mts +0 -87
- package/dist/el.d.mts +0 -207
- package/dist/fs.d.mts +0 -255
- package/dist/hmr.d.mts +0 -38
- package/dist/http.d.mts +0 -163
- package/dist/https.d.mts +0 -108
- package/dist/index.d.mts +0 -629
- package/dist/mime-types.d.mts +0 -48
- package/dist/path.d.mts +0 -163
- package/dist/router.d.mts +0 -47
- package/dist/runtime.d.mts +0 -97
- package/dist/server.d.mts +0 -7
- package/dist/state.d.mts +0 -111
- package/dist/style.d.mts +0 -159
- package/dist/types-C0nGi6MX.d.mts +0 -346
- package/dist/types.d.mts +0 -452
- package/dist/ws.d.mts +0 -195
- 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
|
+
};
|