git.iko.soy/rowtype-yoga/purescript-yoga-fetch-om
on 0d63100 help sign in
104 files changed+670−6070
since splitsnapshots
unifiedsplit
.c8rc.json−22 .github/workflows/ci.yml+2−7 .gitignore+1−4 .psci_modules/Data.Int.Bits/externs.cbor .psci_modules/Data.Int.Bits/foreign.js−48 .psci_modules/Data.Int.Bits/index.js−12 .psci_modules/Data.NaturalTransformation/externs.cbor .psci_modules/Data.NaturalTransformation/index.js−1 .psci_modules/Data.String.Unsafe/externs.cbor .psci_modules/Data.String.Unsafe/foreign.js−11 .psci_modules/Data.String.Unsafe/index.js−7 .psci_modules/Record.Unsafe/externs.cbor .psci_modules/Record.Unsafe/foreign.js−38 .psci_modules/Record.Unsafe/index.js−14 .psci_modules/Spago.Generated.BuildInfo/externs.cbor .psci_modules/Spago.Generated.BuildInfo/index.js−13 .psci_modules/Type.Equality/externs.cbor .psci_modules/Type.Equality/index.js−35 .psci_modules/Type.Function/externs.cbor .psci_modules/Type.Function/index.js−1 .psci_modules/Type.Proxy/externs.cbor .psci_modules/Type.Proxy/index.js−58 .psci_modules/Type.Row/externs.cbor .psci_modules/Type.Row/index.js−1 .psci_modules/Unsafe.Coerce/externs.cbor .psci_modules/Unsafe.Coerce/foreign.js−5 .psci_modules/Unsafe.Coerce/index.js−5 .psci_modules/Web.DOM.Internal.Types/externs.cbor .psci_modules/Web.DOM.Internal.Types/index.js−1 .psci_modules/Web.Event.Internal.Types/externs.cbor .psci_modules/Web.Event.Internal.Types/index.js−1 .psci_modules/Yoga.HTTP.API.Route.Encoding/externs.cbor .psci_modules/Yoga.HTTP.API.Route.Encoding/index.js−1 .psci_modules/Yoga.HTTP.API.Route.Method/externs.cbor .psci_modules/Yoga.HTTP.API.Route.Method/index.js−1 .psci_modules/cache-db.json−1 .psci_modules/package.json−1 .purs-repl−1 .purslint-cache/props.db LICENSE−21 README.md+127−153 bun.lock−1089 compile-fail-tests/ClientBadBodyType.purs−12 compile-fail-tests/ClientBadCurriedBodyType.purs−12 compile-fail-tests/ClientBadHeaderType.purs−13 compile-fail-tests/ClientBadOptionalQueryType.purs−13 compile-fail-tests/ClientBadPathType.purs−12 compile-fail-tests/ClientExtraBodyField.purs−12 compile-fail-tests/ClientExtraHeaderField.purs−13 compile-fail-tests/ClientExtraOptionalQueryField.purs−13 compile-fail-tests/ClientExtraPathField.purs−12 compile-fail-tests/ClientMissingBodyArgument.purs−12 compile-fail-tests/ClientMissingBodyField.purs−12 compile-fail-tests/ClientMissingHeaderArgument.purs−13 compile-fail-tests/ClientMissingHeaderField.purs−13 compile-fail-tests/ClientMissingPathField.purs−12 compile-fail-tests/ClientMissingRequiredQuery.purs−13 compile-fail-tests/ClientMissingThirdArgument.purs−13 compile-fail-tests/run.js−101 package.json+4−19 spago.lock−1792 spago.yaml+8−25 src/Yoga/Fetch/Om.js−1 src/Yoga/Fetch/Om.purs+37−231 src/Yoga/Fetch/Om/BuildUrl.js−87 src/Yoga/Fetch/Om/BuildUrl.purs+17−60 src/Yoga/Fetch/Om/ClientFn.purs+142 src/Yoga/Fetch/Om/ClientFunction.purs−157 src/Yoga/Fetch/Om/ExtractParams.purs+1−22 src/Yoga/Fetch/Om/MakeRequest.js−1 src/Yoga/Fetch/Om/MakeRequest.purs+16−44 src/Yoga/Fetch/Om/ParseResponse.purs+20−83 src/Yoga/Fetch/Om/ReadOptional.js−18 src/Yoga/Fetch/Om/ReadOptional.purs−56 src/Yoga/Fetch/Om/Simple.purs+72−63 src/Yoga/Fetch/Om/SplitResponses.purs+2−24 src/Yoga/Fetch/Om/StreamDecode.js−12 src/Yoga/Fetch/Om/StreamDecode.purs−61 test-compile-fail/cases/ClientBogusSignature.purs−9 test-compile-fail/cases/ClientExtraField.purs−12 test-compile-fail/cases/ClientMissingField.purs−12 test-compile-fail/cases/ClientNoArgsPassedArg.purs−12 test-compile-fail/cases/ClientWrongFieldName.purs−12 test-compile-fail/cases/ClientWrongFieldType.purs−12 test-compile-fail/run.sh−26 test/BodylessResponse.Example.purs−27 test/BodylessResponse.Spec.purs−125 test/BuildUrl.Spec.purs+100−154 test/BuildUrlProperty.Spec.purs−256 test/Complete.Example.purs+26−29 test/Example.purs+8−20 test/MakeRequest.Spec.purs−54 test/PlainTextResponse.Spec.purs−122 test/Polymorphic.Spec.purs−70 test/Roundtrip.Spec.purs−380 test/Simple.Spec.purs+16−16 test/SplitParams.Spec.purs+31−22 test/StreamDecode.Spec.js−1 test/StreamDecode.Spec.purs−32 test/Test.Main.purs+20 test/Test/Main.purs−14 test/TestServer.purs−38 test/Variant.Spec.purs+11−6 vitest.config.js+9
.c8rc.jsondeleted−22
@@ -1,22 +0,0 @@
1−{
2− "all": true,
3− "include": [
4− "output/Yoga.Fetch.Om*/index.js",
5− "output/Yoga.Fetch.Om*/foreign.js"
6− ],
7− "exclude": [
8− "output/Yoga.Fetch.Om.ExtractParams/index.js",
9− "output/Yoga.Fetch.Om.SplitResponses/index.js"
10− ],
11− "reporter": [
12− "text",
13− "html",
14− "lcov"
15− ],
16− "reports-dir": "coverage",
17− "check-coverage": true,
18− "statements": 95,
19− "branches": 90,
20− "functions": 85,
21− "lines": 95
22−}
.github/workflows/ci.yml+2−7
@@ -12,10 +12,5 @@ jobs:
1212 steps:
1313 - uses: actions/checkout@v4
1414 - uses: rowtype-yoga/purescript-yoga-actions/.github/actions/setup@main
15− - run: bun run coverage
16− - uses: actions/upload-artifact@v4
17− if: always()
18− with:
19− name: coverage
20− path: coverage/
21− - run: bun compile-fail-tests/run.js
15+ - run: spago build
16+ - run: spago test
.gitignore+1−4
@@ -1,9 +1,6 @@
11output/
22output-compile-fail/
3−coverage/
4−generated-docs/
53node_modules/
64.spago/
75.psc-ide-port
8−package-lock.json
9−bun.lockb
6+*.lock
.psci_modules/Data.Int.Bits/externs.cbordeleted

Binary file not shown.

.psci_modules/Data.Int.Bits/foreign.jsdeleted−48
@@ -1,48 +0,0 @@
1−// module Data.Int.Bits
2−
3−export const and = function (n1) {
4− return function (n2) {
5− /* jshint bitwise: false */
6− return n1 & n2;
7− };
8−};
9−
10−export const or = function (n1) {
11− return function (n2) {
12− /* jshint bitwise: false */
13− return n1 | n2;
14− };
15−};
16−
17−export const xor = function (n1) {
18− return function (n2) {
19− /* jshint bitwise: false */
20− return n1 ^ n2;
21− };
22−};
23−
24−export const shl = function (n1) {
25− return function (n2) {
26− /* jshint bitwise: false */
27− return n1 << n2;
28− };
29−};
30−
31−export const shr = function (n1) {
32− return function (n2) {
33− /* jshint bitwise: false */
34− return n1 >> n2;
35− };
36−};
37−
38−export const zshr = function (n1) {
39− return function (n2) {
40− /* jshint bitwise: false */
41− return n1 >>> n2;
42− };
43−};
44−
45−export const complement = function (n) {
46− /* jshint bitwise: false */
47− return ~n;
48−};
.psci_modules/Data.Int.Bits/index.jsdeleted−12
@@ -1,12 +0,0 @@
1−// | This module defines bitwise operations for the `Int` type.
2−import * as $foreign from "./foreign.js";
3−
4−export {
5− and,
6− or,
7− xor,
8− shl,
9− shr,
10− zshr,
11− complement
12−} from "./foreign.js";
.psci_modules/Data.NaturalTransformation/externs.cbordeleted

Binary file not shown.

.psci_modules/Data.NaturalTransformation/index.jsdeleted−1
@@ -1 +0,0 @@
1−
.psci_modules/Data.String.Unsafe/externs.cbordeleted

Binary file not shown.

.psci_modules/Data.String.Unsafe/foreign.jsdeleted−11
@@ -1,11 +0,0 @@
1−export const charAt = function (i) {
2− return function (s) {
3− if (i >= 0 && i < s.length) return s.charAt(i);
4− throw new Error("Data.String.Unsafe.charAt: Invalid index.");
5− };
6−};
7−
8−export const char = function (s) {
9− if (s.length === 1) return s.charAt(0);
10− throw new Error("Data.String.Unsafe.char: Expected string of length 1.");
11−};
.psci_modules/Data.String.Unsafe/index.jsdeleted−7
@@ -1,7 +0,0 @@
1−// | Unsafe string and character functions.
2−import * as $foreign from "./foreign.js";
3−
4−export {
5− char,
6− charAt
7−} from "./foreign.js";
.psci_modules/Record.Unsafe/externs.cbordeleted

Binary file not shown.

.psci_modules/Record.Unsafe/foreign.jsdeleted−38
@@ -1,38 +0,0 @@
1−export const unsafeHas = function (label) {
2− return function (rec) {
3− return {}.hasOwnProperty.call(rec, label);
4− };
5−};
6−
7−export const unsafeGet = function (label) {
8− return function (rec) {
9− return rec[label];
10− };
11−};
12−
13−export const unsafeSet = function (label) {
14− return function (value) {
15− return function (rec) {
16− var copy = {};
17− for (var key in rec) {
18− if ({}.hasOwnProperty.call(rec, key)) {
19− copy[key] = rec[key];
20− }
21− }
22− copy[label] = value;
23− return copy;
24− };
25− };
26−};
27−
28−export const unsafeDelete = function (label) {
29− return function (rec) {
30− var copy = {};
31− for (var key in rec) {
32− if (key !== label && {}.hasOwnProperty.call(rec, key)) {
33− copy[key] = rec[key];
34− }
35− }
36− return copy;
37− };
38−};
.psci_modules/Record.Unsafe/index.jsdeleted−14
@@ -1,14 +0,0 @@
1−// | The functions in this module are highly unsafe as they treat records like
2−// | stringly-keyed maps and can coerce the row of labels that a record has.
3−// |
4−// | These function are intended for situations where there is some other way of
5−// | proving things about the structure of the record - for example, when using
6−// | `RowToList`. **They should never be used for general record manipulation.**
7−import * as $foreign from "./foreign.js";
8−
9−export {
10− unsafeHas,
11− unsafeGet,
12− unsafeSet,
13− unsafeDelete
14−} from "./foreign.js";
.psci_modules/Spago.Generated.BuildInfo/externs.cbordeleted

Binary file not shown.

.psci_modules/Spago.Generated.BuildInfo/index.jsdeleted−13
@@ -1,13 +0,0 @@
1−// @inline export packages always
2−// @inline export pursVersion always
3−// @inline export spagoVersion always
4−var spagoVersion = "1.0.3";
5−var pursVersion = "0.15.15";
6−var packages = {
7− "yoga-fetch-om": "0.3.0"
8−};
9−export {
10− packages,
11− pursVersion,
12− spagoVersion
13−};
.psci_modules/Type.Equality/externs.cbordeleted

Binary file not shown.

.psci_modules/Type.Equality/index.jsdeleted−35
@@ -1,35 +0,0 @@
1−var To = function (x) {
2− return x;
3−};
4−var From = function (x) {
5− return x;
6−};
7−var refl = {
8− proof: function (a) {
9− return a;
10− },
11− Coercible0: function () {
12− return undefined;
13− }
14−};
15−var proof = function (dict) {
16− return dict.proof;
17−};
18−var to = function (dictTypeEquals) {
19− var v = proof(dictTypeEquals)(function (a) {
20− return a;
21− });
22− return v;
23−};
24−var from = function (dictTypeEquals) {
25− var v = proof(dictTypeEquals)(function (a) {
26− return a;
27− });
28− return v;
29−};
30−export {
31− proof,
32− to,
33− from,
34− refl
35−};
.psci_modules/Type.Function/externs.cbordeleted

Binary file not shown.

.psci_modules/Type.Function/index.jsdeleted−1
@@ -1 +0,0 @@
1−
.psci_modules/Type.Proxy/externs.cbordeleted

Binary file not shown.

.psci_modules/Type.Proxy/index.jsdeleted−58
@@ -1,58 +0,0 @@
1−// | The `Proxy` type and values are for situations where type information is
2−// | required for an input to determine the type of an output, but where it is
3−// | not possible or convenient to provide a _value_ for the input.
4−// |
5−// | A hypothetical example: if you have a class that is used to handle the
6−// | result of an AJAX request, you may want to use this information to set the
7−// | expected content type of the request, so you might have a class something
8−// | like this:
9−// |
10−// | ``` purescript
11−// | class AjaxResponse a where
12−// | responseType :: a -> ResponseType
13−// | fromResponse :: Foreign -> a
14−// | ```
15−// |
16−// | The problem here is `responseType` requires a value of type `a`, but we
17−// | won't have a value of that type until the request has been completed. The
18−// | solution is to use a `Proxy` type instead:
19−// |
20−// | ``` purescript
21−// | class AjaxResponse a where
22−// | responseType :: Proxy a -> ResponseType
23−// | fromResponse :: Foreign -> a
24−// | ```
25−// |
26−// | We can now call `responseType (Proxy :: Proxy SomeContentType)` to produce
27−// | a `ResponseType` for `SomeContentType` without having to construct some
28−// | empty version of `SomeContentType` first. In situations like this where
29−// | the `Proxy` type can be statically determined, it is recommended to pull
30−// | out the definition to the top level and make a declaration like:
31−// |
32−// | ``` purescript
33−// | _SomeContentType :: Proxy SomeContentType
34−// | _SomeContentType = Proxy
35−// | ```
36−// |
37−// | That way the proxy value can be used as `responseType _SomeContentType`
38−// | for improved readability. However, this is not always possible, sometimes
39−// | the type required will be determined by a type variable. As PureScript has
40−// | scoped type variables, we can do things like this:
41−// |
42−// | ``` purescript
43−// | makeRequest :: URL -> ResponseType -> Aff _ Foreign
44−// | makeRequest = ...
45−// |
46−// | fetchData :: forall a. (AjaxResponse a) => URL -> Aff _ a
47−// | fetchData url = fromResponse <$> makeRequest url (responseType (Proxy :: Proxy a))
48−// | ```
49−var $$Proxy = /* #__PURE__ */ (function () {
50− function $$Proxy() {
51−
52− };
53− $$Proxy.value = new $$Proxy();
54− return $$Proxy;
55−})();
56−export {
57− $$Proxy as Proxy
58−};
.psci_modules/Type.Row/externs.cbordeleted

Binary file not shown.

.psci_modules/Type.Row/index.jsdeleted−1
@@ -1 +0,0 @@
1−
.psci_modules/Unsafe.Coerce/externs.cbordeleted

Binary file not shown.

.psci_modules/Unsafe.Coerce/foreign.jsdeleted−5
@@ -1,5 +0,0 @@
1−// module Unsafe.Coerce
2−
3−export const unsafeCoerce = function (x) {
4− return x;
5−};
.psci_modules/Unsafe.Coerce/index.jsdeleted−5
@@ -1,5 +0,0 @@
1−import * as $foreign from "./foreign.js";
2−
3−export {
4− unsafeCoerce
5−} from "./foreign.js";
.psci_modules/Web.DOM.Internal.Types/externs.cbordeleted

Binary file not shown.

.psci_modules/Web.DOM.Internal.Types/index.jsdeleted−1
@@ -1 +0,0 @@
1−
.psci_modules/Web.Event.Internal.Types/externs.cbordeleted

Binary file not shown.

.psci_modules/Web.Event.Internal.Types/index.jsdeleted−1
@@ -1 +0,0 @@
1−
.psci_modules/Yoga.HTTP.API.Route.Encoding/externs.cbordeleted

Binary file not shown.

.psci_modules/Yoga.HTTP.API.Route.Encoding/index.jsdeleted−1
@@ -1 +0,0 @@
1−
.psci_modules/Yoga.HTTP.API.Route.Method/externs.cbordeleted

Binary file not shown.

.psci_modules/Yoga.HTTP.API.Route.Method/index.jsdeleted−1
@@ -1 +0,0 @@
1−
.psci_modules/cache-db.jsondeleted−1
@@ -1 +0,0 @@
1−{"Data.Int.Bits":{".spago/p/integers-6.0.0/src/Data/Int/Bits.js":["1970-01-01T06:00:00Z","bdbabdb4bf0d318a750d7ff7e1542735731877a33803a87011e670bafa8d59c8c3ef42107be1ca1b86dc7b8222c11008895341e36760cf7989a0da098d848100"],".spago/p/integers-6.0.0/src/Data/Int/Bits.purs":["1970-01-01T06:00:00Z","61f10b047f013a5b4505df8cc49e566ce827bce1272b471cdcc2a2b849e39db49f0850613e036931a4d2efd7a2cc727bbd8a8a310498ea28552cc4d6547fc800"]},"Data.NaturalTransformation":{".spago/p/prelude-6.0.2/src/Data/NaturalTransformation.purs":["1970-01-01T00:00:00Z","6b9fc42ec524a517d464dea99867c64345cdbcbada4260a772373a956961ad1c9a4a3a4f8ed4a0c7c7f3e36120068954141841c5d6bdc4e5898ea06435104bb7"]},"Data.String.Unsafe":{".spago/p/strings-6.0.1/src/Data/String/Unsafe.js":["1970-01-01T06:00:00Z","81c79d607f04aaa23089d717e10d358971deec3254ee25837a9d14e947c4d28444e4057abd2cdc1c114327a43584c3cef2cbec957b011ab4ed412e1a25596812"],".spago/p/strings-6.0.1/src/Data/String/Unsafe.purs":["1970-01-01T06:00:00Z","c3bddfdcefc7c46316a573e2af253df77fae08a64ad096f692391d33266d0f77623c0a6c8008a15bcae0d440670734399edd547ed335f5beecf9042b49fa2d9b"]},"Record.Unsafe":{".spago/p/prelude-6.0.2/src/Record/Unsafe.js":["1970-01-01T00:00:00Z","667d613a0e1265a710e98c9f6e64ff791b9e9b7227cdf699c3a25724077c02e42726c807c0387ca4484454fd853d5b41522bf2e048887f22a894413ef80cbb92"],".spago/p/prelude-6.0.2/src/Record/Unsafe.purs":["1970-01-01T00:00:00Z","af8a7c83127f5e61853ad0e572be799c04e321562a375d51ab133706ac6a6777e169b057f01a709ad7aae2d8c7a5ae8daa28eae8793c4fe92e2e8f0cfaecf870"]},"Spago.Generated.BuildInfo":{".spago/BuildInfo.purs":["2026-02-09T12:42:13.813485312Z","abfa99370d332ed1138a8d9f7ec91fe0377758e01f2520a6d390bdec7c3b5bacd6778fca0e5571642cde24de431c68071562941dde9fadc7a1dcb8de511370d8"]},"Type.Equality":{".spago/p/type-equality-4.0.1/src/Type/Equality.purs":["1970-01-01T05:00:00Z","2713b8d5621912fe0dad9cd588cf4579181566459fe200f5089de472d00e29ab4a1c020f73a8e89f04f3ef02b94ec28082d17d395b89349d6c5f8016426a009e"]},"Type.Function":{".spago/p/typelevel-prelude-7.0.0/src/Type/Function.purs":["1970-01-01T06:00:00Z","d1b8eb136c5e23ded6dcd622ef352200ea9a323dd4f3dec0328fe0dbcf673ee4c959a495efecc5605fedcb7824bb086faaf8684fa30afe0625b1d03fc921b149"]},"Type.Proxy":{".spago/p/prelude-6.0.2/src/Type/Proxy.purs":["1970-01-01T00:00:00Z","333d0ae90b05098eada860ad476ed9e1eacd67d969dc1573c74375610cf8de22e85a358a7783a0a461d7ffa6fe322d8c3e90696be02555a02793ac99aba687f2"]},"Type.Row":{".spago/p/typelevel-prelude-7.0.0/src/Type/Row.purs":["1970-01-01T06:00:00Z","cee5ad6bca731f76da8388f32d1e2f644b0dd976734261a01d2a5dd1671924e4534168e085f843f1576c754c917ccdf7fb0e68925fd23a2e121a1bed33d9a4c0"]},"Unsafe.Coerce":{".spago/p/unsafe-coerce-6.0.0/src/Unsafe/Coerce.js":["1970-01-01T05:00:00Z","031c3187f7ce65110a359260041309506e1ff39a97b6eb22c9a8f2e5c14b35db87d509bb5929f245c5d80df6ccd6dadf83579ebe4ac46650acdfa34a493cfc0d"],".spago/p/unsafe-coerce-6.0.0/src/Unsafe/Coerce.purs":["1970-01-01T05:00:00Z","04b214d9cbbf0c438bb2af4b25f8db5d04f247059241982f718c6d83322c3180f0eced0eb5c410860dcdb35650e9129a1cffe87f7279308cc4cf6c6570bba74f"]},"Web.DOM.Internal.Types":{".spago/p/web-dom-6.0.0/src/Web/DOM/Internal/Types.purs":["1970-01-01T05:00:00Z","c113e0d6553a99ad7dc85145336ddf709dd07893a49db715d8ab460be7ed42f6a17df038966e06b02fe7896b6347893fab0caf216dcd4262dd53a15d9d4b6596"]},"Web.Event.Internal.Types":{".spago/p/web-events-4.0.0/src/Web/Event/Internal/Types.purs":["1970-01-01T06:00:00Z","f7497de5e0b09a66fc33a8959bdbe979d56bd185d5a032894a357db7195e82454e55d4a672311d5a4cfb0fed2f55897d3bda655c9a7a68b39e84d7a04619b9ba"]},"Yoga.HTTP.API.Route.Encoding":{".spago/p/yoga-http-api-0.1.0/src/Yoga/HTTP/API/Route/Encoding.purs":["1970-01-01T00:00:00Z","7f41a999eace3d73aacf6ea69c91f9a49a6948959fcfb0fb784ff83479345f88c6e5970783ce7fb4d38e2648caf506e68f889fc185a80a91b029ccfd2c269c0b"]},"Yoga.HTTP.API.Route.Method":{".spago/p/yoga-http-api-0.1.0/src/Yoga/HTTP/API/Route/Method.purs":["1970-01-01T00:00:00Z","344b6850269f52ff385b364d9bebb1e884269d46a900dda3d451028770793c7ec6308ccaaec047664c6b6db9be3861a1039a6af5230c98a588ea47e62bdbea7c"]}}
.psci_modules/package.jsondeleted−1
@@ -1 +0,0 @@
1−{"type":"module"}
.purs-repldeleted−1
@@ -1 +0,0 @@
1−import Prelude
.purslint-cache/props.dbdeleted

Binary file not shown.

