prisma-flare 1.1.8 → 1.2.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 ADDED
@@ -0,0 +1,162 @@
1
+ # Prisma Flare
2
+
3
+ A powerful TypeScript utilities package for Prisma ORM that provides a callback system and a query builder for chained operations.
4
+
5
+ ## Features
6
+
7
+ - **Plug & Play**: Works with any existing Prisma project
8
+ - **Flare Builder**: Elegant chainable query API for Prisma models
9
+ - **Auto-Generated Queries**: Automatically generates query classes based on your schema
10
+ - **Callback System**: Hooks for before/after operations (create, update, delete) and column-level changes
11
+ - **Type-Safe**: Full IntelliSense and compile-time type checking
12
+ - **Zero Overhead**: ~0.1-0.4% overhead per query (~0.001ms)
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install prisma-flare
18
+ ```
19
+
20
+ ### Compatibility
21
+
22
+ | Prisma Version | Generator Provider | Support |
23
+ |----------------|-------------------|---------|
24
+ | 5.x - 7.x | `prisma-client-js` | ✅ |
25
+ | 7.x+ | `prisma-client` | ✅ |
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Generate and Initialize
30
+
31
+ ```bash
32
+ # Generate prisma-flare client (run after prisma generate)
33
+ npx prisma-flare generate
34
+ ```
35
+
36
+ ```typescript
37
+ // prisma/db.ts
38
+ import './callbacks';
39
+ import { FlareClient } from 'prisma-flare/client';
40
+
41
+ export const db = new FlareClient();
42
+ ```
43
+
44
+ > **Note**: For advanced setups (custom Prisma output, monorepos), see [Configuration](docs/configuration.md).
45
+
46
+ ### 2. Generate Query Classes
47
+
48
+ Query classes are auto-generated based on your Prisma schema:
49
+
50
+ ```bash
51
+ npx prisma-flare generate
52
+ ```
53
+
54
+ ### 3. Use the Fluent API
55
+
56
+ ```typescript
57
+ import { DB } from 'prisma-flare/generated';
58
+
59
+ // Chainable queries with full type safety
60
+ const posts = await DB.posts
61
+ .where({ published: true })
62
+ .order({ createdAt: 'desc' })
63
+ .limit(10)
64
+ .include('author')
65
+ .findMany();
66
+
67
+ // Pagination
68
+ const { data, meta } = await DB.users.paginate(1, 15);
69
+
70
+ // Conditional queries
71
+ const users = await DB.users
72
+ .when(!!search, (q) => q.where({ name: { contains: search } }))
73
+ .findMany();
74
+ ```
75
+
76
+ ### 4. Define Callbacks
77
+
78
+ ```typescript
79
+ // prisma/callbacks/user.ts
80
+ import { beforeCreate, afterChange } from 'prisma-flare';
81
+
82
+ beforeCreate('user', async (args) => {
83
+ if (!args.data.email.includes('@')) {
84
+ throw new Error('Invalid email');
85
+ }
86
+ });
87
+
88
+ afterChange('post', 'published', async (oldValue, newValue, record) => {
89
+ if (!oldValue && newValue) {
90
+ await notifySubscribers(record);
91
+ }
92
+ });
93
+ ```
94
+
95
+ ## Documentation
96
+
97
+ - **[API Reference](docs/api-reference.md)** - Complete FlareBuilder API documentation
98
+ - **[Hooks & Callbacks](docs/hooks.md)** - Lifecycle hooks and column-level change tracking
99
+ - **[Configuration](docs/configuration.md)** - Config options, custom paths, and CLI commands
100
+ - **[How It Works](docs/how-it-works.md)** - Architecture and type generation internals
101
+ - **[Development](docs/development.md)** - Testing, contributing, and project structure
102
+
103
+ ## Custom Prisma Output
104
+
105
+ prisma-flare fully supports custom Prisma output paths. Just run `npx prisma-flare generate` and import from `prisma-flare/client`:
106
+
107
+ ```prisma
108
+ generator client {
109
+ provider = "prisma-client-js"
110
+ output = "./generated/client"
111
+ }
112
+ ```
113
+
114
+ ```typescript
115
+ // The recommended import - works with any Prisma configuration
116
+ import { FlareClient, FlareBuilder } from 'prisma-flare/client';
117
+
118
+ export const db = new FlareClient();
119
+ ```
120
+
121
+ For the new `prisma-client` provider (Prisma 7+), you can also import from the generated `flare.ts`:
122
+
123
+ ```typescript
124
+ import { FlareClient } from './generated/flare';
125
+ import { PrismaPg } from '@prisma/adapter-pg';
126
+
127
+ const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
128
+ export const db = new FlareClient({ adapter });
129
+ ```
130
+
131
+ See [Configuration](docs/configuration.md#new-provider-prisma-client---prisma-7) for full setup.
132
+
133
+ ## Transactions
134
+
135
+ ```typescript
136
+ await DB.instance.transaction(async (tx) => {
137
+ const user = await tx.from('user').create({
138
+ email: 'new@example.com',
139
+ name: 'New User',
140
+ });
141
+
142
+ await tx.from('post').create({
143
+ title: 'First Post',
144
+ authorId: user.id,
145
+ });
146
+ });
147
+ ```
148
+
149
+ ## Performance
150
+
151
+ | Query Type | Overhead |
152
+ |------------|----------|
153
+ | findFirst by ID | +0.25% |
154
+ | findFirst + include | +0.23% |
155
+ | COUNT with WHERE | +0.34% |
156
+ | Complex query | +0.38% |
157
+
158
+ **Median overhead: 0.1-0.4%** (~0.001ms per query)
159
+
160
+ ## License
161
+
162
+ ISC
@@ -23,6 +23,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  mod
24
24
  ));
25
25
 
26
+ // src/cli/db-create.ts
27
+ var import_dotenv = require("dotenv");
28
+
26
29
  // src/core/adapters/postgres.ts
27
30
  var PostgresAdapter = {
28
31
  name: "postgres",
@@ -30,26 +33,26 @@ var PostgresAdapter = {
30
33
  return url.startsWith("postgresql://") || url.startsWith("postgres://");
31
34
  },
32
35
  async create(url) {
33
- const config = parseDatabaseUrl(url);
36
+ const config2 = parseDatabaseUrl(url);
34
37
  const { Client } = await import("pg");
35
38
  const client = new Client({
36
- user: config.user,
37
- password: config.password,
38
- host: config.host,
39
- port: config.port,
39
+ user: config2.user,
40
+ password: config2.password,
41
+ host: config2.host,
42
+ port: config2.port,
40
43
  database: "postgres"
41
44
  });
42
45
  try {
43
46
  await client.connect();
44
47
  const checkRes = await client.query(
45
48
  `SELECT 1 FROM pg_database WHERE datname = $1`,
46
- [config.database]
49
+ [config2.database]
47
50
  );
48
51
  if (checkRes.rowCount === 0) {
49
- await client.query(`CREATE DATABASE "${config.database}"`);
50
- console.log(`\u2705 Database "${config.database}" created successfully.`);
52
+ await client.query(`CREATE DATABASE "${config2.database}"`);
53
+ console.log(`\u2705 Database "${config2.database}" created successfully.`);
51
54
  } else {
52
- console.log(`\u26A0\uFE0F Database "${config.database}" already exists.`);
55
+ console.log(`\u26A0\uFE0F Database "${config2.database}" already exists.`);
53
56
  }
54
57
  } catch (error) {
55
58
  console.error("\u274C Error creating database:", error);
@@ -59,13 +62,13 @@ var PostgresAdapter = {
59
62
  }
60
63
  },
61
64
  async drop(url) {
62
- const config = parseDatabaseUrl(url);
65
+ const config2 = parseDatabaseUrl(url);
63
66
  const { Client } = await import("pg");
64
67
  const client = new Client({
65
- user: config.user,
66
- password: config.password,
67
- host: config.host,
68
- port: config.port,
68
+ user: config2.user,
69
+ password: config2.password,
70
+ host: config2.host,
71
+ port: config2.port,
69
72
  database: "postgres"
70
73
  });
71
74
  try {
@@ -75,10 +78,10 @@ var PostgresAdapter = {
75
78
  FROM pg_stat_activity
76
79
  WHERE pg_stat_activity.datname = $1
77
80
  AND pid <> pg_backend_pid()`,
