Skip to content

Commit

Permalink
feat(engine): add S3 engine
Browse files Browse the repository at this point in the history
  • Loading branch information
acodeninja committed Aug 1, 2024
1 parent 3a0f63e commit da3a1ef
Show file tree
Hide file tree
Showing 11 changed files with 591 additions and 10 deletions.
3 changes: 3 additions & 0 deletions exports/engine/s3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import S3Engine from '../../src/engine/S3Engine.js';

export default S3Engine;
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"eslint": "^9.6.0",
"globals": "^15.8.0",
"husky": "^9.1.1",
"lodash": "^4.17.21",
"monocart-coverage-reports": "^2.9.2",
"semantic-release": "^24.0.0",
"sinon": "^18.0.0"
Expand Down
2 changes: 1 addition & 1 deletion src/engine/Engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export default class Engine {
}

static toString() {
return 'Engine';
return this.name;
}
};

Expand Down
4 changes: 0 additions & 4 deletions src/engine/FileEngine.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,4 @@ export default class FileEngine extends Engine {

await processIndex('', Object.values(index).flat());
}

static toString() {
return 'FileEngine';
}
}
5 changes: 2 additions & 3 deletions src/engine/FileEngine.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ test('FileEngine.get(MainModel, id) when id exists', async t => {
});

test('FileEngine.get(MainModel, id) when id does not exist', async t => {
const filesystem = stubFs();
filesystem.readFile.rejects(new Error);
const filesystem = stubFs({});

await t.throwsAsync(
() => FileEngine.configure({
Expand All @@ -51,7 +50,7 @@ test('FileEngine.get(MainModel, id) when id does not exist', async t => {
});

test('FileEngine.put(model)', async t => {
const filesystem = stubFs();
const filesystem = stubFs({});

const model = getTestModelInstance(valid);
await t.notThrowsAsync(() => FileEngine.configure({
Expand Down
77 changes: 77 additions & 0 deletions src/engine/S3Engine.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {GetObjectCommand, PutObjectCommand} from '@aws-sdk/client-s3';

import Engine from './Engine.js';

export default class S3Engine extends Engine {
static async getById(id) {
const objectPath = [this._configuration.prefix, `${id}.json`].join('/');

try {
const data = await this._configuration.client.send(new GetObjectCommand({
Bucket: this._configuration.bucket,
Key: objectPath,
}));
return JSON.parse(await data.Body.transformToString());
} catch (_error) {
return undefined;
}
}

static async findByValue(model, parameters) {
const index = await this.getIndex(model.name);
return Object.values(index)
.filter((model) =>
Object.entries(parameters)
.some(([name, value]) => model[name] === value),
);
}

static async putModel(model) {
const Key = [this._configuration.prefix, `${model.id}.json`].join('/');

await this._configuration.client.send(new PutObjectCommand({
Key,
Body: JSON.stringify(model.toData()),
Bucket: this._configuration.bucket,
ContentType: 'application/json',
}));
}

static async getIndex(location) {
try {
const data = await this._configuration.client.send(new GetObjectCommand({
Key: [this._configuration.prefix].concat([location]).concat(['_index.json']).filter(e => !!e).join('/'),
Bucket: this._configuration.bucket,
}));

return JSON.parse(await data.Body.transformToString());
} catch (_error) {
return {};
}
}

static async putIndex(index) {
const processIndex = async (location, models) => {
const modelIndex = Object.fromEntries(models.map(m => [m.id, m.toIndexData()]));
const Key = [this._configuration.prefix].concat([location]).concat(['_index.json']).filter(e => !!e).join('/');

const currentIndex = await this.getIndex(location);

await this._configuration.client.send(new PutObjectCommand({
Key,
Bucket: this._configuration.bucket,
ContentType: 'application/json',
Body: JSON.stringify({
...currentIndex,
...modelIndex,
}),
}));
};

for (const [location, models] of Object.entries(index)) {
await processIndex(location, models);
}

await processIndex(null, Object.values(index).flat());
}
}
Loading

0 comments on commit da3a1ef

Please sign in to comment.