This commit is contained in:
parent
794820e1d3
commit
5cbc445597
1354
package-lock.json
generated
1354
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
36
package.json
36
package.json
@ -17,31 +17,31 @@
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/jsonwebtoken": "^8.3.8",
|
||||
"@types/koa": "^2.11.2",
|
||||
"@types/koa-router": "^7.4.0",
|
||||
"@types/jsonwebtoken": "^8.5.0",
|
||||
"@types/koa": "^2.11.3",
|
||||
"@types/koa-router": "^7.4.1",
|
||||
"@types/leveldown": "^4.0.2",
|
||||
"@types/levelup": "^4.3.0",
|
||||
"@types/nanoid": "^2.1.0",
|
||||
"@types/node": "^13.9.3",
|
||||
"@types/ws": "^7.2.3",
|
||||
"concurrently": "^5.1.0",
|
||||
"nodemon": "^2.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
"@types/node": "^14.0.27",
|
||||
"@types/ws": "^7.2.6",
|
||||
"concurrently": "^5.3.0",
|
||||
"nodemon": "^2.0.4",
|
||||
"typescript": "^3.9.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hibas123/nodelogging": "^2.1.5",
|
||||
"@hibas123/utils": "^2.2.3",
|
||||
"@hibas123/nodelogging": "^2.4.5",
|
||||
"@hibas123/utils": "^2.2.4",
|
||||
"dotenv": "^8.2.0",
|
||||
"handlebars": "^4.7.3",
|
||||
"handlebars": "^4.7.6",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"koa": "^2.11.0",
|
||||
"koa-body": "^4.1.1",
|
||||
"koa-router": "^8.0.8",
|
||||
"leveldown": "^5.5.1",
|
||||
"levelup": "^4.3.2",
|
||||
"nanoid": "^2.1.11",
|
||||
"koa": "^2.13.0",
|
||||
"koa-body": "^4.2.0",
|
||||
"koa-router": "^9.4.0",
|
||||
"leveldown": "^5.6.0",
|
||||
"levelup": "^4.4.0",
|
||||
"nanoid": "^3.1.12",
|
||||
"what-the-pack": "^2.0.3",
|
||||
"ws": "^7.2.3"
|
||||
"ws": "^7.3.1"
|
||||
}
|
||||
}
|
||||
|
@ -12,12 +12,15 @@ import {
|
||||
} from "./query";
|
||||
import Logging from "@hibas123/nodelogging";
|
||||
import Session from "./session";
|
||||
import nanoid = require("nanoid/generate");
|
||||
import nanoid = require("nanoid");
|
||||
import { Observable } from "@hibas123/utils";
|
||||
|
||||
const ALPHABET =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
const longNanoId = nanoid.customAlphabet(ALPHABET, 32);
|
||||
const shortNanoId = nanoid.customAlphabet(ALPHABET, 16);
|
||||
|
||||
// interface ITransaction {
|
||||
// queries: ITypedQuery<IWriteQueries>[];
|
||||
// }
|
||||
@ -156,7 +159,7 @@ export class Database {
|
||||
.then((r) => r.toString())
|
||||
.catch(resNull);
|
||||
if (!collectionID && create) {
|
||||
collectionID = nanoid(ALPHABET, 32);
|
||||
collectionID = longNanoId();
|
||||
await this.collections.put(key, collectionID);
|
||||
setImmediate(() => {
|
||||
this.collectionChangeListener.send({
|
||||
@ -329,7 +332,7 @@ export class Database {
|
||||
|
||||
const { unsubscribe, value } = await query.snapshot(onchange);
|
||||
|
||||
const id = nanoid(ALPHABET, 16);
|
||||
const id = shortNanoId();
|
||||
session.subscriptions.set(id, unsubscribe);
|
||||
return {
|
||||
id,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Database, Change, ChangeTypes } from "./database";
|
||||
import { resNull } from "../storage";
|
||||
import nanoid = require("nanoid/generate");
|
||||
import * as nanoid from "nanoid";
|
||||
import Logging from "@hibas123/nodelogging";
|
||||
import * as MSGPack from "what-the-pack";
|
||||
import Session from "./session";
|
||||
@ -31,6 +31,8 @@ export const MP = MSGPack.initialize(2 ** 20);
|
||||
const ALPHABET =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
const longNanoID = nanoid.customAlphabet(ALPHABET, 32);
|
||||
|
||||
const { encode, decode } = MP;
|
||||
|
||||
type Runner = (
|
||||
@ -61,7 +63,7 @@ export abstract class Query {
|
||||
*/
|
||||
private validatePath(path: string[]) {
|
||||
return path.every(
|
||||
e => (e.match(/[^a-zA-Z0-9_\-\<\>]/g) || []).length === 0
|
||||
(e) => (e.match(/[^a-zA-Z0-9_\-\<\>]/g) || []).length === 0
|
||||
);
|
||||
}
|
||||
|
||||
@ -106,7 +108,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<any>(res as Buffer))
|
||||
.catch(resNull);
|
||||
}
|
||||
|
||||
@ -121,7 +123,7 @@ export abstract class Query {
|
||||
document,
|
||||
collection,
|
||||
data,
|
||||
sender: this.session.id
|
||||
sender: this.session.id,
|
||||
};
|
||||
|
||||
this.changes.push(change);
|
||||
@ -179,23 +181,25 @@ export abstract class Query {
|
||||
|
||||
const receivedChanges = (changes: Change[]) => {
|
||||
let res = changes
|
||||
.filter(change => this.checkChange(change))
|
||||
.map(change => {
|
||||
.filter((change) => this.checkChange(change))
|
||||
.map((change) => {
|
||||
return {
|
||||
id: change.document,
|
||||
data: change.data,
|
||||
type: change.type
|
||||
type: change.type,
|
||||
};
|
||||
});
|
||||
if (res.length > 0) onChange(res);
|
||||
};
|
||||
|
||||
const unsub = this.database.collectionChangeListener.subscribe(change => {
|
||||
const unsub = this.database.collectionChangeListener.subscribe(
|
||||
(change) => {
|
||||
if (change.key === collectionKey) {
|
||||
if (change.type === "create") addSubscriber(change.id);
|
||||
else removeSubscriber(); // Send delete for all elements (Don't know how to do this...)
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
let { collection, document, collectionKey } = await this.database.resolve(
|
||||
this.query.path
|
||||
@ -236,7 +240,7 @@ export abstract class Query {
|
||||
unsub();
|
||||
removeSubscriber();
|
||||
},
|
||||
value: await this.firstSend(collection, document)
|
||||
value: await this.firstSend(collection, document),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -257,7 +261,7 @@ export class DocumentQuery extends Query {
|
||||
createCollection: false,
|
||||
needDocument: false,
|
||||
permission: "read",
|
||||
runner: this.get
|
||||
runner: this.get,
|
||||
};
|
||||
case "set":
|
||||
return {
|
||||
@ -265,7 +269,7 @@ export class DocumentQuery extends Query {
|
||||
createCollection: true,
|
||||
needDocument: true,
|
||||
permission: "write",
|
||||
runner: this.set
|
||||
runner: this.set,
|
||||
};
|
||||
case "update":
|
||||
return {
|
||||
@ -273,7 +277,7 @@ export class DocumentQuery extends Query {
|
||||
createCollection: true,
|
||||
needDocument: true,
|
||||
permission: "write",
|
||||
runner: this.update
|
||||
runner: this.update,
|
||||
};
|
||||
case "delete":
|
||||
return {
|
||||
@ -281,7 +285,7 @@ export class DocumentQuery extends Query {
|
||||
createCollection: false,
|
||||
needDocument: true,
|
||||
permission: "write",
|
||||
runner: this.delete
|
||||
runner: this.delete,
|
||||
};
|
||||
default:
|
||||
throw new Error("Invalid query type: " + type);
|
||||
@ -431,14 +435,14 @@ export class CollectionQuery extends Query {
|
||||
prepare(query): IPreparedQuery {
|
||||
switch (query.type as ICollectionQueries) {
|
||||
case "add":
|
||||
this._addId = nanoid(ALPHABET, 32);
|
||||
this._addId = longNanoID();
|
||||
return {
|
||||
batchCompatible: true,
|
||||
createCollection: true,
|
||||
needDocument: false,
|
||||
runner: this.add,
|
||||
permission: "write",
|
||||
additionalLock: [...query.path, this._addId]
|
||||
additionalLock: [...query.path, this._addId],
|
||||
};
|
||||
case "get":
|
||||
const limit = (query.options || {}).limit;
|
||||
@ -451,7 +455,7 @@ export class CollectionQuery extends Query {
|
||||
createCollection: false,
|
||||
needDocument: false,
|
||||
permission: "read",
|
||||
runner: this.get
|
||||
runner: this.get,
|
||||
};
|
||||
case "keys":
|
||||
return {
|
||||
@ -459,7 +463,7 @@ export class CollectionQuery extends Query {
|
||||
createCollection: false,
|
||||
needDocument: false,
|
||||
permission: "read",
|
||||
runner: this.keys
|
||||
runner: this.keys,
|
||||
};
|
||||
case "list":
|
||||
return {
|
||||
@ -467,7 +471,7 @@ export class CollectionQuery extends Query {
|
||||
createCollection: false,
|
||||
needDocument: false,
|
||||
permission: "read",
|
||||
runner: this.keys
|
||||
runner: this.keys,
|
||||
};
|
||||
case "delete-collection":
|
||||
return {
|
||||
@ -475,7 +479,7 @@ export class CollectionQuery extends Query {
|
||||
createCollection: false,
|
||||
needDocument: false,
|
||||
permission: "write",
|
||||
runner: this.deleteCollection
|
||||
runner: this.deleteCollection,
|
||||
};
|
||||
// run = () => q.deleteCollection();
|
||||
// break;
|
||||
@ -489,7 +493,7 @@ export class CollectionQuery extends Query {
|
||||
const invalidWhere = new QueryError("Invalid Where");
|
||||
if (!Array.isArray(value)) throw invalidWhere;
|
||||
let c = [];
|
||||
this._where = value.map(cond => {
|
||||
this._where = value.map((cond) => {
|
||||
Logging.debug("Query Condition", cond);
|
||||
if (Array.isArray(cond)) {
|
||||
if (cond.length !== 3) throw invalidWhere;
|
||||
@ -522,7 +526,7 @@ export class CollectionQuery extends Query {
|
||||
type: "set",
|
||||
path: this.additionalLock,
|
||||
data: this.query.data,
|
||||
options: this.query.options
|
||||
options: this.query.options,
|
||||
});
|
||||
await q.run(collection, this._addId, batch, collectionKey);
|
||||
return this._addId;
|
||||
@ -538,7 +542,7 @@ export class CollectionQuery extends Query {
|
||||
|
||||
return {
|
||||
gt,
|
||||
lt
|
||||
lt,
|
||||
};
|
||||
}
|
||||
|
||||
@ -549,7 +553,7 @@ export class CollectionQuery extends Query {
|
||||
let keys = [];
|
||||
const stream = this.database.data.createKeyStream({
|
||||
...this.getStreamOptions(collection),
|
||||
keyAsBuffer: false
|
||||
keyAsBuffer: false,
|
||||
});
|
||||
stream.on("data", (key: string) => {
|
||||
let s = key.split("/", 2);
|
||||
@ -589,7 +593,7 @@ export class CollectionQuery extends Query {
|
||||
return val > value;
|
||||
case "array-contains":
|
||||
if (Array.isArray(val)) {
|
||||
return val.some(e => e === value);
|
||||
return val.some((e) => e === value);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -614,7 +618,7 @@ export class CollectionQuery extends Query {
|
||||
const stream = this.database.data.iterator({
|
||||
...this.getStreamOptions(collection),
|
||||
keyAsBuffer: false,
|
||||
valueAsBuffer: true
|
||||
valueAsBuffer: true,
|
||||
});
|
||||
|
||||
let values: DocRes[] = [];
|
||||
@ -622,7 +626,7 @@ export class CollectionQuery extends Query {
|
||||
const onValue = (err: Error, key: string, value: Buffer) => {
|
||||
if (err) {
|
||||
no(err);
|
||||
stream.end(err => Logging.error(err));
|
||||
stream.end((err) => Logging.error(err));
|
||||
} else {
|
||||
if (!key && !value) {
|
||||
// END
|
||||
@ -639,10 +643,10 @@ export class CollectionQuery extends Query {
|
||||
if (this.limit < 0 || values.length < this.limit) {
|
||||
values.push({
|
||||
id,
|
||||
data
|
||||
data,
|
||||
});
|
||||
} else {
|
||||
stream.end(err => (err ? no(err) : yes(values)));
|
||||
stream.end((err) => (err ? no(err) : yes(values)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -670,7 +674,7 @@ export class CollectionQuery extends Query {
|
||||
return new Promise<string[]>((yes, no) => {
|
||||
let keys = [];
|
||||
const stream = this.database.data.createKeyStream({
|
||||
keyAsBuffer: false
|
||||
keyAsBuffer: false,
|
||||
});
|
||||
stream.on("data", (key: string) => keys.push(key.split("/")));
|
||||
stream.on("end", () => yes(keys));
|
||||
@ -701,7 +705,7 @@ export class CollectionQuery extends Query {
|
||||
this.database.collectionChangeListener.send({
|
||||
id: collection,
|
||||
key: collectionKey,
|
||||
type: "delete"
|
||||
type: "delete",
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
|
@ -4,18 +4,18 @@ import { DatabaseManager } from "../../database/database";
|
||||
import {
|
||||
NotFoundError,
|
||||
NoPermissionError,
|
||||
BadRequestError
|
||||
BadRequestError,
|
||||
} from "../helper/errors";
|
||||
import Logging from "@hibas123/nodelogging";
|
||||
import Session from "../../database/session";
|
||||
import nanoid = require("nanoid");
|
||||
import { nanoid } from "nanoid";
|
||||
import { verifyJWT } from "../../helper/jwt";
|
||||
import { QueryError } from "../../database/query";
|
||||
const V1 = new Router({ prefix: "/v1" });
|
||||
|
||||
V1.use("/admin", AdminRoute.routes(), AdminRoute.allowedMethods());
|
||||
|
||||
V1.post("/db/:database/query", async ctx => {
|
||||
V1.post("/db/:database/query", async (ctx) => {
|
||||
const { database } = ctx.params;
|
||||
const { accesskey, authkey, rootkey } = ctx.query;
|
||||
|
||||
@ -52,7 +52,7 @@ V1.post("/db/:database/query", async ctx => {
|
||||
}
|
||||
}
|
||||
|
||||
ctx.body = await db.run([query], session).catch(err => {
|
||||
ctx.body = await db.run([query], session).catch((err) => {
|
||||
if (err instanceof QueryError) {
|
||||
throw new BadRequestError(err.message);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from "./database/query";
|
||||
import Session from "./database/session";
|
||||
import { verifyJWT } from "./helper/jwt";
|
||||
import nanoid = require("nanoid");
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
export class WebsocketConnectionManager {
|
||||
static server: WebSocket.Server;
|
||||
|
Reference in New Issue
Block a user