master
Avril 4 years ago
parent 86cff91d9d
commit 33ebd7f4e1
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -0,0 +1 @@
avril@flan-laptop.2546:1595960333

@ -0,0 +1,2 @@
var MessageQueue=function(){"use strict";var t=function(t,s){return t(s={exports:{}},s.exports),s.exports}((function(t){t&&(t.exports=function(t){var s=this;this.array=t||[],this.over=!1,this.acceptInvalid=!1;var e={waiters:[],wait:function(){return new Promise(t=>e.waiters.push((function(){t()})))},signal:function(){e.waiters.length>0&&e.waiters.shift()()},flush:function(){for(;e.waiters.length>0;)e.waiters.shift()()}};this.take=async function(){if(!(s.over&&s.array.length<=0||(s.array.length<=0&&await e.wait(),s.over&&s.array.length<=0)))return s.array.shift()},this.poll=function(){return s.array},this.takeNB=function(){return s.array.length<=0?null:s.array.shift()},this.swallow0=async function(){for(var t,e=[];t=await s.take();)e.push(t);return e},this.swallow=function(t){return t?new Promise((function(e,o){var n=!0;s.swallow0().then((function(t){n&&e(t),n=!1})),t>0&&setTimeout(()=>{return s=new Error("swallow timeout reached ("+t+")"),n&&o(s),void(n=!1);var s},t)})):s.swallow0()},this.giveMany=function(t){for(let e of t)s.give(e)},this.give=function(t){(t||s.acceptInvalid)&&(s.array.push(t),e.signal())},this.commit=function(){return s.over=!0,e.flush(),s}})}));function s(){this.hooks=[]}s.prototype.hook=function(t){return this.hooks.push(t),this.hooks.length-1},s.prototype.unhook=function(t){this.hooks[t]=null},s.prototype.signal=function(t){for(const s of this.hooks)s&&s.apply(this,[t])},s.prototype.clear=function(){this.hooks=[]};const e=(t,s,e)=>(t.addEventListener(s,e),e);s.socket=(t,s)=>o(t);const o=o=>{const n=new s,i=new t;let r=!1;n.socket=o;const a=e(o,"message",t=>i.give(t.data)),c=e(o,"close",()=>i.commit());return(async()=>{let t;for(;void 0!==(t=await i.take());)n.signal({op:"message",value:t});n.signal({op:"close"})})(),n.close=t=>{r||(o.removeEventListener("message",a),o.removeEventListener("close",c),i.commit(),t&&o.close(),r=!0)},n.send=t=>{r||o.send(t)},n},n=t=>{const e=new s;let o=!1;e.socket=t.socket;const n=t.hook(t=>e.signal(t));e.close=s=>{o||(t.unhook(n),s&&t.close&&t.close(!0),o=!0)},e.send=s=>{o||t.socket.send(s)}};function i(e,r,a,c){this.socket=e instanceof s?n(e):e instanceof i?(t=>n(t.socket))(e):o(e),this.filter=r||(()=>!0),this.apply=a||(t=>t),this.map=c||(t=>t),this.premap=t=>t;const h=this.stage=new t,l=this;this.hook=this.socket.hook(t=>{if(t)switch(t.op){case"close":l.close();break;case"message":t=this.premap(t.value),this.filter(t)&&h.give(this.map(t))}})}i.JSON=(...t)=>{const s=new i(...t);return s.premap=t=>{try{return JSON.parse(t)}catch(t){return null}},s.apply=t=>JSON.stringify(s.apply(t)),s};const r=i.prototype;return r.clone=function(t,s,e){const o=new i(this.socket.socket,t||this.filter,s||this.apply,e||this.map);return o.premap=this.premap,o.on_close=this.on_close,o},r.close=function(t){this.on_close&&(this.on_close(this,t),this.on_close=null),this.socket.unhook(this.hook),this.stage.commit(),this.socket.close(t)},r.send=async function(t){for(;;){const s=this.stage.take();this.socket.send(this.apply(t));const e=await s;return e}},r.send0=function(t){this.socket.send(this.apply(t))},r.read=async function(){for(;;){const t=await this.stage.take();return t}},r.oneshot=async function(t){const s=await this.send(t);return this.close(),s},i}();
//# sourceMappingURL=message-min.js.map

