webpack-dev-service 0.9.0 → 0.10.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 (57) hide show
  1. package/{server/cjs → cjs/server}/index.cjs +1 -1
  2. package/package.json +13 -28
  3. package/client/cjs/client.cjs +0 -128
  4. package/client/cjs/events.cjs +0 -64
  5. package/client/cjs/hot.cjs +0 -111
  6. package/client/cjs/index.cjs +0 -15
  7. package/client/cjs/main.cjs +0 -59
  8. package/client/cjs/ui/overlay.cjs +0 -233
  9. package/client/cjs/ui/progress.cjs +0 -92
  10. package/client/cjs/ui/utils.cjs +0 -136
  11. package/client/esm/client.js +0 -126
  12. package/client/esm/events.js +0 -60
  13. package/client/esm/hot.js +0 -106
  14. package/client/esm/index.js +0 -10
  15. package/client/esm/main.js +0 -57
  16. package/client/esm/ui/overlay.js +0 -231
  17. package/client/esm/ui/progress.js +0 -90
  18. package/client/esm/ui/utils.js +0 -123
  19. package/server/cjs/compose.cjs +0 -56
  20. package/server/cjs/dev/Service.cjs +0 -269
  21. package/server/cjs/dev/index.cjs +0 -60
  22. package/server/cjs/dev/middleware.cjs +0 -96
  23. package/server/cjs/dev/utils/fs.cjs +0 -29
  24. package/server/cjs/dev/utils/hash.cjs +0 -46
  25. package/server/cjs/dev/utils/http.cjs +0 -227
  26. package/server/cjs/dev/utils/path.cjs +0 -46
  27. package/server/cjs/dev/utils/paths.cjs +0 -59
  28. package/server/cjs/dev/utils/ready.cjs +0 -23
  29. package/server/cjs/dev/utils/setupHooks.cjs +0 -106
  30. package/server/cjs/dev/utils/setupOutputFileSystem.cjs +0 -31
  31. package/server/cjs/dev/utils/setupWatching.cjs +0 -43
  32. package/server/cjs/dev/utils/setupWriteToDisk.cjs +0 -54
  33. package/server/cjs/hot/Socket.cjs +0 -174
  34. package/server/cjs/hot/index.cjs +0 -34
  35. package/server/cjs/hot/utils.cjs +0 -100
  36. package/server/cjs/schema.cjs +0 -127
  37. package/server/cjs/utils.cjs +0 -45
  38. package/server/esm/compose.js +0 -54
  39. package/server/esm/dev/Service.js +0 -260
  40. package/server/esm/dev/index.js +0 -58
  41. package/server/esm/dev/middleware.js +0 -94
  42. package/server/esm/dev/utils/fs.js +0 -27
  43. package/server/esm/dev/utils/hash.js +0 -44
  44. package/server/esm/dev/utils/http.js +0 -216
  45. package/server/esm/dev/utils/path.js +0 -42
  46. package/server/esm/dev/utils/paths.js +0 -57
  47. package/server/esm/dev/utils/ready.js +0 -21
  48. package/server/esm/dev/utils/setupHooks.js +0 -98
  49. package/server/esm/dev/utils/setupOutputFileSystem.js +0 -29
  50. package/server/esm/dev/utils/setupWatching.js +0 -41
  51. package/server/esm/dev/utils/setupWriteToDisk.js +0 -52
  52. package/server/esm/hot/Socket.js +0 -165
  53. package/server/esm/hot/index.js +0 -32
  54. package/server/esm/hot/utils.js +0 -93
  55. package/server/esm/index.js +0 -37
  56. package/server/esm/schema.js +0 -125
  57. package/server/esm/utils.js +0 -37
