Compare commits
	
		
			2 commits
		
	
	
		
			cad4c59d51
			...
			42f48fb046
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 42f48fb046 | |||
| 9f74db9857 | 
					 17 changed files with 1983 additions and 133 deletions
				
			
		
							
								
								
									
										1
									
								
								.eslintignore
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.eslintignore
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					build/
 | 
				
			||||||
							
								
								
									
										20
									
								
								.eslintrc.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								.eslintrc.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    "env": {
 | 
				
			||||||
 | 
					        "es2021": true,
 | 
				
			||||||
 | 
					        "node": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "extends": [
 | 
				
			||||||
 | 
					        "eslint:recommended",
 | 
				
			||||||
 | 
					        "plugin:@typescript-eslint/recommended"
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "parser": "@typescript-eslint/parser",
 | 
				
			||||||
 | 
					    "parserOptions": {
 | 
				
			||||||
 | 
					        "ecmaVersion": "latest",
 | 
				
			||||||
 | 
					        "sourceType": "module"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "plugins": [
 | 
				
			||||||
 | 
					        "@typescript-eslint"
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "rules": {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -1,3 +1,3 @@
 | 
				
			||||||
node_modules/
 | 
					node_modules/
 | 
				
			||||||
build/
 | 
					dist/
 | 
				
			||||||
.env
 | 
					.env
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								.prettierignore
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.prettierignore
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					build/
 | 
				
			||||||
							
								
								
									
										19
									
								
								.swcrc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								.swcrc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "jsc": {
 | 
				
			||||||
 | 
					    "parser": {
 | 
				
			||||||
 | 
					      "syntax": "typescript",
 | 
				
			||||||
 | 
					      "tsx": false,
 | 
				
			||||||
 | 
					      "decorators": true,
 | 
				
			||||||
 | 
					      "dynamicImport": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "target": "es2020",
 | 
				
			||||||
 | 
					    "paths": {
 | 
				
			||||||
 | 
					      "~/*": ["./src/*"],
 | 
				
			||||||
 | 
					      "~entities/*": ["./src/db/entities/*"]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "baseUrl": "."
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "module": {
 | 
				
			||||||
 | 
					    "type": "es6"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
					@ -1 +1,21 @@
 | 
				
			||||||
# Mercury
 | 
					# Mercury
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ActivityPub server implementation (hopefully, eventually),
 | 
				
			||||||
 | 
					currently mostly a way for me to play around with writing an API server in TypeScript.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For now, check out `src/config.ts`, the names should be mostly self explanatory.
 | 
				
			||||||
 | 
					Consider all environment variables required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Development commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Building the server: `pnpm build`
 | 
				
			||||||
 | 
					- Migrating the database: `pnpm migrate`
 | 
				
			||||||
 | 
					- Watching for changes and reloading the server automatically: `pnpm dev`
 | 
				
			||||||
 | 
					- Formatting: `pnpm format`
 | 
				
			||||||
 | 
					- Linting (if you don't have an ESLint plugin): `pnpm format`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Mercury is licensed under the GNU Affero General Public License, version 3 **only**.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								package.json
									
										
									
									
									
								
							| 
						 | 
					@ -8,8 +8,12 @@
 | 
				
			||||||
  "license": "AGPL-3.0-only",
 | 
					  "license": "AGPL-3.0-only",
 | 
				
			||||||
  "main": "dist/index.js",
 | 
					  "main": "dist/index.js",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "dev": "nodemon ./src/index.ts",
 | 
					    "dev": "concurrently \"pnpm watch:build\" \"pnpm watch:dev\"",
 | 
				
			||||||
    "build": "tsc",
 | 
					    "build": "swc src -d dist",
 | 
				
			||||||
 | 
					    "watch:build": "swc src -w --out-dir dist",
 | 
				
			||||||
 | 
					    "watch:dev": "nodemon --watch \"dist/**/*\" -e js ./dist/index.js",
 | 
				
			||||||
 | 
					    "format": "prettier -w",
 | 
				
			||||||
 | 
					    "lint": "eslint src/",
 | 
				
			||||||
    "typeorm": "typeorm-ts-node-esm",
 | 
					    "typeorm": "typeorm-ts-node-esm",
 | 
				
			||||||
    "migrate": "typeorm-ts-node-esm migration:run -d ./src/db/index.ts"
 | 
					    "migrate": "typeorm-ts-node-esm migration:run -d ./src/db/index.ts"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
| 
						 | 
					@ -17,6 +21,8 @@
 | 
				
			||||||
    "argon2": "^0.30.3",
 | 
					    "argon2": "^0.30.3",
 | 
				
			||||||
    "dotenv": "^16.3.1",
 | 
					    "dotenv": "^16.3.1",
 | 
				
			||||||
    "express": "^4.18.2",
 | 
					    "express": "^4.18.2",
 | 
				
			||||||
 | 
					    "fastify": "^4.20.0",
 | 
				
			||||||
 | 
					    "glob": "^10.3.3",
 | 
				
			||||||
    "pg": "^8.11.1",
 | 
					    "pg": "^8.11.1",
 | 
				
			||||||
    "reflect-metadata": "^0.1.13",
 | 
					    "reflect-metadata": "^0.1.13",
 | 
				
			||||||
    "tslog": "^4.8.2",
 | 
					    "tslog": "^4.8.2",
 | 
				
			||||||
| 
						 | 
					@ -24,10 +30,16 @@
 | 
				
			||||||
    "ulid": "^2.3.0"
 | 
					    "ulid": "^2.3.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "@swc/cli": "^0.1.62",
 | 
				
			||||||
 | 
					    "@swc/core": "^1.3.70",
 | 
				
			||||||
    "@types/express": "^4.17.17",
 | 
					    "@types/express": "^4.17.17",
 | 
				
			||||||
 | 
					    "@typescript-eslint/eslint-plugin": "^6.1.0",
 | 
				
			||||||
 | 
					    "@typescript-eslint/parser": "^6.1.0",
 | 
				
			||||||
 | 
					    "chokidar": "^3.5.3",
 | 
				
			||||||
 | 
					    "concurrently": "^8.2.0",
 | 
				
			||||||
 | 
					    "eslint": "^8.45.0",
 | 
				
			||||||
    "nodemon": "^3.0.1",
 | 
					    "nodemon": "^3.0.1",
 | 
				
			||||||
    "prettier": "^3.0.0",
 | 
					    "prettier": "^3.0.0",
 | 
				
			||||||
    "ts-node": "^10.9.1",
 | 
					 | 
				
			||||||
    "typescript": "5.1.6"
 | 
					    "typescript": "5.1.6"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1869
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										1869
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -9,3 +9,10 @@ export const DATABASE_PORT = Number(process.env.DATABASE_PORT) || 5432;
 | 
				
			||||||
export const DATABASE_USER = process.env.DATABASE_USER || "postgres";
 | 
					export const DATABASE_USER = process.env.DATABASE_USER || "postgres";
 | 
				
			||||||
export const DATABASE_PASS = process.env.DATABASE_PASS || "postgres";
 | 
					export const DATABASE_PASS = process.env.DATABASE_PASS || "postgres";
 | 
				
			||||||
export const DATABASE_NAME = process.env.DATABASE_NAME || "postgres";
 | 
					export const DATABASE_NAME = process.env.DATABASE_NAME || "postgres";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const HTTPS = process.env.HTTPS === "true";
 | 
				
			||||||
 | 
					export const DOMAIN = process.env.DOMAIN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!DOMAIN) throw "$DOMAIN is empty";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const BASE_URL = `${HTTPS ? "https" : "http"}://${DOMAIN}`;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
import { ulid } from "ulid";
 | 
					import { ulid } from "ulid";
 | 
				
			||||||
import { hash } from "argon2";
 | 
					import { hash } from "argon2";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Account } from "./entities/account.js";
 | 
					import { Account } from "~entities/account.js";
 | 
				
			||||||
import MercuryDataSource from "./index.js";
 | 
					import MercuryDataSource from "./index.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const missingAuthData = new Error("missing auth data for local user");
 | 
					const missingAuthData = new Error("missing auth data for local user");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
import { ulid } from "ulid";
 | 
					import { ulid } from "ulid";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Account } from "./entities/account.js";
 | 
					import { Account } from "~entities/account.js";
 | 
				
			||||||
import { Blog } from "./entities/blog.js";
 | 
					import { Blog } from "~entities/blog.js";
 | 
				
			||||||
import { generateKeyPair } from "./util/rsa.js";
 | 
					import { generateKeyPair } from "./util/rsa.js";
 | 
				
			||||||
import MercuryDataSource from "./index.js";
 | 
					import MercuryDataSource from "./index.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,10 @@
 | 
				
			||||||
import { DataSource } from "typeorm";
 | 
					import { DataSource } from "typeorm";
 | 
				
			||||||
import * as config from "../config.js";
 | 
					import * as config from "~/config.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Entity types
 | 
					// Entity types
 | 
				
			||||||
import { Account } from "./entities/account.js";
 | 
					import { Account } from "~entities/account.js";
 | 
				
			||||||
import { Blog } from "./entities/blog.js";
 | 
					import { Blog } from "~entities/blog.js";
 | 
				
			||||||
import { Post } from "./entities/post.js";
 | 
					import { Post } from "~entities/post.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const MercuryDataSource = new DataSource({
 | 
					const MercuryDataSource = new DataSource({
 | 
				
			||||||
  type: "postgres",
 | 
					  type: "postgres",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
import * as crypto from "node:crypto";
 | 
					import * as crypto from "node:crypto";
 | 
				
			||||||
import * as util from "node:util";
 | 
					import { promisify }from "node:util";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const generate = util.promisify(crypto.generateKeyPair);
 | 
					const generate = promisify(crypto.generateKeyPair);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function generateKeyPair() {
 | 
					export async function generateKeyPair() {
 | 
				
			||||||
  return await generate("rsa", {
 | 
					  return await generate("rsa", {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										31
									
								
								src/routes.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/routes.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					import { dirname, join } from "node:path";
 | 
				
			||||||
 | 
					import { fileURLToPath } from "node:url";
 | 
				
			||||||
 | 
					import { glob } from "glob";
 | 
				
			||||||
 | 
					import type { FastifyInstance, RouteOptions } from "fastify";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import log from "./log.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default async function getRoutes() {
 | 
				
			||||||
 | 
					  const rootDir = dirname(fileURLToPath(import.meta.url));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const routes: RouteOptions[] = [];
 | 
				
			||||||
 | 
					  const matches = await glob(join(rootDir, "/routes/**/*.{js,ts}"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (const filename of matches) {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const mod = await import(filename);
 | 
				
			||||||
 | 
					      routes.push(mod.default as RouteOptions);
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      log.error("Importing route %s", filename, e);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return routes;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function mountRoutes(app: FastifyInstance, routes: RouteOptions[]) {
 | 
				
			||||||
 | 
					  for (const route of routes) {
 | 
				
			||||||
 | 
					    log.trace("Mounting route %s %s", route.method, route.url);
 | 
				
			||||||
 | 
					    app.route(route);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										80
									
								
								src/routes/well-known/webfinger.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/routes/well-known/webfinger.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,80 @@
 | 
				
			||||||
 | 
					import type { FastifyReply, FastifyRequest, RouteOptions } from "fastify";
 | 
				
			||||||
 | 
					import { IsNull } from "typeorm";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import log from "~/log.js";
 | 
				
			||||||
 | 
					import MercuryDataSource from "~/db/index.js";
 | 
				
			||||||
 | 
					import { Blog } from "~entities/blog.js";
 | 
				
			||||||
 | 
					import { BASE_URL } from "~/config.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const route: RouteOptions = {
 | 
				
			||||||
 | 
					  method: "GET",
 | 
				
			||||||
 | 
					  url: "/.well-known/webfinger",
 | 
				
			||||||
 | 
					  handler: async (req, res) => {
 | 
				
			||||||
 | 
					    // TypeScript complains if we just use plain `req.query` :(
 | 
				
			||||||
 | 
					    const encodedResource = (req.query as { resource: string }).resource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!encodedResource || typeof encodedResource !== "string") {
 | 
				
			||||||
 | 
					      res.status(400).send({
 | 
				
			||||||
 | 
					        error: "resource query parameter is missing or invalid",
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const resource = decodeURIComponent(encodedResource);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    log.debug("Handling WebFinger request for %s", resource);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (resource.startsWith("acct:")) {
 | 
				
			||||||
 | 
					      await handleAcctWebfinger(req, res, resource);
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    res.status(500).send({ error: "Unhandled WebFinger resource type" });
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default route;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function handleAcctWebfinger(
 | 
				
			||||||
 | 
					  req: FastifyRequest,
 | 
				
			||||||
 | 
					  res: FastifyReply,
 | 
				
			||||||
 | 
					  resource: string
 | 
				
			||||||
 | 
					): Promise<void> {
 | 
				
			||||||
 | 
					  const [username, domain] = resource.slice("acct:".length).split("@");
 | 
				
			||||||
 | 
					  if (domain !== process.env.DOMAIN) {
 | 
				
			||||||
 | 
					    res.status(404).send({
 | 
				
			||||||
 | 
					      error: "Account not found",
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const blog = await MercuryDataSource.getRepository(Blog).findOneBy({
 | 
				
			||||||
 | 
					    username: username,
 | 
				
			||||||
 | 
					    host: IsNull(),
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  if (!blog) {
 | 
				
			||||||
 | 
					    res.status(404).send({
 | 
				
			||||||
 | 
					      error: "Account not found",
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  res.send({
 | 
				
			||||||
 | 
					    subject: resource,
 | 
				
			||||||
 | 
					    aliases: [
 | 
				
			||||||
 | 
					      `${BASE_URL}/@${blog.username}`,
 | 
				
			||||||
 | 
					      `${BASE_URL}/blogs/${blog.username}`,
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    links: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        rel: "http://webfinger.net/rel/profile-page",
 | 
				
			||||||
 | 
					        type: "text/html",
 | 
				
			||||||
 | 
					        href: `${BASE_URL}/@${blog.username}`,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        rel: "self",
 | 
				
			||||||
 | 
					        type: "application/activity+json",
 | 
				
			||||||
 | 
					        href: `${BASE_URL}/blogs/${blog.username}`,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										22
									
								
								src/start.ts
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								src/start.ts
									
										
									
									
									
								
							| 
						 | 
					@ -1,9 +1,10 @@
 | 
				
			||||||
import "reflect-metadata"; // Required for TypeORM
 | 
					import "reflect-metadata"; // Required for TypeORM
 | 
				
			||||||
import express from "express";
 | 
					import Fastify from "fastify";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import MercuryDataSource from "./db/index.js";
 | 
					import MercuryDataSource from "./db/index.js";
 | 
				
			||||||
import log from "./log.js";
 | 
					import log from "./log.js";
 | 
				
			||||||
import { Blog } from "./db/entities/blog.js";
 | 
					 | 
				
			||||||
import { PORT } from "./config.js";
 | 
					import { PORT } from "./config.js";
 | 
				
			||||||
 | 
					import getRoutes, { mountRoutes } from "./routes.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default async function start() {
 | 
					export default async function start() {
 | 
				
			||||||
  log.info("Initializing database");
 | 
					  log.info("Initializing database");
 | 
				
			||||||
| 
						 | 
					@ -17,17 +18,12 @@ export default async function start() {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  log.debug("Setting up routes")
 | 
					  log.debug("Setting up routes");
 | 
				
			||||||
  const app = express();
 | 
					  const app = Fastify();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  app.get("/", async (_, res) => {
 | 
					  const routes = await getRoutes();
 | 
				
			||||||
    const blogRepository = MercuryDataSource.getRepository(Blog);
 | 
					  mountRoutes(app, routes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const resp = await blogRepository.find();
 | 
					  log.info("Listening on port %d", PORT);
 | 
				
			||||||
 | 
					  await app.listen({ port: PORT });
 | 
				
			||||||
    return res.json(resp)
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  log.info("Listening on port %d", PORT)
 | 
					 | 
				
			||||||
  app.listen(PORT);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,8 +6,7 @@
 | 
				
			||||||
    "rootDir": "./src",
 | 
					    "rootDir": "./src",
 | 
				
			||||||
    "allowJs": true,
 | 
					    "allowJs": true,
 | 
				
			||||||
    "checkJs": true,
 | 
					    "checkJs": true,
 | 
				
			||||||
    "declaration": true,
 | 
					    "declaration": false,
 | 
				
			||||||
    "declarationMap": true,
 | 
					 | 
				
			||||||
    "sourceMap": true,
 | 
					    "sourceMap": true,
 | 
				
			||||||
    "outDir": "./build",
 | 
					    "outDir": "./build",
 | 
				
			||||||
    "esModuleInterop": true,
 | 
					    "esModuleInterop": true,
 | 
				
			||||||
| 
						 | 
					@ -17,5 +16,10 @@
 | 
				
			||||||
    "strict": true,
 | 
					    "strict": true,
 | 
				
			||||||
    "skipLibCheck": true,
 | 
					    "skipLibCheck": true,
 | 
				
			||||||
    "noImplicitAny": false,
 | 
					    "noImplicitAny": false,
 | 
				
			||||||
 | 
					    "baseUrl": "./",
 | 
				
			||||||
 | 
					    "paths": {
 | 
				
			||||||
 | 
					      "~/*": ["./src/*"],
 | 
				
			||||||
 | 
					      "~entities/*": ["./src/db/entities/*"]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue