@fluojs/cli 1.0.0-beta.4 → 1.0.0-beta.5
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.ko.md +63 -0
- package/README.md +63 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +171 -4
- package/dist/commands/diagnostics.d.ts +15 -0
- package/dist/commands/diagnostics.d.ts.map +1 -0
- package/dist/commands/diagnostics.js +163 -0
- package/dist/commands/new.js +2 -2
- package/dist/commands/package-manager.d.ts +9 -0
- package/dist/commands/package-manager.d.ts.map +1 -0
- package/dist/commands/package-manager.js +63 -0
- package/dist/commands/package-workflow.d.ts +20 -0
- package/dist/commands/package-workflow.d.ts.map +1 -0
- package/dist/commands/package-workflow.js +137 -0
- package/dist/commands/scripts.d.ts +38 -0
- package/dist/commands/scripts.d.ts.map +1 -0
- package/dist/commands/scripts.js +418 -0
- package/dist/dev-runner/node-restart-runner.d.ts +50 -0
- package/dist/dev-runner/node-restart-runner.d.ts.map +1 -0
- package/dist/dev-runner/node-restart-runner.js +248 -0
- package/dist/generators/manifest.d.ts +24 -0
- package/dist/generators/manifest.d.ts.map +1 -1
- package/dist/generators/manifest.js +9 -0
- package/dist/generators/resource.d.ts +10 -0
- package/dist/generators/resource.d.ts.map +1 -0
- package/dist/generators/resource.js +23 -0
- package/dist/generators/templates/controller.ts.ejs +5 -1
- package/dist/generators/templates/request-dto.ts.ejs +3 -0
- package/dist/new/scaffold.d.ts.map +1 -1
- package/dist/new/scaffold.js +62 -13
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.d.ts.map +1 -1
- package/dist/update-check.js +7 -5
- package/package.json +2 -2
package/README.ko.md
CHANGED
|
@@ -7,6 +7,7 @@ fluo 공식 CLI — 새 애플리케이션 부트스트랩, 컴포넌트 생성,
|
|
|
7
7
|
## 목차
|
|
8
8
|
|
|
9
9
|
- [설치](#설치)
|
|
10
|
+
- [버전 확인](#버전-확인)
|
|
10
11
|
- [업데이트 확인](#업데이트-확인)
|
|
11
12
|
- [사용 시점](#사용-시점)
|
|
12
13
|
- [빠른 시작](#빠른-시작)
|
|
@@ -33,10 +34,22 @@ pnpm dlx @fluojs/cli new my-app
|
|
|
33
34
|
- 지원되는 설치 경로는 전역 패키지(`npm install -g @fluojs/cli`, `pnpm add -g @fluojs/cli`, `bun add -g @fluojs/cli`, `yarn global add @fluojs/cli`)와 무설치 실행 경로(`pnpm dlx @fluojs/cli ...`)입니다.
|
|
34
35
|
- 배포되는 `fluo` bin은 `package.json`에 선언된 dist 빌드 CLI 엔트리포인트를 기준으로 동작합니다.
|
|
35
36
|
|
|
37
|
+
## 버전 확인
|
|
38
|
+
|
|
39
|
+
Interactive update check를 실행하지 않고 설치된 CLI 버전을 확인합니다:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
fluo version
|
|
43
|
+
fluo --version
|
|
44
|
+
fluo -v
|
|
45
|
+
```
|
|
46
|
+
|
|
36
47
|
## 업데이트 확인
|
|
37
48
|
|
|
38
49
|
`fluo`가 interactive TTY에서 실행되면 로컬 캐시를 사용해 공개 npm `latest` dist-tag의 `@fluojs/cli` 버전을 확인하므로 매 invocation마다 registry를 호출하지 않습니다. 더 새로운 버전이 있으면 CLI가 설치 여부를 묻습니다. 거절하면 현재 설치된 버전으로 기존 명령을 계속 실행하고, 승인하면 현재 설치를 소유한 것으로 보이는 package manager의 전역 업데이트 명령(`npm install -g`, `pnpm add -g`, `bun add -g`, `yarn global add`)을 사용한 뒤 같은 인자로 업데이트된 `fluo` 바이너리를 다시 시작합니다. 설치 도구를 추론할 수 없으면 Node.js 기본 전역 설치 경로를 소유하는 npm 기준으로 `npm install -g @fluojs/cli@<latest>`를 fallback으로 사용합니다.
|
|
39
50
|
|
|
51
|
+
`fluo new`와 alias인 `fluo create`는 일반 update-check cache가 아직 fresh하더라도 스캐폴딩 전에 interactive 최신 버전 확인을 새로 시도합니다. 이를 통해 첫 프로젝트 생성 경로가 방금 배포된 starter 동작과 더 잘 맞춰지며, `fluo dev`, `fluo build`, `fluo generate`, `fluo inspect` 같은 일상 명령은 기존처럼 일반 TTL이 만료될 때까지 cached latest-version 결과를 재사용합니다.
|
|
52
|
+
|
|
40
53
|
업데이트 확인은 CI, non-TTY 출력, npm-script context, 업데이트 후 재실행 context, registry/network 실패, 명시적 opt-out 경로에서는 건너뜁니다. 한 번만 끄려면 `--no-update-check`(또는 compatibility alias `--no-update-notifier`)를 사용하고, 자동화에서 절대 prompt가 뜨면 안 되는 경우에는 `FLUO_NO_UPDATE_CHECK=1`을 설정하세요.
|
|
41
54
|
|
|
42
55
|
## 사용 시점
|
|
@@ -57,6 +70,10 @@ cd my-app
|
|
|
57
70
|
pnpm dev
|
|
58
71
|
```
|
|
59
72
|
|
|
73
|
+
생성된 `dev`, `build`, `start` package script는 각각 `fluo dev`, `fluo build`, `fluo start`로 위임합니다. CLI가 런타임별 lifecycle 명령을 소유하고 local toolchain binary를 실행할 때 project-local `node_modules/.bin`을 앞에 붙이며, 호출자가 명시하지 않은 경우 `dev`는 `NODE_ENV=development`, `build`/`start`는 `NODE_ENV=production`을 기본값으로 사용합니다. `fluo dev`는 TTY-aware lifecycle reporter를 사용합니다. Interactive terminal에서는 간결한 fluo-branded status를 보여주고, CI, non-TTY 출력, `--reporter stream`, `--verbose`, `FLUO_VERBOSE=1`에서는 디버깅과 자동화를 위해 raw child-process passthrough를 유지합니다. Cloudflare Workers의 `start`는 배포하지 않고 Wrangler remote preview를 열며, Cloudflare에 게시하려면 명시적인 deploy 명령을 사용하세요.
|
|
74
|
+
|
|
75
|
+
Node.js 프로젝트에서 `fluo dev`는 더 이상 곧바로 `node --watch`에 위임하지 않고 fluo가 소유한 restart boundary를 거칩니다. 이 runner는 source와 주요 config 입력을 watch하고, atomic-save event burst를 debounce하며, restart 전에 파일 content hash를 비교하고, spawn하는 각 앱 child process마다 `.env`를 로드하며, `node_modules`, `dist`, `.git`, `.fluo`, coverage, cache 폴더, editor swap file 같은 noisy output/cache 경로를 무시합니다. 파일 내용이 바뀌지 않은 Ctrl+S 저장은 앱을 재시작하지 않아야 합니다. 계획된 restart가 아닌 terminal 앱 child exit 또는 crash가 발생하면 runner는 watcher를 닫고, pending restart timer와 path를 비우며, `SIGINT`/`SIGTERM` handler를 등록 해제하고, child의 terminal code로 종료합니다. 이 동작은 여전히 full-process restart-on-watch이며 true module-level HMR이 아닙니다. Config watch reload는 별도의 in-process config 관심사이고, 향후 HMR 작업은 어떤 모듈을 안전하게 hot-swap할 수 있는지 따로 문서화해야 합니다. 디버깅을 위해 런타임 native Node watcher로 되돌리려면 `fluo dev --raw-watch` 또는 `FLUO_DEV_RAW_WATCH=1`을 사용하고, 추가 ignore 경로는 `FLUO_DEV_WATCH_IGNORE=path,pattern`으로 지정하세요.
|
|
76
|
+
|
|
60
77
|
`fluo new`는 같은 Node 기반 설치/빌드 흐름 위에서 Node.js + Fastify, Express, raw Node.js HTTP 애플리케이션 스타터를 제공합니다.
|
|
61
78
|
|
|
62
79
|
```bash
|
|
@@ -114,12 +131,15 @@ plan preview 모드는 실제 scaffold와 같은 프로젝트 이름, shape, run
|
|
|
114
131
|
|
|
115
132
|
```bash
|
|
116
133
|
fluo generate module users
|
|
134
|
+
fluo generate resource users
|
|
117
135
|
fluo generate controller users
|
|
118
136
|
fluo generate service users
|
|
119
137
|
fluo generate request-dto users CreateUser
|
|
120
138
|
fluo generate service users --dry-run
|
|
121
139
|
```
|
|
122
140
|
|
|
141
|
+
`fluo generate resource <name>`는 module, controller, service, repository, request DTO, response DTO, test를 포함하는 완전한 feature slice를 생성합니다. 생성된 resource module은 parent module에 자동으로 연결하지 않으므로, slice를 활성화할 준비가 되었을 때 직접 import하세요.
|
|
142
|
+
|
|
123
143
|
Request DTO 생성은 feature 디렉터리와 DTO 클래스 이름을 분리해서 받습니다. 따라서 `CreateUser`, `UpdateUser` 같은 여러 입력 계약을 같은 `src/users/` 슬라이스 안에 둘 수 있습니다.
|
|
124
144
|
|
|
125
145
|
`--dry-run`을 추가하면 실제 실행과 같은 타깃 해석, 기존 파일 건너뛰기 또는 덮어쓰기 판단, 모듈 자동 등록 계획, 파일만 생성하는 wiring 상태, 다음 단계 힌트를 미리 볼 수 있습니다. 이 모드는 디렉터리 생성, 파일 쓰기, 모듈 갱신을 수행하지 않습니다. `--force`는 내용이 달라질 기존 파일의 계획 항목을 `SKIP`에서 `OVERWRITE`로 바꾸며, `--target-directory`는 실제 실행과 동일하게 지정한 소스 디렉터리 기준으로 preview 범위를 제한합니다.
|
|
@@ -128,6 +148,49 @@ Generator discovery는 의도적으로 built-in `@fluojs/cli/builtin` collection
|
|
|
128
148
|
|
|
129
149
|
## 주요 패턴
|
|
130
150
|
|
|
151
|
+
### 진단과 프로젝트 스크립트
|
|
152
|
+
설치된 CLI, npm dist-tag, update-check cache 상태, runtime, project script를 확인해야 할 때는 `doctor`/`info`를 사용합니다:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
fluo doctor
|
|
156
|
+
fluo info
|
|
157
|
+
fluo analyze
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`fluo analyze`는 read-only로 동작하며 더 깊은 `inspect --report`와 `migrate --json` workflow를 안내합니다. 생성된 프로젝트에서는 `fluo dev`, `fluo build`, `fluo start`가 환경 기본값 및 project-local toolchain binary와 함께 생성 lifecycle을 직접 실행합니다. lifecycle 명령은 `--dry-run`으로 미리 확인할 수 있습니다:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
fluo dev --dry-run
|
|
164
|
+
fluo build --dry-run
|
|
165
|
+
fluo start --dry-run
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`fluo dev --dry-run`은 watch boundary도 함께 표시합니다. Node.js 프로젝트는 기본적으로 `Watch mode: fluo-node-restart`를 보여 주며, `--raw-watch` 또는 `FLUO_DEV_RAW_WATCH=1`을 쓰면 `Watch mode: native-watch`를 보여 줍니다. Bun, Deno, Cloudflare Workers는 계속 각 런타임의 native dev watcher를 사용합니다.
|
|
169
|
+
|
|
170
|
+
CLI process boundary를 조정해야 할 때는 런타임 앱 로깅이 아니라 reporter flag를 사용하세요:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# TTY에서는 pretty status, CI/non-TTY에서는 raw passthrough (기본값)
|
|
174
|
+
fluo dev
|
|
175
|
+
|
|
176
|
+
# child process log를 디버깅하기 위한 기존 passthrough에 가까운 출력
|
|
177
|
+
fluo dev --reporter stream
|
|
178
|
+
fluo dev --verbose
|
|
179
|
+
FLUO_VERBOSE=1 fluo dev
|
|
180
|
+
|
|
181
|
+
# child stderr와 실패는 보존하면서 wrapper/tool status는 숨김
|
|
182
|
+
fluo build --reporter silent
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
런타임 애플리케이션 로그는 `ApplicationLogger`로 별도 설정합니다. 예를 들어 `@fluojs/runtime/node`의 `createConsoleApplicationLogger({ mode: 'minimal', level: 'warn' })` 또는 `createJsonApplicationLogger()`를 사용하세요.
|
|
186
|
+
|
|
187
|
+
first-party package 설치 shortcut에는 `fluo add <package>`를 사용하고, CLI/latest-version 및 migration 안내는 `fluo upgrade`로 확인합니다:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
fluo add studio --dev --dry-run
|
|
191
|
+
fluo upgrade
|
|
192
|
+
```
|
|
193
|
+
|
|
131
194
|
### 데코레이터 코드 변환
|
|
132
195
|
코드베이스를 TC39 표준 데코레이터에 맞게 조정하는 codemod를 실행합니다.
|
|
133
196
|
|
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ The canonical CLI for fluo — bootstrap new applications, generate components,
|
|
|
7
7
|
## Table of Contents
|
|
8
8
|
|
|
9
9
|
- [Installation](#installation)
|
|
10
|
+
- [Version Inspection](#version-inspection)
|
|
10
11
|
- [Update Checks](#update-checks)
|
|
11
12
|
- [When to Use](#when-to-use)
|
|
12
13
|
- [Quick Start](#quick-start)
|
|
@@ -33,10 +34,22 @@ pnpm dlx @fluojs/cli new my-app
|
|
|
33
34
|
- The supported install paths are the global package (`npm install -g @fluojs/cli`, `pnpm add -g @fluojs/cli`, `bun add -g @fluojs/cli`, or `yarn global add @fluojs/cli`) and the no-install runner (`pnpm dlx @fluojs/cli ...`).
|
|
34
35
|
- The published `fluo` bin is backed by the dist-built CLI entrypoint declared in `package.json`.
|
|
35
36
|
|
|
37
|
+
## Version Inspection
|
|
38
|
+
|
|
39
|
+
Check the installed CLI version without triggering the interactive update check:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
fluo version
|
|
43
|
+
fluo --version
|
|
44
|
+
fluo -v
|
|
45
|
+
```
|
|
46
|
+
|
|
36
47
|
## Update Checks
|
|
37
48
|
|
|
38
49
|
When `fluo` runs in an interactive TTY, it checks the public npm `latest` dist-tag for `@fluojs/cli` using a local cache so every invocation does not hit the registry. If a newer version is available, the CLI asks whether to install it. Declining continues the current command with the installed version; accepting updates the global CLI with the package manager that appears to own the current installation (`npm install -g`, `pnpm add -g`, `bun add -g`, or `yarn global add`) and then restarts `fluo` with the same arguments under the updated binary. If the installer cannot be inferred, the CLI falls back to `npm install -g @fluojs/cli@<latest>` because npm owns the default Node.js global installation path.
|
|
39
50
|
|
|
51
|
+
`fluo new` and its `fluo create` alias attempt a fresh interactive latest-version check before scaffolding, even when the normal update-check cache is still fresh. This keeps first-run project creation aligned with newly published starter behavior, while day-to-day commands such as `fluo dev`, `fluo build`, `fluo generate`, and `fluo inspect` continue to reuse the cached latest-version result until the normal TTL expires.
|
|
52
|
+
|
|
40
53
|
The update check is skipped in CI, non-TTY output, npm-script contexts, rerun-after-update contexts, registry/network failures, and explicit opt-out paths. Use `--no-update-check` (or the compatibility alias `--no-update-notifier`) for one invocation, or set `FLUO_NO_UPDATE_CHECK=1` when automation must never prompt.
|
|
41
54
|
|
|
42
55
|
## When to Use
|
|
@@ -57,6 +70,10 @@ cd my-app
|
|
|
57
70
|
pnpm dev
|
|
58
71
|
```
|
|
59
72
|
|
|
73
|
+
Generated `dev`, `build`, and `start` package scripts delegate to `fluo dev`, `fluo build`, and `fluo start`. The CLI owns the runtime-specific lifecycle command, prepends the project-local `node_modules/.bin` when invoking local toolchain binaries, and defaults `NODE_ENV` to `development` for `dev` and `production` for `build`/`start` when the caller has not set it explicitly. `fluo dev` uses a TTY-aware lifecycle reporter: interactive terminals get concise fluo-branded status while CI, non-TTY output, `--reporter stream`, `--verbose`, and `FLUO_VERBOSE=1` keep raw child-process passthrough available for debugging and automation. Cloudflare Workers `start` opens a remote Wrangler preview instead of deploying; use an explicit deploy command when you intend to publish to Cloudflare.
|
|
74
|
+
|
|
75
|
+
For Node.js projects, `fluo dev` now runs through a fluo-owned restart boundary instead of delegating directly to `node --watch`. The runner watches source and common config inputs, debounces atomic-save bursts, hashes file content before restarting, loads `.env` for each app child process it spawns, and ignores noisy output/cache paths such as `node_modules`, `dist`, `.git`, `.fluo`, coverage, cache folders, and editor swap files. Pressing Ctrl+S without changing file content should not restart the app. On terminal app child exit or crash outside a planned restart, the runner closes watchers, clears the pending restart timer and paths, unregisters its `SIGINT`/`SIGTERM` handlers, and exits with the child terminal code. This remains full-process restart-on-watch, not true module-level HMR; config watch reloads are a separate in-process config concern, and future HMR work must document which modules can be safely hot-swapped. Use `fluo dev --raw-watch` or `FLUO_DEV_RAW_WATCH=1` to restore the runtime-native Node watcher for debugging, and use `FLUO_DEV_WATCH_IGNORE=path,pattern` to add extra ignored paths.
|
|
76
|
+
|
|
60
77
|
`fluo new` supports Node.js + Fastify, Express, and raw Node.js HTTP application starters on the same Node-oriented install/build flow:
|
|
61
78
|
|
|
62
79
|
```bash
|
|
@@ -114,12 +131,15 @@ Add a new resource with a controller and service, automatically wired into the m
|
|
|
114
131
|
|
|
115
132
|
```bash
|
|
116
133
|
fluo generate module users
|
|
134
|
+
fluo generate resource users
|
|
117
135
|
fluo generate controller users
|
|
118
136
|
fluo generate service users
|
|
119
137
|
fluo generate request-dto users CreateUser
|
|
120
138
|
fluo generate service users --dry-run
|
|
121
139
|
```
|
|
122
140
|
|
|
141
|
+
`fluo generate resource <name>` creates a complete feature slice with a module, controller, service, repository, request DTO, response DTO, and tests. It does not wire the resource module into a parent module automatically; import the generated module when you are ready to activate the slice.
|
|
142
|
+
|
|
123
143
|
Request DTO generation accepts the feature directory separately from the DTO class name, so multiple input contracts such as `CreateUser` and `UpdateUser` can live inside the same `src/users/` slice.
|
|
124
144
|
|
|
125
145
|
Add `--dry-run` to preview the same target resolution, skipped or overwritten file decisions, module auto-registration plan, files-only wiring status, and next-step hint without creating directories, writing files, or updating modules. `--force` still changes existing-file plan entries from `SKIP` to `OVERWRITE` when content would change, and `--target-directory` scopes the preview to that source directory exactly as it does for a real run.
|
|
@@ -128,6 +148,49 @@ Generator discovery is intentionally limited to the built-in `@fluojs/cli/builti
|
|
|
128
148
|
|
|
129
149
|
## Common Patterns
|
|
130
150
|
|
|
151
|
+
### Diagnostics and project scripts
|
|
152
|
+
Use `doctor`/`info` when you need to debug the installed CLI, npm dist-tags, update-check cache state, runtime, and project scripts:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
fluo doctor
|
|
156
|
+
fluo info
|
|
157
|
+
fluo analyze
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`fluo analyze` stays read-only and points to deeper `inspect --report` and `migrate --json` workflows. For generated projects, `fluo dev`, `fluo build`, and `fluo start` run the generated lifecycle directly with environment defaults and project-local toolchain binaries. Use `--dry-run` to preview lifecycle commands:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
fluo dev --dry-run
|
|
164
|
+
fluo build --dry-run
|
|
165
|
+
fluo start --dry-run
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`fluo dev --dry-run` also reports the watch boundary. Node.js projects show `Watch mode: fluo-node-restart` by default, while `--raw-watch` and `FLUO_DEV_RAW_WATCH=1` show `Watch mode: native-watch`. Bun, Deno, and Cloudflare Workers still use their runtime-native dev watchers.
|
|
169
|
+
|
|
170
|
+
Use reporter flags when you need to tune the CLI process boundary rather than runtime app logging:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Pretty status in TTY, raw passthrough in CI/non-TTY (default)
|
|
174
|
+
fluo dev
|
|
175
|
+
|
|
176
|
+
# Current passthrough-like output for debugging child process logs
|
|
177
|
+
fluo dev --reporter stream
|
|
178
|
+
fluo dev --verbose
|
|
179
|
+
FLUO_VERBOSE=1 fluo dev
|
|
180
|
+
|
|
181
|
+
# Suppress wrapper/tool status while keeping child stderr and failures visible
|
|
182
|
+
fluo build --reporter silent
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Runtime application logs are configured separately through `ApplicationLogger`, for example `createConsoleApplicationLogger({ mode: 'minimal', level: 'warn' })` or `createJsonApplicationLogger()` from `@fluojs/runtime/node`.
|
|
186
|
+
|
|
187
|
+
Use `fluo add <package>` for first-party package installation shortcuts and `fluo upgrade` for CLI/latest-version and migration guidance:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
fluo add studio --dev --dry-run
|
|
191
|
+
fluo upgrade
|
|
192
|
+
```
|
|
193
|
+
|
|
131
194
|
### Decorator Codemods
|
|
132
195
|
Run codemods to align your codebase with TC39 standard decorators.
|
|
133
196
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -15,6 +15,14 @@ export interface CliRuntimeOptions {
|
|
|
15
15
|
ci?: boolean;
|
|
16
16
|
cwd?: string;
|
|
17
17
|
env?: NodeJS.ProcessEnv;
|
|
18
|
+
fetchDistTags?: (packageName: string) => Promise<Record<string, string> | undefined>;
|
|
19
|
+
spawnCommand?: (command: string, args: string[], options: {
|
|
20
|
+
cwd: string;
|
|
21
|
+
env: NodeJS.ProcessEnv;
|
|
22
|
+
stderr?: CliStream;
|
|
23
|
+
stdio: 'inherit' | 'pipe';
|
|
24
|
+
stdout?: CliStream;
|
|
25
|
+
}) => Promise<number>;
|
|
18
26
|
stderr?: CliStream;
|
|
19
27
|
stdin?: CliReadableStream;
|
|
20
28
|
stdout?: CliStream;
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,4BAA4B,EAAmC,MAAM,uBAAuB,CAAC;AAE3G,OAAO,EAAE,KAAK,wBAAwB,EAA2B,MAAM,mBAAmB,CAAC;AAO3F,OAAO,EAAE,KAAK,4BAA4B,EAA6C,MAAM,mBAAmB,CAAC;AAEjH,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC;IACrF,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACzL,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,WAAW,CAAC,EAAE,KAAK,GAAG,4BAA4B,CAAC;CACpD;AA+VD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE,iBAAiB,GAAG,wBAAwB,GAAG,4BAAiC,GACxF,OAAO,CAAC,MAAM,CAAC,CAsNjB"}
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { existsSync, readdirSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
2
|
import { join, resolve } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { diagnosticsUsage, runAnalyzeCommand, runDoctorCommand, runInfoCommand } from './commands/diagnostics.js';
|
|
4
5
|
import { runGenerateCommand } from './commands/generate.js';
|
|
5
6
|
import { inspectUsage, runInspectCommand } from './commands/inspect.js';
|
|
6
7
|
import { migrateUsage, runMigrateCommand } from './commands/migrate.js';
|
|
7
8
|
import { newUsage, runNewCommand } from './commands/new.js';
|
|
9
|
+
import { addUsage, runAddCommand, runUpgradeCommand, upgradeUsage } from './commands/package-workflow.js';
|
|
10
|
+
import { runScriptCommand, scriptUsage } from './commands/scripts.js';
|
|
11
|
+
import { runNodeRestartRunner } from './dev-runner/node-restart-runner.js';
|
|
8
12
|
import { builtInGeneratorCollection, generatorManifest, generatorOptionSchemas, resolveGeneratorKind } from './generators/manifest.js';
|
|
9
13
|
import { renderAliasList, renderHelpTable } from './help.js';
|
|
10
14
|
import { removeUpdateCheckFlags, runCliUpdateCheck } from './update-check.js';
|
|
@@ -33,6 +37,34 @@ const TOP_LEVEL_COMMAND_HELP = [{
|
|
|
33
37
|
aliases: ['g'],
|
|
34
38
|
command: 'generate',
|
|
35
39
|
description: 'Generate a schematic inside an existing fluo application.'
|
|
40
|
+
}, {
|
|
41
|
+
aliases: ['info'],
|
|
42
|
+
command: 'doctor',
|
|
43
|
+
description: 'Print CLI, registry, update-cache, runtime, and project diagnostics.'
|
|
44
|
+
}, {
|
|
45
|
+
aliases: [],
|
|
46
|
+
command: 'analyze',
|
|
47
|
+
description: 'Summarize project diagnostics and point to deeper inspection flows.'
|
|
48
|
+
}, {
|
|
49
|
+
aliases: [],
|
|
50
|
+
command: 'dev',
|
|
51
|
+
description: 'Run the generated project development lifecycle.'
|
|
52
|
+
}, {
|
|
53
|
+
aliases: [],
|
|
54
|
+
command: 'start',
|
|
55
|
+
description: 'Run the generated project production lifecycle.'
|
|
56
|
+
}, {
|
|
57
|
+
aliases: [],
|
|
58
|
+
command: 'build',
|
|
59
|
+
description: 'Run the generated project build lifecycle.'
|
|
60
|
+
}, {
|
|
61
|
+
aliases: [],
|
|
62
|
+
command: 'add',
|
|
63
|
+
description: 'Install @fluojs packages with the detected package manager.'
|
|
64
|
+
}, {
|
|
65
|
+
aliases: [],
|
|
66
|
+
command: 'upgrade',
|
|
67
|
+
description: 'Report latest CLI state and migration workflow guidance.'
|
|
36
68
|
}, {
|
|
37
69
|
aliases: [],
|
|
38
70
|
command: 'inspect',
|
|
@@ -41,17 +73,36 @@ const TOP_LEVEL_COMMAND_HELP = [{
|
|
|
41
73
|
aliases: [],
|
|
42
74
|
command: 'migrate',
|
|
43
75
|
description: 'Run NestJS-to-fluo codemods (dry-run by default).'
|
|
76
|
+
}, {
|
|
77
|
+
aliases: ['--version', '-v'],
|
|
78
|
+
command: 'version',
|
|
79
|
+
description: 'Print the installed fluo CLI version.'
|
|
44
80
|
}, {
|
|
45
81
|
aliases: [],
|
|
46
82
|
command: 'help',
|
|
47
83
|
description: 'Show top-level or command-specific help.'
|
|
48
84
|
}];
|
|
85
|
+
const NODE_DEV_RUNNER_COMMAND = '__node-dev-runner';
|
|
49
86
|
function normalizeGeneratorKind(value) {
|
|
50
87
|
return resolveGeneratorKind(value);
|
|
51
88
|
}
|
|
52
89
|
function isHelpFlag(value) {
|
|
53
90
|
return value === '--help' || value === '-h';
|
|
54
91
|
}
|
|
92
|
+
function isVersionCommand(value) {
|
|
93
|
+
return value === 'version' || value === '--version' || value === '-v';
|
|
94
|
+
}
|
|
95
|
+
function isCreationCommand(value) {
|
|
96
|
+
return value === 'new' || value === 'create';
|
|
97
|
+
}
|
|
98
|
+
function readCliVersion() {
|
|
99
|
+
const packageJsonPath = fileURLToPath(new URL('../package.json', import.meta.url));
|
|
100
|
+
const manifest = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
101
|
+
if (typeof manifest !== 'object' || manifest === null || !('version' in manifest) || typeof manifest.version !== 'string') {
|
|
102
|
+
throw new Error('Unable to determine the installed fluo CLI version.');
|
|
103
|
+
}
|
|
104
|
+
return manifest.version;
|
|
105
|
+
}
|
|
55
106
|
function generateUsage() {
|
|
56
107
|
return ['Usage: fluo generate|g <kind> <name> [options]', ' fluo generate|g request-dto|req <feature> <name> [options]', '', 'Schematics', renderHelpTable(GENERATE_KIND_HELP, [{
|
|
57
108
|
header: 'Schematic',
|
|
@@ -173,6 +224,42 @@ function parseGenerateArgs(argv) {
|
|
|
173
224
|
}
|
|
174
225
|
function parseCommand(argv) {
|
|
175
226
|
const [command] = argv;
|
|
227
|
+
if (command === 'analyze') {
|
|
228
|
+
return {
|
|
229
|
+
argv: argv.slice(1),
|
|
230
|
+
command: 'analyze'
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
if (command === 'add') {
|
|
234
|
+
return {
|
|
235
|
+
argv: argv.slice(1),
|
|
236
|
+
command: 'add'
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (command === 'doctor') {
|
|
240
|
+
return {
|
|
241
|
+
argv: argv.slice(1),
|
|
242
|
+
command: 'doctor'
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
if (command === 'info') {
|
|
246
|
+
return {
|
|
247
|
+
argv: argv.slice(1),
|
|
248
|
+
command: 'info'
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
if (command === 'build' || command === 'dev' || command === 'start') {
|
|
252
|
+
return {
|
|
253
|
+
argv: argv.slice(1),
|
|
254
|
+
command
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
if (command === 'upgrade') {
|
|
258
|
+
return {
|
|
259
|
+
argv: argv.slice(1),
|
|
260
|
+
command: 'upgrade'
|
|
261
|
+
};
|
|
262
|
+
}
|
|
176
263
|
if (command === 'new' || command === 'create') {
|
|
177
264
|
return {
|
|
178
265
|
argv: argv.slice(1),
|
|
@@ -225,14 +312,33 @@ export async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
225
312
|
const stdout = runtime.stdout ?? process.stdout;
|
|
226
313
|
const stderr = runtime.stderr ?? process.stderr;
|
|
227
314
|
const env = runtime.env ?? process.env;
|
|
315
|
+
const commandRuntime = {
|
|
316
|
+
...runtime,
|
|
317
|
+
env
|
|
318
|
+
};
|
|
228
319
|
const updateFlagResult = removeUpdateCheckFlags(argv);
|
|
229
320
|
const commandArgv = updateFlagResult.argv;
|
|
230
321
|
try {
|
|
322
|
+
if (commandArgv[0] === NODE_DEV_RUNNER_COMMAND) {
|
|
323
|
+
const separatorIndex = commandArgv.indexOf('--');
|
|
324
|
+
const appArgs = separatorIndex >= 0 ? commandArgv.slice(separatorIndex + 1) : commandArgv.slice(1);
|
|
325
|
+
return runNodeRestartRunner({
|
|
326
|
+
appArgs,
|
|
327
|
+
env,
|
|
328
|
+
stderr,
|
|
329
|
+
stdout
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
if (isVersionCommand(commandArgv[0])) {
|
|
333
|
+
stdout.write(`${readCliVersion()}\n`);
|
|
334
|
+
return 0;
|
|
335
|
+
}
|
|
231
336
|
const updateCheckOptions = runtime.updateCheck === false ? undefined : runtime.updateCheck;
|
|
232
337
|
const updateCheckResult = await runCliUpdateCheck(commandArgv, {
|
|
233
338
|
...updateCheckOptions,
|
|
234
339
|
ci: runtime.ci,
|
|
235
340
|
env,
|
|
341
|
+
bypassCache: isCreationCommand(commandArgv[0]),
|
|
236
342
|
interactive: runtime.interactive,
|
|
237
343
|
skip: updateFlagResult.skipUpdateCheck || runtime.updateCheck === false,
|
|
238
344
|
stderr,
|
|
@@ -255,6 +361,26 @@ export async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
255
361
|
stdout.write(`${generateUsage()}\n`);
|
|
256
362
|
return 0;
|
|
257
363
|
}
|
|
364
|
+
if (topic === 'doctor' || topic === 'info') {
|
|
365
|
+
stdout.write(`${diagnosticsUsage('doctor')}\n`);
|
|
366
|
+
return 0;
|
|
367
|
+
}
|
|
368
|
+
if (topic === 'analyze') {
|
|
369
|
+
stdout.write(`${diagnosticsUsage('analyze')}\n`);
|
|
370
|
+
return 0;
|
|
371
|
+
}
|
|
372
|
+
if (topic === 'build' || topic === 'dev' || topic === 'start') {
|
|
373
|
+
stdout.write(`${scriptUsage(topic)}\n`);
|
|
374
|
+
return 0;
|
|
375
|
+
}
|
|
376
|
+
if (topic === 'add') {
|
|
377
|
+
stdout.write(`${addUsage()}\n`);
|
|
378
|
+
return 0;
|
|
379
|
+
}
|
|
380
|
+
if (topic === 'upgrade') {
|
|
381
|
+
stdout.write(`${upgradeUsage()}\n`);
|
|
382
|
+
return 0;
|
|
383
|
+
}
|
|
258
384
|
if (topic === 'migrate') {
|
|
259
385
|
stdout.write(`${migrateUsage()}\n`);
|
|
260
386
|
return 0;
|
|
@@ -274,6 +400,26 @@ export async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
274
400
|
stdout.write(`${generateUsage()}\n`);
|
|
275
401
|
return 0;
|
|
276
402
|
}
|
|
403
|
+
if ((commandArgv[0] === 'doctor' || commandArgv[0] === 'info') && commandArgv.slice(1).some(isHelpFlag)) {
|
|
404
|
+
stdout.write(`${diagnosticsUsage('doctor')}\n`);
|
|
405
|
+
return 0;
|
|
406
|
+
}
|
|
407
|
+
if (commandArgv[0] === 'analyze' && commandArgv.slice(1).some(isHelpFlag)) {
|
|
408
|
+
stdout.write(`${diagnosticsUsage('analyze')}\n`);
|
|
409
|
+
return 0;
|
|
410
|
+
}
|
|
411
|
+
if ((commandArgv[0] === 'build' || commandArgv[0] === 'dev' || commandArgv[0] === 'start') && commandArgv.slice(1).some(isHelpFlag)) {
|
|
412
|
+
stdout.write(`${scriptUsage(commandArgv[0])}\n`);
|
|
413
|
+
return 0;
|
|
414
|
+
}
|
|
415
|
+
if (commandArgv[0] === 'add' && commandArgv.slice(1).some(isHelpFlag)) {
|
|
416
|
+
stdout.write(`${addUsage()}\n`);
|
|
417
|
+
return 0;
|
|
418
|
+
}
|
|
419
|
+
if (commandArgv[0] === 'upgrade' && commandArgv.slice(1).some(isHelpFlag)) {
|
|
420
|
+
stdout.write(`${upgradeUsage()}\n`);
|
|
421
|
+
return 0;
|
|
422
|
+
}
|
|
277
423
|
if (commandArgv[0] === 'migrate' && commandArgv.slice(1).some(isHelpFlag)) {
|
|
278
424
|
stdout.write(`${migrateUsage()}\n`);
|
|
279
425
|
return 0;
|
|
@@ -283,14 +429,35 @@ export async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
283
429
|
return 0;
|
|
284
430
|
}
|
|
285
431
|
const parsedCommand = parseCommand(commandArgv);
|
|
432
|
+
if (parsedCommand.command === 'analyze') {
|
|
433
|
+
return runAnalyzeCommand(parsedCommand.argv, commandRuntime);
|
|
434
|
+
}
|
|
435
|
+
if (parsedCommand.command === 'add') {
|
|
436
|
+
return runAddCommand(parsedCommand.argv, commandRuntime);
|
|
437
|
+
}
|
|
438
|
+
if (parsedCommand.command === 'doctor') {
|
|
439
|
+
return runDoctorCommand(parsedCommand.argv, commandRuntime);
|
|
440
|
+
}
|
|
441
|
+
if (parsedCommand.command === 'info') {
|
|
442
|
+
return runInfoCommand(parsedCommand.argv, commandRuntime);
|
|
443
|
+
}
|
|
444
|
+
if (parsedCommand.command === 'build' || parsedCommand.command === 'dev' || parsedCommand.command === 'start') {
|
|
445
|
+
return runScriptCommand(parsedCommand.command, parsedCommand.argv, commandRuntime);
|
|
446
|
+
}
|
|
447
|
+
if (parsedCommand.command === 'upgrade') {
|
|
448
|
+
return runUpgradeCommand(parsedCommand.argv, commandRuntime);
|
|
449
|
+
}
|
|
286
450
|
if (parsedCommand.command === 'new') {
|
|
287
|
-
return runNewCommand(parsedCommand.argv,
|
|
451
|
+
return runNewCommand(parsedCommand.argv, commandRuntime);
|
|
288
452
|
}
|
|
289
453
|
if (parsedCommand.command === 'migrate') {
|
|
290
|
-
return runMigrateCommand(parsedCommand.argv,
|
|
454
|
+
return runMigrateCommand(parsedCommand.argv, commandRuntime);
|
|
291
455
|
}
|
|
292
456
|
if (parsedCommand.command === 'inspect') {
|
|
293
|
-
return runInspectCommand(parsedCommand.argv,
|
|
457
|
+
return runInspectCommand(parsedCommand.argv, commandRuntime);
|
|
458
|
+
}
|
|
459
|
+
if (parsedCommand.command !== 'generate') {
|
|
460
|
+
throw new Error(usage());
|
|
294
461
|
}
|
|
295
462
|
const targetDirectory = resolve(cwd, parsedCommand.parsed.targetDirectory ?? resolveDefaultTargetDirectory(cwd));
|
|
296
463
|
const result = runGenerateCommand(parsedCommand.parsed.kind, parsedCommand.parsed.name, targetDirectory, parsedCommand.parsed.options);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type CliStream = {
|
|
2
|
+
write(message: string): unknown;
|
|
3
|
+
};
|
|
4
|
+
type DiagnosticRuntimeOptions = {
|
|
5
|
+
cwd?: string;
|
|
6
|
+
env?: NodeJS.ProcessEnv;
|
|
7
|
+
fetchDistTags?: (packageName: string) => Promise<Record<string, string> | undefined>;
|
|
8
|
+
stdout?: CliStream;
|
|
9
|
+
};
|
|
10
|
+
export declare function diagnosticsUsage(command?: 'analyze' | 'doctor' | 'info'): string;
|
|
11
|
+
export declare function runDoctorCommand(argv: string[], runtime?: DiagnosticRuntimeOptions): Promise<number>;
|
|
12
|
+
export declare function runInfoCommand(argv: string[], runtime?: DiagnosticRuntimeOptions): Promise<number>;
|
|
13
|
+
export declare function runAnalyzeCommand(argv: string[], runtime?: DiagnosticRuntimeOptions): Promise<number>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/commands/diagnostics.ts"],"names":[],"mappings":"AAKA,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC;IACrF,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,CAAC;AAuHF,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,SAAS,GAAG,QAAQ,GAAG,MAAiB,GAAG,MAAM,CAoB1F;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,MAAM,CAAC,CAgC9G;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,MAAM,CAAC,CAO5G;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,MAAM,CAAC,CAsB/G"}
|