@rebasepro/server-postgres 0.17.3-canary.gdd23447 → 0.18.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 (149) hide show
  1. package/LICENSE +0 -1
  2. package/README.md +31 -0
  3. package/dist/backup-argv.d.ts +19 -0
  4. package/dist/branch-argv.d.ts +28 -0
  5. package/dist/branch-prune.d.ts +77 -0
  6. package/dist/cli-collections-path.d.ts +31 -0
  7. package/dist/cli-errors.d.ts +123 -0
  8. package/dist/cli-flags.d.ts +101 -0
  9. package/dist/cli-helpers.d.ts +94 -10
  10. package/dist/collection-index-C7LopMyX.js +247 -0
  11. package/dist/collection-index-C7LopMyX.js.map +1 -0
  12. package/dist/databasePoolManager.d.ts +27 -0
  13. package/dist/{ensure-collection-policies-UCqgv_8c.js → ensure-collection-policies-CagOzEPS.js} +6 -6
  14. package/dist/{ensure-collection-policies-UCqgv_8c.js.map → ensure-collection-policies-CagOzEPS.js.map} +1 -1
  15. package/dist/{ensure-collection-tables-DgVixhX3.js → ensure-collection-tables-DbAhrjnG.js} +614 -52
  16. package/dist/ensure-collection-tables-DbAhrjnG.js.map +1 -0
  17. package/dist/index.d.ts +12 -0
  18. package/dist/index.es.js +19307 -3059
  19. package/dist/index.es.js.map +1 -1
  20. package/dist/{rls-enforcement-DvAbL9YJ.js → rls-enforcement-ClJoTboT.js} +53 -189
  21. package/dist/rls-enforcement-ClJoTboT.js.map +1 -0
  22. package/dist/schema/column-type-drift.d.ts +79 -0
  23. package/dist/schema/doctor.d.ts +42 -0
  24. package/dist/schema/ensure-collection-tables.d.ts +90 -0
  25. package/dist/schema/generate-next-step.d.ts +30 -0
  26. package/dist/schema/generate-postgres-ddl-logic.d.ts +28 -0
  27. package/dist/schema/generated-schema-staleness.d.ts +37 -0
  28. package/dist/schema/introspect-db-queries.d.ts +34 -0
  29. package/dist/security/rls-enforcement.d.ts +63 -2
  30. package/dist/services/BranchService.d.ts +86 -1
  31. package/dist/services/collection-helpers.d.ts +1 -1
  32. package/dist/services/realtimeService.d.ts +30 -2
  33. package/dist/services/row-pipeline.d.ts +12 -1
  34. package/dist/utils/pg-error-utils.d.ts +3 -1
  35. package/dist/utils/pg-numeric-number-patch.d.ts +31 -0
  36. package/package.json +32 -27
  37. package/dist/backup-service-DCk7KhhL.js +0 -9044
  38. package/dist/backup-service-DCk7KhhL.js.map +0 -1
  39. package/dist/collection-index-BRUg10H5.js +0 -5690
  40. package/dist/collection-index-BRUg10H5.js.map +0 -1
  41. package/dist/connection-GOKU3Hu5.js +0 -277
  42. package/dist/connection-GOKU3Hu5.js.map +0 -1
  43. package/dist/ensure-collection-tables-DgVixhX3.js.map +0 -1
  44. package/dist/rls-bootstrap-sql-B5C9LoJ6.js +0 -244
  45. package/dist/rls-bootstrap-sql-B5C9LoJ6.js.map +0 -1
  46. package/dist/rls-enforcement-DvAbL9YJ.js.map +0 -1
  47. package/dist/src-DiB5RP2Z.js +0 -541
  48. package/dist/src-DiB5RP2Z.js.map +0 -1
  49. package/dist/websocket-BZ4H5wUz.js +0 -8198
  50. package/dist/websocket-BZ4H5wUz.js.map +0 -1
  51. package/src/PostgresAdapter.ts +0 -91
  52. package/src/PostgresBackendDriver.ts +0 -1857
  53. package/src/PostgresBootstrapper.ts +0 -1157
  54. package/src/auth/ensure-tables.ts +0 -896
  55. package/src/auth/schema-version.ts +0 -260
  56. package/src/auth/services.ts +0 -1610
  57. package/src/backup/backup-cli.ts +0 -520
  58. package/src/backup/backup-cron.ts +0 -212
  59. package/src/backup/backup-logic.ts +0 -93
  60. package/src/backup/backup-service.ts +0 -485
  61. package/src/backup/index.ts +0 -12
  62. package/src/backup/pg-tools.ts +0 -403
  63. package/src/backup/retention.ts +0 -86
  64. package/src/cli-errors.ts +0 -265
  65. package/src/cli-helpers.ts +0 -569
  66. package/src/cli-output.ts +0 -43
  67. package/src/cli.ts +0 -1339
  68. package/src/collections/PostgresCollectionRegistry.ts +0 -108
  69. package/src/collections/buildRegistry.ts +0 -68
  70. package/src/collections/validate-relations.ts +0 -402
  71. package/src/connection.ts +0 -333
  72. package/src/data-transformer.ts +0 -845
  73. package/src/databasePoolManager.ts +0 -95
  74. package/src/history/HistoryService.ts +0 -254
  75. package/src/history/ensure-history-table.ts +0 -53
  76. package/src/index.ts +0 -19
  77. package/src/interfaces.ts +0 -60
  78. package/src/module-dir.ts +0 -7
  79. package/src/schema/atlas-argv.ts +0 -94
  80. package/src/schema/auth-schema.ts +0 -298
  81. package/src/schema/auth-users-columns.ts +0 -131
  82. package/src/schema/carved-out-migration.ts +0 -404
  83. package/src/schema/classify-change.ts +0 -436
  84. package/src/schema/collection-index.ts +0 -427
  85. package/src/schema/collections-schema-version.ts +0 -103
  86. package/src/schema/destructive-sql.ts +0 -94
  87. package/src/schema/doctor-cli.ts +0 -66
  88. package/src/schema/doctor-policy-checks.ts +0 -105
  89. package/src/schema/doctor.ts +0 -837
  90. package/src/schema/drizzle-ddl.ts +0 -33
  91. package/src/schema/dynamic-tables.test.ts +0 -302
  92. package/src/schema/dynamic-tables.ts +0 -293
  93. package/src/schema/ensure-collection-policies.ts +0 -198
  94. package/src/schema/ensure-collection-tables.test.ts +0 -518
  95. package/src/schema/ensure-collection-tables.ts +0 -1267
  96. package/src/schema/generate-drizzle-schema-logic.ts +0 -957
  97. package/src/schema/generate-drizzle-schema.ts +0 -143
  98. package/src/schema/generate-postgres-ddl-logic.ts +0 -1339
  99. package/src/schema/generate-postgres-ddl.ts +0 -180
  100. package/src/schema/generate-schema-commit.ts +0 -267
  101. package/src/schema/generated-schema-staleness.ts +0 -284
  102. package/src/schema/introspect-db-constraints.ts +0 -385
  103. package/src/schema/introspect-db-inference.ts +0 -255
  104. package/src/schema/introspect-db-logic.ts +0 -1387
  105. package/src/schema/introspect-db-naming.ts +0 -15
  106. package/src/schema/introspect-db-project.ts +0 -78
  107. package/src/schema/introspect-db-queries.ts +0 -326
  108. package/src/schema/introspect-db-structure.ts +0 -670
  109. package/src/schema/introspect-db-types.ts +0 -56
  110. package/src/schema/introspect-db.ts +0 -257
  111. package/src/schema/introspect-runtime.test.ts +0 -260
  112. package/src/schema/introspect-runtime.ts +0 -327
  113. package/src/schema/non-sql-collections.test.ts +0 -131
  114. package/src/schema/rls-bootstrap-sql.ts +0 -288
  115. package/src/schema/search-column.ts +0 -643
  116. package/src/schema/test-schema.ts +0 -11
  117. package/src/schema/vector-index.ts +0 -491
  118. package/src/security/anonymous-grants.test.ts +0 -73
  119. package/src/security/policy-drift.test.ts +0 -435
  120. package/src/security/policy-drift.ts +0 -473
  121. package/src/security/rls-enforcement.ts +0 -505
  122. package/src/services/BranchService.ts +0 -326
  123. package/src/services/FetchService.ts +0 -2115
  124. package/src/services/PersistService.ts +0 -557
  125. package/src/services/RelationService.ts +0 -978
  126. package/src/services/RelationWriteService.ts +0 -653
  127. package/src/services/cdc/CdcListener.ts +0 -103
  128. package/src/services/cdc/junction-tables.ts +0 -91
  129. package/src/services/cdc/trigger-cdc.ts +0 -173
  130. package/src/services/channel-bus/ChannelBus.ts +0 -44
  131. package/src/services/channel-bus/PostgresChannelBus.ts +0 -299
  132. package/src/services/channel-bus/index.ts +0 -114
  133. package/src/services/channel-history.ts +0 -424
  134. package/src/services/channel-presence.ts +0 -185
  135. package/src/services/collection-helpers.ts +0 -420
  136. package/src/services/dataService.ts +0 -256
  137. package/src/services/index.ts +0 -14
  138. package/src/services/junction-writes.ts +0 -295
  139. package/src/services/nested-path.ts +0 -145
  140. package/src/services/pg-notify-listener.ts +0 -151
  141. package/src/services/realtimeService.ts +0 -2545
  142. package/src/services/row-pipeline.ts +0 -240
  143. package/src/services/write-denial.ts +0 -55
  144. package/src/types.ts +0 -4
  145. package/src/utils/connection-string.ts +0 -58
  146. package/src/utils/drizzle-conditions.ts +0 -2743
  147. package/src/utils/pg-array-null-patch.ts +0 -42
  148. package/src/utils/pg-error-utils.ts +0 -391
  149. package/src/websocket.ts +0 -855
