diff --git a/packages/fetch-links/links/authHeadersLink.ts b/packages/fetch-links/links/authHeadersLink.ts deleted file mode 100644 index 4a05667..0000000 --- a/packages/fetch-links/links/authHeadersLink.ts +++ /dev/null @@ -1,35 +0,0 @@ -import {AuthClientOptions, mergeHeaders, modifyRequest} from '@opensdks/runtime' -import {Link} from '../link.js' - -export function authHeadersLink(auth: AuthClientOptions): Link { - if (auth.oauth && auth.authorizationHeader) { - throw new Error('Cannot use both oauth and authorizationHeader') - } - - const headers = { - ['authorization']: auth.oauth?.accessToken - ? `Bearer ${auth.oauth.accessToken}` - : auth.authorizationHeader?.bearer - ? `Bearer ${auth.authorizationHeader.bearer}` - : auth.authorizationHeader?.basic - ? `Basic ${btoa( - `${auth.authorizationHeader.basic.username}:${auth.authorizationHeader.basic.password}`, - )}` - : '', - } satisfies HeadersInit - - if (!headers['authorization']) { - throw new Error('No authorization paramater found') - } - - return async (req, next) => { - req.headers.delete('authorization') - const res = await next( - modifyRequest(req, { - headers: mergeHeaders(req.headers, headers, {}), - body: req.body, - }), - ) - return res - } -} diff --git a/packages/fetch-links/links/authLink.ts b/packages/fetch-links/links/authLink.ts new file mode 100644 index 0000000..f76ca9a --- /dev/null +++ b/packages/fetch-links/links/authLink.ts @@ -0,0 +1,39 @@ +import { + AuthClientOptions, + mergeHeaders, + modifyRequest, + openIntProxyLink, +} from '@opensdks/runtime' +import {Link} from '../link.js' + +export function authLink(auth: AuthClientOptions, baseUrl: string): Link { + if (!auth) { + // No Op + return (req, next) => next(req) + } + + if (auth.openInt) { + return openIntProxyLink(auth.openInt, baseUrl) + } + + const headers = { + ['authorization']: auth.oauth?.accessToken + ? `Bearer ${auth.oauth.accessToken}` + : auth?.bearer + ? `Bearer ${auth.bearer}` + : auth?.basic + ? `Basic ${btoa(`${auth.basic?.username}:${auth.basic?.password}`)}` + : '', + } satisfies HeadersInit + + return async (req, next) => { + req.headers.delete('authorization') + const res = await next( + modifyRequest(req, { + headers: mergeHeaders(req.headers, headers, {}), + body: req.body, + }), + ) + return res + } +} diff --git a/packages/fetch-links/links/openIntProxyLink.ts b/packages/fetch-links/links/openIntProxyLink.ts index 5b40359..0084aa0 100644 --- a/packages/fetch-links/links/openIntProxyLink.ts +++ b/packages/fetch-links/links/openIntProxyLink.ts @@ -53,11 +53,14 @@ interface OpenIntProxyHeaders { function removeEmptyHeaders(headers: OpenIntProxyHeaders): HeadersInit { return Object.fromEntries( - Object.entries(headers).filter(([_, value]) => value !== ''), + Object.entries(headers).filter(([_, value]) => value && value !== ''), ) satisfies HeadersInit } -export function openIntProxyLink(opts: OpenIntProxyLinkOptions): Link { +export function openIntProxyLink( + opts: OpenIntProxyLinkOptions, + baseUrl: string, +): Link { validateOpenIntProxyLinkOptions(opts) const {apiKey, token, resourceId, endUserId, connectorName} = opts @@ -70,13 +73,12 @@ export function openIntProxyLink(opts: OpenIntProxyLinkOptions): Link { }) satisfies HeadersInit return async (req, next) => { - const baseUrl = getBaseUrl(req.url) - const proxyUrl = 'https://app.openint.dev/api/proxy/' + // if (req.url.includes(proxyUrl)) { + // // Was previously necessary as link called twice leading to /api/proxy/api/proxy/? + // return next(req) + // } + const proxyUrl = 'https://api.openint.dev/proxy' - if (req.url.includes(proxyUrl)) { - // QQ: why is this necessary? why is this link called twice leading to /api/proxy/api/proxy/? - return next(req) - } req.headers.delete('authorization') const res = await next( modifyRequest(req, { @@ -88,8 +90,3 @@ export function openIntProxyLink(opts: OpenIntProxyLinkOptions): Link { return res } } - -function getBaseUrl(urlStr: string) { - const url = new URL(urlStr) - return `${url.protocol}//${url.host}/` -} diff --git a/packages/runtime/createClient.spec.ts b/packages/runtime/createClient.spec.ts index a533fe7..c4ec797 100644 --- a/packages/runtime/createClient.spec.ts +++ b/packages/runtime/createClient.spec.ts @@ -1,4 +1,7 @@ -import {createFormUrlEncodedBodySerializer} from '@opensdks/runtime' +import { + createClient, + createFormUrlEncodedBodySerializer, +} from '@opensdks/runtime' test('application/x-www-form-urlencoded defaut dot style', () => { const formUrlEncodedBodySerializer = createFormUrlEncodedBodySerializer({}) @@ -50,3 +53,8 @@ test('application/x-www-form-urlencoded bracket style', () => { 'account=acct_111222&components[account_onboarding][enabled]=true&components[nested][0]=hello&components[nested][1][key]=world', ) }) + +test('expect links array to have 2 elements', () => { + const client = createClient() + expect(client.links.length).toBe(2) +}) diff --git a/packages/runtime/createClient.ts b/packages/runtime/createClient.ts index 06fad60..5fa8a82 100644 --- a/packages/runtime/createClient.ts +++ b/packages/runtime/createClient.ts @@ -4,12 +4,11 @@ import type {PathsWithMethod} from 'openapi-typescript-helpers' import { applyLinks, fetchLink, - openIntProxyLink, OpenIntProxyLinkOptions, - validateOpenIntProxyLinkOptions, type HTTPMethod, type Link, } from '@opensdks/fetch-links' +import {authLink} from '../fetch-links/links/authLink.js' import {HTTPError} from './HTTPError.js' import {flattenNestedObject, FlattenOptions} from './utils.js' @@ -18,11 +17,10 @@ type _ClientOptions = NonNullable[0]> export type AuthClientOptions = { openInt?: OpenIntProxyLinkOptions // to be passed as Authorization header as a bearer token - oauth?: {accessToken: string} - authorizationHeader?: { - basic?: {username: string; password: string} - bearer?: string - } + oauth?: {accessToken: string; refreshToken?: string; expiresAt?: number} + basic?: {username: string; password: string} + /** non oauth / directly specifying bearer token */ + bearer?: string } export interface ClientOptions extends _ClientOptions { links?: Link[] | ((defaultLinks: Link[]) => Link[]) @@ -46,22 +44,7 @@ export function createClient({ }: ClientOptions = {}) { const links = typeof _links === 'function' ? _links(defaultLinks) : _links - const expectsAuthProxy = validateOpenIntProxyLinkOptions( - clientOptions.auth?.openInt ?? {}, - ) - - const hasOtherAuthMethods = - clientOptions.auth?.authorizationHeader || clientOptions.auth?.oauth - - if (expectsAuthProxy && hasOtherAuthMethods) { - throw new Error('Cannot use both openInt proxy and other auth methods') - } - - if (expectsAuthProxy) { - links.unshift(openIntProxyLink(clientOptions.auth?.openInt ?? {})) - } else if (hasOtherAuthMethods) { - links.unshift(fetchLink()) - } + links.unshift(authLink(clientOptions.auth ?? {}, clientOptions.baseUrl ?? '')) const customFetch: typeof fetch = (url, init) => applyLinks(new Request(url, init), links)