First commit

This commit is contained in:
2025-01-19 11:07:46 +01:00
commit 8902b17d66
112 changed files with 3476 additions and 0 deletions

51
server/build.gradle.kts Normal file
View File

@@ -0,0 +1,51 @@
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin.Companion.kotlinNodeJsEnvSpec
plugins {
alias(libs.plugins.kotlinJvm)
alias(libs.plugins.ktor)
application
}
group = "org.neutrino.ktans"
version = "1.0.0"
application {
mainClass.set("org.neutrino.ktans.ApplicationKt")
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=${extra["io.ktor.development"] ?: "false"}")
}
dependencies {
implementation(libs.ktor.server.core.jvm)
implementation(libs.ktor.server.netty.jvm)
implementation(libs.ktor.server.netty.jvm)
implementation(libs.kotlinx.serialization.json.jvm)
implementation(libs.kotlinx.serialization.core)
implementation(libs.ktor.server.cors)
implementation(libs.ktor.server.netty)
implementation(libs.ktor.server.core)
implementation(libs.ktor.server.request.validation)
implementation(libs.ktor.server.content.negotiation)
implementation(libs.ktor.serialization.kotlinx.json)
implementation(projects.shared)
implementation(libs.ktor.server.call.logging)
implementation(libs.ktor.server.default.headers)
implementation(libs.ktor.server.websockets)
implementation(libs.kotlin.stdlib)
implementation(libs.kotliquery)
implementation(libs.h2)
implementation(libs.postgresql)
implementation(libs.exposed.core)
implementation(libs.exposed.dao)
implementation(libs.exposed.jdbc)
implementation(libs.exposed.json)
implementation(libs.hikaricp)
implementation(libs.flyway.core)
implementation(libs.logback)
implementation(libs.kformat)
testImplementation(libs.ktor.server.tests)
testImplementation(libs.kotlin.test.junit)
}

View File

@@ -0,0 +1,69 @@
package org.neutrino.ktans
import dao.DictionaryDao
import dao.PronunciationDao
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.netty.*
import io.ktor.server.plugins.calllogging.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.plugins.defaultheaders.*
import io.ktor.server.routing.*
import io.ktor.server.websocket.*
import org.jetbrains.exposed.sql.transactions.transaction
import service.DatabaseFactory
import util.JsonMapper
import web.index
import service.DatabaseFactory.dbExecId
import service.DatabaseFactory.dbExecName
import service.DictTypeService
import service.DictTypeServiceImpl
import service.DictionaryServiceImpl
import service.PronunciationServiceImpl
import service.LanguageServiceImpl
import service.TranslationServiceImpl
import service.TermServiceImpl
import web.dictType
import web.dictionary
import web.pronunciation
import web.language
import web.translation
import web.term
fun Application.module() {
install(DefaultHeaders)
install(CallLogging)
install(ContentNegotiation) {
json(JsonMapper.defaultMapper)
}
DatabaseFactory.connectAndMigrate()
DatabaseFactory.connectAll()
val dictTypeService = DictTypeServiceImpl()
val dictionaryService = DictionaryServiceImpl()
val pronunciationService = PronunciationServiceImpl()
val languageService = LanguageServiceImpl()
val translationService = TranslationServiceImpl()
val termService = TermServiceImpl()
routing {
index()
dictType(dictTypeService)
dictionary(dictionaryService)
pronunciation(pronunciationService)
language(languageService)
translation(translationService,termService)
term(termService)
}
}
fun main(args: Array<String>) {
EngineMain.main(args)
}

View File

@@ -0,0 +1,17 @@
ktor {
deployment {
port = 8080
watch = [ build ]
}
application {
modules = [ org.neutrino.ktans.ApplicationKt.module ]
}
}
h2 {
driver = org.h2.Driver
url = "jdbc:h2:file:./data/%s;DB_CLOSE_DELAY=-1;"
user = "sa"
password = ""
}

View File

@@ -0,0 +1,53 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Kotlin/Ktor/Exposed Starter - It's Working!</title>
<meta name="author" content="Ryan Harrison">
</head>
<body>
<h1 id="it-s-working-">It&#39;s Working!</h1>
<p>This starter project creates a new in-memory H2 database with one table for <code>Widget</code> instances. A simple RESTful interface is provided
to perform CRUD operations on <code>Widgets</code> alongside a websocket to be notified in real-time of any changes.</p>
<h2 id="routes-">Routes:</h2>
<p><code>GET /widgets</code> --&gt; get all widgets in the database</p>
<p><code>GET /widgets/{id}</code> --&gt; get one widget instance by id (integer)</p>
<p><code>POST /widgets</code> --&gt; add a new widget to the database by providing a JSON object (converted to a NewWidget instance).
e.g - </p>
<pre><code>{
<span class="hljs-attr">"name"</span>: <span class="hljs-string">"new widget"</span>,
<span class="hljs-attr">"quantity"</span>: <span class="hljs-number">64</span>
}
</code></pre>
<p>returns</p>
<pre><code>{
<span class="hljs-attr">"id"</span>: <span class="hljs-number">4</span>,
<span class="hljs-attr">"name"</span>: <span class="hljs-string">"new widget"</span>,
<span class="hljs-attr">"quantity"</span>: <span class="hljs-number">64</span>,
<span class="hljs-attr">"dateCreated"</span>: <span class="hljs-number">1519926898</span>
}
</code></pre>
<p><code>PUT /widgets</code> --&gt; update an existing widgets name or quantity. Pass in the id in the JSON request to determine which record to update
</p>
<p><code>DELETE /widgets/{id}</code> --&gt; delete the widget with the specified id</p>
<h2 id="notifications-websocket-">Notifications (WebSocket)</h2>
<p>All updates (creates, updates and deletes) to <code>Widget</code> instances are served as notifications through a WebSocket endpoint:</p>
<p><code>WS /updates</code> --&gt; returns <code>Notification</code> instances containing the change type, id and entity (if applicable) e.g:</p>
<pre><code class="lang-json">{
<span class="hljs-attr">"type"</span>: <span class="hljs-string">"CREATE"</span>,
<span class="hljs-attr">"id"</span>: <span class="hljs-number">12</span>,
<span class="hljs-attr">"entity"</span>: {
<span class="hljs-attr">"id"</span>: <span class="hljs-number">12</span>,
<span class="hljs-attr">"name"</span>: <span class="hljs-string">"widget1"</span>,
<span class="hljs-attr">"quantity"</span>: <span class="hljs-number">5</span>,
<span class="hljs-attr">"dateUpdated"</span>: <span class="hljs-number">1533583858169</span>
}
}
</code></pre>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.eclipse.jetty" level="INFO"/>
<logger name="io.netty" level="INFO"/>
</configuration>