LICENSEdeleted−21
@@ -1,21 +0,0 @@
1−The MIT License (MIT)
2−
3−Copyright (c) 2026 Mark Eibes
4−
5−Permission is hereby granted, free of charge, to any person obtaining a copy
6−of this software and associated documentation files (the "Software"), to deal
7−in the Software without restriction, including without limitation the rights
8−to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9−copies of the Software, and to permit persons to whom the Software is
10−furnished to do so, subject to the following conditions:
11−
12−The above copyright notice and this permission notice shall be included in all
13−copies or substantial portions of the Software.
14−
15−THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16−IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17−FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18−AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19−LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20−OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21−SOFTWARE.
README.md+127−153
@@ -2,141 +2,96 @@
22
33Derive type-safe fetch clients from `purescript-yoga-http-api` route definitions.
44
5−## Installation
5+## Concept
66
7−```bash
8−spago install yoga-fetch-om
9−```
7+Similar to how `purescript-yoga-fastify-om` derives servers from HTTP API definitions, this library derives **clients** from the same definitions using the Fetch API.
108
11−Optional query examples below use [`justifill`](https://pursuit.purescript.org/packages/purescript-justifill):
9+## Installation
1210
1311```bash
14−spago install justifill
12+spago install yoga-fetch-om
1513```
1614
17−## Migrating from 0.7
15+## Quick Start
1816
19−Version 0.8 exposes optional query parameters as explicit `Maybe` fields. Calls that passed plain values no longer compile:
17+### 1. Define your API using yoga-http-api
2018
2119```purescript
22−-- 0.7: offset omitted
23−users <- api.listUsers { limit: 10 }
20+import Yoga.Fetch.Om
2421
25−-- 0.8: every optional field is explicit
26−users <- api.listUsers { limit: Just 10, offset: Nothing }
27−allUsers <- api.listUsers { limit: Nothing, offset: Nothing }
22+type UserAPI =
23+ { getUser ::
24+ Route GET
25+ (Path ("users" / "id" : Int))
26+ (Request {})
27+ ( ok :: { body :: User }
28+ , notFound :: { body :: ErrorMessage }
29+ )
30+ , createUser ::
31+ Route POST
32+ (Path "users")
33+ (Request { body :: JSON CreateUserRequest })
34+ ( created :: { body :: User }
35+ , badRequest :: { body :: ErrorMessage }
36+ )
37+ }
2838```
2939
30−Import `Maybe(..)` from `Data.Maybe` when constructing these records directly. Alternatively, [`justifill`](https://pursuit.purescript.org/packages/purescript-justifill) wraps supplied values in `Just` and fills omitted fields with `Nothing`:
40+### 2. Derive a type-safe client
3141
3242```purescript
33−-- offset remains omitted at the call site
34−users <- api.listUsers (justifill { limit: 10 })
43+api = deriveAPI "https://api.example.com" (Proxy :: _ UserAPI)
3544```
3645
37−Path parameters and request bodies keep their existing argument shapes.
38−
39−## Quick Start
40−
41−### Example 1: Simple GET and POST Requests
46+### 3. Use it!
4247
4348```purescript
44−import Yoga.Fetch.Om.Simple (get, post)
45−
46−type User = { id :: Int, name :: String, email :: String }
47−
4849main = do
49− -- Simple GET request
50− user <- get @User "https://api.example.com/users/42" {}
51− log user.name
52−
53− -- Simple POST request with JSON body
54− newUser <- post @User "https://api.example.com/users" {} { name: "Alice", email: "alice@example.com" }
55− log $ "Created user with ID: " <> show newUser.id
50+ -- Compiler ensures you pass the right parameters
51+ result <- api.getUser { id: 42 }
52+
53+ -- Pattern match on all possible responses
54+ result # Variant.match
55+ { ok: \(Response { body: user }) ->
56+ log $ "User: " <> user.name
57+ , notFound: \_ ->
58+ log "User not found"
59+ }
5660```
5761
58−### Example 2: Type-Safe API Client with Full CRUD
62+## Features
5963
60−```purescript
61−import Justifill (justifill)
64+### ✅ Type-Safe Parameters
6265
63−type UserAPI =
64− { health ::
65− Route GET "health" {}
66− ( ok :: { body :: { status :: String } } )
67− , getUser ::
68− Route GET ("users" / "id" : Int) {}
69− ( ok :: { body :: User }
70− , notFound :: { body :: ErrorMessage }
71− )
72− , listUsers ::
73− Route GET ("users" :? { limit :: Int, offset :: Int }) {}
74− ( ok :: { body :: Array User } )
75− , createUser ::
76− Route POST "users" { body :: JSON CreateUserRequest }
77− ( created :: { body :: User }
78− , badRequest :: { body :: ErrorMessage }
79− )
80− , updateUser ::
81− Route PUT ("users" / "id" : Int) { body :: JSON UpdateUserRequest }
82− ( ok :: { body :: User }
83− , notFound :: { body :: ErrorMessage }
84− , badRequest :: { body :: ErrorMessage }
85− )
86− , deleteUser ::
87− Route DELETE ("users" / "id" : Int) {}
88− ( noContent :: { body :: {} }
89− , notFound :: { body :: ErrorMessage }
90− )
91− }
66+The compiler ensures you provide exactly the right parameters:
9267
93−api = client @UserAPI "https://api.example.com"
94−
95−-- Generated methods use ordinary function application.
96−health <- api.health
97−user <- api.createUser { name: "Alice", email: "alice@example.com" }
98− # handleErrors
99− { badRequest: \err -> do
100− log $ "Validation error: " <> err.error
101− throw err
102− }
103−
104−-- Path parameters and request bodies remain separate arguments.
105−updated <- api.updateUser
106− { id: user.id }
107− { name: "Alice Updated", email: user.email }
108− # handleErrors
109− { notFound: \_ -> throw userNotFound
110− , badRequest: \err -> throw validationError
111− }
112−
113−-- Optional query parameters are explicit `Maybe` fields. Justifill can wrap
114−-- supplied values in `Just` and fill omitted fields with `Nothing`.
115−users <- api.listUsers (justifill { limit: 10 })
116−
117−-- The equivalent call without Justifill:
118−allUsers <- api.listUsers { limit: Nothing, offset: Nothing }
119−```
68+```purescript
69+-- Path parameters
70+api.getUser { id: 42 }
12071
121−## More Examples
72+-- Query parameters
73+api.listUsers { limit: 10, offset: 20 }
12274
123−See the test files for complete, runnable examples with all imports:
75+-- Request body
76+api.createUser { body: { name: "Alice", email: "alice@example.com" } }
12477
125−- **[`test/Simple.Spec.purs`](test/Simple.Spec.purs)** - Basic GET/POST/PUT/PATCH/DELETE requests
126−- **[`test/Complete.Example.purs`](test/Complete.Example.purs)** - Full CRUD API with error handling
127−- **[`test/BuildUrl.Spec.purs`](test/BuildUrl.Spec.purs)** - Path parameters and query strings
128−- **[`test/Variant.Spec.purs`](test/Variant.Spec.purs)** - Response variant handling
129−- **[`test/SplitParams.Spec.purs`](test/SplitParams.Spec.purs)** - Parameter extraction patterns
78+-- Mixed parameters
79+api.updateUser { id: 42, body: { name: "Alice Updated" } }
80+```
13081
131−## Features
82+### ✅ Exhaustive Response Handling
13283
133−### ✅ Type-Safe Everything
84+Variant types ensure you handle all possible responses:
13485
135−- **Path parameters**: `/users/:id` requires `{ id :: Int }`; names and values are percent-encoded
136−- **Query parameters**: Type-safe, percent-encoded query strings with explicit `Maybe` fields for optional values
137−- **Request bodies**: `JSON`, `PlainText`, and URL-encoded `FormData`
138−- **Response bodies**: Parsed JSON, `PlainText` as `String`, and `Streaming a` as `Strom {} () a`
139−- **Error handling**: Exhaustive pattern matching on variants
86+```purescript
87+result <- api.createUser { body: newUser }
88+
89+result # Variant.match
90+ { created: \(Response { body }) -> log $ "Created: " <> show body.id
91+ , badRequest: \(Response { body }) -> log $ "Error: " <> body.error
92+ -- Forgot a case? Compile error!
93+ }
94+```
14095
14196### ✅ Single Source of Truth
14297
@@ -147,20 +102,20 @@ Define your API once, use it everywhere:
147102server = buildServer apiRoutes handlers
148103
149104-- Client (yoga-fetch-om)
150−apiClient = client @apiRoutes baseUrl
105+client = deriveAPI baseUrl (Proxy :: _ apiRoutes)
151106```
152107
153108Changes to routes automatically update both client and server!
154109
155−### ✅ Automatic Derivation
110+### ✅ Automatic Everything
156111
157−No manual client code:
158−- ✅ URL building with segment-safe path substitution
159−- ✅ Query construction that preserves existing queries and fragments
160−- ✅ JSON, plain-text, and URL-encoded request serialization
161−- ✅ JSON and plain-text response decoding
162−- ✅ Incremental UTF-8 and binary response streams
112+No manual client code needed:
113+- ✅ URL building with path parameter substitution
114+- ✅ Query string construction
115+- ✅ JSON request serialization
116+- ✅ JSON response parsing
163117- ✅ Status code → variant mapping
118+- ✅ CORS and credentials handling
164119
165120### ✅ Integration with yoga-om
166121
@@ -170,77 +125,97 @@ Works seamlessly with the Om monad:
170125getUserProfile :: Om AppContext AppErrors User
171126getUserProfile = do
172127 { api, userId } <- ask
173− api.getUser { id: userId }
174− # handleErrors { notFound: \_ -> throw { userNotFound: userId } }
128+ result <- liftAff $ api.getUser { id: userId }
129+ case result of
130+ ok -> pure result.body
131+ notFound -> throw { userNotFound: userId }
175132```
176133
134+## Complete Example
135+
136+See [`test/Complete.Example.purs`](test/Complete.Example.purs) for a full working example with:
137+- GET requests with path parameters
138+- GET requests with query parameters
139+- POST/PUT requests with JSON bodies
140+- DELETE requests
141+- Complete error handling
142+
177143## How It Works
178144
179145The library uses PureScript's type system to:
180146
1811471. **Extract parameters** from route definitions at compile time
182− - Path params: `"users" / "id" : Int` → `{ id :: Int }`
183− - Optional query params: `:? { limit :: Int }` → `{ limit :: Maybe Int }`
184− - Required query params: `:? { limit :: Required Int }` → `{ limit :: Int }`
185− - Body params: `{ body :: JSON User }` → `User`
148+ - Path params from segments: `"users" / "id" : Int`
149+ - Query params from `:?` operator: `:? { limit :: Int }`
150+ - Body params from Request type: `{ body :: JSON User }`
186151
187−2. **Build URLs** automatically
188− - Pattern: `/users/:id` + params: `{ id: 42 }` → `/users/42`
189− - Query: `?limit=10&offset=20`
152+2. **Build URLs** by:
153+ - Getting the path pattern: `/users/:id`
154+ - Substituting path params: `/users/42`
155+ - Appending query params: `?limit=10&offset=20`
190156
191−3. **Make requests** with `js-fetch` and `js-promise-aff`
157+3. **Make requests** using:
158+ - `js-fetch` for the fetch API
159+ - `js-promise-aff` to convert Promises → Aff
160+ - `yoga-json` for JSON serialization
192161
193−4. **Parse responses** by mapping status codes to variant labels
194− - `200` → `"ok"`, `404` → `"notFound"`, etc.
162+4. **Parse responses** by:
163+ - Mapping status codes to variant labels (200 → "ok", 404 → "notFound")
164+ - Parsing JSON response bodies
165+ - Constructing typed Response values
195166
196−All automatically based on your route types!
167+All of this happens automatically based on your route types!
197168
198169## API Reference
199170
200−### `client`
171+### `deriveAPI`
201172
202173```purescript
203−client :: forall @routes. String -> Record clients
174+deriveAPI :: String -> Proxy (Record routes) -> Record clients
204175```
205176
206−Derives a record of client functions from a record of routes using Visible Type Application.
177+Derives a record of client functions from a record of routes.
207178
208179**Parameters:**
209−- `@routes` - Your API route type (provided via VTA syntax)
210−- `baseUrl` - Base URL (e.g., `"https://api.example.com"`)
180+- `baseUrl` - The base URL of the API (e.g., `"https://api.example.com"`)
181+- `routes` - Proxy of your API route definitions
182+
183+**Returns:** A record where each route becomes a function taking params and returning `Aff (Variant response)`
211184
212−**Returns:** Record where each route becomes a function returning `Om context errors result`
185+### `deriveClientFn`
213186
214−**Example:**
215187```purescript
216−api = client @UserAPI "https://api.example.com"
188+deriveClientFn :: String -> Proxy (Route method segments request response) -> ClientFn params response
217189```
218190
219−## Features
191+Derives a single client function from a route. Usually you'll use `deriveAPI` instead, but this is useful for individual routes.
220192
221−- ✅ Core client derivation with VTA syntax
193+## Roadmap
194+
195+### Current Version (0.1.0)
196+- ✅ Core client derivation
222197- ✅ All HTTP methods (GET, POST, PUT, PATCH, DELETE)
223198- ✅ Path, query, and body parameters
224−- ✅ Request/response headers
225199- ✅ JSON encoding/decoding
226−- ✅ FormData support
227200- ✅ Variant response handling
228−- ✅ Om monad integration
201+- ✅ CORS support
229202
230−## Testing
203+### Future
204+- ⏳ Request/response headers support
205+- ⏳ Authentication (Bearer tokens, API keys)
206+- ⏳ Request/response interceptors
207+- ⏳ Retry logic with exponential backoff
208+- ⏳ Timeout configuration
209+- ⏳ FormData and file upload support
210+- ⏳ Progress events
211+- ⏳ Request cancellation
231212
232−```sh
233−bun test
234−bun run test:compile-fail
235−bun run coverage
236−```
237−The suite combines example-based specifications with QuickCheck properties for
238−URL encoding, suffix preservation, repeated parameters, optional fields, and
239−query-separator invariants.
213+## Contributing
240214
241−The coverage command uses compiler source maps to report PureScript source
242−coverage, includes JavaScript FFI modules, enforces regression thresholds, and
243−writes HTML and LCOV reports to `coverage/`.
215+Contributions welcome! This library follows the patterns established by the yoga ecosystem:
216+- Type-level programming for automatic derivation
217+- Integration with yoga-json for serialization
218+- Consistent API design with yoga-fastify-om
244219
245220## License
246221
@@ -251,5 +226,4 @@ MIT
251226- [purescript-yoga-http-api](https://github.com/rowtype-yoga/purescript-yoga-http-api) - HTTP API type definitions
252227- [purescript-yoga-fastify-om](https://github.com/rowtype-yoga/purescript-yoga-fastify-om) - Server-side counterpart
253228- [purescript-yoga-json](https://github.com/rowtype-yoga/purescript-yoga-json) - JSON serialization
254−- [purescript-yoga-om](https://github.com/rowtype-yoga/purescript-yoga-om) - Om monad
255−
229+- [purescript-yoga-om](https://github.com/rowtype-yoga/purescript-yoga-om) - Om monad for effects and DI
bun.lockdeleted−1089
@@ -1,1089 +0,0 @@
1−{
2− "lockfileVersion": 1,
3− "workspaces": {
4− "": {
5− "name": "purescript-yoga-fetch-om",
6− "dependencies": {
7− "pino": "^10.3.1",
8− },
9− "devDependencies": {
10− "@fastify/cookie": "^11.1.2",
11− "@fastify/cors": "^11.3.0",
12− "@fastify/formbody": "^9.0.0",
13− "@fastify/helmet": "^13.1.0",
14− "@fastify/multipart": "^10.1.0",
15− "@fastify/rate-limit": "^11.2.0",
16− "@fastify/websocket": "^11.3.0",
17− "argon2": "^0.45.1",
18− "c8": "^12.0.0",
19− "fastify": "^5.7.4",
20− "jose": "^6.2.8",
21− "jsdom": "^28.0.0",
22− "purescript": "^0.15.15",
23− "spago": "^1.0.3",
24− "vitest": "^2.1.8",
25− },
26− },
27− },
28− "packages": {
29− "@acemir/cssom": ["@acemir/cssom@0.9.31", "", {}, "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA=="],
30−
31− "@asamuzakjp/css-color": ["@asamuzakjp/css-color@4.1.2", "", { "dependencies": { "@csstools/css-calc": "^3.0.0", "@csstools/css-color-parser": "^4.0.1", "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0", "lru-cache": "^11.2.5" } }, "sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg=="],
32−
33− "@asamuzakjp/dom-selector": ["@asamuzakjp/dom-selector@6.7.8", "", { "dependencies": { "@asamuzakjp/nwsapi": "^2.3.9", "bidi-js": "^1.0.3", "css-tree": "^3.1.0", "is-potential-custom-element-name": "^1.0.1", "lru-cache": "^11.2.5" } }, "sha512-stisC1nULNc9oH5lakAj8MH88ZxeGxzyWNDfbdCxvJSJIvDsHNZqYvscGTgy/ysgXWLJPt6K/4t0/GjvtKcFJQ=="],
34−
35− "@asamuzakjp/nwsapi": ["@asamuzakjp/nwsapi@2.3.9", "", {}, "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q=="],
36−
37− "@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="],
38−
39− "@csstools/color-helpers": ["@csstools/color-helpers@6.0.1", "", {}, "sha512-NmXRccUJMk2AWA5A7e5a//3bCIMyOu2hAtdRYrhPPHjDxINuCwX1w6rnIZ4xjLcp0ayv6h8Pc3X0eJUGiAAXHQ=="],
40−
41− "@csstools/css-calc": ["@csstools/css-calc@3.0.0", "", { "peerDependencies": { "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0" } }, "sha512-q4d82GTl8BIlh/dTnVsWmxnbWJeb3kiU8eUH71UxlxnS+WIaALmtzTL8gR15PkYOexMQYVk0CO4qIG93C1IvPA=="],
42−
43− "@csstools/css-color-parser": ["@csstools/css-color-parser@4.0.1", "", { "dependencies": { "@csstools/color-helpers": "^6.0.1", "@csstools/css-calc": "^3.0.0" }, "peerDependencies": { "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0" } }, "sha512-vYwO15eRBEkeF6xjAno/KQ61HacNhfQuuU/eGwH67DplL0zD5ZixUa563phQvUelA07yDczIXdtmYojCphKJcw=="],
44−
45− "@csstools/css-parser-algorithms": ["@csstools/css-parser-algorithms@4.0.0", "", { "peerDependencies": { "@csstools/css-tokenizer": "^4.0.0" } }, "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w=="],
46−
47− "@csstools/css-syntax-patches-for-csstree": ["@csstools/css-syntax-patches-for-csstree@1.0.26", "", {}, "sha512-6boXK0KkzT5u5xOgF6TKB+CLq9SOpEGmkZw0g5n9/7yg85wab3UzSxB8TxhLJ31L4SGJ6BCFRw/iftTha1CJXA=="],
48−
49− "@csstools/css-tokenizer": ["@csstools/css-tokenizer@4.0.0", "", {}, "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA=="],
50−
51− "@epic-web/invariant": ["@epic-web/invariant@1.0.0", "", {}, "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA=="],
52−
53− "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
54−
55− "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
56−
57− "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
58−
59− "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
60−
61− "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
62−
63− "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
64−
65− "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
66−
67− "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
68−
69− "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
70−
71− "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
72−
73− "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
74−
75− "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
76−
77− "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
78−
79− "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
80−
81− "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
82−
83− "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
84−
85− "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
86−
87− "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
88−
89− "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
90−
91− "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
92−
93− "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
94−
95− "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
96−
97− "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
98−
99− "@exodus/bytes": ["@exodus/bytes@1.11.0", "", { "peerDependencies": { "@noble/hashes": "^1.8.0 || ^2.0.0" }, "optionalPeers": ["@noble/hashes"] }, "sha512-wO3vd8nsEHdumsXrjGO/v4p6irbg7hy9kvIeR6i2AwylZSk4HJdWgL0FNaVquW1+AweJcdvU1IEpuIWk/WaPnA=="],
100−
101− "@fastify/ajv-compiler": ["@fastify/ajv-compiler@4.0.5", "", { "dependencies": { "ajv": "^8.12.0", "ajv-formats": "^3.0.1", "fast-uri": "^3.0.0" } }, "sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A=="],
102−
103− "@fastify/busboy": ["@fastify/busboy@3.2.1", "", {}, "sha512-tgK4O+57iz5ycYNGXE5ZWj1ES03lD2XnnBYWSbU/3wYZRMQzCUq7Ycds/RdyBZQeL5MU4fxBt6lzbIWf/Bickw=="],
104−
105− "@fastify/cookie": ["@fastify/cookie@11.1.2", "", { "dependencies": { "cookie": "^2.0.0", "fastify-plugin": "^6.0.0" } }, "sha512-Dtrpk/YOGUsbRMvP/8ZqPpwnMRv0qSqodFdoQ2B589Obc7jw4s4Qla+cV72Bsm7WsZJnqlYFX/i7uSBq0xzg6g=="],
106−
107− "@fastify/cors": ["@fastify/cors@11.3.0", "", { "dependencies": { "fastify-plugin": "^6.0.0", "toad-cache": "^3.7.0" } }, "sha512-ggQGua+xHv1MvePbPr0v//xLYEsCXbWspquXCJS9Ot5YoRXq8J8ZWzHnxDBVnbtXosvistXo6LtNzOJswf64Fw=="],
108−
109− "@fastify/deepmerge": ["@fastify/deepmerge@3.2.1", "", {}, "sha512-N5Oqvltoa2r9z1tbx4xjky0oRR60v+T47Ic4J1ukoVQcptLOrIdRnCSdTGmOmajZuHVKlTnfcmrjyqsGEW1ztA=="],
110−
111− "@fastify/error": ["@fastify/error@4.2.0", "", {}, "sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ=="],
112−
113− "@fastify/fast-json-stringify-compiler": ["@fastify/fast-json-stringify-compiler@5.0.3", "", { "dependencies": { "fast-json-stringify": "^6.0.0" } }, "sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ=="],
114−
115− "@fastify/formbody": ["@fastify/formbody@9.0.0", "", { "dependencies": { "fast-querystring": "^1.1.2", "fastify-plugin": "^6.0.0" } }, "sha512-T/af26CSrUARBCvsEmv+DJLPfZlrRKESzqironxP1j7qzuLyKcoZtj6MuTGShuKx1THXugoie2oFbUJxXfGFzA=="],
116−
117− "@fastify/forwarded": ["@fastify/forwarded@3.0.1", "", {}, "sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw=="],
118−
119− "@fastify/helmet": ["@fastify/helmet@13.1.0", "", { "dependencies": { "fastify-plugin": "^6.0.0", "helmet": "^8.0.0" } }, "sha512-SvVOU0IrzYJW1BvSkfq9G1WUdW3dnaRUvg6m0BtgGMBmML62No0VmSu087jecH58SFbicbREgZTPJ89mAguupA=="],
120−
121− "@fastify/merge-json-schemas": ["@fastify/merge-json-schemas@0.2.1", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A=="],
122−
123− "@fastify/multipart": ["@fastify/multipart@10.1.0", "", { "dependencies": { "@fastify/busboy": "^3.0.0", "@fastify/deepmerge": "^3.0.0", "@fastify/error": "^4.0.0", "fastify-plugin": "^6.0.0", "secure-json-parse": "^4.0.0" } }, "sha512-b2r6CovmLQvLFJ5HJDtxVigZjcO9TwkRGslhiNQxsGJwilm5B3eqvXPOVLudC44zXMXJITpQ/iEATIE7zoXqcQ=="],
124−
125− "@fastify/proxy-addr": ["@fastify/proxy-addr@5.1.0", "", { "dependencies": { "@fastify/forwarded": "^3.0.0", "ipaddr.js": "^2.1.0" } }, "sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw=="],
126−
127− "@fastify/rate-limit": ["@fastify/rate-limit@11.2.0", "", { "dependencies": { "@lukeed/ms": "^2.0.2", "fastify-plugin": "^6.0.0", "ip-address": "^10.2.0", "toad-cache": "^3.7.0" } }, "sha512-X7osJd4XSvMoejYrnJkSZYYjY1eNYoBqhjlzf1RakC2204qExFqZFTKj5+T7VuzA/iUI9Z3UoSqQRkB2HpG0oQ=="],
128−
129− "@fastify/websocket": ["@fastify/websocket@11.3.0", "", { "dependencies": { "duplexify": "^4.1.3", "fastify-plugin": "^6.0.0", "ws": "^8.16.0" } }, "sha512-g89ag4BCcD9YP5wBZXixzoLnuf5j89p/sXFcfpCiv2pdEkYYukBEoK3heVzqsp0EAtszVDc2BBZG0KZqeAShIA=="],
130−
131− "@gar/promisify": ["@gar/promisify@1.1.3", "", {}, "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw=="],
132−
133− "@isaacs/cliui": ["@isaacs/cliui@9.0.0", "", {}, "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg=="],
134−
135− "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
136−
137− "@istanbuljs/schema": ["@istanbuljs/schema@0.1.6", "", {}, "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw=="],
138−
139− "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
140−
141− "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
142−
143− "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
144−
145− "@lukeed/ms": ["@lukeed/ms@2.0.2", "", {}, "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA=="],
146−
147− "@nodelib/fs.scandir": ["@nodelib/fs.scandir@4.0.1", "", { "dependencies": { "@nodelib/fs.stat": "4.0.0", "run-parallel": "^1.2.0" } }, "sha512-vAkI715yhnmiPupY+dq+xenu5Tdf2TBQ66jLvBIcCddtz+5Q8LbMKaf9CIJJreez8fQ8fgaY+RaywQx8RJIWpw=="],
148−
149− "@nodelib/fs.stat": ["@nodelib/fs.stat@4.0.0", "", {}, "sha512-ctr6bByzksKRCV0bavi8WoQevU6plSp2IkllIsEqaiKe2mwNNnaluhnRhcsgGZHrrHk57B3lf95MkLMO3STYcg=="],
150−
151− "@nodelib/fs.walk": ["@nodelib/fs.walk@3.0.1", "", { "dependencies": { "@nodelib/fs.scandir": "4.0.1", "fastq": "^1.15.0" } }, "sha512-nIh/M6Kh3ZtOmlY00DaUYB4xeeV6F3/ts1l29iwl3/cfyY/OuCfUx+v08zgx8TKPTifXRcjjqVQ4KB2zOYSbyw=="],
152−
153− "@npmcli/fs": ["@npmcli/fs@2.1.2", "", { "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" } }, "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ=="],
154−
155− "@npmcli/move-file": ["@npmcli/move-file@2.0.1", "", { "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ=="],
156−
157− "@phc/format": ["@phc/format@1.0.0", "", {}, "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ=="],
158−
159− "@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="],
160−
161− "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.57.1", "", { "os": "android", "cpu": "arm" }, "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg=="],
162−
163− "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.57.1", "", { "os": "android", "cpu": "arm64" }, "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w=="],
164−
165− "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.57.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg=="],
166−
167− "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.57.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w=="],
168−
169− "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.57.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug=="],
170−
171− "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.57.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q=="],
172−
173− "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.57.1", "", { "os": "linux", "cpu": "arm" }, "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw=="],
174−
175− "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.57.1", "", { "os": "linux", "cpu": "arm" }, "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw=="],
176−
177− "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.57.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g=="],
178−
179− "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.57.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q=="],
180−
181− "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA=="],
182−
183− "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw=="],
184−
185− "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.57.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w=="],
186−
187− "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.57.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw=="],
188−
189− "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A=="],
190−
191− "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw=="],
192−
193− "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.57.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg=="],
194−
195− "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg=="],
196−
197− "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw=="],
198−
199− "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.57.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw=="],
200−
201− "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.57.1", "", { "os": "none", "cpu": "arm64" }, "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ=="],
202−
203− "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.57.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ=="],
204−
205− "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.57.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew=="],
206−
207− "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ=="],
208−
209− "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA=="],
210−
211− "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="],
212−
213− "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
214−
215− "@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.6", "", {}, "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="],
216−
217− "@vitest/expect": ["@vitest/expect@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw=="],
218−
219− "@vitest/mocker": ["@vitest/mocker@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.12" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg=="],
220−
221− "@vitest/pretty-format": ["@vitest/pretty-format@2.1.9", "", { "dependencies": { "tinyrainbow": "^1.2.0" } }, "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ=="],
222−
223− "@vitest/runner": ["@vitest/runner@2.1.9", "", { "dependencies": { "@vitest/utils": "2.1.9", "pathe": "^1.1.2" } }, "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g=="],
224−
225− "@vitest/snapshot": ["@vitest/snapshot@2.1.9", "", { "dependencies": { "@vitest/pretty-format": "2.1.9", "magic-string": "^0.30.12", "pathe": "^1.1.2" } }, "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ=="],
226−
227− "@vitest/spy": ["@vitest/spy@2.1.9", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ=="],
228−
229− "@vitest/utils": ["@vitest/utils@2.1.9", "", { "dependencies": { "@vitest/pretty-format": "2.1.9", "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ=="],
230−
231− "abstract-logging": ["abstract-logging@2.0.1", "", {}, "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA=="],
232−
233− "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
234−
235− "agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="],
236−
237− "aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="],
238−
239− "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
240−
241− "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
242−
243− "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
244−
245− "ansi-regex": ["ansi-regex@6.3.0", "", {}, "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ=="],
246−
247− "ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
248−
249− "aproba": ["aproba@1.2.0", "", {}, "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="],
250−
251− "argon2": ["argon2@0.45.1", "", { "dependencies": { "@phc/format": "^1.0.0", "cross-env": "^10.1.0", "node-addon-api": "^8.9.0", "node-gyp-build": "^4.8.4" } }, "sha512-skm+/WCjkGqCQxF7FG1LuZXM5yvbFjgbfiCGsud2oLgaDhh6b6dbH0b1EkghbM+xx4Bj8Ape+KKgixoIlWZicQ=="],
252−
253− "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
254−
255− "asn1": ["asn1@0.2.6", "", { "dependencies": { "safer-buffer": "~2.1.0" } }, "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ=="],
256−
257− "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
258−
259− "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="],
260−
261− "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="],
262−
263− "avvio": ["avvio@9.1.0", "", { "dependencies": { "@fastify/error": "^4.0.0", "fastq": "^1.17.1" } }, "sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw=="],
264−
265− "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
266−
267− "bcrypt-pbkdf": ["bcrypt-pbkdf@1.0.2", "", { "dependencies": { "tweetnacl": "^0.14.3" } }, "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w=="],
268−
269− "bidi-js": ["bidi-js@1.0.3", "", { "dependencies": { "require-from-string": "^2.0.2" } }, "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw=="],
270−
271− "bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="],
272−
273− "brace-expansion": ["brace-expansion@5.0.9", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg=="],
274−
275− "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
276−
277− "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
278−
279− "buildcheck": ["buildcheck@0.0.7", "", {}, "sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA=="],
280−
281− "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
282−
283− "byline": ["byline@5.0.0", "", {}, "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q=="],
284−
285− "c8": ["c8@12.0.0", "", { "dependencies": { "@bcoe/v8-coverage": "^1.0.1", "@istanbuljs/schema": "^0.1.3", "find-up": "^5.0.0", "foreground-child": "^3.1.1", "istanbul-lib-coverage": "^3.2.0", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.1.6", "test-exclude": "^8.0.0", "v8-to-istanbul": "^9.0.0", "yargs": "^18.0.0", "yargs-parser": "^21.1.1" }, "peerDependencies": { "monocart-coverage-reports": "^2" }, "optionalPeers": ["monocart-coverage-reports"], "bin": { "c8": "bin/c8.js" } }, "sha512-4zpJvrd1nKWutnnKC2pXkFmb6iM1l+ffN//o1CzlTNwW7GSOs9a1xrLqkC48nU8oEkjmPZLPiwMsIaOvoF4Pqg=="],
286−
287− "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
288−
289− "cacache": ["cacache@11.3.3", "", { "dependencies": { "bluebird": "^3.5.5", "chownr": "^1.1.1", "figgy-pudding": "^3.5.1", "glob": "^7.1.4", "graceful-fs": "^4.1.15", "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.3", "ssri": "^6.0.1", "unique-filename": "^1.1.1", "y18n": "^4.0.0" } }, "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA=="],
290−
291− "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="],
292−
293− "chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
294−
295− "check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="],
296−
297− "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
298−
299− "clean-stack": ["clean-stack@2.2.0", "", {}, "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="],
300−
301− "cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
302−
303− "cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="],
304−
305− "color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
306−
307− "color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
308−
309− "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
310−
311− "concat-stream": ["concat-stream@1.6.2", "", { "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" } }, "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw=="],
312−
313− "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
314−
315− "cookie": ["cookie@2.0.1", "", {}, "sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w=="],
316−
317− "copy-concurrently": ["copy-concurrently@1.0.5", "", { "dependencies": { "aproba": "^1.1.1", "fs-write-stream-atomic": "^1.0.8", "iferr": "^0.1.5", "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" } }, "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A=="],
318−
319− "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
320−
321− "cpu-features": ["cpu-features@0.0.10", "", { "dependencies": { "buildcheck": "~0.0.6", "nan": "^2.19.0" } }, "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA=="],
322−
323− "cross-env": ["cross-env@10.1.0", "", { "dependencies": { "@epic-web/invariant": "^1.0.0", "cross-spawn": "^7.0.6" }, "bin": { "cross-env": "dist/bin/cross-env.js", "cross-env-shell": "dist/bin/cross-env-shell.js" } }, "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw=="],
324−
325− "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
326−
327− "css-tree": ["css-tree@3.1.0", "", { "dependencies": { "mdn-data": "2.12.2", "source-map-js": "^1.0.1" } }, "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w=="],
328−
329− "cssstyle": ["cssstyle@5.3.7", "", { "dependencies": { "@asamuzakjp/css-color": "^4.1.1", "@csstools/css-syntax-patches-for-csstree": "^1.0.21", "css-tree": "^3.1.0", "lru-cache": "^11.2.4" } }, "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ=="],
330−
331− "cyclist": ["cyclist@1.0.2", "", {}, "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA=="],
332−
333− "data-urls": ["data-urls@7.0.0", "", { "dependencies": { "whatwg-mimetype": "^5.0.0", "whatwg-url": "^16.0.0" } }, "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA=="],
334−
335− "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
336−
337− "decimal.js": ["decimal.js@10.6.0", "", {}, "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="],
338−
339− "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
340−
341− "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],
342−
343− "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],
344−
345− "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
346−
347− "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
348−
349− "duplexify": ["duplexify@4.1.3", "", { "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", "stream-shift": "^1.0.2" } }, "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA=="],
350−
351− "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
352−
353− "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="],
354−
355− "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
356−
357− "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
358−
359− "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="],
360−
361− "err-code": ["err-code@2.0.3", "", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="],
362−
363− "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="],
364−
365− "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
366−
367− "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
368−
369− "escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
370−
371− "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
372−
373− "execa": ["execa@2.1.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^3.0.0", "onetime": "^5.1.0", "p-finally": "^2.0.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" } }, "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw=="],
374−
375− "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
376−
377− "fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
378−
379− "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
380−
381− "fast-json-stringify": ["fast-json-stringify@6.3.0", "", { "dependencies": { "@fastify/merge-json-schemas": "^0.2.0", "ajv": "^8.12.0", "ajv-formats": "^3.0.1", "fast-uri": "^3.0.0", "json-schema-ref-resolver": "^3.0.0", "rfdc": "^1.2.0" } }, "sha512-oRCntNDY/329HJPlmdNLIdogNtt6Vyjb1WuT01Soss3slIdyUp8kAcDU3saQTOquEK8KFVfwIIF7FebxUAu+yA=="],
382−
383− "fast-querystring": ["fast-querystring@1.1.2", "", { "dependencies": { "fast-decode-uri-component": "^1.0.1" } }, "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg=="],
384−
385− "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
386−
387− "fastify": ["fastify@5.7.4", "", { "dependencies": { "@fastify/ajv-compiler": "^4.0.5", "@fastify/error": "^4.0.0", "@fastify/fast-json-stringify-compiler": "^5.0.0", "@fastify/proxy-addr": "^5.0.0", "abstract-logging": "^2.0.1", "avvio": "^9.0.0", "fast-json-stringify": "^6.0.0", "find-my-way": "^9.0.0", "light-my-request": "^6.0.0", "pino": "^10.1.0", "process-warning": "^5.0.0", "rfdc": "^1.3.1", "secure-json-parse": "^4.0.0", "semver": "^7.6.0", "toad-cache": "^3.7.0" } }, "sha512-e6l5NsRdaEP8rdD8VR0ErJASeyaRbzXYpmkrpr2SuvuMq6Si3lvsaVy5C+7gLanEkvjpMDzBXWE5HPeb/hgTxA=="],
388−
389− "fastify-plugin": ["fastify-plugin@6.0.0", "", {}, "sha512-fZOty7z3O7vOliF6d8bHE3wiEh1KcNnKEQensSgTk9C1DvN6nRLS++XVd86v33Hw/8u9Un8A1zDrQ8ujcQDHEg=="],
390−
391− "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
392−
393− "figgy-pudding": ["figgy-pudding@3.5.2", "", {}, "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw=="],
394−
395− "filesize": ["filesize@4.2.1", "", {}, "sha512-bP82Hi8VRZX/TUBKfE24iiUGsB/sfm2WUrwTQyAzQrhO3V9IhcBBNBXMyzLY5orACxRyYJ3d2HeRVX+eFv4lmA=="],
396−
397− "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
398−
399− "find-my-way": ["find-my-way@9.4.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-querystring": "^1.0.0", "safe-regex2": "^5.0.0" } }, "sha512-5Ye4vHsypZRYtS01ob/iwHzGRUDELlsoCftI/OZFhcLs1M0tkGPcXldE80TAZC5yYuJMBPJQQ43UHlqbJWiX2w=="],
400−
401− "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
402−
403− "flush-write-stream": ["flush-write-stream@1.1.1", "", { "dependencies": { "inherits": "^2.0.3", "readable-stream": "^2.3.6" } }, "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w=="],
404−
405− "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
406−
407− "from2": ["from2@2.3.0", "", { "dependencies": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" } }, "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g=="],
408−
409− "fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="],
410−
411− "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="],
412−
413− "fs-write-stream-atomic": ["fs-write-stream-atomic@1.0.10", "", { "dependencies": { "graceful-fs": "^4.1.2", "iferr": "^0.1.5", "imurmurhash": "^0.1.4", "readable-stream": "1 || 2" } }, "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA=="],
414−
415− "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
416−
417− "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
418−
419− "fuse.js": ["fuse.js@7.1.0", "", {}, "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ=="],
420−
421− "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
422−
423− "get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="],
424−
425− "get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
426−
427− "glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="],
428−
429− "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
430−
431− "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
432−
433− "helmet": ["helmet@8.3.0", "", {}, "sha512-Qgpiaws3Sm30Av8Eah6sjMCZZwjlBu+E68rhpCWBshY1lb09HtLwj5GviX0OyQIn+ulUS0iX0AxN5n3tLZzz1w=="],
434−
435− "html-encoding-sniffer": ["html-encoding-sniffer@6.0.0", "", { "dependencies": { "@exodus/bytes": "^1.6.0" } }, "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg=="],
436−
437− "html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="],
438−
439− "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="],
440−
441− "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
442−
443− "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
444−
445− "humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="],
446−
447− "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
448−
449− "iferr": ["iferr@0.1.5", "", {}, "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA=="],
450−
451− "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
452−
453− "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
454−
455− "infer-owner": ["infer-owner@1.0.4", "", {}, "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="],
456−
457− "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="],
458−
459− "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
460−
461− "ip-address": ["ip-address@10.5.0", "", {}, "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g=="],
462−
463− "ipaddr.js": ["ipaddr.js@2.3.0", "", {}, "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg=="],
464−
465− "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
466−
467− "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
468−
469− "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
470−
471− "is-lambda": ["is-lambda@1.0.1", "", {}, "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ=="],
472−
473− "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
474−
475− "is-plain-obj": ["is-plain-obj@2.1.0", "", {}, "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="],
476−
477− "is-potential-custom-element-name": ["is-potential-custom-element-name@1.0.1", "", {}, "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="],
478−
479− "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
480−
481− "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
482−
483− "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
484−
485− "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
486−
487− "istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="],
488−
489− "istanbul-lib-report": ["istanbul-lib-report@3.0.1", "", { "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", "supports-color": "^7.1.0" } }, "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw=="],
490−
491− "istanbul-reports": ["istanbul-reports@3.2.0", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA=="],
492−
493− "jackspeak": ["jackspeak@4.2.3", "", { "dependencies": { "@isaacs/cliui": "^9.0.0" } }, "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg=="],
494−
495− "jose": ["jose@6.2.8", "", {}, "sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ=="],
496−
497− "jsdom": ["jsdom@28.0.0", "", { "dependencies": { "@acemir/cssom": "^0.9.31", "@asamuzakjp/dom-selector": "^6.7.6", "@exodus/bytes": "^1.11.0", "cssstyle": "^5.3.7", "data-urls": "^7.0.0", "decimal.js": "^10.6.0", "html-encoding-sniffer": "^6.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", "is-potential-custom-element-name": "^1.0.1", "parse5": "^8.0.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^6.0.0", "undici": "^7.20.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^8.0.1", "whatwg-mimetype": "^5.0.0", "whatwg-url": "^16.0.0", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^3.0.0" }, "optionalPeers": ["canvas"] }, "sha512-KDYJgZ6T2TKdU8yBfYueq5EPG/EylMsBvCaenWMJb2OXmjgczzwveRCoJ+Hgj1lXPDyasvrgneSn4GBuR1hYyA=="],
498−
499− "json-schema-ref-resolver": ["json-schema-ref-resolver@3.0.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A=="],
500−
501− "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
502−
503− "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],
504−
505− "light-my-request": ["light-my-request@6.6.0", "", { "dependencies": { "cookie": "^1.0.1", "process-warning": "^4.0.0", "set-cookie-parser": "^2.6.0" } }, "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A=="],
506−
507− "linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="],
508−
509− "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
510−
511− "log-symbols": ["log-symbols@3.0.0", "", { "dependencies": { "chalk": "^2.4.2" } }, "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ=="],
512−
513− "log-update": ["log-update@4.0.0", "", { "dependencies": { "ansi-escapes": "^4.3.0", "cli-cursor": "^3.1.0", "slice-ansi": "^4.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg=="],
514−
515− "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
516−
517− "lru-cache": ["lru-cache@11.2.5", "", {}, "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw=="],
518−
519− "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
520−
521− "make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="],
522−
523− "make-fetch-happen": ["make-fetch-happen@10.2.1", "", { "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", "ssri": "^9.0.0" } }, "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w=="],
524−
525− "markdown-it": ["markdown-it@14.1.0", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg=="],
526−
527− "mdn-data": ["mdn-data@2.12.2", "", {}, "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA=="],
528−
529− "mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="],
530−
531− "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
532−
533− "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
534−
535− "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
536−
537− "minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="],
538−
539− "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
540−
541− "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
542−
543− "minipass-collect": ["minipass-collect@1.0.2", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA=="],
544−
545− "minipass-fetch": ["minipass-fetch@2.1.2", "", { "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA=="],
546−
547− "minipass-flush": ["minipass-flush@1.0.5", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw=="],
548−
549− "minipass-pipeline": ["minipass-pipeline@1.2.4", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="],
550−
551− "minipass-sized": ["minipass-sized@1.0.3", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g=="],
552−
553− "minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
554−
555− "mississippi": ["mississippi@3.0.0", "", { "dependencies": { "concat-stream": "^1.5.0", "duplexify": "^3.4.2", "end-of-stream": "^1.1.0", "flush-write-stream": "^1.0.0", "from2": "^2.1.0", "parallel-transform": "^1.1.0", "pump": "^3.0.0", "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" } }, "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA=="],
556−
557− "mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="],
558−
559− "move-concurrently": ["move-concurrently@1.0.1", "", { "dependencies": { "aproba": "^1.1.1", "copy-concurrently": "^1.0.0", "fs-write-stream-atomic": "^1.0.8", "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" } }, "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ=="],
560−
561− "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
562−
563− "nan": ["nan@2.25.0", "", {}, "sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g=="],
564−
565− "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
566−
567− "negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="],
568−
569− "node-addon-api": ["node-addon-api@8.9.2", "", {}, "sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg=="],
570−
571− "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="],
572−
573− "npm-run-path": ["npm-run-path@3.1.0", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg=="],
574−
575− "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="],
576−
577− "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
578−
579− "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
580−
581− "open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
582−
583− "p-finally": ["p-finally@2.0.1", "", {}, "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw=="],
584−
585− "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
586−
587− "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
588−
589− "p-map": ["p-map@4.0.0", "", { "dependencies": { "aggregate-error": "^3.0.0" } }, "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ=="],
590−
591− "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
592−
593− "parallel-transform": ["parallel-transform@1.2.0", "", { "dependencies": { "cyclist": "^1.0.1", "inherits": "^2.0.3", "readable-stream": "^2.1.5" } }, "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg=="],
594−
595− "parse5": ["parse5@8.0.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA=="],
596−
597− "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
598−
599− "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
600−
601− "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
602−
603− "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
604−
605− "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="],
606−
607− "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="],
608−
609− "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
610−
611− "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
612−
613− "pino": ["pino@10.3.1", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^3.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^4.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg=="],
614−
615− "pino-abstract-transport": ["pino-abstract-transport@3.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg=="],
616−
617− "pino-std-serializers": ["pino-std-serializers@7.1.0", "", {}, "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw=="],
618−
619− "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
620−
621− "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
622−
623− "process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="],
624−
625− "promise-inflight": ["promise-inflight@1.0.1", "", {}, "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g=="],
626−
627− "promise-retry": ["promise-retry@2.0.1", "", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="],
628−
629− "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
630−
631− "pumpify": ["pumpify@1.5.1", "", { "dependencies": { "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" } }, "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ=="],
632−
633− "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
634−
635− "punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="],
636−
637− "purescript": ["purescript@0.15.15", "", { "dependencies": { "purescript-installer": "^0.3.5" }, "bin": { "purs": "purs.bin" } }, "sha512-4gwLNJa4KRiV+Wl+lyMY4MUFM6cSnIqvz7MvSTdLdvXJN2P9CrABnNbSspaokkNRFd9soWHBFDlYsAtRchqHtg=="],
638−
639− "purescript-installer": ["purescript-installer@0.3.5", "", { "dependencies": { "byline": "^5.0.0", "cacache": "^11.3.2", "chalk": "^2.4.2", "env-paths": "^2.2.0", "execa": "^2.0.3", "filesize": "^4.1.2", "is-plain-obj": "^2.0.0", "log-symbols": "^3.0.0", "log-update": "^4.0.0", "make-fetch-happen": "^10.0.0", "minimist": "^1.2.0", "ms": "^2.1.2", "once": "^1.4.0", "rimraf": "^2.6.3", "semver": "^7.3.7", "tar": "^6.1.11", "which": "^1.3.1", "zen-observable": "^0.8.14" }, "bin": { "install-purescript": "index.js" } }, "sha512-w04BBvW4BSQlspLsZ9Bs5vtUBZqvC4bC+FizC5GUp2/rpmYvXJ0CTf79Q3MKo2A8p1ZjqbhCI+SqdTQ30UZUIQ=="],
640−
641− "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
642−
643− "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="],
644−
645− "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
646−
647− "readline-sync": ["readline-sync@1.4.10", "", {}, "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw=="],
648−
649− "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="],
650−
651− "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
652−
653− "restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
654−
655− "ret": ["ret@0.5.0", "", {}, "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw=="],
656−
657− "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="],
658−
659− "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
660−
661− "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
662−
663− "rimraf": ["rimraf@2.7.1", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w=="],
664−
665− "rollup": ["rollup@4.57.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.57.1", "@rollup/rollup-android-arm64": "4.57.1", "@rollup/rollup-darwin-arm64": "4.57.1", "@rollup/rollup-darwin-x64": "4.57.1", "@rollup/rollup-freebsd-arm64": "4.57.1", "@rollup/rollup-freebsd-x64": "4.57.1", "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", "@rollup/rollup-linux-arm-musleabihf": "4.57.1", "@rollup/rollup-linux-arm64-gnu": "4.57.1", "@rollup/rollup-linux-arm64-musl": "4.57.1", "@rollup/rollup-linux-loong64-gnu": "4.57.1", "@rollup/rollup-linux-loong64-musl": "4.57.1", "@rollup/rollup-linux-ppc64-gnu": "4.57.1", "@rollup/rollup-linux-ppc64-musl": "4.57.1", "@rollup/rollup-linux-riscv64-gnu": "4.57.1", "@rollup/rollup-linux-riscv64-musl": "4.57.1", "@rollup/rollup-linux-s390x-gnu": "4.57.1", "@rollup/rollup-linux-x64-gnu": "4.57.1", "@rollup/rollup-linux-x64-musl": "4.57.1", "@rollup/rollup-openbsd-x64": "4.57.1", "@rollup/rollup-openharmony-arm64": "4.57.1", "@rollup/rollup-win32-arm64-msvc": "4.57.1", "@rollup/rollup-win32-ia32-msvc": "4.57.1", "@rollup/rollup-win32-x64-gnu": "4.57.1", "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A=="],
666−
667− "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],
668−
669− "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
670−
671− "run-queue": ["run-queue@1.0.3", "", { "dependencies": { "aproba": "^1.1.1" } }, "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg=="],
672−
673− "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
674−
675− "safe-regex2": ["safe-regex2@5.0.0", "", { "dependencies": { "ret": "~0.5.0" } }, "sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw=="],
676−
677− "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="],
678−
679− "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
680−
681− "saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="],
682−
683− "secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="],
684−
685− "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
686−
687− "set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="],
688−
689− "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
690−
691− "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
692−
693− "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
694−
695− "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
696−
697− "slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="],
698−
699− "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
700−
701− "socks": ["socks@2.8.7", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="],
702−
703− "socks-proxy-agent": ["socks-proxy-agent@7.0.0", "", { "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" } }, "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww=="],
704−
705− "sonic-boom": ["sonic-boom@4.2.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww=="],
706−
707− "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
708−
709− "spago": ["spago@1.0.4", "", { "dependencies": { "@nodelib/fs.walk": "^3.0.1", "env-paths": "^3.0.0", "fs-extra": "^11.3.0", "fuse.js": "^7.1.0", "glob": "^11.0.1", "markdown-it": "^14.1.0", "micromatch": "^4.0.8", "open": "^10.1.0", "picomatch": "^4.0.2", "punycode": "^2.3.1", "readline-sync": "^1.4.10", "semver": "^7.7.1", "spdx-expression-parse": "^4.0.0", "ssh2": "^1.16.0", "supports-color": "^10.0.0", "tar": "^7.4.3", "tmp": "^0.2.3", "xhr2": "^0.2.1", "yaml": "^2.7.0" }, "bin": { "spago": "bin/bundle.js" } }, "sha512-iv1HBJppzGJRWWd/DZ32oselcKrhq/PboBdXy5VMX4GiwRqLCUUp3loZ6Yhm8zymNRKHkN/w52cxX6k521nwng=="],
710−
711− "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="],
712−
713− "spdx-expression-parse": ["spdx-expression-parse@4.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ=="],
714−
715− "spdx-license-ids": ["spdx-license-ids@3.0.22", "", {}, "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ=="],
716−
717− "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
718−
719− "ssh2": ["ssh2@1.17.0", "", { "dependencies": { "asn1": "^0.2.6", "bcrypt-pbkdf": "^1.0.2" }, "optionalDependencies": { "cpu-features": "~0.0.10", "nan": "^2.23.0" } }, "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ=="],
720−
721− "ssri": ["ssri@6.0.2", "", { "dependencies": { "figgy-pudding": "^3.5.1" } }, "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q=="],
722−
723− "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
724−
725− "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
726−
727− "stream-each": ["stream-each@1.2.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "stream-shift": "^1.0.0" } }, "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw=="],
728−
729− "stream-shift": ["stream-shift@1.0.3", "", {}, "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="],
730−
731− "string-width": ["string-width@8.2.2", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg=="],
732−
733− "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
734−
735− "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
736−
737− "strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
738−
739− "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
740−
741− "symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="],
742−
743− "tar": ["tar@7.5.7", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ=="],
744−
745− "test-exclude": ["test-exclude@8.0.0", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^13.0.6", "minimatch": "^10.2.2" } }, "sha512-ZOffsNrXYggvU1mDGHk54I96r26P8SyMjO5slMKSc7+IWmtB/MQKnEC2fP51imB3/pT6YK5cT5E8f+Dd9KdyOQ=="],
746−
747− "thread-stream": ["thread-stream@4.0.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA=="],
748−
749− "through2": ["through2@2.0.5", "", { "dependencies": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" } }, "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ=="],
750−
751− "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
752−
753− "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
754−
755− "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="],
756−
757− "tinyrainbow": ["tinyrainbow@1.2.0", "", {}, "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ=="],
758−
759− "tinyspy": ["tinyspy@3.0.2", "", {}, "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q=="],
760−
761− "tldts": ["tldts@7.0.22", "", { "dependencies": { "tldts-core": "^7.0.22" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-nqpKFC53CgopKPjT6Wfb6tpIcZXHcI6G37hesvikhx0EmUGPkZrujRyAjgnmp1SHNgpQfKVanZ+KfpANFt2Hxw=="],
762−
763− "tldts-core": ["tldts-core@7.0.22", "", {}, "sha512-KgbTDC5wzlL6j/x6np6wCnDSMUq4kucHNm00KXPbfNzmllCmtmvtykJHfmgdHntwIeupW04y8s1N/43S1PkQDw=="],
764−
765− "tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="],
766−
767− "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
768−
769− "toad-cache": ["toad-cache@3.7.0", "", {}, "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw=="],
770−
771− "tough-cookie": ["tough-cookie@6.0.0", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w=="],
772−
773− "tr46": ["tr46@6.0.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw=="],
774−
775− "tweetnacl": ["tweetnacl@0.14.5", "", {}, "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="],
776−
777− "type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
778−
779− "typedarray": ["typedarray@0.0.6", "", {}, "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="],
780−
781− "uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="],
782−
783− "undici": ["undici@7.21.0", "", {}, "sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg=="],
784−
785− "unique-filename": ["unique-filename@1.1.1", "", { "dependencies": { "unique-slug": "^2.0.0" } }, "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ=="],
786−
787− "unique-slug": ["unique-slug@2.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w=="],
788−
789− "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
790−
791− "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
792−
793− "v8-to-istanbul": ["v8-to-istanbul@9.3.0", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^2.0.0" } }, "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA=="],
794−
795− "vite": ["vite@5.4.21", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="],
796−
797− "vite-node": ["vite-node@2.1.9", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.3.7", "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA=="],
798−
799− "vitest": ["vitest@2.1.9", "", { "dependencies": { "@vitest/expect": "2.1.9", "@vitest/mocker": "2.1.9", "@vitest/pretty-format": "^2.1.9", "@vitest/runner": "2.1.9", "@vitest/snapshot": "2.1.9", "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "debug": "^4.3.7", "expect-type": "^1.1.0", "magic-string": "^0.30.12", "pathe": "^1.1.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.1", "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", "vite-node": "2.1.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "2.1.9", "@vitest/ui": "2.1.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q=="],
800−
801− "w3c-xmlserializer": ["w3c-xmlserializer@5.0.0", "", { "dependencies": { "xml-name-validator": "^5.0.0" } }, "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA=="],
802−
803− "webidl-conversions": ["webidl-conversions@8.0.1", "", {}, "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ=="],
804−
805− "whatwg-mimetype": ["whatwg-mimetype@5.0.0", "", {}, "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw=="],
806−
807− "whatwg-url": ["whatwg-url@16.0.0", "", { "dependencies": { "@exodus/bytes": "^1.11.0", "tr46": "^6.0.0", "webidl-conversions": "^8.0.1" } }, "sha512-9CcxtEKsf53UFwkSUZjG+9vydAsFO4lFHBpJUtjBcoJOCJpKnSJNwCw813zrYJHpCJ7sgfbtOe0V5Ku7Pa1XMQ=="],
808−
809− "which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
810−
811− "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
812−
813− "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
814−
815− "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
816−
817− "ws": ["ws@8.21.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="],
818−
819− "wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="],
820−
821− "xhr2": ["xhr2@0.2.1", "", {}, "sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw=="],
822−
823− "xml-name-validator": ["xml-name-validator@5.0.0", "", {}, "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg=="],
824−
825− "xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="],
826−
827− "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
828−
829− "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
830−
831− "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
832−
833− "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="],
834−
835− "yargs": ["yargs@18.1.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^8.2.1", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg=="],
836−
837− "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
838−
839− "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
840−
841− "zen-observable": ["zen-observable@0.8.15", "", {}, "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ=="],
842−
843− "@npmcli/move-file/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
844−
845− "@npmcli/move-file/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
846−
847− "cacache/chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
848−
849− "cacache/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
850−
851− "cacache/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
852−
853− "cacache/y18n": ["y18n@4.0.3", "", {}, "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="],
854−
855− "chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
856−
857− "cliui/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
858−
859− "concat-stream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
860−
861− "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
862−
863− "execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
864−
865− "flush-write-stream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
866−
867− "from2/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
868−
869− "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
870−
871− "fs-write-stream-atomic/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
872−
873− "istanbul-lib-report/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
874−
875− "light-my-request/cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
876−
877− "light-my-request/process-warning": ["process-warning@4.0.1", "", {}, "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q=="],
878−
879− "log-update/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
880−
881− "make-fetch-happen/cacache": ["cacache@16.1.3", "", { "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", "glob": "^8.0.1", "infer-owner": "^1.0.4", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", "ssri": "^9.0.0", "tar": "^6.1.11", "unique-filename": "^2.0.0" } }, "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ=="],
882−
883− "make-fetch-happen/http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="],
884−
885− "make-fetch-happen/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
886−
887− "make-fetch-happen/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
888−
889− "make-fetch-happen/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
890−
891− "make-fetch-happen/ssri": ["ssri@9.0.1", "", { "dependencies": { "minipass": "^3.1.1" } }, "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q=="],
892−
893− "markdown-it/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
894−
895− "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
896−
897− "minipass-collect/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
898−
899− "minipass-fetch/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
900−
901− "minipass-fetch/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
902−
903− "minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
904−
905− "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
906−
907− "minipass-sized/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
908−
909− "mississippi/duplexify": ["duplexify@3.7.1", "", { "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g=="],
910−
911− "parallel-transform/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
912−
913− "pumpify/duplexify": ["duplexify@3.7.1", "", { "dependencies": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" } }, "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g=="],
914−
915− "pumpify/pump": ["pump@2.0.1", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA=="],
916−
917− "purescript-installer/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
918−
919− "purescript-installer/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
920−
921− "restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
922−
923− "rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
924−
925− "slice-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
926−
927− "socks/ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],
928−
929− "socks-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
930−
931− "test-exclude/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
932−
933− "through2/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
934−
935− "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
936−
937− "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
938−
939− "yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
940−
941− "@npmcli/move-file/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
942−
943− "cacache/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
944−
945− "cacache/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
946−
947− "chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
948−
949− "concat-stream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
950−
951− "concat-stream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
952−
953− "flush-write-stream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
954−
955− "flush-write-stream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
956−
957− "from2/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
958−
959− "from2/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
960−
961− "fs-minipass/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
962−
963− "fs-write-stream-atomic/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
964−
965− "fs-write-stream-atomic/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
966−
967− "log-update/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
968−
969− "log-update/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
970−
971− "log-update/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
972−
973− "make-fetch-happen/cacache/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
974−
975− "make-fetch-happen/cacache/glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="],
976−
977− "make-fetch-happen/cacache/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
978−
979− "make-fetch-happen/cacache/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
980−
981− "make-fetch-happen/cacache/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
982−
983− "make-fetch-happen/cacache/unique-filename": ["unique-filename@2.0.1", "", { "dependencies": { "unique-slug": "^3.0.0" } }, "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A=="],
984−
985− "make-fetch-happen/http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
986−
987− "make-fetch-happen/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
988−
989− "make-fetch-happen/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
990−
991− "minipass-collect/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
992−
993− "minipass-fetch/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
994−
995− "minipass-fetch/minizlib/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
996−
997− "minipass-flush/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
998−
999− "minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
1000−
1001− "minipass-sized/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
1002−
1003− "mississippi/duplexify/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
1004−
1005− "parallel-transform/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
1006−
1007− "parallel-transform/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
1008−
1009− "pumpify/duplexify/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
1010−
1011− "purescript-installer/tar/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
1012−
1013− "purescript-installer/tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="],
1014−
1015− "purescript-installer/tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
1016−
1017− "purescript-installer/tar/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
1018−
1019− "purescript-installer/tar/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
1020−
1021− "rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
1022−
1023− "slice-ansi/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
1024−
1025− "test-exclude/glob/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
1026−
1027− "through2/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
1028−
1029− "through2/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
1030−
1031− "@npmcli/move-file/rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
1032−
1033− "cacache/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
1034−
1035− "log-update/wrap-ansi/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
1036−
1037− "log-update/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
1038−
1039− "log-update/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
1040−
1041− "make-fetch-happen/cacache/glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
1042−
1043− "make-fetch-happen/cacache/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
1044−
1045− "make-fetch-happen/cacache/tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="],
1046−
1047− "make-fetch-happen/cacache/tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
1048−
1049− "make-fetch-happen/cacache/tar/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
1050−
1051− "make-fetch-happen/cacache/unique-filename/unique-slug": ["unique-slug@3.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w=="],
1052−
1053− "mississippi/duplexify/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
1054−
1055− "mississippi/duplexify/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
1056−
1057− "pumpify/duplexify/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
1058−
1059− "pumpify/duplexify/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
1060−
1061− "purescript-installer/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
1062−
1063− "rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
1064−
1065− "slice-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
1066−
1067− "@npmcli/move-file/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
1068−
1069− "cacache/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
1070−
1071− "log-update/wrap-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
1072−
1073− "make-fetch-happen/cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
1074−
1075− "make-fetch-happen/cacache/rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
1076−
1077− "make-fetch-happen/cacache/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
1078−
1079− "rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
1080−
1081− "@npmcli/move-file/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
1082−
1083− "make-fetch-happen/cacache/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
1084−
1085− "make-fetch-happen/cacache/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
1086−
1087− "make-fetch-happen/cacache/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
1088− }
1089−}
compile-fail-tests/ClientBadBodyType.pursdeleted−12
@@ -1,12 +0,0 @@
1−-- EXPECT: String
2−module CompileFail.ClientBadBodyType where
3−
4−import Yoga.Fetch.Om (JSON, POST, Route, client)
5−
6−type UserApi =
7− { createUser :: Route POST "users" { body :: JSON { name :: String } } (ok :: { body :: {} })
8− }
9−
10−api = client @UserApi ""
11−
12−bad = api.createUser { name: 42 }
compile-fail-tests/ClientBadCurriedBodyType.pursdeleted−12
@@ -1,12 +0,0 @@
1−-- EXPECT: String
2−module CompileFail.ClientBadCurriedBodyType where
3−
4−import Yoga.Fetch.Om (JSON, POST, Route, client, type (/), type (:))
5−
6−type UserApi =
7− { updateUser :: Route POST ("users" / "id" : Int) { body :: JSON { name :: String } } (ok :: { body :: {} })
8− }
9−
10−api = client @UserApi ""
11−
12−bad = api.updateUser { id: 1 } { name: 42 }
compile-fail-tests/ClientBadHeaderType.pursdeleted−13
@@ -1,13 +0,0 @@
1−-- EXPECT: BearerToken
2−module CompileFail.ClientBadHeaderType where
3−
4−import Yoga.Fetch.Om (GET, Route, client)
5−import Yoga.HTTP.API.Route (BearerToken)
6−
7−type UserApi =
8− { me :: Route GET "me" { headers :: { authorization :: BearerToken } } (ok :: { body :: {} })
9− }
10−
11−api = client @UserApi ""
12−
13−bad = api.me { authorization: "secret" }
compile-fail-tests/ClientBadOptionalQueryType.pursdeleted−13
@@ -1,13 +0,0 @@
1−-- EXPECT: limit
2−module CompileFail.ClientBadOptionalQueryType where
3−
4−import Justifill (justifill)
5−import Yoga.Fetch.Om (GET, Route, client, type (:?))
6−
7−type UserApi =
8− { listUsers :: Route GET ("users" :? { limit :: Int, offset :: Int }) {} (ok :: { body :: {} })
9− }
10−
11−api = client @UserApi ""
12−
13−bad = api.listUsers (justifill { limit: "10" })
compile-fail-tests/ClientBadPathType.pursdeleted−12
@@ -1,12 +0,0 @@
1−-- EXPECT: Int
2−module CompileFail.ClientBadPathType where
3−
4−import Yoga.Fetch.Om (GET, Route, client, type (/), type (:))
5−
6−type UserApi =
7− { getUser :: Route GET ("users" / "id" : Int) {} (ok :: { body :: {} })
8− }
9−
10−api = client @UserApi ""
11−
12−bad = api.getUser { id: "1" }
compile-fail-tests/ClientExtraBodyField.pursdeleted−12
@@ -1,12 +0,0 @@
1−-- EXPECT: extra
2−module CompileFail.ClientExtraBodyField where
3−
4−import Yoga.Fetch.Om (JSON, POST, Route, client)
5−
6−type UserApi =
7− { createUser :: Route POST "users" { body :: JSON { name :: String } } (ok :: { body :: {} })
8− }
9−
10−api = client @UserApi ""
11−
12−bad = api.createUser { name: "Alice", extra: true }
compile-fail-tests/ClientExtraHeaderField.pursdeleted−13
@@ -1,13 +0,0 @@
1−-- EXPECT: extra
2−module CompileFail.ClientExtraHeaderField where
3−
4−import Yoga.Fetch.Om (GET, Route, client)
5−import Yoga.HTTP.API.Route (BearerToken(..))
6−
7−type UserApi =
8− { me :: Route GET "me" { headers :: { authorization :: BearerToken } } (ok :: { body :: {} })
9− }
10−
11−api = client @UserApi ""
12−
13−bad = api.me { authorization: BearerToken "secret", extra: true }
compile-fail-tests/ClientExtraOptionalQueryField.pursdeleted−13
@@ -1,13 +0,0 @@
1−-- EXPECT: extra
2−module CompileFail.ClientExtraOptionalQueryField where
3−
4−import Justifill (justifill)
5−import Yoga.Fetch.Om (GET, Route, client, type (:?))
6−
7−type UserApi =
8− { listUsers :: Route GET ("users" :? { limit :: Int, offset :: Int }) {} (ok :: { body :: {} })
9− }
10−
11−api = client @UserApi ""
12−
13−bad = api.listUsers (justifill { limit: 1, extra: "nope" })
compile-fail-tests/ClientExtraPathField.pursdeleted−12
@@ -1,12 +0,0 @@
1−-- EXPECT: extra
2−module CompileFail.ClientExtraPathField where
3−
4−import Yoga.Fetch.Om (GET, Route, client, type (/), type (:))
5−
6−type UserApi =
7− { getUser :: Route GET ("users" / "id" : Int) {} (ok :: { body :: {} })
8− }
9−
10−api = client @UserApi ""
11−
12−bad = api.getUser { id: 1, extra: true }
compile-fail-tests/ClientMissingBodyArgument.pursdeleted−12
@@ -1,12 +0,0 @@
1−-- EXPECT: Function
2−module CompileFail.ClientMissingBodyArgument where
3−
4−import Yoga.Fetch.Om (JSON, POST, Route, client, type (/), type (:))
5−import Yoga.Om (Om)
6−
7−type UserApi =
8− { updateUser :: Route POST ("users" / "id" : Int) { body :: JSON { token :: String } } (ok :: { body :: {} })
9− }
10−
11−api :: forall ctx err. { updateUser :: { id :: Int } -> Om { | ctx } err {} }
12−api = client @UserApi ""
compile-fail-tests/ClientMissingBodyField.pursdeleted−12
@@ -1,12 +0,0 @@
1−-- EXPECT: name :: String
2−module CompileFail.ClientMissingBodyField where
3−
4−import Yoga.Fetch.Om (JSON, POST, Route, client)
5−
6−type UserApi =
7− { createUser :: Route POST "users" { body :: JSON { name :: String, age :: Int } } (ok :: { body :: {} })
8− }
9−
10−api = client @UserApi ""
11−
12−bad = api.createUser { age: 42 }
compile-fail-tests/ClientMissingHeaderArgument.pursdeleted−13
@@ -1,13 +0,0 @@
1−-- EXPECT: Function
2−module CompileFail.ClientMissingHeaderArgument where
3−
4−import Yoga.Fetch.Om (GET, Route, client, type (/), type (:))
5−import Yoga.HTTP.API.Route (BearerToken)
6−import Yoga.Om (Om)
7−
8−type UserApi =
9− { getUser :: Route GET ("users" / "id" : Int) { headers :: { authorization :: BearerToken } } (ok :: { body :: {} })
10− }
11−
12−api :: forall ctx err. { getUser :: { id :: Int } -> Om { | ctx } err {} }
13−api = client @UserApi ""
compile-fail-tests/ClientMissingHeaderField.pursdeleted−13
@@ -1,13 +0,0 @@
1−-- EXPECT: authorization :: BearerToken
2−module CompileFail.ClientMissingHeaderField where
3−
4−import Yoga.Fetch.Om (GET, Route, client)
5−import Yoga.HTTP.API.Route (BearerToken)
6−
7−type UserApi =
8− { me :: Route GET "me" { headers :: { authorization :: BearerToken } } (ok :: { body :: {} })
9− }
10−
11−api = client @UserApi ""
12−
13−bad = api.me {}
compile-fail-tests/ClientMissingPathField.pursdeleted−12
@@ -1,12 +0,0 @@
1−-- EXPECT: id :: Int
2−module CompileFail.ClientMissingPathField where
3−
4−import Yoga.Fetch.Om (GET, Route, client, type (/), type (:))
5−
6−type UserApi =
7− { getUser :: Route GET ("users" / "id" : Int) {} (ok :: { body :: {} })
8− }
9−
10−api = client @UserApi ""
11−
12−bad = api.getUser {}
compile-fail-tests/ClientMissingRequiredQuery.pursdeleted−13
@@ -1,13 +0,0 @@
1−-- EXPECT: id :: Int
2−module CompileFail.ClientMissingRequiredQuery where
3−
4−import Justifill (justifill)
5−import Yoga.Fetch.Om (GET, Required, Route, client, type (:?))
6−
7−type UserApi =
8− { getUser :: Route GET ("users" :? { id :: Required Int, token :: Required String }) {} (ok :: { body :: {} })
9− }
10−
11−api = client @UserApi ""
12−
13−bad = api.getUser (justifill { token: "secret" })
compile-fail-tests/ClientMissingThirdArgument.pursdeleted−13
@@ -1,13 +0,0 @@
1−-- EXPECT: Function
2−module CompileFail.ClientMissingThirdArgument where
3−
4−import Yoga.Fetch.Om (JSON, POST, Route, client, type (/), type (:))
5−import Yoga.HTTP.API.Route (BearerToken)
6−import Yoga.Om (Om)
7−
8−type UserApi =
9− { updateUser :: Route POST ("users" / "id" : Int) { headers :: { authorization :: BearerToken }, body :: JSON { token :: String } } (ok :: { body :: {} })
10− }
11−
12−api :: forall ctx err. { updateUser :: { id :: Int } -> { authorization :: BearerToken } -> Om { | ctx } err {} }
13−api = client @UserApi ""
compile-fail-tests/run.jsdeleted−101
@@ -1,101 +0,0 @@
1−import { mkdtempSync, readdirSync, readFileSync, rmSync } from "node:fs";
2−import { tmpdir } from "node:os";
3−import { basename, join } from "node:path";
4−
5−const cwd = new URL("..", import.meta.url).pathname;
6−const casesDir = join(cwd, "compile-fail-tests");
7−const decoder = new TextDecoder();
8−
9−function run(args, options = {}) {
10− const proc = Bun.spawnSync(args, {
11− cwd,
12− stdout: options.stdout ?? "pipe",
13− stderr: options.stderr ?? "pipe",
14− });
15− return {
16− code: proc.exitCode,
17− stdout: proc.stdout ? decoder.decode(proc.stdout) : "",
18− stderr: proc.stderr ? decoder.decode(proc.stderr) : "",
19− };
20−}
21−
22−function printResult(label, result) {
23− console.error(`\n${label} failed with exit code ${result.code}`);
24− if (result.stdout) console.error(result.stdout);
25− if (result.stderr) console.error(result.stderr);
26−}
27−
28−function expectedSubstring(file) {
29− const firstLine = readFileSync(file, "utf8").split("\n", 1)[0];
30− return firstLine.startsWith("-- EXPECT: ") ? firstLine.slice("-- EXPECT: ".length) : null;
31−}
32−
33−const sourcesResult = run(["bunx", "spago", "sources", "--quiet", "--json"]);
34−if (sourcesResult.code !== 0) {
35− printResult("spago sources", sourcesResult);
36− process.exit(1);
37−}
38−
39−const excludedSourceGlobs = new Set([
40− "test/**/*.purs",
41− "../purescript-yoga-fastify-om/src/**/*.purs",
42− "../purescript-yoga-fastify-om/local-packages/yoga-fastify/src/**/*.purs",
43−]);
44−
45−const librarySources = JSON.parse(sourcesResult.stdout)
46− .filter((source) => !excludedSourceGlobs.has(source));
47−
48−const cases = readdirSync(casesDir)
49− .filter((file) => file.endsWith(".purs"))
50− .sort()
51− .map((file) => join("compile-fail-tests", file));
52−
53−const libOutput = mkdtempSync(join(tmpdir(), "yoga-fetch-om-lib-"));
54−
55−try {
56− const libResult = run(["bunx", "purs", "compile", ...librarySources, "--output", libOutput], { stdout: "ignore" });
57− if (libResult.code !== 0) {
58− printResult("library compile", libResult);
59− process.exit(1);
60− }
61−
62− let failed = 0;
63−
64− for (const testCase of cases) {
65− const failOutput = mkdtempSync(join(tmpdir(), "yoga-fetch-om-compile-fail-"));
66− try {
67− const result = run([
68− "bunx",
69− "purs",
70− "compile",
71− ...librarySources,
72− testCase,
73− "--output",
74− failOutput,
75− ]);
76−
77− const output = `${result.stdout}\n${result.stderr}`;
78− const expected = expectedSubstring(join(cwd, testCase));
79− const name = basename(testCase, ".purs");
80−
81− if (result.code === 0) {
82− console.error(`FAIL ${name} - compiled successfully (should have failed)`);
83− failed++;
84− } else if (expected && !output.includes(expected)) {
85− printResult(`FAIL ${name}`, result);
86− console.error(`Expected failure to contain: ${expected}`);
87− failed++;
88− } else {
89− console.log(`PASS ${name}`);
90− }
91− } finally {
92− rmSync(failOutput, { recursive: true, force: true });
93− }
94− }
95−
96− if (failed > 0) {
97− process.exit(1);
98− }
99−} finally {
100− rmSync(libOutput, { recursive: true, force: true });
101−}
package.json+4−19
@@ -1,14 +1,12 @@
11{
22 "name": "purescript-yoga-fetch-om",
3− "version": "0.8.1",
3+ "version": "0.1.0",
44 "description": "Derive type-safe fetch clients from yoga HTTP API definitions",
55 "type": "module",
66 "scripts": {
77 "build": "spago build",
88 "test": "spago test",
9− "coverage": "spago build && c8 spago test",
10− "test:compile-fail": "bun compile-fail-tests/run.js",
11− "clean": "rm -rf output .spago coverage",
9+ "clean": "rm -rf output .spago",
1210 "watch": "spago build --watch",
1311 "repl": "spago repl",
1412 "docs": "spago docs",
@@ -26,23 +24,10 @@
2624 "author": "",
2725 "license": "MIT",
2826 "devDependencies": {
29− "@fastify/cookie": "^11.1.2",
30− "@fastify/cors": "^11.3.0",
31− "@fastify/formbody": "^9.0.0",
32− "@fastify/helmet": "^13.1.0",
33− "@fastify/multipart": "^10.1.0",
34− "@fastify/rate-limit": "^11.2.0",
35− "@fastify/websocket": "^11.3.0",
36− "argon2": "^0.45.1",
37− "c8": "^12.0.0",
38− "fastify": "^5.7.4",
39− "jose": "^6.2.8",
4027 "jsdom": "^28.0.0",
4128 "purescript": "^0.15.15",
42− "spago": "^1.0.3",
29+ "spago": "^0.93.42",
4330 "vitest": "^2.1.8"
4431 },
45− "dependencies": {
46− "pino": "^10.3.1"
47− }
32+ "dependencies": {}
4833}
spago.lockdeleted−1792
@@ -1,1792 +0,0 @@
1−{
2− "workspace": {
3− "packages": {
4− "yoga-fetch-om": {
5− "path": "./",
6− "core": {
7− "dependencies": [
8− {
9− "aff": ">=8.0.0 <9.0.0"
10− },
11− {
12− "arraybuffer-types": ">=3.0.2 <4.0.0"
13− },
14− {
15− "arrays": ">=7.3.0 <8.0.0"
16− },
17− {
18− "effect": ">=4.0.0 <5.0.0"
19− },
20− {
21− "either": ">=6.1.0 <7.0.0"
22− },
23− {
24− "exceptions": ">=6.1.0 <7.0.0"
25− },
26− {
27− "http-methods": ">=6.1.0 <7.0.0"
28− },
29− {
30− "js-fetch": ">=0.2.1 <0.3.0"
31− },
32− {
33− "js-promise-aff": ">=1.0.0 <2.0.0"
34− },
35− {
36− "maybe": ">=6.0.0 <7.0.0"
37− },
38− {
39− "prelude": ">=6.0.2 <7.0.0"
40− },
41− {
42− "record": ">=4.0.0 <5.0.0"
43− },
44− {
45− "strings": ">=6.0.1 <7.0.0"
46− },
47− {
48− "tailrec": ">=6.1.0 <7.0.0"
49− },
50− {
51− "transformers": ">=6.1.0 <7.0.0"
52− },
53− {
54− "tuples": ">=7.0.0 <8.0.0"
55− },
56− {
57− "typelevel-prelude": ">=7.0.0 <8.0.0"
58− },
59− {
60− "unsafe-coerce": ">=6.0.0 <7.0.0"
61− },
62− {
63− "variant": ">=8.0.0 <9.0.0"
64− },
65− {
66− "yoga-http-api": ">=0.3.4 <0.4.0"
67− },
68− {
69− "yoga-json": ">=5.2.1 <6.0.0"
70− },
71− {
72− "yoga-om": ">=1.5.2 <2.0.0"
73− },
74− {
75− "yoga-om-strom": ">=0.4.3 <0.5.0"
76− }
77− ]
78− },
79− "test": {
80− "dependencies": [
81− {
82− "console": ">=6.0.0 <7.0.0"
83− },
84− "enums",
85− "foldable-traversable",
86− "foreign",
87− "foreign-object",
88− "integers",
89− "js-promise",
90− {
91− "js-uri": ">=3.1.0 <4.0.0"
92− },
93− {
94− "justifill": ">=0.5.0 <0.6.0"
95− },
96− "partial",
97− {
98− "quickcheck": ">=8.0.1 <9.0.0"
99− },
100− {
101− "refs": ">=6.0.0 <7.0.0"
102− },
103− {
104− "spec": ">=8.0.0 <9.0.0"
105− },
106− {
107− "spec-discovery": ">=8.0.0 <9.0.0"
108− },
109− {
110− "spec-quickcheck": ">=5.0.2 <6.0.0"
111− },
112− "yoga-fastify",
113− {
114− "yoga-fastify-om": ">=0.4.7 <0.5.0"
115− }
116− ]
117− }
118− }
119− },
120− "extra_packages": {}
121− },
122− "packages": {
123− "aff": {
124− "type": "registry",
125− "version": "8.0.0",
126− "integrity": "sha256-9BRIrSdRoYybfiUmBqgKJ66cPqxYHb277bVWQMn/9sg=",
127− "dependencies": [
128− "control",
129− "datetime",
130− "effect",
131− "either",
132− "exceptions",
133− "functions",
134− "newtype",
135− "parallel",
136− "partial",
137− "prelude",
138− "st",
139− "tailrec",
140− "transformers",
141− "unsafe-coerce"
142− ]
143− },
144− "aff-retry": {
145− "type": "registry",
146− "version": "2.0.0",
147− "integrity": "sha256-rKZNcP4IKSyBFQBVzrCvE0ULoJt0N/uDLLJ0dPotr4k=",
148− "dependencies": [
149− "aff",
150− "arrays",
151− "datetime",
152− "effect",
153− "either",
154− "exceptions",
155− "integers",
156− "maybe",
157− "newtype",
158− "numbers",
159− "prelude",
160− "random",
161− "transformers"
162− ]
163− },
164− "ansi": {
165− "type": "registry",
166− "version": "7.0.0",
167− "integrity": "sha256-tOUaXJFzPSfBVAqLI8hc+Tz2M1rg16cXqyHaK/3SmFg=",
168− "dependencies": [
169− "foldable-traversable",
170− "lists",
171− "prelude"
172− ]
173− },
174− "argonaut-codecs": {
175− "type": "registry",
176− "version": "9.1.0",
177− "integrity": "sha256-K910SBrmYallESsm8pxJYThs7lig6hxX3M4PW33Cgew=",
178− "dependencies": [
179− "argonaut-core",
180− "arrays",
181− "bifunctors",
182− "either",
183− "foldable-traversable",
184− "foreign-object",
185− "identity",
186− "integers",
187− "lists",
188− "maybe",
189− "nonempty",
190− "ordered-collections",
191− "prelude",
192− "record",
193− "strings",
194− "tuples"
195− ]
196− },
197− "argonaut-core": {
198− "type": "registry",
199− "version": "7.0.0",
200− "integrity": "sha256-gYZihtBIKthVuXXoiPphMookSf8M5aHyFYkcIWqlxTM=",
201− "dependencies": [
202− "arrays",
203− "control",
204− "either",
205− "foreign-object",
206− "functions",
207− "gen",
208− "maybe",
209− "nonempty",
210− "prelude",
211− "strings",
212− "tailrec"
213− ]
214− },
215− "arraybuffer-types": {
216− "type": "registry",
217− "version": "3.0.2",
218− "integrity": "sha256-p05cJnSkyeoB7VHzMyc2Eb1RwUaB7Nl0sQSqEGNEUD8=",
219− "dependencies": []
220− },
221− "arrays": {
222− "type": "registry",
223− "version": "7.3.0",
224− "integrity": "sha256-GD4z7LCi9wzi7FCQqbWhvs8paoUK9NO+HwgXZ+KP8Rk=",
225− "dependencies": [
226− "bifunctors",
227− "control",
228− "foldable-traversable",
229− "functions",
230− "maybe",
231− "nonempty",
232− "partial",
233− "prelude",
234− "safe-coerce",
235− "st",
236− "tailrec",
237− "tuples",
238− "unfoldable",
239− "unsafe-coerce"
240− ]
241− },
242− "avar": {
243− "type": "registry",
244− "version": "5.0.1",
245− "integrity": "sha256-8V4SxF4TIWZ9Ik1P4lPzIRUAZeFBe8w5WA2VcCEKsIk=",
246− "dependencies": [
247− "aff",
248− "effect",
249− "either",
250− "exceptions",
251− "functions",
252− "maybe",
253− "prelude"
254− ]
255− },
256− "bifunctors": {
257− "type": "registry",
258− "version": "6.1.0",
259− "integrity": "sha256-CvZRb8uI75eKIqiYntR+k05Wk6tKlMS5w8sCA2AFna0=",
260− "dependencies": [
261− "const",
262− "either",
263− "newtype",
264− "prelude",
265− "tuples"
266− ]
267− },
268− "catenable-lists": {
269− "type": "registry",
270− "version": "7.0.0",
271− "integrity": "sha256-7+i/MHBLIRh604iCNT4ENWRWE/wuHIotER4kpdX9Ve0=",
272− "dependencies": [
273− "control",
274− "foldable-traversable",
275− "lists",
276− "maybe",
277− "prelude",
278− "tuples",
279− "unfoldable"
280− ]
281− },
282− "console": {
283− "type": "registry",
284− "version": "6.1.0",
285− "integrity": "sha256-3T5PPz1mATZmV0C4GzkCkpLlCa5xG7u8ZNgnLrrrI1Q=",
286− "dependencies": [
287− "effect",
288− "prelude"
289− ]
290− },
291− "const": {
292− "type": "registry",
293− "version": "6.0.0",
294− "integrity": "sha256-S+m0lQsxnji0z1XRUmkn+3RFuWJ5CXWuIr1u3i8Bfoc=",
295− "dependencies": [
296− "invariant",
297− "newtype",
298− "prelude"
299− ]
300− },
301− "contravariant": {
302− "type": "registry",
303− "version": "6.0.0",
304− "integrity": "sha256-nuckEWqL80NaPmR/l9AUyrfycNh18XcvlZV9PAamwqc=",
305− "dependencies": [
306− "const",
307− "either",
308− "newtype",
309− "prelude",
310− "tuples"
311− ]
312− },
313− "control": {
314− "type": "registry",
315− "version": "6.0.0",
316− "integrity": "sha256-0vxyYh5FL+ilxgLo954w1LqCUC0RSIivNNlb9CaNUQg=",
317− "dependencies": [
318− "newtype",
319− "prelude"
320− ]
321− },
322− "datetime": {
323− "type": "registry",
324− "version": "6.1.0",
325− "integrity": "sha256-tbv6eDXy6QOD7YSknxYSbsDF32OC2JrNbSBpzMs7Doc=",
326− "dependencies": [
327− "bifunctors",
328− "control",
329− "either",
330− "enums",
331− "foldable-traversable",
332− "functions",
333− "gen",
334− "integers",
335− "lists",
336− "maybe",
337− "newtype",
338− "numbers",
339− "ordered-collections",
340− "partial",
341− "prelude",
342− "tuples"
343− ]
344− },
345− "distributive": {
346− "type": "registry",
347− "version": "6.0.0",
348− "integrity": "sha256-netyJK4B32PDYHD0tF2AenKgo3urzbI770ycM0pArAo=",
349− "dependencies": [
350− "identity",
351− "newtype",
352− "prelude",
353− "tuples",
354− "type-equality"
355− ]
356− },
357− "effect": {
358− "type": "registry",
359− "version": "4.0.0",
360− "integrity": "sha256-DdqU3bncRTjgMVPPRlAuGHVeajSPEcRaRhNuio7if6s=",
361− "dependencies": [
362− "prelude"
363− ]
364− },
365− "either": {
366− "type": "registry",
367− "version": "6.1.0",
368− "integrity": "sha256-tBHx3PgtH4GZOApZCDkcM7szRTYJinrUrVGWazQCUUg=",
369− "dependencies": [
370− "control",
371− "invariant",
372− "maybe",
373− "prelude"
374− ]
375− },
376− "enums": {
377− "type": "registry",
378− "version": "6.0.1",
379− "integrity": "sha256-sdZOmLX5+5pASGpvVyT0vSD5BBYQjZiayjV5XiPutso=",
380− "dependencies": [
381− "control",
382− "either",
383− "gen",
384− "maybe",
385− "newtype",
386− "nonempty",
387− "partial",
388− "prelude",
389− "tuples",
390− "unfoldable"
391− ]
392− },
393− "exceptions": {
394− "type": "registry",
395− "version": "6.1.0",
396− "integrity": "sha256-nRrr+N0wk0TUFOWLR7e1n1oxcXo/X345bQUtoY9lW6A=",
397− "dependencies": [
398− "effect",
399− "either",
400− "maybe",
401− "prelude"
402− ]
403− },
404− "exists": {
405− "type": "registry",
406− "version": "6.0.0",
407− "integrity": "sha256-vtLbrWNaI+pzx/2fw2AQnCovoLtcosClIhjO26QKkh8=",
408− "dependencies": [
409− "unsafe-coerce"
410− ]
411− },
412− "exitcodes": {
413− "type": "registry",
414− "version": "4.0.0",
415− "integrity": "sha256-xBl4aFSEQ05Owp1ZvO6OxxvLK3LVzU35RSbj79SsePQ=",
416− "dependencies": [
417− "enums",
418− "maybe",
419− "prelude"
420− ]
421− },
422− "foldable-traversable": {
423− "type": "registry",
424− "version": "6.0.0",
425− "integrity": "sha256-NGGWyCio/xjce6fPP7y3wwg7CheqllID6aJudDxbWhA=",
426− "dependencies": [
427− "bifunctors",
428− "const",
429− "control",
430− "either",
431− "functors",
432− "identity",
433− "maybe",
434− "newtype",
435− "orders",
436− "prelude",
437− "tuples"
438− ]
439− },
440− "foreign": {
441− "type": "registry",
442− "version": "7.0.0",
443− "integrity": "sha256-jiDRMVQfovGsbbA/FzbzYf6iWk9i2b5gNrIjz+gFfsI=",
444− "dependencies": [
445− "either",
446− "functions",
447− "integers",
448− "lists",
449− "maybe",
450− "prelude",
451− "strings",
452− "transformers",
453− "unsafe-coerce"
454− ]
455− },
456− "foreign-object": {
457− "type": "registry",
458− "version": "4.1.0",
459− "integrity": "sha256-x/Q7r80z/vmHRKvPwhYmHP/DnJciPtsyGfRTMzayKIU=",
460− "dependencies": [
461− "arrays",
462− "foldable-traversable",
463− "functions",
464− "gen",
465− "lists",
466− "maybe",
467− "prelude",
468− "st",
469− "tailrec",
470− "tuples",
471− "typelevel-prelude",
472− "unfoldable",
473− "unsafe-coerce"
474− ]
475− },
476− "fork": {
477− "type": "registry",
478− "version": "6.0.0",
479− "integrity": "sha256-0keBVeZZg1eCZEy/En1CohVW829gQUqKtqBNIRa93/A=",
480− "dependencies": [
481− "aff",
482− "prelude",
483− "transformers"
484− ]
485− },
486− "free": {
487− "type": "registry",
488− "version": "7.1.0",
489− "integrity": "sha256-tUBInfUpRQEw4u94GWcYW7EYdmSdDHSRn88a+C0eltU=",
490− "dependencies": [
491− "catenable-lists",
492− "control",
493− "distributive",
494− "either",
495− "exists",
496− "foldable-traversable",
497− "invariant",
498− "lazy",
499− "maybe",
500− "prelude",
501− "tailrec",
502− "transformers",
503− "tuples",
504− "unsafe-coerce"
505− ]
506− },
507− "functions": {
508− "type": "registry",
509− "version": "6.0.0",
510− "integrity": "sha256-0jgtOr+SFO4UScKc40oA/9Vdcf2rLn3h3vZlY0KfqVo=",
511− "dependencies": [
512− "prelude"
513− ]
514− },
515− "functors": {
516− "type": "registry",
517− "version": "5.0.0",
518− "integrity": "sha256-W1o/4wcp6S3chodYL8uixlXK2mfr1L+SzM1R+whqUco=",
519− "dependencies": [
520− "bifunctors",
521− "const",
522− "contravariant",
523− "control",
524− "distributive",
525− "either",
526− "invariant",
527− "maybe",
528− "newtype",
529− "prelude",
530− "profunctor",
531− "tuples",
532− "unsafe-coerce"
533− ]
534− },
535− "gen": {
536− "type": "registry",
537− "version": "4.0.0",
538− "integrity": "sha256-kyOateeOtQa07vfTMYeSuCKdelgKE1R65fwKkZ10wsY=",
539− "dependencies": [
540− "either",
541− "foldable-traversable",
542− "identity",
543− "maybe",
544− "newtype",
545− "nonempty",
546− "prelude",
547− "tailrec",
548− "tuples",
549− "unfoldable"
550− ]
551− },
552− "heterogeneous": {
553− "type": "registry",
554− "version": "0.7.0",
555− "integrity": "sha256-pQwcFvhWL8noktxaoD7FlLs2F2lYf3QHoyO0VOWO3I0=",
556− "dependencies": [
557− "either",
558− "foldable-traversable",
559− "functors",
560− "prelude",
561− "record",
562− "tuples",
563− "variant"
564− ]
565− },
566− "http-methods": {
567− "type": "registry",
568− "version": "6.1.0",
569− "integrity": "sha256-WbjEmCv6rysY/aKwlrcspyzShi5bIQy+AFpDzPMnSP4=",
570− "dependencies": [
571− "either",
572− "prelude",
573− "strings"
574− ]
575− },
576− "identity": {
577− "type": "registry",
578− "version": "6.0.0",
579− "integrity": "sha256-RY/iXPpxpqvKHYfJeFVNI1J06kohB9rbtWYuha8t0LE=",
580− "dependencies": [
581− "control",
582− "invariant",
583− "newtype",
584− "prelude"
585− ]
586− },
587− "integers": {
588− "type": "registry",
589− "version": "6.0.0",
590− "integrity": "sha256-Y8yozC1uHRLcruobEyv5/bMKzE1BoKJ/olHv6o+bgm8=",
591− "dependencies": [
592− "maybe",
593− "numbers",
594− "prelude"
595− ]
596− },
597− "invariant": {
598− "type": "registry",
599− "version": "6.0.0",
600− "integrity": "sha256-HyoT1I5qIHRq8RSZji6zZDvqnpVjLw748utrKwZtqsw=",
601− "dependencies": [
602− "control",
603− "prelude"
604− ]
605− },
606− "js-bigints": {
607− "type": "registry",
608− "version": "2.2.1",
609− "integrity": "sha256-r1rE6Olv5b3JrP32lY2uKJ+eBRTsrVnC983K8VWwqe4=",
610− "dependencies": [
611− "integers",
612− "maybe",
613− "prelude"
614− ]
615− },
616− "js-date": {
617− "type": "registry",
618− "version": "8.0.0",
619− "integrity": "sha256-DNQrp4xYc8o80jtxo0aOkUeXGi6h0Xidkk2ZQ8Y4l5Y=",
620− "dependencies": [
621− "datetime",
622− "effect",
623− "enums",
624− "foreign",
625− "functions",
626− "integers",
627− "maybe",
628− "prelude"
629− ]
630− },
631− "js-fetch": {
632− "type": "registry",
633− "version": "0.2.1",
634− "integrity": "sha256-jsMrMh8kIUW5bHbHl7hy8ev/iMru1MzfDa+hoAxo14Q=",
635− "dependencies": [
636− "arraybuffer-types",
637− "arrays",
638− "effect",
639− "foldable-traversable",
640− "foreign",
641− "foreign-object",
642− "functions",
643− "http-methods",
644− "js-promise",
645− "maybe",
646− "newtype",
647− "prelude",
648− "record",
649− "tuples",
650− "typelevel-prelude",
651− "unfoldable",
652− "web-file",
653− "web-streams"
654− ]
655− },
656− "js-promise": {
657− "type": "registry",
658− "version": "1.0.0",
659− "integrity": "sha256-u+6+ofIwT5XhT2fbMu4dShwkyWGfPRt9642Cnzw/Wvk=",
660− "dependencies": [
661− "effect",
662− "exceptions",
663− "foldable-traversable",
664− "functions",
665− "maybe",
666− "newtype",
667− "prelude"
668− ]
669− },
670− "js-promise-aff": {
671− "type": "registry",
672− "version": "1.0.0",
673− "integrity": "sha256-gEKAdNnTWjXS+tTp/AhYl/ezloKfuoQFcBKrdOx2USo=",
674− "dependencies": [
675− "aff",
676− "control",
677− "effect",
678− "either",
679− "exceptions",
680− "foreign",
681− "js-promise",
682− "maybe",
683− "prelude",
684− "transformers"
685− ]
686− },
687− "js-uri": {
688− "type": "registry",
689− "version": "3.1.0",
690− "integrity": "sha256-7waHOctAfqhhw540FNJ7C/YsDMQW9TmA+SpHhduH6Uw=",
691− "dependencies": [
692− "functions",
693− "maybe",
694− "prelude"
695− ]
696− },
697− "justifill": {
698− "type": "registry",
699− "version": "0.5.0",
700− "integrity": "sha256-IwoDO72+IROcUvFIwnronb/ny8SepssgTUG3Qp2TEKg=",
701− "dependencies": [
702− "maybe",
703− "prelude",
704− "record",
705− "typelevel-prelude"
706− ]
707− },
708− "lazy": {
709− "type": "registry",
710− "version": "6.0.0",
711− "integrity": "sha256-MHRC+1Pc+AjortBp4b/e1e6KpEpsDwaJBNBB7TOL+1I=",
712− "dependencies": [
713− "control",
714− "foldable-traversable",
715− "invariant",
716− "prelude"
717− ]
718− },
719− "lcg": {
720− "type": "registry",
721− "version": "4.0.0",
722− "integrity": "sha256-bUYyfXYmjTn7zSpj2hTiePywzsuD80fCjkonsrpdGOw=",
723− "dependencies": [
724− "effect",
725− "integers",
726− "maybe",
727− "numbers",
728− "partial",
729− "prelude",
730− "random"
731− ]
732− },
733− "lists": {
734− "type": "registry",
735− "version": "7.0.0",
736− "integrity": "sha256-/mGd7wLoU+wsTcqii7SSUByxsvwvjnu2PjwAD47yYb4=",
737− "dependencies": [
738− "bifunctors",
739− "control",
740− "foldable-traversable",
741− "lazy",
742− "maybe",
743− "newtype",
744− "nonempty",
745− "partial",
746− "prelude",
747− "tailrec",
748− "tuples",
749− "unfoldable"
750− ]
751− },
752− "literals": {
753− "type": "registry",
754− "version": "1.0.2",
755− "integrity": "sha256-ZkGRFD6gb8etYvyMYpX1Z7lx1Tql7R1VGnD1Dzinup8=",
756− "dependencies": [
757− "integers",
758− "maybe",
759− "numbers",
760− "partial",
761− "prelude",
762− "typelevel-prelude",
763− "unsafe-coerce"
764− ]
765− },
766− "maybe": {
767− "type": "registry",
768− "version": "6.0.0",
769− "integrity": "sha256-8X6XEgtZ5lqfkEuc1hWOofnL6mwhk8gSJTxwvbR/SbY=",
770− "dependencies": [
771− "control",
772− "invariant",
773− "newtype",
774− "prelude"
775− ]
776− },
777− "media-types": {
778− "type": "registry",
779− "version": "6.0.0",
780− "integrity": "sha256-3Wyq+vfqJFTmy1k6DGVnXStxtZxgK631wusDPzlFVxg=",
781− "dependencies": [
782− "newtype",
783− "prelude"
784− ]
785− },
786− "mmorph": {
787− "type": "registry",
788− "version": "7.0.0",
789− "integrity": "sha256-Cfltaq+tfYjuSoSBN/b8cSQZbvZTqIRs6ebQewbIkGs=",
790− "dependencies": [
791− "bifunctors",
792− "either",
793− "free",
794− "functors",
795− "identity",
796− "maybe",
797− "newtype",
798− "prelude",
799− "transformers",
800− "tuples"
801− ]
802− },
803− "newtype": {
804− "type": "registry",
805− "version": "5.0.0",
806− "integrity": "sha256-dt6w0cty4OS+Pjt9fsh3iU6ottqSU83mdAZkaEEvo6c=",
807− "dependencies": [
808− "prelude",
809− "safe-coerce"
810− ]
811− },
812− "node-buffer": {
813− "type": "registry",
814− "version": "9.0.0",
815− "integrity": "sha256-RdQjilmEHqsT4fwpCr8Mavw8KTafYrS3ZM6zeAAVAl8=",
816− "dependencies": [
817− "arraybuffer-types",
818− "effect",
819− "functions",
820− "maybe",
821− "nullable",
822− "partial",
823− "prelude",
824− "st",
825− "unsafe-coerce"
826− ]
827− },
828− "node-event-emitter": {
829− "type": "registry",
830− "version": "3.0.0",
831− "integrity": "sha256-wodx71NxJBPXOaawFn01V1ByYB2vT+I3RuV2giOVKMg=",
832− "dependencies": [
833− "effect",
834− "either",
835− "functions",
836− "maybe",
837− "nullable",
838− "prelude",
839− "unsafe-coerce"
840− ]
841− },
842− "node-fs": {
843− "type": "registry",
844− "version": "9.2.0",
845− "integrity": "sha256-fxioTSm9y47WuYs9F/7nxCh/RVDCl3Kr3Hg779J4SJA=",
846− "dependencies": [
847− "aff",
848− "datetime",
849− "effect",
850− "either",
851− "enums",
852− "exceptions",
853− "functions",
854− "integers",
855− "js-date",
856− "maybe",
857− "node-buffer",
858− "node-path",
859− "node-streams",
860− "nullable",
861− "partial",
862− "prelude",
863− "strings"
864− ]
865− },
866− "node-path": {
867− "type": "registry",
868− "version": "5.0.1",
869− "integrity": "sha256-j7n/SmpVz0FOMJl4XZop3ofJ+MeIPkMNqUEUKHEL6Us=",
870− "dependencies": [
871− "effect"
872− ]
873− },
874− "node-process": {
875− "type": "registry",
876− "version": "11.2.0",
877− "integrity": "sha256-onzKeNmaeYfN3HSDPqSFTrrP2Yl9tnVsfKKhnf2plxM=",
878− "dependencies": [
879− "effect",
880− "exceptions",
881− "foreign",
882− "foreign-object",
883− "maybe",
884− "node-event-emitter",
885− "node-streams",
886− "nullable",
887− "posix-types",
888− "prelude",
889− "strings"
890− ]
891− },
892− "node-streams": {
893− "type": "registry",
894− "version": "9.0.1",
895− "integrity": "sha256-yuVGm/R/tBr4Nphi+a1a984Z0fkmN9Q5wWtSmbmJTpA=",
896− "dependencies": [
897− "aff",
898− "arrays",
899− "effect",
900− "either",
901− "exceptions",
902− "maybe",
903− "node-buffer",
904− "node-event-emitter",
905− "nullable",
906− "prelude",
907− "refs",
908− "st",
909− "tailrec",
910− "unsafe-coerce"
911− ]
912− },
913− "nonempty": {
914− "type": "registry",
915− "version": "7.0.0",
916− "integrity": "sha256-Ctkq8/+KiGqCE53Y/LvibA/coy7ev9HtRZU+GYS7yfQ=",
917− "dependencies": [
918− "control",
919− "foldable-traversable",
920− "maybe",
921− "prelude",
922− "tuples",
923− "unfoldable"
924− ]
925− },
926− "now": {
927− "type": "registry",
928− "version": "6.0.0",
929− "integrity": "sha256-mTyG4s8tps3XIf0jjV/lME2/QlwMzrQly2wqfSSUM3o=",
930− "dependencies": [
931− "datetime",
932− "effect",
933− "prelude"
934− ]
935− },
936− "nullable": {
937− "type": "registry",
938− "version": "6.0.0",
939− "integrity": "sha256-CDAZk+L9Sc0GCFTkE8n+qdp4Ys8avvnkU+m2hVALt7M=",
940− "dependencies": [
941− "functions",
942− "maybe",
943− "prelude"
944− ]
945− },
946− "numbers": {
947− "type": "registry",
948− "version": "9.0.1",
949− "integrity": "sha256-ZydYckgwRAnRaFC7pu6fADhzdwX+UqHZrfJyet64zls=",
950− "dependencies": [
951− "functions",
952− "maybe",
953− "prelude"
954− ]
955− },
956− "open-memoize": {
957− "type": "registry",
958− "version": "6.2.0",
959− "integrity": "sha256-yJLuVYX8FocHIJ+6q7efH/Pj4S+e1Y57DZ5Dn7qf4ww=",
960− "dependencies": [
961− "either",
962− "integers",
963− "lazy",
964− "lists",
965− "maybe",
966− "partial",
967− "prelude",
968− "strings",
969− "tuples"
970− ]
971− },
972− "optparse": {
973− "type": "registry",
974− "version": "5.0.1",
975− "integrity": "sha256-2btDjHPRR0uujUQJuZAN9AzvVoXe7yG6IwnY5evERhQ=",
976− "dependencies": [
977− "arrays",
978− "bifunctors",
979− "control",
980− "effect",
981− "either",
982− "enums",
983− "exists",
984− "exitcodes",
985− "foldable-traversable",
986− "free",
987− "integers",
988− "lazy",
989− "lists",
990− "maybe",
991− "newtype",
992− "node-buffer",
993− "node-process",
994− "node-streams",
995− "nonempty",
996− "numbers",
997− "open-memoize",
998− "partial",
999− "prelude",
1000− "strings",
1001− "tailrec",
1002− "transformers",
1003− "tuples"
1004− ]
1005− },
1006− "ordered-collections": {
1007− "type": "registry",
1008− "version": "3.2.0",
1009− "integrity": "sha256-NaEXc2cz/7lJfxPWEja4XlZbGxuRqJwFKQJjsJf51kQ=",
1010− "dependencies": [
1011− "arrays",
1012− "control",
1013− "foldable-traversable",
1014− "functions",
1015− "gen",
1016− "lists",
1017− "maybe",
1018− "newtype",
1019− "partial",
1020− "prelude",
1021− "safe-coerce",
1022− "tailrec",
1023− "tuples",
1024− "unfoldable"
1025− ]
1026− },
1027− "orders": {
1028− "type": "registry",
1029− "version": "6.0.0",
1030− "integrity": "sha256-nSMxZK7wxyDULkjZqvMyB71mVo6b0AyLLHosDVbv1XM=",
1031− "dependencies": [
1032− "newtype",
1033− "prelude"
1034− ]
1035− },
1036− "parallel": {
1037− "type": "registry",
1038− "version": "7.0.0",
1039− "integrity": "sha256-bAGpVhrFz2IyHkA4MR7+tE/19FZ7dzYBdYPgK5svkqw=",
1040− "dependencies": [
1041− "control",
1042− "effect",
1043− "either",
1044− "foldable-traversable",
1045− "functors",
1046− "maybe",
1047− "newtype",
1048− "prelude",
1049− "profunctor",
1050− "refs",
1051− "transformers"
1052− ]
1053− },
1054− "partial": {
1055− "type": "registry",
1056− "version": "4.0.0",
1057− "integrity": "sha256-mdrlJBAgFMh79hNRW39uv7c+BwnnaOrAMmdh7+VhEhs=",
1058− "dependencies": []
1059− },
1060− "pipes": {
1061− "type": "registry",
1062− "version": "8.0.0",
1063− "integrity": "sha256-dtUNpG8BGVr7pu6mQZyAnUAftUHgNS7f0QH3Kw5UTpQ=",
1064− "dependencies": [
1065− "aff",
1066− "control",
1067− "effect",
1068− "either",
1069− "foldable-traversable",
1070− "identity",
1071− "lists",
1072− "maybe",
1073− "mmorph",
1074− "newtype",
1075− "prelude",
1076− "tailrec",
1077− "transformers",
1078− "tuples"
1079− ]
1080− },
1081− "posix-types": {
1082− "type": "registry",
1083− "version": "6.0.0",
1084− "integrity": "sha256-Je5jG439F/SFO/IvVevZnWVxDIonrehlKuJkefP2lHE=",
1085− "dependencies": [
1086− "maybe",
1087− "newtype",
1088− "prelude"
1089− ]
1090− },
1091− "prelude": {
1092− "type": "registry",
1093− "version": "6.0.2",
1094− "integrity": "sha256-IqykrDRquGUD/LRSad7y75hZv3bUsGQ4knc8tdez8Qw=",
1095− "dependencies": []
1096− },
1097− "profunctor": {
1098− "type": "registry",
1099− "version": "6.0.1",
1100− "integrity": "sha256-Ow0mJC+PIIRq/a3mzCWY5vxuTgR/e+Ee68+mWeSRnWY=",
1101− "dependencies": [
1102− "control",
1103− "distributive",
1104− "either",
1105− "exists",
1106− "invariant",
1107− "newtype",
1108− "prelude",
1109− "tuples"
1110− ]
1111− },
1112− "quickcheck": {
1113− "type": "registry",
1114− "version": "8.0.1",
1115− "integrity": "sha256-SfW+maesCt0jnnFhfrgJZGPcWLj8oFcGbcDIVklmdzc=",
1116− "dependencies": [
1117− "arrays",
1118− "console",
1119− "control",
1120− "effect",
1121− "either",
1122− "enums",
1123− "exceptions",
1124− "foldable-traversable",
1125− "gen",
1126− "identity",
1127− "integers",
1128− "lazy",
1129− "lcg",
1130− "lists",
1131− "maybe",
1132− "newtype",
1133− "nonempty",
1134− "numbers",
1135− "partial",
1136− "prelude",
1137− "record",
1138− "st",
1139− "strings",
1140− "tailrec",
1141− "transformers",
1142− "tuples"
1143− ]
1144− },
1145− "random": {
1146− "type": "registry",
1147− "version": "6.0.0",
1148− "integrity": "sha256-7sZRo6P9UIiXDZ9s2QL9T8h3wlIwLdQrR4+oZKOijQw=",
1149− "dependencies": [
1150− "effect",
1151− "integers",
1152− "prelude"
1153− ]
1154− },
1155− "record": {
1156− "type": "registry",
1157− "version": "4.0.0",
1158− "integrity": "sha256-WQ8fqp4X1wTA70J4qUcPW4Z7DCwx6e5KJnT/EuTdWSc=",
1159− "dependencies": [
1160− "functions",
1161− "prelude",
1162− "unsafe-coerce"
1163− ]
1164− },
1165− "record-studio": {
1166− "type": "registry",
1167− "version": "1.0.4",
1168− "integrity": "sha256-CRnFvSXpDDzio+buibUxFU9zPZDd7/lzrYC1Ya3FuIw=",
1169− "dependencies": [
1170− "heterogeneous",
1171− "lists",
1172− "prelude",
1173− "record",
1174− "typelevel-prelude",
1175− "unsafe-coerce"
1176− ]
1177− },
1178− "refs": {
1179− "type": "registry",
1180− "version": "6.0.0",
1181− "integrity": "sha256-KKD5G9dR2SauuDGULUJsxjqDOEi1Jqm+2Sq5U2mY8YU=",
1182− "dependencies": [
1183− "effect",
1184− "prelude"
1185− ]
1186− },
1187− "routing-duplex": {
1188− "type": "registry",
1189− "version": "0.7.0",
1190− "integrity": "sha256-rQw9yC01qE/LS134zucIhLD6GFcVUzHX5HyzwosdGXM=",
1191− "dependencies": [
1192− "arrays",
1193− "control",
1194− "either",
1195− "foldable-traversable",
1196− "integers",
1197− "js-uri",
1198− "lazy",
1199− "maybe",
1200− "newtype",
1201− "prelude",
1202− "profunctor",
1203− "record",
1204− "strings",
1205− "tuples"
1206− ]
1207− },
1208− "safe-coerce": {
1209− "type": "registry",
1210− "version": "2.0.0",
1211− "integrity": "sha256-EJrxtKt5xC7TYjBZrSBO/J7Aw3DmtilYjt4olpAXWVc=",
1212− "dependencies": [
1213− "unsafe-coerce"
1214− ]
1215− },
1216− "spec": {
1217− "type": "registry",
1218− "version": "8.1.2",
1219− "integrity": "sha256-klPPJ6lBQI1CGOAdLJ+ZoGRt8XZippkTKjn53BrSkL0=",
1220− "dependencies": [
1221− "aff",
1222− "ansi",
1223− "arrays",
1224− "avar",
1225− "bifunctors",
1226− "control",
1227− "datetime",
1228− "effect",
1229− "either",
1230− "exceptions",
1231− "foldable-traversable",
1232− "fork",
1233− "identity",
1234− "integers",
1235− "lists",
1236− "maybe",
1237− "newtype",
1238− "now",
1239− "ordered-collections",
1240− "parallel",
1241− "pipes",
1242− "prelude",
1243− "refs",
1244− "strings",
1245− "tailrec",
1246− "transformers",
1247− "tuples"
1248− ]
1249− },
1250− "spec-discovery": {
1251− "type": "registry",
1252− "version": "8.4.1",
1253− "integrity": "sha256-guvY+NtSOBQmM+HqNJ7woX6taN8hS1wEz7JDmdKF11E=",
1254− "dependencies": [
1255− "aff",
1256− "effect",
1257− "foldable-traversable",
1258− "prelude",
1259− "spec",
1260− "spec-node"
1261− ]
1262− },
1263− "spec-node": {
1264− "type": "registry",
1265− "version": "0.0.2",
1266− "integrity": "sha256-HDW02z3Mj+daux0j9487ApDBX32/gX0od6YR4zvDRZI=",
1267− "dependencies": [
1268− "aff",
1269− "argonaut-codecs",
1270− "argonaut-core",
1271− "arrays",
1272− "control",
1273− "datetime",
1274− "effect",
1275− "either",
1276− "foldable-traversable",
1277− "identity",
1278− "integers",
1279− "maybe",
1280− "newtype",
1281− "node-buffer",
1282− "node-fs",
1283− "node-process",
1284− "now",
1285− "numbers",
1286− "optparse",
1287− "ordered-collections",
1288− "partial",
1289− "prelude",
1290− "spec",
1291− "strings",
1292− "tuples"
1293− ]
1294− },
1295− "spec-quickcheck": {
1296− "type": "registry",
1297− "version": "5.0.2",
1298− "integrity": "sha256-pmnLu9e9Yk+Yx4hi71XwbyuPS27ya4hjTOKk2KFK/Ns=",
1299− "dependencies": [
1300− "aff",
1301− "arrays",
1302− "effect",
1303− "foldable-traversable",
1304− "lists",
1305− "maybe",
1306− "prelude",
1307− "quickcheck",
1308− "tuples"
1309− ]
1310− },
1311− "st": {
1312− "type": "registry",
1313− "version": "6.2.0",
1314− "integrity": "sha256-WI4MEkkwUd4pnwZQ3G8VKWgX5t1RSNJludm5e9boaRo=",
1315− "dependencies": [
1316− "effect",
1317− "partial",
1318− "prelude",
1319− "tailrec",
1320− "unsafe-coerce"
1321− ]
1322− },
1323− "strings": {
1324− "type": "registry",
1325− "version": "6.0.1",
1326− "integrity": "sha256-FNto2hoNW5Da6W6crIk77YXMagBvOGHZE1kO7eZ1vLM=",
1327− "dependencies": [
1328− "arrays",
1329− "control",
1330− "either",
1331− "enums",
1332− "foldable-traversable",
1333− "gen",
1334− "integers",
1335− "maybe",
1336− "newtype",
1337− "nonempty",
1338− "partial",
1339− "prelude",
1340− "tailrec",
1341− "tuples",
1342− "unfoldable",
1343− "unsafe-coerce"
1344− ]
1345− },
1346− "tailrec": {
1347− "type": "registry",
1348− "version": "6.1.0",
1349− "integrity": "sha256-xrorCfP0xV1wubs27idQCHQqdvSUuqmmL/am7Ji1wVU=",
1350− "dependencies": [
1351− "bifunctors",
1352− "effect",
1353− "either",
1354− "identity",
1355− "maybe",
1356− "partial",
1357− "prelude",
1358− "refs"
1359− ]
1360− },
1361− "transformers": {
1362− "type": "registry",
1363− "version": "6.1.0",
1364− "integrity": "sha256-QJmgNT/y7ljPHSsXaW4zxF/982BFiQ90KNL1g/NtEOQ=",
1365− "dependencies": [
1366− "control",
1367− "distributive",
1368− "effect",
1369− "either",
1370− "exceptions",
1371− "foldable-traversable",
1372− "identity",
1373− "lazy",
1374− "maybe",
1375− "newtype",
1376− "prelude",
1377− "st",
1378− "tailrec",
1379− "tuples",
1380− "unfoldable"
1381− ]
1382− },
1383− "tuples": {
1384− "type": "registry",
1385− "version": "7.0.0",
1386− "integrity": "sha256-BKy7EfK8S1KeTCwyWqyW1wwcpSAQuh3IsczSVgS6fzY=",
1387− "dependencies": [
1388− "control",
1389− "invariant",
1390− "prelude"
1391− ]
1392− },
1393− "type-equality": {
1394− "type": "registry",
1395− "version": "4.0.1",
1396− "integrity": "sha256-BBqYOSnAKmayRvR5mtZoCf4SlYs2ipatD/+5nQx73aw=",
1397− "dependencies": []
1398− },
1399− "typelevel-prelude": {
1400− "type": "registry",
1401− "version": "7.0.0",
1402− "integrity": "sha256-+pHi14/40mTj/+lmCWqL0T7iXIXD1+NSg/KItyyoB0A=",
1403− "dependencies": [
1404− "prelude",
1405− "type-equality"
1406− ]
1407− },
1408− "uncurried-transformers": {
1409− "type": "registry",
1410− "version": "1.1.0",
1411− "integrity": "sha256-AqqBMzVLzozVoDorE3QcVVRDkLd7O3624mRHCDnPhaI=",
1412− "dependencies": [
1413− "control",
1414− "effect",
1415− "either",
1416− "functions",
1417− "identity",
1418− "prelude",
1419− "safe-coerce",
1420− "tailrec",
1421− "transformers",
1422− "tuples"
1423− ]
1424− },
1425− "undefined-is-not-a-problem": {
1426− "type": "registry",
1427− "version": "1.1.0",
1428− "integrity": "sha256-0YkVzpcKi40T43go7/f8uLVIYgir6lGzOytL6LPfiog=",
1429− "dependencies": [
1430− "effect",
1431− "either",
1432− "foreign",
1433− "maybe",
1434− "newtype",
1435− "prelude",
1436− "tuples",
1437− "type-equality",
1438− "unsafe-coerce"
1439− ]
1440− },
1441− "unfoldable": {
1442− "type": "registry",
1443− "version": "6.0.0",
1444− "integrity": "sha256-BK/6By1sKp/ztk+9CF3q43SV0QDTLVdsGqFerKHSmbg=",
1445− "dependencies": [
1446− "foldable-traversable",
1447− "maybe",
1448− "partial",
1449− "prelude",
1450− "tuples"
1451− ]
1452− },
1453− "unsafe-coerce": {
1454− "type": "registry",
1455− "version": "6.0.0",
1456− "integrity": "sha256-0L1QsaY20OILjfU5TV72d3U/tSjhmL9hJ32WMp857Lk=",
1457− "dependencies": []
1458− },
1459− "untagged-union": {
1460− "type": "registry",
1461− "version": "1.0.0",
1462− "integrity": "sha256-MQvpb13TZEBoi9n/AoQ7ugniSQqbN6XQmAjii9pqJRk=",
1463− "dependencies": [
1464− "either",
1465− "foreign",
1466− "foreign-object",
1467− "literals",
1468− "maybe",
1469− "newtype",
1470− "prelude",
1471− "tuples",
1472− "unsafe-coerce"
1473− ]
1474− },
1475− "variant": {
1476− "type": "registry",
1477− "version": "8.0.0",
1478− "integrity": "sha256-Ydrgl8liWEwYQOWW76PdZtg3vxKpoKgsnmFyTLgZkoU=",
1479− "dependencies": [
1480− "control",
1481− "enums",
1482− "foldable-traversable",
1483− "lists",
1484− "maybe",
1485− "partial",
1486− "prelude",
1487− "type-equality",
1488− "unsafe-coerce"
1489− ]
1490− },
1491− "web-events": {
1492− "type": "registry",
1493− "version": "4.0.0",
1494− "integrity": "sha256-wZNeldG0OU+8qGycUJ9e6vxf1/GC4Ep4OlRMhvjs9LA=",
1495− "dependencies": [
1496− "datetime",
1497− "effect",
1498− "enums",
1499− "foreign",
1500− "functions",
1501− "maybe",
1502− "newtype",
1503− "nullable",
1504− "prelude",
1505− "unsafe-coerce"
1506− ]
1507− },
1508− "web-file": {
1509− "type": "registry",
1510− "version": "4.0.0",
1511− "integrity": "sha256-txsdkeWBKU/+5v9m5c6kysgJQSDyV1r7MHaeT4STpjQ=",
1512− "dependencies": [
1513− "datetime",
1514− "effect",
1515− "enums",
1516− "foreign",
1517− "integers",
1518− "maybe",
1519− "media-types",
1520− "nullable",
1521− "numbers",
1522− "partial",
1523− "prelude",
1524− "tuples",
1525− "unfoldable",
1526− "unsafe-coerce",
1527− "web-events"
1528− ]
1529− },
1530− "web-streams": {
1531− "type": "registry",
1532− "version": "4.0.0",
1533− "integrity": "sha256-iKQbHh/3wNOWyGTZmWJZ1Yuri9J/wQIJKXcxrELaHVo=",
1534− "dependencies": [
1535− "arraybuffer-types",
1536− "effect",
1537− "exceptions",
1538− "js-promise",
1539− "maybe",
1540− "nullable",
1541− "prelude",
1542− "tuples"
1543− ]
1544− },
1545− "yoga-fastify": {
1546− "type": "registry",
1547− "version": "0.5.4",
1548− "integrity": "sha256-YenjePRdiApMPpcvkXlzre7c4fIuvk5T19Z2uEAWhR4=",
1549− "dependencies": [
1550− "aff",
1551− "arrays",
1552− "bifunctors",
1553− "effect",
1554− "either",
1555− "foldable-traversable",
1556− "foreign",
1557− "foreign-object",
1558− "js-promise",
1559− "js-promise-aff",
1560− "maybe",
1561− "newtype",
1562− "nullable",
1563− "prelude",
1564− "record",
1565− "strings",
1566− "unsafe-coerce",
1567− "variant",
1568− "yoga-http-api",
1569− "yoga-json"
1570− ]
1571− },
1572− "yoga-fastify-om": {
1573− "type": "registry",
1574− "version": "0.4.7",
1575− "integrity": "sha256-KGQ7lHI7pcSiEQoEq6j6K+3XilcPy8wQ/M9C1y+uaEk=",
1576− "dependencies": [
1577− "aff",
1578− "console",
1579− "effect",
1580− "either",
1581− "exceptions",
1582− "foreign",
1583− "foreign-object",
1584− "integers",
1585− "maybe",
1586− "node-buffer",
1587− "numbers",
1588− "prelude",
1589− "record",
1590− "refs",
1591− "routing-duplex",
1592− "strings",
1593− "transformers",
1594− "typelevel-prelude",
1595− "unsafe-coerce",
1596− "variant",
1597− "yoga-fastify",
1598− "yoga-http-api",
1599− "yoga-json",
1600− "yoga-om",
1601− "yoga-om-layer",
1602− "yoga-om-strom"
1603− ]
1604− },
1605− "yoga-http-api": {
1606− "type": "registry",
1607− "version": "0.3.4",
1608− "integrity": "sha256-DSIJ8YWr5vB5IMpyaBALM+fx57lz3AAAR0MGtfHeWxo=",
1609− "dependencies": [
1610− "aff",
1611− "arraybuffer-types",
1612− "arrays",
1613− "effect",
1614− "either",
1615− "foldable-traversable",
1616− "foreign",
1617− "foreign-object",
1618− "identity",
1619− "integers",
1620− "js-promise",
1621− "js-promise-aff",
1622− "maybe",
1623− "newtype",
1624− "nullable",
1625− "numbers",
1626− "prelude",
1627− "record",
1628− "strings",
1629− "tuples",
1630− "undefined-is-not-a-problem",
1631− "unsafe-coerce",
1632− "variant",
1633− "yoga-json",
1634− "yoga-options"
1635− ]
1636− },
1637− "yoga-json": {
1638− "type": "registry",
1639− "version": "5.2.1",
1640− "integrity": "sha256-12I7qIf27oKV/D/YRcHtGpN8n7GQ0Bm3uzvI4ZjOQrs=",
1641− "dependencies": [
1642− "arrays",
1643− "bifunctors",
1644− "control",
1645− "datetime",
1646− "effect",
1647− "either",
1648− "exceptions",
1649− "foldable-traversable",
1650− "foreign",
1651− "foreign-object",
1652− "free",
1653− "identity",
1654− "integers",
1655− "js-bigints",
1656− "js-date",
1657− "lists",
1658− "maybe",
1659− "newtype",
1660− "nullable",
1661− "numbers",
1662− "ordered-collections",
1663− "partial",
1664− "prelude",
1665− "record",
1666− "safe-coerce",
1667− "strings",
1668− "transformers",
1669− "tuples",
1670− "typelevel-prelude",
1671− "unsafe-coerce",
1672− "variant",
1673− "yoga-tree"
1674− ]
1675− },
1676− "yoga-om": {
1677− "type": "registry",
1678− "version": "1.5.2",
1679− "integrity": "sha256-2ys14BF6NPgzFDFUIFk0EDxmqkA8+yghIA9TXHlOmE0=",
1680− "dependencies": [
1681− "aff",
1682− "aff-retry",
1683− "avar",
1684− "console",
1685− "control",
1686− "datetime",
1687− "effect",
1688− "either",
1689− "exceptions",
1690− "functions",
1691− "heterogeneous",
1692− "maybe",
1693− "newtype",
1694− "parallel",
1695− "prelude",
1696− "record",
1697− "record-studio",
1698− "refs",
1699− "tailrec",
1700− "transformers",
1701− "tuples",
1702− "typelevel-prelude",
1703− "uncurried-transformers",
1704− "unsafe-coerce",
1705− "variant"
1706− ]
1707− },
1708− "yoga-om-layer": {
1709− "type": "registry",
1710− "version": "1.2.2",
1711− "integrity": "sha256-Usw2ZysteSYNkEG3CDmVVXUk7cgr1mntkmhbR33nF6M=",
1712− "dependencies": [
1713− "aff",
1714− "aff-retry",
1715− "arrays",
1716− "effect",
1717− "exceptions",
1718− "foldable-traversable",
1719− "maybe",
1720− "nullable",
1721− "ordered-collections",
1722− "parallel",
1723− "prelude",
1724− "record",
1725− "record-studio",
1726− "refs",
1727− "transformers",
1728− "type-equality",
1729− "typelevel-prelude",
1730− "unsafe-coerce",
1731− "variant",
1732− "yoga-om"
1733− ]
1734− },
1735− "yoga-om-strom": {
1736− "type": "registry",
1737− "version": "0.4.3",
1738− "integrity": "sha256-dxj1zveEES6lF+iiMHx+qOhUG3zmiJJnlNpwiAfUBRE=",
1739− "dependencies": [
1740− "aff",
1741− "arrays",
1742− "avar",
1743− "catenable-lists",
1744− "console",
1745− "control",
1746− "datetime",
1747− "effect",
1748− "either",
1749− "exceptions",
1750− "foldable-traversable",
1751− "integers",
1752− "lists",
1753− "maybe",
1754− "now",
1755− "prelude",
1756− "refs",
1757− "spec",
1758− "st",
1759− "tailrec",
1760− "transformers",
1761− "tuples",
1762− "variant",
1763− "yoga-om"
1764− ]
1765− },
1766− "yoga-options": {
1767− "type": "registry",
1768− "version": "0.1.1",
1769− "integrity": "sha256-INtZKI2rw7KcDikzmyXlglsEujSMqHT5jz3ho9dVYC8=",
1770− "dependencies": [
1771− "identity",
1772− "literals",
1773− "unsafe-coerce",
1774− "untagged-union"
1775− ]
1776− },
1777− "yoga-tree": {
1778− "type": "registry",
1779− "version": "1.0.0",
1780− "integrity": "sha256-s8rIVEQkRi1VrMc92T9ceXcY0X6r5A4QqT6f7GgmDQI=",
1781− "dependencies": [
1782− "arrays",
1783− "control",
1784− "foldable-traversable",
1785− "free",
1786− "maybe",
1787− "prelude",
1788− "tailrec"
1789− ]
1790− }
1791− }
1792−}
spago.yaml+8−25
@@ -1,8 +1,9 @@
11workspace: {}
2+
23package:
34 name: yoga-fetch-om
45 publish:
5− version: 0.8.1
6+ version: 0.1.0
67 license: MIT
78 location:
89 githubOwner: rowtype-yoga
@@ -10,49 +11,31 @@ package:
1011 include:
1112 - LICENSE
1213 - README.md
14+ - CHANGELOG.md
1315 exclude:
1416 - .github
1517 dependencies:
1618 - aff: ">=8.0.0 <9.0.0"
17− - arraybuffer-types: ">=3.0.2 <4.0.0"
1819 - arrays: ">=7.3.0 <8.0.0"
1920 - effect: ">=4.0.0 <5.0.0"
20− - either: ">=6.1.0 <7.0.0"
2121 - exceptions: ">=6.1.0 <7.0.0"
22− - http-methods: ">=6.1.0 <7.0.0"
22+ - http-methods: ">=6.0.0 <7.0.0"
2323 - js-fetch: ">=0.2.1 <0.3.0"
2424 - js-promise-aff: ">=1.0.0 <2.0.0"
2525 - maybe: ">=6.0.0 <7.0.0"
2626 - prelude: ">=6.0.2 <7.0.0"
2727 - record: ">=4.0.0 <5.0.0"
2828 - strings: ">=6.0.1 <7.0.0"
29− - tailrec: ">=6.1.0 <7.0.0"
3029 - transformers: ">=6.1.0 <7.0.0"
3130 - tuples: ">=7.0.0 <8.0.0"
3231 - typelevel-prelude: ">=7.0.0 <8.0.0"
3332 - unsafe-coerce: ">=6.0.0 <7.0.0"
3433 - variant: ">=8.0.0 <9.0.0"
35− - yoga-http-api: ">=0.3.4 <0.4.0"
36− - yoga-json: ">=5.2.1 <6.0.0"
37− - yoga-om: ">=1.5.2 <2.0.0"
38− - yoga-om-strom: ">=0.4.3 <0.5.0"
34+ - yoga-http-api: ">=0.1.0 <0.2.0"
35+ - yoga-json: ">=5.2.0 <6.0.0"
36+ - yoga-om: ">=0.1.0 <0.2.0"
3937 test:
4038 main: Test.Main
4139 dependencies:
42− - enums
43− - foldable-traversable
44− - foreign
45− - foreign-object
46− - integers
47− - js-promise
48− - partial
49− - yoga-fastify
40+ - vitest: ">=1.0.0 <2.0.0"
5041 - console: ">=6.0.0 <7.0.0"
51− - js-uri: ">=3.1.0 <4.0.0"
52− - justifill: ">=0.5.0 <0.6.0"
53− - quickcheck: ">=8.0.1 <9.0.0"
54− - refs: ">=6.0.0 <7.0.0"
55− - spec: ">=8.0.0 <9.0.0"
56− - spec-discovery: ">=8.0.0 <9.0.0"
57− - spec-quickcheck: ">=5.0.2 <6.0.0"
58− - yoga-fastify-om: ">=0.4.7 <0.5.0"
src/Yoga/Fetch/Om.jsdeleted−1
@@ -1 +0,0 @@
1−export const mergeRecords = (left) => (right) => ({ ...right, ...left });
src/Yoga/Fetch/Om.purs+37−231
@@ -1,34 +1,18 @@
11module Yoga.Fetch.Om
2− ( client
3− , clientWith
4− , ClientInputs
5− , ClientWithConfig
2+ ( class DeriveClient
63 , deriveClient
7− , class DeriveClient
8− , deriveClientImpl
9− , class DeriveClientRL
10− , deriveClientRL
114 , class DeriveClientFn
125 , deriveClientFn
13− , class DeriveClientFnWith
14− , deriveClientFnWith
15− , class DeriveClientWith
16− , deriveClientWithImpl
17− , class DeriveClientWithRL
18− , deriveClientWithRL
19− , class RecordRow
20− , class ToHeaders
21− , toHeaders
6+ , class DeriveClientRL
7+ , deriveClientRL
228 , module Yoga.HTTP.API.Route
239 , module Yoga.HTTP.API.Path
24− , module Yoga.Fetch.Om.StreamDecode
2510 , module Yoga.Fetch.Om.Simple
2611 ) where
2712
2813import Prelude
2914
30−import Data.Symbol (class IsSymbol, reflectSymbol)
31−import Data.Tuple.Nested ((/\))
15+import Data.Symbol (class IsSymbol)
3216import Data.Variant (Variant)
3317import Prim.Row as Row
3418import Prim.RowList (class RowToList, RowList)
@@ -36,265 +20,87 @@ import Prim.RowList as RL
3620import Record as Record
3721import Type.Proxy (Proxy(..))
3822import Unsafe.Coerce (unsafeCoerce)
39−import JS.Fetch.Headers (Headers)
40−import JS.Fetch.Headers as Headers
4123import Yoga.Fetch.Om.BuildUrl (class BuildUrl, buildUrl)
4224import Yoga.Fetch.Om.Simple (class DecodeResponse, decodeResponse, FetchError, FetchResponse, get, getWithHeaders, delete, deleteWithHeaders, delete_, post, postWithHeaders, post_, put, putWithHeaders, put_, patch, patchWithHeaders, patch_)
43−import Yoga.Fetch.Om.StreamDecode (class StreamDecode, decodeStream)
44−import Yoga.Fetch.Om.ClientFunction (class BuildClientFn, class CheckBodyIsUnit, buildClientFn)
45−import Yoga.Fetch.Om.ExtractParams (class ExtractRequestBody, class ExtractBodyEncoding, class ExtractRequestHeaders)
46−import Yoga.Fetch.Om.MakeRequest (class MakeRequest, class BodyEncoding, makeRequest, encodingContentType, encodeBody)
25+import Yoga.Fetch.Om.ClientFn (class BuildClientFn, class CheckBodyIsUnit, class CheckRowEmpty, buildClientFn)
26+import Yoga.Fetch.Om.ExtractParams (class ExtractRequestBody, class ExtractRequestHeaders)
27+import Yoga.Fetch.Om.MakeRequest (class MakeRequest, class SerializeBody, makeRequest, serializeBody)
4728import Yoga.Fetch.Om.ParseResponse (class ParseResponse, parseResponse)
4829import Yoga.Fetch.Om.SplitResponses (class SplitResponses)
4930import Yoga.Fetch.Om.Variant (class VariantOrValue, variantOrValue)
5031import Yoga.HTTP.API.Path (Path, Root, Lit, Capture, PathCons, Param, QueryParams, Required, type (/), type (:), type (:?), class PathPattern)
51−import Yoga.HTTP.API.Route (Route(..), GET, POST, PUT, DELETE, PATCH, QUERY, Response(..), JSON, FormData, PlainText, Streaming, NoBody, class HeaderValue, printHeader)
32+import Yoga.HTTP.API.Route (Route(..), GET, POST, PUT, DELETE, PATCH, Response(..), JSON, FormData, NoBody)
5233import Yoga.HTTP.API.Route.Handler (class SegmentPathParams, class SegmentQueryParams)
53−import Yoga.Om (Om, toOm)
54−
55−type ClientInputs providedHeaders providedQuery =
56− { headers :: Record providedHeaders
57− , query :: Record providedQuery
58− }
59−
60−type ClientWithConfig ctx err providedHeaders providedQuery =
61− { baseUrl :: Om { | ctx } err String
62− , provide :: Om { | ctx } err (ClientInputs providedHeaders providedQuery)
63− }
64−
65−foreign import mergeRecords :: forall left right out. Record left -> Record right -> Record out
66−
67−-- | Extract row type from Record type
68−class RecordRow :: Type -> Row Type -> Constraint
69−class RecordRow t r | t -> r
70−
71−instance RecordRow (Record r) r
72−
73−class ToHeaders :: RowList Type -> Row Type -> Constraint
74−class ToHeaders headersRL headers where
75− toHeaders :: Proxy headersRL -> Record headers -> Headers
76−
77−instance ToHeaders RL.Nil headers where
78− toHeaders _ _ = Headers.empty
79−
80−else instance
81− ( IsSymbol name
82− , HeaderValue ty
83− , Row.Cons name ty tailRow headers
84− , Row.Lacks name tailRow
85− , ToHeaders tail tailRow
86− ) =>
87− ToHeaders (RL.Cons name ty tail) headers where
88− toHeaders _ headers = Headers.fromFoldable ([ headerName /\ headerValue ] <> Headers.toArray rest)
89− where
90− headerName = reflectSymbol (Proxy :: Proxy name)
91− headerValue = printHeader (Record.get (Proxy :: Proxy name) headers)
92− rest = toHeaders (Proxy :: Proxy tail) (unsafeCoerce headers :: Record tailRow)
34+import Yoga.Om (Om, fromAff)
9335
94−class DeriveClientFn
95− :: forall k1. Type -> k1 -> Type -> Row Type -> Row Type -> Row Type -> Row Type -> Type -> Type -> Constraint
36+class DeriveClientFn :: forall k1. Type -> k1 -> Type -> Row Type -> Row Type -> Row Type -> Type -> Type -> Constraint
9637class
97− DeriveClientFn method segments request response ctx extraErr routeErrors result fn
98− | method segments request response -> routeErrors result
99− , method segments request response ctx extraErr -> fn where
38+ DeriveClientFn method segments request response errorRow successRow result fn
39+ | method segments request response -> errorRow successRow result fn where
10040 deriveClientFn :: String -> Proxy (Route method segments request response) -> fn
10141
10242instance
10343 ( SegmentPathParams segments pathParams
10444 , SegmentQueryParams segments queryParams
10545 , ExtractRequestBody request body
106− , ExtractBodyEncoding request encoding
10746 , ExtractRequestHeaders request headers
10847 , PathPattern segments
10948 , BuildUrl segments pathParams queryParams
11049 , MakeRequest method
111− , BodyEncoding encoding body
112− , SplitResponses response successRow routeErrors
113− , ParseResponse routeErrors successRow
50+ , SerializeBody body
51+ , SplitResponses response successRow errorRow
52+ , ParseResponse errorRow successRow
11453 , RowToList successRow successRL
11554 , VariantOrValue successRL successRow result
11655 , Row.Union pathParams queryParams pathQuery
11756 , Row.Nub pathQuery pathQuery
11857 , RowToList pathQuery pathQueryRL
119− , RowToList headers headersRL
120− , ToHeaders headersRL headers
58+ , CheckRowEmpty headers headersFlag
12159 , CheckBodyIsUnit body bodyFlag
122− , Row.Union routeErrors extraErr errRow
123− , BuildClientFn pathQueryRL headersRL bodyFlag body pathQuery headers (Record pathQuery) { | ctx } errRow result fn
60+ , BuildClientFn pathQueryRL headersFlag bodyFlag body pathQuery headers errorRow result fn
12461 ) =>
125− DeriveClientFn method segments request response ctx extraErr routeErrors result fn where
62+ DeriveClientFn method segments request response errorRow successRow result fn where
12663 deriveClientFn baseUrl _ =
127− buildClientFn (Proxy :: _ pathQueryRL) (Proxy :: _ headersRL) (Proxy :: _ bodyFlag) identity impl
64+ buildClientFn (Proxy :: _ pathQueryRL) (Proxy :: _ headersFlag) (Proxy :: _ bodyFlag) impl
12865 where
129− impl :: Record pathQuery -> Record headers -> body -> Om { | ctx } errRow result
130− impl pathQueryRec headersRec bodyVal = widenOm do
66+ impl :: Record pathQuery -> Record headers -> body -> Om {} errorRow result
67+ impl pathQueryRec _headers bodyVal = do
13168 let url = buildUrl baseUrl (Proxy :: _ segments) pathParamsRec queryParamsRec
132− let hdrs = toHeaders (Proxy :: _ headersRL) headersRec
133− let ct = encodingContentType (Proxy :: _ encoding)
134− fetchResp <- makeRequest (Proxy :: _ method) url hdrs ct (encodeBody @encoding bodyVal) # toOm
135− variant <- parseResponse fetchResp :: Om (Record ()) routeErrors (Variant successRow)
69+ fetchResp <- makeRequest (Proxy :: _ method) url (serializeBody bodyVal) # fromAff
70+ variant <- parseResponse fetchResp :: Om {} errorRow (Variant successRow)
13671 variantOrValue (Proxy :: _ successRL) variant # pure
13772 where
13873 pathParamsRec = unsafeCoerce pathQueryRec :: Record pathParams
13974 queryParamsRec = unsafeCoerce pathQueryRec :: Record queryParams
14075
141− widenOm :: Om (Record ()) routeErrors ~> Om { | ctx } errRow
142− widenOm = unsafeCoerce
143−
144−class DeriveClientFnWith
145− :: forall k1. Type -> k1 -> Type -> Row Type -> Row Type -> Row Type -> Row Type -> Row Type -> Row Type -> Type -> Type -> Constraint
146−class
147− DeriveClientFnWith method segments request response providedHeaders providedQuery ctx extraErr routeErrors result fn
148− | method segments request response -> routeErrors result
149− , method segments request response providedHeaders providedQuery ctx extraErr -> fn where
150− deriveClientFnWith
151− :: ClientWithConfig ctx extraErr providedHeaders providedQuery
152− -> Proxy (Route method segments request response)
153− -> fn
154−
155−instance
156− ( SegmentPathParams segments pathParams
157− , SegmentQueryParams segments queryParams
158− , ExtractRequestBody request body
159− , ExtractBodyEncoding request encoding
160− , ExtractRequestHeaders request headers
161− , PathPattern segments
162− , BuildUrl segments pathParams queryParams
163− , MakeRequest method
164− , BodyEncoding encoding body
165− , SplitResponses response successRow routeErrors
166− , Row.Union pathParams queryParams pathQuery
167− , Row.Nub pathQuery pathQuery
168− , ParseResponse routeErrors successRow
169− , RowToList successRow successRL
170− , VariantOrValue successRL successRow result
171− , Row.Union routeErrors extraErr errRow
172− , Row.Union providedQuery remainingQuery queryParams
173− , Row.Union pathParams remainingQuery callerPathQuery
174− , Row.Nub callerPathQuery callerPathQuery
175− , RowToList callerPathQuery callerPathQueryRL
176− , RowToList headers headersRL
177− , ToHeaders headersRL headers
178− , Row.Union providedHeaders remainingHeaders headers
179− , Row.Nub headers headers
180− , RowToList remainingHeaders remainingHeadersRL
181− , CheckBodyIsUnit body bodyFlag
182− , BuildClientFn callerPathQueryRL remainingHeadersRL bodyFlag body callerPathQuery remainingHeaders (Record callerPathQuery) { | ctx } errRow result fn
183− ) =>
184− DeriveClientFnWith method segments request response providedHeaders providedQuery ctx extraErr routeErrors result fn where
185− deriveClientFnWith config _ =
186− buildClientFn (Proxy :: _ callerPathQueryRL) (Proxy :: _ remainingHeadersRL) (Proxy :: _ bodyFlag) identity impl
187− where
188− impl :: Record callerPathQuery -> Record remainingHeaders -> body -> Om { | ctx } errRow result
189− impl pathQueryRec headersRec bodyVal = do
190− baseUrl <- widenExtra config.baseUrl
191− provided <- widenExtra config.provide
192− let pathParamsRec = unsafeCoerce pathQueryRec :: Record pathParams
193− let queryParamsRec = mergeRecords provided.query (unsafeCoerce pathQueryRec :: Record remainingQuery) :: Record queryParams
194− let fullHeaders = mergeRecords provided.headers headersRec :: Record headers
195− let url = buildUrl baseUrl (Proxy :: _ segments) pathParamsRec queryParamsRec
196− let hdrs = toHeaders (Proxy :: _ headersRL) fullHeaders
197− let ct = encodingContentType (Proxy :: _ encoding)
198− fetchResp <- makeRequest (Proxy :: _ method) url hdrs ct (encodeBody @encoding bodyVal) # toOm # widenRoute
199− variant <- parseResponse fetchResp # widenRoute :: Om { | ctx } errRow (Variant successRow)
200− variantOrValue (Proxy :: _ successRL) variant # pure
201− where
202− widenExtra :: Om { | ctx } extraErr ~> Om { | ctx } errRow
203− widenExtra = unsafeCoerce
204−
205− widenRoute :: Om (Record ()) routeErrors ~> Om { | ctx } errRow
206− widenRoute = unsafeCoerce
207−
208−class DeriveClient :: Row Type -> Row Type -> Row Type -> Row Type -> Constraint
209−class DeriveClient ctx extraErr routesRow clientsRow | routesRow ctx extraErr -> clientsRow where
210− deriveClientImpl :: String -> Proxy (Record routesRow) -> Record clientsRow
211−
212−-- | Derive API client functions from route definitions using VTA.
213−-- | Generated fields use ordinary function application. Path parameters are
214−-- | plain records; optional query parameters are explicit `Maybe` fields.
215−-- |
216−-- | ```purescript
217−-- | type UserAPI = { getUser :: Route ... }
218−-- | api = client @UserAPI "https://api.example.com"
219−-- | user <- api.getUser { id: 42 }
220−-- | users <- api.listUsers { limit: Just 10, offset: Nothing }
221−-- | health <- api.health
222−-- | ```
223−client :: forall @routes routesRow ctx extraErr clientsRow. RecordRow routes routesRow => DeriveClient ctx extraErr routesRow clientsRow => String -> Record clientsRow
224−client baseUrl = deriveClientImpl @ctx @extraErr baseUrl (Proxy :: _ { | routesRow })
225−
226−-- | Deprecated: Use `client` with VTA instead
227−-- |
228−-- | ```purescript
229−-- | api = deriveClient @UserAPI "https://api.example.com"
230−-- | ```
231−deriveClient :: forall @routesRow ctx extraErr clientsRow. DeriveClient ctx extraErr routesRow clientsRow => String -> Record clientsRow
232−deriveClient baseUrl = deriveClientImpl @ctx @extraErr baseUrl (Proxy :: _ { | routesRow })
233−
234−clientWith
235− :: forall @routes @providedHeaders @providedQuery routesRow ctx extraErr clientsRow
236− . RecordRow routes routesRow
237− => DeriveClientWith providedHeaders providedQuery ctx extraErr routesRow clientsRow
238− => ClientWithConfig ctx extraErr providedHeaders providedQuery
239− -> Record clientsRow
240−clientWith config = deriveClientWithImpl @providedHeaders @providedQuery @ctx @extraErr config (Proxy :: _ { | routesRow })
76+class DeriveClient :: Row Type -> Row Type -> Constraint
77+class DeriveClient routesRow clientsRow | routesRow -> clientsRow where
78+ deriveClient :: String -> Proxy (Record routesRow) -> Record clientsRow
24179
24280instance
24381 ( RowToList routesRow rl
244− , DeriveClientRL ctx extraErr rl () clientsRow
82+ , DeriveClientRL rl () clientsRow
24583 ) =>
246− DeriveClient ctx extraErr routesRow clientsRow where
247− deriveClientImpl baseUrl _ = deriveClientRL @ctx @extraErr baseUrl (Proxy :: _ rl) {}
248−
249−class DeriveClientWith :: Row Type -> Row Type -> Row Type -> Row Type -> Row Type -> Row Type -> Constraint
250−class DeriveClientWith providedHeaders providedQuery ctx extraErr routesRow clientsRow | providedHeaders providedQuery routesRow ctx extraErr -> clientsRow where
251− deriveClientWithImpl :: ClientWithConfig ctx extraErr providedHeaders providedQuery -> Proxy (Record routesRow) -> Record clientsRow
252−
253−instance
254− ( RowToList routesRow rl
255− , DeriveClientWithRL providedHeaders providedQuery ctx extraErr rl () clientsRow
256− ) =>
257− DeriveClientWith providedHeaders providedQuery ctx extraErr routesRow clientsRow where
258− deriveClientWithImpl config _ = deriveClientWithRL @providedHeaders @providedQuery @ctx @extraErr config (Proxy :: _ rl) {}
259−
260−class DeriveClientWithRL :: Row Type -> Row Type -> Row Type -> Row Type -> RowList Type -> Row Type -> Row Type -> Constraint
261−class DeriveClientWithRL providedHeaders providedQuery ctx extraErr rl acc out | providedHeaders providedQuery ctx extraErr rl acc -> out where
262− deriveClientWithRL :: ClientWithConfig ctx extraErr providedHeaders providedQuery -> Proxy rl -> Record acc -> Record out
263−
264−instance DeriveClientWithRL providedHeaders providedQuery ctx extraErr RL.Nil acc acc where
265− deriveClientWithRL _ _ acc = acc
266−
267−instance
268− ( IsSymbol label
269− , DeriveClientFnWith method segments request response providedHeaders providedQuery ctx extraErr routeErrors result fn
270− , DeriveClientWithRL providedHeaders providedQuery ctx extraErr tail acc1 acc2
271− , Row.Cons label fn acc2 out
272− , Row.Lacks label acc2
273− , Row.Cons label (Route method segments request response) routeTail routeRow
274− ) =>
275− DeriveClientWithRL providedHeaders providedQuery ctx extraErr (RL.Cons label (Route method segments request response) tail) acc1 out where
276− deriveClientWithRL config _ acc = Record.insert (Proxy :: _ label) clientFn rest
277− where
278− clientFn = deriveClientFnWith @_ @_ @_ @_ @providedHeaders @providedQuery @ctx @extraErr config (Proxy :: _ (Route method segments request response))
279− rest = deriveClientWithRL @providedHeaders @providedQuery @ctx @extraErr config (Proxy :: _ tail) acc
84+ DeriveClient routesRow clientsRow where
85+ deriveClient baseUrl _ = deriveClientRL baseUrl (Proxy :: _ rl) {}
28086
281−class DeriveClientRL :: Row Type -> Row Type -> RowList Type -> Row Type -> Row Type -> Constraint
282−class DeriveClientRL ctx extraErr rl acc out | ctx extraErr rl acc -> out where
87+class DeriveClientRL :: RowList Type -> Row Type -> Row Type -> Constraint
88+class DeriveClientRL rl acc out | rl acc -> out where
28389 deriveClientRL :: String -> Proxy rl -> Record acc -> Record out
28490
285−instance DeriveClientRL ctx extraErr RL.Nil acc acc where
91+instance DeriveClientRL RL.Nil acc acc where
28692 deriveClientRL _ _ acc = acc
28793
28894instance
28995 ( IsSymbol label
290− , DeriveClientFn method segments request response ctx extraErr routeErrors result fn
291− , DeriveClientRL ctx extraErr tail acc1 acc2
96+ , DeriveClientFn method segments request response errorRow successRow result fn
97+ , DeriveClientRL tail acc1 acc2
29298 , Row.Cons label fn acc2 out
29399 , Row.Lacks label acc2
294100 , Row.Cons label (Route method segments request response) routeTail routeRow
295101 ) =>
296− DeriveClientRL ctx extraErr (RL.Cons label (Route method segments request response) tail) acc1 out where
102+ DeriveClientRL (RL.Cons label (Route method segments request response) tail) acc1 out where
297103 deriveClientRL baseUrl _ acc = Record.insert (Proxy :: _ label) clientFn rest
298104 where
299− clientFn = deriveClientFn @_ @_ @_ @_ @ctx @extraErr baseUrl (Proxy :: _ (Route method segments request response))
300− rest = deriveClientRL @ctx @extraErr baseUrl (Proxy :: _ tail) acc
105+ clientFn = deriveClientFn baseUrl (Proxy :: _ (Route method segments request response))
106+ rest = deriveClientRL baseUrl (Proxy :: _ tail) acc
src/Yoga/Fetch/Om/BuildUrl.jsdeleted−87
@@ -1,87 +0,0 @@
1−export function encodeURIComponent_(value) {
2− try {
3− return encodeURIComponent(value);
4− } catch (error) {
5− if (!(error instanceof URIError)) throw error;
6− return encodeURIComponent(toWellFormed(value));
7− }
8−}
9−
10−function toWellFormed(value) {
11− if (typeof value.toWellFormed === "function") return value.toWellFormed();
12−
13− let result = "";
14− let sliceStart = 0;
15− for (let index = 0; index < value.length; index += 1) {
16− const codeUnit = value.charCodeAt(index);
17− const previous = index === 0 ? 0 : value.charCodeAt(index - 1);
18− const next =
19− index + 1 === value.length ? 0 : value.charCodeAt(index + 1);
20− const loneHigh =
21− codeUnit >= 0xd800 &&
22− codeUnit <= 0xdbff &&
23− (next < 0xdc00 || next > 0xdfff);
24− const loneLow =
25− codeUnit >= 0xdc00 &&
26− codeUnit <= 0xdfff &&
27− (previous < 0xd800 || previous > 0xdbff);
28−
29− if (!loneHigh && !loneLow) continue;
30− result += value.slice(sliceStart, index) + "\ufffd";
31− sliceStart = index + 1;
32− }
33−
34− return sliceStart === 0 ? value : result + value.slice(sliceStart);
35−}
36−
37−function urlSuffixIndex(url) {
38− const queryIndex = url.indexOf("?");
39− const fragmentIndex = url.indexOf("#");
40− return Math.min(
41− queryIndex === -1 ? url.length : queryIndex,
42− fragmentIndex === -1 ? url.length : fragmentIndex,
43− );
44−}
45−
46−export function appendPath_(base) {
47− return function (path) {
48− const suffixIndex = urlSuffixIndex(base);
49− const prefix = base.slice(0, suffixIndex).replace(/\/+$/, "");
50− return prefix + path + base.slice(suffixIndex);
51− };
52−}
53−
54−
55−export function substitutePathParam_(name) {
56− const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
57− const segment = new RegExp(`(^|/):${escapedName}(?=/|[?#]|$)`, "g");
58− return function (value) {
59− const encodedValue = encodeURIComponent_(value);
60− return function (url) {
61− const suffixIndex = urlSuffixIndex(url);
62− const path = url.slice(0, suffixIndex);
63− return (
64− path.replace(segment, (_, prefix) => prefix + encodedValue) +
65− url.slice(suffixIndex)
66− );
67− };
68− };
69−}
70−
71−export function appendQueryString_(url) {
72− return function (queryString) {
73− if (queryString === "") return url;
74−
75− const fragmentIndex = url.indexOf("#");
76− const beforeFragment =
77− fragmentIndex === -1 ? url : url.slice(0, fragmentIndex);
78− const fragment = fragmentIndex === -1 ? "" : url.slice(fragmentIndex);
79− const separator = beforeFragment.includes("?")
80− ? beforeFragment.endsWith("?") || beforeFragment.endsWith("&")
81− ? ""
82− : "&"
83− : "?";
84−
85− return beforeFragment + separator + queryString + fragment;
86− };
87−}
src/Yoga/Fetch/Om/BuildUrl.purs+17−60
@@ -3,10 +3,8 @@ module Yoga.Fetch.Om.BuildUrl
33 , buildUrl
44 , class SubstitutePathParams
55 , substitutePathParams
6− , substitutePathParamsImpl
76 , class AppendQueryParams
87 , appendQueryParams
9− , appendQueryParamsImpl
108 , class AppendQueryParamsRL
119 , appendQueryParamsRL
1210 , class SubstitutePathParamsRL
@@ -19,6 +17,7 @@ import Prelude
1917
2018import Data.Array as Array
2119import Data.Maybe (Maybe(..))
20+import Data.String (Pattern(..), Replacement(..))
2221import Data.String as String
2322import Data.Symbol (class IsSymbol, reflectSymbol)
2423import Prim.Row as Row
@@ -27,13 +26,6 @@ import Prim.RowList as RL
2726import Record as Record
2827import Type.Proxy (Proxy(..))
2928import Yoga.HTTP.API.Path (class PathPattern, pathPattern)
30−import Yoga.Fetch.Om.ReadOptional (readOptional)
31−
32−foreign import encodeURIComponent_ :: String -> String
33−foreign import appendPath_ :: String -> String -> String
34−foreign import substitutePathParam_ :: String -> String -> String -> String
35−
36−foreign import appendQueryString_ :: String -> String -> String
3729
3830class BuildUrl :: forall k. k -> Row Type -> Row Type -> Constraint
3931class BuildUrl segments pathParams queryParams | segments -> pathParams queryParams where
@@ -50,23 +42,20 @@ instance
5042 pattern = pathPattern segmentsProxy
5143 withBase = case baseUrl of
5244 "" -> pattern
53− base -> appendPath_ base pattern
54− withPathParams = substitutePathParamsImpl (Proxy :: _ pathParams) pathParamsRec withBase
55− withQueryParams = appendQueryParamsImpl (Proxy :: _ queryParams) queryParamsRec withPathParams
45+ base -> base <> pattern
46+ withPathParams = substitutePathParams (Proxy :: _ pathParams) pathParamsRec withBase
47+ withQueryParams = appendQueryParams (Proxy :: _ queryParams) queryParamsRec withPathParams
5648
5749class SubstitutePathParams :: Row Type -> Constraint
5850class SubstitutePathParams params where
59− substitutePathParamsImpl :: Proxy params -> Record params -> String -> String
60−
61−substitutePathParams :: forall @params. SubstitutePathParams params => Record params -> String -> String
62−substitutePathParams = substitutePathParamsImpl (Proxy :: _ params)
51+ substitutePathParams :: Proxy params -> Record params -> String -> String
6352
6453instance
6554 ( RowToList params rl
6655 , SubstitutePathParamsRL rl params
6756 ) =>
6857 SubstitutePathParams params where
69− substitutePathParamsImpl _ = substitutePathParamsRL (Proxy :: _ rl)
58+ substitutePathParams _ = substitutePathParamsRL (Proxy :: _ rl)
7059
7160class SubstitutePathParamsRL :: RowList Type -> Row Type -> Constraint
7261class SubstitutePathParamsRL rl r where
@@ -85,26 +74,24 @@ instance
8574 substitutePathParamsRL _ rec url = substitutePathParamsRL (Proxy :: _ tail) rec replaced
8675 where
8776 value = Record.get (Proxy :: _ name) rec
88− name = reflectSymbol (Proxy :: _ name)
89− replaced = substitutePathParam_ name (serializeParam value) url
77+ pattern = Pattern (":" <> reflectSymbol (Proxy :: _ name))
78+ replaced = String.replaceAll pattern (Replacement (serializeParam value)) url
9079
9180class AppendQueryParams :: Row Type -> Constraint
9281class AppendQueryParams params where
93− appendQueryParamsImpl :: Proxy params -> Record params -> String -> String
94−
95−appendQueryParams :: forall @params. AppendQueryParams params => Record params -> String -> String
96−appendQueryParams = appendQueryParamsImpl (Proxy :: _ params)
82+ appendQueryParams :: Proxy params -> Record params -> String -> String
9783
9884instance
9985 ( RowToList params rl
10086 , AppendQueryParamsRL rl params
10187 ) =>
10288 AppendQueryParams params where
103− appendQueryParamsImpl _ rec url = case pairs of
104− [] -> url
105− _ -> appendQueryString_ url (String.joinWith "&" pairs)
89+ appendQueryParams _ rec url = url <> queryString
10690 where
10791 pairs = appendQueryParamsRL (Proxy :: _ rl) rec []
92+ queryString = case pairs of
93+ [] -> ""
94+ _ -> "?" <> String.joinWith "&" pairs
10895
10996class AppendQueryParamsRL :: RowList Type -> Row Type -> Constraint
11097class AppendQueryParamsRL rl r where
@@ -113,49 +100,19 @@ class AppendQueryParamsRL rl r where
113100instance AppendQueryParamsRL RL.Nil r where
114101 appendQueryParamsRL _ _ acc = acc
115102
116−-- Maybe (Array ty): optional repeated query param — missing/empty field → no pairs
117103instance
118104 ( IsSymbol name
119105 , SerializeParam ty
120106 , AppendQueryParamsRL tail r
121− ) =>
122− AppendQueryParamsRL (RL.Cons name (Maybe (Array ty)) tail) r where
123− appendQueryParamsRL _ rec acc = appendQueryParamsRL (Proxy :: _ tail) rec acc'
124− where
125− encName = encodeURIComponent_ (reflectSymbol (Proxy :: _ name))
126− acc' = case (readOptional @name rec :: Maybe (Array ty)) of
127− Nothing -> acc
128− Just values -> acc <> map (\v -> encName <> "=" <> encodeURIComponent_ (serializeParam v)) values
129−
130−-- Maybe ty: read with undefined-awareness — missing field → skip
131−else instance
132− ( IsSymbol name
133− , SerializeParam ty
134− , AppendQueryParamsRL tail r
107+ , Row.Cons name (Maybe ty) tailRow r
135108 ) =>
136109 AppendQueryParamsRL (RL.Cons name (Maybe ty) tail) r where
137110 appendQueryParamsRL _ rec acc = appendQueryParamsRL (Proxy :: _ tail) rec acc'
138111 where
139− acc' = case (readOptional @name rec :: Maybe ty) of
112+ acc' = case Record.get (Proxy :: _ name) rec of
140113 Nothing -> acc
141− Just value -> Array.snoc acc (encodeURIComponent_ (reflectSymbol (Proxy :: _ name)) <> "=" <> encodeURIComponent_ (serializeParam value))
142−
143−-- Array ty: emit one `name=value` pair per element (repeated keys)
144−else instance
145− ( IsSymbol name
146− , SerializeParam ty
147− , AppendQueryParamsRL tail r
148− , Row.Cons name (Array ty) tailRow r
149− ) =>
150− AppendQueryParamsRL (RL.Cons name (Array ty) tail) r where
151− appendQueryParamsRL _ rec acc =
152− appendQueryParamsRL (Proxy :: _ tail) rec (acc <> pairs)
153− where
154− encName = encodeURIComponent_ (reflectSymbol (Proxy :: _ name))
155− values = Record.get (Proxy :: _ name) rec
156− pairs = map (\v -> encName <> "=" <> encodeURIComponent_ (serializeParam v)) values
114+ Just value -> Array.snoc acc (reflectSymbol (Proxy :: _ name) <> "=" <> serializeParam value)
157115
158−-- bare ty (Required query param): always present
159116else instance
160117 ( IsSymbol name
161118 , SerializeParam ty
@@ -166,7 +123,7 @@ else instance
166123 appendQueryParamsRL _ rec acc =
167124 appendQueryParamsRL (Proxy :: _ tail) rec (Array.snoc acc pair)
168125 where
169− pair = encodeURIComponent_ (reflectSymbol (Proxy :: _ name)) <> "=" <> encodeURIComponent_ (serializeParam (Record.get (Proxy :: _ name) rec))
126+ pair = reflectSymbol (Proxy :: _ name) <> "=" <> serializeParam (Record.get (Proxy :: _ name) rec)
170127
171128class SerializeParam :: Type -> Constraint
172129class SerializeParam a where
src/Yoga/Fetch/Om/ClientFn.pursnew file+142
@@ -0,0 +1,142 @@
1+module Yoga.Fetch.Om.ClientFn
2+ ( class BuildClientFn
3+ , buildClientFn
4+ , class CheckBodyIsUnit
5+ , class CheckRowEmpty
6+ , IsUnit
7+ , IsNotUnit
8+ , IsEmpty
9+ , IsNonEmpty
10+ ) where
11+
12+import Data.Unit (Unit, unit)
13+import Prim.RowList (class RowToList, RowList)
14+import Prim.RowList as RL
15+import Type.Proxy (Proxy)
16+import Unsafe.Coerce (unsafeCoerce)
17+import Yoga.Om (Om)
18+
19+data IsUnit
20+data IsNotUnit
21+data IsEmpty
22+data IsNonEmpty
23+
24+class CheckBodyIsUnit :: Type -> Type -> Constraint
25+class CheckBodyIsUnit body flag | body -> flag
26+
27+instance CheckBodyIsUnit Unit IsUnit
28+else instance CheckBodyIsUnit body IsNotUnit
29+
30+class CheckRowEmpty :: Row Type -> Type -> Constraint
31+class CheckRowEmpty row flag | row -> flag
32+
33+instance RowToList row RL.Nil => CheckRowEmpty row IsEmpty
34+else instance CheckRowEmpty row IsNonEmpty
35+
36+class BuildClientFn
37+ :: RowList Type -> Type -> Type -> Type -> Row Type -> Row Type -> Row Type -> Type -> Type -> Constraint
38+class
39+ BuildClientFn pathQueryRL headersFlag bodyFlag body pathQuery headers errorRow result fn
40+ | pathQueryRL headersFlag bodyFlag body pathQuery headers errorRow result -> fn where
41+ buildClientFn
42+ :: Proxy pathQueryRL
43+ -> Proxy headersFlag
44+ -> Proxy bodyFlag
45+ -> (Record pathQuery -> Record headers -> body -> Om {} errorRow result)
46+ -> fn
47+
48+instance
49+ BuildClientFn RL.Nil
50+ IsEmpty
51+ IsUnit
52+ Unit
53+ pq
54+ h
55+ errorRow
56+ result
57+ (Om {} errorRow result) where
58+ buildClientFn _ _ _ f = f (unsafeCoerce {}) (unsafeCoerce {}) unit
59+
60+instance
61+ BuildClientFn RL.Nil
62+ IsEmpty
63+ IsNotUnit
64+ body
65+ pq
66+ h
67+ errorRow
68+ result
69+ (body -> Om {} errorRow result) where
70+ buildClientFn _ _ _ f = \b -> f (unsafeCoerce {}) (unsafeCoerce {}) b
71+
72+instance
73+ BuildClientFn RL.Nil
74+ IsNonEmpty
75+ IsUnit
76+ Unit
77+ pq
78+ h
79+ errorRow
80+ result
81+ (Record h -> Om {} errorRow result) where
82+ buildClientFn _ _ _ f = \hdrs -> f (unsafeCoerce {}) hdrs unit
83+
84+instance
85+ BuildClientFn RL.Nil
86+ IsNonEmpty
87+ IsNotUnit
88+ body
89+ pq
90+ h
91+ errorRow
92+ result
93+ (Record h -> body -> Om {} errorRow result) where
94+ buildClientFn _ _ _ f = \hdrs b -> f (unsafeCoerce {}) hdrs b
95+
96+instance
97+ BuildClientFn (RL.Cons n t tl)
98+ IsEmpty
99+ IsUnit
100+ Unit
101+ pq
102+ h
103+ errorRow
104+ result
105+ (Record pq -> Om {} errorRow result) where
106+ buildClientFn _ _ _ f = \pqr -> f pqr (unsafeCoerce {}) unit
107+
108+instance
109+ BuildClientFn (RL.Cons n t tl)
110+ IsEmpty
111+ IsNotUnit
112+ body
113+ pq
114+ h
115+ errorRow
116+ result
117+ (Record pq -> body -> Om {} errorRow result) where
118+ buildClientFn _ _ _ f = \pqr b -> f pqr (unsafeCoerce {}) b
119+
120+instance
121+ BuildClientFn (RL.Cons n t tl)
122+ IsNonEmpty
123+ IsUnit
124+ Unit
125+ pq
126+ h
127+ errorRow
128+ result
129+ (Record pq -> Record h -> Om {} errorRow result) where
130+ buildClientFn _ _ _ f = \pqr hdrs -> f pqr hdrs unit
131+
132+instance
133+ BuildClientFn (RL.Cons n t tl)
134+ IsNonEmpty
135+ IsNotUnit
136+ body
137+ pq
138+ h
139+ errorRow
140+ result
141+ (Record pq -> Record h -> body -> Om {} errorRow result) where
142+ buildClientFn _ _ _ f = f
src/Yoga/Fetch/Om/ClientFunction.pursdeleted−157
@@ -1,157 +0,0 @@
1−module Yoga.Fetch.Om.ClientFunction
2− ( class BuildClientFn
3− , buildClientFn
4− , class CheckBodyIsUnit
5− , IsUnit
6− , IsNotUnit
7− ) where
8−
9−import Data.Unit (Unit, unit)
10−import Prim.RowList (RowList)
11−import Prim.RowList as RL
12−import Type.Proxy (Proxy)
13−import Yoga.Om (Om)
14−
15−data IsUnit
16−data IsNotUnit
17−
18−class CheckBodyIsUnit :: Type -> Type -> Constraint
19−class CheckBodyIsUnit body flag | body -> flag
20−
21−instance CheckBodyIsUnit Unit IsUnit
22−else instance CheckBodyIsUnit body IsNotUnit
23−
24−class BuildClientFn
25− :: RowList Type -> RowList Type -> Type -> Type -> Row Type -> Row Type -> Type -> Type -> Row Type -> Type -> Type -> Constraint
26−class
27− BuildClientFn pathQueryRL headersRL bodyFlag body pathQuery headers arg ctx errorRow result fn
28− | pathQueryRL -> pathQuery
29− , headersRL -> headers
30− , pathQueryRL headersRL bodyFlag body arg ctx errorRow result -> fn where
31− buildClientFn
32− :: Proxy pathQueryRL
33− -> Proxy headersRL
34− -> Proxy bodyFlag
35− -> (arg -> Record pathQuery)
36− -> (Record pathQuery -> Record headers -> body -> Om ctx errorRow result)
37− -> fn
38−
39−-- No path/query, no headers, no body
40−instance
41− BuildClientFn RL.Nil
42− RL.Nil
43− IsUnit
44− Unit
45− ()
46− ()
47− arg
48− ctx
49− errorRow
50− result
51− (Om ctx errorRow result) where
52− buildClientFn _ _ _ _ f = f {} {} unit
53−
54−-- No path/query, no headers, with body
55−instance
56− BuildClientFn RL.Nil
57− RL.Nil
58− IsNotUnit
59− body
60− ()
61− ()
62− arg
63− ctx
64− errorRow
65− result
66− (body -> Om ctx errorRow result) where
67− buildClientFn _ _ _ _ f b = f {} {} b
68−
69−-- No path/query, with headers, no body
70−instance
71− BuildClientFn RL.Nil
72− (RL.Cons n t tl)
73− IsUnit
74− Unit
75− ()
76− h
77− arg
78− ctx
79− errorRow
80− result
81− (Record h -> Om ctx errorRow result) where
82− buildClientFn _ _ _ _ f hdrs = f {} hdrs unit
83−
84−-- No path/query, with headers, with body
85−instance
86− BuildClientFn RL.Nil
87− (RL.Cons n t tl)
88− IsNotUnit
89− body
90− ()
91− h
92− arg
93− ctx
94− errorRow
95− result
96− (Record h -> body -> Om ctx errorRow result) where
97− buildClientFn _ _ _ _ f hdrs b = f {} hdrs b
98−
99−-- With path/query, no headers, no body
100−instance
101− BuildClientFn (RL.Cons n t tl)
102− RL.Nil
103− IsUnit
104− Unit
105− pq
106− ()
107− arg
108− ctx
109− errorRow
110− result
111− (arg -> Om ctx errorRow result) where
112− buildClientFn _ _ _ convert f pqr = f (convert pqr) {} unit
113−
114−-- With path/query, no headers, with body
115−instance
116− BuildClientFn (RL.Cons n t tl)
117− RL.Nil
118− IsNotUnit
119− body
120− pq
121− ()
122− arg
123− ctx
124− errorRow
125− result
126− (arg -> body -> Om ctx errorRow result) where
127− buildClientFn _ _ _ convert f pqr b = f (convert pqr) {} b
128−
129−-- With path/query, with headers, no body
130−instance
131− BuildClientFn (RL.Cons n t tl)
132− (RL.Cons hn ht htl)
133− IsUnit
134− Unit
135− pq
136− h
137− arg
138− ctx
139− errorRow
140− result
141− (arg -> Record h -> Om ctx errorRow result) where
142− buildClientFn _ _ _ convert f pqr hdrs = f (convert pqr) hdrs unit
143−
144−-- With path/query, with headers, with body
145−instance
146− BuildClientFn (RL.Cons n t tl)
147− (RL.Cons hn ht htl)
148− IsNotUnit
149− body
150− pq
151− h
152− arg
153− ctx
154− errorRow
155− result
156− (arg -> Record h -> body -> Om ctx errorRow result) where
157− buildClientFn _ _ _ convert f pqr hdrs b = f (convert pqr) hdrs b
src/Yoga/Fetch/Om/ExtractParams.purs+1−22
@@ -1,7 +1,6 @@
11module Yoga.Fetch.Om.ExtractParams
22 ( class ExtractRequestHeaders
33 , class ExtractRequestBody
4− , class ExtractBodyEncoding
54 , class FindBodyType
65 , class UnwrapEncoding
76 , class FindHeaders
@@ -10,8 +9,7 @@ module Yoga.Fetch.Om.ExtractParams
109import Data.Unit (Unit)
1110import Prim.RowList (class RowToList, RowList)
1211import Prim.RowList as RL
13−import Yoga.HTTP.API.Route.Encoding (JSON, FormData, NoBody, PlainText)
14−import Yoga.HTTP.API.Route.Handler (Request)
12+import Yoga.HTTP.API.Route.Encoding (JSON, FormData, NoBody)
1513
1614class ExtractRequestBody :: Type -> Type -> Constraint
1715class ExtractRequestBody request body | request -> body
@@ -22,21 +20,6 @@ instance
2220 , UnwrapEncoding encoding body
2321 ) =>
2422 ExtractRequestBody (Record row) body
25−else instance
26− ExtractRequestBody (Record row) body =>
27− ExtractRequestBody (Request (Record row)) body
28−
29−class ExtractBodyEncoding :: Type -> Type -> Constraint
30−class ExtractBodyEncoding request encoding | request -> encoding
31−
32−instance
33− ( RowToList row rl
34− , FindBodyType rl encoding
35− ) =>
36− ExtractBodyEncoding (Record row) encoding
37−else instance
38− ExtractBodyEncoding (Record row) encoding =>
39− ExtractBodyEncoding (Request (Record row)) encoding
4023
4124class ExtractRequestHeaders :: Type -> Row Type -> Constraint
4225class ExtractRequestHeaders request headers | request -> headers
@@ -46,9 +29,6 @@ instance
4629 , FindHeaders rl headers
4730 ) =>
4831 ExtractRequestHeaders (Record row) headers
49−else instance
50− ExtractRequestHeaders (Record row) headers =>
51− ExtractRequestHeaders (Request (Record row)) headers
5232
5333class FindBodyType :: RowList Type -> Type -> Constraint
5434class FindBodyType rl encoding | rl -> encoding
@@ -63,7 +43,6 @@ class UnwrapEncoding encoding body | encoding -> body
6343instance UnwrapEncoding (JSON ty) ty
6444instance UnwrapEncoding (FormData ty) ty
6545instance UnwrapEncoding NoBody Unit
66−instance UnwrapEncoding PlainText String
6746
6847class FindHeaders :: RowList Type -> Row Type -> Constraint
6948class FindHeaders rl headers | rl -> headers
src/Yoga/Fetch/Om/MakeRequest.jsdeleted−1
@@ -1 +0,0 @@
1−export const toUrlEncoded = (obj) => new URLSearchParams(obj).toString();
src/Yoga/Fetch/Om/MakeRequest.purs+16−44
@@ -2,22 +2,18 @@ module Yoga.Fetch.Om.MakeRequest
22 ( class MakeRequest
33 , httpMethod
44 , makeRequest
5− , class BodyEncoding
6− , encodingContentType
7− , encodeBody
5+ , class SerializeBody
6+ , serializeBody
87 ) where
98
109import Prelude
1110
1211import Data.HTTP.Method (Method(..))
13−import Data.Array as Array
1412import Data.Maybe (Maybe(..))
15−import Data.Tuple (fst)
1613import Data.Tuple.Nested ((/\))
1714import Effect.Aff (Aff)
1815import Effect.Class (liftEffect)
1916import JS.Fetch as Fetch
20−import JS.Fetch.Headers (Headers)
2117import JS.Fetch.Headers as Headers
2218import JS.Fetch.Request as Request
2319import JS.Fetch.RequestBody as Body
@@ -31,7 +27,6 @@ import JS.Fetch.Duplex as Duplex
3127import JS.Fetch.Response (Response) as FetchResponse
3228import Promise.Aff as Promise
3329import Type.Proxy (Proxy)
34−import Yoga.HTTP.API.Route.Encoding (JSON, FormData, PlainText, NoBody)
3530import Yoga.HTTP.API.Route.Method as Method
3631import Yoga.JSON (class WriteForeign, writeJSON)
3732
@@ -54,65 +49,42 @@ instance MakeRequest Method.DELETE where
5449instance MakeRequest Method.PATCH where
5550 httpMethod _ = PATCH
5651
57−instance MakeRequest Method.QUERY where
58− httpMethod _ = QUERY
59−
6052makeRequest
6153 :: forall method
6254 . MakeRequest method
6355 => Proxy method
6456 -> String
65− -> Headers
66− -> String
6757 -> Maybe String
6858 -> Aff FetchResponse.Response
69−makeRequest proxy url customHeaders bodyContentType maybeBody = do
59+makeRequest proxy url maybeBody = do
7060 request <- Request.new url options # liftEffect
7161 Promise.toAffE $ Fetch.fetch request
7262 where
7363 method = httpMethod proxy
74− customArr = Headers.toArray customHeaders
75− hasContentType = Array.any (\t -> fst t == "content-type") customArr
76− contentTypeArr = case maybeBody of
77− Nothing -> []
78− Just _ | hasContentType -> []
79− Just _ -> [ "Content-Type" /\ bodyContentType ]
80− allHeaders = Headers.fromFoldable (contentTypeArr <> customArr)
64+ headers = case maybeBody of
65+ Nothing -> Headers.empty
66+ Just _ -> Headers.fromFoldable [ "Content-Type" /\ "application/json" ]
8167 body = case maybeBody of
8268 Nothing -> Body.empty
8369 Just b -> Body.fromString b
8470 options =
8571 { method
86− , headers: allHeaders
72+ , headers
8773 , body
88− , credentials: Credentials.SameOrigin
74+ , credentials: Credentials.Include
8975 , mode: Mode.Cors
90− , referrer: Referrer.ReferrerUrl ""
76+ , referrer: Referrer.ReferrerClient
9177 , referrerPolicy: ReferrerPolicy.NoReferrer
9278 , integrity: Integrity ""
9379 , duplex: Duplex.Half
9480 , cache: Cache.Default
9581 }
9682
97−class BodyEncoding :: Type -> Type -> Constraint
98−class BodyEncoding encoding body | encoding -> body where
99− encodingContentType :: Proxy encoding -> String
100− encodeBody :: body -> Maybe String
101−
102−instance WriteForeign ty => BodyEncoding (JSON ty) ty where
103− encodingContentType _ = "application/json"
104− encodeBody b = Just (writeJSON b)
105−
106−else instance BodyEncoding PlainText String where
107− encodingContentType _ = "text/plain"
108− encodeBody = Just
109−
110−else instance BodyEncoding (FormData ty) ty where
111− encodingContentType _ = "application/x-www-form-urlencoded"
112− encodeBody b = Just (toUrlEncoded b)
113−
114−else instance BodyEncoding NoBody Unit where
115− encodingContentType _ = ""
116− encodeBody _ = Nothing
83+class SerializeBody :: Type -> Constraint
84+class SerializeBody body where
85+ serializeBody :: body -> Maybe String
11786
118−foreign import toUrlEncoded :: forall a. a -> String
87+instance SerializeBody Unit where
88+ serializeBody _ = Nothing
89+else instance WriteForeign body => SerializeBody body where
90+ serializeBody b = Just (writeJSON b)
src/Yoga/Fetch/Om/ParseResponse.purs+20−83
@@ -5,20 +5,17 @@ module Yoga.Fetch.Om.ParseResponse
55 , parseSuccessRL
66 , class ParseErrorRL
77 , parseErrorRL
8− , class ParseResponseBody
9− , parseResponseBody
108 ) where
119
1210import Prelude
1311
1412import Control.Monad.Error.Class (throwError)
15−import Data.Either (Either(..))
13+import Data.Maybe (Maybe(..))
1614import Data.Symbol (class IsSymbol)
1715import Data.Variant (Variant)
1816import Data.Variant as Variant
1917import Effect.Aff (Aff)
2018import Effect.Aff as Aff
21−import Effect.Class (liftEffect)
2219import Effect.Exception as Exception
2320import JS.Fetch.Response (Response) as FetchResponse
2421import JS.Fetch.Response as Fetch
@@ -27,24 +24,10 @@ import Prim.RowList (class RowToList, RowList)
2724import Prim.RowList as RL
2825import Promise.Aff as Promise
2926import Type.Proxy (Proxy(..))
30−import Unsafe.Coerce (unsafeCoerce)
31−import Yoga.Fetch.Om.StreamDecode (class StreamDecode, decodeStream)
3227import Yoga.HTTP.API.Route.StatusCode (class StatusCodeMap, statusCodeFor, StatusCode(..))
33−import Yoga.JSON (class ReadForeign, readJSON)
34−import Yoga.JSON.Error (withStringErrors)
35−import Yoga.Om (Om, toOm)
28+import Yoga.JSON (class ReadForeign, readJSON_)
29+import Yoga.Om (Om, fromAff)
3630import Yoga.Om.Error (Exception)
37−import Yoga.Om.Strom (Strom)
38−import Yoga.Om.Strom.WebStream as WebStream
39−
40−class ParseResponseBody (body :: Type) where
41− parseResponseBody :: String -> Either String body
42−
43−instance ParseResponseBody String where
44− parseResponseBody = Right
45−
46−else instance ReadForeign body => ParseResponseBody body where
47− parseResponseBody = withStringErrors <<< readJSON
4831
4932class ParseResponse (errorRow :: Row Type) (successRow :: Row Type) where
5033 parseResponse :: FetchResponse.Response -> Om {} errorRow (Variant successRow)
@@ -58,14 +41,16 @@ instance
5841 ParseResponse errorRow successRow where
5942 parseResponse fetchResp = do
6043 let status = Fetch.status fetchResp
44+ jsonText <- Promise.toAffE (Fetch.text fetchResp) # fromAff
6145 if status >= 200 && status < 300 then
62− parseSuccessRL (Proxy :: _ successRL) status fetchResp # toOm
63− else do
64− errorText <- Promise.toAffE (Fetch.text fetchResp) # toOm
65− parseErrorRL (Proxy :: _ errorRL) (Proxy :: _ errorRow) status errorText
46+ parseSuccessRL (Proxy :: _ successRL) status jsonText # fromAff
47+ else if status >= 400 then
48+ parseErrorRL (Proxy :: _ errorRL) (Proxy :: _ errorRow) status jsonText
49+ else
50+ throwError (Variant.inj (Proxy :: _ "exception") (Exception.error ("Unexpected HTTP status code: " <> show status)))
6651
6752class ParseSuccessRL (rl :: RowList Type) (successRow :: Row Type) | rl -> successRow where
68− parseSuccessRL :: Proxy rl -> Int -> FetchResponse.Response -> Aff (Variant successRow)
53+ parseSuccessRL :: Proxy rl -> Int -> String -> Aff (Variant successRow)
6954
7055instance ParseSuccessRL RL.Nil successRow where
7156 parseSuccessRL _ status _ =
@@ -74,53 +59,19 @@ instance ParseSuccessRL RL.Nil successRow where
7459else instance
7560 ( IsSymbol label
7661 , StatusCodeMap label
77− , StreamDecode a
78− , Row.Cons label (Strom streamContext streamError a) tailRow successRow
79− , Row.Lacks label tailRow
80− , ParseSuccessRL tailRL successRow
81− ) =>
82− ParseSuccessRL (RL.Cons label (Strom streamContext streamError a) tailRL) successRow where
83− parseSuccessRL _ actualStatus fetchResp = do
84− let StatusCode expected = statusCodeFor (Proxy :: _ label)
85− if actualStatus == expected then do
86− webStream <- liftEffect (Fetch.body fetchResp)
87− let strom = decodeStream (WebStream.fromReadableStream (unsafeCoerce webStream)) :: Strom {} () a
88− pure (Variant.inj (Proxy :: _ label) (unsafeCoerce strom))
89− else
90− parseSuccessRL (Proxy :: _ tailRL) actualStatus fetchResp
91−
92−else instance
93− ( IsSymbol label
94− , StatusCodeMap label
95− , Row.Cons label Unit tailRow successRow
96− , Row.Lacks label tailRow
97− , ParseSuccessRL tailRL successRow
98− ) =>
99− ParseSuccessRL (RL.Cons label Unit tailRL) successRow where
100− parseSuccessRL _ actualStatus fetchResp = do
101− let StatusCode expected = statusCodeFor (Proxy :: _ label)
102− if actualStatus == expected then
103− pure (Variant.inj (Proxy :: _ label) unit)
104− else
105− parseSuccessRL (Proxy :: _ tailRL) actualStatus fetchResp
106−else instance
107− ( IsSymbol label
108− , StatusCodeMap label
109− , ParseResponseBody body
62+ , ReadForeign body
11063 , Row.Cons label body tailRow successRow
11164 , Row.Lacks label tailRow
11265 , ParseSuccessRL tailRL successRow
11366 ) =>
11467 ParseSuccessRL (RL.Cons label body tailRL) successRow where
115− parseSuccessRL _ actualStatus fetchResp = do
68+ parseSuccessRL _ actualStatus jsonText = do
11669 let StatusCode expected = statusCodeFor (Proxy :: _ label)
117− if actualStatus == expected then do
118− jsonText <- liftEffect (Fetch.text fetchResp) >>= Promise.toAff
119− case parseResponseBody jsonText of
120− Left errs -> Aff.throwError (Exception.error ("Failed to parse response (status " <> show actualStatus <> "):\n" <> errs))
121− Right parsed -> pure (Variant.inj (Proxy :: _ label) parsed)
70+ if actualStatus == expected then case readJSON_ jsonText of
71+ Nothing -> Aff.throwError (Exception.error "JSON parse error")
72+ Just parsed -> pure (Variant.inj (Proxy :: _ label) parsed)
12273 else
123− parseSuccessRL (Proxy :: _ tailRL) actualStatus fetchResp
74+ parseSuccessRL (Proxy :: _ tailRL) actualStatus jsonText
12475
12576class ParseErrorRL (rl :: RowList Type) (errorRow :: Row Type) | rl -> errorRow where
12677 parseErrorRL
@@ -138,21 +89,7 @@ instance ParseErrorRL RL.Nil errorRow where
13889else instance
13990 ( IsSymbol label
14091 , StatusCodeMap label
141− , Row.Cons label Unit tailRow errorRow
142− , Row.Lacks label tailRow
143− , Row.Cons label Unit tailExc (Exception errorRow)
144− , ParseErrorRL tailRL errorRow
145− ) =>
146− ParseErrorRL (RL.Cons label Unit tailRL) errorRow where
147− parseErrorRL _ errorProxy actualStatus jsonText = do
148− let StatusCode expected = statusCodeFor (Proxy :: _ label)
149− if actualStatus == expected then throwError (Variant.inj (Proxy :: _ label) unit)
150− else parseErrorRL (Proxy :: _ tailRL) errorProxy actualStatus jsonText
151−
152−else instance
153− ( IsSymbol label
154− , StatusCodeMap label
155− , ParseResponseBody body
92+ , ReadForeign body
15693 , Row.Cons label body tailRow errorRow
15794 , Row.Lacks label tailRow
15895 , Row.Cons label body tailExc (Exception errorRow)
@@ -161,8 +98,8 @@ else instance
16198 ParseErrorRL (RL.Cons label body tailRL) errorRow where
16299 parseErrorRL _ errorProxy actualStatus jsonText = do
163100 let StatusCode expected = statusCodeFor (Proxy :: _ label)
164− if actualStatus == expected then case parseResponseBody jsonText of
165− Left errs -> throwError (Variant.inj (Proxy :: _ "exception") (Exception.error ("Failed to parse error response (status " <> show actualStatus <> "):\n" <> errs)))
166− Right parsed -> throwError (Variant.inj (Proxy :: _ label) parsed)
101+ if actualStatus == expected then case readJSON_ jsonText of
102+ Nothing -> throwError (Variant.inj (Proxy :: _ "exception") (Exception.error "JSON parse error"))
103+ Just parsed -> throwError (Variant.inj (Proxy :: _ label) parsed)
167104 else
168105 parseErrorRL (Proxy :: _ tailRL) errorProxy actualStatus jsonText
src/Yoga/Fetch/Om/ReadOptional.jsdeleted−18
@@ -1,18 +0,0 @@
1−import * as Maybe from "../Data.Maybe/index.js";
2−
3−export function readOptionalImpl(key) {
4− return function (obj) {
5− const val = obj[key];
6− if (val === undefined || val instanceof Maybe.Nothing) {
7− return Maybe.Nothing.value;
8− }
9− if (val instanceof Maybe.Just) return val;
10− return Maybe.Just.create(val);
11− };
12−}
13−
14−export function readRequiredField(key) {
15− return function (obj) {
16− return obj[key];
17− };
18−}
src/Yoga/Fetch/Om/ReadOptional.pursdeleted−56
@@ -1,56 +0,0 @@
1−module Yoga.Fetch.Om.ReadOptional
2− ( readOptional
3− , class ReadPartialQuery
4− , readPartialQuery
5− ) where
6−
7−import Data.Maybe (Maybe)
8−import Data.Symbol (class IsSymbol, reflectSymbol)
9−import Prim.Row as Row
10−import Prim.RowList (RowList)
11−import Prim.RowList as RL
12−import Record as Record
13−import Type.Proxy (Proxy(..))
14−
15−foreign import readOptionalImpl :: forall a r. String -> Record r -> Maybe a
16−
17−-- | Accept explicit `Maybe` fields as well as undefined-aware partial records.
18−readOptional :: forall @name ty r. IsSymbol name => Record r -> Maybe ty
19−readOptional rec = readOptionalImpl (reflectSymbol (Proxy :: _ name)) rec
20−
21−-- | Read query params from a potentially-partial record.
22−-- | Walks the query params RowList:
23−-- | Maybe ty → read with undefined-awareness (present → Just, absent → Nothing)
24−-- | bare ty → read directly (required, always present)
25−class ReadPartialQuery (rl :: RowList Type) (queryParams :: Row Type) | rl -> queryParams where
26− readPartialQuery :: forall r. Record r -> Record queryParams
27−
28−instance ReadPartialQuery RL.Nil () where
29− readPartialQuery _ = {}
30−
31−-- Maybe ty: optional field, may be undefined at runtime
32−instance
33− ( IsSymbol name
34− , ReadPartialQuery tail tailQuery
35− , Row.Cons name (Maybe ty) tailQuery queryParams
36− , Row.Lacks name tailQuery
37− ) =>
38− ReadPartialQuery (RL.Cons name (Maybe ty) tail) queryParams where
39− readPartialQuery rec = Record.insert (Proxy :: _ name) (readOptional @name rec) rest
40− where
41− rest = readPartialQuery @tail rec
42−
43−-- bare ty: required field (from Required query params), always present
44−else instance
45− ( IsSymbol name
46− , ReadPartialQuery tail tailQuery
47− , Row.Cons name ty tailQuery queryParams
48− , Row.Lacks name tailQuery
49− ) =>
50− ReadPartialQuery (RL.Cons name ty tail) queryParams where
51− readPartialQuery rec = Record.insert (Proxy :: _ name) val rest
52− where
53− val = readRequiredField (reflectSymbol (Proxy :: _ name)) rec
54− rest = readPartialQuery @tail rec
55−
56−foreign import readRequiredField :: forall a r. String -> Record r -> a
src/Yoga/Fetch/Om/Simple.purs+72−63
@@ -22,24 +22,27 @@ module Yoga.Fetch.Om.Simple
2222import Prelude
2323
2424import Data.HTTP.Method (Method(..))
25−import Data.Array as Array
26−import Data.Either (Either(..))
2725import Data.Maybe (Maybe(..))
28−import Data.Tuple (fst)
2926import Data.Tuple.Nested ((/\))
3027import Effect.Class (liftEffect)
3128import JS.Fetch as Fetch
3229import JS.Fetch.Duplex as Duplex
3330import JS.Fetch.Headers (Headers)
3431import JS.Fetch.Headers as Headers
32+import JS.Fetch.Integrity (Integrity(..))
33+import JS.Fetch.Referrer as Referrer
34+import JS.Fetch.ReferrerPolicy as ReferrerPolicy
3535import JS.Fetch.Request as Request
3636import JS.Fetch.RequestBody as Body
37+import JS.Fetch.RequestCache as Cache
38+import JS.Fetch.RequestCredentials as Credentials
39+import JS.Fetch.RequestMode as Mode
3740import JS.Fetch.Response as Resp
3841import Promise.Aff as Promise
3942import Type.Row.Homogeneous (class Homogeneous)
40−import Yoga.JSON (class ReadForeign, class WriteForeign, readJSON, writeJSON)
41−import Yoga.JSON.Error (withStringErrors)
42−import Yoga.Om (Om, toOm, throw)
43+-- PlainText removed, using local phantom type
44+import Yoga.JSON (class ReadForeign, class WriteForeign, readJSON_, writeJSON)
45+import Yoga.Om (Om, fromAff, throw)
4346
4447type FetchError = { status :: Int, body :: String }
4548
@@ -47,13 +50,15 @@ type FetchResponse a = { headers :: Headers, body :: a }
4750
4851class DecodeResponse :: forall k. k -> Type -> Constraint
4952class DecodeResponse a result | a -> result where
50− decodeResponse :: String -> Either String result
53+ decodeResponse :: String -> Maybe result
5154
52−instance DecodeResponse String String where
53− decodeResponse = Right
55+data PlainTextResponse
56+
57+instance DecodeResponse PlainTextResponse String where
58+ decodeResponse = Just
5459
5560else instance ReadForeign a => DecodeResponse a a where
56− decodeResponse = withStringErrors <<< readJSON
61+ decodeResponse = readJSON_
5762
5863simpleFetch
5964 :: forall @a result headers ctx err
@@ -65,27 +70,25 @@ simpleFetch
6570 -> Maybe String
6671 -> Om ctx (fetchError :: FetchError | err) (FetchResponse result)
6772simpleFetch method headers url maybeBody = do
68− resp <- doFetch # toOm
69− respText <- Promise.toAffE (Resp.text resp) # toOm
73+ resp <- doFetch # fromAff
74+ respText <- Promise.toAffE (Resp.text resp) # fromAff
7075 let status = Resp.status resp
7176 let respHeaders = Resp.headers resp
7277 if status >= 200 && status < 300 then
7378 case decodeResponse @a respText of
74− Left errs -> throw { fetchError: { status, body: "Failed to parse response:\n" <> errs <> "\nBody: " <> respText } }
75− Right body -> pure { headers: respHeaders, body }
79+ Nothing -> throw { fetchError: { status, body: respText } }
80+ Just body -> pure { headers: respHeaders, body }
7681 else
7782 throw { fetchError: { status, body: respText } }
7883 where
7984 doFetch = do
8085 request <- Request.new url options # liftEffect
8186 Promise.toAffE $ Fetch.fetch request
82− customArr = Headers.toArray (Headers.fromRecord headers)
83− hasContentType = Array.any (\t -> fst t == "content-type") customArr
84− contentTypeArr = case maybeBody of
85− Nothing -> []
86− Just _ | hasContentType -> []
87− Just _ -> [ "Content-Type" /\ "application/json" ]
88− allHeaders = Headers.fromFoldable (contentTypeArr <> customArr)
87+ contentTypeHeaders = case maybeBody of
88+ Nothing -> Headers.empty
89+ Just _ -> Headers.fromFoldable [ "Content-Type" /\ "application/json" ]
90+ allHeaders = Headers.fromFoldable
91+ (Headers.toArray contentTypeHeaders <> Headers.toArray (Headers.fromRecord headers))
8992 reqBody = case maybeBody of
9093 Nothing -> Body.empty
9194 Just b -> Body.fromString b
@@ -93,145 +96,151 @@ simpleFetch method headers url maybeBody = do
9396 { method
9497 , headers: allHeaders
9598 , body: reqBody
99+ , credentials: Credentials.Include
100+ , mode: Mode.Cors
101+ , referrer: Referrer.ReferrerClient
102+ , referrerPolicy: ReferrerPolicy.NoReferrer
103+ , integrity: Integrity ""
96104 , duplex: Duplex.Half
105+ , cache: Cache.Default
97106 }
98107
99108get
100109 :: forall @a result headers ctx err
101110 . DecodeResponse a result
102111 => Homogeneous headers String
103− => String
104− -> Record headers
112+ => Record headers
113+ -> String
105114 -> Om ctx (fetchError :: FetchError | err) result
106−get url headers = _.body <$> simpleFetch @a GET headers url Nothing
115+get headers url = _.body <$> simpleFetch @a GET headers url Nothing
107116
108117getWithHeaders
109118 :: forall @a result headers ctx err
110119 . DecodeResponse a result
111120 => Homogeneous headers String
112− => String
113− -> Record headers
121+ => Record headers
122+ -> String
114123 -> Om ctx (fetchError :: FetchError | err) (FetchResponse result)
115−getWithHeaders url headers = simpleFetch @a GET headers url Nothing
124+getWithHeaders headers url = simpleFetch @a GET headers url Nothing
116125
117126delete
118127 :: forall @a result headers ctx err
119128 . DecodeResponse a result
120129 => Homogeneous headers String
121− => String
122− -> Record headers
130+ => Record headers
131+ -> String
123132 -> Om ctx (fetchError :: FetchError | err) result
124−delete url headers = _.body <$> simpleFetch @a DELETE headers url Nothing
133+delete headers url = _.body <$> simpleFetch @a DELETE headers url Nothing
125134
126135deleteWithHeaders
127136 :: forall @a result headers ctx err
128137 . DecodeResponse a result
129138 => Homogeneous headers String
130− => String
131− -> Record headers
139+ => Record headers
140+ -> String
132141 -> Om ctx (fetchError :: FetchError | err) (FetchResponse result)
133−deleteWithHeaders url headers = simpleFetch @a DELETE headers url Nothing
142+deleteWithHeaders headers url = simpleFetch @a DELETE headers url Nothing
134143
135144delete_
136145 :: forall headers ctx err
137146 . Homogeneous headers String
138− => String
139− -> Record headers
147+ => Record headers
148+ -> String
140149 -> Om ctx (fetchError :: FetchError | err) Unit
141−delete_ url headers = void $ simpleFetch @String DELETE headers url Nothing
150+delete_ headers url = void $ simpleFetch @PlainTextResponse DELETE headers url Nothing
142151
143152post
144153 :: forall @a result headers body ctx err
145154 . DecodeResponse a result
146155 => Homogeneous headers String
147156 => WriteForeign body
148− => String
149− -> Record headers
157+ => Record headers
158+ -> String
150159 -> body
151160 -> Om ctx (fetchError :: FetchError | err) result
152−post url headers body = _.body <$> simpleFetch @a POST headers url (Just (writeJSON body))
161+post headers url body = _.body <$> simpleFetch @a POST headers url (Just (writeJSON body))
153162
154163postWithHeaders
155164 :: forall @a result headers body ctx err
156165 . DecodeResponse a result
157166 => Homogeneous headers String
158167 => WriteForeign body
159− => String
160− -> Record headers
168+ => Record headers
169+ -> String
161170 -> body
162171 -> Om ctx (fetchError :: FetchError | err) (FetchResponse result)
163−postWithHeaders url headers body = simpleFetch @a POST headers url (Just (writeJSON body))
172+postWithHeaders headers url body = simpleFetch @a POST headers url (Just (writeJSON body))
164173
165174post_
166175 :: forall headers body ctx err
167176 . Homogeneous headers String
168177 => WriteForeign body
169− => String
170− -> Record headers
178+ => Record headers
179+ -> String
171180 -> body
172181 -> Om ctx (fetchError :: FetchError | err) Unit
173−post_ url headers body = void $ simpleFetch @String POST headers url (Just (writeJSON body))
182+post_ headers url body = void $ simpleFetch @PlainTextResponse POST headers url (Just (writeJSON body))
174183
175184put
176185 :: forall @a result headers body ctx err
177186 . DecodeResponse a result
178187 => Homogeneous headers String
179188 => WriteForeign body
180− => String
181− -> Record headers
189+ => Record headers
190+ -> String
182191 -> body
183192 -> Om ctx (fetchError :: FetchError | err) result
184−put url headers body = _.body <$> simpleFetch @a PUT headers url (Just (writeJSON body))
193+put headers url body = _.body <$> simpleFetch @a PUT headers url (Just (writeJSON body))
185194
186195putWithHeaders
187196 :: forall @a result headers body ctx err
188197 . DecodeResponse a result
189198 => Homogeneous headers String
190199 => WriteForeign body
191− => String
192− -> Record headers
200+ => Record headers
201+ -> String
193202 -> body
194203 -> Om ctx (fetchError :: FetchError | err) (FetchResponse result)
195−putWithHeaders url headers body = simpleFetch @a PUT headers url (Just (writeJSON body))
204+putWithHeaders headers url body = simpleFetch @a PUT headers url (Just (writeJSON body))
196205
197206put_
198207 :: forall headers body ctx err
199208 . Homogeneous headers String
200209 => WriteForeign body
201− => String
202− -> Record headers
210+ => Record headers
211+ -> String
203212 -> body
204213 -> Om ctx (fetchError :: FetchError | err) Unit
205−put_ url headers body = void $ simpleFetch @String PUT headers url (Just (writeJSON body))
214+put_ headers url body = void $ simpleFetch @PlainTextResponse PUT headers url (Just (writeJSON body))
206215
207216patch
208217 :: forall @a result headers body ctx err
209218 . DecodeResponse a result
210219 => Homogeneous headers String
211220 => WriteForeign body
212− => String
213− -> Record headers
221+ => Record headers
222+ -> String
214223 -> body
215224 -> Om ctx (fetchError :: FetchError | err) result
216−patch url headers body = _.body <$> simpleFetch @a PATCH headers url (Just (writeJSON body))
225+patch headers url body = _.body <$> simpleFetch @a PATCH headers url (Just (writeJSON body))
217226
218227patchWithHeaders
219228 :: forall @a result headers body ctx err
220229 . DecodeResponse a result
221230 => Homogeneous headers String
222231 => WriteForeign body
223− => String
224− -> Record headers
232+ => Record headers
233+ -> String
225234 -> body
226235 -> Om ctx (fetchError :: FetchError | err) (FetchResponse result)
227−patchWithHeaders url headers body = simpleFetch @a PATCH headers url (Just (writeJSON body))
236+patchWithHeaders headers url body = simpleFetch @a PATCH headers url (Just (writeJSON body))
228237
229238patch_
230239 :: forall headers body ctx err
231240 . Homogeneous headers String
232241 => WriteForeign body
233− => String
234− -> Record headers
242+ => Record headers
243+ -> String
235244 -> body
236245 -> Om ctx (fetchError :: FetchError | err) Unit
237−patch_ url headers body = void $ simpleFetch @String PATCH headers url (Just (writeJSON body))
246+patch_ headers url body = void $ simpleFetch @PlainTextResponse PATCH headers url (Just (writeJSON body))
src/Yoga/Fetch/Om/SplitResponses.purs+2−24
@@ -1,8 +1,6 @@
11module Yoga.Fetch.Om.SplitResponses
22 ( class IsSuccessStatus
3− , class ExtractBodyRL
43 , class ExtractBody
5− , class ClientResponseBody
64 , class SplitResponses
75 , class SplitResponsesRL
86 , class DispatchResponse
@@ -12,10 +10,7 @@ import Prim.Boolean (True, False)
1210import Prim.Row as Row
1311import Prim.RowList (RowList)
1412import Prim.RowList as RL
15−import Data.Unit (Unit)
1613import Yoga.HTTP.API.Route (Response)
17−import Yoga.HTTP.API.Route.Encoding (PlainText, Streaming)
18−import Yoga.Om.Strom (Strom)
1914
2015class IsSuccessStatus (label :: Symbol) (isSuccess :: Boolean) | label -> isSuccess
2116
@@ -31,29 +26,12 @@ else instance IsSuccessStatus "alreadyReported" True
3126else instance IsSuccessStatus "imUsed" True
3227else instance IsSuccessStatus label False
3328
34−-- Traverse a RowList to find the "body" field; fall back to Unit if absent.
35−class ExtractBodyRL (rl :: RowList Type) (body :: Type) | rl -> body
36−
37−instance ExtractBodyRL RL.Nil Unit
38−
39−instance ExtractBodyRL (RL.Cons "body" body tail) body
40−
41−else instance ExtractBodyRL tail body => ExtractBodyRL (RL.Cons label ty tail) body
42−
43−class ClientResponseBody (encoded :: Type) (decoded :: Type) | encoded -> decoded
44−
45−instance ClientResponseBody PlainText String
46−else instance ClientResponseBody (Streaming a) (Strom {} () a)
47−else instance ClientResponseBody body body
48−
4929class ExtractBody (responseType :: Type) (bodyType :: Type) | responseType -> bodyType
5030
51−instance ClientResponseBody encoded body => ExtractBody (Response headers encoded) body
31+instance ExtractBody (Response headers body) body
5232
5333else instance
54− ( RL.RowToList row rl
55− , ExtractBodyRL rl encoded
56− , ClientResponseBody encoded body
34+ ( Row.Cons "body" body rest row
5735 ) =>
5836 ExtractBody (Record row) body
5937
src/Yoga/Fetch/Om/StreamDecode.jsdeleted−12
@@ -1,12 +0,0 @@
1−export const newUtf8Decoder = () => new TextDecoder();
2−
3−export const decodeUtf8Chunks = (decoder) => (chunks) => () => {
4− const decoded = [];
5− for (const bytes of chunks) {
6− const text = decoder.decode(bytes, { stream: true });
7− if (text !== "") decoded.push(text);
8− }
9− return decoded;
10−};
11−
12−export const flushUtf8Decoder = (decoder) => () => decoder.decode();
src/Yoga/Fetch/Om/StreamDecode.pursdeleted−61
@@ -1,61 +0,0 @@
1−module Yoga.Fetch.Om.StreamDecode
2− ( class StreamDecode
3− , decodeStream
4− ) where
5−
6−import Prelude
7−
8−import Control.Monad.Rec.Class (Step(..))
9−import Data.Array as Array
10−import Data.ArrayBuffer.Types (Uint8Array)
11−import Data.Maybe (Maybe(..))
12−import Data.Tuple.Nested ((/\))
13−import Effect (Effect)
14−import Effect.Class (liftEffect)
15−import Yoga.Om (Om)
16−import Yoga.Om.Strom (Strom)
17−import Yoga.Om.Strom as Strom
18−
19−class StreamDecode a where
20− decodeStream :: Strom {} () Uint8Array -> Strom {} () a
21−
22−instance StreamDecode Uint8Array where
23− decodeStream = identity
24−
25−else instance StreamDecode String where
26− decodeStream stream =
27− Strom.fromOm (liftEffect newUtf8Decoder) >>= \decoder ->
28− decodeUtf8Stream decoder stream
29−
30−data Utf8Decoder
31−
32−foreign import newUtf8Decoder :: Effect Utf8Decoder
33−
34−foreign import decodeUtf8Chunks :: Utf8Decoder -> Array Uint8Array -> Effect (Array String)
35−
36−foreign import flushUtf8Decoder :: Utf8Decoder -> Effect String
37−
38−decodeUtf8Stream :: Utf8Decoder -> Strom {} () Uint8Array -> Strom {} () String
39−decodeUtf8Stream decoder stream = Strom.mkStrom do
40− step <- Strom.runStrom stream
41− case step of
42− Done maybeChunk -> do
43− decoded <- decodeChunk decoder maybeChunk
44− trailing <- liftEffect $ flushUtf8Decoder decoder
45− let
46− finalChunk =
47− if trailing == "" then decoded
48− else Array.snoc decoded trailing
49− pure $ Done (nonEmpty finalChunk)
50− Loop (maybeChunk /\ next) -> do
51− decoded <- decodeChunk decoder maybeChunk
52− pure $ Loop (nonEmpty decoded /\ decodeUtf8Stream decoder next)
53−
54−decodeChunk :: Utf8Decoder -> Maybe (Array Uint8Array) -> Om {} () (Array String)
55−decodeChunk _ Nothing = pure []
56−decodeChunk decoder (Just chunk) = liftEffect $ decodeUtf8Chunks decoder chunk
57−
58−nonEmpty :: forall a. Array a -> Maybe (Array a)
59−nonEmpty values
60− | Array.null values = Nothing
61− | otherwise = Just values
test-compile-fail/cases/ClientBogusSignature.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Test.CompileFail.ClientBogusSignature where
2−
3−import Yoga.Fetch.Om (GET, Route, type (/), type (:), client)
4−
5−type GetUserRoute = Route GET ("users" / "id" : Int) {} (ok :: { body :: { id :: Int, name :: String } })
6−type TestAPI = { getUser :: GetUserRoute }
7−
8−wrong :: { getUser :: String -> Int }
9−wrong = client @TestAPI "http://localhost:3000"
test-compile-fail/cases/ClientExtraField.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Test.CompileFail.ClientExtraField where
2−
3−import Yoga.Fetch.Om (GET, Route, type (/), type (:), client)
4−import Yoga.Om (Om)
5−
6−type GetUserRoute = Route GET ("users" / "id" : Int) {} (ok :: { body :: { id :: Int, name :: String } })
7−type TestAPI = { getUser :: GetUserRoute }
8−
9−api = client @TestAPI "http://localhost:3000"
10−
11−wrong :: forall ctx err. Om ctx err { id :: Int, name :: String }
12−wrong = api.getUser { id: 42, extra: "oops" }
test-compile-fail/cases/ClientMissingField.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Test.CompileFail.ClientMissingField where
2−
3−import Yoga.Fetch.Om (GET, Route, type (/), type (:), client)
4−import Yoga.Om (Om)
5−
6−type GetUserRoute = Route GET ("users" / "id" : Int) {} (ok :: { body :: { id :: Int, name :: String } })
7−type TestAPI = { getUser :: GetUserRoute }
8−
9−api = client @TestAPI "http://localhost:3000"
10−
11−wrong :: forall ctx err. Om ctx err { id :: Int, name :: String }
12−wrong = api.getUser {}
test-compile-fail/cases/ClientNoArgsPassedArg.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Test.CompileFail.ClientNoArgsPassedArg where
2−
3−import Yoga.Fetch.Om (GET, Route, client)
4−import Yoga.Om (Om)
5−
6−type HealthRoute = Route GET "health" {} (ok :: { body :: String })
7−type TestAPI = { health :: HealthRoute }
8−
9−api = client @TestAPI "http://localhost:3000"
10−
11−wrong :: forall ctx err. Om ctx err String
12−wrong = api.health "should not accept this"
test-compile-fail/cases/ClientWrongFieldName.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Test.CompileFail.ClientWrongFieldName where
2−
3−import Yoga.Fetch.Om (GET, Route, type (/), type (:), client)
4−import Yoga.Om (Om)
5−
6−type GetUserRoute = Route GET ("users" / "id" : Int) {} (ok :: { body :: { id :: Int, name :: String } })
7−type TestAPI = { getUser :: GetUserRoute }
8−
9−api = client @TestAPI "http://localhost:3000"
10−
11−wrong :: forall ctx err. Om ctx err { id :: Int, name :: String }
12−wrong = api.getUser { userId: 42 }
test-compile-fail/cases/ClientWrongFieldType.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Test.CompileFail.ClientWrongFieldType where
2−
3−import Yoga.Fetch.Om (GET, Route, type (/), type (:), client)
4−import Yoga.Om (Om)
5−
6−type GetUserRoute = Route GET ("users" / "id" : Int) {} (ok :: { body :: { id :: Int, name :: String } })
7−type TestAPI = { getUser :: GetUserRoute }
8−
9−api = client @TestAPI "http://localhost:3000"
10−
11−wrong :: forall ctx err. Om ctx err { id :: Int, name :: String }
12−wrong = api.getUser { id: "not-an-int" }
test-compile-fail/run.shdeleted−26
@@ -1,26 +0,0 @@
1−#!/usr/bin/env bash
2−set -euo pipefail
3−
4−# Compile-fail tests for client derivation type safety.
5−# Each .purs file in cases/ must FAIL to compile.
6−
7−SOURCES=$(bunx spago sources 2>/dev/null | grep -v 'test/')
8−OUTPUT_DIR="output-compile-fail"
9−CASES_DIR="test-compile-fail/cases"
10−PASS=0
11−FAIL=0
12−
13−for f in "$CASES_DIR"/*.purs; do
14− name=$(basename "$f" .purs)
15− if bunx purs compile --output "$OUTPUT_DIR" $SOURCES "$f" >/dev/null 2>&1; then
16− echo "FAIL: $name compiled but should not have"
17− FAIL=$((FAIL + 1))
18− else
19− echo " ok: $name correctly rejected"
20− PASS=$((PASS + 1))
21− fi
22−done
23−
24−echo ""
25−echo "$PASS passed, $FAIL failed"
26−[ "$FAIL" -eq 0 ]
test/BodylessResponse.Example.pursdeleted−27
@@ -1,27 +0,0 @@
1−-- Compile-time test: bodyless responses (e.g. 304, 401) can use {} without
2−-- wrapping in { body :: {} }.
3−module BodylessResponse.Example where
4−
5−import Prelude
6−
7−import Yoga.Fetch.Om (GET, Route, type (/), client)
8−import Yoga.Om (Om)
9−
10−type Resource = { id :: Int, name :: String }
11−
12−type ResourceAPI =
13− { getResource ::
14− Route GET
15− ("resources" / "id")
16− {}
17− ( ok :: { body :: Resource }
18− , notModified :: {}
19− , unauthorized :: {}
20− )
21− }
22−
23−-- This must typecheck: the derived client exposes notModified/unauthorized as Unit errors.
24−api
25− :: forall ctx err
26− . { getResource :: Om (Record ctx) (notModified :: Unit, unauthorized :: Unit | err) Resource }
27−api = client @ResourceAPI "https://api.example.com"
test/BodylessResponse.Spec.pursdeleted−125
@@ -1,125 +0,0 @@
1−module BodylessResponse.Spec where
2−
3−import Prelude
4−
5−import Effect.Ref (Ref)
6−import Effect.Ref as Ref
7−import Effect.Aff (Aff, bracket)
8−import Effect.Aff.Class (liftAff)
9−import Effect.Class (liftEffect)
10−import Foreign (unsafeToForeign)
11−import Test.Spec (Spec, around, describe, it)
12−import Test.Spec.Assertions (shouldEqual)
13−import Yoga.Fastify.Fastify as F
14−import Yoga.Fastify.Fastify (Port(..), Host(..), RouteURL(..), StatusCode(..))
15−import Yoga.Fastify.Om (createOmFastify, deleteOm, getOm)
16−import Yoga.Fetch.Om (DELETE, GET, Route, type (/), type (:), client)
17−import Yoga.Om (runOm)
18−
19−type Resource = { id :: Int, name :: String }
20−
21−type ResourceAPI =
22− { getResource ::
23− Route GET
24− ("bodyless-test" / "resource")
25− {}
26− ( ok :: { body :: Resource }
27− , notModified :: {}
28− , unauthorized :: {}
29− )
30− , deleteUser ::
31− Route DELETE
32− ("bodyless-test" / "users" / "id" : Int)
33− {}
34− ( noContent :: {}
35− , notFound :: { body :: { error :: String } }
36− )
37− }
38−
39−api = client @ResourceAPI "http://localhost:44932"
40−
41−spec :: Spec Unit
42−spec = around withServer $ describe "bodyless responses (notModified / unauthorized)" do
43− it "304 Not Modified triggers the notModified handler" \serverMode -> do
44− liftEffect $ Ref.write "notModified" serverMode
45− triggered <- liftEffect $ Ref.new false
46− runOm {}
47− { exception: \_ -> pure unit
48− , notModified: \_ -> liftEffect $ Ref.write true triggered
49− , unauthorized: \_ -> pure unit
50− }
51− (void api.getResource)
52− result <- liftEffect $ Ref.read triggered
53− liftAff $ result `shouldEqual` true
54−
55− it "401 Unauthorized triggers the unauthorized handler" \serverMode -> do
56− liftEffect $ Ref.write "unauthorized" serverMode
57− triggered <- liftEffect $ Ref.new false
58− runOm {}
59− { exception: \_ -> pure unit
60− , notModified: \_ -> pure unit
61− , unauthorized: \_ -> liftEffect $ Ref.write true triggered
62− }
63− (void api.getResource)
64− result <- liftEffect $ Ref.read triggered
65− liftAff $ result `shouldEqual` true
66−
67− it "200 OK returns the resource body" \serverMode -> do
68− liftEffect $ Ref.write "ok" serverMode
69− resource <- runOm {}
70− { exception: \_ -> pure { id: -1, name: "" }
71− , notModified: \_ -> pure { id: -1, name: "" }
72− , unauthorized: \_ -> pure { id: -1, name: "" }
73− }
74− api.getResource
75− liftAff $ resource `shouldEqual` { id: 1, name: "test" }
76−
77− it "204 No Content returns Unit for noContent shorthand" \serverMode -> do
78− liftEffect $ Ref.write "deleted" serverMode
79− result <- runOm {}
80− { exception: \_ -> pure false
81− , notFound: \_ -> pure false
82− }
83− (api.deleteUser { id: 1 } $> true)
84− liftAff $ result `shouldEqual` true
85−
86−withServer :: forall a. (Ref String -> Aff a) -> Aff a
87−withServer test = bracket acquire release (\{ serverMode } -> test serverMode)
88− where
89− acquire = do
90− serverMode <- liftEffect $ Ref.new "ok"
91− fastify <- liftEffect do
92− f <- F.fastify {}
93− omApp <- createOmFastify {} f
94− getOm (RouteURL "/bodyless-test/resource") (handler serverMode) omApp
95− deleteOm (RouteURL "/bodyless-test/users/:id") (deleteHandler serverMode) omApp
96− pure f
97− void $ F.listen { port: Port 44932, host: Host "0.0.0.0" } fastify
98− pure { fastify, serverMode }
99−
100− release { fastify } = F.close fastify
101−
102− handler serverMode reply = do
103− mode <- liftEffect $ Ref.read serverMode
104− case mode of
105− "notModified" -> do
106− void $ F.status (StatusCode 304) reply # liftEffect
107− F.send (unsafeToForeign "") reply # liftAff
108− "unauthorized" -> do
109− void $ F.status (StatusCode 401) reply # liftEffect
110− F.send (unsafeToForeign "") reply # liftAff
111− _ -> do
112− void $ F.status (StatusCode 200) reply # liftEffect
113− void $ F.header "content-type" "application/json" reply # liftEffect
114− F.sendJson (unsafeToForeign { id: 1, name: "test" }) reply # liftAff
115−
116− deleteHandler serverMode reply = do
117− mode <- liftEffect $ Ref.read serverMode
118− case mode of
119− "deleted" -> do
120− void $ F.status (StatusCode 204) reply # liftEffect
121− F.send (unsafeToForeign "") reply # liftAff
122− _ -> do
123− void $ F.status (StatusCode 404) reply # liftEffect
124− void $ F.header "content-type" "application/json" reply # liftEffect
125− F.sendJson (unsafeToForeign { error: "Missing user" }) reply # liftAff
test/BuildUrl.Spec.purs+100−154
@@ -3,165 +3,111 @@ module BuildUrl.Spec where
33import Prelude
44
55import Data.Maybe (Maybe(..))
6−import Test.Spec (Spec, describe, it)
7−import Test.Spec.Assertions (shouldEqual)
6+import Effect (Effect)
7+import Effect.Aff (Aff)
88import Type.Proxy (Proxy(..))
9−import Unsafe.Coerce (unsafeCoerce)
109import Yoga.Fetch.Om.BuildUrl (buildUrl, substitutePathParams, appendQueryParams)
1110import Yoga.HTTP.API.Path (Path, type (/), type (:))
11+import ViTest (ViTest, describe, test)
12+import ViTest.Expect (expectToBe)
13+
14+expectToEqual :: forall a. Eq a => a -> a -> Aff Unit
15+expectToEqual expected actual = expectToBe true (expected == actual)
1216
1317--------------------------------------------------------------------------------
1418-- SubstitutePathParams Tests
1519--------------------------------------------------------------------------------
1620
17−spec :: Spec Unit
18−spec = do
19− describe "substitutePathParams" do
20− it "substitutes single path param" do
21− let result = substitutePathParams @(id :: Int) { id: 42 } "/users/:id"
22− result `shouldEqual` "/users/42"
23−
24− it "substitutes multiple path params" do
25− let
26− result = substitutePathParams @(userId :: Int, postId :: Int)
27− { userId: 1, postId: 99 }
28− "/users/:userId/posts/:postId"
29− result `shouldEqual` "/users/1/posts/99"
30−
31− it "handles String params" do
32− let
33− result = substitutePathParams @(slug :: String)
34− { slug: "hello-world" }
35− "/posts/:slug"
36− result `shouldEqual` "/posts/hello-world"
37− it "URL-encodes reserved characters in path params" do
38− let
39− result = substitutePathParams @(slug :: String)
40− { slug: "a/b c?d#e" }
41− "/users/:slug"
42− result `shouldEqual` "/users/a%2Fb%20c%3Fd%23e"
43−
44− it "distinguishes path param names with shared prefixes" do
45− let
46− result = substitutePathParams @(id :: Int, id2 :: Int)
47− { id: 1, id2: 2 }
48− "/pairs/:id/:id2"
49− result `shouldEqual` "/pairs/1/2"
50−
51− it "handles empty params" do
52− let result = substitutePathParams @() {} "/users"
53− result `shouldEqual` "/users"
54−
55− describe "appendQueryParams" do
56− it "appends single query param" do
57− let result = appendQueryParams @(limit :: Int) { limit: 10 } "/users"
58− result `shouldEqual` "/users?limit=10"
59−
60− it "appends multiple query params" do
61− let
62− result = appendQueryParams @(limit :: Int, offset :: Int)
63− { limit: 10, offset: 20 }
64− "/users"
65− result `shouldEqual` "/users?limit=10&offset=20"
66−
67− it "handles optional params - provided via partial record" do
68− let
69− result = appendQueryParams @(limit :: Maybe Int)
70− (unsafeCoerce { limit: 10 } :: Record (limit :: Maybe Int))
71− "/users"
72− result `shouldEqual` "/users?limit=10"
73−
74− it "serializes a present explicit Maybe query param" do
75− let result = appendQueryParams @(id :: Maybe Int) { id: Just 42 } "/users"
76− result `shouldEqual` "/users?id=42"
77−
78− it "omits an explicit Nothing query param" do
79− let result = appendQueryParams @(id :: Maybe Int) { id: Nothing } "/users"
80− result `shouldEqual` "/users"
81−
82− it "handles optional params - omitted via partial record" do
83− let
84− result = appendQueryParams @(limit :: Maybe Int)
85− (unsafeCoerce {} :: Record (limit :: Maybe Int))
86− "/users"
87− result `shouldEqual` "/users"
88−
89− it "handles mixed optional and required params" do
90− let
91− result = appendQueryParams @(limit :: Maybe Int, offset :: Int)
92− (unsafeCoerce { offset: 20 } :: Record (limit :: Maybe Int, offset :: Int))
93− "/users"
94− result `shouldEqual` "/users?offset=20"
95−
96− it "handles empty query params" do
97− let result = appendQueryParams @() {} "/users"
98− result `shouldEqual` "/users"
99−
100− it "URL-encodes special characters in values" do
101− let result = appendQueryParams @(search :: String) { search: "hello world&more=yes" } "/users"
102− result `shouldEqual` "/users?search=hello%20world%26more%3Dyes"
103− it "appends query params to an existing query string" do
104− let result = appendQueryParams @(search :: String) { search: "new value" } "/users?token=old"
105− result `shouldEqual` "/users?token=old&search=new%20value"
106−
107− it "inserts query params before a URL fragment" do
108− let result = appendQueryParams @(search :: String) { search: "new value" } "/users#details"
109− result `shouldEqual` "/users?search=new%20value#details"
110−
111− it "repeats Array query params one pair per element" do
112− let
113− result = appendQueryParams @(categories :: Array Int)
114− { categories: [ 3030, 103130 ] }
115− "/users"
116− result `shouldEqual` "/users?categories=3030&categories=103130"
117−
118− it "omits empty Array query params" do
119− let
120− result = appendQueryParams @(categories :: Array Int)
121− { categories: [] }
122− "/users"
123− result `shouldEqual` "/users"
124−
125− it "mixes Array and bare query params" do
126− let
127− result = appendQueryParams @(query :: String, categories :: Array Int)
128− { query: "foo", categories: [ 1, 2 ] }
129− "/users"
130− result `shouldEqual` "/users?categories=1&categories=2&query=foo"
131−
132− describe "buildUrl" do
133− it "builds URL with path params only" do
134− let
135− result = buildUrl
136− "https://api.example.com"
137− (Proxy :: _ (Path ("users" / "id" : Int)))
138− { id: 42 }
139− {}
140− result `shouldEqual` "https://api.example.com/users/42"
141−
142− it "builds URL with query params only" do
143− let
144− result = buildUrl
145− "https://api.example.com"
146− (Proxy :: _ (Path "users"))
147− {}
148− { limit: 10, offset: 20 }
149− result `shouldEqual` "https://api.example.com/users?limit=10&offset=20"
150−
151− it "appends route paths before base URL query strings and fragments" do
152− let
153− result = buildUrl
154− "https://api.example.com/base/?token=old#details"
155− (Proxy :: _ (Path "users"))
156− {}
157− { search: "new value" }
158− result `shouldEqual` "https://api.example.com/base/users?token=old&search=new%20value#details"
159−
160− it "does not substitute path captures inside a base URL query string" do
161− let
162− result = buildUrl
163− "https://api.example.com?redirect=/:id#details"
164− (Proxy :: _ (Path ("users" / "id" : Int)))
165− { id: 42 }
166− {}
167− result `shouldEqual` "https://api.example.com/users/42?redirect=/:id#details"
21+testSubstitutePathParams :: Effect ViTest
22+testSubstitutePathParams = describe "substitutePathParams" $ do
23+ _ <- test "substitutes single path param" do
24+ let
25+ result = substitutePathParams (Proxy :: _ (id :: Int)) { id: 42 } "/users/:id"
26+ expectToEqual "/users/42" result
27+
28+ _ <- test "substitutes multiple path params" do
29+ let
30+ result = substitutePathParams (Proxy :: _ (userId :: Int, postId :: Int))
31+ { userId: 1, postId: 99 }
32+ "/users/:userId/posts/:postId"
33+ expectToEqual "/users/1/posts/99" result
34+
35+ _ <- test "handles String params" do
36+ let
37+ result = substitutePathParams (Proxy :: _ (slug :: String))
38+ { slug: "hello-world" }
39+ "/posts/:slug"
40+ expectToEqual "/posts/hello-world" result
41+
42+ test "handles empty params" do
43+ let
44+ result = substitutePathParams (Proxy :: _ ()) {} "/users"
45+ expectToEqual "/users" result
46+
47+--------------------------------------------------------------------------------
48+-- AppendQueryParams Tests
49+--------------------------------------------------------------------------------
50+
51+testAppendQueryParams :: Effect ViTest
52+testAppendQueryParams = describe "appendQueryParams" $ do
53+ _ <- test "appends single query param" do
54+ let
55+ result = appendQueryParams (Proxy :: _ (limit :: Int)) { limit: 10 } "/users"
56+ expectToEqual "/users?limit=10" result
57+
58+ _ <- test "appends multiple query params" do
59+ let
60+ result = appendQueryParams (Proxy :: _ (limit :: Int, offset :: Int))
61+ { limit: 10, offset: 20 }
62+ "/users"
63+ expectToEqual "/users?limit=10&offset=20" result
64+
65+ _ <- test "handles Maybe params - Just" do
66+ let
67+ result = appendQueryParams (Proxy :: _ (limit :: Maybe Int))
68+ { limit: Just 10 }
69+ "/users"
70+ expectToEqual "/users?limit=10" result
71+
72+ _ <- test "handles Maybe params - Nothing" do
73+ let
74+ result = appendQueryParams (Proxy :: _ (limit :: Maybe Int))
75+ { limit: Nothing }
76+ "/users"
77+ expectToEqual "/users" result
78+
79+ _ <- test "handles mixed Maybe and required params" do
80+ let
81+ result = appendQueryParams (Proxy :: _ (limit :: Maybe Int, offset :: Int))
82+ { limit: Nothing, offset: 20 }
83+ "/users"
84+ expectToEqual "/users?offset=20" result
85+
86+ test "handles empty query params" do
87+ let
88+ result = appendQueryParams (Proxy :: _ ()) {} "/users"
89+ expectToEqual "/users" result
90+
91+--------------------------------------------------------------------------------
92+-- BuildUrl Tests
93+--------------------------------------------------------------------------------
94+
95+testBuildUrl :: Effect ViTest
96+testBuildUrl = describe "buildUrl" $ do
97+ _ <- test "builds URL with path params only" do
98+ let
99+ result = buildUrl
100+ "https://api.example.com"
101+ (Proxy :: _ (Path ("users" / "id" : Int)))
102+ { id: 42 }
103+ {}
104+ expectToEqual "https://api.example.com/users/42" result
105+
106+ test "builds URL with query params only" do
107+ let
108+ result = buildUrl
109+ "https://api.example.com"
110+ (Proxy :: _ (Path "users"))
111+ {}
112+ { limit: 10, offset: 20 }
113+ expectToEqual "https://api.example.com/users?limit=10&offset=20" result
test/BuildUrlProperty.Spec.pursdeleted−256
@@ -1,256 +0,0 @@
1−module BuildUrlProperty.Spec where
2−
3−import Prelude
4−
5−import Data.Array as Array
6−import Data.Array.NonEmpty as NEA
7−import Data.Enum (toEnum)
8−import Data.Foldable (all)
9−import Data.Maybe (Maybe(..), fromJust, isJust)
10−import Data.String as String
11−import Data.String.CodeUnits as CodeUnits
12−import Data.String.Gen (genAsciiString)
13−import Data.String.CodePoints (CodePoint, fromCodePointArray)
14−import Data.String.Pattern (Pattern(..))
15−import JSURI (decodeURIComponent)
16−import Test.QuickCheck ((<?>), (===))
17−import Test.QuickCheck.Arbitrary (arbitrary)
18−import Test.QuickCheck.Gen (Gen, arrayOf1, chooseInt)
19−import Test.Spec (Spec, describe, it)
20−import Test.Spec.Assertions (shouldEqual)
21−import Test.Spec.QuickCheck (quickCheck)
22−import Partial.Unsafe (unsafePartial)
23−import Unsafe.Coerce (unsafeCoerce)
24−import Yoga.Fetch.Om.BuildUrl (appendQueryParams, substitutePathParams)
25−
26−spec :: Spec Unit
27−spec = describe "URL properties" do
28− it "never substitutes path captures in the query or fragment" $ quickCheck do
29− value <- (genAsciiString :: Gen String)
30− let
31− suffix = "?next=/:slug#/:slug"
32− result = substitutePathParams @(slug :: String)
33− { slug: value }
34− ("/items/:slug" <> suffix)
35− property = case String.stripSuffix (Pattern suffix) result of
36− Nothing -> false
37− Just path -> not $ String.contains (Pattern ":slug") path
38− pure $ property <?> "unexpected path substitution result: " <> show result
39−
40− it "round-trips percent-encoded path and query values" $ quickCheck do
41− value <- (genAsciiString :: Gen String)
42− let
43− pathResult = substitutePathParams @(value :: String)
44− { value }
45− "/items/:value"
46− queryResult = appendQueryParams @(value :: String)
47− { value }
48− "/items"
49− property = case
50− String.stripPrefix (Pattern "/items/") pathResult,
51− String.stripPrefix (Pattern "/items?value=") queryResult
52− of
53− Just encodedPath, Just encodedQuery ->
54− decodeURIComponent encodedPath == Just value
55− && decodeURIComponent encodedQuery == Just value
56− _, _ -> false
57− pure $ property <?> "failed to round-trip value " <> show value
58−
59− it "preserves existing query values and fragments" $ quickCheck do
60− existing <- (genAsciiString :: Gen String)
61− added <- (genAsciiString :: Gen String)
62− let
63− base = appendQueryParams @(token :: String)
64− { token: existing }
65− "/items#details"
66− result = appendQueryParams @(search :: String)
67− { search: added }
68− base
69− property = do
70− withoutFragment <- String.stripSuffix (Pattern "#details") result
71− query <- String.stripPrefix (Pattern "/items?token=") withoutFragment
72− case String.split (Pattern "&search=") query of
73− [ encodedExisting, encodedAdded ] ->
74− pure
75− $ decodeURIComponent encodedExisting == Just existing
76− && decodeURIComponent encodedAdded == Just added
77− _ -> Nothing
78− pure
79− $ (property == Just true)
80− <?> "query or fragment changed unexpectedly: " <> show result
81−
82− it "preserves repeated query parameter order and multiplicity" $ quickCheck do
83− values <- arbitrary
84− let
85− result = appendQueryParams @(tag :: Array Int) { tag: values } "/items"
86− expected = case values of
87− [] -> "/items"
88− _ -> "/items?" <> String.joinWith "&" (map (\value -> "tag=" <> show value) values)
89− pure $ result === expected
90−
91− it "normalizes absent, Nothing, and Just optional fields" $ quickCheck do
92− missing <- arbitrary
93− value <- arbitrary
94− let
95− params :: Record (id :: Maybe Int)
96− params = if missing then unsafeCoerce {} else { id: value }
97− result = appendQueryParams @(id :: Maybe Int) params "/items"
98− expected = case missing, value of
99− true, _ -> "/items"
100− false, Nothing -> "/items"
101− false, Just id -> "/items?id=" <> show id
102− pure $ result === expected
103−
104− it "never introduces malformed query separators" $ quickCheck do
105− value <- arbitrary
106− let
107− bases =
108− [ "/items"
109− , "/items?existing=1"
110− , "/items?"
111− , "/items?existing=1&"
112− , "/items#details"
113− , "/items?existing=1#details"
114− , "/items?#details"
115− , "/items?existing=1&#details"
116− ]
117− results = map (appendQueryParams @(id :: Int) { id: value }) bases
118− pure
119− $ all isWellFormed results
120− <?> "malformed URL generated from " <> show results
121−
122− it "preserves repeated existing query keys" $ quickCheck do
123− first <- (arbitrary :: Gen Int)
124− second <- (arbitrary :: Gen Int)
125− page <- (arbitrary :: Gen Int)
126− let
127− base = "/items?id=" <> show first <> "&id=" <> show second <> "#details"
128− result = appendQueryParams @(page :: Int) { page } base
129− expected =
130− "/items?id=" <> show first <> "&id=" <> show second
131− <> "&page="
132− <> show page
133− <> "#details"
134− pure $ result === expected
135−
136− it "appends duplicate query values without coalescing existing ones" $ quickCheck do
137− first <- (arbitrary :: Gen Int)
138− second <- (arbitrary :: Gen Int)
139− added <- (arbitrary :: Gen (Array Int))
140− let
141− base = "/items?id=" <> show first <> "&id=" <> show second
142− result = appendQueryParams @(id :: Array Int) { id: added } base
143− expected = case added of
144− [] -> base
145− _ -> base <> "&" <> String.joinWith "&" (map (\value -> "id=" <> show value) added)
146− pure $ result === expected
147−
148− it "ignores query-looking text inside fragments" $ quickCheck do
149− value <- (arbitrary :: Gen Int)
150− let
151− rendered = show (value :: Int)
152− cases =
153− [ { base: "/items#section?fake=1", expected: "/items?id=" <> rendered <> "#section?fake=1" }
154− , { base: "/items?real=1#section?fake=1", expected: "/items?real=1&id=" <> rendered <> "#section?fake=1" }
155− , { base: "/items#?fake=1&other=2", expected: "/items?id=" <> rendered <> "#?fake=1&other=2" }
156− , { base: "/items#first#second?fake=1", expected: "/items?id=" <> rendered <> "#first#second?fake=1" }
157− ]
158− property = all
159− (\entry -> appendQueryParams @(id :: Int) { id: value } entry.base == entry.expected)
160− cases
161− pure $ property <?> "fragment handling failed for id " <> rendered
162−
163− it "encodes every query delimiter inside values" $ quickCheck do
164− prefix <- (genAsciiString :: Gen String)
165− suffix <- (genAsciiString :: Gen String)
166− let
167− value = prefix <> "?#&=%+ /" <> suffix
168− result = appendQueryParams @(value :: String) { value } "/items"
169− property = case String.stripPrefix (Pattern "/items?value=") result of
170− Nothing -> false
171− Just encoded ->
172− decodeURIComponent encoded == Just value
173− && all
174− (\delimiter -> not $ String.contains (Pattern delimiter) encoded)
175− [ "?", "#", "&", "=", "+", "/" ]
176− && String.contains (Pattern "%25") encoded
177− pure $ property <?> "delimiter encoding failed: " <> show result
178−
179− it "substitutes repeated captures without matching overlapping names" $ quickCheck do
180− id <- (arbitrary :: Gen Int)
181− id2 <- (arbitrary :: Gen Int)
182− let
183− result = substitutePathParams @(id :: Int, id2 :: Int)
184− { id, id2 }
185− "/:id/:id/:id2/:id20?next=/:id#/:id2"
186− expected =
187− "/" <> show id <> "/" <> show id <> "/" <> show id2
188− <> "/:id20?next=/:id#/:id2"
189− pure $ result === expected
190−
191− it "normalizes lone UTF-16 surrogates before percent-encoding" do
192− let
193− value = codeUnit 0xD800 <> "x" <> codeUnit 0xDFFF
194− result = appendQueryParams @(value :: String) { value } "/items"
195− result `shouldEqual` "/items?value=%EF%BF%BDx%EF%BF%BD"
196−
197− it "percent-encodes arbitrary UTF-16 strings without throwing" $ quickCheck do
198− value <- (arbitrary :: Gen String)
199− let
200− pathResult = substitutePathParams @(value :: String) { value } "/items/:value"
201− queryResult = appendQueryParams @(value :: String) { value } "/items"
202− property =
203− isJust (String.stripPrefix (Pattern "/items/") pathResult)
204− && isJust (String.stripPrefix (Pattern "/items?value=") queryResult)
205− pure $ property <?> "encoding failed for UTF-16 input " <> show value
206−
207− it "round-trips valid non-ASCII scalar values" $ quickCheck do
208− value <- unicodeScalarString
209− let
210− pathResult = substitutePathParams @(value :: String) { value } "/items/:value"
211− queryResult = appendQueryParams @(value :: String) { value } "/items"
212− property = case
213− String.stripPrefix (Pattern "/items/") pathResult,
214− String.stripPrefix (Pattern "/items?value=") queryResult
215− of
216− Just encodedPath, Just encodedQuery ->
217− decodeURIComponent encodedPath == Just value
218− && decodeURIComponent encodedQuery == Just value
219− _, _ -> false
220− pure $ property <?> "Unicode round-trip failed for " <> show value
221−
222−isWellFormed :: String -> Boolean
223−isWellFormed url =
224− occurrences "?" url == 1
225− && occurrences "#" url <= 1
226− && not (String.contains (Pattern "??") url)
227− && not (String.contains (Pattern "&&") url)
228− && not (String.contains (Pattern "?#") url)
229− && not (String.contains (Pattern "&#") url)
230− && queryPrecedesFragment url
231−
232−queryPrecedesFragment :: String -> Boolean
233−queryPrecedesFragment url = case String.indexOf (Pattern "#") url of
234− Nothing -> true
235− Just fragmentIndex -> case String.indexOf (Pattern "?") url of
236− Nothing -> false
237− Just queryIndex -> queryIndex < fragmentIndex
238−
239−occurrences :: String -> String -> Int
240−occurrences needle = (_ - 1) <<< Array.length <<< String.split (Pattern needle)
241−
242−unicodeScalarString :: Gen String
243−unicodeScalarString =
244− fromCodePointArray <<< NEA.toArray <$> arrayOf1 unicodeScalar
245−
246−unicodeScalar :: Gen CodePoint
247−unicodeScalar = do
248− useBasicMultilingualPlane <- arbitrary
249− value <- if useBasicMultilingualPlane then
250− chooseInt 0x80 0xD7FF
251− else
252− chooseInt 0xE000 0x10FFFF
253− pure $ unsafePartial $ fromJust $ toEnum value
254−
255−codeUnit :: Int -> String
256−codeUnit value = CodeUnits.singleton $ unsafePartial $ fromJust $ toEnum value
test/Complete.Example.purs+26−29
@@ -3,10 +3,10 @@ module Complete.Example where
33import Prelude
44
55import Data.Array (length)
6−import Justifill (justifill)
6+import Data.Maybe (Maybe(..))
77import Effect.Class.Console (log)
8−import Yoga.Fetch.Om (GET, POST, PUT, DELETE, Route, JSON, type (/), type (:), type (:?), client)
9−import Yoga.HTTP.API.Route (BearerToken(..))
8+import Type.Proxy (Proxy(..))
9+import Yoga.Fetch.Om (GET, POST, PUT, DELETE, Route, JSON, Path, type (/), type (:), type (:?), deriveClient)
1010import Yoga.Om (Om, handleErrors)
1111
1212type User =
@@ -31,44 +31,50 @@ type ErrorMessage =
3131
3232type UserAPI =
3333 { getUser ::
34− Route GET ("users" / "id" : Int)
34+ Route GET
35+ (Path ("users" / "id" : Int))
3536 {}
3637 ( ok :: { body :: User }
3738 , notFound :: { body :: ErrorMessage }
3839 )
3940 , listUsers ::
40− Route GET ("users" :? { limit :: Int, offset :: Int })
41+ Route GET
42+ (Path "users" :? { limit :: Int, offset :: Int })
4143 {}
4244 ( ok :: { body :: Array User }
4345 )
4446 , createUser ::
45− Route POST "users"
47+ Route POST
48+ (Path "users")
4649 { body :: JSON CreateUserRequest }
4750 ( created :: { body :: User }
4851 , badRequest :: { body :: ErrorMessage }
4952 )
5053 , updateUser ::
51− Route PUT ("users" / "id" : Int)
54+ Route PUT
55+ (Path ("users" / "id" : Int))
5256 { body :: JSON UpdateUserRequest }
5357 ( ok :: { body :: User }
5458 , notFound :: { body :: ErrorMessage }
5559 , badRequest :: { body :: ErrorMessage }
5660 )
5761 , deleteUser ::
58− Route DELETE ("users" / "id" : Int)
62+ Route DELETE
63+ (Path ("users" / "id" : Int))
5964 {}
60− ( noContent :: {}
65+ ( noContent :: { body :: {} }
6166 , notFound :: { body :: ErrorMessage }
6267 )
63− , createUserAuth ::
64− Route POST "users"
65− { headers :: Record (authorization :: BearerToken), body :: JSON CreateUserRequest }
66− ( created :: { body :: User }
67− , badRequest :: { body :: ErrorMessage }
68− )
6968 }
7069
71−api = client @UserAPI "https://api.example.com"
70+api
71+ :: { createUser :: CreateUserRequest -> Om {} (badRequest :: ErrorMessage) User
72+ , deleteUser :: { id :: Int } -> Om {} (notFound :: ErrorMessage) {}
73+ , getUser :: { id :: Int } -> Om {} (notFound :: ErrorMessage) User
74+ , listUsers :: { limit :: Maybe Int, offset :: Maybe Int } -> Om {} () (Array User)
75+ , updateUser :: { id :: Int } -> UpdateUserRequest -> Om {} (badRequest :: ErrorMessage, notFound :: ErrorMessage) User
76+ }
77+api = deriveClient "https://api.example.com" (Proxy :: Proxy UserAPI)
7278
7379exampleGetUser :: Om {} (notFound :: ErrorMessage) Unit
7480exampleGetUser = do
@@ -79,15 +85,15 @@ exampleGetUserHandled :: Om {} () Unit
7985exampleGetUserHandled = do
8086 user <- api.getUser { id: 42 }
8187 # handleErrors
82− { notFound: \err -> ado
88+ { notFound: \err -> do
8389 log $ "User not found: " <> err.error
84− in { id: 0, name: "unknown", email: "" }
90+ pure { id: 0, name: "unknown", email: "" }
8591 }
8692 log $ "Found user: " <> user.name
8793
8894exampleListUsers :: Om {} () Unit
8995exampleListUsers = do
90− users <- api.listUsers (justifill { limit: 10, offset: 0 })
96+ users <- api.listUsers { limit: Just 10, offset: Just 0 }
9197 log $ "Found " <> show (length users) <> " users"
9298
9399exampleCreateUser :: Om {} (badRequest :: ErrorMessage) Unit
@@ -100,8 +106,7 @@ exampleCreateUser = do
100106
101107exampleUpdateUser :: Om {} (notFound :: ErrorMessage, badRequest :: ErrorMessage) Unit
102108exampleUpdateUser = do
103− user <- api.updateUser
104− { id: 42 }
109+ user <- api.updateUser { id: 42 }
105110 { name: "Alice Updated"
106111 , email: "alice.new@example.com"
107112 }
@@ -111,11 +116,3 @@ exampleDeleteUser :: Om {} (notFound :: ErrorMessage) Unit
111116exampleDeleteUser = do
112117 _ <- api.deleteUser { id: 42 }
113118 log "User deleted successfully"
114−
115−exampleCreateUserAuth :: Om {} (badRequest :: ErrorMessage) Unit
116−exampleCreateUserAuth = do
117− user <- api.createUserAuth { authorization: BearerToken "abc123" }
118− { name: "Alice"
119− , email: "alice@example.com"
120− }
121− log $ "Created user with ID: " <> show user.id
test/Example.purs+8−20
@@ -1,51 +1,39 @@
11module Example where
22
3−import Yoga.HTTP.API.Route (GET, POST, DELETE, Route, BearerToken)
3+import Yoga.HTTP.API.Route (GET, POST, DELETE, Route)
44import Yoga.HTTP.API.Route.Encoding (JSON)
55import Yoga.HTTP.API.Path (Path, type (/), type (:), type (:?))
66
7−type User = { id :: UserId, name :: UserName, email :: UserMail }
8−type CreateUserRequest = { name :: String, email :: UserMail }
7+type User = { id :: Int, name :: String, email :: String }
8+type CreateUserRequest = { name :: String, email :: String }
99type ErrorMessage = { error :: String }
10−newtype UserId = UserId Int
11−newtype UserName = UserName String
12−newtype UserMail = UserMail String
13−newtype Limit = Limit Int
14−newtype Offset = Offset Int
1510
1611type UserAPI =
1712 { getUser ::
1813 Route GET
19− ("users" / "id" : UserId)
14+ (Path ("users" / "id" : Int))
2015 {}
2116 ( ok :: { body :: User }
2217 , notFound :: { body :: ErrorMessage }
2318 )
2419 , listUsers ::
2520 Route GET
26− ("users" :? { limit :: Limit, offset :: Offset })
21+ (Path "users" :? { limit :: Int, offset :: Int })
2722 {}
2823 ( ok :: { body :: Array User }
2924 )
3025 , createUser ::
3126 Route POST
32− "users"
27+ (Path "users")
3328 { body :: JSON CreateUserRequest }
3429 ( created :: { body :: User }
3530 , badRequest :: { body :: ErrorMessage }
3631 )
3732 , deleteUser ::
3833 Route DELETE
39− ("users" / "id" : UserId)
34+ (Path ("users" / "id" : Int))
4035 {}
41− ( noContent :: {}
36+ ( noContent :: { body :: {} }
4237 , notFound :: { body :: ErrorMessage }
4338 )
44− , createUserAuth ::
45− Route POST
46− "users"
47− { headers :: Record (authorization :: BearerToken), body :: JSON CreateUserRequest }
48− ( created :: { body :: User }
49− , badRequest :: { body :: ErrorMessage }
50− )
5139 }
test/MakeRequest.Spec.pursdeleted−54
@@ -1,54 +0,0 @@
1−module MakeRequest.Spec where
2−
3−import Prelude
4−
5−import Data.HTTP.Method as HTTP
6−import Data.Maybe (Maybe(..))
7−import Data.Tuple.Nested ((/\))
8−import JS.Fetch.Headers as Headers
9−import Prim.RowList as RL
10−import Test.Spec (Spec, describe, it)
11−import Test.Spec.Assertions (shouldEqual, shouldSatisfy)
12−import Type.Proxy (Proxy(..))
13−import Yoga.Fetch.Om (FormData, PlainText, QUERY, toHeaders)
14−import Yoga.Fetch.Om.MakeRequest (encodeBody, encodingContentType, httpMethod)
15−import Yoga.HTTP.API.Route (BearerToken(..))
16−
17−spec :: Spec Unit
18−spec = do
19− describe "MakeRequest" do
20− it "maps a QUERY route method imported from the public module" do
21− httpMethod (Proxy :: Proxy QUERY) `shouldEqual` HTTP.QUERY
22−
23− describe "BodyEncoding" do
24− it "sends PlainText request bodies without JSON quoting" do
25− encodingContentType (Proxy :: Proxy PlainText) `shouldEqual` "text/plain"
26− encodeBody @PlainText "hello" `shouldEqual` Just "hello"
27−
28− it "URL-encodes FormData request bodies" do
29− encodingContentType (Proxy :: Proxy (FormData { username :: String })) `shouldEqual` "application/x-www-form-urlencoded"
30− encodeBody @(FormData { username :: String }) { username: "Ada Lovelace" }
31− `shouldEqual` Just "username=Ada+Lovelace"
32−
33− describe "toHeaders" do
34− it "empty headers produces no entries" do
35− let hdrs = toHeaders (Proxy :: _ RL.Nil) {}
36− Headers.toArray hdrs `shouldEqual` []
37−
38− it "single header is included" do
39− let hdrs = toHeaders (Proxy :: _ (RL.Cons "authorization" String RL.Nil)) { authorization: "Bearer abc123" }
40− Headers.toArray hdrs `shouldEqual` [ "authorization" /\ "Bearer abc123" ]
41−
42− it "multiple headers are included" do
43− let
44− hdrs = toHeaders
45− (Proxy :: _ (RL.Cons "authorization" String (RL.Cons "x-custom" String RL.Nil)))
46− { authorization: "Bearer abc123", "x-custom": "value" }
47− arr = Headers.toArray hdrs
48− arr `shouldSatisfy` \a ->
49− a == [ "authorization" /\ "Bearer abc123", "x-custom" /\ "value" ]
50− || a == [ "x-custom" /\ "value", "authorization" /\ "Bearer abc123" ]
51−
52− it "typed header values are rendered with HeaderValue" do
53− let hdrs = toHeaders (Proxy :: _ (RL.Cons "authorization" BearerToken RL.Nil)) { authorization: BearerToken "abc123" }
54− Headers.toArray hdrs `shouldEqual` [ "authorization" /\ "Bearer abc123" ]
test/PlainTextResponse.Spec.pursdeleted−122
@@ -1,122 +0,0 @@
1−module PlainTextResponse.Spec where
2−
3−import Prelude
4−import Data.String as String
5−
6−import Effect.Aff (Aff, bracket)
7−import Effect.Aff.Class (liftAff)
8−import Effect.Class (liftEffect)
9−import Effect.Ref (Ref)
10−import Effect.Exception as Exn
11−import Effect.Ref as Ref
12−import Foreign (unsafeToForeign)
13−import Test.Spec (Spec, around, describe, it)
14−import Test.Spec.Assertions (shouldEqual)
15−import Yoga.Fastify.Fastify as F
16−import Yoga.Fastify.Fastify (Port(..), Host(..), RouteURL(..), StatusCode(..))
17−import Yoga.Fastify.Om (createOmFastify, getOm, postOm)
18−import Yoga.Fetch.Om (GET, POST, Route, type (/), JSON, PlainText, Streaming, client)
19−import Yoga.Fetch.Om.Simple as Simple
20−import Yoga.Om (Om, runOm)
21−import Yoga.Om.Strom (Strom)
22−import Yoga.Om.Strom as Strom
23−
24−type Payload = { value :: Int }
25−type Result = { doubled :: Int }
26−
27−type TestAPI =
28− { double ::
29− Route POST
30− ("plain-text-test" / "double")
31− { body :: JSON Payload }
32− ( ok :: { body :: Result }
33− , badRequest :: { body :: PlainText }
34− )
35− , health :: Route GET ("plain-text-test" / "health") {} (ok :: { body :: PlainText })
36− , stream :: Route GET ("plain-text-test" / "stream") {} (ok :: { body :: Streaming String })
37− }
38−
39−api
40− :: forall ctx err
41− . { double :: Payload -> Om (Record ctx) (badRequest :: String | err) Result
42− , health :: Om (Record ctx) err String
43− , stream :: Om (Record ctx) err (Strom {} () String)
44− }
45−api = client @TestAPI "http://localhost:44933"
46−
47−spec :: Spec Unit
48−spec = around withServer $ describe "String body on error responses" do
49− it "200 OK decodes the JSON response body" \_ -> do
50− result <- runOm {}
51− { exception: \_ -> pure { doubled: -1 }
52− , badRequest: \_ -> pure { doubled: -1 }
53− }
54− (api.double { value: 21 })
55− liftAff $ result `shouldEqual` { doubled: 42 }
56−
57− it "400 badRequest delivers the raw text body as a String" \serverMode -> do
58− liftEffect $ Ref.write "badRequest" serverMode
59− captured <- liftEffect $ Ref.new ""
60− runOm {}
61− { exception: \_ -> pure unit
62− , badRequest: \b -> liftEffect $ Ref.write b captured
63− }
64− (void $ api.double { value: 0 })
65− body <- liftEffect $ Ref.read captured
66− liftAff $ body `shouldEqual` "invalid value"
67−
68− it "Simple.get returns plain text for String responses" \_ -> do
69− result <- runOm {}
70− { exception: \e -> pure $ "exception: " <> Exn.message e
71− , fetchError: \e -> pure $ "fetch error: " <> e.body
72− }
73− (Simple.get @String "http://localhost:44933/plain-text-test/health" {})
74− liftAff $ result `shouldEqual` "healthy"
75−
76− it "derived PlainText responses decode to String" \_ -> do
77− result <- runOm {}
78− { exception: \e -> pure $ "exception: " <> Exn.message e }
79− api.health
80− liftAff $ result `shouldEqual` "healthy"
81−
82− it "derived Streaming responses decode to a usable Strom" \_ -> do
83− chunks <- runOm {}
84− { exception: \e -> pure [ "exception: " <> Exn.message e ] }
85− do
86− stream <- api.stream
87− Strom.runCollect stream
88− liftAff $ String.joinWith "" chunks `shouldEqual` "stream €"
89−
90−withServer :: forall a. (Ref String -> Aff a) -> Aff a
91−withServer test = bracket acquire release (\{ serverMode } -> test serverMode)
92− where
93− acquire = do
94− serverMode <- liftEffect $ Ref.new "ok"
95− fastify <- liftEffect do
96− f <- F.fastify {}
97− omApp <- createOmFastify {} f
98− postOm (RouteURL "/plain-text-test/double") (handler serverMode) omApp
99− getOm (RouteURL "/plain-text-test/health") (plainTextHandler "healthy") omApp
100− getOm (RouteURL "/plain-text-test/stream") (plainTextHandler "stream €") omApp
101− pure f
102− void $ F.listen { port: Port 44933, host: Host "0.0.0.0" } fastify
103− pure { fastify, serverMode }
104−
105− release { fastify } = F.close fastify
106−
107− plainTextHandler text reply = do
108− void $ F.status (StatusCode 200) reply # liftEffect
109− void $ F.header "content-type" "text/plain" reply # liftEffect
110− F.send (unsafeToForeign text) reply # liftAff
111−
112− handler serverMode reply = do
113− mode <- liftEffect $ Ref.read serverMode
114− case mode of
115− "badRequest" -> do
116− void $ F.status (StatusCode 400) reply # liftEffect
117− void $ F.header "content-type" "text/plain" reply # liftEffect
118− F.send (unsafeToForeign "invalid value") reply # liftAff
119− _ -> do
120− void $ F.status (StatusCode 200) reply # liftEffect
121− void $ F.header "content-type" "application/json" reply # liftEffect
122− F.sendJson (unsafeToForeign { doubled: 42 }) reply # liftAff
test/Polymorphic.Spec.pursdeleted−70
@@ -1,70 +0,0 @@
1−module Polymorphic.Spec where
2−
3−import Prelude
4−
5−import Effect.Aff (bracket)
6−import Effect.Aff.Class (liftAff)
7−import Effect.Class (liftEffect)
8−import Test.Spec (Spec, around, describe, it)
9−import Test.Spec.Assertions (shouldEqual)
10−import Yoga.Fastify.Fastify as F
11−import Yoga.Fastify.Fastify (Port(..), Host(..))
12−import Yoga.Fastify.Om.API (registerAPI)
13−import Yoga.Fastify.Om.Route (Handler, handle, respond)
14−import Yoga.Fetch.Om (GET, Route, type (/), type (:), client)
15−import Yoga.Om (ask, runOm)
16−import Control.Monad.Error.Class (throwError)
17−
18−type User = { id :: Int, name :: String }
19−
20−type GetUserRoute = Route GET ("users" / "id" : Int) {} (ok :: { body :: User })
21−
22−type TestAPI =
23− { getUser :: GetUserRoute
24− }
25−
26−api = client @TestAPI "http://localhost:44931"
27−
28−spec :: Spec Unit
29−spec = around withServer $ describe "polymorphic client" do
30− it "fetches user with { token :: String } context" \_ ->
31− runOm { token: "secret123" } { exception: throwError } do
32− { token } <- ask
33− { name } <- api.getUser { id: 42 }
34− liftAff $ (token <> ":" <> name) `shouldEqual` "secret123:User 42"
35−
36− it "fetches user with { apiKey :: String, userId :: Int } context" \_ ->
37− runOm { apiKey: "mykey", userId: 7 } { exception: throwError } do
38− { apiKey, userId } <- ask
39− { name } <- api.getUser { id: userId }
40− liftAff $ (apiKey <> ":" <> name) `shouldEqual` "mykey:User 7"
41−
42− it "same api.getUser works in two different contexts" \_ -> do
43−
44− runOm { token: "tok1" } { exception: throwError } do
45− { token } <- ask
46− { name } <- api.getUser { id: 1 }
47− liftAff $ (token <> ":" <> name) `shouldEqual` "tok1:User 1"
48−
49− runOm { endpoint: "prod", region: "eu" } { exception: throwError } do
50− { endpoint, region } <- ask
51− { name } <- api.getUser { id: 2 }
52− liftAff $ (endpoint <> "-" <> region <> ":" <> name) `shouldEqual` "prod-eu:User 2"
53−
54−withServer :: forall a. (Unit -> _ a) -> _ a
55−withServer test = bracket acquire release (\_ -> test unit)
56− where
57− acquire = do
58− fastify <- liftEffect do
59− f <- F.fastify {}
60− registerAPI @TestAPI { getUser: getUserHandler } f
61− pure f
62− void $ F.listen { port: Port 44931, host: Host "0.0.0.0" } fastify
63− pure fastify
64−
65− release = F.close
66−
67−getUserHandler :: Handler GetUserRoute ()
68−getUserHandler = handle do
69− { path } <- ask
70− respond @"ok" { id: path.id, name: "User " <> show path.id }
test/Roundtrip.Spec.pursdeleted−380
@@ -1,380 +0,0 @@
1−module Roundtrip.Spec where
2−
3−import Prelude
4−
5−import Data.Maybe (Maybe(..))
6−import Effect.Aff (bracket)
7−import Effect.Aff.Class (liftAff)
8−import Effect.Class (liftEffect)
9−import Effect.Ref as Ref
10−import Effect.Exception as Exn
11−import Justifill (justifill)
12−import Test.Spec (Spec, around, describe, it)
13−import Test.Spec.Assertions (shouldEqual)
14−import Yoga.Fastify.Fastify as F
15−import Yoga.Fastify.Fastify (Port(..), Host(..))
16−import Yoga.Fastify.Om.API (registerAPI)
17−import Yoga.Fastify.Om.Route (Handler, handle, respond, reject, BearerToken(..))
18−import Yoga.Fetch.Om (GET, POST, PUT, DELETE, Required, Route, JSON, type (/), type (:), type (:?), client, clientWith)
19−import Yoga.Om (ask, handleErrors, runOm)
20−
21−-- Types
22−
23−type User = { id :: Int, name :: String, email :: String }
24−type CreateUserReq = { name :: String, email :: String }
25−type ErrorMsg = { error :: String }
26−
27−-- Route definitions shared by server and client
28−
29−type GetUserRoute = Route GET
30− ("users" / "id" : Int)
31− {}
32− ( ok :: { body :: User }
33− , notFound :: { body :: ErrorMsg }
34− )
35−
36−type ListUsersRoute = Route GET
37− ("users" :? { limit :: Int, offset :: Int })
38− {}
39− (ok :: { body :: Array User })
40−
41−type CreateUserRoute = Route POST
42− "users"
43− { body :: JSON CreateUserReq }
44− ( created :: { body :: User }
45− , badRequest :: { body :: ErrorMsg }
46− )
47−
48−type UpdateUserRoute = Route PUT
49− ("users" / "id" : Int)
50− { body :: JSON CreateUserReq }
51− ( ok :: { body :: User }
52− , notFound :: { body :: ErrorMsg }
53− )
54−
55−type DeleteUserRoute = Route DELETE
56− ("users" / "id" : Int)
57− {}
58− ( ok :: { body :: {} }
59− , notFound :: { body :: ErrorMsg }
60− )
61−
62−type AuthRoute = Route GET
63− "me"
64− { headers :: { authorization :: BearerToken } }
65− ( ok :: { body :: User }
66− , unauthorized :: { body :: ErrorMsg }
67− )
68−
69−type SearchRoute = Route GET
70− ("search" :? { active :: Boolean, minScore :: Number })
71− {}
72− (ok :: { body :: { active :: Boolean, minScore :: Number } })
73−
74−type FindByQueryRoute = Route GET
75− ("find-by-query" :? { id :: Int })
76− {}
77− (ok :: { body :: { id :: Int } })
78−
79−type InjectedTenantRoute = Route GET
80− ("tenant-users" / "id" : Int :? { tenant :: Required String })
81− { headers :: { authorization :: BearerToken, requestid :: String } }
82− ( ok :: { body :: User }
83− , unauthorized :: { body :: ErrorMsg }
84− )
85−
86−type InjectedAPI =
87− { getTenantUser :: InjectedTenantRoute
88− }
89−
90−injectedApi tokenRef =
91− clientWith @InjectedAPI
92− { baseUrl: pure "http://localhost:44932"
93− , provide: do
94− ctx <- ask
95− token <- liftEffect $ Ref.read tokenRef
96− pure
97− { headers: { authorization: BearerToken token, requestid: ctx.requestid }
98− , query: { tenant: ctx.tenant }
99− }
100− }
101−
102−type API =
103− { getUser :: GetUserRoute
104− , listUsers :: ListUsersRoute
105− , createUser :: CreateUserRoute
106− , updateUser :: UpdateUserRoute
107− , deleteUser :: DeleteUserRoute
108− , me :: AuthRoute
109− , search :: SearchRoute
110− , findByQuery :: FindByQueryRoute
111− }
112−
113−api = client @API "http://localhost:44932"
114−
115−-- Handlers
116−
117−getUserHandler :: Handler GetUserRoute ()
118−getUserHandler = handle do
119− { path } <- ask
120− if path.id == 42 then respond @"ok" { id: 42, name: "Alice", email: "alice@test.com" }
121− else reject @"notFound" { error: "User " <> show path.id <> " not found" }
122−
123−listUsersHandler :: Handler ListUsersRoute ()
124−listUsersHandler = handle do
125− { query } <- ask
126− let
127− users =
128− [ { id: 1, name: "Alice", email: "a@t.com" }
129− , { id: 2, name: "Bob", email: "b@t.com" }
130− , { id: 3, name: "Charlie", email: "c@t.com" }
131− ]
132− let
133− limited = case query.limit of
134− Just l -> take l users
135− Nothing -> users
136− respond @"ok" limited
137− where
138− take n xs =
139− if n <= 0 then []
140− else case xs of
141− [] -> []
142− [ a ] -> [ a ]
143− [ a, _ ] | n == 1 -> [ a ]
144− [ a, b ] -> [ a, b ]
145− _ -> xs
146−
147−createUserHandler :: Handler CreateUserRoute ()
148−createUserHandler = handle do
149− { body } <- ask
150− if body.name == "" then reject @"badRequest" { error: "Name required" }
151− else respond @"created" { id: 99, name: body.name, email: body.email }
152−
153−updateUserHandler :: Handler UpdateUserRoute ()
154−updateUserHandler = handle do
155− { path, body } <- ask
156− if path.id /= 42 then reject @"notFound" { error: "Not found" }
157− else respond @"ok" { id: path.id, name: body.name, email: body.email }
158−
159−deleteUserHandler :: Handler DeleteUserRoute ()
160−deleteUserHandler = handle do
161− { path } <- ask
162− if path.id /= 42 then reject @"notFound" { error: "Not found" }
163− else respond @"ok" {}
164−
165−meHandler :: Handler AuthRoute ()
166−meHandler = handle do
167− { headers } <- ask
168− case headers.authorization of
169− BearerToken "secret" -> respond @"ok" { id: 1, name: "Admin", email: "admin@test.com" }
170− _ -> reject @"unauthorized" { error: "Invalid token" }
171−
172−searchHandler :: Handler SearchRoute ()
173−searchHandler = handle do
174− { query } <- ask
175− let
176− active = case query.active of
177− Just a -> a
178− Nothing -> false
179− let
180− minScore = case query.minScore of
181− Just s -> s
182− Nothing -> 0.0
183− respond @"ok" { active, minScore }
184−
185−findByQueryHandler :: Handler FindByQueryRoute ()
186−findByQueryHandler = handle do
187− { query } <- ask
188− let
189− id = case query.id of
190− Just value -> value
191− Nothing -> -1
192− respond @"ok" { id }
193−
194−tenantUserHandler :: Handler InjectedTenantRoute ()
195−tenantUserHandler = handle do
196− { path, query, headers } <- ask
197− case headers.authorization of
198− BearerToken "secret" -> respond @"ok" { id: path.id, name: query.tenant <> ":" <> headers.requestid, email: "tenant@test.com" }
199− _ -> reject @"unauthorized" { error: "Invalid token" }
200−
201−-- Test suite
202−
203−spec :: Spec Unit
204−spec = around withServer $ describe "server ↔ client roundtrip" do
205−
206− describe "GET with path params" do
207− it "returns user for valid id" \_ ->
208− runOm {} { exception: \_ -> pure unit } do
209− user <- api.getUser { id: 42 }
210− # handleErrors { notFound: \e -> pure { id: 0, name: e.error, email: "" } }
211− liftAff $ user.name `shouldEqual` "Alice"
212−
213− it "returns notFound for invalid id" \_ ->
214− runOm {} { exception: \_ -> pure unit } do
215− user <- api.getUser { id: 999 }
216− # handleErrors { notFound: \e -> pure { id: 0, name: e.error, email: "" } }
217− liftAff $ user.name `shouldEqual` "User 999 not found"
218−
219− describe "GET with query params" do
220− it "passes query params correctly" \_ ->
221− runOm {} { exception: \_ -> pure unit } do
222− users <- api.listUsers (justifill { limit: 1 })
223− liftAff $ (map _.name users) `shouldEqual` [ "Alice" ]
224−
225− it "serializes a single explicit Maybe query through the derived client" \_ ->
226− runOm {} { exception: \_ -> pure unit } do
227− result <- api.findByQuery { id: Just 42 }
228− liftAff $ result.id `shouldEqual` 42
229−
230− it "handles no query params" \_ ->
231− runOm {} { exception: \_ -> pure unit } do
232− users <- api.listUsers (justifill {})
233− liftAff $ (map _.name users) `shouldEqual` [ "Alice", "Bob", "Charlie" ]
234−
235− describe "POST with JSON body" do
236− it "sends and receives JSON body" \_ ->
237− runOm {} { exception: \_ -> pure unit } do
238− user <- api.createUser { name: "Dave", email: "d@t.com" }
239− # handleErrors { badRequest: \e -> pure { id: 0, name: e.error, email: "" } }
240− liftAff do
241− user.name `shouldEqual` "Dave"
242− user.email `shouldEqual` "d@t.com"
243− user.id `shouldEqual` 99
244−
245− it "rejects with badRequest for empty name" \_ ->
246− runOm {} { exception: \_ -> pure unit } do
247− user <- api.createUser { name: "", email: "e@t.com" }
248− # handleErrors { badRequest: \e -> pure { id: 0, name: e.error, email: "" } }
249− liftAff $ user.name `shouldEqual` "Name required"
250−
251− describe "PUT with path params and JSON body" do
252− it "sends path params and body together" \_ ->
253− runOm {} { exception: \_ -> pure unit } do
254− user <-
255− api.updateUser
256− { id: 42 }
257− { name: "Updated", email: "u@t.com" }
258− # handleErrors { notFound: \e -> pure { id: 0, name: e.error, email: "" } }
259− liftAff do
260− user.id `shouldEqual` 42
261− user.name `shouldEqual` "Updated"
262−
263− it "supports partial application before the body argument" \_ ->
264− runOm {} { exception: \_ -> pure unit } do
265− let update42 = api.updateUser { id: 42 }
266− user <- update42 { name: "Curried", email: "curried@t.com" }
267− # handleErrors { notFound: \e -> pure { id: 0, name: e.error, email: "" } }
268− liftAff do
269− user.id `shouldEqual` 42
270− user.name `shouldEqual` "Curried"
271−
272− describe "DELETE with path params" do
273− it "deletes successfully" \_ ->
274− runOm {} { exception: \_ -> pure unit } do
275− result <- api.deleteUser { id: 42 }
276− # handleErrors { notFound: \_ -> pure {} }
277− liftAff $ result `shouldEqual` {}
278−
279− it "returns notFound for wrong id" \_ ->
280− runOm {} { exception: \_ -> pure unit } do
281− result <- api.deleteUser { id: 1 }
282− # handleErrors { notFound: \_ -> pure {} }
283− liftAff $ result `shouldEqual` {}
284−
285− describe "GET with authorization header" do
286− it "passes bearer token in header" \_ ->
287− runOm {} { exception: \_ -> pure unit } do
288− user <- api.me { authorization: BearerToken "secret" }
289− # handleErrors { unauthorized: \e -> pure { id: 0, name: e.error, email: "" } }
290− liftAff $ user.name `shouldEqual` "Admin"
291−
292− it "rejects unauthorized" \_ ->
293− runOm {} { exception: \_ -> pure unit } do
294− user <- api.me { authorization: BearerToken "wrong" }
295− # handleErrors { unauthorized: \e -> pure { id: 0, name: e.error, email: "" } }
296− liftAff $ user.name `shouldEqual` "Invalid token"
297−
298− describe "GET with Boolean and Number query params" do
299− it "passes Boolean and Number query params" \_ ->
300− runOm {} { exception: \_ -> pure unit } do
301− result <- api.search (justifill { active: true, minScore: 3.14 })
302− liftAff do
303− result.active `shouldEqual` true
304− result.minScore `shouldEqual` 3.14
305−
306− it "handles missing optional query params" \_ ->
307− runOm {} { exception: \_ -> pure unit } do
308− result <- api.search (justifill {})
309− liftAff do
310− result.active `shouldEqual` false
311− result.minScore `shouldEqual` 0.0
312−
313− describe "optional query params" do
314− it "accepts a selected optional query parameter" \_ ->
315− runOm {} { exception: \_ -> pure unit } do
316− users <- api.listUsers (justifill { limit: 1 })
317− liftAff $ (map _.name users) `shouldEqual` [ "Alice" ]
318−
319− it "accepts all optional query parameters" \_ ->
320− runOm {} { exception: \_ -> pure unit } do
321− users <- api.listUsers (justifill { limit: 2, offset: 0 })
322− liftAff $ (map _.name users) `shouldEqual` [ "Alice", "Bob" ]
323−
324− it "fills omitted optional query parameters with Nothing" \_ ->
325− runOm {} { exception: \_ -> pure unit } do
326− users <- api.listUsers (justifill {})
327− liftAff $ (map _.name users) `shouldEqual` [ "Alice", "Bob", "Charlie" ]
328−
329− it "passes selected Boolean query param" \_ ->
330− runOm {} { exception: \_ -> pure unit } do
331− result <- api.search (justifill { active: true })
332− liftAff do
333− result.active `shouldEqual` true
334− result.minScore `shouldEqual` 0.0
335−
336− describe "clientWith injected inputs" do
337− it "reads provided headers and query params from Om context for each call" \_ -> do
338− tokenRef <- liftEffect $ Ref.new "secret"
339− let injected = injectedApi tokenRef
340− user <- runOm { tenant: "acme", requestid: "req-1" }
341− { exception: \e -> pure { id: -1, name: Exn.message e, email: "" }
342− , unauthorized: \e -> pure { id: -2, name: e.error, email: "" }
343− }
344− (injected.getTenantUser { id: 7 })
345− liftAff do
346− user.id `shouldEqual` 7
347− user.name `shouldEqual` "acme:req-1"
348− liftEffect $ Ref.write "wrong" tokenRef
349− rejected <- runOm { tenant: "acme", requestid: "req-2" }
350− { exception: \e -> pure { id: -1, name: Exn.message e, email: "" }
351− , unauthorized: \e -> pure { id: -2, name: e.error, email: "" }
352− }
353− (injected.getTenantUser { id: 8 })
354− liftAff $ rejected.name `shouldEqual` "Invalid token"
355−
356−-- Server setup
357−
358−withServer :: forall a. (Unit -> _ a) -> _ a
359−withServer test = bracket acquire release (\_ -> test unit)
360− where
361− acquire = do
362− fastify <- liftEffect do
363− f <- F.fastify {}
364− registerAPI @API
365− { getUser: getUserHandler
366− , listUsers: listUsersHandler
367− , createUser: createUserHandler
368− , updateUser: updateUserHandler
369− , deleteUser: deleteUserHandler
370− , me: meHandler
371− , search: searchHandler
372− , findByQuery: findByQueryHandler
373− }
374− f
375− registerAPI @InjectedAPI { getTenantUser: tenantUserHandler } f
376− pure f
377− void $ F.listen { port: Port 44932, host: Host "0.0.0.0" } fastify
378− pure fastify
379−
380− release = F.close
test/Simple.Spec.purs+16−16
@@ -10,59 +10,59 @@ type User = { id :: Int, name :: String, email :: String }
1010type CreateUser = { name :: String, email :: String }
1111
1212exampleGet :: forall ctx err. Om ctx (fetchError :: FetchError | err) User
13−exampleGet = get @User "https://api.example.com/users/42" {}
13+exampleGet = get @User {} "https://api.example.com/users/42"
1414
1515exampleGetWithAuth :: forall ctx err. Om ctx (fetchError :: FetchError | err) User
16−exampleGetWithAuth = get @User "https://api.example.com/users/42" { authorization: "Bearer abc123" }
16+exampleGetWithAuth = get @User { authorization: "Bearer abc123" } "https://api.example.com/users/42"
1717
1818exampleGetPlainText :: forall ctx err. Om ctx (fetchError :: FetchError | err) String
19−exampleGetPlainText = get @String "https://api.example.com/health" {}
19+exampleGetPlainText = get @String {} "https://api.example.com/health"
2020
2121exampleGetWithHeaders :: forall ctx err. Om ctx (fetchError :: FetchError | err) (FetchResponse User)
2222exampleGetWithHeaders = do
23− { headers, body: user } <- getWithHeaders @User "https://api.example.com/users/42" {}
23+ { headers, body: user } <- getWithHeaders @User {} "https://api.example.com/users/42"
2424 log $ "Got user: " <> user.name
2525 pure { headers, body: user }
2626
2727examplePost :: forall ctx err. Om ctx (fetchError :: FetchError | err) User
28−examplePost = post @User "https://api.example.com/users" {} { name: "Alice", email: "alice@example.com" }
28+examplePost = post @User {} "https://api.example.com/users" { name: "Alice", email: "alice@example.com" }
2929
3030examplePostFireAndForget :: forall ctx err. Om ctx (fetchError :: FetchError | err) Unit
31−examplePostFireAndForget = post_ "https://api.example.com/users" {} { name: "Alice", email: "alice@example.com" }
31+examplePostFireAndForget = post_ {} "https://api.example.com/users" { name: "Alice", email: "alice@example.com" }
3232
3333examplePut :: forall ctx err. Om ctx (fetchError :: FetchError | err) User
34−examplePut = put @User "https://api.example.com/users/42" {} { name: "Bob", email: "bob@example.com" }
34+examplePut = put @User {} "https://api.example.com/users/42" { name: "Bob", email: "bob@example.com" }
3535
3636examplePut_ :: forall ctx err. Om ctx (fetchError :: FetchError | err) Unit
37−examplePut_ = put_ "https://api.example.com/users/42" {} { name: "Bob", email: "bob@example.com" }
37+examplePut_ = put_ {} "https://api.example.com/users/42" { name: "Bob", email: "bob@example.com" }
3838
3939examplePatch :: forall ctx err. Om ctx (fetchError :: FetchError | err) User
40−examplePatch = patch @User "https://api.example.com/users/42" {} { name: "Bob" }
40+examplePatch = patch @User {} "https://api.example.com/users/42" { name: "Bob" }
4141
4242examplePatch_ :: forall ctx err. Om ctx (fetchError :: FetchError | err) Unit
43−examplePatch_ = patch_ "https://api.example.com/users/42" {} { name: "Bob" }
43+examplePatch_ = patch_ {} "https://api.example.com/users/42" { name: "Bob" }
4444
4545exampleDelete :: forall ctx err. Om ctx (fetchError :: FetchError | err) User
46−exampleDelete = delete @User "https://api.example.com/users/42" {}
46+exampleDelete = delete @User {} "https://api.example.com/users/42"
4747
4848exampleDelete_ :: forall ctx err. Om ctx (fetchError :: FetchError | err) Unit
49−exampleDelete_ = delete_ "https://api.example.com/users/42" {}
49+exampleDelete_ = delete_ {} "https://api.example.com/users/42"
5050
5151exampleHandleError :: forall ctx. Om ctx () Unit
5252exampleHandleError = do
53− user <- get @User "https://api.example.com/users/42" {}
53+ user <- get @User {} "https://api.example.com/users/42"
5454 # handleErrors { fetchError: \_ -> pure { id: 0, name: "unknown", email: "" } }
5555 log $ "Got user: " <> user.name
5656
5757exampleComposition :: forall ctx. Om ctx () Unit
5858exampleComposition = do
59− user <- post @User "https://api.example.com/users" {} { name: "Alice", email: "alice@example.com" }
59+ user <- post @User {} "https://api.example.com/users" { name: "Alice", email: "alice@example.com" }
6060 # handleErrors
6161 { fetchError: \e -> do
6262 log $ "Failed with status " <> show e.status <> ": " <> e.body
6363 pure { id: 0, name: "", email: "" }
6464 }
65− _ <- put @User ("https://api.example.com/users/" <> show user.id) {} { name: "Alice Updated", email: user.email }
65+ _ <- put @User {} ("https://api.example.com/users/" <> show user.id) { name: "Alice Updated", email: user.email }
6666 # handleErrors { fetchError: \_ -> pure user }
67− delete_ ("https://api.example.com/users/" <> show user.id) {}
67+ delete_ {} ("https://api.example.com/users/" <> show user.id)
6868 # handleErrors { fetchError: \_ -> pure unit }
test/SplitParams.Spec.purs+31−22
@@ -2,13 +2,22 @@ module SplitParams.Spec where
22
33import Prelude
44
5−import Test.Spec (Spec, describe, it)
6−import Test.Spec.Assertions (shouldEqual)
5+import Effect (Effect)
6+import Effect.Aff (Aff)
77import Yoga.Fetch.Om.SplitParams (splitParams)
8+import ViTest (ViTest, describe, test)
9+import ViTest.Expect (expectToBe)
810
9−spec :: Spec Unit
10−spec = describe "splitParams" do
11− it "splits path and query params" do
11+expectToEqual :: forall a. Eq a => a -> a -> Aff Unit
12+expectToEqual expected actual = expectToBe true (expected == actual)
13+
14+--------------------------------------------------------------------------------
15+-- SplitParams Tests
16+--------------------------------------------------------------------------------
17+
18+testSplitParams :: Effect ViTest
19+testSplitParams = describe "splitParams" $ do
20+ _ <- test "splits path and query params" do
1221 let
1322 allParams = { id: 42, limit: 10, offset: 20 }
1423 result =
@@ -17,12 +26,12 @@ spec = describe "splitParams" do
1726 , query :: { limit :: Int, offset :: Int }
1827 , body :: {}
1928 }
20− result.path.id `shouldEqual` 42
21− result.query.limit `shouldEqual` 10
22− result.query.offset `shouldEqual` 20
23− result.body `shouldEqual` {}
29+ expectToEqual 42 result.path.id
30+ expectToEqual 10 result.query.limit
31+ expectToEqual 20 result.query.offset
32+ expectToEqual {} result.body
2433
25− it "splits path and body params" do
34+ _ <- test "splits path and body params" do
2635 let
2736 allParams = { id: 42, name: "Alice", email: "alice@example.com" }
2837 result =
@@ -31,12 +40,12 @@ spec = describe "splitParams" do
3140 , query :: {}
3241 , body :: { name :: String, email :: String }
3342 }
34− result.path.id `shouldEqual` 42
35− result.query `shouldEqual` {}
36− result.body.name `shouldEqual` "Alice"
37− result.body.email `shouldEqual` "alice@example.com"
43+ expectToEqual 42 result.path.id
44+ expectToEqual {} result.query
45+ expectToEqual "Alice" result.body.name
46+ expectToEqual "alice@example.com" result.body.email
3847
39− it "splits all three param types" do
48+ _ <- test "splits all three param types" do
4049 let
4150 allParams =
4251 { id: 42
@@ -49,11 +58,11 @@ spec = describe "splitParams" do
4958 , query :: { limit :: Int }
5059 , body :: { name :: String }
5160 }
52− result.path.id `shouldEqual` 42
53− result.query.limit `shouldEqual` 10
54− result.body.name `shouldEqual` "Bob"
61+ expectToEqual 42 result.path.id
62+ expectToEqual 10 result.query.limit
63+ expectToEqual "Bob" result.body.name
5564
56− it "handles empty splits" do
65+ test "handles empty splits" do
5766 let
5867 allParams = { id: 42 }
5968 result =
@@ -62,6 +71,6 @@ spec = describe "splitParams" do
6271 , query :: {}
6372 , body :: {}
6473 }
65− result.path.id `shouldEqual` 42
66− result.query `shouldEqual` {}
67− result.body `shouldEqual` {}
74+ expectToEqual 42 result.path.id
75+ expectToEqual {} result.query
76+ expectToEqual {} result.body
test/StreamDecode.Spec.jsdeleted−1
@@ -1 +0,0 @@
1−export const uint8Array = (values) => new Uint8Array(values);
test/StreamDecode.Spec.pursdeleted−32
@@ -1,32 +0,0 @@
1−module StreamDecode.Spec where
2−
3−import Prelude
4−
5−import Data.ArrayBuffer.Types (Uint8Array)
6−import Data.String as String
7−import Effect.Aff (Aff)
8−import Effect.Class (liftEffect)
9−import Effect.Exception (throwException)
10−import Test.Spec (Spec, describe, it)
11−import Test.Spec.Assertions (shouldEqual)
12−import Yoga.Fetch.Om.StreamDecode (decodeStream)
13−import Yoga.Om (Om)
14−import Yoga.Om as Om
15−import Yoga.Om.Strom as Strom
16−
17−foreign import uint8Array :: Array Int -> Uint8Array
18−
19−runOm :: forall a. Om {} () a -> Aff a
20−runOm om = Om.runOm {} { exception: \err -> liftEffect (throwException err) } om
21−
22−spec :: Spec Unit
23−spec = describe "StreamDecode" do
24− it "preserves UTF-8 code points split across chunks" do
25− chunks <- runOm $
26− Strom.fromArray
27− [ uint8Array [ 0xe2 ]
28− , uint8Array [ 0x82, 0xac ]
29− ]
30− # decodeStream @String
31− # Strom.runCollect
32− String.joinWith "" chunks `shouldEqual` "€"
test/Test.Main.pursnew file+20
@@ -0,0 +1,20 @@
1+module Test.Main where
2+
3+import Prelude
4+
5+import BuildUrl.Spec as BuildUrl
6+import SplitParams.Spec as SplitParams
7+import Variant.Spec as Variant
8+import Effect (Effect)
9+import ViTest (ViTest, viTest)
10+
11+spec :: Effect ViTest
12+spec = do
13+ _ <- BuildUrl.testSubstitutePathParams
14+ _ <- BuildUrl.testAppendQueryParams
15+ _ <- BuildUrl.testBuildUrl
16+ _ <- SplitParams.testSplitParams
17+ Variant.testOnly
18+
19+main :: ViTest
20+main = viTest spec
test/Test/Main.pursdeleted−14
@@ -1,14 +0,0 @@
1−module Test.Main where
2−
3−import Prelude
4−
5−import Effect (Effect)
6−import Effect.Aff (launchAff_)
7−import Test.Spec.Discovery (discover)
8−import Test.Spec.Reporter (consoleReporter)
9−import Test.Spec.Runner (runSpec)
10−
11−main :: Effect Unit
12−main = launchAff_ do
13− specs <- discover ".*\\.Spec"
14− runSpec [ consoleReporter ] specs
test/TestServer.pursdeleted−38
@@ -1,38 +0,0 @@
1−module TestServer where
2−
3−import Prelude
4−
5−import Data.Int as Int
6−import Data.Maybe (fromMaybe)
7−import Effect (Effect)
8−import Effect.Aff.Class (liftAff)
9−import Effect.Class (liftEffect)
10−import Foreign (unsafeToForeign)
11−import Foreign.Object as FObject
12−import Promise (Promise)
13−import Promise.Aff (fromAff)
14−import Yoga.Fastify.Fastify as F
15−import Yoga.Fastify.Fastify (Fastify, Port(..), Host(..), RouteURL(..), StatusCode(..))
16−import Yoga.Fastify.Om (createOmFastify, getOm, requestParams)
17−
18−mkServer :: Effect Fastify
19−mkServer = do
20− fastify <- F.fastify {}
21− omApp <- createOmFastify {} fastify
22− getOm (RouteURL "/users/:id") handleGetUser omApp
23− pure fastify
24− where
25− handleGetUser reply = do
26− params <- requestParams
27− let idStr = fromMaybe "0" (FObject.lookup "id" params)
28− let id = fromMaybe 0 (Int.fromString idStr)
29− let body = unsafeToForeign { id, name: "User " <> idStr }
30− void $ F.status (StatusCode 200) reply # liftEffect
31− void $ F.header "content-type" "application/json" reply # liftEffect
32− F.sendJson body reply # liftAff
33−
34−listenServer :: Fastify -> Effect (Promise String)
35−listenServer fastify = fromAff $ F.listen { port: Port 44931, host: Host "0.0.0.0" } fastify
36−
37−closeServer :: Fastify -> Effect (Promise Unit)
38−closeServer fastify = fromAff $ F.close fastify
test/Variant.Spec.purs+11−6
@@ -4,16 +4,21 @@ import Prelude
44
55import Data.Variant (Variant)
66import Data.Variant as Variant
7−import Test.Spec (Spec, describe, it)
8−import Test.Spec.Assertions (shouldEqual)
7+import Effect (Effect)
8+import Effect.Aff (Aff)
99import Type.Proxy (Proxy(..))
10+import ViTest (ViTest, describe, test)
11+import ViTest.Expect (expectToBe)
1012import Yoga.Fetch.Om.Variant (only)
1113
12−spec :: Spec Unit
13−spec = describe "only" do
14− it "extracts single variant value - record" do
14+expectToEqual :: forall a. Eq a => a -> a -> Aff Unit
15+expectToEqual expected actual = expectToBe true (expected == actual)
16+
17+testOnly :: Effect ViTest
18+testOnly = describe "only" do
19+ test "extracts single variant value - record" do
1520 let
1621 variant :: Variant (ok :: { id :: Int, name :: String })
1722 variant = Variant.inj (Proxy :: _ "ok") { id: 42, name: "Alice" }
1823 result = only variant
19− result `shouldEqual` { id: 42, name: "Alice" }
24+ expectToEqual { id: 42, name: "Alice" } result
vitest.config.jsnew file+9
@@ -0,0 +1,9 @@
1+import { defineConfig } from "vitest/config";
2+
3+export default defineConfig({
4+ test: {
5+ include: ["output/Test.Main/index.js"],
6+ globals: true,
7+ environment: "jsdom",
8+ },
9+});