From 458c17c372a2a1a5a33f8923998dba88d2644135 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:04:30 +0300 Subject: [PATCH] feat: koa support (#1792) --- README.md | 23 +- package-lock.json | 224 ++++++++++++++++ package.json | 1 + src/index.js | 78 +++++- src/utils/compatibleAPI.js | 49 ++-- test/middleware.test.js | 475 +++++++++++++++------------------ types/index.d.ts | 29 +- types/utils/compatibleAPI.d.ts | 2 + 8 files changed, 585 insertions(+), 296 deletions(-) diff --git a/README.md b/README.md index 5a005d1de..720c6f4b2 100644 --- a/README.md +++ b/README.md @@ -579,6 +579,25 @@ app.use(devMiddleware(compiler, devMiddlewareOptions)); app.listen(3000, () => console.log("Example app listening on port 3000!")); ``` +### Koa + +```js +const Koa = require("koa"); +const webpack = require("webpack"); +const webpackConfig = require("./test/fixtures/webpack.simple.config"); +const middleware = require("./dist"); + +const compiler = webpack(webpackConfig); +const devMiddlewareOptions = { + /** Your webpack-dev-middleware-options */ +}; +const app = new Koa(); + +app.use(middleware.koaWrapper(compiler, devMiddlewareOptions)); + +app.listen(3000); +``` + ### Hapi ```js @@ -613,10 +632,6 @@ process.on("unhandledRejection", (err) => { }); ``` -### Koa - -Soon... - ### Fastify Fastify interop will require the use of `fastify-express` instead of `middie` for providing middleware support. As the authors of `fastify-express` recommend, this should only be used as a stopgap while full Fastify support is worked on. diff --git a/package-lock.json b/package-lock.json index 21597b884..64a6c2479 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,6 +46,7 @@ "husky": "^9.0.10", "jest": "^29.3.1", "joi": "^17.12.2", + "koa": "^2.15.2", "lint-staged": "^15.2.0", "npm-run-all": "^4.1.5", "prettier": "^3.2.4", @@ -5551,6 +5552,19 @@ "node": ">= 0.8" } }, + "node_modules/cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "dev": true, + "dependencies": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -7277,6 +7291,19 @@ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, + "node_modules/cookies": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz", + "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", + "dev": true, + "dependencies": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/core-js-compat": { "version": "3.36.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", @@ -7893,6 +7920,12 @@ } } }, + "node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", + "dev": true + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -8443,6 +8476,12 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -10802,6 +10841,53 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/http-assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", + "dev": true, + "dependencies": { + "deep-equal": "~1.0.1", + "http-errors": "~1.8.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-assert/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -11141,6 +11227,21 @@ "node": ">=6" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -13252,6 +13353,18 @@ "node": "*" } }, + "node_modules/keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "dev": true, + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -13279,6 +13392,93 @@ "node": ">=6" } }, + "node_modules/koa": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.15.2.tgz", + "integrity": "sha512-MXTeZH3M6AJ8ukW2QZ8wqO3Dcdfh2WRRmjCBkEP+NhKNCiqlO5RDqHmSnsyNrbRJrdjyvIGSJho4vQiWgQJSVA==", + "dev": true, + "dependencies": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.9.0", + "debug": "^4.3.2", + "delegates": "^1.0.0", + "depd": "^2.0.0", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^2.0.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + }, + "engines": { + "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" + } + }, + "node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "dev": true + }, + "node_modules/koa-convert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz", + "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", + "dev": true, + "dependencies": { + "co": "^4.6.0", + "koa-compose": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/koa/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -14340,6 +14540,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==", + "dev": true + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -16482,6 +16688,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "dev": true, + "engines": { + "node": ">=0.6.x" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -17221,6 +17436,15 @@ "node": ">=8" } }, + "node_modules/ylru": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.3.2.tgz", + "integrity": "sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 46fdf9ecc..2c21cff8d 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "husky": "^9.0.10", "jest": "^29.3.1", "joi": "^17.12.2", + "koa": "^2.15.2", "lint-staged": "^15.2.0", "npm-run-all": "^4.1.5", "prettier": "^3.2.4", diff --git a/src/index.js b/src/index.js index ba67ff858..305eaf3a4 100644 --- a/src/index.js +++ b/src/index.js @@ -183,8 +183,8 @@ const noop = () => {}; */ /** - * @template {IncomingMessage} RequestInternal - * @template {ServerResponse} ResponseInternal + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] * @param {Compiler | MultiCompiler} compiler * @param {Options} [options] * @returns {API} @@ -314,7 +314,7 @@ function wdm(compiler, options = {}) { * @template {HapiOptions} HapiOptionsInternal * @returns {HapiPlugin} */ -function hapiPlugin() { +function hapiWrapper() { return { pkg: { name: "webpack-dev-middleware", @@ -351,6 +351,76 @@ function hapiPlugin() { }; } -wdm.hapiPlugin = hapiPlugin; +wdm.hapiWrapper = hapiWrapper; + +/** + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] + * @param {Compiler | MultiCompiler} compiler + * @param {Options} [options] + * @returns {(ctx: any, next: Function) => Promise | void} + */ +function koaWrapper(compiler, options) { + const devMiddleware = wdm(compiler, options); + + /** + * @param {any} ctx + * @param {Function} next + * @returns {Promise} + */ + const wrapper = async function webpackDevMiddleware(ctx, next) { + return new Promise((resolve, reject) => { + const { req } = ctx; + const { res } = ctx; + + res.locals = ctx.state; + /** + * @param {number} status status code + */ + res.status = (status) => { + // eslint-disable-next-line no-param-reassign + ctx.status = status; + }; + /** + * @param {import("fs").ReadStream} stream readable stream + */ + res.pipeInto = (stream) => { + // eslint-disable-next-line no-param-reassign + ctx.body = stream; + resolve(); + }; + /** + * @param {string | Buffer} content content + */ + res.send = (content) => { + // eslint-disable-next-line no-param-reassign + ctx.body = content; + resolve(); + }; + + devMiddleware(req, res, (err) => { + if (err) { + reject(err); + return; + } + + resolve(next()); + }).catch((err) => { + // eslint-disable-next-line no-param-reassign + ctx.status = err.statusCode || err.status || 500; + // eslint-disable-next-line no-param-reassign + ctx.body = { + message: err.message, + }; + }); + }); + }; + + wrapper.devMiddleware = devMiddleware; + + return wrapper; +} + +wdm.koaWrapper = koaWrapper; module.exports = wdm; diff --git a/src/utils/compatibleAPI.js b/src/utils/compatibleAPI.js index 933572ec3..e6ee6c740 100644 --- a/src/utils/compatibleAPI.js +++ b/src/utils/compatibleAPI.js @@ -17,6 +17,7 @@ const escapeHtml = require("./escapeHtml"); * @property {(name: string, value: number | string | string[]) => void} set * @property {(status: number) => void} status * @property {(data: any) => void} send + * @property {(data: any) => void} [pipeInto] */ /** @@ -25,12 +26,14 @@ const escapeHtml = require("./escapeHtml"); * @returns {string[]} */ function getHeaderNames(res) { + // Pseudo API, TODO? if (typeof res.getHeaderNames !== "function") { // @ts-ignore // eslint-disable-next-line no-underscore-dangle return Object.keys(res._headers || {}); } + // Node.js API return res.getHeaderNames(); } @@ -128,6 +131,7 @@ function clearHeadersForResponse(res) { * @param {number} code */ function setStatusCode(res, code) { + // Pseudo API if ( typeof (/** @type {Response & ExpectedResponse} */ (res).status) === "function" @@ -138,6 +142,7 @@ function setStatusCode(res, code) { return; } + // Node.js API // eslint-disable-next-line no-param-reassign res.statusCode = code; } @@ -296,16 +301,6 @@ async function send(req, res, filename, start, end, goNext, options) { typeof (/** @type {import("fs").ReadStream} */ (bufferOrStream).pipe) === "function" ) { - setHeaderForResponse(res, "Content-Length", byteLength); - - if (req.method === "HEAD") { - res.end(); - return; - } - - /** @type {import("fs").ReadStream} */ - (bufferOrStream).pipe(res); - // Cleanup const cleanup = () => { destroyStream( @@ -314,10 +309,7 @@ async function send(req, res, filename, start, end, goNext, options) { ); }; - // Response finished, cleanup - onFinishedStream(res, cleanup); - - // error handling + // Error handling /** @type {import("fs").ReadStream} */ (bufferOrStream).on("error", (error) => { // clean up stream early @@ -336,10 +328,35 @@ async function send(req, res, filename, start, end, goNext, options) { } }); + setHeaderForResponse(res, "Content-Length", byteLength); + + // Pseudo API and Koa API + if ( + typeof (/** @type {Response & ExpectedResponse} */ (res).pipeInto) === + "function" + ) { + // Writable stream into Readable stream + /** @type {Response & ExpectedResponse} */ + (res).pipeInto(bufferOrStream); + } + // Node.js API and Express API and Hapi API + else { + /** @type {import("fs").ReadStream} */ + (bufferOrStream).pipe(res); + } + + if (req.method === "HEAD") { + res.end(); + return; + } + + // Response finished, cleanup + onFinishedStream(res, cleanup); + return; } - // Express API + // Pseudo API and Express API and Koa API if ( typeof (/** @type {Response & ExpectedResponse} */ (res).send) === "function" @@ -349,7 +366,7 @@ async function send(req, res, filename, start, end, goNext, options) { return; } - // Only Node.js API used + // Only Node.js API and Hapi API res.setHeader("Content-Length", byteLength); if (req.method === "HEAD") { diff --git a/test/middleware.test.js b/test/middleware.test.js index d920bd0cd..b96bc3a50 100644 --- a/test/middleware.test.js +++ b/test/middleware.test.js @@ -3,6 +3,7 @@ import path from "path"; import connect from "connect"; import express from "express"; +import koa from "koa"; import Hapi from "@hapi/hapi"; import request from "supertest"; import memfs, { createFsFromVolume, Volume } from "memfs"; @@ -45,7 +46,7 @@ async function frameworkFactory( case "hapi": { const server = framework.server(); const hapiPlugin = { - plugin: middleware.hapiPlugin(), + plugin: middleware.hapiWrapper(), options: { compiler, ...devMiddlewareOptions, @@ -71,7 +72,34 @@ async function frameworkFactory( await server.start(); - return [server, server.listener, server.webpackDevMiddleware]; + const req = request(server.listener); + + return [server, req, server.webpackDevMiddleware]; + } + case "koa": { + // eslint-disable-next-line new-cap + const app = new framework(); + const koaMiddleware = middleware.koaWrapper( + compiler, + devMiddlewareOptions, + ); + const middlewares = + typeof options.setupMiddlewares === "function" + ? options.setupMiddlewares([koaMiddleware]) + : [koaMiddleware]; + + for (const item of middlewares) { + if (item.route) { + app.use(item.route, item.fn); + } else { + app.use(item); + } + } + + const server = await startServer(app); + const req = request(server); + + return [server, req, koaMiddleware.devMiddleware]; } default: { const app = framework(); @@ -90,8 +118,9 @@ async function frameworkFactory( } const server = await startServer(app); + const req = request(app); - return [server, app, instance]; + return [server, req, instance]; } } } @@ -144,6 +173,8 @@ async function close(server, instance) { function get404ContentTypeHeader(name) { switch (name) { + case "koa": + return "text/plain; charset=utf-8"; case "hapi": return "application/json; charset=utf-8"; default: @@ -168,6 +199,15 @@ function applyTestMiddleware(name, middlewares) { }, }, }); + } else if (name === "koa") { + middlewares.push((ctx, next) => { + if (ctx.request.url === "/file.jpg") { + ctx.set("Content-Type", "text/html"); + ctx.body = "welcome"; + } + + next(); + }); } else { middlewares.push({ route: "/file.jpg", @@ -191,12 +231,12 @@ function applyTestMiddleware(name, middlewares) { describe.each([ ["connect", connect], ["express", express], + ["koa", koa], ["hapi", Hapi], ])("%s framework:", (name, framework) => { describe("middleware", () => { let instance; let server; - let app; let req; describe("basic", () => { @@ -218,7 +258,7 @@ describe.each([ codeContent = params.assets["bundle.js"].source(); }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -260,8 +300,6 @@ describe.each([ path.resolve(outputPath, "empty-file.txt"), "", ); - - req = request(app); }); afterAll(async () => { @@ -469,7 +507,7 @@ describe.each([ expect(response.text.length).toBe(501); }); - it('should return the "206" code for the "GET" request with the valid range header for "HEAD" request', async () => { + it('should return the "206" code for the "HEAD" request with the valid range header', async () => { const response = await req .head("/bundle.js") .set("Range", "bytes=3000-3500"); @@ -670,13 +708,11 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -694,13 +730,11 @@ describe.each([ beforeAll(async () => { const compiler = getCompiler(webpackMultiConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -1159,14 +1193,12 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - req = request(app); - const { context: { outputFileSystem: { mkdirSync, writeFileSync }, @@ -1219,7 +1251,7 @@ describe.each([ beforeAll(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -1227,7 +1259,16 @@ describe.each([ undefined, { setupMiddlewares: (middlewares) => { - if (name === "hapi") { + if (name === "koa") { + middlewares.unshift(async (ctx, next) => { + ctx.set( + "Content-Type", + "application/vnd.test+octet-stream", + ); + + await next(); + }); + } else if (name === "hapi") { middlewares.unshift({ plugin: { name: "myPlugin", @@ -1269,8 +1310,6 @@ describe.each([ }, }, ); - - req = request(app); }); afterAll(async () => { @@ -1292,13 +1331,11 @@ describe.each([ // eslint-disable-next-line no-undefined const compiler = getCompiler({ ...webpackConfig, output: undefined }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -1346,13 +1383,11 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -1394,13 +1429,11 @@ describe.each([ beforeAll(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -1449,13 +1482,11 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -1518,7 +1549,7 @@ describe.each([ hash = h; }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -1533,8 +1564,6 @@ describe.each([ } }, 10); }); - - req = request(app); }); afterAll(async () => { @@ -1614,7 +1643,7 @@ describe.each([ hashTwo = two.hash; }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -1629,8 +1658,6 @@ describe.each([ } }, 10); }); - - req = request(app); }); afterAll(async () => { @@ -1708,13 +1735,11 @@ describe.each([ beforeAll(async () => { const compiler = getCompiler(webpackMultiConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -1809,13 +1834,11 @@ describe.each([ }, ]); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -1892,13 +1915,11 @@ describe.each([ }, ]); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -1985,13 +2006,11 @@ describe.each([ beforeAll(async () => { const compiler = getCompiler(webpackClientServerConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -2045,13 +2064,11 @@ describe.each([ webpackClientServerConfig[0], ]); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -2115,13 +2132,11 @@ describe.each([ }, ]); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -2179,13 +2194,11 @@ describe.each([ } }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -2216,7 +2229,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -2243,8 +2256,6 @@ describe.each([ return brokenStream; }; - - req = request(app); }); afterAll(async () => { @@ -2290,7 +2301,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -2321,8 +2332,6 @@ describe.each([ return brokenStream; }; - - req = request(app); }); afterAll(async () => { @@ -2372,7 +2381,7 @@ describe.each([ codeContent = params.assets["bundle.js"].source(); }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -2387,8 +2396,6 @@ describe.each([ ); instance.context.outputFileSystem.createReadStream = null; - - req = request(app); }); afterAll(async () => { @@ -2451,14 +2458,12 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - req = request(app); - instance.context.outputFileSystem.mkdirSync(outputPath, { recursive: true, }); @@ -2494,7 +2499,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -2505,8 +2510,6 @@ describe.each([ }, ); - req = request(app); - instance.context.outputFileSystem.mkdirSync(outputPath, { recursive: true, }); @@ -2542,7 +2545,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -2553,8 +2556,6 @@ describe.each([ }, ); - req = request(app); - instance.context.outputFileSystem.mkdirSync(outputPath, { recursive: true, }); @@ -2589,7 +2590,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -2606,8 +2607,6 @@ describe.each([ }, }, ); - - req = request(app); }); afterAll(async () => { @@ -2635,7 +2634,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -2644,8 +2643,6 @@ describe.each([ }, ); - req = request(app); - instance.context.outputFileSystem.mkdirSync(outputPath, { recursive: true, }); @@ -2680,13 +2677,11 @@ describe.each([ compiler = getCompiler(webpackConfig); spy = jest.spyOn(compiler, "watch"); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -2713,13 +2708,11 @@ describe.each([ spy = jest.spyOn(compiler, "watch"); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -2749,13 +2742,11 @@ describe.each([ spy = jest.spyOn(compiler, "watch"); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, ); - - req = request(app); }); afterAll(async () => { @@ -2795,14 +2786,12 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, { writeToDisk: true }, ); - - req = request(app); }); afterAll(async () => { @@ -2814,40 +2803,38 @@ describe.each([ }); it("should find the bundle file on disk", (done) => { - request(app) - .get("/public/bundle.js") - .expect(200, (error) => { - if (error) { - return done(error); - } + req.get("/public/bundle.js").expect(200, (error) => { + if (error) { + return done(error); + } - const bundlePath = path.resolve( - __dirname, - "./outputs/write-to-disk-true/bundle.js", - ); + const bundlePath = path.resolve( + __dirname, + "./outputs/write-to-disk-true/bundle.js", + ); - expect( - compiler.hooks.assetEmitted.taps.filter( - (hook) => hook.name === "DevMiddleware", - ).length, - ).toBe(1); - expect(fs.existsSync(bundlePath)).toBe(true); + expect( + compiler.hooks.assetEmitted.taps.filter( + (hook) => hook.name === "DevMiddleware", + ).length, + ).toBe(1); + expect(fs.existsSync(bundlePath)).toBe(true); - instance.invalidate(); + instance.invalidate(); - return compiler.hooks.done.tap( - "DevMiddlewareWriteToDiskTest", - () => { - expect( - compiler.hooks.assetEmitted.taps.filter( - (hook) => hook.name === "DevMiddleware", - ).length, - ).toBe(1); + return compiler.hooks.done.tap( + "DevMiddlewareWriteToDiskTest", + () => { + expect( + compiler.hooks.assetEmitted.taps.filter( + (hook) => hook.name === "DevMiddleware", + ).length, + ).toBe(1); - done(); - }, - ); - }); + done(); + }, + ); + }); }); it("should not allow to get files above root", async () => { @@ -2888,7 +2875,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -2899,8 +2886,6 @@ describe.each([ recursive: true, }); fs.writeFileSync(path.resolve(outputPath, "test.json"), "{}"); - - req = request(app); }); afterAll(async () => { @@ -2910,41 +2895,39 @@ describe.each([ }); it("should find the bundle file on disk", (done) => { - request(app) - .get("/bundle.js") - .expect(200, (error) => { - if (error) { - return done(error); - } + req.get("/bundle.js").expect(200, (error) => { + if (error) { + return done(error); + } - const bundlePath = path.resolve(outputPath, "bundle.js"); + const bundlePath = path.resolve(outputPath, "bundle.js"); - expect(fs.existsSync(path.resolve(outputPath, "test.json"))).toBe( - false, - ); + expect(fs.existsSync(path.resolve(outputPath, "test.json"))).toBe( + false, + ); - expect( - compiler.hooks.assetEmitted.taps.filter( - (hook) => hook.name === "DevMiddleware", - ).length, - ).toBe(1); - expect(fs.existsSync(bundlePath)).toBe(true); + expect( + compiler.hooks.assetEmitted.taps.filter( + (hook) => hook.name === "DevMiddleware", + ).length, + ).toBe(1); + expect(fs.existsSync(bundlePath)).toBe(true); - instance.invalidate(); + instance.invalidate(); - return compiler.hooks.done.tap( - "DevMiddlewareWriteToDiskTest", - () => { - expect( - compiler.hooks.assetEmitted.taps.filter( - (hook) => hook.name === "DevMiddleware", - ).length, - ).toBe(1); + return compiler.hooks.done.tap( + "DevMiddlewareWriteToDiskTest", + () => { + expect( + compiler.hooks.assetEmitted.taps.filter( + (hook) => hook.name === "DevMiddleware", + ).length, + ).toBe(1); - done(); - }, - ); - }); + done(); + }, + ); + }); }); }); @@ -2960,7 +2943,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -2973,40 +2956,38 @@ describe.each([ }); it("should not find the bundle file on disk", (done) => { - request(app) - .get("/bundle.js") - .expect(200, (error) => { - if (error) { - return done(error); - } - - const bundlePath = path.resolve( - __dirname, - "./outputs/write-to-disk-false/bundle.js", - ); - - expect( - compiler.hooks.assetEmitted.taps.filter( - (hook) => hook.name === "DevMiddleware", - ).length, - ).toBe(0); - expect(fs.existsSync(bundlePath)).toBe(false); - - instance.invalidate(); + req.get("/bundle.js").expect(200, (error) => { + if (error) { + return done(error); + } - return compiler.hooks.done.tap( - "DevMiddlewareWriteToDiskTest", - () => { - expect( - compiler.hooks.assetEmitted.taps.filter( - (hook) => hook.name === "DevMiddleware", - ).length, - ).toBe(0); + const bundlePath = path.resolve( + __dirname, + "./outputs/write-to-disk-false/bundle.js", + ); - done(); - }, - ); - }); + expect( + compiler.hooks.assetEmitted.taps.filter( + (hook) => hook.name === "DevMiddleware", + ).length, + ).toBe(0); + expect(fs.existsSync(bundlePath)).toBe(false); + + instance.invalidate(); + + return compiler.hooks.done.tap( + "DevMiddlewareWriteToDiskTest", + () => { + expect( + compiler.hooks.assetEmitted.taps.filter( + (hook) => hook.name === "DevMiddleware", + ).length, + ).toBe(0); + + done(); + }, + ); + }); }); }); @@ -3025,7 +3006,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3033,8 +3014,6 @@ describe.each([ writeToDisk: (filePath) => /bundle\.js$/.test(filePath), }, ); - - req = request(app); }); afterAll(async () => { @@ -3077,7 +3056,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3085,8 +3064,6 @@ describe.each([ writeToDisk: (filePath) => !/bundle\.js$/.test(filePath), }, ); - - req = request(app); }); afterAll(async () => { @@ -3129,14 +3106,12 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, { writeToDisk: true }, ); - - req = request(app); }); afterAll(async () => { @@ -3193,14 +3168,12 @@ describe.each([ }, ]); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, { writeToDisk: true }, ); - - req = request(app); }); afterAll(async () => { @@ -3260,7 +3233,7 @@ describe.each([ hash = h; }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3276,8 +3249,6 @@ describe.each([ } }, 10); }); - - req = request(app); }); afterAll(async () => { @@ -3309,7 +3280,7 @@ describe.each([ beforeAll(async () => { compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3318,8 +3289,6 @@ describe.each([ publicPath: "/public/", }, ); - - req = request(app); }); afterAll(async () => { @@ -3350,7 +3319,7 @@ describe.each([ beforeEach(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3365,8 +3334,6 @@ describe.each([ }, }, ); - - req = request(app); }); afterEach(async () => { @@ -3382,7 +3349,7 @@ describe.each([ }); it('should return the "200" code for the "GET" request to path not in outputFileSystem but not return headers', async () => { - const res = await request(app).get("/file.jpg"); + const res = await req.get("/file.jpg"); expect(res.statusCode).toEqual(200); expect(res.headers["X-nonsense-1"]).toBeUndefined(); expect(res.headers["X-nonsense-2"]).toBeUndefined(); @@ -3393,7 +3360,7 @@ describe.each([ beforeEach(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3417,8 +3384,6 @@ describe.each([ }, }, ); - - req = request(app); }); afterEach(async () => { @@ -3434,7 +3399,7 @@ describe.each([ }); it('should return the "200" code for the "GET" request to path not in outputFileSystem but not return headers', async () => { - const res = await request(app).get("/file.jpg"); + const res = await req.get("/file.jpg"); expect(res.statusCode).toEqual(200); expect(res.headers["x-foo"]).toBeUndefined(); expect(res.headers["x-bar"]).toBeUndefined(); @@ -3445,7 +3410,7 @@ describe.each([ beforeEach(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3462,8 +3427,6 @@ describe.each([ }, }, ); - - req = request(app); }); afterEach(async () => { @@ -3490,7 +3453,7 @@ describe.each([ beforeEach(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3514,8 +3477,6 @@ describe.each([ }, }, ); - - req = request(app); }); afterEach(async () => { @@ -3542,7 +3503,7 @@ describe.each([ beforeEach(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3561,8 +3522,6 @@ describe.each([ }, }, ); - - req = request(app); }); afterEach(async () => { @@ -3591,14 +3550,12 @@ describe.each([ beforeAll(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, { publicPath: "/public/" }, ); - - req = request(app); }); afterAll(async () => { @@ -3616,14 +3573,12 @@ describe.each([ beforeAll(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, { publicPath: "auto" }, ); - - req = request(app); }); afterAll(async () => { @@ -3644,14 +3599,22 @@ describe.each([ beforeAll(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, { serverSideRender: true }, { setupMiddlewares: (middlewares) => { - if (name === "hapi") { + if (name === "koa") { + middlewares.push(async (ctx, next) => { + locals = ctx.state; + + ctx.status = 200; + + await next(); + }); + } else if (name === "hapi") { middlewares.push({ plugin: { name: "myPlugin", @@ -3692,8 +3655,6 @@ describe.each([ }, }, ); - - req = request(app); }); afterAll(async () => { @@ -3715,7 +3676,7 @@ describe.each([ beforeAll(async () => { compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3747,7 +3708,7 @@ describe.each([ configuredFs.join = path.join.bind(path); configuredFs.mkdirp = () => {}; - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3784,7 +3745,7 @@ describe.each([ configuredFs.join = path.join.bind(path); configuredFs.mkdirp = () => {}; - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3822,7 +3783,7 @@ describe.each([ configuredFs.join = path.join.bind(path); configuredFs.mkdirp = () => {}; - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3861,14 +3822,12 @@ describe.each([ beforeAll(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, { index: false, publicPath: "/" }, ); - - req = request(app); }); afterAll(async () => { @@ -3898,14 +3857,12 @@ describe.each([ beforeAll(async () => { const compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, { index: true, publicPath: "/" }, ); - - req = request(app); }); afterAll(async () => { @@ -3942,7 +3899,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3952,8 +3909,6 @@ describe.each([ }, ); - req = request(app); - instance.context.outputFileSystem.mkdirSync(outputPath, { recursive: true, }); @@ -3988,7 +3943,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -3998,8 +3953,6 @@ describe.each([ }, ); - req = request(app); - instance.context.outputFileSystem.mkdirSync(outputPath, { recursive: true, }); @@ -4031,7 +3984,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -4044,8 +3997,6 @@ describe.each([ }, ); - req = request(app); - instance.context.outputFileSystem.mkdirSync(outputPath, { recursive: true, }); @@ -4080,15 +4031,13 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, { index: "noextension" }, ); - req = request(app); - instance.context.outputFileSystem.mkdirSync(outputPath, { recursive: true, }); @@ -4120,7 +4069,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -4130,8 +4079,6 @@ describe.each([ }, ); - req = request(app); - instance.context.outputFileSystem.mkdirSync(outputPath, { recursive: true, }); @@ -4158,7 +4105,7 @@ describe.each([ beforeAll(async () => { compiler = getCompiler(webpackConfig); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -4176,8 +4123,6 @@ describe.each([ isDirectory: () => false, }; }); - - req = request(app); }); afterAll(async () => { @@ -4212,7 +4157,7 @@ describe.each([ }, }); - [server, app, instance] = await frameworkFactory( + [server, req, instance] = await frameworkFactory( name, framework, compiler, @@ -4225,8 +4170,6 @@ describe.each([ }, ); - req = request(app); - instance.context.outputFileSystem.mkdirSync(outputPath, { recursive: true, }); diff --git a/types/index.d.ts b/types/index.d.ts index 6cea92174..ee6f4c9e0 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -145,22 +145,24 @@ export = wdm; * @typedef {T & { [P in K]: NonNullable }} WithoutUndefined */ /** - * @template {IncomingMessage} RequestInternal - * @template {ServerResponse} ResponseInternal + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] * @param {Compiler | MultiCompiler} compiler * @param {Options} [options] * @returns {API} */ declare function wdm< - RequestInternal extends import("http").IncomingMessage, - ResponseInternal extends ServerResponse, + RequestInternal extends + import("http").IncomingMessage = import("http").IncomingMessage, + ResponseInternal extends ServerResponse = ServerResponse, >( compiler: Compiler | MultiCompiler, options?: Options | undefined, ): API; declare namespace wdm { export { - hapiPlugin, + hapiWrapper, + koaWrapper, Schema, Compiler, MultiCompiler, @@ -226,10 +228,25 @@ type API< * @template {HapiOptions} HapiOptionsInternal * @returns {HapiPlugin} */ -declare function hapiPlugin< +declare function hapiWrapper< HapiServer, HapiOptionsInternal extends HapiOptions, >(): HapiPlugin; +/** + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] + * @param {Compiler | MultiCompiler} compiler + * @param {Options} [options] + * @returns {(ctx: any, next: Function) => Promise | void} + */ +declare function koaWrapper< + RequestInternal extends + import("http").IncomingMessage = import("http").IncomingMessage, + ResponseInternal extends ServerResponse = ServerResponse, +>( + compiler: Compiler | MultiCompiler, + options?: Options | undefined, +): (ctx: any, next: Function) => Promise | void; type Schema = import("schema-utils/declarations/validate").Schema; type Configuration = import("webpack").Configuration; type Stats = import("webpack").Stats; diff --git a/types/utils/compatibleAPI.d.ts b/types/utils/compatibleAPI.d.ts index f2af44ce3..88844c4bd 100644 --- a/types/utils/compatibleAPI.d.ts +++ b/types/utils/compatibleAPI.d.ts @@ -10,6 +10,7 @@ export type ExpectedResponse = { set: (name: string, value: number | string | string[]) => void; status: (status: number) => void; send: (data: any) => void; + pipeInto?: ((data: any) => void) | undefined; }; /** * send error options @@ -46,6 +47,7 @@ export type SendOptions< * @property {(name: string, value: number | string | string[]) => void} set * @property {(status: number) => void} status * @property {(data: any) => void} send + * @property {(data: any) => void} [pipeInto] */ /** * @template {ServerResponse} Response