From 5d459f40c8eecb95ea7ee9ec1b31b13e504397e8 Mon Sep 17 00:00:00 2001 From: Orion Kindel Date: Sun, 1 Dec 2024 16:27:17 -0600 Subject: [PATCH] second commit --- .tool-versions | 2 + bun.lockb | Bin 0 -> 3169 bytes jsconfig.json | 6 +- rename.js | 14 + spago.lock | 1629 +++++++++++++++++++++++++++ spago.yaml | 13 + src/Data.String.Lower.purs | 21 + src/Tower.Request.Method.purs | 38 + src/Tower.Request.Parts.Body.purs | 18 + src/Tower.Request.Parts.Class.purs | 149 +++ src/Tower.Request.Parts.Method.purs | 62 + src/Tower.Request.Parts.Path.purs | 50 + src/Tower.Request.purs | 200 ++++ src/Tower.Response.Body.purs | 35 + src/Tower.Response.purs | 40 + src/Tower.Service.Class.purs | 2 + src/Tower.Web.Headers.js | 5 + src/Tower.Web.Headers.purs | 7 + src/Tower.Web.Request.js | 45 + src/Tower.Web.Request.purs | 19 + src/Tower.Web.Response.purs | 1 + 21 files changed, 2351 insertions(+), 5 deletions(-) create mode 100644 .tool-versions create mode 100755 bun.lockb create mode 100644 rename.js create mode 100644 spago.lock create mode 100644 src/Data.String.Lower.purs create mode 100644 src/Tower.Request.Method.purs create mode 100644 src/Tower.Request.Parts.Body.purs create mode 100644 src/Tower.Request.Parts.Class.purs create mode 100644 src/Tower.Request.Parts.Method.purs create mode 100644 src/Tower.Request.Parts.Path.purs create mode 100644 src/Tower.Request.purs create mode 100644 src/Tower.Response.Body.purs create mode 100644 src/Tower.Response.purs create mode 100644 src/Tower.Service.Class.purs create mode 100644 src/Tower.Web.Headers.js create mode 100644 src/Tower.Web.Headers.purs create mode 100644 src/Tower.Web.Request.js create mode 100644 src/Tower.Web.Request.purs create mode 100644 src/Tower.Web.Response.purs diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..5329811 --- /dev/null +++ b/.tool-versions @@ -0,0 +1,2 @@ +purescript 0.15.16-4 +bun 1.1.38 diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..357bea9602ea32a89a16335971505555c170c136 GIT binary patch literal 3169 zcmd^B2}~4c6dquyxKxotV~W&8aO1TzyNin)3tm8?w17f2BHAL%t^>>LIx{RsEn*5} z4PvoqJZj?sZ7tfMCN!V^=xT9BGy`)5=qO^_jc!Brw5eOG-=Y8{QLfY z=6&D3_vX#K7Zu5riUPBS;~AEBYSxtUYFIj(y`b2_*;t*$E|la;I;URkOHq`uYRh8j z$}6Um9S>?vse$jd8oqd$xA1@E6?1NdVJW&tG?mKpr;2aUmy>#!YGh+P9% zB?2CeA#Q4P;B6et=d9!~(U44~;m*g3pRn_M(hJBsf_WOP8uG!BWzA+`l7249#oAyo8(ymDf z=jYX}&1{(WWz&|viC1#J-7x)hae*^KvnYjbrx$MJ^N$`@@REGHc|%u3U&!W8?+RI* zwLLHGy@gw7z9enKs+Mt2i?x-L-#9 z!hi>Z{?=3K~?=+Z|k+7tgH1I{v{W+gI86?`r1PircGF#YfP7N zI>Op(vVycsP{Xq56D@UZUBym1Q^BjOOO-ZjbK>p&(gJnsl66f7CNHZFTeddl-l@cM zbGv$+(xEvAk4E0g+MaPfnmJjsb47)J9^+bn?A6GJT_2>6w{%ywD0oSIx$|(~qq!Sj z$TlAwwfxkLj61h0RTrn6J=MKgyJ1hV_QK@Ev5A*1mpDrzwiWkw&a4bq1v_**a_-(w z$^6--9_KjO*a*CTB_td!w?H244CE^ZC+`NT~!(f zQN?)a69${ZX1(C`Tp7BPie54{<;$#InwOnEa zKHrut2^?=t))*coA11EBHlb?yQ%Ak8pPZxjIa?se|6LgYNRi%gj)Z+LqlI}Dq` z3i!}iCl`($*-H6Bu7LAoZ5S4%8PF(?kQ%5q)87Q;^%~G+qRw5_F^G{X@;|430}<~? AZvX%Q literal 0 HcmV?d00001 diff --git a/jsconfig.json b/jsconfig.json index 4567f8f..361136a 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -14,10 +14,6 @@ }, "include": [ "./scripts/*.js", - "ui-serve/**/*.js", - "api/**/*.js", - "ui/**/*.js", - "aws/**/*.js", - "logging/**/*.js" + "src/**/*.js" ] } diff --git a/rename.js b/rename.js new file mode 100644 index 0000000..cab94de --- /dev/null +++ b/rename.js @@ -0,0 +1,14 @@ +import File from 'fs/promises' +import Path from 'path' + +const contents = new Map() + +const files = (await File.readdir('./src', {recursive: true})).map(a => Path.resolve('./src', a)).filter(a => a.endsWith('.purs') || a.endsWith('.js')) +for (const f of files) { + const fc = await File.readFile(f, 'utf8') + const fc_ = fc.replaceAll(/\bTower\b/g, 'Axon') + await File.writeFile(f, fc_) + const f_ = f.replace(/\bTower\b/, 'Axon') + await File.rename(f, f_) + console.log(`${f} -> ${f_}`) +} diff --git a/spago.lock b/spago.lock new file mode 100644 index 0000000..e4b8bfa --- /dev/null +++ b/spago.lock @@ -0,0 +1,1629 @@ +{ + "workspace": { + "packages": { + "tower": { + "path": "./", + "core": { + "dependencies": [ + "aff", + "argonaut-codecs", + "argonaut-core", + "console", + "effect", + "ezfetch", + "maybe", + "node-net", + "node-streams", + "nullable", + "prelude", + "strings", + "transformers", + "tuples", + "url-immutable", + "web-streams" + ], + "build_plan": [ + "aff", + "aff-promise", + "argonaut-codecs", + "argonaut-core", + "arraybuffer-types", + "arrays", + "b64", + "bifunctors", + "console", + "const", + "contravariant", + "control", + "datetime", + "distributive", + "effect", + "either", + "encoding", + "enums", + "exceptions", + "exists", + "ezfetch", + "filterable", + "foldable-traversable", + "foreign", + "foreign-object", + "functions", + "functors", + "gen", + "identity", + "integers", + "invariant", + "js-date", + "js-promise", + "lazy", + "lists", + "maybe", + "media-types", + "newtype", + "node-buffer", + "node-event-emitter", + "node-fs", + "node-net", + "node-path", + "node-streams", + "nonempty", + "now", + "nullable", + "numbers", + "options", + "ordered-collections", + "orders", + "parallel", + "partial", + "prelude", + "profunctor", + "record", + "refs", + "safe-coerce", + "simple-json", + "st", + "strings", + "stringutils", + "tailrec", + "transformers", + "tuples", + "type-equality", + "typelevel-prelude", + "unfoldable", + "unsafe-coerce", + "url-immutable", + "variant", + "web-dom", + "web-events", + "web-file", + "web-streams" + ] + }, + "test": { + "dependencies": [], + "build_plan": [] + } + } + }, + "package_set": { + "address": { + "registry": "61.2.0" + }, + "compiler": ">=0.15.15 <0.16.0", + "content": { + "abc-parser": "2.0.1", + "ace": "9.1.0", + "address-rfc2821": "0.1.1", + "aff": "8.0.0", + "aff-bus": "6.0.0", + "aff-coroutines": "9.0.0", + "aff-promise": "4.0.0", + "aff-retry": "2.0.0", + "affjax": "13.0.0", + "affjax-node": "1.0.0", + "affjax-web": "1.0.0", + "ansi": "7.0.0", + "apexcharts": "0.5.0", + "applicative-phases": "1.0.0", + "argonaut": "9.0.0", + "argonaut-aeson-generic": "0.4.1", + "argonaut-codecs": "9.1.0", + "argonaut-core": "7.0.0", + "argonaut-generic": "8.0.0", + "argonaut-traversals": "10.0.0", + "argparse-basic": "2.0.0", + "array-builder": "0.1.2", + "array-search": "0.6.0", + "arraybuffer": "13.2.0", + "arraybuffer-builder": "3.1.0", + "arraybuffer-types": "3.0.2", + "arrays": "7.3.0", + "arrays-extra": "0.6.1", + "arrays-zipper": "2.0.1", + "ask": "1.0.0", + "assert": "6.0.0", + "assert-multiple": "0.4.0", + "avar": "5.0.0", + "b64": "0.0.8", + "barbies": "1.0.1", + "barlow-lens": "0.9.0", + "bifunctors": "6.0.0", + "bigints": "7.0.1", + "bolson": "0.3.9", + "bookhound": "0.1.7", + "bower-json": "3.0.0", + "call-by-name": "4.0.1", + "canvas": "6.0.0", + "canvas-action": "9.0.0", + "cartesian": "1.0.6", + "catenable-lists": "7.0.0", + "cbor-stream": "1.3.0", + "chameleon": "1.0.0", + "chameleon-halogen": "1.0.3", + "chameleon-react-basic": "1.1.0", + "chameleon-styled": "2.5.0", + "chameleon-transformers": "1.0.0", + "channel": "1.0.0", + "checked-exceptions": "3.1.1", + "choku": "1.0.2", + "classless": "0.1.1", + "classless-arbitrary": "0.1.1", + "classless-decode-json": "0.1.1", + "classless-encode-json": "0.1.3", + "classnames": "2.0.0", + "codec": "6.1.0", + "codec-argonaut": "10.0.0", + "codec-json": "2.0.0", + "colors": "7.0.1", + "concur-core": "0.5.0", + "concur-react": "0.5.0", + "concurrent-queues": "3.0.0", + "console": "6.1.0", + "const": "6.0.0", + "contravariant": "6.0.0", + "control": "6.0.0", + "convertable-options": "1.0.0", + "coroutines": "7.0.0", + "css": "6.0.0", + "css-frameworks": "1.0.1", + "csv-stream": "2.3.0", + "data-mvc": "0.0.2", + "datetime": "6.1.0", + "datetime-parsing": "0.2.0", + "debounce": "0.1.0", + "debug": "6.0.2", + "decimals": "7.1.0", + "default-values": "1.0.1", + "deku": "0.9.23", + "deno": "0.0.5", + "dissect": "1.0.0", + "distributive": "6.0.0", + "dom-filereader": "7.0.0", + "dom-indexed": "12.0.0", + "dom-simple": "0.4.0", + "dotenv": "4.0.3", + "droplet": "0.6.0", + "dts": "1.0.0", + "dual-numbers": "1.0.3", + "dynamic-buffer": "3.0.1", + "echarts-simple": "0.0.1", + "effect": "4.0.0", + "either": "6.1.0", + "elmish": "0.13.0", + "elmish-enzyme": "0.1.1", + "elmish-hooks": "0.10.3", + "elmish-html": "0.9.0", + "elmish-testing-library": "0.3.2", + "email-validate": "7.0.0", + "encoding": "0.0.9", + "enums": "6.0.1", + "env-names": "0.4.0", + "error": "2.0.0", + "eta-conversion": "0.3.2", + "exceptions": "6.1.0", + "exists": "6.0.0", + "exitcodes": "4.0.0", + "expect-inferred": "3.0.0", + "ezfetch": "1.1.0", + "fahrtwind": "2.0.0", + "fallback": "0.1.0", + "fast-vect": "1.2.0", + "fetch": "4.1.0", + "fetch-argonaut": "1.0.1", + "fetch-core": "5.1.0", + "fetch-yoga-json": "1.1.0", + "ffi-simple": "0.5.1", + "fft-js": "0.1.0", + "filterable": "5.0.0", + "fix-functor": "0.1.0", + "fixed-points": "7.0.0", + "fixed-precision": "5.0.0", + "flame": "1.3.0", + "float32": "2.0.0", + "fmt": "0.2.1", + "foldable-traversable": "6.0.0", + "foldable-traversable-extra": "0.0.6", + "foreign": "7.0.0", + "foreign-object": "4.1.0", + "foreign-readwrite": "3.4.0", + "forgetmenot": "0.1.0", + "fork": "6.0.0", + "form-urlencoded": "7.0.0", + "formatters": "7.0.0", + "framer-motion": "1.0.1", + "free": "7.1.0", + "freeap": "7.0.0", + "freer-free": "0.0.1", + "freet": "7.0.0", + "functions": "6.0.0", + "functor1": "3.0.0", + "functors": "5.0.0", + "fuzzy": "0.4.0", + "gen": "4.0.0", + "generate-values": "1.0.1", + "generic-router": "0.0.1", + "geojson": "0.0.5", + "geometria": "2.2.0", + "gojs": "0.1.1", + "grain": "3.0.0", + "grain-router": "3.0.0", + "grain-virtualized": "3.0.0", + "graphs": "8.1.0", + "group": "4.1.1", + "halogen": "7.0.0", + "halogen-bootstrap5": "5.3.2", + "halogen-canvas": "1.0.0", + "halogen-css": "10.0.0", + "halogen-echarts-simple": "0.0.4", + "halogen-formless": "4.0.3", + "halogen-helix": "1.0.1", + "halogen-hooks": "0.6.3", + "halogen-hooks-extra": "0.9.0", + "halogen-infinite-scroll": "1.1.0", + "halogen-store": "0.5.4", + "halogen-storybook": "2.0.0", + "halogen-subscriptions": "2.0.0", + "halogen-svg-elems": "8.0.0", + "halogen-typewriter": "1.0.4", + "halogen-vdom": "8.0.0", + "halogen-vdom-string-renderer": "0.5.0", + "halogen-xterm": "2.0.0", + "heckin": "2.0.1", + "heterogeneous": "0.6.0", + "homogeneous": "0.4.0", + "http-methods": "6.0.0", + "httpurple": "4.0.0", + "huffman": "0.4.0", + "humdrum": "0.0.1", + "hyrule": "2.3.8", + "identity": "6.0.0", + "identy": "4.0.1", + "indexed-db": "1.0.0", + "indexed-monad": "3.0.0", + "int64": "3.0.0", + "integers": "6.0.0", + "interpolate": "5.0.2", + "intersection-observer": "1.0.1", + "invariant": "6.0.0", + "jarilo": "1.0.1", + "jelly": "0.10.0", + "jelly-router": "0.3.0", + "jelly-signal": "0.4.0", + "jest": "1.0.0", + "js-abort-controller": "1.0.0", + "js-bigints": "2.2.1", + "js-date": "8.0.0", + "js-fetch": "0.2.1", + "js-fileio": "3.0.0", + "js-intl": "1.1.4", + "js-iterators": "0.1.1", + "js-maps": "0.1.2", + "js-promise": "1.0.0", + "js-promise-aff": "1.0.0", + "js-timers": "6.1.0", + "js-uri": "3.1.0", + "jsdom": "1.0.0", + "json": "1.1.0", + "json-codecs": "5.0.0", + "justifill": "0.5.0", + "jwt": "0.0.9", + "labeled-data": "0.2.0", + "language-cst-parser": "0.14.0", + "lazy": "6.0.0", + "lazy-joe": "1.0.0", + "lcg": "4.0.0", + "leibniz": "5.0.0", + "leveldb": "1.0.1", + "liminal": "1.0.1", + "linalg": "6.0.0", + "lists": "7.0.0", + "literals": "1.0.2", + "logging": "3.0.0", + "logging-journald": "0.4.0", + "lumi-components": "18.0.0", + "machines": "7.0.0", + "maps-eager": "0.5.0", + "marionette": "1.0.0", + "marionette-react-basic-hooks": "0.1.1", + "marked": "0.1.0", + "matrices": "5.0.1", + "matryoshka": "1.0.0", + "maybe": "6.0.0", + "media-types": "6.0.0", + "meowclient": "1.0.0", + "midi": "4.0.0", + "milkis": "9.0.0", + "minibench": "4.0.1", + "mmorph": "7.0.0", + "monad-control": "5.0.0", + "monad-logger": "1.3.1", + "monad-loops": "0.5.0", + "monad-unlift": "1.0.1", + "monoid-extras": "0.0.1", + "monoidal": "0.16.0", + "morello": "0.4.0", + "mote": "3.0.0", + "motsunabe": "2.0.0", + "mvc": "0.0.1", + "mysql": "6.0.1", + "n3": "0.1.0", + "nano-id": "1.1.0", + "nanoid": "0.1.0", + "naturals": "3.0.0", + "nested-functor": "0.2.1", + "newtype": "5.0.0", + "nextjs": "0.1.1", + "nextui": "0.2.0", + "node-buffer": "9.0.0", + "node-child-process": "11.1.0", + "node-event-emitter": "3.0.0", + "node-execa": "5.0.0", + "node-fs": "9.2.0", + "node-glob-basic": "1.3.0", + "node-http": "9.1.0", + "node-http2": "1.1.1", + "node-human-signals": "1.0.0", + "node-net": "5.1.0", + "node-os": "5.1.0", + "node-path": "5.0.0", + "node-process": "11.2.0", + "node-readline": "8.1.1", + "node-sqlite3": "8.0.0", + "node-stream-pipes": "2.1.6", + "node-streams": "9.0.0", + "node-tls": "0.3.1", + "node-url": "7.0.1", + "node-zlib": "0.4.0", + "nonempty": "7.0.0", + "now": "6.0.0", + "npm-package-json": "2.0.0", + "nullable": "6.0.0", + "numberfield": "0.2.2", + "numbers": "9.0.1", + "oak": "3.1.1", + "oak-debug": "1.2.2", + "object-maps": "0.3.0", + "ocarina": "1.5.4", + "oooooooooorrrrrrrmm-lib": "0.0.1", + "open-colors-scales-and-schemes": "1.0.0", + "open-folds": "6.4.0", + "open-foreign-generic": "11.0.3", + "open-memoize": "6.2.0", + "open-mkdirp-aff": "1.2.0", + "open-pairing": "6.2.0", + "open-smolder": "12.0.2", + "options": "7.0.0", + "optparse": "5.0.1", + "ordered-collections": "3.2.0", + "ordered-set": "0.4.0", + "orders": "6.0.0", + "owoify": "1.2.0", + "pairs": "9.0.1", + "parallel": "7.0.0", + "parsing": "10.2.0", + "parsing-dataview": "3.2.4", + "partial": "4.0.0", + "pathy": "9.0.0", + "pha": "0.13.0", + "phaser": "0.7.0", + "phylio": "1.1.2", + "pipes": "8.0.0", + "pirates-charm": "0.0.1", + "pmock": "0.9.0", + "point-free": "1.0.0", + "pointed-list": "0.5.1", + "polymorphic-vectors": "4.0.0", + "posix-types": "6.0.0", + "postgresql": "2.0.20", + "precise": "6.0.0", + "precise-datetime": "7.0.0", + "prelude": "6.0.1", + "prettier-printer": "3.0.0", + "printf": "0.1.0", + "priority-queue": "0.1.2", + "profunctor": "6.0.1", + "profunctor-lenses": "8.0.0", + "protobuf": "4.4.0", + "psa-utils": "8.0.0", + "psci-support": "6.0.0", + "punycode": "1.0.0", + "qualified-do": "2.2.0", + "quantities": "12.2.0", + "quickcheck": "8.0.1", + "quickcheck-combinators": "0.1.3", + "quickcheck-laws": "7.0.0", + "quickcheck-utf8": "0.0.0", + "random": "6.0.0", + "rationals": "6.0.0", + "rdf": "0.1.0", + "react": "11.0.0", + "react-aria": "0.2.0", + "react-basic": "17.0.0", + "react-basic-classic": "3.0.0", + "react-basic-dnd": "10.1.0", + "react-basic-dom": "7.0.0", + "react-basic-dom-beta": "0.1.1", + "react-basic-emotion": "7.1.0", + "react-basic-hooks": "8.2.0", + "react-basic-storybook": "2.0.0", + "react-dom": "8.0.0", + "react-halo": "3.0.0", + "react-icons": "1.1.5", + "react-markdown": "0.1.0", + "react-testing-library": "4.0.1", + "react-virtuoso": "1.0.0", + "reactix": "0.6.1", + "read": "1.0.1", + "recharts": "1.1.0", + "record": "4.0.0", + "record-extra": "5.0.1", + "record-ptional-fields": "0.1.2", + "record-studio": "1.0.4", + "refs": "6.0.0", + "remotedata": "5.0.1", + "repr": "0.5.0", + "resize-observer": "1.0.0", + "resource": "2.0.1", + "resourcet": "1.0.0", + "result": "1.0.3", + "return": "0.2.0", + "ring-modules": "5.0.1", + "rito": "0.3.4", + "roman": "0.4.0", + "rough-notation": "1.0.2", + "routing": "11.0.0", + "routing-duplex": "0.7.0", + "run": "5.0.0", + "safe-coerce": "2.0.0", + "safely": "4.0.1", + "school-of-music": "1.3.0", + "selection-foldable": "0.2.0", + "selective-functors": "1.0.1", + "semirings": "7.0.0", + "signal": "13.0.0", + "simple-emitter": "3.0.1", + "simple-i18n": "2.0.1", + "simple-json": "9.0.0", + "simple-json-generics": "0.2.1", + "simple-ulid": "3.0.0", + "sized-matrices": "1.0.0", + "sized-vectors": "5.0.2", + "slug": "3.1.0", + "small-ffi": "4.0.1", + "soundfonts": "4.1.0", + "sparse-matrices": "2.0.1", + "sparse-polynomials": "3.0.1", + "spec": "8.1.1", + "spec-discovery": "8.4.0", + "spec-mocha": "5.1.1", + "spec-node": "0.0.3", + "spec-quickcheck": "5.0.2", + "spec-reporter-xunit": "0.7.1", + "splitmix": "2.1.0", + "ssrs": "1.0.0", + "st": "6.2.0", + "statistics": "0.3.2", + "strictlypositiveint": "1.0.1", + "string-parsers": "8.0.0", + "strings": "6.0.1", + "strings-extra": "4.0.0", + "stringutils": "0.0.12", + "substitute": "0.2.3", + "supply": "0.2.0", + "svg-parser": "3.0.0", + "systemd-journald": "0.3.0", + "tagged": "4.0.2", + "tailrec": "6.1.0", + "tecton": "0.2.1", + "tecton-halogen": "0.2.0", + "test-unit": "17.0.0", + "thermite": "6.3.1", + "thermite-dom": "0.3.1", + "these": "6.0.0", + "threading": "0.0.3", + "tldr": "0.0.0", + "toestand": "0.9.0", + "transformation-matrix": "1.0.1", + "transformers": "6.1.0", + "tree-rose": "4.0.2", + "ts-bridge": "4.0.0", + "tuples": "7.0.0", + "two-or-more": "1.0.0", + "type-equality": "4.0.1", + "typedenv": "2.0.1", + "typelevel": "6.0.0", + "typelevel-lists": "2.1.0", + "typelevel-peano": "1.0.1", + "typelevel-prelude": "7.0.0", + "typelevel-regex": "0.0.3", + "typelevel-rows": "0.1.0", + "typisch": "0.4.0", + "uint": "7.0.0", + "ulid": "3.0.1", + "uncurried-transformers": "1.1.0", + "undefined": "2.0.0", + "undefined-is-not-a-problem": "1.1.0", + "unfoldable": "6.0.0", + "unicode": "6.0.0", + "unique": "0.6.1", + "unlift": "1.0.1", + "unordered-collections": "3.1.0", + "unsafe-coerce": "6.0.0", + "unsafe-reference": "5.0.0", + "untagged-to-tagged": "0.1.4", + "untagged-union": "1.0.0", + "uri": "9.0.0", + "url-immutable": "1.0.0", + "uuid": "9.0.0", + "uuidv4": "1.0.0", + "validation": "6.0.0", + "variant": "8.0.0", + "variant-encodings": "2.0.0", + "vectorfield": "1.0.1", + "vectors": "2.1.0", + "versions": "7.0.0", + "visx": "0.0.2", + "web-clipboard": "6.0.0", + "web-cssom": "2.0.0", + "web-cssom-view": "0.1.0", + "web-dom": "6.0.0", + "web-dom-parser": "8.0.0", + "web-dom-xpath": "3.0.0", + "web-encoding": "3.0.0", + "web-events": "4.0.0", + "web-fetch": "4.0.1", + "web-file": "4.0.0", + "web-geometry": "0.1.0", + "web-html": "4.1.0", + "web-pointerevents": "2.0.0", + "web-proletarian": "1.0.0", + "web-promise": "3.2.0", + "web-resize-observer": "2.1.0", + "web-router": "1.0.0", + "web-socket": "4.0.0", + "web-storage": "5.0.0", + "web-streams": "4.0.0", + "web-touchevents": "4.0.0", + "web-uievents": "5.0.0", + "web-url": "2.0.0", + "web-workers": "1.1.0", + "web-xhr": "5.0.1", + "webextension-polyfill": "0.1.0", + "webgpu": "0.0.1", + "which": "2.0.0", + "xterm": "1.0.0", + "yoga-fetch": "1.0.1", + "yoga-json": "5.1.0", + "yoga-om": "0.1.0", + "yoga-postgres": "6.0.0", + "yoga-subtlecrypto": "0.1.0", + "yoga-tree": "1.0.0", + "z3": "0.0.2", + "zipperarray": "2.0.0" + } + }, + "extra_packages": {} + }, + "packages": { + "aff": { + "type": "registry", + "version": "8.0.0", + "integrity": "sha256-5MmdI4+0RHBtSBy+YlU3/Cq4R5W2ih3OaRedJIrVHdk=", + "dependencies": [ + "bifunctors", + "control", + "datetime", + "effect", + "either", + "exceptions", + "foldable-traversable", + "functions", + "maybe", + "newtype", + "parallel", + "prelude", + "refs", + "tailrec", + "transformers", + "unsafe-coerce" + ] + }, + "aff-promise": { + "type": "registry", + "version": "4.0.0", + "integrity": "sha256-Kq5EupbUpXeUXx4JqGQE7/RTTz/H6idzWhsocwlEFhM=", + "dependencies": [ + "aff", + "foreign" + ] + }, + "argonaut-codecs": { + "type": "registry", + "version": "9.1.0", + "integrity": "sha256-N6efXByUeg848ompEqJfVvZuZPfdRYDGlTDFn0G0Oh8=", + "dependencies": [ + "argonaut-core", + "arrays", + "effect", + "foreign-object", + "identity", + "integers", + "maybe", + "nonempty", + "ordered-collections", + "prelude", + "record" + ] + }, + "argonaut-core": { + "type": "registry", + "version": "7.0.0", + "integrity": "sha256-RC82GfAjItydxrO24cdX373KHVZiLqybu19b5X8u7B4=", + "dependencies": [ + "arrays", + "control", + "either", + "foreign-object", + "functions", + "gen", + "maybe", + "nonempty", + "prelude", + "strings", + "tailrec" + ] + }, + "arraybuffer-types": { + "type": "registry", + "version": "3.0.2", + "integrity": "sha256-mQKokysYVkooS4uXbO+yovmV/s8b138Ws3zQvOwIHRA=", + "dependencies": [] + }, + "arrays": { + "type": "registry", + "version": "7.3.0", + "integrity": "sha256-tmcklBlc/muUtUfr9RapdCPwnlQeB3aSrC4dK85gQlc=", + "dependencies": [ + "bifunctors", + "control", + "foldable-traversable", + "functions", + "maybe", + "nonempty", + "partial", + "prelude", + "safe-coerce", + "st", + "tailrec", + "tuples", + "unfoldable", + "unsafe-coerce" + ] + }, + "b64": { + "type": "registry", + "version": "0.0.8", + "integrity": "sha256-3QkOhnewZIqhfn0wIU6Zde6Q/LfrS59kgSOcQQaG0gM=", + "dependencies": [ + "arraybuffer-types", + "either", + "encoding", + "enums", + "exceptions", + "functions", + "partial", + "prelude", + "strings" + ] + }, + "bifunctors": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-/gZwC9YhNxZNQpnHa5BIYerCGM2jeX9ukZiEvYxm5Nw=", + "dependencies": [ + "const", + "either", + "newtype", + "prelude", + "tuples" + ] + }, + "console": { + "type": "registry", + "version": "6.1.0", + "integrity": "sha256-CxmAzjgyuGDmt9FZW51VhV6rBPwR6o0YeKUzA9rSzcM=", + "dependencies": [ + "effect", + "prelude" + ] + }, + "const": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-tNrxDW8D8H4jdHE2HiPzpLy08zkzJMmGHdRqt5BQuTc=", + "dependencies": [ + "invariant", + "newtype", + "prelude" + ] + }, + "contravariant": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-TP+ooAp3vvmdjfQsQJSichF5B4BPDHp3wAJoWchip6c=", + "dependencies": [ + "const", + "either", + "newtype", + "prelude", + "tuples" + ] + }, + "control": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-sH7Pg9E96JCPF9PIA6oQ8+BjTyO/BH1ZuE/bOcyj4Jk=", + "dependencies": [ + "newtype", + "prelude" + ] + }, + "datetime": { + "type": "registry", + "version": "6.1.0", + "integrity": "sha256-g/5X5BBegQWLpI9IWD+sY6mcaYpzzlW5lz5NBzaMtyI=", + "dependencies": [ + "bifunctors", + "control", + "either", + "enums", + "foldable-traversable", + "functions", + "gen", + "integers", + "lists", + "maybe", + "newtype", + "numbers", + "ordered-collections", + "partial", + "prelude", + "tuples" + ] + }, + "distributive": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-HTDdmEnzigMl+02SJB88j+gAXDx9VKsbvR4MJGDPbOQ=", + "dependencies": [ + "identity", + "newtype", + "prelude", + "tuples", + "type-equality" + ] + }, + "effect": { + "type": "registry", + "version": "4.0.0", + "integrity": "sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M=", + "dependencies": [ + "prelude" + ] + }, + "either": { + "type": "registry", + "version": "6.1.0", + "integrity": "sha256-6hgTPisnMWVwQivOu2PKYcH8uqjEOOqDyaDQVUchTpY=", + "dependencies": [ + "control", + "invariant", + "maybe", + "prelude" + ] + }, + "encoding": { + "type": "registry", + "version": "0.0.9", + "integrity": "sha256-vtyUO06Jww8pFl4wRekPd1YpJl2XuQXcaNXQgHtG8Tk=", + "dependencies": [ + "arraybuffer-types", + "effect", + "either", + "exceptions", + "functions", + "prelude" + ] + }, + "enums": { + "type": "registry", + "version": "6.0.1", + "integrity": "sha256-HWaD73JFLorc4A6trKIRUeDMdzE+GpkJaEOM1nTNkC8=", + "dependencies": [ + "control", + "either", + "gen", + "maybe", + "newtype", + "nonempty", + "partial", + "prelude", + "tuples", + "unfoldable" + ] + }, + "exceptions": { + "type": "registry", + "version": "6.1.0", + "integrity": "sha256-K0T89IHtF3vBY7eSAO7eDOqSb2J9kZGAcDN5+IKsF8E=", + "dependencies": [ + "effect", + "either", + "maybe", + "prelude" + ] + }, + "exists": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-A0JQHpTfo1dNOj9U5/Fd3xndlRSE0g2IQWOGor2yXn8=", + "dependencies": [ + "unsafe-coerce" + ] + }, + "ezfetch": { + "type": "registry", + "version": "1.1.0", + "integrity": "sha256-EA8KHFS6PMuOdZiFt7h0E5D5yCf7/sWAfsRJoCE/xP8=", + "dependencies": [ + "aff", + "aff-promise", + "arraybuffer-types", + "b64", + "bifunctors", + "effect", + "either", + "exceptions", + "foldable-traversable", + "foreign", + "foreign-object", + "integers", + "maybe", + "newtype", + "node-buffer", + "node-streams", + "nullable", + "numbers", + "ordered-collections", + "prelude", + "record", + "simple-json", + "transformers", + "tuples", + "typelevel-prelude", + "unsafe-coerce", + "url-immutable", + "web-file", + "web-streams" + ] + }, + "filterable": { + "type": "registry", + "version": "5.0.0", + "integrity": "sha256-cCojJHRnTmpY1j1kegI4CFwghdQ2Fm/8dzM8IlC+lng=", + "dependencies": [ + "arrays", + "either", + "foldable-traversable", + "identity", + "lists", + "ordered-collections" + ] + }, + "foldable-traversable": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-fLeqRYM4jUrZD5H4WqcwUgzU7XfYkzO4zhgtNc3jcWM=", + "dependencies": [ + "bifunctors", + "const", + "control", + "either", + "functors", + "identity", + "maybe", + "newtype", + "orders", + "prelude", + "tuples" + ] + }, + "foreign": { + "type": "registry", + "version": "7.0.0", + "integrity": "sha256-1ORiqoS3HW+qfwSZAppHPWy4/6AQysxZ2t29jcdUMNA=", + "dependencies": [ + "either", + "functions", + "identity", + "integers", + "lists", + "maybe", + "prelude", + "strings", + "transformers" + ] + }, + "foreign-object": { + "type": "registry", + "version": "4.1.0", + "integrity": "sha256-q24okj6mT+yGHYQ+ei/pYPj5ih6sTbu7eDv/WU56JVo=", + "dependencies": [ + "arrays", + "foldable-traversable", + "functions", + "gen", + "lists", + "maybe", + "prelude", + "st", + "tailrec", + "tuples", + "typelevel-prelude", + "unfoldable" + ] + }, + "functions": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-adMyJNEnhGde2unHHAP79gPtlNjNqzgLB8arEOn9hLI=", + "dependencies": [ + "prelude" + ] + }, + "functors": { + "type": "registry", + "version": "5.0.0", + "integrity": "sha256-zfPWWYisbD84MqwpJSZFlvM6v86McM68ob8p9s27ywU=", + "dependencies": [ + "bifunctors", + "const", + "contravariant", + "control", + "distributive", + "either", + "invariant", + "maybe", + "newtype", + "prelude", + "profunctor", + "tuples", + "unsafe-coerce" + ] + }, + "gen": { + "type": "registry", + "version": "4.0.0", + "integrity": "sha256-f7yzAXWwr+xnaqEOcvyO3ezKdoes8+WXWdXIHDBCAPI=", + "dependencies": [ + "either", + "foldable-traversable", + "identity", + "maybe", + "newtype", + "nonempty", + "prelude", + "tailrec", + "tuples", + "unfoldable" + ] + }, + "identity": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-4wY0XZbAksjY6UAg99WkuKyJlQlWAfTi2ssadH0wVMY=", + "dependencies": [ + "control", + "invariant", + "newtype", + "prelude" + ] + }, + "integers": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-sf+sK26R1hzwl3NhXR7WAu9zCDjQnfoXwcyGoseX158=", + "dependencies": [ + "maybe", + "numbers", + "prelude" + ] + }, + "invariant": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-RGWWyYrz0Hs1KjPDA+87Kia67ZFBhfJ5lMGOMCEFoLo=", + "dependencies": [ + "control", + "prelude" + ] + }, + "js-date": { + "type": "registry", + "version": "8.0.0", + "integrity": "sha256-6TVF4DWg5JL+jRAsoMssYw8rgOVALMUHT1CuNZt8NRo=", + "dependencies": [ + "datetime", + "effect", + "exceptions", + "foreign", + "integers", + "now" + ] + }, + "js-promise": { + "type": "registry", + "version": "1.0.0", + "integrity": "sha256-kXNo5g9RJgPdrTuKRe5oG2kBIwPp+j5VDPDplqZBJzQ=", + "dependencies": [ + "effect", + "exceptions", + "foldable-traversable", + "functions", + "maybe", + "prelude" + ] + }, + "lazy": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-lMsfFOnlqfe4KzRRiW8ot5ge6HtcU3Eyh2XkXcP5IgU=", + "dependencies": [ + "control", + "foldable-traversable", + "invariant", + "prelude" + ] + }, + "lists": { + "type": "registry", + "version": "7.0.0", + "integrity": "sha256-EKF15qYqucuXP2lT/xPxhqy58f0FFT6KHdIB/yBOayI=", + "dependencies": [ + "bifunctors", + "control", + "foldable-traversable", + "lazy", + "maybe", + "newtype", + "nonempty", + "partial", + "prelude", + "tailrec", + "tuples", + "unfoldable" + ] + }, + "maybe": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-5cCIb0wPwbat2PRkQhUeZO0jcAmf8jCt2qE0wbC3v2Q=", + "dependencies": [ + "control", + "invariant", + "newtype", + "prelude" + ] + }, + "media-types": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-n/4FoGBasbVSYscGVRSyBunQ6CZbL3jsYL+Lp01mc9k=", + "dependencies": [ + "newtype", + "prelude" + ] + }, + "newtype": { + "type": "registry", + "version": "5.0.0", + "integrity": "sha256-gdrQu8oGe9eZE6L3wOI8ql/igOg+zEGB5ITh2g+uttw=", + "dependencies": [ + "prelude", + "safe-coerce" + ] + }, + "node-buffer": { + "type": "registry", + "version": "9.0.0", + "integrity": "sha256-PWE2DJ5ruBLCmeA/fUiuySEFmUJ/VuRfyrnCuVZBlu4=", + "dependencies": [ + "arraybuffer-types", + "effect", + "maybe", + "nullable", + "st", + "unsafe-coerce" + ] + }, + "node-event-emitter": { + "type": "registry", + "version": "3.0.0", + "integrity": "sha256-Qw0MjsT4xRH2j2i4K8JmRjcMKnH5z1Cw39t00q4LE4w=", + "dependencies": [ + "effect", + "either", + "functions", + "maybe", + "nullable", + "prelude", + "unsafe-coerce" + ] + }, + "node-fs": { + "type": "registry", + "version": "9.2.0", + "integrity": "sha256-Sg0vkXycEzkEerX6hLccz21Ygd9w1+QSk1thotRZPGI=", + "dependencies": [ + "datetime", + "effect", + "either", + "enums", + "exceptions", + "functions", + "integers", + "js-date", + "maybe", + "node-buffer", + "node-path", + "node-streams", + "nullable", + "partial", + "prelude", + "strings", + "unsafe-coerce" + ] + }, + "node-net": { + "type": "registry", + "version": "5.1.0", + "integrity": "sha256-WnYf9RoPBJrTUAEkzc0NbIhOqN0lKbhyDf0JNgZjAKY=", + "dependencies": [ + "effect", + "either", + "exceptions", + "foreign", + "maybe", + "node-buffer", + "node-event-emitter", + "node-fs", + "nullable", + "options", + "prelude", + "transformers" + ] + }, + "node-path": { + "type": "registry", + "version": "5.0.0", + "integrity": "sha256-pd82nQ+2l5UThzaxPdKttgDt7xlsgIDLpPG0yxDEdyE=", + "dependencies": [ + "effect" + ] + }, + "node-streams": { + "type": "registry", + "version": "9.0.0", + "integrity": "sha256-2n6dq7YWleTDmD1Kur/ul7Cn08IvWrScgPf+0PgX2TQ=", + "dependencies": [ + "aff", + "effect", + "either", + "exceptions", + "node-buffer", + "node-event-emitter", + "nullable", + "prelude" + ] + }, + "nonempty": { + "type": "registry", + "version": "7.0.0", + "integrity": "sha256-54ablJZUHGvvlTJzi3oXyPCuvY6zsrWJuH/dMJ/MFLs=", + "dependencies": [ + "control", + "foldable-traversable", + "maybe", + "prelude", + "tuples", + "unfoldable" + ] + }, + "now": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-xZ7x37ZMREfs6GCDw/h+FaKHV/3sPWmtqBZRGTxybQY=", + "dependencies": [ + "datetime", + "effect" + ] + }, + "nullable": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-yiGBVl3AD+Guy4kNWWeN+zl1gCiJK+oeIFtZtPCw4+o=", + "dependencies": [ + "effect", + "functions", + "maybe" + ] + }, + "numbers": { + "type": "registry", + "version": "9.0.1", + "integrity": "sha256-/9M6aeMDBdB4cwYDeJvLFprAHZ49EbtKQLIJsneXLIk=", + "dependencies": [ + "functions", + "maybe" + ] + }, + "options": { + "type": "registry", + "version": "7.0.0", + "integrity": "sha256-treC6h+jvzcWhplPaF/aMENCOx+JGk+ysa5pL1BGHtg=", + "dependencies": [ + "contravariant", + "foreign", + "foreign-object", + "maybe", + "tuples" + ] + }, + "ordered-collections": { + "type": "registry", + "version": "3.2.0", + "integrity": "sha256-o9jqsj5rpJmMdoe/zyufWHFjYYFTTsJpgcuCnqCO6PM=", + "dependencies": [ + "arrays", + "foldable-traversable", + "gen", + "lists", + "maybe", + "partial", + "prelude", + "st", + "tailrec", + "tuples", + "unfoldable" + ] + }, + "orders": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-nBA0g3/ai0euH8q9pSbGqk53W2q6agm/dECZTHcoink=", + "dependencies": [ + "newtype", + "prelude" + ] + }, + "parallel": { + "type": "registry", + "version": "7.0.0", + "integrity": "sha256-gUC9i4Txnx9K9RcMLsjujbwZz6BB1bnE2MLvw4GIw5o=", + "dependencies": [ + "control", + "effect", + "either", + "foldable-traversable", + "functors", + "maybe", + "newtype", + "prelude", + "profunctor", + "refs", + "transformers" + ] + }, + "partial": { + "type": "registry", + "version": "4.0.0", + "integrity": "sha256-fwXerld6Xw1VkReh8yeQsdtLVrjfGiVuC5bA1Wyo/J4=", + "dependencies": [] + }, + "prelude": { + "type": "registry", + "version": "6.0.1", + "integrity": "sha256-o8p6SLYmVPqzXZhQFd2hGAWEwBoXl1swxLG/scpJ0V0=", + "dependencies": [] + }, + "profunctor": { + "type": "registry", + "version": "6.0.1", + "integrity": "sha256-E58hSYdJvF2Qjf9dnWLPlJKh2Z2fLfFLkQoYi16vsFk=", + "dependencies": [ + "control", + "distributive", + "either", + "exists", + "invariant", + "newtype", + "prelude", + "tuples" + ] + }, + "record": { + "type": "registry", + "version": "4.0.0", + "integrity": "sha256-Za5U85bTRJEfGK5Sk4hM41oXy84YQI0I8TL3WUn1Qzg=", + "dependencies": [ + "functions", + "prelude", + "unsafe-coerce" + ] + }, + "refs": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-Vgwne7jIbD3ZMoLNNETLT8Litw6lIYo3MfYNdtYWj9s=", + "dependencies": [ + "effect", + "prelude" + ] + }, + "safe-coerce": { + "type": "registry", + "version": "2.0.0", + "integrity": "sha256-a1ibQkiUcbODbLE/WAq7Ttbbh9ex+x33VCQ7GngKudU=", + "dependencies": [ + "unsafe-coerce" + ] + }, + "simple-json": { + "type": "registry", + "version": "9.0.0", + "integrity": "sha256-K3RJaThqsszTd+TEklzZmAdDqvIHWgXIfKqlsoykU1c=", + "dependencies": [ + "arrays", + "exceptions", + "foreign", + "foreign-object", + "nullable", + "prelude", + "record", + "typelevel-prelude", + "variant" + ] + }, + "st": { + "type": "registry", + "version": "6.2.0", + "integrity": "sha256-z9X0WsOUlPwNx9GlCC+YccCyz8MejC8Wb0C4+9fiBRY=", + "dependencies": [ + "partial", + "prelude", + "tailrec", + "unsafe-coerce" + ] + }, + "strings": { + "type": "registry", + "version": "6.0.1", + "integrity": "sha256-WssD3DbX4OPzxSdjvRMX0yvc9+pS7n5gyPv5I2Trb7k=", + "dependencies": [ + "arrays", + "control", + "either", + "enums", + "foldable-traversable", + "gen", + "integers", + "maybe", + "newtype", + "nonempty", + "partial", + "prelude", + "tailrec", + "tuples", + "unfoldable", + "unsafe-coerce" + ] + }, + "stringutils": { + "type": "registry", + "version": "0.0.12", + "integrity": "sha256-t63QWBlp49U0nRqUcFryKflSJsNKGTQAHKjn24/+ooI=", + "dependencies": [ + "arrays", + "integers", + "maybe", + "partial", + "prelude", + "strings" + ] + }, + "tailrec": { + "type": "registry", + "version": "6.1.0", + "integrity": "sha256-Xx19ECVDRrDWpz9D2GxQHHV89vd61dnXxQm0IcYQHGk=", + "dependencies": [ + "bifunctors", + "effect", + "either", + "identity", + "maybe", + "partial", + "prelude", + "refs" + ] + }, + "transformers": { + "type": "registry", + "version": "6.1.0", + "integrity": "sha256-3Bm+Z6tsC/paG888XkywDngJ2JMos+JfOhRlkVfb7gI=", + "dependencies": [ + "control", + "distributive", + "effect", + "either", + "exceptions", + "foldable-traversable", + "identity", + "lazy", + "maybe", + "newtype", + "prelude", + "st", + "tailrec", + "tuples", + "unfoldable" + ] + }, + "tuples": { + "type": "registry", + "version": "7.0.0", + "integrity": "sha256-1rXgTomes9105BjgXqIw0FL6Fz1lqqUTLWOumhWec1M=", + "dependencies": [ + "control", + "invariant", + "prelude" + ] + }, + "type-equality": { + "type": "registry", + "version": "4.0.1", + "integrity": "sha256-Hs9D6Y71zFi/b+qu5NSbuadUQXe5iv5iWx0226vOHUw=", + "dependencies": [] + }, + "typelevel-prelude": { + "type": "registry", + "version": "7.0.0", + "integrity": "sha256-uFF2ph+vHcQpfPuPf2a3ukJDFmLhApmkpTMviHIWgJM=", + "dependencies": [ + "prelude", + "type-equality" + ] + }, + "unfoldable": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-JtikvJdktRap7vr/K4ITlxUX1QexpnqBq0G/InLr6eg=", + "dependencies": [ + "foldable-traversable", + "maybe", + "partial", + "prelude", + "tuples" + ] + }, + "unsafe-coerce": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-IqIYW4Vkevn8sI+6aUwRGvd87tVL36BBeOr0cGAE7t0=", + "dependencies": [] + }, + "url-immutable": { + "type": "registry", + "version": "1.0.0", + "integrity": "sha256-6uCg5k4fjrqyTYUYKTmcykXgXCJKsvVpzx+gZJczAx0=", + "dependencies": [ + "arrays", + "bifunctors", + "either", + "filterable", + "foldable-traversable", + "foreign", + "integers", + "maybe", + "newtype", + "nullable", + "ordered-collections", + "partial", + "prelude", + "simple-json", + "strings", + "stringutils", + "transformers", + "tuples" + ] + }, + "variant": { + "type": "registry", + "version": "8.0.0", + "integrity": "sha256-SR//zQDg2dnbB8ZHslcxieUkCeNlbMToapvmh9onTtw=", + "dependencies": [ + "enums", + "lists", + "maybe", + "partial", + "prelude", + "record", + "tuples", + "unsafe-coerce" + ] + }, + "web-dom": { + "type": "registry", + "version": "6.0.0", + "integrity": "sha256-1kSKWFDI4LupdmpjK01b1MMxDFW7jvatEgPgVmCmSBQ=", + "dependencies": [ + "web-events" + ] + }, + "web-events": { + "type": "registry", + "version": "4.0.0", + "integrity": "sha256-YDt8b6u1tzGtnWyNRodne57iO8FNSGPaTCVzBUyUn4k=", + "dependencies": [ + "datetime", + "enums", + "foreign", + "nullable" + ] + }, + "web-file": { + "type": "registry", + "version": "4.0.0", + "integrity": "sha256-1h5jPBkvjY71jLEdwVadXCx86/2inNoMBO//Rd3eCSU=", + "dependencies": [ + "foreign", + "media-types", + "web-dom" + ] + }, + "web-streams": { + "type": "registry", + "version": "4.0.0", + "integrity": "sha256-02HgXIk6R+pU9fWOX42krukAI1QkCbLKcCv3b4Jq6WI=", + "dependencies": [ + "arraybuffer-types", + "effect", + "exceptions", + "js-promise", + "nullable", + "prelude", + "tuples" + ] + } + } +} diff --git a/spago.yaml b/spago.yaml index e50fb89..769506c 100644 --- a/spago.yaml +++ b/spago.yaml @@ -1,9 +1,22 @@ package: name: tower dependencies: + - aff + - argonaut-codecs + - argonaut-core - console - effect + - ezfetch + - maybe + - node-net + - node-streams + - nullable - prelude + - strings + - transformers + - tuples + - url-immutable + - web-streams test: main: Test.Main dependencies: [] diff --git a/src/Data.String.Lower.purs b/src/Data.String.Lower.purs new file mode 100644 index 0000000..5ea595e --- /dev/null +++ b/src/Data.String.Lower.purs @@ -0,0 +1,21 @@ +module Data.String.Lower where + +import Prelude + +import Data.Generic.Rep (class Generic) +import Data.String as String + +newtype StringLower = StringLower String + +derive instance Generic StringLower _ +derive newtype instance Show StringLower +derive newtype instance Eq StringLower +derive newtype instance Ord StringLower +derive newtype instance Monoid StringLower +derive newtype instance Semigroup StringLower + +fromString :: String -> StringLower +fromString = StringLower <<< String.toLower + +toString :: StringLower -> String +toString (StringLower a) = a diff --git a/src/Tower.Request.Method.purs b/src/Tower.Request.Method.purs new file mode 100644 index 0000000..f9f1516 --- /dev/null +++ b/src/Tower.Request.Method.purs @@ -0,0 +1,38 @@ +module Tower.Request.Method where + +import Prelude + +import Data.Generic.Rep (class Generic) +import Data.Maybe (Maybe(..)) +import Data.Show.Generic (genericShow) +import Data.String as String + +data Method = GET | POST | PUT | PATCH | DELETE | OPTIONS | TRACE | CONNECT +derive instance Generic Method _ +derive instance Eq Method +instance Show Method where show = genericShow + +methodToString :: Method -> String +methodToString GET = "GET" +methodToString POST = "POST" +methodToString PUT = "PUT" +methodToString PATCH = "PATCH" +methodToString DELETE = "DELETE" +methodToString OPTIONS = "OPTIONS" +methodToString TRACE = "TRACE" +methodToString CONNECT = "CONNECT" + +methodFromString :: String -> Maybe Method +methodFromString = + let + go "GET" = Just GET + go "POST" = Just POST + go "PUT" = Just PUT + go "PATCH" = Just PATCH + go "DELETE" = Just DELETE + go "OPTIONS" = Just OPTIONS + go "TRACE" = Just TRACE + go "CONNECT" = Just CONNECT + go _ = Nothing + in + go <<< String.toUpper diff --git a/src/Tower.Request.Parts.Body.purs b/src/Tower.Request.Parts.Body.purs new file mode 100644 index 0000000..8617e85 --- /dev/null +++ b/src/Tower.Request.Parts.Body.purs @@ -0,0 +1,18 @@ +module Tower.Request.Parts.Body where + +import Prelude + +import Data.Generic.Rep (class Generic) +import Data.Newtype (class Newtype) +import Node.Stream as Stream + +newtype Json a = Json a +derive instance Generic (Json a) _ +derive instance Newtype (Json a) _ +derive newtype instance (Eq a) => Eq (Json a) +derive newtype instance (Ord a) => Ord (Json a) +derive newtype instance (Show a) => Show (Json a) + +newtype Stream = Stream (Stream.Readable ()) +derive instance Generic Stream _ +derive instance Newtype Stream _ diff --git a/src/Tower.Request.Parts.Class.purs b/src/Tower.Request.Parts.Class.purs new file mode 100644 index 0000000..0dee8c3 --- /dev/null +++ b/src/Tower.Request.Parts.Class.purs @@ -0,0 +1,149 @@ +module Tower.Request.Parts.Class (class RequestParts, extractRequestParts, module Parts.Method, module Parts.Body, module Path.Parts) where + +import Prelude + +import Control.Alternative (guard) +import Control.Monad.Except (ExceptT(..), runExceptT) +import Control.Monad.Maybe.Trans (MaybeT(..), runMaybeT) +import Control.Monad.Trans.Class (lift) +import Data.Argonaut.Decode (class DecodeJson, decodeJson) +import Data.Array as Array +import Data.Bifunctor (lmap) +import Data.Either (Either(..)) +import Data.Maybe (Maybe(..)) +import Data.Newtype (class Newtype, wrap) +import Data.Tuple.Nested (type (/\), (/\)) +import Data.URL as URL +import Effect.Aff (Aff) +import Effect.Class (liftEffect) +import Node.Buffer (Buffer) +import Tower.Request (Request) +import Tower.Request as Request +import Tower.Request.Method (Method) +import Tower.Request.Method as Method +import Tower.Request.Parts.Body (Json(..), Stream(..)) +import Tower.Request.Parts.Body (Json(..), Stream(..)) as Parts.Body +import Tower.Request.Parts.Method (Connect, Delete, Get, Options, Patch, Post, Put, Trace) +import Tower.Request.Parts.Method (Get(..), Post(..), Put(..), Patch(..), Delete(..), Trace(..), Options(..), Connect(..)) as Parts.Method +import Tower.Request.Parts.Path (Path(..)) as Path.Parts +import Tower.Request.Parts.Path (class PathParts, Path(..), extractPathParts) +import Tower.Response (Response) +import Tower.Response as Response + +extractMethod :: forall @t a. RequestParts a => Newtype t a => Method -> Request -> Aff (Either Response (Maybe t)) +extractMethod method r = + if Request.method r == method then + extractRequestParts @a r + # ExceptT + # MaybeT + <#> wrap + # runMaybeT + # runExceptT + else + pure $ Right Nothing + +class RequestParts a where + extractRequestParts :: Request -> Aff (Either Response (Maybe a)) + +instance RequestParts Unit where + extractRequestParts _ = pure unit # runMaybeT # runExceptT + +instance RequestParts Request where + extractRequestParts r = pure r # runMaybeT # runExceptT + +instance RequestParts String where + extractRequestParts r = + Request.bodyString r + <#> lmap (const $ Response.fromStatus 500) + # ExceptT + # lift + # runMaybeT + # runExceptT + +instance PathParts a b => RequestParts (Path a b) where + extractRequestParts r = + let + segments = Request.url r # URL.path # case _ of + URL.PathAbsolute a -> a + URL.PathRelative a -> a + _ -> [] + extract = extractPathParts @a @b (Request.url r) + ensureConsumed (leftover /\ x) = guard (Array.null leftover) $> x + in + segments + # extract + # Right + # MaybeT + >>= ensureConsumed + <#> Path + # runMaybeT + # pure + +instance (DecodeJson a) => RequestParts (Json a) where + extractRequestParts r = + let + jsonBody = + Request.bodyJSON r + <#> lmap (const $ Response.fromStatus 500) + # ExceptT + # lift + decode j = + decodeJson j + # lmap (const $ Response.fromStatus 400) + # pure + # ExceptT + # lift + in + jsonBody >>= decode <#> Json # runMaybeT # runExceptT + +instance RequestParts Buffer where + extractRequestParts r = + let + bufBody = + Request.bodyBuffer r + <#> lmap (const $ Response.fromStatus 500) + # ExceptT + # lift + in + bufBody # runMaybeT # runExceptT + +instance RequestParts Stream where + extractRequestParts r = + let + streamBody = + Request.bodyReadable r + <#> lmap (const $ Response.fromStatus 500) + # ExceptT + # lift + in + streamBody <#> Stream # runMaybeT # runExceptT # liftEffect + +instance (RequestParts a) => RequestParts (Get a) where + extractRequestParts = extractMethod @(Get a) Method.GET + +instance (RequestParts a) => RequestParts (Post a) where + extractRequestParts = extractMethod @(Post a) Method.POST + +instance (RequestParts a) => RequestParts (Put a) where + extractRequestParts = extractMethod @(Put a) Method.PUT + +instance (RequestParts a) => RequestParts (Patch a) where + extractRequestParts = extractMethod @(Patch a) Method.PATCH + +instance (RequestParts a) => RequestParts (Delete a) where + extractRequestParts = extractMethod @(Delete a) Method.DELETE + +instance (RequestParts a) => RequestParts (Options a) where + extractRequestParts = extractMethod @(Options a) Method.OPTIONS + +instance (RequestParts a) => RequestParts (Connect a) where + extractRequestParts = extractMethod @(Connect a) Method.CONNECT + +instance (RequestParts a) => RequestParts (Trace a) where + extractRequestParts = extractMethod @(Trace a) Method.TRACE + +instance (RequestParts a, RequestParts b) => RequestParts (a /\ b) where + extractRequestParts r = runExceptT $ runMaybeT do + a <- extractRequestParts @a r # ExceptT # MaybeT + b <- extractRequestParts @b r # ExceptT # MaybeT + pure $ a /\ b diff --git a/src/Tower.Request.Parts.Method.purs b/src/Tower.Request.Parts.Method.purs new file mode 100644 index 0000000..fedd557 --- /dev/null +++ b/src/Tower.Request.Parts.Method.purs @@ -0,0 +1,62 @@ +module Tower.Request.Parts.Method where + +import Prelude + +import Data.Generic.Rep (class Generic) +import Data.Newtype (class Newtype) + +newtype Get a = Get a +derive instance Generic (Get a) _ +derive instance Newtype (Get a) _ +derive newtype instance (Eq a) => Eq (Get a) +derive newtype instance (Ord a) => Ord (Get a) +derive newtype instance (Show a) => Show (Get a) + +newtype Post a = Post a +derive instance Generic (Post a) _ +derive instance Newtype (Post a) _ +derive newtype instance (Eq a) => Eq (Post a) +derive newtype instance (Ord a) => Ord (Post a) +derive newtype instance (Show a) => Show (Post a) + +newtype Put a = Put a +derive instance Generic (Put a) _ +derive instance Newtype (Put a) _ +derive newtype instance (Eq a) => Eq (Put a) +derive newtype instance (Ord a) => Ord (Put a) +derive newtype instance (Show a) => Show (Put a) + +newtype Patch a = Patch a +derive instance Generic (Patch a) _ +derive instance Newtype (Patch a) _ +derive newtype instance (Eq a) => Eq (Patch a) +derive newtype instance (Ord a) => Ord (Patch a) +derive newtype instance (Show a) => Show (Patch a) + +newtype Delete a = Delete a +derive instance Generic (Delete a) _ +derive instance Newtype (Delete a) _ +derive newtype instance (Eq a) => Eq (Delete a) +derive newtype instance (Ord a) => Ord (Delete a) +derive newtype instance (Show a) => Show (Delete a) + +newtype Options a = Options a +derive instance Generic (Options a) _ +derive instance Newtype (Options a) _ +derive newtype instance (Eq a) => Eq (Options a) +derive newtype instance (Ord a) => Ord (Options a) +derive newtype instance (Show a) => Show (Options a) + +newtype Trace a = Trace a +derive instance Generic (Trace a) _ +derive instance Newtype (Trace a) _ +derive newtype instance (Eq a) => Eq (Trace a) +derive newtype instance (Ord a) => Ord (Trace a) +derive newtype instance (Show a) => Show (Trace a) + +newtype Connect a = Connect a +derive instance Generic (Connect a) _ +derive instance Newtype (Connect a) _ +derive newtype instance (Eq a) => Eq (Connect a) +derive newtype instance (Ord a) => Ord (Connect a) +derive newtype instance (Show a) => Show (Connect a) diff --git a/src/Tower.Request.Parts.Path.purs b/src/Tower.Request.Parts.Path.purs new file mode 100644 index 0000000..12f67f6 --- /dev/null +++ b/src/Tower.Request.Parts.Path.purs @@ -0,0 +1,50 @@ +module Tower.Request.Parts.Path where + +import Prelude + +import Control.Alternative (guard) +import Data.Array as Array +import Data.Int as Int +import Data.Maybe (Maybe(..), fromMaybe) +import Data.Symbol (class IsSymbol, reflectSymbol) +import Data.Tuple.Nested (type (/\), (/\)) +import Data.URL (URL) +import Type.Prelude (Proxy(..)) + +newtype Path :: Type -> Type -> Type +newtype Path a b = Path b + +data Sep :: Type -> Type -> Type +data Sep a b + +data IgnoreRest :: Type +data IgnoreRest + +infixl 9 type Sep as / +infixl 9 type IgnoreRest as ... + +class PathParts :: forall a. a -> Type -> Constraint +class PathParts a b | a -> b where + extractPathParts :: URL -> Array String -> Maybe (Array String /\ b) + +instance (PathParts aa ab, PathParts ba bb) => PathParts (aa / ba) (ab /\ bb) where + extractPathParts u segments = do + segments' /\ ab <- extractPathParts @aa u segments + segments'' /\ bb <- extractPathParts @ba u segments' + pure $ segments'' /\ ab /\ bb +else instance PathParts (...) Unit where + extractPathParts _ _ = Just $ [] /\ unit +else instance PathParts String String where + extractPathParts _ segments = do + head <- Array.head segments + pure $ (fromMaybe [] (Array.tail segments) /\ head) +else instance PathParts Int Int where + extractPathParts _ segments = do + head <- Array.head segments + a <- Int.fromString head + pure $ (fromMaybe [] (Array.tail segments) /\ a) +else instance (IsSymbol k) => PathParts k Unit where + extractPathParts _ segments = do + head <- Array.head segments + guard $ head == reflectSymbol (Proxy @k) + pure $ (fromMaybe [] (Array.tail segments) /\ unit) diff --git a/src/Tower.Request.purs b/src/Tower.Request.purs new file mode 100644 index 0000000..d71730b --- /dev/null +++ b/src/Tower.Request.purs @@ -0,0 +1,200 @@ +module Tower.Request (Request, BodyReadableError(..), BodyStringError(..), BodyJSONError(..), BodyBufferError(..), bodyReadable, bodyString, bodyJSON, bodyBuffer, headers, method, address, url, contentType, accept, contentLength, lookupHeader) where + +import Prelude + +import Control.Monad.Error.Class (throwError, try) +import Control.Monad.Except (ExceptT(..), runExceptT) +import Control.Monad.Trans.Class (lift) +import Data.Argonaut.Core (Json) +import Data.Argonaut.Core (stringify) as JSON +import Data.Argonaut.Parser (jsonParser) as JSON +import Data.Bifunctor (lmap) +import Data.Either (Either, note) +import Data.Generic.Rep (class Generic) +import Data.Int as Int +import Data.MIME (MIME) +import Data.MIME as MIME +import Data.Map (Map) +import Data.Map as Map +import Data.Maybe (Maybe(..)) +import Data.Show.Generic (genericShow) +import Data.String.Lower (StringLower) +import Data.String.Lower as String.Lower +import Data.URL (URL) +import Effect (Effect) +import Effect.Aff (Aff) +import Effect.Aff.Class (liftAff) +import Effect.Class (liftEffect) +import Effect.Exception (Error) +import Effect.Exception as Error +import Effect.Ref (Ref) as Effect +import Effect.Ref as Ref +import Node.Buffer (Buffer) +import Node.Buffer as Buffer +import Node.Encoding (Encoding(..)) +import Node.Net.Types (IPv4, IPv6, SocketAddress) +import Node.Stream as Stream +import Node.Stream.Aff as Stream.Aff +import Tower.Request.Method (Method) + +data BodyReadableError + = BodyReadableErrorHasBeenConsumed + | BodyReadableErrorEmpty + +derive instance Generic BodyReadableError _ +derive instance Eq BodyReadableError +instance Show BodyReadableError where + show = genericShow + +data BodyBufferError + = BodyBufferErrorReadable BodyReadableError + | BodyBufferErrorReading Error + +derive instance Generic BodyBufferError _ +instance Eq BodyBufferError where + eq (BodyBufferErrorReadable a) (BodyBufferErrorReadable b) = a == b + eq (BodyBufferErrorReading a) (BodyBufferErrorReading b) = Error.message a == Error.message b + eq _ _ = false +instance Show BodyBufferError where + show = genericShow + +data BodyStringError + = BodyStringErrorBuffer BodyBufferError + | BodyStringErrorNotUTF8 + +derive instance Generic BodyStringError _ +derive instance Eq BodyStringError +instance Show BodyStringError where + show = genericShow + +data BodyJSONError + = BodyJSONErrorString BodyStringError + | BodyJSONErrorParsing String + +derive instance Generic BodyJSONError _ +derive instance Eq BodyJSONError +instance Show BodyJSONError where + show = genericShow + +data Body + = BodyEmpty + | BodyReadable (Stream.Readable ()) + | BodyReadableConsumed + | BodyCached Buffer + | BodyCachedString String + | BodyCachedJSON Json + +data Request = + Request + { headers :: Map StringLower String + , address :: Either (SocketAddress IPv4) (SocketAddress IPv6) + , url :: URL + , method :: Method + , bodyRef :: Effect.Ref Body + } + +headers :: Request -> Map StringLower String +headers (Request a) = a.headers + +lookupHeader :: String -> Request -> Maybe String +lookupHeader k (Request a) = Map.lookup (String.Lower.fromString k) a.headers + +contentType :: Request -> Maybe MIME +contentType = lookupHeader "content-type" >>> map MIME.fromString + +accept :: Request -> Maybe MIME +accept = lookupHeader "accept" >>> map MIME.fromString + +contentLength :: Request -> Maybe Int +contentLength = lookupHeader "content-length" >=> Int.fromString + +method :: Request -> Method +method (Request a) = a.method + +address :: Request -> Either (SocketAddress IPv4) (SocketAddress IPv6) +address (Request a) = a.address + +url :: Request -> URL +url (Request a) = a.url + +bodyReadable :: Request -> Effect (Either BodyReadableError (Stream.Readable ())) +bodyReadable (Request {bodyRef}) = runExceptT do + body <- liftEffect $ Ref.read bodyRef + case body of + BodyEmpty -> throwError BodyReadableErrorEmpty + BodyReadableConsumed -> throwError BodyReadableErrorHasBeenConsumed + BodyReadable r -> + Ref.write BodyReadableConsumed bodyRef $> r # lift + BodyCached buf -> Stream.readableFromBuffer buf # lift + BodyCachedString str -> Stream.readableFromString str UTF8 # lift + BodyCachedJSON json -> json # JSON.stringify # flip Buffer.fromString UTF8 >>= Stream.readableFromBuffer # lift + +bodyBuffer :: Request -> Aff (Either BodyBufferError Buffer) +bodyBuffer r@(Request {bodyRef}) = + let + stream = + bodyReadable r + # liftEffect + <#> lmap BodyBufferErrorReadable + # ExceptT + readAll s = + Stream.Aff.readAll s + # liftAff + # try + <#> lmap BodyBufferErrorReading + # ExceptT + >>= (liftEffect <<< Buffer.concat) + in + runExceptT do + body <- Ref.read bodyRef # liftEffect + case body of + BodyCached buf -> pure buf + BodyCachedString str -> Buffer.fromString str UTF8 # liftEffect + BodyCachedJSON json -> Buffer.fromString (JSON.stringify json) UTF8 # liftEffect + _ -> do + buf <- stream >>= readAll + Ref.write (BodyCached buf) bodyRef $> buf # liftEffect + +bodyString :: Request -> Aff (Either BodyStringError String) +bodyString r@(Request {bodyRef}) = + let + buf = + bodyBuffer r + <#> lmap BodyStringErrorBuffer + # ExceptT + bufString b = + Buffer.toString UTF8 b + # liftEffect + # try + <#> lmap (const BodyStringErrorNotUTF8) + # ExceptT + in + runExceptT do + body <- Ref.read bodyRef # liftEffect + case body of + BodyCachedString str -> pure str + BodyCachedJSON json -> JSON.stringify json # pure + _ -> do + str <- buf >>= bufString + Ref.write (BodyCachedString str) bodyRef $> str # liftEffect + +bodyJSON :: Request -> Aff (Either BodyJSONError Json) +bodyJSON r@(Request {bodyRef}) = + let + str = + bodyString r + <#> lmap BodyJSONErrorString + # ExceptT + parse s = + JSON.jsonParser s + # lmap BodyJSONErrorParsing + # pure + # ExceptT + in + runExceptT do + body <- Ref.read bodyRef # liftEffect + case body of + BodyCachedJSON j -> pure j + _ -> do + j <- str >>= parse + Ref.write (BodyCachedJSON j) bodyRef $> j # liftEffect diff --git a/src/Tower.Response.Body.purs b/src/Tower.Response.Body.purs new file mode 100644 index 0000000..70bbadc --- /dev/null +++ b/src/Tower.Response.Body.purs @@ -0,0 +1,35 @@ +module Tower.Response.Body where + +import Prelude + +import Data.Argonaut.Core (Json, stringify) +import Effect (Effect) +import Effect.Aff.HTTP.Form (Form, RawFormData) as HTTP +import Effect.Aff.HTTP.Form as HTTP.Form +import Node.Buffer (Buffer) +import Node.Stream as Stream + +data Body + = BodyEmpty + | BodyString String + | BodyBuffer Buffer + | BodyFormData HTTP.RawFormData + | BodyReadable (Stream.Readable ()) + +formBody :: HTTP.Form -> Effect Body +formBody f = HTTP.Form.toRawFormData f <#> BodyFormData + +stringBody :: String -> Body +stringBody = BodyString + +bufferBody :: Buffer -> Body +bufferBody = BodyBuffer + +streamBody :: Stream.Readable () -> Body +streamBody = BodyReadable + +emptyBody :: Body +emptyBody = BodyEmpty + +jsonBody :: Json -> Body +jsonBody = stringify >>> BodyString diff --git a/src/Tower.Response.purs b/src/Tower.Response.purs new file mode 100644 index 0000000..61728b4 --- /dev/null +++ b/src/Tower.Response.purs @@ -0,0 +1,40 @@ +module Tower.Response (Response, response, body, status, headers, withHeader, withBody, withStatus, fromStatus, ok, module Body) where + +import Prelude + +import Data.FoldableWithIndex (foldlWithIndex) +import Data.Map (Map) +import Data.Map as Map +import Data.String.Lower (StringLower) +import Data.String.Lower as String.Lower +import Tower.Response.Body (Body(..)) +import Tower.Response.Body (Body(..), formBody) as Body + +data Response = Response {body :: Body, headers :: Map StringLower String, status :: Int} + +response :: Int -> Body -> Map String String -> Response +response s b h = Response {status: s, body: b, headers: h # foldlWithIndex (\k m v -> Map.insert (String.Lower.fromString k) v m) Map.empty} + +status :: Response -> Int +status (Response a) = a.status + +body :: Response -> Body +body (Response a) = a.body + +headers :: Response -> Map StringLower String +headers (Response a) = a.headers + +withHeader :: String -> String -> Response -> Response +withHeader k v (Response a) = Response $ a {headers = Map.insert (String.Lower.fromString k) v a.headers} + +withStatus :: Int -> Response -> Response +withStatus s (Response a) = Response $ a {status = s} + +withBody :: Body -> Response -> Response +withBody b (Response a) = Response $ a {body = b} + +fromStatus :: Int -> Response +fromStatus s = Response {body: BodyEmpty, headers: Map.empty, status: s} + +ok :: Response +ok = fromStatus 200 diff --git a/src/Tower.Service.Class.purs b/src/Tower.Service.Class.purs new file mode 100644 index 0000000..90e16d0 --- /dev/null +++ b/src/Tower.Service.Class.purs @@ -0,0 +1,2 @@ +module Tower.Service.Class where + diff --git a/src/Tower.Web.Headers.js b/src/Tower.Web.Headers.js new file mode 100644 index 0000000..7814dc8 --- /dev/null +++ b/src/Tower.Web.Headers.js @@ -0,0 +1,5 @@ +/// +/// + +/** @type {(_: {tuple: (a: A) => (b: B) => unknown}) => (h: Headers) => () => Array} */ +export const headerEntries = ({tuple}) => hs => () => Array.from(hs.entries()).map(([a, b]) => tuple(a)(b)) diff --git a/src/Tower.Web.Headers.purs b/src/Tower.Web.Headers.purs new file mode 100644 index 0000000..acba21b --- /dev/null +++ b/src/Tower.Web.Headers.purs @@ -0,0 +1,7 @@ +module Tower.Web.Headers where + +import Data.Tuple.Nested (type (/\)) +import Effect (Effect) + +foreign import data WebHeaders :: Type +foreign import headerEntries :: {tuple :: forall a b. a -> b -> a /\ b} -> WebHeaders -> Effect (Array (String /\ String)) diff --git a/src/Tower.Web.Request.js b/src/Tower.Web.Request.js new file mode 100644 index 0000000..d9abfeb --- /dev/null +++ b/src/Tower.Web.Request.js @@ -0,0 +1,45 @@ +/// +/// + +import Stream from 'stream' + +/** @type {(r: Request) => () => ReadableStream | null} */ +export const body = r => () => r.body + +/** @type {(r: Request) => () => boolean} */ +export const bodyUsed = r => () => r.bodyUsed + +/** @type {(r: Request) => () => string} */ +export const method = r => () => r.method + +/** @type {(r: Request) => () => string} */ +export const url = r => () => r.url + +/** @type {(r: Request) => () => Headers} */ +export const headers = r => () => r.headers + +/** @type {(r: ReadableStream) => () => Stream.Readable} */ +export const readableFromWeb = r => () => { + const reader = r.getReader(); + return new Stream.Readable({ + read: function() { + (async () => { + /** @type {ReadableStreamReadResult | undefined} */ + let res = undefined; + try { + res = await reader.read() + } catch(e) { + if (typeof e === 'undefined' || e instanceof Error) { + this.destroy(e) + return + } else { + throw e + } + } + + if (res.value) this.push(res.value); + if (res.done) this.push(null); + })() + }, + }) +} diff --git a/src/Tower.Web.Request.purs b/src/Tower.Web.Request.purs new file mode 100644 index 0000000..691e65b --- /dev/null +++ b/src/Tower.Web.Request.purs @@ -0,0 +1,19 @@ +module Tower.Web.Request where + +import Data.ArrayBuffer.Types (Uint8Array) +import Data.Nullable (Nullable) +import Effect (Effect) +import Node.Stream as Stream +import Tower.Request.Web (WebHeaders) +import Web.Streams.ReadableStream (ReadableStream) + +foreign import data WebRequest :: Type + +foreign import body :: WebRequest -> Effect (Nullable (ReadableStream Uint8Array)) +foreign import bodyUsed :: WebRequest -> Effect Boolean +foreign import method :: WebRequest -> Effect String +foreign import url :: WebRequest -> Effect String + +foreign import headers :: WebRequest -> Effect WebHeaders + +foreign import readableFromWeb :: ReadableStream Uint8Array -> Effect (Stream.Readable ()) diff --git a/src/Tower.Web.Response.purs b/src/Tower.Web.Response.purs new file mode 100644 index 0000000..7086add --- /dev/null +++ b/src/Tower.Web.Response.purs @@ -0,0 +1 @@ +module Tower.Web.Response where