webpack-dev-service 0.10.0 → 0.10.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.
Files changed (57) hide show
  1. package/cjs/client/client.cjs +128 -0
  2. package/cjs/client/events.cjs +64 -0
  3. package/cjs/client/hot.cjs +111 -0
  4. package/cjs/client/index.cjs +15 -0
  5. package/cjs/client/main.cjs +59 -0
  6. package/cjs/client/ui/overlay.cjs +233 -0
  7. package/cjs/client/ui/progress.cjs +92 -0
  8. package/cjs/client/ui/utils.cjs +136 -0
  9. package/cjs/server/compose.cjs +56 -0
  10. package/cjs/server/dev/Service.cjs +269 -0
  11. package/cjs/server/dev/index.cjs +60 -0
  12. package/cjs/server/dev/middleware.cjs +96 -0
  13. package/cjs/server/dev/utils/fs.cjs +29 -0
  14. package/cjs/server/dev/utils/hash.cjs +46 -0
  15. package/cjs/server/dev/utils/http.cjs +227 -0
  16. package/cjs/server/dev/utils/path.cjs +46 -0
  17. package/cjs/server/dev/utils/paths.cjs +59 -0
  18. package/cjs/server/dev/utils/ready.cjs +23 -0
  19. package/cjs/server/dev/utils/setupHooks.cjs +106 -0
  20. package/cjs/server/dev/utils/setupOutputFileSystem.cjs +31 -0
  21. package/cjs/server/dev/utils/setupWatching.cjs +43 -0
  22. package/cjs/server/dev/utils/setupWriteToDisk.cjs +54 -0
  23. package/cjs/server/hot/Socket.cjs +185 -0
  24. package/cjs/server/hot/index.cjs +34 -0
  25. package/cjs/server/hot/utils.cjs +100 -0
  26. package/cjs/server/index.cjs +1 -1
  27. package/cjs/server/schema.cjs +127 -0
  28. package/cjs/server/utils.cjs +45 -0
  29. package/esm/client/client.js +126 -0
  30. package/esm/client/events.js +60 -0
  31. package/esm/client/hot.js +106 -0
  32. package/esm/client/index.js +10 -0
  33. package/esm/client/main.js +57 -0
  34. package/esm/client/ui/overlay.js +231 -0
  35. package/esm/client/ui/progress.js +90 -0
  36. package/esm/client/ui/utils.js +123 -0
  37. package/esm/server/compose.js +54 -0
  38. package/esm/server/dev/Service.js +260 -0
  39. package/esm/server/dev/index.js +58 -0
  40. package/esm/server/dev/middleware.js +94 -0
  41. package/esm/server/dev/utils/fs.js +27 -0
  42. package/esm/server/dev/utils/hash.js +44 -0
  43. package/esm/server/dev/utils/http.js +216 -0
  44. package/esm/server/dev/utils/path.js +42 -0
  45. package/esm/server/dev/utils/paths.js +57 -0
  46. package/esm/server/dev/utils/ready.js +21 -0
  47. package/esm/server/dev/utils/setupHooks.js +98 -0
  48. package/esm/server/dev/utils/setupOutputFileSystem.js +29 -0
  49. package/esm/server/dev/utils/setupWatching.js +41 -0
  50. package/esm/server/dev/utils/setupWriteToDisk.js +52 -0
  51. package/esm/server/hot/Socket.js +176 -0
  52. package/esm/server/hot/index.js +32 -0
  53. package/esm/server/hot/utils.js +93 -0
  54. package/esm/server/index.js +37 -0
  55. package/esm/server/schema.js +125 -0
  56. package/esm/server/utils.js +37 -0
  57. package/package.json +4 -4
