@loomcli/core 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/application.d.ts +44 -31
- package/dist/application.js +122 -110
- package/dist/bindings.d.ts +26 -0
- package/dist/bindings.js +45 -0
- package/dist/chain.d.ts +11 -6
- package/dist/chain.js +28 -81
- package/dist/command.d.ts +161 -84
- package/dist/command.js +650 -349
- package/dist/errors.d.ts +7 -2
- package/dist/errors.js +9 -1
- package/dist/extension.d.ts +3 -1
- package/dist/extension.js +8 -11
- package/dist/facts.d.ts +5 -0
- package/dist/facts.js +10 -3
- package/dist/globals.d.ts +45 -12
- package/dist/globals.js +74 -18
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -0
- package/dist/inspect.d.ts +25 -2
- package/dist/inspect.js +43 -5
- package/dist/locate.d.ts +41 -0
- package/dist/locate.js +121 -0
- package/dist/options.d.ts +73 -0
- package/dist/options.js +124 -27
- package/dist/output.d.ts +2 -0
- package/dist/output.js +5 -1
- package/dist/plugin.d.ts +107 -53
- package/dist/plugin.js +204 -66
- package/dist/sources.d.ts +56 -0
- package/dist/sources.js +249 -0
- package/dist/types.d.ts +65 -20
- package/dist/validation.d.ts +22 -8
- package/dist/validation.js +184 -77
- package/dist/view.d.ts +1 -1
- package/dist/view.js +2 -2
- package/package.json +3 -2
package/dist/chain.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { prepareDispatch, routeInvocation } from './command.js';
|
|
2
2
|
import { InternalError, reasonOf, routedSubject, toFailure } from './errors.js';
|
|
3
|
-
import { inspectGraph } from './inspect.js';
|
|
4
|
-
import {
|
|
5
|
-
import { pluginSentence } from './plugin.js';
|
|
3
|
+
import { inspectGraph, nodeAt } from './inspect.js';
|
|
4
|
+
import { isSupplied } from './options.js';
|
|
5
|
+
import { loadDefault, pluginSentence, pluginSpellings, pluginValues } from './plugin.js';
|
|
6
6
|
/**
|
|
7
7
|
* The view one run selects, which is one value whichever middleware wrote it. The assignment is
|
|
8
8
|
* kept as it arrived, because a JavaScript caller reaches the setter with any value and the check
|
|
@@ -72,79 +72,33 @@ class ViewSelection {
|
|
|
72
72
|
function isMiddlewareExport(value) {
|
|
73
73
|
return typeof value === 'function';
|
|
74
74
|
}
|
|
75
|
-
/** Whether one option name was supplied as a token, in any spelling a declaration accepts. */
|
|
76
|
-
function supplied(scan, name) {
|
|
77
|
-
return scan.strings.has(name) || scan.lists.has(name) || scan.booleans.has(name);
|
|
78
|
-
}
|
|
79
|
-
/** A collected value, or the declared array default, as this run's own copy. */
|
|
80
|
-
function collectedValue(collected, declared) {
|
|
81
|
-
if (collected) {
|
|
82
|
-
return [...collected];
|
|
83
|
-
}
|
|
84
|
-
return Array.isArray(declared) ? [...declared] : [];
|
|
85
|
-
}
|
|
86
75
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* that writes to what it received changes neither the declaration nor the next run.
|
|
76
|
+
* Whether one plugin's declared activation matched. A listed option activates when argv or an input
|
|
77
|
+
* source supplied it, whatever value it holds, and a declared default never does.
|
|
90
78
|
*/
|
|
91
|
-
function
|
|
92
|
-
const values = {};
|
|
93
|
-
for (const { config, name } of inputs) {
|
|
94
|
-
const declared = config.default;
|
|
95
|
-
if (config.type === 'boolean') {
|
|
96
|
-
values[name] = booleanValue(scan, name, config);
|
|
97
|
-
}
|
|
98
|
-
else if (config.multiple === true) {
|
|
99
|
-
values[name] = collectedValue(scan.lists.get(name), declared);
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
// Build already proved that a string option without a schema declares a string default.
|
|
103
|
-
values[name] =
|
|
104
|
-
scan.strings.get(name) ?? (typeof declared === 'string' ? declared : undefined);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return values;
|
|
108
|
-
}
|
|
109
|
-
/** Whether one plugin's declared activation matched the tokens the pre-scan consumed. */
|
|
110
|
-
function activates(installed, scan) {
|
|
79
|
+
function activates(installed, values) {
|
|
111
80
|
const { middleware } = installed;
|
|
112
81
|
if (!middleware) {
|
|
113
82
|
return false;
|
|
114
83
|
}
|
|
115
|
-
return (middleware.activate === 'always' || middleware.activate.some((name) =>
|
|
84
|
+
return (middleware.activate === 'always' || middleware.activate.some((name) => isSupplied(values, name)));
|
|
116
85
|
}
|
|
117
86
|
/**
|
|
118
87
|
* The chain for one invocation: each installed plugin whose activation matched, in installation
|
|
119
|
-
* order. Activation is read
|
|
120
|
-
* option
|
|
88
|
+
* order. Activation is read after the input-source stage and before any plugin code loads, so a
|
|
89
|
+
* plugin whose option no tier supplied is not in the chain and its loader is never called.
|
|
121
90
|
*/
|
|
122
|
-
function activatedEntries(plugins,
|
|
91
|
+
function activatedEntries(plugins, values) {
|
|
123
92
|
return plugins
|
|
124
|
-
.filter((installed) => activates(installed,
|
|
93
|
+
.filter((installed) => activates(installed, values))
|
|
125
94
|
.map((installed) => ({
|
|
126
95
|
identity: installed.identity,
|
|
127
96
|
// Activation proved the middleware exists, so the empty loader is never the one core calls.
|
|
128
97
|
load: installed.middleware?.load ?? (() => undefined),
|
|
129
|
-
options: pluginValues(installed.inputs,
|
|
98
|
+
options: pluginValues(installed.inputs, values),
|
|
99
|
+
spellings: pluginSpellings(installed.inputs, values),
|
|
130
100
|
}));
|
|
131
101
|
}
|
|
132
|
-
/**
|
|
133
|
-
* The routed node inside the inspected graph, which routing already proved reachable. A missing
|
|
134
|
-
* segment means the two readings of one graph disagree, so the chain stops rather than hand a
|
|
135
|
-
* middleware the wrong Command.
|
|
136
|
-
*/
|
|
137
|
-
function nodeAt(graph, path) {
|
|
138
|
-
let node = graph.root;
|
|
139
|
-
for (const name of path) {
|
|
140
|
-
const child = node.children.find((entry) => entry.name === name);
|
|
141
|
-
if (!child) {
|
|
142
|
-
throw new InternalError(`The routed command "${path.join(' ')}" is not in the inspected graph.`, undefined);
|
|
143
|
-
}
|
|
144
|
-
node = child;
|
|
145
|
-
}
|
|
146
|
-
return node;
|
|
147
|
-
}
|
|
148
102
|
/** A downstream promise core awaits for its completion alone; its outcome was recorded already. */
|
|
149
103
|
async function quiet(pending) {
|
|
150
104
|
if (pending) {
|
|
@@ -240,25 +194,12 @@ async function settle(turn, thrown) {
|
|
|
240
194
|
// The recorded failure still decides the exit code.
|
|
241
195
|
return reported(chain, state.outcome ?? (chain.invoked() ? 'dispatched' : 'taken-over'));
|
|
242
196
|
}
|
|
243
|
-
/** The module one loader answers with, whether it throws where it is called or rejects later. */
|
|
244
|
-
async function loadModule(entry) {
|
|
245
|
-
try {
|
|
246
|
-
return await entry.load();
|
|
247
|
-
}
|
|
248
|
-
catch (error) {
|
|
249
|
-
throw new InternalError(`Loading plugin "${entry.identity}" failed: ${reasonOf(error)}`, error);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
197
|
/** A plugin's module is loaded when the chain reaches it, never before. */
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
if (!isMiddlewareExport(handler)) {
|
|
259
|
-
throw new InternalError(`Loading plugin "${entry.identity}" failed: the module exports no default middleware function.`, undefined);
|
|
260
|
-
}
|
|
261
|
-
return handler;
|
|
198
|
+
function loadMiddleware(entry) {
|
|
199
|
+
return loadDefault(entry.identity, entry.load, {
|
|
200
|
+
guard: isMiddlewareExport,
|
|
201
|
+
noun: 'middleware',
|
|
202
|
+
});
|
|
262
203
|
}
|
|
263
204
|
/** One entry's turn: its module loads here, when the chain reaches it and never before. */
|
|
264
205
|
async function runEntry(entry, index, chain) {
|
|
@@ -278,7 +219,7 @@ async function runEntry(entry, index, chain) {
|
|
|
278
219
|
}
|
|
279
220
|
/** The whole chain, answering with the failure it raised when a middleware caught that failure. */
|
|
280
221
|
async function runChain(invocation, routed, prepared) {
|
|
281
|
-
const entries = activatedEntries(invocation.plugins,
|
|
222
|
+
const entries = activatedEntries(invocation.plugins, prepared.globals);
|
|
282
223
|
const run = { invoked: false, raised: undefined };
|
|
283
224
|
const selection = new ViewSelection(prepared.result);
|
|
284
225
|
/**
|
|
@@ -304,7 +245,7 @@ async function runChain(invocation, routed, prepared) {
|
|
|
304
245
|
return undefined;
|
|
305
246
|
}
|
|
306
247
|
// The graph a middleware reads is the one `inspect()` returns, built once for the run.
|
|
307
|
-
const graph =
|
|
248
|
+
const graph = invocation.inspected();
|
|
308
249
|
const command = nodeAt(graph, routed.path);
|
|
309
250
|
// Every fault this chain has reported, so the same one raised again carries no second report.
|
|
310
251
|
const announced = new WeakSet();
|
|
@@ -320,6 +261,7 @@ async function runChain(invocation, routed, prepared) {
|
|
|
320
261
|
out: invocation.out,
|
|
321
262
|
request: prepared.request,
|
|
322
263
|
signal: invocation.signal,
|
|
264
|
+
spellings: entry.spellings,
|
|
323
265
|
get view() {
|
|
324
266
|
return selection.read();
|
|
325
267
|
},
|
|
@@ -360,8 +302,13 @@ async function runChain(invocation, routed, prepared) {
|
|
|
360
302
|
async function runInvocation(invocation) {
|
|
361
303
|
const routed = routeInvocation(invocation.graph, invocation.host.argv);
|
|
362
304
|
invocation.route(routed.path);
|
|
363
|
-
|
|
364
|
-
|
|
305
|
+
// The graph `inspect()` returns, built at most once for the run.
|
|
306
|
+
// A configuration source reads its requests from it, and the chain reads it after the source.
|
|
307
|
+
let graph = undefined;
|
|
308
|
+
const inspected = () => (graph ??= inspectGraph(invocation.name, invocation.graph, invocation.facts));
|
|
309
|
+
const run = { ...invocation, inspected };
|
|
310
|
+
const prepared = await prepareDispatch(invocation.graph, routed, run);
|
|
311
|
+
const raised = await runChain(run, routed, prepared);
|
|
365
312
|
if (raised) {
|
|
366
313
|
// The chain resolved because a middleware caught the rejection.
|
|
367
314
|
// The failure it caught still decides the exit code.
|
package/dist/command.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { RegisteredGlobals } from './environment.js';
|
|
2
|
-
import type { DescriptorRegistry, ExtensionRecords, ExtensionValue } from './extension.js';
|
|
3
|
-
import type { BuiltGlobals, GlobalsState } from './globals.js';
|
|
2
|
+
import type { AnyExtension, DescriptorRegistry, ExtensionRecords, ExtensionStore, ExtensionSubject, ExtensionValue } from './extension.js';
|
|
3
|
+
import type { BuiltGlobals, GlobalsState, GlobalTable, InputRecords } from './globals.js';
|
|
4
|
+
import type { CommandGraph, CommandNode } from './inspect.js';
|
|
4
5
|
import { compileOptions } from './options.js';
|
|
5
6
|
import type { OptionValues } from './options.js';
|
|
6
|
-
import type { BuiltPlugin
|
|
7
|
+
import type { BuiltPlugin } from './plugin.js';
|
|
7
8
|
import type { ContextualStyle } from './style.js';
|
|
8
|
-
import type { Action, ActionChannel, ArgumentConfig, ArgumentValue, declaredTypes, DeclaredResult, DeclaredTypes, DefaultConstraint, GlobalNameConstraint, Host,
|
|
9
|
+
import type { Action, ActionChannel, ArgumentConfig, ArgumentValue, declaredTypes, DeclaredResult, DeclaredTypes, DefaultConstraint, GlobalNameConstraint, Host, PerValueConstraint, NameConstraint, OpenResult, OptionConfig, OptionValue, Out, Request, ResultBinding, ResultViews, ResultViewsOf, RowViews, ValidateOmittedConstraint } from './types.js';
|
|
9
10
|
import type { ArgumentInput, DefaultValues, InputDeclaration, OptionInput, ValidatedInputs } from './validation.js';
|
|
10
11
|
/** One positional slot: the declaration it fills and whether it takes the remaining tokens. */
|
|
11
12
|
export interface ArgumentSlot {
|
|
@@ -13,7 +14,15 @@ export interface ArgumentSlot {
|
|
|
13
14
|
required: boolean;
|
|
14
15
|
variadic: boolean;
|
|
15
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* What one dispatch hands its action. `graph` and `command` are the run's inspected graph and the
|
|
19
|
+
* routed node inside it, the values its middleware read. Each builds on its first read, so a run
|
|
20
|
+
* whose action reads neither, whose chain is empty, and which asks no configuration source renders
|
|
21
|
+
* no graph and calls no converter.
|
|
22
|
+
*/
|
|
16
23
|
export interface DispatchInput {
|
|
24
|
+
command: () => CommandNode;
|
|
25
|
+
graph: () => CommandGraph;
|
|
17
26
|
style: ContextualStyle;
|
|
18
27
|
host: Host;
|
|
19
28
|
/** The action's channel, whose `results` accepts whatever the routed declaration named. */
|
|
@@ -57,8 +66,8 @@ export interface BuiltCommand {
|
|
|
57
66
|
export declare const commandValue: unique symbol;
|
|
58
67
|
/**
|
|
59
68
|
* The input, alias, child, and action calls a Command can publish. Its type state is a subset,
|
|
60
|
-
* and each call removes the names it invalidates.
|
|
61
|
-
*
|
|
69
|
+
* and each call removes the names it invalidates. `command()` belongs to every Command and to the
|
|
70
|
+
* unnamed root alike, and attach bounds how deep the children it adds may nest.
|
|
62
71
|
*/
|
|
63
72
|
export type CommandMethod = 'action' | 'alias' | 'argument' | 'command' | 'option' | 'result' | 'rows';
|
|
64
73
|
/** One Command declares arguments or attaches children, so the first call removes the other. */
|
|
@@ -69,57 +78,48 @@ export type AfterCommand<State> = Exclude<State, 'argument'>;
|
|
|
69
78
|
export type AfterResult<State> = Exclude<State, 'result' | 'rows'>;
|
|
70
79
|
/** Registering the action closes input, alias, child, and further action declarations. */
|
|
71
80
|
export type AfterAction = never;
|
|
72
|
-
/** A declaration made after its authoring phase closed; build reports the first in call order. */
|
|
73
|
-
type LateDeclaration = {
|
|
74
|
-
alias: string;
|
|
75
|
-
kind: 'alias';
|
|
76
|
-
} | {
|
|
77
|
-
name: string;
|
|
78
|
-
kind: 'global';
|
|
79
|
-
} | {
|
|
80
|
-
child: object;
|
|
81
|
-
kind: 'child';
|
|
82
|
-
} | {
|
|
83
|
-
kind: 'result';
|
|
84
|
-
} | {
|
|
85
|
-
input: InputDeclaration;
|
|
86
|
-
kind: 'input';
|
|
87
|
-
};
|
|
88
81
|
/**
|
|
89
|
-
* The
|
|
90
|
-
*
|
|
82
|
+
* The private handle one graph node is reached through, without its inferred declaration types:
|
|
83
|
+
* what attach and the Application's walk read, and the build that compiles the node.
|
|
91
84
|
*/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
readonly name: string
|
|
85
|
+
export interface CommandNodeHandle {
|
|
86
|
+
readonly declared: Declared;
|
|
87
|
+
readonly hasAction: boolean;
|
|
88
|
+
readonly name: string;
|
|
96
89
|
build(context: BuildContext): BuiltCommand;
|
|
97
90
|
}
|
|
91
|
+
/** One attached child, under the canonical name its parent's namespace holds it by. */
|
|
92
|
+
export interface AttachedChild {
|
|
93
|
+
readonly name: string;
|
|
94
|
+
readonly node: CommandNodeHandle;
|
|
95
|
+
}
|
|
98
96
|
/**
|
|
99
|
-
* One graph build's shared state. `globals` compiles once and every Command reads it.
|
|
100
|
-
*
|
|
101
|
-
* is building a graph with more than one path to that node, not a tree. The build is a depth-first
|
|
102
|
-
* walk in attachment order, and a parent claims each child as the walk reaches it, so the first
|
|
103
|
-
* owner is the parent whose attachment the walk meets first.
|
|
97
|
+
* One graph build's shared state. `globals` compiles once and every Command reads it. The build is
|
|
98
|
+
* a depth-first walk in attachment order.
|
|
104
99
|
*/
|
|
105
100
|
interface BuildContext {
|
|
106
101
|
descriptors: DescriptorRegistry;
|
|
107
102
|
extensions: ExtensionRecords;
|
|
108
103
|
globals: BuiltGlobals;
|
|
109
|
-
owners: Map<CommandNodeHandle, string | null>;
|
|
110
104
|
/** The route from the root to the Command being built, which a lifecycle hook reads. */
|
|
111
105
|
path: readonly string[];
|
|
112
106
|
/** The installed plugins in installation order, whose hooks run over every Command. */
|
|
113
107
|
plugins: readonly BuiltPlugin[];
|
|
114
108
|
}
|
|
109
|
+
/** The handle behind a value an author built as a Command, or nothing for any other value. */
|
|
110
|
+
export declare function commandNode(value: unknown): CommandNodeHandle | undefined;
|
|
115
111
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
112
|
+
* The portable name rule, for every name an operator types as a command at a shell prompt: the
|
|
113
|
+
* application name, every Command name, and every alias. The characters are the POSIX portable
|
|
114
|
+
* filename set, and a name starts with neither `-`, which reads as an option, nor `.`, which a
|
|
115
|
+
* shell hides.
|
|
118
116
|
*/
|
|
117
|
+
export declare function isPortableName(name: unknown): name is string;
|
|
118
|
+
/** The one correction every portable name diagnostic ends with. */
|
|
119
|
+
export declare const portableNameCorrection = "Use a nonempty name of A-Z, a-z, 0-9, \".\", \"_\", and \"-\" that does not start with \"-\" or \".\".";
|
|
119
120
|
/**
|
|
120
121
|
* One call of the results lane, in the order it was made. A `result()` or `rows()` call declares
|
|
121
122
|
* the unit, and a `views()` call reshapes the views of whichever declaration it follows.
|
|
122
|
-
* Each record arrives unexamined, because build owns every rule the lane carries.
|
|
123
123
|
*/
|
|
124
124
|
export type ResultCall = {
|
|
125
125
|
kind: 'value' | 'rows';
|
|
@@ -129,64 +129,128 @@ export type ResultCall = {
|
|
|
129
129
|
kind: 'views';
|
|
130
130
|
views: unknown;
|
|
131
131
|
};
|
|
132
|
+
/** The core facts a named Command declares, which its constructor checked. The root carries none. */
|
|
133
|
+
export interface CommandFacts {
|
|
134
|
+
deprecated: string | undefined;
|
|
135
|
+
description: string | undefined;
|
|
136
|
+
hidden: boolean;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Everything one Command declaration holds, each part checked by the call that added it. The
|
|
140
|
+
* transitions below copy it with fields replaced, and the Command and Application builders share
|
|
141
|
+
* them, so one declaration call has one implementation.
|
|
142
|
+
*/
|
|
132
143
|
export interface CommandState<Args, Options, Globals> {
|
|
133
144
|
/**
|
|
134
|
-
* The registered
|
|
145
|
+
* The registered action, with the declared result erased. An action is stored under the widest
|
|
135
146
|
* result, so a handler typed from its own declaration stores here and the channel that carries
|
|
136
147
|
* the result is built for it at dispatch.
|
|
137
148
|
*/
|
|
138
|
-
|
|
139
|
-
aliases: readonly
|
|
149
|
+
action: Action<Args, Globals & Options, OpenResult> | undefined;
|
|
150
|
+
aliases: readonly string[];
|
|
140
151
|
bind: (values: ValidatedInputs) => {
|
|
141
152
|
args: Args;
|
|
142
153
|
options: Options;
|
|
143
154
|
};
|
|
144
|
-
children: readonly
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
155
|
+
children: readonly AttachedChild[];
|
|
156
|
+
/**
|
|
157
|
+
* Every descriptor this declaration's extension values name, by identity. The root's holds the
|
|
158
|
+
* whole Application's: its plugins', its global options', and every attached subtree's.
|
|
159
|
+
*/
|
|
160
|
+
descriptors: ReadonlyMap<string, AnyExtension>;
|
|
161
|
+
/** The extension values of every layer, validated at the call that carried each one. */
|
|
162
|
+
extensions: ExtensionStore;
|
|
163
|
+
facts: CommandFacts;
|
|
149
164
|
inputs: readonly InputDeclaration[];
|
|
150
|
-
late: readonly LateDeclaration[];
|
|
151
165
|
name: string | null;
|
|
152
|
-
|
|
166
|
+
/** The extension record each input's own call validated. */
|
|
167
|
+
records: InputRecords;
|
|
153
168
|
results: readonly ResultCall[];
|
|
154
169
|
}
|
|
170
|
+
/** The untyped part of a declaration, which every attach and build check reads. */
|
|
171
|
+
export type Declared = Pick<CommandState<unknown, unknown, unknown>, 'aliases' | 'children' | 'descriptors' | 'inputs' | 'name' | 'records' | 'results'>;
|
|
172
|
+
/** How the extension diagnostics of one Command's own layers name it. */
|
|
173
|
+
export declare function layerOf(name: string | null): ExtensionSubject;
|
|
155
174
|
/**
|
|
156
|
-
* The state every declaration starts from. The unnamed root and each named Command share it.
|
|
157
|
-
*
|
|
158
|
-
* passed changes nothing the declaration holds.
|
|
175
|
+
* The state every declaration starts from. The unnamed root and each named Command share it. The
|
|
176
|
+
* declaration values arrive checked, because the constructor that read them threw for any fault.
|
|
159
177
|
*/
|
|
160
178
|
export declare function freshState<Globals>(declaration: {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
hidden: unknown;
|
|
179
|
+
descriptors: ReadonlyMap<string, AnyExtension>;
|
|
180
|
+
extensions: ExtensionStore;
|
|
181
|
+
facts: CommandFacts;
|
|
165
182
|
name: string | null;
|
|
166
|
-
options: unknown;
|
|
167
183
|
}): CommandState<{}, {}, Globals>;
|
|
168
184
|
/** The declared value joins `args` under its literal name, typed by its own config. */
|
|
169
185
|
export declare function declareArgument<Args, Options, Globals, Name extends string, Config extends ArgumentConfig>(state: CommandState<Args, Options, Globals>, input: ArgumentInput<Name, Config>): CommandState<Args & Record<Name, ArgumentValue<Config>>, Options, Globals>;
|
|
170
|
-
/**
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
export declare function
|
|
176
|
-
/**
|
|
177
|
-
|
|
186
|
+
/**
|
|
187
|
+
* The declared value joins `options` under its literal name, typed by its own config. The root's
|
|
188
|
+
* options also meet the Application's globals table, which a named Command meets when its subtree
|
|
189
|
+
* joins an Application.
|
|
190
|
+
*/
|
|
191
|
+
export declare function declareOption<Args, Options, Globals, Name extends string, Config extends OptionConfig>(state: CommandState<Args, Options, Globals>, input: OptionInput<Name, Config>, table?: GlobalTable): CommandState<Args, Options & Record<Name, OptionValue<Config>>, Globals>;
|
|
192
|
+
/**
|
|
193
|
+
* One call's names join the Command's aliases. A call that names none, which the types reject and
|
|
194
|
+
* a JavaScript author can still write, reports as the call it is.
|
|
195
|
+
*/
|
|
196
|
+
export declare function declareAlias<Args, Options, Globals>(state: CommandState<Args, Options, Globals>, names: readonly string[]): CommandState<Args, Options, Globals>;
|
|
197
|
+
/**
|
|
198
|
+
* Extension layers remain open after inputs and the action have been fixed. Each layer is validated
|
|
199
|
+
* at its own call, against every descriptor the declaration already names.
|
|
200
|
+
*/
|
|
201
|
+
export declare function declareExtensions<Args, Options, Globals>(state: CommandState<Args, Options, Globals>, values: readonly unknown[]): CommandState<Args, Options, Globals>;
|
|
178
202
|
/**
|
|
179
203
|
* The handler is typed against the result its own declaration carries, and the state holds one
|
|
180
|
-
*
|
|
204
|
+
* action for every declaration, so the context the handler receives is read back at the call.
|
|
181
205
|
*/
|
|
182
206
|
export declare function declareAction<Args, Options, Globals, Result>(state: CommandState<Args, Options, Globals>, handler: Action<Args, Globals & Options, Result>): CommandState<Args, Options, Globals>;
|
|
183
|
-
/**
|
|
207
|
+
/**
|
|
208
|
+
* The result declaration, which closes both result calls. Every rule its own call can judge throws
|
|
209
|
+
* here; the empty record and the default wait for attach, because `views()` can still add keys.
|
|
210
|
+
*/
|
|
184
211
|
export declare function declareResult<Args, Options, Globals>(state: CommandState<Args, Options, Globals>, kind: 'value' | 'rows', declaration: unknown): CommandState<Args, Options, Globals>;
|
|
185
212
|
/** A `views()` call reshapes views and closes nothing, so it is never a late declaration. */
|
|
186
213
|
export declare function declareResultViews<Args, Options, Globals>(state: CommandState<Args, Options, Globals>, replacements: unknown, options: unknown): CommandState<Args, Options, Globals>;
|
|
187
|
-
/**
|
|
188
|
-
|
|
189
|
-
/**
|
|
214
|
+
/** The parent one attach reads: its name, the children it holds, and the calls that close it. */
|
|
215
|
+
interface AttachParent {
|
|
216
|
+
/** The first argument the parent declares, which no child may sit beside. */
|
|
217
|
+
argument: string | undefined;
|
|
218
|
+
children: readonly AttachedChild[];
|
|
219
|
+
hasAction: boolean;
|
|
220
|
+
name: string | null;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* The one attach operation `Command.command()`, `Application.command()`, and a plugin's
|
|
224
|
+
* `commands` list share. A Command is an immutable value, so the child is final here: it is checked
|
|
225
|
+
* as a finished Command, against the parent's current children, and against the nesting cap from
|
|
226
|
+
* the shallowest level the parent can sit at.
|
|
227
|
+
*/
|
|
228
|
+
export declare function attach(parent: AttachParent, node: CommandNodeHandle): AttachedChild;
|
|
229
|
+
/** The handle behind the value one `command()` call received; anything else is a declaration error. */
|
|
230
|
+
export declare function childNode(parent: string | null, child: unknown): CommandNodeHandle;
|
|
231
|
+
/** What an Application holds while a subtree joins it, each register a copy the caller commits. */
|
|
232
|
+
interface JoinScope {
|
|
233
|
+
descriptors: DescriptorRegistry;
|
|
234
|
+
/** The parent that claimed each node the Application holds, by the name a diagnostic reads. */
|
|
235
|
+
owners: Map<CommandNodeHandle, string | null>;
|
|
236
|
+
table: GlobalTable;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Attaches one child to an Application's root and walks the subtree it brings, once. The scope's
|
|
240
|
+
* registers are copies: the caller commits the owners, and the returned root holds the descriptors.
|
|
241
|
+
*/
|
|
242
|
+
export declare function attachToRoot<Args, Options, Globals>(state: CommandState<Args, Options, Globals>, node: CommandNodeHandle, scope: JoinScope): CommandState<Args, Options, Globals>;
|
|
243
|
+
/**
|
|
244
|
+
* A declaration's own options and every attached Command's, against a globals table that has just
|
|
245
|
+
* grown. The table's new option reads as the other side of any collision.
|
|
246
|
+
*/
|
|
247
|
+
export declare function checkDeclaredOptions(state: Declared, table: GlobalTable): void;
|
|
248
|
+
/**
|
|
249
|
+
* Compiles one declaration for dispatch against the shared globals table. Every authored rule threw
|
|
250
|
+
* at the call or the attach that first held its data, so what can still fail here is the root's
|
|
251
|
+
* finished-Command rules, the root never being attached, and whatever the lifecycle hooks
|
|
252
|
+
* contributed.
|
|
253
|
+
*/
|
|
190
254
|
export declare function buildCommand<Args, Options, Globals>(state: CommandState<Args, Options, Globals>, context: BuildContext): BuiltCommand;
|
|
191
255
|
/** One built graph: the shared globals table, the root Command, and the facts each node carries. */
|
|
192
256
|
export interface BuiltGraph {
|
|
@@ -194,20 +258,20 @@ export interface BuiltGraph {
|
|
|
194
258
|
globals: BuiltGlobals;
|
|
195
259
|
root: BuiltCommand;
|
|
196
260
|
}
|
|
197
|
-
/**
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
261
|
+
/**
|
|
262
|
+
* The globals table compiles once per build and the whole graph shares it. The root's registry
|
|
263
|
+
* holds every descriptor the Application names, so a hook's `extend()` call meets all of them.
|
|
264
|
+
*/
|
|
265
|
+
export declare function buildGraph<Args, Options, Globals>(root: CommandState<Args, Options, Globals>, globals: GlobalsState<Globals>, plugins: readonly BuiltPlugin[]): BuiltGraph;
|
|
201
266
|
export declare class CommandBuilder<Args, Options, Globals, State extends CommandMethod = CommandMethod, Result = unknown> {
|
|
202
267
|
#private;
|
|
203
268
|
readonly [commandValue]: true;
|
|
204
269
|
readonly [declaredTypes]: DeclaredTypes<Args, Options, Globals, Result>;
|
|
205
|
-
constructor(state: CommandState<Args, Options, Globals>);
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
option<const Name extends string, const Config extends OptionConfig>(name: Name, config: Config & NameConstraint<Name> & GlobalNameConstraint<Name, Globals> & NoInfer<DefaultConstraint<Config>> & NoInfer<MultipleConstraint<Config>> & NoInfer<ValidateOmittedConstraint<Config>>): Command<Args, Options & Record<Name, OptionValue<Config>>, Globals, State, Result>;
|
|
270
|
+
constructor(name: string, state: CommandState<Args, Options, Globals>);
|
|
271
|
+
argument<const Name extends string, const Config extends ArgumentConfig>(name: Name, config: Config & NameConstraint<Name> & NoInfer<DefaultConstraint<Config>> & NoInfer<PerValueConstraint<Config>> & NoInfer<ValidateOmittedConstraint<Config>>): Command<Args & Record<Name, ArgumentValue<Config>>, Options, Globals, AfterArgument<State>, Result>;
|
|
272
|
+
option<const Name extends string, const Config extends OptionConfig>(name: Name, config: Config & NameConstraint<Name> & GlobalNameConstraint<Name, Globals> & NoInfer<DefaultConstraint<Config>> & NoInfer<PerValueConstraint<Config>> & NoInfer<ValidateOmittedConstraint<Config>>): Command<Args, Options & Record<Name, OptionValue<Config>>, Globals, State, Result>;
|
|
209
273
|
/**
|
|
210
|
-
* Aliases are other
|
|
274
|
+
* Aliases are other portable names that route to this Command. They invalidate no call, and the
|
|
211
275
|
* tuple rest parameter rejects a call that names none.
|
|
212
276
|
*/
|
|
213
277
|
alias(...names: [string, ...string[]]): Command<Args, Options, Globals, State, Result>;
|
|
@@ -240,12 +304,6 @@ export declare class CommandBuilder<Args, Options, Globals, State extends Comman
|
|
|
240
304
|
/** The action closes input authoring; `extend()` remains outside this state transition. */
|
|
241
305
|
action(handler: Action<Args, Globals & Options, Result>): Command<Args, Options, Globals, AfterAction, Result>;
|
|
242
306
|
extend(...values: readonly ExtensionValue<'command'>[]): Command<Args, Options, Globals, State, Result>;
|
|
243
|
-
build(context: BuildContext): BuiltCommand;
|
|
244
|
-
/**
|
|
245
|
-
* The same runtime value in the state the calling method's return type names. Each call states
|
|
246
|
-
* its own transition, and the declared result travels with it unless the call replaces it.
|
|
247
|
-
*/
|
|
248
|
-
private derive;
|
|
249
307
|
}
|
|
250
308
|
/**
|
|
251
309
|
* The authoring surface of a Command in one type state. Every call returns a new declaration value,
|
|
@@ -282,12 +340,22 @@ type CommandConstructor = new (name: string, options?: CommandOptions) => Comman
|
|
|
282
340
|
export declare const Command: CommandConstructor;
|
|
283
341
|
/** Every declaration in the graph, so defaults are validated before any token is read. */
|
|
284
342
|
export declare function collectInputs(command: BuiltCommand): InputDeclaration[];
|
|
343
|
+
/**
|
|
344
|
+
* Whether a token names one of the Command's children: the Command has children and the token is
|
|
345
|
+
* no option token. Routing and `locate` read a bare word through this rule.
|
|
346
|
+
*/
|
|
347
|
+
export declare function readsAsChild(command: BuiltCommand, token: string): boolean;
|
|
285
348
|
/** Bare tokens, names or aliases, select children until a Command has none; a hyphen commits. */
|
|
286
349
|
export declare function route(root: BuiltCommand, tokens: readonly string[]): {
|
|
287
350
|
command: BuiltCommand;
|
|
288
351
|
path: string[];
|
|
289
352
|
tokens: string[];
|
|
290
353
|
};
|
|
354
|
+
/**
|
|
355
|
+
* The slot the positional at one index fills: the slot at that index, else a variadic last slot,
|
|
356
|
+
* which accepts every later positional, else none. Binding and `locate` read positions through it.
|
|
357
|
+
*/
|
|
358
|
+
export declare function argumentSlot(slots: readonly ArgumentSlot[], position: number): ArgumentSlot | undefined;
|
|
291
359
|
/** One invocation after the pre-scan and routing, which the middleware chain runs on top of. */
|
|
292
360
|
export interface RoutedInvocation {
|
|
293
361
|
command: BuiltCommand;
|
|
@@ -303,16 +371,23 @@ export interface DispatchInvocation {
|
|
|
303
371
|
channel: (binding: ResultBinding) => ActionChannel;
|
|
304
372
|
defaults: DefaultValues;
|
|
305
373
|
host: Host;
|
|
374
|
+
/** The graph `inspect()` returns for the run, built on its first read, which a source reads. */
|
|
375
|
+
inspected: () => CommandGraph;
|
|
306
376
|
signal: AbortSignal;
|
|
377
|
+
/** The channel a configuration source writes through, whose results call names the source. */
|
|
378
|
+
sourceOut: Out<OpenResult>;
|
|
307
379
|
style: ContextualStyle;
|
|
308
380
|
}
|
|
309
381
|
/**
|
|
310
382
|
* One invocation prepared ahead of the middleware chain. `'ready'` carries the request a middleware
|
|
311
383
|
* reads and the call that dispatches; `'held'` carries the fault this phase found, which core
|
|
312
384
|
* raises at the dispatch boundary and never before, so a takeover swallows it. `result` is what the
|
|
313
|
-
* routed Command declared, whose views a middleware selects among, on either shape.
|
|
385
|
+
* routed Command declared, whose views a middleware selects among, on either shape. `globals` holds
|
|
386
|
+
* the globals table's values after the input-source stage, which activation and every plugin's own
|
|
387
|
+
* options read on either shape.
|
|
314
388
|
*/
|
|
315
389
|
export type Prepared = {
|
|
390
|
+
globals: OptionValues;
|
|
316
391
|
result: DeclaredResult | undefined;
|
|
317
392
|
} & ({
|
|
318
393
|
dispatch: (view: string | null) => Promise<void>;
|
|
@@ -326,6 +401,8 @@ export type Prepared = {
|
|
|
326
401
|
/**
|
|
327
402
|
* Prepares one dispatch ahead of the middleware chain and holds whatever fault it found, so a
|
|
328
403
|
* middleware reads the request before the action runs and a takeover never observes the fault.
|
|
404
|
+
* The phases run in order: local parsing, the input-source stage, and validation. A local fault
|
|
405
|
+
* outranks a configuration source's fault, and after either one core runs no validation.
|
|
329
406
|
*/
|
|
330
407
|
export declare function prepareDispatch(graph: BuiltGraph, routed: RoutedInvocation, invocation: DispatchInvocation): Promise<Prepared>;
|
|
331
408
|
export {};
|