@fluojs/cli 1.0.0-beta.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/LICENSE +21 -0
- package/README.ko.md +155 -0
- package/README.md +155 -0
- package/bin/fluo.mjs +5 -0
- package/dist/cli.d.ts +37 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +292 -0
- package/dist/commands/generate.d.ts +40 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +134 -0
- package/dist/commands/inspect.d.ts +30 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +221 -0
- package/dist/commands/migrate.d.ts +30 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +173 -0
- package/dist/commands/new.d.ts +45 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +353 -0
- package/dist/generator-types.d.ts +21 -0
- package/dist/generator-types.d.ts.map +1 -0
- package/dist/generator-types.js +1 -0
- package/dist/generators/controller.d.ts +3 -0
- package/dist/generators/controller.d.ts.map +1 -0
- package/dist/generators/controller.js +22 -0
- package/dist/generators/guard.d.ts +3 -0
- package/dist/generators/guard.d.ts.map +1 -0
- package/dist/generators/guard.js +15 -0
- package/dist/generators/interceptor.d.ts +3 -0
- package/dist/generators/interceptor.d.ts.map +1 -0
- package/dist/generators/interceptor.js +15 -0
- package/dist/generators/manifest.d.ts +121 -0
- package/dist/generators/manifest.d.ts.map +1 -0
- package/dist/generators/manifest.js +130 -0
- package/dist/generators/middleware.d.ts +3 -0
- package/dist/generators/middleware.d.ts.map +1 -0
- package/dist/generators/middleware.js +15 -0
- package/dist/generators/module.d.ts +6 -0
- package/dist/generators/module.d.ts.map +1 -0
- package/dist/generators/module.js +143 -0
- package/dist/generators/render.d.ts +2 -0
- package/dist/generators/render.d.ts.map +1 -0
- package/dist/generators/render.js +17 -0
- package/dist/generators/repository.d.ts +3 -0
- package/dist/generators/repository.d.ts.map +1 -0
- package/dist/generators/repository.js +29 -0
- package/dist/generators/request-dto.d.ts +3 -0
- package/dist/generators/request-dto.d.ts.map +1 -0
- package/dist/generators/request-dto.js +17 -0
- package/dist/generators/response-dto.d.ts +3 -0
- package/dist/generators/response-dto.d.ts.map +1 -0
- package/dist/generators/response-dto.js +17 -0
- package/dist/generators/service.d.ts +3 -0
- package/dist/generators/service.d.ts.map +1 -0
- package/dist/generators/service.js +22 -0
- package/dist/generators/templates/controller.test.ts.ejs +21 -0
- package/dist/generators/templates/controller.ts.ejs +29 -0
- package/dist/generators/templates/guard.ts.ejs +7 -0
- package/dist/generators/templates/interceptor.ts.ejs +7 -0
- package/dist/generators/templates/middleware.ts.ejs +11 -0
- package/dist/generators/templates/module.ts.ejs +9 -0
- package/dist/generators/templates/repository.slice.test.ts.ejs +15 -0
- package/dist/generators/templates/repository.test.ts.ejs +9 -0
- package/dist/generators/templates/repository.ts.ejs +10 -0
- package/dist/generators/templates/request-dto.ts.ejs +9 -0
- package/dist/generators/templates/response-dto.ts.ejs +3 -0
- package/dist/generators/templates/service.test.ts.ejs +21 -0
- package/dist/generators/templates/service.ts.ejs +24 -0
- package/dist/generators/utils.d.ts +4 -0
- package/dist/generators/utils.d.ts.map +1 -0
- package/dist/generators/utils.js +18 -0
- package/dist/help.d.ts +8 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +16 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/new/install.d.ts +51 -0
- package/dist/new/install.d.ts.map +1 -0
- package/dist/new/install.js +140 -0
- package/dist/new/package-spec-resolver.d.ts +4 -0
- package/dist/new/package-spec-resolver.d.ts.map +1 -0
- package/dist/new/package-spec-resolver.js +397 -0
- package/dist/new/prompt.d.ts +56 -0
- package/dist/new/prompt.d.ts.map +1 -0
- package/dist/new/prompt.js +278 -0
- package/dist/new/resolver.d.ts +32 -0
- package/dist/new/resolver.d.ts.map +1 -0
- package/dist/new/resolver.js +93 -0
- package/dist/new/scaffold.d.ts +14 -0
- package/dist/new/scaffold.d.ts.map +1 -0
- package/dist/new/scaffold.js +2010 -0
- package/dist/new/starter-profiles.d.ts +91 -0
- package/dist/new/starter-profiles.d.ts.map +1 -0
- package/dist/new/starter-profiles.js +347 -0
- package/dist/new/types.d.ts +63 -0
- package/dist/new/types.d.ts.map +1 -0
- package/dist/new/types.js +1 -0
- package/dist/registry.d.ts +10 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +30 -0
- package/dist/transforms/nestjs-migrate.d.ts +33 -0
- package/dist/transforms/nestjs-migrate.d.ts.map +1 -0
- package/dist/transforms/nestjs-migrate.js +891 -0
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 fluo contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# @fluojs/cli
|
|
2
|
+
|
|
3
|
+
<p><a href="./README.md"><kbd>English</kbd></a> <strong><kbd>한국어</kbd></strong></p>
|
|
4
|
+
|
|
5
|
+
fluo 공식 CLI — 새 애플리케이션 부트스트랩, 컴포넌트 생성, 런타임 그래프 검사, 코드 변환을 지원합니다.
|
|
6
|
+
|
|
7
|
+
## 목차
|
|
8
|
+
|
|
9
|
+
- [설치](#설치)
|
|
10
|
+
- [사용 시점](#사용-시점)
|
|
11
|
+
- [빠른 시작](#빠른-시작)
|
|
12
|
+
- [주요 패턴](#주요-패턴)
|
|
13
|
+
- [공개 API](#공개-api)
|
|
14
|
+
- [관련 패키지](#관련-패키지)
|
|
15
|
+
- [예제 소스](#예제-소스)
|
|
16
|
+
|
|
17
|
+
## 설치
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add -g @fluojs/cli
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
설치 없이 직접 실행하려면:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm dlx @fluojs/cli new my-app
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 릴리스 계약
|
|
30
|
+
|
|
31
|
+
- `@fluojs/cli`는 intended publish surface에 포함되는 공개 패키지입니다.
|
|
32
|
+
- 지원되는 설치 경로는 전역 패키지(`pnpm add -g @fluojs/cli`)와 무설치 실행 경로(`pnpm dlx @fluojs/cli ...`)입니다.
|
|
33
|
+
- 배포되는 `fluo` bin은 `package.json`에 선언된 dist 빌드 CLI 엔트리포인트를 기준으로 동작합니다.
|
|
34
|
+
|
|
35
|
+
## 사용 시점
|
|
36
|
+
|
|
37
|
+
- **부트스트랩**: 표준적이고 검증 가능한 구조로 새 프로젝트를 시작할 때.
|
|
38
|
+
- **코드 생성**: 일관된 네이밍 규칙과 자동 연결 기능을 갖춘 모듈, 컨트롤러, 서비스, 레포지토리를 생성할 때.
|
|
39
|
+
- **코드 변환**: 기존 코드베이스를 fluo의 표준 데코레이터 모델에 맞출 때.
|
|
40
|
+
- **검사(Inspection)**: 런타임 의존성 그래프를 시각화하고 플랫폼 수준의 문제를 진단할 때.
|
|
41
|
+
|
|
42
|
+
## 빠른 시작
|
|
43
|
+
|
|
44
|
+
### 1. 새 프로젝트 생성
|
|
45
|
+
몇 초 만에 완전한 스타터 애플리케이션을 스캐폴딩합니다.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
fluo new my-app
|
|
49
|
+
cd my-app
|
|
50
|
+
pnpm dev
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`fluo new`는 같은 Node 기반 설치/빌드 흐름 위에서 Node.js + Fastify, Express, raw Node.js HTTP 애플리케이션 스타터를 제공합니다.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
fluo new my-app --shape application --transport http --runtime node --platform fastify
|
|
57
|
+
fluo new my-express-app --shape application --transport http --runtime node --platform express
|
|
58
|
+
fluo new my-node-app --shape application --transport http --runtime node --platform nodejs
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
애플리케이션 매트릭스에는 런타임별 entrypoint, scripts, dependency 세트를 갖춘 Bun, Deno, Cloudflare Workers 네이티브 스타터도 포함됩니다.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
fluo new my-bun-app --shape application --transport http --runtime bun --platform bun
|
|
65
|
+
fluo new my-deno-app --shape application --transport http --runtime deno --platform deno
|
|
66
|
+
fluo new my-worker-app --shape application --transport http --runtime cloudflare-workers --platform cloudflare-workers
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`fluo new`는 microservice starter path도 제공합니다. `--transport`를 생략하면 TCP가 기본 경로로 사용되며, starter 매트릭스에는 transport별 dependency, env 템플릿, entrypoint를 갖춘 Redis Streams, NATS, Kafka, RabbitMQ, MQTT, gRPC 변형도 포함됩니다.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
fluo new my-microservice --shape microservice --transport tcp --runtime node --platform none
|
|
73
|
+
fluo new my-redis-streams-service --shape microservice --transport redis-streams --runtime node --platform none
|
|
74
|
+
fluo new my-nats-service --shape microservice --transport nats --runtime node --platform none
|
|
75
|
+
fluo new my-kafka-service --shape microservice --transport kafka --runtime node --platform none
|
|
76
|
+
fluo new my-rabbitmq-service --shape microservice --transport rabbitmq --runtime node --platform none
|
|
77
|
+
fluo new my-mqtt-service --shape microservice --transport mqtt --runtime node --platform none
|
|
78
|
+
fluo new my-grpc-service --shape microservice --transport grpc --runtime node --platform none
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
지원되는 `--shape microservice --transport` 스타터 값은 정확히 `tcp`, `redis-streams`, `nats`, `kafka`, `rabbitmq`, `mqtt`, `grpc`입니다. 이전 문서에 있던 `redis` 값은 더 이상 제공되는 스타터 계약에 포함되지 않으며, 유지보수되는 Redis 기반 스타터가 필요하면 `redis-streams`를 사용하고, 더 넓은 Redis 통합 패턴이 필요하면 스캐폴딩 후 `@fluojs/redis`를 수동으로 추가하세요.
|
|
82
|
+
|
|
83
|
+
NATS/Kafka/RabbitMQ 스타터 계약은 외부 broker와 caller-owned client library 의존성을 숨기지 않고 명시적으로 유지합니다. 생성된 프로젝트는 `src/app.ts`에서 `nats` + `JSONCodec()`, `kafkajs` producer/consumer collaborator, `amqplib` publisher/consumer collaborator를 직접 연결하므로, 기본 fluo 패키지가 그 의존성을 감춘 것처럼 가장하지 않는 runnable starter 계약이 됩니다.
|
|
84
|
+
|
|
85
|
+
starter 매트릭스에는 mixed single-package starter도 포함됩니다. 하나의 Fastify HTTP 앱과 attached TCP microservice를 같은 생성 프로젝트 안에 함께 배치합니다.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
fluo new my-mixed-app --shape mixed --transport tcp --runtime node --platform fastify
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`fluo new`가 interactive TTY에서 실행되면 wizard는 기존 flags/config 모델을 그대로 사용합니다. wizard는 프로젝트 이름, shape-first 분기(`application` -> runtime + HTTP platform, `microservice` -> transport), 유지보수 가능한 tooling preset, package manager, 즉시 dependency를 설치할지 여부, git 저장소를 초기화할지 여부를 묻습니다. non-interactive 플래그 경로와 프로그래밍 방식의 `runNewCommand(...)` 호출도 동일한 resolved defaults를 사용합니다.
|
|
92
|
+
|
|
93
|
+
현재 제공되는 스타터 매트릭스(Node.js Fastify/Express/raw Node.js HTTP, Bun, Deno, Cloudflare Workers, TCP/Redis Streams/NATS/Kafka/RabbitMQ/MQTT/gRPC microservice, 그리고 mixed)와 남아 있는 더 넓은 어댑터 생태계를 문서 수준에서 구분한 표는 [fluo new 지원 매트릭스](../../docs/reference/fluo-new-support-matrix.ko.md)를 확인하세요. `@fluojs/redis` 같은 패키지 수준 통합은 더 넓은 생태계에 남아 있지만, 추가 `fluo new --transport` 스타터 플래그는 아닙니다.
|
|
94
|
+
|
|
95
|
+
### 2. 기능 추가
|
|
96
|
+
컨트롤러와 서비스가 포함된 새 리소스를 추가하고, 모듈에 자동으로 연결합니다.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
fluo generate module users
|
|
100
|
+
fluo generate controller users
|
|
101
|
+
fluo generate service users
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 주요 패턴
|
|
105
|
+
|
|
106
|
+
### 데코레이터 코드 변환
|
|
107
|
+
코드베이스를 TC39 표준 데코레이터에 맞게 조정하는 codemod를 실행합니다.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# 변경 사항 미리보기 (dry-run)
|
|
111
|
+
fluo migrate ./src
|
|
112
|
+
|
|
113
|
+
# 변환 적용
|
|
114
|
+
fluo migrate ./src --apply
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**주요 변환 사항:**
|
|
118
|
+
- `@nestjs/common` 임포트를 `@fluojs/core` 또는 `@fluojs/http`로 재작성합니다.
|
|
119
|
+
- `@Injectable()`을 제거하고 스코프를 `@Scope()`로 매핑합니다.
|
|
120
|
+
- `tsconfig.json`을 업데이트하여 `experimentalDecorators`를 비활성화하고 `baseUrl` 기반 경로 별칭을 TS6-safe `paths` 엔트리로 재작성합니다.
|
|
121
|
+
|
|
122
|
+
### 런타임 검사 (Inspection)
|
|
123
|
+
애플리케이션 구조를 시각화하고 초기화 문제를 해결합니다.
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# 의존성 그래프를 Mermaid 형식으로 내보내기
|
|
127
|
+
fluo inspect ./src/app.module.ts --mermaid
|
|
128
|
+
|
|
129
|
+
# @fluojs/studio용 snapshot 내보내기
|
|
130
|
+
fluo inspect ./src/app.module.ts --json > snapshot.json
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## 공개 API
|
|
134
|
+
|
|
135
|
+
다른 도구 내에서 CLI 동작을 트리거하기 위해 패키지를 프로그래밍 방식으로 사용할 수 있습니다.
|
|
136
|
+
|
|
137
|
+
| 익스포트 | 설명 |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `runCli(argv?, options?)` | 모든 CLI 명령을 실행하는 메인 진입점입니다. |
|
|
140
|
+
| `runNewCommand(argv, options?)` | 프로젝트 스캐폴딩 로직에 대한 프로그래밍적 접근을 제공합니다. |
|
|
141
|
+
| `GeneratorKind` | 지원되는 모든 생성기 유형(예: `'controller'`, `'service'`)의 유니온 타입입니다. |
|
|
142
|
+
|
|
143
|
+
## 관련 패키지
|
|
144
|
+
|
|
145
|
+
- **[@fluojs/runtime](../runtime/README.ko.md)**: 검사 및 부트스트랩에 사용되는 기본 엔진입니다.
|
|
146
|
+
- **[@fluojs/studio](../studio/README.ko.md)**: `inspect --json` 출력을 시각화하기 위한 웹 기반 UI입니다.
|
|
147
|
+
- **[@fluojs/testing](../testing/README.ko.md)**: 통합 및 E2E 테스트를 위해 생성된 테스트 템플릿에서 사용됩니다.
|
|
148
|
+
- **[Canonical Runtime Package Matrix](../../docs/reference/package-surface.ko.md)**: 공식 런타임/패키지 조합을 보여주는 기준 문서입니다.
|
|
149
|
+
|
|
150
|
+
## 예제 소스
|
|
151
|
+
|
|
152
|
+
- [cli.ts](./src/cli.ts) - 명령 디스패처 및 인자 파싱.
|
|
153
|
+
- [commands/new.ts](./src/commands/new.ts) - 프로젝트 스캐폴딩 구현.
|
|
154
|
+
- [generators/](./src/generators/) - 템플릿 기반 파일 생성 로직.
|
|
155
|
+
- [transforms/](./src/transforms/) - 코드 변환 구현.
|
package/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# @fluojs/cli
|
|
2
|
+
|
|
3
|
+
<p><strong><kbd>English</kbd></strong> <a href="./README.ko.md"><kbd>한국어</kbd></a></p>
|
|
4
|
+
|
|
5
|
+
The canonical CLI for fluo — bootstrap new applications, generate components, inspect runtime graphs, and run code transforms.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [When to Use](#when-to-use)
|
|
11
|
+
- [Quick Start](#quick-start)
|
|
12
|
+
- [Common Patterns](#common-patterns)
|
|
13
|
+
- [Public API](#public-api)
|
|
14
|
+
- [Related Packages](#related-packages)
|
|
15
|
+
- [Example Sources](#example-sources)
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add -g @fluojs/cli
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Or run directly without installation:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm dlx @fluojs/cli new my-app
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Release Contract
|
|
30
|
+
|
|
31
|
+
- `@fluojs/cli` is a public package in the intended publish surface.
|
|
32
|
+
- The supported install paths are the global package (`pnpm add -g @fluojs/cli`) and the no-install runner (`pnpm dlx @fluojs/cli ...`).
|
|
33
|
+
- The published `fluo` bin is backed by the dist-built CLI entrypoint declared in `package.json`.
|
|
34
|
+
|
|
35
|
+
## When to Use
|
|
36
|
+
|
|
37
|
+
- **Bootstrapping**: When starting a new project with a standard, verifiable structure.
|
|
38
|
+
- **Generation**: To create modules, controllers, services, and repositories with consistent naming and automatic wiring.
|
|
39
|
+
- **Code transforms**: When aligning an existing codebase with fluo's standard decorator model.
|
|
40
|
+
- **Inspection**: To visualize the runtime dependency graph and diagnose platform-level issues.
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
### 1. Create a new project
|
|
45
|
+
Scaffold a complete starter application in seconds.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
fluo new my-app
|
|
49
|
+
cd my-app
|
|
50
|
+
pnpm dev
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`fluo new` supports Node.js + Fastify, Express, and raw Node.js HTTP application starters on the same Node-oriented install/build flow:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
fluo new my-app --shape application --transport http --runtime node --platform fastify
|
|
57
|
+
fluo new my-express-app --shape application --transport http --runtime node --platform express
|
|
58
|
+
fluo new my-node-app --shape application --transport http --runtime node --platform nodejs
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The application matrix also includes runtime-native Bun, Deno, and Cloudflare Workers starters with runtime-specific entrypoints, scripts, and dependency sets:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
fluo new my-bun-app --shape application --transport http --runtime bun --platform bun
|
|
65
|
+
fluo new my-deno-app --shape application --transport http --runtime deno --platform deno
|
|
66
|
+
fluo new my-worker-app --shape application --transport http --runtime cloudflare-workers --platform cloudflare-workers
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`fluo new` also exposes microservice starter paths. TCP is the default when you omit `--transport`, and the starter matrix includes runnable Redis Streams, NATS, Kafka, RabbitMQ, MQTT, and gRPC variants with transport-specific dependencies, env templates, and entrypoints:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
fluo new my-microservice --shape microservice --transport tcp --runtime node --platform none
|
|
73
|
+
fluo new my-redis-streams-service --shape microservice --transport redis-streams --runtime node --platform none
|
|
74
|
+
fluo new my-nats-service --shape microservice --transport nats --runtime node --platform none
|
|
75
|
+
fluo new my-kafka-service --shape microservice --transport kafka --runtime node --platform none
|
|
76
|
+
fluo new my-rabbitmq-service --shape microservice --transport rabbitmq --runtime node --platform none
|
|
77
|
+
fluo new my-mqtt-service --shape microservice --transport mqtt --runtime node --platform none
|
|
78
|
+
fluo new my-grpc-service --shape microservice --transport grpc --runtime node --platform none
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Supported `--shape microservice --transport` starter values are exactly `tcp`, `redis-streams`, `nats`, `kafka`, `rabbitmq`, `mqtt`, and `grpc`. Earlier docs mentioned `redis`, but that value is no longer part of the shipped starter contract; use `redis-streams` for the maintained Redis-backed starter, or add `@fluojs/redis` manually after scaffolding when you need broader Redis integration patterns.
|
|
82
|
+
|
|
83
|
+
The NATS/Kafka/RabbitMQ starter contracts stay explicit about external brokers and caller-owned client libraries. Generated projects wire `nats` + `JSONCodec()`, `kafkajs` producer/consumer collaborators, and `amqplib` publisher/consumer collaborators directly in `src/app.ts` so the starter contract is runnable without pretending the base fluo packages hide those dependencies.
|
|
84
|
+
|
|
85
|
+
The starter matrix also includes a mixed single-package starter: one Fastify HTTP app with an attached TCP microservice in the same generated project.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
fluo new my-mixed-app --shape mixed --transport tcp --runtime node --platform fastify
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
When `fluo new` runs in an interactive TTY, the wizard uses the same flags/config model. It asks for the project name, shape-first branch (`application` -> runtime + HTTP platform, `microservice` -> transport), the maintained tooling preset, package-manager choice, whether to install dependencies immediately, and whether to initialize a git repository. Non-interactive flags and programmatic `runNewCommand(...)` calls use the same resolved defaults.
|
|
92
|
+
|
|
93
|
+
For a docs-level table that separates the shipped starter matrix (Node.js Fastify/Express/raw Node.js HTTP, Bun, Deno, Cloudflare Workers, TCP/Redis Streams/NATS/Kafka/RabbitMQ/MQTT/gRPC microservices, plus mixed) from the remaining broader adapter ecosystem, see the [fluo new support matrix](../../docs/reference/fluo-new-support-matrix.md). Package-level integrations such as `@fluojs/redis` remain part of the broader ecosystem, but they are not extra `fluo new --transport` starter flags.
|
|
94
|
+
|
|
95
|
+
### 2. Generate a feature
|
|
96
|
+
Add a new resource with a controller and service, automatically wired into the module.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
fluo generate module users
|
|
100
|
+
fluo generate controller users
|
|
101
|
+
fluo generate service users
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Common Patterns
|
|
105
|
+
|
|
106
|
+
### Decorator Codemods
|
|
107
|
+
Run codemods to align your codebase with TC39 standard decorators.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Preview changes (dry-run)
|
|
111
|
+
fluo migrate ./src
|
|
112
|
+
|
|
113
|
+
# Apply transformations
|
|
114
|
+
fluo migrate ./src --apply
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Key Transformations:**
|
|
118
|
+
- Rewrites imports from `@nestjs/common` to `@fluojs/core` or `@fluojs/http`.
|
|
119
|
+
- Removes `@Injectable()` and maps scopes to `@Scope()`.
|
|
120
|
+
- Updates `tsconfig.json` to disable `experimentalDecorators` and rewrites `baseUrl`-backed path aliases to TS6-safe `paths` entries.
|
|
121
|
+
|
|
122
|
+
### Runtime Inspection
|
|
123
|
+
Visualize your application structure and troubleshoot initialization issues.
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Export dependency graph as Mermaid
|
|
127
|
+
fluo inspect ./src/app.module.ts --mermaid
|
|
128
|
+
|
|
129
|
+
# Export snapshot for @fluojs/studio
|
|
130
|
+
fluo inspect ./src/app.module.ts --json > snapshot.json
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Public API
|
|
134
|
+
|
|
135
|
+
The package can be used programmatically to trigger CLI actions from within other tools.
|
|
136
|
+
|
|
137
|
+
| Export | Description |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `runCli(argv?, options?)` | Main entry point to execute any CLI command. |
|
|
140
|
+
| `runNewCommand(argv, options?)` | Programmatic access to the project scaffolding logic. |
|
|
141
|
+
| `GeneratorKind` | Union type of all supported generator types (e.g., `'controller'`, `'service'`). |
|
|
142
|
+
|
|
143
|
+
## Related Packages
|
|
144
|
+
|
|
145
|
+
- **[@fluojs/runtime](../runtime/README.md)**: The underlying engine used for inspection and bootstrap.
|
|
146
|
+
- **[@fluojs/studio](../studio/README.md)**: The web-based UI for visualizing `inspect --json` exports.
|
|
147
|
+
- **[@fluojs/testing](../testing/README.md)**: Used by generated test templates for integration and E2E testing.
|
|
148
|
+
- **[Canonical Runtime Package Matrix](../../docs/reference/package-surface.md)**: The source of truth for official runtime/package combinations.
|
|
149
|
+
|
|
150
|
+
## Example Sources
|
|
151
|
+
|
|
152
|
+
- [cli.ts](./src/cli.ts) - Command dispatcher and argument parsing.
|
|
153
|
+
- [commands/new.ts](./src/commands/new.ts) - Project scaffolding implementation.
|
|
154
|
+
- [generators/](./src/generators/) - Template-based file generation logic.
|
|
155
|
+
- [transforms/](./src/transforms/) - Code transformation implementations.
|
package/bin/fluo.mjs
ADDED
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type NewCommandRuntimeOptions } from './commands/new.js';
|
|
2
|
+
type CliStream = {
|
|
3
|
+
write(message: string): unknown;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Runtime dependency overrides for embedding the CLI in tests or higher-level tooling.
|
|
7
|
+
*/
|
|
8
|
+
export interface CliRuntimeOptions {
|
|
9
|
+
cwd?: string;
|
|
10
|
+
stderr?: CliStream;
|
|
11
|
+
stdout?: CliStream;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Runs the top-level CLI command dispatcher and returns a process-style exit code.
|
|
15
|
+
*
|
|
16
|
+
* This programmatic entry point mirrors the published `fluo` binary while allowing callers to swap
|
|
17
|
+
* standard streams or the working directory for tests, sandboxes, and editor integrations.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { runCli } from '@fluojs/cli';
|
|
22
|
+
*
|
|
23
|
+
* const output: string[] = [];
|
|
24
|
+
* const exitCode = await runCli(['generate', 'service', 'Post'], {
|
|
25
|
+
* cwd: '/workspace/app',
|
|
26
|
+
* stdout: { write: (chunk) => output.push(String(chunk)) },
|
|
27
|
+
* stderr: { write: (chunk) => output.push(String(chunk)) },
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @param argv Argument vector to execute. Defaults to the current process arguments without the node/bin prefix.
|
|
32
|
+
* @param runtime Optional runtime overrides shared by the top-level dispatcher and the `new` command.
|
|
33
|
+
* @returns `0` when the command completes successfully, otherwise `1` after writing the error message to `stderr`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function runCli(argv?: string[], runtime?: CliRuntimeOptions & NewCommandRuntimeOptions): Promise<number>;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,wBAAwB,EAA2B,MAAM,mBAAmB,CAAC;AAK3F,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAmPD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE,iBAAiB,GAAG,wBAA6B,GACzD,OAAO,CAAC,MAAM,CAAC,CAgGjB"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { runGenerateCommand } from './commands/generate.js';
|
|
5
|
+
import { inspectUsage, runInspectCommand } from './commands/inspect.js';
|
|
6
|
+
import { migrateUsage, runMigrateCommand } from './commands/migrate.js';
|
|
7
|
+
import { newUsage, runNewCommand } from './commands/new.js';
|
|
8
|
+
import { generatorManifest, resolveGeneratorKind } from './generators/manifest.js';
|
|
9
|
+
import { renderAliasList, renderHelpTable } from './help.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Runtime dependency overrides for embedding the CLI in tests or higher-level tooling.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const GENERATE_KIND_HELP = [...generatorManifest.map(entry => ({
|
|
16
|
+
aliases: [...entry.aliases],
|
|
17
|
+
description: entry.description,
|
|
18
|
+
kind: entry.kind,
|
|
19
|
+
schematic: entry.schematic,
|
|
20
|
+
wiring: entry.wiringBehavior === 'auto-registered' ? 'auto' : 'manual'
|
|
21
|
+
}))];
|
|
22
|
+
const GENERATE_OPTION_HELP = [{
|
|
23
|
+
aliases: ['-o'],
|
|
24
|
+
description: 'Write generated files under a specific source directory.',
|
|
25
|
+
option: '--target-directory <path>'
|
|
26
|
+
}, {
|
|
27
|
+
aliases: ['-f'],
|
|
28
|
+
description: 'Overwrite files that already exist.',
|
|
29
|
+
option: '--force'
|
|
30
|
+
}, {
|
|
31
|
+
aliases: ['-h'],
|
|
32
|
+
description: 'Show help for the generate command.',
|
|
33
|
+
option: '--help'
|
|
34
|
+
}];
|
|
35
|
+
const TOP_LEVEL_COMMAND_HELP = [{
|
|
36
|
+
aliases: ['create'],
|
|
37
|
+
command: 'new',
|
|
38
|
+
description: 'Scaffold a new fluo application and install dependencies.'
|
|
39
|
+
}, {
|
|
40
|
+
aliases: ['g'],
|
|
41
|
+
command: 'generate',
|
|
42
|
+
description: 'Generate a schematic inside an existing fluo application.'
|
|
43
|
+
}, {
|
|
44
|
+
aliases: [],
|
|
45
|
+
command: 'inspect',
|
|
46
|
+
description: 'Inspect runtime platform snapshot/diagnostics and emit timing optionally.'
|
|
47
|
+
}, {
|
|
48
|
+
aliases: [],
|
|
49
|
+
command: 'migrate',
|
|
50
|
+
description: 'Run NestJS-to-fluo codemods (dry-run by default).'
|
|
51
|
+
}, {
|
|
52
|
+
aliases: [],
|
|
53
|
+
command: 'help',
|
|
54
|
+
description: 'Show top-level or command-specific help.'
|
|
55
|
+
}];
|
|
56
|
+
function normalizeGeneratorKind(value) {
|
|
57
|
+
return resolveGeneratorKind(value);
|
|
58
|
+
}
|
|
59
|
+
function isHelpFlag(value) {
|
|
60
|
+
return value === '--help' || value === '-h';
|
|
61
|
+
}
|
|
62
|
+
function generateUsage() {
|
|
63
|
+
return ['Usage: fluo generate|g <kind> <name> [options]', '', 'Schematics', renderHelpTable(GENERATE_KIND_HELP, [{
|
|
64
|
+
header: 'Schematic',
|
|
65
|
+
render: entry => entry.schematic
|
|
66
|
+
}, {
|
|
67
|
+
header: 'Aliases',
|
|
68
|
+
render: entry => renderAliasList(entry.aliases)
|
|
69
|
+
}, {
|
|
70
|
+
header: 'Wiring',
|
|
71
|
+
render: entry => entry.wiring
|
|
72
|
+
}, {
|
|
73
|
+
header: 'Description',
|
|
74
|
+
render: entry => entry.description
|
|
75
|
+
}]), '', ' auto = class is auto-registered in the domain module (created if absent)', ' manual = files only; you must wire the generated class into a module yourself', '', 'Options', renderHelpTable(GENERATE_OPTION_HELP, [{
|
|
76
|
+
header: 'Option',
|
|
77
|
+
render: entry => entry.option
|
|
78
|
+
}, {
|
|
79
|
+
header: 'Aliases',
|
|
80
|
+
render: entry => renderAliasList(entry.aliases)
|
|
81
|
+
}, {
|
|
82
|
+
header: 'Description',
|
|
83
|
+
render: entry => entry.description
|
|
84
|
+
}]), '', 'Next steps:', ' Run \'pnpm typecheck\' to verify the generated module wiring.', ' Run \'pnpm test\' to execute the generated test templates.', '', 'Docs: https://github.com/fluojs/fluo/tree/main/docs/getting-started/generator-workflow.md'].join('\n');
|
|
85
|
+
}
|
|
86
|
+
function usage() {
|
|
87
|
+
return ['Usage: fluo <command> [options]', '', 'Commands', renderHelpTable(TOP_LEVEL_COMMAND_HELP, [{
|
|
88
|
+
header: 'Command',
|
|
89
|
+
render: entry => entry.command
|
|
90
|
+
}, {
|
|
91
|
+
header: 'Aliases',
|
|
92
|
+
render: entry => renderAliasList(entry.aliases)
|
|
93
|
+
}, {
|
|
94
|
+
header: 'Description',
|
|
95
|
+
render: entry => entry.description
|
|
96
|
+
}]), '', "Run 'fluo help <command>' for more information on a command.", 'Docs: https://github.com/fluojs/fluo/tree/main/docs/getting-started/quick-start.md'].join('\n');
|
|
97
|
+
}
|
|
98
|
+
function resolveDefaultTargetDirectory(startDirectory) {
|
|
99
|
+
const resolvedStartDirectory = resolve(startDirectory);
|
|
100
|
+
if (existsSync(join(resolvedStartDirectory, 'package.json')) && existsSync(join(resolvedStartDirectory, 'src'))) {
|
|
101
|
+
return join(resolvedStartDirectory, 'src');
|
|
102
|
+
}
|
|
103
|
+
if (existsSync(join(resolvedStartDirectory, 'apps'))) {
|
|
104
|
+
const appDirectories = readdirSync(join(resolvedStartDirectory, 'apps'), {
|
|
105
|
+
withFileTypes: true
|
|
106
|
+
}).filter(entry => entry.isDirectory()).map(entry => join(resolvedStartDirectory, 'apps', entry.name)).filter(directory => existsSync(join(directory, 'package.json')) && existsSync(join(directory, 'src')));
|
|
107
|
+
if (appDirectories.length === 1) {
|
|
108
|
+
return join(appDirectories[0], 'src');
|
|
109
|
+
}
|
|
110
|
+
if (appDirectories.length > 1) {
|
|
111
|
+
throw new Error('Multiple app targets were found under apps/. Use --target-directory to choose the app src directory explicitly.');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return resolvedStartDirectory;
|
|
115
|
+
}
|
|
116
|
+
function parseGenerateArgs(argv) {
|
|
117
|
+
const [command, rawKind, name, ...optionArgs] = argv;
|
|
118
|
+
const kind = normalizeGeneratorKind(rawKind);
|
|
119
|
+
if (!(command === 'g' || command === 'generate')) {
|
|
120
|
+
throw new Error(usage());
|
|
121
|
+
}
|
|
122
|
+
if (!kind || !name) {
|
|
123
|
+
throw new Error(generateUsage());
|
|
124
|
+
}
|
|
125
|
+
if (name.startsWith('-')) {
|
|
126
|
+
throw new Error(`Invalid resource name "${name}": names cannot start with "-".`);
|
|
127
|
+
}
|
|
128
|
+
const parsedOptions = {};
|
|
129
|
+
let targetDirectory;
|
|
130
|
+
let seenForce = false;
|
|
131
|
+
let seenTargetDirectory = false;
|
|
132
|
+
for (let index = 0; index < optionArgs.length; index += 1) {
|
|
133
|
+
const option = optionArgs[index];
|
|
134
|
+
const next = optionArgs[index + 1];
|
|
135
|
+
if (option === '--target-directory' || option === '-o') {
|
|
136
|
+
if (seenTargetDirectory) {
|
|
137
|
+
throw new Error('Duplicate --target-directory option.');
|
|
138
|
+
}
|
|
139
|
+
if (!next || next.startsWith('-')) {
|
|
140
|
+
throw new Error('Expected --target-directory to have a path value.');
|
|
141
|
+
}
|
|
142
|
+
targetDirectory = next;
|
|
143
|
+
seenTargetDirectory = true;
|
|
144
|
+
index += 1;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (option === '--force' || option === '-f') {
|
|
148
|
+
if (seenForce) {
|
|
149
|
+
throw new Error('Duplicate --force option.');
|
|
150
|
+
}
|
|
151
|
+
parsedOptions.force = true;
|
|
152
|
+
seenForce = true;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
throw new Error(`Unknown option: ${option}`);
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
kind,
|
|
159
|
+
name,
|
|
160
|
+
options: parsedOptions,
|
|
161
|
+
targetDirectory
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function parseCommand(argv) {
|
|
165
|
+
const [command] = argv;
|
|
166
|
+
if (command === 'new' || command === 'create') {
|
|
167
|
+
return {
|
|
168
|
+
argv: argv.slice(1),
|
|
169
|
+
command: 'new'
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (command === 'migrate') {
|
|
173
|
+
return {
|
|
174
|
+
argv: argv.slice(1),
|
|
175
|
+
command: 'migrate'
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
if (command === 'inspect') {
|
|
179
|
+
return {
|
|
180
|
+
argv: argv.slice(1),
|
|
181
|
+
command: 'inspect'
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
argv,
|
|
186
|
+
command: 'generate',
|
|
187
|
+
parsed: parseGenerateArgs(argv)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Runs the top-level CLI command dispatcher and returns a process-style exit code.
|
|
193
|
+
*
|
|
194
|
+
* This programmatic entry point mirrors the published `fluo` binary while allowing callers to swap
|
|
195
|
+
* standard streams or the working directory for tests, sandboxes, and editor integrations.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* import { runCli } from '@fluojs/cli';
|
|
200
|
+
*
|
|
201
|
+
* const output: string[] = [];
|
|
202
|
+
* const exitCode = await runCli(['generate', 'service', 'Post'], {
|
|
203
|
+
* cwd: '/workspace/app',
|
|
204
|
+
* stdout: { write: (chunk) => output.push(String(chunk)) },
|
|
205
|
+
* stderr: { write: (chunk) => output.push(String(chunk)) },
|
|
206
|
+
* });
|
|
207
|
+
* ```
|
|
208
|
+
*
|
|
209
|
+
* @param argv Argument vector to execute. Defaults to the current process arguments without the node/bin prefix.
|
|
210
|
+
* @param runtime Optional runtime overrides shared by the top-level dispatcher and the `new` command.
|
|
211
|
+
* @returns `0` when the command completes successfully, otherwise `1` after writing the error message to `stderr`.
|
|
212
|
+
*/
|
|
213
|
+
export async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
214
|
+
const cwd = runtime.cwd ? resolve(runtime.cwd) : process.cwd();
|
|
215
|
+
const stdout = runtime.stdout ?? process.stdout;
|
|
216
|
+
const stderr = runtime.stderr ?? process.stderr;
|
|
217
|
+
try {
|
|
218
|
+
if (argv.length === 0) {
|
|
219
|
+
throw new Error(usage());
|
|
220
|
+
}
|
|
221
|
+
if (argv[0] === 'help') {
|
|
222
|
+
const topic = argv[1];
|
|
223
|
+
if (topic === 'new' || topic === 'create') {
|
|
224
|
+
stdout.write(`${newUsage()}\n`);
|
|
225
|
+
return 0;
|
|
226
|
+
}
|
|
227
|
+
if (topic === 'g' || topic === 'generate') {
|
|
228
|
+
stdout.write(`${generateUsage()}\n`);
|
|
229
|
+
return 0;
|
|
230
|
+
}
|
|
231
|
+
if (topic === 'migrate') {
|
|
232
|
+
stdout.write(`${migrateUsage()}\n`);
|
|
233
|
+
return 0;
|
|
234
|
+
}
|
|
235
|
+
if (topic === 'inspect') {
|
|
236
|
+
stdout.write(`${inspectUsage()}\n`);
|
|
237
|
+
return 0;
|
|
238
|
+
}
|
|
239
|
+
stdout.write(`${usage()}\n`);
|
|
240
|
+
return 0;
|
|
241
|
+
}
|
|
242
|
+
if (isHelpFlag(argv[0])) {
|
|
243
|
+
stdout.write(`${usage()}\n`);
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
if ((argv[0] === 'g' || argv[0] === 'generate') && argv.slice(1).some(isHelpFlag)) {
|
|
247
|
+
stdout.write(`${generateUsage()}\n`);
|
|
248
|
+
return 0;
|
|
249
|
+
}
|
|
250
|
+
if (argv[0] === 'migrate' && argv.slice(1).some(isHelpFlag)) {
|
|
251
|
+
stdout.write(`${migrateUsage()}\n`);
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
if (argv[0] === 'inspect' && argv.slice(1).some(isHelpFlag)) {
|
|
255
|
+
stdout.write(`${inspectUsage()}\n`);
|
|
256
|
+
return 0;
|
|
257
|
+
}
|
|
258
|
+
const parsedCommand = parseCommand(argv);
|
|
259
|
+
if (parsedCommand.command === 'new') {
|
|
260
|
+
return runNewCommand(parsedCommand.argv, runtime);
|
|
261
|
+
}
|
|
262
|
+
if (parsedCommand.command === 'migrate') {
|
|
263
|
+
return runMigrateCommand(parsedCommand.argv, runtime);
|
|
264
|
+
}
|
|
265
|
+
if (parsedCommand.command === 'inspect') {
|
|
266
|
+
return runInspectCommand(parsedCommand.argv, runtime);
|
|
267
|
+
}
|
|
268
|
+
const targetDirectory = resolve(cwd, parsedCommand.parsed.targetDirectory ?? resolveDefaultTargetDirectory(cwd));
|
|
269
|
+
const result = runGenerateCommand(parsedCommand.parsed.kind, parsedCommand.parsed.name, targetDirectory, parsedCommand.parsed.options);
|
|
270
|
+
stdout.write(`Generated ${result.generatedFiles.length} file(s):\n`);
|
|
271
|
+
for (const file of result.generatedFiles) {
|
|
272
|
+
stdout.write(` CREATE ${file}\n`);
|
|
273
|
+
}
|
|
274
|
+
stdout.write('\n');
|
|
275
|
+
if (result.wiringBehavior === 'auto-registered' && result.moduleRegistered) {
|
|
276
|
+
stdout.write(`Wiring: auto-registered in ${result.modulePath ?? 'module'}\n`);
|
|
277
|
+
} else if (result.wiringBehavior === 'files-only') {
|
|
278
|
+
stdout.write('Wiring: files only — manual registration required (see next steps)\n');
|
|
279
|
+
}
|
|
280
|
+
stdout.write(`\nNext steps:\n ${result.nextStepHint}\n`);
|
|
281
|
+
return 0;
|
|
282
|
+
} catch (error) {
|
|
283
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
284
|
+
stderr.write(`${message}\n`);
|
|
285
|
+
return 1;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
|
|
289
|
+
process.exitCode = await runCli(undefined, {
|
|
290
|
+
userAgent: process.env.npm_config_user_agent
|
|
291
|
+
});
|
|
292
|
+
}
|