git.iko.soy/rowtype-yoga/purescript-lazy-joe
on main help sign in
Initial commit
commit7ac025a4ac28eefb00f2ba9423ec86445a5ec473 authorsigma-andex <77549848+sigma-andex@users.noreply.github.com> dateThu 16 Jun 2022, 22:20 (4 years ago) parentbcc6b24
12 files changed+1145−71
LICENSE+16 README.md+168 assets/blau-azul.png assets/green-leaf.png assets/purple-kite.png assets/red-velvet.png package-lock.json+689−2 package.json+3−1 spago.dhall+3−2 src/Lazy/Joe.js+61−40 src/Lazy/Joe.purs+174−10 test/Main.purs+31−16
LICENSEnew file+16
@@ -0,0 +1,16 @@
1+MIT No Attribution
2+
3+Copyright 2021 Jan Schulte
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy of this
6+software and associated documentation files (the "Software"), to deal in the Software
7+without restriction, including without limitation the rights to use, copy, modify,
8+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
9+permit persons to whom the Software is furnished to do so.
10+
11+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
12+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
13+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
14+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
15+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
16+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
README.md+168
@@ -1,2 +1,170 @@
11# 🎷 purescript-lazy-joe 🦥
22
3+A purescript library for these days when you got the blues and are just too lazy to write ffi code.
4+
5+`lazy-joe` let's you ffi your js library without having to write the typical purescript ffi boilerplate.
6+
7+## ToC
8+* [Installation](#installation)
9+* [Usage](#usage)
10+ * [Method chaining](#method-chaining)
11+ * [Uncurried](#uncurried)
12+ * [Varargs](#varargs)
13+ * [Scoped](#scoped)
14+ * [Effectful](#effectful)
15+* [Credits](#credits)
16+
17+## Installation
18+
19+```
20+spago install lazy-joe
21+```
22+
23+## Usage
24+
25+Imagine we want to use the amazing [`chalk`](https://github.com/chalk/chalk) js library for terminal styling in our purescript code.
26+
27+We start by installing chalk.
28+```
29+npm install chalk
30+```
31+
32+`chalk` defines a number of functions and combinators that allow you to write coloured text to your terminal. For instance the function `red` from `chalk` prints a red string. In js you would use it like this:
33+
34+```js
35+import chalk from 'chalk';
36+
37+console.log(chalk.red("Red velvet 🎂"));
38+```
39+
40+Let's see how we can ffi this in our purescript code:
41+
42+```purescript
43+main :: Effect Unit
44+main = launchAff_ do
45+ { red } <- fromDefault "chalk"
46+ log $ red "Red velvet 🎂"
47+```
48+Running it will print:
49+
50+
51+![red velvet in red letters](./assets/red-velvet.png)
52+
53+
54+You can easily import the `default` export from a module using `fromDefault`. This will type red as `String -> String`.
55+
56+### Method chaining
57+
58+In js method chaining is often used. In chalk, you can combine different styles by chaining:
59+
60+```js
61+import chalk from 'chalk';
62+
63+console.log(chalk.underline.bold.green('Leaf 🍃'));
64+```
65+
66+In purescript, we can use function application to model this method chaining:
67+```purescript
68+main :: Effect Unit
69+main = launchAff_ do
70+ { underline } <- fromDefault "chalk"
71+ log $ underline # \{ bold } -> bold # \{ green } -> green "Leaf 🍃"
72+```
73+
74+Running it will print:
75+
76+![green leaf printed in bold green underline](./assets/green-leaf.png).
77+
78+### Uncurried
79+
80+js typically uses uncurried functions (e.g. `f(a,b,c) `) instead of uncurried functions (e.g. `f(a)(b)(c)` ) like purescript. E.g. we can use the `blue` function as a three-argument uncurried function:
81+
82+```js
83+console.log(chalk.blue('blue', 'azul', 'blau'));
84+```
85+
86+In purescript functions are curried, so we need to uncurry them using `uncurried`:
87+
88+```purescript
89+main :: Effect Unit
90+main = launchAff_ do
91+ { blue } <- fromDefault "chalk"
92+
93+ log $ uncurried blue "blue" "azul" "blau"
94+```
95+
96+Running it will print:
97+
98+![blue azul blau in blue colours](./assets/blau-azul.png)
99+
100+### Varargs
101+
102+js functions are sometimes designed to be variadic, i.e. to have a variable number of arguments. In fact, the colour methods in `chalk` are variadic methods (as you have seen in the previous example) and you can pass an arbitrary number of arguments:
103+```js
104+console.log(chalk.blue('Hello', 'world!', 'Hola', 'mundo!'));
105+```
106+
107+If we need this variadic behaviour, we can use `variadic` to model this:
108+```purescript
109+main :: Effect Unit
110+main = launchAff_ do
111+ { blue } <- fromDefault "chalk"
112+
113+ log $ variadic blue "Hello"
114+ log $ variadic blue "Hello" "world!"
115+ log $ variadic blue [ "Hello", "world!", "Hola", "mundo!"]
116+```
117+
118+### Scoped
119+
120+Sometimes js functions don't work in purescript, because they sometimes use `this` internally which fails to resolve in a curried contex. E.g. simply using the `rgb` function from `chalk` as we did before will fail. To make it work again we will need to set the scope for `this` properly. You can use `scoped` to set the scope of a function to the module:
121+
122+```purescript
123+main :: Effect Unit
124+main = launchAff_ do
125+ m@{ rgb } <- fromDefault "chalk"
126+
127+ log $ scoped m (uncurried rgb) 129 37 218 # \{ bold } -> bold "PURPLE!!! 🪁"
128+```
129+
130+Running it will print:
131+
132+![purple in bold purple with a kite](./assets/purple-kite.png)
133+
134+### Effectful
135+
136+Let's try another example and install minimalistic http-client `got`:
137+
138+```console
139+npm install got
140+```
141+
142+With `got` we can create a simple http request using the `post` function and passing a url and a json body:
143+```js
144+import got from 'got';
145+
146+const {data} = await got.post('https://httpbin.org/anything', {
147+ json: {
148+ hello: '🌎'
149+ }
150+}).json();
151+
152+console.log(data);
153+```
154+
155+Clearly, `post` is an effectful function, as it triggers a promise. So in purescript `post` will have the signature `Effect (Promise json)` which we can then be converted to an `Aff` using the `toAffE`.
156+
157+```purescript
158+main :: Effect Unit
159+main = launchAff_ do
160+ { post } <- fromDefault "got"
161+ resp <- Promise.toAffE $ effectful (uncurried post) "https://httpbin.org/anything" { json: { hello: "🌎" } } >>= \{ json } -> json
162+ log resp.json
163+```
164+
165+We import the `post` from `got`. The first thing we need to do is uncurry it, since it receives two arguments, the url and the json record. We then wrap it using `effectful` so that is run in an `Effect`. We can then call the effectful js function `json()` on the resulting `Promise` to get the body, so we can just `bind` (`>>=`) it.
166+
167+
168+## Credits
169+
170+Kudos to @paluh for writing the [`purescript-js-object`](https://github.com/paluh/purescript-js-object) library (check it out!), which basically inspired me to write this library. @paluh's library is probably the (type-)safer option, but I thought if I am already too lazy to write ffi, then I really want to be lazy and not write anything at all. So this library follows a different implementation approach to basically not require any ffi code, at the expense of more type-safety.
assets/blau-azul.pngnew file

Binary file not shown.

assets/green-leaf.pngnew file

Binary file not shown.

assets/purple-kite.pngnew file

Binary file not shown.

assets/red-velvet.pngnew file

Binary file not shown.

package-lock.json+689−2
@@ -7,9 +7,134 @@
77 "": {
88 "name": "purescript-lazy-joe",
99 "version": "1.0.0",
10− "license": "ISC",
10+ "license": "MIT-0",
1111 "devDependencies": {
12− "chalk": "^5.0.1"
12+ "chalk": "^5.0.1",
13+ "fuse.js": "^6.6.2",
14+ "got": "^12.1.0"
15+ }
16+ },
17+ "node_modules/@sindresorhus/is": {
18+ "version": "4.6.0",
19+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
20+ "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
21+ "dev": true,
22+ "engines": {
23+ "node": ">=10"
24+ },
25+ "funding": {
26+ "url": "https://github.com/sindresorhus/is?sponsor=1"
27+ }
28+ },
29+ "node_modules/@szmarczak/http-timer": {
30+ "version": "5.0.1",
31+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
32+ "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==",
33+ "dev": true,
34+ "dependencies": {
35+ "defer-to-connect": "^2.0.1"
36+ },
37+ "engines": {
38+ "node": ">=14.16"
39+ }
40+ },
41+ "node_modules/@types/cacheable-request": {
42+ "version": "6.0.2",
43+ "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz",
44+ "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==",
45+ "dev": true,
46+ "dependencies": {
47+ "@types/http-cache-semantics": "*",
48+ "@types/keyv": "*",
49+ "@types/node": "*",
50+ "@types/responselike": "*"
51+ }
52+ },
53+ "node_modules/@types/http-cache-semantics": {
54+ "version": "4.0.1",
55+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
56+ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==",
57+ "dev": true
58+ },
59+ "node_modules/@types/json-buffer": {
60+ "version": "3.0.0",
61+ "resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz",
62+ "integrity": "sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ==",
63+ "dev": true
64+ },
65+ "node_modules/@types/keyv": {
66+ "version": "3.1.4",
67+ "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
68+ "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
69+ "dev": true,
70+ "dependencies": {
71+ "@types/node": "*"
72+ }
73+ },
74+ "node_modules/@types/node": {
75+ "version": "17.0.44",
76+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.44.tgz",
77+ "integrity": "sha512-gWYiOlu6Y4oyLYBvsJAPlwHbC8H4tX+tLsHy6Ee976wedwwZKrG2hFl3Y/HiH6bIyLTbDWQexQF/ohwKkOpUCg==",
78+ "dev": true
79+ },
80+ "node_modules/@types/responselike": {
81+ "version": "1.0.0",
82+ "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
83+ "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
84+ "dev": true,
85+ "dependencies": {
86+ "@types/node": "*"
87+ }
88+ },
89+ "node_modules/cacheable-lookup": {
90+ "version": "6.0.4",
91+ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.0.4.tgz",
92+ "integrity": "sha512-mbcDEZCkv2CZF4G01kr8eBd/5agkt9oCqz75tJMSIsquvRZ2sL6Hi5zGVKi/0OSC9oO1GHfJ2AV0ZIOY9vye0A==",
93+ "dev": true,
94+ "engines": {
95+ "node": ">=10.6.0"
96+ }
97+ },
98+ "node_modules/cacheable-request": {
99+ "version": "7.0.2",
100+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz",
101+ "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==",
102+ "dev": true,
103+ "dependencies": {
104+ "clone-response": "^1.0.2",
105+ "get-stream": "^5.1.0",
106+ "http-cache-semantics": "^4.0.0",
107+ "keyv": "^4.0.0",
108+ "lowercase-keys": "^2.0.0",
109+ "normalize-url": "^6.0.1",
110+ "responselike": "^2.0.0"
111+ },
112+ "engines": {
113+ "node": ">=8"
114+ }
115+ },
116+ "node_modules/cacheable-request/node_modules/get-stream": {
117+ "version": "5.2.0",
118+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
119+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
120+ "dev": true,
121+ "dependencies": {
122+ "pump": "^3.0.0"
123+ },
124+ "engines": {
125+ "node": ">=8"
126+ },
127+ "funding": {
128+ "url": "https://github.com/sponsors/sindresorhus"
129+ }
130+ },
131+ "node_modules/cacheable-request/node_modules/lowercase-keys": {
132+ "version": "2.0.0",
133+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
134+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
135+ "dev": true,
136+ "engines": {
137+ "node": ">=8"
13138 }
14139 },
15140 "node_modules/chalk": {
@@ -23,14 +148,576 @@
23148 "funding": {
24149 "url": "https://github.com/chalk/chalk?sponsor=1"
25150 }
151+ },
152+ "node_modules/clone-response": {
153+ "version": "1.0.2",
154+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
155+ "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==",
156+ "dev": true,
157+ "dependencies": {
158+ "mimic-response": "^1.0.0"
159+ }
160+ },
161+ "node_modules/compress-brotli": {
162+ "version": "1.3.8",
163+ "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.8.tgz",
164+ "integrity": "sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ==",
165+ "dev": true,
166+ "dependencies": {
167+ "@types/json-buffer": "~3.0.0",
168+ "json-buffer": "~3.0.1"
169+ },
170+ "engines": {
171+ "node": ">= 12"
172+ }
173+ },
174+ "node_modules/decompress-response": {
175+ "version": "6.0.0",
176+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
177+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
178+ "dev": true,
179+ "dependencies": {
180+ "mimic-response": "^3.1.0"
181+ },
182+ "engines": {
183+ "node": ">=10"
184+ },
185+ "funding": {
186+ "url": "https://github.com/sponsors/sindresorhus"
187+ }
188+ },
189+ "node_modules/decompress-response/node_modules/mimic-response": {
190+ "version": "3.1.0",
191+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
192+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
193+ "dev": true,
194+ "engines": {
195+ "node": ">=10"
196+ },
197+ "funding": {
198+ "url": "https://github.com/sponsors/sindresorhus"
199+ }
200+ },
201+ "node_modules/defer-to-connect": {
202+ "version": "2.0.1",
203+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
204+ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
205+ "dev": true,
206+ "engines": {
207+ "node": ">=10"
208+ }
209+ },
210+ "node_modules/end-of-stream": {
211+ "version": "1.4.4",
212+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
213+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
214+ "dev": true,
215+ "dependencies": {
216+ "once": "^1.4.0"
217+ }
218+ },
219+ "node_modules/form-data-encoder": {
220+ "version": "1.7.1",
221+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz",
222+ "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==",
223+ "dev": true
224+ },
225+ "node_modules/fuse.js": {
226+ "version": "6.6.2",
227+ "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz",
228+ "integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==",
229+ "dev": true,
230+ "engines": {
231+ "node": ">=10"
232+ }
233+ },
234+ "node_modules/get-stream": {
235+ "version": "6.0.1",
236+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
237+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
238+ "dev": true,
239+ "engines": {
240+ "node": ">=10"
241+ },
242+ "funding": {
243+ "url": "https://github.com/sponsors/sindresorhus"
244+ }
245+ },
246+ "node_modules/got": {
247+ "version": "12.1.0",
248+ "resolved": "https://registry.npmjs.org/got/-/got-12.1.0.tgz",
249+ "integrity": "sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==",
250+ "dev": true,
251+ "dependencies": {
252+ "@sindresorhus/is": "^4.6.0",
253+ "@szmarczak/http-timer": "^5.0.1",
254+ "@types/cacheable-request": "^6.0.2",
255+ "@types/responselike": "^1.0.0",
256+ "cacheable-lookup": "^6.0.4",
257+ "cacheable-request": "^7.0.2",
258+ "decompress-response": "^6.0.0",
259+ "form-data-encoder": "1.7.1",
260+ "get-stream": "^6.0.1",
261+ "http2-wrapper": "^2.1.10",
262+ "lowercase-keys": "^3.0.0",
263+ "p-cancelable": "^3.0.0",
264+ "responselike": "^2.0.0"
265+ },
266+ "engines": {
267+ "node": ">=14.16"
268+ },
269+ "funding": {
270+ "url": "https://github.com/sindresorhus/got?sponsor=1"
271+ }
272+ },
273+ "node_modules/http-cache-semantics": {
274+ "version": "4.1.0",
275+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
276+ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
277+ "dev": true
278+ },
279+ "node_modules/http2-wrapper": {
280+ "version": "2.1.11",
281+ "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.1.11.tgz",
282+ "integrity": "sha512-aNAk5JzLturWEUiuhAN73Jcbq96R7rTitAoXV54FYMatvihnpD2+6PUgU4ce3D/m5VDbw+F5CsyKSF176ptitQ==",
283+ "dev": true,
284+ "dependencies": {
285+ "quick-lru": "^5.1.1",
286+ "resolve-alpn": "^1.2.0"
287+ },
288+ "engines": {
289+ "node": ">=10.19.0"
290+ }
291+ },
292+ "node_modules/http2-wrapper/node_modules/quick-lru": {
293+ "version": "5.1.1",
294+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
295+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
296+ "dev": true,
297+ "engines": {
298+ "node": ">=10"
299+ },
300+ "funding": {
301+ "url": "https://github.com/sponsors/sindresorhus"
302+ }
303+ },
304+ "node_modules/json-buffer": {
305+ "version": "3.0.1",
306+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
307+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
308+ "dev": true
309+ },
310+ "node_modules/keyv": {
311+ "version": "4.3.0",
312+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.3.0.tgz",
313+ "integrity": "sha512-C30Un9+63J0CsR7Wka5quXKqYZsT6dcRQ2aOwGcSc3RiQ4HGWpTAHlCA+puNfw2jA/s11EsxA1nCXgZRuRKMQQ==",
314+ "dev": true,
315+ "dependencies": {
316+ "compress-brotli": "^1.3.8",
317+ "json-buffer": "3.0.1"
318+ }
319+ },
320+ "node_modules/lowercase-keys": {
321+ "version": "3.0.0",
322+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
323+ "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==",
324+ "dev": true,
325+ "engines": {
326+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
327+ },
328+ "funding": {
329+ "url": "https://github.com/sponsors/sindresorhus"
330+ }
331+ },
332+ "node_modules/mimic-response": {
333+ "version": "1.0.1",
334+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
335+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
336+ "dev": true,
337+ "engines": {
338+ "node": ">=4"
339+ }
340+ },
341+ "node_modules/normalize-url": {
342+ "version": "6.1.0",
343+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
344+ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
345+ "dev": true,
346+ "engines": {
347+ "node": ">=10"
348+ },
349+ "funding": {
350+ "url": "https://github.com/sponsors/sindresorhus"
351+ }
352+ },
353+ "node_modules/once": {
354+ "version": "1.4.0",
355+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
356+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
357+ "dev": true,
358+ "dependencies": {
359+ "wrappy": "1"
360+ }
361+ },
362+ "node_modules/p-cancelable": {
363+ "version": "3.0.0",
364+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz",
365+ "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==",
366+ "dev": true,
367+ "engines": {
368+ "node": ">=12.20"
369+ }
370+ },
371+ "node_modules/pump": {
372+ "version": "3.0.0",
373+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
374+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
375+ "dev": true,
376+ "dependencies": {
377+ "end-of-stream": "^1.1.0",
378+ "once": "^1.3.1"
379+ }
380+ },
381+ "node_modules/resolve-alpn": {
382+ "version": "1.2.1",
383+ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
384+ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
385+ "dev": true
386+ },
387+ "node_modules/responselike": {
388+ "version": "2.0.0",
389+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz",
390+ "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==",
391+ "dev": true,
392+ "dependencies": {
393+ "lowercase-keys": "^2.0.0"
394+ }
395+ },
396+ "node_modules/responselike/node_modules/lowercase-keys": {
397+ "version": "2.0.0",
398+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
399+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
400+ "dev": true,
401+ "engines": {
402+ "node": ">=8"
403+ }
404+ },
405+ "node_modules/wrappy": {
406+ "version": "1.0.2",
407+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
408+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
409+ "dev": true
26410 }
27411 },
28412 "dependencies": {
413+ "@sindresorhus/is": {
414+ "version": "4.6.0",
415+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
416+ "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
417+ "dev": true
418+ },
419+ "@szmarczak/http-timer": {
420+ "version": "5.0.1",
421+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
422+ "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==",
423+ "dev": true,
424+ "requires": {
425+ "defer-to-connect": "^2.0.1"
426+ }
427+ },
428+ "@types/cacheable-request": {
429+ "version": "6.0.2",
430+ "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz",
431+ "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==",
432+ "dev": true,
433+ "requires": {
434+ "@types/http-cache-semantics": "*",
435+ "@types/keyv": "*",
436+ "@types/node": "*",
437+ "@types/responselike": "*"
438+ }
439+ },
440+ "@types/http-cache-semantics": {
441+ "version": "4.0.1",
442+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
443+ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==",
444+ "dev": true
445+ },
446+ "@types/json-buffer": {
447+ "version": "3.0.0",
448+ "resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz",
449+ "integrity": "sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ==",
450+ "dev": true
451+ },
452+ "@types/keyv": {
453+ "version": "3.1.4",
454+ "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
455+ "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
456+ "dev": true,
457+ "requires": {
458+ "@types/node": "*"
459+ }
460+ },
461+ "@types/node": {
462+ "version": "17.0.44",
463+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.44.tgz",
464+ "integrity": "sha512-gWYiOlu6Y4oyLYBvsJAPlwHbC8H4tX+tLsHy6Ee976wedwwZKrG2hFl3Y/HiH6bIyLTbDWQexQF/ohwKkOpUCg==",
465+ "dev": true
466+ },
467+ "@types/responselike": {
468+ "version": "1.0.0",
469+ "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
470+ "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
471+ "dev": true,
472+ "requires": {
473+ "@types/node": "*"
474+ }
475+ },
476+ "cacheable-lookup": {
477+ "version": "6.0.4",
478+ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.0.4.tgz",
479+ "integrity": "sha512-mbcDEZCkv2CZF4G01kr8eBd/5agkt9oCqz75tJMSIsquvRZ2sL6Hi5zGVKi/0OSC9oO1GHfJ2AV0ZIOY9vye0A==",
480+ "dev": true
481+ },
482+ "cacheable-request": {
483+ "version": "7.0.2",
484+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz",
485+ "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==",
486+ "dev": true,
487+ "requires": {
488+ "clone-response": "^1.0.2",
489+ "get-stream": "^5.1.0",
490+ "http-cache-semantics": "^4.0.0",
491+ "keyv": "^4.0.0",
492+ "lowercase-keys": "^2.0.0",
493+ "normalize-url": "^6.0.1",
494+ "responselike": "^2.0.0"
495+ },
496+ "dependencies": {
497+ "get-stream": {
498+ "version": "5.2.0",
499+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
500+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
501+ "dev": true,
502+ "requires": {
503+ "pump": "^3.0.0"
504+ }
505+ },
506+ "lowercase-keys": {
507+ "version": "2.0.0",
508+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
509+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
510+ "dev": true
511+ }
512+ }
513+ },
29514 "chalk": {
30515 "version": "5.0.1",
31516 "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz",
32517 "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==",
33518 "dev": true
519+ },
520+ "clone-response": {
521+ "version": "1.0.2",
522+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
523+ "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==",
524+ "dev": true,
525+ "requires": {
526+ "mimic-response": "^1.0.0"
527+ }
528+ },
529+ "compress-brotli": {
530+ "version": "1.3.8",
531+ "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.8.tgz",
532+ "integrity": "sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ==",
533+ "dev": true,
534+ "requires": {
535+ "@types/json-buffer": "~3.0.0",
536+ "json-buffer": "~3.0.1"
537+ }
538+ },
539+ "decompress-response": {
540+ "version": "6.0.0",
541+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
542+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
543+ "dev": true,
544+ "requires": {
545+ "mimic-response": "^3.1.0"
546+ },
547+ "dependencies": {
548+ "mimic-response": {
549+ "version": "3.1.0",
550+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
551+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
552+ "dev": true
553+ }
554+ }
555+ },
556+ "defer-to-connect": {
557+ "version": "2.0.1",
558+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
559+ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
560+ "dev": true
561+ },
562+ "end-of-stream": {
563+ "version": "1.4.4",
564+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
565+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
566+ "dev": true,
567+ "requires": {
568+ "once": "^1.4.0"
569+ }
570+ },
571+ "form-data-encoder": {
572+ "version": "1.7.1",
573+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz",
574+ "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==",
575+ "dev": true
576+ },
577+ "fuse.js": {
578+ "version": "6.6.2",
579+ "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz",
580+ "integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==",
581+ "dev": true
582+ },
583+ "get-stream": {
584+ "version": "6.0.1",
585+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
586+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
587+ "dev": true
588+ },
589+ "got": {
590+ "version": "12.1.0",
591+ "resolved": "https://registry.npmjs.org/got/-/got-12.1.0.tgz",
592+ "integrity": "sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==",
593+ "dev": true,
594+ "requires": {
595+ "@sindresorhus/is": "^4.6.0",
596+ "@szmarczak/http-timer": "^5.0.1",
597+ "@types/cacheable-request": "^6.0.2",
598+ "@types/responselike": "^1.0.0",
599+ "cacheable-lookup": "^6.0.4",
600+ "cacheable-request": "^7.0.2",
601+ "decompress-response": "^6.0.0",
602+ "form-data-encoder": "1.7.1",
603+ "get-stream": "^6.0.1",
604+ "http2-wrapper": "^2.1.10",
605+ "lowercase-keys": "^3.0.0",
606+ "p-cancelable": "^3.0.0",
607+ "responselike": "^2.0.0"
608+ }
609+ },
610+ "http-cache-semantics": {
611+ "version": "4.1.0",
612+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
613+ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
614+ "dev": true
615+ },
616+ "http2-wrapper": {
617+ "version": "2.1.11",
618+ "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.1.11.tgz",
619+ "integrity": "sha512-aNAk5JzLturWEUiuhAN73Jcbq96R7rTitAoXV54FYMatvihnpD2+6PUgU4ce3D/m5VDbw+F5CsyKSF176ptitQ==",
620+ "dev": true,
621+ "requires": {
622+ "quick-lru": "^5.1.1",
623+ "resolve-alpn": "^1.2.0"
624+ },
625+ "dependencies": {
626+ "quick-lru": {
627+ "version": "5.1.1",
628+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
629+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
630+ "dev": true
631+ }
632+ }
633+ },
634+ "json-buffer": {
635+ "version": "3.0.1",
636+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
637+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
638+ "dev": true
639+ },
640+ "keyv": {
641+ "version": "4.3.0",
642+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.3.0.tgz",
643+ "integrity": "sha512-C30Un9+63J0CsR7Wka5quXKqYZsT6dcRQ2aOwGcSc3RiQ4HGWpTAHlCA+puNfw2jA/s11EsxA1nCXgZRuRKMQQ==",
644+ "dev": true,
645+ "requires": {
646+ "compress-brotli": "^1.3.8",
647+ "json-buffer": "3.0.1"
648+ }
649+ },
650+ "lowercase-keys": {
651+ "version": "3.0.0",
652+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
653+ "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==",
654+ "dev": true
655+ },
656+ "mimic-response": {
657+ "version": "1.0.1",
658+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
659+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
660+ "dev": true
661+ },
662+ "normalize-url": {
663+ "version": "6.1.0",
664+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
665+ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
666+ "dev": true
667+ },
668+ "once": {
669+ "version": "1.4.0",
670+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
671+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
672+ "dev": true,
673+ "requires": {
674+ "wrappy": "1"
675+ }
676+ },
677+ "p-cancelable": {
678+ "version": "3.0.0",
679+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz",
680+ "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==",
681+ "dev": true
682+ },
683+ "pump": {
684+ "version": "3.0.0",
685+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
686+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
687+ "dev": true,
688+ "requires": {
689+ "end-of-stream": "^1.1.0",
690+ "once": "^1.3.1"
691+ }
692+ },
693+ "resolve-alpn": {
694+ "version": "1.2.1",
695+ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
696+ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
697+ "dev": true
698+ },
699+ "responselike": {
700+ "version": "2.0.0",
701+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz",
702+ "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==",
703+ "dev": true,
704+ "requires": {
705+ "lowercase-keys": "^2.0.0"
706+ },
707+ "dependencies": {
708+ "lowercase-keys": {
709+ "version": "2.0.0",
710+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
711+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
712+ "dev": true
713+ }
714+ }
715+ },
716+ "wrappy": {
717+ "version": "1.0.2",
718+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
719+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
720+ "dev": true
34721 }
35722 }
36723}
package.json+3−1
@@ -11,6 +11,8 @@
1111 "license": "MIT-0",
1212 "type": "module",
1313 "devDependencies": {
14− "chalk": "^5.0.1"
14+ "chalk": "^5.0.1",
15+ "fuse.js": "^6.6.2",
16+ "got": "^12.1.0"
1517 }
1618}
spago.dhall+3−2
@@ -2,12 +2,13 @@
22, dependencies =
33 [ "aff"
44 , "aff-promise"
5− , "console"
65 , "effect"
76 , "functions"
87 , "prelude"
98 , "unsafe-coerce"
109 ]
1110, packages = ./packages.dhall
12−, sources = [ "src/**/*.purs", "test/**/*.purs" ]
11+, sources = [ "src/**/*.purs" ]
12+, license = "MIT-0"
13+, repository = "https://github.com/sigma-andex/purescript-lazy-joe.git"
1314}
src/Lazy/Joe.js+61−40
@@ -1,53 +1,74 @@
11
2−
32export const fromImpl = (name) => () => import(name).then(m => { return m })
43
54export const fromDefaultImpl = (name) => () => import(name).then(m => { return m.default })
65
7−export const effectful3 = (f) => {
8− return (a) => {
9− return (b) => {
10− return (c) => {
11− return () => {
12− return f(a, b, c)
13− }
14− }
15− }
16− }
17−}
18−
19−export const scoped3 = (m) => (f) => {
20− return (a) => {
21− return (b) => {
22− return (c) => {
23− const g = f.bind(m)
24− return g(a, b, c)
25− }
26− }
27− }
28−}
29−
30−export const effectful2 = (f) => {
31− return (a) => {
32− return (b) => {
33− return () => {
34− return f(a, b)
35− }
36− }
37− }
38−}
39−
40−export const effectful1 = (f) => {
41− return (a) => {
42− return () => {
43− return f(a)
44− }
45− }
6+
7+export const scoped1 = (m) => (f) => (a) => {
8+ const g = f.bind(m)
9+ return g(a)
10+}
11+
12+export const scoped2 = (m) => (f) => (a) => (b) => {
13+ const g = f.bind(m)
14+ return g(a, b)
15+}
16+
17+export const scoped3 = (m) => (f) => (a) => (b) => (c) => {
18+ const g = f.bind(m)
19+ return g(a, b, c)
20+}
21+
22+export const scoped4 = (m) => (f) => (a) => (b) => (c) => (d) => {
23+ const g = f.bind(m)
24+ return g(a, b, c, d)
25+}
26+
27+export const scoped5 = (m) => (f) => (a) => (b) => (c) => (d) => (e) => {
28+ const g = f.bind(m)
29+ return g(a, b, c, d, e)
4630}
4731
32+export const effectful1 = (f) => (a) => () => f(a)
33+
34+export const effectful2 = (f) => (a) => (b) => () => f(a, b)
35+
36+export const effectful3 = (f) => (a) => (b) => (c) => () => f(a, b, c)
37+
38+export const effectful4 = (f) => (a) => (b) => (c) => (d) => () => f(a, b, c, d)
39+
40+export const effectful5 = (f) => (a) => (b) => (c) => (d) => (e) => () => f(a, b, c, d, e)
41+
4842export const variadicImpl = (f) => (args) => {
4943 return f(...args)
5044}
5145
5246export const varargs1 = (a) => [a]
5347export const varargs2 = (a) => (b) => [a, b]
48+export const varargs3 = (a) => (b) => (c) => [a, b, c]
49+export const varargs4 = (a) => (b) => (c) => (d) => [a, b, c, d]
50+export const varargs5 = (a) => (b) => (c) => (d) => (e) => [a, b, c, d, e]
51+
52+export const new0 = (obj) => {
53+ return new obj()
54+}
55+
56+export const new1 = (obj) => (arg1) => {
57+ return new obj(arg1)
58+}
59+
60+export const new2 = (obj) => (arg1) => (arg2) => {
61+ return new obj(arg1, arg2)
62+}
63+
64+export const new3 = (obj) => (arg1) => (arg2) => (arg3) => {
65+ return new obj(arg1, arg2, arg3)
66+}
67+
68+export const new4 = (obj) => (arg1) => (arg2) => (arg3) => (arg4) => {
69+ return new obj(arg1, arg2, arg3, arg4)
70+}
71+
72+export const new5 = (obj) => (arg1) => (arg2) => (arg3) => (arg4) => (arg5) => {
73+ return new obj(arg1, arg2, arg3, arg4, arg5)
74+}
src/Lazy/Joe.purs+174−10
@@ -1,10 +1,24 @@
1−module Lazy.Joe where
1+module Lazy.Joe
2+ ( Varargs
3+ , class Effectful
4+ , effectful
5+ , class New
6+ , new
7+ , class Scoped
8+ , scoped
9+ , class Uncurried
10+ , uncurried
11+ , class Variadic
12+ , variadic
13+ , from
14+ , fromDefault
15+ ) where
216
317import Prelude
418
519import Control.Promise (Promise)
620import Control.Promise as Promise
7−import Data.Function.Uncurried (Fn1, Fn2, Fn3, mkFn2, mkFn3, runFn1, runFn2, runFn3)
21+import Data.Function.Uncurried (Fn0, Fn1, Fn2, Fn3, Fn4, Fn5, mkFn1, mkFn2, mkFn3, mkFn4, mkFn5, runFn1, runFn2, runFn3, runFn4, runFn5)
822import Effect (Effect)
923import Effect.Aff.Class (class MonadAff, liftAff)
1024import Effect.Class (class MonadEffect, liftEffect)
@@ -12,51 +26,170 @@ import Unsafe.Coerce (unsafeCoerce)
1226
1327foreign import fromImpl :: forall mod. String -> Effect (Promise mod)
1428
29+-- | Import a module
1530from :: forall mod m. MonadAff m => String -> m { | mod }
1631from = fromImpl >>> Promise.toAffE >>> liftAff
1732
1833foreign import fromDefaultImpl :: forall mod. String -> Effect (Promise mod)
1934
20−fromDefault :: forall mod m. MonadAff m => String -> m { | mod }
35+-- | Import a module with a `default` export
36+fromDefault :: forall mod m. MonadAff m => String -> m mod
2137fromDefault = fromDefaultImpl >>> Promise.toAffE >>> liftAff
2238
2339class Uncurried f output | output -> f where
2440 uncurried :: f -> output
2541
26−instance Uncurried (Fn3 a b c d) (a -> b -> c -> d) where
42+instance Uncurried (Fn5 a b c d e f) (a -> b -> c -> d -> e -> f) where
43+ uncurried = runFn5
44+
45+else instance Uncurried (Fn5 a b c d e f) (Fn5 a b c d e f) where
46+ uncurried = identity
47+
48+else instance Uncurried (Fn4 a b c d e) (a -> b -> c -> d -> e) where
49+ uncurried = runFn4
50+
51+else instance Uncurried (Fn4 a b c d e) (Fn4 a b c d e) where
52+ uncurried = identity
53+
54+else instance Uncurried (Fn3 a b c d) (a -> b -> c -> d) where
2755 uncurried = runFn3
56+
57+else instance Uncurried (Fn3 a b c d) (Fn3 a b c d) where
58+ uncurried = identity
59+
2860else instance Uncurried (Fn2 a b c) (a -> b -> c) where
2961 uncurried = runFn2
62+
63+else instance Uncurried (Fn2 a b c) (Fn2 a b c) where
64+ uncurried = identity
65+
66+else instance Uncurried (Fn1 a b) (Fn1 a b) where
67+ uncurried = identity
68+
3069else instance Uncurried (Fn1 a b) (a -> b) where
3170 uncurried = runFn1
3271
72+
73+foreign import new0 :: forall a. Fn0 a -> a
74+
75+foreign import new1 :: forall a b. Fn1 a b -> a -> b
76+
77+foreign import new2 :: forall a b c. Fn2 a b c -> a -> b -> c
78+
79+foreign import new3 :: forall a b c d. Fn3 a b c d -> a -> b -> c -> d
80+
81+foreign import new4 :: forall a b c d e. Fn4 a b c d e -> a -> b -> c -> d -> e
82+
83+foreign import new5 :: forall a b c d e f. Fn5 a b c d e f -> a -> b -> c -> d -> e -> f
84+
85+class New f output | output -> f where
86+ new :: f -> output
87+
88+instance New (Fn5 a b c d e f) (a -> b -> c -> d -> e -> f) where
89+ new f = \a -> \b -> \c -> \d -> \e -> new5 f a b c d e
90+
91+else instance New (Fn4 a b c d e) (a -> b -> c -> d -> e) where
92+ new f = \a -> \b -> \c -> \d -> new4 f a b c d
93+
94+else instance New (Fn3 a b c d) (a -> b -> c -> d) where
95+ new f = \a -> \b -> \c -> new3 f a b c
96+
97+else instance New (Fn2 a b c) (a -> b -> c) where
98+ new f = \a -> \b -> new2 f a b
99+
100+else instance New (Fn1 a b) (a -> b) where
101+ new f = \a -> new1 f a
102+
103+else instance New (Fn0 a) (a) where
104+ new f = new0 f
105+
33106class Effectful f output | output -> f where
34107 effectful :: f -> output
35108
109+foreign import effectful5 :: forall a b c d e f. Fn5 a b c d e f -> a -> b -> c -> d -> e -> Effect f
110+
111+foreign import effectful4 :: forall a b c d e. Fn4 a b c d e -> a -> b -> c -> d -> Effect e
112+
36113foreign import effectful3 :: forall a b c d. Fn3 a b c d -> a -> b -> c -> Effect d
37114
38115foreign import effectful2 :: forall a b c. Fn2 a b c -> a -> b -> Effect c
39116
40117foreign import effectful1 :: forall a b. Fn1 a b -> a -> Effect b
41118
42−instance MonadEffect eff => Effectful (Fn3 a b c d) (a -> b -> c -> eff d) where
119+instance MonadEffect eff => Effectful (Fn5 a b c d e f) (Fn5 a b c d e (eff f)) where
120+ effectful f = mkFn5 (\a -> \b -> \c -> \d -> \e -> effectful5 f a b c d e # liftEffect)
121+
122+else instance MonadEffect eff => Effectful (Fn5 a b c d e f) (a -> b -> c -> d -> e -> eff f) where
123+ effectful f = \a -> \b -> \c -> \d -> \e -> effectful5 f a b c d e # liftEffect
124+
125+else instance MonadEffect eff => Effectful (Fn4 a b c d e) (Fn4 a b c d (eff e)) where
126+ effectful f = mkFn4 (\a -> \b -> \c -> \d -> effectful4 f a b c d # liftEffect)
127+
128+else instance MonadEffect eff => Effectful (Fn4 a b c d e) (a -> b -> c -> d -> eff e) where
129+ effectful f = \a -> \b -> \c -> \d -> effectful4 f a b c d # liftEffect
130+
131+else instance MonadEffect eff => Effectful (Fn3 a b c d) (Fn3 a b c (eff d)) where
132+ effectful f = mkFn3 (\a -> \b -> \c -> effectful3 f a b c # liftEffect)
133+
134+else instance MonadEffect eff => Effectful (Fn3 a b c d) (a -> b -> c -> eff d) where
43135 effectful f = \a -> \b -> \c -> effectful3 f a b c # liftEffect
136+
137+else instance MonadEffect eff => Effectful (Fn2 a b c) (Fn2 a b (eff c)) where
138+ effectful f = mkFn2 (\a -> \b -> effectful2 f a b # liftEffect)
139+
44140else instance MonadEffect eff => Effectful (Fn2 a b c) (a -> b -> eff c) where
45141 effectful f = \a -> \b -> effectful2 f a b # liftEffect
142+
143+else instance MonadEffect eff => Effectful (Fn1 a b) (Fn1 a (eff b)) where
144+ effectful f = mkFn1 (\a -> effectful1 f a # liftEffect)
145+
46146else instance MonadEffect eff => Effectful (Fn1 a b) (a -> eff b) where
47147 effectful f = \a -> effectful1 f a # liftEffect
48148
149+foreign import scoped1 :: forall mod a b. mod -> Fn1 a b -> a -> b
150+
151+foreign import scoped2 :: forall mod a b c. mod -> Fn2 a b c -> a -> b -> c
152+
49153foreign import scoped3 :: forall mod a b c d. mod -> Fn3 a b c d -> a -> b -> c -> d
50154
155+foreign import scoped4 :: forall mod a b c d e. mod -> Fn4 a b c d e -> a -> b -> c -> d -> e
156+
157+foreign import scoped5 :: forall mod a b c d e f. mod -> Fn5 a b c d e f -> a -> b -> c -> d -> e -> f
158+
51159class Scoped f output | output -> f where
52160 scoped :: forall mod. mod -> f -> output
53161
54−instance Scoped (Fn3 a b c d) (a -> b -> c -> d) where
55− scoped m f = \a -> \b -> \c -> scoped3 m f a b c
162+instance Scoped (Fn5 a b c d e f) (Fn5 a b c d e f) where
163+ scoped m f = mkFn5 \a -> \b -> \c -> \d -> \e -> scoped5 m f a b c d e
164+
165+else instance Scoped (Fn5 a b c d e f) (a -> b -> c -> d -> e -> f) where
166+ scoped m f = \a -> \b -> \c -> \d -> \e -> scoped5 m f a b c d e
167+
168+else instance Scoped (Fn4 a b c d e) (Fn4 a b c d e) where
169+ scoped m f = mkFn4 \a -> \b -> \c -> \d -> scoped4 m f a b c d
56170
57−instance Scoped (Fn3 a b c d) (Fn3 a b c d) where
171+else instance Scoped (Fn4 a b c d e) (a -> b -> c -> d -> e) where
172+ scoped m f = \a -> \b -> \c -> \d -> scoped4 m f a b c d
173+
174+else instance Scoped (Fn3 a b c d) (Fn3 a b c d) where
58175 scoped m f = mkFn3 \a -> \b -> \c -> scoped3 m f a b c
59176
177+else instance Scoped (Fn3 a b c d) (a -> b -> c -> d) where
178+ scoped m f = \a -> \b -> \c -> scoped3 m f a b c
179+
180+else instance Scoped (Fn2 a b c) (Fn2 a b c) where
181+ scoped m f = mkFn2 (\a -> \b -> scoped2 m f a b)
182+
183+else instance Scoped (Fn2 a b c) (a -> b -> c) where
184+ scoped m f = \a -> \b -> scoped2 m f a b
185+
186+else instance Scoped (Fn1 a b) (Fn1 a b) where
187+ scoped m f = \a -> scoped1 m f a
188+
189+else instance Scoped (Fn1 a b) (a -> b) where
190+ scoped m f = mkFn1 (\a -> scoped1 m f a)
191+
192+
60193foreign import variadicImpl :: forall output. (Varargs -> output) -> Varargs -> output
61194
62195class Variadic f output | output -> f where
@@ -65,14 +198,45 @@ class Variadic f output | output -> f where
65198foreign import data Varargs :: Type
66199
67200foreign import varargs1 :: forall a. a -> Varargs
201+
68202foreign import varargs2 :: forall a b. a -> b -> Varargs
69203
70−instance Variadic (Varargs -> c) (a -> b -> c) where
71− variadic f = \a -> \b -> variadicImpl f $ varargs2 a b
204+foreign import varargs3 :: forall a b c. a -> b -> c -> Varargs
205+
206+foreign import varargs4 :: forall a b c d. a -> b -> c -> d -> Varargs
207+
208+foreign import varargs5 :: forall a b c d e. a -> b -> c -> d -> e -> Varargs
209+
210+instance Variadic (Varargs -> f) (Fn5 a b c d e f) where
211+ variadic f = mkFn5 (\a -> \b -> \c -> \d -> \e -> variadicImpl f $ varargs5 a b c d e)
212+
213+else instance Variadic (Varargs -> f) (a -> b -> c -> d -> e -> f) where
214+ variadic f = \a -> \b -> \c -> \d -> \e -> variadicImpl f $ varargs5 a b c d e
215+
216+else instance Variadic (Varargs -> e) (Fn4 a b c d e) where
217+ variadic f = mkFn4 (\a -> \b -> \c -> \d -> variadicImpl f $ varargs4 a b c d)
218+
219+else instance Variadic (Varargs -> e) (a -> b -> c -> d -> e) where
220+ variadic f = \a -> \b -> \c -> \d -> variadicImpl f $ varargs4 a b c d
221+
222+else instance Variadic (Varargs -> d) (Fn3 a b c d) where
223+ variadic f = mkFn3 (\a -> \b -> \c -> variadicImpl f $ varargs3 a b c)
224+
225+else instance Variadic (Varargs -> d) (a -> b -> c -> d) where
226+ variadic f = \a -> \b -> \c -> variadicImpl f $ varargs3 a b c
227+
72228else instance Variadic (Varargs -> c) (Fn2 a b c) where
73229 variadic f = mkFn2 (\a -> \b -> variadicImpl f $ varargs2 a b)
230+
231+else instance Variadic (Varargs -> c) (a -> b -> c) where
232+ variadic f = \a -> \b -> variadicImpl f $ varargs2 a b
233+
74234else instance Variadic (Varargs -> b) (Array a -> b) where
75235 variadic f = \a -> variadicImpl f $ unsafeCoerce a
236+
237+else instance Variadic (Varargs -> b) (Fn1 a b) where
238+ variadic f = mkFn1 (\a -> variadicImpl f $ varargs1 a)
239+
76240else instance Variadic (Varargs -> b) (a -> b) where
77241 variadic f = \a -> variadicImpl f $ varargs1 a
78242
test/Main.purs+31−16
@@ -2,42 +2,57 @@ module Test.Main where
22
33import Prelude
44
5+import Control.Promise as Promise
56import Effect (Effect)
67import Effect.Aff (Aff, launchAff_)
7−import Effect.Class.Console (log)
8−import Lazy.Joe (effectful, fromDefault, scoped, variadic)
8+import Effect.Class.Console (log, logShow)
9+import Lazy.Joe (effectful, fromDefault, new, scoped, uncurried, variadic)
910
1011main :: Effect Unit
1112main = launchAff_ do
12− m@{ blue, underline, rgb, green } <- fromDefault "chalk"
13+ m@{ blue, underline, rgb, green, red } <- fromDefault "chalk"
1314
15+ log $ red "Red velvet 🎂"
1416 log $ variadic green "hello"
1517 log $ variadic green "hello" "world"
16− log $ variadic green ["hello","world", "hallo", "welt", "hola", "mundo"]
18+ log $ variadic green [ "hello", "world", "hallo", "welt", "hola", "mundo" ]
1719
1820 let
19− --x :: Effect String
2021 x = effectful (variadic blue) "hello" "wurst"
21−
22− -- y :: Effect String
2322 y = effectful (variadic blue) "hello"
24−
23+ log "Effects not run"
2524 x >>= log
2625 y >>= log
27− -- log $ blue "blau"
26+
2827 let
2928 underlined :: Aff String
30− underlined = underline # \{ bold } -> bold # \{ green:g } -> effectful g "grün"
29+ underlined = underline # \{ bold } -> bold # \{ green: g } -> effectful g "grün"
3130 underlined >>= log
32− -- let
33− -- c :: Effect String
34− -- c = effectfulScoped3 m rgb 123 45 67 <#> \{ underline } -> underline "Underlined reddish color"
31+
3532 log $ scoped m rgb 123 45 67 # \{ underline: u } -> u "Underlined reddish color"
3633
37− let
34+ let
3835 c :: Aff String
39− c = effectful (scoped m rgb) 123 45 67 <#> \{ underline:u } -> u "Underlined reddish color"
40−
36+ c = effectful (scoped m rgb) 123 45 67 <#> \{ underline: u } -> u "Underlined reddish color"
37+
4138 log "Effect not run"
4239 c >>= log
40+
41+ { post } <- fromDefault "got"
42+ resp <- Promise.toAffE $ effectful (uncurried post) "https://httpbin.org/anything" { json: { hello: "🌎" } } >>= \{ json } -> json
43+ log resp.json
44+
45+ fuse <- fromDefault "fuse.js"
46+ let
47+ list =
48+ [ { "title": "Old Man's War", "author": { "firstName": "John", "lastName": "Scalzi" } }
49+ , { "title": "The Lock Artist", "author": { "firstName": "Steve", "lastName": "Hamilton" } }
50+ ]
51+ options =
52+ { keys: [ "title", "author.firstName" ]
53+ }
54+ result :: Array { item :: { title :: String, author :: { firstName :: String, lastName :: String } } } <-
55+ (new fuse list options) # \f@{ search } -> effectful (scoped f search) "eve"
56+
57+ logShow result
4358 pure unit