@tdk-landscape/tdk-cli-core 1.3.79 → 1.3.80
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/CHANGELOG.md +6 -0
- package/README.md +27 -213
- package/cli/dist/commands/config.js +34 -6
- package/cli/dist/commands/doctor.js +57 -23
- package/cli/dist/commands/help.js +3 -2
- package/cli/dist/commands/networks.js +121 -101
- package/cli/dist/commands/resource.js +4 -1
- package/cli/dist/commands/resources.js +40 -9
- package/cli/dist/commands/status.js +65 -7
- package/cli/dist/generator/template-engine.js +27 -15
- package/cli/dist/utils/doctor-report.js +40 -0
- package/cli/dist/utils/host-port-plan.js +62 -0
- package/cli/dist/utils/machine-output.js +24 -0
- package/cli/dist/utils/service-manifest.js +1 -0
- package/cli/package.json +1 -1
- package/engine/schemas/project-schema.json +142 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ Notable changes to the `tdk` CLI. Versions match [npm](https://www.npmjs.com/pac
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
- Add `tdk doctor --json` with schema-versioned readiness, checks, and structured errors; diagnostics remain on stderr.
|
|
8
|
+
- Stabilize doctor exits: 0 ready, 1 blocking findings, 2 invalid arguments/internal check failures. Invalid `--ping-timeout` now exits 2 instead of 1 and rejects fractional/unit-suffixed values.
|
|
9
|
+
- Add versioned `--json` envelopes to `tdk status`, `tdk resources`, and `tdk networks`; existing `networks --json` array consumers can migrate with `--json-legacy` through CLI 1.4.x. The compatibility flag is scheduled for removal in 1.5.0.
|
|
10
|
+
- Add `tdk config verify --json` with drift summaries and unified diffs for missing or stale master outputs; verification remains read-only, and structured command/internal failures use exits 1/2.
|
|
11
|
+
|
|
12
|
+
|
|
7
13
|
## 1.3.77 (2026-09-30)
|
|
8
14
|
|
|
9
15
|
- `tdk up` no longer leaves `nats` (and any other service in `services/platform/messaging/docker-compose.yml`, e.g. a local mail catcher) disabled in Tilt. The pre-alpha default always goes through a focus-filter path that only re-enabled `init-networks`/`postgres`/`traefik`/`golden-layers-build`, so a resource with the `nats` feature retried its broker connection forever until you ran `tilt enable nats` by hand. Fixes #155.
|
package/README.md
CHANGED
|
@@ -1,27 +1,6 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
1
|
# TDK — Tilt Development Kit
|
|
4
2
|
|
|
5
|
-
TDK
|
|
6
|
-
laptop with Docker and Tilt (hot reload, health, Traefik, Postgres).
|
|
7
|
-
|
|
8
|
-
It is not a Kubernetes packager. It does not replace Helm, Argo CD,
|
|
9
|
-
Kustomize, or your production charts.
|
|
10
|
-
|
|
11
|
-
Use TDK when local bring-up of many services is painful and you do not want a
|
|
12
|
-
cluster on the laptop.
|
|
13
|
-
|
|
14
|
-
Skip TDK if `helm install` (or your existing compose/Tilt/Skaffold) already
|
|
15
|
-
gives you a working local or shared-dev environment.
|
|
16
|
-
|
|
17
|
-
## Status
|
|
18
|
-
|
|
19
|
-
Supported: macOS, Linux, Windows via WSL2 Ubuntu.
|
|
20
|
-
Native Windows: CLI inspect only; `tdk up` unsupported.
|
|
21
|
-
WSL2 smoke: local script only (no GitHub WSL runner).
|
|
22
|
-
Stability: 1.x — generated files are a contract; verify in CI.
|
|
23
|
-
Check your machine: `tdk doctor`
|
|
24
|
-
Known limits: [docs/compare-honest.md](docs/compare-honest.md)
|
|
3
|
+
TDK runs many services on your laptop with Docker + Tilt. Helm still deploys the cluster.
|
|
25
4
|
|
|
26
5
|
[](https://www.npmjs.com/package/@tdk-landscape/tdk-cli-core)
|
|
27
6
|
[](https://github.com/tdk-landscape/tdk-cli-core/actions/workflows/ci.yml)
|
|
@@ -32,216 +11,51 @@ Known limits: [docs/compare-honest.md](docs/compare-honest.md)
|
|
|
32
11
|
[](https://socket.dev/npm/package/@tdk-landscape/tdk-cli-core/overview)
|
|
33
12
|
[](LICENSE)
|
|
34
13
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
</div>
|
|
38
|
-
|
|
39
|
-
## When not to use TDK
|
|
40
|
-
|
|
41
|
-
- Production or shared-cluster deploy is Helm/Argo/Kustomize — keep it.
|
|
42
|
-
- Your local or namespace-per-dev environment already works.
|
|
43
|
-
- You will not adopt `service.json` and generated files.
|
|
14
|
+
## Installation
|
|
44
15
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
- You have many services and want `tdk up <one stack>` on Docker.
|
|
48
|
-
- You do not want kind or minikube as your daily path.
|
|
49
|
-
- You want to generate services, run `tdk config verify`, and use Traefik `*.localhost` routes.
|
|
50
|
-
|
|
51
|
-
Start with the [bundled product example](examples/tdk-example/README.md); its write path is covered by [example-e2e](.github/workflows/example-e2e.yml).
|
|
16
|
+
Install the CLI from npm (requires Node.js 22.12+) or use the prebuilt binary (no Node.js or Bun required):
|
|
52
17
|
|
|
53
18
|
```bash
|
|
54
19
|
npm install -g @tdk-landscape/tdk-cli-core
|
|
55
|
-
|
|
56
|
-
mkdir shop && cd shop # tdk writes files into the current directory
|
|
57
|
-
tdk project --yes # set up the project
|
|
58
|
-
tdk resource orders-api --type backend --stack shop # scaffold a service
|
|
59
|
-
tdk up shop # run it with hot reload
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-

|
|
63
|
-
|
|
64
|
-
Want to inspect a stack before starting containers? `tdk up shop --dry-run` shows the services and local URLs without Docker or Tilt installed.
|
|
65
|
-
|
|
66
|
-

|
|
67
|
-
|
|
68
|
-
**Requirements:** Docker (Desktop, OrbStack or Colima; Engine 25+, Compose 2.20+), [Tilt](https://docs.tilt.dev/install.html), [Bun](https://bun.sh) for the generated services, and Node.js 22.12+ for npm installs. Ports 80, 443 and 5432 must be free (a local Postgres is the usual conflict). macOS and Linux releases are available. Windows native is unsupported. WSL2 Ubuntu is supported. See docs/wsl2.md. Run `tdk doctor` to check your setup.
|
|
69
|
-
|
|
70
|
-
This is the core monorepo for TDK: the `tdk` CLI, the Starlark-based Tilt orchestration engine that powers it, and the discovery system that turns a directory of services into a running local landscape.
|
|
71
|
-
|
|
72
|
-
## Why TDK?
|
|
73
|
-
|
|
74
|
-
| | docker-compose | Local Kubernetes (kind, minikube) | Plain Tilt | **TDK** |
|
|
75
|
-
|---|---|---|---|---|
|
|
76
|
-
| Scaffold a new service in one command | ❌ | ❌ | ❌ | ✅ `tdk resource` |
|
|
77
|
-
| Hot reload on file change | ⚠️ `compose watch` config | ⚠️ extra tooling | ✅ | ✅ |
|
|
78
|
-
| Health-checked startup order | ✅ `depends_on: condition: service_healthy` | ✅ | ⚠️ write it yourself | ✅ |
|
|
79
|
-
| Proxy, Postgres, monitoring included | ❌ | ❌ | ❌ | ✅ |
|
|
80
|
-
| Needs a cluster | No | Yes | Optional | **No** |
|
|
81
|
-
| Start only one stack of a large system | ⚠️ profiles | ⚠️ | ⚠️ | ✅ `tdk up <stack>` |
|
|
82
|
-
|
|
83
|
-
TDK is not a replacement for Tilt: it generates the Tiltfile, Dockerfiles and compose files and then runs Tilt. If you already have a hand-written Tiltfile or compose setup you're happy with, TDK mostly saves you the boilerplate for the next service.
|
|
84
|
-
|
|
85
|
-
## Fixture bench: 100 generated services on one laptop
|
|
86
|
-
|
|
87
|
-
Measured with [`scripts/benchmark/container-scale.ts`](scripts/benchmark/README.md) against the 100-service [`tdk-erp-system` fixture bench](https://github.com/tdk-landscape/tdk-erp-system), a scale fixture of generated `/health` services rather than an ERP product, on a 16 GB machine (Docker VM: 7.75 GiB). Raw results are in [`benchmarks/results/`](benchmarks/results).
|
|
88
|
-
|
|
89
|
-
| Services | All healthy after | Total memory | Avg memory / service | Crashes / OOM kills |
|
|
90
|
-
|---:|---:|---:|---:|---:|
|
|
91
|
-
| 10 | 8 s | 161 MiB | 16 MiB | 0 / 0 |
|
|
92
|
-
| 50 | 24 s | 829 MiB | 17 MiB | 0 / 0 |
|
|
93
|
-
| 100 | 112 s | 1.6 GiB | 17 MiB | 0 / 0 |
|
|
94
|
-
|
|
95
|
-
What this does and doesn't measure:
|
|
96
|
-
|
|
97
|
-
- The ERP services are small generated Bun HTTP services (about 20 lines each) answering `/health`. Real services with real dependencies use more memory; the point is that TDK's per-service overhead (runtime image, healthchecks, proxy routing) stays small.
|
|
98
|
-
- Images were already built, so build time isn't included. The clean-machine run below includes it.
|
|
99
|
-
- The script starts the service containers with the settings `tdk up` generates (512 MiB / 0.5 CPU limits, healthchecks), without Tilt running. The memory column counts only the service containers, not Postgres or Traefik.
|
|
100
|
-
- Numbers vary between runs (a later run reached 100 healthy in 74 s). Run it yourself with `bun scripts/benchmark/container-scale.ts`.
|
|
101
|
-
|
|
102
|
-
### Cold boot on a clean machine (CI)
|
|
103
|
-
|
|
104
|
-
The table above is a warm start. Two workflows install the published CLI on a fresh GitHub-hosted Ubuntu runner and run `tdk up` from nothing, building every image:
|
|
105
|
-
|
|
106
|
-
- [**Quickstart E2E**](.github/workflows/quickstart-e2e.yml): the commands from the top of this README, one scaffolded backend, until it answers `/health` through Traefik. About 4 minutes. Runs after each release and daily.
|
|
107
|
-
- [**ERP fixture scale E2E**](.github/workflows/erp-scale-e2e.yml): the 100-service generated-health fixture bench. [Run 36395860088](https://github.com/tdk-landscape/tdk-cli-core/actions/runs/36395860088) (CLI 1.3.72, 4 vCPU / 15 GB): **100 / 100 backends healthy through Traefik after 472 s**, 111 containers, 1.8 GiB used by all containers. Runs weekly.
|
|
108
|
-
|
|
109
|
-
Both are Linux/Ubuntu CI fixtures: generated services answering `/health`, not a real business app. A green run means TDK can generate, build, route and health-check a landscape of that size on a clean Ubuntu runner. Windows now has a separate smoke workflow for CLI startup and unit tests, but it does not boot a full landscape on Windows. These CI runs also don't cover Apple Silicon or an existing repo you bring yourself.
|
|
110
|
-
|
|
111
|
-
## What is TDK?
|
|
112
|
-
|
|
113
|
-
TDK organizes microservices using a **Project → Stack → Resource** hierarchy, then uses Tilt to build, run, and hot-reload them locally:
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
Project (1 per repo)
|
|
117
|
-
├── TILT_RESOURCE_DEFAULTS.star # Ports, health checks, memory
|
|
118
|
-
├── TILT_TECH_STACK.star # Bun, Vite, Prisma, NATS
|
|
119
|
-
│
|
|
120
|
-
└── Stacks (deployment groups)
|
|
121
|
-
├── api-stack
|
|
122
|
-
│ ├── api-backend # Resource
|
|
123
|
-
│ └── web-frontend # Resource
|
|
124
|
-
│
|
|
125
|
-
└── worker-stack
|
|
126
|
-
├── worker-backend
|
|
127
|
-
└── web-frontend
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
`.tdk/project.json` also groups stacks into phases (`pre_alpha`, `alpha`, `beta`, `out_of_scope`) so a large system can be brought up in stages. `tdk up` runs stacks from the first three and adds any new stack to `pre_alpha`.
|
|
131
|
-
|
|
132
|
-
Running `tdk resource` scaffolds a service (Dockerfile, TypeScript config, starter code, tests); `tdk up` hands the whole landscape to Tilt for orchestration, live-reload, and health checking — sized to fit dozens of services on a single laptop.
|
|
133
|
-
|
|
134
|
-
## Install
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
npm install -g @tdk-landscape/tdk-cli-core
|
|
138
|
-
# or
|
|
139
|
-
bun install -g @tdk-landscape/tdk-cli-core
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Or install the prebuilt binary (no Node or Bun needed; verified against the release checksums):
|
|
143
|
-
|
|
144
|
-
```bash
|
|
20
|
+
# or install the prebuilt binary
|
|
145
21
|
curl -fsSL https://tdk-landscape.github.io/install.sh | sh
|
|
146
22
|
```
|
|
147
23
|
|
|
148
|
-
Premium features don't need a different install: set `TDK_LICENSE_KEY` and any of these installs unlocks them. See [docs/FEATURES.md](docs/FEATURES.md).
|
|
149
|
-
|
|
150
24
|
## Quick start
|
|
151
25
|
|
|
152
26
|
```bash
|
|
153
27
|
mkdir shop && cd shop
|
|
154
|
-
tdk project --yes
|
|
155
|
-
tdk resource orders-api --type backend --stack shop
|
|
156
|
-
tdk
|
|
157
|
-
tdk
|
|
158
|
-
tdk networks # lists the *.localhost URLs Traefik routes
|
|
159
|
-
tdk down # stops everything
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
See the [CLI reference](cli/README.md) for the full command set (`stack`, `resources`, `doctor`, `ui`, and more).
|
|
163
|
-
|
|
164
|
-
## Repository layout
|
|
165
|
-
|
|
166
|
-
This is a monorepo — most day-to-day CLI work happens under `cli/`, while `engine/` and `discovery/` implement the Tilt-side orchestration that the CLI drives.
|
|
167
|
-
|
|
168
|
-
| Path | What it is |
|
|
169
|
-
|------|------------|
|
|
170
|
-
| [`cli/`](cli) | The `tdk` CLI source (TypeScript/Bun) — commands, UI, templates. See [cli/README.md](cli/README.md). |
|
|
171
|
-
| [`engine/`](engine) | The Starlark Tilt framework: topology modules for Docker, networking, database virtualization, secrets, observability. See [engine/README.md](engine/README.md). |
|
|
172
|
-
| [`discovery/`](discovery) | Manifest-driven service discovery — scans `service.json` files and builds the resource/dependency graph consumed by the engine. |
|
|
173
|
-
| [`ext/`](ext) | Tilt extension (`ext://tdk-cli`) plus IDE/UI enhancement components. |
|
|
174
|
-
| [`scripts/`](scripts) | Release, benchmarking, and dev-environment scripts (git hooks, pre-commit, idle-footprint measurement). |
|
|
175
|
-
| [`benchmarks/`](benchmarks) | Container/landscape scale benchmarks. |
|
|
176
|
-
| [`docs/`](docs) | Reference docs, including [FEATURES.md](docs/FEATURES.md) for project- and resource-level feature flags. |
|
|
177
|
-
| [`Tiltfile`](Tiltfile) | Entry point that wires the engine into `tilt up`. |
|
|
178
|
-
| [`install.sh`](install.sh) | Legacy installer URL; hands off to the official installer at `tdk-landscape.github.io/install.sh`. |
|
|
179
|
-
|
|
180
|
-
## Features
|
|
181
|
-
|
|
182
|
-
TDK ships a set of always-on infrastructure services (Traefik proxy, PostgreSQL) plus opt-in features — monitoring, ELK, Debezium CDC, a local npm registry, and more. Enable/disable them per-project via `.tdk/project.json`, or per-resource via each service's `service.json`. Full reference: [docs/FEATURES.md](docs/FEATURES.md).
|
|
183
|
-
|
|
184
|
-
## Free and paid features
|
|
185
|
-
|
|
186
|
-
The CLI, engine and everything in this repository are MIT-licensed and work without an account or key. A few extras are paid and need a `TDK_LICENSE_KEY`: on-demand start/stop of idle services (Sablier), a local npm registry (Verdaccio), DDD scaffolding, Playwright config, C4 diagrams, synthetic monitoring, and a few generators (see `KNOWN_RESOURCES` in [extension-fetch.ts](cli/src/generator/extension-fetch.ts)). In this repo those are disabled stubs; with a key set, the CLI downloads the real implementations. [docs/FEATURES.md](docs/FEATURES.md) marks which features are which. To get a key, use the [request form on the website](https://tdk-landscape.github.io/tdk-website/#waitlist) or open a [Premium license request](https://github.com/tdk-landscape/tdk-cli-core/issues/new?template=premium_license.yml).
|
|
187
|
-
|
|
188
|
-
## Network access and telemetry
|
|
189
|
-
|
|
190
|
-
TDK has no telemetry or analytics. The CLI only goes online when you ask it to:
|
|
191
|
-
|
|
192
|
-
- `tdk upgrade` checks the latest release on GitHub.
|
|
193
|
-
- With `TDK_LICENSE_KEY` set, `tdk project` and `tdk up` download the paid bundle from `tdk-extension-dist.oranguman.workers.dev` and re-check the key every 12 hours. Without a key, nothing is sent.
|
|
194
|
-
- Docker and Tilt pull images and packages as they normally would.
|
|
195
|
-
- Tilt, which TDK runs, has its own anonymous usage analytics. Turn them off with `tilt analytics opt out`.
|
|
196
|
-
|
|
197
|
-
## FAQ
|
|
198
|
-
|
|
199
|
-
**Why not just docker compose?** For a handful of services, compose is fine. TDK generates the compose files for you. It adds hot reload through Tilt, one-command scaffolding with matching Dockerfiles, and a stack-level `tdk up` for large systems where starting everything is too slow.
|
|
200
|
-
|
|
201
|
-
**How is this different from Skaffold, Garden, DevSpace or Tilt itself?** Skaffold, Garden and DevSpace are built around Kubernetes, and plain Tilt leaves the Tiltfile to you. TDK runs on plain Docker with no cluster, and generates both the services and the Tilt config from a `service.json` per service.
|
|
202
|
-
|
|
203
|
-
See the [honest comparison](docs/compare-honest.md) for tradeoffs and cases where TDK may not fit.
|
|
204
|
-
|
|
205
|
-
**Do I need 100 microservices?** No. Two services work the same way. The 100-service fixture bench is a stress test to show the overhead stays flat; it is not an ERP product example.
|
|
206
|
-
|
|
207
|
-
**Is TDK affiliated with Tilt or Docker?** No. TDK is an independent project built on top of [Tilt](https://tilt.dev), which is maintained by Docker, Inc.
|
|
208
|
-
|
|
209
|
-
## Development
|
|
210
|
-
|
|
211
|
-
```bash
|
|
212
|
-
make help # list all make targets
|
|
213
|
-
make test # run the full test suite
|
|
214
|
-
make test-fast # fast unit tests, no external deps
|
|
215
|
-
make pre-commit-run # run pre-commit hooks on all files
|
|
28
|
+
tdk project --yes
|
|
29
|
+
tdk resource orders-api --type backend --stack shop --yes
|
|
30
|
+
tdk up shop
|
|
31
|
+
tdk networks
|
|
216
32
|
```
|
|
217
33
|
|
|
218
|
-
`
|
|
34
|
+
`tdk up shop --dry-run` previews selected local services and URLs before starting containers. The default starter is Bun/TypeScript; TDK's core role is running local containers through Docker + Tilt, not providing a Node.js application framework. See the [one-backend example](examples/one-backend/README.md).
|
|
219
35
|
|
|
220
|
-
##
|
|
36
|
+
## When not to use TDK
|
|
221
37
|
|
|
222
|
-
|
|
38
|
+
- Your existing Compose or Tilt workflow already gives you a working local environment.
|
|
39
|
+
- You do not want `service.json` manifests and generated local configuration.
|
|
223
40
|
|
|
224
|
-
|
|
225
|
-
npx @tdk-landscape/tdk-cli-core
|
|
226
|
-
npx @tdk-landscape/tdk-cli-core doctor
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
Ranked first failures: Node 22.12+, Docker Engine 25+, Compose 2.20.2+, Tilt 0.25+, Bun 1.2+, and ports 80/443/5432.
|
|
230
|
-
Install Bun 1.2+ as a machine prerequisite. `tdk project` generates the stack configuration; Prisma and NATS are project-specific, and NATS is required only when the feature is enabled.
|
|
41
|
+
## Docs
|
|
231
42
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
43
|
+
- [Documentation index](docs/README.md)
|
|
44
|
+
- [Working alongside Helm](docs/with-helm.md)
|
|
45
|
+
- [Configuration and editor schemas](docs/configuration.md)
|
|
46
|
+
- [Runnable one-backend example](examples/one-backend/README.md)
|
|
47
|
+
- [Full multi-service example](examples/tdk-example/README.md)
|
|
48
|
+
- [Features and license limits](docs/FEATURES.md)
|
|
49
|
+
- [Honest comparison and known limits](docs/compare-honest.md)
|
|
50
|
+
- [Architecture and repository map](docs/project-overview.md)
|
|
51
|
+
- [Scale fixture measurements and caveats](docs/scale-bench.md)
|
|
235
52
|
|
|
236
|
-
|
|
53
|
+
## Requirements and support
|
|
237
54
|
|
|
238
|
-
|
|
55
|
+
For the local runtime, install Docker (Desktop, OrbStack, or Colima; Engine 25+, Compose 2.20+) and [Tilt](https://docs.tilt.dev/install.html). Bun 1.2+ is used by the default generated services. Ports 80, 443, and 5432 must be free. TDK supports macOS, Linux, and Windows through WSL2 Ubuntu; native Windows supports CLI inspection only. Run `tdk doctor` to check local readiness. See [WSL2 setup](docs/wsl2.md).
|
|
239
56
|
|
|
240
|
-
|
|
241
|
-
- **Contributing:** see [CONTRIBUTING.md](CONTRIBUTING.md) and the [step-by-step guide](docs/contributing/README.md). Issues labeled [`good first issue`](https://github.com/tdk-landscape/tdk-cli-core/labels/good%20first%20issue) are a good place to start.
|
|
242
|
-
- **Security:** see [SECURITY.md](SECURITY.md). Please don't report vulnerabilities in public issues.
|
|
243
|
-
- **Examples:** bundled [TDK product example](examples/tdk-example), [ERP fixture bench (100 generated services)](https://github.com/tdk-landscape/tdk-erp-system), [SaaS starter](https://github.com/tdk-landscape/tdk-saas-starter), [restaurant](https://github.com/tdk-landscape/tdk-restaurant-example), [ecommerce (Vue + Hono)](https://github.com/tdk-landscape/tdk-ecommerce-example).
|
|
57
|
+
## Contributing and license
|
|
244
58
|
|
|
245
|
-
|
|
59
|
+
Contributions are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md) and the [contributor guide](docs/contributing/README.md). Report security issues using [SECURITY.md](SECURITY.md).
|
|
246
60
|
|
|
247
|
-
|
|
61
|
+
TDK is MIT-licensed; see [LICENSE](LICENSE).
|
|
@@ -8,8 +8,10 @@ import { generateMasterConfigs, readProjectConfig, TemplateEngine, verifyMasterC
|
|
|
8
8
|
import { isMasterConfigFileName } from "../types/index.js";
|
|
9
9
|
import { assertValid } from "../utils/command-helpers.js";
|
|
10
10
|
import { MASTER_CONFIG_FILES } from "../utils/constants.js";
|
|
11
|
-
import { requireProjectRoot, runCommand } from "../utils/errors.js";
|
|
11
|
+
import { errorFactories, requireProjectRoot, runCommand } from "../utils/errors.js";
|
|
12
12
|
import { writeJsonFile } from "../utils/file-helpers.js";
|
|
13
|
+
import { createMachineEnvelope, writeMachineError } from "../utils/machine-output.js";
|
|
14
|
+
import { findProjectRoot } from "../utils/paths.js";
|
|
13
15
|
import { SERVICE_MANIFEST_SCHEMA_VERSION, validateServiceManifest, } from "../utils/service-manifest.js";
|
|
14
16
|
import { discoverServiceManifestPaths } from "../utils/services.js";
|
|
15
17
|
import { validateOptionalInfraService } from "../utils/validation.js";
|
|
@@ -173,11 +175,25 @@ export const configCommand = new Command("config")
|
|
|
173
175
|
}))
|
|
174
176
|
.addCommand(new Command("verify")
|
|
175
177
|
.description("Verify that generated files match .tdk/project.json")
|
|
176
|
-
.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
.option("--json", "Emit a machine-readable verification report")
|
|
179
|
+
.action(async (options) => {
|
|
180
|
+
const action = async () => {
|
|
181
|
+
const projectRoot = options.json ? findProjectRoot() : requireProjectRoot();
|
|
182
|
+
if (!projectRoot)
|
|
183
|
+
throw errorFactories.notInProject();
|
|
180
184
|
const result = verifyMasterConfigs(projectRoot);
|
|
185
|
+
if (options.json) {
|
|
186
|
+
console.log(JSON.stringify(createMachineEnvelope({
|
|
187
|
+
valid: result.valid,
|
|
188
|
+
errors: result.errors,
|
|
189
|
+
warnings: result.warnings,
|
|
190
|
+
diffs: result.diffs,
|
|
191
|
+
})));
|
|
192
|
+
if (!result.valid)
|
|
193
|
+
process.exit(1);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
console.log(chalk.blue("🔍 Verifying configuration...\n"));
|
|
181
197
|
for (const warning of result.warnings) {
|
|
182
198
|
console.warn(chalk.yellow(`⚠️ ${warning}`));
|
|
183
199
|
}
|
|
@@ -190,10 +206,22 @@ export const configCommand = new Command("config")
|
|
|
190
206
|
for (const error of result.errors) {
|
|
191
207
|
console.log(chalk.gray(` - ${error}`));
|
|
192
208
|
}
|
|
209
|
+
for (const { diff } of result.diffs)
|
|
210
|
+
console.log(chalk.gray(`\n${diff}`));
|
|
193
211
|
console.log(chalk.gray("\nRun `tdk config regenerate` to fix."));
|
|
194
212
|
process.exit(1);
|
|
195
213
|
}
|
|
196
|
-
}
|
|
214
|
+
};
|
|
215
|
+
if (options.json) {
|
|
216
|
+
try {
|
|
217
|
+
await action();
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
writeMachineError(error);
|
|
221
|
+
}
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
await runCommand(action);
|
|
197
225
|
}))
|
|
198
226
|
.addCommand(new Command("edit").description("Open .tdk/project.json in your $EDITOR").action(async () => {
|
|
199
227
|
await runCommand(async () => {
|
|
@@ -6,6 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
import { hasVerdaccioLicense } from "../generator/extension-fetch.js";
|
|
7
7
|
import { MASTER_CONFIG_FILES, REQUIRED_PACKAGE_SCRIPTS } from "../utils/constants.js";
|
|
8
8
|
import { isPathDiscovered, readDiscoveryPaths } from "../utils/discovery-paths.js";
|
|
9
|
+
import { collectDoctorChecks, createDoctorReport, getDoctorExitCode, } from "../utils/doctor-report.js";
|
|
9
10
|
import { checkHealthRoutes, checkHostPorts, checkIngressPorts, checkPrivateNpmRegistry, checkTiltResourceHealth, projectConfigEnablesVerdaccio, summarizeServiceProbes, } from "../utils/doctor-runtime.js";
|
|
10
11
|
import { checkDockerNetworkCapacity, checkFrontendBackendUrls, checkNatsBroker, checkResourcePackageJson, checkServiceUrlPorts, checkTiltInstances, } from "../utils/doctor-wiring.js";
|
|
11
12
|
import { validateEnvFile } from "../utils/env-validator.js";
|
|
@@ -66,8 +67,8 @@ export function checkWslProjectLocation(projectPath, strict, isWsl = process.pla
|
|
|
66
67
|
}
|
|
67
68
|
/** Failures are shown before passing statuses, with a 5432 conflict first. */
|
|
68
69
|
export function orderDoctorResults(results) {
|
|
69
|
-
const failures = results.filter((result) => !result.didPass && !result.isSkipped);
|
|
70
|
-
const remaining = results.filter((result) => result.didPass || result.isSkipped);
|
|
70
|
+
const failures = results.filter((result) => !result.didPass && !result.isSkipped && !result.isWarning);
|
|
71
|
+
const remaining = results.filter((result) => result.didPass || result.isSkipped || result.isWarning);
|
|
71
72
|
failures.sort((left, right) => {
|
|
72
73
|
const rank = (result) => result.name === "Host Ports" && /\b5432\b/.test(result.message)
|
|
73
74
|
? 0
|
|
@@ -968,21 +969,52 @@ async function checkServiceHealth(timeoutMs) {
|
|
|
968
969
|
}
|
|
969
970
|
export const doctorCommand = new Command("doctor")
|
|
970
971
|
.description("Check environment readiness for TDK")
|
|
972
|
+
.option("--json", "Output a versioned JSON readiness report", false)
|
|
973
|
+
.exitOverride((error) => {
|
|
974
|
+
if (error.exitCode === 0)
|
|
975
|
+
process.exit(0);
|
|
976
|
+
if (doctorCommand.opts().json) {
|
|
977
|
+
console.log(JSON.stringify(createDoctorReport([], false, [{ code: "USAGE", message: error.message }])));
|
|
978
|
+
}
|
|
979
|
+
process.exit(2);
|
|
980
|
+
})
|
|
971
981
|
.option("--no-ping", "Skip pinging running services' /health endpoints")
|
|
972
982
|
.option("--strict", "Fail warnings such as a WSL project under /mnt/c")
|
|
973
983
|
.option("--ping-timeout <ms>", "Per-service ping timeout in milliseconds", String(DEFAULT_PING_TIMEOUT_MS))
|
|
974
984
|
.action(async (options) => {
|
|
985
|
+
// Validate before running any probe; parseInt would silently accept "100ms" or "1.5".
|
|
986
|
+
const pingTimeout = Number(options.pingTimeout);
|
|
987
|
+
if (!/^\d+$/.test(options.pingTimeout) ||
|
|
988
|
+
!Number.isSafeInteger(pingTimeout) ||
|
|
989
|
+
pingTimeout <= 0) {
|
|
990
|
+
const message = "--ping-timeout must be a positive integer number of milliseconds";
|
|
991
|
+
if (options.json)
|
|
992
|
+
console.log(JSON.stringify(createDoctorReport([], false, [{ code: "USAGE", message }])));
|
|
993
|
+
console.error(message);
|
|
994
|
+
process.exit(2);
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
if (!options.json) {
|
|
998
|
+
console.log("TDK doctor checks your local Docker + Tilt development environment; it does not check cluster deployments.");
|
|
999
|
+
}
|
|
975
1000
|
if (process.platform === "win32") {
|
|
1001
|
+
if (options.json) {
|
|
1002
|
+
console.log(JSON.stringify(createDoctorReport([
|
|
1003
|
+
{
|
|
1004
|
+
name: "Native Windows support",
|
|
1005
|
+
didPass: false,
|
|
1006
|
+
message: NATIVE_WINDOWS_DOCTOR_MESSAGE,
|
|
1007
|
+
fix: "Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md",
|
|
1008
|
+
},
|
|
1009
|
+
], Boolean(findProjectRoot()))));
|
|
1010
|
+
}
|
|
976
1011
|
console.error(NATIVE_WINDOWS_DOCTOR_MESSAGE);
|
|
977
1012
|
process.exit(1);
|
|
978
1013
|
return;
|
|
979
1014
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
if (!Number.isFinite(pingTimeout) || pingTimeout <= 0) {
|
|
984
|
-
console.log(`${chalk.red("✗")} --ping-timeout must be a positive number of milliseconds`);
|
|
985
|
-
process.exit(1);
|
|
1015
|
+
if (!options.json) {
|
|
1016
|
+
console.log(`\n${chalk.bold("🔍 TDK Doctor")}\n`);
|
|
1017
|
+
console.log("Checking environment...\n");
|
|
986
1018
|
}
|
|
987
1019
|
const machineChecks = [
|
|
988
1020
|
() => checkHostPorts(),
|
|
@@ -1035,20 +1067,22 @@ export const doctorCommand = new Command("doctor")
|
|
|
1035
1067
|
// project. Only the machine checks mean anything there; the project checks
|
|
1036
1068
|
// would all fail with "run tdk project".
|
|
1037
1069
|
const inProject = Boolean(findProjectRoot());
|
|
1038
|
-
const checks = inProject ?
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
const
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1070
|
+
const { checks: results, errors } = await collectDoctorChecks(machineChecks, inProject ? projectChecks : []);
|
|
1071
|
+
const report = createDoctorReport(orderDoctorResults(results), inProject, errors);
|
|
1072
|
+
const exitCode = getDoctorExitCode(report);
|
|
1073
|
+
const allPassed = report.data.ready;
|
|
1074
|
+
if (options.json) {
|
|
1075
|
+
console.log(JSON.stringify(report));
|
|
1076
|
+
for (const error of errors)
|
|
1077
|
+
console.error(error.message);
|
|
1078
|
+
if (exitCode !== 0)
|
|
1079
|
+
process.exit(exitCode);
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
for (const error of errors)
|
|
1083
|
+
console.error(`${chalk.red("✗")} Doctor check failed: ${error.message}`);
|
|
1050
1084
|
for (const result of orderDoctorResults(results)) {
|
|
1051
|
-
if (!result.didPass && !result.isSkipped) {
|
|
1085
|
+
if (!result.didPass && !result.isSkipped && !result.isWarning) {
|
|
1052
1086
|
console.log(`${chalk.red("✗")} ${result.message}`);
|
|
1053
1087
|
if (result.fix)
|
|
1054
1088
|
console.log(`${chalk.blue("ℹ")} Fix: ${result.fix}`);
|
|
@@ -1074,7 +1108,7 @@ export const doctorCommand = new Command("doctor")
|
|
|
1074
1108
|
}
|
|
1075
1109
|
const outcome = getDoctorOutcomeMessage(inProject, allPassed);
|
|
1076
1110
|
console.log(`${allPassed ? chalk.green(chalk.bold("✓")) : chalk.red(chalk.bold("✗"))} ${outcome}`);
|
|
1077
|
-
if (
|
|
1078
|
-
process.exit(
|
|
1111
|
+
if (exitCode !== 0)
|
|
1112
|
+
process.exit(exitCode);
|
|
1079
1113
|
});
|
|
1080
1114
|
//# sourceMappingURL=doctor.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import pkg from "../../package.json" with { type: "json" };
|
|
3
3
|
const TDK_BANNER = `
|
|
4
|
-
${chalk.bold.cyan("tdk")} ${chalk.gray(`v${pkg.version}`)} ${chalk.white("
|
|
4
|
+
${chalk.bold.cyan("tdk")} ${chalk.gray(`v${pkg.version}`)} ${chalk.white("TDK runs many services locally with Docker + Tilt; Helm deploys the cluster")}
|
|
5
5
|
`;
|
|
6
6
|
const COMMAND_GROUPS = [
|
|
7
7
|
{
|
|
@@ -78,7 +78,8 @@ function formatCommand(name, desc, alias, color) {
|
|
|
78
78
|
}
|
|
79
79
|
export function showHelp() {
|
|
80
80
|
console.log(TDK_BANNER);
|
|
81
|
-
console.log(chalk.
|
|
81
|
+
console.log(chalk.gray("\n Local development inner loop; TDK does not replace Helm for cluster deployments.\n"));
|
|
82
|
+
console.log(chalk.bold.white(" Project → Phase → Stack → Resource\n"));
|
|
82
83
|
console.log(chalk.gray(" Usage: tdk [command] [options]\n"));
|
|
83
84
|
console.log(chalk.bold.yellow(" Global Options:"));
|
|
84
85
|
console.log(` ${chalk.cyan("-v, --version".padEnd(20))} ${chalk.white("Display version number")}`);
|