@typespec/ts-http-runtime 1.0.0-alpha.20240110.1 → 1.0.0-alpha.20240119.1

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/index.js CHANGED
@@ -4,11 +4,11 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var os = require('os');
6
6
  var util = require('util');
7
- var httpsProxyAgent = require('https-proxy-agent');
8
- var httpProxyAgent = require('http-proxy-agent');
9
7
  var tslib = require('tslib');
10
8
  var stream = require('stream');
11
9
  var crypto = require('crypto');
10
+ var httpsProxyAgent = require('https-proxy-agent');
11
+ var httpProxyAgent = require('http-proxy-agent');
12
12
  var http = require('http');
13
13
  var https = require('https');
14
14
  var zlib = require('zlib');
@@ -393,7 +393,6 @@ function extend(namespace) {
393
393
  newDebugger.log = this.log;
394
394
  return newDebugger;
395
395
  }
396
- var debug = debugObj;
397
396
 
398
397
  // Copyright (c) Microsoft Corporation.
399
398
  // Licensed under the MIT license.
@@ -406,9 +405,9 @@ let typeSpecRuntimeLogLevel;
406
405
  * By default, logs are sent to stderr.
407
406
  * Override the `log` method to redirect logs to another location.
408
407
  */
409
- const TypeSpecRuntimeLogger = debug("typeSpecRuntime");
408
+ const TypeSpecRuntimeLogger = debugObj("typeSpecRuntime");
410
409
  TypeSpecRuntimeLogger.log = (...args) => {
411
- debug.log(...args);
410
+ debugObj.log(...args);
412
411
  };
413
412
  const TYPESPEC_RUNTIME_LOG_LEVELS = ["verbose", "info", "warning", "error"];
414
413
  if (logLevelFromEnv) {
@@ -440,7 +439,7 @@ function setLogLevel(level) {
440
439
  enabledNamespaces.push(logger.namespace);
441
440
  }
442
441
  }
443
- debug.enable(enabledNamespaces.join(","));
442
+ debugObj.enable(enabledNamespaces.join(","));
444
443
  }
445
444
  const levelMap = {
446
445
  verbose: 400,
@@ -474,8 +473,8 @@ function createLogger(parent, level) {
474
473
  });
475
474
  patchLogMethod(parent, logger);
476
475
  if (shouldEnable(logger)) {
477
- const enabledNamespaces = debug.disable();
478
- debug.enable(enabledNamespaces + "," + logger.namespace);
476
+ const enabledNamespaces = debugObj.disable();
477
+ debugObj.enable(enabledNamespaces + "," + logger.namespace);
479
478
  }
480
479
  registeredLoggers.add(logger);
481
480
  return logger;
