/** * Represents a file attached to a {@link LimeObject} * * LimeFile provides metadata and URLs for files that are stored as attachments * on Lime objects. This interface is typically used when working with file * properties on LimeObjects, allowing components to display file information * and provide download or viewing capabilities. * * Files can be accessed in different ways depending on the use case - for direct * download, inline viewing, editing, or PDF conversion. * * @example Displaying files from a LimeObject * ```ts * import type { LimeFile } from '@limetech/lime-web-components'; * import { * PlatformServiceName, * createLogger, * } from '@limetech/lime-web-components'; * * const logger = createLogger('my-component'); * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const deal = repository.getObject('deal', 1234); * * // Every file sits on its own file property, so there is no list to read * const attachments = ['contract', 'quote', 'drawing'] * .map((property) => deal?.getFile(property)) * .filter((file): file is LimeFile => !!file); * * for (const file of attachments) { * logger.info(`${file.filename} is ${file.size} bytes`, { * download: file.getUrl('download'), * }); * } * ``` * * @public * @group Lime objects */ export interface LimeFile { /** * The unique identifier of the file in the Lime database * * @example Use the id as a key * ```ts * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const contract = repository.getObject('deal', 1234)?.getFile('contract'); * * // The id is optional, so fall back to the filename when it is missing * const key = contract?.id ?? contract?.filename; * ``` * * @beta */ readonly id?: number; /** * The name of the file including its extension * * This is the original filename as it was uploaded or created, * including the file extension. * * @example Read the filename * ```ts * import { * PlatformServiceName, * createLogger, * } from '@limetech/lime-web-components'; * * const logger = createLogger('my-component'); * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const contract = repository.getObject('deal', 1234)?.getFile('contract'); * * if (contract) { * logger.info(contract.filename); // "annual-report.pdf" * } * ``` */ readonly filename: string; /** * The file extension without the leading dot * * The extension is extracted from the filename and provided separately * for convenience when filtering or categorizing files. * * @example Pick out the image files * ```ts * import type { LimeFile } from '@limetech/lime-web-components'; * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const IMAGE_EXTENSIONS = new Set(['jpg', 'jpeg', 'png', 'gif']); * * function isImage(file: LimeFile): boolean { * return IMAGE_EXTENSIONS.has(file.extension.toLowerCase()); * } * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const attachment = repository.getObject('deal', 1234)?.getFile('drawing'); * * const imageUrl = * attachment && isImage(attachment) ? attachment.getUrl('view') : undefined; * ``` */ readonly extension: string; /** * The size of the file in bytes * * Use this to display file size information to users or to implement * file size validation. * * @example Show the size in megabytes * ```ts * import type { LimeFile } from '@limetech/lime-web-components'; * import { * PlatformServiceName, * createLogger, * } from '@limetech/lime-web-components'; * * const logger = createLogger('my-component'); * * function formatSize(file: LimeFile): string { * const megabytes = file.size / (1024 * 1024); * * return `${megabytes.toFixed(2)} MB`; * } * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const contract = repository.getObject('deal', 1234)?.getFile('contract'); * * if (contract) { * logger.info(`File size: ${formatSize(contract)}`); * } * ``` * * @example File size validation * ```ts * import { * PlatformServiceName, * createLogger, * } from '@limetech/lime-web-components'; * * const MAX_SIZE = 10 * 1024 * 1024; * * const logger = createLogger('my-component'); * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const contract = repository.getObject('deal', 1234)?.getFile('contract'); * * if (contract && contract.size > MAX_SIZE) { * logger.error('File too large', undefined, { * filename: contract.filename, * size: contract.size, * max: MAX_SIZE, * }); * } * ``` */ readonly size: number; /** * Get a URL for accessing the file in different ways * * Different URL types are available depending on how you want to access * the file. Some URL types may return `undefined` if not supported for * the specific file type. * * @param type - The type of URL to retrieve. See {@link LimeFileUrlType} * for available options. * @returns The URL as a string, or `undefined` if the URL type is not * available for this file. * * @example Fall back when a url type is missing * ```ts * import type { LimeFile } from '@limetech/lime-web-components'; * import { PlatformServiceName } from '@limetech/lime-web-components'; * * // A pdf url only exists when conversion is available for the file type * function getPreviewUrl(file: LimeFile): string | undefined { * return file.getUrl('pdf') ?? file.getUrl('view'); * } * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const contract = repository.getObject('deal', 1234)?.getFile('contract'); * const previewUrl = contract && getPreviewUrl(contract); * * if (previewUrl) { * window.open(previewUrl); * } * ``` */ getUrl(type: LimeFileUrlType): string | undefined; } /** * Types of URLs that can be retrieved for a file * * Different URL types provide different ways to access or interact with files. * * - `contents`: Raw file contents URL * - `download`: URL that triggers a file download * - `edit`: URL for editing the file (if supported) * - `pdf`: URL for a PDF version of the file (if conversion is available) * - `view`: URL for viewing the file inline in the browser * * @example Using different URL types * ```ts * import type { LimeFileUrlType } from '@limetech/lime-web-components'; * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const contract = repository.getObject('deal', 1234)?.getFile('contract'); * * const downloadUrl = contract?.getUrl('download'); * const viewUrl = contract?.getUrl('view'); * const pdfUrl = contract?.getUrl('pdf'); * * // The type can also come from a variable or a component property * const type: LimeFileUrlType = 'edit'; * const editUrl = contract?.getUrl(type); * ``` * * @public * @group Lime objects */ export type LimeFileUrlType = 'contents' | 'download' | 'edit' | 'pdf' | 'view';