@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.
Files changed (3) hide show
  1. package/README.md +405 -0
  2. package/package.json +1 -1
  3. 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrisluyi/daas-cli",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "daas": "./dist/index.js"
package/dist/daas-bin DELETED
Binary file