Compare commits
	
		
			No commits in common. "42f48fb0468408b1da11aea9dbb1fe49ff535c7e" and "cad4c59d51f7ca67a1f15d546a3b859bc93b9532" have entirely different histories.
		
	
	
		
			42f48fb046
			...
			cad4c59d51
		
	
		
					 17 changed files with 132 additions and 1982 deletions
				
			
		| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
build/
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,20 +0,0 @@
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    "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/
 | 
				
			||||||
dist/
 | 
					build/
 | 
				
			||||||
.env
 | 
					.env
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
build/
 | 
					 | 
				
			||||||
							
								
								
									
										19
									
								
								.swcrc
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								.swcrc
									
										
									
									
									
								
							| 
						 | 
					@ -1,19 +0,0 @@
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  "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,21 +1 @@
 | 
				
			||||||
# 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,12 +8,8 @@
 | 
				
			||||||
  "license": "AGPL-3.0-only",
 | 
					  "license": "AGPL-3.0-only",
 | 
				
			||||||
  "main": "dist/index.js",
 | 
					  "main": "dist/index.js",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "dev": "concurrently \"pnpm watch:build\" \"pnpm watch:dev\"",
 | 
					    "dev": "nodemon ./src/index.ts",
 | 
				
			||||||
    "build": "swc src -d dist",
 | 
					    "build": "tsc",
 | 
				
			||||||
    "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"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
| 
						 | 
					@ -21,8 +17,6 @@
 | 
				
			||||||
    "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",
 | 
				
			||||||
| 
						 | 
					@ -30,16 +24,10 @@
 | 
				
			||||||
    "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"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1867
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										1867
									
								
								pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -9,10 +9,3 @@ 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 { promisify }from "node:util";
 | 
					import * as util from "node:util";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const generate = promisify(crypto.generateKeyPair);
 | 
					const generate = util.promisify(crypto.generateKeyPair);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function generateKeyPair() {
 | 
					export async function generateKeyPair() {
 | 
				
			||||||
  return await generate("rsa", {
 | 
					  return await generate("rsa", {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,31 +0,0 @@
 | 
				
			||||||
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);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,80 +0,0 @@
 | 
				
			||||||
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,10 +1,9 @@
 | 
				
			||||||
import "reflect-metadata"; // Required for TypeORM
 | 
					import "reflect-metadata"; // Required for TypeORM
 | 
				
			||||||
import Fastify from "fastify";
 | 
					import express from "express";
 | 
				
			||||||
 | 
					 | 
				
			||||||
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");
 | 
				
			||||||
| 
						 | 
					@ -18,12 +17,17 @@ export default async function start() {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  log.debug("Setting up routes");
 | 
					  log.debug("Setting up routes")
 | 
				
			||||||
  const app = Fastify();
 | 
					  const app = express();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const routes = await getRoutes();
 | 
					  app.get("/", async (_, res) => {
 | 
				
			||||||
  mountRoutes(app, routes);
 | 
					    const blogRepository = MercuryDataSource.getRepository(Blog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  log.info("Listening on port %d", PORT);
 | 
					    const resp = await blogRepository.find();
 | 
				
			||||||
  await app.listen({ port: PORT });
 | 
					
 | 
				
			||||||
 | 
					    return res.json(resp)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  log.info("Listening on port %d", PORT)
 | 
				
			||||||
 | 
					  app.listen(PORT);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,8 @@
 | 
				
			||||||
    "rootDir": "./src",
 | 
					    "rootDir": "./src",
 | 
				
			||||||
    "allowJs": true,
 | 
					    "allowJs": true,
 | 
				
			||||||
    "checkJs": true,
 | 
					    "checkJs": true,
 | 
				
			||||||
    "declaration": false,
 | 
					    "declaration": true,
 | 
				
			||||||
 | 
					    "declarationMap": true,
 | 
				
			||||||
    "sourceMap": true,
 | 
					    "sourceMap": true,
 | 
				
			||||||
    "outDir": "./build",
 | 
					    "outDir": "./build",
 | 
				
			||||||
    "esModuleInterop": true,
 | 
					    "esModuleInterop": true,
 | 
				
			||||||
| 
						 | 
					@ -16,10 +17,5 @@
 | 
				
			||||||
    "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