diff --git a/.github/workflows/binary.yml b/.github/workflows/binary.yml deleted file mode 100644 index 6fec22e0..00000000 --- a/.github/workflows/binary.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: "Publish binary aqua" - -on: - workflow_dispatch: - inputs: - runs-on: - type: string - required: true - arch: - type: string - required: true - os: - type: string - required: true - static: - type: boolean - required: true - workflow_call: - inputs: - runs-on: - type: string - required: true - arch: - type: string - required: true - os: - type: string - required: true - static: - type: boolean - required: true - -jobs: - build: - name: "Publish aqua-native" - runs-on: ${{ inputs.runs-on }} - timeout-minutes: 10 - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - uses: graalvm/setup-graalvm@v1 - with: - version: '22.3.1' - java-version: '17' - set-java-home: true - components: 'native-image' - github-token: ${{ secrets.GITHUB_TOKEN }} - - - uses: coursier/cache-action@v6 - - - uses: coursier/setup-action@v1 - with: - apps: sbt - - - name: build - run: sbt "cli/GraalVMNativeImage/packageBin" - env: - COMPILE_STATIC: ${{ inputs.static }} - - - uses: actions/upload-artifact@v3 - with: - name: aqua-${{ inputs.os }}-${{ inputs.arch }} - path: cli/cli/.jvm/target/graalvm-native-image/cli - - - uses: actions/upload-artifact@v3 - with: - name: aqua-${{ inputs.os }}-${{ inputs.arch }} - path: cli/cli/.jvm/target/graalvm-native-image/cli diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9163340e..ba27b986 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -41,7 +41,7 @@ jobs: apps: sbt - name: scala-js build - run: sbt ";cliJS/fullOptJS;language-server-apiJS/fullOptJS;aqua-apiJS/fullOptJS" + run: sbt ";language-server-apiJS/fullOptJS;aqua-apiJS/fullOptJS" - name: Import secrets uses: hashicorp/vault-action@v2.7.3 @@ -73,24 +73,3 @@ jobs: - name: Publish to NPM registry run: pnpm --filter='!integration-tests' publish --access public --tag unstable - - aqua-native: - name: "Publish aqua-native" - strategy: - matrix: - runner: - - runs-on: ubuntu-latest - arch: amd64 - os: linux - static: true - - runs-on: macos-latest - arch: amd64 - os: macos - static: false - - uses: ./.github/workflows/binary.yml - with: - runs-on: ${{ matrix.runner.runs-on }} - arch: ${{ matrix.runner.arch }} - os: ${{ matrix.runner.os }} - static: ${{ matrix.runner.static }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d41b836..472d977f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -74,10 +74,6 @@ jobs: registry-url: "https://registry.npmjs.org" cache: "pnpm" - - name: Set cli version - run: pnpm version ${{ steps.version.outputs.version }} - working-directory: cli/cli-npm - - name: Set api version run: pnpm version ${{ steps.version.outputs.version }} working-directory: api/api-npm @@ -86,11 +82,6 @@ jobs: run: pnpm version ${{ steps.version.outputs.version }} working-directory: language-server/language-server-npm - - name: Set cli version in tests - run: | - pnpm add @fluencelabs/aqua@${{ steps.version.outputs.version }} --save-workspace-protocol=false - working-directory: integration-tests - - name: Regenerate lock run: pnpm -r i diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index b8af390f..27873d21 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -51,7 +51,7 @@ jobs: - name: scala-js build env: SNAPSHOT: ${{ steps.version.outputs.id }} - run: sbt ";cliJS/fastOptJS;language-server-apiJS/fastOptJS;aqua-apiJS/fastOptJS" + run: sbt ";language-server-apiJS/fastOptJS;aqua-apiJS/fastOptJS" - name: Import secrets uses: hashicorp/vault-action@v2.7.3 diff --git a/ci.cjs b/ci.cjs index f8480dcc..022a4c89 100644 --- a/ci.cjs +++ b/ci.cjs @@ -36,7 +36,6 @@ function validateArgs() { } const PATHS_TO_PACKAGES = [ - "./cli/cli-npm", "./api/api-npm", "./language-server/language-server-npm", "./integration-tests" diff --git a/cli/cli-npm/.gitignore b/cli/cli-npm/.gitignore deleted file mode 100644 index c1f9ccff..00000000 --- a/cli/cli-npm/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.jar -*.tgz -node_modules diff --git a/cli/cli-npm/LICENSE b/cli/cli-npm/LICENSE deleted file mode 100644 index 74732650..00000000 --- a/cli/cli-npm/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -Copyright 2021 Fluence Labs - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/cli/cli-npm/README.md b/cli/cli-npm/README.md deleted file mode 100644 index 831475f9..00000000 --- a/cli/cli-npm/README.md +++ /dev/null @@ -1,56 +0,0 @@ -## Aqua - -Aqua is a new-gen language for distributed systems. - -Aqua programs are executed on many peers, sequentially -or in parallel, forming a single-use coordination network. - -Aqua's runtime is heterogeneous: it includes browsers, servers, devices, all involved in solving a single task. -Therefore, Aqua scripts are compiled into several targets at once, with AIR and Typescript as a default. - -## aqua - -The package contains a convenience `aqua` wrapper for usage in npm-based projects. - -### usage - -Get the latest package - -```bash -npm i --save-dev @fluencelabs/aqua -``` - -Create a directory for the source files: `.aqua` and for compiled files: `.ts` - -``` -mkdir src/aqua src/compiled -``` - -To compile files run: - -```bash -aqua -i ./src/aqua/ -o ./src/compiled -``` - -Alternatively the compilation script can be put into scripts section of `package.json` - -``` -... -"scripts": { - ... - "compile": "aqua -i ./src/aqua/ -o ./src/compiled" -}, -... -``` - -and can be started with - -``` -npm run compile -``` - -### references - -- For the list of compiler options see: https://github.com/fluencelabs/aqua -- To get started writing aqua see: https://github.com/fluencelabs/aqua-playground - diff --git a/cli/cli-npm/aqua-run.md b/cli/cli-npm/aqua-run.md deleted file mode 100644 index ee4b510e..00000000 --- a/cli/cli-npm/aqua-run.md +++ /dev/null @@ -1,45 +0,0 @@ -## Installation - -- run `sbt "cliJS/fullLinkJS"` in a root dir of a project after any code update (better to keep `sbt` running for faster compilation) -- `npm` installed required -- run `npm i` in `npm` directory -- feel free to change `@fluencelabs/fluence` version in `package.json` file, run `npm i` after changes - -## Run script - -Generally, use this script to run compiled aqua compiler from a repo: - -``` -npm run from:scalajs -- run -f "someFunction(arg1, arg2)" -i path/to/aqua --data-path path/to/args -m path/to/exports --addr /multiaddr/to/node -``` - -- `-f or --func` is a function to call with arguments -- `-i or --input` aqua file where function located -- `-m or --import` imports location, could be used multiple times -- `-a or --addr` multiaddress to a Fluence node -- `-p or --data-path` path to a file with JSON where arguments are located - -As example, use `test/sample.aqua` with args from `test/data.json` running on `/dns4/kras-04.fluence.dev/tcp/19001/wss/p2p/12D3KooWFEwNWcHqi9rtsmDhsYcDbRUCDXH84RC4FW6UfsFWaoHi` node: - -``` -npm run from:scalajs -- run -f "identityArgsAndReturn(structField, stringField, numberField)" -i test/sample.aqua --data-path test/data.json --addr /dns4/kras-04.fluence.dev/tcp/19001/wss/p2p/12D3KooWFEwNWcHqi9rtsmDhsYcDbRUCDXH84RC4FW6UfsFWaoHi -``` - -To simplify experience you can use `./aqua-run.sh` command and change all arguments straight in this file. - -## Node addresses - -Different Fluence network addresses could be found here: https://github.com/fluencelabs/fluence-network-environment/blob/main/src/index.ts - -## Useful flags -- `--print-air` to print resulted air -- `--no-xor` to disable xor wrapping aroung service calls -- `--sk secret_key` send request signed with specific secret key. Secret key could be created with `npm run from:scalajs -- create_keypair` or `aqua create_keypair` if you want to use installed aqua -- `--data "json""` use instead of `--data-path` to pass arguments through command line -- `--timeout 10000` to change timeout -- `--log-level debug/info/..` to change log level - -## Builtins for `aqua run` - -You can find all builtins in aqua/run-builtins/run-builtins.aqua - diff --git a/cli/cli-npm/aqua-run.sh b/cli/cli-npm/aqua-run.sh deleted file mode 100755 index a2ed84fa..00000000 --- a/cli/cli-npm/aqua-run.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -FUNC='deploy(tsOracle)' -INPUT='aqua/dist.aqua' -DATAPATH='test/deploy.json' -ADDR='/dns4/kras-04.fluence.dev/tcp/19001/wss/p2p/12D3KooWFEwNWcHqi9rtsmDhsYcDbRUCDXH84RC4FW6UfsFWaoHi' -# IMPORT= - -if [ -z "$IMPORT" ] -then - npm run build - npm run -- run -f "$FUNC" -i "$INPUT" --data-path "$DATAPATH" --addr "$ADDR" -else - npm run build - npm run run -- run -f "$FUNC" -i "$INPUT" --data-path "$DATAPATH" --addr "$ADDR" -m "$IMPORT" -fi diff --git a/cli/cli-npm/aqua/dist.aqua b/cli/cli-npm/aqua/dist.aqua deleted file mode 100644 index 0f716c0a..00000000 --- a/cli/cli-npm/aqua/dist.aqua +++ /dev/null @@ -1,96 +0,0 @@ -module ServiceDist declares * - -import "run-builtins/run-builtins.aqua" -import "@fluencelabs/aqua-lib/builtin.aqua" -import "@fluencelabs/aqua-ipfs/ipfs.aqua" - -export deploy, remove, createService, addBlueprint - -data ModuleConf: - name: string - path: string - mounted_binaries: ?[][]string - preopened_files: ?[]string - mapped_dirs: ?[][]string - envs: ?[][]string - logger_enabled: ?bool - logging_mask: ?i32 - mem_pages_count: ?u32 - max_heap_size: ?string - -service OpC("op"): - array_length(arr: []ModuleConf) -> u32 - -data DeployResult: - blueprint_id: string - service_id: string - -service DeployHelper("deploy_helper"): - create_result(bid: string, sid: string) -> DeployResult - -data ServiceConf: - modules: []ModuleConf - -const ON_PEER ?= HOST_PEER_ID - -func flattenSS(input: [][]string) -> ?[][]string: - res: *[][]string - res <<- input - <- res - -func flattenS(input: []string) -> ?[]string: - res: *[]string - res <<- input - <- res - -func deploy(serviceName: string, serviceConf: ServiceConf) -> DeployResult: - - on ON_PEER: - multiaddr <- Ipfs.get_external_api_multiaddr() - - mod_hashes: *[]string - for m <- serviceConf.modules par: - -- TODO check for cache - Console.print(Op.concat_strings("Going to upload module: ", m.name)) - uploadRes <- LocalIpfs.uploadFile(m.path, multiaddr) - cid = uploadRes.cid - Console.print(Op.concat_strings(Op.concat_strings("Module '", m.name), "' was uploaded")) - - on ON_PEER: - hostRes <- Ipfs.get(cid) - conf <- Dist.make_module_config(m.name, m.mem_pages_count, m.max_heap_size, m.logger_enabled, m.preopened_files, m.envs, m.mapped_dirs, m.mounted_binaries, m.logging_mask) - mod_hash <- Dist.add_module_from_vault(hostRes.path, conf) - mod_hashes <<- [mod_hash, m.name] - - join mod_hashes[OpC.array_length(serviceConf.modules) - 1] - - -- sort hashes to the same order as was in serviceConf.modules - sorted_hashes: *string - for m <- serviceConf.modules: - for hash_name <- mod_hashes: - if m.name == hash_name[1]: - sorted_hashes <<- hash_name[0] - - Console.print("Now time to make the blueprint...") - on ON_PEER: - blueprint <- Dist.make_blueprint(serviceName, sorted_hashes) - blueprint_id <- Dist.add_blueprint(blueprint) - service_id <- Srv.create(blueprint_id) - - res <- DeployHelper.create_result(blueprint_id, service_id) - <- res - -func remove(service_id: string): - on ON_PEER: - Srv.remove(service_id) - Console.print("Service was deleted") - -func createService(blueprint_id: string) -> string: - on ON_PEER: - service_id <- Srv.create(blueprint_id) - <- service_id - -func addBlueprint(bp: AddBlueprint) -> string: - on ON_PEER: - blueprint_id <- Dist.add_blueprint(bp) - <- blueprint_id diff --git a/cli/cli-npm/aqua/ipfs.aqua b/cli/cli-npm/aqua/ipfs.aqua deleted file mode 100644 index 736e5cd6..00000000 --- a/cli/cli-npm/aqua/ipfs.aqua +++ /dev/null @@ -1,18 +0,0 @@ -module IpfsExports - -import "@fluencelabs/aqua-ipfs/ipfs-api.aqua" -import "run-builtins/run-builtins.aqua" - - -export uploadFile - -const ON_PEER ?= HOST_PEER_ID - -func uploadFile(path: string) -> UploadResult: - on ON_PEER: - multiaddr <- get_external_api_multiaddr(ON_PEER) - result <- LocalIpfs.uploadFile(path, multiaddr) - <- result - - - diff --git a/cli/cli-npm/aqua/network-info.aqua b/cli/cli-npm/aqua/network-info.aqua deleted file mode 100644 index 58ac0048..00000000 --- a/cli/cli-npm/aqua/network-info.aqua +++ /dev/null @@ -1,41 +0,0 @@ -module NetworkInfo - -import "@fluencelabs/aqua-lib/builtin.aqua" - -export list_modules, list_interfaces_by_peer, get_interface, list_blueprints, list_services - -const ON_PEER ?= HOST_PEER_ID - -func list_modules() -> []Module: - on ON_PEER: - res <- Dist.list_modules() - <- res - -func list_services() -> []Service: - on ON_PEER: - services <- Srv.list() - <- services - -func list_interfaces_by_peer(peer: PeerId) -> []Interface: - on ON_PEER: - services <- Srv.list() - interfaces: *Interface - for srv <- services: - if srv.owner_id == peer: - interfaces <- Srv.get_interface(srv.id) - <- interfaces - -func get_interface(serviceId: string) -> Interface: - on ON_PEER: - res <- Srv.get_interface(serviceId) - <- res - -func get_module_interface(moduleHash: string) -> Interface: - on ON_PEER: - res <- Dist.get_module_interface(moduleHash) - <- res - -func list_blueprints() -> []Blueprint: - on ON_PEER: - res <- Dist.list_blueprints() - <- res diff --git a/cli/cli-npm/aqua/run-builtins/run-builtins.aqua b/cli/cli-npm/aqua/run-builtins/run-builtins.aqua deleted file mode 100644 index 89ccfb5d..00000000 --- a/cli/cli-npm/aqua/run-builtins/run-builtins.aqua +++ /dev/null @@ -1,13 +0,0 @@ -import "@fluencelabs/aqua-ipfs/ipfs.aqua" - --- printing strings in console -service Console("run-console"): - print(str: string) - -data UploadResult: - error: string - cid: string - size: u64 - -service LocalIpfs("ipfs"): - uploadFile(path: string, multiaddr: IpfsMultiaddrResult) -> UploadResult \ No newline at end of file diff --git a/cli/cli-npm/aqua/script.aqua b/cli/cli-npm/aqua/script.aqua deleted file mode 100644 index a4b0881d..00000000 --- a/cli/cli-npm/aqua/script.aqua +++ /dev/null @@ -1,28 +0,0 @@ -module ServiceScript declares * - -import "run-builtins/run-builtins.aqua" -import "@fluencelabs/aqua-lib/builtin.aqua" -import "@fluencelabs/aqua-ipfs/ipfs.aqua" - -export schedule, remove, list - -const ON_PEER ?= HOST_PEER_ID - -func schedule(air: string, interval: ?u64) -> string: - on ON_PEER: - res <- Script.add(air, interval) - Console.print("Script was scheduled") - <- res - -func remove(script_id: string): - on ON_PEER: - res <- Script.remove(script_id) - if res: - Console.print("Script was removed") - else: - Console.print("No script with such ID") - -func list() -> []ScriptInfo: - on ON_PEER: - res <- Script.list() - <- res \ No newline at end of file diff --git a/cli/cli-npm/error.js b/cli/cli-npm/error.js deleted file mode 100755 index e46877a7..00000000 --- a/cli/cli-npm/error.js +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env node - -"use strict"; - -console.error("ERROR: use 'aqua' command!") diff --git a/cli/cli-npm/index.js b/cli/cli-npm/index.js deleted file mode 100755 index 69237637..00000000 --- a/cli/cli-npm/index.js +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env node - -"use strict"; - -handleEPIPE(process.stderr) -handleEPIPE(process.stdout) -function handleEPIPE(stream) { - stream.on('error', onerror) - function onerror(err) { - if (err.code === 'EPIPE') { - stream._write = noopWrite - stream._writev = noopWritev - stream._read = noopRead - return stream.removeListener('error', onerror) - } - if (EE.listenerCount(stream, 'error') === 1) { - stream.removeListener('error', onerror) - stream.emit('error', err) - } - } -} -function noopWrite(chunk, enc, cb) { - cb() -} -function noopRead() { - this.push('') -} -function noopWritev(chunks, cb) { - cb() -} - -import "./aqua.js"; diff --git a/cli/cli-npm/meta-utils.js b/cli/cli-npm/meta-utils.js deleted file mode 100644 index cf5b14c2..00000000 --- a/cli/cli-npm/meta-utils.js +++ /dev/null @@ -1,2 +0,0 @@ -// It should work in scala as js.`import`.meta.url, but it doesn't compile for some reasons -export const metaUrl = import.meta.url diff --git a/cli/cli-npm/package.json b/cli/cli-npm/package.json deleted file mode 100644 index 9c4075ce..00000000 --- a/cli/cli-npm/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "@fluencelabs/aqua", - "version": "0.12.1", - "description": "Aqua compiler", - "type": "module", - "files": [ - "aqua.js", - "index.js", - "error.js", - "meta-utils.js", - "dist/*", - "aqua/*" - ], - "bin": { - "aqua": "index.js", - "aqua-cli": "error.js" - }, - "scripts": { - "run": "node index.js", - "build": "tsc" - }, - "dependencies": { - "@fluencelabs/aqua-ipfs": "0.5.9", - "@fluencelabs/aqua-lib": "0.7.3", - "@fluencelabs/fluence": "0.28.0", - "@fluencelabs/fluence-network-environment": "1.1.2", - "ipfs-http-client": "50.1.2", - "multiaddr": "10.0.1" - }, - "devDependencies": { - "ts-node": "10.9.1", - "typescript": "5.1.3" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/fluencelabs/aqua.git" - }, - "keywords": [ - "aqua", - "fluence" - ], - "author": "Fluence Labs", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/fluencelabs/aqua/issues" - }, - "homepage": "https://github.com/fluencelabs/aqua#readme" -} diff --git a/cli/cli-npm/src/ipfs.ts b/cli/cli-npm/src/ipfs.ts deleted file mode 100644 index 8a2c629e..00000000 --- a/cli/cli-npm/src/ipfs.ts +++ /dev/null @@ -1,55 +0,0 @@ -import {create, globSource} from "ipfs-http-client"; -import { Multiaddr, protocols } from "multiaddr"; -import { existsSync } from "fs"; - -type UploadResult = { - cid: string, - size: number -} - -export async function uploadFile( - path: string, - multiaddrResult: any, - infoLogger: (s: string) => void, - errorLogger: (s: string) => void -): Promise { - - let rpcAddr; - - if (multiaddrResult.success) { - rpcAddr = multiaddrResult.multiaddr; - } else { - errorLogger( - "Failed to retrieve external api multiaddr" - ); - throw multiaddrResult.error; - } - - let rpcMaddr = new Multiaddr(rpcAddr).decapsulateCode( - protocols.names.p2p.code - ); - // HACK: `as any` is needed because ipfs-http-client forgot to add `| Multiaddr` to the `create` types - const ipfs = create(rpcMaddr as any); - infoLogger("created ipfs client to " + rpcMaddr); - - await ipfs.id(); - infoLogger("connected to ipfs"); - - if (!existsSync(path)) { - let errMsg = "File does not exist: " + path - errorLogger( - errMsg - ); - throw errMsg; - } - - const source: any = await globSource(path) - const file = await ipfs.add(source); - - infoLogger("file uploaded"); - - return { - cid: file.cid.toString(), - size: file.size - }; -} diff --git a/cli/cli-npm/test/data.json b/cli/cli-npm/test/data.json deleted file mode 100644 index 2a051b31..00000000 --- a/cli/cli-npm/test/data.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "target": "12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz", - "validators": [ - "12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er", - "12D3KooWBUJifCTgaxAUrcM9JysqCcS4CS8tiYH5hExbdWCAoNwb", - "12D3KooWJbJFaZ3k5sNd8DjQgg3aERoKtBAnirEvPV8yp76kEXHB", - "12D3KooWCKCeqLPSgMnDjyFsJuWqREDtKNHx1JEBiwaMXhCLNTRb", - "12D3KooWKnRcsTpYx9axkJ6d69LPfpPXrkVLe96skuPTAo76LLVH", - "12D3KooWBSdm6TkqnEFrgBuSkpVE3dR1kr6952DsWQRNwJZjFZBv", - "12D3KooWGzNvhSDsgFoHwpWHAyPf1kcTYCGeRBPfznL8J6qdyu2H", - "12D3KooWF7gjXhQ4LaKj6j7ntxsPpGk34psdQicN2KNfBi9bFKXg", - "12D3KooWB9P1xmV3c7ZPpBemovbwCiRRTKd3Kq2jsVPQN4ZukDfy" - ], - "timeout": 5000, - "stringField": "some string", - "numberField": 123, - "structField": { - "numField": 42, - "arrField": ["str1", "str2", "r43r34", "ferer"], - "arr2": [{ - "a": "fef", - "b": [1,2,3,4], - "c": "erfer", - "d": "frefe" - },{ - "b": [1,2,3,4], - "c": "erfer", - "d": "frefe" - }, { - "a": "as", - "c": "erfer", - "d": "gerrt" - }] - } -} diff --git a/cli/cli-npm/test/deploy.json b/cli/cli-npm/test/deploy.json deleted file mode 100644 index 9c545815..00000000 --- a/cli/cli-npm/test/deploy.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "serviceConf": { - "name": "ts-oracle", - "modules": [ - { - "name": "ts-oracle", - "path": "./deploy/ts_oracle.wasm", - "mounted_binaries": [] - } - ] - } -} - diff --git a/cli/cli-npm/test/sample.aqua b/cli/cli-npm/test/sample.aqua deleted file mode 100644 index 1b0ace41..00000000 --- a/cli/cli-npm/test/sample.aqua +++ /dev/null @@ -1,44 +0,0 @@ -import "@fluencelabs/aqua-lib/builtin.aqua" --- import "run-builtins.aqua" - -data StructType: - numField: u32 - arrField: []string - -service OpString("op"): - identity(s: string) -> string - -service OpNumber("op"): - identity(n: u32) -> u32 - -service OpStruct("op"): - identity(st: StructType) -> StructType - noop() - -func parseBug(): - stream: *string - if stream[0] != "FOO": - Op.noop() - -func identityArgsAndReturn (structArg: StructType, stringArg: string, numberArg: u32) -> string, u32, StructType: - on HOST_PEER_ID: - sArg <- OpString.identity(stringArg) - nArg = OpNumber.identity (numberArg) + OpNumber.identity (numberArg) - stArg <- OpStruct.identity(structArg) - -- it could be used only on init_peer_id - <- sArg, nArg, stArg - -service Ssss("ss"): - foo4: u64 -> u16 - -func aaa(a: u64) -> u16: - res <- Ssss.foo4(a) - <- res - -func bar(callback: u32 -> u32): - callback(1) - -func baz(): - bar(aaa) - - diff --git a/cli/cli-npm/tsconfig.json b/cli/cli-npm/tsconfig.json deleted file mode 100644 index 4979d1cd..00000000 --- a/cli/cli-npm/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - - "target": "esnext", - "module": "ESNext", - "lib": [ - "ESNext" - ], - "declaration": true, - "outDir": "dist", - "moduleResolution": "node", - "strict": true, - "esModuleInterop": true, - "noImplicitAny": false, - "strictNullChecks": false, - "skipLibCheck": true, - }, - "include": ["src/**/*"], - "exclude": [ - "node_modules", - "dist", - "bundle", - "src/__test__", - "src/compiled" - ] -} \ No newline at end of file diff --git a/cli/cli/.js/src/main/scala/aqua/ArgOpts.scala b/cli/cli/.js/src/main/scala/aqua/ArgOpts.scala deleted file mode 100644 index 1e79a079..00000000 --- a/cli/cli/.js/src/main/scala/aqua/ArgOpts.scala +++ /dev/null @@ -1,139 +0,0 @@ -package aqua - -import aqua.builder.ArgumentGetter -import aqua.js.VarJson -import aqua.parser.expr.func.CallArrowExpr -import aqua.parser.lexer.{CallArrowToken, CollectionToken, LiteralToken, VarToken} -import aqua.parser.lift.Span -import aqua.raw.value.{CollectionRaw, LiteralRaw, ValueRaw, VarRaw} -import aqua.types.* -import aqua.run.CliFunc -import cats.data.* -import cats.data.Validated.{invalid, invalidNec, invalidNel, valid, validNec, validNel} -import cats.effect.Concurrent -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.semigroup.* -import cats.syntax.traverse.* -import cats.{~>, Id, Semigroup} -import com.monovore.decline.Opts -import fs2.io.file.{Files, Path} - -import scala.collection.immutable.SortedMap -import scala.scalajs.js -import scala.scalajs.js.JSON - -case class FuncWithData(func: CliFunc, getters: Map[String, VarJson]) - -object ArgOpts { - - // Parses a function name and arguments from a string - def funcOpt: Opts[CliFunc] = - Opts - .option[String]("func", "Function to call with args", "f", "funcName(args)") - .mapValidated { str => - CliFunc.fromString(str) - } - - // Gets data from a file or from a json string - def dataFileOrStringOpt[F[_]: Files: Concurrent] - : Opts[F[ValidatedNec[String, Option[js.Dynamic]]]] = - (AppOpts.wrapWithOption(dataOpt), AppOpts.wrapWithOption(dataFromFileOpt[F])).mapN { - case (dataFromString, dataFromFile) => - dataFromFile match { - case Some(dataFromFileF) => - dataFromFileF.map(_.andThen(args => getData(Some(args), dataFromString))) - case None => validNec(dataFromString).pure[F] - } - } - - // Creates getters based on function arguments and data, return all info - def funcWithArgsOpt[F[_]: Files: Concurrent]: Opts[F[ValidatedNec[String, FuncWithData]]] = { - (dataFileOrStringOpt[F], funcOpt).mapN { case (dataF, func) => - dataF.map { dataV => - dataV.andThen { data => - VarJson.checkDataGetServices(func.args, data).map { case (argsWithTypes, getters) => - FuncWithData(func.copy(args = argsWithTypes), getters) - } - } - } - } - } - - def dataOpt: Opts[js.Dynamic] = - Opts - .option[String]( - "data", - "JSON in { [argumentName]: argumentValue } format. You can call a function using these argument names", - "d", - "json" - ) - .mapValidated { str => - Validated.catchNonFatal { - JSON.parse(str) - }.leftMap(t => NonEmptyList.one("Data argument isn't a valid JSON: " + t.getMessage)) - } - - def dataFromFileOpt[F[_]: Files: Concurrent]: Opts[F[ValidatedNec[String, js.Dynamic]]] = { - jsonFromFileOpt( - "data-path", - "Path to a JSON file in { [argumentName]: argumentValue } format. You can call a function using these argument names", - "p" - ) - } - - def jsonFromFileOpt[F[_]: Files: Concurrent]( - name: String, - help: String, - short: String - ): Opts[F[ValidatedNec[String, js.Dynamic]]] = { - FileOpts.fileOpt( - name, - help, - short, - (path, str) => { - Validated.catchNonFatal { - JSON.parse(str) - }.leftMap(t => - NonEmptyChain - .one(s"Data in ${path.toString} isn't a valid JSON: " + t.getMessage) - ) - } - ) - } - - def jsonFromFileOpts[F[_]: Files: Concurrent]( - name: String, - help: String, - short: String - ): Opts[F[ValidatedNec[String, NonEmptyList[(Path, js.Dynamic)]]]] = { - FileOpts.fileOpts( - name, - help, - short, - (path, str) => { - Validated.catchNonFatal { - JSON.parse(str) - }.leftMap(t => - NonEmptyChain - .one(s"Data in ${path.toString} isn't a valid JSON: " + t.getMessage) - ) - } - ) - } - - // get data from sources, error if both sources exist - def getData( - dataFromArgument: Option[js.Dynamic], - dataFromFile: Option[js.Dynamic] - ): ValidatedNec[String, Option[js.Dynamic]] = { - (dataFromArgument, dataFromFile) match { - case (Some(_), Some(_)) => - // TODO: maybe allow to use both and simple merge with data argument having higher priority - invalidNec("Please use either --data or --data-path. Don't use both") - case _ => validNec(dataFromArgument.orElse(dataFromFile)) - } - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/CommandBuilder.scala b/cli/cli/.js/src/main/scala/aqua/CommandBuilder.scala deleted file mode 100644 index e350ede5..00000000 --- a/cli/cli/.js/src/main/scala/aqua/CommandBuilder.scala +++ /dev/null @@ -1,122 +0,0 @@ -package aqua - -import aqua.builder.{ArgumentGetter, Service} -import aqua.io.{AquaPath, PackagePath} -import aqua.js.VarJson -import aqua.raw.value.{ValueRaw, VarRaw} -import aqua.run.{CliFunc, GeneralOptions, GeneralOpts, JsonService, RunCommand, RunOpts} -import aqua.logging.LogFormatter -import cats.data.Validated.{invalid, invalidNec, valid, validNec, validNel} -import cats.data.{NonEmptyList, Validated, ValidatedNec} -import cats.effect.ExitCode -import cats.effect.kernel.Async -import cats.syntax.applicative.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.monad.* -import cats.{Applicative, Monad} -import com.monovore.decline.{Command, Opts} -import fs2.io.file.{Files, Path} -import scribe.Logging - -import scalajs.js -import scala.concurrent.ExecutionContext - -// All info to run any aqua function -case class RunInfo( - common: GeneralOptions, - func: CliFunc, - input: Option[AquaPath], - imports: List[Path] = Nil, - argumentGetters: Map[String, VarJson] = Map.empty, - services: List[Service] = Nil, - jsonServices: List[JsonService] = Nil, - pluginsPaths: List[String] = Nil -) - -// Builds subcommand -class SubCommandBuilder[F[_]: Async]( - name: String, - header: String, - opts: Opts[F[ValidatedNec[String, RunInfo]]] -) extends Logging { - - def command: Command[F[ValidatedNec[String, Unit]]] = Command(name, header) { - opts.map { riF => - riF.flatMap { - case Validated.Valid(ri) => - LogFormatter.initLogger(Some(ri.common.logLevel.compiler)) - RunCommand.execRun( - ri - ) - case i @ Validated.Invalid(_) => - i.pure[F] - } - } - } -} - -object SubCommandBuilder { - - def apply[F[_]: Async]( - name: String, - header: String, - opts: Opts[ValidatedNec[String, RunInfo]] - ): SubCommandBuilder[F] = { - new SubCommandBuilder(name, header, opts.map(_.pure[F])) - } - - def applyF[F[_]: Async]( - name: String, - header: String, - opts: Opts[F[ValidatedNec[String, RunInfo]]] - ): SubCommandBuilder[F] = { - new SubCommandBuilder(name, header, opts) - } - - def valid[F[_]: Async]( - name: String, - header: String, - opts: Opts[RunInfo] - ): SubCommandBuilder[F] = { - SubCommandBuilder(name, header, opts.map(ri => validNec[String, RunInfo](ri))) - } - - def simple[F[_]: Async]( - name: String, - header: String, - path: AquaPath, - funcName: String - ): SubCommandBuilder[F] = - SubCommandBuilder - .valid( - name, - header, - GeneralOpts.opt.map { c => - RunInfo(c, CliFunc(funcName), Some(path)) - } - ) - - def subcommands[F[_]: Async]( - subs: NonEmptyList[SubCommandBuilder[F]] - ): Opts[F[ValidatedNec[String, Unit]]] = - Opts.subcommands(subs.head.command, subs.tail.map(_.command): _*) -} - -// Builds top command with subcommands -case class CommandBuilder[F[_]: Async]( - name: String, - header: String, - subcommands: NonEmptyList[SubCommandBuilder[F]], - rawCommands: List[Command[F[ValidatedNec[String, Unit]]]] = Nil -) { - - def command: Command[F[ValidatedNec[String, Unit]]] = { - Command(name = name, header = header) { - Opts.subcommands( - subcommands.head.command, - (subcommands.tail.map(_.command) ++ rawCommands): _* - ) - } - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/LogLevelTransformer.scala b/cli/cli/.js/src/main/scala/aqua/LogLevelTransformer.scala deleted file mode 100644 index 3294b7ee..00000000 --- a/cli/cli/.js/src/main/scala/aqua/LogLevelTransformer.scala +++ /dev/null @@ -1,34 +0,0 @@ -package aqua - -import aqua.js.{LogLevel, FluenceJSLogLevel} -import fs2.io.file.Path -import scribe.Level - -import scala.util.Try - -object LogLevelTransformer { - - def logLevelToAvm(logLevel: Level): LogLevel = { - logLevel match { - case Level.Trace => "trace" - case Level.Debug => "debug" - case Level.Info => "info" - case Level.Warn => "warn" - case Level.Error => "error" - case Level.Fatal => "off" - case _ => "info" - } - } - - def logLevelToFluenceJS(logLevel: Level): FluenceJSLogLevel = { - logLevel match { - case Level.Trace => "trace" - case Level.Debug => "debug" - case Level.Info => "info" - case Level.Warn => "warn" - case Level.Error => "error" - case Level.Fatal => "silent" - case _ => "info" - } - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/PlatformOpts.scala b/cli/cli/.js/src/main/scala/aqua/PlatformOpts.scala deleted file mode 100644 index d0c329dd..00000000 --- a/cli/cli/.js/src/main/scala/aqua/PlatformOpts.scala +++ /dev/null @@ -1,35 +0,0 @@ -package aqua - -import aqua.config.ConfigOpts -import aqua.ipfs.IpfsOpts -import aqua.keypair.KeyPairOpts -import aqua.remote.{DistOpts, RemoteOpts} -import aqua.run.RunOpts -import aqua.script.ScriptOpts -import cats.data.ValidatedNec -import cats.effect.ExitCode -import cats.effect.kernel.Async -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.monad.* -import com.monovore.decline.Opts -import fs2.io.file.{Files, Path} -import scribe.Logging - -import scala.concurrent.ExecutionContext -import scala.util.Try -import cats.effect.std.Console - -// JS-specific options and subcommands -object PlatformOpts extends Logging { - - def opts[F[_]: Files: AquaIO: Async: Console]: Opts[F[ValidatedNec[String, Unit]]] = - Opts.subcommand(RunOpts.runCommand[F]) orElse - Opts.subcommand(KeyPairOpts.command[F]) orElse - Opts.subcommand(IpfsOpts.ipfsOpt[F]) orElse - Opts.subcommand(ScriptOpts.scriptOpt[F]) orElse - Opts.subcommand(RemoteOpts.commands[F]) orElse - Opts.subcommand(ConfigOpts.command[F]) -} diff --git a/cli/cli/.js/src/main/scala/aqua/air/AirValidation.scala b/cli/cli/.js/src/main/scala/aqua/air/AirValidation.scala deleted file mode 100644 index 80efdc52..00000000 --- a/cli/cli/.js/src/main/scala/aqua/air/AirValidation.scala +++ /dev/null @@ -1,47 +0,0 @@ -package aqua.air - -import aqua.backend.AirFunction -import aqua.js.Fluence -import cats.data.Validated.{invalid, validNec} -import cats.data.{Chain, NonEmptyChain, ValidatedNec} -import cats.effect.Async -import cats.syntax.traverse.* -import cats.syntax.functor.* -import cats.syntax.applicative.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* - -import scala.concurrent.ExecutionContext -import scala.scalajs.js - -object AirValidation { - - // HACK: memoize doesn't work in scalajs, so, call this function once before `validate` - def init[F[_]: Async](): F[Unit] = { - Async[F].fromFuture(Fluence.start(js.undefined).toFuture.pure[F]).as(()) - } - - def validate[F[_]: Async]( - airs: List[AirFunction] - ): F[ValidatedNec[String, Unit]] = - Async[F].fromFuture { - - Async[F].executionContext.map { implicit ec => - for { - statuses <- airs - .map(a => Fluence.getPeer().internals.parseAst(a.air).toFuture.map(s => (a.name, s))) - .sequence - } yield { - val errors = NonEmptyChain.fromSeq(statuses.filterNot(_._2.success)) - errors.map { errs => - val errorsStrs = errs.map { case (fName, status) => - s"Cannot compile AIR for '$fName' function: ${js.JSON.stringify(status.data)}\n\n" + - "This is unexpected error. Please, dump your Aqua code and make an issue here https://github.com/fluencelabs/aqua/issues." - } - invalid(errorsStrs) - }.getOrElse(validNec(())) - } - } - } - -} diff --git a/cli/cli/.js/src/main/scala/aqua/builder/ArgumentGetter.scala b/cli/cli/.js/src/main/scala/aqua/builder/ArgumentGetter.scala deleted file mode 100644 index 3bf5c485..00000000 --- a/cli/cli/.js/src/main/scala/aqua/builder/ArgumentGetter.scala +++ /dev/null @@ -1,49 +0,0 @@ -package aqua.builder - -import aqua.backend.* -import aqua.js.{CallJsFunction, FluencePeer, ServiceHandler} -import aqua.model.{LiteralModel, VarModel} -import aqua.raw.ops -import aqua.raw.ops.{Call, CallArrowRawTag} -import aqua.raw.value.{LiteralRaw, VarRaw} -import aqua.definitions.* -import cats.data.NonEmptyList - -import scala.concurrent.Promise -import scala.scalajs.js - -// Service that can return argument to use it from a code -// TODO: create one service with multiple argument getters instead of service per argument -abstract class ArgumentGetter( - serviceId: String, - val function: GetFunction -) extends Service(serviceId, NonEmptyList.one(function)) { - - def callTag(): CallArrowRawTag - -} - -case class GetFunction(value: VarRaw, arg: scalajs.js.Dynamic) extends AquaFunction { - override def fnName: String = value.name - - def handler: ServiceHandler = _ => js.Promise.resolve(arg) - def arrow: ArrowTypeDef = ArrowTypeDef(NilTypeDef, UnlabeledProductTypeDef(TopTypeDef :: Nil)) -} - -object ArgumentGetter { - - val ServiceId = "getDataSrv" - - private def getFunction(value: VarRaw, arg: scalajs.js.Dynamic) = GetFunction(value, arg) - - def apply(value: VarRaw, arg: scalajs.js.Dynamic): ArgumentGetter = - new ArgumentGetter(ServiceId, getFunction(value, arg)) { - - override def callTag(): CallArrowRawTag = - CallArrowRawTag.service( - LiteralRaw.quote(ServiceId), - value.name, - Call(List.empty, List(Call.Export(value.name, value.baseType))) - ) - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/builder/Console.scala b/cli/cli/.js/src/main/scala/aqua/builder/Console.scala deleted file mode 100644 index 0a551052..00000000 --- a/cli/cli/.js/src/main/scala/aqua/builder/Console.scala +++ /dev/null @@ -1,42 +0,0 @@ -package aqua.builder - -import aqua.backend.* -import aqua.io.OutputPrinter -import aqua.js.{CallJsFunction, FluencePeer, ServiceHandler} -import aqua.types.ScalarType -import aqua.definitions.* -import cats.data.NonEmptyList -import scribe.Logging - -import scala.scalajs.js -import scala.scalajs.js.JSON - -private case class Console(serviceId: String, functions: NonEmptyList[AquaFunction]) - extends Service(serviceId, functions) - -object Console extends Logging { - - private def printFunction(funcName: String) = new AquaFunction { - override def fnName: String = funcName - - def handler: ServiceHandler = { varArgs => - js.typeOf(varArgs(0)) match { - case "string" | "number" | "boolean" => println(varArgs(0).toString) - case _ => println(JSON.stringify(varArgs(0), space = 2)) - } - js.Promise.resolve(Service.emptyObject) - } - - def arrow: ArrowTypeDef = ArrowTypeDef( - LabeledProductTypeDef(("str", ScalarTypeDef.fromScalar(ScalarType.string)) :: Nil), - NilTypeDef - ) - } - - val PrintName = "print" - - def apply(serviceId: String = "run-console"): Console = { - - Console(serviceId, NonEmptyList.one(printFunction(PrintName))) - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/builder/DeployHelper.scala b/cli/cli/.js/src/main/scala/aqua/builder/DeployHelper.scala deleted file mode 100644 index 701932a8..00000000 --- a/cli/cli/.js/src/main/scala/aqua/builder/DeployHelper.scala +++ /dev/null @@ -1,49 +0,0 @@ -package aqua.builder - -import aqua.backend.* -import aqua.ipfs.js.IpfsApi -import aqua.js.{CallJsFunction, FluencePeer, ServiceHandler} -import aqua.types.ScalarType -import aqua.definitions.* -import cats.data.NonEmptyList -import scribe.Logging - -import scala.scalajs.js - -object DeployHelper extends Logging { - - private val CreateResult = "create_result" - - private def createResult(funcName: String): AquaFunction = new AquaFunction { - override def fnName: String = funcName - - override def handler: ServiceHandler = args => { - val bid = args(0) - val sid = args(1) - js.Promise.resolve(js.Dynamic.literal(blueprint_id = bid, service_id = sid)) - } - - def arrow: ArrowTypeDef = ArrowTypeDef( - LabeledProductTypeDef( - ("bid", ScalarTypeDef.fromScalar(ScalarType.string)) :: ( - "sid", - ScalarTypeDef.fromScalar(ScalarType.string) - ) :: Nil - ), - UnlabeledProductTypeDef( - StructTypeDef( - "DeployResult", - Map( - "blueprint_id" -> ScalarTypeDef.fromScalar(ScalarType.string), - "service_id" -> ScalarTypeDef.fromScalar(ScalarType.string) - ) - ) :: Nil - ) - ) - } - - def apply(serviceId: String = "deploy_helper"): Service = { - val funcs = NonEmptyList.one(createResult(CreateResult)) - Service(serviceId, funcs) - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/builder/Finisher.scala b/cli/cli/.js/src/main/scala/aqua/builder/Finisher.scala deleted file mode 100644 index 416da221..00000000 --- a/cli/cli/.js/src/main/scala/aqua/builder/Finisher.scala +++ /dev/null @@ -1,49 +0,0 @@ -package aqua.builder - -import aqua.backend.* -import aqua.js.{CallJsFunction, FluencePeer, ServiceHandler} -import aqua.model.{LiteralModel, VarModel} -import aqua.raw.ops.{Call, CallArrowRawTag} -import aqua.definitions.* -import aqua.raw.value.LiteralRaw -import cats.data.NonEmptyList - -import scala.concurrent.Promise -import scala.scalajs.js -import scala.scalajs.js.{Dynamic, JSON} - -// Will finish promise on service call -abstract class Finisher private ( - serviceId: String, - functions: NonEmptyList[AquaFunction], - val promise: Promise[Unit] -) extends Service(serviceId, functions) { - - def callTag(): CallArrowRawTag -} - -object Finisher { - - private def finishFunction(funcName: String, promise: Promise[Unit]) = new AquaFunction { - def fnName: String = funcName - - def handler: ServiceHandler = _ => { - promise.success(()) - js.Promise.resolve(Service.emptyObject) - } - def arrow: ArrowTypeDef = ArrowTypeDef(NilTypeDef, NilTypeDef) - } - - def apply(servId: String, fnName: String): Finisher = { - val promise = Promise[Unit]() - val funcs = NonEmptyList.one(finishFunction(fnName, promise)) - new Finisher(servId, funcs, promise) { - def callTag(): CallArrowRawTag = - CallArrowRawTag.service( - LiteralRaw.quote(servId), - fnName, - Call(Nil, Nil) - ) - } - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/builder/IPFSUploader.scala b/cli/cli/.js/src/main/scala/aqua/builder/IPFSUploader.scala deleted file mode 100644 index b1bbb369..00000000 --- a/cli/cli/.js/src/main/scala/aqua/builder/IPFSUploader.scala +++ /dev/null @@ -1,56 +0,0 @@ -package aqua.builder - -import aqua.backend.* -import aqua.ipfs.js.IpfsApi -import aqua.js.{CallJsFunction, FluencePeer, ServiceHandler} -import aqua.types.ScalarType -import aqua.definitions.* -import cats.data.NonEmptyList -import scribe.Logging - -import scala.scalajs.js - -object IPFSUploader extends Logging { - - private val UploadFile = "uploadFile" - - private def uploadFunc(funcName: String): AquaFunction = new AquaFunction { - override def fnName: String = funcName - - private def logError(s: String) = logger.error(s) - private def logInfo(s: String) = logger.info(s) - - override def handler: ServiceHandler = args => { - IpfsApi - .uploadFile(args(0), args(1), logInfo, logError) - .`catch` { err => - js.Dynamic.literal(error = "File upload error: " + err) - } - - } - - def arrow: ArrowTypeDef = ArrowTypeDef( - LabeledProductTypeDef( - ("path", ScalarTypeDef.fromScalar(ScalarType.string)) :: ( - "multiaddr", - ScalarTypeDef.fromScalar(ScalarType.string) - ) :: Nil - ), - UnlabeledProductTypeDef( - StructTypeDef( - "UploadResult", - Map( - "error" -> ScalarTypeDef.fromScalar(ScalarType.string), - "cid" -> ScalarTypeDef.fromScalar(ScalarType.string), - "size" -> ScalarTypeDef.fromScalar(ScalarType.u64) - ) - ) :: Nil - ) - ) - } - - def apply(serviceId: String): Service = { - val funcs = NonEmptyList.one(uploadFunc(UploadFile)) - Service(serviceId, funcs) - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/builder/ResultPrinter.scala b/cli/cli/.js/src/main/scala/aqua/builder/ResultPrinter.scala deleted file mode 100644 index 540cfafb..00000000 --- a/cli/cli/.js/src/main/scala/aqua/builder/ResultPrinter.scala +++ /dev/null @@ -1,60 +0,0 @@ -package aqua.builder - -import aqua.backend.* -import aqua.io.OutputPrinter -import aqua.js.{CallJsFunction, FluencePeer, ServiceHandler} -import aqua.raw.ops.{Call, CallArrowRawTag} -import aqua.raw.value.{LiteralRaw, VarRaw} -import aqua.definitions.* -import aqua.types.ScalarType -import cats.data.NonEmptyList - -import scala.scalajs.js -import scala.scalajs.js.{Dynamic, JSON} - -// Function to print any variables that passed as arguments -abstract class ResultPrinter(serviceId: String, functions: NonEmptyList[AquaFunction]) - extends Service(serviceId, functions) { - - def callTag(variables: List[VarRaw]): CallArrowRawTag -} - -object ResultPrinter { - - private def resultPrinterFunc(funcName: String, resultNames: List[String]) = new AquaFunction { - override def fnName: String = funcName - - override def handler: ServiceHandler = varArgs => { - // drop last argument (tetraplets) - val args: Seq[js.Any] = varArgs.init - val toPrint = args.toList match { - case arg :: Nil => JSON.stringify(arg, space = 2) - case _ => args.map(a => JSON.stringify(a, space = 2)).mkString("[\n", ",\n", "\n]") - } - - // if an input function returns a result, our success will be after it is printed - // otherwise finish after JS SDK will finish sending a request - OutputPrinter.print(toPrint) - // empty JS object - js.Promise.resolve(Service.emptyObject) - } - - def arrow: ArrowTypeDef = ArrowTypeDef( - LabeledProductTypeDef(resultNames.map(n => (n, TopTypeDef))), - NilTypeDef - ) - } - - def apply(serviceId: String, fnName: String, resultNames: List[String]): ResultPrinter = { - val funcs = NonEmptyList.one(resultPrinterFunc(fnName, resultNames)) - new ResultPrinter(serviceId, funcs) { - def callTag(variables: List[VarRaw]): CallArrowRawTag = - CallArrowRawTag.service( - LiteralRaw.quote(serviceId), - fnName, - Call(variables, Nil) - ) - } - } - -} diff --git a/cli/cli/.js/src/main/scala/aqua/builder/Service.scala b/cli/cli/.js/src/main/scala/aqua/builder/Service.scala deleted file mode 100644 index 30dbc72b..00000000 --- a/cli/cli/.js/src/main/scala/aqua/builder/Service.scala +++ /dev/null @@ -1,45 +0,0 @@ -package aqua.builder - -import aqua.backend.* -import aqua.js.{CallJsFunction, FluencePeer, ServiceHandler} -import aqua.definitions.* -import cats.data.NonEmptyList -import scribe.Logging - -import scala.scalajs.js -import scala.scalajs.js.{Dynamic, JSON} - -class Service(serviceId: String, functions: NonEmptyList[AquaFunction]) extends Logging { - - def register(peer: FluencePeer): Unit = { - val handlers = functions.map(f => (f.fnName, f.handler)) - val defs = LabeledProductTypeDef( - functions.map(f => (f.fnName, f.arrow)).toList - ) - - logger.debug( - s"Registering service $serviceId with functions ${functions.map(_.fnName).toList.mkString(",")}" - ) - - CallJsFunction.registerService( - peer, - serviceId, - handlers.toList, - ServiceDef( - None, - defs, - "" - ) - ) - } -} - -trait AquaFunction { - def fnName: String - def handler: ServiceHandler - def arrow: ArrowTypeDef -} - -object Service { - val emptyObject: Dynamic = Dynamic.literal() -} diff --git a/cli/cli/.js/src/main/scala/aqua/config/ConfigOpts.scala b/cli/cli/.js/src/main/scala/aqua/config/ConfigOpts.scala deleted file mode 100644 index 91cc65df..00000000 --- a/cli/cli/.js/src/main/scala/aqua/config/ConfigOpts.scala +++ /dev/null @@ -1,54 +0,0 @@ -package aqua.config - -import aqua.js.{FluenceEnvironment, FluenceNode} -import cats.Applicative -import cats.data.{Validated, ValidatedNec} -import cats.data.Validated.{invalidNel, validNel} -import cats.effect.ExitCode -import cats.effect.kernel.Async -import cats.syntax.applicative.* -import com.monovore.decline.{Command, Opts} -import cats.data.Validated.{invalidNec, validNec} - -import scala.scalajs.js - -object ConfigOpts { - - def command[F[_]: Async]: Command[F[ValidatedNec[String, Unit]]] = - Command(name = "config", header = "Aqua CLI configuration") { - Opts.subcommands( - listPeers - ) - } - - val Krasnodar = "krasnodar" - val Stage = "stage" - val TestNet = "testnet" - - def envArg: Opts[js.Array[FluenceNode]] = - Opts - .argument[String](s"$Krasnodar | $Stage | $TestNet") - .withDefault(Krasnodar) - .mapValidated { - case Krasnodar => - validNel(FluenceEnvironment.krasnodar) - case TestNet => - validNel(FluenceEnvironment.testnet) - case Stage => - validNel(FluenceEnvironment.stage) - case e => - invalidNel( - s"There is no environment '$e' in our list. Use one of these: '$Krasnodar', '$TestNet', '$Stage'" - ) - } - - def listPeers[F[_]: Applicative]: Command[F[ValidatedNec[String, Unit]]] = - Command( - name = "default_peers", - header = "List addresses of default peers in Fluence network" - ) { - envArg.map { env => - validNec(println(env.toList.map(n => n.multiaddr).mkString("\n"))).pure[F] - } - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/ipfs/IpfsOpts.scala b/cli/cli/.js/src/main/scala/aqua/ipfs/IpfsOpts.scala deleted file mode 100644 index 993c474f..00000000 --- a/cli/cli/.js/src/main/scala/aqua/ipfs/IpfsOpts.scala +++ /dev/null @@ -1,64 +0,0 @@ -package aqua.ipfs - -import aqua.{ - AppOpts, - AquaIO, - CommandBuilder, - FluenceOpts, - LogLevelTransformer, - PlatformOpts, - RunInfo, - SubCommandBuilder -} -import aqua.keypair.KeyPairShow.show -import cats.data.{NonEmptyChain, NonEmptyList, Validated, ValidatedNec, ValidatedNel} -import Validated.{invalid, invalidNec, valid, validNec, validNel} -import aqua.builder.IPFSUploader -import aqua.io.PackagePath -import aqua.ipfs.js.IpfsApi -import aqua.model.LiteralModel -import aqua.raw.value.LiteralRaw -import aqua.run.{GeneralOptions, RunCommand, RunConfig, RunOpts, GeneralOpts, CliFunc} -import cats.effect.{Concurrent, ExitCode, Resource, Sync} -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.effect.kernel.Async -import cats.syntax.show.* -import cats.{Applicative, Monad} -import com.monovore.decline.{Command, Opts} -import fs2.io.file.{Files, Path} -import scribe.Logging - -import scala.concurrent.{ExecutionContext, Future} -import scala.scalajs.js - -// Options and commands to work with IPFS -object IpfsOpts extends Logging { - - val IpfsAqua = "aqua/ipfs.aqua" - - val UploadFuncName = "uploadFile" - - def pathOpt: Opts[String] = - Opts - .option[String]("path", "Path to a file", "p", "path") - - def ipfsOpt[F[_]: Async]: Command[F[ValidatedNec[String, Unit]]] = - CommandBuilder("ipfs", "Work with IPFS on a peer", NonEmptyList.one(upload[F])).command - - // Uploads a file to IPFS - def upload[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.valid( - "upload", - "Upload a file to IPFS", - (GeneralOpts.opt, pathOpt).mapN { (common, path) => - RunInfo( - common, - CliFunc(UploadFuncName, LiteralRaw.quote(path) :: Nil), - Option(PackagePath(IpfsAqua)) - ) - } - ) -} diff --git a/cli/cli/.js/src/main/scala/aqua/ipfs/js/IpfsApi.scala b/cli/cli/.js/src/main/scala/aqua/ipfs/js/IpfsApi.scala deleted file mode 100644 index 45d093c2..00000000 --- a/cli/cli/.js/src/main/scala/aqua/ipfs/js/IpfsApi.scala +++ /dev/null @@ -1,16 +0,0 @@ -package aqua.ipfs.js - -import scala.scalajs.js -import scala.scalajs.js.annotation.{JSExportAll, JSImport} - -object IpfsApi { - - @js.native - @JSImport("./dist/ipfs.js", "uploadFile") - def uploadFile( - path: js.Any, - multiaddrResult: js.Any, - infoLogger: js.Any, - errorLogger: js.Any - ): js.Promise[js.Dynamic] = js.native -} diff --git a/cli/cli/.js/src/main/scala/aqua/json/JsonEncoder.scala b/cli/cli/.js/src/main/scala/aqua/json/JsonEncoder.scala deleted file mode 100644 index e69de29b..00000000 diff --git a/cli/cli/.js/src/main/scala/aqua/keypair/KeyPairOpts.scala b/cli/cli/.js/src/main/scala/aqua/keypair/KeyPairOpts.scala deleted file mode 100644 index 9267f266..00000000 --- a/cli/cli/.js/src/main/scala/aqua/keypair/KeyPairOpts.scala +++ /dev/null @@ -1,43 +0,0 @@ -package aqua.keypair - -import aqua.io.OutputPrinter -import aqua.js.KeyPair -import aqua.keypair.KeyPairShow.show -import cats.data.ValidatedNec -import cats.effect.ExitCode -import cats.effect.kernel.Async -import cats.syntax.applicative.* -import cats.syntax.functor.* -import cats.syntax.show.* -import cats.{Applicative, Monad} -import com.monovore.decline.{Command, Opts} -import cats.data.Validated.{invalidNec, validNec} -import scribe.Logging - -import scala.concurrent.{ExecutionContext, Future} - -// Options and commands to work with KeyPairs -object KeyPairOpts extends Logging { - - def command[F[_]: Async]: Command[F[ValidatedNec[String, Unit]]] = - Command(name = "key", header = "Manage local keys and identity") { - Opts.subcommands( - createKeypair - ) - } - - // KeyPair generation - def createKeypair[F[_]: Async]: Command[F[ValidatedNec[String, Unit]]] = - Command( - name = "create", - header = "Generate new key pair" - ) { - Opts.unit.map(_ => - Async[F] - .fromFuture( - KeyPair.randomEd25519().toFuture.pure[F] - ) - .map(keypair => validNec(OutputPrinter.print(s"${keypair.show}"))) - ) - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/keypair/KeyPairShow.scala b/cli/cli/.js/src/main/scala/aqua/keypair/KeyPairShow.scala deleted file mode 100644 index 9bab3ff9..00000000 --- a/cli/cli/.js/src/main/scala/aqua/keypair/KeyPairShow.scala +++ /dev/null @@ -1,17 +0,0 @@ -package aqua.keypair - -import aqua.js.{KeyPair, KeyPairOp} -import cats.Show - -import java.util.Base64 -import scala.scalajs.js -import scala.scalajs.js.JSON - -object KeyPairShow { - - def stringify(keypair: KeyPair): String = { - JSON.stringify(KeyPairOp.toDynamicJSON(keypair), space = 4) - } - - implicit val show: Show[KeyPair] = Show.show(KeyPairShow.stringify) -} diff --git a/cli/cli/.js/src/main/scala/aqua/remote/DistOpts.scala b/cli/cli/.js/src/main/scala/aqua/remote/DistOpts.scala deleted file mode 100644 index 056173fd..00000000 --- a/cli/cli/.js/src/main/scala/aqua/remote/DistOpts.scala +++ /dev/null @@ -1,171 +0,0 @@ -package aqua.remote - -import aqua.ArgOpts.jsonFromFileOpt -import aqua.builder.ArgumentGetter -import aqua.raw.value.{LiteralRaw, VarRaw} -import aqua.run.{GeneralOptions, GeneralOpts, CliFunc} -import aqua.types.{ArrayType, ScalarType, StructType} -import aqua.* -import aqua.io.PackagePath -import aqua.js.{JsonEncoder, VarJson} -import cats.data.{NonEmptyList, NonEmptyMap, ValidatedNec} -import cats.data.Validated.{invalidNec, validNec} -import cats.effect.{Async, Concurrent, ExitCode, Resource, Sync} -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.traverse.* -import cats.syntax.show.* -import cats.{Applicative, Monad} -import com.monovore.decline.Opts -import fs2.io.file.Files -import scribe.Logging - -import scala.collection.immutable.SortedMap -import scala.scalajs.js.JSConverters.* -import scala.scalajs.js - -// Options and commands to work blueprints, modules and services -object DistOpts extends Logging { - - val DistAqua = "aqua/dist.aqua" - - val DeployFuncName = "deploy" - val RemoveFuncName = "remove" - val CreateServiceFuncName = "createService" - val AddBlueprintFuncName = "addBlueprint" - - def srvNameOpt: Opts[String] = - Opts - .option[String]("service", "Service to deploy from the config file") - - def srvIdOpt: Opts[String] = - Opts - .option[String]("id", "Service id to remove", "i") - - def blueprintIdOpt: Opts[String] = - Opts - .option[String]("id", "Blueprint id", "i") - - def blueprintNameOpt: Opts[String] = - Opts - .option[String]("name", "Blueprint name", "n") - - def dependencyOpt: Opts[NonEmptyList[String]] = - Opts - .options[String]("dependency", "Blueprint dependency. May be used several times", "d") - - // Removes service from a node - def remove[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.valid( - "remove_service", - "Remove service", - (GeneralOpts.opt, srvIdOpt).mapN { (common, srvId) => - RunInfo( - common, - CliFunc(RemoveFuncName, LiteralRaw.quote(srvId) :: Nil), - Option(PackagePath(DistAqua)) - ) - } - ) - - def createService[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.valid( - "create_service", - "Deploy service from existing blueprint", - (GeneralOpts.opt, blueprintIdOpt).mapN { (common, blueprintId) => - RunInfo( - common, - CliFunc(CreateServiceFuncName, LiteralRaw.quote(blueprintId) :: Nil), - Option(PackagePath(DistAqua)) - ) - } - ) - - def addBlueprint[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.valid( - "add_blueprint", - "Add blueprint to a peer", - (GeneralOpts.opt, blueprintNameOpt, dependencyOpt).mapN { - (common, blueprintName, dependencies) => - val depsWithHash = dependencies.map { d => - if (d.startsWith("hash:")) - d - else - "hash:" + d - } - val addBlueprintType = StructType( - "AddBlueprint", - NonEmptyMap.of( - ("name", ScalarType.string), - ("dependencies", ArrayType(ScalarType.string)) - ) - ) - val addBlueprintRequestVar = - VarRaw("addBlueprint", addBlueprintType) - RunInfo( - common, - CliFunc(AddBlueprintFuncName, addBlueprintRequestVar :: Nil), - Option(PackagePath(DistAqua)), - Nil, - Map( - addBlueprintRequestVar.name -> VarJson( - addBlueprintRequestVar, - js.Dynamic - .literal("name" -> blueprintName, "dependencies" -> depsWithHash.toList.toJSArray) - ) - ) - ) - } - ) - - def configFromFileOpt[F[_]: Files: Concurrent]: Opts[F[ValidatedNec[String, js.Dynamic]]] = { - jsonFromFileOpt("config-path", "Path to a deploy config", "p") - } - - // Uploads a file to IPFS, creates blueprints and deploys a service - def deploy[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.applyF( - "deploy_service", - "Deploy service from WASM modules", - ( - GeneralOpts.optWithSecretKeyCustomTimeout(60000), - configFromFileOpt[F], - srvNameOpt - ).mapN { (common, configFromFileF, srvName) => - configFromFileF.map { dff => - dff - .andThen(config => - val srvConfig = { - val c = config.selectDynamic(srvName) - if (js.isUndefined(c)) None - else Some(c) - } - srvConfig match { - case Some(c) => - JsonEncoder.aquaTypeFromJson(srvName, c).andThen { configType => - val srvArg = VarRaw(srvName, configType) - val args = LiteralRaw.quote(srvName) :: srvArg :: Nil - // if we have default timeout, increase it - validNec( - RunInfo( - common, - CliFunc(DeployFuncName, args), - Option(PackagePath(DistAqua)), - Nil, - // hack: air cannot use undefined fields, fill undefined arrays with nils - Map(srvName -> VarJson(srvArg, c)) - ) - ) - } - - case None => - invalidNec(s"No service '$srvName' in the config.") - - } - ) - } - } - ) -} diff --git a/cli/cli/.js/src/main/scala/aqua/remote/RemoteInfoOpts.scala b/cli/cli/.js/src/main/scala/aqua/remote/RemoteInfoOpts.scala deleted file mode 100644 index 9e18c92a..00000000 --- a/cli/cli/.js/src/main/scala/aqua/remote/RemoteInfoOpts.scala +++ /dev/null @@ -1,120 +0,0 @@ -package aqua.remote - -import aqua.builder.IPFSUploader -import DistOpts.* -import aqua.ipfs.IpfsOpts.{pathOpt, UploadFuncName} -import aqua.model.{LiteralModel, ValueModel} -import aqua.raw.value.{LiteralRaw, ValueRaw} -import aqua.run.{GeneralOptions, GeneralOpts, RunCommand, RunConfig, RunOpts, CliFunc} -import aqua.* -import cats.Applicative -import cats.data.{NonEmptyList, Validated} -import Validated.{invalidNel, validNel} -import aqua.io.PackagePath -import cats.effect.ExitCode -import cats.effect.kernel.Async -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import com.monovore.decline.{Command, Opts} -import fs2.io.file.Path - -import scala.concurrent.ExecutionContext -import scala.scalajs.js - -object RemoteInfoOpts { - - val NetworkAqua = "aqua/network-info.aqua" - - val ListModulesFuncName = "list_modules" - val ListBlueprintsFuncName = "list_blueprints" - val ListInterfacesByPeerFuncName = "list_interfaces_by_peer" - val ListInterfacesFuncName = "list_services" - val GetInterfaceFuncName = "get_interface" - val GetModuleInterfaceFuncName = "get_module_interface" - - def ownerOpt: Opts[String] = - Opts - .option[String]("owner", "PeerId", "o") - - def allFlag: Opts[Boolean] = - Opts - .flag("all", "Get all services on a node") - .map(_ => true) - .withDefault(false) - - def idOpt: Opts[String] = - Opts - .option[String]("id", "Service ID", "s") - - def listModules[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.simple( - ListModulesFuncName, - "List all modules on a peer", - PackagePath(NetworkAqua), - ListModulesFuncName - ) - - def listBlueprints[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.simple( - ListBlueprintsFuncName, - "List all blueprints on a peer", - PackagePath(NetworkAqua), - ListBlueprintsFuncName - ) - - def listInterfaces[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.valid( - "list_interfaces", - "List all service interfaces on a peer by a given owner", - (GeneralOpts.opt, AppOpts.wrapWithOption(ownerOpt), allFlag).mapN { - (common, peer, printAll) => - if (printAll) - RunInfo( - common, - CliFunc( - ListInterfacesFuncName, - Nil - ), - Option(PackagePath(NetworkAqua)) - ) - else - RunInfo( - common, - CliFunc( - ListInterfacesByPeerFuncName, - peer.map(LiteralRaw.quote).getOrElse(ValueRaw.InitPeerId) :: Nil - ), - Option(PackagePath(NetworkAqua)) - ) - } - ) - - def getInterface[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.valid( - GetInterfaceFuncName, - "Show interface of a service", - (GeneralOpts.opt, idOpt).mapN { (common, serviceId) => - RunInfo( - common, - CliFunc(GetInterfaceFuncName, LiteralRaw.quote(serviceId) :: Nil), - Option(PackagePath(NetworkAqua)) - ) - } - ) - - def getModuleInterface[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.valid( - GetModuleInterfaceFuncName, - "Print a module interface", - (GeneralOpts.opt, idOpt).mapN { (common, serviceId) => - RunInfo( - common, - CliFunc(GetModuleInterfaceFuncName, LiteralRaw.quote(serviceId) :: Nil), - Option(PackagePath(NetworkAqua)) - ) - } - ) - -} diff --git a/cli/cli/.js/src/main/scala/aqua/remote/RemoteOpts.scala b/cli/cli/.js/src/main/scala/aqua/remote/RemoteOpts.scala deleted file mode 100644 index 0e4ecdf8..00000000 --- a/cli/cli/.js/src/main/scala/aqua/remote/RemoteOpts.scala +++ /dev/null @@ -1,23 +0,0 @@ -package aqua.remote - -import aqua.{AquaIO, CommandBuilder} -import cats.data.{NonEmptyList, ValidatedNec} -import cats.effect.ExitCode -import cats.effect.kernel.Async -import com.monovore.decline.Command -import RemoteInfoOpts.* -import DistOpts.* - -object RemoteOpts { - - // All remote commands - def commands[F[_]: AquaIO: Async]: Command[F[ValidatedNec[String, Unit]]] = - CommandBuilder( - "remote", - "Manage and query services on a remote peer", - NonEmptyList( - deploy, - remove :: createService :: addBlueprint :: listModules :: listBlueprints :: listInterfaces :: getInterface :: Nil - ) - ).command -} diff --git a/cli/cli/.js/src/main/scala/aqua/run/ConfigOpts.scala b/cli/cli/.js/src/main/scala/aqua/run/ConfigOpts.scala deleted file mode 100644 index d50797e6..00000000 --- a/cli/cli/.js/src/main/scala/aqua/run/ConfigOpts.scala +++ /dev/null @@ -1,92 +0,0 @@ -package aqua.run - -import aqua.AppOpts -import aqua.FluenceOpts.* -import aqua.builder.{ArgumentGetter, Service} -import aqua.config.ConfigOpts.{Krasnodar, Stage, TestNet} -import aqua.js.FluenceEnvironment -import aqua.raw.ConstantRaw -import aqua.raw.value.VarRaw -import aqua.logging.LogLevels -import cats.data.{NonEmptyList, Validated} -import cats.data.Validated.{invalidNel, validNel} -import cats.syntax.applicative.* -import cats.syntax.apply.* -import com.monovore.decline.Opts -import scribe.Level - -import java.util.concurrent.TimeUnit -import scala.concurrent.duration.Duration -import scala.scalajs.js -import scala.util.Try - -object GeneralOpts { - - val multiaddrOpt: Opts[String] = - Opts - .option[String]("addr", "Relay multiaddress", "a") - .mapValidated { s => - if ((s.startsWith("/dns4/") || s.startsWith("/ip4/")) && s.contains("/p2p/12D3")) { - validNel(s) - } else { - Validated.catchNonFatal { - val splitted = s.split("-") - val index = splitted(1).toInt - splitted.head.toLowerCase match { - case Krasnodar => - validNel(FluenceEnvironment.krasnodar(index).multiaddr) - case TestNet => - validNel(FluenceEnvironment.testnet(index).multiaddr) - case Stage => - validNel(FluenceEnvironment.stage(index).multiaddr) - case _ => - invalidNel( - // TODO: maybe show an example of valid format in this error message and in the one below - "Invalid multiaddr format. Run 'aqua config default_peers' for valid multiaddress." - ) - } - }.andThen(identity) - .leftMap(_ => - NonEmptyList.one( - "Invalid multiaddr format. Run 'aqua config default_peers' for valid multiaddress." - ) - ) - } - } - - def flagsOpt(isRun: Boolean): Opts[Flags] = - (( - printAir, - showConfigOpt, - verboseOpt - ) ++ { - if (isRun) - (AppOpts.noXorWrapper, AppOpts.noRelay) - else - (false.pure[Opts], false.pure[Opts]) - }).mapN(Flags.apply) - - def commonOpt( - isRun: Boolean, - withSecret: Boolean, - withConstants: Boolean, - defaultTimeout: Duration = Duration(7000, TimeUnit.MILLISECONDS) - ): Opts[GeneralOptions] = - ( - timeoutOpt.withDefault(defaultTimeout), - logLevelOpt, - multiaddrOpt, - onOpt, - flagsOpt(isRun), - if (withSecret) { secretKeyOpt.map(Some.apply) } - else { AppOpts.wrapWithOption(secretKeyOpt) }, - if (withConstants) AppOpts.constantOpts else Nil.pure[Opts] - ).mapN(GeneralOptions.apply) - - val opt: Opts[GeneralOptions] = commonOpt(false, false, false) - val runOpt: Opts[GeneralOptions] = commonOpt(true, false, true) - val optWithSecretKey: Opts[GeneralOptions] = commonOpt(false, true, false) - - def optWithSecretKeyCustomTimeout(timeoutMs: Int): Opts[GeneralOptions] = - commonOpt(false, true, false, Duration(timeoutMs, TimeUnit.MILLISECONDS)) -} diff --git a/cli/cli/.js/src/main/scala/aqua/run/FuncCaller.scala b/cli/cli/.js/src/main/scala/aqua/run/FuncCaller.scala deleted file mode 100644 index f181c3e6..00000000 --- a/cli/cli/.js/src/main/scala/aqua/run/FuncCaller.scala +++ /dev/null @@ -1,149 +0,0 @@ -package aqua.run - -import aqua.LogLevelTransformer -import aqua.builder.{ArgumentGetter, Finisher, ResultPrinter, Service} -import aqua.definitions.FunctionDef -import aqua.io.OutputPrinter -import aqua.js.* -import aqua.keypair.KeyPairShow.show -import aqua.run.RunCommand.createKeyPair -import aqua.run.plugin.Plugin -import cats.data.Validated.{invalidNec, validNec} -import cats.data.ValidatedNec -import cats.effect.kernel.Async -import cats.effect.{Resource, Sync} -import cats.syntax.applicative.* -import cats.syntax.flatMap.* -import cats.syntax.show.* - -import scala.concurrent.duration.Duration -import scala.concurrent.{ExecutionContext, Future, Promise, TimeoutException} -import scala.scalajs.js -import scala.scalajs.js.JSConverters.* -import scala.scalajs.js.{JSON, JavaScriptException, timers} - -object FuncCaller { - - /** - * Register services and call an air code with FluenceJS SDK. - * @param air code to call - * @return - */ - def funcCall[F[_]: Async]( - name: String, - air: String, - functionDef: FunctionDef, - config: RunConfig, - resultPrinterService: ResultPrinter, - finisherService: Finisher, - services: List[Service], - getters: List[ArgumentGetter], - plugins: List[String] - ): F[ValidatedNec[String, Unit]] = { - - FluenceUtils.setLogLevel( - LogLevelTransformer.logLevelToFluenceJS(config.common.logLevel.fluencejs) - ) - - // stops peer in any way at the end of execution - val resource = Resource.make(Fluence.getPeer().pure[F]) { peer => - Async[F].fromFuture(Sync[F].delay(peer.stop().toFuture)) - } - - resource.use { peer => - Async[F].executionContext.flatMap { implicit ec => - Async[F].fromFuture { - (for { - keyPair <- createKeyPair(config.common.secretKey) - logLevel: js.UndefOr[aqua.js.LogLevel] = LogLevelTransformer.logLevelToAvm( - config.common.logLevel.aquavm - ) - pc = PeerConfig( - config.common.multiaddr, - config.common.timeout.toMillis.toInt : js.UndefOr[Int], - keyPair, - Debug(printParticleId = config.common.flags.verbose, marineLogLevel = logLevel) - ) - peerConfig = Some( - pc.createObj() - ).orUndefined - _ <- Fluence.start(peerConfig).toFuture - _ = - if (config.common.flags.showConfig) { - val configJson = KeyPairOp.toDynamicJSON(keyPair) - configJson.updateDynamic("relay")(config.common.multiaddr) - configJson.updateDynamic("timeout")(config.common.timeout.toMillis) - configJson.updateDynamic("log-level")(config.common.logLevel.compiler.name) - OutputPrinter.print(JSON.stringify(configJson, null, 4)) - } - - // register all services - _ = (services ++ getters :+ finisherService :+ resultPrinterService).map(_.register(peer)) - // register all plugins - plugins <- Plugin.getPlugins(plugins) - _ = plugins.map(_.register(peer)) - callFuture = CallJsFunction.funcCallJs( - air, - functionDef, - List.empty - ) - // error will be thrown on failed call - _ <- callFuture - finisherFuture = finisherService.promise.future - // use a timeout in finisher if we have an async function and it hangs on node's side - finisher = setTimeout(name, finisherFuture, config.common.timeout) - _ <- finisher - _ <- Fluence.stop().toFuture - } yield validNec(())) - .recover(handleFuncCallErrors(name, config.common.timeout)) - .pure[F] - } - } - - } - } - - private def setTimeout[T](funcName: String, f: Future[T], timeout: Duration)(implicit - ec: ExecutionContext - ): Future[T] = { - val p = Promise[T]() - val timeoutHandle = - timers.setTimeout(timeout.toMillis)( - p.tryFailure(new TimeoutException(timeoutErrorMessage(funcName, timeout, None))) - ) - f.onComplete { result => - timers.clearTimeout(timeoutHandle) - p.tryComplete(result) - } - p.future - } - - private def timeoutErrorMessage(funcName: String, timeout: Duration, pid: Option[String]) = { - val pidStr = pid.map(s => " " + s).getOrElse("") - s"Function '$funcName' timed out after ${timeout.toMillis} milliseconds. Increase the timeout with '--timeout' option or check if your code can hang while executing$pidStr." - } - - private def handleFuncCallErrors( - funcName: String, - timeout: Duration - ): PartialFunction[Throwable, ValidatedNec[String, Unit]] = { t => - val message = - t match { - case te: TimeoutException => te.getMessage - case t if t.getMessage.contains("Request timed out after") => - val msg = t.getMessage - timeoutErrorMessage( - funcName, - timeout, - Some(msg.substring(msg.indexOf("particle id") - 1, msg.length)) - ) - case tjs: JavaScriptException => - val msg = tjs.exception.asInstanceOf[js.Dynamic].selectDynamic("message") - if (scalajs.js.isUndefined(msg)) JSON.stringify(tjs.exception.asInstanceOf[js.Any]) - else msg.toString - case _ => t.toString - } - - invalidNec(message) - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/run/JsonService.scala b/cli/cli/.js/src/main/scala/aqua/run/JsonService.scala deleted file mode 100644 index 97df23f6..00000000 --- a/cli/cli/.js/src/main/scala/aqua/run/JsonService.scala +++ /dev/null @@ -1,96 +0,0 @@ -package aqua.run - -import aqua.ArgOpts.jsonFromFileOpts -import aqua.builder.{AquaFunction, ArgumentGetter, Service} -import aqua.definitions.{ArrowTypeDef, ProductTypeDef, TypeDefinition} -import aqua.js.{Conversions, ServiceHandler, TypeDefinitionJs} -import aqua.model.{AquaContext, ServiceModel} -import aqua.parser.expr.func.CallArrowExpr -import aqua.parser.lexer.{CallArrowToken, CollectionToken, LiteralToken, VarToken} -import aqua.parser.lift.Span -import aqua.raw.value.{CollectionRaw, LiteralRaw, ValueRaw, VarRaw} -import aqua.types.* -import cats.data.* -import cats.data.Validated.{invalid, invalidNec, invalidNel, valid, validNec, validNel} -import cats.effect.Concurrent -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.semigroup.* -import cats.syntax.traverse.* -import cats.{Id, Semigroup, ~>} -import com.monovore.decline.Opts -import fs2.io.file.{Files, Path} - -import scala.scalajs.js - -// Description of a service with functions that return structures -case class JsonService(name: String, serviceId: String, functions: NonEmptyList[JsonFunction]) -case class JsonFunction(name: String, result: js.Dynamic, resultType: Type) - -object JsonService { - - def findServices( - contexts: Chain[AquaContext], - services: List[JsonService] - ): ValidatedNec[String, List[Service]] = { - services - .map(js => - contexts - .collectFirstSome(_.services.get(js.name)) - .map(sm => (js, sm)) - .map(validNec) - .getOrElse( - Validated.invalidNec[String, ServiceModel]( - s"There is no service '${js.name}' (described in json-service file) in aqua source or it is not exported. Check the spelling or see https://fluence.dev/docs/aqua-book/language/header/#export" - ) - ) - ) - .sequence - .andThen { l => - l.map { case (jsonService: JsonService, sm: ServiceModel) => - val aquaFunctions: ValidatedNec[String, NonEmptyList[AquaFunction]] = - jsonService.functions.map { jf => - sm.arrows(jf.name) - .map { case arr: ArrowType => - if (arr.domain.isEmpty) - TypeValidator - .validateTypes(jf.name, arr.codomain, Some(ProductType(jf.resultType :: Nil))) - .map { _ => - new AquaFunction { - override def fnName: String = jf.name - - override def handler: ServiceHandler = _ => { - val converted = arr.codomain.toList match { - case h :: _ => - Conversions.ts2aqua(jf.result, TypeDefinitionJs(TypeDefinition(h))) - case Nil => - Conversions.ts2aqua( - jf.result, - TypeDefinitionJs(TypeDefinition(NilType)) - ) - } - - js.Promise.resolve(converted) - } - override def arrow: ArrowTypeDef = - ArrowTypeDef(ProductTypeDef(NilType), ProductTypeDef(arr.codomain)) - } - } - else - invalidNec(s"Json service '${jf.name}' cannot have any arguments") - } - .getOrElse( - Validated.invalidNec[String, AquaFunction]( - s"There is no function '${jf.name}' in service '${jsonService.name}' in aqua source. Check your 'json-service' options" - ) - ) - }.sequence - - aquaFunctions.map(funcs => Service(jsonService.serviceId, funcs)) - }.sequence - } - } - -} diff --git a/cli/cli/.js/src/main/scala/aqua/run/JsonServiceOpts.scala b/cli/cli/.js/src/main/scala/aqua/run/JsonServiceOpts.scala deleted file mode 100644 index c06cc29d..00000000 --- a/cli/cli/.js/src/main/scala/aqua/run/JsonServiceOpts.scala +++ /dev/null @@ -1,87 +0,0 @@ -package aqua.run - -import aqua.ArgOpts.jsonFromFileOpts -import aqua.builder.ArgumentGetter -import aqua.js.JsonEncoder -import aqua.parser.expr.func.CallArrowExpr -import aqua.parser.lexer.{CallArrowToken, CollectionToken, LiteralToken, VarToken} -import aqua.parser.lift.Span -import aqua.raw.value.{CollectionRaw, LiteralRaw, ValueRaw, VarRaw} -import aqua.types.* -import cats.data.* -import cats.data.Validated.{invalid, invalidNec, invalidNel, valid, validNec, validNel} -import cats.effect.Concurrent -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.semigroup.* -import cats.syntax.traverse.* -import cats.{Id, Semigroup, ~>} -import com.monovore.decline.Opts -import fs2.io.file.{Files, Path} - -import scala.scalajs.js - -object JsonServiceOpts { - - def jsonServiceOpt[F[_]: Files: Concurrent] - : Opts[F[ValidatedNec[String, NonEmptyList[JsonService]]]] = { - jsonFromFileOpts("json-service", "Path to file that describes service with JSON result", "j") - .map(b => - b.map { case a: ValidatedNec[String, NonEmptyList[(Path, js.Dynamic)]] => - a.andThen { results => - results.map { case (path, res) => - val name = res.name - val serviceId = res.serviceId - val functionsRaw = res.functions - if (js.isUndefined(name) || js.typeOf(name) != "string") - invalidNec(s"No name in JSON service '$path' or it is not a string") - else if (js.isUndefined(serviceId) || js.typeOf(serviceId) != "string") - invalidNec(s"No serviceId in JSON service '$path' or it is not a string") - else if (js.isUndefined(functionsRaw) || !js.Array.isArray(functionsRaw)) - invalidNec( - s"'functions' field should exist and be an array in JSON service '$path'" - ) - else { - val functionsV: ValidatedNec[String, List[JsonFunction]] = functionsRaw - .asInstanceOf[js.Array[js.Dynamic]] - .toList - .map { f => - val fName = f.name - val fResult = f.result - if (js.isUndefined(fName) || js.typeOf(fName) != "string") - invalidNec( - s"One of the functions doesn't have a name or it is not a string in JSON service '$path'" - ) - else if (js.isUndefined(fResult)) - invalidNec(s"Function '$fName' don't have a result in '$path'") - else { - val funcName = fName.asInstanceOf[String] - JsonEncoder - .aquaTypeFromJson(funcName, fResult) - .map(t => JsonFunction(funcName, fResult, t)) - } - } - .sequence - - functionsV.andThen { fs => - NonEmptyList - .fromList(fs) - .map(fNEL => - validNec( - JsonService(name.asInstanceOf[String], serviceId.asInstanceOf[String], fNEL) - ) - ) - .getOrElse( - invalidNec(s"List of functions in '$name' service is empty in $path") - ) - } - } - }.sequence - } - } - ) - - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/run/RunCommand.scala b/cli/cli/.js/src/main/scala/aqua/run/RunCommand.scala deleted file mode 100644 index c7bde008..00000000 --- a/cli/cli/.js/src/main/scala/aqua/run/RunCommand.scala +++ /dev/null @@ -1,229 +0,0 @@ -package aqua.run - -import aqua.* -import aqua.ErrorRendering.showError -import aqua.backend.air.{AirBackend, FuncAirGen} -import aqua.backend.js.JavaScriptBackend -import aqua.backend.ts.TypeScriptBackend -import aqua.backend.Generated -import aqua.logging.LogFormatter -import aqua.definitions.{FunctionDef, TypeDefinition} -import aqua.builder.{ArgumentGetter, Finisher, ResultPrinter, Service} -import aqua.compiler.{AquaCompiled, AquaCompiler} -import aqua.files.{AquaFileSources, AquaFilesIO, FileModuleId} -import aqua.io.{AquaFileError, AquaPath, OutputPrinter, Prelude} -import aqua.js.* -import aqua.model.transform.{Transform, TransformConfig} -import aqua.model.{AquaContext, FuncArrow} -import aqua.parser.expr.func.CallArrowExpr -import aqua.parser.lexer.LiteralToken -import aqua.parser.lift.FileSpan -import aqua.raw.value.{ValueRaw, VarRaw} -import aqua.run.RunConfig -import aqua.run.RunOpts.transformConfig -import aqua.types.* -import cats.data.* -import cats.effect.* -import cats.effect.kernel.{Async, Clock} -import cats.effect.syntax.async.* -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.list.* -import cats.syntax.monad.* -import cats.syntax.show.* -import cats.syntax.traverse.* -import cats.{Id, Monad, ~>} -import fs2.io.file.{Files, Path} -import scribe.Logging - -import scala.concurrent.{ExecutionContext, Future, Promise} -import scala.scalajs.js -import scala.scalajs.js.JSConverters.* -import scala.scalajs.js.JSON -import scala.scalajs.js.annotation.* - -object RunCommand extends Logging { - - def createKeyPair( - sk: Option[Array[Byte]] - ): Future[KeyPair] = { - sk.map { arr => - val typedArr = js.typedarray.Uint8Array.from(arr.map(_.toShort).toJSArray) - KeyPair.fromEd25519SK(typedArr).toFuture - }.getOrElse(KeyPair.randomEd25519().toFuture) - } - - private def createGetter(value: VarRaw, arg: js.Dynamic, argType: Type): ArgumentGetter = { - val converted = Conversions.ts2aqua(arg, TypeDefinitionJs(TypeDefinition(argType))) - ArgumentGetter(value.copy(baseType = argType), converted) - } - - // Creates getter services for variables. Return an error if there is no variable in services - // and type of this variable couldn't be optional - private def getGettersForVars( - vars: List[(String, Type)], - argGetters: Map[String, VarJson] - ): ValidatedNec[String, List[ArgumentGetter]] = { - vars.map { (n, argType) => - val argGetterOp = argGetters.get(n) - (argGetterOp, argType) match { - case (None, _) => Validated.invalidNec(s"Unexcepted. There is no service for '$n' argument") - // BoxType could be undefined, so, pass service that will return 'undefined' for this argument - case (Some(s), _: BoxType) if s._2 == js.undefined => - Validated.validNec(createGetter(s._1, s._2, argType) :: Nil) - case (Some(s), _) if s._2 == js.undefined => - Validated.invalidNec( - s"Argument '$n' is missing. Expected argument '$n' of type '$argType'" - ) - case (Some(s), _) => - Validated.validNec(createGetter(s._1, s._2, argType) :: Nil) - } - }.reduceOption(_ combine _).getOrElse(Validated.validNec(Nil)) - } - - def resultVariableNames(funcCallable: FuncArrow, name: String): List[String] = - funcCallable.arrowType.codomain.toList.zipWithIndex.map { case (t, idx) => - name + idx - } - - /** - * Runs a function that is located in `input` file with FluenceJS SDK. Returns no output - * @param func - * function name - * @param input - * path to an aqua code with a function - * @param imports - * the sources the input needs - */ - def run[F[_]: Files: AquaIO: Async]( - func: CliFunc, - input: Option[AquaPath], - imports: List[Path], - runConfig: RunConfig, - // services that will pass arguments to air - argumentGetters: Map[String, VarJson], - // builtin services for aqua run, for example: Console, FileSystem, etc - services: List[Service], - jsonServices: List[JsonService], - plugins: List[String], - transformConfig: TransformConfig - ): F[ValidatedNec[String, Unit]] = { - val funcCompiler = new FuncCompiler[F](input, imports, transformConfig) - - for { - prelude <- Prelude.init[F](true) - contextV <- funcCompiler.compile(prelude.importPaths, true) - callResult <- Clock[F].timed { - contextV.andThen { context => - FuncCompiler - .findFunction(context, func) - .andThen(callable => - JsonService - .findServices(context, jsonServices) - .map(jsonServices => (callable, jsonServices)) - ) - }.andThen { case (funcCallable, jsonServices) => - val resultNames = resultVariableNames(funcCallable, runConfig.resultName) - val resultPrinterService = - ResultPrinter( - runConfig.resultPrinterServiceId, - runConfig.resultPrinterName, - resultNames - ) - val promiseFinisherService = - Finisher(runConfig.finisherServiceId, runConfig.finisherFnName) - - val vars = func.args - .zip(funcCallable.arrowType.domain.toList) - .collect { case (VarRaw(n, _), argType) => - (n, argType) - } - .distinctBy(_._1) - getGettersForVars(vars, argumentGetters).andThen { getters => - val gettersTags = getters.map(s => s.callTag()) - val preparer = - new CallPreparer( - func, - funcCallable, - gettersTags, - resultPrinterService.callTag, - promiseFinisherService.callTag(), - runConfig, - transformConfig - ) - preparer.prepare().map { info => - FuncCaller.funcCall[F]( - info.name, - info.air, - info.definitions, - info.config, - resultPrinterService, - promiseFinisherService, - services ++ jsonServices, - getters, - plugins - ) - } - - } - } match { - case Validated.Valid(f) => - f - case i @ Validated.Invalid(_) => i.pure[F] - } - } - (callTime, result) = callResult - } yield { - logger.debug(s"Call time: ${callTime.toMillis}ms") - result - } - } - - private val builtinServices = - aqua.builder - .Console() :: aqua.builder.IPFSUploader("ipfs") :: aqua.builder.DeployHelper() :: Nil - - /** - * Executes a function with the specified settings - * @param common - * common settings - * @param funcName - * function name - * @param inputPath - * path to a file with a function - * @param imports - * imports that must be specified for correct compilation - * @param args - * arguments to pass into a function - * @param argumentGetters - * services to get argument if it is a variable - * @param services - * will be registered before calling for correct execution - * @return - */ - def execRun[F[_]: Async]( - runInfo: RunInfo - ): F[ValidatedNec[String, Unit]] = { - val common = runInfo.common - LogFormatter.initLogger(Some(common.logLevel.compiler)) - implicit val aio: AquaIO[F] = new AquaFilesIO[F] - - RunCommand - .run[F]( - runInfo.func, - runInfo.input, - runInfo.imports, - RunConfig( - common - ), - runInfo.argumentGetters, - runInfo.services ++ builtinServices, - runInfo.jsonServices, - runInfo.pluginsPaths, - transformConfig(common.on, common.constants, common.flags.noXor, common.flags.noRelay) - ) - } - -} diff --git a/cli/cli/.js/src/main/scala/aqua/run/RunOpts.scala b/cli/cli/.js/src/main/scala/aqua/run/RunOpts.scala deleted file mode 100644 index 100df48e..00000000 --- a/cli/cli/.js/src/main/scala/aqua/run/RunOpts.scala +++ /dev/null @@ -1,116 +0,0 @@ -package aqua.run - -import aqua.* -import aqua.builder.{ArgumentGetter, Service} -import aqua.io.{AquaPath, RelativePath} -import aqua.model.transform.TransformConfig -import aqua.model.{LiteralModel, ValueModel, VarModel} -import aqua.parser.expr.func.CallArrowExpr -import aqua.parser.lexer.{LiteralToken, VarToken} -import aqua.parser.lift.LiftParser.Implicits.idLiftParser -import aqua.parser.lift.Span -import aqua.logging.LogFormatter -import aqua.raw.ConstantRaw -import aqua.raw.value.{LiteralRaw, ValueRaw, VarRaw} -import aqua.run.plugin.Plugin -import aqua.types.BottomType -import cats.data.* -import cats.data.Validated.{invalid, invalidNec, valid, validNec, validNel} -import cats.effect.kernel.Async -import cats.effect.{Concurrent, ExitCode, IO} -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.{~>, Id, Monad} -import com.monovore.decline.{Command, Opts} -import fs2.io.file.{Files, Path} -import scribe.Logging - -import java.util.Base64 -import scala.concurrent.ExecutionContext -import scala.scalajs.js -import scala.scalajs.js.JSON - -object RunOpts extends Logging { - - val OnPeerConst = "ON_PEER" - - // Default transform config with `onPeer` constant - def transformConfig( - onPeer: Option[String], - constants: List[ConstantRaw], - noXor: Boolean, - noRelay: Boolean - ): TransformConfig = { - val tc = TransformConfig( - constants = - onPeer.map(s => ConstantRaw(OnPeerConst, LiteralRaw.quote(s), false)).toList ++ constants - ) - tc.copy(relayVarName = tc.relayVarName.filterNot(_ => noRelay)) - } - - def runOptsCompose[F[_]: Files: Concurrent]: Opts[F[ValidatedNec[ - String, - (Option[AquaPath], List[Path], FuncWithData, Option[NonEmptyList[JsonService]], List[String]) - ]]] = { - ( - AppOpts.wrapWithOption(AppOpts.inputOpts[F]), - AppOpts.importOpts[F], - ArgOpts.funcWithArgsOpt[F], - AppOpts.wrapWithOption(JsonServiceOpts.jsonServiceOpt), - AppOpts.wrapWithOption(Plugin.opt) - ).mapN { case (inputF, importF, funcWithArgsF, jsonServiceOp, pluginsOp) => - for { - inputV: ValidatedNec[String, Option[AquaPath]] <- - inputF.map(_.map(_.map(p => Option(RelativePath(p))))).getOrElse { - validNec[String, Option[AquaPath]](None).pure[F] - } - importV <- importF - funcWithArgsV <- funcWithArgsF - jsonServiceV <- jsonServiceOp - .map(_.map(_.map(js => Some(js)))) - .getOrElse(validNec[String, Option[NonEmptyList[JsonService]]](None).pure[F]) - pluginsPathsV <- pluginsOp.getOrElse(validNec[String, List[String]](Nil).pure[F]) - } yield { - (inputV, importV, funcWithArgsV, jsonServiceV, pluginsPathsV).mapN { - case (i, im, f, j, p) => - (i, im, f, j, p) - } - } - } - } - - def runOptions[F[_]: AquaIO: Async]: SubCommandBuilder[F] = - SubCommandBuilder.applyF( - name = "run", - header = "Run Aqua code", - ( - GeneralOpts.runOpt, - runOptsCompose[F] - ).mapN { - case ( - common, - optionsF - ) => - LogFormatter.initLogger(Some(common.logLevel.compiler)) - optionsF.map( - _.map { case (input, imps, funcWithArgs, services, pluginsPaths) => - RunInfo( - common, - funcWithArgs.func, - input, - imps, - funcWithArgs.getters, - Nil, - services.map(_.toList).getOrElse(Nil), - pluginsPaths - ) - } - ) - } - ) - - def runCommand[F[_]: Files: AquaIO: Async]: Command[F[ValidatedNec[String, Unit]]] = - runOptions.command -} diff --git a/cli/cli/.js/src/main/scala/aqua/run/plugin/Plugin.scala b/cli/cli/.js/src/main/scala/aqua/run/plugin/Plugin.scala deleted file mode 100644 index 5da4091c..00000000 --- a/cli/cli/.js/src/main/scala/aqua/run/plugin/Plugin.scala +++ /dev/null @@ -1,149 +0,0 @@ -package aqua.run.plugin - -import aqua.js.{CallJsFunction, FluencePeer, ServiceHandler} -import aqua.run.JsonService -import aqua.run.plugin.Plugin.toPromise -import aqua.types.TopType -import aqua.definitions.* -import cats.data.{NonEmptyList, ValidatedNec} -import cats.effect.Concurrent -import cats.syntax.applicative.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.traverse.* -import cats.data.Validated.{invalid, invalidNec, valid, validNec, validNel} -import com.monovore.decline.Opts -import fs2.io.file.{Files, Path} - -import scalajs.js -import scala.concurrent.{ExecutionContext, Future} -import scala.scalajs.js.Promise - -case class Function(name: String, closure: js.Function) - -case class Plugin(name: String, functions: List[Function]) { - - def register(peer: FluencePeer): Unit = { - val (handlers, funcTypes) = functions.map { f => - // get arguments types as TopType - val argCount = f.closure.length - val fields = Range(0, argCount).toList.map { i => ("arg" + i, TopTypeDef) } - val arrowType = - ArrowTypeDef(LabeledProductTypeDef(fields), UnlabeledProductTypeDef(TopTypeDef :: Nil)) - val fType = (f.name, arrowType) - - // handlers for registering - val h: ServiceHandler = args => { - val argsList = Range(0, argCount).toList.map { i => - args(i) - } - val res = f.closure.call(this.asInstanceOf[js.Any], argsList: _*) - toPromise(res) - - } - - ((f.name, h), fType) - }.unzip - - CallJsFunction.registerService( - peer, - name, - handlers, - ServiceDef(Some(name), LabeledProductTypeDef(funcTypes), "") - ) - } -} - -object Plugin { - - private def fileExt(p: Path): String = - p.fileName.toString.split('.').toList.lastOption.getOrElse("") - - def pathToMjsFilesList[F[_]: Files: Concurrent](str: String): F[ValidatedNec[String, List[String]]] = { - val path = Path(str).absolute - Files[F] - .exists(path) - .flatMap { exists => - if (exists) - Files[F].isRegularFile(path).flatMap { isFile => - if (isFile) { - if (fileExt(path) == "mjs") { - validNec(path.toString :: Nil).pure[F] - } else { - invalidNec(s"If path '$str' is a file, it must be with '.mjs' extension") - .pure[F] - } - } else { - Files[F] - .list(path) - .evalMap { ps => - val psAbs = ps.absolute - for { - isFile <- Files[F].isRegularFile(ps) - files <- - if (isFile) { - if (fileExt(ps) == "mjs") (psAbs :: Nil).pure[F] - else Nil.pure[F] - } else if (ps.fileName.toString != "node_modules") { - Files[F].list(psAbs).filter(pp => fileExt(pp) == "mjs").compile.toList - } else { - Nil.pure[F] - } - } yield { - files - } - } - .compile - .toList - .map(_.flatten.map(_.absolute.toString)) - .map(validNec) - } - } - else { - invalidNec(s"There is no path '$str'").pure[F] - } - } - } - - def opt[F[_]: Files: Concurrent]: Opts[F[ValidatedNec[String, List[String]]]] = { - Opts - .options[String]("plugin", "[experimental] Path to a directory with JS plugins", "", "path") - .map { strs => - strs.toList.map(s => pathToMjsFilesList(s)).sequence.map(_.sequence.map(_.flatten)) - } - } - - def getPlugins(paths: List[String])(implicit - ec: ExecutionContext - ): Future[List[Plugin]] = - paths.map(p => getPlugin(p)).sequence.map(_.flatten) - - private def toPromise(arg: js.Dynamic): js.Promise[js.Dynamic] = { - if (js.typeOf(arg) == "object" && js.typeOf(arg.`then`) == "function") - arg.asInstanceOf[js.Promise[js.Dynamic]] - else js.Promise.resolve(arg) - } - - def getPlugin(path: String)(implicit - ec: ExecutionContext - ): Future[List[Plugin]] = { - for { - file <- js.`import`[js.Dynamic](path).toFuture - plugin <- { - if (js.typeOf(file.plugins) == "function") { - val res = file.applyDynamic("plugins")() - toPromise(res).toFuture.map(_.asInstanceOf[js.Dictionary[js.Dictionary[js.Any]]]) - } else { - Future(js.Dictionary[js.Dictionary[js.Any]]()) - } - } - } yield { - plugin.map { case (k, v) => - val functions = v.map { case (kf, vf) => - Function(kf, vf.asInstanceOf[js.Function]) - }.toList - Plugin(k, functions) - }.toList - } - } -} diff --git a/cli/cli/.js/src/main/scala/aqua/script/ScriptOpts.scala b/cli/cli/.js/src/main/scala/aqua/script/ScriptOpts.scala deleted file mode 100644 index 67368dbe..00000000 --- a/cli/cli/.js/src/main/scala/aqua/script/ScriptOpts.scala +++ /dev/null @@ -1,241 +0,0 @@ -package aqua.script - -import aqua.* -import aqua.ArgOpts.{dataFileOrStringOpt, funcOpt, funcWithArgsOpt} -import aqua.backend.Generated -import aqua.backend.air.{AirBackend, AirGen, FuncAirGen} -import aqua.builder.ArgumentGetter -import aqua.compiler.AquaCompiler -import aqua.js.VarJson -import aqua.io.{PackagePath, Prelude, RelativePath} -import aqua.ipfs.js.IpfsApi -import aqua.keypair.KeyPairShow.show -import aqua.model.transform.{Transform, TransformConfig} -import aqua.model.{AquaContext, FuncArrow, LiteralModel} -import aqua.parser.lift.FileSpan -import aqua.raw.ops.{Call, CallArrowRawTag} -import aqua.raw.value.{LiteralRaw, ValueRaw, VarRaw} -import aqua.res.{AquaRes, FuncRes} -import aqua.run.RunOpts.logger -import aqua.run.{CliFunc, FuncCompiler, GeneralOptions, GeneralOpts, RunCommand, RunConfig, RunOpts} -import aqua.types.{ArrowType, LiteralType, NilType, ScalarType} -import cats.data.* -import cats.data.Validated.{invalid, invalidNec, valid, validNec, validNel} -import cats.effect.kernel.{Async, Clock} -import cats.effect.{Concurrent, ExitCode, Resource, Sync} -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.show.* -import cats.syntax.traverse.* -import cats.{Applicative, Monad} -import com.monovore.decline.{Command, Opts} -import fs2.io.file.{Files, Path} -import scribe.Logging - -import scala.concurrent.ExecutionContext -import scala.scalajs.js - -object ScriptOpts extends Logging { - - val ScriptAqua = "aqua/script.aqua" - - val AddFuncName = "schedule" - val RemoveFuncName = "remove" - val ListFuncName = "list" - - case class FuncWithLiteralArgs(func: CliFunc, args: List[LiteralRaw]) - - // Func with only literal arguments (strings, booleans or numbers) - def funcWithLiteralsOpt[F[_]: Files: Concurrent] - : Opts[F[ValidatedNec[String, FuncWithLiteralArgs]]] = { - (dataFileOrStringOpt[F], funcOpt).mapN { case (dataF, func) => - dataF.map { dataV => - dataV.andThen { data => - resolveOnlyLiteralsFromData(func.args, data).map { literals => - FuncWithLiteralArgs(func, literals) - } - } - } - } - } - - private def resolveOnlyLiteralsFromData( - args: List[ValueRaw], - data: Option[js.Dynamic] - ): ValidatedNec[String, List[LiteralRaw]] = { - val literals = args.map { - case l: LiteralRaw => validNec(l) // TODO handle CollectionRaw? - case v @ VarRaw(name, _) => - data.map { d => - val arg = d.selectDynamic(name) - js.typeOf(arg) match { - case "number" => validNec(LiteralRaw(arg.toString, LiteralType.number)) - case "string" => validNec(LiteralRaw(arg.toString, LiteralType.string)) - case "boolean" => validNec(LiteralRaw(arg.toString, LiteralType.bool)) - case t => - invalidNec( - s"Scheduled script functions support 'string', 'boolean' and 'number' argument types only" - ) - } - }.getOrElse(invalidNec(s"There is no '$name' argument in data")) - case _ => - invalidNec( - s"Scheduled script functions support 'string', 'boolean' and 'number' argument types only" - ) - } - - literals.traverse(identity) - } - - def scriptOpt[F[_]: Async: AquaIO]: Command[F[ValidatedNec[String, Unit]]] = - CommandBuilder( - name = "script", - header = "Manage scheduled scripts", - NonEmptyList(add, list :: remove :: Nil) - ).command - - def intervalOpt: Opts[Option[Int]] = - AppOpts.wrapWithOption( - Opts - .option[Int]("interval", "Indicating how often the script will run in seconds", "n") - ) - - def scriptIdOpt: Opts[String] = - Opts - .option[String]("script-id", "Script id to remove", "c") - - def generateAir(callable: FuncArrow, transformConfig: TransformConfig): String = { - val funcRes = Transform.funcRes(callable, transformConfig).value - AirGen(funcRes.body).generate.show - } - - private def commonScriptOpts = GeneralOpts.commonOpt(false, true, true) - - private def compileAir[F[_]: Async: AquaIO]( - input: Path, - imports: List[Path], - funcWithArgs: FuncWithLiteralArgs - ): F[ValidatedNec[String, String]] = { - val tConfig = TransformConfig(relayVarName = None) - val funcCompiler = - new FuncCompiler[F]( - Option(RelativePath(input)), - imports, - tConfig - ) - - val funcName = funcWithArgs.func.name - - for { - prelude <- Prelude.init[F](true) - contextV <- funcCompiler.compile(prelude.importPaths) - wrappedBody = CallArrowRawTag.func(funcName, Call(funcWithArgs.func.args, Nil)).leaf - result = contextV - .andThen(context => FuncCompiler.findFunction(context, funcWithArgs.func)) - .map { callable => - generateAir( - FuncArrow( - funcName + "_scheduled", - wrappedBody, - ArrowType(NilType, NilType), - Nil, - Map(funcName -> callable), - Map.empty, - None - ), - tConfig - ) - } - } yield result - } - - def add[F[_]: Async: AquaIO]: SubCommandBuilder[F] = - SubCommandBuilder.applyF( - name = "add", - header = "Upload aqua function as a scheduled script.", - ( - commonScriptOpts, - scheduleOptsCompose[F], - intervalOpt - ).mapN { (common, optionsF, intervalOp) => - val res: F[ValidatedNec[String, RunInfo]] = optionsF - .flatMap( - _.map { case (input, imports, funcWithArgs) => - val intervalArg = - intervalOp - .map(i => LiteralRaw(i.toString, LiteralType.number)) - .getOrElse(ValueRaw.Nil) - - val someRes: F[ValidatedNec[String, RunInfo]] = for { - scriptV <- compileAir(input, imports, funcWithArgs) - result: ValidatedNec[String, RunInfo] = scriptV.map { script => - val scriptVar = VarRaw("script", ScalarType.string) - RunInfo( - common, - CliFunc(AddFuncName, scriptVar :: intervalArg :: Nil), - Option(PackagePath(ScriptAqua)), - Nil, - Map( - "script" -> VarJson( - scriptVar, - // hack, cannot create unnamed Dynamic - // TODO: fix it - scalajs.js.Dynamic.literal("script" -> script).selectDynamic("script") - ) - ) - ) - } - } yield { - result - } - - someRes - }.fold( - errs => Validated.Invalid[NonEmptyChain[String]](errs).pure[F], - identity - ) - ) - res - } - ) - - def scheduleOptsCompose[F[_]: Files: Async] - : Opts[F[ValidatedNec[String, (Path, List[Path], FuncWithLiteralArgs)]]] = { - (AppOpts.inputOpts[F], AppOpts.importOpts[F], funcWithLiteralsOpt[F]).mapN { - case (inputF, importF, funcWithLiteralsF) => - for { - inputV <- inputF - importV <- importF - funcWithLiteralsV <- funcWithLiteralsF - } yield { - (inputV, importV, funcWithLiteralsV).mapN { case (i, im, f) => - (i, im, f) - } - } - } - } - - // Removes scheduled script from a node - def remove[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder.valid[F]( - "remove", - "Remove a script from a remote peer", - ( - commonScriptOpts, - scriptIdOpt - ).mapN { (common, scriptId) => - RunInfo( - common, - CliFunc(RemoveFuncName, LiteralRaw.quote(scriptId) :: Nil), - Option(PackagePath(ScriptAqua)) - ) - } - ) - - // Print all scheduled scripts - def list[F[_]: Async]: SubCommandBuilder[F] = - SubCommandBuilder - .simple[F]("list", "Print all scheduled scripts", PackagePath(ScriptAqua), ListFuncName) -} diff --git a/cli/cli/.js/src/test/scala/aqua/JsonEncoderSpec.scala b/cli/cli/.js/src/test/scala/aqua/JsonEncoderSpec.scala deleted file mode 100644 index 8bfacfa8..00000000 --- a/cli/cli/.js/src/test/scala/aqua/JsonEncoderSpec.scala +++ /dev/null @@ -1,150 +0,0 @@ -package aqua - -import aqua.js.JsonEncoder -import aqua.types.{ArrayType, LiteralType, OptionType, StructType} -import cats.Id -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import cats.data.{NonEmptyList, NonEmptyMap} - -class JsonEncoderSpec extends AnyFlatSpec with Matchers { - - "json encoder" should "get type from json" in { - val json = scalajs.js.JSON.parse("""{ - |"arr2": [{ - | "a": "fef", - | "b": [1,2,3,4], - | "c": "erfer" - | },{ - | "a": "ferfer", - | "b": [1,2,3,4], - | "c": "erfer" - | }, { - | "a": "as", - | "d": "gerrt" - | }] - |} """.stripMargin) - val res = JsonEncoder.aquaTypeFromJson("n", json) - res.isValid shouldBe true - - val elType = StructType( - "", - NonEmptyMap.of( - ("a", LiteralType.string), - ("b", ArrayType(LiteralType.number)), - ("c", OptionType(LiteralType.string)), - ("d", OptionType(LiteralType.string)) - ) - ) - res.toOption.get shouldBe StructType("", NonEmptyMap.of(("arr2", ArrayType(elType)))) - } - - "json encoder" should "get type from json 1" in { - val json = scalajs.js.JSON.parse("""{ - |"arr2": [{ - | "b": [1,2,3,4] - | },{ - | "b": [1,2,3,4] - | }, { - | "b": "gerrt" - | }] - |} """.stripMargin) - val res = JsonEncoder.aquaTypeFromJson("n", json) - res.isValid shouldBe false - } - - "json encoder" should "get type from json 2" in { - val json = - scalajs.js.JSON.parse( - """{ - |"arr1": [{"a": [{"c": "", "d": 123}, {"c": ""}], "b": ""}, {"b": ""}], - |"arr2": [1,2,3,4], - |"arr3": ["fre", "grt", "rtgrt"], - |"str": "egrerg", - |"num": 123 - |} """.stripMargin - ) - val res = JsonEncoder.aquaTypeFromJson("n", json) - res.isValid shouldBe true - - val innerElType = StructType( - "", - NonEmptyMap.of( - ("c", LiteralType.string), - ("d", OptionType(LiteralType.number)) - ) - ) - val elType = StructType( - "", - NonEmptyMap.of( - ("a", ArrayType(innerElType)), - ("b", LiteralType.string) - ) - ) - - val t = StructType( - "", - NonEmptyMap.of( - ("arr1", ArrayType(elType)), - ("arr2", ArrayType(LiteralType.number)), - ("arr3", ArrayType(LiteralType.string)), - ("str", LiteralType.string), - ("num", LiteralType.number) - ) - ) - - res.toOption.get shouldBe t - } - - "json encoder" should "get type from json 3" in { - val json = scalajs.js.JSON.parse("""{ - |"arr2": [{ - | "b": [1,2,3,4] - | },{ - | "b": [1,2,3,4] - | }, { - | "b": "gerrt" - | }] - |} """.stripMargin) - val res = JsonEncoder.aquaTypeFromJson("n", json) - res.isValid shouldBe false - } - - "json encoder" should "get type from json 4" in { - val json = - scalajs.js.JSON.parse( - """{ - |"arr4": [{"a": "", "b": {"c": "", "d": [1,2,3,4]}}, {"a": ""}] - |} """.stripMargin - ) - val res = JsonEncoder.aquaTypeFromJson("n", json) - res.isValid shouldBe true - - val arr4InnerType = OptionType( - StructType( - "", - NonEmptyMap.of( - ("c", LiteralType.string), - ("d", ArrayType(LiteralType.number)) - ) - ) - ) - - val arr4ElType = StructType( - "", - NonEmptyMap.of( - ("a", LiteralType.string), - ("b", arr4InnerType) - ) - ) - - val t = StructType( - "", - NonEmptyMap.of( - ("arr4", ArrayType(arr4ElType)) - ) - ) - - res.toOption.get shouldBe t - } -} diff --git a/cli/cli/.js/src/test/scala/aqua/TypeValidatorSpec.scala b/cli/cli/.js/src/test/scala/aqua/TypeValidatorSpec.scala deleted file mode 100644 index 76b4ed51..00000000 --- a/cli/cli/.js/src/test/scala/aqua/TypeValidatorSpec.scala +++ /dev/null @@ -1,207 +0,0 @@ -package aqua -import aqua.run.TypeValidator -import aqua.types.{ArrayType, LiteralType, OptionType, ScalarType, StructType, Type} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import cats.data.{NonEmptyList, NonEmptyMap, ValidatedNec} - -class TypeValidatorSpec extends AnyFlatSpec with Matchers { - - val aquaType = StructType( - "some", - NonEmptyMap.of( - ("field1", OptionType(ArrayType(ScalarType.u8))), - ("field2", OptionType(ArrayType(OptionType(ScalarType.i32)))), - ("field3", ArrayType(ArrayType(ArrayType(ScalarType.i64)))), - ( - "field4", - OptionType( - StructType( - "some2", - NonEmptyMap.of( - ("innerfield1", OptionType(ScalarType.u32)), - ("innerfield2", ArrayType(ScalarType.i16)) - ) - ) - ) - ) - ) - ) - - private def validate(aquaType: Type, jsonType: Type) = { - TypeValidator.validateTypes("some", aquaType, Some(jsonType)) - } - - "type validator" should "return invalid result if check same type" in { - val res = validate(aquaType, aquaType) - res.isValid shouldBe false - } - - "type validator" should "return invalid result if there is no field" in { - val res = validate( - StructType( - "some", - NonEmptyMap.of( - ("field1", ScalarType.u8), - ("field2", ArrayType(ScalarType.string)) - ) - ), - StructType( - "some", - NonEmptyMap.of( - ("field1", ScalarType.u8) - ) - )) - res.isValid shouldBe false - } - - "type validator" should "validate optional types properly" in { - val aquaOptionalArrArrType = OptionType(ArrayType(ArrayType(ScalarType.u8))) - val aquaOptionalArrType = OptionType(ArrayType(ScalarType.u8)) - val aquaOptionalType = OptionType(ScalarType.u8) - - val res1 = validate(aquaOptionalType, LiteralType.number) - res1.isValid shouldBe true - val res2 = validate(aquaOptionalArrType, ArrayType(LiteralType.number)) - res2.isValid shouldBe true - val res3 = validate(aquaOptionalArrArrType, ArrayType(ArrayType(LiteralType.number))) - res3.isValid shouldBe true - - val res1Invalid = validate(aquaOptionalType, ArrayType(LiteralType.number)) - res1Invalid.isValid shouldBe false - } - - "type validator" should "validate array types properly" in { - val aquaArrArrArrType = ArrayType(ArrayType(ArrayType(ScalarType.u8))) - val aquaArrArrType = ArrayType(ArrayType(ScalarType.u8)) - val aquaArrType = ArrayType(ScalarType.u8) - - val res1 = validate(aquaArrType, ArrayType(LiteralType.number)) - res1.isValid shouldBe true - val res2 = validate(aquaArrArrType, ArrayType(ArrayType(LiteralType.number))) - res2.isValid shouldBe true - val res3 = validate(aquaArrArrArrType, ArrayType(ArrayType(ArrayType(LiteralType.number)))) - res3.isValid shouldBe true - - val res1invalid = validate(aquaArrType, LiteralType.number) - res1invalid.isInvalid shouldBe true - val res2invalid = validate(aquaArrArrType, ArrayType(LiteralType.number)) - res2invalid.isInvalid shouldBe true - } - - "type validator" should "validate options with arrays types properly" in { - val aquaOptArrOptArrType = OptionType(ArrayType(OptionType(ArrayType(ScalarType.u8)))) - - val res1 = validate(aquaOptArrOptArrType, ArrayType(ArrayType(LiteralType.number))) - res1.isValid shouldBe true - - val res1invalid = - validate(aquaOptArrOptArrType, ArrayType(ArrayType(ArrayType(LiteralType.number)))) - res1invalid.isValid shouldBe false - val res2invalid = - validate(aquaOptArrOptArrType, ArrayType(ArrayType(ArrayType(ArrayType(LiteralType.number))))) - res2invalid.isValid shouldBe false - } - - "type validator" should "validate complex types properly" in { - - val res1 = validate( - aquaType, - StructType( - "some", - NonEmptyMap.of( - ("field1", ArrayType(LiteralType.number)), - ("field2", ArrayType(LiteralType.number)), - ("field3", ArrayType(ArrayType(ArrayType(LiteralType.number)))), - ( - "field4", - StructType( - "some2", - NonEmptyMap.of( - ("innerfield1", LiteralType.number), - ("innerfield2", ArrayType(LiteralType.number)) - ) - ) - ) - ) - ) - ) - - res1.isValid shouldBe true - } - - "type validator" should "return invalid if there is no field" in { - val structType = StructType( - "some", - NonEmptyMap.of( - ("field1", ScalarType.u8), - ("field2", ScalarType.string), - ("field3", OptionType(ScalarType.string)) - ) - ) - - val res1invalid = validate( - structType, - StructType( - "some", - NonEmptyMap.of( - ("field2", LiteralType.string) - ) - ) - ) - res1invalid.isValid shouldBe false - - val res2invalid = validate( - structType, - StructType( - "some", - NonEmptyMap.of( - ("field1", ScalarType.u8) - ) - ) - ) - res2invalid.isValid shouldBe false - - val res1 = validate( - structType, - StructType( - "some", - NonEmptyMap.of( - ("field1", LiteralType.number), - ("field2", LiteralType.string) - ) - ) - ) - res1.isValid shouldBe true - - validate( - structType, - StructType( - "some", - NonEmptyMap.of( - ("field1", ScalarType.u8), - ("field2", ScalarType.string), - ("field3", ScalarType.string) - ) - ) - ).isValid shouldBe true - } - - "type validator" should "return invalid if there is one array when it must be two" in { - val leftType = StructType( - "some", - NonEmptyMap.of( - ("arrr", OptionType(ArrayType(ArrayType(ScalarType.u8)))) - ) - ) - - val rightType = StructType( - "some", - NonEmptyMap.of( - ("arrr", ArrayType(LiteralType.number)) - ) - ) - - validate(leftType, rightType).isInvalid shouldBe true - } -} diff --git a/cli/cli/.jvm/src/main/scala/aqua/PlatformOpts.scala b/cli/cli/.jvm/src/main/scala/aqua/PlatformOpts.scala deleted file mode 100644 index 3a2f2e6f..00000000 --- a/cli/cli/.jvm/src/main/scala/aqua/PlatformOpts.scala +++ /dev/null @@ -1,15 +0,0 @@ -package aqua - -import cats.data.ValidatedNec -import cats.effect.ExitCode -import cats.effect.kernel.Async -import cats.effect.std.Console -import com.monovore.decline.Opts -import fs2.io.file.{Files, Path} - -import scala.concurrent.ExecutionContext - -// Scala-specific options and subcommands -object PlatformOpts { - def opts[F[_]: Files: AquaIO: Async: Console]: Opts[F[ValidatedNec[String, Unit]]] = Opts.never -} diff --git a/cli/cli/.jvm/src/main/scala/aqua/Test.scala b/cli/cli/.jvm/src/main/scala/aqua/Test.scala deleted file mode 100644 index 6f894706..00000000 --- a/cli/cli/.jvm/src/main/scala/aqua/Test.scala +++ /dev/null @@ -1,43 +0,0 @@ -package aqua - -import aqua.backend.ts.TypeScriptBackend -import aqua.files.AquaFilesIO -import aqua.logging.LogFormatter -import aqua.model.transform.TransformConfig -import cats.data.Validated -import cats.effect.{IO, IOApp, Sync} -import fs2.io.file.Path -import scribe.Level - -object Test extends IOApp.Simple { - - implicit val aio: AquaIO[IO] = new AquaFilesIO[IO] - - override def run: IO[Unit] = { - scribe.Logger.root - .clearHandlers() - .clearModifiers() - .withHandler(formatter = LogFormatter.formatterWithFilename, minimumLevel = Some(Level.Info)) - .replace() - for { - start <- IO(System.currentTimeMillis()) - _ <- AquaPathCompiler - .compileFilesTo[IO]( - Path("./aqua-src/antithesis.aqua"), - List(Path("./aqua")), - Option(Path("./target")), - TypeScriptBackend(false, "IFluenceClient$$"), - TransformConfig(), - false - ) - .map { - case Validated.Invalid(errs) => - errs.map(System.err.println): Unit - case Validated.Valid(res) => - res.map(println): Unit - } - _ <- IO.println("Compilation ends in: " + (System.currentTimeMillis() - start) + " ms") - } yield () - } - -} diff --git a/cli/cli/.jvm/src/main/scala/aqua/air/AirValidation.scala b/cli/cli/.jvm/src/main/scala/aqua/air/AirValidation.scala deleted file mode 100644 index adde6919..00000000 --- a/cli/cli/.jvm/src/main/scala/aqua/air/AirValidation.scala +++ /dev/null @@ -1,15 +0,0 @@ -package aqua.air -import aqua.backend.AirFunction -import cats.data.ValidatedNec -import cats.effect.Async -import cats.data.Validated.validNec - -import scala.concurrent.ExecutionContext - -object AirValidation { - - def init[F[_]: Async](): F[Unit] = Async[F].pure(()) - - def validate[F[_]: Async](airs: List[AirFunction]): F[ValidatedNec[String, Unit]] = Async[F].pure(validNec(())) - -} diff --git a/cli/cli/.jvm/src/test/aqua/test.aqua b/cli/cli/.jvm/src/test/aqua/test.aqua deleted file mode 100644 index 57642e24..00000000 --- a/cli/cli/.jvm/src/test/aqua/test.aqua +++ /dev/null @@ -1,18 +0,0 @@ -service CustomId("cid"): - id() -> string - -func first(node_id: string, viaAr: []string) -> string: - on node_id via viaAr: - p <- CustomId.id() - <- p - - -func second(node_id: string, viaStr: *string) -> string: - on node_id via viaStr: - p <- CustomId.id() - <- p - -func third(relay: string, node_id: string, viaOpt: ?string) -> string: - on node_id via viaOpt: - p <- CustomId.id() - <- p \ No newline at end of file diff --git a/cli/cli/.jvm/src/test/scala/SourcesSpec.scala b/cli/cli/.jvm/src/test/scala/SourcesSpec.scala deleted file mode 100644 index 9a780b30..00000000 --- a/cli/cli/.jvm/src/test/scala/SourcesSpec.scala +++ /dev/null @@ -1,180 +0,0 @@ -import aqua.AquaIO -import aqua.backend.Generated -import aqua.compiler.AquaCompiled -import aqua.files.{AquaFileSources, AquaFilesIO, FileModuleId} -import cats.data.Chain -import cats.effect.IO -import cats.effect.unsafe.implicits.global -import fs2.text -import org.scalatest.matchers.should.Matchers -import fs2.io.file.{Files, Path} -import org.scalatest.flatspec.AsyncFlatSpec - -class SourcesSpec extends AsyncFlatSpec with Matchers { - implicit val aquaIO: AquaIO[IO] = AquaFilesIO.summon[IO] - - "AquaFileSources" should "generate correct fileId with imports" in { - val path = Path("cli/cli/.jvm/src/test/test-dir/path-test") - val importPath = path.resolve("imports") - - val sourceGen = new AquaFileSources[IO](path, importPath :: Nil) - sourceGen.sources.map { result => - result.isValid shouldBe true - - val listResult = result - .getOrElse(Chain.empty) - .toList - .map { case (fid, s) => - (fid.file.toString.split("/").last, s) - } - .sortBy(_._1) // sort cause different systems have different order of file reading - - val (id, importFile) = listResult(1) - id shouldBe "index.aqua" - importFile.nonEmpty shouldBe true - - val (importNearId, importFileNear) = listResult.head - importNearId shouldBe "importNear.aqua" - importFileNear.nonEmpty shouldBe true - }.unsafeToFuture() - } - - "AquaFileSources" should "throw an error if a source file doesn't exist" in { - val path = Path("some/random/path") - - val sourceGen = new AquaFileSources[IO](path, Nil) - - sourceGen.sources.map(result => result.isInvalid shouldBe true).unsafeToFuture() - } - - "AquaFileSources" should "throw an error if there is no import that is indicated in a source" in { - val path = Path("cli/cli/.jvm/src/test/test-dir") - val importPath = path.resolve("random/import/path") - - val sourceGen = new AquaFileSources[IO](path, importPath :: Nil) - sourceGen - .resolveImport(FileModuleId(path.resolve("no-file.aqua")), "no/file") - .map(result => result.isInvalid shouldBe true) - .unsafeToFuture() - } - - "AquaFileSources" should "find correct imports" in { - val srcPath = Path("cli/cli/.jvm/src/test/test-dir/index.aqua") - val importPath = srcPath.resolve("imports") - - val sourceGen = new AquaFileSources[IO](srcPath, importPath :: Nil) - - (for { - // should be found in importPath - result <- sourceGen.resolveImport(FileModuleId(srcPath), "imports/import.aqua") - exists <- { - result.isValid shouldBe true - val file = result.getOrElse(FileModuleId(Path("/some/random"))).file - Files[IO].exists(file) - } - _ = exists shouldBe true - - // should be found near src file - result2 <- sourceGen.resolveImport(FileModuleId(srcPath), "importNear.aqua") - exists2 <- { - result2.isValid shouldBe true - val file2 = result2.getOrElse(FileModuleId(Path("/some/random"))).file - Files[IO].exists(file2) - } - _ = exists2 shouldBe true - // near src file but in another directory - sourceGen2 = new AquaFileSources[IO](srcPath, Nil) - result3 <- sourceGen2.resolveImport(FileModuleId(srcPath), "imports/import.aqua") - exists3 <- { - result3.isValid shouldBe true - val file3 = result3.getOrElse(FileModuleId(Path("/some/random"))).file - Files[IO].exists(file3) - } - } yield { exists3 shouldBe true }).unsafeToFuture() - } - - "AquaFileSources" should "resolve correct path for target" in { - val path = Path("cli/cli/.jvm/src/test/test-dir") - val filePath = path.resolve("some-dir/file.aqua") - - val targetPath = Path("/target/dir/") - - val sourceGen = new AquaFileSources[IO](path, Nil) - - val suffix = "_custom.super" - - sourceGen - .resolveTargetPath(filePath, targetPath, suffix) - .map { resolved => - resolved.isValid shouldBe true - - val targetFilePath = resolved.toOption.get - targetFilePath.toString shouldBe "/target/dir/some-dir/file_custom.super" - } - .unsafeToFuture() - } - - "AquaFileSources" should "resolve correct path for target when file is in current directory" in { - val path = Path("cli/cli/.jvm/src/test/test-dir") - val filePath = path.resolve("file.aqua") - - val targetPath = Path("/target/dir/") - - val sourceGen = new AquaFileSources[IO](path, Nil) - - val suffix = "_custom.super" - - sourceGen - .resolveTargetPath(filePath, targetPath, suffix) - .map { resolved => - resolved.isValid shouldBe true - - val targetFilePath = resolved.toOption.get - targetFilePath.toString shouldBe "/target/dir/file_custom.super" - } - .unsafeToFuture() - } - - "AquaFileSources" should "write correct file with correct path" in { - val path = Path("cli/cli/.jvm/src/test/test-dir") - val filePath = path.resolve("imports/import.aqua") - - val targetPath = path.resolve("target/") - - // clean up - val resultPath = Path("cli/cli/.jvm/src/test/test-dir/target/imports/import_hey.custom") - (for { - _ <- Files[IO].deleteIfExists(resultPath) - sourceGen = new AquaFileSources[IO](path, Nil) - content = "some random content" - compiled = AquaCompiled[FileModuleId]( - FileModuleId(filePath), - Seq(Generated("_hey.custom", content, Nil)), - 1, - 1 - ) - resolved <- sourceGen.write(targetPath)(compiled) - _ = { - resolved.size shouldBe 1 - resolved.head.isValid shouldBe true - } - exists <- Files[IO].exists(resultPath) - _ = exists shouldBe true - result <- Files[IO] - .readAll(resultPath) - .fold( - Vector - .empty[Byte] - )((acc, b) => acc :+ b) - .flatMap(fs2.Stream.emits) - .through(text.utf8.decode) - .attempt - .compile - .last - resultText = result.get.right.get - _ <- Files[IO].deleteIfExists(resultPath) - } yield { - resultText shouldBe content - }).unsafeToFuture() - } -} diff --git a/cli/cli/.jvm/src/test/scala/WriteFileSpec.scala b/cli/cli/.jvm/src/test/scala/WriteFileSpec.scala deleted file mode 100644 index e395eaa4..00000000 --- a/cli/cli/.jvm/src/test/scala/WriteFileSpec.scala +++ /dev/null @@ -1,67 +0,0 @@ -import aqua.AquaPathCompiler -import aqua.backend.air.AirBackend -import aqua.backend.js.JavaScriptBackend -import aqua.backend.ts.TypeScriptBackend -import aqua.model.transform.TransformConfig -import cats.effect.IO -import cats.effect.unsafe.implicits.global -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import fs2.io.file.{Files, Path} - -class WriteFileSpec extends AnyFlatSpec with Matchers { - - "cli" should "compile aqua code in js" in { - val src = Path("./cli/cli/.jvm/src/test/aqua") - val targetTs = Files[IO].createTempDirectory.unsafeRunSync() - val targetJs = Files[IO].createTempDirectory.unsafeRunSync() - val targetAir = Files[IO].createTempDirectory.unsafeRunSync() - - import aqua.files.AquaFilesIO.summon - - val bc = TransformConfig() - AquaPathCompiler - .compileFilesTo[IO](src, List.empty, Option(targetTs), TypeScriptBackend(false), bc, false) - .unsafeRunSync() - .leftMap { err => - println(err) - err - } - .isValid should be(true) - val targetTsFile = targetTs.resolve("test.ts") - Files[IO].exists(targetTsFile).unsafeRunSync() should be(true) - Files[IO].deleteIfExists(targetTsFile).unsafeRunSync() - - AquaPathCompiler - .compileFilesTo[IO](src, List.empty, Option(targetJs), JavaScriptBackend(false), bc, false) - .unsafeRunSync() - .leftMap { err => - println(err) - err - } - .isValid should be(true) - val targetJsFile = targetJs.resolve("test.js") - Files[IO].exists(targetJsFile).unsafeRunSync() should be(true) - Files[IO].deleteIfExists(targetJsFile).unsafeRunSync() - - AquaPathCompiler - .compileFilesTo[IO](src, List.empty, Option(targetAir), AirBackend, bc, false) - .unsafeRunSync() - .leftMap { err => - println(err) - err - } - .isValid should be(true) - val targetAirFileFirst = targetAir.resolve("test.first.air") - val targetAirFileSecond = targetAir.resolve("test.second.air") - val targetAirFileThird = targetAir.resolve("test.third.air") - Files[IO].exists(targetAirFileFirst).unsafeRunSync() should be(true) - Files[IO].exists(targetAirFileSecond).unsafeRunSync() should be(true) - Files[IO].exists(targetAirFileThird).unsafeRunSync() should be(true) - - Seq(targetAirFileFirst, targetAirFileSecond, targetAirFileThird).map(f => - Files[IO].deleteIfExists(f).unsafeRunSync() - ) - } - -} diff --git a/cli/cli/.jvm/src/test/test-dir/broken-import/broken.aqua b/cli/cli/.jvm/src/test/test-dir/broken-import/broken.aqua deleted file mode 100644 index 919b4bdb..00000000 --- a/cli/cli/.jvm/src/test/test-dir/broken-import/broken.aqua +++ /dev/null @@ -1,4 +0,0 @@ -import "random/import/import.aqua" - -func indexCall(): - Println.print("it is true") \ No newline at end of file diff --git a/cli/cli/.jvm/src/test/test-dir/importNear.aqua b/cli/cli/.jvm/src/test/test-dir/importNear.aqua deleted file mode 100644 index 1a5f47af..00000000 --- a/cli/cli/.jvm/src/test/test-dir/importNear.aqua +++ /dev/null @@ -1,5 +0,0 @@ -service Println("println-service-id"): - print: string -> () - -func print(str: string): - Println.print(str) diff --git a/cli/cli/.jvm/src/test/test-dir/imports/import.aqua b/cli/cli/.jvm/src/test/test-dir/imports/import.aqua deleted file mode 100644 index 1a5f47af..00000000 --- a/cli/cli/.jvm/src/test/test-dir/imports/import.aqua +++ /dev/null @@ -1,5 +0,0 @@ -service Println("println-service-id"): - print: string -> () - -func print(str: string): - Println.print(str) diff --git a/cli/cli/.jvm/src/test/test-dir/index.aqua b/cli/cli/.jvm/src/test/test-dir/index.aqua deleted file mode 100644 index 2adf2e62..00000000 --- a/cli/cli/.jvm/src/test/test-dir/index.aqua +++ /dev/null @@ -1,4 +0,0 @@ -import "imports/import.aqua" - -func indexCall(): - Println.print("it is true") \ No newline at end of file diff --git a/cli/cli/.jvm/src/test/test-dir/path-test/importNear.aqua b/cli/cli/.jvm/src/test/test-dir/path-test/importNear.aqua deleted file mode 100644 index 1a5f47af..00000000 --- a/cli/cli/.jvm/src/test/test-dir/path-test/importNear.aqua +++ /dev/null @@ -1,5 +0,0 @@ -service Println("println-service-id"): - print: string -> () - -func print(str: string): - Println.print(str) diff --git a/cli/cli/.jvm/src/test/test-dir/path-test/index.aqua b/cli/cli/.jvm/src/test/test-dir/path-test/index.aqua deleted file mode 100644 index 2adf2e62..00000000 --- a/cli/cli/.jvm/src/test/test-dir/path-test/index.aqua +++ /dev/null @@ -1,4 +0,0 @@ -import "imports/import.aqua" - -func indexCall(): - Println.print("it is true") \ No newline at end of file diff --git a/cli/cli/src/main/resources/META-INF/native-image/jni-config.json b/cli/cli/src/main/resources/META-INF/native-image/jni-config.json deleted file mode 100644 index 084aebda..00000000 --- a/cli/cli/src/main/resources/META-INF/native-image/jni-config.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "name":"aqua.AquaCli", - "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] - }, - { - "name":"java.lang.Boolean", - "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] - }, - { - "name":"java.lang.InternalError", - "methods":[{"name":"","parameterTypes":["java.lang.String"] }] - }, - { - "name":"java.lang.String", - "methods":[ - {"name":"lastIndexOf","parameterTypes":["int"] }, - {"name":"substring","parameterTypes":["int"] } - ] - }, - { - "name":"java.lang.System", - "methods":[ - {"name":"getProperty","parameterTypes":["java.lang.String"] }, - {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] } - ] - }, - { - "name":"java.util.Arrays", - "methods":[{"name":"asList","parameterTypes":["java.lang.Object[]"] }] - } -] diff --git a/cli/cli/src/main/resources/META-INF/native-image/proxy-config.json b/cli/cli/src/main/resources/META-INF/native-image/proxy-config.json deleted file mode 100644 index 4a9716c1..00000000 --- a/cli/cli/src/main/resources/META-INF/native-image/proxy-config.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - { - "interfaces":["sun.misc.SignalHandler"] - } -] diff --git a/cli/cli/src/main/resources/META-INF/native-image/reflect-config.json b/cli/cli/src/main/resources/META-INF/native-image/reflect-config.json deleted file mode 100644 index 6547e634..00000000 --- a/cli/cli/src/main/resources/META-INF/native-image/reflect-config.json +++ /dev/null @@ -1,380 +0,0 @@ -[ -{ - "name":"aqua.AppOpts$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.AquaCli$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.backend.Version$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.io.Prelude$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.logging.LogLevels$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.model.AquaContext", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.model.AquaContext$Cache", - "fields":[{"name":"0bitmap$2"}] -}, -{ - "name":"aqua.model.ArgsCall", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.model.CallServiceModel", - "fields":[{"name":"0bitmap$14"}] -}, -{ - "name":"aqua.model.DetachModel$", - "fields":[{"name":"0bitmap$4"}] -}, -{ - "name":"aqua.model.EmptyModel$", - "fields":[{"name":"0bitmap$19"}] -}, -{ - "name":"aqua.model.FuncArrow", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.model.OnModel", - "fields":[{"name":"0bitmap$6"}] -}, -{ - "name":"aqua.model.OpModel$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.model.ParModel$", - "fields":[{"name":"0bitmap$3"}] -}, -{ - "name":"aqua.model.SeqModel$", - "fields":[{"name":"0bitmap$2"}] -}, -{ - "name":"aqua.model.VarModel", - "fields":[{"name":"0bitmap$2"}] -}, -{ - "name":"aqua.model.XorModel$", - "fields":[{"name":"0bitmap$5"}] -}, -{ - "name":"aqua.model.inline.state.InliningState$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.model.transform.cursor.ChainCursor", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.model.transform.topology.OpModelTreeCursor", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.model.transform.topology.Topology", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.parser.Expr", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.parser.Expr$$anon$1", - "fields":[{"name":"0bitmap$2"}] -}, -{ - "name":"aqua.parser.Expr$AndIndented", - "fields":[{"name":"0bitmap$3"}] -}, -{ - "name":"aqua.parser.Parser$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.parser.expr.RootExpr$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.parser.lift.Span$Focus", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.raw.RawContext", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.raw.ops.AssignmentTag", - "fields":[{"name":"0bitmap$16"}] -}, -{ - "name":"aqua.raw.ops.CallArrowRawTag", - "fields":[{"name":"0bitmap$14"}] -}, -{ - "name":"aqua.raw.ops.EmptyTag$", - "fields":[{"name":"0bitmap$19"}] -}, -{ - "name":"aqua.raw.ops.OnTag", - "fields":[{"name":"0bitmap$9"}] -}, -{ - "name":"aqua.raw.ops.ParTag$", - "fields":[{"name":"0bitmap$5"}] -}, -{ - "name":"aqua.raw.ops.ParTag$Detach$", - "fields":[{"name":"0bitmap$4"}] -}, -{ - "name":"aqua.raw.ops.RawTag$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.raw.ops.ReturnTag", - "fields":[{"name":"0bitmap$18"}] -}, -{ - "name":"aqua.raw.ops.SeqTag$", - "fields":[{"name":"0bitmap$3"}] -}, -{ - "name":"aqua.raw.ops.XorTag$", - "fields":[{"name":"0bitmap$7"}] -}, -{ - "name":"aqua.raw.ops.XorTag$LeftBiased$", - "fields":[{"name":"0bitmap$6"}] -}, -{ - "name":"aqua.res.CallServiceRes", - "fields":[{"name":"0bitmap$9"}] -}, -{ - "name":"aqua.res.ParRes$", - "fields":[{"name":"0bitmap$3"}] -}, -{ - "name":"aqua.res.SeqRes$", - "fields":[{"name":"0bitmap$2"}] -}, -{ - "name":"aqua.res.XorRes$", - "fields":[{"name":"0bitmap$4"}] -}, -{ - "name":"aqua.semantics.CompilerState", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.types.ArrowType", - "fields":[{"name":"0bitmap$4"}] -}, -{ - "name":"aqua.types.LabeledConsType", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"aqua.types.NilType$", - "fields":[{"name":"0bitmap$3"}] -}, -{ - "name":"aqua.types.Type$", - "fields":[{"name":"0bitmap$5"}] -}, -{ - "name":"aqua.types.UnlabeledConsType", - "fields":[{"name":"0bitmap$2"}] -}, -{ - "name":"cats.Later", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"cats.effect.unsafe.IORuntimeCompanionPlatform", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"cats.effect.unsafe.metrics.ComputePoolSampler", - "queryAllPublicConstructors":true -}, -{ - "name":"cats.effect.unsafe.metrics.LiveFiberSnapshotTrigger", - "queryAllPublicConstructors":true -}, -{ - "name":"cats.effect.unsafe.metrics.LocalQueueSampler", - "queryAllPublicConstructors":true -}, -{ - "name":"cats.parse.Parser$State", - "fields":[{"name":"0bitmap$2"}] -}, -{ - "name":"cats.parse.Parser0", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"fs2.Chunk$", - "fields":[{"name":"0bitmap$2"}] -}, -{ - "name":"fs2.Chunk$Queue", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"fs2.internal.ScopedResource$$anon$1", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"fs2.io.file.Files$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"fs2.io.file.Path$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"io.circe.Encoder$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"java.lang.Boolean", - "fields":[{"name":"TYPE"}] -}, -{ - "name":"java.lang.Byte", - "fields":[{"name":"TYPE"}] -}, -{ - "name":"java.lang.Character", - "fields":[{"name":"TYPE"}] -}, -{ - "name":"java.lang.ClassValue" -}, -{ - "name":"java.lang.Deprecated", - "queryAllPublicMethods":true -}, -{ - "name":"java.lang.Double", - "fields":[{"name":"TYPE"}] -}, -{ - "name":"java.lang.Float", - "fields":[{"name":"TYPE"}] -}, -{ - "name":"java.lang.Integer", - "fields":[{"name":"TYPE"}] -}, -{ - "name":"java.lang.Long", - "fields":[{"name":"TYPE"}] -}, -{ - "name":"java.lang.Short", - "fields":[{"name":"TYPE"}] -}, -{ - "name":"java.lang.StackTraceElement", - "queryAllPublicMethods":true -}, -{ - "name":"java.lang.String" -}, -{ - "name":"java.lang.Void", - "fields":[{"name":"TYPE"}] -}, -{ - "name":"java.lang.invoke.VarHandle", - "methods":[{"name":"releaseFence","parameterTypes":[] }] -}, -{ - "name":"java.math.BigDecimal" -}, -{ - "name":"java.math.BigInteger" -}, -{ - "name":"java.util.Date" -}, -{ - "name":"java.util.PropertyPermission", - "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String"] }] -}, -{ - "name":"scodec.bits.ByteVector", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"scribe.Logger", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"scribe.Logger$", - "fields":[{"name":"0bitmap$2"}] -}, -{ - "name":"scribe.Platform$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"scribe.Priority$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"scribe.format.FormatBlock$Date$Standard$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"scribe.format.Formatter$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"scribe.format.package$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"scribe.message.LazyMessage", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"scribe.modify.LevelFilter$", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"scribe.output.Color$Cyan$", - "fields":[{"name":"0bitmap$7"}] -}, -{ - "name":"scribe.output.Color$Green$", - "fields":[{"name":"0bitmap$8"}] -}, -{ - "name":"scribe.record.SimpleLogRecord", - "fields":[{"name":"0bitmap$1"}] -}, -{ - "name":"sun.misc.SignalHandler" -}, -{ - "name":"sun.misc.Unsafe", - "allDeclaredFields":true -} -] diff --git a/cli/cli/src/main/scala/aqua/AppOpts.scala b/cli/cli/src/main/scala/aqua/AppOpts.scala deleted file mode 100644 index 8beb60c9..00000000 --- a/cli/cli/src/main/scala/aqua/AppOpts.scala +++ /dev/null @@ -1,199 +0,0 @@ -package aqua - -import aqua.backend.Version -import aqua.model.LiteralModel -import aqua.model.transform.TransformConfig -import aqua.parser.expr.ConstantExpr -import aqua.parser.lift.LiftParser -import aqua.raw.ConstantRaw -import aqua.raw.value.LiteralRaw -import aqua.constants.Constants -import cats.data.Validated.{Invalid, Valid} -import cats.data.{NonEmptyList, Validated, ValidatedNec, ValidatedNel} -import cats.data.Validated.{invalidNel, validNel} -import cats.effect.kernel.Async -import cats.effect.std.Console -import cats.effect.{ExitCode, IO} -import cats.syntax.applicative.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.traverse.* -import cats.{~>, Comonad, Functor, Monad} -import com.monovore.decline.Opts.help -import com.monovore.decline.{Argument, Opts, Visibility} -import fs2.io.file.{Files, Path} -import scribe.Level - -import scala.concurrent.{ExecutionContext, Future} - -object AppOpts { - - val helpOpt: Opts[Unit] = - Opts.flag("help", help = "Display this help text", "h", Visibility.Partial).asHelp.as(()) - - val versionOpt: Opts[Unit] = - Opts.flag("version", help = "Show version", "v", Visibility.Partial) - - def checkOutput[F[_]: Monad: Files](pathStr: String): F[ValidatedNec[String, Option[Path]]] = { - val p = Path(pathStr) - Files[F] - .exists(p) - .flatMap { exists => - if (exists) - Files[F].isRegularFile(p).map { isFile => - if (isFile) { - Validated.invalidNec(s"Output path should be a directory. Current: '$p'") - } else - Validated.validNec(Option(p)) - } - else - Files[F].createDirectories(p).map(_ => Validated.validNec(Option(p))) - } - } - - def inputOpts[F[_]: Monad: Files]: Opts[F[ValidatedNec[String, Path]]] = { - FileOpts.pathOpt( - "input", - "Path to an aqua file or an input directory that contains your .aqua files", - "i", - s => - FileOpts - .checkDirOrFile(s) - ) - } - - def outputOpts[F[_]: Monad: Files]: Opts[F[ValidatedNec[String, Option[Path]]]] = - Opts - .option[String]( - "output", - "Path to the output directory. Will be created if it doesn't exists", - "o", - "path" - ) - .map(s => Option(s)) - .withDefault(None) - .map(_.map(checkOutput[F]).getOrElse(Validated.validNec[String, Option[Path]](None).pure[F])) - - def importOpts[F[_]: Monad: Files]: Opts[F[ValidatedNec[String, List[Path]]]] = - Opts - .options[String]( - "import", - "Path to the directory to import from. May be used several times", - "m", - "path" - ) - .orEmpty - .map { ps => - val checked: List[F[ValidatedNec[String, Path]]] = ps.map { pStr => - val p = Path(pStr) - for { - exists <- Files[F].exists(p) - isDir <- Files[F].isDirectory(p) - } yield { - if (exists && isDir) Validated.validNec[String, Path](p) - else - Validated.invalidNec[String, Path]( - s"${p.toString}: No such directory" - ) - } - } - - checked.sequence.map(_.sequence) - } - - def constantOpts: Opts[List[ConstantRaw]] = - Opts - .options[String]( - "const", - "Constant that will be used in the aqua code that you run. Constant name must be upper cased.", - "c", - "NAME=value" - ) - .mapValidated { strs => - Constants.parse(strs.toList) - } - .withDefault(List.empty) - - val noAirValidation: Opts[Boolean] = - Opts - .flag("no-air-validation", "Don't parse and validate AIR after compilation") - .map(_ => false) - .withDefault(true) - - val compileToAir: Opts[Boolean] = - Opts - .flag("air", "Generate .air file instead of .ts", "a") - .map(_ => true) - .withDefault(false) - - val compileToJs: Opts[Boolean] = - Opts - .flag("js", "Generate .js file instead of .ts") - .map(_ => true) - .withDefault(false) - - val noRelay: Opts[Boolean] = - Opts - .flag("no-relay", "Do not generate a pass through the relay node") - .map(_ => true) - .withDefault(false) - - val noXorWrapper: Opts[Boolean] = - Opts - .flag("no-xor", "Do not generate a wrapper that catches and displays errors") - .map(_ => true) - .withDefault(false) - - val tracing: Opts[Boolean] = - Opts - .flag("trace", "Generate tace events calls") - .map(_ => true) - .withDefault(false) - - val isOldFluenceJs: Opts[Boolean] = - Opts - .flagOption[String]( - "old-fluence-js", - "Generate TypeScript or JavaScript files for new JS Client" - ) - .mapValidated { - case Some(str) => - str.toLowerCase match { - case "true" => validNel(true) - case "false" => validNel(false) - case s => invalidNel(s"'$s' must be 'true' or 'false'") - } - case None => validNel(true) - - } - .withDefault(false) - - val dryOpt: Opts[Boolean] = - Opts - .flag("dry", "Checks if compilation is succeeded, without output") - .map(_ => true) - .withDefault(false) - - val scriptOpt: Opts[Boolean] = - Opts - .flag( - "scheduled", - "Generate air code for script storage. Without error handling wrappers, hops on relay and tracing. Will ignore other options" - ) - .map(_ => true) - .withDefault(false) - - lazy val versionStr: String = - Version.version - - def versionAndExit[F[_]: Console: Functor]: F[ExitCode] = Console[F] - .println(versionStr) - .as(ExitCode.Success) - - def helpAndExit[F[_]: Console: Functor]: F[ExitCode] = Console[F] - .println(help) - .as(ExitCode.Success) - - def wrapWithOption[A](opt: Opts[A]): Opts[Option[A]] = - opt.map(v => Some(v)).withDefault(None) -} diff --git a/cli/cli/src/main/scala/aqua/AquaCli.scala b/cli/cli/src/main/scala/aqua/AquaCli.scala deleted file mode 100644 index 94eb5fdd..00000000 --- a/cli/cli/src/main/scala/aqua/AquaCli.scala +++ /dev/null @@ -1,238 +0,0 @@ -package aqua - -import aqua.backend.Backend -import aqua.backend.air.AirBackend -import aqua.backend.js.JavaScriptBackend -import aqua.backend.ts.TypeScriptBackend -import aqua.logging.LogFormatter -import aqua.files.AquaFilesIO -import aqua.io.OutputPrinter -import aqua.model.transform.TransformConfig -import aqua.parser.lift.LiftParser.Implicits.idLiftParser -import cats.data.* -import cats.effect.* -import cats.effect.std.Console as ConsoleEff -import cats.syntax.applicative.* -import cats.syntax.apply.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.traverse.* -import cats.{~>, Functor, Id, Monad} -import com.monovore.decline -import com.monovore.decline.effect.CommandIOApp -import com.monovore.decline.effect.CommandIOApp.printHelp -import com.monovore.decline.{Command, Help, Opts, PlatformApp} -import fs2.io.file.Files -import scribe.Logging - -import scala.concurrent.Future - -object AquaCli extends IOApp with Logging { - import AppOpts.* - - sealed trait CompileTarget - case object TypescriptTarget extends CompileTarget - case object JavaScriptTarget extends CompileTarget - case object AirTarget extends CompileTarget - - def targetToBackend(target: CompileTarget, isOldFluenceJs: Boolean): Backend = { - val client = if (isOldFluenceJs) "FluencePeer" else Backend.client - target match { - case TypescriptTarget => - TypeScriptBackend(isOldFluenceJs, client) - case JavaScriptTarget => - JavaScriptBackend(isOldFluenceJs, client) - case AirTarget => - AirBackend - } - } - - def printErrorsOr[F[_]: Async: ConsoleEff, T]( - result: ValidatedNec[String, T], - or: T => F[ExitCode] - ): F[ExitCode] = { - result match { - case Validated.Invalid(errs) => - printCommandErrors[F](errs).as { - ExitCode.Error - } - case Validated.Valid(results) => - or(results) - } - } - - def printCommandErrors[F[_]: ConsoleEff: Async](errs: NonEmptyChain[String]): F[Unit] = { - errs.map(OutputPrinter.errorF _).sequence.flatMap { _ => - OutputPrinter.errorF("\nTry 'aqua --help' for usage instructions") - } - - } - - def main[F[_]: Files: ConsoleEff: Async](runtime: unsafe.IORuntime): Opts[F[ExitCode]] = { - implicit val r = runtime - implicit val aio: AquaIO[F] = new AquaFilesIO[F] - implicit val ec = r.compute - - PlatformOpts.opts.map { res => - res.flatMap { - case Validated.Invalid(errs) => - printCommandErrors[F](errs).as { - ExitCode.Error - } - case Validated.Valid(_) => - ExitCode.Success.pure[F] - } - } orElse versionOpt - .as( - versionAndExit - ) orElse helpOpt.as( - helpAndExit - ) orElse ( - inputOpts[F], - importOpts[F], - outputOpts[F], - compileToAir, - compileToJs, - noRelay, - noXorWrapper, // TODO: Remove - tracing, - isOldFluenceJs, - wrapWithOption(helpOpt), - wrapWithOption(versionOpt), - FluenceOpts.logLevelOpt, - constantOpts, - dryOpt, - scriptOpt, - noAirValidation - ).mapN { - case ( - inputF, - importsF, - outputF, - toAirOp, - toJs, - noRelayOp, - noXorOp, - tracingOp, - isOldFluenceJsOp, - h, - v, - logLevel, - constants, - isDryRun, - isScheduled, - disableAirValidation - ) => - val toAir = toAirOp || isScheduled - val noXor = noXorOp || isScheduled - val noRelay = noRelayOp || isScheduled - val tracingEnabled = tracingOp && !isScheduled - - // if there is `--help` or `--version` flag - show help and version - // otherwise continue program execution - h.map(_ => helpAndExit) orElse v.map(_ => versionAndExit) getOrElse { - val target = - if (toAir) AirTarget - else if (toJs) JavaScriptTarget - else TypescriptTarget - val bc = { - val bc = TransformConfig( - constants = constants, - tracing = Option.when(tracingEnabled)(TransformConfig.TracingConfig.default) - ) - bc.copy(relayVarName = bc.relayVarName.filterNot(_ => noRelay)) - } - LogFormatter.initLogger(Some(logLevel.compiler)) - logger.info(s"Aqua Compiler $versionStr") - - (inputF, outputF, importsF).mapN { (i, o, imp) => - i.andThen { input => - o.andThen { output => - imp.map { imports => - if (output.isEmpty && !isDryRun) - Validated - .invalidNec( - "Output path should be specified ('--output' or '-o'). " + - "Or use --dry if you want to check that the code compiles" - ) - .pure[F] - else { - val resultOutput = if (isDryRun) { - None - } else { - output - } - AquaPathCompiler - .compileFilesTo[F]( - input, - imports, - resultOutput, - targetToBackend(target, isOldFluenceJsOp), - bc, - disableAirValidation - ) - } - } - } - } - }.flatMap { results => - printErrorsOr[F, F[ValidatedNec[String, Chain[String]]]]( - results, - { res => - res.flatMap { - case Validated.Invalid(errs) => - printCommandErrors[F](errs).as { - ExitCode.Error - } - case Validated.Valid(results) => - results.map(OutputPrinter.print _) - ExitCode.Success.pure[F] - } - } - ) - } - } - } - } - - def handleCommand(args: List[String]): IO[ExitCode] = { - val command = Command("aqua", "Aqua Compiler", false)(main[IO](runtime)) - for { - parseResult: Either[Help, IO[ExitCode]] <- Sync[IO].delay( - // ambientArgs returns arguments for scala.js under node.js - command.parse(PlatformApp.ambientArgs getOrElse args, sys.env) - ) - exitCode <- parseResult.fold( - { h => - NonEmptyChain - .fromSeq(h.errors) - .map { errs => - printCommandErrors[IO](errs).as { - ExitCode.Error - } - } - .getOrElse { - ConsoleEff[IO].print(h).map { _ => - // hack to show last string in `help` - println() - ExitCode.Success - } - } - }, - identity - ) - } yield exitCode - } - - override def run(args: List[String]): IO[ExitCode] = { - handleCommand( - args match { - // Weird ugly hack: in case version flag or help flag is present, ignore other options, - // be it correct or not - case _ if args.contains("-v") || args.contains("--version") => "-v" :: Nil - case _ if args.contains("-h") || args.contains("--help") => "-h" :: Nil - case _ => args - } - ) - } -} diff --git a/cli/cli/src/main/scala/aqua/AquaPathCompiler.scala b/cli/cli/src/main/scala/aqua/AquaPathCompiler.scala deleted file mode 100644 index c64cba56..00000000 --- a/cli/cli/src/main/scala/aqua/AquaPathCompiler.scala +++ /dev/null @@ -1,98 +0,0 @@ -package aqua - -import aqua.backend.{Backend, Generated} -import aqua.compiler.{AirValidator, AquaCompiled, AquaCompiler, AquaCompilerConf, AquaError, CompilerAPI} -import aqua.files.{AquaFileSources, FileModuleId} -import aqua.io.Prelude -import aqua.io.* -import aqua.air.AirValidation -import aqua.backend.AirFunction -import aqua.model.AquaContext -import aqua.model.transform.TransformConfig -import aqua.model.transform.Transform -import aqua.parser.lift.LiftParser.LiftErrorOps -import aqua.parser.lift.Span.spanLiftParser -import aqua.parser.lift.{FileSpan, LiftParser, Span} -import aqua.parser.{Ast, LexerError, Parser} -import aqua.raw.ConstantRaw -import aqua.res.AquaRes -import cats.data.* -import cats.effect.Async -import cats.parse.LocationMap -import cats.syntax.applicative.* -import cats.syntax.functor.* -import cats.syntax.flatMap.* -import cats.syntax.show.* -import cats.{Applicative, Eval, Monad, Show, ~>} -import fs2.io.file.{Files, Path} -import scribe.Logging -import cats.data.Validated.validNec - -object AquaPathCompiler extends Logging { - - /** - * @param srcPath path to aqua sources - * @param imports additional paths to possible aqua imports - * @param targetPath path where compiled files will be created. Creates no output if empty - * @param backend creates output (TS, JS, ...) from a model - * @param transformConfig transformation configuration for a model - * @return errors or result messages - */ - def compileFilesTo[F[_]: AquaIO: Monad: Files: Async]( - srcPath: Path, - imports: List[Path], - targetPath: Option[Path], - backend: Backend, - transformConfig: TransformConfig, - disableAirValidation: Boolean - ): F[ValidatedNec[String, Chain[String]]] = { - import ErrorRendering.showError - (for { - prelude <- Prelude.init() - sources = new AquaFileSources[F](srcPath, imports ++ prelude.importPaths) - validator = - if (disableAirValidation) { - new AirValidator[F] { - override def init(): F[Unit] = Applicative[F].pure(()) - override def validate(airs: List[AirFunction]): F[ValidatedNec[String, Unit]] = - Applicative[F].pure(validNec(())) - } - } else { - new AirValidator[F] { - override def init(): F[Unit] = AirValidation.init[F]() - override def validate( - airs: List[AirFunction] - ): F[ValidatedNec[String, Unit]] = AirValidation.validate[F](airs) - } - } - compiler <- CompilerAPI - .compileTo[F, AquaFileError, FileModuleId, FileSpan.F, String]( - sources, - SpanParser.parser, - validator, - new Backend.Transform: - override def transform(ex: AquaContext): AquaRes = - Transform.contextRes(ex, transformConfig) - - override def generate(aqua: AquaRes): Seq[Generated] = backend.generate(aqua) - , - AquaCompilerConf(transformConfig.constantsList), - targetPath.map(sources.write).getOrElse(dry[F]) - ) - } yield { - compiler - // 'distinct' to delete all duplicated errors - }).map(_.leftMap(_.map(_.show).distinct)) - - } - - def dry[F[_]: Applicative]( - ac: AquaCompiled[FileModuleId] - ): F[Seq[Validated[AquaFileError, String]]] = - Seq( - Validated.valid[AquaFileError, String]( - s"Source ${ac.sourceId.file}: compilation OK" - ) - ).pure[F] - -} diff --git a/cli/cli/src/main/scala/aqua/FileOpts.scala b/cli/cli/src/main/scala/aqua/FileOpts.scala deleted file mode 100644 index 8efbaf68..00000000 --- a/cli/cli/src/main/scala/aqua/FileOpts.scala +++ /dev/null @@ -1,134 +0,0 @@ -package aqua - -import cats.data.Validated.{invalid, invalidNec, valid, validNec, validNel} -import cats.data.* -import cats.effect.Concurrent -import cats.syntax.applicative.* -import cats.syntax.flatMap.* -import cats.syntax.functor.* -import cats.syntax.traverse.* -import cats.{~>, Comonad, Functor, Monad} -import com.monovore.decline.Opts -import fs2.io.file.{Files, Path} - -object FileOpts { - - // Validate, read and transform a file - def fileOptionalOpt[A, F[_]: Files: Concurrent]( - long: String, - help: String, - short: String = "", - transform: (Path, String) => ValidatedNec[String, A] - ): Opts[Option[F[ValidatedNec[String, A]]]] = { - AppOpts.wrapWithOption(fileOpt(long, help, short, transform)) - } - - // Get and validate path - def pathOpt[A, F[_]: Files: Monad]( - long: String, - help: String, - short: String = "", - check: String => F[ValidatedNec[String, Path]] - ): Opts[F[ValidatedNec[String, Path]]] = - Opts - .option[String](long, help, short, "path") - .map(check) - - def fileOptTransform[A, F[_]: Files: Concurrent]( - str: String, - transform: (Path, String) => ValidatedNec[String, A] - ): F[ValidatedNec[String, (Path, A)]] = { - checkAndTransformPath( - str, - checkFile, - { p => - Files[F] - .readAll(p) - .through(fs2.text.utf8.decode) - .fold(List.empty[String]) { case (acc, str) => acc :+ str } - .map(_.mkString("")) - .map(str => transform(p, str).map(r => (p, r))) - .compile - .last - .map(_.getOrElse(invalidNec(s"Path ${p.toString} is empty"))) - } - ) - } - - // Validate, read and transform a file - def fileOpt[A, F[_]: Files: Concurrent]( - long: String, - help: String, - short: String = "", - transform: (Path, String) => ValidatedNec[String, A] - ): Opts[F[ValidatedNec[String, A]]] = { - Opts - .option[String](long, help, short, "path") - .map(str => fileOptTransform(str, transform).map(_.map(_._2))) - } - - // Validate, read and transform multiple files - def fileOpts[A, F[_]: Files: Concurrent]( - long: String, - help: String, - short: String = "", - transform: (Path, String) => ValidatedNec[String, A] - ): Opts[F[ValidatedNec[String, NonEmptyList[(Path, A)]]]] = { - Opts - .options[String](long, help, short, "path") - .map(strs => strs.map(str => fileOptTransform(str, transform)).sequence.map(_.sequence)) - } - - // Checks if the path is a file and it exists - def checkFile[F[_]: Files: Monad](path: String): F[ValidatedNec[String, Path]] = { - val p = Path(path) - Files[F] - .exists(p) - .flatMap { exists => - if (exists) - Files[F].isRegularFile(p).map { isFile => - if (isFile) { - validNec(p) - } else { - invalidNec(s"Path '${p.toString}' is not a file") - } - } - else { - invalidNec(s"There is no path '${p.toString}'").pure[F] - } - } - } - - // Checks if the path is a file or a directory and it exists - def checkDirOrFile[F[_]: Files: Monad]( - path: String, - isAqua: Boolean = true - ): F[ValidatedNec[String, Path]] = { - val p = Path(path) - Files[F] - .exists(p) - .flatMap { exists => - if (exists) - Files[F].isRegularFile(p).map { isFile => - if (isFile && p.extName != ".aqua") - Validated.invalidNec("File must have '.aqua' extension") - else Validated.validNec(p) - } - else { - invalidNec(s"'${p.toString}': No such file or directory").pure[F] - } - } - } - - // Checks a path and transforms it - def checkAndTransformPath[F[_]: Files: Concurrent, T]( - path: String, - check: String => F[ValidatedNec[String, Path]], - transform: Path => F[ValidatedNec[String, T]] - ): F[ValidatedNec[String, T]] = { - check(path).flatMap { - case Validated.Valid(p) => transform(p) - case i @ Validated.Invalid(_) => i.pure[F] - } - } -} diff --git a/cli/cli/src/main/scala/aqua/FluenceOpts.scala b/cli/cli/src/main/scala/aqua/FluenceOpts.scala deleted file mode 100644 index f3c81fd2..00000000 --- a/cli/cli/src/main/scala/aqua/FluenceOpts.scala +++ /dev/null @@ -1,65 +0,0 @@ -package aqua - -import cats.data.{NonEmptyList, Validated, ValidatedNel} -import aqua.logging.LogLevels -import com.monovore.decline.Opts -import scribe.Level -import cats.syntax.traverse.* -import cats.data.Validated.{invalid, invalidNec, invalidNel, valid, validNec, validNel} - -import java.util.Base64 -import java.util.concurrent.TimeUnit -import scala.concurrent.duration.Duration - -object FluenceOpts { - - val timeoutOpt: Opts[Duration] = - Opts - .option[Int]("timeout", "Request timeout in milliseconds", "t") - .map(i => Duration(i, TimeUnit.MILLISECONDS)) - - val onOpt: Opts[Option[String]] = - AppOpts.wrapWithOption( - Opts - .option[String]( - "on", - "peerId of the peer that will execute the function. Default: host_peer_id", - "o", - "peerId" - ) - ) - - val showConfigOpt: Opts[Boolean] = - Opts - .flag("show-config", "Print current configuration on start") - .map(_ => true) - .withDefault(false) - - val verboseOpt: Opts[Boolean] = - Opts - .flag("verbose", "Show additional information about the call") - .map(_ => true) - .withDefault(false) - - val secretKeyOpt: Opts[Array[Byte]] = - Opts - .option[String]("sk", "Ed25519 32-byte secret key in base64", "s", "base64") - .mapValidated { s => - val decoder = Base64.getDecoder - Validated.catchNonFatal { - decoder.decode(s) - }.leftMap(t => NonEmptyList.one("secret key isn't a valid base64 string: " + t.getMessage)) - } - - val printAir: Opts[Boolean] = - Opts - .flag("print-air", "Prints generated AIR code before function execution") - .map(_ => true) - .withDefault(false) - - val logLevelOpt: Opts[LogLevels] = - Opts.option[String]("log-level", help = s"Set log level. ${LogLevels.logHelpMessage}").mapValidated { - str => - LogLevels.fromString(str) - }.withDefault(LogLevels()) -} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 1648f287..09d7c147 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,4 @@ packages: - - 'cli/cli-npm' - 'api/api-npm' - 'api/api-example' - 'language-server/language-server-npm'