feat: add subscribeToEntry
This commit is contained in:
parent
41274582b9
commit
672b462bbe
|
@ -8,14 +8,16 @@
|
||||||
"name": "@lumeweb/s5-js",
|
"name": "@lumeweb/s5-js",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lumeweb/libs5": "^0.1.0-develop.77",
|
"@lumeweb/libs5": "^0.1.0-develop.78",
|
||||||
"@noble/hashes": "^1.3.2",
|
"@noble/hashes": "^1.3.2",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
|
"isomorphic-ws": "^5.0.0",
|
||||||
"tus-js-client": "^4.0.0",
|
"tus-js-client": "^4.0.0",
|
||||||
"url-join": "^5.0.0"
|
"url-join": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lumeweb/node-library-preset": "^0.2.7",
|
"@lumeweb/node-library-preset": "^0.2.7",
|
||||||
|
"@types/ws": "^8.5.10",
|
||||||
"presetter": "*"
|
"presetter": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1786,9 +1788,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@lumeweb/libs5": {
|
"node_modules/@lumeweb/libs5": {
|
||||||
"version": "0.1.0-develop.77",
|
"version": "0.1.0-develop.78",
|
||||||
"resolved": "https://registry.npmjs.org/@lumeweb/libs5/-/libs5-0.1.0-develop.77.tgz",
|
"resolved": "https://registry.npmjs.org/@lumeweb/libs5/-/libs5-0.1.0-develop.78.tgz",
|
||||||
"integrity": "sha512-CDq5rhFFpLWouHIQCrc+VXO73ZXnIOOq3DoUzHJonqsUpQ2dBOZFJwfkumWVwlHIaEXHbfaRUrq6CCpE86L9vQ==",
|
"integrity": "sha512-7ippBR7x9KbhkEjoMWPYZHJmmVxqeO2LvtAN+gJdj74NiAVujsKC1S3u5sXAeXyHdQ4Grsl8ClUfDumSirkdXg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@noble/curves": "^1.1.0",
|
"@noble/curves": "^1.1.0",
|
||||||
"@noble/hashes": "^1.3.1",
|
"@noble/hashes": "^1.3.1",
|
||||||
|
@ -3513,7 +3515,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
|
||||||
"integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==",
|
"integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~5.26.4"
|
"undici-types": "~5.26.4"
|
||||||
}
|
}
|
||||||
|
@ -3552,6 +3553,15 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ws": {
|
||||||
|
"version": "8.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
|
||||||
|
"integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/yargs": {
|
"node_modules/@types/yargs": {
|
||||||
"version": "17.0.32",
|
"version": "17.0.32",
|
||||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz",
|
||||||
|
@ -9234,6 +9244,14 @@
|
||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/isomorphic-ws": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"ws": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/issue-parser": {
|
"node_modules/issue-parser": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz",
|
||||||
|
@ -19658,8 +19676,7 @@
|
||||||
"version": "5.26.5",
|
"version": "5.26.5",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/unicorn-magic": {
|
"node_modules/unicorn-magic": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"module": "lib/index.js",
|
"module": "lib/index.js",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lumeweb/node-library-preset": "^0.2.7",
|
"@lumeweb/node-library-preset": "^0.2.7",
|
||||||
|
"@types/ws": "^8.5.10",
|
||||||
"presetter": "*"
|
"presetter": "*"
|
||||||
},
|
},
|
||||||
"readme": "ERROR: No README data found!",
|
"readme": "ERROR: No README data found!",
|
||||||
|
@ -15,9 +16,10 @@
|
||||||
"semantic-release": "semantic-release"
|
"semantic-release": "semantic-release"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lumeweb/libs5": "^0.1.0-develop.77",
|
"@lumeweb/libs5": "^0.1.0-develop.78",
|
||||||
"@noble/hashes": "^1.3.2",
|
"@noble/hashes": "^1.3.2",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
|
"isomorphic-ws": "^5.0.0",
|
||||||
"tus-js-client": "^4.0.0",
|
"tus-js-client": "^4.0.0",
|
||||||
"url-join": "^5.0.0"
|
"url-join": "^5.0.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,6 +24,7 @@ import {
|
||||||
ExecuteRequestError,
|
ExecuteRequestError,
|
||||||
Headers,
|
Headers,
|
||||||
} from "./request.js";
|
} from "./request.js";
|
||||||
|
import { subscribeToEntry } from "./methods/registry.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom client options.
|
* Custom client options.
|
||||||
|
@ -125,6 +126,9 @@ export class S5Client {
|
||||||
getCidUrl = getCidUrl;
|
getCidUrl = getCidUrl;
|
||||||
getMetadata = getMetadata;
|
getMetadata = getMetadata;
|
||||||
|
|
||||||
|
// Registry
|
||||||
|
subscribeToEntry = subscribeToEntry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The S5 Client which can be used to access S5-net.
|
* The S5 Client which can be used to access S5-net.
|
||||||
*
|
*
|
||||||
|
@ -268,36 +272,6 @@ export class S5Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===============
|
|
||||||
// Private Methods
|
|
||||||
// ===============
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current server URL for the portal. You should generally use
|
|
||||||
* `portalUrl` instead - this method can be used for detecting whether the
|
|
||||||
* current URL is a server URL.
|
|
||||||
*
|
|
||||||
* @returns - The portal server URL.
|
|
||||||
*/
|
|
||||||
protected async resolvePortalServerUrl(): Promise<string> {
|
|
||||||
const response = await this.executeRequest({
|
|
||||||
...this.customOptions,
|
|
||||||
method: "head",
|
|
||||||
url: this.initialPortalUrl,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.headers) {
|
|
||||||
throw new Error(
|
|
||||||
"Did not get 'headers' in response despite a successful request. Please try again and report this issue to the devs if it persists.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const portalUrl = response.headers["s5-server-api"];
|
|
||||||
if (!portalUrl) {
|
|
||||||
throw new Error("Could not get server portal URL for the given portal");
|
|
||||||
}
|
|
||||||
return portalUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a request to resolve the provided `initialPortalUrl`.
|
* Make a request to resolve the provided `initialPortalUrl`.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { DEFAULT_BASE_OPTIONS } from "../utils/options.js";
|
||||||
|
import { CustomClientOptions, S5Client } from "../client.js";
|
||||||
|
import { ensureBytes } from "@noble/curves/abstract/utils";
|
||||||
|
|
||||||
|
import WS from "isomorphic-ws";
|
||||||
|
import { buildRequestUrl } from "#request.js";
|
||||||
|
import { Packer, SignedRegistryEntry } from "@lumeweb/libs5";
|
||||||
|
import { deserializeRegistryEntry } from "@lumeweb/libs5/lib/service/registry.js";
|
||||||
|
import { Buffer } from "buffer";
|
||||||
|
export const DEFAULT_GET_ENTRY_OPTIONS = {
|
||||||
|
...DEFAULT_BASE_OPTIONS,
|
||||||
|
endpointGetEntry: "/s5/registry",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_SET_ENTRY_OPTIONS = {
|
||||||
|
...DEFAULT_BASE_OPTIONS,
|
||||||
|
endpointSetEntry: "/s5/registry",
|
||||||
|
deleteForever: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_SUBSCRIBE_ENTRY_OPTIONS = {
|
||||||
|
...DEFAULT_BASE_OPTIONS,
|
||||||
|
endpointSubscribeEntry: "/s5/registry/subscription",
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BaseCustomOptions = CustomClientOptions;
|
||||||
|
|
||||||
|
export type CustomRegistryOptions = BaseCustomOptions & {
|
||||||
|
endpointSubscribeEntry?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function subscribeToEntry(
|
||||||
|
this: S5Client,
|
||||||
|
publicKey: Uint8Array,
|
||||||
|
customOptions?: CustomRegistryOptions,
|
||||||
|
) {
|
||||||
|
const opts = {
|
||||||
|
...DEFAULT_SUBSCRIBE_ENTRY_OPTIONS,
|
||||||
|
...this.customOptions,
|
||||||
|
...customOptions,
|
||||||
|
};
|
||||||
|
|
||||||
|
publicKey = ensureBytes("public key", publicKey, 32);
|
||||||
|
|
||||||
|
const url = await buildRequestUrl(this, {
|
||||||
|
baseUrl: await this.portalUrl(),
|
||||||
|
endpointPath: opts.endpointSubscribeEntry,
|
||||||
|
});
|
||||||
|
|
||||||
|
const socket = new WS(url);
|
||||||
|
|
||||||
|
socket.once("open", () => {
|
||||||
|
const packer = new Packer();
|
||||||
|
packer.pack(2);
|
||||||
|
packer.pack(publicKey);
|
||||||
|
|
||||||
|
socket.send(packer.takeBytes());
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
listen(cb: (entry: SignedRegistryEntry) => void) {
|
||||||
|
socket.on("message", (data) => {
|
||||||
|
cb(deserializeRegistryEntry(new Uint8Array(data as Buffer)));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
end() {
|
||||||
|
if ([socket.CLOSING, socket.CLOSED].includes(socket.readyState as any)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
socket.close();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue