Skip to content

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

Package listing

@kody/meta

src/request.ts

73 lines · 2.3 KB · TypeScript
import { resolveMetaIntegration } from './accounts.ts'
import { graphRequest, isReadOnlyMethod, type GraphRequestParams } from './core.ts'
import { type GraphMethod } from './scopes.ts'
import { inputRecord, optionalRecord, optionalString, requiredString } from './validation.ts'

function parseMethod(value: string | undefined): GraphMethod {
	const method = (value ?? 'GET').toUpperCase()
	switch (method) {
		case 'GET':
		case 'POST':
		case 'PATCH':
		case 'PUT':
		case 'DELETE':
			return method
		default:
			throw new Error('method must be GET, POST, PATCH, PUT, or DELETE.')
	}
}

/**
 * Call any Meta Graph path through saved OAuth or a system user token.
 * Mutating requests require `confirm: true`; use `dryRun: true` to preview.
 * @example
 * import request from 'kody:@kody/meta/request'
 * const me = await request({ path: '/me', query: { fields: 'id,name' } })
 */
export default async function request(params: Record<string, unknown> = {}) {
	const input = inputRecord(params)
	const path = requiredString(input, 'path')
	const method = parseMethod(optionalString(input, 'method'))
	const body = optionalRecord(input, 'body')
	const query = optionalRecord(input, 'query') as GraphRequestParams['query']
	const integration = optionalString(input, 'integration')
	const account = optionalString(input, 'account')
	const tokenSecret = optionalString(input, 'tokenSecret')
	const authMode = optionalString(input, 'authMode')
	if (authMode && authMode !== 'oauth' && authMode !== 'system-user') {
		throw new Error("authMode must be 'oauth' or 'system-user'.")
	}
	const resolvedAuthMode = authMode === 'system-user' || authMode === 'oauth' ? authMode : undefined

	if (!isReadOnlyMethod(method)) {
		if (input.dryRun === true) {
			return {
				dryRun: true as const,
				method,
				path,
				query: query ?? null,
				body: body ?? null,
				integration: resolveMetaIntegration({ integration, account }),
			}
		}
		if (input.confirm !== true) {
			throw new Error(
				method +
					' ' +
					path +
					' mutates Meta data and requires confirm: true after explicit user approval. Use dryRun: true to preview. Do not send live WhatsApp or Page posts without that confirmation.',
			)
		}
	}

	return graphRequest({
		integration: resolveMetaIntegration({ integration, account }),
		account,
		tokenSecret,
		authMode: resolvedAuthMode,
		path,
		method,
		query,
		body,
	})
}