11import axios , {
2+ Axios ,
23 AxiosInstance ,
34 AxiosRequestConfig ,
45 AxiosRequestHeaders ,
5- AxiosResponse ,
66} from "axios"
77import axiosRetry from "axios-retry"
88import { SeamAPIError , SeamMalformedInputError } from "../lib/api-error"
@@ -13,7 +13,7 @@ import {
1313 SuccessfulAPIResponse ,
1414} from "../types/globals"
1515import { version } from "../../package.json"
16- import { ClientSession , ClientSessionResponse } from "../types"
16+ import { ClientSessionResponse } from "../types"
1717
1818export interface SeamClientOptions {
1919 /* Seam API Key */
@@ -38,17 +38,11 @@ export interface SeamClientOptions {
3838export const getSeamClientOptionsWithDefaults = (
3939 apiKeyOrOptions ?: string | SeamClientOptions
4040) : SeamClientOptions => {
41- let seamClientDefaults : SeamClientOptions = { }
42- try {
43- // try to get defaults from environment (for server-side use)
44- seamClientDefaults = {
45- apiKey : process ?. env ?. SEAM_API_KEY ,
46- endpoint : process ?. env ?. SEAM_API_URL || "https://connect.getseam.com" ,
47- workspaceId : process ?. env ?. SEAM_WORKSPACE_ID ,
48- }
49- } catch ( error ) {
50- // we are in a browser, so use the apiKeyOrOptions
51- // do nothing
41+ const seamClientDefaults = {
42+ apiKey : globalThis ?. process ?. env ?. SEAM_API_KEY ?? undefined ,
43+ endpoint :
44+ globalThis ?. process ?. env ?. SEAM_API_URL ?? "https://connect.getseam.com" ,
45+ workspaceId : globalThis ?. process ?. env ?. SEAM_WORKSPACE_ID ?? undefined ,
5246 }
5347 if ( typeof apiKeyOrOptions === "string" ) {
5448 // for both browser and server, if apiKeyOrOptions is a string, use it as the apiKey, and merge with defaults
@@ -58,44 +52,6 @@ export const getSeamClientOptionsWithDefaults = (
5852 }
5953}
6054
61- const getAuthHeaders = ( {
62- clientSessionToken,
63- apiKey,
64- workspaceId,
65- } : {
66- clientSessionToken ?: string
67- apiKey ?: string
68- workspaceId ?: string
69- } ) : Record < string , string > => {
70- if ( apiKey && clientSessionToken ) {
71- throw new Error ( "You can't use clientSessionToken AND specify apiKey." )
72- }
73-
74- if ( clientSessionToken ) {
75- if ( ! clientSessionToken . startsWith ( "seam_cst" ) ) {
76- throw new Error ( "clientSessionToken must start with seam_cst" )
77- }
78- return { "client-session-token" : clientSessionToken }
79- }
80-
81- if ( apiKey ) {
82- if ( apiKey . startsWith ( "seam_cst" ) ) {
83- console . warn (
84- "Using API Key as Client Session Token is deprecated. Please use the clientSessionToken option instead."
85- )
86- return { "client-session-token" : apiKey }
87- }
88- if ( ! apiKey . startsWith ( "seam_at" ) && workspaceId )
89- throw new Error (
90- "You can't use API Key Authentication AND specify a workspace. Your API Key only works for the workspace it was created in. To use Session Key Authentication with multi-workspace support, contact Seam support."
91- )
92- return { authorization : `Bearer ${ apiKey } ` }
93- }
94- throw new Error (
95- "Must provide either clientSessionToken or apiKey (API Key or Access Token with Workspace ID)."
96- )
97- }
98-
9955export class Seam extends Routes {
10056 public client : AxiosInstance
10157
@@ -137,78 +93,121 @@ export class Seam extends Routes {
13793 public async makeRequest < T > (
13894 request : AxiosRequestConfig
13995 ) : Promise < SuccessfulAPIResponse < T > > {
140- try {
141- const response = await this . client . request ( request )
142- return response . data
143- } catch ( error ) {
144- if ( axios . isAxiosError ( error ) && error . response ) {
145- if ( error . response . data . error ?. type === "invalid_input" ) {
146- throw new SeamMalformedInputError (
147- error . response . data . error . validation_errors
148- )
96+ return makeRequest < T > ( this . client , request )
97+ }
98+
99+ static async getClientSessionToken ( options : {
100+ publishableKey ?: string
101+ userIdentifierKey : string
102+ endpoint ?: string
103+ workspaceId ?: string
104+ apiKey ?: string
105+ } ) : Promise < APIResponse < ClientSessionResponse > > {
106+ const { apiKey, endpoint, axiosOptions } =
107+ getSeamClientOptionsWithDefaults ( options )
108+
109+ if ( ! options . userIdentifierKey ) {
110+ throw new Error ( "userIdentifierKey is required" )
111+ }
112+
113+ const getKeyHeaders = ( ) : AxiosRequestHeaders => {
114+ const { publishableKey } = options
115+ if ( publishableKey ) {
116+ if ( ! publishableKey . startsWith ( "seam_pk" ) ) {
117+ throw new Error ( "Invalid publishableKey" )
149118 }
119+ return { "seam-publishable-key" : publishableKey }
120+ }
150121
151- throw new SeamAPIError (
152- error . response . status ,
153- error . response . headers [ "seam-request-id" ] ,
154- ( error . response . data as ErroredAPIResponse ) . error
155- )
122+ if ( apiKey ) {
123+ if ( ! apiKey ?. startsWith ( "seam_" ) ) {
124+ throw new Error ( "Invalid apiKey" )
125+ }
126+ return { "seam-api-key" : apiKey }
156127 }
157128
158- throw error
129+ throw new Error ( "Must provide a publishableKey or apiKey" )
159130 }
160- }
161131
162- static async getClientSessionToken (
163- ops : CSTParams
164- ) : Promise < APIResponse < ClientSessionResponse > > {
165- const { apiKey, endpoint, axiosOptions } =
166- getSeamClientOptionsWithDefaults ( ops )
167- let headers : AxiosRequestHeaders = {
132+ const headers = {
133+ "seam-user-identifier-key" : options . userIdentifierKey ,
134+ ...getKeyHeaders ( ) ,
168135 ...axiosOptions ?. headers ,
169136 }
170137
171- if ( ops . publishableKey ?. startsWith ( "seam_pk" ) ) {
172- // frontend mode
173- headers [ "seam-publishable-key" ] = ops . publishableKey
174- } else if ( apiKey ?. startsWith ( "seam_" ) ) {
175- // backend mode
176- headers [ "seam-api-key" ] = apiKey
177- }
178- if ( ops . userIdentifierKey ) {
179- headers [ "seam-user-identifier-key" ] = ops . userIdentifierKey
180- } else {
181- throw new Error ( "userIdentifierKey is required" )
182- }
183138 const client = axios . create ( {
184139 ...axiosOptions ,
185140 baseURL : endpoint ,
186141 headers,
187142 } )
188- try {
189- const response : AxiosResponse & {
190- data : { client_session : ClientSession }
191- } = await client . post (
192- "/internal/client_sessions/create" ,
193- { } ,
194- // { headers: { "seam-sdk-version": version } }
195- { }
196- )
197- return await response . data
198- } catch ( error : any ) {
143+
144+ return makeRequest ( client , {
145+ method : "POST" ,
146+ url : "/internal/client_sessions/create" ,
147+ } )
148+ }
149+ }
150+
151+ const makeRequest = async < T > (
152+ client : Axios ,
153+ request : AxiosRequestConfig
154+ ) : Promise < SuccessfulAPIResponse < T > > => {
155+ try {
156+ const response = await client . request ( request )
157+ return response . data
158+ } catch ( error ) {
159+ if ( axios . isAxiosError ( error ) && error . response ) {
160+ if ( error . response . data . error ?. type === "invalid_input" ) {
161+ throw new SeamMalformedInputError (
162+ error . response . data . error . validation_errors
163+ )
164+ }
165+
199166 throw new SeamAPIError (
200167 error . response . status ,
201168 error . response . headers [ "seam-request-id" ] ,
202169 ( error . response . data as ErroredAPIResponse ) . error
203170 )
204171 }
172+
173+ throw error
205174 }
206175}
207176
208- type CSTParams = {
209- publishableKey ?: string
210- userIdentifierKey : string
211- endpoint ?: string
212- workspaceId ?: string
177+ const getAuthHeaders = ( {
178+ clientSessionToken,
179+ apiKey,
180+ workspaceId,
181+ } : {
182+ clientSessionToken ?: string
213183 apiKey ?: string
184+ workspaceId ?: string
185+ } ) : Record < string , string > => {
186+ if ( apiKey && clientSessionToken ) {
187+ throw new Error ( "You can't use clientSessionToken AND specify apiKey." )
188+ }
189+
190+ if ( clientSessionToken ) {
191+ if ( ! clientSessionToken . startsWith ( "seam_cst" ) ) {
192+ throw new Error ( "clientSessionToken must start with seam_cst" )
193+ }
194+ return { "client-session-token" : clientSessionToken }
195+ }
196+
197+ if ( apiKey ) {
198+ if ( apiKey . startsWith ( "seam_cst" ) ) {
199+ console . warn (
200+ "Using API Key as Client Session Token is deprecated. Please use the clientSessionToken option instead."
201+ )
202+ return { "client-session-token" : apiKey }
203+ }
204+ if ( ! apiKey . startsWith ( "seam_at" ) && workspaceId )
205+ throw new Error (
206+ "You can't use API Key Authentication AND specify a workspace. Your API Key only works for the workspace it was created in. To use Session Key Authentication with multi-workspace support, contact Seam support."
207+ )
208+ return { authorization : `Bearer ${ apiKey } ` }
209+ }
210+ throw new Error (
211+ "Must provide either clientSessionToken or apiKey (API Key or Access Token with Workspace ID)."
212+ )
214213}
0 commit comments