microsoft-graph 3.7.1 → 3.8.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/dist/cjs/models/Address.d.ts +32 -1
- package/dist/cjs/models/Address.d.ts.map +1 -1
- package/dist/cjs/models/DriveItem.d.ts +6 -0
- package/dist/cjs/models/DriveItem.d.ts.map +1 -1
- package/dist/cjs/operations/driveItem/createDriveItem.d.ts +3 -0
- package/dist/cjs/operations/driveItem/createDriveItem.d.ts.map +1 -1
- package/dist/cjs/operations/driveItem/createDriveItem.js +3 -0
- package/dist/cjs/operations/driveItem/createDriveItemContent.d.ts +21 -0
- package/dist/cjs/operations/driveItem/createDriveItemContent.d.ts.map +1 -0
- package/dist/cjs/operations/driveItem/createDriveItemContent.js +122 -0
- package/dist/cjs/operations/driveItem/existsDriveItem.d.ts.map +1 -1
- package/dist/cjs/operations/driveItem/existsDriveItem.js +1 -2
- package/dist/cjs/operations/driveItem/getDriveItemContent.d.ts.map +1 -1
- package/dist/cjs/operations/driveItem/getDriveItemContent.js +2 -9
- package/dist/cjs/operations/driveItem/streamDriveItemContent.d.ts.map +1 -1
- package/dist/cjs/operations/driveItem/streamDriveItemContent.js +2 -9
- package/dist/cjs/services/azureApplicationCredentials.d.ts +2 -7
- package/dist/cjs/services/azureApplicationCredentials.d.ts.map +1 -1
- package/dist/cjs/services/azureApplicationCredentials.js +2 -7
- package/dist/cjs/services/context.d.ts +11 -8
- package/dist/cjs/services/context.d.ts.map +1 -1
- package/dist/cjs/services/context.js +19 -16
- package/dist/cjs/services/http.d.ts +12 -2
- package/dist/cjs/services/http.d.ts.map +1 -1
- package/dist/cjs/services/http.js +207 -3
- package/dist/cjs/services/httpStatus.d.ts +6 -0
- package/dist/cjs/services/httpStatus.d.ts.map +1 -1
- package/dist/cjs/services/httpStatus.js +9 -0
- package/dist/cjs/services/operationInvoker.d.ts +0 -1
- package/dist/cjs/services/operationInvoker.d.ts.map +1 -1
- package/dist/cjs/services/operationInvoker.js +8 -207
- package/dist/cjs/services/usedAddress.d.ts +25 -0
- package/dist/cjs/services/usedAddress.d.ts.map +1 -0
- package/dist/cjs/services/usedAddress.js +69 -0
- package/dist/cjs/tasks/iterateDriveItems.d.ts.map +1 -1
- package/dist/cjs/tasks/iterateDriveItems.js +1 -2
- package/dist/cjs/tasks/iterateDrives.d.ts.map +1 -1
- package/dist/cjs/tasks/iterateDrives.js +1 -2
- package/dist/cjs/tasks/iterateSiteSearch.d.ts.map +1 -1
- package/dist/cjs/tasks/iterateSiteSearch.js +1 -2
- package/dist/cjs/tasks/iterateSites.d.ts.map +1 -1
- package/dist/cjs/tasks/iterateSites.js +1 -2
- package/dist/esm/models/Address.d.ts +32 -1
- package/dist/esm/models/Address.d.ts.map +1 -1
- package/dist/esm/models/DriveItem.d.ts +6 -0
- package/dist/esm/models/DriveItem.d.ts.map +1 -1
- package/dist/esm/operations/driveItem/createDriveItem.d.ts +3 -0
- package/dist/esm/operations/driveItem/createDriveItem.d.ts.map +1 -1
- package/dist/esm/operations/driveItem/createDriveItem.js +3 -0
- package/dist/esm/operations/driveItem/createDriveItemContent.d.ts +21 -0
- package/dist/esm/operations/driveItem/createDriveItemContent.d.ts.map +1 -0
- package/dist/esm/operations/driveItem/createDriveItemContent.js +116 -0
- package/dist/esm/operations/driveItem/existsDriveItem.d.ts.map +1 -1
- package/dist/esm/operations/driveItem/existsDriveItem.js +2 -3
- package/dist/esm/operations/driveItem/getDriveItemContent.d.ts.map +1 -1
- package/dist/esm/operations/driveItem/getDriveItemContent.js +4 -11
- package/dist/esm/operations/driveItem/streamDriveItemContent.d.ts.map +1 -1
- package/dist/esm/operations/driveItem/streamDriveItemContent.js +4 -11
- package/dist/esm/services/azureApplicationCredentials.d.ts +2 -7
- package/dist/esm/services/azureApplicationCredentials.d.ts.map +1 -1
- package/dist/esm/services/azureApplicationCredentials.js +2 -7
- package/dist/esm/services/context.d.ts +11 -8
- package/dist/esm/services/context.d.ts.map +1 -1
- package/dist/esm/services/context.js +18 -15
- package/dist/esm/services/http.d.ts +12 -2
- package/dist/esm/services/http.d.ts.map +1 -1
- package/dist/esm/services/http.js +204 -2
- package/dist/esm/services/httpStatus.d.ts +6 -0
- package/dist/esm/services/httpStatus.d.ts.map +1 -1
- package/dist/esm/services/httpStatus.js +8 -0
- package/dist/esm/services/operationInvoker.d.ts +0 -1
- package/dist/esm/services/operationInvoker.d.ts.map +1 -1
- package/dist/esm/services/operationInvoker.js +10 -208
- package/dist/esm/services/usedAddress.d.ts +25 -0
- package/dist/esm/services/usedAddress.d.ts.map +1 -0
- package/dist/esm/services/usedAddress.js +63 -0
- package/dist/esm/tasks/iterateDriveItems.d.ts.map +1 -1
- package/dist/esm/tasks/iterateDriveItems.js +2 -3
- package/dist/esm/tasks/iterateDrives.d.ts.map +1 -1
- package/dist/esm/tasks/iterateDrives.js +2 -3
- package/dist/esm/tasks/iterateSiteSearch.d.ts.map +1 -1
- package/dist/esm/tasks/iterateSiteSearch.js +2 -3
- package/dist/esm/tasks/iterateSites.d.ts.map +1 -1
- package/dist/esm/tasks/iterateSites.js +2 -3
- package/docs/api/Address.md +99 -13
- package/docs/api/DriveItem-1.md +16 -0
- package/docs/api/README.md +3 -3
- package/docs/api/context.md +28 -26
- package/docs/api/createDriveItemContent.md +37 -0
- package/docs/api/drive.md +3 -3
- package/docs/api/http.md +65 -4
- package/docs/api/httpStatus.md +48 -26
- package/docs/api/operationInvoker.md +3 -22
- package/docs/api/services/usedAddress.md +47 -0
- package/docs/api/streamDriveItemContent.md +1 -1
- package/package.json +21 -1
- package/docs/api/azureApplicationCredentials.md +0 -31
- package/docs/api/createDriveItem.md +0 -38
- /package/docs/api/{AzureApplicationCredentials-1.md → AzureApplicationCredentials.md} +0 -0
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
* @module http
|
|
4
4
|
* @category Services
|
|
5
5
|
*/
|
|
6
|
-
import { type
|
|
7
|
-
|
|
6
|
+
import { type AxiosResponse, type RawAxiosRequestHeaders, type ResponseType } from "axios";
|
|
7
|
+
import type { HttpMethod } from "../models/Http.ts";
|
|
8
|
+
export type Request = {
|
|
9
|
+
url: string;
|
|
10
|
+
method: HttpMethod;
|
|
11
|
+
headers?: RawAxiosRequestHeaders;
|
|
12
|
+
data?: unknown;
|
|
13
|
+
responseType?: ResponseType;
|
|
14
|
+
};
|
|
15
|
+
export declare function execute<TResponse>(request: Request): Promise<TResponse>;
|
|
16
|
+
export declare function throwHttpException(responseCode: number, message: string): never;
|
|
17
|
+
export declare function executeRaw(request: Request): Promise<AxiosResponse<any, any>>;
|
|
8
18
|
//# sourceMappingURL=http.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/services/http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/services/http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAc,EAA+C,KAAK,aAAa,EAA4B,KAAK,sBAAsB,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AA0BzK,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAkCpD,MAAM,MAAM,OAAO,GAAG;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,wBAAsB,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAkD7E;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAwE/E;AAID,wBAAsB,UAAU,CAAC,OAAO,EAAE,OAAO,oCAMhD"}
|
|
@@ -5,12 +5,159 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import axios from "axios";
|
|
7
7
|
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
8
|
+
import BadRequestError from "../errors/BadRequestError.js";
|
|
9
|
+
import BandwidthLimitExceededError from "../errors/BandwidthLimitExceededError.js";
|
|
10
|
+
import ConflictError from "../errors/ConflictError.js";
|
|
11
|
+
import ForbiddenError from "../errors/ForbiddenError.js";
|
|
12
|
+
import GatewayTimeoutError from "../errors/GatewayTimeoutError.js";
|
|
13
|
+
import GoneError from "../errors/GoneError.js";
|
|
14
|
+
import InsufficientStorageError from "../errors/InsufficientStorageError.js";
|
|
15
|
+
import InternalServerError from "../errors/InternalServerError.js";
|
|
16
|
+
import LengthRequiredError from "../errors/LengthRequiredError.js";
|
|
17
|
+
import LockedError from "../errors/LockedError.js";
|
|
18
|
+
import MethodNotAllowedError from "../errors/MethodNotAllowedError.js";
|
|
19
|
+
import NeverError from "../errors/NeverError.js";
|
|
20
|
+
import NotAcceptableError from "../errors/NotAcceptableError.js";
|
|
21
|
+
import NotFoundError from "../errors/NotFoundError.js";
|
|
22
|
+
import NotImplementedError from "../errors/NotImplementedError.js";
|
|
23
|
+
import PaymentRequiredError from "../errors/PaymentRequiredError.js";
|
|
24
|
+
import PreconditionFailedError from "../errors/PreconditionFailedError.js";
|
|
25
|
+
import RequestedRangeNotSatisfiableError from "../errors/RequestedRangeNotSatisfiableError.js";
|
|
26
|
+
import RequestEntityTooLargeError from "../errors/RequestEntityTooLargeError.js";
|
|
27
|
+
import ServiceUnavailableError from "../errors/ServiceUnavailableError.js";
|
|
28
|
+
import TooManyRequestsError from "../errors/TooManyRequestsError.js";
|
|
29
|
+
import UnauthorizedError from "../errors/UnauthorizedError.js";
|
|
30
|
+
import UnprocessableEntityError from "../errors/UnprocessableEntityError.js";
|
|
31
|
+
import UnsupportedMediaTypeError from "../errors/UnsupportedMediaTypeError.js";
|
|
32
|
+
import { isHttpBadRequest, isHttpBandwidthLimitExceeded, isHttpConflict, isHttpForbidden, isHttpGatewayTimeout, isHttpGone, isHttpInsufficientStorage, isHttpInternalServerError, isHttpLengthRequired, isHttpLocked, isHttpMethodNotAllowed, isHttpNotAcceptable, isHttpNotFound, isHttpNotImplemented, isHttpPaymentRequired, isHttpPreconditionFailed, isHttpRequestedRangeNotSatisfiable, isHttpRequestEntityTooLarge, isHttpServiceUnavailable, isHttpSuccess, isHttpTooManyRequests, isHttpUnauthorized, isHttpUnprocessableEntity, isHttpUnsupportedMediaType, isRetryable, } from "./httpStatus.js";
|
|
33
|
+
import { sleep } from "./sleep.js";
|
|
34
|
+
const maxRetries = 3;
|
|
35
|
+
const defaultRetryDelayMilliseconds = 1000;
|
|
36
|
+
const consecutiveRetryDelayMultiplier = 2;
|
|
37
|
+
export async function execute(request) {
|
|
38
|
+
let retryAfterMilliseconds = defaultRetryDelayMilliseconds;
|
|
39
|
+
let response = null;
|
|
40
|
+
let attempts = 0;
|
|
41
|
+
let errorLog = "";
|
|
42
|
+
while (true) {
|
|
43
|
+
try {
|
|
44
|
+
response = await executeRaw(request);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const message = error instanceof Error ? error.message : error?.toString() || "Unknown error";
|
|
48
|
+
response = {
|
|
49
|
+
status: -1,
|
|
50
|
+
statusText: message,
|
|
51
|
+
headers: {},
|
|
52
|
+
data: null,
|
|
53
|
+
config: request,
|
|
54
|
+
request: null,
|
|
55
|
+
};
|
|
56
|
+
errorLog += message;
|
|
57
|
+
}
|
|
58
|
+
errorLog += requestToString(request);
|
|
59
|
+
errorLog += responseToString(response);
|
|
60
|
+
attempts++;
|
|
61
|
+
if (isHttpSuccess(response.status) || !isRetryable(response.status) || attempts === maxRetries) {
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
const requestedRetryAfterSeconds = Number.parseInt(response.headers["retry-after"] ?? "0", 10);
|
|
65
|
+
if (requestedRetryAfterSeconds) {
|
|
66
|
+
retryAfterMilliseconds = requestedRetryAfterSeconds * 1000;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
retryAfterMilliseconds += Math.random() * 1000; // Add some randomness to the retry delay to avoid thundering herd problem
|
|
70
|
+
}
|
|
71
|
+
errorLog += waitToString(retryAfterMilliseconds);
|
|
72
|
+
await sleep(retryAfterMilliseconds);
|
|
73
|
+
retryAfterMilliseconds *= consecutiveRetryDelayMultiplier;
|
|
74
|
+
}
|
|
75
|
+
if (!response) {
|
|
76
|
+
throw new NeverError("Response is empty.");
|
|
77
|
+
}
|
|
78
|
+
if (!isHttpSuccess(response.status)) {
|
|
79
|
+
handleResponseError(response, errorLog, attempts);
|
|
80
|
+
}
|
|
81
|
+
return response.data;
|
|
82
|
+
}
|
|
83
|
+
export function throwHttpException(responseCode, message) {
|
|
84
|
+
if (isHttpBadRequest(responseCode)) {
|
|
85
|
+
throw new BadRequestError(message);
|
|
86
|
+
}
|
|
87
|
+
if (isHttpUnauthorized(responseCode)) {
|
|
88
|
+
throw new UnauthorizedError(message);
|
|
89
|
+
}
|
|
90
|
+
if (isHttpPaymentRequired(responseCode)) {
|
|
91
|
+
throw new PaymentRequiredError(message);
|
|
92
|
+
}
|
|
93
|
+
if (isHttpForbidden(responseCode)) {
|
|
94
|
+
throw new ForbiddenError(message);
|
|
95
|
+
}
|
|
96
|
+
if (isHttpNotFound(responseCode)) {
|
|
97
|
+
throw new NotFoundError(message);
|
|
98
|
+
}
|
|
99
|
+
if (isHttpMethodNotAllowed(responseCode)) {
|
|
100
|
+
throw new MethodNotAllowedError(message);
|
|
101
|
+
}
|
|
102
|
+
if (isHttpNotAcceptable(responseCode)) {
|
|
103
|
+
throw new NotAcceptableError(message);
|
|
104
|
+
}
|
|
105
|
+
if (isHttpConflict(responseCode)) {
|
|
106
|
+
throw new ConflictError(message);
|
|
107
|
+
}
|
|
108
|
+
if (isHttpGone(responseCode)) {
|
|
109
|
+
throw new GoneError(message);
|
|
110
|
+
}
|
|
111
|
+
if (isHttpLengthRequired(responseCode)) {
|
|
112
|
+
throw new LengthRequiredError(message);
|
|
113
|
+
}
|
|
114
|
+
if (isHttpPreconditionFailed(responseCode)) {
|
|
115
|
+
throw new PreconditionFailedError(message);
|
|
116
|
+
}
|
|
117
|
+
if (isHttpRequestEntityTooLarge(responseCode)) {
|
|
118
|
+
throw new RequestEntityTooLargeError(message);
|
|
119
|
+
}
|
|
120
|
+
if (isHttpUnsupportedMediaType(responseCode)) {
|
|
121
|
+
throw new UnsupportedMediaTypeError(message);
|
|
122
|
+
}
|
|
123
|
+
if (isHttpRequestedRangeNotSatisfiable(responseCode)) {
|
|
124
|
+
throw new RequestedRangeNotSatisfiableError(message);
|
|
125
|
+
}
|
|
126
|
+
if (isHttpUnprocessableEntity(responseCode)) {
|
|
127
|
+
throw new UnprocessableEntityError(message);
|
|
128
|
+
}
|
|
129
|
+
if (isHttpLocked(responseCode)) {
|
|
130
|
+
throw new LockedError(message);
|
|
131
|
+
}
|
|
132
|
+
if (isHttpTooManyRequests(responseCode)) {
|
|
133
|
+
throw new TooManyRequestsError(message);
|
|
134
|
+
}
|
|
135
|
+
if (isHttpInternalServerError(responseCode)) {
|
|
136
|
+
throw new InternalServerError(message);
|
|
137
|
+
}
|
|
138
|
+
if (isHttpNotImplemented(responseCode)) {
|
|
139
|
+
throw new NotImplementedError(message);
|
|
140
|
+
}
|
|
141
|
+
if (isHttpServiceUnavailable(responseCode)) {
|
|
142
|
+
throw new ServiceUnavailableError(message);
|
|
143
|
+
}
|
|
144
|
+
if (isHttpGatewayTimeout(responseCode)) {
|
|
145
|
+
throw new GatewayTimeoutError(message);
|
|
146
|
+
}
|
|
147
|
+
if (isHttpInsufficientStorage(responseCode)) {
|
|
148
|
+
throw new InsufficientStorageError(message);
|
|
149
|
+
}
|
|
150
|
+
if (isHttpBandwidthLimitExceeded(responseCode)) {
|
|
151
|
+
throw new BandwidthLimitExceededError(message);
|
|
152
|
+
}
|
|
153
|
+
throw new Error(message);
|
|
154
|
+
}
|
|
8
155
|
let instance = null;
|
|
9
|
-
export async function
|
|
156
|
+
export async function executeRaw(request) {
|
|
10
157
|
if (!instance) {
|
|
11
158
|
instance = createAxiosInstance();
|
|
12
159
|
}
|
|
13
|
-
return await instance(
|
|
160
|
+
return await instance(request);
|
|
14
161
|
}
|
|
15
162
|
function createAxiosInstance() {
|
|
16
163
|
const config = {
|
|
@@ -24,3 +171,58 @@ function createAxiosInstance() {
|
|
|
24
171
|
}
|
|
25
172
|
return axios.create(config);
|
|
26
173
|
}
|
|
174
|
+
function requestToString(request) {
|
|
175
|
+
const url = request.url || "";
|
|
176
|
+
let message = ` 📤 ${request.method} ${url}\n`;
|
|
177
|
+
if (request.data) {
|
|
178
|
+
message += errorObjectToString(request.data);
|
|
179
|
+
}
|
|
180
|
+
return message;
|
|
181
|
+
}
|
|
182
|
+
function responseToString(response) {
|
|
183
|
+
const message = ` 📥 ${response.status} ${response.statusText}\n`;
|
|
184
|
+
// TODO: Is there any case where we care about the response body?
|
|
185
|
+
// if (response.data) {
|
|
186
|
+
// message += errorObjectToString(response.data);
|
|
187
|
+
// }
|
|
188
|
+
return message;
|
|
189
|
+
}
|
|
190
|
+
function waitToString(milliseconds) {
|
|
191
|
+
return ` ⏳ Wait ${milliseconds}ms for retry.\n`;
|
|
192
|
+
}
|
|
193
|
+
function errorObjectToString(obj) {
|
|
194
|
+
const maxLength = 1024;
|
|
195
|
+
const ellipses = "...";
|
|
196
|
+
let str = JSON.stringify(obj, null, 2)
|
|
197
|
+
.split("\n")
|
|
198
|
+
.map((line) => ` ${line}`)
|
|
199
|
+
.join("\n");
|
|
200
|
+
if (str.length > maxLength) {
|
|
201
|
+
str = `${str.substring(0, maxLength - ellipses.length)}${ellipses}`;
|
|
202
|
+
}
|
|
203
|
+
return `${str}\n`;
|
|
204
|
+
}
|
|
205
|
+
function handleResponseError(response, errorLog, attempts, operationIndex = null) {
|
|
206
|
+
const error = response.data;
|
|
207
|
+
let message = error?.error?.message;
|
|
208
|
+
if (message && !message.endsWith(".")) {
|
|
209
|
+
message += ".";
|
|
210
|
+
}
|
|
211
|
+
if (error?.error?.innerError?.message) {
|
|
212
|
+
message += ` ${error.error.innerError.message}`;
|
|
213
|
+
}
|
|
214
|
+
if (message && !message.endsWith(".")) {
|
|
215
|
+
message += ".";
|
|
216
|
+
}
|
|
217
|
+
if (!message) {
|
|
218
|
+
message = response.statusText;
|
|
219
|
+
}
|
|
220
|
+
if (attempts > 1) {
|
|
221
|
+
message += ` Operation attempted ${attempts} time(s).`;
|
|
222
|
+
}
|
|
223
|
+
if (operationIndex !== null) {
|
|
224
|
+
message += ` (op #${operationIndex})`;
|
|
225
|
+
}
|
|
226
|
+
message += `\n${errorLog}`;
|
|
227
|
+
throwHttpException(response.status, message);
|
|
228
|
+
}
|
|
@@ -15,6 +15,12 @@ export declare function isHttpSuccess(status: number): boolean;
|
|
|
15
15
|
* @returns True if the status code is 200, otherwise false.
|
|
16
16
|
*/
|
|
17
17
|
export declare function isHttpOk(status: number): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Checks if the HTTP status code is created
|
|
20
|
+
* @param status - The HTTP status code.
|
|
21
|
+
* @returns True if the status code is 201, otherwise false.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isHttpCreated(status: number): boolean;
|
|
18
24
|
/**
|
|
19
25
|
* Checks if the HTTP status code indicates not found.
|
|
20
26
|
* @param status - The HTTP status code.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpStatus.d.ts","sourceRoot":"","sources":["../../../src/services/httpStatus.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElE;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAenD"}
|
|
1
|
+
{"version":3,"file":"httpStatus.d.ts","sourceRoot":"","sources":["../../../src/services/httpStatus.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElE;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAenD"}
|
|
@@ -19,6 +19,14 @@ export function isHttpSuccess(status) {
|
|
|
19
19
|
export function isHttpOk(status) {
|
|
20
20
|
return status === 200;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Checks if the HTTP status code is created
|
|
24
|
+
* @param status - The HTTP status code.
|
|
25
|
+
* @returns True if the status code is 201, otherwise false.
|
|
26
|
+
*/
|
|
27
|
+
export function isHttpCreated(status) {
|
|
28
|
+
return status === 201;
|
|
29
|
+
}
|
|
22
30
|
/**
|
|
23
31
|
* Checks if the HTTP status code indicates not found.
|
|
24
32
|
* @param status - The HTTP status code.
|
|
@@ -39,5 +39,4 @@ export declare function parallel<T extends GraphOperation<unknown>[]>(...operati
|
|
|
39
39
|
* @returns The responses for each operation, in the same order.
|
|
40
40
|
*/
|
|
41
41
|
export declare function sequential<T extends GraphOperation<unknown>[]>(...operations: T): Promise<OperationResponse<T>>;
|
|
42
|
-
export declare function throwException(responseCode: number, message: string): never;
|
|
43
42
|
//# sourceMappingURL=operationInvoker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operationInvoker.d.ts","sourceRoot":"","sources":["../../../src/services/operationInvoker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"operationInvoker.d.ts","sourceRoot":"","sources":["../../../src/services/operationInvoker.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAM/G;;;GAGG;AACH,eAAO,MAAM,QAAQ,qCAAqC,CAAC;AAE3D;;;GAGG;AACH,eAAO,MAAM,aAAa,4CAAuB,CAAC;AAElD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAQvF;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,CAAC,SAAS,cAAc,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,UAAU,EAAE,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAInH;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,cAAc,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,UAAU,EAAE,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAOrH"}
|
|
@@ -1,34 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import GoneError from "../errors/GoneError.js";
|
|
1
|
+
/**
|
|
2
|
+
* Invoke operations, potentially as parallel or sequential batches.
|
|
3
|
+
* @module operationInvoker
|
|
4
|
+
* @category Services
|
|
5
|
+
**/
|
|
7
6
|
import InconsistentContextError from "../errors/InconsistentContextError.js";
|
|
8
|
-
import InsufficientStorageError from "../errors/InsufficientStorageError.js";
|
|
9
|
-
import InternalServerError from "../errors/InternalServerError.js";
|
|
10
7
|
import InvalidArgumentError from "../errors/InvalidArgumentError.js";
|
|
11
|
-
import LengthRequiredError from "../errors/LengthRequiredError.js";
|
|
12
|
-
import LockedError from "../errors/LockedError.js";
|
|
13
|
-
import MethodNotAllowedError from "../errors/MethodNotAllowedError.js";
|
|
14
8
|
import NeverError from "../errors/NeverError.js";
|
|
15
|
-
import NotAcceptableError from "../errors/NotAcceptableError.js";
|
|
16
|
-
import NotFoundError from "../errors/NotFoundError.js";
|
|
17
|
-
import NotImplementedError from "../errors/NotImplementedError.js";
|
|
18
|
-
import PaymentRequiredError from "../errors/PaymentRequiredError.js";
|
|
19
|
-
import PreconditionFailedError from "../errors/PreconditionFailedError.js";
|
|
20
9
|
import ProtocolError from "../errors/ProtocolError.js";
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import ServiceUnavailableError from "../errors/ServiceUnavailableError.js";
|
|
24
|
-
import TooManyRequestsError from "../errors/TooManyRequestsError.js";
|
|
25
|
-
import UnauthorizedError from "../errors/UnauthorizedError.js";
|
|
26
|
-
import UnprocessableEntityError from "../errors/UnprocessableEntityError.js";
|
|
27
|
-
import UnsupportedMediaTypeError from "../errors/UnsupportedMediaTypeError.js";
|
|
28
|
-
import { executeHttpRequest } from "./http.js";
|
|
29
|
-
import { isHttpBadRequest, isHttpBandwidthLimitExceeded, isHttpConflict, isHttpForbidden, isHttpGatewayTimeout, isHttpGone, isHttpInsufficientStorage, isHttpInternalServerError, isHttpLengthRequired, isHttpLocked, isHttpMethodNotAllowed, isHttpNotAcceptable, isHttpNotFound, isHttpNotImplemented, isHttpPaymentRequired, isHttpPreconditionFailed, isHttpRequestedRangeNotSatisfiable, isHttpRequestEntityTooLarge, isHttpServiceUnavailable, isHttpSuccess, isHttpTooManyRequests, isHttpUnauthorized, isHttpUnprocessableEntity, isHttpUnsupportedMediaType, isRetryable, } from "./httpStatus.js";
|
|
10
|
+
import { execute, throwHttpException } from "./http.js";
|
|
11
|
+
import { isHttpSuccess } from "./httpStatus.js";
|
|
30
12
|
import { operationIdToIndex, operationIndexToId } from "./operationId.js";
|
|
31
|
-
import { sleep } from "./sleep.js";
|
|
32
13
|
/**
|
|
33
14
|
* Endpoint for submitting individual requests.
|
|
34
15
|
* @internal
|
|
@@ -86,12 +67,9 @@ export async function sequential(...operations) {
|
|
|
86
67
|
return (await executeBatch(...definitions));
|
|
87
68
|
}
|
|
88
69
|
const maxBatchOperations = 20; // https://learn.microsoft.com/en-us/graph/json-batching?tabs=http#batch-size-limitations
|
|
89
|
-
const maxRetries = 3;
|
|
90
|
-
const defaultRetryDelayMilliseconds = 1000;
|
|
91
|
-
const consecutiveRetryDelayMultiplier = 2;
|
|
92
70
|
async function executeSingle(definition) {
|
|
93
71
|
const accessToken = await definition.context.generateAccessToken();
|
|
94
|
-
const response = await
|
|
72
|
+
const response = await execute({
|
|
95
73
|
url: `${endpoint}${definition.path}`,
|
|
96
74
|
method: definition.method,
|
|
97
75
|
headers: {
|
|
@@ -116,7 +94,7 @@ async function executeBatch(...ops) {
|
|
|
116
94
|
throw new InconsistentContextError("All operations in a batch must share the same context.");
|
|
117
95
|
}
|
|
118
96
|
const accessToken = await context.generateAccessToken();
|
|
119
|
-
const body = await
|
|
97
|
+
const body = await execute({
|
|
120
98
|
url: batchEndpoint,
|
|
121
99
|
method: "POST",
|
|
122
100
|
headers: {
|
|
@@ -146,188 +124,12 @@ async function executeBatch(...ops) {
|
|
|
146
124
|
throw new ProtocolError("Reference to operation that was not submitted in the batch");
|
|
147
125
|
}
|
|
148
126
|
if (!isHttpSuccess(r.status)) {
|
|
149
|
-
|
|
127
|
+
throwHttpException(r.status, `Batch operation failed for op #${index}: ${JSON.stringify(r.body, null, 2)}`);
|
|
150
128
|
}
|
|
151
129
|
responses[index] = op.responseTransform(body);
|
|
152
130
|
}
|
|
153
131
|
return responses; // TODO: Is there a neater way to massage the types correctly? This is functionally correct, but I do want to avoid using `unknown` here if possible.
|
|
154
132
|
}
|
|
155
|
-
async function innerFetch(request) {
|
|
156
|
-
let retryAfterMilliseconds = defaultRetryDelayMilliseconds;
|
|
157
|
-
let response = null;
|
|
158
|
-
let attempts = 0;
|
|
159
|
-
let errorLog = "";
|
|
160
|
-
while (true) {
|
|
161
|
-
try {
|
|
162
|
-
response = await executeHttpRequest(request);
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
const message = error instanceof Error ? error.message : error?.toString() || "Unknown error";
|
|
166
|
-
response = {
|
|
167
|
-
status: -1,
|
|
168
|
-
statusText: message,
|
|
169
|
-
headers: {},
|
|
170
|
-
data: null,
|
|
171
|
-
config: request,
|
|
172
|
-
request: null,
|
|
173
|
-
};
|
|
174
|
-
errorLog += message;
|
|
175
|
-
}
|
|
176
|
-
errorLog += requestToString(request);
|
|
177
|
-
errorLog += responseToString(response);
|
|
178
|
-
attempts++;
|
|
179
|
-
if (isHttpSuccess(response.status) || !isRetryable(response.status) || attempts === maxRetries) {
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
const requestedRetryAfterSeconds = Number.parseInt(response.headers["retry-after"] ?? "0", 10);
|
|
183
|
-
if (requestedRetryAfterSeconds) {
|
|
184
|
-
retryAfterMilliseconds = requestedRetryAfterSeconds * 1000;
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
retryAfterMilliseconds += Math.random() * 1000; // Add some randomness to the retry delay to avoid thundering herd problem
|
|
188
|
-
}
|
|
189
|
-
errorLog += waitToString(retryAfterMilliseconds);
|
|
190
|
-
await sleep(retryAfterMilliseconds);
|
|
191
|
-
retryAfterMilliseconds *= consecutiveRetryDelayMultiplier;
|
|
192
|
-
}
|
|
193
|
-
if (!response) {
|
|
194
|
-
throw new NeverError("Response is empty.");
|
|
195
|
-
}
|
|
196
|
-
if (!isHttpSuccess(response.status)) {
|
|
197
|
-
handleResponseError(response, errorLog, attempts);
|
|
198
|
-
}
|
|
199
|
-
return response.data;
|
|
200
|
-
}
|
|
201
|
-
function requestToString(request) {
|
|
202
|
-
let url = request.url || "";
|
|
203
|
-
if (url.startsWith(endpoint)) {
|
|
204
|
-
url = url.substring(endpoint.length);
|
|
205
|
-
}
|
|
206
|
-
let message = ` 📤 ${request.method} ${url}\n`;
|
|
207
|
-
if (request.data) {
|
|
208
|
-
message += errorObjectToString(request.data);
|
|
209
|
-
}
|
|
210
|
-
return message;
|
|
211
|
-
}
|
|
212
|
-
function responseToString(response) {
|
|
213
|
-
const message = ` 📥 ${response.status} ${response.statusText}\n`;
|
|
214
|
-
// TODO: Is there any case where we care about the response body?
|
|
215
|
-
// if (response.data) {
|
|
216
|
-
// message += errorObjectToString(response.data);
|
|
217
|
-
// }
|
|
218
|
-
return message;
|
|
219
|
-
}
|
|
220
|
-
function waitToString(milliseconds) {
|
|
221
|
-
return ` ⏳ Wait ${milliseconds}ms for retry.\n`;
|
|
222
|
-
}
|
|
223
|
-
function errorObjectToString(obj) {
|
|
224
|
-
const maxLength = 1024;
|
|
225
|
-
const ellipses = "...";
|
|
226
|
-
let str = JSON.stringify(obj, null, 2)
|
|
227
|
-
.split("\n")
|
|
228
|
-
.map((line) => ` ${line}`)
|
|
229
|
-
.join("\n");
|
|
230
|
-
if (str.length > maxLength) {
|
|
231
|
-
str = `${str.substring(0, maxLength - ellipses.length)}${ellipses}`;
|
|
232
|
-
}
|
|
233
|
-
return `${str}\n`;
|
|
234
|
-
}
|
|
235
|
-
function handleResponseError(response, errorLog, attempts, operationIndex = null) {
|
|
236
|
-
const error = response.data;
|
|
237
|
-
let message = error?.error?.message;
|
|
238
|
-
if (message && !message.endsWith(".")) {
|
|
239
|
-
message += ".";
|
|
240
|
-
}
|
|
241
|
-
if (error?.error?.innerError?.message) {
|
|
242
|
-
message += ` ${error.error.innerError.message}`;
|
|
243
|
-
}
|
|
244
|
-
if (message && !message.endsWith(".")) {
|
|
245
|
-
message += ".";
|
|
246
|
-
}
|
|
247
|
-
if (!message) {
|
|
248
|
-
message = response.statusText;
|
|
249
|
-
}
|
|
250
|
-
if (attempts > 1) {
|
|
251
|
-
message += ` Operation attempted ${attempts} time(s).`;
|
|
252
|
-
}
|
|
253
|
-
if (operationIndex !== null) {
|
|
254
|
-
message += ` (op #${operationIndex})`;
|
|
255
|
-
}
|
|
256
|
-
message += `\n${errorLog}`;
|
|
257
|
-
throwException(response.status, message);
|
|
258
|
-
}
|
|
259
|
-
export function throwException(responseCode, message) {
|
|
260
|
-
if (isHttpBadRequest(responseCode)) {
|
|
261
|
-
throw new BadRequestError(message);
|
|
262
|
-
}
|
|
263
|
-
if (isHttpUnauthorized(responseCode)) {
|
|
264
|
-
throw new UnauthorizedError(message);
|
|
265
|
-
}
|
|
266
|
-
if (isHttpPaymentRequired(responseCode)) {
|
|
267
|
-
throw new PaymentRequiredError(message);
|
|
268
|
-
}
|
|
269
|
-
if (isHttpForbidden(responseCode)) {
|
|
270
|
-
throw new ForbiddenError(message);
|
|
271
|
-
}
|
|
272
|
-
if (isHttpNotFound(responseCode)) {
|
|
273
|
-
throw new NotFoundError(message);
|
|
274
|
-
}
|
|
275
|
-
if (isHttpMethodNotAllowed(responseCode)) {
|
|
276
|
-
throw new MethodNotAllowedError(message);
|
|
277
|
-
}
|
|
278
|
-
if (isHttpNotAcceptable(responseCode)) {
|
|
279
|
-
throw new NotAcceptableError(message);
|
|
280
|
-
}
|
|
281
|
-
if (isHttpConflict(responseCode)) {
|
|
282
|
-
throw new ConflictError(message);
|
|
283
|
-
}
|
|
284
|
-
if (isHttpGone(responseCode)) {
|
|
285
|
-
throw new GoneError(message);
|
|
286
|
-
}
|
|
287
|
-
if (isHttpLengthRequired(responseCode)) {
|
|
288
|
-
throw new LengthRequiredError(message);
|
|
289
|
-
}
|
|
290
|
-
if (isHttpPreconditionFailed(responseCode)) {
|
|
291
|
-
throw new PreconditionFailedError(message);
|
|
292
|
-
}
|
|
293
|
-
if (isHttpRequestEntityTooLarge(responseCode)) {
|
|
294
|
-
throw new RequestEntityTooLargeError(message);
|
|
295
|
-
}
|
|
296
|
-
if (isHttpUnsupportedMediaType(responseCode)) {
|
|
297
|
-
throw new UnsupportedMediaTypeError(message);
|
|
298
|
-
}
|
|
299
|
-
if (isHttpRequestedRangeNotSatisfiable(responseCode)) {
|
|
300
|
-
throw new RequestedRangeNotSatisfiableError(message);
|
|
301
|
-
}
|
|
302
|
-
if (isHttpUnprocessableEntity(responseCode)) {
|
|
303
|
-
throw new UnprocessableEntityError(message);
|
|
304
|
-
}
|
|
305
|
-
if (isHttpLocked(responseCode)) {
|
|
306
|
-
throw new LockedError(message);
|
|
307
|
-
}
|
|
308
|
-
if (isHttpTooManyRequests(responseCode)) {
|
|
309
|
-
throw new TooManyRequestsError(message);
|
|
310
|
-
}
|
|
311
|
-
if (isHttpInternalServerError(responseCode)) {
|
|
312
|
-
throw new InternalServerError(message);
|
|
313
|
-
}
|
|
314
|
-
if (isHttpNotImplemented(responseCode)) {
|
|
315
|
-
throw new NotImplementedError(message);
|
|
316
|
-
}
|
|
317
|
-
if (isHttpServiceUnavailable(responseCode)) {
|
|
318
|
-
throw new ServiceUnavailableError(message);
|
|
319
|
-
}
|
|
320
|
-
if (isHttpGatewayTimeout(responseCode)) {
|
|
321
|
-
throw new GatewayTimeoutError(message);
|
|
322
|
-
}
|
|
323
|
-
if (isHttpInsufficientStorage(responseCode)) {
|
|
324
|
-
throw new InsufficientStorageError(message);
|
|
325
|
-
}
|
|
326
|
-
if (isHttpBandwidthLimitExceeded(responseCode)) {
|
|
327
|
-
throw new BandwidthLimitExceededError(message);
|
|
328
|
-
}
|
|
329
|
-
throw new NeverError(message);
|
|
330
|
-
}
|
|
331
133
|
function normalizeBatchBody(contentType, body) {
|
|
332
134
|
if (contentType?.startsWith("application/json") && typeof body === "string") {
|
|
333
135
|
return JSON.parse(atob(body));
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Address, CellRangeAddress, UsedAddress } from "../models/Address.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a used range address (which may use partial or open-ended A1 notation, e.g., ":D5", "C:", etc.) against a concrete used range.
|
|
4
|
+
*
|
|
5
|
+
* This function fills in any missing start/end columns or rows in the `usedRangeAddress` using the corresponding values from the provided `usedRange`.
|
|
6
|
+
*
|
|
7
|
+
* @param address - The used range address (may be open-ended, e.g., ":D5", "C:", etc.).
|
|
8
|
+
* @param usedRange - The concrete used range address to resolve against (e.g., "B2:E10").
|
|
9
|
+
* @returns The resolved address as a concrete A1 range (e.g., "C2:E10"), or null if there is no overlap.
|
|
10
|
+
* @throws {InvalidArgumentError} If the used range address is invalid or cannot be resolved.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // If usedRange is "B2:E10":
|
|
14
|
+
* // resolveUsedRangeAddress("C:", usedRange) // "C2:E10"
|
|
15
|
+
* // resolveUsedRangeAddress(":D", usedRange) // "B2:D10"
|
|
16
|
+
* // resolveUsedRangeAddress("3:", usedRange) // "B3:E10"
|
|
17
|
+
* // resolveUsedRangeAddress(":5", usedRange) // "B2:E5"
|
|
18
|
+
* // resolveUsedRangeAddress("C3:", usedRange) // "C3:E10"
|
|
19
|
+
* // resolveUsedRangeAddress(":D5", usedRange) // "B2:D5"
|
|
20
|
+
* // resolveUsedRangeAddress(":", usedRange) // "B2:E10"
|
|
21
|
+
* // resolveUsedRangeAddress("Z100:Z200", usedRange) // null (no overlap)
|
|
22
|
+
* // resolveUsedRangeAddress("A1:A1", usedRange) // null (no overlap)
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveUsedAddress(address: Address | UsedAddress, usedRange: CellRangeAddress): Address | null;
|
|
25
|
+
//# sourceMappingURL=usedAddress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usedAddress.d.ts","sourceRoot":"","sources":["../../../src/services/usedAddress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMnF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,EAAE,SAAS,EAAE,gBAAgB,GAAG,OAAO,GAAG,IAAI,CAuC9G"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import InvalidArgumentError from "../errors/InvalidArgumentError.js";
|
|
2
|
+
import { composeAddress, decomposeAddress } from "./addressManipulation.js";
|
|
3
|
+
import { columnAddressToOffset, rowAddressToOffset } from "./addressOffset.js";
|
|
4
|
+
const pattern = /^(?<startColumn>[A-Z]*)(?<startRow>[0-9]*):(?<endColumn>[A-Z]*)(?<endRow>[0-9]*)$/;
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a used range address (which may use partial or open-ended A1 notation, e.g., ":D5", "C:", etc.) against a concrete used range.
|
|
7
|
+
*
|
|
8
|
+
* This function fills in any missing start/end columns or rows in the `usedRangeAddress` using the corresponding values from the provided `usedRange`.
|
|
9
|
+
*
|
|
10
|
+
* @param address - The used range address (may be open-ended, e.g., ":D5", "C:", etc.).
|
|
11
|
+
* @param usedRange - The concrete used range address to resolve against (e.g., "B2:E10").
|
|
12
|
+
* @returns The resolved address as a concrete A1 range (e.g., "C2:E10"), or null if there is no overlap.
|
|
13
|
+
* @throws {InvalidArgumentError} If the used range address is invalid or cannot be resolved.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // If usedRange is "B2:E10":
|
|
17
|
+
* // resolveUsedRangeAddress("C:", usedRange) // "C2:E10"
|
|
18
|
+
* // resolveUsedRangeAddress(":D", usedRange) // "B2:D10"
|
|
19
|
+
* // resolveUsedRangeAddress("3:", usedRange) // "B3:E10"
|
|
20
|
+
* // resolveUsedRangeAddress(":5", usedRange) // "B2:E5"
|
|
21
|
+
* // resolveUsedRangeAddress("C3:", usedRange) // "C3:E10"
|
|
22
|
+
* // resolveUsedRangeAddress(":D5", usedRange) // "B2:D5"
|
|
23
|
+
* // resolveUsedRangeAddress(":", usedRange) // "B2:E10"
|
|
24
|
+
* // resolveUsedRangeAddress("Z100:Z200", usedRange) // null (no overlap)
|
|
25
|
+
* // resolveUsedRangeAddress("A1:A1", usedRange) // null (no overlap)
|
|
26
|
+
*/
|
|
27
|
+
export function resolveUsedAddress(address, usedRange) {
|
|
28
|
+
const match = pattern.exec(address.toUpperCase());
|
|
29
|
+
if (!match || !match.groups) {
|
|
30
|
+
throw new InvalidArgumentError(`Invalid used range address '${address}', Must match pattern '${pattern}'.`);
|
|
31
|
+
}
|
|
32
|
+
let { startColumn, startRow, endColumn, endRow } = match.groups;
|
|
33
|
+
const { startColumn: usedStartColumn, endColumn: usedEndColumn, startRow: usedStartRow, endRow: usedEndRow } = decomposeAddress(usedRange);
|
|
34
|
+
if (!startColumn)
|
|
35
|
+
startColumn = usedStartColumn;
|
|
36
|
+
if (!endColumn)
|
|
37
|
+
endColumn = usedEndColumn;
|
|
38
|
+
if (!startRow)
|
|
39
|
+
startRow = usedStartRow;
|
|
40
|
+
if (!endRow)
|
|
41
|
+
endRow = usedEndRow;
|
|
42
|
+
const resolved = composeAddress({
|
|
43
|
+
startColumn: startColumn,
|
|
44
|
+
endColumn: endColumn,
|
|
45
|
+
startRow: startRow,
|
|
46
|
+
endRow: endRow,
|
|
47
|
+
});
|
|
48
|
+
const decomposed = decomposeAddress(resolved);
|
|
49
|
+
const resStartCol = columnAddressToOffset(decomposed.startColumn);
|
|
50
|
+
const resEndCol = columnAddressToOffset(decomposed.endColumn);
|
|
51
|
+
const usedStartCol = columnAddressToOffset(usedStartColumn);
|
|
52
|
+
const usedEndCol = columnAddressToOffset(usedEndColumn);
|
|
53
|
+
const resStartRow = rowAddressToOffset(decomposed.startRow);
|
|
54
|
+
const resEndRow = rowAddressToOffset(decomposed.endRow);
|
|
55
|
+
const usedStartRowNum = rowAddressToOffset(usedStartRow);
|
|
56
|
+
const usedEndRowNum = rowAddressToOffset(usedEndRow);
|
|
57
|
+
const colOverlap = resStartCol <= usedEndCol && resEndCol >= usedStartCol;
|
|
58
|
+
const rowOverlap = resStartRow <= usedEndRowNum && resEndRow >= usedStartRowNum;
|
|
59
|
+
if (!colOverlap || !rowOverlap) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return resolved;
|
|
63
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iterateDriveItems.d.ts","sourceRoot":"","sources":["../../../src/tasks/iterateDriveItems.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAKxE;;;;;;GAMG;AACH,wBAA+B,iBAAiB,CAAC,SAAS,EAAE,QAAQ,GAAG,YAAY,EAAE,WAAW,SAAO,GAAG,cAAc,CAAC,SAAS,GAAG,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"iterateDriveItems.d.ts","sourceRoot":"","sources":["../../../src/tasks/iterateDriveItems.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAKxE;;;;;;GAMG;AACH,wBAA+B,iBAAiB,CAAC,SAAS,EAAE,QAAQ,GAAG,YAAY,EAAE,WAAW,SAAO,GAAG,cAAc,CAAC,SAAS,GAAG,YAAY,CAAC,CAyBjJ"}
|