0
# Commands and Routing
1
2
Define commands and organize them into nested route maps.
3
4
## Quick Reference
5
6
```typescript
7
// Simple command
8
const cmd = buildCommand({
9
func: async function(flags, arg1, arg2) { /* ... */ },
10
parameters: { flags: { /* ... */ }, positional: { /* ... */ } },
11
docs: { brief: "Description" }
12
})
13
14
// Lazy-loaded command
15
const cmd = buildCommand({
16
loader: () => import("./commands/deploy.js"),
17
parameters: { /* ... */ },
18
docs: { brief: "Description" }
19
})
20
21
// Route map
22
const routes = buildRouteMap({
23
routes: { cmd1, cmd2, nested: nestedRouteMap },
24
defaultCommand: "cmd1", // optional
25
docs: { brief: "Description" },
26
aliases: { c: "cmd1" } // optional
27
})
28
```
29
30
## buildCommand
31
32
Builds a command from a function or loader with parameters and documentation.
33
34
```typescript { .api }
35
function buildCommand<FLAGS, ARGS, CONTEXT>(
36
builderArgs: CommandBuilderArguments<FLAGS, ARGS, CONTEXT>
37
): Command<CONTEXT>
38
```
39
40
**Local Function:**
41
42
```typescript
43
buildCommand({
44
func: async function(flags, ...args) {
45
this.process.stdout.write("Hello\n");
46
},
47
parameters: {
48
flags: { /* FlagParametersForType<FLAGS> */ },
49
positional: { /* TypedPositionalParameters<ARGS> */ },
50
aliases: { /* single-char to flag name mapping */ }
51
},
52
docs: {
53
brief: "Short description",
54
fullDescription: "Optional longer description"
55
}
56
})
57
```
58
59
**Lazy-Loaded Function:**
60
61
```typescript
62
buildCommand({
63
loader: async () => import("./commands/deploy.js"), // or () => CommandFunction
64
parameters: { /* ... */ },
65
docs: { /* ... */ }
66
})
67
68
// In commands/deploy.ts:
69
export default async function(flags, ...args) {
70
// Command implementation
71
}
72
```
73
74
**CommandFunction Signature:**
75
76
```typescript { .api }
77
type CommandFunction<FLAGS, ARGS, CONTEXT> = (
78
this: CONTEXT,
79
flags: FLAGS,
80
...args: ARGS
81
) => void | Error | Promise<void | Error>
82
```
83
84
**Validation:** Checks for reserved flags (`--help`, `--helpAll`, `-h`, `-H`), negation collisions, and variadic separators.
85
86
## buildRouteMap
87
88
Organizes commands into nested structures with optional default command and aliases.
89
90
```typescript { .api }
91
function buildRouteMap<R extends string, CONTEXT>(
92
args: RouteMapBuilderArguments<R, CONTEXT>
93
): RouteMap<CONTEXT>
94
```
95
96
**Example:**
97
98
```typescript
99
const dbRoutes = buildRouteMap({
100
routes: {
101
connect: connectCmd,
102
migrate: migrateCmd,
103
backup: backupCmd
104
},
105
defaultCommand: "connect", // Optional: runs when user types "myapp db"
106
docs: { brief: "Database commands" },
107
aliases: { c: "connect", m: "migrate", b: "backup" } // Optional
108
});
109
110
const app = buildApplication(
111
buildRouteMap({
112
routes: {
113
db: dbRoutes,
114
server: serverCmd
115
},
116
docs: { brief: "Application CLI" }
117
}),
118
{ name: "myapp" }
119
);
120
121
// Usage:
122
// myapp db connect --host localhost
123
// myapp db c --host localhost (using alias)
124
// myapp db (runs default connect command)
125
// myapp server --port 8080
126
```
127
128
**Validation:** Route map must contain at least one route, aliases can't conflict with route names, default command must be a Command (not another RouteMap).
129
130
## Complete Example
131
132
```typescript
133
import { buildApplication, buildRouteMap, buildCommand, numberParser } from "@stricli/core";
134
135
// Commands
136
const deployCmd = buildCommand({
137
func: async function(flags, service) {
138
this.process.stdout.write(`Deploying ${service} to ${flags.env}\n`);
139
},
140
parameters: {
141
flags: {
142
env: { kind: "enum", values: ["dev", "staging", "prod"], brief: "Environment", default: "dev" },
143
force: { kind: "boolean", brief: "Force deployment" }
144
},
145
positional: {
146
kind: "tuple",
147
parameters: [{ brief: "Service name", parse: String }]
148
},
149
aliases: { e: "env", f: "force" }
150
},
151
docs: { brief: "Deploy service" }
152
});
153
154
const statusCmd = buildCommand({
155
func: async function(flags) {
156
this.process.stdout.write(`Checking status (verbose: ${flags.verbose})\n`);
157
},
158
parameters: {
159
flags: {
160
verbose: { kind: "boolean", brief: "Verbose output", default: false }
161
},
162
aliases: { v: "verbose" }
163
},
164
docs: { brief: "Check status" }
165
});
166
167
// Route map
168
const app = buildApplication(
169
buildRouteMap({
170
routes: {
171
deploy: deployCmd,
172
status: statusCmd
173
},
174
docs: { brief: "Deployment CLI" }
175
}),
176
{
177
name: "myapp",
178
scanner: { caseStyle: "allow-kebab-for-camel" }
179
}
180
);
181
182
// Usage:
183
// myapp deploy api --env prod --force
184
// myapp deploy api -e prod -f
185
// myapp status --verbose
186
// myapp status -v
187
```
188
189
## Related
190
191
- [Flag Parameters](./flag-parameters.md)
192
- [Positional Parameters](./positional-parameters.md)
193
- [Configuration and Context](./configuration-and-context.md)
194