mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2025-06-16 01:21:20 +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",
|
"name": "@fluencelabs/fluence",
|
||||||
"version": "0.27.4",
|
"version": "0.27.5",
|
||||||
"description": "TypeScript implementation of Fluence Peer",
|
"description": "TypeScript implementation of Fluence Peer",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"typings": "./dist/index.d.ts",
|
"typings": "./dist/index.d.ts",
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import { FnConfig, FunctionCallDef } from './interface';
|
import { FnConfig, FunctionCallDef } from './interface';
|
||||||
import { FluencePeer } from '../../FluencePeer';
|
import { FluencePeer } from '../../FluencePeer';
|
||||||
import { Fluence } from '../../../index';
|
import { Fluence } from '../../../index';
|
||||||
import { Particle } from '../../Particle';
|
|
||||||
import {
|
import {
|
||||||
injectRelayService,
|
injectRelayService,
|
||||||
argToServiceDef,
|
|
||||||
registerParticleScopeService,
|
registerParticleScopeService,
|
||||||
responseService,
|
responseService,
|
||||||
errorHandlingService,
|
errorHandlingService,
|
||||||
@ -21,18 +19,31 @@ import {
|
|||||||
* @param def - function definition generated by the Aqua compiler
|
* @param def - function definition generated by the Aqua compiler
|
||||||
* @param script - air script with function execution logic 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) {
|
export function callFunction(rawFnArgs: Array<any>, def: FunctionCallDef, script: string): Promise<unknown> {
|
||||||
if (def.arrow.domain.tag !== 'labeledProduct') {
|
const { args, peer, config } = extractArgs(rawFnArgs, def);
|
||||||
throw new Error('Should be impossible');
|
|
||||||
|
return callFunctionImpl(def, script, config || {}, peer, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
const argumentTypes = Object.entries(def.arrow.domain.fields);
|
/**
|
||||||
const expectedNumberOfArguments = argumentTypes.length;
|
* Convenience function which does all the internal work of creating particles
|
||||||
const { args, peer, config } = extractArgs(rawFnArgs, expectedNumberOfArguments);
|
* and making necessary service registrations in order to support Aqua function calls
|
||||||
|
*
|
||||||
if (args.length !== expectedNumberOfArguments) {
|
* @param def - function definition generated by the Aqua compiler
|
||||||
throw new Error('Incorrect number of arguments. Expecting ${def.argDefs.length}');
|
* @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 promise = new Promise((resolve, reject) => {
|
||||||
const particle = peer.internals.createNewParticle(script, config?.ttl);
|
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);
|
return reject(particle.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < expectedNumberOfArguments; i++) {
|
for (let [name, argVal] of Object.entries(args)) {
|
||||||
const [name, type] = argumentTypes[i];
|
const type = argumentTypes[name];
|
||||||
let service: ServiceDescription;
|
let service: ServiceDescription;
|
||||||
if (type.tag === 'arrow') {
|
if (type.tag === 'arrow') {
|
||||||
service = userHandlerService(def.names.callbackSrv, [name, type], args[i]);
|
service = userHandlerService(def.names.callbackSrv, [name, type], argVal);
|
||||||
} else {
|
} else {
|
||||||
service = injectValueService(def.names.getDataSrv, name, type, args[i]);
|
service = injectValueService(def.names.getDataSrv, name, type, argVal);
|
||||||
}
|
}
|
||||||
registerParticleScopeService(peer, particle, service);
|
registerParticleScopeService(peer, particle, service);
|
||||||
}
|
}
|
||||||
@ -105,15 +116,19 @@ const isReturnTypeVoid = (def: FunctionCallDef) => {
|
|||||||
*/
|
*/
|
||||||
const extractArgs = (
|
const extractArgs = (
|
||||||
args: any[],
|
args: any[],
|
||||||
numberOfExpectedArgs: number,
|
def: FunctionCallDef,
|
||||||
): {
|
): {
|
||||||
peer: FluencePeer;
|
peer: FluencePeer;
|
||||||
config?: FnConfig;
|
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 peer: FluencePeer;
|
||||||
let structuredArgs: any[];
|
let structuredArgs: any[];
|
||||||
let config: any;
|
let config: FnConfig;
|
||||||
if (FluencePeer.isInstance(args[0])) {
|
if (FluencePeer.isInstance(args[0])) {
|
||||||
peer = args[0];
|
peer = args[0];
|
||||||
structuredArgs = args.slice(1, numberOfExpectedArgs + 1);
|
structuredArgs = args.slice(1, numberOfExpectedArgs + 1);
|
||||||
@ -124,9 +139,23 @@ const extractArgs = (
|
|||||||
config = args[numberOfExpectedArgs];
|
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 {
|
return {
|
||||||
peer: peer,
|
peer: peer,
|
||||||
config: config,
|
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