rsbuild-plugin-workspace-dev 0.0.2 → 0.1.1
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 +5 -4
- package/README.zh-CN.md +3 -1
- package/dist/constant.d.ts +1 -2
- package/dist/index.cjs +33 -16
- package/dist/index.js +34 -16
- package/dist/types.d.ts +6 -0
- package/dist/utils.d.ts +2 -2
- package/dist/workspace-dev.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -104,10 +104,11 @@ interface projects {
|
|
|
104
104
|
*/
|
|
105
105
|
match?: (stdout: string) => boolean;
|
|
106
106
|
/**
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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 日志
|
package/dist/constant.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export declare const PACKAGE_JSON = "package.json";
|
|
2
|
-
export declare const
|
|
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
|
-
export declare const MODERN_MODULE_READY_MESSAGE = "Watching for file changes";
|
|
5
4
|
export declare const TSUP_READY_MESSAGE = "Watching for changes in";
|
package/dist/index.cjs
CHANGED
|
@@ -39,9 +39,8 @@ __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
|
|
42
|
+
const PLUGIN_LOG_TITLE = '[Rsbuild Workspace Dev Plugin]: ';
|
|
43
43
|
const RSLIB_READY_MESSAGE = 'build complete, watching for changes';
|
|
44
|
-
const MODERN_MODULE_READY_MESSAGE = 'Watching for file changes';
|
|
45
44
|
const TSUP_READY_MESSAGE = 'Watching for changes in';
|
|
46
45
|
const external_fs_namespaceObject = require("fs");
|
|
47
46
|
var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
|
|
@@ -107,10 +106,10 @@ class Logger {
|
|
|
107
106
|
this.name = name;
|
|
108
107
|
this.stdout = '';
|
|
109
108
|
this.stderr = '';
|
|
110
|
-
this.logTitle =
|
|
109
|
+
this.logTitle = PLUGIN_LOG_TITLE;
|
|
111
110
|
}
|
|
112
111
|
}
|
|
113
|
-
const debugLog = (msg, prefix =
|
|
112
|
+
const debugLog = (msg, prefix = PLUGIN_LOG_TITLE)=>{
|
|
114
113
|
if (isDebug) console.log(prefix + msg);
|
|
115
114
|
};
|
|
116
115
|
const get_packages_namespaceObject = require("@manypkg/get-packages");
|
|
@@ -118,7 +117,6 @@ const external_child_process_namespaceObject = require("child_process");
|
|
|
118
117
|
const external_graphlib_namespaceObject = require("graphlib");
|
|
119
118
|
var external_graphlib_default = /*#__PURE__*/ __webpack_require__.n(external_graphlib_namespaceObject);
|
|
120
119
|
const external_path_namespaceObject = require("path");
|
|
121
|
-
var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
|
|
122
120
|
function workspace_dev_define_property(obj, key, value) {
|
|
123
121
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
124
122
|
value: value,
|
|
@@ -131,7 +129,7 @@ function workspace_dev_define_property(obj, key, value) {
|
|
|
131
129
|
}
|
|
132
130
|
class WorkspaceDevRunner {
|
|
133
131
|
async init() {
|
|
134
|
-
this.metaData = await readPackageJson(
|
|
132
|
+
this.metaData = await readPackageJson((0, external_path_namespaceObject.join)(this.cwd, PACKAGE_JSON));
|
|
135
133
|
this.buildDependencyGraph();
|
|
136
134
|
debugLog(`Dependency graph:\nnodes: ${this.getNodes().join(', ')}\nedges: ${this.getEdges().map((edge)=>`${edge.v} -> ${edge.w}`).join(', ')}\n`);
|
|
137
135
|
}
|
|
@@ -147,6 +145,8 @@ class WorkspaceDevRunner {
|
|
|
147
145
|
packageJson,
|
|
148
146
|
path: dir
|
|
149
147
|
};
|
|
148
|
+
const skip = this.options.projects?.[name]?.skip;
|
|
149
|
+
if (true === skip) return;
|
|
150
150
|
this.graph.setNode(name, node);
|
|
151
151
|
this.visited[name] = false;
|
|
152
152
|
this.visiting[name] = false;
|
|
@@ -159,12 +159,13 @@ class WorkspaceDevRunner {
|
|
|
159
159
|
};
|
|
160
160
|
for (const depName of Object.keys(deps)){
|
|
161
161
|
const isInternalDep = this.packages.some((p)=>p.packageJson.name === depName);
|
|
162
|
-
|
|
162
|
+
const skip = this.options.projects?.[depName]?.skip;
|
|
163
|
+
if (isInternalDep) if (true !== skip) {
|
|
163
164
|
this.graph.setEdge(packageName, depName);
|
|
164
165
|
this.checkGraph();
|
|
165
166
|
const depPackage = packages.find((pkg)=>pkg.packageJson.name === depName);
|
|
166
167
|
if (!this.getNode(depName)) initNode(depPackage);
|
|
167
|
-
}
|
|
168
|
+
} else debugLog(`Prune project ${depName} and its dependencies because it is marked as skip: true`);
|
|
168
169
|
}
|
|
169
170
|
};
|
|
170
171
|
initNode(currentPackage);
|
|
@@ -172,8 +173,11 @@ class WorkspaceDevRunner {
|
|
|
172
173
|
checkGraph() {
|
|
173
174
|
const cycles = external_graphlib_default().alg.findCycles(this.graph);
|
|
174
175
|
const nonSelfCycles = cycles.filter((c)=>1 !== c.length);
|
|
175
|
-
|
|
176
|
-
|
|
176
|
+
const nonSkipCycles = nonSelfCycles.filter((group)=>{
|
|
177
|
+
const isSkip = group.some((node)=>this.options.projects?.[node]?.skip);
|
|
178
|
+
return !isSkip;
|
|
179
|
+
});
|
|
180
|
+
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
181
|
}
|
|
178
182
|
async start() {
|
|
179
183
|
const promises = [];
|
|
@@ -185,7 +189,8 @@ class WorkspaceDevRunner {
|
|
|
185
189
|
const canStart = dependencies.every((dep)=>{
|
|
186
190
|
const selfStart = node === dep;
|
|
187
191
|
const isVisiting = this.visiting[dep];
|
|
188
|
-
const
|
|
192
|
+
const skipDep = this.options.projects?.[dep]?.skip;
|
|
193
|
+
const isVisited = selfStart || this.visited[dep] || skipDep;
|
|
189
194
|
return isVisited && !isVisiting;
|
|
190
195
|
});
|
|
191
196
|
if (canStart && !this.visited[node] && !this.visiting[node]) {
|
|
@@ -198,22 +203,24 @@ class WorkspaceDevRunner {
|
|
|
198
203
|
}
|
|
199
204
|
visitNodes(node) {
|
|
200
205
|
return new Promise((resolve)=>{
|
|
201
|
-
const { name, path } = this.getNode(node);
|
|
206
|
+
const { name, path, packageJson } = this.getNode(node);
|
|
202
207
|
const logger = new Logger({
|
|
203
208
|
name
|
|
204
209
|
});
|
|
205
210
|
const config = this.options?.projects?.[name];
|
|
206
|
-
|
|
211
|
+
const command = config?.command ? config.command : 'dev';
|
|
212
|
+
const scripts = packageJson.scripts || {};
|
|
213
|
+
if (config?.skip || !scripts[command]) {
|
|
207
214
|
this.visited[node] = true;
|
|
208
215
|
this.visiting[node] = false;
|
|
209
216
|
debugLog(`Skip visit node: ${node}`);
|
|
210
|
-
logger.emitLogOnce('stdout', `
|
|
217
|
+
logger.emitLogOnce('stdout', `Skip visit node: ${name}`);
|
|
211
218
|
return this.start().then(()=>resolve());
|
|
212
219
|
}
|
|
213
220
|
this.visiting[node] = true;
|
|
214
221
|
const child = (0, external_child_process_namespaceObject.spawn)('npm', [
|
|
215
222
|
'run',
|
|
216
|
-
|
|
223
|
+
command
|
|
217
224
|
], {
|
|
218
225
|
cwd: path,
|
|
219
226
|
env: {
|
|
@@ -229,7 +236,7 @@ class WorkspaceDevRunner {
|
|
|
229
236
|
debugLog(content, `${name}: `);
|
|
230
237
|
logger.appendLog('stdout', stdout);
|
|
231
238
|
const match = config?.match;
|
|
232
|
-
const matchResult = match ? match(stdout) : stdout.match(RSLIB_READY_MESSAGE) || stdout.match(
|
|
239
|
+
const matchResult = match ? match(stdout) : stdout.match(RSLIB_READY_MESSAGE) || stdout.match(TSUP_READY_MESSAGE);
|
|
233
240
|
if (matchResult) {
|
|
234
241
|
logger.flushStdout();
|
|
235
242
|
this.matched[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
|
@@ -4,11 +4,10 @@ import json5 from "json5";
|
|
|
4
4
|
import { getPackagesSync } from "@manypkg/get-packages";
|
|
5
5
|
import { spawn } from "child_process";
|
|
6
6
|
import graphlib, { Graph } from "graphlib";
|
|
7
|
-
import
|
|
7
|
+
import { join } from "path";
|
|
8
8
|
const PACKAGE_JSON = 'package.json';
|
|
9
|
-
const
|
|
9
|
+
const PLUGIN_LOG_TITLE = '[Rsbuild Workspace Dev Plugin]: ';
|
|
10
10
|
const RSLIB_READY_MESSAGE = 'build complete, watching for changes';
|
|
11
|
-
const MODERN_MODULE_READY_MESSAGE = 'Watching for file changes';
|
|
12
11
|
const TSUP_READY_MESSAGE = 'Watching for changes in';
|
|
13
12
|
async function pathExists(path) {
|
|
14
13
|
return fs.promises.access(path).then(()=>true).catch(()=>false);
|
|
@@ -70,10 +69,10 @@ class Logger {
|
|
|
70
69
|
this.name = name;
|
|
71
70
|
this.stdout = '';
|
|
72
71
|
this.stderr = '';
|
|
73
|
-
this.logTitle =
|
|
72
|
+
this.logTitle = PLUGIN_LOG_TITLE;
|
|
74
73
|
}
|
|
75
74
|
}
|
|
76
|
-
const debugLog = (msg, prefix =
|
|
75
|
+
const debugLog = (msg, prefix = PLUGIN_LOG_TITLE)=>{
|
|
77
76
|
if (isDebug) console.log(prefix + msg);
|
|
78
77
|
};
|
|
79
78
|
function workspace_dev_define_property(obj, key, value) {
|
|
@@ -88,7 +87,7 @@ function workspace_dev_define_property(obj, key, value) {
|
|
|
88
87
|
}
|
|
89
88
|
class WorkspaceDevRunner {
|
|
90
89
|
async init() {
|
|
91
|
-
this.metaData = await readPackageJson(
|
|
90
|
+
this.metaData = await readPackageJson(join(this.cwd, PACKAGE_JSON));
|
|
92
91
|
this.buildDependencyGraph();
|
|
93
92
|
debugLog(`Dependency graph:\nnodes: ${this.getNodes().join(', ')}\nedges: ${this.getEdges().map((edge)=>`${edge.v} -> ${edge.w}`).join(', ')}\n`);
|
|
94
93
|
}
|
|
@@ -104,6 +103,8 @@ class WorkspaceDevRunner {
|
|
|
104
103
|
packageJson,
|
|
105
104
|
path: dir
|
|
106
105
|
};
|
|
106
|
+
const skip = this.options.projects?.[name]?.skip;
|
|
107
|
+
if (true === skip) return;
|
|
107
108
|
this.graph.setNode(name, node);
|
|
108
109
|
this.visited[name] = false;
|
|
109
110
|
this.visiting[name] = false;
|
|
@@ -116,12 +117,13 @@ class WorkspaceDevRunner {
|
|
|
116
117
|
};
|
|
117
118
|
for (const depName of Object.keys(deps)){
|
|
118
119
|
const isInternalDep = this.packages.some((p)=>p.packageJson.name === depName);
|
|
119
|
-
|
|
120
|
+
const skip = this.options.projects?.[depName]?.skip;
|
|
121
|
+
if (isInternalDep) if (true !== skip) {
|
|
120
122
|
this.graph.setEdge(packageName, depName);
|
|
121
123
|
this.checkGraph();
|
|
122
124
|
const depPackage = packages.find((pkg)=>pkg.packageJson.name === depName);
|
|
123
125
|
if (!this.getNode(depName)) initNode(depPackage);
|
|
124
|
-
}
|
|
126
|
+
} else debugLog(`Prune project ${depName} and its dependencies because it is marked as skip: true`);
|
|
125
127
|
}
|
|
126
128
|
};
|
|
127
129
|
initNode(currentPackage);
|
|
@@ -129,8 +131,11 @@ class WorkspaceDevRunner {
|
|
|
129
131
|
checkGraph() {
|
|
130
132
|
const cycles = graphlib.alg.findCycles(this.graph);
|
|
131
133
|
const nonSelfCycles = cycles.filter((c)=>1 !== c.length);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
const nonSkipCycles = nonSelfCycles.filter((group)=>{
|
|
135
|
+
const isSkip = group.some((node)=>this.options.projects?.[node]?.skip);
|
|
136
|
+
return !isSkip;
|
|
137
|
+
});
|
|
138
|
+
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
139
|
}
|
|
135
140
|
async start() {
|
|
136
141
|
const promises = [];
|
|
@@ -142,7 +147,8 @@ class WorkspaceDevRunner {
|
|
|
142
147
|
const canStart = dependencies.every((dep)=>{
|
|
143
148
|
const selfStart = node === dep;
|
|
144
149
|
const isVisiting = this.visiting[dep];
|
|
145
|
-
const
|
|
150
|
+
const skipDep = this.options.projects?.[dep]?.skip;
|
|
151
|
+
const isVisited = selfStart || this.visited[dep] || skipDep;
|
|
146
152
|
return isVisited && !isVisiting;
|
|
147
153
|
});
|
|
148
154
|
if (canStart && !this.visited[node] && !this.visiting[node]) {
|
|
@@ -155,22 +161,24 @@ class WorkspaceDevRunner {
|
|
|
155
161
|
}
|
|
156
162
|
visitNodes(node) {
|
|
157
163
|
return new Promise((resolve)=>{
|
|
158
|
-
const { name, path } = this.getNode(node);
|
|
164
|
+
const { name, path, packageJson } = this.getNode(node);
|
|
159
165
|
const logger = new Logger({
|
|
160
166
|
name
|
|
161
167
|
});
|
|
162
168
|
const config = this.options?.projects?.[name];
|
|
163
|
-
|
|
169
|
+
const command = config?.command ? config.command : 'dev';
|
|
170
|
+
const scripts = packageJson.scripts || {};
|
|
171
|
+
if (config?.skip || !scripts[command]) {
|
|
164
172
|
this.visited[node] = true;
|
|
165
173
|
this.visiting[node] = false;
|
|
166
174
|
debugLog(`Skip visit node: ${node}`);
|
|
167
|
-
logger.emitLogOnce('stdout', `
|
|
175
|
+
logger.emitLogOnce('stdout', `Skip visit node: ${name}`);
|
|
168
176
|
return this.start().then(()=>resolve());
|
|
169
177
|
}
|
|
170
178
|
this.visiting[node] = true;
|
|
171
179
|
const child = spawn('npm', [
|
|
172
180
|
'run',
|
|
173
|
-
|
|
181
|
+
command
|
|
174
182
|
], {
|
|
175
183
|
cwd: path,
|
|
176
184
|
env: {
|
|
@@ -186,7 +194,7 @@ class WorkspaceDevRunner {
|
|
|
186
194
|
debugLog(content, `${name}: `);
|
|
187
195
|
logger.appendLog('stdout', stdout);
|
|
188
196
|
const match = config?.match;
|
|
189
|
-
const matchResult = match ? match(stdout) : stdout.match(RSLIB_READY_MESSAGE) || stdout.match(
|
|
197
|
+
const matchResult = match ? match(stdout) : stdout.match(RSLIB_READY_MESSAGE) || stdout.match(TSUP_READY_MESSAGE);
|
|
190
198
|
if (matchResult) {
|
|
191
199
|
logger.flushStdout();
|
|
192
200
|
this.matched[node] = true;
|
|
@@ -260,6 +268,16 @@ function pluginWorkspaceDev(options) {
|
|
|
260
268
|
await runner.start();
|
|
261
269
|
Logger.setEndBanner();
|
|
262
270
|
});
|
|
271
|
+
api.onBeforeBuild(async ({ isWatch, isFirstCompile })=>{
|
|
272
|
+
if (!isWatch || !isFirstCompile) return;
|
|
273
|
+
const runner = new WorkspaceDevRunner({
|
|
274
|
+
cwd: rootPath,
|
|
275
|
+
...options
|
|
276
|
+
});
|
|
277
|
+
await runner.init();
|
|
278
|
+
await runner.start();
|
|
279
|
+
Logger.setEndBanner();
|
|
280
|
+
});
|
|
263
281
|
}
|
|
264
282
|
};
|
|
265
283
|
}
|
package/dist/types.d.ts
ADDED
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PackageWithScripts } from './types.js';
|
|
2
2
|
export declare const readJson: <T>(jsonFileAbsPath: string) => Promise<T>;
|
|
3
|
-
export declare const readPackageJson: (pkgJsonFilePath: string) => Promise<
|
|
3
|
+
export declare const readPackageJson: (pkgJsonFilePath: string) => Promise<PackageWithScripts["packageJson"]>;
|
|
4
4
|
export declare const isDebug: boolean;
|
package/dist/workspace-dev.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rsbuild-plugin-workspace-dev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
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",
|