Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@
"@rxfork/r2wc-react-to-web-component": "^2.4.0",
"@seamapi/fake-devicedb": "^1.6.1",
"@seamapi/fake-seam-connect": "^1.76.0",
"@seamapi/http": "^1.38.3",
"@seamapi/http": "^1.40.0",
"@seamapi/types": "^1.395.3",
"@storybook/addon-designs": "^7.0.1",
"@storybook/addon-essentials": "^7.0.2",
Expand Down
89 changes: 86 additions & 3 deletions src/lib/seam/SeamQueryProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ export interface SeamQueryContext {
publishableKey?: string | undefined
userIdentifierKey?: string | undefined
clientSessionToken?: string | undefined
consoleSessionToken?: string | undefined
workspaceId?: string | undefined
queryKeyPrefix?: string | undefined
}

export type SeamQueryProviderProps =
| SeamQueryProviderPropsWithClient
| SeamQueryProviderPropsWithPublishableKey
| SeamQueryProviderPropsWithClientSessionToken
| SeamQueryProviderPropsWithConsoleSessionToken

export interface SeamQueryProviderPropsWithClient
extends SeamQueryProviderBaseProps {
Expand All @@ -52,6 +55,13 @@ export interface SeamQueryProviderPropsWithClientSessionToken
clientSessionToken: string
}

export interface SeamQueryProviderPropsWithConsoleSessionToken
extends SeamQueryProviderBaseProps,
SeamQueryProviderClientOptions {
consoleSessionToken: string
workspaceId?: string | undefined
}

interface SeamQueryProviderBaseProps extends PropsWithChildren {
queryClient?: QueryClient | undefined
onSessionUpdate?: (client: SeamHttp) => void
Expand All @@ -74,7 +84,8 @@ export function SeamQueryProvider({
if (
context.client == null &&
context.publishableKey == null &&
context.clientSessionToken == null
context.clientSessionToken == null &&
context.consoleSessionToken == null
) {
return defaultSeamQueryContextValue
}
Expand All @@ -84,10 +95,11 @@ export function SeamQueryProvider({
if (
value.client == null &&
value.publishableKey == null &&
value.clientSessionToken == null
value.clientSessionToken == null &&
value.consoleSessionToken == null
) {
throw new Error(
`Must provide either a Seam client, clientSessionToken, or a publishableKey.`
`Must provide either a Seam client, clientSessionToken, publishableKey or consoleSessionToken.`
)
}

Expand Down Expand Up @@ -177,6 +189,17 @@ const createSeamQueryContextValue = (
}
}

if (isSeamQueryProviderPropsWithConsoleSessionToken(options)) {
const { consoleSessionToken, workspaceId, ...clientOptions } = options
return {
consoleSessionToken,
workspaceId,
clientOptions,
client: null,
endpointClient: null,
}
}

return { client: null, endpointClient: null }
}

Expand Down Expand Up @@ -229,6 +252,18 @@ const isSeamQueryProviderPropsWithPublishableKey = (
)
}

if ('consoleSessionToken' in props && props.consoleSessionToken != null) {
throw new InvalidSeamQueryProviderProps(
'The consoleSessionToken prop cannot be used with the publishableKey prop.'
)
}

if ('workspaceId' in props && props.workspaceId != null) {
throw new InvalidSeamQueryProviderProps(
'The workspaceId prop cannot be used with the publishableKey prop.'
)
}

return true
}

Expand Down Expand Up @@ -259,6 +294,54 @@ const isSeamQueryProviderPropsWithClientSessionToken = (
)
}

if ('consoleSessionToken' in props && props.consoleSessionToken != null) {
throw new InvalidSeamQueryProviderProps(
'The consoleSessionToken prop cannot be used with the clientSessionToken prop.'
)
}

if ('workspaceId' in props && props.workspaceId != null) {
throw new InvalidSeamQueryProviderProps(
'The workspaceId prop cannot be used with the clientSessionToken prop.'
)
}

return true
}

const isSeamQueryProviderPropsWithConsoleSessionToken = (
props: SeamQueryProviderProps
): props is SeamQueryProviderPropsWithConsoleSessionToken &
SeamQueryProviderClientOptions => {
if (!('consoleSessionToken' in props)) return false

const { consoleSessionToken } = props
if (consoleSessionToken == null) return false

if ('client' in props && props.client != null) {
throw new InvalidSeamQueryProviderProps(
'The client prop cannot be used with the publishableKey prop.'
)
}

if ('clientSessionToken' in props && props.clientSessionToken != null) {
throw new InvalidSeamQueryProviderProps(
'The clientSessionToken prop cannot be used with the publishableKey prop.'
)
}

if ('publishableKey' in props && props.publishableKey != null) {
throw new InvalidSeamQueryProviderProps(
'The publishableKey prop cannot be used with the consoleSessionToken prop.'
)
}

if ('userIdentifierKey' in props && props.userIdentifierKey != null) {
throw new InvalidSeamQueryProviderProps(
'The userIdentifierKey prop cannot be used with the consoleSessionToken prop.'
)
}

return true
}

