feat: add subscribeToEntry
This commit is contained in:
parent
41274582b9
commit
672b462bbe
|
@ -8,14 +8,16 @@
|
|||
"name": "@lumeweb/s5-js",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@lumeweb/libs5": "^0.1.0-develop.77",
|
||||
"@lumeweb/libs5": "^0.1.0-develop.78",
|
||||
"@noble/hashes": "^1.3.2",
|
||||
"axios": "^1.6.2",
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"tus-js-client": "^4.0.0",
|
||||
"url-join": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lumeweb/node-library-preset": "^0.2.7",
|
||||
"@types/ws": "^8.5.10",
|
||||
"presetter": "*"
|
||||
}
|
||||
},
|
||||
|
@ -1786,9 +1788,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@lumeweb/libs5": {
|
||||
"version": "0.1.0-develop.77",
|
||||
"resolved": "https://registry.npmjs.org/@lumeweb/libs5/-/libs5-0.1.0-develop.77.tgz",
|
||||
"integrity": "sha512-CDq5rhFFpLWouHIQCrc+VXO73ZXnIOOq3DoUzHJonqsUpQ2dBOZFJwfkumWVwlHIaEXHbfaRUrq6CCpE86L9vQ==",
|
||||
"version": "0.1.0-develop.78",
|
||||
"resolved": "https://registry.npmjs.org/@lumeweb/libs5/-/libs5-0.1.0-develop.78.tgz",
|
||||
"integrity": "sha512-7ippBR7x9KbhkEjoMWPYZHJmmVxqeO2LvtAN+gJdj74NiAVujsKC1S3u5sXAeXyHdQ4Grsl8ClUfDumSirkdXg==",
|
||||
"dependencies": {
|
||||
"@noble/curves": "^1.1.0",
|
||||
"@noble/hashes": "^1.3.1",
|
||||
|
@ -3513,7 +3515,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
|
||||
"integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
|
@ -3552,6 +3553,15 @@
|
|||
"dev": 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": {
|
||||
"version": "17.0.32",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz",
|
||||
|
@ -9234,6 +9244,14 @@
|
|||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"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": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz",
|
||||
|
@ -19658,8 +19676,7 @@
|
|||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/unicorn-magic": {
|
||||
"version": "0.1.0",
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"module": "lib/index.js",
|
||||
"devDependencies": {
|
||||
"@lumeweb/node-library-preset": "^0.2.7",
|
||||
"@types/ws": "^8.5.10",
|
||||
"presetter": "*"
|
||||
},
|
||||
"readme": "ERROR: No README data found!",
|
||||
|
@ -15,9 +16,10 @@
|
|||
"semantic-release": "semantic-release"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lumeweb/libs5": "^0.1.0-develop.77",
|
||||
"@lumeweb/libs5": "^0.1.0-develop.78",
|
||||
"@noble/hashes": "^1.3.2",
|
||||
"axios": "^1.6.2",
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"tus-js-client": "^4.0.0",
|
||||
"url-join": "^5.0.0"
|
||||
},
|
||||
|
|
|
@ -24,6 +24,7 @@ import {
|
|||
ExecuteRequestError,
|
||||
Headers,
|
||||
} from "./request.js";
|
||||
import { subscribeToEntry } from "./methods/registry.js";
|
||||
|
||||
/**
|
||||
* Custom client options.
|
||||
|
@ -125,6 +126,9 @@ export class S5Client {
|
|||
getCidUrl = getCidUrl;
|
||||
getMetadata = getMetadata;
|
||||
|
||||
// Registry
|
||||
subscribeToEntry = subscribeToEntry;
|
||||
|
||||
/**
|
||||
* 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`.
|
||||
*
|
||||
|
|
|
@ -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