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