Expand Down
2 changes: 2 additions & 0 deletions src/lib/seam/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ export * from './devices/use-devices.js'
export * from './SeamProvider.js'
export * from './use-seam-client.js'
export * from './use-seam-mutation.js'
export * from './use-seam-mutation-without-workspace.js'
export * from './use-seam-query.js'
export * from './use-seam-query-result.js'
export * from './use-seam-query-without-workspace.js'
117 changes: 94 additions & 23 deletions src/lib/seam/use-seam-client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { SeamHttp, SeamHttpEndpoints } from '@seamapi/http/connect'
import {
SeamHttp,
SeamHttpEndpoints,
SeamHttpEndpointsWithoutWorkspace,
SeamHttpWithoutWorkspace,
} from '@seamapi/http/connect'
import { useQuery } from '@tanstack/react-query'
import { useEffect } from 'react'
import { v4 as uuidv4 } from 'uuid'
Expand All @@ -8,6 +13,8 @@ import { useSeamQueryContext } from './SeamQueryProvider.js'
export function useSeamClient(): {
client: SeamHttp | null
endpointClient: SeamHttpEndpoints | null
clientWithoutWorkspace: SeamHttpWithoutWorkspace | null
endpointClientWithoutWorkspace: SeamHttpEndpointsWithoutWorkspace | null
queryKeyPrefixes: string[]
isPending: boolean
isError: boolean
Expand All @@ -18,16 +25,21 @@ export function useSeamClient(): {
clientOptions,
publishableKey,
clientSessionToken,
consoleSessionToken,
workspaceId,
queryKeyPrefix,
...context
} = useSeamQueryContext()
const userIdentifierKey = useUserIdentifierKeyOrFingerprint(
clientSessionToken != null ? '' : context.userIdentifierKey
)

const { isPending, isError, error, data } = useQuery<
[SeamHttp, SeamHttpEndpoints]
>({
const { isPending, isError, error, data } = useQuery<{
client: SeamHttp | null
endpointClient: SeamHttpEndpoints | null
clientWithoutWorkspace: SeamHttpWithoutWorkspace | null
endpointClientWithoutWorkspace: SeamHttpEndpointsWithoutWorkspace | null
}>({
queryKey: [
...getQueryKeyPrefixes({ queryKeyPrefix }),
'client',
Expand All @@ -41,46 +53,93 @@ export function useSeamClient(): {
],
queryFn: async () => {
if (client != null)
return [client, SeamHttpEndpoints.fromClient(client.client)]
return {
client,
endpointClient: SeamHttpEndpoints.fromClient(client.client),
clientWithoutWorkspace: null,
endpointClientWithoutWorkspace: null,
}

if (clientSessionToken != null) {
const clientSessionTokenClient = SeamHttp.fromClientSessionToken(
const seam = SeamHttp.fromClientSessionToken(
clientSessionToken,
clientOptions
)

return [
clientSessionTokenClient,
SeamHttpEndpoints.fromClient(clientSessionTokenClient.client),
]
return {
client: seam,
endpointClient: SeamHttpEndpoints.fromClient(seam.client),
clientWithoutWorkspace: null,
endpointClientWithoutWorkspace: null,
}
}

if (publishableKey == null) {
throw new Error(
'Missing either a client, publishableKey, or clientSessionToken'
if (publishableKey != null) {
const seam = await SeamHttp.fromPublishableKey(
publishableKey,
userIdentifierKey,
clientOptions
)

return {
client: seam,
endpointClient: SeamHttpEndpoints.fromClient(seam.client),
clientWithoutWorkspace: null,
endpointClientWithoutWorkspace: null,
}
}

const publishableKeyClient = await SeamHttp.fromPublishableKey(
publishableKey,
userIdentifierKey,
clientOptions
if (consoleSessionToken != null) {
const clientWithoutWorkspace =
SeamHttpWithoutWorkspace.fromConsoleSessionToken(consoleSessionToken)

const endpointClientWithoutWorkspace =
SeamHttpEndpointsWithoutWorkspace.fromClient(
clientWithoutWorkspace.client
)

if (workspaceId == null) {
return {
client: null,
endpointClient: null,
clientWithoutWorkspace,
endpointClientWithoutWorkspace,
}
}

const seam = SeamHttp.fromConsoleSessionToken(
consoleSessionToken,
workspaceId,
clientOptions
)

return {
client: seam,
endpointClient: SeamHttpEndpoints.fromClient(seam.client),
clientWithoutWorkspace,
endpointClientWithoutWorkspace,
}
}

throw new Error(
'Missing either a client, publishableKey, clientSessionToken, or consoleSessionToken.'
)
return [
publishableKeyClient,
SeamHttpEndpoints.fromClient(publishableKeyClient.client),
]
},
})

return {
client: data?.[0] ?? null,
endpointClient: data?.[1] ?? null,
client: data?.client ?? null,
endpointClient: data?.endpointClient ?? null,
clientWithoutWorkspace: data?.clientWithoutWorkspace ?? null,
endpointClientWithoutWorkspace:
data?.endpointClientWithoutWorkspace ?? null,
queryKeyPrefixes: getQueryKeyPrefixes({
queryKeyPrefix,
userIdentifierKey,
publishableKey,
clientSessionToken,
consoleSessionToken,
workspaceId,
}),
isPending,
isError,
Expand Down Expand Up @@ -132,11 +191,15 @@ const getQueryKeyPrefixes = ({
userIdentifierKey,
publishableKey,
clientSessionToken,
consoleSessionToken,
workspaceId,
}: {
queryKeyPrefix: string | undefined
userIdentifierKey?: string
publishableKey?: string | undefined
clientSessionToken?: string | undefined
consoleSessionToken?: string | undefined
workspaceId?: string | undefined
}): string[] => {
const seamPrefix = 'seam'

Expand All @@ -150,5 +213,13 @@ const getQueryKeyPrefixes = ({
return [seamPrefix, publishableKey, userIdentifierKey]
}

if (consoleSessionToken != null) {
if (workspaceId != null) {
return [seamPrefix, consoleSessionToken, workspaceId]
}

return [seamPrefix, consoleSessionToken, 'without_workspace']
}

return [seamPrefix]
}
Loading
Loading