@rebasepro/server-postgres 0.9.1-canary.c0d4c07 → 0.9.1-canary.d906fb7

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.
@@ -19,22 +19,6 @@ export declare class UserService implements UserRepository {
19
19
  private userIdentitiesTable;
20
20
  constructor(db: NodePgDatabase, tableOrTables?: RebasePgTable | Partial<AuthSchemaTables>);
21
21
  private getQualifiedUsersTableName;
22
- /**
23
- * Run a privileged auth write with an explicitly cleared RLS context.
24
- *
25
- * The auth services run on the base/owner connection, which by design
26
- * carries a NULL `app.user_id` so the `auth.uid() IS NULL` server-escape
27
- * in the default policies applies. That NULL is normally guaranteed by
28
- * `set_config(..., is_local = true)` resetting at transaction end — but a
29
- * GUC that survives on a pooled connection (or a connection role that
30
- * doesn't bypass RLS: FORCE ROW LEVEL SECURITY, or a non-owner role)
31
- * turns the trusted write into an RLS-scoped one and denies it with
32
- * SQLSTATE 42501. Clearing the GUCs here, transaction-locally at the
33
- * single chokepoint, makes the server context deterministic instead of
34
- * trusting whatever state the pool hands us. `auth.uid()` reads '' as
35
- * NULL via NULLIF, so '' is the server context.
36
- */
37
- private withServerContext;
38
22
  private mapRowToUser;
39
23
  private mapPayload;
40
24
  createUser(data: CreateUserData): Promise<UserData>;
@@ -19,27 +19,6 @@ export interface PostgresPoolConfig {
19
19
  /** Enable TCP keep-alive (default: true) */
20
20
  keepAlive?: boolean;
21
21
  }
22
- /**
23
- * Destroy pool clients that are released while still inside a transaction.
24
- *
25
- * pg-pool returns a client to the idle list whenever `release()` is called
26
- * without an error — even if the connection is still mid-transaction (status
27
- * `T`/`E`). That happens in practice: drizzle's pool transaction releases in
28
- * a `finally` after attempting ROLLBACK, and if the ROLLBACK itself fails
29
- * (e.g. it was queued behind a statement that hit the client-side
30
- * query_timeout), the client goes back dirty. The next checkout then runs
31
- * its statements inside the zombie transaction — with the previous request's
32
- * `app.*` RLS GUCs still applied, which turns unrelated queries into
33
- * RLS-scoped ones (observed in production as registration failing with
34
- * SQLSTATE 42501 under a leaked anonymous context).
35
- *
36
- * pg-pool emits `release` before it consults its private `_expired` set, so
37
- * marking the client expired here makes `_release()` destroy it instead of
38
- * pooling it. Both `client._txStatus` (pg ≥ 8.16) and `pool._expired` are
39
- * private APIs — feature-detect and fall back to loud logging so an upstream
40
- * change degrades to observability, never to silent corruption.
41
- */
42
- export declare function guardPoolAgainstDirtyRelease(pool: Pool, label: string): void;
43
22
  /**
44
23
  * Create a Drizzle-backed Postgres connection with a production-grade
45
24
  * connection pool.
package/dist/index.es.js CHANGED
@@ -71,51 +71,16 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
71
71
  var connection_exports = /* @__PURE__ */ __exportAll({
72
72
  createDirectDatabaseConnection: () => createDirectDatabaseConnection,
73
73
  createPostgresDatabaseConnection: () => createPostgresDatabaseConnection,
74
- createReadReplicaConnection: () => createReadReplicaConnection,
75
- guardPoolAgainstDirtyRelease: () => guardPoolAgainstDirtyRelease
74
+ createReadReplicaConnection: () => createReadReplicaConnection
76
75
  });
77
76
  var DEFAULT_POOL = {
78
77
  max: 20,
79
78
  idleTimeoutMillis: 3e4,
80
79
  connectionTimeoutMillis: 1e4,
81
- queryTimeout: 6e4,
80
+ queryTimeout: 3e4,
82
81
  statementTimeout: 3e4,
83
82
  keepAlive: true
84
83
  };
85
- /** ReadyForQuery status byte: `I` idle, `T` in transaction, `E` failed transaction. */
86
- var TX_IDLE = "I";
87
- /**
88
- * Destroy pool clients that are released while still inside a transaction.
89
- *
90
- * pg-pool returns a client to the idle list whenever `release()` is called
91
- * without an error — even if the connection is still mid-transaction (status
92
- * `T`/`E`). That happens in practice: drizzle's pool transaction releases in
93
- * a `finally` after attempting ROLLBACK, and if the ROLLBACK itself fails
94
- * (e.g. it was queued behind a statement that hit the client-side
95
- * query_timeout), the client goes back dirty. The next checkout then runs
96
- * its statements inside the zombie transaction — with the previous request's
97
- * `app.*` RLS GUCs still applied, which turns unrelated queries into
98
- * RLS-scoped ones (observed in production as registration failing with
99
- * SQLSTATE 42501 under a leaked anonymous context).
100
- *
101
- * pg-pool emits `release` before it consults its private `_expired` set, so
102
- * marking the client expired here makes `_release()` destroy it instead of
103
- * pooling it. Both `client._txStatus` (pg ≥ 8.16) and `pool._expired` are
104
- * private APIs — feature-detect and fall back to loud logging so an upstream
105
- * change degrades to observability, never to silent corruption.
106
- */
107
- function guardPoolAgainstDirtyRelease(pool, label) {
108
- pool.on("release", (err, client) => {
109
- if (err) return;
110
- const txStatus = client?._txStatus;
111
- if (typeof txStatus !== "string" || txStatus === TX_IDLE) return;
112
- const expired = pool._expired;
113
- if (expired && typeof expired.add === "function" && typeof expired.has === "function" && client && typeof client === "object") {
114
- expired.add(client);
115
- logger.error(`[${label}] Client released back to the pool while still in a transaction (status '${txStatus}') — destroying it so the open transaction and its session state (RLS GUCs) cannot leak into the next request.`);
116
- } else logger.error(`[${label}] Client released mid-transaction (status '${txStatus}') but the pool's internal expiry set is unavailable (pg-pool internals changed?). The connection may leak its open transaction into subsequent requests.`);
117
- });
118
- }
119
84
  /**
120
85
  * Create a Drizzle-backed Postgres connection with a production-grade
121
86
  * connection pool.
@@ -147,7 +112,6 @@ function createPostgresDatabaseConnection(connectionString, schema, poolConfig)
147
112
  logger.error("[pg-pool] Unexpected pool error", { detail: err.message });
148
113
  if (err.message.includes("ETIMEDOUT")) logger.warn("[pg-pool] Connection timeout detected — pool will auto-retry");
149
114
  });
150
- guardPoolAgainstDirtyRelease(pool, "pg-pool");
151
115
  return {
152
116
  db: schema ? drizzle(pool, { schema }) : drizzle(pool),
153
117
  pool,
@@ -180,7 +144,6 @@ function createDirectDatabaseConnection(connectionString, schema, poolConfig) {
180
144
  pool.on("error", (err) => {
181
145
  logger.error("[pg-direct-pool] Unexpected pool error", { detail: err.message });
182
146
  });
183
- guardPoolAgainstDirtyRelease(pool, "pg-direct-pool");
184
147
  return {
185
148
  db: schema ? drizzle(pool, { schema }) : drizzle(pool),
186
149
  pool,
@@ -210,7 +173,6 @@ function createReadReplicaConnection(connectionString, schema, poolConfig) {
210
173
  pool.on("error", (err) => {
211
174
  logger.error("[pg-replica-pool] Unexpected pool error", { detail: err.message });
212
175
  });
213
- guardPoolAgainstDirtyRelease(pool, "pg-replica-pool");
214
176
  return {
215
177
  db: schema ? drizzle(pool, { schema }) : drizzle(pool),
216
178
  pool,
@@ -6524,27 +6486,8 @@ function coerceDeclaredNumbers(row, collection) {
6524
6486
  return out;
6525
6487
  }
6526
6488
  /** Render one target row in the requested style. */
6527
- /**
6528
- * Drop every column the collection marked `excludeFromApi`.
6529
- *
6530
- * Password hashes and verification tokens have to be readable server-side but
6531
- * must never reach a client — and "never" has to mean every exit from this
6532
- * pipeline, including relation targets, or a secret leaks through whichever
6533
- * path was overlooked. Keyed by both the property name and its column name,
6534
- * since a row can arrive keyed either way depending on the caller.
6535
- */
6536
- function stripExcluded(row, collection) {
6537
- const properties = collection.properties;
6538
- if (!properties) return row;
6539
- for (const [key, property] of Object.entries(properties)) {
6540
- if (!property?.excludeFromApi) continue;
6541
- delete row[key];
6542
- if (property.columnName) delete row[property.columnName];
6543
- }
6544
- return row;
6545
- }
6546
6489
  function renderTarget(targetRow, targetCollection, style, registry) {
6547
- if (style === "inline") return stripExcluded(coerceDeclaredNumbers({ ...targetRow }, targetCollection), targetCollection);
6490
+ if (style === "inline") return coerceDeclaredNumbers({ ...targetRow }, targetCollection);
6548
6491
  const address = relationTargetAddress(targetRow, targetCollection, registry);
6549
6492
  const path = targetCollection.slug;
6550
6493
  return createRelationRefWithData(address, path, {
@@ -6586,7 +6529,7 @@ function toCmsRow(row, collection, registry) {
6586
6529
  normalized[key] = relData.map((item) => renderTarget(isJunctionRelation(relation) ? unwrapJunctionRow(item) : item, targetCollection, "ref", registry));
6587
6530
  } else if (relation.cardinality === "one" && typeof relData === "object" && !Array.isArray(relData)) normalized[key] = renderTarget(relData, relation.target(), "ref", registry);
6588
6531
  }
6589
- return stripExcluded(normalized, collection);
6532
+ return normalized;
6590
6533
  }
6591
6534
  /**
6592
6535
  * The row REST serves: every column under its own name, with the value Postgres
@@ -6611,7 +6554,7 @@ function toRestRow(row, collection, registry) {
6611
6554
  else if (relation && typeof value === "object" && value !== null) flat[key] = renderTarget(value, relation.target(), "inline", registry);
6612
6555
  else flat[key] = coerceDeclaredNumber(value, collection.properties?.[key]);
6613
6556
  }
6614
- return stripExcluded(flat, collection);
6557
+ return flat;
6615
6558
  }
6616
6559
  //#endregion
6617
6560
  //#region src/services/FetchService.ts
@@ -9253,7 +9196,6 @@ var DatabasePoolManager = class {
9253
9196
  pool.on("error", (err) => {
9254
9197
  logger.error(`[DatabasePoolManager] Unexpected error on idle client for db ${databaseName}`, { error: err });
9255
9198
  });
9256
- guardPoolAgainstDirtyRelease(pool, `pg-pool:${databaseName}`);
9257
9199
  this.pools.set(databaseName, pool);
9258
9200
  return pool;
9259
9201
  }
@@ -20814,22 +20756,14 @@ async function ensureAuthTablesExist(db, collection) {
20814
20756
  $$ LANGUAGE sql STABLE
20815
20757
  `);
20816
20758
  });
20817
- for (const columnDef of [
20818
- "display_name VARCHAR(255)",
20819
- "photo_url VARCHAR(500)",
20820
- "roles TEXT[] DEFAULT '{}' NOT NULL",
20821
- "password_hash VARCHAR(255)",
20822
- "email_verified BOOLEAN DEFAULT FALSE NOT NULL",
20823
- "email_verification_token VARCHAR(255)",
20824
- "email_verification_sent_at TIMESTAMP WITH TIME ZONE",
20825
- "is_anonymous BOOLEAN DEFAULT FALSE NOT NULL",
20826
- "metadata JSONB DEFAULT '{}' NOT NULL",
20827
- "created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL",
20828
- "updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL"
20829
- ]) await db.execute(sql`
20830
- ALTER TABLE ${sql.raw(usersTableName)}
20831
- ADD COLUMN IF NOT EXISTS ${sql.raw(columnDef)}
20832
- `);
20759
+ await db.execute(sql`
20760
+ ALTER TABLE ${sql.raw(usersTableName)}
20761
+ ADD COLUMN IF NOT EXISTS is_anonymous BOOLEAN DEFAULT FALSE
20762
+ `);
20763
+ await db.execute(sql`
20764
+ ALTER TABLE ${sql.raw(usersTableName)}
20765
+ ADD COLUMN IF NOT EXISTS roles TEXT[] DEFAULT '{}' NOT NULL
20766
+ `);
20833
20767
  try {
20834
20768
  if ((await db.execute(sql`
20835
20769
  SELECT EXISTS (
@@ -20900,34 +20834,6 @@ async function ensureAuthTablesExist(db, collection) {
20900
20834
  CREATE INDEX IF NOT EXISTS idx_recovery_codes_user
20901
20835
  ON ${sql.raw(recoveryCodesTableName)}(user_id)
20902
20836
  `);
20903
- try {
20904
- const authTablePairs = [
20905
- [usersSchema, resolvedTable],
20906
- [authSchema, "user_identities"],
20907
- [authSchema, "refresh_tokens"],
20908
- [authSchema, "password_reset_tokens"],
20909
- [authSchema, "app_config"],
20910
- [authSchema, "mfa_factors"],
20911
- [authSchema, "mfa_challenges"],
20912
- [authSchema, "recovery_codes"]
20913
- ];
20914
- for (const [schemaName, tableName] of authTablePairs) if ((await db.execute(sql`
20915
- SELECT 1
20916
- FROM pg_class c
20917
- JOIN pg_namespace n ON n.oid = c.relnamespace
20918
- WHERE n.nspname = ${schemaName}
20919
- AND c.relname = ${tableName}
20920
- AND c.relforcerowsecurity
20921
- `)).rows.length > 0) {
20922
- await db.execute(sql`
20923
- ALTER TABLE ${sql.raw(`"${schemaName}"."${tableName}"`)}
20924
- NO FORCE ROW LEVEL SECURITY
20925
- `);
20926
- logger.warn(`🔧 Cleared stale FORCE ROW LEVEL SECURITY on "${schemaName}"."${tableName}" (legacy RLS model — it binds the owner connection and breaks privileged auth writes)`);
20927
- }
20928
- } catch (rlsReconcileError) {
20929
- logger.warn(`⚠️ Could not reconcile FORCE ROW LEVEL SECURITY on auth tables: ${rlsReconcileError instanceof Error ? rlsReconcileError.message : String(rlsReconcileError)}`);
20930
- }
20931
20837
  logger.info("✅ Auth tables ready");
20932
20838
  } catch (error) {
20933
20839
  logger.error("❌ Failed to create auth tables", { error });
@@ -20975,31 +20881,6 @@ var UserService = class {
20975
20881
  const name = getTableName(this.usersTable);
20976
20882
  return `"${getTableConfig(this.usersTable).schema || "public"}"."${name}"`;
20977
20883
  }
20978
- /**
20979
- * Run a privileged auth write with an explicitly cleared RLS context.
20980
- *
20981
- * The auth services run on the base/owner connection, which by design
20982
- * carries a NULL `app.user_id` so the `auth.uid() IS NULL` server-escape
20983
- * in the default policies applies. That NULL is normally guaranteed by
20984
- * `set_config(..., is_local = true)` resetting at transaction end — but a
20985
- * GUC that survives on a pooled connection (or a connection role that
20986
- * doesn't bypass RLS: FORCE ROW LEVEL SECURITY, or a non-owner role)
20987
- * turns the trusted write into an RLS-scoped one and denies it with
20988
- * SQLSTATE 42501. Clearing the GUCs here, transaction-locally at the
20989
- * single chokepoint, makes the server context deterministic instead of
20990
- * trusting whatever state the pool hands us. `auth.uid()` reads '' as
20991
- * NULL via NULLIF, so '' is the server context.
20992
- */
20993
- async withServerContext(fn) {
20994
- return await this.db.transaction(async (tx) => {
20995
- await tx.execute(sql`
20996
- SELECT set_config('app.user_id', '', true),
20997
- set_config('app.user_roles', '', true),
20998
- set_config('app.jwt', '', true)
20999
- `);
21000
- return await fn(tx);
21001
- });
21002
- }
21003
20884
  mapRowToUser(row) {
21004
20885
  if (!row) return row;
21005
20886
  const id = row.id ?? row.uid;
@@ -21097,7 +20978,7 @@ var UserService = class {
21097
20978
  }
21098
20979
  async createUser(data) {
21099
20980
  const payload = this.mapPayload(data);
21100
- const [row] = await this.withServerContext(async (db) => await db.insert(this.usersTable).values(payload).returning());
20981
+ const [row] = await this.db.insert(this.usersTable).values(payload).returning();
21101
20982
  return this.mapRowToUser(row);
21102
20983
  }
21103
20984
  async getUserById(id) {
@@ -21136,12 +21017,12 @@ var UserService = class {
21136
21017
  }));
21137
21018
  }
21138
21019
  async linkUserIdentity(userId, provider, providerId, profileData) {
21139
- await this.withServerContext(async (db) => db.insert(this.userIdentitiesTable).values({
21020
+ await this.db.insert(this.userIdentitiesTable).values({
21140
21021
  userId,
21141
21022
  provider,
21142
21023
  providerId,
21143
21024
  profileData: profileData || null
21144
- }).onConflictDoNothing({ target: [this.userIdentitiesTable.provider, this.userIdentitiesTable.providerId] }));
21025
+ }).onConflictDoNothing({ target: [this.userIdentitiesTable.provider, this.userIdentitiesTable.providerId] });
21145
21026
  }
21146
21027
  async updateUser(id, data) {
21147
21028
  const idCol = getColumn(this.usersTable, "id");
@@ -21149,13 +21030,13 @@ var UserService = class {
21149
21030
  const payload = this.mapPayload(data);
21150
21031
  const updatedAtKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
21151
21032
  payload[updatedAtKey] = /* @__PURE__ */ new Date();
21152
- const [row] = await this.withServerContext(async (db) => await db.update(this.usersTable).set(payload).where(eq(idCol, id)).returning());
21033
+ const [row] = await this.db.update(this.usersTable).set(payload).where(eq(idCol, id)).returning();
21153
21034
  return row ? this.mapRowToUser(row) : null;
21154
21035
  }
21155
21036
  async deleteUser(id) {
21156
21037
  const idCol = getColumn(this.usersTable, "id");
21157
21038
  if (!idCol) return;
21158
- await this.withServerContext(async (db) => db.delete(this.usersTable).where(eq(idCol, id)));
21039
+ await this.db.delete(this.usersTable).where(eq(idCol, id));
21159
21040
  }
21160
21041
  async listUsers() {
21161
21042
  return (await this.db.select().from(this.usersTable)).map((row) => this.mapRowToUser(row));
@@ -21209,10 +21090,10 @@ var UserService = class {
21209
21090
  if (!idCol) return;
21210
21091
  const passwordHashColKey = getColumnKey(this.usersTable, "passwordHash", "password_hash") || "passwordHash";
21211
21092
  const updatedAtColKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
21212
- await this.withServerContext(async (db) => db.update(this.usersTable).set({
21093
+ await this.db.update(this.usersTable).set({
21213
21094
  [passwordHashColKey]: passwordHash,
21214
21095
  [updatedAtColKey]: /* @__PURE__ */ new Date()
21215
- }).where(eq(idCol, id)));
21096
+ }).where(eq(idCol, id));
21216
21097
  }
21217
21098
  /**
21218
21099
  * Set email verification status
@@ -21223,11 +21104,11 @@ var UserService = class {
21223
21104
  const emailVerifiedColKey = getColumnKey(this.usersTable, "emailVerified", "email_verified") || "emailVerified";
21224
21105
  const emailVerificationTokenColKey = getColumnKey(this.usersTable, "emailVerificationToken", "email_verification_token") || "emailVerificationToken";
21225
21106
  const updatedAtColKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
21226
- await this.withServerContext(async (db) => db.update(this.usersTable).set({
21107
+ await this.db.update(this.usersTable).set({
21227
21108
  [emailVerifiedColKey]: verified,
21228
21109
  [emailVerificationTokenColKey]: null,
21229
21110
  [updatedAtColKey]: /* @__PURE__ */ new Date()
21230
- }).where(eq(idCol, id)));
21111
+ }).where(eq(idCol, id));
21231
21112
  }
