Skip to content
This repository was archived by the owner on Nov 15, 2024. It is now read-only.

Commit 5b0696d

Browse files
authored
Merge pull request #191 from seamapi/cleanup-get-client-session
Improvements to client session methods
2 parents ec99ba9 + 8a26dd7 commit 5b0696d

2 files changed

Lines changed: 111 additions & 107 deletions

File tree

docs/classes/Seam.md

Lines changed: 11 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/seam-connect/client.ts

Lines changed: 100 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import axios, {
2+
Axios,
23
AxiosInstance,
34
AxiosRequestConfig,
45
AxiosRequestHeaders,
5-
AxiosResponse,
66
} from "axios"
77
import axiosRetry from "axios-retry"
88
import { SeamAPIError, SeamMalformedInputError } from "../lib/api-error"
@@ -13,7 +13,7 @@ import {
1313
SuccessfulAPIResponse,
1414
} from "../types/globals"
1515
import { version } from "../../package.json"
16-
import { ClientSession, ClientSessionResponse } from "../types"
16+
import { ClientSessionResponse } from "../types"
1717

1818
export interface SeamClientOptions {
1919
/* Seam API Key */
@@ -38,17 +38,11 @@ export interface SeamClientOptions {
3838
export 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-
9955
export 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

Comments
 (0)