outlook-cli 1.2.1 → 1.2.3

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.
@@ -5,6 +5,45 @@ const https = require('https');
5
5
  const config = require('../config');
6
6
  const mockData = require('./mock-data');
7
7
 
8
+ function debugLog(...args) {
9
+ if (config.DEBUG_LOGS) {
10
+ console.error(...args);
11
+ }
12
+ }
13
+
14
+ function buildEncodedPath(path) {
15
+ return String(path || '')
16
+ .split('/')
17
+ .map((segment) => encodeURIComponent(segment))
18
+ .join('/');
19
+ }
20
+
21
+ function buildQueryString(queryParams = {}) {
22
+ if (!queryParams || Object.keys(queryParams).length === 0) {
23
+ return '';
24
+ }
25
+
26
+ const params = { ...queryParams };
27
+ const filter = params.$filter;
28
+ delete params.$filter;
29
+
30
+ let queryString = new URLSearchParams(params).toString();
31
+
32
+ if (filter) {
33
+ if (queryString) {
34
+ queryString += `&$filter=${encodeURIComponent(filter)}`;
35
+ } else {
36
+ queryString = `$filter=${encodeURIComponent(filter)}`;
37
+ }
38
+ }
39
+
40
+ if (!queryString) {
41
+ return '';
42
+ }
43
+
44
+ return `?${queryString}`;
45
+ }
46
+
8
47
  /**
9
48
  * Makes a request to the Microsoft Graph API
10
49
  * @param {string} accessToken - The access token for authentication
@@ -17,53 +56,20 @@ const mockData = require('./mock-data');
17
56
  async function callGraphAPI(accessToken, method, path, data = null, queryParams = {}) {
18
57
  // For test tokens, we'll simulate the API call
19
58
  if (config.USE_TEST_MODE && accessToken.startsWith('test_access_token_')) {
20
- console.error(`TEST MODE: Simulating ${method} ${path} API call`);
59
+ debugLog(`TEST MODE: Simulating ${method} ${path} API call`);
21
60
  return mockData.simulateGraphAPIResponse(method, path, data, queryParams);
22
61
  }
23
62
 
24
63
  try {
25
- console.error(`Making real API call: ${method} ${path}`);
26
-
27
- // Encode path segments properly
28
- const encodedPath = path.split('/')
29
- .map(segment => encodeURIComponent(segment))
30
- .join('/');
31
-
32
- // Build query string from parameters with special handling for OData filters
33
- let queryString = '';
34
- if (Object.keys(queryParams).length > 0) {
35
- // Handle $filter parameter specially to ensure proper URI encoding
36
- const filter = queryParams.$filter;
37
- if (filter) {
38
- delete queryParams.$filter; // Remove from regular params
39
- }
40
-
41
- // Build query string with proper encoding for regular params
42
- const params = new URLSearchParams();
43
- for (const [key, value] of Object.entries(queryParams)) {
44
- params.append(key, value);
45
- }
46
-
47
- queryString = params.toString();
48
-
49
- // Add filter parameter separately with proper encoding
50
- if (filter) {
51
- if (queryString) {
52
- queryString += `&$filter=${encodeURIComponent(filter)}`;
53
- } else {
54
- queryString = `$filter=${encodeURIComponent(filter)}`;
55
- }
56
- }
57
-
58
- if (queryString) {
59
- queryString = '?' + queryString;
60
- }
61
-
62
- console.error(`Query string: ${queryString}`);
63
- }
64
-
64
+ debugLog(`Making real API call: ${method} ${path}`);
65
+
66
+ const encodedPath = buildEncodedPath(path);
67
+ const queryString = buildQueryString(queryParams);
68
+
69
+ debugLog(`Query string: ${queryString}`);
70
+
65
71
  const url = `${config.GRAPH_API_ENDPOINT}${encodedPath}${queryString}`;
66
- console.error(`Full URL: ${url}`);
72
+ debugLog(`Full URL: ${url}`);
67
73
 
68
74
  return new Promise((resolve, reject) => {
69
75
  const options = {
@@ -110,11 +116,93 @@ async function callGraphAPI(accessToken, method, path, data = null, queryParams
110
116
  req.end();
111
117
  });
112
118
  } catch (error) {
113
- console.error('Error calling Graph API:', error);
119
+ debugLog('Error calling Graph API:', error);
120
+ throw error;
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Makes a raw request to the Microsoft Graph API and returns bytes.
126
+ * @param {string} accessToken - The access token for authentication
127
+ * @param {string} method - HTTP method (GET, POST, etc.)
128
+ * @param {string} path - API endpoint path
129
+ * @param {object} data - Data to send for POST/PUT requests
130
+ * @param {object} queryParams - Query parameters
131
+ * @returns {Promise<{statusCode:number, headers:object, body:Buffer}>}
132
+ */
133
+ async function callGraphAPIRaw(accessToken, method, path, data = null, queryParams = {}) {
134
+ if (config.USE_TEST_MODE && accessToken.startsWith('test_access_token_')) {
135
+ debugLog(`TEST MODE: Simulating raw ${method} ${path} API call`);
136
+ return {
137
+ statusCode: 200,
138
+ headers: {
139
+ 'content-type': 'application/octet-stream'
140
+ },
141
+ body: Buffer.from('')
142
+ };
143
+ }
144
+
145
+ try {
146
+ debugLog(`Making raw API call: ${method} ${path}`);
147
+
148
+ const encodedPath = buildEncodedPath(path);
149
+ const queryString = buildQueryString(queryParams);
150
+ const url = `${config.GRAPH_API_ENDPOINT}${encodedPath}${queryString}`;
151
+ debugLog(`Full raw URL: ${url}`);
152
+
153
+ return new Promise((resolve, reject) => {
154
+ const options = {
155
+ method,
156
+ headers: {
157
+ Authorization: `Bearer ${accessToken}`
158
+ }
159
+ };
160
+
161
+ const req = https.request(url, options, (res) => {
162
+ const chunks = [];
163
+
164
+ res.on('data', (chunk) => {
165
+ chunks.push(chunk);
166
+ });
167
+
168
+ res.on('end', () => {
169
+ const body = Buffer.concat(chunks);
170
+
171
+ if (res.statusCode >= 200 && res.statusCode < 300) {
172
+ resolve({
173
+ statusCode: res.statusCode,
174
+ headers: res.headers,
175
+ body
176
+ });
177
+ return;
178
+ }
179
+
180
+ if (res.statusCode === 401) {
181
+ reject(new Error('UNAUTHORIZED'));
182
+ return;
183
+ }
184
+
185
+ reject(new Error(`API call failed with status ${res.statusCode}: ${body.toString('utf8')}`));
186
+ });
187
+ });
188
+
189
+ req.on('error', (error) => {
190
+ reject(new Error(`Network error during API call: ${error.message}`));
191
+ });
192
+
193
+ if (data && (method === 'POST' || method === 'PATCH' || method === 'PUT')) {
194
+ req.write(JSON.stringify(data));
195
+ }
196
+
197
+ req.end();
198
+ });
199
+ } catch (error) {
200
+ debugLog('Error calling Graph API (raw):', error);
114
201
  throw error;
115
202
  }
116
203
  }
117
204
 
118
205
  module.exports = {
119
- callGraphAPI
206
+ callGraphAPI,
207
+ callGraphAPIRaw
120
208
  };