Comparing version 1.0.0 to 1.0.2
@@ -56,6 +56,7 @@ { | ||
"brace-style": [ | ||
2, | ||
"error", | ||
"allman" | ||
] | ||
], | ||
"indent": [2, 4, {"VariableDeclarator": 0}] | ||
} | ||
} |
@@ -0,1 +1,15 @@ | ||
## [1.0.2](https://github.com/TopGunBuild/topgun/compare/v1.0.1...v1.0.2) (2023-04-13) | ||
### Bug Fixes | ||
* **client:** return graph key in put callback ([f68a810](https://github.com/TopGunBuild/topgun/commit/f68a8109c4f97443d686031581ea8f71d12eea9e)) | ||
## [1.0.1](https://github.com/TopGunBuild/topgun/compare/v1.0.0...v1.0.1) (2023-04-13) | ||
### Bug Fixes | ||
* using topgun-webcrypto instead of @peculiar/webcrypto for isomorphic support ([b2444e3](https://github.com/TopGunBuild/topgun/commit/b2444e38e4df8f6e7e1c1de8aa89962991976bce)) | ||
# 1.0.0 (2023-04-13) | ||
@@ -2,0 +16,0 @@ |
@@ -10,2 +10,5 @@ import { T as TGMessage, a as TGGraphData, b as TGPut, c as TGGet, d as TGMiddleware, e as TGMiddlewareType, f as TGOnCb, g as TGValue, h as TGMessageCb, i as TGOptionsPut, j as TGOptionsGet, k as TGChainOptions, l as TGSupportedStorage, m as TGUserReference, n as TGAuthCallback, o as TGUserCredentials, L as LEX, p as TGNode, q as TGGraphAdapter } from './common-ff4232f2.js'; | ||
private _listeners; | ||
/** | ||
* Constructor | ||
*/ | ||
constructor(name?: string); | ||
@@ -40,2 +43,5 @@ /** | ||
private _queue; | ||
/** | ||
* Constructor | ||
*/ | ||
constructor(name?: string); | ||
@@ -52,2 +58,5 @@ count(): number; | ||
private readonly _middlewareFunctions; | ||
/** | ||
* Constructor | ||
*/ | ||
constructor(name?: string); | ||
@@ -83,2 +92,5 @@ /** | ||
protected alreadyProcessed: T[]; | ||
/** | ||
* Constructor | ||
*/ | ||
constructor(name?: string, processDupes?: TGProcessDupesOption); | ||
@@ -101,3 +113,6 @@ has(item: T): boolean; | ||
protected readonly outputQueue: TGProcessQueue<TGMessage>; | ||
constructor(name?: string); | ||
/** | ||
* Constructor | ||
*/ | ||
protected constructor(name?: string); | ||
connectToGraph(graph: TGGraph): TGGraphConnector; | ||
@@ -132,3 +147,3 @@ off(_msgId: string): TGGraphConnector; | ||
ingest(msgs: readonly TGMessage[]): TGGraphConnector; | ||
private __onConnectedChange; | ||
private _onConnectedChange; | ||
} | ||
@@ -165,6 +180,2 @@ | ||
* Configure graph options | ||
* | ||
* Currently unused | ||
* | ||
* @param options | ||
*/ | ||
@@ -188,3 +199,3 @@ opt(options: TGGraphOptions): TGGraph; | ||
* @param middleware The middleware function to add | ||
* @param kind Optionaly register write middleware instead of read by passing "write" | ||
* @param kind optionally register write middleware instead of read by passing "write" | ||
*/ | ||
@@ -196,3 +207,3 @@ use(middleware: TGMiddleware, kind?: TGMiddlewareType): TGGraph; | ||
* @param middleware The middleware function to remove | ||
* @param kind Optionaly unregister write middleware instead of read by passing "write" | ||
* @param kind optionally unregister write middleware instead of read by passing "write" | ||
*/ | ||
@@ -217,3 +228,2 @@ unuse(middleware: TGMiddleware, kind?: TGMiddlewareType): TGGraph; | ||
* @param putOpt | ||
* @returns a promise | ||
*/ | ||
@@ -280,4 +290,2 @@ putPath(fullPath: string[], data: TGValue, cb?: TGMessageCb, uuidFn?: (path: readonly string[]) => Promise<string> | string, getPub?: string, putOpt?: TGOptionsPut): Promise<void>; | ||
* Graph from the current chain link | ||
* | ||
* @returns {TGGraph} | ||
*/ | ||
@@ -306,63 +314,18 @@ getGraph(): TGGraph; | ||
/** | ||
* Save data into topGun, syncing it with your connected peers. | ||
* | ||
* @param {TGValue} value | ||
* @param {TGMessageCb} cb | ||
* @param {TGOptionsPut} opt | ||
* @returns {Link} | ||
*/ | ||
* You do not need to re-save the entire object every time, topGun will automatically | ||
* merge your data into what already exists as a "partial" update. | ||
* | ||
* @param value the data to save | ||
* @param cb an optional callback, invoked on each acknowledgment | ||
* @param opt options put | ||
* @returns same chain context | ||
**/ | ||
put(value: TGValue, cb?: TGMessageCb, opt?: TGOptionsPut): TGLink; | ||
/** | ||
* Add a unique item to an unordered list. | ||
* | ||
* Works like a mathematical set, where each item in the list is unique. | ||
* If the item is added twice, it will be merged. | ||
* This means only objects, for now, are supported. | ||
* | ||
* @param data should be a topGun reference or an object | ||
* @param cb The callback is invoked exactly the same as .put | ||
* @param {TGOptionsPut} opt | ||
* @returns chain context for added object | ||
*/ | ||
set(data: any, cb?: TGMessageCb, opt?: TGOptionsPut): TGLink; | ||
/** | ||
* Register a callback for when it appears a record does not exist | ||
* | ||
* If you need to know whether a property or key exists, you can check with .not. | ||
* It will consult the connected peers and invoke the callback if there's reasonable certainty that none of them have the data available. | ||
* | ||
* @param cb If there's reason to believe the data doesn't exist, the callback will be invoked. This can be used as a check to prevent implicitly writing data | ||
* @returns same chain context | ||
*/ | ||
not(cb: (key: string) => void): TGLink; | ||
/** | ||
* Change the configuration of this chain link | ||
* | ||
* @param options | ||
* @returns current options | ||
*/ | ||
opt(options?: TGChainOptions): TGChainOptions; | ||
/** | ||
* Get the current data without subscribing to updates. Or undefined if it cannot be found. | ||
* | ||
* @param cb The data is the value for that chain at that given point in time. And the key is the last property name or ID of the node. | ||
* @returns same chain context | ||
*/ | ||
once(cb: TGOnCb): TGLink; | ||
/** | ||
* Subscribe to updates and changes on a node or property in realtime. | ||
* | ||
* Triggered once initially and whenever the property or node you're focused on changes, | ||
* Since topGun streams data, the callback will probably be called multiple times as new chunk comes in. | ||
* | ||
* To remove a listener call .off() on the same property or node. | ||
* | ||
* @param cb The callback is immediately fired with the data as it is at that point in time. | ||
* @returns same chain context | ||
*/ | ||
on(cb: TGOnCb): TGLink; | ||
/** | ||
* Unsubscribe one or all listeners subscribed with on | ||
* | ||
* @returns same chain context | ||
*/ | ||
off(cb?: TGOnCb): TGLink; | ||
@@ -373,10 +336,2 @@ promise(opts?: { | ||
then(fn?: (val: TGValue) => any): Promise<any>; | ||
/** | ||
* Iterates over each property and item on a node, passing it down the chain | ||
* | ||
* Behaves like a forEach on your data. | ||
* It also subscribes to every item as well and listens for newly inserted items. | ||
* | ||
* @returns a new chain context holding many chains simultaneously. | ||
*/ | ||
map(): TGLink; | ||
@@ -494,8 +449,3 @@ protected _onQueryResponse(value?: TGValue): void; | ||
/** | ||
* Main entry point for TopGun | ||
* | ||
* Usage: | ||
* | ||
* const topGun = new TopGun.Client({ peers: ["https://top-gun.io/topgun"]}) | ||
* topGun.get("topgun/things/f8c3de3d-1fea-4d7c-a8b0-29f63c4c3454").on(thing => console.log(thing)) | ||
* Main entry point for TopGun in browser | ||
*/ | ||
@@ -539,3 +489,3 @@ declare class TGClient { | ||
/** | ||
* Connect to peers via connector SocketClusterConnector | ||
* Connect to peers via connector TopGunSocket | ||
*/ | ||
@@ -547,2 +497,5 @@ private handlePeers; | ||
private readonly _callbacks; | ||
/** | ||
* Constructor | ||
*/ | ||
constructor(name?: string); | ||
@@ -549,0 +502,0 @@ off(msgId: string): TGGraphWireConnector; |
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunkIRXYP7GMjs = require('./chunk-IRXYP7GM.js');var x=class{constructor(e,t,r){this._onDirectQueryReply=this._onDirectQueryReply.bind(this),this._data=new (0, _chunkIRXYP7GMjs.g)(`<GraphNode ${t}>`),this._graph=e,this._updateGraph=r,this.soul=t}listenerCount(){return this._data.listenerCount()}get(e){return e&&this.on(e),this._ask(),this}receive(e){return this._data.trigger(e,this.soul),this}on(e){return this._data.on(e),this}off(e){return e?this._data.off(e):this._data.reset(),this._endCurQuery&&!this._data.listenerCount()&&(this._endCurQuery(),this._endCurQuery=void 0),this}_ask(){return this._endCurQuery?this:(this._endCurQuery=this._graph.get(this.soul,this._onDirectQueryReply),this)}_onDirectQueryReply(e){e.put||this._updateGraph({[this.soul]:void 0},e["@"])}};function te(n){return typeof n=="boolean"}function q(n){return _chunkIRXYP7GMjs.a.call(void 0, n)||_chunkIRXYP7GMjs.i.call(void 0, n)||te(n)||_chunkIRXYP7GMjs.m.call(void 0, n)&&n!==1/0&&n!==-1/0&&!Number.isNaN(n)||n===null}function re(n,e){return n&&(e=n.constructor)&&e.name||typeof n}function R(n,e){return n.reverse().reduce((t,r)=>({[r]:t}),e)}function Q(n,e=[],t={}){if(q(n))_chunkIRXYP7GMjs.a.call(void 0, n)||(n=R(e,n));else throw Error("Invalid data: "+re(n)+" at "+e.join("."));let r=e.join("/");e.length>0&&!_chunkIRXYP7GMjs.a.call(void 0, t[r])&&(t[r]={});for(let i in n){if(!n.hasOwnProperty(i))continue;let s=n[i],o=[...e,i],a=o.join("/");if(!q(s)){console.log("Invalid data: "+re(s)+" at "+o.join("."));continue}_chunkIRXYP7GMjs.a.call(void 0, s)?(t[r][i]={"#":a},Q(s,o,t)):t[r][i]=s}return t}var g=class{constructor(){this.id=_chunkIRXYP7GMjs.u.call(void 0, ),this.receiveGraphData=this.receiveGraphData.bind(this),this.__onConnectorStatus=this.__onConnectorStatus.bind(this),this.activeConnectors=0,this.events={get:new (0, _chunkIRXYP7GMjs.g)("request soul"),graphData:new (0, _chunkIRXYP7GMjs.g)("graph data"),off:new (0, _chunkIRXYP7GMjs.g)("off event"),put:new (0, _chunkIRXYP7GMjs.g)("put data")},this._opt={},this._graph={},this._nodes={},this._connectors=[],this._readMiddleware=[],this._writeMiddleware=[]}opt(e){return this._opt={...this._opt,...e},this}connect(e){return this._connectors.indexOf(e)!==-1?this:(this._connectors.push(e.connectToGraph(this)),e.events.connection.on(this.__onConnectorStatus),e.events.graphData.on(this.receiveGraphData),e.isConnected&&this.activeConnectors++,this)}disconnect(e){let t=this._connectors.indexOf(e);return e.events.graphData.off(this.receiveGraphData),e.events.connection.off(this.__onConnectorStatus),t!==-1&&this._connectors.splice(t,1),e.isConnected&&this.activeConnectors--,this}use(e,t="read"){return t==="read"?this._readMiddleware.push(e):t==="write"&&this._writeMiddleware.push(e),this}unuse(e,t="read"){if(t==="read"){let r=this._readMiddleware.indexOf(e);r!==-1&&this._readMiddleware.splice(r,1)}else if(t==="write"){let r=this._writeMiddleware.indexOf(e);r!==-1&&this._writeMiddleware.splice(r,1)}return this}query(e,t){let r=[],i,s=()=>{let{souls:o,value:a,complete:d}=_chunkIRXYP7GMjs.x.call(void 0, e,this._graph),[c,G]=_chunkIRXYP7GMjs.v.call(void 0, r,o);(d&&!_chunkIRXYP7GMjs.h.call(void 0, i)||_chunkIRXYP7GMjs.h.call(void 0, a)&&a!==i)&&(i=a,t(a,e[e.length-1]));for(let I of c)this._requestSoul(I,s);for(let I of G)this._unlistenSoul(I,s);r=o};return s(),()=>{for(let o of r)this._unlistenSoul(o,s)}}async putPath(e,t,r,i,s,o){if(!e.length){let G=new Error("No path specified");throw r&&r({"#":void 0,"@":"",err:G,ok:!1}),G}let a=e.shift(),d=R(e,t),c=Q(d,[a]);this.put(c,e,r,void 0,a,o)}get(e,t,r){let i=r||_chunkIRXYP7GMjs.u.call(void 0, );return this.events.get.trigger({cb:t,msgId:i,soul:e}),()=>this.events.off.trigger(i)}put(e,t,r,i,s,o){let a=_chunkIRXYP7GMjs.w.call(void 0, _chunkIRXYP7GMjs.c.call(void 0, e)),d=i||_chunkIRXYP7GMjs.u.call(void 0, );return(async()=>{for(let c of this._writeMiddleware){if(!a)return;a=await c(a,this._graph,o,t)}a&&(await this.receiveGraphData(a),this.events.put.trigger({cb:r,graph:a,msgId:d}),r&&r({"#":void 0,"@":i,err:null,ok:!0}))})(),()=>this.events.off.trigger(d)}connectorCount(){return this._connectors.length}eachConnector(e){for(let t of this._connectors)e(t);return this}async receiveGraphData(e,t,r){let i=e;for(let s of this._readMiddleware){if(!i)return;i=await s(i,this._graph)}if(i){for(let s in i)s&&this._node(s).receive(this._graph[s]=_chunkIRXYP7GMjs.e.call(void 0, this._graph[s],i[s],this._opt.mutable?"mutable":"immutable"));this.events.graphData.trigger(i,t,r)}}_node(e){return this._nodes[e]=this._nodes[e]||new x(this,e,this.receiveGraphData)}_requestSoul(e,t){return this._node(e).get(t),this}_unlistenSoul(e,t){let r=this._nodes[e];return r?(r.off(t),r.listenerCount()<=0&&(r.off(),this._forgetSoul(e)),this):this}_forgetSoul(e){let t=this._nodes[e];return t&&(t.off(),delete this._nodes[e]),this}__onConnectorStatus(e){e?this.activeConnectors++:this.activeConnectors--}};var _=class{constructor(e="Queue"){this.name=e,this._queue=[]}count(){return this._queue.length}has(e){return this._queue.indexOf(e)!==-1}enqueue(e){return this.has(e)?this:(this._queue.splice(0,0,e),this)}dequeue(){return this._queue.pop()}enqueueMany(e){let t=e.filter(r=>!this.has(r));return t.length&&this._queue.splice(0,0,...t.slice().reverse()),this}};var S=class{constructor(e="MiddlewareSystem"){this.name=e,this._middlewareFunctions=[]}use(e){return this._middlewareFunctions.indexOf(e)!==-1?this:(this._middlewareFunctions.push(e),this)}unuse(e){let t=this._middlewareFunctions.indexOf(e);return t!==-1&&this._middlewareFunctions.splice(t,1),this}async process(e,t,r){let i=e;for(let s of this._middlewareFunctions){if(!i)return;i=await s(i,t,r)}return i}};var m=class extends _{constructor(t="ProcessQueue",r="process_dupes"){super(t);this.alreadyProcessed=[],this.isProcessing=!1,this.processDupes=r,this.completed=new (0, _chunkIRXYP7GMjs.g)(`${t}.processed`),this.emptied=new (0, _chunkIRXYP7GMjs.g)(`${t}.emptied`),this.middleware=new S(`${t}.middleware`)}has(t){return super.has(t)||this.alreadyProcessed.indexOf(t)!==-1}async processNext(t,r){let i=this.dequeue(),s=i;i&&(i=await this.middleware.process(i,t,r),s&&this.processDupes==="dont_process_dupes"&&this.alreadyProcessed.push(s),i&&this.completed.trigger(i))}enqueueMany(t){return super.enqueueMany(t),this}async process(){if(!this.isProcessing&&this.count()){for(this.isProcessing=!0;this.count();)try{await this.processNext()}catch(t){console.error("Process Queue error",t)}this.emptied.trigger(!0),this.isProcessing=!1}}};var y=class{constructor(e="GraphConnector"){this.isConnected=!1,this.name=e,this.put=this.put.bind(this),this.off=this.off.bind(this),this.inputQueue=new m(`${e}.inputQueue`),this.outputQueue=new m(`${e}.outputQueue`),this.events={connection:new (0, _chunkIRXYP7GMjs.g)(`${e}.events.connection`),graphData:new (0, _chunkIRXYP7GMjs.g)(`${e}.events.graphData`),receiveMessage:new (0, _chunkIRXYP7GMjs.g)(`${e}.events.receiveMessage`)},this.__onConnectedChange=this.__onConnectedChange.bind(this),this.events.connection.on(this.__onConnectedChange)}connectToGraph(e){return e.events.off.on(this.off),this}off(e){return this}sendPutsFromGraph(e){return e.events.put.on(this.put),this}sendRequestsFromGraph(e){return e.events.get.on(t=>{this.get(t)}),this}waitForConnection(){return this.isConnected?Promise.resolve():new Promise(e=>{let t=r=>{r&&(e(),this.events.connection.off(t))};this.events.connection.on(t)})}put(e){return()=>{}}get(e){return()=>{}}send(e){return this.outputQueue.enqueueMany(e),this.isConnected&&this.outputQueue.process(),this}ingest(e){return this.inputQueue.enqueueMany(e).process(),this}__onConnectedChange(e){e?(this.isConnected=!0,this.outputQueue.process()):this.isConnected=!1}};var f=class extends y{constructor(t="GraphWireConnector"){super(t);this._callbacks={},this._onProcessedInput=this._onProcessedInput.bind(this),this.inputQueue.completed.on(this._onProcessedInput)}off(t){return super.off(t),delete this._callbacks[t],this}put({graph:t,msgId:r="",replyTo:i="",cb:s}){if(!t)return()=>{};let o={put:t};return r&&(o["#"]=r),i&&(o["@"]=i),this.req(o,s)}get({soul:t,cb:r,msgId:i=""}){let o={get:{"#":t}};return i&&(o["#"]=i),this.req(o,r)}req(t,r){let i=t["#"]=t["#"]||_chunkIRXYP7GMjs.u.call(void 0, );return r&&(this._callbacks[i]=r),this.send([t]),()=>{this.off(i)}}_onProcessedInput(t){if(!t)return;let r=t["#"],i=t["@"];if(t.put&&this.events.graphData.trigger(t.put,r,i),i){let s=this._callbacks[i];s&&s(t)}this.events.receiveMessage.trigger(t)}};var _client2 = require('topgun-socket/client');var F=class extends f{constructor(t,r="TGWebSocketGraphConnector"){super(r);this._requestChannels={},this.opts=t,this.socket=_client2.create.call(void 0, this.opts||{}),this.onConnect(),this.onError(),this.outputQueue.completed.on(this.onOutputProcessed.bind(this))}off(t){super.off(t);let r=this._requestChannels[t];return r&&(r.unsubscribe(),delete this._requestChannels[t]),this}get({soul:t,msgId:r,cb:i,opts:s}){let o=a=>{this.ingest([a]),i&&i(a)};return r=r||_chunkIRXYP7GMjs.u.call(void 0, ),this._requestChannels[r]=this.subscribeToChannel(`topgun/nodes/${t}`,o),super.get({soul:t,msgId:r,cb:i,opts:s})}put({graph:t,msgId:r="",replyTo:i="",cb:s}){if(!t)return()=>{};if(r=r||_chunkIRXYP7GMjs.u.call(void 0, ),s){let o=a=>{this.ingest([a]),s(a),this.off(r)};return this._requestChannels[r]=this.subscribeToChannel(`topgun/@${r}`,o),super.put({graph:t,msgId:r,replyTo:i,cb:o})}else return super.put({graph:t,msgId:r,replyTo:i,cb:s})}async authenticate(t,r){await this.waitForConnection(),this.doAuth(t,r);for await(let i of this.socket.listener("connect"))this.doAuth(t,r)}publishToChannel(t,r){return this.socket.transmitPublish(t,r),this}subscribeToChannel(t,r,i){let s=this.socket.subscribe(t,i);return this.onChannelMessage(s,r),s}async doAuth(t,r){let i=this.socket.id,s=new Date().getTime(),o=`${i}/${s}`,a=await _chunkIRXYP7GMjs.q.call(void 0, o,{pub:t,priv:r},{raw:!0});return this.socket.invoke("login",{proof:a,pub:t})}async onChannelMessage(t,r){for await(let i of t)this.ingest([i]),r&&r(i)}onOutputProcessed(t){if(t&&this.socket){let r=t["@"];r?this.publishToChannel(`topgun/@${r}`,t):"get"in t?this.publishToChannel("topgun/get",t):"put"in t&&this.publishToChannel("topgun/put",t)}}async onConnect(){for await(let t of this.socket.listener("connect")){console.log(`SC client ${t.id} is connected.`);try{this.events.connection.trigger(!0)}catch(r){console.error(r)}}}async onError(){for await(let t of this.socket.listener("error"))console.error("Socket Connection Error",t.error.stack,t.error.message),this.events.connection.trigger(!1)}};function ie(n){return new F(n)}var ne=async(n,e,t)=>{await n.setItem(e,JSON.stringify(t))},se=async(n,e)=>{let t=await n.getItem(e);if(!t)return null;try{return JSON.parse(t)}catch (e2){return t}},oe=async(n,e)=>{await n.removeItem(e)};function V(n){return typeof n=="function"}var b=class{constructor(e,t,r,i,s){this._authEvent=s,this._client=e,this._persistSession=t||v.persistSession,this._sessionStorage=r||v.sessionStorage,this._sessionStorageKey=i||v.sessionStorageKey}async create(e,t,r){try{let i=await _chunkIRXYP7GMjs.s.call(void 0, this._client,e,t),s=this.useCredentials(i);return r&&r(s),s}catch(i){throw r&&r({err:i}),i}}async auth(e,t,r,i){let s=V(r)?r:V(t)?t:null;try{await this.recoverCredentials();let o,a;if(_chunkIRXYP7GMjs.a.call(void 0, e)&&(e.pub||e.epub)){let d=e,c=r;return o=await _chunkIRXYP7GMjs.n.call(void 0, this._client,d,c),a=this.useCredentials(o),s&&s(a),a}else if(_chunkIRXYP7GMjs.i.call(void 0, e)&&_chunkIRXYP7GMjs.i.call(void 0, t)){let d=e,c=t,G=i;return o=await _chunkIRXYP7GMjs.n.call(void 0, this._client,d,c,G),a=this.useCredentials(o),s&&s(a),a}}catch(o){throw s&&s({err:o}),o}}leave(){return this._signMiddleware&&(this._client.graph.unuse(this._signMiddleware,"write"),this._signMiddleware=void 0,this.is=void 0),this}get(e){return this.is&&this._client.get(`~${this.is.pub}/${e}`)}async recoverCredentials(){if(this._persistSession){let e=await se(this._sessionStorage,this._sessionStorageKey);e!==null&&(this._isValidCredentials(e)?this.useCredentials(e):await this._removeCredentials())}}useCredentials(e){return this.leave(),this._signMiddleware=_chunkIRXYP7GMjs.r.call(void 0, this._client,{priv:e.priv,pub:e.pub}),this._client.graph.use(this._signMiddleware,"write"),this.is={alias:e.alias,pub:e.pub},this.is&&this.is.pub&&this._authSuccess(e),this.is}_authSuccess(e){this._authEvent.trigger({alias:e.alias,pub:e.pub}),this._authConnectors(e),this._persistCredentials(e)}_authConnectors(e){this._client.graph.eachConnector(t=>{t.name==="TGWebSocketGraphConnector"&&t.authenticate(e.pub,e.priv)})}async _persistCredentials(e){this._persistSession&&await ne(this._sessionStorage,this._sessionStorageKey,e)}async _removeCredentials(){this._persistSession&&await oe(this._sessionStorage,this._sessionStorageKey)}_isValidCredentials(e){return _chunkIRXYP7GMjs.a.call(void 0, e)&&"priv"in e&&"epriv"in e&&"alias"in e&&"pub"in e&&"epub"in e}};function ae(){if(!_chunkIRXYP7GMjs.a.call(void 0, globalThis))try{Object.defineProperty(Object.prototype,"__magic__",{get:function(){return this},configurable:!0}),__magic__.globalThis=__magic__,delete Object.prototype.__magic__}catch (e3){typeof self<"u"&&(self.globalThis=self)}}var P=class{constructor(e){this._dbName=e,this._storeName=e,this._init()}get(e){let t;return this._withIDBStore("readwrite",r=>{t=r.get(e)}).then(()=>t.result)}getALlKeys(){let e;return this._withIDBStore("readwrite",t=>{e=t.getAll()}).then(()=>e.result)}set(e,t){return this._withIDBStore("readwrite",r=>{r.put(t,e)})}update(e,t){return this._withIDBStore("readwrite",r=>{let i=r.get(e);i.onsuccess=()=>{r.put(t(i.result),e)}})}del(e){return this._withIDBStore("readwrite",t=>{t.delete(e)})}_init(){this._dbp||(this._dbp=new Promise((e,t)=>{let r=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB||window.shimIndexedDB;if(!r)return t(Error("IndexedDB could not be found!"));let i=r.open(this._dbName);i.onerror=()=>t(i.error),i.onsuccess=()=>e(i.result),i.onupgradeneeded=()=>{i.result.createObjectStore(this._storeName)}}))}_withIDBStore(e,t){return this._init(),this._dbp.then(r=>new Promise((i,s)=>{let o=r.transaction(this._storeName,e);o.oncomplete=()=>i(),o.onabort=o.onerror=()=>s(o.error),t(o.objectStore(this._storeName))}))}};var de="topgun-nodes",B={diffFn:_chunkIRXYP7GMjs.d,mergeFn:_chunkIRXYP7GMjs.f};function ue(n=de){let e=new P(n);return le(e)}function le(n){return{get:e=>fe(n,e),put:e=>Ge(n,e)}}async function fe(n,e){return n.get(e)}async function Ge(n,e,t=B){let r={};for(let i in e){if(!i)continue;let s=await Te(n,{[i]:e[i]},t);s&&(r[i]=s[i])}return Object.keys(r).length?r:null}async function Te(n,e,t=B){for(;;){let r=await ge(n,e,t);if(!r)return null;let{diff:i,toWrite:s}=r;if(await _e(n,s))return i;console.warn("unsuccessful patch, retrying",Object.keys(i))}}async function ge(n,e,t=B){let{diffFn:r=_chunkIRXYP7GMjs.d,mergeFn:i=_chunkIRXYP7GMjs.f}=t,s=await me(n,e),o=r(e,s);if(!o||!Object.keys(o).length)return null;let a={};for(let c in o)c&&(a[c]=s[c]);let d=i(s,o,"mutable");return{diff:o,existing:a,toWrite:d}}async function me(n,e){let t={};for(let r in e)r&&(t[r]=await n.get(r));return t}async function _e(n,e){try{for(let t in e){if(!t)continue;let r=e[t];r&&await n.set(t,r)}return!0}catch(t){throw t}}var pe=()=>{},C= exports.TGGraphConnectorFromAdapter =class extends f{constructor(t,r="GraphConnectorFromAdapter"){super(r);this.adapter=t}get({soul:t,cb:r,opts:i,msgId:s=""}){return this.adapter.get(t,i).then(o=>({"#":_chunkIRXYP7GMjs.u.call(void 0, ),"@":s,put:o?{[t]:o}:void 0})).catch(o=>(console.warn(o.stack||o),{"#":_chunkIRXYP7GMjs.u.call(void 0, ),"@":s,err:"Error fetching node"})).then(o=>{this.ingest([o]),r&&r(o)}),pe}put({graph:t,msgId:r="",cb:i}){return this.adapter.put(t).then(()=>({"#":_chunkIRXYP7GMjs.u.call(void 0, ),"@":r,err:null,ok:!0})).catch(s=>(console.warn(s.stack||s),{"#":_chunkIRXYP7GMjs.u.call(void 0, ),"@":r,err:"Error saving put",ok:!1})).then(s=>{this.ingest([s]),i&&i(s)}),pe}};var M=class extends C{constructor(e){super(ue(e),"TGIndexedDbConnector")}};var k=()=>typeof document<"u";var he={getItem:n=>k()?globalThis.localStorage.getItem(n):null,setItem:(n,e)=>{k()&&globalThis.localStorage.setItem(n,e)},removeItem:n=>{k()&&globalThis.localStorage.removeItem(n)}};var L=class extends _chunkIRXYP7GMjs.t{constructor(e,t){super(e,t)}get(e){if(_chunkIRXYP7GMjs.a.call(void 0, e)&&!_chunkIRXYP7GMjs.i.call(void 0, e)){let t=this.getPath().shift();return this.optionsGet={["#"]:t,["."]:{}},_chunkIRXYP7GMjs.a.call(void 0, e["."])&&(this.optionsGet["."]=_chunkIRXYP7GMjs.b.call(void 0, e["."])),_chunkIRXYP7GMjs.m.call(void 0, e["%"])&&(this.optionsGet["%"]=e["%"]),this}else return new (0, _chunkIRXYP7GMjs.t)(this._chain,e,this)}start(e){return this._setLex(">",e),this}end(e){return this._setLex("<",e),this}prefix(e){return this._setLex("*",e),this}equals(e){return this._setLex("=",e),this}limit(e){return this.optionsGet["%"]=e,this}reverse(e=!0){return this.optionsGet["-"]=e,this}map(){return super.map()}toString(){return JSON.stringify(this.optionsGet)}getQuery(){return this.optionsGet}on(e){return super.on(e)}once(e){return super.once(e)}_setLex(e,t){this.optionsGet["."][e]=t}};ae();var v={peers:[],graph:new g,connectors:[],persistStorage:!1,storageKey:"top-gun-nodes",persistSession:!0,sessionStorage:he,sessionStorageKey:"top-gun-session",passwordMinLength:8},O= exports.TGClient =class{constructor(e){e=_chunkIRXYP7GMjs.a.call(void 0, e)?e:{},this.options={...v,...e},this._authEvent=new (0, _chunkIRXYP7GMjs.g)("auth data"),this.options&&this.options.graph?this.graph=this.options.graph:(this.graph=new g,this.graph.use(_chunkIRXYP7GMjs.d),this.graph.use(_chunkIRXYP7GMjs.d,"write")),this.opt(this.options),this.registerSeaMiddleware(),this.user().recoverCredentials()}user(e){return e?(_chunkIRXYP7GMjs.a.call(void 0, e)&&e._&&e._["#"]?this.pub=_chunkIRXYP7GMjs.j.call(void 0, e._["#"]):_chunkIRXYP7GMjs.i.call(void 0, e)&&(this.pub=e.startsWith("~")?_chunkIRXYP7GMjs.j.call(void 0, e):e),this.get("~"+this.pub)):this._user=this._user||new b(this,this.options.persistSession,this.options.sessionStorage,this.options.sessionStorageKey,this._authEvent)}opt(e){return this.options={...this.options,...e},Array.isArray(e.peers)&&this.handlePeers(e.peers),e.persistStorage&&this.useConnector(new M(e.storageKey)),Array.isArray(e.connectors)&&e.connectors.forEach(t=>this.useConnector(t)),this}get(e){return new L(this,e)}on(e,t){switch(e){case"auth":this._authEvent.on(t),_optionalChain([this, 'access', _2 => _2._user, 'optionalAccess', _3 => _3.is])&&this._authEvent.trigger(this._user.is);break}return this}registerSeaMiddleware(){this.graph.use(e=>_chunkIRXYP7GMjs.k.call(void 0, e,this.graph._opt.mutable?"mutable":"immutable"))}useConnector(e){e.sendPutsFromGraph(this.graph),e.sendRequestsFromGraph(this.graph),this.graph.connect(e)}async handlePeers(e){e.forEach(t=>{try{let r=new URL(t),i={hostname:r.hostname,secure:r.protocol.includes("https")};r.port.length>0&&(i.port=Number(r.port)),this.useConnector(ie(i))}catch(r){console.error(r)}})}};O.match=_chunkIRXYP7GMjs.p;exports.TGClient = O; exports.TGEvent = _chunkIRXYP7GMjs.g; exports.TGGraph = g; exports.TGGraphConnector = y; exports.TGGraphConnectorFromAdapter = C; exports.TGGraphWireConnector = f; exports.TGLink = _chunkIRXYP7GMjs.t; exports.TGProcessQueue = m; exports.TGQueue = _; exports.TGUserApi = b; | ||
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunkC4KWPA6Zjs = require('./chunk-C4KWPA6Z.js');var D=class{constructor(e,t,r){this._onDirectQueryReply=this._onDirectQueryReply.bind(this),this._data=new (0, _chunkC4KWPA6Zjs.g)(`<GraphNode ${t}>`),this._graph=e,this._updateGraph=r,this.soul=t}listenerCount(){return this._data.listenerCount()}get(e){return e&&this.on(e),this._ask(),this}receive(e){return this._data.trigger(e,this.soul),this}on(e){return this._data.on(e),this}off(e){return e?this._data.off(e):this._data.reset(),this._endCurQuery&&!this._data.listenerCount()&&(this._endCurQuery(),this._endCurQuery=void 0),this}_ask(){return this._endCurQuery?this:(this._endCurQuery=this._graph.get(this.soul,this._onDirectQueryReply),this)}_onDirectQueryReply(e){e.put||this._updateGraph({[this.soul]:void 0},e["@"])}};function te(s){return typeof s=="boolean"}function q(s){return _chunkC4KWPA6Zjs.a.call(void 0, s)||_chunkC4KWPA6Zjs.i.call(void 0, s)||te(s)||_chunkC4KWPA6Zjs.m.call(void 0, s)&&s!==1/0&&s!==-1/0&&!Number.isNaN(s)||s===null}function re(s,e){return s&&(e=s.constructor)&&e.name||typeof s}function R(s,e){return s.reverse().reduce((t,r)=>({[r]:t}),e)}function Q(s,e=[],t={}){if(q(s))_chunkC4KWPA6Zjs.a.call(void 0, s)||(s=R(e,s));else throw Error("Invalid data: "+re(s)+" at "+e.join("."));let r=e.join("/");e.length>0&&!_chunkC4KWPA6Zjs.a.call(void 0, t[r])&&(t[r]={});for(let n in s){if(!s.hasOwnProperty(n))continue;let i=s[n],o=[...e,n],a=o.join("/");if(!q(i)){console.log("Invalid data: "+re(i)+" at "+o.join("."));continue}_chunkC4KWPA6Zjs.a.call(void 0, i)?(t[r][n]={"#":a},Q(i,o,t)):t[r][n]=i}return t}var f=class{constructor(){this.id=_chunkC4KWPA6Zjs.u.call(void 0, ),this.receiveGraphData=this.receiveGraphData.bind(this),this.__onConnectorStatus=this.__onConnectorStatus.bind(this),this.activeConnectors=0,this.events={get:new (0, _chunkC4KWPA6Zjs.g)("request soul"),graphData:new (0, _chunkC4KWPA6Zjs.g)("graph data"),off:new (0, _chunkC4KWPA6Zjs.g)("off event"),put:new (0, _chunkC4KWPA6Zjs.g)("put data")},this._opt={},this._graph={},this._nodes={},this._connectors=[],this._readMiddleware=[],this._writeMiddleware=[]}opt(e){return this._opt={...this._opt,...e},this}connect(e){return this._connectors.indexOf(e)!==-1?this:(this._connectors.push(e.connectToGraph(this)),e.events.connection.on(this.__onConnectorStatus),e.events.graphData.on(this.receiveGraphData),e.isConnected&&this.activeConnectors++,this)}disconnect(e){let t=this._connectors.indexOf(e);return e.events.graphData.off(this.receiveGraphData),e.events.connection.off(this.__onConnectorStatus),t!==-1&&this._connectors.splice(t,1),e.isConnected&&this.activeConnectors--,this}use(e,t="read"){return t==="read"?this._readMiddleware.push(e):t==="write"&&this._writeMiddleware.push(e),this}unuse(e,t="read"){if(t==="read"){let r=this._readMiddleware.indexOf(e);r!==-1&&this._readMiddleware.splice(r,1)}else if(t==="write"){let r=this._writeMiddleware.indexOf(e);r!==-1&&this._writeMiddleware.splice(r,1)}return this}query(e,t){let r=[],n,i=()=>{let{souls:o,value:a,complete:c}=_chunkC4KWPA6Zjs.x.call(void 0, e,this._graph),[d,T]=_chunkC4KWPA6Zjs.v.call(void 0, r,o);(c&&!_chunkC4KWPA6Zjs.h.call(void 0, n)||_chunkC4KWPA6Zjs.h.call(void 0, a)&&a!==n)&&(n=a,t(a,e[e.length-1]));for(let I of d)this._requestSoul(I,i);for(let I of T)this._unlistenSoul(I,i);r=o};return i(),()=>{for(let o of r)this._unlistenSoul(o,i)}}async putPath(e,t,r,n,i,o){if(!e.length){let T=new Error("No path specified");throw r&&r({"#":void 0,"@":"",err:T,ok:!1}),T}let a=e.shift(),c=R(e,t),d=Q(c,[a]);this.put(d,e,r,void 0,a,o)}get(e,t,r){let n=r||_chunkC4KWPA6Zjs.u.call(void 0, );return this.events.get.trigger({cb:t,msgId:n,soul:e}),()=>this.events.off.trigger(n)}put(e,t,r,n,i,o){let a=_chunkC4KWPA6Zjs.w.call(void 0, _chunkC4KWPA6Zjs.c.call(void 0, e)),c=n||_chunkC4KWPA6Zjs.u.call(void 0, );return(async()=>{for(let d of this._writeMiddleware){if(!a)return;a=await d(a,this._graph,o,t)}a&&(await this.receiveGraphData(a),this.events.put.trigger({cb:r,graph:a,msgId:c}),r&&r({"#":t.length>0?t[t.length-1]:i,"@":n,err:null,ok:!0}))})(),()=>this.events.off.trigger(c)}connectorCount(){return this._connectors.length}eachConnector(e){for(let t of this._connectors)e(t);return this}async receiveGraphData(e,t,r){let n=e;for(let i of this._readMiddleware){if(!n)return;n=await i(n,this._graph)}if(n){for(let i in n)i&&this._node(i).receive(this._graph[i]=_chunkC4KWPA6Zjs.e.call(void 0, this._graph[i],n[i],this._opt.mutable?"mutable":"immutable"));this.events.graphData.trigger(n,t,r)}}_node(e){return this._nodes[e]=this._nodes[e]||new D(this,e,this.receiveGraphData)}_requestSoul(e,t){return this._node(e).get(t),this}_unlistenSoul(e,t){let r=this._nodes[e];return r?(r.off(t),r.listenerCount()<=0&&(r.off(),this._forgetSoul(e)),this):this}_forgetSoul(e){let t=this._nodes[e];return t&&(t.off(),delete this._nodes[e]),this}__onConnectorStatus(e){e?this.activeConnectors++:this.activeConnectors--}};var x=()=>typeof document<"u";var ne={getItem:s=>x()?globalThis.localStorage.getItem(s):null,setItem:(s,e)=>{x()&&globalThis.localStorage.setItem(s,e)},removeItem:s=>{x()&&globalThis.localStorage.removeItem(s)}};var m={peers:[],graph:new f,connectors:[],persistStorage:!1,storageKey:"top-gun-nodes",persistSession:!0,sessionStorage:ne,sessionStorageKey:"top-gun-session",passwordMinLength:8};var y=class{constructor(e="Queue"){this.name=e,this._queue=[]}count(){return this._queue.length}has(e){return this._queue.indexOf(e)!==-1}enqueue(e){return this.has(e)?this:(this._queue.splice(0,0,e),this)}dequeue(){return this._queue.pop()}enqueueMany(e){let t=e.filter(r=>!this.has(r));return t.length&&this._queue.splice(0,0,...t.slice().reverse()),this}};var P=class{constructor(e="MiddlewareSystem"){this.name=e,this._middlewareFunctions=[]}use(e){return this._middlewareFunctions.indexOf(e)!==-1?this:(this._middlewareFunctions.push(e),this)}unuse(e){let t=this._middlewareFunctions.indexOf(e);return t!==-1&&this._middlewareFunctions.splice(t,1),this}async process(e,t,r){let n=e;for(let i of this._middlewareFunctions){if(!n)return;n=await i(n,t,r)}return n}};var _=class extends y{constructor(t="ProcessQueue",r="process_dupes"){super(t);this.alreadyProcessed=[],this.isProcessing=!1,this.processDupes=r,this.completed=new (0, _chunkC4KWPA6Zjs.g)(`${t}.processed`),this.emptied=new (0, _chunkC4KWPA6Zjs.g)(`${t}.emptied`),this.middleware=new P(`${t}.middleware`)}has(t){return super.has(t)||this.alreadyProcessed.indexOf(t)!==-1}async processNext(t,r){let n=this.dequeue(),i=n;n&&(n=await this.middleware.process(n,t,r),i&&this.processDupes==="dont_process_dupes"&&this.alreadyProcessed.push(i),n&&this.completed.trigger(n))}enqueueMany(t){return super.enqueueMany(t),this}async process(){if(!this.isProcessing&&this.count()){for(this.isProcessing=!0;this.count();)try{await this.processNext()}catch(t){console.error("Process Queue error",t)}this.emptied.trigger(!0),this.isProcessing=!1}}};var v=class{constructor(e="GraphConnector"){this.isConnected=!1,this.name=e,this.put=this.put.bind(this),this.off=this.off.bind(this),this.inputQueue=new _(`${e}.inputQueue`),this.outputQueue=new _(`${e}.outputQueue`),this.events={connection:new (0, _chunkC4KWPA6Zjs.g)(`${e}.events.connection`),graphData:new (0, _chunkC4KWPA6Zjs.g)(`${e}.events.graphData`),receiveMessage:new (0, _chunkC4KWPA6Zjs.g)(`${e}.events.receiveMessage`)},this._onConnectedChange=this._onConnectedChange.bind(this),this.events.connection.on(this._onConnectedChange)}connectToGraph(e){return e.events.off.on(this.off),this}off(e){return this}sendPutsFromGraph(e){return e.events.put.on(this.put),this}sendRequestsFromGraph(e){return e.events.get.on(t=>{this.get(t)}),this}waitForConnection(){return this.isConnected?Promise.resolve():new Promise(e=>{let t=r=>{r&&(e(),this.events.connection.off(t))};this.events.connection.on(t)})}put(e){return()=>{}}get(e){return()=>{}}send(e){return this.outputQueue.enqueueMany(e),this.isConnected&&this.outputQueue.process(),this}ingest(e){return this.inputQueue.enqueueMany(e).process(),this}_onConnectedChange(e){e?(this.isConnected=!0,this.outputQueue.process()):this.isConnected=!1}};var G=class extends v{constructor(t="GraphWireConnector"){super(t);this._callbacks={},this._onProcessedInput=this._onProcessedInput.bind(this),this.inputQueue.completed.on(this._onProcessedInput)}off(t){return super.off(t),delete this._callbacks[t],this}put({graph:t,msgId:r="",replyTo:n="",cb:i}){if(!t)return()=>{};let o={put:t};return r&&(o["#"]=r),n&&(o["@"]=n),this.req(o,i)}get({soul:t,cb:r,msgId:n=""}){let o={get:{"#":t}};return n&&(o["#"]=n),this.req(o,r)}req(t,r){let n=t["#"]=t["#"]||_chunkC4KWPA6Zjs.u.call(void 0, );return r&&(this._callbacks[n]=r),this.send([t]),()=>{this.off(n)}}_onProcessedInput(t){if(!t)return;let r=t["#"],n=t["@"];if(t.put&&this.events.graphData.trigger(t.put,r,n),n){let i=this._callbacks[n];i&&i(t)}this.events.receiveMessage.trigger(t)}};var _client2 = require('topgun-socket/client');var F=class extends G{constructor(t,r="TGWebSocketGraphConnector"){super(r);this._requestChannels={},this.opts=t,this.socket=_client2.create.call(void 0, this.opts||{}),this.onConnect(),this.onError(),this.outputQueue.completed.on(this.onOutputProcessed.bind(this))}off(t){super.off(t);let r=this._requestChannels[t];return r&&(r.unsubscribe(),delete this._requestChannels[t]),this}get({soul:t,msgId:r,cb:n,opts:i}){let o=a=>{this.ingest([a]),n&&n(a)};return r=r||_chunkC4KWPA6Zjs.u.call(void 0, ),this._requestChannels[r]=this.subscribeToChannel(`topgun/nodes/${t}`,o),super.get({soul:t,msgId:r,cb:n,opts:i})}put({graph:t,msgId:r="",replyTo:n="",cb:i}){if(!t)return()=>{};if(r=r||_chunkC4KWPA6Zjs.u.call(void 0, ),i){let o=a=>{this.ingest([a]),i(a),this.off(r)};return this._requestChannels[r]=this.subscribeToChannel(`topgun/@${r}`,o),super.put({graph:t,msgId:r,replyTo:n,cb:o})}else return super.put({graph:t,msgId:r,replyTo:n,cb:i})}async authenticate(t,r){await this.waitForConnection(),this.doAuth(t,r);for await(let n of this.socket.listener("connect"))this.doAuth(t,r)}publishToChannel(t,r){return this.socket.transmitPublish(t,r),this}subscribeToChannel(t,r,n){let i=this.socket.subscribe(t,n);return this.onChannelMessage(i,r),i}async doAuth(t,r){let n=this.socket.id,i=new Date().getTime(),o=`${n}/${i}`,a=await _chunkC4KWPA6Zjs.q.call(void 0, o,{pub:t,priv:r},{raw:!0});return this.socket.invoke("login",{proof:a,pub:t})}async onChannelMessage(t,r){for await(let n of t)this.ingest([n]),r&&r(n)}onOutputProcessed(t){if(t&&this.socket){let r=t["@"];r?this.publishToChannel(`topgun/@${r}`,t):"get"in t?this.publishToChannel("topgun/get",t):"put"in t&&this.publishToChannel("topgun/put",t)}}async onConnect(){for await(let t of this.socket.listener("connect")){console.log(`SC client ${t.id} is connected.`);try{this.events.connection.trigger(!0)}catch(r){console.error(r)}}}async onError(){for await(let t of this.socket.listener("error"))console.error("Socket Connection Error",t.error.stack,t.error.message),this.events.connection.trigger(!1)}};function ie(s){return new F(s)}var se=async(s,e,t)=>{await s.setItem(e,JSON.stringify(t))},oe=async(s,e)=>{let t=await s.getItem(e);if(!t)return null;try{return JSON.parse(t)}catch (e2){return t}},ae=async(s,e)=>{await s.removeItem(e)};function V(s){return typeof s=="function"}var C=class{constructor(e,t,r,n,i){this._authEvent=i,this._client=e,this._persistSession=t||m.persistSession,this._sessionStorage=r||m.sessionStorage,this._sessionStorageKey=n||m.sessionStorageKey}async create(e,t,r){try{let n=await _chunkC4KWPA6Zjs.s.call(void 0, this._client,e,t),i=this.useCredentials(n);return r&&r(i),i}catch(n){throw r&&r({err:n}),n}}async auth(e,t,r,n){let i=V(r)?r:V(t)?t:null;try{await this.recoverCredentials();let o,a;if(_chunkC4KWPA6Zjs.a.call(void 0, e)&&(e.pub||e.epub)){let c=e,d=r;return o=await _chunkC4KWPA6Zjs.n.call(void 0, this._client,c,d),a=this.useCredentials(o),i&&i(a),a}else if(_chunkC4KWPA6Zjs.i.call(void 0, e)&&_chunkC4KWPA6Zjs.i.call(void 0, t)){let c=e,d=t,T=n;return o=await _chunkC4KWPA6Zjs.n.call(void 0, this._client,c,d,T),a=this.useCredentials(o),i&&i(a),a}}catch(o){throw i&&i({err:o}),o}}leave(){return this._signMiddleware&&(this._client.graph.unuse(this._signMiddleware,"write"),this._signMiddleware=void 0,this.is=void 0),this}get(e){return this.is&&this._client.get(`~${this.is.pub}/${e}`)}async recoverCredentials(){if(this._persistSession){let e=await oe(this._sessionStorage,this._sessionStorageKey);e!==null&&(this._isValidCredentials(e)?this.useCredentials(e):await this._removeCredentials())}}useCredentials(e){return this.leave(),this._signMiddleware=_chunkC4KWPA6Zjs.r.call(void 0, this._client,{priv:e.priv,pub:e.pub}),this._client.graph.use(this._signMiddleware,"write"),this.is={alias:e.alias,pub:e.pub},this.is&&this.is.pub&&this._authSuccess(e),this.is}_authSuccess(e){this._authEvent.trigger({alias:e.alias,pub:e.pub}),this._authConnectors(e),this._persistCredentials(e)}_authConnectors(e){this._client.graph.eachConnector(t=>{t.name==="TGWebSocketGraphConnector"&&t.authenticate(e.pub,e.priv)})}async _persistCredentials(e){this._persistSession&&await se(this._sessionStorage,this._sessionStorageKey,e)}async _removeCredentials(){this._persistSession&&await ae(this._sessionStorage,this._sessionStorageKey)}_isValidCredentials(e){return _chunkC4KWPA6Zjs.a.call(void 0, e)&&"priv"in e&&"epriv"in e&&"alias"in e&&"pub"in e&&"epub"in e}};function he(){if(!_chunkC4KWPA6Zjs.a.call(void 0, globalThis))try{Object.defineProperty(Object.prototype,"__magic__",{get:function(){return this},configurable:!0}),__magic__.globalThis=__magic__,delete Object.prototype.__magic__}catch (e3){typeof self<"u"&&(self.globalThis=self)}}var M=class{constructor(e){this._dbName=e,this._storeName=e,this._init()}get(e){let t;return this._withIDBStore("readwrite",r=>{t=r.get(e)}).then(()=>t.result)}getALlKeys(){let e;return this._withIDBStore("readwrite",t=>{e=t.getAll()}).then(()=>e.result)}set(e,t){return this._withIDBStore("readwrite",r=>{r.put(t,e)})}update(e,t){return this._withIDBStore("readwrite",r=>{let n=r.get(e);n.onsuccess=()=>{r.put(t(n.result),e)}})}del(e){return this._withIDBStore("readwrite",t=>{t.delete(e)})}_init(){this._dbp||(this._dbp=new Promise((e,t)=>{let r=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB||window.shimIndexedDB;if(!r)return t(Error("IndexedDB could not be found!"));let n=r.open(this._dbName);n.onerror=()=>t(n.error),n.onsuccess=()=>e(n.result),n.onupgradeneeded=()=>{n.result.createObjectStore(this._storeName)}}))}_withIDBStore(e,t){return this._init(),this._dbp.then(r=>new Promise((n,i)=>{let o=r.transaction(this._storeName,e);o.oncomplete=()=>n(),o.onabort=o.onerror=()=>i(o.error),t(o.objectStore(this._storeName))}))}};var ce="topgun-nodes",B={diffFn:_chunkC4KWPA6Zjs.d,mergeFn:_chunkC4KWPA6Zjs.f};function pe(s=ce){let e=new M(s);return le(e)}function le(s){return{get:e=>fe(s,e),put:e=>Ge(s,e)}}async function fe(s,e){return s.get(e)}async function Ge(s,e,t=B){let r={};for(let n in e){if(!n)continue;let i=await Te(s,{[n]:e[n]},t);i&&(r[n]=i[n])}return Object.keys(r).length?r:null}async function Te(s,e,t=B){for(;;){let r=await ge(s,e,t);if(!r)return null;let{diff:n,toWrite:i}=r;if(await _e(s,i))return n;console.warn("unsuccessful patch, retrying",Object.keys(n))}}async function ge(s,e,t=B){let{diffFn:r=_chunkC4KWPA6Zjs.d,mergeFn:n=_chunkC4KWPA6Zjs.f}=t,i=await me(s,e),o=r(e,i);if(!o||!Object.keys(o).length)return null;let a={};for(let d in o)d&&(a[d]=i[d]);let c=n(i,o,"mutable");return{diff:o,existing:a,toWrite:c}}async function me(s,e){let t={};for(let r in e)r&&(t[r]=await s.get(r));return t}async function _e(s,e){try{for(let t in e){if(!t)continue;let r=e[t];r&&await s.set(t,r)}return!0}catch(t){throw t}}var ue=()=>{},w= exports.TGGraphConnectorFromAdapter =class extends G{constructor(t,r="GraphConnectorFromAdapter"){super(r);this.adapter=t}get({soul:t,cb:r,opts:n,msgId:i=""}){return this.adapter.get(t,n).then(o=>({"#":_chunkC4KWPA6Zjs.u.call(void 0, ),"@":i,put:o?{[t]:o}:void 0})).catch(o=>(console.warn(o.stack||o),{"#":_chunkC4KWPA6Zjs.u.call(void 0, ),"@":i,err:"Error fetching node"})).then(o=>{this.ingest([o]),r&&r(o)}),ue}put({graph:t,msgId:r="",cb:n}){return this.adapter.put(t).then(()=>({"#":_chunkC4KWPA6Zjs.u.call(void 0, ),"@":r,err:null,ok:!0})).catch(i=>(console.warn(i.stack||i),{"#":_chunkC4KWPA6Zjs.u.call(void 0, ),"@":r,err:"Error saving put",ok:!1})).then(i=>{this.ingest([i]),n&&n(i)}),ue}};var k=class extends w{constructor(e){super(pe(e),"TGIndexedDbConnector")}};var L=class extends _chunkC4KWPA6Zjs.t{constructor(e,t){super(e,t)}get(e){if(_chunkC4KWPA6Zjs.a.call(void 0, e)&&!_chunkC4KWPA6Zjs.i.call(void 0, e)){let t=this.getPath().shift();return this.optionsGet={["#"]:t,["."]:{}},_chunkC4KWPA6Zjs.a.call(void 0, e["."])&&(this.optionsGet["."]=_chunkC4KWPA6Zjs.b.call(void 0, e["."])),_chunkC4KWPA6Zjs.m.call(void 0, e["%"])&&(this.optionsGet["%"]=e["%"]),this}else return new (0, _chunkC4KWPA6Zjs.t)(this._chain,e,this)}start(e){return this._setLex(">",e),this}end(e){return this._setLex("<",e),this}prefix(e){return this._setLex("*",e),this}equals(e){return this._setLex("=",e),this}limit(e){return this.optionsGet["%"]=e,this}reverse(e=!0){return this.optionsGet["-"]=e,this}map(){return super.map()}toString(){return JSON.stringify(this.optionsGet)}getQuery(){return this.optionsGet}on(e){return super.on(e)}once(e){return super.once(e)}_setLex(e,t){this.optionsGet["."][e]=t}};he();var O=class{constructor(e){e=_chunkC4KWPA6Zjs.a.call(void 0, e)?e:{},this.options={...m,...e},this._authEvent=new (0, _chunkC4KWPA6Zjs.g)("auth data"),this.options&&this.options.graph?this.graph=this.options.graph:(this.graph=new f,this.graph.use(_chunkC4KWPA6Zjs.d),this.graph.use(_chunkC4KWPA6Zjs.d,"write")),this.opt(this.options),this.registerSeaMiddleware(),this.user().recoverCredentials()}user(e){return e?(_chunkC4KWPA6Zjs.a.call(void 0, e)&&e._&&e._["#"]?this.pub=_chunkC4KWPA6Zjs.j.call(void 0, e._["#"]):_chunkC4KWPA6Zjs.i.call(void 0, e)&&(this.pub=e.startsWith("~")?_chunkC4KWPA6Zjs.j.call(void 0, e):e),this.get("~"+this.pub)):this._user=this._user||new C(this,this.options.persistSession,this.options.sessionStorage,this.options.sessionStorageKey,this._authEvent)}opt(e){return this.options={...this.options,...e},Array.isArray(e.peers)&&this.handlePeers(e.peers),e.persistStorage&&this.useConnector(new k(e.storageKey)),Array.isArray(e.connectors)&&e.connectors.forEach(t=>this.useConnector(t)),this}get(e){return new L(this,e)}on(e,t){switch(e){case"auth":this._authEvent.on(t),_optionalChain([this, 'access', _2 => _2._user, 'optionalAccess', _3 => _3.is])&&this._authEvent.trigger(this._user.is);break}return this}registerSeaMiddleware(){this.graph.use(e=>_chunkC4KWPA6Zjs.k.call(void 0, e,this.graph._opt.mutable?"mutable":"immutable"))}useConnector(e){e.sendPutsFromGraph(this.graph),e.sendRequestsFromGraph(this.graph),this.graph.connect(e)}async handlePeers(e){e.forEach(t=>{try{let r=new URL(t),n={hostname:r.hostname,secure:r.protocol.includes("https")};r.port.length>0&&(n.port=Number(r.port)),this.useConnector(ie(n))}catch(r){console.error(r)}})}};O.match=_chunkC4KWPA6Zjs.p;exports.TGClient = O; exports.TGEvent = _chunkC4KWPA6Zjs.g; exports.TGGraph = f; exports.TGGraphConnector = v; exports.TGGraphConnectorFromAdapter = w; exports.TGGraphWireConnector = G; exports.TGLink = _chunkC4KWPA6Zjs.t; exports.TGProcessQueue = _; exports.TGQueue = y; exports.TGUserApi = C; |
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunkIRXYP7GMjs = require('./chunk-IRXYP7GM.js');var A=class{default(t){t.allow()}};var b=class extends A{constructor(e,r){super();this.adapter=e;this.options=r}onPublishIn(e){let r=e.data;if(e.channel!=="topgun/put"){this.isAdmin(e.socket)?e.allow():e.block(new Error("You aren't allowed to write to this channel"));return}e.allow(),!(e.channel!=="topgun/put"||!r||!r.put)&&this.processPut(r).then(n=>{this.publish(e,{channel:`topgun/@${r["#"]}`,data:n})})}async onSubscribe(e){if(e.channel==="topgun/put"&&!this.isAdmin(e.socket)){e.block(new Error(`You aren't allowed to subscribe to ${e.channel}`));return}let r=String(e.channel).replace(/^topgun\/nodes\//,"");if(!r||r===e.channel){e.allow();return}if(e.allow(),r==="changelog")return;let n=_chunkIRXYP7GMjs.u.call(void 0, );this.readNode(r).then(i=>({channel:e.channel,data:{"#":n,put:i?{[r]:i}:null}})).catch(i=>(console.warn(i.stack||i),{channel:e.channel,data:{"#":n,"@":e.data["#"],err:"Error fetching node"}})).then(i=>{this.publish(e,i)})}default(e){e.allow()}async onAuthenticate(e){e.allow()}readNode(e){return this.adapter.get(e)}isAdmin(e){return e.authToken&&e.authToken.pub===this.options.ownerPub}async processPut(e){let r=_chunkIRXYP7GMjs.l.call(void 0, );try{return e.put&&await this.adapter.put(e.put),{"#":r,"@":e["#"],err:null,ok:!0}}catch (e2){return{"#":r,"@":e["#"],err:"Error saving",ok:!1}}}publish(e,r){e.socket.transmit("#publish",r,{})}};var _routeparser = require('route-parser'); var _routeparser2 = _interopRequireDefault(_routeparser);var _ajv = require('ajv'); var _ajv2 = _interopRequireDefault(_ajv);var _regexp = require('route-parser/lib/route/visitors/regexp'); var _regexp2 = _interopRequireDefault(_regexp);function g(o,...t){if(!t.length)return o;let e=t.shift();if(_chunkIRXYP7GMjs.a.call(void 0, o)&&_chunkIRXYP7GMjs.a.call(void 0, e))for(let r in e)_chunkIRXYP7GMjs.a.call(void 0, e[r])?(o[r]||Object.assign(o,{[r]:{}}),g(o[r],e[r])):Object.assign(o,{[r]:e[r]});return g(o,...t)}var W=new (0, _routeparser2.default)("#/definitions/:refName");function X(o){let{re:t}=_regexp2.default.visit(o.ast),e=t.toString();return e.slice(1,e.length-1)}var v={Node:{type:"object",title:"Node",description:"Any node supported by TopGun",$async:!0,additionalProperties:{anyOf:[{$ref:"#/definitions/TopGunEdge"},{type:"null"},{type:"string"},{type:"number"},{type:"boolean"},{type:"object"}]},soul:{pattern:"*soul",type:"object",properties:{soul:{type:"string"}},required:["soul"]}}},Y=v,Z=o=>t=>{t=t||{};let e={...t};delete e.pattern;let r=t.pattern||"",n=new (0, _routeparser2.default)(r);return(i,s)=>{let a=i&&i._&&i._["#"];if(!a||!r||a!==_optionalChain([s, 'optionalAccess', _2 => _2.parentDataProperty]))return!1;let l=n.match(a);return l?o.compile(e)(l):!1}},z=(o,t)=>{let e=t&&t.soul&&t.soul.pattern||"",r=new (0, _routeparser2.default)(e);return n=>{let i=n&&n._&&n._["#"]||"",s=r.match(i)||{};return!Object.keys(o).find(a=>a in n?s[a]!==n[o[a]]:!1)}},J=o=>(t,e,r,n)=>o?t["#"]===n:!0;function I({coerceTypes:o=!0,removeAdditional:t=!1,...e}={}){let r=new (0, _ajv2.default)({coerceTypes:o,removeAdditional:t,...e});return r.addKeyword({keyword:"soul",compile:Z(r)}),r.addKeyword({keyword:"edgeMatchesKey",compile:J}),r.addKeyword({keyword:"propsFromSoul",compile:z}),r}function V({init:o=I,id:t="http://example.com/schemas/topgun-schema.json",jsonSchema:e="http://json-schema.org/draft-07/schema#",title:r="TopGun Message Schema",description:n="A defintion for the TopGun wire protocol",definitions:i=Y}={}){let s=[],a=Object.keys(i).reduce((p,c)=>{let d=_optionalChain([p, 'access', _3 => _3[c], 'optionalAccess', _4 => _4.soul, 'optionalAccess', _5 => _5.pattern])||"";if(!d)return p;let y=new (0, _routeparser2.default)(d),M=m=>{let h=m.reduce((k,q)=>k&&k[q],p),L=h&&h.$refs,j=W.match(L||""),E=j&&j.refName,$=E?p[E]:h;return _chunkIRXYP7GMjs.a.call(void 0, $)?$:{}};return s.push(c),g({},p,{[c]:{$async:!0,required:["_",...p&&p[c]&&p[c].required||[]],type:"object",properties:{_:{type:"object",allOf:[{$ref:"#/definitions/TopGunNodeMeta"}],properties:{"#":{$ref:`#/definitions/${c}Soul`},">":{type:"object",properties:Object.keys(M([c,"properties"])).reduce((m,h)=>({...m,[h]:{type:"number"}}),{}),patternProperties:Object.keys(M([c,"patternProperties"])).reduce((m,h)=>({...m,[h]:{type:"number"}}),{})}}}}}},{[`${c}Soul`]:{type:"string",pattern:X(y)}},{[`${c}Edge`]:{type:"object",additionalProperties:!1,properties:{"#":{$ref:`#/definitions/${c}Soul`}},required:["#"]}})},i),l={$id:t,$schema:e,$async:!0,title:r,description:n,anyOf:[{$ref:"#/definitions/TopGunMsg"}],definitions:{TopGunMsg:{$async:!0,type:"object",required:["#"],additionalProperties:!1,properties:{"#":{title:"Message Identifier",description:"This should be a globally unique identifier",type:"string"},"##":{title:"Fast Hash Value?",description:"I have no idea how this is calculated",type:"number"},"@":{title:"Responding To",description:"The message identifier this message is responding to",type:"string"},"><":{title:"Adjacent Peers",description:"Not really sure how this works",type:"string"},$:{title:"??"},I:{title:"??"},ok:{title:"??",description:"Shouldn't actually be sent over wire",type:"boolean"},how:{title:"Used for debugging",description:"Shouldn't actually be sent over wire (but it is)",type:"string"},mesh:{title:"??",description:"Shouldn't be sent over wire"},rad:{title:"??",description:"Shouldn't be sent over wire"},user:{title:"??",description:"I don't think this is supposed to be sent over wire"},err:{anyOf:[{type:"null"},{type:"string"}]},leech:{title:"Leech Command",description:"TopGun protocol extension added by pistol",type:"boolean"},ping:{title:"Ping Command",description:"TopGun protocol extension added by pistol",type:"boolean"},get:{title:"Get Command",description:"A request for graph data",type:"object",additionalProperties:!1,properties:{"#":{description:"The soul to request data for",anyOf:s.map(p=>({$ref:`#/definitions/${p}Soul`}))},".":{description:"Request a single property?",type:"string"}}},put:{anyOf:[{$async:!0,title:"Put Command",description:"A payload of graph data",type:"object",additionalProperties:{anyOf:[...s.map(p=>({$ref:`#/definitions/${p}`})),{type:"null"}]}},{type:"null"}]}}},TopGunChangeStates:{type:"object",title:"TopGun Change States",description:"A map of property names to update timestamps",patternProperties:{".*":{type:"number"}}},TopGunNodeMeta:{title:"TopGun Node Metadata",description:"Change State and soul of a node",type:"object",additionalProperties:!1,properties:{"#":{title:"Soul",type:"string"},">":{$ref:"#/definitions/TopGunChangeStates"}},required:["#",">"]},TopGunEdge:{type:"object",additionalProperties:!1,properties:{"#":{type:"string"}},required:["#"]},...a}},u=o();return u.addSchema({$id:"schema.json",definitions:l.definitions}),{schema:l,validate:u.compile(l)}}var Q=512,ee=128,R="~:authorId",te=new (0, _routeparser2.default)(R),re=new (0, _routeparser2.default)("*stuff~:authorId."),oe={seaAlias:{type:"string",maxLength:Q},SEAAlias:{type:"object",title:"TopGun SEA Alias",$async:!0,soul:{pattern:"~@:alias",properties:{alias:{$ref:"schema.json#/definitions/seaAlias"}},required:["alias"]},additionalProperties:{edgeMatchesKey:!0,anyOf:[{$ref:"#/definitions/SEAAuthorEdge"}]}},seaAuthorId:{type:"string",maxLength:ee},seaAuthObj:{oneOf:[{type:"object",properties:{ek:{type:"object",properties:{ct:{type:"string"},iv:{type:"string"},s:{type:"string"}}},s:{type:"string"}}},{type:"string"}]},SEAAuthor:{type:"object",title:"TopGun SEA Author",$async:!0,properties:{pub:{$ref:"#/definitions/seaAuthorId"},epub:{sea:{type:"string"}},alias:{sea:{$ref:"schema.json#/definitions/seaAlias"}},auth:{sea:{$ref:"schema.json#/definitions/seaAuthObj"}}},additionalProperties:{sea:{anyOf:[{$ref:"schema.json#/definitions/TopGunEdge"},{$ref:"schema.json#/definitions/seaAuthObj"},{type:"null"},{type:"string"},{type:"number"},{type:"boolean"}]}},soul:{pattern:R,properties:{authorId:{$ref:"schema.json#/definitions/seaAuthorId"}},required:["authorId"]}}},ne={type:"object",title:"TopGun SEA Node",description:"Any SEA node supported by TopGun",$async:!0,soul:{pattern:"*path~:authorId.",properties:{path:{type:"string"},authorId:{$ref:"schema.json#/definitions/seaAuthorId"}},required:["path","authorId"]}},ie={...oe,SEANode:ne,...v},se=(o,t,e=!1)=>(console.log("read",{data:o,key:t,pair:e}),Promise.resolve()),ae=o=>(t,e,r,n,i,s)=>{let a=i&&i._&&i._["#"]||"";if(s==="_")return!0;let u=(re.match(a)||te.match(a)||{}).authorId||"";if(!u)return!1;if(a===`~${u}`&&s==="pub")return e===u;let p=o.compile({additionalProperties:!0,properties:{[s]:t}}),c;return se(i,s,u).then(d=>c=d).then(d=>({...i,[s]:d})).catch(d=>(console.error("key err",a,s,u,i[s],d.stack||d),!1)).then(d=>!d||typeof d[s]>"u"?(delete i[s],i&&i._&&i._[">"]&&delete i._[">"],console.error("sea prop err",a,s,c,r),d):Promise.resolve(p(d)).then(y=>(y||console.error("sea validation err",a,s,c,p.errors,r),y)))},pe=o=>{let t=I(o);return t.addKeyword({keyword:"sea",async:!0,modifying:!0,validate:ae(t)}),t},F=()=>V({definitions:ie,init:pe});var _server = require('topgun-socket/server');var w={diffFn:_chunkIRXYP7GMjs.d,mergeFn:_chunkIRXYP7GMjs.f},N=(o,t,e)=>(o.direct?t[e]:_chunkIRXYP7GMjs.b.call(void 0, t[e]))||null,ce=(o,t,e)=>Promise.resolve(N(o,t,e)),H=({diffFn:o=w.diffFn,mergeFn:t=w.mergeFn},e,r)=>{let n=o(r,e);return n&&t(e,n,"mutable"),n||null},de=(o,t,e)=>Promise.resolve(H(o,t,e));function U(o=w){let t={};return{get:e=>ce(o,t,e),getSync:e=>N(o,t,e),put:e=>de(o,t,e),putSync:e=>H(o,t,e)}}var P=class{constructor(t){this.options=t;this.validaror=F(),this.internalAdapter=this.options.adapter||U(),this.adapter=this.wrapAdapter(this.internalAdapter),this.server=new (0, _server.TGServerSocketGateway)(this.options)}run(){this.setInboundMiddleware(new b(this.adapter,this.options)),this.handleWebsocketConnection()}publishDiff(t,e,r){this.server.exchange.invokePublish(`topgun/nodes/${t}`,{"#":`${e}/${t}`,put:{[t]:r}})}wrapAdapter(t){let e={...t,put:async r=>{let n=await t.put(r);return n&&this.publishIsDiff({"#":_chunkIRXYP7GMjs.l.call(void 0, ),put:n}),n},putSync:void 0};return{...e,put:r=>this.validatePut(r).then(n=>{if(n)return e.put(r);throw new Error("Invalid graph data")})}}publishIsDiff(t){let e=t["#"]||_chunkIRXYP7GMjs.u.call(void 0, ),r=t.put;if(r)for(let n in r){if(!n)continue;let i=r[n];i&&this.publishDiff(n,e,i)}}async validatePut(t){return this.options.disableValidation?!0:this.validaror.validate({"#":"dummymsgid",put:t})}async handleWebsocketConnection(){for await(let{socket:t}of this.server.listener("connection"))(async()=>{for await(let e of t.procedure("login"))this.authenticateLogin(t,e)})()}async authenticateLogin(t,e){let r=e.data;if(!r.pub||!r.proof){e.end("Missing login info");return}try{let[n,i]=r.proof.m.split("/"),s=parseInt(i,10),a=new Date().getTime(),l=Math.abs(a-s),u=this.options.authMaxDrift&&parseInt(`${this.options.authMaxDrift}`,10)||1e3*60*5;if(l>u){e.error(new Error("Exceeded max clock drift"));return}if(!n||n!==t.id){e.error(new Error("Socket ID doesn't match"));return}await _chunkIRXYP7GMjs.o.call(void 0, r.proof,r.pub)?(t.setAuthToken({pub:r.pub,timestamp:s}),e.end()):e.end("Invalid login")}catch (e3){e.end("Invalid login")}}setInboundMiddleware(t){t&&this.server.setMiddleware(_server.MIDDLEWARE_INBOUND,async e=>{for await(let r of e)this.handleInboundAction(r,t)})}handleInboundAction(t,e){switch(t.type){case t.AUTHENTICATE:e.onAuthenticate?e.onAuthenticate(t):e.default(t);break;case t.SUBSCRIBE:e.onSubscribe?e.onSubscribe(t):e.default(t);break;case t.TRANSMIT:e.onTransmit?e.onTransmit(t):e.default;break;case t.INVOKE:e.onInvoke?e.onInvoke(t):e.default(t);break;case t.PUBLISH_IN:e.onPublishIn?e.onPublishIn(t):e.default(t);break;default:console.warn(`Not implemented type "${t}"!`),e.default(t)}}};function Ke(o){return new P(o)}exports.TGServer = P; exports.createServer = Ke; | ||
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunkC4KWPA6Zjs = require('./chunk-C4KWPA6Z.js');var A=class{default(t){t.allow()}};var g=class extends A{constructor(e,r){super();this.adapter=e;this.options=r}onPublishIn(e){let r=e.data;if(e.channel!=="topgun/put"){this.isAdmin(e.socket)?e.allow():e.block(new Error("You aren't allowed to write to this channel"));return}e.allow(),!(e.channel!=="topgun/put"||!r||!r.put)&&this.processPut(r).then(n=>{this.publish(e,{channel:`topgun/@${r["#"]}`,data:n})})}async onSubscribe(e){if(e.channel==="topgun/put"&&!this.isAdmin(e.socket)){e.block(new Error(`You aren't allowed to subscribe to ${e.channel}`));return}let r=String(e.channel).replace(/^topgun\/nodes\//,"");if(!r||r===e.channel){e.allow();return}if(e.allow(),r==="changelog")return;let n=_chunkC4KWPA6Zjs.u.call(void 0, );this.readNode(r).then(i=>({channel:e.channel,data:{"#":n,put:i?{[r]:i}:null}})).catch(i=>(console.warn(i.stack||i),{channel:e.channel,data:{"#":n,"@":e.data["#"],err:"Error fetching node"}})).then(i=>{this.publish(e,i)})}default(e){e.allow()}async onAuthenticate(e){e.allow()}readNode(e){return this.adapter.get(e)}isAdmin(e){return e.authToken&&e.authToken.pub===this.options.ownerPub}async processPut(e){let r=_chunkC4KWPA6Zjs.l.call(void 0, );try{return e.put&&await this.adapter.put(e.put),{"#":r,"@":e["#"],err:null,ok:!0}}catch (e2){return{"#":r,"@":e["#"],err:"Error saving",ok:!1}}}publish(e,r){e.socket.transmit("#publish",r,{})}};var _routeparser = require('route-parser'); var _routeparser2 = _interopRequireDefault(_routeparser);var _ajv = require('ajv'); var _ajv2 = _interopRequireDefault(_ajv);var _regexp = require('route-parser/lib/route/visitors/regexp'); var _regexp2 = _interopRequireDefault(_regexp);function b(o,...t){if(!t.length)return o;let e=t.shift();if(_chunkC4KWPA6Zjs.a.call(void 0, o)&&_chunkC4KWPA6Zjs.a.call(void 0, e))for(let r in e)_chunkC4KWPA6Zjs.a.call(void 0, e[r])?(o[r]||Object.assign(o,{[r]:{}}),b(o[r],e[r])):Object.assign(o,{[r]:e[r]});return b(o,...t)}var W=new (0, _routeparser2.default)("#/definitions/:refName");function X(o){let{re:t}=_regexp2.default.visit(o.ast),e=t.toString();return e.slice(1,e.length-1)}var v={Node:{type:"object",title:"Node",description:"Any node supported by TopGun",$async:!0,additionalProperties:{anyOf:[{$ref:"#/definitions/TopGunEdge"},{type:"null"},{type:"string"},{type:"number"},{type:"boolean"},{type:"object"}]},soul:{pattern:"*soul",type:"object",properties:{soul:{type:"string"}},required:["soul"]}}},Y=v,Z=o=>t=>{t=t||{};let e={...t};delete e.pattern;let r=t.pattern||"",n=new (0, _routeparser2.default)(r);return(i,s)=>{let a=i&&i._&&i._["#"];if(!a||!r||a!==_optionalChain([s, 'optionalAccess', _2 => _2.parentDataProperty]))return!1;let l=n.match(a);return l?o.compile(e)(l):!1}},z=(o,t)=>{let e=t&&t.soul&&t.soul.pattern||"",r=new (0, _routeparser2.default)(e);return n=>{let i=n&&n._&&n._["#"]||"",s=r.match(i)||{};return!Object.keys(o).find(a=>a in n?s[a]!==n[o[a]]:!1)}},J=o=>(t,e,r,n)=>o?t["#"]===n:!0;function I({coerceTypes:o=!0,removeAdditional:t=!1,...e}={}){let r=new (0, _ajv2.default)({coerceTypes:o,removeAdditional:t,...e});return r.addKeyword({keyword:"soul",compile:Z(r)}),r.addKeyword({keyword:"edgeMatchesKey",compile:J}),r.addKeyword({keyword:"propsFromSoul",compile:z}),r}function V({init:o=I,id:t="http://example.com/schemas/topgun-schema.json",jsonSchema:e="http://json-schema.org/draft-07/schema#",title:r="TopGun Message Schema",description:n="A defintion for the TopGun wire protocol",definitions:i=Y}={}){let s=[],a=Object.keys(i).reduce((p,c)=>{let d=_optionalChain([p, 'access', _3 => _3[c], 'optionalAccess', _4 => _4.soul, 'optionalAccess', _5 => _5.pattern])||"";if(!d)return p;let y=new (0, _routeparser2.default)(d),M=m=>{let h=m.reduce((k,q)=>k&&k[q],p),L=h&&h.$refs,j=W.match(L||""),E=j&&j.refName,$=E?p[E]:h;return _chunkC4KWPA6Zjs.a.call(void 0, $)?$:{}};return s.push(c),b({},p,{[c]:{$async:!0,required:["_",...p&&p[c]&&p[c].required||[]],type:"object",properties:{_:{type:"object",allOf:[{$ref:"#/definitions/TopGunNodeMeta"}],properties:{"#":{$ref:`#/definitions/${c}Soul`},">":{type:"object",properties:Object.keys(M([c,"properties"])).reduce((m,h)=>({...m,[h]:{type:"number"}}),{}),patternProperties:Object.keys(M([c,"patternProperties"])).reduce((m,h)=>({...m,[h]:{type:"number"}}),{})}}}}}},{[`${c}Soul`]:{type:"string",pattern:X(y)}},{[`${c}Edge`]:{type:"object",additionalProperties:!1,properties:{"#":{$ref:`#/definitions/${c}Soul`}},required:["#"]}})},i),l={$id:t,$schema:e,$async:!0,title:r,description:n,anyOf:[{$ref:"#/definitions/TopGunMsg"}],definitions:{TopGunMsg:{$async:!0,type:"object",required:["#"],additionalProperties:!1,properties:{"#":{title:"Message Identifier",description:"This should be a globally unique identifier",type:"string"},"##":{title:"Fast Hash Value?",description:"I have no idea how this is calculated",type:"number"},"@":{title:"Responding To",description:"The message identifier this message is responding to",type:"string"},"><":{title:"Adjacent Peers",description:"Not really sure how this works",type:"string"},$:{title:"??"},I:{title:"??"},ok:{title:"??",description:"Shouldn't actually be sent over wire",type:"boolean"},how:{title:"Used for debugging",description:"Shouldn't actually be sent over wire (but it is)",type:"string"},mesh:{title:"??",description:"Shouldn't be sent over wire"},rad:{title:"??",description:"Shouldn't be sent over wire"},user:{title:"??",description:"I don't think this is supposed to be sent over wire"},err:{anyOf:[{type:"null"},{type:"string"}]},leech:{title:"Leech Command",description:"TopGun protocol extension",type:"boolean"},ping:{title:"Ping Command",description:"TopGun protocol extension",type:"boolean"},get:{title:"Get Command",description:"A request for graph data",type:"object",additionalProperties:!1,properties:{"#":{description:"The soul to request data for",anyOf:s.map(p=>({$ref:`#/definitions/${p}Soul`}))},".":{description:"Request a single property?",type:"string"}}},put:{anyOf:[{$async:!0,title:"Put Command",description:"A payload of graph data",type:"object",additionalProperties:{anyOf:[...s.map(p=>({$ref:`#/definitions/${p}`})),{type:"null"}]}},{type:"null"}]}}},TopGunChangeStates:{type:"object",title:"TopGun Change States",description:"A map of property names to update timestamps",patternProperties:{".*":{type:"number"}}},TopGunNodeMeta:{title:"TopGun Node Metadata",description:"Change State and soul of a node",type:"object",additionalProperties:!1,properties:{"#":{title:"Soul",type:"string"},">":{$ref:"#/definitions/TopGunChangeStates"}},required:["#",">"]},TopGunEdge:{type:"object",additionalProperties:!1,properties:{"#":{type:"string"}},required:["#"]},...a}},u=o();return u.addSchema({$id:"schema.json",definitions:l.definitions}),{schema:l,validate:u.compile(l)}}var Q=512,ee=128,R="~:authorId",te=new (0, _routeparser2.default)(R),re=new (0, _routeparser2.default)("*stuff~:authorId."),oe={seaAlias:{type:"string",maxLength:Q},SEAAlias:{type:"object",title:"TopGun SEA Alias",$async:!0,soul:{pattern:"~@:alias",properties:{alias:{$ref:"schema.json#/definitions/seaAlias"}},required:["alias"]},additionalProperties:{edgeMatchesKey:!0,anyOf:[{$ref:"#/definitions/SEAAuthorEdge"}]}},seaAuthorId:{type:"string",maxLength:ee},seaAuthObj:{oneOf:[{type:"object",properties:{ek:{type:"object",properties:{ct:{type:"string"},iv:{type:"string"},s:{type:"string"}}},s:{type:"string"}}},{type:"string"}]},SEAAuthor:{type:"object",title:"TopGun SEA Author",$async:!0,properties:{pub:{$ref:"#/definitions/seaAuthorId"},epub:{sea:{type:"string"}},alias:{sea:{$ref:"schema.json#/definitions/seaAlias"}},auth:{sea:{$ref:"schema.json#/definitions/seaAuthObj"}}},additionalProperties:{sea:{anyOf:[{$ref:"schema.json#/definitions/TopGunEdge"},{$ref:"schema.json#/definitions/seaAuthObj"},{type:"null"},{type:"string"},{type:"number"},{type:"boolean"}]}},soul:{pattern:R,properties:{authorId:{$ref:"schema.json#/definitions/seaAuthorId"}},required:["authorId"]}}},ne={type:"object",title:"TopGun SEA Node",description:"Any SEA node supported by TopGun",$async:!0,soul:{pattern:"*path~:authorId.",properties:{path:{type:"string"},authorId:{$ref:"schema.json#/definitions/seaAuthorId"}},required:["path","authorId"]}},ie={...oe,SEANode:ne,...v},se=(o,t,e=!1)=>(console.log("read",{data:o,key:t,pair:e}),Promise.resolve()),ae=o=>(t,e,r,n,i,s)=>{let a=i&&i._&&i._["#"]||"";if(s==="_")return!0;let u=(re.match(a)||te.match(a)||{}).authorId||"";if(!u)return!1;if(a===`~${u}`&&s==="pub")return e===u;let p=o.compile({additionalProperties:!0,properties:{[s]:t}}),c;return se(i,s,u).then(d=>c=d).then(d=>({...i,[s]:d})).catch(d=>(console.error("key err",a,s,u,i[s],d.stack||d),!1)).then(d=>!d||typeof d[s]>"u"?(delete i[s],i&&i._&&i._[">"]&&delete i._[">"],console.error("sea prop err",a,s,c,r),d):Promise.resolve(p(d)).then(y=>(y||console.error("sea validation err",a,s,c,p.errors,r),y)))},pe=o=>{let t=I(o);return t.addKeyword({keyword:"sea",async:!0,modifying:!0,validate:ae(t)}),t},F=()=>V({definitions:ie,init:pe});var _server = require('topgun-socket/server');var w={diffFn:_chunkC4KWPA6Zjs.d,mergeFn:_chunkC4KWPA6Zjs.f},N=(o,t,e)=>(o.direct?t[e]:_chunkC4KWPA6Zjs.b.call(void 0, t[e]))||null,ce=(o,t,e)=>Promise.resolve(N(o,t,e)),H=({diffFn:o=w.diffFn,mergeFn:t=w.mergeFn},e,r)=>{let n=o(r,e);return n&&t(e,n,"mutable"),n||null},de=(o,t,e)=>Promise.resolve(H(o,t,e));function U(o=w){let t={};return{get:e=>ce(o,t,e),getSync:e=>N(o,t,e),put:e=>de(o,t,e),putSync:e=>H(o,t,e)}}var P=class{constructor(t){this.options=t;this.validaror=F(),this.internalAdapter=this.options.adapter||U(),this.adapter=this.wrapAdapter(this.internalAdapter),this.server=new (0, _server.TGServerSocketGateway)(this.options)}run(){this.setInboundMiddleware(new g(this.adapter,this.options)),this.handleWebsocketConnection()}publishDiff(t,e,r){this.server.exchange.invokePublish(`topgun/nodes/${t}`,{"#":`${e}/${t}`,put:{[t]:r}})}wrapAdapter(t){let e={...t,put:async r=>{let n=await t.put(r);return n&&this.publishIsDiff({"#":_chunkC4KWPA6Zjs.l.call(void 0, ),put:n}),n},putSync:void 0};return{...e,put:r=>this.validatePut(r).then(n=>{if(n)return e.put(r);throw new Error("Invalid graph data")})}}publishIsDiff(t){let e=t["#"]||_chunkC4KWPA6Zjs.u.call(void 0, ),r=t.put;if(r)for(let n in r){if(!n)continue;let i=r[n];i&&this.publishDiff(n,e,i)}}async validatePut(t){return this.options.disableValidation?!0:this.validaror.validate({"#":"dummymsgid",put:t})}async handleWebsocketConnection(){for await(let{socket:t}of this.server.listener("connection"))(async()=>{for await(let e of t.procedure("login"))this.authenticateLogin(t,e)})()}async authenticateLogin(t,e){let r=e.data;if(!r.pub||!r.proof){e.end("Missing login info");return}try{let[n,i]=r.proof.m.split("/"),s=parseInt(i,10),a=new Date().getTime(),l=Math.abs(a-s),u=this.options.authMaxDrift&&parseInt(`${this.options.authMaxDrift}`,10)||1e3*60*5;if(l>u){e.error(new Error("Exceeded max clock drift"));return}if(!n||n!==t.id){e.error(new Error("Socket ID doesn't match"));return}await _chunkC4KWPA6Zjs.o.call(void 0, r.proof,r.pub)?(t.setAuthToken({pub:r.pub,timestamp:s}),e.end()):e.end("Invalid login")}catch (e3){e.end("Invalid login")}}setInboundMiddleware(t){t&&this.server.setMiddleware(_server.MIDDLEWARE_INBOUND,async e=>{for await(let r of e)this.handleInboundAction(r,t)})}handleInboundAction(t,e){switch(t.type){case t.AUTHENTICATE:e.onAuthenticate?e.onAuthenticate(t):e.default(t);break;case t.SUBSCRIBE:e.onSubscribe?e.onSubscribe(t):e.default(t);break;case t.TRANSMIT:e.onTransmit?e.onTransmit(t):e.default;break;case t.INVOKE:e.onInvoke?e.onInvoke(t):e.default(t);break;case t.PUBLISH_IN:e.onPublishIn?e.onPublishIn(t):e.default(t);break;default:console.warn(`Not implemented type "${t}"!`),e.default(t)}}};function Ke(o){return new P(o)}exports.TGServer = P; exports.createServer = Ke; |
{ | ||
"name": "topgun", | ||
"version": "1.0.0", | ||
"version": "1.0.2", | ||
"description": "Realtime, offline-first, secure, graph data synchronization engine. Reimplementation of gunDB in TypeScript", | ||
@@ -66,6 +66,6 @@ "publishConfig": { | ||
"dependencies": { | ||
"@peculiar/webcrypto": "^1.4.3", | ||
"ajv": "^8.12.0", | ||
"route-parser": "^0.0.5", | ||
"topgun-socket": "1.0.5" | ||
"topgun-socket": "1.0.5", | ||
"topgun-webcrypto": "^1.0.3" | ||
}, | ||
@@ -72,0 +72,0 @@ "devDependencies": { |
<p align="center"> | ||
<a href="https://github.com/TopGunBuild" target="blank"><img src="https://avatars.githubusercontent.com/u/121893825?s=200&v=4" width="120" alt="TopGun Logo" /></a> | ||
<a href="https://github.com/TopGunBuild/topgun" target="blank"><img src="https://avatars.githubusercontent.com/u/121893825?s=200&v=4" width="120" alt="TopGun Logo" /></a> | ||
</p> | ||
@@ -21,2 +21,12 @@ <h1 align="center" style="border-bottom: none;">🚀 TopGun</h1> | ||
</a> | ||
</p> | ||
</p> | ||
## Installation | ||
```bash | ||
$ npm install topgun --save | ||
``` | ||
## License | ||
TopGun is [MIT licensed](LICENSE). |
import { TGClient } from '../src/client'; | ||
import { dataWalking } from '../src/utils/data-walking'; | ||
@@ -7,12 +6,12 @@ describe('Client', () => { | ||
// it('callback', async () => { | ||
// const key = 'test'; | ||
// | ||
// client.get(key).put({ yo: 'hi' }, async (ack) => { | ||
// expect(ack['#']).toBe(key); | ||
// expect(ack.ok).toBeTruthy(); | ||
// expect(client.graph['_graph'][key]?.yo).toBe('hi'); | ||
// }); | ||
// }); | ||
it('callback', async () => { | ||
const key = 'test'; | ||
client.get(key).put({ yo: 'hi' }, async (ack) => { | ||
expect(ack['#']).toBe(key); | ||
expect(ack.ok).toBeTruthy(); | ||
expect(client.graph['_graph'][key]?.yo).toBe('hi'); | ||
}); | ||
}); | ||
it('save/read number', async () => { | ||
@@ -24,3 +23,2 @@ client | ||
expect(ack.err).toBeFalsy(); | ||
console.log(ack); | ||
client | ||
@@ -30,3 +28,2 @@ .get('a') | ||
.once((data) => { | ||
console.log(client.graph['_graph']); | ||
expect(data).toBe(0); | ||
@@ -73,20 +70,2 @@ }); | ||
}); | ||
it('prepare input data', async () => { | ||
const data = { | ||
y: { | ||
name: 'Billy', | ||
email: 'billy@minigun.tech', | ||
bio: { | ||
date: '27.11.85', | ||
}, | ||
}, | ||
w: 'wall', | ||
}; | ||
const a = dataWalking(data, ['x', 'z']); | ||
console.log(a); | ||
// const b = addMissingState(a); | ||
// const c = flattenGraphData(addMissingState(a)); | ||
}); | ||
}); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
31
655483
3433
+ Addedtopgun-webcrypto@^1.0.3
+ Addedtopgun-webcrypto@1.0.5(transitive)
- Removed@peculiar/webcrypto@^1.4.3