@rspack/dev-server 2.0.0-beta.2 → 2.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/client/type.d.ts +15 -0
- package/client/type.js +0 -0
- package/dist/131.js +105 -13
- package/dist/rslib-runtime.js +9 -0
- package/dist/server.d.ts +4 -3
- package/dist/types.d.ts +10 -10
- package/package.json +11 -12
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Use Rspack with a development server that provides live reloading. This should b
|
|
|
11
11
|
|
|
12
12
|
## Versions
|
|
13
13
|
|
|
14
|
-
- `2.x`: For Rspack v2
|
|
14
|
+
- `2.x`: For Rspack v2, see [v1 -> v2](./docs/migrate-v1-to-v2.md) for migration guide.
|
|
15
15
|
- `1.x`: For Rspack v1, see [v1.x - README](https://github.com/rstackjs/rspack-dev-server/tree/v1.x#rspackdev-server) for usage guide.
|
|
16
16
|
|
|
17
17
|
## Installation
|
package/client/type.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type LogLevel = false | true | 'none' | 'error' | 'warn' | 'info' | 'log' | 'verbose';
|
|
2
|
+
export type EXPECTED_ANY = any;
|
|
3
|
+
declare global {
|
|
4
|
+
const __resourceQuery: string;
|
|
5
|
+
const BUILD_HASH: string;
|
|
6
|
+
const RESOURCE_QUERY: string;
|
|
7
|
+
}
|
|
8
|
+
export interface CommunicationClient {
|
|
9
|
+
onOpen(fn: (...args: unknown[]) => void): void;
|
|
10
|
+
onClose(fn: (...args: unknown[]) => void): void;
|
|
11
|
+
onMessage(fn: (...args: unknown[]) => void): void;
|
|
12
|
+
}
|
|
13
|
+
export interface CommunicationClientConstructor {
|
|
14
|
+
new (url: string): CommunicationClient;
|
|
15
|
+
}
|
package/client/type.js
ADDED
|
File without changes
|
package/dist/131.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as __rspack_external_zlib from "zlib";
|
|
1
2
|
import { __webpack_require__ } from "./rslib-runtime.js";
|
|
2
3
|
import node_fs, { lstatSync, promises, readFileSync, realpathSync, statSync, unlinkSync } from "node:fs";
|
|
3
4
|
import { createRequire } from "node:module";
|
|
@@ -8,6 +9,94 @@ import { deprecate, promisify, styleText } from "node:util";
|
|
|
8
9
|
import ipaddr from "ipaddr.js";
|
|
9
10
|
import { createServer } from "node:net";
|
|
10
11
|
import { WebSocketServer } from "ws";
|
|
12
|
+
__webpack_require__.add({
|
|
13
|
+
"./node_modules/.pnpm/http-compression@1.1.2/node_modules/http-compression/src/index.js" (module, __unused_rspack_exports, __webpack_require__) {
|
|
14
|
+
const zlib = __webpack_require__("zlib");
|
|
15
|
+
const MIMES = /text|javascript|\/json|xml/i;
|
|
16
|
+
const noop = ()=>{};
|
|
17
|
+
const getChunkSize = (chunk, enc)=>chunk ? Buffer.byteLength(chunk, enc) : 0;
|
|
18
|
+
module.exports = ({ threshold = 1024, level = {
|
|
19
|
+
brotli: 0,
|
|
20
|
+
gzip: 1
|
|
21
|
+
}, brotli = true, gzip = true, mimes = MIMES } = {})=>{
|
|
22
|
+
const brotliOpts = 'object' == typeof brotli && brotli || {};
|
|
23
|
+
const gzipOpts = 'object' == typeof gzip && gzip || {};
|
|
24
|
+
if (brotli && !zlib.createBrotliCompress) brotli = false;
|
|
25
|
+
return (req, res, next = noop)=>{
|
|
26
|
+
const accept = req.headers['accept-encoding'];
|
|
27
|
+
const encoding = accept && (brotli && accept.match(/\bbr\b/) || gzip && accept.match(/\bgzip\b/) || [])[0];
|
|
28
|
+
if ('HEAD' === req.method || !encoding) return next();
|
|
29
|
+
let compress;
|
|
30
|
+
let pendingStatus;
|
|
31
|
+
let pendingListeners = [];
|
|
32
|
+
let started = false;
|
|
33
|
+
let size = 0;
|
|
34
|
+
function start() {
|
|
35
|
+
started = true;
|
|
36
|
+
size = 0 | res.getHeader('Content-Length') || size;
|
|
37
|
+
const compressible = mimes.test(String(res.getHeader('Content-Type') || 'text/plain'));
|
|
38
|
+
const cleartext = !res.getHeader('Content-Encoding');
|
|
39
|
+
const listeners = pendingListeners || [];
|
|
40
|
+
if (compressible && cleartext && size >= threshold) {
|
|
41
|
+
res.setHeader('Content-Encoding', encoding);
|
|
42
|
+
res.removeHeader('Content-Length');
|
|
43
|
+
compress = 'br' === encoding ? zlib.createBrotliCompress({
|
|
44
|
+
params: Object.assign({
|
|
45
|
+
[zlib.constants.BROTLI_PARAM_QUALITY]: level.brotli,
|
|
46
|
+
[zlib.constants.BROTLI_PARAM_SIZE_HINT]: size
|
|
47
|
+
}, brotliOpts)
|
|
48
|
+
}) : zlib.createGzip(Object.assign({
|
|
49
|
+
level: level.gzip
|
|
50
|
+
}, gzipOpts));
|
|
51
|
+
compress.on('data', (chunk)=>false === write.call(res, chunk) && compress.pause());
|
|
52
|
+
on.call(res, 'drain', ()=>compress.resume());
|
|
53
|
+
compress.on('end', ()=>end.call(res));
|
|
54
|
+
listeners.forEach((p)=>compress.on.apply(compress, p));
|
|
55
|
+
} else {
|
|
56
|
+
pendingListeners = null;
|
|
57
|
+
listeners.forEach((p)=>on.apply(res, p));
|
|
58
|
+
}
|
|
59
|
+
writeHead.call(res, pendingStatus || res.statusCode);
|
|
60
|
+
}
|
|
61
|
+
const { end, write, on, writeHead } = res;
|
|
62
|
+
res.writeHead = function(status, reason, headers) {
|
|
63
|
+
if ('string' != typeof reason) [headers, reason] = [
|
|
64
|
+
reason,
|
|
65
|
+
headers
|
|
66
|
+
];
|
|
67
|
+
if (headers) for(const i in headers)res.setHeader(i, headers[i]);
|
|
68
|
+
pendingStatus = status;
|
|
69
|
+
return this;
|
|
70
|
+
};
|
|
71
|
+
res.write = function(chunk, enc) {
|
|
72
|
+
size += getChunkSize(chunk, enc);
|
|
73
|
+
if (!started) start();
|
|
74
|
+
if (!compress) return write.apply(this, arguments);
|
|
75
|
+
return compress.write.apply(compress, arguments);
|
|
76
|
+
};
|
|
77
|
+
res.end = function(chunk, enc) {
|
|
78
|
+
if (arguments.length > 0 && 'function' != typeof chunk) size += getChunkSize(chunk, enc);
|
|
79
|
+
if (!started) start();
|
|
80
|
+
if (!compress) return end.apply(this, arguments);
|
|
81
|
+
return compress.end.apply(compress, arguments);
|
|
82
|
+
};
|
|
83
|
+
res.on = function(type, listener) {
|
|
84
|
+
if (pendingListeners && 'drain' === type) if (compress) compress.on(type, listener);
|
|
85
|
+
else pendingListeners.push([
|
|
86
|
+
type,
|
|
87
|
+
listener
|
|
88
|
+
]);
|
|
89
|
+
else on.call(this, type, listener);
|
|
90
|
+
return this;
|
|
91
|
+
};
|
|
92
|
+
next();
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
zlib (module) {
|
|
97
|
+
module.exports = __rspack_external_zlib;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
11
100
|
var external_node_util_namespaceObject = {};
|
|
12
101
|
__webpack_require__.r(external_node_util_namespaceObject);
|
|
13
102
|
__webpack_require__.d(external_node_util_namespaceObject, {
|
|
@@ -127,6 +216,8 @@ class WebsocketServer extends servers_BaseServer {
|
|
|
127
216
|
});
|
|
128
217
|
}
|
|
129
218
|
}
|
|
219
|
+
const src = __webpack_require__("./node_modules/.pnpm/http-compression@1.1.2/node_modules/http-compression/src/index.js");
|
|
220
|
+
var src_default = /*#__PURE__*/ __webpack_require__.n(src);
|
|
130
221
|
const { styleText: server_styleText } = external_node_util_namespaceObject;
|
|
131
222
|
const server_require = createRequire(import.meta.url);
|
|
132
223
|
if (!process.env.WEBPACK_SERVE) process.env.WEBPACK_SERVE = 'true';
|
|
@@ -142,7 +233,11 @@ const memoize = (fn)=>{
|
|
|
142
233
|
return result;
|
|
143
234
|
};
|
|
144
235
|
};
|
|
145
|
-
const
|
|
236
|
+
const getConnect = async ()=>{
|
|
237
|
+
const { connect } = await import("connect-next");
|
|
238
|
+
return connect;
|
|
239
|
+
};
|
|
240
|
+
const getServeStatic = memoize(()=>server_require('serve-static'));
|
|
146
241
|
const encodeOverlaySettings = (setting)=>'function' == typeof setting ? encodeURIComponent(setting.toString()) : setting;
|
|
147
242
|
const DEFAULT_ALLOWED_PROTOCOLS = /^(file|.+-extension):/i;
|
|
148
243
|
function parseHostnameFromHeader(header) {
|
|
@@ -840,7 +935,7 @@ class Server {
|
|
|
840
935
|
for (const webSocketProxy of webSocketProxies)this.server.on('upgrade', webSocketProxy.upgrade);
|
|
841
936
|
}
|
|
842
937
|
async setupApp() {
|
|
843
|
-
this.app = 'function' == typeof this.options.app ? await this.options.app() :
|
|
938
|
+
this.app = 'function' == typeof this.options.app ? await this.options.app() : (await getConnect())();
|
|
844
939
|
}
|
|
845
940
|
getStats(statsObj) {
|
|
846
941
|
const stats = Server.DEFAULT_STATS;
|
|
@@ -906,13 +1001,10 @@ class Server {
|
|
|
906
1001
|
next();
|
|
907
1002
|
}
|
|
908
1003
|
});
|
|
909
|
-
if (this.options.compress) {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
middleware: compression()
|
|
914
|
-
});
|
|
915
|
-
}
|
|
1004
|
+
if (this.options.compress) middlewares.push({
|
|
1005
|
+
name: 'compression',
|
|
1006
|
+
middleware: src_default()()
|
|
1007
|
+
});
|
|
916
1008
|
if (void 0 !== this.options.headers) middlewares.push({
|
|
917
1009
|
name: 'set-headers',
|
|
918
1010
|
middleware: this.setHeaders.bind(this)
|
|
@@ -1030,9 +1122,9 @@ class Server {
|
|
|
1030
1122
|
}
|
|
1031
1123
|
const staticOptions = this.options.static;
|
|
1032
1124
|
if (staticOptions.length > 0) for (const staticOption of staticOptions)for (const publicPath of staticOption.publicPath)middlewares.push({
|
|
1033
|
-
name: '
|
|
1125
|
+
name: 'serve-static',
|
|
1034
1126
|
path: publicPath,
|
|
1035
|
-
middleware:
|
|
1127
|
+
middleware: getServeStatic()(staticOption.directory, staticOption.staticOptions)
|
|
1036
1128
|
});
|
|
1037
1129
|
if (this.options.historyApiFallback) {
|
|
1038
1130
|
const connectHistoryApiFallback = server_require('connect-history-api-fallback');
|
|
@@ -1047,9 +1139,9 @@ class Server {
|
|
|
1047
1139
|
middleware: this.middleware
|
|
1048
1140
|
});
|
|
1049
1141
|
if (staticOptions.length > 0) for (const staticOption of staticOptions)for (const publicPath of staticOption.publicPath)middlewares.push({
|
|
1050
|
-
name: '
|
|
1142
|
+
name: 'serve-static',
|
|
1051
1143
|
path: publicPath,
|
|
1052
|
-
middleware:
|
|
1144
|
+
middleware: getServeStatic()(staticOption.directory, staticOption.staticOptions)
|
|
1053
1145
|
});
|
|
1054
1146
|
}
|
|
1055
1147
|
if (staticOptions.length > 0) {
|
package/dist/rslib-runtime.js
CHANGED
|
@@ -15,6 +15,15 @@ __webpack_require__.m = __webpack_modules__;
|
|
|
15
15
|
Object.assign(__webpack_require__.m, modules);
|
|
16
16
|
};
|
|
17
17
|
})();
|
|
18
|
+
(()=>{
|
|
19
|
+
__webpack_require__.n = (module)=>{
|
|
20
|
+
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
21
|
+
__webpack_require__.d(getter, {
|
|
22
|
+
a: getter
|
|
23
|
+
});
|
|
24
|
+
return getter;
|
|
25
|
+
};
|
|
26
|
+
})();
|
|
18
27
|
(()=>{
|
|
19
28
|
var getProto = Object.getPrototypeOf ? (obj)=>Object.getPrototypeOf(obj) : (obj)=>obj.__proto__;
|
|
20
29
|
var leafPrototypes;
|
package/dist/server.d.ts
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* Copyright (c) JS Foundation and other contributors
|
|
8
8
|
* https://github.com/webpack/webpack-dev-server/blob/main/LICENSE
|
|
9
9
|
*/
|
|
10
|
-
import type { BasicApplication, ClientConfiguration, ClientConnection, Compiler, ConnectHistoryApiFallbackOptions, DevMiddlewareContext, DevMiddlewareOptions, DevServer, EXPECTED_ANY,
|
|
11
|
-
|
|
10
|
+
import type { BasicApplication, ClientConfiguration, ClientConnection, Compiler, ConnectHistoryApiFallbackOptions, DevMiddlewareContext, DevMiddlewareOptions, DevServer, EXPECTED_ANY, FSWatcher, HTTPServer, Headers, Host, LiteralUnion, Middleware, MultiCompiler, MultiStats, NextFunction, Open, Port, ProxyConfigArray, Request, RequestHandler, Response, ServerConfiguration, ServerType, Socket, Static, Stats, StatsCompilation, StatsOptions, WatchFiles, WatchOptions, WebSocketServerConfiguration, WebSocketServerImplementation } from './types';
|
|
11
|
+
import type { ConnectApplication } from './types';
|
|
12
|
+
export interface Configuration<A extends BasicApplication = ConnectApplication, S extends HTTPServer = HTTPServer> {
|
|
12
13
|
ipc?: boolean | string;
|
|
13
14
|
host?: Host;
|
|
14
15
|
port?: Port;
|
|
@@ -31,7 +32,7 @@ export interface Configuration<A extends BasicApplication = ExpressApplication,
|
|
|
31
32
|
onListening?: (devServer: Server<A, S>) => void;
|
|
32
33
|
setupMiddlewares?: (middlewares: Middleware[], devServer: Server<A, S>) => Middleware[];
|
|
33
34
|
}
|
|
34
|
-
declare class Server<A extends BasicApplication =
|
|
35
|
+
declare class Server<A extends BasicApplication = ConnectApplication, S extends import('http').Server = HTTPServer> {
|
|
35
36
|
compiler: Compiler | MultiCompiler;
|
|
36
37
|
logger: ReturnType<Compiler['getInfrastructureLogger']>;
|
|
37
38
|
options: Configuration<A, S>;
|
package/dist/types.d.ts
CHANGED
|
@@ -6,10 +6,10 @@ export type { NetworkInterfaceInfo } from 'node:os';
|
|
|
6
6
|
export type { Compiler, DevServer, MultiCompiler, MultiStats, Stats, StatsCompilation, StatsOptions, } from '@rspack/core';
|
|
7
7
|
import type { FSWatcher, WatchOptions } from 'chokidar';
|
|
8
8
|
export type { FSWatcher, WatchOptions };
|
|
9
|
+
import type { Server as ConnectApplication, IncomingMessage as ConnectIncomingMessage } from 'connect-next';
|
|
10
|
+
export type { ConnectApplication };
|
|
9
11
|
import type { Options as ConnectHistoryApiFallbackOptions } from 'connect-history-api-fallback';
|
|
10
12
|
export type { ConnectHistoryApiFallbackOptions };
|
|
11
|
-
import type { Application as ExpressApplication, ErrorRequestHandler as ExpressErrorRequestHandler, Request as ExpressRequest, RequestHandler as ExpressRequestHandler, Response as ExpressResponse } from 'express';
|
|
12
|
-
export type { ExpressApplication };
|
|
13
13
|
import type { Options as HttpProxyMiddlewareOptions, Filter as HttpProxyMiddlewareOptionsFilter, RequestHandler } from 'http-proxy-middleware';
|
|
14
14
|
export type { RequestHandler };
|
|
15
15
|
export type { IPv6 } from 'ipaddr.js';
|
|
@@ -25,8 +25,8 @@ export type NextHandleFunction = (req: IncomingMessage, res: ServerResponse, nex
|
|
|
25
25
|
export type ErrorHandleFunction = (err: EXPECTED_ANY, req: IncomingMessage, res: ServerResponse, next: NextFunction) => void;
|
|
26
26
|
export type HandleFunction = SimpleHandleFunction | NextHandleFunction | ErrorHandleFunction;
|
|
27
27
|
export type ServerOptions = import('https').ServerOptions;
|
|
28
|
-
export type Request<T extends BasicApplication =
|
|
29
|
-
export type Response
|
|
28
|
+
export type Request<T extends BasicApplication = ConnectApplication> = T extends ConnectApplication ? ConnectIncomingMessage : IncomingMessage;
|
|
29
|
+
export type Response = ServerResponse;
|
|
30
30
|
export type DevMiddlewareOptions<T extends Request, U extends Response> = import('webpack-dev-middleware').Options<T, U>;
|
|
31
31
|
export type DevMiddlewareContext<T extends Request, U extends Response> = import('webpack-dev-middleware').Context<T, U>;
|
|
32
32
|
export type Host = LiteralUnion<'local-ip' | 'local-ipv4' | 'local-ipv6', string>;
|
|
@@ -57,8 +57,8 @@ export interface NormalizedStatic {
|
|
|
57
57
|
staticOptions: ServeStaticOptions;
|
|
58
58
|
watch: false | WatchOptions;
|
|
59
59
|
}
|
|
60
|
-
export type ServerType<A extends BasicApplication =
|
|
61
|
-
export interface ServerConfiguration<A extends BasicApplication =
|
|
60
|
+
export type ServerType<A extends BasicApplication = ConnectApplication, S extends import('http').Server = import('http').Server> = LiteralUnion<'http' | 'https' | 'http2', string> | ((serverOptions: ServerOptions, application: A) => S);
|
|
61
|
+
export interface ServerConfiguration<A extends BasicApplication = ConnectApplication, S extends import('http').Server = import('http').Server> {
|
|
62
62
|
type?: ServerType<A, S>;
|
|
63
63
|
options?: ServerOptions;
|
|
64
64
|
}
|
|
@@ -118,13 +118,13 @@ export type Headers = Array<{
|
|
|
118
118
|
key: string;
|
|
119
119
|
value: string;
|
|
120
120
|
}> | Record<string, string | string[]>;
|
|
121
|
-
export type MiddlewareHandler
|
|
122
|
-
export interface MiddlewareObject
|
|
121
|
+
export type MiddlewareHandler = (...args: EXPECTED_ANY[]) => EXPECTED_ANY;
|
|
122
|
+
export interface MiddlewareObject {
|
|
123
123
|
name?: string;
|
|
124
124
|
path?: string;
|
|
125
|
-
middleware: MiddlewareHandler
|
|
125
|
+
middleware: MiddlewareHandler;
|
|
126
126
|
}
|
|
127
|
-
export type Middleware
|
|
127
|
+
export type Middleware = MiddlewareObject | MiddlewareHandler;
|
|
128
128
|
export type BasicServer = import('net').Server | import('tls').Server;
|
|
129
129
|
export type OverlayMessageOptions = boolean | ((error: Error) => void);
|
|
130
130
|
declare function useFn(fn: NextHandleFunction): BasicApplication;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rspack/dev-server",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.4",
|
|
4
4
|
"description": "Development server for rspack",
|
|
5
5
|
"homepage": "https://rspack.rs",
|
|
6
6
|
"bugs": "https://github.com/rstackjs/rspack-dev-server/issues",
|
|
@@ -51,39 +51,38 @@
|
|
|
51
51
|
"@types/ws": "^8.18.1",
|
|
52
52
|
"chokidar": "^3.6.0",
|
|
53
53
|
"connect-history-api-fallback": "^2.0.0",
|
|
54
|
-
"
|
|
54
|
+
"connect-next": "^4.0.0",
|
|
55
55
|
"http-proxy-middleware": "^3.0.5",
|
|
56
56
|
"ipaddr.js": "^2.3.0",
|
|
57
57
|
"serve-index": "^1.9.2",
|
|
58
|
+
"serve-static": "^2.2.1",
|
|
58
59
|
"webpack-dev-middleware": "^7.4.5",
|
|
59
60
|
"ws": "^8.19.0"
|
|
60
61
|
},
|
|
61
62
|
"devDependencies": {
|
|
62
63
|
"@biomejs/biome": "^1.9.4",
|
|
63
|
-
"@hono/node-server": "^1.19.
|
|
64
|
+
"@hono/node-server": "^1.19.11",
|
|
64
65
|
"@rslib/core": "^0.19.6",
|
|
65
66
|
"@rspack/core": "2.0.0-beta.5",
|
|
66
67
|
"@rspack/plugin-react-refresh": "1.6.1",
|
|
67
|
-
"@rstest/core": "^0.
|
|
68
|
-
"@types/compression": "^1.8.1",
|
|
69
|
-
"@types/express": "5.0.6",
|
|
68
|
+
"@rstest/core": "^0.9.0",
|
|
70
69
|
"@types/mime-types": "3.0.1",
|
|
71
|
-
"@types/node": "^24.
|
|
70
|
+
"@types/node": "^24.12.0",
|
|
72
71
|
"@types/node-forge": "^1.3.14",
|
|
73
72
|
"@types/trusted-types": "^2.0.7",
|
|
74
73
|
"@types/ws": "8.18.1",
|
|
75
|
-
"compression": "^1.8.1",
|
|
76
|
-
"connect": "^3.7.0",
|
|
77
74
|
"cross-env": "^10.1.0",
|
|
78
75
|
"css-loader": "^7.1.4",
|
|
79
|
-
"
|
|
76
|
+
"express": "^5.2.1",
|
|
77
|
+
"hono": "^4.12.5",
|
|
78
|
+
"http-compression": "^1.1.2",
|
|
80
79
|
"http-proxy": "^1.18.1",
|
|
81
80
|
"launch-editor": "^2.13.1",
|
|
82
81
|
"nano-staged": "^0.9.0",
|
|
83
82
|
"open": "^11.0.0",
|
|
84
83
|
"p-retry": "^7.1.1",
|
|
85
84
|
"prettier": "3.8.1",
|
|
86
|
-
"puppeteer": "^24.
|
|
85
|
+
"puppeteer": "^24.38.0",
|
|
87
86
|
"react-refresh": "0.18.0",
|
|
88
87
|
"require-from-string": "^2.0.2",
|
|
89
88
|
"selfsigned": "^5.5.0",
|
|
@@ -101,7 +100,7 @@
|
|
|
101
100
|
"optional": true
|
|
102
101
|
}
|
|
103
102
|
},
|
|
104
|
-
"packageManager": "pnpm@10.
|
|
103
|
+
"packageManager": "pnpm@10.31.0",
|
|
105
104
|
"engines": {
|
|
106
105
|
"node": "^20.19.0 || >=22.12.0"
|
|
107
106
|
},
|