Skip to content

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

Package listing

@kody/meta

src/smoke-test.ts

84 lines · 2.3 KB · TypeScript
import { kody } from 'kody:runtime'
import {
	resolveAuthMode,
	resolveMetaIntegration,
	resolveSystemUserSecret,
	type MetaAccountParams,
} from './accounts.ts'
import { graphRequest, type JsonObject } from './core.ts'
import { setupUrls } from './scopes.ts'

export type SmokeTestSuccess = {
	ok: true
	authMode: 'oauth' | 'system-user'
	integration: string
	id: string | null
	name: string | null
}

export type SmokeTestSetup = {
	ok: false
	reason: 'not_connected'
	auth: 'oauth-or-system-user'
	setup: ReturnType<typeof setupUrls>
}

export type SmokeTestResult = SmokeTestSuccess | SmokeTestSetup

async function hasOauthIntegration(name: string): Promise<boolean> {
	try {
		const listed = await kody.integration_list({})
		const items = listed.integrations ?? []
		return items.some((item) => item.name === name)
	} catch {
		return false
	}
}

async function hasSystemUserSecret(name: string): Promise<boolean> {
	try {
		const listed = await kody.secret_list({})
		return listed.secrets.some((item) => item.name === name)
	} catch {
		return false
	}
}

/**
 * Verify Meta Graph auth with GET /me. Does not publish, comment, or send WhatsApp.
 * Missing credentials return `{ ok: false, setup }` with prefilled connect / secret URLs.
 * @example
 * import smokeTest from 'kody:@kody/meta/smoke-test'
 * const result = await smokeTest()
 */
export default async function smokeTest(params: MetaAccountParams = {}): Promise<SmokeTestResult> {
	const integration = resolveMetaIntegration(params)
	const tokenSecret = resolveSystemUserSecret(params)
	const requestedMode = params.authMode ? resolveAuthMode(params) : null
	const oauthReady = await hasOauthIntegration(integration)
	const secretReady = await hasSystemUserSecret(tokenSecret)
	const setup = setupUrls(integration, tokenSecret)

	let authMode = requestedMode
	if (!authMode) {
		if (oauthReady) authMode = 'oauth'
		else if (secretReady) authMode = 'system-user'
		else return { ok: false, reason: 'not_connected', auth: 'oauth-or-system-user', setup }
	}

	const me = await graphRequest<JsonObject>({
		integration,
		account: params.account,
		tokenSecret,
		authMode,
		path: '/me',
		query: { fields: 'id,name' },
	})
	return {
		ok: true,
		authMode,
		integration: authMode === 'system-user' ? tokenSecret : integration,
		id: typeof me.id === 'string' ? me.id : null,
		name: typeof me.name === 'string' ? me.name : null,
	}
}