icore 1.0.15 → 1.0.16
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 +220 -0
- package/dist/{argv.d.ts → argv/parser.d.ts} +3 -1
- package/dist/{argv.js → argv/parser.js} +5 -5
- package/dist/{commands.d.ts → command/mechanics.d.ts} +73 -6
- package/dist/{commands.js → command/mechanics.js} +53 -15
- package/dist/{errors.d.ts → errors/icore-error.d.ts} +2 -0
- package/dist/{errors.js → errors/icore-error.js} +2 -0
- package/dist/index.d.ts +28 -1
- package/dist/index.js +61 -17
- package/dist/options/parser.d.ts +43 -0
- package/dist/{options.js → options/parser.js} +27 -17
- package/dist/{options.d.ts → options/schema.d.ts} +16 -23
- package/dist/options/schema.js +23 -0
- package/dist/output/facade.d.ts +28 -0
- package/dist/output/facade.js +32 -0
- package/dist/output/node-writer.d.ts +17 -0
- package/dist/output/node-writer.js +25 -0
- package/dist/output/text-writer.d.ts +29 -0
- package/dist/output/text-writer.js +49 -0
- package/dist/presentation/facade.d.ts +39 -0
- package/dist/presentation/facade.js +47 -0
- package/dist/presentation/format-options.d.ts +31 -0
- package/dist/presentation/format-options.js +37 -0
- package/dist/presentation/renderers/csv.d.ts +18 -0
- package/dist/presentation/renderers/csv.js +35 -0
- package/dist/presentation/renderers/json.d.ts +13 -0
- package/dist/presentation/renderers/json.js +18 -0
- package/dist/presentation/renderers/table.d.ts +14 -0
- package/dist/presentation/renderers/table.js +29 -0
- package/dist/presentation/result-renderer.d.ts +25 -0
- package/dist/presentation/result-renderer.js +184 -0
- package/dist/presentation/view.d.ts +58 -0
- package/dist/presentation/view.js +56 -0
- package/dist/terminal/app.d.ts +51 -0
- package/dist/terminal/app.js +100 -0
- package/examples/cli-argument-syntax.md +218 -0
- package/examples/command-resolution.md +174 -0
- package/examples/custom-command-flow.md +109 -0
- package/examples/option-schemas.md +206 -0
- package/examples/output-writers.md +128 -0
- package/examples/practical-cli-patterns.md +385 -0
- package/examples/presentation-output.md +66 -0
- package/examples/presentation-primitives.md +190 -0
- package/examples/readme.md +48 -0
- package/examples/terminal-app.md +118 -0
- package/examples/two-phase-primitives.md +282 -0
- package/package.json +9 -4
- package/readme.md +278 -299
- package/dist/cli.d.ts +0 -14
- package/dist/cli.js +0 -32
package/dist/index.js
CHANGED
|
@@ -1,19 +1,63 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The package entrypoint exposes the supported command mechanics API.
|
|
4
|
+
*
|
|
5
|
+
* Allowed here:
|
|
6
|
+
* - re-exporting public argv parser contracts;
|
|
7
|
+
* - re-exporting public option schema contracts;
|
|
8
|
+
* - re-exporting public command registry contracts;
|
|
9
|
+
* - re-exporting public presentation and output contracts;
|
|
10
|
+
* - re-exporting public terminal app composition contracts;
|
|
11
|
+
*
|
|
12
|
+
* This file must not contain parser, validator, or command runtime logic.
|
|
13
|
+
*/
|
|
2
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
var
|
|
5
|
-
Object.defineProperty(exports, "
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(exports, "
|
|
8
|
-
Object.defineProperty(exports, "
|
|
9
|
-
Object.defineProperty(exports, "
|
|
10
|
-
Object.defineProperty(exports, "
|
|
11
|
-
Object.defineProperty(exports, "
|
|
12
|
-
Object.defineProperty(exports, "
|
|
13
|
-
Object.defineProperty(exports, "
|
|
14
|
-
Object.defineProperty(exports, "
|
|
15
|
-
Object.defineProperty(exports, "
|
|
16
|
-
Object.defineProperty(exports, "
|
|
17
|
-
Object.defineProperty(exports, "
|
|
18
|
-
Object.defineProperty(exports, "
|
|
19
|
-
|
|
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;
|
|
16
|
+
var parser_1 = require("./argv/parser");
|
|
17
|
+
Object.defineProperty(exports, "parseArgv", { enumerable: true, get: function () { return parser_1.parseArgv; } });
|
|
18
|
+
var mechanics_1 = require("./command/mechanics");
|
|
19
|
+
Object.defineProperty(exports, "createCommand", { enumerable: true, get: function () { return mechanics_1.createCommand; } });
|
|
20
|
+
Object.defineProperty(exports, "createCommands", { enumerable: true, get: function () { return mechanics_1.createCommands; } });
|
|
21
|
+
Object.defineProperty(exports, "defineCommand", { enumerable: true, get: function () { return mechanics_1.defineCommand; } });
|
|
22
|
+
Object.defineProperty(exports, "defineCommandRegistry", { enumerable: true, get: function () { return mechanics_1.defineCommandRegistry; } });
|
|
23
|
+
Object.defineProperty(exports, "isCommandName", { enumerable: true, get: function () { return mechanics_1.isCommandName; } });
|
|
24
|
+
Object.defineProperty(exports, "isPreparedCommandName", { enumerable: true, get: function () { return mechanics_1.isPreparedCommandName; } });
|
|
25
|
+
Object.defineProperty(exports, "prepareCommandFromArgs", { enumerable: true, get: function () { return mechanics_1.prepareCommandFromArgs; } });
|
|
26
|
+
Object.defineProperty(exports, "resolveCommand", { enumerable: true, get: function () { return mechanics_1.resolveCommand; } });
|
|
27
|
+
Object.defineProperty(exports, "resolveCommandFromArgs", { enumerable: true, get: function () { return mechanics_1.resolveCommandFromArgs; } });
|
|
28
|
+
Object.defineProperty(exports, "runCommand", { enumerable: true, get: function () { return mechanics_1.runCommand; } });
|
|
29
|
+
Object.defineProperty(exports, "runPreparedCommand", { enumerable: true, get: function () { return mechanics_1.runPreparedCommand; } });
|
|
30
|
+
Object.defineProperty(exports, "runCommandFromRegistry", { enumerable: true, get: function () { return mechanics_1.runCommandFromRegistry; } });
|
|
31
|
+
var icore_error_1 = require("./errors/icore-error");
|
|
32
|
+
Object.defineProperty(exports, "IcoreError", { enumerable: true, get: function () { return icore_error_1.IcoreError; } });
|
|
33
|
+
var parser_2 = require("./options/parser");
|
|
34
|
+
Object.defineProperty(exports, "parseOptions", { enumerable: true, get: function () { return parser_2.parseOptions; } });
|
|
35
|
+
Object.defineProperty(exports, "parseOptionsDetailed", { enumerable: true, get: function () { return parser_2.parseOptionsDetailed; } });
|
|
36
|
+
Object.defineProperty(exports, "parseOptionsSubsetDetailed", { enumerable: true, get: function () { return parser_2.parseOptionsSubsetDetailed; } });
|
|
37
|
+
var schema_1 = require("./options/schema");
|
|
38
|
+
Object.defineProperty(exports, "mergeOptionsSchema", { enumerable: true, get: function () { return schema_1.mergeOptionsSchema; } });
|
|
39
|
+
var facade_1 = require("./presentation/facade");
|
|
40
|
+
Object.defineProperty(exports, "createPresentation", { enumerable: true, get: function () { return facade_1.createPresentation; } });
|
|
41
|
+
var format_options_1 = require("./presentation/format-options");
|
|
42
|
+
Object.defineProperty(exports, "isPresentationFormat", { enumerable: true, get: function () { return format_options_1.isPresentationFormat; } });
|
|
43
|
+
Object.defineProperty(exports, "presentationFormatOptions", { enumerable: true, get: function () { return format_options_1.presentationFormatOptions; } });
|
|
44
|
+
Object.defineProperty(exports, "presentationFormats", { enumerable: true, get: function () { return format_options_1.presentationFormats; } });
|
|
45
|
+
var csv_1 = require("./presentation/renderers/csv");
|
|
46
|
+
Object.defineProperty(exports, "renderCsv", { enumerable: true, get: function () { return csv_1.renderCsv; } });
|
|
47
|
+
Object.defineProperty(exports, "renderCsvRow", { enumerable: true, get: function () { return csv_1.renderCsvRow; } });
|
|
48
|
+
var json_1 = require("./presentation/renderers/json");
|
|
49
|
+
Object.defineProperty(exports, "renderJson", { enumerable: true, get: function () { return json_1.renderJson; } });
|
|
50
|
+
var table_1 = require("./presentation/renderers/table");
|
|
51
|
+
Object.defineProperty(exports, "renderTextTable", { enumerable: true, get: function () { return table_1.renderTextTable; } });
|
|
52
|
+
var result_renderer_1 = require("./presentation/result-renderer");
|
|
53
|
+
Object.defineProperty(exports, "isPresentationResult", { enumerable: true, get: function () { return result_renderer_1.isPresentationResult; } });
|
|
54
|
+
Object.defineProperty(exports, "renderPresentationResult", { enumerable: true, get: function () { return result_renderer_1.renderPresentationResult; } });
|
|
55
|
+
var facade_2 = require("./output/facade");
|
|
56
|
+
Object.defineProperty(exports, "createOutput", { enumerable: true, get: function () { return facade_2.createOutput; } });
|
|
57
|
+
var node_writer_1 = require("./output/node-writer");
|
|
58
|
+
Object.defineProperty(exports, "createStderrWriter", { enumerable: true, get: function () { return node_writer_1.createStderrWriter; } });
|
|
59
|
+
Object.defineProperty(exports, "createStdoutWriter", { enumerable: true, get: function () { return node_writer_1.createStdoutWriter; } });
|
|
60
|
+
var text_writer_1 = require("./output/text-writer");
|
|
61
|
+
Object.defineProperty(exports, "createBackpressureTextWriter", { enumerable: true, get: function () { return text_writer_1.createBackpressureTextWriter; } });
|
|
62
|
+
var app_1 = require("./terminal/app");
|
|
63
|
+
Object.defineProperty(exports, "createTerminalApp", { enumerable: true, get: function () { return app_1.createTerminalApp; } });
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The option parser module validates raw option values against declarative
|
|
3
|
+
* primitive option contracts.
|
|
4
|
+
*
|
|
5
|
+
* Allowed here:
|
|
6
|
+
* - applying and validating default values;
|
|
7
|
+
* - producing typed option values and user-provided metadata;
|
|
8
|
+
*
|
|
9
|
+
* This file must not contain argv tokenization, command resolution, or
|
|
10
|
+
* application-specific validation rules.
|
|
11
|
+
*/
|
|
12
|
+
import type { InferOptions, InferProvidedOptions, OptionsSchema, RawOptionValue } from './schema';
|
|
13
|
+
/**
|
|
14
|
+
* Detailed option parsing result with values and user-provided metadata.
|
|
15
|
+
*/
|
|
16
|
+
export type ParseOptionsResult<TSchema extends OptionsSchema> = {
|
|
17
|
+
/** Parsed values. */
|
|
18
|
+
options: InferOptions<TSchema>;
|
|
19
|
+
/** Explicit option presence metadata. */
|
|
20
|
+
provided: InferProvidedOptions<TSchema>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Detailed option subset parsing result with untouched options for later
|
|
24
|
+
* command-layer validation.
|
|
25
|
+
*/
|
|
26
|
+
export type ParseOptionsSubsetResult<TSchema extends OptionsSchema> = ParseOptionsResult<TSchema> & {
|
|
27
|
+
/** Unparsed raw values. */
|
|
28
|
+
rest: Record<string, RawOptionValue>;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Validates raw option values against a declarative option schema.
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseOptions<const TSchema extends OptionsSchema>(schema: TSchema, values: Record<string, RawOptionValue>): InferOptions<TSchema>;
|
|
34
|
+
/**
|
|
35
|
+
* Validates raw option values and returns parsed values with user-provided
|
|
36
|
+
* metadata.
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseOptionsDetailed<const TSchema extends OptionsSchema>(schema: TSchema, values: Record<string, RawOptionValue>): ParseOptionsResult<TSchema>;
|
|
39
|
+
/**
|
|
40
|
+
* Validates only raw option values known by the given schema and leaves the
|
|
41
|
+
* remaining raw options untouched.
|
|
42
|
+
*/
|
|
43
|
+
export declare function parseOptionsSubsetDetailed<const TSchema extends OptionsSchema>(schema: TSchema, values: Record<string, RawOptionValue>): ParseOptionsSubsetResult<TSchema>;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* The option
|
|
3
|
+
* The option parser module validates raw option values against declarative
|
|
4
4
|
* primitive option contracts.
|
|
5
5
|
*
|
|
6
6
|
* Allowed here:
|
|
7
|
-
* - defining string, boolean, and number option contracts;
|
|
8
7
|
* - applying and validating default values;
|
|
9
8
|
* - producing typed option values and user-provided metadata;
|
|
10
9
|
*
|
|
@@ -12,18 +11,10 @@
|
|
|
12
11
|
* application-specific validation rules.
|
|
13
12
|
*/
|
|
14
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.mergeOptionsSchema = mergeOptionsSchema;
|
|
16
14
|
exports.parseOptions = parseOptions;
|
|
17
15
|
exports.parseOptionsDetailed = parseOptionsDetailed;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
* Merges option schemas while preserving literal option definition types.
|
|
21
|
-
*
|
|
22
|
-
* Later schemas override earlier schemas with the same option name.
|
|
23
|
-
*/
|
|
24
|
-
function mergeOptionsSchema(schema, ...schemas) {
|
|
25
|
-
return Object.assign({}, schema, ...schemas);
|
|
26
|
-
}
|
|
16
|
+
exports.parseOptionsSubsetDetailed = parseOptionsSubsetDetailed;
|
|
17
|
+
const icore_error_1 = require("../errors/icore-error");
|
|
27
18
|
/**
|
|
28
19
|
* Validates raw option values against a declarative option schema.
|
|
29
20
|
*/
|
|
@@ -67,6 +58,25 @@ function parseOptionsDetailed(schema, values) {
|
|
|
67
58
|
provided: provided
|
|
68
59
|
};
|
|
69
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Validates only raw option values known by the given schema and leaves the
|
|
63
|
+
* remaining raw options untouched.
|
|
64
|
+
*/
|
|
65
|
+
function parseOptionsSubsetDetailed(schema, values) {
|
|
66
|
+
const subsetValues = {};
|
|
67
|
+
const rest = {};
|
|
68
|
+
for (const [name, value] of Object.entries(values)) {
|
|
69
|
+
if (Object.hasOwn(schema, name)) {
|
|
70
|
+
subsetValues[name] = value;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
rest[name] = value;
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
...parseOptionsDetailed(schema, subsetValues),
|
|
77
|
+
rest
|
|
78
|
+
};
|
|
79
|
+
}
|
|
70
80
|
function parseOptionValue(name, definition, value) {
|
|
71
81
|
if (definition.type === 'string') {
|
|
72
82
|
return parseStringOption(name, definition, value);
|
|
@@ -189,13 +199,13 @@ function assertChoice(name, choices, value, source = 'value') {
|
|
|
189
199
|
throw createInvalidOptionChoiceError(name, choices, value, message);
|
|
190
200
|
}
|
|
191
201
|
function createUnexpectedArgumentError(name) {
|
|
192
|
-
return new
|
|
202
|
+
return new icore_error_1.IcoreError('UNEXPECTED_ARGUMENT', `Unexpected argument '--${name}'`, {
|
|
193
203
|
argument: `--${name}`,
|
|
194
204
|
option: name
|
|
195
205
|
});
|
|
196
206
|
}
|
|
197
207
|
function createExpectedRequiredArgumentError(name) {
|
|
198
|
-
return new
|
|
208
|
+
return new icore_error_1.IcoreError('EXPECTED_REQUIRED_ARGUMENT', `Expected required argument '--${name}'`, {
|
|
199
209
|
argument: `--${name}`,
|
|
200
210
|
option: name
|
|
201
211
|
});
|
|
@@ -213,14 +223,14 @@ function createExpectedDefaultError(name, expected, value) {
|
|
|
213
223
|
});
|
|
214
224
|
}
|
|
215
225
|
function createInvalidOptionTypeError(name, message, details) {
|
|
216
|
-
return new
|
|
226
|
+
return new icore_error_1.IcoreError('INVALID_OPTION_TYPE', message, {
|
|
217
227
|
argument: `--${name}`,
|
|
218
228
|
option: name,
|
|
219
229
|
...details
|
|
220
230
|
});
|
|
221
231
|
}
|
|
222
232
|
function createInvalidOptionChoiceError(name, choices, value, message) {
|
|
223
|
-
return new
|
|
233
|
+
return new icore_error_1.IcoreError('INVALID_OPTION_CHOICE', message, {
|
|
224
234
|
argument: `--${name}`,
|
|
225
235
|
option: name,
|
|
226
236
|
choices: [...choices],
|
|
@@ -228,7 +238,7 @@ function createInvalidOptionChoiceError(name, choices, value, message) {
|
|
|
228
238
|
});
|
|
229
239
|
}
|
|
230
240
|
function createInvalidOptionDefaultError(name, message, details) {
|
|
231
|
-
return new
|
|
241
|
+
return new icore_error_1.IcoreError('INVALID_OPTION_DEFAULT', message, {
|
|
232
242
|
argument: `--${name}`,
|
|
233
243
|
option: name,
|
|
234
244
|
...details
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The option schema module
|
|
3
|
-
*
|
|
2
|
+
* The option schema module defines declarative primitive option contracts and
|
|
3
|
+
* their inferred TypeScript result types.
|
|
4
4
|
*
|
|
5
5
|
* Allowed here:
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
6
|
+
* - string, boolean, and number option contracts;
|
|
7
|
+
* - schema merge mechanics;
|
|
8
|
+
* - inferred parsed option and provided-option types;
|
|
9
9
|
*
|
|
10
|
-
* This file must not contain argv tokenization,
|
|
11
|
-
*
|
|
10
|
+
* This file must not contain argv tokenization, value validation, or command
|
|
11
|
+
* resolution.
|
|
12
12
|
*/
|
|
13
13
|
type OptionBase<TType extends string, TValue> = {
|
|
14
|
+
/** Primitive option kind. */
|
|
14
15
|
type: TType;
|
|
16
|
+
/** One-letter short alias. */
|
|
15
17
|
alias?: string;
|
|
18
|
+
/** Requires an explicit value. */
|
|
16
19
|
required?: boolean;
|
|
17
20
|
default?: TValue;
|
|
18
21
|
};
|
|
@@ -30,6 +33,7 @@ export type RawOptionValue = string | boolean;
|
|
|
30
33
|
* is declared with `as const`.
|
|
31
34
|
*/
|
|
32
35
|
export type StringOption<TChoices extends readonly string[] = readonly string[]> = OptionBase<'string', TChoices[number] | string> & {
|
|
36
|
+
/** Allowed string values. */
|
|
33
37
|
choices?: TChoices;
|
|
34
38
|
};
|
|
35
39
|
/**
|
|
@@ -39,6 +43,7 @@ export type StringOption<TChoices extends readonly string[] = readonly string[]>
|
|
|
39
43
|
* syntax is enforced.
|
|
40
44
|
*/
|
|
41
45
|
export type BooleanOption = OptionBase<'boolean', boolean> & {
|
|
46
|
+
/** Restricts boolean syntax. */
|
|
42
47
|
syntax?: 'flag';
|
|
43
48
|
};
|
|
44
49
|
/**
|
|
@@ -48,9 +53,13 @@ export type BooleanOption = OptionBase<'boolean', boolean> & {
|
|
|
48
53
|
* bounds.
|
|
49
54
|
*/
|
|
50
55
|
export type NumberOption<TChoices extends readonly number[] = readonly number[]> = OptionBase<'number', TChoices[number] | number> & {
|
|
56
|
+
/** Allowed numeric values. */
|
|
51
57
|
choices?: TChoices;
|
|
58
|
+
/** Requires a whole number. */
|
|
52
59
|
integer?: boolean;
|
|
60
|
+
/** Inclusive lower bound. */
|
|
53
61
|
min?: number;
|
|
62
|
+
/** Inclusive upper bound. */
|
|
54
63
|
max?: number;
|
|
55
64
|
};
|
|
56
65
|
/**
|
|
@@ -109,26 +118,10 @@ export type InferOptions<TSchema extends OptionsSchema> = {
|
|
|
109
118
|
export type InferProvidedOptions<TSchema extends OptionsSchema> = {
|
|
110
119
|
[TName in keyof TSchema]: boolean;
|
|
111
120
|
};
|
|
112
|
-
/**
|
|
113
|
-
* Detailed option parsing result with values and user-provided metadata.
|
|
114
|
-
*/
|
|
115
|
-
export type ParseOptionsResult<TSchema extends OptionsSchema> = {
|
|
116
|
-
options: InferOptions<TSchema>;
|
|
117
|
-
provided: InferProvidedOptions<TSchema>;
|
|
118
|
-
};
|
|
119
121
|
/**
|
|
120
122
|
* Merges option schemas while preserving literal option definition types.
|
|
121
123
|
*
|
|
122
124
|
* Later schemas override earlier schemas with the same option name.
|
|
123
125
|
*/
|
|
124
126
|
export declare function mergeOptionsSchema<const TSchema extends OptionsSchema, const TSchemas extends readonly OptionsSchema[]>(schema: TSchema, ...schemas: TSchemas): MergeOptionsSchemas<readonly [TSchema, ...TSchemas]>;
|
|
125
|
-
/**
|
|
126
|
-
* Validates raw option values against a declarative option schema.
|
|
127
|
-
*/
|
|
128
|
-
export declare function parseOptions<const TSchema extends OptionsSchema>(schema: TSchema, values: Record<string, RawOptionValue>): InferOptions<TSchema>;
|
|
129
|
-
/**
|
|
130
|
-
* Validates raw option values and returns parsed values with user-provided
|
|
131
|
-
* metadata.
|
|
132
|
-
*/
|
|
133
|
-
export declare function parseOptionsDetailed<const TSchema extends OptionsSchema>(schema: TSchema, values: Record<string, RawOptionValue>): ParseOptionsResult<TSchema>;
|
|
134
127
|
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The option schema module defines declarative primitive option contracts and
|
|
4
|
+
* their inferred TypeScript result types.
|
|
5
|
+
*
|
|
6
|
+
* Allowed here:
|
|
7
|
+
* - string, boolean, and number option contracts;
|
|
8
|
+
* - schema merge mechanics;
|
|
9
|
+
* - inferred parsed option and provided-option types;
|
|
10
|
+
*
|
|
11
|
+
* This file must not contain argv tokenization, value validation, or command
|
|
12
|
+
* resolution.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.mergeOptionsSchema = mergeOptionsSchema;
|
|
16
|
+
/**
|
|
17
|
+
* Merges option schemas while preserving literal option definition types.
|
|
18
|
+
*
|
|
19
|
+
* Later schemas override earlier schemas with the same option name.
|
|
20
|
+
*/
|
|
21
|
+
function mergeOptionsSchema(schema, ...schemas) {
|
|
22
|
+
return Object.assign({}, schema, ...schemas);
|
|
23
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The output facade exposes semantic stdout and stderr write operations.
|
|
3
|
+
*
|
|
4
|
+
* Allowed here:
|
|
5
|
+
* - creating stdout/stderr writer channels;
|
|
6
|
+
* - delegating `write` to stdout and `error` to stderr;
|
|
7
|
+
*
|
|
8
|
+
* This file must not contain command semantics, rendering rules, or
|
|
9
|
+
* application-specific diagnostics.
|
|
10
|
+
*/
|
|
11
|
+
import type { BackpressureTextSink, TextWriter } from './text-writer';
|
|
12
|
+
export type Output = {
|
|
13
|
+
/** Writes regular output. */
|
|
14
|
+
write(chunk: string): unknown | Promise<unknown>;
|
|
15
|
+
/** Writes diagnostic output. */
|
|
16
|
+
error(chunk: string): unknown | Promise<unknown>;
|
|
17
|
+
stdout: TextWriter;
|
|
18
|
+
stderr: TextWriter;
|
|
19
|
+
};
|
|
20
|
+
export type OutputOptions = {
|
|
21
|
+
stdout?: BackpressureTextSink;
|
|
22
|
+
stderr?: BackpressureTextSink;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Creates semantic output methods while keeping raw stdout/stderr channels
|
|
26
|
+
* available for lower-level integrations.
|
|
27
|
+
*/
|
|
28
|
+
export declare function createOutput(options?: OutputOptions): Output;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The output facade exposes semantic stdout and stderr write operations.
|
|
4
|
+
*
|
|
5
|
+
* Allowed here:
|
|
6
|
+
* - creating stdout/stderr writer channels;
|
|
7
|
+
* - delegating `write` to stdout and `error` to stderr;
|
|
8
|
+
*
|
|
9
|
+
* This file must not contain command semantics, rendering rules, or
|
|
10
|
+
* application-specific diagnostics.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.createOutput = createOutput;
|
|
14
|
+
const node_writer_1 = require("./node-writer");
|
|
15
|
+
/**
|
|
16
|
+
* Creates semantic output methods while keeping raw stdout/stderr channels
|
|
17
|
+
* available for lower-level integrations.
|
|
18
|
+
*/
|
|
19
|
+
function createOutput(options = {}) {
|
|
20
|
+
const stdout = (0, node_writer_1.createStdoutWriter)(options.stdout);
|
|
21
|
+
const stderr = (0, node_writer_1.createStderrWriter)(options.stderr);
|
|
22
|
+
return {
|
|
23
|
+
write(chunk) {
|
|
24
|
+
return stdout.write(chunk);
|
|
25
|
+
},
|
|
26
|
+
error(chunk) {
|
|
27
|
+
return stderr.write(chunk);
|
|
28
|
+
},
|
|
29
|
+
stdout,
|
|
30
|
+
stderr
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Node writer module exposes stdout and stderr text writer factories.
|
|
3
|
+
*
|
|
4
|
+
* Allowed here:
|
|
5
|
+
* - binding Node-compatible writable streams to text writers;
|
|
6
|
+
*
|
|
7
|
+
* This file must not contain rendering rules or command semantics.
|
|
8
|
+
*/
|
|
9
|
+
import { type BackpressureTextSink, type TextWriter } from './text-writer';
|
|
10
|
+
/**
|
|
11
|
+
* Creates a stdout writer from an already selected Node-compatible sink.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createStdoutWriter(stdout?: BackpressureTextSink): TextWriter;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a stderr writer from an already selected Node-compatible sink.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createStderrWriter(stderr?: BackpressureTextSink): TextWriter;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The Node writer module exposes stdout and stderr text writer factories.
|
|
4
|
+
*
|
|
5
|
+
* Allowed here:
|
|
6
|
+
* - binding Node-compatible writable streams to text writers;
|
|
7
|
+
*
|
|
8
|
+
* This file must not contain rendering rules or command semantics.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.createStdoutWriter = createStdoutWriter;
|
|
12
|
+
exports.createStderrWriter = createStderrWriter;
|
|
13
|
+
const text_writer_1 = require("./text-writer");
|
|
14
|
+
/**
|
|
15
|
+
* Creates a stdout writer from an already selected Node-compatible sink.
|
|
16
|
+
*/
|
|
17
|
+
function createStdoutWriter(stdout = process.stdout) {
|
|
18
|
+
return (0, text_writer_1.createBackpressureTextWriter)(stdout);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates a stderr writer from an already selected Node-compatible sink.
|
|
22
|
+
*/
|
|
23
|
+
function createStderrWriter(stderr = process.stderr) {
|
|
24
|
+
return (0, text_writer_1.createBackpressureTextWriter)(stderr);
|
|
25
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The text writer module adapts writable text sinks to backpressure-aware
|
|
3
|
+
* writer contracts.
|
|
4
|
+
*
|
|
5
|
+
* Allowed here:
|
|
6
|
+
* - the minimal text writer contract;
|
|
7
|
+
* - promise-returning sink support;
|
|
8
|
+
* - Node-style `drain` waiting when a writable sink reports backpressure;
|
|
9
|
+
*
|
|
10
|
+
* This file must not contain stdout/stderr selection or command semantics.
|
|
11
|
+
*/
|
|
12
|
+
export type TextWriter = {
|
|
13
|
+
write(chunk: string): unknown | Promise<unknown>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Minimal writable stream shape accepted by icore output adapters.
|
|
17
|
+
*/
|
|
18
|
+
export type BackpressureTextSink = {
|
|
19
|
+
write(chunk: string): unknown;
|
|
20
|
+
/** Optional `drain` event hook. */
|
|
21
|
+
once?(event: 'drain', listener: () => void): unknown;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Creates a text writer that preserves writable-stream backpressure.
|
|
25
|
+
*
|
|
26
|
+
* Promise-returning sinks are awaited, and Node-style sinks returning `false`
|
|
27
|
+
* are resumed after their next `drain` event.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createBackpressureTextWriter(sink: BackpressureTextSink): TextWriter;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The text writer module adapts writable text sinks to backpressure-aware
|
|
4
|
+
* writer contracts.
|
|
5
|
+
*
|
|
6
|
+
* Allowed here:
|
|
7
|
+
* - the minimal text writer contract;
|
|
8
|
+
* - promise-returning sink support;
|
|
9
|
+
* - Node-style `drain` waiting when a writable sink reports backpressure;
|
|
10
|
+
*
|
|
11
|
+
* This file must not contain stdout/stderr selection or command semantics.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.createBackpressureTextWriter = createBackpressureTextWriter;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a text writer that preserves writable-stream backpressure.
|
|
17
|
+
*
|
|
18
|
+
* Promise-returning sinks are awaited, and Node-style sinks returning `false`
|
|
19
|
+
* are resumed after their next `drain` event.
|
|
20
|
+
*/
|
|
21
|
+
function createBackpressureTextWriter(sink) {
|
|
22
|
+
return {
|
|
23
|
+
async write(chunk) {
|
|
24
|
+
const writeResult = sink.write(chunk);
|
|
25
|
+
if (isPromiseLike(writeResult)) {
|
|
26
|
+
await writeResult;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (writeResult !== false) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (typeof sink.once !== 'function') {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
await waitForDrain(sink.once.bind(sink));
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function isPromiseLike(value) {
|
|
40
|
+
return (typeof value === 'object'
|
|
41
|
+
&& value !== null
|
|
42
|
+
&& 'then' in value
|
|
43
|
+
&& typeof value.then === 'function');
|
|
44
|
+
}
|
|
45
|
+
function waitForDrain(onceDrain) {
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
onceDrain('drain', resolve);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The presentation facade exposes reusable terminal view and rendering
|
|
3
|
+
* mechanics as a small semantic surface.
|
|
4
|
+
*
|
|
5
|
+
* Allowed here:
|
|
6
|
+
* - creating presentation view factories;
|
|
7
|
+
* - wiring generic JSON, CSV, and text table renderers;
|
|
8
|
+
* - exposing a single `render` method for terminal app composition;
|
|
9
|
+
*
|
|
10
|
+
* This file must not contain application report mapping, command execution, or
|
|
11
|
+
* stdout/stderr delivery.
|
|
12
|
+
*/
|
|
13
|
+
import { presentationFormats, type PresentationFormat } from './format-options';
|
|
14
|
+
import { type CsvRow, type PresentationResult, type PresentationViewFactory, type TextTableRow } from './view';
|
|
15
|
+
export type PresentationRenderers = {
|
|
16
|
+
json: {
|
|
17
|
+
render(value: unknown): string;
|
|
18
|
+
};
|
|
19
|
+
table: {
|
|
20
|
+
render(rows: readonly TextTableRow[]): string;
|
|
21
|
+
};
|
|
22
|
+
csv: {
|
|
23
|
+
render(rows: readonly CsvRow[]): string;
|
|
24
|
+
renderRow(row: CsvRow): string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export type Presentation = PresentationViewFactory & {
|
|
28
|
+
formats: typeof presentationFormats;
|
|
29
|
+
render(result: PresentationResult, format?: PresentationFormat): string;
|
|
30
|
+
renderers: PresentationRenderers;
|
|
31
|
+
};
|
|
32
|
+
export type { PresentationResult } from './view';
|
|
33
|
+
/**
|
|
34
|
+
* Creates the presentation facade used by terminal applications.
|
|
35
|
+
*
|
|
36
|
+
* The facade owns generic rendering mechanics only; callers still map their
|
|
37
|
+
* domain objects to presentation views.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createPresentation(): Presentation;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The presentation facade exposes reusable terminal view and rendering
|
|
4
|
+
* mechanics as a small semantic surface.
|
|
5
|
+
*
|
|
6
|
+
* Allowed here:
|
|
7
|
+
* - creating presentation view factories;
|
|
8
|
+
* - wiring generic JSON, CSV, and text table renderers;
|
|
9
|
+
* - exposing a single `render` method for terminal app composition;
|
|
10
|
+
*
|
|
11
|
+
* This file must not contain application report mapping, command execution, or
|
|
12
|
+
* stdout/stderr delivery.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.createPresentation = createPresentation;
|
|
16
|
+
const format_options_1 = require("./format-options");
|
|
17
|
+
const csv_1 = require("./renderers/csv");
|
|
18
|
+
const json_1 = require("./renderers/json");
|
|
19
|
+
const table_1 = require("./renderers/table");
|
|
20
|
+
const result_renderer_1 = require("./result-renderer");
|
|
21
|
+
const view_1 = require("./view");
|
|
22
|
+
/**
|
|
23
|
+
* Creates the presentation facade used by terminal applications.
|
|
24
|
+
*
|
|
25
|
+
* The facade owns generic rendering mechanics only; callers still map their
|
|
26
|
+
* domain objects to presentation views.
|
|
27
|
+
*/
|
|
28
|
+
function createPresentation() {
|
|
29
|
+
const viewFactory = (0, view_1.createPresentationViewFactory)();
|
|
30
|
+
return {
|
|
31
|
+
...viewFactory,
|
|
32
|
+
formats: format_options_1.presentationFormats,
|
|
33
|
+
render: result_renderer_1.renderPresentationResult,
|
|
34
|
+
renderers: {
|
|
35
|
+
json: {
|
|
36
|
+
render: json_1.renderJson
|
|
37
|
+
},
|
|
38
|
+
table: {
|
|
39
|
+
render: table_1.renderTextTable
|
|
40
|
+
},
|
|
41
|
+
csv: {
|
|
42
|
+
render: csv_1.renderCsv,
|
|
43
|
+
renderRow: csv_1.renderCsvRow
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The presentation format options module defines shared output format
|
|
3
|
+
* contracts for terminal commands.
|
|
4
|
+
*
|
|
5
|
+
* Allowed here:
|
|
6
|
+
* - supported presentation format names;
|
|
7
|
+
* - reusable option schema for `--format`;
|
|
8
|
+
* - format guards for terminal app composition;
|
|
9
|
+
*
|
|
10
|
+
* This file must not contain rendering logic or command execution.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Supported output formats for the shared terminal presentation renderer.
|
|
14
|
+
*/
|
|
15
|
+
export declare const presentationFormats: readonly ["json", "table", "csv"];
|
|
16
|
+
/**
|
|
17
|
+
* Reusable `--format` option schema for commands that return presentation
|
|
18
|
+
* results.
|
|
19
|
+
*/
|
|
20
|
+
export declare const presentationFormatOptions: {
|
|
21
|
+
readonly format: {
|
|
22
|
+
readonly type: "string";
|
|
23
|
+
readonly choices: readonly ["json", "table", "csv"];
|
|
24
|
+
readonly default: "table";
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export type PresentationFormat = typeof presentationFormats[number];
|
|
28
|
+
/**
|
|
29
|
+
* Narrows unknown option values to supported presentation formats.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isPresentationFormat(value: unknown): value is PresentationFormat;
|