mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2025-06-12 23:51:21 +00:00
Review fixes
This commit is contained in:
@ -57,8 +57,7 @@
|
||||
"rxjs": "7.5.5",
|
||||
"uint8arrays": "4.0.3",
|
||||
"uuid": "8.3.2",
|
||||
"zod": "3.22.4",
|
||||
"zod-validation-error": "2.1.0"
|
||||
"zod": "3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fluencelabs/aqua-api": "0.9.3",
|
||||
|
@ -14,77 +14,155 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { CallAquaFunctionArgs } from "./compilerSupport/callFunction.js";
|
||||
import type {
|
||||
FunctionCallDef,
|
||||
JSONValue,
|
||||
SimpleTypes,
|
||||
ArrowWithoutCallbacks,
|
||||
ServiceDef,
|
||||
} from "@fluencelabs/interfaces";
|
||||
|
||||
import { CallAquaFunctionConfig } from "./compilerSupport/callFunction.js";
|
||||
import {
|
||||
aqua2ts,
|
||||
ts2aqua,
|
||||
wrapFunction,
|
||||
wrapServiceFunction,
|
||||
} from "./compilerSupport/conversions.js";
|
||||
import { ServiceImpl } from "./compilerSupport/types.js";
|
||||
import { FluencePeer } from "./jsPeer/FluencePeer.js";
|
||||
|
||||
import { callAquaFunction, Fluence, registerService } from "./index.js";
|
||||
|
||||
export const isFluencePeer = (
|
||||
fluencePeerCandidate: unknown,
|
||||
): fluencePeerCandidate is FluencePeer => {
|
||||
return fluencePeerCandidate instanceof FluencePeer;
|
||||
};
|
||||
|
||||
type CallAquaFunctionArgsTuned = Pick<CallAquaFunctionArgs, "args" | "script"> &
|
||||
Partial<Pick<CallAquaFunctionArgs, "config" | "peer">>;
|
||||
|
||||
type RegisterServiceArgs = {
|
||||
peer?: FluencePeer;
|
||||
service: ServiceImpl;
|
||||
serviceId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience function to support Aqua `func` generation backend
|
||||
* The compiler only need to generate a call the function and provide the air script
|
||||
* The compiler only need to generate a call the function and provide the corresponding definitions and the air script
|
||||
*
|
||||
* @param args - raw arguments passed by user to the generated function
|
||||
* @param def - function definition generated by the Aqua compiler
|
||||
* @param script - air script with function execution logic generated by the Aqua compiler
|
||||
*/
|
||||
export const v5_callFunction = async ({
|
||||
config = {},
|
||||
peer,
|
||||
args,
|
||||
script,
|
||||
}: CallAquaFunctionArgsTuned): Promise<unknown> => {
|
||||
if (peer == null) {
|
||||
if (Fluence.defaultClient == null) {
|
||||
throw new Error(
|
||||
"Could not register Aqua service because the client is not initialized. Did you forget to call Fluence.connect()?",
|
||||
);
|
||||
}
|
||||
export const v5_callFunction = async (
|
||||
args: (JSONValue | ((...args: JSONValue[]) => JSONValue))[],
|
||||
def: FunctionCallDef,
|
||||
script: string,
|
||||
): Promise<unknown> => {
|
||||
const argNames = Object.keys(def.arrow);
|
||||
const argCount = argNames.length;
|
||||
|
||||
const functionArgs: Record<string, SimpleTypes | ArrowWithoutCallbacks> =
|
||||
def.arrow.domain.tag === "nil" ? {} : def.arrow.domain.fields;
|
||||
|
||||
let peer: FluencePeer | undefined;
|
||||
|
||||
if (args[0] instanceof FluencePeer) {
|
||||
peer = args[0];
|
||||
args = args.slice(1);
|
||||
} else {
|
||||
peer = Fluence.defaultClient;
|
||||
}
|
||||
|
||||
return callAquaFunction({
|
||||
args,
|
||||
script,
|
||||
config,
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const config =
|
||||
argCount < args.length
|
||||
? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
(args.pop() as CallAquaFunctionConfig | undefined)
|
||||
: undefined;
|
||||
|
||||
if (peer == null) {
|
||||
throw new Error(
|
||||
"Could not register Aqua service because the client is not initialized. Did you forget to call Fluence.connect()?",
|
||||
);
|
||||
}
|
||||
|
||||
const callArgs = Object.fromEntries<
|
||||
JSONValue | ((...args: JSONValue[]) => JSONValue)
|
||||
>(
|
||||
args.slice(0, argCount).map((arg, i) => {
|
||||
const argSchema = functionArgs[argNames[i]];
|
||||
|
||||
if (argSchema.tag === "arrow") {
|
||||
if (typeof arg !== "function") {
|
||||
throw new Error("Argument and schema doesn't match");
|
||||
}
|
||||
|
||||
const wrappedFunction = wrapFunction(arg, argSchema);
|
||||
|
||||
return [argNames[i], wrappedFunction];
|
||||
}
|
||||
|
||||
if (typeof arg === "function") {
|
||||
throw new Error("Argument and schema doesn't match");
|
||||
}
|
||||
|
||||
return [argNames[i], ts2aqua(arg, argSchema)];
|
||||
}),
|
||||
);
|
||||
|
||||
const params = {
|
||||
peer,
|
||||
args: callArgs,
|
||||
config,
|
||||
};
|
||||
|
||||
const result = await callAquaFunction({
|
||||
script,
|
||||
...params,
|
||||
});
|
||||
|
||||
const valueSchema =
|
||||
def.arrow.codomain.tag === "unlabeledProduct" &&
|
||||
def.arrow.codomain.items.length === 1
|
||||
? def.arrow.codomain.items[0]
|
||||
: def.arrow.codomain;
|
||||
|
||||
return aqua2ts(result, valueSchema);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience function to support Aqua `service` generation backend
|
||||
* The compiler only need to generate a call the function and provide the air script
|
||||
* The compiler only need to generate a call the function and provide the corresponding definitions and the air script
|
||||
* @param args - raw arguments passed by user to the generated function
|
||||
* @param def - service definition generated by the Aqua compiler
|
||||
*/
|
||||
export const v5_registerService = ({
|
||||
serviceId,
|
||||
service,
|
||||
peer,
|
||||
}: RegisterServiceArgs): void => {
|
||||
if (peer == null) {
|
||||
if (Fluence.defaultClient == null) {
|
||||
throw new Error(
|
||||
"Could not register Aqua service because the client is not initialized. Did you forget to call Fluence.connect()?",
|
||||
);
|
||||
}
|
||||
export const v5_registerService = (args: unknown[], def: ServiceDef): void => {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const serviceImpl = args.pop() as ServiceImpl;
|
||||
let peer: FluencePeer | undefined;
|
||||
let serviceId = def.defaultServiceId;
|
||||
|
||||
if (args[0] instanceof FluencePeer) {
|
||||
peer = args[0];
|
||||
args = args.slice(1);
|
||||
} else {
|
||||
peer = Fluence.defaultClient;
|
||||
}
|
||||
|
||||
if (peer == null) {
|
||||
throw new Error(
|
||||
"Could not register Aqua service because the client is not initialized. Did you forget to call Fluence.connect()?",
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof args[0] === "string") {
|
||||
serviceId = args[0];
|
||||
}
|
||||
|
||||
if (serviceId == null) {
|
||||
throw new Error("Service ID is not provided");
|
||||
}
|
||||
|
||||
const serviceSchema = def.functions.tag === "nil" ? {} : def.functions.fields;
|
||||
|
||||
const wrappedServiceImpl = Object.fromEntries(
|
||||
Object.entries(serviceImpl).map(([name, func]) => {
|
||||
return [name, wrapServiceFunction(func, serviceSchema[name])];
|
||||
}),
|
||||
);
|
||||
|
||||
registerService({
|
||||
service,
|
||||
serviceId,
|
||||
service: wrappedServiceImpl,
|
||||
peer,
|
||||
serviceId,
|
||||
});
|
||||
};
|
||||
|
@ -0,0 +1,248 @@
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { JSONValue, NonArrowSimpleType } from "@fluencelabs/interfaces";
|
||||
import { it, describe, expect, test } from "vitest";
|
||||
|
||||
import { aqua2ts, ts2aqua } from "../conversions.js";
|
||||
|
||||
const i32 = { tag: "scalar", name: "i32" } as const;
|
||||
|
||||
const opt_i32 = {
|
||||
tag: "option",
|
||||
type: i32,
|
||||
} as const;
|
||||
|
||||
const array_i32 = { tag: "array", type: i32 };
|
||||
|
||||
const array_opt_i32 = { tag: "array", type: opt_i32 };
|
||||
|
||||
const labeledProduct = {
|
||||
tag: "labeledProduct",
|
||||
fields: {
|
||||
a: i32,
|
||||
b: opt_i32,
|
||||
c: array_opt_i32,
|
||||
},
|
||||
};
|
||||
|
||||
const struct = {
|
||||
tag: "struct",
|
||||
name: "someStruct",
|
||||
fields: {
|
||||
a: i32,
|
||||
b: opt_i32,
|
||||
c: array_opt_i32,
|
||||
},
|
||||
};
|
||||
|
||||
const structs = [
|
||||
{
|
||||
aqua: {
|
||||
a: 1,
|
||||
b: [2],
|
||||
c: [[1], [2]],
|
||||
},
|
||||
|
||||
ts: {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: [1, 2],
|
||||
},
|
||||
},
|
||||
{
|
||||
aqua: {
|
||||
a: 1,
|
||||
b: [],
|
||||
c: [[], [2]],
|
||||
},
|
||||
|
||||
ts: {
|
||||
a: 1,
|
||||
b: null,
|
||||
c: [null, 2],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const labeledProduct2 = {
|
||||
tag: "labeledProduct",
|
||||
fields: {
|
||||
x: i32,
|
||||
y: i32,
|
||||
},
|
||||
};
|
||||
|
||||
const nestedLabeledProductType = {
|
||||
tag: "labeledProduct",
|
||||
fields: {
|
||||
a: labeledProduct2,
|
||||
b: {
|
||||
tag: "option",
|
||||
type: labeledProduct2,
|
||||
},
|
||||
c: {
|
||||
tag: "array",
|
||||
type: labeledProduct2,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const nestedStructs = [
|
||||
{
|
||||
aqua: {
|
||||
a: {
|
||||
x: 1,
|
||||
y: 2,
|
||||
},
|
||||
b: [
|
||||
{
|
||||
x: 1,
|
||||
y: 2,
|
||||
},
|
||||
],
|
||||
c: [
|
||||
{
|
||||
x: 1,
|
||||
y: 2,
|
||||
},
|
||||
{
|
||||
x: 3,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
ts: {
|
||||
a: {
|
||||
x: 1,
|
||||
y: 2,
|
||||
},
|
||||
b: {
|
||||
x: 1,
|
||||
y: 2,
|
||||
},
|
||||
|
||||
c: [
|
||||
{
|
||||
x: 1,
|
||||
y: 2,
|
||||
},
|
||||
{
|
||||
x: 3,
|
||||
y: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
aqua: {
|
||||
a: {
|
||||
x: 1,
|
||||
y: 2,
|
||||
},
|
||||
b: [],
|
||||
c: [],
|
||||
},
|
||||
|
||||
ts: {
|
||||
a: {
|
||||
x: 1,
|
||||
y: 2,
|
||||
},
|
||||
b: null,
|
||||
c: [],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
interface ConversionTestArgs {
|
||||
aqua: JSONValue;
|
||||
ts: JSONValue;
|
||||
type: NonArrowSimpleType;
|
||||
}
|
||||
|
||||
describe("Conversion from aqua to typescript", () => {
|
||||
test.each`
|
||||
aqua | ts | type
|
||||
${1} | ${1} | ${i32}
|
||||
${[]} | ${null} | ${opt_i32}
|
||||
${[1]} | ${1} | ${opt_i32}
|
||||
${[1, 2, 3]} | ${[1, 2, 3]} | ${array_i32}
|
||||
${[]} | ${[]} | ${array_i32}
|
||||
${[[1]]} | ${[1]} | ${array_opt_i32}
|
||||
${[[]]} | ${[null]} | ${array_opt_i32}
|
||||
${[[1], [2]]} | ${[1, 2]} | ${array_opt_i32}
|
||||
${[[], [2]]} | ${[null, 2]} | ${array_opt_i32}
|
||||
${structs[0].aqua} | ${structs[0].ts} | ${labeledProduct}
|
||||
${structs[1].aqua} | ${structs[1].ts} | ${labeledProduct}
|
||||
${structs[0].aqua} | ${structs[0].ts} | ${struct}
|
||||
${structs[1].aqua} | ${structs[1].ts} | ${struct}
|
||||
${nestedStructs[0].aqua} | ${nestedStructs[0].ts} | ${nestedLabeledProductType}
|
||||
${nestedStructs[1].aqua} | ${nestedStructs[1].ts} | ${nestedLabeledProductType}
|
||||
`(
|
||||
//
|
||||
"aqua: $aqua. ts: $ts. type: $type",
|
||||
({ aqua, ts, type }: ConversionTestArgs) => {
|
||||
// arrange
|
||||
|
||||
// act
|
||||
const tsFromAqua = aqua2ts(aqua, type);
|
||||
const aquaFromTs = ts2aqua(ts, type);
|
||||
|
||||
// assert
|
||||
expect(tsFromAqua).toStrictEqual(ts);
|
||||
expect(aquaFromTs).toStrictEqual(aqua);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("Conversion corner cases", () => {
|
||||
it("Should accept undefined in object entry", () => {
|
||||
// arrange
|
||||
const type = {
|
||||
tag: "labeledProduct",
|
||||
fields: {
|
||||
x: opt_i32,
|
||||
y: opt_i32,
|
||||
},
|
||||
} as const;
|
||||
|
||||
const valueInTs = {
|
||||
x: 1,
|
||||
};
|
||||
|
||||
const valueInAqua = {
|
||||
x: [1],
|
||||
y: [],
|
||||
};
|
||||
|
||||
// act
|
||||
const aqua = ts2aqua(valueInTs, type);
|
||||
const ts = aqua2ts(valueInAqua, type);
|
||||
|
||||
// assert
|
||||
expect(aqua).toStrictEqual({
|
||||
x: [1],
|
||||
y: [],
|
||||
});
|
||||
|
||||
expect(ts).toStrictEqual({
|
||||
x: 1,
|
||||
y: null,
|
||||
});
|
||||
});
|
||||
});
|
@ -17,7 +17,9 @@
|
||||
import { JSONValue } from "@fluencelabs/interfaces";
|
||||
|
||||
import { FluencePeer } from "../jsPeer/FluencePeer.js";
|
||||
import { ParticleContext } from "../jsServiceHost/interfaces.js";
|
||||
import { logger } from "../util/logger.js";
|
||||
import { ArgCallbackFunction } from "../util/testUtils.js";
|
||||
|
||||
import {
|
||||
errorHandlingService,
|
||||
@ -28,7 +30,6 @@ import {
|
||||
ServiceDescription,
|
||||
userHandlerService,
|
||||
} from "./services.js";
|
||||
import { ServiceImpl } from "./types.js";
|
||||
|
||||
const log = logger("aqua");
|
||||
|
||||
@ -46,9 +47,9 @@ const log = logger("aqua");
|
||||
|
||||
export type CallAquaFunctionArgs = {
|
||||
script: string;
|
||||
config?: CallAquaFunctionConfig;
|
||||
config: CallAquaFunctionConfig | undefined;
|
||||
peer: FluencePeer;
|
||||
args: { [key: string]: JSONValue | ServiceImpl[string] };
|
||||
args: { [key: string]: JSONValue | ArgCallbackFunction };
|
||||
};
|
||||
|
||||
export type CallAquaFunctionConfig = {
|
||||
@ -65,12 +66,21 @@ export const callAquaFunction = async ({
|
||||
|
||||
const particle = await peer.internals.createNewParticle(script, config.ttl);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise<JSONValue>((resolve, reject) => {
|
||||
for (const [name, argVal] of Object.entries(args)) {
|
||||
let service: ServiceDescription;
|
||||
|
||||
if (typeof argVal === "function") {
|
||||
service = userHandlerService("callbackSrv", name, argVal);
|
||||
service = userHandlerService(
|
||||
"callbackSrv",
|
||||
name,
|
||||
(...args: [...JSONValue[], ParticleContext]) => {
|
||||
// Impossible to extract all element except the last one and coerce type
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const jsonArgs = args.slice(0, args.length - 1) as JSONValue[];
|
||||
return argVal(jsonArgs);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
service = injectValueService("getDataSrv", name, argVal);
|
||||
}
|
||||
|
166
packages/core/js-client/src/compilerSupport/conversions.ts
Normal file
166
packages/core/js-client/src/compilerSupport/conversions.ts
Normal file
@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Copyright 2023 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ArrowWithCallbacks,
|
||||
ArrowWithoutCallbacks,
|
||||
JSONValue,
|
||||
NonArrowSimpleType,
|
||||
} from "@fluencelabs/interfaces";
|
||||
|
||||
import { ParticleContext } from "../jsServiceHost/interfaces.js";
|
||||
|
||||
import { MaybePromise } from "./types.js";
|
||||
|
||||
export function aqua2ts(
|
||||
value: JSONValue,
|
||||
schema: NonArrowSimpleType,
|
||||
): JSONValue {
|
||||
if (schema.tag === "nil") {
|
||||
return null;
|
||||
} else if (schema.tag === "option") {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error("Value and schema doesn't match");
|
||||
}
|
||||
|
||||
if (value.length === 0) {
|
||||
return null;
|
||||
} else {
|
||||
return aqua2ts(value[0], schema.type);
|
||||
}
|
||||
} else if (
|
||||
schema.tag === "scalar" ||
|
||||
schema.tag === "bottomType" ||
|
||||
schema.tag === "topType"
|
||||
) {
|
||||
return value;
|
||||
} else if (schema.tag === "array") {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error("Value and schema doesn't match");
|
||||
}
|
||||
|
||||
return value.map((y) => {
|
||||
return aqua2ts(y, schema.type);
|
||||
});
|
||||
} else if (schema.tag === "unlabeledProduct") {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error("Value and schema doesn't match");
|
||||
}
|
||||
|
||||
return value.map((y, i) => {
|
||||
return aqua2ts(y, schema.items[i]);
|
||||
});
|
||||
} else if (["labeledProduct", "struct"].includes(schema.tag)) {
|
||||
if (typeof value !== "object" || value == null || Array.isArray(value)) {
|
||||
throw new Error("Value and schema doesn't match");
|
||||
}
|
||||
|
||||
return Object.entries(schema.fields).reduce((agg, [key, type]) => {
|
||||
const val = aqua2ts(value[key], type);
|
||||
return { ...agg, [key]: val };
|
||||
}, {});
|
||||
} else {
|
||||
throw new Error("Unexpected tag: " + JSON.stringify(schema));
|
||||
}
|
||||
}
|
||||
|
||||
export function ts2aqua(
|
||||
value: JSONValue,
|
||||
schema: NonArrowSimpleType,
|
||||
): JSONValue {
|
||||
if (schema.tag === "nil") {
|
||||
return null;
|
||||
} else if (schema.tag === "option") {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
return value == null ? [] : ([ts2aqua(value, schema.type)] as [JSONValue]);
|
||||
} else if (
|
||||
schema.tag === "scalar" ||
|
||||
schema.tag === "bottomType" ||
|
||||
schema.tag === "topType"
|
||||
) {
|
||||
return value;
|
||||
} else if (schema.tag === "array") {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error("Value and schema doesn't match");
|
||||
}
|
||||
|
||||
return value.map((y) => {
|
||||
return ts2aqua(y, schema.type);
|
||||
});
|
||||
} else if (schema.tag === "unlabeledProduct") {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error("Value and schema doesn't match");
|
||||
}
|
||||
|
||||
return value.map((y, i) => {
|
||||
return ts2aqua(y, schema.items[i]);
|
||||
});
|
||||
} else if (["labeledProduct", "struct"].includes(schema.tag)) {
|
||||
if (typeof value !== "object" || value == null || Array.isArray(value)) {
|
||||
throw new Error("Value and schema doesn't match");
|
||||
}
|
||||
|
||||
return Object.entries(schema.fields).reduce((agg, [key, type]) => {
|
||||
const val = ts2aqua(value[key], type);
|
||||
return { ...agg, [key]: val };
|
||||
}, {});
|
||||
} else {
|
||||
throw new Error("Unexpected tag: " + JSON.stringify(schema));
|
||||
}
|
||||
}
|
||||
|
||||
export const wrapFunction = (
|
||||
value: (...args: JSONValue[]) => JSONValue,
|
||||
schema: ArrowWithoutCallbacks,
|
||||
): ((...args: JSONValue[]) => JSONValue) => {
|
||||
return (...args) => {
|
||||
const schemaArgs =
|
||||
schema.codomain.tag === "nil" ? [] : schema.codomain.items;
|
||||
|
||||
const tsArgs = args.map((arg, i) => {
|
||||
return aqua2ts(arg, schemaArgs[i]);
|
||||
});
|
||||
|
||||
const result = value(...tsArgs);
|
||||
return ts2aqua(result, schema.codomain);
|
||||
};
|
||||
};
|
||||
|
||||
export const wrapServiceFunction = (
|
||||
value: (
|
||||
...args: [...JSONValue[], ParticleContext]
|
||||
) => MaybePromise<JSONValue>,
|
||||
schema: ArrowWithCallbacks,
|
||||
): ((
|
||||
...args: [...JSONValue[], ParticleContext]
|
||||
) => MaybePromise<JSONValue>) => {
|
||||
return async (...args) => {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const jsonArgs = args.slice(0, args.length - 1) as JSONValue[];
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const context = args[args.length - 1] as ParticleContext;
|
||||
|
||||
const schemaArgs =
|
||||
schema.codomain.tag === "nil" ? [] : schema.codomain.items;
|
||||
|
||||
const tsArgs = jsonArgs.map((arg, i) => {
|
||||
return aqua2ts(arg, schemaArgs[i]);
|
||||
});
|
||||
|
||||
const result = await value(...tsArgs, context);
|
||||
return ts2aqua(result, schema.codomain);
|
||||
};
|
||||
};
|
@ -204,6 +204,4 @@ export {
|
||||
|
||||
export { FluencePeer } from "./jsPeer/FluencePeer.js";
|
||||
|
||||
export type { JSONValue, NonArrowSimpleType } from "@fluencelabs/interfaces";
|
||||
|
||||
export * from "./network.js";
|
||||
|
@ -16,36 +16,11 @@
|
||||
|
||||
import { it, describe, expect } from "vitest";
|
||||
|
||||
import { isFluencePeer } from "../../api.js";
|
||||
import { handleTimeout } from "../../particle/Particle.js";
|
||||
import {
|
||||
mkTestPeer,
|
||||
registerHandlersHelper,
|
||||
withPeer,
|
||||
} from "../../util/testUtils.js";
|
||||
import { registerHandlersHelper, withPeer } from "../../util/testUtils.js";
|
||||
import { FluencePeer } from "../FluencePeer.js";
|
||||
|
||||
describe("FluencePeer usage test suite", () => {
|
||||
it("should perform test for FluencePeer class correctly", async () => {
|
||||
// arrange
|
||||
const peer = await mkTestPeer();
|
||||
const number = 1;
|
||||
const object = { str: "Hello!" };
|
||||
const undefinedVal = undefined;
|
||||
|
||||
// act
|
||||
const isPeerPeer = isFluencePeer(peer);
|
||||
const isNumberPeer = isFluencePeer(number);
|
||||
const isObjectPeer = isFluencePeer(object);
|
||||
const isUndefinedPeer = isFluencePeer(undefinedVal);
|
||||
|
||||
// act
|
||||
expect(isPeerPeer).toBe(true);
|
||||
expect(isNumberPeer).toBe(false);
|
||||
expect(isObjectPeer).toBe(false);
|
||||
expect(isUndefinedPeer).toBe(false);
|
||||
});
|
||||
|
||||
it("Should successfully call identity on local peer", async function () {
|
||||
await withPeer(async (peer) => {
|
||||
const script = `
|
||||
|
@ -30,10 +30,7 @@ import { ClientConfig, RelayOptions } from "../clientPeer/types.js";
|
||||
import { callAquaFunction } from "../compilerSupport/callFunction.js";
|
||||
import { IConnection } from "../connection/interfaces.js";
|
||||
import { DEFAULT_CONFIG, FluencePeer } from "../jsPeer/FluencePeer.js";
|
||||
import {
|
||||
CallServiceResultType,
|
||||
ParticleContext,
|
||||
} from "../jsServiceHost/interfaces.js";
|
||||
import { CallServiceResultType } from "../jsServiceHost/interfaces.js";
|
||||
import { JsServiceHost } from "../jsServiceHost/JsServiceHost.js";
|
||||
import { WrapFnIntoServiceCall } from "../jsServiceHost/serviceUtils.js";
|
||||
import { KeyPair } from "../keypair/index.js";
|
||||
@ -80,7 +77,7 @@ interface FunctionInfo {
|
||||
* Type for callback passed as aqua function argument
|
||||
*/
|
||||
export type ArgCallbackFunction = (
|
||||
...args: [...JSONValue[], ParticleContext]
|
||||
...args: JSONValue[]
|
||||
) => JSONValue | Promise<JSONValue>;
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user