import { inject, injectable } from "@codemation/core"; import { PairedFetch } from "../pairing/PairedFetch"; import type { PairingConfig } from "../pairing/pairing.types"; import { PairingConfigToken } from "../pairing/PairingConfigToken"; import { BrokerRefreshInvalidGrantError } from "./BrokerRefreshInvalidGrantError"; import { BrokerRefreshError } from "./BrokerRefreshError"; export type BrokerRefreshResult = Readonly<{ accessToken: string; expiresAt: number; scopesGranted: ReadonlyArray; refreshToken?: string; }>; export { BrokerRefreshInvalidGrantError, BrokerRefreshError }; @injectable() export class BrokerClient { constructor( @inject(PairedFetch) private readonly pairedFetch: PairedFetch, @inject(PairingConfigToken) private readonly pairingConfig: PairingConfig, ) {} async refreshCredential( args: Readonly<{ credentialInstanceId: string; refreshToken: string }>, ): Promise { const url = `${this.pairingConfig.controlPlaneUrl}/internal/credentials/refresh`; const response = await this.pairedFetch.post(url, { credentialInstanceId: args.credentialInstanceId, refreshToken: args.refreshToken, }); if (response.status === 410) { throw new BrokerRefreshInvalidGrantError(args.credentialInstanceId); } if (!response.ok) { throw new BrokerRefreshError(args.credentialInstanceId, response.status); } return (await response.json()) as BrokerRefreshResult; } }