cindel 1.0.6 → 1.1.1

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 CHANGED
@@ -23,6 +23,7 @@
23
23
  - HTTP CORS proxy with configurable header injection
24
24
  - WebSocket proxy with header forwarding and message interception
25
25
  - Static file server and automatic `index.html` loader injection
26
+ - Custom route handlers and directory mirroring via Bun's native routing
26
27
  - TLS/HTTPS + WSS support
27
28
  - `/files` endpoint exposing the live watched file list as JSON
28
29
 
@@ -140,8 +141,10 @@ You can even load it through a user script on any domain:
140
141
  | `static` | `string \| false` | `'.'` | Directory to serve static files from. Pass `false` to disable static serving |
141
142
  | `indexPath` | `string` | `'index.html'` | Path to `index.html` |
142
143
  | `injectLoader` | `string` | | Script path injected into `index.html` before `</head>` |
144
+ | `injectPaths` | `Array<string\|{path: string, html: string}>` | `['/']` | Paths where the loader script is injected |
143
145
  | `corsProxy` | `boolean \| string\| CORSProxyConfig` | | Enable the HTTP CORS proxy |
144
146
  | `wsProxy` | `WSProxyConfig` | | Proxy WebSocket connections to an upstream server |
147
+ | `routes` | `Object` | | Custom routes passed directly to `Bun.serve` |
145
148
  | `filesEndpoint` | `boolean \| string` | `'/files'` | Expose the watched file list as JSON. `true` mounts at `/files` |
146
149
  | `configEndpoint` | `boolean \| string` | `'/config'` | Expose the server config as JSON. `false` to disable |
147
150
  | `getFiles` | `() => string[]` | | Override the file list sent to connecting clients |
