Skip to content

Commit b1323b3

Browse files
committed
Add client with workspaces.get
1 parent 5beaaf9 commit b1323b3

File tree

5 files changed

+322
-14
lines changed

5 files changed

+322
-14
lines changed

package-lock.json

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

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@
7171
"npm": ">= 8.1.0"
7272
},
7373
"dependencies": {
74-
"@seamapi/types": "^1.12.0"
74+
"@seamapi/types": "^1.13.0",
75+
"axios": "^1.5.0"
7576
},
7677
"devDependencies": {
7778
"@types/node": "^18.11.18",

src/lib/seam/connect/auth.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import type {
2+
SeamHttpOptionsWithApiKey,
3+
SeamHttpOptionsWithClientSessionToken,
4+
} from './client-options.js'
5+
6+
type Headers = Record<string, string>
7+
8+
export const getAuthHeadersForApiKey = ({
9+
apiKey,
10+
}: SeamHttpOptionsWithApiKey): Headers => {
11+
if (isClientSessionToken(apiKey)) {
12+
throw new InvalidSeamTokenError(
13+
'A Client Session Token cannot be used as an apiKey',
14+
)
15+
}
16+
17+
if (isAccessToken(apiKey)) {
18+
throw new InvalidSeamTokenError(
19+
'An access token cannot be used as an apiKey without specifying a workspaceId',
20+
)
21+
}
22+
23+
if (isJwt(apiKey) || !isSeamToken(apiKey)) {
24+
throw new InvalidSeamTokenError(
25+
`Unknown or Invalid apiKey format, expected token to start with ${tokenPrefix}`,
26+
)
27+
}
28+
29+
return {
30+
authorization: `Bearer ${apiKey}`,
31+
}
32+
}
33+
34+
export const getAuthHeadersForClientSessionToken = ({
35+
clientSessionToken,
36+
}: SeamHttpOptionsWithClientSessionToken): Headers => {
37+
if (!isClientSessionToken(clientSessionToken)) {
38+
throw new InvalidSeamTokenError(
39+
`Unknown or invalid clientSessionToken format, expected token to start with ${clientSessionTokenPrefix}`,
40+
)
41+
}
42+
43+
return {
44+
authorization: `Bearer ${clientSessionToken}`,
45+
'client-session-token': clientSessionToken,
46+
}
47+
}
48+
49+
export class InvalidSeamTokenError extends Error {
50+
constructor(message: string) {
51+
super(`SeamHttp received an authorization invalid token: ${message}`)
52+
this.name = this.constructor.name
53+
Error.captureStackTrace(this, this.constructor)
54+
}
55+
}
56+
57+
const tokenPrefix = 'seam_'
58+
59+
const clientSessionTokenPrefix = 'seam_cst'
60+
61+
const isClientSessionToken = (token: string): boolean =>
62+
token.startsWith(clientSessionTokenPrefix)
63+
64+
const isAccessToken = (token: string): boolean => token.startsWith('seam_at')
65+
66+
const isJwt = (token: string): boolean => token.startsWith('ey')
67+
68+
const isSeamToken = (token: string): boolean => token.startsWith(tokenPrefix)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import type { AxiosRequestConfig } from 'axios'
2+
3+
export type SeamHttpOptions =
4+
| SeamHttpOptionsWithApiKey
5+
| SeamHttpOptionsWithClientSessionToken
6+
7+
interface SeamHttpCommonOptions {
8+
endpoint?: string
9+
axiosOptions?: AxiosRequestConfig
10+
}
11+
12+
export interface SeamHttpOptionsWithApiKey extends SeamHttpCommonOptions {
13+
apiKey: string
14+
}
15+
16+
export const isSeamHttpOptionsWithApiKey = (
17+
options: SeamHttpOptions,
18+
): options is SeamHttpOptionsWithApiKey => {
19+
if (!('apiKey' in options)) return false
20+
21+
if ('clientSessionToken' in options && options.clientSessionToken != null) {
22+
throw new InvalidSeamHttpOptionsError(
23+
'The clientSessionToken option cannot be used with the apiKey option.',
24+
)
25+
}
26+
27+
return true
28+
}
29+
30+
export interface SeamHttpOptionsWithClientSessionToken
31+
extends SeamHttpCommonOptions {
32+
clientSessionToken: string
33+
}
34+
35+
export const isSeamHttpOptionsWithClientSessionToken = (
36+
options: SeamHttpOptions,
37+
): options is SeamHttpOptionsWithClientSessionToken => {
38+
if (!('clientSessionToken' in options)) return false
39+
40+
if ('apiKey' in options && options.apiKey != null) {
41+
throw new InvalidSeamHttpOptionsError(
42+
'The clientSessionToken option cannot be used with the apiKey option.',
43+
)
44+
}
45+
46+
return true
47+
}
48+
49+
export class InvalidSeamHttpOptionsError extends Error {
50+
constructor(message: string) {
51+
super(`SeamHttp received invalid options: ${message}`)
52+
this.name = this.constructor.name
53+
Error.captureStackTrace(this, this.constructor)
54+
}
55+
}

0 commit comments

Comments
 (0)