diff --git a/packages/core/aqua-to-js/src/generate/__test__/__snapshots__/generate.snap.d.ts b/packages/core/aqua-to-js/src/generate/__test__/__snapshots__/generate.snap.d.ts index 0795649f..74fee0b1 100644 --- a/packages/core/aqua-to-js/src/generate/__test__/__snapshots__/generate.snap.d.ts +++ b/packages/core/aqua-to-js/src/generate/__test__/__snapshots__/generate.snap.d.ts @@ -50,19 +50,19 @@ export function registerHelloWorld(peer: IFluenceClient$$, serviceId: string, se // Functions export type ResourceTestResultType = [string | null, string[]] -export type resourceTestParams = [label: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, label: string, config?: {ttl?: number}]; +export type ResourceTestParams = [label: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, label: string, config?: {ttl?: number}]; export type ResourceTestResult = Promise; -export type helloTestParams = [config?: {ttl?: number}] | [peer: IFluenceClient$$, config?: {ttl?: number}]; +export type HelloTestParams = [config?: {ttl?: number}] | [peer: IFluenceClient$$, config?: {ttl?: number}]; export type HelloTestResult = Promise; -export type demo_calculationParams = [service_id: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, service_id: string, config?: {ttl?: number}]; +export type Demo_calculationParams = [service_id: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, service_id: string, config?: {ttl?: number}]; export type Demo_calculationResult = Promise; -export type marineTestParams = [wasm64: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, wasm64: string, config?: {ttl?: number}]; +export type MarineTestParams = [wasm64: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, wasm64: string, config?: {ttl?: number}]; export type MarineTestResult = Promise; diff --git a/packages/core/aqua-to-js/src/generate/__test__/__snapshots__/generate.snap.ts b/packages/core/aqua-to-js/src/generate/__test__/__snapshots__/generate.snap.ts index e680d7c8..8a5cdee4 100644 --- a/packages/core/aqua-to-js/src/generate/__test__/__snapshots__/generate.snap.ts +++ b/packages/core/aqua-to-js/src/generate/__test__/__snapshots__/generate.snap.ts @@ -542,7 +542,7 @@ export const resourceTest_script = ` export type ResourceTestResultType = [string | null, string[]] -export type resourceTestParams = [label: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, label: string, config?: {ttl?: number}]; +export type ResourceTestParams = [label: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, label: string, config?: {ttl?: number}]; export type ResourceTestResult = Promise; @@ -609,7 +609,7 @@ export const helloTest_script = ` ) `; -export type helloTestParams = [config?: {ttl?: number}] | [peer: IFluenceClient$$, config?: {ttl?: number}]; +export type HelloTestParams = [config?: {ttl?: number}] | [peer: IFluenceClient$$, config?: {ttl?: number}]; export type HelloTestResult = Promise; @@ -679,7 +679,7 @@ export const demo_calculation_script = ` ) `; -export type demo_calculationParams = [service_id: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, service_id: string, config?: {ttl?: number}]; +export type Demo_calculationParams = [service_id: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, service_id: string, config?: {ttl?: number}]; export type Demo_calculationResult = Promise; @@ -757,7 +757,7 @@ export const marineTest_script = ` ) `; -export type marineTestParams = [wasm64: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, wasm64: string, config?: {ttl?: number}]; +export type MarineTestParams = [wasm64: string, config?: {ttl?: number}] | [peer: IFluenceClient$$, wasm64: string, config?: {ttl?: number}]; export type MarineTestResult = Promise; diff --git a/packages/core/aqua-to-js/src/generate/interfaces.ts b/packages/core/aqua-to-js/src/generate/interfaces.ts index 7b46d5f8..73f9910f 100644 --- a/packages/core/aqua-to-js/src/generate/interfaces.ts +++ b/packages/core/aqua-to-js/src/generate/interfaces.ts @@ -86,7 +86,9 @@ export class TSTypeGenerator implements TypeGenerator { return [ argsDesc.join("\n"), resTypeDesc ?? "", - `export type ${funcDef.functionName}Params = ${functionOverloadArgsType};`, + `export type ${capitalize( + funcDef.functionName, + )}Params = ${functionOverloadArgsType};`, `export type ${capitalize( funcDef.functionName, )}Result = Promise<${resType}>;\n`, diff --git a/packages/core/js-client/src/api.ts b/packages/core/js-client/src/api.ts index dfdc0b3a..acef4450 100644 --- a/packages/core/js-client/src/api.ts +++ b/packages/core/js-client/src/api.ts @@ -25,6 +25,7 @@ import type { import { CallAquaFunctionConfig } from "./compilerSupport/callFunction.js"; import { aqua2ts, + SchemaValidationError, ts2aqua, wrapFunction, } from "./compilerSupport/conversions.js"; @@ -37,10 +38,11 @@ const isAquaConfig = ( config: JSONValue | ServiceImpl[string] | undefined, ): config is CallAquaFunctionConfig => { return ( - typeof config === "object" && - config !== null && - !Array.isArray(config) && - ["undefined", "number"].includes(typeof config["ttl"]) + config === undefined || + (typeof config === "object" && + config !== null && + !Array.isArray(config) && + ["undefined", "number"].includes(typeof config["ttl"])) ); }; @@ -60,14 +62,17 @@ export const v5_callFunction = async ( def: FunctionCallDef, script: string, ): Promise => { - const [peer, ...rest] = args; + const [peerOrArg, ...rest] = args; - if (!(peer instanceof FluencePeer)) { - await v5_callFunction([getDefaultPeer(), ...rest], def, script); + if (!(peerOrArg instanceof FluencePeer)) { + await v5_callFunction([getDefaultPeer(), peerOrArg, ...rest], def, script); return; } - const argNames = Object.keys(def.arrow); + const argNames = Object.keys( + def.arrow.domain.tag === "nil" ? [] : def.arrow.domain.fields, + ); + const schemaArgCount = argNames.length; type FunctionArg = SimpleTypes | ArrowWithoutCallbacks; @@ -88,7 +93,12 @@ export const v5_callFunction = async ( if (argSchema.tag === "arrow") { if (typeof arg !== "function") { - throw new Error("Argument and schema don't match"); + throw new SchemaValidationError( + [argNames[i]], + argSchema, + "function", + arg, + ); } const wrappedFunction = wrapFunction(arg, argSchema); @@ -97,7 +107,12 @@ export const v5_callFunction = async ( } if (typeof arg === "function") { - throw new Error("Argument and schema don't match"); + throw new SchemaValidationError( + [argNames[i]], + argSchema, + "non-function value", + arg, + ); } return [ @@ -111,7 +126,7 @@ export const v5_callFunction = async ( def.arrow.codomain.tag === "nil" || def.arrow.codomain.items.length === 0; const params = { - peer, + peer: peerOrArg, args: callArgs, config, }; diff --git a/packages/core/js-client/src/compilerSupport/conversions.ts b/packages/core/js-client/src/compilerSupport/conversions.ts index 1923703e..9cf5a7c0 100644 --- a/packages/core/js-client/src/compilerSupport/conversions.ts +++ b/packages/core/js-client/src/compilerSupport/conversions.ts @@ -28,12 +28,12 @@ import { ParticleContext } from "../jsServiceHost/interfaces.js"; import { ServiceImpl } from "./types.js"; -class SchemaValidationError extends Error { +export class SchemaValidationError extends Error { constructor( public path: string[], - schema: NonArrowSimpleType, + schema: NonArrowSimpleType | ArrowWithoutCallbacks, expected: string, - provided: JSONValue, + provided: JSONValue | ServiceImpl[string], ) { const given = provided === null