chatgpt-api/packages/api-client/src/agentic-api-client.ts

908 wiersze
24 KiB
TypeScript
Czysty Zwykły widok Historia

2025-05-31 08:41:35 +00:00
import type {
AdminConsumer,
2025-05-31 08:41:35 +00:00
AdminDeployment,
AuthSession,
2025-05-31 08:41:35 +00:00
Consumer,
Deployment,
openapi,
Project,
Team,
TeamMember,
User
} from '@agentic/platform-types'
2025-05-20 16:28:31 +00:00
import type { Simplify } from 'type-fest'
import { assert, sanitizeSearchParams } from '@agentic/platform-core'
2025-05-20 16:28:31 +00:00
import defaultKy, { type KyInstance } from 'ky'
import type { OnUpdateAuthSessionFunction } from './types'
2025-05-20 16:28:31 +00:00
export class AgenticApiClient {
2025-05-20 17:06:39 +00:00
static readonly DEFAULT_API_BASE_URL = 'https://api.agentic.so'
public readonly apiBaseUrl: string
2025-05-28 19:03:42 +00:00
public readonly apiKey?: string
2025-05-24 15:02:24 +00:00
public readonly ky: KyInstance
public readonly onUpdateAuth?: OnUpdateAuthSessionFunction
2025-06-16 01:21:00 +00:00
// protected _authClient: AuthClient
protected _authSession?: AuthSession
2025-05-20 16:28:31 +00:00
constructor({
2025-05-20 17:06:39 +00:00
apiBaseUrl = AgenticApiClient.DEFAULT_API_BASE_URL,
2025-05-28 19:03:42 +00:00
apiKey,
2025-05-24 15:02:24 +00:00
ky = defaultKy,
onUpdateAuth
2025-05-20 16:28:31 +00:00
}: {
2025-05-20 17:06:39 +00:00
apiBaseUrl?: string
2025-05-28 19:03:42 +00:00
apiKey?: string
2025-05-20 16:28:31 +00:00
ky?: KyInstance
2025-05-24 15:02:24 +00:00
onUpdateAuth?: OnUpdateAuthSessionFunction
} = {}) {
2025-05-22 17:19:04 +00:00
assert(apiBaseUrl, 'AgenticApiClient missing required "apiBaseUrl"')
2025-05-24 15:02:24 +00:00
2025-05-20 17:06:39 +00:00
this.apiBaseUrl = apiBaseUrl
2025-05-28 19:03:42 +00:00
this.apiKey = apiKey
2025-05-24 15:02:24 +00:00
this.onUpdateAuth = onUpdateAuth
2025-06-16 01:21:00 +00:00
// this._authClient = createAuthClient({
// issuer: apiBaseUrl,
// clientId: 'agentic-api-client'
// })
2025-05-20 17:06:39 +00:00
this.ky = ky.extend({
prefixUrl: apiBaseUrl,
// Set a longer timeout on localhost to account for backend debugging / breakpoints.
timeout: apiBaseUrl.startsWith('http://localhost') ? 120_000 : undefined,
2025-05-28 19:03:42 +00:00
headers: apiKey
? {
Authorization: `Bearer ${apiKey}`
}
: undefined,
2025-05-24 15:02:24 +00:00
hooks: {
beforeRequest: [
async (request) => {
if (!this.apiKey && this._authSession) {
2025-06-03 09:48:24 +00:00
// Always verify freshness of auth tokens before making a request
// TODO: handle refreshing auth tokens
// await this.verifyAuthAndRefreshIfNecessary()
// assert(this._authSession, 'Not authenticated')
2025-06-03 09:48:24 +00:00
request.headers.set(
'Authorization',
`Bearer ${this._authSession.token}`
2025-06-03 09:48:24 +00:00
)
}
2025-05-24 15:02:24 +00:00
}
]
}
2025-05-20 17:06:39 +00:00
})
2025-05-24 15:02:24 +00:00
}
2025-05-22 17:19:04 +00:00
2025-05-24 15:02:24 +00:00
get isAuthenticated(): boolean {
return !!this._authSession
2025-05-24 15:02:24 +00:00
}
get authSession(): AuthSession | undefined {
return structuredClone(this._authSession)
2025-05-20 16:28:31 +00:00
}
set authSession(authSession: AuthSession | undefined) {
// TODO: validate auth sessino with zod
this._authSession = structuredClone(authSession)
2025-05-22 17:23:39 +00:00
}
2025-06-16 01:21:00 +00:00
// async verifyAuthAndRefreshIfNecessary(): Promise<AuthSession> {
// this._ensureNoApiKey()
// if (!this._authTokens) {
// throw new Error('This method requires authentication.')
// }
// const verified = await this._authClient.verify(
// authSubjects,
// this._authTokens.access,
// {
// refresh: this._authTokens.refresh
// }
// )
// if (verified.err) {
// throw verified.err
// }
// if (verified.tokens) {
// this._authTokens = verified.tokens
// }
// this.onUpdateAuth?.({
// session: this._authTokens,
// user: verified.subject.properties
// })
// return verified.subject.properties
// }
// async exchangeAuthCode({
// code,
// redirectUri,
// verifier
// }: {
// code: string
// redirectUri: string
// verifier?: string
// }): Promise<AuthSession> {
// this._ensureNoApiKey()
// const result = await this._authClient.exchange(code, redirectUri, verifier)
// if (result.err) {
// throw result.err
// }
// this._authTokens = result.tokens
// return this.verifyAuthAndRefreshIfNecessary()
// }
// async initAuthFlow({
// redirectUri,
// provider
// }: {
// redirectUri: string
// provider: 'github'
// }): Promise<AuthorizeResult> {
// this._ensureNoApiKey()
// return this._authClient.authorize(redirectUri, 'code', {
// provider
// })
// }
2025-05-24 15:02:24 +00:00
async logout(): Promise<void> {
this._authSession = undefined
2025-05-24 15:02:24 +00:00
this.onUpdateAuth?.()
}
2025-05-28 19:03:42 +00:00
protected _ensureNoApiKey() {
assert(
!this.apiKey,
'AgenticApiClient was initialized with an API key. This method is only supported with wnon-API-key-based authentication.'
)
}
/** Signs in with email + password. */
async signInWithPassword(
json: OperationBody<'signInWithPassword'>
// searchParams?: OperationParameters<'signInWithPassword'>
): Promise<AuthSession> {
this._authSession = await this.ky
2025-06-16 01:21:00 +00:00
.post('v1/auth/password/signin', { json })
.json<AuthSession>()
this.onUpdateAuth?.(this._authSession)
return this._authSession
}
/** Registers a new account with username + email + password. */
async signUpWithPassword(
json: OperationBody<'signUpWithPassword'>
// searchParams?: OperationParameters<'signUpWithPassword'>
): Promise<AuthSession> {
this._authSession = await this.ky
2025-06-16 01:21:00 +00:00
.post('v1/auth/password/signup', { json })
.json()
this.onUpdateAuth?.(this._authSession)
2025-06-16 01:21:00 +00:00
return this._authSession
}
// TODO
async initAuthFlowWithGitHub({
redirectUri,
scope = 'user:email',
clientId = 'Iv23lizZv3CnggDT7JED'
}: {
redirectUri: string
scope?: string
clientId?: string
}): Promise<string> {
2025-06-16 01:54:23 +00:00
const url = new URL(`${this.apiBaseUrl}/v1/auth/github/init`)
2025-06-16 01:21:00 +00:00
url.searchParams.append('client_id', clientId)
url.searchParams.append('scope', scope)
2025-06-16 01:54:23 +00:00
url.searchParams.append('redirect_uri', redirectUri)
2025-06-16 01:21:00 +00:00
return url.toString()
}
// TODO
async exchangeOAuthCodeWithGitHub(
json: OperationBody<'exchangeOAuthCodeWithGitHub'>
): Promise<AuthSession> {
2025-06-16 01:54:23 +00:00
this._authSession = await this.ky
.post('v1/auth/github/exchange', { json })
.json()
2025-06-16 01:21:00 +00:00
this.onUpdateAuth?.(this._authSession)
return this._authSession
}
/** Gets the currently authenticated user. */
2025-05-30 18:05:30 +00:00
async getMe(): Promise<User> {
// const user = await this.verifyAuthAndRefreshIfNecessary()
const userId = this._authSession?.user.id
assert(userId, 'This method requires authentication.')
2025-05-24 15:02:24 +00:00
return this.ky.get(`v1/users/${userId}`).json()
2025-05-24 15:02:24 +00:00
}
/** Gets a user by ID. */
2025-05-20 16:28:31 +00:00
async getUser({
userId,
...searchParams
2025-05-30 18:05:30 +00:00
}: OperationParameters<'getUser'>): Promise<User> {
2025-05-20 17:06:39 +00:00
return this.ky.get(`v1/users/${userId}`, { searchParams }).json()
2025-05-20 16:28:31 +00:00
}
/** Updates a user. */
2025-05-20 16:28:31 +00:00
async updateUser(
user: OperationBody<'updateUser'>,
{ userId, ...searchParams }: OperationParameters<'updateUser'>
2025-05-30 18:05:30 +00:00
): Promise<User> {
2025-05-20 16:28:31 +00:00
return this.ky
2025-05-20 17:06:39 +00:00
.post(`v1/users/${userId}`, { json: user, searchParams })
.json()
}
/** Lists all teams the authenticated user belongs to. */
2025-05-28 20:29:35 +00:00
async listTeams(
searchParams: OperationParameters<'listTeams'> = {}
2025-05-30 18:05:30 +00:00
): Promise<Array<Team>> {
return this.ky
.get('v1/teams', { searchParams: sanitizeSearchParams(searchParams) })
.json()
2025-05-20 17:06:39 +00:00
}
/** Creates a team. */
2025-05-20 17:06:39 +00:00
async createTeam(
team: OperationBody<'createTeam'>,
2025-05-28 20:29:35 +00:00
searchParams: OperationParameters<'createTeam'> = {}
2025-05-30 18:05:30 +00:00
): Promise<Team> {
return this.ky
.post('v1/teams', {
json: team,
searchParams: sanitizeSearchParams(searchParams)
})
.json()
2025-05-20 17:06:39 +00:00
}
/** Gets a team by ID. */
2025-05-20 17:06:39 +00:00
async getTeam({
teamId,
...searchParams
2025-05-30 18:05:30 +00:00
}: OperationParameters<'getTeam'>): Promise<Team> {
2025-05-20 17:06:39 +00:00
return this.ky.get(`v1/teams/${teamId}`, { searchParams }).json()
}
/** Updates a team. */
2025-05-20 17:06:39 +00:00
async updateTeam(
team: OperationBody<'updateTeam'>,
{ teamId, ...searchParams }: OperationParameters<'updateTeam'>
2025-05-30 18:05:30 +00:00
): Promise<Team> {
2025-05-20 17:06:39 +00:00
return this.ky
.post(`v1/teams/${teamId}`, { json: team, searchParams })
.json()
}
/** Deletes a team by ID. */
2025-05-20 17:06:39 +00:00
async deleteTeam({
teamId,
...searchParams
2025-05-30 18:05:30 +00:00
}: OperationParameters<'deleteTeam'>): Promise<Team> {
2025-05-20 17:06:39 +00:00
return this.ky.delete(`v1/teams/${teamId}`, { searchParams }).json()
}
/** Creates a new team member. */
2025-05-20 17:06:39 +00:00
async createTeamMember(
member: OperationBody<'createTeamMember'>,
{ teamId, ...searchParams }: OperationParameters<'createTeamMember'>
2025-05-30 18:05:30 +00:00
): Promise<TeamMember> {
2025-05-20 17:06:39 +00:00
return this.ky
.post(`v1/teams/${teamId}/members`, { json: member, searchParams })
.json()
}
/** Updates a team member. */
2025-05-20 17:06:39 +00:00
async updateTeamMember(
member: OperationBody<'updateTeamMember'>,
{ teamId, userId, ...searchParams }: OperationParameters<'updateTeamMember'>
2025-05-30 18:05:30 +00:00
): Promise<TeamMember> {
2025-05-20 17:06:39 +00:00
return this.ky
.post(`v1/teams/${teamId}/members/${userId}`, {
json: member,
searchParams
})
.json()
}
/** Deletes a team member. */
2025-05-20 17:06:39 +00:00
async deleteTeamMember({
teamId,
userId,
...searchParams
2025-05-30 18:05:30 +00:00
}: OperationParameters<'deleteTeamMember'>): Promise<TeamMember> {
2025-05-20 17:06:39 +00:00
return this.ky
.delete(`v1/teams/${teamId}/members/${userId}`, { searchParams })
.json()
}
/** Lists projects that have been published publicly to the marketplace. */
async listPublicProjects<
TPopulate extends NonNullable<
OperationParameters<'listPublicProjects'>['populate']
>[number]
>(
searchParams: OperationParameters<'listPublicProjects'> & {
populate?: TPopulate[]
} = {}
): Promise<Array<PopulateProject<TPopulate>>> {
return this.ky
2025-06-18 00:39:02 +00:00
.get('v1/projects/public', {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/**
* Gets a public project by ID. The project must be publicly available on
* the marketplace.
*/
async getPublicProject<
TPopulate extends NonNullable<
OperationParameters<'getPublicProject'>['populate']
>[number]
>({
projectId,
...searchParams
}: OperationParameters<'getPublicProject'> & {
populate?: TPopulate[]
}): Promise<PopulateProject<TPopulate>> {
return this.ky
.get(`v1/projects/public/${projectId}`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/**
* Gets a public project by its identifier. The project must be publicly
* available on the marketplace.
*/
async getPublicProjectByIdentifier<
TPopulate extends NonNullable<
OperationParameters<'getPublicProjectByIdentifier'>['populate']
>[number]
>(
searchParams: OperationParameters<'getPublicProjectByIdentifier'> & {
populate?: TPopulate[]
}
): Promise<PopulateProject<TPopulate>> {
return this.ky
.get('v1/projects/public/by-identifier', {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/**
* Lists projects the authenticated user has access to.
*/
2025-05-28 20:29:35 +00:00
async listProjects<
TPopulate extends NonNullable<
OperationParameters<'listProjects'>['populate']
2025-05-30 18:05:30 +00:00
>[number]
2025-05-28 20:29:35 +00:00
>(
searchParams: OperationParameters<'listProjects'> & {
populate?: TPopulate[]
} = {}
2025-05-30 18:05:30 +00:00
): Promise<Array<PopulateProject<TPopulate>>> {
2025-05-20 18:20:00 +00:00
return this.ky
.get(`v1/projects`, {
searchParams: sanitizeSearchParams(searchParams)
})
2025-05-20 18:20:00 +00:00
.json()
2025-05-20 17:06:39 +00:00
}
/** Creates a new project. */
2025-05-20 17:06:39 +00:00
async createProject(
project: OperationBody<'createProject'>,
2025-05-28 20:29:35 +00:00
searchParams: OperationParameters<'createProject'> = {}
2025-05-30 18:05:30 +00:00
): Promise<Project> {
2025-05-20 17:06:39 +00:00
return this.ky.post('v1/projects', { json: project, searchParams }).json()
}
/**
* Gets a project by ID. Authenticated user must have access to the project.
*/
2025-05-28 20:29:35 +00:00
async getProject<
TPopulate extends NonNullable<
OperationParameters<'getProject'>['populate']
2025-05-30 18:05:30 +00:00
>[number]
2025-05-28 20:29:35 +00:00
>({
2025-05-20 17:06:39 +00:00
projectId,
...searchParams
2025-05-28 20:29:35 +00:00
}: OperationParameters<'getProject'> & {
populate?: TPopulate[]
2025-05-30 18:05:30 +00:00
}): Promise<PopulateProject<TPopulate>> {
2025-05-20 18:20:00 +00:00
return this.ky
.get(`v1/projects/${projectId}`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
2025-05-20 17:06:39 +00:00
}
/**
* Gets a project by its identifier. Authenticated user must have access to
* the project.
*/
2025-05-28 20:29:35 +00:00
async getProjectByIdentifier<
TPopulate extends NonNullable<
OperationParameters<'getProjectByIdentifier'>['populate']
2025-05-30 18:05:30 +00:00
>[number]
2025-05-28 20:29:35 +00:00
>(
searchParams: OperationParameters<'getProjectByIdentifier'> & {
populate?: TPopulate[]
}
2025-05-30 18:05:30 +00:00
): Promise<PopulateProject<TPopulate>> {
2025-05-26 18:23:16 +00:00
return this.ky
.get(`v1/projects/by-identifier`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/**
* Updates a project. Authenticated user must have access to the project.
*/
2025-05-20 17:06:39 +00:00
async updateProject(
project: OperationBody<'updateProject'>,
{ projectId, ...searchParams }: OperationParameters<'updateProject'>
2025-05-30 18:05:30 +00:00
): Promise<Project> {
2025-05-20 17:06:39 +00:00
return this.ky
.post(`v1/projects/${projectId}`, { json: project, searchParams })
.json()
}
/** Gets a consumer by ID. */
2025-05-30 12:08:05 +00:00
async getConsumer<
TPopulate extends NonNullable<
OperationParameters<'getConsumer'>['populate']
2025-05-30 18:05:30 +00:00
>[number]
2025-05-30 12:08:05 +00:00
>({
2025-05-20 17:06:39 +00:00
consumerId,
...searchParams
2025-05-30 12:08:05 +00:00
}: OperationParameters<'getConsumer'> & {
populate?: TPopulate[]
2025-05-30 18:05:30 +00:00
}): Promise<PopulateConsumer<TPopulate>> {
2025-05-20 18:20:00 +00:00
return this.ky
.get(`v1/consumers/${consumerId}`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
2025-05-20 17:06:39 +00:00
}
/** Gets a consumer by ID. */
async getConsumerByProjectIdentifier<
TPopulate extends NonNullable<
OperationParameters<'getConsumerByProjectIdentifier'>['populate']
>[number]
>(
searchParams: OperationParameters<'getConsumerByProjectIdentifier'> & {
populate?: TPopulate[]
}
): Promise<PopulateConsumer<TPopulate>> {
return this.ky
.get(`v1/consumers/by-project-identifier`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/**
* Updates a consumer's subscription to a different deployment or pricing
* plan. Set `plan` to undefined to cancel the subscription.
*/
2025-05-20 17:06:39 +00:00
async updateConsumer(
consumer: OperationBody<'updateConsumer'>,
{ consumerId, ...searchParams }: OperationParameters<'updateConsumer'>
2025-05-30 18:05:30 +00:00
): Promise<Consumer> {
2025-05-20 17:06:39 +00:00
return this.ky
.post(`v1/consumers/${consumerId}`, { json: consumer, searchParams })
.json()
}
/**
* Creates a new consumer by subscribing a customer to a project.
*
* @deprecated Use `createConsumerCheckoutSession` instead. This method will
* be removed in a future version.
*/
2025-05-20 17:06:39 +00:00
async createConsumer(
consumer: OperationBody<'createConsumer'>,
2025-05-28 20:29:35 +00:00
searchParams: OperationParameters<'createConsumer'> = {}
2025-05-30 18:05:30 +00:00
): Promise<Consumer> {
return this.ky
.post('v1/consumers', {
json: consumer,
searchParams: sanitizeSearchParams(searchParams)
})
.json()
2025-05-20 17:06:39 +00:00
}
/**
* Creates a Stripe Checkout Session for a customer to modify their
* subscription to a project.
*/
async createConsumerCheckoutSession(
consumer: OperationBody<'createConsumerCheckoutSession'>,
searchParams: OperationParameters<'createConsumerCheckoutSession'> = {}
): Promise<{
checkoutSession: {
id: string
url: string
}
consumer: Consumer
}> {
return this.ky
.post('v1/consumers/checkout', {
json: consumer,
searchParams: sanitizeSearchParams(searchParams)
2025-06-20 18:29:24 +00:00
})
.json()
}
/**
* Creates a Stripe Billing Portal Session for the authenticated user.
*/
async createBillingPortalSession(
searchParams: OperationParameters<'createBillingPortalSession'> = {}
): Promise<{
url: string
}> {
return this.ky
.post(`v1/consumers/billing-portal`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/**
* Creates a Stripe Billing Portal Session for a customer.
*/
async createConsumerBillingPortalSession({
consumerId,
...searchParams
}: OperationParameters<'createConsumerBillingPortalSession'>): Promise<{
url: string
}> {
return this.ky
.post(`v1/consumers/${consumerId}/billing-portal`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/** Refreshes a consumer's API token. */
2025-05-20 17:06:39 +00:00
async refreshConsumerToken({
consumerId,
...searchParams
2025-05-30 18:05:30 +00:00
}: OperationParameters<'refreshConsumerToken'>): Promise<Consumer> {
2025-05-20 17:06:39 +00:00
return this.ky
.post(`v1/consumers/${consumerId}/refresh-token`, { searchParams })
.json()
}
/** Lists all of the customers. */
2025-05-30 12:08:05 +00:00
async listConsumers<
TPopulate extends NonNullable<
OperationParameters<'listConsumers'>['populate']
2025-05-30 18:05:30 +00:00
>[number]
>(
searchParams: OperationParameters<'listConsumers'> & {
populate?: TPopulate[]
} = {}
): Promise<Array<PopulateConsumer<TPopulate>>> {
return this.ky
.get('v1/consumers', {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/** Lists all of the customers for a project. */
async listConsumersForProject<
TPopulate extends NonNullable<
OperationParameters<'listConsumersForProject'>['populate']
>[number]
2025-05-30 12:08:05 +00:00
>({
2025-05-20 17:06:39 +00:00
projectId,
...searchParams
}: OperationParameters<'listConsumersForProject'> & {
2025-05-30 12:08:05 +00:00
populate?: TPopulate[]
2025-05-30 18:05:30 +00:00
}): Promise<Array<PopulateConsumer<TPopulate>>> {
2025-05-20 17:06:39 +00:00
return this.ky
2025-05-20 18:20:00 +00:00
.get(`v1/projects/${projectId}/consumers`, {
searchParams: sanitizeSearchParams(searchParams)
})
2025-05-20 17:06:39 +00:00
.json()
}
/** Gets a deployment by its ID. */
2025-05-28 20:29:35 +00:00
async getDeployment<
TPopulate extends NonNullable<
OperationParameters<'getDeployment'>['populate']
2025-05-30 18:05:30 +00:00
>[number]
2025-05-28 20:29:35 +00:00
>({
2025-05-20 17:06:39 +00:00
deploymentId,
...searchParams
2025-05-28 20:29:35 +00:00
}: OperationParameters<'getDeployment'> & {
populate?: TPopulate[]
2025-05-30 18:05:30 +00:00
}): Promise<PopulateDeployment<TPopulate>> {
2025-05-20 17:06:39 +00:00
return this.ky
2025-05-20 18:20:00 +00:00
.get(`v1/deployments/${deploymentId}`, {
searchParams: sanitizeSearchParams(searchParams)
})
2025-05-20 17:06:39 +00:00
.json()
}
/** Gets a deployment by its identifier. */
2025-05-28 20:29:35 +00:00
async getDeploymentByIdentifier<
TPopulate extends NonNullable<
OperationParameters<'getDeploymentByIdentifier'>['populate']
2025-05-30 18:05:30 +00:00
>[number]
2025-05-28 20:29:35 +00:00
>(
searchParams: OperationParameters<'getDeploymentByIdentifier'> & {
populate?: TPopulate[]
}
2025-05-30 18:05:30 +00:00
): Promise<PopulateDeployment<TPopulate>> {
2025-05-26 17:35:19 +00:00
return this.ky
.get(`v1/deployments/by-identifier`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/** Gets a public deployment by its identifier. */
async getPublicDeploymentByIdentifier<
TPopulate extends NonNullable<
OperationParameters<'getPublicDeploymentByIdentifier'>['populate']
>[number]
>(
searchParams: OperationParameters<'getPublicDeploymentByIdentifier'> & {
populate?: TPopulate[]
}
): Promise<PopulateDeployment<TPopulate>> {
return this.ky
.get(`v1/deployments/public/by-identifier`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/** Updates a deployment. */
2025-05-20 17:06:39 +00:00
async updateDeployment(
deployment: OperationBody<'updateDeployment'>,
{ deploymentId, ...searchParams }: OperationParameters<'updateDeployment'>
2025-05-30 18:05:30 +00:00
): Promise<Deployment> {
2025-05-20 17:06:39 +00:00
return this.ky
.post(`v1/deployments/${deploymentId}`, {
json: deployment,
searchParams
})
.json()
}
/**
* Lists deployments the user or team has access to, optionally filtering by
* project.
*/
2025-05-28 20:29:35 +00:00
async listDeployments<
TPopulate extends NonNullable<
OperationParameters<'listDeployments'>['populate']
2025-05-30 18:05:30 +00:00
>[number]
2025-05-28 20:29:35 +00:00
>(
searchParams: OperationParameters<'listDeployments'> & {
populate?: TPopulate[]
} = {}
2025-05-30 18:05:30 +00:00
): Promise<Array<PopulateDeployment<TPopulate>>> {
2025-05-20 18:20:00 +00:00
return this.ky
.get('v1/deployments', {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
2025-05-20 17:06:39 +00:00
}
/** Creates a new deployment within a project. */
2025-05-20 17:06:39 +00:00
async createDeployment(
deployment: OperationBody<'createDeployment'>,
2025-05-28 20:29:35 +00:00
searchParams: OperationParameters<'createDeployment'> = {}
2025-05-30 18:05:30 +00:00
): Promise<Deployment> {
2025-05-20 17:06:39 +00:00
return this.ky
.post('v1/deployments', { json: deployment, searchParams })
.json()
}
/** Publishes a deployment. */
2025-05-20 17:06:39 +00:00
async publishDeployment(
deployment: OperationBody<'publishDeployment'>,
{ deploymentId, ...searchParams }: OperationParameters<'publishDeployment'>
2025-05-30 18:05:30 +00:00
): Promise<Deployment> {
2025-05-20 17:06:39 +00:00
return this.ky
.post(`v1/deployments/${deploymentId}/publish`, {
json: deployment,
searchParams
})
.json()
}
/**
* Gets a consumer by API token. This method is admin-only.
*
* @internal
*/
2025-05-30 12:08:05 +00:00
async adminGetConsumerByToken<
TPopulate extends NonNullable<
OperationParameters<'adminGetConsumerByToken'>['populate']
2025-05-30 18:05:30 +00:00
>[number]
2025-05-30 12:08:05 +00:00
>({
2025-05-20 17:06:39 +00:00
token,
...searchParams
2025-05-30 12:08:05 +00:00
}: OperationParameters<'adminGetConsumerByToken'> & {
populate?: TPopulate[]
}): Promise<PopulateConsumer<TPopulate, AdminConsumer>> {
2025-05-20 17:06:39 +00:00
return this.ky
2025-05-20 18:20:00 +00:00
.get(`v1/admin/consumers/tokens/${token}`, {
searchParams: sanitizeSearchParams(searchParams)
})
2025-05-20 16:28:31 +00:00
.json()
}
2025-05-30 12:08:05 +00:00
/**
* Activates a consumer signifying that at least one API call has been made
* using the consumer's API token. This method is idempotent and admin-only.
*
* @internal
*/
async adminActivateConsumer({
consumerId,
...searchParams
}: OperationParameters<'adminActivateConsumer'>): Promise<AdminConsumer> {
return this.ky
.put(`v1/admin/consumers/${consumerId}/activate`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
/**
* Gets a deployment by its public identifier. This method is admin-only.
*
* @internal
*/
2025-05-30 12:08:05 +00:00
async adminGetDeploymentByIdentifier<
TPopulate extends NonNullable<
OperationParameters<'adminGetDeploymentByIdentifier'>['populate']
2025-05-30 18:05:30 +00:00
>[number]
2025-05-30 12:08:05 +00:00
>(
searchParams: OperationParameters<'adminGetDeploymentByIdentifier'> & {
populate?: TPopulate[]
}
2025-05-30 18:05:30 +00:00
): Promise<PopulateDeployment<TPopulate, AdminDeployment>> {
2025-05-30 12:08:05 +00:00
return this.ky
.get(`v1/admin/deployments/by-identifier`, {
searchParams: sanitizeSearchParams(searchParams)
})
.json()
}
2025-05-20 16:28:31 +00:00
}
2025-05-31 08:41:35 +00:00
type Operations = openapi.operations
2025-05-20 16:28:31 +00:00
type OperationParameters<
2025-05-31 08:41:35 +00:00
T extends keyof Operations,
Q = NonNullable<Operations[T]['parameters']['query']>,
P = NonNullable<Operations[T]['parameters']['path']>
2025-05-20 16:28:31 +00:00
> = Simplify<
2025-05-20 18:20:00 +00:00
([Q] extends [never] ? unknown : Q) & ([P] extends [never] ? unknown : P)
2025-05-20 16:28:31 +00:00
>
2025-05-30 18:05:30 +00:00
// Currently unused because some types need customization (e.g. Deployment) over
// the default OpenAPI types.
2025-05-31 08:41:35 +00:00
// type OperationResponse<T extends keyof Operations> =
// Operations[T]['responses'][200]['content']['application/json']
2025-05-20 16:28:31 +00:00
type OperationKeysWithRequestBody = {
2025-05-31 08:41:35 +00:00
[K in keyof Operations]: Operations[K]['requestBody'] extends {
2025-05-20 16:28:31 +00:00
content: {
'application/json': unknown
}
}
? K
: never
2025-05-31 08:41:35 +00:00
}[keyof Operations]
2025-05-20 16:28:31 +00:00
type OperationBody<
T extends OperationKeysWithRequestBody,
B extends
| object
2025-05-31 08:41:35 +00:00
| undefined = Operations[T]['requestBody']['content']['application/json']
2025-05-20 16:28:31 +00:00
> = B
2025-05-28 20:29:35 +00:00
2025-05-30 18:05:30 +00:00
type PopulateProject<TPopulate> = Simplify<
Project &
(TPopulate extends 'user'
? {
user: User
}
: unknown) &
(TPopulate extends 'team'
? {
team: Team
}
: unknown) &
(TPopulate extends 'lastPublishedDeployment'
? {
lastPublishedDeployment?: Deployment
}
: unknown) &
(TPopulate extends 'lastDeployment'
? {
lastDeployment?: Deployment
}
: unknown)
>
2025-05-28 20:29:35 +00:00
2025-05-30 18:05:30 +00:00
type PopulateDeployment<
TPopulate,
TDeployment extends Deployment = Deployment
> = Simplify<
TDeployment &
(TPopulate extends 'user'
? {
user: User
}
: unknown) &
(TPopulate extends 'team'
? {
team: Team
}
: unknown) &
(TPopulate extends 'project'
? {
project: Project
}
: unknown)
>
2025-05-30 12:08:05 +00:00
type PopulateConsumer<
TPopulate,
TConsumer extends Consumer = Consumer
> = Simplify<
TConsumer &
2025-05-30 18:05:30 +00:00
(TPopulate extends 'user'
? {
user: User
}
: unknown) &
(TPopulate extends 'project'
? {
project: Project
}
: unknown) &
(TPopulate extends 'deployment'
? {
deployment: Deployment
}
: unknown)
>