@optique/discover 1.1.0-dev.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 +20 -0
- package/README.md +124 -0
- package/dist/command-2HtR3-TV.d.cts +136 -0
- package/dist/command-BAVhIzfI.d.ts +136 -0
- package/dist/command-DZA06E08.cjs +45 -0
- package/dist/command-y_A3hG0g.js +33 -0
- package/dist/command.cjs +4 -0
- package/dist/command.d.cts +2 -0
- package/dist/command.d.ts +2 -0
- package/dist/command.js +3 -0
- package/dist/index.cjs +376 -0
- package/dist/index.d.cts +226 -0
- package/dist/index.d.ts +226 -0
- package/dist/index.js +348 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright 2025–2026 Hong Minhee
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
@optique/discover
|
|
2
|
+
=================
|
|
3
|
+
|
|
4
|
+
Runtime-aware command discovery for Optique CLI programs.
|
|
5
|
+
|
|
6
|
+
Use *@optique/discover* when your CLI has many commands and you want the
|
|
7
|
+
command tree to come from files instead of one large `or(command(...))`
|
|
8
|
+
definition. Each command module exports a `defineCommand()` result, and
|
|
9
|
+
`runProgram()` discovers those modules, builds a parser tree, enables help,
|
|
10
|
+
version, and shell completion, then dispatches to the selected command's
|
|
11
|
+
handler.
|
|
12
|
+
|
|
13
|
+
> [!WARNING]
|
|
14
|
+
> *@optique/discover* reads command files and imports them dynamically at
|
|
15
|
+
> runtime. It is a poor fit for CLIs that rely on aggressive tree shaking,
|
|
16
|
+
> static bundling, or single-file executable packaging. In those cases, use
|
|
17
|
+
> manually imported commands with `runProgram({ commands })`.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
Installation
|
|
21
|
+
------------
|
|
22
|
+
|
|
23
|
+
~~~~ bash
|
|
24
|
+
deno add jsr:@optique/discover jsr:@optique/core jsr:@optique/run
|
|
25
|
+
npm add @optique/discover @optique/core @optique/run
|
|
26
|
+
pnpm add @optique/discover @optique/core @optique/run
|
|
27
|
+
yarn add @optique/discover @optique/core @optique/run
|
|
28
|
+
~~~~
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
Quick example
|
|
32
|
+
-------------
|
|
33
|
+
|
|
34
|
+
Create command modules under a directory:
|
|
35
|
+
|
|
36
|
+
~~~~ typescript
|
|
37
|
+
// commands/user/add.ts
|
|
38
|
+
import { defineCommand } from "@optique/discover/command";
|
|
39
|
+
import { object } from "@optique/core/constructs";
|
|
40
|
+
import { message } from "@optique/core/message";
|
|
41
|
+
import { option } from "@optique/core/primitives";
|
|
42
|
+
import { string } from "@optique/core/valueparser";
|
|
43
|
+
|
|
44
|
+
export default defineCommand({
|
|
45
|
+
parser: object({
|
|
46
|
+
name: option("--name", string()),
|
|
47
|
+
}),
|
|
48
|
+
metadata: {
|
|
49
|
+
brief: message`Add a user.`,
|
|
50
|
+
},
|
|
51
|
+
handler(value) {
|
|
52
|
+
console.log(`Adding ${value.name}.`);
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
~~~~
|
|
56
|
+
|
|
57
|
+
Then run the discovered program from your entry point:
|
|
58
|
+
|
|
59
|
+
~~~~ typescript
|
|
60
|
+
// cli.ts
|
|
61
|
+
import { runProgram } from "@optique/discover";
|
|
62
|
+
import { message } from "@optique/core/message";
|
|
63
|
+
|
|
64
|
+
await runProgram({
|
|
65
|
+
dir: new URL("./commands/", import.meta.url),
|
|
66
|
+
metadata: {
|
|
67
|
+
name: "admin",
|
|
68
|
+
version: "1.0.0",
|
|
69
|
+
brief: message`Administrative command-line tools.`,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
~~~~
|
|
73
|
+
|
|
74
|
+
The file path becomes the command path, so the example above is available as:
|
|
75
|
+
|
|
76
|
+
~~~~ bash
|
|
77
|
+
admin user add --name Ada
|
|
78
|
+
admin --help
|
|
79
|
+
admin completion bash
|
|
80
|
+
~~~~
|
|
81
|
+
|
|
82
|
+
For bundlers and single-file packagers, import commands manually and declare
|
|
83
|
+
their paths in the command definitions:
|
|
84
|
+
|
|
85
|
+
~~~~ typescript
|
|
86
|
+
// cli.ts
|
|
87
|
+
import { defineCommand, runProgram } from "@optique/discover";
|
|
88
|
+
import { object } from "@optique/core/constructs";
|
|
89
|
+
import { message } from "@optique/core/message";
|
|
90
|
+
import { option } from "@optique/core/primitives";
|
|
91
|
+
import { string } from "@optique/core/valueparser";
|
|
92
|
+
|
|
93
|
+
const addUser = defineCommand({
|
|
94
|
+
path: ["user", "add"],
|
|
95
|
+
parser: object({
|
|
96
|
+
name: option("--name", string()),
|
|
97
|
+
}),
|
|
98
|
+
metadata: {
|
|
99
|
+
brief: message`Add a user.`,
|
|
100
|
+
},
|
|
101
|
+
handler(value) {
|
|
102
|
+
console.log(`Adding ${value.name}.`);
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
await runProgram({
|
|
107
|
+
commands: [addUser],
|
|
108
|
+
metadata: {
|
|
109
|
+
name: "admin",
|
|
110
|
+
version: "1.0.0",
|
|
111
|
+
brief: message`Administrative command-line tools.`,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
~~~~
|
|
115
|
+
|
|
116
|
+
By default, Deno and Bun discover `.ts`, `.mts`, `.js`, and `.mjs` files.
|
|
117
|
+
Node.js discovers `.js`, `.mjs`, and `.cjs` files, plus `.ts`, `.mts`, and
|
|
118
|
+
`.cts` when it reports native TypeScript support or runs with a recognized
|
|
119
|
+
TypeScript loader. TypeScript declaration files such as `.d.ts` are ignored.
|
|
120
|
+
|
|
121
|
+
For more resources, see the [docs] and the [*examples/*](/examples/)
|
|
122
|
+
directory.
|
|
123
|
+
|
|
124
|
+
[docs]: https://optique.dev/concepts/discover
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { CommandOptions } from "@optique/core/primitives";
|
|
2
|
+
import { Mode, Parser } from "@optique/core/parser";
|
|
3
|
+
|
|
4
|
+
//#region src/command.d.ts
|
|
5
|
+
declare const commandBrand: unique symbol;
|
|
6
|
+
/**
|
|
7
|
+
* Metadata shown for a discovered command.
|
|
8
|
+
*
|
|
9
|
+
* This uses the same shape as Optique's `command()` options so discovered
|
|
10
|
+
* commands can provide descriptions, usage overrides, visibility, and custom
|
|
11
|
+
* command-level errors.
|
|
12
|
+
*
|
|
13
|
+
* @since 1.1.0
|
|
14
|
+
*/
|
|
15
|
+
type CommandMetadata = CommandOptions;
|
|
16
|
+
/**
|
|
17
|
+
* Non-empty command path used by static command registration.
|
|
18
|
+
*
|
|
19
|
+
* @since 1.1.0
|
|
20
|
+
*/
|
|
21
|
+
type CommandPath = readonly [string, ...string[]];
|
|
22
|
+
/**
|
|
23
|
+
* Input accepted by {@link defineCommand}.
|
|
24
|
+
*
|
|
25
|
+
* @template M The mode of the command parser.
|
|
26
|
+
* @template T The parsed value passed to the command handler.
|
|
27
|
+
* @since 1.1.0
|
|
28
|
+
*/
|
|
29
|
+
interface CommandDefinition<M extends Mode, T> {
|
|
30
|
+
/**
|
|
31
|
+
* Command path used when commands are passed directly to `runProgram()`.
|
|
32
|
+
*
|
|
33
|
+
* File-based discovery derives the command path from the file name and uses
|
|
34
|
+
* this field only to validate that the declared path matches.
|
|
35
|
+
*/
|
|
36
|
+
readonly path?: CommandPath;
|
|
37
|
+
/**
|
|
38
|
+
* Parser for this command's command-specific arguments and options.
|
|
39
|
+
*/
|
|
40
|
+
readonly parser: Parser<M, T, unknown>;
|
|
41
|
+
/**
|
|
42
|
+
* Metadata used in help output and shell completion.
|
|
43
|
+
*/
|
|
44
|
+
readonly metadata?: CommandMetadata;
|
|
45
|
+
/**
|
|
46
|
+
* Handles the parsed command value.
|
|
47
|
+
*
|
|
48
|
+
* @param value Parsed command value.
|
|
49
|
+
* @returns Nothing, or a promise that resolves when command handling
|
|
50
|
+
* completes.
|
|
51
|
+
*/
|
|
52
|
+
readonly handler: (value: T) => void | Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A discovered command module definition.
|
|
56
|
+
*
|
|
57
|
+
* @template M The mode of the command parser.
|
|
58
|
+
* @template T The parsed value passed to the command handler.
|
|
59
|
+
* @since 1.1.0
|
|
60
|
+
*/
|
|
61
|
+
interface Command<M extends Mode, T> extends CommandDefinition<M, T> {
|
|
62
|
+
/**
|
|
63
|
+
* Internal marker used to validate discovered modules.
|
|
64
|
+
*
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
readonly [commandBrand]: true;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A command that declares its own command path.
|
|
71
|
+
*
|
|
72
|
+
* Static `runProgram({ commands })` registration accepts this shape.
|
|
73
|
+
*
|
|
74
|
+
* @template M The mode of the command parser.
|
|
75
|
+
* @template T The parsed value passed to the command handler.
|
|
76
|
+
* @since 1.1.0
|
|
77
|
+
*/
|
|
78
|
+
interface StaticCommand<M extends Mode, T> extends Command<M, T> {
|
|
79
|
+
/**
|
|
80
|
+
* Command path used by static command registration.
|
|
81
|
+
*/
|
|
82
|
+
readonly path: CommandPath;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A command with its handler value type erased.
|
|
86
|
+
*
|
|
87
|
+
* This type is used by discovery APIs that collect commands with different
|
|
88
|
+
* parsed value types. The handler cannot be called directly without first
|
|
89
|
+
* recovering the parser's value type.
|
|
90
|
+
*
|
|
91
|
+
* @since 1.1.0
|
|
92
|
+
*/
|
|
93
|
+
type AnyCommand = Omit<Command<Mode, unknown>, "handler"> & {
|
|
94
|
+
/**
|
|
95
|
+
* Erased command handler.
|
|
96
|
+
*/
|
|
97
|
+
readonly handler: (value: never) => void | Promise<void>;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* A statically registered command with its handler value type erased.
|
|
101
|
+
*
|
|
102
|
+
* @since 1.1.0
|
|
103
|
+
*/
|
|
104
|
+
type AnyStaticCommand = Omit<StaticCommand<Mode, unknown>, "handler"> & {
|
|
105
|
+
/**
|
|
106
|
+
* Erased command handler.
|
|
107
|
+
*/
|
|
108
|
+
readonly handler: (value: never) => void | Promise<void>;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Defines a command module for `@optique/discover`.
|
|
112
|
+
*
|
|
113
|
+
* This helper returns its argument unchanged while preserving parser value
|
|
114
|
+
* inference for the handler callback.
|
|
115
|
+
*
|
|
116
|
+
* @template M The mode of the command parser.
|
|
117
|
+
* @template T The parsed value passed to the command handler.
|
|
118
|
+
* @param command The command definition.
|
|
119
|
+
* @returns The same command definition with inferred types.
|
|
120
|
+
* @throws {TypeError} If the parser, path, or handler is missing or malformed.
|
|
121
|
+
* @since 1.1.0
|
|
122
|
+
*/
|
|
123
|
+
declare function defineCommand<M extends Mode, T>(command: CommandDefinition<M, T> & {
|
|
124
|
+
readonly path: CommandPath;
|
|
125
|
+
}): StaticCommand<M, T>;
|
|
126
|
+
declare function defineCommand<M extends Mode, T>(command: CommandDefinition<M, T>): Command<M, T>;
|
|
127
|
+
/**
|
|
128
|
+
* Returns whether a value is a command created by {@link defineCommand}.
|
|
129
|
+
*
|
|
130
|
+
* @param value The value to inspect.
|
|
131
|
+
* @returns `true` when the value is a discovered command definition.
|
|
132
|
+
* @since 1.1.0
|
|
133
|
+
*/
|
|
134
|
+
declare function isCommand(value: unknown): value is AnyCommand;
|
|
135
|
+
//#endregion
|
|
136
|
+
export { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand };
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { CommandOptions } from "@optique/core/primitives";
|
|
2
|
+
import { Mode, Parser } from "@optique/core/parser";
|
|
3
|
+
|
|
4
|
+
//#region src/command.d.ts
|
|
5
|
+
declare const commandBrand: unique symbol;
|
|
6
|
+
/**
|
|
7
|
+
* Metadata shown for a discovered command.
|
|
8
|
+
*
|
|
9
|
+
* This uses the same shape as Optique's `command()` options so discovered
|
|
10
|
+
* commands can provide descriptions, usage overrides, visibility, and custom
|
|
11
|
+
* command-level errors.
|
|
12
|
+
*
|
|
13
|
+
* @since 1.1.0
|
|
14
|
+
*/
|
|
15
|
+
type CommandMetadata = CommandOptions;
|
|
16
|
+
/**
|
|
17
|
+
* Non-empty command path used by static command registration.
|
|
18
|
+
*
|
|
19
|
+
* @since 1.1.0
|
|
20
|
+
*/
|
|
21
|
+
type CommandPath = readonly [string, ...string[]];
|
|
22
|
+
/**
|
|
23
|
+
* Input accepted by {@link defineCommand}.
|
|
24
|
+
*
|
|
25
|
+
* @template M The mode of the command parser.
|
|
26
|
+
* @template T The parsed value passed to the command handler.
|
|
27
|
+
* @since 1.1.0
|
|
28
|
+
*/
|
|
29
|
+
interface CommandDefinition<M extends Mode, T> {
|
|
30
|
+
/**
|
|
31
|
+
* Command path used when commands are passed directly to `runProgram()`.
|
|
32
|
+
*
|
|
33
|
+
* File-based discovery derives the command path from the file name and uses
|
|
34
|
+
* this field only to validate that the declared path matches.
|
|
35
|
+
*/
|
|
36
|
+
readonly path?: CommandPath;
|
|
37
|
+
/**
|
|
38
|
+
* Parser for this command's command-specific arguments and options.
|
|
39
|
+
*/
|
|
40
|
+
readonly parser: Parser<M, T, unknown>;
|
|
41
|
+
/**
|
|
42
|
+
* Metadata used in help output and shell completion.
|
|
43
|
+
*/
|
|
44
|
+
readonly metadata?: CommandMetadata;
|
|
45
|
+
/**
|
|
46
|
+
* Handles the parsed command value.
|
|
47
|
+
*
|
|
48
|
+
* @param value Parsed command value.
|
|
49
|
+
* @returns Nothing, or a promise that resolves when command handling
|
|
50
|
+
* completes.
|
|
51
|
+
*/
|
|
52
|
+
readonly handler: (value: T) => void | Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A discovered command module definition.
|
|
56
|
+
*
|
|
57
|
+
* @template M The mode of the command parser.
|
|
58
|
+
* @template T The parsed value passed to the command handler.
|
|
59
|
+
* @since 1.1.0
|
|
60
|
+
*/
|
|
61
|
+
interface Command<M extends Mode, T> extends CommandDefinition<M, T> {
|
|
62
|
+
/**
|
|
63
|
+
* Internal marker used to validate discovered modules.
|
|
64
|
+
*
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
readonly [commandBrand]: true;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A command that declares its own command path.
|
|
71
|
+
*
|
|
72
|
+
* Static `runProgram({ commands })` registration accepts this shape.
|
|
73
|
+
*
|
|
74
|
+
* @template M The mode of the command parser.
|
|
75
|
+
* @template T The parsed value passed to the command handler.
|
|
76
|
+
* @since 1.1.0
|
|
77
|
+
*/
|
|
78
|
+
interface StaticCommand<M extends Mode, T> extends Command<M, T> {
|
|
79
|
+
/**
|
|
80
|
+
* Command path used by static command registration.
|
|
81
|
+
*/
|
|
82
|
+
readonly path: CommandPath;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A command with its handler value type erased.
|
|
86
|
+
*
|
|
87
|
+
* This type is used by discovery APIs that collect commands with different
|
|
88
|
+
* parsed value types. The handler cannot be called directly without first
|
|
89
|
+
* recovering the parser's value type.
|
|
90
|
+
*
|
|
91
|
+
* @since 1.1.0
|
|
92
|
+
*/
|
|
93
|
+
type AnyCommand = Omit<Command<Mode, unknown>, "handler"> & {
|
|
94
|
+
/**
|
|
95
|
+
* Erased command handler.
|
|
96
|
+
*/
|
|
97
|
+
readonly handler: (value: never) => void | Promise<void>;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* A statically registered command with its handler value type erased.
|
|
101
|
+
*
|
|
102
|
+
* @since 1.1.0
|
|
103
|
+
*/
|
|
104
|
+
type AnyStaticCommand = Omit<StaticCommand<Mode, unknown>, "handler"> & {
|
|
105
|
+
/**
|
|
106
|
+
* Erased command handler.
|
|
107
|
+
*/
|
|
108
|
+
readonly handler: (value: never) => void | Promise<void>;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Defines a command module for `@optique/discover`.
|
|
112
|
+
*
|
|
113
|
+
* This helper returns its argument unchanged while preserving parser value
|
|
114
|
+
* inference for the handler callback.
|
|
115
|
+
*
|
|
116
|
+
* @template M The mode of the command parser.
|
|
117
|
+
* @template T The parsed value passed to the command handler.
|
|
118
|
+
* @param command The command definition.
|
|
119
|
+
* @returns The same command definition with inferred types.
|
|
120
|
+
* @throws {TypeError} If the parser, path, or handler is missing or malformed.
|
|
121
|
+
* @since 1.1.0
|
|
122
|
+
*/
|
|
123
|
+
declare function defineCommand<M extends Mode, T>(command: CommandDefinition<M, T> & {
|
|
124
|
+
readonly path: CommandPath;
|
|
125
|
+
}): StaticCommand<M, T>;
|
|
126
|
+
declare function defineCommand<M extends Mode, T>(command: CommandDefinition<M, T>): Command<M, T>;
|
|
127
|
+
/**
|
|
128
|
+
* Returns whether a value is a command created by {@link defineCommand}.
|
|
129
|
+
*
|
|
130
|
+
* @param value The value to inspect.
|
|
131
|
+
* @returns `true` when the value is a discovered command definition.
|
|
132
|
+
* @since 1.1.0
|
|
133
|
+
*/
|
|
134
|
+
declare function isCommand(value: unknown): value is AnyCommand;
|
|
135
|
+
//#endregion
|
|
136
|
+
export { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/command.ts
|
|
3
|
+
const commandBrand = Symbol.for("@optique/discover/command");
|
|
4
|
+
function defineCommand(command) {
|
|
5
|
+
if (!isParser(command.parser)) throw new TypeError("Command parser must be an Optique parser.");
|
|
6
|
+
if (command.path != null) validateCommandPath(command.path);
|
|
7
|
+
if (typeof command.handler !== "function") throw new TypeError("Command handler must be a function.");
|
|
8
|
+
return {
|
|
9
|
+
...command,
|
|
10
|
+
[commandBrand]: true
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Returns whether a value is a command created by {@link defineCommand}.
|
|
15
|
+
*
|
|
16
|
+
* @param value The value to inspect.
|
|
17
|
+
* @returns `true` when the value is a discovered command definition.
|
|
18
|
+
* @since 1.1.0
|
|
19
|
+
*/
|
|
20
|
+
function isCommand(value) {
|
|
21
|
+
return value != null && typeof value === "object" && value[commandBrand] === true && (value.path == null || isCommandPath(value.path)) && isParser(value.parser) && typeof value.handler === "function";
|
|
22
|
+
}
|
|
23
|
+
function validateCommandPath(path) {
|
|
24
|
+
if (!isCommandPath(path)) throw new TypeError("Command path must be a non-empty array of non-empty strings.");
|
|
25
|
+
}
|
|
26
|
+
function isCommandPath(path) {
|
|
27
|
+
return Array.isArray(path) && path.length > 0 && path.every((segment) => typeof segment === "string" && segment.length > 0);
|
|
28
|
+
}
|
|
29
|
+
function isParser(value) {
|
|
30
|
+
return value != null && typeof value === "object" && typeof value.parse === "function" && typeof value.complete === "function" && typeof value.suggest === "function" && typeof value.getDocFragments === "function" && (value.mode === "sync" || value.mode === "async");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
Object.defineProperty(exports, 'defineCommand', {
|
|
35
|
+
enumerable: true,
|
|
36
|
+
get: function () {
|
|
37
|
+
return defineCommand;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
Object.defineProperty(exports, 'isCommand', {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get: function () {
|
|
43
|
+
return isCommand;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/command.ts
|
|
2
|
+
const commandBrand = Symbol.for("@optique/discover/command");
|
|
3
|
+
function defineCommand(command) {
|
|
4
|
+
if (!isParser(command.parser)) throw new TypeError("Command parser must be an Optique parser.");
|
|
5
|
+
if (command.path != null) validateCommandPath(command.path);
|
|
6
|
+
if (typeof command.handler !== "function") throw new TypeError("Command handler must be a function.");
|
|
7
|
+
return {
|
|
8
|
+
...command,
|
|
9
|
+
[commandBrand]: true
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Returns whether a value is a command created by {@link defineCommand}.
|
|
14
|
+
*
|
|
15
|
+
* @param value The value to inspect.
|
|
16
|
+
* @returns `true` when the value is a discovered command definition.
|
|
17
|
+
* @since 1.1.0
|
|
18
|
+
*/
|
|
19
|
+
function isCommand(value) {
|
|
20
|
+
return value != null && typeof value === "object" && value[commandBrand] === true && (value.path == null || isCommandPath(value.path)) && isParser(value.parser) && typeof value.handler === "function";
|
|
21
|
+
}
|
|
22
|
+
function validateCommandPath(path) {
|
|
23
|
+
if (!isCommandPath(path)) throw new TypeError("Command path must be a non-empty array of non-empty strings.");
|
|
24
|
+
}
|
|
25
|
+
function isCommandPath(path) {
|
|
26
|
+
return Array.isArray(path) && path.length > 0 && path.every((segment) => typeof segment === "string" && segment.length > 0);
|
|
27
|
+
}
|
|
28
|
+
function isParser(value) {
|
|
29
|
+
return value != null && typeof value === "object" && typeof value.parse === "function" && typeof value.complete === "function" && typeof value.suggest === "function" && typeof value.getDocFragments === "function" && (value.mode === "sync" || value.mode === "async");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
export { defineCommand, isCommand };
|
package/dist/command.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand } from "./command-2HtR3-TV.cjs";
|
|
2
|
+
export { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand } from "./command-BAVhIzfI.js";
|
|
2
|
+
export { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand };
|
package/dist/command.js
ADDED