prisma-sharding 0.0.6 → 0.0.7

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.
@@ -39,36 +39,152 @@ var isVerboseEnv = (names, env = process.env) => names.some((name) => parseBoole
39
39
  // src/cli/utils/command.ts
40
40
  var import_child_process = require("child_process");
41
41
  var import_path = __toESM(require("path"));
42
+
43
+ // src/constants/internal.ts
44
+ var INTERNAL_DEFAULTS = {
45
+ HEALTH_CHECK_TIMEOUT_MS: 5e3,
46
+ CROSS_SHARD_CONCURRENCY: 4,
47
+ CROSS_SHARD_TIMEOUT_MS: 1e4,
48
+ CLI_COMMAND_TIMEOUT_MS: 12e4,
49
+ CLI_FORCE_KILL_GRACE_MS: 5e3,
50
+ CLI_MAX_OUTPUT_LENGTH: 1e6,
51
+ CLI_TEST_TCP_TIMEOUT_MS: 5e3,
52
+ CLI_TEST_COMMAND_TIMEOUT_MS: 15e3,
53
+ STUDIO_BASE_PORT: 51212,
54
+ STUDIO_REUSE_EXISTING: true,
55
+ STUDIO_STRICT_PORT_CHECK: false,
56
+ STUDIO_START_TIMEOUT_MS: 15e3,
57
+ STUDIO_STABILITY_MS: 500,
58
+ STUDIO_SHUTDOWN_TIMEOUT_MS: 5e3
59
+ };
60
+
61
+ // src/utils/sanitize.ts
62
+ var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
63
+ var maskDatabaseUrl = (url) => {
64
+ try {
65
+ const parsed = new URL(url);
66
+ if (parsed.password) {
67
+ parsed.password = "***";
68
+ }
69
+ return parsed.toString();
70
+ } catch {
71
+ return url.replace(/:[^:@]+@/, ":***@");
72
+ }
73
+ };
74
+ var sanitizeDatabaseText = (output, databaseUrls) => {
75
+ let sanitized = output;
76
+ for (const url of databaseUrls) {
77
+ sanitized = sanitized.replace(new RegExp(escapeRegExp(url), "g"), maskDatabaseUrl(url));
78
+ try {
79
+ const password = new URL(url).password;
80
+ if (password.length >= 4) {
81
+ sanitized = sanitized.replace(
82
+ new RegExp(escapeRegExp(decodeURIComponent(password)), "g"),
83
+ "***"
84
+ );
85
+ }
86
+ } catch {
87
+ }
88
+ }
89
+ return sanitized.replace(
90
+ /(postgres(?:ql)?:\/\/[^:/\s]+:)[^@\s]+(@)/gi,
91
+ "$1***$2"
92
+ );
93
+ };
94
+
95
+ // src/cli/utils/process.ts
96
+ var isChildProcessRunning = (childProcess) => {
97
+ return childProcess.exitCode === null && childProcess.signalCode === null;
98
+ };
99
+ var terminateChildProcess = (childProcess, options = {}) => {
100
+ if (!isChildProcessRunning(childProcess)) {
101
+ return false;
102
+ }
103
+ const signal = options.signal || "SIGTERM";
104
+ try {
105
+ if (options.processGroup && childProcess.pid && process.platform !== "win32") {
106
+ try {
107
+ process.kill(-childProcess.pid, signal);
108
+ return true;
109
+ } catch {
110
+ }
111
+ }
112
+ return childProcess.kill(signal);
113
+ } catch {
114
+ return false;
115
+ }
116
+ };
117
+
118
+ // src/cli/utils/command.ts
42
119
  var getNpxCommand = () => process.platform === "win32" ? "npx.cmd" : "npx";
120
+ var OUTPUT_TRUNCATED_MARKER = "\n[output truncated]\n";
121
+ var appendBoundedOutput = (current, chunk, limit) => {
122
+ const combined = current + chunk;
123
+ if (combined.length <= limit) {
124
+ return combined;
125
+ }
126
+ if (limit <= OUTPUT_TRUNCATED_MARKER.length) {
127
+ return combined.slice(-limit);
128
+ }
129
+ return OUTPUT_TRUNCATED_MARKER + combined.slice(-(limit - OUTPUT_TRUNCATED_MARKER.length));
130
+ };
131
+ var sanitizeCommandOutput = (output, env = process.env) => {
132
+ const databaseUrls = Object.entries(env).filter(
133
+ ([name, value]) => Boolean(value) && (name === "DATABASE_URL" || /^SHARD_\d+_URL$/.test(name))
134
+ ).map(([, value]) => value);
135
+ return sanitizeDatabaseText(output, databaseUrls).replace(/(\bpassword\s*[=:]\s*)[^\s,;]+/gi, "$1***");
136
+ };
43
137
  var runCommand = (command, args, options = {}) => {
44
138
  return new Promise((resolve) => {
45
139
  let stdout = "";
46
140
  let stderr = "";
47
141
  let settled = false;
142
+ let timedOut = false;
143
+ let forceKillTimeout;
144
+ const env = options.env || process.env;
145
+ const timeoutMs = options.timeoutMs ?? INTERNAL_DEFAULTS.CLI_COMMAND_TIMEOUT_MS;
146
+ const forceKillGraceMs = options.forceKillGraceMs ?? INTERNAL_DEFAULTS.CLI_FORCE_KILL_GRACE_MS;
147
+ const maxOutputLength = options.maxOutputLength ?? INTERNAL_DEFAULTS.CLI_MAX_OUTPUT_LENGTH;
148
+ const processGroup = process.platform !== "win32";
48
149
  const child = (0, import_child_process.spawn)(command, args, {
49
- env: options.env || process.env,
150
+ env,
50
151
  cwd: import_path.default.resolve(options.cwd || process.cwd()),
152
+ detached: processGroup,
51
153
  shell: false,
52
154
  stdio: ["ignore", "pipe", "pipe"]
53
155
  });
54
156
  const settle = (result) => {
55
157
  if (!settled) {
56
158
  settled = true;
57
- resolve(result);
159
+ clearTimeout(timeout);
160
+ if (forceKillTimeout) {
161
+ clearTimeout(forceKillTimeout);
162
+ }
163
+ const sanitizedResult = {
164
+ ...result,
165
+ stdout: sanitizeCommandOutput(result.stdout, env),
166
+ stderr: sanitizeCommandOutput(result.stderr, env),
167
+ error: result.error ? sanitizeCommandOutput(result.error, env) : void 0
168
+ };
169
+ if (options.verbose) {
170
+ if (sanitizedResult.stdout) {
171
+ process.stdout.write(sanitizedResult.stdout);
172
+ }
173
+ if (sanitizedResult.stderr) {
174
+ process.stderr.write(sanitizedResult.stderr);
175
+ }
176
+ }
177
+ resolve(sanitizedResult);
58
178
  }
59
179
  };
60
180
  child.stdout?.on("data", (data) => {
61
- const output = data.toString();
62
- stdout += output;
63
- if (options.verbose) {
64
- process.stdout.write(output);
181
+ if (!settled) {
182
+ stdout = appendBoundedOutput(stdout, data.toString(), maxOutputLength);
65
183
  }
66
184
  });
67
185
  child.stderr?.on("data", (data) => {
68
- const output = data.toString();
69
- stderr += output;
70
- if (options.verbose) {
71
- process.stderr.write(output);
186
+ if (!settled) {
187
+ stderr = appendBoundedOutput(stderr, data.toString(), maxOutputLength);
72
188
  }
73
189
  });
74
190
  child.once("error", (error) => {
@@ -76,18 +192,35 @@ var runCommand = (command, args, options = {}) => {
76
192
  success: false,
77
193
  stdout,
78
194
  stderr,
79
- error: error.message
195
+ exitCode: null,
196
+ error: timedOut ? `Command timed out after ${timeoutMs}ms` : error.message
80
197
  });
81
198
  });
82
199
  child.once("close", (exitCode) => {
83
200
  settle({
84
- success: exitCode === 0,
201
+ success: !timedOut && exitCode === 0,
85
202
  stdout,
86
203
  stderr,
87
204
  exitCode,
88
- error: exitCode === 0 ? void 0 : stderr.trim() || stdout.trim() || `Command exited with code ${exitCode}`
205
+ error: timedOut ? `Command timed out after ${timeoutMs}ms` : exitCode === 0 ? void 0 : stderr.trim() || stdout.trim() || `Command exited with code ${exitCode}`
89
206
  });
90
207
  });
208
+ const timeout = setTimeout(() => {
209
+ timedOut = true;
210
+ terminateChildProcess(child, { signal: "SIGTERM", processGroup });
211
+ forceKillTimeout = setTimeout(() => {
212
+ terminateChildProcess(child, { signal: "SIGKILL", processGroup });
213
+ settle({
214
+ success: false,
215
+ stdout,
216
+ stderr,
217
+ exitCode: null,
218
+ error: `Command timed out after ${timeoutMs}ms`
219
+ });
220
+ }, forceKillGraceMs);
221
+ forceKillTimeout.unref?.();
222
+ }, timeoutMs);
223
+ timeout.unref?.();
91
224
  });
92
225
  };
93
226
  var runPrismaCommand = (args, options = {}) => runCommand(getNpxCommand(), ["prisma", ...args], options);
@@ -161,42 +294,47 @@ var getShardConfigResult = (env = process.env) => {
161
294
  }
162
295
  return { shards, missingShardIds };
163
296
  };
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
- };
297
+ var maskShardUrl = maskDatabaseUrl;
178
298
 
