Skip to content
40 changes: 26 additions & 14 deletions src/integrations/database/Database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ export default class Database implements Driver

get connected() { return this.#driver.connected; }

connect(): Promise<void>
clear(): Promise<void>
{
return this.#driver.connect();
return this.#driver.clear();
}

disconnect(): Promise<void>
connect(): Promise<void>
{
return this.#driver.disconnect();
return this.#driver.connect();
}

createRecord(type: RecordType, data: RecordData): Promise<RecordId>
Expand All @@ -32,35 +32,47 @@ export default class Database implements Driver
return this.#driver.createRecord(type, cleanData);
}

readRecord(type: RecordType, id: RecordId, fields?: RecordField[]): Promise<RecordData>
deleteRecord(type: RecordType, id: RecordId): Promise<void>
{
return this.#driver.readRecord(type, id, fields);
return this.#driver.deleteRecord(type, id);
}

updateRecord(type: RecordType, id: RecordId, data: RecordData): Promise<void>
deleteRecords(type: RecordType, query: RecordQuery): Promise<void>
{
const cleanData = sanitize(data);

return this.#driver.updateRecord(type, id, cleanData);
return this.#driver.deleteRecords(type, query);
}

deleteRecord(type: RecordType, id: RecordId): Promise<void>
disconnect(): Promise<void>
{
return this.#driver.deleteRecord(type, id);
return this.#driver.disconnect();
}

findRecord(type: RecordType, query: RecordQuery, fields?: RecordField[], sort?: RecordSort): Promise<RecordData | undefined>
{
return this.#driver.findRecord(type, query, fields, sort);
}

readRecord(type: RecordType, id: RecordId, fields?: RecordField[]): Promise<RecordData>
{
return this.#driver.readRecord(type, id, fields);
}

searchRecords(type: RecordType, query: RecordQuery, fields?: RecordField[], sort?: RecordSort, limit?: number, offset?: number): Promise<RecordData[]>
{
return this.#driver.searchRecords(type, query, fields, sort, limit, offset);
}

clear(): Promise<void>
updateRecord(type: RecordType, id: RecordId, data: RecordData): Promise<void>
{
return this.#driver.clear();
const cleanData = sanitize(data);

return this.#driver.updateRecord(type, id, cleanData);
}

updateRecords(type: RecordType, query: RecordQuery, data: RecordData): Promise<void>
{
const cleanData = sanitize(data);

return this.#driver.updateRecords(type, query, cleanData);
}
}
2 changes: 2 additions & 0 deletions src/integrations/database/definitions/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ export interface Driver
deleteRecord(type: RecordType, id: RecordId): Promise<void>;
findRecord(type: RecordType, query: RecordQuery, fields?: RecordField[], sort?: RecordSort): Promise<RecordData | undefined>;
searchRecords(type: RecordType, query: RecordQuery, fields?: RecordField[], sort?: RecordSort, limit?: number, offset?: number): Promise<RecordData[]>;
updateRecords(type: RecordType, query: RecordQuery, data: RecordData): Promise<void>;
deleteRecords(type: RecordType, query: RecordQuery): Promise<void>;
clear(): Promise<void>;
}
84 changes: 53 additions & 31 deletions src/integrations/database/implementations/memory/Memory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ export default class Memory implements Driver

get connected() { return this.#connected; }

async connect(): Promise<void>
async clear(): Promise<void>
{
this.#connected = true;
this.#memory.clear();
}

async disconnect(): Promise<void>
async connect(): Promise<void>
{
this.#connected = false;
this.#connected = true;
}

async createRecord(type: string, data: RecordData): Promise<string>
Expand All @@ -55,46 +55,33 @@ export default class Memory implements Driver
return record.id as string;
}

async readRecord(type: string, id: string, fields?: string[]): Promise<RecordData>
async deleteRecord(type: string, id: string): Promise<void>
{
const collection = this.#getCollection(type);
const record = collection.find(object => object.id === id);
const index = collection.findIndex(object => object.id === id);

if (record === undefined)
if (index === -1)
{
throw new RecordNotFound();
}

return this.#buildRecordData(record, fields);
collection.splice(index, 1);
}

