Skip to content

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

Package listing

@kody/trello

src/accounts.ts

117 lines · 3.3 KB · TypeScript
import {
	API_KEY_SETUP_URL,
	DEFAULT_API_KEY_SECRET,
	DEFAULT_INTEGRATION_NAME,
	DEFAULT_TOKEN_SECRET,
	OAUTH_CONNECT_URL,
	TOKEN_SETUP_URL,
	TRELLO_APPS_ADMIN_URL,
	TRELLO_AUTHORIZE_PAGE_URL,
	TRELLO_CALLBACK_URL,
	TRELLO_REQUIRED_HOSTS,
	TRELLO_SCOPES,
	apiKeySetupUrl,
	oauthConnectUrl,
	resolveApiKeySecretName,
	resolveIntegrationName,
	resolveTokenSecretName,
	tokenSetupUrl,
	trelloAuthorizeUrl,
} from './setup.ts'
import {
	listTrelloIntegrationNames,
	listUserSecretNames,
	parseAuthInput,
	requireAuthMode,
	type ResolvedTrelloAuth,
} from './auth.ts'
import type { TrelloAuthInput } from './types.ts'
import { requireRecord } from './types.ts'

export type TrelloAccountResolution = {
	integrationName: string
	apiKeySecretName: string
	tokenSecretName: string
	oauthConnected: boolean
	apiKeySaved: boolean
	tokenSaved: boolean
	keyTokenSaved: boolean
	preferredAuth: ResolvedTrelloAuth['mode'] | null
	connectUrl: string
	reconnectUrl: string
	apiKeyUrl: string
	tokenUrl: string
	authorizeUrl: string
	scopes: typeof TRELLO_SCOPES
	requiredHosts: Array<string>
	callbackUrl: string
	appsAdminUrl: string
}

/**
 * Resolve which Trello OAuth integration or API key + token to use.
 * @example
 * import { accounts } from 'kody:@kody/trello/accounts'
 * const info = await accounts({ account: 'work' })
 */
export async function accounts(params: TrelloAuthInput = {}): Promise<TrelloAccountResolution> {
	const integrationName = resolveIntegrationName(params)
	const apiKeySecretName = resolveApiKeySecretName(params)
	const tokenSecretName = resolveTokenSecretName(params)
	const [secrets, integrations] = await Promise.all([
		listUserSecretNames(),
		listTrelloIntegrationNames(),
	])
	const oauthConnected = integrations.includes(integrationName)
	const apiKeySaved = secrets.has(apiKeySecretName)
	const tokenSaved = secrets.has(tokenSecretName)
	const keyTokenSaved = apiKeySaved && tokenSaved
	const forced = requireAuthMode(params.auth)
	let preferredAuth: TrelloAccountResolution['preferredAuth'] = null
	if (forced === 'oauth' && oauthConnected) preferredAuth = 'oauth'
	else if (forced === 'keyToken' && keyTokenSaved) preferredAuth = 'keyToken'
	else if (keyTokenSaved) preferredAuth = 'keyToken'
	else if (oauthConnected) preferredAuth = 'oauth'

	return {
		integrationName,
		apiKeySecretName,
		tokenSecretName,
		oauthConnected,
		apiKeySaved,
		tokenSaved,
		keyTokenSaved,
		preferredAuth,
		connectUrl: oauthConnectUrl(integrationName),
		reconnectUrl: `https://kody.codes/connect/oauth?provider=${encodeURIComponent(integrationName)}`,
		apiKeyUrl: apiKeySetupUrl(apiKeySecretName),
		tokenUrl: tokenSetupUrl(tokenSecretName),
		authorizeUrl: trelloAuthorizeUrl(),
		scopes: TRELLO_SCOPES,
		requiredHosts: [...TRELLO_REQUIRED_HOSTS],
		callbackUrl: TRELLO_CALLBACK_URL,
		appsAdminUrl: TRELLO_APPS_ADMIN_URL,
	}
}

export {
	API_KEY_SETUP_URL,
	DEFAULT_API_KEY_SECRET,
	DEFAULT_INTEGRATION_NAME,
	DEFAULT_TOKEN_SECRET,
	OAUTH_CONNECT_URL,
	TOKEN_SETUP_URL,
	TRELLO_AUTHORIZE_PAGE_URL,
}

/**
 * Resolve which Trello OAuth integration or API key + token to use.
 * @example
 * import accounts from 'kody:@kody/trello/accounts'
 * const info = await accounts()
 */
export default async function accountsEntrypoint(
	params: TrelloAuthInput & Record<string, unknown> = {},
) {
	return accounts(parseAuthInput(requireRecord(params, 'accounts')))
}