rsbuild-plugin-workspace-dev 0.0.2 → 0.1.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/README.md CHANGED
@@ -104,10 +104,11 @@ interface projects {
104
104
  */
105
105
  match?: (stdout: string) => boolean;
106
106
  /**
107
- * Whether to skip starting the current sub-project. Default is `false`.
108
- * Useful for sub-projects that do not need to be started.
109
- */
110
- skip?: boolean;
107
+ * Whether to skip starting the current sub-project. The default value is `false`, typically used to skip sub-projects that don't need to be started.
108
+ * When the value is `true`, pruning will be performed on the specified project, meaning that this project and all its direct and indirect dependencies will not be started by the plugin.
109
+ * When the value is `only`, starting the specified project will be skipped, but no pruning will be performed, meaning that the project's direct and indirect dependencies will still be started by the plugin.
110
+ */
111
+ skip?: boolean | 'only';
111
112
  }
112
113
 
113
114
 
package/README.zh-CN.md CHANGED
@@ -99,8 +99,10 @@ interface Projects {
99
99
  match?: (stdout: string) => boolean;
100
100
  /**
101
101
  * 是否跳过当前子项目的启动,默认值为 `false`,通常用于跳过一些不需要启动的子项目。
102
+ * 当值为 `true` 时,会从指定项目进行剪枝,这意味着该项目以及他的所有直接和间接依赖都不会被插件启动。
103
+ * 当值为 `only` 时,会跳过指定项目的启动,但不会进行剪枝,这意味着该项目的直接和间接依赖仍然会被插件启动。
102
104
  */
103
- skip?: boolean;
105
+ skip?: boolean | 'only';
104
106
  }
105
107
 
106
108
  // 例如,配置 lib1 子项目,用 build:watch 命令启动,匹配 watch success 日志
@@ -1,5 +1,5 @@
1
1
  export declare const PACKAGE_JSON = "package.json";
2
- export declare const DEBUG_LOG_TITLE = "[Rsbuild Workspace Dev Plugin]: ";
2
+ export declare const PLUGIN_LOG_TITLE = "[Rsbuild Workspace Dev Plugin]: ";
3
3
  export declare const RSLIB_READY_MESSAGE = "build complete, watching for changes";
4
4
  export declare const MODERN_MODULE_READY_MESSAGE = "Watching for file changes";
5
5
  export declare const TSUP_READY_MESSAGE = "Watching for changes in";
