@modern-js/plugin-devtools 2.49.3 → 2.50.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.
package/dist/cli.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { AppTools, CliPlugin } from '@modern-js/app-tools';
2
2
  import { ClientDefinition } from '@modern-js/devtools-kit/node';
3
- import { DevtoolsPluginOptions } from './config';
3
+ import { DevtoolsPluginOptions } from './options';
4
4
  export type { DevtoolsPluginOptions };
5
5
  export type DevtoolsPlugin = CliPlugin<AppTools> & {
6
6
  setClientDefinition: (def: ClientDefinition) => void;
package/dist/cli.js CHANGED
@@ -35,14 +35,27 @@ module.exports = __toCommonJS(cli_exports);
35
35
  var import_http = __toESM(require("http"));
36
36
  var import_path = __toESM(require("path"));
37
37
  var import_assert = __toESM(require("assert"));
38
+ var import_url = require("url");
39
+ var import_lodash = __toESM(require("@modern-js/utils/lodash"));
38
40
  var import_utils = require("@modern-js/utils");
39
- var import_serve_static = __toESM(require("serve-static"));
41
+ var import_hono = require("hono");
42
+ var import_node_server = require("@hono/node-server");
43
+ var import_serve_static = require("@hono/node-server/serve-static");
40
44
  var import_node = require("@modern-js/devtools-kit/node");
41
- var import_config = require("./config");
45
+ var import_valtio = require("valtio");
46
+ var import_options = require("./options");
42
47
  var import_rpc = require("./rpc");
43
48
  var import_socket = require("./utils/socket");
49
+ var import_config = require("./utils/config");
44
50
  const devtoolsPlugin = (inlineOptions = {}) => {
45
- const ctx = (0, import_config.resolveContext)(inlineOptions);
51
+ const ctx = (0, import_valtio.proxy)((0, import_options.resolveContext)(inlineOptions));
52
+ let watcher = null;
53
+ const closeWatcher = () => {
54
+ if (!watcher)
55
+ return;
56
+ watcher.close();
57
+ watcher = null;
58
+ };
46
59
  return {
47
60
  name: "@modern-js/plugin-devtools",
48
61
  usePlugins: [],
@@ -59,15 +72,41 @@ const devtoolsPlugin = (inlineOptions = {}) => {
59
72
  });
60
73
  const rpc = await (0, import_rpc.setupClientConnection)({
61
74
  api,
62
- server: socketServer,
63
- def: ctx.def
75
+ ctx,
76
+ server: socketServer
64
77
  });
65
78
  return {
66
- prepare: rpc.hooks.prepare,
79
+ async prepare() {
80
+ await rpc.hooks.prepare();
81
+ const appConfig = api.useConfigContext();
82
+ const appCtx = api.useAppContext();
83
+ const { devtools: options = {} } = appConfig;
84
+ (0, import_options.updateContext)(ctx, options);
85
+ const basename = `${ctx.def.name.shortName}.runtime.json`;
86
+ const watcher2 = import_utils.chokidar.watch((0, import_config.getConfigFilenames)(basename), {
87
+ cwd: appCtx.appDirectory,
88
+ ignorePermissionErrors: true
89
+ });
90
+ const refreshStoragePreset = async () => {
91
+ const configs = await (0, import_config.loadConfigFiles)(basename, appCtx.appDirectory);
92
+ if (!configs)
93
+ return;
94
+ ctx.storagePresets = [];
95
+ (0, import_options.updateContext)(ctx, ...configs);
96
+ };
97
+ watcher2.on("add", refreshStoragePreset);
98
+ watcher2.on("change", refreshStoragePreset);
99
+ watcher2.on("unlink", refreshStoragePreset);
100
+ },
67
101
  modifyFileSystemRoutes: rpc.hooks.modifyFileSystemRoutes,
102
+ afterCreateCompiler: rpc.hooks.afterCreateCompiler,
68
103
  beforeRestart() {
104
+ closeWatcher();
69
105
  return new Promise((resolve, reject) => httpServer.instance.close((err) => err ? reject(err) : resolve()));
70
106
  },
107
+ beforeExit() {
108
+ closeWatcher();
109
+ },
71
110
  modifyServerRoutes({ routes }) {
72
111
  routes.push({
73
112
  urlPath: "/sw-proxy.js",
@@ -79,13 +118,18 @@ const devtoolsPlugin = (inlineOptions = {}) => {
79
118
  routes
80
119
  };
81
120
  },
82
- config() {
83
- var _api_useConfigContext_devtools;
84
- const config = (_api_useConfigContext_devtools = api.useConfigContext().devtools) !== null && _api_useConfigContext_devtools !== void 0 ? _api_useConfigContext_devtools : {};
85
- Object.assign(ctx, (0, import_config.resolveContext)(ctx, config));
121
+ async config() {
86
122
  import_utils.logger.info(`${ctx.def.name.formalName} DevTools is enabled`);
87
123
  const swProxyEntry = require.resolve("@modern-js/devtools-client/sw-proxy");
88
- const serializedOptions = JSON.stringify(ctx);
124
+ const clientOptions = import_lodash.default.pick(ctx, [
125
+ "def",
126
+ "endpoint",
127
+ "dataSource"
128
+ ]);
129
+ Object.assign(clientOptions, {
130
+ __keep: true
131
+ });
132
+ const serializedOptions = JSON.stringify(clientOptions);
89
133
  const tags = [
90
134
  {
91
135
  tag: "script",
@@ -140,11 +184,20 @@ const devtoolsPlugin = (inlineOptions = {}) => {
140
184
  devServer: {
141
185
  proxy: {
142
186
  [import_node.ROUTE_BASENAME]: {
143
- target: `http://localhost:${httpServer.port}`,
187
+ target: `http://127.0.0.1:${httpServer.port}`,
144
188
  pathRewrite: {
145
189
  [`^${import_node.ROUTE_BASENAME}`]: ""
146
190
  },
147
- ws: true
191
+ ws: true,
192
+ onProxyReq(proxyReq, req) {
193
+ const addrInfo = req.socket.address();
194
+ if ("address" in addrInfo) {
195
+ const { address } = addrInfo;
196
+ proxyReq.setHeader("X-Forwarded-For", address);
197
+ } else {
198
+ proxyReq.removeHeader("X-Forwarded-For");
199
+ }
200
+ }
148
201
  }
149
202
  }
150
203
  }
@@ -157,24 +210,71 @@ const devtoolsPlugin = (inlineOptions = {}) => {
157
210
  };
158
211
  var cli_default = devtoolsPlugin;
159
212
  const setupHttpServer = async () => {
213
+ const app = new import_hono.Hono();
160
214
  const port = await (0, import_utils.getPort)(8782, {
161
215
  slient: true
162
216
  });
163
217
  const clientServeDir = import_path.default.resolve(require.resolve("@modern-js/devtools-client/package.json"), "../dist");
164
- const serveMiddleware = (0, import_serve_static.default)(clientServeDir);
165
- const instance = import_http.default.createServer((req, res) => {
166
- const usePageNotFound = () => {
167
- res.write("404");
168
- res.statusCode = 404;
169
- res.end();
170
- };
171
- const useMainRoute = () => {
172
- req.url = "/html/client/index.html";
173
- serveMiddleware(req, res, usePageNotFound);
174
- };
175
- serveMiddleware(req, res, useMainRoute);
218
+ const handleCookieApi = async (c) => {
219
+ const raw = c.req.header("Cookie");
220
+ const { parse } = await import("cookie-es");
221
+ const cookies = raw ? parse(raw) : {};
222
+ const body = await c.req.json().catch(() => null);
223
+ if (body === null || body === void 0 ? void 0 : body.setCookies) {
224
+ const { setCookies } = body;
225
+ (0, import_assert.default)(typeof setCookies === "object", "setCookies should be object");
226
+ for (const [k, v] of Object.entries(setCookies)) {
227
+ (0, import_assert.default)(typeof v === "string");
228
+ const expires = new Date(Date.now() + 30 * 24 * 36e5).toUTCString();
229
+ cookies[k] = v;
230
+ c.header("Set-Cookie", `${k}=${v}; Expires=${expires}; Path=/`, {
231
+ append: true
232
+ });
233
+ }
234
+ }
235
+ return c.json({
236
+ cookies
237
+ });
238
+ };
239
+ app.get("/api/cookies", handleCookieApi);
240
+ app.post("/api/cookies", handleCookieApi);
241
+ app.use(
242
+ "/static/*",
243
+ // Workaround for https://github.com/honojs/node-server/blob/dd0e0cd160b0b8f18abbcb28c5f5c39b72105d98/src/serve-static.ts#L56
244
+ (0, import_serve_static.serveStatic)({
245
+ root: import_path.default.relative(process.cwd(), clientServeDir)
246
+ })
247
+ );
248
+ app.get(":filename{.+\\.hot-update\\.\\w+$}", async (c) => {
249
+ if (process.env.NODE_ENV !== "development") {
250
+ return c.text("Not found", 404);
251
+ }
252
+ const filename = c.req.param("filename");
253
+ const target = new import_url.URL(filename, "http://127.0.0.1:8780");
254
+ const { body, headers, status } = await fetch(target.href);
255
+ const newResp = c.newResponse(body, {
256
+ headers,
257
+ status
258
+ });
259
+ if (newResp.headers.get("content-encoding") === "gzip") {
260
+ newResp.headers.delete("content-encoding");
261
+ }
262
+ return newResp;
263
+ });
264
+ app.get("*", async (c) => {
265
+ const filename = import_path.default.resolve(clientServeDir, "html/client/index.html");
266
+ const content = await import_utils.fs.readFile(filename, "utf-8");
267
+ return c.html(content);
268
+ });
269
+ const instance = (0, import_node_server.serve)({
270
+ fetch: app.fetch,
271
+ port,
272
+ hostname: "127.0.0.1",
273
+ serverOptions: {
274
+ allowHTTP1: true
275
+ }
176
276
  });
177
- instance.listen(port);
277
+ (0, import_assert.default)(instance instanceof import_http.default.Server, "instance should be http.Server");
178
278
  return {
179
279
  instance,
180
280
  port
@@ -0,0 +1,8 @@
1
+ import { DevtoolsContext } from '@modern-js/devtools-kit/node';
2
+ export interface DevtoolsPluginOptions {
3
+ enable?: boolean;
4
+ endpoint?: string;
5
+ dataSource?: string;
6
+ }
7
+ export declare const resolveContext: (...sources: Partial<DevtoolsContext>[]) => DevtoolsContext;
8
+ export declare const updateContext: (context: DevtoolsContext, ...sources: Partial<DevtoolsContext>[]) => void;
@@ -16,22 +16,21 @@ var __copyProps = (to, from, except, desc) => {
16
16
  return to;
17
17
  };
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var config_exports = {};
20
- __export(config_exports, {
21
- resolveContext: () => resolveContext
19
+ var options_exports = {};
20
+ __export(options_exports, {
21
+ resolveContext: () => resolveContext,
22
+ updateContext: () => updateContext
22
23
  });
23
- module.exports = __toCommonJS(config_exports);
24
+ module.exports = __toCommonJS(options_exports);
24
25
  var import_node = require("@modern-js/devtools-kit/node");
25
26
  const resolveContext = (...sources) => {
26
27
  const ret = {
27
28
  enable: process.env.NODE_ENV === "development",
28
29
  dataSource: `${import_node.ROUTE_BASENAME}/rpc`,
29
30
  endpoint: import_node.ROUTE_BASENAME,
30
- def: new import_node.ClientDefinition()
31
+ def: new import_node.ClientDefinition(),
32
+ storagePresets: []
31
33
  };
32
- Object.assign(ret, {
33
- __keep: true
34
- });
35
34
  for (const opts of sources) {
36
35
  var _opts_enable;
37
36
  ret.enable = (_opts_enable = opts.enable) !== null && _opts_enable !== void 0 ? _opts_enable : ret.enable;
@@ -41,10 +40,15 @@ const resolveContext = (...sources) => {
41
40
  ret.endpoint = (_opts_endpoint = opts.endpoint) !== null && _opts_endpoint !== void 0 ? _opts_endpoint : ret.endpoint;
42
41
  var _opts_def;
43
42
  ret.def = (_opts_def = opts.def) !== null && _opts_def !== void 0 ? _opts_def : ret.def;
43
+ opts.storagePresets && ret.storagePresets.push(...opts.storagePresets);
44
44
  }
45
45
  return ret;
46
46
  };
47
+ const updateContext = (context, ...sources) => {
48
+ Object.assign(context, resolveContext(context, ...sources));
49
+ };
47
50
  // Annotate the CommonJS export names for ESM import in node:
48
51
  0 && (module.exports = {
49
- resolveContext
52
+ resolveContext,
53
+ updateContext
50
54
  });
@@ -1,11 +1,11 @@
1
- import { ClientDefinition, type ClientFunctions, type ServerFunctions } from '@modern-js/devtools-kit/node';
1
+ import { type ClientFunctions, type ServerFunctions, DevtoolsContext } from '@modern-js/devtools-kit/node';
2
2
  import type { RsbuildPlugin } from '@modern-js/uni-builder';
3
3
  import { CliPluginAPI, InjectedHooks } from '../types';
4
4
  import { SocketServer } from '../utils/socket';
5
5
  export interface SetupClientConnectionOptions {
6
6
  api: CliPluginAPI;
7
7
  server: SocketServer;
8
- def: ClientDefinition;
8
+ ctx: DevtoolsContext;
9
9
  }
10
10
  export declare const setupClientConnection: (options: SetupClientConnectionOptions) => Promise<{
11
11
  client: import("birpc").BirpcReturn<ClientFunctions, ServerFunctions>;
package/dist/rpc/index.js CHANGED
@@ -31,15 +31,96 @@ __export(rpc_exports, {
31
31
  setupClientConnection: () => setupClientConnection
32
32
  });
33
33
  module.exports = __toCommonJS(rpc_exports);
34
- var import_lodash = __toESM(require("@modern-js/utils/lodash"));
34
+ var import_path = __toESM(require("path"));
35
+ var import_buffer = require("buffer");
35
36
  var import_node = require("@modern-js/devtools-kit/node");
37
+ var import_lodash = __toESM(require("@modern-js/utils/lodash"));
36
38
  var import_birpc = require("birpc");
37
39
  var flatted = __toESM(require("flatted"));
38
- var import_p_defer = __toESM(require("p-defer"));
40
+ var import_valtio = require("valtio");
41
+ var import_utils = require("@modern-js/utils");
39
42
  var import_module = require("../utils/module");
43
+ var import_state = require("../state");
44
+ const resolveDependencies = async (rootPath) => {
45
+ const ret = {};
46
+ const resolveExprs = {
47
+ react: [
48
+ rootPath,
49
+ "react/package.json"
50
+ ],
51
+ "@modern-js/app-tools": [
52
+ rootPath,
53
+ "@modern-js/app-tools/package.json"
54
+ ],
55
+ "@edenx/app-tools": [
56
+ rootPath,
57
+ "@edenx/app-tools/package.json"
58
+ ],
59
+ webpack: [
60
+ rootPath,
61
+ "@modern-js/app-tools",
62
+ "@modern-js/uni-builder",
63
+ "@rsbuild/webpack",
64
+ "webpack/package.json"
65
+ ],
66
+ "@rspack/core": [
67
+ rootPath,
68
+ "@modern-js/uni-builder",
69
+ "@rsbuild/core",
70
+ "@rspack/core/package.json"
71
+ ],
72
+ "@rsdoctor/rspack-plugin": [
73
+ rootPath,
74
+ "@rsdoctor/rspack-plugin/package.json"
75
+ ],
76
+ "@rsdoctor/webpack-plugin": [
77
+ rootPath,
78
+ "@rsdoctor/webpack-plugin/package.json"
79
+ ],
80
+ "@web-doctor/webpack-plugin": [
81
+ rootPath,
82
+ "@web-doctor/webpack-plugin/package.json"
83
+ ],
84
+ "@web-doctor/rspack-plugin": [
85
+ rootPath,
86
+ "@web-doctor/rspack-plugin/package.json"
87
+ ],
88
+ "@web-doctor/webpack-plugin(builder)": [
89
+ rootPath,
90
+ "@edenx/builder-plugin-web-doctor",
91
+ "@web-doctor/webpack-plugin/package.json"
92
+ ],
93
+ "@web-doctor/rspack-plugin(builder)": [
94
+ rootPath,
95
+ "@edenx/builder-plugin-web-doctor",
96
+ "@web-doctor/rspack-plugin/package.json"
97
+ ],
98
+ "@rsdoctor/core": [
99
+ rootPath,
100
+ "@rsdoctor/core/package.json"
101
+ ]
102
+ };
103
+ for (const [name, expr] of Object.entries(resolveExprs)) {
104
+ try {
105
+ ret[name] = (0, import_module.requireModule)(expr).version;
106
+ } catch {
107
+ }
108
+ }
109
+ return ret;
110
+ };
111
+ const getDoctorOverview = async (ctx) => {
112
+ const manifestPath = await (0, import_node.findManifest)(ctx.distDirectory);
113
+ const json = await (0, import_node.parseManifest)(require(manifestPath));
114
+ return {
115
+ numModules: json.data.moduleGraph.modules.length,
116
+ numChunks: json.data.chunkGraph.chunks.length,
117
+ numPackages: json.data.packageGraph.packages.length,
118
+ summary: json.data.summary,
119
+ errors: json.data.errors
120
+ };
121
+ };
40
122
  const setupClientConnection = async (options) => {
41
- const { api, server, def } = options;
42
- const _fileSystemRoutesMap = {};
123
+ const { api, server, ctx } = options;
43
124
  let handleMessage = null;
44
125
  const onceConnection = new Promise((resolve) => {
45
126
  server.on("connection", (ws) => {
@@ -47,151 +128,106 @@ const setupClientConnection = async (options) => {
47
128
  ws.on("message", (data, isBinary) => handleMessage === null || handleMessage === void 0 ? void 0 : handleMessage(data, isBinary));
48
129
  });
49
130
  });
50
- const deferred = {
51
- prepare: (0, import_p_defer.default)(),
52
- builder: {
53
- context: (0, import_p_defer.default)(),
54
- config: {
55
- resolved: (0, import_p_defer.default)(),
56
- transformed: (0, import_p_defer.default)()
57
- }
58
- },
59
- bundler: {
60
- config: {
61
- resolved: (0, import_p_defer.default)(),
62
- transformed: (0, import_p_defer.default)()
131
+ if ("resolve" in import_state.$resolvers.context) {
132
+ import_state.$resolvers.context.resolve(ctx);
133
+ }
134
+ import_state.$state.context = ctx;
135
+ (0, import_valtio.subscribe)(import_state.$state, (ops) => {
136
+ clientConn.applyStateOperations.asEvent(ops);
137
+ });
138
+ const validateSafeToOpen = (filename) => {
139
+ const { appDirectory } = api.useAppContext();
140
+ const resolved = import_path.default.resolve(appDirectory, filename);
141
+ for (const preset of ctx.storagePresets) {
142
+ if (import_path.default.resolve(appDirectory, preset.filename) === resolved) {
143
+ return true;
63
144
  }
64
- },
65
- compileTimeCost: (0, import_p_defer.default)()
145
+ }
146
+ return false;
66
147
  };
67
148
  const serverFunctions = {
68
- async getFrameworkConfig() {
69
- await deferred.prepare.promise;
70
- return api.useConfigContext();
71
- },
72
- async getTransformedFrameworkConfig() {
73
- await deferred.prepare.promise;
74
- return api.useResolvedConfigContext();
75
- },
76
- async getBuilderConfig() {
77
- return deferred.builder.config.resolved.promise;
78
- },
79
- async getTransformedBuilderConfig() {
80
- return deferred.builder.config.transformed.promise;
81
- },
82
- async getBundlerConfigs() {
83
- return deferred.bundler.config.resolved.promise;
149
+ echo(content) {
150
+ return content;
84
151
  },
85
- async getTransformedBundlerConfigs() {
86
- return deferred.bundler.config.transformed.promise;
152
+ async pullExportedState() {
153
+ (0, import_node.extractSettledOperations)(import_state.$state).then((ops) => {
154
+ clientConn.applyStateOperations.asEvent(ops);
155
+ });
156
+ return import_state.$state;
87
157
  },
88
- async getAppContext() {
89
- await deferred.prepare.promise;
90
- const ctx = {
91
- ...api.useAppContext()
158
+ async createTemporaryStoragePreset() {
159
+ var _config;
160
+ const appCtx = api.useAppContext();
161
+ const basename = `${ctx.def.name.shortName}.runtime.json`;
162
+ const filename = import_path.default.resolve(appCtx.appDirectory, basename);
163
+ const id = (0, import_utils.nanoid)();
164
+ const name = `New Preset ${id.slice(0, 6)}`;
165
+ const config = {};
166
+ if (await import_utils.fs.pathExists(filename)) {
167
+ Object.assign(config, await import_utils.fs.readJSON(filename));
168
+ }
169
+ const newPreset = {
170
+ name,
171
+ id,
172
+ cookie: {},
173
+ localStorage: {},
174
+ sessionStorage: {}
92
175
  };
93
- return import_lodash.default.omit(ctx, [
94
- "builder",
95
- "serverInternalPlugins"
96
- ]);
97
- },
98
- async getFileSystemRoutes(entryName) {
99
- var _fileSystemRoutesMap_entryName;
100
- return (_fileSystemRoutesMap_entryName = _fileSystemRoutesMap[entryName]) !== null && _fileSystemRoutesMap_entryName !== void 0 ? _fileSystemRoutesMap_entryName : [];
101
- },
102
- async getBuilderContext() {
103
- const ctx = await deferred.builder.context.promise;
104
- return ctx;
176
+ (_config = config).storagePresets || (_config.storagePresets = []);
177
+ config.storagePresets.push(newPreset);
178
+ await import_utils.fs.outputJSON(filename, config, {
179
+ spaces: 2
180
+ });
181
+ return newPreset;
105
182
  },
106
- async getDependencies() {
107
- const ctx = await deferred.builder.context.promise;
108
- const ret = {};
109
- const resolveExprs = {
110
- react: [
111
- ctx.rootPath,
112
- "react/package.json"
113
- ],
114
- "@modern-js/app-tools": [
115
- ctx.rootPath,
116
- "@modern-js/app-tools/package.json"
117
- ],
118
- "@edenx/app-tools": [
119
- ctx.rootPath,
120
- "@edenx/app-tools/package.json"
121
- ],
122
- webpack: [
123
- ctx.rootPath,
124
- "@modern-js/app-tools",
125
- "@modern-js/uni-builder",
126
- "@rsbuild/webpack",
127
- "webpack/package.json"
128
- ],
129
- "@rspack/core": [
130
- ctx.rootPath,
131
- "@modern-js/uni-builder",
132
- "@rsbuild/core",
133
- "@rspack/core/package.json"
134
- ],
135
- "@rsdoctor/rspack-plugin": [
136
- ctx.rootPath,
137
- "@rsdoctor/rspack-plugin/package.json"
138
- ],
139
- "@rsdoctor/webpack-plugin": [
140
- ctx.rootPath,
141
- "@rsdoctor/webpack-plugin/package.json"
142
- ],
143
- "@web-doctor/webpack-plugin": [
144
- ctx.rootPath,
145
- "@web-doctor/webpack-plugin/package.json"
146
- ],
147
- "@web-doctor/rspack-plugin": [
148
- ctx.rootPath,
149
- "@web-doctor/rspack-plugin/package.json"
150
- ],
151
- "@web-doctor/webpack-plugin(builder)": [
152
- ctx.rootPath,
153
- "@edenx/builder-plugin-web-doctor",
154
- "@web-doctor/webpack-plugin/package.json"
155
- ],
156
- "@web-doctor/rspack-plugin(builder)": [
157
- ctx.rootPath,
158
- "@edenx/builder-plugin-web-doctor",
159
- "@web-doctor/rspack-plugin/package.json"
160
- ],
161
- "@rsdoctor/core": [
162
- ctx.rootPath,
163
- "@rsdoctor/core/package.json"
164
- ]
165
- };
166
- for (const [name, expr] of Object.entries(resolveExprs)) {
167
- try {
168
- ret[name] = (0, import_module.requireModule)(expr).version;
169
- } catch {
170
- }
183
+ async pasteStoragePreset(target) {
184
+ var _config;
185
+ const { default: clipboardy } = await import("clipboardy");
186
+ const raw = clipboardy.readSync();
187
+ const HEAD = `data:application/json;base64,`;
188
+ if (!raw.startsWith(HEAD)) {
189
+ throw new Error("Failed to parse data URL");
171
190
  }
172
- return ret;
173
- },
174
- async getCompileTimeCost() {
175
- return deferred.compileTimeCost.promise;
176
- },
177
- async getClientDefinition() {
178
- return def;
179
- },
180
- async getDoctorOverview() {
181
- const ctx = api.useAppContext();
182
- const manifestPath = await (0, import_node.findManifest)(ctx.distDirectory);
183
- const json = await (0, import_node.parseManifest)(require(manifestPath));
184
- const data = {
185
- numModules: json.data.moduleGraph.modules.length,
186
- numChunks: json.data.chunkGraph.chunks.length,
187
- numPackages: json.data.packageGraph.packages.length,
188
- summary: json.data.summary,
189
- errors: json.data.errors
190
- };
191
- return data;
191
+ const encoded = raw.slice(HEAD.length);
192
+ const preset = JSON.parse(import_buffer.Buffer.from(encoded, "base64").toString("utf-8"));
193
+ if (typeof preset !== "object" || preset === null) {
194
+ throw new Error("Failed to parse data URL");
195
+ }
196
+ if (typeof preset.name !== "string") {
197
+ throw new Error("Failed to parse data URL");
198
+ }
199
+ const appCtx = api.useAppContext();
200
+ const filename = import_path.default.resolve(appCtx.appDirectory, target.filename);
201
+ const config = {};
202
+ if (await import_utils.fs.pathExists(filename)) {
203
+ Object.assign(config, await import_utils.fs.readJSON(filename));
204
+ }
205
+ (_config = config).storagePresets || (_config.storagePresets = []);
206
+ const diff = import_lodash.default.pick(preset, [
207
+ "cookie",
208
+ "localStorage",
209
+ "sessionStorage"
210
+ ]);
211
+ const matched = import_lodash.default.find(config.storagePresets, {
212
+ id: target.id
213
+ });
214
+ if (matched) {
215
+ import_lodash.default.merge(matched, diff);
216
+ } else {
217
+ config.storagePresets.push(preset);
218
+ }
219
+ await import_utils.fs.outputJSON(filename, config, {
220
+ spaces: 2
221
+ });
192
222
  },
193
- echo(content) {
194
- return content;
223
+ async open(filename) {
224
+ const name = import_path.default.resolve(api.useAppContext().appDirectory, filename);
225
+ const validated = validateSafeToOpen(name);
226
+ if (!validated) {
227
+ throw new Error("Failed to validate the file.");
228
+ }
229
+ const { default: open } = await import("open");
230
+ await open(name);
195
231
  }
196
232
  };
197
233
  const clientRpcOptions = {
@@ -199,36 +235,70 @@ const setupClientConnection = async (options) => {
199
235
  on: (cb) => handleMessage = cb,
200
236
  serialize: (v) => flatted.stringify([
201
237
  v
202
- ]),
203
- deserialize: (v) => flatted.parse(v.toString())[0]
238
+ ], import_node.replacer),
239
+ deserialize: (v) => {
240
+ const msg = flatted.parse(v.toString(), import_node.reviver)[0];
241
+ return msg;
242
+ }
204
243
  };
205
244
  const clientConn = (0, import_birpc.createBirpc)(serverFunctions, clientRpcOptions);
245
+ let _pendingCompiler = 0;
246
+ const resolveRsdoctorManifest = async () => {
247
+ _pendingCompiler -= 1;
248
+ if (_pendingCompiler === 0) {
249
+ try {
250
+ const doctor = await getDoctorOverview(await import_state.$state.framework.context);
251
+ import_state.$resolvers.doctor.resolve(doctor);
252
+ } catch (err) {
253
+ import_state.$resolvers.doctor.resolve(void 0);
254
+ }
255
+ }
256
+ };
206
257
  const hooks = {
207
258
  prepare() {
208
- deferred.prepare.resolve();
259
+ const frameworkContext = {
260
+ ...api.useAppContext(),
261
+ builder: null,
262
+ serverInternalPlugins: null
263
+ };
264
+ import_state.$resolvers.framework.context.resolve(frameworkContext);
265
+ import_state.$resolvers.framework.config.resolved.resolve(api.useConfigContext());
266
+ import_state.$resolvers.framework.config.transformed.resolve(api.useResolvedConfigContext());
209
267
  },
210
268
  modifyFileSystemRoutes({ entrypoint, routes }) {
211
- _fileSystemRoutesMap[entrypoint.entryName] = import_lodash.default.cloneDeep(routes);
269
+ import_state.$state.fileSystemRoutes[entrypoint.entryName] = import_lodash.default.cloneDeep(routes);
212
270
  return {
213
271
  entrypoint,
214
272
  routes
215
273
  };
274
+ },
275
+ afterCreateCompiler({ compiler }) {
276
+ if (!compiler)
277
+ return;
278
+ _pendingCompiler += 1;
279
+ compiler.hooks.done.tap({
280
+ name: "@modern-js/plugin-devtools",
281
+ stage: 4e3
282
+ }, () => resolveRsdoctorManifest());
216
283
  }
217
284
  };
218
285
  const builderPlugin = {
219
286
  name: "builder-plugin-devtools",
220
287
  setup(api2) {
221
- deferred.builder.context.resolve(import_lodash.default.cloneDeep(api2.context));
288
+ import_state.$resolvers.builder.context.resolve(api2.context);
289
+ resolveDependencies(api2.context.rootPath).then((deps) => {
290
+ import_state.$state.dependencies = deps;
291
+ });
222
292
  api2.modifyBundlerChain(() => {
223
- deferred.builder.config.resolved.resolve(import_lodash.default.cloneDeep(api2.getRsbuildConfig()));
224
- deferred.builder.config.transformed.resolve(import_lodash.default.cloneDeep(api2.getNormalizedConfig()));
293
+ import_state.$resolvers.builder.config.resolved.resolve(import_lodash.default.cloneDeep(api2.getRsbuildConfig()));
294
+ import_state.$resolvers.builder.config.transformed.resolve(import_lodash.default.cloneDeep(api2.getNormalizedConfig()));
225
295
  });
226
296
  const expectBundlerNum = import_lodash.default.castArray(api2.context.targets).length;
227
297
  const bundlerConfigs = [];
228
298
  const handleBundlerConfig = (config) => {
229
299
  bundlerConfigs.push(config);
230
300
  if (bundlerConfigs.length >= expectBundlerNum) {
231
- deferred.bundler.config.resolved.resolve(import_lodash.default.cloneDeep(bundlerConfigs));
301
+ import_state.$state.bundler.configs.resolved = import_lodash.default.cloneDeep(bundlerConfigs);
232
302
  }
233
303
  };
234
304
  if (api2.context.bundlerType === "webpack") {
@@ -241,17 +311,21 @@ const setupClientConnection = async (options) => {
241
311
  });
242
312
  }
243
313
  api2.onBeforeCreateCompiler(({ bundlerConfigs: bundlerConfigs2 }) => {
244
- deferred.bundler.config.transformed.resolve(import_lodash.default.cloneDeep(bundlerConfigs2));
314
+ import_state.$resolvers.bundler.configs.transformed.resolve(import_lodash.default.cloneDeep(bundlerConfigs2));
245
315
  });
246
316
  let buildStartedAt = NaN;
247
317
  api2.onAfterCreateCompiler(() => {
248
318
  buildStartedAt = Date.now();
249
319
  });
250
320
  api2.onDevCompileDone(() => {
251
- deferred.compileTimeCost.resolve(Date.now() - buildStartedAt);
321
+ import_state.$resolvers.performance.resolve({
322
+ compileDuration: Date.now() - buildStartedAt
323
+ });
252
324
  });
253
325
  api2.onAfterBuild(() => {
254
- deferred.compileTimeCost.resolve(Date.now() - buildStartedAt);
326
+ import_state.$resolvers.performance.resolve({
327
+ compileDuration: Date.now() - buildStartedAt
328
+ });
255
329
  });
256
330
  }
257
331
  };
@@ -0,0 +1,4 @@
1
+ import { ServerExportedStateResolvers } from '@modern-js/devtools-kit/node';
2
+ export declare const $serverExportedState: import("@modern-js/devtools-kit/node").ServerExportedStateResult;
3
+ export declare const $resolvers: ServerExportedStateResolvers;
4
+ export declare const $state: import("@modern-js/devtools-kit/node").ServerExportedState;
package/dist/state.js ADDED
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var state_exports = {};
20
+ __export(state_exports, {
21
+ $resolvers: () => $resolvers,
22
+ $serverExportedState: () => $serverExportedState,
23
+ $state: () => $state
24
+ });
25
+ module.exports = __toCommonJS(state_exports);
26
+ var import_valtio = require("valtio");
27
+ var import_node = require("@modern-js/devtools-kit/node");
28
+ const $serverExportedState = (0, import_node.createServerExportedState)();
29
+ const $resolvers = $serverExportedState.resolvers;
30
+ const $state = (0, import_valtio.proxy)($serverExportedState.state);
31
+ // Annotate the CommonJS export names for ESM import in node:
32
+ 0 && (module.exports = {
33
+ $resolvers,
34
+ $serverExportedState,
35
+ $state
36
+ });
@@ -18,4 +18,4 @@ export type BufferLike = string | Buffer | DataView | number | ArrayBufferView |
18
18
  [Symbol.toPrimitive]: (hint: string) => string;
19
19
  };
20
20
  export type Hooks = BaseHooks<any> & AppToolsHooks<any>;
21
- export type InjectedHooks = Pick<ToThreads<Hooks>, 'prepare' | 'modifyFileSystemRoutes'>;
21
+ export type InjectedHooks = Pick<ToThreads<Hooks>, 'prepare' | 'modifyFileSystemRoutes' | 'afterCreateCompiler'>;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var common_exports = {};
16
+ module.exports = __toCommonJS(common_exports);
@@ -0,0 +1,4 @@
1
+ import { StoragePresetWithIdent } from '@modern-js/devtools-kit/node';
2
+ export interface DevtoolsConfig {
3
+ storagePresets?: StoragePresetWithIdent[];
4
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var config_exports = {};
16
+ module.exports = __toCommonJS(config_exports);
@@ -0,0 +1,2 @@
1
+ export type * from './common';
2
+ export type * from './config';
@@ -0,0 +1,8 @@
1
+ import { DevtoolsContext, StoragePresetContext } from '@modern-js/devtools-kit';
2
+ export declare function getConfigFilenames(base: string, dir?: string): string[];
3
+ /** Resolve all config files from target directory upward to the root path. */
4
+ export declare function resolveConfigFiles(base: string, dir?: string): Promise<string[]>;
5
+ export declare function loadConfigFile(filename: string): Promise<{
6
+ storagePresets: StoragePresetContext[];
7
+ } | null>;
8
+ export declare function loadConfigFiles(base: string, dir?: string): Promise<Partial<DevtoolsContext>[] | null>;
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var config_exports = {};
30
+ __export(config_exports, {
31
+ getConfigFilenames: () => getConfigFilenames,
32
+ loadConfigFile: () => loadConfigFile,
33
+ loadConfigFiles: () => loadConfigFiles,
34
+ resolveConfigFiles: () => resolveConfigFiles
35
+ });
36
+ module.exports = __toCommonJS(config_exports);
37
+ var import_path = __toESM(require("path"));
38
+ var import_fs_extra = __toESM(require("@modern-js/utils/fs-extra"));
39
+ var import_utils = require("@modern-js/utils");
40
+ function getConfigFilenames(base, dir = process.cwd()) {
41
+ const files = [];
42
+ let curr = dir;
43
+ while (import_path.default.dirname(curr) !== curr) {
44
+ files.push(import_path.default.join(curr, base));
45
+ curr = import_path.default.dirname(curr);
46
+ }
47
+ return files;
48
+ }
49
+ async function resolveConfigFiles(base, dir = process.cwd()) {
50
+ const files = getConfigFilenames(base, dir);
51
+ const ret = [];
52
+ await Promise.all(files.map(async (file) => await import_fs_extra.default.pathExists(file) && ret.push(file)));
53
+ return ret;
54
+ }
55
+ async function loadConfigFile(filename) {
56
+ const storagePresets = [];
57
+ try {
58
+ const config = await import_fs_extra.default.readJSON(filename);
59
+ config.storagePresets && storagePresets.push(...config.storagePresets);
60
+ } catch (e) {
61
+ import_utils.logger.error(e);
62
+ return null;
63
+ }
64
+ const presets = [];
65
+ let _validated = true;
66
+ for (const preset of storagePresets) {
67
+ if (typeof preset.id !== "string") {
68
+ preset.id = (0, import_utils.nanoid)();
69
+ _validated = false;
70
+ }
71
+ presets.push(preset);
72
+ }
73
+ if (!_validated) {
74
+ await import_fs_extra.default.outputJSON(filename, {
75
+ storagePresets: presets
76
+ }, {
77
+ spaces: 2
78
+ });
79
+ return null;
80
+ }
81
+ const ret = [];
82
+ for (const preset of presets) {
83
+ ret.push({
84
+ ...preset,
85
+ filename
86
+ });
87
+ }
88
+ return {
89
+ storagePresets: ret
90
+ };
91
+ }
92
+ async function loadConfigFiles(base, dir = process.cwd()) {
93
+ const filenames = await resolveConfigFiles(base, dir);
94
+ const resolved = await Promise.all(filenames.map(loadConfigFile));
95
+ const ret = [];
96
+ for (const config of resolved) {
97
+ if (config) {
98
+ ret.push(config);
99
+ } else {
100
+ return null;
101
+ }
102
+ }
103
+ return ret;
104
+ }
105
+ // Annotate the CommonJS export names for ESM import in node:
106
+ 0 && (module.exports = {
107
+ getConfigFilenames,
108
+ loadConfigFile,
109
+ loadConfigFiles,
110
+ resolveConfigFiles
111
+ });
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.49.3",
18
+ "version": "2.50.0",
19
19
  "jsnext:source": "./src/index.ts",
20
20
  "types": "./dist/index.d.ts",
21
21
  "main": "./dist/index.js",
@@ -43,34 +43,38 @@
43
43
  }
44
44
  },
45
45
  "dependencies": {
46
+ "@hono/node-server": "^1.8.2",
46
47
  "birpc": "0.2.13",
48
+ "clipboardy": "^4.0.0",
49
+ "cookie-es": "^1.0.0",
47
50
  "flatted": "^3.2.9",
48
- "serve-static": "^1.14.1",
51
+ "hono": "^3.12.2",
52
+ "open": "^10.1.0",
49
53
  "p-defer": "^3.0.0",
50
- "ws": "^8.13.0",
51
54
  "ufo": "^1.3.0",
52
- "@modern-js/devtools-client": "2.49.3",
53
- "@modern-js/devtools-kit": "2.49.3",
54
- "@modern-js/utils": "2.49.3"
55
+ "valtio": "^1.11.1",
56
+ "ws": "^8.13.0",
57
+ "@modern-js/devtools-kit": "2.50.0",
58
+ "@modern-js/utils": "2.50.0",
59
+ "@modern-js/devtools-client": "2.50.0"
55
60
  },
56
61
  "devDependencies": {
57
- "@types/serve-static": "^1.13.10",
58
62
  "@swc/helpers": "0.5.3",
59
63
  "@types/node": "^14",
60
64
  "@types/ws": "^8.5.5",
61
65
  "type-fest": "^4.1.0",
62
66
  "typescript": "^5",
63
- "@modern-js/app-tools": "2.49.3",
64
- "@modern-js/core": "2.49.3",
65
- "@modern-js/module-tools": "2.49.3",
66
- "@modern-js/runtime": "2.49.3",
67
- "@modern-js/server-core": "2.49.3",
68
- "@modern-js/types": "2.49.3",
69
- "@scripts/build": "2.49.3",
70
- "@modern-js/uni-builder": "2.49.3"
67
+ "@modern-js/core": "2.50.0",
68
+ "@modern-js/app-tools": "2.50.0",
69
+ "@modern-js/module-tools": "2.50.0",
70
+ "@modern-js/server-core": "2.50.0",
71
+ "@modern-js/types": "2.50.0",
72
+ "@modern-js/uni-builder": "2.50.0",
73
+ "@modern-js/runtime": "2.50.0",
74
+ "@scripts/build": "2.50.0"
71
75
  },
72
76
  "peerDependencies": {
73
- "@modern-js/runtime": "^2.49.3"
77
+ "@modern-js/runtime": "^2.50.0"
74
78
  },
75
79
  "peerDependenciesMeta": {
76
80
  "@modern-js/runtime": {
package/dist/config.d.ts DELETED
@@ -1,11 +0,0 @@
1
- import { ClientDefinition } from '@modern-js/devtools-kit/node';
2
- import type { RequiredDeep } from 'type-fest';
3
- export interface DevtoolsPluginOptions {
4
- enable?: boolean;
5
- endpoint?: string;
6
- dataSource?: string;
7
- }
8
- export interface DevtoolsContext extends RequiredDeep<DevtoolsPluginOptions> {
9
- def: ClientDefinition;
10
- }
11
- export declare const resolveContext: (...sources: Partial<DevtoolsContext>[]) => DevtoolsContext;
File without changes