@wirecat/cli-core 0.504.0 → 0.505.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/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ shape of this file.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.505.0 — 31.10.2026
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`appDoctorCommand` takes `--online`, and a messenger's and an app's `doctor` now say one thing.** Both use the
|
|
15
|
+
summary "the state this installation is in, without connecting unless --online" and the option text "also connect
|
|
16
|
+
once and read the account; sends nothing" (one constant, `doctor-text.ts`). Without the flag the answer is as before
|
|
17
|
+
and nothing is called. With it, `online` joins the answer: `{ ok, duration_ms, version: { current, latest, newer } }`,
|
|
18
|
+
plus the fields of the new `AppDoctorOptions.online(env)` hook, where a CLI checks its own service (a login, a folder
|
|
19
|
+
read); a throw there is `ok: false` with `error_code` and `error`, never a failed command. `version` comes from npm
|
|
20
|
+
(the `latestVersion` that `upgrade` uses) when the CLI passes the new `AppDoctorOptions.packageName`; without it that
|
|
21
|
+
check is left out. The command's effects are now `REMOTE_READ`, as the messenger's.
|
|
22
|
+
|
|
10
23
|
## 0.504.0 — 31.10.2026
|
|
11
24
|
|
|
12
25
|
### Added
|
|
@@ -9,6 +9,15 @@ export interface AppDoctorOptions {
|
|
|
9
9
|
oauthClient?: (env: NodeJS.ProcessEnv) => {
|
|
10
10
|
client: "wirecat" | "own";
|
|
11
11
|
};
|
|
12
|
+
/** The npm package, so `--online` can say whether a newer version is published; without it that check is left out. */
|
|
13
|
+
packageName?: string;
|
|
14
|
+
/**
|
|
15
|
+
* What `--online` checks of the service: a login, a folder read. Its fields join the `online` answer, and `ok: false`
|
|
16
|
+
* (or a throw, reported as `error_code` and `error`) makes the whole check fail without failing the command.
|
|
17
|
+
*/
|
|
18
|
+
online?: (env: NodeJS.ProcessEnv) => Promise<{
|
|
19
|
+
ok: boolean;
|
|
20
|
+
} & Record<string, unknown>>;
|
|
12
21
|
}
|
|
13
22
|
/**
|
|
14
23
|
* Run when everything else is broken, so a problem in the config file or the OAuth setting is a field, never a throw.
|
|
@@ -103,5 +112,9 @@ export declare const appDoctorReport: (app: AppIdentity, configuration: Configur
|
|
|
103
112
|
};
|
|
104
113
|
fixes: string[] | never[];
|
|
105
114
|
};
|
|
106
|
-
/**
|
|
115
|
+
/**
|
|
116
|
+
* `doctor` for a CLI that is not a messenger: gcal, drive, zoom. A messenger's is `doctorCommand(messenger)`, and both
|
|
117
|
+
* say the same thing: the state from disk, and only with `--online` a call out. Here that call is `options.online`
|
|
118
|
+
* and, with `options.packageName`, whether npm has a newer version.
|
|
119
|
+
*/
|
|
107
120
|
export declare const appDoctorCommand: (app: AppIdentity, configuration: Configuration, options?: AppDoctorOptions) => Command;
|
|
@@ -2,15 +2,48 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { dirname, resolve } from "node:path";
|
|
3
3
|
import { CliError, configFilePath, resolvePaths } from "@wirecat/cli-base";
|
|
4
4
|
import { annotate } from "@wirecat/cli-base/commands";
|
|
5
|
+
import { isNewer, latestVersion } from "@wirecat/cli-base/update";
|
|
5
6
|
import { Command } from "commander";
|
|
6
7
|
import { envName, readOnlyLockOf } from "../ports/app.js";
|
|
7
8
|
import { storePath } from "../store/path.js";
|
|
8
9
|
import { environmentOf, outputFor } from "./context.js";
|
|
9
|
-
import {
|
|
10
|
+
import { DOCTOR_ONLINE_OPTION, DOCTOR_SUMMARY } from "./doctor-text.js";
|
|
11
|
+
import { REMOTE_READ } from "./effects.js";
|
|
10
12
|
import { itemOf, renderAnswer } from "./envelope.js";
|
|
11
13
|
import { privateFiles } from "./messenger/private-files.js";
|
|
12
14
|
import { unknownPermissionIssues } from "./permission-keys.js";
|
|
13
15
|
import { profileFree } from "./profile.js";
|
|
16
|
+
const onlineCheck = async (app, env, fetcher, options) => {
|
|
17
|
+
const started = Date.now();
|
|
18
|
+
let service = { ok: true };
|
|
19
|
+
if (options.online)
|
|
20
|
+
try {
|
|
21
|
+
service = await options.online(env);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
service = {
|
|
25
|
+
ok: false,
|
|
26
|
+
error_code: error instanceof CliError ? error.code : "generic_failure",
|
|
27
|
+
error: error instanceof Error ? error.message : String(error),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const latest = options.packageName
|
|
31
|
+
? await latestVersion(options.packageName, fetcher, { timeoutMs: 3000 })
|
|
32
|
+
: undefined;
|
|
33
|
+
return {
|
|
34
|
+
...service,
|
|
35
|
+
duration_ms: Date.now() - started,
|
|
36
|
+
...(options.packageName
|
|
37
|
+
? {
|
|
38
|
+
version: {
|
|
39
|
+
current: app.version,
|
|
40
|
+
latest: latest ?? null,
|
|
41
|
+
newer: latest !== undefined && isNewer(latest, app.version),
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
: {}),
|
|
45
|
+
};
|
|
46
|
+
};
|
|
14
47
|
const failure = (error) => {
|
|
15
48
|
if (error instanceof CliError)
|
|
16
49
|
return error.message;
|
|
@@ -85,17 +118,26 @@ export const appDoctorReport = (app, configuration, env, command, options = {})
|
|
|
85
118
|
};
|
|
86
119
|
}
|
|
87
120
|
};
|
|
88
|
-
/**
|
|
121
|
+
/**
|
|
122
|
+
* `doctor` for a CLI that is not a messenger: gcal, drive, zoom. A messenger's is `doctorCommand(messenger)`, and both
|
|
123
|
+
* say the same thing: the state from disk, and only with `--online` a call out. Here that call is `options.online`
|
|
124
|
+
* and, with `options.packageName`, whether npm has a newer version.
|
|
125
|
+
*/
|
|
89
126
|
export const appDoctorCommand = (app, configuration, options = {}) => profileFree(annotate(new Command("doctor"), {
|
|
90
|
-
effects:
|
|
127
|
+
effects: REMOTE_READ,
|
|
91
128
|
examples: [`${app.command} doctor`, `${app.command} doctor --json`],
|
|
92
129
|
}))
|
|
93
|
-
.description(
|
|
94
|
-
.
|
|
95
|
-
|
|
130
|
+
.description(DOCTOR_SUMMARY)
|
|
131
|
+
.option("--online", DOCTOR_ONLINE_OPTION)
|
|
132
|
+
.action(async function () {
|
|
133
|
+
const environment = environmentOf(this);
|
|
134
|
+
const env = environment.env ?? process.env;
|
|
96
135
|
const { report, fixes } = appDoctorReport(app, configuration, env, this, options);
|
|
136
|
+
const online = this.opts().online
|
|
137
|
+
? await onlineCheck(app, env, environment.fetch ?? fetch, options)
|
|
138
|
+
: undefined;
|
|
97
139
|
const output = outputFor(this);
|
|
98
|
-
renderAnswer(this, output, itemOf(report));
|
|
140
|
+
renderAnswer(this, output, itemOf(online ? { ...report, online } : report));
|
|
99
141
|
for (const fix of fixes)
|
|
100
142
|
output.renderer.note(`to make it private: ${fix}`);
|
|
101
143
|
});
|
|
@@ -10,6 +10,7 @@ import { FloodMemory, floodPathFor } from "../../sends/flood.js";
|
|
|
10
10
|
import { SendJournal, sendsPathFor } from "../../sends/journal.js";
|
|
11
11
|
import { storePath } from "../../store/path.js";
|
|
12
12
|
import { baseContext, environmentOf, outputFor } from "../context.js";
|
|
13
|
+
import { DOCTOR_ONLINE_OPTION, DOCTOR_SUMMARY } from "../doctor-text.js";
|
|
13
14
|
import { destroysNothing, LOCAL_WRITE, NO_EFFECTS, REMOTE_READ } from "../effects.js";
|
|
14
15
|
import { itemOf, renderAnswer, snakeKeys } from "../envelope.js";
|
|
15
16
|
import { unknownPermissionIssues } from "../permission-keys.js";
|
|
@@ -28,8 +29,8 @@ import { storeSummary } from "./store-maintenance-command.js";
|
|
|
28
29
|
*/
|
|
29
30
|
export const doctorCommand = (messenger) => {
|
|
30
31
|
const command = annotate(new Command("doctor"), { effects: REMOTE_READ })
|
|
31
|
-
.description(
|
|
32
|
-
.option("--online",
|
|
32
|
+
.description(DOCTOR_SUMMARY)
|
|
33
|
+
.option("--online", DOCTOR_ONLINE_OPTION)
|
|
33
34
|
.action(async function () {
|
|
34
35
|
const { online } = this.opts();
|
|
35
36
|
const { report, renderer, fixes = [] } = await diagnose(this, messenger);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.505.0",
|
|
4
4
|
"description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|