@bleedingdev/modern-js-server 3.2.0-ultramodern.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -0
  3. package/dist/cjs/createDevServer.js +102 -0
  4. package/dist/cjs/dev-tools/https/index.js +57 -0
  5. package/dist/cjs/dev-tools/watcher/dependencyTree.js +94 -0
  6. package/dist/cjs/dev-tools/watcher/index.js +143 -0
  7. package/dist/cjs/dev-tools/watcher/statsCache.js +95 -0
  8. package/dist/cjs/dev.js +111 -0
  9. package/dist/cjs/helpers/devOptions.js +61 -0
  10. package/dist/cjs/helpers/fileReader.js +53 -0
  11. package/dist/cjs/helpers/index.js +173 -0
  12. package/dist/cjs/helpers/mock.js +136 -0
  13. package/dist/cjs/helpers/repack.js +50 -0
  14. package/dist/cjs/helpers/utils.js +37 -0
  15. package/dist/cjs/index.js +36 -0
  16. package/dist/cjs/types.js +18 -0
  17. package/dist/esm/createDevServer.mjs +58 -0
  18. package/dist/esm/dev-tools/https/index.mjs +23 -0
  19. package/dist/esm/dev-tools/watcher/dependencyTree.mjs +57 -0
  20. package/dist/esm/dev-tools/watcher/index.mjs +91 -0
  21. package/dist/esm/dev-tools/watcher/statsCache.mjs +50 -0
  22. package/dist/esm/dev.mjs +77 -0
  23. package/dist/esm/helpers/devOptions.mjs +24 -0
  24. package/dist/esm/helpers/fileReader.mjs +19 -0
  25. package/dist/esm/helpers/index.mjs +65 -0
  26. package/dist/esm/helpers/mock.mjs +86 -0
  27. package/dist/esm/helpers/repack.mjs +16 -0
  28. package/dist/esm/helpers/utils.mjs +3 -0
  29. package/dist/esm/index.mjs +1 -0
  30. package/dist/esm/types.mjs +0 -0
  31. package/dist/esm-node/createDevServer.mjs +59 -0
  32. package/dist/esm-node/dev-tools/https/index.mjs +28 -0
  33. package/dist/esm-node/dev-tools/watcher/dependencyTree.mjs +58 -0
  34. package/dist/esm-node/dev-tools/watcher/index.mjs +93 -0
  35. package/dist/esm-node/dev-tools/watcher/statsCache.mjs +51 -0
  36. package/dist/esm-node/dev.mjs +78 -0
  37. package/dist/esm-node/helpers/devOptions.mjs +25 -0
  38. package/dist/esm-node/helpers/fileReader.mjs +20 -0
  39. package/dist/esm-node/helpers/index.mjs +67 -0
  40. package/dist/esm-node/helpers/mock.mjs +87 -0
  41. package/dist/esm-node/helpers/repack.mjs +18 -0
  42. package/dist/esm-node/helpers/utils.mjs +4 -0
  43. package/dist/esm-node/index.mjs +2 -0
  44. package/dist/esm-node/types.mjs +1 -0
  45. package/dist/types/createDevServer.d.ts +8 -0
  46. package/dist/types/dev-tools/https/index.d.ts +6 -0
  47. package/dist/types/dev-tools/watcher/dependencyTree.d.ts +28 -0
  48. package/dist/types/dev-tools/watcher/index.d.ts +17 -0
  49. package/dist/types/dev-tools/watcher/statsCache.d.ts +10 -0
  50. package/dist/types/dev.d.ts +9 -0
  51. package/dist/types/helpers/devOptions.d.ts +11 -0
  52. package/dist/types/helpers/fileReader.d.ts +3 -0
  53. package/dist/types/helpers/index.d.ts +15 -0
  54. package/dist/types/helpers/mock.d.ts +16 -0
  55. package/dist/types/helpers/repack.d.ts +2 -0
  56. package/dist/types/helpers/utils.d.ts +1 -0
  57. package/dist/types/index.d.ts +4 -0
  58. package/dist/types/types.d.ts +56 -0
  59. package/package.json +89 -0
  60. package/rslib.config.mts +4 -0
  61. package/rstest.config.mts +5 -0
