@rebasepro/server-postgresql 0.6.1 → 0.8.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.
Files changed (55) hide show
  1. package/dist/PostgresBackendDriver.d.ts +8 -0
  2. package/dist/auth/services.d.ts +21 -1
  3. package/dist/cli-errors.d.ts +29 -0
  4. package/dist/cli-helpers.d.ts +7 -0
  5. package/dist/collections/PostgresCollectionRegistry.d.ts +2 -2
  6. package/dist/index.es.js +2987 -230
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/schema/auth-default-policies.d.ts +12 -0
  9. package/dist/schema/auth-schema.d.ts +227 -0
  10. package/dist/schema/generate-postgres-ddl-logic.d.ts +5 -0
  11. package/dist/schema/generate-postgres-ddl.d.ts +1 -0
  12. package/dist/services/entityService.d.ts +1 -1
  13. package/dist/utils/pg-error-utils.d.ts +10 -0
  14. package/dist/utils/table-classification.d.ts +8 -0
  15. package/package.json +15 -9
  16. package/src/PostgresBackendDriver.ts +200 -68
  17. package/src/PostgresBootstrapper.ts +34 -2
  18. package/src/auth/ensure-tables.ts +56 -1
  19. package/src/auth/services.ts +94 -1
  20. package/src/cli-errors.ts +162 -0
  21. package/src/cli-helpers.ts +183 -0
  22. package/src/cli.ts +264 -245
  23. package/src/collections/PostgresCollectionRegistry.ts +6 -6
  24. package/src/data-transformer.ts +2 -2
  25. package/src/schema/auth-default-policies.ts +97 -0
  26. package/src/schema/auth-schema.ts +25 -2
  27. package/src/schema/doctor.ts +2 -4
  28. package/src/schema/generate-drizzle-schema-logic.ts +20 -82
  29. package/src/schema/generate-drizzle-schema.ts +3 -5
  30. package/src/schema/generate-postgres-ddl-logic.ts +487 -0
  31. package/src/schema/generate-postgres-ddl.ts +116 -0
  32. package/src/services/EntityPersistService.ts +10 -8
  33. package/src/services/entityService.ts +28 -3
  34. package/src/services/realtimeService.ts +26 -2
  35. package/src/utils/pg-error-utils.ts +16 -0
  36. package/src/utils/table-classification.ts +16 -0
  37. package/src/websocket.ts +9 -0
  38. package/test/auth-default-policies.test.ts +89 -0
  39. package/test/cli-helpers-extended.test.ts +324 -0
  40. package/test/cli-helpers.test.ts +59 -0
  41. package/test/connection.test.ts +292 -0
  42. package/test/databasePoolManager.test.ts +289 -0
  43. package/test/doctor-extended.test.ts +443 -0
  44. package/test/e2e/db-e2e.test.ts +293 -0
  45. package/test/e2e/pg-setup.ts +79 -0
  46. package/test/entity-callbacks-redaction.test.ts +86 -0
  47. package/test/entity-persist-composite-keys.test.ts +451 -0
  48. package/test/generate-postgres-ddl-edge-cases.test.ts +716 -0
  49. package/test/generate-postgres-ddl.test.ts +300 -0
  50. package/test/mfa-service.test.ts +544 -0
  51. package/test/pg-error-utils.test.ts +50 -1
  52. package/test/postgresDataDriver.test.ts +2 -1
  53. package/test/realtimeService-channels.test.ts +696 -0
  54. package/test/unmapped-tables-safety.test.ts +55 -342
  55. package/vitest.e2e.config.ts +10 -0
