Saltearse al contenido

Search Client Implementation

Esta página aún no está disponible en tu idioma.

/**
You need to install `typesense` to get the types right.
npm install typesense --save-dev
And then create the instance of the client
@example
const API_KEY = "ryl_sk_YOUR_SECRET_KEY";
const client = new SearchClient({ apiKey: API_KEY });
// ...
const searchResult = await client.searchAll("Alice");
*/
import type {
SearchOptions,
SearchParams,
SearchParamsWithPreset,
SearchResponse,
} from "typesense/lib/Typesense/Documents";
export class SearchClient {
private HOST: string;
private API_KEY: string;
private RAW_RESPONSES: boolean;
static DEFAULT_API_PATH = "/v0/provenance/search";
constructor(
{
apiKey = "",
host = `https://api.royal.io/${SearchClient.DEFAULT_API_PATH}`,
rawResponses = false,
} = {}
) {
this.HOST = host;
this.API_KEY = apiKey;
this.RAW_RESPONSES = rawResponses;
}
public async performSearch<T extends {}>(
searchParameters: SearchParams | SearchParamsWithPreset,
options: SearchOptions = {}
): Promise<PerformSearchResponse<T>> {
try {
const rawResults = await fetch(this.HOST, {
headers: {
"Content-Type": "application/json",
...(this.API_KEY ? { Authorization: `Bearer ${this.API_KEY}` } : {}),
},
method: "POST",
body: JSON.stringify({
searchParameters,
options,
}),
});
if (
rawResults.status !== 200 ||
rawResults.headers.get("Content-Type")?.startsWith("text/")
) {
const errorResult = await rawResults.text();
throw new Error(errorResult);
}
const results = await rawResults.json();
if (this.RAW_RESPONSES) {
return results as PerformSearchResponse<T>;
}
return {
data: ((results as SearchResponse<T>).hits || []).map(
(hit) => hit.document as T
),
total: (results as SearchResponse<T>).found,
numPages: Math.ceil((results as SearchResponse<T>).found / PAGE_SIZE),
};
} catch (e) {
console.error("Search failed: ", e);
return {
data: [],
total: 0,
numPages: 0,
};
}
}
public searchAll(q = "", page = 1, perPage = PAGE_SIZE) {
return this.performSearch<
AccountDocumentType | ProvenanceClaimDocumentType
>({
q,
query_by: "username,psqlId,contentHash,metadata.name,custody",
page,
per_page: perPage,
});
}
public searchAccounts(q = "", page = 1, perPage = PAGE_SIZE) {
return this.performSearch<AccountDocumentType>({
q,
query_by: "username,psqlId,custody",
filter_by: "type:account",
page,
per_page: perPage,
});
}
public searchClaims(q = "", page = 1, perPage = PAGE_SIZE) {
return this.performSearch<ProvenanceClaimDocumentType>({
q,
query_by: "metadata.name,originatorUsername,psqlId,contentHash",
filter_by: "type:provenanceClaim",
page,
per_page: perPage,
});
}
}
const PAGE_SIZE = 10;
type AccountDocumentType = {
type: "account";
id: string;
psqlId: string;
username: string;
custody: string;
provenanceClaimCount: number;
originatedProvenanceClaimCount: number;
registeredProvenanceClaimCount: number;
dayBucket: number;
hourBucket: number;
recovery: string;
createdAt: string;
updatedAt: string;
};
type ProvenanceClaimDocumentType = {
type: 'provenanceClaim';
id: string;
psqlId: string;
originatorAddress: string;
originatorId: string;
originatorUsername: string;
registrarAddress: string;
registrarId: string;
registrarUsername: string;
blockNumber: string;
contentHash: string;
transactionHash: string;
transactionIndex: number;
nftContract?: string;
nftTokenId?: string;
dayBucket: number;
hourBucket: number;
metadata?: PCMetadataType;
createdAt: string;
updatedAt: string;
};
type PCMetadataType = Record<string, any> & {
name?: string;
description?: string;
image?: string;
animation_url?: string;
external_url?: string;
attributes?: Array<any>;
royal?: {
provenance?: {
attributes?: Array<any>;
content_hash?: string;
file_locations?: Array<{
url: string;
}>;
title?: string;
};
};
};
type PerformSearchResponse<T> = {
data: T[];
total: number;
numPages: number;
};