@@ -1,260 +0,0 @@
1
- /**
2
- * @package webpack-dev-service
3
- * @license MIT
4
- * @version 0.9.0
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 createEtag from 'etag';
11
- import destroy from 'destroy';
12
- import { PassThrough } from 'stream';
13
- import { isFunction } from '../utils.js';
14
- import { stat } from './utils/fs.js';
15
- import { resolve, extname, join } from 'path';
16
- import { unixify, isOutRoot, hasTrailingSlash } from './utils/path.js';
17
- import { isConditionalGET, isPreconditionFailure, parseRanges } from './utils/http.js';
18
-
19
- /**
20
- * @module Service
21
- */
22
- /**
23
- * @class Service
24
- */
25
- class Service {
26
- /**
27
- * @constructor
28
- * @description Create file service.
29
- * @param root File service root.
30
- * @param options File service options.
31
- */
32
- constructor(root, options) {
33
- this.options = options;
34
- this.root = unixify(resolve(root));
35
- }
36
- /**
37
- * @private
38
- * @method isIgnore
39
- * @description Check if path is ignore.
40
- * @param path File path.
41
- */
42
- isIgnore(path) {
43
- const { ignore } = this.options;
44
- return (isFunction(ignore) ? ignore(path) : false) === true;
45
- }
46
- /**
47
- * @private
48
- * @method setupHeaders
49
- * @description Setup headers
50
- * @param context Koa context
51
- * @param path File path
52
- * @param stats File stats
53
- */
54
- setupHeaders(context, path, stats) {
55
- const { options } = this;
56
- const { headers, etag } = options;
57
- // Set status.
58
- context.status = 200;
59
- // Set Content-Type.
60
- context.type = extname(path);
61
- // Accept-Ranges.
62
- if (options.acceptRanges === false) {
63
- // Set Accept-Ranges to none tell client not support.
64
- context.set('Accept-Ranges', 'none');
65
- } else {
66
- // Set Accept-Ranges.
67
- context.set('Accept-Ranges', 'bytes');
68
- }
69
- // ETag.
70
- if (etag === false) {
71
- // Remove ETag.
72
- context.remove('ETag');
73
- } else {
74
- // Set ETag.
75
- context.set('ETag', createEtag(stats));
76
- }
77
- // Last-Modified.
78
- if (options.lastModified === false) {
79
- // Remove Last-Modified.
80
- context.remove('Last-Modified');
81
- } else {
82
- // Set mtime utc string.
83
- context.set('Last-Modified', stats.mtime.toUTCString());
84
- }
85
- // Set headers.
86
- if (headers) {
87
- if (isFunction(headers)) {
88
- const fields = headers(path, stats);
89
- if (fields) {
90
- context.set(fields);
91
- }
92
- } else {
93
- context.set(headers);
94
- }
95
- }
96
- }
97
- /**
98
- * @private
99
- * @method write
100
- * @description Write file to stream.
101
- * @param stream Destination stream.
102
- * @param path The file path to read.
103
- * @param range The range to read.
104
- * @param end Is destory destination stream after read complete.
105
- */
106
- write(stream, path, range, end) {
107
- const { fs } = this.options;
108
- return new Promise(resolve => {
109
- // Range prefix and suffix.
110
- const { prefix, suffix } = range;
111
- // Create file stream reader.
112
- const reader = fs.createReadStream(path, range);
113
- // File read stream open.
114
- if (prefix) {
115
- reader.once('open', () => {
116
- // Write prefix boundary.
117
- stream.write(prefix);
118
- });
119
- }
120
- // File read stream end.
121
- if (suffix) {
122
- reader.once('end', () => {
123
- // Push suffix boundary.
124
- stream.write(suffix);
125
- });
126
- }
127
- // File read stream error.
128
- reader.once('error', () => {
129
- // End stream.
130
- stream.end();
131
- // Unpipe.
132
- reader.unpipe();
133
- // Destroy.
134
- destroy(reader);
135
- // Resolve.
136
- resolve(false);
137
- });
138
- // File read stream close.
139
- reader.once('close', () => {
140
- // Unpipe.
141
- reader.unpipe();
142
- // Destroy.
143
- destroy(reader);
144
- // Resolve.
145
- resolve(true);
146
- });
147
- // Write data to buffer.
148
- reader.pipe(stream, { end });
149
- });
150
- }
151
- /**
152
- * @private
153
- * @method send
154
- * @description Send file.
155
- * @param context Koa context.
156
- * @param path File path.
157
- * @param ranges Read ranges.
158
- */
159
- async send(context, path, ranges) {
160
- // Set stream body, highWaterMark 64kb.
161
- const stream = new PassThrough({
162
- highWaterMark: 65536
163
- });
164
- // Set response body.
165
- context.body = stream;
166
- // Ranges length.
167
- let { length } = ranges;
168
- // Write ranges to stream.
169
- for (const range of ranges) {
170
- // Write range.
171
- const passed = await this.write(stream, path, range, --length === 0);
172
- // If not passed, break.
173
- if (!passed) {
174
- break;
175
- }
176
- }
177
- }
178
- /**
179
- * @public
180
- * @method response
181
- * @description Response to koa context.
182
- * @param context Koa context.
183
- */
184
- async response(context) {
185
- const { root } = this;
186
- // Only support GET and HEAD (405).
187
- if (context.method !== 'GET' && context.method !== 'HEAD') {
188
- return false;
189
- }
190
- // Get path of file.
191
- const path = unixify(join(root, context.path));
192
- // Malicious path (403).
193
- if (isOutRoot(path, root)) {
194
- return false;
195
- }
196
- // Is ignore path or file (403).
197
- if (this.isIgnore(path)) {
198
- return false;
199
- }
200
- // File stats.
201
- const stats = await stat(this.options.fs, path);
202
- // Check file stats.
203
- if (
204
- // File not exist (404 | 500).
205
- stats == null ||
206
- // Is directory (403).
207
- stats.isDirectory() ||
208
- // Not a directory but has trailing slash (404).
209
- hasTrailingSlash(path)
210
- ) {
211
- return false;
212
- }
213
- // Setup headers.
214
- this.setupHeaders(context, path, stats);
215
- // Conditional get support.
216
- if (isConditionalGET(context)) {
217
- // Request precondition failure.
218
- if (isPreconditionFailure(context)) {
219
- return context.throw(412);
220
- }
221
- // Request fresh (304).
222
- if (context.fresh) {
223
- // Set status.
224
- context.status = 304;
225
- // Set body null.
226
- context.body = null;
227
- // File found.
228
- return true;
229
- }
230
- }
231
- // Head request.
232
- if (context.method === 'HEAD') {
233
- // Set Content-Length.
234
- context.length = stats.size;
235
- // Set body null
236
- context.body = null;
237
- // File found.
238
- return true;
239
- }
240
- // Parsed ranges.
241
- const ranges = parseRanges(context, stats);
242
- // 416
243
- if (ranges === -1) {
244
- // Set Content-Range.
245
- context.set('Content-Range', `bytes */${stats.size}`);
246
- // Unsatisfiable 416.
247
- return context.throw(416);
248
- }
249
- // 400.
250
- if (ranges === -2) {
251
- return context.throw(400);
252
- }
253
- // Send file.
254
- this.send(context, path, ranges);
255
- // File found.
256
- return true;
257
- }
258
- }
259
-
260
- export { Service };
@@ -1,58 +0,0 @@
1
- /**
2
- * @package webpack-dev-service
3
- * @license MIT
4
- * @version 0.9.0
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 { ready } from './utils/ready.js';
11
- import { middleware } from './middleware.js';
12
- import { PLUGIN_NAME } from '../utils.js';
13
- import { setupHooks } from './utils/setupHooks.js';
14
- import { setupWatching } from './utils/setupWatching.js';
15
- import { setupWriteToDisk } from './utils/setupWriteToDisk.js';
16
- import { setupOutputFileSystem } from './utils/setupOutputFileSystem.js';
17
-
18
- /**
19
- * @module index
20
- */
21
- function setup(compiler, options) {
22
- const context = {
23
- options,
24
- compiler,
25
- stats: null,
26
- callbacks: [],
27
- logger: compiler.getInfrastructureLogger(PLUGIN_NAME)
28
- };
29
- setupHooks(context);
30
- if (options.writeToDisk) {
31
- setupWriteToDisk(context);
32
- }
33
- setupOutputFileSystem(context);
34
- setupWatching(context);
35
- return context;
36
- }
37
- function dev(compiler, options) {
38
- const context = setup(compiler, options);
39
- return Object.assign(middleware(context), {
40
- get state() {
41
- return !!context.stats;
42
- },
43
- get logger() {
44
- return context.logger;
45
- },
46
- ready(callback) {
47
- ready(context, callback);
48
- },
49
- close(callback) {
50
- context.watching.close(callback);
51
- },
52
- invalidate(callback) {
53
- context.watching.invalidate(callback);
54
- }
55
- });
56
- }
57
-
58
- export { dev };
@@ -1,94 +0,0 @@
1
- /**
2
- * @package webpack-dev-service
3
- * @license MIT
4
- * @version 0.9.0
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 { Service } from './Service.js';
11
- import { ready } from './utils/ready.js';
12
- import { decodeURI } from './utils/http.js';
13
- import { getPaths } from './utils/paths.js';
14
-
15
- /**
16
- * @module middleware
17
- */
18
- function getFileServices(context, stats) {
19
- const cached = context.services;
20
- // Cache hit.
21
- if (cached) {
22
- return cached;
23
- }
24
- const paths = getPaths(stats);
25
- const { fs, options } = context;
26
- const services = [];
27
- const { etag, ignore, headers, acceptRanges, lastModified } = options;
28
- // Get the file services.
29
- for (const [outputPath, publicPath] of paths) {
30
- services.push([
31
- publicPath,
32
- new Service(outputPath, {
33
- fs,
34
- etag,
35
- ignore,
36
- headers,
37
- acceptRanges,
38
- lastModified
39
- })
40
- ]);
41
- }
42
- // Cache services.
43
- context.services = services;
44
- // Return services.
45
- return services;
46
- }
47
- function getFileServicesAsync(context, path) {
48
- return new Promise(resolve => {
49
- const { stats } = context;
50
- // If stats exists, resolve immediately.
51
- if (stats) {
52
- resolve(getFileServices(context, stats));
53
- } else {
54
- // Log waiting info.
55
- context.logger.info(`wait until bundle finished: ${path}`);
56
- // Otherwise, wait until bundle finished.
57
- ready(context, stats => {
58
- resolve(getFileServices(context, stats));
59
- });
60
- }
61
- });
62
- }
63
- function middleware(context) {
64
- // Middleware.
65
- return async (ctx, next) => {
66
- const path = decodeURI(ctx.path);
67
- // Path -1 or null byte(s).
68
- if (path === -1 || path.includes('\0')) {
69
- return ctx.throw(400);
70
- }
71
- // Is path respond.
72
- let respond = false;
73
- // Get the file services.
74
- const services = await getFileServicesAsync(context, path);
75
- // Try to respond.
76
- for (const [publicPath, service] of services) {
77
- if (path.startsWith(publicPath)) {
78
- ctx.path = path.slice(publicPath.length);
79
- respond = await service.response(ctx);
80
- if (respond) {
81
- return;
82
- } else {
83
- ctx.path = path;
84
- }
85
- }
86
- }
87
- // Not respond.
88
- if (!respond) {
89
- await next();
90
- }
91
- };
92
- }
93
-
94
- export { middleware };
@@ -1,27 +0,0 @@
1
- /**
2
- * @package webpack-dev-service
3
- * @license MIT
4
- * @version 0.9.0
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 fs
12
- */
13
- /**
14
- * @function stat
15
- * @description Get file stats.
16
- * @param fs The file system to used.
17
- * @param path The file path.
18
- */
19
- function stat(fs, path) {
20
- return new Promise(resolve => {
21
- fs.stat(path, (error, stats) => {
22
- resolve(error ? null : stats);
23
- });
24
- });
25
- }
26
-
27
- export { stat };
@@ -1,44 +0,0 @@
1
- /**
2
- * @package webpack-dev-service
3
- * @license MIT
4
- * @version 0.9.0
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 { getRandomValues } from 'crypto';
11
-
12
- /**
13
- * @module hash
14
- */
15
- // prettier-ignore
16
- const CHARS = [
17
- // 0-9
18
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
19
- // A-M
20
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
21
- // N-Z
22
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
23
- // a-m
24
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
25
- // n-z
26
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
27
- ];
28
- /**
29
- * @function generate
30
- * @description Generate a hash.
31
- * @param length The length of hash.
32
- */
33
- function generate(length = 32) {
34
- let hash = '';
35
- const randomValues = getRandomValues(new Uint8Array(length));
36
- // Create hash.
37
- for (const value of randomValues) {
38
- hash += CHARS[value % 62];
39
- }
40
- // Return hash.
41
- return hash;
42
- }
43
-
44
- export { generate };
@@ -1,216 +0,0 @@
1
- /**
2
- * @package webpack-dev-service
3
- * @license MIT
4
- * @version 0.9.0
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 { generate } from './hash.js';
11
- import parseRange from 'range-parser';
12
-
13
- /**
14
- * @module http
15
- */
16
- /**
17
- * @function isETag
18
- * @description Check if etag is valid.
19
- * @param value The value to check.
20
- */
21
- function isETag(value) {
22
- return /^(?:W\/)?"[\s\S]+"$/.test(value);
23
- }
24
- /**
25
- * @function parseTokens
26
- * @description Parse HTTP tokens.
27
- * @param value The tokens value string.
28
- */
29
- function parseTokens(value) {
30
- let end = 0;
31
- let start = 0;
32
- let tokens = [];
33
- // Gather tokens.
34
- for (let i = 0, length = value.length; i < length; i++) {
35
- switch (value.charCodeAt(i)) {
36
- case 0x20:
37
- // ' '.
38
- if (start === end) {
39
- start = end = i + 1;
40
- }
41
- break;
42
- case 0x2c:
43
- // ','.
44
- tokens.push(value.substring(start, end));
45
- start = end = i + 1;
46
- break;
47
- default:
48
- end = i + 1;
49
- break;
50
- }
51
- }
52
- // Final token.
53
- tokens.push(value.substring(start, end));
54
- return tokens;
55
- }
56
- /**
57
- * @function isRangeFresh
58
- * @description Check if request range fresh.
59
- * @param context Koa context.
60
- */
61
- function isRangeFresh(context) {
62
- const { request, response } = context;
63
- const ifRange = request.get('If-Range');
64
- // No If-Range.
65
- if (!ifRange) {
66
- return true;
67
- }
68
- // If-Range as etag.
69
- if (isETag(ifRange)) {
70
- const etag = response.get('ETag');
71
- return !!(etag && isETagFresh(ifRange, etag));
72
- }
73
- // If-Range as modified date.
74
- const lastModified = response.get('Last-Modified');
75
- return Date.parse(lastModified) <= Date.parse(ifRange);
76
- }
77
- /**
78
- * @function isETagFresh
79
- * @description Check if etag is fresh.
80
- * @param match The match value.
81
- * @param etag The etag value.
82
- */
83
- function isETagFresh(match, etag) {
84
- return parseTokens(match).some(match => {
85
- return match === etag || match === 'W/' + etag || 'W/' + match === etag;
86
- });
87
- }
88
- /**
89
- * @function decodeURI
90
- * @description Decode URI component.
91
- * @param URI The URI to decode.
92
- */
93
- function decodeURI(URI) {
94
- try {
95
- return decodeURIComponent(URI);
96
- } catch (_a) {
97
- return -1;
98
- }
99
- }
100
- /**
101
- * @function isConditionalGET
102
- * @description Check if request is conditional GET.
103
- * @param context Koa context.
104
- */
105
- function isConditionalGET(context) {
106
- const { request } = context;
107
- return !!(
108
- request.get('If-Match') ||
109
- request.get('If-None-Match') ||
110
- request.get('If-Modified-Since') ||
111
- request.get('If-Unmodified-Since')
112
- );
113
- }
114
- /**
115
- * @function isPreconditionFailure
116
- * @description Check if request precondition failure.
117
- * @param context Koa context.
118
- */
119
- function isPreconditionFailure({ request, response }) {
120
- // If-Match.
121
- const match = request.get('If-Match');
122
- // Check if request match.
123
- if (match) {
124
- // Etag.
125
- const etag = response.get('ETag');
126
- return !etag || match === '*' || !isETagFresh(match, etag);
127
- }
128
- // If-Unmodified-Since.
129
- const unmodifiedSince = Date.parse(request.get('If-Unmodified-Since'));
130
- // Check if request unmodified.
131
- if (!Number.isNaN(unmodifiedSince)) {
132
- // Last-Modified.
133
- const lastModified = Date.parse(response.get('Last-Modified'));
134
- return Number.isNaN(lastModified) || lastModified > unmodifiedSince;
135
- }
136
- // Check precondition passed.
137
- return false;
138
- }
139
- /**
140
- * @function parseRanges
141
- * @description Parse ranges.
142
- * @param context Koa context.
143
- * @param stats File stats.
144
- */
145
- function parseRanges(context, stats) {
146
- const { size } = stats;
147
- // Range support.
148
- if (/^bytes$/i.test(context.response.get('Accept-Ranges'))) {
149
- const range = context.request.get('Range');
150
- // Range fresh.
151
- if (range && isRangeFresh(context)) {
152
- // Parse range -1 -2 or [].
153
- const parsed = parseRange(size, range, { combine: true });
154
- // -1 signals an unsatisfiable range.
155
- // -2 signals a malformed header string.
156
- if (parsed === -1 || parsed === -2) {
157
- return parsed;
158
- }
159
- // Ranges ok, support multiple ranges.
160
- if (parsed.type === 'bytes') {
161
- // Set 206 status.
162
- context.status = 206;
163
- const { length } = parsed;
164
- // Multiple ranges.
165
- if (length > 1) {
166
- // Content-Length.
167
- let contentLength = 0;
168
- // Ranges.
169
- const ranges = [];
170
- // Range boundary.
171
- const boundary = `<${generate()}>`;
172
- // Range suffix.
173
- const suffix = `\r\n--${boundary}--\r\n`;
174
- // Multipart Content-Type.
175
- const contentType = `Content-Type: ${context.type}`;
176
- // Override Content-Type.
177
- context.type = `multipart/byteranges; boundary=${boundary}`;
178
- // Map ranges.
179
- for (let index = 0; index < length; index++) {
180
- const { start, end } = parsed[index];
181
- // The first prefix boundary no \r\n.
182
- const head = index > 0 ? '\r\n' : '';
183
- const contentRange = `Content-Range: bytes ${start}-${end}/${size}`;
184
- const prefix = `${head}--${boundary}\r\n${contentType}\r\n${contentRange}\r\n\r\n`;
185
- // Compute Content-Length
186
- contentLength += end - start + 1 + Buffer.byteLength(prefix);
187
- // Cache range.
188
- ranges.push({ start, end, prefix });
189
- }
190
- // The last add suffix boundary.
191
- ranges[length - 1].suffix = suffix;
192
- // Compute Content-Length.
193
- contentLength += Buffer.byteLength(suffix);
194
- // Set Content-Length.
195
- context.length = contentLength;
196
- // Return ranges.
197
- return ranges;
198
- } else {
199
- const [{ start, end }] = parsed;
200
- // Set Content-Length.
201
- context.length = end - start + 1;
202
- // Set Content-Range.
203
- context.set('Content-Range', `bytes ${start}-${end}/${size}`);
204
- // Return ranges.
205
- return parsed;
206
- }
207
- }
208
- }
209
- }
210
- // Set Content-Length.
211
- context.length = size;
212
- // Return ranges.
213
- return [{ start: 0, end: Math.max(size - 1) }];
214
- }
215
-
216
- export { decodeURI, isConditionalGET, isPreconditionFailure, parseRanges };