Skip to content

Commit

Permalink
Add SeamHttpMultiWorkspace client
Browse files Browse the repository at this point in the history
  • Loading branch information
razor-x committed Nov 10, 2023
1 parent f1b5378 commit 89efac6
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 32 deletions.
38 changes: 28 additions & 10 deletions src/lib/seam/connect/auth.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import {
isSeamHttpMultiWorkspaceOptionsWithConsoleSessionToken,
isSeamHttpMultiWorkspaceOptionsWithPersonalAccessToken,
isSeamHttpOptionsWithApiKey,
isSeamHttpOptionsWithClientSessionToken,
isSeamHttpOptionsWithConsoleSessionToken,
isSeamHttpOptionsWithPersonalAccessToken,
SeamHttpInvalidOptionsError,
type SeamHttpMultiWorkspaceOptionsWithConsoleSessionToken,
type SeamHttpMultiWorkspaceOptionsWithPersonalAccessToken,
type SeamHttpOptionsWithApiKey,
type SeamHttpOptionsWithClientSessionToken,
type SeamHttpOptionsWithConsoleSessionToken,
Expand All @@ -26,11 +30,17 @@ export const getAuthHeaders = (options: Options): Headers => {
return getAuthHeadersForClientSessionToken(options)
}

if (isSeamHttpOptionsWithConsoleSessionToken(options)) {
if (
isSeamHttpMultiWorkspaceOptionsWithConsoleSessionToken(options) ||
isSeamHttpOptionsWithConsoleSessionToken(options)
) {
return getAuthHeadersForConsoleSessionToken(options)
}

if (isSeamHttpOptionsWithPersonalAccessToken(options)) {
if (
isSeamHttpMultiWorkspaceOptionsWithPersonalAccessToken(options) ||
isSeamHttpOptionsWithPersonalAccessToken(options)
) {
return getAuthHeadersForPersonalAccessToken(options)
}

Expand All @@ -40,8 +50,8 @@ export const getAuthHeaders = (options: Options): Headers => {
'an apiKey,',
'clientSessionToken,',
'publishableKey,',
'consoleSessionToken with a workspaceId',
'or personalAccessToken with a workspaceId',
'consoleSessionToken',
'or personalAccessToken',
].join(' '),
)
}
Expand Down Expand Up @@ -117,8 +127,12 @@ const getAuthHeadersForClientSessionToken = ({

const getAuthHeadersForConsoleSessionToken = ({
consoleSessionToken,
workspaceId,
}: SeamHttpOptionsWithConsoleSessionToken): Headers => {
...options
}:
| SeamHttpMultiWorkspaceOptionsWithConsoleSessionToken
| SeamHttpOptionsWithConsoleSessionToken): Headers => {
const workspaceId = 'workspaceId' in options ? options.workspaceId : undefined

if (isAccessToken(consoleSessionToken)) {
throw new SeamHttpInvalidTokenError(
'An Access Token cannot be used as a consoleSessionToken',
Expand All @@ -145,14 +159,18 @@ const getAuthHeadersForConsoleSessionToken = ({

return {
authorization: `Bearer ${consoleSessionToken}`,
'seam-workspace-id': workspaceId,
...(workspaceId != null ? { 'seam-workspace-id': workspaceId } : {}),
}
}

const getAuthHeadersForPersonalAccessToken = ({
personalAccessToken,
workspaceId,
}: SeamHttpOptionsWithPersonalAccessToken): Headers => {
...options
}:
| SeamHttpMultiWorkspaceOptionsWithPersonalAccessToken
| SeamHttpOptionsWithPersonalAccessToken): Headers => {
const workspaceId = 'workspaceId' in options ? options.workspaceId : undefined

if (isJwt(personalAccessToken)) {
throw new SeamHttpInvalidTokenError(
'A JWT cannot be used as a personalAccessToken',
Expand All @@ -179,7 +197,7 @@ const getAuthHeadersForPersonalAccessToken = ({

return {
authorization: `Bearer ${personalAccessToken}`,
'seam-workspace-id': workspaceId,
...(workspaceId != null ? { 'seam-workspace-id': workspaceId } : {}),
}
}

Expand Down
1 change: 1 addition & 0 deletions src/lib/seam/connect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export * from './options.js'
export * from './routes/index.js'
export * from './seam-http.js'
export * from './seam-http-error.js'
export * from './seam-http-multi-workspace.js'
export * from 'lib/params-serializer.js'
77 changes: 60 additions & 17 deletions src/lib/seam/connect/options.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { Client, ClientOptions } from './client.js'

export type SeamHttpMultiWorkspaceOptions =
| SeamHttpMultiWorkspaceOptionsWithClient
| SeamHttpMultiWorkspaceOptionsWithConsoleSessionToken
| SeamHttpMultiWorkspaceOptionsWithPersonalAccessToken

export type SeamHttpOptions =
| SeamHttpOptionsFromEnv
| SeamHttpOptionsWithClient
Expand All @@ -17,6 +22,14 @@ export interface SeamHttpFromPublishableKeyOptions

export interface SeamHttpOptionsFromEnv extends SeamHttpCommonOptions {}

export interface SeamHttpMultiWorkspaceOptionsWithClient {
client: Client
}

export const isSeamHttpMultiWorkspaceOptionsWithClient = (
options: SeamHttpOptions,
): options is SeamHttpOptionsWithClient => isSeamHttpOptionsWithClient(options)

export interface SeamHttpOptionsWithClient {
client: Client
}
Expand Down Expand Up @@ -102,24 +115,17 @@ export const isSeamHttpOptionsWithClientSessionToken = (
return true
}

export interface SeamHttpOptionsWithConsoleSessionToken
export interface SeamHttpMultiWorkspaceOptionsWithConsoleSessionToken
extends SeamHttpCommonOptions {
consoleSessionToken: string
workspaceId: string
}

export const isSeamHttpOptionsWithConsoleSessionToken = (
export const isSeamHttpMultiWorkspaceOptionsWithConsoleSessionToken = (
options: SeamHttpOptions,
): options is SeamHttpOptionsWithConsoleSessionToken => {
): options is SeamHttpMultiWorkspaceOptionsWithConsoleSessionToken => {
if (!('consoleSessionToken' in options)) return false
if (options.consoleSessionToken == null) return false

if (!('workspaceId' in options) || options.workspaceId == null) {
throw new SeamHttpInvalidOptionsError(
'Must pass a workspaceId when using a consoleSessionToken',
)
}

if ('apiKey' in options && options.apiKey != null) {
throw new SeamHttpInvalidOptionsError(
'The apiKey option cannot be used with the consoleSessionToken option',
Expand All @@ -141,24 +147,38 @@ export const isSeamHttpOptionsWithConsoleSessionToken = (
return true
}

export interface SeamHttpOptionsWithPersonalAccessToken
export interface SeamHttpOptionsWithConsoleSessionToken
extends SeamHttpCommonOptions {
personalAccessToken: string
consoleSessionToken: string
workspaceId: string
}

export const isSeamHttpOptionsWithPersonalAccessToken = (
export const isSeamHttpOptionsWithConsoleSessionToken = (
options: SeamHttpOptions,
): options is SeamHttpOptionsWithPersonalAccessToken => {
if (!('personalAccessToken' in options)) return false
if (options.personalAccessToken == null) return false
): options is SeamHttpOptionsWithConsoleSessionToken => {
if (!isSeamHttpMultiWorkspaceOptionsWithConsoleSessionToken(options))
return false

if (!('workspaceId' in options) || options.workspaceId == null) {
throw new SeamHttpInvalidOptionsError(
'Must pass a workspaceId when using a personalAccessToken',
'Must pass a workspaceId when using a consoleSessionToken',
)
}

return true
}

export interface SeamHttpMultiWorkspaceOptionsWithPersonalAccessToken
extends SeamHttpCommonOptions {
personalAccessToken: string
}

export const isSeamHttpMultiWorkspaceOptionsWithPersonalAccessToken = (
options: SeamHttpOptions,
): options is SeamHttpMultiWorkspaceOptionsWithPersonalAccessToken => {
if (!('personalAccessToken' in options)) return false
if (options.personalAccessToken == null) return false

if ('apiKey' in options && options.apiKey != null) {
throw new SeamHttpInvalidOptionsError(
'The apiKey option cannot be used with the personalAccessToken option',
Expand All @@ -180,10 +200,33 @@ export const isSeamHttpOptionsWithPersonalAccessToken = (
return true
}

export interface SeamHttpOptionsWithPersonalAccessToken
extends SeamHttpCommonOptions {
personalAccessToken: string
workspaceId: string
}

export const isSeamHttpOptionsWithPersonalAccessToken = (
options: SeamHttpOptions,
): options is SeamHttpOptionsWithPersonalAccessToken => {
if (!isSeamHttpMultiWorkspaceOptionsWithPersonalAccessToken(options))
return false

if (!('workspaceId' in options) || options.workspaceId == null) {
throw new SeamHttpInvalidOptionsError(
'Must pass a workspaceId when using a personalAccessToken',
)
}

return true
}

export class SeamHttpInvalidOptionsError extends Error {
constructor(message: string) {
super(`SeamHttp received invalid options: ${message}`)
this.name = this.constructor.name
Error.captureStackTrace(this, this.constructor)
}
}

export class SeamHttpMultiWorkspaceInvalidOptionsError extends SeamHttpInvalidOptionsError {}
7 changes: 6 additions & 1 deletion src/lib/seam/connect/parse-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import version from 'lib/version.js'
import { getAuthHeaders } from './auth.js'
import type { ClientOptions } from './client.js'
import {
isSeamHttpMultiWorkspaceOptionsWithClient,
isSeamHttpOptionsWithClient,
isSeamHttpOptionsWithClientSessionToken,
type SeamHttpMultiWorkspaceOptions,
type SeamHttpOptions,
} from './options.js'

Expand All @@ -15,14 +17,17 @@ const sdkHeaders = {
'seam-sdk-version': version,
}

export type Options = SeamHttpOptions & { publishableKey?: string }
export type Options =
| SeamHttpMultiWorkspaceOptions
| (SeamHttpOptions & { publishableKey?: string })

export const parseOptions = (
apiKeyOrOptions: string | Options,
): ClientOptions => {
const options = getNormalizedOptions(apiKeyOrOptions)

if (isSeamHttpOptionsWithClient(options)) return options
if (isSeamHttpMultiWorkspaceOptionsWithClient(options)) return options

return {
axiosOptions: {
Expand Down
77 changes: 77 additions & 0 deletions src/lib/seam/connect/seam-http-multi-workspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { type Client, createClient } from './client.js'

Check failure on line 1 in src/lib/seam/connect/seam-http-multi-workspace.ts

View workflow job for this annotation

GitHub Actions / Lint (Node.js v16)

Run autofix to sort these imports!

Check failure on line 1 in src/lib/seam/connect/seam-http-multi-workspace.ts

View workflow job for this annotation

GitHub Actions / Lint (Node.js v18)

Run autofix to sort these imports!
import { SeamHttpWorkspaces } from './routes/index.js'
import {
isSeamHttpMultiWorkspaceOptionsWithClient,
isSeamHttpMultiWorkspaceOptionsWithConsoleSessionToken,
isSeamHttpMultiWorkspaceOptionsWithPersonalAccessToken,
SeamHttpMultiWorkspaceInvalidOptionsError,
type SeamHttpMultiWorkspaceOptions,
type SeamHttpMultiWorkspaceOptionsWithClient,
type SeamHttpMultiWorkspaceOptionsWithConsoleSessionToken,
type SeamHttpMultiWorkspaceOptionsWithPersonalAccessToken,
} from './options.js'
import { parseOptions } from './parse-options.js'

export class SeamHttpMultiWorkspace {
client: Client

constructor(options: SeamHttpMultiWorkspaceOptions) {
const clientOptions = parseOptions(options)
this.client = createClient(clientOptions)
}

static fromClient(
client: SeamHttpMultiWorkspaceOptionsWithClient['client'],
options: Omit<SeamHttpMultiWorkspaceOptionsWithClient, 'client'> = {},
): SeamHttpMultiWorkspace {
const constructorOptions = { ...options, client }
if (!isSeamHttpMultiWorkspaceOptionsWithClient(constructorOptions)) {
throw new SeamHttpMultiWorkspaceInvalidOptionsError('Missing client')
}
return new SeamHttpMultiWorkspace(constructorOptions)
}

static fromConsoleSessionToken(
consoleSessionToken: SeamHttpMultiWorkspaceOptionsWithConsoleSessionToken['consoleSessionToken'],
options: Omit<
SeamHttpMultiWorkspaceOptionsWithConsoleSessionToken,
'consoleSessionToken'
> = {},
): SeamHttpMultiWorkspace {
const constructorOptions = { ...options, consoleSessionToken }
if (
!isSeamHttpMultiWorkspaceOptionsWithConsoleSessionToken(
constructorOptions,
)
) {
throw new SeamHttpMultiWorkspaceInvalidOptionsError(
'Missing consoleSessionToken',
)
}
return new SeamHttpMultiWorkspace(constructorOptions)
}

static fromPersonalAccessToken(
personalAccessToken: SeamHttpMultiWorkspaceOptionsWithPersonalAccessToken['personalAccessToken'],
options: Omit<
SeamHttpMultiWorkspaceOptionsWithPersonalAccessToken,
'personalAccessToken'
> = {},
): SeamHttpMultiWorkspace {
const constructorOptions = { ...options, personalAccessToken }
if (
!isSeamHttpMultiWorkspaceOptionsWithPersonalAccessToken(
constructorOptions,
)
) {
throw new SeamHttpMultiWorkspaceInvalidOptionsError(
'Missing personalAccessToken',
)
}
return new SeamHttpMultiWorkspace(constructorOptions)
}

get workspaces(): SeamHttpWorkspaces {
return SeamHttpWorkspaces.fromClient(this.client)
}
}
Loading

0 comments on commit 89efac6

Please sign in to comment.