21232
21113
  /**
21233
21114
  * Set email verification token
@@ -21238,11 +21119,11 @@ var UserService = class {
21238
21119
  const emailVerificationTokenColKey = getColumnKey(this.usersTable, "emailVerificationToken", "email_verification_token") || "emailVerificationToken";
21239
21120
  const emailVerificationSentAtColKey = getColumnKey(this.usersTable, "emailVerificationSentAt", "email_verification_sent_at") || "emailVerificationSentAt";
21240
21121
  const updatedAtColKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
21241
- await this.withServerContext(async (db) => db.update(this.usersTable).set({
21122
+ await this.db.update(this.usersTable).set({
21242
21123
  [emailVerificationTokenColKey]: token,
21243
21124
  [emailVerificationSentAtColKey]: token ? /* @__PURE__ */ new Date() : null,
21244
21125
  [updatedAtColKey]: /* @__PURE__ */ new Date()
21245
- }).where(eq(idCol, id)));
21126
+ }).where(eq(idCol, id));
21246
21127
  }
21247
21128
  /**
21248
21129
  * Find user by email verification token
@@ -21287,22 +21168,22 @@ var UserService = class {
21287
21168
  async setUserRoles(userId, roleIds) {
21288
21169
  const usersTableName = this.getQualifiedUsersTableName();
21289
21170
  const rolesArray = `{${roleIds.join(",")}}`;
21290
- await this.withServerContext(async (db) => db.execute(sql`
21171
+ await this.db.execute(sql`
21291
21172
  UPDATE ${sql.raw(usersTableName)}
21292
21173
  SET roles = ${rolesArray}::text[], updated_at = NOW()
21293
21174
  WHERE id = ${userId}
21294
- `));
21175
+ `);
21295
21176
  }
21296
21177
  /**
21297
21178
  * Assign a specific role to new user (appends if not present)
21298
21179
  */
