Compare commits

...

96 Commits

Author SHA1 Message Date
semantic-release-bot 14e3df654a chore(release): 0.0.2-develop.1 [skip ci]
## [0.0.2-develop.1](https://git.lumeweb.com/LumeWeb/hyperswarm-web/compare/v0.0.1...v0.0.2-develop.1) (2023-07-01)

### Reverts

* Revert "*Store copy of activeRelay size to prevent infinite loop" ([cb16b87](cb16b87b73))
2023-07-01 06:35:27 +00:00
Derrick Hammer 743e76bcf1
refactor: use new sdks 2023-07-01 02:34:18 -04:00
Derrick Hammer 6a6f460967
*Update dist 2023-03-29 14:57:31 -04:00
Derrick Hammer e95b366ea4
*Use just acquire not waitForUnlock 2023-03-29 14:57:18 -04:00
Derrick Hammer 276da74eb5
*Update dist 2023-03-29 14:50:42 -04:00
Derrick Hammer b6dda4dd5e
*Ensure we release the mutex before aborting if we have an active relay 2023-03-29 14:50:24 -04:00
Derrick Hammer 4b6ab61da5
*Update dist 2023-03-19 13:23:20 -04:00
Derrick Hammer 9102cc77d5
*Add offSelf and onceSelf 2023-03-19 13:23:07 -04:00
Derrick Hammer f5d93fe03d
*Update dist 2023-03-19 12:00:17 -04:00
Derrick Hammer b3e0722364
*Add close event for when the relay connection closes 2023-03-19 12:00:00 -04:00
Derrick Hammer e48440710e
*Update dist 2023-02-17 22:23:06 -05:00
Derrick Hammer 42f0c1b60d
*Add onSelf and emitSelf methods to use local event emitter
*Emit local init before processing queued actions
2023-02-17 22:22:46 -05:00
Derrick Hammer 8427cbdff6
*Update dist 2023-02-17 16:32:55 -05:00
Derrick Hammer e8a44315a8
*Need to hook to the stream directly 2023-02-17 16:32:39 -05:00
Derrick Hammer 411582ef05
*Update dist 2023-02-17 08:04:33 -05:00
Derrick Hammer 439bd9f022
*Add ready property 2023-02-17 08:04:16 -05:00
Derrick Hammer 343fda1172
*Update dist 2023-02-05 14:03:09 -05:00
Derrick Hammer 701a3190ae
*Convert more api methods to use _processOrQueueAction 2023-02-05 14:02:53 -05:00
Derrick Hammer b4e406b468
*Update dist 2023-02-01 13:45:36 -05:00
Derrick Hammer 5bdbf77971
*Add public api methods from hyperswarm 2023-02-01 13:45:21 -05:00
Derrick Hammer 511185e921
*Update deps 2023-02-01 13:14:06 -05:00
Derrick Hammer 2a4806b0b3
*Update dist 2023-02-01 08:36:58 -05:00
Derrick Hammer fb13e6e323
*Add getter for activeRelay 2023-02-01 08:36:43 -05:00
Derrick Hammer 400d768fe8
*Update dist 2023-02-01 08:31:06 -05:00
Derrick Hammer c7fd7f294b
*Emit the ready event after successful init 2023-02-01 08:29:35 -05:00
Derrick Hammer 50aa507410
*Update dist 2023-02-01 08:22:47 -05:00
Derrick Hammer 249311c522
*Rename ready to init 2023-02-01 08:22:30 -05:00
Derrick Hammer a1afba565e
*Update dist 2023-02-01 08:15:36 -05:00
Derrick Hammer 9d14579ae9
*Add a mutex lock so we are only ever attempting 1 bootup at a time
*Only try to process relays when we have one
2023-02-01 08:15:16 -05:00
Derrick Hammer 5a49d74b77
*Update dist 2023-02-01 05:01:12 -05:00
Derrick Hammer af76d85983
*Need to wrap DhtNode in a hyperswarm instance 2023-02-01 05:00:51 -05:00
Derrick Hammer 17ca564f43
*dht-relay ready is on the main object, dht object does not exist 2023-02-01 04:57:22 -05:00
Derrick Hammer 9ae03e12e2
*Update dist 2023-02-01 04:51:05 -05:00
Derrick Hammer 5472397958
*Need to pass arguments as a spread 2023-02-01 04:50:55 -05:00
Derrick Hammer 6a843447b1
*Update dist 2023-02-01 04:42:29 -05:00
Derrick Hammer cc7c7c8edf
*Only run loop while this._activeRelay is not set 2023-02-01 04:41:45 -05:00
Derrick Hammer 21fb795488
*Update dist 2023-01-31 08:49:16 -05:00
Derrick Hammer 9b815444e1
*If discover returns false, treat like an error 2023-01-31 08:48:47 -05:00
Derrick Hammer 2b836207ab
*Update @lumeweb/kernel-peer-discovery-client 2023-01-31 08:15:18 -05:00
Derrick Hammer 47ab88f56f
*Update deps 2023-01-31 08:07:14 -05:00
Derrick Hammer f20aafe52e
*Update @lumeweb/libkernel-universal 2023-01-31 07:49:54 -05:00
Derrick Hammer f597e56285
*Update @lumeweb/libkernel-universal 2023-01-31 07:43:55 -05:00
Derrick Hammer ce8edbdaa0
*Update dist 2023-01-31 07:39:11 -05:00
Derrick Hammer 5073788529
*only use RNG if we have more than 1 relay available 2023-01-31 07:38:48 -05:00
Derrick Hammer 929b64cc1d
*Update @lumeweb/kernel-peer-discovery-client 2023-01-31 07:24:09 -05:00
Derrick Hammer e61bd06454
*Update dist 2023-01-31 06:58:39 -05:00
Derrick Hammer 281121b7cc
*Add basic eventemitter action queue to process once we have an active relay, or to immediately process if we already have one 2023-01-31 06:58:03 -05:00
Derrick Hammer bd82046a94
*Update dist 2023-01-31 05:43:58 -05:00
Derrick Hammer e2ab0b8e91
*Switch to eventemitter2 2023-01-31 05:43:29 -05:00
Derrick Hammer a41e162b1d
*Update dist 2023-01-31 05:10:34 -05:00
Derrick Hammer 35e394fec4
*rewrite for new design 2023-01-31 05:10:12 -05:00
Derrick Hammer f8b5bcab64
*update dist 2022-08-14 07:25:37 -04:00
Derrick Hammer 5276de4363
*add getter to return relay servers 2022-08-14 07:25:16 -04:00
Derrick Hammer 8c30190a78
*Update dist 2022-08-13 20:05:01 -04:00
Derrick Hammer f6bcc8ecdb
*Delete relay from active list when the raw stream/websocket closes
*Attempt to refill and reconnect to relays if we have 0 active relays in the pool
2022-08-13 20:04:35 -04:00
Derrick Hammer 0120b67c59
*move away from node Buffer 2022-08-13 20:02:51 -04:00
Derrick Hammer c8e320d798 *Update dist 2022-07-27 00:37:44 -04:00
Derrick Hammer 21bcebb689 *Only choose a random index if we have more than 1 relay 2022-07-27 00:37:30 -04:00
Derrick Hammer 7633e000e6 *Update dist 2022-07-27 00:12:49 -04:00
Derrick Hammer 3f843b5266 *If server is not available, remove from the available array and call removeRelay. 2022-07-27 00:12:41 -04:00
Derrick Hammer ad062df383 *Update dist 2022-07-27 00:05:42 -04:00
Derrick Hammer 3864465ba2 *isServerAvailable is async 2022-07-27 00:05:28 -04:00
Derrick Hammer 3cf6738850 *Update dist 2022-07-27 00:00:04 -04:00
Derrick Hammer 1090b203dc *Handle available only having 1 item 2022-07-26 23:59:45 -04:00
Derrick Hammer 7a12d7e4cd *Update dist 2022-07-26 23:28:47 -04:00
Derrick Hammer cb139131e1 *Call updateAvailable in loop
*Check available length and abort and return if empty
2022-07-26 23:28:12 -04:00
Derrick Hammer 00b0fe29f3 *Update dist 2022-07-26 23:22:34 -04:00
Derrick Hammer 5f37b74baf *Try to update the available list every loop and only compare max _activeRelays against the min of _maxConnections and available 2022-07-26 23:22:10 -04:00
Derrick Hammer cb16b87b73 Revert "*Store copy of activeRelay size to prevent infinite loop"
This reverts commit 7cb32b716a.
2022-07-26 23:13:30 -04:00
Derrick Hammer 58ba247740 Revert "*Update dist"
This reverts commit 8ebaa2a5a5.
2022-07-26 23:13:30 -04:00
Derrick Hammer 8ebaa2a5a5 *Update dist 2022-07-26 23:09:44 -04:00
Derrick Hammer 7cb32b716a *Store copy of activeRelay size to prevent infinite loop 2022-07-26 23:09:25 -04:00
Derrick Hammer 8ee4df8d1b *Update dist 2022-07-26 23:00:19 -04:00
Derrick Hammer ce575b623c *cast to string 2022-07-26 22:58:24 -04:00
Derrick Hammer 007b9a09d7 *Fix usage of connection 2022-07-26 22:56:49 -04:00
Derrick Hammer b4962e994b *Update dist 2022-07-26 22:50:55 -04:00
Derrick Hammer 8d4be6ec4a *Using wrong map 2022-07-26 22:49:46 -04:00
Derrick Hammer 83692b8225 *Update dist 2022-07-26 21:47:13 -04:00
Derrick Hammer b52bdcdeb2 *check for 0, not less than 0 2022-07-26 21:46:58 -04:00
Derrick Hammer fe09e2a5d9 *add negative condition 2022-07-26 21:46:24 -04:00
Derrick Hammer ec291909c4 *Update dist 2022-07-26 21:39:51 -04:00
Derrick Hammer 2e71082a59 *prettier 2022-07-26 21:39:32 -04:00
Derrick Hammer c7b64064ad *_relays is a map 2022-07-26 21:39:16 -04:00
Derrick Hammer 377b9548cf *Prevent ready from running fillConnections twice 2022-07-26 21:38:05 -04:00
Derrick Hammer 35eed2a157 *Abort if no available relays to process 2022-07-26 21:36:30 -04:00
Derrick Hammer a0ecea1dc9 *Update dist 2022-07-26 19:28:53 -04:00
Derrick Hammer 685bc59894 *Refactor to use persistent websocket connections, randomly (secure) picked, then load balance connect requests the same way 2022-07-26 19:27:59 -04:00
Derrick Hammer 918c49f146 *Set custodial to false 2022-07-21 14:58:32 -04:00
Derrick Hammer b2f2c7e9f0 *Update dist 2022-07-20 02:06:55 -04:00
Derrick Hammer f2e6e36783 *Remove tsup 2022-07-20 02:06:21 -04:00
Derrick Hammer 83a7dcd64f *Update dist 2022-07-20 01:59:16 -04:00
Derrick Hammer 0325d4488f *Add tsup 2022-07-20 01:58:34 -04:00
Derrick Hammer 615b3fcc0c *add deps
*add main
2022-07-20 01:56:25 -04:00
Derrick Hammer 2c197cdeef *refactor
*remove wspool
*reformat
2022-07-20 01:55:44 -04:00
Derrick Hammer 428e8b3160 *add dist 2022-06-27 18:22:53 -04:00
Derrick Hammer 915d15a9dc *Initial version 2022-06-27 18:22:38 -04:00
7 changed files with 19198 additions and 1 deletions

