@fluojs/cli 1.0.0-beta.1 → 1.0.0-beta.2
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 +52 -6
- package/README.md +52 -6
- package/dist/cli.d.ts +12 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +69 -33
- package/dist/commands/generate.d.ts +11 -1
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +71 -2
- package/dist/commands/inspect.d.ts +20 -0
- package/dist/commands/inspect.d.ts.map +1 -1
- package/dist/commands/inspect.js +149 -31
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +42 -0
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +21 -1
- package/dist/generator-types.d.ts +15 -1
- package/dist/generator-types.d.ts.map +1 -1
- package/dist/generators/manifest.d.ts +267 -0
- package/dist/generators/manifest.d.ts.map +1 -1
- package/dist/generators/manifest.js +86 -1
- package/dist/new/prompt.d.ts +1 -0
- package/dist/new/prompt.d.ts.map +1 -1
- package/dist/new/prompt.js +7 -1
- package/dist/new/scaffold.d.ts.map +1 -1
- package/dist/new/scaffold.js +17 -1
- package/dist/registry.d.ts +4 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +13 -5
- package/dist/update-check.d.ts +50 -0
- package/dist/update-check.d.ts.map +1 -0
- package/dist/update-check.js +356 -0
- package/package.json +9 -1
package/README.ko.md
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
<p><a href="./README.md"><kbd>English</kbd></a> <strong><kbd>한국어</kbd></strong></p>
|
|
4
4
|
|
|
5
|
-
fluo 공식 CLI — 새 애플리케이션 부트스트랩, 컴포넌트 생성, 런타임
|
|
5
|
+
fluo 공식 CLI — 새 애플리케이션 부트스트랩, 컴포넌트 생성, 런타임 검사 데이터 내보내기, 코드 변환을 지원합니다.
|
|
6
6
|
|
|
7
7
|
## 목차
|
|
8
8
|
|
|
9
9
|
- [설치](#설치)
|
|
10
|
+
- [업데이트 확인](#업데이트-확인)
|
|
10
11
|
- [사용 시점](#사용-시점)
|
|
11
12
|
- [빠른 시작](#빠른-시작)
|
|
12
13
|
- [주요 패턴](#주요-패턴)
|
|
@@ -32,12 +33,18 @@ pnpm dlx @fluojs/cli new my-app
|
|
|
32
33
|
- 지원되는 설치 경로는 전역 패키지(`pnpm add -g @fluojs/cli`)와 무설치 실행 경로(`pnpm dlx @fluojs/cli ...`)입니다.
|
|
33
34
|
- 배포되는 `fluo` bin은 `package.json`에 선언된 dist 빌드 CLI 엔트리포인트를 기준으로 동작합니다.
|
|
34
35
|
|
|
36
|
+
## 업데이트 확인
|
|
37
|
+
|
|
38
|
+
`fluo`가 interactive TTY에서 실행되면 로컬 캐시를 사용해 공개 npm `latest` dist-tag의 `@fluojs/cli` 버전을 확인하므로 매 invocation마다 registry를 호출하지 않습니다. 더 새로운 버전이 있으면 CLI가 설치 여부를 묻습니다. 거절하면 현재 설치된 버전으로 기존 명령을 계속 실행하고, 승인하면 `pnpm add -g @fluojs/cli@<latest>`를 실행한 뒤 같은 인자로 업데이트된 `fluo` 바이너리를 다시 시작합니다.
|
|
39
|
+
|
|
40
|
+
업데이트 확인은 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
|
+
|
|
35
42
|
## 사용 시점
|
|
36
43
|
|
|
37
44
|
- **부트스트랩**: 표준적이고 검증 가능한 구조로 새 프로젝트를 시작할 때.
|
|
38
45
|
- **코드 생성**: 일관된 네이밍 규칙과 자동 연결 기능을 갖춘 모듈, 컨트롤러, 서비스, 레포지토리를 생성할 때.
|
|
39
46
|
- **코드 변환**: 기존 코드베이스를 fluo의 표준 데코레이터 모델에 맞출 때.
|
|
40
|
-
- **검사(Inspection)**: 런타임
|
|
47
|
+
- **검사(Inspection)**: 런타임 snapshot 데이터를 내보내고 그래프 보기 또는 렌더링은 Studio 소유 헬퍼에 위임할 때.
|
|
41
48
|
|
|
42
49
|
## 빠른 시작
|
|
43
50
|
|
|
@@ -90,6 +97,16 @@ fluo new my-mixed-app --shape mixed --transport tcp --runtime node --platform fa
|
|
|
90
97
|
|
|
91
98
|
`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
99
|
|
|
100
|
+
side effect 없이 완전히 resolved starter를 미리 확인하려면 `--print-plan`을 사용하세요:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
fluo new my-app --shape application --runtime node --platform fastify --print-plan
|
|
104
|
+
fluo new my-service --shape microservice --transport tcp --print-plan
|
|
105
|
+
fluo new my-mixed-app --shape mixed --print-plan
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
plan preview 모드는 실제 scaffold와 같은 프로젝트 이름, shape, runtime, platform, transport, tooling preset, package manager, install 선택, git 선택을 resolve합니다. 선택된 starter recipe와 dependency 세트를 출력한 뒤 파일 생성, dependency 설치, git 저장소 초기화 없이 종료합니다.
|
|
109
|
+
|
|
93
110
|
현재 제공되는 스타터 매트릭스(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
111
|
|
|
95
112
|
### 2. 기능 추가
|
|
@@ -99,8 +116,16 @@ fluo new my-mixed-app --shape mixed --transport tcp --runtime node --platform fa
|
|
|
99
116
|
fluo generate module users
|
|
100
117
|
fluo generate controller users
|
|
101
118
|
fluo generate service users
|
|
119
|
+
fluo generate request-dto users CreateUser
|
|
120
|
+
fluo generate service users --dry-run
|
|
102
121
|
```
|
|
103
122
|
|
|
123
|
+
Request DTO 생성은 feature 디렉터리와 DTO 클래스 이름을 분리해서 받습니다. 따라서 `CreateUser`, `UpdateUser` 같은 여러 입력 계약을 같은 `src/users/` 슬라이스 안에 둘 수 있습니다.
|
|
124
|
+
|
|
125
|
+
`--dry-run`을 추가하면 실제 실행과 같은 타깃 해석, 기존 파일 건너뛰기 또는 덮어쓰기 판단, 모듈 자동 등록 계획, 파일만 생성하는 wiring 상태, 다음 단계 힌트를 미리 볼 수 있습니다. 이 모드는 디렉터리 생성, 파일 쓰기, 모듈 갱신을 수행하지 않습니다. `--force`는 내용이 달라질 기존 파일의 계획 항목을 `SKIP`에서 `OVERWRITE`로 바꾸며, `--target-directory`는 실제 실행과 동일하게 지정한 소스 디렉터리 기준으로 preview 범위를 제한합니다.
|
|
126
|
+
|
|
127
|
+
Generator discovery는 의도적으로 built-in `@fluojs/cli/builtin` collection으로 제한됩니다. 외부 package-owned 또는 app-local generator collection은 보류되어 있습니다. `fluo generate`는 config file을 스캔하거나, 임의 package를 로드하거나, workspace-owned collection code를 실행하지 않습니다. 이 경계는 shipped generator 계약을 보존하면서 generator metadata, option schema, help output, file-write boundary를 결정적이고 테스트 가능하게 유지합니다.
|
|
128
|
+
|
|
104
129
|
## 주요 패턴
|
|
105
130
|
|
|
106
131
|
### 데코레이터 코드 변환
|
|
@@ -109,27 +134,48 @@ fluo generate service users
|
|
|
109
134
|
```bash
|
|
110
135
|
# 변경 사항 미리보기 (dry-run)
|
|
111
136
|
fluo migrate ./src
|
|
137
|
+
fluo migrate ./src --json
|
|
112
138
|
|
|
113
139
|
# 변환 적용
|
|
114
140
|
fluo migrate ./src --apply
|
|
141
|
+
fluo migrate ./src --apply --json
|
|
115
142
|
```
|
|
116
143
|
|
|
144
|
+
CI 작업, 대시보드, migration report에서 안정적인 machine-readable 결과가 필요하면 `--json`을 사용하세요. 사람을 위한 출력은 기본값으로 유지됩니다. JSON 모드는 성공 시 stdout에 structured report만 기록하고, parser 오류나 잘못된 flag 조합은 기존처럼 stderr에 메시지를 기록한 뒤 exit code `1`을 반환하며 partial JSON을 출력하지 않습니다. Report에는 `mode`(`dry-run` 또는 `apply`), `dryRun`, `apply`, 활성화된 `transforms`, `scannedFiles`, `changedFiles`, 전체 `warningCount`, 그리고 `filePath`, `changed`, `appliedTransforms`, `warningCount`, category label과 source line number가 포함된 warnings per-file metadata가 포함됩니다.
|
|
145
|
+
|
|
117
146
|
**주요 변환 사항:**
|
|
118
147
|
- `@nestjs/common` 임포트를 `@fluojs/core` 또는 `@fluojs/http`로 재작성합니다.
|
|
119
148
|
- `@Injectable()`을 제거하고 스코프를 `@Scope()`로 매핑합니다.
|
|
120
149
|
- `tsconfig.json`을 업데이트하여 `experimentalDecorators`를 비활성화하고 `baseUrl` 기반 경로 별칭을 TS6-safe `paths` 엔트리로 재작성합니다.
|
|
121
150
|
|
|
122
151
|
### 런타임 검사 (Inspection)
|
|
123
|
-
애플리케이션 구조를
|
|
152
|
+
CLI가 그래프 렌더링을 소유하지 않으면서 애플리케이션 구조를 내보내고 초기화 문제를 해결합니다.
|
|
124
153
|
|
|
125
154
|
```bash
|
|
126
|
-
#
|
|
155
|
+
# 선택적 Studio 렌더러를 통해 Mermaid 내보내기
|
|
127
156
|
fluo inspect ./src/app.module.ts --mermaid
|
|
128
157
|
|
|
129
158
|
# @fluojs/studio용 snapshot 내보내기
|
|
130
159
|
fluo inspect ./src/app.module.ts --json > snapshot.json
|
|
160
|
+
|
|
161
|
+
# shell redirection 없이 같은 JSON snapshot을 CI artifact 경로에 쓰기
|
|
162
|
+
fluo inspect ./src/app.module.ts --json --output artifacts/inspect-snapshot.json
|
|
163
|
+
|
|
164
|
+
# 런타임이 생산한 snapshot 옆에 bootstrap timing 포함하기
|
|
165
|
+
fluo inspect ./src/app.module.ts --json --timing
|
|
166
|
+
|
|
167
|
+
# 요약, snapshot, diagnostics, timing을 포함한 support triage report 내보내기
|
|
168
|
+
fluo inspect ./src/app.module.ts --report --output artifacts/inspect-report.json
|
|
131
169
|
```
|
|
132
170
|
|
|
171
|
+
런타임이 inspection snapshot을 생산합니다. `fluo inspect`는 그 snapshot을 JSON으로 직렬화하고, `fluo inspect --mermaid`는 snapshot-to-Mermaid 렌더링을 선택적 `@fluojs/studio` 계약에 위임합니다. `--timing`은 JSON 출력에 bootstrap timing diagnostics를 기록하고, `--report`는 CI/support triage를 위해 런타임이 생산한 snapshot을 안정적인 요약과 함께 감쌉니다. `--output <path>`는 선택한 inspect payload를 stdout 대신 명시적 artifact 경로에 씁니다. 이 동작은 검사 대상 애플리케이션을 writable하게 만들지 않으며, 일반 bootstrap/close cycle 외에 module graph state를 바꾸지 않습니다. Mermaid 출력이 필요하면 명령을 실행하는 프로젝트에 Studio를 설치하세요:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
pnpm add -D @fluojs/studio
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Studio가 없으면 CI와 non-interactive 실행은 prompt나 package manager 실행 없이 설치 안내와 함께 빠르게 실패합니다. Interactive 실행에서는 Studio 설치 여부를 물을 수 있지만, 명시적으로 승인되고 구현된 설치 흐름이 없는 한 `fluo inspect`가 package manager install을 실행하지 않습니다.
|
|
178
|
+
|
|
133
179
|
## 공개 API
|
|
134
180
|
|
|
135
181
|
다른 도구 내에서 CLI 동작을 트리거하기 위해 패키지를 프로그래밍 방식으로 사용할 수 있습니다.
|
|
@@ -142,8 +188,8 @@ fluo inspect ./src/app.module.ts --json > snapshot.json
|
|
|
142
188
|
|
|
143
189
|
## 관련 패키지
|
|
144
190
|
|
|
145
|
-
- **[@fluojs/runtime](../runtime/README.ko.md)**: 검사
|
|
146
|
-
- **[@fluojs/studio](../studio/README.ko.md)**: `inspect --json` 출력을
|
|
191
|
+
- **[@fluojs/runtime](../runtime/README.ko.md)**: 부트스트랩 안전 런타임 검사 중 inspection snapshot을 생산하는 기본 엔진입니다.
|
|
192
|
+
- **[@fluojs/studio](../studio/README.ko.md)**: `inspect --json` 출력을 확인하고 `inspect --mermaid`가 사용하는 canonical renderer를 제공하는 웹 기반 UI입니다.
|
|
147
193
|
- **[@fluojs/testing](../testing/README.ko.md)**: 통합 및 E2E 테스트를 위해 생성된 테스트 템플릿에서 사용됩니다.
|
|
148
194
|
- **[Canonical Runtime Package Matrix](../../docs/reference/package-surface.ko.md)**: 공식 런타임/패키지 조합을 보여주는 기준 문서입니다.
|
|
149
195
|
|
package/README.md
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
<p><strong><kbd>English</kbd></strong> <a href="./README.ko.md"><kbd>한국어</kbd></a></p>
|
|
4
4
|
|
|
5
|
-
The canonical CLI for fluo — bootstrap new applications, generate components,
|
|
5
|
+
The canonical CLI for fluo — bootstrap new applications, generate components, export runtime inspection data, and run code transforms.
|
|
6
6
|
|
|
7
7
|
## Table of Contents
|
|
8
8
|
|
|
9
9
|
- [Installation](#installation)
|
|
10
|
+
- [Update Checks](#update-checks)
|
|
10
11
|
- [When to Use](#when-to-use)
|
|
11
12
|
- [Quick Start](#quick-start)
|
|
12
13
|
- [Common Patterns](#common-patterns)
|
|
@@ -32,12 +33,18 @@ pnpm dlx @fluojs/cli new my-app
|
|
|
32
33
|
- The supported install paths are the global package (`pnpm add -g @fluojs/cli`) and the no-install runner (`pnpm dlx @fluojs/cli ...`).
|
|
33
34
|
- The published `fluo` bin is backed by the dist-built CLI entrypoint declared in `package.json`.
|
|
34
35
|
|
|
36
|
+
## Update Checks
|
|
37
|
+
|
|
38
|
+
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 runs `pnpm add -g @fluojs/cli@<latest>` and then restarts `fluo` with the same arguments under the updated binary.
|
|
39
|
+
|
|
40
|
+
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
|
+
|
|
35
42
|
## When to Use
|
|
36
43
|
|
|
37
44
|
- **Bootstrapping**: When starting a new project with a standard, verifiable structure.
|
|
38
45
|
- **Generation**: To create modules, controllers, services, and repositories with consistent naming and automatic wiring.
|
|
39
46
|
- **Code transforms**: When aligning an existing codebase with fluo's standard decorator model.
|
|
40
|
-
- **Inspection**: To
|
|
47
|
+
- **Inspection**: To export runtime snapshot data and delegate graph viewing or rendering to Studio-owned helpers.
|
|
41
48
|
|
|
42
49
|
## Quick Start
|
|
43
50
|
|
|
@@ -90,6 +97,16 @@ fluo new my-mixed-app --shape mixed --transport tcp --runtime node --platform fa
|
|
|
90
97
|
|
|
91
98
|
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
99
|
|
|
100
|
+
Use `--print-plan` when you want to preview the fully resolved starter without side effects:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
fluo new my-app --shape application --runtime node --platform fastify --print-plan
|
|
104
|
+
fluo new my-service --shape microservice --transport tcp --print-plan
|
|
105
|
+
fluo new my-mixed-app --shape mixed --print-plan
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Plan preview mode resolves the same project name, shape, runtime, platform, transport, tooling preset, package manager, install choice, and git choice as a real scaffold. It prints the selected starter recipe and dependency sets, then exits without creating files, installing dependencies, or initializing a git repository.
|
|
109
|
+
|
|
93
110
|
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
111
|
|
|
95
112
|
### 2. Generate a feature
|
|
@@ -99,8 +116,16 @@ Add a new resource with a controller and service, automatically wired into the m
|
|
|
99
116
|
fluo generate module users
|
|
100
117
|
fluo generate controller users
|
|
101
118
|
fluo generate service users
|
|
119
|
+
fluo generate request-dto users CreateUser
|
|
120
|
+
fluo generate service users --dry-run
|
|
102
121
|
```
|
|
103
122
|
|
|
123
|
+
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
|
+
|
|
125
|
+
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.
|
|
126
|
+
|
|
127
|
+
Generator discovery is intentionally limited to the built-in `@fluojs/cli/builtin` collection. External package-owned or app-local generator collections are deferred: `fluo generate` does not scan config files, load arbitrary packages, or execute workspace-owned collection code. This keeps generator metadata, option schemas, help output, and file-write boundaries deterministic and testable while preserving the shipped generator contract.
|
|
128
|
+
|
|
104
129
|
## Common Patterns
|
|
105
130
|
|
|
106
131
|
### Decorator Codemods
|
|
@@ -109,27 +134,48 @@ Run codemods to align your codebase with TC39 standard decorators.
|
|
|
109
134
|
```bash
|
|
110
135
|
# Preview changes (dry-run)
|
|
111
136
|
fluo migrate ./src
|
|
137
|
+
fluo migrate ./src --json
|
|
112
138
|
|
|
113
139
|
# Apply transformations
|
|
114
140
|
fluo migrate ./src --apply
|
|
141
|
+
fluo migrate ./src --apply --json
|
|
115
142
|
```
|
|
116
143
|
|
|
144
|
+
Use `--json` when CI jobs, dashboards, or migration reports need a stable machine-readable result. Human output remains the default. JSON mode writes only the structured report to stdout on success, while parser errors and invalid flag combinations still write their message to stderr and return exit code `1` without partial JSON output. The report includes `mode` (`dry-run` or `apply`), `dryRun`, `apply`, enabled `transforms`, `scannedFiles`, `changedFiles`, aggregate `warningCount`, and per-file metadata with `filePath`, `changed`, `appliedTransforms`, `warningCount`, and warnings including category labels and source line numbers.
|
|
145
|
+
|
|
117
146
|
**Key Transformations:**
|
|
118
147
|
- Rewrites imports from `@nestjs/common` to `@fluojs/core` or `@fluojs/http`.
|
|
119
148
|
- Removes `@Injectable()` and maps scopes to `@Scope()`.
|
|
120
149
|
- Updates `tsconfig.json` to disable `experimentalDecorators` and rewrites `baseUrl`-backed path aliases to TS6-safe `paths` entries.
|
|
121
150
|
|
|
122
151
|
### Runtime Inspection
|
|
123
|
-
|
|
152
|
+
Export your application structure and troubleshoot initialization issues without making the CLI own graph rendering.
|
|
124
153
|
|
|
125
154
|
```bash
|
|
126
|
-
# Export
|
|
155
|
+
# Export Mermaid through the optional Studio renderer
|
|
127
156
|
fluo inspect ./src/app.module.ts --mermaid
|
|
128
157
|
|
|
129
158
|
# Export snapshot for @fluojs/studio
|
|
130
159
|
fluo inspect ./src/app.module.ts --json > snapshot.json
|
|
160
|
+
|
|
161
|
+
# Write the same JSON snapshot to a CI artifact path without shell redirection
|
|
162
|
+
fluo inspect ./src/app.module.ts --json --output artifacts/inspect-snapshot.json
|
|
163
|
+
|
|
164
|
+
# Include bootstrap timing next to the runtime-produced snapshot
|
|
165
|
+
fluo inspect ./src/app.module.ts --json --timing
|
|
166
|
+
|
|
167
|
+
# Emit a support triage report with summary, snapshot, diagnostics, and timing
|
|
168
|
+
fluo inspect ./src/app.module.ts --report --output artifacts/inspect-report.json
|
|
131
169
|
```
|
|
132
170
|
|
|
171
|
+
The runtime produces the inspection snapshot. `fluo inspect` serializes that snapshot as JSON, and `fluo inspect --mermaid` delegates snapshot-to-Mermaid rendering to the optional `@fluojs/studio` contract. `--timing` records bootstrap timing diagnostics for JSON output, and `--report` wraps the runtime-produced snapshot with a stable summary for CI/support triage. `--output <path>` writes the selected inspect payload to an explicit artifact path instead of stdout; it does not make the inspected application writable or change module graph state beyond the normal bootstrap/close cycle. Install Studio in the project that runs the command when you need Mermaid output:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
pnpm add -D @fluojs/studio
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
If Studio is missing, CI and other non-interactive runs fail fast with install guidance instead of prompting or running a package manager. Interactive runs may ask whether you want to install Studio, but `fluo inspect` does not run installs unless an explicit install flow is implemented and approved.
|
|
178
|
+
|
|
133
179
|
## Public API
|
|
134
180
|
|
|
135
181
|
The package can be used programmatically to trigger CLI actions from within other tools.
|
|
@@ -142,8 +188,8 @@ The package can be used programmatically to trigger CLI actions from within othe
|
|
|
142
188
|
|
|
143
189
|
## Related Packages
|
|
144
190
|
|
|
145
|
-
- **[@fluojs/runtime](../runtime/README.md)**: The underlying engine
|
|
146
|
-
- **[@fluojs/studio](../studio/README.md)**: The web-based UI for
|
|
191
|
+
- **[@fluojs/runtime](../runtime/README.md)**: The underlying engine that produces inspection snapshots during bootstrap-safe runtime inspection.
|
|
192
|
+
- **[@fluojs/studio](../studio/README.md)**: The web-based UI for viewing `inspect --json` exports and the canonical renderer used by `inspect --mermaid`.
|
|
147
193
|
- **[@fluojs/testing](../testing/README.md)**: Used by generated test templates for integration and E2E testing.
|
|
148
194
|
- **[Canonical Runtime Package Matrix](../../docs/reference/package-surface.md)**: The source of truth for official runtime/package combinations.
|
|
149
195
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
|
+
import { type InspectCommandRuntimeOptions } from './commands/inspect.js';
|
|
1
2
|
import { type NewCommandRuntimeOptions } from './commands/new.js';
|
|
3
|
+
import { type CliUpdateCheckRuntimeOptions } from './update-check.js';
|
|
2
4
|
type CliStream = {
|
|
5
|
+
isTTY?: boolean;
|
|
3
6
|
write(message: string): unknown;
|
|
4
7
|
};
|
|
8
|
+
type CliReadableStream = {
|
|
9
|
+
isTTY?: boolean;
|
|
10
|
+
};
|
|
5
11
|
/**
|
|
6
12
|
* Runtime dependency overrides for embedding the CLI in tests or higher-level tooling.
|
|
7
13
|
*/
|
|
8
14
|
export interface CliRuntimeOptions {
|
|
15
|
+
ci?: boolean;
|
|
9
16
|
cwd?: string;
|
|
17
|
+
env?: NodeJS.ProcessEnv;
|
|
10
18
|
stderr?: CliStream;
|
|
19
|
+
stdin?: CliReadableStream;
|
|
11
20
|
stdout?: CliStream;
|
|
21
|
+
updateCheck?: false | CliUpdateCheckRuntimeOptions;
|
|
12
22
|
}
|
|
13
23
|
/**
|
|
14
24
|
* Runs the top-level CLI command dispatcher and returns a process-style exit code.
|
|
@@ -29,9 +39,9 @@ export interface CliRuntimeOptions {
|
|
|
29
39
|
* ```
|
|
30
40
|
*
|
|
31
41
|
* @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
|
|
42
|
+
* @param runtime Optional runtime overrides shared by the top-level dispatcher and delegated commands.
|
|
33
43
|
* @returns `0` when the command completes successfully, otherwise `1` after writing the error message to `stderr`.
|
|
34
44
|
*/
|
|
35
|
-
export declare function runCli(argv?: string[], runtime?: CliRuntimeOptions & NewCommandRuntimeOptions): Promise<number>;
|
|
45
|
+
export declare function runCli(argv?: string[], runtime?: CliRuntimeOptions & NewCommandRuntimeOptions & InspectCommandRuntimeOptions): Promise<number>;
|
|
36
46
|
export {};
|
|
37
47
|
//# sourceMappingURL=cli.d.ts.map
|
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":"AAKA,OAAO,EAAE,KAAK,4BAA4B,EAAmC,MAAM,uBAAuB,CAAC;AAE3G,OAAO,EAAE,KAAK,wBAAwB,EAA2B,MAAM,mBAAmB,CAAC;AAI3F,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,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;AAkRD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE,iBAAiB,GAAG,wBAAwB,GAAG,4BAAiC,GACxF,OAAO,CAAC,MAAM,CAAC,CA2HjB"}
|
package/dist/cli.js
CHANGED
|
@@ -5,8 +5,9 @@ import { runGenerateCommand } from './commands/generate.js';
|
|
|
5
5
|
import { inspectUsage, runInspectCommand } from './commands/inspect.js';
|
|
6
6
|
import { migrateUsage, runMigrateCommand } from './commands/migrate.js';
|
|
7
7
|
import { newUsage, runNewCommand } from './commands/new.js';
|
|
8
|
-
import { generatorManifest, resolveGeneratorKind } from './generators/manifest.js';
|
|
8
|
+
import { builtInGeneratorCollection, generatorManifest, generatorOptionSchemas, resolveGeneratorKind } from './generators/manifest.js';
|
|
9
9
|
import { renderAliasList, renderHelpTable } from './help.js';
|
|
10
|
+
import { removeUpdateCheckFlags, runCliUpdateCheck } from './update-check.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Runtime dependency overrides for embedding the CLI in tests or higher-level tooling.
|
|
@@ -19,19 +20,11 @@ const GENERATE_KIND_HELP = [...generatorManifest.map(entry => ({
|
|
|
19
20
|
schematic: entry.schematic,
|
|
20
21
|
wiring: entry.wiringBehavior === 'auto-registered' ? 'auto' : 'manual'
|
|
21
22
|
}))];
|
|
22
|
-
const GENERATE_OPTION_HELP = [{
|
|
23
|
-
aliases: [
|
|
24
|
-
description:
|
|
25
|
-
option:
|
|
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
|
-
}];
|
|
23
|
+
const GENERATE_OPTION_HELP = [...generatorOptionSchemas.map(option => ({
|
|
24
|
+
aliases: [...option.aliases],
|
|
25
|
+
description: option.description,
|
|
26
|
+
option: option.name
|
|
27
|
+
}))];
|
|
35
28
|
const TOP_LEVEL_COMMAND_HELP = [{
|
|
36
29
|
aliases: ['create'],
|
|
37
30
|
command: 'new',
|
|
@@ -60,7 +53,7 @@ function isHelpFlag(value) {
|
|
|
60
53
|
return value === '--help' || value === '-h';
|
|
61
54
|
}
|
|
62
55
|
function generateUsage() {
|
|
63
|
-
return ['Usage: fluo generate|g <kind> <name> [options]', '', 'Schematics', renderHelpTable(GENERATE_KIND_HELP, [{
|
|
56
|
+
return ['Usage: fluo generate|g <kind> <name> [options]', ' fluo generate|g request-dto|req <feature> <name> [options]', '', 'Schematics', renderHelpTable(GENERATE_KIND_HELP, [{
|
|
64
57
|
header: 'Schematic',
|
|
65
58
|
render: entry => entry.schematic
|
|
66
59
|
}, {
|
|
@@ -72,7 +65,7 @@ function generateUsage() {
|
|
|
72
65
|
}, {
|
|
73
66
|
header: 'Description',
|
|
74
67
|
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, [{
|
|
68
|
+
}]), '', ' 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', '', 'Collections', ` ${builtInGeneratorCollection.id} (${builtInGeneratorCollection.source})`, ' External or app-local generator collections are intentionally deferred; no packages or config files are loaded by generate.', '', 'Options', renderHelpTable(GENERATE_OPTION_HELP, [{
|
|
76
69
|
header: 'Option',
|
|
77
70
|
render: entry => entry.option
|
|
78
71
|
}, {
|
|
@@ -93,7 +86,7 @@ function usage() {
|
|
|
93
86
|
}, {
|
|
94
87
|
header: 'Description',
|
|
95
88
|
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');
|
|
89
|
+
}]), '', 'Options', ' --no-update-check Skip the interactive CLI update check for this invocation.', ' Alias: --no-update-notifier.', '', "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
90
|
}
|
|
98
91
|
function resolveDefaultTargetDirectory(startDirectory) {
|
|
99
92
|
const resolvedStartDirectory = resolve(startDirectory);
|
|
@@ -114,24 +107,33 @@ function resolveDefaultTargetDirectory(startDirectory) {
|
|
|
114
107
|
return resolvedStartDirectory;
|
|
115
108
|
}
|
|
116
109
|
function parseGenerateArgs(argv) {
|
|
117
|
-
const [command, rawKind,
|
|
110
|
+
const [command, rawKind, firstName, ...optionArgs] = argv;
|
|
118
111
|
const kind = normalizeGeneratorKind(rawKind);
|
|
119
112
|
if (!(command === 'g' || command === 'generate')) {
|
|
120
113
|
throw new Error(usage());
|
|
121
114
|
}
|
|
122
|
-
if (!kind || !
|
|
115
|
+
if (!kind || !firstName) {
|
|
123
116
|
throw new Error(generateUsage());
|
|
124
117
|
}
|
|
125
|
-
if (
|
|
126
|
-
throw new Error(`Invalid resource name "${
|
|
118
|
+
if (firstName.startsWith('-')) {
|
|
119
|
+
throw new Error(`Invalid resource name "${firstName}": names cannot start with "-".`);
|
|
127
120
|
}
|
|
128
121
|
const parsedOptions = {};
|
|
122
|
+
let name = firstName;
|
|
123
|
+
let seenRequestDtoName = false;
|
|
129
124
|
let targetDirectory;
|
|
130
125
|
let seenForce = false;
|
|
126
|
+
let seenDryRun = false;
|
|
131
127
|
let seenTargetDirectory = false;
|
|
132
128
|
for (let index = 0; index < optionArgs.length; index += 1) {
|
|
133
129
|
const option = optionArgs[index];
|
|
134
130
|
const next = optionArgs[index + 1];
|
|
131
|
+
if (kind === 'request-dto' && !seenRequestDtoName && !option.startsWith('-')) {
|
|
132
|
+
parsedOptions.targetFeature = firstName;
|
|
133
|
+
name = option;
|
|
134
|
+
seenRequestDtoName = true;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
135
137
|
if (option === '--target-directory' || option === '-o') {
|
|
136
138
|
if (seenTargetDirectory) {
|
|
137
139
|
throw new Error('Duplicate --target-directory option.');
|
|
@@ -152,6 +154,14 @@ function parseGenerateArgs(argv) {
|
|
|
152
154
|
seenForce = true;
|
|
153
155
|
continue;
|
|
154
156
|
}
|
|
157
|
+
if (option === '--dry-run') {
|
|
158
|
+
if (seenDryRun) {
|
|
159
|
+
throw new Error('Duplicate --dry-run option.');
|
|
160
|
+
}
|
|
161
|
+
parsedOptions.dryRun = true;
|
|
162
|
+
seenDryRun = true;
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
155
165
|
throw new Error(`Unknown option: ${option}`);
|
|
156
166
|
}
|
|
157
167
|
return {
|
|
@@ -207,19 +217,36 @@ function parseCommand(argv) {
|
|
|
207
217
|
* ```
|
|
208
218
|
*
|
|
209
219
|
* @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
|
|
220
|
+
* @param runtime Optional runtime overrides shared by the top-level dispatcher and delegated commands.
|
|
211
221
|
* @returns `0` when the command completes successfully, otherwise `1` after writing the error message to `stderr`.
|
|
212
222
|
*/
|
|
213
223
|
export async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
214
224
|
const cwd = runtime.cwd ? resolve(runtime.cwd) : process.cwd();
|
|
215
225
|
const stdout = runtime.stdout ?? process.stdout;
|
|
216
226
|
const stderr = runtime.stderr ?? process.stderr;
|
|
227
|
+
const env = runtime.env ?? process.env;
|
|
228
|
+
const updateFlagResult = removeUpdateCheckFlags(argv);
|
|
229
|
+
const commandArgv = updateFlagResult.argv;
|
|
217
230
|
try {
|
|
218
|
-
|
|
231
|
+
const updateCheckOptions = runtime.updateCheck === false ? undefined : runtime.updateCheck;
|
|
232
|
+
const updateCheckResult = await runCliUpdateCheck(commandArgv, {
|
|
233
|
+
...updateCheckOptions,
|
|
234
|
+
ci: runtime.ci,
|
|
235
|
+
env,
|
|
236
|
+
interactive: runtime.interactive,
|
|
237
|
+
skip: updateFlagResult.skipUpdateCheck || runtime.updateCheck === false,
|
|
238
|
+
stderr,
|
|
239
|
+
stdin: runtime.stdin,
|
|
240
|
+
stdout
|
|
241
|
+
});
|
|
242
|
+
if (updateCheckResult.action === 'reran') {
|
|
243
|
+
return updateCheckResult.exitCode;
|
|
244
|
+
}
|
|
245
|
+
if (commandArgv.length === 0) {
|
|
219
246
|
throw new Error(usage());
|
|
220
247
|
}
|
|
221
|
-
if (
|
|
222
|
-
const topic =
|
|
248
|
+
if (commandArgv[0] === 'help') {
|
|
249
|
+
const topic = commandArgv[1];
|
|
223
250
|
if (topic === 'new' || topic === 'create') {
|
|
224
251
|
stdout.write(`${newUsage()}\n`);
|
|
225
252
|
return 0;
|
|
@@ -239,23 +266,23 @@ export async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
239
266
|
stdout.write(`${usage()}\n`);
|
|
240
267
|
return 0;
|
|
241
268
|
}
|
|
242
|
-
if (isHelpFlag(
|
|
269
|
+
if (isHelpFlag(commandArgv[0])) {
|
|
243
270
|
stdout.write(`${usage()}\n`);
|
|
244
271
|
return 0;
|
|
245
272
|
}
|
|
246
|
-
if ((
|
|
273
|
+
if ((commandArgv[0] === 'g' || commandArgv[0] === 'generate') && commandArgv.slice(1).some(isHelpFlag)) {
|
|
247
274
|
stdout.write(`${generateUsage()}\n`);
|
|
248
275
|
return 0;
|
|
249
276
|
}
|
|
250
|
-
if (
|
|
277
|
+
if (commandArgv[0] === 'migrate' && commandArgv.slice(1).some(isHelpFlag)) {
|
|
251
278
|
stdout.write(`${migrateUsage()}\n`);
|
|
252
279
|
return 0;
|
|
253
280
|
}
|
|
254
|
-
if (
|
|
281
|
+
if (commandArgv[0] === 'inspect' && commandArgv.slice(1).some(isHelpFlag)) {
|
|
255
282
|
stdout.write(`${inspectUsage()}\n`);
|
|
256
283
|
return 0;
|
|
257
284
|
}
|
|
258
|
-
const parsedCommand = parseCommand(
|
|
285
|
+
const parsedCommand = parseCommand(commandArgv);
|
|
259
286
|
if (parsedCommand.command === 'new') {
|
|
260
287
|
return runNewCommand(parsedCommand.argv, runtime);
|
|
261
288
|
}
|
|
@@ -267,9 +294,17 @@ export async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
267
294
|
}
|
|
268
295
|
const targetDirectory = resolve(cwd, parsedCommand.parsed.targetDirectory ?? resolveDefaultTargetDirectory(cwd));
|
|
269
296
|
const result = runGenerateCommand(parsedCommand.parsed.kind, parsedCommand.parsed.name, targetDirectory, parsedCommand.parsed.options);
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
stdout.write(`
|
|
297
|
+
if (parsedCommand.parsed.options.dryRun) {
|
|
298
|
+
stdout.write('Dry run: no files were written.\n');
|
|
299
|
+
stdout.write(`Planned ${result.plannedFiles.length} file action(s):\n`);
|
|
300
|
+
for (const file of result.plannedFiles) {
|
|
301
|
+
stdout.write(` ${file.action.toUpperCase()} ${file.path}\n`);
|
|
302
|
+
}
|
|
303
|
+
} else {
|
|
304
|
+
stdout.write(`Generated ${result.generatedFiles.length} file(s):\n`);
|
|
305
|
+
for (const file of result.generatedFiles) {
|
|
306
|
+
stdout.write(` CREATE ${file}\n`);
|
|
307
|
+
}
|
|
273
308
|
}
|
|
274
309
|
stdout.write('\n');
|
|
275
310
|
if (result.wiringBehavior === 'auto-registered' && result.moduleRegistered) {
|
|
@@ -287,6 +322,7 @@ export async function runCli(argv = process.argv.slice(2), runtime = {}) {
|
|
|
287
322
|
}
|
|
288
323
|
if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
|
|
289
324
|
process.exitCode = await runCli(undefined, {
|
|
325
|
+
ci: process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true',
|
|
290
326
|
userAgent: process.env.npm_config_user_agent
|
|
291
327
|
});
|
|
292
328
|
}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { GenerateOptions, GeneratorKind } from '../types.js';
|
|
2
2
|
import type { GeneratorManifestEntry } from '../generators/manifest.js';
|
|
3
|
+
/** Describes how one generated artifact would interact with the workspace. */
|
|
4
|
+
export type GeneratePlanAction = 'create' | 'module-create' | 'module-unchanged' | 'module-update' | 'overwrite' | 'skip' | 'unchanged';
|
|
5
|
+
/** One path-level action reported by generate dry-run previews and structured results. */
|
|
6
|
+
export type GeneratePlanEntry = {
|
|
7
|
+
/** Planned action for this path. */
|
|
8
|
+
action: GeneratePlanAction;
|
|
9
|
+
/** Absolute path affected by the plan entry. */
|
|
10
|
+
path: string;
|
|
11
|
+
};
|
|
3
12
|
/**
|
|
4
13
|
* Structured result returned by {@link runGenerateCommand} for tooling-friendly automation.
|
|
5
14
|
*
|
|
@@ -12,6 +21,7 @@ export type GenerateResult = {
|
|
|
12
21
|
moduleRegistered: boolean;
|
|
13
22
|
modulePath: string | undefined;
|
|
14
23
|
nextStepHint: string;
|
|
24
|
+
plannedFiles: GeneratePlanEntry[];
|
|
15
25
|
wiringBehavior: GeneratorManifestEntry['wiringBehavior'];
|
|
16
26
|
};
|
|
17
27
|
/**
|
|
@@ -32,7 +42,7 @@ export type GenerateResult = {
|
|
|
32
42
|
* @param kind Generator kind to execute.
|
|
33
43
|
* @param name Resource name supplied by the caller before normalization.
|
|
34
44
|
* @param baseDirectory Source directory that should receive the generated domain folder.
|
|
35
|
-
* @param options Optional generation flags that control overwrites and sibling-aware templates.
|
|
45
|
+
* @param options Optional generation flags that control overwrites, request DTO feature placement, and sibling-aware templates.
|
|
36
46
|
* @returns Structured file and wiring metadata for the completed generation run.
|
|
37
47
|
* @throws {Error} When the resource name is invalid, the generator kind is unknown, or the target module source cannot be updated safely.
|
|
38
48
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,sBAAsB,EAAkB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,sBAAsB,EAAkB,MAAM,2BAA2B,CAAC;AAexF,8EAA8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,eAAe,GAAG,kBAAkB,GAAG,eAAe,GAAG,WAAW,GAAG,MAAM,GAAG,WAAW,CAAC;AAExI,0FAA0F;AAC1F,MAAM,MAAM,iBAAiB,GAAG;IAC9B,oCAAoC;IACpC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AA0HF;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,cAAc,EAAE,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;CAC1D,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,cAAc,CAgE1I"}
|