179
299
  // 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)}
300
+ var executeShardCommand = async (shard, commandArgs, verbose, action) => {
301
+ const commandEnv = { ...process.env, DATABASE_URL: shard.url };
302
+ if (verbose) {
303
+ console.log(`
304
+ ${action} ${shard.id}...`);
305
+ console.log(`Database: ${maskShardUrl(shard.url)}
188
306
  `);
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
- }
307
+ console.log(
308
+ `Command: ${sanitizeCommandOutput(`prisma ${commandArgs.join(" ")}`, commandEnv)}`
196
309
  );
197
- if (verbose && result.error && !result.stderr.trim() && !result.stdout.trim()) {
198
- console.error(result.error);
199
- }
310
+ }
311
+ const result = await runPrismaCommand(commandArgs, {
312
+ env: commandEnv,
313
+ verbose
314
+ });
315
+ if (verbose) {
316
+ console.log(`Exit code: ${result.exitCode ?? "unavailable"}`);
317
+ }
318
+ if (verbose && result.error && !result.stderr.trim() && !result.stdout.trim()) {
319
+ console.error(result.error);
320
+ }
321
+ if (verbose && !result.success) {
322
+ console.error(`Next: verify ${shard.id} connectivity and migration state, then retry.`);
323
+ }
324
+ return result;
325
+ };
326
+ var runShardCommands = async ({
327
+ shards,
328
+ args,
329
+ extraArgs,
330
+ verbose,
331
+ action
332
+ }) => {
333
+ const results = [];
334
+ for (const shard of shards) {
335
+ const loader = createCliLoader(shard.id, action, !verbose);
336
+ const commandArgs = [...args, ...extraArgs];
337
+ const result = await executeShardCommand(shard, commandArgs, verbose, action);
200
338
  results.push({ shardId: shard.id, success: result.success });
201
339
  if (result.success) {
202
340
  loader.succeed("Synced");
@@ -206,13 +344,24 @@ Syncing ${shard.id}...`);
206
344
  }
207
345
  return results;
208
346
  };
347
+ var syncShardSchemas = (shards, extraArgs, verbose) => runShardCommands({
348
+ shards,
349
+ args: ["db", "push"],
350
+ extraArgs,
351
+ verbose,
352
+ action: "Syncing"
353
+ });
209
354
 
210
355
  // src/cli/update.ts
211
356
  var updateAll = async () => {
212
357
  const verbose = isVerboseEnv(["SHARD_UPDATE_VERBOSE", "SHARD_CLI_VERBOSE"]);
213
- const shards = getShardConfigs();
358
+ const { shards, missingShardIds } = getShardConfigResult();
214
359
  const extraArgs = process.argv.slice(2);
215
360
  printCliHeader("\u{1F504}", "Prisma Sharding Update");
361
+ if (missingShardIds.length > 0) {
362
+ printCliRow("\u274C", "config", `Missing shard URLs: ${missingShardIds.join(", ")}`);
363
+ process.exit(1);
364
+ }
216
365
  if (shards.length === 0) {
217
366
  printCliRow("\u274C", "config", NO_SHARDS_CONFIGURED_MESSAGE);
218
367
  process.exit(1);
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/cli/utils/command.ts
31
+ var command_exports = {};
32
+ __export(command_exports, {
33
+ getNpxCommand: () => getNpxCommand,
34
+ runCommand: () => runCommand,
35
+ runPrismaCommand: () => runPrismaCommand,
36
+ sanitizeCommandOutput: () => sanitizeCommandOutput
37
+ });
38
+ module.exports = __toCommonJS(command_exports);
39
+ var import_child_process = require("child_process");
40
+ var import_path = __toESM(require("path"));
41
+
42
+ // src/constants/internal.ts
43
+ var INTERNAL_DEFAULTS = {
44
+ HEALTH_CHECK_TIMEOUT_MS: 5e3,
45
+ CROSS_SHARD_CONCURRENCY: 4,
46
+ CROSS_SHARD_TIMEOUT_MS: 1e4,
47
+ CLI_COMMAND_TIMEOUT_MS: 12e4,
48
+ CLI_FORCE_KILL_GRACE_MS: 5e3,
49
+ CLI_MAX_OUTPUT_LENGTH: 1e6,
50
+ CLI_TEST_TCP_TIMEOUT_MS: 5e3,
51
+ CLI_TEST_COMMAND_TIMEOUT_MS: 15e3,
52
+ STUDIO_BASE_PORT: 51212,
53
+ STUDIO_REUSE_EXISTING: true,
54
+ STUDIO_STRICT_PORT_CHECK: false,
55
+ STUDIO_START_TIMEOUT_MS: 15e3,
56
+ STUDIO_STABILITY_MS: 500,
57
+ STUDIO_SHUTDOWN_TIMEOUT_MS: 5e3
58
+ };
59
+
60
+ // src/utils/sanitize.ts
61
+ var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
62
+ var maskDatabaseUrl = (url) => {
63
+ try {
64
+ const parsed = new URL(url);
65
+ if (parsed.password) {
66
+ parsed.password = "***";
67
+ }
68
+ return parsed.toString();
69
+ } catch {
70
+ return url.replace(/:[^:@]+@/, ":***@");
71
+ }
72
+ };
73
+ var sanitizeDatabaseText = (output, databaseUrls) => {
74
+ let sanitized = output;
75
+ for (const url of databaseUrls) {
76
+ sanitized = sanitized.replace(new RegExp(escapeRegExp(url), "g"), maskDatabaseUrl(url));
77
+ try {
78
+ const password = new URL(url).password;
79
+ if (password.length >= 4) {
80
+ sanitized = sanitized.replace(
81
+ new RegExp(escapeRegExp(decodeURIComponent(password)), "g"),
82
+ "***"
83
+ );
84
+ }
85
+ } catch {
86
+ }
87
+ }
88
+ return sanitized.replace(
89
+ /(postgres(?:ql)?:\/\/[^:/\s]+:)[^@\s]+(@)/gi,
90
+ "$1***$2"
91
+ );
92
+ };
93
+
94
+ // src/cli/utils/process.ts
95
+ var isChildProcessRunning = (childProcess) => {
96
+ return childProcess.exitCode === null && childProcess.signalCode === null;
97
+ };
98
+ var terminateChildProcess = (childProcess, options = {}) => {
99
+ if (!isChildProcessRunning(childProcess)) {
100
+ return false;
101
+ }
102
+ const signal = options.signal || "SIGTERM";
103
+ try {
104
+ if (options.processGroup && childProcess.pid && process.platform !== "win32") {
105
+ try {
106
+ process.kill(-childProcess.pid, signal);
107
+ return true;
108
+ } catch {
109
+ }
110
+ }
111
+ return childProcess.kill(signal);
112
+ } catch {
113
+ return false;
114
+ }
115
+ };
116
+
117
+ // src/cli/utils/command.ts
118
+ var getNpxCommand = () => process.platform === "win32" ? "npx.cmd" : "npx";
119
+ var OUTPUT_TRUNCATED_MARKER = "\n[output truncated]\n";
120
+ var appendBoundedOutput = (current, chunk, limit) => {
121
+ const combined = current + chunk;
122
+ if (combined.length <= limit) {
123
+ return combined;
124
+ }
125
+ if (limit <= OUTPUT_TRUNCATED_MARKER.length) {
126
+ return combined.slice(-limit);
127
+ }
128
+ return OUTPUT_TRUNCATED_MARKER + combined.slice(-(limit - OUTPUT_TRUNCATED_MARKER.length));
129
+ };
130
+ var sanitizeCommandOutput = (output, env = process.env) => {
131
+ const databaseUrls = Object.entries(env).filter(
132
+ ([name, value]) => Boolean(value) && (name === "DATABASE_URL" || /^SHARD_\d+_URL$/.test(name))
133
+ ).map(([, value]) => value);
134
+ return sanitizeDatabaseText(output, databaseUrls).replace(/(\bpassword\s*[=:]\s*)[^\s,;]+/gi, "$1***");
135
+ };
136
+ var runCommand = (command, args, options = {}) => {
137
+ return new Promise((resolve) => {
138
+ let stdout = "";
139
+ let stderr = "";
140
+ let settled = false;
141
+ let timedOut = false;
142
+ let forceKillTimeout;
143
+ const env = options.env || process.env;
144
+ const timeoutMs = options.timeoutMs ?? INTERNAL_DEFAULTS.CLI_COMMAND_TIMEOUT_MS;
145
+ const forceKillGraceMs = options.forceKillGraceMs ?? INTERNAL_DEFAULTS.CLI_FORCE_KILL_GRACE_MS;
146
+ const maxOutputLength = options.maxOutputLength ?? INTERNAL_DEFAULTS.CLI_MAX_OUTPUT_LENGTH;
147
+ const processGroup = process.platform !== "win32";
148
+ const child = (0, import_child_process.spawn)(command, args, {
149
+ env,
150
+ cwd: import_path.default.resolve(options.cwd || process.cwd()),
151
+ detached: processGroup,
152
+ shell: false,
153
+ stdio: ["ignore", "pipe", "pipe"]
154
+ });
155
+ const settle = (result) => {
156
+ if (!settled) {
157
+ settled = true;
158
+ clearTimeout(timeout);
159
+ if (forceKillTimeout) {
160
+ clearTimeout(forceKillTimeout);
161
+ }
162
+ const sanitizedResult = {
163
+ ...result,
164
+ stdout: sanitizeCommandOutput(result.stdout, env),
165
+ stderr: sanitizeCommandOutput(result.stderr, env),
166
+ error: result.error ? sanitizeCommandOutput(result.error, env) : void 0
167
+ };
168
+ if (options.verbose) {
169
+ if (sanitizedResult.stdout) {
170
+ process.stdout.write(sanitizedResult.stdout);
171
+ }
172
+ if (sanitizedResult.stderr) {
173
+ process.stderr.write(sanitizedResult.stderr);
174
+ }
175
+ }
176
+ resolve(sanitizedResult);
177
+ }
178
+ };
179
+ child.stdout?.on("data", (data) => {
180
+ if (!settled) {
181
+ stdout = appendBoundedOutput(stdout, data.toString(), maxOutputLength);
182
+ }
183
+ });
184
+ child.stderr?.on("data", (data) => {
185
+ if (!settled) {
186
+ stderr = appendBoundedOutput(stderr, data.toString(), maxOutputLength);
187
+ }
188
+ });
189
+ child.once("error", (error) => {
190
+ settle({
191
+ success: false,
192
+ stdout,
193
+ stderr,
194
+ exitCode: null,
195
+ error: timedOut ? `Command timed out after ${timeoutMs}ms` : error.message
196
+ });
197
+ });
198
+ child.once("close", (exitCode) => {
199
+ settle({
200
+ success: !timedOut && exitCode === 0,
201
+ stdout,
202
+ stderr,
203
+ exitCode,
204
+ error: timedOut ? `Command timed out after ${timeoutMs}ms` : exitCode === 0 ? void 0 : stderr.trim() || stdout.trim() || `Command exited with code ${exitCode}`
205
+ });
206
+ });
207
+ const timeout = setTimeout(() => {
208
+ timedOut = true;
209
+ terminateChildProcess(child, { signal: "SIGTERM", processGroup });
210
+ forceKillTimeout = setTimeout(() => {
211
+ terminateChildProcess(child, { signal: "SIGKILL", processGroup });
212
+ settle({
213
+ success: false,
214
+ stdout,
215
+ stderr,
216
+ exitCode: null,
217
+ error: `Command timed out after ${timeoutMs}ms`
218
+ });
219
+ }, forceKillGraceMs);
220
+ forceKillTimeout.unref?.();
221
+ }, timeoutMs);
222
+ timeout.unref?.();
223
+ });
224
+ };
225
+ var runPrismaCommand = (args, options = {}) => runCommand(getNpxCommand(), ["prisma", ...args], options);
226
+ // Annotate the CommonJS export names for ESM import in node:
227
+ 0 && (module.exports = {
228
+ getNpxCommand,
229
+ runCommand,
230
+ runPrismaCommand,
231
+ sanitizeCommandOutput
232
+ });
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/cli/utils/postgres.ts
21
+ var postgres_exports = {};
22
+ __export(postgres_exports, {
23
+ parsePostgresUrl: () => parsePostgresUrl,
24
+ postgresEndpoint: () => postgresEndpoint
25
+ });
26
+ module.exports = __toCommonJS(postgres_exports);
27
+ var parsePostgresUrl = (url) => {
28
+ try {
29
+ const parsed = new URL(url);
30
+ if (parsed.protocol !== "postgresql:" && parsed.protocol !== "postgres:") {
31
+ return null;
32
+ }
33
+ const database = decodeURIComponent(parsed.pathname.replace(/^\/+/, ""));
34
+ const port = parsed.port ? Number(parsed.port) : 5432;
35
+ const queryHost = parsed.searchParams.get("host");
36
+ const host = parsed.hostname.replace(/^\[(.*)\]$/, "$1");
37
+ if (!database || !host || !Number.isInteger(port) || port <= 0 || port > 65535) {
38
+ return null;
39
+ }
40
+ return {
41
+ host,
42
+ port,
43
+ database,
44
+ socketPath: queryHost?.startsWith("/") ? queryHost : void 0
45
+ };
46
+ } catch {
47
+ return null;
48
+ }
49
+ };
50
+ var postgresEndpoint = (info) => info.socketPath || `${info.host}:${info.port}`;
51
+ // Annotate the CommonJS export names for ESM import in node:
52
+ 0 && (module.exports = {
53
+ parsePostgresUrl,
54
+ postgresEndpoint
55
+ });