@colisweb/rescript-toolkit 2.25.1 → 2.27.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/package.json +1 -1
- package/src/mock/MockOverlay.res +43 -0
- package/src/mock/MockOverlay.resi +4 -0
- package/src/mock/index.md +94 -0
- package/src/primitives/Toolkit__Primitives.res +7 -0
- package/src/primitives/index.md +13 -0
- package/src/vendors/Browser.res +2 -0
- package/src/vendors/Browser.resi +1 -0
- package/src/vendors/Msw.res +32 -0
package/package.json
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
let localStorageKey = "@colisweb/mock"
|
|
2
|
+
|
|
3
|
+
@react.component
|
|
4
|
+
let make = (~worker: Msw.worker, ~children) => {
|
|
5
|
+
let (mockEnabled, setMock) = React.useState(() =>
|
|
6
|
+
Browser.LocalStorage.getItem(localStorageKey)
|
|
7
|
+
->Js.Nullable.toOption
|
|
8
|
+
->Option.mapWithDefault(false, bool_of_string)
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
React.useEffect1(() => {
|
|
12
|
+
if mockEnabled {
|
|
13
|
+
worker->Msw.start
|
|
14
|
+
Browser.LocalStorage.setItem(localStorageKey, Js.Nullable.return("true"))
|
|
15
|
+
} else {
|
|
16
|
+
worker->Msw.stop
|
|
17
|
+
Browser.LocalStorage.removeItem(localStorageKey)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
None
|
|
21
|
+
}, [mockEnabled])
|
|
22
|
+
|
|
23
|
+
<React.Suspense fallback={<Toolkit__Ui_SpinnerFullScreen />}>
|
|
24
|
+
<label
|
|
25
|
+
className={`fixed top-2 left-1/2 flex flex-row gap-2 items-center justify-center ${mockEnabled
|
|
26
|
+
? "bg-success-100 border-success-400 text-success-700"
|
|
27
|
+
: "bg-neutral-100"} p-1 border rounded-lg z-50 cursor-pointer`}>
|
|
28
|
+
<span> {"Mock"->React.string} </span>
|
|
29
|
+
<input
|
|
30
|
+
type_={"checkbox"}
|
|
31
|
+
checked={mockEnabled}
|
|
32
|
+
onChange={event => {
|
|
33
|
+
let checked = (event->ReactEvent.Form.target)["checked"]
|
|
34
|
+
|
|
35
|
+
setMock(_ => checked)
|
|
36
|
+
}}
|
|
37
|
+
/>
|
|
38
|
+
</label>
|
|
39
|
+
{children}
|
|
40
|
+
</React.Suspense>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let default = make
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Mock
|
|
2
|
+
|
|
3
|
+
We use [msw](https://mswjs.io) for mocking API content.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
Install the package
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
yarn add msw --dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Wrap the App for dev only
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import React from "react";
|
|
17
|
+
import ReactDOM from "react-dom";
|
|
18
|
+
import "@colisweb/rescript-toolkit/src/ui/styles.css";
|
|
19
|
+
import { make as App } from "../lib/es6_global/src/App.bs";
|
|
20
|
+
import { make as Spinner } from "@colisweb/rescript-toolkit/lib/es6_global/src/ui/Toolkit__Ui_SpinnerFullScreen.bs.js";
|
|
21
|
+
import { make as AppWithMock } from "@colisweb/rescript-toolkit/lib/es6_global/src/mock/AppWithMock.bs";
|
|
22
|
+
|
|
23
|
+
const root = ReactDOM.createRoot(document.getElementById("root"));
|
|
24
|
+
|
|
25
|
+
if (import.meta.env.DEV) {
|
|
26
|
+
import("../lib/es6_global/mocks/Mock.bs").then(({ worker }) => {
|
|
27
|
+
root.render(
|
|
28
|
+
<AppWithMock worker={worker}>
|
|
29
|
+
<App />
|
|
30
|
+
</AppWithMock>
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
root.render(
|
|
35
|
+
<React.Suspense fallback={<Spinner />}>
|
|
36
|
+
<App />
|
|
37
|
+
</React.Suspense>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Define the mock
|
|
43
|
+
|
|
44
|
+
```rescript
|
|
45
|
+
/* Mock_Page_X.res */
|
|
46
|
+
|
|
47
|
+
open Identifiers
|
|
48
|
+
|
|
49
|
+
let mocks = [
|
|
50
|
+
Msw.Rest.get(
|
|
51
|
+
"https://api.url",
|
|
52
|
+
(req, res, ctx) => {
|
|
53
|
+
open ColiswebApi.V5.Transporter.GetContactsWithParameters.Config
|
|
54
|
+
let _emptyResponse = []
|
|
55
|
+
let defaultResponse = [
|
|
56
|
+
{
|
|
57
|
+
id: ContactIdString.make("1"),
|
|
58
|
+
firstName: "Thomas",
|
|
59
|
+
lastName: "Deconinck",
|
|
60
|
+
email: "dck@colisweb.com",
|
|
61
|
+
primaryPhone: "0123456789",
|
|
62
|
+
parameters: {
|
|
63
|
+
id: ParameterId.make("1"),
|
|
64
|
+
email: true,
|
|
65
|
+
sms: true,
|
|
66
|
+
call: true,
|
|
67
|
+
},
|
|
68
|
+
carrier: None,
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
let transporterId = req.params["transporterId"]
|
|
73
|
+
|
|
74
|
+
switch transporterId {
|
|
75
|
+
| "9" => res(Msw.Ctx.json(ctx, defaultResponse))
|
|
76
|
+
| _ => ()
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
),
|
|
80
|
+
Msw.Rest.put(
|
|
81
|
+
"https://api.url",
|
|
82
|
+
(_req, res, ctx) => {
|
|
83
|
+
res(Msw.Ctx.status(ctx, 200))
|
|
84
|
+
},
|
|
85
|
+
),
|
|
86
|
+
]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Define the worker with the mock at the top of your app.
|
|
90
|
+
|
|
91
|
+
```rescript
|
|
92
|
+
/* Mock.res */
|
|
93
|
+
let worker = Msw.setupWorker([]->Array.concat(Mock_Page_X.mocks))
|
|
94
|
+
```
|
|
@@ -4,6 +4,13 @@ module String = {
|
|
|
4
4
|
|
|
5
5
|
@ocaml.doc(" TODO: remove ")
|
|
6
6
|
let join = joinNonEmty
|
|
7
|
+
|
|
8
|
+
let includes = (str1, str2) => {
|
|
9
|
+
str1
|
|
10
|
+
->Js.String2.toLowerCase
|
|
11
|
+
->Js.String2.normalizeByForm("NFD")
|
|
12
|
+
->Js.String2.includes(str2->Js.String2.toLowerCase->Js.String2.normalizeByForm("NFD"))
|
|
13
|
+
}
|
|
7
14
|
}
|
|
8
15
|
|
|
9
16
|
module Option = {
|
package/src/primitives/index.md
CHANGED
|
@@ -8,6 +8,19 @@ Utililties functions for primitives types :
|
|
|
8
8
|
|
|
9
9
|
## API
|
|
10
10
|
|
|
11
|
+
### String
|
|
12
|
+
|
|
13
|
+
#### includes
|
|
14
|
+
|
|
15
|
+
Check if the string is included by setting both strings to lowercase and using `normalize("NFD")`.
|
|
16
|
+
|
|
17
|
+
```rescript
|
|
18
|
+
let search = "aurelie"
|
|
19
|
+
let data = "Aurélie
|
|
20
|
+
|
|
21
|
+
data->Primitives.String.includes(search) // true
|
|
22
|
+
```
|
|
23
|
+
|
|
11
24
|
### Option
|
|
12
25
|
|
|
13
26
|
```rescript
|
package/src/vendors/Browser.res
CHANGED
|
@@ -3,6 +3,8 @@ module LocalStorage = {
|
|
|
3
3
|
external getItem: string => Js.Nullable.t<string> = "localStorage.getItem"
|
|
4
4
|
@val
|
|
5
5
|
external setItem: (string, Js.Nullable.t<string>) => unit = "localStorage.setItem"
|
|
6
|
+
@val
|
|
7
|
+
external removeItem: string => unit = "localStorage.removeItem"
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
module Location = {
|
package/src/vendors/Browser.resi
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
type mock
|
|
2
|
+
type worker
|
|
3
|
+
|
|
4
|
+
@module("msw") @variadic
|
|
5
|
+
external setupWorker: array<mock> => worker = "setupWorker"
|
|
6
|
+
|
|
7
|
+
@send
|
|
8
|
+
external start: worker => unit = "start"
|
|
9
|
+
@send
|
|
10
|
+
external stop: worker => unit = "stop"
|
|
11
|
+
|
|
12
|
+
module Ctx = {
|
|
13
|
+
type t
|
|
14
|
+
|
|
15
|
+
@send
|
|
16
|
+
external json: (t, 'a) => 'b = "json"
|
|
17
|
+
@send
|
|
18
|
+
external status: (t, 'a) => 'b = "status"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module Rest = {
|
|
22
|
+
type req<'params> = {params: 'params}
|
|
23
|
+
|
|
24
|
+
@module("msw") @scope("rest")
|
|
25
|
+
external get: (string, (req<'params>, @uncurry ('z => 't), Ctx.t) => 'a) => mock = "get"
|
|
26
|
+
@module("msw") @scope("rest")
|
|
27
|
+
external put: (string, (req<'params>, @uncurry ('z => 't), Ctx.t) => 'a) => mock = "put"
|
|
28
|
+
@module("msw") @scope("rest")
|
|
29
|
+
external post: (string, (req<'params>, @uncurry ('z => 't), Ctx.t) => 'a) => mock = "post"
|
|
30
|
+
@module("msw") @scope("rest")
|
|
31
|
+
external delete: (string, (req<'params>, @uncurry ('z => 't), Ctx.t) => 'a) => mock = "delete"
|
|
32
|
+
}
|