UNPKG

lokalise-file-exchange

Version:
416 lines (397 loc) 16.7 kB
import { DownloadFileParams, UploadFileParams, QueuedProcess, LokaliseApi, ClientParams, DownloadBundle } from '@lokalise/node-api'; import { LogThreshold, LogFunction, LogLevel } from 'kliedz'; /** * Describes the structure of a Lokalise error. */ interface LokaliseError$1 { /** * The error message. */ message: string; /** * The error code representing the type of Lokalise API error. */ code?: number | undefined; /** * Additional details about the error (optional). */ details?: Record<string, string | number | boolean>; } /** * Represents a custom error. */ declare class LokaliseError extends Error implements LokaliseError$1 { /** * The error code representing the type of Lokalise API error. */ code?: number | undefined; /** * Additional details about the error. */ details?: Record<string, string | number | boolean>; /** * Creates a new instance of LokaliseError. * * @param message - The error message. * @param code - The error code (optional). * @param details - Optional additional details about the error. */ constructor(message: string, code?: number, details?: Record<string, string | number | boolean>); /** * Returns a string representation of the error, including code and details. * * @returns The formatted error message. */ toString(): string; } interface CollectFileParams { inputDirs?: string[]; extensions?: string[]; excludePatterns?: string[] | RegExp[]; recursive?: boolean; fileNamePattern?: string | RegExp; } interface ExtractParams { outputDir?: string; } interface ProcessDownloadFileParams { asyncDownload?: boolean; pollInitialWaitTime?: number; pollMaximumWaitTime?: number; bundleDownloadTimeout?: number; } interface DownloadTranslationParams { downloadFileParams: DownloadFileParams; extractParams?: ExtractParams; processDownloadFileParams?: ProcessDownloadFileParams; } interface FileUploadError { file: string; error: unknown; } interface LokaliseExchangeConfig { projectId: string; useOAuth2?: boolean; retryParams?: Partial<RetryParams>; logThreshold?: LogThreshold; logColor?: boolean; } type UploadFileParamsBase = Omit<UploadFileParams, "data" | "filename" | "lang_iso">; interface PartialUploadFileParams extends UploadFileParamsBase { } interface ProcessedFile { data: string; filename: string; lang_iso: string; } type Inferer = (filePath: string) => Promise<string> | string; interface ProcessUploadFileParams { languageInferer?: Inferer; filenameInferer?: Inferer; pollStatuses?: boolean; pollInitialWaitTime?: number; pollMaximumWaitTime?: number; } interface QueuedUploadProcessesWithErrors { processes: QueuedProcess[]; errors: FileUploadError[]; } interface RetryParams { maxRetries: number; initialSleepTime: number; jitterRatio: number; rng: () => number; } interface UploadTranslationParams { uploadFileParams?: PartialUploadFileParams; collectFileParams?: CollectFileParams; processUploadFileParams?: ProcessUploadFileParams; } /** * A utility class for exchanging files with the Lokalise API. */ declare class LokaliseFileExchange { /** * The Lokalise API client instance. */ protected readonly apiClient: LokaliseApi; /** * The ID of the project in Lokalise. */ protected readonly projectId: string; /** * Retry parameters for API requests. */ protected readonly retryParams: RetryParams; /** * Logger function. */ protected readonly logger: LogFunction; /** * Log threshold (do not print messages with severity less than the specified value). */ protected readonly logThreshold: LogThreshold; /** * Default retry parameters for API requests. */ private static readonly defaultRetryParams; private static readonly FINISHED_STATUSES; private static readonly RETRYABLE_CODES; protected static readonly maxConcurrentProcesses = 6; private static isPendingStatus; static isFinishedStatus(status?: string | null): boolean; /** * Creates a new instance of LokaliseFileExchange. * * @param clientConfig - Configuration for the Lokalise SDK. * @param exchangeConfig - The configuration object for file exchange operations. * @throws {LokaliseError} If the provided configuration is invalid. */ constructor(clientConfig: ClientParams, { projectId, useOAuth2, retryParams, logThreshold, logColor, }: LokaliseExchangeConfig); /** * Executes an asynchronous operation with exponential backoff retry logic. */ protected withExponentialBackoff<T>(operation: () => Promise<T>): Promise<T>; /** * Polls the status of queued processes until they are marked as "finished" or until the maximum wait time is exceeded. */ protected pollProcesses(processes: QueuedProcess[], initialWaitTime: number, maxWaitTime: number, concurrency?: number): Promise<QueuedProcess[]>; /** * Determines if a given error is eligible for retry. */ private isRetryable; /** * Logs a message with a specified level and the current threshold. */ protected logMsg(level: LogLevel, ...args: unknown[]): void; /** * Retrieves the latest state of a queued process from the API. */ protected getUpdatedProcess(processId: string): Promise<QueuedProcess>; /** * Validates the required client configuration parameters. */ private validateParams; protected runWithConcurrencyLimit<T, R>(items: T[], limit: number, worker: (item: T, index: number) => Promise<R>): Promise<R[]>; protected fetchProcessesBatch(processIds: string[], concurrency?: number): Promise<Array<{ id: string; process?: QueuedProcess; }>>; /** * Pauses execution for the specified number of milliseconds. */ protected static sleep(ms: number): Promise<void>; } /** * Handles downloading and extracting translation files from Lokalise. */ declare class LokaliseDownload extends LokaliseFileExchange { private static readonly defaultProcessParams; private readonly streamPipeline; /** * Downloads translations from Lokalise, optionally using async polling, and extracts them to disk. * * @param downloadTranslationParams - Full configuration for the download process, extraction destination, and optional polling or timeout settings. * @throws {LokaliseError} If the download, polling, or extraction fails. */ downloadTranslations({ downloadFileParams, extractParams, processDownloadFileParams, }: DownloadTranslationParams): Promise<void>; /** * Unpacks a ZIP file into the specified directory. * * @param zipFilePath - Path to the ZIP file. * @param outputDir - Directory to extract the files into. * @throws {LokaliseError} If extraction fails or malicious paths are detected. */ protected unpackZip(zipFilePath: string, outputDir: string): Promise<void>; /** * Downloads a ZIP file from the given URL. * * @param url - The URL of the ZIP file. * @returns The file path of the downloaded ZIP file. * @throws {LokaliseError} If the download fails or the response body is empty. */ protected downloadZip(url: string, downloadTimeout?: number): Promise<string>; /** * Retrieves a translation bundle from Lokalise with retries and exponential backoff. * * @param downloadFileParams - Parameters for Lokalise API file download. * @returns The downloaded bundle metadata. * @throws {LokaliseError} If retries are exhausted or an API error occurs. */ protected getTranslationsBundle(downloadFileParams: DownloadFileParams): Promise<DownloadBundle>; /** * Retrieves a translation bundle from Lokalise with retries and exponential backoff. * * @param downloadFileParams - Parameters for Lokalise API file download. * @returns The queued process. * @throws {LokaliseError} If retries are exhausted or an API error occurs. */ protected getTranslationsBundleAsync(downloadFileParams: DownloadFileParams): Promise<QueuedProcess>; /** * Extracts a single entry from a ZIP archive to the specified output directory. * * Creates necessary directories and streams the file content to disk. * * @param entry - The ZIP entry to extract. * @param zipfile - The open ZIP file instance. * @param outputDir - The directory where the entry should be written. * @returns A promise that resolves when the entry is fully written. */ private handleZipEntry; /** * Creates a directory and all necessary parent directories. * * @param dir - The directory path to create. * @returns A promise that resolves when the directory is created. */ private createDir; /** * Resolves and validates the full output path for a ZIP entry. * * Prevents path traversal attacks by ensuring the resolved path stays within the output directory. * * @param outputDir - The base output directory. * @param entryFilename - The filename of the ZIP entry. * @returns The absolute and safe path to write the entry. * @throws {LokaliseError} If the entry path is detected as malicious. */ private processZipEntryPath; /** * Parses and validates a URL string, ensuring it uses HTTP or HTTPS protocol. * * @param value - The URL string to validate. * @returns A parsed `URL` object if valid. * @throws {LokaliseError} If the URL is invalid or uses an unsupported protocol. */ private assertHttpUrl; } /** * Handles uploading translation files to Lokalise. */ declare class LokaliseUpload extends LokaliseFileExchange { private static readonly defaultPollingParams; /** * Collects files, uploads them to Lokalise, and optionally polls for process completion, returning both processes and errors. * * @param {UploadTranslationParams} uploadTranslationParams - Parameters for collecting and uploading files. * @returns {Promise<{ processes: QueuedProcess[]; errors: FileUploadError[] }>} A promise resolving with successful processes and upload errors. */ uploadTranslations({ uploadFileParams, collectFileParams, processUploadFileParams, }?: UploadTranslationParams): Promise<QueuedUploadProcessesWithErrors>; /** * Collects files from the filesystem based on the given parameters. * * @param {CollectFileParams} collectFileParams - Parameters for file collection, including directories, extensions, and patterns. * @returns {Promise<string[]>} A promise resolving with the list of collected file paths. */ protected collectFiles({ inputDirs, extensions, excludePatterns, recursive, fileNamePattern, }?: CollectFileParams): Promise<string[]>; /** * Uploads a single file to Lokalise. * * @param {UploadFileParams} uploadParams - Parameters for uploading the file. * @returns {Promise<QueuedProcess>} A promise resolving with the upload process details. */ protected uploadSingleFile(uploadParams: UploadFileParams): Promise<QueuedProcess>; /** * Processes a file to prepare it for upload, converting it to base64 and extracting its language code. * * @param {string} file - The absolute path to the file. * @param {string} projectRoot - The root directory of the project. * @param {ProcessUploadFileParams} [processParams] - Optional processing settings including inferers. * @returns {Promise<ProcessedFile>} A promise resolving with the processed file details, including base64 content, relative path, and language code. */ protected processFile(file: string, projectRoot: string, processParams?: ProcessUploadFileParams): Promise<ProcessedFile>; /** * Uploads files in parallel with a limit on the number of concurrent uploads. * * @param {string[]} files - List of file paths to upload. * @param {Partial<UploadFileParams>} baseUploadFileParams - Base parameters for uploads. * @param {ProcessUploadFileParams} [processParams] - Optional processing settings including inferers. * @returns {Promise<{ processes: QueuedProcess[]; errors: FileUploadError[] }>} A promise resolving with successful processes and upload errors. */ private parallelUpload; /** * Normalizes an array of file extensions by ensuring each starts with a dot and is lowercase. * * @param extensions - The list of file extensions to normalize. * @returns A new array with normalized file extensions. */ private normalizeExtensions; /** * Determines whether a file should be collected based on its extension and name pattern. * * @param entry - The directory entry to evaluate. * @param normalizedExtensions - List of allowed file extensions. * @param fileNameRegex - Regular expression to match valid filenames. * @returns `true` if the file matches both extension and name pattern, otherwise `false`. */ private shouldCollectFile; /** * Creates a regular expression from a given pattern string or RegExp. * * @param fileNamePattern - The filename pattern to convert into a RegExp. * @returns A valid RegExp object. * @throws {Error} If the pattern string is invalid and cannot be compiled. */ private makeFilenameRegexp; /** * Converts an array of exclude patterns into an array of RegExp objects. * * @param excludePatterns - An array of strings or regular expressions to exclude. * @returns An array of compiled RegExp objects. * @throws {Error} If any pattern is invalid and cannot be compiled. */ private makeExcludeRegExes; /** * Safely reads the contents of a directory, returning an empty array if access fails. * * Logs a warning if the directory cannot be read (e.g. due to permissions or non-existence). * * @param dir - The directory path to read. * @returns A promise that resolves to an array of directory entries, or an empty array on failure. */ private safeReadDir; /** * Checks if a file path matches any of the provided exclusion patterns. * * @param filePath - The path of the file to check. * @param excludeRegexes - An array of RegExp patterns to test against. * @returns `true` if the file path matches any exclude pattern, otherwise `false`. */ private shouldExclude; /** * Creates a queue of absolute paths from the provided input directories. * * @param inputDirs - An array of input directory paths (relative or absolute). * @returns An array of resolved absolute directory paths. */ private makeQueue; /** * Processes a queue of directories to collect files matching given criteria. * * Recursively reads directories (if enabled), filters files by extension, * filename pattern, and exclusion rules, and collects matching file paths. * * @param queue - The list of directories to process. * @param exts - Allowed file extensions (normalized). * @param nameRx - Regular expression to match valid filenames. * @param excludeRx - Array of exclusion patterns. * @param recursive - Whether to traverse subdirectories. * @returns A promise that resolves to an array of matched file paths. */ private processCollectionQueue; /** * Handles a single directory entry during file collection. * * Applies exclusion rules, optionally queues directories for recursion, * and collects files that match the specified extension and filename pattern. * * @param entry - The directory entry to handle. * @param fullPath - The absolute path to the entry. * @param queue - The processing queue for directories. * @param found - The list to store matched file paths. * @param opts - Options including extensions, name pattern, exclusions, and recursion flag. */ private handleEntry; private toPosixPath; } export { type CollectFileParams, type DownloadTranslationParams, type ExtractParams, type FileUploadError, LokaliseDownload, LokaliseError, type LokaliseExchangeConfig, LokaliseUpload, type PartialUploadFileParams, type ProcessDownloadFileParams, type ProcessUploadFileParams, type ProcessedFile, type QueuedUploadProcessesWithErrors, type RetryParams, type UploadTranslationParams };