File diff suppressed because one or more lines are too long

@ -0,0 +1,24 @@
const sock = new WebSocket("ws://localhost:7777");
sock.addEventListener('open', () => {
(async ()=> {
const mw = new MessageQueue(sock);
let msg = await mw.read();
console.log(`=> ${msg}`);
let next = await mw.send("uwu");
console.log(`now => ${next}`);
mw.close();
await (async () => {
const mw = new MessageQueue(sock);
let msg = await mw.send("OWO");
console.log(`other ${msg}`);
mw.close(true);
})();
})();
});

@ -0,0 +1,25 @@
function Dispatcher() {
this.hooks = [];
}
Dispatcher.prototype.hook = function(cb) {
this.hooks.push(cb);
return this.hooks.length-1;
};
Dispatcher.prototype.unhook = function(index) {
this.hooks[index] = null;
};
Dispatcher.prototype.signal = function(value) {
for(const cb of this.hooks) {
if(cb) cb.apply(this, [value]);
}
};
Dispatcher.prototype.clear = function() {
this.hooks = [];
};
export default Dispatcher;

@ -0,0 +1,6 @@
<html>
<head>
<script src='./build/message-min.js'></script>
<script src='./build/test.js'></script>
</head>
</html>

@ -0,0 +1,73 @@
const MessageQueue = require("./message");
const util = require("./util");
const addEventListenerHack = util.addEventListenerHack;
const uuidv4 = util.uuidv4;
const is_uuid = util.is_uuid;
/**
*
*/
function Pipe(ws) {
this.socket = ws;
this.clients=0;
this.MAX_CLIENTS = 100;
}
const P = Pipe.prototype;
P.connect = async function(message) {
let msg;
const socket = new MessageQueue(this.socket);
try {
while ((msg = await socket.read()) !== undefined) { // Expects {com: 'open', id: uuidv4()}
try {
msg = JSON.parse(msg);
} catch(_) {continue;}
if (msg?.com === 'open' && (!message || msg?.msg === message)) {
let id = validate_id(msg?.id);
if(id) {
if(this.clients < this.MAX_CLIENTS) {
const cli = new MessageQueue(this.socket);
let open = true;
cli.premap = (raw) => {
try {
return JSON.parse(raw);
}catch(_) {return null;}
};
cli.filter = (json) => json?.id === id && (json?.com === 'msg' || ((json?.com === 'close') && cli.close() && false));
cli.map = (json) => json?.message;
cli.apply = (raw) => {
const json = {message: raw, id: id, com: 'resp'};
return JSON.stringify(json);
};
cli.on_close = (self)=> {
if(open && self.id === id) { //in case of mistaken cloning
self.send0({com: 'resp', message: 'closing', id: id});
this.clients -= 1;
open = false;
}
};
cli.id= id;
this.clients -=1;
socket.send0(JSON.stringify({com: 'resp', message: 'accepted', id: id}));
return cli;
} else {
socket.send0(JSON.stringify({com: 'resp', message: 'declined', id: id, reason: 'too many open connections'}));
}
}
}
}
} finally {
socket.close();
}
return undefined;
};
P.close = function() {
this.socket.close();
};
exports = Pipe;

