Skip to content

Commit

Permalink
Release v1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
exAspArk committed Sep 17, 2024
1 parent a58449e commit d08f13e
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 163 deletions.
26 changes: 0 additions & 26 deletions .github/ISSUE_TEMPLATE /bug-report---.md

This file was deleted.

17 changes: 0 additions & 17 deletions .github/ISSUE_TEMPLATE /feature-request---.md

This file was deleted.

5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## v1.2.0

- Allow calling `setContext` multiple times
- Validate the passed context payload size

## v1.1.0

- Updated license from MIT to LGPL-3.0 `#LoveOpenSource`
Expand Down
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
install:
pnpm install

build:
pnpm run build

publish:
npm publish --access public
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
·
<a href="https://discord.gg/mXeZ6w2tGf">Discord</a>
·
<a href="https://twitter.com/BemiHQ">Twitter</a>
<a href="https://x.com/BemiHQ">X</a>
·
<a href="https://www.linkedin.com/company/bemihq/about">LinkedIn</a>
</p>
Expand Down Expand Up @@ -103,23 +103,23 @@ psql -h [HOSTNAME] -U [USERNAME] -d [DATABASE] -c 'SELECT "primary_key", "table"
27 | todo | DELETE | {"id": 27, "task": "Eat", "isCompleted": false} | {} | {"userId": 187234, "endpoint": "/todo/27", "params": {"id": 27}} | 2023-12-11 17:09:18+00
```

Check out our [TypeORM Docs](https://docs.bemi.io/orms/typeorm) for more details.
Check out our [TypeORM docs](https://docs.bemi.io/orms/typeorm) for more details.

## Architecture overview

Bemi is designed to be lightweight and secure. It takes a practical approach to achieving the benefits of [event sourcing](https://martinfowler.com/eaaDev/EventSourcing.html) without requiring rearchitecting existing code, switching to highly specialized databases, or using unnecessary git-like abstractions on top of databases. We want your system to work the way it already does with your existing database to allow keeping things as simple as possible.
Bemi is designed to be lightweight and secure. It takes a practical approach to achieving the benefits of [event sourcing](https://blog.bemi.io/rethinking-event-sourcing/) without requiring rearchitecting existing code, switching to highly specialized databases, or using unnecessary git-like abstractions on top of databases. We want your system to work the way it already does with your existing database to allow keeping things as simple as possible.

Bemi plugs into both the database and application levels, ensuring 100% reliability and a comprehensive understanding of every change.

On the database level, Bemi securely connects to PostgreSQL's [Write-Ahead Log](https://www.postgresql.org/docs/current/wal-intro.html)'s and implements [Change Data Capture](https://en.wikipedia.org/wiki/Change_data_capture). This allows tracking even the changes that get triggered via direct SQL.
On the database level, Bemi securely connects to PostgreSQL's [Write-Ahead Log](https://www.postgresql.org/docs/current/wal-intro.html)'s and implements [Change Data Capture](https://blog.bemi.io/cdc/). This allows tracking even the changes that get triggered via direct SQL.

On the application level, this package automatically passes application context to the replication logs to enhance the low-level database changes. For example, information about a user who made a change, an API endpoint where the change was triggered, a worker name that automatically triggered database changes, etc.

Bemi workers then stitch the low-level data with the application context and store this information in a structured easily queryable format, as depicted below:

![bemi-architechture](https://docs.bemi.io/img/architecture.png)

The cloud solution includes worker ingesters, queues for fault tolerance, and an automatically scalable cloud-hosted PostgreSQL. Bemi currently doesn't support a self hosted option, but [contact us](mailto:hi@bemi.io) if this is required.
The cloud solution includes worker ingesters, queues for fault tolerance, and a serverless PostgreSQL. If you are interested in running a self-hosted version yourself, see our [self-hosting docs](https://docs.bemi.io/self-hosting).

## License

Expand Down
12 changes: 2 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bemi-db/typeorm",
"version": "1.1.0",
"version": "1.2.0",
"description": "Automatic database change tracking for TypeORM.",
"main": "dist/index.js",
"module": "dist/index.mjs",
Expand All @@ -22,23 +22,15 @@
"express": "^4.18.2"
},
"devDependencies": {
"@types/chai": "^4.3.11",
"@types/express": "^4.17.21",
"@types/mocha": "^10.0.6",
"@types/node": "^20.10.4",
"@types/sinon": "^17.0.2",
"chai": "^4.3.10",
"chai-http": "^4.4.0",
"mocha": "^10.2.0",
"sinon": "^17.0.1",
"ts-node": "^10.9.1",
"tsup": "^8.0.1",
"typescript": "^5.0.0"
},
"registry-url": "https://registry.npmjs.org/",
"scripts": {
"build": "tsup",
"test": "mocha -r ts-node/register './test/*.test.ts'"
"build": "tsup"
},
"tsup": {
"entry": [
Expand Down
50 changes: 34 additions & 16 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,48 @@ interface PostgresDriver {
postgres: any;
}

const asyncLocalStorage = new AsyncLocalStorage();
const ASYNC_LOCAL_STORAGE = new AsyncLocalStorage();
const MAX_CONTEXT_SIZE = 1000000 // ~ 1MB

let wrappedOriginalQuery = false;

const wrapOriginalQuery = (typeORM: DataSource) => {
if (wrappedOriginalQuery) return;

if (!("postgres" in typeORM.driver)) {
throw new Error("Bemi currently supports only PostgreSQL databases");
}

const driver = typeORM.driver as PostgresDriver;
const originalQuery = driver.postgres.Client.prototype.query;
driver.postgres.Client.prototype.query = function(config: any, values: any, clbk: any) {
let sql = config;
const writeOperationsRegex = /(INSERT|UPDATE|DELETE)\s/gi;
const context = ASYNC_LOCAL_STORAGE.getStore();

if (context && sql && writeOperationsRegex.test(sql)) {
const contextComment = `/*Bemi ${JSON.stringify(context)} Bemi*/`
if (contextComment.length <= MAX_CONTEXT_SIZE) {
sql = `${sql} ${contextComment}`;
if (process.env.BEMI_DEBUG) console.log(`>>[Bemi] ${sql}`);
}
}
return originalQuery.call(this, sql, values, clbk);
};

wrappedOriginalQuery = true;
}

export const setContext = (
typeORM: DataSource,
callback: (req: Request) => any
) => {
if ("postgres" in typeORM.driver) {
const driver = typeORM.driver as PostgresDriver;
const originalQuery = driver.postgres.Client.prototype.query;
driver.postgres.Client.prototype.query = async function(config: any, values: any, clbk: any) {
const writeOperationsRegex = /(INSERT|UPDATE|DELETE)\s/gi;
if (writeOperationsRegex.test(config)) {
const context = asyncLocalStorage.getStore();
config = config.concat(` /*Bemi ${JSON.stringify(context)} Bemi*/`);
}
return await originalQuery.call(this, config, values, clbk);
};
} else {
console.error("Bemi currently supports only PostgreSQL databases");
}
wrapOriginalQuery(typeORM);

return (req: Request, _res: Response, next: NextFunction) => {
const config = callback(req);

asyncLocalStorage.run(config, () => {
ASYNC_LOCAL_STORAGE.run(config, () => {
next();
});
};
Expand Down
89 changes: 0 additions & 89 deletions test/metadata.test.ts

This file was deleted.

0 comments on commit d08f13e

Please sign in to comment.