78
- [config.database]
81
+ [config2.database]
79
82
  );
80
- await client.query(`DROP DATABASE IF EXISTS "${config.database}"`);
81
- console.log(`\u2705 Database "${config.database}" dropped successfully.`);
83
+ await client.query(`DROP DATABASE IF EXISTS "${config2.database}"`);
84
+ console.log(`\u2705 Database "${config2.database}" dropped successfully.`);
82
85
  } catch (error) {
83
86
  console.error("\u274C Error dropping database:", error);
84
87
  throw error;
@@ -181,10 +184,12 @@ registry.register(PostgresAdapter);
181
184
  registry.register(SqliteAdapter);
182
185
 
183
186
  // src/cli/db-create.ts
187
+ (0, import_dotenv.config)();
184
188
  async function createDatabase() {
185
189
  const databaseUrl = process.env.DATABASE_URL;
186
190
  if (!databaseUrl) {
187
191
  console.error("\u274C DATABASE_URL environment variable is not set");
192
+ console.error(" Make sure DATABASE_URL is set in your .env file or environment");
188
193
  process.exit(1);
189
194
  }
190
195
  try {
@@ -1 +1,2 @@
1
1
  #!/usr/bin/env node
2
+ import 'prisma-flare-generated';
@@ -1 +1,2 @@
1
1
  #!/usr/bin/env node
2
+ import 'prisma-flare-generated';
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/cli/db-create.ts
4
+ import { config } from "dotenv";
5
+
3
6
  // src/core/adapters/postgres.ts
4
7
  var PostgresAdapter = {
5
8
  name: "postgres",
@@ -7,26 +10,26 @@ var PostgresAdapter = {
7
10
  return url.startsWith("postgresql://") || url.startsWith("postgres://");
8
11
  },
9
12
  async create(url) {
10
- const config = parseDatabaseUrl(url);
13
+ const config2 = parseDatabaseUrl(url);
11
14
  const { Client } = await import("pg");
12
15
  const client = new Client({
13
- user: config.user,
14
- password: config.password,
15
- host: config.host,
16
- port: config.port,
16
+ user: config2.user,
17
+ password: config2.password,
18
+ host: config2.host,
19
+ port: config2.port,
17
20
  database: "postgres"
18
21
  });
19
22
  try {
20
23
  await client.connect();
21
24
  const checkRes = await client.query(
22
25
  `SELECT 1 FROM pg_database WHERE datname = $1`,
23
- [config.database]
26
+ [config2.database]
24
27
  );
25
28
  if (checkRes.rowCount === 0) {
26
- await client.query(`CREATE DATABASE "${config.database}"`);
27
- console.log(`\u2705 Database "${config.database}" created successfully.`);
29
+ await client.query(`CREATE DATABASE "${config2.database}"`);
30
+ console.log(`\u2705 Database "${config2.database}" created successfully.`);
28
31
  } else {
29
- console.log(`\u26A0\uFE0F Database "${config.database}" already exists.`);
32
+ console.log(`\u26A0\uFE0F Database "${config2.database}" already exists.`);
30
33
  }
31
34
  } catch (error) {
32
35
  console.error("\u274C Error creating database:", error);
@@ -36,13 +39,13 @@ var PostgresAdapter = {
36
39
  }
37
40
  },
38
41
  async drop(url) {
39
- const config = parseDatabaseUrl(url);
42
+ const config2 = parseDatabaseUrl(url);
40
43
  const { Client } = await import("pg");
41
44
  const client = new Client({
42
- user: config.user,
43
- password: config.password,
44
- host: config.host,
45
- port: config.port,
45
+ user: config2.user,
46
+ password: config2.password,
47
+ host: config2.host,
48
+ port: config2.port,
46
49
  database: "postgres"
47
50
  });
48
51
  try {
@@ -52,10 +55,10 @@ var PostgresAdapter = {
52
55
  FROM pg_stat_activity
53
56
  WHERE pg_stat_activity.datname = $1
54
57
  AND pid <> pg_backend_pid()`,
55
- [config.database]
58
+ [config2.database]
56
59
  );
57
- await client.query(`DROP DATABASE IF EXISTS "${config.database}"`);
58
- console.log(`\u2705 Database "${config.database}" dropped successfully.`);
60
+ await client.query(`DROP DATABASE IF EXISTS "${config2.database}"`);
61
+ console.log(`\u2705 Database "${config2.database}" dropped successfully.`);
59
62
  } catch (error) {
60
63
  console.error("\u274C Error dropping database:", error);
61
64
  throw error;
@@ -158,10 +161,12 @@ registry.register(PostgresAdapter);
158
161
  registry.register(SqliteAdapter);
159
162
 
160
163
  // src/cli/db-create.ts
164
+ config();
161
165
  async function createDatabase() {
162
166
  const databaseUrl = process.env.DATABASE_URL;
163
167
  if (!databaseUrl) {
164
168
  console.error("\u274C DATABASE_URL environment variable is not set");
169
+ console.error(" Make sure DATABASE_URL is set in your .env file or environment");
165
170
  process.exit(1);
166
171
  }
167
172
  try {
@@ -24,6 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/cli/db-drop.ts
27
+ var import_dotenv = require("dotenv");
27
28
  var readline = __toESM(require("readline"), 1);
28
29
 
29
30
  // src/core/adapters/postgres.ts
@@ -33,26 +34,26 @@ var PostgresAdapter = {
33
34
  return url.startsWith("postgresql://") || url.startsWith("postgres://");
34
35
  },
35
36
  async create(url) {
36
- const config = parseDatabaseUrl(url);
37
+ const config2 = parseDatabaseUrl(url);
37
38
  const { Client } = await import("pg");
38
39
  const client = new Client({
39
- user: config.user,
40
- password: config.password,
41
- host: config.host,
42
- port: config.port,
40
+ user: config2.user,
41
+ password: config2.password,
42
+ host: config2.host,
43
+ port: config2.port,
43
44
  database: "postgres"
44
45
  });
45
46
  try {
46
47
  await client.connect();
47
48
  const checkRes = await client.query(
48
49
  `SELECT 1 FROM pg_database WHERE datname = $1`,
49
- [config.database]
50
+ [config2.database]
50
51
  );
51
52
  if (checkRes.rowCount === 0) {
52
- await client.query(`CREATE DATABASE "${config.database}"`);
53
- console.log(`\u2705 Database "${config.database}" created successfully.`);
53
+ await client.query(`CREATE DATABASE "${config2.database}"`);
54
+ console.log(`\u2705 Database "${config2.database}" created successfully.`);
54
55
  } else {
55
- console.log(`\u26A0\uFE0F Database "${config.database}" already exists.`);
56
+ console.log(`\u26A0\uFE0F Database "${config2.database}" already exists.`);
56
57
  }
57
58
  } catch (error) {
58
59
  console.error("\u274C Error creating database:", error);
@@ -62,13 +63,13 @@ var PostgresAdapter = {
62
63
  }
63
64
  },
64
65
  async drop(url) {
65
- const config = parseDatabaseUrl(url);
66
+ const config2 = parseDatabaseUrl(url);
66
67
  const { Client } = await import("pg");
67
68
  const client = new Client({
68
- user: config.user,
69
- password: config.password,
70
- host: config.host,
71
- port: config.port,
69
+ user: config2.user,
70
+ password: config2.password,
71
+ host: config2.host,
72
+ port: config2.port,
72
73
  database: "postgres"
73
74
  });
74
75
  try {
@@ -78,10 +79,10 @@ var PostgresAdapter = {
78
79
  FROM pg_stat_activity
79
80
  WHERE pg_stat_activity.datname = $1
80
81
  AND pid <> pg_backend_pid()`,
81
- [config.database]
82
+ [config2.database]
82
83
  );
83
- await client.query(`DROP DATABASE IF EXISTS "${config.database}"`);
84
- console.log(`\u2705 Database "${config.database}" dropped successfully.`);
84
+ await client.query(`DROP DATABASE IF EXISTS "${config2.database}"`);
85
+ console.log(`\u2705 Database "${config2.database}" dropped successfully.`);
85
86
  } catch (error) {
86
87
  console.error("\u274C Error dropping database:", error);
87
88
  throw error;
@@ -184,6 +185,7 @@ registry.register(PostgresAdapter);
184
185
  registry.register(SqliteAdapter);
185
186
 
186
187
  // src/cli/db-drop.ts
188
+ (0, import_dotenv.config)();
187
189
  function confirm(question) {
188
190
  const rl = readline.createInterface({
189
191
  input: process.stdin,
@@ -201,6 +203,7 @@ async function dropDatabase() {
201
203
  const skipConfirmation = process.argv.includes("--force") || process.argv.includes("-f");
202
204
  if (!databaseUrl) {
203
205
  console.error("\u274C DATABASE_URL environment variable is not set");
206
+ console.error(" Make sure DATABASE_URL is set in your .env file or environment");
204
207
  process.exit(1);
205
208
  }
206
209
  try {
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/db-drop.ts
4
+ import { config } from "dotenv";
4
5
  import * as readline from "readline";
5
6
 
6
7
  // src/core/adapters/postgres.ts
@@ -10,26 +11,26 @@ var PostgresAdapter = {
10
11
  return url.startsWith("postgresql://") || url.startsWith("postgres://");
11
12
  },
12
13
  async create(url) {
13
- const config = parseDatabaseUrl(url);
14
+ const config2 = parseDatabaseUrl(url);
14
15
  const { Client } = await import("pg");
15
16
  const client = new Client({
16
- user: config.user,
17
- password: config.password,
18
- host: config.host,
19
- port: config.port,
17
+ user: config2.user,
18
+ password: config2.password,
19
+ host: config2.host,
20
+ port: config2.port,
20
21
  database: "postgres"
21
22
  });
22
23
  try {
23
24
  await client.connect();
24
25
  const checkRes = await client.query(
25
26
  `SELECT 1 FROM pg_database WHERE datname = $1`,
26
- [config.database]
27
+ [config2.database]
27
28
  );
28
29
  if (checkRes.rowCount === 0) {
29
- await client.query(`CREATE DATABASE "${config.database}"`);
30
- console.log(`\u2705 Database "${config.database}" created successfully.`);
30
+ await client.query(`CREATE DATABASE "${config2.database}"`);
31
+ console.log(`\u2705 Database "${config2.database}" created successfully.`);
31
32
  } else {
32
- console.log(`\u26A0\uFE0F Database "${config.database}" already exists.`);
33
+ console.log(`\u26A0\uFE0F Database "${config2.database}" already exists.`);
33
34
  }
34
35
  } catch (error) {
35
36
  console.error("\u274C Error creating database:", error);
@@ -39,13 +40,13 @@ var PostgresAdapter = {
39
40
  }
40
41
  },
41
42
  async drop(url) {
42
- const config = parseDatabaseUrl(url);
43
+ const config2 = parseDatabaseUrl(url);
43
44
  const { Client } = await import("pg");
44
45
  const client = new Client({
45
- user: config.user,
46
- password: config.password,
47
- host: config.host,
48
- port: config.port,
46
+ user: config2.user,
47
+ password: config2.password,
48
+ host: config2.host,
49
+ port: config2.port,
49
50
  database: "postgres"
50
51
  });
51
52
  try {
@@ -55,10 +56,10 @@ var PostgresAdapter = {
55
56
  FROM pg_stat_activity
56
57
  WHERE pg_stat_activity.datname = $1
57
58
  AND pid <> pg_backend_pid()`,
58
- [config.database]
59
+ [config2.database]
59
60
  );
60
- await client.query(`DROP DATABASE IF EXISTS "${config.database}"`);
61
- console.log(`\u2705 Database "${config.database}" dropped successfully.`);
61
+ await client.query(`DROP DATABASE IF EXISTS "${config2.database}"`);
62
+ console.log(`\u2705 Database "${config2.database}" dropped successfully.`);
62
63
  } catch (error) {
63
64
  console.error("\u274C Error dropping database:", error);
64
65
  throw error;
@@ -161,6 +162,7 @@ registry.register(PostgresAdapter);
161
162
  registry.register(SqliteAdapter);
162
163
 
163
164
  // src/cli/db-drop.ts
165
+ config();
164
166
  function confirm(question) {
165
167
  const rl = readline.createInterface({
166
168
  input: process.stdin,
@@ -178,6 +180,7 @@ async function dropDatabase() {
178
180
  const skipConfirmation = process.argv.includes("--force") || process.argv.includes("-f");
179
181
  if (!databaseUrl) {
180
182
  console.error("\u274C DATABASE_URL environment variable is not set");
183
+ console.error(" Make sure DATABASE_URL is set in your .env file or environment");
181
184
  process.exit(1);
182
185
  }
183
186
  try {