@simplito/privmx-webendpoint
Version:
PrivMX Web Endpoint library
283 lines (280 loc) • 11.5 kB
JavaScript
;
/*!
PrivMX Web Endpoint.
Copyright © 2024 Simplito sp. z o.o.
This file is part of the PrivMX Platform (https://privmx.dev).
This software is Licensed under the PrivMX Free License.
See the License for the specific language governing permissions and
limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.EndpointFactory = void 0;
const Api_1 = require("../api/Api");
const ApiStatic_1 = require("../api/ApiStatic");
const ConnectionNative_1 = require("../api/ConnectionNative");
const CryptoApiNative_1 = require("../api/CryptoApiNative");
const EventApiNative_1 = require("../api/EventApiNative");
const EventQueueNative_1 = require("../api/EventQueueNative");
const InboxApiNative_1 = require("../api/InboxApiNative");
const KvdbApiNative_1 = require("../api/KvdbApiNative");
const StoreApiNative_1 = require("../api/StoreApiNative");
const StreamApiNative_1 = require("../api/StreamApiNative");
const ThreadApiNative_1 = require("../api/ThreadApiNative");
const FinalizationHelper_1 = require("../FinalizationHelper");
const WebRtcClient_1 = require("../webStreams/WebRtcClient");
const Connection_1 = require("./Connection");
const CryptoApi_1 = require("./CryptoApi");
const EventApi_1 = require("./EventApi");
const EventQueue_1 = require("./EventQueue");
const InboxApi_1 = require("./InboxApi");
const KvdbApi_1 = require("./KvdbApi");
const StoreApi_1 = require("./StoreApi");
const StreamApi_1 = require("./StreamApi");
const ThreadApi_1 = require("./ThreadApi");
/**
* Contains static factory methods - generators for Connection and APIs.
*/
class EndpointFactory {
static api;
static eventQueueInstance;
static assetsBasePath;
/**
* Load the Endpoint's WASM assets and initialize the Endpoint library.
*
* @param {string} [assetsBasePath] base path/url to the Endpoint's WebAssembly assets (like: endpoint-wasm-module.js, driver-web-context.js and others)
*/
static async setup(assetsBasePath) {
const basePath = this.resolveAssetsBasePath(assetsBasePath);
this.assetsBasePath = basePath;
const assets = ["driver-web-context.js", "endpoint-wasm-module.js"];
for (const asset of assets) {
await this.loadScript(this.buildAssetUrl(basePath, asset));
}
const lib = await endpointWasmModule();
EndpointFactory.init(lib);
}
static resolveAssetsBasePath(assetsBasePath) {
if (assetsBasePath != null) {
return this.normalizeBasePath(assetsBasePath);
}
return "/";
}
static normalizeBasePath(path) {
const trimmed = path.trim();
if (trimmed === "" || trimmed === "/") {
return "/";
}
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(trimmed)) {
return trimmed.replace(/\/+$/, "");
}
const resolved = new URL(trimmed.replace(/\/+$/, "") + "/", document.baseURI).href;
return resolved.replace(/\/+$/, "");
}
static buildAssetUrl(basePath, asset) {
const fileName = asset.replace(/^\/+/, "");
if (basePath === "/") {
return `/${fileName}`;
}
return new URL(fileName, basePath.endsWith("/") ? basePath : `${basePath}/`).href;
}
static async loadScript(url) {
return new Promise((resolve) => {
const head = document.getElementsByTagName("head")[0];
const script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
script.onload = () => {
resolve();
};
head.appendChild(script);
});
}
/**
* //doc-gen:ignore
*/
static init(lib) {
this.api = new Api_1.Api(lib);
ApiStatic_1.ApiStatic.init(this.api);
FinalizationHelper_1.FinalizationHelper.init(lib);
}
/**
* Gets the EventQueue instance.
*
* @returns {EventQueue} instance of EventQueue
*/
static async getEventQueue() {
if (!this.eventQueueInstance) {
const nativeApi = new EventQueueNative_1.EventQueueNative(this.api);
const ptr = await nativeApi.newEventQueue();
this.eventQueueInstance = new EventQueue_1.EventQueue(nativeApi, ptr);
}
return this.eventQueueInstance;
}
static generateDefaultPKIVerificationOptions() {
return {
bridgeInstanceId: undefined,
bridgePubKey: undefined,
};
}
/**
* Connects to the platform backend.
*
* @param {string} userPrivKey user's private key
* @param {string} solutionId ID of the Solution
* @param {string} bridgeUrl the Bridge Server URL
* @param {PKIVerificationOptions} [verificationOptions] PrivMX Bridge server instance verification options using a PKI server
* @returns {Connection} instance of Connection
*/
static async connect(userPrivKey, solutionId, bridgeUrl, verificationOptions) {
const nativeApi = new ConnectionNative_1.ConnectionNative(this.api);
const ptr = await nativeApi.newConnection();
await nativeApi.connect(ptr, [
userPrivKey,
solutionId,
bridgeUrl,
verificationOptions || this.generateDefaultPKIVerificationOptions(),
]);
return new Connection_1.Connection(nativeApi, ptr);
}
/**
* Connects to the Platform backend as a guest user.
*
* @param {string} solutionId ID of the Solution
* @param {string} bridgeUrl the Bridge Server URL
* @param {PKIVerificationOptions} [verificationOptions] PrivMX Bridge server instance verification options using a PKI server
* @returns {Connection} instance of Connection
*/
static async connectPublic(solutionId, bridgeUrl, verificationOptions) {
const nativeApi = new ConnectionNative_1.ConnectionNative(this.api);
const ptr = await nativeApi.newConnection();
await nativeApi.connectPublic(ptr, [
solutionId,
bridgeUrl,
verificationOptions || this.generateDefaultPKIVerificationOptions(),
]);
return new Connection_1.Connection(nativeApi, ptr);
}
/**
* Creates an instance of the Thread API.
*
* @param {Connection} connection instance of Connection
*
* @returns {ThreadApi} instance of ThreadApi
*/
static async createThreadApi(connection) {
if ("threads" in connection.apisRefs) {
throw new Error("ThreadApi already registered for given connection.");
}
const nativeApi = new ThreadApiNative_1.ThreadApiNative(this.api);
const ptr = await nativeApi.newApi(connection.servicePtr);
await nativeApi.create(ptr, []);
connection.apisRefs["threads"] = { _apiServicePtr: ptr };
connection.nativeApisDeps["threads"] = nativeApi;
return new ThreadApi_1.ThreadApi(nativeApi, ptr);
}
/**
* Creates an instance of the Store API.
*
* @param {Connection} connection instance of Connection
*
* @returns {StoreApi} instance of StoreApi
*/
static async createStoreApi(connection) {
if ("stores" in connection.apisRefs) {
throw new Error("StoreApi already registered for given connection.");
}
const nativeApi = new StoreApiNative_1.StoreApiNative(this.api);
const ptr = await nativeApi.newApi(connection.servicePtr);
connection.apisRefs["stores"] = { _apiServicePtr: ptr };
connection.nativeApisDeps["stores"] = nativeApi;
await nativeApi.create(ptr, []);
return new StoreApi_1.StoreApi(nativeApi, ptr);
}
/**
* Creates an instance of the Inbox API.
*
* @param {Connection} connection instance of Connection
* @param {ThreadApi} threadApi instance of ThreadApi
* @param {StoreApi} storeApi instance of StoreApi
* @returns {InboxApi} instance of InboxApi
*/
static async createInboxApi(connection, threadApi, storeApi) {
if ("inboxes" in connection.apisRefs) {
throw new Error("InboxApi already registered for given connection.");
}
const nativeApi = new InboxApiNative_1.InboxApiNative(this.api);
const ptr = await nativeApi.newApi(connection.servicePtr, threadApi.servicePtr, storeApi.servicePtr);
await nativeApi.create(ptr, []);
connection.apisRefs["inboxes"] = { _apiServicePtr: ptr };
connection.nativeApisDeps["inboxes"] = nativeApi;
return new InboxApi_1.InboxApi(nativeApi, ptr);
}
/**
* Creates an instance of the Kvdb API.
*
* @param {Connection} connection instance of Connection
*
* @returns {KvdbApi} instance of KvdbApi
*/
static async createKvdbApi(connection) {
if ("kvdbs" in connection.apisRefs) {
throw new Error("KvdbApi already registered for given connection.");
}
const nativeApi = new KvdbApiNative_1.KvdbApiNative(this.api);
const ptr = await nativeApi.newApi(connection.servicePtr);
await nativeApi.create(ptr, []);
connection.apisRefs["kvdbs"] = { _apiServicePtr: ptr };
connection.nativeApisDeps["kvdbs"] = nativeApi;
return new KvdbApi_1.KvdbApi(nativeApi, ptr);
}
/**
* Creates an instance of the Crypto API.
*
* @returns {CryptoApi} instance of CryptoApi
*/
static async createCryptoApi() {
const nativeApi = new CryptoApiNative_1.CryptoApiNative(this.api);
const ptr = await nativeApi.newApi();
await nativeApi.create(ptr, []);
return new CryptoApi_1.CryptoApi(nativeApi, ptr);
}
/**
* Creates an instance of 'EventApi'.
*
* @param connection instance of 'Connection'
*
* @returns {EventApi} instance of EventApi
*/
static async createEventApi(connection) {
if ("events" in connection.apisRefs) {
throw new Error("EventApi already registered for given connection.");
}
const nativeApi = new EventApiNative_1.EventApiNative(this.api);
const ptr = await nativeApi.newApi(connection.servicePtr);
await nativeApi.create(ptr, []);
connection.apisRefs["events"] = { _apiServicePtr: ptr };
connection.nativeApisDeps["events"] = nativeApi;
return new EventApi_1.EventApi(nativeApi, ptr);
}
/**
* Creates an instance of the Stream API.
*
* @param {Connection} connection instance of Connection
* @param {EventApi} eventApi instance of EventApi
* @param {StoreApi} storeApi instance of StoreApi
* @returns {StreamApi} instance of StreamApi
*/
static async createStreamApi(connection, eventApi) {
if ("streams" in connection.apisRefs) {
throw new Error("StreamApi already registered for given connection.");
}
const webRtcClient = new WebRtcClient_1.WebRtcClient(this.assetsBasePath);
const nativeApi = new StreamApiNative_1.StreamApiNative(this.api, webRtcClient);
const ptr = await nativeApi.newApi(connection.servicePtr, eventApi.servicePtr);
await nativeApi.create(ptr, []);
connection.apisRefs["streams"] = { _apiServicePtr: ptr };
connection.nativeApisDeps["streams"] = nativeApi;
return new StreamApi_1.StreamApi(nativeApi, ptr, webRtcClient);
}
}
exports.EndpointFactory = EndpointFactory;