Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@ragpipe/plugin-supabase

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ragpipe/plugin-supabase - npm Package Compare versions

Comparing version
0.0.1
to
0.1.0-alpha.1
+42
sql/migrations/20260406164614_init.sql
-- ragpipe/plugin-supabase initial schema
-- 1. Enable pgvector
CREATE EXTENSION IF NOT EXISTS vector;
-- 2. Create the documents table
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
source TEXT NOT NULL,
content TEXT NOT NULL,
vector VECTOR(3072),
UNIQUE(source, content)
);
-- 3. Create the similarity search function
CREATE OR REPLACE FUNCTION match_documents(
query_embedding VECTOR(3072),
match_count INT DEFAULT 5
)
RETURNS TABLE (
source TEXT,
content TEXT,
similarity FLOAT
)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY
SELECT
d.source,
d.content,
1 - (d.vector <=> query_embedding) AS similarity
FROM documents d
ORDER BY d.vector <=> query_embedding
LIMIT match_count;
END;
$$;
-- 4. Create an index for faster search
CREATE INDEX ON documents
USING ivfflat (vector vector_cosine_ops)
WITH (lists = 100);
+28
-32
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;

@@ -20,10 +18,2 @@ var __export = (target, all) => {

};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

@@ -39,35 +29,41 @@

