prisma-sharding 0.0.4 → 0.0.6
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 +129 -5
- package/dist/cli/migrate.js +182 -66
- package/dist/cli/studio.js +600 -59
- package/dist/cli/test.js +27 -21
- package/dist/cli/update.js +249 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +19 -1
- package/dist/index.mjs +19 -1
- package/package.json +5 -3
package/dist/cli/test.js
CHANGED
|
@@ -25,6 +25,31 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
|
|
26
26
|
// src/cli/test.ts
|
|
27
27
|
var import_config = require("dotenv/config");
|
|
28
|
+
|
|
29
|
+
// src/cli/utils/shards.ts
|
|
30
|
+
var NO_SHARDS_CONFIGURED_MESSAGE = "No shards configured. Set SHARD_COUNT and SHARD_N_URL environment variables.";
|
|
31
|
+
var getShardConfigResult = (env = process.env) => {
|
|
32
|
+
const shards = [];
|
|
33
|
+
const missingShardIds = [];
|
|
34
|
+
const shardCount = parseInt(env.SHARD_COUNT || "0", 10);
|
|
35
|
+
for (let i = 1; i <= shardCount; i++) {
|
|
36
|
+
const url = env[`SHARD_${i}_URL`];
|
|
37
|
+
if (url) {
|
|
38
|
+
shards.push({ id: `shard_${i}`, index: i - 1, url });
|
|
39
|
+
} else {
|
|
40
|
+
missingShardIds.push(`shard_${i}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (shards.length === 0 && env.DATABASE_URL) {
|
|
44
|
+
shards.push({ id: "shard_1", index: 0, url: env.DATABASE_URL });
|
|
45
|
+
}
|
|
46
|
+
return { shards, missingShardIds };
|
|
47
|
+
};
|
|
48
|
+
var getShardConfigs = (env = process.env) => {
|
|
49
|
+
return getShardConfigResult(env).shards;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/cli/test.ts
|
|
28
53
|
var results = [];
|
|
29
54
|
var testUsers = [];
|
|
30
55
|
var TEST_USER_COUNT = 24;
|
|
@@ -39,20 +64,6 @@ ${"=".repeat(60)}
|
|
|
39
64
|
${"=".repeat(60)}`),
|
|
40
65
|
detail: (msg) => console.log(` ${msg}`)
|
|
41
66
|
};
|
|
42
|
-
var getShardConfigs = () => {
|
|
43
|
-
const shards = [];
|
|
44
|
-
const shardCount = parseInt(process.env.SHARD_COUNT || "0", 10);
|
|
45
|
-
for (let i = 1; i <= shardCount; i++) {
|
|
46
|
-
const url = process.env[`SHARD_${i}_URL`];
|
|
47
|
-
if (url) {
|
|
48
|
-
shards.push({ id: `shard_${i}`, url });
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (shards.length === 0 && process.env.DATABASE_URL) {
|
|
52
|
-
shards.push({ id: "shard_1", url: process.env.DATABASE_URL });
|
|
53
|
-
}
|
|
54
|
-
return shards;
|
|
55
|
-
};
|
|
56
67
|
var runTest = async (name, testFn) => {
|
|
57
68
|
const start = Date.now();
|
|
58
69
|
try {
|
|
@@ -139,11 +150,7 @@ var executeSqlWithPsql = (url, sql) => {
|
|
|
139
150
|
shell: true,
|
|
140
151
|
stdio: ["pipe", "pipe", "pipe"]
|
|
141
152
|
});
|
|
142
|
-
let stdout = "";
|
|
143
153
|
let stderr = "";
|
|
144
|
-
psql.stdout?.on("data", (data) => {
|
|
145
|
-
stdout += data.toString();
|
|
146
|
-
});
|
|
147
154
|
psql.stderr?.on("data", (data) => {
|
|
148
155
|
stderr += data.toString();
|
|
149
156
|
});
|
|
@@ -188,9 +195,8 @@ var runTests = async () => {
|
|
|
188
195
|
console.log(` \u2022 Test Users: ${TEST_USER_COUNT}`);
|
|
189
196
|
console.log(` \u2022 Test Table: ${testTableName}`);
|
|
190
197
|
if (shards.length === 0) {
|
|
191
|
-
console.error(
|
|
192
|
-
|
|
193
|
-
);
|
|
198
|
+
console.error(`
|
|
199
|
+
\u274C ${NO_SHARDS_CONFIGURED_MESSAGE}`);
|
|
194
200
|
process.exit(1);
|
|
195
201
|
}
|
|
196
202
|
const pgAvailable = await getPgClient();
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
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
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/cli/update.ts
|
|
27
|
+
var import_config = require("dotenv/config");
|
|
28
|
+
|
|
29
|
+
// src/utils/env.ts
|
|
30
|
+
var parseBooleanEnv = (name, defaultValue, env = process.env) => {
|
|
31
|
+
const value = env[name]?.trim();
|
|
32
|
+
if (value === void 0 || value === "") {
|
|
33
|
+
return defaultValue;
|
|
34
|
+
}
|
|
35
|
+
return ["1", "true", "yes", "on"].includes(value.toLowerCase());
|
|
36
|
+
};
|
|
37
|
+
var isVerboseEnv = (names, env = process.env) => names.some((name) => parseBooleanEnv(name, false, env));
|
|
38
|
+
|
|
39
|
+
// src/cli/utils/command.ts
|
|
40
|
+
var import_child_process = require("child_process");
|
|
41
|
+
var import_path = __toESM(require("path"));
|
|
42
|
+
var getNpxCommand = () => process.platform === "win32" ? "npx.cmd" : "npx";
|
|
43
|
+
var runCommand = (command, args, options = {}) => {
|
|
44
|
+
return new Promise((resolve) => {
|
|
45
|
+
let stdout = "";
|
|
46
|
+
let stderr = "";
|
|
47
|
+
let settled = false;
|
|
48
|
+
const child = (0, import_child_process.spawn)(command, args, {
|
|
49
|
+
env: options.env || process.env,
|
|
50
|
+
cwd: import_path.default.resolve(options.cwd || process.cwd()),
|
|
51
|
+
shell: false,
|
|
52
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
53
|
+
});
|
|
54
|
+
const settle = (result) => {
|
|
55
|
+
if (!settled) {
|
|
56
|
+
settled = true;
|
|
57
|
+
resolve(result);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
child.stdout?.on("data", (data) => {
|
|
61
|
+
const output = data.toString();
|
|
62
|
+
stdout += output;
|
|
63
|
+
if (options.verbose) {
|
|
64
|
+
process.stdout.write(output);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
child.stderr?.on("data", (data) => {
|
|
68
|
+
const output = data.toString();
|
|
69
|
+
stderr += output;
|
|
70
|
+
if (options.verbose) {
|
|
71
|
+
process.stderr.write(output);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
child.once("error", (error) => {
|
|
75
|
+
settle({
|
|
76
|
+
success: false,
|
|
77
|
+
stdout,
|
|
78
|
+
stderr,
|
|
79
|
+
error: error.message
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
child.once("close", (exitCode) => {
|
|
83
|
+
settle({
|
|
84
|
+
success: exitCode === 0,
|
|
85
|
+
stdout,
|
|
86
|
+
stderr,
|
|
87
|
+
exitCode,
|
|
88
|
+
error: exitCode === 0 ? void 0 : stderr.trim() || stdout.trim() || `Command exited with code ${exitCode}`
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
var runPrismaCommand = (args, options = {}) => runCommand(getNpxCommand(), ["prisma", ...args], options);
|
|
94
|
+
|
|
95
|
+
// src/cli/utils/output.ts
|
|
96
|
+
var import_readline = __toESM(require("readline"));
|
|
97
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
98
|
+
var printCliHeader = (icon, title) => {
|
|
99
|
+
console.log(`${icon} ${title}
|
|
100
|
+
`);
|
|
101
|
+
};
|
|
102
|
+
var printCliRow = (icon, label, message) => {
|
|
103
|
+
console.log(`${icon} ${label} ${message}`);
|
|
104
|
+
};
|
|
105
|
+
var printVerboseHint = () => {
|
|
106
|
+
console.log("\nRun with SHARD_CLI_VERBOSE=true for details.");
|
|
107
|
+
};
|
|
108
|
+
var createCliLoader = (label, message, enabled = true) => {
|
|
109
|
+
const animated = enabled && Boolean(process.stdout.isTTY);
|
|
110
|
+
let frameIndex = 0;
|
|
111
|
+
let timer;
|
|
112
|
+
let finished = false;
|
|
113
|
+
const clear = () => {
|
|
114
|
+
if (animated) {
|
|
115
|
+
import_readline.default.clearLine(process.stdout, 0);
|
|
116
|
+
import_readline.default.cursorTo(process.stdout, 0);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const render = () => {
|
|
120
|
+
clear();
|
|
121
|
+
process.stdout.write(`${SPINNER_FRAMES[frameIndex]} ${label} ${message}`);
|
|
122
|
+
frameIndex = (frameIndex + 1) % SPINNER_FRAMES.length;
|
|
123
|
+
};
|
|
124
|
+
if (animated) {
|
|
125
|
+
render();
|
|
126
|
+
timer = setInterval(render, 80);
|
|
127
|
+
}
|
|
128
|
+
const finish = (icon, finalMessage) => {
|
|
129
|
+
if (finished) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
finished = true;
|
|
133
|
+
if (timer) {
|
|
134
|
+
clearInterval(timer);
|
|
135
|
+
}
|
|
136
|
+
clear();
|
|
137
|
+
printCliRow(icon, label, finalMessage);
|
|
138
|
+
};
|
|
139
|
+
return {
|
|
140
|
+
succeed: (finalMessage) => finish("\u2705", finalMessage),
|
|
141
|
+
fail: (finalMessage) => finish("\u274C", finalMessage)
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// src/cli/utils/shards.ts
|
|
146
|
+
var NO_SHARDS_CONFIGURED_MESSAGE = "No shards configured. Set SHARD_COUNT and SHARD_N_URL environment variables.";
|
|
147
|
+
var getShardConfigResult = (env = process.env) => {
|
|
148
|
+
const shards = [];
|
|
149
|
+
const missingShardIds = [];
|
|
150
|
+
const shardCount = parseInt(env.SHARD_COUNT || "0", 10);
|
|
151
|
+
for (let i = 1; i <= shardCount; i++) {
|
|
152
|
+
const url = env[`SHARD_${i}_URL`];
|
|
153
|
+
if (url) {
|
|
154
|
+
shards.push({ id: `shard_${i}`, index: i - 1, url });
|
|
155
|
+
} else {
|
|
156
|
+
missingShardIds.push(`shard_${i}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (shards.length === 0 && env.DATABASE_URL) {
|
|
160
|
+
shards.push({ id: "shard_1", index: 0, url: env.DATABASE_URL });
|
|
161
|
+
}
|
|
162
|
+
return { shards, missingShardIds };
|
|
163
|
+
};
|
|
164
|
+
var getShardConfigs = (env = process.env) => {
|
|
165
|
+
return getShardConfigResult(env).shards;
|
|
166
|
+
};
|
|
167
|
+
var maskShardUrl = (url) => {
|
|
168
|
+
try {
|
|
169
|
+
const parsed = new URL(url);
|
|
170
|
+
if (parsed.password) {
|
|
171
|
+
parsed.password = "***";
|
|
172
|
+
}
|
|
173
|
+
return parsed.toString();
|
|
174
|
+
} catch {
|
|
175
|
+
return url.replace(/:[^:@]+@/, ":***@");
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// src/cli/utils/prisma.ts
|
|
180
|
+
var syncShardSchemas = async (shards, extraArgs, verbose) => {
|
|
181
|
+
const results = [];
|
|
182
|
+
for (const shard of shards) {
|
|
183
|
+
const loader = createCliLoader(shard.id, "Syncing", !verbose);
|
|
184
|
+
if (verbose) {
|
|
185
|
+
console.log(`
|
|
186
|
+
Syncing ${shard.id}...`);
|
|
187
|
+
console.log(`Database: ${maskShardUrl(shard.url)}
|
|
188
|
+
`);
|
|
189
|
+
}
|
|
190
|
+
const result = await runPrismaCommand(
|
|
191
|
+
["db", "push", "--accept-data-loss", ...extraArgs],
|
|
192
|
+
{
|
|
193
|
+
env: { ...process.env, DATABASE_URL: shard.url },
|
|
194
|
+
verbose
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
if (verbose && result.error && !result.stderr.trim() && !result.stdout.trim()) {
|
|
198
|
+
console.error(result.error);
|
|
199
|
+
}
|
|
200
|
+
results.push({ shardId: shard.id, success: result.success });
|
|
201
|
+
if (result.success) {
|
|
202
|
+
loader.succeed("Synced");
|
|
203
|
+
} else {
|
|
204
|
+
loader.fail("Failed");
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return results;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// src/cli/update.ts
|
|
211
|
+
var updateAll = async () => {
|
|
212
|
+
const verbose = isVerboseEnv(["SHARD_UPDATE_VERBOSE", "SHARD_CLI_VERBOSE"]);
|
|
213
|
+
const shards = getShardConfigs();
|
|
214
|
+
const extraArgs = process.argv.slice(2);
|
|
215
|
+
printCliHeader("\u{1F504}", "Prisma Sharding Update");
|
|
216
|
+
if (shards.length === 0) {
|
|
217
|
+
printCliRow("\u274C", "config", NO_SHARDS_CONFIGURED_MESSAGE);
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
if (verbose) {
|
|
221
|
+
console.log("Generating Prisma Client...\n");
|
|
222
|
+
}
|
|
223
|
+
const generateLoader = createCliLoader("client", "Generating", !verbose);
|
|
224
|
+
const generateResult = await runPrismaCommand(["generate"], { verbose });
|
|
225
|
+
if (verbose && generateResult.error && !generateResult.stderr.trim() && !generateResult.stdout.trim()) {
|
|
226
|
+
console.error(generateResult.error);
|
|
227
|
+
}
|
|
228
|
+
if (!generateResult.success) {
|
|
229
|
+
generateLoader.fail("Generation failed");
|
|
230
|
+
if (!verbose) {
|
|
231
|
+
printVerboseHint();
|
|
232
|
+
}
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
generateLoader.succeed("Generated");
|
|
236
|
+
const results = await syncShardSchemas(shards, extraArgs, verbose);
|
|
237
|
+
const successful = results.filter((result) => result.success).length;
|
|
238
|
+
const failed = results.length - successful;
|
|
239
|
+
if (failed > 0) {
|
|
240
|
+
if (!verbose) {
|
|
241
|
+
printVerboseHint();
|
|
242
|
+
}
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
updateAll().catch((error) => {
|
|
247
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
248
|
+
process.exit(1);
|
|
249
|
+
});
|
package/dist/index.d.mts
CHANGED
|
@@ -68,6 +68,10 @@ declare class PrismaSharding<TClient> {
|
|
|
68
68
|
getShardById(shardId: string): TClient;
|
|
69
69
|
getShardWithInfo(key: string): ShardResult<TClient>;
|
|
70
70
|
getRandomShard(): TClient;
|
|
71
|
+
/**
|
|
72
|
+
* Returns both the random shard client and its shardId.
|
|
73
|
+
* Used when the shardId must be stored on the user record for future routing.
|
|
74
|
+
*/
|
|
71
75
|
getRandomShardWithInfo(): ShardResult<TClient>;
|
|
72
76
|
findFirst<T>(finder: (client: TClient) => Promise<T | null>): Promise<FindFirstResult<T, TClient>>;
|
|
73
77
|
runOnAll<T>(operation: (client: TClient, shardId: string) => Promise<T>): Promise<T[]>;
|
package/dist/index.d.ts
CHANGED
|
@@ -68,6 +68,10 @@ declare class PrismaSharding<TClient> {
|
|
|
68
68
|
getShardById(shardId: string): TClient;
|
|
69
69
|
getShardWithInfo(key: string): ShardResult<TClient>;
|
|
70
70
|
getRandomShard(): TClient;
|
|
71
|
+
/**
|
|
72
|
+
* Returns both the random shard client and its shardId.
|
|
73
|
+
* Used when the shardId must be stored on the user record for future routing.
|
|
74
|
+
*/
|
|
71
75
|
getRandomShardWithInfo(): ShardResult<TClient>;
|
|
72
76
|
findFirst<T>(finder: (client: TClient) => Promise<T | null>): Promise<FindFirstResult<T, TClient>>;
|
|
73
77
|
runOnAll<T>(operation: (client: TClient, shardId: string) => Promise<T>): Promise<T[]>;
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,15 @@ __export(index_exports, {
|
|
|
33
33
|
});
|
|
34
34
|
module.exports = __toCommonJS(index_exports);
|
|
35
35
|
|
|
36
|
+
// src/utils/env.ts
|
|
37
|
+
var parseBooleanEnv = (name, defaultValue, env = process.env) => {
|
|
38
|
+
const value = env[name]?.trim();
|
|
39
|
+
if (value === void 0 || value === "") {
|
|
40
|
+
return defaultValue;
|
|
41
|
+
}
|
|
42
|
+
return ["1", "true", "yes", "on"].includes(value.toLowerCase());
|
|
43
|
+
};
|
|
44
|
+
|
|
36
45
|
// src/utils/index.ts
|
|
37
46
|
function hashString(str) {
|
|
38
47
|
let hash = 0;
|
|
@@ -47,8 +56,13 @@ function validateUrl(url) {
|
|
|
47
56
|
return url.startsWith("postgresql://") || url.startsWith("postgres://");
|
|
48
57
|
}
|
|
49
58
|
function createDefaultLogger() {
|
|
59
|
+
const verbose = parseBooleanEnv("PRISMA_SHARDING_VERBOSE", false);
|
|
50
60
|
return {
|
|
51
|
-
info: (msg) =>
|
|
61
|
+
info: (msg) => {
|
|
62
|
+
if (verbose) {
|
|
63
|
+
console.log(`[PrismaSharding] ${msg}`);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
52
66
|
warn: (msg) => console.warn(`[PrismaSharding] ${msg}`),
|
|
53
67
|
error: (msg) => console.error(`[PrismaSharding] ${msg}`)
|
|
54
68
|
};
|
|
@@ -416,6 +430,10 @@ var PrismaSharding = class {
|
|
|
416
430
|
const shardId = this.router.getRandomShardId();
|
|
417
431
|
return this.manager.getClient(shardId);
|
|
418
432
|
}
|
|
433
|
+
/**
|
|
434
|
+
* Returns both the random shard client and its shardId.
|
|
435
|
+
* Used when the shardId must be stored on the user record for future routing.
|
|
436
|
+
*/
|
|
419
437
|
getRandomShardWithInfo() {
|
|
420
438
|
this.ensureConnected();
|
|
421
439
|
const shardId = this.router.getRandomShardId();
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
// src/utils/env.ts
|
|
2
|
+
var parseBooleanEnv = (name, defaultValue, env = process.env) => {
|
|
3
|
+
const value = env[name]?.trim();
|
|
4
|
+
if (value === void 0 || value === "") {
|
|
5
|
+
return defaultValue;
|
|
6
|
+
}
|
|
7
|
+
return ["1", "true", "yes", "on"].includes(value.toLowerCase());
|
|
8
|
+
};
|
|
9
|
+
|
|
1
10
|
// src/utils/index.ts
|
|
2
11
|
function hashString(str) {
|
|
3
12
|
let hash = 0;
|
|
@@ -12,8 +21,13 @@ function validateUrl(url) {
|
|
|
12
21
|
return url.startsWith("postgresql://") || url.startsWith("postgres://");
|
|
13
22
|
}
|
|
14
23
|
function createDefaultLogger() {
|
|
24
|
+
const verbose = parseBooleanEnv("PRISMA_SHARDING_VERBOSE", false);
|
|
15
25
|
return {
|
|
16
|
-
info: (msg) =>
|
|
26
|
+
info: (msg) => {
|
|
27
|
+
if (verbose) {
|
|
28
|
+
console.log(`[PrismaSharding] ${msg}`);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
17
31
|
warn: (msg) => console.warn(`[PrismaSharding] ${msg}`),
|
|
18
32
|
error: (msg) => console.error(`[PrismaSharding] ${msg}`)
|
|
19
33
|
};
|
|
@@ -381,6 +395,10 @@ var PrismaSharding = class {
|
|
|
381
395
|
const shardId = this.router.getRandomShardId();
|
|
382
396
|
return this.manager.getClient(shardId);
|
|
383
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Returns both the random shard client and its shardId.
|
|
400
|
+
* Used when the shardId must be stored on the user record for future routing.
|
|
401
|
+
*/
|
|
384
402
|
getRandomShardWithInfo() {
|
|
385
403
|
this.ensureConnected();
|
|
386
404
|
const shardId = this.router.getRandomShardId();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prisma-sharding",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
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",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"bin": {
|
|
22
22
|
"prisma-sharding-migrate": "./dist/cli/migrate.js",
|
|
23
|
+
"prisma-sharding-update": "./dist/cli/update.js",
|
|
23
24
|
"prisma-sharding-studio": "./dist/cli/studio.js",
|
|
24
25
|
"prisma-sharding-test": "./dist/cli/test.js"
|
|
25
26
|
},
|
|
@@ -34,11 +35,12 @@
|
|
|
34
35
|
}
|
|
35
36
|
},
|
|
36
37
|
"scripts": {
|
|
37
|
-
"build": "tsup src/index.ts --format cjs,esm --dts --clean && tsup src/cli/migrate.ts src/cli/studio.ts src/cli/test.ts --format cjs --outDir dist/cli --clean",
|
|
38
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean && tsup src/cli/migrate.ts src/cli/studio.ts src/cli/test.ts src/cli/update.ts --format cjs --outDir dist/cli --clean",
|
|
38
39
|
"build:lib": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
39
|
-
"build:cli": "tsup src/cli/migrate.ts src/cli/studio.ts src/cli/test.ts --format cjs --outDir dist/cli",
|
|
40
|
+
"build:cli": "tsup src/cli/migrate.ts src/cli/studio.ts src/cli/test.ts src/cli/update.ts --format cjs --outDir dist/cli",
|
|
40
41
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
41
42
|
"lint": "eslint src --ext .ts",
|
|
43
|
+
"test": "yarn build && node --test test/*.test.js",
|
|
42
44
|
"typecheck": "tsc --noEmit",
|
|
43
45
|
"prepublishOnly": "yarn build",
|
|
44
46
|
"patch": "yarn version --patch && yarn publish",
|