@effect/platform 0.62.4 → 0.63.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/HttpApi/package.json +6 -0
- package/HttpApiBuilder/package.json +6 -0
- package/HttpApiClient/package.json +6 -0
- package/HttpApiEndpoint/package.json +6 -0
- package/HttpApiError/package.json +6 -0
- package/HttpApiGroup/package.json +6 -0
- package/HttpApiSchema/package.json +6 -0
- package/HttpApiSecurity/package.json +6 -0
- package/HttpApiSwagger/package.json +6 -0
- package/OpenApi/package.json +6 -0
- package/README.md +863 -302
- package/dist/cjs/HttpApi.js +168 -0
- package/dist/cjs/HttpApi.js.map +1 -0
- package/dist/cjs/HttpApiBuilder.js +471 -0
- package/dist/cjs/HttpApiBuilder.js.map +1 -0
- package/dist/cjs/HttpApiClient.js +134 -0
- package/dist/cjs/HttpApiClient.js.map +1 -0
- package/dist/cjs/HttpApiEndpoint.js +181 -0
- package/dist/cjs/HttpApiEndpoint.js.map +1 -0
- package/dist/cjs/HttpApiError.js +69 -0
- package/dist/cjs/HttpApiError.js.map +1 -0
- package/dist/cjs/HttpApiGroup.js +151 -0
- package/dist/cjs/HttpApiGroup.js.map +1 -0
- package/dist/cjs/HttpApiSchema.js +241 -0
- package/dist/cjs/HttpApiSchema.js.map +1 -0
- package/dist/cjs/HttpApiSecurity.js +83 -0
- package/dist/cjs/HttpApiSecurity.js.map +1 -0
- package/dist/cjs/HttpApiSwagger.js +50 -0
- package/dist/cjs/HttpApiSwagger.js.map +1 -0
- package/dist/cjs/HttpMethod.js +1 -1
- package/dist/cjs/HttpMethod.js.map +1 -1
- package/dist/cjs/HttpRouter.js +6 -1
- package/dist/cjs/HttpRouter.js.map +1 -1
- package/dist/cjs/OpenApi.js +317 -0
- package/dist/cjs/OpenApi.js.map +1 -0
- package/dist/cjs/index.js +21 -1
- package/dist/cjs/internal/apiSwagger.js +2 -0
- package/dist/cjs/internal/apiSwagger.js.map +1 -0
- package/dist/cjs/internal/httpRouter.js +6 -1
- package/dist/cjs/internal/httpRouter.js.map +1 -1
- package/dist/cjs/internal/multipart.js +5 -1
- package/dist/cjs/internal/multipart.js.map +1 -1
- package/dist/dts/HttpApi.d.ts +156 -0
- package/dist/dts/HttpApi.d.ts.map +1 -0
- package/dist/dts/HttpApiBuilder.d.ts +296 -0
- package/dist/dts/HttpApiBuilder.d.ts.map +1 -0
- package/dist/dts/HttpApiClient.d.ts +31 -0
- package/dist/dts/HttpApiClient.d.ts.map +1 -0
- package/dist/dts/HttpApiEndpoint.d.ts +350 -0
- package/dist/dts/HttpApiEndpoint.d.ts.map +1 -0
- package/dist/dts/HttpApiError.d.ts +70 -0
- package/dist/dts/HttpApiError.d.ts.map +1 -0
- package/dist/dts/HttpApiGroup.d.ts +196 -0
- package/dist/dts/HttpApiGroup.d.ts.map +1 -0
- package/dist/dts/HttpApiSchema.d.ts +223 -0
- package/dist/dts/HttpApiSchema.d.ts.map +1 -0
- package/dist/dts/HttpApiSecurity.d.ts +122 -0
- package/dist/dts/HttpApiSecurity.d.ts.map +1 -0
- package/dist/dts/HttpApiSwagger.d.ts +10 -0
- package/dist/dts/HttpApiSwagger.d.ts.map +1 -0
- package/dist/dts/HttpMethod.d.ts +16 -0
- package/dist/dts/HttpMethod.d.ts.map +1 -1
- package/dist/dts/HttpRouter.d.ts +8 -0
- package/dist/dts/HttpRouter.d.ts.map +1 -1
- package/dist/dts/HttpServerResponse.d.ts +3 -3
- package/dist/dts/HttpServerResponse.d.ts.map +1 -1
- package/dist/dts/OpenApi.d.ts +348 -0
- package/dist/dts/OpenApi.d.ts.map +1 -0
- package/dist/dts/index.d.ts +40 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/apiSwagger.d.ts +2 -0
- package/dist/dts/internal/apiSwagger.d.ts.map +1 -0
- package/dist/dts/internal/httpRouter.d.ts.map +1 -1
- package/dist/esm/HttpApi.js +157 -0
- package/dist/esm/HttpApi.js.map +1 -0
- package/dist/esm/HttpApiBuilder.js +447 -0
- package/dist/esm/HttpApiBuilder.js.map +1 -0
- package/dist/esm/HttpApiClient.js +124 -0
- package/dist/esm/HttpApiClient.js.map +1 -0
- package/dist/esm/HttpApiEndpoint.js +169 -0
- package/dist/esm/HttpApiEndpoint.js.map +1 -0
- package/dist/esm/HttpApiError.js +59 -0
- package/dist/esm/HttpApiError.js.map +1 -0
- package/dist/esm/HttpApiGroup.js +140 -0
- package/dist/esm/HttpApiGroup.js.map +1 -0
- package/dist/esm/HttpApiSchema.js +217 -0
- package/dist/esm/HttpApiSchema.js.map +1 -0
- package/dist/esm/HttpApiSecurity.js +73 -0
- package/dist/esm/HttpApiSecurity.js.map +1 -0
- package/dist/esm/HttpApiSwagger.js +40 -0
- package/dist/esm/HttpApiSwagger.js.map +1 -0
- package/dist/esm/HttpMethod.js +1 -1
- package/dist/esm/HttpMethod.js.map +1 -1
- package/dist/esm/HttpRouter.js +5 -0
- package/dist/esm/HttpRouter.js.map +1 -1
- package/dist/esm/OpenApi.js +299 -0
- package/dist/esm/OpenApi.js.map +1 -0
- package/dist/esm/index.js +40 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/apiSwagger.js +2 -0
- package/dist/esm/internal/apiSwagger.js.map +1 -0
- package/dist/esm/internal/httpRouter.js +5 -0
- package/dist/esm/internal/httpRouter.js.map +1 -1
- package/dist/esm/internal/multipart.js +5 -1
- package/dist/esm/internal/multipart.js.map +1 -1
- package/package.json +83 -3
- package/src/HttpApi.ts +342 -0
- package/src/HttpApiBuilder.ts +869 -0
- package/src/HttpApiClient.ts +228 -0
- package/src/HttpApiEndpoint.ts +818 -0
- package/src/HttpApiError.ts +113 -0
- package/src/HttpApiGroup.ts +365 -0
- package/src/HttpApiSchema.ts +384 -0
- package/src/HttpApiSecurity.ts +169 -0
- package/src/HttpApiSwagger.ts +46 -0
- package/src/HttpMethod.ts +19 -1
- package/src/HttpRouter.ts +9 -0
- package/src/HttpServerResponse.ts +3 -3
- package/src/OpenApi.ts +665 -0
- package/src/index.ts +50 -0
- package/src/internal/apiSwagger.ts +7 -0
- package/src/internal/httpRouter.ts +9 -0
- package/src/internal/multipart.ts +5 -1
|
@@ -0,0 +1,818 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Schema from "@effect/schema/Schema"
|
|
5
|
+
import type { Brand } from "effect/Brand"
|
|
6
|
+
import * as Context from "effect/Context"
|
|
7
|
+
import type { Effect } from "effect/Effect"
|
|
8
|
+
import { dual } from "effect/Function"
|
|
9
|
+
import * as Option from "effect/Option"
|
|
10
|
+
import { type Pipeable, pipeArguments } from "effect/Pipeable"
|
|
11
|
+
import * as Predicate from "effect/Predicate"
|
|
12
|
+
import type { Redacted } from "effect/Redacted"
|
|
13
|
+
import type * as Types from "effect/Types"
|
|
14
|
+
import * as HttpApiSchema from "./HttpApiSchema.js"
|
|
15
|
+
import type { HttpMethod } from "./HttpMethod.js"
|
|
16
|
+
import * as HttpRouter from "./HttpRouter.js"
|
|
17
|
+
import type { HttpServerResponse } from "./HttpServerResponse.js"
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @since 1.0.0
|
|
21
|
+
* @category type ids
|
|
22
|
+
*/
|
|
23
|
+
export const TypeId: unique symbol = Symbol.for("@effect/platform/HttpApiEndpoint")
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @since 1.0.0
|
|
27
|
+
* @category type ids
|
|
28
|
+
*/
|
|
29
|
+
export type TypeId = typeof TypeId
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @since 1.0.0
|
|
33
|
+
* @category guards
|
|
34
|
+
*/
|
|
35
|
+
export const isHttpApiEndpoint = (u: unknown): u is HttpApiEndpoint<any, any, any> => Predicate.hasProperty(u, TypeId)
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Represents an API endpoint. An API endpoint is mapped to a single route on
|
|
39
|
+
* the underlying `HttpRouter`.
|
|
40
|
+
*
|
|
41
|
+
* @since 1.0.0
|
|
42
|
+
* @category models
|
|
43
|
+
*/
|
|
44
|
+
export interface HttpApiEndpoint<
|
|
45
|
+
out Name extends string,
|
|
46
|
+
out Method extends HttpMethod,
|
|
47
|
+
in out Path = never,
|
|
48
|
+
in out Payload = never,
|
|
49
|
+
in out Headers = never,
|
|
50
|
+
in out Success = void,
|
|
51
|
+
in out Error = never,
|
|
52
|
+
out R = never
|
|
53
|
+
> extends Pipeable {
|
|
54
|
+
readonly [TypeId]: TypeId
|
|
55
|
+
readonly name: Name
|
|
56
|
+
readonly path: HttpRouter.PathInput
|
|
57
|
+
readonly method: Method
|
|
58
|
+
readonly pathSchema: Option.Option<Schema.Schema<Path, unknown, R>>
|
|
59
|
+
readonly payloadSchema: Option.Option<Schema.Schema<Payload, unknown, R>>
|
|
60
|
+
readonly headersSchema: Option.Option<Schema.Schema<Headers, unknown, R>>
|
|
61
|
+
readonly successSchema: Schema.Schema<Success, unknown, R>
|
|
62
|
+
readonly errorSchema: Schema.Schema<Error, unknown, R>
|
|
63
|
+
readonly annotations: Context.Context<never>
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @since 1.0.0
|
|
68
|
+
* @category models
|
|
69
|
+
*/
|
|
70
|
+
export declare namespace HttpApiEndpoint {
|
|
71
|
+
/**
|
|
72
|
+
* @since 1.0.0
|
|
73
|
+
* @category models
|
|
74
|
+
*/
|
|
75
|
+
export interface Any extends Pipeable {
|
|
76
|
+
readonly [TypeId]: TypeId
|
|
77
|
+
readonly name: string
|
|
78
|
+
readonly path: HttpRouter.PathInput
|
|
79
|
+
readonly method: HttpMethod
|
|
80
|
+
readonly pathSchema: Option.Option<Schema.Schema.Any>
|
|
81
|
+
readonly payloadSchema: Option.Option<Schema.Schema.Any>
|
|
82
|
+
readonly headersSchema: Option.Option<Schema.Schema.Any>
|
|
83
|
+
readonly successSchema: Schema.Schema.Any
|
|
84
|
+
readonly errorSchema: Schema.Schema.Any
|
|
85
|
+
readonly annotations: Context.Context<never>
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @since 1.0.0
|
|
90
|
+
* @category models
|
|
91
|
+
*/
|
|
92
|
+
export interface All extends Pipeable {
|
|
93
|
+
readonly [TypeId]: TypeId
|
|
94
|
+
readonly name: string
|
|
95
|
+
readonly path: HttpRouter.PathInput
|
|
96
|
+
readonly method: HttpMethod
|
|
97
|
+
readonly pathSchema: Option.Option<Schema.Schema.All>
|
|
98
|
+
readonly payloadSchema: Option.Option<Schema.Schema.All>
|
|
99
|
+
readonly headersSchema: Option.Option<Schema.Schema.All>
|
|
100
|
+
readonly successSchema: Schema.Schema.Any
|
|
101
|
+
readonly errorSchema: Schema.Schema.All
|
|
102
|
+
readonly annotations: Context.Context<never>
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @since 1.0.0
|
|
107
|
+
* @category models
|
|
108
|
+
*/
|
|
109
|
+
export type Success<Endpoint extends All> = Endpoint extends HttpApiEndpoint<
|
|
110
|
+
infer _Name,
|
|
111
|
+
infer _Method,
|
|
112
|
+
infer _Path,
|
|
113
|
+
infer _Payload,
|
|
114
|
+
infer _Headers,
|
|
115
|
+
infer _Success,
|
|
116
|
+
infer _Error,
|
|
117
|
+
infer _R
|
|
118
|
+
> ? _Success
|
|
119
|
+
: never
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @since 1.0.0
|
|
123
|
+
* @category models
|
|
124
|
+
*/
|
|
125
|
+
export type Error<Endpoint extends All> = Endpoint extends HttpApiEndpoint<
|
|
126
|
+
infer _Name,
|
|
127
|
+
infer _Method,
|
|
128
|
+
infer _Path,
|
|
129
|
+
infer _Payload,
|
|
130
|
+
infer _Headers,
|
|
131
|
+
infer _Success,
|
|
132
|
+
infer _Error,
|
|
133
|
+
infer _R
|
|
134
|
+
> ? _Error
|
|
135
|
+
: never
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @since 1.0.0
|
|
139
|
+
* @category models
|
|
140
|
+
*/
|
|
141
|
+
export type PathParsed<Endpoint extends All> = Endpoint extends HttpApiEndpoint<
|
|
142
|
+
infer _Name,
|
|
143
|
+
infer _Method,
|
|
144
|
+
infer _Path,
|
|
145
|
+
infer _Payload,
|
|
146
|
+
infer _Headers,
|
|
147
|
+
infer _Success,
|
|
148
|
+
infer _Error,
|
|
149
|
+
infer _R
|
|
150
|
+
> ? _Path
|
|
151
|
+
: never
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @since 1.0.0
|
|
155
|
+
* @category models
|
|
156
|
+
*/
|
|
157
|
+
export type Payload<Endpoint extends All> = Endpoint extends HttpApiEndpoint<
|
|
158
|
+
infer _Name,
|
|
159
|
+
infer _Method,
|
|
160
|
+
infer _Path,
|
|
161
|
+
infer _Payload,
|
|
162
|
+
infer _Headers,
|
|
163
|
+
infer _Success,
|
|
164
|
+
infer _Error,
|
|
165
|
+
infer _R
|
|
166
|
+
> ? _Payload
|
|
167
|
+
: never
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @since 1.0.0
|
|
171
|
+
* @category models
|
|
172
|
+
*/
|
|
173
|
+
export type Headers<Endpoint extends All> = Endpoint extends HttpApiEndpoint<
|
|
174
|
+
infer _Name,
|
|
175
|
+
infer _Method,
|
|
176
|
+
infer _Path,
|
|
177
|
+
infer _Payload,
|
|
178
|
+
infer _Headers,
|
|
179
|
+
infer _Success,
|
|
180
|
+
infer _Error,
|
|
181
|
+
infer _R
|
|
182
|
+
> ? _Headers
|
|
183
|
+
: never
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @since 1.0.0
|
|
187
|
+
* @category models
|
|
188
|
+
*/
|
|
189
|
+
export type Request<Endpoint extends All> =
|
|
190
|
+
& {
|
|
191
|
+
readonly path: PathParsed<Endpoint>
|
|
192
|
+
}
|
|
193
|
+
& ([Payload<Endpoint>] extends [infer P] ? [P] extends [never] ? {} : { readonly payload: P } : {})
|
|
194
|
+
& ([Headers<Endpoint>] extends [infer H] ? [H] extends [never] ? {} : { readonly headers: H } : {})
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @since 1.0.0
|
|
198
|
+
* @category models
|
|
199
|
+
*/
|
|
200
|
+
export type ClientRequest<Path, Payload, Headers> = (
|
|
201
|
+
& ([Path] extends [void] ? {} : { readonly path: Path })
|
|
202
|
+
& ([Headers] extends [never] ? {} : { readonly headers: Headers })
|
|
203
|
+
& ([Payload] extends [never] ? {}
|
|
204
|
+
: [Payload] extends [Brand<HttpApiSchema.MultipartTypeId>] ? { readonly payload: FormData }
|
|
205
|
+
: { readonly payload: Payload })
|
|
206
|
+
) extends infer Req ? keyof Req extends never ? void : Req : void
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @since 1.0.0
|
|
210
|
+
* @category models
|
|
211
|
+
*/
|
|
212
|
+
export type Context<Endpoint> = Endpoint extends HttpApiEndpoint<
|
|
213
|
+
infer _Name,
|
|
214
|
+
infer _Method,
|
|
215
|
+
infer _Path,
|
|
216
|
+
infer _Payload,
|
|
217
|
+
infer _Headers,
|
|
218
|
+
infer _Success,
|
|
219
|
+
infer _Error,
|
|
220
|
+
infer _R
|
|
221
|
+
> ? _R
|
|
222
|
+
: never
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* @since 1.0.0
|
|
226
|
+
* @category models
|
|
227
|
+
*/
|
|
228
|
+
export type Handler<Endpoint extends All, E, R> = (
|
|
229
|
+
request: Types.Simplify<Request<Endpoint>>
|
|
230
|
+
) => Effect<Success<Endpoint>, E, R>
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @since 1.0.0
|
|
234
|
+
* @category models
|
|
235
|
+
*/
|
|
236
|
+
export type HandlerRedacted<Endpoint extends All, E, R> = (
|
|
237
|
+
request: Types.Simplify<Request<Endpoint>>
|
|
238
|
+
) => Effect<readonly [Success<Endpoint>, Redacted], E, R>
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* @since 1.0.0
|
|
242
|
+
* @category models
|
|
243
|
+
*/
|
|
244
|
+
export type HandlerResponse<Endpoint extends All, E, R> = (
|
|
245
|
+
request: Types.Simplify<Request<Endpoint>>
|
|
246
|
+
) => Effect<HttpServerResponse, E, R>
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @since 1.0.0
|
|
250
|
+
* @category models
|
|
251
|
+
*/
|
|
252
|
+
export type WithName<Endpoints extends All, Name extends string> = Endpoints extends infer Endpoint
|
|
253
|
+
? Endpoint extends { readonly name: Name } ? Endpoint : never
|
|
254
|
+
: never
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* @since 1.0.0
|
|
258
|
+
* @category models
|
|
259
|
+
*/
|
|
260
|
+
export type ExcludeName<Endpoints extends All, Name extends string> = Exclude<Endpoints, { readonly name: Name }>
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* @since 1.0.0
|
|
264
|
+
* @category models
|
|
265
|
+
*/
|
|
266
|
+
export type HandlerWithName<Endpoints extends All, Name extends string, E, R> = Handler<
|
|
267
|
+
WithName<Endpoints, Name>,
|
|
268
|
+
E,
|
|
269
|
+
R
|
|
270
|
+
>
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @since 1.0.0
|
|
274
|
+
* @category models
|
|
275
|
+
*/
|
|
276
|
+
export type HandlerResponseWithName<Endpoints extends All, Name extends string, E, R> = HandlerResponse<
|
|
277
|
+
WithName<Endpoints, Name>,
|
|
278
|
+
E,
|
|
279
|
+
R
|
|
280
|
+
>
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* @since 1.0.0
|
|
284
|
+
* @category models
|
|
285
|
+
*/
|
|
286
|
+
export type HandlerRedactedWithName<Endpoints extends All, Name extends string, E, R> = HandlerRedacted<
|
|
287
|
+
WithName<Endpoints, Name>,
|
|
288
|
+
E,
|
|
289
|
+
R
|
|
290
|
+
>
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* @since 1.0.0
|
|
294
|
+
* @category models
|
|
295
|
+
*/
|
|
296
|
+
export type SuccessWithName<Endpoints extends All, Name extends string> = Success<WithName<Endpoints, Name>>
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* @since 1.0.0
|
|
300
|
+
* @category models
|
|
301
|
+
*/
|
|
302
|
+
export type ErrorWithName<Endpoints extends All, Name extends string> = Error<WithName<Endpoints, Name>>
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* @since 1.0.0
|
|
306
|
+
* @category models
|
|
307
|
+
*/
|
|
308
|
+
export type ExcludeProvided<R> = Exclude<
|
|
309
|
+
R,
|
|
310
|
+
HttpRouter.HttpRouter.DefaultServices | HttpRouter.HttpRouter.Provided
|
|
311
|
+
>
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* @since 1.0.0
|
|
315
|
+
* @category models
|
|
316
|
+
*/
|
|
317
|
+
export type ValidatePath<S extends Schema.Schema.Any> = S extends Schema.Schema<infer _A, infer _I, infer _R>
|
|
318
|
+
? [_I] extends [Readonly<Record<string, string | undefined>>] ? {}
|
|
319
|
+
: `Path schema must be encodeable to strings`
|
|
320
|
+
: {}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @since 1.0.0
|
|
324
|
+
* @category models
|
|
325
|
+
*/
|
|
326
|
+
export type ValidateHeaders<S extends Schema.Schema.Any> = S extends Schema.Schema<infer _A, infer _I, infer _R>
|
|
327
|
+
? [_I] extends [Readonly<Record<string, string | undefined>>] ? {}
|
|
328
|
+
: `Headers schema must be encodeable to strings`
|
|
329
|
+
: {}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* @since 1.0.0
|
|
333
|
+
* @category models
|
|
334
|
+
*/
|
|
335
|
+
export type ValidatePayload<Method extends HttpMethod, P extends Schema.Schema.All> = Method extends
|
|
336
|
+
HttpMethod.NoBody ?
|
|
337
|
+
P extends Schema.Schema<infer _A, infer _I, infer _R>
|
|
338
|
+
? [_I] extends [Readonly<Record<string, string | ReadonlyArray<string> | undefined>>] ? {}
|
|
339
|
+
: `'${Method}' payload must be encodeable to strings`
|
|
340
|
+
: {}
|
|
341
|
+
: {}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const Proto = {
|
|
345
|
+
[TypeId]: TypeId,
|
|
346
|
+
pipe() {
|
|
347
|
+
return pipeArguments(this, arguments)
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const makeProto = <
|
|
352
|
+
Name extends string,
|
|
353
|
+
Method extends HttpMethod,
|
|
354
|
+
Path,
|
|
355
|
+
Payload,
|
|
356
|
+
Headers,
|
|
357
|
+
Success,
|
|
358
|
+
Error,
|
|
359
|
+
R
|
|
360
|
+
>(options: {
|
|
361
|
+
readonly name: Name
|
|
362
|
+
readonly path: HttpRouter.PathInput
|
|
363
|
+
readonly method: Method
|
|
364
|
+
readonly pathSchema: Option.Option<Schema.Schema<Path, unknown, R>>
|
|
365
|
+
readonly payloadSchema: Option.Option<Schema.Schema<Payload, unknown, R>>
|
|
366
|
+
readonly headersSchema: Option.Option<Schema.Schema<Headers, unknown, R>>
|
|
367
|
+
readonly successSchema: Schema.Schema<Success, unknown, R>
|
|
368
|
+
readonly errorSchema: Schema.Schema<Error, unknown, R>
|
|
369
|
+
readonly annotations: Context.Context<never>
|
|
370
|
+
}): HttpApiEndpoint<Name, Method, Path, Payload, Headers, Success, Error, R> =>
|
|
371
|
+
Object.assign(Object.create(Proto), options)
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* @since 1.0.0
|
|
375
|
+
* @category constructors
|
|
376
|
+
*/
|
|
377
|
+
export const make = <Method extends HttpMethod>(method: Method) =>
|
|
378
|
+
<const Name extends string>(
|
|
379
|
+
name: Name,
|
|
380
|
+
path: HttpRouter.PathInput
|
|
381
|
+
): HttpApiEndpoint<Name, Method> =>
|
|
382
|
+
makeProto({
|
|
383
|
+
name,
|
|
384
|
+
path,
|
|
385
|
+
method,
|
|
386
|
+
pathSchema: Option.none(),
|
|
387
|
+
payloadSchema: Option.none(),
|
|
388
|
+
headersSchema: Option.none(),
|
|
389
|
+
successSchema: HttpApiSchema.NoContent as any,
|
|
390
|
+
errorSchema: Schema.Never as any,
|
|
391
|
+
annotations: Context.empty()
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* @since 1.0.0
|
|
396
|
+
* @category constructors
|
|
397
|
+
*/
|
|
398
|
+
export const get: <const Name extends string>(
|
|
399
|
+
name: Name,
|
|
400
|
+
path: HttpRouter.PathInput
|
|
401
|
+
) => HttpApiEndpoint<Name, "GET"> = make("GET")
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* @since 1.0.0
|
|
405
|
+
* @category constructors
|
|
406
|
+
*/
|
|
407
|
+
export const post: <const Name extends string>(
|
|
408
|
+
name: Name,
|
|
409
|
+
path: HttpRouter.PathInput
|
|
410
|
+
) => HttpApiEndpoint<Name, "POST"> = make("POST")
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* @since 1.0.0
|
|
414
|
+
* @category constructors
|
|
415
|
+
*/
|
|
416
|
+
export const put: <const Name extends string>(
|
|
417
|
+
name: Name,
|
|
418
|
+
path: HttpRouter.PathInput
|
|
419
|
+
) => HttpApiEndpoint<Name, "PUT"> = make("PUT")
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* @since 1.0.0
|
|
423
|
+
* @category constructors
|
|
424
|
+
*/
|
|
425
|
+
export const patch: <const Name extends string>(
|
|
426
|
+
name: Name,
|
|
427
|
+
path: HttpRouter.PathInput
|
|
428
|
+
) => HttpApiEndpoint<Name, "PATCH"> = make("PATCH")
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* @since 1.0.0
|
|
432
|
+
* @category constructors
|
|
433
|
+
*/
|
|
434
|
+
export const del: <const Name extends string>(
|
|
435
|
+
name: Name,
|
|
436
|
+
path: HttpRouter.PathInput
|
|
437
|
+
) => HttpApiEndpoint<Name, "DELETE"> = make("DELETE")
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Set the schema for the success response of the endpoint. The status code
|
|
441
|
+
* will be inferred from the schema, otherwise it will default to 200.
|
|
442
|
+
*
|
|
443
|
+
* @since 1.0.0
|
|
444
|
+
* @category result
|
|
445
|
+
*/
|
|
446
|
+
export const setSuccess: {
|
|
447
|
+
<S extends Schema.Schema.Any>(
|
|
448
|
+
schema: S,
|
|
449
|
+
annotations?: {
|
|
450
|
+
readonly status?: number | undefined
|
|
451
|
+
}
|
|
452
|
+
): <
|
|
453
|
+
Name extends string,
|
|
454
|
+
Method extends HttpMethod,
|
|
455
|
+
_Path,
|
|
456
|
+
_P,
|
|
457
|
+
_H,
|
|
458
|
+
_S,
|
|
459
|
+
_E,
|
|
460
|
+
_R
|
|
461
|
+
>(
|
|
462
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>
|
|
463
|
+
) => HttpApiEndpoint<Name, Method, _Path, _P, _H, Schema.Schema.Type<S>, _E, _R | Schema.Schema.Context<S>>
|
|
464
|
+
<
|
|
465
|
+
Name extends string,
|
|
466
|
+
Method extends HttpMethod,
|
|
467
|
+
_Path,
|
|
468
|
+
_P,
|
|
469
|
+
_H,
|
|
470
|
+
_S,
|
|
471
|
+
_E,
|
|
472
|
+
_R,
|
|
473
|
+
S extends Schema.Schema.Any
|
|
474
|
+
>(
|
|
475
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>,
|
|
476
|
+
schema: S,
|
|
477
|
+
annotations?: {
|
|
478
|
+
readonly status?: number | undefined
|
|
479
|
+
}
|
|
480
|
+
): HttpApiEndpoint<Name, Method, _Path, _P, _H, Schema.Schema.Type<S>, _E, _R | Schema.Schema.Context<S>>
|
|
481
|
+
} = dual(
|
|
482
|
+
(args) => isHttpApiEndpoint(args[0]),
|
|
483
|
+
<
|
|
484
|
+
Name extends string,
|
|
485
|
+
Method extends HttpMethod,
|
|
486
|
+
_Path,
|
|
487
|
+
_P,
|
|
488
|
+
_H,
|
|
489
|
+
_S,
|
|
490
|
+
_E,
|
|
491
|
+
_R,
|
|
492
|
+
S extends Schema.Schema.Any
|
|
493
|
+
>(
|
|
494
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>,
|
|
495
|
+
schema: S,
|
|
496
|
+
annotations?: {
|
|
497
|
+
readonly status?: number | undefined
|
|
498
|
+
}
|
|
499
|
+
): HttpApiEndpoint<Name, Method, _Path, _P, Schema.Schema.Type<S>, _E, _R | Schema.Schema.Context<S>> =>
|
|
500
|
+
makeProto({
|
|
501
|
+
...self as any,
|
|
502
|
+
successSchema: schema.annotations(HttpApiSchema.annotations({
|
|
503
|
+
status: annotations?.status ?? HttpApiSchema.getStatusSuccess(schema)
|
|
504
|
+
}))
|
|
505
|
+
})
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Add an error response schema to the endpoint. The status code
|
|
510
|
+
* will be inferred from the schema, otherwise it will default to 500.
|
|
511
|
+
*
|
|
512
|
+
* @since 1.0.0
|
|
513
|
+
* @category result
|
|
514
|
+
*/
|
|
515
|
+
export const addError: {
|
|
516
|
+
<E extends Schema.Schema.All>(
|
|
517
|
+
schema: E,
|
|
518
|
+
annotations?: {
|
|
519
|
+
readonly status?: number | undefined
|
|
520
|
+
}
|
|
521
|
+
): <
|
|
522
|
+
Name extends string,
|
|
523
|
+
Method extends HttpMethod,
|
|
524
|
+
_Path,
|
|
525
|
+
_P,
|
|
526
|
+
_H,
|
|
527
|
+
_S,
|
|
528
|
+
_E,
|
|
529
|
+
_R
|
|
530
|
+
>(
|
|
531
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>
|
|
532
|
+
) => HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E | Schema.Schema.Type<E>, _R | Schema.Schema.Context<E>>
|
|
533
|
+
<
|
|
534
|
+
Name extends string,
|
|
535
|
+
Method extends HttpMethod,
|
|
536
|
+
_Path,
|
|
537
|
+
_P,
|
|
538
|
+
_H,
|
|
539
|
+
_S,
|
|
540
|
+
_E,
|
|
541
|
+
_R,
|
|
542
|
+
E extends Schema.Schema.All
|
|
543
|
+
>(
|
|
544
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>,
|
|
545
|
+
schema: E,
|
|
546
|
+
annotations?: {
|
|
547
|
+
readonly status?: number | undefined
|
|
548
|
+
}
|
|
549
|
+
): HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E | Schema.Schema.Type<E>, _R | Schema.Schema.Context<E>>
|
|
550
|
+
} = dual(
|
|
551
|
+
(args) => isHttpApiEndpoint(args[0]),
|
|
552
|
+
<
|
|
553
|
+
Name extends string,
|
|
554
|
+
Method extends HttpMethod,
|
|
555
|
+
_Path,
|
|
556
|
+
_P,
|
|
557
|
+
_H,
|
|
558
|
+
_S,
|
|
559
|
+
_E,
|
|
560
|
+
_R,
|
|
561
|
+
E extends Schema.Schema.All
|
|
562
|
+
>(
|
|
563
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>,
|
|
564
|
+
schema: E,
|
|
565
|
+
annotations?: {
|
|
566
|
+
readonly status?: number | undefined
|
|
567
|
+
}
|
|
568
|
+
): HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E | Schema.Schema.Type<E>, _R | Schema.Schema.Context<E>> =>
|
|
569
|
+
makeProto({
|
|
570
|
+
...self as any,
|
|
571
|
+
errorSchema: HttpApiSchema.UnionUnify(
|
|
572
|
+
self.errorSchema,
|
|
573
|
+
schema.pipe(
|
|
574
|
+
Schema.annotations(HttpApiSchema.annotations({
|
|
575
|
+
status: annotations?.status ?? HttpApiSchema.getStatusError(schema)
|
|
576
|
+
}))
|
|
577
|
+
)
|
|
578
|
+
)
|
|
579
|
+
})
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Set the schema for the request body of the endpoint. The schema will be
|
|
584
|
+
* used to validate the request body before the handler is called.
|
|
585
|
+
*
|
|
586
|
+
* For endpoints with no request body, the payload will use the url search
|
|
587
|
+
* parameters.
|
|
588
|
+
*
|
|
589
|
+
* You can set a multipart schema to handle file uploads by using the
|
|
590
|
+
* `HttpApiSchema.Multipart` combinator.
|
|
591
|
+
*
|
|
592
|
+
* @since 1.0.0
|
|
593
|
+
* @category request
|
|
594
|
+
*/
|
|
595
|
+
export const setPayload: {
|
|
596
|
+
<Method extends HttpMethod, P extends Schema.Schema.All>(
|
|
597
|
+
schema: P & HttpApiEndpoint.ValidatePayload<Method, P>
|
|
598
|
+
): <
|
|
599
|
+
Name extends string,
|
|
600
|
+
_Path,
|
|
601
|
+
_P,
|
|
602
|
+
_H,
|
|
603
|
+
_S,
|
|
604
|
+
_E,
|
|
605
|
+
_R
|
|
606
|
+
>(
|
|
607
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>
|
|
608
|
+
) => HttpApiEndpoint<Name, Method, _Path, Schema.Schema.Type<P>, _H, _S, _E, _R | Schema.Schema.Context<P>>
|
|
609
|
+
<
|
|
610
|
+
Name extends string,
|
|
611
|
+
Method extends HttpMethod,
|
|
612
|
+
_Path,
|
|
613
|
+
_P,
|
|
614
|
+
_H,
|
|
615
|
+
_S,
|
|
616
|
+
_E,
|
|
617
|
+
_R,
|
|
618
|
+
P extends Schema.Schema.All
|
|
619
|
+
>(
|
|
620
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>,
|
|
621
|
+
schema: P & HttpApiEndpoint.ValidatePayload<Method, P>
|
|
622
|
+
): HttpApiEndpoint<Name, Method, _Path, Schema.Schema.Type<P>, _H, _S, _E, _R | Schema.Schema.Context<P>>
|
|
623
|
+
} = dual(
|
|
624
|
+
2,
|
|
625
|
+
<
|
|
626
|
+
Name extends string,
|
|
627
|
+
Method extends HttpMethod,
|
|
628
|
+
_Path,
|
|
629
|
+
_P,
|
|
630
|
+
_H,
|
|
631
|
+
_S,
|
|
632
|
+
_E,
|
|
633
|
+
_R,
|
|
634
|
+
P extends Schema.Schema.All
|
|
635
|
+
>(
|
|
636
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>,
|
|
637
|
+
schema: P & HttpApiEndpoint.ValidatePayload<Method, P>
|
|
638
|
+
): HttpApiEndpoint<Name, Method, _Path, Schema.Schema.Type<P>, _H, _S, _E, _R | Schema.Schema.Context<P>> =>
|
|
639
|
+
makeProto({
|
|
640
|
+
...self as any,
|
|
641
|
+
payloadSchema: Option.some(schema)
|
|
642
|
+
})
|
|
643
|
+
)
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Set the schema for the path parameters of the endpoint. The schema will be
|
|
647
|
+
* used to validate the path parameters before the handler is called.
|
|
648
|
+
*
|
|
649
|
+
* @since 1.0.0
|
|
650
|
+
* @category request
|
|
651
|
+
*/
|
|
652
|
+
export const setPath: {
|
|
653
|
+
<Path extends Schema.Schema.Any>(
|
|
654
|
+
schema: Path & HttpApiEndpoint.ValidatePath<Path>
|
|
655
|
+
): <
|
|
656
|
+
Name extends string,
|
|
657
|
+
Method extends HttpMethod,
|
|
658
|
+
_Path,
|
|
659
|
+
_P,
|
|
660
|
+
_H,
|
|
661
|
+
_S,
|
|
662
|
+
_E,
|
|
663
|
+
_R
|
|
664
|
+
>(
|
|
665
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>
|
|
666
|
+
) => HttpApiEndpoint<Name, Method, Schema.Schema.Type<Path>, _P, _H, _S, _E, _R | Schema.Schema.Context<Path>>
|
|
667
|
+
<
|
|
668
|
+
Name extends string,
|
|
669
|
+
Method extends HttpMethod,
|
|
670
|
+
_Path,
|
|
671
|
+
_P,
|
|
672
|
+
_H,
|
|
673
|
+
_S,
|
|
674
|
+
_E,
|
|
675
|
+
_R,
|
|
676
|
+
Path extends Schema.Schema.Any
|
|
677
|
+
>(
|
|
678
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>,
|
|
679
|
+
schema: Path & HttpApiEndpoint.ValidatePath<Path>
|
|
680
|
+
): HttpApiEndpoint<Name, Method, Schema.Schema.Type<Path>, _P, _H, _S, _E, _R | Schema.Schema.Context<Path>>
|
|
681
|
+
} = dual(
|
|
682
|
+
2,
|
|
683
|
+
<
|
|
684
|
+
Name extends string,
|
|
685
|
+
Method extends HttpMethod,
|
|
686
|
+
_Path,
|
|
687
|
+
_P,
|
|
688
|
+
_H,
|
|
689
|
+
_S,
|
|
690
|
+
_E,
|
|
691
|
+
_R,
|
|
692
|
+
Path extends Schema.Schema.Any
|
|
693
|
+
>(
|
|
694
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>,
|
|
695
|
+
schema: Path & HttpApiEndpoint.ValidatePath<Path>
|
|
696
|
+
): HttpApiEndpoint<Name, Method, Schema.Schema.Type<Path>, _P, _H, _S, _E, _R | Schema.Schema.Context<Path>> =>
|
|
697
|
+
makeProto({
|
|
698
|
+
...self as any,
|
|
699
|
+
pathSchema: Option.some(schema)
|
|
700
|
+
})
|
|
701
|
+
)
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Set the schema for the headers of the endpoint. The schema will be
|
|
705
|
+
* used to validate the headers before the handler is called.
|
|
706
|
+
*
|
|
707
|
+
* @since 1.0.0
|
|
708
|
+
* @category request
|
|
709
|
+
*/
|
|
710
|
+
export const setHeaders: {
|
|
711
|
+
<Method extends HttpMethod, H extends Schema.Schema.Any>(
|
|
712
|
+
schema: H & HttpApiEndpoint.ValidateHeaders<H>
|
|
713
|
+
): <
|
|
714
|
+
Name extends string,
|
|
715
|
+
_Path,
|
|
716
|
+
_P,
|
|
717
|
+
_H,
|
|
718
|
+
_S,
|
|
719
|
+
_E,
|
|
720
|
+
_R
|
|
721
|
+
>(
|
|
722
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>
|
|
723
|
+
) => HttpApiEndpoint<Name, Method, _Path, _P, Schema.Schema.Type<H>, _S, _E, _R | Schema.Schema.Context<H>>
|
|
724
|
+
<
|
|
725
|
+
Name extends string,
|
|
726
|
+
Method extends HttpMethod,
|
|
727
|
+
_Path,
|
|
728
|
+
_P,
|
|
729
|
+
_H,
|
|
730
|
+
_S,
|
|
731
|
+
_E,
|
|
732
|
+
_R,
|
|
733
|
+
H extends Schema.Schema.Any
|
|
734
|
+
>(
|
|
735
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>,
|
|
736
|
+
schema: H & HttpApiEndpoint.ValidateHeaders<H>
|
|
737
|
+
): HttpApiEndpoint<Name, Method, _Path, _P, Schema.Schema.Type<H>, _S, _E, _R | Schema.Schema.Context<H>>
|
|
738
|
+
} = dual(
|
|
739
|
+
2,
|
|
740
|
+
<
|
|
741
|
+
Name extends string,
|
|
742
|
+
Method extends HttpMethod,
|
|
743
|
+
_Path,
|
|
744
|
+
_P,
|
|
745
|
+
_H,
|
|
746
|
+
_S,
|
|
747
|
+
_E,
|
|
748
|
+
_R,
|
|
749
|
+
H extends Schema.Schema.Any
|
|
750
|
+
>(
|
|
751
|
+
self: HttpApiEndpoint<Name, Method, _Path, _P, _H, _S, _E, _R>,
|
|
752
|
+
schema: H & HttpApiEndpoint.ValidateHeaders<H>
|
|
753
|
+
): HttpApiEndpoint<Name, Method, _Path, _P, Schema.Schema.Type<H>, _S, _E, _R | Schema.Schema.Context<H>> =>
|
|
754
|
+
makeProto({
|
|
755
|
+
...self as any,
|
|
756
|
+
headersSchema: Option.some(schema)
|
|
757
|
+
})
|
|
758
|
+
)
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* Add a prefix to the path of the endpoint.
|
|
762
|
+
*
|
|
763
|
+
* @since 1.0.0
|
|
764
|
+
* @category request
|
|
765
|
+
*/
|
|
766
|
+
export const prefix: {
|
|
767
|
+
(prefix: HttpRouter.PathInput): <A extends HttpApiEndpoint.All>(self: A) => A
|
|
768
|
+
<A extends HttpApiEndpoint.All>(self: A, prefix: HttpRouter.PathInput): A
|
|
769
|
+
} = dual(2, <A extends HttpApiEndpoint.All>(self: A, prefix: HttpRouter.PathInput): A =>
|
|
770
|
+
makeProto({
|
|
771
|
+
...self as any,
|
|
772
|
+
path: HttpRouter.prefixPath(self.path, prefix)
|
|
773
|
+
}) as A)
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* @since 1.0.0
|
|
777
|
+
* @category reflection
|
|
778
|
+
*/
|
|
779
|
+
export const schemaSuccess = <A extends HttpApiEndpoint.All>(
|
|
780
|
+
self: A
|
|
781
|
+
): Option.Option<Schema.Schema<HttpApiEndpoint.Success<A>, unknown, HttpApiEndpoint.Context<A>>> =>
|
|
782
|
+
HttpApiSchema.isVoid(self.successSchema.ast) ? Option.none() : Option.some(self.successSchema as any)
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Merge the annotations of the endpoint with the provided context.
|
|
786
|
+
*
|
|
787
|
+
* @since 1.0.0
|
|
788
|
+
* @category annotations
|
|
789
|
+
*/
|
|
790
|
+
export const annotateMerge: {
|
|
791
|
+
<I>(context: Context.Context<I>): <A extends HttpApiEndpoint.All>(self: A) => A
|
|
792
|
+
<A extends HttpApiEndpoint.All, I>(self: A, context: Context.Context<I>): A
|
|
793
|
+
} = dual(
|
|
794
|
+
2,
|
|
795
|
+
<A extends HttpApiEndpoint.All, I>(self: A, context: Context.Context<I>): A =>
|
|
796
|
+
makeProto({
|
|
797
|
+
...self as any,
|
|
798
|
+
annotations: Context.merge(self.annotations, context)
|
|
799
|
+
}) as A
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Add an annotation to the endpoint.
|
|
804
|
+
*
|
|
805
|
+
* @since 1.0.0
|
|
806
|
+
* @category annotations
|
|
807
|
+
*/
|
|
808
|
+
export const annotate: {
|
|
809
|
+
<I, S>(tag: Context.Tag<I, S>, value: S): <A extends HttpApiEndpoint.All>(self: A) => A
|
|
810
|
+
<A extends HttpApiEndpoint.All, I, S>(self: A, tag: Context.Tag<I, S>, value: S): A
|
|
811
|
+
} = dual(
|
|
812
|
+
3,
|
|
813
|
+
<A extends HttpApiEndpoint.All, I, S>(self: A, tag: Context.Tag<I, S>, value: S): A =>
|
|
814
|
+
makeProto({
|
|
815
|
+
...self as any,
|
|
816
|
+
annotations: Context.add(self.annotations, tag, value)
|
|
817
|
+
}) as A
|
|
818
|
+
)
|