@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colisweb/rescript-toolkit",
3
- "version": "2.25.1",
3
+ "version": "2.27.0",
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
+ ```
@@ -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 = {
@@ -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
@@ -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
+ }