-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ATL-1759] feat(castor): castor services scaffolding (#24)
* feat(castor): create empty scala project * feat(castor): bootstrap castor subprojects * feat(castor): add castor http server subproject * feat(castor): add guardrail openapi codegen * feat(castor): update gitignore * feat(castor): use OpenAPI-Generator for server codegen * feat(castor): update dependencies for openapi codegen * feat(castor): restructor openapi directory * feat(castor): add sample http-server * feat(castor): reorganize actorsystem layer * feat(castor): add template for ApiService generated file * feat(castor): add AkkaZioSupport * feat(castor): add mock resonse and adjust openapi spec * feat(castor): add worker subproject * feat(castor): add DIDApi api group * feat(castor): add DIDOperations api group * feat(castor): add EventConsumer for worker process * feat(castor): re-organize structure to account for grpc module * feat(castor): add grpc dependencies * feat(castor): remove models subproject * feat(castor): add grpc server * feat(castor): format sbt definitions * feat(castor): add grpc services * feat(castor): fix openapi spec unwanted edits * feat(castor): add local docker-compose db and migrations * feat(castor): add repository module * feat(castor): initializing transactorLayer type can fail * feat(castor): change doobie Transactor to use hikari pool
- Loading branch information
Showing
52 changed files
with
1,558 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,3 +10,6 @@ megalinter-reports | |
**/project/metals.sbt | ||
|
||
target | ||
|
||
shell.nix | ||
.envrc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
syntax = "proto3"; | ||
|
||
import "scalapb/scalapb.proto"; | ||
|
||
option (scalapb.options) = { | ||
no_default_values_in_constructor: true | ||
package_name: "io.iohk.atala.castor.proto" | ||
}; | ||
|
||
|
||
message Ping { | ||
string message = 1; | ||
float delaySeconds = 2; | ||
} | ||
|
||
message Pong { | ||
string message = 1; | ||
} | ||
|
||
service DIDService { | ||
rpc SendPing(Ping) returns (Pong) {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# macOS | ||
.DS_Store | ||
|
||
# sbt specific | ||
dist/* | ||
target/ | ||
lib_managed/ | ||
src_managed/ | ||
project/boot/ | ||
project/plugins/project/ | ||
project/local-plugins.sbt | ||
.history | ||
.ensime | ||
.ensime_cache/ | ||
.sbt-scripted/ | ||
local.sbt | ||
|
||
# Bloop | ||
.bsp | ||
|
||
# VS Code | ||
.vscode/ | ||
|
||
# Metals | ||
.bloop/ | ||
.metals/ | ||
metals.sbt | ||
|
||
# IDEA | ||
.idea | ||
.idea_modules | ||
/.worksheet/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
version = 3.5.8 | ||
runner.dialect = scala3 | ||
|
||
maxColumn = 120 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Castor BB service | ||
|
||
## Quickstart | ||
|
||
__Running Castor service locally for development__ | ||
|
||
```bash | ||
docker-compose -f docker/docker-compose-local.yaml up -d | ||
sbt api-server/run | ||
``` |
17 changes: 17 additions & 0 deletions
17
castor/service/api-server/openapi/generator-config/config.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# The folder where templates can be found | ||
templateDir: "api-server/openapi/generator-config/scala-akka-http-server" | ||
|
||
# Only generate output for templates registered with the 'Apis' or 'Models' types | ||
globalProperties: | ||
apis: "" | ||
models: "" | ||
|
||
# Define output packages for generated classes | ||
apiPackage: "io.iohk.atala.castor.openapi.api" | ||
modelPackage: "io.iohk.atala.castor.openapi.model" | ||
|
||
# The generator to use | ||
generatorName: "scala-akka-http-server" | ||
|
||
# Use handwritten classes for the types below. This is useful to customize the (de)serialization | ||
#importMappings: |
32 changes: 32 additions & 0 deletions
32
castor/service/api-server/openapi/generator-config/scala-akka-http-server/README.mustache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# {{&appName}} | ||
|
||
{{&appDescription}} | ||
|
||
{{^hideGenerationTimestamp}} | ||
This Scala akka-http framework project was generated by the OpenAPI generator tool at {{generatedDate}}. | ||
{{/hideGenerationTimestamp}} | ||
|
||
{{#generateApis}} | ||
## API | ||
|
||
{{#apiInfo}} | ||
{{#apis}} | ||
### {{baseName}} | ||
|
||
|Name|Role| | ||
|----|----| | ||
|`{{importPath}}Controller`|akka-http API controller| | ||
|`{{importPath}}Api`|Representing trait| | ||
{{^skipStubs}} | ||
|`{{importPath}}ApiImpl`|Default implementation| | ||
{{/skipStubs}} | ||
|
||
{{#operations}} | ||
{{#operation}} | ||
* `{{httpMethod}} {{contextPath}}{{path}}{{#queryParams.0}}?{{/queryParams.0}}{{#queryParams}}{{paramName}}=[value]{{^-last}}&{{/-last}}{{/queryParams}}` - {{summary}} | ||
{{/operation}} | ||
{{/operations}} | ||
|
||
{{/apis}} | ||
{{/apiInfo}} | ||
{{/generateApis}} |
96 changes: 96 additions & 0 deletions
96
castor/service/api-server/openapi/generator-config/scala-akka-http-server/api.mustache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package {{package}} | ||
|
||
import akka.http.scaladsl.server.Directives._ | ||
import akka.http.scaladsl.server.Route | ||
import akka.http.scaladsl.model.StatusCodes | ||
{{^pathMatcherPatterns.isEmpty}}import akka.http.scaladsl.server.{PathMatcher, PathMatcher1} | ||
{{/pathMatcherPatterns.isEmpty}} | ||
{{#hasMarshalling}}import akka.http.scaladsl.marshalling.ToEntityMarshaller | ||
import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller | ||
import akka.http.scaladsl.unmarshalling.FromStringUnmarshaller | ||
{{/hasMarshalling}} | ||
{{#hasCookieParams}}import akka.http.scaladsl.model.headers.HttpCookiePair | ||
{{/hasCookieParams}} | ||
{{#hasMultipart}}import {{invokerPackage}}.StringDirectives | ||
import {{invokerPackage}}.MultipartDirectives | ||
import {{invokerPackage}}.FileField | ||
import {{invokerPackage}}.PartsAndFiles | ||
{{/hasMultipart}} | ||
{{#imports}}import {{import}} | ||
{{/imports}} | ||
{{#hasMultipart}}import scala.util.Try | ||
import akka.http.scaladsl.server.MalformedRequestContentRejection | ||
import akka.http.scaladsl.server.directives.FileInfo | ||
{{/hasMultipart}} | ||
|
||
|
||
{{#operations}} | ||
class {{classname}}( | ||
{{classVarName}}Service: {{classname}}Service{{#hasMarshalling}}, | ||
{{classVarName}}Marshaller: {{classname}}Marshaller{{/hasMarshalling}} | ||
) {{#hasMultipart}} extends MultipartDirectives with StringDirectives {{/hasMultipart}}{ | ||
{{#pathMatcherPatterns}}import {{classname}}Patterns.{{pathMatcherVarName}} | ||
{{/pathMatcherPatterns}} | ||
|
||
{{#hasMarshalling}}import {{classVarName}}Marshaller._ | ||
{{/hasMarshalling}} | ||
|
||
lazy val route: Route = | ||
{{#operation}} | ||
path({{#vendorExtensions.x-paths}}{{#isText}}"{{/isText}}{{value}}{{#isText}}"{{/isText}}{{^-last}} / {{/-last}}{{/vendorExtensions.x-paths}}) { {{^pathParams.isEmpty}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) => {{/pathParams.isEmpty}} | ||
{{#lambda.lowercase}}{{httpMethod}}{{/lambda.lowercase}} { {{^queryParams.isEmpty}} | ||
parameters({{#queryParams}}"{{baseName}}".as[{{dataType}}]{{^required}}.?{{#vendorExtensions.x-has-default-value}}({{{defaultValue}}}){{/vendorExtensions.x-has-default-value}}{{/required}}{{^-last}}, {{/-last}}{{/queryParams}}) { ({{#queryParams}}{{paramName}}{{^-last}}, {{/-last}}{{/queryParams}}) =>{{/queryParams.isEmpty}} {{^headerParams.isEmpty}} | ||
{{#headerParams}}{{#required}}headerValueByName{{/required}}{{^required}}optionalHeaderValueByName{{/required}}("{{baseName}}") { {{paramName}} => {{/headerParams}}{{/headerParams.isEmpty}}{{^cookieParams.isEmpty}} | ||
{{#cookieParams}}{{#required}}cookie({{/required}}{{^required}}optionalCookie({{/required}}"{{baseName}}"){ {{paramName}} => {{/cookieParams}}{{/cookieParams.isEmpty}}{{#isMultipart}} | ||
{{> multipart}}{{/isMultipart}}{{^isMultipart}}{{> noMultipart}}{{/isMultipart}}{{^cookieParams.isEmpty}} | ||
}{{/cookieParams.isEmpty}}{{^headerParams.isEmpty}} | ||
}{{/headerParams.isEmpty}}{{^queryParams.isEmpty}} | ||
}{{/queryParams.isEmpty}} | ||
} | ||
}{{^-last}} ~{{/-last}} | ||
{{/operation}} | ||
} | ||
|
||
{{^pathMatcherPatterns.isEmpty}} | ||
object {{classname}}Patterns { | ||
{{#pathMatcherPatterns}}val {{pathMatcherVarName}}: PathMatcher1[String] = PathMatcher("{{pattern}}".r) | ||
{{/pathMatcherPatterns}} | ||
} | ||
{{/pathMatcherPatterns.isEmpty}} | ||
|
||
trait {{classname}}Service { | ||
{{#operation}} | ||
{{#responses}} def {{operationId}}{{#vendorExtensions.x-is-default}}Default{{/vendorExtensions.x-is-default}}{{^vendorExtensions.x-is-default}}{{code}}{{/vendorExtensions.x-is-default}}{{#baseType}}({{#vendorExtensions.x-is-default}}statusCode: Int, {{/vendorExtensions.x-is-default}}response{{baseType}}{{containerType}}: {{dataType}})(implicit toEntityMarshaller{{baseType}}{{containerType}}: ToEntityMarshaller[{{dataType}}]){{/baseType}}{{^baseType}}{{#vendorExtensions.x-is-default}}(statusCode: Int){{/vendorExtensions.x-is-default}}{{/baseType}}: Route ={{#vendorExtensions.x-empty-response}} | ||
complete({{#vendorExtensions.x-is-default}}statusCode{{/vendorExtensions.x-is-default}}{{^vendorExtensions.x-is-default}}StatusCodes.getForKey({{code}}){{/vendorExtensions.x-is-default}}){{/vendorExtensions.x-empty-response}}{{^vendorExtensions.x-empty-response}} | ||
complete(({{#vendorExtensions.x-is-default}}statusCode{{/vendorExtensions.x-is-default}}{{^vendorExtensions.x-is-default}}{{code}}{{/vendorExtensions.x-is-default}}, {{#baseType}}response{{baseType}}{{containerType}}{{/baseType}}{{^baseType}}"{{message}}"{{/baseType}})){{/vendorExtensions.x-empty-response}} | ||
{{/responses}} | ||
/** | ||
{{#responses}} * {{#code}}Code: {{.}}{{/code}}{{#message}}, Message: {{.}}{{/message}}{{#dataType}}, DataType: {{.}}{{/dataType}} | ||
{{/responses}} | ||
*/ | ||
def {{operationId}}({{> operationParam}}){{^vendorExtensions.x-specific-marshallers.isEmpty}} | ||
(implicit {{#vendorExtensions.x-specific-marshallers}}toEntityMarshaller{{varName}}: ToEntityMarshaller[{{dataType}}]{{^-last}}, {{/-last}}{{/vendorExtensions.x-specific-marshallers}}){{/vendorExtensions.x-specific-marshallers.isEmpty}}: Route | ||
|
||
{{/operation}} | ||
} | ||
|
||
{{#hasMarshalling}} | ||
trait {{classname}}Marshaller { | ||
{{#entityUnmarshallers}} implicit def fromEntityUnmarshaller{{varName}}: FromEntityUnmarshaller[{{dataType}}] | ||
|
||
{{/entityUnmarshallers}} | ||
|
||
{{#stringUnmarshallers}} implicit def fromStringUnmarshaller{{varName}}: FromStringUnmarshaller[{{dataType}}] | ||
|
||
{{/stringUnmarshallers}} | ||
|
||
{{#entityMarshallers}} implicit def toEntityMarshaller{{varName}}: ToEntityMarshaller[{{dataType}}] | ||
|
||
{{/entityMarshallers}} | ||
} | ||
{{/hasMarshalling}} | ||
|
||
{{/operations}} |
16 changes: 16 additions & 0 deletions
16
castor/service/api-server/openapi/generator-config/scala-akka-http-server/build.sbt.mustache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
version := "{{artifactVersion}}" | ||
name := "{{artifactId}}" | ||
organization := "{{groupId}}" | ||
scalaVersion := "2.12.8" | ||
|
||
val AkkaVersion = "2.6.19" | ||
val AkkaHttpVersion = "10.2.9" | ||
val LogbackVersion = "1.2.11" | ||
|
||
libraryDependencies ++= Seq( | ||
"com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion, | ||
"com.typesafe.akka" %% "akka-stream" % AkkaVersion, | ||
"com.typesafe.akka" %% "akka-http" % AkkaHttpVersion, | ||
"com.typesafe.akka" %% "akka-http-spray-json" % AkkaHttpVersion, | ||
"ch.qos.logback" % "logback-classic" % LogbackVersion % Runtime | ||
) |
15 changes: 15 additions & 0 deletions
15
...or/service/api-server/openapi/generator-config/scala-akka-http-server/controller.mustache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package {{invokerPackage}} | ||
|
||
import akka.actor.typed.ActorSystem | ||
import akka.http.scaladsl.Http | ||
import akka.http.scaladsl.server.Route | ||
{{#apiInfo}}{{#apis}}{{#operations}}import {{package}}.{{classname}} | ||
{{/operations}}{{/apis}}{{/apiInfo}} | ||
import akka.http.scaladsl.server.Directives._ | ||
|
||
class Controller[T]({{#apiInfo}}{{#apis}}{{#operations}}{{classVarName}}: {{classname}}{{^-last}}, {{/-last}}{{/operations}}{{/apis}}{{/apiInfo}})(implicit system: ActorSystem[T]) { | ||
lazy val routes: Route = {{#apiInfo}}{{#apis}}{{#operations}}{{classVarName}}.route {{^-last}}~ {{/-last}}{{/operations}}{{/apis}}{{/apiInfo}} | ||
|
||
Http().newServerAt("0.0.0.0", 9000).bind(routes) | ||
} |
34 changes: 34 additions & 0 deletions
34
castor/service/api-server/openapi/generator-config/scala-akka-http-server/helper.mustache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package {{invokerPackage}} | ||
|
||
import akka.http.scaladsl.server.Directives._ | ||
import akka.http.scaladsl.server.{PathMatcher, PathMatcher1} | ||
import scala.util.{Failure, Success, Try} | ||
import scala.util.control.NoStackTrace | ||
|
||
object AkkaHttpHelper { | ||
def optToTry[T](opt: Option[T], err: => String): Try[T] = | ||
opt.map[Try[T]](Success(_)) getOrElse Failure(new RuntimeException(err) with NoStackTrace) | ||
/** | ||
* A PathMatcher that matches and extracts a Float value. The matched string representation is the pure decimal, | ||
* optionally signed form of a float value, i.e. without exponent. | ||
* | ||
* @group pathmatcher | ||
*/ | ||
val FloatNumber: PathMatcher1[Float] = | ||
PathMatcher("""[+-]?\d*\.?\d*""".r) flatMap { string => | ||
try Some(java.lang.Float.parseFloat(string)) | ||
catch { case _: NumberFormatException => None } | ||
} | ||
|
||
/** | ||
* A PathMatcher that matches and extracts a Boolean value. | ||
* | ||
* @group pathmatcher | ||
*/ | ||
val Boolean: PathMatcher1[Boolean] = | ||
Segment.flatMap { string => | ||
try Some(string.toBoolean) | ||
catch { case _: IllegalArgumentException => None } | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
castor/service/api-server/openapi/generator-config/scala-akka-http-server/model.mustache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package {{package}} | ||
|
||
{{#imports}} | ||
import {{import}} | ||
{{/imports}} | ||
|
||
{{#models}} | ||
{{#model}} | ||
/** | ||
{{#title}} * = {{{.}}} = | ||
* | ||
{{/title}} | ||
{{#description}} * {{{.}}} | ||
* | ||
{{/description}} | ||
{{#vars}} | ||
* @param {{{name}}} {{{description}}}{{#example}} for example: ''{{{.}}}''{{/example}} | ||
{{/vars}} | ||
*/ | ||
final case class {{classname}} ( | ||
{{#vars}} | ||
{{{name}}}: {{^required}}Option[{{/required}}{{datatype}}{{^required}}] = None{{/required}}{{^-last}},{{/-last}} | ||
{{/vars}} | ||
) | ||
|
||
{{/model}} | ||
{{/models}} |
12 changes: 12 additions & 0 deletions
12
castor/service/api-server/openapi/generator-config/scala-akka-http-server/multipart.mustache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
formAndFiles({{#vendorExtensions.x-file-params}}FileField("{{baseName}}")){{/vendorExtensions.x-file-params}}{{^-last}}, {{/-last}} { partsAndFiles => {{^vendorExtensions.x-file-params.isEmpty}} | ||
val _____ : Try[Route] = for { | ||
{{#vendorExtensions.x-file-params}}{{baseName}} <- optToTry(partsAndFiles.files.get("{{baseName}}"), s"File {{baseName}} missing") | ||
{{/vendorExtensions.x-file-params}} | ||
} yield { {{/vendorExtensions.x-file-params.isEmpty}} | ||
implicit val vp: StringValueProvider = partsAndFiles.form{{^vendorExtensions.x-non-file-params.isEmpty}} | ||
stringFields({{#vendorExtensions.x-non-file-params}}"{{baseName}}".as[{{dataType}}]{{^required}}.?{{#vendorExtensions.x-has-default-value}}({{defaultValue}}){{/vendorExtensions.x-has-default-value}}{{/required}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-non-file-params}}) { ({{#vendorExtensions.x-non-file-params}}{{paramName}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-non-file-params}}) =>{{/vendorExtensions.x-non-file-params.isEmpty}} | ||
{{classVarName}}Service.{{operationId}}({{#allParams}}{{paramName}} = {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{^vendorExtensions.nonFileFormParams.isEmpty}} | ||
}{{/vendorExtensions.nonFileFormParams.isEmpty}}{{^vendorExtensions.x-file-params.isEmpty}} | ||
} | ||
_____.fold[Route](t => reject(MalformedRequestContentRejection("Missing file.", t)), identity){{/vendorExtensions.x-file-params.isEmpty}} | ||
} |
Oops, something went wrong.