icore 1.0.19 → 2.0.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 +91 -54
- package/dist/argv/parser.js +1 -0
- package/dist/command/mechanics.js +3 -0
- package/dist/errors/icore-error.d.ts +133 -10
- package/dist/errors/icore-error.js +24 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -1
- package/dist/options/parser.js +7 -1
- package/dist/terminal/app.d.ts +31 -0
- package/dist/terminal/app.js +75 -26
- package/examples/terminal-app.md +67 -0
- package/package.json +2 -2
- package/readme.md +170 -640
package/CHANGELOG.md
CHANGED
|
@@ -9,42 +9,81 @@ Historical entries before this file was introduced were reconstructed from npm
|
|
|
9
9
|
publish metadata and local git history. Older entries are intentionally
|
|
10
10
|
conservative.
|
|
11
11
|
|
|
12
|
-
Version boundaries
|
|
13
|
-
|
|
12
|
+
Version boundaries from `1.0.12` through `1.0.19` were checked against npm
|
|
13
|
+
`gitHead` metadata and local git history.
|
|
14
14
|
|
|
15
15
|
## [Unreleased]
|
|
16
16
|
|
|
17
|
+
## [2.0.0] - 2026-07-14
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Added reusable terminal error rendering and exit-code policy with prepare,
|
|
22
|
+
execute, render, write, and external phase context.
|
|
23
|
+
- Added `TerminalApp.reportError(...)` for caller-owned lifecycle flows that
|
|
24
|
+
need the same stderr and exit-code behavior as `run(...)` and
|
|
25
|
+
`runPrepared(...)`.
|
|
26
|
+
- Added `IcoreError.category` to distinguish usage failures from invalid
|
|
27
|
+
command and option definitions.
|
|
28
|
+
- Added the public `IcoreErrorDetailsMap`, generic `IcoreErrorDetails<TCode>`,
|
|
29
|
+
and distributed `AnyIcoreError` contracts for code-specific error details.
|
|
30
|
+
- Added `isIcoreError(...)` overloads for narrowing any `IcoreError` or one
|
|
31
|
+
exact error code while preserving its details type.
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- Clarified that extra positionals after a matched command path are rejected
|
|
36
|
+
during prepare unless the command declares `allowExtraPositionals: true`.
|
|
37
|
+
- Changed `TerminalApp.run(...)` and `TerminalApp.runPrepared(...)` to share the
|
|
38
|
+
configured terminal error policy while preserving the default error text and
|
|
39
|
+
exit code.
|
|
40
|
+
- **Breaking:** changed the `IcoreError` constructor to require code-specific
|
|
41
|
+
`details`; direct callers must now provide the third argument.
|
|
42
|
+
- Added explicit variant discriminators to `UNKNOWN_COMMAND`,
|
|
43
|
+
`UNEXPECTED_ARGUMENT`, `EXPECTED_REQUIRED_ARGUMENT`, and
|
|
44
|
+
`INVALID_OPTION_DEFAULT` details.
|
|
45
|
+
|
|
46
|
+
## [1.0.19]
|
|
47
|
+
|
|
17
48
|
### Added
|
|
18
49
|
|
|
19
|
-
- Added `TerminalApp.runPrepared(...)` for running prepared commands through terminal rendering and output.
|
|
20
50
|
- Added `TerminalApp.writePreparedOutput(...)` for rendering and writing already obtained terminal output.
|
|
51
|
+
- Added `docs/roadmap.md` for directional project decisions that are not release history.
|
|
21
52
|
|
|
22
53
|
### Changed
|
|
23
54
|
|
|
24
|
-
- Changed `createTerminalApp` typing to accept command registries with void and prepared payloads.
|
|
25
55
|
- Changed `createTerminalApp` typing to allow custom command results when consumers run prepared commands themselves.
|
|
26
|
-
-
|
|
56
|
+
- Documented the caller-owned flow for command execution results that may be
|
|
57
|
+
lifecycle handles before terminal output is written.
|
|
58
|
+
- Documented that terminal string output is written exactly as provided.
|
|
27
59
|
|
|
28
|
-
## [1.0.
|
|
60
|
+
## [1.0.18]
|
|
29
61
|
|
|
30
62
|
### Added
|
|
31
63
|
|
|
32
|
-
- Added `
|
|
33
|
-
- Added semantic presentation facade: `createPresentation()`.
|
|
34
|
-
- Added semantic output facade: `createOutput()` with `output.write(...)` and `output.error(...)`.
|
|
35
|
-
- Added terminal-ready command output support: text, async text streams, presentation results, and empty output.
|
|
36
|
-
- Added guide-style examples for terminal app, command flow, option schemas, presentation, output, and lower-level mechanics.
|
|
64
|
+
- Added `TerminalApp.runPrepared(...)` for running prepared commands through terminal rendering and output.
|
|
37
65
|
|
|
38
66
|
### Changed
|
|
39
67
|
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
- Public README now positions `icore` as terminal application mechanics, not only argv parsing.
|
|
68
|
+
- Documented the `app.prepare(...)` and `app.runPrepared(...)` flow for applications
|
|
69
|
+
that create and clean up runtime context themselves.
|
|
43
70
|
|
|
44
|
-
## [1.0.
|
|
71
|
+
## [1.0.17]
|
|
72
|
+
|
|
73
|
+
### Changed
|
|
74
|
+
|
|
75
|
+
- Relaxed `createTerminalApp` typing so command registries with commands
|
|
76
|
+
without `prepare()` hooks and with void payloads compile without adapter casts.
|
|
77
|
+
|
|
78
|
+
## [1.0.16]
|
|
45
79
|
|
|
46
80
|
### Added
|
|
47
81
|
|
|
82
|
+
- Added `createTerminalApp()` as the top-level terminal application composition API.
|
|
83
|
+
- Added command mechanics facade: `createCommand()`.
|
|
84
|
+
- Added semantic presentation facade: `createPresentation()`.
|
|
85
|
+
- Added semantic output facade: `createOutput()` with `output.write(...)` and `output.error(...)`.
|
|
86
|
+
- Added terminal-ready command output support: text, async text streams, presentation results, and empty output.
|
|
48
87
|
- Added presentation primitives and renderers:
|
|
49
88
|
- `renderJson`
|
|
50
89
|
- `renderCsv`
|
|
@@ -56,67 +95,62 @@ verified against git tags.
|
|
|
56
95
|
- `createStdoutWriter`
|
|
57
96
|
- `createStderrWriter`
|
|
58
97
|
- `createBackpressureTextWriter`
|
|
98
|
+
- Added typed option subset parsing with `parseOptionsSubsetDetailed`.
|
|
99
|
+
- Added guide-style examples for terminal app, command flow, option schemas, presentation, output, and lower-level mechanics.
|
|
59
100
|
|
|
60
101
|
### Changed
|
|
61
102
|
|
|
62
|
-
-
|
|
103
|
+
- Documentation was reorganized around `command`, `presentation`, and `output`.
|
|
104
|
+
- Examples were grouped by usage level: Terminal Application, Layer Toolkit, Primitive Mechanics.
|
|
105
|
+
- Public README now positions `icore` as terminal application mechanics, not only argv parsing.
|
|
106
|
+
- Source files were reorganized by framework area: argv, command, options,
|
|
107
|
+
presentation, output, and terminal app.
|
|
108
|
+
- Updated tests to run with `fwa --prune`.
|
|
109
|
+
- Restored `CHANGELOG.md` to published package contents.
|
|
63
110
|
|
|
64
|
-
|
|
111
|
+
### Removed
|
|
112
|
+
|
|
113
|
+
- Removed the redundant CLI barrel module.
|
|
114
|
+
- Removed the legacy `git-flow.md` document.
|
|
115
|
+
- Removed the `prepare` package script.
|
|
116
|
+
|
|
117
|
+
## [1.0.15]
|
|
65
118
|
|
|
66
119
|
### Added
|
|
67
120
|
|
|
68
|
-
- Added command
|
|
69
|
-
- Added command registry flow:
|
|
70
|
-
- `command.define(...)`
|
|
71
|
-
- `command.registry(...)`
|
|
72
|
-
- `commands.prepare(...)`
|
|
73
|
-
- `commands.run(...)`
|
|
74
|
-
- `commands.runFromArgs(...)`
|
|
75
|
-
- Added lower-level command primitives:
|
|
76
|
-
- `defineCommand`
|
|
77
|
-
- `defineCommandRegistry`
|
|
78
|
-
- `createCommands`
|
|
79
|
-
- `resolveCommand`
|
|
80
|
-
- `prepareCommandFromArgs`
|
|
81
|
-
- `runPreparedCommand`
|
|
82
|
-
- `runCommandFromRegistry`
|
|
83
|
-
- `runCommand`
|
|
121
|
+
- Added `isPreparedCommandName` for narrowing prepared command unions by command name.
|
|
84
122
|
|
|
85
123
|
### Changed
|
|
86
124
|
|
|
87
|
-
-
|
|
125
|
+
- Temporarily excluded `CHANGELOG.md` from published package contents.
|
|
126
|
+
|
|
127
|
+
## [1.0.14]
|
|
128
|
+
|
|
129
|
+
### Changed
|
|
130
|
+
|
|
131
|
+
- Preserved prepared command payload correlation when narrowing registry unions.
|
|
132
|
+
- Reformatted `CHANGELOG.md` according to Keep a Changelog.
|
|
88
133
|
|
|
89
134
|
## [1.0.13]
|
|
90
135
|
|
|
91
136
|
### Added
|
|
92
137
|
|
|
93
|
-
- Added
|
|
94
|
-
- Added
|
|
95
|
-
- Added
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- Added detailed option parsing contracts for cases where caller needs explicit provided/not-provided metadata.
|
|
138
|
+
- Added machine-readable `IcoreError` codes and details.
|
|
139
|
+
- Added strict command resolution mode with `strict: true`.
|
|
140
|
+
- Added strict mode support to direct `runCommand(...)` calls.
|
|
141
|
+
- Added typed prepared command payloads.
|
|
142
|
+
- Added `CHANGELOG.md`.
|
|
99
143
|
|
|
100
144
|
### Changed
|
|
101
145
|
|
|
102
|
-
- Boolean option handling was tightened
|
|
146
|
+
- Boolean option handling was tightened to flag syntax only.
|
|
103
147
|
|
|
104
148
|
## [1.0.12]
|
|
105
149
|
|
|
106
|
-
###
|
|
150
|
+
### Changed
|
|
107
151
|
|
|
108
|
-
-
|
|
109
|
-
|
|
110
|
-
- `type: 'boolean'`
|
|
111
|
-
- `type: 'number'`
|
|
112
|
-
- Added GNU-style argv parsing:
|
|
113
|
-
- `--name value`
|
|
114
|
-
- `--name=value`
|
|
115
|
-
- `--flag`
|
|
116
|
-
- short aliases
|
|
117
|
-
- `--` terminator
|
|
118
|
-
- Added machine-readable `IcoreError`.
|
|
119
|
-
- Added initial TypeScript-first public API for command-line mechanics.
|
|
152
|
+
- Replaced the preliminary `flagOnly` boolean option setting with typed
|
|
153
|
+
`syntax: 'flag'`.
|
|
120
154
|
|
|
121
155
|
## [1.0.11] - 2026-07-02
|
|
122
156
|
|
|
@@ -268,6 +302,9 @@ verified against git tags.
|
|
|
268
302
|
- Detailed changelog entries were not maintained for these releases.
|
|
269
303
|
|
|
270
304
|
[Unreleased]: https://github.com/woodger/icore/commits/develop
|
|
305
|
+
[1.0.19]: https://www.npmjs.com/package/icore/v/1.0.19
|
|
306
|
+
[1.0.18]: https://www.npmjs.com/package/icore/v/1.0.18
|
|
307
|
+
[1.0.17]: https://www.npmjs.com/package/icore/v/1.0.17
|
|
271
308
|
[1.0.16]: https://www.npmjs.com/package/icore/v/1.0.16
|
|
272
309
|
[1.0.15]: https://www.npmjs.com/package/icore/v/1.0.15
|
|
273
310
|
[1.0.14]: https://www.npmjs.com/package/icore/v/1.0.14
|
package/dist/argv/parser.js
CHANGED
|
@@ -147,6 +147,7 @@ function createDuplicateArgumentError(name) {
|
|
|
147
147
|
}
|
|
148
148
|
function createUnexpectedArgumentError(argument) {
|
|
149
149
|
return new icore_error_1.IcoreError('UNEXPECTED_ARGUMENT', `Unexpected argument '${argument}'`, {
|
|
150
|
+
reason: 'malformed-option',
|
|
150
151
|
argument
|
|
151
152
|
});
|
|
152
153
|
}
|
|
@@ -220,6 +220,7 @@ function resolveCommandPositionals(path, positionals) {
|
|
|
220
220
|
if (positionals[index] !== path[index]) {
|
|
221
221
|
const command = path.join(' ');
|
|
222
222
|
throw new icore_error_1.IcoreError('UNKNOWN_COMMAND', `Expected command '${command}'`, {
|
|
223
|
+
reason: 'path-mismatch',
|
|
223
224
|
command,
|
|
224
225
|
path: [...path],
|
|
225
226
|
positionals: [...positionals]
|
|
@@ -305,12 +306,14 @@ function isOptionBeforeCommand(arg) {
|
|
|
305
306
|
function createUnknownCommandError(positionals) {
|
|
306
307
|
const command = formatCommandPositionals(positionals);
|
|
307
308
|
return new icore_error_1.IcoreError('UNKNOWN_COMMAND', `Unknown command: ${command}`, {
|
|
309
|
+
reason: 'unresolved',
|
|
308
310
|
command,
|
|
309
311
|
positionals: [...positionals]
|
|
310
312
|
});
|
|
311
313
|
}
|
|
312
314
|
function createUnexpectedArgumentError(argument) {
|
|
313
315
|
return new icore_error_1.IcoreError('UNEXPECTED_ARGUMENT', `Unexpected argument '${argument}'`, {
|
|
316
|
+
reason: 'option-before-command',
|
|
314
317
|
argument
|
|
315
318
|
});
|
|
316
319
|
}
|
|
@@ -3,27 +3,150 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Allowed here:
|
|
5
5
|
* - defining stable error codes;
|
|
6
|
+
* - correlating error codes with structured details;
|
|
6
7
|
* - preserving human-readable messages on Error instances;
|
|
7
8
|
* - carrying structured details for application-level handling;
|
|
9
|
+
* - narrowing unknown errors by their stable codes;
|
|
8
10
|
*
|
|
9
11
|
* This file must not contain parser, validator, or command resolution logic.
|
|
10
12
|
*/
|
|
13
|
+
type OptionIdentityDetails = {
|
|
14
|
+
argument: string;
|
|
15
|
+
option: string;
|
|
16
|
+
};
|
|
17
|
+
type UnknownCommandDetails = {
|
|
18
|
+
reason: 'unresolved';
|
|
19
|
+
command: string;
|
|
20
|
+
positionals: readonly string[];
|
|
21
|
+
} | {
|
|
22
|
+
reason: 'path-mismatch';
|
|
23
|
+
command: string;
|
|
24
|
+
path: readonly string[];
|
|
25
|
+
positionals: readonly string[];
|
|
26
|
+
};
|
|
27
|
+
type UnexpectedArgumentDetails = {
|
|
28
|
+
reason: 'malformed-option';
|
|
29
|
+
argument: string;
|
|
30
|
+
} | {
|
|
31
|
+
reason: 'unknown-option';
|
|
32
|
+
argument: string;
|
|
33
|
+
option: string;
|
|
34
|
+
} | {
|
|
35
|
+
reason: 'option-before-command';
|
|
36
|
+
argument: string;
|
|
37
|
+
};
|
|
38
|
+
type ExpectedRequiredArgumentDetails = {
|
|
39
|
+
reason: 'option';
|
|
40
|
+
argument: string;
|
|
41
|
+
option: string;
|
|
42
|
+
} | {
|
|
43
|
+
reason: 'positional';
|
|
44
|
+
argument: string;
|
|
45
|
+
positional: string;
|
|
46
|
+
};
|
|
47
|
+
type InvalidOptionTypeDetails = OptionIdentityDetails & ({
|
|
48
|
+
expected: 'string' | 'boolean flag' | 'number';
|
|
49
|
+
value: unknown;
|
|
50
|
+
} | {
|
|
51
|
+
expected: 'integer';
|
|
52
|
+
value: number;
|
|
53
|
+
} | {
|
|
54
|
+
expected: 'minimum';
|
|
55
|
+
min: number;
|
|
56
|
+
value: number;
|
|
57
|
+
} | {
|
|
58
|
+
expected: 'maximum';
|
|
59
|
+
max: number;
|
|
60
|
+
value: number;
|
|
61
|
+
});
|
|
62
|
+
type InvalidOptionDefaultDetails = OptionIdentityDetails & ({
|
|
63
|
+
expected: 'string' | 'boolean' | 'number';
|
|
64
|
+
value: unknown;
|
|
65
|
+
} | {
|
|
66
|
+
expected: 'integer';
|
|
67
|
+
value: number;
|
|
68
|
+
} | {
|
|
69
|
+
expected: 'minimum';
|
|
70
|
+
min: number;
|
|
71
|
+
value: number;
|
|
72
|
+
} | {
|
|
73
|
+
expected: 'maximum';
|
|
74
|
+
max: number;
|
|
75
|
+
value: number;
|
|
76
|
+
} | {
|
|
77
|
+
expected: 'choice';
|
|
78
|
+
choices: readonly (string | number)[];
|
|
79
|
+
value: string | number;
|
|
80
|
+
});
|
|
81
|
+
/** Structured details protocol keyed by every stable `IcoreError` code. */
|
|
82
|
+
export type IcoreErrorDetailsMap = {
|
|
83
|
+
UNKNOWN_COMMAND: UnknownCommandDetails;
|
|
84
|
+
UNEXPECTED_ARGUMENT: UnexpectedArgumentDetails;
|
|
85
|
+
DUPLICATE_ARGUMENT: OptionIdentityDetails;
|
|
86
|
+
EXPECTED_REQUIRED_ARGUMENT: ExpectedRequiredArgumentDetails;
|
|
87
|
+
INVALID_OPTION_TYPE: InvalidOptionTypeDetails;
|
|
88
|
+
INVALID_OPTION_CHOICE: OptionIdentityDetails & {
|
|
89
|
+
choices: readonly (string | number)[];
|
|
90
|
+
value: string | number;
|
|
91
|
+
};
|
|
92
|
+
UNEXPECTED_POSITIONAL: {
|
|
93
|
+
command: string;
|
|
94
|
+
positional: string;
|
|
95
|
+
positionals: readonly string[];
|
|
96
|
+
};
|
|
97
|
+
INVALID_OPTION_ALIAS: OptionIdentityDetails & {
|
|
98
|
+
alias: unknown;
|
|
99
|
+
};
|
|
100
|
+
DUPLICATE_ALIAS: {
|
|
101
|
+
argument: string;
|
|
102
|
+
alias: string;
|
|
103
|
+
};
|
|
104
|
+
INVALID_OPTION_DEFAULT: InvalidOptionDefaultDetails;
|
|
105
|
+
DUPLICATE_COMMAND: {
|
|
106
|
+
command: string;
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
/** Stable machine-readable error code for `icore` CLI mechanics errors. */
|
|
110
|
+
export type IcoreErrorCode = keyof IcoreErrorDetailsMap;
|
|
111
|
+
/** Structured details for one exact `IcoreError` code. */
|
|
112
|
+
export type IcoreErrorDetails<TCode extends IcoreErrorCode> = Readonly<IcoreErrorDetailsMap[TCode]>;
|
|
11
113
|
/**
|
|
12
|
-
* Stable
|
|
114
|
+
* Stable category for distinguishing user input failures from invalid command
|
|
115
|
+
* or option definitions.
|
|
13
116
|
*/
|
|
14
|
-
export type
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
117
|
+
export type IcoreErrorCategory = 'usage' | 'definition';
|
|
118
|
+
declare const icoreErrorCategoryByCode: {
|
|
119
|
+
readonly UNKNOWN_COMMAND: "usage";
|
|
120
|
+
readonly UNEXPECTED_ARGUMENT: "usage";
|
|
121
|
+
readonly DUPLICATE_ARGUMENT: "usage";
|
|
122
|
+
readonly EXPECTED_REQUIRED_ARGUMENT: "usage";
|
|
123
|
+
readonly INVALID_OPTION_TYPE: "usage";
|
|
124
|
+
readonly INVALID_OPTION_CHOICE: "usage";
|
|
125
|
+
readonly UNEXPECTED_POSITIONAL: "usage";
|
|
126
|
+
readonly INVALID_OPTION_ALIAS: "definition";
|
|
127
|
+
readonly DUPLICATE_ALIAS: "definition";
|
|
128
|
+
readonly INVALID_OPTION_DEFAULT: "definition";
|
|
129
|
+
readonly DUPLICATE_COMMAND: "definition";
|
|
130
|
+
};
|
|
19
131
|
/**
|
|
20
132
|
* Error thrown by `icore` for CLI parsing, option validation, command
|
|
21
133
|
* resolution, and schema configuration failures.
|
|
22
134
|
*/
|
|
23
|
-
export declare class IcoreError extends Error {
|
|
135
|
+
export declare class IcoreError<TCode extends IcoreErrorCode = IcoreErrorCode> extends Error {
|
|
24
136
|
/** Stable machine-readable code. */
|
|
25
|
-
readonly code:
|
|
137
|
+
readonly code: TCode;
|
|
138
|
+
/** Stable high-level error category. */
|
|
139
|
+
readonly category: typeof icoreErrorCategoryByCode[TCode];
|
|
26
140
|
/** Structured error context. */
|
|
27
|
-
readonly details: IcoreErrorDetails
|
|
28
|
-
constructor(code:
|
|
141
|
+
readonly details: IcoreErrorDetails<TCode>;
|
|
142
|
+
constructor(code: TCode, message: string, details: IcoreErrorDetails<TCode>);
|
|
29
143
|
}
|
|
144
|
+
/** Distributed union preserving the correlation between code and details. */
|
|
145
|
+
export type AnyIcoreError = {
|
|
146
|
+
[TCode in IcoreErrorCode]: IcoreError<TCode>;
|
|
147
|
+
}[IcoreErrorCode];
|
|
148
|
+
/** Checks whether an unknown value is any supported `IcoreError`. */
|
|
149
|
+
export declare function isIcoreError(error: unknown): error is AnyIcoreError;
|
|
150
|
+
/** Checks and narrows an unknown value to one exact `IcoreError` code. */
|
|
151
|
+
export declare function isIcoreError<TCode extends IcoreErrorCode>(error: unknown, code: TCode): error is IcoreError<TCode>;
|
|
152
|
+
export {};
|
|
@@ -4,13 +4,29 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Allowed here:
|
|
6
6
|
* - defining stable error codes;
|
|
7
|
+
* - correlating error codes with structured details;
|
|
7
8
|
* - preserving human-readable messages on Error instances;
|
|
8
9
|
* - carrying structured details for application-level handling;
|
|
10
|
+
* - narrowing unknown errors by their stable codes;
|
|
9
11
|
*
|
|
10
12
|
* This file must not contain parser, validator, or command resolution logic.
|
|
11
13
|
*/
|
|
12
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
15
|
exports.IcoreError = void 0;
|
|
16
|
+
exports.isIcoreError = isIcoreError;
|
|
17
|
+
const icoreErrorCategoryByCode = {
|
|
18
|
+
UNKNOWN_COMMAND: 'usage',
|
|
19
|
+
UNEXPECTED_ARGUMENT: 'usage',
|
|
20
|
+
DUPLICATE_ARGUMENT: 'usage',
|
|
21
|
+
EXPECTED_REQUIRED_ARGUMENT: 'usage',
|
|
22
|
+
INVALID_OPTION_TYPE: 'usage',
|
|
23
|
+
INVALID_OPTION_CHOICE: 'usage',
|
|
24
|
+
UNEXPECTED_POSITIONAL: 'usage',
|
|
25
|
+
INVALID_OPTION_ALIAS: 'definition',
|
|
26
|
+
DUPLICATE_ALIAS: 'definition',
|
|
27
|
+
INVALID_OPTION_DEFAULT: 'definition',
|
|
28
|
+
DUPLICATE_COMMAND: 'definition'
|
|
29
|
+
};
|
|
14
30
|
/**
|
|
15
31
|
* Error thrown by `icore` for CLI parsing, option validation, command
|
|
16
32
|
* resolution, and schema configuration failures.
|
|
@@ -18,14 +34,21 @@ exports.IcoreError = void 0;
|
|
|
18
34
|
class IcoreError extends Error {
|
|
19
35
|
/** Stable machine-readable code. */
|
|
20
36
|
code;
|
|
37
|
+
/** Stable high-level error category. */
|
|
38
|
+
category;
|
|
21
39
|
/** Structured error context. */
|
|
22
40
|
details;
|
|
23
|
-
constructor(code, message, details
|
|
41
|
+
constructor(code, message, details) {
|
|
24
42
|
super(message);
|
|
25
43
|
this.name = 'IcoreError';
|
|
26
44
|
this.code = code;
|
|
45
|
+
this.category = icoreErrorCategoryByCode[code];
|
|
27
46
|
this.details = details;
|
|
28
47
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
29
48
|
}
|
|
30
49
|
}
|
|
31
50
|
exports.IcoreError = IcoreError;
|
|
51
|
+
function isIcoreError(error, code) {
|
|
52
|
+
return error instanceof IcoreError
|
|
53
|
+
&& (code === undefined || error.code === code);
|
|
54
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export { parseArgv, type ParsedArgv } from './argv/parser';
|
|
14
14
|
export { createCommand, createCommands, defineCommand, defineCommandRegistry, isCommandName, isPreparedCommandName, prepareCommandFromArgs, resolveCommand, resolveCommandFromArgs, runCommand, runPreparedCommand, runCommandFromRegistry, type Command, type CommandDefinition, type CommandContext, type CommandInput, type CommandName, type CommandPayload, type CommandRegistry, type CommandResolutionOptions, type CommandResult, type Commands, type PreparedCommand, type PreparedCommandInput, type ResolvedCommand } from './command/mechanics';
|
|
15
|
-
export { IcoreError, type IcoreErrorCode, type IcoreErrorDetails } from './errors/icore-error';
|
|
15
|
+
export { IcoreError, isIcoreError, type AnyIcoreError, type IcoreErrorCategory, type IcoreErrorCode, type IcoreErrorDetails, type IcoreErrorDetailsMap } from './errors/icore-error';
|
|
16
16
|
export { parseOptions, parseOptionsDetailed, parseOptionsSubsetDetailed, type ParseOptionsResult, type ParseOptionsSubsetResult } from './options/parser';
|
|
17
17
|
export { mergeOptionsSchema, type BooleanOption, type InferOptions, type InferProvidedOptions, type MergeOptionsSchemas, type NumberOption, type OptionDefinition, type OptionsSchema, type RawOptionValue, type StringOption } from './options/schema';
|
|
18
18
|
export { createPresentation, type Presentation, type PresentationRenderers } from './presentation/facade';
|
|
@@ -25,4 +25,4 @@ export { type CsvCell, type CsvRow, type CsvPresentationView, type EmptyPresenta
|
|
|
25
25
|
export { createOutput, type Output, type OutputOptions } from './output/facade';
|
|
26
26
|
export { createStderrWriter, createStdoutWriter } from './output/node-writer';
|
|
27
27
|
export { createBackpressureTextWriter, type BackpressureTextSink, type TextWriter } from './output/text-writer';
|
|
28
|
-
export { createTerminalApp, type TerminalApp, type TerminalAppOptions, type TerminalCommandOutput } from './terminal/app';
|
|
28
|
+
export { createTerminalApp, type TerminalApp, type TerminalAppOptions, type TerminalCommandOutput, type TerminalErrorContext, type TerminalErrorPhase, type TerminalErrorPolicy } from './terminal/app';
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* This file must not contain parser, validator, or command runtime logic.
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.createTerminalApp = exports.createBackpressureTextWriter = exports.createStdoutWriter = exports.createStderrWriter = exports.createOutput = exports.renderPresentationResult = exports.isPresentationResult = exports.renderTextTable = exports.renderJson = exports.renderCsvRow = exports.renderCsv = exports.presentationFormats = exports.presentationFormatOptions = exports.isPresentationFormat = exports.createPresentation = exports.mergeOptionsSchema = exports.parseOptionsSubsetDetailed = exports.parseOptionsDetailed = exports.parseOptions = exports.IcoreError = exports.runCommandFromRegistry = exports.runPreparedCommand = exports.runCommand = exports.resolveCommandFromArgs = exports.resolveCommand = exports.prepareCommandFromArgs = exports.isPreparedCommandName = exports.isCommandName = exports.defineCommandRegistry = exports.defineCommand = exports.createCommands = exports.createCommand = exports.parseArgv = void 0;
|
|
15
|
+
exports.createTerminalApp = exports.createBackpressureTextWriter = exports.createStdoutWriter = exports.createStderrWriter = exports.createOutput = exports.renderPresentationResult = exports.isPresentationResult = exports.renderTextTable = exports.renderJson = exports.renderCsvRow = exports.renderCsv = exports.presentationFormats = exports.presentationFormatOptions = exports.isPresentationFormat = exports.createPresentation = exports.mergeOptionsSchema = exports.parseOptionsSubsetDetailed = exports.parseOptionsDetailed = exports.parseOptions = exports.isIcoreError = exports.IcoreError = exports.runCommandFromRegistry = exports.runPreparedCommand = exports.runCommand = exports.resolveCommandFromArgs = exports.resolveCommand = exports.prepareCommandFromArgs = exports.isPreparedCommandName = exports.isCommandName = exports.defineCommandRegistry = exports.defineCommand = exports.createCommands = exports.createCommand = exports.parseArgv = void 0;
|
|
16
16
|
var parser_1 = require("./argv/parser");
|
|
17
17
|
Object.defineProperty(exports, "parseArgv", { enumerable: true, get: function () { return parser_1.parseArgv; } });
|
|
18
18
|
var mechanics_1 = require("./command/mechanics");
|
|
@@ -30,6 +30,7 @@ Object.defineProperty(exports, "runPreparedCommand", { enumerable: true, get: fu
|
|
|
30
30
|
Object.defineProperty(exports, "runCommandFromRegistry", { enumerable: true, get: function () { return mechanics_1.runCommandFromRegistry; } });
|
|
31
31
|
var icore_error_1 = require("./errors/icore-error");
|
|
32
32
|
Object.defineProperty(exports, "IcoreError", { enumerable: true, get: function () { return icore_error_1.IcoreError; } });
|
|
33
|
+
Object.defineProperty(exports, "isIcoreError", { enumerable: true, get: function () { return icore_error_1.isIcoreError; } });
|
|
33
34
|
var parser_2 = require("./options/parser");
|
|
34
35
|
Object.defineProperty(exports, "parseOptions", { enumerable: true, get: function () { return parser_2.parseOptions; } });
|
|
35
36
|
Object.defineProperty(exports, "parseOptionsDetailed", { enumerable: true, get: function () { return parser_2.parseOptionsDetailed; } });
|
package/dist/options/parser.js
CHANGED
|
@@ -151,7 +151,10 @@ function validateNumberConstraints(name, definition, parsed, source = 'value') {
|
|
|
151
151
|
value: parsed
|
|
152
152
|
});
|
|
153
153
|
}
|
|
154
|
-
throw
|
|
154
|
+
throw createInvalidOptionTypeError(name, `Expected '--${name}' as integer`, {
|
|
155
|
+
expected: 'integer',
|
|
156
|
+
value: parsed
|
|
157
|
+
});
|
|
155
158
|
}
|
|
156
159
|
if (definition.min !== undefined && parsed < definition.min) {
|
|
157
160
|
const message = `Expected '--${name}' to be greater than or equal to ${String(definition.min)}`;
|
|
@@ -192,6 +195,7 @@ function assertChoice(name, choices, value, source = 'value') {
|
|
|
192
195
|
const message = `Expected '--${name}' as one of: ${choices.join(', ')}`;
|
|
193
196
|
if (source === 'default') {
|
|
194
197
|
throw createInvalidOptionDefaultError(name, message, {
|
|
198
|
+
expected: 'choice',
|
|
195
199
|
choices: [...choices],
|
|
196
200
|
value
|
|
197
201
|
});
|
|
@@ -200,12 +204,14 @@ function assertChoice(name, choices, value, source = 'value') {
|
|
|
200
204
|
}
|
|
201
205
|
function createUnexpectedArgumentError(name) {
|
|
202
206
|
return new icore_error_1.IcoreError('UNEXPECTED_ARGUMENT', `Unexpected argument '--${name}'`, {
|
|
207
|
+
reason: 'unknown-option',
|
|
203
208
|
argument: `--${name}`,
|
|
204
209
|
option: name
|
|
205
210
|
});
|
|
206
211
|
}
|
|
207
212
|
function createExpectedRequiredArgumentError(name) {
|
|
208
213
|
return new icore_error_1.IcoreError('EXPECTED_REQUIRED_ARGUMENT', `Expected required argument '--${name}'`, {
|
|
214
|
+
reason: 'option',
|
|
209
215
|
argument: `--${name}`,
|
|
210
216
|
option: name
|
|
211
217
|
});
|
package/dist/terminal/app.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* - preparing and running command facades;
|
|
6
6
|
* - rendering presentation results;
|
|
7
7
|
* - writing command output through the output facade;
|
|
8
|
+
* - reporting terminal errors through caller-configured policy;
|
|
8
9
|
*
|
|
9
10
|
* This file must not contain argv tokenization, option validation internals,
|
|
10
11
|
* domain behavior, or application-specific report mapping.
|
|
@@ -21,6 +22,32 @@ import { type Output } from '../output/facade';
|
|
|
21
22
|
* no output. Other result shapes are rejected before writing to stdout.
|
|
22
23
|
*/
|
|
23
24
|
export type TerminalCommandOutput = string | AsyncIterable<string> | PresentationResult | undefined;
|
|
25
|
+
/** Terminal operation in which an error was observed. */
|
|
26
|
+
export type TerminalErrorPhase = 'prepare' | 'execute' | 'render' | 'write' | 'external';
|
|
27
|
+
/**
|
|
28
|
+
* Context supplied to terminal error policy callbacks.
|
|
29
|
+
*
|
|
30
|
+
* Prepared command data is guaranteed for command execution and terminal
|
|
31
|
+
* output phases. Errors outside terminal app operations may provide either
|
|
32
|
+
* arguments, prepared command data, or neither.
|
|
33
|
+
*/
|
|
34
|
+
export type TerminalErrorContext<TPrepared> = {
|
|
35
|
+
phase: 'prepare';
|
|
36
|
+
args: readonly string[];
|
|
37
|
+
} | {
|
|
38
|
+
phase: 'execute' | 'render' | 'write';
|
|
39
|
+
prepared: TPrepared;
|
|
40
|
+
args?: readonly string[];
|
|
41
|
+
} | {
|
|
42
|
+
phase: 'external';
|
|
43
|
+
args?: readonly string[];
|
|
44
|
+
prepared?: TPrepared;
|
|
45
|
+
};
|
|
46
|
+
/** Caller-owned terminal error rendering and process exit-code policy. */
|
|
47
|
+
export type TerminalErrorPolicy<TPrepared> = {
|
|
48
|
+
renderError?(error: unknown, context: TerminalErrorContext<TPrepared>): string;
|
|
49
|
+
resolveExitCode?(error: unknown, context: TerminalErrorContext<TPrepared>): number;
|
|
50
|
+
};
|
|
24
51
|
type BivariantCallback<TInput, TOutput> = {
|
|
25
52
|
bivarianceHack(input: TInput): TOutput;
|
|
26
53
|
}['bivarianceHack'];
|
|
@@ -47,6 +74,8 @@ export type TerminalAppOptions<TCommands extends readonly TerminalCommandDefinit
|
|
|
47
74
|
presentation?: Presentation;
|
|
48
75
|
/** Custom output facade. */
|
|
49
76
|
output?: Output;
|
|
77
|
+
/** Custom terminal error rendering and exit-code policy. */
|
|
78
|
+
errorPolicy?: TerminalErrorPolicy<PreparedCommand<TCommands[number]>>;
|
|
50
79
|
/** Resolves output format. */
|
|
51
80
|
resolveFormat?(prepared: PreparedCommand<TCommands[number]>): PresentationFormat | undefined;
|
|
52
81
|
};
|
|
@@ -54,6 +83,8 @@ export type TerminalApp<TCommands extends readonly TerminalCommandDefinition[]>
|
|
|
54
83
|
commands: Commands<TCommands>;
|
|
55
84
|
presentation: Presentation;
|
|
56
85
|
output: Output;
|
|
86
|
+
/** Renders an error to stderr and returns its process-style exit code. */
|
|
87
|
+
reportError(error: unknown, context?: TerminalErrorContext<PreparedCommand<TCommands[number]>>): Promise<number>;
|
|
57
88
|
/** No application context required. */
|
|
58
89
|
prepare(args: readonly string[], options?: CommandResolutionOptions): Promise<PreparedCommand<TCommands[number]>>;
|
|
59
90
|
/** Runs an already prepared command through terminal rendering and output. */
|