From 5226ba93e8fb400afec0a321f519c56f8df633d7 Mon Sep 17 00:00:00 2001 From: Matthew Rothenberg Date: Sat, 8 Feb 2020 00:54:01 -0500 Subject: [PATCH] integrate scalafmt code formatting scaffolding (#175) * integrate code formatting scaffolding Since OSS contributors to this repo are more likely to be touching the JS portion, I left out the "recommend extensions" for Scala for the default vscode conf, so we dont bug everyone who wants to contribute to install it. * apply scalafmt auto fix * apply lint-style-fix globally catches a Markdown formatting thing in README via Prettier. --- .github/workflows/lint.yml | 9 + .scalafmt.conf | 25 + .vscode/extensions.json | 9 + .vscode/settings.json | 6 + Makefile | 58 ++ README.md | 15 + build.sbt | 40 +- project/plugins.sbt | 9 +- .../adridadou/openlaw/client/Openlaw.scala | 800 ++++++++++++------ 9 files changed, 713 insertions(+), 258 deletions(-) create mode 100644 .scalafmt.conf create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 Makefile diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 3c7c4b1..e491d2c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,3 +19,12 @@ jobs: - uses: actions/checkout@v1 - name: Shellcheck Lint uses: azohra/shell-linter@v0.1.0 + + lint-scala: + name: Run scalafmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 1 + - uses: openlawteam/scalafmt-ci@v2 diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 0000000..f719f6a --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,25 @@ +# Scalafmt configuration +# +# Reference: https://scalameta.org/scalafmt/docs/configuration.html + +# We would like to define an "edition" to freeze the rules without requiring a +# specific version. +# +# In effect, this then enforces a minimum version of scalafmt but allows some +# users to have more recent versions installed on their machine, and lets us +# upgrade the default ruleset all at once for the project if desired. +# +# Unfortunately, IntelliJ parses the conf file on its own prior to passing to +# scalafmt, and it does not yet support the `edition` tag and bombs. +# +# https://intellij-support.jetbrains.com/hc/en-us/requests/2449753 + +# edition = 2019-12 +version = "2.3.2" + + +project.excludeFilters = ["target/"] + +# NOTE: To adhere to OSS community standards, and to have as minimum a gap as +# possible between "default" projects, we do not override any of the style +# defaults. diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..7824889 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": ["esbenp.prettier-vscode"], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9f1b3da --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "editor.formatOnSave": true, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e322207 --- /dev/null +++ b/Makefile @@ -0,0 +1,58 @@ +############################################################################### +# Linters (not normally run manually via command line, but here for backup.) +############################################################################### +.PHONY: lint lint-style lint-style-fix lint-code +lint: lint-style lint-code +lint-code: lint-code-js +lint-style: lint-style-js lint-style-scala ## Lint all files for code style +lint-style-fix: lint-style-js-fix lint-style-scala-fix # Automatically fix all files for code style + +lint-style-js: + npm run style + +lint-style-js-fix: + npm run style:fix + +lint-code-js: + npm run lint + +lint-code-js-fix: + npm run lint:fix + +SCALAFMT_IMAGE = mrothy/scalafmt-native:2.3.2 +SCALAFMT_TARGETS = src project build.sbt +SCALAFMT_EXCLUSIONS = target/ + +lint-style-scala: # Lint scala files for code style + docker run \ + -v $$(PWD):/src \ + --rm -it \ + --workdir /src \ + $(SCALAFMT_IMAGE) \ + --exclude $(SCALAFMT_EXCLUSIONS) \ + --list \ + $(SCALAFMT_TARGETS) + +lint-style-scala-fix: # Automatically fix scala files for code style + docker run \ + -v $$(PWD):/src \ + --rm -it \ + --workdir /src \ + $(SCALAFMT_IMAGE) \ + --exclude $(SCALAFMT_EXCLUSIONS) \ + $(SCALAFMT_TARGETS) + +############################################################################### +# Modified version of self-documenting help script from: +# https://suva.sh/posts/well-documented-makefiles/ +# +# This creates a default `help` goal that will document all tasks that are +# annotated with a double comment "#" marker. +############################################################################### +.DEFAULT_GOAL:=help +help: ## Display this help message + @awk 'BEGIN { \ + FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n\nTargets:\n" \ + } /^[a-zA-Z0-9_-]+:.*?##/ { \ + printf " \033[36m%-12s\033[0m %s\n", $$1, $$2 \ + }' $(MAKEFILE_LIST) diff --git a/README.md b/README.md index ba9b888..9ff6cba 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,21 @@ More detailed documentation about the release process is [here](docs/ReleaseProc See information about contributing [here](docs/CONTRIBUTING.md). +### Code Formatting + +We adhere to standardized code formatting via [Prettier](https://prettier.io) +and [scalafmt](https://scalameta.org/scalafmt/). All PRs will be automatically +checked for adherence. If they do not adhere to standardized formatting, they +should be corrected prior to being merged. + +The best way is let your editor handle everything for you everytime you hit +save, see the [Scalafmt Installation +Docs](https://scalameta.org/scalafmt/docs/installation.html) or the OpenLaw +developer setup documentation. + +To manually verify, can run `make lint-style` to check and `make lint-style-fix` +to automatically repair all files. + ## License Copyright 2019 Aaron Wright, David Roon, and ConsenSys AG. diff --git a/build.sbt b/build.sbt index 47e7929..072a9cf 100644 --- a/build.sbt +++ b/build.sbt @@ -9,7 +9,7 @@ always upgrade in a controlled fashion. If you wish to update either Scala or SBT, please open an issue and and tag @openlawteam/infra. -*/ + */ lazy val scalaV = "2.12.10" lazy val repositories = Seq( @@ -23,18 +23,28 @@ lazy val repositories = Seq( ) scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature") -javacOptions ++= Seq("-Xms512M", "-Xmx1024M", "-Xss1M", "-XX:+CMSClassUnloadingEnabled") +javacOptions ++= Seq( + "-Xms512M", + "-Xmx1024M", + "-Xss1M", + "-XX:+CMSClassUnloadingEnabled" +) -lazy val root = (project in file(".")).settings( - scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.ESModule).withESFeatures(_.withUseECMAScript2015(true))}, - resolvers ++= repositories, - organization := "org.openlaw", - name := "openlaw-core-client", - scalaVersion := scalaV, - libraryDependencies ++= Seq( - "org.openlaw" %%% "openlaw-core" % "0.1.57" - ), - relativeSourceMaps := true, - artifactPath in (Compile, fullOptJS) := crossTarget.value / "client.js", - artifactPath in (Compile, fastOptJS) := crossTarget.value / "client.js" -).enablePlugins(ScalaJSPlugin) +lazy val root = (project in file(".")) + .settings( + scalaJSLinkerConfig ~= { + _.withModuleKind(ModuleKind.ESModule) + .withESFeatures(_.withUseECMAScript2015(true)) + }, + resolvers ++= repositories, + organization := "org.openlaw", + name := "openlaw-core-client", + scalaVersion := scalaV, + libraryDependencies ++= Seq( + "org.openlaw" %%% "openlaw-core" % "0.1.57" + ), + relativeSourceMaps := true, + artifactPath in (Compile, fullOptJS) := crossTarget.value / "client.js", + artifactPath in (Compile, fastOptJS) := crossTarget.value / "client.js" + ) + .enablePlugins(ScalaJSPlugin) diff --git a/project/plugins.sbt b/project/plugins.sbt index f3c8daf..2b7ce2e 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,21 +2,24 @@ logLevel := Level.Warn resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/" resolvers += "Typesafe Repository" at "https://repo.typesafe.com/typesafe/releases/" -resolvers += Resolver.url("sbt-plugins", url("https://dl.bintray.com/ssidorenko/sbt-plugins/"))(Resolver.ivyStylePatterns) +resolvers += Resolver.url( + "sbt-plugins", + url("https://dl.bintray.com/ssidorenko/sbt-plugins/") +)(Resolver.ivyStylePatterns) addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.31") addSbtPlugin("org.lyranthe.sbt" % "partial-unification" % "1.1.0") /* WartRemover currently chokes on ScalaJS and causes lots of false positives. In the future, we can re-enable here if resikved and then enable it in our build -settings. */ +settings. */ // addSbtPlugin("org.wartremover" % "sbt-wartremover" % "2.4.1") /* Informational tools you may wish to install locally: "sbt-dependency-graph is an informational tool rather than one that changes your build, so you will more than likely wish to install it as a global plugin so that you can use it in any SBT project without the need to explicitly add it -to each one. To do this, add the plugin dependency to +to each one. To do this, add the plugin dependency to ~/.sbt/1.0/plugins/plugins.sbt for sbt 1.0" Same logic appears to apply to sbt-updates and sbt-dependency check. */ diff --git a/src/main/scala/org/adridadou/openlaw/client/Openlaw.scala b/src/main/scala/org/adridadou/openlaw/client/Openlaw.scala index cdddc71..fec5462 100644 --- a/src/main/scala/org/adridadou/openlaw/client/Openlaw.scala +++ b/src/main/scala/org/adridadou/openlaw/client/Openlaw.scala @@ -11,7 +11,11 @@ import cats.implicits._ import org.adridadou.openlaw.parser.contract.ParagraphEdits import org.adridadou.openlaw.result.{Failure, Result, Success} import org.adridadou.openlaw.result.Implicits._ -import org.adridadou.openlaw.values.{ContractId, TemplateParameters, TemplateTitle} +import org.adridadou.openlaw.values.{ + ContractId, + TemplateParameters, + TemplateTitle +} import org.adridadou.openlaw.vm.OpenlawExecutionEngine import slogging.LazyLogging import io.circe.parser._ @@ -34,162 +38,274 @@ object Openlaw extends LazyLogging { val markdown = new OpenlawTemplateLanguageParserService(clock) @JSExport - def compileTemplate(text:String) : js.Dictionary[Any] = markdown.compileTemplate(text, clock) match { - case Left(err) => js.Dictionary( - "isError" -> true, - "errorMessage" -> err.message, - "compiledTemplate" -> js.undefined - ) - case Right(result) => js.Dictionary( - "isError" -> false, - "errorMessage" -> "", - "compiledTemplate" -> result - ) - } + def compileTemplate(text: String): js.Dictionary[Any] = + markdown.compileTemplate(text, clock) match { + case Left(err) => + js.Dictionary( + "isError" -> true, + "errorMessage" -> err.message, + "compiledTemplate" -> js.undefined + ) + case Right(result) => + js.Dictionary( + "isError" -> false, + "errorMessage" -> "", + "compiledTemplate" -> result + ) + } @JSExport - def execute(compiledTemplate:CompiledTemplate, jsTemplates:js.Dictionary[CompiledTemplate], jsParams:js.Dictionary[Any]) : js.Dictionary[Any] = { - handleExecutionResult(engine.execute( - compiledTemplate, - prepareParameters(jsParams), - prepareTemplates(jsTemplates))) + def execute( + compiledTemplate: CompiledTemplate, + jsTemplates: js.Dictionary[CompiledTemplate], + jsParams: js.Dictionary[Any] + ): js.Dictionary[Any] = { + handleExecutionResult( + engine.execute( + compiledTemplate, + prepareParameters(jsParams), + prepareTemplates(jsTemplates) + ) + ) } @JSExport - def execute(compiledTemplate:CompiledTemplate, jsTemplates:js.Dictionary[CompiledTemplate], jsParams:js.Dictionary[Any], externalCallStructures:js.Dictionary[Any]) : js.Dictionary[Any] = { - handleExecutionResult(engine.execute( - compiledTemplate, - prepareParameters(jsParams), - prepareTemplates(jsTemplates), - prepareStructures(externalCallStructures))) + def execute( + compiledTemplate: CompiledTemplate, + jsTemplates: js.Dictionary[CompiledTemplate], + jsParams: js.Dictionary[Any], + externalCallStructures: js.Dictionary[Any] + ): js.Dictionary[Any] = { + handleExecutionResult( + engine.execute( + compiledTemplate, + prepareParameters(jsParams), + prepareTemplates(jsTemplates), + prepareStructures(externalCallStructures) + ) + ) } @JSExport - def executeForReview(compiledTemplate:CompiledTemplate, proofs:js.Dictionary[String], jsTemplates:js.Dictionary[CompiledTemplate], jsParams:js.Dictionary[Any], externalCallStructures:js.Dictionary[Any], contractId:js.UndefOr[String], profileAddress:js.UndefOr[String]) : js.Dictionary[Any] = { - handleExecutionResult(engine.execute( - compiledTemplate, - prepareParameters(jsParams), - prepareTemplates(jsTemplates), - signatureProofs = prepareProofs(proofs.toMap).getOrThrow(), - executions = Map.empty, - prepareStructures(externalCallStructures), - contractId.toOption.map(ContractId(_)), - profileAddress.toOption.map(EthereumAddress(_).getOrThrow()))) + def executeForReview( + compiledTemplate: CompiledTemplate, + proofs: js.Dictionary[String], + jsTemplates: js.Dictionary[CompiledTemplate], + jsParams: js.Dictionary[Any], + externalCallStructures: js.Dictionary[Any], + contractId: js.UndefOr[String], + profileAddress: js.UndefOr[String] + ): js.Dictionary[Any] = { + handleExecutionResult( + engine.execute( + compiledTemplate, + prepareParameters(jsParams), + prepareTemplates(jsTemplates), + signatureProofs = prepareProofs(proofs.toMap).getOrThrow(), + executions = Map.empty, + prepareStructures(externalCallStructures), + contractId.toOption.map(ContractId(_)), + profileAddress.toOption.map(EthereumAddress(_).getOrThrow()) + ) + ) } - private def prepareProofs(proofs:Map[String, String]):Result[Map[Email, SignatureProof]] = proofs.toList + private def prepareProofs( + proofs: Map[String, String] + ): Result[Map[Email, SignatureProof]] = + proofs.toList .map({ case (strEmail, strProof) => for { email <- Email(strEmail) proof <- toResult(decode[SignatureProof](strProof)) } yield email -> proof - }).sequence.map(_.toMap) + }) + .sequence + .map(_.toMap) - private def toResult[T](r:Either[io.circe.Error, T]):Result[T] = r match { - case Right(v) => Success(v) + private def toResult[T](r: Either[io.circe.Error, T]): Result[T] = r match { + case Right(v) => Success(v) case Left(err) => Failure(err.getMessage) } @JSExport - def resumeExecution(executionResult:OpenlawExecutionState, jsTemplates:js.Dictionary[CompiledTemplate]) : js.Dictionary[Any] = { - handleExecutionResult(engine.resumeExecution(executionResult, prepareTemplates(jsTemplates))) + def resumeExecution( + executionResult: OpenlawExecutionState, + jsTemplates: js.Dictionary[CompiledTemplate] + ): js.Dictionary[Any] = { + handleExecutionResult( + engine.resumeExecution(executionResult, prepareTemplates(jsTemplates)) + ) } @JSExport - def createAddress(address:js.Dictionary[String]):String = { - AddressType.internalFormat(Address( - formattedAddress = printAddressElement(address.get("address")), - placeId = printAddressElement(address.get("placeId")), - streetName = printAddressElement(address.get("streetName")), - streetNumber = printAddressElement(address.get("streetNumber")), - city = printAddressElement(address.get("city")), - state = printAddressElement(address.get("state")), - country = printAddressElement(address.get("country")), - zipCode = printAddressElement(address.get("zipCode")) - )).getOrThrow() + def createAddress(address: js.Dictionary[String]): String = { + AddressType + .internalFormat( + Address( + formattedAddress = printAddressElement(address.get("address")), + placeId = printAddressElement(address.get("placeId")), + streetName = printAddressElement(address.get("streetName")), + streetNumber = printAddressElement(address.get("streetNumber")), + city = printAddressElement(address.get("city")), + state = printAddressElement(address.get("state")), + country = printAddressElement(address.get("country")), + zipCode = printAddressElement(address.get("zipCode")) + ) + ) + .getOrThrow() } - private def printAddressElement(optStr:Option[String]):String = optStr.getOrElse("n/a") + private def printAddressElement(optStr: Option[String]): String = + optStr.getOrElse("n/a") @JSExport - def validationErrors(result:ValidationResult):js.Array[String] = result.validationExpressionErrors.toJSArray + def validationErrors(result: ValidationResult): js.Array[String] = + result.validationExpressionErrors.toJSArray @JSExport - def validateContract(executionResult:OpenlawExecutionState):ValidationResult = + def validateContract( + executionResult: OpenlawExecutionState + ): ValidationResult = executionResult.validateExecution.getOrThrow() @JSExport - def showInForm(variable:VariableDefinition, executionResult:TemplateExecutionResult):Boolean = + def showInForm( + variable: VariableDefinition, + executionResult: TemplateExecutionResult + ): Boolean = variable.varType(executionResult) match { - case _:NoShowInForm => false - case _ => true + case _: NoShowInForm => false + case _ => true } @JSExport - def isChoiceType(variable:VariableDefinition, executionResult:TemplateExecutionResult):Boolean = variable.varType(executionResult) match { - case _:DefinedChoiceType => + def isChoiceType( + variable: VariableDefinition, + executionResult: TemplateExecutionResult + ): Boolean = variable.varType(executionResult) match { + case _: DefinedChoiceType => true case _ => variable.defaultValue - .map(getDefaultChoices(_, variable.varType(executionResult), executionResult)) + .map( + getDefaultChoices( + _, + variable.varType(executionResult), + executionResult + ) + ) .exists(_.nonEmpty) } @JSExport - def isStructuredType(variable:VariableDefinition, executionResult:TemplateExecutionResult):Boolean = variable.varType(executionResult) match { - case _:DefinedStructureType => true - case _ => false + def isStructuredType( + variable: VariableDefinition, + executionResult: TemplateExecutionResult + ): Boolean = variable.varType(executionResult) match { + case _: DefinedStructureType => true + case _ => false } @JSExport - def getChoiceValues(variable:VariableDefinition, executionResult: TemplateExecutionResult):js.Array[String] = variable.varType(executionResult) match { - case choice:DefinedChoiceType => + def getChoiceValues( + variable: VariableDefinition, + executionResult: TemplateExecutionResult + ): js.Array[String] = variable.varType(executionResult) match { + case choice: DefinedChoiceType => choice.choices.values.toJSArray case _ => - variable.defaultValue.map(getDefaultChoices(_, variable.varType(executionResult), executionResult)).getOrElse(Seq()).toJSArray + variable.defaultValue + .map( + getDefaultChoices( + _, + variable.varType(executionResult), + executionResult + ) + ) + .getOrElse(Seq()) + .toJSArray } - private def getDefaultChoices(parameter:Parameter, variableType:VariableType, executionResult: TemplateExecutionResult):Seq[String] = parameter match { + private def getDefaultChoices( + parameter: Parameter, + variableType: VariableType, + executionResult: TemplateExecutionResult + ): Seq[String] = parameter match { case Parameters(parameterMap) => - parameterMap.toMap.get("options").map({ - case ListParameter(params) => - params.flatMap(_.evaluate(executionResult).getOrThrow()).map(variableType.internalFormat(_).getOrThrow()) - case OneValueParameter(expr) => - expr.evaluate(executionResult).getOrThrow().map(variableType.internalFormat(_).getOrThrow()).toSeq - case _ => Seq() - }).getOrElse(Seq()) + parameterMap.toMap + .get("options") + .map({ + case ListParameter(params) => + params + .flatMap(_.evaluate(executionResult).getOrThrow()) + .map(variableType.internalFormat(_).getOrThrow()) + case OneValueParameter(expr) => + expr + .evaluate(executionResult) + .getOrThrow() + .map(variableType.internalFormat(_).getOrThrow()) + .toSeq + case _ => Seq() + }) + .getOrElse(Seq()) case _ => Seq() } @JSExport - def getStructureFieldDefinitions(variable:VariableDefinition, executionResult: TemplateExecutionResult):js.Array[VariableDefinition] = variable.varType(executionResult) match { - case structure:DefinedStructureType => - structure.structure.names.map(name => structure.structure.typeDefinition(name)).toJSArray + def getStructureFieldDefinitions( + variable: VariableDefinition, + executionResult: TemplateExecutionResult + ): js.Array[VariableDefinition] = variable.varType(executionResult) match { + case structure: DefinedStructureType => + structure.structure.names + .map(name => structure.structure.typeDefinition(name)) + .toJSArray case _ => Seq().toJSArray } @JSExport - def getStructureFieldValue(variable:VariableDefinition, field:VariableDefinition, structureValue:js.UndefOr[String], executionResult: TemplateExecutionResult):js.UndefOr[String] = variable.varType(executionResult) match { - case structureType:DefinedStructureType => - val values:Map[VariableName, OpenlawValue] = structureValue.map(structureType.cast(_, executionResult).getOrThrow().underlying).getOrElse(Map()) + def getStructureFieldValue( + variable: VariableDefinition, + field: VariableDefinition, + structureValue: js.UndefOr[String], + executionResult: TemplateExecutionResult + ): js.UndefOr[String] = variable.varType(executionResult) match { + case structureType: DefinedStructureType => + val values: Map[VariableName, OpenlawValue] = structureValue + .map(structureType.cast(_, executionResult).getOrThrow().underlying) + .getOrElse(Map()) (for { value <- values.get(field.name) fieldType <- structureType.structure.typeDefinition.get(field.name) - } yield fieldType.varType(executionResult).internalFormat(value).getOrThrow()).orUndefined + } yield fieldType + .varType(executionResult) + .internalFormat(value) + .getOrThrow()).orUndefined case _ => js.undefined } @JSExport - def setStructureFieldValue(variable:VariableDefinition, fieldName:String, fieldValue:js.UndefOr[String], structureValue:js.UndefOr[String], executionResult: TemplateExecutionResult):js.UndefOr[String] = variable.varType(executionResult) match { - case structure:DefinedStructureType => + def setStructureFieldValue( + variable: VariableDefinition, + fieldName: String, + fieldValue: js.UndefOr[String], + structureValue: js.UndefOr[String], + executionResult: TemplateExecutionResult + ): js.UndefOr[String] = variable.varType(executionResult) match { + case structure: DefinedStructureType => structure.structure.typeDefinition.get(VariableName(fieldName)) match { case Some(fieldType) => - val currentMap = structureValue.map(structure.cast(_, executionResult).getOrThrow().underlying).getOrElse(Map()) + val currentMap = structureValue + .map(structure.cast(_, executionResult).getOrThrow().underlying) + .getOrElse(Map()) fieldValue.toOption match { case Some(value) => - val newMap = currentMap + (VariableName(fieldName) -> fieldType.cast(value, executionResult).getOrThrow()) + val newMap = currentMap + (VariableName(fieldName) -> fieldType + .cast(value, executionResult) + .getOrThrow()) structure.internalFormat(newMap).getOrThrow() case None => val newMap = currentMap - VariableName(fieldName) @@ -203,36 +319,46 @@ object Openlaw extends LazyLogging { } @JSExport - def getAddress(json:String):Address = AddressType.cast(json).getOrThrow() + def getAddress(json: String): Address = AddressType.cast(json).getOrThrow() @JSExport - def getFormattedAddress(address:Address):String = address.formattedAddress + def getFormattedAddress(address: Address): String = address.formattedAddress @JSExport - def noIdentity(result:ValidationResult):Boolean = result.identities.isEmpty + def noIdentity(result: ValidationResult): Boolean = result.identities.isEmpty @JSExport - def missingIdentities(result:ValidationResult):Boolean = result.missingIdentities.nonEmpty + def missingIdentities(result: ValidationResult): Boolean = + result.missingIdentities.nonEmpty @JSExport - def hasMissingInputs(result:ValidationResult):Boolean = result.missingInputs.nonEmpty + def hasMissingInputs(result: ValidationResult): Boolean = + result.missingInputs.nonEmpty @JSExport - def getMissingInputs(result:ValidationResult):js.Array[String] = result.missingInputs.map(_.name).distinct.toJSArray + def getMissingInputs(result: ValidationResult): js.Array[String] = + result.missingInputs.map(_.name).distinct.toJSArray @JSExport - def missingAllIdentities(result:ValidationResult):Boolean = result.identities.nonEmpty && result.missingIdentities.length === result.identities.length + def missingAllIdentities(result: ValidationResult): Boolean = + result.identities.nonEmpty && result.missingIdentities.length === result.identities.length @JSExport - def deserializeExecutionResult(resultJson:String):SerializableTemplateExecutionResult = decode[SerializableTemplateExecutionResult](resultJson) match { - case Right(value) => value - case Left(ex) => throw new RuntimeException(ex.getMessage) - } + def deserializeExecutionResult( + resultJson: String + ): SerializableTemplateExecutionResult = + decode[SerializableTemplateExecutionResult](resultJson) match { + case Right(value) => value + case Left(ex) => throw new RuntimeException(ex.getMessage) + } @JSExport - def serializeExecutionResult(executionResult:OpenlawExecutionState):String = executionResult.toSerializable.asJson.noSpaces + def serializeExecutionResult(executionResult: OpenlawExecutionState): String = + executionResult.toSerializable.asJson.noSpaces - private def handleExecutionResult(executionResult:Result[OpenlawExecutionState]):js.Dictionary[Any] = executionResult match { + private def handleExecutionResult( + executionResult: Result[OpenlawExecutionState] + ): js.Dictionary[Any] = executionResult match { case Success(result) => result.state match { case ExecutionFinished => @@ -240,331 +366,525 @@ object Openlaw extends LazyLogging { "executionResult" -> result, "isError" -> false, "missingTemplate" -> false, - "errorMessage" -> "") + "errorMessage" -> "" + ) case ExecutionWaitForTemplate(_, definition, _) => js.Dictionary( "executionResult" -> result, "isError" -> false, "missingTemplate" -> true, "missingTemplateName" -> definition.name.title, - "errorMessage" -> s"the template ${definition.name} was not loaded") + "errorMessage" -> s"the template ${definition.name} was not loaded" + ) case _ => js.Dictionary( "executionResult" -> result, "isError" -> true, "missingTemplate" -> false, - "errorMessage" -> s"invalid end state ${result.state}") + "errorMessage" -> s"invalid end state ${result.state}" + ) } case Failure(_, message) => js.Dictionary( "executionResult" -> js.undefined, "isError" -> true, - "errorMessage" -> message) + "errorMessage" -> message + ) } @JSExport - def getInitialParameters(executionResult:TemplateExecutionResult):js.Array[js.Dictionary[String]] = { + def getInitialParameters( + executionResult: TemplateExecutionResult + ): js.Array[js.Dictionary[String]] = { executionResult.getAllVariables .filter({ - case (_, variable) => variable.varType(executionResult) match { - case _:NoShowInForm => false - case _ => true - }}).filter({case (_, variable) => variable.defaultValue.isDefined}) - .map({ case (result, variable) => js.Dictionary( - "name" -> variable.name.name, - "value" -> getInitialParameter(variable, result)) - }).toJSArray + case (_, variable) => + variable.varType(executionResult) match { + case _: NoShowInForm => false + case _ => true + } + }) + .filter({ case (_, variable) => variable.defaultValue.isDefined }) + .map({ + case (result, variable) => + js.Dictionary( + "name" -> variable.name.name, + "value" -> getInitialParameter(variable, result) + ) + }) + .toJSArray } - private def getInitialParameter(variable:VariableDefinition, executionResult: TemplateExecutionResult):String = + private def getInitialParameter( + variable: VariableDefinition, + executionResult: TemplateExecutionResult + ): String = variable.defaultValue .map(variable.varType(executionResult).construct(_, executionResult)) .map({ - case Success(Some(value)) => variable.varType(executionResult).internalFormat(value).getOrThrow() + case Success(Some(value)) => + variable.varType(executionResult).internalFormat(value).getOrThrow() case Success(None) => "" case Failure(ex, message) => logger.error(message, ex) "" - }).getOrElse("") - - + }) + .getOrElse("") @JSExport - def getType(variable:VariableDefinition):String = variable.variableTypeDefinition.map(_.name).getOrElse(TextType.name) + def getType(variable: VariableDefinition): String = + variable.variableTypeDefinition.map(_.name).getOrElse(TextType.name) @JSExport - def getDescription(variable:VariableDefinition):String = variable.description.getOrElse(variable.name.name) + def getDescription(variable: VariableDefinition): String = + variable.description.getOrElse(variable.name.name) @JSExport - def getName(variable:VariableDefinition):String = variable.name.name + def getName(variable: VariableDefinition): String = variable.name.name @JSExport - def getTemplateName(templateDefinition: TemplateDefinition):String = templateDefinition.name.name.title + def getTemplateName(templateDefinition: TemplateDefinition): String = + templateDefinition.name.name.title @JSExport - def getCleanName(variable:VariableDefinition):String = variable.name.name.replace(" ", "-") + def getCleanName(variable: VariableDefinition): String = + variable.name.name.replace(" ", "-") @JSExport - def renderForReview(agreement:StructuredAgreement, jsOverriddenParagraphs:js.Dictionary[String]): String = + def renderForReview( + agreement: StructuredAgreement, + jsOverriddenParagraphs: js.Dictionary[String] + ): String = render(agreement, List(), jsOverriddenParagraphs, markdown.forReview) @JSExport - def renderForPreview(agreement:StructuredAgreement, hiddenVariables:js.Array[String], jsOverriddenParagraphs:js.Dictionary[String]): String = - render(agreement, hiddenVariables.toList, jsOverriddenParagraphs, markdown.forPreview) + def renderForPreview( + agreement: StructuredAgreement, + hiddenVariables: js.Array[String], + jsOverriddenParagraphs: js.Dictionary[String] + ): String = + render( + agreement, + hiddenVariables.toList, + jsOverriddenParagraphs, + markdown.forPreview + ) @JSExport - def parseMarkdown(str:String):String = markdown.forReviewParagraph(str).getOrThrow() + def parseMarkdown(str: String): String = + markdown.forReviewParagraph(str).getOrThrow() @JSExport - def renderParagraphForEdit(agreement: StructuredAgreement, index:Int): String = + def renderParagraphForEdit( + agreement: StructuredAgreement, + index: Int + ): String = markdown.forReviewEdit(agreement.paragraphs(index - 1)) - private def render(agreement:StructuredAgreement, hiddenVariables:List[String], jsOverriddenParagraphs:js.Dictionary[String], renderFunc:(StructuredAgreement, ParagraphEdits, List[String]) => String):String = - renderFunc(agreement, prepareParagraphs(agreement, jsOverriddenParagraphs), hiddenVariables) + private def render( + agreement: StructuredAgreement, + hiddenVariables: List[String], + jsOverriddenParagraphs: js.Dictionary[String], + renderFunc: (StructuredAgreement, ParagraphEdits, List[String]) => String + ): String = + renderFunc( + agreement, + prepareParagraphs(agreement, jsOverriddenParagraphs), + hiddenVariables + ) @JSExport - def checkValidity(variable:VariableDefinition, optValue:js.UndefOr[String], executionResult: TemplateExecutionResult): js.Dictionary[Any] = optValue.toOption - .map(variable.varType(executionResult).cast(_, executionResult)) match { - case Some(Failure(_ ,message)) => - Dictionary( - "isError" -> true, - "errorMessage" -> message - ) + def checkValidity( + variable: VariableDefinition, + optValue: js.UndefOr[String], + executionResult: TemplateExecutionResult + ): js.Dictionary[Any] = + optValue.toOption + .map(variable.varType(executionResult).cast(_, executionResult)) match { + case Some(Failure(_, message)) => + Dictionary( + "isError" -> true, + "errorMessage" -> message + ) - case _ => - Dictionary( - "isError" -> false - ) - } + case _ => + Dictionary( + "isError" -> false + ) + } @JSExport - def getTypes:js.Array[String] = - js.Array(VariableType.allTypes().map(_.name):_*) + def getTypes: js.Array[String] = + js.Array(VariableType.allTypes().map(_.name): _*) @JSExport - def getExecutedVariables(executionResult:TemplateExecutionResult, jsDefinedValues:js.Dictionary[Any]): js.Array[VariableDefinition] = { - getVariables(executionResult, executionResult.getExecutedVariables, prepareParameters(jsDefinedValues)).toJSArray + def getExecutedVariables( + executionResult: TemplateExecutionResult, + jsDefinedValues: js.Dictionary[Any] + ): js.Array[VariableDefinition] = { + getVariables( + executionResult, + executionResult.getExecutedVariables, + prepareParameters(jsDefinedValues) + ).toJSArray } @JSExport - def getVariables(executionResult:TemplateExecutionResult, jsDefinedValues:js.Dictionary[Any]): js.Array[VariableDefinition] = { - getVariables(executionResult, executionResult.getAllVariableNames, prepareParameters(jsDefinedValues)).toJSArray + def getVariables( + executionResult: TemplateExecutionResult, + jsDefinedValues: js.Dictionary[Any] + ): js.Array[VariableDefinition] = { + getVariables( + executionResult, + executionResult.getAllVariableNames, + prepareParameters(jsDefinedValues) + ).toJSArray } @JSExport - def getAllConditionalVariableNames(executionResult:TemplateExecutionResult): js.Array[String] = { + def getAllConditionalVariableNames( + executionResult: TemplateExecutionResult + ): js.Array[String] = { executionResult.getAllVariables - .map({ case (_, variable) => variable}) - .filter(_.variableTypeDefinition === Some(VariableTypeDefinition(YesNoType.name))) - .map(variable => variable.name.name).distinct.toJSArray + .map({ case (_, variable) => variable }) + .filter( + _.variableTypeDefinition === Some( + VariableTypeDefinition(YesNoType.name) + ) + ) + .map(variable => variable.name.name) + .distinct + .toJSArray } - def getVariables(executionResult: TemplateExecutionResult, variables: Seq[VariableName], definedValues:TemplateParameters): Seq[VariableDefinition] = { + def getVariables( + executionResult: TemplateExecutionResult, + variables: Seq[VariableName], + definedValues: TemplateParameters + ): Seq[VariableDefinition] = { val predefinedVariables = definedValues.params.keys.toSet variables .flatMap(name => executionResult.getVariable(name)) .filter(_.varType(executionResult) match { - case _:NoShowInForm => false - case _ => true + case _: NoShowInForm => false + case _ => true }) .filter(variable => !predefinedVariables.contains(variable.name)) } @JSExport - def getAgreements(executionResult: TemplateExecutionResult):js.Array[js.Dictionary[Any]] = - executionResult.agreements.map(agreement => { - executionResult.findExecutionResult(agreement.executionResultId) match { - case Some(agreementExecutionResult) => - Dictionary[Any]( - "agreement" -> agreement, - "executionResult" -> agreementExecutionResult, - "mainTemplate" -> agreement.mainTemplate, - "showTitle" -> agreement.header.shouldShowTitle, - "name" -> agreement.name, - "title" -> agreement.title.title - ) - case None => - dom.console.log(s"error! execution result with id ${agreement.executionResultId.id} not found!. available: ${executionResult.subExecutions.values.map(_.id.id).mkString(",")}") - Dictionary[Any]( - "agreement" -> agreement, - "mainTemplate" -> agreement.mainTemplate, - "showTitle" -> agreement.header.shouldShowTitle, - "name" -> agreement.name, - "title" -> agreement.title.title - ) - } + def getAgreements( + executionResult: TemplateExecutionResult + ): js.Array[js.Dictionary[Any]] = + executionResult.agreements + .map(agreement => { + executionResult.findExecutionResult(agreement.executionResultId) match { + case Some(agreementExecutionResult) => + Dictionary[Any]( + "agreement" -> agreement, + "executionResult" -> agreementExecutionResult, + "mainTemplate" -> agreement.mainTemplate, + "showTitle" -> agreement.header.shouldShowTitle, + "name" -> agreement.name, + "title" -> agreement.title.title + ) + case None => + dom.console.log( + s"error! execution result with id ${agreement.executionResultId.id} not found!. available: ${executionResult.subExecutions.values + .map(_.id.id) + .mkString(",")}" + ) + Dictionary[Any]( + "agreement" -> agreement, + "mainTemplate" -> agreement.mainTemplate, + "showTitle" -> agreement.header.shouldShowTitle, + "name" -> agreement.name, + "title" -> agreement.title.title + ) + } - }).toJSArray + }) + .toJSArray @JSExport - def createExternalSignatureValue(userId:js.UndefOr[String], email: String, serviceName: String):String = - ExternalSignatureType.internalFormat(ExternalSignature(Option(createIdentity(userId, email)), ServiceName(serviceName))).getOrThrow() + def createExternalSignatureValue( + userId: js.UndefOr[String], + email: String, + serviceName: String + ): String = + ExternalSignatureType + .internalFormat( + ExternalSignature( + Option(createIdentity(userId, email)), + ServiceName(serviceName) + ) + ) + .getOrThrow() @JSExport - def getIdentityEmail(identity:Identity):String = identity.email.email + def getIdentityEmail(identity: Identity): String = identity.email.email @JSExport - def createIdentityInternalValue(userId:js.UndefOr[String], email:String):String = + def createIdentityInternalValue( + userId: js.UndefOr[String], + email: String + ): String = IdentityType.internalFormat(createIdentity(userId, email)).getOrThrow() @JSExport - def createIdentity(userId:js.UndefOr[String], email:String):Identity = { + def createIdentity(userId: js.UndefOr[String], email: String): Identity = { Identity( email = Email(email).getOrThrow() ) } @JSExport - def getIdentities(validationResult: ValidationResult, executionResult: TemplateExecutionResult):js.Array[VariableDefinition] = { + def getIdentities( + validationResult: ValidationResult, + executionResult: TemplateExecutionResult + ): js.Array[VariableDefinition] = { executionResult .getVariables(IdentityType, ExternalSignatureType) - .map({case (_,variable) => variable.name -> variable}) - .toMap.values - .filter(variable => validationResult.missingIdentities.contains(variable.name)) + .map({ case (_, variable) => variable.name -> variable }) + .toMap + .values + .filter(variable => + validationResult.missingIdentities.contains(variable.name) + ) .toJSArray } @JSExport - def isSignatory(email:String, executionResult: TemplateExecutionResult):Boolean = { + def isSignatory( + email: String, + executionResult: TemplateExecutionResult + ): Boolean = { executionResult .getVariableValues[Identity](IdentityType) .getOrThrow() .exists(_.email.email === email) || - executionResult - .getVariableValues[ExternalSignature](ExternalSignatureType) - .getOrThrow() - .exists(_.identity.exists(id => id.email.email === email)) + executionResult + .getVariableValues[ExternalSignature](ExternalSignatureType) + .getOrThrow() + .exists(_.identity.exists(id => id.email.email === email)) } @JSExport - def getSections(document:TemplateExecutionResult):js.Array[String] = document.variableSectionList.toJSArray + def getSections(document: TemplateExecutionResult): js.Array[String] = + document.variableSectionList.toJSArray @JSExport - def getVariableSections(document:TemplateExecutionResult):js.Dictionary[js.Array[String]] = document.sections - .map({case (key,variables) => key -> variables.map(_.name).toJSArray}).toJSDictionary + def getVariableSections( + document: TemplateExecutionResult + ): js.Dictionary[js.Array[String]] = + document.sections + .map({ case (key, variables) => key -> variables.map(_.name).toJSArray }) + .toJSDictionary @JSExport - def isDeal(template:CompiledTemplate):Boolean = template match { - case _:CompiledDeal => true - case _ => false + def isDeal(template: CompiledTemplate): Boolean = template match { + case _: CompiledDeal => true + case _ => false } @JSExport - def isHidden(variableDefinition: VariableDefinition):Boolean = variableDefinition.isHidden + def isHidden(variableDefinition: VariableDefinition): Boolean = + variableDefinition.isHidden @JSExport - def getCollectionSize(variable:VariableDefinition, value:String, executionResult: TemplateExecutionResult):Int = + def getCollectionSize( + variable: VariableDefinition, + value: String, + executionResult: TemplateExecutionResult + ): Int = getCollection(variable, executionResult, value).size @JSExport - def createVariableFromCollection(variable:VariableDefinition, index:Int, executionResult: TemplateExecutionResult):VariableDefinition = + def createVariableFromCollection( + variable: VariableDefinition, + index: Int, + executionResult: TemplateExecutionResult + ): VariableDefinition = variable.varType(executionResult) match { - case collectionType:CollectionType => - VariableDefinition(VariableName(variable.name.name + "_" + index), variableTypeDefinition = Some(VariableTypeDefinition(collectionType.typeParameter.name)), description = Some(getDescription(variable))) + case collectionType: CollectionType => + VariableDefinition( + VariableName(variable.name.name + "_" + index), + variableTypeDefinition = + Some(VariableTypeDefinition(collectionType.typeParameter.name)), + description = Some(getDescription(variable)) + ) case _ => - throw new RuntimeException(s"add element to collection only works for a variable of type Collection, not '${variable.varType(executionResult).name}'") + throw new RuntimeException( + s"add element to collection only works for a variable of type Collection, not '${variable.varType(executionResult).name}'" + ) } @JSExport - def addElementToCollection(variable:VariableDefinition, value:String, executionResult: TemplateExecutionResult):String = { + def addElementToCollection( + variable: VariableDefinition, + value: String, + executionResult: TemplateExecutionResult + ): String = { val collection = getCollection(variable, executionResult, value) - collection.collectionType.internalFormat(collection.copy(size = collection.size + 1)).getOrThrow() + collection.collectionType + .internalFormat(collection.copy(size = collection.size + 1)) + .getOrThrow() } @JSExport - def setElementToCollection(optValue:js.UndefOr[String], index:Int, variable:VariableDefinition, collectionValue:String, executionResult: TemplateExecutionResult): String = { + def setElementToCollection( + optValue: js.UndefOr[String], + index: Int, + variable: VariableDefinition, + collectionValue: String, + executionResult: TemplateExecutionResult + ): String = { val collection = getCollection(variable, executionResult, collectionValue) optValue.toOption match { case Some(value) => - val openlawValue = collection.castValue(value, executionResult).getOrThrow() - val values: Map[Int, OpenlawValue] = collection.values ++ Map(index -> openlawValue) - collection.collectionType.internalFormat(collection.copy(values = values)).getOrThrow() + val openlawValue = + collection.castValue(value, executionResult).getOrThrow() + val values: Map[Int, OpenlawValue] = collection.values ++ Map( + index -> openlawValue + ) + collection.collectionType + .internalFormat(collection.copy(values = values)) + .getOrThrow() case None => - collection.collectionType.internalFormat(collection.copy(values = collection.values - index)).getOrThrow() + collection.collectionType + .internalFormat(collection.copy(values = collection.values - index)) + .getOrThrow() } } @JSExport - def removeElementFromCollection(index:Int, variable:VariableDefinition, executionResult: TemplateExecutionResult, value:String):String = { + def removeElementFromCollection( + index: Int, + variable: VariableDefinition, + executionResult: TemplateExecutionResult, + value: String + ): String = { val collection = getCollection(variable, executionResult, value) val newValues = (collection.values - index).map({ - case (key,v) if key < index => key -> v - case (key,v) => (key - 1) -> v + case (key, v) if key < index => key -> v + case (key, v) => (key - 1) -> v }) - collection.collectionType.internalFormat(collection - .copy(values = newValues, size = Math.max(collection.size - 1, 0)) - ).getOrThrow() + collection.collectionType + .internalFormat( + collection + .copy(values = newValues, size = Math.max(collection.size - 1, 0)) + ) + .getOrThrow() } @JSExport - def getCollectionElementValue(variable:VariableDefinition, executionResult: TemplateExecutionResult, value:String, index:Int):String = { + def getCollectionElementValue( + variable: VariableDefinition, + executionResult: TemplateExecutionResult, + value: String, + index: Int + ): String = { val collection = getCollection(variable, executionResult, value) - collection.values.get(index) + collection.values + .get(index) .map(collection.valueInternalFormat(_).getOrThrow()) .getOrElse("") } @JSExport - def getCollectionValue(variable:VariableDefinition, executionResult: TemplateExecutionResult, value:String):String = { + def getCollectionValue( + variable: VariableDefinition, + executionResult: TemplateExecutionResult, + value: String + ): String = { val collection = getCollection(variable, executionResult, value) - CollectionType(collection.collectionType).internalFormat(collection).getOrThrow() + CollectionType(collection.collectionType) + .internalFormat(collection) + .getOrThrow() } - private def getCollection(variable:VariableDefinition, executionResult: TemplateExecutionResult, value:String):CollectionValue = { + private def getCollection( + variable: VariableDefinition, + executionResult: TemplateExecutionResult, + value: String + ): CollectionValue = { variable.varType(executionResult) match { - case collectionType:CollectionType => - if(value.isEmpty) { + case collectionType: CollectionType => + if (value.isEmpty) { CollectionValue(collectionType = collectionType) } else { - VariableType.convert[CollectionValue](collectionType.cast(value, executionResult).getOrThrow()).getOrThrow() + VariableType + .convert[CollectionValue]( + collectionType.cast(value, executionResult).getOrThrow() + ) + .getOrThrow() } case other => - throw new RuntimeException(s"add element to collection only works for a variable of type Collection, not '${other.name}'") + throw new RuntimeException( + s"add element to collection only works for a variable of type Collection, not '${other.name}'" + ) } } - private def prepareParameters(jsParams:js.Dictionary[Any]):TemplateParameters = { + private def prepareParameters( + jsParams: js.Dictionary[Any] + ): TemplateParameters = { val keys = jsParams.keys.toSeq val dynParams = jsParams.asInstanceOf[js.Dynamic] val params = keys .map(key => key -> dynParams.selectDynamic(key)) - .filter({case (_,value) => !js.isUndefined(value)}) - .map({case (key,value) => VariableName(key) -> value.toString}) + .filter({ case (_, value) => !js.isUndefined(value) }) + .map({ case (key, value) => VariableName(key) -> value.toString }) TemplateParameters(params.toMap) } - private def prepareParagraphs(agreement:StructuredAgreement, jsParagraphs:js.Dictionary[String]):ParagraphEdits = { - if(js.isUndefined(jsParagraphs)){ + private def prepareParagraphs( + agreement: StructuredAgreement, + jsParagraphs: js.Dictionary[String] + ): ParagraphEdits = { + if (js.isUndefined(jsParagraphs)) { ParagraphEdits() - }else{ + } else { val edits = agreement.paragraphs.indices - .flatMap(index => jsParagraphs.get(index.toString).map(index -> _)).toMap + .flatMap(index => jsParagraphs.get(index.toString).map(index -> _)) + .toMap ParagraphEdits(edits) } } - private def prepareTemplates(jsTemplates: js.Dictionary[CompiledTemplate]): Map[TemplateSourceIdentifier, CompiledTemplate] = { - jsTemplates.map({ case (name, template) => TemplateSourceIdentifier(TemplateTitle(name)) -> template}).toMap + private def prepareTemplates( + jsTemplates: js.Dictionary[CompiledTemplate] + ): Map[TemplateSourceIdentifier, CompiledTemplate] = { + jsTemplates + .map({ + case (name, template) => + TemplateSourceIdentifier(TemplateTitle(name)) -> template + }) + .toMap } - private def prepareStructures(externalCallStructures: Dictionary[Any]): Map[ServiceName, IntegratedServiceDefinition] = { + private def prepareStructures( + externalCallStructures: Dictionary[Any] + ): Map[ServiceName, IntegratedServiceDefinition] = { val dynParams = externalCallStructures.asInstanceOf[js.Dynamic] - externalCallStructures - .keys - .toSeq + externalCallStructures.keys.toSeq .map(key => key -> dynParams.selectDynamic(key)) - .filter({case (_,value) => !js.isUndefined(value)}) - .map({case (key,value) => ServiceName(key) -> value.toString}) + .filter({ case (_, value) => !js.isUndefined(value) }) + .map({ case (key, value) => ServiceName(key) -> value.toString }) .toMap .map({ case (serviceName, jsonAbi) => val abi = decode[IntegratedServiceDefinition](jsonAbi).toOption - serviceName -> abi.toResult(s"Missing or invalid abi for external service <$serviceName>, abi: <$jsonAbi>").getOrThrow() + serviceName -> abi + .toResult( + s"Missing or invalid abi for external service <$serviceName>, abi: <$jsonAbi>" + ) + .getOrThrow() }) } }