hyperbole 0.4.2 → 0.4.3
raw patch · 11 files changed
+117/−64 lines, 11 filesdep −Diffdep ~cookiedep ~web-view
Dependencies removed: Diff
Dependency ranges changed: cookie, web-view
Files
- CHANGELOG.md +4/−0
- README.md +57/−26
- client/dist/hyperbole.js +1/−1
- hyperbole.cabal +6/−7
- src/Web/Hyperbole.hs +6/−6
- src/Web/Hyperbole/Effect/Hyperbole.hs +1/−9
- src/Web/Hyperbole/Effect/Query.hs +21/−5
- src/Web/Hyperbole/Effect/Server.hs +6/−4
- src/Web/Hyperbole/HyperView.hs +2/−2
- src/Web/Hyperbole/View/Event.hs +3/−4
- test/Test/ViewActionSpec.hs +10/−0
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for hyperbole +## 0.4.3 -- 2024-01-31++* Bug fixes and improvements+ ## 0.4.2 -- 2024-01-21 * Cleaner HyperView class [(@cgeorgii)](https://github.com/cgeorgii)
README.md view
@@ -1,4 +1,4 @@-+ [](https://hackage.haskell.org/package/hyperbole) @@ -113,30 +113,8 @@ The NSO uses Hyperbole for the Level 2 Data creation tool for the [DKIST telescope](https://nso.edu/telescopes/dki-solar-telescope/). It is completely [open source](https://github.com/DKISTDC/level2/). This production application contains complex interfaces, workers, databases, and more. --Local Development--------------------### Recommended ghcid command--If you want to work on both the hyperbole library and example code, this `ghcid` command will run (and hot reload) the examples server as you change any non-testing code.--```-ghcid --setup=Main.update --command="cabal repl exe:examples lib:hyperbole" --run=Main.update --warnings --reload=./client/dist/hyperbole.js-```--If you want to work on the test suite, this will run the tests each time any library code is changed.--```-ghcid --command="cabal repl test lib:hyperbole" --run=Main.main --warnings --reload=./client/dist/hyperbole.js-```--### Nix--Prepend targets with ghc982 or ghc966 to use GHC 9.8.2 or GHC 9.6.6--- `nix run` or `nix run .#ghc966-hyperbole-examples` to start the example project with GHC 9.8.2-- `nix develop` or `nix develop .#ghc982-shell` to get a shell with all dependencies installed for GHC 9.8.2. +How to Import Flake+------------ You can import this flake's overlay to add `hyperbole` to all package sets and override ghc966 and ghc982 with the packages to satisfy `hyperbole`'s dependencies. @@ -156,7 +134,7 @@ inherit system; overlays = [ hyperbole.overlays.default ]; };- haskellPackagesOverride = pkgs.haskell.packages.ghc966.override (old: {+ haskellPackagesOverride = pkgs.overriddenHaskellPackages.ghc966.override (old: { overrides = pkgs.lib.composeExtensions (old.overrides or (_: _: { })) (hfinal: hprev: { # your overrides here });@@ -171,7 +149,60 @@ } ``` ++Local Development+-----------------++### Recommended ghcid command++If you want to work on both the hyperbole library and example code, this `ghcid` command will run (and hot reload) the examples server as you change any non-testing code.++```+ghcid --setup=Main.update --command="cabal repl exe:examples lib:hyperbole" --run=Main.update --warnings --reload=./client/dist/hyperbole.js+```++If you want to work on the test suite, this will run the tests each time any library code is changed.++```+ghcid --command="cabal repl test lib:hyperbole" --run=Main.main --warnings --reload=./client/dist/hyperbole.js+```++### Nix++- `nix flake check` will build the library, example executable and devShell with ghc-9.8.2 and ghc-9.6.6+ - This is what the CI on GitHub runs+- `nix run` or `nix run .#ghc982-example` to start the example project with GHC 9.8.2+ - `nix run .#ghc966-example` to start the example project with GHC 9.6.6+- `nix develop` or `nix develop .#ghc982-shell` to get a shell with all dependencies installed for GHC 9.8.2. + - `nix develop .#ghc966-shell` to get a shell with all dependencies installed for GHC 9.6.6. +- `nix build`, `nix build .#ghc982-hyperbole` and `nix build .#ghc966-hyperbole` builds the library with the `overriddenHaskellPackages`+ - If you want to import this flake, use the overlay+- `nix flake update web-view` will update the `web-view` input+ Note: You can always run `cachix use hyperbole` to use the GitHub CI populated cache if you didn't allow adding 'extra-substituters' when first using this flake.++### Common Nix Issues++#### Not Allowed to Refer to GHC++If you get an error like:++```+error: output '/nix/store/64k8iw0ryz76qpijsnl9v87fb26v28z8-my-haskell-package-1.0.0.0' is not allowed to refer to the following paths:+ /nix/store/5q5s4a07gaz50h04zpfbda8xjs8wrnhg-ghc-9.6.3+```++Follow these [instructions](https://nixos.org/manual/nixpkgs/unstable/#haskell-packaging-helpers)++#### Dependencies Incorrect++If you need to update `web-view` run `nix flake update web-view`, otherwise:++You will need to update the overlay, look for where it says `"${packageName}" = hfinal.callCabal2nix packageName src { };` and add a line like `Diff = hfinal.callHackage "Diff" "0.5" { };` with the package and version you need.++#### Missing Files++Check the `include` inside the `nix-filter.lib` to see if all files needed by cabal are there. ### Manual dependency installation
client/dist/hyperbole.js view
@@ -1,3 +1,3 @@ /*! For license information please see hyperbole.js.LICENSE.txt */-(()=>{var e={296:e=>{function t(e,t=100,n={}){if("function"!=typeof e)throw new TypeError(`Expected the first parameter to be a function, got \`${typeof e}\`.`);if(t<0)throw new RangeError("`wait` must not be negative.");const{immediate:r}="boolean"==typeof n?{immediate:n}:n;let o,i,a,c,u;function s(){const t=o,n=i;return o=void 0,i=void 0,u=e.apply(t,n),u}function l(){const e=Date.now()-c;e<t&&e>=0?a=setTimeout(l,t-e):(a=void 0,r||(u=s()))}const d=function(...e){if(o&&this!==o&&Object.getPrototypeOf(this)===Object.getPrototypeOf(o))throw new Error("Debounced method called with different contexts of the same prototype.");o=this,i=e,c=Date.now();const n=r&&!a;return a||(a=setTimeout(l,t)),n&&(u=s()),u};return Object.defineProperty(d,"isPending",{get:()=>void 0!==a}),d.clear=()=>{a&&(clearTimeout(a),a=void 0)},d.flush=()=>{a&&d.trigger()},d.trigger=()=>{u=s(),d.clear()},d}e.exports.debounce=t,e.exports=t}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,n),i.exports}(()=>{"use strict";var e=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t=function(e,t){var n=e.length,r=-1;if(n)for(;++r<n&&!1!==t(e[r],r););},r=function(e,t,n){return e.node.insertBefore(t.node,n)};function o(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i,a,c=[],u=!0,s=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;u=!1}else for(;!(u=(r=i.call(n)).done)&&(c.push(r.value),c.length!==t);u=!0);}catch(e){s=!0,o=e}finally{try{if(!u&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(s)throw o}}return c}}(e,t)||function(e,t){if(e){if("string"==typeof e)return i(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?i(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}var a="string",c="number",u="boolean",s={},l=function(e,t,n){return{attrName:e,propName:t,type:n}};t([["style","cssText"],["class","className"]],(function(e){var t=o(e,2),n=t[0],r=t[1];s[n]=l(n,r||n,a)})),t(["autofocus","draggable","hidden","checked","multiple","muted","selected"],(function(e){s[e]=l(e,e,u)})),t([["tabindex","tabIndex"]],(function(e){var t=o(e,2),n=t[0],r=t[1];s[n]=l(n,r,c)}));var d="xlink:",f="http://www.w3.org/1999/xlink",v="xml:",h="http://www.w3.org/XML/1998/namespace",p=function(e,t,n,r){switch(t){case a:n===s.style.propName?e.style[n]=null===r?"":r:e[n]=null===r?"":r;break;case c:if(null===r){var o=n.toLowerCase();e.removeAttribute(o)}else if("0"===r)e[n]=0;else if("-1"===r)e[n]=-1;else{var i=parseInt(r,10);isNaN(i)||(e[n]=i)}break;case u:["","true"].indexOf(r)<0?e[n]=!1:e[n]=!0}},y=function n(o,i,c){if(o&&i){c=c||i.node.parentNode;var u=o.content&&o.content!==i.content;if(o.type!==i.type||u)return c.replaceChild(o.node,i.node),function(e,t){for(var n in e)t[n]=e[n]}(o,i);(function(n,r){var o=[],i={};for(var c in r.attributes){var u=r.attributes[c],l=n.attributes[c];u!==l&&void 0===l&&o.push(c)}for(var y in n.attributes){var m=r.attributes[y],b=n.attributes[y];m!==b&&void 0!==b&&(i[y]=b)}!function(n,r){t(r,(function(t){if(e(s,t)){var r=s[t];p(n.node,r.type,r.propName,null)}else t in n.node&&p(n.node,a,t,null),n.node.removeAttribute(t);delete n.attributes[t]}))}(r,o),function(t,n){for(var r in n){var o=n[r];if(t.attributes[r]=o,e(s,r)){var i=s[r];p(t.node,i.type,i.propName,o)}else r.startsWith(d)?t.node.setAttributeNS(f,r,o):r.startsWith(v)?t.node.setAttributeNS(h,r,o):(r in t.node&&p(t.node,a,r,o),t.node.setAttribute(r,o||""))}}(r,i)})(o,i),function(n,o,i){var a=n.children.length,c=o.children.length;if(a||c){var u=function(n){var r={};for(var o in t(n,(function(t){var n=t.attributes["data-key"];(function(t,n){return!(!n||e(t,n)&&(console.warn("[OmDomDom]: Children with duplicate keys detected. Children with duplicate keys will be skipped, resulting in dropped node references. Keys must be unique and non-indexed."),1))})(r,n)&&(r[n]=t)})),r)return r}(o.children),s=Array(a);t(n.children,void 0!==u?function(e,t){var n=o.node.childNodes,a=e.attributes["data-key"];if(Object.prototype.hasOwnProperty.call(u,a)){var c=u[a];Array.prototype.indexOf.call(n,c.node)!==t&&r(o,c,n[t]),s[t]=c,delete u[a],i(e,s[t])}else r(o,e,n[t]),s[t]=e}:function(e,t){var n=o.children[t];void 0!==n?(i(e,n),s[t]=n):(o.node.appendChild(e.node),s[t]=e)}),o.children=s;var l=o.node.childNodes.length,d=l-a;if(d>0)for(;d>0;)o.node.removeChild(o.node.childNodes[l-1]),l--,d--}}(o,i,n)}},m=function n(r){var o,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];"string"==typeof r&&(o=r.trim().replace(/\s+</g,"<").replace(/>\s+/g,">"),r=(new DOMParser).parseFromString(o,"text/html").body);var a="BODY"===r.tagName,c=r.childNodes,u=c?c.length:0;if(a){if(u>1)throw new Error("[OmDomDom]: Your element should not have more than one root node.");if(0===u)throw new Error("[OmDomDom]: Your element should have at least one root node.");return n(c[0])}var l=3===r.nodeType?"text":8===r.nodeType?"comment":r.tagName.toLowerCase(),d=i||"svg"===l,f=1===r.nodeType?function(t){var n=function(t){return Array.prototype.reduce.call(t.attributes,(function(t,n){return e(s,n.name)||(t[n.name]=n.value),t}),{})}(t);return function(e,t){for(var n in s){var r=s[n].propName,o=e.getAttribute(n);n===s.style.attrName?t[n]=e.style[r]:"string"==typeof o&&(t[n]=o)}}(t,n),n}(r):{},v=u>0?null:r.textContent,h=Array(u);return t(c,(function(e,t){h[t]=n(e,d)})),{type:l,attributes:f,children:h,content:v,node:r,isSVGContext:d}};function b(e){if(void 0===e&&(e=""),location.search!=e){""!=e&&(e="?"+e);var t=location.pathname+e;console.log("history.replaceState(",t,")"),window.history.replaceState({},"",t)}}var w=function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function c(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,c)}u((r=r.apply(e,t||[])).next())}))},g=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(c){return function(u){return function(c){if(n)throw new TypeError("Generator is already executing.");for(;i&&(i=0,c[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&c[0]?r.return:c[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,c[1])).done)return o;switch(r=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return a.label++,{value:c[1],done:!1};case 5:a.label++,r=c[1],c=[0];continue;case 7:c=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==c[0]&&2!==c[0])){a=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){a.label=c[1];break}if(6===c[0]&&a.label<o[1]){a.label=o[1],o=c;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(c);break}o[2]&&a.ops.pop(),a.trys.pop();continue}c=t.call(e,a)}catch(e){c=[6,e],r=0}finally{n=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}([c,u])}}},k="https:"===window.location.protocol?"wss:":"ws:",x="".concat(k,"//").concat(window.location.host).concat(window.location.pathname),E=function(){function e(){this.reconnectDelay=0}return e.prototype.connect=function(e){var t=this;void 0===e&&(e=x);var n=new WebSocket(e);function r(e){console.log("Connection Error",e)}this.socket=n,n.addEventListener("error",r),n.addEventListener("open",(function(e){console.log("Opened",e),t.isConnected=!0,t.hasEverConnected=!0,t.reconnectDelay=0,t.socket.removeEventListener("error",r)})),n.addEventListener("close",(function(n){t.isConnected=!1,console.log("Closed"),t.hasEverConnected&&(t.reconnectDelay+=1e3,console.log("Reconnecting in "+t.reconnectDelay/1e3+"s"),setTimeout((function(){return t.connect(e)}),t.reconnectDelay))}))},e.prototype.sendAction=function(e){return w(this,void 0,void 0,(function(){var t,n;return g(this,(function(r){switch(r.label){case 0:return t=[e.url.pathname+e.url.search,"Host: "+window.location.host,"Cookie: "+document.cookie,e.form].join("\n"),[4,this.fetch(e.id,t)];case 1:return(n=r.sent()).metadata,[2,n.rest]}}))}))},e.prototype.fetch=function(e,t){return w(this,void 0,void 0,(function(){return g(this,(function(n){switch(n.label){case 0:return this.sendMessage(t),[4,this.waitMessage(e)];case 1:return[2,n.sent()]}}))}))},e.prototype.sendMessage=function(e){this.socket.send(e)},e.prototype.waitMessage=function(e){return w(this,void 0,void 0,(function(){var t=this;return g(this,(function(n){return[2,new Promise((function(n,r){var o=function(r){var i,a,c=function(e){var t=e.split("\n"),n=function(e,t){for(var n=[],r=0,o=t;r<o.length;r++){var i=e(o[r]);if(!i)break;n.push(i)}return n}(o,t),r=function(e,t){for(var n=0;n<t.length&&e(t[n]);)n++;return t.slice(n)}(o,t).join("\n");return{metadata:C(n),rest:r};function o(e){var t=e.match(/^\|([A-Z\-]+)\|(.*)$/);if(t)return{key:t[1],value:t[2]}}}(r.data),u=c.metadata,s=c.rest;if(u.error)throw i=u.error,(a=new Error).name=i.substring(0,i.indexOf(" ")),a.message=i.substring(i.indexOf(" ")+1),a;u.cookies.forEach((function(e){document.cookie=e})),u.redirect?window.location.href=u.redirect:(b(u.query),u.viewId==e&&(n({metadata:u,rest:s}),t.socket.removeEventListener("message",o)))};t.socket.addEventListener("message",o),t.socket.addEventListener("error",r)}))]}))}))},e.prototype.disconnect=function(){this.socket.close()},e}();function C(e){var t,n,r,o;return{cookies:e.filter((function(e){return"COOKIE"==e.key})).map((function(e){return e.value})),redirect:null===(t=e.find((function(e){return"REDIRECT"==e.key})))||void 0===t?void 0:t.value,error:null===(n=e.find((function(e){return"ERROR"==e.key})))||void 0===n?void 0:n.value,viewId:null===(r=e.find((function(e){return"VIEW-ID"==e.key})))||void 0===r?void 0:r.value,query:null===(o=e.find((function(e){return"QUERY"==e.key})))||void 0===o?void 0:o.value}}var D=n(296);function O(e,t){document.addEventListener(e.toLowerCase(),(function(n){var r=n.target,o="on"+e+n.key,i=r.dataset[o];i&&(n.preventDefault(),t(L(r),i))}))}function S(e){e.querySelectorAll("[data-on-load]").forEach((function(e){var t=parseInt(e.dataset.delay)||0;setTimeout((function(){var t=new CustomEvent("hyp-load",{bubbles:!0,detail:{target:L(e)}});e.dispatchEvent(t)}),t)}))}function L(e){var t=function(e){var t,n=e.closest("[data-target]");return(null==n?void 0:n.dataset.target)||(null===(t=e.closest("[id]"))||void 0===t?void 0:t.id)}(e),n=document.getElementById(t);if(n)return n;console.error("Cannot find target: ",e)}function T(e){if(e){var t=new URLSearchParams;return e.forEach((function(e,n){t.append(n,e)})),t}}function A(e,t,n){var r=function(e,t){var n=new URL(window.location.href);return n.searchParams.append("hyp-id",e),n.searchParams.append("hyp-action",t),n}(e,t);return{id:e,url:r,form:T(n)}}var I,N=function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function c(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,c)}u((r=r.apply(e,t||[])).next())}))},P=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(c){return function(u){return function(c){if(n)throw new TypeError("Generator is already executing.");for(;i&&(i=0,c[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&c[0]?r.return:c[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,c[1])).done)return o;switch(r=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return a.label++,{value:c[1],done:!1};case 5:a.label++,r=c[1],c=[0];continue;case 7:c=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==c[0]&&2!==c[0])){a=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){a.label=c[1];break}if(6===c[0]&&a.label<o[1]){a.label=o[1],o=c;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(c);break}o[2]&&a.ops.pop(),a.trys.pop();continue}c=t.call(e,a)}catch(e){c=[6,e],r=0}finally{n=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}([c,u])}}};console.log("Hyperbole 0.4.2");var j=new Set;function R(e){return N(this,void 0,void 0,(function(){function t(e){return N(this,void 0,void 0,(function(){var t,n,r;return P(this,(function(o){switch(o.label){case 0:return[4,fetch(e.url,{method:"POST",headers:{Accept:"text/html","Content-Type":"application/x-www-form-urlencoded"},body:e.form,redirect:"manual"})];case 1:return(t=o.sent()).headers.get("location")?(console.log("Found Redirect",t.headers.get("location")),window.location.href=t.headers.get("location"),[2]):t.headers.get("location")?(window.location.href=t.headers.get("location"),[2]):(b(t.headers.get("set-query")),t.ok?[3,3]:((n=new Error).name="Fetch Error "+t.status,[4,t.text()]));case 2:throw r=o.sent(),n.message=r,n;case 3:return[2,t.text()]}}))}))}return P(this,(function(n){return B.isConnected?[2,B.sendAction(e)]:[2,t(e)]}))}))}function M(e){return N(this,void 0,void 0,(function(){var t;return P(this,(function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,R(e)];case 1:return[2,n.sent()];case 2:throw t=n.sent(),document.body.innerHTML=(o=[".hyp-error {background-color:#DB3524; color:white; padding: 10px}",".hyp-details {padding: 10px}"],i="<div class='hyp-error'>".concat((r=t).name,"</div>"),a="<div class='hyp-details'>".concat(r.message,"</div>"),["<style>"+o.join("\n")+"</style>",i,a].join("\n")),t;case 3:return[2]}var r,o,i,a}))}))}function q(e,t,n){return N(this,void 0,void 0,(function(){var r,o,i,a;return P(this,(function(c){switch(c.label){case 0:return r=setTimeout((function(){e.classList.add("hyp-loading")}),200),[4,M(A(e.id,t,n))];case 1:return u=c.sent(),l=(s=(new DOMParser).parseFromString(u,"text/html")).querySelector("style"),(o={content:s.querySelector("div"),css:l}).css&&o.content?(function(e){for(var t=0,n=e.sheet.cssRules;t<n.length;t++){var r=n[t];0==j.has(r.cssText)&&(I.sheet.insertRule(r.cssText),j.add(r.cssText))}}(o.css),i=m(o.content),a=m(e),y(i,a),S(document.getElementById(e.id)),clearTimeout(r),e.classList.remove("hyp-loading"),[2]):(console.error("Empty Response",o),[2])}var u,s,l}))}))}document.addEventListener("DOMContentLoaded",(function(){var e;I=document.querySelector("style"),e=function(e,t){return N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))},document.addEventListener("hyp-load",(function(t){var n=t.target.dataset.onLoad,r=t.detail.target;e(r,n)})),S(document.body),document.addEventListener("click",(function(e){var t=e.target.closest("[data-on-click]");t&&(e.preventDefault(),function(e,t){N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))}(L(t),t.dataset.onClick))})),document.addEventListener("dblclick",(function(e){var t=e.target.closest("[data-on-dblclick]");t&&(e.preventDefault(),function(e,t){N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))}(L(t),t.dataset.onDblclick))})),O("Keydown",(function(e,t){return N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))})),O("Keyup",(function(e,t){return N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))})),document.addEventListener("submit",(function(e){var t=e.target;if(null==t?void 0:t.dataset.onSubmit){e.preventDefault();var n=L(t),r=new FormData(t);!function(e,t,n){N(this,void 0,void 0,(function(){return P(this,(function(r){return q(e,t,n),[2]}))}))}(n,t.dataset.onSubmit,r)}else console.error("Missing onSubmit: ",t)})),document.addEventListener("change",(function(e){var t=e.target.closest("[data-on-change]");t&&(e.preventDefault(),t.value?function(e,t){N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))}(L(t),t.value):console.error("Missing input value:",t))})),document.addEventListener("input",(function(e){var t=e.target.closest("[data-on-input]");if(t){var n=parseInt(t.dataset.delay)||250;if(n<250&&console.warn("Input delay < 100 can result in poor performance."),null==t?void 0:t.dataset.onInput){e.preventDefault();var r=L(t);t.debouncedCallback||(t.debouncedCallback=D((function(){return function(e,t,n){return N(this,void 0,void 0,(function(){var r;return P(this,(function(o){return r="".concat(t,' "').concat(n.replace(/\\/g,"\\\\").replace(/"/g,'\\"'),'"'),q(e,r),[2]}))}))}(r,t.dataset.onInput,t.value)}),n)),t.debouncedCallback()}else console.error("Missing onInput: ",t)}}))}));var B=new E;B.connect()})()})();+(()=>{var e={296:e=>{function t(e,t=100,n={}){if("function"!=typeof e)throw new TypeError(`Expected the first parameter to be a function, got \`${typeof e}\`.`);if(t<0)throw new RangeError("`wait` must not be negative.");const{immediate:r}="boolean"==typeof n?{immediate:n}:n;let o,i,a,c,u;function s(){const t=o,n=i;return o=void 0,i=void 0,u=e.apply(t,n),u}function l(){const e=Date.now()-c;e<t&&e>=0?a=setTimeout(l,t-e):(a=void 0,r||(u=s()))}const d=function(...e){if(o&&this!==o&&Object.getPrototypeOf(this)===Object.getPrototypeOf(o))throw new Error("Debounced method called with different contexts of the same prototype.");o=this,i=e,c=Date.now();const n=r&&!a;return a||(a=setTimeout(l,t)),n&&(u=s()),u};return Object.defineProperty(d,"isPending",{get:()=>void 0!==a}),d.clear=()=>{a&&(clearTimeout(a),a=void 0)},d.flush=()=>{a&&d.trigger()},d.trigger=()=>{u=s(),d.clear()},d}e.exports.debounce=t,e.exports=t}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,n),i.exports}(()=>{"use strict";var e=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t=function(e,t){var n=e.length,r=-1;if(n)for(;++r<n&&!1!==t(e[r],r););},r=function(e,t,n){return e.node.insertBefore(t.node,n)};function o(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i,a,c=[],u=!0,s=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;u=!1}else for(;!(u=(r=i.call(n)).done)&&(c.push(r.value),c.length!==t);u=!0);}catch(e){s=!0,o=e}finally{try{if(!u&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(s)throw o}}return c}}(e,t)||function(e,t){if(e){if("string"==typeof e)return i(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?i(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}var a="string",c="number",u="boolean",s={},l=function(e,t,n){return{attrName:e,propName:t,type:n}};t([["style","cssText"],["class","className"]],(function(e){var t=o(e,2),n=t[0],r=t[1];s[n]=l(n,r||n,a)})),t(["autofocus","draggable","hidden","checked","multiple","muted","selected"],(function(e){s[e]=l(e,e,u)})),t([["tabindex","tabIndex"]],(function(e){var t=o(e,2),n=t[0],r=t[1];s[n]=l(n,r,c)}));var d="xlink:",f="http://www.w3.org/1999/xlink",v="xml:",h="http://www.w3.org/XML/1998/namespace",p=function(e,t,n,r){switch(t){case a:n===s.style.propName?e.style[n]=null===r?"":r:e[n]=null===r?"":r;break;case c:if(null===r){var o=n.toLowerCase();e.removeAttribute(o)}else if("0"===r)e[n]=0;else if("-1"===r)e[n]=-1;else{var i=parseInt(r,10);isNaN(i)||(e[n]=i)}break;case u:["","true"].indexOf(r)<0?e[n]=!1:e[n]=!0}},y=function n(o,i,c){if(o&&i){c=c||i.node.parentNode;var u=o.content&&o.content!==i.content;if(o.type!==i.type||u)return c.replaceChild(o.node,i.node),function(e,t){for(var n in e)t[n]=e[n]}(o,i);(function(n,r){var o=[],i={};for(var c in r.attributes){var u=r.attributes[c],l=n.attributes[c];u!==l&&void 0===l&&o.push(c)}for(var y in n.attributes){var m=r.attributes[y],w=n.attributes[y];m!==w&&void 0!==w&&(i[y]=w)}!function(n,r){t(r,(function(t){if(e(s,t)){var r=s[t];p(n.node,r.type,r.propName,null)}else t in n.node&&p(n.node,a,t,null),n.node.removeAttribute(t);delete n.attributes[t]}))}(r,o),function(t,n){for(var r in n){var o=n[r];if(t.attributes[r]=o,e(s,r)){var i=s[r];p(t.node,i.type,i.propName,o)}else r.startsWith(d)?t.node.setAttributeNS(f,r,o):r.startsWith(v)?t.node.setAttributeNS(h,r,o):(r in t.node&&p(t.node,a,r,o),t.node.setAttribute(r,o||""))}}(r,i)})(o,i),function(n,o,i){var a=n.children.length,c=o.children.length;if(a||c){var u=function(n){var r={};for(var o in t(n,(function(t){var n=t.attributes["data-key"];(function(t,n){return!(!n||e(t,n)&&(console.warn("[OmDomDom]: Children with duplicate keys detected. Children with duplicate keys will be skipped, resulting in dropped node references. Keys must be unique and non-indexed."),1))})(r,n)&&(r[n]=t)})),r)return r}(o.children),s=Array(a);t(n.children,void 0!==u?function(e,t){var n=o.node.childNodes,a=e.attributes["data-key"];if(Object.prototype.hasOwnProperty.call(u,a)){var c=u[a];Array.prototype.indexOf.call(n,c.node)!==t&&r(o,c,n[t]),s[t]=c,delete u[a],i(e,s[t])}else r(o,e,n[t]),s[t]=e}:function(e,t){var n=o.children[t];void 0!==n?(i(e,n),s[t]=n):(o.node.appendChild(e.node),s[t]=e)}),o.children=s;var l=o.node.childNodes.length,d=l-a;if(d>0)for(;d>0;)o.node.removeChild(o.node.childNodes[l-1]),l--,d--}}(o,i,n)}},m=function n(r){var o,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];"string"==typeof r&&(o=r.trim().replace(/\s+</g,"<").replace(/>\s+/g,">"),r=(new DOMParser).parseFromString(o,"text/html").body);var a="BODY"===r.tagName,c=r.childNodes,u=c?c.length:0;if(a){if(u>1)throw new Error("[OmDomDom]: Your element should not have more than one root node.");if(0===u)throw new Error("[OmDomDom]: Your element should have at least one root node.");return n(c[0])}var l=3===r.nodeType?"text":8===r.nodeType?"comment":r.tagName.toLowerCase(),d=i||"svg"===l,f=1===r.nodeType?function(t){var n=function(t){return Array.prototype.reduce.call(t.attributes,(function(t,n){return e(s,n.name)||(t[n.name]=n.value),t}),{})}(t);return function(e,t){for(var n in s){var r=s[n].propName,o=e.getAttribute(n);n===s.style.attrName?t[n]=e.style[r]:"string"==typeof o&&(t[n]=o)}}(t,n),n}(r):{},v=u>0?null:r.textContent,h=Array(u);return t(c,(function(e,t){h[t]=n(e,d)})),{type:l,attributes:f,children:h,content:v,node:r,isSVGContext:d}};function w(e){if(e!=function(){var e=window.location.search;return e.startsWith("?")?e.substring(1):e}()){""!=e&&(e="?"+e);var t=location.pathname+e;console.log("history.replaceState(",t,")"),window.history.replaceState({},"",t)}}var b=function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function c(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,c)}u((r=r.apply(e,t||[])).next())}))},g=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(c){return function(u){return function(c){if(n)throw new TypeError("Generator is already executing.");for(;i&&(i=0,c[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&c[0]?r.return:c[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,c[1])).done)return o;switch(r=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return a.label++,{value:c[1],done:!1};case 5:a.label++,r=c[1],c=[0];continue;case 7:c=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==c[0]&&2!==c[0])){a=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){a.label=c[1];break}if(6===c[0]&&a.label<o[1]){a.label=o[1],o=c;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(c);break}o[2]&&a.ops.pop(),a.trys.pop();continue}c=t.call(e,a)}catch(e){c=[6,e],r=0}finally{n=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}([c,u])}}},k="https:"===window.location.protocol?"wss:":"ws:",x="".concat(k,"//").concat(window.location.host).concat(window.location.pathname),E=function(){function e(){this.reconnectDelay=0}return e.prototype.connect=function(e){var t=this;void 0===e&&(e=x);var n=new WebSocket(e);function r(e){console.log("Connection Error",e)}this.socket=n,n.addEventListener("error",r),n.addEventListener("open",(function(e){console.log("Opened",e),t.isConnected=!0,t.hasEverConnected=!0,t.reconnectDelay=0,t.socket.removeEventListener("error",r)})),n.addEventListener("close",(function(n){t.isConnected=!1,console.log("Closed"),t.hasEverConnected&&(t.reconnectDelay+=1e3,console.log("Reconnecting in "+t.reconnectDelay/1e3+"s"),setTimeout((function(){return t.connect(e)}),t.reconnectDelay))}))},e.prototype.sendAction=function(e){return b(this,void 0,void 0,(function(){var t,n;return g(this,(function(r){switch(r.label){case 0:return t=[e.url.pathname+e.url.search,"Host: "+window.location.host,"Cookie: "+document.cookie,e.form].join("\n"),[4,this.fetch(e.id,t)];case 1:return(n=r.sent()).metadata,[2,n.rest]}}))}))},e.prototype.fetch=function(e,t){return b(this,void 0,void 0,(function(){return g(this,(function(n){switch(n.label){case 0:return this.sendMessage(t),[4,this.waitMessage(e)];case 1:return[2,n.sent()]}}))}))},e.prototype.sendMessage=function(e){this.socket.send(e)},e.prototype.waitMessage=function(e){return b(this,void 0,void 0,(function(){var t=this;return g(this,(function(n){return[2,new Promise((function(n,r){var o=function(r){var i,a,c=function(e){var t=e.split("\n"),n=function(e,t){for(var n=[],r=0,o=t;r<o.length;r++){var i=e(o[r]);if(!i)break;n.push(i)}return n}(o,t),r=function(e,t){for(var n=0;n<t.length&&e(t[n]);)n++;return t.slice(n)}(o,t).join("\n");return{metadata:C(n),rest:r};function o(e){var t=e.match(/^\|([A-Z\-]+)\|(.*)$/);if(t)return{key:t[1],value:t[2]}}}(r.data),u=c.metadata,s=c.rest;if(u.error)throw i=u.error,(a=new Error).name=i.substring(0,i.indexOf(" ")),a.message=i.substring(i.indexOf(" ")+1),a;u.cookies.forEach((function(e){document.cookie=e})),u.redirect?window.location.href=u.redirect:(void 0!==u.query&&w(u.query),u.viewId==e&&(n({metadata:u,rest:s}),t.socket.removeEventListener("message",o)))};t.socket.addEventListener("message",o),t.socket.addEventListener("error",r)}))]}))}))},e.prototype.disconnect=function(){this.socket.close()},e}();function C(e){var t,n,r,o;return{cookies:e.filter((function(e){return"COOKIE"==e.key})).map((function(e){return e.value})),redirect:null===(t=e.find((function(e){return"REDIRECT"==e.key})))||void 0===t?void 0:t.value,error:null===(n=e.find((function(e){return"ERROR"==e.key})))||void 0===n?void 0:n.value,viewId:null===(r=e.find((function(e){return"VIEW-ID"==e.key})))||void 0===r?void 0:r.value,query:null===(o=e.find((function(e){return"QUERY"==e.key})))||void 0===o?void 0:o.value}}var D=n(296);function O(e){if(e){var t=new URLSearchParams;return e.forEach((function(e,n){t.append(n,e)})),t}}function S(e,t,n){var r=function(e,t){var n=new URL(window.location.href);return n.searchParams.append("hyp-id",e),n.searchParams.append("hyp-action",t),n}(e,t);return{id:e,url:r,form:O(n)}}function L(e,t){document.addEventListener(e.toLowerCase(),(function(n){var r=n.target,o="on"+e+n.key,i=r.dataset[o];i&&(n.preventDefault(),t(A(r),i))}))}function T(e){e.querySelectorAll("[data-on-load]").forEach((function(e){var t=parseInt(e.dataset.delay)||0;setTimeout((function(){var t=new CustomEvent("hyp-load",{bubbles:!0,detail:{target:A(e)}});e.dispatchEvent(t)}),t)}))}function A(e){var t=function(e){var t,n=e.closest("[data-target]");return(null==n?void 0:n.dataset.target)||(null===(t=e.closest("[id]"))||void 0===t?void 0:t.id)}(e),n=document.getElementById(t);if(n)return n;console.error("Cannot find target: ",e)}var I,N=function(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function c(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,c)}u((r=r.apply(e,t||[])).next())}))},P=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(c){return function(u){return function(c){if(n)throw new TypeError("Generator is already executing.");for(;i&&(i=0,c[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&c[0]?r.return:c[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,c[1])).done)return o;switch(r=0,o&&(c=[2&c[0],o.value]),c[0]){case 0:case 1:o=c;break;case 4:return a.label++,{value:c[1],done:!1};case 5:a.label++,r=c[1],c=[0];continue;case 7:c=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==c[0]&&2!==c[0])){a=0;continue}if(3===c[0]&&(!o||c[1]>o[0]&&c[1]<o[3])){a.label=c[1];break}if(6===c[0]&&a.label<o[1]){a.label=o[1],o=c;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(c);break}o[2]&&a.ops.pop(),a.trys.pop();continue}c=t.call(e,a)}catch(e){c=[6,e],r=0}finally{n=o=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}([c,u])}}};console.log("Hyperbole 0.4.3c");var j=new Set;function M(e){return N(this,void 0,void 0,(function(){function t(e){return N(this,void 0,void 0,(function(){var t,n,r;return P(this,(function(o){switch(o.label){case 0:return[4,fetch(e.url,{method:"POST",headers:{Accept:"text/html","Content-Type":"application/x-www-form-urlencoded"},body:e.form,redirect:"manual"})];case 1:return(t=o.sent()).headers.get("location")?(console.log("Found Redirect",t.headers.get("location")),window.location.href=t.headers.get("location"),[2]):t.headers.get("location")?(window.location.href=t.headers.get("location"),[2]):(t.headers.has("set-query")&&w(t.headers.get("set-query")),t.ok?[3,3]:((n=new Error).name="Fetch Error "+t.status,[4,t.text()]));case 2:throw r=o.sent(),n.message=r,n;case 3:return[2,t.text()]}}))}))}return P(this,(function(n){return B.isConnected?[2,B.sendAction(e)]:[2,t(e)]}))}))}function R(e){return N(this,void 0,void 0,(function(){var t;return P(this,(function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,M(e)];case 1:return[2,n.sent()];case 2:throw t=n.sent(),document.body.innerHTML=(o=[".hyp-error {background-color:#DB3524; color:white; padding: 10px}",".hyp-details {padding: 10px}"],i="<div class='hyp-error'>".concat((r=t).name,"</div>"),a="<div class='hyp-details'>".concat(r.message,"</div>"),["<style>"+o.join("\n")+"</style>",i,a].join("\n")),t;case 3:return[2]}var r,o,i,a}))}))}function q(e,t,n){return N(this,void 0,void 0,(function(){var r,o,i,a,c;return P(this,(function(u){switch(u.label){case 0:return r=setTimeout((function(){e.classList.add("hyp-loading")}),100),[4,R(S(e.id,t,n))];case 1:return s=u.sent(),d=(l=(new DOMParser).parseFromString(s,"text/html")).querySelector("style"),(o={content:l.querySelector("div"),css:d}).css&&o.content?(function(e){for(var t=0,n=e.sheet.cssRules;t<n.length;t++){var r=n[t];0==j.has(r.cssText)&&(I.sheet.insertRule(r.cssText),j.add(r.cssText))}}(o.css),i=m(o.content),a=m(e),y(i,a),(c=document.getElementById(e.id))?T(c):console.warn("Target Missing: ",e.id),clearTimeout(r),e.classList.remove("hyp-loading"),[2]):(console.error("Empty Response",o),[2])}var s,l,d}))}))}document.addEventListener("DOMContentLoaded",(function(){var e;I=document.querySelector("style"),e=function(e,t){return N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))},document.addEventListener("hyp-load",(function(t){var n=t.target.dataset.onLoad,r=t.detail.target;e(r,n)})),T(document.body),document.addEventListener("click",(function(e){var t=e.target.closest("[data-on-click]");t&&(e.preventDefault(),function(e,t){N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))}(A(t),t.dataset.onClick))})),document.addEventListener("dblclick",(function(e){var t=e.target.closest("[data-on-dblclick]");t&&(e.preventDefault(),function(e,t){N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))}(A(t),t.dataset.onDblclick))})),L("Keydown",(function(e,t){return N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))})),L("Keyup",(function(e,t){return N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))})),document.addEventListener("submit",(function(e){var t=e.target;if(null==t?void 0:t.dataset.onSubmit){e.preventDefault();var n=A(t),r=new FormData(t);!function(e,t,n){N(this,void 0,void 0,(function(){return P(this,(function(r){return q(e,t,n),[2]}))}))}(n,t.dataset.onSubmit,r)}else console.error("Missing onSubmit: ",t)})),document.addEventListener("change",(function(e){var t=e.target.closest("[data-on-change]");t&&(e.preventDefault(),t.value?function(e,t){N(this,void 0,void 0,(function(){return P(this,(function(n){return q(e,t),[2]}))}))}(A(t),t.value):console.error("Missing input value:",t))})),document.addEventListener("input",(function(e){var t=e.target.closest("[data-on-input]");if(t){var n=parseInt(t.dataset.delay)||250;if(n<250&&console.warn("Input delay < 100 can result in poor performance."),null==t?void 0:t.dataset.onInput){e.preventDefault();var r=A(t);t.debouncedCallback||(t.debouncedCallback=D((function(){var e=function(e,t){return e.replace(/%HYP-INP%/,t.replace(/\\/g,"\\\\").replace(/"/g,'\\"'))}(t.dataset.onInput,t.value);!function(e,t){N(this,void 0,void 0,(function(){return P(this,(function(n){return console.log("INPUT",e.id,t),q(e,t),[2]}))}))}(r,e)}),n)),t.debouncedCallback()}else console.error("Missing onInput: ",t)}}))}));var B=new E;B.connect()})()})(); //# sourceMappingURL=hyperbole.js.map
hyperbole.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: hyperbole-version: 0.4.2+version: 0.4.3 synopsis: Interactive HTML apps using type-safe serverside Haskell description: Interactive serverside web framework Inspired by HTMX, Elm, and Phoenix LiveView category: Web, Network@@ -73,7 +73,7 @@ , bytestring >=0.11 && <0.13 , casing >0.1 && <0.2 , containers >=0.6 && <1- , cookie ==0.4.*+ , cookie >=0.4 && <0.6 , data-default >0.8 && <0.9 , effectful >=2.4 && <3 , file-embed >=0.0.10 && <0.1@@ -87,7 +87,7 @@ , wai >=3.2 && <4 , wai-websockets >=3.0 && <4 , warp >=3.3 && <4- , web-view >=0.6.2 && <=1.0+ , web-view >=0.7 && <=1.0 , websockets >=0.12 && <0.14 default-language: GHC2021 @@ -116,12 +116,11 @@ DeriveAnyClass ghc-options: -Wall -fdefer-typed-holes -threaded -rtsopts -with-rtsopts=-N -F -pgmF=skeletest-preprocessor build-depends:- Diff >=0.5 && <1.0- , base >=4.16 && <5+ base >=4.16 && <5 , bytestring >=0.11 && <0.13 , casing >0.1 && <0.2 , containers >=0.6 && <1- , cookie ==0.4.*+ , cookie >=0.4 && <0.6 , data-default >0.8 && <0.9 , effectful >=2.4 && <3 , file-embed >=0.0.10 && <0.1@@ -137,6 +136,6 @@ , wai >=3.2 && <4 , wai-websockets >=3.0 && <4 , warp >=3.3 && <4- , web-view >=0.6.2 && <=1.0+ , web-view >=0.7 && <=1.0 , websockets >=0.12 && <0.14 default-language: GHC2021
src/Web/Hyperbole.hs view
@@ -396,24 +396,24 @@ See [Example.Page.Simple](https://docs.hyperbole.live/simple) @-#EMBED Example/Page/Simple.hs data Message+#EMBED Example/Docs/MultiCopies.hs data Message @ Now we can embed multiple `Message` 'HyperView's into the same page. Each will update independently. @-#EMBED Example/Page/Simple.hs page'+#EMBED Example/Docs/MultiCopies.hs page @ -This is especially useful if we put identifying information in our 'ViewId', such as a database id. The [Contacts Example](https://docs.hyperbole.live/contacts) uses this to allow the user to edit multiple contacts on the same page. The 'viewId' function gives us access to that info+This is especially useful if we put identifying information in our 'ViewId', such as a database id. The 'viewId' function gives us access to that info. See the [Contacts Example](https://docs.hyperbole.live/contacts) and the [Lazy Loading Example](https://docs.hyperbole.live/lazyloading) -From [Example.Contacts](https://docs.hyperbole.live/contacts)+From [Example.Page.LazyLoading](https://docs.hyperbole.live/lazyloading) @-#EMBED Example/Page/Contact.hs data Contact+#EMBED Example/Page/LazyLoading.hs data LazyData -#EMBED Example/Page/Contact.hs instance (Users :> es,+#EMBED Example/Page/LazyLoading.hs instance (Debug :> es, GenRandom :> es) => HyperView @ -}
src/Web/Hyperbole/Effect/Hyperbole.hs view
@@ -3,12 +3,10 @@ module Web.Hyperbole.Effect.Hyperbole where -import Data.ByteString qualified as BS import Effectful import Effectful.Dispatch.Dynamic import Effectful.Error.Static import Effectful.State.Static.Local-import Web.Hyperbole.Data.QueryData (queryData) import Web.Hyperbole.Effect.Server @@ -44,15 +42,9 @@ runLocal eff = do -- Load the request ONCE right when we start r <- send LoadRequest- let client = Client mempty (queryData $ queryParams r)+ let client = Client mempty mempty let st = HyperState r client runErrorNoCallStack @Response . runState st $ eff-- queryParams request =- filter (not . isSystemParam) request.query-- isSystemParam (key, _) =- "hyp-" `BS.isPrefixOf` key combine :: (Server :> es) => Eff es (Either Response (Response, HyperState)) -> Eff es Response combine eff = do
src/Web/Hyperbole/Effect/Query.hs view
@@ -1,12 +1,15 @@ module Web.Hyperbole.Effect.Query where +import Data.ByteString qualified as BS+import Data.Maybe (fromMaybe) import Data.String.Conversions (cs) import Effectful import Effectful.Dispatch.Dynamic (send)-import Web.Hyperbole.Data.QueryData (FromParam (..), FromQuery (..), Param, QueryData (..), ToParam (..), ToQuery (..))+import Web.Hyperbole.Data.QueryData (FromParam (..), FromQuery (..), Param, QueryData (..), ToParam (..), ToQuery (..), queryData) import Web.Hyperbole.Data.QueryData qualified as QueryData import Web.Hyperbole.Effect.Hyperbole (Hyperbole (..))-import Web.Hyperbole.Effect.Server (Client (..), Response (..), ResponseError (..))+import Web.Hyperbole.Effect.Request (request)+import Web.Hyperbole.Effect.Server (Client (..), Request (..), Response (..), ResponseError (..)) import Prelude @@ -77,10 +80,23 @@ -- | Return the query from 'Request' as a 'QueryData' queryParams :: (Hyperbole :> es) => Eff es QueryData queryParams = do- (.query) <$> send GetClient+ cq <- clientQuery+ rq <- requestQuery+ pure $ fromMaybe rq cq+ where+ clientQuery = (.query) <$> send GetClient + requestQuery :: (Hyperbole :> es) => Eff es QueryData+ requestQuery = do+ r <- request+ pure $ queryData $ filter (not . isSystemParam) r.query + isSystemParam (key, _) =+ "hyp-" `BS.isPrefixOf` key++ modifyQuery :: (Hyperbole :> es) => (QueryData -> QueryData) -> Eff es ()-modifyQuery f =+modifyQuery f = do+ q <- queryParams send $ ModClient $ \client ->- Client{query = f client.query, session = client.session}+ Client{query = Just $ f q, session = client.session}
src/Web/Hyperbole/Effect/Server.hs view
@@ -89,7 +89,8 @@ setCookie cookie = ("Set-Cookie", renderCookie (Wai.pathInfo req) cookie) - setQuery qd =+ setQuery Nothing = []+ setQuery (Just qd) = [("Set-Query", QueryData.render qd)] -- convert to document if full page request. Subsequent POST requests will only include fragments@@ -186,8 +187,9 @@ cookieMeta cookie = Metadata [("COOKIE", cs (renderCookie req.path cookie))] - queryMeta :: QueryData -> Metadata- queryMeta q =+ queryMeta :: Maybe QueryData -> Metadata+ queryMeta Nothing = mempty+ queryMeta (Just q) = Metadata [("QUERY", cs $ QueryData.render q)] viewIdMeta :: TargetViewId -> Metadata@@ -218,7 +220,7 @@ data Client = Client { session :: Cookies- , query :: QueryData+ , query :: Maybe QueryData }
src/Web/Hyperbole/HyperView.hs view
@@ -202,9 +202,9 @@ {- | Access the 'viewId' in a 'View' or 'update' @-#EMBED Example/Page/Contact.hs data Contact+#EMBED Example/Page/LazyLoading.hs data LazyData -#EMBED Example/Page/Contact.hs instance (Users :> es+#EMBED Example/Page/LazyLoading.hs instance (Debug :> es, GenRandom :> es) => HyperView LazyData es where @ -} class HasViewId m view where
src/Web/Hyperbole/View/Event.hs view
@@ -4,7 +4,6 @@ import Data.String.Conversions (cs) import Data.Text (Text)-import Data.Text qualified as T import Text.Casing (kebab) import Web.Hyperbole.HyperView import Web.View (Mod, View, addContext, att, parent)@@ -18,7 +17,7 @@ {- | Send the action after N milliseconds. Can be used to implement lazy loading or polling. See [Example.Page.Concurrent](https://docs.hyperbole.live/concurrent) @-#EMBED Example/Page/Concurrent.hs viewUpdating+#EMBED Example/Page/LazyLoading.hs viewTaskLoad @ -} onLoad :: (ViewAction (Action id)) => Action id -> DelayMs -> Mod id@@ -91,8 +90,8 @@ -- | Serialize a constructor that expects a single 'Text', like `data MyAction = GoSearch Text` toActionInput :: (ViewAction a) => (Text -> a) -> Text toActionInput con =- -- remove the ' ""' at the end of the constructor- T.dropEnd 3 $ toAction $ con ""+ let marker = "%HYP-INP%"+ in toAction $ con marker {- | Apply a Mod only when a request is in flight. See [Example.Page.Contact](https://docs.hyperbole.live/contacts/1)
test/Test/ViewActionSpec.hs view
@@ -4,6 +4,7 @@ import GHC.Generics import Skeletest import Web.Hyperbole.HyperView+import Web.Hyperbole.View.Event (toActionInput) data Simple = Simple@@ -21,6 +22,8 @@ data Sum = SumA | SumB Int+ | SubC Text+ | SubD (Maybe Text) deriving (Generic, Show, Eq, Read, ViewAction) @@ -58,6 +61,13 @@ it "product" $ toAction (Product "hello world" 123) `shouldBe` "Product \"hello world\" 123" it "sum" $ toAction (SumB 123) `shouldBe` "SumB 123" it "compound" $ toAction (Compound (Product "hello world" 123)) `shouldBe` "Compound (Product \"hello world\" 123)"++ describe "toActionInput" $ withMarkers ["focus"] $ do+ it "Constructor Text" $ do+ toActionInput SubC `shouldBe` "SubC \"%HYP-INP%\""++ it "Constructor (Maybe Text)" $ do+ toActionInput (SubD . Just) `shouldBe` "SubD (Just \"%HYP-INP%\")" describe "parseAction" $ do it "simple" $ parseAction "Simple" `shouldBe` Just Simple