diff --git a/README.md b/README.md index fa00530..3b61cdf 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ bun add -D @rspack/dev-middleware ## Usage ```js -const middleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const express = require("express"); const { rspack } = require("@rspack/core"); @@ -50,7 +50,7 @@ const compiler = rspack({ const app = express(); app.use( - middleware(compiler, { + devMiddleware(compiler, { // options }), ); @@ -100,7 +100,7 @@ eg. `{ "X-Custom-Header": "yes" }` or ```js -middleware(compiler, { +devMiddleware(compiler, { headers: () => ({ "Last-Modified": new Date(), }), @@ -110,7 +110,7 @@ middleware(compiler, { or ```js -middleware(compiler, { +devMiddleware(compiler, { headers: (req, res, context) => { res.setHeader("Last-Modified", new Date()); }, @@ -120,7 +120,7 @@ middleware(compiler, { or ```js -middleware(compiler, { +devMiddleware(compiler, { headers: [ { key: "X-custom-header", @@ -137,7 +137,7 @@ middleware(compiler, { or ```js -middleware(compiler, { +devMiddleware(compiler, { headers: () => [ { key: "X-custom-header", @@ -256,7 +256,7 @@ const configuration = { }; const compiler = rspack(configuration); -middleware(compiler, { +devMiddleware(compiler, { writeToDisk: (filePath) => /superman\.css$/.test(filePath), }); ``` @@ -284,7 +284,7 @@ const compiler = rspack({ /* Rspack configuration */ }); -middleware(compiler, { outputFileSystem: myOutputFileSystem }); +devMiddleware(compiler, { outputFileSystem: myOutputFileSystem }); ``` ### modifyResponseData @@ -299,7 +299,7 @@ const configuration = { }; const compiler = rspack(configuration); -middleware(compiler, { +devMiddleware(compiler, { // Note - if you send the `Range` header you will have `ReadStream` // Also `data` can be `string` or `Buffer` modifyResponseData: (req, res, data, byteLength) => @@ -328,7 +328,7 @@ Required: `No` A function executed once the middleware has stopped watching. ```js -const middleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const express = require("express"); const { rspack } = require("@rspack/core"); @@ -336,7 +336,7 @@ const compiler = rspack({ /* Rspack configuration */ }); -const instance = middleware(compiler); +const instance = devMiddleware(compiler); // eslint-disable-next-line new-cap const app = new express(); @@ -363,7 +363,7 @@ Required: `No` A function executed once the middleware has invalidated. ```js -const middleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const express = require("express"); const { rspack } = require("@rspack/core"); @@ -371,7 +371,7 @@ const compiler = rspack({ /* Rspack configuration */ }); -const instance = middleware(compiler); +const instance = devMiddleware(compiler); // eslint-disable-next-line new-cap const app = new express(); @@ -403,7 +403,7 @@ A function executed when the bundle becomes valid. If the bundle is valid at the time of calling, the callback is executed immediately. ```js -const middleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const express = require("express"); const { rspack } = require("@rspack/core"); @@ -411,7 +411,7 @@ const compiler = rspack({ /* Rspack configuration */ }); -const instance = middleware(compiler); +const instance = devMiddleware(compiler); // eslint-disable-next-line new-cap const app = new express(); @@ -437,7 +437,7 @@ Required: `Yes` URL for the requested file. ```js -const middleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const express = require("express"); const { rspack } = require("@rspack/core"); @@ -445,7 +445,7 @@ const compiler = rspack({ /* Rspack configuration */ }); -const instance = middleware(compiler); +const instance = devMiddleware(compiler); // eslint-disable-next-line new-cap const app = new express(); @@ -468,7 +468,7 @@ Since `output.publicPath` and `output.filename`/`output.chunkFilename` can be dy But there is a solution to avoid it - mount the middleware to a non-root route, for example: ```js -const middleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const express = require("express"); const { rspack } = require("@rspack/core"); @@ -482,7 +482,7 @@ const app = express(); // Note - check your public path, if you want to handle `/dist/`, you need to setup `output.publicPath` to `/` value. app.use( "/dist/", - middleware(compiler, { + devMiddleware(compiler, { // @rspack/dev-middleware options }), ); @@ -495,11 +495,11 @@ app.listen(3000, () => console.log("Example app listening on port 3000!")); _Note: this feature is experimental and may be removed or changed completely in the future._ In order to develop an app using server-side rendering, we need access to the -[`stats`](https://github.com/webpack/docs/wiki/node.js-api#stats), which is +[`stats`](https://rspack.rs/api/javascript-api/stats), which is generated with each build. -With server-side rendering enabled, `@rspack/dev-middleware` sets the `stats` to `res.locals.webpack.devMiddleware.stats` -and the filesystem to `res.locals.webpack.devMiddleware.outputFileSystem` before invoking the next middleware, +With server-side rendering enabled, `@rspack/dev-middleware` sets the `stats` to `res.locals.rspack.devMiddleware.stats` +and the filesystem to `res.locals.rspack.devMiddleware.outputFileSystem` before invoking the next middleware, allowing a developer to render the page body and manage the response to clients. _Note: Requests for bundle files will still be handled by @@ -509,7 +509,7 @@ process is finished with server-side rendering enabled._ Example Implementation: ```js -const middleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const express = require("express"); const isObject = require("is-object"); const { rspack } = require("@rspack/core"); @@ -530,14 +530,14 @@ function normalizeAssets(assets) { return Array.isArray(assets) ? assets : [assets]; } -app.use(middleware(compiler, { serverSideRender: true })); +app.use(devMiddleware(compiler, { serverSideRender: true })); // The following middleware would not be invoked until the latest build is finished. app.use((req, res) => { - const { devMiddleware } = res.locals.webpack; + const { devMiddleware } = res.locals.rspack; const { outputFileSystem } = devMiddleware; - const jsonWebpackStats = devMiddleware.stats.toJson(); - const { assetsByChunkName, outputPath } = jsonWebpackStats; + const jsonStats = devMiddleware.stats.toJson(); + const { assetsByChunkName, outputPath } = jsonStats; // Then use `assetsByChunkName` for server-side rendering // For example, if you have only one main chunk: @@ -572,7 +572,7 @@ Examples of use with other servers will follow here. ```js const http = require("node:http"); -const devMiddleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const connect = require("connect"); const { rspack } = require("@rspack/core"); const rspackConfig = require("./rspack.config.js"); @@ -592,7 +592,7 @@ http.createServer(app).listen(3000); ```js const http = require("node:http"); -const devMiddleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const finalhandler = require("finalhandler"); const Router = require("router"); const { rspack } = require("@rspack/core"); @@ -618,7 +618,7 @@ server.listen(3000); ### Express ```js -const devMiddleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const express = require("express"); const { rspack } = require("@rspack/core"); const rspackConfig = require("./rspack.config.js"); @@ -637,7 +637,7 @@ app.listen(3000, () => console.log("Example app listening on port 3000!")); ### Koa ```js -const middleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const Koa = require("koa"); const { rspack } = require("@rspack/core"); const rspackConfig = require("./rspack.simple.config"); @@ -657,7 +657,7 @@ app.listen(3000); ```js const Hapi = require("@hapi/hapi"); -const devMiddleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const { rspack } = require("@rspack/core"); const rspackConfig = require("./rspack.config.js"); @@ -690,7 +690,7 @@ process.on("unhandledRejection", (err) => { 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. ```js -const devMiddleware = require("@rspack/dev-middleware"); +const { devMiddleware } = require("@rspack/dev-middleware"); const fastify = require("fastify")(); const { rspack } = require("@rspack/core"); const rspackConfig = require("./rspack.config.js"); diff --git a/package.json b/package.json index 2530fd3..9f84795 100644 --- a/package.json +++ b/package.json @@ -4,17 +4,12 @@ "description": "A development middleware for Rspack", "keywords": [ "rspack", - "webpack", "middleware", "development" ], "homepage": "https://github.com/rstackjs/rspack-dev-middleware", "bugs": "https://github.com/rstackjs/rspack-dev-middleware/issues", "repository": "rstackjs/rspack-dev-middleware", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, "license": "MIT", "author": "Tobias Koppers @sokra", "type": "module", diff --git a/src/index.js b/src/index.js index d4d73a6..bfd888e 100644 --- a/src/index.js +++ b/src/index.js @@ -18,7 +18,7 @@ const noop = () => {}; /** * @typedef {object} ExtendedServerResponse - * @property {{ webpack?: { devMiddleware?: Context } }=} locals locals + * @property {{ rspack?: { devMiddleware?: Context }, webpack?: { devMiddleware?: Context } }=} locals locals */ /** @typedef {import("http").IncomingMessage} IncomingMessage */ @@ -197,9 +197,9 @@ const noop = () => {}; * @template {ServerResponse} [ResponseInternal=ServerResponse] * @param {Compiler | MultiCompiler} compiler compiler * @param {Options=} options options - * @returns {API} webpack dev middleware + * @returns {API} rspack dev middleware */ -function wdm(compiler, options = {}) { +function rdm(compiler, options = {}) { const { mimeTypes } = options; if (mimeTypes) { @@ -220,7 +220,7 @@ function wdm(compiler, options = {}) { callbacks: [], options, compiler, - logger: compiler.getInfrastructureLogger("webpack-dev-middleware"), + logger: compiler.getInfrastructureLogger("rspack-dev-middleware"), }; setupHooks(context); @@ -242,8 +242,7 @@ function wdm(compiler, options = {}) { if (error) { // TODO: improve that in future // For example - `writeToDisk` can throw an error and right now it is ends watching. - // We can improve that and keep watching active, but it is require API on webpack side. - // Let's implement that in webpack@5 because it is rare case. + // We can improve that and keep watching active, but it requires compiler support. context.logger.error(error); } }; @@ -321,7 +320,7 @@ function wdm(compiler, options = {}) { function hapiWrapper() { return { pkg: { - name: "webpack-dev-middleware", + name: "rspack-dev-middleware", }, // Allow to have multiple middleware multiple: true, @@ -332,12 +331,12 @@ function hapiWrapper() { throw new Error("The compiler options is required."); } - const devMiddleware = wdm(compiler, rest); + const devMiddleware = rdm(compiler, rest); // @ts-expect-error - if (!server.decorations.server.includes("webpackDevMiddleware")) { + if (!server.decorations.server.includes("rspackDevMiddleware")) { // @ts-expect-error - server.decorate("server", "webpackDevMiddleware", devMiddleware); + server.decorate("server", "rspackDevMiddleware", devMiddleware); } // @ts-expect-error @@ -384,7 +383,7 @@ function hapiWrapper() { }; } -wdm.hapiWrapper = hapiWrapper; +rdm.hapiWrapper = hapiWrapper; /** * @template {IncomingMessage} [RequestInternal=IncomingMessage] @@ -394,14 +393,14 @@ wdm.hapiWrapper = hapiWrapper; * @returns {(ctx: EXPECTED_ANY, next: EXPECTED_FUNCTION) => Promise | void} kow wrapper */ function koaWrapper(compiler, options) { - const devMiddleware = wdm(compiler, options); + const devMiddleware = rdm(compiler, options); /** * @param {{ req: RequestInternal, res: ResponseInternal & import("./utils/compatibleAPI").ExpectedServerResponse, status: number, body: string | Buffer | import("fs").ReadStream | { message: string }, state: object }} ctx context * @param {EXPECTED_FUNCTION} next next * @returns {Promise} */ - async function webpackDevMiddleware(ctx, next) { + async function rspackDevMiddleware(ctx, next) { const { req, res } = ctx; res.locals = ctx.state; @@ -492,12 +491,12 @@ function koaWrapper(compiler, options) { } } - webpackDevMiddleware.devMiddleware = devMiddleware; + rspackDevMiddleware.devMiddleware = devMiddleware; - return webpackDevMiddleware; + return rspackDevMiddleware; } -wdm.koaWrapper = koaWrapper; +rdm.koaWrapper = koaWrapper; /** * @template {IncomingMessage} [RequestInternal=IncomingMessage] @@ -507,17 +506,18 @@ wdm.koaWrapper = koaWrapper; * @returns {(ctx: EXPECTED_ANY, next: EXPECTED_FUNCTION) => Promise | void} hono wrapper */ function honoWrapper(compiler, options) { - const devMiddleware = wdm(compiler, options); + const devMiddleware = rdm(compiler, options); /** * @param {{ env: EXPECTED_ANY, body: EXPECTED_ANY, json: EXPECTED_ANY, status: EXPECTED_ANY, set: EXPECTED_ANY, req: RequestInternal & import("./utils/compatibleAPI").ExpectedIncomingMessage & { header: (name: string) => string }, res: ResponseInternal & import("./utils/compatibleAPI").ExpectedServerResponse & { headers: EXPECTED_ANY, status: EXPECTED_ANY } }} context context * @param {EXPECTED_FUNCTION} next next function * @returns {Promise} */ - async function webpackDevMiddleware(context, next) { + async function rspackDevMiddleware(context, next) { const { req, res } = context; context.set("webpack", { devMiddleware: devMiddleware.context }); + context.set("rspack", { devMiddleware: devMiddleware.context }); /** * @returns {string | undefined} method @@ -663,11 +663,11 @@ function honoWrapper(compiler, options) { await next(); } - webpackDevMiddleware.devMiddleware = devMiddleware; + rspackDevMiddleware.devMiddleware = devMiddleware; - return webpackDevMiddleware; + return rspackDevMiddleware; } -wdm.honoWrapper = honoWrapper; +rdm.honoWrapper = honoWrapper; -export default wdm; +export const devMiddleware = rdm; diff --git a/src/middleware.js b/src/middleware.js index cccc73d..396f8d6 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -182,6 +182,8 @@ function wrapper(context) { ready( context, () => { + setState(res, "rspack", { devMiddleware: context }); + // Preserve the legacy SSR API shape for existing integrations. setState(res, "webpack", { devMiddleware: context }); resolve(next(err)); }, diff --git a/src/utils/setupHooks.js b/src/utils/setupHooks.js index d8bb3d4..22e3441 100644 --- a/src/utils/setupHooks.js +++ b/src/utils/setupHooks.js @@ -105,9 +105,9 @@ function setupHooks(context) { /** @type {import("../index.js").Context} */ (context).compiler; - compiler.hooks.watchRun.tap("webpack-dev-middleware", invalid); - compiler.hooks.invalid.tap("webpack-dev-middleware", invalid); - compiler.hooks.done.tap("webpack-dev-middleware", done); + compiler.hooks.watchRun.tap("rspack-dev-middleware", invalid); + compiler.hooks.invalid.tap("rspack-dev-middleware", invalid); + compiler.hooks.done.tap("rspack-dev-middleware", done); } export default setupHooks; diff --git a/src/utils/setupOutputFileSystem.js b/src/utils/setupOutputFileSystem.js index aa8c12b..a978d14 100644 --- a/src/utils/setupOutputFileSystem.js +++ b/src/utils/setupOutputFileSystem.js @@ -42,7 +42,7 @@ function setupOutputFileSystem(context) { if (isMultiCompiler) { // Prefer compiler with `devServer` option or fallback on the first - // TODO we need to support webpack-dev-server as a plugin or revisit it + // TODO we need to support rspack-dev-server as a plugin or revisit it const compiler = /** @type {MultiCompiler} */ (context.compiler).compilers.find( diff --git a/src/utils/setupWriteToDisk.js b/src/utils/setupWriteToDisk.js index f6fb87f..684ea12 100644 --- a/src/utils/setupWriteToDisk.js +++ b/src/utils/setupWriteToDisk.js @@ -8,6 +8,9 @@ import path from "node:path"; /** @typedef {import("../index.js").IncomingMessage} IncomingMessage */ /** @typedef {import("../index.js").ServerResponse} ServerResponse */ +const ASSET_EMITTED_CALLBACK_FLAG = + "hasRspackDevMiddlewareAssetEmittedCallback"; + /** * @template {IncomingMessage} Request * @template {ServerResponse} Response @@ -28,7 +31,7 @@ function setupWriteToDisk(context) { compiler.hooks.emit.tap("DevMiddleware", () => { // @ts-expect-error - if (compiler.hasWebpackDevMiddlewareAssetEmittedCallback) { + if (compiler[ASSET_EMITTED_CALLBACK_FLAG]) { return; } @@ -78,7 +81,7 @@ function setupWriteToDisk(context) { ); // @ts-expect-error - compiler.hasWebpackDevMiddlewareAssetEmittedCallback = true; + compiler[ASSET_EMITTED_CALLBACK_FLAG] = true; }); } } diff --git a/test/helpers/getCompilerHooks.js b/test/helpers/getCompilerHooks.js index 0a8f873..c96f82b 100644 --- a/test/helpers/getCompilerHooks.js +++ b/test/helpers/getCompilerHooks.js @@ -3,7 +3,7 @@ export default (compiler) => { for (const hook of Object.keys(compiler.hooks)) { for (const tap of compiler.hooks[hook].taps) { - if (tap.name === "webpack-dev-middleware") { + if (tap.name === "rspack-dev-middleware") { if (!result[hook]) { result[hook] = []; } diff --git a/test/helpers/listenAndCompile.js b/test/helpers/listenAndCompile.js index 3b20b02..5301f60 100644 --- a/test/helpers/listenAndCompile.js +++ b/test/helpers/listenAndCompile.js @@ -17,7 +17,7 @@ export default (app, compiler, callback) => { return progress(); }); - compiler.hooks.done.tap("wdm-test", () => progress()); + compiler.hooks.done.tap("rdm-test", () => progress()); return listen; }; diff --git a/test/middleware.test.js b/test/middleware.test.js index aa26461..a7565f4 100644 --- a/test/middleware.test.js +++ b/test/middleware.test.js @@ -17,7 +17,7 @@ import { lookup, mimes } from "mrmime"; import router from "router"; import request from "supertest"; -import middleware from "../src/index.js"; +import { devMiddleware } from "../src/index.js"; import webpackMultiConfig from "./fixtures/webpack.array.config.js"; import webpackMultiDevServerFalseConfig from "./fixtures/webpack.array.dev-server-false.js"; @@ -90,7 +90,7 @@ async function frameworkFactory( case "hapi": { const server = framework.server(); const hapiPlugin = { - plugin: middleware.hapiWrapper(), + plugin: devMiddleware.hapiWrapper(), options: { compiler, ...devMiddlewareOptions, @@ -117,12 +117,12 @@ async function frameworkFactory( const req = request(server.listener); - return [server, req, server.webpackDevMiddleware]; + return [server, req, server.rspackDevMiddleware]; } case "koa": { // eslint-disable-next-line new-cap const app = new framework(); - const koaMiddleware = middleware.koaWrapper( + const koaMiddleware = devMiddleware.koaWrapper( compiler, devMiddlewareOptions, ); @@ -149,7 +149,10 @@ async function frameworkFactory( const app = new framework(); const server = await startServer(name, app); const req = request(server); - const instance = middleware.honoWrapper(compiler, devMiddlewareOptions); + const instance = devMiddleware.honoWrapper( + compiler, + devMiddlewareOptions, + ); const middlewares = typeof options.setupMiddlewares === "function" ? options.setupMiddlewares([instance]) @@ -174,7 +177,7 @@ async function frameworkFactory( await app.register(fastifyExpress); } - const instance = middleware(compiler, devMiddlewareOptions); + const instance = devMiddleware(compiler, devMiddlewareOptions); const middlewares = typeof options.setupMiddlewares === "function" ? options.setupMiddlewares([instance]) @@ -223,7 +226,7 @@ function waitUntilValid(instance) { }); } -function waitForCompilerDone(compiler, name = "wdm-test") { +function waitForCompilerDone(compiler, name = "rdm-test") { return new Promise((resolve) => { compiler.hooks.done.tap(name, resolve); }); @@ -421,7 +424,7 @@ describe.each([ beforeEach(async () => { compiler = getCompiler({ ...webpackConfig, watch: true }); - instance = middleware(compiler); + instance = devMiddleware(compiler); [server, req, instance] = await frameworkFactory( name, @@ -860,7 +863,7 @@ describe.each([ path: outputPath, }, }); - compiler.hooks.afterCompile.tap("wdm-test", (params) => { + compiler.hooks.afterCompile.tap("rdm-test", (params) => { codeContent = params.assets["bundle.js"].source(); }); @@ -2274,7 +2277,7 @@ describe.each([ path: path.resolve(__dirname, "./outputs/other-basic-[fullhash]"), }, }); - compiler.hooks.afterCompile.tap("wdm-test", ({ hash: h }) => { + compiler.hooks.afterCompile.tap("rdm-test", ({ hash: h }) => { hash = h; }); @@ -2365,7 +2368,7 @@ describe.each([ }, }, ]); - compiler.hooks.done.tap("wdm-test", (stats) => { + compiler.hooks.done.tap("rdm-test", (stats) => { const [one, two] = stats.stats; hashOne = one.hash; @@ -3104,7 +3107,7 @@ describe.each([ path: outputPath, }, }); - compiler.hooks.afterCompile.tap("wdm-test", (params) => { + compiler.hooks.afterCompile.tap("rdm-test", (params) => { codeContent = params.assets["bundle.js"].source(); }); @@ -4490,7 +4493,7 @@ describe.each([ ), }, }); - compiler.hooks.afterCompile.tap("wdm-test", ({ hash: h }) => { + compiler.hooks.afterCompile.tap("rdm-test", ({ hash: h }) => { hash = h; }); @@ -4876,7 +4879,10 @@ describe.each([ }); } else if (name === "hono") { middlewares.push((c) => { - locals = { webpack: c.get("webpack") }; + locals = { + rspack: c.get("rspack"), + webpack: c.get("webpack"), + }; return c.body("welcome", 200); }); @@ -4928,6 +4934,7 @@ describe.each([ const response = await req.get("/foo/bar"); expect(response.statusCode).toBe(200); + expect(locals.rspack.devMiddleware).toBeDefined(); expect(locals.webpack.devMiddleware).toBeDefined(); }); }); diff --git a/test/utils/setupWriteToDisk.test.js b/test/utils/setupWriteToDisk.test.js index fdf65ca..b676913 100644 --- a/test/utils/setupWriteToDisk.test.js +++ b/test/utils/setupWriteToDisk.test.js @@ -63,7 +63,7 @@ describe("setupWriteToDisk", () => { }; setupWriteToDisk(context); const cb = rs.fn(); - // webpack@5 info style + // rspack assetEmitted info style runAssetEmitted( null, { @@ -73,7 +73,7 @@ describe("setupWriteToDisk", () => { cb, ); - // the getPath helper is not needed for webpack@5 + // the getPath helper is not needed here expect(getPath).not.toHaveBeenCalled(); expect(filter).toHaveBeenCalledTimes(1); @@ -104,7 +104,7 @@ describe("setupWriteToDisk", () => { try { setupWriteToDisk(context); const cb = rs.fn(); - // webpack@5 info style + // rspack assetEmitted info style runAssetEmitted( null, { @@ -115,7 +115,7 @@ describe("setupWriteToDisk", () => { cb, ); - // the getPath helper is not needed for webpack@5 + // the getPath helper is not needed here expect(getPath).not.toHaveBeenCalled(); expect(mkdirSpy).toHaveBeenCalledTimes(1); diff --git a/types/index.d.ts b/types/index.d.ts index 3e6da27..8946aca 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,4 +1,174 @@ -export default wdm; +/** @typedef {import("@rspack/core").Compiler} Compiler */ +/** @typedef {import("@rspack/core").MultiCompiler} MultiCompiler */ +/** @typedef {import("@rspack/core").Configuration} Configuration */ +/** @typedef {import("@rspack/core").Stats} Stats */ +/** @typedef {import("@rspack/core").MultiStats} MultiStats */ +/** @typedef {import("fs").ReadStream} ReadStream */ +/** + * @typedef {object} ExtendedServerResponse + * @property {{ rspack?: { devMiddleware?: Context }, webpack?: { devMiddleware?: Context } }=} locals locals + */ +/** @typedef {import("http").IncomingMessage} IncomingMessage */ +/** @typedef {import("http").ServerResponse & ExtendedServerResponse} ServerResponse */ +/** @typedef {any} EXPECTED_ANY */ +/** @typedef {Function} EXPECTED_FUNCTION */ +/** + * @callback NextFunction + * @param {EXPECTED_ANY=} err error + * @returns {void} + */ +/** + * @typedef {NonNullable} WatchOptions + */ +/** + * @typedef {boolean | Configuration["devServer"] | undefined} DevServerOption + */ +/** + * @typedef {Compiler["watching"]} Watching + */ +/** + * @typedef {ReturnType} MultiWatching + */ +/** + * @typedef {import("@rspack/core").OutputFileSystem & { createReadStream?: import("fs").createReadStream, statSync: import("fs").statSync, readFileSync: import("fs").readFileSync }} OutputFileSystem + */ +/** @typedef {ReturnType} Logger */ +/** @typedef {{ close(callback: (err?: Error | null | undefined) => void): void }} ClosableWatching */ +/** + * @callback Callback + * @param {(Stats | MultiStats)=} stats + */ +/** + * @typedef {object} ResponseData + * @property {Buffer | ReadStream} data data + * @property {number} byteLength byte length + */ +/** + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] + * @callback ModifyResponseData + * @param {RequestInternal} req req + * @param {ResponseInternal} res res + * @param {Buffer | ReadStream} data data + * @param {number} byteLength byte length + * @returns {ResponseData} + */ +/** + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] + * @typedef {object} Context + * @property {boolean} state state + * @property {Stats | MultiStats | undefined} stats stats + * @property {Callback[]} callbacks callbacks + * @property {Options} options options + * @property {Compiler | MultiCompiler} compiler compiler + * @property {Watching | MultiWatching | undefined} watching watching + * @property {Logger} logger logger + * @property {OutputFileSystem} outputFileSystem output file system + */ +/** + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] + * @typedef {WithoutUndefined, "watching">} FilledContext + */ +/** @typedef {Record | { key: string, value: number | string }[]} NormalizedHeaders */ +/** + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] + * @typedef {NormalizedHeaders | ((req: RequestInternal, res: ResponseInternal, context: Context) => void | undefined | NormalizedHeaders) | undefined} Headers + */ +/** + * @template {IncomingMessage} [RequestInternal = IncomingMessage] + * @template {ServerResponse} [ResponseInternal = ServerResponse] + * @typedef {object} Options + * @property {{ [key: string]: string }=} mimeTypes mime types + * @property {(string | undefined)=} mimeTypeDefault mime type default + * @property {(boolean | ((targetPath: string) => boolean))=} writeToDisk write to disk + * @property {string[]=} methods methods + * @property {Headers=} headers headers + * @property {NonNullable["publicPath"]=} publicPath public path + * @property {Configuration["stats"]=} stats stats + * @property {boolean=} serverSideRender is server side render + * @property {OutputFileSystem=} outputFileSystem output file system + * @property {(boolean | string)=} index index + * @property {ModifyResponseData=} modifyResponseData modify response data + * @property {"weak" | "strong"=} etag options to generate etag header + * @property {boolean=} lastModified options to generate last modified header + * @property {(boolean | number | string | { maxAge?: number, immutable?: boolean })=} cacheControl options to generate cache headers + * @property {boolean=} cacheImmutable is cache immutable + */ +/** + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] + * @callback Middleware + * @param {RequestInternal} req + * @param {ResponseInternal} res + * @param {NextFunction} next + * @returns {Promise} + */ +/** @typedef {import("./utils/getFilenameFromUrl").Extra} Extra */ +/** + * @callback GetFilenameFromUrl + * @param {string} url + * @param {Extra=} extra + * @returns {string | undefined} + */ +/** + * @callback WaitUntilValid + * @param {Callback} callback + */ +/** + * @callback Invalidate + * @param {Callback} callback + */ +/** + * @callback Close + * @param {(err: Error | null | undefined) => void} callback + */ +/** + * @template {IncomingMessage} RequestInternal + * @template {ServerResponse} ResponseInternal + * @typedef {object} AdditionalMethods + * @property {GetFilenameFromUrl} getFilenameFromUrl get filename from url + * @property {WaitUntilValid} waitUntilValid wait until valid + * @property {Invalidate} invalidate invalidate + * @property {Close} close close + * @property {Context} context context + */ +/** + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] + * @typedef {Middleware & AdditionalMethods} API + */ +/** + * @template T + * @template {keyof T} K + * @typedef {Omit & Partial} WithOptional + */ +/** + * @template T + * @template {keyof T} K + * @typedef {T & { [P in K]: NonNullable }} WithoutUndefined + */ +/** + * @template {IncomingMessage} [RequestInternal=IncomingMessage] + * @template {ServerResponse} [ResponseInternal=ServerResponse] + * @param {Compiler | MultiCompiler} compiler compiler + * @param {Options=} options options + * @returns {API} rspack dev middleware + */ +export function devMiddleware< + RequestInternal extends IncomingMessage = import("http").IncomingMessage, + ResponseInternal extends ServerResponse = ServerResponse, +>( + compiler: Compiler | MultiCompiler, + options?: Options | undefined, +): API; +export namespace devMiddleware { + export { hapiWrapper }; + export { koaWrapper }; + export { honoWrapper }; +} export type Compiler = import("@rspack/core").Compiler; export type MultiCompiler = import("@rspack/core").MultiCompiler; export type Configuration = import("@rspack/core").Configuration; @@ -11,6 +181,9 @@ export type ExtendedServerResponse = { */ locals?: | { + rspack?: { + devMiddleware?: Context; + }; webpack?: { devMiddleware?: Context; }; @@ -260,177 +433,6 @@ export type HapiPlugin = HapiPluginBase & { export type HapiOptions = Options & { compiler: Compiler | MultiCompiler; }; -/** @typedef {import("@rspack/core").Compiler} Compiler */ -/** @typedef {import("@rspack/core").MultiCompiler} MultiCompiler */ -/** @typedef {import("@rspack/core").Configuration} Configuration */ -/** @typedef {import("@rspack/core").Stats} Stats */ -/** @typedef {import("@rspack/core").MultiStats} MultiStats */ -/** @typedef {import("fs").ReadStream} ReadStream */ -/** - * @typedef {object} ExtendedServerResponse - * @property {{ webpack?: { devMiddleware?: Context } }=} locals locals - */ -/** @typedef {import("http").IncomingMessage} IncomingMessage */ -/** @typedef {import("http").ServerResponse & ExtendedServerResponse} ServerResponse */ -/** @typedef {any} EXPECTED_ANY */ -/** @typedef {Function} EXPECTED_FUNCTION */ -/** - * @callback NextFunction - * @param {EXPECTED_ANY=} err error - * @returns {void} - */ -/** - * @typedef {NonNullable} WatchOptions - */ -/** - * @typedef {boolean | Configuration["devServer"] | undefined} DevServerOption - */ -/** - * @typedef {Compiler["watching"]} Watching - */ -/** - * @typedef {ReturnType} MultiWatching - */ -/** - * @typedef {import("@rspack/core").OutputFileSystem & { createReadStream?: import("fs").createReadStream, statSync: import("fs").statSync, readFileSync: import("fs").readFileSync }} OutputFileSystem - */ -/** @typedef {ReturnType} Logger */ -/** @typedef {{ close(callback: (err?: Error | null | undefined) => void): void }} ClosableWatching */ -/** - * @callback Callback - * @param {(Stats | MultiStats)=} stats - */ -/** - * @typedef {object} ResponseData - * @property {Buffer | ReadStream} data data - * @property {number} byteLength byte length - */ -/** - * @template {IncomingMessage} [RequestInternal=IncomingMessage] - * @template {ServerResponse} [ResponseInternal=ServerResponse] - * @callback ModifyResponseData - * @param {RequestInternal} req req - * @param {ResponseInternal} res res - * @param {Buffer | ReadStream} data data - * @param {number} byteLength byte length - * @returns {ResponseData} - */ -/** - * @template {IncomingMessage} [RequestInternal=IncomingMessage] - * @template {ServerResponse} [ResponseInternal=ServerResponse] - * @typedef {object} Context - * @property {boolean} state state - * @property {Stats | MultiStats | undefined} stats stats - * @property {Callback[]} callbacks callbacks - * @property {Options} options options - * @property {Compiler | MultiCompiler} compiler compiler - * @property {Watching | MultiWatching | undefined} watching watching - * @property {Logger} logger logger - * @property {OutputFileSystem} outputFileSystem output file system - */ -/** - * @template {IncomingMessage} [RequestInternal=IncomingMessage] - * @template {ServerResponse} [ResponseInternal=ServerResponse] - * @typedef {WithoutUndefined, "watching">} FilledContext - */ -/** @typedef {Record | { key: string, value: number | string }[]} NormalizedHeaders */ -/** - * @template {IncomingMessage} [RequestInternal=IncomingMessage] - * @template {ServerResponse} [ResponseInternal=ServerResponse] - * @typedef {NormalizedHeaders | ((req: RequestInternal, res: ResponseInternal, context: Context) => void | undefined | NormalizedHeaders) | undefined} Headers - */ -/** - * @template {IncomingMessage} [RequestInternal = IncomingMessage] - * @template {ServerResponse} [ResponseInternal = ServerResponse] - * @typedef {object} Options - * @property {{ [key: string]: string }=} mimeTypes mime types - * @property {(string | undefined)=} mimeTypeDefault mime type default - * @property {(boolean | ((targetPath: string) => boolean))=} writeToDisk write to disk - * @property {string[]=} methods methods - * @property {Headers=} headers headers - * @property {NonNullable["publicPath"]=} publicPath public path - * @property {Configuration["stats"]=} stats stats - * @property {boolean=} serverSideRender is server side render - * @property {OutputFileSystem=} outputFileSystem output file system - * @property {(boolean | string)=} index index - * @property {ModifyResponseData=} modifyResponseData modify response data - * @property {"weak" | "strong"=} etag options to generate etag header - * @property {boolean=} lastModified options to generate last modified header - * @property {(boolean | number | string | { maxAge?: number, immutable?: boolean })=} cacheControl options to generate cache headers - * @property {boolean=} cacheImmutable is cache immutable - */ -/** - * @template {IncomingMessage} [RequestInternal=IncomingMessage] - * @template {ServerResponse} [ResponseInternal=ServerResponse] - * @callback Middleware - * @param {RequestInternal} req - * @param {ResponseInternal} res - * @param {NextFunction} next - * @returns {Promise} - */ -/** @typedef {import("./utils/getFilenameFromUrl").Extra} Extra */ -/** - * @callback GetFilenameFromUrl - * @param {string} url - * @param {Extra=} extra - * @returns {string | undefined} - */ -/** - * @callback WaitUntilValid - * @param {Callback} callback - */ -/** - * @callback Invalidate - * @param {Callback} callback - */ -/** - * @callback Close - * @param {(err: Error | null | undefined) => void} callback - */ -/** - * @template {IncomingMessage} RequestInternal - * @template {ServerResponse} ResponseInternal - * @typedef {object} AdditionalMethods - * @property {GetFilenameFromUrl} getFilenameFromUrl get filename from url - * @property {WaitUntilValid} waitUntilValid wait until valid - * @property {Invalidate} invalidate invalidate - * @property {Close} close close - * @property {Context} context context - */ -/** - * @template {IncomingMessage} [RequestInternal=IncomingMessage] - * @template {ServerResponse} [ResponseInternal=ServerResponse] - * @typedef {Middleware & AdditionalMethods} API - */ -/** - * @template T - * @template {keyof T} K - * @typedef {Omit & Partial} WithOptional - */ -/** - * @template T - * @template {keyof T} K - * @typedef {T & { [P in K]: NonNullable }} WithoutUndefined - */ -/** - * @template {IncomingMessage} [RequestInternal=IncomingMessage] - * @template {ServerResponse} [ResponseInternal=ServerResponse] - * @param {Compiler | MultiCompiler} compiler compiler - * @param {Options=} options options - * @returns {API} webpack dev middleware - */ -declare function wdm< - RequestInternal extends IncomingMessage = import("http").IncomingMessage, - ResponseInternal extends ServerResponse = ServerResponse, ->( - compiler: Compiler | MultiCompiler, - options?: Options | undefined, -): API; -declare namespace wdm { - export { hapiWrapper }; - export { koaWrapper }; - export { honoWrapper }; -} /** * @template S * @template O @@ -482,3 +484,4 @@ declare function honoWrapper< compiler: Compiler | MultiCompiler, options?: Options | undefined, ): (ctx: EXPECTED_ANY, next: EXPECTED_FUNCTION) => Promise | void; +export {}; diff --git a/types/utils/setupWriteToDisk.d.ts b/types/utils/setupWriteToDisk.d.ts index 5ffc520..ee94e8b 100644 --- a/types/utils/setupWriteToDisk.d.ts +++ b/types/utils/setupWriteToDisk.d.ts @@ -5,12 +5,6 @@ export type Compilation = import("@rspack/core").Compilation; export type DevServerOption = import("../index.js").DevServerOption; export type IncomingMessage = import("../index.js").IncomingMessage; export type ServerResponse = import("../index.js").ServerResponse; -/** @typedef {import("@rspack/core").Compiler} Compiler */ -/** @typedef {import("@rspack/core").MultiCompiler} MultiCompiler */ -/** @typedef {import("@rspack/core").Compilation} Compilation */ -/** @typedef {import("../index.js").DevServerOption} DevServerOption */ -/** @typedef {import("../index.js").IncomingMessage} IncomingMessage */ -/** @typedef {import("../index.js").ServerResponse} ServerResponse */ /** * @template {IncomingMessage} Request * @template {ServerResponse} Response