Skip to content

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

Package listing

@kody/meta

src/accounts.ts

124 lines · 4.3 KB · TypeScript
export const DEFAULT_META_INTEGRATION = 'meta'
export const DEFAULT_SYSTEM_USER_SECRET = 'metaSystemUserToken'

export type MetaAuthMode = 'oauth' | 'system-user'

export type MetaAccountParams = {
	/** Exact Kody OAuth integration name. Wins over `account`. */
	integration?: string
	/**
	 * Convenience alias. `default` / `meta` / omitted → `meta`.
	 * `work` → `meta-work`. Values that already start with `meta-`
	 * are used as-is.
	 */
	account?: string
	/** Auth lane. Default `oauth`. Use `system-user` for a Business system user token secret. */
	authMode?: MetaAuthMode
	/** Secret name for a system user token. Defaults to `metaSystemUserToken` or `metaSystemUserToken-<purpose>`. */
	tokenSecret?: string
}

export type MetaAccountInfo = {
	account: string
	integrationName: string
	tokenSecret: string
	authMode: MetaAuthMode
	useWhen: string
}

/**
 * Resolve which saved Meta OAuth integration to use.
 *
 * - `integration` wins when set (exact name, e.g. `meta-work`)
 * - `account: 'work'` → `meta-work`
 * - `account: 'default'` / `'meta'` / omitted → `meta`
 * - bare values that already start with `meta-` are used as-is
 */
export function resolveMetaIntegration(input: MetaAccountParams | string = {}): string {
	if (typeof input === 'string') {
		return resolveMetaIntegration({ account: input })
	}
	const explicit = input.integration?.trim()
	if (explicit) return explicit

	const account = input.account?.trim()
	if (!account || account === 'default' || account === 'meta') {
		return DEFAULT_META_INTEGRATION
	}
	if (account.startsWith('meta-') || account === DEFAULT_META_INTEGRATION) {
		return account
	}
	return 'meta-' + account
}

export function resolveAuthMode(input: MetaAccountParams = {}): MetaAuthMode {
	if (input.authMode === 'system-user' || (input.tokenSecret && input.tokenSecret.trim())) {
		return 'system-user'
	}
	return 'oauth'
}

export function resolveSystemUserSecret(input: MetaAccountParams | string = {}): string {
	if (typeof input === 'string') {
		return resolveSystemUserSecret({ account: input })
	}
	const explicit = input.tokenSecret?.trim()
	if (explicit) return explicit

	const account = input.account?.trim()
	if (!account || account === 'default' || account === 'meta') {
		return DEFAULT_SYSTEM_USER_SECRET
	}
	if (account.startsWith(DEFAULT_SYSTEM_USER_SECRET + '-')) {
		return account
	}
	const purpose = account.startsWith('meta-') ? account.slice('meta-'.length) : account
	return DEFAULT_SYSTEM_USER_SECRET + '-' + purpose
}

export function describeMetaAccount(input: MetaAccountParams | string = {}): MetaAccountInfo {
	const params = typeof input === 'string' ? { account: input } : input
	const authMode = resolveAuthMode(params)
	const integrationName = resolveMetaIntegration(params)
	const tokenSecret = resolveSystemUserSecret(params)
	const account =
		typeof input === 'string'
			? input || 'default'
			: params.account?.trim() || (params.integration ? params.integration : 'default')
	return {
		account,
		integrationName,
		tokenSecret,
		authMode,
		useWhen:
			authMode === 'system-user'
				? 'Business system user token secret ' +
					tokenSecret +
					'. Save it at /account/secrets/new, never paste the value into chat.'
				: integrationName === DEFAULT_META_INTEGRATION
					? 'Default Meta Graph connection. Connect at /connect/oauth?provider=meta.'
					: 'Additional Meta account. Connect at /connect/oauth?provider=' + integrationName + '.',
	}
}

/**
 * Return how this package maps `account` / `integration` to a Kody connection.
 * @example
 * import accounts from 'kody:@kody/meta/accounts'
 * const { defaultIntegration } = accounts()
 * // => 'meta'
 */
export default function accounts() {
	return {
		defaultIntegration: DEFAULT_META_INTEGRATION,
		defaultSystemUserSecret: DEFAULT_SYSTEM_USER_SECRET,
		naming:
			'Pass integration for an exact Kody OAuth name, or account as a short alias (`work` → meta-work). System user tokens use metaSystemUserToken or metaSystemUserToken-<purpose>.',
		examples: [
			{ account: 'default', integrationName: 'meta', tokenSecret: 'metaSystemUserToken' },
			{ account: 'work', integrationName: 'meta-work', tokenSecret: 'metaSystemUserToken-work' },
			{ integration: 'meta-personal', integrationName: 'meta-personal' },
			{ authMode: 'system-user', tokenSecret: 'metaSystemUserToken' },
		],
	}
}