@ -1,32 +1,8 @@
const Stage = require('stage-js');
import Stage from "@notflan/stage-js";
import Dispatcher from "./dispatcher";
import {addEventListenerHack} from "./util";
function Dispatcher() {
this.hooks = [];
}
Dispatcher.prototype.hook = function(cb) {
this.hooks.push(cb);
return this.hooks.length-1;
};
Dispatcher.prototype.unhook = function(index) {
this.hooks[index] = null;
};
Dispatcher.prototype.signal = function(value) {
for(const cb of this.hooks) {
if(cb) cb.apply(this, [value]);
}
};
Dispatcher.prototype.clear = function() {
this.hooks = [];
};
const addEventListenerHack = (to, ev, lam) => {
to.addEventListener(ev, lam);
return lam;
};
Dispatcher.socket = (sock,cloned) => socket_dispatcher(sock,cloned);
const socket_dispatcher = (ws) => {
const disp = new Dispatcher();
@ -35,20 +11,26 @@ const socket_dispatcher = (ws) => {
disp.socket = ws;
const h0 = ws.addEventListener('message', (ev) => pusher.give(ev.data));
const h1 = ws.addEventListener('close', () => pusher.commit());
const h0 = addEventListenerHack(ws, 'message', (ev) => pusher.give(ev.data));
const h1 = addEventListenerHack(ws, 'close', () => pusher.commit());
(async () => {
while ( (msg = await pusher.take()) !== undefined)
let msg;
while ( (msg = await pusher.take()) !== undefined)
disp.signal({op: 'message', value: msg});
disp.signal({op: 'close'});
})();
disp.close = () => {
disp.close = (consume) => {
if(!closed) {
ws.removeEventListener('message', h0);
ws.removeEventListener('close', h1);
pusher.commit();
if(consume)
ws.close();
closed=true;
}
};
@ -62,10 +44,38 @@ const socket_dispatcher = (ws) => {
return disp;
};
function MessageQueue(ws, filter, apply) {
this.socket = socket_dispatcher(ws);
this.filter = filter || (()=>true);
this.apply = apply || ((o) => o);
const message_dispatcher = (ws) => {
return dispatcher_dispatcher(ws.socket);
};
const dispatcher_dispatcher = (ws) => {
const disp = new Dispatcher();
let closed=false;
disp.socket = ws.socket;
const hook = ws.hook((sig) => disp.signal(sig));//just pass it
disp.close = (consume) => {
if(!closed){
ws.unhook(hook);
if(consume && ws.close)
ws.close(true);
closed=true;
}
};
disp.send = (msg) => {
if(!closed) ws.socket.send(msg);
};
};
function MessageQueue(ws, filter, apply, map) {
this.socket = (ws instanceof Dispatcher) ? dispatcher_dispatcher(ws) : (ws instanceof MessageQueue) ? message_dispatcher(ws) : socket_dispatcher(ws);
this.filter = filter || (()=>true); // Filter incoming messages. Return true to keep, false to ignore.
this.apply = apply || ((o) => o); // Apply this function to outgoing messages.
this.map = map || ((o) => o); // Apply this function to incoming messages after `filter`
this.premap = ((o) => o); // Apply this function to incoming messages before `filter`
const stage = this.stage = new Stage();
const base = this;
@ -79,7 +89,9 @@ function MessageQueue(ws, filter, apply) {
base.close();
break;
case 'message':
stage.give(msg.value);
msg = this.premap(msg.value);
if(this.filter(msg))
stage.give(this.map(msg));
break;
default:
//uhh
@ -88,29 +100,65 @@ function MessageQueue(ws, filter, apply) {
}
});
}
MessageQueue.JSON = (...vars) => {
const q = new MessageQueue(...vars);
q.premap = x=> {
try {
return JSON.parse(x);
} catch(_) {
return null;
}
};
q.apply = x=> JSON.stringify(q.apply(x));
return q;
};
const MQ = MessageQueue.prototype;
MQ.close = () => {
MQ.clone = function(filter, apply, map) {
const mq = new MessageQueue(this.socket.socket, filter || this.filter, apply || this.apply, map || this.map);
mq.premap = this.premap;
mq.on_close = this.on_close;
return mq;
};
MQ.close = function(consume) {
if (this.on_close) {this.on_close(this, consume); this.on_close = null;}
this.socket.unhook(this.hook);
this.stage.commit();
this.socket.close();
this.socket.close(consume);
};
MQ.send = async (value) => {
const awaiter = this.stage.take();
MQ.send = async function(value) {
while(true) {
const awaiter = this.stage.take();
this.socket.send(this.apply(value));
const ret = await awaiter;
if(ret === undefined) return ret;
else return ret;
}
};
MQ.send0 = function(value) {
this.socket.send(this.apply(value));
const ret = await awaiter;
};
MQ.read = () => this.stage.take();
MQ.read = async function() {
while(true) {
const ret = await this.stage.take();
MQ.oneshot = async (value) => {
if(ret === undefined) return ret;
else return ret;
}
};
MQ.oneshot = async function(value) {
const ret = await this.send(value);
this.close();
return ret;
};
if(module)
module.exports = MessageQueue;
export default MessageQueue;

331
package-lock.json generated

@ -4,10 +4,341 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@babel/code-frame": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
"integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
"dev": true,
"requires": {
"@babel/highlight": "^7.10.4"
}
},
"@babel/helper-validator-identifier": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
"integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
"dev": true
},
"@babel/highlight": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
"integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.10.4",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
},
"@notflan/stage-js": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@notflan/stage-js/-/stage-js-0.1.0.tgz",
"integrity": "sha512-oEkEgLBPB4ghtV1XE6j6gWoX6C3x8BcBjLCpdXTADTKU8q7qAJeM3tP7/fFgrVst5CXR9RtOcXri/kAltuek5g=="
},
"@types/estree": {
"version": "0.0.45",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz",
"integrity": "sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==",
"dev": true
},
"@types/node": {
"version": "14.0.26",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.26.tgz",
"integrity": "sha512-W+fpe5s91FBGE0pEa0lnqGLL4USgpLgs4nokw16SrBBco/gQxuua7KnArSEOd5iaMqbbSHV10vUDkJYJJqpXKA==",
"dev": true
},
"@types/resolve": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
"integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
"builtin-modules": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
"integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==",
"dev": true
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
},
"estree-walker": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
"dev": true
},
"fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"is-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
"dev": true
},
"is-reference": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
"dev": true,
"requires": {
"@types/estree": "*"
}
},
"jest-worker": {
"version": "26.1.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.1.0.tgz",
"integrity": "sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ==",
"dev": true,
"requires": {
"merge-stream": "^2.0.0",
"supports-color": "^7.0.0"
},
"dependencies": {
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"magic-string": {
"version": "0.25.7",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
"dev": true,
"requires": {
"sourcemap-codec": "^1.4.4"
}
},
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"dev": true
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"requires": {
"safe-buffer": "^5.1.0"
}
},
"resolve": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
"integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
"dev": true,
"requires": {
"path-parse": "^1.0.6"
}
},
"rollup": {
"version": "2.23.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.23.0.tgz",
"integrity": "sha512-vLNmZFUGVwrnqNAJ/BvuLk1MtWzu4IuoqsH9UWK5AIdO3rt8/CSiJNvPvCIvfzrbNsqKbNzPAG1V2O4eTe2XZg==",
"dev": true,
"requires": {
"fsevents": "~2.1.2"
}
},
"rollup-plugin-commonjs": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz",
"integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==",
"dev": true,
"requires": {
"estree-walker": "^0.6.1",
"is-reference": "^1.1.2",
"magic-string": "^0.25.2",
"resolve": "^1.11.0",
"rollup-pluginutils": "^2.8.1"
}
},
"rollup-plugin-node-resolve": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz",
"integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==",
"dev": true,
"requires": {
"@types/resolve": "0.0.8",
"builtin-modules": "^3.1.0",
"is-module": "^1.0.0",
"resolve": "^1.11.1",
"rollup-pluginutils": "^2.8.1"
}
},
"rollup-plugin-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-6.1.0.tgz",
"integrity": "sha512-4fB3M9nuoWxrwm39habpd4hvrbrde2W2GG4zEGPQg1YITNkM3Tqur5jSuXlWNzbv/2aMLJ+dZJaySc3GCD8oDw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.8.3",
"jest-worker": "^26.0.0",
"serialize-javascript": "^3.0.0",
"terser": "^4.7.0"
}
},
"rollup-pluginutils": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
"dev": true,
"requires": {
"estree-walker": "^0.6.1"
}
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true
},
"serialize-javascript": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
"integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"sourcemap-codec": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
},
"terser": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
"integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
"dev": true,
"requires": {
"commander": "^2.20.0",
"source-map": "~0.6.1",
"source-map-support": "~0.5.12"
}
},
"ws": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==",
"dev": true
}
}
}

