Skip to content

Commit

Permalink
Release v0.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
exAspArk committed Oct 14, 2024
1 parent a1871b9 commit 0f4e667
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- uses: pnpm/action-setup@v2
name: Install pnpm
with:
version: 8
version: 9
run_install: false

- name: Install dependencies
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

#### [v0.6.0](https://github.com/BemiHQ/bemi-prisma/compare/v0.5.0...v0.6.0) - 2024-10-14

- Fix compatibility with Prisma v5.20+

#### [v0.5.0](https://github.com/BemiHQ/bemi-prisma/compare/v0.4.1...v0.5.0) - 2024-08-08

- Allow context passing only for specific models with `includeModels`
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ build:

publish:
npm publish --access public

test:
pnpm run test
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,23 +111,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}, "SQL": "DELETE FROM ..."} | 2023-12-11 17:09:18+00
```

Check out our [Prisma Docs](https://docs.bemi.io/orms/prisma) for more details.
Check out our [Prisma docs](https://docs.bemi.io/orms/prisma) 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) 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) 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 by using a [Prisma extension](https://www.prisma.io/docs/orm/prisma-client/client-extensions) 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
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bemi-db/prisma",
"version": "0.5.0",
"version": "0.6.0",
"description": "Automatic data change tracking for Prisma",
"main": "dist/index.js",
"module": "./dist/index.mjs",
Expand All @@ -22,14 +22,14 @@
},
"homepage": "https://github.com/BemiHQ/bemi-prisma#readme",
"dependencies": {
"@prisma/driver-adapter-utils": "~5.15.0",
"@prisma/driver-adapter-utils": "~5.20.0",
"commander": "^11.1.0",
"kleur": "^4.1.5",
"pg": "^8.11.5",
"postgres-array": "^3.0.2"
},
"peerDependencies": {
"@prisma/client": "^5.15.0"
"@prisma/client": "^5.20.0"
},
"devDependencies": {
"@types/express": "^4.17.21",
Expand Down
13 changes: 11 additions & 2 deletions src/conversion.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Last commit: https://github.com/prisma/prisma/commit/b36b73c2c349f80dc456dfd321f3c4cdc2aacfed#diff-848cf139de14ecb4c49c2e3f52703fecef4789f51052651f22ca2c5caf0afe99
// Last commit: https://github.com/prisma/prisma/commit/47e8f1307ba73df65b80da32c4dd0d5e2816cc95
// https://github.com/prisma/prisma/compare/b36b73c2c349f80dc456dfd321f3c4cdc2aacfed..47e8f1307ba73df65b80da32c4dd0d5e2816cc95

// @ts-ignore: this is used to avoid the `Module '"<path>/node_modules/@types/pg/index"' has no default export.` error.
import { type ColumnType, ColumnTypeEnum } from '@prisma/driver-adapter-utils'
import pg from 'pg'
import { parse as parseArray } from 'postgres-array'

const { types } = pg
const { builtins: ScalarColumnType, getTypeParser } = types
import { type ColumnType, ColumnTypeEnum } from '@prisma/driver-adapter-utils'

/**
* PostgreSQL array column types (not defined in ScalarColumnType).
Expand Down Expand Up @@ -327,6 +328,13 @@ function normalize_money(money: string): string {
return money.slice(1)
}

/******************/
/* XML handling */
/******************/
function normalize_xml(xml: string): string {
return xml
}

/*****************/
/* JSON handling */
/*****************/
Expand Down Expand Up @@ -410,6 +418,7 @@ export const customParsers = {
[ArrayColumnType.BYTEA_ARRAY]: normalizeByteaArray,
[ArrayColumnType.BIT_ARRAY]: normalize_array(normalizeBit),
[ArrayColumnType.VARBIT_ARRAY]: normalize_array(normalizeBit),
[ArrayColumnType.XML_ARRAY]: normalize_array(normalize_xml),
}

// https://github.com/brianc/node-postgres/pull/2930
Expand Down
2 changes: 1 addition & 1 deletion src/pg-adapter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const callMockedPgAdapater = async (queries: string[]) => {
const pgAdapter = new PrismaPg(client as any)

for(const sql of queries) {
await pgAdapter['performIO']({ sql, args: [] })
await pgAdapter['performIO']({ sql, args: [], argTypes: [] })
}

return query
Expand Down
38 changes: 25 additions & 13 deletions src/pg-adapter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable @typescript-eslint/require-await */

import type {
ColumnType,
ConnectionInfo,
Expand All @@ -8,6 +9,7 @@ import type {
Result,
ResultSet,
Transaction,
TransactionContext,
TransactionOptions,
} from '@prisma/driver-adapter-utils'
import { Debug, err, ok } from '@prisma/driver-adapter-utils'
Expand Down Expand Up @@ -237,6 +239,23 @@ class PgTransaction extends PgQueryable<TransactionClient> implements Transactio
}
}

class PgTransactionContext extends PgQueryable<TransactionClient> implements TransactionContext {
constructor(readonly conn: TransactionClient) {
super(conn)
}

async startTransaction(): Promise<Result<Transaction>> {
const options: TransactionOptions = {
usePhantomQuery: false,
}

const tag = '[js::startTransaction]'
debug('%s options: %O', tag, options)

return ok(new PgTransaction(this.conn, options))
}
}

export type PrismaPgOptions = {
schema?: string
}
Expand Down Expand Up @@ -276,21 +295,14 @@ const adapter = new PrismaPg(pool)
})
}

async startTransaction(): Promise<Result<Transaction>> {
const options: TransactionOptions = {
usePhantomQuery: false,
}

const tag = '[js::startTransaction]'
debug(`${tag} options: %O`, options)

async transactionContext(): Promise<Result<TransactionContext>> {
// PATCH: Customize connection
const connection = await this.client.connect() as TransactionClient
connection.previousQueries = []
connection.logQueries = this.logQueries
connection.readyToExecuteTransaction = false
const conn = await this.client.connect() as TransactionClient
conn.previousQueries = []
conn.logQueries = this.logQueries
conn.readyToExecuteTransaction = false
// PATCH: end

return ok(new PgTransaction(connection, options))
return ok(new PgTransactionContext(conn))
}
}

0 comments on commit 0f4e667

Please sign in to comment.