@mantlejs/pinecone
Pinecone vector database adapter for Mantle JS. Provides PineconeRepository<T> — an abstract Repository<T> base class that stores entities as Pinecone vectors with metadata.
Installation
Section titled “Installation”npm install @mantlejs/pinecone @pinecone-database/pineconeConcepts
Section titled “Concepts”The pinecone() plugin
Section titled “The pinecone() plugin”pinecone(config) is a Mantle plugin. It creates a Pinecone client (from @pinecone-database/pinecone)
and stores it on the application at app.get("pinecone"). PineconeRepository reads this client from
the app in its constructor, so .configure(pinecone(...)) must run before any repository is instantiated.
Vector storage
Section titled “Vector storage”Pinecone is a managed vector database. Each record is stored as a high-dimensional float array (the “embedding”) plus a metadata object. PineconeRepository maps a Mantle entity to a Pinecone vector by serialising all non-idField fields as metadata.
Embedding generation
Section titled “Embedding generation”save() and saveAll() write a zero-vector placeholder (sized to vectorDimension) — they never
call an embedding model. Attach a real embedding separately with upsertVector(id, vector, data), using
a vector from your embedding model of choice (OpenAI, Cohere, a local model, etc.). This keeps the
adapter model-agnostic: it never generates embeddings itself.
Namespace
Section titled “Namespace”A single Pinecone index can be partitioned into isolated namespaces. Declare namespace as a required
property on your repository subclass to scope all operations to that namespace.
Quick start
Section titled “Quick start”import { mantle } from "@mantlejs/mantle";import { pinecone, PineconeRepository } from "@mantlejs/pinecone";
interface Document extends Record<string, unknown> { id: string; title: string; body: string;}
class DocumentRepository extends PineconeRepository<Document> { readonly indexName = "documents"; readonly namespace = "prod"; readonly vectorDimension = 1536; // must match your embedding model's output size}
const app = mantle().configure(pinecone({ apiKey: process.env.PINECONE_API_KEY }));
const repo = new DocumentRepository(app);
app.use("/documents", new DocumentService(repo));app.listen(3030);
// save() only writes a zero-vector placeholder — attach the real embedding separately:const doc = await repo.save({ title: "Hello", body: "World" });const vector = await myEmbeddingModel.embed(`${doc.title} ${doc.body}`);await repo.upsertVector(doc.id, vector, doc);pinecone(config?)
Section titled “pinecone(config?)”Returns a MantlePlugin. Call via app.configure(pinecone(config)).
app.configure( pinecone({ apiKey: process.env.PINECONE_API_KEY, // optional — falls back to the PINECONE_API_KEY env var }),);Side effects:
- Stores the
Pineconeclient atapp.get("pinecone")
PineconeConfig
Section titled “PineconeConfig”Partial<PineconeConfiguration> — every option accepted by the underlying @pinecone-database/pinecone
client’s constructor (apiKey, custom fetch implementation, etc.) is passed straight through.
PineconeRepository<T, D> (abstract class)
Section titled “PineconeRepository<T, D> (abstract class)”An abstract base class that implements VectorRepository<T, D> for Pinecone. Requires pinecone() to
be configured first — the constructor reads the client via app.get("pinecone").
abstract class PineconeRepository<T extends Record<string, unknown>, D = Partial<T>> implements VectorRepository<T, D>{ constructor(app: MantleApplication);
abstract readonly indexName: string; abstract readonly namespace: string; abstract readonly vectorDimension: number;}Properties
Section titled “Properties”| Property | Type | Default | Description |
|---|---|---|---|
indexName |
string |
— | Pinecone index name (required) |
namespace |
string |
— | Pinecone namespace to scope operations to (required) |
vectorDimension |
number |
— | Vector dimensionality of the index — sizes the zero-vector placeholder written by save()/saveAll() (required) |
idField |
string |
"id" |
Metadata key that holds the record id |
timestamps |
boolean |
true |
Auto-write createdAt / updatedAt ISO-8601 strings |
VectorRepository<T> methods
Section titled “VectorRepository<T> methods”| Method | Description |
|---|---|
findSimilar(vector, topK, params?) |
ANN search — returns the top-K most similar records |
upsertVector(id, vector, data) |
Attach (or replace) the embedding for a record |
deleteVector(id) |
Delete the record and its embedding (alias for deleteById) |
Every findSimilar result carries the Pinecone match score as _score — higher is more similar
(similarity, not distance, for the common cosine/dotproduct metrics).
Inherited from Repository<T, D>
Section titled “Inherited from Repository<T, D>”| Method | Description |
|---|---|
findAll(params?) |
List all records, with optional QueryParams filtering |
findPage(params?) |
One page via Pinecone’s native paginationToken as the cursor. where/skip/sort are rejected with BadRequest — the list API cannot filter or order |
findById(id) |
Fetch a single record by ID; returns null if not found |
save(data) |
Insert a new record with a zero-vector placeholder (sized to vectorDimension) — does not generate a real embedding; call upsertVector() for that |
saveAll(data[]) |
Batch insert multiple records, each with a zero-vector placeholder |
updateById(id, data) |
Replace all metadata for a record; throws NotFound if absent |
patchById(id, data) |
Update individual metadata fields for a record; throws NotFound if absent |
deleteById(id) |
Delete a record; throws NotFound if absent |
count(params?) |
Count records matching optional QueryParams |
Error mapping
Section titled “Error mapping”Pinecone’s SDK doesn’t expose a rich exception taxonomy the way DynamoDB or MongoDB do, so
wrapError() is intentionally simple:
| Thrown value | Error thrown |
|---|---|
Already a MantleError (e.g. NotFound from a missing record, or thrown by a hook or custom repository method) |
passed through unchanged |
Any other Error |
GeneralError |
A non-Error throw |
GeneralError |
toPineconeFilter(where)
Section titled “toPineconeFilter(where)”Converts a Mantle QueryParams.where clause into a Pinecone metadata filter object. Used internally by
findAll() and findSimilar(); exported for writing raw SDK calls inside a custom repository method.
| Operator | Pinecone filter |
|---|---|
{ field: value } |
{ field: { $eq: value } } |
{ field: null } |
{ field: { $eq: null } } |
{ field: [a, b] } |
{ field: { $in: [a, b] } } |
{ field: { $lt/$lte/$gt/$gte } } |
passed through unchanged |
{ field: { $ne/$in/$nin } } |
passed through unchanged |
{ $or: [...] } |
{ $or: [mapped…] } |
{ $and: [...] } |
{ $and: [mapped…] } |
$like and other pattern-matching operators are unsupported — Pinecone metadata filters have no
wildcard matching — and throw BadRequest naming the operator.
$contains and dot-path nested fields ("metadata.owner.name") are also not supported —
architectural, not a missing translator feature: Pinecone metadata values are flat scalars or
scalar arrays only, so there’s no nested structure to address or check containment against.
describe().capabilities.nestedPaths reports false accordingly.
import { toPineconeFilter } from "@mantlejs/pinecone";
const filter = toPineconeFilter({ category: "docs", views: { $gt: 100 } });// { category: { $eq: "docs" }, views: { $gt: 100 } }import type { PineconeConfig, WhereClause } from "@mantlejs/pinecone";| Type | Description |
|---|---|
PineconeConfig |
Options passed to pinecone() |
WhereClause |
Input type for toPineconeFilter() |
Development
Section titled “Development”npx nx build pinecone # compilenpx nx test pinecone # run testsnpx nx lint pinecone # lintPublishing
Section titled “Publishing”Build before publishing:
npx nx build pineconeFirst publish (scoped packages require --access public):
cd packages/pineconenpm publish --access publicSubsequent releases — bump version in packages/pinecone/package.json, then:
cd packages/pineconenpm publishTesting locally with Verdaccio
Section titled “Testing locally with Verdaccio”# Terminal 1 — start the local registrynpx nx run @mantle/source:local-registry
# Terminal 2 — publish to itcd packages/pineconenpm publish --registry http://localhost:4873
# Install from it in another projectnpm install @mantlejs/pinecone --registry http://localhost:4873