@ -2,9 +2,11 @@
"name": "@username/message-queue",
"version": "0.0.0",
"description": "Await on websocket messages",
"private": true,
"entry": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "rollup -c -w",
"build": "rollup -c"
},
"keywords": [
"async"
@ -14,5 +16,11 @@
"dependencies": {
"@notflan/stage-js": "^0.1.0"
},
"devDependencies": {}
"devDependencies": {
"rollup": "^2.23.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-terser": "^6.1.0",
"ws": "^7.3.1"
}
}

@ -0,0 +1,62 @@
import MessageQueue from "./message.js";
import {addEventListenerHack, uuidv4, is_uuid} from "./util";
function Pipe(ws)
{
this.socket =ws;
this.id = uuidv4();
}
const P = Pipe.prototype;
P.connect = async function(message) {
const socket = new MessageQueue(this.socket);
socket.send0(JSON.stringify({com: 'open', id: this.id, msg: message}));
try {
let msg;
while ((msg = await socket.read()) !== undefined) {
try {
msg = JSON.parse(msg);
} catch(_){continue;}
if (msg.id === id && msg.com === 'resp') {
if (msg.message === 'accepted') {
const cli = new MessageQueue(this.socket);
let open=true;
cli.id = id;
cli.apply = (raw) => {
return JSON.stringify({message: raw, com: 'msg', id: id});
};
cli.premap = (raw) => {
try {
return JSON.parse(raw);
}catch(_) {return null;}
};
cli.filter = (json) => json?.id === 'id' && (json?.com === 'msg' || json?.com === 'resp' && json?.message === 'closing' && cli.close() && false);
cli.map = (json) => json?.message;
cli.on_close = (self) => {
if(open && self.id === id) { //in case of mistaken cloning
self.send0({com: 'close', message: 'closing', id: id});
open = false;
}
};
return cli;
} else {
console.log(`[${id}]: server responded with ${msg.message}: ${msg.reason}`);
return false;
}
}
}
} finally{
socket.close();
}
return undefined;
};
P.close = function() {
this.socket.close();
};
export default Pipe;

