webpack-dev-service 0.13.2 → 0.14.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.
Files changed (148) hide show
  1. package/README.md +9 -8
  2. package/cjs/client/client.cjs +24 -9
  3. package/cjs/client/client.d.cts +14 -0
  4. package/cjs/client/events.cjs +1 -1
  5. package/cjs/client/events.d.cts +28 -0
  6. package/cjs/client/hot.cjs +19 -21
  7. package/cjs/client/hot.d.cts +16 -0
  8. package/cjs/client/index.cjs +1 -1
  9. package/cjs/client/index.d.cts +4 -0
  10. package/cjs/client/main.cjs +4 -3
  11. package/cjs/client/main.d.cts +4 -0
  12. package/cjs/client/ui/Overlay.cjs +1 -1
  13. package/cjs/client/ui/Overlay.d.cts +12 -0
  14. package/cjs/client/ui/Progress.cjs +1 -1
  15. package/cjs/client/ui/Progress.d.cts +12 -0
  16. package/cjs/client/ui/utils.cjs +1 -1
  17. package/cjs/client/ui/utils.d.cts +15 -0
  18. package/cjs/server/compose.cjs +13 -12
  19. package/cjs/server/compose.d.cts +18 -0
  20. package/cjs/server/dev/ReadStream.cjs +1 -1
  21. package/cjs/server/dev/ReadStream.d.cts +43 -0
  22. package/cjs/server/dev/Service.cjs +1 -1
  23. package/cjs/server/dev/Service.d.cts +48 -0
  24. package/cjs/server/dev/index.cjs +1 -1
  25. package/cjs/server/dev/index.d.cts +8 -0
  26. package/cjs/server/dev/interface.d.cts +38 -0
  27. package/cjs/server/dev/middleware.cjs +1 -1
  28. package/cjs/server/dev/middleware.d.cts +6 -0
  29. package/cjs/server/dev/utils/fs.cjs +1 -1
  30. package/cjs/server/dev/utils/fs.d.cts +24 -0
  31. package/cjs/server/dev/utils/hash.cjs +1 -1
  32. package/cjs/server/dev/utils/hash.d.cts +9 -0
  33. package/cjs/server/dev/utils/http.cjs +1 -1
  34. package/cjs/server/dev/utils/http.d.cts +37 -0
  35. package/cjs/server/dev/utils/path.cjs +1 -1
  36. package/cjs/server/dev/utils/path.d.cts +22 -0
  37. package/cjs/server/dev/utils/paths.cjs +1 -1
  38. package/cjs/server/dev/utils/paths.d.cts +7 -0
  39. package/cjs/server/dev/utils/ready.cjs +1 -1
  40. package/cjs/server/dev/utils/ready.d.cts +5 -0
  41. package/cjs/server/dev/utils/setupHooks.cjs +2 -5
  42. package/cjs/server/dev/utils/setupHooks.d.cts +5 -0
  43. package/cjs/server/dev/utils/setupOutputFileSystem.cjs +1 -1
  44. package/cjs/server/dev/utils/setupOutputFileSystem.d.cts +5 -0
  45. package/cjs/server/dev/utils/setupWatching.cjs +1 -1
  46. package/cjs/server/dev/utils/setupWatching.d.cts +5 -0
  47. package/cjs/server/dev/utils/setupWriteToDisk.cjs +2 -2
  48. package/cjs/server/dev/utils/setupWriteToDisk.d.cts +5 -0
  49. package/cjs/server/hot/Message.d.cts +49 -0
  50. package/cjs/server/hot/Socket.cjs +109 -97
  51. package/cjs/server/hot/Socket.d.cts +11 -0
  52. package/cjs/server/hot/index.cjs +3 -10
  53. package/cjs/server/hot/index.d.cts +8 -0
  54. package/cjs/server/hot/interface.d.cts +22 -0
  55. package/cjs/server/hot/utils.cjs +11 -36
  56. package/cjs/server/hot/utils.d.cts +12 -0
  57. package/cjs/server/index.cjs +8 -2
  58. package/cjs/server/index.d.cts +17 -0
  59. package/cjs/server/interface.d.cts +14 -0
  60. package/cjs/server/schema.cjs +1 -1
  61. package/cjs/server/schema.d.cts +7 -0
  62. package/cjs/server/utils.cjs +1 -5
  63. package/cjs/server/utils.d.cts +11 -0
  64. package/esm/client/client.d.ts +14 -0
  65. package/esm/client/client.js +25 -10
  66. package/esm/client/events.d.ts +28 -0
  67. package/esm/client/events.js +1 -1
  68. package/esm/client/hot.d.ts +16 -0
  69. package/esm/client/hot.js +19 -19
  70. package/esm/client/index.d.ts +4 -0
  71. package/esm/client/index.js +1 -1
  72. package/esm/client/main.d.ts +4 -0
  73. package/esm/client/main.js +4 -3
  74. package/esm/client/ui/Overlay.d.ts +12 -0
  75. package/esm/client/ui/Overlay.js +1 -1
  76. package/esm/client/ui/Progress.d.ts +12 -0
  77. package/esm/client/ui/Progress.js +1 -1
  78. package/esm/client/ui/utils.d.ts +15 -0
  79. package/esm/client/ui/utils.js +1 -1
  80. package/esm/server/compose.d.ts +18 -0
  81. package/esm/server/compose.js +13 -12
  82. package/esm/server/dev/ReadStream.d.ts +43 -0
  83. package/esm/server/dev/ReadStream.js +1 -1
  84. package/esm/server/dev/Service.d.ts +48 -0
  85. package/esm/server/dev/Service.js +1 -1
  86. package/esm/server/dev/index.d.ts +8 -0
  87. package/esm/server/dev/index.js +1 -1
  88. package/esm/server/dev/interface.d.ts +38 -0
  89. package/esm/server/dev/middleware.d.ts +6 -0
  90. package/esm/server/dev/middleware.js +1 -1
  91. package/esm/server/dev/utils/fs.d.ts +24 -0
  92. package/esm/server/dev/utils/fs.js +1 -1
  93. package/esm/server/dev/utils/hash.d.ts +9 -0
  94. package/esm/server/dev/utils/hash.js +1 -1
  95. package/esm/server/dev/utils/http.d.ts +37 -0
  96. package/esm/server/dev/utils/http.js +1 -1
  97. package/esm/server/dev/utils/path.d.ts +22 -0
  98. package/esm/server/dev/utils/path.js +1 -1
  99. package/esm/server/dev/utils/paths.d.ts +7 -0
  100. package/esm/server/dev/utils/paths.js +1 -1
  101. package/esm/server/dev/utils/ready.d.ts +5 -0
  102. package/esm/server/dev/utils/ready.js +1 -1
  103. package/esm/server/dev/utils/setupHooks.d.ts +5 -0
  104. package/esm/server/dev/utils/setupHooks.js +2 -5
  105. package/esm/server/dev/utils/setupOutputFileSystem.d.ts +5 -0
  106. package/esm/server/dev/utils/setupOutputFileSystem.js +1 -1
  107. package/esm/server/dev/utils/setupWatching.d.ts +5 -0
  108. package/esm/server/dev/utils/setupWatching.js +1 -1
  109. package/esm/server/dev/utils/setupWriteToDisk.d.ts +5 -0
  110. package/esm/server/dev/utils/setupWriteToDisk.js +2 -2
  111. package/{types/client → esm/server/hot}/Message.d.ts +15 -7
  112. package/esm/server/hot/Socket.d.ts +11 -0
  113. package/esm/server/hot/Socket.js +110 -98
  114. package/esm/server/hot/index.d.ts +8 -0
  115. package/esm/server/hot/index.js +3 -10
  116. package/esm/server/hot/interface.d.ts +22 -0
  117. package/esm/server/hot/utils.d.ts +12 -0
  118. package/esm/server/hot/utils.js +12 -38
  119. package/esm/server/index.d.ts +17 -0
  120. package/esm/server/index.js +8 -2
  121. package/esm/server/interface.d.ts +14 -0
  122. package/esm/server/schema.d.ts +7 -0
  123. package/esm/server/schema.js +1 -1
  124. package/esm/server/utils.d.ts +11 -0
  125. package/esm/server/utils.js +2 -5
  126. package/global.d.ts +2 -0
  127. package/package.json +20 -19
  128. package/types/client/client.d.ts +2 -1
  129. package/types/client/events.d.ts +2 -9
  130. package/types/client/hot.d.ts +3 -14
  131. package/types/server/compose.d.ts +2 -2
  132. package/types/server/dev/index.d.ts +1 -1
  133. package/types/server/dev/interface.d.ts +2 -2
  134. package/types/server/dev/utils/fs.d.ts +2 -4
  135. package/types/server/dev/utils/paths.d.ts +1 -1
  136. package/types/server/dev/utils/ready.d.ts +1 -1
  137. package/types/server/dev/utils/setupHooks.d.ts +1 -1
  138. package/types/server/dev/utils/setupOutputFileSystem.d.ts +1 -1
  139. package/types/server/dev/utils/setupWatching.d.ts +1 -1
  140. package/types/server/dev/utils/setupWriteToDisk.d.ts +1 -1
  141. package/types/server/hot/Message.d.ts +49 -0
  142. package/types/server/hot/Socket.d.ts +1 -4
  143. package/types/server/hot/index.d.ts +4 -4
  144. package/types/server/hot/interface.d.ts +8 -6
  145. package/types/server/hot/utils.d.ts +4 -4
  146. package/types/server/index.d.ts +6 -26
  147. package/types/server/interface.d.ts +3 -0
  148. package/types/server/utils.d.ts +0 -1
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @module fs
3
+ */
4
+ import webpack from 'webpack';
5
+ import fs, { Stats } from 'node:fs';
6
+ import { GetProp } from '../../interface.cjs';
7
+ export interface FileSystem extends GetProp<webpack.Compiler, 'outputFileSystem'> {
8
+ stat: typeof fs.stat;
9
+ open: typeof fs.open;
10
+ read: typeof fs.read;
11
+ close: typeof fs.close;
12
+ }
13
+ /**
14
+ * @function createMemfs
15
+ * @description Create memfs instance.
16
+ */
17
+ export declare function createMemfs(): FileSystem;
18
+ /**
19
+ * @function stat
20
+ * @description Get file stats.
21
+ * @param fs The file system to used.
22
+ * @param path The file path.
23
+ */
24
+ export declare function stat(fs: FileSystem, path: string): Promise<Stats | null>;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @module hash
3
+ */
4
+ /**
5
+ * @function generate
6
+ * @description Generate a hash.
7
+ * @param length The length of hash.
8
+ */
9
+ export declare function generate(length: number): string;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @module http
3
+ */
4
+ import { Context } from 'koa';
5
+ import { Stats } from 'node:fs';
6
+ import { Buffer } from 'node:buffer';
7
+ export interface Range {
8
+ offset: number;
9
+ length: number;
10
+ prefix?: Buffer;
11
+ suffix?: Buffer;
12
+ }
13
+ /**
14
+ * @function decodeURI
15
+ * @description Decode URI component.
16
+ * @param URI The URI to decode.
17
+ */
18
+ export declare function decodeURI(URI: string): string | -1;
19
+ /**
20
+ * @function isConditionalGET
21
+ * @description Check if request is conditional GET.
22
+ * @param context The koa context.
23
+ */
24
+ export declare function isConditionalGET({ request }: Context): boolean;
25
+ /**
26
+ * @function isPreconditionFailed
27
+ * @description Check if request precondition failed.
28
+ * @param context The koa context.
29
+ */
30
+ export declare function isPreconditionFailed({ request, response }: Context): boolean;
31
+ /**
32
+ * @function parseRanges
33
+ * @description Parse ranges.
34
+ * @param context The koa context.
35
+ * @param stats The file stats.
36
+ */
37
+ export declare function parseRanges(context: Context, stats: Stats): Range[] | -1 | -2;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @module path
3
+ */
4
+ /**
5
+ * @function unixify
6
+ * @description Convert path to unix style.
7
+ * @param path The path to convert.
8
+ */
9
+ export declare function unixify(path: string): string;
10
+ /**
11
+ * @function hasTrailingSlash
12
+ * @description Check if path has trailing slash.
13
+ * @param path The path to check.
14
+ */
15
+ export declare function hasTrailingSlash(path: string): boolean;
16
+ /**
17
+ * @function isOutRoot
18
+ * @description Check if path is out of root.
19
+ * @param path The path to check.
20
+ * @param root The root path.
21
+ */
22
+ export declare function isOutRoot(path: string, root: string): boolean;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @module paths
3
+ */
4
+ import { UnionStats } from '../../interface.cjs';
5
+ type PathsItem = [outputPath: string, publicPath: string];
6
+ export declare function getPaths(stats: UnionStats): PathsItem[];
7
+ export {};
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @module ready
3
+ */
4
+ import { Callback, Context } from '../interface.cjs';
5
+ export declare function ready({ stats, callbacks }: Context, callback: Callback): void;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -38,7 +38,7 @@ function normalizeStatsOptions(statsOptions) {
38
38
  function getStatsOptions(context) {
39
39
  const { compiler } = context;
40
40
  const { stats } = context.options;
41
- if (stats) {
41
+ if (stats != null) {
42
42
  if (utils.isMultiCompiler(compiler)) {
43
43
  return {
44
44
  children: compiler.compilers.map(() => {
@@ -63,8 +63,6 @@ function setupHooks(context) {
63
63
  const invalid = () => {
64
64
  // We are now in invalid state.
65
65
  context.stats = null;
66
- };
67
- const watchRun = () => {
68
66
  // Log compilation starting.
69
67
  context.logger.log('compilation starting...');
70
68
  };
@@ -102,7 +100,6 @@ function setupHooks(context) {
102
100
  };
103
101
  hooks.done.tap(utils.PLUGIN_NAME, done);
104
102
  hooks.invalid.tap(utils.PLUGIN_NAME, invalid);
105
- hooks.watchRun.tap(utils.PLUGIN_NAME, watchRun);
106
103
  }
107
104
 
108
105
  exports.setupHooks = setupHooks;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @module setupHooks
3
+ */
4
+ import { InitialContext } from '../interface.cjs';
5
+ export declare function setupHooks(context: InitialContext): void;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @module setupOutputFileSystem
3
+ */
4
+ import { InitialContext } from '../interface.cjs';
5
+ export declare function setupOutputFileSystem(context: InitialContext): void;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @module setupWatching
3
+ */
4
+ import { InitialContext } from '../interface.cjs';
5
+ export declare function setupWatching(context: InitialContext): void;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -17,7 +17,7 @@ const utils = require('../../utils.cjs');
17
17
  * @module setupWriteToDisk
18
18
  */
19
19
  function getCompilerName({ options: { name } }) {
20
- return name ? `compiler "${name}": ` : '';
20
+ return `compiler ${name ? `${name}: ` : ''}`;
21
21
  }
22
22
  function isAllowWrite(targetPath, filter) {
23
23
  return utils.isFunction(filter) ? filter(targetPath) : filter === true;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @module setupWriteToDisk
3
+ */
4
+ import { InitialContext } from '../interface.cjs';
5
+ export declare function setupWriteToDisk(context: InitialContext): void;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @module message
3
+ */
4
+ import webpack from 'webpack';
5
+ import { GetProp } from '../interface.cjs';
6
+ export interface Invalid {
7
+ action: 'invalid';
8
+ payload: {
9
+ timestamp: number;
10
+ path: string | null;
11
+ };
12
+ }
13
+ export interface Progress {
14
+ action: 'progress';
15
+ payload: {
16
+ status: string;
17
+ messages: string[];
18
+ percentage: number;
19
+ };
20
+ }
21
+ export interface Hash {
22
+ action: 'hash';
23
+ payload: {
24
+ hash: string;
25
+ timestamp: number;
26
+ };
27
+ }
28
+ export interface Issues {
29
+ action: 'issues';
30
+ payload: {
31
+ timestamp: number;
32
+ errors: webpack.StatsError[];
33
+ warnings: webpack.StatsError[];
34
+ };
35
+ }
36
+ export interface Ok {
37
+ action: 'ok';
38
+ payload: {
39
+ timestamp: number;
40
+ };
41
+ }
42
+ export interface Messages {
43
+ ok: GetProp<Ok, 'payload'>;
44
+ hash: GetProp<Hash, 'payload'>;
45
+ issues: GetProp<Issues, 'payload'>;
46
+ invalid: GetProp<Invalid, 'payload'>;
47
+ progress: GetProp<Progress, 'payload'>;
48
+ }
49
+ export type Message = Invalid | Progress | Hash | Issues | Ok;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -10,9 +10,10 @@
10
10
  'use strict';
11
11
 
12
12
  const webpack = require('webpack');
13
+ const uuid = require('uuid');
13
14
  const node_buffer = require('node:buffer');
14
- const node_url = require('node:url');
15
15
  const node_path = require('node:path');
16
+ const node_url = require('node:url');
16
17
  const WebSocket = require('ws');
17
18
  const utils$1 = require('../utils.cjs');
18
19
  const utils = require('./utils.cjs');
@@ -29,52 +30,45 @@ const WebSocket__default = /*#__PURE__*/ _interopDefault(WebSocket);
29
30
  */
30
31
  function entrypoint() {
31
32
  const filename = require.main.filename;
32
- try {
33
- return node_path.dirname(node_url.fileURLToPath(filename));
34
- } catch {
35
- return node_path.dirname(filename);
36
- }
33
+ return node_path.dirname(filename);
37
34
  }
38
35
  const client = node_path.resolve(entrypoint(), '../../client/main.cjs');
39
36
  class Socket {
40
37
  // Readonly props.
41
38
  #logger;
42
- #compiler;
43
39
  #server;
44
40
  #options;
45
- // Mutable props.
46
- #percentage = -1;
47
- #stats = null;
48
41
  constructor(compiler, options) {
49
- this.#compiler = compiler;
50
42
  this.#options = utils.getOptions(options);
51
43
  this.#logger = compiler.getInfrastructureLogger(utils$1.PLUGIN_NAME);
52
44
  this.#server = new WebSocket.WebSocketServer({ noServer: true, path: this.#options.path });
53
- this.#setupWss();
54
- this.#setupHooks();
55
- this.#setupPlugins();
56
- }
57
- #setupWss() {
58
- const logger = this.#logger;
59
- const server = this.#server;
60
- server.on('connection', client => {
61
- const stats = this.#stats;
62
- logger.log('client connected');
63
- client.on('close', () => {
64
- logger.log('client disconnected');
65
- });
66
- if (stats) {
67
- this.#broadcastStats([client], stats);
68
- }
69
- });
70
- server.on('error', error => {
71
- logger.error(error);
72
- });
45
+ const compilers = utils$1.getCompilers(compiler);
46
+ const contexts = new Map();
47
+ for (const compiler of compilers) {
48
+ const uuid$1 = uuid.v7();
49
+ const context = {
50
+ uuid: uuid$1,
51
+ stats: null,
52
+ percentage: -1,
53
+ clients: new Set()
54
+ };
55
+ contexts.set(uuid$1, context);
56
+ this.#setupHooks(compiler, context);
57
+ this.#setupPlugins(compiler, context);
58
+ }
59
+ this.#setupWss(contexts);
73
60
  }
74
- #setupHooks() {
75
- const compiler = this.#compiler;
61
+ #setupHooks(compiler, context) {
76
62
  const { hooks } = compiler;
77
63
  const statsOptions = utils.getStatsOptions(compiler);
64
+ hooks.invalid.tap(utils$1.PLUGIN_NAME, (path, timestamp) => {
65
+ // Set stats to null.
66
+ context.stats = null;
67
+ // Reset percentage.
68
+ context.percentage = -1;
69
+ // Broadcast invalid.
70
+ this.#broadcast(context.clients, 'invalid', { path, timestamp });
71
+ });
78
72
  hooks.done.tap(utils$1.PLUGIN_NAME, stats => {
79
73
  // Get json stats.
80
74
  const jsonStats = stats.toJson(statsOptions);
@@ -83,66 +77,102 @@ class Socket {
83
77
  jsonStats.builtAt = utils.getTimestamp(jsonStats);
84
78
  }
85
79
  // Cache stats.
86
- this.#stats = jsonStats;
80
+ context.stats = jsonStats;
87
81
  // Do the stuff in nextTick, because bundle may be invalidated if a change happened while compiling.
88
82
  process.nextTick(() => {
89
- const stats = this.#stats;
83
+ const { stats } = context;
90
84
  // Broadcast stats.
91
85
  if (stats) {
92
- this.#broadcastStats(this.clients(), stats);
86
+ this.#broadcastStats(context.clients, stats);
93
87
  }
94
88
  });
95
89
  });
96
- hooks.invalid.tap(utils$1.PLUGIN_NAME, (path, timestamp) => {
97
- // Set stats to null.
98
- this.#stats = null;
99
- // Reset percentage.
100
- this.#percentage = -1;
101
- // Broadcast invalid.
102
- this.broadcast(this.clients(), 'invalid', { path, timestamp });
103
- });
104
90
  }
105
- #setupPlugins() {
91
+ #setupPlugins(compiler, context) {
106
92
  const options = this.#options;
107
- const compiler = this.#compiler;
108
- const compilers = utils$1.getCompilers(compiler);
93
+ const params = new URLSearchParams();
94
+ params.set('uuid', context.uuid);
95
+ params.set('path', options.path);
96
+ const { wss } = options;
97
+ if (wss != null) {
98
+ params.set('wss', wss ? 'true' : 'false');
99
+ }
100
+ params.set('name', compiler.name || 'rspack');
101
+ params.set('hmr', options.hmr ? 'true' : 'false');
102
+ params.set('reload', options.reload ? 'true' : 'false');
103
+ params.set('overlay', options.overlay ? 'true' : 'false');
104
+ params.set('progress', options.progress ? 'true' : 'false');
109
105
  const plugins = [
110
- () => {
111
- return new webpack__default.default.HotModuleReplacementPlugin();
112
- },
113
- ({ name, context }) => {
114
- const params = new URLSearchParams();
115
- params.set('path', options.path);
116
- params.set('name', name || 'webpack');
117
- params.set('hmr', options.hmr ? 'true' : 'false');
118
- params.set('wss', options.wss ? 'true' : 'false');
119
- params.set('reload', options.reload ? 'true' : 'false');
120
- params.set('overlay', options.overlay ? 'true' : 'false');
121
- params.set('progress', options.progress ? 'true' : 'false');
122
- // Auto add hot client to entry.
123
- return new webpack__default.default.EntryPlugin(context, `${client}?${params}`, {
124
- // Don't create runtime.
125
- runtime: false
126
- });
127
- }
106
+ new webpack__default.default.HotModuleReplacementPlugin(),
107
+ // Auto add hot client to entry.
108
+ new webpack__default.default.EntryPlugin(compiler.context, `${client}?${params}`, {
109
+ // Don't create runtime.
110
+ runtime: false
111
+ })
128
112
  ];
129
- for (const compiler of compilers) {
130
- for (const plugin of plugins) {
131
- plugin(compiler).apply(compiler);
132
- }
133
- }
134
113
  if (options.progress) {
135
- const progress = new webpack__default.default.ProgressPlugin((percentage, status, ...messages) => {
136
- if (percentage > this.#percentage) {
137
- this.#percentage = percentage;
138
- this.broadcast(this.clients(), 'progress', { status, messages, percentage });
114
+ plugins.push(
115
+ new webpack__default.default.ProgressPlugin((percentage, status, ...messages) => {
116
+ if (percentage > context.percentage) {
117
+ context.percentage = percentage;
118
+ this.#broadcast(context.clients, 'progress', { status, messages, percentage });
119
+ }
120
+ })
121
+ );
122
+ }
123
+ for (const plugin of plugins) {
124
+ plugin.apply(compiler);
125
+ }
126
+ }
127
+ #setupWss(contexts) {
128
+ const logger = this.#logger;
129
+ const server = this.#server;
130
+ const { path } = this.#options;
131
+ server.on('connection', (client, { url: input = path }) => {
132
+ const url = new node_url.URL(input, utils.BASE_URL);
133
+ const uuid = url.searchParams.get('uuid');
134
+ if (uuid) {
135
+ const context = contexts.get(uuid);
136
+ if (context) {
137
+ const { stats } = context;
138
+ context.clients.add(client);
139
+ logger.log('client connected');
140
+ client.on('close', () => {
141
+ context.clients.delete(client);
142
+ logger.log('client disconnected');
143
+ });
144
+ if (stats) {
145
+ const clients = new Set([client]);
146
+ this.#broadcastStats(clients, stats);
147
+ }
148
+ } else {
149
+ client.close(4001, 'compiler not found');
139
150
  }
140
- });
141
- progress.apply(compiler);
151
+ } else {
152
+ client.close(4000, 'uuid not found');
153
+ }
154
+ });
155
+ server.on('error', error => {
156
+ logger.error(error);
157
+ });
158
+ }
159
+ #broadcast(clients, action, payload) {
160
+ for (const client of clients) {
161
+ if (client.readyState === WebSocket__default.default.OPEN) {
162
+ client.send(JSON.stringify({ action, payload }));
163
+ }
142
164
  }
143
165
  }
144
- clients() {
145
- return this.#server.clients;
166
+ #broadcastStats(clients, stats) {
167
+ if (clients.size > 0) {
168
+ const { hash, errors, warnings, builtAt: timestamp } = stats;
169
+ this.#broadcast(clients, 'hash', { hash, timestamp });
170
+ if (utils.hasIssues(errors) || utils.hasIssues(warnings)) {
171
+ this.#broadcast(clients, 'issues', { errors, warnings, timestamp });
172
+ } else {
173
+ this.#broadcast(clients, 'ok', { timestamp });
174
+ }
175
+ }
146
176
  }
147
177
  upgrade(context) {
148
178
  const server = this.#server;
@@ -158,24 +188,6 @@ class Socket {
158
188
  }
159
189
  return false;
160
190
  }
161
- broadcast(clients, action, payload) {
162
- for (const client of clients) {
163
- if (client.readyState === WebSocket__default.default.OPEN) {
164
- client.send(JSON.stringify({ action, payload }));
165
- }
166
- }
167
- }
168
- #broadcastStats(clients, stats) {
169
- if (clients.size > 0 || clients.length > 0) {
170
- const { hash, errors, warnings, builtAt: timestamp } = stats;
171
- this.broadcast(clients, 'hash', { hash, timestamp });
172
- if (utils.hasIssues(errors) || utils.hasIssues(warnings)) {
173
- this.broadcast(clients, 'issues', { errors, warnings, timestamp });
174
- } else {
175
- this.broadcast(clients, 'ok', { timestamp });
176
- }
177
- }
178
- }
179
191
  }
180
192
 
181
193
  exports.Socket = Socket;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @module Socket
3
+ */
4
+ import { Context } from 'koa';
5
+ import { UnionCompiler } from '../interface.cjs';
6
+ import { Options } from './interface.cjs';
7
+ export declare class Socket {
8
+ #private;
9
+ constructor(compiler: UnionCompiler, options?: Options);
10
+ upgrade(context: Context): boolean;
11
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -16,19 +16,12 @@ const Socket = require('./Socket.cjs');
16
16
  */
17
17
  function hot(compiler, options) {
18
18
  const socket = new Socket.Socket(compiler, options);
19
- const middleware = async (ctx, next) => {
19
+ // Middleware.
20
+ return async (ctx, next) => {
20
21
  if (!socket.upgrade(ctx)) {
21
22
  await next();
22
23
  }
23
24
  };
24
- return Object.assign(middleware, {
25
- clients() {
26
- return socket.clients();
27
- },
28
- broadcast(clients, action, payload) {
29
- socket.broadcast(clients, action, payload);
30
- }
31
- });
32
25
  }
33
26
 
34
27
  exports.hot = hot;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @module index
3
+ */
4
+ import { Middleware } from 'koa';
5
+ import { Options } from './interface.cjs';
6
+ import { UnionCompiler } from '../interface.cjs';
7
+ export { Options };
8
+ export declare function hot(compiler: UnionCompiler, options?: Options): Middleware;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @module interface
3
+ */
4
+ import WebSocket from 'ws';
5
+ import webpack from 'webpack';
6
+ import { RequiredKeys } from '../interface.cjs';
7
+ export interface Options {
8
+ hmr?: boolean;
9
+ path?: string;
10
+ wss?: boolean;
11
+ reload?: boolean;
12
+ overlay?: boolean;
13
+ progress?: boolean;
14
+ }
15
+ export type Clients = Set<WebSocket>;
16
+ export interface CompilerContext {
17
+ percentage: number;
18
+ readonly uuid: string;
19
+ readonly clients: Clients;
20
+ stats: Required<webpack.StatsCompilation> | null;
21
+ }
22
+ export type NormalizedOptions = RequiredKeys<Options, 'hmr' | 'path' | 'reload' | 'overlay' | 'progress'>;