@wirecat/cli-base 0.70.0 → 0.71.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
@@ -8,6 +8,20 @@ Versions before 0.8.0 are in the [git tags](https://github.com/WireCatLabs/cli-b
8
8
  Every entry says what changed as a caller sees it, why, and what to watch for — the rules are
9
9
  [`docs/dev/CONVENTIONS.md`](docs/dev/CONVENTIONS.md#the-changelog).
10
10
 
11
+ ## 0.71.0 — 01.11.2026
12
+
13
+ ### Added
14
+
15
+ - **A vocabulary flag can list the value names other domains give it (`otherValues`).** `--to` stays `<chat>` and also
16
+ takes `<address>` (mail); `--subject` stays `<ref>` and also takes `<text>`. `flag-two-meanings` accepts those and
17
+ reports any other value name. A CLI that declares `--to <address>` or `--subject <text>` needs no override.
18
+
19
+ ### Fixed
20
+
21
+ - **0.70.0 made every messenger CLI fail `flag-two-meanings`.** It wrote `--to` as `<chat|address>` and `--subject`
22
+ as `<ref|text>`, and the lint compares the value name as written, so `--to <chat>` was reported. Both go back to
23
+ the original value name, and mail's names are listed beside them. Do not use 0.70.0.
24
+
11
25
  ## 0.70.0 — 01.11.2026
12
26
 
13
27
  ### Added
package/dist/dev/lint.js CHANGED
@@ -229,7 +229,10 @@ const CHECKS = {
229
229
  }));
230
230
  },
231
231
  "flag-two-meanings": (document, vocabulary) => {
232
- const registered = new Map(vocabulary.flags.map((flag) => [flag.name, flag.value?.slice(1, -1).toLowerCase() ?? "switch"]));
232
+ const registered = new Map(vocabulary.flags.map((flag) => [
233
+ flag.name,
234
+ [flag.value?.slice(1, -1).toLowerCase() ?? "switch", ...(flag.otherValues ?? [])],
235
+ ]));
233
236
  const uses = new Map();
234
237
  const note = (option, where) => {
235
238
  const name = longName(option.flags);
@@ -246,8 +249,8 @@ const CHECKS = {
246
249
  const found = [];
247
250
  for (const [name, kinds] of [...uses].sort(([a], [b]) => byText(a, b))) {
248
251
  const expected = registered.get(name);
249
- const off = expected === undefined ? [] : [...kinds.keys()].filter((kind) => kind !== expected);
250
- if (kinds.size < 2 && off.length === 0)
252
+ const off = expected === undefined ? [] : [...kinds.keys()].filter((kind) => !expected.includes(kind));
253
+ if (expected === undefined ? kinds.size < 2 : off.length === 0)
251
254
  continue;
252
255
  const described = [...kinds]
253
256
  .map(([kind, where]) => `${kind === "switch" ? "a switch" : `<${kind}>`} in ${where.slice(0, 3).join(", ")}`)
@@ -256,7 +259,7 @@ const CHECKS = {
256
259
  target: name,
257
260
  message: expected === undefined
258
261
  ? `${name} has ${kinds.size} meanings: ${described}`
259
- : `${name} is ${expected === "switch" ? "a switch" : `<${expected}>`} in the vocabulary, but: ${described}`,
262
+ : `${name} is ${expected[0] === "switch" ? "a switch" : expected.map((kind) => `<${kind}>`).join(" or ")} in the vocabulary, but: ${described}`,
260
263
  });
261
264
  }
262
265
  return found;
@@ -444,10 +444,11 @@ export const WHAT_FLAGS = [
444
444
  { name: "--task", value: "<id>", role: "target", type: "id", meaning: "a task, by id" },
445
445
  {
446
446
  name: "--to",
447
- value: "<chat|address>",
447
+ value: "<chat>",
448
448
  role: "target",
449
- type: "string",
450
- meaning: "who it goes to: a chat in a messenger, an e-mail address in mail; repeat it for more addresses",
449
+ type: "id",
450
+ otherValues: ["address"],
451
+ meaning: "who it goes to: a chat in a messenger (<chat>), an e-mail address in mail (<address>, repeated for more)",
451
452
  },
452
453
  {
453
454
  name: "--topic-name",
@@ -895,10 +896,11 @@ export const WHAT_FLAGS = [
895
896
  { name: "--sticker", value: "<id>", role: "value", type: "id", meaning: "send this sticker, alone" },
896
897
  {
897
898
  name: "--subject",
898
- value: "<ref|text>",
899
+ value: "<ref>",
899
900
  role: "value",
900
901
  type: "string",
901
- meaning: "what it is about: a reference in a note or task, the subject line in mail",
902
+ otherValues: ["text"],
903
+ meaning: "what it is about: a reference in a note or task (<ref>), the subject line in mail (<text>)",
902
904
  replaces: ["--about"],
903
905
  },
904
906
  {
@@ -43,6 +43,11 @@ export declare const vocabularySchema: v.StrictObjectSchema<{
43
43
  readonly type: v.PicklistSchema<readonly ["switch", "count", "number", "string", "id", "time", "duration", "choice", "list", "path", "cursor"], undefined>;
44
44
  readonly role: v.PicklistSchema<["action" | "budget" | "mode" | "output" | "paging" | "query" | "scope" | "sort" | "target" | "value", ...("action" | "budget" | "mode" | "output" | "paging" | "query" | "scope" | "sort" | "target" | "value")[]], undefined>;
45
45
  readonly meaning: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "must not be empty">]>;
46
+ /**
47
+ * Value names a domain other than the main one gives the flag, such as mail's `--to <address>` beside the
48
+ * messengers' `<chat>`. The meaning for each says which is which. `flag-two-meanings` accepts these and no others.
49
+ */
50
+ readonly otherValues: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a value name such as address">]>, undefined>, undefined>;
46
51
  readonly unit: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "must not be empty">]>, undefined>;
47
52
  /** Other names for the same flag, which `flag-synonym` refuses. */
48
53
  readonly replaces: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a long flag">]>, undefined>, undefined>;
@@ -49,6 +49,11 @@ const flagSchema = v.strictObject({
49
49
  type: v.picklist(FLAG_TYPES),
50
50
  role: v.picklist(Object.keys(FLAG_ROLES)),
51
51
  meaning: text,
52
+ /**
53
+ * Value names a domain other than the main one gives the flag, such as mail's `--to <address>` beside the
54
+ * messengers' `<chat>`. The meaning for each says which is which. `flag-two-meanings` accepts these and no others.
55
+ */
56
+ otherValues: v.optional(v.array(v.pipe(v.string(), v.regex(/^[a-z][a-z0-9-]*$/, "a value name such as address")))),
52
57
  unit: v.optional(text),
53
58
  /** Other names for the same flag, which `flag-synonym` refuses. */
54
59
  replaces: v.optional(v.array(v.pipe(v.string(), v.regex(/^--[a-z][a-z0-9]*(-[a-z0-9]+)*$/, "a long flag")))),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-base",
3
- "version": "0.70.0",
3
+ "version": "0.71.0",
4
4
  "description": "The parts every command line tool needs: output modes, terminal rendering, error model, exit codes, credentials, clocks",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Viacheslav Ptsarev",