@optique/discover 1.1.0 → 1.2.0-dev.2169
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/README.md +21 -19
- package/dist/{command-DZA06E08.cjs → command-B0lV6NBO.cjs} +2 -2
- package/dist/{command-y_A3hG0g.js → command-DO5zgkvS.js} +2 -2
- package/dist/{command-2HtR3-TV.d.cts → command-DSHBTa5c.d.cts} +5 -2
- package/dist/{command-BAVhIzfI.d.ts → command-DyiVIMUh.d.ts} +5 -2
- package/dist/command.cjs +1 -1
- package/dist/command.d.cts +1 -1
- package/dist/command.d.ts +1 -1
- package/dist/command.js +1 -1
- package/dist/index.cjs +465 -58
- package/dist/index.d.cts +119 -8
- package/dist/index.d.ts +119 -8
- package/dist/index.js +467 -61
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -14,7 +14,8 @@ handler.
|
|
|
14
14
|
> *@optique/discover* reads command files and imports them dynamically at
|
|
15
15
|
> runtime. It is a poor fit for CLIs that rely on aggressive tree shaking,
|
|
16
16
|
> static bundling, or single-file executable packaging. In those cases, use
|
|
17
|
-
>
|
|
17
|
+
> `commandsFromModules()` with a static module map, or manually imported
|
|
18
|
+
> commands with `runProgram({ commands })`.
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
Installation
|
|
@@ -79,32 +80,23 @@ admin --help
|
|
|
79
80
|
admin completion bash
|
|
80
81
|
~~~~
|
|
81
82
|
|
|
82
|
-
For bundlers and single-file packagers,
|
|
83
|
-
|
|
83
|
+
For bundlers and single-file packagers, turn a static module map into command
|
|
84
|
+
entries:
|
|
84
85
|
|
|
85
86
|
~~~~ typescript
|
|
86
87
|
// cli.ts
|
|
87
|
-
import {
|
|
88
|
-
import { object } from "@optique/core/constructs";
|
|
88
|
+
import { commandsFromModules, runProgram } from "@optique/discover";
|
|
89
89
|
import { message } from "@optique/core/message";
|
|
90
|
-
import { option } from "@optique/core/primitives";
|
|
91
|
-
import { string } from "@optique/core/valueparser";
|
|
92
90
|
|
|
93
|
-
const
|
|
94
|
-
|
|
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
|
-
},
|
|
91
|
+
const modules = import.meta.glob("./commands/**/*.ts", {
|
|
92
|
+
eager: true,
|
|
104
93
|
});
|
|
105
94
|
|
|
106
95
|
await runProgram({
|
|
107
|
-
commands:
|
|
96
|
+
commands: commandsFromModules(modules, {
|
|
97
|
+
base: "./commands",
|
|
98
|
+
extensions: [".ts"],
|
|
99
|
+
}),
|
|
108
100
|
metadata: {
|
|
109
101
|
name: "admin",
|
|
110
102
|
version: "1.0.0",
|
|
@@ -113,10 +105,20 @@ await runProgram({
|
|
|
113
105
|
});
|
|
114
106
|
~~~~
|
|
115
107
|
|
|
108
|
+
`commandsFromModules()` preserves the file-based command layout while making
|
|
109
|
+
the module list visible to bundlers. For smaller registries, you can also
|
|
110
|
+
import commands manually, declare `path` in each `defineCommand()` call, and
|
|
111
|
+
pass those commands to `runProgram({ commands })`.
|
|
112
|
+
|
|
116
113
|
By default, Deno and Bun discover `.ts`, `.mts`, `.js`, and `.mjs` files.
|
|
117
114
|
Node.js discovers `.js`, `.mjs`, and `.cjs` files, plus `.ts`, `.mts`, and
|
|
118
115
|
`.cts` when it reports native TypeScript support or runs with a recognized
|
|
119
116
|
TypeScript loader. TypeScript declaration files such as `.d.ts` are ignored.
|
|
117
|
+
Entry files named `index` map to their containing command path, so
|
|
118
|
+
`commands/index.ts` defines the root command and `commands/user/index.ts`
|
|
119
|
+
defines `user`. Use `entryFileName` to choose another entry name or disable
|
|
120
|
+
this rule. `commandsFromModules()` applies the same path rules to module map
|
|
121
|
+
keys after stripping its `base` option.
|
|
120
122
|
|
|
121
123
|
For more resources, see the [docs] and the [*examples/*](/examples/)
|
|
122
124
|
directory.
|
|
@@ -21,10 +21,10 @@ function isCommand(value) {
|
|
|
21
21
|
return value != null && typeof value === "object" && value[commandBrand] === true && (value.path == null || isCommandPath(value.path)) && isParser(value.parser) && typeof value.handler === "function";
|
|
22
22
|
}
|
|
23
23
|
function validateCommandPath(path) {
|
|
24
|
-
if (!isCommandPath(path)) throw new TypeError("Command path must be
|
|
24
|
+
if (!isCommandPath(path)) throw new TypeError("Command path must be an array of non-empty strings.");
|
|
25
25
|
}
|
|
26
26
|
function isCommandPath(path) {
|
|
27
|
-
return Array.isArray(path) && path.
|
|
27
|
+
return Array.isArray(path) && path.every((segment) => typeof segment === "string" && segment.length > 0);
|
|
28
28
|
}
|
|
29
29
|
function isParser(value) {
|
|
30
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");
|
|
@@ -20,10 +20,10 @@ function isCommand(value) {
|
|
|
20
20
|
return value != null && typeof value === "object" && value[commandBrand] === true && (value.path == null || isCommandPath(value.path)) && isParser(value.parser) && typeof value.handler === "function";
|
|
21
21
|
}
|
|
22
22
|
function validateCommandPath(path) {
|
|
23
|
-
if (!isCommandPath(path)) throw new TypeError("Command path must be
|
|
23
|
+
if (!isCommandPath(path)) throw new TypeError("Command path must be an array of non-empty strings.");
|
|
24
24
|
}
|
|
25
25
|
function isCommandPath(path) {
|
|
26
|
-
return Array.isArray(path) && path.
|
|
26
|
+
return Array.isArray(path) && path.every((segment) => typeof segment === "string" && segment.length > 0);
|
|
27
27
|
}
|
|
28
28
|
function isParser(value) {
|
|
29
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");
|
|
@@ -14,11 +14,13 @@ declare const commandBrand: unique symbol;
|
|
|
14
14
|
*/
|
|
15
15
|
type CommandMetadata = CommandOptions;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Command path used by static command registration.
|
|
18
|
+
*
|
|
19
|
+
* An empty path represents the root command.
|
|
18
20
|
*
|
|
19
21
|
* @since 1.1.0
|
|
20
22
|
*/
|
|
21
|
-
type CommandPath = readonly
|
|
23
|
+
type CommandPath = readonly string[];
|
|
22
24
|
/**
|
|
23
25
|
* Input accepted by {@link defineCommand}.
|
|
24
26
|
*
|
|
@@ -29,6 +31,7 @@ type CommandPath = readonly [string, ...string[]];
|
|
|
29
31
|
interface CommandDefinition<M extends Mode, T> {
|
|
30
32
|
/**
|
|
31
33
|
* Command path used when commands are passed directly to `runProgram()`.
|
|
34
|
+
* Use an empty path (`[]`) to register the root command.
|
|
32
35
|
*
|
|
33
36
|
* File-based discovery derives the command path from the file name and uses
|
|
34
37
|
* this field only to validate that the declared path matches.
|
|
@@ -14,11 +14,13 @@ declare const commandBrand: unique symbol;
|
|
|
14
14
|
*/
|
|
15
15
|
type CommandMetadata = CommandOptions;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Command path used by static command registration.
|
|
18
|
+
*
|
|
19
|
+
* An empty path represents the root command.
|
|
18
20
|
*
|
|
19
21
|
* @since 1.1.0
|
|
20
22
|
*/
|
|
21
|
-
type CommandPath = readonly
|
|
23
|
+
type CommandPath = readonly string[];
|
|
22
24
|
/**
|
|
23
25
|
* Input accepted by {@link defineCommand}.
|
|
24
26
|
*
|
|
@@ -29,6 +31,7 @@ type CommandPath = readonly [string, ...string[]];
|
|
|
29
31
|
interface CommandDefinition<M extends Mode, T> {
|
|
30
32
|
/**
|
|
31
33
|
* Command path used when commands are passed directly to `runProgram()`.
|
|
34
|
+
* Use an empty path (`[]`) to register the root command.
|
|
32
35
|
*
|
|
33
36
|
* File-based discovery derives the command path from the file name and uses
|
|
34
37
|
* this field only to validate that the declared path matches.
|
package/dist/command.cjs
CHANGED
package/dist/command.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand } from "./command-
|
|
1
|
+
import { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand } from "./command-DSHBTa5c.cjs";
|
|
2
2
|
export { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand };
|
package/dist/command.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand } from "./command-
|
|
1
|
+
import { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand } from "./command-DyiVIMUh.js";
|
|
2
2
|
export { AnyCommand, AnyStaticCommand, Command, CommandDefinition, CommandMetadata, CommandPath, StaticCommand, defineCommand, isCommand };
|
package/dist/command.js
CHANGED