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

supabase / storage / 26941789962

04 Jun 2026 08:59AM UTC coverage: 76.304% (+0.9%) from 75.379%
26941789962

push

github

web-flow
fix: add acceptance matrix for vectors (#1132)

Signed-off-by: ferhat elmas <elmas.ferhat@gmail.com>

4478 of 6438 branches covered (69.56%)

Branch coverage included in aggregate %.

429 of 458 new or added lines in 27 files covered. (93.67%)

2 existing lines in 2 files now uncovered.

8837 of 11012 relevant lines covered (80.25%)

365.41 hits per line

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

59.68
/src/http/plugins/vector.ts
1
import { getTenantConfig, multitenantKnex } from '@internal/database'
2
import { deriveVectorDatabaseUrl } from '@internal/database/vector-store-url'
3
import { ERRORS } from '@internal/errors'
4
import {
5
  BucketScopedSingleShard,
6
  KnexShardStoreFactory,
7
  ShardCatalog,
8
  Sharder,
9
  SingleShard,
10
} from '@internal/sharding'
11
import {
12
  createS3VectorClient,
13
  createVectorTransactionKnexResolver,
14
  KnexVectorMetadataDB,
15
  PgVectorStore,
16
  S3Vector,
17
  VectorStore,
18
  VectorStoreManager,
19
} from '@storage/protocols/vector'
20
import { FastifyInstance } from 'fastify'
21
import fastifyPlugin from 'fastify-plugin'
22
import Knex from 'knex'
23
import { getConfig } from '../../config'
24

25
declare module 'fastify' {
26
  interface FastifyRequest {
27
    s3Vector: VectorStoreManager
28
  }
29
}
30

31
export const s3vector = fastifyPlugin(async function (fastify: FastifyInstance) {
29✔
32
  const config = getConfig()
272✔
33
  const {
34
    vectorBucketProvider,
35
    vectorDatabaseURL,
36
    vectorS3Buckets,
37
    isMultitenant,
38
    databaseApplicationName,
39
  } = config
272✔
40

41
  // S3 mode: build a singleton client+adapter at boot.
42
  let s3Adapter: S3Vector | undefined
43
  if (vectorBucketProvider === 's3' && vectorS3Buckets.length > 0) {
272✔
44
    s3Adapter = new S3Vector(createS3VectorClient())
271✔
45
  }
46

47
  // pgvector + single-tenant: VECTOR_DATABASE_URL is the maintenance URL the
48
  // migration runner used to CREATE DATABASE; the runtime pool targets the
49
  // derived `storage_vectors` database on the same server.
50
  let stPgVectorAdapter: PgVectorStore | undefined
51
  if (vectorBucketProvider === 'pgvector' && !isMultitenant && vectorDatabaseURL) {
272!
52
    const vectorKnex = Knex({
×
53
      client: 'pg',
54
      connection: {
55
        connectionString: deriveVectorDatabaseUrl(vectorDatabaseURL),
56
        application_name: databaseApplicationName,
57
      },
58
      pool: { min: 0, max: 10 },
59
    })
60
    stPgVectorAdapter = new PgVectorStore(vectorKnex)
×
61
    fastify.addHook('onClose', async () => {
×
62
      await vectorKnex.destroy()
×
63
    })
64
  }
65

66
  const featureEnabled =
67
    (vectorBucketProvider === 's3' && Boolean(s3Adapter)) ||
272!
68
    (vectorBucketProvider === 'pgvector' && (isMultitenant || Boolean(stPgVectorAdapter)))
69

70
  fastify.addHook('preHandler', async (req) => {
272✔
71
    if (!featureEnabled) {
151✔
72
      throw ERRORS.FeatureNotEnabled('vector', 'Vector service not configured')
1✔
73
    }
74

75
    const { vectorMaxBucketsCount, vectorMaxIndexesCount } = config
150✔
76

77
    let maxBucketCount = vectorMaxBucketsCount
150✔
78
    let maxIndexCount = vectorMaxIndexesCount
150✔
79

80
    if (isMultitenant) {
150!
81
      const { features } = await getTenantConfig(req.tenantId)
×
82
      maxBucketCount = features?.vectorBuckets?.maxBuckets || vectorMaxBucketsCount
×
83
      maxIndexCount = features?.vectorBuckets?.maxIndexes || vectorMaxIndexesCount
×
84
    }
85

86
    const db = req.db.pool.acquire()
150✔
87
    const store = new KnexVectorMetadataDB(db)
150✔
88

89
    // Pick the adapter. In multi-tenant pgvector mode the adapter binds to the
90
    // request's own tenant pool (vectors live in the tenant DB); ST pgvector
91
    // uses the singleton; s3 uses the singleton S3 client.
92
    let adapter: VectorStore
93
    if (vectorBucketProvider === 'pgvector') {
150!
NEW
94
      adapter = isMultitenant
×
95
        ? new PgVectorStore(createVectorTransactionKnexResolver(db))
96
        : stPgVectorAdapter!
97
    } else {
98
      adapter = s3Adapter!
150✔
99
    }
100

101
    let shard: Sharder
102
    if (vectorBucketProvider === 'pgvector') {
150!
103
      shard = new BucketScopedSingleShard({
×
104
        keyPrefix: 'pgvector__',
105
        capacity: Number.MAX_SAFE_INTEGER,
106
      })
107
    } else if (isMultitenant) {
150!
108
      shard = new ShardCatalog(new KnexShardStoreFactory(multitenantKnex))
×
109
    } else {
110
      shard = new SingleShard({
150✔
111
        shardKey: vectorS3Buckets[0],
112
        capacity: 10000,
113
      })
114
    }
115

116
    req.s3Vector = new VectorStoreManager(adapter, store, shard, {
150✔
117
      tenantId: req.tenantId,
118
      maxBucketCount,
119
      maxIndexCount,
120
    })
121
  })
122
})
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