init
This commit is contained in:
commit
dfcb6667ed
16 changed files with 2453 additions and 0 deletions
11
src/config.ts
Normal file
11
src/config.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { config as dotenv } from "dotenv";
|
||||
|
||||
dotenv();
|
||||
|
||||
export const PORT = Number(process.env.PORT) || 3000;
|
||||
|
||||
export const DATABASE_HOST = process.env.DATABASE_HOST || "localhost";
|
||||
export const DATABASE_PORT = Number(process.env.DATABASE_PORT) || 5432;
|
||||
export const DATABASE_USER = process.env.DATABASE_USER || "postgres";
|
||||
export const DATABASE_PASS = process.env.DATABASE_PASS || "postgres";
|
||||
export const DATABASE_NAME = process.env.DATABASE_NAME || "postgres";
|
21
src/db/entities/account.ts
Normal file
21
src/db/entities/account.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { Entity, Column, PrimaryColumn, Index, OneToMany } from "typeorm";
|
||||
import { Blog } from "./blog.js";
|
||||
|
||||
@Entity()
|
||||
@Index(["username", "host"], { unique: true })
|
||||
export class Account {
|
||||
@PrimaryColumn("text")
|
||||
id: string;
|
||||
@Column("text", { nullable: false })
|
||||
username: string;
|
||||
@Column("text", { nullable: true })
|
||||
host: string | null;
|
||||
|
||||
@Column("text", { nullable: true, unique: true })
|
||||
email: string | null;
|
||||
@Column("text", { nullable: true })
|
||||
password: string | null;
|
||||
|
||||
@OneToMany(() => Blog, (blog) => blog.account)
|
||||
blogs: Blog[];
|
||||
}
|
31
src/db/entities/blog.ts
Normal file
31
src/db/entities/blog.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import {
|
||||
Entity,
|
||||
Column,
|
||||
PrimaryColumn,
|
||||
Index,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
} from "typeorm";
|
||||
import { Account } from "./account.js";
|
||||
import { Post } from "./post.js";
|
||||
|
||||
@Entity()
|
||||
@Index(["username", "host"], { unique: true })
|
||||
export class Blog {
|
||||
@PrimaryColumn("text")
|
||||
id: string;
|
||||
@Column("text", { nullable: false })
|
||||
username: string;
|
||||
@Column("text", { nullable: true })
|
||||
host: string | null;
|
||||
|
||||
@ManyToOne(() => Account, (account) => account.blogs)
|
||||
account: Account;
|
||||
@OneToMany(() => Post, (post) => post.blog)
|
||||
posts: Post[];
|
||||
|
||||
@Column("text", { nullable: false })
|
||||
publicKey: string;
|
||||
@Column("text", { nullable: true })
|
||||
privateKey: string | null;
|
||||
}
|
15
src/db/entities/post.ts
Normal file
15
src/db/entities/post.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Entity, Column, PrimaryColumn, ManyToOne } from "typeorm";
|
||||
import { Blog } from "./blog.js";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
@PrimaryColumn("text")
|
||||
id: string;
|
||||
@Column("text", { nullable: true })
|
||||
content: string | null;
|
||||
@Column("text", { nullable: true })
|
||||
contentType: string | null;
|
||||
|
||||
@ManyToOne(() => Blog, (blog) => blog.posts)
|
||||
blog: Blog;
|
||||
}
|
20
src/db/index.ts
Normal file
20
src/db/index.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { DataSource } from "typeorm";
|
||||
import * as config from "../config.js";
|
||||
|
||||
// Entity types
|
||||
import { Account } from "./entities/account.js";
|
||||
import { Blog } from "./entities/blog.js";
|
||||
import { Post } from "./entities/post.js";
|
||||
|
||||
const MercuryDataSource = new DataSource({
|
||||
type: "postgres",
|
||||
host: config.DATABASE_HOST,
|
||||
port: config.DATABASE_PORT,
|
||||
username: config.DATABASE_USER,
|
||||
password: config.DATABASE_PASS,
|
||||
database: config.DATABASE_NAME,
|
||||
entities: [Account, Blog, Post],
|
||||
migrations: ["src/db/migrations/*.js"],
|
||||
});
|
||||
|
||||
export default MercuryDataSource;
|
76
src/db/migrations/1689867206797-init.js
Normal file
76
src/db/migrations/1689867206797-init.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
export class Init1689867206797 {
|
||||
name = 'Init1689867206797'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE "post" (
|
||||
"id" text NOT NULL,
|
||||
"content" text,
|
||||
"contentType" text,
|
||||
"blogId" text,
|
||||
CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id")
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE "blog" (
|
||||
"id" text NOT NULL,
|
||||
"username" text NOT NULL,
|
||||
"host" text,
|
||||
"publicKey" text NOT NULL,
|
||||
"privateKey" text,
|
||||
"accountId" text,
|
||||
CONSTRAINT "PK_85c6532ad065a448e9de7638571" PRIMARY KEY ("id")
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE UNIQUE INDEX "IDX_20609d68760ccd572e82155a84" ON "blog" ("username", "host")
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE "account" (
|
||||
"id" text NOT NULL,
|
||||
"username" text NOT NULL,
|
||||
"host" text,
|
||||
"email" text,
|
||||
"password" text,
|
||||
CONSTRAINT "UQ_4c8f96ccf523e9a3faefd5bdd4c" UNIQUE ("email"),
|
||||
CONSTRAINT "PK_54115ee388cdb6d86bb4bf5b2ea" PRIMARY KEY ("id")
|
||||
)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE UNIQUE INDEX "IDX_0d4f7bfab65220a2aac213407b" ON "account" ("username", "host")
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "post"
|
||||
ADD CONSTRAINT "FK_d0418ddc42c5707dbc37b05bef9" FOREIGN KEY ("blogId") REFERENCES "blog"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "blog"
|
||||
ADD CONSTRAINT "FK_9dd44887bd917f9ee76aff90a02" FOREIGN KEY ("accountId") REFERENCES "account"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
|
||||
`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "blog" DROP CONSTRAINT "FK_9dd44887bd917f9ee76aff90a02"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "post" DROP CONSTRAINT "FK_d0418ddc42c5707dbc37b05bef9"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
DROP INDEX "public"."IDX_0d4f7bfab65220a2aac213407b"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
DROP TABLE "account"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
DROP INDEX "public"."IDX_20609d68760ccd572e82155a84"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
DROP TABLE "blog"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
DROP TABLE "post"
|
||||
`);
|
||||
}
|
||||
|
||||
}
|
3
src/index.ts
Normal file
3
src/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import start from "./start.js";
|
||||
|
||||
start();
|
5
src/log.ts
Normal file
5
src/log.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { Logger, ILogObj } from "tslog";
|
||||
|
||||
const log: Logger<ILogObj> = new Logger();
|
||||
|
||||
export default log;
|
33
src/start.ts
Normal file
33
src/start.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import "reflect-metadata"; // Required for TypeORM
|
||||
import express from "express";
|
||||
import MercuryDataSource from "./db/index.js";
|
||||
import log from "./log.js";
|
||||
import { Blog } from "./db/entities/blog.js";
|
||||
import { PORT } from "./config.js";
|
||||
|
||||
export default async function start() {
|
||||
log.info("Initializing database");
|
||||
await MercuryDataSource.initialize();
|
||||
|
||||
const pendingMigrations = await MercuryDataSource.showMigrations();
|
||||
if (pendingMigrations) {
|
||||
log.error(
|
||||
"There are pending migrations, please run these with `pnpm migrate`."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("Setting up routes")
|
||||
const app = express();
|
||||
|
||||
app.get("/", async (_, res) => {
|
||||
const blogRepository = MercuryDataSource.getRepository(Blog);
|
||||
|
||||
const resp = await blogRepository.find();
|
||||
|
||||
return res.json(resp)
|
||||
})
|
||||
|
||||
log.info("Listening on port %d", PORT)
|
||||
app.listen(PORT);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue