nylas
Version:
A NodeJS wrapper for the Nylas REST API for email, contacts, and calendar.
118 lines (117 loc) • 4.11 kB
JavaScript
import { camelCase, snakeCase } from 'change-case';
import * as fs from 'fs';
import * as path from 'path';
import * as mime from 'mime-types';
import { Readable } from 'stream';
export function createFileRequestBuilder(filePath) {
const stats = fs.statSync(filePath);
const filename = path.basename(filePath);
const contentType = mime.lookup(filePath) || 'application/octet-stream';
const content = fs.createReadStream(filePath);
return {
filename,
contentType,
content,
size: stats.size,
};
}
/**
* Converts a ReadableStream to a base64 encoded string.
* @param stream The ReadableStream containing the binary data.
* @returns The stream base64 encoded to a string.
*/
function streamToBase64(stream) {
return new Promise((resolve, reject) => {
const chunks = [];
stream.on('data', (chunk) => {
chunks.push(chunk);
});
stream.on('end', () => {
const base64 = Buffer.concat(chunks).toString('base64');
resolve(base64);
});
stream.on('error', err => {
reject(err);
});
});
}
/**
* Encodes the content of each attachment stream to base64.
* @param attachments The attachments to encode.
* @returns The attachments with their content encoded to base64.
*/
export async function encodeAttachmentStreams(attachments) {
return await Promise.all(attachments.map(async (attachment) => {
const base64EncodedContent = attachment.content instanceof Readable
? await streamToBase64(attachment.content)
: attachment.content;
return { ...attachment, content: base64EncodedContent }; // Replace the stream with its base64 string
}));
}
/**
* Applies the casing function and ensures numeric parts are preceded by underscores in snake_case.
* @param casingFunction The original casing function.
* @param input The string to convert.
* @returns The converted string.
*/
function applyCasing(casingFunction, input) {
const transformed = casingFunction(input);
if (casingFunction === snakeCase) {
return transformed.replace(/(\d+)/g, '_$1');
}
else {
return transformed.replace(/_+(\d+)/g, (match, p1) => p1);
}
}
/**
* A utility function that recursively converts all keys in an object to a given case.
* @param obj The object to convert
* @param casingFunction The function to use to convert the keys
* @param excludeKeys An array of keys to exclude from conversion
* @returns The converted object
* @ignore Not for public use.
*/
function convertCase(obj, casingFunction, excludeKeys) {
const newObj = {};
for (const key in obj) {
if (excludeKeys?.includes(key)) {
newObj[key] = obj[key];
}
else if (Array.isArray(obj[key])) {
newObj[applyCasing(casingFunction, key)] = obj[key].map(item => {
if (typeof item === 'object') {
return convertCase(item, casingFunction);
}
else {
return item;
}
});
}
else if (typeof obj[key] === 'object' && obj[key] !== null) {
newObj[applyCasing(casingFunction, key)] = convertCase(obj[key], casingFunction);
}
else {
newObj[applyCasing(casingFunction, key)] = obj[key];
}
}
return newObj;
}
/**
* A utility function that recursively converts all keys in an object to camelCase.
* @param obj The object to convert
* @param exclude An array of keys to exclude from conversion
* @returns The converted object
* @ignore Not for public use.
*/
export function objKeysToCamelCase(obj, exclude) {
return convertCase(obj, camelCase, exclude);
}
/**
* A utility function that recursively converts all keys in an object to snake_case.
* @param obj The object to convert
* @param exclude An array of keys to exclude from conversion
* @returns The converted object
*/
export function objKeysToSnakeCase(obj, exclude) {
return convertCase(obj, snakeCase, exclude);
}