icore 1.0.16 → 1.0.18
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 +100 -32
- package/dist/terminal/app.d.ts +27 -6
- package/dist/terminal/app.js +14 -4
- package/examples/two-phase-primitives.md +29 -0
- package/package.json +1 -1
- package/readme.md +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -9,48 +9,112 @@ 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 between `1.0.12` and `1.0.15` are draft-level and should be
|
|
13
|
+
verified against git tags.
|
|
14
|
+
|
|
12
15
|
## [Unreleased]
|
|
13
16
|
|
|
14
17
|
### Added
|
|
15
18
|
|
|
16
|
-
- Added `
|
|
17
|
-
- Added `createCommands` as a high-level command mechanics facade.
|
|
18
|
-
- Added `createPresentation` and `PresentationResult` for terminal view-model rendering.
|
|
19
|
-
- Added semantic `Presentation` view factory methods such as `presentation.records(...)`.
|
|
20
|
-
- Added `createOutput` as a stdout/stderr output boundary facade.
|
|
21
|
-
- Added semantic `Output.write()` and `Output.error()` methods.
|
|
22
|
-
- Added `createTerminalApp` to compose command, presentation, and output mechanics.
|
|
23
|
-
- Added generic terminal presentation renderers for JSON, CSV, and text tables.
|
|
24
|
-
- Added reusable stdout/stderr text writers with backpressure handling.
|
|
25
|
-
- Added shared `presentationFormatOptions` for common `--format` command options.
|
|
26
|
-
- Added machine-readable `IcoreError` codes and details.
|
|
27
|
-
- Added `parseOptionsSubsetDetailed` for validating known option subsets while preserving unknown raw options.
|
|
28
|
-
- Added opt-in `strict: true` command resolution for rejecting options before command paths.
|
|
29
|
-
- Added `strict: true` support to direct `runCommand` execution.
|
|
30
|
-
- Added typed prepared command `payload` returned from `prepare` and passed to `handle`.
|
|
31
|
-
- Added public `CommandPayload`, `CommandContext`, and `CommandResult` helper types.
|
|
32
|
-
- Added `isPreparedCommandName` for narrowing prepared command unions by name.
|
|
33
|
-
- Added this changelog.
|
|
34
|
-
|
|
35
|
-
### Changed
|
|
36
|
-
|
|
37
|
-
- Changed `PreparedCommand` typing to preserve payload correlation when narrowing registry unions by command name.
|
|
38
|
-
- Changed output writers to await promise-returning custom sinks.
|
|
39
|
-
- Reorganized internal source files by CLI framework responsibility without changing the root public API.
|
|
40
|
-
- Split option schema contracts from option value parsing internals.
|
|
41
|
-
- Changed npm package contents to include `CHANGELOG.md`.
|
|
42
|
-
- Removed the redundant `cli` barrel so `index` is the only package entrypoint.
|
|
19
|
+
- Added `TerminalApp.runPrepared(...)` for running prepared commands through terminal rendering and output.
|
|
43
20
|
|
|
44
|
-
###
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Changed `createTerminalApp` typing to accept command registries with void and prepared payloads.
|
|
24
|
+
- Updated testing instructions to use `yarn build` and `yarn test`.
|
|
25
|
+
|
|
26
|
+
## [1.0.16]
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- Added `createTerminalApp()` as the top-level terminal application composition API.
|
|
31
|
+
- Added semantic presentation facade: `createPresentation()`.
|
|
32
|
+
- Added semantic output facade: `createOutput()` with `output.write(...)` and `output.error(...)`.
|
|
33
|
+
- Added terminal-ready command output support: text, async text streams, presentation results, and empty output.
|
|
34
|
+
- Added guide-style examples for terminal app, command flow, option schemas, presentation, output, and lower-level mechanics.
|
|
45
35
|
|
|
46
|
-
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- Documentation was reorganized around `command`, `presentation`, and `output`.
|
|
39
|
+
- Examples were grouped by usage level: Terminal Application, Layer Toolkit, Primitive Mechanics.
|
|
40
|
+
- Public README now positions `icore` as terminal application mechanics, not only argv parsing.
|
|
41
|
+
|
|
42
|
+
## [1.0.15]
|
|
43
|
+
|
|
44
|
+
### Added
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
- Added presentation primitives and renderers:
|
|
47
|
+
- `renderJson`
|
|
48
|
+
- `renderCsv`
|
|
49
|
+
- `renderCsvRow`
|
|
50
|
+
- `renderTextTable`
|
|
51
|
+
- `renderPresentationResult`
|
|
52
|
+
- `isPresentationResult`
|
|
53
|
+
- Added reusable output writer primitives:
|
|
54
|
+
- `createStdoutWriter`
|
|
55
|
+
- `createStderrWriter`
|
|
56
|
+
- `createBackpressureTextWriter`
|
|
49
57
|
|
|
50
58
|
### Changed
|
|
51
59
|
|
|
52
|
-
-
|
|
53
|
-
|
|
60
|
+
- Extracted generic JSON/CSV/table rendering mechanics from project-specific CLI code.
|
|
61
|
+
|
|
62
|
+
## [1.0.14]
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
|
|
66
|
+
- Added command mechanics facade: `createCommand()`.
|
|
67
|
+
- Added command registry flow:
|
|
68
|
+
- `command.define(...)`
|
|
69
|
+
- `command.registry(...)`
|
|
70
|
+
- `commands.prepare(...)`
|
|
71
|
+
- `commands.run(...)`
|
|
72
|
+
- `commands.runFromArgs(...)`
|
|
73
|
+
- Added lower-level command primitives:
|
|
74
|
+
- `defineCommand`
|
|
75
|
+
- `defineCommandRegistry`
|
|
76
|
+
- `createCommands`
|
|
77
|
+
- `resolveCommand`
|
|
78
|
+
- `prepareCommandFromArgs`
|
|
79
|
+
- `runPreparedCommand`
|
|
80
|
+
- `runCommandFromRegistry`
|
|
81
|
+
- `runCommand`
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- CLI command execution became explicitly two-phase: prepare without runtime context, then run with context.
|
|
86
|
+
|
|
87
|
+
## [1.0.13]
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
|
|
91
|
+
- Added typed option schema composition with `mergeOptionsSchema`.
|
|
92
|
+
- Added option inference helpers for parsed values and provided metadata.
|
|
93
|
+
- Added command-name guards:
|
|
94
|
+
- `isCommandName`
|
|
95
|
+
- `isPreparedCommandName`
|
|
96
|
+
- Added detailed option parsing contracts for cases where caller needs explicit provided/not-provided metadata.
|
|
97
|
+
|
|
98
|
+
### Changed
|
|
99
|
+
|
|
100
|
+
- Boolean option handling was tightened around flag syntax: `--flag` and `--no-flag`.
|
|
101
|
+
|
|
102
|
+
## [1.0.12]
|
|
103
|
+
|
|
104
|
+
### Added
|
|
105
|
+
|
|
106
|
+
- Added core typed CLI option mechanics based on literal schemas:
|
|
107
|
+
- `type: 'string'`
|
|
108
|
+
- `type: 'boolean'`
|
|
109
|
+
- `type: 'number'`
|
|
110
|
+
- Added GNU-style argv parsing:
|
|
111
|
+
- `--name value`
|
|
112
|
+
- `--name=value`
|
|
113
|
+
- `--flag`
|
|
114
|
+
- short aliases
|
|
115
|
+
- `--` terminator
|
|
116
|
+
- Added machine-readable `IcoreError`.
|
|
117
|
+
- Added initial TypeScript-first public API for command-line mechanics.
|
|
54
118
|
|
|
55
119
|
## [1.0.11] - 2026-07-02
|
|
56
120
|
|
|
@@ -202,6 +266,10 @@ conservative.
|
|
|
202
266
|
- Detailed changelog entries were not maintained for these releases.
|
|
203
267
|
|
|
204
268
|
[Unreleased]: https://github.com/woodger/icore/commits/develop
|
|
269
|
+
[1.0.16]: https://www.npmjs.com/package/icore/v/1.0.16
|
|
270
|
+
[1.0.15]: https://www.npmjs.com/package/icore/v/1.0.15
|
|
271
|
+
[1.0.14]: https://www.npmjs.com/package/icore/v/1.0.14
|
|
272
|
+
[1.0.13]: https://www.npmjs.com/package/icore/v/1.0.13
|
|
205
273
|
[1.0.12]: https://www.npmjs.com/package/icore/v/1.0.12
|
|
206
274
|
[1.0.11]: https://www.npmjs.com/package/icore/v/1.0.11
|
|
207
275
|
[1.0.10]: https://www.npmjs.com/package/icore/v/1.0.10
|
package/dist/terminal/app.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* This file must not contain argv tokenization, option validation internals,
|
|
10
10
|
* domain behavior, or application-specific report mapping.
|
|
11
11
|
*/
|
|
12
|
-
import type {
|
|
12
|
+
import type { CommandContext, CommandResolutionOptions, Commands, PreparedCommand } from '../command/mechanics';
|
|
13
13
|
import type { OptionsSchema } from '../options/schema';
|
|
14
14
|
import { type Presentation, type PresentationResult } from '../presentation/facade';
|
|
15
15
|
import { type PresentationFormat } from '../presentation/format-options';
|
|
@@ -21,8 +21,27 @@ import { type Output } from '../output/facade';
|
|
|
21
21
|
* or no output. Other result shapes are rejected before writing to stdout.
|
|
22
22
|
*/
|
|
23
23
|
export type TerminalCommandOutput = string | AsyncIterable<string> | PresentationResult | undefined;
|
|
24
|
-
type
|
|
25
|
-
|
|
24
|
+
type BivariantCallback<TInput, TOutput> = {
|
|
25
|
+
bivarianceHack(input: TInput): TOutput;
|
|
26
|
+
}['bivarianceHack'];
|
|
27
|
+
type TerminalCommandDefinition = {
|
|
28
|
+
path: readonly [string, ...string[]];
|
|
29
|
+
options: OptionsSchema;
|
|
30
|
+
metadata?: unknown;
|
|
31
|
+
allowExtraPositionals?: boolean;
|
|
32
|
+
prepare?: BivariantCallback<PreparedCommandInput, unknown | Promise<unknown>>;
|
|
33
|
+
handle: BivariantCallback<TerminalCommandInput, TerminalCommandOutput | Promise<TerminalCommandOutput>>;
|
|
34
|
+
};
|
|
35
|
+
type PreparedCommandInput = {
|
|
36
|
+
options: Record<string, unknown>;
|
|
37
|
+
provided: Record<string, boolean>;
|
|
38
|
+
positionals: string[];
|
|
39
|
+
};
|
|
40
|
+
type TerminalCommandInput = PreparedCommandInput & {
|
|
41
|
+
context: unknown;
|
|
42
|
+
payload?: unknown;
|
|
43
|
+
};
|
|
44
|
+
export type TerminalAppOptions<TCommands extends readonly TerminalCommandDefinition[]> = {
|
|
26
45
|
commands: Commands<TCommands>;
|
|
27
46
|
/** Custom presentation facade. */
|
|
28
47
|
presentation?: Presentation;
|
|
@@ -31,14 +50,16 @@ export type TerminalAppOptions<TContext, TCommands extends readonly TerminalComm
|
|
|
31
50
|
/** Resolves output format. */
|
|
32
51
|
resolveFormat?(prepared: PreparedCommand<TCommands[number]>): PresentationFormat | undefined;
|
|
33
52
|
};
|
|
34
|
-
export type TerminalApp<
|
|
53
|
+
export type TerminalApp<TCommands extends readonly TerminalCommandDefinition[]> = {
|
|
35
54
|
commands: Commands<TCommands>;
|
|
36
55
|
presentation: Presentation;
|
|
37
56
|
output: Output;
|
|
38
57
|
/** No application context required. */
|
|
39
58
|
prepare(args: readonly string[], options?: CommandResolutionOptions): Promise<PreparedCommand<TCommands[number]>>;
|
|
59
|
+
/** Runs an already prepared command through terminal rendering and output. */
|
|
60
|
+
runPrepared(prepared: PreparedCommand<TCommands[number]>, context: CommandContext<TCommands[number]>): Promise<number>;
|
|
40
61
|
/** Returns a process-style exit code. */
|
|
41
|
-
run(args: readonly string[], context:
|
|
62
|
+
run(args: readonly string[], context: CommandContext<TCommands[number]>, options?: CommandResolutionOptions): Promise<number>;
|
|
42
63
|
};
|
|
43
64
|
/**
|
|
44
65
|
* Composes command mechanics, presentation rendering, and output delivery into
|
|
@@ -47,5 +68,5 @@ export type TerminalApp<TContext, TCommands extends readonly TerminalCommandDefi
|
|
|
47
68
|
* Command handlers keep ownership of application work; this facade only
|
|
48
69
|
* prepares commands, renders supported terminal results, and writes output.
|
|
49
70
|
*/
|
|
50
|
-
export declare function createTerminalApp<
|
|
71
|
+
export declare function createTerminalApp<const TCommands extends readonly TerminalCommandDefinition[]>(options: TerminalAppOptions<TCommands>): TerminalApp<TCommands>;
|
|
51
72
|
export {};
|
package/dist/terminal/app.js
CHANGED
|
@@ -27,6 +27,18 @@ function createTerminalApp(options) {
|
|
|
27
27
|
const presentation = options.presentation ?? (0, facade_1.createPresentation)();
|
|
28
28
|
const output = options.output ?? (0, facade_2.createOutput)();
|
|
29
29
|
const resolveFormat = options.resolveFormat ?? resolvePreparedFormat;
|
|
30
|
+
async function runPrepared(prepared, context) {
|
|
31
|
+
try {
|
|
32
|
+
const result = await options.commands.run(prepared, context);
|
|
33
|
+
const format = resolveFormat(prepared);
|
|
34
|
+
await writeTerminalOutput(result, format, presentation, output);
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
await output.error(renderTerminalError(error));
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
30
42
|
return {
|
|
31
43
|
commands: options.commands,
|
|
32
44
|
presentation,
|
|
@@ -34,13 +46,11 @@ function createTerminalApp(options) {
|
|
|
34
46
|
prepare(args, commandOptions) {
|
|
35
47
|
return options.commands.prepare(args, commandOptions);
|
|
36
48
|
},
|
|
49
|
+
runPrepared,
|
|
37
50
|
async run(args, context, commandOptions) {
|
|
38
51
|
try {
|
|
39
52
|
const prepared = await options.commands.prepare(args, commandOptions);
|
|
40
|
-
|
|
41
|
-
const format = resolveFormat(prepared);
|
|
42
|
-
await writeTerminalOutput(result, format, presentation, output);
|
|
43
|
-
return 0;
|
|
53
|
+
return runPrepared(prepared, context);
|
|
44
54
|
}
|
|
45
55
|
catch (error) {
|
|
46
56
|
await output.error(renderTerminalError(error));
|
|
@@ -75,6 +75,35 @@ This is useful when the selected command decides which runtime resources to
|
|
|
75
75
|
create. If preparation fails, the application can print an argument error
|
|
76
76
|
without opening connections or starting background work.
|
|
77
77
|
|
|
78
|
+
## Run Prepared Through A Terminal App
|
|
79
|
+
|
|
80
|
+
`app.runPrepared(...)` keeps terminal rendering, stdout/stderr writing, and exit
|
|
81
|
+
code handling in `createTerminalApp()` after the application has created its
|
|
82
|
+
own runtime context.
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const prepared = await app.prepare([
|
|
86
|
+
'jobs',
|
|
87
|
+
'run',
|
|
88
|
+
'--job-id',
|
|
89
|
+
'job-42'
|
|
90
|
+
], {
|
|
91
|
+
strict: true
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const context = await createContext(prepared);
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
process.exitCode = await app.runPrepared(prepared, context);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
await cleanup(context);
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Resource creation and cleanup stay application-owned. The terminal app only
|
|
105
|
+
runs the prepared command and applies the same output behavior as `app.run(...)`.
|
|
106
|
+
|
|
78
107
|
## Prepare From A Registry
|
|
79
108
|
|
|
80
109
|
`prepareCommandFromArgs(...)` is the standalone primitive behind
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -80,8 +80,8 @@ without taking ownership of application behavior.
|
|
|
80
80
|
|
|
81
81
|
The checked TypeScript contract lives in [`src/terminal/app.ts`](src/terminal/app.ts).
|
|
82
82
|
|
|
83
|
-
The method returns an application object with `prepare(args)
|
|
84
|
-
`run(args, context)`.
|
|
83
|
+
The method returns an application object with `prepare(args)`,
|
|
84
|
+
`runPrepared(prepared, context)`, and `run(args, context)`.
|
|
85
85
|
|
|
86
86
|
Construction inputs:
|
|
87
87
|
|
|
@@ -97,6 +97,8 @@ Returned app methods:
|
|
|
97
97
|
|
|
98
98
|
- `app.prepare(args, options?)` delegates to
|
|
99
99
|
[`commands.prepare(args, options?)`](#commandsprepareargs-options);
|
|
100
|
+
- `app.runPrepared(prepared, context)` runs an already prepared command, then
|
|
101
|
+
renders and writes terminal output;
|
|
100
102
|
- `app.run(args, context, options?)` prepares the command, delegates command
|
|
101
103
|
execution to [`commands.run(prepared, context)`](#commandsrunprepared-context),
|
|
102
104
|
then renders and writes terminal output.
|