package/dist/index.cjs CHANGED
@@ -39,7 +39,7 @@ __webpack_require__.d(__webpack_exports__, {
39
39
  const external_chalk_namespaceObject = require("chalk");
40
40
  var external_chalk_default = /*#__PURE__*/ __webpack_require__.n(external_chalk_namespaceObject);
41
41
  const PACKAGE_JSON = 'package.json';
42
- const DEBUG_LOG_TITLE = '[Rsbuild Workspace Dev Plugin]: ';
42
+ const PLUGIN_LOG_TITLE = '[Rsbuild Workspace Dev Plugin]: ';
43
43
  const RSLIB_READY_MESSAGE = 'build complete, watching for changes';
44
44
  const MODERN_MODULE_READY_MESSAGE = 'Watching for file changes';
45
45
  const TSUP_READY_MESSAGE = 'Watching for changes in';
@@ -107,10 +107,10 @@ class Logger {
107
107
  this.name = name;
108
108
  this.stdout = '';
109
109
  this.stderr = '';
110
- this.logTitle = DEBUG_LOG_TITLE;
110
+ this.logTitle = PLUGIN_LOG_TITLE;
111
111
  }
112
112
  }
113
- const debugLog = (msg, prefix = DEBUG_LOG_TITLE)=>{
113
+ const debugLog = (msg, prefix = PLUGIN_LOG_TITLE)=>{
114
114
  if (isDebug) console.log(prefix + msg);
115
115
  };
116
116
  const get_packages_namespaceObject = require("@manypkg/get-packages");
@@ -147,6 +147,8 @@ class WorkspaceDevRunner {
147
147
  packageJson,
148
148
  path: dir
149
149
  };
150
+ const skip = this.options.projects?.[name]?.skip;
151
+ if (true === skip) return;
150
152
  this.graph.setNode(name, node);
151
153
  this.visited[name] = false;
152
154
  this.visiting[name] = false;
@@ -159,12 +161,13 @@ class WorkspaceDevRunner {
159
161
  };
160
162
  for (const depName of Object.keys(deps)){
161
163
  const isInternalDep = this.packages.some((p)=>p.packageJson.name === depName);
162
- if (isInternalDep) {
164
+ const skip = this.options.projects?.[depName]?.skip;
165
+ if (isInternalDep) if (true !== skip) {
163
166
  this.graph.setEdge(packageName, depName);
164
167
  this.checkGraph();
165
168
  const depPackage = packages.find((pkg)=>pkg.packageJson.name === depName);
166
169
  if (!this.getNode(depName)) initNode(depPackage);
167
- }
170
+ } else debugLog(`Prune project ${depName} and its dependencies because it is marked as skip: true`);
168
171
  }
169
172
  };
170
173
  initNode(currentPackage);
@@ -172,8 +175,11 @@ class WorkspaceDevRunner {
172
175
  checkGraph() {
173
176
  const cycles = external_graphlib_default().alg.findCycles(this.graph);
174
177
  const nonSelfCycles = cycles.filter((c)=>1 !== c.length);
175
- debugLog(`cycles check: ${cycles}`);
176
- if (nonSelfCycles.length) throw new Error(`${DEBUG_LOG_TITLE}Dependency graph do not allow cycles.`);
178
+ const nonSkipCycles = nonSelfCycles.filter((group)=>{
179
+ const isSkip = group.some((node)=>this.options.projects?.[node]?.skip);
180
+ return !isSkip;
181
+ });
182
+ if (nonSkipCycles.length) throw new Error(`${PLUGIN_LOG_TITLE} Cycle dependency graph found: ${nonSkipCycles}, you should config projects in plugin options to skip someone, or fix the cycle dependency. Otherwise, a loop of dev will occur.`);
177
183
  }
178
184
  async start() {
179
185
  const promises = [];
@@ -185,7 +191,8 @@ class WorkspaceDevRunner {
185
191
  const canStart = dependencies.every((dep)=>{
186
192
  const selfStart = node === dep;
187
193
  const isVisiting = this.visiting[dep];
188
- const isVisited = selfStart || this.visited[dep];
194
+ const skipDep = this.options.projects?.[dep]?.skip;
195
+ const isVisited = selfStart || this.visited[dep] || skipDep;
189
196
  return isVisited && !isVisiting;
190
197
  });
191
198
  if (canStart && !this.visited[node] && !this.visiting[node]) {
@@ -207,7 +214,7 @@ class WorkspaceDevRunner {
207
214
  this.visited[node] = true;
208
215
  this.visiting[node] = false;
209
216
  debugLog(`Skip visit node: ${node}`);
210
- logger.emitLogOnce('stdout', `skip visit node: ${name}`);
217
+ logger.emitLogOnce('stdout', `Skip visit node: ${name}`);
211
218
  return this.start().then(()=>resolve());
212
219
  }
213
220
  this.visiting[node] = true;
@@ -303,6 +310,16 @@ function pluginWorkspaceDev(options) {
303
310
  await runner.start();
304
311
  Logger.setEndBanner();
305
312
  });
313
+ api.onBeforeBuild(async ({ isWatch, isFirstCompile })=>{
314
+ if (!isWatch || !isFirstCompile) return;
315
+ const runner = new WorkspaceDevRunner({
316
+ cwd: rootPath,
317
+ ...options
318
+ });
319
+ await runner.init();
320
+ await runner.start();
321
+ Logger.setEndBanner();
322
+ });
306
323
  }
307
324
  };
308
325
  }
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { spawn } from "child_process";
6
6
  import graphlib, { Graph } from "graphlib";
7
7
  import path_0 from "path";
8
8
  const PACKAGE_JSON = 'package.json';
9
- const DEBUG_LOG_TITLE = '[Rsbuild Workspace Dev Plugin]: ';
9
+ const PLUGIN_LOG_TITLE = '[Rsbuild Workspace Dev Plugin]: ';
10
10
  const RSLIB_READY_MESSAGE = 'build complete, watching for changes';
11
11
  const MODERN_MODULE_READY_MESSAGE = 'Watching for file changes';
12
12
  const TSUP_READY_MESSAGE = 'Watching for changes in';
@@ -70,10 +70,10 @@ class Logger {
70
70
  this.name = name;
71
71
  this.stdout = '';
72
72
  this.stderr = '';
73
- this.logTitle = DEBUG_LOG_TITLE;
73
+ this.logTitle = PLUGIN_LOG_TITLE;
74
74
  }
75
75
  }
