rsbuild-plugin-workspace-dev 0.0.1-beta.0 → 0.0.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 +197 -1
- package/README.zh-CN.md +57 -10
- package/dist/index.cjs +24 -26
- package/dist/index.js +22 -24
- package/dist/logger.d.ts +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/workspace-dev.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1 +1,197 @@
|
|
|
1
|
-
# rsbuild-plugin-workspace-dev
|
|
1
|
+
# rsbuild-plugin-workspace-dev
|
|
2
|
+
|
|
3
|
+
Start monorepo sub-projects in topological order.
|
|
4
|
+
|
|
5
|
+
`rsbuild-plugin-workspace-dev` is designed for monorepo development. It computes the dependency graph starting from the current project and starts sub-projects in topological order.
|
|
6
|
+
|
|
7
|
+
<p>
|
|
8
|
+
<a href="https://npmjs.com/package/rsbuild-plugin-workspace-dev">
|
|
9
|
+
<img src="https://img.shields.io/npm/v/rsbuild-plugin-workspace-dev?style=flat-square&colorA=564341&colorB=EDED91" alt="npm version" />
|
|
10
|
+
</a>
|
|
11
|
+
<img src="https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square&colorA=564341&colorB=EDED91" alt="license" />
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
English | [简体中文](./README.zh-CN.md)
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
Install:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add rsbuild-plugin-workspace-dev -D
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Register the plugin in `rsbuild.config.ts`:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
// rsbuild.config.ts
|
|
28
|
+
import { pluginWorkspaceDev } from "rsbuild-plugin-workspace-dev";
|
|
29
|
+
|
|
30
|
+
export default {
|
|
31
|
+
plugins: [pluginWorkspaceDev()],
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Use Cases
|
|
36
|
+
|
|
37
|
+
In a monorepo, one project may depend on multiple sub-projects, and those sub-projects can also depend on each other.
|
|
38
|
+
|
|
39
|
+
For example, the monorepo contains an app and several lib packages:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
monorepo
|
|
43
|
+
├── app
|
|
44
|
+
└── lib1
|
|
45
|
+
└── lib2
|
|
46
|
+
└── lib3
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Here, app is built with Rsbuild, and lib is built with Rslib. The app depends on lib1 and lib2:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"name": "app",
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"lib1": "workspace:*",
|
|
56
|
+
"lib2": "workspace:*"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
lib2 depends on lib3:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"name": "lib2",
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"lib3": "workspace:*"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
When you run `pnpm dev` under app, sub-projects start in topological order: first lib1 and lib3, then lib2, and finally app. Starting a lib refers to running its dev command, for example:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"scripts": {
|
|
77
|
+
"dev": "rslib build --watch"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Whether a sub-project has finished starting is determined by matching sub-project logs. By default, logs from Rslib and tsup sub-projects are recognized. You can also provide a custom match function to determine when a sub-project is ready.
|
|
83
|
+
|
|
84
|
+
## Options
|
|
85
|
+
|
|
86
|
+
### projects
|
|
87
|
+
Configure how sub-projects are started and define custom log matching logic.
|
|
88
|
+
|
|
89
|
+
- Type:
|
|
90
|
+
```
|
|
91
|
+
type projects = {
|
|
92
|
+
// The key is the name of the sub-project's package.json file.
|
|
93
|
+
[key: string]: Projects;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface projects {
|
|
97
|
+
/**
|
|
98
|
+
* Custom sub-project start command. Default is `dev` (runs `npm run dev`).
|
|
99
|
+
*/
|
|
100
|
+
command?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Custom logic to detect when a sub-project has started.
|
|
103
|
+
* By default, logs from `Rsbuild` and `tsup` are supported.
|
|
104
|
+
*/
|
|
105
|
+
match?: (stdout: string) => boolean;
|
|
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;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
// For example, to configure lib1 sub-project to use build:watch command and match watch success log
|
|
115
|
+
pluginWorkspaceDev({
|
|
116
|
+
projects: {
|
|
117
|
+
lib1: {
|
|
118
|
+
command: 'build:watch',
|
|
119
|
+
match: (stdout) => stdout.includes('watch success'),
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
})
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### startCurrent
|
|
126
|
+
|
|
127
|
+
- Type: `boolean`
|
|
128
|
+
- Default: `false`
|
|
129
|
+
|
|
130
|
+
Whether to also start the current project. The default is `false`. In most cases, you start the current project manually, so the plugin does not interfere.
|
|
131
|
+
|
|
132
|
+
Consider a scenario where docs and lib are in the same project, and docs needs to debug the output of lib. In this case, you want to run `pnpm doc` for the docs, while lib should run `pnpm dev`. After configuring this option in your Rspress config, starting `pnpm doc` will automatically run `pnpm dev` to start the lib sub-project.
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
├── docs
|
|
136
|
+
│ └── index.mdx
|
|
137
|
+
├── package.json
|
|
138
|
+
├── src
|
|
139
|
+
│ └── Button.tsx
|
|
140
|
+
├── rslib.config.ts
|
|
141
|
+
├── rspress.config.ts
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
"scripts": {
|
|
146
|
+
"dev": "rslib build --watch",
|
|
147
|
+
"doc": "rspress dev"
|
|
148
|
+
},
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### cwd
|
|
152
|
+
|
|
153
|
+
- Type: `string`
|
|
154
|
+
- Default: `process.cwd()`
|
|
155
|
+
|
|
156
|
+
Set the current working directory. The default is the current project directory; usually no configuration is needed.
|
|
157
|
+
|
|
158
|
+
### workspaceFileDir
|
|
159
|
+
|
|
160
|
+
- Type: `string`
|
|
161
|
+
- Default: `process.cwd()`
|
|
162
|
+
|
|
163
|
+
Set the directory where the workspace file resides. The default is the current project directory; usually no configuration is needed.
|
|
164
|
+
|
|
165
|
+
## Frequently Asked Questions
|
|
166
|
+
|
|
167
|
+
### Project startup stuck
|
|
168
|
+
Stuck may be due to slow sub-project builds, etc. The lack of log output is because, by default, sub-project logs are output all at once after startup (to avoid interleaving sub-project logs). You can enable debug mode by adding an environment variable, which will allow sub-project logs to be output in real time.
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
DEBUG=rsbuild pnpm dev
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Some projects don't need to start
|
|
175
|
+
|
|
176
|
+
If some sub-projects don't need to start, simply configure `skip: true` for the specified project in `rsbuild.config.ts`.
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
// rsbuild.config.ts
|
|
180
|
+
import { pluginWorkspaceDev } from "rsbuild-plugin-workspace-dev";
|
|
181
|
+
|
|
182
|
+
export default {
|
|
183
|
+
plugins: [
|
|
184
|
+
pluginWorkspaceDev({
|
|
185
|
+
projects: {
|
|
186
|
+
lib1: {
|
|
187
|
+
skip: true,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
}),
|
|
191
|
+
],
|
|
192
|
+
};
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
[MIT](./LICENSE).
|
package/README.zh-CN.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
安装:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
|
|
19
|
+
pnpm add rsbuild-plugin-workspace-dev -D
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
在 `rsbuild.config.ts` 里注册插件:
|
|
@@ -78,12 +78,17 @@ lib2 依赖了 lib3:
|
|
|
78
78
|
|
|
79
79
|
## 选项
|
|
80
80
|
|
|
81
|
-
###
|
|
81
|
+
### projects
|
|
82
82
|
用于子项目的启动项配置和自定义日志匹配逻辑。
|
|
83
83
|
|
|
84
|
-
-
|
|
84
|
+
- **类型:**
|
|
85
85
|
```
|
|
86
|
-
|
|
86
|
+
type projects = {
|
|
87
|
+
// key 为子项目 package.json name
|
|
88
|
+
[key: string]: Projects;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
interface Projects {
|
|
87
92
|
/**
|
|
88
93
|
* 自定义子项目启动命令,默认值为 `dev`, 即执行 `npm run dev`。
|
|
89
94
|
*/
|
|
@@ -97,14 +102,26 @@ interface ProjectConfig {
|
|
|
97
102
|
*/
|
|
98
103
|
skip?: boolean;
|
|
99
104
|
}
|
|
105
|
+
|
|
106
|
+
// 例如,配置 lib1 子项目,用 build:watch 命令启动,匹配 watch success 日志
|
|
107
|
+
pluginWorkspaceDev({
|
|
108
|
+
projects: {
|
|
109
|
+
lib1: {
|
|
110
|
+
command: 'build:watch',
|
|
111
|
+
match: (stdout) => stdout.includes('watch success'),
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
})
|
|
100
115
|
```
|
|
101
116
|
|
|
102
|
-
|
|
117
|
+
|
|
118
|
+
### startCurrent
|
|
103
119
|
|
|
104
120
|
- **类型:** `boolean`
|
|
105
|
-
- **默认值:** `
|
|
106
|
-
|
|
107
|
-
|
|
121
|
+
- **默认值:** `false`
|
|
122
|
+
|
|
123
|
+
插件是否同时启动当前项目,默认值为 `false`。通常无需手动配置,当前项目通常由用户手动执行 dev 启动,无需插件干预。
|
|
124
|
+
|
|
108
125
|
考虑如下场景,docs 和 lib 是在同一个项目中,而 docs 需要调试 lib 的产物,此时需要启动 `pnpm doc` 命令,而 lib 则需要启动 `pnpm dev` 命令,配置该选项到 rspress 配置中后,启动 `pnpm doc` 时会自动执行 `pnpm dev` 命令,用于启动 lib 子项目。
|
|
109
126
|
```
|
|
110
127
|
├── docs
|
|
@@ -127,14 +144,44 @@ interface ProjectConfig {
|
|
|
127
144
|
- **类型:** `string`
|
|
128
145
|
- **默认值:** `process.cwd()`
|
|
129
146
|
|
|
130
|
-
|
|
147
|
+
用于配置当前工作目录,默认值为当前项目目录,通常无需配置。
|
|
131
148
|
|
|
132
149
|
### workspaceFileDir
|
|
133
150
|
|
|
134
151
|
- **类型:** `string`
|
|
135
152
|
- **默认值:** `process.cwd()`
|
|
136
153
|
|
|
137
|
-
用于配置 workspace
|
|
154
|
+
用于配置 workspace 文件目录,默认值为当前项目目录,通常无需配置。
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
## 常见问题
|
|
158
|
+
|
|
159
|
+
### 启动项目时卡住
|
|
160
|
+
卡住可能是因为子项目构建过慢等原因,没有日志输出是因为默认情况下子项目日志是启动完成后一次性输出的(为了避免子项目日志混和在一起交错输出),可以通过添加环境变量来开启调试模式,这会让子项目的日志实时输出。
|
|
161
|
+
```
|
|
162
|
+
DEBUG=rsbuild pnpm dev
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### 某些项目无需启动
|
|
166
|
+
如果某些子项目不需要启动,只需要在 `rsbuild.config.ts` 中给指定项目配置 `skip: true` 即可。
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
// rsbuild.config.ts
|
|
170
|
+
import { pluginWorkspaceDev } from "rsbuild-plugin-workspace-dev";
|
|
171
|
+
|
|
172
|
+
export default {
|
|
173
|
+
plugins: [
|
|
174
|
+
pluginWorkspaceDev({
|
|
175
|
+
projects: {
|
|
176
|
+
lib1: {
|
|
177
|
+
skip: true,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
}),
|
|
181
|
+
],
|
|
182
|
+
};
|
|
183
|
+
```
|
|
184
|
+
|
|
138
185
|
|
|
139
186
|
## License
|
|
140
187
|
|
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,21 @@ const DEBUG_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';
|
|
46
|
+
const external_fs_namespaceObject = require("fs");
|
|
47
|
+
var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
|
|
48
|
+
const external_json5_namespaceObject = require("json5");
|
|
49
|
+
var external_json5_default = /*#__PURE__*/ __webpack_require__.n(external_json5_namespaceObject);
|
|
50
|
+
async function pathExists(path) {
|
|
51
|
+
return external_fs_default().promises.access(path).then(()=>true).catch(()=>false);
|
|
52
|
+
}
|
|
53
|
+
const readJson = async (jsonFileAbsPath)=>{
|
|
54
|
+
if (!await pathExists(jsonFileAbsPath)) return {};
|
|
55
|
+
const content = await external_fs_default().promises.readFile(jsonFileAbsPath, 'utf-8');
|
|
56
|
+
const json = external_json5_default().parse(content);
|
|
57
|
+
return json;
|
|
58
|
+
};
|
|
59
|
+
const readPackageJson = async (pkgJsonFilePath)=>readJson(pkgJsonFilePath);
|
|
60
|
+
const isDebug = 'rsbuild' === process.env.DEBUG || '*' === process.env.DEBUG;
|
|
46
61
|
function _define_property(obj, key, value) {
|
|
47
62
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
48
63
|
value: value,
|
|
@@ -76,6 +91,7 @@ class Logger {
|
|
|
76
91
|
this.stdout = startBanner + this.stdout;
|
|
77
92
|
}
|
|
78
93
|
flushStdout() {
|
|
94
|
+
if (isDebug) return;
|
|
79
95
|
this.setBanner(this.name);
|
|
80
96
|
this.emitLog("stdout");
|
|
81
97
|
}
|
|
@@ -94,9 +110,8 @@ class Logger {
|
|
|
94
110
|
this.logTitle = DEBUG_LOG_TITLE;
|
|
95
111
|
}
|
|
96
112
|
}
|
|
97
|
-
const debugLog = (msg)=>{
|
|
98
|
-
|
|
99
|
-
if (isDebug) console.log(DEBUG_LOG_TITLE + msg);
|
|
113
|
+
const debugLog = (msg, prefix = DEBUG_LOG_TITLE)=>{
|
|
114
|
+
if (isDebug) console.log(prefix + msg);
|
|
100
115
|
};
|
|
101
116
|
const get_packages_namespaceObject = require("@manypkg/get-packages");
|
|
102
117
|
const external_child_process_namespaceObject = require("child_process");
|
|
@@ -104,20 +119,6 @@ const external_graphlib_namespaceObject = require("graphlib");
|
|
|
104
119
|
var external_graphlib_default = /*#__PURE__*/ __webpack_require__.n(external_graphlib_namespaceObject);
|
|
105
120
|
const external_path_namespaceObject = require("path");
|
|
106
121
|
var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
|
|
107
|
-
const external_fs_namespaceObject = require("fs");
|
|
108
|
-
var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_namespaceObject);
|
|
109
|
-
const external_json5_namespaceObject = require("json5");
|
|
110
|
-
var external_json5_default = /*#__PURE__*/ __webpack_require__.n(external_json5_namespaceObject);
|
|
111
|
-
async function pathExists(path) {
|
|
112
|
-
return external_fs_default().promises.access(path).then(()=>true).catch(()=>false);
|
|
113
|
-
}
|
|
114
|
-
const readJson = async (jsonFileAbsPath)=>{
|
|
115
|
-
if (!await pathExists(jsonFileAbsPath)) return {};
|
|
116
|
-
const content = await external_fs_default().promises.readFile(jsonFileAbsPath, 'utf-8');
|
|
117
|
-
const json = external_json5_default().parse(content);
|
|
118
|
-
return json;
|
|
119
|
-
};
|
|
120
|
-
const readPackageJson = async (pkgJsonFilePath)=>readJson(pkgJsonFilePath);
|
|
121
122
|
function workspace_dev_define_property(obj, key, value) {
|
|
122
123
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
123
124
|
value: value,
|
|
@@ -178,7 +179,7 @@ class WorkspaceDevRunner {
|
|
|
178
179
|
const promises = [];
|
|
179
180
|
const allNodes = this.getNodes();
|
|
180
181
|
const filterSelfNodes = allNodes.filter((node)=>node !== this.metaData.name);
|
|
181
|
-
const nodes = this.options.
|
|
182
|
+
const nodes = this.options.startCurrent ? allNodes : filterSelfNodes;
|
|
182
183
|
for (const node of nodes){
|
|
183
184
|
const dependencies = this.getDependencies(node) || [];
|
|
184
185
|
const canStart = dependencies.every((dep)=>{
|
|
@@ -201,12 +202,11 @@ class WorkspaceDevRunner {
|
|
|
201
202
|
const logger = new Logger({
|
|
202
203
|
name
|
|
203
204
|
});
|
|
204
|
-
const config = this.options?.
|
|
205
|
+
const config = this.options?.projects?.[name];
|
|
205
206
|
if (config?.skip) {
|
|
206
207
|
this.visited[node] = true;
|
|
207
208
|
this.visiting[node] = false;
|
|
208
209
|
debugLog(`Skip visit node: ${node}`);
|
|
209
|
-
logger.flushStdout();
|
|
210
210
|
logger.emitLogOnce('stdout', `skip visit node: ${name}`);
|
|
211
211
|
return this.start().then(()=>resolve());
|
|
212
212
|
}
|
|
@@ -224,11 +224,9 @@ class WorkspaceDevRunner {
|
|
|
224
224
|
});
|
|
225
225
|
child.stdout.on('data', async (data)=>{
|
|
226
226
|
const stdout = data.toString();
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
227
|
+
const content = data.toString().replace(/\n$/, '');
|
|
228
|
+
if (this.matched[node]) return void logger.emitLogOnce('stdout', content);
|
|
229
|
+
debugLog(content, `${name}: `);
|
|
232
230
|
logger.appendLog('stdout', stdout);
|
|
233
231
|
const match = config?.match;
|
|
234
232
|
const matchResult = match ? match(stdout) : stdout.match(RSLIB_READY_MESSAGE) || stdout.match(MODERN_MODULE_READY_MESSAGE) || stdout.match(TSUP_READY_MESSAGE);
|
|
@@ -277,7 +275,7 @@ class WorkspaceDevRunner {
|
|
|
277
275
|
workspace_dev_define_property(this, "matched", void 0);
|
|
278
276
|
workspace_dev_define_property(this, "metaData", void 0);
|
|
279
277
|
this.options = {
|
|
280
|
-
|
|
278
|
+
startCurrent: false,
|
|
281
279
|
...options
|
|
282
280
|
};
|
|
283
281
|
this.cwd = options.cwd || process.cwd();
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import json5 from "json5";
|
|
2
4
|
import { getPackagesSync } from "@manypkg/get-packages";
|
|
3
5
|
import { spawn } from "child_process";
|
|
4
6
|
import graphlib, { Graph } from "graphlib";
|
|
5
7
|
import path_0 from "path";
|
|
6
|
-
import fs from "fs";
|
|
7
|
-
import json5 from "json5";
|
|
8
8
|
const PACKAGE_JSON = 'package.json';
|
|
9
9
|
const DEBUG_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';
|
|
13
|
+
async function pathExists(path) {
|
|
14
|
+
return fs.promises.access(path).then(()=>true).catch(()=>false);
|
|
15
|
+
}
|
|
16
|
+
const readJson = async (jsonFileAbsPath)=>{
|
|
17
|
+
if (!await pathExists(jsonFileAbsPath)) return {};
|
|
18
|
+
const content = await fs.promises.readFile(jsonFileAbsPath, 'utf-8');
|
|
19
|
+
const json = json5.parse(content);
|
|
20
|
+
return json;
|
|
21
|
+
};
|
|
22
|
+
const readPackageJson = async (pkgJsonFilePath)=>readJson(pkgJsonFilePath);
|
|
23
|
+
const isDebug = 'rsbuild' === process.env.DEBUG || '*' === process.env.DEBUG;
|
|
13
24
|
function _define_property(obj, key, value) {
|
|
14
25
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
15
26
|
value: value,
|
|
@@ -43,6 +54,7 @@ class Logger {
|
|
|
43
54
|
this.stdout = startBanner + this.stdout;
|
|
44
55
|
}
|
|
45
56
|
flushStdout() {
|
|
57
|
+
if (isDebug) return;
|
|
46
58
|
this.setBanner(this.name);
|
|
47
59
|
this.emitLog("stdout");
|
|
48
60
|
}
|
|
@@ -61,20 +73,9 @@ class Logger {
|
|
|
61
73
|
this.logTitle = DEBUG_LOG_TITLE;
|
|
62
74
|
}
|
|
63
75
|
}
|
|
64
|
-
const debugLog = (msg)=>{
|
|
65
|
-
|
|
66
|
-
if (isDebug) console.log(DEBUG_LOG_TITLE + msg);
|
|
67
|
-
};
|
|
68
|
-
async function pathExists(path) {
|
|
69
|
-
return fs.promises.access(path).then(()=>true).catch(()=>false);
|
|
70
|
-
}
|
|
71
|
-
const readJson = async (jsonFileAbsPath)=>{
|
|
72
|
-
if (!await pathExists(jsonFileAbsPath)) return {};
|
|
73
|
-
const content = await fs.promises.readFile(jsonFileAbsPath, 'utf-8');
|
|
74
|
-
const json = json5.parse(content);
|
|
75
|
-
return json;
|
|
76
|
+
const debugLog = (msg, prefix = DEBUG_LOG_TITLE)=>{
|
|
77
|
+
if (isDebug) console.log(prefix + msg);
|
|
76
78
|
};
|
|
77
|
-
const readPackageJson = async (pkgJsonFilePath)=>readJson(pkgJsonFilePath);
|
|
78
79
|
function workspace_dev_define_property(obj, key, value) {
|
|
79
80
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
80
81
|
value: value,
|
|
@@ -135,7 +136,7 @@ class WorkspaceDevRunner {
|
|
|
135
136
|
const promises = [];
|
|
136
137
|
const allNodes = this.getNodes();
|
|
137
138
|
const filterSelfNodes = allNodes.filter((node)=>node !== this.metaData.name);
|
|
138
|
-
const nodes = this.options.
|
|
139
|
+
const nodes = this.options.startCurrent ? allNodes : filterSelfNodes;
|
|
139
140
|
for (const node of nodes){
|
|
140
141
|
const dependencies = this.getDependencies(node) || [];
|
|
141
142
|
const canStart = dependencies.every((dep)=>{
|
|
@@ -158,12 +159,11 @@ class WorkspaceDevRunner {
|
|
|
158
159
|
const logger = new Logger({
|
|
159
160
|
name
|
|
160
161
|
});
|
|
161
|
-
const config = this.options?.
|
|
162
|
+
const config = this.options?.projects?.[name];
|
|
162
163
|
if (config?.skip) {
|
|
163
164
|
this.visited[node] = true;
|
|
164
165
|
this.visiting[node] = false;
|
|
165
166
|
debugLog(`Skip visit node: ${node}`);
|
|
166
|
-
logger.flushStdout();
|
|
167
167
|
logger.emitLogOnce('stdout', `skip visit node: ${name}`);
|
|
168
168
|
return this.start().then(()=>resolve());
|
|
169
169
|
}
|
|
@@ -181,11 +181,9 @@ class WorkspaceDevRunner {
|
|
|
181
181
|
});
|
|
182
182
|
child.stdout.on('data', async (data)=>{
|
|
183
183
|
const stdout = data.toString();
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
184
|
+
const content = data.toString().replace(/\n$/, '');
|
|
185
|
+
if (this.matched[node]) return void logger.emitLogOnce('stdout', content);
|
|
186
|
+
debugLog(content, `${name}: `);
|
|
189
187
|
logger.appendLog('stdout', stdout);
|
|
190
188
|
const match = config?.match;
|
|
191
189
|
const matchResult = match ? match(stdout) : stdout.match(RSLIB_READY_MESSAGE) || stdout.match(MODERN_MODULE_READY_MESSAGE) || stdout.match(TSUP_READY_MESSAGE);
|
|
@@ -234,7 +232,7 @@ class WorkspaceDevRunner {
|
|
|
234
232
|
workspace_dev_define_property(this, "matched", void 0);
|
|
235
233
|
workspace_dev_define_property(this, "metaData", void 0);
|
|
236
234
|
this.options = {
|
|
237
|
-
|
|
235
|
+
startCurrent: false,
|
|
238
236
|
...options
|
|
239
237
|
};
|
|
240
238
|
this.cwd = options.cwd || process.cwd();
|
package/dist/logger.d.ts
CHANGED
package/dist/utils.d.ts
CHANGED
package/dist/workspace-dev.d.ts
CHANGED
|
@@ -2,12 +2,12 @@ import graphlib from 'graphlib';
|
|
|
2
2
|
export interface WorkspaceDevRunnerOptions {
|
|
3
3
|
cwd?: string;
|
|
4
4
|
workspaceFileDir?: string;
|
|
5
|
-
|
|
5
|
+
projects?: Record<string, {
|
|
6
6
|
match?: (stdout: string) => boolean;
|
|
7
7
|
command?: string;
|
|
8
8
|
skip?: boolean;
|
|
9
9
|
}>;
|
|
10
|
-
|
|
10
|
+
startCurrent?: boolean;
|
|
11
11
|
}
|
|
12
12
|
export declare class WorkspaceDevRunner {
|
|
13
13
|
private options;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rsbuild-plugin-workspace-dev",
|
|
3
|
-
"version": "0.0.1
|
|
3
|
+
"version": "0.0.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",
|