prisma-sql 1.30.0 → 1.32.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prisma-sql",
3
- "version": "1.30.0",
3
+ "version": "1.32.0",
4
4
  "description": "Convert Prisma queries to optimized SQL with type safety. 2-7x faster than Prisma Client.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -65,7 +65,7 @@
65
65
  "author": "multipliedtwice <multipliedtwice@gmail.com>",
66
66
  "license": "MIT",
67
67
  "dependencies": {
68
- "@dee-wan/schema-parser": "1.3.0",
68
+ "@dee-wan/schema-parser": "1.4.0",
69
69
  "@prisma/generator-helper": "^7.2.0",
70
70
  "@prisma/internals": "^7.2.0"
71
71
  },
package/readme.md CHANGED
@@ -4,19 +4,15 @@
4
4
 
5
5
  Speed up Prisma reads **2-7x** by executing queries via postgres.js or better-sqlite3 instead of Prisma's query engine.
6
6
 
7
-
8
7
  **Same API. Same types. Just faster.**
9
8
 
10
9
  ```typescript
11
- import { PrismaClient, Prisma } from '@prisma/client'
12
- import { speedExtension, convertDMMFToModels } from 'prisma-sql'
10
+ import { PrismaClient } from '@prisma/client'
11
+ import { speedExtension } from './generated/sql'
13
12
  import postgres from 'postgres'
14
13
 
15
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
16
14
  const sql = postgres(process.env.DATABASE_URL)
17
- const prisma = new PrismaClient().$extends(
18
- speedExtension({ postgres: sql, models }),
19
- )
15
+ const prisma = new PrismaClient().$extends(speedExtension({ postgres: sql }))
20
16
 
21
17
  // Just use Prisma normally - queries are automatically faster
22
18
  const users = await prisma.user.findMany({
@@ -54,19 +50,54 @@ npm install prisma-sql better-sqlite3
54
50
 
55
51
  ## Quick Start
56
52
 
53
+ ### Step 1: Add Generator to Schema
54
+
55
+ Add the SQL generator to your `schema.prisma`:
56
+
57
+ ```prisma
58
+ generator client {
59
+ provider = "prisma-client-js"
60
+ }
61
+
62
+ generator sql {
63
+ provider = "prisma-sql-generator"
64
+ }
65
+
66
+ model User {
67
+ id Int @id @default(autoincrement())
68
+ email String @unique
69
+ status String
70
+ posts Post[]
71
+ }
72
+
73
+ model Post {
74
+ id Int @id @default(autoincrement())
75
+ title String
76
+ authorId Int
77
+ author User @relation(fields: [authorId], references: [id])
78
+ }
79
+ ```
80
+
81
+ ### Step 2: Generate
82
+
83
+ ```bash
84
+ npx prisma generate
85
+ ```
86
+
87
+ This creates `./generated/sql/index.ts` with pre-converted models and optimized queries.
88
+
89
+ ### Step 3: Use the Extension
90
+
57
91
  **PostgreSQL:**
58
92
 
59
93
  ```typescript
60
- import { PrismaClient, Prisma } from '@prisma/client'
61
- import { speedExtension, convertDMMFToModels } from 'prisma-sql'
94
+ import { PrismaClient } from '@prisma/client'
95
+ import { speedExtension } from './generated/sql'
62
96
  import postgres from 'postgres'
63
97
 
64
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
65
98
  const sql = postgres(process.env.DATABASE_URL)
66
99
 
67
- const prisma = new PrismaClient().$extends(
68
- speedExtension({ postgres: sql, models }),
69
- )
100
+ const prisma = new PrismaClient().$extends(speedExtension({ postgres: sql }))
70
101
 
71
102
  // Use Prisma exactly as before - it's just faster now
