@resapi/core 0.2.0 → 0.4.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/README.md +1 -1
- package/package.json +1 -1
- package/src/Client.res +4 -4
- package/src/Dispatch.res +2 -2
- package/src/Dispatch.resi +1 -1
- package/src/Endpoint.res +29 -1
- package/src/Endpoint.resi +15 -3
- package/src/Fetch.res +3 -1
package/README.md
CHANGED
|
@@ -8,4 +8,4 @@ npm install @resapi/core
|
|
|
8
8
|
|
|
9
9
|
Add `"@resapi/core"` to `dependencies` in `rescript.json`. Modules are under the `ResApi` namespace.
|
|
10
10
|
|
|
11
|
-
See the [README](https://github.com/Seaside-Logic/resapi#readme) and [API reference](https://github.com/Seaside-Logic/resapi/blob/main/
|
|
11
|
+
See the [README](https://github.com/Seaside-Logic/resapi#readme) and [API reference](https://github.com/Seaside-Logic/resapi/blob/main/site/content/api.md).
|
package/package.json
CHANGED
package/src/Client.res
CHANGED
|
@@ -139,13 +139,13 @@ let requestInit = (
|
|
|
139
139
|
): Fetch.Request.requestInit => {
|
|
140
140
|
let signal = signal->Option.map(Nullable.make)
|
|
141
141
|
switch contract.method {
|
|
142
|
-
| Get => {
|
|
143
|
-
method:
|
|
142
|
+
| Get | Delete => {
|
|
143
|
+
method: Endpoint.methodName(contract.method),
|
|
144
144
|
headers: Fetch.HeadersInit.fromDict(mergeHeaders([client.headers, headers])),
|
|
145
145
|
?signal,
|
|
146
146
|
}
|
|
147
|
-
| Post => {
|
|
148
|
-
method:
|
|
147
|
+
| Post | Put => {
|
|
148
|
+
method: Endpoint.methodName(contract.method),
|
|
149
149
|
headers: Fetch.HeadersInit.fromDict(
|
|
150
150
|
mergeHeaders([client.headers, dict{"content-type": "application/json"}, headers]),
|
|
151
151
|
),
|
package/src/Dispatch.res
CHANGED
|
@@ -36,8 +36,8 @@ let applicationErrorResponse = (contract: Endpoint.t<_, _, _, _>, error) => {
|
|
|
36
36
|
|
|
37
37
|
let readJsonBody = async (contract: Endpoint.t<_, _, _, _>, readBody) =>
|
|
38
38
|
switch contract.method {
|
|
39
|
-
| Get => Ok(JSON.Null)
|
|
40
|
-
| Post =>
|
|
39
|
+
| Get | Delete => Ok(JSON.Null)
|
|
40
|
+
| Post | Put =>
|
|
41
41
|
switch readBody() {
|
|
42
42
|
| Parsed(json) => Ok(json)
|
|
43
43
|
| Text(text) =>
|
package/src/Dispatch.resi
CHANGED
|
@@ -17,7 +17,7 @@ let errorResponse: (
|
|
|
17
17
|
~path: array<string>=?,
|
|
18
18
|
) => response
|
|
19
19
|
|
|
20
|
-
/** `readBody` is called only for POST, after params decode. `handle` must return one of the contract's
|
|
20
|
+
/** `readBody` is called only for POST and PUT, after params decode. `handle` must return one of the contract's
|
|
21
21
|
declared errors. Any exception from a codec, `handle` or reading the body is logged and answered
|
|
22
22
|
with a 500 that reveals nothing. */
|
|
23
23
|
let run: (
|
package/src/Endpoint.res
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// it references no server or runtime code. Server adapters turn contracts into routes.
|
|
3
3
|
// Constructors check the route's params against the params codec and throw on a mismatch (RouteCheck).
|
|
4
4
|
|
|
5
|
-
type method = Get | Post
|
|
5
|
+
type method = Get | Post | Put | Delete
|
|
6
6
|
|
|
7
7
|
type noError
|
|
8
8
|
|
|
@@ -48,6 +48,32 @@ let post = (path, ~params, ~body, ~response) => {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
let put = (path, ~params, ~body, ~response) => {
|
|
52
|
+
RouteCheck.assertValid(path, params)
|
|
53
|
+
{
|
|
54
|
+
method: Put,
|
|
55
|
+
path,
|
|
56
|
+
paramsCodec: params,
|
|
57
|
+
bodyCodec: body,
|
|
58
|
+
responseCodec: response,
|
|
59
|
+
errorCodec: noErrorCodec,
|
|
60
|
+
errorStatus: _ => 500,
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let delete = (path, ~params, ~response) => {
|
|
65
|
+
RouteCheck.assertValid(path, params)
|
|
66
|
+
{
|
|
67
|
+
method: Delete,
|
|
68
|
+
path,
|
|
69
|
+
paramsCodec: params,
|
|
70
|
+
bodyCodec: Codec.unit,
|
|
71
|
+
responseCodec: response,
|
|
72
|
+
errorCodec: noErrorCodec,
|
|
73
|
+
errorStatus: _ => 500,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
51
77
|
let withErrors = (contract: t<'p, 'b, 'r, noError>, errorCodec: Codec.t<'e>, ~status) => {
|
|
52
78
|
...contract,
|
|
53
79
|
errorCodec,
|
|
@@ -62,4 +88,6 @@ let methodName = method =>
|
|
|
62
88
|
switch method {
|
|
63
89
|
| Get => "GET"
|
|
64
90
|
| Post => "POST"
|
|
91
|
+
| Put => "PUT"
|
|
92
|
+
| Delete => "DELETE"
|
|
65
93
|
}
|
package/src/Endpoint.resi
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// A contract describes an endpoint's wire format and is safe to share with clients: it references no
|
|
2
2
|
// server or runtime code. Server adapters turn contracts into routes.
|
|
3
3
|
|
|
4
|
-
type method = Get | Post
|
|
4
|
+
type method = Get | Post | Put | Delete
|
|
5
5
|
|
|
6
6
|
/** The error type of an endpoint that declares no application errors. It has no values, so a handler
|
|
7
7
|
for such an endpoint cannot return `Error(_)`. */
|
|
8
8
|
type noError
|
|
9
9
|
|
|
10
|
-
/** Read-only outside this module: contracts are built with `get`/`post`, which check the route. */
|
|
10
|
+
/** Read-only outside this module: contracts are built with `get`/`post`/`put`/`delete`, which check the route. */
|
|
11
11
|
type t<'params, 'body, 'response, 'error> = private {
|
|
12
12
|
method: method,
|
|
13
13
|
path: string,
|
|
@@ -30,6 +30,18 @@ let post: (
|
|
|
30
30
|
~response: Codec.t<'r>,
|
|
31
31
|
) => t<'p, 'b, 'r, noError>
|
|
32
32
|
|
|
33
|
+
/** Throws if the route's `:params` don't match the params codec (see `RouteCheck`). */
|
|
34
|
+
let put: (
|
|
35
|
+
string,
|
|
36
|
+
~params: Codec.t<'p>,
|
|
37
|
+
~body: Codec.t<'b>,
|
|
38
|
+
~response: Codec.t<'r>,
|
|
39
|
+
) => t<'p, 'b, 'r, noError>
|
|
40
|
+
|
|
41
|
+
/** Like `get`, a DELETE contract has no request body. Throws if the route's `:params` don't match the
|
|
42
|
+
params codec (see `RouteCheck`). */
|
|
43
|
+
let delete: (string, ~params: Codec.t<'p>, ~response: Codec.t<'r>) => t<'p, unit, 'r, noError>
|
|
44
|
+
|
|
33
45
|
/** Declares the endpoint's application errors and the HTTP status (4xx or 5xx) each one is sent with. */
|
|
34
46
|
let withErrors: (t<'p, 'b, 'r, noError>, Codec.t<'e>, ~status: 'e => int) => t<'p, 'b, 'r, 'e>
|
|
35
47
|
|
|
@@ -39,5 +51,5 @@ type any = private {method: method, path: string}
|
|
|
39
51
|
|
|
40
52
|
let any: t<'p, 'b, 'r, 'e> => any
|
|
41
53
|
|
|
42
|
-
/** `"GET"` or `"
|
|
54
|
+
/** `"GET"`, `"POST"`, `"PUT"`, or `"DELETE"`. */
|
|
43
55
|
let methodName: method => string
|
package/src/Fetch.res
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
//
|
|
7
7
|
// Mirrored from rescript-lang/experimental-rescript-webapi main as of 2026-10-11 (alpha build b1d58f9):
|
|
8
8
|
// src/fetch/{Request,Response,Headers,HeadersInit,BodyInit,Fetch}.res, src/event/{AbortSignal,
|
|
9
|
-
// AbortController}.res. Re-checked for 0.
|
|
9
|
+
// AbortController}.res. Re-checked for 0.4.0 against main 4888db2 on 2026-11-15: nothing mirrored here
|
|
10
|
+
// changed (upstream retyped byte streams as Uint8Array and added `type t` aliases to Headers and
|
|
11
|
+
// AbortController).
|
|
10
12
|
// Re-check it at every resAPI release (docs/release-process.md).
|
|
11
13
|
// Abstract types (Headers.t, AbortSignal.t) are subsets of webapi's records: the re-export adds
|
|
12
14
|
// `type t = WebAPI.FetchTypes.headers` and `type t = WebAPI.DOM.abortSignal`.
|