-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update to PureScript v0.15.0 #171
Update to PureScript v0.15.0 #171
Conversation
CI fails for now as I'm not entirely sure how we should update the FFI here. |
This patch would make eslint pass and get tests to run as well. diff --git a/.eslintrc.json b/.eslintrc.json
index 9d6a62b..d894fe7 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,6 +1,7 @@
{
"extends": "eslint:recommended",
"parserOptions": { "ecmaVersion": 6, "sourceType": "module" },
+ "env": { "browser": "true", "node": true },
"rules": {
"block-scoped-var": "error",
"consistent-return": "error",
diff --git a/packages.dhall b/packages.dhall
index 582d6d3..a7ee8b2 100644
--- a/packages.dhall
+++ b/packages.dhall
@@ -1,4 +1,5 @@
let upstream =
https://raw.githubusercontent.com/purescript/package-sets/prepare-0.15/src/packages.dhall
+ sha256:b7f601683fe3f760ea88f2375c2b08cfe43b98c9a4fc6d000ae8bc49ac8bfb07
in upstream
diff --git a/src/Affjax.js b/src/Affjax.js
index 318172a..5b011cf 100644
--- a/src/Affjax.js
+++ b/src/Affjax.js
@@ -1,6 +1,4 @@
-/* global XMLHttpRequest */
-/* global process */
-export function _ajax() {
+export function _ajax(timeoutErrorMessageIdent, requestFailedMessageIdent, mkHeader, options) {
var platformSpecific = { };
if (typeof module !== "undefined" && module.require && !(typeof process !== "undefined" && process.versions["electron"])) {
// We are on node.js
@@ -39,56 +37,54 @@ export function _ajax() {
};
}
- return function (timeoutErrorMessageIdent, requestFailedMessageIdent, mkHeader, options) {
- return function (errback, callback) {
- var xhr = platformSpecific.newXHR();
- var fixedUrl = platformSpecific.fixupUrl(options.url, xhr);
- xhr.open(options.method || "GET", fixedUrl, true, options.username, options.password);
- if (options.headers) {
- try {
- // eslint-disable-next-line no-eq-null,eqeqeq
- for (var i = 0, header; (header = options.headers[i]) != null; i++) {
- xhr.setRequestHeader(header.field, header.value);
- }
- } catch (e) {
- errback(e);
+ return function (errback, callback) {
+ var xhr = platformSpecific.newXHR();
+ var fixedUrl = platformSpecific.fixupUrl(options.url, xhr);
+ xhr.open(options.method || "GET", fixedUrl, true, options.username, options.password);
+ if (options.headers) {
+ try {
+ // eslint-disable-next-line no-eq-null,eqeqeq
+ for (var i = 0, header; (header = options.headers[i]) != null; i++) {
+ xhr.setRequestHeader(header.field, header.value);
}
+ } catch (e) {
+ errback(e);
}
- var onerror = function (msgIdent) {
- return function () {
- errback(new Error(msgIdent));
- };
+ }
+ var onerror = function (msgIdent) {
+ return function () {
+ errback(new Error(msgIdent));
};
- xhr.onerror = onerror(requestFailedMessageIdent);
- xhr.ontimeout = onerror(timeoutErrorMessageIdent);
- xhr.onload = function () {
- callback({
- status: xhr.status,
- statusText: xhr.statusText,
- headers: xhr.getAllResponseHeaders().split("\r\n")
- .filter(function (header) {
- return header.length > 0;
- })
- .map(function (header) {
- var i = header.indexOf(":");
- return mkHeader(header.substring(0, i))(header.substring(i + 2));
- }),
- body: platformSpecific.getResponse(xhr)
- });
- };
- xhr.responseType = options.responseType;
- xhr.withCredentials = options.withCredentials;
- xhr.timeout = options.timeout;
- xhr.send(options.content);
+ };
+ xhr.onerror = onerror(requestFailedMessageIdent);
+ xhr.ontimeout = onerror(timeoutErrorMessageIdent);
+ xhr.onload = function () {
+ callback({
+ status: xhr.status,
+ statusText: xhr.statusText,
+ headers: xhr.getAllResponseHeaders().split("\r\n")
+ .filter(function (header) {
+ return header.length > 0;
+ })
+ .map(function (header) {
+ var i = header.indexOf(":");
+ return mkHeader(header.substring(0, i))(header.substring(i + 2));
+ }),
+ body: platformSpecific.getResponse(xhr)
+ });
+ };
+ xhr.responseType = options.responseType;
+ xhr.withCredentials = options.withCredentials;
+ xhr.timeout = options.timeout;
+ xhr.send(options.content);
- return function (error, cancelErrback, cancelCallback) {
- try {
- xhr.abort();
- } catch (e) {
- return cancelErrback(e);
- }
- return cancelCallback();
- };
+ return function (error, cancelErrback, cancelCallback) {
+ try {
+ xhr.abort();
+ } catch (e) {
+ return cancelErrback(e);
+ }
+ return cancelCallback();
};
};
-}();
+}
\ No newline at end of file
diff --git a/test/Main.js b/test/Main.js
index 5813d41..b0bfa42 100644
--- a/test/Main.js
+++ b/test/Main.js
@@ -1,3 +1,10 @@
+import express from "express";
+import bodyParser from "body-parser";
+import { dirname } from 'path';
+import { fileURLToPath } from 'url';
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+
export function logAny(a) {
return function () {
console.log(a);
@@ -6,9 +13,7 @@ export function logAny(a) {
}
export function startServer(errback, callback) {
- var express = require('express');
var app = express();
- var bodyParser = require('body-parser');
// Always make req.body available as a String
app.use(bodyParser.text(function() { return true; })); |
I'm not sure this library can be fixed "properly" for ES modules while supporting both the browser and workarounds for node/electron/etc. I've been wondering for a while if this library's time has come, since there are competing sets of demands for what it should support, and things that don't fit well into the current model (progress events, for example). And there's An option that might be worth considering if we do want to keep it going, is to make this library implementation agnostic by having the functions accept a kind of "driver" value, and then create |
The first of the two options there - the idea behind what I said is that you only end up with the correct driver being included in the project, avoiding the need for any bundling-related workarounds. |
Ok, that works. Now how do we create new repositories? That's a gap in my knowledge. |
You can just initialize a new repository with Spago, then run the contrib updater tool. Docs here: https://github.com/purescript-contrib/governance/blob/main/updater/docs/01-Generate.md We may need to update the template files so that CI includes |
I'm having second thoughts about this, 😄 as it is a fairly large change. Basically, I want to resolve/avoid #161, and especially post-ESM I'm not sure how best to resolve it. It seems esbuild makes no attempt to resolve dynamic imports, so it would "just work" if we did something with that, but... yeah, I dunno. |
@garyb We discussed this repo's issue with ES modules in today's working group call. Below is an example for how the code is currently written: import Affjax as AX
import Affjax.RequestFormat as ResponseFormat
foo = do
result1 <- AX.get ResponseFormat.json "/api/one"
result2 <- AX.get ResponseFormat.json "/api/two"
result3 <- AX.get ResponseFormat.json "/api/three" Here is my understanding of Option 1. Option 1 means everyone would "consume" the import Affjax as AX
import Affjax.Driver.Node (nodeDriver)
import Affjax.RequestFormat as ResponseFormat
foo = do
result1 <- AX.get nodeDriver ResponseFormat.json "/api/one"
result2 <- AX.get nodeDriver ResponseFormat.json "/api/two"
result3 <- AX.get nodeDriver ResponseFormat.json "/api/three" Here's my understanding of Option 2. In option 2, end-users do not "consume" the - import Affjax as AX
import Affjax.RequestFormat as AXRF
+ import Affjax.Node as AXN
foo = do
result1 <- AXN.get ResponseFormat.json "/api/one"
result2 <- AXN.get ResponseFormat.json "/api/two"
result3 <- AXN.get ResponseFormat.json "/api/three" AFAIU, there isn't really a good way to make Affjax work on multiple environments while using ES modules. If my understanding between the two is correct, the second seems to entail less breakage than the first. What are your thoughts? Since you're the primary maintainer of this library, your decision stands. Whatever it is, I'd like to work on it so we can unblock the ecosystem update. |
I think both cases are much the same actually - to provide The only downside of including these functions per-driver is that it's more stuff to keep in sync if we introduce a new function in |
Ok, this PR and the other two are ready for review. Once this PR is approved and merged, I can add |
Also, I moved the request code out of |
Also, I didn't include the |
Re-implementing the xhr2 driver in test code is one option, but it kinda sucks. The other would to be to do some kind of browser automated testing thing, but that's probably even worse since it takes constant maintenance to keep browser-based testing working due to browser version upgrades and corresponding webdriver version bumps. We could just leave it without automated tests, as realistically the implementation there should be trivial, and unchanging after initial implementation, since it's just passing through the global object, and the rest of Affjax's FFI code will be exercised by the node driver tests. I don't really think there is a perfect solution. 😕 |
I'll take a look at the rest of the changes here later, probably tomorrow. Thanks for sorting all this out! |
I'll wait to add the packages to the registry until we know this is the direction we're going — once @garyb has had a chance to review. Thanks! |
Sounds good! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you're going for with moving the stuff out of Affjax
into Affjax.Driver
, but I think the naming of that is a little strange, since most of the module's content is not driver interface or implementation really. I'd suggest we just keep everything in Affjax
.
Actually, we should probably re-export Error
/printError
/etc from the new Affjax.Driver.*
modules too, so they can be a complete drop in for the Affjax
module when migrating existing code.
src/Affjax/Driver.purs
Outdated
foreign import data Xhr :: Type | ||
|
||
-- Drivers should have the following 'shape': | ||
-- ``` | ||
-- { newXHR :: Effect Xhr | ||
-- , fixupUrl :: Fn2 Xhr String String | ||
-- } | ||
-- ``` | ||
foreign import data AffjaxDriver :: Type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this Xhr
type, since it's not actually used anywhere aside from within this comment?
This is ready for another review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great 👌, thanks again for taking this on
@JordanMartinez Does the README still need to be updated to clarify how to use Affjax on Node or the browser now? |
@thomashoneyman Ah, yeah it does. |
Description of the change
Backlinking to purescript/purescript#4244
Migrates FFI to ES modules
Checklist: