All files / src/core/bindings VectorizeBinding.ts

30% Statements 6/20
0% Branches 0/10
10% Functions 1/10
31.57% Lines 6/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 15428x 28x                                     28x                                             28x   28x   28x                                                                                                                                                                                                                    
import { Binding } from '@/core/bindings/Binding'
import { lazySettings } from '@/utils/lazySettings'
import { VectorizeSettings } from '@/types/VectorizeSettings'
import type { CloudflareEnv } from '@/types/CloudflareEnv'
 
/**
 * Accessor for the Vectorize index binding (`vectorize` in `wrangler.json`).
 *
 * @example
 * ```ts
 * const index = new VectorizeBinding() // binding name and default topK from the configuration layer
 * const matches = await index.query(ctx.env, embedding)
 * ```
 *
 * @class
 *
 * @author Bayu Dwiyan Satria
 * @version 1.0.0
 * @since 1.0.0
 */
export class VectorizeBinding<E extends CloudflareEnv = CloudflareEnv> extends Binding<Vectorize, E> {
  /**
   * This accessor’s settings, resolved on first read.
   */
  private readonly settings: () => VectorizeSettings
 
  /**
   * Default number of matches returned by queries.
   */
  private readonly topK?: number
 
  /**
   * Default namespace applied to queries.
   */
  private readonly namespace?: string
 
  /**
   * Constructs a VectorizeBinding instance.
   *
   * @param settings Resolved settings. Defaults to `resolve('vectorize')`, so callers
   *   normally construct this with no arguments at all.
   */
  constructor(settings?: VectorizeSettings) {
    const settle = lazySettings<VectorizeSettings>('vectorize', settings)
 
    super(() => settle().binding)
 
    this.settings = settle
  }
 
  /**
   * Runs a similarity search for the given vector.
   *
   * @param env The Worker environment.
   * @param vector The query vector.
   * @param options Query options — overrides the configured defaults.
   * @returns The scored matches, ordered by similarity.
   * @throws {@link MissingBindingError} When the Vectorize binding is absent.
   */
  public async query(
    env: E,
    vector: VectorFloatArray | number[],
    options: VectorizeQueryOptions = {}
  ): Promise<VectorizeMatches> {
    return await this.resolve(env).query(vector, this.withDefaults(options))
  }
 
  /**
   * Runs a similarity search for a vector already stored in the index.
   *
   * @param env The Worker environment.
   * @param vectorId Id of the stored vector to search against.
   * @param options Query options — overrides the configured defaults.
   * @returns The scored matches, ordered by similarity.
   */
  public async queryById(env: E, vectorId: string, options: VectorizeQueryOptions = {}): Promise<VectorizeMatches> {
    return await this.resolve(env).queryById(vectorId, this.withDefaults(options))
  }
 
  /**
   * Inserts vectors, failing when an id already exists.
   *
   * @param env The Worker environment.
   * @param vectors The vectors to insert.
   * @returns The mutation id — writes are applied asynchronously.
   */
  public async insert(env: E, vectors: VectorizeVector[]): Promise<VectorizeAsyncMutation> {
    return await this.resolve(env).insert(vectors)
  }
 
  /**
   * Inserts vectors, replacing any that already exist.
   *
   * @param env The Worker environment.
   * @param vectors The vectors to upsert.
   * @returns The mutation id — writes are applied asynchronously.
   */
  public async upsert(env: E, vectors: VectorizeVector[]): Promise<VectorizeAsyncMutation> {
    return await this.resolve(env).upsert(vectors)
  }
 
  /**
   * Fetches vectors by id.
   *
   * @param env The Worker environment.
   * @param ids The vector ids to fetch.
   * @returns The matching vectors, unscored.
   */
  public async getByIds(env: E, ids: string[]): Promise<VectorizeVector[]> {
    return await this.resolve(env).getByIds(ids)
  }
 
  /**
   * Deletes vectors by id.
   *
   * @param env The Worker environment.
   * @param ids The vector ids to delete.
   * @returns The mutation id — deletes are applied asynchronously.
   */
  public async deleteByIds(env: E, ids: string[]): Promise<VectorizeAsyncMutation> {
    return await this.resolve(env).deleteByIds(ids)
  }
 
  /**
   * Reads index metadata — dimensions, metric, and vector count.
   *
   * @param env The Worker environment.
   * @returns Information about the bound index.
   */
  public async describe(env: E): Promise<VectorizeIndexInfo> {
    return await this.resolve(env).describe()
  }
 
  /**
   * Applies the configured defaults to query options that do not set them.
   *
   * @param options The caller-supplied query options.
   * @returns Query options with defaults filled in.
   */
  private withDefaults(options: VectorizeQueryOptions): VectorizeQueryOptions {
    const merged: VectorizeQueryOptions = { ...options }
 
    if (this.settings().topK !== undefined && merged.topK === undefined) {
      merged.topK = this.settings().topK
    }
 
    if (this.settings().namespace !== undefined && merged.namespace === undefined) {
      merged.namespace = this.settings().namespace
    }
 
    return merged
  }
}