@@ -804,282 +803,592 @@ function userAgentPolicy(options = {}) {
804
803
  // Copyright (c) Microsoft Corporation.
805
804
  // Licensed under the MIT license.
806
805
  /**
807
- * The programmatic identifier of the decompressResponsePolicy.
806
+ * The helper that transforms bytes with specific character encoding into string
807
+ * @param bytes - the uint8array bytes
808
+ * @param format - the format we use to encode the byte
809
+ * @returns a string of the encoded string
808
810
  */
809
- const decompressResponsePolicyName = "decompressResponsePolicy";
811
+ function uint8ArrayToString(bytes, format) {
812
+ return Buffer.from(bytes).toString(format);
813
+ }
810
814
  /**
811
- * A policy to enable response decompression according to Accept-Encoding header
812
- * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
815
+ * The helper that transforms string to specific character encoded bytes array.
816
+ * @param value - the string to be converted
817
+ * @param format - the format we use to decode the value
818
+ * @returns a uint8array
813
819
  */
814
- function decompressResponsePolicy() {
815
- return {
816
- name: decompressResponsePolicyName,
817
- async sendRequest(request, next) {
818
- // HEAD requests have no body
819
- if (request.method !== "HEAD") {
820
- request.headers.set("Accept-Encoding", "gzip,deflate");
821
- }
822
- return next(request);
823
- },
824
- };
820
+ function stringToUint8Array(value, format) {
821
+ return Buffer.from(value, format);
825
822
  }
826
823
 
827
824
  // Copyright (c) Microsoft Corporation.
828
825
  // Licensed under the MIT license.
829
826
  /**
830
- * Returns a random integer value between a lower and upper bound,
831
- * inclusive of both bounds.
832
- * Note that this uses Math.random and isn't secure. If you need to use
833
- * this for any kind of security purpose, find a better source of random.
834
- * @param min - The smallest integer value allowed.
835
- * @param max - The largest integer value allowed.
827
+ * Helper TypeGuard that checks if something is defined or not.
828
+ * @param thing - Anything
836
829
  */
837
- function getRandomIntegerInclusive(min, max) {
838
- // Make sure inputs are integers.
839
- min = Math.ceil(min);
840
- max = Math.floor(max);
841
- // Pick a random offset from zero to the size of the range.
842
- // Since Math.random() can never return 1, we have to make the range one larger
843
- // in order to be inclusive of the maximum value after we take the floor.
844
- const offset = Math.floor(Math.random() * (max - min + 1));
845
- return offset + min;
830
+ function isDefined(thing) {
831
+ return typeof thing !== "undefined" && thing !== null;
846
832
  }
847
-
848
- // Copyright (c) Microsoft Corporation.
849
- // Licensed under the MIT license.
850
833
  /**
851
- * This error is thrown when an asynchronous operation has been aborted.
852
- * Check for this error by testing the `name` that the name property of the
853
- * error matches `"AbortError"`.
854
- *
855
- * @example
856
- * ```ts
857
- * const controller = new AbortController();
858
- * controller.abort();
859
- * try {
860
- * doAsyncWork(controller.signal)
861
- * } catch (e) {
862
- * if (e.name === 'AbortError') {
863
- * // handle abort error here.
864
- * }
865
- * }
866
- * ```
834
+ * Helper TypeGuard that checks if the input is an object with the specified properties.
835
+ * @param thing - Anything.
836
+ * @param properties - The name of the properties that should appear in the object.
867
837
  */
868
- class AbortError extends Error {
869
- constructor(message) {
870
- super(message);
871
- this.name = "AbortError";
838
+ function isObjectWithProperties(thing, properties) {
839
+ if (!isDefined(thing) || typeof thing !== "object") {
840
+ return false;
872
841
  }
842
+ for (const property of properties) {
843
+ if (!objectHasProperty(thing, property)) {
844
+ return false;
845
+ }
846
+ }
847
+ return true;
848
+ }
849
+ /**
850
+ * Helper TypeGuard that checks if the input is an object with the specified property.
851
+ * @param thing - Any object.
852
+ * @param property - The name of the property that should appear in the object.
853
+ */
854
+ function objectHasProperty(thing, property) {
855
+ return (isDefined(thing) && typeof thing === "object" && property in thing);
856
+ }
857
+ function isNodeReadableStream(x) {
858
+ return Boolean(x && typeof x["pipe"] === "function");
859
+ }
860
+ function isWebReadableStream(x) {
861
+ return Boolean(x &&
862
+ typeof x.getReader === "function" &&
863
+ typeof x.tee === "function");
864
+ }
865
+ function isReadableStream$1(x) {
866
+ return isNodeReadableStream(x) || isWebReadableStream(x);
867
+ }
868
+ function isBlob(x) {
869
+ return typeof x.stream === "function";
873
870
  }
874
871
 
875
872
  // Copyright (c) Microsoft Corporation.
876
873
  // Licensed under the MIT license.
877
- const StandardAbortMessage$1 = "The operation was aborted.";
878
- /**
879
- * A wrapper for setTimeout that resolves a promise after delayInMs milliseconds.
880
- * @param delayInMs - The number of milliseconds to be delayed.
881
- * @param value - The value to be resolved with after a timeout of t milliseconds.
882
- * @param options - The options for delay - currently abort options
883
- * - abortSignal - The abortSignal associated with containing operation.
884
- * - abortErrorMsg - The abort error message associated with containing operation.
885
- * @returns Resolved promise
886
- */
887
- function delay$1(delayInMs, value, options) {
888
- return new Promise((resolve, reject) => {
889
- let timer = undefined;
890
- let onAborted = undefined;
891
- const rejectOnAbort = () => {
892
- return reject(new AbortError((options === null || options === void 0 ? void 0 : options.abortErrorMsg) ? options === null || options === void 0 ? void 0 : options.abortErrorMsg : StandardAbortMessage$1));
893
- };
894
- const removeListeners = () => {
895
- if ((options === null || options === void 0 ? void 0 : options.abortSignal) && onAborted) {
896
- options.abortSignal.removeEventListener("abort", onAborted);
897
- }
898
- };
899
- onAborted = () => {
900
- if (timer) {
901
- clearTimeout(timer);
874
+ function streamAsyncIterator() {
875
+ return tslib.__asyncGenerator(this, arguments, function* streamAsyncIterator_1() {
876
+ const reader = this.getReader();
877
+ try {
878
+ while (true) {
879
+ const { done, value } = yield tslib.__await(reader.read());
880
+ if (done) {
881
+ return yield tslib.__await(void 0);
882
+ }
883
+ yield yield tslib.__await(value);
902
884
  }
903
- removeListeners();
904
- return rejectOnAbort();
905
- };
906
- if ((options === null || options === void 0 ? void 0 : options.abortSignal) && options.abortSignal.aborted) {
907
- return rejectOnAbort();
908
885
  }
909
- timer = setTimeout(() => {
910
- removeListeners();
911
- resolve(value);
912
- }, delayInMs);
913
- if (options === null || options === void 0 ? void 0 : options.abortSignal) {
914
- options.abortSignal.addEventListener("abort", onAborted);
886
+ finally {
887
+ reader.releaseLock();
915
888
  }
916
889
  });
917
890
  }
918
- /**
919
- * @internal
920
- * @returns the parsed value or undefined if the parsed value is invalid.
921
- */
922
- function parseHeaderValueAsNumber(response, headerName) {
923
- const value = response.headers.get(headerName);
924
- if (!value)
925
- return;
926
- const valueAsNum = Number(value);
927
- if (Number.isNaN(valueAsNum))
928
- return;
929
- return valueAsNum;
891
+ function makeAsyncIterable(webStream) {
892
+ if (!webStream[Symbol.asyncIterator]) {
893
+ webStream[Symbol.asyncIterator] = streamAsyncIterator.bind(webStream);
894
+ }
895
+ if (!webStream.values) {
896
+ webStream.values = streamAsyncIterator.bind(webStream);
897
+ }
898
+ }
899
+ function nodeStreamFromWebStream(webStream) {
900
+ makeAsyncIterable(webStream);
901
+ return stream.Readable.fromWeb(webStream);
902
+ }
903
+ function toWebStream(stream$1) {
904
+ return isWebReadableStream(stream$1)
905
+ ? stream$1
906
+ : stream.Readable.toWeb(stream.Readable.from(stream$1));
907
+ }
908
+ function toStream(source) {
909
+ if (source instanceof Uint8Array) {
910
+ return stream.Readable.from(Buffer.from(source));
911
+ }
912
+ else if (isBlob(source)) {
913
+ return nodeStreamFromWebStream(source.stream());
914
+ }
915
+ else if (isNodeReadableStream(source)) {
916
+ return source;
917
+ }
918
+ else {
919
+ return nodeStreamFromWebStream(source);
920
+ }
921
+ }
922
+ function concatenateStreams(sources) {
923
+ if (sources.some(isWebReadableStream)) {
924
+ throw new Error("Was not expecting a Web stream here");
925
+ }
926
+ return stream.Readable.from((function () {
927
+ return tslib.__asyncGenerator(this, arguments, function* () {
928
+ var _a, e_1, _b, _c;
929
+ for (const stream of sources) {
930
+ try {
931
+ for (var _d = true, stream_1 = (e_1 = void 0, tslib.__asyncValues(stream)), stream_1_1; stream_1_1 = yield tslib.__await(stream_1.next()), _a = stream_1_1.done, !_a; _d = true) {
932
+ _c = stream_1_1.value;
933
+ _d = false;
934
+ const chunk = _c;
935
+ yield yield tslib.__await(chunk);
936
+ }
937
+ }
938
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
939
+ finally {
940
+ try {
941
+ if (!_d && !_a && (_b = stream_1.return)) yield tslib.__await(_b.call(stream_1));
942
+ }
943
+ finally { if (e_1) throw e_1.error; }
944
+ }
945
+ }
946
+ });
947
+ })());
930
948
  }
931
949
 
932
950
  // Copyright (c) Microsoft Corporation.
933
951
  // Licensed under the MIT license.
934
- /**
935
- * The header that comes back from services representing
936
- * the amount of time (minimum) to wait to retry (in seconds or timestamp after which we can retry).
937
- */
938
- const RetryAfterHeader = "Retry-After";
939
- /**
940
- * The headers that come back from services representing
941
- * the amount of time (minimum) to wait to retry.
942
- *
943
- * "retry-after-ms", "x-ms-retry-after-ms" : milliseconds
944
- * "Retry-After" : seconds or timestamp
952
+ /*
953
+ * NOTE: When moving this file, please update "react-native" section in package.json.
945
954
  */
946
- const AllRetryAfterHeaders = ["retry-after-ms", "x-ms-retry-after-ms", RetryAfterHeader];
947
955
  /**
948
- * A response is a throttling retry response if it has a throttling status code (429 or 503),
949
- * as long as one of the [ "Retry-After" or "retry-after-ms" or "x-ms-retry-after-ms" ] headers has a valid value.
950
- *
951
- * Returns the `retryAfterInMs` value if the response is a throttling retry response.
952
- * If not throttling retry response, returns `undefined`.
956
+ * Generated Universally Unique Identifier
953
957
  *
954
- * @internal
958
+ * @returns RFC4122 v4 UUID.
955
959
  */
956
- function getRetryAfterInMs(response) {
957
- if (!(response && [429, 503].includes(response.status)))
958
- return undefined;
959
- try {
960
- // Headers: "retry-after-ms", "x-ms-retry-after-ms", "Retry-After"
961
- for (const header of AllRetryAfterHeaders) {
962
- const retryAfterValue = parseHeaderValueAsNumber(response, header);
963
- if (retryAfterValue === 0 || retryAfterValue) {
964
- // "Retry-After" header ==> seconds
965
- // "retry-after-ms", "x-ms-retry-after-ms" headers ==> milli-seconds
966
- const multiplyingFactor = header === RetryAfterHeader ? 1000 : 1;
967
- return retryAfterValue * multiplyingFactor; // in milli-seconds
968
- }
960
+ function generateUUID() {
961
+ let uuid = "";
962
+ for (let i = 0; i < 32; i++) {
963
+ // Generate a random number between 0 and 15
964
+ const randomNumber = Math.floor(Math.random() * 16);
965
+ // Set the UUID version to 4 in the 13th position
966
+ if (i === 12) {
967
+ uuid += "4";
968
+ }
969
+ else if (i === 16) {
970
+ // Set the UUID variant to "10" in the 17th position
971
+ uuid += (randomNumber & 0x3) | 0x8;
972
+ }
973
+ else {
974
+ // Add a random hexadecimal digit to the UUID string
975
+ uuid += randomNumber.toString(16);
976
+ }
977
+ // Add hyphens to the UUID string at the appropriate positions
978
+ if (i === 7 || i === 11 || i === 15 || i === 19) {
979
+ uuid += "-";
969
980
  }
970
- // RetryAfterHeader ("Retry-After") has a special case where it might be formatted as a date instead of a number of seconds
971
- const retryAfterHeader = response.headers.get(RetryAfterHeader);
972
- if (!retryAfterHeader)
973
- return;
974
- const date = Date.parse(retryAfterHeader);
975
- const diff = date - Date.now();
976
- // negative diff would mean a date in the past, so retry asap with 0 milliseconds
977
- return Number.isFinite(diff) ? Math.max(0, diff) : undefined;
978
981
  }
979
- catch (e) {
982
+ return uuid;
983
+ }
984
+
985
+ // Copyright (c) Microsoft Corporation.
986
+ // Licensed under the MIT license.
987
+ var _a$1;
988
+ // NOTE: This is a workaround until we can use `globalThis.crypto.randomUUID` in Node.js 19+.
989
+ let uuidFunction = typeof ((_a$1 = globalThis === null || globalThis === void 0 ? void 0 : globalThis.crypto) === null || _a$1 === void 0 ? void 0 : _a$1.randomUUID) === "function"
990
+ ? globalThis.crypto.randomUUID.bind(globalThis.crypto)
991
+ : crypto.randomUUID;
992
+ // Not defined in earlier versions of Node.js 14
993
+ if (!uuidFunction) {
994
+ uuidFunction = generateUUID;
995
+ }
996
+ /**
997
+ * Generated Universally Unique Identifier
998
+ *
999
+ * @returns RFC4122 v4 UUID.
1000
+ */
1001
+ function randomUUID() {
1002
+ return uuidFunction();
1003
+ }
1004
+
1005
+ // Copyright (c) Microsoft Corporation.
1006
+ // Licensed under the MIT license.
1007
+ function generateBoundary() {
1008
+ return `----AzSDKFormBoundary${randomUUID()}`;
1009
+ }
1010
+ function encodeHeaders(headers) {
1011
+ let result = "";
1012
+ for (const [key, value] of headers) {
1013
+ result += `${key}: ${value}\r\n`;
1014
+ }
1015
+ return result;
1016
+ }
1017
+ function getLength(source) {
1018
+ if (source instanceof Uint8Array) {
1019
+ return source.byteLength;
1020
+ }
1021
+ else if (isBlob(source)) {
1022
+ // if was created using createFile then -1 means we have an unknown size
1023
+ return source.size === -1 ? undefined : source.size;
1024
+ }
1025
+ else {
980
1026
  return undefined;
981
1027
  }
982
1028
  }
1029
+ function getTotalLength(sources) {
1030
+ let total = 0;
1031
+ for (const source of sources) {
1032
+ const partLength = getLength(source);
1033
+ if (partLength === undefined) {
1034
+ return undefined;
1035
+ }
1036
+ else {
1037
+ total += partLength;
1038
+ }
1039
+ }
1040
+ return total;
1041
+ }
1042
+ function buildRequestBody(request, parts, boundary) {
1043
+ const sources = [
1044
+ stringToUint8Array(`--${boundary}`, "utf-8"),
1045
+ ...parts.flatMap((part) => [
1046
+ stringToUint8Array("\r\n", "utf-8"),
1047
+ stringToUint8Array(encodeHeaders(part.headers), "utf-8"),
1048
+ stringToUint8Array("\r\n", "utf-8"),
1049
+ part.body,
1050
+ stringToUint8Array(`\r\n--${boundary}`, "utf-8"),
1051
+ ]),
1052
+ stringToUint8Array("--\r\n\r\n", "utf-8"),
1053
+ ];
1054
+ const contentLength = getTotalLength(sources);
1055
+ if (contentLength) {
1056
+ request.headers.set("Content-Length", contentLength);
1057
+ }
1058
+ request.body = (() => concatenateStreams(sources.map((source) => (typeof source === "function" ? source() : source)).map(toStream)));
1059
+ }
983
1060
  /**
984
- * A response is a retry response if it has a throttling status code (429 or 503),
985
- * as long as one of the [ "Retry-After" or "retry-after-ms" or "x-ms-retry-after-ms" ] headers has a valid value.
1061
+ * Name of multipart policy
986
1062
  */
987
- function isThrottlingRetryResponse(response) {
988
- return Number.isFinite(getRetryAfterInMs(response));
1063
+ const multipartPolicyName = "multipartPolicy";
1064
+ const maxBoundaryLength = 70;
1065
+ const validBoundaryCharacters = new Set(`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'()+,-./:=?`);
1066
+ function assertValidBoundary(boundary) {
1067
+ if (boundary.length > maxBoundaryLength) {
1068
+ throw new Error(`Multipart boundary "${boundary}" exceeds maximum length of 70 characters`);
1069
+ }
1070
+ if (Array.from(boundary).some((x) => !validBoundaryCharacters.has(x))) {
1071
+ throw new Error(`Multipart boundary "${boundary}" contains invalid characters`);
1072
+ }
989
1073
  }
990
- function throttlingRetryStrategy() {
1074
+ /**
1075
+ * Pipeline policy for multipart requests
1076
+ */
1077
+ function multipartPolicy() {
991
1078
  return {
992
- name: "throttlingRetryStrategy",
993
- retry({ response }) {
994
- const retryAfterInMs = getRetryAfterInMs(response);
995
- if (!Number.isFinite(retryAfterInMs)) {
996
- return { skipStrategy: true };
1079
+ name: multipartPolicyName,
1080
+ sendRequest(request, next) {
1081
+ var _a;
1082
+ if (!request.multipartBody) {
1083
+ return next(request);
997
1084
  }
998
- return {
999
- retryAfterInMs,
1000
- };
1085
+ if (request.body) {
1086
+ throw new Error("multipartBody and regular body cannot be set at the same time");
1087
+ }
1088
+ let boundary = request.multipartBody.boundary;
1089
+ const contentTypeHeader = (_a = request.headers.get("Content-Type")) !== null && _a !== void 0 ? _a : "multipart/mixed";
1090
+ const parsedHeader = contentTypeHeader.match(/^(multipart\/[^ ;]+)(?:; *boundary=(.+))?$/);
1091
+ if (!parsedHeader) {
1092
+ throw new Error(`Got multipart request body, but content-type header was not multipart: ${contentTypeHeader}`);
1093
+ }
1094
+ const [, contentType, parsedBoundary] = parsedHeader;
1095
+ if (parsedBoundary && boundary && parsedBoundary !== boundary) {
1096
+ throw new Error(`Multipart boundary was specified as ${parsedBoundary} in the header, but got ${boundary} in the request body`);
1097
+ }
1098
+ boundary !== null && boundary !== void 0 ? boundary : (boundary = parsedBoundary);
1099
+ if (boundary) {
1100
+ assertValidBoundary(boundary);
1101
+ }
1102
+ else {
1103
+ boundary = generateBoundary();
1104
+ }
1105
+ request.headers.set("Content-Type", `${contentType}; boundary=${boundary}`);
1106
+ buildRequestBody(request, request.multipartBody.parts, boundary);
1107
+ request.multipartBody = undefined;
1108
+ return next(request);
1001
1109
  },
1002
1110
  };
1003
1111
  }
1004
1112
 
1005
1113
  // Copyright (c) Microsoft Corporation.
1006
1114
  // Licensed under the MIT license.
1007
- // intervals are in milliseconds
1008
- const DEFAULT_CLIENT_RETRY_INTERVAL = 1000;
1009
- const DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 64;
1010
1115
  /**
1011
- * A retry strategy that retries with an exponentially increasing delay in these two cases:
1012
- * - When there are errors in the underlying transport layer (e.g. DNS lookup failures).
1013
- * - Or otherwise if the outgoing request fails (408, greater or equal than 500, except for 501 and 505).
1116
+ * The programmatic identifier of the decompressResponsePolicy.
1014
1117
  */
1015
- function exponentialRetryStrategy(options = {}) {
1016
- var _a, _b;
1017
- const retryInterval = (_a = options.retryDelayInMs) !== null && _a !== void 0 ? _a : DEFAULT_CLIENT_RETRY_INTERVAL;
1018
- const maxRetryInterval = (_b = options.maxRetryDelayInMs) !== null && _b !== void 0 ? _b : DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
1019
- let retryAfterInMs = retryInterval;
1118
+ const decompressResponsePolicyName = "decompressResponsePolicy";
1119
+ /**
1120
+ * A policy to enable response decompression according to Accept-Encoding header
1121
+ * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
1122
+ */
1123
+ function decompressResponsePolicy() {
1020
1124
  return {
1021
- name: "exponentialRetryStrategy",
1022
- retry({ retryCount, response, responseError }) {
1023
- const matchedSystemError = isSystemError(responseError);
1024
- const ignoreSystemErrors = matchedSystemError && options.ignoreSystemErrors;
1025
- const isExponential = isExponentialRetryResponse(response);
1026
- const ignoreExponentialResponse = isExponential && options.ignoreHttpStatusCodes;
1027
- const unknownResponse = response && (isThrottlingRetryResponse(response) || !isExponential);
1028
- if (unknownResponse || ignoreExponentialResponse || ignoreSystemErrors) {
1029
- return { skipStrategy: true };
1030
- }
1031
- if (responseError && !matchedSystemError && !isExponential) {
1032
- return { errorToThrow: responseError };
1125
+ name: decompressResponsePolicyName,
1126
+ async sendRequest(request, next) {
1127
+ // HEAD requests have no body
1128
+ if (request.method !== "HEAD") {
1129
+ request.headers.set("Accept-Encoding", "gzip,deflate");
1033
1130
  }
1034
- // Exponentially increase the delay each time
1035
- const exponentialDelay = retryAfterInMs * Math.pow(2, retryCount);
1036
- // Don't let the delay exceed the maximum
1037
- const clampedExponentialDelay = Math.min(maxRetryInterval, exponentialDelay);
1038
- // Allow the final value to have some "jitter" (within 50% of the delay size) so
1039
- // that retries across multiple clients don't occur simultaneously.
1040
- retryAfterInMs =
1041
- clampedExponentialDelay / 2 + getRandomIntegerInclusive(0, clampedExponentialDelay / 2);
1042
- return { retryAfterInMs };
1131
+ return next(request);
1043
1132
  },
1044
1133
  };
1045
1134
  }
1135
+
1136
+ // Copyright (c) Microsoft Corporation.
1137
+ // Licensed under the MIT license.
1046
1138
  /**
1047
- * A response is a retry response if it has status codes:
1048
- * - 408, or
1049
- * - Greater or equal than 500, except for 501 and 505.
1050
- */
1051
- function isExponentialRetryResponse(response) {
1052
- return Boolean(response &&
1053
- response.status !== undefined &&
1054
- (response.status >= 500 || response.status === 408) &&
1055
- response.status !== 501 &&
1056
- response.status !== 505);
1057
- }
1058
- /**
1059
- * Determines whether an error from a pipeline response was triggered in the network layer.
1139
+ * Returns a random integer value between a lower and upper bound,
1140
+ * inclusive of both bounds.
1141
+ * Note that this uses Math.random and isn't secure. If you need to use
1142
+ * this for any kind of security purpose, find a better source of random.
1143
+ * @param min - The smallest integer value allowed.
1144
+ * @param max - The largest integer value allowed.
1060
1145
  */
1061
- function isSystemError(err) {
1062
- if (!err) {
1063
- return false;
1064
- }
1065
- return (err.code === "ETIMEDOUT" ||
1066
- err.code === "ESOCKETTIMEDOUT" ||
1067
- err.code === "ECONNREFUSED" ||
1068
- err.code === "ECONNRESET" ||
1069
- err.code === "ENOENT" ||
1070
- err.code === "ENOTFOUND");
1146
+ function getRandomIntegerInclusive(min, max) {
1147
+ // Make sure inputs are integers.
1148
+ min = Math.ceil(min);
1149
+ max = Math.floor(max);
1150
+ // Pick a random offset from zero to the size of the range.
1151
+ // Since Math.random() can never return 1, we have to make the range one larger
1152
+ // in order to be inclusive of the maximum value after we take the floor.
1153
+ const offset = Math.floor(Math.random() * (max - min + 1));
1154
+ return offset + min;
1071
1155
  }
1072
1156
 
1073
1157
  // Copyright (c) Microsoft Corporation.
1074
1158
  // Licensed under the MIT license.
1075
- const retryPolicyLogger = createClientLogger("core-rest-pipeline retryPolicy");
1076
- /**
1077
- * The programmatic identifier of the retryPolicy.
1078
- */
1079
- const retryPolicyName = "retryPolicy";
1080
1159
  /**
1081
- * retryPolicy is a generic policy to enable retrying requests when certain conditions are met
1082
- */
1160
+ * This error is thrown when an asynchronous operation has been aborted.
1161
+ * Check for this error by testing the `name` that the name property of the
1162
+ * error matches `"AbortError"`.
1163
+ *
1164
+ * @example
1165
+ * ```ts
1166
+ * const controller = new AbortController();
1167
+ * controller.abort();
1168
+ * try {
1169
+ * doAsyncWork(controller.signal)
1170
+ * } catch (e) {
1171
+ * if (e.name === 'AbortError') {
1172
+ * // handle abort error here.
1173
+ * }
1174
+ * }
1175
+ * ```
1176
+ */
1177
+ class AbortError extends Error {
1178
+ constructor(message) {
1179
+ super(message);
1180
+ this.name = "AbortError";
1181
+ }
1182
+ }
1183
+
1184
+ // Copyright (c) Microsoft Corporation.
1185
+ // Licensed under the MIT license.
1186
+ const StandardAbortMessage$1 = "The operation was aborted.";
1187
+ /**
1188
+ * A wrapper for setTimeout that resolves a promise after delayInMs milliseconds.
1189
+ * @param delayInMs - The number of milliseconds to be delayed.
1190
+ * @param value - The value to be resolved with after a timeout of t milliseconds.
1191
+ * @param options - The options for delay - currently abort options
1192
+ * - abortSignal - The abortSignal associated with containing operation.
1193
+ * - abortErrorMsg - The abort error message associated with containing operation.
1194
+ * @returns Resolved promise
1195
+ */
1196
+ function delay$1(delayInMs, value, options) {
1197
+ return new Promise((resolve, reject) => {
1198
+ let timer = undefined;
1199
+ let onAborted = undefined;
1200
+ const rejectOnAbort = () => {
1201
+ return reject(new AbortError((options === null || options === void 0 ? void 0 : options.abortErrorMsg) ? options === null || options === void 0 ? void 0 : options.abortErrorMsg : StandardAbortMessage$1));
1202
+ };
1203
+ const removeListeners = () => {
1204
+ if ((options === null || options === void 0 ? void 0 : options.abortSignal) && onAborted) {
1205
+ options.abortSignal.removeEventListener("abort", onAborted);
1206
+ }
1207
+ };
1208
+ onAborted = () => {
1209
+ if (timer) {
1210
+ clearTimeout(timer);
1211
+ }
1212
+ removeListeners();
1213
+ return rejectOnAbort();
1214
+ };
1215
+ if ((options === null || options === void 0 ? void 0 : options.abortSignal) && options.abortSignal.aborted) {
1216
+ return rejectOnAbort();
1217
+ }
1218
+ timer = setTimeout(() => {
1219
+ removeListeners();
1220
+ resolve(value);
1221
+ }, delayInMs);
1222
+ if (options === null || options === void 0 ? void 0 : options.abortSignal) {
1223
+ options.abortSignal.addEventListener("abort", onAborted);
1224
+ }
1225
+ });
1226
+ }
1227
+ /**
1228
+ * @internal
1229
+ * @returns the parsed value or undefined if the parsed value is invalid.
1230
+ */
1231
+ function parseHeaderValueAsNumber(response, headerName) {
1232
+ const value = response.headers.get(headerName);
1233
+ if (!value)
1234
+ return;
1235
+ const valueAsNum = Number(value);
1236
+ if (Number.isNaN(valueAsNum))
1237
+ return;
1238
+ return valueAsNum;
1239
+ }
1240
+
1241
+ // Copyright (c) Microsoft Corporation.
1242
+ // Licensed under the MIT license.
1243
+ /**
1244
+ * The header that comes back from services representing
1245
+ * the amount of time (minimum) to wait to retry (in seconds or timestamp after which we can retry).
1246
+ */
1247
+ const RetryAfterHeader = "Retry-After";
1248
+ /**
1249
+ * The headers that come back from services representing
1250
+ * the amount of time (minimum) to wait to retry.
1251
+ *
1252
+ * "retry-after-ms", "x-ms-retry-after-ms" : milliseconds
1253
+ * "Retry-After" : seconds or timestamp
1254
+ */
1255
+ const AllRetryAfterHeaders = ["retry-after-ms", "x-ms-retry-after-ms", RetryAfterHeader];
1256
+ /**
1257
+ * A response is a throttling retry response if it has a throttling status code (429 or 503),
1258
+ * as long as one of the [ "Retry-After" or "retry-after-ms" or "x-ms-retry-after-ms" ] headers has a valid value.
1259
+ *
1260
+ * Returns the `retryAfterInMs` value if the response is a throttling retry response.
1261
+ * If not throttling retry response, returns `undefined`.
1262
+ *
1263
+ * @internal
1264
+ */
1265
+ function getRetryAfterInMs(response) {
1266
+ if (!(response && [429, 503].includes(response.status)))
1267
+ return undefined;
1268
+ try {
1269
+ // Headers: "retry-after-ms", "x-ms-retry-after-ms", "Retry-After"
1270
+ for (const header of AllRetryAfterHeaders) {
1271
+ const retryAfterValue = parseHeaderValueAsNumber(response, header);
1272
+ if (retryAfterValue === 0 || retryAfterValue) {
1273
+ // "Retry-After" header ==> seconds
1274
+ // "retry-after-ms", "x-ms-retry-after-ms" headers ==> milli-seconds
1275
+ const multiplyingFactor = header === RetryAfterHeader ? 1000 : 1;
1276
+ return retryAfterValue * multiplyingFactor; // in milli-seconds
1277
+ }
1278
+ }
1279
+ // RetryAfterHeader ("Retry-After") has a special case where it might be formatted as a date instead of a number of seconds
1280
+ const retryAfterHeader = response.headers.get(RetryAfterHeader);
1281
+ if (!retryAfterHeader)
1282
+ return;
1283
+ const date = Date.parse(retryAfterHeader);
1284
+ const diff = date - Date.now();
1285
+ // negative diff would mean a date in the past, so retry asap with 0 milliseconds
1286
+ return Number.isFinite(diff) ? Math.max(0, diff) : undefined;
1287
+ }
1288
+ catch (e) {
1289
+ return undefined;
1290
+ }
1291
+ }
1292
+ /**
1293
+ * A response is a retry response if it has a throttling status code (429 or 503),
1294
+ * as long as one of the [ "Retry-After" or "retry-after-ms" or "x-ms-retry-after-ms" ] headers has a valid value.
1295
+ */
1296
+ function isThrottlingRetryResponse(response) {
1297
+ return Number.isFinite(getRetryAfterInMs(response));
1298
+ }
1299
+ function throttlingRetryStrategy() {
1300
+ return {
1301
+ name: "throttlingRetryStrategy",
1302
+ retry({ response }) {
1303
+ const retryAfterInMs = getRetryAfterInMs(response);
1304
+ if (!Number.isFinite(retryAfterInMs)) {
1305
+ return { skipStrategy: true };
1306
+ }
1307
+ return {
1308
+ retryAfterInMs,
1309
+ };
1310
+ },
1311
+ };
1312
+ }
1313
+
1314
+ // Copyright (c) Microsoft Corporation.
1315
+ // Licensed under the MIT license.
1316
+ // intervals are in milliseconds
1317
+ const DEFAULT_CLIENT_RETRY_INTERVAL = 1000;
1318
+ const DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 64;
1319
+ /**
1320
+ * A retry strategy that retries with an exponentially increasing delay in these two cases:
1321
+ * - When there are errors in the underlying transport layer (e.g. DNS lookup failures).
1322
+ * - Or otherwise if the outgoing request fails (408, greater or equal than 500, except for 501 and 505).
1323
+ */
1324
+ function exponentialRetryStrategy(options = {}) {
1325
+ var _a, _b;
1326
+ const retryInterval = (_a = options.retryDelayInMs) !== null && _a !== void 0 ? _a : DEFAULT_CLIENT_RETRY_INTERVAL;
1327
+ const maxRetryInterval = (_b = options.maxRetryDelayInMs) !== null && _b !== void 0 ? _b : DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
1328
+ let retryAfterInMs = retryInterval;
1329
+ return {
1330
+ name: "exponentialRetryStrategy",
1331
+ retry({ retryCount, response, responseError }) {
1332
+ const matchedSystemError = isSystemError(responseError);
1333
+ const ignoreSystemErrors = matchedSystemError && options.ignoreSystemErrors;
1334
+ const isExponential = isExponentialRetryResponse(response);
1335
+ const ignoreExponentialResponse = isExponential && options.ignoreHttpStatusCodes;
1336
+ const unknownResponse = response && (isThrottlingRetryResponse(response) || !isExponential);
1337
+ if (unknownResponse || ignoreExponentialResponse || ignoreSystemErrors) {
1338
+ return { skipStrategy: true };
1339
+ }
1340
+ if (responseError && !matchedSystemError && !isExponential) {
1341
+ return { errorToThrow: responseError };
1342
+ }
1343
+ // Exponentially increase the delay each time
1344
+ const exponentialDelay = retryAfterInMs * Math.pow(2, retryCount);
1345
+ // Don't let the delay exceed the maximum
1346
+ const clampedExponentialDelay = Math.min(maxRetryInterval, exponentialDelay);
1347
+ // Allow the final value to have some "jitter" (within 50% of the delay size) so
1348
+ // that retries across multiple clients don't occur simultaneously.
1349
+ retryAfterInMs =
1350
+ clampedExponentialDelay / 2 + getRandomIntegerInclusive(0, clampedExponentialDelay / 2);
1351
+ return { retryAfterInMs };
1352
+ },
1353
+ };
1354
+ }
1355
+ /**
1356
+ * A response is a retry response if it has status codes:
1357
+ * - 408, or
1358
+ * - Greater or equal than 500, except for 501 and 505.
1359
+ */
1360
+ function isExponentialRetryResponse(response) {
1361
+ return Boolean(response &&
1362
+ response.status !== undefined &&
1363
+ (response.status >= 500 || response.status === 408) &&
1364
+ response.status !== 501 &&
1365
+ response.status !== 505);
1366
+ }
1367
+ /**
1368
+ * Determines whether an error from a pipeline response was triggered in the network layer.
1369
+ */
1370
+ function isSystemError(err) {
1371
+ if (!err) {
1372
+ return false;
1373
+ }
1374
+ return (err.code === "ETIMEDOUT" ||
1375
+ err.code === "ESOCKETTIMEDOUT" ||
1376
+ err.code === "ECONNREFUSED" ||
1377
+ err.code === "ECONNRESET" ||
1378
+ err.code === "ENOENT" ||
1379
+ err.code === "ENOTFOUND");
1380
+ }
1381
+
1382
+ // Copyright (c) Microsoft Corporation.
1383
+ // Licensed under the MIT license.
1384
+ const retryPolicyLogger = createClientLogger("core-rest-pipeline retryPolicy");
1385
+ /**
1386
+ * The programmatic identifier of the retryPolicy.
1387
+ */
1388
+ const retryPolicyName = "retryPolicy";
1389
+ /**
1390
+ * retryPolicy is a generic policy to enable retrying requests when certain conditions are met
1391
+ */
1083
1392
  function retryPolicy(strategies, options = { maxRetries: DEFAULT_RETRY_POLICY_COUNT }) {
1084
1393
  const logger = options.logger || retryPolicyLogger;
1085
1394
  return {
@@ -1194,27 +1503,6 @@ function defaultRetryPolicy(options = {}) {
1194
1503
  };
1195
1504
  }
1196
1505
 
1197
- // Copyright (c) Microsoft Corporation.
1198
- // Licensed under the MIT license.
1199
- /**
1200
- * The helper that transforms bytes with specific character encoding into string
1201
- * @param bytes - the uint8array bytes
1202
- * @param format - the format we use to encode the byte
1203
- * @returns a string of the encoded string
1204
- */
1205
- function uint8ArrayToString(bytes, format) {
1206
- return Buffer.from(bytes).toString(format);
1207
- }
1208
- /**
1209
- * The helper that transforms string to specific character encoded bytes array.
1210
- * @param value - the string to be converted
1211
- * @param format - the format we use to decode the value
1212
- * @returns a uint8array
1213
- */
1214
- function stringToUint8Array(value, format) {
1215
- return Buffer.from(value, format);
1216
- }
1217
-
1218
1506
  // Copyright (c) Microsoft Corporation.
1219
1507
  // Licensed under the MIT license.
1220
1508
  function normalizeName(name) {
@@ -1379,13 +1667,13 @@ async function prepareFormData(formData, request) {
1379
1667
  });
1380
1668
  }
1381
1669
  }
1382
- request.multipartBody = { parts };
1383
1670
  }
1671
+ request.multipartBody = { parts };
1384
1672
  }
1385
1673
 
1386
1674
  // Copyright (c) Microsoft Corporation.
1387
1675
  // Licensed under the MIT license.
1388
- var _a$1, _b, _c, _d;
1676
+ var _a, _b, _c, _d;
1389
1677
  /**
1390
1678
  * A constant that indicates whether the environment the code is running is a Web Browser.
1391
1679
  */
@@ -1396,7 +1684,7 @@ const isBrowser = typeof window !== "undefined" && typeof window.document !== "u
1396
1684
  */
1397
1685
  const isWebWorker = typeof self === "object" &&
1398
1686
  typeof (self === null || self === void 0 ? void 0 : self.importScripts) === "function" &&
1399
- (((_a$1 = self.constructor) === null || _a$1 === void 0 ? void 0 : _a$1.name) === "DedicatedWorkerGlobalScope" ||
1687
+ (((_a = self.constructor) === null || _a === void 0 ? void 0 : _a.name) === "DedicatedWorkerGlobalScope" ||
1400
1688
  ((_b = self.constructor) === null || _b === void 0 ? void 0 : _b.name) === "ServiceWorkerGlobalScope" ||
1401
1689
  ((_c = self.constructor) === null || _c === void 0 ? void 0 : _c.name) === "SharedWorkerGlobalScope");
1402
1690
  /**
@@ -2011,295 +2299,6 @@ function tryProcessResponse(span, response) {
2011
2299
  }
2012
2300
  }
2013
2301
 
2014
- // Copyright (c) Microsoft Corporation.
2015
- // Licensed under the MIT license.
2016
- /**
2017
- * Helper TypeGuard that checks if something is defined or not.
2018
- * @param thing - Anything
2019
- */
2020
- function isDefined(thing) {
2021
- return typeof thing !== "undefined" && thing !== null;
2022
- }
2023
- /**
2024
- * Helper TypeGuard that checks if the input is an object with the specified properties.
2025
- * @param thing - Anything.
2026
- * @param properties - The name of the properties that should appear in the object.
2027
- */
2028
- function isObjectWithProperties(thing, properties) {
2029
- if (!isDefined(thing) || typeof thing !== "object") {
2030
- return false;
2031
- }
2032
- for (const property of properties) {
2033
- if (!objectHasProperty(thing, property)) {
2034
- return false;
2035
- }
2036
- }
2037
- return true;
2038
- }
2039
- /**
2040
- * Helper TypeGuard that checks if the input is an object with the specified property.
2041
- * @param thing - Any object.
2042
- * @param property - The name of the property that should appear in the object.
2043
- */
2044
- function objectHasProperty(thing, property) {
2045
- return (isDefined(thing) && typeof thing === "object" && property in thing);
2046
- }
2047
- function isNodeReadableStream(x) {
2048
- return Boolean(x && typeof x["pipe"] === "function");
2049
- }
2050
- function isWebReadableStream(x) {
2051
- return Boolean(x &&
2052
- typeof x.getReader === "function" &&
2053
- typeof x.tee === "function");
2054
- }
2055
- function isReadableStream$1(x) {
2056
- return isNodeReadableStream(x) || isWebReadableStream(x);
2057
- }
2058
- function isBlob(x) {
2059
- return typeof x.stream === "function";
2060
- }
2061
-
2062
- // Copyright (c) Microsoft Corporation.
2063
- // Licensed under the MIT license.
2064
- function streamAsyncIterator() {
2065
- return tslib.__asyncGenerator(this, arguments, function* streamAsyncIterator_1() {
2066
- const reader = this.getReader();
2067
- try {
2068
- while (true) {
2069
- const { done, value } = yield tslib.__await(reader.read());
2070
- if (done) {
2071
- return yield tslib.__await(void 0);
2072
- }
2073
- yield yield tslib.__await(value);
2074
- }
2075
- }
2076
- finally {
2077
- reader.releaseLock();
2078
- }
2079
- });
2080
- }
2081
- function makeAsyncIterable(webStream) {
2082
- if (!webStream[Symbol.asyncIterator]) {
2083
- webStream[Symbol.asyncIterator] = streamAsyncIterator.bind(webStream);
2084
- }
2085
- if (!webStream.values) {
2086
- webStream.values = streamAsyncIterator.bind(webStream);
2087
- }
2088
- }
2089
- function nodeStreamFromWebStream(webStream) {
2090
- makeAsyncIterable(webStream);
2091
- return stream.Readable.fromWeb(webStream);
2092
- }
2093
- function toWebStream(stream$1) {
2094
- return isWebReadableStream(stream$1)
2095
- ? stream$1
2096
- : stream.Readable.toWeb(stream.Readable.from(stream$1));
2097
- }
2098
- function toStream(source) {
2099
- if (source instanceof Uint8Array) {
2100
- return stream.Readable.from(Buffer.from(source));
2101
- }
2102
- else if (isBlob(source)) {
2103
- return nodeStreamFromWebStream(source.stream());
2104
- }
2105
- else if (isNodeReadableStream(source)) {
2106
- return source;
2107
- }
2108
- else {
2109
- return nodeStreamFromWebStream(source);
2110
- }
2111
- }
2112
- function concatenateStreams(sources) {
2113
- if (sources.some(isWebReadableStream)) {
2114
- throw new Error("Was not expecting a Web stream here");
2115
- }
2116
- return stream.Readable.from((function () {
2117
- return tslib.__asyncGenerator(this, arguments, function* () {
2118
- var _a, e_1, _b, _c;
2119
- for (const stream of sources) {
2120
- try {
2121
- for (var _d = true, stream_1 = (e_1 = void 0, tslib.__asyncValues(stream)), stream_1_1; stream_1_1 = yield tslib.__await(stream_1.next()), _a = stream_1_1.done, !_a; _d = true) {
2122
- _c = stream_1_1.value;
2123
- _d = false;
2124
- const chunk = _c;
2125
- yield yield tslib.__await(chunk);
2126
- }
2127
- }
2128
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
2129
- finally {
2130
- try {
2131
- if (!_d && !_a && (_b = stream_1.return)) yield tslib.__await(_b.call(stream_1));
2132
- }
2133
- finally { if (e_1) throw e_1.error; }
2134
- }
2135
- }
2136
- });
2137
- })());
2138
- }
2139
-
2140
- // Copyright (c) Microsoft Corporation.
2141
- // Licensed under the MIT license.
2142
- /*
2143
- * NOTE: When moving this file, please update "react-native" section in package.json.
2144
- */
2145
- /**
2146
- * Generated Universally Unique Identifier
2147
- *
2148
- * @returns RFC4122 v4 UUID.
2149
- */
2150
- function generateUUID() {
2151
- let uuid = "";
2152
- for (let i = 0; i < 32; i++) {
2153
- // Generate a random number between 0 and 15
2154
- const randomNumber = Math.floor(Math.random() * 16);
2155
- // Set the UUID version to 4 in the 13th position
2156
- if (i === 12) {
2157
- uuid += "4";
2158
- }
2159
- else if (i === 16) {
2160
- // Set the UUID variant to "10" in the 17th position
2161
- uuid += (randomNumber & 0x3) | 0x8;
2162
- }
2163
- else {
2164
- // Add a random hexadecimal digit to the UUID string
2165
- uuid += randomNumber.toString(16);
2166
- }
2167
- // Add hyphens to the UUID string at the appropriate positions
2168
- if (i === 7 || i === 11 || i === 15 || i === 19) {
2169
- uuid += "-";
2170
- }
2171
- }
2172
- return uuid;
2173
- }
2174
-
2175
- // Copyright (c) Microsoft Corporation.
2176
- // Licensed under the MIT license.
2177
- var _a;
2178
- // NOTE: This is a workaround until we can use `globalThis.crypto.randomUUID` in Node.js 19+.
2179
- let uuidFunction = typeof ((_a = globalThis === null || globalThis === void 0 ? void 0 : globalThis.crypto) === null || _a === void 0 ? void 0 : _a.randomUUID) === "function"
2180
- ? globalThis.crypto.randomUUID.bind(globalThis.crypto)
2181
- : crypto.randomUUID;
2182
- // Not defined in earlier versions of Node.js 14
2183
- if (!uuidFunction) {
2184
- uuidFunction = generateUUID;
2185
- }
2186
- /**
2187
- * Generated Universally Unique Identifier
2188
- *
2189
- * @returns RFC4122 v4 UUID.
2190
- */
2191
- function randomUUID() {
2192
- return uuidFunction();
2193
- }
2194
-
2195
- // Copyright (c) Microsoft Corporation.
2196
- // Licensed under the MIT license.
2197
- function generateBoundary() {
2198
- return `----AzSDKFormBoundary${randomUUID()}`;
2199
- }
2200
- function encodeHeaders(headers) {
2201
- let result = "";
2202
- for (const [key, value] of headers) {
2203
- result += `${key}: ${value}\r\n`;
2204
- }
2205
- return result;
2206
- }
2207
- function getLength(source) {
2208
- if (source instanceof Uint8Array) {
2209
- return source.byteLength;
2210
- }
2211
- else if (isBlob(source)) {
2212
- // if was created using createFile then -1 means we have an unknown size
2213
- return source.size === -1 ? undefined : source.size;
2214
- }
2215
- else {
2216
- return undefined;
2217
- }
2218
- }
2219
- function getTotalLength(sources) {
2220
- let total = 0;
2221
- for (const source of sources) {
2222
- const partLength = getLength(source);
2223
- if (partLength === undefined) {
2224
- return undefined;
2225
- }
2226
- else {
2227
- total += partLength;
2228
- }
2229
- }
2230
- return total;
2231
- }
2232
- function buildRequestBody(request, parts, boundary) {
2233
- const sources = [
2234
- stringToUint8Array(`--${boundary}`, "utf-8"),
2235
- ...parts.flatMap((part) => [
2236
- stringToUint8Array("\r\n", "utf-8"),
2237
- stringToUint8Array(encodeHeaders(part.headers), "utf-8"),
2238
- stringToUint8Array("\r\n", "utf-8"),
2239
- part.body,
2240
- stringToUint8Array(`\r\n--${boundary}`, "utf-8"),
2241
- ]),
2242
- stringToUint8Array("--\r\n\r\n", "utf-8"),
2243
- ];
2244
- const contentLength = getTotalLength(sources);
2245
- if (contentLength) {
2246
- request.headers.set("Content-Length", contentLength);
2247
- }
2248
- request.body = (() => concatenateStreams(sources.map((source) => (typeof source === "function" ? source() : source)).map(toStream)));
2249
- }
2250
- /**
2251
- * Name of multipart policy
2252
- */
2253
- const multipartPolicyName = "multipartPolicy";
2254
- const maxBoundaryLength = 70;
2255
- const validBoundaryCharacters = new Set(`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'()+,-./:=?`);
2256
- function assertValidBoundary(boundary) {
2257
- if (boundary.length > maxBoundaryLength) {
2258
- throw new Error(`Multipart boundary "${boundary}" exceeds maximum length of 70 characters`);
2259
- }
2260
- if (Array.from(boundary).some((x) => !validBoundaryCharacters.has(x))) {
2261
- throw new Error(`Multipart boundary "${boundary}" contains invalid characters`);
2262
- }
2263
- }
2264
- /**
2265
- * Pipeline policy for multipart requests
2266
- */
2267
- function multipartPolicy() {
2268
- return {
2269
- name: multipartPolicyName,
2270
- sendRequest(request, next) {
2271
- var _a;
2272
- if (!request.multipartBody) {
2273
- return next(request);
2274
- }
2275
- if (request.body) {
2276
- throw new Error("multipartBody and regular body cannot be set at the same time");
2277
- }
2278
- let boundary = request.multipartBody.boundary;
2279
- const contentTypeHeader = (_a = request.headers.get("Content-Type")) !== null && _a !== void 0 ? _a : "multipart/mixed";
2280
- const parsedHeader = contentTypeHeader.match(/^(multipart\/[^ ;]+)(?:; *boundary=(.+))?$/);
2281
- if (!parsedHeader) {
2282
- throw new Error(`Got multipart request body, but content-type header was not multipart: ${contentTypeHeader}`);
2283
- }
2284
- const [, contentType, parsedBoundary] = parsedHeader;
2285
- if (parsedBoundary && boundary && parsedBoundary !== boundary) {
2286
- throw new Error(`Multipart boundary was specified as ${parsedBoundary} in the header, but got ${boundary} in the request body`);
2287
- }
2288
- boundary !== null && boundary !== void 0 ? boundary : (boundary = parsedBoundary);
2289
- if (boundary) {
2290
- assertValidBoundary(boundary);
2291
- }
2292
- else {
2293
- boundary = generateBoundary();
2294
- }
2295
- request.headers.set("Content-Type", `${contentType}; boundary=${boundary}`);
2296
- buildRequestBody(request, request.multipartBody.parts, boundary);
2297
- request.multipartBody = undefined;
2298
- return next(request);
2299
- },
2300
- };
2301
- }
2302
-
2303
2302
  // Copyright (c) Microsoft Corporation.
2304
2303
  // Licensed under the MIT license.
2305
2304
  /**
@@ -2315,7 +2314,7 @@ function createPipelineFromOptions(options) {
2315
2314
  pipeline.addPolicy(proxyPolicy(options.proxyOptions));
2316
2315
  pipeline.addPolicy(decompressResponsePolicy());
2317
2316
  }
2318
- pipeline.addPolicy(formDataPolicy());
2317
+ pipeline.addPolicy(formDataPolicy(), { beforePolicies: [multipartPolicyName] });
2319
2318
  pipeline.addPolicy(userAgentPolicy(options.userAgentOptions));
2320
2319
  // The multipart policy is added after policies with no phase, so that
2321
2320
  // policies can be added between it and formDataPolicy to modify