prisma-sharding 0.0.3 → 0.0.4

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.
Files changed (3) hide show
  1. package/README.md +46 -0
  2. package/dist/cli/test.js +321 -42
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -213,6 +213,52 @@ Test connections to all shards.
213
213
  yarn test:shards
214
214
  ```
215
215
 
216
+ ```
217
+ ================================
218
+ 📋 User Distribution Test
219
+ ================================
220
+ Creating 24 test users across 3 shards...
221
+
222
+ User 1/24: "testuser_0" → shard_3
223
+ User 2/24: "testuser_1" → shard_1
224
+ User 3/24: "testuser_2" → shard_2
225
+ User 4/24: "testuser_3" → shard_3
226
+ User 5/24: "testuser_4" → shard_1
227
+ User 6/24: "testuser_5" → shard_2
228
+ User 7/24: "testuser_6" → shard_3
229
+ User 8/24: "testuser_7" → shard_1
230
+ User 9/24: "testuser_8" → shard_2
231
+ User 10/24: "testuser_9" → shard_3
232
+ User 11/24: "testuser_10" → shard_2
233
+ User 12/24: "testuser_11" → shard_1
234
+ User 13/24: "testuser_12" → shard_3
235
+ User 14/24: "testuser_13" → shard_2
236
+ User 15/24: "testuser_14" → shard_1
237
+ User 16/24: "testuser_15" → shard_3
238
+ User 17/24: "testuser_16" → shard_2
239
+ User 18/24: "testuser_17" → shard_1
240
+ User 19/24: "testuser_18" → shard_3
241
+ User 20/24: "testuser_19" → shard_2
242
+ User 21/24: "testuser_20" → shard_1
243
+ User 22/24: "testuser_21" → shard_3
244
+ User 23/24: "testuser_22" → shard_2
245
+ User 24/24: "testuser_23" → shard_1
246
+ ✅ Created 24/24 test users
247
+ ```
248
+
249
+ ```
250
+ ================================
251
+ 📋 Read Verification
252
+ ================================
253
+ ✓ User "test_user_1770289330292_0" found on shard_3
254
+ ✓ User "test_user_1770289330292_1" found on shard_1
255
+ ✓ User "test_user_1770289330292_2" found on shard_2
256
+ ✓ User "test_user_1770289330292_3" found on shard_3
257
+ ✓ User "test_user_1770289330292_4" found on shard_1
258
+ Verified 5/5 users on correct shards
259
+ ✅ Verify users exist on correct shards (136ms)
260
+ ```
261
+
216
262
  ## Configuration
217
263
 
218
264
  | Option | Type | Default | Description |
package/dist/cli/test.js CHANGED
@@ -1,19 +1,43 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
3
25
 
4
26
  // src/cli/test.ts
5
27
  var import_config = require("dotenv/config");
6
- var import_child_process = require("child_process");
7
28
  var results = [];
29
+ var testUsers = [];
30
+ var TEST_USER_COUNT = 24;
8
31
  var log = {
9
32
  info: (msg) => console.log(`\u2139\uFE0F ${msg}`),
10
33
  success: (msg) => console.log(`\u2705 ${msg}`),
11
34
  error: (msg) => console.log(`\u274C ${msg}`),
12
35
  warn: (msg) => console.log(`\u26A0\uFE0F ${msg}`),
13
36
  section: (msg) => console.log(`
14
- ${"=".repeat(50)}
37
+ ${"=".repeat(60)}
15
38
  \u{1F4CB} ${msg}
16
- ${"=".repeat(50)}`)
39
+ ${"=".repeat(60)}`),
40
+ detail: (msg) => console.log(` ${msg}`)
17
41
  };
18
42
  var getShardConfigs = () => {
19
43
  const shards = [];
@@ -43,78 +67,333 @@ var runTest = async (name, testFn) => {
43
67
  log.error(`${name}: ${message}`);
44
68
  }
45
69
  };
