Skip to content

Commit

Permalink
feat: init repo
Browse files Browse the repository at this point in the history
  • Loading branch information
DCKT committed Feb 17, 2024
1 parent 7328c2e commit fbcb065
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ test/bundle/*.js
test/bundle/*.js.gz
promise-*
_release

*.mjs
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,33 @@
# rescript-bindings-template
# rescript-ky

ReScript bindings for ky HTTP client

## Setup

1. Install the module

```bash
bun install @dck/rescript-ky
```

or

```bash
yarn install @dck/rescript-ky
```

or

```bash
npm install @dck/rescript-ky
```

2. Add it to your `rescript.json` config

```json
{
"bsc-flags": ["@dck/rescript-ky"]
}
```

## API
Binary file modified bun.lockb
Binary file not shown.
18 changes: 12 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
"name": "@dck/rescript-bindings-template",
"name": "@dck/rescript-ky",
"version": "0.0.0",
"description": "",
"description": "ReScript bindings for ky HTTP client",
"type": "module",
"keywords": [
"rescript",
"bindings"
"bindings",
"ky"
],
"license": "MIT",
"author": {
Expand All @@ -13,15 +15,19 @@
"url": "https://github.com/DCKT"
},
"peerDependencies": {
"rescript": ">=11.0.0"
"rescript": ">=11.0.0",
"ky": "~1.2.0"
},
"devDependencies": {
"ky": "1.2.0",
"nock": "13.5.1",
"rescript": ">=11.0.0"
},
"scripts": {
"build": "rescript build",
"watch": "rescript build -w",
"clean": "rescript clean"
"dev": "rescript build -w",
"clean": "rescript clean",
"test": "rescript build && retest tests/**/*.mjs"
},
"files": [
"src/*",
Expand Down
19 changes: 18 additions & 1 deletion rescript.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,22 @@
"name": "@dck/rescript-bindings-template",
"uncurried": true,
"namespace": false,
"sources": ["src/js"]
"sources": [
{
"dir": "src",
"subdirs": true
},
{
"dir": "tests",
"type": "dev",
"subdirs": true
}
],
"suffix": ".mjs",
"package-specs": [
{
"module": "es6",
"in-source": true
}
]
}
1 change: 0 additions & 1 deletion src/Bindings.res

This file was deleted.

61 changes: 61 additions & 0 deletions src/Ky.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
type request
type response<'data> = {json: unit => promise<'data>, status: int, url: string, ok: bool}
type error<'data> = {response: option<response<'data>>, request: option<request>, name: string}

type httpMethod =
| GET
| POST
| PUT
| HEAD
| DELETE
| PATCH

type retryMethod =
| GET
| PUT
| HEAD
| DELETE
| OPTIONS
| TRACE

type retryOptions = {
limit?: int,
methods?: array<retryMethod>,
statusCodes?: array<int>,
backoffLimit?: int,
delay?: int => float,
}

type retryCallbackParams = {
request: request,
retryCount: int,
}

type beforeRequestCallback = request => unit
type beforeRetryCallback = retryCallbackParams => unit
type beforeErrorCallback<'data> = error<'data> => unit

type hooks<'errorData> = {
beforeRequest?: array<beforeRequestCallback>,
beforeRetry?: array<beforeRetryCallback>,
beforeError?: array<beforeErrorCallback<'errorData>>,
}

@unboxed
type retry =
| Int(int)
| Options(retryOptions)

type requestOptions<'json, 'searchParams, 'errorData> = {
prefixUrl?: string,
method?: httpMethod,
json?: 'json,
searchParams?: 'searchParams,
retry?: retry,
timeout?: int,
hooks?: hooks<'errorData>,
}

@module("ky")
external fetch: (string, requestOptions<'json, 'searchParams, 'errorData>) => response<'data> =
"default"
46 changes: 46 additions & 0 deletions tests/Simple_test.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
type expect<'a> = {toBe: 'a}
@module("bun:test")
external expect: 'a => expect<'b> = "expect"
@module("bun:test")
external test: (string, unit => unit) => unit = "test"
@module("bun:test")
external testAsync: (string, unit => promise<unit>) => unit = "test"

type mock = {
mockInstance: unit => unit,
path: string,
}

@module("./mock.ts")
external mockBasePath: string = "mockBasePath"

@module("./mock.ts")
external initMockServer: unit => unit = "initMockServer"

initMockServer()

testAsync("Simple fetch", async () => {
let response = await Ky.fetch("", {prefixUrl: mockBasePath, method: GET}).json()

expect(response["test"]).toBe(1)
})

testAsync("Custom retry", async () => {
let response = await Ky.fetch(
`retry`,
{prefixUrl: mockBasePath, method: GET, retry: Int(1)},
).json()

expect(response["retryCount"]).toBe(1)
})

testAsync("Custom timeout", async () => {
try {
await Ky.fetch(`timeout`, {prefixUrl: mockBasePath, method: GET, timeout: 100}).json()
} catch {
| JsError(err) => {
let err: Ky.error<unit> = err->Obj.magic
expect(err.name).toBe("TimeoutError")
}
}
})
28 changes: 28 additions & 0 deletions tests/mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export const mockBasePath = "http://localhost:3000";

let retry = 0;

function wait(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

export const initMockServer = () =>
Bun.serve({
async fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/") return Response.json({ test: 1 });
if (url.pathname === "/timeout") {
await wait(2000);
return Response.json({ test: 1 });
}
if (url.pathname === "/retry") {
if (retry === 0) {
retry = retry + 1;
return new Response("busy !", { status: 429 });
} else {
return Response.json({ retryCount: retry });
}
}
return new Response("404!", { status: 404 });
},
});

0 comments on commit fbcb065

Please sign in to comment.