72
103
  const users = await prisma.user.findMany({
@@ -78,21 +109,18 @@ const users = await prisma.user.findMany({
78
109
  **SQLite:**
79
110
 
80
111
  ```typescript
81
- import { PrismaClient, Prisma } from '@prisma/client'
82
- import { speedExtension, convertDMMFToModels } from 'prisma-sql'
112
+ import { PrismaClient } from '@prisma/client'
113
+ import { speedExtension } from './generated/sql'
83
114
  import Database from 'better-sqlite3'
84
115
 
85
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
86
116
  const db = new Database('./data.db')
87
117
 
88
- const prisma = new PrismaClient().$extends(
89
- speedExtension({ sqlite: db, models }),
90
- )
118
+ const prisma = new PrismaClient().$extends(speedExtension({ sqlite: db }))
91
119
 
92
120
  const users = await prisma.user.findMany({ where: { status: 'ACTIVE' } })
93
121
  ```
94
122
 
95
- That's it! All your read queries are now 2-7x faster with zero code changes.
123
+ That's it! All your read queries are now 2-7x faster with zero runtime overhead.
96
124
 
97
125
  ## Performance
98
126
 
@@ -277,15 +305,11 @@ Benchmarks from 137 E2E tests comparing identical queries:
277
305
  See generated SQL for every query:
278
306
 
279
307
  ```typescript
280
- import { convertDMMFToModels } from 'prisma-sql'
281
- import { Prisma } from '@prisma/client'
282
-
283
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
308
+ import { speedExtension } from './generated/sql'
284
309
 
285
310
  const prisma = new PrismaClient().$extends(
286
311
  speedExtension({
287
312
  postgres: sql,
288
- models,
289
313
  debug: true, // Logs SQL for every query
290
314
  }),
291
315
  )
@@ -296,12 +320,11 @@ const prisma = new PrismaClient().$extends(
296
320
  Track query performance:
297
321
 
298
322
  ```typescript
299
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
323
+ import { speedExtension } from './generated/sql'
300
324
 
301
325
  const prisma = new PrismaClient().$extends(
302
326
  speedExtension({
303
327
  postgres: sql,
304
- models,
305
328
  onQuery: (info) => {
306
329
  console.log(`${info.model}.${info.method}: ${info.duration}ms`)
307
330
 
@@ -326,26 +349,10 @@ interface QueryInfo {
326
349
  sql: string // The executed SQL
327
350
  params: unknown[] // SQL parameters
328
351
  duration: number // Query duration in ms
329
- prebaked: boolean // true if using generated SQL (see Advanced Usage)
352
+ prebaked: boolean // true if using @optimize directive
330
353
  }
331
354
  ```
332
355
 
333
- ### Selective Models
334
-
335
- Only accelerate specific models:
336
-
337
- ```typescript
338
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
339
-
340
- const prisma = new PrismaClient().$extends(
341
- speedExtension({
342
- postgres: sql,
343
- models,
344
- allowedModels: ['User', 'Post'], // Only speed up these models
345
- }),
346
- )
347
- ```
348
-
349
356
  ## Supported Queries
350
357
 
351
358
  ### Filters
@@ -474,20 +481,11 @@ await prisma.task.groupBy({
474
481
 
475
482
  ## Advanced Usage
476
483
 
477
- ### Generator Mode - Prebaked SQL Queries
484
+ ### Prebaked SQL Queries (@optimize)
478
485
 
479
- For maximum performance, prebake your most common queries at build time. This reduces overhead from ~0.2ms (runtime) to ~0.03ms.
486
+ For maximum performance, prebake your most common queries at build time using `@optimize` directives. This reduces overhead from ~0.2ms (runtime) to ~0.03ms.
480
487
 
481
- **1. Add generator to your schema:**
482
-
483
- ```prisma
484
- // schema.prisma
485
- generator sql {
486
- provider = "prisma-sql-generator"
487
- }
488
- ```
489
-
490
- **2. Add optimize directives to your models:**
488
+ **Add optimize directives to your models:**
491
489
 
492
490
  ```prisma
493
491
  /// @optimize {
@@ -509,21 +507,18 @@ model User {
509
507
  }
510
508
  ```
511
509
 
512
- **3. Generate:**
510
+ **Generate:**
513
511
 
514
512
  ```bash
515
513
  npx prisma generate
516
514
  ```
517
515
 
518
- **4. Use the generated extension:**
516
+ **Use:**
519
517
 
520
518
  ```typescript
521
- import { PrismaClient } from '@prisma/client'
522
- import { createExtension } from '../path/to/generated/sql'
523
- import postgres from 'postgres'
519
+ import { speedExtension } from './generated/sql'
524
520
 
525
- const sql = postgres(process.env.DATABASE_URL)
526
- const prisma = new PrismaClient().$extends(createExtension({ postgres: sql }))
521
+ const prisma = new PrismaClient().$extends(speedExtension({ postgres: sql }))
527
522
 
528
523
  // ⚡ PREBAKED - Uses pre-generated SQL (~0.03ms overhead)
529
524
  const activeUsers = await prisma.user.findMany({
@@ -570,46 +565,28 @@ model User {
570
565
  generator sql {
571
566
  provider = "prisma-sql-generator"
572
567
 
573
- // Optional: Override auto-detected dialect
574
- // dialect = "postgres" // or "sqlite"
568
+ # Optional: Override auto-detected dialect
569
+ # dialect = "postgres" # or "sqlite"
575
570
 
576
- // Optional: Custom output directory
577
- // output = "./generated/sql"
571
+ # Optional: Custom output directory
572
+ # output = "./generated/sql"
578
573
 
579
- // Optional: Skip invalid directives instead of failing
580
- // skipInvalid = "true"
574
+ # Optional: Skip invalid directives instead of failing
575
+ # skipInvalid = "true"
581
576
  }
582
577
  ```
583
578
 
584
- ### Access Original Prisma
585
-
586
- ```typescript
587
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
588
- const prisma = new PrismaClient().$extends(
589
- speedExtension({ postgres: sql, models }),
590
- )
591
-
592
- // Fast (via raw SQL)
593
- const fast = await prisma.user.findMany()
594
-
595
- // Slow (via Prisma engine)
596
- const slow = await prisma.$original.user.findMany()
597
- ```
598
-
599
579
  ### Edge Runtime
600
580
 
601
581
  **Vercel Edge Functions:**
602
582
 
603
583
  ```typescript
604
- import { PrismaClient, Prisma } from '@prisma/client'
605
- import { speedExtension, convertDMMFToModels } from 'prisma-sql'
584
+ import { PrismaClient } from '@prisma/client'
585
+ import { speedExtension } from './generated/sql'
606
586
  import postgres from 'postgres'
607
587
 
608
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
609
588
  const sql = postgres(process.env.DATABASE_URL)
610
- const prisma = new PrismaClient().$extends(
611
- speedExtension({ postgres: sql, models }),
612
- )
589
+ const prisma = new PrismaClient().$extends(speedExtension({ postgres: sql }))
613
590
 
614
591
  export const config = { runtime: 'edge' }
615
592
 
@@ -624,11 +601,10 @@ export default async function handler(req: Request) {
624
601
  For Cloudflare Workers, use the standalone SQL generation API:
625
602
 
626
603
  ```typescript
627
- import { createToSQL, convertDMMFToModels } from 'prisma-sql'
628
- import { Prisma } from '@prisma/client'
604
+ import { createToSQL } from 'prisma-sql'
605
+ import { MODELS } from './generated/sql'
629
606
 
630
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
631
- const toSQL = createToSQL(models, 'sqlite')
607
+ const toSQL = createToSQL(MODELS, 'sqlite')
632
608
 
633
609
  export default {
634
610
  async fetch(request: Request, env: Env) {
@@ -658,7 +634,8 @@ Build Time:
658
634
 
659
635
  generated/sql/index.ts
660
636
 
661
- QUERIES = {
637
+ export const MODELS = [...] // Pre-converted models
638
+ const QUERIES = { // Pre-generated SQL
662
639
  User: {
663
640
  findMany: {
664
641
  '{"where":{"status":"ACTIVE"}}': {
@@ -669,6 +646,7 @@ Build Time:
669
646
  }
670
647
  }
671
648
  }
649
+ export function speedExtension() { ... }
672
650
 
673
651
  Runtime:
674
652
  prisma.user.findMany({ where: { status: 'ACTIVE' } })
@@ -764,15 +742,12 @@ const users = await prisma.user.findMany()
764
742
  **After:**
765
743
 
766
744
  ```typescript
767
- import { PrismaClient, Prisma } from '@prisma/client'
768
- import { speedExtension, convertDMMFToModels } from 'prisma-sql'
745
+ import { PrismaClient } from '@prisma/client'
746
+ import { speedExtension } from './generated/sql'
769
747
  import postgres from 'postgres'
770
748
 
771
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
772
749
  const sql = postgres(process.env.DATABASE_URL)
773
- const prisma = new PrismaClient().$extends(
774
- speedExtension({ postgres: sql, models }),
775
- )
750
+ const prisma = new PrismaClient().$extends(speedExtension({ postgres: sql }))
776
751
 
777
752
  const users = await prisma.user.findMany() // Same API, just faster
778
753
  ```
@@ -797,15 +772,12 @@ const users = await db
797
772
  **After:**
798
773
 
799
774
  ```typescript
800
- import { PrismaClient, Prisma } from '@prisma/client'
801
- import { speedExtension, convertDMMFToModels } from 'prisma-sql'
775
+ import { PrismaClient } from '@prisma/client'
776
+ import { speedExtension } from './generated/sql'
802
777
  import postgres from 'postgres'
803
778
 
804
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
805
779
  const sql = postgres(DATABASE_URL)
806
- const prisma = new PrismaClient().$extends(
807
- speedExtension({ postgres: sql, models }),
808
- )
780
+ const prisma = new PrismaClient().$extends(speedExtension({ postgres: sql }))
809
781
 
810
782
  const users = await prisma.user.findMany({
811
783
  where: { status: 'ACTIVE' },
@@ -843,36 +815,44 @@ Enable `debug: true` to see which queries are accelerated vs fallback.
843
815
 
844
816
  ## Troubleshooting
845
817
 
846
- ### "speedExtension requires models parameter"
818
+ ### "speedExtension requires postgres or sqlite client"
847
819
 
848
- Convert DMMF at module level:
820
+ Make sure you're importing from the generated file and passing the database client:
849
821
 
850
822
  ```typescript
851
- import { Prisma } from '@prisma/client'
852
- import { convertDMMFToModels } from 'prisma-sql'
853
-
854
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
823
+ import { speedExtension } from './generated/sql'
824
+ import postgres from 'postgres'
855
825
 
826
+ const sql = postgres(process.env.DATABASE_URL)
856
827
  const prisma = new PrismaClient().$extends(
857
- speedExtension({
858
- postgres: sql,
859
- models,
860
- }),
828
+ speedExtension({ postgres: sql }), // ✅ Pass postgres client
861
829
  )
862
830
  ```
863
831
 
832
+ ### "Generated code is for postgres, but you provided sqlite"
833
+
834
+ The generator auto-detects your database from `schema.prisma`. If you need to override:
835
+
836
+ ```prisma
837
+ generator sql {
838
+ provider = "prisma-sql-generator"
839
+ dialect = "postgres" # or "sqlite"
840
+ }
841
+ ```
842
+
864
843
  ### "Results don't match Prisma Client"
865
844
 
866
845
  Enable debug mode and compare SQL:
867
846
 
868
847
  ```typescript
869
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
848
+ import { speedExtension } from './generated/sql'
870
849
 
871
- speedExtension({
872
- postgres: sql,
873
- models,
874
- debug: true, // Shows generated SQL
875
- })
850
+ const prisma = new PrismaClient().$extends(
851
+ speedExtension({
852
+ postgres: sql,
853
+ debug: true, // Shows generated SQL
854
+ }),
855
+ )
876
856
  ```
877
857
 
878
858
  Compare with Prisma's query log:
@@ -904,57 +884,16 @@ Some queries won't see dramatic improvements:
904
884
  Use `onQuery` to measure actual speedup:
905
885
 
906
886
  ```typescript
907
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
908
-
909
- speedExtension({
910
- postgres: sql,
911
- models,
912
- onQuery: (info) => {
913
- console.log(`${info.method} took ${info.duration}ms`)
914
- },
915
- })
916
- ```
917
-
918
- ## Local Development
919
-
920
- ### Testing the Generator Locally
921
-
922
- **1. Build the package:**
923
-
924
- ```bash
925
- cd prisma-sql
926
- npm install
927
- npm run build
928
- ```
929
-
930
- **2. Link globally:**
931
-
932
- ```bash
933
- npm link
934
- ```
887
+ import { speedExtension } from './generated/sql'
935
888
 
936
- **3. Use in your project:**
937
-
938
- ```bash
939
- cd your-project
940
- npm link prisma-sql
941
- npx prisma generate
942
- ```
943
-
944
- **Alternative: Use file path directly in schema:**
945
-
946
- ```prisma
947
- generator sql {
948
- provider = "node ../path/to/prisma-sql/dist/generator.cjs"
949
- }
950
- ```
951
-
952
- **Unlink when done:**
953
-
954
- ```bash
955
- npm unlink prisma-sql # In your project
956
- cd prisma-sql
957
- npm unlink # In prisma-sql directory
889
+ const prisma = new PrismaClient().$extends(
890
+ speedExtension({
891
+ postgres: sql,
892
+ onQuery: (info) => {
893
+ console.log(`${info.method} took ${info.duration}ms`)
894
+ },
895
+ }),
896
+ )
958
897
  ```
959
898
 
960
899
  ## FAQ
@@ -963,7 +902,7 @@ npm unlink # In prisma-sql directory
963
902
  A: Yes. You need Prisma for schema management, migrations, types, and write operations. This extension only speeds up reads.
964
903
 
965
904
  **Q: Does it work with my existing schema?**
966
- A: Yes. No schema changes required. It works with your existing Prisma schema and generated client.
905
+ A: Yes. No schema changes required except adding the generator. It works with your existing Prisma schema and generated client.
967
906
 
968
907
  **Q: What about writes (create, update, delete)?**
969
908
  A: Writes still use Prisma Client. This extension only accelerates reads.
@@ -981,10 +920,10 @@ A: The extension runs after middlewares. For middleware to see actual SQL, use P
981
920
  A: Yes. Those methods are unaffected.
982
921
 
983
922
  **Q: What's the overhead of SQL generation?**
984
- A: Runtime mode: ~0.2ms per query. Generator mode: ~0.03ms for prebaked queries. Still 2-7x faster than Prisma overall.
923
+ A: Runtime mode: ~0.2ms per query. Generator mode with `@optimize`: ~0.03ms for prebaked queries. Still 2-7x faster than Prisma overall.
985
924
 
986
- **Q: Should I use generator mode or runtime mode?**
987
- A: Start with runtime mode (simpler). Add generator mode for your hottest queries later if needed.
925
+ **Q: Do I need @optimize directives?**
926
+ A: No! The generator works without them. `@optimize` directives are optional for squeezing out the last bit of performance on your hottest queries.
988
927
 
989
928
  ## Examples
990
929
 
@@ -1006,16 +945,13 @@ npm test
1006
945
  Benchmark your own queries:
1007
946
 
1008
947
  ```typescript
1009
- import { speedExtension, convertDMMFToModels } from 'prisma-sql'
1010
- import { Prisma } from '@prisma/client'
948
+ import { speedExtension } from './generated/sql'
1011
949
 
1012
950
  const queries: { name: string; duration: number }[] = []
1013
- const models = convertDMMFToModels(Prisma.dmmf.datamodel)
1014
951
 
1015
952
  const prisma = new PrismaClient().$extends(
1016
953
  speedExtension({
1017
954
  postgres: sql,
1018
- models,
1019
955
  onQuery: (info) => {
1020
956
  queries.push({
1021
957
  name: `${info.model}.${info.method}`,
@@ -1066,13 +1002,18 @@ Please ensure:
1066
1002
  └────────────────────┬────────────────────────────────┘
1067
1003
 
1068
1004
  ┌───────────▼──────────┐
1069
- Speed Extension
1070
- Intercepts query
1005
+ Generated Extension
1006
+ Uses internal MODELS
1007
+ └───────────┬──────────┘
1008
+
1009
+ ┌───────────▼──────────┐
1010
+ │ Check for prebaked │
1011
+ │ query in QUERIES │
1071
1012
  └───────────┬──────────┘
1072
1013
 
1073
1014
  ┌───────────▼──────────┐
1074
1015
  │ Generate SQL │
1075
- Parser + Builder
1016
+ (if not prebaked)
1076
1017
  └───────────┬──────────┘
1077
1018
 
1078
1019
  ┌───────────▼──────────┐