Skip to main content

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:490

Counts total eprints by author.

Parameters

author

DID

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`);

deleteByUri()

deleteByUri(table, uri): Promise<void>

Defined in: src/types/interfaces/storage.interface.ts:871

Deletes a record from an index table by AT-URI.

Parameters

table

string

uri

AtUri

Returns

Promise<void>


deleteChangelog()

deleteChangelog(uri): Promise<Result<void, Error>>

Defined in: src/types/interfaces/storage.interface.ts:792

Deletes a changelog from the index.

Parameters

uri

AtUri

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:925

Deletes a user-provided citation by its record URI.

Parameters

userRecordUri

AtUri

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:694

Deletes an eprint from the index.

Parameters

uri

AtUri

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:979

Deletes a related work record by its URI.

Parameters

uri

AtUri

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:572

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:

  1. DOI (most authoritative)
  2. arXiv ID
  3. Semantic Scholar ID
  4. OpenAlex ID
  5. DBLP ID
  6. OpenReview ID
  7. PubMed ID
  8. 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:719

Retrieves a single changelog entry by URI.

Parameters

uri

AtUri

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:898

Retrieves citations for an eprint.

Parameters

eprintUri

AtUri

AT URI of the eprint

options?

EprintCitationQueryOptions

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

AtUri

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);
}

getEprintsByAuthor()

getEprintsByAuthor(author, options?): Promise<StoredEprint[]>

Defined in: src/types/interfaces/storage.interface.ts:470

Queries eprints by author.

Parameters

author

DID

Author DID

options?

EprintQueryOptions

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:830

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:952

Retrieves related works for an eprint.

Parameters

eprintUri

AtUri

AT URI of the eprint

options?

RelatedWorkQueryOptions

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<readonly IndexedUserTag[]>

Defined in: src/types/interfaces/storage.interface.ts:817

Retrieves user tags for an eprint.

Parameters

eprintUri

AtUri

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:915

Indexes a user-provided citation from the firehose.

Parameters

citation

IndexCitationInput

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:969

Indexes a related work record from the firehose.

Parameters

relatedWork

IndexRelatedWorkInput

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:858

Indexes a user tag record into the user_tags_index table.

Parameters

tag

Tag data to index

cid

CID

createdAt

Date

eprintUri

AtUri

pdsUrl

string

tag

string

taggerDid

DID

uri

AtUri

Returns

Promise<void>

void


isStale()

isStale(uri): Promise<boolean>

Defined in: src/types/interfaces/storage.interface.ts:667

Checks if an indexed record is stale (PDS has newer version).

Parameters

uri

AtUri

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:746

Lists changelogs for a specific eprint with pagination.

Parameters

eprintUri

AtUri

AT URI of the eprint

options?

ChangelogQueryOptions

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}`);
}

listEprintUris()

listEprintUris(options?): Promise<readonly string[]>

Defined in: src/types/interfaces/storage.interface.ts:509

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<readonly string[]>

Defined in: src/types/interfaces/storage.interface.ts:533

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:845

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


storeChangelog()

storeChangelog(changelog): Promise<Result<void, Error>>

Defined in: src/types/interfaces/storage.interface.ts:779

Stores or updates a changelog index record.

Parameters

changelog

StoredChangelog

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

StoredEprint

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:635

Stores an eprint and tracks PDS source in a single transaction.

Parameters

eprint

StoredEprint

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:608

Tracks PDS source for staleness detection.

Parameters

uri

AtUri

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()
);