aboutsummaryrefslogtreecommitdiff
path: root/src/server/database.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/database.ts')
-rw-r--r--src/server/database.ts175
1 files changed, 101 insertions, 74 deletions
diff --git a/src/server/database.ts b/src/server/database.ts
index 725b66836..3a087ce38 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -9,8 +9,12 @@ import { Transferable } from './Message';
import { Upload } from './SharedMediaTypes';
export namespace Database {
-
export let disconnect: Function;
+
+ class DocSchema implements mongodb.BSON.Document {
+ _id!: string;
+ id!: string;
+ }
const schema = 'Dash';
const port = 27017;
export const url = `mongodb://localhost:${port}/${schema}`;
@@ -26,7 +30,7 @@ export namespace Database {
export async function tryInitializeConnection() {
try {
const { connection } = mongoose;
- disconnect = async () => new Promise<any>(resolve => connection.close(resolve));
+ disconnect = async () => new Promise<any>(resolve => connection.close().then(resolve));
if (connection.readyState === ConnectionStates.disconnected) {
await new Promise<void>((resolve, reject) => {
connection.on('error', reject);
@@ -35,12 +39,11 @@ export namespace Database {
resolve();
});
mongoose.connect(url, {
- useNewUrlParser: true,
- useUnifiedTopology: true,
+ //useNewUrlParser: true,
dbName: schema,
// reconnectTries: Number.MAX_VALUE,
// reconnectInterval: 1000,
- });
+ });
});
}
} catch (e) {
@@ -60,11 +63,10 @@ export namespace Database {
async doConnect() {
console.error(`\nConnecting to Mongo with URL : ${url}\n`);
return new Promise<void>(resolve => {
- this.MongoClient.connect(url, { connectTimeoutMS: 30000, socketTimeoutMS: 30000, useUnifiedTopology: true }, (_err, client) => {
- console.error("mongo connect response\n");
+ this.MongoClient.connect(url, { connectTimeoutMS: 30000, socketTimeoutMS: 30000 }).then(client => {
+ console.error('mongo connect response\n');
if (!client) {
- console.error("\nMongo connect failed with the error:\n");
- console.log(_err);
+ console.error('\nMongo connect failed with the error:\n');
process.exit(0);
}
this.db = client.db();
@@ -74,20 +76,24 @@ export namespace Database {
});
}
- public async update(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateWriteOpResult) => void, upsert = true, collectionName = DocumentsCollection) {
+ public async update(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateResult) => void, upsert = true, collectionName = DocumentsCollection) {
if (this.db) {
- const collection = this.db.collection(collectionName);
+ const collection = this.db.collection<DocSchema>(collectionName);
const prom = this.currentWrites[id];
let newProm: Promise<void>;
const run = (): Promise<void> => {
return new Promise<void>(resolve => {
- collection.updateOne({ _id: id }, value, { upsert }
- , (err, res) => {
+ collection
+ .updateOne({ _id: id }, value, { upsert })
+ .then(res => {
if (this.currentWrites[id] === newProm) {
delete this.currentWrites[id];
}
resolve();
- callback(err, res);
+ callback(undefined as any, res);
+ })
+ .catch(error => {
+ console.log('MOngo UPDATE ONE ERROR:', error);
});
});
};
@@ -99,21 +105,20 @@ export namespace Database {
}
}
- public replace(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateWriteOpResult) => void, upsert = true, collectionName = DocumentsCollection) {
+ public replace(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateResult<mongodb.Document>) => void, upsert = true, collectionName = DocumentsCollection) {
if (this.db) {
- const collection = this.db.collection(collectionName);
+ const collection = this.db.collection<DocSchema>(collectionName);
const prom = this.currentWrites[id];
let newProm: Promise<void>;
const run = (): Promise<void> => {
return new Promise<void>(resolve => {
- collection.replaceOne({ _id: id }, value, { upsert }
- , (err, res) => {
- if (this.currentWrites[id] === newProm) {
- delete this.currentWrites[id];
- }
- resolve();
- callback(err, res);
- });
+ collection.replaceOne({ _id: id }, value, { upsert }).then(res => {
+ if (this.currentWrites[id] === newProm) {
+ delete this.currentWrites[id];
+ }
+ resolve();
+ callback(undefined as any, res as any);
+ });
});
};
newProm = prom ? prom.then(run) : run();
@@ -135,15 +140,20 @@ export namespace Database {
return collectionNames;
}
- public delete(query: any, collectionName?: string): Promise<mongodb.DeleteWriteOpResultObject>;
- public delete(id: string, collectionName?: string): Promise<mongodb.DeleteWriteOpResultObject>;
+ public delete(query: any, collectionName?: string): Promise<mongodb.DeleteResult>;
+ public delete(id: string, collectionName?: string): Promise<mongodb.DeleteResult>;
public delete(id: any, collectionName = DocumentsCollection) {
- if (typeof id === "string") {
+ if (typeof id === 'string') {
id = { _id: id };
}
if (this.db) {
const db = this.db;
- return new Promise(res => db.collection(collectionName).deleteMany(id, (err, result) => res(result)));
+ return new Promise(res =>
+ db
+ .collection(collectionName)
+ .deleteMany(id)
+ .then(result => res(result))
+ );
} else {
return new Promise(res => this.onConnect.push(() => res(this.delete(id, collectionName))));
}
@@ -170,22 +180,27 @@ export namespace Database {
public async insert(value: any, collectionName = DocumentsCollection) {
if (this.db && value !== null) {
- if ("id" in value) {
+ if ('id' in value) {
value._id = value.id;
delete value.id;
}
const id = value._id;
- const collection = this.db.collection(collectionName);
+ const collection = this.db.collection<DocSchema>(collectionName);
const prom = this.currentWrites[id];
let newProm: Promise<void>;
const run = (): Promise<void> => {
return new Promise<void>(resolve => {
- collection.insertOne(value, (err, res) => {
- if (this.currentWrites[id] === newProm) {
- delete this.currentWrites[id];
- }
- resolve();
- });
+ collection
+ .insertOne(value)
+ .then(res => {
+ if (this.currentWrites[id] === newProm) {
+ delete this.currentWrites[id];
+ }
+ resolve();
+ })
+ .catch(err => {
+ console.log('Mongo INSERT ERROR: ', err);
+ });
});
};
newProm = prom ? prom.then(run) : run();
@@ -198,11 +213,12 @@ export namespace Database {
public getDocument(id: string, fn: (result?: Transferable) => void, collectionName = DocumentsCollection) {
if (this.db) {
- this.db.collection(collectionName).findOne({ _id: id }, (err, result) => {
+ const collection = this.db.collection<DocSchema>(collectionName);
+ collection.findOne({ _id: id }).then(result => {
if (result) {
result.id = result._id;
- delete result._id;
- fn(result);
+ //delete result._id;
+ fn(result as any);
} else {
fn(undefined);
}
@@ -212,19 +228,19 @@ export namespace Database {
}
}
- public getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = DocumentsCollection) {
+ public async getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = DocumentsCollection) {
if (this.db) {
- this.db.collection(collectionName).find({ _id: { "$in": ids } }).toArray((err, docs) => {
- if (err) {
- console.log(err.message);
- console.log(err.errmsg);
- }
- fn(docs.map(doc => {
+ const found = await this.db
+ .collection<DocSchema>(collectionName)
+ .find({ _id: { $in: ids } })
+ .toArray();
+ fn(
+ found.map((doc: any) => {
doc.id = doc._id;
delete doc._id;
return doc;
- }));
- });
+ })
+ );
} else {
this.onConnect.push(() => this.getDocuments(ids, fn, collectionName));
}
@@ -257,15 +273,15 @@ export namespace Database {
}
}
- public query(query: { [key: string]: any }, projection?: { [key: string]: 0 | 1 }, collectionName = DocumentsCollection): Promise<mongodb.Cursor> {
+ public query(query: { [key: string]: any }, projection?: { [key: string]: 0 | 1 }, collectionName = DocumentsCollection): Promise<mongodb.FindCursor> {
if (this.db) {
- let cursor = this.db.collection(collectionName).find(query);
+ let cursor = this.db.collection<DocSchema>(collectionName).find(query);
if (projection) {
cursor = cursor.project(projection);
}
- return Promise.resolve<mongodb.Cursor>(cursor);
+ return Promise.resolve<mongodb.FindCursor>(cursor);
} else {
- return new Promise<mongodb.Cursor>(res => {
+ return new Promise<mongodb.FindCursor>(res => {
this.onConnect.push(() => res(this.query(query, projection, collectionName)));
});
}
@@ -274,22 +290,36 @@ export namespace Database {
public updateMany(query: any, update: any, collectionName = DocumentsCollection) {
if (this.db) {
const db = this.db;
- return new Promise<mongodb.WriteOpResult>(res => db.collection(collectionName).update(query, update, (_, result) => res(result)));
+ return new Promise<mongodb.UpdateResult>(res =>
+ db
+ .collection(collectionName)
+ .updateMany(query, update)
+ .then(result => res(result))
+ .catch(error => {
+ console.log('Mongo INSERT MANY ERROR:', error);
+ })
+ );
} else {
- return new Promise<mongodb.WriteOpResult>(res => {
- this.onConnect.push(() => this.updateMany(query, update, collectionName).then(res));
+ return new Promise<mongodb.UpdateResult>(res => {
+ this.onConnect.push(() =>
+ this.updateMany(query, update, collectionName)
+ .then(res)
+ .catch(error => {
+ console.log('Mongo UPDATAE MANY ERROR: ', error);
+ })
+ );
});
}
}
public print() {
- console.log("db says hi!");
+ console.log('db says hi!');
}
}
function getDatabase() {
switch (process.env.DB) {
- case "MEM":
+ case 'MEM':
return new MemoryDatabase();
default:
return new Database();
@@ -304,13 +334,12 @@ export namespace Database {
* or Dash-internal user data.
*/
export namespace Auxiliary {
-
/**
* All the auxiliary MongoDB collections (schemas)
*/
export enum AuxiliaryCollections {
- GooglePhotosUploadHistory = "uploadedFromGooglePhotos",
- GoogleAccess = "googleAuthentication",
+ GooglePhotosUploadHistory = 'uploadedFromGooglePhotos',
+ GoogleAccess = 'googleAuthentication',
}
/**
@@ -322,16 +351,18 @@ export namespace Database {
const cursor = await Instance.query(query, undefined, collection);
const results = await cursor.toArray();
const slice = results.slice(0, Math.min(cap, results.length));
- return removeId ? slice.map(result => {
- delete result._id;
- return result;
- }) : slice;
+ return removeId
+ ? slice.map((result: any) => {
+ delete result._id;
+ return result;
+ })
+ : slice;
};
/**
* Searches for the @param query in the specified @param collection,
* and returns at most the first result. If @param removeId is true,
- * as it is by default, each object will be stripped of its database id.
+ * as it is by default, each object will be stripped of its database id.
* Worth the special case since it converts the Array return type to a single
* object of the specified type.
*/
@@ -341,7 +372,7 @@ export namespace Database {
};
/**
- * Checks to see if an image with the given @param contentSize
+ * Checks to see if an image with the given @param contentSize
* already exists in the aux database, i.e. has already been downloaded from Google Photos.
*/
export const QueryUploadHistory = async (contentSize: number) => {
@@ -355,7 +386,7 @@ export namespace Database {
export const LogUpload = async (information: Upload.ImageInformation) => {
const bundle = {
_id: Utils.GenerateDeterministicGuid(String(information.contentSize)),
- ...information
+ ...information,
};
return Instance.insert(bundle, AuxiliaryCollections.GooglePhotosUploadHistory);
};
@@ -365,7 +396,6 @@ export namespace Database {
* facilitates interactions with all their APIs for a given account.
*/
export namespace GoogleAccessToken {
-
/**
* Format stored in database.
*/
@@ -373,7 +403,7 @@ export namespace Database {
/**
* Retrieves the credentials associaed with @param userId
- * and optionally removes their database id according to @param removeId.
+ * and optionally removes their database id according to @param removeId.
*/
export const Fetch = async (userId: string, removeId = true): Promise<Opt<StoredCredentials>> => {
return SanitizedSingletonQuery<StoredCredentials>({ userId }, AuxiliaryCollections.GoogleAccess, removeId);
@@ -381,7 +411,7 @@ export namespace Database {
/**
* Writes the @param enrichedCredentials to the database, associated
- * with @param userId for later retrieval and updating.
+ * with @param userId for later retrieval and updating.
*/
export const Write = async (userId: string, enrichedCredentials: GoogleApiServerUtils.EnrichedCredentials) => {
return Instance.insert({ userId, canAccess: [], ...enrichedCredentials }, AuxiliaryCollections.GoogleAccess);
@@ -400,7 +430,7 @@ export namespace Database {
};
/**
- * Revokes the credentials associated with @param userId.
+ * Revokes the credentials associated with @param userId.
*/
export const Revoke = async (userId: string) => {
const entry = await Fetch(userId, false);
@@ -408,9 +438,6 @@ export namespace Database {
Instance.delete({ _id: entry._id }, AuxiliaryCollections.GoogleAccess);
}
};
-
}
-
}
-
}