@@ -0,0 +1,93 @@
1
+ import __rslib_shim_module__ from "node:module";
2
+ const require = /*#__PURE__*/ __rslib_shim_module__.createRequire(/*#__PURE__*/ (()=>import.meta.url)());
3
+ import { chokidar, fs } from "@modern-js/utils";
4
+ import path from "path";
5
+ import { DependencyTree } from "./dependencyTree.mjs";
6
+ import { StatsCache } from "./statsCache.mjs";
7
+ const defaultWatchOptions = {
8
+ ignoreInitial: true,
9
+ ignored: /api\/typings\/.*/
10
+ };
11
+ const getWatchedFiles = (watcher)=>{
12
+ const watched = watcher.getWatched();
13
+ const files = [];
14
+ Object.keys(watched).forEach((dir)=>{
15
+ const dirFiles = watched[dir];
16
+ if (!dirFiles) return;
17
+ dirFiles.forEach((fileName)=>{
18
+ files.push(path.join(dir, fileName));
19
+ });
20
+ });
21
+ return files;
22
+ };
23
+ const mergeWatchOptions = (options)=>{
24
+ const watchOptions = {
25
+ ...options
26
+ };
27
+ if (watchOptions) {
28
+ const { ignored } = watchOptions;
29
+ const finalIgnored = ignored ? [
30
+ defaultWatchOptions.ignored,
31
+ ...Array.isArray(ignored) ? ignored : [
32
+ ignored
33
+ ]
34
+ ] : ignored;
35
+ if (finalIgnored) watchOptions.ignored = finalIgnored;
36
+ }
37
+ const finalWatchOptions = {
38
+ ...defaultWatchOptions,
39
+ ...watchOptions
40
+ };
41
+ return finalWatchOptions;
42
+ };
43
+ class Watcher {
44
+ listen(files, options, callback) {
45
+ const watched = files.filter(Boolean);
46
+ const filenames = watched.map((filename)=>filename.replace(/\\/g, '/'));
47
+ const cache = new StatsCache();
48
+ const watcher = chokidar.watch(filenames, options);
49
+ watcher.on('ready', ()=>{
50
+ cache.add(getWatchedFiles(watcher));
51
+ });
52
+ watcher.on('change', (changed)=>{
53
+ if (!fs.existsSync(changed) || cache.isDiff(changed)) {
54
+ cache.refresh(changed);
55
+ callback(changed, 'change');
56
+ }
57
+ });
58
+ watcher.on('add', (changed)=>{
59
+ if (!cache.has(changed)) {
60
+ cache.add([
61
+ changed
62
+ ]);
63
+ callback(changed, 'add');
64
+ }
65
+ });
66
+ watcher.on('unlink', (changed)=>{
67
+ cache.del(changed);
68
+ callback(changed, 'unlink');
69
+ });
70
+ this.watcher = watcher;
71
+ }
72
+ createDepTree() {
73
+ this.dependencyTree = new DependencyTree();
74
+ }
75
+ updateDepTree() {
76
+ this.dependencyTree?.update(require.cache);
77
+ }
78
+ cleanDepCache(filepath) {
79
+ const node = this.dependencyTree?.getNode(filepath);
80
+ if (node && require.cache[filepath]) {
81
+ delete require.cache[filepath];
82
+ for (const parentNode of node.parent.values())this.cleanDepCache(parentNode.module.filename);
83
+ }
84
+ }
85
+ close() {
86
+ return this.watcher.close();
87
+ }
88
+ constructor(){
89
+ this.dependencyTree = null;
90
+ }
91
+ }
92
+ export default Watcher;
93
+ export { defaultWatchOptions, getWatchedFiles, mergeWatchOptions };
@@ -0,0 +1,51 @@
1
+ import "node:module";
2
+ import crypto_0 from "crypto";
3
+ import fs from "fs";
4
+ class StatsCache {
5
+ add(files) {
6
+ const { cachedHash, cachedSize } = this;
7
+ for (const filename of files)if (fs.existsSync(filename)) {
8
+ const stats = fs.statSync(filename);
9
+ if (stats.isFile() && !cachedHash[filename]) {
10
+ cachedHash[filename] = this.hash(stats, filename);
11
+ cachedSize[filename] = stats.size;
12
+ }
13
+ }
14
+ }
15
+ refresh(filename) {
16
+ const { cachedHash, cachedSize } = this;
17
+ if (fs.existsSync(filename)) {
18
+ const stats = fs.statSync(filename);
19
+ if (stats.isFile()) {
20
+ cachedHash[filename] = this.hash(stats, filename);
21
+ cachedSize[filename] = stats.size;
22
+ }
23
+ }
24
+ }
25
+ del(filename) {
26
+ if (this.cachedHash[filename]) {
27
+ delete this.cachedHash[filename];
28
+ delete this.cachedSize[filename];
29
+ }
30
+ }
31
+ isDiff(filename) {
32
+ const { cachedHash, cachedSize } = this;
33
+ const stats = fs.statSync(filename);
34
+ const hash = cachedHash[filename];
35
+ const size = cachedSize[filename];
36
+ if (stats.size !== size) return true;
37
+ if (this.hash(stats, filename) !== hash) return true;
38
+ return false;
39
+ }
40
+ has(filename) {
41
+ return Boolean(this.cachedHash[filename]);
42
+ }
43
+ hash(stats, filename) {
44
+ return crypto_0.createHash('md5').update(fs.readFileSync(filename)).digest('hex');
45
+ }
46
+ constructor(){
47
+ this.cachedHash = {};
48
+ this.cachedSize = {};
49
+ }
50
+ }
51
+ export { StatsCache };
@@ -0,0 +1,78 @@
1
+ import "node:module";
2
+ import { connectMid2HonoMid } from "@modern-js/server-core/node";
3
+ import { API_DIR, SHARED_DIR } from "@modern-js/utils";
4
+ import { getDevOptions, getMockMiddleware, initFileReader, onRepack, startWatcher } from "./helpers/index.mjs";
5
+ const devPlugin = (options, compiler)=>({
6
+ name: '@modern-js/plugin-dev',
7
+ setup (api) {
8
+ const { config, pwd, builder, builderDevServer } = options;
9
+ const closeCb = [];
10
+ const dev = getDevOptions(options.dev);
11
+ api.onPrepare(async ()=>{
12
+ const { middlewares: builderMiddlewares, close, connectWebSocket } = builderDevServer || {};
13
+ close && closeCb.push(close);
14
+ const { middlewares, distDirectory, nodeServer, apiDirectory, sharedDirectory, serverBase } = api.getServerContext();
15
+ connectWebSocket && nodeServer && connectWebSocket({
16
+ server: nodeServer
17
+ });
18
+ const hooks = api.getHooks();
19
+ builder?.onDevCompileDone(({ stats })=>{
20
+ if ('server' !== stats.toJson({
21
+ all: false
22
+ }).name) onRepack(distDirectory, hooks);
23
+ });
24
+ const { watchOptions } = config.server;
25
+ const watcher = startWatcher({
26
+ pwd,
27
+ distDir: distDirectory,
28
+ apiDir: apiDirectory || API_DIR,
29
+ sharedDir: sharedDirectory || SHARED_DIR,
30
+ watchOptions,
31
+ server: serverBase
32
+ });
33
+ closeCb.push(watcher.close.bind(watcher));
34
+ closeCb.length > 0 && nodeServer?.on('close', ()=>{
35
+ closeCb.forEach((cb)=>{
36
+ cb();
37
+ });
38
+ });
39
+ const before = [];
40
+ const after = [];
41
+ const { setupMiddlewares = [] } = dev;
42
+ setupMiddlewares.forEach((handler)=>{
43
+ handler({
44
+ unshift: (...handlers)=>before.unshift(...handlers),
45
+ push: (...handlers)=>after.push(...handlers)
46
+ }, {
47
+ sockWrite: ()=>{}
48
+ });
49
+ });
50
+ before.forEach((middleware, index)=>{
51
+ middlewares.push({
52
+ name: `before-dev-server-${index}`,
53
+ handler: connectMid2HonoMid(middleware)
54
+ });
55
+ });
56
+ const mockMiddleware = await getMockMiddleware(pwd);
57
+ middlewares.push({
58
+ name: 'mock-dev',
59
+ handler: mockMiddleware
60
+ });
61
+ builderMiddlewares && middlewares.push({
62
+ name: 'rsbuild-dev',
63
+ handler: connectMid2HonoMid(builderMiddlewares)
64
+ });
65
+ after.forEach((middleware, index)=>{
66
+ middlewares.push({
67
+ name: `after-dev-server-${index}`,
68
+ handler: connectMid2HonoMid(middleware)
69
+ });
70
+ });
71
+ middlewares.push({
72
+ name: 'init-file-reader',
73
+ handler: initFileReader(compiler)
74
+ });
75
+ });
76
+ }
77
+ });
78
+ export { devPlugin };
@@ -0,0 +1,25 @@
1
+ import "node:module";
2
+ const getDevOptions = (devOptions)=>{
3
+ const defaultOptions = {
4
+ https: false,
5
+ server: {}
6
+ };
7
+ return {
8
+ ...defaultOptions,
9
+ ...devOptions
10
+ };
11
+ };
12
+ const getDevAssetPrefix = (builder)=>new Promise((resolve)=>{
13
+ if (!builder) return resolve('');
14
+ builder?.onAfterCreateCompiler((params)=>{
15
+ let webCompiler;
16
+ webCompiler = 'compilers' in params.compiler ? params.compiler.compilers.find((c)=>'web' === c.name || 'client' === c.name) : params.compiler;
17
+ const publicPath = webCompiler?.options?.output?.publicPath;
18
+ if (publicPath && 'string' == typeof publicPath) {
19
+ const formatPublicPath = publicPath.replace(/^https?:\/\/[^/]+/, '');
20
+ return resolve(formatPublicPath);
21
+ }
22
+ return resolve('');
23
+ });
24
+ });
25
+ export { getDevAssetPrefix, getDevOptions };
@@ -0,0 +1,20 @@
1
+ import "node:module";
2
+ import { fileReader } from "@modern-js/runtime-utils/fileReader";
3
+ const initFileReader = (compiler)=>{
4
+ let isInit = false;
5
+ return async (ctx, next)=>{
6
+ if (isInit) return next();
7
+ isInit = true;
8
+ const { res } = ctx.env.node;
9
+ if (!compiler) {
10
+ fileReader.reset();
11
+ return next();
12
+ }
13
+ const resolvedCompiler = 'compilers' in compiler ? compiler.compilers[0] : compiler;
14
+ const outputFileSystem = resolvedCompiler?.outputFileSystem;
15
+ if (outputFileSystem) fileReader.reset(outputFileSystem);
16
+ else fileReader.reset();
17
+ return next();
18
+ };
19
+ };
20
+ export { initFileReader };
@@ -0,0 +1,67 @@
1
+ import __rslib_shim_module__ from "node:module";
2
+ const require = /*#__PURE__*/ __rslib_shim_module__.createRequire(/*#__PURE__*/ (()=>import.meta.url)());
3
+ import { AGGRED_DIR } from "@modern-js/server-core";
4
+ import { SERVER_BUNDLE_DIRECTORY, SERVER_DIR, logger } from "@modern-js/utils";
5
+ import path from "path";
6
+ import dev_tools_watcher, { mergeWatchOptions } from "../dev-tools/watcher/index.mjs";
7
+ import { initOrUpdateMockMiddlewares } from "./mock.mjs";
8
+ import { debug } from "./utils.mjs";
9
+ export * from "./devOptions.mjs";
10
+ export * from "./fileReader.mjs";
11
+ export * from "./mock.mjs";
12
+ export * from "./repack.mjs";
13
+ async function onServerChange({ pwd, filepath, event, server }) {
14
+ const { mock } = AGGRED_DIR;
15
+ const mockPath = path.normalize(path.join(pwd, mock));
16
+ const { hooks } = server;
17
+ if (filepath.startsWith(mockPath)) {
18
+ await initOrUpdateMockMiddlewares(pwd);
19
+ logger.info('Finish update the mock handlers');
20
+ } else try {
21
+ const fileChangeEvent = {
22
+ type: 'file-change',
23
+ payload: [
24
+ {
25
+ filename: filepath,
26
+ event
27
+ }
28
+ ]
29
+ };
30
+ await hooks.onReset.call({
31
+ event: fileChangeEvent
32
+ });
33
+ debug(`Finish reload server, trigger by ${filepath} ${event}`);
34
+ } catch (e) {
35
+ logger.error(e);
36
+ }
37
+ }
38
+ function startWatcher({ pwd, distDir, apiDir, sharedDir, watchOptions, server }) {
39
+ const { mock } = AGGRED_DIR;
40
+ const defaultWatched = [
41
+ `${mock}/**/*`,
42
+ `${SERVER_DIR}/**/*`,
43
+ `${apiDir}/**`,
44
+ `${sharedDir}/**/*`,
45
+ `${distDir}/${SERVER_BUNDLE_DIRECTORY}/*-server-loaders.js`
46
+ ];
47
+ const mergedWatchOptions = mergeWatchOptions(watchOptions);
48
+ const defaultWatchedPaths = defaultWatched.map((p)=>{
49
+ const finalPath = path.isAbsolute(p) ? p : path.join(pwd, p);
50
+ return path.normalize(finalPath);
51
+ });
52
+ const watcher = new dev_tools_watcher();
53
+ watcher.createDepTree();
54
+ watcher.listen(defaultWatchedPaths, mergedWatchOptions, (filepath, event)=>{
55
+ if (filepath.includes('-server-loaders.js')) return void delete require.cache[filepath];
56
+ watcher.updateDepTree();
57
+ watcher.cleanDepCache(filepath);
58
+ onServerChange({
59
+ pwd,
60
+ filepath,
61
+ event,
62
+ server
63
+ });
64
+ });
65
+ return watcher;
66
+ }
67
+ export { startWatcher };
@@ -0,0 +1,87 @@
1
+ import "node:module";
2
+ import node_path from "node:path";
3
+ import { AGGRED_DIR } from "@modern-js/server-core";
4
+ import { connectMockMid2HonoMid } from "@modern-js/server-core/node";
5
+ import { fs } from "@modern-js/utils";
6
+ import { match } from "path-to-regexp";
7
+ let mockAPIs = [];
8
+ let mockConfig;
9
+ const parseKey = (key)=>{
10
+ const _blank = ' ';
11
+ const splitted = key.split(_blank).filter(Boolean);
12
+ if (splitted.length > 1) {
13
+ const [method, pathname] = splitted;
14
+ return {
15
+ method: (method ?? 'get').toLowerCase(),
16
+ path: pathname ?? '/'
17
+ };
18
+ }
19
+ return {
20
+ method: 'get',
21
+ path: key
22
+ };
23
+ };
24
+ const getMockModule = async (pwd)=>{
25
+ const exts = [
26
+ '.ts',
27
+ '.js'
28
+ ];
29
+ let mockFilePath = '';
30
+ for (const ext of exts){
31
+ const maybeMatch = node_path.join(pwd, `${AGGRED_DIR.mock}/index${ext}`);
32
+ if (await fs.pathExists(maybeMatch)) {
33
+ mockFilePath = maybeMatch;
34
+ break;
35
+ }
36
+ }
37
+ if (!mockFilePath) return;
38
+ const { default: mockHandlers, config } = await import(mockFilePath);
39
+ const enable = config?.enable;
40
+ if (false === enable) return;
41
+ if (!mockHandlers) throw new Error(`Mock file ${mockFilePath} parsed failed!`);
42
+ return {
43
+ mockHandlers,
44
+ config
45
+ };
46
+ };
47
+ const getMatched = (request, mockApis)=>{
48
+ const { path: targetPathname, method: targetMethod } = request;
49
+ const matched = mockApis.find((mockApi)=>{
50
+ const { method, path: pathname } = mockApi;
51
+ if (method.toLowerCase() === targetMethod.toLowerCase()) return match(pathname, {
52
+ decode: decodeURIComponent
53
+ })(targetPathname);
54
+ return false;
55
+ });
56
+ return matched;
57
+ };
58
+ async function initOrUpdateMockMiddlewares(pwd) {
59
+ const mockModule = await getMockModule(pwd);
60
+ mockConfig = mockModule?.config;
61
+ mockAPIs = Object.entries(mockModule?.mockHandlers || {}).map(([key, handler])=>{
62
+ const { method, path } = parseKey(key);
63
+ return {
64
+ method,
65
+ path,
66
+ handler
67
+ };
68
+ });
69
+ }
70
+ async function getMockMiddleware(pwd) {
71
+ await initOrUpdateMockMiddlewares(pwd);
72
+ const mockMiddleware = async (c, next)=>{
73
+ if ('function' == typeof mockConfig?.enable) {
74
+ const isEnabled = mockConfig.enable(c.env.node.req, c.env.node.res);
75
+ if (!isEnabled) return next();
76
+ }
77
+ const matchedMockAPI = getMatched(c.req, mockAPIs);
78
+ if (matchedMockAPI) {
79
+ const { handler } = matchedMockAPI;
80
+ if ('function' == typeof handler) return await connectMockMid2HonoMid(handler)(c, next);
81
+ return c.json(handler);
82
+ }
83
+ return next();
84
+ };
85
+ return mockMiddleware;
86
+ }
87
+ export { getMatched, getMockMiddleware, initOrUpdateMockMiddlewares };
@@ -0,0 +1,18 @@
1
+ import __rslib_shim_module__ from "node:module";
2
+ const require = /*#__PURE__*/ __rslib_shim_module__.createRequire(/*#__PURE__*/ (()=>import.meta.url)());
3
+ import { fileReader } from "@modern-js/runtime-utils/fileReader";
4
+ const cleanSSRCache = (distDir)=>{
5
+ Object.keys(require.cache).forEach((key)=>{
6
+ if (key.startsWith(distDir)) delete require.cache[key];
7
+ });
8
+ };
9
+ const onRepack = (distDir, hooks)=>{
10
+ cleanSSRCache(distDir);
11
+ fileReader.reset();
12
+ hooks.onReset.call({
13
+ event: {
14
+ type: 'repack'
15
+ }
16
+ });
17
+ };
18
+ export { onRepack };
@@ -0,0 +1,4 @@
1
+ import "node:module";
2
+ import { createDebugger } from "@modern-js/utils";
3
+ const debug = createDebugger('server');
4
+ export { debug };
@@ -0,0 +1,2 @@
1
+ import "node:module";
2
+ export { createDevServer } from "./createDevServer.mjs";
@@ -0,0 +1 @@
1
+ import "node:module";
@@ -0,0 +1,8 @@
1
+ import type { ApplyPlugins, ModernDevServerOptions } from './types';
2
+ export declare function createDevServer(options: ModernDevServerOptions, applyPlugins: ApplyPlugins): Promise<{
3
+ server: (import("node:http").Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse> | import("node:https").Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse> | import("node:http2").Http2SecureServer<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse, typeof import("node:http2").Http2ServerRequest, typeof import("node:http2").Http2ServerResponse>) & {
4
+ getRequestListener: () => ReturnType<(handler: import("@modern-js/server-core/dist/types/types").RequestHandler) => (req: import("@modern-js/types/server").NodeRequest, res: import("@modern-js/types/server").NodeResponse) => Promise<void>>;
5
+ getRequestHandler: () => import("@modern-js/server-core/dist/types/types").RequestHandler;
6
+ };
7
+ afterListen: () => Promise<void>;
8
+ }>;
@@ -0,0 +1,6 @@
1
+ import type Buffer from 'buffer';
2
+ import type { DevServerHttpsOptions } from '../../types';
3
+ export declare const genHttpsOptions: (userOptions: DevServerHttpsOptions, pwd: string) => Promise<{
4
+ key?: Buffer | string;
5
+ cert?: Buffer | string;
6
+ }>;
@@ -0,0 +1,28 @@
1
+ export declare const defaultIgnores: string[];
2
+ export interface DependencyTreeOptions {
3
+ root: string;
4
+ ignore?: string[];
5
+ }
6
+ export interface TreeNode {
7
+ module: NodeModule;
8
+ parent: Set<TreeNode>;
9
+ children: Set<TreeNode>;
10
+ }
11
+ /**
12
+ * `require.cache` already is a dependency tree, however require cache's
13
+ * `module.parent` is the module that first required. so we have to implement
14
+ * a new tree which revisit the cache tree to find all parent node
15
+ */
16
+ export declare class DependencyTree {
17
+ private readonly tree;
18
+ private readonly ignore;
19
+ constructor();
20
+ getNode(path: string): TreeNode | undefined;
21
+ /**
22
+ * update dependency tree
23
+ *
24
+ * @param cache
25
+ */
26
+ update(cache: any): void;
27
+ private shouldIgnore;
28
+ }
@@ -0,0 +1,17 @@
1
+ import { type FSWatcher, type WatchOptions } from '@modern-js/utils';
2
+ export type WatchEvent = 'add' | 'change' | 'unlink';
3
+ export declare const defaultWatchOptions: {
4
+ ignoreInitial: boolean;
5
+ ignored: RegExp;
6
+ };
7
+ export declare const getWatchedFiles: (watcher: FSWatcher) => string[];
8
+ export declare const mergeWatchOptions: (options?: WatchOptions) => WatchOptions;
9
+ export default class Watcher {
10
+ private dependencyTree;
11
+ private watcher;
12
+ listen(files: string[], options: WatchOptions, callback: (changed: string, event: WatchEvent) => void): void;
13
+ createDepTree(): void;
14
+ updateDepTree(): void;
15
+ cleanDepCache(filepath: string): void;
16
+ close(): Promise<void>;
17
+ }
@@ -0,0 +1,10 @@
1
+ export declare class StatsCache {
2
+ private readonly cachedHash;
3
+ private readonly cachedSize;
4
+ add(files: string[]): void;
5
+ refresh(filename: string): void;
6
+ del(filename: string): void;
7
+ isDiff(filename: string): boolean;
8
+ has(filename: string): boolean;
9
+ private hash;
10
+ }
@@ -0,0 +1,9 @@
1
+ import type { BuilderInstance, Rspack } from '@modern-js/builder';
2
+ import type { ServerBaseOptions, ServerPlugin } from '@modern-js/server-core';
3
+ import type { ModernDevServerOptions } from './types';
4
+ type BuilderDevServer = Awaited<ReturnType<BuilderInstance['createDevServer']>>;
5
+ export type DevPluginOptions = ModernDevServerOptions<ServerBaseOptions> & {
6
+ builderDevServer?: BuilderDevServer;
7
+ };
8
+ export declare const devPlugin: (options: DevPluginOptions, compiler: Rspack.Compiler | Rspack.MultiCompiler | null) => ServerPlugin;
9
+ export {};
@@ -0,0 +1,11 @@
1
+ import type { BuilderInstance } from '@modern-js/builder';
2
+ import type { DevServerOptions } from '../types';
3
+ export declare const getDevOptions: (devOptions: DevServerOptions) => {
4
+ setupMiddlewares?: Array<(middlewares: {
5
+ unshift: (...handlers: import("@modern-js/types/server").RequestHandler[]) => void;
6
+ push: (...handlers: import("@modern-js/types/server").RequestHandler[]) => void;
7
+ }, server: import("@modern-js/types/server").ExposeServerApis) => void>;
8
+ https?: import("@modern-js/types/server/devServer").DevServerHttpsOptions;
9
+ server?: import("../types").DevServerConfig;
10
+ };
11
+ export declare const getDevAssetPrefix: (builder?: BuilderInstance) => Promise<string>;
@@ -0,0 +1,3 @@
1
+ import type { Rspack } from '@modern-js/builder';
2
+ import type { Middleware } from '@modern-js/server-core';
3
+ export declare const initFileReader: (compiler: Rspack.Compiler | Rspack.MultiCompiler | null) => Middleware;
@@ -0,0 +1,15 @@
1
+ import { type ServerBase } from '@modern-js/server-core';
2
+ import { type WatchOptions } from '@modern-js/utils';
3
+ import Watcher from '../dev-tools/watcher';
4
+ export * from './devOptions';
5
+ export * from './fileReader';
6
+ export * from './mock';
7
+ export * from './repack';
8
+ export declare function startWatcher({ pwd, distDir, apiDir, sharedDir, watchOptions, server, }: {
9
+ pwd: string;
10
+ distDir: string;
11
+ apiDir: string;
12
+ sharedDir: string;
13
+ watchOptions?: WatchOptions;
14
+ server: ServerBase;
15
+ }): Watcher;
@@ -0,0 +1,16 @@
1
+ import { type InternalRequest, type Middleware } from '@modern-js/server-core';
2
+ import type { NextFunction } from '@modern-js/types';
3
+ import type { NodeRequest, NodeResponse } from '@modern-js/types/server';
4
+ /** Types: Mock */
5
+ type MockHandler = {
6
+ data: any;
7
+ } | ((req: NodeRequest, res: NodeResponse, next: NextFunction) => Promise<void> | void);
8
+ type MockAPI = {
9
+ method: string;
10
+ path: string;
11
+ handler: MockHandler;
12
+ };
13
+ export declare const getMatched: (request: InternalRequest, mockApis: MockAPI[]) => MockAPI | undefined;
14
+ export declare function initOrUpdateMockMiddlewares(pwd: string): Promise<void>;
15
+ export declare function getMockMiddleware(pwd: string): Promise<Middleware>;
16
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { ServerPluginHooks } from '@modern-js/server-core';
2
+ export declare const onRepack: (distDir: string, hooks: ServerPluginHooks) => void;
@@ -0,0 +1 @@
1
+ export declare const debug: import("@modern-js/utils/compiled/debug").Debugger;
@@ -0,0 +1,4 @@
1
+ import type { DevServerOptions } from './types';
2
+ export { createDevServer } from './createDevServer';
3
+ export type { ApplyPlugins, CorsOptions, ModernDevServerOptions, } from './types';
4
+ export type SetupMiddlewares = DevServerOptions['setupMiddlewares'];
@@ -0,0 +1,56 @@
1
+ import type { Server as NodeServer } from 'node:http';
2
+ import type { Http2SecureServer } from 'node:http2';
3
+ import type { BuilderInstance } from '@modern-js/builder';
4
+ import type { ServerBase, ServerBaseOptions, ServerPlugin } from '@modern-js/server-core';
5
+ import type { DevServerHttpsOptions, ExposeServerApis, RequestHandler } from '@modern-js/types';
6
+ export type { DevServerHttpsOptions };
7
+ type StaticOrigin = boolean | string | RegExp | Array<boolean | string | RegExp>;
8
+ type CustomOrigin = (requestOrigin: string | undefined, callback: (err: Error | null, origin?: StaticOrigin) => void) => void;
9
+ export interface CorsOptions {
10
+ /**
11
+ * @default '*''
12
+ */
13
+ origin?: StaticOrigin | CustomOrigin | undefined;
14
+ }
15
+ export interface DevServerConfig {
16
+ /**
17
+ * Configure CORS for the dev server.
18
+ * - object: enable CORS with the specified options.
19
+ * - true: enable CORS with default options (allow all origins, not recommended).
20
+ * - false: disable CORS.
21
+ * @default
22
+ * ```js
23
+ * { origin: defaultAllowedOrigins }
24
+ * ```
25
+ * where `defaultAllowedOrigins` includes:
26
+ * - `localhost`
27
+ * - `127.0.0.1`
28
+ *
29
+ * @link https://github.com/expressjs/cors
30
+ */
31
+ cors?: boolean | CorsOptions;
32
+ }
33
+ export type DevServerOptions = {
34
+ /** Provides the ability to execute a custom function and apply custom middlewares */
35
+ setupMiddlewares?: Array<(
36
+ /** Order: `devServer.before` => `unshift` => internal middlewares => `push` => `devServer.after` */
37
+ middlewares: {
38
+ /** Use the `unshift` method if you want to run a middleware before all other middlewares */
39
+ unshift: (...handlers: RequestHandler[]) => void;
40
+ /** Use the `push` method if you want to run a middleware after all other middlewares */
41
+ push: (...handlers: RequestHandler[]) => void;
42
+ }, server: ExposeServerApis) => void>;
43
+ /** Whether to enable hot reload. */
44
+ https?: DevServerHttpsOptions;
45
+ /** Dev server specific options. */
46
+ server?: DevServerConfig;
47
+ };
48
+ export type ExtraOptions = {
49
+ dev: DevServerOptions;
50
+ runCompile?: boolean;
51
+ serverConfigPath: string;
52
+ builder?: BuilderInstance;
53
+ plugins?: ServerPlugin[];
54
+ };
55
+ export type ModernDevServerOptions<O extends ServerBaseOptions = ServerBaseOptions> = O & ExtraOptions;
56
+ export type ApplyPlugins<O extends ServerBaseOptions = ServerBaseOptions> = (server: ServerBase, options: ModernDevServerOptions<O>, nodeServer?: NodeServer | Http2SecureServer) => Promise<void>;