@@ -19,6 +19,13 @@ export declare class PostgresBackendDriver implements DataDriver {
19
19
  user?: User;
20
20
  data: RebaseData;
21
21
  client?: RebaseClient;
22
+ /**
23
+ * Auto-set to `true` when a SET LOCAL ROLE fails with insufficient
24
+ * privileges, so subsequent queries skip the doomed attempt.
25
+ * Mirrors the static `DISABLE_DB_ROLE_SWITCHING` env var but is
26
+ * learned at runtime.
27
+ */
28
+ private _roleSwitchingDisabled;
22
29
  /**
23
30
  * When true, realtime notifications are deferred until after the
24
31
  * wrapping transaction commits. Set by `withAuth` → `withTransaction`.
@@ -58,6 +65,7 @@ export declare class PostgresBackendDriver implements DataDriver {
58
65
  executeSql(sqlText: string, options?: {
59
66
  database?: string;
60
67
  role?: string;
68
+ params?: unknown[];
61
69
  }): Promise<Record<string, unknown>[]>;
62
70
  fetchAvailableDatabases(): Promise<string[]>;
63
71
  fetchAvailableRoles(): Promise<string[]>;
@@ -1,6 +1,6 @@
1
1
  import { NodePgDatabase } from "drizzle-orm/node-postgres";
2
2
  import type { RebasePgTable } from "../types";
3
- import { UserRepository, TokenRepository, MfaRepository, AuthRepository, UserData, CreateUserData, RoleData, CreateRoleData, RefreshTokenInfo, PasswordResetTokenInfo, UserIdentityData, ListUsersOptions, PaginatedUsersResult, MfaFactor, MfaChallengeInfo, RoleData as Role } from "@rebasepro/server-core";
3
+ import { UserRepository, TokenRepository, MfaRepository, AuthRepository, UserData, CreateUserData, RoleData, CreateRoleData, RefreshTokenInfo, PasswordResetTokenInfo, MagicLinkTokenInfo, UserIdentityData, ListUsersOptions, PaginatedUsersResult, MfaFactor, MfaChallengeInfo, RoleData as Role } from "@rebasepro/server-core";
4
4
  export type { Role };
5
5
  export interface AuthSchemaTables {
6
6
  users: RebasePgTable;
@@ -115,6 +115,19 @@ export declare class PasswordResetTokenService {
115
115
  */
116
116
  deleteExpired(): Promise<void>;
117
117
  }
