@truestamp/client
Version:
## Description
225 lines (199 loc) • 6.24 kB
text/typescript
// Copyright © 2020-2023 Truestamp Inc. All rights reserved.
import { z } from 'zod'
import { fromZodError } from 'zod-validation-error'
import { httpGet, httpPost, httpPut } from 'utils'
import {
ApiKeyBody,
ApiKeyBodySchema,
ApiKeyResponse,
Commitment,
CommitmentVerification,
HealthResponse,
ItemRequest,
ItemRequestSchema,
ItemResponse,
} from 'types'
const ClientConfigSchema = z.object({
apiBaseUrl: z
.string()
.url()
.regex(/https:\/\/(api|staging-api|dev-api)\.truestamp\.com/)
.optional(),
apiKey: z.string().min(1),
})
export type ClientConfig = z.infer<typeof ClientConfigSchema>
// Define the API key and base URL as class properties
export class TruestampClient {
private readonly API_KEY: string
private readonly API_VERSION: string
private readonly BASE_URL: string
private readonly BASE_URL_W_VERSION: string
private readonly COMMON_HEADERS: HeadersInit
// In the constructor, initialize the API key and base URL
constructor(config: ClientConfig) {
try {
// Input validation
ClientConfigSchema.parse(config)
} catch (err) {
if (err instanceof z.ZodError) {
const validationError = fromZodError(err)
throw new Error(validationError.message)
} else {
throw err
}
}
const { apiBaseUrl, apiKey } = config
this.API_KEY = apiKey
this.API_VERSION = 'v1'
this.BASE_URL = apiBaseUrl ?? 'https://api.truestamp.com'
this.BASE_URL_W_VERSION = `${this.BASE_URL}/${this.API_VERSION}`
this.COMMON_HEADERS = {
Authorization: `Bearer ${this.API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
}
}
/**
* Retrieve the current health of the API.
* @return An object reflecting the current health of the API.
*/
public async getHealth(): Promise<HealthResponse> {
return await httpGet<HealthResponse>(`${this.BASE_URL_W_VERSION}/health`, {
headers: this.COMMON_HEADERS,
})
}
/**
* Create a new API key for an account.
* @param body The body of the request including a refresh token to be used for key generation.
* @return The new API key along with its description and expiration date.
*/
public async createApiKey(body: ApiKeyBody): Promise<ApiKeyResponse> {
try {
// Input validation
ApiKeyBodySchema.parse(body)
} catch (err) {
if (err instanceof z.ZodError) {
const validationError = fromZodError(err)
throw new Error(validationError.message)
} else {
throw err
}
}
return await httpPost<ApiKeyBody, ApiKeyResponse>(
`${this.BASE_URL_W_VERSION}/apikeys`,
body,
{
headers: this.COMMON_HEADERS,
},
)
}
/**
* Get the current commitment for an Item ID.
* @param id The Item ID that the commitment is for.
* @return A commitment object.
*/
public async getCommitment(id: string): Promise<Commitment> {
return await httpGet<Commitment>(
`${this.BASE_URL_W_VERSION}/commitments/${id}`,
{
headers: this.COMMON_HEADERS,
},
)
}
/**
* Get the verification result for a commitment associated with an Item ID.
* @param id The Item ID for the commitment that should be verified.
* @return A commitment verification object.
*/
public async getCommitmentVerification(
id: string,
): Promise<CommitmentVerification> {
return await httpGet<CommitmentVerification>(
`${this.BASE_URL_W_VERSION}/commitments/${id}/verify`,
{
headers: this.COMMON_HEADERS,
},
)
}
/**
* Create a new Item.
* @param body The Item body.
* @param args An object with additional arguments for the API.
* @param args.skipCF A boolean indicating whether to skip adding Cloudflare request data to the Item.
* @param args.skipOE A boolean indicating whether to skip adding Observable Entropy hash to the Item.
* @return An object containing the ID of the new Item.
*/
public async createItem(
body: ItemRequest,
args?: { skipCF?: boolean; skipOE?: boolean },
): Promise<ItemResponse> {
try {
// Input validation
ItemRequestSchema.parse(body)
} catch (err) {
if (err instanceof z.ZodError) {
const validationError = fromZodError(err)
throw new Error(validationError.message)
} else {
throw err
}
}
const newHeaders: HeadersInit = {}
// Skip adding Cloudflare request data to Item
if (args?.skipCF) {
newHeaders['skip-cf'] = 'true'
}
// Skip adding Observable Entropy hash to Item
if (args?.skipOE) {
newHeaders['skip-oe'] = 'true'
}
return await httpPost<ItemRequest, ItemResponse>(
`${this.BASE_URL_W_VERSION}/items`,
body,
{
headers: { ...this.COMMON_HEADERS, ...newHeaders },
},
)
}
/**
* Update an existing Item specified by an Item ID.
* @param body The updated Item body.
* @param args An object with additional arguments for the API.
* @param args.skipCF A boolean indicating whether to skip adding Cloudflare request data to the Item.
* @param args.skipOE A boolean indicating whether to skip adding Observable Entropy hash to the Item.
* @return An object containing the ID of the updated Item.
*/
public async updateItem(
id: string,
body: ItemRequest,
args?: { skipCF?: boolean; skipOE?: boolean },
): Promise<ItemResponse> {
try {
// Input validation
ItemRequestSchema.parse(body)
} catch (err) {
if (err instanceof z.ZodError) {
const validationError = fromZodError(err)
throw new Error(validationError.message)
} else {
throw err
}
}
const newHeaders: HeadersInit = {}
// Skip adding Cloudflare request data to Item
if (args?.skipCF) {
newHeaders['skip-cf'] = 'true'
}
// Skip adding Observable Entropy hash to Item
if (args?.skipOE) {
newHeaders['skip-oe'] = 'true'
}
return await httpPut<ItemRequest, ItemResponse>(
`${this.BASE_URL_W_VERSION}/items/${id}`,
body,
{
headers: { ...this.COMMON_HEADERS, ...newHeaders },
},
)
}
}