import { createHash, createHmac } from 'node:crypto'; import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api'; const algorithms = ['md5', 'sha1', 'sha256', 'sha512'] as const; const encodings = ['base64', 'hex'] as const; type TemplateFunctionPlugin = NonNullable[number]; const hashFunctions: TemplateFunctionPlugin[] = algorithms.map((algorithm) => ({ name: `hash.${algorithm}`, description: 'Hash a value to its hexadecimal representation', args: [ { type: 'text', name: 'input', label: 'Input', placeholder: 'input text', multiLine: true, }, { type: 'select', name: 'encoding', label: 'Encoding', defaultValue: 'base64', options: encodings.map((encoding) => ({ label: capitalize(encoding), value: encoding, })), }, ], async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise { const input = String(args.values.input); const encoding = String(args.values.encoding) as (typeof encodings)[number]; return createHash(algorithm).update(input, 'utf-8').digest(encoding); }, })); const hmacFunctions: TemplateFunctionPlugin[] = algorithms.map((algorithm) => ({ name: `hmac.${algorithm}`, description: 'Compute the HMAC of a value', args: [ { type: 'text', name: 'input', label: 'Input', placeholder: 'input text', multiLine: true, }, { type: 'text', name: 'key', label: 'Key', password: true, }, { type: 'select', name: 'encoding', label: 'Encoding', defaultValue: 'base64', options: encodings.map((encoding) => ({ value: encoding, label: capitalize(encoding), })), }, ], async onRender(_ctx: Context, args: CallTemplateFunctionArgs): Promise { const input = String(args.values.input); const key = String(args.values.key); const encoding = String(args.values.encoding) as (typeof encodings)[number]; return createHmac(algorithm, key, {}).update(input).digest(encoding); }, })); export const plugin: PluginDefinition = { templateFunctions: [...hashFunctions, ...hmacFunctions], }; function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1); }