@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 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/docs/api.md).
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resapi/core",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Type-safe HTTP contracts for ReScript: endpoint contracts, codecs and a typed client.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://resapi.dev",
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: "GET",
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: "POST",
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 `"POST"`. */
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.2.0 against main b46bc2c on 2026-10-11: those files are unchanged.
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`.