effect 4.0.0-beta.14 → 4.0.0-beta.16
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/Channel.d.ts +6 -6
- package/dist/Channel.d.ts.map +1 -1
- package/dist/Channel.js +4 -4
- package/dist/Channel.js.map +1 -1
- package/dist/Effect.d.ts +7 -7
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js.map +1 -1
- package/dist/Schema.d.ts +43 -0
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +37 -0
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaParser.d.ts +5 -0
- package/dist/SchemaParser.d.ts.map +1 -1
- package/dist/SchemaParser.js +10 -0
- package/dist/SchemaParser.js.map +1 -1
- package/dist/SchemaTransformation.d.ts +70 -3
- package/dist/SchemaTransformation.d.ts.map +1 -1
- package/dist/SchemaTransformation.js +79 -4
- package/dist/SchemaTransformation.js.map +1 -1
- package/dist/Stream.d.ts +7 -7
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +8 -6
- package/dist/Stream.js.map +1 -1
- package/dist/Types.d.ts +70 -0
- package/dist/Types.d.ts.map +1 -1
- package/dist/internal/effect.js +4 -4
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/schema/schema.js +1 -0
- package/dist/internal/schema/schema.js.map +1 -1
- package/dist/unstable/ai/LanguageModel.d.ts +2 -0
- package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
- package/dist/unstable/ai/LanguageModel.js.map +1 -1
- package/dist/unstable/cli/Command.d.ts +34 -4
- package/dist/unstable/cli/Command.d.ts.map +1 -1
- package/dist/unstable/cli/Command.js +73 -24
- package/dist/unstable/cli/Command.js.map +1 -1
- package/dist/unstable/cli/GlobalFlag.d.ts +21 -56
- package/dist/unstable/cli/GlobalFlag.d.ts.map +1 -1
- package/dist/unstable/cli/GlobalFlag.js +9 -48
- package/dist/unstable/cli/GlobalFlag.js.map +1 -1
- package/dist/unstable/cli/internal/command.d.ts +3 -0
- package/dist/unstable/cli/internal/command.d.ts.map +1 -1
- package/dist/unstable/cli/internal/command.js +2 -0
- package/dist/unstable/cli/internal/command.js.map +1 -1
- package/dist/unstable/cli/internal/help.d.ts +18 -4
- package/dist/unstable/cli/internal/help.d.ts.map +1 -1
- package/dist/unstable/cli/internal/help.js +61 -7
- package/dist/unstable/cli/internal/help.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.d.ts +10 -4
- package/dist/unstable/httpapi/HttpApiBuilder.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.js +17 -6
- package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiEndpoint.d.ts +7 -2
- package/dist/unstable/httpapi/HttpApiEndpoint.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiEndpoint.js.map +1 -1
- package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
- package/dist/unstable/httpapi/OpenApi.js +11 -1
- package/dist/unstable/httpapi/OpenApi.js.map +1 -1
- package/dist/unstable/reactivity/AtomHttpApi.d.ts +2 -2
- package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomRegistry.js +2 -6
- package/dist/unstable/reactivity/AtomRegistry.js.map +1 -1
- package/package.json +1 -1
- package/src/Channel.ts +24 -14
- package/src/Effect.ts +30 -8
- package/src/Schema.ts +61 -0
- package/src/SchemaParser.ts +11 -0
- package/src/SchemaTransformation.ts +85 -4
- package/src/Stream.ts +46 -22
- package/src/Types.ts +66 -0
- package/src/internal/effect.ts +41 -14
- package/src/internal/schema/schema.ts +1 -0
- package/src/unstable/ai/LanguageModel.ts +9 -6
- package/src/unstable/cli/Command.ts +119 -31
- package/src/unstable/cli/GlobalFlag.ts +36 -114
- package/src/unstable/cli/internal/command.ts +5 -0
- package/src/unstable/cli/internal/help.ts +103 -22
- package/src/unstable/httpapi/HttpApiBuilder.ts +68 -13
- package/src/unstable/httpapi/HttpApiEndpoint.ts +13 -4
- package/src/unstable/httpapi/OpenApi.ts +18 -1
- package/src/unstable/reactivity/AtomHttpApi.ts +2 -2
- package/src/unstable/reactivity/AtomRegistry.ts +2 -6
package/src/Stream.ts
CHANGED
|
@@ -48,7 +48,9 @@ import type {
|
|
|
48
48
|
ExcludeTag,
|
|
49
49
|
ExtractReason,
|
|
50
50
|
ExtractTag,
|
|
51
|
+
NarrowReason,
|
|
51
52
|
NoInfer,
|
|
53
|
+
OmitReason,
|
|
52
54
|
ReasonTags,
|
|
53
55
|
Tags,
|
|
54
56
|
unassigned
|
|
@@ -8092,8 +8094,16 @@ export const catchReason: {
|
|
|
8092
8094
|
>(
|
|
8093
8095
|
errorTag: K,
|
|
8094
8096
|
reasonTag: RK,
|
|
8095
|
-
f: (
|
|
8096
|
-
|
|
8097
|
+
f: (
|
|
8098
|
+
reason: ExtractReason<ExtractTag<NoInfer<E>, K>, RK>,
|
|
8099
|
+
error: NarrowReason<ExtractTag<NoInfer<E>, K>, RK>
|
|
8100
|
+
) => Stream<A2, E2, R2>,
|
|
8101
|
+
orElse?:
|
|
8102
|
+
| ((
|
|
8103
|
+
reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, RK>,
|
|
8104
|
+
error: OmitReason<ExtractTag<NoInfer<E>, K>, RK>
|
|
8105
|
+
) => Stream<A3, E3, R3>)
|
|
8106
|
+
| undefined
|
|
8097
8107
|
): <A, R>(
|
|
8098
8108
|
self: Stream<A, E, R>
|
|
8099
8109
|
) => Stream<A | A2 | Exclude<A3, unassigned>, (A3 extends unassigned ? E : ExcludeTag<E, K>) | E2 | E3, R | R2 | R3>
|
|
@@ -8156,8 +8166,10 @@ export const catchReason: {
|
|
|
8156
8166
|
self: Stream<A, E, R>,
|
|
8157
8167
|
errorTag: K,
|
|
8158
8168
|
reasonTag: RK,
|
|
8159
|
-
f: (reason: ExtractReason<ExtractTag<E, K>, RK>) => Stream<A2, E2, R2>,
|
|
8160
|
-
orElse?:
|
|
8169
|
+
f: (reason: ExtractReason<ExtractTag<E, K>, RK>, error: NarrowReason<ExtractTag<E, K>, RK>) => Stream<A2, E2, R2>,
|
|
8170
|
+
orElse?:
|
|
8171
|
+
| ((reason: ExcludeReason<ExtractTag<E, K>, RK>, error: OmitReason<ExtractTag<E, K>, RK>) => Stream<A3, E3, R3>)
|
|
8172
|
+
| undefined
|
|
8161
8173
|
): Stream<A | A2 | Exclude<A3, unassigned>, (A3 extends unassigned ? E : ExcludeTag<E, K>) | E2 | E3, R | R2 | R3>
|
|
8162
8174
|
} = dual(
|
|
8163
8175
|
(args) => isStream(args[0]),
|
|
@@ -8177,16 +8189,18 @@ export const catchReason: {
|
|
|
8177
8189
|
self: Stream<A, E, R>,
|
|
8178
8190
|
errorTag: K,
|
|
8179
8191
|
reasonTag: RK,
|
|
8180
|
-
f: (reason: ExtractReason<ExtractTag<E, K>, RK>) => Stream<A2, E2, R2>,
|
|
8181
|
-
orElse?:
|
|
8192
|
+
f: (reason: ExtractReason<ExtractTag<E, K>, RK>, error: NarrowReason<ExtractTag<E, K>, RK>) => Stream<A2, E2, R2>,
|
|
8193
|
+
orElse?:
|
|
8194
|
+
| ((reason: ExcludeReason<ExtractTag<E, K>, RK>, error: OmitReason<ExtractTag<E, K>, RK>) => Stream<A3, E3, R3>)
|
|
8195
|
+
| undefined
|
|
8182
8196
|
): Stream<A | A2 | Exclude<A3, unassigned>, (A3 extends unassigned ? E : ExcludeTag<E, K>) | E2 | E3, R | R2 | R3> =>
|
|
8183
8197
|
fromChannel(
|
|
8184
8198
|
Channel.catchReason(
|
|
8185
8199
|
toChannel(self),
|
|
8186
8200
|
errorTag,
|
|
8187
8201
|
reasonTag,
|
|
8188
|
-
(reason) => f(reason).channel,
|
|
8189
|
-
orElse && ((reason) => orElse(reason).channel)
|
|
8202
|
+
(reason, error) => f(reason, error).channel,
|
|
8203
|
+
orElse && ((reason, error) => orElse(reason, error).channel)
|
|
8190
8204
|
)
|
|
8191
8205
|
) as any
|
|
8192
8206
|
)
|
|
@@ -8279,7 +8293,8 @@ export const catchReasons: {
|
|
|
8279
8293
|
E,
|
|
8280
8294
|
Cases extends {
|
|
8281
8295
|
[RK in ReasonTags<ExtractTag<NoInfer<E>, K>>]+?: (
|
|
8282
|
-
reason: ExtractReason<ExtractTag<NoInfer<E>, K>, RK
|
|
8296
|
+
reason: ExtractReason<ExtractTag<NoInfer<E>, K>, RK>,
|
|
8297
|
+
error: NarrowReason<ExtractTag<NoInfer<E>, K>, RK>
|
|
8283
8298
|
) => Stream<any, any, any>
|
|
8284
8299
|
},
|
|
8285
8300
|
A2 = unassigned,
|
|
@@ -8289,7 +8304,10 @@ export const catchReasons: {
|
|
|
8289
8304
|
errorTag: K,
|
|
8290
8305
|
cases: Cases,
|
|
8291
8306
|
orElse?:
|
|
8292
|
-
| ((
|
|
8307
|
+
| ((
|
|
8308
|
+
reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>,
|
|
8309
|
+
error: OmitReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>
|
|
8310
|
+
) => Stream<A2, E2, R2>)
|
|
8293
8311
|
| undefined
|
|
8294
8312
|
): <A, R>(self: Stream<A, E, R>) => Stream<
|
|
8295
8313
|
| A
|
|
@@ -8356,7 +8374,8 @@ export const catchReasons: {
|
|
|
8356
8374
|
K extends Tags<E>,
|
|
8357
8375
|
Cases extends {
|
|
8358
8376
|
[RK in ReasonTags<ExtractTag<E, K>>]+?: (
|
|
8359
|
-
reason: ExtractReason<ExtractTag<E, K>, RK
|
|
8377
|
+
reason: ExtractReason<ExtractTag<E, K>, RK>,
|
|
8378
|
+
error: NarrowReason<ExtractTag<E, K>, RK>
|
|
8360
8379
|
) => Stream<any, any, any>
|
|
8361
8380
|
},
|
|
8362
8381
|
A2 = unassigned,
|
|
@@ -8367,7 +8386,10 @@ export const catchReasons: {
|
|
|
8367
8386
|
errorTag: K,
|
|
8368
8387
|
cases: Cases,
|
|
8369
8388
|
orElse?:
|
|
8370
|
-
| ((
|
|
8389
|
+
| ((
|
|
8390
|
+
reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>,
|
|
8391
|
+
error: OmitReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>
|
|
8392
|
+
) => Stream<A2, E2, R2>)
|
|
8371
8393
|
| undefined
|
|
8372
8394
|
): Stream<
|
|
8373
8395
|
| A
|
|
@@ -8387,12 +8409,12 @@ export const catchReasons: {
|
|
|
8387
8409
|
}[keyof Cases]
|
|
8388
8410
|
>
|
|
8389
8411
|
} = dual((args) => isStream(args[0]), (self, errorTag, cases, orElse) => {
|
|
8390
|
-
const handlers: Record<string, (reason: any) => Channel.Channel<any, any, any, any, any, any, any>> = {}
|
|
8412
|
+
const handlers: Record<string, (reason: any, error: any) => Channel.Channel<any, any, any, any, any, any, any>> = {}
|
|
8391
8413
|
for (const key of Object.keys(cases)) {
|
|
8392
8414
|
const handler = (cases as any)[key]
|
|
8393
|
-
handlers[key] = (reason) => handler(reason).channel
|
|
8415
|
+
handlers[key] = (reason, error) => handler(reason, error).channel
|
|
8394
8416
|
}
|
|
8395
|
-
const orElseHandler = orElse && ((reason: any) => orElse(reason).channel)
|
|
8417
|
+
const orElseHandler = orElse && ((reason: any, error: any) => orElse(reason, error).channel)
|
|
8396
8418
|
return fromChannel(
|
|
8397
8419
|
Channel.catchReasons(self.channel, errorTag as any, handlers as any, orElseHandler as any) as Channel.Channel<
|
|
8398
8420
|
Arr.NonEmptyReadonlyArray<any>,
|
|
@@ -13638,12 +13660,15 @@ export const aggregateWithin: {
|
|
|
13638
13660
|
* @category Aggregation
|
|
13639
13661
|
*/
|
|
13640
13662
|
B>()
|
|
13663
|
+
let leftover: Arr.NonEmptyReadonlyArray<A2> | undefined
|
|
13641
13664
|
const step = yield* Schedule.toStepWithSleep(schedule)
|
|
13642
|
-
const stepToBuffer = Effect.suspend(()
|
|
13643
|
-
|
|
13644
|
-
|
|
13645
|
-
|
|
13646
|
-
|
|
13665
|
+
const stepToBuffer = Effect.suspend(function loop(): Pull.Pull<never, E3, void, R3> {
|
|
13666
|
+
return step(lastOutput).pipe(
|
|
13667
|
+
Effect.flatMap(() => !hadChunk && leftover === undefined ? loop() : Queue.offer(buffer, scheduleStep)),
|
|
13668
|
+
Effect.flatMap(() => Effect.never),
|
|
13669
|
+
Pull.catchDone(() => Cause.done())
|
|
13670
|
+
)
|
|
13671
|
+
})
|
|
13647
13672
|
|
|
13648
13673
|
// buffer -> sink
|
|
13649
13674
|
const pullFromBuffer: Pull.Pull<
|
|
@@ -13653,7 +13678,6 @@ export const aggregateWithin: {
|
|
|
13653
13678
|
Effect.flatMap((arr) => arr === scheduleStep ? Cause.done() : Effect.succeed(arr))
|
|
13654
13679
|
)
|
|
13655
13680
|
|
|
13656
|
-
let leftover: Arr.NonEmptyReadonlyArray<A2> | undefined
|
|
13657
13681
|
const sinkUpstream = Effect.suspend((): Pull.Pull<Arr.NonEmptyReadonlyArray<A | A2>, E> => {
|
|
13658
13682
|
if (leftover !== undefined) {
|
|
13659
13683
|
const chunk = leftover
|
|
@@ -13665,7 +13689,7 @@ export const aggregateWithin: {
|
|
|
13665
13689
|
return pullFromBuffer
|
|
13666
13690
|
})
|
|
13667
13691
|
const catchSinkHalt = Effect.flatMap(([value, leftover_]: Sink.End<B, A2>) => {
|
|
13668
|
-
// ignore the last output if the
|
|
13692
|
+
// ignore the last output if the upstream only pulled a halt
|
|
13669
13693
|
if (!hadChunk && buffer.state._tag === "Done") return Cause.done()
|
|
13670
13694
|
lastOutput = Option.some(value)
|
|
13671
13695
|
leftover = leftover_
|
package/src/Types.ts
CHANGED
|
@@ -927,6 +927,72 @@ export type ExtractReason<E, K extends string> = E extends { readonly reason: in
|
|
|
927
927
|
: never
|
|
928
928
|
: never
|
|
929
929
|
|
|
930
|
+
/**
|
|
931
|
+
* Narrows a specific reason variant by its `_tag` from an error's `reason`
|
|
932
|
+
* field.
|
|
933
|
+
*
|
|
934
|
+
* - Use to narrow down to a single reason variant from a nested error type.
|
|
935
|
+
* - Returns `never` if `E` has no matching reason variant.
|
|
936
|
+
*
|
|
937
|
+
* **Example** (Narrowing a reason variant)
|
|
938
|
+
*
|
|
939
|
+
* ```ts
|
|
940
|
+
* import type { Types } from "effect"
|
|
941
|
+
*
|
|
942
|
+
* type RateLimitError = { readonly _tag: "RateLimitError"; readonly retryAfter: number }
|
|
943
|
+
* type QuotaError = { readonly _tag: "QuotaError"; readonly limit: number }
|
|
944
|
+
* type ApiError = { readonly _tag: "ApiError"; readonly reason: RateLimitError | QuotaError }
|
|
945
|
+
*
|
|
946
|
+
* type Result = Types.NarrowReason<ApiError, "RateLimitError">
|
|
947
|
+
* // ApiError & { readonly reason: { readonly _tag: "RateLimitError"; readonly retryAfter: number } }
|
|
948
|
+
* ```
|
|
949
|
+
*
|
|
950
|
+
* @see {@link ExcludeReason}
|
|
951
|
+
* @see {@link ReasonOf}
|
|
952
|
+
* @see {@link ReasonTags}
|
|
953
|
+
*
|
|
954
|
+
* @since 4.0.0
|
|
955
|
+
* @category types
|
|
956
|
+
*/
|
|
957
|
+
export type NarrowReason<E, K extends string> = E extends { readonly reason: infer R }
|
|
958
|
+
? R extends { readonly _tag: infer T } ? K extends T ? E & { readonly reason: R } : never
|
|
959
|
+
: never
|
|
960
|
+
: never
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* Narrows an error's `reason` field to exclude a specific reason variant by
|
|
964
|
+
* its `_tag`.
|
|
965
|
+
*
|
|
966
|
+
* - Use to narrow the error to only the remaining reason variants after
|
|
967
|
+
* excluding the matched one.
|
|
968
|
+
* - Returns `never` if `E` has no `reason` field or no remaining variants.
|
|
969
|
+
*
|
|
970
|
+
* **Example** (Omitting a reason variant)
|
|
971
|
+
*
|
|
972
|
+
* ```ts
|
|
973
|
+
* import type { Types } from "effect"
|
|
974
|
+
*
|
|
975
|
+
* type RateLimitError = { readonly _tag: "RateLimitError"; readonly retryAfter: number }
|
|
976
|
+
* type QuotaError = { readonly _tag: "QuotaError"; readonly limit: number }
|
|
977
|
+
* type ApiError = { readonly _tag: "ApiError"; readonly reason: RateLimitError | QuotaError }
|
|
978
|
+
*
|
|
979
|
+
* type Result = Types.OmitReason<ApiError, "RateLimitError">
|
|
980
|
+
* // ApiError & { readonly reason: { readonly _tag: "QuotaError"; readonly limit: number } }
|
|
981
|
+
* ```
|
|
982
|
+
*
|
|
983
|
+
* @see {@link NarrowReason}
|
|
984
|
+
* @see {@link ExcludeReason}
|
|
985
|
+
* @see {@link ReasonOf}
|
|
986
|
+
* @see {@link ReasonTags}
|
|
987
|
+
*
|
|
988
|
+
* @since 4.0.0
|
|
989
|
+
* @category types
|
|
990
|
+
*/
|
|
991
|
+
export type OmitReason<E, K extends string> = E extends { readonly reason: infer R }
|
|
992
|
+
? R extends { readonly _tag: infer T } ? K extends T ? never : E & { readonly reason: R }
|
|
993
|
+
: never
|
|
994
|
+
: never
|
|
995
|
+
|
|
930
996
|
/**
|
|
931
997
|
* Excludes a specific reason variant by its `_tag` from an error's `reason`
|
|
932
998
|
* field.
|
package/src/internal/effect.ts
CHANGED
|
@@ -50,7 +50,9 @@ import type {
|
|
|
50
50
|
ExcludeTag,
|
|
51
51
|
ExtractReason,
|
|
52
52
|
ExtractTag,
|
|
53
|
+
NarrowReason,
|
|
53
54
|
NoInfer,
|
|
55
|
+
OmitReason,
|
|
54
56
|
ReasonOf,
|
|
55
57
|
ReasonTags,
|
|
56
58
|
Simplify,
|
|
@@ -2824,8 +2826,16 @@ export const catchReason: {
|
|
|
2824
2826
|
>(
|
|
2825
2827
|
errorTag: K,
|
|
2826
2828
|
reasonTag: RK,
|
|
2827
|
-
f: (
|
|
2828
|
-
|
|
2829
|
+
f: (
|
|
2830
|
+
reason: ExtractReason<ExtractTag<NoInfer<E>, K>, RK>,
|
|
2831
|
+
error: NarrowReason<ExtractTag<NoInfer<E>, K>, RK>
|
|
2832
|
+
) => Effect.Effect<A2, E2, R2>,
|
|
2833
|
+
orElse?:
|
|
2834
|
+
| ((
|
|
2835
|
+
reasons: ExcludeReason<ExtractTag<NoInfer<E>, K>, RK>,
|
|
2836
|
+
error: OmitReason<ExtractTag<NoInfer<E>, K>, RK>
|
|
2837
|
+
) => Effect.Effect<A3, E3, R3>)
|
|
2838
|
+
| undefined
|
|
2829
2839
|
): <A, R>(
|
|
2830
2840
|
self: Effect.Effect<A, E, R>
|
|
2831
2841
|
) => Effect.Effect<
|
|
@@ -2849,8 +2859,16 @@ export const catchReason: {
|
|
|
2849
2859
|
self: Effect.Effect<A, E, R>,
|
|
2850
2860
|
errorTag: K,
|
|
2851
2861
|
reasonTag: RK,
|
|
2852
|
-
f: (
|
|
2853
|
-
|
|
2862
|
+
f: (
|
|
2863
|
+
reason: ExtractReason<ExtractTag<E, K>, RK>,
|
|
2864
|
+
error: NarrowReason<ExtractTag<E, K>, RK>
|
|
2865
|
+
) => Effect.Effect<A2, E2, R2>,
|
|
2866
|
+
orElse?:
|
|
2867
|
+
| ((
|
|
2868
|
+
reasons: ExcludeReason<ExtractTag<E, K>, RK>,
|
|
2869
|
+
error: OmitReason<ExtractTag<E, K>, RK>
|
|
2870
|
+
) => Effect.Effect<A3, E3, R3>)
|
|
2871
|
+
| undefined
|
|
2854
2872
|
): Effect.Effect<
|
|
2855
2873
|
A | A2 | Exclude<A3, unassigned>,
|
|
2856
2874
|
(A3 extends unassigned ? E : ExcludeTag<E, K>) | E2 | E3,
|
|
@@ -2874,8 +2892,13 @@ export const catchReason: {
|
|
|
2874
2892
|
self: Effect.Effect<A, E, R>,
|
|
2875
2893
|
errorTag: K,
|
|
2876
2894
|
reasonTag: RK,
|
|
2877
|
-
f: (reason: ExtractReason<ExtractTag<E, K>, RK>) => Effect.Effect<A2, E2, R2>,
|
|
2878
|
-
orElse?:
|
|
2895
|
+
f: (reason: ExtractReason<ExtractTag<E, K>, RK>, error: ExtractTag<E, K>) => Effect.Effect<A2, E2, R2>,
|
|
2896
|
+
orElse?:
|
|
2897
|
+
| ((
|
|
2898
|
+
reasons: ExcludeReason<ExtractTag<E, K>, RK>,
|
|
2899
|
+
error: OmitReason<ExtractTag<E, K>, RK>
|
|
2900
|
+
) => Effect.Effect<A3, E3, R3>)
|
|
2901
|
+
| undefined
|
|
2879
2902
|
): Effect.Effect<
|
|
2880
2903
|
A | A2 | Exclude<A3, unassigned>,
|
|
2881
2904
|
(A3 extends unassigned ? E : ExcludeTag<E, K>) | E2 | E3,
|
|
@@ -2886,8 +2909,8 @@ export const catchReason: {
|
|
|
2886
2909
|
((e: any) => isTagged(e, errorTag) && hasProperty(e, "reason")) as any,
|
|
2887
2910
|
(e: any): Effect.Effect<A2 | A3, E | E2 | E3, R2 | R3> => {
|
|
2888
2911
|
const reason = e.reason as any
|
|
2889
|
-
if (isTagged(reason, reasonTag)) return f(reason as any)
|
|
2890
|
-
return orElse ? internalCall(() => orElse(reason)) : fail(e)
|
|
2912
|
+
if (isTagged(reason, reasonTag)) return f(reason as any, e)
|
|
2913
|
+
return orElse ? internalCall(() => orElse(reason, e)) : fail(e)
|
|
2891
2914
|
}
|
|
2892
2915
|
) as any
|
|
2893
2916
|
)
|
|
@@ -2899,7 +2922,8 @@ export const catchReasons: {
|
|
|
2899
2922
|
E,
|
|
2900
2923
|
Cases extends {
|
|
2901
2924
|
[RK in ReasonTags<ExtractTag<NoInfer<E>, K>>]+?: (
|
|
2902
|
-
reason: ExtractReason<ExtractTag<NoInfer<E>, K>, RK
|
|
2925
|
+
reason: ExtractReason<ExtractTag<NoInfer<E>, K>, RK>,
|
|
2926
|
+
error: NarrowReason<ExtractTag<NoInfer<E>, K>, RK>
|
|
2903
2927
|
) => Effect.Effect<any, any, any>
|
|
2904
2928
|
},
|
|
2905
2929
|
A2 = unassigned,
|
|
@@ -2910,7 +2934,8 @@ export const catchReasons: {
|
|
|
2910
2934
|
cases: Cases,
|
|
2911
2935
|
orElse?:
|
|
2912
2936
|
| ((
|
|
2913
|
-
reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string
|
|
2937
|
+
reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>,
|
|
2938
|
+
error: OmitReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>
|
|
2914
2939
|
) => Effect.Effect<A2, E2, R2>)
|
|
2915
2940
|
| undefined
|
|
2916
2941
|
): <A, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<
|
|
@@ -2937,7 +2962,8 @@ export const catchReasons: {
|
|
|
2937
2962
|
K extends Tags<E>,
|
|
2938
2963
|
Cases extends {
|
|
2939
2964
|
[RK in ReasonTags<ExtractTag<E, K>>]+?: (
|
|
2940
|
-
reason: ExtractReason<ExtractTag<E, K>, RK
|
|
2965
|
+
reason: ExtractReason<ExtractTag<E, K>, RK>,
|
|
2966
|
+
error: NarrowReason<ExtractTag<E, K>, RK>
|
|
2941
2967
|
) => Effect.Effect<any, any, any>
|
|
2942
2968
|
},
|
|
2943
2969
|
A2 = unassigned,
|
|
@@ -2949,7 +2975,8 @@ export const catchReasons: {
|
|
|
2949
2975
|
cases: Cases,
|
|
2950
2976
|
orElse?:
|
|
2951
2977
|
| ((
|
|
2952
|
-
reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string
|
|
2978
|
+
reason: ExcludeReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>,
|
|
2979
|
+
error: OmitReason<ExtractTag<NoInfer<E>, K>, Extract<keyof Cases, string>>
|
|
2953
2980
|
) => Effect.Effect<A2, E2, R2>)
|
|
2954
2981
|
| undefined
|
|
2955
2982
|
): Effect.Effect<
|
|
@@ -2982,9 +3009,9 @@ export const catchReasons: {
|
|
|
2982
3009
|
const reason = e.reason
|
|
2983
3010
|
keys ??= Object.keys(cases)
|
|
2984
3011
|
if (keys.includes(reason._tag)) {
|
|
2985
|
-
return internalCall(() => (cases as any)[reason._tag](reason))
|
|
3012
|
+
return internalCall(() => (cases as any)[reason._tag](reason, e))
|
|
2986
3013
|
}
|
|
2987
|
-
return orElse ? internalCall(() => orElse(reason)) : fail(e)
|
|
3014
|
+
return orElse ? internalCall(() => orElse(reason, e)) : fail(e)
|
|
2988
3015
|
}
|
|
2989
3016
|
)
|
|
2990
3017
|
})
|
|
@@ -527,13 +527,16 @@ export type ExtractError<Options> = Options extends {
|
|
|
527
527
|
* @category utility types
|
|
528
528
|
*/
|
|
529
529
|
export type ExtractServices<Options> = Options extends {
|
|
530
|
-
readonly
|
|
531
|
-
}
|
|
530
|
+
readonly disableToolCallResolution: true
|
|
531
|
+
} ? never
|
|
532
|
+
: Options extends {
|
|
533
|
+
readonly toolkit: Toolkit.WithHandler<infer _Tools>
|
|
534
|
+
}
|
|
532
535
|
// Required for tool call execution
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
536
|
+
?
|
|
537
|
+
| Tool.ResultEncodingServices<_Tools[keyof _Tools]>
|
|
538
|
+
// Required for decoding large language model responses
|
|
539
|
+
| Tool.ResultDecodingServices<_Tools[keyof _Tools]>
|
|
537
540
|
: Options extends {
|
|
538
541
|
readonly toolkit: Effect.Yieldable<
|
|
539
542
|
Toolkit.Toolkit<infer _Tools>,
|
|
@@ -6,7 +6,7 @@ import * as Console from "../../Console.ts"
|
|
|
6
6
|
import * as Effect from "../../Effect.ts"
|
|
7
7
|
import type * as FileSystem from "../../FileSystem.ts"
|
|
8
8
|
import { dual } from "../../Function.ts"
|
|
9
|
-
import * as Layer from "../../Layer.ts"
|
|
9
|
+
import type * as Layer from "../../Layer.ts"
|
|
10
10
|
import * as Option from "../../Option.ts"
|
|
11
11
|
import type * as Path from "../../Path.ts"
|
|
12
12
|
import type { Pipeable } from "../../Pipeable.ts"
|
|
@@ -22,7 +22,7 @@ import * as CliOutput from "./CliOutput.ts"
|
|
|
22
22
|
import * as GlobalFlag from "./GlobalFlag.ts"
|
|
23
23
|
import { checkForDuplicateFlags, makeCommand, toImpl, TypeId } from "./internal/command.ts"
|
|
24
24
|
import { parseConfig } from "./internal/config.ts"
|
|
25
|
-
import { getHelpForCommandPath } from "./internal/help.ts"
|
|
25
|
+
import { getGlobalFlagsForCommandPath, getGlobalFlagsForCommandTree, getHelpForCommandPath } from "./internal/help.ts"
|
|
26
26
|
import * as Lexer from "./internal/lexer.ts"
|
|
27
27
|
import * as Parser from "./internal/parser.ts"
|
|
28
28
|
import * as Param from "./Param.ts"
|
|
@@ -588,7 +588,7 @@ export const make: {
|
|
|
588
588
|
name: Name,
|
|
589
589
|
config: Config,
|
|
590
590
|
handler: (config: Command.Config.Infer<Config>) => Effect.Effect<void, E, R>
|
|
591
|
-
): Command<Name, Command.Config.Infer<Config>, E, R
|
|
591
|
+
): Command<Name, Command.Config.Infer<Config>, E, Exclude<R, GlobalFlag.BuiltInSettingContext>>
|
|
592
592
|
} = ((
|
|
593
593
|
name: string,
|
|
594
594
|
config?: Command.Config,
|
|
@@ -661,7 +661,7 @@ export const withHandler: {
|
|
|
661
661
|
*/
|
|
662
662
|
<A, R, E>(handler: (value: A) => Effect.Effect<void, E, R>): <Name extends string, XR, XE>(
|
|
663
663
|
self: Command<Name, A, XE, XR>
|
|
664
|
-
) => Command<Name, A, E, R
|
|
664
|
+
) => Command<Name, A, E, Exclude<R, GlobalFlag.BuiltInSettingContext>>
|
|
665
665
|
/* ========================================================================== */
|
|
666
666
|
/* Combinators */
|
|
667
667
|
/* ========================================================================== */
|
|
@@ -693,11 +693,12 @@ export const withHandler: {
|
|
|
693
693
|
<Name extends string, A, XR, XE, R, E>(
|
|
694
694
|
self: Command<Name, A, XE, XR>,
|
|
695
695
|
handler: (value: A) => Effect.Effect<void, E, R>
|
|
696
|
-
): Command<Name, A, E, R
|
|
696
|
+
): Command<Name, A, E, Exclude<R, GlobalFlag.BuiltInSettingContext>>
|
|
697
697
|
} = dual(2, <Name extends string, A, XR, XE, R, E>(
|
|
698
698
|
self: Command<Name, A, XE, XR>,
|
|
699
699
|
handler: (value: A) => Effect.Effect<void, E, R>
|
|
700
|
-
): Command<Name, A, E, R
|
|
700
|
+
): Command<Name, A, E, Exclude<R, GlobalFlag.BuiltInSettingContext>> =>
|
|
701
|
+
makeCommand({ ...toImpl(self), handle: handler }))
|
|
701
702
|
|
|
702
703
|
interface SubcommandGroupInternal {
|
|
703
704
|
readonly group: string | undefined
|
|
@@ -942,6 +943,7 @@ export const withSubcommands: {
|
|
|
942
943
|
shortDescription: impl.shortDescription,
|
|
943
944
|
alias: impl.alias,
|
|
944
945
|
annotations: impl.annotations,
|
|
946
|
+
globalFlags: impl.globalFlags,
|
|
945
947
|
examples: impl.examples,
|
|
946
948
|
service: impl.service,
|
|
947
949
|
subcommands: normalized.groups,
|
|
@@ -950,7 +952,50 @@ export const withSubcommands: {
|
|
|
950
952
|
})
|
|
951
953
|
})
|
|
952
954
|
|
|
955
|
+
/**
|
|
956
|
+
* Declares global flags for a command scope.
|
|
957
|
+
*
|
|
958
|
+
* Declared global flags apply to the command and all of its descendants.
|
|
959
|
+
*
|
|
960
|
+
* @since 4.0.0
|
|
961
|
+
* @category combinators
|
|
962
|
+
*/
|
|
963
|
+
export const withGlobalFlags: {
|
|
964
|
+
/**
|
|
965
|
+
* Declares global flags for a command scope.
|
|
966
|
+
*
|
|
967
|
+
* Declared global flags apply to the command and all of its descendants.
|
|
968
|
+
*
|
|
969
|
+
* @since 4.0.0
|
|
970
|
+
* @category combinators
|
|
971
|
+
*/
|
|
972
|
+
<const GlobalFlags extends ReadonlyArray<GlobalFlag.GlobalFlag<any>>>(globalFlags: GlobalFlags): <Name extends string, Input, E, R>(
|
|
973
|
+
self: Command<Name, Input, E, R>
|
|
974
|
+
) => Command<Name, Input, E, Exclude<R, ExtractGlobalFlagContext<GlobalFlags>>>
|
|
975
|
+
/**
|
|
976
|
+
* Declares global flags for a command scope.
|
|
977
|
+
*
|
|
978
|
+
* Declared global flags apply to the command and all of its descendants.
|
|
979
|
+
*
|
|
980
|
+
* @since 4.0.0
|
|
981
|
+
* @category combinators
|
|
982
|
+
*/
|
|
983
|
+
<Name extends string, Input, E, R, const GlobalFlags extends ReadonlyArray<GlobalFlag.GlobalFlag<any>>>(self: Command<Name, Input, E, R>, globalFlags: GlobalFlags): Command<Name, Input, E, Exclude<R, ExtractGlobalFlagContext<GlobalFlags>>>
|
|
984
|
+
} = dual(
|
|
985
|
+
2,
|
|
986
|
+
<Name extends string, Input, E, R, const GlobalFlags extends ReadonlyArray<GlobalFlag.GlobalFlag<any>>>(
|
|
987
|
+
self: Command<Name, Input, E, R>,
|
|
988
|
+
globalFlags: GlobalFlags
|
|
989
|
+
): Command<Name, Input, E, Exclude<R, ExtractGlobalFlagContext<GlobalFlags>>> => {
|
|
990
|
+
const impl = toImpl(self)
|
|
991
|
+
const next = Array.from(new Set([...impl.globalFlags, ...globalFlags]))
|
|
992
|
+
return makeCommand({ ...impl, globalFlags: next })
|
|
993
|
+
}
|
|
994
|
+
)
|
|
995
|
+
|
|
953
996
|
// Type extractors for subcommand arrays - T[number] gives union of all elements
|
|
997
|
+
type ExtractGlobalFlagContext<T extends ReadonlyArray<GlobalFlag.GlobalFlag<any>>> = T[number] extends
|
|
998
|
+
GlobalFlag.Setting<infer Id, any> ? GlobalFlag.Setting.Identifier<Id> : never
|
|
954
999
|
type ExtractSubcommand<T> = T extends Command<any, any, any, any> ? T
|
|
955
1000
|
: T extends Command.SubcommandGroup<infer Commands> ? Commands[number]
|
|
956
1001
|
: never
|
|
@@ -1534,6 +1579,45 @@ export const provideEffectDiscard: {
|
|
|
1534
1579
|
/* Execution */
|
|
1535
1580
|
/* ========================================================================== */
|
|
1536
1581
|
|
|
1582
|
+
const getOutOfScopeGlobalFlagErrors = (
|
|
1583
|
+
allFlags: ReadonlyArray<GlobalFlag.GlobalFlag<any>>,
|
|
1584
|
+
activeFlags: ReadonlyArray<GlobalFlag.GlobalFlag<any>>,
|
|
1585
|
+
flagMap: Record<string, ReadonlyArray<string>>,
|
|
1586
|
+
commandPath: ReadonlyArray<string>
|
|
1587
|
+
): ReadonlyArray<CliError.CliError> => {
|
|
1588
|
+
const activeSet = new Set(activeFlags)
|
|
1589
|
+
const errors: Array<CliError.CliError> = []
|
|
1590
|
+
const seen = new Set<string>()
|
|
1591
|
+
|
|
1592
|
+
for (const flag of allFlags) {
|
|
1593
|
+
if (activeSet.has(flag)) {
|
|
1594
|
+
continue
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
const singles = Param.extractSingleParams(flag.flag)
|
|
1598
|
+
for (const single of singles) {
|
|
1599
|
+
const entries = flagMap[single.name]
|
|
1600
|
+
if (!entries || entries.length === 0) {
|
|
1601
|
+
continue
|
|
1602
|
+
}
|
|
1603
|
+
const option = `--${single.name}`
|
|
1604
|
+
if (seen.has(option)) {
|
|
1605
|
+
continue
|
|
1606
|
+
}
|
|
1607
|
+
seen.add(option)
|
|
1608
|
+
errors.push(
|
|
1609
|
+
new CliError.UnrecognizedOption({
|
|
1610
|
+
option,
|
|
1611
|
+
suggestions: [],
|
|
1612
|
+
command: commandPath
|
|
1613
|
+
})
|
|
1614
|
+
)
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
return errors
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1537
1621
|
const showHelp = <Name extends string, Input, E, R>(
|
|
1538
1622
|
command: Command<Name, Input, E, R>,
|
|
1539
1623
|
commandPath: ReadonlyArray<string>,
|
|
@@ -1541,7 +1625,7 @@ const showHelp = <Name extends string, Input, E, R>(
|
|
|
1541
1625
|
): Effect.Effect<void, never, Environment> =>
|
|
1542
1626
|
Effect.gen(function*() {
|
|
1543
1627
|
const formatter = yield* CliOutput.Formatter
|
|
1544
|
-
const helpDoc = yield* getHelpForCommandPath(command, commandPath, GlobalFlag.
|
|
1628
|
+
const helpDoc = yield* getHelpForCommandPath(command, commandPath, GlobalFlag.BuiltIns)
|
|
1545
1629
|
yield* Console.log(formatter.formatHelpDoc(helpDoc))
|
|
1546
1630
|
if (errors && errors.length > 0) {
|
|
1547
1631
|
yield* Console.error(formatter.formatErrors(errors))
|
|
@@ -1698,11 +1782,11 @@ export const runWith = <const Name extends string, Input, E, R>(
|
|
|
1698
1782
|
function*(args: ReadonlyArray<string>) {
|
|
1699
1783
|
const { tokens, trailingOperands } = Lexer.lex(args)
|
|
1700
1784
|
|
|
1701
|
-
// 1.
|
|
1702
|
-
const
|
|
1785
|
+
// 1. Collect known global flags from the command tree
|
|
1786
|
+
const allFlags = getGlobalFlagsForCommandTree(command, GlobalFlag.BuiltIns)
|
|
1703
1787
|
|
|
1704
1788
|
// 2. Extract global flag tokens
|
|
1705
|
-
const allFlagParams =
|
|
1789
|
+
const allFlagParams = allFlags.flatMap((f) => Param.extractSingleParams(f.flag))
|
|
1706
1790
|
const globalRegistry = Parser.createFlagRegistry(allFlagParams.filter(Param.isFlagParam))
|
|
1707
1791
|
const { flagMap, remainder } = Parser.consumeKnownFlags(tokens, globalRegistry)
|
|
1708
1792
|
const emptyArgs: Param.ParsedArgs = { flags: flagMap, arguments: [] }
|
|
@@ -1711,9 +1795,17 @@ export const runWith = <const Name extends string, Input, E, R>(
|
|
|
1711
1795
|
const parsedArgs = yield* Parser.parseArgs({ tokens: remainder, trailingOperands }, command)
|
|
1712
1796
|
const commandPath = [command.name, ...Parser.getCommandPath(parsedArgs)] as const
|
|
1713
1797
|
const handlerCtx: GlobalFlag.HandlerContext = { command, commandPath, version: config.version }
|
|
1798
|
+
const activeFlags = getGlobalFlagsForCommandPath(command, commandPath, GlobalFlag.BuiltIns)
|
|
1714
1799
|
|
|
1715
|
-
// 4.
|
|
1716
|
-
|
|
1800
|
+
// 4. Reject globals that were passed outside the active command scope
|
|
1801
|
+
const outOfScopeErrors = getOutOfScopeGlobalFlagErrors(allFlags, activeFlags, flagMap, commandPath)
|
|
1802
|
+
if (outOfScopeErrors.length > 0) {
|
|
1803
|
+
const parseErrors = parsedArgs.errors ?? []
|
|
1804
|
+
return yield* showHelp(command, commandPath, [...outOfScopeErrors, ...parseErrors])
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
// 5. Process action flags — first present action wins, then exit
|
|
1808
|
+
for (const flag of activeFlags) {
|
|
1717
1809
|
if (flag._tag !== "Action") continue
|
|
1718
1810
|
const singles = Param.extractSingleParams(flag.flag)
|
|
1719
1811
|
const hasEntry = singles.some((s) => {
|
|
@@ -1726,7 +1818,7 @@ export const runWith = <const Name extends string, Input, E, R>(
|
|
|
1726
1818
|
return
|
|
1727
1819
|
}
|
|
1728
1820
|
|
|
1729
|
-
//
|
|
1821
|
+
// 6. Handle parsing errors
|
|
1730
1822
|
if (parsedArgs.errors && parsedArgs.errors.length > 0) {
|
|
1731
1823
|
return yield* showHelp(command, commandPath, parsedArgs.errors)
|
|
1732
1824
|
}
|
|
@@ -1735,29 +1827,25 @@ export const runWith = <const Name extends string, Input, E, R>(
|
|
|
1735
1827
|
return yield* showHelp(command, commandPath, [parseResult.failure])
|
|
1736
1828
|
}
|
|
1737
1829
|
|
|
1738
|
-
//
|
|
1739
|
-
let
|
|
1740
|
-
for (const flag of
|
|
1830
|
+
// 7. Provide setting values
|
|
1831
|
+
let program = commandImpl.handle(parseResult.success, [command.name])
|
|
1832
|
+
for (const flag of activeFlags) {
|
|
1741
1833
|
if (flag._tag !== "Setting") continue
|
|
1742
1834
|
const [, value] = yield* flag.flag.parse(emptyArgs)
|
|
1743
|
-
|
|
1835
|
+
program = Effect.provideService(program, flag, value)
|
|
1744
1836
|
}
|
|
1745
1837
|
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
})
|
|
1755
|
-
)
|
|
1756
|
-
}
|
|
1838
|
+
const [, logLevel] = yield* GlobalFlag.LogLevel.flag.parse(emptyArgs)
|
|
1839
|
+
program = Effect.provideService(program, GlobalFlag.LogLevel, logLevel)
|
|
1840
|
+
|
|
1841
|
+
// 8. Apply built-in setting behavior
|
|
1842
|
+
const services = Option.match(logLevel, {
|
|
1843
|
+
onNone: () => ServiceMap.empty(),
|
|
1844
|
+
onSome: (level) => ServiceMap.make(References.MinimumLogLevel, level)
|
|
1845
|
+
})
|
|
1757
1846
|
|
|
1758
|
-
//
|
|
1759
|
-
|
|
1760
|
-
yield* Effect.provide(program, contextLayer)
|
|
1847
|
+
// 9. Run command handler with composed context
|
|
1848
|
+
yield* Effect.provideServices(program, services)
|
|
1761
1849
|
},
|
|
1762
1850
|
Effect.catchIf(
|
|
1763
1851
|
((error: any) =>
|