Finish full rewrite of server and testing systems

This commit is contained in:
Jesse Wierzbinski 2024-03-10 16:04:14 -10:00
parent 0e4d6b401c
commit 0541776d3d
No known key found for this signature in database
32 changed files with 1168 additions and 916 deletions

View file

@ -14,7 +14,7 @@ export const convertTextToHtml = async (
content_type?: string
) => {
if (content_type === "text/markdown") {
return linkifyHtml(await sanitizeHtml(parse(text)));
return linkifyHtml(await sanitizeHtml(await parse(text)));
} else if (content_type === "text/x.misskeymarkdown") {
// Parse as MFM
// TODO: Implement MFM

View file

@ -1,17 +1,18 @@
import { getConfig } from "~classes/configmanager";
import chalk from "chalk";
import { client } from "~database/datasource";
import { Meilisearch } from "meilisearch";
import type { Status, User } from "@prisma/client";
import { ConfigManager } from "config-manager";
import { LogLevel, type LogManager, type MultiLogManager } from "log-manager";
const config = getConfig();
const config = await new ConfigManager({}).getConfig();
export const meilisearch = new Meilisearch({
host: `${config.meilisearch.host}:${config.meilisearch.port}`,
apiKey: config.meilisearch.api_key,
});
export const connectMeili = async () => {
export const connectMeili = async (logger: MultiLogManager | LogManager) => {
if (!config.meilisearch.enabled) return;
if (await meilisearch.isHealthy()) {
@ -31,14 +32,16 @@ export const connectMeili = async () => {
.index(MeiliIndexType.Statuses)
.updateSearchableAttributes(["content"]);
console.log(
`${chalk.green(``)} ${chalk.bold(`Connected to Meilisearch`)}`
await logger.log(
LogLevel.INFO,
"Meilisearch",
"Connected to Meilisearch"
);
} else {
console.error(
`${chalk.red(``)} ${chalk.bold(
`Error while connecting to Meilisearch`
)}`
await logger.log(
LogLevel.CRITICAL,
"Meilisearch",
"Error while connecting to Meilisearch"
);
process.exit(1);
}

31
utils/module.ts Normal file
View file

@ -0,0 +1,31 @@
import { fileURLToPath } from "url";
/**
* Determines whether a module is the entry point for the running node process.
* This works for both CommonJS and ES6 environments.
*
* ### CommonJS
* ```js
* if (moduleIsEntry(module)) {
* console.log('WOO HOO!!!');
* }
* ```
*
* ### ES6
* ```js
* if (moduleIsEntry(import.meta.url)) {
* console.log('WOO HOO!!!');
* }
* ```
*/
export const moduleIsEntry = (moduleOrImportMetaUrl: NodeModule | string) => {
if (typeof moduleOrImportMetaUrl === "string") {
return process.argv[1] === fileURLToPath(moduleOrImportMetaUrl);
}
if (typeof require !== "undefined" && "exports" in moduleOrImportMetaUrl) {
return require.main === moduleOrImportMetaUrl;
}
return false;
};

View file

@ -1,10 +1,10 @@
import { getConfig } from "~classes/configmanager";
import type { Prisma } from "@prisma/client";
import chalk from "chalk";
import { ConfigManager } from "config-manager";
import Redis from "ioredis";
import { createPrismaRedisCache } from "prisma-redis-middleware";
const config = getConfig();
const config = await new ConfigManager({}).getConfig();
const cacheRedis = config.redis.cache.enabled
? new Redis({
@ -12,7 +12,7 @@ const cacheRedis = config.redis.cache.enabled
port: Number(config.redis.cache.port),
password: config.redis.cache.password,
db: Number(config.redis.cache.database ?? 0),
})
})
: null;
cacheRedis?.on("error", e => {

View file

@ -1,96 +0,0 @@
/**
* Takes a request, and turns FormData or query parameters
* into a JSON object as would be returned by req.json()
* This is a translation layer that allows clients to use
* either FormData, query parameters, or JSON in the request
* @param request The request to parse
*/
/* export async function parseRequest<T>(request: Request): Promise<Partial<T>> {
const query = new URL(request.url).searchParams;
let output: Partial<T> = {};
// Parse SearchParams arrays into JSON arrays
const arrayKeys = [...query.keys()].filter(key => key.endsWith("[]"));
const nonArrayKeys = [...query.keys()].filter(key => !key.endsWith("[]"));
for (const key of arrayKeys) {
const value = query.getAll(key);
query.delete(key);
query.append(key, JSON.stringify(value));
}
// Append non array keys to output
for (const key of nonArrayKeys) {
// @ts-expect-error Complains about type
output[key] = query.get(key);
}
const queryEntries = [...query.entries()];
if (queryEntries.length > 0) {
const data: Record<string, string | string[]> = {};
const arrayKeys = [...query.keys()].filter(key => key.endsWith("[]"));
for (const key of arrayKeys) {
const value = query.getAll(key);
query.delete(key);
// @ts-expect-error JSON arrays are valid
data[key] = JSON.parse(value);
}
output = {
...output,
...(data as T),
};
}
// if request contains a JSON body
if (request.headers.get("Content-Type")?.includes("application/json")) {
try {
output = {
...output,
...((await request.json()) as T),
};
} catch {
// Invalid JSON
}
}
// If request contains FormData
if (request.headers.get("Content-Type")?.includes("multipart/form-data")) {
// @ts-expect-error It hates entries() for some reason
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const formData = [...(await request.formData()).entries()];
if (formData.length > 0) {
const data: Record<string, string | File> = {};
for (const [key, value] of formData) {
// If object, parse as JSON
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-base-to-string, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
data[key] = JSON.parse(value.toString());
} catch {
// If a file, set as a file
if (value instanceof File) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
data[key] = value;
} else {
// Otherwise, set as a string
// eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
data[key] = value.toString();
}
}
}
output = {
...output,
...(data as T),
};
}
}
return output;
}
*/

View file

@ -1,8 +1,8 @@
import { getConfig } from "~classes/configmanager";
import { ConfigManager } from "config-manager";
import { sanitize } from "isomorphic-dompurify";
export const sanitizeHtml = async (html: string) => {
const config = getConfig();
const config = await new ConfigManager({}).getConfig();
const sanitizedHtml = sanitize(html, {
ALLOWED_TAGS: [