async updateRecord(type: string, id: string, data: RecordData): Promise<void>
async deleteRecords(type: string, query: QueryStatement): Promise<void>
{
const filterFunction = this.#buildFilterFunction(query);
const collection = this.#getCollection(type);
const record = collection.find(object => object.id === id);

if (record === undefined)
{
throw new RecordNotUpdated();
}

for (const key of Object.keys(data))
const records = collection.filter(filterFunction);
records.forEach(item =>
{
record[key] = data[key];
}
this.deleteRecord(type, item.id as string);
});
}

async deleteRecord(type: string, id: string): Promise<void>
async disconnect(): Promise<void>
{
const collection = this.#getCollection(type);
const index = collection.findIndex(object => object.id === id);

if (index === -1)
{
throw new RecordNotFound();
}

collection.splice(index, 1);
this.#connected = false;
}

async findRecord(type: string, query: QueryStatement, fields?: string[], sort?: RecordSort): Promise<RecordData | undefined>
Expand All @@ -104,6 +91,19 @@ export default class Memory implements Driver
return result[0];
}

async readRecord(type: string, id: string, fields?: string[]): Promise<RecordData>
{
const collection = this.#getCollection(type);
const record = collection.find(object => object.id === id);

if (record === undefined)
{
throw new RecordNotFound();
}

return this.#buildRecordData(record, fields);
}

async searchRecords(type: string, query: QueryStatement, fields?: string[], sort?: RecordSort, limit?: number, offset?: number): Promise<RecordData[]>
{
const collection = this.#getCollection(type);
Expand All @@ -116,9 +116,31 @@ export default class Memory implements Driver
return limitedResult.map(records => this.#buildRecordData(records, fields));
}

async clear(): Promise<void>
async updateRecord(type: string, id: string, data: RecordData): Promise<void>
{
this.#memory.clear();
const collection = this.#getCollection(type);
const record = collection.find(object => object.id === id);

if (record === undefined)
{
throw new RecordNotUpdated();
}

for (const key of Object.keys(data))
{
record[key] = data[key];
}
}

async updateRecords(type: string, query: QueryStatement, data: RecordData): Promise<void>
{
const filterFunction = this.#buildFilterFunction(query);
const collection = this.#getCollection(type);
const records = collection.filter(filterFunction);
records.forEach(item =>
{
this.updateRecord(type, item.id as string, data);
});
}

#limitNumberOfRecords(result: RecordData[], offset?: number, limit?: number): RecordData[]
Expand Down
24 changes: 24 additions & 0 deletions src/integrations/database/implementations/mongodb/MongoDb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,30 @@ export default class MongoDB implements Driver
return result.map(data => this.#buildRecordData(data, fields));
}

async updateRecords(type: RecordType, query: RecordQuery, data: RecordData): Promise<void>
{
const mongoQuery = this.#buildMongoQuery(query);

const collection = await this.#getCollection(type);
const result = await collection.updateMany(mongoQuery, { $set: data });
if (result.acknowledged === false)
{
throw new DatabaseError();
}
}

async deleteRecords(type: RecordType, query: RecordQuery): Promise<void>
{
const mongoQuery = this.#buildMongoQuery(query);

const collection = await this.#getCollection(type);
const result = await collection.deleteMany(mongoQuery);
if (result.acknowledged === false)
{
throw new DatabaseError();
}
}

async clear(): Promise<void>
{
return; // Deliberately not implemented
Expand Down
1 change: 1 addition & 0 deletions test/integrations/database/fixtures/queries.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const { CALZONE, VEGETARIAN, HAWAII } = RECORDS.PIZZAS;

export const QUERIES: Record<string, RecordQuery> =
{
UPDATED: { size: { EQUALS: 40 } },
EMPTY: {},
NO_MATCH: { name: { EQUALS: 'Not existing' } },

Expand Down
Loading