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
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Console from "../../Console.ts"
|
|
6
6
|
import * as Effect from "../../Effect.ts"
|
|
7
|
-
import { dual } from "../../Function.ts"
|
|
8
7
|
import type { LogLevel as LogLevelType } from "../../LogLevel.ts"
|
|
9
8
|
import * as Option from "../../Option.ts"
|
|
10
9
|
import * as ServiceMap from "../../ServiceMap.ts"
|
|
@@ -49,18 +48,30 @@ export interface Action<A> {
|
|
|
49
48
|
* @since 4.0.0
|
|
50
49
|
* @category models
|
|
51
50
|
*/
|
|
52
|
-
export interface Setting<A> extends ServiceMap.
|
|
51
|
+
export interface Setting<Id extends string, A> extends ServiceMap.Service<Setting.Identifier<Id>, A> {
|
|
53
52
|
readonly _tag: "Setting"
|
|
53
|
+
readonly id: Id
|
|
54
54
|
readonly flag: Flag.Flag<A>
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* @since 4.0.0
|
|
59
|
+
*/
|
|
60
|
+
export declare namespace Setting {
|
|
61
|
+
/**
|
|
62
|
+
* @since 4.0.0
|
|
63
|
+
* @category models
|
|
64
|
+
*/
|
|
65
|
+
export type Identifier<Id extends string> = `effect/unstable/cli/GlobalFlag/${Id}`
|
|
66
|
+
}
|
|
67
|
+
|
|
57
68
|
/**
|
|
58
69
|
* Global flag discriminated union.
|
|
59
70
|
*
|
|
60
71
|
* @since 4.0.0
|
|
61
72
|
* @category models
|
|
62
73
|
*/
|
|
63
|
-
export type GlobalFlag<A> = Action<A> | Setting<A>
|
|
74
|
+
export type GlobalFlag<A> = Action<A> | Setting<any, A>
|
|
64
75
|
|
|
65
76
|
/* ========================================================================== */
|
|
66
77
|
/* Constructors */
|
|
@@ -90,17 +101,19 @@ export const action = <A>(options: {
|
|
|
90
101
|
* @since 4.0.0
|
|
91
102
|
* @category constructors
|
|
92
103
|
*/
|
|
93
|
-
export const setting = <
|
|
104
|
+
export const setting = <const Id extends string>(
|
|
105
|
+
id: Id
|
|
106
|
+
) =>
|
|
107
|
+
<A>(options: {
|
|
94
108
|
readonly flag: Flag.Flag<A>
|
|
95
|
-
|
|
96
|
-
}): Setting<A> => {
|
|
109
|
+
}): Setting<Id, A> => {
|
|
97
110
|
settingIdCounter += 1
|
|
98
|
-
const ref = ServiceMap.
|
|
99
|
-
`effect/cli/GlobalFlag
|
|
100
|
-
{ defaultValue: options.defaultValue }
|
|
111
|
+
const ref = ServiceMap.Service<Setting.Identifier<Id>, A>(
|
|
112
|
+
`effect/unstable/cli/GlobalFlag/${id}/${settingIdCounter}`
|
|
101
113
|
)
|
|
102
114
|
return Object.assign(ref, {
|
|
103
115
|
_tag: "Setting" as const,
|
|
116
|
+
id,
|
|
104
117
|
flag: options.flag
|
|
105
118
|
})
|
|
106
119
|
}
|
|
@@ -130,7 +143,7 @@ export const Help: Action<boolean> = action({
|
|
|
130
143
|
run: (_, { command, commandPath }) =>
|
|
131
144
|
Effect.gen(function*() {
|
|
132
145
|
const formatter = yield* CliOutput.Formatter
|
|
133
|
-
const helpDoc = yield* HelpInternal.getHelpForCommandPath(command, commandPath,
|
|
146
|
+
const helpDoc = yield* HelpInternal.getHelpForCommandPath(command, commandPath, BuiltIns)
|
|
134
147
|
yield* Console.log(formatter.formatHelpDoc(helpDoc))
|
|
135
148
|
})
|
|
136
149
|
})
|
|
@@ -184,7 +197,7 @@ export const Completions: Action<Option.Option<"bash" | "zsh" | "fish">> = actio
|
|
|
184
197
|
* @since 4.0.0
|
|
185
198
|
* @category references
|
|
186
199
|
*/
|
|
187
|
-
export const LogLevel: Setting<Option.Option<LogLevelType>> = setting({
|
|
200
|
+
export const LogLevel: Setting<"log-level", Option.Option<LogLevelType>> = setting("log-level")({
|
|
188
201
|
flag: Flag.choiceWithValue(
|
|
189
202
|
"log-level",
|
|
190
203
|
[
|
|
@@ -201,121 +214,30 @@ export const LogLevel: Setting<Option.Option<LogLevelType>> = setting({
|
|
|
201
214
|
).pipe(
|
|
202
215
|
Flag.optional,
|
|
203
216
|
Flag.withDescription("Sets the minimum log level")
|
|
204
|
-
)
|
|
205
|
-
defaultValue: () => Option.none()
|
|
217
|
+
)
|
|
206
218
|
})
|
|
207
219
|
|
|
208
220
|
/* ========================================================================== */
|
|
209
|
-
/*
|
|
221
|
+
/* References */
|
|
210
222
|
/* ========================================================================== */
|
|
211
223
|
|
|
212
224
|
/**
|
|
213
|
-
*
|
|
214
|
-
* The parser iterates this set to know which flags to extract.
|
|
225
|
+
* Built-in global flags in default precedence order.
|
|
215
226
|
*
|
|
216
227
|
* @since 4.0.0
|
|
217
228
|
* @category references
|
|
218
229
|
*/
|
|
219
|
-
export const
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
Version,
|
|
226
|
-
Completions,
|
|
227
|
-
LogLevel
|
|
228
|
-
])
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
/* ========================================================================== */
|
|
232
|
-
/* Public API */
|
|
233
|
-
/* ========================================================================== */
|
|
230
|
+
export const BuiltIns: ReadonlyArray<GlobalFlag<any>> = [
|
|
231
|
+
Help,
|
|
232
|
+
Version,
|
|
233
|
+
Completions,
|
|
234
|
+
LogLevel
|
|
235
|
+
]
|
|
234
236
|
|
|
235
237
|
/**
|
|
236
|
-
*
|
|
238
|
+
* Built-in setting context identifiers.
|
|
237
239
|
*
|
|
238
240
|
* @since 4.0.0
|
|
239
|
-
* @category
|
|
240
|
-
*/
|
|
241
|
-
export const add: {
|
|
242
|
-
/* ========================================================================== */
|
|
243
|
-
/* Public API */
|
|
244
|
-
/* ========================================================================== */
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Adds a global flag to the registry.
|
|
248
|
-
*
|
|
249
|
-
* @since 4.0.0
|
|
250
|
-
* @category modifiers
|
|
251
|
-
*/
|
|
252
|
-
<A>(flag: GlobalFlag<A>): <B, E, R>(
|
|
253
|
-
self: Effect.Effect<B, E, R>
|
|
254
|
-
) => Effect.Effect<B, E, R>
|
|
255
|
-
/* ========================================================================== */
|
|
256
|
-
/* Public API */
|
|
257
|
-
/* ========================================================================== */
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Adds a global flag to the registry.
|
|
261
|
-
*
|
|
262
|
-
* @since 4.0.0
|
|
263
|
-
* @category modifiers
|
|
264
|
-
*/
|
|
265
|
-
<B, E, R, A>(self: Effect.Effect<B, E, R>, flag: GlobalFlag<A>): Effect.Effect<B, E, R>
|
|
266
|
-
} = dual(
|
|
267
|
-
2,
|
|
268
|
-
Effect.fnUntraced(function*<B, E, R, A>(
|
|
269
|
-
self: Effect.Effect<B, E, R>,
|
|
270
|
-
flag: GlobalFlag<A>
|
|
271
|
-
) {
|
|
272
|
-
const currentRegistry = yield* Registry
|
|
273
|
-
const nextRegistry = new Set([...currentRegistry, flag])
|
|
274
|
-
return yield* Effect.provideService(self, Registry, nextRegistry)
|
|
275
|
-
})
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Removes a global flag by its reference.
|
|
280
|
-
*
|
|
281
|
-
* @since 4.0.0
|
|
282
|
-
* @category modifiers
|
|
283
|
-
*/
|
|
284
|
-
export const remove: {
|
|
285
|
-
/**
|
|
286
|
-
* Removes a global flag by its reference.
|
|
287
|
-
*
|
|
288
|
-
* @since 4.0.0
|
|
289
|
-
* @category modifiers
|
|
290
|
-
*/
|
|
291
|
-
<A>(flag: GlobalFlag<A>): <B, E, R>(
|
|
292
|
-
self: Effect.Effect<B, E, R>
|
|
293
|
-
) => Effect.Effect<B, E, R>
|
|
294
|
-
/**
|
|
295
|
-
* Removes a global flag by its reference.
|
|
296
|
-
*
|
|
297
|
-
* @since 4.0.0
|
|
298
|
-
* @category modifiers
|
|
299
|
-
*/
|
|
300
|
-
<B, E, R, A>(self: Effect.Effect<B, E, R>, flag: GlobalFlag<A>): Effect.Effect<B, E, R>
|
|
301
|
-
} = dual(
|
|
302
|
-
2,
|
|
303
|
-
Effect.fnUntraced(function*<B, E, R, A>(
|
|
304
|
-
self: Effect.Effect<B, E, R>,
|
|
305
|
-
flag: GlobalFlag<A>
|
|
306
|
-
) {
|
|
307
|
-
const currentRegistry = yield* Registry
|
|
308
|
-
const nextRegistry = new Set(currentRegistry)
|
|
309
|
-
nextRegistry.delete(flag)
|
|
310
|
-
return yield* Effect.provideService(self, Registry, nextRegistry)
|
|
311
|
-
})
|
|
312
|
-
)
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* Removes all global flags (built-in and user-defined).
|
|
316
|
-
*
|
|
317
|
-
* @since 4.0.0
|
|
318
|
-
* @category modifiers
|
|
241
|
+
* @category models
|
|
319
242
|
*/
|
|
320
|
-
export
|
|
321
|
-
Effect.provideService(self, Registry, new Set())
|
|
243
|
+
export type BuiltInSettingContext = Setting.Identifier<"log-level">
|
|
@@ -12,6 +12,7 @@ import { pipeArguments } from "../../../Pipeable.ts"
|
|
|
12
12
|
import * as Predicate from "../../../Predicate.ts"
|
|
13
13
|
import * as ServiceMap from "../../../ServiceMap.ts"
|
|
14
14
|
import * as CliError from "../CliError.ts"
|
|
15
|
+
import type * as GlobalFlag from "../GlobalFlag.ts"
|
|
15
16
|
import type { ArgDoc, ExampleDoc, FlagDoc, HelpDoc, SubcommandGroupDoc } from "../HelpDoc.ts"
|
|
16
17
|
import * as Param from "../Param.ts"
|
|
17
18
|
import * as Primitive from "../Primitive.ts"
|
|
@@ -36,6 +37,7 @@ export interface CommandInternal<Name extends string, Input, E, R> extends Comma
|
|
|
36
37
|
readonly config: ConfigInternal
|
|
37
38
|
readonly service: ServiceMap.Service<CommandContext<Name>, Input>
|
|
38
39
|
readonly annotations: ServiceMap.ServiceMap<never>
|
|
40
|
+
readonly globalFlags: ReadonlyArray<GlobalFlag.GlobalFlag<any>>
|
|
39
41
|
readonly parse: (input: ParsedTokens) => Effect.Effect<Input, CliError.CliError, Environment>
|
|
40
42
|
readonly handle: (
|
|
41
43
|
input: Input,
|
|
@@ -88,6 +90,7 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
88
90
|
readonly config: ConfigInternal
|
|
89
91
|
readonly service?: ServiceMap.Service<CommandContext<Name>, Input> | undefined
|
|
90
92
|
readonly annotations?: ServiceMap.ServiceMap<never> | undefined
|
|
93
|
+
readonly globalFlags?: ReadonlyArray<GlobalFlag.GlobalFlag<any>> | undefined
|
|
91
94
|
readonly description?: string | undefined
|
|
92
95
|
readonly shortDescription?: string | undefined
|
|
93
96
|
readonly alias?: string | undefined
|
|
@@ -101,6 +104,7 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
101
104
|
const service = options.service ?? ServiceMap.Service<CommandContext<Name>, Input>(`${TypeId}/${options.name}`)
|
|
102
105
|
const config = options.config
|
|
103
106
|
const annotations = options.annotations ?? ServiceMap.empty()
|
|
107
|
+
const globalFlags = options.globalFlags ?? []
|
|
104
108
|
const subcommands = options.subcommands ?? []
|
|
105
109
|
|
|
106
110
|
const handle = (
|
|
@@ -191,6 +195,7 @@ export const makeCommand = <const Name extends string, Input, E, R>(options: {
|
|
|
191
195
|
name: options.name,
|
|
192
196
|
examples: options.examples ?? [],
|
|
193
197
|
annotations,
|
|
198
|
+
globalFlags,
|
|
194
199
|
subcommands,
|
|
195
200
|
config,
|
|
196
201
|
service,
|
|
@@ -6,46 +6,127 @@
|
|
|
6
6
|
* Extracted from command.ts to avoid circular dependencies.
|
|
7
7
|
*/
|
|
8
8
|
import * as Effect from "../../../Effect.ts"
|
|
9
|
-
import type * as ServiceMap from "../../../ServiceMap.ts"
|
|
10
9
|
import type { Command } from "../Command.ts"
|
|
11
|
-
import type
|
|
10
|
+
import type * as GlobalFlag from "../GlobalFlag.ts"
|
|
12
11
|
import type { FlagDoc, HelpDoc } from "../HelpDoc.ts"
|
|
13
12
|
import * as Param from "../Param.ts"
|
|
14
13
|
import * as Primitive from "../Primitive.ts"
|
|
15
14
|
import { toImpl } from "./command.ts"
|
|
16
15
|
|
|
16
|
+
const dedupeGlobalFlags = (
|
|
17
|
+
flags: ReadonlyArray<GlobalFlag.GlobalFlag<any>>
|
|
18
|
+
): ReadonlyArray<GlobalFlag.GlobalFlag<any>> => {
|
|
19
|
+
const seen = new Set<GlobalFlag.GlobalFlag<any>>()
|
|
20
|
+
const deduped: Array<GlobalFlag.GlobalFlag<any>> = []
|
|
21
|
+
for (const flag of flags) {
|
|
22
|
+
if (seen.has(flag)) {
|
|
23
|
+
continue
|
|
24
|
+
}
|
|
25
|
+
seen.add(flag)
|
|
26
|
+
deduped.push(flag)
|
|
27
|
+
}
|
|
28
|
+
return deduped
|
|
29
|
+
}
|
|
30
|
+
|
|
17
31
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* Reads global flags from the registry and includes them in the help doc.
|
|
32
|
+
* Returns the resolved command lineage for the provided path.
|
|
33
|
+
* Includes the root command as the first element.
|
|
21
34
|
*/
|
|
22
|
-
export const
|
|
35
|
+
export const getCommandsForCommandPath = <Name extends string, Input, E, R>(
|
|
23
36
|
command: Command<Name, Input, E, R>,
|
|
24
|
-
commandPath: ReadonlyArray<string
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
let currentCommand: Command.Any = command
|
|
37
|
+
commandPath: ReadonlyArray<string>
|
|
38
|
+
): ReadonlyArray<Command.Any> => {
|
|
39
|
+
const commands: Array<Command.Any> = [command]
|
|
40
|
+
let currentCommand: Command.Any = command
|
|
29
41
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
42
|
+
for (let i = 1; i < commandPath.length; i++) {
|
|
43
|
+
const subcommandName = commandPath[i]
|
|
44
|
+
let subcommand: Command.Any | undefined = undefined
|
|
33
45
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
46
|
+
for (const group of currentCommand.subcommands) {
|
|
47
|
+
subcommand = group.commands.find((sub) => sub.name === subcommandName)
|
|
48
|
+
if (subcommand) {
|
|
49
|
+
break
|
|
39
50
|
}
|
|
51
|
+
}
|
|
40
52
|
|
|
41
|
-
|
|
42
|
-
|
|
53
|
+
if (!subcommand) {
|
|
54
|
+
break
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
commands.push(subcommand)
|
|
58
|
+
currentCommand = subcommand
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return commands
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Returns active global flags for a command path.
|
|
66
|
+
* Built-ins are prepended and declarations are collected root -> leaf.
|
|
67
|
+
*/
|
|
68
|
+
export const getGlobalFlagsForCommandPath = <Name extends string, Input, E, R>(
|
|
69
|
+
command: Command<Name, Input, E, R>,
|
|
70
|
+
commandPath: ReadonlyArray<string>,
|
|
71
|
+
builtIns: ReadonlyArray<GlobalFlag.GlobalFlag<any>>
|
|
72
|
+
): ReadonlyArray<GlobalFlag.GlobalFlag<any>> => {
|
|
73
|
+
const commands = getCommandsForCommandPath(command, commandPath)
|
|
74
|
+
const declared = commands.flatMap((current) => toImpl(current).globalFlags)
|
|
75
|
+
return dedupeGlobalFlags([
|
|
76
|
+
...builtIns,
|
|
77
|
+
...declared
|
|
78
|
+
])
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const collectDeclaredGlobalFlags = (command: Command.Any): ReadonlyArray<GlobalFlag.GlobalFlag<any>> => {
|
|
82
|
+
const collected: Array<GlobalFlag.GlobalFlag<any>> = []
|
|
83
|
+
|
|
84
|
+
const visit = (current: Command.Any): void => {
|
|
85
|
+
const impl = toImpl(current)
|
|
86
|
+
for (const flag of impl.globalFlags) {
|
|
87
|
+
collected.push(flag)
|
|
88
|
+
}
|
|
89
|
+
for (const group of current.subcommands) {
|
|
90
|
+
for (const subcommand of group.commands) {
|
|
91
|
+
visit(subcommand)
|
|
43
92
|
}
|
|
44
93
|
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
visit(command)
|
|
97
|
+
return dedupeGlobalFlags(collected)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Returns all global flags declared in a command tree.
|
|
102
|
+
* Built-ins are prepended and command declarations are deduplicated by identity.
|
|
103
|
+
*/
|
|
104
|
+
export const getGlobalFlagsForCommandTree = <Name extends string, Input, E, R>(
|
|
105
|
+
command: Command<Name, Input, E, R>,
|
|
106
|
+
builtIns: ReadonlyArray<GlobalFlag.GlobalFlag<any>>
|
|
107
|
+
): ReadonlyArray<GlobalFlag.GlobalFlag<any>> =>
|
|
108
|
+
dedupeGlobalFlags([
|
|
109
|
+
...builtIns,
|
|
110
|
+
...collectDeclaredGlobalFlags(command)
|
|
111
|
+
])
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Helper function to get help documentation for a specific command path.
|
|
115
|
+
* Navigates through the command hierarchy to find the right command.
|
|
116
|
+
* Reads active global flags for the path and includes them in the help doc.
|
|
117
|
+
*/
|
|
118
|
+
export const getHelpForCommandPath = <Name extends string, Input, E, R>(
|
|
119
|
+
command: Command<Name, Input, E, R>,
|
|
120
|
+
commandPath: ReadonlyArray<string>,
|
|
121
|
+
builtIns: ReadonlyArray<GlobalFlag.GlobalFlag<any>>
|
|
122
|
+
): Effect.Effect<HelpDoc, never, never> =>
|
|
123
|
+
Effect.gen(function*() {
|
|
124
|
+
const commands = getCommandsForCommandPath(command, commandPath)
|
|
125
|
+
const currentCommand = commands.length > 0 ? commands[commands.length - 1] : command
|
|
45
126
|
|
|
46
127
|
const baseDoc = toImpl(currentCommand).buildHelpDoc(commandPath)
|
|
47
128
|
|
|
48
|
-
const flags =
|
|
129
|
+
const flags = getGlobalFlagsForCommandPath(command, commandPath, builtIns)
|
|
49
130
|
const globalFlagDocs: Array<FlagDoc> = []
|
|
50
131
|
for (const flag of flags) {
|
|
51
132
|
const singles = Param.extractSingleParams(flag.flag)
|
|
@@ -20,7 +20,7 @@ import * as Transformation from "../../SchemaTransformation.ts"
|
|
|
20
20
|
import type * as Scope from "../../Scope.ts"
|
|
21
21
|
import * as ServiceMap from "../../ServiceMap.ts"
|
|
22
22
|
import * as Stream from "../../Stream.ts"
|
|
23
|
-
import type { Covariant } from "../../Types.ts"
|
|
23
|
+
import type { Covariant, NoInfer } from "../../Types.ts"
|
|
24
24
|
import * as UndefinedOr from "../../UndefinedOr.ts"
|
|
25
25
|
import type { Cookie } from "../http/Cookies.ts"
|
|
26
26
|
import type * as Etag from "../http/Etag.ts"
|
|
@@ -63,7 +63,6 @@ export const layer = <Id extends string, Groups extends HttpApiGroup.Any>(
|
|
|
63
63
|
| HttpPlatform
|
|
64
64
|
| Path
|
|
65
65
|
| HttpApiGroup.ToService<Id, Groups>
|
|
66
|
-
| HttpApiGroup.ErrorServicesEncode<Groups>
|
|
67
66
|
> =>
|
|
68
67
|
HttpRouter.use(Effect.fnUntraced(function*(router) {
|
|
69
68
|
const services = yield* Effect.services<
|
|
@@ -168,7 +167,7 @@ export interface Handlers<
|
|
|
168
167
|
| R
|
|
169
168
|
| HttpApiEndpoint.MiddlewareWithName<Endpoints, Name>
|
|
170
169
|
| HttpApiEndpoint.MiddlewareServicesWithName<Endpoints, Name>
|
|
171
|
-
| HttpApiEndpoint.
|
|
170
|
+
| HttpApiEndpoint.ExcludeProvidedWithName<
|
|
172
171
|
Endpoints,
|
|
173
172
|
Name,
|
|
174
173
|
R1 | HttpApiEndpoint.ServerServicesWithName<Endpoints, Name>
|
|
@@ -188,7 +187,7 @@ export interface Handlers<
|
|
|
188
187
|
| R
|
|
189
188
|
| HttpApiEndpoint.MiddlewareWithName<Endpoints, Name>
|
|
190
189
|
| HttpApiEndpoint.MiddlewareServicesWithName<Endpoints, Name>
|
|
191
|
-
| HttpApiEndpoint.
|
|
190
|
+
| HttpApiEndpoint.ExcludeProvidedWithName<
|
|
192
191
|
Endpoints,
|
|
193
192
|
Name,
|
|
194
193
|
R1 | HttpApiEndpoint.ServerServicesWithName<Endpoints, Name>
|
|
@@ -284,6 +283,54 @@ export declare namespace Handlers {
|
|
|
284
283
|
never
|
|
285
284
|
}
|
|
286
285
|
|
|
286
|
+
/**
|
|
287
|
+
* @since 4.0.0
|
|
288
|
+
* @category handlers
|
|
289
|
+
*/
|
|
290
|
+
export const endpoint = <
|
|
291
|
+
ApiId extends string,
|
|
292
|
+
Groups extends HttpApiGroup.Any,
|
|
293
|
+
const GroupName extends HttpApiGroup.Name<Groups>,
|
|
294
|
+
const EndpointName extends HttpApiEndpoint.Name<HttpApiGroup.Endpoints<HttpApiGroup.WithName<Groups, GroupName>>>,
|
|
295
|
+
R,
|
|
296
|
+
Group extends HttpApiGroup.Any = HttpApiGroup.WithName<Groups, GroupName>,
|
|
297
|
+
Endpoint extends HttpApiEndpoint.Any = HttpApiEndpoint.WithName<HttpApiGroup.Endpoints<Group>, EndpointName>
|
|
298
|
+
>(
|
|
299
|
+
api: HttpApi.HttpApi<ApiId, Groups>,
|
|
300
|
+
groupName: GroupName,
|
|
301
|
+
endpointName: EndpointName,
|
|
302
|
+
handler: NoInfer<
|
|
303
|
+
HttpApiEndpoint.HandlerWithName<
|
|
304
|
+
HttpApiGroup.Endpoints<HttpApiGroup.WithName<Groups, GroupName>>,
|
|
305
|
+
EndpointName,
|
|
306
|
+
never,
|
|
307
|
+
R
|
|
308
|
+
>
|
|
309
|
+
>
|
|
310
|
+
): Effect.Effect<
|
|
311
|
+
Effect.Effect<
|
|
312
|
+
HttpServerResponse,
|
|
313
|
+
never,
|
|
314
|
+
| HttpServerRequest
|
|
315
|
+
| HttpRouter.RouteContext
|
|
316
|
+
| Request.ParsedSearchParams
|
|
317
|
+
| Exclude<R, HttpApiEndpoint.MiddlewareProvides<Endpoint>>
|
|
318
|
+
>,
|
|
319
|
+
never,
|
|
320
|
+
| HttpApiEndpoint.ServerServices<Endpoint>
|
|
321
|
+
| HttpApiEndpoint.Middleware<Endpoint>
|
|
322
|
+
| HttpApiEndpoint.MiddlewareServices<Endpoint>
|
|
323
|
+
| Etag.Generator
|
|
324
|
+
| FileSystem
|
|
325
|
+
| HttpPlatform
|
|
326
|
+
| Path
|
|
327
|
+
> =>
|
|
328
|
+
Effect.servicesWith((services: ServiceMap.ServiceMap<any>) => {
|
|
329
|
+
const group = api.groups[groupName] as unknown as HttpApiGroup.AnyWithProps
|
|
330
|
+
const endpoint = group.endpoints[endpointName] as unknown as HttpApiEndpoint.AnyWithProps
|
|
331
|
+
return Effect.succeed(handlerToHttpEffect(group, endpoint, services, handler as any, false))
|
|
332
|
+
})
|
|
333
|
+
|
|
287
334
|
/**
|
|
288
335
|
* @since 4.0.0
|
|
289
336
|
* @category security
|
|
@@ -497,22 +544,23 @@ function decodePayload(
|
|
|
497
544
|
}
|
|
498
545
|
}
|
|
499
546
|
|
|
500
|
-
function
|
|
547
|
+
function handlerToHttpEffect(
|
|
501
548
|
group: HttpApiGroup.AnyWithProps,
|
|
502
|
-
|
|
503
|
-
services: ServiceMap.ServiceMap<any
|
|
504
|
-
|
|
505
|
-
|
|
549
|
+
endpoint: HttpApiEndpoint.AnyWithProps,
|
|
550
|
+
services: ServiceMap.ServiceMap<any>,
|
|
551
|
+
handler: HttpApiEndpoint.Handler<any, any, any>,
|
|
552
|
+
isRaw: boolean
|
|
553
|
+
) {
|
|
506
554
|
const encodeSuccess = Schema.encodeUnknownEffect(makeSuccessSchema(endpoint))
|
|
507
555
|
const encodeError = Schema.encodeUnknownEffect(makeErrorSchema(endpoint))
|
|
508
556
|
const decodeParams = UndefinedOr.map(endpoint.params, Schema.decodeUnknownEffect)
|
|
509
557
|
const decodeHeaders = UndefinedOr.map(endpoint.headers, Schema.decodeUnknownEffect)
|
|
510
558
|
const decodeQuery = UndefinedOr.map(endpoint.query, Schema.decodeUnknownEffect)
|
|
511
559
|
|
|
512
|
-
const shouldParsePayload = endpoint.payload.size > 0 && !
|
|
560
|
+
const shouldParsePayload = endpoint.payload.size > 0 && !isRaw
|
|
513
561
|
const payloadBy = shouldParsePayload ? buildPayloadDecoders(endpoint.payload) : undefined
|
|
514
562
|
|
|
515
|
-
|
|
563
|
+
return applyMiddleware(
|
|
516
564
|
group,
|
|
517
565
|
endpoint,
|
|
518
566
|
services,
|
|
@@ -545,7 +593,7 @@ function handlerToRoute(
|
|
|
545
593
|
request.payload = yield* result
|
|
546
594
|
}
|
|
547
595
|
}
|
|
548
|
-
const response = yield* handler
|
|
596
|
+
const response = yield* handler(request)
|
|
549
597
|
return Response.isHttpServerResponse(response) ? response : yield* encodeSuccess(response)
|
|
550
598
|
})
|
|
551
599
|
).pipe(
|
|
@@ -558,11 +606,18 @@ function handlerToRoute(
|
|
|
558
606
|
}),
|
|
559
607
|
Effect.provideServices(services)
|
|
560
608
|
)
|
|
609
|
+
}
|
|
561
610
|
|
|
611
|
+
function handlerToRoute(
|
|
612
|
+
group: HttpApiGroup.AnyWithProps,
|
|
613
|
+
handler: Handlers.Item<any>,
|
|
614
|
+
services: ServiceMap.ServiceMap<any>
|
|
615
|
+
): HttpRouter.Route<any, any> {
|
|
616
|
+
const endpoint = handler.endpoint
|
|
562
617
|
return HttpRouter.route(
|
|
563
618
|
endpoint.method,
|
|
564
619
|
endpoint.path as HttpRouter.PathInput,
|
|
565
|
-
|
|
620
|
+
handlerToHttpEffect(group, endpoint, services, handler.handler, handler.isRaw),
|
|
566
621
|
{ uninterruptible: handler.uninterruptible }
|
|
567
622
|
)
|
|
568
623
|
}
|
|
@@ -513,8 +513,8 @@ export type ServerServices<Endpoint> = Endpoint extends HttpApiEndpoint<
|
|
|
513
513
|
| _Payload["DecodingServices"]
|
|
514
514
|
| _Headers["DecodingServices"]
|
|
515
515
|
| _Success["EncodingServices"]
|
|
516
|
-
|
|
517
|
-
|
|
516
|
+
| _Error["EncodingServices"]
|
|
517
|
+
| HttpApiMiddleware.ErrorServicesEncode<_M>
|
|
518
518
|
: never
|
|
519
519
|
|
|
520
520
|
/**
|
|
@@ -668,10 +668,19 @@ export type MiddlewareServicesWithName<Endpoints extends Any, Name extends strin
|
|
|
668
668
|
* @since 4.0.0
|
|
669
669
|
* @category models
|
|
670
670
|
*/
|
|
671
|
-
export type
|
|
671
|
+
export type ExcludeProvidedWithName<Endpoints extends Any, Name extends string, R> = ExcludeProvided<
|
|
672
|
+
WithName<Endpoints, Name>,
|
|
673
|
+
R
|
|
674
|
+
>
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* @since 4.0.0
|
|
678
|
+
* @category models
|
|
679
|
+
*/
|
|
680
|
+
export type ExcludeProvided<Endpoint extends Any, R> = Exclude<
|
|
672
681
|
R,
|
|
673
682
|
| HttpRouter.Provided
|
|
674
|
-
| HttpApiMiddleware.Provides<
|
|
683
|
+
| HttpApiMiddleware.Provides<Middleware<Endpoint>>
|
|
675
684
|
>
|
|
676
685
|
|
|
677
686
|
/**
|
|
@@ -635,9 +635,26 @@ function toEncodingAST(ast: AST.AST, _tag: HttpApiSchema.Encoding["_tag"]): AST.
|
|
|
635
635
|
return Schema.String.ast
|
|
636
636
|
case "FormUrlEncoded":
|
|
637
637
|
case "Json":
|
|
638
|
-
case "Multipart":
|
|
639
638
|
return ast
|
|
639
|
+
case "Multipart":
|
|
640
|
+
return persistedFileToBinaryEncoding(ast)
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
function persistedFileToBinaryEncoding(ast: AST.AST): AST.AST {
|
|
645
|
+
if (
|
|
646
|
+
AST.isDeclaration(ast) &&
|
|
647
|
+
((ast.annotations as (Schema.Annotations.Declaration<unknown, readonly []> | undefined))?.typeConstructor?._tag ===
|
|
648
|
+
"effect/http/PersistedFile")
|
|
649
|
+
) {
|
|
650
|
+
return Uint8ArrayEncoding.ast
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
if (typeof (ast as any)?.recur === "function") {
|
|
654
|
+
return (ast as any).recur(persistedFileToBinaryEncoding)
|
|
640
655
|
}
|
|
656
|
+
|
|
657
|
+
return ast
|
|
641
658
|
}
|
|
642
659
|
|
|
643
660
|
const makeSecurityScheme = (security: HttpApiSecurity): OpenAPISecurityScheme => {
|
|
@@ -66,7 +66,7 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
|
|
|
66
66
|
readonly reactivityKeys?: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
|
|
67
67
|
}
|
|
68
68
|
>,
|
|
69
|
-
WithResponse extends true ? [_Success, HttpClientResponse] : _Success,
|
|
69
|
+
WithResponse extends true ? [_Success["Type"], HttpClientResponse] : _Success["Type"],
|
|
70
70
|
_Error | HttpClientError.HttpClientError | SchemaError
|
|
71
71
|
>
|
|
72
72
|
: never
|
|
@@ -123,7 +123,7 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
|
|
|
123
123
|
>
|
|
124
124
|
] ? Atom.Atom<
|
|
125
125
|
AsyncResult.AsyncResult<
|
|
126
|
-
WithResponse extends true ? [_Success, HttpClientResponse] : _Success,
|
|
126
|
+
WithResponse extends true ? [_Success["Type"], HttpClientResponse] : _Success["Type"],
|
|
127
127
|
_Error | HttpClientError.HttpClientError | SchemaError
|
|
128
128
|
>
|
|
129
129
|
>
|
|
@@ -482,9 +482,7 @@ class RegistryImpl implements AtomRegistry {
|
|
|
482
482
|
|
|
483
483
|
removeNodeTimeout(node: NodeImpl<any>): void {
|
|
484
484
|
const bucket = this.nodeTimeoutBucket.get(node)
|
|
485
|
-
if (bucket === undefined)
|
|
486
|
-
return
|
|
487
|
-
}
|
|
485
|
+
if (bucket === undefined) return
|
|
488
486
|
this.nodeTimeoutBucket.delete(node)
|
|
489
487
|
this.scheduleNodeRemoval(node)
|
|
490
488
|
|
|
@@ -502,10 +500,8 @@ class RegistryImpl implements AtomRegistry {
|
|
|
502
500
|
this.timeoutBuckets.delete(bucket)
|
|
503
501
|
|
|
504
502
|
nodes.forEach((node) => {
|
|
505
|
-
if (!node.canBeRemoved) {
|
|
506
|
-
return
|
|
507
|
-
}
|
|
508
503
|
this.nodeTimeoutBucket.delete(node)
|
|
504
|
+
if (!node.canBeRemoved) return
|
|
509
505
|
this.nodes.delete(atomKey(node.atom))
|
|
510
506
|
this.onNodeRemoved?.(node)
|
|
511
507
|
this.#currentSweepTTL = node.atom.idleTTL ?? this.defaultIdleTTL!
|