mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2025-06-25 13:51:34 +00:00
feat: Simplify JS Client public API (#257)
This commit is contained in:
@ -19,7 +19,7 @@ import type { IFluenceClient } from '@fluencelabs/interfaces';
|
||||
import { getArgumentTypes } from '@fluencelabs/interfaces';
|
||||
import { isFluencePeer } from '@fluencelabs/interfaces';
|
||||
|
||||
import { getDefaultPeer } from '../util.js';
|
||||
import { getFluenceInterface } from '../util.js';
|
||||
|
||||
/**
|
||||
* Convenience function to support Aqua `func` generation backend
|
||||
@ -30,12 +30,20 @@ import { getDefaultPeer } from '../util.js';
|
||||
* @param script - air script with function execution logic generated by the Aqua compiler
|
||||
*/
|
||||
export const callFunction = async (rawFnArgs: Array<any>, def: FunctionCallDef, script: string): Promise<unknown> => {
|
||||
const { args, peer, config } = await extractFunctionArgs(rawFnArgs, def);
|
||||
return peer.compilerSupport.callFunction({
|
||||
const { args, client: peer, config } = await extractFunctionArgs(rawFnArgs, def);
|
||||
if (peer.internals.getConnectionState() !== 'connected') {
|
||||
throw new Error(
|
||||
'Could not call the Aqua function because client is disconnected. Did you forget to call Fluence.connect()?',
|
||||
);
|
||||
}
|
||||
|
||||
const fluence = await getFluenceInterface();
|
||||
return fluence.callAquaFunction({
|
||||
args,
|
||||
def,
|
||||
script,
|
||||
config: config || {},
|
||||
peer: peer,
|
||||
});
|
||||
};
|
||||
|
||||
@ -47,10 +55,21 @@ export const callFunction = async (rawFnArgs: Array<any>, def: FunctionCallDef,
|
||||
*/
|
||||
export const registerService = async (args: any[], def: ServiceDef): Promise<unknown> => {
|
||||
const { peer, service, serviceId } = await extractServiceArgs(args, def.defaultServiceId);
|
||||
return peer.compilerSupport.registerService({
|
||||
|
||||
// TODO: TBH service registration is just putting some stuff into a hashmap
|
||||
// there should not be such a check at all
|
||||
if (peer.internals.getConnectionState() !== 'connected') {
|
||||
throw new Error(
|
||||
'Could not register Aqua service because the client is disconnected. Did you forget to call Fluence.connect()?',
|
||||
);
|
||||
}
|
||||
|
||||
const fluence = await getFluenceInterface();
|
||||
return fluence.registerService({
|
||||
def,
|
||||
service,
|
||||
serviceId,
|
||||
peer,
|
||||
});
|
||||
};
|
||||
|
||||
@ -68,7 +87,7 @@ const extractFunctionArgs = async (
|
||||
args: any[],
|
||||
def: FunctionCallDef,
|
||||
): Promise<{
|
||||
peer: IFluenceClient;
|
||||
client: IFluenceClient;
|
||||
config?: FnConfig;
|
||||
args: { [key: string]: any };
|
||||
}> => {
|
||||
@ -84,7 +103,8 @@ const extractFunctionArgs = async (
|
||||
structuredArgs = args.slice(1, numberOfExpectedArgs + 1);
|
||||
config = args[numberOfExpectedArgs + 1];
|
||||
} else {
|
||||
peer = await getDefaultPeer();
|
||||
const fluence = await getFluenceInterface();
|
||||
peer = fluence.defaultClient;
|
||||
structuredArgs = args.slice(0, numberOfExpectedArgs);
|
||||
config = args[numberOfExpectedArgs];
|
||||
}
|
||||
@ -96,7 +116,7 @@ const extractFunctionArgs = async (
|
||||
const argsRes = argumentNames.reduce((acc, name, index) => ({ ...acc, [name]: structuredArgs[index] }), {});
|
||||
|
||||
return {
|
||||
peer: peer,
|
||||
client: peer,
|
||||
config: config,
|
||||
args: argsRes,
|
||||
};
|
||||
@ -124,7 +144,8 @@ const extractServiceArgs = async (
|
||||
if (isFluencePeer(args[0])) {
|
||||
peer = args[0];
|
||||
} else {
|
||||
peer = await getDefaultPeer();
|
||||
const fluence = await getFluenceInterface();
|
||||
peer = fluence.defaultClient;
|
||||
}
|
||||
|
||||
if (typeof args[0] === 'string') {
|
||||
|
@ -1,5 +1,11 @@
|
||||
import { getDefaultPeer } from './util.js';
|
||||
import type { IFluenceClient, ClientOptions } from '@fluencelabs/interfaces';
|
||||
import { getFluenceInterface, getFluenceInterfaceFromGlobalThis } from './util.js';
|
||||
import {
|
||||
IFluenceClient,
|
||||
ClientOptions,
|
||||
RelayOptions,
|
||||
ConnectionState,
|
||||
ConnectionStates,
|
||||
} from '@fluencelabs/interfaces';
|
||||
export type { IFluenceClient, ClientOptions, CallParams } from '@fluencelabs/interfaces';
|
||||
|
||||
export {
|
||||
@ -30,33 +36,56 @@ export {
|
||||
} from './compilerSupport/implementation.js';
|
||||
|
||||
/**
|
||||
* Public interface to Fluence JS
|
||||
* Public interface to Fluence Network
|
||||
*/
|
||||
export const Fluence = {
|
||||
/**
|
||||
* Initializes the default peer: starts the Aqua VM, initializes the default call service handlers
|
||||
* and (optionally) connect to the Fluence network
|
||||
* @param options - object specifying peer configuration
|
||||
* Connect to the Fluence network
|
||||
* @param relay - relay node to connect to
|
||||
* @param options - client options
|
||||
*/
|
||||
start: async (options?: ClientOptions): Promise<void> => {
|
||||
const peer = await getDefaultPeer();
|
||||
return peer.start(options);
|
||||
connect: async (relay: RelayOptions, options?: ClientOptions): Promise<void> => {
|
||||
const fluence = await getFluenceInterface();
|
||||
return fluence.defaultClient.connect(relay, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Un-initializes the default peer: stops all the underlying workflows, stops the Aqua VM
|
||||
* and disconnects from the Fluence network
|
||||
* Disconnect from the Fluence network
|
||||
*/
|
||||
stop: async (): Promise<void> => {
|
||||
const peer = await getDefaultPeer();
|
||||
return peer.stop();
|
||||
disconnect: async (): Promise<void> => {
|
||||
const fluence = await getFluenceInterface();
|
||||
return fluence.defaultClient.disconnect();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the default peer instance
|
||||
* @returns the default peer instance
|
||||
* Handle connection state changes. Immediately returns the current connection state
|
||||
*/
|
||||
getPeer: async (): Promise<IFluenceClient> => {
|
||||
return getDefaultPeer();
|
||||
onConnectionStateChange(handler: (state: ConnectionState) => void): ConnectionState {
|
||||
const optimisticResult = getFluenceInterfaceFromGlobalThis();
|
||||
if (optimisticResult) {
|
||||
return optimisticResult.defaultClient.onConnectionStateChange(handler);
|
||||
}
|
||||
|
||||
getFluenceInterface().then((fluence) => fluence.defaultClient.onConnectionStateChange(handler));
|
||||
|
||||
return 'disconnected';
|
||||
},
|
||||
|
||||
/**
|
||||
* Low level API. Get the underlying client instance which holds the connection to the network
|
||||
* @returns IFluenceClient instance
|
||||
*/
|
||||
getClient: async (): Promise<IFluenceClient> => {
|
||||
const fluence = await getFluenceInterface();
|
||||
return fluence.defaultClient;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Low level API. Generally you need Fluence.connect() instead.
|
||||
* @returns IFluenceClient instance
|
||||
*/
|
||||
export const createClient = async (): Promise<IFluenceClient> => {
|
||||
const fluence = await getFluenceInterface();
|
||||
return fluence.clientFactory();
|
||||
};
|
||||
|
@ -1,12 +1,23 @@
|
||||
import type { IFluenceClient } from '@fluencelabs/interfaces';
|
||||
import type { CallAquaFunction, IFluenceClient, RegisterService } from '@fluencelabs/interfaces';
|
||||
|
||||
const getPeerFromGlobalThis = (): IFluenceClient | undefined => {
|
||||
// @ts-ignore
|
||||
return globalThis.defaultPeer;
|
||||
type PublicFluenceInterface = {
|
||||
clientFactory: () => IFluenceClient;
|
||||
defaultClient: IFluenceClient;
|
||||
callAquaFunction: CallAquaFunction;
|
||||
registerService: RegisterService;
|
||||
};
|
||||
|
||||
// TODO: DXJ-271
|
||||
const REJECT_MESSAGE = 'You probably forgot to add script tag. Read about it here: ';
|
||||
export const getFluenceInterfaceFromGlobalThis = (): PublicFluenceInterface | undefined => {
|
||||
// @ts-ignore
|
||||
return globalThis.fluence;
|
||||
};
|
||||
|
||||
// TODO: fix link DXJ-271
|
||||
const REJECT_MESSAGE = `Could not load Fluence JS Client library.
|
||||
If you are using Node.js that probably means that you forgot in install or import the @fluencelabs/js-client.node package.
|
||||
If you are using a browser, then you probably forgot to add the <script> tag to your HTML.
|
||||
Please refer to the documentation page for more details: https://fluence.dev/
|
||||
`;
|
||||
|
||||
// Let's assume that if the library has not been loaded in 5 seconds, then the user has forgotten to add the script tag
|
||||
const POLL_PEER_TIMEOUT = 5000;
|
||||
@ -17,7 +28,13 @@ const POLL_PEER_INTERVAL = 100;
|
||||
/**
|
||||
* Wait until the js client script it loaded and return the default peer from globalThis
|
||||
*/
|
||||
export const getDefaultPeer = (): Promise<IFluenceClient> => {
|
||||
export const getFluenceInterface = (): Promise<PublicFluenceInterface> => {
|
||||
// If the script is already loaded, then return the value immediately
|
||||
const optimisticResult = getFluenceInterfaceFromGlobalThis();
|
||||
if (optimisticResult) {
|
||||
return Promise.resolve(optimisticResult);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// This function is internal
|
||||
// Make it sure that would be zero way for unnecessary types
|
||||
@ -30,7 +47,7 @@ export const getDefaultPeer = (): Promise<IFluenceClient> => {
|
||||
reject(REJECT_MESSAGE);
|
||||
}
|
||||
|
||||
let res = getPeerFromGlobalThis();
|
||||
let res = getFluenceInterfaceFromGlobalThis();
|
||||
if (res) {
|
||||
clearInterval(interval);
|
||||
resolve(res);
|
||||
|
Reference in New Issue
Block a user