Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/workos

src/auth.ts

68 lines · 2.1 KB · TypeScript
import { kody } from 'kody:runtime'
import type { WorkosAuthInput } from './types.ts'
import { optionalString } from './types.ts'
import { DEFAULT_API_KEY_SECRET, missingCredentialsMessage } from './setup.ts'

export type ResolvedWorkosAuth = {
	secretName: string
	authorization: string
}

function secretEntries(result: unknown): Array<{ name?: string; scope?: string }> {
	if (
		result &&
		typeof result === 'object' &&
		Array.isArray((result as { secrets?: unknown }).secrets)
	) {
		return (result as { secrets: Array<{ name?: string; scope?: string }> }).secrets
	}
	return Array.isArray(result) ? result : []
}

export async function listUserSecretNames(): Promise<Set<string>> {
	const listed = await kody.secret_list({ scope: 'user' })
	const names = new Set<string>()
	for (const entry of secretEntries(listed)) {
		if (entry?.name && (entry.scope === 'user' || !entry.scope)) {
			names.add(entry.name)
		}
	}
	return names
}

export function resolveSecretName(input: WorkosAuthInput = {}): string {
	const explicit = optionalString(input.secretName, 'secretName')
	if (explicit) return explicit
	const account = optionalString(input.account, 'account')
	if (!account || account === 'default' || account === 'workos') {
		return DEFAULT_API_KEY_SECRET
	}
	if (account.startsWith('workosApiKey-') || account.startsWith('workos-')) {
		return account.startsWith('workosApiKey-') ? account : `workosApiKey-${account.slice('workos-'.length)}`
	}
	return `workosApiKey-${account}`
}

export async function resolveWorkosAuth(
	input: WorkosAuthInput = {},
): Promise<ResolvedWorkosAuth> {
	const secretName = resolveSecretName(input)
	const secrets = await listUserSecretNames()
	if (!secrets.has(secretName)) {
		throw new Error(missingCredentialsMessage({ secretName }))
	}
	return {
		secretName,
		authorization: `Bearer {{secret:${secretName}}}`,
	}
}

export async function workosFetch(
	auth: ResolvedWorkosAuth,
	url: string,
	init: RequestInit,
): Promise<Response> {
	const headers = new Headers(init.headers)
	headers.set('Authorization', `Bearer {{secret:${auth.secretName}}}`)
	return fetch(url, { ...init, headers })
}