@@ -1,260 +0,0 @@
1
- import { sql } from "drizzle-orm";
2
- import { NodePgDatabase } from "drizzle-orm/node-postgres";
3
- import type { CollectionConfig } from "@rebasepro/types";
4
-
5
- /**
6
- * The auth schema version this runtime expects to find in the database.
7
- *
8
- * Bump this whenever a migration in `ensureAuthTablesExist` makes the schema
9
- * unreadable by the runtime that came before it — that is, whenever a *previous*
10
- * version's auth queries would break against the migrated shape. Additive
11
- * changes (a new nullable column nobody older references) do not need a bump.
12
- *
13
- * History. Note that 1 is a label for an era, not a value any database holds:
14
- * stamping did not exist then, so an era-1 database reads as unstamped
15
- * (`null`), and 2 is the first version ever actually written. The numbering
16
- * starts at 2 only because two schema eras already existed when it was
17
- * introduced; it could just as well have started at 1. It is not worth
18
- * renumbering now — deployed databases already carry 2, and lowering the
19
- * constant would make them look newer than the runtime and refuse the boot.
20
- *
21
- * 1 — Device-session refresh tokens. A row *was* a session, identified by
22
- * `unique_device_session UNIQUE (uid, user_agent, ip_address)`, and
23
- * `createToken` upserted with `ON CONFLICT (uid, user_agent, ip_address)`.
24
- * 2 — Session-scoped, rotation-safe refresh tokens: `session_id`, `revoked`,
25
- * `rotated_at`, `session_started_at`, and `unique_device_session`
26
- * dropped because two live tokens of one session share all three columns.
27
- *
28
- * The 1 → 2 migration is why this file exists. Dropping the constraint is
29
- * one-way: a version-1 runtime deployed afterwards boots perfectly, logs
30
- * `✅ Auth tables ready` (its `CREATE TABLE IF NOT EXISTS` never revisits the
31
- * existing table, so it cannot re-add the constraint), answers `/health` with
32
- * 200 — and then fails every single login and refresh with SQLSTATE 42P10,
33
- * because its `ON CONFLICT` names a constraint that no longer exists. A silent
34
- * total auth outage behind a green health check. The stamp below turns that
35
- * into a boot refusal.
36
- */
37
- export const AUTH_SCHEMA_VERSION = 2;
38
-
39
- /** Key under which the version is stored in the auth schema's meta table. */
40
- const VERSION_KEY = "auth_schema_version";
41
-
42
- /**
43
- * Columns `refresh_tokens` must have for the current runtime's auth write path
44
- * to work. Checked by the health probe so a database that drifted *below* this
45
- * runtime is reported as unhealthy rather than discovered one failed login at a
46
- * time. Kept in step with the migration in `ensureAuthTablesExist`.
47
- */
48
- const REQUIRED_REFRESH_TOKEN_COLUMNS = ["session_id", "revoked", "rotated_at", "session_started_at"];
49
-
50
- /**
51
- * A constraint whose *presence* means the database is still at version 1, in a
52
- * shape this runtime's rotation logic cannot write to: it makes two live tokens
53
- * of one rotating session collide.
54
- */
55
- const RETIRED_REFRESH_TOKEN_CONSTRAINT = "unique_device_session";
56
-
57
- /**
58
- * Thrown when the database was migrated by a runtime newer than this one.
59
- *
60
- * Distinct class rather than a bare `Error` because `ensureAuthTablesExist`
61
- * wraps its migrations in a catch that deliberately swallows failures and
62
- * continues — every other problem there is better survived than crashed on.
63
- * This one is not, so the catch rethrows on this type specifically.
64
- */
65
- export class AuthSchemaVersionError extends Error {
66
- readonly databaseVersion: number;
67
- readonly runtimeVersion: number;
68
-
69
- constructor(databaseVersion: number, runtimeVersion: number) {
70
- super(
71
- `Auth schema version mismatch: the database is at version ${databaseVersion}, ` +
72
- `but this runtime understands version ${runtimeVersion}.\n\n` +
73
- "A newer version of the framework has already migrated this database. Running this " +
74
- "older runtime against it would boot cleanly and then fail every login and token " +
75
- "refresh, because the auth schema it expects no longer exists.\n\n" +
76
- "Refusing to start. Deploy a framework version at or above the one that migrated " +
77
- "this database, or restore the database from a backup taken before the upgrade."
78
- );
79
- this.name = "AuthSchemaVersionError";
80
- this.databaseVersion = databaseVersion;
81
- this.runtimeVersion = runtimeVersion;
82
- }
83
- }
84
-
85
- /**
86
- * The schema the auth tables live in, derived exactly as `ensureAuthTablesExist`
87
- * derives it. Shared so the two cannot drift: a stamp written to one schema and
88
- * read from another would read as "never stamped" forever.
89
- */
90
- export function resolveAuthSchema(collection?: CollectionConfig): string {
91
- if (!collection) return "rebase";
92
- const usersSchema = ("schema" in collection && typeof collection.schema === "string")
93
- ? collection.schema
94
- : "public";
95
- return usersSchema === "public" ? "rebase" : usersSchema;
96
- }
97
-
98
- /**
99
- * Read the stamped version, or `null` when the database has never been stamped.
100
- *
101
- * `null` is not an error and must not be treated as one: every database
102
- * provisioned before this file existed is unstamped, and so is every fresh one.
103
- * Uses `to_regclass` rather than selecting straight from the table so a missing
104
- * schema or table is a `null` rather than a thrown 42P01.
105
- */
106
- export async function readAuthSchemaVersion(
107
- db: NodePgDatabase,
108
- authSchema: string
109
- ): Promise<number | null> {
110
- const qualified = `"${authSchema}"."schema_meta"`;
111
- const exists = await db.execute(sql`SELECT to_regclass(${qualified}) IS NOT NULL AS present`);
112
- if (!(exists.rows[0] as { present: boolean } | undefined)?.present) return null;
113
-
114
- const result = await db.execute(sql`
115
- SELECT value FROM ${sql.raw(qualified)} WHERE key = ${VERSION_KEY}
116
- `);
117
- const raw = (result.rows[0] as { value: string } | undefined)?.value;
118
- if (raw === undefined) return null;
119
-
120
- const parsed = Number.parseInt(raw, 10);
121
- // A meta row we cannot parse is treated as unstamped rather than as version
122
- // 0: refusing to boot over a garbled string would be a worse failure than
123
- // the drift it is meant to catch.
124
- return Number.isFinite(parsed) ? parsed : null;
125
- }
126
-
127
- /**
128
- * Refuse to run against a database a newer runtime has already migrated.
129
- *
130
- * Deliberately one-directional. A database *older* than this runtime is the
131
- * normal upgrade path — the migrations in `ensureAuthTablesExist` are about to
132
- * bring it forward, so it is not an error. Only the reverse is unrecoverable.
133
- */
134
- export async function assertAuthSchemaCompatible(
135
- db: NodePgDatabase,
136
- authSchema: string
137
- ): Promise<void> {
138
- const databaseVersion = await readAuthSchemaVersion(db, authSchema);
139
- if (databaseVersion !== null && databaseVersion > AUTH_SCHEMA_VERSION) {
140
- throw new AuthSchemaVersionError(databaseVersion, AUTH_SCHEMA_VERSION);
141
- }
142
- }
143
-
144
- /**
145
- * Record that this runtime's migrations have been applied.
146
- *
147
- * Called at the end of `ensureAuthTablesExist`, so a boot that failed partway
148
- * through leaves the older stamp in place and the next boot migrates again.
149
- */
150
- export async function stampAuthSchemaVersion(
151
- db: NodePgDatabase,
152
- authSchema: string
153
- ): Promise<void> {
154
- const qualified = `"${authSchema}"."schema_meta"`;
155
- await db.execute(sql`
156
- CREATE TABLE IF NOT EXISTS ${sql.raw(qualified)} (
157
- key TEXT PRIMARY KEY,
158
- value TEXT NOT NULL,
159
- updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
160
- )
161
- `);
162
- await db.execute(sql`
163
- INSERT INTO ${sql.raw(qualified)} (key, value)
164
- VALUES (${VERSION_KEY}, ${String(AUTH_SCHEMA_VERSION)})
165
- ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()
166
- `);
167
- }
168
-
169
- /** What {@link probeAuthSchema} found. */
170
- export interface AuthSchemaProbeResult {
171
- /** False when this runtime cannot be trusted to serve auth against this database. */
172
- healthy: boolean;
173
- /** The stamped version, or `null` on a database that predates stamping. */
174
- databaseVersion: number | null;
175
- /** {@link AUTH_SCHEMA_VERSION}. */
176
- runtimeVersion: number;
177
- /** Human-readable descriptions of each mismatch found. Empty when healthy. */
178
- problems: string[];
179
- }
180
-
181
- /**
182
- * Check that the auth schema is one this runtime can actually write to.
183
- *
184
- * Two independent checks, because either alone has a blind spot:
185
- *
186
- * - The **stamp** catches a runtime older than the database. It is the precise
187
- * signal, but it is blind on every database provisioned before stamping
188
- * existed — which today is all of them.
189
- * - The **structure** catches a database older than the runtime, and works on
190
- * unstamped databases. It is what makes this useful immediately rather than
191
- * one upgrade cycle from now.
192
- *
193
- * Never throws: a probe that fails to run reports unhealthy with the reason, so
194
- * a broken check surfaces as a degraded health response rather than a 500 from
195
- * the health endpoint itself.
196
- */
197
- export async function probeAuthSchema(
198
- db: NodePgDatabase,
199
- authSchema: string
200
- ): Promise<AuthSchemaProbeResult> {
201
- const problems: string[] = [];
202
- let databaseVersion: number | null = null;
203
-
204
- try {
205
- databaseVersion = await readAuthSchemaVersion(db, authSchema);
206
- if (databaseVersion !== null && databaseVersion > AUTH_SCHEMA_VERSION) {
207
- problems.push(
208
- `database is at auth schema version ${databaseVersion}, this runtime understands ` +
209
- `${AUTH_SCHEMA_VERSION} — it was migrated by a newer framework version`
210
- );
211
- }
212
-
213
- const refreshTokens = `"${authSchema}"."refresh_tokens"`;
214
- const present = await db.execute(sql`SELECT to_regclass(${refreshTokens}) IS NOT NULL AS present`);
215
- if (!(present.rows[0] as { present: boolean } | undefined)?.present) {
216
- // Not a problem in itself: auth may simply not be configured on this
217
- // deployment, and the table is created on demand at boot when it is.
218
- return { healthy: problems.length === 0, databaseVersion, runtimeVersion: AUTH_SCHEMA_VERSION, problems };
219
- }
220
-
221
- const columns = await db.execute(sql`
222
- SELECT column_name FROM information_schema.columns
223
- WHERE table_schema = ${authSchema} AND table_name = 'refresh_tokens'
224
- `);
225
- const found = new Set((columns.rows as { column_name: string }[]).map(row => row.column_name));
226
- const missing = REQUIRED_REFRESH_TOKEN_COLUMNS.filter(column => !found.has(column));
227
- if (missing.length > 0) {
228
- problems.push(
229
- `refresh_tokens is missing ${missing.join(", ")} — the auth migrations have not been ` +
230
- "applied to this database, so token rotation will fail"
231
- );
232
- }
233
-
234
- const retired = await db.execute(sql`
235
- SELECT 1 FROM pg_constraint c
236
- JOIN pg_class t ON t.oid = c.conrelid
237
- JOIN pg_namespace n ON n.oid = t.relnamespace
238
- WHERE n.nspname = ${authSchema}
239
- AND t.relname = 'refresh_tokens'
240
- AND c.conname = ${RETIRED_REFRESH_TOKEN_CONSTRAINT}
241
- `);
242
- if (retired.rows.length > 0) {
243
- problems.push(
244
- `refresh_tokens still carries ${RETIRED_REFRESH_TOKEN_CONSTRAINT} — concurrent token ` +
245
- "rotation for one session will fail on it"
246
- );
247
- }
248
- } catch (error: unknown) {
249
- problems.push(
250
- `auth schema probe failed: ${error instanceof Error ? error.message : String(error)}`
251
- );
252
- }
253
-
254
- return {
255
- healthy: problems.length === 0,
256
- databaseVersion,
257
- runtimeVersion: AUTH_SCHEMA_VERSION,
258
- problems
259
- };
260
- }