@adobe/helix-onedrive-support 12.2.3 → 12.3.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.
- package/CHANGELOG.md +7 -0
- package/package.json +5 -4
- package/src/CustomNetworkModule.js +169 -0
- package/src/OneDriveAuth.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [12.3.0](https://github.com/adobe/helix-onedrive-support/compare/v12.2.3...v12.3.0) (2026-03-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **msal:** use custom network module and @adobe/fetch ([#729](https://github.com/adobe/helix-onedrive-support/issues/729)) ([6dc88a7](https://github.com/adobe/helix-onedrive-support/commit/6dc88a70a0447214b82aa3e6d59d7da7e97cb052))
|
|
7
|
+
|
|
1
8
|
## [12.2.3](https://github.com/adobe/helix-onedrive-support/compare/v12.2.2...v12.2.3) (2026-03-04)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-onedrive-support",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.3.0",
|
|
4
4
|
"description": "Helix OneDrive Support",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -27,15 +27,16 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://github.com/adobe/helix-onedrive-support#readme",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@adobe/fetch": "^4.
|
|
30
|
+
"@adobe/fetch": "^4.2.3",
|
|
31
31
|
"@adobe/helix-shared-string": "^2.1.0",
|
|
32
32
|
"@adobe/helix-shared-tokencache": "^1.4.19",
|
|
33
|
+
"@azure/msal-common": "16.0.4",
|
|
33
34
|
"@azure/msal-node": "5.0.4",
|
|
34
35
|
"jose": "6.1.3"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"@adobe/eslint-config-helix": "3.0.21",
|
|
38
|
-
"@aws-sdk/client-s3": "3.
|
|
39
|
+
"@aws-sdk/client-s3": "3.996.0",
|
|
39
40
|
"@eslint/config-helpers": "0.5.2",
|
|
40
41
|
"@semantic-release/changelog": "6.0.3",
|
|
41
42
|
"@semantic-release/git": "10.0.1",
|
|
@@ -54,7 +55,7 @@
|
|
|
54
55
|
"mocha-multi-reporters": "1.5.1",
|
|
55
56
|
"mocha-suppress-logs": "0.6.0",
|
|
56
57
|
"nock": "14.0.11",
|
|
57
|
-
"npm": "11.10.
|
|
58
|
+
"npm": "11.10.1",
|
|
58
59
|
"semantic-release": "25.0.3"
|
|
59
60
|
},
|
|
60
61
|
"lint-staged": {
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
import { Headers } from '@adobe/fetch';
|
|
13
|
+
import { createAuthError, ClientAuthErrorCodes, createNetworkError } from '@azure/msal-common/node';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* HTTP methods
|
|
17
|
+
*/
|
|
18
|
+
const HttpMethod = {
|
|
19
|
+
GET: 'GET',
|
|
20
|
+
POST: 'POST',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Converts a fetch Headers object to a plain JavaScript object.
|
|
25
|
+
*
|
|
26
|
+
* The fetch API returns headers as a Headers object with methods like get(), has(),
|
|
27
|
+
* etc. However, the rest of the MSAL codebase expects headers as a simple key-value
|
|
28
|
+
* object. This function performs that conversion.
|
|
29
|
+
*
|
|
30
|
+
* @param headers - The Headers object returned by fetch response
|
|
31
|
+
* @returns A plain object with header names as keys and values as strings
|
|
32
|
+
*/
|
|
33
|
+
function getHeaderDict(headers) {
|
|
34
|
+
const headerDict = {};
|
|
35
|
+
headers.forEach((value, key) => {
|
|
36
|
+
headerDict[key] = value;
|
|
37
|
+
});
|
|
38
|
+
return headerDict;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Converts NetworkRequestOptions headers to a fetch-compatible Headers object.
|
|
42
|
+
*
|
|
43
|
+
* The MSAL library uses plain objects for headers in NetworkRequestOptions,
|
|
44
|
+
* but the fetch API expects either a Headers object, plain object, or array
|
|
45
|
+
* of arrays. Using the Headers constructor provides better compatibility
|
|
46
|
+
* and validation.
|
|
47
|
+
*
|
|
48
|
+
* @param options - Optional NetworkRequestOptions containing headers
|
|
49
|
+
* @returns A Headers object ready for use with fetch API
|
|
50
|
+
*/
|
|
51
|
+
function getFetchHeaders(options) {
|
|
52
|
+
const headers = new Headers();
|
|
53
|
+
if (options?.headers) {
|
|
54
|
+
Object.entries(options.headers).forEach(([key, value]) => {
|
|
55
|
+
headers.append(key, value);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return headers;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Custom network module implementation using @adobe/fetch.
|
|
63
|
+
*/
|
|
64
|
+
export class CustomNetworkModule {
|
|
65
|
+
/**
|
|
66
|
+
* @constructor
|
|
67
|
+
* @param {import('@adobe/fetch').FetchContext} fetchContext fetch context
|
|
68
|
+
*/
|
|
69
|
+
constructor(fetchContext) {
|
|
70
|
+
this.fetchContext = fetchContext;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Sends an HTTP GET request to the specified URL.
|
|
75
|
+
*
|
|
76
|
+
* This method handles GET requests with optional timeout support. The timeout
|
|
77
|
+
* is implemented using AbortController, which provides a clean way to cancel
|
|
78
|
+
* fetch requests that take too long to complete.
|
|
79
|
+
*
|
|
80
|
+
* @param url - The target URL for the GET request
|
|
81
|
+
* @param options - Optional request configuration including headers
|
|
82
|
+
* @param timeout - Optional timeout in milliseconds. If specified, the request
|
|
83
|
+
* will be aborted if it doesn't complete within this time
|
|
84
|
+
* @returns Promise that resolves to a NetworkResponse containing headers, body, and status
|
|
85
|
+
* @throws {AuthError} When the request times out or response parsing fails
|
|
86
|
+
* @throws {NetworkError} When the network request fails
|
|
87
|
+
*/
|
|
88
|
+
async sendGetRequestAsync(url, options, timeout) {
|
|
89
|
+
return this.sendRequest(url, HttpMethod.GET, options, timeout);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Sends an HTTP POST request to the specified URL.
|
|
94
|
+
*
|
|
95
|
+
* This method handles POST requests with request body support. Currently,
|
|
96
|
+
* timeout functionality is not exposed for POST requests, but the underlying
|
|
97
|
+
* implementation supports it through the shared sendRequest method.
|
|
98
|
+
*
|
|
99
|
+
* @param url - The target URL for the POST request
|
|
100
|
+
* @param options - Optional request configuration including headers and body
|
|
101
|
+
* @returns Promise that resolves to a NetworkResponse containing headers, body, and status
|
|
102
|
+
* @throws {AuthError} When the request times out or response parsing fails
|
|
103
|
+
* @throws {NetworkError} When the network request fails
|
|
104
|
+
*/
|
|
105
|
+
async sendPostRequestAsync(url, options) {
|
|
106
|
+
return this.sendRequest(url, HttpMethod.POST, options);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Send an HTTP request to the specified URL.
|
|
111
|
+
*
|
|
112
|
+
* @param url - The target URL for the request
|
|
113
|
+
* @param method - HTTP method (GET or POST)
|
|
114
|
+
* @param options - Optional request configuration (headers, body)
|
|
115
|
+
* @param timeout - Optional timeout in milliseconds for request cancellation
|
|
116
|
+
* @returns Promise resolving to NetworkResponse with parsed JSON body
|
|
117
|
+
* @throws {AuthError} For timeouts or JSON parsing errors
|
|
118
|
+
* @throws {NetworkError} For network failures
|
|
119
|
+
*/
|
|
120
|
+
async sendRequest(url, method, options, timeout) {
|
|
121
|
+
const fetchOptions = {
|
|
122
|
+
method,
|
|
123
|
+
headers: getFetchHeaders(options),
|
|
124
|
+
};
|
|
125
|
+
/*
|
|
126
|
+
* Configure timeout if specified
|
|
127
|
+
* The setTimeout will trigger abort() if the request takes too long
|
|
128
|
+
*/
|
|
129
|
+
let timerId;
|
|
130
|
+
if (timeout) {
|
|
131
|
+
const controller = new AbortController();
|
|
132
|
+
timerId = setTimeout(() => controller.abort(), timeout);
|
|
133
|
+
fetchOptions.signal = controller.signal;
|
|
134
|
+
}
|
|
135
|
+
if (method === HttpMethod.POST) {
|
|
136
|
+
fetchOptions.body = options?.body || '';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let response;
|
|
140
|
+
try {
|
|
141
|
+
const { fetch } = this.fetchContext;
|
|
142
|
+
response = await fetch(url, fetchOptions);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
// Clean up timeout to prevent memory leaks
|
|
145
|
+
if (timerId) {
|
|
146
|
+
clearTimeout(timerId);
|
|
147
|
+
}
|
|
148
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
149
|
+
throw createAuthError(ClientAuthErrorCodes.networkError, 'Request timeout');
|
|
150
|
+
}
|
|
151
|
+
const baseAuthError = createAuthError(ClientAuthErrorCodes.networkError, `Network request failed: ${error instanceof Error ? error.message : /* c8 ignore next */ 'unknown'}`);
|
|
152
|
+
throw createNetworkError(
|
|
153
|
+
baseAuthError,
|
|
154
|
+
undefined,
|
|
155
|
+
undefined,
|
|
156
|
+
error instanceof Error ? error : /* c8 ignore next */ undefined,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
return {
|
|
161
|
+
headers: getHeaderDict(response.headers),
|
|
162
|
+
body: (await response.json()),
|
|
163
|
+
status: response.status,
|
|
164
|
+
};
|
|
165
|
+
} catch (error) {
|
|
166
|
+
throw createAuthError(ClientAuthErrorCodes.tokenParsingError, `Failed to parse response: ${error instanceof Error ? error.message : /* c8 ignore next */ 'unknown'}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
package/src/OneDriveAuth.js
CHANGED
|
@@ -16,6 +16,7 @@ import { ConfidentialClientApplication, LogLevel, PublicClientApplication } from
|
|
|
16
16
|
import { MemCachePlugin } from '@adobe/helix-shared-tokencache';
|
|
17
17
|
import { decodeJwt } from 'jose';
|
|
18
18
|
import { StatusCodeError } from './StatusCodeError.js';
|
|
19
|
+
import { CustomNetworkModule } from './CustomNetworkModule.js';
|
|
19
20
|
|
|
20
21
|
const AZ_AUTHORITY_HOST_URL = 'https://login.windows.net';
|
|
21
22
|
const AZ_COMMON_TENANT = 'common';
|
|
@@ -155,6 +156,7 @@ export class OneDriveAuth {
|
|
|
155
156
|
piiLoggingEnabled: false,
|
|
156
157
|
logLevel: LogLevel.Info,
|
|
157
158
|
},
|
|
159
|
+
networkClient: new CustomNetworkModule(this.fetchContext),
|
|
158
160
|
},
|
|
159
161
|
};
|
|
160
162
|
if (cachePlugin) {
|