diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..3c4498a --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,29 @@ +{ + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module" + }, + "extends": "eslint:recommended", + "env": { + "browser": true + }, + "rules": { + "strict": [2, "global"], + "block-scoped-var": 2, + "consistent-return": 2, + "eqeqeq": [2, "smart"], + "guard-for-in": 2, + "no-caller": 2, + "no-extend-native": 2, + "no-loop-func": 2, + "no-new": 2, + "no-param-reassign": 2, + "no-return-assign": 2, + "no-unused-expressions": 2, + "no-use-before-define": 2, + "radix": [2, "always"], + "indent": [2, 2], + "quotes": [2, "double"], + "semi": [2, "always", { "omitLastInOneLineBlock": true }] + } +} diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..4435abb --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,12 @@ +**Description of the change** + +Clearly and concisely describe the purpose of the pull request. If this PR relates to an existing issue or change proposal, please link to it. Include any other background context that would help reviewers understand the motivation for this PR. + +--- + +**Checklist:** + +- [ ] Added the change to the changelog's "Unreleased" section with a reference to this PR (e.g. "- Made a change (#0000)") +- [ ] Linked any existing issues or proposals that this pull request should close +- [ ] Updated or added relevant documentation +- [ ] Added a test for the contribution (if applicable) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..06ed895 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,35 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: purescript-contrib/setup-purescript@main + with: + purescript: "unstable" + + - uses: actions/setup-node@v2 + with: + node-version: "14" + + - name: Install dependencies + run: | + npm install -g bower + npm install + bower install --production + + - name: Build source + run: npm run-script build + + - name: Run tests + run: | + bower install + npm run-script test --if-present diff --git a/.gitignore b/.gitignore index 20e090a..a56845c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ +/.* +!/.gitignore +!/.eslintrc.json +!/.github/ +package-lock.json /bower_components/ /node_modules/ -/.pulp-cache/ /output/ /generated-docs/ -/.psc-package/ -/.psc* -/.purs* -/.psa* diff --git a/.tidyrc.json b/.tidyrc.json new file mode 100644 index 0000000..9e39cf1 --- /dev/null +++ b/.tidyrc.json @@ -0,0 +1,10 @@ +{ + "importSort": "ide", + "importWrap": "source", + "indent": 2, + "operatorsFile": null, + "ribbon": 1, + "typeArrowPlacement": "first", + "unicode": "never", + "width": null +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..bc1b2e0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,46 @@ +# Changelog + +Notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +Breaking changes: +- Migrated from `web-promise` to `js-promise` + +New features: + +Bugfixes: + +Other improvements: + +## [v3.0.0](https://github.com/purescript-web/purescript-web-fetch/releases/tag/v3.0.0) - 2022-04-27 + +Breaking changes: +- Migrate FFI to ES modules (#8 by @JordanMartinez) + +New features: + +Bugfixes: + +Other improvements: + +## [v2.0.0](https://github.com/purescript-web/purescript-web-fetch/releases/tag/v2.0.0) - 2021-02-26 + +Breaking changes: +- Added support for PureScript 0.14 and dropped support for all previous versions (#2) + +New features: + +Bugfixes: + +Other improvements: +- Migrated CI to GitHub Actions and updated installation instructions to use Spago (#1) +- Added a CHANGELOG.md file and pull request template (#3, #4) + +## [v1.0.1](https://github.com/purescript-web/purescript-web-fetch/releases/tag/v1.0.1) - 2020-01-15 + +- Fixed illegal fetch invocation when not specifying options + +## [v1.0.0](https://github.com/purescript-web/purescript-web-fetch/releases/tag/v1.0.0) - 2020-01-14 + +- Initial release diff --git a/README.md b/README.md index e21f9c0..359bcb1 100644 --- a/README.md +++ b/README.md @@ -1 +1,17 @@ # purescript-web-fetch + +[![Latest release](http://img.shields.io/github/release/purescript-web/purescript-web-fetch.svg)](https://github.com/purescript-web/purescript-web-fetch/releases) +[![Build status](https://github.com/purescript-web/purescript-web-fetch/workflows/CI/badge.svg?branch=master)](https://github.com/purescript-web/purescript-web-fetch/actions?query=workflow%3ACI+branch%3Amaster) +[![Pursuit](https://pursuit.purescript.org/packages/purescript-web-fetch/badge)](https://pursuit.purescript.org/packages/purescript-web-fetch) + +Types and low-level implementations for the [WHATWG Fetch Living Standard](https://fetch.spec.whatwg.org/). + +## Installation + +``` +spago install web-fetch +``` + +## Documentation + +Module documentation is [published on Pursuit](http://pursuit.purescript.org/packages/purescript-web-fetch). diff --git a/bower.json b/bower.json index e98dd21..15e3937 100644 --- a/bower.json +++ b/bower.json @@ -4,7 +4,7 @@ "license": "MIT", "repository": { "type": "git", - "url": "git://github.com/purescript-web/purescript-web-fetch.git" + "url": "https://github.com/purescript-web/purescript-web-fetch.git" }, "ignore": [ "**/.*", @@ -15,14 +15,14 @@ "package.json" ], "dependencies": { - "purescript-prelude": "^4.0.0", - "purescript-effect": "^2.0.0", - "purescript-http-methods": "^4.0.0", - "purescript-typelevel-prelude": "^5.0.0", - "purescript-web-file": "^2.3.0", - "purescript-record": "^2.0.0", - "purescript-foreign-object": "^2.0.0", - "purescript-web-promise": "https://github.com/purescript-web/purescript-web-promise.git#^1.0.0", - "purescript-web-streams": "https://github.com/purescript-web/purescript-web-streams.git#^1.0.0" + "purescript-effect": "^4.0.0", + "purescript-foreign-object": "^4.0.0", + "purescript-http-methods": "^6.0.0", + "purescript-js-promise": "https://github.com/purescript-contrib/purescript-js-promise.git#^1.0.0", + "purescript-prelude": "^6.0.0", + "purescript-record": "^4.0.0", + "purescript-typelevel-prelude": "^7.0.0", + "purescript-web-file": "^4.0.0", + "purescript-web-streams": "https://github.com/purescript-web/purescript-web-streams.git#^4.0.0" } } diff --git a/package.json b/package.json new file mode 100644 index 0000000..532609e --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "private": true, + "scripts": { + "clean": "rimraf output && rimraf .pulp-cache", + "build": "eslint src && purs-tidy check --config-require src/**/*.purs && pulp build -- --censor-lib --strict" + }, + "devDependencies": { + "eslint": "^8.28.0", + "pulp": "^16.0.2", + "purescript-psa": "^0.8.2", + "purs-tidy": "^0.9.2", + "rimraf": "^3.0.2" + } +} diff --git a/src/Web/Fetch.js b/src/Web/Fetch.js index 23a2873..6168ebe 100644 --- a/src/Web/Fetch.js +++ b/src/Web/Fetch.js @@ -1 +1,3 @@ -exports._fetch = fetch; \ No newline at end of file +export function _fetch(a, b) { + return fetch(a, b); +} diff --git a/src/Web/Fetch.purs b/src/Web/Fetch.purs index 9ef390a..bb05340 100644 --- a/src/Web/Fetch.purs +++ b/src/Web/Fetch.purs @@ -7,10 +7,10 @@ module Web.Fetch import Effect (Effect) import Effect.Uncurried (EffectFn2, runEffectFn2) import Prim.Row as Row +import Promise (Promise) import Web.Fetch.AbortController (AbortSignal) import Web.Fetch.Request (Request) import Web.Fetch.Response (Response) -import Web.Promise (Promise) type FetchOptions = ( keepalive :: Boolean diff --git a/src/Web/Fetch/AbortController.js b/src/Web/Fetch/AbortController.js index d77c3e9..e9bf3d5 100644 --- a/src/Web/Fetch/AbortController.js +++ b/src/Web/Fetch/AbortController.js @@ -1,13 +1,14 @@ -exports.new = function() { +const newImpl = function () { return new AbortController(); }; +export { newImpl as new }; -exports.abort = function(controller) { +export function abort(controller) { return function() { return controller.abort(); }; -}; +} -exports.signal = function(controller) { +export function signal(controller) { return controller.signal; -}; \ No newline at end of file +} diff --git a/src/Web/Fetch/Headers.js b/src/Web/Fetch/Headers.js index 2a3c76e..dd8398d 100644 --- a/src/Web/Fetch/Headers.js +++ b/src/Web/Fetch/Headers.js @@ -1,23 +1,21 @@ -exports.unsafeNew = function() { +export function unsafeNew() { return new Headers(); -}; +} -exports.unsafeAppend = function(key, value, headers) { +export function unsafeAppend(key, value, headers) { return headers.append(key, value); -}; +} -exports.unsafeFromRecord = function(r) { +export function unsafeFromRecord(r) { return new Headers(r); -}; +} -exports._toArray = function(tuple, headers) { - var arr = []; - for (var pair of headers.entries()) { - arr.push(tuple(pair[0])(pair[1])); - } - return arr; +export function _toArray(tuple, headers) { + return Array.from(headers.entries(), function (pair) { + return tuple(pair[0])(pair[1]); + }); } -exports.fromObject = function(obj) { +export function fromObject(obj) { return new Headers(obj); -}; \ No newline at end of file +} diff --git a/src/Web/Fetch/Request.js b/src/Web/Fetch/Request.js index 2b18702..0f30528 100644 --- a/src/Web/Fetch/Request.js +++ b/src/Web/Fetch/Request.js @@ -1,8 +1,8 @@ -exports._unsafeNew = function(url, options) { +export function _unsafeNew(url, options) { try { return new Request(url, options); } catch (e) { console.error(e); throw e; } -}; \ No newline at end of file +} diff --git a/src/Web/Fetch/Request.purs b/src/Web/Fetch/Request.purs index db198dc..35ff325 100644 --- a/src/Web/Fetch/Request.purs +++ b/src/Web/Fetch/Request.purs @@ -22,17 +22,17 @@ import Data.HTTP.Method (Method(..)) import Data.Maybe (Maybe(..)) import Data.Newtype (un) import Data.Nullable (Nullable, toNullable) -import Data.Symbol (class IsSymbol, SProxy(..)) +import Data.Symbol (class IsSymbol) import Data.Tuple (Tuple) import Effect (Effect) import Effect.Uncurried (EffectFn2, runEffectFn2) import Foreign.Object (Object) import Prim.Row as Row -import Prim.RowList (kind RowList) +import Prim.RowList (RowList) import Prim.RowList as RowList import Record (merge) import Record.Builder as Record -import Type.Data.RowList (RLProxy(..)) +import Type.Proxy (Proxy(..)) import Type.Row.Homogeneous (class Homogeneous) import Web.Fetch.Headers (Headers) import Web.Fetch.Headers as Headers @@ -126,10 +126,10 @@ instance buildRequestOptionsRecord , Row.Nub r'' RequestOptions ) => BuildRequestOptions { | r } where - buildRequestOptions r = merge (Record.build (convertOptions (RLProxy :: _ rl)) r) defaultOptions + buildRequestOptions r = merge (Record.build (convertOptions (Proxy :: _ rl)) r) defaultOptions -class ConvertOptions (rl :: RowList) (input :: # Type) (output :: # Type) | rl input -> output where - convertOptions :: RLProxy rl -> Record.Builder { | input } { | output } +class ConvertOptions (rl :: RowList Type) (input :: Row Type) (output :: Row Type) | rl input -> output where + convertOptions :: forall rlproxy. rlproxy rl -> Record.Builder { | input } { | output } instance convertOptionsCons :: ( ConvertOptions rest input' output @@ -139,14 +139,14 @@ instance convertOptionsCons :: , IsSymbol field ) => ConvertOptions (RowList.Cons field from rest) input output where convertOptions _ = - convertOptions (RLProxy :: _ rest) - <<< Record.modify (SProxy :: _ field) (convertOption (SProxy :: _ field)) + convertOptions (Proxy :: _ rest) + <<< Record.modify (Proxy :: _ field) (convertOption (Proxy :: _ field)) instance convertOptionsNil :: ConvertOptions RowList.Nil r r where convertOptions _ = identity class ConvertOption (field :: Symbol) from to | field -> to where - convertOption :: SProxy field -> from -> to + convertOption :: forall sproxy. sproxy field -> from -> to instance convertMethod :: ConvertOption "method" Method Method where convertOption _ = identity @@ -188,4 +188,4 @@ instance convertReferrerPolicy :: ConvertOption "referrerPolicy" ReferrerPolicy convertOption _ = identity instance convertIntegrity :: ConvertOption "integrity" Integrity Integrity where - convertOption _ = identity \ No newline at end of file + convertOption _ = identity diff --git a/src/Web/Fetch/RequestBody.js b/src/Web/Fetch/RequestBody.js index 7a7a717..6727e56 100644 --- a/src/Web/Fetch/RequestBody.js +++ b/src/Web/Fetch/RequestBody.js @@ -1,5 +1,5 @@ -exports.fromArrayBuffer = function(a) { return a }; -exports.fromArrayView = function(a) { return a }; -exports.fromString = function(a) { return a }; -exports.fromReadableStream = function(a) { return a }; -exports.empty = null; \ No newline at end of file +export function fromArrayBuffer(a) { return a } +export function fromArrayView(a) { return a } +export function fromString(a) { return a } +export function fromReadableStream(a) { return a } +export const empty = null; diff --git a/src/Web/Fetch/Response.js b/src/Web/Fetch/Response.js index decb2c9..7c2db67 100644 --- a/src/Web/Fetch/Response.js +++ b/src/Web/Fetch/Response.js @@ -1,47 +1,47 @@ -exports.headers = function (resp) { +export function headers(resp) { return resp.headers; -}; +} -exports.ok = function (resp) { +export function ok(resp) { return resp.ok; -}; +} -exports.redirected = function (resp) { +export function redirected(resp) { return resp.redirected; -}; +} -exports.status = function (resp) { +export function status(resp) { return resp.status; -}; +} -exports.statusText = function (resp) { +export function statusText(resp) { return resp.statusText; -}; +} -exports.url = function (resp) { +export function url(resp) { return resp.url; -}; +} -exports.body = function (resp) { +export function body(resp) { return function() { return resp.body; }; -}; +} -exports.arrayBuffer = function (resp) { +export function arrayBuffer(resp) { return function() { return resp.arrayBuffer(); }; -}; +} -exports.blob = function (resp) { +export function blob(resp) { return function() { return resp.blob(); }; -}; +} -exports.text = function (resp) { +export function text(resp) { return function() { return resp.text(); }; -}; \ No newline at end of file +} diff --git a/src/Web/Fetch/Response.purs b/src/Web/Fetch/Response.purs index fc0e9e7..8f2c721 100644 --- a/src/Web/Fetch/Response.purs +++ b/src/Web/Fetch/Response.purs @@ -2,9 +2,9 @@ module Web.Fetch.Response where import Data.ArrayBuffer.Types (ArrayBuffer, Uint8Array) import Effect (Effect) +import Promise (Promise) import Web.Fetch.Headers (Headers) import Web.File.Blob (Blob) -import Web.Promise (Promise) import Web.Streams.ReadableStream (ReadableStream) foreign import data Response :: Type