13
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: Build/Publish
on:
push:
branches:
- master
- develop
- develop-*
jobs:
main:
uses: lumeweb/github-node-deploy-workflow/.github/workflows/main.yml@master
secrets: inherit

3
.presetterrc.json Normal file
View File

@ -0,0 +1,3 @@
{
"preset": ["@lumeweb/node-library-preset"]
}

6
CHANGELOG.md Normal file
View File

@ -0,0 +1,6 @@
## [0.0.2-develop.1](https://git.lumeweb.com/LumeWeb/hyperswarm-web/compare/v0.0.1...v0.0.2-develop.1) (2023-07-01)
### Reverts
* Revert "*Store copy of activeRelay size to prevent infinite loop" ([cb16b87](https://git.lumeweb.com/LumeWeb/hyperswarm-web/commit/cb16b87b73e104aa2e6ad3dad1b827cb0a85243a))

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 Lume Web
Copyright (c) 2022 Hammer Technologies LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

18861
npm-shrinkwrap.json generated Normal file

File diff suppressed because it is too large Load Diff

43
package.json Normal file
View File

@ -0,0 +1,43 @@
{
"name": "@lumeweb/hyperswarm-web",
"type": "module",
"version": "0.0.2-develop.1",
"main": "lib/index.js",
"repository": {
"type": "git",
"url": "gitea@git.lumeweb.com:LumeWeb/hyperswarm-web.git"
},
"scripts": {
"prepare": "presetter bootstrap",
"build": "run build",
"semantic-release": "semantic-release"
},
"devDependencies": {
"@lumeweb/node-library-preset": "^0.2.5",
"@types/random-number-csprng": "^1.0.0",
"@types/ws": "^8.5.5",
"async-mutex": "^0.4.0",
"esbuild": "^0.14.54",
"eventemitter2": "^6.4.9",
"hyperswarm": "^4.5.1",
"presetter": "*",
"prettier": "^2.8.8",
"rimraf": "^3.0.2",
"typescript": "^4.9.5"
},
"dependencies": {
"@hyperswarm/dht-relay": "^0.4.1",
"@lumeweb/kernel-peer-discovery-client": "^0.0.2-develop.1",
"@lumeweb/libkernel": "^0.1.0-develop.6",
"async-mutex": "^0.4.0",
"eventemitter2": "^6.4.9",
"hyperswarm": "^4.5.1"
},
"readme": "ERROR: No README data found!",
"files": [
"lib/**"
],
"publishConfig": {
"access": "public"
}
}

271
src/index.ts Normal file
View File

@ -0,0 +1,271 @@
// @ts-ignore
import DhtNode from "@hyperswarm/dht-relay";
// @ts-ignore
import Stream from "@hyperswarm/dht-relay/ws";
import { createClient } from "@lumeweb/kernel-peer-discovery-client";
import type {
PeerDiscoveryClient,
Peer,
} from "@lumeweb/kernel-peer-discovery-client";
// @ts-ignore
import Hyperswarm from "hyperswarm";
import randomNumber from "random-number-csprng";
import EventEmitter, { OnOptions } from "eventemitter2";
import { Mutex } from "async-mutex";
import { logErr } from "@lumeweb/libkernel";
export default class HyperswarmWeb extends EventEmitter.default {
private _options: any;
private _discovery: PeerDiscoveryClient;
private _queuedEmActions: [string, any][] = [];
private _connectionMutex: Mutex = new Mutex();
constructor(opts: any = {}) {
super();
opts.custodial = false;
this._options = opts;
this._discovery = createClient();
}
private _relays: Set<string> = new Set();
get relays(): string[] {
return [...this._relays.values()];
}
private _activeRelay: Hyperswarm;
get activeRelay(): Hyperswarm {
return this._activeRelay;
}
private _ready = false;
get ready(): boolean {
return this._ready;
}
init(): Promise<void> {
return this.ensureConnection();
}
async connect(pubkey: string, options = {}): Promise<DhtNode> {
if (!this._activeRelay) {
await this.ensureConnection();
}
return this._activeRelay.connect(pubkey, options);
}
public async addRelay(pubkey: string): Promise<void> {
this._relays.add(pubkey);
}
public removeRelay(pubkey: string): boolean {
if (!this._relays.has(pubkey)) {
return false;
}
this._relays.delete(pubkey);
return true;
}
public clearRelays(): void {
this._relays.clear();
}
on(
eventName: string | symbol,
listener: (...args: any[]) => void,
): Hyperswarm {
return this._processOrQueueAction("on", ...arguments);
}
onSelf(
eventName: string | symbol,
listener: (...args: any[]) => void,
options?: boolean | OnOptions,
): Hyperswarm {
return super.on(eventName, listener, options);
}
addListener(
eventName: string | symbol,
listener: (...args: any[]) => void,
): this {
return this.on(eventName, listener);
}
off(
eventName: string | symbol,
listener: (...args: any[]) => void,
): Hyperswarm {
return this._processOrQueueAction("off", ...arguments);
}
offSelf(
eventName: string | symbol,
listener: (...args: any[]) => void,
): Hyperswarm {
return super.off(eventName, listener);
}
removeListener(
eventName: string | symbol,
listener: (...args: any[]) => void,
): this {
return this.off(eventName, listener);
}
emit(eventName: string | symbol, ...args: any[]): boolean {
return this._processOrQueueAction("emit", ...arguments);
}
emitSelf(eventName: string | symbol, ...args: any[]): boolean {
return super.emit(eventName, ...args);
}
once(eventName: string | symbol, listener: (...args: any[]) => void): this {
return this._processOrQueueAction("once", ...arguments);
}
onceSelf(
eventName: string | symbol,
listener: (...args: any[]) => void,
): this {
return this.once(eventName, listener);
}
public join(topic: Uint8Array, opts = {}): void {
return this._processOrQueueAction("join", ...arguments);
}
public joinPeer(publicKey: Uint8Array): void {
return this._processOrQueueAction("joinPeer", ...arguments);
}
public leave(topic: Uint8Array): void {
return this._processOrQueueAction("leave", ...arguments);
}
public leavePeer(publicKey: Uint8Array): void {
return this._processOrQueueAction("leavePeer", ...arguments);
}
public status(publicKey: Uint8Array) {
return this._activeRelay?.status(publicKey);
}
public topics(): string[] {
return this._activeRelay?.topics();
}
public async flush(): Promise<any> {
return this._activeRelay?.flush();
}
public async clear(): Promise<any> {
return this._activeRelay?.clear();
}
private async ensureConnection(): Promise<any> {
await this._connectionMutex.acquire();
if (this._activeRelay) {
this._connectionMutex.release();
return;
}
const relays = this.relays;
if (relays.length > 0) {
do {
const index =
relays.length > 1 ? await randomNumber(0, relays.length - 1) : 0;
const relay = relays[index];
let ret;
try {
ret = await this._discovery.discover(relay);
} catch (e) {
logErr(e);
relays.splice(index, 1);
continue;
}
if (!ret) {
relays.splice(index, 1);
continue;
}
ret = ret as Peer;
const connection = `wss://${ret.host}:${ret.port}`;
if (!(await this.isServerAvailable(connection))) {
relays.splice(index, 1);
continue;
}
this._activeRelay = new Hyperswarm({
dht: new DhtNode(
new Stream(true, new WebSocket(connection)),
this._options,
),
keyPair: this._options.keyPair,
});
this._activeRelay.dht._protocol._stream.once("close", () => {
this._activeRelay = undefined;
this._ready = false;
this.emitSelf("close");
});
} while (relays.length > 0 && !this._activeRelay);
}
if (!this._activeRelay) {
this._connectionMutex.release();
throw new Error("Failed to find an available relay");
}
this.emitSelf("init");
this._processQueuedActions();
await this._activeRelay.dht.ready();
this._connectionMutex.release();
this._ready = true;
this.emit("ready");
}
private async isServerAvailable(connection: string): Promise<boolean> {
return new Promise<boolean>((resolve) => {
const ws = new WebSocket(connection);
ws.addEventListener("open", () => {
ws.close();
resolve(true);
});
ws.addEventListener("error", () => {
resolve(false);
});
});
}
private _processOrQueueAction(method: string, ...args: any[]) {
if (this._activeRelay) {
return this._activeRelay[method](...args);
}
this._queuedEmActions.push([method, args]);
return this;
}
private _processQueuedActions(): void {
for (const action of this._queuedEmActions) {
this._activeRelay[action[0]](...action[1]);
}
this._queuedEmActions = [];
}
}