From 144a2a7cd5a4024c835fd4c5a244e8870724515d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 29 Jul 2023 06:09:22 -0700 Subject: [PATCH 01/16] Move files into Old module --- src/Node/{ => Old}/URL.js | 0 src/Node/{ => Old}/URL.purs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Node/{ => Old}/URL.js (100%) rename src/Node/{ => Old}/URL.purs (98%) diff --git a/src/Node/URL.js b/src/Node/Old/URL.js similarity index 100% rename from src/Node/URL.js rename to src/Node/Old/URL.js diff --git a/src/Node/URL.purs b/src/Node/Old/URL.purs similarity index 98% rename from src/Node/URL.purs rename to src/Node/Old/URL.purs index 08df4f8..29d9e74 100644 --- a/src/Node/URL.purs +++ b/src/Node/Old/URL.purs @@ -1,6 +1,6 @@ -- | This module defines bindings to the Node URL and Query String APIs. -module Node.URL where +module Node.Old.URL where import Data.Nullable From e57cbc8f9bcf46df02554a9eea8a56469e60b193 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 29 Jul 2023 06:32:50 -0700 Subject: [PATCH 02/16] Add deps on prelude and effect --- bower.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bower.json b/bower.json index 56815b0..00a32f1 100644 --- a/bower.json +++ b/bower.json @@ -12,6 +12,8 @@ "url": "https://github.com/purescript-node/purescript-node-url.git" }, "dependencies": { + "purescript-prelude": "^6.0.1", + "purescript-effect": "^4.0.0", "purescript-nullable": "^6.0.0" }, "devDependencies": { From 8b991fb8ce018e80cb27a1ab2a0217ec76fac638 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 29 Jul 2023 06:33:03 -0700 Subject: [PATCH 03/16] Implement bindings for URL --- src/Node/URL.js | 49 ++++++++++++++++ src/Node/URL.purs | 140 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 src/Node/URL.js create mode 100644 src/Node/URL.purs diff --git a/src/Node/URL.js b/src/Node/URL.js new file mode 100644 index 0000000..b5edae1 --- /dev/null +++ b/src/Node/URL.js @@ -0,0 +1,49 @@ +import url from "node:url"; + +export const newImpl = (input) => new url.URL(input); +export const newRelativeImpl = (input, base) => new url.URL(input, base); +export const hashImpl = (u) => u.hash; +export const setHashImpl = (h, u) => { + u.hash = h; +}; +export const hostImpl = (url) => url.host; +export const setHostImpl = (val, u) => { + u.host = val; +}; +export const hostnameImpl = (u) => u.hostname; +export const setHostnameImpl = (val, u) => { + u.hostname = val; +}; +export const uneffectfulHref = (u) => u.href; +export const hrefImpl = (u) => u.href; +export const setHrefImpl = (val, u) => { + u.href = val; +}; +export const origin = (u) => u.origin; +export const passwordImpl = (u) => u.password; +export const setPasswordImpl = (val, u) => { + u.password = val; +}; +export const pathnameImpl = (u) => u.pathname; +export const setPathnameImpl = (val, u) => { + u.pathname = val; +}; +export const portImpl = (u) => u.port; +export const setPortImpl = (val, u) => { + u.port = val; +}; +export const protocolImpl = (u) => u.protocol; +export const setProtocolImpl = (val, u) => { + u.protocol = val; +}; +export const searchImpl = (u) => u.search; +export const setSearchImpl = (val, u) => { + u.search = val; +}; +export const searchParamsImpl = (u) => u.searchParams; +export const usernameImpl = (u) => u.username; +export const setUsernameImpl = (val, u) => { + u.username = val; +}; + +export const canParseImpl = (input, base) => URL.canParse(input, base); diff --git a/src/Node/URL.purs b/src/Node/URL.purs new file mode 100644 index 0000000..3c5f6f2 --- /dev/null +++ b/src/Node/URL.purs @@ -0,0 +1,140 @@ +module Node.URL where + +import Prelude + +import Data.Function.Uncurried (Fn2, runFn2) +import Effect (Effect) +import Effect.Uncurried (EffectFn1, EffectFn2, runEffectFn1, runEffectFn2) + +foreign import data URL :: Type + +instance Show URL where + show x = "URL(" <> uneffectfulHref x <> ")" + +new :: String -> Effect URL +new input = runEffectFn1 newImpl input + +foreign import newImpl :: EffectFn1 (String) (URL) + +new' :: String -> String -> Effect URL +new' input base = runEffectFn2 newRelativeImpl input base + +foreign import newRelativeImpl :: EffectFn2 (String) (String) (URL) + +hash :: URL -> Effect String +hash url = runEffectFn1 hashImpl url + +foreign import hashImpl :: EffectFn1 URL String + +setHash :: String -> URL -> Effect Unit +setHash val url = runEffectFn2 setHashImpl val url + +foreign import setHashImpl :: EffectFn2 String URL Unit + +host :: URL -> Effect String +host url = runEffectFn1 hostImpl url + +foreign import hostImpl :: EffectFn1 URL String + +setHost :: String -> URL -> Effect Unit +setHost val url = runEffectFn2 setHostImpl val url + +foreign import setHostImpl :: EffectFn2 String URL Unit + +hostname :: URL -> Effect String +hostname url = runEffectFn1 hostnameImpl url + +foreign import hostnameImpl :: EffectFn1 URL String + +setHostname :: String -> URL -> Effect Unit +setHostname val url = runEffectFn2 setHostnameImpl val url + +foreign import setHostnameImpl :: EffectFn2 String URL Unit + +foreign import uneffectfulHref :: URL -> String + +href :: URL -> Effect String +href url = runEffectFn1 hrefImpl url + +foreign import hrefImpl :: EffectFn1 URL String + +setHref :: String -> URL -> Effect Unit +setHref val url = runEffectFn2 setHrefImpl val url + +foreign import setHrefImpl :: EffectFn2 String URL Unit + +foreign import origin :: URL -> String + +password :: URL -> Effect String +password url = runEffectFn1 passwordImpl url + +foreign import passwordImpl :: EffectFn1 URL String + +setPassword :: String -> URL -> Effect Unit +setPassword val url = runEffectFn2 setPasswordImpl val url + +foreign import setPasswordImpl :: EffectFn2 String URL Unit + +pathname :: URL -> Effect String +pathname url = runEffectFn1 pathnameImpl url + +foreign import pathnameImpl :: EffectFn1 URL String + +setPathname :: String -> URL -> Effect Unit +setPathname val url = runEffectFn2 setPathnameImpl val url + +foreign import setPathnameImpl :: EffectFn2 String URL Unit + +port :: URL -> Effect String +port url = runEffectFn1 portImpl url + +foreign import portImpl :: EffectFn1 URL String + +setPort :: String -> URL -> Effect Unit +setPort val url = runEffectFn2 setPortImpl val url + +foreign import setPortImpl :: EffectFn2 String URL Unit + +protocol :: URL -> Effect String +protocol url = runEffectFn1 protocolImpl url + +foreign import protocolImpl :: EffectFn1 URL String + +setProtocol :: String -> URL -> Effect Unit +setProtocol val url = runEffectFn2 setProtocolImpl val url + +foreign import setProtocolImpl :: EffectFn2 String URL Unit + +search :: URL -> Effect String +search url = runEffectFn1 searchImpl url + +foreign import searchImpl :: EffectFn1 URL String + +setSearch :: String -> URL -> Effect Unit +setSearch val url = runEffectFn2 setSearchImpl val url + +foreign import setSearchImpl :: EffectFn2 String URL Unit + +searchParams :: URL -> Effect URLSearchParams +searchParams url = runEffectFn1 searchParamsImpl url + +foreign import searchParamsImpl :: EffectFn1 (URL) (URLSearchParams) + +username :: URL -> Effect String +username url = runEffectFn1 usernameImpl url + +foreign import usernameImpl :: EffectFn1 URL String + +setUsername :: String -> URL -> Effect Unit +setUsername val url = runEffectFn2 setUsernameImpl val url + +foreign import setUsernameImpl :: EffectFn2 String URL Unit + +canParse :: String -> String -> Boolean +canParse input base = runFn2 canParseImpl input base + +foreign import canParseImpl :: Fn2 (String) (String) (Boolean) + +-- searchParams + +foreign import data URLSearchParams :: Type From 89a024288eb0b7b5893e886899789e2a85af18ff Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 17:24:31 -0500 Subject: [PATCH 04/16] Add bindings to UrlSearchParams --- bower.json | 4 +- src/Node/URL/URLSearchParams.js | 26 +++++++++ src/Node/URL/URLSearchParams.purs | 91 +++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 src/Node/URL/URLSearchParams.js create mode 100644 src/Node/URL/URLSearchParams.purs diff --git a/bower.json b/bower.json index 00a32f1..4470a66 100644 --- a/bower.json +++ b/bower.json @@ -14,7 +14,9 @@ "dependencies": { "purescript-prelude": "^6.0.1", "purescript-effect": "^4.0.0", - "purescript-nullable": "^6.0.0" + "purescript-foreign": "^7.0.0", + "purescript-nullable": "^6.0.0", + "purescript-tuples": "^7.0.0" }, "devDependencies": { "purescript-assert": "^6.0.0" diff --git a/src/Node/URL/URLSearchParams.js b/src/Node/URL/URLSearchParams.js new file mode 100644 index 0000000..f8730dd --- /dev/null +++ b/src/Node/URL/URLSearchParams.js @@ -0,0 +1,26 @@ +const newImpl = () => new URLSearchParams(); +export { newImpl as new } +export const fromStringImpl = (str) => new URLSearchParams(str); +export const fromObjectImpl = (obj) => new URLSearchParams(obj); +export const appendParamImpl = (name, value, params) => params.append(name, value); +export const deleteImpl = (name, params) => params.delete(name); +export const getNameImpl = (name, params) => params.getName(name); +export const getAllImpl = (name, params) => params.getAll(name); +export const hasImpl = (name, params) => params.has(name); +export const setImpl = (name, value, params) => params.set(name, value); +export const sizeImpl = (params) => params.size; +export const sortImpl = (params) => params.sort(); +export const toStringImpl = (params) => params.toString(); +export const entriesImpl = (params, tuple) => { + const arr = new Array(params.size); + params.forEach((value, name) => { + arr.push(tuple(name, value)); + }); + return arr; +}; +export const keysImpl = (params) => { + Array.from(params.keys()); +}; +export const valuesImpl = (params) => { + Array.from(params.values()); +}; diff --git a/src/Node/URL/URLSearchParams.purs b/src/Node/URL/URLSearchParams.purs new file mode 100644 index 0000000..1c1dd36 --- /dev/null +++ b/src/Node/URL/URLSearchParams.purs @@ -0,0 +1,91 @@ +module Node.URL.URLSearchParams where + +import Prelude + +import Data.Maybe (Maybe) +import Data.Nullable (Nullable, toMaybe) +import Data.Tuple (Tuple(..)) +import Effect (Effect) +import Effect.Uncurried (EffectFn1, EffectFn2, EffectFn3, runEffectFn1, runEffectFn2, runEffectFn3) +import Foreign (Foreign) + +foreign import data URLSearchParams :: Type + +foreign import new :: Effect (URLSearchParams) + +fromString :: String -> Effect URLSearchParams +fromString str = runEffectFn1 fromStringImpl str + +foreign import fromStringImpl :: EffectFn1 (String) (URLSearchParams) + +-- | Each label in the record arg must be of type `String`, `Array String`, +-- | or a newtyped version of those two types. +-- | Note: the compiler does not check the record arg to verify that this constraint +-- | has been satisfied. +fromObject + :: forall r + . { | r } + -> Effect URLSearchParams +fromObject obj = runEffectFn1 fromObjectImpl obj + +foreign import fromObjectImpl :: forall r. EffectFn1 ({ | r }) (URLSearchParams) + +appendParam :: String -> String -> URLSearchParams -> Effect Unit +appendParam name value params = runEffectFn3 appendParamImpl name value params + +foreign import appendParamImpl :: EffectFn3 (String) (String) (URLSearchParams) (Unit) + +delete :: String -> URLSearchParams -> Effect Unit +delete name params = runEffectFn2 deleteImpl name params + +foreign import deleteImpl :: EffectFn2 (String) (URLSearchParams) (Unit) + +getName :: String -> URLSearchParams -> Effect (Maybe String) +getName name params = map toMaybe $ runEffectFn2 getNameImpl name params + +foreign import getNameImpl :: EffectFn2 (String) (URLSearchParams) (Nullable String) + +getAll :: String -> URLSearchParams -> Effect (Array String) +getAll name params = runEffectFn2 getAllImpl name params + +foreign import getAllImpl :: EffectFn2 (String) (URLSearchParams) (Array String) + +has :: String -> URLSearchParams -> Effect Boolean +has name params = runEffectFn2 hasImpl name params + +foreign import hasImpl :: EffectFn2 (String) (URLSearchParams) (Boolean) + +set :: String -> String -> URLSearchParams -> Effect Unit +set name value params = runEffectFn3 setImpl name value params + +foreign import setImpl :: EffectFn3 (String) (String) (URLSearchParams) (Unit) + +size :: URLSearchParams -> Effect Int +size params = runEffectFn1 sizeImpl params + +foreign import sizeImpl :: EffectFn1 (URLSearchParams) (Int) + +sort :: URLSearchParams -> Effect Unit +sort params = runEffectFn1 sortImpl params + +foreign import sortImpl :: EffectFn1 (URLSearchParams) (Unit) + +toString :: URLSearchParams -> Effect String +toString params = runEffectFn1 toStringImpl params + +foreign import toStringImpl :: EffectFn1 (URLSearchParams) (String) + +entries :: URLSearchParams -> Effect (Array (Tuple String Foreign)) +entries params = runEffectFn2 entriesImpl params Tuple + +foreign import entriesImpl :: forall a b. EffectFn2 URLSearchParams (a -> b -> Tuple a b) (Array (Tuple String Foreign)) + +keys :: URLSearchParams -> Effect (Array String) +keys params = runEffectFn1 keysImpl params + +foreign import keysImpl :: EffectFn1 (URLSearchParams) (Array String) + +values :: URLSearchParams -> Effect (Array Foreign) +values params = runEffectFn1 valuesImpl params + +foreign import valuesImpl :: EffectFn1 (URLSearchParams) (Array Foreign) From 9b7960cba5851635ad61c42361fa596a84044034 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 17:24:53 -0500 Subject: [PATCH 05/16] Finish implementing URL bindings --- src/Node/URL.js | 8 +++++ src/Node/URL.purs | 81 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/src/Node/URL.js b/src/Node/URL.js index b5edae1..ea42e01 100644 --- a/src/Node/URL.js +++ b/src/Node/URL.js @@ -2,6 +2,7 @@ import url from "node:url"; export const newImpl = (input) => new url.URL(input); export const newRelativeImpl = (input, base) => new url.URL(input, base); +export const pathToFileURLImpl = (path) => url.pathToFileURL(path); export const hashImpl = (u) => u.hash; export const setHashImpl = (h, u) => { u.hash = h; @@ -47,3 +48,10 @@ export const setUsernameImpl = (val, u) => { }; export const canParseImpl = (input, base) => URL.canParse(input, base); +export const domainToAsciiImpl = (domain) => url.domainToASCII(domain); +export const domainToUnicodeImpl = (domain) => url.domainToUnicode(domain); +export const fileURLToPathImpl = (str) => url.fileURLToPath(str); +export const fileURLToPathUrlImpl = (str) => url.fileURLToPath(str); +export const formatImpl = (theUrl, opts) => url.format(theUrl, opts); +export const pathToFileUrlImpl = (path) => url.pathToFileURL(path); +export const urlToHttpOptionsImpl = (theUrl) => url.urlToHttpOptions(theUrl); diff --git a/src/Node/URL.purs b/src/Node/URL.purs index 3c5f6f2..aee10ab 100644 --- a/src/Node/URL.purs +++ b/src/Node/URL.purs @@ -5,6 +5,8 @@ import Prelude import Data.Function.Uncurried (Fn2, runFn2) import Effect (Effect) import Effect.Uncurried (EffectFn1, EffectFn2, runEffectFn1, runEffectFn2) +import Node.URL.URLSearchParams (URLSearchParams) +import Prim.Row as Row foreign import data URL :: Type @@ -21,6 +23,11 @@ new' input base = runEffectFn2 newRelativeImpl input base foreign import newRelativeImpl :: EffectFn2 (String) (String) (URL) +pathToFileURL :: String -> Effect URL +pathToFileURL path = runEffectFn1 pathToFileURLImpl path + +foreign import pathToFileURLImpl :: EffectFn1 (String) (URL) + hash :: URL -> Effect String hash url = runEffectFn1 hashImpl url @@ -135,6 +142,74 @@ canParse input base = runFn2 canParseImpl input base foreign import canParseImpl :: Fn2 (String) (String) (Boolean) --- searchParams - -foreign import data URLSearchParams :: Type +domainToAscii :: String -> Effect String +domainToAscii domain = runEffectFn1 domainToAsciiImpl domain + +foreign import domainToAsciiImpl :: EffectFn1 (String) (String) + +domainToUnicode :: String -> Effect String +domainToUnicode domain = runEffectFn1 domainToUnicodeImpl domain + +foreign import domainToUnicodeImpl :: EffectFn1 (String) (String) + +fileURLToPath :: String -> Effect String +fileURLToPath str = runEffectFn1 fileURLToPathImpl str + +foreign import fileURLToPathImpl :: EffectFn1 String String + +fileURLToPath' :: URL -> Effect String +fileURLToPath' url = runEffectFn1 fileURLToPathUrlImpl url + +foreign import fileURLToPathUrlImpl :: EffectFn1 URL String + +-- | - `auth` true if the serialized URL string should include the username and password, false otherwise. Default: true. +-- | - `fragment` true if the serialized URL string should include the fragment, false otherwise. Default: true. +-- | - `search` true if the serialized URL string should include the search query, false otherwise. Default: true. +-- | - `unicode` true if Unicode characters appearing in the host component of the URL string should be encoded directly as opposed to being Punycode encoded. Default: false. +type UrlFormatOptions = + ( auth :: Boolean + , fragment :: Boolean + , search :: Boolean + , unicode :: Boolean + ) + +format + :: forall r trash + . Row.Union r trash UrlFormatOptions + => URL + -> { | r } + -> Effect String +format url opts = runEffectFn2 formatImpl url opts + +foreign import formatImpl :: forall r. EffectFn2 (URL) ({ | r }) (String) + +pathToFileUrl :: String -> Effect URL +pathToFileUrl path = runEffectFn1 pathToFileUrlImpl path + +foreign import pathToFileUrlImpl :: EffectFn1 (String) (URL) + +-- | - `protocol` Protocol to use. +-- | - `hostname` A domain name or IP address of the server to issue the request to. +-- | - `hash` The fragment portion of the URL. +-- | - `search` The serialized query portion of the URL. +-- | - `pathname` The path portion of the URL. +-- | - `path` Request path. Should include query string if any. E.G. '/index.html?page=12'. An exception is thrown when the request path contains illegal characters. Currently, only spaces are rejected but that may change in the future. +-- | - `href` The serialized URL. +-- | - `port` Port of remote server. +-- | - `auth` Basic authentication i.e. 'user:password' to compute an Authorization header. +type HttpOptions = + { protocol :: String + , hostname :: String + , hash :: String + , search :: String + , pathname :: String + , path :: String + , href :: String + , port :: Int + , auth :: String + } + +urlToHTTPOptions :: URL -> Effect HttpOptions +urlToHTTPOptions url = runEffectFn1 urlToHttpOptionsImpl url + +foreign import urlToHttpOptionsImpl :: EffectFn1 (URL) (HttpOptions) From cb4432898d4d3553e399c1fc99ab268d36348388 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 17:37:01 -0500 Subject: [PATCH 06/16] Add both variants of format --- src/Node/URL.js | 3 ++- src/Node/URL.purs | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Node/URL.js b/src/Node/URL.js index ea42e01..c700aad 100644 --- a/src/Node/URL.js +++ b/src/Node/URL.js @@ -52,6 +52,7 @@ export const domainToAsciiImpl = (domain) => url.domainToASCII(domain); export const domainToUnicodeImpl = (domain) => url.domainToUnicode(domain); export const fileURLToPathImpl = (str) => url.fileURLToPath(str); export const fileURLToPathUrlImpl = (str) => url.fileURLToPath(str); -export const formatImpl = (theUrl, opts) => url.format(theUrl, opts); +export const formatImpl = (theUrl) => url.format(theUrl); +export const formatOptsImpl = (theUrl, opts) => url.format(theUrl, opts); export const pathToFileUrlImpl = (path) => url.pathToFileURL(path); export const urlToHttpOptionsImpl = (theUrl) => url.urlToHttpOptions(theUrl); diff --git a/src/Node/URL.purs b/src/Node/URL.purs index aee10ab..a01b872 100644 --- a/src/Node/URL.purs +++ b/src/Node/URL.purs @@ -162,6 +162,11 @@ fileURLToPath' url = runEffectFn1 fileURLToPathUrlImpl url foreign import fileURLToPathUrlImpl :: EffectFn1 URL String +format :: URL -> Effect String +format url = runEffectFn1 formatImpl url + +foreign import formatImpl :: EffectFn1 (URL) (String) + -- | - `auth` true if the serialized URL string should include the username and password, false otherwise. Default: true. -- | - `fragment` true if the serialized URL string should include the fragment, false otherwise. Default: true. -- | - `search` true if the serialized URL string should include the search query, false otherwise. Default: true. @@ -173,15 +178,15 @@ type UrlFormatOptions = , unicode :: Boolean ) -format +format' :: forall r trash . Row.Union r trash UrlFormatOptions => URL -> { | r } -> Effect String -format url opts = runEffectFn2 formatImpl url opts +format' url opts = runEffectFn2 formatOptsImpl url opts -foreign import formatImpl :: forall r. EffectFn2 (URL) ({ | r }) (String) +foreign import formatOptsImpl :: forall r. EffectFn2 (URL) ({ | r }) (String) pathToFileUrl :: String -> Effect URL pathToFileUrl path = runEffectFn1 pathToFileUrlImpl path From ff2c01f66936a8b93226ef3012d301b69a8fc125 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 17:37:13 -0500 Subject: [PATCH 07/16] Update export lists to exclude FFI --- src/Node/URL.purs | 40 ++++++++++++++++++++++++++++++- src/Node/URL/URLSearchParams.purs | 19 ++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/Node/URL.purs b/src/Node/URL.purs index a01b872..e5bf177 100644 --- a/src/Node/URL.purs +++ b/src/Node/URL.purs @@ -1,4 +1,42 @@ -module Node.URL where +module Node.URL + ( URL + , new + , new' + , pathToFileURL + , hash + , setHash + , host + , setHost + , hostname + , setHostname + , href + , setHref + , origin + , password + , setPassword + , pathname + , setPathname + , port + , setPort + , protocol + , setProtocol + , search + , setSearch + , searchParams + , username + , setUsername + , canParse + , domainToAscii + , domainToUnicode + , fileURLToPath + , fileURLToPath' + , UrlFormatOptions + , format + , format' + , pathToFileUrl + , HttpOptions + , urlToHTTPOptions + ) where import Prelude diff --git a/src/Node/URL/URLSearchParams.purs b/src/Node/URL/URLSearchParams.purs index 1c1dd36..4dc7d1f 100644 --- a/src/Node/URL/URLSearchParams.purs +++ b/src/Node/URL/URLSearchParams.purs @@ -1,4 +1,21 @@ -module Node.URL.URLSearchParams where +module Node.URL.URLSearchParams + ( URLSearchParams + , new + , fromString + , fromObject + , appendParam + , delete + , getName + , getAll + , has + , set + , size + , sort + , toString + , entries + , keys + , values + ) where import Prelude From 2fbb790c4fcb00a7bb7942a751048f089a486b7f Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 17:37:18 -0500 Subject: [PATCH 08/16] Update tests --- test/Main.purs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/Main.purs b/test/Main.purs index 7a5d9ee..dd259bb 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -3,10 +3,12 @@ module Test.Main where import Prelude import Effect (Effect) -import Node.URL (format, parse, parseQueryString, toQueryString) +import Node.URL as URL import Test.Assert (assertEqual) main ∷ Effect Unit main = do - assertEqual { expected: "http://example.com/", actual: format $ parse "http://example.com/" } - assertEqual { expected: "foo=42", actual: toQueryString $ parseQueryString "foo=42" } + let urlStr = "http://example.com/" + url <- URL.new urlStr + urlStr' <- URL.format url + assertEqual { expected: urlStr, actual: urlStr' } From e33cbfd1a7f44d27c43443c865117500fe91a956 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 17:37:24 -0500 Subject: [PATCH 09/16] Add changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c070b3c..c72bf69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ Notable changes to this project are documented in this file. The format is based ## [Unreleased] Breaking changes: +- Drop support for Legacy API (#20 by @JordanMartinez) +- Implement WHATWG URL API bindings (#20 by @JordanMartinez) New features: From 53de3790ea549b5167f3f1717946497006501667 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 17:38:11 -0500 Subject: [PATCH 10/16] Add entry for queryString droppage --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c72bf69..0885a41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Notable changes to this project are documented in this file. The format is based Breaking changes: - Drop support for Legacy API (#20 by @JordanMartinez) +- Drop support for `querystring` bindings (#20 by @JordanMartinez) - Implement WHATWG URL API bindings (#20 by @JordanMartinez) New features: From 0cffdf306fd74a25d5dfe85a34f7530e21f543a5 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 17:43:21 -0500 Subject: [PATCH 11/16] Update CI actions/node; add purs-tidy --- .github/workflows/ci.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 06ed895..c9b2d23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,15 +10,16 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: purescript-contrib/setup-purescript@main with: purescript: "unstable" + purs-tidy: "latest" - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 with: - node-version: "14" + node-version: "lts/*" - name: Install dependencies run: | @@ -33,3 +34,8 @@ jobs: run: | bower install npm run-script test --if-present + + - name: Check formatting + run: | + purs-tidy check src test + \ No newline at end of file From 88260219b20542ecf8ccc4c679c92f88ec566e4d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 17:43:40 -0500 Subject: [PATCH 12/16] Drop old bindings --- src/Node/Old/URL.js | 10 ---------- src/Node/Old/URL.purs | 44 ------------------------------------------- 2 files changed, 54 deletions(-) delete mode 100644 src/Node/Old/URL.js delete mode 100644 src/Node/Old/URL.purs diff --git a/src/Node/Old/URL.js b/src/Node/Old/URL.js deleted file mode 100644 index c8afc32..0000000 --- a/src/Node/Old/URL.js +++ /dev/null @@ -1,10 +0,0 @@ -import url from "url"; -import queryString from "querystring"; -export { parse, format } from "url"; - -export function resolve(from) { - return to => url.resolve(from, to); -} - -export const parseQueryString = queryString.parse; -export const toQueryString = queryString.stringify; diff --git a/src/Node/Old/URL.purs b/src/Node/Old/URL.purs deleted file mode 100644 index 29d9e74..0000000 --- a/src/Node/Old/URL.purs +++ /dev/null @@ -1,44 +0,0 @@ --- | This module defines bindings to the Node URL and Query String APIs. - -module Node.Old.URL where - -import Data.Nullable - --- | A query object is a JavaScript object whose values are strings or arrays of strings. --- | --- | It is intended that the user coerce values of this type to/from some trusted representation via --- | e.g. `Data.Foreign` or `Unsafe.Coerce`.. -data Query - --- | A URL object. --- | --- | All fields are nullable, and will be missing if the URL string passed to --- | `parse` did not contain the appropriate URL part. -type URL = - { protocol :: Nullable String - , slashes :: Nullable Boolean - , host :: Nullable String - , auth :: Nullable String - , hostname :: Nullable String - , port :: Nullable String - , pathname :: Nullable String - , search :: Nullable String - , path :: Nullable String - , query :: Nullable String - , hash :: Nullable String - } - --- | Parse a URL string into a URL object. -foreign import parse :: String -> URL - --- | Format a URL object as a URL string. -foreign import format :: URL -> String - --- | Resolve a URL relative to some base URL. -foreign import resolve :: String -> String -> String - --- | Convert a query string to an object. -foreign import parseQueryString :: String -> Query - --- | Convert a query string to an object. -foreign import toQueryString :: Query -> String From b8dcd3e6a47018ce213622c127fb5af8fd637bb3 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 17:44:05 -0500 Subject: [PATCH 13/16] Fix lint error --- src/Node/URL/URLSearchParams.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Node/URL/URLSearchParams.js b/src/Node/URL/URLSearchParams.js index f8730dd..0b4d46f 100644 --- a/src/Node/URL/URLSearchParams.js +++ b/src/Node/URL/URLSearchParams.js @@ -1,5 +1,5 @@ const newImpl = () => new URLSearchParams(); -export { newImpl as new } +export { newImpl as new }; export const fromStringImpl = (str) => new URLSearchParams(str); export const fromObjectImpl = (obj) => new URLSearchParams(obj); export const appendParamImpl = (name, value, params) => params.append(name, value); From 5075a0a1d04056c2b55e415cc03125484bbe1e42 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 21:19:07 -0500 Subject: [PATCH 14/16] Fix remaining eslint issues --- src/Node/URL.js | 2 +- src/Node/URL/URLSearchParams.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Node/URL.js b/src/Node/URL.js index c700aad..e669819 100644 --- a/src/Node/URL.js +++ b/src/Node/URL.js @@ -47,7 +47,7 @@ export const setUsernameImpl = (val, u) => { u.username = val; }; -export const canParseImpl = (input, base) => URL.canParse(input, base); +export const canParseImpl = (input, base) => url.URL.canParse(input, base); export const domainToAsciiImpl = (domain) => url.domainToASCII(domain); export const domainToUnicodeImpl = (domain) => url.domainToUnicode(domain); export const fileURLToPathImpl = (str) => url.fileURLToPath(str); diff --git a/src/Node/URL/URLSearchParams.js b/src/Node/URL/URLSearchParams.js index 0b4d46f..3c185cd 100644 --- a/src/Node/URL/URLSearchParams.js +++ b/src/Node/URL/URLSearchParams.js @@ -1,7 +1,9 @@ -const newImpl = () => new URLSearchParams(); +import url from "node:url"; + +const newImpl = () => new url.URLSearchParams(); export { newImpl as new }; -export const fromStringImpl = (str) => new URLSearchParams(str); -export const fromObjectImpl = (obj) => new URLSearchParams(obj); +export const fromStringImpl = (str) => new url.URLSearchParams(str); +export const fromObjectImpl = (obj) => new url.URLSearchParams(obj); export const appendParamImpl = (name, value, params) => params.append(name, value); export const deleteImpl = (name, params) => params.delete(name); export const getNameImpl = (name, params) => params.getName(name); From b03a51554fdb26aec0e8cfc22ad78358bf83d7a4 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 21:21:12 -0500 Subject: [PATCH 15/16] Add another entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42fd930..e136b57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Breaking changes: - Implement WHATWG URL API bindings (#20 by @JordanMartinez) New features: +- Implement bindings for `URLSearchParams` (#20 by @JordanMartinez) Bugfixes: From 37d33d5f7412f761a58de3e869d8b7d37e46b28e Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 31 Jul 2023 21:22:37 -0500 Subject: [PATCH 16/16] Make next release entry --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e136b57..2533bae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ Notable changes to this project are documented in this file. The format is based ## [Unreleased] +Breaking changes: + +New features: + +Bugfixes: + +Other improvements: + +## [v7.0.0](https://github.com/purescript-node/purescript-node-url/releases/tag/v7.0.0) - 2023-07-31 + Breaking changes: - Drop support for Legacy API (#20 by @JordanMartinez) - Drop support for `querystring` bindings (#20 by @JordanMartinez)