import {
asStringArray,
DEFAULT_COUNTRY_CODES,
DEFAULT_PRODUCTS,
mutationPreview,
plaidRequest,
requireString,
type MutationGuardInput,
} from './plaid-core.ts'
export type CreateLinkTokenInput = MutationGuardInput & {
clientName?: string
language?: string
countryCodes?: string[]
products?: string[]
clientUserId?: string
webhook?: string
redirectUri?: string
/** Link update mode for an existing Item. Never collect a bank password. */
accessToken?: string
}
/**
* Create a Plaid Link token (`/link/token/create`). Defaults to dry-run;
* live creation needs `confirm: true`.
*
* Link itself collects bank credentials in Plaid's UI. Agents must never ask
* for or store a bank username or password in chat.
*/
export async function createLinkToken(input: CreateLinkTokenInput = {}) {
const live = input.confirm === true && input.dryRun !== true
const clientName = live ? requireString(input.clientName ?? 'Kody', 'clientName') : (input.clientName ?? 'Kody')
const clientUserId = live
? requireString(input.clientUserId, 'clientUserId')
: (input.clientUserId ?? '<client_user_id>')
const products = asStringArray(input.products, DEFAULT_PRODUCTS)
const countryCodes = asStringArray(input.countryCodes, DEFAULT_COUNTRY_CODES)
const body: Record<string, unknown> = {
client_name: clientName,
language: input.language ?? 'en',
country_codes: countryCodes,
user: { client_user_id: clientUserId },
products,
...(input.webhook ? { webhook: input.webhook } : {}),
...(input.redirectUri ? { redirect_uri: input.redirectUri } : {}),
...(input.accessToken ? { access_token: '<access_token>' } : {}),
}
const preview = mutationPreview(input, {
action: 'create link token',
method: 'POST',
path: '/link/token/create',
body,
})
if (preview) return preview
const liveBody: Record<string, unknown> = {
client_name: clientName,
language: input.language ?? 'en',
country_codes: countryCodes,
user: { client_user_id: clientUserId },
products,
...(input.webhook ? { webhook: input.webhook } : {}),
...(input.redirectUri ? { redirect_uri: input.redirectUri } : {}),
...(input.accessToken ? { access_token: input.accessToken } : {}),
}
const data = await plaidRequest({
...input,
path: '/link/token/create',
body: liveBody,
})
return {
link_token: data?.link_token ?? null,
expiration: data?.expiration ?? null,
request_id: data?.request_id ?? null,
hosted_link_url: data?.hosted_link_url ?? null,
note: 'Open Plaid Link with this token. Do not collect bank login passwords in chat.',
}
}
export default createLinkToken