• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / storage / 29406887750

15 Jul 2026 10:05AM UTC coverage: 79.516% (+0.1%) from 79.399%
29406887750

Pull #1233

github

web-flow
Merge b6bc3191b into 03509efb1
Pull Request #1233: fix: cut down promises from connection create/dispose

5427 of 7395 branches covered (73.39%)

Branch coverage included in aggregate %.

12 of 16 new or added lines in 11 files covered. (75.0%)

10555 of 12704 relevant lines covered (83.08%)

424.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.47
/src/http/plugins/db.ts
1
import { createSingleFlightByKey } from '@internal/concurrency'
2
import {
3
  getPostgresConnection,
4
  getServiceKeyUser,
5
  getTenantConfig,
6
  PgTenantConnection,
7
} from '@internal/database'
8
import {
9
  areMigrationsUpToDate,
10
  DBMigration,
11
  lastLocalMigrationName,
12
  progressiveMigrations,
13
  runMigrationsOnTenant,
14
  updateTenantMigrationsState,
15
} from '@internal/database/migrations'
16
import { ERRORS } from '@internal/errors'
17
import fastifyPlugin from 'fastify-plugin'
18
import { getConfig, MultitenantMigrationStrategy } from '../../config'
19

20
declare module 'fastify' {
21
  interface FastifyRequest {
22
    db: PgTenantConnection
23
    latestMigration?: keyof typeof DBMigration
24
  }
25
}
26

27
const { databaseEnableQueryCancellation, dbMigrationStrategy, isMultitenant, dbMigrationFreezeAt } =
46✔
28
  getConfig()
29

30
const migrationSingleFlight = createSingleFlightByKey<void>()
46✔
31

32
export const db = fastifyPlugin(
46✔
33
  async function db(fastify) {
34
    fastify.register(migrations)
4,563✔
35

36
    fastify.decorateRequest('db')
4,563✔
37

38
    fastify.addHook('preHandler', async (request) => {
4,563✔
39
      const adminUser = await getServiceKeyUser(request.tenantId)
1,051✔
40
      const userPayload = request.jwtPayload
1,051✔
41

42
      if (!userPayload) {
1,051!
43
        throw ERRORS.AccessDenied('JWT payload is missing')
×
44
      }
45

46
      request.db = await getPostgresConnection({
1,051✔
47
        user: {
48
          payload: userPayload,
49
          jwt: request.jwt,
50
        },
51
        superUser: adminUser,
52
        tenantId: request.tenantId,
53
        host: request.headers['x-forwarded-host'] as string,
54
        headers: request.headers,
55
        path: request.url,
56
        method: request.method,
57
        operation: () => request.operation,
2,313✔
58
      })
59

60
      // Connect abort signal to DB connection for query cancellation
61
      if (databaseEnableQueryCancellation && request.signals) {
1,049✔
62
        request.db.setAbortSignal(request.signals.disconnect.signal)
1✔
63
      }
64
    })
65

66
    fastify.addHook('onSend', async (request, reply, payload) => {
4,563✔
67
      request.db?.dispose()
1,052✔
68
      return payload
1,052✔
69
    })
70

71
    fastify.addHook('onTimeout', async (request) => {
4,563✔
NEW
72
      request.db?.dispose()
×
73
    })
74

75
    fastify.addHook('onRequestAbort', async (request) => {
4,563✔
NEW
76
      request.db?.dispose()
×
77
    })
78
  },
79
  { name: 'db-init' }
80
)
81

82
interface DbSuperUserPluginOptions {
83
  disableHostCheck?: boolean
84
}
85

86
export const dbSuperUser = fastifyPlugin<DbSuperUserPluginOptions>(
46✔
87
  async function dbSuperUser(fastify, opts) {
88
    fastify.register(migrations)
1,750✔
89
    fastify.decorateRequest('db')
1,750✔
90

91
    fastify.addHook('preHandler', async (request) => {
1,750✔
92
      const adminUser = await getServiceKeyUser(request.tenantId)
215✔
93

94
      request.db = await getPostgresConnection({
215✔
95
        user: adminUser,
96
        superUser: adminUser,
97
        tenantId: request.tenantId,
98
        host: request.headers['x-forwarded-host'] as string,
99
        path: request.url,
100
        method: request.method,
101
        headers: request.headers,
102
        disableHostCheck: opts.disableHostCheck,
103
        operation: () => request.operation,
65✔
104
      })
105

106
      // Connect abort signal to DB connection for query cancellation
107
      if (databaseEnableQueryCancellation && request.signals) {
215✔
108
        request.db.setAbortSignal(request.signals.disconnect.signal)
1✔
109
      }
110
    })
111

112
    fastify.addHook('onSend', async (request, reply, payload) => {
1,750✔
113
      request.db?.dispose()
278✔
114
      return payload
278✔
115
    })
116

117
    fastify.addHook('onTimeout', async (request) => {
1,750✔
NEW
118
      request.db?.dispose()
×
119
    })
120

121
    fastify.addHook('onRequestAbort', async (request) => {
1,750✔
122
      request.db?.dispose()
1✔
123
    })
124
  },
125
  { name: 'db-superuser-init' }
126
)
127

128
/**
129
 * Handle database migration for multitenant applications when a request is made
130
 */
131
export const migrations = fastifyPlugin(
46✔
132
  async function migrations(fastify) {
133
    fastify.addHook('preHandler', async (req) => {
6,313✔
134
      if (isMultitenant) {
1,268✔
135
        const { migrationVersion } = await getTenantConfig(req.tenantId)
16✔
136
        req.latestMigration = migrationVersion
16✔
137
        return
16✔
138
      }
139

140
      req.latestMigration = await lastLocalMigrationName()
1,252✔
141
    })
142

143
    if (dbMigrationStrategy === MultitenantMigrationStrategy.ON_REQUEST) {
6,313✔
144
      fastify.addHook('preHandler', async (request) => {
6,306✔
145
        // migrations are handled via async migrations
146
        if (!isMultitenant) {
1,261✔
147
          return
1,245✔
148
        }
149

150
        const tenant = await getTenantConfig(request.tenantId)
16✔
151
        if (tenant.syncMigrationsDone) {
16✔
152
          return
3✔
153
        }
154

155
        await migrationSingleFlight(request.tenantId, async () => {
13✔
156
          if (await areMigrationsUpToDate(request.tenantId)) {
10✔
157
            tenant.syncMigrationsDone = true
1✔
158
            return
1✔
159
          }
160

161
          await runMigrationsOnTenant({
9✔
162
            databaseUrl: tenant.databaseUrl,
163
            tenantId: request.tenantId,
164
            upToMigration: dbMigrationFreezeAt,
165
          })
166
          await updateTenantMigrationsState(request.tenantId)
8✔
167
          tenant.syncMigrationsDone = true
8✔
168
        })
169
      })
170
    }
171

172
    if (dbMigrationStrategy === MultitenantMigrationStrategy.PROGRESSIVE) {
6,313✔
173
      fastify.addHook('preHandler', async (request) => {
7✔
174
        if (!isMultitenant) {
7!
175
          return
7✔
176
        }
177

178
        const tenant = await getTenantConfig(request.tenantId)
×
179
        if (tenant.syncMigrationsDone) {
×
180
          return
×
181
        }
182

183
        // migrations are up to date
184
        if (await areMigrationsUpToDate(request.tenantId)) {
×
185
          tenant.syncMigrationsDone = true
×
186
          return
×
187
        }
188

189
        progressiveMigrations.addTenant(request.tenantId)
×
190
      })
191
    }
192
  },
193
  { name: 'db-migrations' }
194
)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc