@monarcode/effetch 0.1.0-alpha.1 → 0.1.0-alpha.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  All notable changes to `@monarcode/effetch`, newest first.
4
4
 
5
+ ## 0.1.0-alpha.2
6
+
7
+ ### Changed
8
+
9
+ - `make`'s `error` option is now `defaultError`, so it reads differently from
10
+ a call's `error`, which replaces it.
11
+
12
+ ### Fixed
13
+
14
+ - `query` now accepts values typed with an `interface`. Each property is
15
+ still checked, so a `Date`, a nested object or a function is rejected. The
16
+ new `QueryOf<Q>` type is the constraint; `QueryInput` is unchanged, and the
17
+ option types (`BaseOptions`, `NoBodyRequestOptions`, `RequestOptions`) take
18
+ an optional trailing `Q` parameter that defaults to it.
19
+ - `HttpError.status` and `DecodeError.status` use `Schema.Finite` instead of
20
+ `Schema.Number`. The value is still a `number`, as before.
21
+
22
+ ### Documentation
23
+
24
+ - Examples use `Schema.Finite` instead of `Schema.Number`. Through the JSON
25
+ codec, `Schema.Number` decodes `"NaN"`, `"Infinity"` and `"-Infinity"`
26
+ strings into numbers and encodes them back as strings.
27
+
5
28
  ## 0.1.0-alpha.1
6
29
 
7
30
  First release published from CI with npm provenance. No changes to the
package/README.md CHANGED
@@ -20,7 +20,7 @@ import type * as Fetch from "@monarcode/effetch";
20
20
 
21
21
  declare const api: Fetch.Client;
22
22
 
23
- const Todo = Schema.Struct({ id: Schema.Number, title: Schema.String });
23
+ const Todo = Schema.Struct({ id: Schema.Finite, title: Schema.String });
24
24
 
25
25
  const todo = api.get("/todos/:id", { params: { id: 1 }, output: Todo });
26
26
  // Effect<{ readonly id: number; readonly title: string },
@@ -98,7 +98,7 @@ import * as Schema from "effect/Schema";
98
98
  import * as Fetch from "@monarcode/effetch";
99
99
 
100
100
  const Todo = Schema.Struct({
101
- id: Schema.Number,
101
+ id: Schema.Finite,
102
102
  title: Schema.String,
103
103
  completed: Schema.Boolean,
104
104
  });
