@doist/cli-core 0.0.1 → 0.2.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/LICENSE +9 -0
- package/README.md +17 -35
- package/dist/config.d.ts +88 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +139 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +45 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +33 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +19 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +35 -0
- package/dist/json.js.map +1 -0
- package/dist/terminal.d.ts +22 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +31 -0
- package/dist/terminal.js.map +1 -0
- package/package.json +60 -8
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## [0.2.0](https://github.com/Doist/cli-core/compare/v0.1.0...v0.2.0) (2026-05-06)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* bake cli-core codes into CliError, add CliErrorCode aggregator ([#4](https://github.com/Doist/cli-core/issues/4)) ([8c0d959](https://github.com/Doist/cli-core/commit/8c0d95987db3b35b1715cd72eb603cbb99420211))
|
|
6
|
+
|
|
7
|
+
## [0.1.0](https://github.com/Doist/cli-core/compare/v0.0.1...v0.1.0) (2026-05-06)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
- add CliError + config file I/O helpers ([#1](https://github.com/Doist/cli-core/issues/1)) ([8daf2d1](https://github.com/Doist/cli-core/commit/8daf2d1f67f44f91713ffc2192b681704fa86d88))
|
|
12
|
+
- add terminal detection + JSON/NDJSON formatters ([#2](https://github.com/Doist/cli-core/issues/2)) ([f2bfde8](https://github.com/Doist/cli-core/commit/f2bfde8ff3a2a41eb402acc49223980c5d4be393))
|
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Doist
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,45 +1,27 @@
|
|
|
1
1
|
# @doist/cli-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Shared core utilities for Doist CLI projects ([todoist-cli](https://github.com/Doist/todoist-cli), [twist-cli](https://github.com/Doist/twist-cli), [outline-cli](https://github.com/Doist/outline-cli)).
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
> **Status:** scaffolding only. No exports yet — extraction work is in progress.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Install
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
```bash
|
|
10
|
+
npm install @doist/cli-core
|
|
11
|
+
```
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
1. Configure OIDC trusted publishing for the package name `@doist/cli-core`
|
|
13
|
-
2. Enable secure, token-less publishing from CI/CD workflows
|
|
14
|
-
3. Establish provenance for packages published under this name
|
|
13
|
+
## Development
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
```bash
|
|
16
|
+
npm install
|
|
17
|
+
npm run build
|
|
18
|
+
npm test
|
|
19
|
+
npm run check # lint + format
|
|
20
|
+
npm run fix # auto-fix lint + format
|
|
21
|
+
```
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
Requires Node `>=20.18.1`.
|
|
19
24
|
|
|
20
|
-
##
|
|
25
|
+
## License
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
|
|
25
|
-
2. Configure the trusted publisher (e.g., GitHub Actions)
|
|
26
|
-
3. Specify the repository and workflow that should be allowed to publish
|
|
27
|
-
4. Use the configured workflow to publish your actual package
|
|
28
|
-
|
|
29
|
-
## DO NOT USE THIS PACKAGE
|
|
30
|
-
|
|
31
|
-
This package is a placeholder for OIDC configuration only. It:
|
|
32
|
-
- Contains no executable code
|
|
33
|
-
- Provides no functionality
|
|
34
|
-
- Should not be installed as a dependency
|
|
35
|
-
- Exists only for administrative purposes
|
|
36
|
-
|
|
37
|
-
## More Information
|
|
38
|
-
|
|
39
|
-
For more details about npm's trusted publishing feature, see:
|
|
40
|
-
- [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
|
|
41
|
-
- [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
**Maintained for OIDC setup purposes only**
|
|
27
|
+
MIT
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the canonical config path for a CLI, honouring `XDG_CONFIG_HOME`
|
|
3
|
+
* when set: `${XDG_CONFIG_HOME ?? ~/.config}/<appName>/config.json`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getConfigPath(appName: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Read and parse a JSON config file leniently. Returns `{}` when the file is
|
|
8
|
+
* missing, unreadable, invalid JSON, or not a JSON object — the shape runtime
|
|
9
|
+
* code paths expect ("no config" looks the same as "empty config").
|
|
10
|
+
*
|
|
11
|
+
* The return type is `Partial<T>` because at runtime any field may be absent;
|
|
12
|
+
* the cast is the consumer's responsibility once they have validated.
|
|
13
|
+
*
|
|
14
|
+
* Use `readConfigStrict` instead when you need to distinguish failure modes
|
|
15
|
+
* (e.g. `doctor`-style inspection commands).
|
|
16
|
+
*/
|
|
17
|
+
export declare function readConfig<T extends object>(path: string): Promise<Partial<T>>;
|
|
18
|
+
export type ReadConfigStrictResult = {
|
|
19
|
+
state: 'missing';
|
|
20
|
+
} | {
|
|
21
|
+
state: 'read-failed';
|
|
22
|
+
error: Error;
|
|
23
|
+
} | {
|
|
24
|
+
state: 'invalid-json';
|
|
25
|
+
error: Error;
|
|
26
|
+
} | {
|
|
27
|
+
state: 'invalid-shape';
|
|
28
|
+
actual: 'array' | 'null' | 'number' | 'string' | 'boolean';
|
|
29
|
+
} | {
|
|
30
|
+
state: 'present';
|
|
31
|
+
config: Record<string, unknown>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Canonical CliError codes for the broken states of `readConfigStrict`. The
|
|
35
|
+
* `satisfies` clause guarantees every failure state has a corresponding code.
|
|
36
|
+
*
|
|
37
|
+
* Exported as both a runtime map (so a future `readConfigOrThrow` helper — and
|
|
38
|
+
* consumers writing their own state-to-throw translation — can look codes up
|
|
39
|
+
* instead of hand-writing strings) and as the `ConfigErrorCode` type alias.
|
|
40
|
+
*/
|
|
41
|
+
export declare const BROKEN_CONFIG_STATE_TO_CODE: {
|
|
42
|
+
readonly 'read-failed': "CONFIG_READ_FAILED";
|
|
43
|
+
readonly 'invalid-json': "CONFIG_INVALID_JSON";
|
|
44
|
+
readonly 'invalid-shape': "CONFIG_INVALID_SHAPE";
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Canonical CliError codes emitted when `readConfigStrict` reports a broken
|
|
48
|
+
* config file. Derived from `BROKEN_CONFIG_STATE_TO_CODE` so the type and the
|
|
49
|
+
* runtime map can never drift.
|
|
50
|
+
*
|
|
51
|
+
* cli-core does not throw these itself (the library returns a discriminated
|
|
52
|
+
* result so consumers control formatting), but every consumer that does the
|
|
53
|
+
* states-to-throw translation ends up using the same three codes. Including
|
|
54
|
+
* this in each CLI's `ErrorCode` union is also unnecessary now that
|
|
55
|
+
* `CliError`'s constructor accepts the cli-core canonical codes directly.
|
|
56
|
+
*/
|
|
57
|
+
export type ConfigErrorCode = (typeof BROKEN_CONFIG_STATE_TO_CODE)[keyof typeof BROKEN_CONFIG_STATE_TO_CODE];
|
|
58
|
+
/**
|
|
59
|
+
* Read and parse a JSON config file strictly, distinguishing missing files
|
|
60
|
+
* from broken ones. The library returns a discriminated result instead of
|
|
61
|
+
* throwing so consumers can format errors with their own copy/codes.
|
|
62
|
+
*
|
|
63
|
+
* `present.config` is typed as `Record<string, unknown>` because cli-core does
|
|
64
|
+
* not validate shape — only that the file parsed to a plain object. Cast or
|
|
65
|
+
* decode in the consumer.
|
|
66
|
+
*/
|
|
67
|
+
export declare function readConfigStrict(path: string): Promise<ReadConfigStrictResult>;
|
|
68
|
+
export interface WriteConfigOptions {
|
|
69
|
+
/**
|
|
70
|
+
* When true and the supplied config has no own enumerable keys, delete the
|
|
71
|
+
* file instead of writing an empty `{}`. Default false.
|
|
72
|
+
*/
|
|
73
|
+
deleteWhenEmpty?: boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Write a config file with restrictive permissions (parent dir 0700, file 0600)
|
|
77
|
+
* and a trailing newline. Creates parent directories as needed and tightens
|
|
78
|
+
* their permissions even if they already existed.
|
|
79
|
+
*/
|
|
80
|
+
export declare function writeConfig<T extends object>(path: string, config: T, options?: WriteConfigOptions): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Read the existing config strictly, shallow-merge the supplied updates, and
|
|
83
|
+
* write the result. Throws if the existing file is unreadable or unparseable
|
|
84
|
+
* to avoid silently overwriting data that a user might still recover by
|
|
85
|
+
* fixing their config file.
|
|
86
|
+
*/
|
|
87
|
+
export declare function updateConfig<T extends object>(path: string, updates: Partial<T>, options?: WriteConfigOptions): Promise<void>;
|
|
88
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAGpF;AAED,MAAM,MAAM,sBAAsB,GAC5B;IAAE,KAAK,EAAE,SAAS,CAAA;CAAE,GACpB;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GACtC;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GACvC;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;CAAE,GACtF;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAA;AAU3D;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B;;;;CAIc,CAAA;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,eAAe,GACvB,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,OAAO,2BAA2B,CAAC,CAAA;AAElF;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAqBpF;AAED,MAAM,WAAW,kBAAkB;IAC/B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;CAC5B;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,CAAC,SAAS,MAAM,EAC9C,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,kBAAuB,GACjC,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EAC/C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,OAAO,GAAE,kBAAuB,GACjC,OAAO,CAAC,IAAI,CAAC,CAoBf"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { chmod, mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { formatJson } from './json.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the canonical config path for a CLI, honouring `XDG_CONFIG_HOME`
|
|
7
|
+
* when set: `${XDG_CONFIG_HOME ?? ~/.config}/<appName>/config.json`.
|
|
8
|
+
*/
|
|
9
|
+
export function getConfigPath(appName) {
|
|
10
|
+
const base = process.env.XDG_CONFIG_HOME || join(homedir(), '.config');
|
|
11
|
+
return join(base, appName, 'config.json');
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Read and parse a JSON config file leniently. Returns `{}` when the file is
|
|
15
|
+
* missing, unreadable, invalid JSON, or not a JSON object — the shape runtime
|
|
16
|
+
* code paths expect ("no config" looks the same as "empty config").
|
|
17
|
+
*
|
|
18
|
+
* The return type is `Partial<T>` because at runtime any field may be absent;
|
|
19
|
+
* the cast is the consumer's responsibility once they have validated.
|
|
20
|
+
*
|
|
21
|
+
* Use `readConfigStrict` instead when you need to distinguish failure modes
|
|
22
|
+
* (e.g. `doctor`-style inspection commands).
|
|
23
|
+
*/
|
|
24
|
+
export async function readConfig(path) {
|
|
25
|
+
const result = await readConfigStrict(path);
|
|
26
|
+
return result.state === 'present' ? result.config : {};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Canonical CliError codes for the broken states of `readConfigStrict`. The
|
|
30
|
+
* `satisfies` clause guarantees every failure state has a corresponding code.
|
|
31
|
+
*
|
|
32
|
+
* Exported as both a runtime map (so a future `readConfigOrThrow` helper — and
|
|
33
|
+
* consumers writing their own state-to-throw translation — can look codes up
|
|
34
|
+
* instead of hand-writing strings) and as the `ConfigErrorCode` type alias.
|
|
35
|
+
*/
|
|
36
|
+
export const BROKEN_CONFIG_STATE_TO_CODE = {
|
|
37
|
+
'read-failed': 'CONFIG_READ_FAILED',
|
|
38
|
+
'invalid-json': 'CONFIG_INVALID_JSON',
|
|
39
|
+
'invalid-shape': 'CONFIG_INVALID_SHAPE',
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Read and parse a JSON config file strictly, distinguishing missing files
|
|
43
|
+
* from broken ones. The library returns a discriminated result instead of
|
|
44
|
+
* throwing so consumers can format errors with their own copy/codes.
|
|
45
|
+
*
|
|
46
|
+
* `present.config` is typed as `Record<string, unknown>` because cli-core does
|
|
47
|
+
* not validate shape — only that the file parsed to a plain object. Cast or
|
|
48
|
+
* decode in the consumer.
|
|
49
|
+
*/
|
|
50
|
+
export async function readConfigStrict(path) {
|
|
51
|
+
let content;
|
|
52
|
+
try {
|
|
53
|
+
content = await readFile(path, 'utf-8');
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (isMissingFileError(error))
|
|
57
|
+
return { state: 'missing' };
|
|
58
|
+
return { state: 'read-failed', error: toError(error) };
|
|
59
|
+
}
|
|
60
|
+
let parsed;
|
|
61
|
+
try {
|
|
62
|
+
parsed = JSON.parse(content);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return { state: 'invalid-json', error: toError(error) };
|
|
66
|
+
}
|
|
67
|
+
if (!isPlainObject(parsed)) {
|
|
68
|
+
return { state: 'invalid-shape', actual: describeNonObject(parsed) };
|
|
69
|
+
}
|
|
70
|
+
return { state: 'present', config: parsed };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Write a config file with restrictive permissions (parent dir 0700, file 0600)
|
|
74
|
+
* and a trailing newline. Creates parent directories as needed and tightens
|
|
75
|
+
* their permissions even if they already existed.
|
|
76
|
+
*/
|
|
77
|
+
export async function writeConfig(path, config, options = {}) {
|
|
78
|
+
if (options.deleteWhenEmpty && Object.keys(config).length === 0) {
|
|
79
|
+
try {
|
|
80
|
+
await unlink(path);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (!isMissingFileError(error))
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const dir = dirname(path);
|
|
89
|
+
await mkdir(dir, { recursive: true, mode: 0o700 });
|
|
90
|
+
await chmod(dir, 0o700);
|
|
91
|
+
await writeFile(path, `${formatJson(config)}\n`, {
|
|
92
|
+
encoding: 'utf-8',
|
|
93
|
+
mode: 0o600,
|
|
94
|
+
});
|
|
95
|
+
await chmod(path, 0o600);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Read the existing config strictly, shallow-merge the supplied updates, and
|
|
99
|
+
* write the result. Throws if the existing file is unreadable or unparseable
|
|
100
|
+
* to avoid silently overwriting data that a user might still recover by
|
|
101
|
+
* fixing their config file.
|
|
102
|
+
*/
|
|
103
|
+
export async function updateConfig(path, updates, options = {}) {
|
|
104
|
+
const result = await readConfigStrict(path);
|
|
105
|
+
switch (result.state) {
|
|
106
|
+
case 'missing':
|
|
107
|
+
await writeConfig(path, updates, options);
|
|
108
|
+
return;
|
|
109
|
+
case 'present':
|
|
110
|
+
await writeConfig(path, { ...result.config, ...updates }, options);
|
|
111
|
+
return;
|
|
112
|
+
case 'read-failed':
|
|
113
|
+
throw new Error(`Cannot update config at ${path}: ${result.error.message}`);
|
|
114
|
+
case 'invalid-json':
|
|
115
|
+
throw new Error(`Cannot update config at ${path}: file is not valid JSON (${result.error.message}). Fix or remove the file before retrying.`);
|
|
116
|
+
case 'invalid-shape':
|
|
117
|
+
throw new Error(`Cannot update config at ${path}: file contents are ${result.actual}, not a JSON object. Fix or remove the file before retrying.`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function isPlainObject(value) {
|
|
121
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
122
|
+
}
|
|
123
|
+
function isMissingFileError(error) {
|
|
124
|
+
return (error instanceof Error && 'code' in error && error.code === 'ENOENT');
|
|
125
|
+
}
|
|
126
|
+
function toError(value) {
|
|
127
|
+
return value instanceof Error ? value : new Error(String(value));
|
|
128
|
+
}
|
|
129
|
+
function describeNonObject(value) {
|
|
130
|
+
if (Array.isArray(value))
|
|
131
|
+
return 'array';
|
|
132
|
+
if (value === null)
|
|
133
|
+
return 'null';
|
|
134
|
+
const t = typeof value;
|
|
135
|
+
if (t === 'number' || t === 'string' || t === 'boolean')
|
|
136
|
+
return t;
|
|
137
|
+
return 'null';
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ConfigErrorCode } from './config.js';
|
|
2
|
+
export type ErrorType = 'error' | 'info';
|
|
3
|
+
export interface CliErrorOptions {
|
|
4
|
+
hints?: string[];
|
|
5
|
+
type?: ErrorType;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Aggregator of every error code that cli-core itself defines. Baked into the
|
|
9
|
+
* `CliError` constructor so consumers don't have to redeclare these strings in
|
|
10
|
+
* their own `ErrorCode` union — they're always accepted.
|
|
11
|
+
*
|
|
12
|
+
* Grows as future modules add their own well-known codes:
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* export type CliErrorCode = ConfigErrorCode | SpinnerErrorCode | …
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export type CliErrorCode = ConfigErrorCode;
|
|
19
|
+
/**
|
|
20
|
+
* Generic CLI error carrying a structured code, optional hints, and a severity
|
|
21
|
+
* type.
|
|
22
|
+
*
|
|
23
|
+
* `code` accepts either the consumer's `TCode` union or any code defined by
|
|
24
|
+
* cli-core itself (`CliErrorCode`). Pass a string-literal union as `TCode` to
|
|
25
|
+
* constrain codes per CLI; the cli-core codes are always allowed alongside.
|
|
26
|
+
*
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { CliError } from '@doist/cli-core'
|
|
29
|
+
* type Code = 'AUTH_FAILED' | 'NOT_FOUND' | (string & {})
|
|
30
|
+
* throw new CliError<Code>('AUTH_FAILED', 'Token rejected', {
|
|
31
|
+
* hints: ['Run td auth login'],
|
|
32
|
+
* })
|
|
33
|
+
* // CONFIG_INVALID_JSON also accepted without listing it in `Code`:
|
|
34
|
+
* throw new CliError<Code>('CONFIG_INVALID_JSON', 'Bad JSON')
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* The `(string & {})` trick preserves intellisense while accepting dynamic codes.
|
|
38
|
+
*/
|
|
39
|
+
export declare class CliError<TCode extends string = string> extends Error {
|
|
40
|
+
readonly code: TCode | CliErrorCode;
|
|
41
|
+
readonly hints?: string[];
|
|
42
|
+
readonly type: ErrorType;
|
|
43
|
+
constructor(code: TCode | CliErrorCode, message: string, options?: CliErrorOptions);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAA;AAExC,MAAM,WAAW,eAAe;IAC5B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,IAAI,CAAC,EAAE,SAAS,CAAA;CACnB;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,YAAY,GAAG,eAAe,CAAA;AAE1C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,QAAQ,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,KAAK;IAC9D,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,YAAY,CAAA;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;gBAEZ,IAAI,EAAE,KAAK,GAAG,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAOzF"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic CLI error carrying a structured code, optional hints, and a severity
|
|
3
|
+
* type.
|
|
4
|
+
*
|
|
5
|
+
* `code` accepts either the consumer's `TCode` union or any code defined by
|
|
6
|
+
* cli-core itself (`CliErrorCode`). Pass a string-literal union as `TCode` to
|
|
7
|
+
* constrain codes per CLI; the cli-core codes are always allowed alongside.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { CliError } from '@doist/cli-core'
|
|
11
|
+
* type Code = 'AUTH_FAILED' | 'NOT_FOUND' | (string & {})
|
|
12
|
+
* throw new CliError<Code>('AUTH_FAILED', 'Token rejected', {
|
|
13
|
+
* hints: ['Run td auth login'],
|
|
14
|
+
* })
|
|
15
|
+
* // CONFIG_INVALID_JSON also accepted without listing it in `Code`:
|
|
16
|
+
* throw new CliError<Code>('CONFIG_INVALID_JSON', 'Bad JSON')
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* The `(string & {})` trick preserves intellisense while accepting dynamic codes.
|
|
20
|
+
*/
|
|
21
|
+
export class CliError extends Error {
|
|
22
|
+
code;
|
|
23
|
+
hints;
|
|
24
|
+
type;
|
|
25
|
+
constructor(code, message, options = {}) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'CliError';
|
|
28
|
+
this.code = code;
|
|
29
|
+
this.hints = options.hints;
|
|
30
|
+
this.type = options.type ?? 'error';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,QAAwC,SAAQ,KAAK;IACrD,IAAI,CAAsB;IAC1B,KAAK,CAAW;IAChB,IAAI,CAAW;IAExB,YAAY,IAA0B,EAAE,OAAe,EAAE,UAA2B,EAAE;QAClF,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,UAAU,CAAA;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;QAC1B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAA;IACvC,CAAC;CACJ"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { BROKEN_CONFIG_STATE_TO_CODE, getConfigPath, readConfig, readConfigStrict, updateConfig, writeConfig, } from './config.js';
|
|
2
|
+
export type { ConfigErrorCode, ReadConfigStrictResult, WriteConfigOptions } from './config.js';
|
|
3
|
+
export { CliError } from './errors.js';
|
|
4
|
+
export type { CliErrorCode, CliErrorOptions, ErrorType } from './errors.js';
|
|
5
|
+
export { formatJson, formatNdjson } from './json.js';
|
|
6
|
+
export { isCI, isStderrTTY, isStdinTTY, isStdoutTTY } from './terminal.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { BROKEN_CONFIG_STATE_TO_CODE, getConfigPath, readConfig, readConfigStrict, updateConfig, writeConfig, } from './config.js';
|
|
2
|
+
export { CliError } from './errors.js';
|
|
3
|
+
export { formatJson, formatNdjson } from './json.js';
|
|
4
|
+
export { isCI, isStderrTTY, isStdinTTY, isStdoutTTY } from './terminal.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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;AACpD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/json.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pretty-print a value as JSON with 2-space indentation. Matches the canonical
|
|
3
|
+
* `--json` output style used across the Doist CLIs.
|
|
4
|
+
*
|
|
5
|
+
* Throws if `value` cannot be serialized (top-level `undefined`, a function,
|
|
6
|
+
* a symbol, or an object whose `toJSON()` returns `undefined`) so the
|
|
7
|
+
* `string` return type is honoured.
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatJson(value: unknown): string;
|
|
10
|
+
/**
|
|
11
|
+
* Format an array as newline-delimited JSON (NDJSON): one JSON value per line,
|
|
12
|
+
* separated by `\n`, with no trailing newline. Matches the canonical `--ndjson`
|
|
13
|
+
* output style used across the Doist CLIs.
|
|
14
|
+
*
|
|
15
|
+
* Throws if any item cannot be serialized — surfacing the bad index instead of
|
|
16
|
+
* silently emitting blank lines that would corrupt the output stream.
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatNdjson(items: readonly unknown[]): string;
|
|
19
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQjD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAY9D"}
|
package/dist/json.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pretty-print a value as JSON with 2-space indentation. Matches the canonical
|
|
3
|
+
* `--json` output style used across the Doist CLIs.
|
|
4
|
+
*
|
|
5
|
+
* Throws if `value` cannot be serialized (top-level `undefined`, a function,
|
|
6
|
+
* a symbol, or an object whose `toJSON()` returns `undefined`) so the
|
|
7
|
+
* `string` return type is honoured.
|
|
8
|
+
*/
|
|
9
|
+
export function formatJson(value) {
|
|
10
|
+
const result = JSON.stringify(value, null, 2);
|
|
11
|
+
if (result === undefined) {
|
|
12
|
+
throw new TypeError('formatJson: value is not JSON-serializable (got undefined, function, or symbol at top level)');
|
|
13
|
+
}
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Format an array as newline-delimited JSON (NDJSON): one JSON value per line,
|
|
18
|
+
* separated by `\n`, with no trailing newline. Matches the canonical `--ndjson`
|
|
19
|
+
* output style used across the Doist CLIs.
|
|
20
|
+
*
|
|
21
|
+
* Throws if any item cannot be serialized — surfacing the bad index instead of
|
|
22
|
+
* silently emitting blank lines that would corrupt the output stream.
|
|
23
|
+
*/
|
|
24
|
+
export function formatNdjson(items) {
|
|
25
|
+
return items
|
|
26
|
+
.map((item, i) => {
|
|
27
|
+
const line = JSON.stringify(item);
|
|
28
|
+
if (line === undefined) {
|
|
29
|
+
throw new TypeError(`formatNdjson: item at index ${i} is not JSON-serializable (got undefined, function, or symbol)`);
|
|
30
|
+
}
|
|
31
|
+
return line;
|
|
32
|
+
})
|
|
33
|
+
.join('\n');
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=json.js.map
|
package/dist/json.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC7C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CACf,8FAA8F,CACjG,CAAA;IACL,CAAC;IACD,OAAO,MAAM,CAAA;AACjB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAyB;IAClD,OAAO,KAAK;SACP,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACb,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACrB,MAAM,IAAI,SAAS,CACf,+BAA+B,CAAC,gEAAgE,CACnG,CAAA;QACL,CAAC;QACD,OAAO,IAAI,CAAA;IACf,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;AACnB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal-environment detection helpers shared across the Doist CLIs.
|
|
3
|
+
*
|
|
4
|
+
* These primitives read globals (`process.stdout.isTTY`, `process.env.CI`)
|
|
5
|
+
* directly so callers can compose them. CLI-specific fan-out — opt-out env
|
|
6
|
+
* vars like `TD_SPINNER`, `--json` flags, etc. — stays in the consuming CLI;
|
|
7
|
+
* cli-core only owns the platform signals.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isStdoutTTY(): boolean;
|
|
10
|
+
export declare function isStdinTTY(): boolean;
|
|
11
|
+
export declare function isStderrTTY(): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* True when the process appears to be running under continuous integration.
|
|
14
|
+
* Checks `process.env.CI`, which every major CI provider (GitHub Actions,
|
|
15
|
+
* GitLab, CircleCI, Buildkite, Travis, …) sets to a truthy value by
|
|
16
|
+
* convention.
|
|
17
|
+
*
|
|
18
|
+
* `CI='false'` is treated as opt-out (handy when a parent environment has
|
|
19
|
+
* `CI=true` set but a nested invocation needs to behave interactively).
|
|
20
|
+
*/
|
|
21
|
+
export declare function isCI(): boolean;
|
|
22
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED;;;;;;;;GAQG;AACH,wBAAgB,IAAI,IAAI,OAAO,CAG9B"}
|
package/dist/terminal.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal-environment detection helpers shared across the Doist CLIs.
|
|
3
|
+
*
|
|
4
|
+
* These primitives read globals (`process.stdout.isTTY`, `process.env.CI`)
|
|
5
|
+
* directly so callers can compose them. CLI-specific fan-out — opt-out env
|
|
6
|
+
* vars like `TD_SPINNER`, `--json` flags, etc. — stays in the consuming CLI;
|
|
7
|
+
* cli-core only owns the platform signals.
|
|
8
|
+
*/
|
|
9
|
+
export function isStdoutTTY() {
|
|
10
|
+
return Boolean(process.stdout.isTTY);
|
|
11
|
+
}
|
|
12
|
+
export function isStdinTTY() {
|
|
13
|
+
return Boolean(process.stdin.isTTY);
|
|
14
|
+
}
|
|
15
|
+
export function isStderrTTY() {
|
|
16
|
+
return Boolean(process.stderr.isTTY);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* True when the process appears to be running under continuous integration.
|
|
20
|
+
* Checks `process.env.CI`, which every major CI provider (GitHub Actions,
|
|
21
|
+
* GitLab, CircleCI, Buildkite, Travis, …) sets to a truthy value by
|
|
22
|
+
* convention.
|
|
23
|
+
*
|
|
24
|
+
* `CI='false'` is treated as opt-out (handy when a parent environment has
|
|
25
|
+
* `CI=true` set but a nested invocation needs to behave interactively).
|
|
26
|
+
*/
|
|
27
|
+
export function isCI() {
|
|
28
|
+
const value = process.env.CI;
|
|
29
|
+
return Boolean(value) && value !== 'false';
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,UAAU,WAAW;IACvB,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,UAAU;IACtB,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,WAAW;IACvB,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACxC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,IAAI;IAChB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAA;IAC5B,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,OAAO,CAAA;AAC9C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,62 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
2
|
+
"name": "@doist/cli-core",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Shared core utilities for Doist CLI projects",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc -p tsconfig.build.json",
|
|
16
|
+
"dev": "tsc -p tsconfig.build.json --watch",
|
|
17
|
+
"type-check": "tsc --noEmit",
|
|
18
|
+
"check": "oxlint src && oxfmt --check",
|
|
19
|
+
"fix": "oxlint src --fix && oxfmt",
|
|
20
|
+
"test": "vitest run --passWithNoTests",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"prepublishOnly": "npm run build && npm test"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"cli",
|
|
26
|
+
"doist"
|
|
27
|
+
],
|
|
28
|
+
"author": "Doist",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/Doist/cli-core.git"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/Doist/cli-core#readme",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/Doist/cli-core/issues"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public",
|
|
40
|
+
"provenance": true
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20.18.1"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"dist",
|
|
47
|
+
"CHANGELOG.md"
|
|
48
|
+
],
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@semantic-release/changelog": "6.0.3",
|
|
51
|
+
"@semantic-release/exec": "7.1.0",
|
|
52
|
+
"@semantic-release/git": "10.0.1",
|
|
53
|
+
"@types/node": "25.6.0",
|
|
54
|
+
"conventional-changelog-conventionalcommits": "9.3.1",
|
|
55
|
+
"lefthook": "2.1.6",
|
|
56
|
+
"oxfmt": "0.46.0",
|
|
57
|
+
"oxlint": "1.61.0",
|
|
58
|
+
"semantic-release": "25.0.3",
|
|
59
|
+
"typescript": "6.0.3",
|
|
60
|
+
"vitest": "4.1.5"
|
|
61
|
+
}
|
|
10
62
|
}
|