Fix aqua-to-js, start to split responsibility

This commit is contained in:
Akim Mamedov 2023-11-12 21:54:43 +07:00
parent f5e9923974
commit 2f316cc8fb
12 changed files with 1071 additions and 6886 deletions

View File

@ -0,0 +1,48 @@
/**
* 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 { writeFile } from "fs/promises";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
import { compileFromPath } from "@fluencelabs/aqua-api";
import aquaToJs from "@fluencelabs/aqua-to-js";
const cr = await compileFromPath({
filePath: join(
dirname(fileURLToPath(import.meta.url)),
"_aqua",
"smoke_test.aqua",
),
targetType: "air",
imports: [join(dirname(fileURLToPath(import.meta.url)), "node_modules")],
});
const res = await aquaToJs(cr, "ts");
if (res == null) {
throw new Error(cr.errors.join("\n"));
}
await writeFile(
join(
dirname(fileURLToPath(import.meta.url)),
"src",
"_aqua",
"smoke_test.ts",
),
res.sources,
);

View File

@ -11,7 +11,7 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"compile-aqua": "fluence aqua -i ./_aqua -o ./src/_aqua" "compile-aqua": "node --loader ts-node/esm compile-aqua.ts"
}, },
"repository": "https://github.com/fluencelabs/fluence-js", "repository": "https://github.com/fluencelabs/fluence-js",
"author": "Fluence Labs", "author": "Fluence Labs",
@ -20,10 +20,12 @@
"base64-js": "1.5.1" "base64-js": "1.5.1"
}, },
"devDependencies": { "devDependencies": {
"@fluencelabs/aqua-api": "0.12.2",
"@fluencelabs/aqua-lib": "0.6.0", "@fluencelabs/aqua-lib": "0.6.0",
"@fluencelabs/cli": "0.7.2", "@fluencelabs/aqua-to-js": "workspace:*",
"@fluencelabs/js-client": "workspace:^", "@fluencelabs/js-client": "workspace:*",
"@fluencelabs/registry": "0.8.2", "@fluencelabs/registry": "0.8.7",
"@fluencelabs/trust-graph": "3.1.2" "@fluencelabs/trust-graph": "3.1.2",
"ts-node": "10.9.1"
} }
} }

View File

@ -2,23 +2,24 @@
// @ts-nocheck // @ts-nocheck
/** /**
* *
* This file is auto-generated. Do not edit manually: changes may be erased. * This file is generated using:
* Generated by Aqua compiler: https://github.com/fluencelabs/aqua/. * @fluencelabs/aqua-api version: 0.12.0
* If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues * @fluencelabs/aqua-to-js version: 0.2.0
* Aqua version: 0.12.0 * If you find any bugs in generated AIR, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues
* If you find any bugs in generated JS/TS, please write an issue on GitHub: https://github.com/fluencelabs/js-client/issues
* *
*/ */
import type { import type {
IFluenceClient as IFluenceClient$$, IFluenceClient as IFluenceClient$$,
CallParams as CallParams$$, CallParams as CallParams$$,
} from "@fluencelabs/js-client"; } from "@fluencelabs/js-client";
import { import {
v5_callFunction as callFunction$$, v5_callFunction as callFunction$$,
v5_registerService as registerService$$, v5_registerService as registerService$$,
} from "@fluencelabs/js-client"; } from "@fluencelabs/js-client";
// Services // Services
export interface SrvDef { export interface SrvDef {
create: ( create: (
wasm_b64_content: string, wasm_b64_content: string,
@ -46,131 +47,130 @@ export function registerSrv(
serviceId: string, serviceId: string,
service: SrvDef, service: SrvDef,
): void; ): void;
export function registerSrv(...args: any[]) {
export function registerSrv(...args: any) {
registerService$$(args, { registerService$$(args, {
defaultServiceId: "single_module_srv", defaultServiceId: "single_module_srv",
functions: { functions: {
tag: "labeledProduct",
fields: { fields: {
create: { create: {
tag: "arrow",
domain: { domain: {
tag: "labeledProduct",
fields: { fields: {
wasm_b64_content: { wasm_b64_content: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
}, },
tag: "labeledProduct",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "struct",
name: "ServiceCreationResult", name: "ServiceCreationResult",
fields: { fields: {
error: { error: {
tag: "option",
type: { type: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
tag: "option",
}, },
service_id: { service_id: {
tag: "option",
type: { type: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
tag: "option",
}, },
success: { success: {
tag: "scalar",
name: "bool", name: "bool",
tag: "scalar",
}, },
}, },
tag: "struct",
}, },
], ],
tag: "unlabeledProduct",
}, },
tag: "arrow",
}, },
list: { list: {
tag: "arrow",
domain: { domain: {
tag: "nil", tag: "nil",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "array",
type: { type: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
tag: "array",
}, },
], ],
tag: "unlabeledProduct",
}, },
tag: "arrow",
}, },
remove: { remove: {
tag: "arrow",
domain: { domain: {
tag: "labeledProduct",
fields: { fields: {
service_id: { service_id: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
}, },
tag: "labeledProduct",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "struct",
name: "RemoveResult", name: "RemoveResult",
fields: { fields: {
error: { error: {
tag: "option",
type: { type: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
tag: "option",
}, },
success: { success: {
tag: "scalar",
name: "bool", name: "bool",
tag: "scalar",
}, },
}, },
tag: "struct",
}, },
], ],
tag: "unlabeledProduct",
},
tag: "arrow",
}, },
}, },
}, tag: "labeledProduct",
}, },
}); });
} }
export interface CalcServiceDef { export interface CalcServiceDef {
add: (
num: number,
callParams: CallParams$$<"num">,
) => number | Promise<number>;
clear_state: (callParams: CallParams$$<null>) => void | Promise<void>;
divide: ( divide: (
num: number, num: number,
callParams: CallParams$$<"num">, callParams: CallParams$$<"num">,
) => number | Promise<number>; ) => number | Promise<number>;
clear_state: (callParams: CallParams$$<null>) => void | Promise<void>;
test_logs: (callParams: CallParams$$<null>) => void | Promise<void>;
multiply: ( multiply: (
num: number, num: number,
callParams: CallParams$$<"num">, callParams: CallParams$$<"num">,
) => number | Promise<number>; ) => number | Promise<number>;
add: (
num: number,
callParams: CallParams$$<"num">,
) => number | Promise<number>;
state: (callParams: CallParams$$<null>) => number | Promise<number>; state: (callParams: CallParams$$<null>) => number | Promise<number>;
subtract: ( subtract: (
num: number, num: number,
callParams: CallParams$$<"num">, callParams: CallParams$$<"num">,
) => number | Promise<number>; ) => number | Promise<number>;
test_logs: (callParams: CallParams$$<null>) => void | Promise<void>;
} }
export function registerCalcService( export function registerCalcService(
serviceId: string, serviceId: string,
@ -181,130 +181,129 @@ export function registerCalcService(
serviceId: string, serviceId: string,
service: CalcServiceDef, service: CalcServiceDef,
): void; ): void;
export function registerCalcService(...args: any[]) {
export function registerCalcService(...args: any) {
registerService$$(args, { registerService$$(args, {
functions: { functions: {
tag: "labeledProduct",
fields: { fields: {
add: { divide: {
tag: "arrow",
domain: { domain: {
tag: "labeledProduct",
fields: { fields: {
num: { num: {
tag: "scalar",
name: "f64", name: "f64",
tag: "scalar",
}, },
}, },
tag: "labeledProduct",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "scalar",
name: "f64", name: "f64",
tag: "scalar",
}, },
], ],
tag: "unlabeledProduct",
}, },
tag: "arrow",
}, },
clear_state: { clear_state: {
tag: "arrow",
domain: { domain: {
tag: "nil", tag: "nil",
}, },
codomain: { codomain: {
tag: "nil", tag: "nil",
}, },
},
divide: {
tag: "arrow", tag: "arrow",
domain: {
tag: "labeledProduct",
fields: {
num: {
tag: "scalar",
name: "f64",
},
},
},
codomain: {
tag: "unlabeledProduct",
items: [
{
tag: "scalar",
name: "f64",
},
],
},
},
multiply: {
tag: "arrow",
domain: {
tag: "labeledProduct",
fields: {
num: {
tag: "scalar",
name: "f64",
},
},
},
codomain: {
tag: "unlabeledProduct",
items: [
{
tag: "scalar",
name: "f64",
},
],
},
},
state: {
tag: "arrow",
domain: {
tag: "nil",
},
codomain: {
tag: "unlabeledProduct",
items: [
{
tag: "scalar",
name: "f64",
},
],
},
},
subtract: {
tag: "arrow",
domain: {
tag: "labeledProduct",
fields: {
num: {
tag: "scalar",
name: "f64",
},
},
},
codomain: {
tag: "unlabeledProduct",
items: [
{
tag: "scalar",
name: "f64",
},
],
},
}, },
test_logs: { test_logs: {
tag: "arrow",
domain: { domain: {
tag: "nil", tag: "nil",
}, },
codomain: { codomain: {
tag: "nil", tag: "nil",
}, },
tag: "arrow",
},
multiply: {
domain: {
fields: {
num: {
name: "f64",
tag: "scalar",
}, },
}, },
tag: "labeledProduct",
},
codomain: {
items: [
{
name: "f64",
tag: "scalar",
},
],
tag: "unlabeledProduct",
},
tag: "arrow",
},
add: {
domain: {
fields: {
num: {
name: "f64",
tag: "scalar",
},
},
tag: "labeledProduct",
},
codomain: {
items: [
{
name: "f64",
tag: "scalar",
},
],
tag: "unlabeledProduct",
},
tag: "arrow",
},
state: {
domain: {
tag: "nil",
},
codomain: {
items: [
{
name: "f64",
tag: "scalar",
},
],
tag: "unlabeledProduct",
},
tag: "arrow",
},
subtract: {
domain: {
fields: {
num: {
name: "f64",
tag: "scalar",
},
},
tag: "labeledProduct",
},
codomain: {
items: [
{
name: "f64",
tag: "scalar",
},
],
tag: "unlabeledProduct",
},
tag: "arrow",
},
},
tag: "labeledProduct",
}, },
}); });
} }
@ -329,35 +328,44 @@ export function registerHelloWorld(
serviceId: string, serviceId: string,
service: HelloWorldDef, service: HelloWorldDef,
): void; ): void;
type registerHelloWorldArgs =
export function registerHelloWorld(...args: any) { | [HelloWorldDef]
| [string, HelloWorldDef]
| [IFluenceClient$$, string, HelloWorldDef]
| [IFluenceClient$$, HelloWorldDef];
export function registerHelloWorld(...args: registerHelloWorldArgs) {
if (typeof args[0] === "string") {
args[0].toString();
args[1].toString();
args[2].hello;
}
registerService$$(args, { registerService$$(args, {
defaultServiceId: "hello-world", defaultServiceId: "hello-world",
functions: { functions: {
tag: "labeledProduct",
fields: { fields: {
hello: { hello: {
tag: "arrow",
domain: { domain: {
tag: "labeledProduct",
fields: { fields: {
str: { str: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
}, },
tag: "labeledProduct",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
], ],
tag: "unlabeledProduct",
},
tag: "arrow",
}, },
}, },
}, tag: "labeledProduct",
}, },
}); });
} }
@ -369,26 +377,26 @@ export const resourceTest_script = `
(seq (seq
(seq (seq
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-) (call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
(call %init_peer_id% ("getDataSrv" "label") [] label) (call %init_peer_id% ("getDataSrv" "label") [] -label-arg-)
) )
(xor (xor
(new $resource_id (new $resource_id
(seq (seq
(seq (seq
(seq (seq
(call %init_peer_id% ("peer" "timestamp_sec") [] t) (call %init_peer_id% ("peer" "timestamp_sec") [] ret)
(xor (xor
(seq (seq
(seq (seq
(call -relay- ("registry" "get_key_bytes") [label [] t [] ""] bytes) (call -relay- ("registry" "get_key_bytes") [-label-arg- [] ret [] ""] ret-0)
(xor (xor
(call %init_peer_id% ("sig" "sign") [bytes] result) (call %init_peer_id% ("sig" "sign") [ret-0] ret-1)
(fail %last_error%) (fail %last_error%)
) )
) )
(xor (xor
(match result.$.success false (match ret-1.$.success false
(ap result.$.error.[0] $error) (ap ret-1.$.error.[0] $error)
) )
(new $successful (new $successful
(seq (seq
@ -397,29 +405,29 @@ export const resourceTest_script = `
(seq (seq
(seq (seq
(seq (seq
(ap result.$.signature result_flat) (ap ret-1.$.signature ret-1_flat)
(call -relay- ("registry" "get_key_id") [label %init_peer_id%] id) (call -relay- ("registry" "get_key_id") [-label-arg- %init_peer_id%] ret-2)
) )
(call -relay- ("op" "string_to_b58") [id] k) (call -relay- ("op" "string_to_b58") [ret-2] ret-3)
) )
(call -relay- ("kad" "neighborhood") [k [] []] nodes) (call -relay- ("kad" "neighborhood") [ret-3 [] []] ret-4)
) )
(par (par
(fold nodes n-0 (fold ret-4 n-0
(par (par
(xor (xor
(xor (xor
(seq (seq
(seq (seq
(seq (seq
(call n-0 ("peer" "timestamp_sec") [] t-0) (call n-0 ("peer" "timestamp_sec") [] ret-5)
(call n-0 ("trust-graph" "get_weight") [%init_peer_id% t-0] weight) (call n-0 ("trust-graph" "get_weight") [%init_peer_id% ret-5] ret-6)
) )
(call n-0 ("registry" "register_key") [label [] t [] "" result_flat.$.[0] weight t-0] result-0) (call n-0 ("registry" "register_key") [-label-arg- [] ret [] "" ret-1_flat.$.[0] ret-6 ret-5] ret-7)
) )
(xor (xor
(seq (seq
(match result-0.$.success true (match ret-7.$.success true
(ap true $successful) (ap true $successful)
) )
(new $-ephemeral-stream- (new $-ephemeral-stream-
@ -429,7 +437,7 @@ export const resourceTest_script = `
) )
) )
(seq (seq
(ap result-0.$.error $error) (ap ret-7.$.error $error)
(new $-ephemeral-stream- (new $-ephemeral-stream-
(new #-ephemeral-canon- (new #-ephemeral-canon-
(canon -relay- $-ephemeral-stream- #-ephemeral-canon-) (canon -relay- $-ephemeral-stream- #-ephemeral-canon-)
@ -490,7 +498,10 @@ export const resourceTest_script = `
) )
(ap "ok" $status) (ap "ok" $status)
) )
(call -relay- ("peer" "timeout") [6000 "timeout"] $status) (seq
(call -relay- ("peer" "timeout") [6000 "timeout"] ret-8)
(ap ret-8 $status)
)
) )
(new $status_test (new $status_test
(seq (seq
@ -560,7 +571,7 @@ export const resourceTest_script = `
(match result-1_gate.$.[0] false (match result-1_gate.$.[0] false
(ap "resource wasn't created: timeout exceeded" $error) (ap "resource wasn't created: timeout exceeded" $error)
) )
(ap id $resource_id) (ap ret-2 $resource_id)
) )
) )
) )
@ -584,6 +595,7 @@ export const resourceTest_script = `
`; `;
export type ResourceTestResult = [string | null, string[]]; export type ResourceTestResult = [string | null, string[]];
export function resourceTest( export function resourceTest(
label: string, label: string,
config?: { ttl?: number }, config?: { ttl?: number },
@ -595,41 +607,41 @@ export function resourceTest(
config?: { ttl?: number }, config?: { ttl?: number },
): Promise<ResourceTestResult>; ): Promise<ResourceTestResult>;
export function resourceTest(...args: any) { export function resourceTest(...args: any[]) {
return callFunction$$( return callFunction$$(
args, args,
{ {
functionName: "resourceTest", functionName: "resourceTest",
arrow: { arrow: {
tag: "arrow",
domain: { domain: {
tag: "labeledProduct",
fields: { fields: {
label: { label: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
}, },
tag: "labeledProduct",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "option",
type: { type: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
tag: "option",
}, },
{ {
tag: "array",
type: { type: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
tag: "array",
}, },
], ],
tag: "unlabeledProduct",
}, },
tag: "arrow",
}, },
names: { names: {
relay: "-relay-", relay: "-relay-",
@ -650,11 +662,11 @@ export const helloTest_script = `
(seq (seq
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-) (call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
(xor (xor
(call %init_peer_id% ("hello-world" "hello") ["Fluence user"] hello) (call %init_peer_id% ("hello-world" "hello") ["Fluence user"] ret)
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 0]) (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 0])
) )
) )
(call %init_peer_id% ("callbackSrv" "response") [hello]) (call %init_peer_id% ("callbackSrv" "response") [ret])
) )
`; `;
@ -665,26 +677,26 @@ export function helloTest(
config?: { ttl?: number }, config?: { ttl?: number },
): Promise<string>; ): Promise<string>;
export function helloTest(...args: any) { export function helloTest(...args: any[]) {
return callFunction$$( return callFunction$$(
args, args,
{ {
functionName: "helloTest", functionName: "helloTest",
arrow: { arrow: {
tag: "arrow",
domain: { domain: {
tag: "labeledProduct",
fields: {}, fields: {},
tag: "labeledProduct",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
], ],
tag: "unlabeledProduct",
}, },
tag: "arrow",
}, },
names: { names: {
relay: "-relay-", relay: "-relay-",
@ -707,11 +719,11 @@ export const callHappy_script = `
(seq (seq
(seq (seq
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-) (call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
(call %init_peer_id% ("getDataSrv" "a") [] a) (call %init_peer_id% ("getDataSrv" "a") [] -a-arg-)
) )
(call %init_peer_id% ("getDataSrv" "b") [] b) (call %init_peer_id% ("getDataSrv" "b") [] -b-arg-)
) )
(call %init_peer_id% ("getDataSrv" "c") [] c) (call %init_peer_id% ("getDataSrv" "c") [] -c-arg-)
) )
(xor (xor
(xor (xor
@ -729,10 +741,7 @@ export function callHappy(
a: string, a: string,
b: number, b: number,
c: number, c: number,
d: ( d: (arg0: string) => number | Promise<number>,
arg0: string,
callParams: CallParams$$<"arg0">,
) => number | Promise<number>,
config?: { ttl?: number }, config?: { ttl?: number },
): Promise<number>; ): Promise<number>;
@ -741,67 +750,64 @@ export function callHappy(
a: string, a: string,
b: number, b: number,
c: number, c: number,
d: ( d: (arg0: string) => number | Promise<number>,
arg0: string,
callParams: CallParams$$<"arg0">,
) => number | Promise<number>,
config?: { ttl?: number }, config?: { ttl?: number },
): Promise<number>; ): Promise<number>;
export function callHappy(...args: any) { export function callHappy(...args: any[]) {
return callFunction$$( return callFunction$$(
args, args,
{ {
functionName: "callHappy", functionName: "callHappy",
arrow: { arrow: {
tag: "arrow",
domain: { domain: {
tag: "labeledProduct",
fields: { fields: {
a: { a: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
b: { b: {
tag: "scalar",
name: "f64", name: "f64",
tag: "scalar",
}, },
c: { c: {
tag: "scalar",
name: "f64", name: "f64",
tag: "scalar",
}, },
d: { d: {
tag: "arrow",
domain: { domain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
], ],
tag: "unlabeledProduct",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "scalar",
name: "f64", name: "f64",
tag: "scalar",
}, },
], ],
tag: "unlabeledProduct",
},
tag: "arrow",
}, },
}, },
}, tag: "labeledProduct",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "scalar",
name: "f64", name: "f64",
tag: "scalar",
}, },
], ],
tag: "unlabeledProduct",
}, },
tag: "arrow",
}, },
names: { names: {
relay: "-relay-", relay: "-relay-",
@ -822,7 +828,7 @@ export const demo_calculation_script = `
(seq (seq
(seq (seq
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-) (call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
(call %init_peer_id% ("getDataSrv" "service_id") [] service_id) (call %init_peer_id% ("getDataSrv" "service_id") [] -service_id-arg-)
) )
(xor (xor
(seq (seq
@ -830,21 +836,21 @@ export const demo_calculation_script = `
(seq (seq
(seq (seq
(seq (seq
(call %init_peer_id% (service_id "test_logs") []) (call %init_peer_id% (-service_id-arg- "test_logs") [])
(call %init_peer_id% (service_id "add") [10]) (call %init_peer_id% (-service_id-arg- "add") [10] ret)
) )
(call %init_peer_id% (service_id "multiply") [5]) (call %init_peer_id% (-service_id-arg- "multiply") [5] ret-0)
) )
(call %init_peer_id% (service_id "subtract") [8]) (call %init_peer_id% (-service_id-arg- "subtract") [8] ret-1)
) )
(call %init_peer_id% (service_id "divide") [6]) (call %init_peer_id% (-service_id-arg- "divide") [6] ret-2)
) )
(call %init_peer_id% (service_id "state") [] res) (call %init_peer_id% (-service_id-arg- "state") [] ret-3)
) )
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 0]) (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 0])
) )
) )
(call %init_peer_id% ("callbackSrv" "response") [res]) (call %init_peer_id% ("callbackSrv" "response") [ret-3])
) )
`; `;
@ -859,31 +865,31 @@ export function demo_calculation(
config?: { ttl?: number }, config?: { ttl?: number },
): Promise<number>; ): Promise<number>;
export function demo_calculation(...args: any) { export function demo_calculation(...args: any[]) {
return callFunction$$( return callFunction$$(
args, args,
{ {
functionName: "demo_calculation", functionName: "demo_calculation",
arrow: { arrow: {
tag: "arrow",
domain: { domain: {
tag: "labeledProduct",
fields: { fields: {
service_id: { service_id: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
}, },
tag: "labeledProduct",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "scalar",
name: "f64", name: "f64",
tag: "scalar",
}, },
], ],
tag: "unlabeledProduct",
}, },
tag: "arrow",
}, },
names: { names: {
relay: "-relay-", relay: "-relay-",
@ -904,7 +910,7 @@ export const marineTest_script = `
(seq (seq
(seq (seq
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-) (call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
(call %init_peer_id% ("getDataSrv" "wasm64") [] wasm64) (call %init_peer_id% ("getDataSrv" "wasm64") [] -wasm64-arg-)
) )
(xor (xor
(seq (seq
@ -913,23 +919,23 @@ export const marineTest_script = `
(seq (seq
(seq (seq
(seq (seq
(call %init_peer_id% ("single_module_srv" "create") [wasm64] serviceResult) (call %init_peer_id% ("single_module_srv" "create") [-wasm64-arg-] ret)
(call %init_peer_id% (serviceResult.$.service_id.[0] "test_logs") []) (call %init_peer_id% (ret.$.service_id.[0] "test_logs") [])
) )
(call %init_peer_id% (serviceResult.$.service_id.[0] "add") [10]) (call %init_peer_id% (ret.$.service_id.[0] "add") [10] ret-0)
) )
(call %init_peer_id% (serviceResult.$.service_id.[0] "multiply") [5]) (call %init_peer_id% (ret.$.service_id.[0] "multiply") [5] ret-1)
) )
(call %init_peer_id% (serviceResult.$.service_id.[0] "subtract") [8]) (call %init_peer_id% (ret.$.service_id.[0] "subtract") [8] ret-2)
) )
(call %init_peer_id% (serviceResult.$.service_id.[0] "divide") [6]) (call %init_peer_id% (ret.$.service_id.[0] "divide") [6] ret-3)
) )
(call %init_peer_id% (serviceResult.$.service_id.[0] "state") [] res) (call %init_peer_id% (ret.$.service_id.[0] "state") [] ret-4)
) )
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 0]) (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 0])
) )
) )
(call %init_peer_id% ("callbackSrv" "response") [res]) (call %init_peer_id% ("callbackSrv" "response") [ret-4])
) )
`; `;
@ -944,31 +950,31 @@ export function marineTest(
config?: { ttl?: number }, config?: { ttl?: number },
): Promise<number>; ): Promise<number>;
export function marineTest(...args: any) { export function marineTest(...args: any[]) {
return callFunction$$( return callFunction$$(
args, args,
{ {
functionName: "marineTest", functionName: "marineTest",
arrow: { arrow: {
tag: "arrow",
domain: { domain: {
tag: "labeledProduct",
fields: { fields: {
wasm64: { wasm64: {
tag: "scalar",
name: "string", name: "string",
tag: "scalar",
}, },
}, },
tag: "labeledProduct",
}, },
codomain: { codomain: {
tag: "unlabeledProduct",
items: [ items: [
{ {
tag: "scalar",
name: "f64", name: "f64",
tag: "scalar",
}, },
], ],
tag: "unlabeledProduct",
}, },
tag: "arrow",
}, },
names: { names: {
relay: "-relay-", relay: "-relay-",
@ -983,5 +989,3 @@ export function marineTest(...args: any) {
marineTest_script, marineTest_script,
); );
} }
/* eslint-enable */

View File

@ -14,13 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { ArrowWithoutCallbacks, NonArrowType } from "@fluencelabs/interfaces"; import { ArrowType, NonArrowType } from "@fluencelabs/interfaces";
import { match, P } from "ts-pattern"; import { match, P } from "ts-pattern";
import { getFuncArgs } from "./utils.js"; import { getFuncArgs } from "./utils.js";
export function genTypeName( export function genTypeName(
t: NonArrowType | ArrowWithoutCallbacks, t: NonArrowType | ArrowType,
name: string, name: string,
): readonly [string | undefined, string] { ): readonly [string | undefined, string] {
const genType = typeToTs(t); const genType = typeToTs(t);
@ -46,7 +46,7 @@ export function genTypeName(
}); });
} }
export function typeToTs(t: NonArrowType | ArrowWithoutCallbacks): string { export function typeToTs(t: NonArrowType | ArrowType): string {
return match(t) return match(t)
.with({ tag: "nil" }, () => { .with({ tag: "nil" }, () => {
return "null"; return "null";
@ -120,6 +120,8 @@ export function typeToTs(t: NonArrowType | ArrowWithoutCallbacks): string {
return [name, typeToTs(type)]; return [name, typeToTs(type)];
}); });
// JS-client argument
if (domain.tag !== "unlabeledProduct") {
const generic = const generic =
args.length === 0 args.length === 0
? "null" ? "null"
@ -130,6 +132,7 @@ export function typeToTs(t: NonArrowType | ArrowWithoutCallbacks): string {
.join(" | "); .join(" | ");
args.push(["callParams", `CallParams$$<${generic}>`]); args.push(["callParams", `CallParams$$<${generic}>`]);
}
const funcArgs = args const funcArgs = args
.map(([name, type]) => { .map(([name, type]) => {

View File

@ -20,6 +20,8 @@ import { genTypeName, typeToTs } from "../common.js";
import { CLIENT } from "../constants.js"; import { CLIENT } from "../constants.js";
import { capitalize, getFuncArgs } from "../utils.js"; import { capitalize, getFuncArgs } from "../utils.js";
import { DefaultServiceId } from "./service.js";
export interface TypeGenerator { export interface TypeGenerator {
type(field: string, type: string): string; type(field: string, type: string): string;
generic(field: string, type: string): string; generic(field: string, type: string): string;
@ -117,11 +119,18 @@ export class TSTypeGenerator implements TypeGenerator {
const serviceDecl = `service: ${srvName}Def`; const serviceDecl = `service: ${srvName}Def`;
const serviceIdDecl = `serviceId: string`; const serviceIdDecl = `serviceId: string`;
const registerServiceArgs = [ const registerServiceArgs =
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
(srvDef.defaultServiceId as DefaultServiceId).s_Some__f_value != null
? [
[serviceDecl], [serviceDecl],
[serviceIdDecl, serviceDecl], [serviceIdDecl, serviceDecl],
[peerDecl, serviceDecl], [peerDecl, serviceDecl],
[peerDecl, serviceIdDecl, serviceDecl], [peerDecl, serviceIdDecl, serviceDecl],
]
: [
[serviceIdDecl, serviceDecl],
[peerDecl, serviceIdDecl, serviceDecl],
]; ];
return [ return [

View File

@ -20,7 +20,7 @@ import { recursiveRenameLaquaProps } from "../utils.js";
import { TypeGenerator } from "./interfaces.js"; import { TypeGenerator } from "./interfaces.js";
interface DefaultServiceId { export interface DefaultServiceId {
s_Some__f_value?: string; s_Some__f_value?: string;
} }

View File

@ -0,0 +1,120 @@
/**
* 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 {
ArrowWithoutCallbacks,
FunctionCallDef,
JSONValue,
SimpleTypes,
UnlabeledProductType,
} from "@fluencelabs/interfaces";
import { typeToTs } from "../common.js";
export function validateFunctionCall(
schema: FunctionCallDef,
...args: JSONValue[]
) {
const schemaArgs =
schema.arrow.domain.tag === "nil"
? []
: Object.values(schema.arrow.domain.fields);
if (args.length !== schemaArgs.length) {
throw new Error(
`Expected ${schemaArgs.length} arguments but provided ${args.length}`,
);
}
for (let i = 0; i < args.length; i++) {
validateFunctionCallArg(schemaArgs[i], args[i], i + 1);
}
}
export function validateFunctionCallArg(
schema: SimpleTypes | UnlabeledProductType | ArrowWithoutCallbacks,
arg: JSONValue,
argIndex: number,
) {
if (!isTypeMatchesSchema(schema, arg)) {
const expectedType = typeToTs(schema);
throw new Error(
`Argument ${argIndex} doesn't match schema. Expected type: ${expectedType}`,
);
}
}
export function isTypeMatchesSchema(
schema: SimpleTypes | UnlabeledProductType | ArrowWithoutCallbacks,
arg: JSONValue,
): boolean {
if (schema.tag === "nil") {
return arg === null;
} else if (schema.tag === "option") {
return arg === null || isTypeMatchesSchema(schema.type, arg);
} else if (schema.tag === "scalar") {
if (
[
"u8",
"u16",
"u32",
"u64",
"i8",
"i16",
"i32",
"i64",
"f32",
"f64",
].includes(schema.name)
) {
return typeof arg === "number";
} else if (schema.name === "bool") {
return typeof arg === "boolean";
} else if (schema.name === "string") {
return typeof arg === "string";
} else {
// Should not be possible
return false;
}
} else if (schema.tag === "array") {
return (
Array.isArray(arg) &&
arg.every((item) => {
return isTypeMatchesSchema(schema.type, item);
})
);
} else if (schema.tag === "struct") {
return (
!Array.isArray(arg) &&
typeof arg === "object" &&
arg !== null &&
Object.entries(schema.fields).every(([field, type]) => {
return isTypeMatchesSchema(type, arg[field]);
})
);
} else if (schema.tag === "unlabeledProduct") {
return (
Array.isArray(arg) &&
arg.every((item, index) => {
return isTypeMatchesSchema(schema.items[index], item);
})
);
} else if (schema.tag === "arrow") {
return typeof arg === "function";
} else {
return schema.tag === "topType";
}
}

View File

@ -154,7 +154,13 @@ export type ProductType = UnlabeledProductType | LabeledProductType;
* ArrowType is a profunctor pointing its domain to codomain. * ArrowType is a profunctor pointing its domain to codomain.
* Profunctor means variance: Arrow is contravariant on domain, and variant on codomain. * Profunctor means variance: Arrow is contravariant on domain, and variant on codomain.
*/ */
export type ArrowType<T extends LabeledProductType | UnlabeledProductType> = { export type ArrowType<
T extends
| LabeledProductType<SimpleTypes | ArrowType<UnlabeledProductType>>
| UnlabeledProductType =
| LabeledProductType<SimpleTypes | ArrowType<UnlabeledProductType>>
| UnlabeledProductType,
> = {
/** /**
* Type descriptor. Used for pattern-matching * Type descriptor. Used for pattern-matching
*/ */
@ -174,14 +180,14 @@ export type ArrowType<T extends LabeledProductType | UnlabeledProductType> = {
/** /**
* Arrow which domain contains only non-arrow types * Arrow which domain contains only non-arrow types
*/ */
export type ArrowWithoutCallbacks = ArrowType< export type ArrowWithoutCallbacks = ArrowType<UnlabeledProductType>;
UnlabeledProductType | LabeledProductType<SimpleTypes>
>;
/** /**
* Arrow which domain does can contain both non-arrow types and arrows (which themselves cannot contain arrows) * Arrow which domain does can contain both non-arrow types and arrows (which themselves cannot contain arrows)
*/ */
export type ArrowWithCallbacks = ArrowType<LabeledProductType>; export type ArrowWithCallbacks = ArrowType<
LabeledProductType<SimpleTypes | ArrowWithoutCallbacks>
>;
export interface FunctionCallConstants { export interface FunctionCallConstants {
/** /**
@ -232,9 +238,7 @@ export interface FunctionCallDef {
/** /**
* Underlying arrow which represents function in aqua * Underlying arrow which represents function in aqua
*/ */
arrow: ArrowType< arrow: ArrowWithCallbacks;
LabeledProductType<SimpleTypes | ArrowType<UnlabeledProductType>>
>;
/** /**
* Names of the different entities used in generated air script * Names of the different entities used in generated air script

View File

@ -25,7 +25,9 @@ import type {
ArrowWithoutCallbacks, ArrowWithoutCallbacks,
JSONArray, JSONArray,
JSONValue, JSONValue,
LabeledProductType,
NonArrowType, NonArrowType,
SimpleTypes,
} from "@fluencelabs/interfaces"; } from "@fluencelabs/interfaces";
import { match } from "ts-pattern"; import { match } from "ts-pattern";
@ -95,7 +97,7 @@ export const aqua2ts = (value: JSONValue, type: NonArrowType): JSONValue => {
*/ */
export const aquaArgs2Ts = ( export const aquaArgs2Ts = (
req: CallServiceData, req: CallServiceData,
arrow: ArrowWithoutCallbacks, arrow: ArrowType<LabeledProductType<SimpleTypes>>,
): JSONArray => { ): JSONArray => {
const argTypes = match(arrow.domain) const argTypes = match(arrow.domain)
.with({ tag: "labeledProduct" }, (x) => { .with({ tag: "labeledProduct" }, (x) => {
@ -187,6 +189,7 @@ export const returnType2Aqua = (
returnValue: any, returnValue: any,
arrowType: ArrowType<NonArrowType>, arrowType: ArrowType<NonArrowType>,
) => { ) => {
// TODO: cover with tests
if (arrowType.codomain.tag === "nil") { if (arrowType.codomain.tag === "nil") {
return {}; return {};
} }

View File

@ -0,0 +1,28 @@
/**
* 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 { JSONArray, JSONValue } from "@fluencelabs/interfaces";
import { ParticleContext } from "../jsServiceHost/interfaces.js";
export type MaybePromise<T> = T | Promise<T>;
export type ServiceImpl = Record<
string,
(
...args: [...JSONArray, ParticleContext]
) => MaybePromise<JSONValue | undefined>
>;

6697
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
{ {
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"include": ["**/src/**/*"] "include": ["packages"],
"exclude": ["node_modules", "dist", "build"]
} }