@doist/cli-core 0.3.0 → 0.5.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 +12 -0
- package/dist/empty.d.ts +15 -0
- package/dist/empty.d.ts.map +1 -0
- package/dist/empty.js +21 -0
- package/dist/empty.js.map +1 -0
- package/dist/global-args.d.ts +129 -0
- package/dist/global-args.d.ts.map +1 -0
- package/dist/global-args.js +175 -0
- package/dist/global-args.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/options.d.ts +14 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +2 -0
- package/dist/options.js.map +1 -0
- package/dist/testing.d.ts +21 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +56 -0
- package/dist/testing.js.map +1 -0
- package/package.json +13 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [0.5.0](https://github.com/Doist/cli-core/compare/v0.4.0...v0.5.0) (2026-05-08)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* add global args parser + factories ([#7](https://github.com/Doist/cli-core/issues/7)) ([419243e](https://github.com/Doist/cli-core/commit/419243e8543f180e15a2f6efe91d99a4c93bee40))
|
|
6
|
+
|
|
7
|
+
## [0.4.0](https://github.com/Doist/cli-core/compare/v0.3.0...v0.4.0) (2026-05-08)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* add printEmpty + describeEmptyMachineOutput helpers ([#6](https://github.com/Doist/cli-core/issues/6)) ([2c0a74e](https://github.com/Doist/cli-core/commit/2c0a74e7874ef47184a071f9fc15f22f254ca20a))
|
|
12
|
+
|
|
1
13
|
## [0.3.0](https://github.com/Doist/cli-core/compare/v0.2.0...v0.3.0) (2026-05-06)
|
|
2
14
|
|
|
3
15
|
### Features
|
package/dist/empty.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ViewOptions } from './options.js';
|
|
2
|
+
/**
|
|
3
|
+
* Gate the empty-state print on the active output mode:
|
|
4
|
+
* --json → prints exactly `'[]'`
|
|
5
|
+
* --ndjson → prints nothing (no stray newline; ndjson EOF = end of stream)
|
|
6
|
+
* neither → prints the human-readable message
|
|
7
|
+
*
|
|
8
|
+
* Use at every list/array empty-result branch so machine consumers never see
|
|
9
|
+
* human strings on stdout when they asked for `--json` / `--ndjson`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function printEmpty({ options, message }: {
|
|
12
|
+
options: ViewOptions;
|
|
13
|
+
message: string;
|
|
14
|
+
}): void;
|
|
15
|
+
//# sourceMappingURL=empty.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty.d.ts","sourceRoot":"","sources":["../src/empty.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAShG"}
|
package/dist/empty.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { formatJson } from './json.js';
|
|
2
|
+
/**
|
|
3
|
+
* Gate the empty-state print on the active output mode:
|
|
4
|
+
* --json → prints exactly `'[]'`
|
|
5
|
+
* --ndjson → prints nothing (no stray newline; ndjson EOF = end of stream)
|
|
6
|
+
* neither → prints the human-readable message
|
|
7
|
+
*
|
|
8
|
+
* Use at every list/array empty-result branch so machine consumers never see
|
|
9
|
+
* human strings on stdout when they asked for `--json` / `--ndjson`.
|
|
10
|
+
*/
|
|
11
|
+
export function printEmpty({ options, message }) {
|
|
12
|
+
if (options.json) {
|
|
13
|
+
console.log(formatJson([]));
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (options.ndjson) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
console.log(message);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=empty.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty.js","sourceRoot":"","sources":["../src/empty.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAGtC;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,EAA6C;IACtF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAA;QAC3B,OAAM;IACV,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACjB,OAAM;IACV,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;AACxB,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized, type-safe parsing of well-known global CLI flags shared
|
|
3
|
+
* across the Doist CLIs.
|
|
4
|
+
*
|
|
5
|
+
* Replaces scattered `process.argv.includes()` checks with a single parse
|
|
6
|
+
* that correctly handles grouped short flags (e.g., `-vq`), repeated flags
|
|
7
|
+
* (e.g., `-vvv`), `--flag=value` forms, and avoids false-positives from
|
|
8
|
+
* option values.
|
|
9
|
+
*
|
|
10
|
+
* The parser is pure — pass an explicit argv for testing, or use
|
|
11
|
+
* `createGlobalArgsStore` for the lazy-cached singleton pattern. The store
|
|
12
|
+
* is generic so per-CLI extensions (e.g. todoist's `--user`/`--raw`,
|
|
13
|
+
* twist's `--non-interactive`) can layer their own fields over `GlobalArgs`.
|
|
14
|
+
*/
|
|
15
|
+
import type { ViewOptions } from './options.js';
|
|
16
|
+
export type GlobalArgs = Required<Pick<ViewOptions, 'json' | 'ndjson'>> & {
|
|
17
|
+
quiet: boolean;
|
|
18
|
+
verbose: 0 | 1 | 2 | 3 | 4;
|
|
19
|
+
accessible: boolean;
|
|
20
|
+
noSpinner: boolean;
|
|
21
|
+
/** false = absent, true = present without path, string = path. */
|
|
22
|
+
progressJsonl: string | true | false;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Parse well-known global flags from `argv`. Pure — pass an explicit array
|
|
26
|
+
* for testing, or omit to read `process.argv.slice(2)`.
|
|
27
|
+
*
|
|
28
|
+
* The parser scans the entire argv: a CLI-specific positional that happens
|
|
29
|
+
* to look like a global short flag (`td comment add 123 -q`) will flip the
|
|
30
|
+
* matching global state. Workaround: use the standard `--` terminator
|
|
31
|
+
* (`td comment add 123 -- -q`) so the parser stops before the positional.
|
|
32
|
+
* The trade-off is intentional — callers run this before Commander has
|
|
33
|
+
* parsed argv, so we can't yet distinguish positionals from option values.
|
|
34
|
+
*
|
|
35
|
+
* `--progress-jsonl` accepts only the bare form (output to stderr) and the
|
|
36
|
+
* `--progress-jsonl=path` form. The space-separated `--progress-jsonl path`
|
|
37
|
+
* form is intentionally unsupported because it silently consumes the next
|
|
38
|
+
* positional argument (e.g., `td task add --progress-jsonl "Buy milk"`
|
|
39
|
+
* would treat `Buy milk` as a file path).
|
|
40
|
+
*/
|
|
41
|
+
export declare function parseGlobalArgs(argv?: string[]): GlobalArgs;
|
|
42
|
+
export type GlobalArgsStore<T extends GlobalArgs = GlobalArgs> = {
|
|
43
|
+
get(): T;
|
|
44
|
+
/** Clear the cached parse result. Call from test teardown. */
|
|
45
|
+
reset(): void;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Lazy-cached singleton wrapper around a parser function. Each CLI builds
|
|
49
|
+
* one store at startup; callers read via `store.get()`. Tests reset between
|
|
50
|
+
* cases so a mutated `process.argv` is re-parsed on next access.
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* // Vanilla — canonical fields only.
|
|
54
|
+
* const store = createGlobalArgsStore()
|
|
55
|
+
* export const isJsonMode = () => store.get().json
|
|
56
|
+
* export const resetGlobalArgs = store.reset
|
|
57
|
+
*
|
|
58
|
+
* // Extended — layer CLI-specific fields over GlobalArgs.
|
|
59
|
+
* type CliArgs = GlobalArgs & { user: string | undefined; raw: boolean }
|
|
60
|
+
* const store = createGlobalArgsStore<CliArgs>(() => {
|
|
61
|
+
* const base = parseGlobalArgs()
|
|
62
|
+
* const argv = process.argv.slice(2)
|
|
63
|
+
* return { ...base, user: parseUser(argv), raw: argv.includes('--raw') }
|
|
64
|
+
* })
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function createGlobalArgsStore(): GlobalArgsStore<GlobalArgs>;
|
|
68
|
+
export declare function createGlobalArgsStore<T extends GlobalArgs>(parse: () => T): GlobalArgsStore<T>;
|
|
69
|
+
export declare function isProgressJsonlEnabled(args: GlobalArgs): boolean;
|
|
70
|
+
export declare function getProgressJsonlPath(args: GlobalArgs): string | undefined;
|
|
71
|
+
export type AccessibleGateOptions = {
|
|
72
|
+
/** Env var that, when set to `'1'`, forces accessible mode (e.g. `TD_ACCESSIBLE`). */
|
|
73
|
+
envVar: string;
|
|
74
|
+
getArgs: () => GlobalArgs;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Build an `isAccessible` predicate that combines the `--accessible` flag
|
|
78
|
+
* with a CLI-specific opt-in env var (e.g. `TD_ACCESSIBLE=1`).
|
|
79
|
+
*
|
|
80
|
+
* ```ts
|
|
81
|
+
* const store = createGlobalArgsStore()
|
|
82
|
+
* export const isAccessible = createAccessibleGate({
|
|
83
|
+
* envVar: 'TD_ACCESSIBLE',
|
|
84
|
+
* getArgs: store.get,
|
|
85
|
+
* })
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export declare function createAccessibleGate(opts: AccessibleGateOptions): () => boolean;
|
|
89
|
+
export type SpinnerGateOptions = {
|
|
90
|
+
/** Env var that, when set to `'false'`, force-disables the spinner (e.g. `TD_SPINNER`). */
|
|
91
|
+
envVar: string;
|
|
92
|
+
getArgs: () => GlobalArgs;
|
|
93
|
+
/**
|
|
94
|
+
* CLI-specific extra disable triggers — e.g. twist returns true when
|
|
95
|
+
* `--non-interactive` is set. Evaluated only after the canonical checks
|
|
96
|
+
* already returned false.
|
|
97
|
+
*/
|
|
98
|
+
extraTriggers?: () => boolean;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Build a `shouldDisableSpinner` predicate. Disables on:
|
|
102
|
+
* - env var equals `'false'`
|
|
103
|
+
* - `isCI()`
|
|
104
|
+
* - any of `--json`, `--ndjson`, `--no-spinner`, `--progress-jsonl`, `--verbose`
|
|
105
|
+
* - `extraTriggers?.()` returning true
|
|
106
|
+
*
|
|
107
|
+
* Pair with `createSpinner({ isDisabled })` from `./spinner.js`.
|
|
108
|
+
*
|
|
109
|
+
* ```ts
|
|
110
|
+
* const store = createGlobalArgsStore()
|
|
111
|
+
*
|
|
112
|
+
* // todoist: env var + canonical flags only.
|
|
113
|
+
* const shouldDisableSpinner = createSpinnerGate({
|
|
114
|
+
* envVar: 'TD_SPINNER',
|
|
115
|
+
* getArgs: store.get,
|
|
116
|
+
* })
|
|
117
|
+
*
|
|
118
|
+
* // twist: also disable when --non-interactive is set.
|
|
119
|
+
* const shouldDisableSpinner = createSpinnerGate({
|
|
120
|
+
* envVar: 'TW_SPINNER',
|
|
121
|
+
* getArgs: store.get,
|
|
122
|
+
* extraTriggers: () => isNonInteractive(),
|
|
123
|
+
* })
|
|
124
|
+
*
|
|
125
|
+
* const { withSpinner } = createSpinner({ isDisabled: shouldDisableSpinner })
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export declare function createSpinnerGate(opts: SpinnerGateOptions): () => boolean;
|
|
129
|
+
//# sourceMappingURL=global-args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-args.d.ts","sourceRoot":"","sources":["../src/global-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG/C,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,GAAG;IACtE,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC1B,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,kEAAkE;IAClE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,CAAA;CACvC,CAAA;AAOD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,UAAU,CAiD3D;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,IAAI;IAC7D,GAAG,IAAI,CAAC,CAAA;IACR,8DAA8D;IAC9D,KAAK,IAAI,IAAI,CAAA;CAChB,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAAC,UAAU,CAAC,CAAA;AACpE,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AAkB/F,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAEhE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAEzE;AAED,MAAM,MAAM,qBAAqB,GAAG;IAChC,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,UAAU,CAAA;CAC5B,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,OAAO,CAE/E;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC7B,2FAA2F;IAC3F,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,UAAU,CAAA;IACzB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,OAAO,CAAA;CAChC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,OAAO,CAgBzE"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized, type-safe parsing of well-known global CLI flags shared
|
|
3
|
+
* across the Doist CLIs.
|
|
4
|
+
*
|
|
5
|
+
* Replaces scattered `process.argv.includes()` checks with a single parse
|
|
6
|
+
* that correctly handles grouped short flags (e.g., `-vq`), repeated flags
|
|
7
|
+
* (e.g., `-vvv`), `--flag=value` forms, and avoids false-positives from
|
|
8
|
+
* option values.
|
|
9
|
+
*
|
|
10
|
+
* The parser is pure — pass an explicit argv for testing, or use
|
|
11
|
+
* `createGlobalArgsStore` for the lazy-cached singleton pattern. The store
|
|
12
|
+
* is generic so per-CLI extensions (e.g. todoist's `--user`/`--raw`,
|
|
13
|
+
* twist's `--non-interactive`) can layer their own fields over `GlobalArgs`.
|
|
14
|
+
*/
|
|
15
|
+
import { isCI } from './terminal.js';
|
|
16
|
+
const SHORT_FLAGS = {
|
|
17
|
+
q: 'quiet',
|
|
18
|
+
v: 'verbose',
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Parse well-known global flags from `argv`. Pure — pass an explicit array
|
|
22
|
+
* for testing, or omit to read `process.argv.slice(2)`.
|
|
23
|
+
*
|
|
24
|
+
* The parser scans the entire argv: a CLI-specific positional that happens
|
|
25
|
+
* to look like a global short flag (`td comment add 123 -q`) will flip the
|
|
26
|
+
* matching global state. Workaround: use the standard `--` terminator
|
|
27
|
+
* (`td comment add 123 -- -q`) so the parser stops before the positional.
|
|
28
|
+
* The trade-off is intentional — callers run this before Commander has
|
|
29
|
+
* parsed argv, so we can't yet distinguish positionals from option values.
|
|
30
|
+
*
|
|
31
|
+
* `--progress-jsonl` accepts only the bare form (output to stderr) and the
|
|
32
|
+
* `--progress-jsonl=path` form. The space-separated `--progress-jsonl path`
|
|
33
|
+
* form is intentionally unsupported because it silently consumes the next
|
|
34
|
+
* positional argument (e.g., `td task add --progress-jsonl "Buy milk"`
|
|
35
|
+
* would treat `Buy milk` as a file path).
|
|
36
|
+
*/
|
|
37
|
+
export function parseGlobalArgs(argv) {
|
|
38
|
+
const args = argv ?? process.argv.slice(2);
|
|
39
|
+
const result = {
|
|
40
|
+
json: false,
|
|
41
|
+
ndjson: false,
|
|
42
|
+
quiet: false,
|
|
43
|
+
verbose: 0,
|
|
44
|
+
accessible: false,
|
|
45
|
+
noSpinner: false,
|
|
46
|
+
progressJsonl: false,
|
|
47
|
+
};
|
|
48
|
+
for (let i = 0; i < args.length; i++) {
|
|
49
|
+
const arg = args[i];
|
|
50
|
+
if (arg === '--')
|
|
51
|
+
break;
|
|
52
|
+
if (arg === '--json') {
|
|
53
|
+
result.json = true;
|
|
54
|
+
}
|
|
55
|
+
else if (arg === '--ndjson') {
|
|
56
|
+
result.ndjson = true;
|
|
57
|
+
}
|
|
58
|
+
else if (arg === '--quiet') {
|
|
59
|
+
result.quiet = true;
|
|
60
|
+
}
|
|
61
|
+
else if (arg === '--verbose') {
|
|
62
|
+
result.verbose = Math.min(result.verbose + 1, 4);
|
|
63
|
+
}
|
|
64
|
+
else if (arg === '--accessible') {
|
|
65
|
+
result.accessible = true;
|
|
66
|
+
}
|
|
67
|
+
else if (arg === '--no-spinner') {
|
|
68
|
+
result.noSpinner = true;
|
|
69
|
+
}
|
|
70
|
+
else if (arg === '--progress-jsonl') {
|
|
71
|
+
result.progressJsonl = true;
|
|
72
|
+
}
|
|
73
|
+
else if (arg.startsWith('--progress-jsonl=')) {
|
|
74
|
+
result.progressJsonl = arg.slice('--progress-jsonl='.length);
|
|
75
|
+
}
|
|
76
|
+
else if (arg.length > 1 && arg[0] === '-' && arg[1] !== '-') {
|
|
77
|
+
// Short-flag group: -v, -vq, -vvv, etc. Unknown shorts are
|
|
78
|
+
// silently ignored — they belong to Commander or subcommands.
|
|
79
|
+
for (let j = 1; j < arg.length; j++) {
|
|
80
|
+
const mapped = SHORT_FLAGS[arg[j]];
|
|
81
|
+
if (mapped === 'verbose') {
|
|
82
|
+
result.verbose = Math.min(result.verbose + 1, 4);
|
|
83
|
+
}
|
|
84
|
+
else if (mapped === 'quiet') {
|
|
85
|
+
result.quiet = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
export function createGlobalArgsStore(parse) {
|
|
93
|
+
// Overloads ensure callers passing a custom `T` must supply a matching
|
|
94
|
+
// parser; the implementation default only kicks in for the no-arg
|
|
95
|
+
// canonical case where `T` collapses to `GlobalArgs`.
|
|
96
|
+
const parser = parse ?? parseGlobalArgs;
|
|
97
|
+
let cached = null;
|
|
98
|
+
return {
|
|
99
|
+
get() {
|
|
100
|
+
if (cached === null)
|
|
101
|
+
cached = parser();
|
|
102
|
+
return cached;
|
|
103
|
+
},
|
|
104
|
+
reset() {
|
|
105
|
+
cached = null;
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export function isProgressJsonlEnabled(args) {
|
|
110
|
+
return args.progressJsonl !== false;
|
|
111
|
+
}
|
|
112
|
+
export function getProgressJsonlPath(args) {
|
|
113
|
+
return typeof args.progressJsonl === 'string' ? args.progressJsonl : undefined;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Build an `isAccessible` predicate that combines the `--accessible` flag
|
|
117
|
+
* with a CLI-specific opt-in env var (e.g. `TD_ACCESSIBLE=1`).
|
|
118
|
+
*
|
|
119
|
+
* ```ts
|
|
120
|
+
* const store = createGlobalArgsStore()
|
|
121
|
+
* export const isAccessible = createAccessibleGate({
|
|
122
|
+
* envVar: 'TD_ACCESSIBLE',
|
|
123
|
+
* getArgs: store.get,
|
|
124
|
+
* })
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export function createAccessibleGate(opts) {
|
|
128
|
+
return () => process.env[opts.envVar] === '1' || opts.getArgs().accessible;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Build a `shouldDisableSpinner` predicate. Disables on:
|
|
132
|
+
* - env var equals `'false'`
|
|
133
|
+
* - `isCI()`
|
|
134
|
+
* - any of `--json`, `--ndjson`, `--no-spinner`, `--progress-jsonl`, `--verbose`
|
|
135
|
+
* - `extraTriggers?.()` returning true
|
|
136
|
+
*
|
|
137
|
+
* Pair with `createSpinner({ isDisabled })` from `./spinner.js`.
|
|
138
|
+
*
|
|
139
|
+
* ```ts
|
|
140
|
+
* const store = createGlobalArgsStore()
|
|
141
|
+
*
|
|
142
|
+
* // todoist: env var + canonical flags only.
|
|
143
|
+
* const shouldDisableSpinner = createSpinnerGate({
|
|
144
|
+
* envVar: 'TD_SPINNER',
|
|
145
|
+
* getArgs: store.get,
|
|
146
|
+
* })
|
|
147
|
+
*
|
|
148
|
+
* // twist: also disable when --non-interactive is set.
|
|
149
|
+
* const shouldDisableSpinner = createSpinnerGate({
|
|
150
|
+
* envVar: 'TW_SPINNER',
|
|
151
|
+
* getArgs: store.get,
|
|
152
|
+
* extraTriggers: () => isNonInteractive(),
|
|
153
|
+
* })
|
|
154
|
+
*
|
|
155
|
+
* const { withSpinner } = createSpinner({ isDisabled: shouldDisableSpinner })
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export function createSpinnerGate(opts) {
|
|
159
|
+
return () => {
|
|
160
|
+
if (process.env[opts.envVar] === 'false')
|
|
161
|
+
return true;
|
|
162
|
+
if (isCI())
|
|
163
|
+
return true;
|
|
164
|
+
const args = opts.getArgs();
|
|
165
|
+
if (args.json ||
|
|
166
|
+
args.ndjson ||
|
|
167
|
+
args.noSpinner ||
|
|
168
|
+
isProgressJsonlEnabled(args) ||
|
|
169
|
+
args.verbose > 0) {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
return opts.extraTriggers?.() ?? false;
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=global-args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-args.js","sourceRoot":"","sources":["../src/global-args.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
export { BROKEN_CONFIG_STATE_TO_CODE, getConfigPath, readConfig, readConfigStrict, updateConfig, writeConfig, } from './config.js';
|
|
2
2
|
export type { ConfigErrorCode, ReadConfigStrictResult, WriteConfigOptions } from './config.js';
|
|
3
|
+
export { printEmpty } from './empty.js';
|
|
3
4
|
export { CliError } from './errors.js';
|
|
4
5
|
export type { CliErrorCode, CliErrorOptions, ErrorType } from './errors.js';
|
|
6
|
+
export { createAccessibleGate, createGlobalArgsStore, createSpinnerGate, getProgressJsonlPath, isProgressJsonlEnabled, parseGlobalArgs, } from './global-args.js';
|
|
7
|
+
export type { AccessibleGateOptions, GlobalArgs, GlobalArgsStore, SpinnerGateOptions, } from './global-args.js';
|
|
5
8
|
export { formatJson, formatNdjson } from './json.js';
|
|
9
|
+
export type { ViewOptions } from './options.js';
|
|
6
10
|
export { createSpinner } from './spinner.js';
|
|
7
11
|
export type { LoadingSpinner, SpinnerColor, SpinnerConfig, SpinnerKit, SpinnerOptions, } from './spinner.js';
|
|
8
12
|
export { isCI, isStderrTTY, isStdinTTY, isStdoutTTY } from './terminal.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,2BAA2B,EAC3B,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,GACd,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAC9F,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC3E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,YAAY,EACR,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,cAAc,GACjB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,2BAA2B,EAC3B,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,GACd,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAC9F,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC3E,OAAO,EACH,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACR,qBAAqB,EACrB,UAAU,EACV,eAAe,EACf,kBAAkB,GACrB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACpD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,YAAY,EACR,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,cAAc,GACjB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { BROKEN_CONFIG_STATE_TO_CODE, getConfigPath, readConfig, readConfigStrict, updateConfig, writeConfig, } from './config.js';
|
|
2
|
+
export { printEmpty } from './empty.js';
|
|
2
3
|
export { CliError } from './errors.js';
|
|
4
|
+
export { createAccessibleGate, createGlobalArgsStore, createSpinnerGate, getProgressJsonlPath, isProgressJsonlEnabled, parseGlobalArgs, } from './global-args.js';
|
|
3
5
|
export { formatJson, formatNdjson } from './json.js';
|
|
4
6
|
export { createSpinner } from './spinner.js';
|
|
5
7
|
export { isCI, isStderrTTY, isStdinTTY, isStdoutTTY } from './terminal.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,2BAA2B,EAC3B,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,GACd,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,2BAA2B,EAC3B,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,GACd,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC,OAAO,EACH,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,GAClB,MAAM,kBAAkB,CAAA;AAOzB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAQ5C,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared shape for commands that respect the canonical machine-output flags.
|
|
3
|
+
* Seeded narrow so the type only declares what cli-core helpers actually read
|
|
4
|
+
* today; will grow (`full?`, `raw?`, etc.) as the global-args parser extraction
|
|
5
|
+
* lands (see EXTRACTION_ROADMAP.md, Tier 1).
|
|
6
|
+
*
|
|
7
|
+
* Per-CLI `ViewOptions` types should extend this rather than re-declare the
|
|
8
|
+
* `json` / `ndjson` fields.
|
|
9
|
+
*/
|
|
10
|
+
export type ViewOptions = {
|
|
11
|
+
json?: boolean;
|
|
12
|
+
ndjson?: boolean;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,GAAG;IACtB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA"}
|
package/dist/options.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
type EmptyOutputConfig = {
|
|
2
|
+
setup: () => void | Promise<void>;
|
|
3
|
+
run: (extraArgs: string[]) => Promise<void>;
|
|
4
|
+
humanMessage: string | RegExp;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Asserts the standard `printEmpty` contract for a command:
|
|
8
|
+
* --json → writes exactly `'[]\n'` to stdout
|
|
9
|
+
* --ndjson → writes nothing to stdout (no stray newline)
|
|
10
|
+
* neither → writes exactly the human message + `\n` to stdout
|
|
11
|
+
*
|
|
12
|
+
* Captures bytes from both `console.log` (which vitest intercepts before
|
|
13
|
+
* it reaches the real stream) and `process.stdout.write`, so commands
|
|
14
|
+
* using either pathway satisfy the contract.
|
|
15
|
+
*
|
|
16
|
+
* Spies are installed AFTER `setup` so any `vi.clearAllMocks()` inside
|
|
17
|
+
* `setup` doesn't clobber them.
|
|
18
|
+
*/
|
|
19
|
+
export declare function describeEmptyMachineOutput(label: string, config: EmptyOutputConfig): void;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAEA,KAAK,iBAAiB,GAAG;IACrB,KAAK,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,GAAG,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3C,YAAY,EAAE,MAAM,GAAG,MAAM,CAAA;CAChC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CA8CzF"}
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
/**
|
|
3
|
+
* Asserts the standard `printEmpty` contract for a command:
|
|
4
|
+
* --json → writes exactly `'[]\n'` to stdout
|
|
5
|
+
* --ndjson → writes nothing to stdout (no stray newline)
|
|
6
|
+
* neither → writes exactly the human message + `\n` to stdout
|
|
7
|
+
*
|
|
8
|
+
* Captures bytes from both `console.log` (which vitest intercepts before
|
|
9
|
+
* it reaches the real stream) and `process.stdout.write`, so commands
|
|
10
|
+
* using either pathway satisfy the contract.
|
|
11
|
+
*
|
|
12
|
+
* Spies are installed AFTER `setup` so any `vi.clearAllMocks()` inside
|
|
13
|
+
* `setup` doesn't clobber them.
|
|
14
|
+
*/
|
|
15
|
+
export function describeEmptyMachineOutput(label, config) {
|
|
16
|
+
describe(label, () => {
|
|
17
|
+
let captured = '';
|
|
18
|
+
let consoleSpy;
|
|
19
|
+
let writeSpy;
|
|
20
|
+
beforeEach(async () => {
|
|
21
|
+
await config.setup();
|
|
22
|
+
captured = '';
|
|
23
|
+
consoleSpy = vi.spyOn(console, 'log').mockImplementation((...args) => {
|
|
24
|
+
captured += `${args.map((a) => (typeof a === 'string' ? a : String(a))).join(' ')}\n`;
|
|
25
|
+
});
|
|
26
|
+
writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(((chunk) => {
|
|
27
|
+
captured += typeof chunk === 'string' ? chunk : chunk.toString();
|
|
28
|
+
return true;
|
|
29
|
+
}));
|
|
30
|
+
});
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
consoleSpy?.mockRestore();
|
|
33
|
+
writeSpy?.mockRestore();
|
|
34
|
+
consoleSpy = undefined;
|
|
35
|
+
writeSpy = undefined;
|
|
36
|
+
});
|
|
37
|
+
it('writes exactly "[]\\n" to stdout for --json', async () => {
|
|
38
|
+
await config.run(['--json']);
|
|
39
|
+
expect(captured).toBe('[]\n');
|
|
40
|
+
});
|
|
41
|
+
it('writes nothing to stdout for --ndjson (no stray newline)', async () => {
|
|
42
|
+
await config.run(['--ndjson']);
|
|
43
|
+
expect(captured).toBe('');
|
|
44
|
+
});
|
|
45
|
+
it('writes exactly the human message to stdout when no machine flag is set', async () => {
|
|
46
|
+
await config.run([]);
|
|
47
|
+
if (typeof config.humanMessage === 'string') {
|
|
48
|
+
expect(captured).toBe(`${config.humanMessage}\n`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
expect(captured).toMatch(config.humanMessage);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAQxE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,0BAA0B,CAAC,KAAa,EAAE,MAAyB;IAC/E,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE;QACjB,IAAI,QAAQ,GAAG,EAAE,CAAA;QACjB,IAAI,UAAmD,CAAA;QACvD,IAAI,QAAiD,CAAA;QAErD,UAAU,CAAC,KAAK,IAAI,EAAE;YAClB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;YACpB,QAAQ,GAAG,EAAE,CAAA;YACb,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,CAAC,GAAG,IAAe,EAAE,EAAE;gBAC5E,QAAQ,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAA;YACzF,CAAC,CAAC,CAAA;YACF,QAAQ,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAC7D,KAA0B,EACnB,EAAE;gBACT,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAA;gBAChE,OAAO,IAAI,CAAA;YACf,CAAC,CAAgC,CAAC,CAAA;QACtC,CAAC,CAAC,CAAA;QAEF,SAAS,CAAC,GAAG,EAAE;YACX,UAAU,EAAE,WAAW,EAAE,CAAA;YACzB,QAAQ,EAAE,WAAW,EAAE,CAAA;YACvB,UAAU,GAAG,SAAS,CAAA;YACtB,QAAQ,GAAG,SAAS,CAAA;QACxB,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;YAC5B,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACjC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;YACtE,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;YAC9B,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC7B,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;YACpF,MAAM,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACpB,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;gBAC1C,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,YAAY,IAAI,CAAC,CAAA;YACrD,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;YACjD,CAAC;QACL,CAAC,CAAC,CAAA;IACN,CAAC,CAAC,CAAA;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doist/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Shared core utilities for Doist CLI projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./testing": {
|
|
14
|
+
"types": "./dist/testing.d.ts",
|
|
15
|
+
"import": "./dist/testing.js"
|
|
12
16
|
}
|
|
13
17
|
},
|
|
14
18
|
"scripts": {
|
|
@@ -62,5 +66,13 @@
|
|
|
62
66
|
"dependencies": {
|
|
63
67
|
"chalk": "5.6.2",
|
|
64
68
|
"yocto-spinner": "1.1.0"
|
|
69
|
+
},
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"vitest": ">=4.1"
|
|
72
|
+
},
|
|
73
|
+
"peerDependenciesMeta": {
|
|
74
|
+
"vitest": {
|
|
75
|
+
"optional": true
|
|
76
|
+
}
|
|
65
77
|
}
|
|
66
78
|
}
|