76
- const debugLog = (msg, prefix = DEBUG_LOG_TITLE)=>{
76
+ const debugLog = (msg, prefix = PLUGIN_LOG_TITLE)=>{
77
77
  if (isDebug) console.log(prefix + msg);
78
78
  };
79
79
  function workspace_dev_define_property(obj, key, value) {
@@ -104,6 +104,8 @@ class WorkspaceDevRunner {
104
104
  packageJson,
105
105
  path: dir
106
106
  };
107
+ const skip = this.options.projects?.[name]?.skip;
108
+ if (true === skip) return;
107
109
  this.graph.setNode(name, node);
108
110
  this.visited[name] = false;
109
111
  this.visiting[name] = false;
@@ -116,12 +118,13 @@ class WorkspaceDevRunner {
116
118
  };
117
119
  for (const depName of Object.keys(deps)){
118
120
  const isInternalDep = this.packages.some((p)=>p.packageJson.name === depName);
119
- if (isInternalDep) {
121
+ const skip = this.options.projects?.[depName]?.skip;
122
+ if (isInternalDep) if (true !== skip) {
120
123
  this.graph.setEdge(packageName, depName);
121
124
  this.checkGraph();
122
125
  const depPackage = packages.find((pkg)=>pkg.packageJson.name === depName);
123
126
  if (!this.getNode(depName)) initNode(depPackage);
124
- }
127
+ } else debugLog(`Prune project ${depName} and its dependencies because it is marked as skip: true`);
125
128
  }
126
129
  };
127
130
  initNode(currentPackage);
@@ -129,8 +132,11 @@ class WorkspaceDevRunner {
129
132
  checkGraph() {
130
133
  const cycles = graphlib.alg.findCycles(this.graph);
131
134
  const nonSelfCycles = cycles.filter((c)=>1 !== c.length);
132
- debugLog(`cycles check: ${cycles}`);
133
- if (nonSelfCycles.length) throw new Error(`${DEBUG_LOG_TITLE}Dependency graph do not allow cycles.`);
135
+ const nonSkipCycles = nonSelfCycles.filter((group)=>{
136
+ const isSkip = group.some((node)=>this.options.projects?.[node]?.skip);
137
+ return !isSkip;
138
+ });
139
+ if (nonSkipCycles.length) throw new Error(`${PLUGIN_LOG_TITLE} Cycle dependency graph found: ${nonSkipCycles}, you should config projects in plugin options to skip someone, or fix the cycle dependency. Otherwise, a loop of dev will occur.`);
134
140
  }
135
141
  async start() {
136
142
  const promises = [];
@@ -142,7 +148,8 @@ class WorkspaceDevRunner {
142
148
  const canStart = dependencies.every((dep)=>{
143
149
  const selfStart = node === dep;
144
150
  const isVisiting = this.visiting[dep];
145
- const isVisited = selfStart || this.visited[dep];
151
+ const skipDep = this.options.projects?.[dep]?.skip;
152
+ const isVisited = selfStart || this.visited[dep] || skipDep;
146
153
  return isVisited && !isVisiting;
147
154
  });
148
155
  if (canStart && !this.visited[node] && !this.visiting[node]) {
@@ -164,7 +171,7 @@ class WorkspaceDevRunner {
164
171
  this.visited[node] = true;
165
172
  this.visiting[node] = false;
166
173
  debugLog(`Skip visit node: ${node}`);
167
- logger.emitLogOnce('stdout', `skip visit node: ${name}`);
174
+ logger.emitLogOnce('stdout', `Skip visit node: ${name}`);
168
175
  return this.start().then(()=>resolve());
169
176
  }
170
177
  this.visiting[node] = true;
@@ -260,6 +267,16 @@ function pluginWorkspaceDev(options) {
260
267
  await runner.start();
261
268
  Logger.setEndBanner();
262
269
  });
270
+ api.onBeforeBuild(async ({ isWatch, isFirstCompile })=>{
271
+ if (!isWatch || !isFirstCompile) return;
272
+ const runner = new WorkspaceDevRunner({
273
+ cwd: rootPath,
274
+ ...options
275
+ });
276
+ await runner.init();
277
+ await runner.start();
278
+ Logger.setEndBanner();
279
+ });
263
280
  }
264
281
  };
265
282
  }
@@ -5,7 +5,7 @@ export interface WorkspaceDevRunnerOptions {
5
5
  projects?: Record<string, {
6
6
  match?: (stdout: string) => boolean;
7
7
  command?: string;
8
- skip?: boolean;
8
+ skip?: boolean | 'only';
9
9
  }>;
10
10
  startCurrent?: boolean;
11
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rsbuild-plugin-workspace-dev",
3
- "version": "0.0.2",
3
+ "version": "0.1.0",
4
4
  "description": "An Rsbuild plugin to provides workspace recursive dev functionality for Monorepo topologies.",
5
5
  "repository": "https://github.com/rspack-contrib/rsbuild-plugin-workspace-dev",
6
6
  "license": "MIT",