@farming-labs/mini-dev 0.0.2-beta.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/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # mini-dev
2
+
3
+ A minimal dev server with HMR (Hot Module Replacement) for TypeScript, TSX, CSS, and HTML.
4
+
5
+ ## Features
6
+
7
+ - **Zero config** — Works out of the box
8
+ - **TypeScript/TSX** — On-the-fly transpilation via esbuild
9
+ - **HMR** — Hot module replacement without full page reload
10
+ - **Simple API** — Programmatic and CLI usage
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pnpm add @farming-labs/mini-dev
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ### CLI
21
+
22
+ ```bash
23
+ npx @farming-labs/mini-dev
24
+ # Server at http://localhost:3000
25
+
26
+ # Custom port and root
27
+ npx @farming-labs/mini-dev -p 5173 -r ./my-app
28
+ ```
29
+
30
+ ### Programmatic API
31
+
32
+ ```ts
33
+ import { createDevServer } from '@farming-labs/mini-dev';
34
+
35
+ const { url, stop } = await createDevServer({ port: 3000 });
36
+ console.log('Running at', url);
37
+ // await stop(); // when done
38
+ ```
39
+
40
+ ### DevServer Class
41
+
42
+ ```ts
43
+ import { DevServer } from '@farming-labs/mini-dev';
44
+
45
+ const server = new DevServer({
46
+ root: './src',
47
+ port: 3000,
48
+ host: '0.0.0.0',
49
+ verbose: true,
50
+ });
51
+
52
+ const { port, url } = await server.start();
53
+ // await server.stop();
54
+ ```
55
+
56
+ ## Example
57
+
58
+ See the [example](./example) directory:
59
+
60
+ ```bash
61
+ cd example
62
+ pnpm dev
63
+ ```
64
+
65
+ Edit `App.tsx` or `style.css` and save — changes apply via HMR without a full reload.
66
+
67
+ ## API Reference
68
+
69
+ See [docs/API.md](./docs/API.md) for full API documentation.
70
+
71
+ ## Development
72
+
73
+ ```bash
74
+ pnpm install
75
+ pnpm build
76
+ pnpm test
77
+ ```
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=api.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.test.d.ts","sourceRoot":"","sources":["../src/api.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import { describe, it, expect, afterAll } from 'vitest';
2
+ import { createDevServer } from './index.js';
3
+ import { writeFile, rm } from 'node:fs/promises';
4
+ import { mkdtemp } from 'node:fs/promises';
5
+ import { tmpdir } from 'node:os';
6
+ import { join } from 'node:path';
7
+ describe('createDevServer API', () => {
8
+ let instance;
9
+ let root;
10
+ it('starts server and returns url', async () => {
11
+ root = await mkdtemp(join(tmpdir(), 'mini-dev-api-'));
12
+ await writeFile(join(root, 'index.html'), '<html><body>ok</body></html>');
13
+ instance = await createDevServer({ root, port: 3098 });
14
+ expect(instance.port).toBe(3098);
15
+ expect(instance.url).toContain('3098');
16
+ expect(instance.server).toBeDefined();
17
+ expect(typeof instance.stop).toBe('function');
18
+ const res = await fetch(instance.url + '/index.html');
19
+ expect(res.ok).toBe(true);
20
+ });
21
+ afterAll(async () => {
22
+ if (instance)
23
+ await instance.stop();
24
+ if (root)
25
+ await rm(root, { recursive: true, force: true });
26
+ });
27
+ });
28
+ //# sourceMappingURL=api.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.test.js","sourceRoot":"","sources":["../src/api.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,IAAI,QAAqD,CAAC;IAC1D,IAAI,IAAY,CAAC;IAEjB,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;QACtD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,8BAA8B,CAAC,CAAC;QAE1E,QAAQ,GAAG,MAAM,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAEvD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QACtC,MAAM,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAE9C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,KAAK,IAAI,EAAE;QAClB,IAAI,QAAQ;YAAE,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,IAAI;YAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from 'node:path';
3
+ import { DevServer } from './dev-server.js';
4
+ const args = process.argv.slice(2);
5
+ let port = 3000;
6
+ let root = process.cwd();
7
+ let verbose = false;
8
+ for (let i = 0; i < args.length; i++) {
9
+ switch (args[i]) {
10
+ case '-p':
11
+ case '--port':
12
+ port = parseInt(args[++i] ?? '3000', 10);
13
+ break;
14
+ case '-r':
15
+ case '--root':
16
+ root = resolve(args[++i] ?? process.cwd());
17
+ break;
18
+ case '-v':
19
+ case '--verbose':
20
+ verbose = true;
21
+ break;
22
+ case '-h':
23
+ case '--help':
24
+ console.log(`
25
+ mini-dev - Minimal dev server with HMR
26
+
27
+ Usage:
28
+ mini-dev [options]
29
+
30
+ Options:
31
+ -p, --port <number> Port to listen on (default: 3000)
32
+ -r, --root <path> Root directory to serve (default: cwd)
33
+ -v, --verbose Enable verbose logging
34
+ -h, --help Show this help
35
+ `);
36
+ process.exit(0);
37
+ }
38
+ }
39
+ const server = new DevServer({ root, port, verbose });
40
+ await server.start();
41
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,IAAI,IAAI,GAAG,IAAI,CAAC;AAChB,IAAI,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AACzB,IAAI,OAAO,GAAG,KAAK,CAAC;AAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;IACrC,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAChB,KAAK,IAAI,CAAC;QACV,KAAK,QAAQ;YACX,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;YACzC,MAAM;QACR,KAAK,IAAI,CAAC;QACV,KAAK,QAAQ;YACX,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAC3C,MAAM;QACR,KAAK,IAAI,CAAC;QACV,KAAK,WAAW;YACd,OAAO,GAAG,IAAI,CAAC;YACf,MAAM;QACR,KAAK,IAAI,CAAC;QACV,KAAK,QAAQ;YACX,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;CAWjB,CAAC,CAAC;YACG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AACtD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,43 @@
1
+ import type { DevServerOptions } from './types.js';
2
+ /**
3
+ * Mini-DX Dev Server with HMR support.
4
+ * Serves TypeScript/TSX/CSS/HTML with on-the-fly transpilation.
5
+ */
6
+ export declare class DevServer {
7
+ private root;
8
+ private port;
9
+ private host;
10
+ private verbose;
11
+ private ignored;
12
+ private moduleGraph;
13
+ private clients;
14
+ private httpServer;
15
+ private wss;
16
+ private watcher;
17
+ constructor(options?: DevServerOptions);
18
+ private log;
19
+ /**
20
+ * Start the dev server.
21
+ */
22
+ start(): Promise<{
23
+ port: number;
24
+ url: string;
25
+ }>;
26
+ /**
27
+ * Stop the dev server.
28
+ */
29
+ stop(): Promise<void>;
30
+ private handleRequest;
31
+ private redirect;
32
+ private serveHMRClient;
33
+ private serveHtml;
34
+ private serveTypeScript;
35
+ private transformImports;
36
+ private resolveImportPath;
37
+ private addExtension;
38
+ private serveCss;
39
+ private serveStatic;
40
+ private handleFileChange;
41
+ private broadcast;
42
+ }
43
+ //# sourceMappingURL=dev-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,gBAAgB,EAAc,MAAM,YAAY,CAAC;AAsB/D;;;GAGG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,UAAU,CAAgD;IAClE,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,OAAO,CAA0B;gBAE7B,OAAO,GAAE,gBAAqB;IAQ1C,OAAO,CAAC,GAAG;IAMX;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IA6CrD;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAuBb,aAAa;IAgC3B,OAAO,CAAC,QAAQ;YAKF,cAAc;YASd,SAAS;YA0BT,eAAe;IAsC7B,OAAO,CAAC,gBAAgB;IAgDxB,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,YAAY;YAON,QAAQ;YAeR,WAAW;IAiBzB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,SAAS;CAQlB"}
@@ -0,0 +1,330 @@
1
+ import { createServer } from 'node:http';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { existsSync } from 'node:fs';
4
+ import { join, extname, dirname, resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { createRequire } from 'node:module';
7
+ const require = createRequire(import.meta.url);
8
+ const pkg = require(join(dirname(fileURLToPath(import.meta.url)), '../package.json'));
9
+ import { WebSocketServer } from 'ws';
10
+ import chokidar from 'chokidar';
11
+ import { transform } from 'esbuild';
12
+ import { getHMRClient } from './hmr-client.js';
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ const MIME_TYPES = {
15
+ '.html': 'text/html',
16
+ '.js': 'application/javascript',
17
+ '.mjs': 'application/javascript',
18
+ '.ts': 'application/javascript',
19
+ '.tsx': 'application/javascript',
20
+ '.json': 'application/json',
21
+ '.css': 'text/css',
22
+ '.ico': 'image/x-icon',
23
+ '.png': 'image/png',
24
+ '.jpg': 'image/jpeg',
25
+ '.jpeg': 'image/jpeg',
26
+ '.gif': 'image/gif',
27
+ '.svg': 'image/svg+xml',
28
+ '.woff': 'font/woff',
29
+ '.woff2': 'font/woff2',
30
+ };
31
+ /**
32
+ * Mini-DX Dev Server with HMR support.
33
+ * Serves TypeScript/TSX/CSS/HTML with on-the-fly transpilation.
34
+ */
35
+ export class DevServer {
36
+ root;
37
+ port;
38
+ host;
39
+ verbose;
40
+ ignored;
41
+ moduleGraph = new Map();
42
+ clients = new Set();
43
+ httpServer = null;
44
+ wss = null;
45
+ watcher = null;
46
+ constructor(options = {}) {
47
+ this.root = resolve(options.root ?? process.cwd());
48
+ this.port = options.port ?? 3000;
49
+ this.host = options.host ?? '0.0.0.0';
50
+ this.verbose = options.verbose ?? false;
51
+ this.ignored = options.ignored ?? /node_modules/;
52
+ }
53
+ log(...args) {
54
+ if (this.verbose) {
55
+ console.log('[mini-dev]', ...args);
56
+ }
57
+ }
58
+ /**
59
+ * Start the dev server.
60
+ */
61
+ async start() {
62
+ this.httpServer = createServer(this.handleRequest.bind(this));
63
+ this.wss = new WebSocketServer({ server: this.httpServer });
64
+ this.wss.on('connection', (ws) => {
65
+ this.clients.add(ws);
66
+ const c = { dim: '\x1b[2m', green: '\x1b[32m', reset: '\x1b[0m' };
67
+ console.log(`${c.dim}[HMR]${c.reset} ${c.green}client connected${c.reset} (${this.clients.size} total)`);
68
+ ws.on('close', () => {
69
+ this.clients.delete(ws);
70
+ if (this.verbose) {
71
+ console.log(`${c.dim}[HMR]${c.reset} client disconnected`);
72
+ }
73
+ });
74
+ });
75
+ this.watcher = chokidar.watch(this.root, {
76
+ ignored: this.ignored,
77
+ ignoreInitial: true,
78
+ });
79
+ this.watcher.on('change', this.handleFileChange.bind(this));
80
+ const startTime = Date.now();
81
+ return new Promise((resolve) => {
82
+ this.httpServer.listen(this.port, this.host, () => {
83
+ const readyMs = Date.now() - startTime;
84
+ const url = `http://localhost:${this.port}/`;
85
+ const c = {
86
+ dim: '\x1b[2m',
87
+ cyan: '\x1b[36m',
88
+ green: '\x1b[32m',
89
+ bold: '\x1b[1m',
90
+ reset: '\x1b[0m',
91
+ };
92
+ const version = pkg.version ?? '0.0.1';
93
+ console.log(`\n${c.bold}${c.cyan} mini-dev${c.reset} v${version} ${c.dim}ready in ${readyMs}ms${c.reset}\n\n` +
94
+ `${c.green} ➜${c.reset} ${c.dim}Local:${c.reset} ${url}\n` +
95
+ `${c.green} ➜${c.reset} ${c.dim}Network:${c.reset} use --host to expose\n`);
96
+ resolve({ port: this.port, url });
97
+ });
98
+ });
99
+ }
100
+ /**
101
+ * Stop the dev server.
102
+ */
103
+ async stop() {
104
+ if (this.watcher) {
105
+ await this.watcher.close();
106
+ this.watcher = null;
107
+ }
108
+ if (this.wss) {
109
+ for (const client of this.clients) {
110
+ client.close();
111
+ }
112
+ this.clients.clear();
113
+ this.wss.close();
114
+ this.wss = null;
115
+ }
116
+ if (this.httpServer) {
117
+ return new Promise((resolve) => {
118
+ this.httpServer.close(() => {
119
+ this.httpServer = null;
120
+ resolve();
121
+ });
122
+ });
123
+ }
124
+ }
125
+ async handleRequest(req, res) {
126
+ let url = req.url ?? '/';
127
+ const [pathname, search] = url.split('?');
128
+ if (pathname === '/') {
129
+ return this.redirect(res, '/index.html');
130
+ }
131
+ if (pathname === '/@hmr-client') {
132
+ return this.serveHMRClient(res);
133
+ }
134
+ try {
135
+ const ext = extname(pathname);
136
+ if (ext === '.html') {
137
+ await this.serveHtml(pathname, res);
138
+ }
139
+ else if (ext === '.ts' || ext === '.tsx') {
140
+ await this.serveTypeScript(pathname, res);
141
+ }
142
+ else if (ext === '.css') {
143
+ await this.serveCss(pathname, res);
144
+ }
145
+ else {
146
+ await this.serveStatic(pathname, res);
147
+ }
148
+ }
149
+ catch (error) {
150
+ const msg = error instanceof Error ? error.message : String(error);
151
+ this.log('Error serving', pathname, msg);
152
+ res.writeHead(500, { 'Content-Type': 'text/plain' });
153
+ res.end(msg);
154
+ }
155
+ }
156
+ redirect(res, location) {
157
+ res.writeHead(302, { Location: location });
158
+ res.end();
159
+ }
160
+ async serveHMRClient(res) {
161
+ const code = getHMRClient('ws');
162
+ res.writeHead(200, {
163
+ 'Content-Type': 'application/javascript',
164
+ 'Cache-Control': 'no-cache',
165
+ });
166
+ res.end(code);
167
+ }
168
+ async serveHtml(url, res) {
169
+ const filePath = join(this.root, url.slice(1));
170
+ if (!existsSync(filePath)) {
171
+ res.writeHead(404);
172
+ res.end('Not Found');
173
+ return;
174
+ }
175
+ let html = await readFile(filePath, 'utf-8');
176
+ if (!html.includes('@hmr-client') && !html.includes('</head>')) {
177
+ html = html.replace('</html>', '<script type="module" src="/@hmr-client"></script></html>');
178
+ }
179
+ else if (!html.includes('@hmr-client')) {
180
+ html = html.replace('</head>', '<script type="module" src="/@hmr-client"></script></head>');
181
+ }
182
+ res.writeHead(200, {
183
+ 'Content-Type': MIME_TYPES['.html'],
184
+ 'Cache-Control': 'no-cache',
185
+ });
186
+ res.end(html);
187
+ }
188
+ async serveTypeScript(url, res) {
189
+ const cleanPath = url.split('?')[0];
190
+ const filePath = join(this.root, cleanPath.slice(1));
191
+ if (!existsSync(filePath)) {
192
+ res.writeHead(404);
193
+ res.end('Not Found');
194
+ return;
195
+ }
196
+ const code = await readFile(filePath, 'utf-8');
197
+ const ext = extname(filePath);
198
+ const loader = ext === '.tsx' ? 'tsx' : 'ts';
199
+ const result = await transform(code, {
200
+ loader,
201
+ sourcemap: 'inline',
202
+ target: 'esnext',
203
+ format: 'esm',
204
+ });
205
+ const importerDir = '/' + dirname(cleanPath.slice(1));
206
+ const transformed = this.transformImports(result.code, importerDir, cleanPath);
207
+ const timestamp = Date.now();
208
+ this.moduleGraph.set(cleanPath, {
209
+ code: transformed,
210
+ timestamp,
211
+ url: cleanPath,
212
+ });
213
+ res.writeHead(200, {
214
+ 'Content-Type': MIME_TYPES['.ts'],
215
+ 'Cache-Control': 'no-cache',
216
+ });
217
+ res.end(transformed);
218
+ }
219
+ transformImports(code, importerDir, importerPath) {
220
+ const timestamp = Date.now();
221
+ // Rewrite relative imports to include full path and cache-bust
222
+ code = code.replace(/from\s+['"]([^'"]+)['"]/g, (_match, path) => {
223
+ if (path.startsWith('.') || path.startsWith('/')) {
224
+ const resolved = this.resolveImportPath(path, importerDir, importerPath);
225
+ return `from '${resolved}?t=${timestamp}'`;
226
+ }
227
+ return `from '${path}'`;
228
+ });
229
+ code = code.replace(/import\s+\(['"]([^'"]+)['"]\)/g, (_match, path) => {
230
+ if (path.startsWith('.') || path.startsWith('/')) {
231
+ const resolved = this.resolveImportPath(path, importerDir, importerPath);
232
+ return `import('${resolved}?t=${timestamp}')`;
233
+ }
234
+ return `import('${path}')`;
235
+ });
236
+ code = code.replace(/import\s+['"]([^'"]+)['"]/g, (_match, path) => {
237
+ if (path.startsWith('.') || path.startsWith('/')) {
238
+ const resolved = this.resolveImportPath(path, importerDir, importerPath);
239
+ return `import '${resolved}?t=${timestamp}'`;
240
+ }
241
+ return `import '${path}'`;
242
+ });
243
+ // Inject HMR context at start (so import.meta.hot exists before user code runs)
244
+ const hmrInject = `
245
+ if (typeof window !== 'undefined' && window.__MINI_DEV_HOT__) {
246
+ import.meta.hot = window.__MINI_DEV_HOT__(import.meta.url);
247
+ }
248
+ `;
249
+ code = hmrInject.trim() + '\n' + code;
250
+ return code;
251
+ }
252
+ resolveImportPath(path, importerDir, importerPath) {
253
+ if (path.startsWith('/')) {
254
+ const resolved = path;
255
+ if (!extname(resolved)) {
256
+ return this.addExtension(resolved);
257
+ }
258
+ return resolved;
259
+ }
260
+ const base = importerDir === '/' ? '' : importerDir;
261
+ let resolved = join(base, path).replace(/\\/g, '/');
262
+ if (!resolved.startsWith('/'))
263
+ resolved = '/' + resolved;
264
+ if (!extname(resolved)) {
265
+ return this.addExtension(resolved);
266
+ }
267
+ return resolved;
268
+ }
269
+ addExtension(path) {
270
+ if (existsSync(join(this.root, path.slice(1) + '.tsx')))
271
+ return path + '.tsx';
272
+ if (existsSync(join(this.root, path.slice(1) + '.ts')))
273
+ return path + '.ts';
274
+ if (existsSync(join(this.root, path.slice(1) + '.js')))
275
+ return path + '.js';
276
+ return path + '.ts';
277
+ }
278
+ async serveCss(url, res) {
279
+ const filePath = join(this.root, url.slice(1));
280
+ if (!existsSync(filePath)) {
281
+ res.writeHead(404);
282
+ res.end('Not Found');
283
+ return;
284
+ }
285
+ const css = await readFile(filePath, 'utf-8');
286
+ res.writeHead(200, {
287
+ 'Content-Type': MIME_TYPES['.css'],
288
+ 'Cache-Control': 'no-cache',
289
+ });
290
+ res.end(css);
291
+ }
292
+ async serveStatic(url, res) {
293
+ const filePath = join(this.root, url.slice(1));
294
+ if (!existsSync(filePath)) {
295
+ res.writeHead(404);
296
+ res.end('Not Found');
297
+ return;
298
+ }
299
+ const ext = extname(filePath);
300
+ const contentType = MIME_TYPES[ext] ?? 'application/octet-stream';
301
+ const data = await readFile(filePath);
302
+ res.writeHead(200, {
303
+ 'Content-Type': contentType,
304
+ 'Cache-Control': 'no-cache',
305
+ });
306
+ res.end(data);
307
+ }
308
+ handleFileChange(file) {
309
+ const relative = file.replace(this.root, '').replace(/\\/g, '/');
310
+ const url = relative.startsWith('/') ? relative : '/' + relative;
311
+ this.moduleGraph.delete(url);
312
+ const c = { dim: '\x1b[2m', cyan: '\x1b[36m', yellow: '\x1b[33m', reset: '\x1b[0m' };
313
+ console.log(`${c.dim}[HMR]${c.reset} ${c.yellow}file changed${c.reset} ${c.cyan}${url}${c.reset}`);
314
+ const msg = { type: 'update', path: url, timestamp: Date.now() };
315
+ this.broadcast(msg);
316
+ const n = this.clients.size;
317
+ if (n > 0) {
318
+ console.log(`${c.dim}[HMR]${c.reset} update sent to ${n} client${n === 1 ? '' : 's'}`);
319
+ }
320
+ }
321
+ broadcast(message) {
322
+ const data = JSON.stringify(message);
323
+ for (const client of this.clients) {
324
+ if (client.readyState === 1) {
325
+ client.send(data);
326
+ }
327
+ }
328
+ }
329
+ }
330
+ //# sourceMappingURL=dev-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA6C,MAAM,WAAW,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC;AACtF,OAAO,EAAE,eAAe,EAAiC,MAAM,IAAI,CAAC;AACpE,OAAO,QAA4B,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,UAAU,GAA2B;IACzC,OAAO,EAAE,WAAW;IACpB,KAAK,EAAE,wBAAwB;IAC/B,MAAM,EAAE,wBAAwB;IAChC,KAAK,EAAE,wBAAwB;IAC/B,MAAM,EAAE,wBAAwB;IAChC,OAAO,EAAE,kBAAkB;IAC3B,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,cAAc;IACtB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,eAAe;IACvB,OAAO,EAAE,WAAW;IACpB,QAAQ,EAAE,YAAY;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,OAAO,SAAS;IACZ,IAAI,CAAS;IACb,IAAI,CAAS;IACb,IAAI,CAAS;IACb,OAAO,CAAU;IACjB,OAAO,CAAwC;IAC/C,WAAW,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC5C,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IACjC,UAAU,GAA2C,IAAI,CAAC;IAC1D,GAAG,GAA2B,IAAI,CAAC;IACnC,OAAO,GAAqB,IAAI,CAAC;IAEzC,YAAY,UAA4B,EAAE;QACxC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,SAAS,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,cAAc,CAAC;IACnD,CAAC;IAEO,GAAG,CAAC,GAAG,IAAe;QAC5B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAE9D,IAAI,CAAC,GAAG,GAAG,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,EAAE;YAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACrB,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YAClE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,mBAAmB,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,CAAC;YACzG,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBAClB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACxB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACjB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,sBAAsB,CAAC,CAAC;gBAC7D,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;YACvC,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAE5D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,UAAW,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE;gBACjD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;gBACvC,MAAM,GAAG,GAAG,oBAAoB,IAAI,CAAC,IAAI,GAAG,CAAC;gBAC7C,MAAM,CAAC,GAAG;oBACR,GAAG,EAAE,SAAS;oBACd,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE,UAAU;oBACjB,IAAI,EAAE,SAAS;oBACf,KAAK,EAAE,SAAS;iBACjB,CAAC;gBACF,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;gBACvC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,YAAY,OAAO,KAAK,CAAC,CAAC,KAAK,MAAM;oBAChG,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,KAAK,MAAM,GAAG,IAAI;oBAC9D,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,KAAK,yBAAyB,CAC/E,CAAC;gBACF,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;YACpC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAClB,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,IAAI,CAAC,UAAW,CAAC,KAAK,CAAC,GAAG,EAAE;oBAC1B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;oBACvB,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,GAAoB,EAAE,GAAmB;QACnE,IAAI,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;QACzB,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YAE9B,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACtC,CAAC;iBAAM,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBAC3C,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YAC5C,CAAC;iBAAM,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBAC1B,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnE,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;YACzC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;YACrD,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IAEO,QAAQ,CAAC,GAAmB,EAAE,QAAgB;QACpD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3C,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,GAAmB;QAC9C,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAChC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,cAAc,EAAE,wBAAwB;YACxC,eAAe,EAAE,UAAU;SAC5B,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,GAAmB;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,IAAI,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAE7C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/D,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,2DAA2D,CAAC,CAAC;QAC9F,CAAC;aAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACzC,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,SAAS,EACT,2DAA2D,CAC5D,CAAC;QACJ,CAAC;QAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,cAAc,EAAE,UAAU,CAAC,OAAO,CAAC;YACnC,eAAe,EAAE,UAAU;SAC5B,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,GAAW,EAAE,GAAmB;QAC5D,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAErD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAE7C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE;YACnC,MAAM;YACN,SAAS,EAAE,QAAQ;YACnB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QAC/E,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE;YAC9B,IAAI,EAAE,WAAW;YACjB,SAAS;YACT,GAAG,EAAE,SAAS;SACf,CAAC,CAAC;QAEH,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,cAAc,EAAE,UAAU,CAAC,KAAK,CAAC;YACjC,eAAe,EAAE,UAAU;SAC5B,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvB,CAAC;IAEO,gBAAgB,CAAC,IAAY,EAAE,WAAmB,EAAE,YAAoB;QAC9E,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,+DAA+D;QAC/D,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,0BAA0B,EAC1B,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE;YACvB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;gBACzE,OAAO,SAAS,QAAQ,MAAM,SAAS,GAAG,CAAC;YAC7C,CAAC;YACD,OAAO,SAAS,IAAI,GAAG,CAAC;QAC1B,CAAC,CACF,CAAC;QAEF,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,gCAAgC,EAChC,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE;YACvB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;gBACzE,OAAO,WAAW,QAAQ,MAAM,SAAS,IAAI,CAAC;YAChD,CAAC;YACD,OAAO,WAAW,IAAI,IAAI,CAAC;QAC7B,CAAC,CACF,CAAC;QAEF,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,4BAA4B,EAC5B,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE;YACvB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;gBACzE,OAAO,WAAW,QAAQ,MAAM,SAAS,GAAG,CAAC;YAC/C,CAAC;YACD,OAAO,WAAW,IAAI,GAAG,CAAC;QAC5B,CAAC,CACF,CAAC;QAEF,gFAAgF;QAChF,MAAM,SAAS,GAAG;;;;CAIrB,CAAC;QACE,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;QAEtC,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,iBAAiB,CAAC,IAAY,EAAE,WAAmB,EAAE,YAAoB;QAC/E,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACvB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACrC,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;QACpD,IAAI,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,QAAQ,GAAG,GAAG,GAAG,QAAQ,CAAC;QAEzD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEO,YAAY,CAAC,IAAY;QAC/B,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;YAAE,OAAO,IAAI,GAAG,MAAM,CAAC;QAC9E,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,GAAG,KAAK,CAAC;QAC5E,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,GAAG,KAAK,CAAC;QAC5E,OAAO,IAAI,GAAG,KAAK,CAAC;IACtB,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,GAAW,EAAE,GAAmB;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC9C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC;YAClC,eAAe,EAAE,UAAU;SAC5B,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,GAAW,EAAE,GAAmB;QACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,0BAA0B,CAAC;QAClE,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACtC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,cAAc,EAAE,WAAW;YAC3B,eAAe,EAAE,UAAU;SAC5B,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IAEO,gBAAgB,CAAC,IAAY;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,QAAQ,CAAC;QAEjE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAE7B,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QACrF,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAEnG,MAAM,GAAG,GAAG,EAAE,IAAI,EAAE,QAAiB,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QAC1E,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,mBAAmB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,OAA0D;QAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,MAAM,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dev-server.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-server.test.d.ts","sourceRoot":"","sources":["../src/dev-server.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import { DevServer } from './dev-server.js';
3
+ import { mkdtemp, writeFile, rm } from 'node:fs/promises';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ describe('DevServer', () => {
7
+ let server;
8
+ let root;
9
+ const port = 3099;
10
+ beforeAll(async () => {
11
+ root = await mkdtemp(join(tmpdir(), 'mini-dev-test-'));
12
+ await writeFile(join(root, 'index.html'), '<html><head></head><body>Hello</body></html>');
13
+ await writeFile(join(root, 'main.ts'), "console.log('hi');");
14
+ await writeFile(join(root, 'style.css'), 'body { color: red; }');
15
+ server = new DevServer({ root, port, verbose: false });
16
+ await server.start();
17
+ });
18
+ afterAll(async () => {
19
+ await server.stop();
20
+ await rm(root, { recursive: true, force: true });
21
+ });
22
+ it('serves HTML and injects HMR client', async () => {
23
+ const res = await fetch(`http://localhost:${port}/`);
24
+ expect(res.redirected).toBe(true);
25
+ expect(res.url).toContain('index.html');
26
+ const htmlRes = await fetch(`http://localhost:${port}/index.html`);
27
+ const html = await htmlRes.text();
28
+ expect(html).toContain('@hmr-client');
29
+ expect(html).toContain('</head>');
30
+ });
31
+ it('serves TypeScript with transpilation', async () => {
32
+ const res = await fetch(`http://localhost:${port}/main.ts`);
33
+ expect(res.ok).toBe(true);
34
+ const js = await res.text();
35
+ expect(js).toContain('console.log');
36
+ expect(js).toContain('import.meta.hot');
37
+ });
38
+ it('serves CSS', async () => {
39
+ const res = await fetch(`http://localhost:${port}/style.css`);
40
+ expect(res.ok).toBe(true);
41
+ const css = await res.text();
42
+ expect(css).toContain('color: red');
43
+ });
44
+ it('returns 404 for missing files', async () => {
45
+ const res = await fetch(`http://localhost:${port}/nonexistent.html`);
46
+ expect(res.status).toBe(404);
47
+ });
48
+ it('serves HMR client script', async () => {
49
+ const res = await fetch(`http://localhost:${port}/@hmr-client`);
50
+ expect(res.ok).toBe(true);
51
+ const js = await res.text();
52
+ expect(js).toContain('WebSocket');
53
+ expect(js).toContain('__MINI_DEV_HOT__');
54
+ });
55
+ });
56
+ //# sourceMappingURL=dev-server.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-server.test.js","sourceRoot":"","sources":["../src/dev-server.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * HMR client script injected into HTML pages.
3
+ * Auto-injects HMR: re-imports entry on .ts/.tsx change, swaps CSS links.
4
+ */
5
+ export declare function getHMRClient(_wsProtocol: string): string;
6
+ //# sourceMappingURL=hmr-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmr-client.d.ts","sourceRoot":"","sources":["../src/hmr-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAyFxD"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * HMR client script injected into HTML pages.
3
+ * Auto-injects HMR: re-imports entry on .ts/.tsx change, swaps CSS links.
4
+ */
5
+ export function getHMRClient(_wsProtocol) {
6
+ return `
7
+ (function() {
8
+ const wsProto = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
9
+ const socket = new WebSocket(wsProto + '//' + location.host);
10
+
11
+ socket.onopen = () => console.log('[mini-dev] HMR connected');
12
+ socket.onclose = () => console.log('[mini-dev] HMR disconnected');
13
+ socket.onerror = (e) => console.error('[mini-dev] HMR error', e);
14
+
15
+ function getEntryUrl() {
16
+ const scripts = document.querySelectorAll('script[type="module"][src]');
17
+ for (const s of scripts) {
18
+ if (s.src && !s.src.includes('@hmr-client')) {
19
+ try { return new URL(s.src).pathname; } catch { return s.src; }
20
+ }
21
+ }
22
+ return null;
23
+ }
24
+
25
+ const acceptors = new Map();
26
+ function resolvePath(moduleUrl, dep) {
27
+ try { return new URL(dep, moduleUrl.replace(/[^/]+$/, '') + '/').pathname; } catch { return dep.startsWith('/') ? dep : '/' + dep; }
28
+ }
29
+
30
+ window.__MINI_DEV_HOT__ = function(moduleUrl) {
31
+ return {
32
+ accept(deps, callback) {
33
+ if (typeof deps === 'function') { callback = deps; deps = [moduleUrl]; }
34
+ else if (typeof deps === 'string') { deps = [resolvePath(moduleUrl, deps)]; }
35
+ else if (Array.isArray(deps)) { deps = deps.map(d => resolvePath(moduleUrl, d)); }
36
+ else { deps = [moduleUrl]; }
37
+ for (const p of deps) {
38
+ const list = acceptors.get(p) || [];
39
+ list.push({ callback });
40
+ acceptors.set(p, list);
41
+ }
42
+ },
43
+ invalidate() { location.reload(); },
44
+ dispose() {}
45
+ };
46
+ };
47
+
48
+ socket.onmessage = async (event) => {
49
+ try {
50
+ const data = JSON.parse(event.data);
51
+ if (data.type !== 'update') return;
52
+
53
+ const { path, timestamp } = data;
54
+ const url = path.startsWith('/') ? path : '/' + path;
55
+ const fullUrl = url.split('?')[0] + '?t=' + timestamp;
56
+
57
+ console.log('[mini-dev] HMR update:', path);
58
+
59
+ try {
60
+ if (/\\.css(\\?|$)/.test(url)) {
61
+ const pathPart = url.split('?')[0];
62
+ for (const link of document.querySelectorAll('link[rel="stylesheet"]')) {
63
+ if (link.href && link.href.includes(pathPart)) {
64
+ link.href = link.href.replace(/[?&]t=\\d+/, '').replace(/([?&])$/, '') + (link.href.includes('?') ? '&' : '?') + 't=' + timestamp;
65
+ }
66
+ }
67
+ console.log('[mini-dev] CSS updated:', path);
68
+ return;
69
+ }
70
+ const list = acceptors.get(url);
71
+ if (list && list.length > 0) {
72
+ const newModule = await import(/* @vite-ignore */ fullUrl);
73
+ for (const { callback } of list) { callback(newModule); }
74
+ console.log('[mini-dev] Module updated:', path);
75
+ } else {
76
+ const entry = getEntryUrl();
77
+ if (entry) {
78
+ await import(/* @vite-ignore */ entry.split('?')[0] + '?t=' + timestamp);
79
+ console.log('[mini-dev] App refreshed:', entry);
80
+ } else {
81
+ location.reload();
82
+ }
83
+ }
84
+ } catch (err) {
85
+ console.error('[mini-dev] HMR failed for', path, err);
86
+ location.reload();
87
+ }
88
+ } catch (err) {
89
+ console.error('[mini-dev] HMR message error', err);
90
+ }
91
+ };
92
+ })();
93
+ `.trim();
94
+ }
95
+ //# sourceMappingURL=hmr-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmr-client.js","sourceRoot":"","sources":["../src/hmr-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuFR,CAAC,IAAI,EAAE,CAAC;AACT,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * mini-dev - A minimal dev server with HMR for TypeScript/JS/CSS
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { createDevServer } from '@farming-labs/mini-dev';
7
+ *
8
+ * const { server, url } = await createDevServer({ port: 3000 });
9
+ * console.log('Server running at', url);
10
+ *
11
+ * // Later: await server.stop();
12
+ * ```
13
+ */
14
+ export { DevServer } from './dev-server.js';
15
+ export type { DevServerOptions, HMRMessage, ModuleInfo } from './types.js';
16
+ /**
17
+ * Create and start a dev server.
18
+ *
19
+ * @param options - Server configuration
20
+ * @returns The started server instance and URL
21
+ */
22
+ export declare function createDevServer(options?: import('./types.js').DevServerOptions): Promise<{
23
+ server: import("./dev-server.js").DevServer;
24
+ port: number;
25
+ url: string;
26
+ stop(): Promise<void>;
27
+ }>;
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE3E;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,OAAO,YAAY,EAAE,gBAAqB;;;;;GAYxF"}
package/dist/index.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * mini-dev - A minimal dev server with HMR for TypeScript/JS/CSS
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { createDevServer } from '@farming-labs/mini-dev';
7
+ *
8
+ * const { server, url } = await createDevServer({ port: 3000 });
9
+ * console.log('Server running at', url);
10
+ *
11
+ * // Later: await server.stop();
12
+ * ```
13
+ */
14
+ export { DevServer } from './dev-server.js';
15
+ /**
16
+ * Create and start a dev server.
17
+ *
18
+ * @param options - Server configuration
19
+ * @returns The started server instance and URL
20
+ */
21
+ export async function createDevServer(options = {}) {
22
+ const { DevServer } = await import('./dev-server.js');
23
+ const server = new DevServer(options);
24
+ const { port, url } = await server.start();
25
+ return {
26
+ server,
27
+ port,
28
+ url,
29
+ async stop() {
30
+ await server.stop();
31
+ },
32
+ };
33
+ }
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAiD,EAAE;IACvF,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAC3C,OAAO;QACL,MAAM;QACN,IAAI;QACJ,GAAG;QACH,KAAK,CAAC,IAAI;YACR,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Configuration options for the dev server.
3
+ */
4
+ export interface DevServerOptions {
5
+ /** Root directory to serve files from. Defaults to `process.cwd()` */
6
+ root?: string;
7
+ /** Port to listen on. Defaults to `3000` */
8
+ port?: number;
9
+ /** Host to bind to. Defaults to `0.0.0.0` */
10
+ host?: string;
11
+ /** Enable verbose logging */
12
+ verbose?: boolean;
13
+ /** Paths/patterns to ignore when watching. Defaults to `node_modules` */
14
+ ignored?: string | RegExp | (string | RegExp)[];
15
+ }
16
+ /**
17
+ * Module metadata stored in the module graph.
18
+ */
19
+ export interface ModuleInfo {
20
+ code: string;
21
+ timestamp: number;
22
+ url: string;
23
+ }
24
+ /**
25
+ * WebSocket message types for HMR.
26
+ */
27
+ export interface HMRUpdateMessage {
28
+ type: 'update';
29
+ path: string;
30
+ timestamp: number;
31
+ }
32
+ export type HMRMessage = HMRUpdateMessage;
33
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CACjD;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,UAAU,GAAG,gBAAgB,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@farming-labs/mini-dev",
3
+ "version": "0.0.2-beta.2",
4
+ "description": "A minimal dev server with HMR for TypeScript/JS/CSS",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "mini-dev": "./dist/cli.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc && tsc-alias -p tsconfig.json",
22
+ "dev": "tsx src/cli.ts",
23
+ "start": "node dist/cli.js",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "bump": "bumpp",
27
+ "bump:patch": "bumpp --release patch --yes",
28
+ "bump:minor": "bumpp --release minor --yes",
29
+ "bump:major": "bumpp --release major --yes",
30
+ "release": "pnpm build && bumpp && pnpm publish --access public --no-git-checks",
31
+ "release:beta": "pnpm build && bumpp --preid beta && pnpm publish --access public --tag beta --no-git-checks"
32
+ },
33
+ "keywords": [
34
+ "dev-server",
35
+ "hmr",
36
+ "typescript",
37
+ "vite-alternative"
38
+ ],
39
+ "license": "MIT",
40
+ "engines": {
41
+ "node": ">=18.0.0"
42
+ },
43
+ "dependencies": {
44
+ "chokidar": "^4.0.1",
45
+ "esbuild": "^0.24.0",
46
+ "ws": "^8.18.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^22.10.0",
50
+ "@types/ws": "^8.5.13",
51
+ "tsc-alias": "^1.8.10",
52
+ "tsx": "^4.19.2",
53
+ "typescript": "^5.7.2",
54
+ "vitest": "^2.1.6",
55
+ "bumpp": "^10.2.3"
56
+ },
57
+ "packageManager": "pnpm@9.15.0",
58
+ "publishConfig": {
59
+ "access": "public"
60
+ },
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "https://github.com/farming-labs/mini-dev.git"
64
+ },
65
+ "homepage": "https://github.com/farming-labs/mini-dev#readme",
66
+ "bugs": {
67
+ "url": "https://github.com/farming-labs/mini-dev/issues"
68
+ }
69
+ }