@@ -262,6 +265,43 @@ new HMRServer({
262
265
 
263
266
  ---
264
267
 
268
+ ### Routing
269
+
270
+ The `routes` option is passed directly to `Bun.serve`. Useful for mocking APIs, serving specific files, or mirroring directories without a separate server process. See [Bun's routing docs](https://bun.sh/docs/api/http#routing) for the full API.
271
+
272
+ ```js
273
+ routes: {
274
+ // Serve a specific file
275
+ '/favicon.ico': new Response(Bun.file('./public/favicon.ico')),
276
+
277
+ // Mock API responses
278
+ '/api/session': Response.json({ user: 'dev', role: 'admin' }),
279
+ '/api/flags': Response.json({ darkMode: true, betaFeatures: false }),
280
+
281
+ // Named params
282
+ '/api/users/:id': req => Response.json({ id: req.params.id }),
283
+
284
+ // Per-method handlers
285
+ '/api/posts': {
286
+ GET: () => new Response("List posts"),
287
+ POST: async req => {
288
+ const body = await req.json();
289
+ return Response.json({ created: true, ...body });
290
+ },
291
+ },
292
+
293
+ // Mirror directory /assets/* served from /dist/assets/*
294
+ '/assets/*': req => new Response(Bun.file(`./dist/assets/${req.params['*']}`)),
295
+
296
+ // SPA fallback
297
+ '/*': new Response(Bun.file('./index.html')),
298
+ }
299
+ ```
300
+
301
+ > **Note:** Avoid paths that overlap with `wsPath`, `filesEndpoint`, `configEndpoint`, or any proxy paths, the server will warn on startup if a collision is detected.
302
+
303
+ ---
304
+
265
305
  ### TLS
266
306
 
267
307
  Pass `tls` to switch the server to HTTPS and WSS. The client's `secure` option or a `wss://` URL flips the client to match.
@@ -442,14 +482,14 @@ client
442
482
  console.log(`Loaded ${files.length} files`);
443
483
  console.log("Server cold patterns:", config.cold);
444
484
  })
445
- .on("reload", ({ file }) => {
485
+ .on("reload", (file) => {
446
486
  console.log(`Hot-reloaded: ${file}`);
447
- applyChanges(file);
487
+ swapPrototype(file);
448
488
  })
449
- .on("add", ({ file }) => {
489
+ .on("add", (file) => {
450
490
  console.log(`New file available: ${file}`);
451
491
  })
452
- .on("remove", ({ file }) => {
492
+ .on("remove", (file) => {
453
493
  console.log(`File removed: ${file}`);
454
494
  cleanupForFile(file);
455
495
  })
@@ -467,9 +507,9 @@ client
467
507
  | `connect` | | WebSocket connection established |
468
508
  | `disconnect` | | WebSocket disconnected |
469
509
  | `init` | `{ files, config }` | Server sent the initial file list |
470
- | `reload` | `{ file }` | A file was changed and hot-reloaded |
471
- | `add` | `{ file }` | A new file was detected |
472
- | `remove` | `{ file }` | A file was removed |
510
+ | `reload` | `file: string` | A file was changed and hot-reloaded |
511
+ | `add` | `file: string` | A new file was detected |
512
+ | `remove` | `file: string` | A file was removed |
473
513
  | `cold` | `file: string` | A cold file changed |
474
514
  | `error` | `Error` | A connection or message error occurred |
475
515
 
@@ -1 +1 @@
1
- {"version":3,"file":"file-loader.d.ts","sourceRoot":"","sources":["../../src/client/file-loader.js"],"names":[],"mappings":"AAAA,mFAAmF;AACnF;IACE;;;;OAiCC;IAhCC,aAAsB;IACtB;;;;;OAKG;IACH,cAFU,MAAM,GAAG,IAAI,CAES;IAChC,qBAAqB;IACrB,cADW,MAAM,CACe;IAChC;;;;;;OAMG;IACH,KAFU,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAExB;IACd;;;;;OAKG;IACH,WAFU,GAAG,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,CAAC,CAEvC;IAC1B;;;;;OAKG;IACH,UAFU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEJ;IAG3B,kCAOC;IAKD,qCAwBC;IAED,oDAmBC;IAED,wCAcC;IAED,oCAwBC;IAKD,oCAeC;IAED,uCAUC;IAED,qCAqBC;IAGD,2BAIC;IAED,6CAaC;IAED,uDAEC;CACF"}
1
+ {"version":3,"file":"file-loader.d.ts","sourceRoot":"","sources":["../../src/client/file-loader.js"],"names":[],"mappings":"AAAA,mFAAmF;AACnF;IACE;;;;OAiCC;IAhCC,aAAsB;IACtB;;;;;OAKG;IACH,cAFU,MAAM,GAAG,IAAI,CAES;IAChC,qBAAqB;IACrB,cADW,MAAM,CACe;IAChC;;;;;;OAMG;IACH,KAFU,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAExB;IACd;;;;;OAKG;IACH,WAFU,GAAG,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,CAAC,CAEvC;IAC1B;;;;;OAKG;IACH,UAFU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEJ;IAG3B,kCAOC;IAKD,qCAwBC;IAED,oDAmBC;IAED,wCAcC;IAED,oCA4BC;IAKD,oCAeC;IAED,uCAUC;IAED,qCAqBC;IAGD,2BAIC;IAED,6CAaC;IAED,uDAEC;CACF"}
@@ -1644,7 +1644,11 @@ var HMR = (() => {
1644
1644
  script.src = url;
1645
1645
  script.setAttribute("data-file", path);
1646
1646
  return new Promise((resolve, reject) => {
1647
- script.onload = () => resolve(true);
1647
+ script.onload = () => {
1648
+ const previous = document.querySelector(`script[data-file="${path}"]:not([src="${url}"])`);
1649
+ if (previous) previous.remove();
1650
+ resolve(true);
1651
+ };
1648
1652
  script.onerror = () => reject(new Error(`Failed to load script: ${path}`));
1649
1653
  document.head.appendChild(script);
1650
1654
  });