118
+ /**
119
+ * Magic link token service.
120
+ * Handles magic link token storage for passwordless email login.
121
+ */
122
+ export declare class MagicLinkTokenService {
123
+ private db;
124
+ private magicLinkTokensTable;
125
+ constructor(db: NodePgDatabase, tableOrTables?: RebasePgTable | Partial<AuthSchemaTables>);
126
+ private getQualifiedTableName;
127
+ createToken(userId: string, tokenHash: string, expiresAt: Date): Promise<void>;
128
+ findValidByHash(tokenHash: string): Promise<MagicLinkTokenInfo | null>;
129
+ markAsUsed(tokenHash: string): Promise<void>;
130
+ }
118
131
  /**
119
132
  * PostgreSQL implementation of TokenRepository.
120
133
  * Combines refresh token and password reset token operations.
@@ -123,6 +136,7 @@ export declare class PostgresTokenRepository implements TokenRepository {
123
136
  private db;
124
137
  private refreshTokenService;
125
138
  private passwordResetTokenService;
139
+ private magicLinkTokenService;
126
140
  constructor(db: NodePgDatabase, tableOrTables?: RebasePgTable | Partial<AuthSchemaTables>);
127
141
  createRefreshToken(userId: string, tokenHash: string, expiresAt: Date, userAgent?: string, ipAddress?: string): Promise<void>;
128
142
  findRefreshTokenByHash(tokenHash: string): Promise<RefreshTokenInfo | null>;
@@ -135,6 +149,9 @@ export declare class PostgresTokenRepository implements TokenRepository {
135
149
  markPasswordResetTokenUsed(tokenHash: string): Promise<void>;
136
150
  deleteAllPasswordResetTokensForUser(userId: string): Promise<void>;
137
151
  deleteExpiredTokens(): Promise<void>;
152
+ createMagicLinkToken(userId: string, tokenHash: string, expiresAt: Date): Promise<void>;
153
+ findValidMagicLinkToken(tokenHash: string): Promise<MagicLinkTokenInfo | null>;
154
+ markMagicLinkTokenUsed(tokenHash: string): Promise<void>;
138
155
  }
139
156
  /**
140
157
  * PostgreSQL implementation of AuthRepository.
@@ -184,6 +201,9 @@ export declare class PostgresAuthRepository implements AuthRepository {
184
201
  markPasswordResetTokenUsed(tokenHash: string): Promise<void>;
185
202
  deleteAllPasswordResetTokensForUser(userId: string): Promise<void>;
186
203
  deleteExpiredTokens(): Promise<void>;
204
+ createMagicLinkToken(userId: string, tokenHash: string, expiresAt: Date): Promise<void>;
205
+ findValidMagicLinkToken(tokenHash: string): Promise<MagicLinkTokenInfo | null>;
206
+ markMagicLinkTokenUsed(tokenHash: string): Promise<void>;
187
207
  private _mfaService;
188
208
  private getMfaService;
189
209
  createMfaFactor(userId: string, factorType: "totp", secretEncrypted: string, friendlyName?: string): Promise<MfaFactor>;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Detect whether an error (or AggregateError wrapping multiple attempts)
3
+ * represents an ECONNREFUSED — i.e. the database is simply not running.
4
+ *
5
+ * Handles:
6
+ * - Direct `{ code: "ECONNREFUSED" }` errors from Node `net`
7
+ * - `AggregateError` from dual-stack IPv4+IPv6 connection attempts
8
+ * - Drizzle's `cause`-wrapped pg errors
9
+ */
10
+ export declare function isEconnrefused(err: unknown): boolean;
11
+ /**
12
+ * Detect PostgreSQL authentication failures.
13
+ * PG error codes: 28P01 (invalid_password), 28000 (invalid_authorization_specification)
14
+ */
15
+ export declare function isAuthFailure(err: unknown): boolean;
16
+ /**
17
+ * Pre-flight check: verify that the database is reachable before running
18
+ * a heavy subprocess (Atlas, migrations, etc.).
19
+ *
20
+ * Exits with code 1 and a friendly banner on known failure modes.
21
+ * On unknown errors, logs a warning and allows the caller to proceed.
22
+ */
23
+ export declare function checkDatabaseConnectivity(databaseUrl: string): Promise<void>;
24
+ /**
25
+ * Post-hoc error diagnosis for direct database operations (e.g. applyPolicies).
26
+ * Returns a formatted diagnostic string if the error matches a known pattern,
27
+ * or null if unrecognized.
28
+ */
29
+ export declare function diagnoseDbError(err: unknown, databaseUrl?: string): string | null;
@@ -0,0 +1,7 @@
1
+ import type { EntityCollection } from "@rebasepro/types";
2
+ export declare function resolveLocalBin(binName: string): string | null;
3
+ export declare function getTableIncludesFromCollections(collections: EntityCollection[]): Promise<string[]>;
4
+ export declare function getTableIncludes(collectionsPath: string): Promise<string[]>;
5
+ export declare function getDevDatabaseUrl(databaseUrl: string): string;
6
+ export declare function ensureDevDatabaseExists(databaseUrl: string, devDatabaseUrl: string): Promise<void>;
7
+ export declare function getTableExcludes(databaseUrl: string, collectionsPath: string): Promise<string[]>;
@@ -24,9 +24,9 @@ export declare class PostgresCollectionRegistry extends CollectionRegistry imple
24
24
  */
25
25
  getTableNames(): string[];
26
26
  /**
27
- * Finds collections assigned to a specific driver that do not have a registered table.
27
+ * Finds collections assigned to a specific data source that do not have a registered table.
28
28
  */
29
- getCollectionsWithoutTables(driverId?: string): EntityCollection[];
29
+ getCollectionsWithoutTables(dataSourceKey?: string): EntityCollection[];
30
30
  registerEnums(enums: Record<string, PgEnum<[string, ...string[]]>>): void;
31
31
  registerRelations(relations: Record<string, Relations>): void;
32
32
  getEnum(name: string): PgEnum<[string, ...string[]]> | undefined;