@@ -0,0 +1,185 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.10.1
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const url = require('url');
13
+ const path = require('path');
14
+ const WebSocket = require('ws');
15
+ const webpack = require('webpack');
16
+ const utils$1 = require('../utils.cjs');
17
+ const utils = require('./utils.cjs');
18
+
19
+ function _interopDefault(e) {
20
+ return e && e.__esModule ? e : { default: e };
21
+ }
22
+
23
+ const WebSocket__default = /*#__PURE__*/ _interopDefault(WebSocket);
24
+ const webpack__default = /*#__PURE__*/ _interopDefault(webpack);
25
+
26
+ /**
27
+ * @module Socket
28
+ */
29
+ function entrypoint() {
30
+ const filename = require.main.filename;
31
+ try {
32
+ return path.dirname(url.fileURLToPath(filename));
33
+ } catch (_a) {
34
+ return path.dirname(filename);
35
+ }
36
+ }
37
+ const client = path.resolve(entrypoint(), '../../client/main.cjs');
38
+ class Socket {
39
+ constructor(compiler, options) {
40
+ this.stats = null;
41
+ this.compiler = compiler;
42
+ this.options = utils.getOptions(options);
43
+ this.server = new WebSocket.WebSocketServer({
44
+ noServer: true,
45
+ path: this.options.path
46
+ });
47
+ this.logger = compiler.getInfrastructureLogger(utils$1.PLUGIN_NAME);
48
+ this.setupWss();
49
+ this.setupHooks();
50
+ this.setupPlugins();
51
+ }
52
+ setupWss() {
53
+ const { server, logger } = this;
54
+ server.on('connection', client => {
55
+ if (this.stats) {
56
+ this.broadcastStats([client], this.stats);
57
+ }
58
+ logger.log('client connected');
59
+ });
60
+ server.on('error', error => {
61
+ logger.error(error);
62
+ });
63
+ server.on('close', function () {
64
+ logger.log('client disconnected');
65
+ });
66
+ }
67
+ setupHooks() {
68
+ const { compiler } = this;
69
+ const { hooks } = compiler;
70
+ const statsOptions = utils.getStatsOptions(compiler);
71
+ hooks.done.tap(utils$1.PLUGIN_NAME, stats => {
72
+ // Get json stats.
73
+ const jsonStats = stats.toJson(statsOptions);
74
+ // Hack builtAt.
75
+ if (jsonStats.builtAt == null) {
76
+ jsonStats.builtAt = utils.getTimestamp(jsonStats);
77
+ }
78
+ // Cache stats.
79
+ this.stats = jsonStats;
80
+ // Do the stuff in nextTick, because bundle may be invalidated if a change happened while compiling.
81
+ process.nextTick(() => {
82
+ const { stats } = this;
83
+ // Broadcast stats.
84
+ if (stats) {
85
+ this.broadcastStats(this.clients(), stats);
86
+ }
87
+ });
88
+ });
89
+ hooks.invalid.tap(utils$1.PLUGIN_NAME, (path, timestamp) => {
90
+ // Set stats to null.
91
+ this.stats = null;
92
+ // Broadcast invalid.
93
+ this.broadcast(this.clients(), 'invalid', { path, timestamp });
94
+ });
95
+ }
96
+ setupPlugins() {
97
+ const { options, compiler } = this;
98
+ const compilers = utils$1.getCompilers(compiler);
99
+ const plugins = [
100
+ () => {
101
+ return new webpack__default.default.NoEmitOnErrorsPlugin();
102
+ },
103
+ () => {
104
+ return new webpack__default.default.HotModuleReplacementPlugin();
105
+ },
106
+ ({ name, context }) => {
107
+ const params = new URLSearchParams();
108
+ params.set('path', options.path);
109
+ params.set('name', name || 'webpack');
110
+ params.set('hmr', options.hmr ? 'true' : 'false');
111
+ params.set('wss', options.wss ? 'true' : 'false');
112
+ params.set('reload', options.reload ? 'true' : 'false');
113
+ params.set('overlay', options.overlay ? 'true' : 'false');
114
+ params.set('progress', options.progress ? 'true' : 'false');
115
+ // Auto add hot client to entry.
116
+ return new webpack__default.default.EntryPlugin(context, `${client}?${params}`, {
117
+ // Don't create runtime.
118
+ runtime: false
119
+ });
120
+ }
121
+ ];
122
+ for (const compiler of compilers) {
123
+ for (const plugin of plugins) {
124
+ plugin(compiler).apply(compiler);
125
+ }
126
+ }
127
+ if (options.progress) {
128
+ let value = 0;
129
+ new webpack__default.default.ProgressPlugin((percentage, status, message) => {
130
+ const nextValue = Math.floor(percentage * 100);
131
+ if (nextValue > value || nextValue === 0) {
132
+ value = nextValue;
133
+ switch (value) {
134
+ case 0:
135
+ status = 'start';
136
+ message = 'end idle';
137
+ break;
138
+ case 100:
139
+ status = 'finish';
140
+ message = 'begin idle';
141
+ break;
142
+ }
143
+ this.broadcast(this.clients(), 'progress', { status, message, value });
144
+ }
145
+ }).apply(compiler);
146
+ }
147
+ }
148
+ clients() {
149
+ return this.server.clients;
150
+ }
151
+ upgrade(context) {
152
+ const { server } = this;
153
+ const { req: request } = context;
154
+ if (utils.isUpgradable(context, utils.WEBSOCKET_RE) && server.shouldHandle(request)) {
155
+ context.respond = false;
156
+ const { socket } = context;
157
+ const head = Buffer.alloc(0);
158
+ server.handleUpgrade(request, socket, head, client => {
159
+ server.emit('connection', client, request);
160
+ });
161
+ return true;
162
+ }
163
+ return false;
164
+ }
165
+ broadcast(clients, action, payload) {
166
+ for (const client of clients) {
167
+ if (client.readyState === WebSocket__default.default.OPEN) {
168
+ client.send(JSON.stringify({ action, payload }));
169
+ }
170
+ }
171
+ }
172
+ broadcastStats(clients, stats) {
173
+ if (clients.size > 0 || clients.length > 0) {
174
+ const { hash, errors, warnings, builtAt: timestamp } = stats;
175
+ this.broadcast(clients, 'hash', { hash, timestamp });
176
+ if (utils.hasIssues(errors) || utils.hasIssues(warnings)) {
177
+ this.broadcast(clients, 'issues', { errors, warnings, timestamp });
178
+ } else {
179
+ this.broadcast(clients, 'ok', { timestamp });
180
+ }
181
+ }
182
+ }
183
+ }
184
+
185
+ exports.Socket = Socket;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.10.1
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const Socket = require('./Socket.cjs');
13
+
14
+ /**
15
+ * @module index
16
+ */
17
+ function hot(compiler, options) {
18
+ const socket = new Socket.Socket(compiler, options);
19
+ const middleware = async (ctx, next) => {
20
+ if (!socket.upgrade(ctx)) {
21
+ await next();
22
+ }
23
+ };
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
+ }
33
+
34
+ exports.hot = hot;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.10.1
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const utils = require('../utils.cjs');
13
+
14
+ /**
15
+ * @module utils
16
+ */
17
+ const WEBSOCKET_RE = /^websocket$/i;
18
+ function normalize(path) {
19
+ const segments = [];
20
+ const parts = path.split(/[\\/]+/);
21
+ for (const segment of parts) {
22
+ switch (segment) {
23
+ case '.':
24
+ break;
25
+ case '..':
26
+ segments.pop();
27
+ break;
28
+ default:
29
+ segments.push(segment);
30
+ break;
31
+ }
32
+ }
33
+ const pathname = segments.join('/');
34
+ return pathname.startsWith('/') ? pathname : `/${pathname}`;
35
+ }
36
+ function getOptions(options) {
37
+ const settings = {
38
+ hmr: true,
39
+ wss: false,
40
+ path: '/hot',
41
+ reload: true,
42
+ overlay: true,
43
+ progress: true,
44
+ ...options
45
+ };
46
+ settings.path = normalize(settings.path);
47
+ return settings;
48
+ }
49
+ function isUpgradable(context, detector) {
50
+ const { upgrade } = context.headers;
51
+ return !!upgrade && detector.test(upgrade.trim());
52
+ }
53
+ function hasIssues(issues) {
54
+ return Array.isArray(issues) && issues.length > 0;
55
+ }
56
+ function normalizeStatsOptions(statsOptions) {
57
+ if (!utils.isObject(statsOptions)) {
58
+ statsOptions = {};
59
+ }
60
+ return {
61
+ ...statsOptions,
62
+ all: false,
63
+ hash: true,
64
+ colors: true,
65
+ errors: true,
66
+ assets: false,
67
+ builtAt: true,
68
+ warnings: true,
69
+ errorDetails: false
70
+ };
71
+ }
72
+ function getStatsOptions(compiler) {
73
+ if (utils.isMultiCompilerMode(compiler)) {
74
+ return {
75
+ children: compiler.compilers.map(({ options }) => {
76
+ return normalizeStatsOptions(options.stats);
77
+ })
78
+ };
79
+ }
80
+ return normalizeStatsOptions(compiler.options.stats);
81
+ }
82
+ function getTimestamp({ builtAt, children = [] }) {
83
+ if (builtAt != null) {
84
+ return builtAt;
85
+ }
86
+ let timestamp = -1;
87
+ for (const { builtAt = timestamp } of children) {
88
+ if (builtAt > timestamp) {
89
+ timestamp = builtAt;
90
+ }
91
+ }
92
+ return timestamp < 0 ? Date.now() : timestamp;
93
+ }
94
+
95
+ exports.WEBSOCKET_RE = WEBSOCKET_RE;
96
+ exports.getOptions = getOptions;
97
+ exports.getStatsOptions = getStatsOptions;
98
+ exports.getTimestamp = getTimestamp;
99
+ exports.hasIssues = hasIssues;
100
+ exports.isUpgradable = isUpgradable;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.10.0
4
+ * @version 0.10.1
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,127 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.10.1
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ /**
13
+ * @module schema
14
+ */
15
+ const schema = {
16
+ type: 'object',
17
+ properties: {
18
+ hot: {
19
+ description: 'Enable or disable HMR server.',
20
+ anyOf: [
21
+ {
22
+ type: 'boolean',
23
+ enum: [false]
24
+ },
25
+ {
26
+ type: 'object',
27
+ properties: {
28
+ hmr: {
29
+ type: 'boolean',
30
+ description: 'Enable or disable Hot Module Replacement.'
31
+ },
32
+ path: {
33
+ type: 'string',
34
+ description: 'Specify the path used by the HMR server.'
35
+ },
36
+ wss: {
37
+ type: 'boolean',
38
+ description: 'Use WebSockets Secure (wss://) for HMR instead of the default WebSocket (ws://).'
39
+ },
40
+ reload: {
41
+ type: 'boolean',
42
+ description: 'Control whether the full page should be reloaded when HMR failure.'
43
+ },
44
+ overlay: {
45
+ type: 'boolean',
46
+ description: 'Enable or disable an error overlay in the browser when there are compilation errors.'
47
+ },
48
+ progress: {
49
+ type: 'boolean',
50
+ description: 'Display a progress bar in the browser during the build process.'
51
+ }
52
+ },
53
+ additionalProperties: false
54
+ }
55
+ ]
56
+ },
57
+ ignore: {
58
+ instanceof: 'Function',
59
+ description: 'Function that determines if a file should be ignored.'
60
+ },
61
+ etag: {
62
+ type: 'boolean',
63
+ description: 'Enable or disable the ETag functionality for file serving.'
64
+ },
65
+ acceptRanges: {
66
+ type: 'boolean',
67
+ description: 'Indicate whether the server supports range requests for file resources.'
68
+ },
69
+ lastModified: {
70
+ type: 'boolean',
71
+ description: 'Enable or disable sending last modified headers for file resources.'
72
+ },
73
+ headers: {
74
+ description: 'Headers to serve with files.',
75
+ anyOf: [
76
+ {
77
+ type: 'object',
78
+ additionalProperties: {
79
+ anyOf: [
80
+ {
81
+ type: 'string'
82
+ },
83
+ {
84
+ type: 'array',
85
+ items: {
86
+ type: 'string'
87
+ }
88
+ }
89
+ ]
90
+ },
91
+ description: 'Headers object to serve with files.'
92
+ },
93
+ {
94
+ instanceof: 'Function',
95
+ description: 'Function that returns headers to serve with files.'
96
+ }
97
+ ]
98
+ },
99
+ fs: {
100
+ type: 'object',
101
+ description: 'The output file system used by the dev server.'
102
+ },
103
+ stats: {
104
+ type: 'object',
105
+ description: 'Options for the statistics output.'
106
+ },
107
+ writeToDisk: {
108
+ anyOf: [
109
+ {
110
+ type: 'boolean',
111
+ description: 'Enable or disable writing files to disk.'
112
+ },
113
+ {
114
+ instanceof: 'Function',
115
+ description: 'Function that determines if a file should be written to disk based on its target path.'
116
+ }
117
+ ]
118
+ },
119
+ onCompilerDone: {
120
+ instanceof: 'Function',
121
+ description: 'Callback function when the compiler is done, providing statistics and options.'
122
+ }
123
+ },
124
+ additionalProperties: false
125
+ };
126
+
127
+ exports.schema = schema;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.10.1
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ /**
13
+ * @module utils
14
+ */
15
+ const { toString } = Object.prototype;
16
+ const PLUGIN_NAME = 'webpack-dev-service';
17
+ function isObject(value) {
18
+ return toString.call(value) === '[object Object]';
19
+ }
20
+ function isString(value) {
21
+ return toString.call(value) === '[object String]';
22
+ }
23
+ function isBoolean(value) {
24
+ return toString.call(value) === '[object Boolean]';
25
+ }
26
+ function isFunction(value) {
27
+ return typeof value === 'function';
28
+ }
29
+ function getCompilers(compiler) {
30
+ if (isMultiCompilerMode(compiler)) {
31
+ return compiler.compilers;
32
+ }
33
+ return [compiler];
34
+ }
35
+ function isMultiCompilerMode(compiler) {
36
+ return 'compilers' in compiler;
37
+ }
38
+
39
+ exports.PLUGIN_NAME = PLUGIN_NAME;
40
+ exports.getCompilers = getCompilers;
41
+ exports.isBoolean = isBoolean;
42
+ exports.isFunction = isFunction;
43
+ exports.isMultiCompilerMode = isMultiCompilerMode;
44
+ exports.isObject = isObject;
45
+ exports.isString = isString;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.10.1
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ import { emit } from './events.js';
11
+ import Overlay from './ui/overlay.js';
12
+ import Progress from './ui/progress.js';
13
+ import { applyUpdate, setHash } from './hot.js';
14
+
15
+ /**
16
+ * @module client
17
+ */
18
+ function createClient(options) {
19
+ let updateTimer;
20
+ const UPDATE_DELAY = 128;
21
+ const RETRY_INTERVAL = 3000;
22
+ const progress = new Progress();
23
+ const overlay = new Overlay(options.name);
24
+ const fallback = () => {
25
+ if (options.reload) {
26
+ self.location.reload();
27
+ } else {
28
+ console.warn('Use fallback update but you turn off live reload, please reload by yourself.');
29
+ }
30
+ };
31
+ const applyUpdateAsync = () => {
32
+ updateTimer = self.setTimeout(() => {
33
+ applyUpdate(options.hmr, fallback);
34
+ }, UPDATE_DELAY);
35
+ };
36
+ const onInvalid = () => {
37
+ clearTimeout(updateTimer);
38
+ if (options.progress) {
39
+ progress.update(0);
40
+ progress.show();
41
+ }
42
+ };
43
+ const onProgress = ({ value }) => {
44
+ if (options.progress) {
45
+ progress.update(value);
46
+ }
47
+ };
48
+ const onHash = ({ hash }) => {
49
+ setHash(hash);
50
+ };
51
+ const setIssues = (type, issues) => {
52
+ if (options.overlay) {
53
+ overlay.setIssues(type, issues);
54
+ }
55
+ const maps = {
56
+ errors: ['\x1b[38;2;100;30;22m\x1b[48;2;255;95;88m ERROR \x1b[0m', 'error'],
57
+ warnings: ['\x1b[38;2;32;39;35m\x1b[48;2;255;189;46m WARNING \x1b[0m', 'warn']
58
+ };
59
+ const [name, method] = maps[type];
60
+ const debug = console[method];
61
+ for (const { moduleName, chunkName, message } of issues) {
62
+ const filename = moduleName || chunkName || 'unknown';
63
+ debug(`${name} in ${filename}\n${message}`);
64
+ }
65
+ };
66
+ const onIssues = ({ errors, warnings }) => {
67
+ progress.hide();
68
+ setIssues('errors', errors);
69
+ setIssues('warnings', warnings);
70
+ if (options.overlay) {
71
+ overlay.show();
72
+ }
73
+ if (errors.length <= 0) {
74
+ applyUpdateAsync();
75
+ }
76
+ };
77
+ const onOk = () => {
78
+ overlay.hide();
79
+ progress.hide();
80
+ applyUpdateAsync();
81
+ };
82
+ const parseMessage = message => {
83
+ try {
84
+ return JSON.parse(message.data);
85
+ } catch (_a) {
86
+ return null;
87
+ }
88
+ };
89
+ const createWebSocket = url => {
90
+ const ws = new WebSocket(url);
91
+ ws.onmessage = message => {
92
+ const parsed = parseMessage(message);
93
+ if (parsed) {
94
+ const { action, payload } = parsed;
95
+ switch (action) {
96
+ case 'invalid':
97
+ onInvalid();
98
+ break;
99
+ case 'progress':
100
+ onProgress(payload);
101
+ break;
102
+ case 'hash':
103
+ onHash(payload);
104
+ break;
105
+ case 'issues':
106
+ onIssues(payload);
107
+ break;
108
+ case 'ok':
109
+ onOk();
110
+ break;
111
+ }
112
+ emit(action, payload, options);
113
+ }
114
+ };
115
+ ws.onclose = () => {
116
+ overlay.hide();
117
+ progress.hide();
118
+ setTimeout(() => {
119
+ createWebSocket(url);
120
+ }, RETRY_INTERVAL);
121
+ };
122
+ };
123
+ createWebSocket(`${options.origin}${options.path}`);
124
+ }
125
+
126
+ export { createClient as default };
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.10.1
5
+ * @author nuintun <nuintun@qq.com>
6
+ * @description A koa 2 middleware for webpack development and hot reloading.
7
+ * @see https://github.com/nuintun/webpack-dev-service#readme
8
+ */
9
+
10
+ /**
11
+ * @module events
12
+ */
13
+ const events = {
14
+ ok: [],
15
+ hash: [],
16
+ issues: [],
17
+ invalid: [],
18
+ progress: []
19
+ };
20
+ /**
21
+ * @function on
22
+ * @description Add an event listener callback.
23
+ * @param event Event name.
24
+ * @param callback Event listener callback.
25
+ */
26
+ function on(event, callback) {
27
+ const callbacks = events[event];
28
+ if (callbacks) {
29
+ callbacks.push(callback);
30
+ }
31
+ }
32
+ /**
33
+ * @function off
34
+ * @description Remove an event listener callback.
35
+ * @param event Event name.
36
+ * @param callback Event listener callback.
37
+ */
38
+ function off(event, callback) {
39
+ const callbacks = events[event];
40
+ if (callbacks) {
41
+ if (callback) {
42
+ const index = callbacks.indexOf(callback);
43
+ if (index >= 0) {
44
+ callbacks.splice(index, 1);
45
+ }
46
+ } else {
47
+ events[event] = [];
48
+ }
49
+ }
50
+ }
51
+ function emit(event, message, options) {
52
+ const callbacks = events[event];
53
+ if (callbacks && callbacks.length > 0) {
54
+ for (const callback of callbacks) {
55
+ callback(message, options);
56
+ }
57
+ }
58
+ }
59
+
60
+ export { emit, off, on };