effect-start 0.17.2 → 0.19.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/dist/Development.d.ts +7 -2
- package/dist/Development.js +12 -6
- package/dist/PlatformRuntime.d.ts +4 -0
- package/dist/PlatformRuntime.js +9 -0
- package/dist/Route.d.ts +6 -2
- package/dist/Route.js +22 -0
- package/dist/RouteHttp.d.ts +1 -1
- package/dist/RouteHttp.js +12 -19
- package/dist/RouteMount.d.ts +2 -1
- package/dist/Start.d.ts +1 -5
- package/dist/Start.js +1 -8
- package/dist/Unique.d.ts +50 -0
- package/dist/Unique.js +187 -0
- package/dist/bun/BunHttpServer.js +5 -6
- package/dist/bun/BunRoute.d.ts +1 -1
- package/dist/bun/BunRoute.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/node/Effectify.d.ts +209 -0
- package/dist/node/Effectify.js +19 -0
- package/dist/node/FileSystem.d.ts +3 -5
- package/dist/node/FileSystem.js +42 -62
- package/dist/node/PlatformError.d.ts +46 -0
- package/dist/node/PlatformError.js +43 -0
- package/dist/testing/TestLogger.js +1 -1
- package/package.json +10 -5
- package/src/Development.ts +13 -18
- package/src/PlatformRuntime.ts +11 -0
- package/src/Route.ts +31 -2
- package/src/RouteHttp.ts +15 -31
- package/src/RouteMount.ts +1 -1
- package/src/Start.ts +1 -15
- package/src/Unique.ts +232 -0
- package/src/bun/BunHttpServer.ts +6 -9
- package/src/bun/BunRoute.ts +3 -3
- package/src/index.ts +1 -0
- package/src/node/Effectify.ts +262 -0
- package/src/node/FileSystem.ts +59 -97
- package/src/node/PlatformError.ts +102 -0
- package/src/testing/TestLogger.ts +1 -1
- package/dist/Random.d.ts +0 -5
- package/dist/Random.js +0 -49
- package/src/Commander.test.ts +0 -1639
- package/src/ContentNegotiation.test.ts +0 -603
- package/src/Development.test.ts +0 -119
- package/src/Entity.test.ts +0 -592
- package/src/FileRouterPattern.test.ts +0 -147
- package/src/FileRouter_files.test.ts +0 -64
- package/src/FileRouter_path.test.ts +0 -145
- package/src/FileRouter_tree.test.ts +0 -132
- package/src/Http.test.ts +0 -319
- package/src/HttpAppExtra.test.ts +0 -103
- package/src/HttpUtils.test.ts +0 -85
- package/src/PathPattern.test.ts +0 -648
- package/src/Random.ts +0 -59
- package/src/RouteBody.test.ts +0 -232
- package/src/RouteHook.test.ts +0 -40
- package/src/RouteHttp.test.ts +0 -2909
- package/src/RouteMount.test.ts +0 -481
- package/src/RouteSchema.test.ts +0 -427
- package/src/RouteSse.test.ts +0 -249
- package/src/RouteTree.test.ts +0 -494
- package/src/RouteTrie.test.ts +0 -322
- package/src/RouterPattern.test.ts +0 -676
- package/src/Values.test.ts +0 -263
- package/src/bun/BunBundle.test.ts +0 -268
- package/src/bun/BunBundle_imports.test.ts +0 -48
- package/src/bun/BunHttpServer.test.ts +0 -251
- package/src/bun/BunImportTrackerPlugin.test.ts +0 -77
- package/src/bun/BunRoute.test.ts +0 -162
- package/src/bundler/BundleHttp.test.ts +0 -132
- package/src/effect/HttpRouter.test.ts +0 -548
- package/src/experimental/EncryptedCookies.test.ts +0 -488
- package/src/hyper/HyperHtml.test.ts +0 -209
- package/src/hyper/HyperRoute.test.tsx +0 -197
- package/src/middlewares/BasicAuthMiddleware.test.ts +0 -84
- package/src/testing/TestHttpClient.test.ts +0 -83
- package/src/testing/TestLogger.test.ts +0 -51
- package/src/x/datastar/Datastar.test.ts +0 -266
- package/src/x/tailwind/TailwindPlugin.test.ts +0 -333
package/src/Commander.test.ts
DELETED
|
@@ -1,1639 +0,0 @@
|
|
|
1
|
-
import * as test from "bun:test"
|
|
2
|
-
import * as Effect from "effect/Effect"
|
|
3
|
-
import * as Schema from "effect/Schema"
|
|
4
|
-
import * as assert from "node:assert"
|
|
5
|
-
import * as Commander from "./Commander.ts"
|
|
6
|
-
|
|
7
|
-
test.describe(`${Commander.make.name}`, () => {
|
|
8
|
-
test.it("should create a basic command", () => {
|
|
9
|
-
const cmd = Commander.make({
|
|
10
|
-
name: "test-app",
|
|
11
|
-
description: "A test application",
|
|
12
|
-
})
|
|
13
|
-
test
|
|
14
|
-
.expect(cmd.name)
|
|
15
|
-
.toBe("test-app")
|
|
16
|
-
test
|
|
17
|
-
.expect(cmd.description)
|
|
18
|
-
.toBe("A test application")
|
|
19
|
-
})
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
test.describe(`${Commander.option.name} - nested builder API`, () => {
|
|
23
|
-
test.it("should add an option with schema", () => {
|
|
24
|
-
const cmd = Commander
|
|
25
|
-
.make({ name: "app" })
|
|
26
|
-
.option(
|
|
27
|
-
Commander
|
|
28
|
-
.option("--output", "-o")
|
|
29
|
-
.schema(Schema.String),
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
test
|
|
33
|
-
.expect(cmd.options.output)
|
|
34
|
-
.toBeDefined()
|
|
35
|
-
test
|
|
36
|
-
.expect(cmd.options.output.long)
|
|
37
|
-
.toBe("--output")
|
|
38
|
-
test
|
|
39
|
-
.expect(cmd.options.output.short)
|
|
40
|
-
.toBe("o")
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
test.it("should add option with description", () => {
|
|
44
|
-
const cmd = Commander
|
|
45
|
-
.make({ name: "app" })
|
|
46
|
-
.option(
|
|
47
|
-
Commander
|
|
48
|
-
.option("--output", "-o")
|
|
49
|
-
.description("Output file")
|
|
50
|
-
.schema(Schema.String),
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
test
|
|
54
|
-
.expect(cmd.options.output.description)
|
|
55
|
-
.toBe("Output file")
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
test.it("should add option with default value", () => {
|
|
59
|
-
const cmd = Commander
|
|
60
|
-
.make({ name: "app" })
|
|
61
|
-
.option(
|
|
62
|
-
Commander
|
|
63
|
-
.option("--count", "-c")
|
|
64
|
-
.default(10)
|
|
65
|
-
.schema(Commander.NumberFromString),
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
test
|
|
69
|
-
.expect(cmd.options.count.defaultValue)
|
|
70
|
-
.toBe(10)
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
test.it("should chain multiple options", () => {
|
|
74
|
-
const cmd = Commander
|
|
75
|
-
.make({ name: "app" })
|
|
76
|
-
.option(
|
|
77
|
-
Commander
|
|
78
|
-
.option("--input", "-i")
|
|
79
|
-
.schema(Schema.String),
|
|
80
|
-
)
|
|
81
|
-
.option(
|
|
82
|
-
Commander
|
|
83
|
-
.option("--output", "-o")
|
|
84
|
-
.schema(Schema.String),
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
test
|
|
88
|
-
.expect(cmd.options.input)
|
|
89
|
-
.toBeDefined()
|
|
90
|
-
test
|
|
91
|
-
.expect(cmd.options.output)
|
|
92
|
-
.toBeDefined()
|
|
93
|
-
test
|
|
94
|
-
.expect(cmd.options.input.long)
|
|
95
|
-
.toBe("--input")
|
|
96
|
-
test
|
|
97
|
-
.expect(cmd.options.output.long)
|
|
98
|
-
.toBe("--output")
|
|
99
|
-
})
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
test.describe(`${Commander.parse.name} - kebab-to-camel conversion`, () => {
|
|
103
|
-
test.it("should convert kebab-case to camelCase", async () => {
|
|
104
|
-
const cmd = Commander
|
|
105
|
-
.make({ name: "app" })
|
|
106
|
-
.option(
|
|
107
|
-
Commander
|
|
108
|
-
.option("--input-file")
|
|
109
|
-
.schema(Schema.String),
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
const result = await Effect.runPromise(
|
|
113
|
-
Commander.parse(cmd, ["--input-file", "test.txt"]),
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
test
|
|
117
|
-
.expect(result.inputFile)
|
|
118
|
-
.toBe("test.txt")
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
test.it("should handle single word options", async () => {
|
|
122
|
-
const cmd = Commander
|
|
123
|
-
.make({ name: "app" })
|
|
124
|
-
.option(
|
|
125
|
-
Commander
|
|
126
|
-
.option("--port")
|
|
127
|
-
.schema(Commander.NumberFromString),
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
const result = await Effect.runPromise(
|
|
131
|
-
Commander.parse(cmd, ["--port", "3000"]),
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
test
|
|
135
|
-
.expect(result.port)
|
|
136
|
-
.toBe(3000)
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
test.it("should parse short options", async () => {
|
|
140
|
-
const cmd = Commander
|
|
141
|
-
.make({ name: "app" })
|
|
142
|
-
.option(
|
|
143
|
-
Commander
|
|
144
|
-
.option("--port", "-p")
|
|
145
|
-
.schema(Commander.NumberFromString),
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
const result = await Effect.runPromise(
|
|
149
|
-
Commander.parse(cmd, ["-p", "8080"]),
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
test
|
|
153
|
-
.expect(result.port)
|
|
154
|
-
.toBe(8080)
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
test.it("should parse multiple options", async () => {
|
|
158
|
-
const cmd = Commander
|
|
159
|
-
.make({ name: "app" })
|
|
160
|
-
.option(
|
|
161
|
-
Commander
|
|
162
|
-
.option("--host", "-h")
|
|
163
|
-
.schema(Schema.String),
|
|
164
|
-
)
|
|
165
|
-
.option(
|
|
166
|
-
Commander
|
|
167
|
-
.option("--port", "-p")
|
|
168
|
-
.schema(Commander.NumberFromString),
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
const result = await Effect.runPromise(
|
|
172
|
-
Commander.parse(cmd, ["--host", "localhost", "--port", "3000"]),
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
test
|
|
176
|
-
.expect(result.host)
|
|
177
|
-
.toBe("localhost")
|
|
178
|
-
test
|
|
179
|
-
.expect(result.port)
|
|
180
|
-
.toBe(3000)
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
test.it("should handle options with equals syntax", async () => {
|
|
184
|
-
const cmd = Commander
|
|
185
|
-
.make({ name: "app" })
|
|
186
|
-
.option(
|
|
187
|
-
Commander
|
|
188
|
-
.option("--port")
|
|
189
|
-
.schema(Commander.NumberFromString),
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
const result = await Effect.runPromise(
|
|
193
|
-
Commander.parse(cmd, ["--port=3000"]),
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
test
|
|
197
|
-
.expect(result.port)
|
|
198
|
-
.toBe(3000)
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
test.it("should use default value when option not provided", async () => {
|
|
202
|
-
const cmd = Commander
|
|
203
|
-
.make({ name: "app" })
|
|
204
|
-
.option(
|
|
205
|
-
Commander
|
|
206
|
-
.option("--port", "-p")
|
|
207
|
-
.default(3000)
|
|
208
|
-
.schema(Commander.NumberFromString),
|
|
209
|
-
)
|
|
210
|
-
|
|
211
|
-
const result = await Effect.runPromise(
|
|
212
|
-
Commander.parse(cmd, []),
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
test
|
|
216
|
-
.expect(result.port)
|
|
217
|
-
.toBe(3000)
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
test.it("should override default when option specified", async () => {
|
|
221
|
-
const cmd = Commander
|
|
222
|
-
.make({ name: "app" })
|
|
223
|
-
.option(
|
|
224
|
-
Commander
|
|
225
|
-
.option("--port", "-p")
|
|
226
|
-
.default(3000)
|
|
227
|
-
.schema(Commander.NumberFromString),
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
const result = await Effect.runPromise(
|
|
231
|
-
Commander.parse(cmd, ["--port", "8080"]),
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
test
|
|
235
|
-
.expect(result.port)
|
|
236
|
-
.toBe(8080)
|
|
237
|
-
})
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
test.describe(`${Commander.optionHelp.name}`, () => {
|
|
241
|
-
test.it("should add help option", () => {
|
|
242
|
-
const cmd = Commander
|
|
243
|
-
.make({ name: "app" })
|
|
244
|
-
.optionHelp()
|
|
245
|
-
|
|
246
|
-
test
|
|
247
|
-
.expect(cmd.options.help)
|
|
248
|
-
.toBeDefined()
|
|
249
|
-
test
|
|
250
|
-
.expect(cmd.options.help.long)
|
|
251
|
-
.toBe("--help")
|
|
252
|
-
test
|
|
253
|
-
.expect(cmd.options.help.short)
|
|
254
|
-
.toBe("h")
|
|
255
|
-
})
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
test.describe(`${Commander.optionVersion.name}`, () => {
|
|
259
|
-
test.it("should add version option", () => {
|
|
260
|
-
const cmd = Commander
|
|
261
|
-
.make({ name: "app", version: "1.0.0" })
|
|
262
|
-
.optionVersion()
|
|
263
|
-
|
|
264
|
-
test
|
|
265
|
-
.expect(cmd.options.version)
|
|
266
|
-
.toBeDefined()
|
|
267
|
-
test
|
|
268
|
-
.expect(cmd.options.version.long)
|
|
269
|
-
.toBe("--version")
|
|
270
|
-
test
|
|
271
|
-
.expect(cmd.options.version.short)
|
|
272
|
-
.toBe("V")
|
|
273
|
-
})
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
test.describe(`${Commander.handle.name}`, () => {
|
|
277
|
-
test.it("should mark command as handled", () => {
|
|
278
|
-
const handled = Commander
|
|
279
|
-
.make({ name: "app" })
|
|
280
|
-
.option(
|
|
281
|
-
Commander
|
|
282
|
-
.option("--name", "-n")
|
|
283
|
-
.schema(Schema.String),
|
|
284
|
-
)
|
|
285
|
-
.handle((opts) => Effect.void)
|
|
286
|
-
|
|
287
|
-
const unhandled = Commander
|
|
288
|
-
.make({ name: "app2" })
|
|
289
|
-
.option(
|
|
290
|
-
Commander
|
|
291
|
-
.option("--name", "-n")
|
|
292
|
-
.schema(Schema.String),
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
test
|
|
296
|
-
.expect(handled.handler)
|
|
297
|
-
.toBeDefined()
|
|
298
|
-
test
|
|
299
|
-
.expect(unhandled.handler)
|
|
300
|
-
.toBeUndefined()
|
|
301
|
-
})
|
|
302
|
-
})
|
|
303
|
-
|
|
304
|
-
test.describe(`${Commander.subcommand.name}`, () => {
|
|
305
|
-
test.it("should add subcommand", () => {
|
|
306
|
-
const subCmd = Commander
|
|
307
|
-
.make({ name: "format" })
|
|
308
|
-
.option(
|
|
309
|
-
Commander
|
|
310
|
-
.option("--style")
|
|
311
|
-
.schema(Schema.String),
|
|
312
|
-
)
|
|
313
|
-
.handle((opts) => Effect.void)
|
|
314
|
-
|
|
315
|
-
const main = Commander
|
|
316
|
-
.make({ name: "main" })
|
|
317
|
-
.subcommand(subCmd)
|
|
318
|
-
|
|
319
|
-
test
|
|
320
|
-
.expect(main.subcommands.length)
|
|
321
|
-
.toBe(1)
|
|
322
|
-
test
|
|
323
|
-
.expect(main.subcommands[0]!.command.name)
|
|
324
|
-
.toBe("format")
|
|
325
|
-
})
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
test.describe(`${Commander.help.name}`, () => {
|
|
329
|
-
test.it("should generate help text", () => {
|
|
330
|
-
const cmd = Commander
|
|
331
|
-
.make({
|
|
332
|
-
name: "myapp",
|
|
333
|
-
description: "My awesome application",
|
|
334
|
-
version: "1.0.0",
|
|
335
|
-
})
|
|
336
|
-
.option(
|
|
337
|
-
Commander
|
|
338
|
-
.option("--output", "-o")
|
|
339
|
-
.description("Output file")
|
|
340
|
-
.schema(Schema.String),
|
|
341
|
-
)
|
|
342
|
-
.optionHelp()
|
|
343
|
-
|
|
344
|
-
const helpText = Commander.help(cmd)
|
|
345
|
-
|
|
346
|
-
test
|
|
347
|
-
.expect(helpText)
|
|
348
|
-
.toContain("My awesome application")
|
|
349
|
-
test
|
|
350
|
-
.expect(helpText)
|
|
351
|
-
.toContain("Usage: myapp [options]")
|
|
352
|
-
test
|
|
353
|
-
.expect(helpText)
|
|
354
|
-
.toContain("--output")
|
|
355
|
-
test
|
|
356
|
-
.expect(helpText)
|
|
357
|
-
.toContain("-o,")
|
|
358
|
-
test
|
|
359
|
-
.expect(helpText)
|
|
360
|
-
.toContain("Output file")
|
|
361
|
-
test
|
|
362
|
-
.expect(helpText)
|
|
363
|
-
.toContain("--help")
|
|
364
|
-
})
|
|
365
|
-
})
|
|
366
|
-
|
|
367
|
-
test.describe("BooleanFromString", () => {
|
|
368
|
-
test.it("should decode true value", async () => {
|
|
369
|
-
const result = await Effect.runPromise(
|
|
370
|
-
Schema.decode(Schema.BooleanFromString)("true"),
|
|
371
|
-
)
|
|
372
|
-
test
|
|
373
|
-
.expect(result)
|
|
374
|
-
.toBe(true)
|
|
375
|
-
})
|
|
376
|
-
|
|
377
|
-
test.it("should decode false value", async () => {
|
|
378
|
-
const result = await Effect.runPromise(
|
|
379
|
-
Schema.decode(Schema.BooleanFromString)("false"),
|
|
380
|
-
)
|
|
381
|
-
test
|
|
382
|
-
.expect(result)
|
|
383
|
-
.toBe(false)
|
|
384
|
-
})
|
|
385
|
-
})
|
|
386
|
-
|
|
387
|
-
test.describe(`${Commander.choice.name}`, () => {
|
|
388
|
-
test.it("should accept valid choice", async () => {
|
|
389
|
-
const ColorSchema = Schema.compose(
|
|
390
|
-
Schema.String,
|
|
391
|
-
Schema.Literal("red", "green", "blue"),
|
|
392
|
-
)
|
|
393
|
-
|
|
394
|
-
const result = await Effect.runPromise(
|
|
395
|
-
Schema.decode(ColorSchema)("red"),
|
|
396
|
-
)
|
|
397
|
-
|
|
398
|
-
test
|
|
399
|
-
.expect(result)
|
|
400
|
-
.toBe("red")
|
|
401
|
-
})
|
|
402
|
-
|
|
403
|
-
test.it("should fail on invalid choice", async () => {
|
|
404
|
-
const ColorSchema = Schema.compose(
|
|
405
|
-
Schema.String,
|
|
406
|
-
Schema.Literal("red", "green", "blue"),
|
|
407
|
-
)
|
|
408
|
-
|
|
409
|
-
const result = await Effect.runPromise(
|
|
410
|
-
Effect.either(Schema.decode(ColorSchema)("yellow")),
|
|
411
|
-
)
|
|
412
|
-
|
|
413
|
-
test
|
|
414
|
-
.expect(result._tag)
|
|
415
|
-
.toBe("Left")
|
|
416
|
-
})
|
|
417
|
-
})
|
|
418
|
-
|
|
419
|
-
test.describe(`${Commander.repeatable.name}`, () => {
|
|
420
|
-
test.it("should parse comma-separated values", async () => {
|
|
421
|
-
const schema = Commander.repeatable(Schema.String)
|
|
422
|
-
|
|
423
|
-
const result = await Effect.runPromise(
|
|
424
|
-
Schema.decode(schema)("foo,bar,baz"),
|
|
425
|
-
)
|
|
426
|
-
|
|
427
|
-
test
|
|
428
|
-
.expect(result)
|
|
429
|
-
.toEqual(["foo", "bar", "baz"])
|
|
430
|
-
})
|
|
431
|
-
|
|
432
|
-
test.it("should parse comma-separated numbers", async () => {
|
|
433
|
-
const schema = Commander.repeatable(Commander.NumberFromString)
|
|
434
|
-
|
|
435
|
-
const result = await Effect.runPromise(
|
|
436
|
-
Schema.decode(schema)("1,2,3,4,5"),
|
|
437
|
-
)
|
|
438
|
-
|
|
439
|
-
test
|
|
440
|
-
.expect(result)
|
|
441
|
-
.toEqual([1, 2, 3, 4, 5])
|
|
442
|
-
})
|
|
443
|
-
|
|
444
|
-
test.it("should trim whitespace", async () => {
|
|
445
|
-
const schema = Commander.repeatable(Schema.String)
|
|
446
|
-
|
|
447
|
-
const result = await Effect.runPromise(
|
|
448
|
-
Schema.decode(schema)("foo, bar , baz"),
|
|
449
|
-
)
|
|
450
|
-
|
|
451
|
-
test
|
|
452
|
-
.expect(result)
|
|
453
|
-
.toEqual(["foo", "bar", "baz"])
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
test.it("should encode back to string", async () => {
|
|
457
|
-
const schema = Commander.repeatable(Schema.String)
|
|
458
|
-
|
|
459
|
-
const result = await Effect.runPromise(
|
|
460
|
-
Schema.encode(schema)(["foo", "bar", "baz"]),
|
|
461
|
-
)
|
|
462
|
-
|
|
463
|
-
test
|
|
464
|
-
.expect(result)
|
|
465
|
-
.toBe("foo,bar,baz")
|
|
466
|
-
})
|
|
467
|
-
})
|
|
468
|
-
|
|
469
|
-
test.describe("integration", () => {
|
|
470
|
-
test.it("should work with builder pattern", async () => {
|
|
471
|
-
const cmd = Commander
|
|
472
|
-
.make({
|
|
473
|
-
name: "converter",
|
|
474
|
-
description: "Convert files",
|
|
475
|
-
version: "2.1.0",
|
|
476
|
-
})
|
|
477
|
-
.option(
|
|
478
|
-
Commander
|
|
479
|
-
.option("--input", "-i")
|
|
480
|
-
.description("Input file")
|
|
481
|
-
.schema(Schema.String),
|
|
482
|
-
)
|
|
483
|
-
.option(
|
|
484
|
-
Commander
|
|
485
|
-
.option("--output", "-o")
|
|
486
|
-
.description("Output file")
|
|
487
|
-
.default("output.txt")
|
|
488
|
-
.schema(Schema.String),
|
|
489
|
-
)
|
|
490
|
-
.option(
|
|
491
|
-
Commander
|
|
492
|
-
.option("--format", "-f")
|
|
493
|
-
.default("json")
|
|
494
|
-
.schema(
|
|
495
|
-
Schema.compose(
|
|
496
|
-
Schema.String,
|
|
497
|
-
Schema.Literal("json", "xml", "yaml"),
|
|
498
|
-
),
|
|
499
|
-
),
|
|
500
|
-
)
|
|
501
|
-
.optionHelp()
|
|
502
|
-
|
|
503
|
-
const result = await Effect.runPromise(
|
|
504
|
-
Commander.parse(cmd, [
|
|
505
|
-
"--input",
|
|
506
|
-
"input.txt",
|
|
507
|
-
"-f",
|
|
508
|
-
"yaml",
|
|
509
|
-
]),
|
|
510
|
-
)
|
|
511
|
-
|
|
512
|
-
test
|
|
513
|
-
.expect(result.input)
|
|
514
|
-
.toBe("input.txt")
|
|
515
|
-
test
|
|
516
|
-
.expect(result.output)
|
|
517
|
-
.toBe("output.txt")
|
|
518
|
-
test
|
|
519
|
-
.expect(result.format)
|
|
520
|
-
.toBe("yaml")
|
|
521
|
-
test
|
|
522
|
-
.expect(result.help)
|
|
523
|
-
.toBe(false)
|
|
524
|
-
})
|
|
525
|
-
|
|
526
|
-
test.it("should handle kebab-case option names", async () => {
|
|
527
|
-
const cmd = Commander
|
|
528
|
-
.make({ name: "app" })
|
|
529
|
-
.option(
|
|
530
|
-
Commander
|
|
531
|
-
.option("--dry-run")
|
|
532
|
-
.default(false)
|
|
533
|
-
.schema(Schema.BooleanFromString),
|
|
534
|
-
)
|
|
535
|
-
.option(
|
|
536
|
-
Commander
|
|
537
|
-
.option("--cache-dir")
|
|
538
|
-
.schema(Schema.String),
|
|
539
|
-
)
|
|
540
|
-
|
|
541
|
-
const result = await Effect.runPromise(
|
|
542
|
-
Commander.parse(cmd, ["--dry-run", "true", "--cache-dir", "/tmp/cache"]),
|
|
543
|
-
)
|
|
544
|
-
|
|
545
|
-
test
|
|
546
|
-
.expect(result.dryRun)
|
|
547
|
-
.toBe(true)
|
|
548
|
-
test
|
|
549
|
-
.expect(result.cacheDir)
|
|
550
|
-
.toBe("/tmp/cache")
|
|
551
|
-
})
|
|
552
|
-
})
|
|
553
|
-
|
|
554
|
-
test.describe(`${Commander.parse.name} - comprehensive`, () => {
|
|
555
|
-
test.it("should parse with explicit args", async () => {
|
|
556
|
-
const cmd = Commander
|
|
557
|
-
.make({ name: "app" })
|
|
558
|
-
.option(
|
|
559
|
-
Commander
|
|
560
|
-
.option("--port", "-p")
|
|
561
|
-
.schema(Commander.NumberFromString),
|
|
562
|
-
)
|
|
563
|
-
|
|
564
|
-
const result = await Effect.runPromise(
|
|
565
|
-
Commander.parse(cmd, ["--port", "3000"]),
|
|
566
|
-
)
|
|
567
|
-
|
|
568
|
-
test
|
|
569
|
-
.expect(result.port)
|
|
570
|
-
.toBe(3000)
|
|
571
|
-
})
|
|
572
|
-
|
|
573
|
-
test.it("should parse short options", async () => {
|
|
574
|
-
const cmd = Commander
|
|
575
|
-
.make({ name: "app" })
|
|
576
|
-
.option(
|
|
577
|
-
Commander
|
|
578
|
-
.option("--port", "-p")
|
|
579
|
-
.schema(Commander.NumberFromString),
|
|
580
|
-
)
|
|
581
|
-
|
|
582
|
-
const result = await Effect.runPromise(
|
|
583
|
-
Commander.parse(cmd, ["-p", "8080"]),
|
|
584
|
-
)
|
|
585
|
-
|
|
586
|
-
test
|
|
587
|
-
.expect(result.port)
|
|
588
|
-
.toBe(8080)
|
|
589
|
-
})
|
|
590
|
-
|
|
591
|
-
test.it("should parse multiple options", async () => {
|
|
592
|
-
const cmd = Commander
|
|
593
|
-
.make({ name: "app" })
|
|
594
|
-
.option(
|
|
595
|
-
Commander
|
|
596
|
-
.option("--host", "-h")
|
|
597
|
-
.schema(Schema.String),
|
|
598
|
-
)
|
|
599
|
-
.option(
|
|
600
|
-
Commander
|
|
601
|
-
.option("--port", "-p")
|
|
602
|
-
.schema(Commander.NumberFromString),
|
|
603
|
-
)
|
|
604
|
-
|
|
605
|
-
const result = await Effect.runPromise(
|
|
606
|
-
Commander.parse(cmd, ["--host", "localhost", "--port", "3000"]),
|
|
607
|
-
)
|
|
608
|
-
|
|
609
|
-
test
|
|
610
|
-
.expect(result.host)
|
|
611
|
-
.toBe("localhost")
|
|
612
|
-
test
|
|
613
|
-
.expect(result.port)
|
|
614
|
-
.toBe(3000)
|
|
615
|
-
})
|
|
616
|
-
|
|
617
|
-
test.it("should handle options with equals syntax", async () => {
|
|
618
|
-
const cmd = Commander
|
|
619
|
-
.make({ name: "app" })
|
|
620
|
-
.option(
|
|
621
|
-
Commander
|
|
622
|
-
.option("--port")
|
|
623
|
-
.schema(Commander.NumberFromString),
|
|
624
|
-
)
|
|
625
|
-
|
|
626
|
-
const result = await Effect.runPromise(
|
|
627
|
-
Commander.parse(cmd, ["--port=3000"]),
|
|
628
|
-
)
|
|
629
|
-
|
|
630
|
-
test
|
|
631
|
-
.expect(result.port)
|
|
632
|
-
.toBe(3000)
|
|
633
|
-
})
|
|
634
|
-
|
|
635
|
-
test.it("should parse combined short flags", async () => {
|
|
636
|
-
const cmd = Commander
|
|
637
|
-
.make({ name: "app" })
|
|
638
|
-
.option(
|
|
639
|
-
Commander
|
|
640
|
-
.option("--verbose", "-v")
|
|
641
|
-
.default(false)
|
|
642
|
-
.schema(Schema.BooleanFromString),
|
|
643
|
-
)
|
|
644
|
-
.option(
|
|
645
|
-
Commander
|
|
646
|
-
.option("--debug", "-d")
|
|
647
|
-
.default(false)
|
|
648
|
-
.schema(Schema.BooleanFromString),
|
|
649
|
-
)
|
|
650
|
-
|
|
651
|
-
const result = await Effect.runPromise(
|
|
652
|
-
Commander.parse(cmd, []),
|
|
653
|
-
)
|
|
654
|
-
|
|
655
|
-
test
|
|
656
|
-
.expect(result.verbose)
|
|
657
|
-
.toBe(false)
|
|
658
|
-
test
|
|
659
|
-
.expect(result.debug)
|
|
660
|
-
.toBe(false)
|
|
661
|
-
})
|
|
662
|
-
})
|
|
663
|
-
|
|
664
|
-
test.describe("boolean options", () => {
|
|
665
|
-
test.it("should return false for boolean flag when not specified", async () => {
|
|
666
|
-
const cmd = Commander
|
|
667
|
-
.make({ name: "app" })
|
|
668
|
-
.option(
|
|
669
|
-
Commander
|
|
670
|
-
.option("--verbose", "-v")
|
|
671
|
-
.default(false)
|
|
672
|
-
.schema(Schema.BooleanFromString),
|
|
673
|
-
)
|
|
674
|
-
|
|
675
|
-
const result = await Effect.runPromise(
|
|
676
|
-
Commander.parse(cmd, []),
|
|
677
|
-
)
|
|
678
|
-
|
|
679
|
-
test
|
|
680
|
-
.expect(result.verbose)
|
|
681
|
-
.toBe(false)
|
|
682
|
-
})
|
|
683
|
-
|
|
684
|
-
test.it("should return true for boolean flag when specified", async () => {
|
|
685
|
-
const cmd = Commander
|
|
686
|
-
.make({ name: "app" })
|
|
687
|
-
.option(
|
|
688
|
-
Commander
|
|
689
|
-
.option("--verbose", "-v")
|
|
690
|
-
.default(false)
|
|
691
|
-
.schema(Schema.BooleanFromString),
|
|
692
|
-
)
|
|
693
|
-
|
|
694
|
-
const result = await Effect.runPromise(
|
|
695
|
-
Commander.parse(cmd, ["--verbose", "true"]),
|
|
696
|
-
)
|
|
697
|
-
|
|
698
|
-
test
|
|
699
|
-
.expect(result.verbose)
|
|
700
|
-
.toBe(true)
|
|
701
|
-
})
|
|
702
|
-
|
|
703
|
-
test.it("should handle boolean with custom default", async () => {
|
|
704
|
-
const cmd = Commander
|
|
705
|
-
.make({ name: "app" })
|
|
706
|
-
.option(
|
|
707
|
-
Commander
|
|
708
|
-
.option("--color")
|
|
709
|
-
.default("auto")
|
|
710
|
-
.schema(Schema.String),
|
|
711
|
-
)
|
|
712
|
-
|
|
713
|
-
const result = await Effect.runPromise(
|
|
714
|
-
Commander.parse(cmd, []),
|
|
715
|
-
)
|
|
716
|
-
|
|
717
|
-
test
|
|
718
|
-
.expect(result.color)
|
|
719
|
-
.toBe("auto")
|
|
720
|
-
})
|
|
721
|
-
})
|
|
722
|
-
|
|
723
|
-
test.describe("options with choices", () => {
|
|
724
|
-
test.it("should accept valid choice", async () => {
|
|
725
|
-
const cmd = Commander
|
|
726
|
-
.make({ name: "app" })
|
|
727
|
-
.option(
|
|
728
|
-
Commander
|
|
729
|
-
.option("--color", "-c")
|
|
730
|
-
.schema(
|
|
731
|
-
Schema.compose(
|
|
732
|
-
Schema.String,
|
|
733
|
-
Schema.Literal("red", "green", "blue"),
|
|
734
|
-
),
|
|
735
|
-
),
|
|
736
|
-
)
|
|
737
|
-
|
|
738
|
-
const result = await Effect.runPromise(
|
|
739
|
-
Commander.parse(cmd, ["--color", "red"]),
|
|
740
|
-
)
|
|
741
|
-
|
|
742
|
-
test
|
|
743
|
-
.expect(result.color)
|
|
744
|
-
.toBe("red")
|
|
745
|
-
})
|
|
746
|
-
|
|
747
|
-
test.it("should reject invalid choice", async () => {
|
|
748
|
-
const cmd = Commander
|
|
749
|
-
.make({ name: "app" })
|
|
750
|
-
.option(
|
|
751
|
-
Commander
|
|
752
|
-
.option("--color", "-c")
|
|
753
|
-
.schema(
|
|
754
|
-
Schema.compose(
|
|
755
|
-
Schema.String,
|
|
756
|
-
Schema.Literal("red", "green", "blue"),
|
|
757
|
-
),
|
|
758
|
-
),
|
|
759
|
-
)
|
|
760
|
-
|
|
761
|
-
const result = await Effect.runPromise(
|
|
762
|
-
Effect.either(Commander.parse(cmd, ["--color", "yellow"])),
|
|
763
|
-
)
|
|
764
|
-
|
|
765
|
-
test
|
|
766
|
-
.expect(result._tag)
|
|
767
|
-
.toBe("Left")
|
|
768
|
-
})
|
|
769
|
-
|
|
770
|
-
test.it("should handle multiple choice options", async () => {
|
|
771
|
-
const cmd = Commander
|
|
772
|
-
.make({ name: "app" })
|
|
773
|
-
.option(
|
|
774
|
-
Commander
|
|
775
|
-
.option("--format", "-f")
|
|
776
|
-
.default("json")
|
|
777
|
-
.schema(
|
|
778
|
-
Schema.compose(
|
|
779
|
-
Schema.String,
|
|
780
|
-
Schema.Literal("json", "xml", "yaml"),
|
|
781
|
-
),
|
|
782
|
-
),
|
|
783
|
-
)
|
|
784
|
-
.option(
|
|
785
|
-
Commander
|
|
786
|
-
.option("--level", "-l")
|
|
787
|
-
.default("info")
|
|
788
|
-
.schema(
|
|
789
|
-
Schema.compose(
|
|
790
|
-
Schema.String,
|
|
791
|
-
Schema.Literal("debug", "info", "warn", "error"),
|
|
792
|
-
),
|
|
793
|
-
),
|
|
794
|
-
)
|
|
795
|
-
|
|
796
|
-
const result = await Effect.runPromise(
|
|
797
|
-
Commander.parse(cmd, ["--format", "xml", "--level", "debug"]),
|
|
798
|
-
)
|
|
799
|
-
|
|
800
|
-
test
|
|
801
|
-
.expect(result.format)
|
|
802
|
-
.toBe("xml")
|
|
803
|
-
test
|
|
804
|
-
.expect(result.level)
|
|
805
|
-
.toBe("debug")
|
|
806
|
-
})
|
|
807
|
-
})
|
|
808
|
-
|
|
809
|
-
test.describe("options with defaults", () => {
|
|
810
|
-
test.it("should use default when option not specified", async () => {
|
|
811
|
-
const cmd = Commander
|
|
812
|
-
.make({ name: "app" })
|
|
813
|
-
.option(
|
|
814
|
-
Commander
|
|
815
|
-
.option("--port", "-p")
|
|
816
|
-
.default(3000)
|
|
817
|
-
.schema(Commander.NumberFromString),
|
|
818
|
-
)
|
|
819
|
-
|
|
820
|
-
const result = await Effect.runPromise(
|
|
821
|
-
Commander.parse(cmd, []),
|
|
822
|
-
)
|
|
823
|
-
|
|
824
|
-
test
|
|
825
|
-
.expect(result.port)
|
|
826
|
-
.toBe(3000)
|
|
827
|
-
})
|
|
828
|
-
|
|
829
|
-
test.it("should override default when option specified", async () => {
|
|
830
|
-
const cmd = Commander
|
|
831
|
-
.make({ name: "app" })
|
|
832
|
-
.option(
|
|
833
|
-
Commander
|
|
834
|
-
.option("--port", "-p")
|
|
835
|
-
.default(3000)
|
|
836
|
-
.schema(Commander.NumberFromString),
|
|
837
|
-
)
|
|
838
|
-
|
|
839
|
-
const result = await Effect.runPromise(
|
|
840
|
-
Commander.parse(cmd, ["--port", "8080"]),
|
|
841
|
-
)
|
|
842
|
-
|
|
843
|
-
test
|
|
844
|
-
.expect(result.port)
|
|
845
|
-
.toBe(8080)
|
|
846
|
-
})
|
|
847
|
-
|
|
848
|
-
test.it("should handle multiple defaults", async () => {
|
|
849
|
-
const cmd = Commander
|
|
850
|
-
.make({ name: "app" })
|
|
851
|
-
.option(
|
|
852
|
-
Commander
|
|
853
|
-
.option("--host")
|
|
854
|
-
.default("localhost")
|
|
855
|
-
.schema(Schema.String),
|
|
856
|
-
)
|
|
857
|
-
.option(
|
|
858
|
-
Commander
|
|
859
|
-
.option("--port")
|
|
860
|
-
.default(3000)
|
|
861
|
-
.schema(Commander.NumberFromString),
|
|
862
|
-
)
|
|
863
|
-
.option(
|
|
864
|
-
Commander
|
|
865
|
-
.option("--debug")
|
|
866
|
-
.default(false)
|
|
867
|
-
.schema(Schema.BooleanFromString),
|
|
868
|
-
)
|
|
869
|
-
|
|
870
|
-
const result = await Effect.runPromise(
|
|
871
|
-
Commander.parse(cmd, []),
|
|
872
|
-
)
|
|
873
|
-
|
|
874
|
-
test
|
|
875
|
-
.expect(result.host)
|
|
876
|
-
.toBe("localhost")
|
|
877
|
-
test
|
|
878
|
-
.expect(result.port)
|
|
879
|
-
.toBe(3000)
|
|
880
|
-
test
|
|
881
|
-
.expect(result.debug)
|
|
882
|
-
.toBe(false)
|
|
883
|
-
})
|
|
884
|
-
|
|
885
|
-
test.it("should use default for string option", async () => {
|
|
886
|
-
const cmd = Commander
|
|
887
|
-
.make({ name: "app" })
|
|
888
|
-
.option(
|
|
889
|
-
Commander
|
|
890
|
-
.option("--output", "-o")
|
|
891
|
-
.default("output.txt")
|
|
892
|
-
.schema(Schema.String),
|
|
893
|
-
)
|
|
894
|
-
|
|
895
|
-
const result = await Effect.runPromise(
|
|
896
|
-
Commander.parse(cmd, []),
|
|
897
|
-
)
|
|
898
|
-
|
|
899
|
-
test
|
|
900
|
-
.expect(result.output)
|
|
901
|
-
.toBe("output.txt")
|
|
902
|
-
})
|
|
903
|
-
})
|
|
904
|
-
|
|
905
|
-
test.describe("action/handler", () => {
|
|
906
|
-
test.it("should invoke handler with parsed options", async () => {
|
|
907
|
-
let capturedOptions: any = null
|
|
908
|
-
|
|
909
|
-
const cmd = Commander
|
|
910
|
-
.make({ name: "app" })
|
|
911
|
-
.option(
|
|
912
|
-
Commander
|
|
913
|
-
.option("--name", "-n")
|
|
914
|
-
.schema(Schema.String),
|
|
915
|
-
)
|
|
916
|
-
.handle((opts) =>
|
|
917
|
-
Effect.sync(() => {
|
|
918
|
-
capturedOptions = opts
|
|
919
|
-
})
|
|
920
|
-
)
|
|
921
|
-
|
|
922
|
-
const parsed = await Effect.runPromise(
|
|
923
|
-
Commander.parse(cmd, ["--name", "test"]),
|
|
924
|
-
)
|
|
925
|
-
|
|
926
|
-
test
|
|
927
|
-
.expect(parsed.name)
|
|
928
|
-
.toBe("test")
|
|
929
|
-
})
|
|
930
|
-
|
|
931
|
-
test.it("should support async handlers", async () => {
|
|
932
|
-
let executed = false
|
|
933
|
-
|
|
934
|
-
const cmd = Commander
|
|
935
|
-
.make({ name: "app" })
|
|
936
|
-
.option(
|
|
937
|
-
Commander
|
|
938
|
-
.option("--delay")
|
|
939
|
-
.default(0)
|
|
940
|
-
.schema(Commander.NumberFromString),
|
|
941
|
-
)
|
|
942
|
-
.handle((opts) =>
|
|
943
|
-
Effect.gen(function*() {
|
|
944
|
-
yield* Effect.sleep(opts.delay)
|
|
945
|
-
executed = true
|
|
946
|
-
})
|
|
947
|
-
)
|
|
948
|
-
|
|
949
|
-
await Effect.runPromise(
|
|
950
|
-
Commander.parse(cmd, ["--delay", "10"]),
|
|
951
|
-
)
|
|
952
|
-
|
|
953
|
-
test
|
|
954
|
-
.expect(executed)
|
|
955
|
-
.toBe(false)
|
|
956
|
-
})
|
|
957
|
-
|
|
958
|
-
test.it("should pass all options to handler", async () => {
|
|
959
|
-
let capturedOpts: any = null
|
|
960
|
-
|
|
961
|
-
const cmd = Commander
|
|
962
|
-
.make({ name: "app" })
|
|
963
|
-
.option(
|
|
964
|
-
Commander
|
|
965
|
-
.option("--input", "-i")
|
|
966
|
-
.schema(Schema.String),
|
|
967
|
-
)
|
|
968
|
-
.option(
|
|
969
|
-
Commander
|
|
970
|
-
.option("--output", "-o")
|
|
971
|
-
.schema(Schema.String),
|
|
972
|
-
)
|
|
973
|
-
.option(
|
|
974
|
-
Commander
|
|
975
|
-
.option("--verbose", "-v")
|
|
976
|
-
.default(false)
|
|
977
|
-
.schema(Schema.BooleanFromString),
|
|
978
|
-
)
|
|
979
|
-
.handle((opts) =>
|
|
980
|
-
Effect.sync(() => {
|
|
981
|
-
capturedOpts = opts
|
|
982
|
-
})
|
|
983
|
-
)
|
|
984
|
-
|
|
985
|
-
await Effect.runPromise(
|
|
986
|
-
Commander.parse(cmd, ["-i", "in.txt", "-o", "out.txt", "-v", "true"]),
|
|
987
|
-
)
|
|
988
|
-
})
|
|
989
|
-
})
|
|
990
|
-
|
|
991
|
-
test.describe(`${Commander.optionVersion.name} - version behavior`, () => {
|
|
992
|
-
test.it("should include version in command definition", () => {
|
|
993
|
-
const cmd = Commander
|
|
994
|
-
.make({ name: "app", version: "1.0.0" })
|
|
995
|
-
.optionVersion()
|
|
996
|
-
|
|
997
|
-
test
|
|
998
|
-
.expect(cmd.version)
|
|
999
|
-
.toBe("1.0.0")
|
|
1000
|
-
test
|
|
1001
|
-
.expect(cmd.options.version)
|
|
1002
|
-
.toBeDefined()
|
|
1003
|
-
})
|
|
1004
|
-
|
|
1005
|
-
test.it("should handle version without version option", () => {
|
|
1006
|
-
const cmd = Commander
|
|
1007
|
-
.make({ name: "app", version: "2.0.0" })
|
|
1008
|
-
|
|
1009
|
-
test
|
|
1010
|
-
.expect(cmd.version)
|
|
1011
|
-
.toBe("2.0.0")
|
|
1012
|
-
test
|
|
1013
|
-
.expect(cmd.options["version"])
|
|
1014
|
-
.toBeUndefined()
|
|
1015
|
-
})
|
|
1016
|
-
|
|
1017
|
-
test.it("should include version option in help", () => {
|
|
1018
|
-
const cmd = Commander
|
|
1019
|
-
.make({ name: "app", version: "1.0.0" })
|
|
1020
|
-
.optionVersion()
|
|
1021
|
-
|
|
1022
|
-
const help = Commander.help(cmd)
|
|
1023
|
-
|
|
1024
|
-
test
|
|
1025
|
-
.expect(help)
|
|
1026
|
-
.toContain("--version")
|
|
1027
|
-
test
|
|
1028
|
-
.expect(help)
|
|
1029
|
-
.toContain("-V")
|
|
1030
|
-
})
|
|
1031
|
-
})
|
|
1032
|
-
|
|
1033
|
-
test.describe(`${Commander.help.name} - comprehensive`, () => {
|
|
1034
|
-
test.it("should generate help with description", () => {
|
|
1035
|
-
const cmd = Commander
|
|
1036
|
-
.make({
|
|
1037
|
-
name: "myapp",
|
|
1038
|
-
description: "A test application",
|
|
1039
|
-
})
|
|
1040
|
-
.optionHelp()
|
|
1041
|
-
|
|
1042
|
-
const help = Commander.help(cmd)
|
|
1043
|
-
|
|
1044
|
-
test
|
|
1045
|
-
.expect(help)
|
|
1046
|
-
.toContain("A test application")
|
|
1047
|
-
test
|
|
1048
|
-
.expect(help)
|
|
1049
|
-
.toContain("Usage: myapp [options]")
|
|
1050
|
-
})
|
|
1051
|
-
|
|
1052
|
-
test.it("should include all options in help", () => {
|
|
1053
|
-
const cmd = Commander
|
|
1054
|
-
.make({ name: "app" })
|
|
1055
|
-
.option(
|
|
1056
|
-
Commander
|
|
1057
|
-
.option("--input", "-i")
|
|
1058
|
-
.description("Input file")
|
|
1059
|
-
.schema(Schema.String),
|
|
1060
|
-
)
|
|
1061
|
-
.option(
|
|
1062
|
-
Commander
|
|
1063
|
-
.option("--output", "-o")
|
|
1064
|
-
.description("Output file")
|
|
1065
|
-
.schema(Schema.String),
|
|
1066
|
-
)
|
|
1067
|
-
.optionHelp()
|
|
1068
|
-
|
|
1069
|
-
const help = Commander.help(cmd)
|
|
1070
|
-
|
|
1071
|
-
test
|
|
1072
|
-
.expect(help)
|
|
1073
|
-
.toContain("--input")
|
|
1074
|
-
test
|
|
1075
|
-
.expect(help)
|
|
1076
|
-
.toContain("-i,")
|
|
1077
|
-
test
|
|
1078
|
-
.expect(help)
|
|
1079
|
-
.toContain("Input file")
|
|
1080
|
-
test
|
|
1081
|
-
.expect(help)
|
|
1082
|
-
.toContain("--output")
|
|
1083
|
-
test
|
|
1084
|
-
.expect(help)
|
|
1085
|
-
.toContain("-o,")
|
|
1086
|
-
test
|
|
1087
|
-
.expect(help)
|
|
1088
|
-
.toContain("Output file")
|
|
1089
|
-
})
|
|
1090
|
-
|
|
1091
|
-
test.it("should show subcommands in help", () => {
|
|
1092
|
-
const subCmd = Commander
|
|
1093
|
-
.make({ name: "init", description: "Initialize project" })
|
|
1094
|
-
.handle(() => Effect.void)
|
|
1095
|
-
|
|
1096
|
-
const cmd = Commander
|
|
1097
|
-
.make({ name: "app" })
|
|
1098
|
-
.subcommand(subCmd)
|
|
1099
|
-
.optionHelp()
|
|
1100
|
-
|
|
1101
|
-
const help = Commander.help(cmd)
|
|
1102
|
-
|
|
1103
|
-
test
|
|
1104
|
-
.expect(help)
|
|
1105
|
-
.toContain("Commands:")
|
|
1106
|
-
test
|
|
1107
|
-
.expect(help)
|
|
1108
|
-
.toContain("init")
|
|
1109
|
-
test
|
|
1110
|
-
.expect(help)
|
|
1111
|
-
.toContain("Initialize project")
|
|
1112
|
-
})
|
|
1113
|
-
|
|
1114
|
-
test.it("should format option descriptions properly", () => {
|
|
1115
|
-
const cmd = Commander
|
|
1116
|
-
.make({ name: "app" })
|
|
1117
|
-
.option(
|
|
1118
|
-
Commander
|
|
1119
|
-
.option("--config", "-c")
|
|
1120
|
-
.description("Config file path")
|
|
1121
|
-
.schema(Schema.String),
|
|
1122
|
-
)
|
|
1123
|
-
|
|
1124
|
-
const help = Commander.help(cmd)
|
|
1125
|
-
|
|
1126
|
-
test
|
|
1127
|
-
.expect(help)
|
|
1128
|
-
.toContain("-c, --config")
|
|
1129
|
-
test
|
|
1130
|
-
.expect(help)
|
|
1131
|
-
.toContain("Config file path")
|
|
1132
|
-
})
|
|
1133
|
-
})
|
|
1134
|
-
|
|
1135
|
-
test.describe(`${Commander.subcommand.name} - comprehensive`, () => {
|
|
1136
|
-
test.it("should add subcommand", () => {
|
|
1137
|
-
const subCmd = Commander
|
|
1138
|
-
.make({ name: "build" })
|
|
1139
|
-
.option(
|
|
1140
|
-
Commander
|
|
1141
|
-
.option("--watch", "-w")
|
|
1142
|
-
.default(false)
|
|
1143
|
-
.schema(Schema.BooleanFromString),
|
|
1144
|
-
)
|
|
1145
|
-
.handle(() => Effect.void)
|
|
1146
|
-
|
|
1147
|
-
const cmd = Commander
|
|
1148
|
-
.make({ name: "app" })
|
|
1149
|
-
.subcommand(subCmd)
|
|
1150
|
-
|
|
1151
|
-
test
|
|
1152
|
-
.expect(cmd.subcommands.length)
|
|
1153
|
-
.toBe(1)
|
|
1154
|
-
test
|
|
1155
|
-
.expect(cmd.subcommands[0]!.command.name)
|
|
1156
|
-
.toBe("build")
|
|
1157
|
-
})
|
|
1158
|
-
|
|
1159
|
-
test.it("should add multiple subcommands", () => {
|
|
1160
|
-
const build = Commander
|
|
1161
|
-
.make({ name: "build" })
|
|
1162
|
-
.handle(() => Effect.void)
|
|
1163
|
-
|
|
1164
|
-
const testCmd = Commander
|
|
1165
|
-
.make({ name: "test" })
|
|
1166
|
-
.handle(() => Effect.void)
|
|
1167
|
-
|
|
1168
|
-
const cmd = Commander
|
|
1169
|
-
.make({ name: "app" })
|
|
1170
|
-
.subcommand(build)
|
|
1171
|
-
.subcommand(testCmd)
|
|
1172
|
-
|
|
1173
|
-
test
|
|
1174
|
-
.expect(cmd.subcommands.length)
|
|
1175
|
-
.toBe(2)
|
|
1176
|
-
test
|
|
1177
|
-
.expect(cmd.subcommands[0]!.command.name)
|
|
1178
|
-
.toBe("build")
|
|
1179
|
-
test
|
|
1180
|
-
.expect(cmd.subcommands[1]!.command.name)
|
|
1181
|
-
.toBe("test")
|
|
1182
|
-
})
|
|
1183
|
-
|
|
1184
|
-
test.it("should nest subcommands", () => {
|
|
1185
|
-
const deploy = Commander
|
|
1186
|
-
.make({ name: "deploy" })
|
|
1187
|
-
.handle(() => Effect.void)
|
|
1188
|
-
|
|
1189
|
-
const build = Commander
|
|
1190
|
-
.make({ name: "build" })
|
|
1191
|
-
.subcommand(deploy)
|
|
1192
|
-
.handle(() => Effect.void)
|
|
1193
|
-
|
|
1194
|
-
const cmd = Commander
|
|
1195
|
-
.make({ name: "app" })
|
|
1196
|
-
.subcommand(build)
|
|
1197
|
-
|
|
1198
|
-
test
|
|
1199
|
-
.expect(cmd.subcommands[0]!.command.subcommands.length)
|
|
1200
|
-
.toBe(1)
|
|
1201
|
-
test
|
|
1202
|
-
.expect(cmd.subcommands[0]!.command.subcommands[0]!.command.name)
|
|
1203
|
-
.toBe("deploy")
|
|
1204
|
-
})
|
|
1205
|
-
})
|
|
1206
|
-
|
|
1207
|
-
test.describe("option types", () => {
|
|
1208
|
-
test.it("should parse string option", async () => {
|
|
1209
|
-
const cmd = Commander
|
|
1210
|
-
.make({ name: "app" })
|
|
1211
|
-
.option(
|
|
1212
|
-
Commander
|
|
1213
|
-
.option("--name")
|
|
1214
|
-
.schema(Schema.String),
|
|
1215
|
-
)
|
|
1216
|
-
|
|
1217
|
-
const result = await Effect.runPromise(
|
|
1218
|
-
Commander.parse(cmd, ["--name", "test"]),
|
|
1219
|
-
)
|
|
1220
|
-
|
|
1221
|
-
test
|
|
1222
|
-
.expect(result.name)
|
|
1223
|
-
.toBe("test")
|
|
1224
|
-
test
|
|
1225
|
-
.expect(typeof result.name)
|
|
1226
|
-
.toBe("string")
|
|
1227
|
-
})
|
|
1228
|
-
|
|
1229
|
-
test.it("should parse number option", async () => {
|
|
1230
|
-
const cmd = Commander
|
|
1231
|
-
.make({ name: "app" })
|
|
1232
|
-
.option(
|
|
1233
|
-
Commander
|
|
1234
|
-
.option("--count")
|
|
1235
|
-
.schema(Commander.NumberFromString),
|
|
1236
|
-
)
|
|
1237
|
-
|
|
1238
|
-
const result = await Effect.runPromise(
|
|
1239
|
-
Commander.parse(cmd, ["--count", "42"]),
|
|
1240
|
-
)
|
|
1241
|
-
|
|
1242
|
-
test
|
|
1243
|
-
.expect(result.count)
|
|
1244
|
-
.toBe(42)
|
|
1245
|
-
test
|
|
1246
|
-
.expect(typeof result.count)
|
|
1247
|
-
.toBe("number")
|
|
1248
|
-
})
|
|
1249
|
-
|
|
1250
|
-
test.it("should parse boolean option", async () => {
|
|
1251
|
-
const cmd = Commander
|
|
1252
|
-
.make({ name: "app" })
|
|
1253
|
-
.option(
|
|
1254
|
-
Commander
|
|
1255
|
-
.option("--enabled")
|
|
1256
|
-
.schema(Schema.BooleanFromString),
|
|
1257
|
-
)
|
|
1258
|
-
|
|
1259
|
-
const result = await Effect.runPromise(
|
|
1260
|
-
Commander.parse(cmd, ["--enabled", "true"]),
|
|
1261
|
-
)
|
|
1262
|
-
|
|
1263
|
-
test
|
|
1264
|
-
.expect(result.enabled)
|
|
1265
|
-
.toBe(true)
|
|
1266
|
-
test
|
|
1267
|
-
.expect(typeof result.enabled)
|
|
1268
|
-
.toBe("boolean")
|
|
1269
|
-
})
|
|
1270
|
-
|
|
1271
|
-
test.it("should fail on invalid number", async () => {
|
|
1272
|
-
const cmd = Commander
|
|
1273
|
-
.make({ name: "app" })
|
|
1274
|
-
.option(
|
|
1275
|
-
Commander
|
|
1276
|
-
.option("--count")
|
|
1277
|
-
.schema(Commander.NumberFromString),
|
|
1278
|
-
)
|
|
1279
|
-
|
|
1280
|
-
const result = await Effect.runPromise(
|
|
1281
|
-
Effect.either(Commander.parse(cmd, ["--count", "not-a-number"])),
|
|
1282
|
-
)
|
|
1283
|
-
|
|
1284
|
-
test
|
|
1285
|
-
.expect(result._tag)
|
|
1286
|
-
.toBe("Left")
|
|
1287
|
-
})
|
|
1288
|
-
})
|
|
1289
|
-
|
|
1290
|
-
test.describe("complex scenarios", () => {
|
|
1291
|
-
test.it("should handle mixed option types", async () => {
|
|
1292
|
-
const cmd = Commander
|
|
1293
|
-
.make({ name: "server" })
|
|
1294
|
-
.option(
|
|
1295
|
-
Commander
|
|
1296
|
-
.option("--host", "-h")
|
|
1297
|
-
.default("localhost")
|
|
1298
|
-
.schema(Schema.String),
|
|
1299
|
-
)
|
|
1300
|
-
.option(
|
|
1301
|
-
Commander
|
|
1302
|
-
.option("--port", "-p")
|
|
1303
|
-
.default(3000)
|
|
1304
|
-
.schema(Commander.NumberFromString),
|
|
1305
|
-
)
|
|
1306
|
-
.option(
|
|
1307
|
-
Commander
|
|
1308
|
-
.option("--ssl")
|
|
1309
|
-
.default(false)
|
|
1310
|
-
.schema(Schema.BooleanFromString),
|
|
1311
|
-
)
|
|
1312
|
-
.option(
|
|
1313
|
-
Commander
|
|
1314
|
-
.option("--env", "-e")
|
|
1315
|
-
.default("development")
|
|
1316
|
-
.schema(
|
|
1317
|
-
Schema.compose(
|
|
1318
|
-
Schema.String,
|
|
1319
|
-
Schema.Literal("development", "production", "test"),
|
|
1320
|
-
),
|
|
1321
|
-
),
|
|
1322
|
-
)
|
|
1323
|
-
|
|
1324
|
-
const result = await Effect.runPromise(
|
|
1325
|
-
Commander.parse(cmd, [
|
|
1326
|
-
"--host",
|
|
1327
|
-
"0.0.0.0",
|
|
1328
|
-
"-p",
|
|
1329
|
-
"8080",
|
|
1330
|
-
"--ssl",
|
|
1331
|
-
"true",
|
|
1332
|
-
"-e",
|
|
1333
|
-
"production",
|
|
1334
|
-
]),
|
|
1335
|
-
)
|
|
1336
|
-
|
|
1337
|
-
test
|
|
1338
|
-
.expect(result.host)
|
|
1339
|
-
.toBe("0.0.0.0")
|
|
1340
|
-
test
|
|
1341
|
-
.expect(result.port)
|
|
1342
|
-
.toBe(8080)
|
|
1343
|
-
test
|
|
1344
|
-
.expect(result.ssl)
|
|
1345
|
-
.toBe(true)
|
|
1346
|
-
test
|
|
1347
|
-
.expect(result.env)
|
|
1348
|
-
.toBe("production")
|
|
1349
|
-
})
|
|
1350
|
-
|
|
1351
|
-
test.it("should handle repeatable options", async () => {
|
|
1352
|
-
const cmd = Commander
|
|
1353
|
-
.make({ name: "app" })
|
|
1354
|
-
.option(
|
|
1355
|
-
Commander
|
|
1356
|
-
.option("--tags", "-t")
|
|
1357
|
-
.schema(Commander.repeatable(Schema.String)),
|
|
1358
|
-
)
|
|
1359
|
-
|
|
1360
|
-
const result = await Effect.runPromise(
|
|
1361
|
-
Commander.parse(cmd, ["--tags", "foo,bar,baz"]),
|
|
1362
|
-
)
|
|
1363
|
-
|
|
1364
|
-
test
|
|
1365
|
-
.expect(result.tags)
|
|
1366
|
-
.toEqual(["foo", "bar", "baz"])
|
|
1367
|
-
})
|
|
1368
|
-
|
|
1369
|
-
test.it("should preserve option order independence", async () => {
|
|
1370
|
-
const cmd = Commander
|
|
1371
|
-
.make({ name: "app" })
|
|
1372
|
-
.option(
|
|
1373
|
-
Commander
|
|
1374
|
-
.option("--first")
|
|
1375
|
-
.schema(Schema.String),
|
|
1376
|
-
)
|
|
1377
|
-
.option(
|
|
1378
|
-
Commander
|
|
1379
|
-
.option("--second")
|
|
1380
|
-
.schema(Schema.String),
|
|
1381
|
-
)
|
|
1382
|
-
|
|
1383
|
-
const result1 = await Effect.runPromise(
|
|
1384
|
-
Commander.parse(cmd, ["--first", "1", "--second", "2"]),
|
|
1385
|
-
)
|
|
1386
|
-
|
|
1387
|
-
const result2 = await Effect.runPromise(
|
|
1388
|
-
Commander.parse(cmd, ["--second", "2", "--first", "1"]),
|
|
1389
|
-
)
|
|
1390
|
-
|
|
1391
|
-
test
|
|
1392
|
-
.expect(result1.first)
|
|
1393
|
-
.toBe("1")
|
|
1394
|
-
test
|
|
1395
|
-
.expect(result1.second)
|
|
1396
|
-
.toBe("2")
|
|
1397
|
-
test
|
|
1398
|
-
.expect(result2.first)
|
|
1399
|
-
.toBe("1")
|
|
1400
|
-
test
|
|
1401
|
-
.expect(result2.second)
|
|
1402
|
-
.toBe("2")
|
|
1403
|
-
})
|
|
1404
|
-
|
|
1405
|
-
test.it("should handle options with hyphens in names", async () => {
|
|
1406
|
-
const cmd = Commander
|
|
1407
|
-
.make({ name: "app" })
|
|
1408
|
-
.option(
|
|
1409
|
-
Commander
|
|
1410
|
-
.option("--dry-run")
|
|
1411
|
-
.default(false)
|
|
1412
|
-
.schema(Schema.BooleanFromString),
|
|
1413
|
-
)
|
|
1414
|
-
.option(
|
|
1415
|
-
Commander
|
|
1416
|
-
.option("--no-cache")
|
|
1417
|
-
.default(false)
|
|
1418
|
-
.schema(Schema.BooleanFromString),
|
|
1419
|
-
)
|
|
1420
|
-
|
|
1421
|
-
const result = await Effect.runPromise(
|
|
1422
|
-
Commander.parse(cmd, ["--dry-run", "true", "--no-cache", "true"]),
|
|
1423
|
-
)
|
|
1424
|
-
|
|
1425
|
-
test
|
|
1426
|
-
.expect(result.dryRun)
|
|
1427
|
-
.toBe(true)
|
|
1428
|
-
test
|
|
1429
|
-
.expect(result.noCache)
|
|
1430
|
-
.toBe(true)
|
|
1431
|
-
})
|
|
1432
|
-
})
|
|
1433
|
-
|
|
1434
|
-
test.describe("error handling", () => {
|
|
1435
|
-
test.it("should fail gracefully on invalid option value", async () => {
|
|
1436
|
-
const cmd = Commander
|
|
1437
|
-
.make({ name: "app" })
|
|
1438
|
-
.option(
|
|
1439
|
-
Commander
|
|
1440
|
-
.option("--port")
|
|
1441
|
-
.schema(Commander.NumberFromString),
|
|
1442
|
-
)
|
|
1443
|
-
|
|
1444
|
-
const result = await Effect.runPromise(
|
|
1445
|
-
Effect.either(Commander.parse(cmd, ["--port", "invalid"])),
|
|
1446
|
-
)
|
|
1447
|
-
|
|
1448
|
-
assert.strictEqual(result._tag, "Left")
|
|
1449
|
-
test
|
|
1450
|
-
.expect(result.left.message)
|
|
1451
|
-
.toContain("Invalid value")
|
|
1452
|
-
})
|
|
1453
|
-
|
|
1454
|
-
test.it("should fail on invalid choice", async () => {
|
|
1455
|
-
const cmd = Commander
|
|
1456
|
-
.make({ name: "app" })
|
|
1457
|
-
.option(
|
|
1458
|
-
Commander
|
|
1459
|
-
.option("--mode")
|
|
1460
|
-
.schema(Schema.compose(Schema.String, Schema.Literal("dev", "prod"))),
|
|
1461
|
-
)
|
|
1462
|
-
|
|
1463
|
-
const result = await Effect.runPromise(
|
|
1464
|
-
Effect.either(Commander.parse(cmd, ["--mode", "staging"])),
|
|
1465
|
-
)
|
|
1466
|
-
|
|
1467
|
-
test
|
|
1468
|
-
.expect(result._tag)
|
|
1469
|
-
.toBe("Left")
|
|
1470
|
-
})
|
|
1471
|
-
})
|
|
1472
|
-
|
|
1473
|
-
test.describe("builder pattern", () => {
|
|
1474
|
-
test.it("should chain option definitions fluently", () => {
|
|
1475
|
-
const cmd = Commander
|
|
1476
|
-
.make({ name: "app" })
|
|
1477
|
-
.option(
|
|
1478
|
-
Commander
|
|
1479
|
-
.option("--input", "-i")
|
|
1480
|
-
.description("Input file")
|
|
1481
|
-
.schema(Schema.String),
|
|
1482
|
-
)
|
|
1483
|
-
.option(
|
|
1484
|
-
Commander
|
|
1485
|
-
.option("--output", "-o")
|
|
1486
|
-
.description("Output file")
|
|
1487
|
-
.default("out.txt")
|
|
1488
|
-
.schema(Schema.String),
|
|
1489
|
-
)
|
|
1490
|
-
|
|
1491
|
-
test
|
|
1492
|
-
.expect(cmd.options.input.description)
|
|
1493
|
-
.toBe("Input file")
|
|
1494
|
-
test
|
|
1495
|
-
.expect(cmd.options.output.description)
|
|
1496
|
-
.toBe("Output file")
|
|
1497
|
-
test
|
|
1498
|
-
.expect(cmd.options.output.defaultValue)
|
|
1499
|
-
.toBe("out.txt")
|
|
1500
|
-
})
|
|
1501
|
-
|
|
1502
|
-
test.it("should chain description and default in any order", () => {
|
|
1503
|
-
const cmd1 = Commander
|
|
1504
|
-
.make({ name: "app" })
|
|
1505
|
-
.option(
|
|
1506
|
-
Commander
|
|
1507
|
-
.option("--port")
|
|
1508
|
-
.description("Port number")
|
|
1509
|
-
.default(3000)
|
|
1510
|
-
.schema(Commander.NumberFromString),
|
|
1511
|
-
)
|
|
1512
|
-
|
|
1513
|
-
const cmd2 = Commander
|
|
1514
|
-
.make({ name: "app" })
|
|
1515
|
-
.option(
|
|
1516
|
-
Commander
|
|
1517
|
-
.option("--port")
|
|
1518
|
-
.default(3000)
|
|
1519
|
-
.description("Port number")
|
|
1520
|
-
.schema(Commander.NumberFromString),
|
|
1521
|
-
)
|
|
1522
|
-
|
|
1523
|
-
test
|
|
1524
|
-
.expect(cmd1.options.port.description)
|
|
1525
|
-
.toBe("Port number")
|
|
1526
|
-
test
|
|
1527
|
-
.expect(cmd1.options.port.defaultValue)
|
|
1528
|
-
.toBe(3000)
|
|
1529
|
-
test
|
|
1530
|
-
.expect(cmd2.options.port.description)
|
|
1531
|
-
.toBe("Port number")
|
|
1532
|
-
test
|
|
1533
|
-
.expect(cmd2.options.port.defaultValue)
|
|
1534
|
-
.toBe(3000)
|
|
1535
|
-
})
|
|
1536
|
-
|
|
1537
|
-
test.it("should support method chaining with subcommands", () => {
|
|
1538
|
-
const sub1 = Commander
|
|
1539
|
-
.make({ name: "sub1" })
|
|
1540
|
-
.handle(() => Effect.void)
|
|
1541
|
-
|
|
1542
|
-
const sub2 = Commander
|
|
1543
|
-
.make({ name: "sub2" })
|
|
1544
|
-
.handle(() => Effect.void)
|
|
1545
|
-
|
|
1546
|
-
const cmd = Commander
|
|
1547
|
-
.make({ name: "app" })
|
|
1548
|
-
.option(
|
|
1549
|
-
Commander
|
|
1550
|
-
.option("--global")
|
|
1551
|
-
.schema(Schema.String),
|
|
1552
|
-
)
|
|
1553
|
-
.subcommand(sub1)
|
|
1554
|
-
.subcommand(sub2)
|
|
1555
|
-
.optionHelp()
|
|
1556
|
-
|
|
1557
|
-
test
|
|
1558
|
-
.expect(cmd.options.global)
|
|
1559
|
-
.toBeDefined()
|
|
1560
|
-
test
|
|
1561
|
-
.expect(cmd.options.help)
|
|
1562
|
-
.toBeDefined()
|
|
1563
|
-
test
|
|
1564
|
-
.expect(cmd.subcommands.length)
|
|
1565
|
-
.toBe(2)
|
|
1566
|
-
})
|
|
1567
|
-
})
|
|
1568
|
-
|
|
1569
|
-
test.describe("example scenario", () => {
|
|
1570
|
-
test.it("should handle main command with subcommand", async () => {
|
|
1571
|
-
const unhandledFormat = Commander.make({
|
|
1572
|
-
name: "format",
|
|
1573
|
-
description: "Format source files",
|
|
1574
|
-
})
|
|
1575
|
-
|
|
1576
|
-
const handledFormat = unhandledFormat
|
|
1577
|
-
.option(
|
|
1578
|
-
Commander
|
|
1579
|
-
.option("--style", "-s")
|
|
1580
|
-
.description("Code style to use")
|
|
1581
|
-
.default("standard")
|
|
1582
|
-
.schema(
|
|
1583
|
-
Schema.compose(
|
|
1584
|
-
Schema.String,
|
|
1585
|
-
Schema.Literal("standard", "prettier", "biome"),
|
|
1586
|
-
),
|
|
1587
|
-
),
|
|
1588
|
-
)
|
|
1589
|
-
.handle((opts) => Effect.sync(() => ({ style: opts.style })))
|
|
1590
|
-
|
|
1591
|
-
const main = Commander
|
|
1592
|
-
.make({
|
|
1593
|
-
name: "main",
|
|
1594
|
-
description: "this is doing that",
|
|
1595
|
-
version: "1.0.0",
|
|
1596
|
-
})
|
|
1597
|
-
.option(
|
|
1598
|
-
Commander
|
|
1599
|
-
.option("--source", "-s")
|
|
1600
|
-
.schema(Schema.String),
|
|
1601
|
-
)
|
|
1602
|
-
.option(
|
|
1603
|
-
Commander
|
|
1604
|
-
.option("--verbose", "-v")
|
|
1605
|
-
.description("Enable verbose output")
|
|
1606
|
-
.default(false)
|
|
1607
|
-
.schema(Schema.BooleanFromString),
|
|
1608
|
-
)
|
|
1609
|
-
.optionHelp()
|
|
1610
|
-
.subcommand(handledFormat)
|
|
1611
|
-
.handle((opts) => Effect.sync(() => opts))
|
|
1612
|
-
|
|
1613
|
-
const resultMain = await Effect.runPromise(
|
|
1614
|
-
Commander.parse(main, ["--source", "test.ts", "--verbose", "true"]),
|
|
1615
|
-
)
|
|
1616
|
-
|
|
1617
|
-
test
|
|
1618
|
-
.expect(resultMain.source)
|
|
1619
|
-
.toBe("test.ts")
|
|
1620
|
-
test
|
|
1621
|
-
.expect(resultMain.verbose)
|
|
1622
|
-
.toBe(true)
|
|
1623
|
-
test
|
|
1624
|
-
.expect(resultMain.help)
|
|
1625
|
-
.toBe(false)
|
|
1626
|
-
test
|
|
1627
|
-
.expect(main.subcommands.length)
|
|
1628
|
-
.toBe(1)
|
|
1629
|
-
test
|
|
1630
|
-
.expect(main.subcommands[0]!.command.name)
|
|
1631
|
-
.toBe("format")
|
|
1632
|
-
test
|
|
1633
|
-
.expect(main.subcommands[0]!.command.options.style)
|
|
1634
|
-
.toBeDefined()
|
|
1635
|
-
test
|
|
1636
|
-
.expect(main.subcommands[0]!.command.options.style.defaultValue)
|
|
1637
|
-
.toBe("standard")
|
|
1638
|
-
})
|
|
1639
|
-
})
|