// src/vector-store.ts
var import_postgres = __toESM(require("postgres"), 1);
var import_supabase_js = require("@supabase/supabase-js");
function supabaseVectorStore(options) {
const table = options.tableName ?? "documents";
const sql = (0, import_postgres.default)(options.databaseUrl);
const queryName = options.queryName ?? "match_documents";
const supabase = (0, import_supabase_js.createClient)(
options.supabaseUrl,
options.supabaseKey
);
return {
name: "supabase",
async search(vector, topK) {
const vectorStr = `[${vector.join(",")}]`;
const results = await sql`
SELECT source, content,
1 - (vector <=> ${vectorStr}::vector) AS score
FROM ${sql(table)}
ORDER BY vector <=> ${vectorStr}::vector
LIMIT ${topK}
`;
return results;
const { data, error } = await supabase.rpc(queryName, {
query_embedding: vector,
match_count: topK
});
if (error) {
throw new Error(`Supabase search error: ${error.message}`);
}
return (data ?? []).map(
(row) => ({
source: row.source,
content: row.content,
score: row.similarity
})
);
},
async upsert(source, content, vector) {
const vectorStr = `[${vector.join(",")}]`;
await sql`
INSERT INTO ${sql(table)} (source, content, vector)
SELECT ${source}, ${content}, ${vectorStr}::vector
WHERE NOT EXISTS (
SELECT 1 FROM ${sql(table)}
WHERE source = ${source} AND content = ${content}
)
`;
const { error } = await supabase.from(table).upsert({ source, content, vector }, { onConflict: "source,content" });
if (error) {
throw new Error(`Supabase upsert error: ${error.message}`);
}
},
async clear() {
await sql`TRUNCATE TABLE ${sql(table)}`;
const { error } = await supabase.from(table).delete().gte("id", 0);
if (error) {
throw new Error(`Supabase clear error: ${error.message}`);
}
},
async disconnect() {
await sql.end();
}

@@ -74,0 +70,0 @@ };

import { VectorStorePlugin } from 'ragpipe';
interface SupabaseVectorStoreOptions {
databaseUrl: string;
supabaseUrl: string;
supabaseKey: string;
tableName?: string;
dimensions?: number;
queryName?: string;
}

@@ -8,0 +9,0 @@ declare function supabaseVectorStore(options: SupabaseVectorStoreOptions): VectorStorePlugin;

import { VectorStorePlugin } from 'ragpipe';
interface SupabaseVectorStoreOptions {
databaseUrl: string;
supabaseUrl: string;
supabaseKey: string;
tableName?: string;
dimensions?: number;
queryName?: string;
}

@@ -8,0 +9,0 @@ declare function supabaseVectorStore(options: SupabaseVectorStoreOptions): VectorStorePlugin;

// src/vector-store.ts
import postgres from "postgres";
import { createClient } from "@supabase/supabase-js";
function supabaseVectorStore(options) {
const table = options.tableName ?? "documents";
const sql = postgres(options.databaseUrl);
const queryName = options.queryName ?? "match_documents";
const supabase = createClient(
options.supabaseUrl,
options.supabaseKey
);
return {
name: "supabase",
async search(vector, topK) {
const vectorStr = `[${vector.join(",")}]`;
const results = await sql`
SELECT source, content,
1 - (vector <=> ${vectorStr}::vector) AS score
FROM ${sql(table)}
ORDER BY vector <=> ${vectorStr}::vector
LIMIT ${topK}
`;
return results;
const { data, error } = await supabase.rpc(queryName, {
query_embedding: vector,
match_count: topK
});
if (error) {
throw new Error(`Supabase search error: ${error.message}`);
}
return (data ?? []).map(
(row) => ({
source: row.source,
content: row.content,
score: row.similarity
})
);
},
async upsert(source, content, vector) {
const vectorStr = `[${vector.join(",")}]`;
await sql`
INSERT INTO ${sql(table)} (source, content, vector)
SELECT ${source}, ${content}, ${vectorStr}::vector
WHERE NOT EXISTS (
SELECT 1 FROM ${sql(table)}
WHERE source = ${source} AND content = ${content}
)
`;
const { error } = await supabase.from(table).upsert({ source, content, vector }, { onConflict: "source,content" });
if (error) {
throw new Error(`Supabase upsert error: ${error.message}`);
}
},
async clear() {
await sql`TRUNCATE TABLE ${sql(table)}`;
const { error } = await supabase.from(table).delete().gte("id", 0);
if (error) {
throw new Error(`Supabase clear error: ${error.message}`);
}
},
async disconnect() {
await sql.end();
}

@@ -36,0 +42,0 @@ };

{
"name": "@ragpipe/plugin-supabase",
"version": "0.0.1",
"version": "0.1.0-alpha.1",
"description": "Supabase pgvector vector store plugin for ragpipe",

@@ -33,3 +33,3 @@ "type": "module",

"types": "./dist/index.d.ts",
"files": ["dist", "README.md"],
"files": ["dist", "sql", "README.md"],
"scripts": {

@@ -55,3 +55,3 @@ "build": "tsup",

"dependencies": {
"postgres": "^3.4.5"
"@supabase/supabase-js": "^2.49.4"
},

@@ -58,0 +58,0 @@ "devDependencies": {

+44
-14
# @ragpipe/plugin-supabase
Supabase pgvector vector store plugin for [ragpipe](https://github.com/yungblud/ragpipe).
Supabase vector store plugin for [ragpipe](https://github.com/yungblud/ragpipe), powered by [`@supabase/supabase-js`](https://github.com/supabase/supabase-js).

@@ -20,5 +20,6 @@ ## Install

vectorStore: supabaseVectorStore({
databaseUrl: process.env.DATABASE_URL ?? "",
tableName: "documents", // default
dimensions: 3072,
supabaseUrl: process.env.SUPABASE_URL ?? "",
supabaseKey: process.env.SUPABASE_SERVICE_ROLE_KEY ?? "",
tableName: "documents", // default
queryName: "match_documents", // default RPC function name
}),

@@ -32,9 +33,10 @@ });

Returns a `VectorStorePlugin` backed by Supabase PostgreSQL with pgvector.
Returns a `VectorStorePlugin` backed by Supabase using the official JS SDK.
| Option | Type | Default | Description |
|---|---|---|---|
| `databaseUrl` | `string` | — | PostgreSQL connection string (required) |
| `tableName` | `string` | `"documents"` | Table to store/query vectors |
| `dimensions` | `number` | — | Vector dimensions (for documentation; table must match) |
| `supabaseUrl` | `string` | — | Supabase project URL (required) |
| `supabaseKey` | `string` | — | Service role key (required) |
| `tableName` | `string` | `"documents"` | Table to store documents |
| `queryName` | `string` | `"match_documents"` | PostgreSQL function for vector search |

@@ -45,14 +47,16 @@ ### Methods

|---|---|
| `search(vector, topK)` | Cosine similarity search, returns top-K results with scores |
| `upsert(source, content, vector)` | Insert a document if it doesn't already exist |
| `clear()` | Truncate the documents table |
| `disconnect()` | Close the PostgreSQL connection |
| `search(vector, topK)` | Calls `supabase.rpc()` for cosine similarity search |
| `upsert(source, content, vector)` | Inserts via `supabase.from().upsert()` with dedup on `source,content` |
| `clear()` | Deletes all rows from the documents table |
| `disconnect()` | No-op (Supabase JS client manages connections automatically) |
## Database Setup
Enable pgvector and create the documents table in your Supabase SQL editor:
Run the following in your Supabase SQL editor:
```sql
-- 1. Enable pgvector
CREATE EXTENSION IF NOT EXISTS vector;
-- 2. Create the documents table
CREATE TABLE documents (

@@ -62,5 +66,31 @@ id BIGSERIAL PRIMARY KEY,

content TEXT NOT NULL,
vector VECTOR(3072)
vector VECTOR(3072),
UNIQUE(source, content)
);
-- 3. Create the similarity search function
CREATE OR REPLACE FUNCTION match_documents(
query_embedding VECTOR(3072),
match_count INT DEFAULT 5
)
RETURNS TABLE (
source TEXT,
content TEXT,
similarity FLOAT
)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY
SELECT
d.source,
d.content,
1 - (d.vector <=> query_embedding) AS similarity
FROM documents d
ORDER BY d.vector <=> query_embedding
LIMIT match_count;
END;
$$;
-- 4. Create an index for faster search
CREATE INDEX ON documents

@@ -67,0 +97,0 @@ USING ivfflat (vector vector_cosine_ops)