import { figmaRequest } from './client.ts'
import { mapImageMap } from './models.ts'
import { normalizeNodeIds, parseFileKey } from './setup.ts'
import type { FigmaAuthInput, FigmaImageMap } from './types.ts'
import {
compactRecord,
optionalBoolean,
optionalNumber,
optionalString,
requireRecord,
requireStringArray,
} from './types.ts'
import { requireAuthMode } from './auth.ts'
export type GetImagesInput = FigmaAuthInput & {
/** File key, or a figma.com file/design/board URL. */
fileKey: string
/** Node ids to render. Hyphenated URL ids (`1-2`) are accepted. */
ids: Array<string> | string
format?: 'jpg' | 'png' | 'svg' | 'pdf'
scale?: number
svgOutlineText?: boolean
svgIncludeId?: boolean
svgSimplifyStroke?: boolean
useAbsoluteBounds?: boolean
version?: string
}
/**
* Render images for nodes in a Figma file. Needs `file_content:read`.
* @example
* import getImages from 'kody:@kody/figma/get-images'
* const { images } = await getImages({ fileKey: 'abc123', ids: ['12:34'], format: 'png' })
*/
export async function getImages(input: GetImagesInput): Promise<FigmaImageMap> {
const fileKey = parseFileKey(input.fileKey)
const ids = normalizeNodeIds(requireStringArray(input.ids, 'ids'))
const format = optionalString(input.format, 'format')
if (format && format !== 'jpg' && format !== 'png' && format !== 'svg' && format !== 'pdf') {
throw new Error('format must be jpg, png, svg, or pdf.')
}
const scale = optionalNumber(input.scale, 'scale')
if (scale !== undefined && (scale < 0.01 || scale > 4)) {
throw new Error('scale must be between 0.01 and 4.')
}
const result = await figmaRequest<unknown>({
...input,
operation: 'files.read',
path: `/v1/images/${encodeURIComponent(fileKey)}`,
query: compactRecord({
ids: ids.join(','),
format,
scale,
svg_outline_text: optionalBoolean(input.svgOutlineText, 'svgOutlineText'),
svg_include_id: optionalBoolean(input.svgIncludeId, 'svgIncludeId'),
svg_simplify_stroke: optionalBoolean(input.svgSimplifyStroke, 'svgSimplifyStroke'),
use_absolute_bounds: optionalBoolean(input.useAbsoluteBounds, 'useAbsoluteBounds'),
version: optionalString(input.version, 'version'),
}),
})
return mapImageMap(fileKey, result.body)
}
/**
* Render images for nodes in a Figma file.
* @example
* import getImages from 'kody:@kody/figma/get-images'
* const result = await getImages({ fileKey: 'abc123', ids: '1-2', format: 'png' })
*/
export default async function getImagesEntrypoint(
params: Partial<GetImagesInput> & Record<string, unknown> = {},
) {
const input = requireRecord(params, 'get-images')
return getImages({
fileKey: String(input.fileKey ?? input.fileUrl ?? ''),
ids: input.ids as GetImagesInput['ids'],
format: optionalString(input.format, 'format') as GetImagesInput['format'],
scale: input.scale as number | undefined,
svgOutlineText: optionalBoolean(input.svgOutlineText, 'svgOutlineText'),
svgIncludeId: optionalBoolean(input.svgIncludeId, 'svgIncludeId'),
svgSimplifyStroke: optionalBoolean(input.svgSimplifyStroke, 'svgSimplifyStroke'),
useAbsoluteBounds: optionalBoolean(input.useAbsoluteBounds, 'useAbsoluteBounds'),
version: optionalString(input.version, 'version'),
integrationName: optionalString(input.integrationName, 'integrationName'),
integration: optionalString(input.integration, 'integration'),
account: optionalString(input.account, 'account'),
secretName: optionalString(input.secretName, 'secretName'),
auth: requireAuthMode(input.auth),
})
}