@chrisluyi/daas-cli 1.2.0 → 1.2.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 +405 -0
- package/package.json +1 -1
- package/dist/daas-bin +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# daas-cli
|
|
2
|
+
|
|
3
|
+
Zero-config build/dev/test CLI for React micro-frontend (MFE) apps using [rsbuild](https://rsbuild.dev) + [Module Federation 2](https://module-federation.io).
|
|
4
|
+
|
|
5
|
+
MFE apps have **no build config files** — no `rsbuild.config.ts`, no `vitest.config.ts`. The CLI owns all of it.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Packages
|
|
10
|
+
|
|
11
|
+
| Package | Version | Description |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| [`@chrisluyi/daas-cli`](https://www.npmjs.com/package/@chrisluyi/daas-cli) | 1.1.0 | CLI binary — install this as your only devDependency |
|
|
14
|
+
| [`@chrisluyi/rsbuild-config`](https://www.npmjs.com/package/@chrisluyi/rsbuild-config) | 1.1.0 | rsbuild config factory + vitest config — arrives transitively |
|
|
15
|
+
| [`@chrisluyi/template`](https://www.npmjs.com/package/@chrisluyi/template) | 1.0.0 | MFE scaffold templates (services / containers / components structure) |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quickstart (3 commands)
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
mkdir my-mfe && cd my-mfe
|
|
23
|
+
echo '{"name":"my-mfe"}' > package.json
|
|
24
|
+
npx @chrisluyi/daas-cli init
|
|
25
|
+
bun install
|
|
26
|
+
daas dev
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Your MFE is now running at `http://localhost:3000` with Module Federation 2, React, hot-reload, and Vitest — zero config required.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# In your MFE project
|
|
37
|
+
bun add -D @chrisluyi/daas-cli
|
|
38
|
+
|
|
39
|
+
# or npm
|
|
40
|
+
npm install -D @chrisluyi/daas-cli
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`daas-cli` is the **only** devDependency you need. It ships rsbuild, vitest, @testing-library/react, happy-dom, and all tooling as its own dependencies. Do not install these separately.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Commands
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
daas init [--template default]
|
|
51
|
+
daas dev [target] [--port <n>] [--json]
|
|
52
|
+
daas build [target] [--json]
|
|
53
|
+
daas test [--json]
|
|
54
|
+
daas info [--json]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### `daas init`
|
|
58
|
+
|
|
59
|
+
Interactive scaffold powered by `@clack/prompts`. Prompts for remote config URL, port, and app name, then writes starter files.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
┌ daas-cli — scaffold new MFE
|
|
63
|
+
│
|
|
64
|
+
◇ Remote config URL?
|
|
65
|
+
│ https://your-org.example.com/daas-config.json
|
|
66
|
+
│
|
|
67
|
+
◇ Dev server port?
|
|
68
|
+
│ 3001
|
|
69
|
+
│
|
|
70
|
+
◇ App name? (leave blank to use package.json name)
|
|
71
|
+
│ mfe-auth
|
|
72
|
+
│
|
|
73
|
+
◇ Does this app expose additional components beyond ./App?
|
|
74
|
+
│ No
|
|
75
|
+
│
|
|
76
|
+
◆ Scaffolding mfe-auth...
|
|
77
|
+
│ ✓ Created src/App.tsx
|
|
78
|
+
│ ✓ Created src/App.test.tsx
|
|
79
|
+
│ ✓ Created tsconfig.json
|
|
80
|
+
│ ✓ Updated package.json
|
|
81
|
+
│
|
|
82
|
+
└ Done! Run: bun install && daas dev
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**What gets created (minimal scaffold):**
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
src/
|
|
89
|
+
├── App.tsx # minimal React component
|
|
90
|
+
└── App.test.tsx # smoke test
|
|
91
|
+
tsconfig.json # jsx: react-jsx, strict mode
|
|
92
|
+
package.json # scripts + daas config injected
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**`--template default`** scaffolds the full opinionated structure:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
src/
|
|
99
|
+
├── App.tsx # entry — renders AppContainer
|
|
100
|
+
├── containers/
|
|
101
|
+
│ └── AppContainer.tsx # data-fetching component
|
|
102
|
+
├── components/
|
|
103
|
+
│ └── App.tsx # presentational component
|
|
104
|
+
├── services/
|
|
105
|
+
│ └── index.ts # service layer stub
|
|
106
|
+
└── config/
|
|
107
|
+
├── regions/ # per-region config (for v1.5 targets)
|
|
108
|
+
├── platforms/ # per-platform config
|
|
109
|
+
└── products/ # per-product config
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `daas dev`
|
|
113
|
+
|
|
114
|
+
Starts the rsbuild dev server with HMR and Module Federation 2 in remote mode.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
daas dev # uses port from package.json#daas
|
|
118
|
+
daas dev --port 3002 # override port at runtime
|
|
119
|
+
daas dev sg-foo-mb-dev # v1.5: activate region/product/platform target
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### `daas build`
|
|
123
|
+
|
|
124
|
+
Production build to `./dist`. Always fetches fresh remote config — fatal if network unavailable.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
daas build
|
|
128
|
+
daas build sg-foo-mb-prod # v1.5: build for a specific target
|
|
129
|
+
daas build --json # machine-readable output (for CI / AI agents)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### `daas test`
|
|
133
|
+
|
|
134
|
+
Runs Vitest with `happy-dom`, `@testing-library/react`, and `@testing-library/jest-dom` pre-configured. The following browser APIs are mocked automatically so MFE tests work without any extra setup:
|
|
135
|
+
|
|
136
|
+
- `window.matchMedia`
|
|
137
|
+
- `ResizeObserver`
|
|
138
|
+
- `IntersectionObserver`
|
|
139
|
+
- `window.scrollTo` / `scrollBy`
|
|
140
|
+
- `URL.createObjectURL` / `revokeObjectURL`
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
daas test
|
|
144
|
+
daas test --json
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Writing tests** — import everything from `@chrisluyi/daas-cli/test` (no direct vitest or `@testing-library` imports needed):
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
import { render, screen, describe, test, expect, userEvent } from "@chrisluyi/daas-cli/test"
|
|
151
|
+
import MyComponent from "./MyComponent"
|
|
152
|
+
|
|
153
|
+
describe("MyComponent", () => {
|
|
154
|
+
test("renders a button", async () => {
|
|
155
|
+
render(<MyComponent />)
|
|
156
|
+
await userEvent.click(screen.getByRole("button"))
|
|
157
|
+
expect(screen.getByText("Clicked!")).toBeInTheDocument()
|
|
158
|
+
})
|
|
159
|
+
})
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Adding extra setup** — append your own setup files after the built-in mocks via `package.json#daas.setupFiles`:
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"daas": {
|
|
167
|
+
"configUrl": "...",
|
|
168
|
+
"port": 3001,
|
|
169
|
+
"setupFiles": ["./src/test-setup.ts"]
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Your setup file can override any of the default mocks or add new ones.
|
|
175
|
+
|
|
176
|
+
### `daas info`
|
|
177
|
+
|
|
178
|
+
Prints the fully resolved project state — useful for debugging and AI agent diagnosis.
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
daas info --json
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Example output:
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"ok": true,
|
|
189
|
+
"command": "info",
|
|
190
|
+
"cliVersion": "1.1.0",
|
|
191
|
+
"appName": "mfe-auth",
|
|
192
|
+
"port": 3001,
|
|
193
|
+
"configUrl": "https://your-org.example.com/daas-config.json",
|
|
194
|
+
"manifest": {
|
|
195
|
+
"name": "mfe-auth",
|
|
196
|
+
"exposes": { "./App": "./src/App" }
|
|
197
|
+
},
|
|
198
|
+
"remoteJson": {
|
|
199
|
+
"version": "1.0.0",
|
|
200
|
+
"minCliVersion": "1.0.0",
|
|
201
|
+
"shared": { "react": "18.3.1", "react-dom": "18.3.1" },
|
|
202
|
+
"rsbuildConfigVersion": 1
|
|
203
|
+
},
|
|
204
|
+
"isMonorepo": false
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Per-App Config (`package.json#daas`)
|
|
211
|
+
|
|
212
|
+
All MFE-specific configuration lives in `package.json`:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"name": "mfe-auth",
|
|
217
|
+
"scripts": {
|
|
218
|
+
"dev": "daas dev",
|
|
219
|
+
"build": "daas build",
|
|
220
|
+
"test": "daas test"
|
|
221
|
+
},
|
|
222
|
+
"devDependencies": {
|
|
223
|
+
"@chrisluyi/daas-cli": "^1.1.0"
|
|
224
|
+
},
|
|
225
|
+
"daas": {
|
|
226
|
+
"configUrl": "https://your-org.example.com/daas-config.json",
|
|
227
|
+
"port": 3001,
|
|
228
|
+
"coverage": {
|
|
229
|
+
"lines": 80,
|
|
230
|
+
"branches": 80
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
| Field | Required | Description |
|
|
237
|
+
|---|---|---|
|
|
238
|
+
| `configUrl` | Yes | URL of the remote JSON config owned by your platform team |
|
|
239
|
+
| `port` | Yes | Dev server port — must be unique per MFE in a monorepo |
|
|
240
|
+
| `coverage` | No | Vitest coverage thresholds |
|
|
241
|
+
| `setupFiles` | No | Extra Vitest setup files appended after the built-in browser mocks |
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Optional Manifest (`mf.manifest.json`)
|
|
246
|
+
|
|
247
|
+
Only needed when exposing more than just `./App`:
|
|
248
|
+
|
|
249
|
+
```json
|
|
250
|
+
{
|
|
251
|
+
"name": "mfe-auth",
|
|
252
|
+
"exposes": {
|
|
253
|
+
"./App": "./src/App",
|
|
254
|
+
"./LoginButton": "./src/components/LoginButton"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
If absent, `name` derives from `package.json#name` (scope stripped), and `exposes` defaults to `{ "./App": "./src/App" }`.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Remote JSON (served by your platform team)
|
|
264
|
+
|
|
265
|
+
The URL in `configUrl` must serve a JSON file like this:
|
|
266
|
+
|
|
267
|
+
```json
|
|
268
|
+
{
|
|
269
|
+
"version": "1.0.0",
|
|
270
|
+
"minCliVersion": "1.0.0",
|
|
271
|
+
"releaseNotesUrl": "https://your-org.example.com/daas-cli/releases",
|
|
272
|
+
"shared": {
|
|
273
|
+
"react": "18.3.1",
|
|
274
|
+
"react-dom": "18.3.1"
|
|
275
|
+
},
|
|
276
|
+
"rsbuildConfigVersion": 1
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
This controls which version of shared dependencies all your MFEs use via Module Federation 2's singleton negotiation. The CLI fetches this at dev startup (5-min cache) and always fresh at build time.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Monorepo Support
|
|
285
|
+
|
|
286
|
+
`daas init` detects monorepos by walking parent directories for `bun.lockb` or `package.json#workspaces`. In a monorepo:
|
|
287
|
+
|
|
288
|
+
- `daas-cli` is **not** added to the app's `devDependencies` (it's resolved from the workspace root)
|
|
289
|
+
- Each MFE has its own `port` in `package.json#daas`
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
my-monorepo/
|
|
293
|
+
├── package.json # workspaces: ["packages/*"]
|
|
294
|
+
├── bun.lockb
|
|
295
|
+
└── packages/
|
|
296
|
+
├── mfe-auth/ # daas dev → port 3001
|
|
297
|
+
│ └── package.json # { "daas": { "port": 3001, ... } }
|
|
298
|
+
└── mfe-dashboard/ # daas dev → port 3002
|
|
299
|
+
└── package.json # { "daas": { "port": 3002, ... } }
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## v1.5 — Multi-Region Target System
|
|
305
|
+
|
|
306
|
+
Target strings let you select region/product/platform/environment at dev and build time:
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
daas dev sg-foo-mb-dev
|
|
310
|
+
│ │ │ └─ environment (dev / staging / prod)
|
|
311
|
+
│ │ └──── platform (mb = mobile, wb = web, etc.)
|
|
312
|
+
│ └──────── product (may contain hyphens)
|
|
313
|
+
└──────────── region (sg, us, eu, …)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
When a target is provided:
|
|
317
|
+
1. The CLI resolves a `TargetContext` from the string
|
|
318
|
+
2. `tsconfig.daas.json` is generated (gitignored) with path aliases:
|
|
319
|
+
- `@region-config` → `./src/config/regions/<region>`
|
|
320
|
+
- `@platform-config` → `./src/config/platforms/<platform>`
|
|
321
|
+
- `@product-config` → `./src/config/products/<product>`
|
|
322
|
+
3. Environment variables are injected at build time: `DAAS_REGION`, `DAAS_PRODUCT`, `DAAS_PLATFORM`, `DAAS_ENV`
|
|
323
|
+
|
|
324
|
+
Use `daas init --template default` to scaffold the config layer folder structure.
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Exit Codes
|
|
329
|
+
|
|
330
|
+
| Code | Meaning | What to do |
|
|
331
|
+
|---|---|---|
|
|
332
|
+
| `0` | Success | — |
|
|
333
|
+
| `1` | General error (build/test failure) | Check output above the JSON |
|
|
334
|
+
| `2` | Config error (missing `configUrl`, bad manifest) | Run `daas init` or fix `package.json#daas` |
|
|
335
|
+
| `3` | CLI too old (`minCliVersion` not met) | Upgrade `@chrisluyi/daas-cli` |
|
|
336
|
+
| `4` | Remote JSON fetch failed | Check network / VPN (only fatal in `build`) |
|
|
337
|
+
| `5` | Config version mismatch | Upgrade `@chrisluyi/daas-cli` |
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## `--json` Output Contract
|
|
342
|
+
|
|
343
|
+
All commands except `init` support `--json` — always use this in CI and AI agent workflows.
|
|
344
|
+
|
|
345
|
+
**Success:**
|
|
346
|
+
```json
|
|
347
|
+
{
|
|
348
|
+
"ok": true,
|
|
349
|
+
"command": "build",
|
|
350
|
+
"appName": "mfe-auth",
|
|
351
|
+
"output": "./dist",
|
|
352
|
+
"cliVersion": "1.1.0"
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**Error:**
|
|
357
|
+
```json
|
|
358
|
+
{
|
|
359
|
+
"ok": false,
|
|
360
|
+
"command": "build",
|
|
361
|
+
"exitCode": 4,
|
|
362
|
+
"error": "Could not fetch remote config: HTTP 503",
|
|
363
|
+
"suggestion": "Check network connectivity or VPN.",
|
|
364
|
+
"cliVersion": "1.1.0"
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## AI Agent Support (Claude Code)
|
|
371
|
+
|
|
372
|
+
Register the bundled skill so Claude Code understands `daas-cli` without hallucinating commands:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
# Per-project
|
|
376
|
+
mkdir -p .claude/skills
|
|
377
|
+
cp node_modules/@chrisluyi/daas-cli/skill.md .claude/skills/daas-cli.md
|
|
378
|
+
|
|
379
|
+
# Or globally
|
|
380
|
+
cp node_modules/@chrisluyi/daas-cli/skill.md ~/.claude/skills/daas-cli.md
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**AI agent workflow:**
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
# 1. Always start here to understand current state
|
|
387
|
+
daas info --json
|
|
388
|
+
|
|
389
|
+
# 2. Run commands and parse stdout JSON
|
|
390
|
+
daas build --json
|
|
391
|
+
# { "ok": true, ... } or { "ok": false, "exitCode": N, "error": "...", "suggestion": "..." }
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Development (this repo)
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
bun install
|
|
400
|
+
bun test # run all tests
|
|
401
|
+
bun run build # build both packages to dist/
|
|
402
|
+
bun run lint # biome check
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
See [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md) for the full release workflow.
|
package/package.json
CHANGED
package/dist/daas-bin
DELETED
|
Binary file
|