Skip to content

Instantly share code, notes, and snippets.

@cj

cj/api.ts Secret

Created June 4, 2021 19:21
Show Gist options
  • Save cj/073baeb3eb07257e7f27a6df0c90419b to your computer and use it in GitHub Desktop.
Save cj/073baeb3eb07257e7f27a6df0c90419b to your computer and use it in GitHub Desktop.
import axios from 'redaxios'
import querystring from 'querystring'
import camelCaseKeys from 'camelcase-keys'
import { Ctx } from 'blitz'
import _ from 'lodash'
import SuperJson from 'superjson'
import { EpcStoreState } from './stores/epc'
const { EPC__API_BASE_URI, EPC__PARTNER_CLIENT_ID, EPC__PARTNER_CLIENT_SECRET } = process.env
export class EpcError extends Error {
name = 'EpcError'
code = undefined
constructor({ code }) {
super()
this.code = code
}
}
// Register with SuperJson serializer so it's reconstructed on the client
SuperJson.registerClass(EpcError)
SuperJson.allowErrorProps('code')
export const api = axios.create({
baseURL: EPC__API_BASE_URI,
responseType: 'json',
headers: {
'Content-Type': 'application/json',
},
})
async function getPrivateData(ctx: Ctx) {
const { session } = ctx
const privateData = (await session.$getPrivateData()) || {}
return privateData
}
export async function createPartnerToken(ctx: Ctx, { force } = { force: false }) {
const { session } = ctx
const { integration, ...privateData } = await getPrivateData(ctx)
const { partnerToken } = integration?.partnerToken || {}
if (!force && partnerToken) {
return partnerToken
}
const { data } = await api.post(
'/oauth2/v1/token',
querystring.stringify({
grant_type: 'client_credentials',
client_id: EPC__PARTNER_CLIENT_ID,
client_secret: EPC__PARTNER_CLIENT_SECRET,
scope: 'pc pcapi',
}),
{ headers: { 'content-type': 'application/x-www-form-urlencoded' } },
)
const response = camelCaseKeys(data)
await session.$setPrivateData({
...privateData,
integration: {
...(integration || {}),
partnerToken: response,
},
})
return response
}
export async function getOrigin(ctx: Ctx, partner: EpcStoreState['partnerToken']) {
const { accessToken } = await createPartnerToken(ctx)
let data: any
let errors: any
let status: number | undefined
try {
const response = await api.get(`/partner/v2/origins/${partner?.id}`, {
headers: {
'X-Elli-PAT': partner?.token,
Authorization: `Bearer ${accessToken}`,
},
})
data = response.data
} catch (error) {
status = error.status
errors = error.data?.errors
if (_.isEmpty(errors) && status === 401) {
await createPartnerToken(ctx, { force: true })
return getOrigin(ctx, partner)
}
if (!_.isEmpty(errors)) {
throw new EpcError({ code: errors[0].code })
}
throw error
}
return data
}
export default { createPartnerToken }
import { Ctx, resolver } from 'blitz'
import { z } from 'zod'
import { getOrigin } from '../api'
export const FetchLoan = z
.object({
id: z.string(),
token: z.string(),
transactionId: z.string().or(z.undefined()),
})
.nonstrict()
export type FetchLoanInput = z.infer<typeof FetchLoan>
export default resolver.pipe(resolver.zod(FetchLoan), async (input, ctx: Ctx) => {
const response = await getOrigin(ctx, input)
return response
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment