Some progress towards accepting and rejecting follows #3
15 changed files with 315 additions and 133 deletions
18
.vscode/launch.json
vendored
18
.vscode/launch.json
vendored
|
@ -6,9 +6,9 @@
|
|||
"configurations": [
|
||||
{
|
||||
"request": "launch",
|
||||
"name": "Dev Server",
|
||||
"name": "Reinitialize database",
|
||||
"type": "node",
|
||||
"program": "${workspaceFolder}/main.ts",
|
||||
"program": "${workspaceFolder}/src/entry/dbInit.ts",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"envFile": "${workspaceFolder}/local.env",
|
||||
"runtimeExecutable": "/usr/bin/deno",
|
||||
|
@ -17,28 +17,26 @@
|
|||
"--watch",
|
||||
"--no-prompt",
|
||||
"--allow-all",
|
||||
"--inspect-wait",
|
||||
"src/main.ts"
|
||||
"--inspect-wait"
|
||||
],
|
||||
"attachSimplePort": 9229
|
||||
},
|
||||
{
|
||||
|
||||
"request": "launch",
|
||||
"name": "Init database",
|
||||
"name": "Dev Server",
|
||||
"type": "node",
|
||||
"program": "${workspaceFolder}/main.ts",
|
||||
"program": "${workspaceFolder}/src/entry/server.ts",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"envFile": "${workspaceFolder}/local.env",
|
||||
"runtimeExecutable": "/usr/bin/deno",
|
||||
"runtimeArgs": [
|
||||
"run",
|
||||
"--watch",
|
||||
"--no-prompt",
|
||||
"--allow-all",
|
||||
"--inspect-wait",
|
||||
"src/database/init/index.ts"
|
||||
"--inspect-wait"
|
||||
],
|
||||
"attachSimplePort": 9229
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
176
src/database/index.ts
Normal file
176
src/database/index.ts
Normal file
|
@ -0,0 +1,176 @@
|
|||
import Postgres from "@@npm/postgres"
|
||||
import { getLogger } from "@logtape/logtape"
|
||||
import { exportJwk, generateCryptoKeyPair, KvStore } from "@fedify/fedify"
|
||||
import { PostgresKvStore } from "@fedify/postgres/kv"
|
||||
|
||||
|
||||
const l = getLogger(["dotino-veloce", "database", "postgres"])
|
||||
|
||||
|
||||
export type DbActor = {
|
||||
handle: string,
|
||||
public_rsa: JsonWebKey,
|
||||
public_ed: JsonWebKey,
|
||||
private_rsa: JsonWebKey,
|
||||
private_ed: JsonWebKey,
|
||||
}
|
||||
|
||||
export type DbActorService = DbActor
|
||||
|
||||
export type DbActorPlayer = DbActor & {
|
||||
steam_id: bigint,
|
||||
}
|
||||
|
||||
export type DbActorGuild = DbActor & {
|
||||
guild_id: number,
|
||||
}
|
||||
|
||||
|
||||
export class Database {
|
||||
sql: Postgres.Sql
|
||||
|
||||
constructor(connString: string) {
|
||||
l.info`Creating Postgres object with string: ${connString}`
|
||||
this.sql = Postgres(connString)
|
||||
}
|
||||
|
||||
static fromEnv() {
|
||||
l.debug`Getting connection string from environment variable DOTINO_POSTGRES_STRING...`
|
||||
const connString = Deno.env.get("DOTINO_POSTGRES_STRING")
|
||||
if(!connString) {
|
||||
l.error`DOTINO_POSTGRES_STRING is unset.`
|
||||
throw new Error("DOTINO_POSTGRES_STRING is unset.")
|
||||
}
|
||||
|
||||
return new Database(connString)
|
||||
}
|
||||
|
||||
useAsKvStore(): KvStore {
|
||||
l.info`Creating Postgres key-value store...`
|
||||
return new PostgresKvStore(this.sql, {})
|
||||
}
|
||||
|
||||
async #doQueryFile<T>(path: string, variables: Postgres.ParameterOrJSON<any>[] = []): Promise<Postgres.RowList<T[]>> {
|
||||
try {
|
||||
l.debug`Running query at ${path}...`
|
||||
var results = await this.sql.file<T[]>(path, variables, undefined)
|
||||
}
|
||||
catch (e) {
|
||||
l.error`Query at ${path} errored out with: ${e}`
|
||||
throw e
|
||||
}
|
||||
l.debug`Query was successful, results are: ${results}`
|
||||
return results
|
||||
}
|
||||
|
||||
async reinitializeDev() {
|
||||
l.warn`Re-initializing database from scratch for development!!!`
|
||||
|
||||
l.info`01/XX Dropping public schema from database...`
|
||||
await this.#doQueryFile("src/database/init/01-drop-schema.sql")
|
||||
|
||||
l.info`02/XX Recreating public schema...`
|
||||
await this.#doQueryFile("src/database/init/02-create-schema.sql")
|
||||
|
||||
l.info`03/XX Creating applied migrations table...`
|
||||
await this.#doQueryFile("src/database/init/03-create-migration_applied.sql")
|
||||
|
||||
l.info`04/XX Creating actor table...`
|
||||
await this.#doQueryFile("src/database/init/04-create-actor.sql")
|
||||
|
||||
l.info`05/XX Creating service table...`
|
||||
await this.#doQueryFile("src/database/init/05-create-actor_service.sql")
|
||||
|
||||
l.info`06/XX Creating player table...`
|
||||
await this.#doQueryFile("src/database/init/06-create-actor_player.sql")
|
||||
|
||||
l.info`07/XX Creating guild table...`
|
||||
await this.#doQueryFile("src/database/init/07-create-actor_guild.sql")
|
||||
|
||||
l.info`08/XX Creating service actor...`
|
||||
l.debug`Creating RSA key pair...`
|
||||
const {publicKey: publicRsa, privateKey: privateRsa} = await generateCryptoKeyPair("RSASSA-PKCS1-v1_5")
|
||||
l.debug`Creating elliptic curve key pair...`
|
||||
const {publicKey: publicEd, privateKey: privateEd} = await generateCryptoKeyPair("Ed25519")
|
||||
l.debug`Exporting to JWK format...`
|
||||
const publicRsaJwk = await exportJwk(publicRsa)
|
||||
const publicEdJwk = await exportJwk(publicEd)
|
||||
const privateRsaJwk = await exportJwk(privateRsa)
|
||||
const privateEdJwk = await exportJwk(privateEd)
|
||||
l.debug`Running SQL query...`
|
||||
await this.#doQueryFile<DbActorService>(
|
||||
"src/database/init/08-insert-actor_service.sql",
|
||||
[
|
||||
publicRsaJwk,
|
||||
publicEdJwk,
|
||||
privateRsaJwk,
|
||||
privateEdJwk,
|
||||
]
|
||||
)
|
||||
|
||||
l.info("Done!")
|
||||
}
|
||||
|
||||
async getActorService(): Promise<DbActorService> {
|
||||
l.info`Getting service actor entity...`
|
||||
|
||||
const results = await this.#doQueryFile<DbActorService>("src/database/query/get-actor_service.sql")
|
||||
|
||||
if(results.count == 0) {
|
||||
l.error`No service actor entity exists.`
|
||||
throw new Error("No service actor entity exists.")
|
||||
}
|
||||
else if(results.count > 1) {
|
||||
l.error`Multiple service actor entities exist.`
|
||||
throw new Error("Multiple service actor entities exist.")
|
||||
}
|
||||
|
||||
l.debug`Attempting to get only result...`
|
||||
const result = results[0]
|
||||
l.debug`Filtered down to result: ${result}`
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
async getActorPlayer(steamId: number): Promise<DbActorPlayer | null> {
|
||||
l.info`Getting player actor entity with id: ${steamId}`
|
||||
|
||||
const results = await this.#doQueryFile<DbActorPlayer>("src/database/query/get-actor_player.sql", [steamId])
|
||||
|
||||
if(results.count == 0) {
|
||||
l.debug`No such player actor entity exists.`
|
||||
return null
|
||||
}
|
||||
else if(results.count > 1) {
|
||||
l.error`Multiple player actor entities having the same SteamID exist.`
|
||||
throw new Error("Multiple player actor entities having the same SteamID exist.")
|
||||
}
|
||||
|
||||
l.debug`Attempting to get only result...`
|
||||
const result = results[0]
|
||||
l.debug`Filtered down to result: ${result}`
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
async getActorGuild(guildId: number): Promise<DbActorGuild | null> {
|
||||
l.info`Getting guild actor entity with id: ${guildId}`
|
||||
|
||||
const results = await this.#doQueryFile<DbActorGuild>("src/database/query/get-actor_guild.sql", [guildId])
|
||||
|
||||
if(results.count == 0) {
|
||||
l.debug`No such guild actor entity exists.`
|
||||
return null
|
||||
}
|
||||
else if(results.count > 1) {
|
||||
l.error`Multiple guild actor entities having the same Guild ID exist.`
|
||||
throw new Error("Multiple guild actor entities having the same Guild ID exist.")
|
||||
}
|
||||
|
||||
l.debug`Attempting to get only result...`
|
||||
const result = results[0]
|
||||
l.debug`Filtered down to result: ${result}`
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
|
@ -1,9 +1,3 @@
|
|||
CREATE TABLE actor (
|
||||
handle VARCHAR PRIMARY KEY,
|
||||
|
||||
public_rsassa BYTEA NOT NULL,
|
||||
private_rsassa BYTEA NOT NULL,
|
||||
|
||||
public_jwk BYTEA NOT NULL,
|
||||
private_jwk BYTEA NOT NULL
|
||||
handle VARCHAR PRIMARY KEY
|
||||
);
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
CREATE TABLE actor_service (
|
||||
service_id SERIAL UNIQUE NOT NULL
|
||||
public_rsa JSON NOT NULL,
|
||||
public_ed JSON NOT NULL,
|
||||
private_rsa JSON NOT NULL,
|
||||
private_ed JSON NOT NULL
|
||||
) INHERITS (
|
||||
actor
|
||||
);
|
||||
|
|
13
src/database/init/08-insert-actor_service.sql
Normal file
13
src/database/init/08-insert-actor_service.sql
Normal file
|
@ -0,0 +1,13 @@
|
|||
INSERT INTO actor_service (
|
||||
handle,
|
||||
public_rsa,
|
||||
public_ed,
|
||||
private_rsa,
|
||||
private_ed
|
||||
) VALUES (
|
||||
'service',
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4
|
||||
);
|
|
@ -1,41 +0,0 @@
|
|||
import { getLogger } from "https://jsr.io/@logtape/logtape/0.6.3/logtape/logger.ts"
|
||||
import { createPostgresFromEnv } from "../postgres.ts"
|
||||
import { initLogging } from "../../deno/logging.ts"
|
||||
|
||||
|
||||
const l = getLogger(["dotino-veloce", "database", "init"])
|
||||
|
||||
|
||||
async function main() {
|
||||
await initLogging()
|
||||
|
||||
l.debug`Creating Postgres instance...`
|
||||
const postgres = createPostgresFromEnv()
|
||||
|
||||
l.info`01/XX Dropping public schema from database...`
|
||||
await postgres.file("src/database/init/01-drop-schema.sql")
|
||||
|
||||
l.info`02/XX Recreating public schema...`
|
||||
await postgres.file("src/database/init/02-create-schema.sql")
|
||||
|
||||
l.info`03/XX Creating applied migrations table...`
|
||||
await postgres.file("src/database/init/03-create-migration_applied.sql")
|
||||
|
||||
l.info`04/XX Creating actor table...`
|
||||
await postgres.file("src/database/init/04-create-actor.sql")
|
||||
|
||||
l.info`05/XX Creating service table...`
|
||||
await postgres.file("src/database/init/05-create-actor_service.sql")
|
||||
|
||||
l.info`06/XX Creating player table...`
|
||||
await postgres.file("src/database/init/06-create-actor_player.sql")
|
||||
|
||||
l.info`07/XX Creating guild table...`
|
||||
await postgres.file("src/database/init/07-create-actor_guild.sql")
|
||||
|
||||
l.info("Done!")
|
||||
Deno.exit(0)
|
||||
}
|
||||
|
||||
|
||||
await main()
|
|
@ -1,12 +0,0 @@
|
|||
import { PostgresKvStore } from "@fedify/postgres/kv"
|
||||
import { getLogger } from "@logtape/logtape"
|
||||
import Postgres from "@@npm/postgres"
|
||||
|
||||
|
||||
const l = getLogger(["dotino-veloce", "database", "kv"])
|
||||
|
||||
|
||||
export function createPostgresKvStore(postgres: Postgres.Sql): PostgresKvStore {
|
||||
l.info`Creating Postgres key-value store...`
|
||||
return new PostgresKvStore(postgres, {})
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
import Postgres from "@@npm/postgres"
|
||||
import { getLogger } from "@logtape/logtape"
|
||||
|
||||
|
||||
const l = getLogger(["dotino-veloce", "database", "postgres"])
|
||||
|
||||
|
||||
export function createPostgres(connString: string): Postgres.Sql {
|
||||
l.info`Creating Postgres object with string: ${connString}`
|
||||
return Postgres(connString)
|
||||
}
|
||||
|
||||
export function createPostgresFromEnv(): Postgres.Sql {
|
||||
l.debug`Getting connection string from environment variable DOTINO_POSTGRES_STRING...`
|
||||
const connString = Deno.env.get("DOTINO_POSTGRES_STRING")
|
||||
if(!connString) {
|
||||
l.error`DOTINO_POSTGRES_STRING is unset.`
|
||||
throw new Error("DOTINO_POSTGRES_STRING is unset.")
|
||||
}
|
||||
|
||||
return createPostgres(connString)
|
||||
}
|
12
src/database/query/get-actor_guild.sql
Normal file
12
src/database/query/get-actor_guild.sql
Normal file
|
@ -0,0 +1,12 @@
|
|||
SELECT
|
||||
actor_guild.handle,
|
||||
actor_guild.guild_id,
|
||||
actor_service.public_rsa,
|
||||
actor_service.public_ed,
|
||||
actor_service.private_rsa,
|
||||
actor_service.private_ed
|
||||
FROM
|
||||
actor_guild,
|
||||
actor_service
|
||||
WHERE
|
||||
actor_guild.steam_id = $1;
|
12
src/database/query/get-actor_player.sql
Normal file
12
src/database/query/get-actor_player.sql
Normal file
|
@ -0,0 +1,12 @@
|
|||
SELECT
|
||||
actor_player.handle,
|
||||
actor_player.steam_id,
|
||||
actor_service.public_rsa,
|
||||
actor_service.public_ed,
|
||||
actor_service.private_rsa,
|
||||
actor_service.private_ed
|
||||
FROM
|
||||
actor_player,
|
||||
actor_service
|
||||
WHERE
|
||||
actor_player.steam_id = $1;
|
8
src/database/query/get-actor_service.sql
Normal file
8
src/database/query/get-actor_service.sql
Normal file
|
@ -0,0 +1,8 @@
|
|||
SELECT
|
||||
actor_service.handle,
|
||||
actor_service.public_rsa,
|
||||
actor_service.public_ed,
|
||||
actor_service.private_rsa,
|
||||
actor_service.private_ed
|
||||
FROM
|
||||
actor_service;
|
|
@ -1,8 +1,9 @@
|
|||
// deno-lint-ignore-file require-await
|
||||
import { createFederation, Person, Application, Image, PropertyValue, Organization, Federation, KvStore, Context, Actor, Follow, Endpoints } from "@fedify/fedify"
|
||||
import { createFederation, Person, Application, Image, PropertyValue, Organization, Federation, KvStore, Context, Actor, Follow, Endpoints, importSpki, importJwk } from "@fedify/fedify"
|
||||
import { getLogger } from "https://jsr.io/@logtape/logtape/0.6.3/logtape/logger.ts"
|
||||
import { escapeHtml } from "@@x/escape"
|
||||
import { StratzAPI } from "../stratz/api.ts"
|
||||
import { Database } from "../database/index.ts"
|
||||
|
||||
|
||||
const l = getLogger(["dotino-veloce", "ap", "federation"])
|
||||
|
@ -12,39 +13,39 @@ type ContextData = undefined
|
|||
|
||||
|
||||
export class DotinoVeloce {
|
||||
db: Database
|
||||
stratz: StratzAPI
|
||||
federation: Federation<ContextData>
|
||||
|
||||
constructor(kv: KvStore, stratz: StratzAPI) {
|
||||
constructor(db: Database, stratz: StratzAPI) {
|
||||
this.db = db
|
||||
this.stratz = stratz
|
||||
|
||||
this.federation = createFederation<ContextData>({ kv })
|
||||
this.federation = createFederation<ContextData>({ kv: db.useAsKvStore() })
|
||||
|
||||
this.federation
|
||||
.setActorDispatcher("/users/{identifier}", this.#actorHandler.bind(this))
|
||||
.setKeyPairsDispatcher(this.#actorKeys.bind(this))
|
||||
.mapHandle(this.#actorMapper.bind(this))
|
||||
// .setKeyPairsDispatcher(this.#actorKeys.bind(this))
|
||||
|
||||
this.federation
|
||||
.setInboxListeners("/inbox/{identifier}", "/inbox")
|
||||
.on(Follow, this.#followHandler.bind(this))
|
||||
}
|
||||
|
||||
#commonActorProperties(ctx: Context<ContextData>, handle: string): Partial<Actor> {
|
||||
async #commonActorProperties(ctx: Context<ContextData>, handle: string): Promise<Partial<Actor>> {
|
||||
l.debug`Generating common actor properties for ${handle}...`
|
||||
const properties = {
|
||||
preferredUsername: handle,
|
||||
id: ctx.getActorUri(handle),
|
||||
publicKeys: (await ctx.getActorKeyPairs(handle)).map(keyPair => keyPair.cryptographicKey),
|
||||
assertionMethods: (await ctx.getActorKeyPairs(handle)).map(keyPair => keyPair.multikey),
|
||||
// Akkoma requires inboxes to be setup to display profiles
|
||||
// https://akkoma.dev/AkkomaGang/akkoma/src/commit/f1018867097e6f293d8b2b5b6935f0a7ebf99bd0/lib/pleroma/web/activity_pub/object_validators/user_validator.ex#L72
|
||||
inbox: ctx.getInboxUri(handle),
|
||||
endpoints: new Endpoints({
|
||||
sharedInbox: ctx.getInboxUri(),
|
||||
}),
|
||||
preferredUsername: handle,
|
||||
// Akkoma expects URL to be equal to ID
|
||||
// Or does it? This makes no sense to me...
|
||||
// https://akkoma.dev/AkkomaGang/akkoma/src/commit/f1018867097e6f293d8b2b5b6935f0a7ebf99bd0/lib/pleroma/object/fetcher.ex#L287
|
||||
// url: id,
|
||||
// Akkoma requires inboxes to be setup to display profiles
|
||||
// https://akkoma.dev/AkkomaGang/akkoma/src/commit/f1018867097e6f293d8b2b5b6935f0a7ebf99bd0/lib/pleroma/web/activity_pub/object_validators/user_validator.ex#L72
|
||||
}
|
||||
l.debug`Generated common actor properties for ${handle}: ${properties}`
|
||||
return properties
|
||||
|
@ -79,7 +80,7 @@ export class DotinoVeloce {
|
|||
|
||||
l.debug`Generating ActivityPub actor for player ${steamId}...`
|
||||
const actor = new Person({
|
||||
...this.#commonActorProperties(ctx, handle),
|
||||
...(await this.#commonActorProperties(ctx, handle)),
|
||||
|
||||
name: `[TEST] ${escapeHtml(player.name)}`,
|
||||
icon: new Image({
|
||||
|
@ -140,7 +141,7 @@ export class DotinoVeloce {
|
|||
|
||||
l.debug`Generating ActivityPub actor for guild ${guildId}...`
|
||||
const actor = new Organization({
|
||||
...this.#commonActorProperties(ctx, handle),
|
||||
...(await this.#commonActorProperties(ctx, handle)),
|
||||
|
||||
name: `[TEST] ${escapeHtml(guild.name)}`,
|
||||
summary: escapeHtml(guild.description),
|
||||
|
@ -181,7 +182,7 @@ export class DotinoVeloce {
|
|||
|
||||
l.debug`Generating ActivityPub actor for service...`
|
||||
const actor = new Application({
|
||||
...this.#commonActorProperties(ctx, handle),
|
||||
...(await this.#commonActorProperties(ctx, handle)),
|
||||
|
||||
name: "[TEST] Dotino Veloce",
|
||||
summary: "Service account of a Dotino Veloce instance.",
|
||||
|
@ -210,11 +211,41 @@ export class DotinoVeloce {
|
|||
}
|
||||
|
||||
async #actorMapper(_ctx: Context<ContextData>, handle: string): Promise<string> {
|
||||
l.debug`Getting handle mapping for: ${handle}`
|
||||
return handle
|
||||
}
|
||||
|
||||
async #actorKeys(ctx: Context<ContextData>, handle: string): Promise<CryptoKeyPair[]> {
|
||||
throw "TODO: Not implemented"
|
||||
async #actorKeys(_ctx: Context<ContextData>, handle: string): Promise<CryptoKeyPair[]> {
|
||||
l.debug`Getting keys for: ${handle}`
|
||||
|
||||
l.debug`Requesting keys from the database...`
|
||||
const {
|
||||
public_rsa: publicRsaJwk,
|
||||
public_ed: publicEdJwk,
|
||||
private_rsa: privateRsaJwk,
|
||||
private_ed: privateEdJwk,
|
||||
} = await this.db.getActorService()
|
||||
|
||||
l.debug`Importing keys from JWK format...`
|
||||
const publicRsa = await importJwk(publicRsaJwk, "public")
|
||||
const publicEd = await importJwk(publicEdJwk, "public")
|
||||
const privateRsa = await importJwk(privateRsaJwk, "private")
|
||||
const privateEd = await importJwk(privateEdJwk, "private")
|
||||
|
||||
l.debug`Bundling keys...`
|
||||
const result = [
|
||||
{
|
||||
publicKey: publicRsa,
|
||||
privateKey: privateRsa,
|
||||
},
|
||||
{
|
||||
publicKey: publicEd,
|
||||
privateKey: privateEd,
|
||||
}
|
||||
]
|
||||
l.debug`Bundled keys are: ${result}`
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
async #followHandler(ctx: Context<ContextData>, follow: Follow) {
|
||||
|
|
12
src/entry/dbInit.ts
Normal file
12
src/entry/dbInit.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Database } from "../database/index.ts"
|
||||
import { initLogging } from "../deno/logging.ts"
|
||||
|
||||
|
||||
async function main() {
|
||||
await initLogging()
|
||||
const db = Database.fromEnv()
|
||||
await db.reinitializeDev()
|
||||
}
|
||||
|
||||
|
||||
main()
|
21
src/entry/server.ts
Normal file
21
src/entry/server.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { doServe } from "../deno/server.ts"
|
||||
import { initLogging } from "../deno/logging.ts"
|
||||
import { StratzAPI } from "../stratz/api.ts"
|
||||
import { behindProxy, Fetch } from "@hongminhee/x-forwarded-fetch"
|
||||
import { createRouter } from "../deno/router.ts"
|
||||
import { DotinoVeloce } from "../dv/dotinoVeloce.ts"
|
||||
import { Database } from "../database/index.ts"
|
||||
|
||||
|
||||
async function main() {
|
||||
await initLogging()
|
||||
const db = Database.fromEnv()
|
||||
const stratz = StratzAPI.fromEnv()
|
||||
const ap = new DotinoVeloce(db, stratz)
|
||||
const router = createRouter(ap)
|
||||
const routerBehindProxy = behindProxy(router as Fetch)
|
||||
await doServe(routerBehindProxy)
|
||||
}
|
||||
|
||||
|
||||
main()
|
23
src/main.ts
23
src/main.ts
|
@ -1,23 +0,0 @@
|
|||
import { doServe } from "./deno/server.ts"
|
||||
import { initLogging } from "./deno/logging.ts"
|
||||
import { StratzAPI } from "./stratz/api.ts"
|
||||
import { behindProxy, Fetch } from "@hongminhee/x-forwarded-fetch"
|
||||
import { createRouter } from "./deno/router.ts"
|
||||
import { DotinoVeloce } from "./dv/dotinoVeloce.ts"
|
||||
import { createPostgresKvStore } from "./database/kv.ts"
|
||||
import { createPostgresFromEnv } from "./database/postgres.ts"
|
||||
|
||||
|
||||
async function main() {
|
||||
await initLogging()
|
||||
const postgres = createPostgresFromEnv()
|
||||
const kv = createPostgresKvStore(postgres)
|
||||
const stratz = StratzAPI.fromEnv()
|
||||
const ap = new DotinoVeloce(kv, stratz)
|
||||
const router = createRouter(ap)
|
||||
const routerBehindProxy = behindProxy(router as Fetch)
|
||||
await doServe(routerBehindProxy)
|
||||
}
|
||||
|
||||
|
||||
main()
|
Loading…
Reference in a new issue