prisma-extension-kysely 1.0.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,12 +3,23 @@
3
3
  [![npm version](https://badge.fury.io/js/prisma-extension-kysely.svg)](https://badge.fury.io/js/prisma-extension-kysely)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/prisma-extension-kysely.svg)](https://www.npmjs.com/package/prisma-extension-kysely)
5
5
  [![GitHub license](https://img.shields.io/github/license/eoin-obrien/prisma-extension-kysely.svg)](https://www.npmjs.com/package/prisma-extension-kysely)
6
- [![Node.js CI](https://github.com/eoin-obrien/prisma-extension-kysely/actions/workflows/node.js.yml/badge.svg)](https://github.com/eoin-obrien/prisma-extension-kysely/actions/workflows/node.js.yml)
6
+ [![Node.js CI](https://github.com/eoin-obrien/prisma-extension-kysely/actions/workflows/ci.yml/badge.svg)](https://github.com/eoin-obrien/prisma-extension-kysely/actions/workflows/ci.yml)
7
7
  [![Node.js Package](https://github.com/eoin-obrien/prisma-extension-kysely/actions/workflows/npm-publish.yml/badge.svg)](https://github.com/eoin-obrien/prisma-extension-kysely/actions/workflows/npm-publish.yml)
8
8
  [![codecov](https://codecov.io/gh/eoin-obrien/prisma-extension-kysely/graph/badge.svg?token=C18C7BGISJ)](https://codecov.io/gh/eoin-obrien/prisma-extension-kysely)
9
+ [![Maintainability](https://api.codeclimate.com/v1/badges/241b8b2b35abafc8af6e/maintainability)](https://codeclimate.com/github/eoin-obrien/prisma-extension-kysely/maintainability)
9
10
 
10
11
  Writing and maintaining raw SQL queries for Prisma can be a tedious and error-prone task. The moment you need to write a query that is not supported out-of-the-box by Prisma, you lose all of that type-safety and autocompletion. This is where `prisma-extension-kysely` comes in! It allows you to easily write raw SQL queries in a type-safe manner with [`kysely`](https://kysely.dev/) and integrate them seamlessly with Prisma.
11
12
 
13
+ And the best part? You can use all of your favorite [`kysely`](https://kysely.dev/) plugins with `prisma-extension-kysely` too!
14
+
15
+ You don't have to take our word for it, though:
16
+
17
+ > I have to say, this is BY FAR the most amazing community package I've seen in the Prisma ecosystem!
18
+ >
19
+ > It makes it so much more convenient to drop down to raw SQL when needed without sacrificing DX — best of both worlds! 🚀
20
+
21
+ — [Nikolas Burk, DevRel @ Prisma](https://twitter.com/nikolasburk/status/1747901827960471699)
22
+
12
23
  ## Features
13
24
 
14
25
  - **Type-safe** — Write raw SQL queries in a type-safe manner with `kysely`
@@ -52,17 +63,24 @@ Extend your Prisma Client:
52
63
  import kyselyExtension from "prisma-extension-kysely";
53
64
  import type { DB } from "./prisma/generated/types";
54
65
 
55
- // Don't forget to customize this to match your database!
56
- const kysely = new Kysely<DB>({
57
- dialect: {
58
- createAdapter: () => new PostgresAdapter(),
59
- createDriver: () => new DummyDriver(),
60
- createIntrospector: (db) => new PostgresIntrospector(db),
61
- createQueryCompiler: () => new PostgresQueryCompiler(),
62
- },
63
- });
64
-
65
- const prisma = new PrismaClient().$extends(kyselyExtension({ kysely }));
66
+ const prisma = new PrismaClient().$extends(
67
+ kyselyExtension({
68
+ kysely: (driver) =>
69
+ new Kysely<DB>({
70
+ dialect: {
71
+ // This is where the magic happens!
72
+ createDriver: () => driver,
73
+ // Don't forget to customize these to match your database!
74
+ createAdapter: () => new PostgresAdapter(),
75
+ createIntrospector: (db) => new PostgresIntrospector(db),
76
+ createQueryCompiler: () => new PostgresQueryCompiler(),
77
+ },
78
+ plugins: [
79
+ // Add your favorite plugins here!
80
+ ],
81
+ }),
82
+ }),
83
+ );
66
84
  ```
67
85
 
68
86
  It's that simple! Now you can write raw SQL queries with `kysely` and use them with Prisma:
@@ -78,20 +96,76 @@ const query = prisma.$kysely
78
96
  .where("id", "=", id);
79
97
 
80
98
  // Thanks to kysely's magic, everything is type-safe!
81
- const result = await prisma.$kyselyQuery(query);
99
+ const result = await query.execute();
82
100
 
83
101
  // You can also execute queries without fetching the results
84
- await prisma.$kyselyExecute(
85
- prisma.$kysely.deleteFrom("User").where("id", "=", id),
102
+ await prisma.$kysely.deleteFrom("User").where("id", "=", id).execute();
103
+ ```
104
+
105
+ ## Transactions
106
+
107
+ Prisma's interactive transactions are fully supported by `prisma-extension-kysely`! Just remeber to use `tx.$kysely` instead of `prisma.$kysely`, and you're good to go:
108
+
109
+ ```typescript
110
+ await prisma.$transaction(async (tx) => {
111
+ await tx.$kysely
112
+ .insertInto("User")
113
+ .values({ id: 1, name: "John Doe" })
114
+ .execute();
115
+
116
+ await tx.$kysely
117
+ .insertInto("User")
118
+ .values({ id: 2, name: "Jane Doe" })
119
+ .execute();
120
+ });
121
+ ```
122
+
123
+ Don't try to use Kysely's `transaction` method directly, though. It's not supported by `prisma-extension-kysely`, and it will throw an error if you try to use it.
124
+
125
+ ```typescript
126
+ // Don't do this! Prefer prisma.$transaction instead.
127
+ await prisma.$kysely.transaction().execute(async (trx) => {});
128
+ ```
129
+
130
+ ## Plugins
131
+
132
+ Do you love Kysely's plugins? So do we! You can use them with `prisma-extension-kysely` as well:
133
+
134
+ ```typescript
135
+ const prisma = new PrismaClient().$extends(
136
+ kyselyExtension({
137
+ kysely: (driver) =>
138
+ new Kysely<DB>({
139
+ dialect: {
140
+ createDriver: () => driver,
141
+ createAdapter: () => new PostgresAdapter(),
142
+ createIntrospector: (db) => new PostgresIntrospector(db),
143
+ createQueryCompiler: () => new PostgresQueryCompiler(),
144
+ },
145
+ // Use your favorite plugins!
146
+ plugins: [new CamelCasePlugin()],
147
+ }),
148
+ }),
86
149
  );
87
150
  ```
88
151
 
152
+ If you're using the `CamelCasePlugin`, don't forget to add the `camelCase` option to your Prisma schema too:
153
+
154
+ ```prisma
155
+ generator kysely {
156
+ provider = "prisma-kysely"
157
+ camelCase = true
158
+ }
159
+ ```
160
+
161
+ Take a look at [the camel case example](examples/camel-case/) to see it in action! Check out the [Kysely documentation](https://kysely.dev/) for more information about plugins.
162
+
89
163
  ## Examples
90
164
 
91
- Check out the [example](example) directory for a sample project!
165
+ Check out the [examples](examples) directory for a sample project!
92
166
 
93
167
  ```shell
94
- cd examples
168
+ cd examples/basic
95
169
  npm install
96
170
  npx prisma db push
97
171
  npm run dev
@@ -0,0 +1,12 @@
1
+ import { PrismaClient } from "@prisma/client/extension";
2
+ import { CompiledQuery, DatabaseConnection, QueryResult } from "kysely";
3
+ /**
4
+ * A Kysely database connection that uses Prisma as the driver
5
+ */
6
+ export declare class PrismaConnection implements DatabaseConnection {
7
+ private readonly prisma;
8
+ constructor(prisma: PrismaClient);
9
+ executeQuery<R>(compiledQuery: CompiledQuery<unknown>): Promise<QueryResult<R>>;
10
+ streamQuery<R>(_compiledQuery: CompiledQuery<unknown>, _chunkSize?: number | undefined): AsyncIterableIterator<QueryResult<R>>;
11
+ }
12
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EACL,aAAa,EACb,kBAAkB,EAGlB,WAAW,EAEZ,MAAM,QAAQ,CAAC;AAEhB;;GAEG;AACH,qBAAa,gBAAiB,YAAW,kBAAkB;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,YAAY;IAE3C,YAAY,CAAC,CAAC,EAClB,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,GACpC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IA2B1B,WAAW,CAAC,CAAC,EACX,cAAc,EAAE,aAAa,CAAC,OAAO,CAAC,EACtC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAC9B,qBAAqB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAKzC"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PrismaConnection = void 0;
13
+ const kysely_1 = require("kysely");
14
+ /**
15
+ * A Kysely database connection that uses Prisma as the driver
16
+ */
17
+ class PrismaConnection {
18
+ constructor(prisma) {
19
+ this.prisma = prisma;
20
+ }
21
+ executeQuery(compiledQuery) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const { sql, parameters, query } = compiledQuery;
24
+ // Delete, update and insert queries return the number of affected rows if no returning clause is specified
25
+ const supportsReturning = kysely_1.DeleteQueryNode.is(query) ||
26
+ kysely_1.UpdateQueryNode.is(query) ||
27
+ kysely_1.InsertQueryNode.is(query);
28
+ const shouldReturnAffectedRows = supportsReturning && !query.returning;
29
+ // Execute the query with $executeRawUnsafe to get the number of affected rows
30
+ if (shouldReturnAffectedRows) {
31
+ const numAffectedRows = BigInt(yield this.prisma.$executeRawUnsafe(sql, ...parameters));
32
+ return {
33
+ rows: [],
34
+ numAffectedRows: numAffectedRows,
35
+ numUpdatedOrDeletedRows: numAffectedRows,
36
+ };
37
+ }
38
+ // Otherwise, execute it with $queryRawUnsafe to get the query results
39
+ const rows = yield this.prisma.$queryRawUnsafe(sql, ...parameters);
40
+ return { rows };
41
+ });
42
+ }
43
+ streamQuery(_compiledQuery, _chunkSize) {
44
+ throw new Error("prisma-extension-kysely does not support streaming queries");
45
+ }
46
+ }
47
+ exports.PrismaConnection = PrismaConnection;
@@ -0,0 +1,14 @@
1
+ import type { PrismaClient } from "@prisma/client/extension";
2
+ import { DatabaseConnection, Driver, TransactionSettings } from "kysely";
3
+ export declare class PrismaDriver<T extends PrismaClient> implements Driver {
4
+ private readonly prisma;
5
+ constructor(prisma: T);
6
+ init(): Promise<void>;
7
+ acquireConnection(): Promise<DatabaseConnection>;
8
+ beginTransaction(_connection: DatabaseConnection, _settings: TransactionSettings): Promise<void>;
9
+ commitTransaction(_connection: DatabaseConnection): Promise<void>;
10
+ rollbackTransaction(_connection: DatabaseConnection): Promise<void>;
11
+ releaseConnection(_connection: DatabaseConnection): Promise<void>;
12
+ destroy(): Promise<void>;
13
+ }
14
+ //# sourceMappingURL=driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAGzE,qBAAa,YAAY,CAAC,CAAC,SAAS,YAAY,CAAE,YAAW,MAAM;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,CAAC;IAEhC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAErB,iBAAiB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAIhD,gBAAgB,CACpB,WAAW,EAAE,kBAAkB,EAC/B,SAAS,EAAE,mBAAmB,GAC7B,OAAO,CAAC,IAAI,CAAC;IAIV,iBAAiB,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,iBAAiB,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAEjE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAC/B"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PrismaDriver = void 0;
13
+ const connection_js_1 = require("./connection.js");
14
+ class PrismaDriver {
15
+ constructor(prisma) {
16
+ this.prisma = prisma;
17
+ }
18
+ init() {
19
+ return __awaiter(this, void 0, void 0, function* () { });
20
+ }
21
+ acquireConnection() {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ return new connection_js_1.PrismaConnection(this.prisma);
24
+ });
25
+ }
26
+ beginTransaction(_connection, _settings) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ throw new Error("prisma-extension-kysely does not support transactions");
29
+ });
30
+ }
31
+ commitTransaction(_connection) {
32
+ return __awaiter(this, void 0, void 0, function* () {
33
+ throw new Error("prisma-extension-kysely does not support transactions");
34
+ });
35
+ }
36
+ rollbackTransaction(_connection) {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ throw new Error("prisma-extension-kysely does not support transactions");
39
+ });
40
+ }
41
+ releaseConnection(_connection) {
42
+ return __awaiter(this, void 0, void 0, function* () { });
43
+ }
44
+ destroy() {
45
+ return __awaiter(this, void 0, void 0, function* () { });
46
+ }
47
+ }
48
+ exports.PrismaDriver = PrismaDriver;
@@ -0,0 +1,29 @@
1
+ import { Kysely } from "kysely";
2
+ import { PrismaDriver } from "./driver.js";
3
+ /**
4
+ * The configuration object for the Prisma Kysely extension
5
+ */
6
+ export type PrismaKyselyExtensionArgs<Database> = {
7
+ /**
8
+ * The Kysely instance to provide to the Prisma client
9
+ */
10
+ kysely: (driver: PrismaDriver<any>) => Kysely<Database>;
11
+ };
12
+ /**
13
+ * Define a Prisma extension that adds Kysely query builder methods to the Prisma client
14
+ * @param extensionArgs The extension configuration object
15
+ */
16
+ declare const _default: <Database>(extensionArgs: PrismaKyselyExtensionArgs<Database>) => (client: any) => {
17
+ $extends: {
18
+ extArgs: {
19
+ result: {};
20
+ model: {};
21
+ query: {};
22
+ client: {
23
+ $kysely: () => Kysely<Database>;
24
+ };
25
+ };
26
+ };
27
+ };
28
+ export default _default;
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,yBAAyB,CAAC,QAAQ,IAAI;IAChD;;OAEG;IAEH,MAAM,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC;CACzD,CAAC;AAEF;;;GAGG;;;;;;;;;;;;;AACH,wBA+CK"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
+ const client_1 = require("@prisma/client");
14
+ const driver_js_1 = require("./driver.js");
15
+ /**
16
+ * Define a Prisma extension that adds Kysely query builder methods to the Prisma client
17
+ * @param extensionArgs The extension configuration object
18
+ */
19
+ exports.default = (extensionArgs) => client_1.Prisma.defineExtension((client) => {
20
+ const driver = new driver_js_1.PrismaDriver(client);
21
+ const kysely = extensionArgs.kysely(driver);
22
+ const extendedClient = client.$extends({
23
+ name: "prisma-extension-kysely",
24
+ client: {
25
+ /**
26
+ * The Kysely instance used by the Prisma client
27
+ */
28
+ $kysely: kysely,
29
+ },
30
+ });
31
+ // Wrap the $transaction method to attach a fresh Kysely instance to the transaction client
32
+ const kyselyTransaction = (target) => (...args) => {
33
+ if (typeof args[0] === "function") {
34
+ // If the first argument is a function, add a fresh Kysely instance to the transaction client
35
+ const [fn, options] = args;
36
+ return target.$transaction((tx) => __awaiter(void 0, void 0, void 0, function* () {
37
+ // The Kysely instance should call the transaction client, not the original client
38
+ const driver = new driver_js_1.PrismaDriver(tx);
39
+ const kysely = extensionArgs.kysely(driver);
40
+ tx.$kysely = kysely;
41
+ return fn(tx);
42
+ }), options);
43
+ }
44
+ else {
45
+ // Otherwise, just call the original $transaction method
46
+ return target.$transaction(...args);
47
+ }
48
+ };
49
+ // Attach the wrapped $transaction method to the extended client using a proxy
50
+ const extendedClientProxy = new Proxy(extendedClient, {
51
+ get: (target, prop, receiver) => {
52
+ if (prop === "$transaction") {
53
+ return kyselyTransaction(target);
54
+ }
55
+ return Reflect.get(target, prop, receiver);
56
+ },
57
+ });
58
+ return extendedClientProxy;
59
+ });
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "prisma-extension-kysely",
3
+ "version": "2.1.0",
4
+ "author": {
5
+ "name": "Eoin O'Brien",
6
+ "url": "https://eoin.ai",
7
+ "email": "eoin@tracworx.ai"
8
+ },
9
+ "description": "Prisma extension for Kysely",
10
+ "license": "MIT",
11
+ "homepage": "https://github.com/eoin-obrien/prisma-extension-kysely#readme",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/eoin-obrien/prisma-extension-kysely"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/eoin-obrien/prisma-extension-kysely/issues"
18
+ },
19
+ "keywords": [
20
+ "prisma",
21
+ "@prisma/client",
22
+ "extension",
23
+ "kysely",
24
+ "sql",
25
+ "query builder",
26
+ "orm",
27
+ "database",
28
+ "postgresql",
29
+ "mysql",
30
+ "sqlite"
31
+ ],
32
+ "type": "commonjs",
33
+ "files": [
34
+ "dist"
35
+ ],
36
+ "scripts": {
37
+ "pretest": "prisma db push",
38
+ "test": "jest",
39
+ "test:watch": "npm run test -- --watch",
40
+ "test:coverage": "npm run test -- --coverage",
41
+ "build:clean": "rm -rf ./dist",
42
+ "build:compile": "tsc -b tsconfig.json tsconfig.cjs.json && tsconfig-to-dual-package",
43
+ "build": "npm run build:clean && npm run build:compile",
44
+ "prepack": "npm run build",
45
+ "prepare": "husky install",
46
+ "commit": "git-cz",
47
+ "lint": "eslint .",
48
+ "lint:fix": "eslint --fix .",
49
+ "format": "prettier --write .",
50
+ "format:check": "prettier --check ."
51
+ },
52
+ "config": {
53
+ "commitizen": {
54
+ "path": "@commitlint/cz-commitlint"
55
+ }
56
+ },
57
+ "peerDependencies": {
58
+ "@prisma/client": "latest"
59
+ },
60
+ "devDependencies": {
61
+ "@commitlint/cli": "^18.4.3",
62
+ "@commitlint/config-conventional": "^18.4.3",
63
+ "@commitlint/cz-commitlint": "^18.4.3",
64
+ "@prisma/client": "latest",
65
+ "@types/jest": "^29.5.10",
66
+ "@typescript-eslint/eslint-plugin": "^6.13.0",
67
+ "@typescript-eslint/parser": "^6.13.0",
68
+ "commitizen": "^4.3.0",
69
+ "eslint": "^8.54.0",
70
+ "eslint-config-prettier": "^9.0.0",
71
+ "eslint-plugin-require-extensions": "^0.1.3",
72
+ "husky": "^9.0.0",
73
+ "inquirer": "^8.2.6",
74
+ "jest": "^29.7.0",
75
+ "jest-mock-extended": "^3.0.5",
76
+ "kysely": "^0.27.0",
77
+ "prettier": "3.2.4",
78
+ "prisma": "latest",
79
+ "prisma-kysely": "^1.7.1",
80
+ "ts-jest": "^29.1.1",
81
+ "tsconfig-to-dual-package": "^1.2.0",
82
+ "typescript": "^5.0.0"
83
+ }
84
+ }
@@ -0,0 +1,12 @@
1
+ import { PrismaClient } from "@prisma/client/extension";
2
+ import { CompiledQuery, DatabaseConnection, QueryResult } from "kysely";
3
+ /**
4
+ * A Kysely database connection that uses Prisma as the driver
5
+ */
6
+ export declare class PrismaConnection implements DatabaseConnection {
7
+ private readonly prisma;
8
+ constructor(prisma: PrismaClient);
9
+ executeQuery<R>(compiledQuery: CompiledQuery<unknown>): Promise<QueryResult<R>>;
10
+ streamQuery<R>(_compiledQuery: CompiledQuery<unknown>, _chunkSize?: number | undefined): AsyncIterableIterator<QueryResult<R>>;
11
+ }
12
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EACL,aAAa,EACb,kBAAkB,EAGlB,WAAW,EAEZ,MAAM,QAAQ,CAAC;AAEhB;;GAEG;AACH,qBAAa,gBAAiB,YAAW,kBAAkB;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,YAAY;IAE3C,YAAY,CAAC,CAAC,EAClB,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,GACpC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IA2B1B,WAAW,CAAC,CAAC,EACX,cAAc,EAAE,aAAa,CAAC,OAAO,CAAC,EACtC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAC9B,qBAAqB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAKzC"}
@@ -0,0 +1,43 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { DeleteQueryNode, InsertQueryNode, UpdateQueryNode, } from "kysely";
11
+ /**
12
+ * A Kysely database connection that uses Prisma as the driver
13
+ */
14
+ export class PrismaConnection {
15
+ constructor(prisma) {
16
+ this.prisma = prisma;
17
+ }
18
+ executeQuery(compiledQuery) {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ const { sql, parameters, query } = compiledQuery;
21
+ // Delete, update and insert queries return the number of affected rows if no returning clause is specified
22
+ const supportsReturning = DeleteQueryNode.is(query) ||
23
+ UpdateQueryNode.is(query) ||
24
+ InsertQueryNode.is(query);
25
+ const shouldReturnAffectedRows = supportsReturning && !query.returning;
26
+ // Execute the query with $executeRawUnsafe to get the number of affected rows
27
+ if (shouldReturnAffectedRows) {
28
+ const numAffectedRows = BigInt(yield this.prisma.$executeRawUnsafe(sql, ...parameters));
29
+ return {
30
+ rows: [],
31
+ numAffectedRows: numAffectedRows,
32
+ numUpdatedOrDeletedRows: numAffectedRows,
33
+ };
34
+ }
35
+ // Otherwise, execute it with $queryRawUnsafe to get the query results
36
+ const rows = yield this.prisma.$queryRawUnsafe(sql, ...parameters);
37
+ return { rows };
38
+ });
39
+ }
40
+ streamQuery(_compiledQuery, _chunkSize) {
41
+ throw new Error("prisma-extension-kysely does not support streaming queries");
42
+ }
43
+ }
@@ -0,0 +1,14 @@
1
+ import type { PrismaClient } from "@prisma/client/extension";
2
+ import { DatabaseConnection, Driver, TransactionSettings } from "kysely";
3
+ export declare class PrismaDriver<T extends PrismaClient> implements Driver {
4
+ private readonly prisma;
5
+ constructor(prisma: T);
6
+ init(): Promise<void>;
7
+ acquireConnection(): Promise<DatabaseConnection>;
8
+ beginTransaction(_connection: DatabaseConnection, _settings: TransactionSettings): Promise<void>;
9
+ commitTransaction(_connection: DatabaseConnection): Promise<void>;
10
+ rollbackTransaction(_connection: DatabaseConnection): Promise<void>;
11
+ releaseConnection(_connection: DatabaseConnection): Promise<void>;
12
+ destroy(): Promise<void>;
13
+ }
14
+ //# sourceMappingURL=driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAGzE,qBAAa,YAAY,CAAC,CAAC,SAAS,YAAY,CAAE,YAAW,MAAM;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,CAAC;IAEhC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAErB,iBAAiB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAIhD,gBAAgB,CACpB,WAAW,EAAE,kBAAkB,EAC/B,SAAS,EAAE,mBAAmB,GAC7B,OAAO,CAAC,IAAI,CAAC;IAIV,iBAAiB,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,iBAAiB,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAEjE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAC/B"}
@@ -0,0 +1,44 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { PrismaConnection } from "./connection.js";
11
+ export class PrismaDriver {
12
+ constructor(prisma) {
13
+ this.prisma = prisma;
14
+ }
15
+ init() {
16
+ return __awaiter(this, void 0, void 0, function* () { });
17
+ }
18
+ acquireConnection() {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ return new PrismaConnection(this.prisma);
21
+ });
22
+ }
23
+ beginTransaction(_connection, _settings) {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ throw new Error("prisma-extension-kysely does not support transactions");
26
+ });
27
+ }
28
+ commitTransaction(_connection) {
29
+ return __awaiter(this, void 0, void 0, function* () {
30
+ throw new Error("prisma-extension-kysely does not support transactions");
31
+ });
32
+ }
33
+ rollbackTransaction(_connection) {
34
+ return __awaiter(this, void 0, void 0, function* () {
35
+ throw new Error("prisma-extension-kysely does not support transactions");
36
+ });
37
+ }
38
+ releaseConnection(_connection) {
39
+ return __awaiter(this, void 0, void 0, function* () { });
40
+ }
41
+ destroy() {
42
+ return __awaiter(this, void 0, void 0, function* () { });
43
+ }
44
+ }
@@ -0,0 +1,29 @@
1
+ import { Kysely } from "kysely";
2
+ import { PrismaDriver } from "./driver.js";
3
+ /**
4
+ * The configuration object for the Prisma Kysely extension
5
+ */
6
+ export type PrismaKyselyExtensionArgs<Database> = {
7
+ /**
8
+ * The Kysely instance to provide to the Prisma client
9
+ */
10
+ kysely: (driver: PrismaDriver<any>) => Kysely<Database>;
11
+ };
12
+ /**
13
+ * Define a Prisma extension that adds Kysely query builder methods to the Prisma client
14
+ * @param extensionArgs The extension configuration object
15
+ */
16
+ declare const _default: <Database>(extensionArgs: PrismaKyselyExtensionArgs<Database>) => (client: any) => {
17
+ $extends: {
18
+ extArgs: {
19
+ result: {};
20
+ model: {};
21
+ query: {};
22
+ client: {
23
+ $kysely: () => Kysely<Database>;
24
+ };
25
+ };
26
+ };
27
+ };
28
+ export default _default;
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,yBAAyB,CAAC,QAAQ,IAAI;IAChD;;OAEG;IAEH,MAAM,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC;CACzD,CAAC;AAEF;;;GAGG;;;;;;;;;;;;;AACH,wBA+CK"}
@@ -0,0 +1,57 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ /* eslint-disable @typescript-eslint/no-explicit-any */
11
+ import { Prisma } from "@prisma/client";
12
+ import { PrismaDriver } from "./driver.js";
13
+ /**
14
+ * Define a Prisma extension that adds Kysely query builder methods to the Prisma client
15
+ * @param extensionArgs The extension configuration object
16
+ */
17
+ export default (extensionArgs) => Prisma.defineExtension((client) => {
18
+ const driver = new PrismaDriver(client);
19
+ const kysely = extensionArgs.kysely(driver);
20
+ const extendedClient = client.$extends({
21
+ name: "prisma-extension-kysely",
22
+ client: {
23
+ /**
24
+ * The Kysely instance used by the Prisma client
25
+ */
26
+ $kysely: kysely,
27
+ },
28
+ });
29
+ // Wrap the $transaction method to attach a fresh Kysely instance to the transaction client
30
+ const kyselyTransaction = (target) => (...args) => {
31
+ if (typeof args[0] === "function") {
32
+ // If the first argument is a function, add a fresh Kysely instance to the transaction client
33
+ const [fn, options] = args;
34
+ return target.$transaction((tx) => __awaiter(void 0, void 0, void 0, function* () {
35
+ // The Kysely instance should call the transaction client, not the original client
36
+ const driver = new PrismaDriver(tx);
37
+ const kysely = extensionArgs.kysely(driver);
38
+ tx.$kysely = kysely;
39
+ return fn(tx);
40
+ }), options);
41
+ }
42
+ else {
43
+ // Otherwise, just call the original $transaction method
44
+ return target.$transaction(...args);
45
+ }
46
+ };
47
+ // Attach the wrapped $transaction method to the extended client using a proxy
48
+ const extendedClientProxy = new Proxy(extendedClient, {
49
+ get: (target, prop, receiver) => {
50
+ if (prop === "$transaction") {
51
+ return kyselyTransaction(target);
52
+ }
53
+ return Reflect.get(target, prop, receiver);
54
+ },
55
+ });
56
+ return extendedClientProxy;
57
+ });
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "prisma-extension-kysely",
3
+ "version": "2.1.0",
4
+ "author": {
5
+ "name": "Eoin O'Brien",
6
+ "url": "https://eoin.ai",
7
+ "email": "eoin@tracworx.ai"
8
+ },
9
+ "description": "Prisma extension for Kysely",
10
+ "license": "MIT",
11
+ "homepage": "https://github.com/eoin-obrien/prisma-extension-kysely#readme",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/eoin-obrien/prisma-extension-kysely"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/eoin-obrien/prisma-extension-kysely/issues"
18
+ },
19
+ "keywords": [
20
+ "prisma",
21
+ "@prisma/client",
22
+ "extension",
23
+ "kysely",
24
+ "sql",
25
+ "query builder",
26
+ "orm",
27
+ "database",
28
+ "postgresql",
29
+ "mysql",
30
+ "sqlite"
31
+ ],
32
+ "type": "module",
33
+ "files": [
34
+ "dist"
35
+ ],
36
+ "scripts": {
37
+ "pretest": "prisma db push",
38
+ "test": "jest",
39
+ "test:watch": "npm run test -- --watch",
40
+ "test:coverage": "npm run test -- --coverage",
41
+ "build:clean": "rm -rf ./dist",
42
+ "build:compile": "tsc -b tsconfig.json tsconfig.cjs.json && tsconfig-to-dual-package",
43
+ "build": "npm run build:clean && npm run build:compile",
44
+ "prepack": "npm run build",
45
+ "prepare": "husky install",
46
+ "commit": "git-cz",
47
+ "lint": "eslint .",
48
+ "lint:fix": "eslint --fix .",
49
+ "format": "prettier --write .",
50
+ "format:check": "prettier --check ."
51
+ },
52
+ "config": {
53
+ "commitizen": {
54
+ "path": "@commitlint/cz-commitlint"
55
+ }
56
+ },
57
+ "peerDependencies": {
58
+ "@prisma/client": "latest"
59
+ },
60
+ "devDependencies": {
61
+ "@commitlint/cli": "^18.4.3",
62
+ "@commitlint/config-conventional": "^18.4.3",
63
+ "@commitlint/cz-commitlint": "^18.4.3",
64
+ "@prisma/client": "latest",
65
+ "@types/jest": "^29.5.10",
66
+ "@typescript-eslint/eslint-plugin": "^6.13.0",
67
+ "@typescript-eslint/parser": "^6.13.0",
68
+ "commitizen": "^4.3.0",
69
+ "eslint": "^8.54.0",
70
+ "eslint-config-prettier": "^9.0.0",
71
+ "eslint-plugin-require-extensions": "^0.1.3",
72
+ "husky": "^9.0.0",
73
+ "inquirer": "^8.2.6",
74
+ "jest": "^29.7.0",
75
+ "jest-mock-extended": "^3.0.5",
76
+ "kysely": "^0.27.0",
77
+ "prettier": "3.2.4",
78
+ "prisma": "latest",
79
+ "prisma-kysely": "^1.7.1",
80
+ "ts-jest": "^29.1.1",
81
+ "tsconfig-to-dual-package": "^1.2.0",
82
+ "typescript": "^5.0.0"
83
+ }
84
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prisma-extension-kysely",
3
- "version": "1.0.4",
3
+ "version": "2.1.0",
4
4
  "author": {
5
5
  "name": "Eoin O'Brien",
6
6
  "url": "https://eoin.ai",
@@ -8,10 +8,14 @@
8
8
  },
9
9
  "description": "Prisma extension for Kysely",
10
10
  "license": "MIT",
11
+ "homepage": "https://github.com/eoin-obrien/prisma-extension-kysely#readme",
11
12
  "repository": {
12
13
  "type": "git",
13
14
  "url": "https://github.com/eoin-obrien/prisma-extension-kysely"
14
15
  },
16
+ "bugs": {
17
+ "url": "https://github.com/eoin-obrien/prisma-extension-kysely/issues"
18
+ },
15
19
  "keywords": [
16
20
  "prisma",
17
21
  "@prisma/client",
@@ -25,22 +29,40 @@
25
29
  "mysql",
26
30
  "sqlite"
27
31
  ],
28
- "main": "dist/index.js",
29
- "types": "dist/index.d.ts",
32
+ "type": "module",
33
+ "main": "dist/cjs/index.js",
34
+ "module": "dist/esm/index.js",
35
+ "types": "dist/cjs/index.d.ts",
36
+ "exports": {
37
+ ".": {
38
+ "import": {
39
+ "types": "./dist/esm/index.d.ts",
40
+ "default": "./dist/esm/index.js"
41
+ },
42
+ "require": {
43
+ "types": "./dist/cjs/index.d.ts",
44
+ "default": "./dist/cjs/index.js"
45
+ },
46
+ "default": "./dist/cjs/index.js"
47
+ },
48
+ "./package.json": "./package.json"
49
+ },
30
50
  "files": [
31
51
  "dist"
32
52
  ],
33
53
  "scripts": {
34
- "pretest": "npm run build && prisma db push",
54
+ "pretest": "prisma db push",
35
55
  "test": "jest",
36
- "test:watch": "jest --watch",
37
- "test:coverage": "jest --coverage",
38
- "clean": "rm -rf ./dist",
39
- "build": "tsc",
40
- "prepack": "npm run clean && npm run build",
56
+ "test:watch": "npm run test -- --watch",
57
+ "test:coverage": "npm run test -- --coverage",
58
+ "build:clean": "rm -rf ./dist",
59
+ "build:compile": "tsc -b tsconfig.json tsconfig.cjs.json && tsconfig-to-dual-package",
60
+ "build": "npm run build:clean && npm run build:compile",
61
+ "prepack": "npm run build",
41
62
  "prepare": "husky install",
42
63
  "commit": "git-cz",
43
64
  "lint": "eslint .",
65
+ "lint:fix": "eslint --fix .",
44
66
  "format": "prettier --write .",
45
67
  "format:check": "prettier --check ."
46
68
  },
@@ -63,15 +85,17 @@
63
85
  "commitizen": "^4.3.0",
64
86
  "eslint": "^8.54.0",
65
87
  "eslint-config-prettier": "^9.0.0",
66
- "husky": "^8.0.3",
88
+ "eslint-plugin-require-extensions": "^0.1.3",
89
+ "husky": "^9.0.0",
67
90
  "inquirer": "^8.2.6",
68
91
  "jest": "^29.7.0",
69
92
  "jest-mock-extended": "^3.0.5",
70
93
  "kysely": "^0.27.0",
71
- "prettier": "3.1.1",
94
+ "prettier": "3.2.4",
72
95
  "prisma": "latest",
73
96
  "prisma-kysely": "^1.7.1",
74
97
  "ts-jest": "^29.1.1",
98
+ "tsconfig-to-dual-package": "^1.2.0",
75
99
  "typescript": "^5.0.0"
76
100
  }
77
101
  }
package/dist/index.d.ts DELETED
@@ -1,34 +0,0 @@
1
- import type { PrismaPromise } from "@prisma/client/runtime/library";
2
- import type { Compilable, Kysely, Simplify } from "kysely";
3
- /**
4
- * The configuration object for the Prisma Kysely extension
5
- */
6
- export type PrismaKyselyExtensionArgs<Database> = {
7
- /**
8
- * The Kysely instance to provide to the Prisma client
9
- */
10
- kysely: Kysely<Database>;
11
- };
12
- /**
13
- * Define a Prisma extension that adds Kysely query builder methods to the Prisma client
14
- * @param extensionArgs The extension configuration object
15
- */
16
- declare const _default: <Database>(extensionArgs: PrismaKyselyExtensionArgs<Database>) => (client: any) => import("@prisma/client/extension").PrismaClientExtends<import("@prisma/client/runtime/library").InternalArgs<{}, {}, {}, {
17
- /**
18
- * The Kysely instance used by the Prisma client
19
- */
20
- $kysely: Kysely<Database>;
21
- /**
22
- * Execute a Kysely query and return the result
23
- * @param query A Kysely select, insert, delete or update query builder
24
- * @returns The result of the query
25
- */
26
- $kyselyQuery<T>(query: Compilable<T>): Promise<Simplify<T>[]>;
27
- /**
28
- * Execute a Kysely query and return the number of rows affected
29
- * @param query A Kysely select, insert, delete or update query builder
30
- * @returns The number of rows affected
31
- */
32
- $kyselyExecute(query: Compilable): PrismaPromise<number>;
33
- }> & import("@prisma/client/runtime/library").DefaultArgs>;
34
- export default _default;
package/dist/index.js DELETED
@@ -1,40 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const extension_1 = require("@prisma/client/extension");
4
- /**
5
- * Define a Prisma extension that adds Kysely query builder methods to the Prisma client
6
- * @param extensionArgs The extension configuration object
7
- */
8
- exports.default = (extensionArgs) => extension_1.Prisma.defineExtension((client) => {
9
- return client.$extends({
10
- name: "prisma-extension-kysely",
11
- client: {
12
- /**
13
- * The Kysely instance used by the Prisma client
14
- */
15
- $kysely: extensionArgs.kysely,
16
- /**
17
- * Execute a Kysely query and return the result
18
- * @param query A Kysely select, insert, delete or update query builder
19
- * @returns The result of the query
20
- */
21
- $kyselyQuery(query) {
22
- const { sql, parameters } = query.compile();
23
- const ctx = extension_1.Prisma.getExtensionContext(this);
24
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
- return ctx.$queryRawUnsafe(sql, ...parameters);
26
- },
27
- /**
28
- * Execute a Kysely query and return the number of rows affected
29
- * @param query A Kysely select, insert, delete or update query builder
30
- * @returns The number of rows affected
31
- */
32
- $kyselyExecute(query) {
33
- const { sql, parameters } = query.compile();
34
- const ctx = extension_1.Prisma.getExtensionContext(this);
35
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
- return ctx.$executeRawUnsafe(sql, ...parameters);
37
- },
38
- },
39
- });
40
- });