@@ -141,7 +141,7 @@ const session: { accessToken?: string } = {};
141
141
  const make = Fetch.make({
142
142
  baseUrl: Config.String("API_URL"),
143
143
  headers: { "x-client": "web" },
144
- error: ApiError,
144
+ defaultError: ApiError,
145
145
  plugins: [
146
146
  logger(),
147
147
  retry(),
@@ -159,12 +159,12 @@ export const ApiLive = Layer.effect(Api)(make).pipe(
159
159
  );
160
160
  ```
161
161
 
162
- | Option | Description |
163
- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
164
- | `baseUrl` | Prepended to every path that isn't an absolute `http(s)://` URL. A string, or an Effect run once when the client is made (a `Config` works). It can't contain a query string or a fragment. |
165
- | `headers` | Sent with every request. A call's header of the same name wins. `content-type` and `content-length` are ignored here: they come from each body. |
166
- | `error` | The default schema for non-2xx response bodies (see [Errors](#errors)). |
167
- | `plugins` | See [Plugins](#plugins). The first one is the outermost. |
162
+ | Option | Description |
163
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
164
+ | `baseUrl` | Prepended to every path that isn't an absolute `http(s)://` URL. A string, or an Effect run once when the client is made (a `Config` works). It can't contain a query string or a fragment. |
165
+ | `headers` | Sent with every request. A call's header of the same name wins. `content-type` and `content-length` are ignored here: they come from each body. |
166
+ | `defaultError` | The schema for non-2xx response bodies of calls without their own `error` (see [Errors](#errors)). |
167
+ | `plugins` | See [Plugins](#plugins). The first one is the outermost. |
168
168
 
169
169
  The client holds on to the `HttpClient`, the `baseUrl` and the services its
170
170
  plugins need. Its calls need nothing from the environment, apart from the
@@ -181,7 +181,7 @@ import type * as Fetch from "@monarcode/effetch";
181
181
  declare const api: Fetch.Client;
182
182
 
183
183
  const Todo = Schema.Struct({
184
- id: Schema.Number,
184
+ id: Schema.Finite,
185
185
  title: Schema.String,
186
186
  done: Schema.Boolean,
187
187
  due: Schema.Date,
@@ -237,6 +237,11 @@ options)` do.
237
237
  An empty 2xx body (204, `HEAD`) decodes as JSON `null`: use `Schema.Void` for
238
238
  endpoints that return nothing.
239
239
 
240
+ Use `Schema.Finite` rather than `Schema.Number` for numbers. Schemas go through
241
+ Effect's JSON codec, where `Schema.Number` also decodes the strings `"NaN"`,
242
+ `"Infinity"` and `"-Infinity"`, and encodes those values back to strings.
243
+ `Schema.Finite` accepts every JSON number and rejects the rest.
244
+
240
245
  `client.httpClient` is the configured `HttpClient` underneath: base URL,
241
246
  default headers and plugins, but no status check and no decoding. Use it for
242
247
  anything the methods don't cover, such as streaming a response.
@@ -255,7 +260,7 @@ anything the methods don't cover, such as streaming a response.
255
260
  - `HttpError.headers` are Effect `Headers`: `authorization`, `set-cookie` and
256
261
  other sensitive headers print as `<redacted>`.
257
262
  - `HttpError.text` is the raw body. `body` is the body decoded with the
258
- `error` schema, `undefined` if it didn't match, or the parsed JSON when
263
+ call's `error` schema (or the client's `defaultError`), `undefined` if it didn't match, or the parsed JSON when
259
264
  there's no schema. Reading it never fails the call.
260
265
 
261
266
  ```ts
@@ -266,7 +271,7 @@ import type * as Fetch from "@monarcode/effetch";
266
271
 
267
272
  declare const api: Fetch.Client;
268
273
 
269
- const Todo = Schema.Struct({ id: Schema.Number, title: Schema.String });
274
+ const Todo = Schema.Struct({ id: Schema.Finite, title: Schema.String });
270
275
  const ApiError = Schema.Struct({ code: Schema.String });
271
276
 
272
277
  export const todo = (id: number) =>
@@ -480,7 +485,7 @@ import * as Schema from "effect/Schema";
480
485
 
481
486
  import * as Fetch from "@monarcode/effetch";
482
487
 
483
- const Todo = Schema.Struct({ id: Schema.Number, title: Schema.String });
488
+ const Todo = Schema.Struct({ id: Schema.Finite, title: Schema.String });
484
489
 
485
490
  const sent: Array<string> = [];
486
491
 
@@ -571,10 +576,10 @@ page's URL.
571
576
  [writing plugins](#writing-a-plugin).
572
577
  - Option and result types, for wrapping the client in your own functions:
573
578
  `RequestOptions`, `NoBodyRequestOptions`, `BaseOptions`, `BodyOptions`,
574
- `ParamsOption`, `QueryInput`, `QueryValue`, `AnySchema`, `Args`,
575
- `Success`, `CallError`, `CallServices`, `CallEffect`, `NoBodyMethod`,
576
- `BodyMethod`, `RequestMethod`, `PathParamNames`, `PathParams`,
577
- `PathParamValue`.
579
+ `ParamsOption`, `QueryInput`, `QueryOf`, `QueryValue`, `AnySchema`,
580
+ `Args`, `Success`, `CallError`, `CallServices`, `CallEffect`,
581
+ `NoBodyMethod`, `BodyMethod`, `RequestMethod`, `PathParamNames`,
582
+ `PathParams`, `PathParamValue`.
578
583
 
579
584
  `@monarcode/effetch/plugins`:
580
585
 
package/dist/Client.d.ts CHANGED
@@ -25,8 +25,8 @@ import { Plugin } from "./Plugin.js";
25
25
  * `content-type` on a call to override it). When a call has an `output`
26
26
  * schema, effetch sends `Accept: application/json` unless an `accept`
27
27
  * header is set here or on the call.
28
- * - `error`: the default schema for non-2xx response bodies. A call's own
29
- * `error` option replaces it.
28
+ * - `defaultError`: the schema for non-2xx response bodies of calls that
29
+ * don't pass their own `error` option. A call's `error` replaces it.
30
30
  * - `plugins`: hooks into every call (see {@link Plugin}). `plugins[0]` is
31
31
  * the outermost layer: its `onRequest` runs first and its `onResponse`
32
32
  * last. Names must be unique. Pass the list inline: annotating it as
@@ -51,7 +51,7 @@ import { Plugin } from "./Plugin.js";
51
51
  * const make = Fetch.make({
52
52
  * baseUrl: Config.String("API_URL"),
53
53
  * headers: { accept: "application/json" },
54
- * error: ApiError,
54
+ * defaultError: ApiError,
55
55
  * plugins: [apiKey],
56
56
  * });
57
57
  * ```
@@ -68,8 +68,8 @@ export interface ClientConfig<
68
68
  readonly baseUrl?: string | Effect.Effect<string, BaseE, BaseR> | undefined;
69
69
  /** Headers sent with every request. */
70
70
  readonly headers?: Headers.Input | undefined;
71
- /** Default schema for non-2xx response bodies. */
72
- readonly error?: EB | undefined;
71
+ /** Schema for non-2xx response bodies, unless a call passes its own `error`. */
72
+ readonly defaultError?: EB | undefined;
73
73
  /** Plugins, outermost first. Names must be unique. */
74
74
  readonly plugins?: Ps | undefined;
75
75
  }
@@ -79,7 +79,7 @@ export interface ClientConfig<
79
79
  * can fail with the plugins' errors on top of effetch's own.
80
80
  *
81
81
  * - `Ps`: the plugins the client was made with.
82
- * - `EB`: the client's default `error` schema.
82
+ * - `EB`: the client's `defaultError` schema.
83
83
  *
84
84
  * @example
85
85
  * ```ts
@@ -87,7 +87,7 @@ export interface ClientConfig<
87
87
  * import * as Schema from "effect/Schema";
88
88
  * import * as Fetch from "@monarcode/effetch";
89
89
  *
90
- * const Todo = Schema.Struct({ id: Schema.Number, title: Schema.String });
90
+ * const Todo = Schema.Struct({ id: Schema.Finite, title: Schema.String });
91
91
  *
92
92
  * const program = (api: Fetch.Client) =>
93
93
  * api.get("/todos/:id", { params: { id: 1 }, output: Todo }).pipe(
@@ -140,7 +140,7 @@ export interface Client<
140
140
  * import * as Schema from "effect/Schema";
141
141
  * import * as Fetch from "@monarcode/effetch";
142
142
  *
143
- * const Todo = Schema.Struct({ id: Schema.Number, done: Schema.Boolean });
143
+ * const Todo = Schema.Struct({ id: Schema.Finite, done: Schema.Boolean });
144
144
  *
145
145
  * const complete = (api: Fetch.Client, id: number) =>
146
146
  * api.request("PATCH", "/todos/:id", {
@@ -159,7 +159,7 @@ export interface Client<
159
159
  * import * as Schema from "effect/Schema";
160
160
  * import * as Fetch from "@monarcode/effetch";
161
161
  *
162
- * const Todo = Schema.Struct({ id: Schema.Number, title: Schema.String });
162
+ * const Todo = Schema.Struct({ id: Schema.Finite, title: Schema.String });
163
163
  *
164
164
  * const list = (api: Fetch.Client) =>
165
165
  * api.get("/todos", {
@@ -212,7 +212,7 @@ export interface Client<
212
212
  * import * as Fetch from "@monarcode/effetch";
213
213
  *
214
214
  * const NewTodo = Schema.Struct({ title: Schema.String, due: Schema.Date });
215
- * const Todo = Schema.Struct({ id: Schema.Number, title: Schema.String });
215
+ * const Todo = Schema.Struct({ id: Schema.Finite, title: Schema.String });
216
216
  *
217
217
  * const create = (api: Fetch.Client) =>
218
218
  * api.post("/todos", {
@@ -238,7 +238,7 @@ export interface Client<
238
238
  * import * as Schema from "effect/Schema";
239
239
  * import * as Fetch from "@monarcode/effetch";
240
240
  *
241
- * const Todo = Schema.Struct({ id: Schema.Number, title: Schema.String });
241
+ * const Todo = Schema.Struct({ id: Schema.Finite, title: Schema.String });
242
242
  *
243
243
  * const replace = (api: Fetch.Client, todo: typeof Todo.Type) =>
244
244
  * api.put("/todos/:id", {
@@ -259,7 +259,7 @@ export interface Client<
259
259
  * import * as Schema from "effect/Schema";
260
260
  * import * as Fetch from "@monarcode/effetch";
261
261
  *
262
- * const Todo = Schema.Struct({ id: Schema.Number, done: Schema.Boolean });
262
+ * const Todo = Schema.Struct({ id: Schema.Finite, done: Schema.Boolean });
263
263
  *
264
264
  * const complete = (api: Fetch.Client, id: number) =>
265
265
  * api.patch("/todos/:id", {
package/dist/Client.js CHANGED
@@ -87,7 +87,7 @@ const make = (config = {}) => Effect.gen(function* () {
87
87
  const chain = applyPlugins(mapClientErrors(provided), plugins, context);
88
88
  const httpClient = HttpClient.mapRequestInput(HttpClient.transformResponse(chain, provideOverrides(void 0)), applyDefaults);
89
89
  const call = makeCall({
90
- errorSchema: config.error,
90
+ errorSchema: config.defaultError,
91
91
  applyDefaults,
92
92
  chain,
93
93
  plugins,
package/dist/Errors.d.ts CHANGED
@@ -46,7 +46,7 @@ declare const HttpError_base: Schema.Class<
46
46
  {
47
47
  readonly method: Schema.String;
48
48
  readonly url: Schema.String;
49
- readonly status: Schema.Number;
49
+ readonly status: Schema.Finite;
50
50
  readonly headers: Schema.declare<Headers.Headers, unknown>;
51
51
  readonly text: Schema.String;
52
52
  readonly body: Schema.Unknown;
@@ -68,7 +68,8 @@ declare const HttpError_base: Schema.Class<
68
68
  * sensitive ones (`set-cookie`, `authorization`, …) print as
69
69
  * `<redacted>` when the error is logged or serialised.
70
70
  * - `text` is always the raw response body (`""` if it couldn't be read).
71
- * - `body` is the body decoded with the call's (or client's) `error` schema,
71
+ * - `body` is the body decoded with the call's `error` schema (or the client's
72
+ * `defaultError`),
72
73
  * or `undefined` if it didn't match. Without an `error` schema, `body` is
73
74
  * the parsed JSON when `text` is valid JSON, else `undefined`. An empty
74
75
  * body is always `undefined`. Reading `body` never fails the call.
@@ -140,7 +141,7 @@ declare const DecodeError_base: Schema.Class<
140
141
  {
141
142
  readonly method: Schema.String;
142
143
  readonly url: Schema.String;
143
- readonly status: Schema.Number;
144
+ readonly status: Schema.Finite;
144
145
  readonly issue: Schema.Unknown;
145
146
  readonly message: Schema.String;
146
147
  }
package/dist/Errors.js CHANGED
@@ -48,7 +48,8 @@ var NetworkError = class extends Schema.TaggedError()("NetworkError", {
48
48
  * sensitive ones (`set-cookie`, `authorization`, …) print as
49
49
  * `<redacted>` when the error is logged or serialised.
50
50
  * - `text` is always the raw response body (`""` if it couldn't be read).
51
- * - `body` is the body decoded with the call's (or client's) `error` schema,
51
+ * - `body` is the body decoded with the call's `error` schema (or the client's
52
+ * `defaultError`),
52
53
  * or `undefined` if it didn't match. Without an `error` schema, `body` is
53
54
  * the parsed JSON when `text` is valid JSON, else `undefined`. An empty
54
55
  * body is always `undefined`. Reading `body` never fails the call.
@@ -80,7 +81,7 @@ var NetworkError = class extends Schema.TaggedError()("NetworkError", {
80
81
  var HttpError = class extends Schema.TaggedError()("HttpError", {
81
82
  method: Schema.String,
82
83
  url: Schema.String,
83
- status: Schema.Number,
84
+ status: Schema.Finite,
84
85
  headers: Schema.declare(Headers.isHeaders),
85
86
  text: Schema.String,
86
87
  body: Schema.Unknown
@@ -124,7 +125,7 @@ var HttpError = class extends Schema.TaggedError()("HttpError", {
124
125
  var DecodeError = class extends Schema.TaggedError()("DecodeError", {
125
126
  method: Schema.String,
126
127
  url: Schema.String,
127
- status: Schema.Number,
128
+ status: Schema.Finite,
128
129
  issue: Schema.Unknown,
129
130
  message: Schema.String
130
131
  }) {};
package/dist/Options.d.ts CHANGED
@@ -46,6 +46,33 @@ export type QueryValue = UrlParams.Coercible;
46
46
  export type QueryInput = {
47
47
  readonly [key: string]: QueryValue | ReadonlyArray<QueryValue>;
48
48
  };
49
+ /**
50
+ * The constraint on a `query` of type `Q`: each of `Q`'s own properties must
51
+ * be a {@link QueryValue} or an array of them.
52
+ *
53
+ * Unlike {@link QueryInput}, this has no index signature, so it also accepts
54
+ * values typed with an `interface` (TypeScript never gives interfaces an
55
+ * implicit index signature).
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * import type * as Fetch from "@monarcode/effetch";
60
+ *
61
+ * interface ListTodosParams {
62
+ * readonly limit: number;
63
+ * readonly tags?: ReadonlyArray<string> | undefined;
64
+ * }
65
+ *
66
+ * declare const params: ListTodosParams;
67
+ *
68
+ * const query: Fetch.QueryOf<ListTodosParams> = params;
69
+ * ```
70
+ *
71
+ * @since 0.1.0
72
+ */
73
+ export type QueryOf<Q> = {
74
+ readonly [K in keyof Q]: QueryValue | ReadonlyArray<QueryValue>;
75
+ };
49
76
  /**
50
77
  * Any Effect schema accepted by the `output`, `error` and `input` options.
51
78
  *
@@ -54,7 +81,7 @@ export type QueryInput = {
54
81
  * import * as Schema from "effect/Schema";
55
82
  * import type * as Fetch from "@monarcode/effetch";
56
83
  *
57
- * const Todo: Fetch.AnySchema = Schema.Struct({ id: Schema.Number });
84
+ * const Todo: Fetch.AnySchema = Schema.Struct({ id: Schema.Finite });
58
85
  * ```
59
86
  *
60
87
  * @since 0.1.0
@@ -98,13 +125,15 @@ export type ParamsOption<P extends string> = string extends P
98
125
  * - `O`: the `output` schema, or `undefined` for the raw response.
99
126
  * - `EB`: the `error` schema for non-2xx bodies.
100
127
  * - `Ps`: the client's plugins, for the `plugins` override map.
128
+ * - `Q`: the type of `query`, checked with {@link QueryOf}. Defaults to
129
+ * {@link QueryInput}.
101
130
  *
102
131
  * @example
103
132
  * ```ts
104
133
  * import * as Schema from "effect/Schema";
105
134
  * import type * as Fetch from "@monarcode/effetch";
106
135
  *
107
- * const Todo = Schema.Struct({ id: Schema.Number });
136
+ * const Todo = Schema.Struct({ id: Schema.Finite });
108
137
  *
109
138
  * const options: Fetch.BaseOptions<typeof Todo, Schema.Unknown, []> = {
110
139
  * query: { expand: "owner" },
@@ -119,9 +148,10 @@ export interface BaseOptions<
119
148
  O extends AnySchema | undefined,
120
149
  EB extends AnySchema,
121
150
  Ps extends ReadonlyArray<Plugin.Any>,
151
+ Q extends QueryOf<Q> = QueryInput,
122
152
  > {
123
153
  /** Query parameters. Arrays repeat the key; `null`/`undefined` are dropped. */
124
- readonly query?: QueryInput | undefined;
154
+ readonly query?: Q | undefined;
125
155
  /** Headers for this call, merged over the client's headers. */
126
156
  readonly headers?: Headers.Input | undefined;
127
157
  /**
@@ -198,8 +228,9 @@ export type NoBodyRequestOptions<
198
228
  O extends AnySchema | undefined,
199
229
  EB extends AnySchema,
200
230
  Ps extends ReadonlyArray<Plugin.Any>,
231
+ Q extends QueryOf<Q> = QueryInput,
201
232
  > = ParamsOption<P> &
202
- BaseOptions<O, EB, Ps> & {
233
+ BaseOptions<O, EB, Ps, Q> & {
203
234
  readonly body?: undefined;
204
235
  readonly input?: undefined;
205
236
  };
@@ -225,7 +256,8 @@ export type RequestOptions<
225
256
  EB extends AnySchema,
226
257
  I extends AnySchema,
227
258
  Ps extends ReadonlyArray<Plugin.Any>,
228
- > = ParamsOption<P> & BaseOptions<O, EB, Ps> & BodyOptions<I>;
259
+ Q extends QueryOf<Q> = QueryInput,
260
+ > = ParamsOption<P> & BaseOptions<O, EB, Ps, Q> & BodyOptions<I>;
229
261
  /**
230
262
  * The rest arguments after the path: the options object `T` is required
231
263
  * when path `P` has parameters, optional otherwise.
@@ -254,7 +286,7 @@ export type Args<P extends string, T> = [PathParamNames<P>] extends [never]
254
286
  * import * as Schema from "effect/Schema";
255
287
  * import type * as Fetch from "@monarcode/effetch";
256
288
  *
257
- * type Todo = Fetch.Success<Schema.Struct<{ id: Schema.Number }>>;
289
+ * type Todo = Fetch.Success<Schema.Struct<{ id: Schema.Finite }>>;
258
290
  * // ^? { readonly id: number }
259
291
  * ```
260
292
  *
@@ -274,7 +306,7 @@ export type Success<O extends AnySchema | undefined> = O extends AnySchema
274
306
  * import type * as Fetch from "@monarcode/effetch";
275
307
  *
276
308
  * type E = Fetch.CallError<
277
- * Schema.Struct<{ id: Schema.Number }>,
309
+ * Schema.Struct<{ id: Schema.Finite }>,
278
310
  * Schema.Struct<{ code: Schema.String }>,
279
311
  * []
280
312
  * >;
@@ -302,7 +334,7 @@ export type CallError<
302
334
  * import type * as Fetch from "@monarcode/effetch";
303
335
  *
304
336
  * type R = Fetch.CallServices<
305
- * Schema.Struct<{ id: Schema.Number }>,
337
+ * Schema.Struct<{ id: Schema.Finite }>,
306
338
  * Schema.Unknown,
307
339
  * Schema.Unknown
308
340
  * >;
@@ -334,7 +366,7 @@ export type CallServices<
334
366
  * import type * as Fetch from "@monarcode/effetch";
335
367
  *
336
368
  * type Call = Fetch.CallEffect<
337
- * Schema.Struct<{ id: Schema.Number }>,
369
+ * Schema.Struct<{ id: Schema.Finite }>,
338
370
  * Schema.Unknown,
339
371
  * Schema.Unknown,
340
372
  * []
@@ -354,7 +386,8 @@ export type CallEffect<
354
386
  * The signature of `get`, `head` and `options`: no `body` or `input`.
355
387
  *
356
388
  * - `Ps`: the client's plugins.
357
- * - `DefaultEB`: the client's `error` schema, used when a call has none.
389
+ * - `DefaultEB`: the client's `defaultError` schema, used when a call has
390
+ * no `error`.
358
391
  *
359
392
  * @example
360
393
  * ```ts
@@ -363,7 +396,7 @@ export type CallEffect<
363
396
  *
364
397
  * declare const get: Fetch.NoBodyMethod<[], Schema.Unknown>;
365
398
  *
366
- * const Todo = Schema.Struct({ id: Schema.Number });
399
+ * const Todo = Schema.Struct({ id: Schema.Finite });
367
400
  * const todo = get("/todos/:id", { params: { id: 1 }, output: Todo });
368
401
  * ```
369
402
  *
@@ -377,9 +410,10 @@ export interface NoBodyMethod<
377
410
  P extends string,
378
411
  O extends AnySchema | undefined = undefined,
379
412
  EB extends AnySchema = DefaultEB,
413
+ Q extends QueryOf<Q> = QueryInput,
380
414
  >(
381
415
  path: P,
382
- ...args: Args<P, NoBodyRequestOptions<P, O, EB, Ps>>
416
+ ...args: Args<P, NoBodyRequestOptions<P, O, EB, Ps, Q>>
383
417
  ): CallEffect<O, EB, Schema.Unknown, Ps>;
384
418
  }
385
419
  /**
@@ -387,7 +421,8 @@ export interface NoBodyMethod<
387
421
  * typed by `input` when given.
388
422
  *
389
423
  * - `Ps`: the client's plugins.
390
- * - `DefaultEB`: the client's `error` schema, used when a call has none.
424
+ * - `DefaultEB`: the client's `defaultError` schema, used when a call has
425
+ * no `error`.
391
426
  *
392
427
  * @example
393
428
  * ```ts
@@ -396,7 +431,7 @@ export interface NoBodyMethod<
396
431
  *
397
432
  * declare const patch: Fetch.BodyMethod<[], Schema.Unknown>;
398
433
  *
399
- * const Todo = Schema.Struct({ id: Schema.Number, done: Schema.Boolean });
434
+ * const Todo = Schema.Struct({ id: Schema.Finite, done: Schema.Boolean });
400
435
  * const updated = patch("/todos/:id", {
401
436
  * params: { id: 1 },
402
437
  * body: { done: true },
@@ -415,9 +450,10 @@ export interface BodyMethod<
415
450
  O extends AnySchema | undefined = undefined,
416
451
  EB extends AnySchema = DefaultEB,
417
452
  I extends AnySchema = Schema.Unknown,
453
+ Q extends QueryOf<Q> = QueryInput,
418
454
  >(
419
455
  path: P,
420
- ...args: Args<P, RequestOptions<P, O, EB, I, Ps>>
456
+ ...args: Args<P, RequestOptions<P, O, EB, I, Ps, Q>>
421
457
  ): CallEffect<O, EB, I, Ps>;
422
458
  }
423
459
  /**
@@ -425,7 +461,8 @@ export interface BodyMethod<
425
461
  * `input` when given.
426
462
  *
427
463
  * - `Ps`: the client's plugins.
428
- * - `DefaultEB`: the client's `error` schema, used when a call has none.
464
+ * - `DefaultEB`: the client's `defaultError` schema, used when a call has
465
+ * no `error`.
429
466
  *
430
467
  * @example
431
468
  * ```ts
@@ -434,7 +471,7 @@ export interface BodyMethod<
434
471
  *
435
472
  * declare const request: Fetch.RequestMethod<[], Schema.Unknown>;
436
473
  *
437
- * const Todo = Schema.Struct({ id: Schema.Number, done: Schema.Boolean });
474
+ * const Todo = Schema.Struct({ id: Schema.Finite, done: Schema.Boolean });
438
475
  * const updated = request("PATCH", "/todos/:id", {
439
476
  * params: { id: 1 },
440
477
  * body: { done: true },
@@ -453,10 +490,11 @@ export interface RequestMethod<
453
490
  O extends AnySchema | undefined = undefined,
454
491
  EB extends AnySchema = DefaultEB,
455
492
  I extends AnySchema = Schema.Unknown,
493
+ Q extends QueryOf<Q> = QueryInput,
456
494
  >(
457
495
  method: HttpMethod.HttpMethod,
458
496
  path: P,
459
- ...args: Args<P, RequestOptions<P, O, EB, I, Ps>>
497
+ ...args: Args<P, RequestOptions<P, O, EB, I, Ps, Q>>
460
498
  ): CallEffect<O, EB, I, Ps>;
461
499
  }
462
500
  //#endregion
package/dist/index.d.ts CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  NoBodyRequestOptions,
20
20
  ParamsOption,
21
21
  QueryInput,
22
+ QueryOf,
22
23
  QueryValue,
23
24
  RequestMethod,
24
25
  RequestOptions,
@@ -50,6 +51,7 @@ export {
50
51
  type Plugin,
51
52
  type PluginContext,
52
53
  type QueryInput,
54
+ type QueryOf,
53
55
  type QueryValue,
54
56
  type RequestMethod,
55
57
  type RequestOptions,
@@ -61,7 +61,7 @@ const encodePlain = (body) => {
61
61
  * `Invalid request body:` and whose `cause` is the underlying error.
62
62
  */
63
63
  const encodeBody = (body, input) => {
64
- if (body === void 0) return Effect.succeed(void 0);
64
+ if (body === void 0) return Effect.undefined;
65
65
  if (input !== void 0) return orDieInvalid(HttpBody.jsonSchema(input)(body));
66
66
  return encodePlain(body);
67
67
  };
@@ -17,7 +17,7 @@ const readErrorBody = (text, schema) => {
17
17
  try {
18
18
  json = parseBody(text);
19
19
  } catch {
20
- return Effect.succeed(void 0);
20
+ return Effect.undefined;
21
21
  }
22
22
  if (json === void 0 || schema === void 0) return Effect.succeed(json);
23
23
  return Effect.orElseSucceed(decodeJson(schema)(json), () => void 0);
@@ -27,14 +27,14 @@ function checkStatus(response, errorSchema) {
27
27
  return Effect.gen(function* () {
28
28
  const text = yield* Effect.orElseSucceed(response.text, () => "");
29
29
  const body = yield* readErrorBody(text, errorSchema);
30
- return yield* Effect.fail(new HttpError({
30
+ return yield* new HttpError({
31
31
  method: response.request.method,
32
32
  url: errorUrl(response.request.url),
33
33
  status: response.status,
34
34
  headers: response.headers,
35
35
  text,
36
36
  body
37
- }));
37
+ });
38
38
  });
39
39
  }
40
40
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monarcode/effetch",
3
- "version": "0.1.0-alpha.1",
3
+ "version": "0.1.0-alpha.2",
4
4
  "description": "Typed, schema-driven HTTP calls on Effect v4's HttpClient: path params, object queries, decoded responses and plugins",
5
5
  "keywords": [
6
6
  "effect",