@colisweb/rescript-toolkit 2.25.0 → 2.26.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colisweb/rescript-toolkit",
3
- "version": "2.25.0",
3
+ "version": "2.26.1",
4
4
  "scripts": {
5
5
  "clean": "rescript clean",
6
6
  "build": "rescript build",
@@ -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,4 @@
1
+ // @react.component
2
+ // let make: (~worker: Msw.worker, ~children: React.element) => React.element
3
+
4
+ let default: {"children": React.element, "worker": Msw.worker} => React.element
@@ -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
+ ```
@@ -7,6 +7,7 @@ type item = {
7
7
  icon: React.element,
8
8
  label: React.element,
9
9
  onClick: unit => unit,
10
+ className: string,
10
11
  }
11
12
 
12
13
  @react.component
@@ -142,12 +143,13 @@ let make = (
142
143
  isXs ? "bg-white p-2 mx-2 shadow rounded-t-lg" : "",
143
144
  ])}>
144
145
  {items
145
- ->Array.mapWithIndex((i, {icon, label, onClick}) => {
146
+ ->Array.mapWithIndex((i, {icon, label, onClick, className}) => {
146
147
  <div
147
148
  onClick={_ => onClick()}
148
149
  className={cx([
149
150
  "flex flex-row gap-4 items-center py-2 hover:bg-neutral-100 focus:bg-neutral-100 cursor-pointer",
150
151
  i == 0 ? "" : "border-t",
152
+ className,
151
153
  ])}
152
154
  key={i->Int.toString}>
153
155
  {icon} {label}
@@ -7,6 +7,7 @@ type item = {
7
7
  icon: React.element,
8
8
  label: React.element,
9
9
  onClick: unit => unit,
10
+ className: string,
10
11
  }
11
12
 
12
13
  @react.component
@@ -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 = {
@@ -1,6 +1,7 @@
1
1
  module LocalStorage: {
2
2
  let getItem: string => Js.Nullable.t<string>
3
3
  let setItem: (string, Js.Nullable.t<string>) => unit
4
+ let removeItem: string => unit
4
5
  }
5
6
 
6
7
  module Location: {
@@ -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
+ }