46
- var testConnection = (url) => {
70
+ var parsePostgresUrl = (url) => {
71
+ try {
72
+ const match = url.match(/postgresql:\/\/([^:]+):([^@]+)@([^:]+):(\d+)\/([^?]+)/);
73
+ if (match) {
74
+ return {
75
+ user: match[1],
76
+ password: match[2],
77
+ host: match[3],
78
+ port: parseInt(match[4], 10),
79
+ database: match[5]
80
+ };
81
+ }
82
+ return null;
83
+ } catch {
84
+ return null;
85
+ }
86
+ };
87
+ var testTcpConnection = (host, port) => {
47
88
  return new Promise((resolve) => {
48
- const prisma = (0, import_child_process.spawn)("npx", ["prisma", "db", "execute", "--url", url, "--stdin"], {
49
- shell: true,
50
- stdio: ["pipe", "pipe", "pipe"]
51
- });
52
- prisma.stdin.write("SELECT 1");
53
- prisma.stdin.end();
54
- prisma.on("close", (code) => {
55
- resolve(code === 0);
56
- });
57
- prisma.on("error", () => {
58
- resolve(false);
89
+ import("net").then(({ default: net }) => {
90
+ const socket = new net.Socket();
91
+ socket.setTimeout(5e3);
92
+ socket.on("connect", () => {
93
+ socket.destroy();
94
+ resolve(true);
95
+ });
96
+ socket.on("timeout", () => {
97
+ socket.destroy();
98
+ resolve(false);
99
+ });
100
+ socket.on("error", () => {
101
+ socket.destroy();
102
+ resolve(false);
103
+ });
104
+ socket.connect(port, host);
105
+ }).catch(() => resolve(false));
106
+ });
107
+ };
108
+ var getPgClient = async () => {
109
+ try {
110
+ const pg = await import("pg");
111
+ return pg.default?.Client || pg.Client;
112
+ } catch {
113
+ return null;
114
+ }
115
+ };
116
+ var executeSql = async (url, sql) => {
117
+ const Client = await getPgClient();
118
+ if (!Client) {
119
+ return executeSqlWithPsql(url, sql);
120
+ }
121
+ const client = new Client({ connectionString: url });
122
+ try {
123
+ await client.connect();
124
+ const result = await client.query(sql);
125
+ await client.end();
126
+ return { success: true, rows: result.rows };
127
+ } catch (error) {
128
+ try {
129
+ await client.end();
130
+ } catch {
131
+ }
132
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
133
+ }
134
+ };
135
+ var executeSqlWithPsql = (url, sql) => {
136
+ return new Promise((resolve) => {
137
+ import("child_process").then(({ spawn }) => {
138
+ const psql = spawn("psql", [url, "-c", sql], {
139
+ shell: true,
140
+ stdio: ["pipe", "pipe", "pipe"]
141
+ });
142
+ let stdout = "";
143
+ let stderr = "";
144
+ psql.stdout?.on("data", (data) => {
145
+ stdout += data.toString();
146
+ });
147
+ psql.stderr?.on("data", (data) => {
148
+ stderr += data.toString();
149
+ });
150
+ const timeout = setTimeout(() => {
151
+ psql.kill();
152
+ resolve({ success: false, error: "Command timeout" });
153
+ }, 15e3);
154
+ psql.on("close", (code) => {
155
+ clearTimeout(timeout);
156
+ resolve({ success: code === 0, error: code !== 0 ? stderr : void 0 });
157
+ });
158
+ psql.on("error", (err) => {
159
+ clearTimeout(timeout);
160
+ resolve({ success: false, error: err.message });
161
+ });
59
162
  });
60
163
  });
61
164
  };
165
+ var hashString = (str) => {
166
+ let hash = 0;
167
+ for (let i = 0; i < str.length; i++) {
168
+ const char = str.charCodeAt(i);
169
+ hash = (hash << 5) - hash + char;
170
+ hash = hash & hash;
171
+ }
172
+ return Math.abs(hash);
173
+ };
174
+ var getShardIndex = (key, shardCount) => {
175
+ return hashString(key) % shardCount;
176
+ };
62
177
  var runTests = async () => {
63
178
  const shards = getShardConfigs();
64
- console.log("\n\u{1F9EA} prisma-sharding: Shard Connection Test Suite\n");
65
- console.log(`\u{1F4CA} Configuration:`);
66
- console.log(` - Shard Count: ${shards.length}`);
67
- console.log(` - Routing Strategy: ${process.env.SHARD_ROUTING_STRATEGY || "modulo"}`);
179
+ const timestamp = Date.now();
180
+ const testTableName = `_prisma_sharding_test_${timestamp}`;
181
+ console.log("\n" + "\u2550".repeat(60));
182
+ console.log("\u{1F9EA} PRISMA SHARDING - Comprehensive Test Suite");
183
+ console.log("\u2550".repeat(60));
184
+ console.log(`
185
+ \u{1F4CA} Configuration:`);
186
+ console.log(` \u2022 Shard Count: ${shards.length}`);
187
+ console.log(` \u2022 Routing Strategy: ${process.env.SHARD_ROUTING_STRATEGY || "modulo"}`);
188
+ console.log(` \u2022 Test Users: ${TEST_USER_COUNT}`);
189
+ console.log(` \u2022 Test Table: ${testTableName}`);
68
190
  if (shards.length === 0) {
69
191
  console.error(
70
192
  "\n\u274C No shards configured. Set SHARD_COUNT and SHARD_N_URL environment variables."
71
193
  );
72
194
  process.exit(1);
73
195
  }
74
- log.section("Test 1: Shard Connection Tests");
75
- for (const shard of shards) {
76
- await runTest(`Connect to ${shard.id}`, async () => {
77
- const success = await testConnection(shard.url);
78
- if (!success) {
79
- throw new Error(`Failed to connect to ${shard.id}`);
80
- }
81
- });
196
+ const pgAvailable = await getPgClient();
197
+ if (pgAvailable) {
198
+ console.log(` \u2022 Database Client: pg (native)`);
199
+ } else {
200
+ console.log(` \u2022 Database Client: psql (fallback)`);
82
201
  }
83
- log.section("Test 2: Configuration Verification");
202
+ log.section("Test 1: Configuration Validation");
84
203
  await runTest("Verify environment variables", async () => {
85
204
  const shardCount = parseInt(process.env.SHARD_COUNT || "0", 10);
86
205
  if (shardCount === 0 && !process.env.DATABASE_URL) {
87
206
  throw new Error("SHARD_COUNT or DATABASE_URL must be set");
88
207
  }
89
- log.info(`SHARD_COUNT: ${shardCount}`);
90
- log.info(`Routing Strategy: ${process.env.SHARD_ROUTING_STRATEGY || "modulo"}`);
208
+ log.detail(`SHARD_COUNT = ${shardCount}`);
209
+ log.detail(`SHARD_ROUTING_STRATEGY = ${process.env.SHARD_ROUTING_STRATEGY || "modulo"}`);
91
210
  });
92
- await runTest("Verify all shard URLs are present", async () => {
93
- const shardCount = parseInt(process.env.SHARD_COUNT || "0", 10);
94
- for (let i = 1; i <= shardCount; i++) {
95
- const url = process.env[`SHARD_${i}_URL`];
96
- if (!url) {
97
- throw new Error(`SHARD_${i}_URL is missing`);
211
+ await runTest("Verify shard URL formats", async () => {
212
+ for (const shard of shards) {
213
+ const urlInfo = parsePostgresUrl(shard.url);
214
+ if (!urlInfo) {
215
+ throw new Error(`Invalid URL format for ${shard.id}`);
216
+ }
217
+ log.detail(`${shard.id} \u2192 ${urlInfo.host}:${urlInfo.port}/${urlInfo.database}`);
218
+ }
219
+ });
220
+ log.section("Test 2: Network Connectivity");
221
+ for (const shard of shards) {
222
+ await runTest(`TCP connection to ${shard.id}`, async () => {
223
+ const urlInfo = parsePostgresUrl(shard.url);
224
+ if (!urlInfo) throw new Error("Invalid URL");
225
+ const connected = await testTcpConnection(urlInfo.host, urlInfo.port);
226
+ if (!connected) {
227
+ throw new Error(`Cannot reach ${urlInfo.host}:${urlInfo.port}`);
228
+ }
229
+ log.detail(`${urlInfo.host}:${urlInfo.port} is reachable`);
230
+ });
231
+ }
232
+ log.section("Test 3: Database Connection");
233
+ for (const shard of shards) {
234
+ await runTest(`SQL execution on ${shard.id}`, async () => {
235
+ const result = await executeSql(shard.url, "SELECT 1 as test;");
236
+ if (!result.success) {
237
+ throw new Error(result.error || "SQL execution failed");
238
+ }
239
+ log.detail(`${shard.id} accepts SQL commands`);
240
+ });
241
+ }
242
+ log.section("Test 4: Create Test Table");
243
+ const createTableSql = `
244
+ CREATE TABLE IF NOT EXISTS "${testTableName}" (
245
+ id VARCHAR(50) PRIMARY KEY,
246
+ email VARCHAR(255) NOT NULL,
247
+ username VARCHAR(100) NOT NULL,
248
+ created_at TIMESTAMP DEFAULT NOW()
249
+ );
250
+ `;
251
+ for (const shard of shards) {
252
+ await runTest(`Create test table on ${shard.id}`, async () => {
253
+ const result = await executeSql(shard.url, createTableSql);
254
+ if (!result.success) {
255
+ throw new Error(result.error || "Failed to create table");
256
+ }
257
+ log.detail(`Table "${testTableName}" created on ${shard.id}`);
258
+ });
259
+ }
260
+ log.section("Test 5: User Distribution Test");
261
+ console.log(`
262
+ Creating ${TEST_USER_COUNT} test users across ${shards.length} shards...
263
+ `);
264
+ const distribution = /* @__PURE__ */ new Map();
265
+ shards.forEach((s) => distribution.set(s.id, 0));
266
+ for (let i = 0; i < TEST_USER_COUNT; i++) {
267
+ const userId = `test_user_${timestamp}_${i}`;
268
+ const email = `test_${timestamp}_${i}@example.com`;
269
+ const username = `testuser_${i}`;
270
+ const shardIndex = getShardIndex(userId, shards.length);
271
+ const targetShard = shards[shardIndex];
272
+ const insertSql = `
273
+ INSERT INTO "${testTableName}" (id, email, username)
274
+ VALUES ('${userId}', '${email}', '${username}');
275
+ `;
276
+ const result = await executeSql(targetShard.url, insertSql);
277
+ if (result.success) {
278
+ testUsers.push({ id: userId, email, shardId: targetShard.id });
279
+ distribution.set(targetShard.id, (distribution.get(targetShard.id) || 0) + 1);
280
+ log.detail(`User ${i + 1}/${TEST_USER_COUNT}: "${username}" \u2192 ${targetShard.id}`);
281
+ } else {
282
+ log.warn(`Failed to create user ${i + 1}: ${result.error}`);
283
+ }
284
+ }
285
+ log.success(`Created ${testUsers.length}/${TEST_USER_COUNT} test users`);
286
+ log.section("Test 6: Distribution Analysis");
287
+ await runTest("Analyze shard distribution", async () => {
288
+ console.log("\n \u{1F4CA} User Distribution Across Shards:\n");
289
+ console.log(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
290
+ console.log(" \u2502 Shard \u2502 Users \u2502 Percentage \u2502 Visual \u2502");
291
+ console.log(" \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
292
+ let minCount = Infinity;
293
+ let maxCount = 0;
294
+ distribution.forEach((count, shardId) => {
295
+ const percentage = testUsers.length > 0 ? (count / testUsers.length * 100).toFixed(1) : "0.0";
296
+ const barLength = testUsers.length > 0 ? Math.round(count / testUsers.length * 15) : 0;
297
+ const bar = "\u2588".repeat(barLength) + "\u2591".repeat(15 - barLength);
298
+ console.log(
299
+ ` \u2502 ${shardId.padEnd(11)} \u2502 ${count.toString().padStart(9)} \u2502 ${percentage.padStart(6)}% \u2502 ${bar} \u2502`
300
+ );
301
+ minCount = Math.min(minCount, count);
302
+ maxCount = Math.max(maxCount, count);
303
+ });
304
+ console.log(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n");
305
+ if (testUsers.length > 0) {
306
+ const minPercentage = minCount / testUsers.length * 100;
307
+ const maxPercentage = maxCount / testUsers.length * 100;
308
+ if (minPercentage < 10) {
309
+ log.warn(`Some shards have very few users (${minPercentage.toFixed(1)}%)`);
310
+ }
311
+ if (maxPercentage > 60) {
312
+ log.warn(`Some shards are overloaded (${maxPercentage.toFixed(1)}%)`);
98
313
  }
314
+ log.detail(`Distribution range: ${minPercentage.toFixed(1)}% - ${maxPercentage.toFixed(1)}%`);
315
+ log.detail(`Average per shard: ${(testUsers.length / shards.length).toFixed(1)} users`);
316
+ }
317
+ });
318
+ log.section("Test 7: Read Verification");
319
+ await runTest("Verify users exist on correct shards", async () => {
320
+ let verified = 0;
321
+ const sampleSize = Math.min(5, testUsers.length);
322
+ for (let i = 0; i < sampleSize; i++) {
323
+ const user = testUsers[i];
324
+ const shard = shards.find((s) => s.id === user.shardId);
325
+ if (!shard) continue;
326
+ const selectSql = `SELECT id, email FROM "${testTableName}" WHERE id = '${user.id}';`;
327
+ const result = await executeSql(shard.url, selectSql);
328
+ if (result.success && result.rows && result.rows.length > 0) {
329
+ verified++;
330
+ log.detail(`\u2713 User "${user.id}" found on ${user.shardId}`);
331
+ } else {
332
+ log.warn(`\u2717 User "${user.id}" NOT found on ${user.shardId}`);
333
+ }
334
+ }
335
+ if (verified < sampleSize) {
336
+ throw new Error(`Only ${verified}/${sampleSize} users verified`);
99
337
  }
338
+ log.detail(`Verified ${verified}/${sampleSize} users on correct shards`);
100
339
  });
101
- log.section("Test Results Summary");
340
+ log.section("Test 8: Cross-Shard Count");
341
+ await runTest("Count users across all shards", async () => {
342
+ let totalCount = 0;
343
+ for (const shard of shards) {
344
+ const countSql = `SELECT COUNT(*) as count FROM "${testTableName}";`;
345
+ const result = await executeSql(shard.url, countSql);
346
+ if (result.success && result.rows && result.rows.length > 0) {
347
+ const count = parseInt(result.rows[0].count, 10);
348
+ totalCount += count;
349
+ log.detail(`${shard.id}: ${count} users`);
350
+ }
351
+ }
352
+ log.detail(`Total users across all shards: ${totalCount}`);
353
+ if (totalCount !== testUsers.length) {
354
+ log.warn(`Expected ${testUsers.length} users, found ${totalCount}`);
355
+ }
356
+ });
357
+ log.section("Test 9: Cleanup");
358
+ let cleanedUp = 0;
359
+ for (const shard of shards) {
360
+ const dropSql = `DROP TABLE IF EXISTS "${testTableName}";`;
361
+ const result = await executeSql(shard.url, dropSql);
362
+ if (result.success) {
363
+ cleanedUp++;
364
+ log.detail(`Test table removed from ${shard.id}`);
365
+ } else {
366
+ log.warn(`Could not drop table on ${shard.id}: ${result.error}`);
367
+ }
368
+ }
369
+ log.success(`Cleanup complete (${cleanedUp}/${shards.length} shards)`);
370
+ console.log("\n" + "\u2550".repeat(60));
371
+ console.log("\u{1F4CB} TEST RESULTS SUMMARY");
372
+ console.log("\u2550".repeat(60));
102
373
  const passed = results.filter((r) => r.passed).length;
103
374
  const failed = results.filter((r) => !r.passed).length;
104
375
  const totalDuration = results.reduce((sum, r) => sum + r.duration, 0);
105
376
  console.log(`
106
377
  Total Tests: ${results.length}`);
107
- console.log(` Passed: ${passed}`);
108
- console.log(` Failed: ${failed}`);
109
- console.log(` Duration: ${totalDuration}ms`);
378
+ console.log(` \u2705 Passed: ${passed}`);
379
+ console.log(` \u274C Failed: ${failed}`);
380
+ console.log(` \u23F1\uFE0F Duration: ${(totalDuration / 1e3).toFixed(2)}s`);
381
+ console.log(` \u{1F4CA} Users Created: ${testUsers.length}`);
110
382
  if (failed > 0) {
111
383
  console.log("\n Failed Tests:");
112
384
  results.filter((r) => !r.passed).forEach((r) => {
113
- console.log(` - ${r.name}: ${r.message}`);
385
+ console.log(` \u2022 ${r.name}: ${r.message}`);
114
386
  });
387
+ console.log("\n\u{1F4A1} Troubleshooting Tips:");
388
+ console.log(" \u2022 Ensure PostgreSQL is running");
389
+ console.log(" \u2022 Verify shard databases exist");
390
+ console.log(" \u2022 Check credentials in SHARD_N_URL");
391
+ console.log(" \u2022 Run: yarn migrate:shards\n");
115
392
  process.exit(1);
116
393
  }
117
- console.log("\n\u2705 All shard tests passed!");
394
+ console.log("\n" + "\u2550".repeat(60));
395
+ console.log("\u2705 ALL TESTS PASSED SUCCESSFULLY!");
396
+ console.log("\u2550".repeat(60) + "\n");
118
397
  };
119
398
  runTests().catch((error) => {
120
399
  console.error("\n\u{1F4A5} Test suite crashed:", error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prisma-sharding",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Lightweight database sharding library for Prisma with connection pooling and health monitoring",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -50,10 +50,12 @@
50
50
  "@prisma/client": ">=5.0.0"
51
51
  },
52
52
  "dependencies": {
53
- "dotenv": "^16.3.1"
53
+ "dotenv": "^16.3.1",
54
+ "pg": "^8.18.0"
54
55
  },
55
56
  "devDependencies": {
56
57
  "@types/node": "^20.10.0",
58
+ "@types/pg": "^8.16.0",
57
59
  "@typescript-eslint/eslint-plugin": "^6.13.0",
58
60
  "@typescript-eslint/parser": "^6.13.0",
59
61
  "eslint": "^8.55.0",