This commit is contained in:
parent
6e561bd30f
commit
97a6b45c92
7490
package-lock.json
generated
7490
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
45
package.json
45
package.json
@ -14,33 +14,32 @@
|
||||
"author": "Fabian Stamm <dev@fabianstamm.de>",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/jsonwebtoken": "^8.5.0",
|
||||
"@types/koa": "^2.11.6",
|
||||
"@types/koa-router": "^7.4.1",
|
||||
"@types/jsonwebtoken": "^8.5.1",
|
||||
"@types/koa": "^2.13.3",
|
||||
"@types/koa-router": "^7.4.2",
|
||||
"@types/leveldown": "^4.0.2",
|
||||
"@types/levelup": "^4.3.0",
|
||||
"@types/nanoid": "^2.1.0",
|
||||
"@types/node": "^14.14.5",
|
||||
"@types/ws": "^7.2.8",
|
||||
"concurrently": "^5.3.0",
|
||||
"nodemon": "^2.0.6",
|
||||
"ts-node": "^9.0.0",
|
||||
"typescript": "^4.0.5"
|
||||
"@types/levelup": "^4.3.1",
|
||||
"@types/msgpack5": "^3.4.1",
|
||||
"@types/node": "^14.17.2",
|
||||
"@types/ws": "^7.4.4",
|
||||
"nodemon": "^2.0.7",
|
||||
"ts-node": "^10.0.0",
|
||||
"typescript": "^4.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hibas123/nodelogging": "^2.4.5",
|
||||
"@hibas123/utils": "^2.2.16",
|
||||
"dotenv": "^8.2.0",
|
||||
"handlebars": "^4.7.6",
|
||||
"@hibas123/logging": "^3.1.2",
|
||||
"@hibas123/nodelogging": "^3.1.3",
|
||||
"@hibas123/utils": "^2.2.18",
|
||||
"dotenv": "^10.0.0",
|
||||
"handlebars": "^4.7.7",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"koa": "^2.13.0",
|
||||
"koa": "^2.13.1",
|
||||
"koa-body": "^4.2.0",
|
||||
"koa-router": "^9.4.0",
|
||||
"leveldown": "^5.6.0",
|
||||
"levelup": "^4.4.0",
|
||||
"nanoid": "^3.1.16",
|
||||
"what-the-pack": "^2.0.3",
|
||||
"ws": "^7.3.1"
|
||||
"koa-router": "^10.0.0",
|
||||
"leveldown": "^6.0.0",
|
||||
"levelup": "^5.0.0",
|
||||
"msgpack5": "^5.3.2",
|
||||
"nanoid": "^3.1.23",
|
||||
"ws": "^7.4.6"
|
||||
}
|
||||
}
|
||||
|
1771
pnpm-lock.yaml
Normal file
1771
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@ export default class DocumentLock {
|
||||
let key = collection + "/" + document;
|
||||
let l = this.locks.get(key);
|
||||
if (l)
|
||||
await new Promise((resolve) => {
|
||||
await new Promise<void>((resolve) => {
|
||||
l.push(resolve);
|
||||
this.locks.set(key, l);
|
||||
});
|
||||
|
@ -2,7 +2,7 @@ import { Database, Change, ChangeTypes } from "./database";
|
||||
import { resNull } from "../storage";
|
||||
import * as nanoid from "nanoid";
|
||||
import Logging from "@hibas123/nodelogging";
|
||||
import * as MSGPack from "what-the-pack";
|
||||
import * as MSGPack from "msgpack5";
|
||||
import Session from "./session";
|
||||
import { LevelUpChain } from "levelup";
|
||||
import { Operations } from "../rules/parser";
|
||||
@ -27,7 +27,9 @@ export type IQuery = ITypedQuery<
|
||||
ICollectionQueries | IDocumentQueries | "snapshot"
|
||||
>;
|
||||
|
||||
export const MP = MSGPack.initialize(2 ** 20);
|
||||
export const MP = MSGPack({});
|
||||
|
||||
// MSGPack.initialize(2 ** 20);
|
||||
|
||||
const ALPHABET =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
@ -110,7 +112,7 @@ export abstract class Query {
|
||||
protected getDoc(collection: string, document: string) {
|
||||
return this.database.data
|
||||
.get(Database.getKey(collection, document), { asBuffer: true })
|
||||
.then((res) => decode<any>(res as Buffer))
|
||||
.then((res) => decode(res as Buffer))
|
||||
.catch(resNull);
|
||||
}
|
||||
|
||||
@ -376,7 +378,7 @@ export class DocumentQuery extends Query {
|
||||
} else {
|
||||
await this.database.data.put(
|
||||
Database.getKey(collection, document),
|
||||
encode(data)
|
||||
encode(data).slice(0)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,49 +4,53 @@ if (!fs.existsSync("./databases/")) {
|
||||
fs.mkdirSync("./databases");
|
||||
}
|
||||
|
||||
import LevelUp, { LevelUp as LU } from "levelup";
|
||||
import LevelDown, { LevelDown as LD } from "leveldown";
|
||||
import * as LUR from "levelup";
|
||||
import * as LDR from "leveldown";
|
||||
|
||||
const LevelUp = LUR as any;
|
||||
const LevelDown = LDR as any;
|
||||
|
||||
import type { LevelUp as LU } from "levelup";
|
||||
import type { LevelDown as LD } from "leveldown";
|
||||
import { AbstractIterator } from "abstract-leveldown";
|
||||
|
||||
export type LevelDB = LU<LD, AbstractIterator<any, any>>;
|
||||
export type DBSet = { data: LevelDB, collection: LevelDB };
|
||||
export type DBSet = { data: LevelDB; collection: LevelDB };
|
||||
|
||||
const databases = new Map<string, DBSet>();
|
||||
|
||||
export function resNull(err): null {
|
||||
if (!err.notFound)
|
||||
throw err;
|
||||
if (!err.notFound) throw err;
|
||||
return null;
|
||||
}
|
||||
|
||||
async function rmRecursice(path: string) {
|
||||
if (fs.existsSync(path)) {
|
||||
await Promise.all(fs.readdirSync(path).map(async (file) => {
|
||||
var curPath = path + "/" + file;
|
||||
if (fs.lstatSync(curPath).isDirectory()) { // recurse
|
||||
await rmRecursice(curPath);
|
||||
} else { // delete file
|
||||
await fs.promises.unlink(curPath);
|
||||
}
|
||||
}));
|
||||
await Promise.all(
|
||||
fs.readdirSync(path).map(async (file) => {
|
||||
var curPath = path + "/" + file;
|
||||
if (fs.lstatSync(curPath).isDirectory()) {
|
||||
// recurse
|
||||
await rmRecursice(curPath);
|
||||
} else {
|
||||
// delete file
|
||||
await fs.promises.unlink(curPath);
|
||||
}
|
||||
})
|
||||
);
|
||||
await fs.promises.rmdir(path);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
export async function deleteLevelDB(name: string) {
|
||||
if (!name || name === "")
|
||||
return;
|
||||
if (!name || name === "") return;
|
||||
let db = databases.get(name);
|
||||
|
||||
if (db) {
|
||||
if (db.data.isOpen())
|
||||
await db.data.close()
|
||||
if (db.collection.isOpen())
|
||||
await db.collection.close()
|
||||
if (db.data.isOpen()) await db.data.close();
|
||||
if (db.collection.isOpen()) await db.collection.close();
|
||||
}
|
||||
|
||||
|
||||
//TODO make sure, that name doesn't make it possible to delete all databases :)
|
||||
await rmRecursice("./databases/" + name);
|
||||
}
|
||||
@ -60,9 +64,15 @@ export default function getLevelDB(name: string): DBSet {
|
||||
}
|
||||
|
||||
db = {
|
||||
data: db && db.data.isOpen() ? db.data : LevelUp(LevelDown("./databases/" + name + "/data")),
|
||||
collection: db && db.collection.isOpen() ? db.collection : LevelUp(LevelDown("./databases/" + name + "/collection"))
|
||||
}
|
||||
data:
|
||||
db && db.data.isOpen()
|
||||
? db.data
|
||||
: LevelUp(LevelDown("./databases/" + name + "/data")),
|
||||
collection:
|
||||
db && db.collection.isOpen()
|
||||
? db.collection
|
||||
: LevelUp(LevelDown("./databases/" + name + "/collection")),
|
||||
};
|
||||
|
||||
databases.set(name, db);
|
||||
return db;
|
||||
|
@ -7,29 +7,30 @@ export default function RequestError(ctx: Context, next) {
|
||||
ctx.body = message;
|
||||
}
|
||||
|
||||
return next().then(() => {
|
||||
if (ctx.status === HttpStatusCode.NOT_FOUND) {
|
||||
reply(HttpStatusCode.NOT_FOUND, "Not found");
|
||||
}
|
||||
}).catch(error => {
|
||||
let message = "Internal server error";
|
||||
let status = HttpStatusCode.INTERNAL_SERVER_ERROR;
|
||||
if (typeof error === "string") {
|
||||
message = error;
|
||||
} else if (!(error instanceof HttpError)) {
|
||||
Logging.error(error);
|
||||
message = error.message;
|
||||
} else {
|
||||
if (error.status === HttpStatusCode.INTERNAL_SERVER_ERROR) {
|
||||
//If internal server error log whole error
|
||||
return next()
|
||||
.then(() => {
|
||||
if (ctx.status === HttpStatusCode.NOT_FOUND) {
|
||||
reply(HttpStatusCode.NOT_FOUND, "Not found");
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
let message = "Internal server error";
|
||||
let status = HttpStatusCode.INTERNAL_SERVER_ERROR;
|
||||
if (typeof error === "string") {
|
||||
message = error;
|
||||
} else if (!(error instanceof HttpError)) {
|
||||
Logging.error(error);
|
||||
message = error.message;
|
||||
} else {
|
||||
if (error.status === HttpStatusCode.INTERNAL_SERVER_ERROR) {
|
||||
//If internal server error log whole error
|
||||
Logging.error(error);
|
||||
} else {
|
||||
message = error.message.split("\n", 1)[0];
|
||||
Logging.error(message);
|
||||
}
|
||||
status = error.status;
|
||||
}
|
||||
else {
|
||||
message = error.message.split("\n", 1)[0];
|
||||
Logging.errorMessage(message);
|
||||
}
|
||||
status = error.status;
|
||||
}
|
||||
reply(status, message);
|
||||
})
|
||||
};
|
||||
reply(status, message);
|
||||
});
|
||||
}
|
||||
|
@ -1,27 +1,40 @@
|
||||
import { LoggingBase } from "@hibas123/nodelogging";
|
||||
import { LoggingBase } from "@hibas123/logging";
|
||||
import { FileAdapter } from "@hibas123/nodelogging";
|
||||
import { Context } from "koa";
|
||||
import config from "../../config";
|
||||
|
||||
const route_logging = new LoggingBase({ name: "access", files: { errorfile: null }, console: config.dev })
|
||||
const route_logging = new LoggingBase({
|
||||
name: "access",
|
||||
console: config.dev,
|
||||
});
|
||||
|
||||
route_logging.addAdapter(new FileAdapter("logs/access.log"));
|
||||
|
||||
const RequestLog = async (ctx: Context, next) => {
|
||||
if (!config.access_log) return next();
|
||||
let start = process.hrtime()
|
||||
let to = false
|
||||
let start = process.hrtime();
|
||||
let to = false;
|
||||
let print = () => {
|
||||
let td = process.hrtime(start)
|
||||
let time = !to ? (td[0] * 1e3 + td[1] / 1e6).toFixed(2) : "--.--"
|
||||
let resColor = ""
|
||||
let td = process.hrtime(start);
|
||||
let time = !to ? (td[0] * 1e3 + td[1] / 1e6).toFixed(2) : "--.--";
|
||||
let resColor = "";
|
||||
let status = ctx.status;
|
||||
if (status >= 200 && status < 300) resColor = "\x1b[32m" //Green
|
||||
else if (status === 304 || status === 302) resColor = "\x1b[33m"
|
||||
else if (status >= 400 && status < 500) resColor = "\x1b[36m" //Cyan
|
||||
else if (status >= 500 && status < 600) resColor = "\x1b[31m" //Red
|
||||
let m = ctx.method
|
||||
while (m.length < 4) m += " "
|
||||
let message = `${m} ${ctx.originalUrl.split("?", 1)[0]} ${resColor}${status}\x1b[0m - ${time}ms`;
|
||||
if (status >= 200 && status < 300) resColor = "\x1b[32m";
|
||||
//Green
|
||||
else if (status === 304 || status === 302) resColor = "\x1b[33m";
|
||||
else if (status >= 400 && status < 500) resColor = "\x1b[36m";
|
||||
//Cyan
|
||||
else if (status >= 500 && status < 600) resColor = "\x1b[31m"; //Red
|
||||
let m = ctx.method;
|
||||
while (m.length < 4) m += " ";
|
||||
let message = `${m} ${
|
||||
ctx.originalUrl.split("?", 1)[0]
|
||||
} ${resColor}${status}\x1b[0m - ${time}ms`;
|
||||
route_logging.log(message);
|
||||
}
|
||||
let timeout = new Promise((yes) => setTimeout(() => (to = true) && yes(), 10000));
|
||||
};
|
||||
let timeout = new Promise<void>((yes) =>
|
||||
setTimeout(() => (to = true) && yes(), 10000)
|
||||
);
|
||||
await Promise.race([timeout, next()]);
|
||||
print();
|
||||
};
|
||||
|
@ -51,7 +51,7 @@ AdminRoute.get("/settings", async (ctx) => {
|
||||
|
||||
AdminRoute.get("/data", async (ctx) => {
|
||||
const { database } = ctx.query;
|
||||
let db = DatabaseManager.getDatabase(database);
|
||||
let db = DatabaseManager.getDatabase(database as string);
|
||||
if (!db) throw new BadRequestError("Database not found");
|
||||
let res = await new Promise<string[][]>((yes, no) => {
|
||||
const stream = db.data.createReadStream({
|
||||
@ -130,7 +130,7 @@ AdminRoute.get("/database", (ctx) => {
|
||||
|
||||
AdminRoute.get("/collections", async (ctx) => {
|
||||
const { database } = ctx.query;
|
||||
let db = DatabaseManager.getDatabase(database);
|
||||
let db = DatabaseManager.getDatabase(database as string);
|
||||
if (!db) throw new BadRequestError("Database not found");
|
||||
|
||||
let res = await new Promise<string[]>((yes, no) => {
|
||||
@ -156,7 +156,7 @@ AdminRoute.get("/collections", async (ctx) => {
|
||||
|
||||
AdminRoute.get("/collections/cleanup", async (ctx) => {
|
||||
const { database } = ctx.query;
|
||||
let db = DatabaseManager.getDatabase(database);
|
||||
let db = DatabaseManager.getDatabase(database as string);
|
||||
if (!db) throw new BadRequestError("Database not found");
|
||||
|
||||
let deleted = await db.runCleanup();
|
||||
@ -184,7 +184,7 @@ AdminRoute.get(
|
||||
|
||||
AdminRoute.get("/database/update", async (ctx) => {
|
||||
const { database } = ctx.query;
|
||||
let db = DatabaseManager.getDatabase(database);
|
||||
let db = DatabaseManager.getDatabase(database as string);
|
||||
if (!db) throw new NotFoundError("Database not found!");
|
||||
getForm("/v1/admin/database", "Change Database", {
|
||||
name: {
|
||||
|
@ -37,7 +37,7 @@ V1.post("/db/:database/query", async (ctx) => {
|
||||
}
|
||||
|
||||
if (authkey && db.publickey) {
|
||||
let res = await verifyJWT(authkey, db.publickey);
|
||||
let res = await verifyJWT(authkey as string, db.publickey);
|
||||
if (res && !res.uid && res.user) res.uid = res.user;
|
||||
if (!res || !res.uid) {
|
||||
throw new BadRequestError("Invalid JWT");
|
||||
|
@ -147,7 +147,7 @@ export class WebsocketConnectionManager {
|
||||
h(message.data);
|
||||
}
|
||||
} catch (err) {
|
||||
Logging.errorMessage("Unknown Error:");
|
||||
Logging.error("Unknown Error:");
|
||||
Logging.error(err);
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user