@wpmoo/toolkit 0.9.31 → 0.9.33
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 +13 -1
- package/dist/cockpit/menu.js +23 -5
- package/dist/doctor.js +17 -3
- package/dist/help.js +1 -0
- package/docs/command-reference.md +12 -0
- package/docs/handoff.md +3 -0
- package/docs/troubleshooting.md +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -143,6 +143,9 @@ Every cockpit action maps to a direct command, so the same workflow can be used
|
|
|
143
143
|
|
|
144
144
|
When an environment has many module candidates, module selection switches to
|
|
145
145
|
search so names, repositories, and source categories can be filtered quickly.
|
|
146
|
+
Runtime actions that need running services or a ready database are disabled in
|
|
147
|
+
the cockpit until the environment is ready; file-only actions such as module
|
|
148
|
+
scaffolding, source repository changes, and safe reset remain available.
|
|
146
149
|
|
|
147
150
|
```bash
|
|
148
151
|
./moo start
|
|
@@ -181,6 +184,9 @@ npx @wpmoo/toolkit doctor --json --postgres
|
|
|
181
184
|
```
|
|
182
185
|
|
|
183
186
|
JSON output is optional; human-readable output remains the default.
|
|
187
|
+
`doctor --json --fix` is intentionally unsupported because `doctor --fix` may
|
|
188
|
+
write safe file-level repairs. Run `doctor --fix` first, then `doctor --json`
|
|
189
|
+
to inspect the post-fix state.
|
|
184
190
|
Human `doctor` output is grouped into stable sections (`Generated files`,
|
|
185
191
|
`Compose`, `Source repositories`, `PostgreSQL`, and `Host tools`) so terminal
|
|
186
192
|
operators can see which lifecycle layer needs attention first.
|
|
@@ -212,6 +218,10 @@ JSON variant exposes a versioned PostgreSQL diagnostics contract.
|
|
|
212
218
|
`doctor --json --postgres` keeps the JSON contract stable by versioning the
|
|
213
219
|
`postgres` payload; individual fields are optional so automation can safely handle
|
|
214
220
|
environments where PostgreSQL does not expose a metric.
|
|
221
|
+
Optional PostgreSQL probe permission failures appear under
|
|
222
|
+
`postgres.optionalProbeFailures` when available; they do not make
|
|
223
|
+
`postgres.available` false and can be ignored by automation that only needs core
|
|
224
|
+
diagnostics.
|
|
215
225
|
All `doctor --json` reports also include optional `sections` entries that group
|
|
216
226
|
checks, warnings, and errors without changing the legacy flat arrays.
|
|
217
227
|
|
|
@@ -244,7 +254,9 @@ warning while keeping the scoped package release valid.
|
|
|
244
254
|
rejects it, the release still succeeds as long as the three required scoped
|
|
245
255
|
packages are valid.
|
|
246
256
|
- **Smoke expectation**: run `npm run smoke:published -- "$VERSION"` after the
|
|
247
|
-
release tag workflow completes.
|
|
257
|
+
release tag workflow completes. The script prints `Smoke step:` progress lines
|
|
258
|
+
before each published CLI check so slow registry-backed `npx` resolution is
|
|
259
|
+
visible.
|
|
248
260
|
- **Deterministic smoke target**: pin the target package explicitly so smoke checks
|
|
249
261
|
are reproducible across reruns:
|
|
250
262
|
|
package/dist/cockpit/menu.js
CHANGED
|
@@ -21,6 +21,16 @@ const topLevelCategoryOrder = [
|
|
|
21
21
|
const topLevelCommands = topLevelCategoryOrder.flatMap((category) => cockpitCommands.filter((command) => command.category === category && command.id !== 'exit'));
|
|
22
22
|
const topLevelCommandLabelWidth = Math.max(...topLevelCommands.map((command) => command.label.length));
|
|
23
23
|
const moduleDependentCommandIds = new Set(['list-modules', 'install', 'update', 'test', 'pot', 'remove-module']);
|
|
24
|
+
const runningServicesRequiredCommandIds = new Set([
|
|
25
|
+
'install',
|
|
26
|
+
'update',
|
|
27
|
+
'test',
|
|
28
|
+
'pot',
|
|
29
|
+
'psql',
|
|
30
|
+
'snapshot',
|
|
31
|
+
'restore-snapshot',
|
|
32
|
+
'resetdb',
|
|
33
|
+
]);
|
|
24
34
|
function rgb(red, green, blue, value) {
|
|
25
35
|
return `\u001B[38;2;${red};${green};${blue}m${value}\u001B[39m`;
|
|
26
36
|
}
|
|
@@ -39,6 +49,7 @@ const disabledReasonNextStep = {
|
|
|
39
49
|
'Services stopped.': 'Next: choose "Start services" first.',
|
|
40
50
|
'Already running.': 'Next: choose "Stop services" or "Restart services".',
|
|
41
51
|
'Docker not running.': 'Next: start Docker, then choose "Start services".',
|
|
52
|
+
'Database not ready.': 'Next: wait for the database or choose "Restart services".',
|
|
42
53
|
'No source repos found.': 'Next: choose "Add source repo" first.',
|
|
43
54
|
};
|
|
44
55
|
function disabledError(reason) {
|
|
@@ -50,15 +61,22 @@ function disabledError(reason) {
|
|
|
50
61
|
return nextStep ? `${base}\nReason: ${reason}\n${nextStep}` : `${base}\nReason: ${reason}`;
|
|
51
62
|
}
|
|
52
63
|
function serviceDisabledReason(command, serviceStatus) {
|
|
53
|
-
if (
|
|
64
|
+
if (!serviceStatus)
|
|
65
|
+
return undefined;
|
|
66
|
+
const requiresRunningServices = command.category === 'services' || runningServicesRequiredCommandIds.has(command.id);
|
|
67
|
+
if (!requiresRunningServices)
|
|
54
68
|
return undefined;
|
|
55
69
|
if (serviceStatus.kind === 'docker-not-running')
|
|
56
70
|
return 'Docker not running.';
|
|
57
71
|
if (serviceStatus.kind === 'running' && command.id === 'start')
|
|
58
72
|
return 'Already running.';
|
|
59
|
-
if (serviceStatus.kind === 'stopped' &&
|
|
73
|
+
if (serviceStatus.kind === 'stopped' &&
|
|
74
|
+
(['stop', 'restart', 'logs', 'shell'].includes(command.id) || runningServicesRequiredCommandIds.has(command.id))) {
|
|
60
75
|
return 'Services stopped.';
|
|
61
76
|
}
|
|
77
|
+
if (serviceStatus.kind === 'services-running' && runningServicesRequiredCommandIds.has(command.id)) {
|
|
78
|
+
return 'Database not ready.';
|
|
79
|
+
}
|
|
62
80
|
return undefined;
|
|
63
81
|
}
|
|
64
82
|
function moduleDisabledReason(command, moduleCount) {
|
|
@@ -71,10 +89,10 @@ function snapshotDisabledReason(command, snapshotCount) {
|
|
|
71
89
|
return snapshotCount === 0 && command.id === 'restore-snapshot' ? 'No snapshots found.' : undefined;
|
|
72
90
|
}
|
|
73
91
|
function disabledReason(command, serviceStatus, moduleCount, sourceRepoCount, snapshotCount) {
|
|
74
|
-
return (
|
|
75
|
-
moduleDisabledReason(command, moduleCount) ??
|
|
92
|
+
return (moduleDisabledReason(command, moduleCount) ??
|
|
76
93
|
sourceRepoDisabledReason(command, sourceRepoCount) ??
|
|
77
|
-
snapshotDisabledReason(command, snapshotCount)
|
|
94
|
+
snapshotDisabledReason(command, snapshotCount) ??
|
|
95
|
+
serviceDisabledReason(command, serviceStatus));
|
|
78
96
|
}
|
|
79
97
|
function commandDisabledValue(reason) {
|
|
80
98
|
if (!reason) {
|
package/dist/doctor.js
CHANGED
|
@@ -115,6 +115,13 @@ function postgresDiagnosticsTimeoutMs(options) {
|
|
|
115
115
|
? options.postgresTimeoutMs
|
|
116
116
|
: defaultPostgresDiagnosticsTimeoutMs;
|
|
117
117
|
}
|
|
118
|
+
function optionalPostgresProbeFailureWarning(error) {
|
|
119
|
+
const message = commandErrorText(error).trim();
|
|
120
|
+
if (!/(?:permission denied|insufficient privilege|must be superuser|not permitted|not allowed)/iu.test(message)) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
return message.split(/\r?\n/u).find((line) => line.trim())?.trim();
|
|
124
|
+
}
|
|
118
125
|
async function readPostgresDiagnosticQuery(target, runner, query, timeoutMs) {
|
|
119
126
|
const queryLiteral = JSON.stringify(query);
|
|
120
127
|
const command = [
|
|
@@ -127,16 +134,21 @@ async function readPostgresDiagnosticQuery(target, runner, query, timeoutMs) {
|
|
|
127
134
|
}
|
|
128
135
|
async function readPostgresDiagnostics(target, runner, timeoutMs) {
|
|
129
136
|
const diagnostics = await readPostgresDiagnosticQuery(target, runner, POSTGRES_DIAGNOSTICS_QUERY, timeoutMs);
|
|
137
|
+
const optionalProbeFailures = [];
|
|
130
138
|
for (const probe of POSTGRES_DIAGNOSTICS_OPTIONAL_QUERIES) {
|
|
131
139
|
try {
|
|
132
140
|
Object.assign(diagnostics, await readPostgresDiagnosticQuery(target, runner, probe.query, timeoutMs));
|
|
133
141
|
}
|
|
134
|
-
catch {
|
|
142
|
+
catch (error) {
|
|
143
|
+
const warning = optionalPostgresProbeFailureWarning(error);
|
|
144
|
+
if (warning) {
|
|
145
|
+
optionalProbeFailures.push({ id: probe.id, warning });
|
|
146
|
+
}
|
|
135
147
|
// Optional probes use PostgreSQL functions that can require elevated roles.
|
|
136
148
|
// Their failure must not hide the core read-only health report.
|
|
137
149
|
}
|
|
138
150
|
}
|
|
139
|
-
return diagnostics;
|
|
151
|
+
return { diagnostics, optionalProbeFailures };
|
|
140
152
|
}
|
|
141
153
|
function stripInlineComment(line) {
|
|
142
154
|
const hashIndex = line.indexOf('#');
|
|
@@ -628,7 +640,7 @@ export async function getDoctorReport(target = process.cwd(), runnerOrOptions =
|
|
|
628
640
|
}
|
|
629
641
|
if (actualOptions.postgres) {
|
|
630
642
|
try {
|
|
631
|
-
const postgresDiagnostics = await readPostgresDiagnostics(target, actualRunner, postgresDiagnosticsTimeoutMs(actualOptions));
|
|
643
|
+
const { diagnostics: postgresDiagnostics, optionalProbeFailures } = await readPostgresDiagnostics(target, actualRunner, postgresDiagnosticsTimeoutMs(actualOptions));
|
|
632
644
|
const missingKeys = missingPostgresDiagnosticKeys(postgresDiagnostics);
|
|
633
645
|
const malformedKeys = malformedPostgresDiagnosticKeys(postgresDiagnostics);
|
|
634
646
|
if (missingKeys.length === 0 && malformedKeys.length === 0) {
|
|
@@ -641,6 +653,7 @@ export async function getDoctorReport(target = process.cwd(), runnerOrOptions =
|
|
|
641
653
|
contractVersion: POSTGRES_DIAGNOSTICS_CONTRACT_VERSION,
|
|
642
654
|
available: true,
|
|
643
655
|
diagnostics: structuredPostgresDiagnostics(postgresDiagnostics),
|
|
656
|
+
...(optionalProbeFailures.length > 0 ? { optionalProbeFailures } : {}),
|
|
644
657
|
};
|
|
645
658
|
warnings.push(...postgresPostgresWarnings(postgresDiagnostics));
|
|
646
659
|
}
|
|
@@ -654,6 +667,7 @@ export async function getDoctorReport(target = process.cwd(), runnerOrOptions =
|
|
|
654
667
|
contractVersion: POSTGRES_DIAGNOSTICS_CONTRACT_VERSION,
|
|
655
668
|
available: false,
|
|
656
669
|
diagnostics: structuredPostgresDiagnostics(postgresDiagnostics),
|
|
670
|
+
...(optionalProbeFailures.length > 0 ? { optionalProbeFailures } : {}),
|
|
657
671
|
warning,
|
|
658
672
|
};
|
|
659
673
|
}
|
package/dist/help.js
CHANGED
|
@@ -161,6 +161,7 @@ Machine-readable JSON output:
|
|
|
161
161
|
npx @wpmoo/toolkit source sync --json
|
|
162
162
|
npx @wpmoo/toolkit doctor --json
|
|
163
163
|
doctor --json --postgres includes a structured postgres object for automation.
|
|
164
|
+
doctor --json is read-only; run doctor --fix first, then doctor --json for post-fix state.
|
|
164
165
|
Incomplete or malformed PostgreSQL metric rows are reported as unavailable diagnostics.
|
|
165
166
|
|
|
166
167
|
JSON compatibility policy:
|
|
@@ -29,6 +29,12 @@ unscoped `npx wpmoo` short alias is optional and best-effort; scripts should use
|
|
|
29
29
|
|
|
30
30
|
Run these from the generated environment root:
|
|
31
31
|
|
|
32
|
+
The cockpit disables runtime actions such as `psql`, `snapshot`, `resetdb`,
|
|
33
|
+
`restore-snapshot`, `install`, `update`, `test`, and `pot` while services are
|
|
34
|
+
stopped or the database is not ready. File-only cockpit actions remain
|
|
35
|
+
selectable so source repositories, module scaffolds, and safe reset can still be
|
|
36
|
+
managed.
|
|
37
|
+
|
|
32
38
|
| Command | Cockpit Equivalent | Guarded In Stage/Prod | Notes |
|
|
33
39
|
| --- | --- | --- | --- |
|
|
34
40
|
| `./moo start` | Services -> Start services | No | Starts local Odoo services. Disabled in cockpit when already running. |
|
|
@@ -66,9 +72,15 @@ Current JSON contract notes:
|
|
|
66
72
|
- `status --json` uses `schemaVersion: 1`.
|
|
67
73
|
- `source list --json` and `source sync --json` use `schemaVersion: 1`.
|
|
68
74
|
- `doctor --json` uses `schemaVersion: 1`.
|
|
75
|
+
- `doctor --json --fix` is intentionally unsupported because `doctor --fix`
|
|
76
|
+
may mutate files. Run `doctor --fix` first, then `doctor --json` to inspect
|
|
77
|
+
post-fix state.
|
|
69
78
|
- `doctor --json --postgres` adds `postgres.contractVersion` and a PostgreSQL
|
|
70
79
|
diagnostics object with its own `schemaVersion`.
|
|
71
80
|
- PostgreSQL fields are optional when a metric is unavailable.
|
|
81
|
+
- Optional privileged PostgreSQL probe failures may appear under
|
|
82
|
+
`postgres.optionalProbeFailures`; core diagnostics remain available when those
|
|
83
|
+
optional probes fail with permission errors.
|
|
72
84
|
- Automation should ignore unknown JSON fields.
|
|
73
85
|
- Minor and patch releases may add optional fields without a breaking release.
|
|
74
86
|
- Removing, renaming, or changing the meaning of a documented field requires a
|
package/docs/handoff.md
CHANGED
|
@@ -70,6 +70,9 @@ pre-existing global `NPM_CONFIG_CACHE` state unless you intentionally reuse it.
|
|
|
70
70
|
|
|
71
71
|
The smoke script checks `--version`, top-level `--help`, and critical command
|
|
72
72
|
help output before optional generated-environment acceptance smoke.
|
|
73
|
+
Long registry-backed smoke runs print `Smoke step:` progress lines before each
|
|
74
|
+
published CLI check, so a slow `npx` or `npm exec` resolution is visible in the
|
|
75
|
+
terminal instead of appearing stuck.
|
|
73
76
|
|
|
74
77
|
For a 1.0.0 tag, run generated-environment acceptance smoke with
|
|
75
78
|
WPMOO_SMOKE_ENVIRONMENT=1. Treat the release as final only after that smoke
|
package/docs/troubleshooting.md
CHANGED
|
@@ -11,6 +11,8 @@ Symptoms:
|
|
|
11
11
|
- The create wizard stops before writing files.
|
|
12
12
|
- `./moo start`, `./moo status`, or `./moo doctor` reports Docker or Docker
|
|
13
13
|
Compose as unavailable.
|
|
14
|
+
- The cockpit disables database or module runtime actions because Docker,
|
|
15
|
+
services, or the database are not ready.
|
|
14
16
|
|
|
15
17
|
Check:
|
|
16
18
|
|
|
@@ -30,6 +32,9 @@ The create wizard intentionally stops before setup questions when required
|
|
|
30
32
|
runtime tools are missing. That protects the workspace from half-created
|
|
31
33
|
environments.
|
|
32
34
|
|
|
35
|
+
If Docker is running but the cockpit says the database is not ready, wait for
|
|
36
|
+
PostgreSQL readiness or choose `Restart services`.
|
|
37
|
+
|
|
33
38
|
## No Modules Found
|
|
34
39
|
|
|
35
40
|
Symptoms:
|