mirror of
https://github.com/fluencelabs/aqua.git
synced 2024-12-04 14:40:17 +00:00
feat(aqua-api): return JS and TS sources from API [LNG-164] (#730)
This commit is contained in:
parent
21cb3937ac
commit
0b66aa96ec
4
.github/workflows/publish.yml
vendored
4
.github/workflows/publish.yml
vendored
@ -40,7 +40,7 @@ jobs:
|
||||
run: sbt cliJS/fullLinkJS
|
||||
|
||||
- name: JS API build
|
||||
run: sbt aqua-api/fullLinkJS
|
||||
run: sbt aqua-apiJS/fullLinkJS
|
||||
|
||||
- name: JS LSP build
|
||||
run: sbt language-server-apiJS/fullLinkJS
|
||||
@ -55,7 +55,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: aqua-api
|
||||
path: api/aqua-api/target/scala-*/aqua-api-opt/main.js
|
||||
path: api/aqua-api/.js/target/scala-*/aqua-api-opt/main.js
|
||||
|
||||
- name: Upload aqua-lsp artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
|
4
.github/workflows/snapshot.yml
vendored
4
.github/workflows/snapshot.yml
vendored
@ -63,7 +63,7 @@ jobs:
|
||||
- name: JS API build
|
||||
env:
|
||||
SNAPSHOT: ${{ steps.version.outputs.id }}
|
||||
run: sbt aqua-api/fastOptJS
|
||||
run: sbt aqua-apiJS/fastOptJS
|
||||
|
||||
- name: Upload aqua-cli artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
@ -75,7 +75,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: aqua-api
|
||||
path: api/aqua-api/target/scala-*/aqua-api-fastopt.js
|
||||
path: api/aqua-api/.js/target/scala-*/aqua-api-fastopt.js
|
||||
|
||||
- name: Upload aqua-lsp artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
|
10
api/aqua-api-npm/aqua-api.d.ts
vendored
10
api/aqua-api-npm/aqua-api.d.ts
vendored
@ -2,11 +2,13 @@ import type {FunctionCallDef, ServiceDef} from "@fluencelabs/fluence/dist/intern
|
||||
|
||||
export class AquaConfig {
|
||||
constructor(logLevel: string, constants: string[], noXor: boolean, noRelay: boolean);
|
||||
constructor(logLevel: string, constants: string[], noXor: boolean, noRelay: boolean, targetType: string);
|
||||
|
||||
logLevel?: string
|
||||
constants?: string[]
|
||||
noXor?: boolean
|
||||
noRelay?: boolean
|
||||
targetType?: string
|
||||
}
|
||||
|
||||
export class AquaFunction {
|
||||
@ -14,11 +16,19 @@ export class AquaFunction {
|
||||
script: string
|
||||
}
|
||||
|
||||
export class GeneratedSource {
|
||||
name: string
|
||||
tsSource?: string
|
||||
jsSource?: string
|
||||
tsTypes?: string
|
||||
}
|
||||
|
||||
export class CompilationResult {
|
||||
services: Record<string, ServiceDef>
|
||||
functions: Record<string, AquaFunction>
|
||||
functionCall?: AquaFunction
|
||||
errors: string[]
|
||||
generatedSources: GeneratedSource[]
|
||||
}
|
||||
|
||||
export class Input {
|
||||
|
5
api/aqua-api-npm/package-lock.json
generated
5
api/aqua-api-npm/package-lock.json
generated
@ -5247,7 +5247,7 @@
|
||||
"node_modules/node-fetch": {
|
||||
"name": "@achingbrain/node-fetch",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://npm.fluence.dev/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"resolved": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
@ -11491,8 +11491,7 @@
|
||||
"dev": true
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "npm:@achingbrain/node-fetch@2.6.7",
|
||||
"resolved": "https://npm.fluence.dev/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"version": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g==",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -9,8 +9,8 @@
|
||||
"meta-utils.js"
|
||||
],
|
||||
"scripts": {
|
||||
"move:scalajs": "cp ../aqua-api/target/scala-3.1.3/aqua-api-opt/main.js ./aqua-api.js",
|
||||
"move:fast": "cp ../aqua-api/target/scala-3.1.3/aqua-api-fastopt/main.js ./aqua-api.js"
|
||||
"move:scalajs": "cp ../aqua-api/.js/target/scala-3.3.0/aqua-api-opt/main.js ./aqua-api.js",
|
||||
"move:fast": "cp ../aqua-api/.js/target/scala-3.3.0/aqua-api-fastopt/main.js ./aqua-api.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
229
api/aqua-api/.js/src/main/scala/api/AquaAPI.scala
Normal file
229
api/aqua-api/.js/src/main/scala/api/AquaAPI.scala
Normal file
@ -0,0 +1,229 @@
|
||||
package api
|
||||
|
||||
import api.types.{AquaConfig, AquaFunction, CompilationResult, GeneratedSource, Input}
|
||||
import aqua.ErrorRendering.showError
|
||||
import aqua.raw.value.ValueRaw
|
||||
import aqua.api.{APICompilation, AquaAPIConfig}
|
||||
import aqua.api.TargetType.*
|
||||
import aqua.backend.air.AirBackend
|
||||
import aqua.backend.{AirFunction, Backend, Generated}
|
||||
import aqua.compiler.*
|
||||
import aqua.files.{AquaFileSources, AquaFilesIO, FileModuleId}
|
||||
import aqua.logging.{LogFormatter, LogLevels}
|
||||
import aqua.constants.Constants
|
||||
import aqua.io.*
|
||||
import aqua.raw.ops.Call
|
||||
import aqua.run.{CallInfo, CallPreparer, CliFunc, FuncCompiler, RunPreparer}
|
||||
import aqua.parser.lexer.{LiteralToken, Token}
|
||||
import aqua.parser.lift.FileSpan.F
|
||||
import aqua.parser.lift.{FileSpan, Span}
|
||||
import aqua.parser.{ArrowReturnError, BlockIndentError, LexerError, ParserError}
|
||||
import aqua.semantics.{CompilerState, HeaderError, RulesViolated, WrongAST}
|
||||
import aqua.{AquaIO, SpanParser}
|
||||
import aqua.model.transform.{Transform, TransformConfig}
|
||||
import aqua.backend.api.APIBackend
|
||||
import aqua.backend.js.JavaScriptBackend
|
||||
import aqua.backend.ts.TypeScriptBackend
|
||||
import aqua.definitions.FunctionDef
|
||||
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
|
||||
import cats.data.Validated.{invalidNec, validNec, Invalid, Valid}
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.apply.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.effect.IO
|
||||
import cats.effect.unsafe.implicits.global
|
||||
import cats.syntax.show.*
|
||||
import cats.syntax.traverse.*
|
||||
import fs2.io.file.{Files, Path}
|
||||
import scribe.Logging
|
||||
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.Future
|
||||
import scala.scalajs.js.{|, undefined, Promise, UndefOr}
|
||||
import scala.scalajs.js
|
||||
import scala.scalajs.js.JSConverters.*
|
||||
import scala.scalajs.js.annotation.*
|
||||
import aqua.js.{FunctionDefJs, ServiceDefJs, VarJson}
|
||||
import aqua.model.AquaContext
|
||||
import aqua.raw.ops.CallArrowRawTag
|
||||
import aqua.raw.value.{LiteralRaw, VarRaw}
|
||||
import aqua.res.AquaRes
|
||||
import cats.Applicative
|
||||
|
||||
@JSExportTopLevel("Aqua")
|
||||
object AquaAPI extends App with Logging {
|
||||
|
||||
/**
|
||||
* All-in-one function that support different inputs and backends
|
||||
* @param input can be a path to aqua file, string with a code or a function call
|
||||
* @param imports list of paths
|
||||
* @param aquaConfigJS compiler config
|
||||
* @return compiler results depends on input and config
|
||||
*/
|
||||
@JSExport
|
||||
def compile(
|
||||
input: types.Input | types.Path | types.Call,
|
||||
imports: js.Array[String],
|
||||
aquaConfigJS: js.UndefOr[AquaConfig]
|
||||
): Promise[CompilationResult] = {
|
||||
aquaConfigJS.toOption
|
||||
.map(cjs => AquaConfig.fromJS(cjs))
|
||||
.getOrElse(
|
||||
validNec(AquaAPIConfig())
|
||||
).map { config =>
|
||||
val importsList = imports.toList
|
||||
|
||||
input match {
|
||||
case i: (types.Input | types.Path) =>
|
||||
compileAll(i, importsList, config)
|
||||
case c: types.Call =>
|
||||
compileCall(c, importsList, config)
|
||||
|
||||
}
|
||||
} match {
|
||||
case Valid(v) => v.unsafeToFuture().toJSPromise
|
||||
case Invalid(errs) => js.Promise.resolve(CompilationResult.errs(errs.toChain.toList))
|
||||
}
|
||||
}
|
||||
|
||||
// Compile all non-call inputs
|
||||
private def compileAll(
|
||||
input: types.Input | types.Path,
|
||||
imports: List[String],
|
||||
config: AquaAPIConfig
|
||||
): IO[CompilationResult] = {
|
||||
val backend: Backend = config.targetType match {
|
||||
case AirType => APIBackend
|
||||
case TypeScriptType => TypeScriptBackend()
|
||||
case JavaScriptType => JavaScriptBackend()
|
||||
}
|
||||
|
||||
extension (res: IO[ValidatedNec[String, Chain[AquaCompiled[FileModuleId]]]])
|
||||
def toResult: IO[CompilationResult] = res.map(
|
||||
_.andThen { compiled =>
|
||||
config.targetType match {
|
||||
case AirType => validNec(generatedToAirResult(compiled))
|
||||
case TypeScriptType => compiledToTsSourceResult(compiled)
|
||||
case JavaScriptType => compiledToJsSourceResult(compiled)
|
||||
}
|
||||
}.leftMap(errorsToResult).merge
|
||||
)
|
||||
|
||||
input match {
|
||||
case i: types.Input =>
|
||||
APICompilation
|
||||
.compileString(
|
||||
i.input,
|
||||
imports,
|
||||
config,
|
||||
backend
|
||||
)
|
||||
.toResult
|
||||
case p: types.Path =>
|
||||
APICompilation
|
||||
.compilePath(
|
||||
p.path,
|
||||
imports,
|
||||
config,
|
||||
backend
|
||||
)
|
||||
.toResult
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private def compileCall(call: types.Call, imports: List[String], config: AquaAPIConfig) = {
|
||||
val path = call.input match {
|
||||
case i: types.Input => i.input
|
||||
case p: types.Path => p.path
|
||||
}
|
||||
|
||||
extension (res: IO[ValidatedNec[String, (FunctionDef, String)]])
|
||||
def callToResult: IO[CompilationResult] = res.map(
|
||||
_.map { case (definitions, air) =>
|
||||
CompilationResult.result(call = Some(AquaFunction(FunctionDefJs(definitions), air)))
|
||||
}.leftMap(errorsToResult).merge
|
||||
)
|
||||
|
||||
APICompilation
|
||||
.compileCall(
|
||||
call.functionCall,
|
||||
path,
|
||||
imports,
|
||||
config,
|
||||
vr => VarJson.checkDataGetServices(vr, Some(call.arguments)).map(_._1)
|
||||
)
|
||||
.callToResult
|
||||
}
|
||||
|
||||
private def errorsToResult(errors: NonEmptyChain[String]): CompilationResult = {
|
||||
CompilationResult.errs(errors.toChain.toList)
|
||||
}
|
||||
|
||||
private def findBySuffix(
|
||||
compiled: Seq[Generated],
|
||||
suffix: String,
|
||||
errorMsg: String
|
||||
): ValidatedNec[String, String] = {
|
||||
Validated
|
||||
.fromOption(
|
||||
compiled.find(_.suffix == suffix).map(_.content), {
|
||||
logger.error(errorMsg)
|
||||
NonEmptyChain.one(errorMsg)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
extension (res: Chain[Validated[NonEmptyChain[String], GeneratedSource]])
|
||||
def toSourcesResult: ValidatedNec[String, CompilationResult] =
|
||||
res.sequence.map(_.toList.toJSArray).map(sources => CompilationResult.result(sources = sources))
|
||||
|
||||
private def compiledToTsSourceResult(
|
||||
compiled: Chain[AquaCompiled[FileModuleId]]
|
||||
): ValidatedNec[String, CompilationResult] = {
|
||||
compiled.map { c =>
|
||||
findBySuffix(
|
||||
c.compiled,
|
||||
TypeScriptBackend.ext,
|
||||
"Unreachable. TypeScript backend must generate content."
|
||||
)
|
||||
.map(GeneratedSource.tsSource(c.sourceId.toString, _))
|
||||
}.toSourcesResult
|
||||
}
|
||||
|
||||
private def compiledToJsSourceResult(
|
||||
compiled: Chain[AquaCompiled[FileModuleId]]
|
||||
): ValidatedNec[String, CompilationResult] = {
|
||||
compiled.map { c =>
|
||||
findBySuffix(
|
||||
c.compiled,
|
||||
JavaScriptBackend.dtsExt,
|
||||
"Unreachable. JavaScript backend must generate '.d.ts' content."
|
||||
).andThen { tsTypes =>
|
||||
findBySuffix(
|
||||
c.compiled,
|
||||
JavaScriptBackend.ext,
|
||||
"Unreachable. JavaScript backend must generate '.js' content."
|
||||
).map(jsSource => GeneratedSource.jsSource(c.sourceId.toString, jsSource, tsTypes))
|
||||
}
|
||||
|
||||
}.toSourcesResult
|
||||
}
|
||||
|
||||
private def generatedToAirResult(
|
||||
compiled: Chain[AquaCompiled[FileModuleId]]
|
||||
): CompilationResult = {
|
||||
val generated = compiled.toList.flatMap(_.compiled)
|
||||
val serviceDefs = generated.flatMap(_.services).map(s => s.name -> ServiceDefJs(s))
|
||||
val functions = generated.flatMap(
|
||||
_.air.map(as => (as.name, AquaFunction(FunctionDefJs(as.funcDef), as.air)))
|
||||
)
|
||||
|
||||
CompilationResult.result(
|
||||
js.Dictionary.apply(serviceDefs: _*),
|
||||
js.Dictionary.apply(functions: _*)
|
||||
)
|
||||
|
||||
}
|
||||
}
|
73
api/aqua-api/.js/src/main/scala/api/types/InputTypes.scala
Normal file
73
api/aqua-api/.js/src/main/scala/api/types/InputTypes.scala
Normal file
@ -0,0 +1,73 @@
|
||||
package api.types
|
||||
|
||||
import aqua.api.AquaAPIConfig
|
||||
import aqua.api.TargetType.*
|
||||
import aqua.js.{FunctionDefJs, ServiceDefJs}
|
||||
import aqua.model.transform.TransformConfig
|
||||
import cats.data.Validated.{Invalid, Valid, invalidNec, validNec}
|
||||
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
|
||||
|
||||
import scala.scalajs.js
|
||||
import scala.scalajs.js.JSConverters.*
|
||||
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
|
||||
import scala.scalajs.js.|
|
||||
|
||||
@JSExportTopLevel("Input")
|
||||
class Input(
|
||||
@JSExport
|
||||
val input: String
|
||||
)
|
||||
|
||||
@JSExportTopLevel("Path")
|
||||
class Path(
|
||||
@JSExport
|
||||
val path: String
|
||||
)
|
||||
|
||||
@JSExportTopLevel("Call")
|
||||
class Call(
|
||||
@JSExport
|
||||
val functionCall: String,
|
||||
@JSExport
|
||||
val arguments: js.Dynamic,
|
||||
@JSExport
|
||||
val input: Path | Input
|
||||
)
|
||||
|
||||
@JSExportTopLevel("AquaConfig")
|
||||
class AquaConfig(
|
||||
@JSExport
|
||||
val logLevel: js.UndefOr[String],
|
||||
@JSExport
|
||||
val constants: js.UndefOr[js.Array[String]],
|
||||
@JSExport
|
||||
val noXor: js.UndefOr[Boolean],
|
||||
@JSExport
|
||||
val noRelay: js.UndefOr[Boolean],
|
||||
@JSExport
|
||||
val targetType: js.UndefOr[String]
|
||||
)
|
||||
|
||||
object AquaConfig {
|
||||
|
||||
def fromJS(cjs: AquaConfig): ValidatedNec[String, AquaAPIConfig] = {
|
||||
cjs.targetType.toOption
|
||||
.map(_.toLowerCase())
|
||||
.map {
|
||||
case "typescript" => validNec(TypeScriptType)
|
||||
case "javascript" => validNec(JavaScriptType)
|
||||
case "air" => validNec(AirType)
|
||||
case _ => invalidNec("Target can be only 'typescript', 'javascript', or 'air'")
|
||||
}
|
||||
.getOrElse(validNec(AirType))
|
||||
.map { target =>
|
||||
AquaAPIConfig(
|
||||
target,
|
||||
cjs.logLevel.getOrElse("info"),
|
||||
cjs.constants.map(_.toList).getOrElse(Nil),
|
||||
cjs.noXor.getOrElse(false),
|
||||
cjs.noRelay.getOrElse(false)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
66
api/aqua-api/.js/src/main/scala/api/types/OutputTypes.scala
Normal file
66
api/aqua-api/.js/src/main/scala/api/types/OutputTypes.scala
Normal file
@ -0,0 +1,66 @@
|
||||
package api.types
|
||||
|
||||
import aqua.js.{FunctionDefJs, ServiceDefJs}
|
||||
import aqua.model.transform.TransformConfig
|
||||
import cats.data.Validated.{Invalid, Valid, invalidNec, validNec}
|
||||
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
|
||||
|
||||
import scala.scalajs.js
|
||||
import scala.scalajs.js.JSConverters.*
|
||||
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
|
||||
import scala.scalajs.js.|
|
||||
|
||||
@JSExportTopLevel("AquaFunction")
|
||||
case class AquaFunction(
|
||||
@JSExport
|
||||
funcDef: FunctionDefJs,
|
||||
@JSExport
|
||||
script: String
|
||||
)
|
||||
|
||||
@JSExportTopLevel("GeneratedSource")
|
||||
case class GeneratedSource(
|
||||
@JSExport
|
||||
val name: String,
|
||||
@JSExport
|
||||
val tsSource: js.UndefOr[String],
|
||||
@JSExport
|
||||
val jsSource: js.UndefOr[String],
|
||||
@JSExport
|
||||
val tsTypes: js.UndefOr[String]
|
||||
)
|
||||
|
||||
object GeneratedSource {
|
||||
def tsSource(name: String, tsSource: String) = new GeneratedSource(name, tsSource, null, null)
|
||||
def jsSource(name: String, jsSource: String, tsTypes: String) = new GeneratedSource(name, null, jsSource, tsTypes)
|
||||
}
|
||||
|
||||
@JSExportTopLevel("CompilationResult")
|
||||
class CompilationResult(
|
||||
@JSExport
|
||||
val services: js.Dictionary[ServiceDefJs],
|
||||
@JSExport
|
||||
val functions: js.Dictionary[AquaFunction],
|
||||
@JSExport
|
||||
val functionCall: js.UndefOr[AquaFunction],
|
||||
@JSExport
|
||||
val generatedSources: js.Array[GeneratedSource],
|
||||
@JSExport
|
||||
val errors: js.Array[String]
|
||||
)
|
||||
|
||||
object CompilationResult {
|
||||
|
||||
def result(
|
||||
services: js.Dictionary[ServiceDefJs] = js.Dictionary(),
|
||||
functions: js.Dictionary[AquaFunction] = js.Dictionary(),
|
||||
call: Option[AquaFunction] = None,
|
||||
sources: js.Array[GeneratedSource] = js.Array()
|
||||
): CompilationResult =
|
||||
new CompilationResult(services, functions, call.orNull, sources, js.Array())
|
||||
|
||||
def errs(
|
||||
errors: List[String]
|
||||
): CompilationResult =
|
||||
CompilationResult(js.Dictionary(), js.Dictionary(), null, null, errors.toJSArray)
|
||||
}
|
18
api/aqua-api/.jvm/src/main/scala/aqua/api/Test.scala
Normal file
18
api/aqua-api/.jvm/src/main/scala/aqua/api/Test.scala
Normal file
@ -0,0 +1,18 @@
|
||||
package aqua.api
|
||||
import cats.effect.{IO, IOApp}
|
||||
import aqua.backend.js.JavaScriptBackend
|
||||
import aqua.backend.ts.TypeScriptBackend
|
||||
import aqua.api.TargetType.JavaScriptType
|
||||
|
||||
object Test extends IOApp.Simple {
|
||||
override def run: IO[Unit] = {
|
||||
val input =
|
||||
"""func getNumber(number: u32) -> u32:
|
||||
| <- number
|
||||
|""".stripMargin
|
||||
APICompilation.compileString(input, Nil, AquaAPIConfig(targetType = JavaScriptType), JavaScriptBackend()).map {
|
||||
res =>
|
||||
println(res)
|
||||
}
|
||||
}
|
||||
}
|
164
api/aqua-api/src/main/scala/aqua/api/APICompilation.scala
Normal file
164
api/aqua-api/src/main/scala/aqua/api/APICompilation.scala
Normal file
@ -0,0 +1,164 @@
|
||||
package aqua.api
|
||||
|
||||
import aqua.ErrorRendering.showError
|
||||
import aqua.raw.value.ValueRaw
|
||||
import aqua.api.AquaAPIConfig
|
||||
import aqua.backend.{AirFunction, Backend, Generated}
|
||||
import aqua.compiler.*
|
||||
import aqua.files.{AquaFileSources, AquaFilesIO, FileModuleId}
|
||||
import aqua.logging.{LogFormatter, LogLevels}
|
||||
import aqua.constants.Constants
|
||||
import aqua.io.*
|
||||
import aqua.raw.ops.Call
|
||||
import aqua.run.{CallInfo, CallPreparer, CliFunc, FuncCompiler, RunPreparer}
|
||||
import aqua.parser.lexer.{LiteralToken, Token}
|
||||
import aqua.parser.lift.FileSpan.F
|
||||
import aqua.parser.lift.{FileSpan, Span}
|
||||
import aqua.parser.{ArrowReturnError, BlockIndentError, LexerError, ParserError}
|
||||
import aqua.semantics.{CompilerState, HeaderError, RulesViolated, WrongAST}
|
||||
import aqua.{AquaIO, SpanParser}
|
||||
import aqua.model.transform.{Transform, TransformConfig}
|
||||
import aqua.backend.api.APIBackend
|
||||
import aqua.definitions.FunctionDef
|
||||
import aqua.model.AquaContext
|
||||
import aqua.res.AquaRes
|
||||
import cats.Applicative
|
||||
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
|
||||
import cats.data.Validated.{Invalid, Valid, invalid, invalidNec, validNec}
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.apply.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.effect.IO
|
||||
import cats.effect.unsafe.implicits.global
|
||||
import cats.syntax.show.*
|
||||
import cats.syntax.traverse.*
|
||||
import fs2.io.file.{Files, Path}
|
||||
import scribe.Logging
|
||||
|
||||
object APICompilation {
|
||||
|
||||
def compileCall(
|
||||
functionStr: String,
|
||||
pathStr: String,
|
||||
imports: List[String],
|
||||
aquaConfig: AquaAPIConfig,
|
||||
fillWithTypes: List[ValueRaw] => ValidatedNec[String, List[ValueRaw]]
|
||||
): IO[ValidatedNec[String, (FunctionDef, String)]] = {
|
||||
implicit val aio: AquaIO[IO] = new AquaFilesIO[IO]
|
||||
(
|
||||
LogLevels.levelFromString(aquaConfig.logLevel),
|
||||
Constants.parse(aquaConfig.constants)
|
||||
).mapN { (level, constants) =>
|
||||
|
||||
val transformConfig = aquaConfig.getTransformConfig.copy(constants = constants)
|
||||
|
||||
LogFormatter.initLogger(Some(level))
|
||||
|
||||
new FuncCompiler[IO](
|
||||
Some(RelativePath(Path(pathStr))),
|
||||
imports.map(Path.apply),
|
||||
transformConfig
|
||||
).compile().map { contextV =>
|
||||
contextV.andThen { context =>
|
||||
CliFunc
|
||||
.fromString(functionStr)
|
||||
.leftMap(errs => NonEmptyChain.fromNonEmptyList(errs))
|
||||
.andThen { cliFunc =>
|
||||
FuncCompiler.findFunction(context, cliFunc).andThen { arrow =>
|
||||
fillWithTypes(cliFunc.args).andThen { argsWithTypes =>
|
||||
val func = cliFunc.copy(args = argsWithTypes)
|
||||
val preparer = new RunPreparer(
|
||||
func,
|
||||
arrow,
|
||||
transformConfig
|
||||
)
|
||||
preparer.prepare().map { ci =>
|
||||
(ci.definitions, ci.air)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.leftMap(_.map(_.show).distinct)
|
||||
|
||||
}
|
||||
} match {
|
||||
case Valid(pr) => pr
|
||||
case Invalid(errs) => IO.pure(Invalid(NonEmptyChain.fromNonEmptyList(errs)))
|
||||
}
|
||||
}
|
||||
|
||||
def compilePath(
|
||||
pathStr: String,
|
||||
imports: List[String],
|
||||
aquaConfig: AquaAPIConfig,
|
||||
backend: Backend
|
||||
): IO[ValidatedNec[String, Chain[AquaCompiled[FileModuleId]]]] = {
|
||||
implicit val aio: AquaIO[IO] = new AquaFilesIO[IO]
|
||||
val path = Path(pathStr)
|
||||
val sources = new AquaFileSources[IO](path, imports.map(Path.apply))
|
||||
compileRaw(
|
||||
aquaConfig,
|
||||
sources,
|
||||
backend
|
||||
)
|
||||
}
|
||||
|
||||
def compileString(
|
||||
input: String,
|
||||
imports: List[String],
|
||||
aquaConfig: AquaAPIConfig,
|
||||
backend: Backend
|
||||
): IO[ValidatedNec[String, Chain[AquaCompiled[FileModuleId]]]] = {
|
||||
implicit val aio: AquaIO[IO] = new AquaFilesIO[IO]
|
||||
val path = Path("")
|
||||
|
||||
val strSources: AquaFileSources[IO] =
|
||||
new AquaFileSources[IO](path, imports.map(Path.apply)) {
|
||||
override def sources: IO[ValidatedNec[AquaFileError, Chain[(FileModuleId, String)]]] = {
|
||||
IO.pure(Valid(Chain.one((FileModuleId(path), input))))
|
||||
}
|
||||
}
|
||||
compileRaw(
|
||||
aquaConfig,
|
||||
strSources,
|
||||
backend
|
||||
)
|
||||
}
|
||||
|
||||
private def compileRaw(
|
||||
aquaConfig: AquaAPIConfig,
|
||||
sources: AquaSources[IO, AquaFileError, FileModuleId],
|
||||
backend: Backend
|
||||
): IO[ValidatedNec[String, Chain[AquaCompiled[FileModuleId]]]] = {
|
||||
|
||||
(
|
||||
LogLevels.levelFromString(aquaConfig.logLevel),
|
||||
Constants.parse(aquaConfig.constants)
|
||||
).traverseN { (level, constants) =>
|
||||
|
||||
LogFormatter.initLogger(Some(level))
|
||||
|
||||
val config = AquaCompilerConf(constants)
|
||||
val transformConfig = aquaConfig.getTransformConfig
|
||||
|
||||
CompilerAPI
|
||||
.compile[IO, AquaFileError, FileModuleId, FileSpan.F](
|
||||
sources,
|
||||
SpanParser.parser,
|
||||
new AirValidator[IO] {
|
||||
override def init(): IO[Unit] = Applicative[IO].pure(())
|
||||
override def validate(airs: List[AirFunction]): IO[ValidatedNec[String, Unit]] =
|
||||
Applicative[IO].pure(validNec(()))
|
||||
},
|
||||
new Backend.Transform:
|
||||
override def transform(ex: AquaContext): AquaRes =
|
||||
Transform.contextRes(ex, transformConfig)
|
||||
|
||||
override def generate(aqua: AquaRes): Seq[Generated] = backend.generate(aqua)
|
||||
,
|
||||
config
|
||||
).map(_.leftMap(_.map(_.show).distinct))
|
||||
}.map(_.leftMap(NonEmptyChain.fromNonEmptyList).andThen(identity))
|
||||
}
|
||||
}
|
@ -1,233 +0,0 @@
|
||||
package aqua.api
|
||||
|
||||
import aqua.ErrorRendering.showError
|
||||
import aqua.api.types.{AquaAPIConfig, AquaConfig, AquaFunction, CompilationResult, Input}
|
||||
import aqua.backend.{AirFunction, Backend, Generated}
|
||||
import aqua.compiler.*
|
||||
import aqua.files.{AquaFileSources, AquaFilesIO, FileModuleId}
|
||||
import aqua.logging.{LogFormatter, LogLevels}
|
||||
import aqua.constants.Constants
|
||||
import aqua.io.*
|
||||
import aqua.raw.ops.Call
|
||||
import aqua.run.{CallInfo, CallPreparer, CliFunc, FuncCompiler, RunPreparer}
|
||||
import aqua.parser.lexer.{LiteralToken, Token}
|
||||
import aqua.parser.lift.FileSpan.F
|
||||
import aqua.parser.lift.{FileSpan, Span}
|
||||
import aqua.parser.{ArrowReturnError, BlockIndentError, LexerError, ParserError}
|
||||
import aqua.semantics.{CompilerState, HeaderError, RulesViolated, WrongAST}
|
||||
import aqua.{AquaIO, SpanParser}
|
||||
import aqua.model.transform.{Transform, TransformConfig}
|
||||
import aqua.backend.api.APIBackend
|
||||
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
|
||||
import cats.data.Validated.{Invalid, Valid, invalidNec, validNec}
|
||||
import cats.syntax.applicative.*
|
||||
import cats.syntax.apply.*
|
||||
import cats.syntax.flatMap.*
|
||||
import cats.syntax.functor.*
|
||||
import cats.effect.IO
|
||||
import cats.effect.unsafe.implicits.global
|
||||
import cats.syntax.show.*
|
||||
import cats.syntax.traverse.*
|
||||
import fs2.io.file.{Files, Path}
|
||||
import scribe.Logging
|
||||
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.Future
|
||||
import scala.scalajs.js.|
|
||||
import scala.scalajs.js
|
||||
import scala.scalajs.js.JSConverters.*
|
||||
import scala.scalajs.js.annotation.*
|
||||
import scala.scalajs.js.{UndefOr, undefined}
|
||||
import aqua.js.{FunctionDefJs, ServiceDefJs, VarJson}
|
||||
import aqua.model.AquaContext
|
||||
import aqua.raw.ops.CallArrowRawTag
|
||||
import aqua.raw.value.{LiteralRaw, VarRaw}
|
||||
import aqua.res.AquaRes
|
||||
import cats.Applicative
|
||||
|
||||
@JSExportTopLevel("Aqua")
|
||||
object AquaAPI extends App with Logging {
|
||||
|
||||
def getTag(serviceId: String, value: VarRaw) = {
|
||||
CallArrowRawTag.service(
|
||||
LiteralRaw.quote(serviceId),
|
||||
value.name,
|
||||
Call(List.empty, List(Call.Export(value.name, value.baseType)))
|
||||
)
|
||||
}
|
||||
|
||||
@JSExport
|
||||
def compile(
|
||||
input: types.Input | types.Path | types.Call,
|
||||
imports: js.Array[String],
|
||||
aquaConfigJS: js.UndefOr[AquaConfig]
|
||||
) = {
|
||||
val aquaConfig: AquaAPIConfig =
|
||||
aquaConfigJS.toOption.map(cjs => AquaAPIConfig.fromJS(cjs)).getOrElse(AquaAPIConfig())
|
||||
|
||||
val importsList = imports.toList
|
||||
|
||||
input match {
|
||||
case i: types.Input => compileString(i.input, importsList, aquaConfig)
|
||||
case p: types.Path => compilePath(p.path, importsList, aquaConfig)
|
||||
case c: types.Call =>
|
||||
val path = c.input match {
|
||||
case i: types.Input => i.input
|
||||
case p: types.Path => p.path
|
||||
}
|
||||
compileCall(c.functionCall, c.arguments, path, importsList, aquaConfig)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
def compileCall(
|
||||
functionStr: String,
|
||||
arguments: js.Dynamic,
|
||||
pathStr: String,
|
||||
imports: List[String],
|
||||
aquaConfig: AquaAPIConfig
|
||||
): js.Promise[CompilationResult] = {
|
||||
implicit val aio: AquaIO[IO] = new AquaFilesIO[IO]
|
||||
(
|
||||
LogLevels.levelFromString(aquaConfig.logLevel),
|
||||
Constants.parse(aquaConfig.constants)
|
||||
).mapN { (level, constants) =>
|
||||
|
||||
val transformConfig = aquaConfig.getTransformConfig.copy(constants = constants)
|
||||
|
||||
LogFormatter.initLogger(Some(level))
|
||||
|
||||
new FuncCompiler[IO](
|
||||
Some(RelativePath(Path(pathStr))),
|
||||
imports.map(Path.apply),
|
||||
transformConfig
|
||||
).compile()
|
||||
.map { contextV =>
|
||||
contextV.andThen { context =>
|
||||
CliFunc
|
||||
.fromString(functionStr)
|
||||
.leftMap(errs => NonEmptyChain.fromNonEmptyList(errs))
|
||||
.andThen { cliFunc =>
|
||||
FuncCompiler.findFunction(context, cliFunc).andThen { arrow =>
|
||||
VarJson.checkDataGetServices(cliFunc.args, Some(arguments)).andThen {
|
||||
case (argsWithTypes, _) =>
|
||||
val func = cliFunc.copy(args = argsWithTypes)
|
||||
val preparer = new RunPreparer(
|
||||
func,
|
||||
arrow,
|
||||
transformConfig
|
||||
)
|
||||
preparer.prepare().map { ci =>
|
||||
AquaFunction(FunctionDefJs(ci.definitions), ci.air)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.flatMap {
|
||||
case Valid(result) => IO.pure(CompilationResult.result(js.Dictionary(), js.Dictionary(), Some(result)))
|
||||
case Invalid(err) =>
|
||||
val errs = err.map(_.show).distinct.toChain.toList
|
||||
IO.pure(CompilationResult.errs(errs))
|
||||
}
|
||||
.unsafeToFuture()
|
||||
.toJSPromise
|
||||
} match {
|
||||
case Valid(pr) => pr
|
||||
case Invalid(err) => js.Promise.resolve(CompilationResult.errs(err.toList))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def compilePath(
|
||||
pathStr: String,
|
||||
imports: List[String],
|
||||
aquaConfig: AquaAPIConfig
|
||||
): js.Promise[CompilationResult] = {
|
||||
implicit val aio: AquaIO[IO] = new AquaFilesIO[IO]
|
||||
val path = Path(pathStr)
|
||||
val sources = new AquaFileSources[IO](path, imports.map(Path.apply))
|
||||
compileRaw(aquaConfig, sources)
|
||||
}
|
||||
|
||||
def compileString(
|
||||
input: String,
|
||||
imports: List[String],
|
||||
aquaConfig: AquaAPIConfig
|
||||
): js.Promise[CompilationResult] = {
|
||||
implicit val aio: AquaIO[IO] = new AquaFilesIO[IO]
|
||||
val path = Path("")
|
||||
|
||||
val strSources: AquaFileSources[IO] =
|
||||
new AquaFileSources[IO](path, imports.map(Path.apply)) {
|
||||
override def sources: IO[ValidatedNec[AquaFileError, Chain[(FileModuleId, String)]]] = {
|
||||
IO.pure(Valid(Chain.one((FileModuleId(path), input))))
|
||||
}
|
||||
}
|
||||
compileRaw(aquaConfig, strSources)
|
||||
}
|
||||
|
||||
def compileRaw(
|
||||
aquaConfig: AquaAPIConfig,
|
||||
sources: AquaSources[IO, AquaFileError, FileModuleId]
|
||||
): js.Promise[CompilationResult] = {
|
||||
|
||||
(
|
||||
LogLevels.levelFromString(aquaConfig.logLevel),
|
||||
Constants.parse(aquaConfig.constants)
|
||||
).mapN { (level, constants) =>
|
||||
|
||||
LogFormatter.initLogger(Some(level))
|
||||
|
||||
val config = AquaCompilerConf(constants)
|
||||
val transformConfig = aquaConfig.getTransformConfig
|
||||
|
||||
val proc = for {
|
||||
res <- CompilerAPI
|
||||
.compile[IO, AquaFileError, FileModuleId, FileSpan.F](
|
||||
sources,
|
||||
SpanParser.parser,
|
||||
new AirValidator[IO] {
|
||||
override def init(): IO[Unit] = Applicative[IO].pure(())
|
||||
override def validate(airs: List[AirFunction]): IO[ValidatedNec[String, Unit]] =
|
||||
Applicative[IO].pure(validNec(()))
|
||||
},
|
||||
new Backend.Transform:
|
||||
override def transform(ex: AquaContext): AquaRes =
|
||||
Transform.contextRes(ex, transformConfig)
|
||||
|
||||
override def generate(aqua: AquaRes): Seq[Generated] = APIBackend.generate(aqua)
|
||||
,
|
||||
config
|
||||
)
|
||||
jsResult <- res match {
|
||||
case Valid(compiled) =>
|
||||
val allGenerated: List[Generated] = compiled.toList.flatMap(_.compiled)
|
||||
val serviceDefs = allGenerated.flatMap(_.services).map(s => s.name -> ServiceDefJs(s))
|
||||
val functions = allGenerated.flatMap(
|
||||
_.air.map(as => (as.name, AquaFunction(FunctionDefJs(as.funcDef), as.air)))
|
||||
)
|
||||
|
||||
IO.pure(
|
||||
CompilationResult.result(
|
||||
js.Dictionary.apply(serviceDefs: _*),
|
||||
js.Dictionary.apply(functions: _*),
|
||||
None
|
||||
)
|
||||
)
|
||||
case Invalid(errChain) =>
|
||||
val errors = errChain.map(_.show).distinct.toChain.toList
|
||||
IO.pure[CompilationResult](CompilationResult.errs(errors))
|
||||
}
|
||||
} yield {
|
||||
jsResult
|
||||
}
|
||||
|
||||
proc.unsafeToFuture().toJSPromise
|
||||
} match {
|
||||
case Valid(pr) => pr
|
||||
case Invalid(err) => js.Promise.resolve(CompilationResult.errs(err.toList))
|
||||
}
|
||||
}
|
||||
}
|
18
api/aqua-api/src/main/scala/aqua/api/AquaAPIConfig.scala
Normal file
18
api/aqua-api/src/main/scala/aqua/api/AquaAPIConfig.scala
Normal file
@ -0,0 +1,18 @@
|
||||
package aqua.api
|
||||
import aqua.model.transform.TransformConfig
|
||||
|
||||
enum TargetType:
|
||||
case TypeScriptType, JavaScriptType, AirType
|
||||
|
||||
case class AquaAPIConfig(
|
||||
targetType: TargetType = TargetType.AirType,
|
||||
logLevel: String = "info",
|
||||
constants: List[String] = Nil,
|
||||
noXor: Boolean = false,
|
||||
noRelay: Boolean = false
|
||||
) {
|
||||
|
||||
def getTransformConfig: TransformConfig =
|
||||
if (noRelay) TransformConfig(relayVarName = None, wrapWithXor = !noXor)
|
||||
else TransformConfig(wrapWithXor = !noXor)
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
package aqua.api.types
|
||||
|
||||
import aqua.api.*
|
||||
import aqua.js.{FunctionDefJs, ServiceDefJs}
|
||||
import aqua.model.transform.TransformConfig
|
||||
|
||||
import scala.scalajs.js
|
||||
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
|
||||
import scala.scalajs.js.|
|
||||
import scala.scalajs.js.JSConverters.*
|
||||
|
||||
@JSExportTopLevel("AquaFunction")
|
||||
case class AquaFunction(
|
||||
@JSExport
|
||||
funcDef: FunctionDefJs,
|
||||
@JSExport
|
||||
script: String
|
||||
)
|
||||
|
||||
@JSExportTopLevel("Input")
|
||||
class Input(
|
||||
@JSExport
|
||||
val input: String
|
||||
)
|
||||
|
||||
@JSExportTopLevel("Path")
|
||||
class Path(
|
||||
@JSExport
|
||||
val path: String
|
||||
)
|
||||
|
||||
@JSExportTopLevel("Call")
|
||||
class Call(
|
||||
@JSExport
|
||||
val functionCall: String,
|
||||
@JSExport
|
||||
val arguments: js.Dynamic,
|
||||
@JSExport
|
||||
val input: Path | Input
|
||||
)
|
||||
|
||||
@JSExportTopLevel("AquaConfig")
|
||||
class AquaConfig(
|
||||
@JSExport
|
||||
val logLevel: js.UndefOr[String],
|
||||
@JSExport
|
||||
val constants: js.UndefOr[js.Array[String]],
|
||||
@JSExport
|
||||
val noXor: js.UndefOr[Boolean],
|
||||
@JSExport
|
||||
val noRelay: js.UndefOr[Boolean]
|
||||
)
|
||||
|
||||
@JSExportTopLevel("CompilationResult")
|
||||
class CompilationResult(
|
||||
@JSExport
|
||||
val services: js.Dictionary[ServiceDefJs],
|
||||
@JSExport
|
||||
val functions: js.Dictionary[AquaFunction],
|
||||
@JSExport
|
||||
val functionCall: js.UndefOr[AquaFunction],
|
||||
@JSExport
|
||||
val errors: js.Array[String]
|
||||
)
|
||||
|
||||
object CompilationResult {
|
||||
|
||||
def result(
|
||||
services: js.Dictionary[ServiceDefJs],
|
||||
functions: js.Dictionary[AquaFunction],
|
||||
call: Option[AquaFunction]
|
||||
): CompilationResult =
|
||||
new CompilationResult(services, functions, call.orNull, js.Array())
|
||||
|
||||
def errs(
|
||||
errors: List[String]
|
||||
): CompilationResult =
|
||||
CompilationResult(js.Dictionary(), js.Dictionary(), null, errors.toJSArray)
|
||||
}
|
||||
|
||||
case class AquaAPIConfig(
|
||||
logLevel: String = "info",
|
||||
constants: List[String] = Nil,
|
||||
noXor: Boolean = false,
|
||||
noRelay: Boolean = false
|
||||
) {
|
||||
|
||||
def getTransformConfig: TransformConfig =
|
||||
if (noRelay) TransformConfig(relayVarName = None, wrapWithXor = !noXor)
|
||||
else TransformConfig(wrapWithXor = !noXor)
|
||||
}
|
||||
|
||||
object AquaAPIConfig {
|
||||
|
||||
def fromJS(cjs: AquaConfig): AquaAPIConfig = {
|
||||
AquaAPIConfig(
|
||||
cjs.logLevel.getOrElse("info"),
|
||||
cjs.constants.map(_.toList).getOrElse(Nil),
|
||||
cjs.noXor.getOrElse(false),
|
||||
cjs.noRelay.getOrElse(false)
|
||||
)
|
||||
}
|
||||
}
|
@ -4,10 +4,7 @@ import aqua.backend.ts.TypeScriptTypes
|
||||
import aqua.backend.*
|
||||
import aqua.res.AquaRes
|
||||
|
||||
case class JavaScriptBackend(isOldFluenceJs: Boolean, client: String = Backend.client) extends Backend {
|
||||
|
||||
val ext = ".js"
|
||||
val tsExt = ".d.ts"
|
||||
case class JavaScriptBackend(isOldFluenceJs: Boolean = false, client: String = Backend.client) extends Backend {
|
||||
val types = TypeScriptTypes(client)
|
||||
|
||||
def typesFile(res: AquaRes): Generated = {
|
||||
@ -31,13 +28,18 @@ case class JavaScriptBackend(isOldFluenceJs: Boolean, client: String = Backend.c
|
||||
|
|
||||
|/* eslint-enable */""".stripMargin
|
||||
|
||||
Generated(tsExt, body, Nil)
|
||||
Generated(JavaScriptBackend.dtsExt, body, Nil)
|
||||
}
|
||||
|
||||
override def generate(res: AquaRes): Seq[Generated] =
|
||||
if (res.isEmpty) Nil
|
||||
else {
|
||||
val (airs, script) = OutputFile(res).generate(EmptyTypes, true, isOldFluenceJs)
|
||||
Generated(ext, script, airs) :: typesFile(res) :: Nil
|
||||
Generated(JavaScriptBackend.ext, script, airs) :: typesFile(res) :: Nil
|
||||
}
|
||||
}
|
||||
|
||||
object JavaScriptBackend {
|
||||
val ext = ".js"
|
||||
val dtsExt = ".d.ts"
|
||||
}
|
||||
|
@ -4,14 +4,16 @@ import aqua.backend.{Backend, Generated, OutputFile}
|
||||
import aqua.res.AquaRes
|
||||
import cats.data.NonEmptyChain
|
||||
|
||||
case class TypeScriptBackend(isOldFluenceJs: Boolean, client: String = Backend.client) extends Backend {
|
||||
|
||||
val ext = ".ts"
|
||||
case class TypeScriptBackend(isOldFluenceJs: Boolean = false, client: String = Backend.client) extends Backend {
|
||||
|
||||
override def generate(res: AquaRes): Seq[Generated] =
|
||||
if (res.isEmpty) Nil
|
||||
else {
|
||||
val (airs, script) = OutputFile(res).generate(TypeScriptTypes(client), false, isOldFluenceJs)
|
||||
Generated(ext, script, airs) :: Nil
|
||||
val (airs, script) = OutputFile(res).generate(TypeScriptTypes(client), isJs = false, isOldFluenceJs)
|
||||
Generated(TypeScriptBackend.ext, script, airs) :: Nil
|
||||
}
|
||||
}
|
||||
|
||||
object TypeScriptBackend {
|
||||
val ext = ".ts"
|
||||
}
|
||||
|
11
build.sbt
11
build.sbt
@ -143,16 +143,21 @@ lazy val `js-imports` = project
|
||||
.settings(commons: _*)
|
||||
.dependsOn(`js-exports`, transform.js)
|
||||
|
||||
lazy val `aqua-api` = project
|
||||
lazy val `aqua-api` = crossProject(JSPlatform, JVMPlatform)
|
||||
.withoutSuffixFor(JVMPlatform)
|
||||
.crossType(CrossType.Pure)
|
||||
.in(file("api/aqua-api"))
|
||||
.enablePlugins(ScalaJSPlugin)
|
||||
.settings(commons: _*)
|
||||
.dependsOn(`aqua-run`, `backend-api`)
|
||||
|
||||
lazy val `aqua-apiJS` = `aqua-api`.js
|
||||
.settings(
|
||||
scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule)),
|
||||
scalaJSUseMainModuleInitializer := true,
|
||||
Test / test := {}
|
||||
)
|
||||
.dependsOn(`js-exports`, `aqua-run`.js, `backend-api`.js)
|
||||
.enablePlugins(ScalaJSPlugin)
|
||||
.dependsOn(`js-exports`)
|
||||
|
||||
lazy val types = crossProject(JVMPlatform, JSPlatform)
|
||||
.withoutSuffixFor(JVMPlatform)
|
||||
|
Loading…
Reference in New Issue
Block a user