@rspack/dev-middleware 2.0.0-beta.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -82
- package/dist/index.js +114 -70
- package/package.json +5 -5
- package/types/index.d.ts +15 -14
- package/types/middleware.d.ts +9 -2
- package/types/utils/compatibleAPI.d.ts +8 -8
- package/types/utils/getFilenameFromUrl.d.ts +23 -11
- package/types/utils/getPaths.d.ts +4 -1
- package/types/utils/memorize.d.ts +1 -1
package/README.md
CHANGED
|
@@ -39,9 +39,9 @@ bun add -D @rspack/dev-middleware
|
|
|
39
39
|
## Usage
|
|
40
40
|
|
|
41
41
|
```js
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
import { rspack } from "@rspack/core";
|
|
43
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
44
|
+
import express from "express";
|
|
45
45
|
|
|
46
46
|
const compiler = rspack({
|
|
47
47
|
// Rspack options
|
|
@@ -72,7 +72,7 @@ See [below](#other-servers) for examples of use with other servers.
|
|
|
72
72
|
| **[`etag`](#tag)** | `boolean\| "weak"\| "strong"` | `undefined` | Enable or disable etag generation. |
|
|
73
73
|
| **[`lastModified`](#lastmodified)** | `boolean` | `undefined` | Enable or disable `Last-Modified` header. Uses the file system's last modified value. |
|
|
74
74
|
| **[`cacheControl`](#cachecontrol)** | `boolean\|number\|string\|Object` | `undefined` | Enable or disable setting `Cache-Control` response header. |
|
|
75
|
-
| **[`cacheImmutable`](#cacheimmutable)** |
|
|
75
|
+
| **[`cacheImmutable`](#cacheimmutable)** | `boolean` | `true` | Enable or disable setting `Cache-Control: public, max-age=31536000, immutable` response header for immutable assets. |
|
|
76
76
|
| **[`publicPath`](#publicpath)** | `string` | `undefined` | The public path that the middleware is bound to. |
|
|
77
77
|
| **[`stats`](#stats)** | `boolean\|string\|Object` | `stats` (from a configuration) | Stats options object or preset name. |
|
|
78
78
|
| **[`serverSideRender`](#serversiderender)** | `boolean` | `undefined` | Instructs the module to enable or disable the server-side rendering mode. |
|
|
@@ -196,21 +196,25 @@ Default: `undefined`
|
|
|
196
196
|
|
|
197
197
|
Depending on the setting, the following headers will be generated:
|
|
198
198
|
|
|
199
|
-
- `Boolean` - `Cache-Control: public, max-age=
|
|
200
|
-
- `Number` - `Cache-Control: public, max-age=
|
|
199
|
+
- `Boolean` - `Cache-Control: public, max-age=31536000`
|
|
200
|
+
- `Number` - `Cache-Control: public, max-age=YOUR_NUMBER_IN_SECONDS`
|
|
201
201
|
- `String` - `Cache-Control: YOUR_STRING`
|
|
202
|
-
- `{ maxAge?: number, immutable?: boolean }` - `Cache-Control: public, max-age=
|
|
202
|
+
- `{ maxAge?: number, immutable?: boolean }` - `Cache-Control: public, max-age=YOUR_MAX_AGE_IN_SECONDS_or_31536000`, also `, immutable` is added when you set the `immutable` option to `true`
|
|
203
|
+
|
|
204
|
+
Numeric `cacheControl` and `cacheControl.maxAge` values are interpreted as milliseconds, clamped to `0..31536000000`, and converted to seconds for the response header.
|
|
203
205
|
|
|
204
206
|
Enable or disable setting `Cache-Control` response header.
|
|
205
207
|
|
|
206
208
|
### cacheImmutable
|
|
207
209
|
|
|
208
210
|
Type: `Boolean`
|
|
209
|
-
Default: `
|
|
211
|
+
Default: `true`
|
|
210
212
|
|
|
211
213
|
Enable or disable setting `Cache-Control: public, max-age=31536000, immutable` response header for immutable assets (i.e. asset with a hash like `image.a4c12bde.jpg`).
|
|
212
214
|
Immutable assets are assets that have their hash in the file name therefore they can be cached, because if you change their contents the file name will be changed.
|
|
213
|
-
|
|
215
|
+
When omitted, immutable assets use this header by default.
|
|
216
|
+
Set `cacheImmutable: false` to fall back to the `cacheControl` option even for immutable assets.
|
|
217
|
+
This takes precedence over the `cacheControl` option only when the asset was defined as immutable and `cacheImmutable` is not `false`.
|
|
214
218
|
|
|
215
219
|
### publicPath
|
|
216
220
|
|
|
@@ -249,7 +253,7 @@ This option also accepts a `Function` value, which can be used to filter which f
|
|
|
249
253
|
The function follows the same premise as [`Array#filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) in which a return value of `false` _will not_ write the file, and a return value of `true` _will_ write the file to disk. eg.
|
|
250
254
|
|
|
251
255
|
```js
|
|
252
|
-
|
|
256
|
+
import { rspack } from "@rspack/core";
|
|
253
257
|
|
|
254
258
|
const configuration = {
|
|
255
259
|
/* Rspack configuration */
|
|
@@ -269,16 +273,16 @@ Default: [memfs](https://github.com/streamich/memfs)
|
|
|
269
273
|
Set the default file system which will be used by Rspack as primary destination of generated files.
|
|
270
274
|
This option isn't affected by the [writeToDisk](#writeToDisk) option.
|
|
271
275
|
|
|
272
|
-
This can be done simply by using `path
|
|
276
|
+
This can be done simply by using `node:path`'s `join`:
|
|
273
277
|
|
|
274
278
|
```js
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
+
import { join } from "node:path";
|
|
280
|
+
import { rspack } from "@rspack/core";
|
|
281
|
+
import mkdirp from "mkdirp";
|
|
282
|
+
import myOutputFileSystem from "my-fs";
|
|
279
283
|
|
|
280
|
-
myOutputFileSystem.join =
|
|
281
|
-
myOutputFileSystem.mkdirp = mkdirp
|
|
284
|
+
myOutputFileSystem.join = join;
|
|
285
|
+
myOutputFileSystem.mkdirp = mkdirp;
|
|
282
286
|
|
|
283
287
|
const compiler = rspack({
|
|
284
288
|
/* Rspack configuration */
|
|
@@ -292,7 +296,7 @@ devMiddleware(compiler, { outputFileSystem: myOutputFileSystem });
|
|
|
292
296
|
Allows to set up a callback to change the response data.
|
|
293
297
|
|
|
294
298
|
```js
|
|
295
|
-
|
|
299
|
+
import { rspack } from "@rspack/core";
|
|
296
300
|
|
|
297
301
|
const configuration = {
|
|
298
302
|
/* Rspack configuration */
|
|
@@ -328,9 +332,9 @@ Required: `No`
|
|
|
328
332
|
A function executed once the middleware has stopped watching.
|
|
329
333
|
|
|
330
334
|
```js
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
335
|
+
import { rspack } from "@rspack/core";
|
|
336
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
337
|
+
import express from "express";
|
|
334
338
|
|
|
335
339
|
const compiler = rspack({
|
|
336
340
|
/* Rspack configuration */
|
|
@@ -338,8 +342,7 @@ const compiler = rspack({
|
|
|
338
342
|
|
|
339
343
|
const instance = devMiddleware(compiler);
|
|
340
344
|
|
|
341
|
-
|
|
342
|
-
const app = new express();
|
|
345
|
+
const app = express();
|
|
343
346
|
|
|
344
347
|
app.use(instance);
|
|
345
348
|
|
|
@@ -363,9 +366,9 @@ Required: `No`
|
|
|
363
366
|
A function executed once the middleware has invalidated.
|
|
364
367
|
|
|
365
368
|
```js
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
+
import { rspack } from "@rspack/core";
|
|
370
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
371
|
+
import express from "express";
|
|
369
372
|
|
|
370
373
|
const compiler = rspack({
|
|
371
374
|
/* Rspack configuration */
|
|
@@ -373,8 +376,7 @@ const compiler = rspack({
|
|
|
373
376
|
|
|
374
377
|
const instance = devMiddleware(compiler);
|
|
375
378
|
|
|
376
|
-
|
|
377
|
-
const app = new express();
|
|
379
|
+
const app = express();
|
|
378
380
|
|
|
379
381
|
app.use(instance);
|
|
380
382
|
|
|
@@ -403,9 +405,9 @@ A function executed when the bundle becomes valid.
|
|
|
403
405
|
If the bundle is valid at the time of calling, the callback is executed immediately.
|
|
404
406
|
|
|
405
407
|
```js
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
408
|
+
import { rspack } from "@rspack/core";
|
|
409
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
410
|
+
import express from "express";
|
|
409
411
|
|
|
410
412
|
const compiler = rspack({
|
|
411
413
|
/* Rspack configuration */
|
|
@@ -413,8 +415,7 @@ const compiler = rspack({
|
|
|
413
415
|
|
|
414
416
|
const instance = devMiddleware(compiler);
|
|
415
417
|
|
|
416
|
-
|
|
417
|
-
const app = new express();
|
|
418
|
+
const app = express();
|
|
418
419
|
|
|
419
420
|
app.use(instance);
|
|
420
421
|
|
|
@@ -437,9 +438,9 @@ Required: `Yes`
|
|
|
437
438
|
URL for the requested file.
|
|
438
439
|
|
|
439
440
|
```js
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
441
|
+
import { rspack } from "@rspack/core";
|
|
442
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
443
|
+
import express from "express";
|
|
443
444
|
|
|
444
445
|
const compiler = rspack({
|
|
445
446
|
/* Rspack configuration */
|
|
@@ -447,15 +448,26 @@ const compiler = rspack({
|
|
|
447
448
|
|
|
448
449
|
const instance = devMiddleware(compiler);
|
|
449
450
|
|
|
450
|
-
|
|
451
|
-
const app = new express();
|
|
451
|
+
const app = express();
|
|
452
452
|
|
|
453
453
|
app.use(instance);
|
|
454
454
|
|
|
455
455
|
instance.waitUntilValid(() => {
|
|
456
|
-
|
|
456
|
+
let resolved;
|
|
457
|
+
|
|
458
|
+
try {
|
|
459
|
+
resolved = instance.getFilenameFromUrl("/bundle.js");
|
|
460
|
+
} catch (error) {
|
|
461
|
+
console.error(error);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (!resolved) {
|
|
466
|
+
console.log("Not found");
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
457
469
|
|
|
458
|
-
console.log(`Filename is ${filename}`);
|
|
470
|
+
console.log(`Filename is ${resolved.filename}`);
|
|
459
471
|
});
|
|
460
472
|
```
|
|
461
473
|
|
|
@@ -468,9 +480,9 @@ Since `output.publicPath` and `output.filename`/`output.chunkFilename` can be dy
|
|
|
468
480
|
But there is a solution to avoid it - mount the middleware to a non-root route, for example:
|
|
469
481
|
|
|
470
482
|
```js
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
483
|
+
import { rspack } from "@rspack/core";
|
|
484
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
485
|
+
import express from "express";
|
|
474
486
|
|
|
475
487
|
const compiler = rspack({
|
|
476
488
|
// Rspack options
|
|
@@ -509,17 +521,17 @@ process is finished with server-side rendering enabled._
|
|
|
509
521
|
Example Implementation:
|
|
510
522
|
|
|
511
523
|
```js
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
524
|
+
import { join } from "node:path";
|
|
525
|
+
import { rspack } from "@rspack/core";
|
|
526
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
527
|
+
import express from "express";
|
|
528
|
+
import isObject from "is-object";
|
|
516
529
|
|
|
517
530
|
const compiler = rspack({
|
|
518
531
|
/* Rspack configuration */
|
|
519
532
|
});
|
|
520
533
|
|
|
521
|
-
|
|
522
|
-
const app = new express();
|
|
534
|
+
const app = express();
|
|
523
535
|
|
|
524
536
|
// This function makes server rendering of asset references consistent with different Rspack chunk/entry configurations
|
|
525
537
|
function normalizeAssets(assets) {
|
|
@@ -547,16 +559,16 @@ app.use((req, res) => {
|
|
|
547
559
|
<title>My App</title>
|
|
548
560
|
<style>
|
|
549
561
|
${normalizeAssets(assetsByChunkName.main)
|
|
550
|
-
.filter((
|
|
551
|
-
.map((
|
|
562
|
+
.filter((asset) => asset.endsWith(".css"))
|
|
563
|
+
.map((asset) => outputFileSystem.readFileSync(join(outputPath, asset)))
|
|
552
564
|
.join("\n")}
|
|
553
565
|
</style>
|
|
554
566
|
</head>
|
|
555
567
|
<body>
|
|
556
568
|
<div id="root"></div>
|
|
557
569
|
${normalizeAssets(assetsByChunkName.main)
|
|
558
|
-
.filter((
|
|
559
|
-
.map((
|
|
570
|
+
.filter((asset) => asset.endsWith(".js"))
|
|
571
|
+
.map((asset) => `<script src="${asset}"></script>`)
|
|
560
572
|
.join("\n")}
|
|
561
573
|
</body>
|
|
562
574
|
</html>
|
|
@@ -568,14 +580,16 @@ app.use((req, res) => {
|
|
|
568
580
|
|
|
569
581
|
Examples of use with other servers will follow here.
|
|
570
582
|
|
|
571
|
-
###
|
|
583
|
+
### connect-next
|
|
584
|
+
|
|
585
|
+
[connect-next](https://github.com/rstackjs/connect-next) is an actively maintained fork of Connect.
|
|
572
586
|
|
|
573
587
|
```js
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
588
|
+
import { createServer } from "node:http";
|
|
589
|
+
import { rspack } from "@rspack/core";
|
|
590
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
591
|
+
import { connect } from "connect-next";
|
|
592
|
+
import rspackConfig from "./rspack.config.js";
|
|
579
593
|
|
|
580
594
|
const compiler = rspack(rspackConfig);
|
|
581
595
|
const devMiddlewareOptions = {
|
|
@@ -585,18 +599,18 @@ const app = connect();
|
|
|
585
599
|
|
|
586
600
|
app.use(devMiddleware(compiler, devMiddlewareOptions));
|
|
587
601
|
|
|
588
|
-
|
|
602
|
+
createServer(app).listen(3000);
|
|
589
603
|
```
|
|
590
604
|
|
|
591
605
|
### Router
|
|
592
606
|
|
|
593
607
|
```js
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
608
|
+
import { createServer } from "node:http";
|
|
609
|
+
import { rspack } from "@rspack/core";
|
|
610
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
611
|
+
import finalhandler from "finalhandler";
|
|
612
|
+
import Router from "router";
|
|
613
|
+
import rspackConfig from "./rspack.config.js";
|
|
600
614
|
|
|
601
615
|
const compiler = rspack(rspackConfig);
|
|
602
616
|
const devMiddlewareOptions = {
|
|
@@ -608,7 +622,7 @@ const router = Router();
|
|
|
608
622
|
|
|
609
623
|
router.use(devMiddleware(compiler, devMiddlewareOptions));
|
|
610
624
|
|
|
611
|
-
const server =
|
|
625
|
+
const server = createServer((req, res) => {
|
|
612
626
|
router(req, res, finalhandler(req, res));
|
|
613
627
|
});
|
|
614
628
|
|
|
@@ -618,10 +632,10 @@ server.listen(3000);
|
|
|
618
632
|
### Express
|
|
619
633
|
|
|
620
634
|
```js
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
635
|
+
import { rspack } from "@rspack/core";
|
|
636
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
637
|
+
import express from "express";
|
|
638
|
+
import rspackConfig from "./rspack.config.js";
|
|
625
639
|
|
|
626
640
|
const compiler = rspack(rspackConfig);
|
|
627
641
|
const devMiddlewareOptions = {
|
|
@@ -637,10 +651,10 @@ app.listen(3000, () => console.log("Example app listening on port 3000!"));
|
|
|
637
651
|
### Koa
|
|
638
652
|
|
|
639
653
|
```js
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
654
|
+
import { rspack } from "@rspack/core";
|
|
655
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
656
|
+
import Koa from "koa";
|
|
657
|
+
import rspackConfig from "./rspack.simple.config.js";
|
|
644
658
|
|
|
645
659
|
const compiler = rspack(rspackConfig);
|
|
646
660
|
const devMiddlewareOptions = {
|
|
@@ -648,7 +662,7 @@ const devMiddlewareOptions = {
|
|
|
648
662
|
};
|
|
649
663
|
const app = new Koa();
|
|
650
664
|
|
|
651
|
-
app.use(
|
|
665
|
+
app.use(devMiddleware.koaWrapper(compiler, devMiddlewareOptions));
|
|
652
666
|
|
|
653
667
|
app.listen(3000);
|
|
654
668
|
```
|
|
@@ -656,10 +670,10 @@ app.listen(3000);
|
|
|
656
670
|
### Hapi
|
|
657
671
|
|
|
658
672
|
```js
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
673
|
+
import Hapi from "@hapi/hapi";
|
|
674
|
+
import { rspack } from "@rspack/core";
|
|
675
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
676
|
+
import rspackConfig from "./rspack.config.js";
|
|
663
677
|
|
|
664
678
|
const compiler = rspack(rspackConfig);
|
|
665
679
|
const devMiddlewareOptions = {};
|
|
@@ -688,10 +702,10 @@ process.on("unhandledRejection", (err) => {
|
|
|
688
702
|
### Hono
|
|
689
703
|
|
|
690
704
|
```js
|
|
705
|
+
import { rspack } from "@rspack/core";
|
|
706
|
+
import { devMiddleware } from "@rspack/dev-middleware";
|
|
691
707
|
import { serve } from "@hono/node-server";
|
|
692
|
-
import devMiddleware from "@rspack/dev-middleware";
|
|
693
708
|
import { Hono } from "hono";
|
|
694
|
-
import { rspack } from "@rspack/core";
|
|
695
709
|
import rspackConfig from "./rspack.config.js";
|
|
696
710
|
|
|
697
711
|
const compiler = rspack(rspackConfig);
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import { __webpack_require__ } from "./rslib-runtime.js";
|
|
|
10
10
|
import node_path from "node:path";
|
|
11
11
|
import node_crypto from "node:crypto";
|
|
12
12
|
import node_querystring from "node:querystring";
|
|
13
|
-
import { parse } from "node:url";
|
|
14
13
|
import node_fs from "node:fs";
|
|
15
14
|
__webpack_require__.add({
|
|
16
15
|
"./node_modules/.pnpm/@jsonjoy.com+base64@17.67.0_tslib@2.8.1/node_modules/@jsonjoy.com/base64/lib/constants.js" (__unused_rspack_module, exports) {
|
|
@@ -8497,8 +8496,10 @@ function getPaths(context) {
|
|
|
8497
8496
|
asset.name,
|
|
8498
8497
|
asset.info
|
|
8499
8498
|
]));
|
|
8499
|
+
const { outputFileSystem } = compilation.compiler;
|
|
8500
8500
|
publicPaths.push({
|
|
8501
8501
|
outputPath,
|
|
8502
|
+
outputFileSystem,
|
|
8502
8503
|
publicPath,
|
|
8503
8504
|
assetsInfo
|
|
8504
8505
|
});
|
|
@@ -8526,70 +8527,113 @@ const utils_memorize = memorize;
|
|
|
8526
8527
|
function decode(input) {
|
|
8527
8528
|
return node_querystring.unescape(input);
|
|
8528
8529
|
}
|
|
8529
|
-
const memoizedParse = utils_memorize(
|
|
8530
|
-
|
|
8531
|
-
return
|
|
8530
|
+
const memoizedParse = utils_memorize((url)=>{
|
|
8531
|
+
const urlObject = new URL(url, "http://localhost");
|
|
8532
|
+
return {
|
|
8533
|
+
...urlObject,
|
|
8534
|
+
pathname: decode(urlObject.pathname)
|
|
8535
|
+
};
|
|
8532
8536
|
});
|
|
8533
8537
|
const UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/;
|
|
8534
|
-
|
|
8538
|
+
class FilenameError extends Error {
|
|
8539
|
+
constructor(message, code){
|
|
8540
|
+
super(message);
|
|
8541
|
+
this.name = "FilenameError";
|
|
8542
|
+
this.statusCode = code;
|
|
8543
|
+
}
|
|
8544
|
+
}
|
|
8545
|
+
function isNotFoundError(error) {
|
|
8546
|
+
switch(error.code){
|
|
8547
|
+
case "ENAMETOOLONG":
|
|
8548
|
+
case "ENOENT":
|
|
8549
|
+
case "ENOTDIR":
|
|
8550
|
+
return true;
|
|
8551
|
+
default:
|
|
8552
|
+
return false;
|
|
8553
|
+
}
|
|
8554
|
+
}
|
|
8555
|
+
function getFilenameFromUrl(context, url) {
|
|
8535
8556
|
const { options } = context;
|
|
8536
8557
|
const paths = utils_getPaths(context);
|
|
8537
|
-
|
|
8558
|
+
const index = false === options.index ? [] : void 0 === options.index || true === options.index ? [
|
|
8559
|
+
"index.html"
|
|
8560
|
+
] : [
|
|
8561
|
+
options.index
|
|
8562
|
+
];
|
|
8538
8563
|
let urlObject;
|
|
8539
8564
|
try {
|
|
8540
|
-
urlObject = memoizedParse(url
|
|
8565
|
+
urlObject = memoizedParse(url);
|
|
8541
8566
|
} catch {
|
|
8542
8567
|
return;
|
|
8543
8568
|
}
|
|
8544
|
-
for (const { publicPath, outputPath, assetsInfo } of paths){
|
|
8569
|
+
for (const { publicPath, outputPath, assetsInfo, outputFileSystem } of paths){
|
|
8545
8570
|
let filename;
|
|
8546
8571
|
let publicPathObject;
|
|
8547
8572
|
try {
|
|
8548
|
-
publicPathObject = memoizedParse("auto" !== publicPath && publicPath ? publicPath : "/"
|
|
8573
|
+
publicPathObject = memoizedParse("auto" !== publicPath && publicPath ? publicPath : "/");
|
|
8549
8574
|
} catch {
|
|
8550
8575
|
continue;
|
|
8551
8576
|
}
|
|
8552
8577
|
const { pathname } = urlObject;
|
|
8553
8578
|
const { pathname: publicPathPathname } = publicPathObject;
|
|
8554
8579
|
if (pathname && publicPathPathname && pathname.startsWith(publicPathPathname)) {
|
|
8555
|
-
if (pathname.includes("\0"))
|
|
8556
|
-
|
|
8557
|
-
return;
|
|
8558
|
-
}
|
|
8559
|
-
if (UP_PATH_REGEXP.test(node_path.normalize(`./${pathname}`))) {
|
|
8560
|
-
extra.errorCode = 403;
|
|
8561
|
-
return;
|
|
8562
|
-
}
|
|
8580
|
+
if (pathname.includes("\0")) throw new FilenameError("Bad Request", 400);
|
|
8581
|
+
if (UP_PATH_REGEXP.test(node_path.normalize(`./${pathname}`))) throw new FilenameError("Forbidden", 403);
|
|
8563
8582
|
filename = node_path.join(outputPath, pathname.slice(publicPathPathname.length));
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
if (assetsInfo) {
|
|
8572
|
-
const assetInfo = assetsInfo.get(pathname.slice(publicPathPathname.length));
|
|
8573
|
-
extra.immutable = assetInfo ? assetInfo.immutable : false;
|
|
8574
|
-
}
|
|
8575
|
-
break;
|
|
8576
|
-
}
|
|
8577
|
-
if (extra.stats.isDirectory() && (void 0 === options.index || options.index)) {
|
|
8578
|
-
const indexValue = void 0 === options.index || "boolean" == typeof options.index ? "index.html" : options.index;
|
|
8579
|
-
filename = node_path.join(filename, indexValue);
|
|
8583
|
+
const resolveIndex = (filename, visited = new Set())=>{
|
|
8584
|
+
if (0 === index.length) return;
|
|
8585
|
+
const nextFilename = node_path.join(filename, index[0]);
|
|
8586
|
+
if (visited.has(nextFilename)) return;
|
|
8587
|
+
visited.add(nextFilename);
|
|
8588
|
+
filename = nextFilename;
|
|
8589
|
+
let stats;
|
|
8580
8590
|
try {
|
|
8581
|
-
|
|
8582
|
-
} catch
|
|
8583
|
-
|
|
8591
|
+
stats = outputFileSystem.statSync(filename);
|
|
8592
|
+
} catch (error) {
|
|
8593
|
+
if (isNotFoundError(error)) return;
|
|
8594
|
+
throw error;
|
|
8584
8595
|
}
|
|
8585
|
-
if (
|
|
8586
|
-
|
|
8587
|
-
|
|
8596
|
+
if (stats.isDirectory()) return resolveIndex(filename, visited);
|
|
8597
|
+
const extra = {
|
|
8598
|
+
immutable: assetsInfo ? assetsInfo.get(pathname.slice(publicPathPathname.length))?.immutable : false,
|
|
8599
|
+
outputFileSystem,
|
|
8600
|
+
stats: stats
|
|
8601
|
+
};
|
|
8602
|
+
return {
|
|
8603
|
+
filename,
|
|
8604
|
+
extra
|
|
8605
|
+
};
|
|
8606
|
+
};
|
|
8607
|
+
const resolveFile = (filename)=>{
|
|
8608
|
+
let stats;
|
|
8609
|
+
try {
|
|
8610
|
+
stats = outputFileSystem.statSync(filename);
|
|
8611
|
+
} catch (error) {
|
|
8612
|
+
if (isNotFoundError(error)) return;
|
|
8613
|
+
throw error;
|
|
8588
8614
|
}
|
|
8615
|
+
if (stats.isDirectory()) return resolveIndex(filename);
|
|
8616
|
+
if (filename.endsWith(node_path.sep)) return;
|
|
8617
|
+
const extra = {
|
|
8618
|
+
immutable: assetsInfo ? assetsInfo.get(pathname.slice(publicPathPathname.length))?.immutable : false,
|
|
8619
|
+
outputFileSystem,
|
|
8620
|
+
stats: stats
|
|
8621
|
+
};
|
|
8622
|
+
return {
|
|
8623
|
+
filename,
|
|
8624
|
+
extra
|
|
8625
|
+
};
|
|
8626
|
+
};
|
|
8627
|
+
if (index.length > 0 && pathname.endsWith("/")) {
|
|
8628
|
+
const result = resolveIndex(filename);
|
|
8629
|
+
if (!result) continue;
|
|
8630
|
+
return result;
|
|
8589
8631
|
}
|
|
8632
|
+
const result = resolveFile(filename);
|
|
8633
|
+
if (!result) continue;
|
|
8634
|
+
return result;
|
|
8590
8635
|
}
|
|
8591
8636
|
}
|
|
8592
|
-
return foundFilename;
|
|
8593
8637
|
}
|
|
8594
8638
|
const utils_getFilenameFromUrl = getFilenameFromUrl;
|
|
8595
8639
|
function parseTokenList(str) {
|
|
@@ -8735,7 +8779,7 @@ function wrapper(context) {
|
|
|
8735
8779
|
setResponseHeader(res, "Content-Length", byteLength);
|
|
8736
8780
|
finish(res, document);
|
|
8737
8781
|
}
|
|
8738
|
-
async function errorHandler(error) {
|
|
8782
|
+
async function errorHandler(error, message, code) {
|
|
8739
8783
|
switch(error.code){
|
|
8740
8784
|
case "ENAMETOOLONG":
|
|
8741
8785
|
case "ENOENT":
|
|
@@ -8745,7 +8789,7 @@ function wrapper(context) {
|
|
|
8745
8789
|
});
|
|
8746
8790
|
break;
|
|
8747
8791
|
default:
|
|
8748
|
-
await sendError(error.message, 500, {
|
|
8792
|
+
await sendError(message || error.message, code || 500, {
|
|
8749
8793
|
modifyResponseData: context.options.modifyResponseData
|
|
8750
8794
|
});
|
|
8751
8795
|
break;
|
|
@@ -8834,17 +8878,19 @@ function wrapper(context) {
|
|
|
8834
8878
|
];
|
|
8835
8879
|
}
|
|
8836
8880
|
async function processRequest() {
|
|
8837
|
-
|
|
8838
|
-
const
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
});
|
|
8881
|
+
let resolved;
|
|
8882
|
+
const requestUrl = getRequestURL(req);
|
|
8883
|
+
try {
|
|
8884
|
+
resolved = utils_getFilenameFromUrl(context, requestUrl);
|
|
8885
|
+
} catch (error) {
|
|
8886
|
+
const errorCode = "object" == typeof error && null !== error && void 0 !== error.statusCode ? error.statusCode : void 0;
|
|
8887
|
+
if (403 === errorCode) context.logger.error(`Malicious path "${requestUrl}".`);
|
|
8888
|
+
await errorHandler(error, 400 === errorCode ? "Bad Request" : 403 === errorCode ? "Forbidden" : void 0, errorCode);
|
|
8844
8889
|
return;
|
|
8845
8890
|
}
|
|
8846
|
-
if (!
|
|
8891
|
+
if (!resolved) return void await goNext();
|
|
8847
8892
|
if (getHeadersSent(res)) return void await goNext();
|
|
8893
|
+
const { extra, filename } = resolved;
|
|
8848
8894
|
const { size } = extra.stats;
|
|
8849
8895
|
let len = size;
|
|
8850
8896
|
let offset = 0;
|
|
@@ -8865,23 +8911,21 @@ function wrapper(context) {
|
|
|
8865
8911
|
}
|
|
8866
8912
|
if (!getResponseHeader(res, "Accept-Ranges")) setResponseHeader(res, "Accept-Ranges", "bytes");
|
|
8867
8913
|
if (!getResponseHeader(res, "Cache-Control")) {
|
|
8868
|
-
const cacheControl = context.options
|
|
8869
|
-
|
|
8870
|
-
|
|
8871
|
-
if (
|
|
8872
|
-
|
|
8873
|
-
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
|
|
8877
|
-
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
setResponseHeader(res, "Cache-Control", cacheControlValue);
|
|
8884
|
-
}
|
|
8914
|
+
const { cacheControl, cacheImmutable } = context.options;
|
|
8915
|
+
const useImmutableCache = (void 0 === cacheImmutable || cacheImmutable) && extra.immutable;
|
|
8916
|
+
let cacheControlValue;
|
|
8917
|
+
if (useImmutableCache) cacheControlValue = `public, max-age=${Math.floor(MAX_MAX_AGE / 1000)}, immutable`;
|
|
8918
|
+
else if (true === cacheControl) cacheControlValue = `public, max-age=${Math.floor(MAX_MAX_AGE / 1000)}`;
|
|
8919
|
+
else if ("number" == typeof cacheControl) {
|
|
8920
|
+
const maxAge = Math.min(Math.max(0, cacheControl), MAX_MAX_AGE);
|
|
8921
|
+
cacheControlValue = `public, max-age=${Math.floor(maxAge / 1000)}`;
|
|
8922
|
+
} else if ("string" == typeof cacheControl) cacheControlValue = cacheControl;
|
|
8923
|
+
else if (cacheControl) {
|
|
8924
|
+
const maxAge = void 0 !== cacheControl.maxAge ? Math.min(Math.max(0, cacheControl.maxAge), MAX_MAX_AGE) : MAX_MAX_AGE;
|
|
8925
|
+
cacheControlValue = `public, max-age=${Math.floor(maxAge / 1000)}`;
|
|
8926
|
+
if (cacheControl.immutable) cacheControlValue += ", immutable";
|
|
8927
|
+
}
|
|
8928
|
+
if (cacheControlValue) setResponseHeader(res, "Cache-Control", cacheControlValue);
|
|
8885
8929
|
}
|
|
8886
8930
|
if (context.options.lastModified && !getResponseHeader(res, "Last-Modified")) {
|
|
8887
8931
|
const modified = extra.stats.mtime.toUTCString();
|
|
@@ -8901,7 +8945,7 @@ function wrapper(context) {
|
|
|
8901
8945
|
}
|
|
8902
8946
|
[start, end] = calcStartAndEnd(offset, len);
|
|
8903
8947
|
try {
|
|
8904
|
-
const result = createReadStreamOrReadFileSync(filename,
|
|
8948
|
+
const result = createReadStreamOrReadFileSync(filename, extra.outputFileSystem, start, end);
|
|
8905
8949
|
({ bufferOrStream, byteLength } = result);
|
|
8906
8950
|
} catch (error) {
|
|
8907
8951
|
await errorHandler(error);
|
|
@@ -8963,7 +9007,7 @@ function wrapper(context) {
|
|
|
8963
9007
|
if (!bufferOrStream) {
|
|
8964
9008
|
[start, end] = calcStartAndEnd(offset, len);
|
|
8965
9009
|
try {
|
|
8966
|
-
({ bufferOrStream, byteLength } = createReadStreamOrReadFileSync(filename,
|
|
9010
|
+
({ bufferOrStream, byteLength } = createReadStreamOrReadFileSync(filename, extra.outputFileSystem, start, end));
|
|
8967
9011
|
} catch (error) {
|
|
8968
9012
|
await errorHandler(error);
|
|
8969
9013
|
return;
|
|
@@ -9120,7 +9164,7 @@ function rdm(compiler, options = {}) {
|
|
|
9120
9164
|
}
|
|
9121
9165
|
const filledContext = context;
|
|
9122
9166
|
const instance = src_middleware(filledContext);
|
|
9123
|
-
instance.getFilenameFromUrl = (url
|
|
9167
|
+
instance.getFilenameFromUrl = (url)=>utils_getFilenameFromUrl(filledContext, url);
|
|
9124
9168
|
instance.waitUntilValid = (callback = noop)=>{
|
|
9125
9169
|
utils_ready(filledContext, callback);
|
|
9126
9170
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rspack/dev-middleware",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A development middleware for Rspack",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rspack",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"build": "rslib --syntax es2023 && pnpm run build:types",
|
|
24
24
|
"build:types": "tsc --declaration --emitDeclarationOnly --outDir types && prettier \"types/**/*.ts\" --write",
|
|
25
25
|
"lint": "npm-run-all -l -p \"lint:**\"",
|
|
26
|
+
"lint:rslint": "rslint",
|
|
26
27
|
"lint:prettier": "prettier --cache --list-different .",
|
|
27
28
|
"lint:spelling": "cspell --cache --no-must-find-files --quiet \"**/*.*\"",
|
|
28
29
|
"lint:types": "tsc --pretty --noEmit",
|
|
@@ -35,19 +36,18 @@
|
|
|
35
36
|
"@hapi/hapi": "^21.3.7",
|
|
36
37
|
"@hono/node-server": "^1.12.0",
|
|
37
38
|
"@rslib/core": "^0.20.0",
|
|
39
|
+
"@rslint/core": "^0.3.3",
|
|
38
40
|
"@rspack/core": "2.0.0-beta.5",
|
|
39
41
|
"@rstest/core": "0.9.2",
|
|
40
|
-
"@types/connect": "^3.4.35",
|
|
41
42
|
"@types/express": "^5.0.2",
|
|
42
43
|
"@types/node": "^22.3.0",
|
|
43
44
|
"@types/on-finished": "^2.3.4",
|
|
44
45
|
"@types/range-parser": "^1.2.7",
|
|
45
|
-
"connect": "^
|
|
46
|
+
"connect-next": "^4.0.0",
|
|
46
47
|
"cspell": "^9.6.2",
|
|
47
48
|
"deepmerge": "^4.2.2",
|
|
48
49
|
"execa": "^5.1.1",
|
|
49
50
|
"express": "^5.1.0",
|
|
50
|
-
"file-loader": "^6.2.0",
|
|
51
51
|
"finalhandler": "^2.1.0",
|
|
52
52
|
"hono": "^4.4.13",
|
|
53
53
|
"koa": "^3.0.0",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"range-parser": "^1.2.1",
|
|
60
60
|
"router": "^2.2.0",
|
|
61
61
|
"supertest": "^7.0.0",
|
|
62
|
-
"typescript": "^
|
|
62
|
+
"typescript": "^6.0.2"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@rspack/core": "^2.0.0-0"
|
package/types/index.d.ts
CHANGED
|
@@ -95,23 +95,22 @@
|
|
|
95
95
|
* @property {"weak" | "strong"=} etag options to generate etag header
|
|
96
96
|
* @property {boolean=} lastModified options to generate last modified header
|
|
97
97
|
* @property {(boolean | number | string | { maxAge?: number, immutable?: boolean })=} cacheControl options to generate cache headers
|
|
98
|
-
* @property {boolean=} cacheImmutable
|
|
98
|
+
* @property {boolean=} cacheImmutable enable immutable cache headers for immutable assets (defaults to true when omitted)
|
|
99
99
|
*/
|
|
100
100
|
/**
|
|
101
101
|
* @template {IncomingMessage} [RequestInternal=IncomingMessage]
|
|
102
102
|
* @template {ServerResponse} [ResponseInternal=ServerResponse]
|
|
103
103
|
* @callback Middleware
|
|
104
|
-
* @param {RequestInternal} req
|
|
105
|
-
* @param {ResponseInternal} res
|
|
106
|
-
* @param {NextFunction} next
|
|
104
|
+
* @param {RequestInternal} req request
|
|
105
|
+
* @param {ResponseInternal} res response
|
|
106
|
+
* @param {NextFunction} next next function
|
|
107
107
|
* @returns {Promise<void>}
|
|
108
108
|
*/
|
|
109
|
-
/** @typedef {import("./utils/getFilenameFromUrl").Extra} Extra */
|
|
109
|
+
/** @typedef {import("./utils/getFilenameFromUrl.js").Extra} Extra */
|
|
110
110
|
/**
|
|
111
111
|
* @callback GetFilenameFromUrl
|
|
112
|
-
* @param {string} url
|
|
113
|
-
* @
|
|
114
|
-
* @returns {string | undefined}
|
|
112
|
+
* @param {string} url request URL
|
|
113
|
+
* @returns {{ filename: string, extra: Extra } | undefined} a filename with additional information, or `undefined` if nothing is found
|
|
115
114
|
*/
|
|
116
115
|
/**
|
|
117
116
|
* @callback WaitUntilValid
|
|
@@ -364,7 +363,7 @@ export type Options<
|
|
|
364
363
|
)
|
|
365
364
|
| undefined;
|
|
366
365
|
/**
|
|
367
|
-
*
|
|
366
|
+
* enable immutable cache headers for immutable assets (defaults to true when omitted)
|
|
368
367
|
*/
|
|
369
368
|
cacheImmutable?: boolean | undefined;
|
|
370
369
|
};
|
|
@@ -376,11 +375,13 @@ export type Middleware<
|
|
|
376
375
|
res: ResponseInternal,
|
|
377
376
|
next: NextFunction,
|
|
378
377
|
) => Promise<void>;
|
|
379
|
-
export type Extra = import("./utils/getFilenameFromUrl").Extra;
|
|
380
|
-
export type GetFilenameFromUrl = (
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
378
|
+
export type Extra = import("./utils/getFilenameFromUrl.js").Extra;
|
|
379
|
+
export type GetFilenameFromUrl = (url: string) =>
|
|
380
|
+
| {
|
|
381
|
+
filename: string;
|
|
382
|
+
extra: Extra;
|
|
383
|
+
}
|
|
384
|
+
| undefined;
|
|
384
385
|
export type WaitUntilValid = (callback: Callback) => any;
|
|
385
386
|
export type Invalidate = (callback: Callback) => any;
|
|
386
387
|
export type Close = (callback: (err: Error | null | undefined) => void) => any;
|
package/types/middleware.d.ts
CHANGED
|
@@ -14,20 +14,27 @@ export type SendErrorOptions<
|
|
|
14
14
|
* modify response data callback
|
|
15
15
|
*/
|
|
16
16
|
modifyResponseData?:
|
|
17
|
-
| import("./index").ModifyResponseData<Request, Response>
|
|
17
|
+
| import("./index.js").ModifyResponseData<Request, Response>
|
|
18
18
|
| undefined;
|
|
19
19
|
};
|
|
20
20
|
export type NextFunction = import("./index.js").NextFunction;
|
|
21
21
|
export type IncomingMessage = import("./index.js").IncomingMessage;
|
|
22
22
|
export type ServerResponse = import("./index.js").ServerResponse;
|
|
23
23
|
export type NormalizedHeaders = import("./index.js").NormalizedHeaders;
|
|
24
|
+
export type FilenameError =
|
|
25
|
+
import("./utils/getFilenameFromUrl.js").FilenameError;
|
|
26
|
+
export type Extra = import("./utils/getFilenameFromUrl.js").Extra;
|
|
24
27
|
export type ReadStream = import("fs").ReadStream;
|
|
28
|
+
export type FilenameWithExtra = {
|
|
29
|
+
filename: string;
|
|
30
|
+
extra: Extra;
|
|
31
|
+
};
|
|
25
32
|
/**
|
|
26
33
|
* @template {IncomingMessage} Request
|
|
27
34
|
* @template {ServerResponse} Response
|
|
28
35
|
* @typedef {object} SendErrorOptions send error options
|
|
29
36
|
* @property {Record<string, number | string | string[] | undefined>=} headers headers
|
|
30
|
-
* @property {import("./index").ModifyResponseData<Request, Response>=} modifyResponseData modify response data callback
|
|
37
|
+
* @property {import("./index.js").ModifyResponseData<Request, Response>=} modifyResponseData modify response data callback
|
|
31
38
|
*/
|
|
32
39
|
/**
|
|
33
40
|
* @template {IncomingMessage} Request
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type IncomingMessage = import("../index").IncomingMessage;
|
|
2
|
-
export type ServerResponse = import("../index").ServerResponse;
|
|
3
|
-
export type OutputFileSystem = import("../index").OutputFileSystem;
|
|
4
|
-
export type EXPECTED_ANY = import("../index").EXPECTED_ANY;
|
|
1
|
+
export type IncomingMessage = import("../index.js").IncomingMessage;
|
|
2
|
+
export type ServerResponse = import("../index.js").ServerResponse;
|
|
3
|
+
export type OutputFileSystem = import("../index.js").OutputFileSystem;
|
|
4
|
+
export type EXPECTED_ANY = import("../index.js").EXPECTED_ANY;
|
|
5
5
|
export type ExpectedIncomingMessage = {
|
|
6
6
|
/**
|
|
7
7
|
* get header extra method
|
|
@@ -111,10 +111,10 @@ export function getHeadersSent<
|
|
|
111
111
|
export function getOutgoing<
|
|
112
112
|
Response extends ServerResponse & ExpectedServerResponse,
|
|
113
113
|
>(res: Response): Response;
|
|
114
|
-
/** @typedef {import("../index").IncomingMessage} IncomingMessage */
|
|
115
|
-
/** @typedef {import("../index").ServerResponse} ServerResponse */
|
|
116
|
-
/** @typedef {import("../index").OutputFileSystem} OutputFileSystem */
|
|
117
|
-
/** @typedef {import("../index").EXPECTED_ANY} EXPECTED_ANY */
|
|
114
|
+
/** @typedef {import("../index.js").IncomingMessage} IncomingMessage */
|
|
115
|
+
/** @typedef {import("../index.js").ServerResponse} ServerResponse */
|
|
116
|
+
/** @typedef {import("../index.js").OutputFileSystem} OutputFileSystem */
|
|
117
|
+
/** @typedef {import("../index.js").EXPECTED_ANY} EXPECTED_ANY */
|
|
118
118
|
/**
|
|
119
119
|
* @typedef {object} ExpectedIncomingMessage
|
|
120
120
|
* @property {((name: string) => string | string[] | undefined)=} getHeader get header extra method
|
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
export default getFilenameFromUrl;
|
|
2
2
|
export type IncomingMessage = import("../index.js").IncomingMessage;
|
|
3
|
+
export type OutputFileSystem = import("../index.js").OutputFileSystem;
|
|
3
4
|
export type ServerResponse = import("../index.js").ServerResponse;
|
|
5
|
+
export type FSStats = import("fs").Stats;
|
|
6
|
+
export type FilenameWithExtra = {
|
|
7
|
+
filename: string;
|
|
8
|
+
extra: Extra;
|
|
9
|
+
};
|
|
4
10
|
export type Extra = {
|
|
5
11
|
/**
|
|
6
12
|
* stats
|
|
7
13
|
*/
|
|
8
|
-
stats
|
|
9
|
-
/**
|
|
10
|
-
* error code
|
|
11
|
-
*/
|
|
12
|
-
errorCode?: number | undefined;
|
|
14
|
+
stats: FSStats;
|
|
13
15
|
/**
|
|
14
16
|
* true when immutable, otherwise false
|
|
15
17
|
*/
|
|
16
18
|
immutable?: boolean | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* output file system
|
|
21
|
+
*/
|
|
22
|
+
outputFileSystem: OutputFileSystem;
|
|
17
23
|
};
|
|
18
24
|
/**
|
|
19
25
|
* @typedef {object} Extra
|
|
20
|
-
* @property {
|
|
21
|
-
* @property {number=} errorCode error code
|
|
26
|
+
* @property {FSStats} stats stats
|
|
22
27
|
* @property {boolean=} immutable true when immutable, otherwise false
|
|
28
|
+
* @property {OutputFileSystem} outputFileSystem output file system
|
|
23
29
|
*/
|
|
24
30
|
/**
|
|
25
31
|
* decodeURIComponent.
|
|
@@ -28,13 +34,20 @@ export type Extra = {
|
|
|
28
34
|
* @param {string} input
|
|
29
35
|
* @returns {string}
|
|
30
36
|
*/
|
|
37
|
+
export class FilenameError extends Error {
|
|
38
|
+
/**
|
|
39
|
+
* @param {string} message message
|
|
40
|
+
* @param {number=} code error code
|
|
41
|
+
*/
|
|
42
|
+
constructor(message: string, code?: number | undefined);
|
|
43
|
+
statusCode: number | undefined;
|
|
44
|
+
}
|
|
31
45
|
/**
|
|
32
46
|
* @template {IncomingMessage} Request
|
|
33
47
|
* @template {ServerResponse} Response
|
|
34
48
|
* @param {import("../index.js").FilledContext<Request, Response>} context context
|
|
35
49
|
* @param {string} url url
|
|
36
|
-
* @
|
|
37
|
-
* @returns {string | undefined} filename
|
|
50
|
+
* @returns {FilenameWithExtra | undefined} result of get filename from url
|
|
38
51
|
*/
|
|
39
52
|
declare function getFilenameFromUrl<
|
|
40
53
|
Request extends IncomingMessage,
|
|
@@ -42,5 +55,4 @@ declare function getFilenameFromUrl<
|
|
|
42
55
|
>(
|
|
43
56
|
context: import("../index.js").FilledContext<Request, Response>,
|
|
44
57
|
url: string,
|
|
45
|
-
|
|
46
|
-
): string | undefined;
|
|
58
|
+
): FilenameWithExtra | undefined;
|
|
@@ -5,6 +5,7 @@ export type MultiStats = import("@rspack/core").MultiStats;
|
|
|
5
5
|
export type Asset = import("@rspack/core").Asset;
|
|
6
6
|
export type DevServerOption = import("../index.js").DevServerOption;
|
|
7
7
|
export type IncomingMessage = import("../index.js").IncomingMessage;
|
|
8
|
+
export type OutputFileSystem = import("../index.js").OutputFileSystem;
|
|
8
9
|
export type ServerResponse = import("../index.js").ServerResponse;
|
|
9
10
|
/** @typedef {import("@rspack/core").Compiler} Compiler */
|
|
10
11
|
/** @typedef {import("@rspack/core").Stats} Stats */
|
|
@@ -12,12 +13,13 @@ export type ServerResponse = import("../index.js").ServerResponse;
|
|
|
12
13
|
/** @typedef {import("@rspack/core").Asset} Asset */
|
|
13
14
|
/** @typedef {import("../index.js").DevServerOption} DevServerOption */
|
|
14
15
|
/** @typedef {import("../index.js").IncomingMessage} IncomingMessage */
|
|
16
|
+
/** @typedef {import("../index.js").OutputFileSystem} OutputFileSystem */
|
|
15
17
|
/** @typedef {import("../index.js").ServerResponse} ServerResponse */
|
|
16
18
|
/**
|
|
17
19
|
* @template {IncomingMessage} Request
|
|
18
20
|
* @template {ServerResponse} Response
|
|
19
21
|
* @param {import("../index.js").FilledContext<Request, Response>} context context
|
|
20
|
-
* @returns {{ outputPath: string, publicPath: string, assetsInfo: Map<string, Asset["info"]> | undefined }[]} paths
|
|
22
|
+
* @returns {{ outputPath: string, outputFileSystem: OutputFileSystem, publicPath: string, assetsInfo: Map<string, Asset["info"]> | undefined }[]} paths
|
|
21
23
|
*/
|
|
22
24
|
declare function getPaths<
|
|
23
25
|
Request extends IncomingMessage,
|
|
@@ -26,6 +28,7 @@ declare function getPaths<
|
|
|
26
28
|
context: import("../index.js").FilledContext<Request, Response>,
|
|
27
29
|
): {
|
|
28
30
|
outputPath: string;
|
|
31
|
+
outputFileSystem: OutputFileSystem;
|
|
29
32
|
publicPath: string;
|
|
30
33
|
assetsInfo: Map<string, Asset["info"]> | undefined;
|
|
31
34
|
}[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export default memorize;
|
|
2
2
|
export type FunctionReturning<T> = (...args: EXPECTED_ANY) => T;
|
|
3
|
-
export type EXPECTED_ANY = import("../index").EXPECTED_ANY;
|
|
3
|
+
export type EXPECTED_ANY = import("../index.js").EXPECTED_ANY;
|
|
4
4
|
/**
|
|
5
5
|
* @template T
|
|
6
6
|
* @typedef {(...args: EXPECTED_ANY) => T} FunctionReturning
|