@ -0,0 +1,16 @@
import commonjs from "rollup-plugin-commonjs";
import resolve from "rollup-plugin-node-resolve";
import {terser} from "rollup-plugin-terser";
export default {
input: "message.js",
output: {
sourcemap: true,
format: "iife",
name: "MessageQueue",
file: "build/message-min.js",
},
plugins: [
resolve({browser:true}), commonjs(),terser(),
],
};

@ -0,0 +1,15 @@
const WebSocket = require('ws');
const wss = new WebSocket.Server({port: 7777});
wss.on('connection', ws => {
console.log(`conn ${ws}`);
ws.on('message', message => {
console.log(`got ${message}`);
ws.send(`Hello ${message}`);
});
ws.send("Start");
ws.on('close', () => {
console.log("closed");
});
});

@ -0,0 +1,21 @@
function uuidv4() {
if (crypto) {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
}
else return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toStirng(16);
});
}
const UUID_RE = /^(\w{8}(-\w{4}){3}-\w{12}?)$/i;
function is_uuid(id) {
return (typeof id === 'string' || id instanceof String) && UUID_RE.test(id);
}
const addEventListenerHack = (to, ev, lam) => {
to.addEventListener(ev, lam);
return lam;
};
export {addEventListenerHack, uuidv4, is_uuid};
Loading…
Cancel
Save