mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2025-06-12 23:51:21 +00:00
Add a more convenient API for calling aqua functions programmatically (#233)
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fluencelabs/fluence",
|
||||
"version": "0.27.4",
|
||||
"version": "0.27.5",
|
||||
"description": "TypeScript implementation of Fluence Peer",
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
|
@ -1,10 +1,8 @@
|
||||
import { FnConfig, FunctionCallDef } from './interface';
|
||||
import { FluencePeer } from '../../FluencePeer';
|
||||
import { Fluence } from '../../../index';
|
||||
import { Particle } from '../../Particle';
|
||||
import {
|
||||
injectRelayService,
|
||||
argToServiceDef,
|
||||
registerParticleScopeService,
|
||||
responseService,
|
||||
errorHandlingService,
|
||||
@ -21,18 +19,31 @@ import {
|
||||
* @param def - function definition generated by the Aqua compiler
|
||||
* @param script - air script with function execution logic generated by the Aqua compiler
|
||||
*/
|
||||
export function callFunction(rawFnArgs: Array<any>, def: FunctionCallDef, script: string) {
|
||||
if (def.arrow.domain.tag !== 'labeledProduct') {
|
||||
throw new Error('Should be impossible');
|
||||
}
|
||||
export function callFunction(rawFnArgs: Array<any>, def: FunctionCallDef, script: string): Promise<unknown> {
|
||||
const { args, peer, config } = extractArgs(rawFnArgs, def);
|
||||
|
||||
const argumentTypes = Object.entries(def.arrow.domain.fields);
|
||||
const expectedNumberOfArguments = argumentTypes.length;
|
||||
const { args, peer, config } = extractArgs(rawFnArgs, expectedNumberOfArguments);
|
||||
return callFunctionImpl(def, script, config || {}, peer, args);
|
||||
}
|
||||
|
||||
if (args.length !== expectedNumberOfArguments) {
|
||||
throw new Error('Incorrect number of arguments. Expecting ${def.argDefs.length}');
|
||||
}
|
||||
/**
|
||||
* Convenience function which does all the internal work of creating particles
|
||||
* and making necessary service registrations in order to support Aqua function calls
|
||||
*
|
||||
* @param def - function definition generated by the Aqua compiler
|
||||
* @param script - air script with function execution logic generated by the Aqua compiler
|
||||
* @param config - options to configure Aqua function execution
|
||||
* @param peer - Fluence Peer to invoke the function at
|
||||
* @param args - args in the form of JSON where each key corresponds to the name of the argument
|
||||
* @returns
|
||||
*/
|
||||
export function callFunctionImpl(
|
||||
def: FunctionCallDef,
|
||||
script: string,
|
||||
config: FnConfig,
|
||||
peer: FluencePeer,
|
||||
args: { [key: string]: any },
|
||||
): Promise<unknown> {
|
||||
const argumentTypes = getArgumentTypes(def);
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const particle = peer.internals.createNewParticle(script, config?.ttl);
|
||||
@ -41,13 +52,13 @@ export function callFunction(rawFnArgs: Array<any>, def: FunctionCallDef, script
|
||||
return reject(particle.message);
|
||||
}
|
||||
|
||||
for (let i = 0; i < expectedNumberOfArguments; i++) {
|
||||
const [name, type] = argumentTypes[i];
|
||||
for (let [name, argVal] of Object.entries(args)) {
|
||||
const type = argumentTypes[name];
|
||||
let service: ServiceDescription;
|
||||
if (type.tag === 'arrow') {
|
||||
service = userHandlerService(def.names.callbackSrv, [name, type], args[i]);
|
||||
service = userHandlerService(def.names.callbackSrv, [name, type], argVal);
|
||||
} else {
|
||||
service = injectValueService(def.names.getDataSrv, name, type, args[i]);
|
||||
service = injectValueService(def.names.getDataSrv, name, type, argVal);
|
||||
}
|
||||
registerParticleScopeService(peer, particle, service);
|
||||
}
|
||||
@ -105,15 +116,19 @@ const isReturnTypeVoid = (def: FunctionCallDef) => {
|
||||
*/
|
||||
const extractArgs = (
|
||||
args: any[],
|
||||
numberOfExpectedArgs: number,
|
||||
def: FunctionCallDef,
|
||||
): {
|
||||
peer: FluencePeer;
|
||||
config?: FnConfig;
|
||||
args: any[];
|
||||
args: { [key: string]: any };
|
||||
} => {
|
||||
const argumentTypes = getArgumentTypes(def);
|
||||
const argumentNames = Object.keys(argumentTypes);
|
||||
const numberOfExpectedArgs = argumentNames.length;
|
||||
|
||||
let peer: FluencePeer;
|
||||
let structuredArgs: any[];
|
||||
let config: any;
|
||||
let config: FnConfig;
|
||||
if (FluencePeer.isInstance(args[0])) {
|
||||
peer = args[0];
|
||||
structuredArgs = args.slice(1, numberOfExpectedArgs + 1);
|
||||
@ -124,9 +139,23 @@ const extractArgs = (
|
||||
config = args[numberOfExpectedArgs];
|
||||
}
|
||||
|
||||
if (structuredArgs.length !== numberOfExpectedArgs) {
|
||||
throw new Error(`Incorrect number of arguments. Expecting ${numberOfExpectedArgs}`);
|
||||
}
|
||||
|
||||
const argsRes = argumentNames.reduce((acc, name, index) => ({ ...acc, [name]: structuredArgs[index] }), {});
|
||||
|
||||
return {
|
||||
peer: peer,
|
||||
config: config,
|
||||
args: structuredArgs,
|
||||
args: argsRes,
|
||||
};
|
||||
};
|
||||
|
||||
const getArgumentTypes = (def: FunctionCallDef) => {
|
||||
if (def.arrow.domain.tag !== 'labeledProduct') {
|
||||
throw new Error('Should be impossible');
|
||||
}
|
||||
|
||||
return def.arrow.domain.fields;
|
||||
};
|
||||
|
Reference in New Issue
Block a user