nylas 7.11.0 → 7.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -156,10 +156,6 @@ class APIClient {
156
156
  }
157
157
  if (optionParams.form) {
158
158
  requestOptions.body = optionParams.form;
159
- requestOptions.headers = {
160
- ...requestOptions.headers,
161
- ...optionParams.form.getHeaders(),
162
- };
163
159
  }
164
160
  return requestOptions;
165
161
  }
@@ -178,11 +174,19 @@ class APIClient {
178
174
  const flowId = headers[exports.FLOW_ID_HEADER];
179
175
  const text = await response.text();
180
176
  try {
181
- const responseJSON = JSON.parse(text);
182
- // Inject the flow ID and headers into the response
183
- responseJSON.flowId = flowId;
184
- responseJSON.headers = headers;
185
- return (0, utils_js_1.objKeysToCamelCase)(responseJSON, ['metadata']);
177
+ const parsed = JSON.parse(text);
178
+ const payload = (0, utils_js_1.objKeysToCamelCase)({
179
+ ...parsed,
180
+ flowId,
181
+ // deprecated: headers will be removed in a future release. This is for backwards compatibility.
182
+ headers,
183
+ }, ['metadata']);
184
+ // Attach rawHeaders as a non-enumerable property to avoid breaking deep equality
185
+ Object.defineProperty(payload, 'rawHeaders', {
186
+ value: headers,
187
+ enumerable: false,
188
+ });
189
+ return payload;
186
190
  }
187
191
  catch (e) {
188
192
  throw new Error(`Could not parse response from the server: ${text}`);
@@ -198,6 +202,10 @@ class APIClient {
198
202
  }
199
203
  async requestStream(options) {
200
204
  const response = await this.sendRequest(options);
205
+ // TODO: See if we can fix this in a backwards compatible way
206
+ if (!response.body) {
207
+ throw new Error('No response body');
208
+ }
201
209
  return response.body;
202
210
  }
203
211
  }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Auth = void 0;
4
4
  const uuid_1 = require("uuid");
5
- const crypto_1 = require("crypto");
5
+ const node_crypto_1 = require("node:crypto");
6
6
  const resource_js_1 = require("./resource.js");
7
7
  const utils_js_1 = require("../utils.js");
8
8
  /**
@@ -166,7 +166,7 @@ class Auth extends resource_js_1.Resource {
166
166
  return url;
167
167
  }
168
168
  hashPKCESecret(secret) {
169
- const hash = (0, crypto_1.createHash)('sha256').update(secret).digest('hex');
169
+ const hash = (0, node_crypto_1.createHash)('sha256').update(secret).digest('hex');
170
170
  return Buffer.from(hash).toString('base64').replace(/=+$/, '');
171
171
  }
172
172
  getTokenInfo(params) {
@@ -55,7 +55,7 @@ class Drafts extends resource_js_1.Resource {
55
55
  });
56
56
  }
57
57
  else if (requestBody.attachments) {
58
- const processedAttachments = await (0, utils_js_1.encodeAttachmentStreams)(requestBody.attachments);
58
+ const processedAttachments = await (0, utils_js_1.encodeAttachmentContent)(requestBody.attachments);
59
59
  requestBody = {
60
60
  ...requestBody,
61
61
  attachments: processedAttachments,
@@ -88,7 +88,7 @@ class Drafts extends resource_js_1.Resource {
88
88
  });
89
89
  }
90
90
  else if (requestBody.attachments) {
91
- const processedAttachments = await (0, utils_js_1.encodeAttachmentStreams)(requestBody.attachments);
91
+ const processedAttachments = await (0, utils_js_1.encodeAttachmentContent)(requestBody.attachments);
92
92
  requestBody = {
93
93
  ...requestBody,
94
94
  attachments: processedAttachments,
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Messages = void 0;
4
+ const formdata_node_1 = require("formdata-node");
4
5
  const utils_js_1 = require("../utils.js");
5
6
  const resource_js_1 = require("./resource.js");
6
7
  const smartCompose_js_1 = require("./smartCompose.js");
@@ -96,7 +97,7 @@ class Messages extends resource_js_1.Resource {
96
97
  }
97
98
  else {
98
99
  if (requestBody.attachments) {
99
- const processedAttachments = await (0, utils_js_1.encodeAttachmentStreams)(requestBody.attachments);
100
+ const processedAttachments = await (0, utils_js_1.encodeAttachmentContent)(requestBody.attachments);
100
101
  requestOptions.body = {
101
102
  ...requestBody,
102
103
  attachments: processedAttachments,
@@ -155,10 +156,7 @@ class Messages extends resource_js_1.Resource {
155
156
  });
156
157
  }
157
158
  static _buildFormRequest(requestBody) {
158
- // FormData imports are funky, cjs needs to use .default, es6 doesn't
159
- const FD = require('form-data');
160
- const FormDataConstructor = FD.default || FD;
161
- const form = new FormDataConstructor();
159
+ const form = new formdata_node_1.FormData();
162
160
  // Split out the message payload from the attachments
163
161
  const messagePayload = {
164
162
  ...requestBody,
@@ -166,13 +164,30 @@ class Messages extends resource_js_1.Resource {
166
164
  };
167
165
  form.append('message', JSON.stringify((0, utils_js_1.objKeysToSnakeCase)(messagePayload)));
168
166
  // Add a separate form field for each attachment
169
- requestBody.attachments?.forEach((attachment, index) => {
170
- const contentId = attachment.contentId || `file${index}`;
171
- form.append(contentId, attachment.content, {
172
- filename: attachment.filename,
173
- contentType: attachment.contentType,
167
+ if (requestBody.attachments && requestBody.attachments.length > 0) {
168
+ requestBody.attachments.map((attachment, index) => {
169
+ const contentId = attachment.contentId || `file${index}`;
170
+ // Handle different content types for formdata-node
171
+ if (typeof attachment.content === 'string') {
172
+ // Base64 string - create a Blob
173
+ const buffer = Buffer.from(attachment.content, 'base64');
174
+ const blob = new formdata_node_1.Blob([buffer], { type: attachment.contentType });
175
+ form.append(contentId, blob, attachment.filename);
176
+ }
177
+ else if (Buffer.isBuffer(attachment.content)) {
178
+ // Buffer - create a Blob
179
+ const blob = new formdata_node_1.Blob([attachment.content], {
180
+ type: attachment.contentType,
181
+ });
182
+ form.append(contentId, blob, attachment.filename);
183
+ }
184
+ else {
185
+ // ReadableStream - create a proper file-like object according to formdata-node docs
186
+ const file = (0, utils_js_1.attachmentStreamToFile)(attachment);
187
+ form.append(contentId, file, attachment.filename);
188
+ }
174
189
  });
175
- });
190
+ }
176
191
  return form;
177
192
  }
178
193
  }
package/lib/cjs/utils.js CHANGED
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createFileRequestBuilder = createFileRequestBuilder;
4
+ exports.attachmentStreamToFile = attachmentStreamToFile;
5
+ exports.encodeAttachmentContent = encodeAttachmentContent;
4
6
  exports.encodeAttachmentStreams = encodeAttachmentStreams;
5
7
  exports.objKeysToCamelCase = objKeysToCamelCase;
6
8
  exports.objKeysToSnakeCase = objKeysToSnakeCase;
@@ -8,10 +10,10 @@ exports.safePath = safePath;
8
10
  exports.makePathParams = makePathParams;
9
11
  exports.calculateTotalPayloadSize = calculateTotalPayloadSize;
10
12
  const change_case_1 = require("change-case");
11
- const fs = require("fs");
12
- const path = require("path");
13
+ const fs = require("node:fs");
14
+ const path = require("node:path");
13
15
  const mime = require("mime-types");
14
- const stream_1 = require("stream");
16
+ const node_stream_1 = require("node:stream");
15
17
  function createFileRequestBuilder(filePath) {
16
18
  const stats = fs.statSync(filePath);
17
19
  const filename = path.basename(filePath);
@@ -45,18 +47,67 @@ function streamToBase64(stream) {
45
47
  });
46
48
  }
47
49
  /**
48
- * Encodes the content of each attachment stream to base64.
50
+ * Converts a ReadableStream to a File-like object that can be used with FormData.
51
+ * @param attachment The attachment containing the stream and metadata.
52
+ * @param mimeType The MIME type for the file (optional).
53
+ * @returns A File-like object that properly handles the stream.
54
+ */
55
+ function attachmentStreamToFile(attachment, mimeType) {
56
+ if (mimeType != null && typeof mimeType !== 'string') {
57
+ throw new Error('Invalid mimetype, expected string.');
58
+ }
59
+ const content = attachment.content;
60
+ if (typeof content === 'string' || Buffer.isBuffer(content)) {
61
+ throw new Error('Invalid attachment content, expected ReadableStream.');
62
+ }
63
+ // Create a file-shaped object that FormData can handle properly
64
+ const fileObject = {
65
+ type: mimeType || attachment.contentType,
66
+ name: attachment.filename,
67
+ [Symbol.toStringTag]: 'File',
68
+ stream() {
69
+ return content;
70
+ },
71
+ };
72
+ // Add size if available
73
+ if (attachment.size !== undefined) {
74
+ fileObject.size = attachment.size;
75
+ }
76
+ return fileObject;
77
+ }
78
+ /**
79
+ * Encodes the content of each attachment to base64.
80
+ * Handles ReadableStream, Buffer, and string content types.
49
81
  * @param attachments The attachments to encode.
50
82
  * @returns The attachments with their content encoded to base64.
51
83
  */
52
- async function encodeAttachmentStreams(attachments) {
84
+ async function encodeAttachmentContent(attachments) {
53
85
  return await Promise.all(attachments.map(async (attachment) => {
54
- const base64EncodedContent = attachment.content instanceof stream_1.Readable
55
- ? await streamToBase64(attachment.content)
56
- : attachment.content;
57
- return { ...attachment, content: base64EncodedContent }; // Replace the stream with its base64 string
86
+ let base64EncodedContent;
87
+ if (attachment.content instanceof node_stream_1.Readable) {
88
+ // ReadableStream -> base64
89
+ base64EncodedContent = await streamToBase64(attachment.content);
90
+ }
91
+ else if (Buffer.isBuffer(attachment.content)) {
92
+ // Buffer -> base64
93
+ base64EncodedContent = attachment.content.toString('base64');
94
+ }
95
+ else {
96
+ // string (assumed to already be base64)
97
+ base64EncodedContent = attachment.content;
98
+ }
99
+ return { ...attachment, content: base64EncodedContent };
58
100
  }));
59
101
  }
102
+ /**
103
+ * @deprecated Use encodeAttachmentContent instead. This alias is provided for backwards compatibility.
104
+ * Encodes the content of each attachment stream to base64.
105
+ * @param attachments The attachments to encode.
106
+ * @returns The attachments with their content encoded to base64.
107
+ */
108
+ async function encodeAttachmentStreams(attachments) {
109
+ return encodeAttachmentContent(attachments);
110
+ }
60
111
  /**
61
112
  * Applies the casing function and ensures numeric parts are preceded by underscores in snake_case.
62
113
  * @param casingFunction The original casing function.
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SDK_VERSION = void 0;
4
4
  // This file is generated by scripts/exportVersion.js
5
- exports.SDK_VERSION = '7.11.0';
5
+ exports.SDK_VERSION = '7.13.0';
@@ -153,10 +153,6 @@ export default class APIClient {
153
153
  }
154
154
  if (optionParams.form) {
155
155
  requestOptions.body = optionParams.form;
156
- requestOptions.headers = {
157
- ...requestOptions.headers,
158
- ...optionParams.form.getHeaders(),
159
- };
160
156
  }
161
157
  return requestOptions;
162
158
  }
@@ -175,11 +171,19 @@ export default class APIClient {
175
171
  const flowId = headers[FLOW_ID_HEADER];
176
172
  const text = await response.text();
177
173
  try {
178
- const responseJSON = JSON.parse(text);
179
- // Inject the flow ID and headers into the response
180
- responseJSON.flowId = flowId;
181
- responseJSON.headers = headers;
182
- return objKeysToCamelCase(responseJSON, ['metadata']);
174
+ const parsed = JSON.parse(text);
175
+ const payload = objKeysToCamelCase({
176
+ ...parsed,
177
+ flowId,
178
+ // deprecated: headers will be removed in a future release. This is for backwards compatibility.
179
+ headers,
180
+ }, ['metadata']);
181
+ // Attach rawHeaders as a non-enumerable property to avoid breaking deep equality
182
+ Object.defineProperty(payload, 'rawHeaders', {
183
+ value: headers,
184
+ enumerable: false,
185
+ });
186
+ return payload;
183
187
  }
184
188
  catch (e) {
185
189
  throw new Error(`Could not parse response from the server: ${text}`);
@@ -195,6 +199,10 @@ export default class APIClient {
195
199
  }
196
200
  async requestStream(options) {
197
201
  const response = await this.sendRequest(options);
202
+ // TODO: See if we can fix this in a backwards compatible way
203
+ if (!response.body) {
204
+ throw new Error('No response body');
205
+ }
198
206
  return response.body;
199
207
  }
200
208
  }
@@ -1,5 +1,5 @@
1
1
  import { v4 as uuid } from 'uuid';
2
- import { createHash } from 'crypto';
2
+ import { createHash } from 'node:crypto';
3
3
  import { Resource } from './resource.js';
4
4
  import { makePathParams } from '../utils.js';
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  import { Messages } from './messages.js';
2
2
  import { Resource } from './resource.js';
3
- import { encodeAttachmentStreams, calculateTotalPayloadSize, } from '../utils.js';
3
+ import { encodeAttachmentContent, calculateTotalPayloadSize, } from '../utils.js';
4
4
  import { makePathParams } from '../utils.js';
5
5
  /**
6
6
  * Nylas Drafts API
@@ -52,7 +52,7 @@ export class Drafts extends Resource {
52
52
  });
53
53
  }
54
54
  else if (requestBody.attachments) {
55
- const processedAttachments = await encodeAttachmentStreams(requestBody.attachments);
55
+ const processedAttachments = await encodeAttachmentContent(requestBody.attachments);
56
56
  requestBody = {
57
57
  ...requestBody,
58
58
  attachments: processedAttachments,
@@ -85,7 +85,7 @@ export class Drafts extends Resource {
85
85
  });
86
86
  }
87
87
  else if (requestBody.attachments) {
88
- const processedAttachments = await encodeAttachmentStreams(requestBody.attachments);
88
+ const processedAttachments = await encodeAttachmentContent(requestBody.attachments);
89
89
  requestBody = {
90
90
  ...requestBody,
91
91
  attachments: processedAttachments,
@@ -1,4 +1,5 @@
1
- import { encodeAttachmentStreams, objKeysToSnakeCase, makePathParams, calculateTotalPayloadSize, } from '../utils.js';
1
+ import { Blob, FormData } from 'formdata-node';
2
+ import { attachmentStreamToFile, calculateTotalPayloadSize, encodeAttachmentContent, makePathParams, objKeysToSnakeCase, } from '../utils.js';
2
3
  import { Resource } from './resource.js';
3
4
  import { SmartCompose } from './smartCompose.js';
4
5
  /**
@@ -93,7 +94,7 @@ export class Messages extends Resource {
93
94
  }
94
95
  else {
95
96
  if (requestBody.attachments) {
96
- const processedAttachments = await encodeAttachmentStreams(requestBody.attachments);
97
+ const processedAttachments = await encodeAttachmentContent(requestBody.attachments);
97
98
  requestOptions.body = {
98
99
  ...requestBody,
99
100
  attachments: processedAttachments,
@@ -152,10 +153,7 @@ export class Messages extends Resource {
152
153
  });
153
154
  }
154
155
  static _buildFormRequest(requestBody) {
155
- // FormData imports are funky, cjs needs to use .default, es6 doesn't
156
- const FD = require('form-data');
157
- const FormDataConstructor = FD.default || FD;
158
- const form = new FormDataConstructor();
156
+ const form = new FormData();
159
157
  // Split out the message payload from the attachments
160
158
  const messagePayload = {
161
159
  ...requestBody,
@@ -163,13 +161,30 @@ export class Messages extends Resource {
163
161
  };
164
162
  form.append('message', JSON.stringify(objKeysToSnakeCase(messagePayload)));
165
163
  // Add a separate form field for each attachment
166
- requestBody.attachments?.forEach((attachment, index) => {
167
- const contentId = attachment.contentId || `file${index}`;
168
- form.append(contentId, attachment.content, {
169
- filename: attachment.filename,
170
- contentType: attachment.contentType,
164
+ if (requestBody.attachments && requestBody.attachments.length > 0) {
165
+ requestBody.attachments.map((attachment, index) => {
166
+ const contentId = attachment.contentId || `file${index}`;
167
+ // Handle different content types for formdata-node
168
+ if (typeof attachment.content === 'string') {
169
+ // Base64 string - create a Blob
170
+ const buffer = Buffer.from(attachment.content, 'base64');
171
+ const blob = new Blob([buffer], { type: attachment.contentType });
172
+ form.append(contentId, blob, attachment.filename);
173
+ }
174
+ else if (Buffer.isBuffer(attachment.content)) {
175
+ // Buffer - create a Blob
176
+ const blob = new Blob([attachment.content], {
177
+ type: attachment.contentType,
178
+ });
179
+ form.append(contentId, blob, attachment.filename);
180
+ }
181
+ else {
182
+ // ReadableStream - create a proper file-like object according to formdata-node docs
183
+ const file = attachmentStreamToFile(attachment);
184
+ form.append(contentId, file, attachment.filename);
185
+ }
171
186
  });
172
- });
187
+ }
173
188
  return form;
174
189
  }
175
190
  }
package/lib/esm/utils.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { camelCase, snakeCase } from 'change-case';
2
- import * as fs from 'fs';
3
- import * as path from 'path';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
4
  import * as mime from 'mime-types';
5
- import { Readable } from 'stream';
5
+ import { Readable } from 'node:stream';
6
6
  export function createFileRequestBuilder(filePath) {
7
7
  const stats = fs.statSync(filePath);
8
8
  const filename = path.basename(filePath);
@@ -36,18 +36,67 @@ function streamToBase64(stream) {
36
36
  });
37
37
  }
38
38
  /**
39
- * Encodes the content of each attachment stream to base64.
39
+ * Converts a ReadableStream to a File-like object that can be used with FormData.
40
+ * @param attachment The attachment containing the stream and metadata.
41
+ * @param mimeType The MIME type for the file (optional).
42
+ * @returns A File-like object that properly handles the stream.
43
+ */
44
+ export function attachmentStreamToFile(attachment, mimeType) {
45
+ if (mimeType != null && typeof mimeType !== 'string') {
46
+ throw new Error('Invalid mimetype, expected string.');
47
+ }
48
+ const content = attachment.content;
49
+ if (typeof content === 'string' || Buffer.isBuffer(content)) {
50
+ throw new Error('Invalid attachment content, expected ReadableStream.');
51
+ }
52
+ // Create a file-shaped object that FormData can handle properly
53
+ const fileObject = {
54
+ type: mimeType || attachment.contentType,
55
+ name: attachment.filename,
56
+ [Symbol.toStringTag]: 'File',
57
+ stream() {
58
+ return content;
59
+ },
60
+ };
61
+ // Add size if available
62
+ if (attachment.size !== undefined) {
63
+ fileObject.size = attachment.size;
64
+ }
65
+ return fileObject;
66
+ }
67
+ /**
68
+ * Encodes the content of each attachment to base64.
69
+ * Handles ReadableStream, Buffer, and string content types.
40
70
  * @param attachments The attachments to encode.
41
71
  * @returns The attachments with their content encoded to base64.
42
72
  */
43
- export async function encodeAttachmentStreams(attachments) {
73
+ export async function encodeAttachmentContent(attachments) {
44
74
  return await Promise.all(attachments.map(async (attachment) => {
45
- const base64EncodedContent = attachment.content instanceof Readable
46
- ? await streamToBase64(attachment.content)
47
- : attachment.content;
48
- return { ...attachment, content: base64EncodedContent }; // Replace the stream with its base64 string
75
+ let base64EncodedContent;
76
+ if (attachment.content instanceof Readable) {
77
+ // ReadableStream -> base64
78
+ base64EncodedContent = await streamToBase64(attachment.content);
79
+ }
80
+ else if (Buffer.isBuffer(attachment.content)) {
81
+ // Buffer -> base64
82
+ base64EncodedContent = attachment.content.toString('base64');
83
+ }
84
+ else {
85
+ // string (assumed to already be base64)
86
+ base64EncodedContent = attachment.content;
87
+ }
88
+ return { ...attachment, content: base64EncodedContent };
49
89
  }));
50
90
  }
91
+ /**
92
+ * @deprecated Use encodeAttachmentContent instead. This alias is provided for backwards compatibility.
93
+ * Encodes the content of each attachment stream to base64.
94
+ * @param attachments The attachments to encode.
95
+ * @returns The attachments with their content encoded to base64.
96
+ */
97
+ export async function encodeAttachmentStreams(attachments) {
98
+ return encodeAttachmentContent(attachments);
99
+ }
51
100
  /**
52
101
  * Applies the casing function and ensures numeric parts are preceded by underscores in snake_case.
53
102
  * @param casingFunction The original casing function.
@@ -1,2 +1,2 @@
1
1
  // This file is generated by scripts/exportVersion.js
2
- export const SDK_VERSION = '7.11.0';
2
+ export const SDK_VERSION = '7.13.0';
@@ -1,6 +1,6 @@
1
1
  import { Request, Response } from 'node-fetch';
2
2
  import { NylasConfig, OverridableNylasConfig } from './config.js';
3
- import FormData from 'form-data';
3
+ import { FormData } from 'formdata-node';
4
4
  /**
5
5
  * The header key for the debugging flow ID
6
6
  */
@@ -69,6 +69,11 @@ export interface CreateDraftRequest {
69
69
  * An array of custom headers to add to the message.
70
70
  */
71
71
  customHeaders?: CustomHeader[];
72
+ /**
73
+ * When true, the message body is sent as plain text and the MIME data doesn't include the HTML version of the message.
74
+ * When false, the message body is sent as HTML. Defaults to false.
75
+ */
76
+ isPlaintext?: boolean;
72
77
  }
73
78
  /**
74
79
  * Interface representing a request to send a message.
@@ -96,7 +101,7 @@ export interface Draft extends BaseMessage, Omit<CreateDraftRequest, 'attachment
96
101
  /**
97
102
  * Interface representing a request to update a draft.
98
103
  */
99
- export type UpdateDraftRequest = Partial<CreateDraftRequest> & {
104
+ export type UpdateDraftRequest = Omit<Partial<CreateDraftRequest>, 'isPlaintext'> & {
100
105
  /**
101
106
  * Return drafts that are unread.
102
107
  */
@@ -3,6 +3,20 @@
3
3
  */
4
4
  export interface NylasBaseResponse {
5
5
  requestId: string;
6
+ /**
7
+ * The flow ID
8
+ * Provide this to Nylas support to help trace requests and responses
9
+ */
10
+ flowId?: string;
11
+ /**
12
+ * The response headers with camelCased keys (backwards compatible)
13
+ * @deprecated Use rawHeaders instead
14
+ */
15
+ headers?: Record<string, string>;
16
+ /**
17
+ * The raw response headers with original dashed lowercase keys
18
+ */
19
+ rawHeaders?: Record<string, string>;
6
20
  }
7
21
  /**
8
22
  * Interface representation of a Nylas response object
@@ -23,8 +37,13 @@ export interface NylasResponse<T> {
23
37
  flowId?: string;
24
38
  /**
25
39
  * The response headers
40
+ * @deprecated Use rawHeaders instead
26
41
  */
27
42
  headers?: Record<string, string>;
43
+ /**
44
+ * The raw response headers with original dashed lowercase keys
45
+ */
46
+ rawHeaders?: Record<string, string>;
28
47
  }
29
48
  /**
30
49
  * Interface representation of a Nylas response object that contains a list of objects.
@@ -42,6 +61,20 @@ export interface NylasListResponse<T> {
42
61
  * The cursor to use to get the next page of data.
43
62
  */
44
63
  nextCursor?: string;
64
+ /**
65
+ * The flow ID
66
+ * Provide this to Nylas support to help trace requests and responses
67
+ */
68
+ flowId?: string;
69
+ /**
70
+ * The response headers with camelCased keys (backwards compatible)
71
+ * @deprecated Use rawHeaders instead
72
+ */
73
+ headers?: Record<string, string>;
74
+ /**
75
+ * The raw response headers with original dashed lowercase keys
76
+ */
77
+ rawHeaders?: Record<string, string>;
45
78
  }
46
79
  /**
47
80
  * Helper type for pagination
@@ -1,4 +1,4 @@
1
- import FormData from 'form-data';
1
+ import { FormData } from 'formdata-node';
2
2
  import APIClient from '../apiClient.js';
3
3
  import { Overrides } from '../config.js';
4
4
  import { CreateDraftRequest, SendMessageRequest, UpdateDraftRequest } from '../models/drafts.js';
@@ -1,6 +1,21 @@
1
1
  import { CreateAttachmentRequest } from './models/attachments.js';
2
2
  export declare function createFileRequestBuilder(filePath: string): CreateAttachmentRequest;
3
3
  /**
4
+ * Converts a ReadableStream to a File-like object that can be used with FormData.
5
+ * @param attachment The attachment containing the stream and metadata.
6
+ * @param mimeType The MIME type for the file (optional).
7
+ * @returns A File-like object that properly handles the stream.
8
+ */
9
+ export declare function attachmentStreamToFile(attachment: CreateAttachmentRequest, mimeType?: string): any;
10
+ /**
11
+ * Encodes the content of each attachment to base64.
12
+ * Handles ReadableStream, Buffer, and string content types.
13
+ * @param attachments The attachments to encode.
14
+ * @returns The attachments with their content encoded to base64.
15
+ */
16
+ export declare function encodeAttachmentContent(attachments: CreateAttachmentRequest[]): Promise<CreateAttachmentRequest[]>;
17
+ /**
18
+ * @deprecated Use encodeAttachmentContent instead. This alias is provided for backwards compatibility.
4
19
  * Encodes the content of each attachment stream to base64.
5
20
  * @param attachments The attachments to encode.
6
21
  * @returns The attachments with their content encoded to base64.
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "7.11.0";
1
+ export declare const SDK_VERSION = "7.13.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nylas",
3
- "version": "7.11.0",
3
+ "version": "7.13.0",
4
4
  "description": "A NodeJS wrapper for the Nylas REST API for email, contacts, and calendar.",
5
5
  "main": "lib/cjs/nylas.js",
6
6
  "types": "lib/types/nylas.d.ts",
@@ -40,9 +40,10 @@
40
40
  "license": "MIT",
41
41
  "dependencies": {
42
42
  "change-case": "^4.1.2",
43
- "form-data": "^4.0.0",
43
+ "form-data-encoder": "^4.1.0",
44
+ "formdata-node": "^6.0.3",
44
45
  "mime-types": "^2.1.35",
45
- "node-fetch": "^2.6.12",
46
+ "node-fetch": "^3.3.2",
46
47
  "uuid": "^8.3.2"
47
48
  },
48
49
  "devDependencies": {
@@ -50,7 +51,6 @@
50
51
  "@types/jest": "^29.5.2",
51
52
  "@types/mime-types": "^2.1.2",
52
53
  "@types/node": "^22.15.21",
53
- "@types/node-fetch": "^2.6.4",
54
54
  "@types/uuid": "^8.3.4",
55
55
  "@typescript-eslint/eslint-plugin": "^2.25.0",
56
56
  "@typescript-eslint/parser": "^2.25.0",
@@ -60,6 +60,7 @@
60
60
  "eslint-plugin-import": "^2.28.1",
61
61
  "eslint-plugin-prettier": "^3.0.1",
62
62
  "jest": "^29.6.1",
63
+ "jest-fetch-mock": "^3.0.3",
63
64
  "prettier": "^3.5.3",
64
65
  "ts-jest": "^29.1.1",
65
66
  "typedoc": "^0.28.4",