Files
simstudioai--sim/apps/sim/hooks/queries/oauth/oauth-credentials.ts
T
wehub-resource-sync d25d482dc2
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:20:55 +08:00

164 lines
4.7 KiB
TypeScript

import { useQuery } from '@tanstack/react-query'
import { requestJson } from '@/lib/api/client/request'
import { listOAuthCredentialsContract } from '@/lib/api/contracts'
import type { Credential } from '@/lib/oauth'
import { useWorkspaceCredential } from '@/hooks/queries/credentials'
export const OAUTH_CREDENTIAL_LIST_STALE_TIME = 60 * 1000
export const OAUTH_CREDENTIAL_DETAIL_STALE_TIME = 60 * 1000
export const oauthCredentialKeys = {
all: ['oauthCredentials'] as const,
lists: () => [...oauthCredentialKeys.all, 'list'] as const,
list: (providerId?: string, workspaceId?: string, workflowId?: string) =>
[
...oauthCredentialKeys.lists(),
providerId ?? 'none',
workspaceId ?? 'none',
workflowId ?? 'none',
] as const,
details: () => [...oauthCredentialKeys.all, 'detail'] as const,
detail: (credentialId?: string, workflowId?: string) =>
[...oauthCredentialKeys.details(), credentialId ?? 'none', workflowId ?? 'none'] as const,
}
interface FetchOAuthCredentialsParams {
providerId: string
workspaceId?: string
workflowId?: string
}
export async function fetchOAuthCredentials(
params: FetchOAuthCredentialsParams,
signal?: AbortSignal
): Promise<Credential[]> {
const { providerId, workspaceId, workflowId } = params
if (!providerId) return []
const data = await requestJson(listOAuthCredentialsContract, {
signal,
query: {
provider: providerId,
workspaceId,
workflowId,
},
})
return data.credentials ?? []
}
export async function fetchOAuthCredentialDetail(
credentialId: string,
workflowId?: string,
signal?: AbortSignal
): Promise<Credential[]> {
if (!credentialId) return []
const data = await requestJson(listOAuthCredentialsContract, {
signal,
query: {
credentialId,
workflowId,
},
})
return data.credentials ?? []
}
interface UseOAuthCredentialsOptions {
enabled?: boolean
workspaceId?: string
workflowId?: string
}
function resolveOptions(
enabledOrOptions?: boolean | UseOAuthCredentialsOptions
): Required<UseOAuthCredentialsOptions> {
if (typeof enabledOrOptions === 'boolean') {
return {
enabled: enabledOrOptions,
workspaceId: '',
workflowId: '',
}
}
return {
enabled: enabledOrOptions?.enabled ?? true,
workspaceId: enabledOrOptions?.workspaceId ?? '',
workflowId: enabledOrOptions?.workflowId ?? '',
}
}
export function useOAuthCredentials(
providerId?: string,
enabledOrOptions?: boolean | UseOAuthCredentialsOptions
) {
const { enabled, workspaceId, workflowId } = resolveOptions(enabledOrOptions)
return useQuery<Credential[]>({
queryKey: oauthCredentialKeys.list(providerId, workspaceId, workflowId),
queryFn: ({ signal }) =>
fetchOAuthCredentials(
{
providerId: providerId ?? '',
workspaceId: workspaceId || undefined,
workflowId: workflowId || undefined,
},
signal
),
enabled: Boolean(providerId) && enabled,
staleTime: OAUTH_CREDENTIAL_LIST_STALE_TIME,
})
}
export function useOAuthCredentialDetail(
credentialId?: string,
workflowId?: string,
enabled = true
) {
return useQuery<Credential[]>({
queryKey: oauthCredentialKeys.detail(credentialId, workflowId),
queryFn: ({ signal }) => fetchOAuthCredentialDetail(credentialId ?? '', workflowId, signal),
enabled: Boolean(credentialId) && enabled,
staleTime: OAUTH_CREDENTIAL_DETAIL_STALE_TIME,
})
}
export function useCredentialName(
credentialId?: string,
providerId?: string,
workflowId?: string,
workspaceId?: string
) {
const { data: credentials = [], isFetching: credentialsLoading } = useOAuthCredentials(
providerId,
{
enabled: Boolean(providerId),
workspaceId,
workflowId,
}
)
const selectedCredential = credentials.find((cred) => cred.id === credentialId)
const shouldFetchDetail = Boolean(credentialId && !selectedCredential && providerId && workflowId)
const { data: foreignCredentials = [], isFetching: foreignLoading } = useOAuthCredentialDetail(
shouldFetchDetail ? credentialId : undefined,
workflowId,
shouldFetchDetail
)
// Fallback for credential blocks that have no serviceId/providerId — look up by ID directly
const { data: workspaceCredential, isFetching: workspaceCredentialLoading } =
useWorkspaceCredential(!providerId ? credentialId : undefined)
const detailCredential = foreignCredentials[0]
const hasForeignMeta = foreignCredentials.length > 0
const displayName =
selectedCredential?.name ?? detailCredential?.name ?? workspaceCredential?.displayName ?? null
return {
displayName,
isLoading: credentialsLoading || foreignLoading || workspaceCredentialLoading,
hasForeignMeta,
}
}