mirror of
https://github.com/fluencelabs/aqua.git
synced 2025-04-24 22:42:13 +00:00
parent
e22867caa4
commit
3e762d6654
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
@ -22,12 +22,6 @@ jobs:
|
|||||||
### Setup
|
### Setup
|
||||||
- uses: olafurpg/setup-scala@v10
|
- uses: olafurpg/setup-scala@v10
|
||||||
|
|
||||||
### Update & build
|
|
||||||
- name: Assembly
|
|
||||||
run: sbt cli/assembly
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ github.run_number }}
|
|
||||||
|
|
||||||
- name: JS build
|
- name: JS build
|
||||||
run: sbt cliJS/fullLinkJS
|
run: sbt cliJS/fullLinkJS
|
||||||
env:
|
env:
|
||||||
@ -55,12 +49,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
BUILD_NUMBER: ${{ github.run_number }}
|
BUILD_NUMBER: ${{ github.run_number }}
|
||||||
|
|
||||||
- name: Check .jar exists
|
|
||||||
run: |
|
|
||||||
JAR="cli/.jvm/target/scala-3.0.2/aqua-${{ env.VERSION }}.jar"
|
|
||||||
stat "$JAR"
|
|
||||||
echo "JAR=$JAR" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Check .js exists
|
- name: Check .js exists
|
||||||
run: |
|
run: |
|
||||||
JS="cli/.js/target/scala-3.0.2/cli-opt/aqua-${{ env.VERSION }}.js"
|
JS="cli/.js/target/scala-3.0.2/cli-opt/aqua-${{ env.VERSION }}.js"
|
||||||
@ -74,7 +62,6 @@ jobs:
|
|||||||
node-version: "15"
|
node-version: "15"
|
||||||
registry-url: "https://registry.npmjs.org"
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
- run: cp ${{ env.JAR }} ./npm/aqua.jar
|
|
||||||
- run: cp ${{ env.JS }} ./npm/aqua.js
|
- run: cp ${{ env.JS }} ./npm/aqua.js
|
||||||
|
|
||||||
- run: npm version ${{ env.VERSION }}
|
- run: npm version ${{ env.VERSION }}
|
||||||
@ -118,7 +105,6 @@ jobs:
|
|||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
files: |
|
files: |
|
||||||
${{ env.JAR }}
|
|
||||||
${{ env.JS }}
|
${{ env.JS }}
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
package aqua
|
package aqua
|
||||||
|
|
||||||
|
import aqua.js.{AvmLogLevel, FluenceJSLogLevel, Meta, Module}
|
||||||
|
import fs2.io.file.Path
|
||||||
import scribe.Level
|
import scribe.Level
|
||||||
|
|
||||||
object Utils {
|
import scala.util.Try
|
||||||
|
|
||||||
|
object LogLevelTransformer {
|
||||||
|
|
||||||
def logLevelToAvm(logLevel: Level): AvmLogLevel = {
|
def logLevelToAvm(logLevel: Level): AvmLogLevel = {
|
||||||
logLevel match {
|
logLevel match {
|
||||||
case Level.Trace => "trace"
|
case Level.Trace => "trace"
|
@ -1,18 +1,39 @@
|
|||||||
package aqua
|
package aqua
|
||||||
|
|
||||||
|
import aqua.js.{Meta, Module}
|
||||||
import cats.effect.ExitCode
|
import cats.effect.ExitCode
|
||||||
import cats.effect.kernel.Async
|
import cats.effect.kernel.Async
|
||||||
import com.monovore.decline.Opts
|
import com.monovore.decline.Opts
|
||||||
import fs2.io.file.Files
|
import fs2.io.file.{Files, Path}
|
||||||
import scala.concurrent.ExecutionContext
|
|
||||||
|
|
||||||
|
import scala.concurrent.ExecutionContext
|
||||||
import aqua.run.RunOpts
|
import aqua.run.RunOpts
|
||||||
import aqua.keypair.KeyPairOpts
|
import aqua.keypair.KeyPairOpts
|
||||||
|
import scribe.Logging
|
||||||
|
|
||||||
|
import scala.util.Try
|
||||||
|
|
||||||
// JS-specific options and subcommands
|
// JS-specific options and subcommands
|
||||||
object PlatformOpts {
|
object PlatformOpts extends Logging {
|
||||||
def opts[F[_]: Files: AquaIO: Async](implicit ec: ExecutionContext): Opts[F[ExitCode]] =
|
|
||||||
Opts.subcommand(RunOpts.runCommand[F]) orElse
|
|
||||||
Opts.subcommand(KeyPairOpts.createKeypair[F])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
def opts[F[_]: Files: AquaIO: Async](implicit ec: ExecutionContext): Opts[F[ExitCode]] =
|
||||||
|
Opts.subcommand(RunOpts.runCommand[F]) orElse
|
||||||
|
Opts.subcommand(KeyPairOpts.createKeypair[F])
|
||||||
|
|
||||||
|
// get path to node modules if there is `aqua-lib` module with `builtin.aqua` in it
|
||||||
|
def getGlobalNodeModulePath: Option[Path] = {
|
||||||
|
val meta = Meta.metaUrl
|
||||||
|
val req = Module.createRequire(meta)
|
||||||
|
Try {
|
||||||
|
// this can throw an error
|
||||||
|
val pathStr = req.resolve("@fluencelabs/aqua-lib/builtin.aqua").toString
|
||||||
|
// hack
|
||||||
|
Path(pathStr).parent.map(_.resolve("../.."))
|
||||||
|
}.getOrElse {
|
||||||
|
// we don't care about path if there is no builtins, but must write an error
|
||||||
|
logger.error("Unexpected. Cannot find 'aqua-lib' dependency with `builtin.aqua` in it")
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package aqua
|
package aqua.js
|
||||||
|
|
||||||
import aqua.backend.{ArgDefinition, FunctionDef, NamesConfig, TypeDefinition}
|
import aqua.backend.{ArgDefinition, FunctionDef, NamesConfig, TypeDefinition}
|
||||||
import aqua.model.transform.TransformConfig
|
import aqua.model.transform.TransformConfig
|
@ -1,5 +1,6 @@
|
|||||||
package aqua
|
package aqua.js
|
||||||
|
|
||||||
|
import aqua.*
|
||||||
import aqua.backend.{ArgDefinition, FunctionDef, NamesConfig, TypeDefinition}
|
import aqua.backend.{ArgDefinition, FunctionDef, NamesConfig, TypeDefinition}
|
||||||
|
|
||||||
import scala.concurrent.Promise
|
import scala.concurrent.Promise
|
25
cli/.js/src/main/scala/aqua/js/Npm.scala
Normal file
25
cli/.js/src/main/scala/aqua/js/Npm.scala
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package aqua.js
|
||||||
|
|
||||||
|
import scala.scalajs.js
|
||||||
|
import scala.scalajs.js.annotation.{JSExportAll, JSImport}
|
||||||
|
|
||||||
|
object Meta {
|
||||||
|
|
||||||
|
// get `import`.meta.url info from javascript
|
||||||
|
// it is needed for `createRequire` function
|
||||||
|
@js.native
|
||||||
|
@JSImport("./utils.js", "metaUrl")
|
||||||
|
val metaUrl: String = js.native
|
||||||
|
}
|
||||||
|
|
||||||
|
@js.native
|
||||||
|
@JSImport("module", JSImport.Namespace)
|
||||||
|
object Module extends js.Object {
|
||||||
|
|
||||||
|
// make it possible to use `require` in ES module type
|
||||||
|
def createRequire(str: String): Require = js.native
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Require extends js.Object {
|
||||||
|
def resolve(str: String): Any
|
||||||
|
}
|
@ -1,18 +1,18 @@
|
|||||||
package aqua.keypair
|
package aqua.keypair
|
||||||
|
|
||||||
import cats.effect.ExitCode
|
import aqua.io.OutputPrinter
|
||||||
import cats.effect.kernel.{Async}
|
import aqua.js.KeyPair
|
||||||
import cats.Monad
|
import aqua.keypair.KeyPairShow.show
|
||||||
import cats.implicits.catsSyntaxApplicativeId
|
|
||||||
import cats.Applicative
|
|
||||||
import cats.Applicative.ops.toAllApplicativeOps
|
import cats.Applicative.ops.toAllApplicativeOps
|
||||||
import cats.syntax.show._
|
import cats.effect.ExitCode
|
||||||
|
import cats.effect.kernel.Async
|
||||||
|
import cats.implicits.catsSyntaxApplicativeId
|
||||||
|
import cats.syntax.show.*
|
||||||
|
import cats.{Applicative, Monad}
|
||||||
import com.monovore.decline.{Command, Opts}
|
import com.monovore.decline.{Command, Opts}
|
||||||
import scribe.Logging
|
import scribe.Logging
|
||||||
import scala.concurrent.{ExecutionContext, Future}
|
|
||||||
|
|
||||||
import aqua.KeyPair
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
import KeyPairShow.show
|
|
||||||
|
|
||||||
// Options and commands to work with KeyPairs
|
// Options and commands to work with KeyPairs
|
||||||
object KeyPairOpts extends Logging {
|
object KeyPairOpts extends Logging {
|
||||||
@ -33,7 +33,7 @@ object KeyPairOpts extends Logging {
|
|||||||
KeyPair.randomEd25519().toFuture.pure[F]
|
KeyPair.randomEd25519().toFuture.pure[F]
|
||||||
)
|
)
|
||||||
.map(keypair =>
|
.map(keypair =>
|
||||||
println(s"${keypair.show}")
|
OutputPrinter.print(s"${keypair.show}")
|
||||||
ExitCode.Success
|
ExitCode.Success
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
package aqua.keypair
|
package aqua.keypair
|
||||||
|
|
||||||
import scala.scalajs.js.JSON
|
import aqua.js.KeyPair
|
||||||
import scala.scalajs.js
|
|
||||||
import java.util.Base64
|
|
||||||
|
|
||||||
import aqua.KeyPair
|
|
||||||
import cats.Show
|
import cats.Show
|
||||||
|
|
||||||
|
import java.util.Base64
|
||||||
|
import scala.scalajs.js
|
||||||
|
import scala.scalajs.js.JSON
|
||||||
|
|
||||||
object KeyPairShow {
|
object KeyPairShow {
|
||||||
def stringify(keypair: KeyPair): String = {
|
def stringify(keypair: KeyPair): String = {
|
||||||
val encoder = Base64.getEncoder()
|
val encoder = Base64.getEncoder()
|
||||||
val kp = js.Dynamic.literal(
|
val kp = js.Dynamic.literal(
|
||||||
peerId = keypair.Libp2pPeerId.toB58String(),
|
peerId = keypair.Libp2pPeerId.toB58String(),
|
||||||
secretKey = encoder.encodeToString(keypair.toEd25519PrivateKey().toArray.map(s => s.toByte)),
|
secretKey = encoder.encodeToString(keypair.toEd25519PrivateKey().toArray.map(s => s.toByte)),
|
||||||
publicKey = encoder.encodeToString(keypair.Libp2pPeerId.pubKey.bytes.toArray.map(s => s.toByte)),
|
publicKey = encoder.encodeToString(keypair.Libp2pPeerId.pubKey.bytes.toArray.map(s => s.toByte)),
|
||||||
)
|
)
|
||||||
|
|
||||||
JSON.stringify(kp, space = 4)
|
JSON.stringify(kp, space = 4)
|
||||||
|
@ -7,7 +7,8 @@ import aqua.backend.ts.TypeScriptBackend
|
|||||||
import aqua.backend.{FunctionDef, Generated}
|
import aqua.backend.{FunctionDef, Generated}
|
||||||
import aqua.compiler.{AquaCompiled, AquaCompiler}
|
import aqua.compiler.{AquaCompiled, AquaCompiler}
|
||||||
import aqua.files.{AquaFileSources, AquaFilesIO, FileModuleId}
|
import aqua.files.{AquaFileSources, AquaFilesIO, FileModuleId}
|
||||||
import aqua.io.AquaFileError
|
import aqua.io.{AquaFileError, OutputPrinter}
|
||||||
|
import aqua.js.*
|
||||||
import aqua.model.func.raw.{CallArrowTag, CallServiceTag, FuncOp, FuncOps}
|
import aqua.model.func.raw.{CallArrowTag, CallServiceTag, FuncOp, FuncOps}
|
||||||
import aqua.model.func.{Call, FuncCallable}
|
import aqua.model.func.{Call, FuncCallable}
|
||||||
import aqua.model.transform.res.{AquaRes, FuncRes}
|
import aqua.model.transform.res.{AquaRes, FuncRes}
|
||||||
@ -34,6 +35,7 @@ import scribe.Logging
|
|||||||
|
|
||||||
import scala.concurrent.{ExecutionContext, Future, Promise}
|
import scala.concurrent.{ExecutionContext, Future, Promise}
|
||||||
import scala.scalajs.js
|
import scala.scalajs.js
|
||||||
|
import scala.scalajs.js.Dynamic.global as g
|
||||||
import scala.scalajs.js.JSConverters.*
|
import scala.scalajs.js.JSConverters.*
|
||||||
import scala.scalajs.js.JSON
|
import scala.scalajs.js.JSON
|
||||||
import scala.scalajs.js.annotation.*
|
import scala.scalajs.js.annotation.*
|
||||||
@ -61,7 +63,7 @@ object RunCommand extends Logging {
|
|||||||
)(implicit
|
)(implicit
|
||||||
ec: ExecutionContext
|
ec: ExecutionContext
|
||||||
): F[Unit] = {
|
): F[Unit] = {
|
||||||
FluenceUtils.setLogLevel(Utils.logLevelToFluenceJS(config.logLevel))
|
FluenceUtils.setLogLevel(LogLevelTransformer.logLevelToFluenceJS(config.logLevel))
|
||||||
|
|
||||||
// stops peer in any way at the end of execution
|
// stops peer in any way at the end of execution
|
||||||
val resource = Resource.make(Fluence.getPeer().pure[F]) { peer =>
|
val resource = Resource.make(Fluence.getPeer().pure[F]) { peer =>
|
||||||
@ -74,10 +76,10 @@ object RunCommand extends Logging {
|
|||||||
secretKey <- keyPairOrNull(config.secretKey)
|
secretKey <- keyPairOrNull(config.secretKey)
|
||||||
_ <- Fluence
|
_ <- Fluence
|
||||||
.start(
|
.start(
|
||||||
PeerConfig(multiaddr, config.timeout, Utils.logLevelToAvm(config.logLevel), secretKey)
|
PeerConfig(multiaddr, config.timeout, LogLevelTransformer.logLevelToAvm(config.logLevel), secretKey)
|
||||||
)
|
)
|
||||||
.toFuture
|
.toFuture
|
||||||
_ = println("Your peerId: " + peer.getStatus().peerId)
|
_ = OutputPrinter.print("Your peerId: " + peer.getStatus().peerId)
|
||||||
promise = Promise.apply[Unit]()
|
promise = Promise.apply[Unit]()
|
||||||
_ = CallJsFunction.registerUnitService(
|
_ = CallJsFunction.registerUnitService(
|
||||||
peer,
|
peer,
|
||||||
@ -88,7 +90,7 @@ object RunCommand extends Logging {
|
|||||||
// if an input function returns a result, our success will be after it is printed
|
// 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
|
// otherwise finish after JS SDK will finish sending a request
|
||||||
// TODO use custom function for output
|
// TODO use custom function for output
|
||||||
println(str)
|
OutputPrinter.print(str)
|
||||||
promise.success(())
|
promise.success(())
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -112,7 +114,6 @@ object RunCommand extends Logging {
|
|||||||
// func wrapFunc():
|
// func wrapFunc():
|
||||||
// res <- funcCallable(args:_*)
|
// res <- funcCallable(args:_*)
|
||||||
// Console.print(res)
|
// Console.print(res)
|
||||||
// TODO: now it supports only one result. If funcCallable will return multiple results, only first will be printed
|
|
||||||
private def wrapCall(
|
private def wrapCall(
|
||||||
funcName: String,
|
funcName: String,
|
||||||
funcCallable: FuncCallable,
|
funcCallable: FuncCallable,
|
||||||
@ -157,7 +158,7 @@ object RunCommand extends Logging {
|
|||||||
"Function execution failed by timeout. You can increase timeout with '--timeout' option in milliseconds or check if your code can hang while executing."
|
"Function execution failed by timeout. You can increase timeout with '--timeout' option in milliseconds or check if your code can hang while executing."
|
||||||
} else t.getMessage
|
} else t.getMessage
|
||||||
// TODO use custom function for error output
|
// TODO use custom function for error output
|
||||||
println(message)
|
OutputPrinter.error(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,9 +179,9 @@ object RunCommand extends Logging {
|
|||||||
)(implicit ec: ExecutionContext): F[Unit] = {
|
)(implicit ec: ExecutionContext): F[Unit] = {
|
||||||
implicit val aio: AquaIO[IO] = new AquaFilesIO[IO]
|
implicit val aio: AquaIO[IO] = new AquaFilesIO[IO]
|
||||||
|
|
||||||
val sources = new AquaFileSources[F](input, imports)
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
prelude <- Prelude.init()
|
||||||
|
sources = new AquaFileSources[F](input, prelude.importPaths)
|
||||||
// compile only context to wrap and call function later
|
// compile only context to wrap and call function later
|
||||||
compileResult <- Clock[F].timed(
|
compileResult <- Clock[F].timed(
|
||||||
AquaCompiler
|
AquaCompiler
|
||||||
@ -204,7 +205,7 @@ object RunCommand extends Logging {
|
|||||||
val air = FuncAirGen(funcRes).generate.show
|
val air = FuncAirGen(funcRes).generate.show
|
||||||
|
|
||||||
if (runConfig.printAir) {
|
if (runConfig.printAir) {
|
||||||
println(air)
|
OutputPrinter.print(air)
|
||||||
}
|
}
|
||||||
|
|
||||||
funcCall[F](multiaddr, air, definitions, runConfig).map { _ =>
|
funcCall[F](multiaddr, air, definitions, runConfig).map { _ =>
|
||||||
@ -223,7 +224,7 @@ object RunCommand extends Logging {
|
|||||||
logger.debug(s"Call time: ${callTime.toMillis}ms")
|
logger.debug(s"Call time: ${callTime.toMillis}ms")
|
||||||
result.fold(
|
result.fold(
|
||||||
{ (errs: NonEmptyChain[String]) =>
|
{ (errs: NonEmptyChain[String]) =>
|
||||||
errs.toChain.toList.foreach(err => println(err + "\n"))
|
errs.toChain.toList.foreach(err => OutputPrinter.error(err + "\n"))
|
||||||
},
|
},
|
||||||
identity
|
identity
|
||||||
)
|
)
|
||||||
|
@ -13,7 +13,7 @@ import cats.syntax.applicative.*
|
|||||||
import cats.syntax.apply.*
|
import cats.syntax.apply.*
|
||||||
import cats.syntax.flatMap.*
|
import cats.syntax.flatMap.*
|
||||||
import cats.syntax.functor.*
|
import cats.syntax.functor.*
|
||||||
import cats.{Id, Monad, ~>}
|
import cats.{~>, Id, Monad}
|
||||||
import com.monovore.decline.{Command, Opts}
|
import com.monovore.decline.{Command, Opts}
|
||||||
import fs2.io.file.Files
|
import fs2.io.file.Files
|
||||||
import scribe.Logging
|
import scribe.Logging
|
||||||
@ -24,9 +24,10 @@ import scala.concurrent.ExecutionContext
|
|||||||
object RunOpts extends Logging {
|
object RunOpts extends Logging {
|
||||||
|
|
||||||
val timeoutOpt: Opts[Int] =
|
val timeoutOpt: Opts[Int] =
|
||||||
Opts.option[Int]("timeout", "Request timeout in milliseconds", "t")
|
Opts
|
||||||
|
.option[Int]("timeout", "Request timeout in milliseconds", "t")
|
||||||
.withDefault(7000)
|
.withDefault(7000)
|
||||||
|
|
||||||
val multiaddrOpt: Opts[String] =
|
val multiaddrOpt: Opts[String] =
|
||||||
Opts
|
Opts
|
||||||
.option[String]("addr", "Relay multiaddress", "a")
|
.option[String]("addr", "Relay multiaddress", "a")
|
||||||
@ -57,7 +58,6 @@ object RunOpts extends Logging {
|
|||||||
.map(_ => true)
|
.map(_ => true)
|
||||||
.withDefault(false)
|
.withDefault(false)
|
||||||
|
|
||||||
|
|
||||||
val funcOpt: Opts[(String, List[LiteralModel])] =
|
val funcOpt: Opts[(String, List[LiteralModel])] =
|
||||||
Opts
|
Opts
|
||||||
.option[String]("func", "Function to call with args", "f")
|
.option[String]("func", "Function to call with args", "f")
|
||||||
@ -70,7 +70,9 @@ object RunOpts extends Logging {
|
|||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
if (hasVars) {
|
if (hasVars) {
|
||||||
Validated.invalidNel("Function can have only literal arguments, no variables or constants allowed at the moment")
|
Validated.invalidNel(
|
||||||
|
"Function can have only literal arguments, no variables or constants allowed at the moment"
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
val args = expr.args.collect { case l @ Literal(_, _) =>
|
val args = expr.args.collect { case l @ Literal(_, _) =>
|
||||||
LiteralModel(l.value, l.ts)
|
LiteralModel(l.value, l.ts)
|
||||||
@ -85,9 +87,26 @@ object RunOpts extends Logging {
|
|||||||
def runOptions[F[_]: Files: AquaIO: Async](implicit
|
def runOptions[F[_]: Files: AquaIO: Async](implicit
|
||||||
ec: ExecutionContext
|
ec: ExecutionContext
|
||||||
): Opts[F[cats.effect.ExitCode]] =
|
): Opts[F[cats.effect.ExitCode]] =
|
||||||
(AppOpts.inputOpts[F], AppOpts.importOpts[F], multiaddrOpt, funcOpt, timeoutOpt, AppOpts.logLevelOpt, printAir, AppOpts.wrapWithOption(secretKeyOpt)).mapN {
|
(
|
||||||
case (inputF, importF, multiaddr, (func, args), timeout, logLevel, printAir, secretKey) =>
|
AppOpts.inputOpts[F],
|
||||||
|
AppOpts.importOpts[F],
|
||||||
|
multiaddrOpt,
|
||||||
|
funcOpt,
|
||||||
|
timeoutOpt,
|
||||||
|
AppOpts.logLevelOpt,
|
||||||
|
printAir,
|
||||||
|
AppOpts.wrapWithOption(secretKeyOpt)
|
||||||
|
).mapN {
|
||||||
|
case (
|
||||||
|
inputF,
|
||||||
|
importF,
|
||||||
|
multiaddr,
|
||||||
|
(func, args),
|
||||||
|
timeout,
|
||||||
|
logLevel,
|
||||||
|
printAir,
|
||||||
|
secretKey
|
||||||
|
) =>
|
||||||
scribe.Logger.root
|
scribe.Logger.root
|
||||||
.clearHandlers()
|
.clearHandlers()
|
||||||
.clearModifiers()
|
.clearModifiers()
|
||||||
@ -114,7 +133,14 @@ object RunOpts extends Logging {
|
|||||||
},
|
},
|
||||||
{ imps =>
|
{ imps =>
|
||||||
RunCommand
|
RunCommand
|
||||||
.run(multiaddr, func, args, input, imps, RunConfig(timeout, logLevel, printAir, secretKey))
|
.run(
|
||||||
|
multiaddr,
|
||||||
|
func,
|
||||||
|
args,
|
||||||
|
input,
|
||||||
|
imps,
|
||||||
|
RunConfig(timeout, logLevel, printAir, secretKey)
|
||||||
|
)
|
||||||
.map(_ => cats.effect.ExitCode.Success)
|
.map(_ => cats.effect.ExitCode.Success)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -2,8 +2,10 @@ package aqua
|
|||||||
|
|
||||||
import cats.effect.ExitCode
|
import cats.effect.ExitCode
|
||||||
import com.monovore.decline.Opts
|
import com.monovore.decline.Opts
|
||||||
|
import fs2.io.file.Path
|
||||||
|
|
||||||
// Scala-specific options and subcommands
|
// Scala-specific options and subcommands
|
||||||
object PlatformOpts {
|
object PlatformOpts {
|
||||||
def opts[F[_]]: Opts[F[ExitCode]] = Opts.never
|
def opts[F[_]]: Opts[F[ExitCode]] = Opts.never
|
||||||
|
def getGlobalNodeModulePath: Option[Path] = None
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import cats.syntax.applicative.*
|
|||||||
import cats.syntax.flatMap.*
|
import cats.syntax.flatMap.*
|
||||||
import cats.syntax.functor.*
|
import cats.syntax.functor.*
|
||||||
import cats.syntax.traverse.*
|
import cats.syntax.traverse.*
|
||||||
import cats.{Comonad, Functor, Monad, ~>}
|
import cats.{~>, Comonad, Functor, Monad}
|
||||||
import com.monovore.decline.Opts.help
|
import com.monovore.decline.Opts.help
|
||||||
import com.monovore.decline.{Opts, Visibility}
|
import com.monovore.decline.{Opts, Visibility}
|
||||||
import fs2.io.file.{Files, Path}
|
import fs2.io.file.{Files, Path}
|
||||||
@ -92,14 +92,19 @@ object AppOpts {
|
|||||||
.map(s => checkPath[F](s))
|
.map(s => checkPath[F](s))
|
||||||
|
|
||||||
def outputOpts[F[_]: Monad: Files]: Opts[F[ValidatedNec[String, Option[Path]]]] =
|
def outputOpts[F[_]: Monad: Files]: Opts[F[ValidatedNec[String, Option[Path]]]] =
|
||||||
Opts.option[String]("output", "Path to the output directory. Will be created if not exists", "o")
|
Opts
|
||||||
|
.option[String]("output", "Path to the output directory. Will be created if not exists", "o")
|
||||||
.map(s => Option(s))
|
.map(s => Option(s))
|
||||||
.withDefault(None)
|
.withDefault(None)
|
||||||
.map(_.map(checkOutput[F]).getOrElse(Validated.validNec[String, Option[Path]](None).pure[F]))
|
.map(_.map(checkOutput[F]).getOrElse(Validated.validNec[String, Option[Path]](None).pure[F]))
|
||||||
|
|
||||||
def importOpts[F[_]: Monad: Files]: Opts[F[ValidatedNec[String, List[Path]]]] =
|
def importOpts[F[_]: Monad: Files]: Opts[F[ValidatedNec[String, List[Path]]]] =
|
||||||
Opts
|
Opts
|
||||||
.options[String]("import", "Path to the directory to import from. May be used several times", "m")
|
.options[String](
|
||||||
|
"import",
|
||||||
|
"Path to the directory to import from. May be used several times",
|
||||||
|
"m"
|
||||||
|
)
|
||||||
.orEmpty
|
.orEmpty
|
||||||
.map { ps =>
|
.map { ps =>
|
||||||
val checked: List[F[ValidatedNec[String, Path]]] = ps.map { pStr =>
|
val checked: List[F[ValidatedNec[String, Path]]] = ps.map { pStr =>
|
||||||
@ -116,21 +121,7 @@ object AppOpts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if node_modules directory exists and add it in imports list
|
checked.sequence.map(_.sequence)
|
||||||
val nodeModules = Path("node_modules")
|
|
||||||
val nodeImportF: F[Option[Path]] = Files[F].exists(nodeModules).flatMap {
|
|
||||||
case true =>
|
|
||||||
Files[F].isDirectory(nodeModules).map(isDir => if (isDir) Some(nodeModules) else None )
|
|
||||||
case false => None.pure[F]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for {
|
|
||||||
result <- checked.sequence.map(_.sequence)
|
|
||||||
nodeImport <- nodeImportF
|
|
||||||
} yield {
|
|
||||||
result.map(_ ++ nodeImport)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def constantOpts[F[_]: LiftParser: Comonad]: Opts[List[TransformConfig.Const]] =
|
def constantOpts[F[_]: LiftParser: Comonad]: Opts[List[TransformConfig.Const]] =
|
||||||
@ -193,7 +184,10 @@ object AppOpts {
|
|||||||
|
|
||||||
val scriptOpt: Opts[Boolean] =
|
val scriptOpt: Opts[Boolean] =
|
||||||
Opts
|
Opts
|
||||||
.flag("scheduled", "Generate air code for script storage. Without error handling wrappers and hops on relay. Will ignore other options")
|
.flag(
|
||||||
|
"scheduled",
|
||||||
|
"Generate air code for script storage. Without error handling wrappers and hops on relay. Will ignore other options"
|
||||||
|
)
|
||||||
.map(_ => true)
|
.map(_ => true)
|
||||||
.withDefault(false)
|
.withDefault(false)
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ object AquaCli extends IOApp with Logging {
|
|||||||
constantOpts[Id],
|
constantOpts[Id],
|
||||||
dryOpt,
|
dryOpt,
|
||||||
scriptOpt
|
scriptOpt
|
||||||
).mapN {
|
).mapN {
|
||||||
case (inputF, importsF, outputF, toAirOp, toJs, noRelayOp, noXorOp, h, v, logLevel, constants, isDryRun, isScheduled) =>
|
case (inputF, importsF, outputF, toAirOp, toJs, noRelayOp, noXorOp, h, v, logLevel, constants, isDryRun, isScheduled) =>
|
||||||
scribe.Logger.root
|
scribe.Logger.root
|
||||||
.clearHandlers()
|
.clearHandlers()
|
||||||
|
@ -13,8 +13,9 @@ import cats.data.*
|
|||||||
import cats.parse.LocationMap
|
import cats.parse.LocationMap
|
||||||
import cats.syntax.applicative.*
|
import cats.syntax.applicative.*
|
||||||
import cats.syntax.functor.*
|
import cats.syntax.functor.*
|
||||||
|
import cats.syntax.flatMap.*
|
||||||
import cats.syntax.show.*
|
import cats.syntax.show.*
|
||||||
import cats.{Applicative, Eval, Monad, Show, ~>}
|
import cats.{~>, Applicative, Eval, Monad, Show}
|
||||||
import fs2.io.file.{Files, Path}
|
import fs2.io.file.{Files, Path}
|
||||||
import scribe.Logging
|
import scribe.Logging
|
||||||
|
|
||||||
@ -36,17 +37,22 @@ object AquaPathCompiler extends Logging {
|
|||||||
transformConfig: TransformConfig
|
transformConfig: TransformConfig
|
||||||
): F[ValidatedNec[String, Chain[String]]] = {
|
): F[ValidatedNec[String, Chain[String]]] = {
|
||||||
import ErrorRendering.showError
|
import ErrorRendering.showError
|
||||||
val sources = new AquaFileSources[F](srcPath, imports)
|
(for {
|
||||||
AquaCompiler
|
prelude <- Prelude.init(withPrelude = false)
|
||||||
.compileTo[F, AquaFileError, FileModuleId, FileSpan.F, String](
|
sources = new AquaFileSources[F](srcPath, imports ++ prelude.importPaths)
|
||||||
sources,
|
compiler <- AquaCompiler
|
||||||
SpanParser.parser,
|
.compileTo[F, AquaFileError, FileModuleId, FileSpan.F, String](
|
||||||
backend,
|
sources,
|
||||||
transformConfig,
|
SpanParser.parser,
|
||||||
targetPath.map(sources.write).getOrElse(dry[F])
|
backend,
|
||||||
)
|
transformConfig,
|
||||||
|
targetPath.map(sources.write).getOrElse(dry[F])
|
||||||
|
)
|
||||||
|
} yield {
|
||||||
|
compiler
|
||||||
// 'distinct' to delete all duplicated errors
|
// 'distinct' to delete all duplicated errors
|
||||||
.map(_.leftMap(_.map(_.show).distinct))
|
}).map(_.leftMap(_.map(_.show).distinct))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def dry[F[_]: Applicative](
|
def dry[F[_]: Applicative](
|
||||||
|
39
cli/src/main/scala/aqua/Prelude.scala
Normal file
39
cli/src/main/scala/aqua/Prelude.scala
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package aqua
|
||||||
|
|
||||||
|
import cats.Monad
|
||||||
|
import cats.syntax.applicative.*
|
||||||
|
import cats.syntax.flatMap.*
|
||||||
|
import cats.syntax.functor.*
|
||||||
|
import fs2.io.file.{Files, Path}
|
||||||
|
import scribe.Logging
|
||||||
|
|
||||||
|
import scala.util.Try
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param importPaths list of paths where imports will be searched
|
||||||
|
*/
|
||||||
|
case class Prelude(importPaths: List[Path])
|
||||||
|
|
||||||
|
// JS-specific functions
|
||||||
|
object Prelude extends Logging {
|
||||||
|
|
||||||
|
def init[F[_]: Files: Monad](withPrelude: Boolean = true): F[Prelude] = {
|
||||||
|
// check if node_modules directory exists and add it in imports list
|
||||||
|
val nodeModules = Path("node_modules")
|
||||||
|
val nodeImportF: F[Option[Path]] = Files[F].exists(nodeModules).flatMap {
|
||||||
|
case true =>
|
||||||
|
Files[F].isDirectory(nodeModules).map(isDir => if (isDir) Some(nodeModules) else None)
|
||||||
|
case false => None.pure[F]
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeImportF.map { nodeImport =>
|
||||||
|
val imports =
|
||||||
|
if (withPrelude)
|
||||||
|
nodeImport.toList ++ PlatformOpts.getGlobalNodeModulePath.toList
|
||||||
|
else nodeImport.toList
|
||||||
|
|
||||||
|
new Prelude(imports)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
cli/src/main/scala/aqua/io/OutputPrinter.scala
Normal file
14
cli/src/main/scala/aqua/io/OutputPrinter.scala
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package aqua.io
|
||||||
|
|
||||||
|
// Uses to print outputs in CLI
|
||||||
|
// TODO: add F[_], cause it is effect
|
||||||
|
object OutputPrinter {
|
||||||
|
|
||||||
|
def print(str: String): Unit = {
|
||||||
|
println(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
def error(str: String): Unit = {
|
||||||
|
println(str)
|
||||||
|
}
|
||||||
|
}
|
25
npm/package-lock.json
generated
25
npm/package-lock.json
generated
@ -9,7 +9,8 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fluencelabs/fluence": "0.15.1"
|
"@fluencelabs/aqua-lib": "0.2.1",
|
||||||
|
"@fluencelabs/fluence": "0.15.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"aqua": "index.js",
|
"aqua": "index.js",
|
||||||
@ -75,6 +76,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
|
||||||
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="
|
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@fluencelabs/aqua-lib": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-lib/-/aqua-lib-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-uLP9mbgFHR1Q1FYhehasNxNBlTclBsjNI9MvIPF8oXtVJtnvPi+R4rGGTOHtRJukunxhpAV/svWQU9a2BRyDmQ=="
|
||||||
|
},
|
||||||
"node_modules/@fluencelabs/avm": {
|
"node_modules/@fluencelabs/avm": {
|
||||||
"version": "0.16.0-restriction-operator.9",
|
"version": "0.16.0-restriction-operator.9",
|
||||||
"resolved": "https://registry.npmjs.org/@fluencelabs/avm/-/avm-0.16.0-restriction-operator.9.tgz",
|
"resolved": "https://registry.npmjs.org/@fluencelabs/avm/-/avm-0.16.0-restriction-operator.9.tgz",
|
||||||
@ -84,9 +90,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@fluencelabs/fluence": {
|
"node_modules/@fluencelabs/fluence": {
|
||||||
"version": "0.15.1",
|
"version": "0.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/@fluencelabs/fluence/-/fluence-0.15.1.tgz",
|
"resolved": "https://registry.npmjs.org/@fluencelabs/fluence/-/fluence-0.15.2.tgz",
|
||||||
"integrity": "sha512-ZHLw85XgVMglCVJjGkdGRFzL7kO2x31BCYDt4BVlMCE/S2nFSsVHU8DO35Jlh40QZhQdN3F5dbJpkgdcwdC8bw==",
|
"integrity": "sha512-RWGh70XkqcJusaqB4TR0tVBSVkzlMU9krwALQmgilLTxaSBMPtB6xMt13ceEJ/G6BwsLZWdgY2Wy6GvdSheKaw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chainsafe/libp2p-noise": "4.0.0",
|
"@chainsafe/libp2p-noise": "4.0.0",
|
||||||
"@fluencelabs/avm": "0.16.0-restriction-operator.9",
|
"@fluencelabs/avm": "0.16.0-restriction-operator.9",
|
||||||
@ -2818,6 +2824,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@fluencelabs/aqua-lib": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-lib/-/aqua-lib-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-uLP9mbgFHR1Q1FYhehasNxNBlTclBsjNI9MvIPF8oXtVJtnvPi+R4rGGTOHtRJukunxhpAV/svWQU9a2BRyDmQ=="
|
||||||
|
},
|
||||||
"@fluencelabs/avm": {
|
"@fluencelabs/avm": {
|
||||||
"version": "0.16.0-restriction-operator.9",
|
"version": "0.16.0-restriction-operator.9",
|
||||||
"resolved": "https://registry.npmjs.org/@fluencelabs/avm/-/avm-0.16.0-restriction-operator.9.tgz",
|
"resolved": "https://registry.npmjs.org/@fluencelabs/avm/-/avm-0.16.0-restriction-operator.9.tgz",
|
||||||
@ -2827,9 +2838,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@fluencelabs/fluence": {
|
"@fluencelabs/fluence": {
|
||||||
"version": "0.15.1",
|
"version": "0.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/@fluencelabs/fluence/-/fluence-0.15.1.tgz",
|
"resolved": "https://registry.npmjs.org/@fluencelabs/fluence/-/fluence-0.15.2.tgz",
|
||||||
"integrity": "sha512-ZHLw85XgVMglCVJjGkdGRFzL7kO2x31BCYDt4BVlMCE/S2nFSsVHU8DO35Jlh40QZhQdN3F5dbJpkgdcwdC8bw==",
|
"integrity": "sha512-RWGh70XkqcJusaqB4TR0tVBSVkzlMU9krwALQmgilLTxaSBMPtB6xMt13ceEJ/G6BwsLZWdgY2Wy6GvdSheKaw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@chainsafe/libp2p-noise": "4.0.0",
|
"@chainsafe/libp2p-noise": "4.0.0",
|
||||||
"@fluencelabs/avm": "0.16.0-restriction-operator.9",
|
"@fluencelabs/avm": "0.16.0-restriction-operator.9",
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"aqua.js",
|
"aqua.js",
|
||||||
"index.js",
|
"index.js",
|
||||||
"index-java.js",
|
"error.js",
|
||||||
"error.js"
|
"utils.js"
|
||||||
],
|
],
|
||||||
"bin": {
|
"bin": {
|
||||||
"aqua": "index.js",
|
"aqua": "index.js",
|
||||||
@ -18,7 +18,8 @@
|
|||||||
"from:scalajs": "cp ../cli/.js/target/scala-3.0.2/cli-opt/main.js ./aqua.js && npm run run -- $@"
|
"from:scalajs": "cp ../cli/.js/target/scala-3.0.2/cli-opt/main.js ./aqua.js && npm run run -- $@"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fluencelabs/fluence": "0.15.1"
|
"@fluencelabs/fluence": "0.15.2",
|
||||||
|
"@fluencelabs/aqua-lib": "0.2.1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
2
npm/utils.js
Normal file
2
npm/utils.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// It should work in scala as js.`import`.meta.url, but it doesn't compile for some reasons
|
||||||
|
export const metaUrl = import.meta.url
|
@ -1,4 +1,4 @@
|
|||||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")
|
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")
|
||||||
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.0")
|
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.1")
|
||||||
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.1.0")
|
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.1.0")
|
||||||
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0")
|
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user