@statewalker/webrun-http-browser 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -1
- package/dist/index-sw-umd.js +8 -4
- package/dist/index-sw-umd.min.js +2 -2
- package/dist/index-sw.js +8 -4
- package/dist/index-sw.min.js +2 -2
- package/dist/index-umd.js +16 -6
- package/dist/index-umd.min.js +2 -2
- package/dist/index.js +16 -6
- package/dist/index.min.js +2 -2
- package/package.json +1 -1
- package/src/http/http-stubs.js +13 -4
- package/src/relay/index.js +2 -1
package/README.md
CHANGED
|
@@ -2,4 +2,71 @@
|
|
|
2
2
|
|
|
3
3
|
This module simulates HTTP server using Service Workers.
|
|
4
4
|
It allows to develop, test, run and debug server-side code directly in the browser.
|
|
5
|
-
After that the same code can be deployed in Deno / Deno Deploy / Cloudflare / Node JS environments (with adapters).
|
|
5
|
+
After that the same code can be deployed in Deno / Deno Deploy / Cloudflare / Node JS environments (with adapters).
|
|
6
|
+
|
|
7
|
+
## Demo
|
|
8
|
+
|
|
9
|
+
* [Demo 1](./demo/demo-1.html) - a dynamic web site with a server-side API, a HTML page and a CSS file
|
|
10
|
+
* [https://observablehq.com/@kotelnikov/webrun-http-service](https://observablehq.com/@kotelnikov/webrun-http-service) - an Observable page demonstrating how it works. You can play with the code here.
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
This module provides a lightweight full-stack development environment in the browser:
|
|
15
|
+
* Code, execute and debug the whole stack in the browser. Even without internet connection.
|
|
16
|
+
* Your data and code don’t leave your browser
|
|
17
|
+
* Instant reproducable environment without installation
|
|
18
|
+
* Easily embeddable in your code
|
|
19
|
+
* Client and server-side code in the browser based on standards:
|
|
20
|
+
- Use module imports for scripts
|
|
21
|
+
- Send requests with fetch
|
|
22
|
+
- Handle HTTP queries with the Request/Response API
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## UseCases
|
|
26
|
+
|
|
27
|
+
* Create rich documentations, tutorials, demos
|
|
28
|
+
* Embed in your rich application - in the new generation Notion, Airtable or Figma
|
|
29
|
+
* Deliver self-contained prototype environments to your clients
|
|
30
|
+
|
|
31
|
+
## How It Works
|
|
32
|
+
|
|
33
|
+
The core of this module is based on the following native browser technologies: ServiceWorker and MessageChannels.
|
|
34
|
+
|
|
35
|
+
A ServiceWorker is used as the "server", intercepting HTTP calls and delegating their handling to registered modules via MessageChannels.
|
|
36
|
+
So in the same browser-based application you can register a standard HTTP endpoint and call it.
|
|
37
|
+
|
|
38
|
+
Example:
|
|
39
|
+
```js
|
|
40
|
+
import { httpService, endpointUrl } from "...";
|
|
41
|
+
|
|
42
|
+
// Server-side code:
|
|
43
|
+
httpService.register(async (request) => { // request: Request
|
|
44
|
+
return new Response("Hello, world!", {
|
|
45
|
+
headers: {
|
|
46
|
+
"Content-Type": "text/plain"
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// Client-side code:
|
|
52
|
+
|
|
53
|
+
const res = await fetch(endpointUrl);
|
|
54
|
+
const text = await res.text();
|
|
55
|
+
console.log(text);
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## They Play Well Together...
|
|
60
|
+
|
|
61
|
+
This in-browser HTTP Server allows to implement the following functionalities:
|
|
62
|
+
- Serve your content from your Local Disk:
|
|
63
|
+
- using [File System Access API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API)
|
|
64
|
+
- using [Origin Private File System API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API)
|
|
65
|
+
- Add version control with Git - using [IsomorphicGit](https://isomorphic-git.org/)
|
|
66
|
+
- Provide direct P2P sharing with others – via [WebRTC](https://webrtc.org/)
|
|
67
|
+
- Implement client/server applications using persistent SQLite on Origin Private File System - using [SQLite Wasm](https://developer.chrome.com/blog/sqlite-wasm-in-the-browser-backed-by-the-origin-private-file-system/)
|
|
68
|
+
- Deploy your local site on Edge - via [Deno Deploy](https://deno.com/deploy)
|
|
69
|
+
- Distribute your work in any browser via IPFS / [LibP2P](https://github.com/libp2p/js-libp2p)
|
|
70
|
+
- Integration with existing powerful APIs like https://trpc.io/
|
|
71
|
+
|
|
72
|
+
...and everything in the browser!
|
package/dist/index-sw-umd.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @statewalker/webrun-http-browser v0.
|
|
1
|
+
// @statewalker/webrun-http-browser v0.3.1 https://github.com/statewalker/statewalker-webrun-http-browser Copyright 2023 Mikhail Kotelnikov
|
|
2
2
|
(function (factory) {
|
|
3
3
|
typeof define === 'function' && define.amd ? define(factory) :
|
|
4
4
|
factory();
|
|
@@ -424,14 +424,18 @@ function newHttpClientStub(send) {
|
|
|
424
424
|
"referrer",
|
|
425
425
|
"referrerPolicy",
|
|
426
426
|
"integrity",
|
|
427
|
-
"keepalive"
|
|
427
|
+
"keepalive"
|
|
428
428
|
];
|
|
429
|
-
|
|
429
|
+
const headers = [...request.headers].map(([key, value]) => {
|
|
430
|
+
return [key, value]
|
|
431
|
+
});
|
|
430
432
|
const requestOptions = fields.reduce((options, key) => {
|
|
431
433
|
const val = request[key];
|
|
432
434
|
if (val !== undefined) options[key] = val;
|
|
433
435
|
return options;
|
|
434
|
-
}, {
|
|
436
|
+
}, {
|
|
437
|
+
headers
|
|
438
|
+
});
|
|
435
439
|
const requestContent = (request.body)
|
|
436
440
|
? fromReadableStream(request.body)
|
|
437
441
|
: [];
|
package/dist/index-sw-umd.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// @statewalker/webrun-http-browser v0.
|
|
2
|
-
!function(t){"function"==typeof define&&define.amd?define(t):t()}((function(){"use strict";function t(t){return new Promise(((e,n)=>{t.oncomplete=t.onsuccess=()=>e(t.result),t.onabort=t.onerror=()=>n(t.error)}))}let e;function n(){return e||(e=function(e,n){const r=indexedDB.open(e);r.onupgradeneeded=()=>r.result.createObjectStore(n);const s=t(r);return(t,e)=>s.then((r=>e(r.transaction(n,t).objectStore(n))))}("keyval-store","keyval")),e}function r(e,r=n()){return r("readonly",(n=>t(n.get(e))))}function s(e,r,s=n()){return s("readwrite",(n=>(n.put(r,e),t(n.transaction))))}function a(t){return Object.assign({message:t,stack:t.stack},t)}function o(t){return"string"==typeof t&&(t={message:t}),Object.assign(new Error(t.message),t)}async function i(t,e,n,...r){return new Promise(((s,a)=>{const i=new MessageChannel;i.port1.onmessage=t=>{const{result:e,error:n}=t.data;n?a(o(n)):s(e)},t.postMessage({type:e,params:n},[i.port2,...r])}))}function c(t,e,n){const r=async t=>{if(!t.data||t.data.type!==e)return;const[r,...s]=t.ports;let o={};try{const e=t.data.params;o.result=await n(t,e,...s)}catch(t){o.error=a(t)}r.postMessage(o)};t.addEventListener("message",r);try{t.start&&t.start()}catch(t){}return()=>t.removeEventListener("message",r)}async function*l(t){yield*async function*(t,e=[]){let n,r,s=async(t,n,s)=>{const a={error:t,value:n,done:s};return a.promise=new Promise((t=>a.notify=t)),await e.push(a),r&&r(),r=null,a.promise};const a=t=>s(void 0,t,!1),o=()=>s(void 0,void 0,!0),i=t=>s(t,void 0,!0),c=t(Object.assign([a,o,i],{next:a,complete:o,error:i}));let l;try{for(;;)if(l=await e.shift(),l)try{if(l.error)throw l.error;if(l.done)break;yield l.value}finally{l.notify(!0)}else await(n=r?n:new Promise((t=>r=t)))}finally{for(r&&r(),s=()=>!1,"function"==typeof c&&await c();l=await e.shift();)l.notify(!1)}}((e=>t((async({done:t=!0,value:n,error:r}={})=>{r?await e.error(r):t?await e.complete():await e.next(n)}))))}async function*u(t,e,n={}){const r=new MessageChannel;t.postMessage({type:"START_CALL",params:n},[r.port2]);const s=function(t){let e=[],n=[];const r=async t=>{for(let n of e)await n(t)},s=d({port:t,handler:r});async function*a(){yield*l((t=>(e.push(t),()=>e=e.filter((e=>e!==t)))))}async function o(t){await async function(t,e){let n;try{for await(let n of e)await t({done:!1,value:n})}catch(t){n=t}finally{await t({done:!0,error:n})}}(s.invoke,async function*(){try{n.push(t),yield*t}finally{n=n.filter((e=>e!==t))}}())}return{start:()=>s.start(),close:async()=>{await r({done:!0}),[...n].forEach((t=>t.return&&t.return())),await s.close()},recieveAll:a,sendAll:o}}(r.port1);try{await s.start(),s.sendAll(e),yield*s.recieveAll()}finally{await s.close()}}function d({port:t,handler:e=(()=>{throw new Error("Handler not implemented")}),onError:n=console.error,newCallId:r=(()=>d.__counter=(d.__counter||0)+1)}){const s="REQUEST",i="RESPONSE",c="message",l={},u=async n=>{const r=n.data||{},{type:c,callId:u}=r;if(c===s)try{const{request:s}=r;let a=await e(s,...n.ports||[]);const[o,...c]=Array.isArray(a)?a:void 0!==a?[a]:[];t.postMessage({type:i,callId:u,response:o},c)}catch(e){t.postMessage({type:i,callId:u,error:a(e)})}else if(c===i){const{callId:t,response:e,error:n}=r,s=l[t];delete l[t],s&&(n?s.reject(o(n)):s.resolve(e))}};return{start:async()=>{try{t.addEventListener(c,u),t.start&&await t.start()}catch(t){n(t)}},close:async()=>{try{t.removeEventListener(c,u),t.close&&await t.close()}catch(t){n(t)}},invoke:async function(e={},...n){const a=r();return new Promise(((r,o)=>{try{l[a]={resolve:r,reject:o},t.postMessage({type:s,callId:a,request:e},n)}catch(t){o(t),delete e[a]}}))}}}function f(t){return async e=>{e=await e
|
|
1
|
+
// @statewalker/webrun-http-browser v0.3.1 https://github.com/statewalker/statewalker-webrun-http-browser Copyright 2023 Mikhail Kotelnikov
|
|
2
|
+
!function(t){"function"==typeof define&&define.amd?define(t):t()}((function(){"use strict";function t(t){return new Promise(((e,n)=>{t.oncomplete=t.onsuccess=()=>e(t.result),t.onabort=t.onerror=()=>n(t.error)}))}let e;function n(){return e||(e=function(e,n){const r=indexedDB.open(e);r.onupgradeneeded=()=>r.result.createObjectStore(n);const s=t(r);return(t,e)=>s.then((r=>e(r.transaction(n,t).objectStore(n))))}("keyval-store","keyval")),e}function r(e,r=n()){return r("readonly",(n=>t(n.get(e))))}function s(e,r,s=n()){return s("readwrite",(n=>(n.put(r,e),t(n.transaction))))}function a(t){return Object.assign({message:t,stack:t.stack},t)}function o(t){return"string"==typeof t&&(t={message:t}),Object.assign(new Error(t.message),t)}async function i(t,e,n,...r){return new Promise(((s,a)=>{const i=new MessageChannel;i.port1.onmessage=t=>{const{result:e,error:n}=t.data;n?a(o(n)):s(e)},t.postMessage({type:e,params:n},[i.port2,...r])}))}function c(t,e,n){const r=async t=>{if(!t.data||t.data.type!==e)return;const[r,...s]=t.ports;let o={};try{const e=t.data.params;o.result=await n(t,e,...s)}catch(t){o.error=a(t)}r.postMessage(o)};t.addEventListener("message",r);try{t.start&&t.start()}catch(t){}return()=>t.removeEventListener("message",r)}async function*l(t){yield*async function*(t,e=[]){let n,r,s=async(t,n,s)=>{const a={error:t,value:n,done:s};return a.promise=new Promise((t=>a.notify=t)),await e.push(a),r&&r(),r=null,a.promise};const a=t=>s(void 0,t,!1),o=()=>s(void 0,void 0,!0),i=t=>s(t,void 0,!0),c=t(Object.assign([a,o,i],{next:a,complete:o,error:i}));let l;try{for(;;)if(l=await e.shift(),l)try{if(l.error)throw l.error;if(l.done)break;yield l.value}finally{l.notify(!0)}else await(n=r?n:new Promise((t=>r=t)))}finally{for(r&&r(),s=()=>!1,"function"==typeof c&&await c();l=await e.shift();)l.notify(!1)}}((e=>t((async({done:t=!0,value:n,error:r}={})=>{r?await e.error(r):t?await e.complete():await e.next(n)}))))}async function*u(t,e,n={}){const r=new MessageChannel;t.postMessage({type:"START_CALL",params:n},[r.port2]);const s=function(t){let e=[],n=[];const r=async t=>{for(let n of e)await n(t)},s=d({port:t,handler:r});async function*a(){yield*l((t=>(e.push(t),()=>e=e.filter((e=>e!==t)))))}async function o(t){await async function(t,e){let n;try{for await(let n of e)await t({done:!1,value:n})}catch(t){n=t}finally{await t({done:!0,error:n})}}(s.invoke,async function*(){try{n.push(t),yield*t}finally{n=n.filter((e=>e!==t))}}())}return{start:()=>s.start(),close:async()=>{await r({done:!0}),[...n].forEach((t=>t.return&&t.return())),await s.close()},recieveAll:a,sendAll:o}}(r.port1);try{await s.start(),s.sendAll(e),yield*s.recieveAll()}finally{await s.close()}}function d({port:t,handler:e=(()=>{throw new Error("Handler not implemented")}),onError:n=console.error,newCallId:r=(()=>d.__counter=(d.__counter||0)+1)}){const s="REQUEST",i="RESPONSE",c="message",l={},u=async n=>{const r=n.data||{},{type:c,callId:u}=r;if(c===s)try{const{request:s}=r;let a=await e(s,...n.ports||[]);const[o,...c]=Array.isArray(a)?a:void 0!==a?[a]:[];t.postMessage({type:i,callId:u,response:o},c)}catch(e){t.postMessage({type:i,callId:u,error:a(e)})}else if(c===i){const{callId:t,response:e,error:n}=r,s=l[t];delete l[t],s&&(n?s.reject(o(n)):s.resolve(e))}};return{start:async()=>{try{t.addEventListener(c,u),t.start&&await t.start()}catch(t){n(t)}},close:async()=>{try{t.removeEventListener(c,u),t.close&&await t.close()}catch(t){n(t)}},invoke:async function(e={},...n){const a=r();return new Promise(((r,o)=>{try{l[a]={resolve:r,reject:o},t.postMessage({type:s,callId:a,request:e},n)}catch(t){o(t),delete e[a]}}))}}}function f(t){return async e=>{const n=[...(e=await e).headers].map((([t,e])=>[t,e])),r=["url","method","mode","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive"].reduce(((t,n)=>{const r=e[n];return void 0!==r&&(t[n]=r),t}),{headers:n}),s=e.body?async function*(t){const e=await t.getReader();let n,r;for(;({done:n,value:r}=await e.read())&&!n;)yield await r}(e.body):[],a=await t({options:r,content:s});let o=null,i={};if(a){i=a.options;const t=a.content;"HEAD"!==r.method&&"OPTIONS"!==r.method?(c=t,o=new ReadableStream({type:"bytes",async pull(t){let e=!1;try{for(;;){const e=await c.next();if(!e||e.done)break;t.enqueue(await e.value)}}catch(n){e=!0,t.error(n)}finally{!e&&t.close()}}})):t&&t.return&&t.return()}else i={status:404,statusText:"Error 404: Not Found"};var c;return new Response(o,i)}}async function y(t,e){const n=f((async e=>await async function(t){t=await t;const{done:e,value:n}=await t.next();let r={};if(!e&&n){const t=(new TextDecoder).decode(n);r=JSON.parse(t)}return{options:r,content:t}}(u(t,async function*(t){const{options:e,content:n}=await t,r=new TextEncoder;yield r.encode(JSON.stringify(e)),yield*n}(e)))));return await n(e)}class w extends Error{constructor(t){super(t.message),this.status=t.status,this.statusText=t.statusText}getResponseOptions(t={}){return Object.assign(this.toJson(),t)}toJson(){return{status:this.status,statusText:this.statusText,message:this.message}}static fromError(t){return t instanceof w||(t=new w(Object.assign({status:500,statusText:"Bad Request",reason:t.message}))),t}static errorResourceNotFound(t={}){return new w({status:404,statusText:"Error 404: Resource not found",...t})}static errorForbidden(t={}){return new w({status:403,statusText:"Error 403: Forbidden",...t})}static errorResourceGone(t={}){return new w({status:410,statusText:"Error 410: Resource Gone",...t})}static errorInternalError(t){return new w({...t,status:500,statusText:"Error 500: Internal error"})}}!function(t){const[e,n]=function(t=console.error){let e=0;const n={},r=r=>{const s=e++;return n[s]=Object.assign((function(e){try{return delete n[s],!e&&r&&r()}catch(e){t(e)}}),{action:r})},s=t=>Object.values(n).forEach((e=>e.action===t&&e(!0))),a=()=>Object.values(n).forEach((t=>t()));return Object.assign([r,a,s],{register:r,clear:a,unregister:s})}();"function"==typeof t.skipWaiting?(console.log("self.skipWaiting() is supported."),t.addEventListener("install",(e=>{e.waitUntil(t.skipWaiting())}))):console.log("self.skipWaiting() is not supported."),t.clients&&"function"==typeof t.clients.claim?(console.log("self.clients.claim() is supported."),t.addEventListener("activate",(e=>{e.waitUntil(t.clients.claim())}))):console.log("self.clients.claim() is not supported.");const a=function({self:t,key:e="clientsIds",get:n,set:r}){let s;async function a(){if(!s){const t=await n(e)||[];s=Object.fromEntries(t)}return s}async function o(){const t=await a(),n=Object.entries(t);return await r(e,n),t}async function i(t,e){const n=await a(),r=e.id;let s=!1;return r in n||(n[t]=r,await o(),s=!0),s}async function c(t){const e=await a();let n=!1;return t in e&&(delete e[t],await o(),n=!0),n}async function l(e){const n=await a(),r=n[e],s=await t.clients.get(r);return s||(delete n[e],await o()),s}return{getClient:l,addClient:i,removeClient:c}}({self:t,get:r,set:s});e(c(t,"REGISTER",(async(t,e)=>await a.addClient(e.key,t.source)))),e(c(t,"UNREGISTER",(async(t,e)=>await a.removeClient(e.key)))),e(c(t,"CONNECT",(async(t,e,n)=>{const{key:r}=e,s=await a.getClient(r);if(!s)throw new Error(`Target client was not found. Target key: "${r}".`);return await i(s,"CONNECT",e,n)})));const o=t=>{const e=t.request,n=function(t,e="~"){let n="",r="",s=t+"";const a=s.indexOf(e);let o="";return a>=0&&(o=s.substring(0,a+e.length),s.substring(a+e.length).replace(/^([^\/]+)/,((t,e)=>(o+=t,o.length<s.length&&(o+="/"),n=e,r=s.substring(o.length),"")))),{url:t,key:n,baseUrl:o,path:r}}(e.url),{key:r}=n;if(r){const s=async()=>{try{const t=new MessageChannel,s=await a.getClient(r);if(!s)throw w.errorResourceGone(n);const o={type:"http",key:r};if(!await i(s,"CONNECT",o,t.port2))throw w.errorForbidden(n);return await y(t.port1,e)}catch(t){const e=(t=w.fromError(t)).getResponseOptions(n);return new Response(JSON.stringify(e),{...e,headers:{"Content-Type":"text/javascript"}})}};t.respondWith(s())}};t.addEventListener("fetch",o),e((()=>t.removeEventListener("fetch",o)))}(self)}));
|
package/dist/index-sw.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @statewalker/webrun-http-browser v0.
|
|
1
|
+
// @statewalker/webrun-http-browser v0.3.1 https://github.com/statewalker/statewalker-webrun-http-browser Copyright 2023 Mikhail Kotelnikov
|
|
2
2
|
// See https://github.com/agenjs/agen-utils/blob/main/src/iterator.js
|
|
3
3
|
async function* iterate(init, queue = []) {
|
|
4
4
|
let promise, notify, push = async (error, value, done) => {
|
|
@@ -419,14 +419,18 @@ function newHttpClientStub(send) {
|
|
|
419
419
|
"referrer",
|
|
420
420
|
"referrerPolicy",
|
|
421
421
|
"integrity",
|
|
422
|
-
"keepalive"
|
|
422
|
+
"keepalive"
|
|
423
423
|
];
|
|
424
|
-
|
|
424
|
+
const headers = [...request.headers].map(([key, value]) => {
|
|
425
|
+
return [key, value]
|
|
426
|
+
});
|
|
425
427
|
const requestOptions = fields.reduce((options, key) => {
|
|
426
428
|
const val = request[key];
|
|
427
429
|
if (val !== undefined) options[key] = val;
|
|
428
430
|
return options;
|
|
429
|
-
}, {
|
|
431
|
+
}, {
|
|
432
|
+
headers
|
|
433
|
+
});
|
|
430
434
|
const requestContent = (request.body)
|
|
431
435
|
? fromReadableStream(request.body)
|
|
432
436
|
: [];
|
package/dist/index-sw.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// @statewalker/webrun-http-browser v0.
|
|
2
|
-
function t(t){return new Promise(((e,n)=>{t.oncomplete=t.onsuccess=()=>e(t.result),t.onabort=t.onerror=()=>n(t.error)}))}let e;function n(){return e||(e=function(e,n){const r=indexedDB.open(e);r.onupgradeneeded=()=>r.result.createObjectStore(n);const s=t(r);return(t,e)=>s.then((r=>e(r.transaction(n,t).objectStore(n))))}("keyval-store","keyval")),e}function r(e,r=n()){return r("readonly",(n=>t(n.get(e))))}function s(e,r,s=n()){return s("readwrite",(n=>(n.put(r,e),t(n.transaction))))}function a(t){return Object.assign({message:t,stack:t.stack},t)}function o(t){return"string"==typeof t&&(t={message:t}),Object.assign(new Error(t.message),t)}async function i(t,e,n,...r){return new Promise(((s,a)=>{const i=new MessageChannel;i.port1.onmessage=t=>{const{result:e,error:n}=t.data;n?a(o(n)):s(e)},t.postMessage({type:e,params:n},[i.port2,...r])}))}function c(t,e,n){const r=async t=>{if(!t.data||t.data.type!==e)return;const[r,...s]=t.ports;let o={};try{const e=t.data.params;o.result=await n(t,e,...s)}catch(t){o.error=a(t)}r.postMessage(o)};t.addEventListener("message",r);try{t.start&&t.start()}catch(t){}return()=>t.removeEventListener("message",r)}async function*l(t){yield*async function*(t,e=[]){let n,r,s=async(t,n,s)=>{const a={error:t,value:n,done:s};return a.promise=new Promise((t=>a.notify=t)),await e.push(a),r&&r(),r=null,a.promise};const a=t=>s(void 0,t,!1),o=()=>s(void 0,void 0,!0),i=t=>s(t,void 0,!0),c=t(Object.assign([a,o,i],{next:a,complete:o,error:i}));let l;try{for(;;)if(l=await e.shift(),l)try{if(l.error)throw l.error;if(l.done)break;yield l.value}finally{l.notify(!0)}else await(n=r?n:new Promise((t=>r=t)))}finally{for(r&&r(),s=()=>!1,"function"==typeof c&&await c();l=await e.shift();)l.notify(!1)}}((e=>t((async({done:t=!0,value:n,error:r}={})=>{r?await e.error(r):t?await e.complete():await e.next(n)}))))}async function*u(t,e,n={}){const r=new MessageChannel;t.postMessage({type:"START_CALL",params:n},[r.port2]);const s=function(t){let e=[],n=[];const r=async t=>{for(let n of e)await n(t)},s=d({port:t,handler:r});async function*a(){yield*l((t=>(e.push(t),()=>e=e.filter((e=>e!==t)))))}async function o(t){await async function(t,e){let n;try{for await(let n of e)await t({done:!1,value:n})}catch(t){n=t}finally{await t({done:!0,error:n})}}(s.invoke,async function*(){try{n.push(t),yield*t}finally{n=n.filter((e=>e!==t))}}())}return{start:()=>s.start(),close:async()=>{await r({done:!0}),[...n].forEach((t=>t.return&&t.return())),await s.close()},recieveAll:a,sendAll:o}}(r.port1);try{await s.start(),s.sendAll(e),yield*s.recieveAll()}finally{await s.close()}}function d({port:t,handler:e=(()=>{throw new Error("Handler not implemented")}),onError:n=console.error,newCallId:r=(()=>d.__counter=(d.__counter||0)+1)}){const s="REQUEST",i="RESPONSE",c="message",l={},u=async n=>{const r=n.data||{},{type:c,callId:u}=r;if(c===s)try{const{request:s}=r;let a=await e(s,...n.ports||[]);const[o,...c]=Array.isArray(a)?a:void 0!==a?[a]:[];t.postMessage({type:i,callId:u,response:o},c)}catch(e){t.postMessage({type:i,callId:u,error:a(e)})}else if(c===i){const{callId:t,response:e,error:n}=r,s=l[t];delete l[t],s&&(n?s.reject(o(n)):s.resolve(e))}};return{start:async()=>{try{t.addEventListener(c,u),t.start&&await t.start()}catch(t){n(t)}},close:async()=>{try{t.removeEventListener(c,u),t.close&&await t.close()}catch(t){n(t)}},invoke:async function(e={},...n){const a=r();return new Promise(((r,o)=>{try{l[a]={resolve:r,reject:o},t.postMessage({type:s,callId:a,request:e},n)}catch(t){o(t),delete e[a]}}))}}}function f(t){return async e=>{e=await e
|
|
1
|
+
// @statewalker/webrun-http-browser v0.3.1 https://github.com/statewalker/statewalker-webrun-http-browser Copyright 2023 Mikhail Kotelnikov
|
|
2
|
+
function t(t){return new Promise(((e,n)=>{t.oncomplete=t.onsuccess=()=>e(t.result),t.onabort=t.onerror=()=>n(t.error)}))}let e;function n(){return e||(e=function(e,n){const r=indexedDB.open(e);r.onupgradeneeded=()=>r.result.createObjectStore(n);const s=t(r);return(t,e)=>s.then((r=>e(r.transaction(n,t).objectStore(n))))}("keyval-store","keyval")),e}function r(e,r=n()){return r("readonly",(n=>t(n.get(e))))}function s(e,r,s=n()){return s("readwrite",(n=>(n.put(r,e),t(n.transaction))))}function a(t){return Object.assign({message:t,stack:t.stack},t)}function o(t){return"string"==typeof t&&(t={message:t}),Object.assign(new Error(t.message),t)}async function i(t,e,n,...r){return new Promise(((s,a)=>{const i=new MessageChannel;i.port1.onmessage=t=>{const{result:e,error:n}=t.data;n?a(o(n)):s(e)},t.postMessage({type:e,params:n},[i.port2,...r])}))}function c(t,e,n){const r=async t=>{if(!t.data||t.data.type!==e)return;const[r,...s]=t.ports;let o={};try{const e=t.data.params;o.result=await n(t,e,...s)}catch(t){o.error=a(t)}r.postMessage(o)};t.addEventListener("message",r);try{t.start&&t.start()}catch(t){}return()=>t.removeEventListener("message",r)}async function*l(t){yield*async function*(t,e=[]){let n,r,s=async(t,n,s)=>{const a={error:t,value:n,done:s};return a.promise=new Promise((t=>a.notify=t)),await e.push(a),r&&r(),r=null,a.promise};const a=t=>s(void 0,t,!1),o=()=>s(void 0,void 0,!0),i=t=>s(t,void 0,!0),c=t(Object.assign([a,o,i],{next:a,complete:o,error:i}));let l;try{for(;;)if(l=await e.shift(),l)try{if(l.error)throw l.error;if(l.done)break;yield l.value}finally{l.notify(!0)}else await(n=r?n:new Promise((t=>r=t)))}finally{for(r&&r(),s=()=>!1,"function"==typeof c&&await c();l=await e.shift();)l.notify(!1)}}((e=>t((async({done:t=!0,value:n,error:r}={})=>{r?await e.error(r):t?await e.complete():await e.next(n)}))))}async function*u(t,e,n={}){const r=new MessageChannel;t.postMessage({type:"START_CALL",params:n},[r.port2]);const s=function(t){let e=[],n=[];const r=async t=>{for(let n of e)await n(t)},s=d({port:t,handler:r});async function*a(){yield*l((t=>(e.push(t),()=>e=e.filter((e=>e!==t)))))}async function o(t){await async function(t,e){let n;try{for await(let n of e)await t({done:!1,value:n})}catch(t){n=t}finally{await t({done:!0,error:n})}}(s.invoke,async function*(){try{n.push(t),yield*t}finally{n=n.filter((e=>e!==t))}}())}return{start:()=>s.start(),close:async()=>{await r({done:!0}),[...n].forEach((t=>t.return&&t.return())),await s.close()},recieveAll:a,sendAll:o}}(r.port1);try{await s.start(),s.sendAll(e),yield*s.recieveAll()}finally{await s.close()}}function d({port:t,handler:e=(()=>{throw new Error("Handler not implemented")}),onError:n=console.error,newCallId:r=(()=>d.__counter=(d.__counter||0)+1)}){const s="REQUEST",i="RESPONSE",c="message",l={},u=async n=>{const r=n.data||{},{type:c,callId:u}=r;if(c===s)try{const{request:s}=r;let a=await e(s,...n.ports||[]);const[o,...c]=Array.isArray(a)?a:void 0!==a?[a]:[];t.postMessage({type:i,callId:u,response:o},c)}catch(e){t.postMessage({type:i,callId:u,error:a(e)})}else if(c===i){const{callId:t,response:e,error:n}=r,s=l[t];delete l[t],s&&(n?s.reject(o(n)):s.resolve(e))}};return{start:async()=>{try{t.addEventListener(c,u),t.start&&await t.start()}catch(t){n(t)}},close:async()=>{try{t.removeEventListener(c,u),t.close&&await t.close()}catch(t){n(t)}},invoke:async function(e={},...n){const a=r();return new Promise(((r,o)=>{try{l[a]={resolve:r,reject:o},t.postMessage({type:s,callId:a,request:e},n)}catch(t){o(t),delete e[a]}}))}}}function f(t){return async e=>{const n=[...(e=await e).headers].map((([t,e])=>[t,e])),r=["url","method","mode","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive"].reduce(((t,n)=>{const r=e[n];return void 0!==r&&(t[n]=r),t}),{headers:n}),s=e.body?async function*(t){const e=await t.getReader();let n,r;for(;({done:n,value:r}=await e.read())&&!n;)yield await r}(e.body):[],a=await t({options:r,content:s});let o=null,i={};if(a){i=a.options;const t=a.content;"HEAD"!==r.method&&"OPTIONS"!==r.method?(c=t,o=new ReadableStream({type:"bytes",async pull(t){let e=!1;try{for(;;){const e=await c.next();if(!e||e.done)break;t.enqueue(await e.value)}}catch(n){e=!0,t.error(n)}finally{!e&&t.close()}}})):t&&t.return&&t.return()}else i={status:404,statusText:"Error 404: Not Found"};var c;return new Response(o,i)}}async function y(t,e){const n=f((async e=>await async function(t){t=await t;const{done:e,value:n}=await t.next();let r={};if(!e&&n){const t=(new TextDecoder).decode(n);r=JSON.parse(t)}return{options:r,content:t}}(u(t,async function*(t){const{options:e,content:n}=await t,r=new TextEncoder;yield r.encode(JSON.stringify(e)),yield*n}(e)))));return await n(e)}class w extends Error{constructor(t){super(t.message),this.status=t.status,this.statusText=t.statusText}getResponseOptions(t={}){return Object.assign(this.toJson(),t)}toJson(){return{status:this.status,statusText:this.statusText,message:this.message}}static fromError(t){return t instanceof w||(t=new w(Object.assign({status:500,statusText:"Bad Request",reason:t.message}))),t}static errorResourceNotFound(t={}){return new w({status:404,statusText:"Error 404: Resource not found",...t})}static errorForbidden(t={}){return new w({status:403,statusText:"Error 403: Forbidden",...t})}static errorResourceGone(t={}){return new w({status:410,statusText:"Error 410: Resource Gone",...t})}static errorInternalError(t){return new w({...t,status:500,statusText:"Error 500: Internal error"})}}!function(t){const[e,n]=function(t=console.error){let e=0;const n={},r=r=>{const s=e++;return n[s]=Object.assign((function(e){try{return delete n[s],!e&&r&&r()}catch(e){t(e)}}),{action:r})},s=t=>Object.values(n).forEach((e=>e.action===t&&e(!0))),a=()=>Object.values(n).forEach((t=>t()));return Object.assign([r,a,s],{register:r,clear:a,unregister:s})}();"function"==typeof t.skipWaiting?(console.log("self.skipWaiting() is supported."),t.addEventListener("install",(e=>{e.waitUntil(t.skipWaiting())}))):console.log("self.skipWaiting() is not supported."),t.clients&&"function"==typeof t.clients.claim?(console.log("self.clients.claim() is supported."),t.addEventListener("activate",(e=>{e.waitUntil(t.clients.claim())}))):console.log("self.clients.claim() is not supported.");const a=function({self:t,key:e="clientsIds",get:n,set:r}){let s;async function a(){if(!s){const t=await n(e)||[];s=Object.fromEntries(t)}return s}async function o(){const t=await a(),n=Object.entries(t);return await r(e,n),t}async function i(t,e){const n=await a(),r=e.id;let s=!1;return r in n||(n[t]=r,await o(),s=!0),s}async function c(t){const e=await a();let n=!1;return t in e&&(delete e[t],await o(),n=!0),n}async function l(e){const n=await a(),r=n[e],s=await t.clients.get(r);return s||(delete n[e],await o()),s}return{getClient:l,addClient:i,removeClient:c}}({self:t,get:r,set:s});e(c(t,"REGISTER",(async(t,e)=>await a.addClient(e.key,t.source)))),e(c(t,"UNREGISTER",(async(t,e)=>await a.removeClient(e.key)))),e(c(t,"CONNECT",(async(t,e,n)=>{const{key:r}=e,s=await a.getClient(r);if(!s)throw new Error(`Target client was not found. Target key: "${r}".`);return await i(s,"CONNECT",e,n)})));const o=t=>{const e=t.request,n=function(t,e="~"){let n="",r="",s=t+"";const a=s.indexOf(e);let o="";return a>=0&&(o=s.substring(0,a+e.length),s.substring(a+e.length).replace(/^([^\/]+)/,((t,e)=>(o+=t,o.length<s.length&&(o+="/"),n=e,r=s.substring(o.length),"")))),{url:t,key:n,baseUrl:o,path:r}}(e.url),{key:r}=n;if(r){const s=async()=>{try{const t=new MessageChannel,s=await a.getClient(r);if(!s)throw w.errorResourceGone(n);const o={type:"http",key:r};if(!await i(s,"CONNECT",o,t.port2))throw w.errorForbidden(n);return await y(t.port1,e)}catch(t){const e=(t=w.fromError(t)).getResponseOptions(n);return new Response(JSON.stringify(e),{...e,headers:{"Content-Type":"text/javascript"}})}};t.respondWith(s())}};t.addEventListener("fetch",o),e((()=>t.removeEventListener("fetch",o)))}(self);
|
package/dist/index-umd.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @statewalker/webrun-http-browser v0.
|
|
1
|
+
// @statewalker/webrun-http-browser v0.3.1 https://github.com/statewalker/statewalker-webrun-http-browser Copyright 2023 Mikhail Kotelnikov
|
|
2
2
|
(function (global, factory) {
|
|
3
3
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
4
4
|
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
@@ -403,14 +403,18 @@ function newHttpClientStub(send) {
|
|
|
403
403
|
"referrer",
|
|
404
404
|
"referrerPolicy",
|
|
405
405
|
"integrity",
|
|
406
|
-
"keepalive"
|
|
406
|
+
"keepalive"
|
|
407
407
|
];
|
|
408
|
-
|
|
408
|
+
const headers = [...request.headers].map(([key, value]) => {
|
|
409
|
+
return [key, value]
|
|
410
|
+
});
|
|
409
411
|
const requestOptions = fields.reduce((options, key) => {
|
|
410
412
|
const val = request[key];
|
|
411
413
|
if (val !== undefined) options[key] = val;
|
|
412
414
|
return options;
|
|
413
|
-
}, {
|
|
415
|
+
}, {
|
|
416
|
+
headers
|
|
417
|
+
});
|
|
414
418
|
const requestContent = (request.body)
|
|
415
419
|
? fromReadableStream(request.body)
|
|
416
420
|
: [];
|
|
@@ -463,7 +467,11 @@ function newHttpServerStub(handler) {
|
|
|
463
467
|
content: requestContent,
|
|
464
468
|
} = await params;
|
|
465
469
|
let requestBody = undefined;
|
|
466
|
-
const { url, mode } = requestOptions;
|
|
470
|
+
const { url, mode, headers = [] } = requestOptions;
|
|
471
|
+
const requestHeaders = new Headers();
|
|
472
|
+
for (let [key, value] of headers) {
|
|
473
|
+
requestHeaders.append(key, value);
|
|
474
|
+
}
|
|
467
475
|
delete requestOptions.mode;
|
|
468
476
|
delete requestOptions.url;
|
|
469
477
|
if (
|
|
@@ -478,6 +486,7 @@ function newHttpServerStub(handler) {
|
|
|
478
486
|
}
|
|
479
487
|
const request = new Request(url, {
|
|
480
488
|
...requestOptions,
|
|
489
|
+
headers: requestHeaders,
|
|
481
490
|
// duplex: 'full',
|
|
482
491
|
body: requestBody,
|
|
483
492
|
});
|
|
@@ -741,9 +750,10 @@ async function newRemoteRelayChannel({
|
|
|
741
750
|
);
|
|
742
751
|
});
|
|
743
752
|
return {
|
|
753
|
+
baseUrl,
|
|
744
754
|
port: messageChannel.port2,
|
|
745
755
|
close: () => {
|
|
746
|
-
|
|
756
|
+
iframe.parentElement && iframe.parentElement.removeChild(iframe);
|
|
747
757
|
messageChannel.port1.close();
|
|
748
758
|
messageChannel.port2.close();
|
|
749
759
|
},
|
package/dist/index-umd.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// @statewalker/webrun-http-browser v0.
|
|
2
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).statewalker=e.statewalker||{},e.statewalker["webrun-http-browser"]=e.statewalker["webrun-http-browser"]||{}))}(this,(function(e){"use strict";function t(e){return Object.assign({message:e,stack:e.stack},e)}function n(e){return"string"==typeof e&&(e={message:e}),Object.assign(new Error(e.message),e)}async function r(e,t,r,...o){return new Promise(((a,s)=>{const c=new MessageChannel;c.port1.onmessage=e=>{const{result:t,error:r}=e.data;r?s(n(r)):a(t)},e.postMessage({type:t,params:r},[c.port2,...o])}))}function o(e,n,r){const o=async e=>{if(!e.data||e.data.type!==n)return;const[o,...a]=e.ports;let s={};try{const t=e.data.params;s.result=await r(e,t,...a)}catch(e){s.error=t(e)}o.postMessage(s)};e.addEventListener("message",o);try{e.start&&e.start()}catch(e){}return()=>e.removeEventListener("message",o)}function a(e=console.error){let t=0;const n={},r=r=>{const o=t++;return n[o]=Object.assign((function(t){try{return delete n[o],!t&&r&&r()}catch(t){e(t)}}),{action:r})},o=e=>Object.values(n).forEach((t=>t.action===e&&t(!0))),a=()=>Object.values(n).forEach((e=>e()));return Object.assign([r,a,o],{register:r,clear:a,unregister:o})}async function*s(e){yield*async function*(e,t=[]){let n,r,o=async(e,n,o)=>{const a={error:e,value:n,done:o};return a.promise=new Promise((e=>a.notify=e)),await t.push(a),r&&r(),r=null,a.promise};const a=e=>o(void 0,e,!1),s=()=>o(void 0,void 0,!0),c=e=>o(e,void 0,!0),i=e(Object.assign([a,s,c],{next:a,complete:s,error:c}));let l;try{for(;;)if(l=await t.shift(),l)try{if(l.error)throw l.error;if(l.done)break;yield l.value}finally{l.notify(!0)}else await(n=r?n:new Promise((e=>r=e)))}finally{for(r&&r(),o=()=>!1,"function"==typeof i&&await i();l=await t.shift();)l.notify(!1)}}((t=>e((async({done:e=!0,value:n,error:r}={})=>{r?await t.error(r):e?await t.complete():await t.next(n)}))))}async function c(e,t){let n;try{for await(let n of t)await e({done:!1,value:n})}catch(e){n=e}finally{await e({done:!0,error:n})}}async function*i(e,t,n={}){const r=new MessageChannel;e.postMessage({type:"START_CALL",params:n},[r.port2]);const o=u(r.port1);try{await o.start(),o.sendAll(t),yield*o.recieveAll()}finally{await o.close()}}function l(e,t){const n=async e=>{const{type:n,params:r}=e.data||{};if("START_CALL"!==n)return;const o=u(e.ports[0]);try{await o.start();const e=o.recieveAll(),n=await t(e,r);await o.sendAll(n)}finally{await o.close()}};e.addEventListener("message",n);try{e.start&&e.start()}catch(e){}return()=>e.removeEventListener("message",n)}function u(e){let t=[],n=[];const r=async e=>{for(let n of t)await n(e)},o=d({port:e,handler:r});return{start:()=>o.start(),close:async()=>{await r({done:!0}),[...n].forEach((e=>e.return&&e.return())),await o.close()},recieveAll:async function*(){yield*s((e=>(t.push(e),()=>t=t.filter((t=>t!==e)))))},sendAll:async function(e){await c(o.invoke,async function*(){try{n.push(e),yield*e}finally{n=n.filter((t=>t!==e))}}())}}}function d({port:e,handler:r=(()=>{throw new Error("Handler not implemented")}),onError:o=console.error,newCallId:a=(()=>d.__counter=(d.__counter||0)+1)}){const s="REQUEST",c="RESPONSE",i="message",l={},u=async o=>{const a=o.data||{},{type:i,callId:u}=a;if(i===s)try{const{request:t}=a;let n=await r(t,...o.ports||[]);const[s,...i]=Array.isArray(n)?n:void 0!==n?[n]:[];e.postMessage({type:c,callId:u,response:s},i)}catch(n){e.postMessage({type:c,callId:u,error:t(n)})}else if(i===c){const{callId:e,response:t,error:r}=a,o=l[e];delete l[e],o&&(r?o.reject(n(r)):o.resolve(t))}};return{start:async()=>{try{e.addEventListener(i,u),e.start&&await e.start()}catch(e){o(e)}},close:async()=>{try{e.removeEventListener(i,u),e.close&&await e.close()}catch(e){o(e)}},invoke:async function(t={},...n){const r=a();return new Promise(((o,a)=>{try{l[r]={resolve:o,reject:a},e.postMessage({type:s,callId:r,request:t},n)}catch(e){a(e),delete t[r]}}))}}}function f(e){return new ReadableStream({type:"bytes",async pull(t){let n=!1;try{for(;;){const n=await e.next();if(!n||n.done)break;t.enqueue(await n.value)}}catch(e){n=!0,t.error(e)}finally{!n&&t.close()}}})}async function*p(e){const t=await e.getReader();let n,r;for(;({done:n,value:r}=await t.read())&&!n;)yield await r}function y(e){return async t=>{t=await t;const n=["url","method","mode","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive"].reduce(((e,n)=>{const r=t[n];return void 0!==r&&(e[n]=r),e}),{}),r=t.body?p(t.body):[],o=await e({options:n,content:r});let a=null,s={};if(o){s=o.options;const e=o.content;"HEAD"!==n.method&&"OPTIONS"!==n.method?a=f(e):e&&e.return&&e.return()}else s={status:404,statusText:"Error 404: Not Found"};return new Response(a,s)}}function w(e){return async t=>{const{options:n,content:r}=await t;let o;const{url:a,mode:s}=n;delete n.mode,delete n.url,"GET"!==n.method&&"HEAD"!==n.method&&"OPTIONS"!==n.method?(o=f(r),n.duplex="half"):r&&r.return&&r.return();const c=new Request(a,{...n,body:o}),i=await e(c);return{options:{status:i.status,statusText:i.statusText,headers:Object.fromEntries([...i.headers])},content:await p(await i.body)}}}async function*m(e){const{options:t,content:n}=await e,r=new TextEncoder;yield r.encode(JSON.stringify(t)),yield*n}async function h(e){e=await e;const{done:t,value:n}=await e.next();let r={};if(!t&&n){const e=(new TextDecoder).decode(n);r=JSON.parse(e)}return{options:r,content:e}}function g(e,t){const n=w(t);return l(e,(e=>m(n(h(e)))))}async function v(e,t){const n=y((async t=>await h(i(e,m(t)))));return await n(t)}function b(){const e=new MessageChannel;return e.port1.onmessage=e=>{navigator.serviceWorker.controller.postMessage(e.data,e.ports)},navigator.serviceWorker.addEventListener("message",(t=>{e.port1.postMessage(t.data,t.ports)})),e.port2}async function E({swUrl:e,scopeUrl:t,type:n}){await navigator.serviceWorker.register(e,{type:n,scope:t});const r=await async function(){return await new Promise((e=>{const t=navigator.serviceWorker;if(t.controller)e(t.controller);else{const n=()=>{e(t.controller),t.removeEventListener("controllerchange",n),t.oncontrollerchange=null};t.addEventListener("controllerchange",n),t.oncontrollerchange=n}}))}();return await async function(e){const t=()=>"activated"===e.state;await new Promise((async n=>{t()?n():e.onstatechange=()=>{t()&&(e.onstatechange=null,n())}}))}(r),r}async function R({key:e,communicationPort:t,...n}){const o=new MessageChannel;return await r(t,"CONNECT",{key:e,...n},o.port2)?o.port1:(o.port1.close(),o.port2.close(),null)}async function k({key:e,handler:t,communicationPort:n}){const[s,c]=a();return await r(n,"REGISTER",{key:e}),s((()=>r(n,"UNREGISTER",{key:e}))),s(o(n,"CONNECT",t)),c}e.callChannel=r,e.callHttpService=async function(e,{key:t,port:n}){const r=await R({key:t,communicationPort:n});return await v(r,e)},e.deserializeError=n,e.fromReadableStream=p,e.getRelayWindowMessageHandler=function({swUrl:e=new URL("./index-sw.js","undefined"==typeof document&&"undefined"==typeof location?new(require("url").URL)("file:"+__filename).href:"undefined"==typeof document?location.href:document.currentScript&&document.currentScript.src||new URL("index-umd.min.js",document.baseURI).href)+"",scopeUrl:t=new URL("../","undefined"==typeof document&&"undefined"==typeof location?new(require("url").URL)("file:"+__filename).href:"undefined"==typeof document?location.href:document.currentScript&&document.currentScript.src||new URL("index-umd.min.js",document.baseURI).href)+""}={}){let n;return async r=>{if("CONNECT"===r.data.type){const o=(r.ports||[])[0];if(n)return void o.close();n=o,await E({swUrl:e,scopeUrl:t});const a=b();a.onmessage=e=>{n.postMessage(e.data,e.ports)},n.onmessage=e=>{a.postMessage(e.data,e.ports)}}}},e.handleChannelCalls=o,e.handleHttpRequests=g,e.handleStreams=l,e.initHttpService=async function(e,{key:t,port:n}){return await k({key:t,communicationPort:n,handler:async(t,n,r)=>(g(r,e),!0)})},e.initServiceWorker=E,e.initServiceWorker1=async function({swUrl:e,scopeUrl:t,type:n}){const{installing:r,waiting:o,active:a}=await navigator.serviceWorker.register(e,{scope:t});(r||o||a).addEventListener("statechange",(e=>{console.log("state",e.target.state)}));const s=navigator.serviceWorker;await new Promise((e=>{if(s.controller)e();else{const t=()=>{e(),s.removeEventListener("controllerchange",t),s.oncontrollerchange=null};s.addEventListener("controllerchange",t),s.oncontrollerchange=t}}));const c=s.controller,i=()=>"activated"===c.state;return await new Promise((async e=>{i()?e(c):c.onstatechange=()=>{i()&&(c.onstatechange=null,e(c))}}))},e.initializeConnection=R,e.newHttpClientStub=y,e.newHttpServerStub=w,e.newInvokationChannel=d,e.newRegistry=a,e.newRemoteRelayChannel=async function({baseUrl:e=new URL("../public-relay/","undefined"==typeof document&&"undefined"==typeof location?new(require("url").URL)("file:"+__filename).href:"undefined"==typeof document?location.href:document.currentScript&&document.currentScript.src||new URL("index-umd.min.js",document.baseURI).href),url:t=new URL("relay.html",e),container:n=document.body}={}){const r=new MessageChannel,{iframe:o,promise:a}=await async function(e){const t=document.createElement("iframe");return t.src=e,Object.assign(t.style,{padding:0,margin:0,border:"none",outline:"none",width:"100%",height:"100%"}),{iframe:t,promise:new Promise(((e,n)=>{try{t.onerror=n,t.onload=()=>e(t)}catch(e){n(e)}}))}}(t);return Object.assign(o.style,{position:"fixed",width:"1px",height:"1px",top:"-1000",left:"-1000",display:"block",opacity:"0",border:"none",outline:"none"}),n.appendChild(o),a.then((()=>{o.contentWindow.postMessage({type:"CONNECT"},"*",[r.port1])})),{port:r.port2,close:()=>{n.parentElement&&n.parentElement.removeChild(n),r.port1.close(),r.port2.close()}}},e.newServiceWorkerPort=b,e.recieveData=s,e.registerConnectionsHandler=k,e.sendData=c,e.sendHttpRequest=v,e.sendStream=i,e.serializeError=t,e.splitServiceUrl=function(e,t="~"){let n="",r="",o=e+"";const a=o.indexOf(t);let s="";return a>=0&&(s=o.substring(0,a+t.length),o.substring(a+t.length).replace(/^([^\/]+)/,((e,t)=>(s+=e,s.length<o.length&&(s+="/"),n=t,r=o.substring(s.length),"")))),{url:e,key:n,baseUrl:s,path:r}},e.toReadableStream=f}));
|
|
1
|
+
// @statewalker/webrun-http-browser v0.3.1 https://github.com/statewalker/statewalker-webrun-http-browser Copyright 2023 Mikhail Kotelnikov
|
|
2
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).statewalker=e.statewalker||{},e.statewalker["webrun-http-browser"]=e.statewalker["webrun-http-browser"]||{}))}(this,(function(e){"use strict";function t(e){return Object.assign({message:e,stack:e.stack},e)}function n(e){return"string"==typeof e&&(e={message:e}),Object.assign(new Error(e.message),e)}async function r(e,t,r,...o){return new Promise(((a,s)=>{const c=new MessageChannel;c.port1.onmessage=e=>{const{result:t,error:r}=e.data;r?s(n(r)):a(t)},e.postMessage({type:t,params:r},[c.port2,...o])}))}function o(e,n,r){const o=async e=>{if(!e.data||e.data.type!==n)return;const[o,...a]=e.ports;let s={};try{const t=e.data.params;s.result=await r(e,t,...a)}catch(e){s.error=t(e)}o.postMessage(s)};e.addEventListener("message",o);try{e.start&&e.start()}catch(e){}return()=>e.removeEventListener("message",o)}function a(e=console.error){let t=0;const n={},r=r=>{const o=t++;return n[o]=Object.assign((function(t){try{return delete n[o],!t&&r&&r()}catch(t){e(t)}}),{action:r})},o=e=>Object.values(n).forEach((t=>t.action===e&&t(!0))),a=()=>Object.values(n).forEach((e=>e()));return Object.assign([r,a,o],{register:r,clear:a,unregister:o})}async function*s(e){yield*async function*(e,t=[]){let n,r,o=async(e,n,o)=>{const a={error:e,value:n,done:o};return a.promise=new Promise((e=>a.notify=e)),await t.push(a),r&&r(),r=null,a.promise};const a=e=>o(void 0,e,!1),s=()=>o(void 0,void 0,!0),c=e=>o(e,void 0,!0),i=e(Object.assign([a,s,c],{next:a,complete:s,error:c}));let l;try{for(;;)if(l=await t.shift(),l)try{if(l.error)throw l.error;if(l.done)break;yield l.value}finally{l.notify(!0)}else await(n=r?n:new Promise((e=>r=e)))}finally{for(r&&r(),o=()=>!1,"function"==typeof i&&await i();l=await t.shift();)l.notify(!1)}}((t=>e((async({done:e=!0,value:n,error:r}={})=>{r?await t.error(r):e?await t.complete():await t.next(n)}))))}async function c(e,t){let n;try{for await(let n of t)await e({done:!1,value:n})}catch(e){n=e}finally{await e({done:!0,error:n})}}async function*i(e,t,n={}){const r=new MessageChannel;e.postMessage({type:"START_CALL",params:n},[r.port2]);const o=u(r.port1);try{await o.start(),o.sendAll(t),yield*o.recieveAll()}finally{await o.close()}}function l(e,t){const n=async e=>{const{type:n,params:r}=e.data||{};if("START_CALL"!==n)return;const o=u(e.ports[0]);try{await o.start();const e=o.recieveAll(),n=await t(e,r);await o.sendAll(n)}finally{await o.close()}};e.addEventListener("message",n);try{e.start&&e.start()}catch(e){}return()=>e.removeEventListener("message",n)}function u(e){let t=[],n=[];const r=async e=>{for(let n of t)await n(e)},o=d({port:e,handler:r});return{start:()=>o.start(),close:async()=>{await r({done:!0}),[...n].forEach((e=>e.return&&e.return())),await o.close()},recieveAll:async function*(){yield*s((e=>(t.push(e),()=>t=t.filter((t=>t!==e)))))},sendAll:async function(e){await c(o.invoke,async function*(){try{n.push(e),yield*e}finally{n=n.filter((t=>t!==e))}}())}}}function d({port:e,handler:r=(()=>{throw new Error("Handler not implemented")}),onError:o=console.error,newCallId:a=(()=>d.__counter=(d.__counter||0)+1)}){const s="REQUEST",c="RESPONSE",i="message",l={},u=async o=>{const a=o.data||{},{type:i,callId:u}=a;if(i===s)try{const{request:t}=a;let n=await r(t,...o.ports||[]);const[s,...i]=Array.isArray(n)?n:void 0!==n?[n]:[];e.postMessage({type:c,callId:u,response:s},i)}catch(n){e.postMessage({type:c,callId:u,error:t(n)})}else if(i===c){const{callId:e,response:t,error:r}=a,o=l[e];delete l[e],o&&(r?o.reject(n(r)):o.resolve(t))}};return{start:async()=>{try{e.addEventListener(i,u),e.start&&await e.start()}catch(e){o(e)}},close:async()=>{try{e.removeEventListener(i,u),e.close&&await e.close()}catch(e){o(e)}},invoke:async function(t={},...n){const r=a();return new Promise(((o,a)=>{try{l[r]={resolve:o,reject:a},e.postMessage({type:s,callId:r,request:t},n)}catch(e){a(e),delete t[r]}}))}}}function f(e){return new ReadableStream({type:"bytes",async pull(t){let n=!1;try{for(;;){const n=await e.next();if(!n||n.done)break;t.enqueue(await n.value)}}catch(e){n=!0,t.error(e)}finally{!n&&t.close()}}})}async function*p(e){const t=await e.getReader();let n,r;for(;({done:n,value:r}=await t.read())&&!n;)yield await r}function y(e){return async t=>{const n=[...(t=await t).headers].map((([e,t])=>[e,t])),r=["url","method","mode","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive"].reduce(((e,n)=>{const r=t[n];return void 0!==r&&(e[n]=r),e}),{headers:n}),o=t.body?p(t.body):[],a=await e({options:r,content:o});let s=null,c={};if(a){c=a.options;const e=a.content;"HEAD"!==r.method&&"OPTIONS"!==r.method?s=f(e):e&&e.return&&e.return()}else c={status:404,statusText:"Error 404: Not Found"};return new Response(s,c)}}function w(e){return async t=>{const{options:n,content:r}=await t;let o;const{url:a,mode:s,headers:c=[]}=n,i=new Headers;for(let[e,t]of c)i.append(e,t);delete n.mode,delete n.url,"GET"!==n.method&&"HEAD"!==n.method&&"OPTIONS"!==n.method?(o=f(r),n.duplex="half"):r&&r.return&&r.return();const l=new Request(a,{...n,headers:i,body:o}),u=await e(l);return{options:{status:u.status,statusText:u.statusText,headers:Object.fromEntries([...u.headers])},content:await p(await u.body)}}}async function*m(e){const{options:t,content:n}=await e,r=new TextEncoder;yield r.encode(JSON.stringify(t)),yield*n}async function h(e){e=await e;const{done:t,value:n}=await e.next();let r={};if(!t&&n){const e=(new TextDecoder).decode(n);r=JSON.parse(e)}return{options:r,content:e}}function g(e,t){const n=w(t);return l(e,(e=>m(n(h(e)))))}async function v(e,t){const n=y((async t=>await h(i(e,m(t)))));return await n(t)}function b(){const e=new MessageChannel;return e.port1.onmessage=e=>{navigator.serviceWorker.controller.postMessage(e.data,e.ports)},navigator.serviceWorker.addEventListener("message",(t=>{e.port1.postMessage(t.data,t.ports)})),e.port2}async function E({swUrl:e,scopeUrl:t,type:n}){await navigator.serviceWorker.register(e,{type:n,scope:t});const r=await async function(){return await new Promise((e=>{const t=navigator.serviceWorker;if(t.controller)e(t.controller);else{const n=()=>{e(t.controller),t.removeEventListener("controllerchange",n),t.oncontrollerchange=null};t.addEventListener("controllerchange",n),t.oncontrollerchange=n}}))}();return await async function(e){const t=()=>"activated"===e.state;await new Promise((async n=>{t()?n():e.onstatechange=()=>{t()&&(e.onstatechange=null,n())}}))}(r),r}async function R({key:e,communicationPort:t,...n}){const o=new MessageChannel;return await r(t,"CONNECT",{key:e,...n},o.port2)?o.port1:(o.port1.close(),o.port2.close(),null)}async function k({key:e,handler:t,communicationPort:n}){const[s,c]=a();return await r(n,"REGISTER",{key:e}),s((()=>r(n,"UNREGISTER",{key:e}))),s(o(n,"CONNECT",t)),c}e.callChannel=r,e.callHttpService=async function(e,{key:t,port:n}){const r=await R({key:t,communicationPort:n});return await v(r,e)},e.deserializeError=n,e.fromReadableStream=p,e.getRelayWindowMessageHandler=function({swUrl:e=new URL("./index-sw.js","undefined"==typeof document&&"undefined"==typeof location?new(require("url").URL)("file:"+__filename).href:"undefined"==typeof document?location.href:document.currentScript&&document.currentScript.src||new URL("index-umd.min.js",document.baseURI).href)+"",scopeUrl:t=new URL("../","undefined"==typeof document&&"undefined"==typeof location?new(require("url").URL)("file:"+__filename).href:"undefined"==typeof document?location.href:document.currentScript&&document.currentScript.src||new URL("index-umd.min.js",document.baseURI).href)+""}={}){let n;return async r=>{if("CONNECT"===r.data.type){const o=(r.ports||[])[0];if(n)return void o.close();n=o,await E({swUrl:e,scopeUrl:t});const a=b();a.onmessage=e=>{n.postMessage(e.data,e.ports)},n.onmessage=e=>{a.postMessage(e.data,e.ports)}}}},e.handleChannelCalls=o,e.handleHttpRequests=g,e.handleStreams=l,e.initHttpService=async function(e,{key:t,port:n}){return await k({key:t,communicationPort:n,handler:async(t,n,r)=>(g(r,e),!0)})},e.initServiceWorker=E,e.initServiceWorker1=async function({swUrl:e,scopeUrl:t,type:n}){const{installing:r,waiting:o,active:a}=await navigator.serviceWorker.register(e,{scope:t});(r||o||a).addEventListener("statechange",(e=>{console.log("state",e.target.state)}));const s=navigator.serviceWorker;await new Promise((e=>{if(s.controller)e();else{const t=()=>{e(),s.removeEventListener("controllerchange",t),s.oncontrollerchange=null};s.addEventListener("controllerchange",t),s.oncontrollerchange=t}}));const c=s.controller,i=()=>"activated"===c.state;return await new Promise((async e=>{i()?e(c):c.onstatechange=()=>{i()&&(c.onstatechange=null,e(c))}}))},e.initializeConnection=R,e.newHttpClientStub=y,e.newHttpServerStub=w,e.newInvokationChannel=d,e.newRegistry=a,e.newRemoteRelayChannel=async function({baseUrl:e=new URL("../public-relay/","undefined"==typeof document&&"undefined"==typeof location?new(require("url").URL)("file:"+__filename).href:"undefined"==typeof document?location.href:document.currentScript&&document.currentScript.src||new URL("index-umd.min.js",document.baseURI).href),url:t=new URL("relay.html",e),container:n=document.body}={}){const r=new MessageChannel,{iframe:o,promise:a}=await async function(e){const t=document.createElement("iframe");return t.src=e,Object.assign(t.style,{padding:0,margin:0,border:"none",outline:"none",width:"100%",height:"100%"}),{iframe:t,promise:new Promise(((e,n)=>{try{t.onerror=n,t.onload=()=>e(t)}catch(e){n(e)}}))}}(t);return Object.assign(o.style,{position:"fixed",width:"1px",height:"1px",top:"-1000",left:"-1000",display:"block",opacity:"0",border:"none",outline:"none"}),n.appendChild(o),a.then((()=>{o.contentWindow.postMessage({type:"CONNECT"},"*",[r.port1])})),{baseUrl:e,port:r.port2,close:()=>{o.parentElement&&o.parentElement.removeChild(o),r.port1.close(),r.port2.close()}}},e.newServiceWorkerPort=b,e.recieveData=s,e.registerConnectionsHandler=k,e.sendData=c,e.sendHttpRequest=v,e.sendStream=i,e.serializeError=t,e.splitServiceUrl=function(e,t="~"){let n="",r="",o=e+"";const a=o.indexOf(t);let s="";return a>=0&&(s=o.substring(0,a+t.length),o.substring(a+t.length).replace(/^([^\/]+)/,((e,t)=>(s+=e,s.length<o.length&&(s+="/"),n=t,r=o.substring(s.length),"")))),{url:e,key:n,baseUrl:s,path:r}},e.toReadableStream=f}));
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @statewalker/webrun-http-browser v0.
|
|
1
|
+
// @statewalker/webrun-http-browser v0.3.1 https://github.com/statewalker/statewalker-webrun-http-browser Copyright 2023 Mikhail Kotelnikov
|
|
2
2
|
function serializeError(error) {
|
|
3
3
|
return Object.assign({
|
|
4
4
|
message: error,
|
|
@@ -397,14 +397,18 @@ function newHttpClientStub(send) {
|
|
|
397
397
|
"referrer",
|
|
398
398
|
"referrerPolicy",
|
|
399
399
|
"integrity",
|
|
400
|
-
"keepalive"
|
|
400
|
+
"keepalive"
|
|
401
401
|
];
|
|
402
|
-
|
|
402
|
+
const headers = [...request.headers].map(([key, value]) => {
|
|
403
|
+
return [key, value]
|
|
404
|
+
});
|
|
403
405
|
const requestOptions = fields.reduce((options, key) => {
|
|
404
406
|
const val = request[key];
|
|
405
407
|
if (val !== undefined) options[key] = val;
|
|
406
408
|
return options;
|
|
407
|
-
}, {
|
|
409
|
+
}, {
|
|
410
|
+
headers
|
|
411
|
+
});
|
|
408
412
|
const requestContent = (request.body)
|
|
409
413
|
? fromReadableStream(request.body)
|
|
410
414
|
: [];
|
|
@@ -457,7 +461,11 @@ function newHttpServerStub(handler) {
|
|
|
457
461
|
content: requestContent,
|
|
458
462
|
} = await params;
|
|
459
463
|
let requestBody = undefined;
|
|
460
|
-
const { url, mode } = requestOptions;
|
|
464
|
+
const { url, mode, headers = [] } = requestOptions;
|
|
465
|
+
const requestHeaders = new Headers();
|
|
466
|
+
for (let [key, value] of headers) {
|
|
467
|
+
requestHeaders.append(key, value);
|
|
468
|
+
}
|
|
461
469
|
delete requestOptions.mode;
|
|
462
470
|
delete requestOptions.url;
|
|
463
471
|
if (
|
|
@@ -472,6 +480,7 @@ function newHttpServerStub(handler) {
|
|
|
472
480
|
}
|
|
473
481
|
const request = new Request(url, {
|
|
474
482
|
...requestOptions,
|
|
483
|
+
headers: requestHeaders,
|
|
475
484
|
// duplex: 'full',
|
|
476
485
|
body: requestBody,
|
|
477
486
|
});
|
|
@@ -735,9 +744,10 @@ async function newRemoteRelayChannel({
|
|
|
735
744
|
);
|
|
736
745
|
});
|
|
737
746
|
return {
|
|
747
|
+
baseUrl,
|
|
738
748
|
port: messageChannel.port2,
|
|
739
749
|
close: () => {
|
|
740
|
-
|
|
750
|
+
iframe.parentElement && iframe.parentElement.removeChild(iframe);
|
|
741
751
|
messageChannel.port1.close();
|
|
742
752
|
messageChannel.port2.close();
|
|
743
753
|
},
|
package/dist/index.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// @statewalker/webrun-http-browser v0.
|
|
2
|
-
function e(e){return Object.assign({message:e,stack:e.stack},e)}function t(e){return"string"==typeof e&&(e={message:e}),Object.assign(new Error(e.message),e)}async function n(e,n,r,...a){return new Promise(((o,s)=>{const c=new MessageChannel;c.port1.onmessage=e=>{const{result:n,error:r}=e.data;r?s(t(r)):o(n)},e.postMessage({type:n,params:r},[c.port2,...a])}))}function r(t,n,r){const a=async t=>{if(!t.data||t.data.type!==n)return;const[a,...o]=t.ports;let s={};try{const e=t.data.params;s.result=await r(t,e,...o)}catch(t){s.error=e(t)}a.postMessage(s)};t.addEventListener("message",a);try{t.start&&t.start()}catch(e){}return()=>t.removeEventListener("message",a)}function a(e=console.error){let t=0;const n={},r=r=>{const a=t++;return n[a]=Object.assign((function(t){try{return delete n[a],!t&&r&&r()}catch(t){e(t)}}),{action:r})},a=e=>Object.values(n).forEach((t=>t.action===e&&t(!0))),o=()=>Object.values(n).forEach((e=>e()));return Object.assign([r,o,a],{register:r,clear:o,unregister:a})}async function*o(e){yield*async function*(e,t=[]){let n,r,a=async(e,n,a)=>{const o={error:e,value:n,done:a};return o.promise=new Promise((e=>o.notify=e)),await t.push(o),r&&r(),r=null,o.promise};const o=e=>a(void 0,e,!1),s=()=>a(void 0,void 0,!0),c=e=>a(e,void 0,!0),i=e(Object.assign([o,s,c],{next:o,complete:s,error:c}));let l;try{for(;;)if(l=await t.shift(),l)try{if(l.error)throw l.error;if(l.done)break;yield l.value}finally{l.notify(!0)}else await(n=r?n:new Promise((e=>r=e)))}finally{for(r&&r(),a=()=>!1,"function"==typeof i&&await i();l=await t.shift();)l.notify(!1)}}((t=>e((async({done:e=!0,value:n,error:r}={})=>{r?await t.error(r):e?await t.complete():await t.next(n)}))))}async function s(e,t){let n;try{for await(let n of t)await e({done:!1,value:n})}catch(e){n=e}finally{await e({done:!0,error:n})}}async function*c(e,t,n={}){const r=new MessageChannel;e.postMessage({type:"START_CALL",params:n},[r.port2]);const a=l(r.port1);try{await a.start(),a.sendAll(t),yield*a.recieveAll()}finally{await a.close()}}function i(e,t){const n=async e=>{const{type:n,params:r}=e.data||{};if("START_CALL"!==n)return;const a=l(e.ports[0]);try{await a.start();const e=a.recieveAll(),n=await t(e,r);await a.sendAll(n)}finally{await a.close()}};e.addEventListener("message",n);try{e.start&&e.start()}catch(e){}return()=>e.removeEventListener("message",n)}function l(e){let t=[],n=[];const r=async e=>{for(let n of t)await n(e)},a=u({port:e,handler:r});return{start:()=>a.start(),close:async()=>{await r({done:!0}),[...n].forEach((e=>e.return&&e.return())),await a.close()},recieveAll:async function*(){yield*o((e=>(t.push(e),()=>t=t.filter((t=>t!==e)))))},sendAll:async function(e){await s(a.invoke,async function*(){try{n.push(e),yield*e}finally{n=n.filter((t=>t!==e))}}())}}}function u({port:n,handler:r=(()=>{throw new Error("Handler not implemented")}),onError:a=console.error,newCallId:o=(()=>u.__counter=(u.__counter||0)+1)}){const s="REQUEST",c="RESPONSE",i="message",l={},d=async a=>{const o=a.data||{},{type:i,callId:u}=o;if(i===s)try{const{request:e}=o;let t=await r(e,...a.ports||[]);const[s,...i]=Array.isArray(t)?t:void 0!==t?[t]:[];n.postMessage({type:c,callId:u,response:s},i)}catch(t){n.postMessage({type:c,callId:u,error:e(t)})}else if(i===c){const{callId:e,response:n,error:r}=o,a=l[e];delete l[e],a&&(r?a.reject(t(r)):a.resolve(n))}};return{start:async()=>{try{n.addEventListener(i,d),n.start&&await n.start()}catch(e){a(e)}},close:async()=>{try{n.removeEventListener(i,d),n.close&&await n.close()}catch(e){a(e)}},invoke:async function(e={},...t){const r=o();return new Promise(((a,o)=>{try{l[r]={resolve:a,reject:o},n.postMessage({type:s,callId:r,request:e},t)}catch(t){o(t),delete e[r]}}))}}}function d(e){return new ReadableStream({type:"bytes",async pull(t){let n=!1;try{for(;;){const n=await e.next();if(!n||n.done)break;t.enqueue(await n.value)}}catch(e){n=!0,t.error(e)}finally{!n&&t.close()}}})}async function*y(e){const t=await e.getReader();let n,r;for(;({done:n,value:r}=await t.read())&&!n;)yield await r}function p(e){return async t=>{t=await t
|
|
1
|
+
// @statewalker/webrun-http-browser v0.3.1 https://github.com/statewalker/statewalker-webrun-http-browser Copyright 2023 Mikhail Kotelnikov
|
|
2
|
+
function e(e){return Object.assign({message:e,stack:e.stack},e)}function t(e){return"string"==typeof e&&(e={message:e}),Object.assign(new Error(e.message),e)}async function n(e,n,r,...a){return new Promise(((o,s)=>{const c=new MessageChannel;c.port1.onmessage=e=>{const{result:n,error:r}=e.data;r?s(t(r)):o(n)},e.postMessage({type:n,params:r},[c.port2,...a])}))}function r(t,n,r){const a=async t=>{if(!t.data||t.data.type!==n)return;const[a,...o]=t.ports;let s={};try{const e=t.data.params;s.result=await r(t,e,...o)}catch(t){s.error=e(t)}a.postMessage(s)};t.addEventListener("message",a);try{t.start&&t.start()}catch(e){}return()=>t.removeEventListener("message",a)}function a(e=console.error){let t=0;const n={},r=r=>{const a=t++;return n[a]=Object.assign((function(t){try{return delete n[a],!t&&r&&r()}catch(t){e(t)}}),{action:r})},a=e=>Object.values(n).forEach((t=>t.action===e&&t(!0))),o=()=>Object.values(n).forEach((e=>e()));return Object.assign([r,o,a],{register:r,clear:o,unregister:a})}async function*o(e){yield*async function*(e,t=[]){let n,r,a=async(e,n,a)=>{const o={error:e,value:n,done:a};return o.promise=new Promise((e=>o.notify=e)),await t.push(o),r&&r(),r=null,o.promise};const o=e=>a(void 0,e,!1),s=()=>a(void 0,void 0,!0),c=e=>a(e,void 0,!0),i=e(Object.assign([o,s,c],{next:o,complete:s,error:c}));let l;try{for(;;)if(l=await t.shift(),l)try{if(l.error)throw l.error;if(l.done)break;yield l.value}finally{l.notify(!0)}else await(n=r?n:new Promise((e=>r=e)))}finally{for(r&&r(),a=()=>!1,"function"==typeof i&&await i();l=await t.shift();)l.notify(!1)}}((t=>e((async({done:e=!0,value:n,error:r}={})=>{r?await t.error(r):e?await t.complete():await t.next(n)}))))}async function s(e,t){let n;try{for await(let n of t)await e({done:!1,value:n})}catch(e){n=e}finally{await e({done:!0,error:n})}}async function*c(e,t,n={}){const r=new MessageChannel;e.postMessage({type:"START_CALL",params:n},[r.port2]);const a=l(r.port1);try{await a.start(),a.sendAll(t),yield*a.recieveAll()}finally{await a.close()}}function i(e,t){const n=async e=>{const{type:n,params:r}=e.data||{};if("START_CALL"!==n)return;const a=l(e.ports[0]);try{await a.start();const e=a.recieveAll(),n=await t(e,r);await a.sendAll(n)}finally{await a.close()}};e.addEventListener("message",n);try{e.start&&e.start()}catch(e){}return()=>e.removeEventListener("message",n)}function l(e){let t=[],n=[];const r=async e=>{for(let n of t)await n(e)},a=u({port:e,handler:r});return{start:()=>a.start(),close:async()=>{await r({done:!0}),[...n].forEach((e=>e.return&&e.return())),await a.close()},recieveAll:async function*(){yield*o((e=>(t.push(e),()=>t=t.filter((t=>t!==e)))))},sendAll:async function(e){await s(a.invoke,async function*(){try{n.push(e),yield*e}finally{n=n.filter((t=>t!==e))}}())}}}function u({port:n,handler:r=(()=>{throw new Error("Handler not implemented")}),onError:a=console.error,newCallId:o=(()=>u.__counter=(u.__counter||0)+1)}){const s="REQUEST",c="RESPONSE",i="message",l={},d=async a=>{const o=a.data||{},{type:i,callId:u}=o;if(i===s)try{const{request:e}=o;let t=await r(e,...a.ports||[]);const[s,...i]=Array.isArray(t)?t:void 0!==t?[t]:[];n.postMessage({type:c,callId:u,response:s},i)}catch(t){n.postMessage({type:c,callId:u,error:e(t)})}else if(i===c){const{callId:e,response:n,error:r}=o,a=l[e];delete l[e],a&&(r?a.reject(t(r)):a.resolve(n))}};return{start:async()=>{try{n.addEventListener(i,d),n.start&&await n.start()}catch(e){a(e)}},close:async()=>{try{n.removeEventListener(i,d),n.close&&await n.close()}catch(e){a(e)}},invoke:async function(e={},...t){const r=o();return new Promise(((a,o)=>{try{l[r]={resolve:a,reject:o},n.postMessage({type:s,callId:r,request:e},t)}catch(t){o(t),delete e[r]}}))}}}function d(e){return new ReadableStream({type:"bytes",async pull(t){let n=!1;try{for(;;){const n=await e.next();if(!n||n.done)break;t.enqueue(await n.value)}}catch(e){n=!0,t.error(e)}finally{!n&&t.close()}}})}async function*y(e){const t=await e.getReader();let n,r;for(;({done:n,value:r}=await t.read())&&!n;)yield await r}function p(e){return async t=>{const n=[...(t=await t).headers].map((([e,t])=>[e,t])),r=["url","method","mode","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive"].reduce(((e,n)=>{const r=t[n];return void 0!==r&&(e[n]=r),e}),{headers:n}),a=t.body?y(t.body):[],o=await e({options:r,content:a});let s=null,c={};if(o){c=o.options;const e=o.content;"HEAD"!==r.method&&"OPTIONS"!==r.method?s=d(e):e&&e.return&&e.return()}else c={status:404,statusText:"Error 404: Not Found"};return new Response(s,c)}}function w(e){return async t=>{const{options:n,content:r}=await t;let a;const{url:o,mode:s,headers:c=[]}=n,i=new Headers;for(let[e,t]of c)i.append(e,t);delete n.mode,delete n.url,"GET"!==n.method&&"HEAD"!==n.method&&"OPTIONS"!==n.method?(a=d(r),n.duplex="half"):r&&r.return&&r.return();const l=new Request(o,{...n,headers:i,body:a}),u=await e(l);return{options:{status:u.status,statusText:u.statusText,headers:Object.fromEntries([...u.headers])},content:await y(await u.body)}}}async function*f(e){const{options:t,content:n}=await e,r=new TextEncoder;yield r.encode(JSON.stringify(t)),yield*n}async function g(e){e=await e;const{done:t,value:n}=await e.next();let r={};if(!t&&n){const e=(new TextDecoder).decode(n);r=JSON.parse(e)}return{options:r,content:e}}function m(e,t){const n=w(t);return i(e,(e=>f(n(g(e)))))}async function h(e,t){const n=p((async t=>await g(c(e,f(t)))));return await n(t)}function v(e,t="~"){let n="",r="",a=e+"";const o=a.indexOf(t);let s="";return o>=0&&(s=a.substring(0,o+t.length),a.substring(o+t.length).replace(/^([^\/]+)/,((e,t)=>(s+=e,s.length<a.length&&(s+="/"),n=t,r=a.substring(s.length),"")))),{url:e,key:n,baseUrl:s,path:r}}function E(){const e=new MessageChannel;return e.port1.onmessage=e=>{navigator.serviceWorker.controller.postMessage(e.data,e.ports)},navigator.serviceWorker.addEventListener("message",(t=>{e.port1.postMessage(t.data,t.ports)})),e.port2}async function b({swUrl:e,scopeUrl:t,type:n}){const{installing:r,waiting:a,active:o}=await navigator.serviceWorker.register(e,{scope:t});(r||a||o).addEventListener("statechange",(e=>{console.log("state",e.target.state)}));const s=navigator.serviceWorker;await new Promise((e=>{if(s.controller)e();else{const t=()=>{e(),s.removeEventListener("controllerchange",t),s.oncontrollerchange=null};s.addEventListener("controllerchange",t),s.oncontrollerchange=t}}));const c=s.controller,i=()=>"activated"===c.state;return await new Promise((async e=>{i()?e(c):c.onstatechange=()=>{i()&&(c.onstatechange=null,e(c))}}))}async function k({swUrl:e,scopeUrl:t,type:n}){await navigator.serviceWorker.register(e,{type:n,scope:t});const r=await async function(){return await new Promise((e=>{const t=navigator.serviceWorker;if(t.controller)e(t.controller);else{const n=()=>{e(t.controller),t.removeEventListener("controllerchange",n),t.oncontrollerchange=null};t.addEventListener("controllerchange",n),t.oncontrollerchange=n}}))}();return await async function(e){const t=()=>"activated"===e.state;await new Promise((async n=>{t()?n():e.onstatechange=()=>{t()&&(e.onstatechange=null,n())}}))}(r),r}async function O(e,{key:t,port:n}){return await U({key:t,communicationPort:n,handler:async(t,n,r)=>(m(r,e),!0)})}async function L(e,{key:t,port:n}){const r=await P({key:t,communicationPort:n});return await h(r,e)}function T({swUrl:e=new URL("./index-sw.js",import.meta.url)+"",scopeUrl:t=new URL("../",import.meta.url)+""}={}){let n;return async r=>{if("CONNECT"===r.data.type){const a=(r.ports||[])[0];if(n)return void a.close();n=a,await k({swUrl:e,scopeUrl:t});const o=E();o.onmessage=e=>{n.postMessage(e.data,e.ports)},n.onmessage=e=>{o.postMessage(e.data,e.ports)}}}}async function C({baseUrl:e=new URL("../public-relay/",import.meta.url),url:t=new URL("relay.html",e),container:n=document.body}={}){const r=new MessageChannel,{iframe:a,promise:o}=await async function(e){const t=document.createElement("iframe");return t.src=e,Object.assign(t.style,{padding:0,margin:0,border:"none",outline:"none",width:"100%",height:"100%"}),{iframe:t,promise:new Promise(((e,n)=>{try{t.onerror=n,t.onload=()=>e(t)}catch(e){n(e)}}))}}(t);return Object.assign(a.style,{position:"fixed",width:"1px",height:"1px",top:"-1000",left:"-1000",display:"block",opacity:"0",border:"none",outline:"none"}),n.appendChild(a),o.then((()=>{a.contentWindow.postMessage({type:"CONNECT"},"*",[r.port1])})),{baseUrl:e,port:r.port2,close:()=>{a.parentElement&&a.parentElement.removeChild(a),r.port1.close(),r.port2.close()}}}async function P({key:e,communicationPort:t,...r}){const a=new MessageChannel;return await n(t,"CONNECT",{key:e,...r},a.port2)?a.port1:(a.port1.close(),a.port2.close(),null)}async function U({key:e,handler:t,communicationPort:o}){const[s,c]=a();return await n(o,"REGISTER",{key:e}),s((()=>n(o,"UNREGISTER",{key:e}))),s(r(o,"CONNECT",t)),c}export{n as callChannel,L as callHttpService,t as deserializeError,y as fromReadableStream,T as getRelayWindowMessageHandler,r as handleChannelCalls,m as handleHttpRequests,i as handleStreams,O as initHttpService,k as initServiceWorker,b as initServiceWorker1,P as initializeConnection,p as newHttpClientStub,w as newHttpServerStub,u as newInvokationChannel,a as newRegistry,C as newRemoteRelayChannel,E as newServiceWorkerPort,o as recieveData,U as registerConnectionsHandler,s as sendData,h as sendHttpRequest,c as sendStream,e as serializeError,v as splitServiceUrl,d as toReadableStream};
|
package/package.json
CHANGED
package/src/http/http-stubs.js
CHANGED
|
@@ -33,14 +33,18 @@ export function newHttpClientStub(send) {
|
|
|
33
33
|
"referrer",
|
|
34
34
|
"referrerPolicy",
|
|
35
35
|
"integrity",
|
|
36
|
-
"keepalive"
|
|
36
|
+
"keepalive"
|
|
37
37
|
];
|
|
38
|
-
|
|
38
|
+
const headers = [...request.headers].map(([key, value]) => {
|
|
39
|
+
return [key, value]
|
|
40
|
+
});
|
|
39
41
|
const requestOptions = fields.reduce((options, key) => {
|
|
40
42
|
const val = request[key];
|
|
41
43
|
if (val !== undefined) options[key] = val;
|
|
42
44
|
return options;
|
|
43
|
-
}, {
|
|
45
|
+
}, {
|
|
46
|
+
headers
|
|
47
|
+
});
|
|
44
48
|
const requestContent = (request.body)
|
|
45
49
|
? fromReadableStream(request.body)
|
|
46
50
|
: [];
|
|
@@ -93,7 +97,11 @@ export function newHttpServerStub(handler) {
|
|
|
93
97
|
content: requestContent,
|
|
94
98
|
} = await params;
|
|
95
99
|
let requestBody = undefined;
|
|
96
|
-
const { url, mode } = requestOptions;
|
|
100
|
+
const { url, mode, headers = [] } = requestOptions;
|
|
101
|
+
const requestHeaders = new Headers()
|
|
102
|
+
for (let [key, value] of headers) {
|
|
103
|
+
requestHeaders.append(key, value);
|
|
104
|
+
}
|
|
97
105
|
delete requestOptions.mode;
|
|
98
106
|
delete requestOptions.url;
|
|
99
107
|
if (
|
|
@@ -108,6 +116,7 @@ export function newHttpServerStub(handler) {
|
|
|
108
116
|
}
|
|
109
117
|
const request = new Request(url, {
|
|
110
118
|
...requestOptions,
|
|
119
|
+
headers: requestHeaders,
|
|
111
120
|
// duplex: 'full',
|
|
112
121
|
body: requestBody,
|
|
113
122
|
});
|
package/src/relay/index.js
CHANGED
|
@@ -189,9 +189,10 @@ export async function newRemoteRelayChannel({
|
|
|
189
189
|
);
|
|
190
190
|
});
|
|
191
191
|
return {
|
|
192
|
+
baseUrl,
|
|
192
193
|
port: messageChannel.port2,
|
|
193
194
|
close: () => {
|
|
194
|
-
|
|
195
|
+
iframe.parentElement && iframe.parentElement.removeChild(iframe);
|
|
195
196
|
messageChannel.port1.close();
|
|
196
197
|
messageChannel.port2.close();
|
|
197
198
|
},
|