21299
21180
  async assignDefaultRole(userId, roleId) {
21300
21181
  const usersTableName = this.getQualifiedUsersTableName();
21301
- await this.withServerContext(async (db) => db.execute(sql`
21182
+ await this.db.execute(sql`
21302
21183
  UPDATE ${sql.raw(usersTableName)}
21303
21184
  SET roles = array_append(roles, ${roleId}), updated_at = NOW()
21304
21185
  WHERE id = ${userId} AND NOT (${roleId} = ANY(roles))
21305
- `));
21186
+ `);
21306
21187
  }
21307
21188
  /**
21308
21189
  * Get user with their roles
@@ -22952,6 +22833,6 @@ function createPostgresAdapter(pgConfig) {
22952
22833
  };
22953
22834
  }
22954
22835
  //#endregion
22955
- export { AuthenticatedPostgresBackendDriver, BackupToolError, BranchService, DatabasePoolManager, DrizzleConditionBuilder, PostgresBackendDriver, PostgresCollectionRegistry, PostgresConditionBuilder, PostgresRealtimeProvider, RealtimeService, appConfig, backupCronConfigFromEnv, buildBackupFilename, buildPgDumpArgs, buildPgRestoreArgs, checkToolServerCompatibility, createAuthSchema, createBackupCron, createDirectDatabaseConnection, createDump, createPostgresAdapter, createPostgresBootstrapper, createPostgresDatabaseConnection, createPostgresWebSocket, createReadReplicaConnection, detectToolMajor, ensureDatabaseExists, generateSchema, getServerVersionMajor, guardPoolAgainstDirtyRelease, joinStorageKey, listBackups, magicLinkTokens, magicLinkTokensRelations, mfaChallenges, mfaChallengesRelations, mfaFactors, mfaFactorsRelations, parseBackupDestination, parseBackupTimestamp, parseDbNameFromUrl, parsePgToolMajor, passwordResetTokens, passwordResetTokensRelations, preflight, pruneBackups, recoveryCodes, recoveryCodesRelations, refreshTokens, refreshTokensRelations, resolveConnectionString, resolvePgBinary, restoreDump, selectBackupsToPrune, serverVersionNumToMajor, uploadBackup, userIdentities, userIdentitiesRelations, users, usersRelations, usersSchema, withDatabaseName };
22836
+ export { AuthenticatedPostgresBackendDriver, BackupToolError, BranchService, DatabasePoolManager, DrizzleConditionBuilder, PostgresBackendDriver, PostgresCollectionRegistry, PostgresConditionBuilder, PostgresRealtimeProvider, RealtimeService, appConfig, backupCronConfigFromEnv, buildBackupFilename, buildPgDumpArgs, buildPgRestoreArgs, checkToolServerCompatibility, createAuthSchema, createBackupCron, createDirectDatabaseConnection, createDump, createPostgresAdapter, createPostgresBootstrapper, createPostgresDatabaseConnection, createPostgresWebSocket, createReadReplicaConnection, detectToolMajor, ensureDatabaseExists, generateSchema, getServerVersionMajor, joinStorageKey, listBackups, magicLinkTokens, magicLinkTokensRelations, mfaChallenges, mfaChallengesRelations, mfaFactors, mfaFactorsRelations, parseBackupDestination, parseBackupTimestamp, parseDbNameFromUrl, parsePgToolMajor, passwordResetTokens, passwordResetTokensRelations, preflight, pruneBackups, recoveryCodes, recoveryCodesRelations, refreshTokens, refreshTokensRelations, resolveConnectionString, resolvePgBinary, restoreDump, selectBackupsToPrune, serverVersionNumToMajor, uploadBackup, userIdentities, userIdentitiesRelations, users, usersRelations, usersSchema, withDatabaseName };
22956
22837
 
22957
22838
  //# sourceMappingURL=index.es.js.map