Skip to content

Commit e4d183e

Browse files
fix(types): make types better (#1786)
1 parent f23ed7c commit e4d183e

19 files changed

+420
-316
lines changed

package-lock.json

+264-198
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.js

+50-62
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ const noop = () => {};
4242
*/
4343

4444
/**
45-
* @typedef {ReturnType<Compiler["watch"]>} MultiWatching
45+
* @typedef {ReturnType<MultiCompiler["watch"]>} MultiWatching
4646
*/
4747

48+
// TODO fix me after the next webpack release
4849
/**
49-
* @typedef {Compiler["outputFileSystem"] & { createReadStream?: import("fs").createReadStream, statSync?: import("fs").statSync, lstat?: import("fs").lstat, readFileSync?: import("fs").readFileSync }} OutputFileSystem
50+
* @typedef {Object & { createReadStream?: import("fs").createReadStream, statSync?: import("fs").statSync, lstat?: import("fs").lstat, readFileSync?: import("fs").readFileSync }} OutputFileSystem
5051
*/
5152

5253
/** @typedef {ReturnType<Compiler["getInfrastructureLogger"]>} Logger */
@@ -82,15 +83,23 @@ const noop = () => {};
8283
* @property {Callback[]} callbacks
8384
* @property {Options<RequestInternal, ResponseInternal>} options
8485
* @property {Compiler | MultiCompiler} compiler
85-
* @property {Watching | MultiWatching} watching
86+
* @property {Watching | MultiWatching | undefined} watching
8687
* @property {Logger} logger
8788
* @property {OutputFileSystem} outputFileSystem
8889
*/
8990

9091
/**
9192
* @template {IncomingMessage} RequestInternal
9293
* @template {ServerResponse} ResponseInternal
93-
* @typedef {Record<string, string | number> | Array<{ key: string, value: number | string }> | ((req: RequestInternal, res: ResponseInternal, context: Context<RequestInternal, ResponseInternal>) => void | undefined | Record<string, string | number>) | undefined} Headers
94+
* @typedef {WithoutUndefined<Context<RequestInternal, ResponseInternal>, "watching">} FilledContext
95+
*/
96+
97+
/** @typedef {Record<string, string | number> | Array<{ key: string, value: number | string }>} NormalizedHeaders */
98+
99+
/**
100+
* @template {IncomingMessage} RequestInternal
101+
* @template {ServerResponse} ResponseInternal
102+
* @typedef {NormalizedHeaders | ((req: RequestInternal, res: ResponseInternal, context: Context<RequestInternal, ResponseInternal>) => void | undefined | NormalizedHeaders) | undefined} Headers
94103
*/
95104

96105
/**
@@ -161,6 +170,18 @@ const noop = () => {};
161170
* @typedef {Middleware<RequestInternal, ResponseInternal> & AdditionalMethods<RequestInternal, ResponseInternal>} API
162171
*/
163172

173+
/**
174+
* @template T
175+
* @template {keyof T} K
176+
* @typedef {Omit<T, K> & Partial<T>} WithOptional
177+
*/
178+
179+
/**
180+
* @template T
181+
* @template {keyof T} K
182+
* @typedef {T & { [P in K]: NonNullable<T[P]> }} WithoutUndefined
183+
*/
184+
164185
/**
165186
* @template {IncomingMessage} RequestInternal
166187
* @template {ServerResponse} ResponseInternal
@@ -186,7 +207,7 @@ function wdm(compiler, options = {}) {
186207
}
187208

188209
/**
189-
* @type {Context<RequestInternal, ResponseInternal>}
210+
* @type {WithOptional<Context<RequestInternal, ResponseInternal>, "watching" | "outputFileSystem">}
190211
*/
191212
const context = {
192213
state: false,
@@ -195,13 +216,7 @@ function wdm(compiler, options = {}) {
195216
callbacks: [],
196217
options,
197218
compiler,
198-
// @ts-ignore
199-
// eslint-disable-next-line no-undefined
200-
watching: undefined,
201219
logger: compiler.getInfrastructureLogger("webpack-dev-middleware"),
202-
// @ts-ignore
203-
// eslint-disable-next-line no-undefined
204-
outputFileSystem: undefined,
205220
};
206221

207222
setupHooks(context);
@@ -216,11 +231,6 @@ function wdm(compiler, options = {}) {
216231
if (/** @type {Compiler} */ (context.compiler).watching) {
217232
context.watching = /** @type {Compiler} */ (context.compiler).watching;
218233
} else {
219-
/**
220-
* @type {WatchOptions | WatchOptions[]}
221-
*/
222-
let watchOptions;
223-
224234
/**
225235
* @param {Error | null | undefined} error
226236
*/
@@ -237,69 +247,47 @@ function wdm(compiler, options = {}) {
237247
if (
238248
Array.isArray(/** @type {MultiCompiler} */ (context.compiler).compilers)
239249
) {
240-
watchOptions =
241-
/** @type {MultiCompiler} */
242-
(context.compiler).compilers.map(
243-
/**
244-
* @param {Compiler} childCompiler
245-
* @returns {WatchOptions}
246-
*/
247-
(childCompiler) => childCompiler.options.watchOptions || {},
248-
);
249-
250-
context.watching =
251-
/** @type {MultiWatching} */
252-
(
253-
context.compiler.watch(
254-
/** @type {WatchOptions}} */
255-
(watchOptions),
256-
errorHandler,
257-
)
258-
);
250+
const compiler = /** @type {MultiCompiler} */ (context.compiler);
251+
const watchOptions = compiler.compilers.map(
252+
(childCompiler) => childCompiler.options.watchOptions || {},
253+
);
254+
255+
context.watching = compiler.watch(watchOptions, errorHandler);
259256
} else {
260-
watchOptions =
261-
/** @type {Compiler} */ (context.compiler).options.watchOptions || {};
257+
const compiler = /** @type {Compiler} */ (context.compiler);
258+
const watchOptions = compiler.options.watchOptions || {};
262259

263-
context.watching = /** @type {Watching} */ (
264-
context.compiler.watch(watchOptions, errorHandler)
265-
);
260+
context.watching = compiler.watch(watchOptions, errorHandler);
266261
}
267262
}
268263

264+
const filledContext =
265+
/** @type {FilledContext<RequestInternal, ResponseInternal>} */
266+
(context);
267+
269268
const instance =
270269
/** @type {API<RequestInternal, ResponseInternal>} */
271-
(middleware(context));
270+
(middleware(filledContext));
272271

273272
// API
274-
/** @type {API<RequestInternal, ResponseInternal>} */
275-
(instance).getFilenameFromUrl = (url, extra) =>
276-
getFilenameFromUrl(context, url, extra);
273+
instance.getFilenameFromUrl = (url, extra) =>
274+
getFilenameFromUrl(filledContext, url, extra);
277275

278-
/** @type {API<RequestInternal, ResponseInternal>} */
279-
(instance).waitUntilValid = (callback = noop) => {
280-
ready(context, callback);
276+
instance.waitUntilValid = (callback = noop) => {
277+
ready(filledContext, callback);
281278
};
282279

283-
/** @type {API<RequestInternal, ResponseInternal>} */
284-
(instance).invalidate = (callback = noop) => {
285-
ready(context, callback);
280+
instance.invalidate = (callback = noop) => {
281+
ready(filledContext, callback);
286282

287-
/**
288-
* @type {NonNullable<Context<RequestInternal, ResponseInternal>["watching"]>}
289-
*/
290-
(context.watching).invalidate();
283+
filledContext.watching.invalidate();
291284
};
292285

293-
/** @type {API<RequestInternal, ResponseInternal>} */
294-
(instance).close = (callback = noop) => {
295-
/**
296-
* @type {NonNullable<Context<RequestInternal, ResponseInternal>["watching"]>}
297-
*/
298-
(context.watching).close(callback);
286+
instance.close = (callback = noop) => {
287+
filledContext.watching.close(callback);
299288
};
300289

301-
/** @type {API<RequestInternal, ResponseInternal>} */
302-
(instance).context = context;
290+
instance.context = filledContext;
303291

304292
return instance;
305293
}

src/middleware.js

+9-13
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const ready = require("./utils/ready");
1616
/** @typedef {import("./index.js").NextFunction} NextFunction */
1717
/** @typedef {import("./index.js").IncomingMessage} IncomingMessage */
1818
/** @typedef {import("./index.js").ServerResponse} ServerResponse */
19+
/** @typedef {import("./index.js").NormalizedHeaders} NormalizedHeaders */
1920

2021
/**
2122
* @param {string} type
@@ -32,7 +33,7 @@ const BYTES_RANGE_REGEXP = /^ *bytes/i;
3233
/**
3334
* @template {IncomingMessage} Request
3435
* @template {ServerResponse} Response
35-
* @param {import("./index.js").Context<Request, Response>} context
36+
* @param {import("./index.js").FilledContext<Request, Response>} context
3637
* @return {import("./index.js").Middleware<Request, Response>}
3738
*/
3839
function wrapper(context) {
@@ -101,8 +102,7 @@ function wrapper(context) {
101102
let { headers } = context.options;
102103

103104
if (typeof headers === "function") {
104-
// @ts-ignore
105-
headers = headers(req, res, context);
105+
headers = /** @type {NormalizedHeaders} */ (headers(req, res, context));
106106
}
107107

108108
/**
@@ -114,21 +114,15 @@ function wrapper(context) {
114114
if (!Array.isArray(headers)) {
115115
// eslint-disable-next-line guard-for-in
116116
for (const name in headers) {
117-
// @ts-ignore
118117
allHeaders.push({ key: name, value: headers[name] });
119118
}
120119

121120
headers = allHeaders;
122121
}
123122

124-
headers.forEach(
125-
/**
126-
* @param {{key: string, value: any}} header
127-
*/
128-
(header) => {
129-
setHeaderForResponse(res, header.key, header.value);
130-
},
131-
);
123+
headers.forEach((header) => {
124+
setHeaderForResponse(res, header.key, header.value);
125+
});
132126
}
133127

134128
if (!getHeaderFromResponse(res, "Content-Type")) {
@@ -152,7 +146,9 @@ function wrapper(context) {
152146
setHeaderForResponse(res, "Accept-Ranges", "bytes");
153147
}
154148

155-
const rangeHeader = getHeaderFromRequest(req, "range");
149+
const rangeHeader =
150+
/** @type {string} */
151+
(getHeaderFromRequest(req, "range"));
156152

157153
let len = /** @type {import("fs").Stats} */ (extra.stats).size;
158154
let offset = 0;

src/utils/compatibleAPI.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const escapeHtml = require("./escapeHtml");
44

55
/** @typedef {import("../index.js").IncomingMessage} IncomingMessage */
66
/** @typedef {import("../index.js").ServerResponse} ServerResponse */
7+
/** @typedef {import("fs").ReadStream} ReadStream */
78

89
/**
910
* @typedef {Object} ExpectedRequest
@@ -37,7 +38,7 @@ function getHeaderNames(res) {
3738
* @template {IncomingMessage} Request
3839
* @param {Request} req
3940
* @param {string} name
40-
* @returns {string | undefined}
41+
* @returns {string | string[] | undefined}
4142
*/
4243
function getHeaderFromRequest(req, name) {
4344
// Express API
@@ -48,7 +49,6 @@ function getHeaderFromRequest(req, name) {
4849
}
4950

5051
// Node.js API
51-
// @ts-ignore
5252
return req.headers[name];
5353
}
5454

@@ -256,6 +256,7 @@ async function send(req, res, filename, start, end, goNext, options) {
256256
const isFsSupportsStream =
257257
typeof options.outputFileSystem.createReadStream === "function";
258258

259+
/** @type {string | Buffer | ReadStream} */
259260
let bufferOrStream;
260261
let byteLength;
261262

src/utils/getFilenameFromUrl.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ const cacheStore = new WeakMap();
1616
* @param {(value: T) => T} callback
1717
* @returns {any}
1818
*/
19-
// @ts-ignore
2019
const mem = (fn, { cache = new Map() } = {}, callback) => {
2120
/**
2221
* @param {any} arguments_
@@ -79,7 +78,7 @@ function decode(input) {
7978
/**
8079
* @template {IncomingMessage} Request
8180
* @template {ServerResponse} Response
82-
* @param {import("../index.js").Context<Request, Response>} context
81+
* @param {import("../index.js").FilledContext<Request, Response>} context
8382
* @param {string} url
8483
* @param {Extra=} extra
8584
* @returns {string | undefined}

src/utils/getPaths.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/**
88
* @template {IncomingMessage} Request
99
* @template {ServerResponse} Response
10-
* @param {import("../index.js").Context<Request, Response>} context
10+
* @param {import("../index.js").FilledContext<Request, Response>} context
1111
*/
1212
function getPaths(context) {
1313
const { stats, options } = context;

src/utils/ready.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/**
55
* @template {IncomingMessage} Request
66
* @template {ServerResponse} Response
7-
* @param {import("../index.js").Context<Request, Response>} context
7+
* @param {import("../index.js").FilledContext<Request, Response>} context
88
* @param {(...args: any[]) => any} callback
99
* @param {Request} [req]
1010
* @returns {void}

src/utils/setupHooks.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
/** @typedef {import("webpack").MultiCompiler} MultiCompiler */
44
/** @typedef {import("webpack").Stats} Stats */
55
/** @typedef {import("webpack").MultiStats} MultiStats */
6-
76
/** @typedef {import("../index.js").IncomingMessage} IncomingMessage */
87
/** @typedef {import("../index.js").ServerResponse} ServerResponse */
8+
99
/** @typedef {Configuration["stats"]} StatsOptions */
1010
/** @typedef {{ children: Configuration["stats"][] }} MultiStatsOptions */
1111
/** @typedef {Exclude<Configuration["stats"], boolean | string | undefined>} StatsObjectOptions */
1212

1313
/**
1414
* @template {IncomingMessage} Request
1515
* @template {ServerResponse} Response
16-
* @param {import("../index.js").Context<Request, Response>} context
16+
* @param {import("../index.js").WithOptional<import("../index.js").Context<Request, Response>, "watching" | "outputFileSystem">} context
1717
*/
1818
function setupHooks(context) {
1919
function invalid() {
@@ -155,9 +155,14 @@ function setupHooks(context) {
155155
});
156156
}
157157

158-
context.compiler.hooks.watchRun.tap("webpack-dev-middleware", invalid);
159-
context.compiler.hooks.invalid.tap("webpack-dev-middleware", invalid);
160-
context.compiler.hooks.done.tap("webpack-dev-middleware", done);
158+
// eslint-disable-next-line prefer-destructuring
159+
const compiler =
160+
/** @type {import("../index.js").Context<Request, Response>} */
161+
(context).compiler;
162+
163+
compiler.hooks.watchRun.tap("webpack-dev-middleware", invalid);
164+
compiler.hooks.invalid.tap("webpack-dev-middleware", invalid);
165+
compiler.hooks.done.tap("webpack-dev-middleware", done);
161166
}
162167

163168
module.exports = setupHooks;

src/utils/setupOutputFileSystem.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const memfs = require("memfs");
77
/**
88
* @template {IncomingMessage} Request
99
* @template {ServerResponse} Response
10-
* @param {import("../index.js").Context<Request, Response>} context
10+
* @param {import("../index.js").WithOptional<import("../index.js").Context<Request, Response>, "watching" | "outputFileSystem">} context
1111
*/
1212
function setupOutputFileSystem(context) {
1313
let outputFileSystem;
@@ -48,6 +48,7 @@ function setupOutputFileSystem(context) {
4848
(context.compiler).compilers || [context.compiler];
4949

5050
for (const compiler of compilers) {
51+
// @ts-ignore
5152
compiler.outputFileSystem = outputFileSystem;
5253
}
5354

src/utils/setupWriteToDisk.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const path = require("path");
1010
/**
1111
* @template {IncomingMessage} Request
1212
* @template {ServerResponse} Response
13-
* @param {import("../index.js").Context<Request, Response>} context
13+
* @param {import("../index.js").WithOptional<import("../index.js").Context<Request, Response>, "watching" | "outputFileSystem">} context
1414
*/
1515
function setupWriteToDisk(context) {
1616
/**

0 commit comments

Comments
 (0)