From 3e762d665445472b44b9f1d471c6d7fb20ae8f1f Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 3 Dec 2021 20:30:00 +0300 Subject: [PATCH] #370 #377 #378 Builtin as default import and minor changes (#384) --- .github/workflows/release.yml | 14 ------ ...{Utils.scala => LogLevelTransformer.scala} | 7 ++- .../src/main/scala/aqua/PlatformOpts.scala | 35 ++++++++++++--- .../scala/aqua/{ => js}/CallJsFunction.scala | 2 +- .../FluenceJsTypes.scala} | 3 +- cli/.js/src/main/scala/aqua/js/Npm.scala | 25 +++++++++++ .../main/scala/aqua/keypair/KeyPairOpts.scala | 20 ++++----- .../main/scala/aqua/keypair/KeyPairShow.scala | 16 +++---- .../src/main/scala/aqua/run/RunCommand.scala | 23 +++++----- cli/.js/src/main/scala/aqua/run/RunOpts.scala | 44 +++++++++++++++---- .../src/main/scala/aqua/PlatformOpts.scala | 4 +- cli/src/main/scala/aqua/AppOpts.scala | 32 ++++++-------- cli/src/main/scala/aqua/AquaCli.scala | 2 +- .../main/scala/aqua/AquaPathCompiler.scala | 28 +++++++----- cli/src/main/scala/aqua/Prelude.scala | 39 ++++++++++++++++ .../main/scala/aqua/io/OutputPrinter.scala | 14 ++++++ npm/package-lock.json | 25 ++++++++--- npm/package.json | 7 +-- npm/utils.js | 2 + project/plugins.sbt | 4 +- 20 files changed, 240 insertions(+), 106 deletions(-) rename cli/.js/src/main/scala/aqua/{Utils.scala => LogLevelTransformer.scala} (82%) rename cli/.js/src/main/scala/aqua/{ => js}/CallJsFunction.scala (98%) rename cli/.js/src/main/scala/aqua/{JsTypes.scala => js/FluenceJsTypes.scala} (99%) create mode 100644 cli/.js/src/main/scala/aqua/js/Npm.scala create mode 100644 cli/src/main/scala/aqua/Prelude.scala create mode 100644 cli/src/main/scala/aqua/io/OutputPrinter.scala create mode 100644 npm/utils.js diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1f1eea5c..feff4bc1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,12 +22,6 @@ jobs: ### Setup - uses: olafurpg/setup-scala@v10 - ### Update & build - - name: Assembly - run: sbt cli/assembly - env: - BUILD_NUMBER: ${{ github.run_number }} - - name: JS build run: sbt cliJS/fullLinkJS env: @@ -55,12 +49,6 @@ jobs: env: 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 run: | JS="cli/.js/target/scala-3.0.2/cli-opt/aqua-${{ env.VERSION }}.js" @@ -74,7 +62,6 @@ jobs: node-version: "15" registry-url: "https://registry.npmjs.org" - - run: cp ${{ env.JAR }} ./npm/aqua.jar - run: cp ${{ env.JS }} ./npm/aqua.js - run: npm version ${{ env.VERSION }} @@ -118,7 +105,6 @@ jobs: draft: false prerelease: false files: | - ${{ env.JAR }} ${{ env.JS }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/cli/.js/src/main/scala/aqua/Utils.scala b/cli/.js/src/main/scala/aqua/LogLevelTransformer.scala similarity index 82% rename from cli/.js/src/main/scala/aqua/Utils.scala rename to cli/.js/src/main/scala/aqua/LogLevelTransformer.scala index dc7e247b..09623d12 100644 --- a/cli/.js/src/main/scala/aqua/Utils.scala +++ b/cli/.js/src/main/scala/aqua/LogLevelTransformer.scala @@ -1,8 +1,13 @@ package aqua +import aqua.js.{AvmLogLevel, FluenceJSLogLevel, Meta, Module} +import fs2.io.file.Path import scribe.Level -object Utils { +import scala.util.Try + +object LogLevelTransformer { + def logLevelToAvm(logLevel: Level): AvmLogLevel = { logLevel match { case Level.Trace => "trace" diff --git a/cli/.js/src/main/scala/aqua/PlatformOpts.scala b/cli/.js/src/main/scala/aqua/PlatformOpts.scala index bece1f92..9f0eaaa7 100644 --- a/cli/.js/src/main/scala/aqua/PlatformOpts.scala +++ b/cli/.js/src/main/scala/aqua/PlatformOpts.scala @@ -1,18 +1,39 @@ package aqua +import aqua.js.{Meta, Module} import cats.effect.ExitCode import cats.effect.kernel.Async import com.monovore.decline.Opts -import fs2.io.file.Files -import scala.concurrent.ExecutionContext +import fs2.io.file.{Files, Path} +import scala.concurrent.ExecutionContext import aqua.run.RunOpts import aqua.keypair.KeyPairOpts +import scribe.Logging + +import scala.util.Try // JS-specific options and subcommands -object PlatformOpts { - def opts[F[_]: Files: AquaIO: Async](implicit ec: ExecutionContext): Opts[F[ExitCode]] = - Opts.subcommand(RunOpts.runCommand[F]) orElse - Opts.subcommand(KeyPairOpts.createKeypair[F]) -} +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]) + + // 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 + } + + } +} diff --git a/cli/.js/src/main/scala/aqua/CallJsFunction.scala b/cli/.js/src/main/scala/aqua/js/CallJsFunction.scala similarity index 98% rename from cli/.js/src/main/scala/aqua/CallJsFunction.scala rename to cli/.js/src/main/scala/aqua/js/CallJsFunction.scala index 7356476c..70bdafa6 100644 --- a/cli/.js/src/main/scala/aqua/CallJsFunction.scala +++ b/cli/.js/src/main/scala/aqua/js/CallJsFunction.scala @@ -1,4 +1,4 @@ -package aqua +package aqua.js import aqua.backend.{ArgDefinition, FunctionDef, NamesConfig, TypeDefinition} import aqua.model.transform.TransformConfig diff --git a/cli/.js/src/main/scala/aqua/JsTypes.scala b/cli/.js/src/main/scala/aqua/js/FluenceJsTypes.scala similarity index 99% rename from cli/.js/src/main/scala/aqua/JsTypes.scala rename to cli/.js/src/main/scala/aqua/js/FluenceJsTypes.scala index 76f79969..9a9bb5d2 100644 --- a/cli/.js/src/main/scala/aqua/JsTypes.scala +++ b/cli/.js/src/main/scala/aqua/js/FluenceJsTypes.scala @@ -1,5 +1,6 @@ -package aqua +package aqua.js +import aqua.* import aqua.backend.{ArgDefinition, FunctionDef, NamesConfig, TypeDefinition} import scala.concurrent.Promise diff --git a/cli/.js/src/main/scala/aqua/js/Npm.scala b/cli/.js/src/main/scala/aqua/js/Npm.scala new file mode 100644 index 00000000..1610d538 --- /dev/null +++ b/cli/.js/src/main/scala/aqua/js/Npm.scala @@ -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 +} diff --git a/cli/.js/src/main/scala/aqua/keypair/KeyPairOpts.scala b/cli/.js/src/main/scala/aqua/keypair/KeyPairOpts.scala index 80bcc6c1..2f1b80ed 100644 --- a/cli/.js/src/main/scala/aqua/keypair/KeyPairOpts.scala +++ b/cli/.js/src/main/scala/aqua/keypair/KeyPairOpts.scala @@ -1,18 +1,18 @@ package aqua.keypair -import cats.effect.ExitCode -import cats.effect.kernel.{Async} -import cats.Monad -import cats.implicits.catsSyntaxApplicativeId -import cats.Applicative +import aqua.io.OutputPrinter +import aqua.js.KeyPair +import aqua.keypair.KeyPairShow.show 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 scribe.Logging -import scala.concurrent.{ExecutionContext, Future} -import aqua.KeyPair -import KeyPairShow.show +import scala.concurrent.{ExecutionContext, Future} // Options and commands to work with KeyPairs object KeyPairOpts extends Logging { @@ -33,7 +33,7 @@ object KeyPairOpts extends Logging { KeyPair.randomEd25519().toFuture.pure[F] ) .map(keypair => - println(s"${keypair.show}") + OutputPrinter.print(s"${keypair.show}") ExitCode.Success ) ) diff --git a/cli/.js/src/main/scala/aqua/keypair/KeyPairShow.scala b/cli/.js/src/main/scala/aqua/keypair/KeyPairShow.scala index 0999b38e..025b0389 100644 --- a/cli/.js/src/main/scala/aqua/keypair/KeyPairShow.scala +++ b/cli/.js/src/main/scala/aqua/keypair/KeyPairShow.scala @@ -1,19 +1,19 @@ package aqua.keypair -import scala.scalajs.js.JSON -import scala.scalajs.js -import java.util.Base64 - -import aqua.KeyPair +import aqua.js.KeyPair import cats.Show +import java.util.Base64 +import scala.scalajs.js +import scala.scalajs.js.JSON + object KeyPairShow { def stringify(keypair: KeyPair): String = { val encoder = Base64.getEncoder() val kp = js.Dynamic.literal( - peerId = keypair.Libp2pPeerId.toB58String(), - secretKey = encoder.encodeToString(keypair.toEd25519PrivateKey().toArray.map(s => s.toByte)), - publicKey = encoder.encodeToString(keypair.Libp2pPeerId.pubKey.bytes.toArray.map(s => s.toByte)), + peerId = keypair.Libp2pPeerId.toB58String(), + secretKey = encoder.encodeToString(keypair.toEd25519PrivateKey().toArray.map(s => s.toByte)), + publicKey = encoder.encodeToString(keypair.Libp2pPeerId.pubKey.bytes.toArray.map(s => s.toByte)), ) JSON.stringify(kp, space = 4) diff --git a/cli/.js/src/main/scala/aqua/run/RunCommand.scala b/cli/.js/src/main/scala/aqua/run/RunCommand.scala index d8c962e3..e812ca83 100644 --- a/cli/.js/src/main/scala/aqua/run/RunCommand.scala +++ b/cli/.js/src/main/scala/aqua/run/RunCommand.scala @@ -7,7 +7,8 @@ import aqua.backend.ts.TypeScriptBackend import aqua.backend.{FunctionDef, Generated} import aqua.compiler.{AquaCompiled, AquaCompiler} 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.{Call, FuncCallable} import aqua.model.transform.res.{AquaRes, FuncRes} @@ -34,6 +35,7 @@ import scribe.Logging import scala.concurrent.{ExecutionContext, Future, Promise} import scala.scalajs.js +import scala.scalajs.js.Dynamic.global as g import scala.scalajs.js.JSConverters.* import scala.scalajs.js.JSON import scala.scalajs.js.annotation.* @@ -61,7 +63,7 @@ object RunCommand extends Logging { )(implicit ec: ExecutionContext ): F[Unit] = { - FluenceUtils.setLogLevel(Utils.logLevelToFluenceJS(config.logLevel)) + FluenceUtils.setLogLevel(LogLevelTransformer.logLevelToFluenceJS(config.logLevel)) // stops peer in any way at the end of execution val resource = Resource.make(Fluence.getPeer().pure[F]) { peer => @@ -74,10 +76,10 @@ object RunCommand extends Logging { secretKey <- keyPairOrNull(config.secretKey) _ <- Fluence .start( - PeerConfig(multiaddr, config.timeout, Utils.logLevelToAvm(config.logLevel), secretKey) + PeerConfig(multiaddr, config.timeout, LogLevelTransformer.logLevelToAvm(config.logLevel), secretKey) ) .toFuture - _ = println("Your peerId: " + peer.getStatus().peerId) + _ = OutputPrinter.print("Your peerId: " + peer.getStatus().peerId) promise = Promise.apply[Unit]() _ = CallJsFunction.registerUnitService( peer, @@ -88,7 +90,7 @@ object RunCommand extends Logging { // 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 // TODO use custom function for output - println(str) + OutputPrinter.print(str) promise.success(()) } ) @@ -112,7 +114,6 @@ object RunCommand extends Logging { // func wrapFunc(): // res <- funcCallable(args:_*) // Console.print(res) - // TODO: now it supports only one result. If funcCallable will return multiple results, only first will be printed private def wrapCall( funcName: String, 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." } else t.getMessage // 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 val aio: AquaIO[IO] = new AquaFilesIO[IO] - val sources = new AquaFileSources[F](input, imports) - for { + prelude <- Prelude.init() + sources = new AquaFileSources[F](input, prelude.importPaths) // compile only context to wrap and call function later compileResult <- Clock[F].timed( AquaCompiler @@ -204,7 +205,7 @@ object RunCommand extends Logging { val air = FuncAirGen(funcRes).generate.show if (runConfig.printAir) { - println(air) + OutputPrinter.print(air) } funcCall[F](multiaddr, air, definitions, runConfig).map { _ => @@ -223,7 +224,7 @@ object RunCommand extends Logging { logger.debug(s"Call time: ${callTime.toMillis}ms") result.fold( { (errs: NonEmptyChain[String]) => - errs.toChain.toList.foreach(err => println(err + "\n")) + errs.toChain.toList.foreach(err => OutputPrinter.error(err + "\n")) }, identity ) diff --git a/cli/.js/src/main/scala/aqua/run/RunOpts.scala b/cli/.js/src/main/scala/aqua/run/RunOpts.scala index 78cf7ba9..29b25ff2 100644 --- a/cli/.js/src/main/scala/aqua/run/RunOpts.scala +++ b/cli/.js/src/main/scala/aqua/run/RunOpts.scala @@ -13,7 +13,7 @@ import cats.syntax.applicative.* import cats.syntax.apply.* import cats.syntax.flatMap.* import cats.syntax.functor.* -import cats.{Id, Monad, ~>} +import cats.{~>, Id, Monad} import com.monovore.decline.{Command, Opts} import fs2.io.file.Files import scribe.Logging @@ -24,9 +24,10 @@ import scala.concurrent.ExecutionContext object RunOpts extends Logging { val timeoutOpt: Opts[Int] = - Opts.option[Int]("timeout", "Request timeout in milliseconds", "t") + Opts + .option[Int]("timeout", "Request timeout in milliseconds", "t") .withDefault(7000) - + val multiaddrOpt: Opts[String] = Opts .option[String]("addr", "Relay multiaddress", "a") @@ -57,7 +58,6 @@ object RunOpts extends Logging { .map(_ => true) .withDefault(false) - val funcOpt: Opts[(String, List[LiteralModel])] = Opts .option[String]("func", "Function to call with args", "f") @@ -70,7 +70,9 @@ object RunOpts extends Logging { case _ => false } 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 { val args = expr.args.collect { case l @ Literal(_, _) => LiteralModel(l.value, l.ts) @@ -85,9 +87,26 @@ object RunOpts extends Logging { def runOptions[F[_]: Files: AquaIO: Async](implicit ec: ExecutionContext ): 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 .clearHandlers() .clearModifiers() @@ -114,7 +133,14 @@ object RunOpts extends Logging { }, { imps => 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) } ) diff --git a/cli/.jvm/src/main/scala/aqua/PlatformOpts.scala b/cli/.jvm/src/main/scala/aqua/PlatformOpts.scala index e371f4e7..37913881 100644 --- a/cli/.jvm/src/main/scala/aqua/PlatformOpts.scala +++ b/cli/.jvm/src/main/scala/aqua/PlatformOpts.scala @@ -2,8 +2,10 @@ package aqua import cats.effect.ExitCode import com.monovore.decline.Opts +import fs2.io.file.Path // Scala-specific options and subcommands object PlatformOpts { - def opts[F[_]]: Opts[F[ExitCode]] = Opts.never + def opts[F[_]]: Opts[F[ExitCode]] = Opts.never + def getGlobalNodeModulePath: Option[Path] = None } diff --git a/cli/src/main/scala/aqua/AppOpts.scala b/cli/src/main/scala/aqua/AppOpts.scala index edf4e772..363143b0 100644 --- a/cli/src/main/scala/aqua/AppOpts.scala +++ b/cli/src/main/scala/aqua/AppOpts.scala @@ -14,7 +14,7 @@ import cats.syntax.applicative.* import cats.syntax.flatMap.* import cats.syntax.functor.* 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, Visibility} import fs2.io.file.{Files, Path} @@ -92,14 +92,19 @@ object AppOpts { .map(s => checkPath[F](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 not exists", "o") + Opts + .option[String]("output", "Path to the output directory. Will be created if not exists", "o") .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") + .options[String]( + "import", + "Path to the directory to import from. May be used several times", + "m" + ) .orEmpty .map { ps => 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 - 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) - } + checked.sequence.map(_.sequence) } def constantOpts[F[_]: LiftParser: Comonad]: Opts[List[TransformConfig.Const]] = @@ -193,7 +184,10 @@ object AppOpts { val scriptOpt: Opts[Boolean] = 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) .withDefault(false) diff --git a/cli/src/main/scala/aqua/AquaCli.scala b/cli/src/main/scala/aqua/AquaCli.scala index 9e1c4f62..5e6f3001 100644 --- a/cli/src/main/scala/aqua/AquaCli.scala +++ b/cli/src/main/scala/aqua/AquaCli.scala @@ -66,7 +66,7 @@ object AquaCli extends IOApp with Logging { constantOpts[Id], dryOpt, scriptOpt - ).mapN { + ).mapN { case (inputF, importsF, outputF, toAirOp, toJs, noRelayOp, noXorOp, h, v, logLevel, constants, isDryRun, isScheduled) => scribe.Logger.root .clearHandlers() diff --git a/cli/src/main/scala/aqua/AquaPathCompiler.scala b/cli/src/main/scala/aqua/AquaPathCompiler.scala index 553a4949..343f96ba 100644 --- a/cli/src/main/scala/aqua/AquaPathCompiler.scala +++ b/cli/src/main/scala/aqua/AquaPathCompiler.scala @@ -13,8 +13,9 @@ import cats.data.* 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 cats.{~>, Applicative, Eval, Monad, Show} import fs2.io.file.{Files, Path} import scribe.Logging @@ -36,17 +37,22 @@ object AquaPathCompiler extends Logging { transformConfig: TransformConfig ): F[ValidatedNec[String, Chain[String]]] = { import ErrorRendering.showError - val sources = new AquaFileSources[F](srcPath, imports) - AquaCompiler - .compileTo[F, AquaFileError, FileModuleId, FileSpan.F, String]( - sources, - SpanParser.parser, - backend, - transformConfig, - targetPath.map(sources.write).getOrElse(dry[F]) - ) + (for { + prelude <- Prelude.init(withPrelude = false) + sources = new AquaFileSources[F](srcPath, imports ++ prelude.importPaths) + compiler <- AquaCompiler + .compileTo[F, AquaFileError, FileModuleId, FileSpan.F, String]( + sources, + SpanParser.parser, + backend, + transformConfig, + targetPath.map(sources.write).getOrElse(dry[F]) + ) + } yield { + compiler // 'distinct' to delete all duplicated errors - .map(_.leftMap(_.map(_.show).distinct)) + }).map(_.leftMap(_.map(_.show).distinct)) + } def dry[F[_]: Applicative]( diff --git a/cli/src/main/scala/aqua/Prelude.scala b/cli/src/main/scala/aqua/Prelude.scala new file mode 100644 index 00000000..04d7b42a --- /dev/null +++ b/cli/src/main/scala/aqua/Prelude.scala @@ -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) + } + } + +} diff --git a/cli/src/main/scala/aqua/io/OutputPrinter.scala b/cli/src/main/scala/aqua/io/OutputPrinter.scala new file mode 100644 index 00000000..6efd3af6 --- /dev/null +++ b/cli/src/main/scala/aqua/io/OutputPrinter.scala @@ -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) + } +} diff --git a/npm/package-lock.json b/npm/package-lock.json index fe8c629f..67ab03ab 100644 --- a/npm/package-lock.json +++ b/npm/package-lock.json @@ -9,7 +9,8 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@fluencelabs/fluence": "0.15.1" + "@fluencelabs/aqua-lib": "0.2.1", + "@fluencelabs/fluence": "0.15.2" }, "bin": { "aqua": "index.js", @@ -75,6 +76,11 @@ "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", "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": { "version": "0.16.0-restriction-operator.9", "resolved": "https://registry.npmjs.org/@fluencelabs/avm/-/avm-0.16.0-restriction-operator.9.tgz", @@ -84,9 +90,9 @@ } }, "node_modules/@fluencelabs/fluence": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@fluencelabs/fluence/-/fluence-0.15.1.tgz", - "integrity": "sha512-ZHLw85XgVMglCVJjGkdGRFzL7kO2x31BCYDt4BVlMCE/S2nFSsVHU8DO35Jlh40QZhQdN3F5dbJpkgdcwdC8bw==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@fluencelabs/fluence/-/fluence-0.15.2.tgz", + "integrity": "sha512-RWGh70XkqcJusaqB4TR0tVBSVkzlMU9krwALQmgilLTxaSBMPtB6xMt13ceEJ/G6BwsLZWdgY2Wy6GvdSheKaw==", "dependencies": { "@chainsafe/libp2p-noise": "4.0.0", "@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": { "version": "0.16.0-restriction-operator.9", "resolved": "https://registry.npmjs.org/@fluencelabs/avm/-/avm-0.16.0-restriction-operator.9.tgz", @@ -2827,9 +2838,9 @@ } }, "@fluencelabs/fluence": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@fluencelabs/fluence/-/fluence-0.15.1.tgz", - "integrity": "sha512-ZHLw85XgVMglCVJjGkdGRFzL7kO2x31BCYDt4BVlMCE/S2nFSsVHU8DO35Jlh40QZhQdN3F5dbJpkgdcwdC8bw==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@fluencelabs/fluence/-/fluence-0.15.2.tgz", + "integrity": "sha512-RWGh70XkqcJusaqB4TR0tVBSVkzlMU9krwALQmgilLTxaSBMPtB6xMt13ceEJ/G6BwsLZWdgY2Wy6GvdSheKaw==", "requires": { "@chainsafe/libp2p-noise": "4.0.0", "@fluencelabs/avm": "0.16.0-restriction-operator.9", diff --git a/npm/package.json b/npm/package.json index c1dbf335..7b78ffe7 100644 --- a/npm/package.json +++ b/npm/package.json @@ -6,8 +6,8 @@ "files": [ "aqua.js", "index.js", - "index-java.js", - "error.js" + "error.js", + "utils.js" ], "bin": { "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 -- $@" }, "dependencies": { - "@fluencelabs/fluence": "0.15.1" + "@fluencelabs/fluence": "0.15.2", + "@fluencelabs/aqua-lib": "0.2.1" }, "repository": { "type": "git", diff --git a/npm/utils.js b/npm/utils.js new file mode 100644 index 00000000..cf5b14c2 --- /dev/null +++ b/npm/utils.js @@ -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 diff --git a/project/plugins.sbt b/project/plugins.sbt index b0c2426b..1aaafa8b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.0") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.1") addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.1.0") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0")