Interface: IStorageBackend
Defined in: src/types/interfaces/storage.interface.ts:379
Storage backend interface for Chive's local index.
Remarks
This interface stores indexes, not source data. All data can be rebuilt from the AT Protocol firehose.
Implementation uses PostgreSQL for relational queries, JSONB columns for flexible schema, partitioning for scalability, and indexes on uri, author, and createdAt.
Methods
countEprintsByAuthor()
countEprintsByAuthor(
author):Promise<number>
Defined in: src/types/interfaces/storage.interface.ts:526
Counts total eprints by author.
Parameters
author
Author DID
Returns
Promise<number>
Total count of eprints by this author
Remarks
Returns the total count without fetching full eprint data. Used for displaying metrics in author profiles.
Example
const count = await storage.countEprintsByAuthor(toDID('did:plc:abc')!);
console.log(`Author has ${count} eprints`);
countEprintsByAuthors()
countEprintsByAuthors(
authors):Promise<Map<string,number>>
Defined in: src/types/interfaces/storage.interface.ts:544
Counts eprints for several authors in one query.
Parameters
authors
readonly DID[]
Author DIDs
Returns
Promise<Map<string, number>>
A map from DID to eprint count, omitting authors with none
Remarks
For paths that need a count per author across a page of authors, where a call per author would be a round trip per author.
Example
const counts = await storage.countEprintsByAuthors([didA, didB]);
console.log(counts.get(didA) ?? 0);
deleteByUri()
deleteByUri(
table,uri):Promise<void>
Defined in: src/types/interfaces/storage.interface.ts:925
Deletes a record from an index table by AT-URI.
Parameters
table
string
uri
Returns
Promise<void>
deleteChangelog()
deleteChangelog(
uri):Promise<Result<void,Error>>
Defined in: src/types/interfaces/storage.interface.ts:846
Deletes a changelog from the index.
Parameters
uri
AT URI of the changelog to delete
Returns
Promise<Result<void, Error>>
Result indicating success or failure
Remarks
Called when firehose receives a deletion event for a changelog.
deleteCitation()
deleteCitation(
userRecordUri):Promise<void>
Defined in: src/types/interfaces/storage.interface.ts:979
Deletes a user-provided citation by its record URI.
Parameters
userRecordUri
AT URI of the user citation record
Returns
Promise<void>
void
deleteEprint()
deleteEprint(
uri):Promise<Result<void,Error>>
Defined in: src/types/interfaces/storage.interface.ts:748
Deletes an eprint from the index.
Parameters
uri
AT URI of the eprint to delete
Returns
Promise<Result<void, Error>>
Result indicating success or failure
Remarks
Removes the eprint from the local index. Does not delete from PDS. ATProto compliance: Chive never writes to user PDSes.
Called when firehose receives a deletion event for an eprint.
Example
const result = await storage.deleteEprint(
toAtUri('at://did:plc:abc/pub.chive.eprint.submission/xyz')!
);
if (!result.ok) {
console.error('Failed to delete:', result.error);
}
deleteRelatedWork()
deleteRelatedWork(
uri):Promise<void>
Defined in: src/types/interfaces/storage.interface.ts:1033
Deletes a related work record by its URI.
Parameters
uri
AT URI of the related work record
Returns
Promise<void>
void
findByExternalIds()
findByExternalIds(
externalIds):Promise<null|StoredEprint>
Defined in: src/types/interfaces/storage.interface.ts:626
Finds an eprint by external identifiers.
Parameters
externalIds
External service identifiers to search
arxivId
string
dblpId
string
doi
string
openAlexId
string
openReviewId
string
pmid
string
semanticScholarId
string
ssrnId
string
Returns
Promise<null | StoredEprint>
First matching eprint or null
Remarks
Searches the eprints index by DOI and external IDs stored in the
external_ids JSONB column. Returns the first match found.
Search priority:
- DOI (most authoritative)
- arXiv ID
- Semantic Scholar ID
- OpenAlex ID
- DBLP ID
- OpenReview ID
- PubMed ID
- SSRN ID
Example
const eprint = await storage.findByExternalIds({
doi: '10.1234/example',
arxivId: '2301.12345',
});
if (eprint) {
console.log('Found duplicate:', eprint.uri);
}
getChangelog()
getChangelog(
uri):Promise<null|StoredChangelog>
Defined in: src/types/interfaces/storage.interface.ts:773
Retrieves a single changelog entry by URI.
Parameters
uri
AT URI of the changelog record
Returns
Promise<null | StoredChangelog>
Changelog view or null if not found
Remarks
Changelogs are indexed from the firehose and describe changes between eprint versions.
Example
const changelog = await storage.getChangelog(
toAtUri('at://did:plc:abc/pub.chive.eprint.changelog/xyz')!
);
if (changelog) {
console.log('Version:', changelog.version);
}
getCitationsForEprint()
getCitationsForEprint(
eprintUri,options?):Promise<CitationListResult>
Defined in: src/types/interfaces/storage.interface.ts:952
Retrieves citations for an eprint.
Parameters
eprintUri
AT URI of the eprint
options?
Query options (limit, offset, source filter)
Returns
Promise<CitationListResult>
Paginated list of citations
Remarks
Returns both auto-extracted and user-provided citations. Filter by source to get only one type.
Example
const result = await storage.getCitationsForEprint(
toAtUri('at://did:plc:abc/pub.chive.eprint.submission/xyz')!,
{ limit: 50, source: 'all' }
);
for (const citation of result.citations) {
console.log(citation.title, citation.source);
}
getEprint()
getEprint(
uri):Promise<null|StoredEprint>
Defined in: src/types/interfaces/storage.interface.ts:445
Retrieves an eprint index record by URI.
Parameters
uri
AT URI of the eprint
Returns
Promise<null | StoredEprint>
Eprint if indexed, null otherwise
Remarks
Returns null if the eprint has not been indexed by Chive. The eprint may still exist in the user's PDS.
Example
const eprint = await storage.getEprint(
toAtUri('at://did:plc:abc/pub.chive.eprint.submission/xyz')!
);
if (eprint) {
console.log('Title:', eprint.title);
}
getEprints()
getEprints(
uris):Promise<Map<AtUri,StoredEprint>>
Defined in: src/types/interfaces/storage.interface.ts:457
Fetches several eprints in a single query.
Parameters
uris
readonly AtUri[]
Eprint URIs to fetch
Returns
Promise<Map<AtUri, StoredEprint>>
Map of URI to eprint, omitting URIs with no row
Remarks
Exists so callers handling a page of results do not issue one round trip per item; a missing URI is absent from the map rather than an error.
getEprintsByAuthor()
getEprintsByAuthor(
author,options?):Promise<StoredEprint[]>
Defined in: src/types/interfaces/storage.interface.ts:506
Queries eprints by author.
Parameters
author
Author DID
options?
Query options (limit, offset, sort)
Returns
Promise<StoredEprint[]>
Array of eprints by this author
Remarks
Returns eprints in order specified by options.sortBy. For full-text search across all fields, use ISearchEngine instead.
Example
const eprints = await storage.getEprintsByAuthor(
toDID('did:plc:abc')!,
{ limit: 10, sortBy: 'createdAt', sortOrder: 'desc' }
);
eprints.forEach(p => console.log(p.title));
getEprintUrisForTerm()
getEprintUrisForTerm(
normalizedTerm,limit,offset):Promise<{total:number;uris:AtUri[]; }>
Defined in: src/types/interfaces/storage.interface.ts:884
Retrieves distinct eprint URIs that match a normalized term as either a community tag (user_tags_index) or an author keyword (eprints_index.keywords).
Parameters
normalizedTerm
string
Normalized tag/keyword string (hyphen-separated)
limit
number
Maximum results (0 for count only)
offset
number
Pagination offset
Returns
Promise<{ total: number; uris: AtUri[]; }>
Deduplicated eprint URIs and total count
getRelatedWorksForEprint()
getRelatedWorksForEprint(
eprintUri,options?):Promise<RelatedWorkListResult>
Defined in: src/types/interfaces/storage.interface.ts:1006
Retrieves related works for an eprint.
Parameters
eprintUri
AT URI of the eprint
options?
Query options (limit, offset)
Returns
Promise<RelatedWorkListResult>
Paginated list of related works
Remarks
Returns user-curated related work links. Each link includes the target eprint URI and the relationship type.
Example
const result = await storage.getRelatedWorksForEprint(
toAtUri('at://did:plc:abc/pub.chive.eprint.submission/xyz')!,
{ limit: 50 }
);
for (const rw of result.relatedWorks) {
console.log(rw.targetEprintUri, rw.relationshipType);
}
getTagsForEprint()
getTagsForEprint(
eprintUri):Promise<readonlyIndexedUserTag[]>
Defined in: src/types/interfaces/storage.interface.ts:871
Retrieves user tags for an eprint.
Parameters
eprintUri
AT URI of the eprint
Returns
Promise<readonly IndexedUserTag[]>
Array of indexed user tags
Remarks
Returns individual user tag records indexed from the firehose. Each tag includes the tagger's DID, original tag text, and creation time.
Example
const tags = await storage.getTagsForEprint(
toAtUri('at://did:plc:abc/pub.chive.eprint.submission/xyz')!
);
for (const tag of tags) {
console.log(`${tag.taggerDid} tagged: ${tag.tag}`);
}
indexCitation()
indexCitation(
citation):Promise<void>
Defined in: src/types/interfaces/storage.interface.ts:969
Indexes a user-provided citation from the firehose.
Parameters
citation
Citation data to index
Returns
Promise<void>
void
Remarks
Upserts into the extracted_citations table using user_record_uri as the deduplication key. Sets source to 'user-provided'.
indexRelatedWork()
indexRelatedWork(
relatedWork):Promise<void>
Defined in: src/types/interfaces/storage.interface.ts:1023
Indexes a related work record from the firehose.
Parameters
relatedWork
Related work data to index
Returns
Promise<void>
void
Remarks
Upserts into the user_related_works_index table using uri as the primary key.
indexTag()
indexTag(
tag):Promise<void>
Defined in: src/types/interfaces/storage.interface.ts:912
Indexes a user tag record into the user_tags_index table.
Parameters
tag
Tag data to index
cid
createdAt
Date
eprintUri
pdsUrl
string
tag
string
taggerDid
uri
Returns
Promise<void>
void
isStale()
isStale(
uri):Promise<boolean>
Defined in: src/types/interfaces/storage.interface.ts:721
Checks if an indexed record is stale (PDS has newer version).
Parameters
uri
Record URI
Returns
Promise<boolean>
True if index is stale, false otherwise
Remarks
Staleness is detected by comparing:
- Indexed CID vs current PDS CID
- Last sync time vs PDS update time
When stale, the indexing pipeline should re-fetch and re-index.
Example
const isStale = await storage.isStale(
toAtUri('at://did:plc:abc/pub.chive.eprint.submission/xyz')!
);
if (isStale) {
console.log('Re-indexing required');
}
listChangelogs()
listChangelogs(
eprintUri,options?):Promise<ChangelogListResult>
Defined in: src/types/interfaces/storage.interface.ts:800
Lists changelogs for a specific eprint with pagination.
Parameters
eprintUri
AT URI of the eprint
options?
Query options (limit, offset)
Returns
Promise<ChangelogListResult>
Paginated list of changelogs, newest first
Remarks
Returns changelogs ordered by creation date descending. Each changelog describes changes introduced in a specific version.
Example
const result = await storage.listChangelogs(
toAtUri('at://did:plc:abc/pub.chive.eprint.submission/xyz')!,
{ limit: 10 }
);
for (const changelog of result.changelogs) {
console.log(`Version ${changelog.version.major}: ${changelog.summary}`);
}
listDeletedEprintUris()
listDeletedEprintUris(
limit?):Promise<readonlyAtUri[]>
Defined in: src/types/interfaces/storage.interface.ts:481
Lists eprints marked deleted, for reconciling derived indexes.
Parameters
limit?
number
Maximum rows to return
Returns
Promise<readonly AtUri[]>
URIs of soft-deleted eprints
listEprintUris()
listEprintUris(
options?):Promise<readonlystring[]>
Defined in: src/types/interfaces/storage.interface.ts:563
Lists all eprint URIs with pagination.
Parameters
options?
Query options including limit
cursor
string
limit
number
Returns
Promise<readonly string[]>
Array of eprint URIs
Remarks
Used for browsing all eprints without facet filtering. Returns URIs only for efficiency; full metadata can be fetched separately.
Example
const uris = await storage.listEprintUris({ limit: 100 });
listEprintUrisByFieldUri()
listEprintUrisByFieldUri(
fieldUris,options?):Promise<readonlystring[]>
Defined in: src/types/interfaces/storage.interface.ts:587
Lists eprint URIs filtered by field URIs.
Parameters
fieldUris
readonly string[]
Field URIs to filter by (OR semantics)
options?
Query options including limit
limit
number
Returns
Promise<readonly string[]>
Array of eprint URIs that have any of the specified fields
Remarks
Used for discipline/field-based filtering in browse pages.
Returns eprints where the fields array contains objects matching any
of the provided field URIs.
Example
const uris = await storage.listEprintUrisByFieldUri(
['at://did:plc:graph-pds/pub.chive.graph.node/5a6b7c8d-9e0f-1a2b-3c4d-5e6f7a8b9c0d'],
{ limit: 100 }
);
searchKeywords()
searchKeywords(
searchText,limit):Promise<object[]>
Defined in: src/types/interfaces/storage.interface.ts:899
Searches distinct keywords from eprints_index matching a search term.
Parameters
searchText
string
Normalized search text
limit
number
Maximum results
Returns
Promise<object[]>
Keywords with usage counts
softDeleteEprint()
softDeleteEprint(
uri,source):Promise<Result<void,Error>>
Defined in: src/types/interfaces/storage.interface.ts:470
Marks an eprint deleted without removing its row.
Parameters
uri
Eprint URI
source
How the deletion was detected
"admin" | "pds_404" | "firehose_tombstone"
Returns
Promise<Result<void, Error>>
Ok on success, Err when the row does not exist
Remarks
Removing the row outright leaves nothing to reconcile against if a derived index (Elasticsearch, Neo4j) fails to drop the record.
storeChangelog()
storeChangelog(
changelog):Promise<Result<void,Error>>
Defined in: src/types/interfaces/storage.interface.ts:833
Stores or updates a changelog index record.
Parameters
changelog
Changelog metadata to index
Returns
Promise<Result<void, Error>>
Result indicating success or failure
Remarks
Upserts the changelog (insert or update based on URI). Called when firehose receives a changelog creation or update event.
ATProto Compliance: Stores metadata only, not source data.
Example
const result = await storage.storeChangelog({
uri: toAtUri('at://did:plc:abc/pub.chive.eprint.changelog/xyz')!,
cid: toCID('bafyreib...')!,
eprintUri: toAtUri('at://did:plc:abc/pub.chive.eprint.submission/xyz')!,
version: { major: 1, minor: 2, patch: 0 },
summary: 'Updated methodology section',
sections: [],
createdAt: '2024-01-15T10:30:00Z',
});
if (!result.ok) {
console.error('Failed to store:', result.error);
}
storeEprint()
storeEprint(
eprint):Promise<Result<void,Error>>
Defined in: src/types/interfaces/storage.interface.ts:420
Stores or updates an eprint index record.
Parameters
eprint
Eprint metadata to index
Returns
Promise<Result<void, Error>>
Result indicating success or failure
Remarks
Upserts the eprint (insert or update based on URI). Updates indexedAt timestamp on every call.
ATProto Compliance: Stores metadata only, not source data.
Example
const result = await storage.storeEprint({
uri: toAtUri('at://did:plc:abc/pub.chive.eprint.submission/xyz')!,
cid: toCID('bafyreib...')!,
author: toDID('did:plc:abc')!,
title: 'Neural Networks in Biology',
abstract: 'This paper explores...',
documentBlobRef: {
$type: 'blob',
ref: toCID('bafyreib...')!,
mimeType: 'application/pdf',
size: 2048576
},
documentFormat: 'pdf',
publicationStatus: 'eprint',
pdsUrl: 'https://pds.example.com',
indexedAt: new Date(),
createdAt: new Date()
});
if (!result.ok) {
console.error('Failed to store:', result.error);
}
storeEprintWithPDSTracking()
storeEprintWithPDSTracking(
eprint,pdsUrl,lastSynced):Promise<Result<void,Error>>
Defined in: src/types/interfaces/storage.interface.ts:689
Stores an eprint and tracks PDS source in a single transaction.
Parameters
eprint
Eprint metadata to index
pdsUrl
string
URL of the user's PDS
lastSynced
Date
Last successful sync timestamp
Returns
Promise<Result<void, Error>>
Result indicating success or failure
Remarks
Wraps both store and PDS tracking in a transaction for atomicity. If either operation fails, both are rolled back.
ATProto Compliance: Ensures consistent PDS source tracking.
Example
const result = await storage.storeEprintWithPDSTracking(
eprintData,
'https://pds.example.com',
new Date()
);
trackPDSSource()
trackPDSSource(
uri,pdsUrl,lastSynced):Promise<Result<void,Error>>
Defined in: src/types/interfaces/storage.interface.ts:662
Tracks PDS source for staleness detection.
Parameters
uri
Record URI
pdsUrl
string
URL of the user's PDS
lastSynced
Date
Last successful sync timestamp
Returns
Promise<Result<void, Error>>
Result indicating success or failure
Remarks
ATProto Compliance: Essential for detecting when index is stale (PDS has newer data) and triggering re-indexing.
This enables rebuilding the index from scratch if needed.
Example
await storage.trackPDSSource(
toAtUri('at://did:plc:abc/pub.chive.eprint.submission/xyz')!,
'https://pds.example.com',
new Date()
);