@treeseed/cli 0.10.21 → 0.11.0
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.md +89 -116
- package/dist/cli/handlers/audit.js +28 -3
- package/dist/cli/handlers/capacity.js +2 -2
- package/dist/cli/handlers/destroy.js +6 -1
- package/dist/cli/handlers/dev.js +16 -2
- package/dist/cli/handlers/doctor.js +13 -3
- package/dist/cli/handlers/hosting.d.ts +2 -0
- package/dist/cli/handlers/hosting.js +257 -0
- package/dist/cli/handlers/operations.d.ts +2 -0
- package/dist/cli/handlers/operations.js +46 -0
- package/dist/cli/handlers/package-image.d.ts +10 -0
- package/dist/cli/handlers/package-image.js +132 -0
- package/dist/cli/handlers/package.d.ts +2 -0
- package/dist/cli/handlers/package.js +14 -0
- package/dist/cli/handlers/projects.js +3 -3
- package/dist/cli/handlers/ready.d.ts +2 -0
- package/dist/cli/handlers/ready.js +84 -0
- package/dist/cli/handlers/reconcile.d.ts +2 -0
- package/dist/cli/handlers/reconcile.js +157 -0
- package/dist/cli/handlers/release.js +12 -3
- package/dist/cli/handlers/save.js +12 -2
- package/dist/cli/handlers/seed.js +2 -2
- package/dist/cli/handlers/stage.js +8 -2
- package/dist/cli/handlers/status.js +30 -1
- package/dist/cli/handlers/tool-wrapper.js +71 -3
- package/dist/cli/handlers/treedx.d.ts +2 -0
- package/dist/cli/handlers/treedx.js +310 -0
- package/dist/cli/handlers/workflow.d.ts +40 -0
- package/dist/cli/handlers/workflow.js +41 -0
- package/dist/cli/operations-registry.js +300 -34
- package/dist/cli/registry.d.ts +6 -0
- package/dist/cli/registry.js +12 -0
- package/dist/cli/runtime.js +17 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,174 +1,147 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @treeseed/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@treeseed/cli` publishes the `treeseed` and `trsd` command surfaces. Use it to configure Treeseed, run local development, save/stage/release work, reconcile hosting, operate capacity providers, manage package images, and inspect workflow state.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The CLI is the human and automation entrypoint over package-owned capabilities. It delegates platform logic to `@treeseed/sdk`, web runtime orchestration to `@treeseed/core`, backend behavior to API surfaces, capacity runtime to `@treeseed/agent`, and TreeDX image workflows to package manifests.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## What You Can Do With The CLI
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
9
|
+
- configure local, staging, and production environments
|
|
10
|
+
- start and inspect local development instances
|
|
11
|
+
- save, stage, close, resume, and release multi-repo work
|
|
12
|
+
- plan/apply/verify hosted infrastructure through reconciliation
|
|
13
|
+
- run operations-runner smoke checks
|
|
14
|
+
- build and operate capacity providers
|
|
15
|
+
- manage TreeDX package image workflows
|
|
16
|
+
- inspect package drift, workflow locks, and interrupted runs
|
|
11
17
|
|
|
12
18
|
## Install
|
|
13
19
|
|
|
14
|
-
Install the CLI with its runtime dependencies:
|
|
15
|
-
|
|
16
20
|
```bash
|
|
17
|
-
npm install @treeseed/cli
|
|
21
|
+
npm install @treeseed/cli
|
|
18
22
|
```
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Workflow guarantees:
|
|
23
|
-
|
|
24
|
-
- `treeseed` is the only supported project-management surface for market and any checked-out `packages/sdk`, `packages/core`, and `packages/cli` repos.
|
|
25
|
-
- `treeseed switch` requires clean worktrees, mirrors the task branch into checked-out package repos, and only pushes the market branch on branch creation.
|
|
26
|
-
- `treeseed save` is the canonical recursive checkpoint command: it verifies, commits, and pushes dirty package repos in dependency order before saving the market repo.
|
|
27
|
-
- `treeseed stage` squash-merges task branches into `staging` across package repos first, refreshes market submodule pointers to package `staging` heads, then stages the market repo.
|
|
28
|
-
- `treeseed close` recursively archives and deletes matching task branches across market and checked-out package repos.
|
|
29
|
-
- `treeseed release` only bumps, tags, and publishes changed packages plus internal dependents, then syncs market production to package `main` heads.
|
|
30
|
-
- Every mutating workflow command supports `--plan`; `--dry-run` is only an alias where it still exists for compatibility.
|
|
31
|
-
- Interrupted workflow runs are journaled under `.treeseed/workflow`; use `treeseed recover` to inspect them and `treeseed resume <run-id>` to continue a resumable run.
|
|
32
|
-
|
|
33
|
-
After installation, the published binary is available as:
|
|
24
|
+
After installation:
|
|
34
25
|
|
|
35
26
|
```bash
|
|
36
27
|
treeseed --help
|
|
28
|
+
trsd --help
|
|
37
29
|
```
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
The main workflow commands exposed by the current CLI are:
|
|
31
|
+
In this workspace, use `npx trsd ...` from the root.
|
|
42
32
|
|
|
43
|
-
|
|
44
|
-
- `treeseed config`
|
|
45
|
-
- `treeseed tasks [--json]`
|
|
46
|
-
- `treeseed switch <branch-name> [--preview]`
|
|
47
|
-
- `treeseed dev`
|
|
48
|
-
- `treeseed dev start|status|logs|stop|restart`
|
|
49
|
-
- `treeseed save [--preview] [--plan] "<commit message>"`
|
|
50
|
-
- `treeseed stage "<resolution message>"`
|
|
51
|
-
- `treeseed close "<close reason>"`
|
|
52
|
-
- `treeseed release --major|--minor|--patch [--plan]`
|
|
53
|
-
- `treeseed resume <run-id>`
|
|
54
|
-
- `treeseed recover`
|
|
55
|
-
- `treeseed destroy --environment <local|staging|prod> [--plan]`
|
|
56
|
-
|
|
57
|
-
Support utilities such as `treeseed rollback`, `treeseed doctor`, `treeseed auth:*`, `treeseed template`, `treeseed sync`, `treeseed lint`, `treeseed test`, `treeseed build`, service helpers, and `treeseed agents ...` remain available.
|
|
58
|
-
|
|
59
|
-
Use `treeseed help` for the full command list and `treeseed help <command>` for command-specific usage, options, and examples.
|
|
60
|
-
|
|
61
|
-
## Common Commands
|
|
33
|
+
## Primary Commands
|
|
62
34
|
|
|
63
35
|
```bash
|
|
64
|
-
treeseed status
|
|
65
|
-
treeseed config
|
|
66
|
-
treeseed switch feature/search-improvements --plan
|
|
67
|
-
treeseed switch feature/search-improvements --preview
|
|
68
|
-
treeseed dev
|
|
69
|
-
treeseed dev start --web-runtime local
|
|
70
|
-
treeseed save --preview "feat: add search filters"
|
|
71
|
-
treeseed stage "feat: add search filters"
|
|
72
|
-
treeseed release --patch
|
|
73
|
-
treeseed recover
|
|
74
36
|
treeseed status --json
|
|
37
|
+
treeseed config
|
|
38
|
+
treeseed ready local --json
|
|
39
|
+
treeseed switch feature/my-change --plan --json
|
|
40
|
+
treeseed dev start --web-runtime local --json
|
|
41
|
+
treeseed save --verify local --json "describe the checkpoint"
|
|
42
|
+
treeseed stage --plan --json "describe the staging change"
|
|
43
|
+
treeseed release --patch --verify-deployed-resources --plan --json
|
|
44
|
+
treeseed recover --json
|
|
75
45
|
```
|
|
76
46
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
`treeseed dev` remains the foreground local runtime supervisor. It delegates to `@treeseed/core`, starts the Market web/API/control-plane development surface, streams output in the active terminal, and exits when the shell-owned process is stopped.
|
|
80
|
-
|
|
81
|
-
Managed dev instances use subcommands:
|
|
47
|
+
Hosted diagnostics:
|
|
82
48
|
|
|
83
49
|
```bash
|
|
84
|
-
treeseed
|
|
85
|
-
treeseed
|
|
86
|
-
treeseed
|
|
87
|
-
treeseed
|
|
88
|
-
treeseed dev stop --json
|
|
89
|
-
treeseed dev restart --web-runtime local --json
|
|
50
|
+
treeseed ready staging --json
|
|
51
|
+
treeseed hosting plan --environment staging --service api --json
|
|
52
|
+
treeseed hosting verify --environment staging --service operationsRunner --live --json
|
|
53
|
+
treeseed operations smoke --environment staging --service operationsRunner --json
|
|
90
54
|
```
|
|
91
55
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
`--force` replaces only the current worktree instance. `--force-conflicts` is the explicit cross-worktree port-owner escape hatch. Additional worktrees receive stable alternate port blocks and worktree-specific local PostgreSQL/Mailpit names, so many agents can run development sessions in the same repository family.
|
|
95
|
-
|
|
96
|
-
For the complete architecture, see the root workspace document `docs/local-dev-instances.md`.
|
|
97
|
-
|
|
98
|
-
## Agent-Safe Workflow
|
|
99
|
-
|
|
100
|
-
Use planning mode before any destructive or multi-repo mutation:
|
|
56
|
+
Capacity providers:
|
|
101
57
|
|
|
102
58
|
```bash
|
|
103
|
-
treeseed
|
|
104
|
-
treeseed
|
|
105
|
-
treeseed
|
|
106
|
-
treeseed
|
|
59
|
+
treeseed capacity build
|
|
60
|
+
treeseed capacity up
|
|
61
|
+
treeseed capacity status
|
|
62
|
+
treeseed capacity logs
|
|
63
|
+
treeseed capacity down
|
|
107
64
|
```
|
|
108
65
|
|
|
109
|
-
|
|
66
|
+
TreeDX package image:
|
|
110
67
|
|
|
111
68
|
```bash
|
|
112
|
-
treeseed
|
|
113
|
-
treeseed
|
|
69
|
+
treeseed package image --package treedx --branch staging --plan --json
|
|
70
|
+
treeseed package image --package treedx --branch staging --sync-config --json
|
|
71
|
+
treeseed package image --package treedx --branch staging --execute --json
|
|
114
72
|
```
|
|
115
73
|
|
|
116
|
-
|
|
74
|
+
Use `treeseed help <command>` for command-specific usage and examples.
|
|
117
75
|
|
|
118
|
-
##
|
|
76
|
+
## Managed Package Set
|
|
119
77
|
|
|
120
|
-
|
|
78
|
+
The CLI coordinates the root market repo plus checked-out package repositories:
|
|
121
79
|
|
|
122
|
-
|
|
80
|
+
- `@treeseed/sdk`
|
|
81
|
+
- `@treeseed/ui`
|
|
82
|
+
- `@treeseed/core`
|
|
83
|
+
- `@treeseed/admin`
|
|
84
|
+
- `@treeseed/api`
|
|
85
|
+
- `@treeseed/cli`
|
|
86
|
+
- `@treeseed/agent`
|
|
87
|
+
- `packages/treedx`
|
|
123
88
|
|
|
124
|
-
|
|
125
|
-
npm install
|
|
126
|
-
```
|
|
89
|
+
Workflow commands save package repos in dependency order, update submodule pointers, verify package release gates, and avoid one-off provider mutation.
|
|
127
90
|
|
|
128
|
-
|
|
91
|
+
## Save, Stage, And Release
|
|
92
|
+
|
|
93
|
+
`treeseed save` is the default checkpoint command. It saves dirty package repositories first, restores workspace links, performs lightweight release-candidate validation, and then saves the root market repo.
|
|
129
94
|
|
|
130
95
|
```bash
|
|
131
|
-
|
|
96
|
+
treeseed save --json "describe the checkpoint"
|
|
97
|
+
treeseed save --verify local --json "describe the checkpoint"
|
|
98
|
+
treeseed save --lane promotion --json "describe the checkpoint"
|
|
132
99
|
```
|
|
133
100
|
|
|
134
|
-
|
|
101
|
+
`treeseed stage` and `treeseed release` are promotion-grade commands. Use `--plan` before risky operations:
|
|
135
102
|
|
|
136
103
|
```bash
|
|
137
|
-
|
|
104
|
+
treeseed stage --plan --json "describe the staging change"
|
|
105
|
+
treeseed release --patch --verify-deployed-resources --plan --json
|
|
138
106
|
```
|
|
139
107
|
|
|
140
|
-
|
|
108
|
+
Interrupted workflow runs are journaled under `.treeseed/workflow`:
|
|
141
109
|
|
|
142
110
|
```bash
|
|
143
|
-
|
|
111
|
+
treeseed recover --json
|
|
112
|
+
treeseed resume <run-id> --json
|
|
144
113
|
```
|
|
145
114
|
|
|
146
|
-
|
|
115
|
+
## How CLI Fits With Other Packages
|
|
147
116
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
117
|
+
- `@treeseed/sdk` owns workflow, reconciliation, config, package discovery, and platform primitives.
|
|
118
|
+
- `@treeseed/core` owns the local web runtime used by `treeseed dev`.
|
|
119
|
+
- `@treeseed/admin` and `@treeseed/ui` are consumed by the web app; CLI does not own those routes or components.
|
|
120
|
+
- `@treeseed/api` owns backend API and operations-runner implementation.
|
|
121
|
+
- `@treeseed/agent` owns capacity-provider runtime artifacts that CLI starts or reconciles.
|
|
122
|
+
- TreeDX owns its service/image; CLI exposes package-image workflow commands.
|
|
154
123
|
|
|
155
|
-
##
|
|
124
|
+
## Package Development
|
|
156
125
|
|
|
157
|
-
|
|
126
|
+
From this package root:
|
|
158
127
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
```text
|
|
166
|
-
<version>
|
|
128
|
+
```bash
|
|
129
|
+
npm install
|
|
130
|
+
npm run build
|
|
131
|
+
npm test
|
|
132
|
+
npm run release:verify
|
|
167
133
|
```
|
|
168
134
|
|
|
169
|
-
|
|
135
|
+
Release verification checks the packaged command surface, parser/help behavior, build output, and publishable artifact shape.
|
|
136
|
+
|
|
137
|
+
## What CLI Does Not Own
|
|
170
138
|
|
|
171
|
-
|
|
139
|
+
- SDK reconciliation internals
|
|
140
|
+
- Core web runtime internals
|
|
141
|
+
- Admin routes or UI components
|
|
142
|
+
- backend API implementation
|
|
143
|
+
- capacity-provider runtime implementation
|
|
144
|
+
- TreeDX service internals
|
|
145
|
+
- root market content or ecommerce
|
|
172
146
|
|
|
173
|
-
|
|
174
|
-
- The README intentionally documents the command surface at a high level. The canonical source of operation identity and semantics is `@treeseed/sdk`, while `@treeseed/cli` owns argv parsing, help rendering, and terminal formatting.
|
|
147
|
+
See the root [Package Ownership](../../docs/package-ownership.md) guide for cross-package boundaries.
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
collectTreeseedHostedServiceChecks,
|
|
3
|
+
collectTreeseedLiveHostedServiceChecks,
|
|
2
4
|
formatTreeseedHostingAuditReport,
|
|
3
5
|
runTreeseedHostingAudit
|
|
4
6
|
} from "@treeseed/sdk/workflow-support";
|
|
@@ -45,12 +47,25 @@ const handleAudit = async (invocation, context) => {
|
|
|
45
47
|
hostKinds: normalizeHostKinds(invocation.args.hostKinds ?? invocation.args.hosts),
|
|
46
48
|
write: context.write
|
|
47
49
|
});
|
|
50
|
+
const hostedTarget = report.environment === "prod" ? "prod" : report.environment === "local" ? "local" : "staging";
|
|
51
|
+
const hostedServices = invocation.args.live === true ? await collectTreeseedLiveHostedServiceChecks({
|
|
52
|
+
tenantRoot: context.cwd,
|
|
53
|
+
target: hostedTarget,
|
|
54
|
+
strict: false,
|
|
55
|
+
env: context.env
|
|
56
|
+
}) : collectTreeseedHostedServiceChecks({
|
|
57
|
+
tenantRoot: context.cwd,
|
|
58
|
+
target: hostedTarget
|
|
59
|
+
});
|
|
48
60
|
const counts = statusCounts(report.checks);
|
|
49
61
|
if (context.outputFormat === "json") {
|
|
50
62
|
return {
|
|
51
63
|
exitCode: report.ok ? 0 : 1,
|
|
52
64
|
stdout: [],
|
|
53
|
-
report
|
|
65
|
+
report: {
|
|
66
|
+
...report,
|
|
67
|
+
hostedServices
|
|
68
|
+
}
|
|
54
69
|
};
|
|
55
70
|
}
|
|
56
71
|
return guidedResult({
|
|
@@ -62,10 +77,20 @@ const handleAudit = async (invocation, context) => {
|
|
|
62
77
|
{ label: "Mode", value: report.repairMode ? "repair" : "read-only" },
|
|
63
78
|
{ label: "Passed", value: counts.passed ?? 0 },
|
|
64
79
|
{ label: "Warnings", value: (counts.warning ?? 0) + report.warnings.length },
|
|
65
|
-
{ label: "Failed", value: counts.failed ?? 0 }
|
|
80
|
+
{ label: "Failed", value: counts.failed ?? 0 },
|
|
81
|
+
{ label: "Hosted checks", value: `${hostedServices.summary.passed} passed, ${hostedServices.summary.warning} warnings, ${hostedServices.summary.failed} failed, ${hostedServices.summary.skipped} skipped` }
|
|
82
|
+
],
|
|
83
|
+
sections: [
|
|
84
|
+
{
|
|
85
|
+
title: "Hosted service checks",
|
|
86
|
+
lines: hostedServices.checks.map((check) => `${check.provider} ${check.serviceKey ?? check.serviceType} ${check.description}: ${check.status}${check.issues.length ? ` (${check.issues.join("; ")})` : ""}`)
|
|
87
|
+
}
|
|
66
88
|
],
|
|
67
89
|
nextSteps: report.nextActions,
|
|
68
|
-
report
|
|
90
|
+
report: {
|
|
91
|
+
...report,
|
|
92
|
+
hostedServices
|
|
93
|
+
},
|
|
69
94
|
exitCode: report.ok ? 0 : 1
|
|
70
95
|
});
|
|
71
96
|
} catch (error) {
|
|
@@ -378,7 +378,7 @@ function runLifecycleAction(action, invocation, context) {
|
|
|
378
378
|
requireConnection: lifecycleActionRequiresConnection(action),
|
|
379
379
|
overrides: {
|
|
380
380
|
TREESEED_MARKET_URL: market.baseUrl,
|
|
381
|
-
|
|
381
|
+
TREESEED_MANAGER_ID: market.id,
|
|
382
382
|
TREESEED_PROVIDER_HOST_DATA_DIR: resolvedHostDataDir,
|
|
383
383
|
TREESEED_PROVIDER_ENVIRONMENT: providerSelector(invocation),
|
|
384
384
|
...diagnostic ? { TREESEED_PROVIDER_STARTUP_MODE: "diagnostic" } : {}
|
|
@@ -442,7 +442,7 @@ function invokeProviderEntrypoint(action, invocation, context) {
|
|
|
442
442
|
env: {
|
|
443
443
|
...context.env,
|
|
444
444
|
TREESEED_MARKET_URL: market.baseUrl,
|
|
445
|
-
|
|
445
|
+
TREESEED_MANAGER_ID: market.id,
|
|
446
446
|
TREESEED_PROVIDER_ENVIRONMENT: providerSelector(invocation)
|
|
447
447
|
},
|
|
448
448
|
encoding: "utf8"
|
|
@@ -28,9 +28,11 @@ const handleDestroy = async (invocation, context) => {
|
|
|
28
28
|
dryRun: invocation.args.dryRun === true,
|
|
29
29
|
force: invocation.args.force === true,
|
|
30
30
|
deleteData: invocation.args.deleteData === true,
|
|
31
|
+
sweepTreeseed: invocation.args.sweepTreeseed === true,
|
|
31
32
|
removeBuildArtifacts: invocation.args.removeBuildArtifacts === true
|
|
32
33
|
});
|
|
33
34
|
const payload = result.payload;
|
|
35
|
+
const verification = payload.remoteResult?.verification ?? null;
|
|
34
36
|
return guidedResult({
|
|
35
37
|
command: invocation.commandName || "destroy",
|
|
36
38
|
summary: result.executionMode === "plan" ? "Treeseed destroy plan ready." : "Treeseed destroy completed successfully.",
|
|
@@ -38,7 +40,10 @@ const handleDestroy = async (invocation, context) => {
|
|
|
38
40
|
{ label: "Environment", value: payload.scope },
|
|
39
41
|
{ label: "Dry run", value: payload.dryRun ? "yes" : "no" },
|
|
40
42
|
{ label: "Delete data", value: payload.deleteData ? "yes" : "no" },
|
|
41
|
-
{ label: "
|
|
43
|
+
{ label: "Sweep TreeSeed resources", value: payload.sweepTreeseed ? "yes" : "no" },
|
|
44
|
+
{ label: "Removed build artifacts", value: payload.removeBuildArtifacts ? "yes" : "no" },
|
|
45
|
+
...verification?.cloudflare ? [{ label: "Cloudflare remaining", value: String(verification.cloudflare.totalRemaining ?? 0) }] : [],
|
|
46
|
+
...verification?.localDocker ? [{ label: "Local Docker remaining", value: String(verification.localDocker.totalRemaining ?? 0) }] : []
|
|
42
47
|
],
|
|
43
48
|
nextSteps: renderWorkflowNextSteps(result),
|
|
44
49
|
report: result
|
package/dist/cli/handlers/dev.js
CHANGED
|
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
4
|
import { ensureLocalWorkspaceLinks, findNearestTreeseedWorkspaceRoot, resolveTreeseedLaunchEnvironment } from "@treeseed/sdk/workflow-support";
|
|
5
|
+
import { discoverTreeseedApplications } from "@treeseed/sdk/hosting";
|
|
5
6
|
import { workflowErrorResult } from "./workflow.js";
|
|
6
7
|
import { fail } from "./utils.js";
|
|
7
8
|
const require2 = createRequire(import.meta.url);
|
|
@@ -52,12 +53,17 @@ const handleDev = async (invocation, context) => {
|
|
|
52
53
|
}
|
|
53
54
|
const feedback = typeof invocation.args.feedback === "string" ? invocation.args.feedback : void 0;
|
|
54
55
|
const watch = feedback !== "off";
|
|
56
|
+
const appId = typeof invocation.args.app === "string" && invocation.args.app.trim() ? invocation.args.app.trim() : void 0;
|
|
57
|
+
const apiMode = typeof invocation.args.api === "string" && invocation.args.api.trim() ? invocation.args.api.trim() : "auto";
|
|
55
58
|
const subcommand = typeof invocation.positionals[0] === "string" ? invocation.positionals[0] : "";
|
|
56
59
|
const managedSubcommands = /* @__PURE__ */ new Set(["start", "status", "logs", "stop", "restart"]);
|
|
57
60
|
if (subcommand && !managedSubcommands.has(subcommand)) {
|
|
58
61
|
return fail(`Unknown dev subcommand "${subcommand}". Use start, status, logs, stop, or restart.`);
|
|
59
62
|
}
|
|
60
|
-
const
|
|
63
|
+
const discoveredApps = discoverTreeseedApplications(context.cwd);
|
|
64
|
+
const hasApiApp = discoveredApps.some((app) => app.id === "api");
|
|
65
|
+
const selectedSurfaces = appId === "api" ? "api" : appId === "web" || apiMode === "remote" ? "web" : hasApiApp ? "web,api" : "web";
|
|
66
|
+
const passthroughArgs = ["--surfaces", selectedSurfaces];
|
|
61
67
|
const forwardStringOption = (name, flag) => {
|
|
62
68
|
const value = invocation.args[name];
|
|
63
69
|
if (typeof value === "string" && value.trim().length > 0) {
|
|
@@ -117,7 +123,15 @@ const handleDev = async (invocation, context) => {
|
|
|
117
123
|
watch,
|
|
118
124
|
executable: resolved.command,
|
|
119
125
|
args,
|
|
120
|
-
workspaceLinks
|
|
126
|
+
workspaceLinks,
|
|
127
|
+
appId: appId ?? null,
|
|
128
|
+
apiMode,
|
|
129
|
+
discoveredApps: discoveredApps.map((app) => ({
|
|
130
|
+
id: app.id,
|
|
131
|
+
relativeRoot: app.relativeRoot,
|
|
132
|
+
roles: app.roles
|
|
133
|
+
})),
|
|
134
|
+
selectedSurfaces
|
|
121
135
|
}
|
|
122
136
|
};
|
|
123
137
|
} catch (error) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import { collectCliPreflight } from "@treeseed/sdk/workflow-support";
|
|
3
|
+
import { collectCliPreflight, collectTreeseedDeploymentReadiness, collectTreeseedHostedServiceChecks } from "@treeseed/sdk/workflow-support";
|
|
4
4
|
import { guidedResult } from "./utils.js";
|
|
5
5
|
import { applyTreeseedSafeRepairs } from "../repair.js";
|
|
6
6
|
import { createWorkflowSdk, workflowErrorResult } from "./workflow.js";
|
|
@@ -8,6 +8,12 @@ const handleDoctor = async (invocation, context) => {
|
|
|
8
8
|
try {
|
|
9
9
|
const status = await createWorkflowSdk(context).status();
|
|
10
10
|
const state = status.payload;
|
|
11
|
+
const hostedServices = invocation.args.live === true || invocation.args.hostedServices === true ? collectTreeseedHostedServiceChecks({
|
|
12
|
+
tenantRoot: context.cwd,
|
|
13
|
+
target: state.branchRole === "production" || state.branchName === "main" ? "prod" : state.branchRole === "staging" || state.branchName === "staging" ? "staging" : "local"
|
|
14
|
+
}) : null;
|
|
15
|
+
const hostedTarget = state.branchRole === "production" || state.branchName === "main" ? "prod" : state.branchRole === "staging" || state.branchName === "staging" ? "staging" : "local";
|
|
16
|
+
const deploymentReadiness = invocation.args.live === true || invocation.args.hostedServices === true ? collectTreeseedDeploymentReadiness({ tenantRoot: context.cwd, environment: hostedTarget }) : null;
|
|
11
17
|
const performedFixes = invocation.args.fix === true && state.deployConfigPresent ? applyTreeseedSafeRepairs(state.cwd) : [];
|
|
12
18
|
const preflight = collectCliPreflight({ cwd: context.cwd, requireAuth: false });
|
|
13
19
|
const railwayManagedServicesEnabled = Object.values(state.managedServices).some((service) => service.enabled);
|
|
@@ -65,7 +71,9 @@ const handleDoctor = async (invocation, context) => {
|
|
|
65
71
|
{ label: "Optional follow-up", value: optional.length },
|
|
66
72
|
{ label: "Safe fixes applied", value: performedFixes.length },
|
|
67
73
|
{ label: "Branch", value: state.branchName ?? "(none)" },
|
|
68
|
-
{ label: "Workspace root", value: state.workspaceRoot ? "yes" : "no" }
|
|
74
|
+
{ label: "Workspace root", value: state.workspaceRoot ? "yes" : "no" },
|
|
75
|
+
...hostedServices ? [{ label: "Hosted checks", value: `${hostedServices.summary.passed} passed, ${hostedServices.summary.warning} warnings, ${hostedServices.summary.failed} failed, ${hostedServices.summary.skipped} skipped` }] : [],
|
|
76
|
+
...deploymentReadiness ? [{ label: "Deployment readiness", value: `${deploymentReadiness.summary.passed} passed, ${deploymentReadiness.summary.failed} failed` }] : []
|
|
69
77
|
],
|
|
70
78
|
nextSteps: [
|
|
71
79
|
...mustFixNow.map((item) => item),
|
|
@@ -77,7 +85,9 @@ const handleDoctor = async (invocation, context) => {
|
|
|
77
85
|
preflight,
|
|
78
86
|
performedFixes,
|
|
79
87
|
mustFixNow,
|
|
80
|
-
optional
|
|
88
|
+
optional,
|
|
89
|
+
hostedServices,
|
|
90
|
+
deploymentReadiness
|
|
81
91
|
},
|
|
82
92
|
exitCode: mustFixNow.length === 0 ? 0 : 1
|
|
83
93
|
});
|