@typespec/ts-http-runtime 0.3.5-alpha.20260306.4 → 0.3.5-alpha.20260310.2
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/browser/client/urlHelpers.d.ts +2 -0
- package/dist/browser/client/urlHelpers.js +109 -14
- package/dist/browser/client/urlHelpers.js.map +1 -1
- package/dist/commonjs/client/urlHelpers.d.ts +2 -0
- package/dist/commonjs/client/urlHelpers.js +86 -10
- package/dist/commonjs/client/urlHelpers.js.map +2 -2
- package/dist/esm/client/urlHelpers.d.ts +2 -0
- package/dist/esm/client/urlHelpers.js +109 -14
- package/dist/esm/client/urlHelpers.js.map +1 -1
- package/dist/react-native/client/urlHelpers.d.ts +2 -0
- package/dist/react-native/client/urlHelpers.js +109 -14
- package/dist/react-native/client/urlHelpers.js.map +1 -1
- package/package.json +3 -3
|
@@ -8,6 +8,8 @@ import type { PathParameterWithOptions, RequestParameters } from "./common.js";
|
|
|
8
8
|
* @returns a full url with path and query parameters
|
|
9
9
|
*/
|
|
10
10
|
export declare function buildRequestUrl(endpoint: string, routePath: string, pathParameters: (string | number | PathParameterWithOptions)[], options?: RequestParameters): string;
|
|
11
|
+
/** @internal */
|
|
12
|
+
export declare function appendQueryParams(url: string, options?: RequestParameters): string;
|
|
11
13
|
export declare function buildBaseUrl(endpoint: string, options: RequestParameters): string;
|
|
12
14
|
/**
|
|
13
15
|
* Replace all of the instances of searchValue in value with the provided replaceValue.
|
|
@@ -17,13 +17,43 @@ export function buildRequestUrl(endpoint, routePath, pathParameters, options = {
|
|
|
17
17
|
return routePath;
|
|
18
18
|
}
|
|
19
19
|
endpoint = buildBaseUrl(endpoint, options);
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
// the route could be
|
|
21
|
+
// 1. a path: "container123/blob456"
|
|
22
|
+
// 2. a component string from template which starts with "?" and may contain more "?" after template is expanded,
|
|
23
|
+
// e.g., "?restype=container&comp=blobs?where=key177196556777405927%3D%27val1177196556777407626%27"
|
|
24
|
+
const updatedRoutePath = buildRoutePath(routePath, pathParameters, options);
|
|
25
|
+
const requestUrl = appendQueryParams(appendPath(endpoint, updatedRoutePath), options);
|
|
22
26
|
const url = new URL(requestUrl);
|
|
23
|
-
return (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
return url.toString();
|
|
28
|
+
}
|
|
29
|
+
function appendPath(endpoint, pathToAppend) {
|
|
30
|
+
const endpointSearchStart = endpoint.indexOf("?");
|
|
31
|
+
const pathSearchStart = pathToAppend.indexOf("?");
|
|
32
|
+
const endpointParts = endpointSearchStart !== -1
|
|
33
|
+
? [endpoint.substring(0, endpointSearchStart), endpoint.substring(endpointSearchStart + 1)]
|
|
34
|
+
: [endpoint, ""];
|
|
35
|
+
const pathParts = pathSearchStart !== -1
|
|
36
|
+
? [pathToAppend.substring(0, pathSearchStart), pathToAppend.substring(pathSearchStart + 1)]
|
|
37
|
+
: [pathToAppend, ""];
|
|
38
|
+
const combinedSearch = [endpointParts[1], pathParts[1].replaceAll("?", "&")]
|
|
39
|
+
.filter(Boolean)
|
|
40
|
+
.join("&");
|
|
41
|
+
const baseEndpoint = endpointParts[0];
|
|
42
|
+
const basePathToAppend = pathParts[0];
|
|
43
|
+
let combinedUrl = baseEndpoint;
|
|
44
|
+
if (!baseEndpoint.endsWith("/") && !basePathToAppend.startsWith("/") && basePathToAppend !== "") {
|
|
45
|
+
combinedUrl += `/${basePathToAppend}`;
|
|
46
|
+
}
|
|
47
|
+
else if (baseEndpoint.endsWith("/") && basePathToAppend.startsWith("/")) {
|
|
48
|
+
combinedUrl += basePathToAppend.substring(1);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
combinedUrl += basePathToAppend;
|
|
52
|
+
}
|
|
53
|
+
if (combinedSearch) {
|
|
54
|
+
combinedUrl += `?${combinedSearch}`;
|
|
55
|
+
}
|
|
56
|
+
return combinedUrl;
|
|
27
57
|
}
|
|
28
58
|
function getQueryParamValue(key, allowReserved, style, param) {
|
|
29
59
|
let separator;
|
|
@@ -62,13 +92,48 @@ function getQueryParamValue(key, allowReserved, style, param) {
|
|
|
62
92
|
.join(separator);
|
|
63
93
|
return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;
|
|
64
94
|
}
|
|
65
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Parses a query string into a map of key/value pairs without decoding the values.
|
|
97
|
+
* This avoids the issue where `URL.searchParams` would decode values, potentially
|
|
98
|
+
* corrupting already-encoded values such as SAS signatures.
|
|
99
|
+
*/
|
|
100
|
+
function simpleParseQueryParams(queryString) {
|
|
101
|
+
const result = new Map();
|
|
102
|
+
if (!queryString || queryString[0] !== "?") {
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
// remove the leading ?
|
|
106
|
+
queryString = queryString.slice(1);
|
|
107
|
+
const pairs = queryString.split("&");
|
|
108
|
+
for (const pair of pairs) {
|
|
109
|
+
const eqIndex = pair.indexOf("=");
|
|
110
|
+
const name = eqIndex === -1 ? pair : pair.substring(0, eqIndex);
|
|
111
|
+
const value = eqIndex === -1 ? "" : pair.substring(eqIndex + 1);
|
|
112
|
+
const existingValue = result.get(name);
|
|
113
|
+
if (existingValue !== undefined) {
|
|
114
|
+
if (Array.isArray(existingValue)) {
|
|
115
|
+
existingValue.push(value);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
result.set(name, [existingValue, value]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
result.set(name, value);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
/** @internal */
|
|
128
|
+
export function appendQueryParams(url, options = {}) {
|
|
66
129
|
if (!options.queryParameters) {
|
|
67
130
|
return url;
|
|
68
131
|
}
|
|
69
132
|
const parsedUrl = new URL(url);
|
|
70
133
|
const queryParams = options.queryParameters;
|
|
71
|
-
|
|
134
|
+
// Parse existing query params from the URL manually to avoid re-encoding issues
|
|
135
|
+
const existingParams = simpleParseQueryParams(parsedUrl.search);
|
|
136
|
+
const newParamStrings = [];
|
|
72
137
|
for (const key of Object.keys(queryParams)) {
|
|
73
138
|
const param = queryParams[key];
|
|
74
139
|
if (param === undefined || param === null) {
|
|
@@ -81,13 +146,13 @@ function appendQueryParams(url, options = {}) {
|
|
|
81
146
|
if (explode) {
|
|
82
147
|
if (Array.isArray(rawValue)) {
|
|
83
148
|
for (const item of rawValue) {
|
|
84
|
-
|
|
149
|
+
newParamStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item));
|
|
85
150
|
}
|
|
86
151
|
}
|
|
87
152
|
else if (typeof rawValue === "object") {
|
|
88
153
|
// For object explode, the name of the query parameter is ignored and we use the object key instead
|
|
89
154
|
for (const [actualKey, value] of Object.entries(rawValue)) {
|
|
90
|
-
|
|
155
|
+
newParamStrings.push(getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value));
|
|
91
156
|
}
|
|
92
157
|
}
|
|
93
158
|
else {
|
|
@@ -96,13 +161,43 @@ function appendQueryParams(url, options = {}) {
|
|
|
96
161
|
}
|
|
97
162
|
}
|
|
98
163
|
else {
|
|
99
|
-
|
|
164
|
+
newParamStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Merge new params into existing params, deduplicating values for the same key
|
|
168
|
+
for (const paramString of newParamStrings) {
|
|
169
|
+
const eqIndex = paramString.indexOf("=");
|
|
170
|
+
const name = paramString.substring(0, eqIndex);
|
|
171
|
+
const value = paramString.substring(eqIndex + 1);
|
|
172
|
+
const existingValue = existingParams.get(name);
|
|
173
|
+
if (existingValue !== undefined) {
|
|
174
|
+
if (Array.isArray(existingValue)) {
|
|
175
|
+
if (!existingValue.includes(value)) {
|
|
176
|
+
existingValue.push(value);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else if (existingValue !== value) {
|
|
180
|
+
existingParams.set(name, [existingValue, value]);
|
|
181
|
+
}
|
|
182
|
+
// if existingValue === value (single string match), no change needed
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
existingParams.set(name, value);
|
|
100
186
|
}
|
|
101
187
|
}
|
|
102
|
-
|
|
103
|
-
|
|
188
|
+
// Reconstruct the search string manually to avoid URL re-encoding
|
|
189
|
+
const searchPieces = [];
|
|
190
|
+
for (const [name, value] of existingParams) {
|
|
191
|
+
if (Array.isArray(value)) {
|
|
192
|
+
for (const subValue of value) {
|
|
193
|
+
searchPieces.push(`${name}=${subValue}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
searchPieces.push(`${name}=${value}`);
|
|
198
|
+
}
|
|
104
199
|
}
|
|
105
|
-
parsedUrl.search
|
|
200
|
+
parsedUrl.search = searchPieces.length ? `?${searchPieces.join("&")}` : "";
|
|
106
201
|
return parsedUrl.toString();
|
|
107
202
|
}
|
|
108
203
|
export function buildBaseUrl(endpoint, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urlHelpers.js","sourceRoot":"","sources":["../../../src/client/urlHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { PathParameterWithOptions, RequestParameters } from \"./common.js\";\n\ntype QueryParameterStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\n\n/**\n * An object that can be passed as a query parameter, allowing for additional options to be set relating to how the parameter is encoded.\n */\ninterface QueryParameterWithOptions {\n /**\n * The value of the query parameter.\n */\n value: unknown;\n\n /**\n * If set to true, value must be an array. Setting this option to true will cause the array to be encoded as multiple query parameters.\n * Setting it to false will cause the array values to be encoded as a single query parameter, with each value separated by a comma ','.\n *\n * For example, with `explode` set to true, a query parameter named \"foo\" with value [\"a\", \"b\", \"c\"] will be encoded as foo=a&foo=b&foo=c.\n * If `explode` was set to false, the same example would instead be encouded as foo=a,b,c.\n *\n * Defaults to false.\n */\n explode?: boolean;\n\n /**\n * Style for encoding arrays. Three possible values:\n * - \"form\": array values will be separated by a comma \",\" in the query parameter value.\n * - \"spaceDelimited\": array values will be separated by a space (\" \", url-encoded to \"%20\").\n * - \"pipeDelimited\": array values will be separated by a pipe (\"|\").\n *\n * Defaults to \"form\".\n */\n style?: QueryParameterStyle;\n}\n\nfunction isQueryParameterWithOptions(x: unknown): x is QueryParameterWithOptions {\n const value = (x as QueryParameterWithOptions).value as any;\n return (\n value !== undefined && value.toString !== undefined && typeof value.toString === \"function\"\n );\n}\n\n/**\n * Builds the request url, filling in query and path parameters\n * @param endpoint - base url which can be a template url\n * @param routePath - path to append to the endpoint\n * @param pathParameters - values of the path parameters\n * @param options - request parameters including query parameters\n * @returns a full url with path and query parameters\n */\nexport function buildRequestUrl(\n endpoint: string,\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n if (routePath.startsWith(\"https://\") || routePath.startsWith(\"http://\")) {\n return routePath;\n }\n endpoint = buildBaseUrl(endpoint, options);\n routePath = buildRoutePath(routePath, pathParameters, options);\n const requestUrl = appendQueryParams(`${endpoint}/${routePath}`, options);\n const url = new URL(requestUrl);\n\n return (\n url\n .toString()\n // Remove double forward slashes\n .replace(/([^:]\\/)\\/+/g, \"$1\")\n );\n}\n\nfunction getQueryParamValue(\n key: string,\n allowReserved: boolean,\n style: QueryParameterStyle,\n param: any,\n): string {\n let separator: string;\n if (style === \"pipeDelimited\") {\n separator = \"|\";\n } else if (style === \"spaceDelimited\") {\n separator = \"%20\";\n } else {\n separator = \",\";\n }\n\n let paramValues: any[];\n if (Array.isArray(param)) {\n paramValues = param;\n } else if (typeof param === \"object\" && param.toString === Object.prototype.toString) {\n // If the parameter is an object without a custom toString implementation (e.g. a Date),\n // then we should deconstruct the object into an array [key1, value1, key2, value2, ...].\n paramValues = Object.entries(param).flat();\n } else {\n paramValues = [param];\n }\n\n const value = paramValues\n .map((p) => {\n if (p === null || p === undefined) {\n return \"\";\n }\n\n if (!p.toString || typeof p.toString !== \"function\") {\n throw new Error(`Query parameters must be able to be represented as string, ${key} can't`);\n }\n\n const rawValue = p.toISOString !== undefined ? p.toISOString() : p.toString();\n return allowReserved ? rawValue : encodeURIComponent(rawValue);\n })\n .join(separator);\n\n return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;\n}\n\nfunction appendQueryParams(url: string, options: RequestParameters = {}): string {\n if (!options.queryParameters) {\n return url;\n }\n const parsedUrl = new URL(url);\n const queryParams = options.queryParameters;\n\n const paramStrings: string[] = [];\n for (const key of Object.keys(queryParams)) {\n const param = queryParams[key] as any;\n if (param === undefined || param === null) {\n continue;\n }\n\n const hasMetadata = isQueryParameterWithOptions(param);\n const rawValue = hasMetadata ? param.value : param;\n const explode = hasMetadata ? (param.explode ?? false) : false;\n const style = hasMetadata && param.style ? param.style : \"form\";\n\n if (explode) {\n if (Array.isArray(rawValue)) {\n for (const item of rawValue) {\n paramStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item));\n }\n } else if (typeof rawValue === \"object\") {\n // For object explode, the name of the query parameter is ignored and we use the object key instead\n for (const [actualKey, value] of Object.entries(rawValue)) {\n paramStrings.push(\n getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value),\n );\n }\n } else {\n // Explode doesn't really make sense for primitives\n throw new Error(\"explode can only be set to true for objects and arrays\");\n }\n } else {\n paramStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue));\n }\n }\n\n if (parsedUrl.search !== \"\") {\n parsedUrl.search += \"&\";\n }\n parsedUrl.search += paramStrings.join(\"&\");\n return parsedUrl.toString();\n}\n\nexport function buildBaseUrl(endpoint: string, options: RequestParameters): string {\n if (!options.pathParameters) {\n return endpoint;\n }\n const pathParams = options.pathParameters;\n for (const [key, param] of Object.entries(pathParams)) {\n if (param === undefined || param === null) {\n throw new Error(`Path parameters ${key} must not be undefined or null`);\n }\n if (!param.toString || typeof param.toString !== \"function\") {\n throw new Error(`Path parameters must be able to be represented as string, ${key} can't`);\n }\n let value = param.toISOString !== undefined ? param.toISOString() : String(param);\n if (!options.skipUrlEncoding) {\n value = encodeURIComponent(param);\n }\n endpoint = replaceAll(endpoint, `{${key}}`, value) ?? \"\";\n }\n return endpoint;\n}\n\nfunction buildRoutePath(\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n for (const pathParam of pathParameters) {\n const allowReserved = typeof pathParam === \"object\" && (pathParam.allowReserved ?? false);\n let value = typeof pathParam === \"object\" ? pathParam.value : pathParam;\n\n if (!options.skipUrlEncoding && !allowReserved) {\n value = encodeURIComponent(value);\n }\n\n routePath = routePath.replace(/\\{[\\w-]+\\}/, String(value));\n }\n return routePath;\n}\n\n/**\n * Replace all of the instances of searchValue in value with the provided replaceValue.\n * @param value - The value to search and replace in.\n * @param searchValue - The value to search for in the value argument.\n * @param replaceValue - The value to replace searchValue with in the value argument.\n * @returns The value where each instance of searchValue was replaced with replacedValue.\n */\nexport function replaceAll(\n value: string | undefined,\n searchValue: string,\n replaceValue: string,\n): string | undefined {\n return !value || !searchValue ? value : value.split(searchValue).join(replaceValue || \"\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"urlHelpers.js","sourceRoot":"","sources":["../../../src/client/urlHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { PathParameterWithOptions, RequestParameters } from \"./common.js\";\n\ntype QueryParameterStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\n\n/**\n * An object that can be passed as a query parameter, allowing for additional options to be set relating to how the parameter is encoded.\n */\ninterface QueryParameterWithOptions {\n /**\n * The value of the query parameter.\n */\n value: unknown;\n\n /**\n * If set to true, value must be an array. Setting this option to true will cause the array to be encoded as multiple query parameters.\n * Setting it to false will cause the array values to be encoded as a single query parameter, with each value separated by a comma ','.\n *\n * For example, with `explode` set to true, a query parameter named \"foo\" with value [\"a\", \"b\", \"c\"] will be encoded as foo=a&foo=b&foo=c.\n * If `explode` was set to false, the same example would instead be encouded as foo=a,b,c.\n *\n * Defaults to false.\n */\n explode?: boolean;\n\n /**\n * Style for encoding arrays. Three possible values:\n * - \"form\": array values will be separated by a comma \",\" in the query parameter value.\n * - \"spaceDelimited\": array values will be separated by a space (\" \", url-encoded to \"%20\").\n * - \"pipeDelimited\": array values will be separated by a pipe (\"|\").\n *\n * Defaults to \"form\".\n */\n style?: QueryParameterStyle;\n}\n\nfunction isQueryParameterWithOptions(x: unknown): x is QueryParameterWithOptions {\n const value = (x as QueryParameterWithOptions).value as any;\n return (\n value !== undefined && value.toString !== undefined && typeof value.toString === \"function\"\n );\n}\n\n/**\n * Builds the request url, filling in query and path parameters\n * @param endpoint - base url which can be a template url\n * @param routePath - path to append to the endpoint\n * @param pathParameters - values of the path parameters\n * @param options - request parameters including query parameters\n * @returns a full url with path and query parameters\n */\nexport function buildRequestUrl(\n endpoint: string,\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n if (routePath.startsWith(\"https://\") || routePath.startsWith(\"http://\")) {\n return routePath;\n }\n endpoint = buildBaseUrl(endpoint, options);\n // the route could be\n // 1. a path: \"container123/blob456\"\n // 2. a component string from template which starts with \"?\" and may contain more \"?\" after template is expanded,\n // e.g., \"?restype=container&comp=blobs?where=key177196556777405927%3D%27val1177196556777407626%27\"\n const updatedRoutePath = buildRoutePath(routePath, pathParameters, options);\n\n const requestUrl = appendQueryParams(appendPath(endpoint, updatedRoutePath), options);\n const url = new URL(requestUrl);\n\n return url.toString();\n}\n\nfunction appendPath(endpoint: string, pathToAppend: string): string {\n const endpointSearchStart = endpoint.indexOf(\"?\");\n const pathSearchStart = pathToAppend.indexOf(\"?\");\n const endpointParts =\n endpointSearchStart !== -1\n ? [endpoint.substring(0, endpointSearchStart), endpoint.substring(endpointSearchStart + 1)]\n : [endpoint, \"\"];\n const pathParts =\n pathSearchStart !== -1\n ? [pathToAppend.substring(0, pathSearchStart), pathToAppend.substring(pathSearchStart + 1)]\n : [pathToAppend, \"\"];\n\n const combinedSearch = [endpointParts[1], pathParts[1].replaceAll(\"?\", \"&\")]\n .filter(Boolean)\n .join(\"&\");\n const baseEndpoint = endpointParts[0];\n const basePathToAppend = pathParts[0];\n\n let combinedUrl = baseEndpoint;\n if (!baseEndpoint.endsWith(\"/\") && !basePathToAppend.startsWith(\"/\") && basePathToAppend !== \"\") {\n combinedUrl += `/${basePathToAppend}`;\n } else if (baseEndpoint.endsWith(\"/\") && basePathToAppend.startsWith(\"/\")) {\n combinedUrl += basePathToAppend.substring(1);\n } else {\n combinedUrl += basePathToAppend;\n }\n\n if (combinedSearch) {\n combinedUrl += `?${combinedSearch}`;\n }\n\n return combinedUrl;\n}\n\nfunction getQueryParamValue(\n key: string,\n allowReserved: boolean,\n style: QueryParameterStyle,\n param: any,\n): string {\n let separator: string;\n if (style === \"pipeDelimited\") {\n separator = \"|\";\n } else if (style === \"spaceDelimited\") {\n separator = \"%20\";\n } else {\n separator = \",\";\n }\n\n let paramValues: any[];\n if (Array.isArray(param)) {\n paramValues = param;\n } else if (typeof param === \"object\" && param.toString === Object.prototype.toString) {\n // If the parameter is an object without a custom toString implementation (e.g. a Date),\n // then we should deconstruct the object into an array [key1, value1, key2, value2, ...].\n paramValues = Object.entries(param).flat();\n } else {\n paramValues = [param];\n }\n\n const value = paramValues\n .map((p) => {\n if (p === null || p === undefined) {\n return \"\";\n }\n\n if (!p.toString || typeof p.toString !== \"function\") {\n throw new Error(`Query parameters must be able to be represented as string, ${key} can't`);\n }\n\n const rawValue = p.toISOString !== undefined ? p.toISOString() : p.toString();\n return allowReserved ? rawValue : encodeURIComponent(rawValue);\n })\n .join(separator);\n\n return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;\n}\n\n/**\n * Parses a query string into a map of key/value pairs without decoding the values.\n * This avoids the issue where `URL.searchParams` would decode values, potentially\n * corrupting already-encoded values such as SAS signatures.\n */\nfunction simpleParseQueryParams(queryString: string): Map<string, string | string[]> {\n const result = new Map<string, string | string[]>();\n if (!queryString || queryString[0] !== \"?\") {\n return result;\n }\n\n // remove the leading ?\n queryString = queryString.slice(1);\n const pairs = queryString.split(\"&\");\n\n for (const pair of pairs) {\n const eqIndex = pair.indexOf(\"=\");\n const name = eqIndex === -1 ? pair : pair.substring(0, eqIndex);\n const value = eqIndex === -1 ? \"\" : pair.substring(eqIndex + 1);\n\n const existingValue = result.get(name);\n if (existingValue !== undefined) {\n if (Array.isArray(existingValue)) {\n existingValue.push(value);\n } else {\n result.set(name, [existingValue, value]);\n }\n } else {\n result.set(name, value);\n }\n }\n\n return result;\n}\n\n/** @internal */\nexport function appendQueryParams(url: string, options: RequestParameters = {}): string {\n if (!options.queryParameters) {\n return url;\n }\n const parsedUrl = new URL(url);\n const queryParams = options.queryParameters;\n\n // Parse existing query params from the URL manually to avoid re-encoding issues\n const existingParams = simpleParseQueryParams(parsedUrl.search);\n\n const newParamStrings: string[] = [];\n for (const key of Object.keys(queryParams)) {\n const param = queryParams[key] as any;\n if (param === undefined || param === null) {\n continue;\n }\n\n const hasMetadata = isQueryParameterWithOptions(param);\n const rawValue = hasMetadata ? param.value : param;\n const explode = hasMetadata ? (param.explode ?? false) : false;\n const style = hasMetadata && param.style ? param.style : \"form\";\n\n if (explode) {\n if (Array.isArray(rawValue)) {\n for (const item of rawValue) {\n newParamStrings.push(\n getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item),\n );\n }\n } else if (typeof rawValue === \"object\") {\n // For object explode, the name of the query parameter is ignored and we use the object key instead\n for (const [actualKey, value] of Object.entries(rawValue)) {\n newParamStrings.push(\n getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value),\n );\n }\n } else {\n // Explode doesn't really make sense for primitives\n throw new Error(\"explode can only be set to true for objects and arrays\");\n }\n } else {\n newParamStrings.push(\n getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue),\n );\n }\n }\n\n // Merge new params into existing params, deduplicating values for the same key\n for (const paramString of newParamStrings) {\n const eqIndex = paramString.indexOf(\"=\");\n const name = paramString.substring(0, eqIndex);\n const value = paramString.substring(eqIndex + 1);\n\n const existingValue = existingParams.get(name);\n if (existingValue !== undefined) {\n if (Array.isArray(existingValue)) {\n if (!existingValue.includes(value)) {\n existingValue.push(value);\n }\n } else if (existingValue !== value) {\n existingParams.set(name, [existingValue, value]);\n }\n // if existingValue === value (single string match), no change needed\n } else {\n existingParams.set(name, value);\n }\n }\n\n // Reconstruct the search string manually to avoid URL re-encoding\n const searchPieces: string[] = [];\n for (const [name, value] of existingParams) {\n if (Array.isArray(value)) {\n for (const subValue of value) {\n searchPieces.push(`${name}=${subValue}`);\n }\n } else {\n searchPieces.push(`${name}=${value}`);\n }\n }\n\n parsedUrl.search = searchPieces.length ? `?${searchPieces.join(\"&\")}` : \"\";\n return parsedUrl.toString();\n}\n\nexport function buildBaseUrl(endpoint: string, options: RequestParameters): string {\n if (!options.pathParameters) {\n return endpoint;\n }\n const pathParams = options.pathParameters;\n for (const [key, param] of Object.entries(pathParams)) {\n if (param === undefined || param === null) {\n throw new Error(`Path parameters ${key} must not be undefined or null`);\n }\n if (!param.toString || typeof param.toString !== \"function\") {\n throw new Error(`Path parameters must be able to be represented as string, ${key} can't`);\n }\n let value = param.toISOString !== undefined ? param.toISOString() : String(param);\n if (!options.skipUrlEncoding) {\n value = encodeURIComponent(param);\n }\n endpoint = replaceAll(endpoint, `{${key}}`, value) ?? \"\";\n }\n return endpoint;\n}\n\nfunction buildRoutePath(\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n for (const pathParam of pathParameters) {\n const allowReserved = typeof pathParam === \"object\" && (pathParam.allowReserved ?? false);\n let value = typeof pathParam === \"object\" ? pathParam.value : pathParam;\n\n if (!options.skipUrlEncoding && !allowReserved) {\n value = encodeURIComponent(value);\n }\n\n routePath = routePath.replace(/\\{[\\w-]+\\}/, String(value));\n }\n return routePath;\n}\n\n/**\n * Replace all of the instances of searchValue in value with the provided replaceValue.\n * @param value - The value to search and replace in.\n * @param searchValue - The value to search for in the value argument.\n * @param replaceValue - The value to replace searchValue with in the value argument.\n * @returns The value where each instance of searchValue was replaced with replacedValue.\n */\nexport function replaceAll(\n value: string | undefined,\n searchValue: string,\n replaceValue: string,\n): string | undefined {\n return !value || !searchValue ? value : value.split(searchValue).join(replaceValue || \"\");\n}\n"]}
|
|
@@ -8,6 +8,8 @@ import type { PathParameterWithOptions, RequestParameters } from "./common.js";
|
|
|
8
8
|
* @returns a full url with path and query parameters
|
|
9
9
|
*/
|
|
10
10
|
export declare function buildRequestUrl(endpoint: string, routePath: string, pathParameters: (string | number | PathParameterWithOptions)[], options?: RequestParameters): string;
|
|
11
|
+
/** @internal */
|
|
12
|
+
export declare function appendQueryParams(url: string, options?: RequestParameters): string;
|
|
11
13
|
export declare function buildBaseUrl(endpoint: string, options: RequestParameters): string;
|
|
12
14
|
/**
|
|
13
15
|
* Replace all of the instances of searchValue in value with the provided replaceValue.
|
|
@@ -17,6 +17,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
18
|
var urlHelpers_exports = {};
|
|
19
19
|
__export(urlHelpers_exports, {
|
|
20
|
+
appendQueryParams: () => appendQueryParams,
|
|
20
21
|
buildBaseUrl: () => buildBaseUrl,
|
|
21
22
|
buildRequestUrl: () => buildRequestUrl,
|
|
22
23
|
replaceAll: () => replaceAll
|
|
@@ -31,10 +32,31 @@ function buildRequestUrl(endpoint, routePath, pathParameters, options = {}) {
|
|
|
31
32
|
return routePath;
|
|
32
33
|
}
|
|
33
34
|
endpoint = buildBaseUrl(endpoint, options);
|
|
34
|
-
|
|
35
|
-
const requestUrl = appendQueryParams(
|
|
35
|
+
const updatedRoutePath = buildRoutePath(routePath, pathParameters, options);
|
|
36
|
+
const requestUrl = appendQueryParams(appendPath(endpoint, updatedRoutePath), options);
|
|
36
37
|
const url = new URL(requestUrl);
|
|
37
|
-
return url.toString()
|
|
38
|
+
return url.toString();
|
|
39
|
+
}
|
|
40
|
+
function appendPath(endpoint, pathToAppend) {
|
|
41
|
+
const endpointSearchStart = endpoint.indexOf("?");
|
|
42
|
+
const pathSearchStart = pathToAppend.indexOf("?");
|
|
43
|
+
const endpointParts = endpointSearchStart !== -1 ? [endpoint.substring(0, endpointSearchStart), endpoint.substring(endpointSearchStart + 1)] : [endpoint, ""];
|
|
44
|
+
const pathParts = pathSearchStart !== -1 ? [pathToAppend.substring(0, pathSearchStart), pathToAppend.substring(pathSearchStart + 1)] : [pathToAppend, ""];
|
|
45
|
+
const combinedSearch = [endpointParts[1], pathParts[1].replaceAll("?", "&")].filter(Boolean).join("&");
|
|
46
|
+
const baseEndpoint = endpointParts[0];
|
|
47
|
+
const basePathToAppend = pathParts[0];
|
|
48
|
+
let combinedUrl = baseEndpoint;
|
|
49
|
+
if (!baseEndpoint.endsWith("/") && !basePathToAppend.startsWith("/") && basePathToAppend !== "") {
|
|
50
|
+
combinedUrl += `/${basePathToAppend}`;
|
|
51
|
+
} else if (baseEndpoint.endsWith("/") && basePathToAppend.startsWith("/")) {
|
|
52
|
+
combinedUrl += basePathToAppend.substring(1);
|
|
53
|
+
} else {
|
|
54
|
+
combinedUrl += basePathToAppend;
|
|
55
|
+
}
|
|
56
|
+
if (combinedSearch) {
|
|
57
|
+
combinedUrl += `?${combinedSearch}`;
|
|
58
|
+
}
|
|
59
|
+
return combinedUrl;
|
|
38
60
|
}
|
|
39
61
|
function getQueryParamValue(key, allowReserved, style, param) {
|
|
40
62
|
let separator;
|
|
@@ -65,13 +87,38 @@ function getQueryParamValue(key, allowReserved, style, param) {
|
|
|
65
87
|
}).join(separator);
|
|
66
88
|
return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;
|
|
67
89
|
}
|
|
90
|
+
function simpleParseQueryParams(queryString) {
|
|
91
|
+
const result = /* @__PURE__ */ new Map();
|
|
92
|
+
if (!queryString || queryString[0] !== "?") {
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
queryString = queryString.slice(1);
|
|
96
|
+
const pairs = queryString.split("&");
|
|
97
|
+
for (const pair of pairs) {
|
|
98
|
+
const eqIndex = pair.indexOf("=");
|
|
99
|
+
const name = eqIndex === -1 ? pair : pair.substring(0, eqIndex);
|
|
100
|
+
const value = eqIndex === -1 ? "" : pair.substring(eqIndex + 1);
|
|
101
|
+
const existingValue = result.get(name);
|
|
102
|
+
if (existingValue !== void 0) {
|
|
103
|
+
if (Array.isArray(existingValue)) {
|
|
104
|
+
existingValue.push(value);
|
|
105
|
+
} else {
|
|
106
|
+
result.set(name, [existingValue, value]);
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
result.set(name, value);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
68
114
|
function appendQueryParams(url, options = {}) {
|
|
69
115
|
if (!options.queryParameters) {
|
|
70
116
|
return url;
|
|
71
117
|
}
|
|
72
118
|
const parsedUrl = new URL(url);
|
|
73
119
|
const queryParams = options.queryParameters;
|
|
74
|
-
const
|
|
120
|
+
const existingParams = simpleParseQueryParams(parsedUrl.search);
|
|
121
|
+
const newParamStrings = [];
|
|
75
122
|
for (const key of Object.keys(queryParams)) {
|
|
76
123
|
const param = queryParams[key];
|
|
77
124
|
if (param === void 0 || param === null) {
|
|
@@ -84,11 +131,13 @@ function appendQueryParams(url, options = {}) {
|
|
|
84
131
|
if (explode) {
|
|
85
132
|
if (Array.isArray(rawValue)) {
|
|
86
133
|
for (const item of rawValue) {
|
|
87
|
-
|
|
134
|
+
newParamStrings.push(
|
|
135
|
+
getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item)
|
|
136
|
+
);
|
|
88
137
|
}
|
|
89
138
|
} else if (typeof rawValue === "object") {
|
|
90
139
|
for (const [actualKey, value] of Object.entries(rawValue)) {
|
|
91
|
-
|
|
140
|
+
newParamStrings.push(
|
|
92
141
|
getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value)
|
|
93
142
|
);
|
|
94
143
|
}
|
|
@@ -96,13 +145,39 @@ function appendQueryParams(url, options = {}) {
|
|
|
96
145
|
throw new Error("explode can only be set to true for objects and arrays");
|
|
97
146
|
}
|
|
98
147
|
} else {
|
|
99
|
-
|
|
148
|
+
newParamStrings.push(
|
|
149
|
+
getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue)
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
for (const paramString of newParamStrings) {
|
|
154
|
+
const eqIndex = paramString.indexOf("=");
|
|
155
|
+
const name = paramString.substring(0, eqIndex);
|
|
156
|
+
const value = paramString.substring(eqIndex + 1);
|
|
157
|
+
const existingValue = existingParams.get(name);
|
|
158
|
+
if (existingValue !== void 0) {
|
|
159
|
+
if (Array.isArray(existingValue)) {
|
|
160
|
+
if (!existingValue.includes(value)) {
|
|
161
|
+
existingValue.push(value);
|
|
162
|
+
}
|
|
163
|
+
} else if (existingValue !== value) {
|
|
164
|
+
existingParams.set(name, [existingValue, value]);
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
existingParams.set(name, value);
|
|
100
168
|
}
|
|
101
169
|
}
|
|
102
|
-
|
|
103
|
-
|
|
170
|
+
const searchPieces = [];
|
|
171
|
+
for (const [name, value] of existingParams) {
|
|
172
|
+
if (Array.isArray(value)) {
|
|
173
|
+
for (const subValue of value) {
|
|
174
|
+
searchPieces.push(`${name}=${subValue}`);
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
searchPieces.push(`${name}=${value}`);
|
|
178
|
+
}
|
|
104
179
|
}
|
|
105
|
-
parsedUrl.search
|
|
180
|
+
parsedUrl.search = searchPieces.length ? `?${searchPieces.join("&")}` : "";
|
|
106
181
|
return parsedUrl.toString();
|
|
107
182
|
}
|
|
108
183
|
function buildBaseUrl(endpoint, options) {
|
|
@@ -141,6 +216,7 @@ function replaceAll(value, searchValue, replaceValue) {
|
|
|
141
216
|
}
|
|
142
217
|
// Annotate the CommonJS export names for ESM import in node:
|
|
143
218
|
0 && (module.exports = {
|
|
219
|
+
appendQueryParams,
|
|
144
220
|
buildBaseUrl,
|
|
145
221
|
buildRequestUrl,
|
|
146
222
|
replaceAll
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["/mnt/vss/_work/1/s/sdk/core/ts-http-runtime/src/client/urlHelpers.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { PathParameterWithOptions, RequestParameters } from \"./common.js\";\n\ntype QueryParameterStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\n\n/**\n * An object that can be passed as a query parameter, allowing for additional options to be set relating to how the parameter is encoded.\n */\ninterface QueryParameterWithOptions {\n /**\n * The value of the query parameter.\n */\n value: unknown;\n\n /**\n * If set to true, value must be an array. Setting this option to true will cause the array to be encoded as multiple query parameters.\n * Setting it to false will cause the array values to be encoded as a single query parameter, with each value separated by a comma ','.\n *\n * For example, with `explode` set to true, a query parameter named \"foo\" with value [\"a\", \"b\", \"c\"] will be encoded as foo=a&foo=b&foo=c.\n * If `explode` was set to false, the same example would instead be encouded as foo=a,b,c.\n *\n * Defaults to false.\n */\n explode?: boolean;\n\n /**\n * Style for encoding arrays. Three possible values:\n * - \"form\": array values will be separated by a comma \",\" in the query parameter value.\n * - \"spaceDelimited\": array values will be separated by a space (\" \", url-encoded to \"%20\").\n * - \"pipeDelimited\": array values will be separated by a pipe (\"|\").\n *\n * Defaults to \"form\".\n */\n style?: QueryParameterStyle;\n}\n\nfunction isQueryParameterWithOptions(x: unknown): x is QueryParameterWithOptions {\n const value = (x as QueryParameterWithOptions).value as any;\n return (\n value !== undefined && value.toString !== undefined && typeof value.toString === \"function\"\n );\n}\n\n/**\n * Builds the request url, filling in query and path parameters\n * @param endpoint - base url which can be a template url\n * @param routePath - path to append to the endpoint\n * @param pathParameters - values of the path parameters\n * @param options - request parameters including query parameters\n * @returns a full url with path and query parameters\n */\nexport function buildRequestUrl(\n endpoint: string,\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n if (routePath.startsWith(\"https://\") || routePath.startsWith(\"http://\")) {\n return routePath;\n }\n endpoint = buildBaseUrl(endpoint, options);\n routePath = buildRoutePath(routePath, pathParameters, options);\n const requestUrl = appendQueryParams(`${endpoint}/${routePath}`, options);\n const url = new URL(requestUrl);\n\n return (\n url\n .toString()\n // Remove double forward slashes\n .replace(/([^:]\\/)\\/+/g, \"$1\")\n );\n}\n\nfunction getQueryParamValue(\n key: string,\n allowReserved: boolean,\n style: QueryParameterStyle,\n param: any,\n): string {\n let separator: string;\n if (style === \"pipeDelimited\") {\n separator = \"|\";\n } else if (style === \"spaceDelimited\") {\n separator = \"%20\";\n } else {\n separator = \",\";\n }\n\n let paramValues: any[];\n if (Array.isArray(param)) {\n paramValues = param;\n } else if (typeof param === \"object\" && param.toString === Object.prototype.toString) {\n // If the parameter is an object without a custom toString implementation (e.g. a Date),\n // then we should deconstruct the object into an array [key1, value1, key2, value2, ...].\n paramValues = Object.entries(param).flat();\n } else {\n paramValues = [param];\n }\n\n const value = paramValues\n .map((p) => {\n if (p === null || p === undefined) {\n return \"\";\n }\n\n if (!p.toString || typeof p.toString !== \"function\") {\n throw new Error(`Query parameters must be able to be represented as string, ${key} can't`);\n }\n\n const rawValue = p.toISOString !== undefined ? p.toISOString() : p.toString();\n return allowReserved ? rawValue : encodeURIComponent(rawValue);\n })\n .join(separator);\n\n return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;\n}\n\nfunction appendQueryParams(url: string, options: RequestParameters = {}): string {\n if (!options.queryParameters) {\n return url;\n }\n const parsedUrl = new URL(url);\n const queryParams = options.queryParameters;\n\n const paramStrings: string[] = [];\n for (const key of Object.keys(queryParams)) {\n const param = queryParams[key] as any;\n if (param === undefined || param === null) {\n continue;\n }\n\n const hasMetadata = isQueryParameterWithOptions(param);\n const rawValue = hasMetadata ? param.value : param;\n const explode = hasMetadata ? (param.explode ?? false) : false;\n const style = hasMetadata && param.style ? param.style : \"form\";\n\n if (explode) {\n if (Array.isArray(rawValue)) {\n for (const item of rawValue) {\n paramStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item));\n }\n } else if (typeof rawValue === \"object\") {\n // For object explode, the name of the query parameter is ignored and we use the object key instead\n for (const [actualKey, value] of Object.entries(rawValue)) {\n paramStrings.push(\n getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value),\n );\n }\n } else {\n // Explode doesn't really make sense for primitives\n throw new Error(\"explode can only be set to true for objects and arrays\");\n }\n } else {\n paramStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue));\n }\n }\n\n if (parsedUrl.search !== \"\") {\n parsedUrl.search += \"&\";\n }\n parsedUrl.search += paramStrings.join(\"&\");\n return parsedUrl.toString();\n}\n\nexport function buildBaseUrl(endpoint: string, options: RequestParameters): string {\n if (!options.pathParameters) {\n return endpoint;\n }\n const pathParams = options.pathParameters;\n for (const [key, param] of Object.entries(pathParams)) {\n if (param === undefined || param === null) {\n throw new Error(`Path parameters ${key} must not be undefined or null`);\n }\n if (!param.toString || typeof param.toString !== \"function\") {\n throw new Error(`Path parameters must be able to be represented as string, ${key} can't`);\n }\n let value = param.toISOString !== undefined ? param.toISOString() : String(param);\n if (!options.skipUrlEncoding) {\n value = encodeURIComponent(param);\n }\n endpoint = replaceAll(endpoint, `{${key}}`, value) ?? \"\";\n }\n return endpoint;\n}\n\nfunction buildRoutePath(\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n for (const pathParam of pathParameters) {\n const allowReserved = typeof pathParam === \"object\" && (pathParam.allowReserved ?? false);\n let value = typeof pathParam === \"object\" ? pathParam.value : pathParam;\n\n if (!options.skipUrlEncoding && !allowReserved) {\n value = encodeURIComponent(value);\n }\n\n routePath = routePath.replace(/\\{[\\w-]+\\}/, String(value));\n }\n return routePath;\n}\n\n/**\n * Replace all of the instances of searchValue in value with the provided replaceValue.\n * @param value - The value to search and replace in.\n * @param searchValue - The value to search for in the value argument.\n * @param replaceValue - The value to replace searchValue with in the value argument.\n * @returns The value where each instance of searchValue was replaced with replacedValue.\n */\nexport function replaceAll(\n value: string | undefined,\n searchValue: string,\n replaceValue: string,\n): string | undefined {\n return !value || !searchValue ? value : value.split(searchValue).join(replaceValue || \"\");\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsCA,SAAS,4BAA4B,GAA4C;AAC/E,QAAM,QAAS,EAAgC;AAC/C,SACE,UAAU,UAAa,MAAM,aAAa,UAAa,OAAO,MAAM,aAAa;AAErF;AAUO,SAAS,gBACd,UACA,WACA,gBACA,UAA6B,CAAC,GACtB;AACR,MAAI,UAAU,WAAW,UAAU,KAAK,UAAU,WAAW,SAAS,GAAG;AACvE,WAAO;AAAA,EACT;AACA,aAAW,aAAa,UAAU,OAAO;
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { PathParameterWithOptions, RequestParameters } from \"./common.js\";\n\ntype QueryParameterStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\n\n/**\n * An object that can be passed as a query parameter, allowing for additional options to be set relating to how the parameter is encoded.\n */\ninterface QueryParameterWithOptions {\n /**\n * The value of the query parameter.\n */\n value: unknown;\n\n /**\n * If set to true, value must be an array. Setting this option to true will cause the array to be encoded as multiple query parameters.\n * Setting it to false will cause the array values to be encoded as a single query parameter, with each value separated by a comma ','.\n *\n * For example, with `explode` set to true, a query parameter named \"foo\" with value [\"a\", \"b\", \"c\"] will be encoded as foo=a&foo=b&foo=c.\n * If `explode` was set to false, the same example would instead be encouded as foo=a,b,c.\n *\n * Defaults to false.\n */\n explode?: boolean;\n\n /**\n * Style for encoding arrays. Three possible values:\n * - \"form\": array values will be separated by a comma \",\" in the query parameter value.\n * - \"spaceDelimited\": array values will be separated by a space (\" \", url-encoded to \"%20\").\n * - \"pipeDelimited\": array values will be separated by a pipe (\"|\").\n *\n * Defaults to \"form\".\n */\n style?: QueryParameterStyle;\n}\n\nfunction isQueryParameterWithOptions(x: unknown): x is QueryParameterWithOptions {\n const value = (x as QueryParameterWithOptions).value as any;\n return (\n value !== undefined && value.toString !== undefined && typeof value.toString === \"function\"\n );\n}\n\n/**\n * Builds the request url, filling in query and path parameters\n * @param endpoint - base url which can be a template url\n * @param routePath - path to append to the endpoint\n * @param pathParameters - values of the path parameters\n * @param options - request parameters including query parameters\n * @returns a full url with path and query parameters\n */\nexport function buildRequestUrl(\n endpoint: string,\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n if (routePath.startsWith(\"https://\") || routePath.startsWith(\"http://\")) {\n return routePath;\n }\n endpoint = buildBaseUrl(endpoint, options);\n // the route could be\n // 1. a path: \"container123/blob456\"\n // 2. a component string from template which starts with \"?\" and may contain more \"?\" after template is expanded,\n // e.g., \"?restype=container&comp=blobs?where=key177196556777405927%3D%27val1177196556777407626%27\"\n const updatedRoutePath = buildRoutePath(routePath, pathParameters, options);\n\n const requestUrl = appendQueryParams(appendPath(endpoint, updatedRoutePath), options);\n const url = new URL(requestUrl);\n\n return url.toString();\n}\n\nfunction appendPath(endpoint: string, pathToAppend: string): string {\n const endpointSearchStart = endpoint.indexOf(\"?\");\n const pathSearchStart = pathToAppend.indexOf(\"?\");\n const endpointParts =\n endpointSearchStart !== -1\n ? [endpoint.substring(0, endpointSearchStart), endpoint.substring(endpointSearchStart + 1)]\n : [endpoint, \"\"];\n const pathParts =\n pathSearchStart !== -1\n ? [pathToAppend.substring(0, pathSearchStart), pathToAppend.substring(pathSearchStart + 1)]\n : [pathToAppend, \"\"];\n\n const combinedSearch = [endpointParts[1], pathParts[1].replaceAll(\"?\", \"&\")]\n .filter(Boolean)\n .join(\"&\");\n const baseEndpoint = endpointParts[0];\n const basePathToAppend = pathParts[0];\n\n let combinedUrl = baseEndpoint;\n if (!baseEndpoint.endsWith(\"/\") && !basePathToAppend.startsWith(\"/\") && basePathToAppend !== \"\") {\n combinedUrl += `/${basePathToAppend}`;\n } else if (baseEndpoint.endsWith(\"/\") && basePathToAppend.startsWith(\"/\")) {\n combinedUrl += basePathToAppend.substring(1);\n } else {\n combinedUrl += basePathToAppend;\n }\n\n if (combinedSearch) {\n combinedUrl += `?${combinedSearch}`;\n }\n\n return combinedUrl;\n}\n\nfunction getQueryParamValue(\n key: string,\n allowReserved: boolean,\n style: QueryParameterStyle,\n param: any,\n): string {\n let separator: string;\n if (style === \"pipeDelimited\") {\n separator = \"|\";\n } else if (style === \"spaceDelimited\") {\n separator = \"%20\";\n } else {\n separator = \",\";\n }\n\n let paramValues: any[];\n if (Array.isArray(param)) {\n paramValues = param;\n } else if (typeof param === \"object\" && param.toString === Object.prototype.toString) {\n // If the parameter is an object without a custom toString implementation (e.g. a Date),\n // then we should deconstruct the object into an array [key1, value1, key2, value2, ...].\n paramValues = Object.entries(param).flat();\n } else {\n paramValues = [param];\n }\n\n const value = paramValues\n .map((p) => {\n if (p === null || p === undefined) {\n return \"\";\n }\n\n if (!p.toString || typeof p.toString !== \"function\") {\n throw new Error(`Query parameters must be able to be represented as string, ${key} can't`);\n }\n\n const rawValue = p.toISOString !== undefined ? p.toISOString() : p.toString();\n return allowReserved ? rawValue : encodeURIComponent(rawValue);\n })\n .join(separator);\n\n return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;\n}\n\n/**\n * Parses a query string into a map of key/value pairs without decoding the values.\n * This avoids the issue where `URL.searchParams` would decode values, potentially\n * corrupting already-encoded values such as SAS signatures.\n */\nfunction simpleParseQueryParams(queryString: string): Map<string, string | string[]> {\n const result = new Map<string, string | string[]>();\n if (!queryString || queryString[0] !== \"?\") {\n return result;\n }\n\n // remove the leading ?\n queryString = queryString.slice(1);\n const pairs = queryString.split(\"&\");\n\n for (const pair of pairs) {\n const eqIndex = pair.indexOf(\"=\");\n const name = eqIndex === -1 ? pair : pair.substring(0, eqIndex);\n const value = eqIndex === -1 ? \"\" : pair.substring(eqIndex + 1);\n\n const existingValue = result.get(name);\n if (existingValue !== undefined) {\n if (Array.isArray(existingValue)) {\n existingValue.push(value);\n } else {\n result.set(name, [existingValue, value]);\n }\n } else {\n result.set(name, value);\n }\n }\n\n return result;\n}\n\n/** @internal */\nexport function appendQueryParams(url: string, options: RequestParameters = {}): string {\n if (!options.queryParameters) {\n return url;\n }\n const parsedUrl = new URL(url);\n const queryParams = options.queryParameters;\n\n // Parse existing query params from the URL manually to avoid re-encoding issues\n const existingParams = simpleParseQueryParams(parsedUrl.search);\n\n const newParamStrings: string[] = [];\n for (const key of Object.keys(queryParams)) {\n const param = queryParams[key] as any;\n if (param === undefined || param === null) {\n continue;\n }\n\n const hasMetadata = isQueryParameterWithOptions(param);\n const rawValue = hasMetadata ? param.value : param;\n const explode = hasMetadata ? (param.explode ?? false) : false;\n const style = hasMetadata && param.style ? param.style : \"form\";\n\n if (explode) {\n if (Array.isArray(rawValue)) {\n for (const item of rawValue) {\n newParamStrings.push(\n getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item),\n );\n }\n } else if (typeof rawValue === \"object\") {\n // For object explode, the name of the query parameter is ignored and we use the object key instead\n for (const [actualKey, value] of Object.entries(rawValue)) {\n newParamStrings.push(\n getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value),\n );\n }\n } else {\n // Explode doesn't really make sense for primitives\n throw new Error(\"explode can only be set to true for objects and arrays\");\n }\n } else {\n newParamStrings.push(\n getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue),\n );\n }\n }\n\n // Merge new params into existing params, deduplicating values for the same key\n for (const paramString of newParamStrings) {\n const eqIndex = paramString.indexOf(\"=\");\n const name = paramString.substring(0, eqIndex);\n const value = paramString.substring(eqIndex + 1);\n\n const existingValue = existingParams.get(name);\n if (existingValue !== undefined) {\n if (Array.isArray(existingValue)) {\n if (!existingValue.includes(value)) {\n existingValue.push(value);\n }\n } else if (existingValue !== value) {\n existingParams.set(name, [existingValue, value]);\n }\n // if existingValue === value (single string match), no change needed\n } else {\n existingParams.set(name, value);\n }\n }\n\n // Reconstruct the search string manually to avoid URL re-encoding\n const searchPieces: string[] = [];\n for (const [name, value] of existingParams) {\n if (Array.isArray(value)) {\n for (const subValue of value) {\n searchPieces.push(`${name}=${subValue}`);\n }\n } else {\n searchPieces.push(`${name}=${value}`);\n }\n }\n\n parsedUrl.search = searchPieces.length ? `?${searchPieces.join(\"&\")}` : \"\";\n return parsedUrl.toString();\n}\n\nexport function buildBaseUrl(endpoint: string, options: RequestParameters): string {\n if (!options.pathParameters) {\n return endpoint;\n }\n const pathParams = options.pathParameters;\n for (const [key, param] of Object.entries(pathParams)) {\n if (param === undefined || param === null) {\n throw new Error(`Path parameters ${key} must not be undefined or null`);\n }\n if (!param.toString || typeof param.toString !== \"function\") {\n throw new Error(`Path parameters must be able to be represented as string, ${key} can't`);\n }\n let value = param.toISOString !== undefined ? param.toISOString() : String(param);\n if (!options.skipUrlEncoding) {\n value = encodeURIComponent(param);\n }\n endpoint = replaceAll(endpoint, `{${key}}`, value) ?? \"\";\n }\n return endpoint;\n}\n\nfunction buildRoutePath(\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n for (const pathParam of pathParameters) {\n const allowReserved = typeof pathParam === \"object\" && (pathParam.allowReserved ?? false);\n let value = typeof pathParam === \"object\" ? pathParam.value : pathParam;\n\n if (!options.skipUrlEncoding && !allowReserved) {\n value = encodeURIComponent(value);\n }\n\n routePath = routePath.replace(/\\{[\\w-]+\\}/, String(value));\n }\n return routePath;\n}\n\n/**\n * Replace all of the instances of searchValue in value with the provided replaceValue.\n * @param value - The value to search and replace in.\n * @param searchValue - The value to search for in the value argument.\n * @param replaceValue - The value to replace searchValue with in the value argument.\n * @returns The value where each instance of searchValue was replaced with replacedValue.\n */\nexport function replaceAll(\n value: string | undefined,\n searchValue: string,\n replaceValue: string,\n): string | undefined {\n return !value || !searchValue ? value : value.split(searchValue).join(replaceValue || \"\");\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -8,6 +8,8 @@ import type { PathParameterWithOptions, RequestParameters } from "./common.js";
|
|
|
8
8
|
* @returns a full url with path and query parameters
|
|
9
9
|
*/
|
|
10
10
|
export declare function buildRequestUrl(endpoint: string, routePath: string, pathParameters: (string | number | PathParameterWithOptions)[], options?: RequestParameters): string;
|
|
11
|
+
/** @internal */
|
|
12
|
+
export declare function appendQueryParams(url: string, options?: RequestParameters): string;
|
|
11
13
|
export declare function buildBaseUrl(endpoint: string, options: RequestParameters): string;
|
|
12
14
|
/**
|
|
13
15
|
* Replace all of the instances of searchValue in value with the provided replaceValue.
|
|
@@ -17,13 +17,43 @@ export function buildRequestUrl(endpoint, routePath, pathParameters, options = {
|
|
|
17
17
|
return routePath;
|
|
18
18
|
}
|
|
19
19
|
endpoint = buildBaseUrl(endpoint, options);
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
// the route could be
|
|
21
|
+
// 1. a path: "container123/blob456"
|
|
22
|
+
// 2. a component string from template which starts with "?" and may contain more "?" after template is expanded,
|
|
23
|
+
// e.g., "?restype=container&comp=blobs?where=key177196556777405927%3D%27val1177196556777407626%27"
|
|
24
|
+
const updatedRoutePath = buildRoutePath(routePath, pathParameters, options);
|
|
25
|
+
const requestUrl = appendQueryParams(appendPath(endpoint, updatedRoutePath), options);
|
|
22
26
|
const url = new URL(requestUrl);
|
|
23
|
-
return (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
return url.toString();
|
|
28
|
+
}
|
|
29
|
+
function appendPath(endpoint, pathToAppend) {
|
|
30
|
+
const endpointSearchStart = endpoint.indexOf("?");
|
|
31
|
+
const pathSearchStart = pathToAppend.indexOf("?");
|
|
32
|
+
const endpointParts = endpointSearchStart !== -1
|
|
33
|
+
? [endpoint.substring(0, endpointSearchStart), endpoint.substring(endpointSearchStart + 1)]
|
|
34
|
+
: [endpoint, ""];
|
|
35
|
+
const pathParts = pathSearchStart !== -1
|
|
36
|
+
? [pathToAppend.substring(0, pathSearchStart), pathToAppend.substring(pathSearchStart + 1)]
|
|
37
|
+
: [pathToAppend, ""];
|
|
38
|
+
const combinedSearch = [endpointParts[1], pathParts[1].replaceAll("?", "&")]
|
|
39
|
+
.filter(Boolean)
|
|
40
|
+
.join("&");
|
|
41
|
+
const baseEndpoint = endpointParts[0];
|
|
42
|
+
const basePathToAppend = pathParts[0];
|
|
43
|
+
let combinedUrl = baseEndpoint;
|
|
44
|
+
if (!baseEndpoint.endsWith("/") && !basePathToAppend.startsWith("/") && basePathToAppend !== "") {
|
|
45
|
+
combinedUrl += `/${basePathToAppend}`;
|
|
46
|
+
}
|
|
47
|
+
else if (baseEndpoint.endsWith("/") && basePathToAppend.startsWith("/")) {
|
|
48
|
+
combinedUrl += basePathToAppend.substring(1);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
combinedUrl += basePathToAppend;
|
|
52
|
+
}
|
|
53
|
+
if (combinedSearch) {
|
|
54
|
+
combinedUrl += `?${combinedSearch}`;
|
|
55
|
+
}
|
|
56
|
+
return combinedUrl;
|
|
27
57
|
}
|
|
28
58
|
function getQueryParamValue(key, allowReserved, style, param) {
|
|
29
59
|
let separator;
|
|
@@ -62,13 +92,48 @@ function getQueryParamValue(key, allowReserved, style, param) {
|
|
|
62
92
|
.join(separator);
|
|
63
93
|
return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;
|
|
64
94
|
}
|
|
65
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Parses a query string into a map of key/value pairs without decoding the values.
|
|
97
|
+
* This avoids the issue where `URL.searchParams` would decode values, potentially
|
|
98
|
+
* corrupting already-encoded values such as SAS signatures.
|
|
99
|
+
*/
|
|
100
|
+
function simpleParseQueryParams(queryString) {
|
|
101
|
+
const result = new Map();
|
|
102
|
+
if (!queryString || queryString[0] !== "?") {
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
// remove the leading ?
|
|
106
|
+
queryString = queryString.slice(1);
|
|
107
|
+
const pairs = queryString.split("&");
|
|
108
|
+
for (const pair of pairs) {
|
|
109
|
+
const eqIndex = pair.indexOf("=");
|
|
110
|
+
const name = eqIndex === -1 ? pair : pair.substring(0, eqIndex);
|
|
111
|
+
const value = eqIndex === -1 ? "" : pair.substring(eqIndex + 1);
|
|
112
|
+
const existingValue = result.get(name);
|
|
113
|
+
if (existingValue !== undefined) {
|
|
114
|
+
if (Array.isArray(existingValue)) {
|
|
115
|
+
existingValue.push(value);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
result.set(name, [existingValue, value]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
result.set(name, value);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
/** @internal */
|
|
128
|
+
export function appendQueryParams(url, options = {}) {
|
|
66
129
|
if (!options.queryParameters) {
|
|
67
130
|
return url;
|
|
68
131
|
}
|
|
69
132
|
const parsedUrl = new URL(url);
|
|
70
133
|
const queryParams = options.queryParameters;
|
|
71
|
-
|
|
134
|
+
// Parse existing query params from the URL manually to avoid re-encoding issues
|
|
135
|
+
const existingParams = simpleParseQueryParams(parsedUrl.search);
|
|
136
|
+
const newParamStrings = [];
|
|
72
137
|
for (const key of Object.keys(queryParams)) {
|
|
73
138
|
const param = queryParams[key];
|
|
74
139
|
if (param === undefined || param === null) {
|
|
@@ -81,13 +146,13 @@ function appendQueryParams(url, options = {}) {
|
|
|
81
146
|
if (explode) {
|
|
82
147
|
if (Array.isArray(rawValue)) {
|
|
83
148
|
for (const item of rawValue) {
|
|
84
|
-
|
|
149
|
+
newParamStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item));
|
|
85
150
|
}
|
|
86
151
|
}
|
|
87
152
|
else if (typeof rawValue === "object") {
|
|
88
153
|
// For object explode, the name of the query parameter is ignored and we use the object key instead
|
|
89
154
|
for (const [actualKey, value] of Object.entries(rawValue)) {
|
|
90
|
-
|
|
155
|
+
newParamStrings.push(getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value));
|
|
91
156
|
}
|
|
92
157
|
}
|
|
93
158
|
else {
|
|
@@ -96,13 +161,43 @@ function appendQueryParams(url, options = {}) {
|
|
|
96
161
|
}
|
|
97
162
|
}
|
|
98
163
|
else {
|
|
99
|
-
|
|
164
|
+
newParamStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Merge new params into existing params, deduplicating values for the same key
|
|
168
|
+
for (const paramString of newParamStrings) {
|
|
169
|
+
const eqIndex = paramString.indexOf("=");
|
|
170
|
+
const name = paramString.substring(0, eqIndex);
|
|
171
|
+
const value = paramString.substring(eqIndex + 1);
|
|
172
|
+
const existingValue = existingParams.get(name);
|
|
173
|
+
if (existingValue !== undefined) {
|
|
174
|
+
if (Array.isArray(existingValue)) {
|
|
175
|
+
if (!existingValue.includes(value)) {
|
|
176
|
+
existingValue.push(value);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else if (existingValue !== value) {
|
|
180
|
+
existingParams.set(name, [existingValue, value]);
|
|
181
|
+
}
|
|
182
|
+
// if existingValue === value (single string match), no change needed
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
existingParams.set(name, value);
|
|
100
186
|
}
|
|
101
187
|
}
|
|
102
|
-
|
|
103
|
-
|
|
188
|
+
// Reconstruct the search string manually to avoid URL re-encoding
|
|
189
|
+
const searchPieces = [];
|
|
190
|
+
for (const [name, value] of existingParams) {
|
|
191
|
+
if (Array.isArray(value)) {
|
|
192
|
+
for (const subValue of value) {
|
|
193
|
+
searchPieces.push(`${name}=${subValue}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
searchPieces.push(`${name}=${value}`);
|
|
198
|
+
}
|
|
104
199
|
}
|
|
105
|
-
parsedUrl.search
|
|
200
|
+
parsedUrl.search = searchPieces.length ? `?${searchPieces.join("&")}` : "";
|
|
106
201
|
return parsedUrl.toString();
|
|
107
202
|
}
|
|
108
203
|
export function buildBaseUrl(endpoint, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urlHelpers.js","sourceRoot":"","sources":["../../../src/client/urlHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { PathParameterWithOptions, RequestParameters } from \"./common.js\";\n\ntype QueryParameterStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\n\n/**\n * An object that can be passed as a query parameter, allowing for additional options to be set relating to how the parameter is encoded.\n */\ninterface QueryParameterWithOptions {\n /**\n * The value of the query parameter.\n */\n value: unknown;\n\n /**\n * If set to true, value must be an array. Setting this option to true will cause the array to be encoded as multiple query parameters.\n * Setting it to false will cause the array values to be encoded as a single query parameter, with each value separated by a comma ','.\n *\n * For example, with `explode` set to true, a query parameter named \"foo\" with value [\"a\", \"b\", \"c\"] will be encoded as foo=a&foo=b&foo=c.\n * If `explode` was set to false, the same example would instead be encouded as foo=a,b,c.\n *\n * Defaults to false.\n */\n explode?: boolean;\n\n /**\n * Style for encoding arrays. Three possible values:\n * - \"form\": array values will be separated by a comma \",\" in the query parameter value.\n * - \"spaceDelimited\": array values will be separated by a space (\" \", url-encoded to \"%20\").\n * - \"pipeDelimited\": array values will be separated by a pipe (\"|\").\n *\n * Defaults to \"form\".\n */\n style?: QueryParameterStyle;\n}\n\nfunction isQueryParameterWithOptions(x: unknown): x is QueryParameterWithOptions {\n const value = (x as QueryParameterWithOptions).value as any;\n return (\n value !== undefined && value.toString !== undefined && typeof value.toString === \"function\"\n );\n}\n\n/**\n * Builds the request url, filling in query and path parameters\n * @param endpoint - base url which can be a template url\n * @param routePath - path to append to the endpoint\n * @param pathParameters - values of the path parameters\n * @param options - request parameters including query parameters\n * @returns a full url with path and query parameters\n */\nexport function buildRequestUrl(\n endpoint: string,\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n if (routePath.startsWith(\"https://\") || routePath.startsWith(\"http://\")) {\n return routePath;\n }\n endpoint = buildBaseUrl(endpoint, options);\n routePath = buildRoutePath(routePath, pathParameters, options);\n const requestUrl = appendQueryParams(`${endpoint}/${routePath}`, options);\n const url = new URL(requestUrl);\n\n return (\n url\n .toString()\n // Remove double forward slashes\n .replace(/([^:]\\/)\\/+/g, \"$1\")\n );\n}\n\nfunction getQueryParamValue(\n key: string,\n allowReserved: boolean,\n style: QueryParameterStyle,\n param: any,\n): string {\n let separator: string;\n if (style === \"pipeDelimited\") {\n separator = \"|\";\n } else if (style === \"spaceDelimited\") {\n separator = \"%20\";\n } else {\n separator = \",\";\n }\n\n let paramValues: any[];\n if (Array.isArray(param)) {\n paramValues = param;\n } else if (typeof param === \"object\" && param.toString === Object.prototype.toString) {\n // If the parameter is an object without a custom toString implementation (e.g. a Date),\n // then we should deconstruct the object into an array [key1, value1, key2, value2, ...].\n paramValues = Object.entries(param).flat();\n } else {\n paramValues = [param];\n }\n\n const value = paramValues\n .map((p) => {\n if (p === null || p === undefined) {\n return \"\";\n }\n\n if (!p.toString || typeof p.toString !== \"function\") {\n throw new Error(`Query parameters must be able to be represented as string, ${key} can't`);\n }\n\n const rawValue = p.toISOString !== undefined ? p.toISOString() : p.toString();\n return allowReserved ? rawValue : encodeURIComponent(rawValue);\n })\n .join(separator);\n\n return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;\n}\n\nfunction appendQueryParams(url: string, options: RequestParameters = {}): string {\n if (!options.queryParameters) {\n return url;\n }\n const parsedUrl = new URL(url);\n const queryParams = options.queryParameters;\n\n const paramStrings: string[] = [];\n for (const key of Object.keys(queryParams)) {\n const param = queryParams[key] as any;\n if (param === undefined || param === null) {\n continue;\n }\n\n const hasMetadata = isQueryParameterWithOptions(param);\n const rawValue = hasMetadata ? param.value : param;\n const explode = hasMetadata ? (param.explode ?? false) : false;\n const style = hasMetadata && param.style ? param.style : \"form\";\n\n if (explode) {\n if (Array.isArray(rawValue)) {\n for (const item of rawValue) {\n paramStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item));\n }\n } else if (typeof rawValue === \"object\") {\n // For object explode, the name of the query parameter is ignored and we use the object key instead\n for (const [actualKey, value] of Object.entries(rawValue)) {\n paramStrings.push(\n getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value),\n );\n }\n } else {\n // Explode doesn't really make sense for primitives\n throw new Error(\"explode can only be set to true for objects and arrays\");\n }\n } else {\n paramStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue));\n }\n }\n\n if (parsedUrl.search !== \"\") {\n parsedUrl.search += \"&\";\n }\n parsedUrl.search += paramStrings.join(\"&\");\n return parsedUrl.toString();\n}\n\nexport function buildBaseUrl(endpoint: string, options: RequestParameters): string {\n if (!options.pathParameters) {\n return endpoint;\n }\n const pathParams = options.pathParameters;\n for (const [key, param] of Object.entries(pathParams)) {\n if (param === undefined || param === null) {\n throw new Error(`Path parameters ${key} must not be undefined or null`);\n }\n if (!param.toString || typeof param.toString !== \"function\") {\n throw new Error(`Path parameters must be able to be represented as string, ${key} can't`);\n }\n let value = param.toISOString !== undefined ? param.toISOString() : String(param);\n if (!options.skipUrlEncoding) {\n value = encodeURIComponent(param);\n }\n endpoint = replaceAll(endpoint, `{${key}}`, value) ?? \"\";\n }\n return endpoint;\n}\n\nfunction buildRoutePath(\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n for (const pathParam of pathParameters) {\n const allowReserved = typeof pathParam === \"object\" && (pathParam.allowReserved ?? false);\n let value = typeof pathParam === \"object\" ? pathParam.value : pathParam;\n\n if (!options.skipUrlEncoding && !allowReserved) {\n value = encodeURIComponent(value);\n }\n\n routePath = routePath.replace(/\\{[\\w-]+\\}/, String(value));\n }\n return routePath;\n}\n\n/**\n * Replace all of the instances of searchValue in value with the provided replaceValue.\n * @param value - The value to search and replace in.\n * @param searchValue - The value to search for in the value argument.\n * @param replaceValue - The value to replace searchValue with in the value argument.\n * @returns The value where each instance of searchValue was replaced with replacedValue.\n */\nexport function replaceAll(\n value: string | undefined,\n searchValue: string,\n replaceValue: string,\n): string | undefined {\n return !value || !searchValue ? value : value.split(searchValue).join(replaceValue || \"\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"urlHelpers.js","sourceRoot":"","sources":["../../../src/client/urlHelpers.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAqClC,SAAS,2BAA2B,CAAC,CAAU;IAC7C,MAAM,KAAK,GAAI,CAA+B,CAAC,KAAY,CAAC;IAC5D,OAAO,CACL,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,UAAU,CAC5F,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,SAAiB,EACjB,cAA8D,EAC9D,UAA6B,EAAE;IAE/B,IAAI,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACxE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3C,qBAAqB;IACrB,sCAAsC;IACtC,mHAAmH;IACnH,wGAAwG;IACxG,MAAM,gBAAgB,GAAG,cAAc,CAAC,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IAE5E,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAU,CAAC,QAAQ,EAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC,CAAC;IACtF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAEhC,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB,EAAE,YAAoB;IACxD,MAAM,mBAAmB,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,eAAe,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,aAAa,GACjB,mBAAmB,KAAK,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,mBAAmB,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAC;QAC3F,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACrB,MAAM,SAAS,GACb,eAAe,KAAK,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,eAAe,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;QAC3F,CAAC,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAEzB,MAAM,cAAc,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;SACzE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,gBAAgB,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAEtC,IAAI,WAAW,GAAG,YAAY,CAAC;IAC/B,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,gBAAgB,KAAK,EAAE,EAAE,CAAC;QAChG,WAAW,IAAI,IAAI,gBAAgB,EAAE,CAAC;IACxC,CAAC;SAAM,IAAI,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,gBAAgB,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1E,WAAW,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,WAAW,IAAI,gBAAgB,CAAC;IAClC,CAAC;IAED,IAAI,cAAc,EAAE,CAAC;QACnB,WAAW,IAAI,IAAI,cAAc,EAAE,CAAC;IACtC,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,kBAAkB,CACzB,GAAW,EACX,aAAsB,EACtB,KAA0B,EAC1B,KAAU;IAEV,IAAI,SAAiB,CAAC;IACtB,IAAI,KAAK,KAAK,eAAe,EAAE,CAAC;QAC9B,SAAS,GAAG,GAAG,CAAC;IAClB,CAAC;SAAM,IAAI,KAAK,KAAK,gBAAgB,EAAE,CAAC;QACtC,SAAS,GAAG,KAAK,CAAC;IACpB,CAAC;SAAM,CAAC;QACN,SAAS,GAAG,GAAG,CAAC;IAClB,CAAC;IAED,IAAI,WAAkB,CAAC;IACvB,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,WAAW,GAAG,KAAK,CAAC;IACtB,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;QACrF,wFAAwF;QACxF,yFAAyF;QACzF,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,KAAK,GAAG,WAAW;SACtB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YAClC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,8DAA8D,GAAG,QAAQ,CAAC,CAAC;QAC7F,CAAC;QAED,MAAM,QAAQ,GAAG,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC9E,OAAO,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACjE,CAAC,CAAC;SACD,IAAI,CAAC,SAAS,CAAC,CAAC;IAEnB,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,SAAS,sBAAsB,CAAC,WAAmB;IACjD,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;IACpD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QAC3C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,uBAAuB;IACvB,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAChE,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;QAEhE,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;gBACjC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC5B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,UAA6B,EAAE;IAC5E,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC;IACb,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC;IAE5C,gFAAgF;IAChF,MAAM,cAAc,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEhE,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAQ,CAAC;QACtC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC1C,SAAS;QACX,CAAC;QAED,MAAM,WAAW,GAAG,2BAA2B,CAAC,KAAK,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;QACnD,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/D,MAAM,KAAK,GAAG,WAAW,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAEhE,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;oBAC5B,eAAe,CAAC,IAAI,CAClB,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,eAAe,IAAI,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CACvE,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACxC,mGAAmG;gBACnG,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC1D,eAAe,CAAC,IAAI,CAClB,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,eAAe,IAAI,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAC9E,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,mDAAmD;gBACnD,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;aAAM,CAAC;YACN,eAAe,CAAC,IAAI,CAClB,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,eAAe,IAAI,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,+EAA+E;IAC/E,KAAK,MAAM,WAAW,IAAI,eAAe,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,aAAa,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;iBAAM,IAAI,aAAa,KAAK,KAAK,EAAE,CAAC;gBACnC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC;YACnD,CAAC;YACD,qEAAqE;QACvE,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,cAAc,EAAE,CAAC;QAC3C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;gBAC7B,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,QAAQ,EAAE,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,SAAS,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3E,OAAO,SAAS,CAAC,QAAQ,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,OAA0B;IACvE,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC5B,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,gCAAgC,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;YAC5D,MAAM,IAAI,KAAK,CAAC,6DAA6D,GAAG,QAAQ,CAAC,CAAC;QAC5F,CAAC;QACD,IAAI,KAAK,GAAG,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClF,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;YAC7B,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QACD,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,GAAG,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IAC3D,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CACrB,SAAiB,EACjB,cAA8D,EAC9D,UAA6B,EAAE;IAE/B,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE,CAAC;QACvC,MAAM,aAAa,GAAG,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,KAAK,CAAC,CAAC;QAC1F,IAAI,KAAK,GAAG,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QAExE,IAAI,CAAC,OAAO,CAAC,eAAe,IAAI,CAAC,aAAa,EAAE,CAAC;YAC/C,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QAED,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CACxB,KAAyB,EACzB,WAAmB,EACnB,YAAoB;IAEpB,OAAO,CAAC,KAAK,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;AAC5F,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { PathParameterWithOptions, RequestParameters } from \"./common.js\";\n\ntype QueryParameterStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\n\n/**\n * An object that can be passed as a query parameter, allowing for additional options to be set relating to how the parameter is encoded.\n */\ninterface QueryParameterWithOptions {\n /**\n * The value of the query parameter.\n */\n value: unknown;\n\n /**\n * If set to true, value must be an array. Setting this option to true will cause the array to be encoded as multiple query parameters.\n * Setting it to false will cause the array values to be encoded as a single query parameter, with each value separated by a comma ','.\n *\n * For example, with `explode` set to true, a query parameter named \"foo\" with value [\"a\", \"b\", \"c\"] will be encoded as foo=a&foo=b&foo=c.\n * If `explode` was set to false, the same example would instead be encouded as foo=a,b,c.\n *\n * Defaults to false.\n */\n explode?: boolean;\n\n /**\n * Style for encoding arrays. Three possible values:\n * - \"form\": array values will be separated by a comma \",\" in the query parameter value.\n * - \"spaceDelimited\": array values will be separated by a space (\" \", url-encoded to \"%20\").\n * - \"pipeDelimited\": array values will be separated by a pipe (\"|\").\n *\n * Defaults to \"form\".\n */\n style?: QueryParameterStyle;\n}\n\nfunction isQueryParameterWithOptions(x: unknown): x is QueryParameterWithOptions {\n const value = (x as QueryParameterWithOptions).value as any;\n return (\n value !== undefined && value.toString !== undefined && typeof value.toString === \"function\"\n );\n}\n\n/**\n * Builds the request url, filling in query and path parameters\n * @param endpoint - base url which can be a template url\n * @param routePath - path to append to the endpoint\n * @param pathParameters - values of the path parameters\n * @param options - request parameters including query parameters\n * @returns a full url with path and query parameters\n */\nexport function buildRequestUrl(\n endpoint: string,\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n if (routePath.startsWith(\"https://\") || routePath.startsWith(\"http://\")) {\n return routePath;\n }\n endpoint = buildBaseUrl(endpoint, options);\n // the route could be\n // 1. a path: \"container123/blob456\"\n // 2. a component string from template which starts with \"?\" and may contain more \"?\" after template is expanded,\n // e.g., \"?restype=container&comp=blobs?where=key177196556777405927%3D%27val1177196556777407626%27\"\n const updatedRoutePath = buildRoutePath(routePath, pathParameters, options);\n\n const requestUrl = appendQueryParams(appendPath(endpoint, updatedRoutePath), options);\n const url = new URL(requestUrl);\n\n return url.toString();\n}\n\nfunction appendPath(endpoint: string, pathToAppend: string): string {\n const endpointSearchStart = endpoint.indexOf(\"?\");\n const pathSearchStart = pathToAppend.indexOf(\"?\");\n const endpointParts =\n endpointSearchStart !== -1\n ? [endpoint.substring(0, endpointSearchStart), endpoint.substring(endpointSearchStart + 1)]\n : [endpoint, \"\"];\n const pathParts =\n pathSearchStart !== -1\n ? [pathToAppend.substring(0, pathSearchStart), pathToAppend.substring(pathSearchStart + 1)]\n : [pathToAppend, \"\"];\n\n const combinedSearch = [endpointParts[1], pathParts[1].replaceAll(\"?\", \"&\")]\n .filter(Boolean)\n .join(\"&\");\n const baseEndpoint = endpointParts[0];\n const basePathToAppend = pathParts[0];\n\n let combinedUrl = baseEndpoint;\n if (!baseEndpoint.endsWith(\"/\") && !basePathToAppend.startsWith(\"/\") && basePathToAppend !== \"\") {\n combinedUrl += `/${basePathToAppend}`;\n } else if (baseEndpoint.endsWith(\"/\") && basePathToAppend.startsWith(\"/\")) {\n combinedUrl += basePathToAppend.substring(1);\n } else {\n combinedUrl += basePathToAppend;\n }\n\n if (combinedSearch) {\n combinedUrl += `?${combinedSearch}`;\n }\n\n return combinedUrl;\n}\n\nfunction getQueryParamValue(\n key: string,\n allowReserved: boolean,\n style: QueryParameterStyle,\n param: any,\n): string {\n let separator: string;\n if (style === \"pipeDelimited\") {\n separator = \"|\";\n } else if (style === \"spaceDelimited\") {\n separator = \"%20\";\n } else {\n separator = \",\";\n }\n\n let paramValues: any[];\n if (Array.isArray(param)) {\n paramValues = param;\n } else if (typeof param === \"object\" && param.toString === Object.prototype.toString) {\n // If the parameter is an object without a custom toString implementation (e.g. a Date),\n // then we should deconstruct the object into an array [key1, value1, key2, value2, ...].\n paramValues = Object.entries(param).flat();\n } else {\n paramValues = [param];\n }\n\n const value = paramValues\n .map((p) => {\n if (p === null || p === undefined) {\n return \"\";\n }\n\n if (!p.toString || typeof p.toString !== \"function\") {\n throw new Error(`Query parameters must be able to be represented as string, ${key} can't`);\n }\n\n const rawValue = p.toISOString !== undefined ? p.toISOString() : p.toString();\n return allowReserved ? rawValue : encodeURIComponent(rawValue);\n })\n .join(separator);\n\n return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;\n}\n\n/**\n * Parses a query string into a map of key/value pairs without decoding the values.\n * This avoids the issue where `URL.searchParams` would decode values, potentially\n * corrupting already-encoded values such as SAS signatures.\n */\nfunction simpleParseQueryParams(queryString: string): Map<string, string | string[]> {\n const result = new Map<string, string | string[]>();\n if (!queryString || queryString[0] !== \"?\") {\n return result;\n }\n\n // remove the leading ?\n queryString = queryString.slice(1);\n const pairs = queryString.split(\"&\");\n\n for (const pair of pairs) {\n const eqIndex = pair.indexOf(\"=\");\n const name = eqIndex === -1 ? pair : pair.substring(0, eqIndex);\n const value = eqIndex === -1 ? \"\" : pair.substring(eqIndex + 1);\n\n const existingValue = result.get(name);\n if (existingValue !== undefined) {\n if (Array.isArray(existingValue)) {\n existingValue.push(value);\n } else {\n result.set(name, [existingValue, value]);\n }\n } else {\n result.set(name, value);\n }\n }\n\n return result;\n}\n\n/** @internal */\nexport function appendQueryParams(url: string, options: RequestParameters = {}): string {\n if (!options.queryParameters) {\n return url;\n }\n const parsedUrl = new URL(url);\n const queryParams = options.queryParameters;\n\n // Parse existing query params from the URL manually to avoid re-encoding issues\n const existingParams = simpleParseQueryParams(parsedUrl.search);\n\n const newParamStrings: string[] = [];\n for (const key of Object.keys(queryParams)) {\n const param = queryParams[key] as any;\n if (param === undefined || param === null) {\n continue;\n }\n\n const hasMetadata = isQueryParameterWithOptions(param);\n const rawValue = hasMetadata ? param.value : param;\n const explode = hasMetadata ? (param.explode ?? false) : false;\n const style = hasMetadata && param.style ? param.style : \"form\";\n\n if (explode) {\n if (Array.isArray(rawValue)) {\n for (const item of rawValue) {\n newParamStrings.push(\n getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item),\n );\n }\n } else if (typeof rawValue === \"object\") {\n // For object explode, the name of the query parameter is ignored and we use the object key instead\n for (const [actualKey, value] of Object.entries(rawValue)) {\n newParamStrings.push(\n getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value),\n );\n }\n } else {\n // Explode doesn't really make sense for primitives\n throw new Error(\"explode can only be set to true for objects and arrays\");\n }\n } else {\n newParamStrings.push(\n getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue),\n );\n }\n }\n\n // Merge new params into existing params, deduplicating values for the same key\n for (const paramString of newParamStrings) {\n const eqIndex = paramString.indexOf(\"=\");\n const name = paramString.substring(0, eqIndex);\n const value = paramString.substring(eqIndex + 1);\n\n const existingValue = existingParams.get(name);\n if (existingValue !== undefined) {\n if (Array.isArray(existingValue)) {\n if (!existingValue.includes(value)) {\n existingValue.push(value);\n }\n } else if (existingValue !== value) {\n existingParams.set(name, [existingValue, value]);\n }\n // if existingValue === value (single string match), no change needed\n } else {\n existingParams.set(name, value);\n }\n }\n\n // Reconstruct the search string manually to avoid URL re-encoding\n const searchPieces: string[] = [];\n for (const [name, value] of existingParams) {\n if (Array.isArray(value)) {\n for (const subValue of value) {\n searchPieces.push(`${name}=${subValue}`);\n }\n } else {\n searchPieces.push(`${name}=${value}`);\n }\n }\n\n parsedUrl.search = searchPieces.length ? `?${searchPieces.join(\"&\")}` : \"\";\n return parsedUrl.toString();\n}\n\nexport function buildBaseUrl(endpoint: string, options: RequestParameters): string {\n if (!options.pathParameters) {\n return endpoint;\n }\n const pathParams = options.pathParameters;\n for (const [key, param] of Object.entries(pathParams)) {\n if (param === undefined || param === null) {\n throw new Error(`Path parameters ${key} must not be undefined or null`);\n }\n if (!param.toString || typeof param.toString !== \"function\") {\n throw new Error(`Path parameters must be able to be represented as string, ${key} can't`);\n }\n let value = param.toISOString !== undefined ? param.toISOString() : String(param);\n if (!options.skipUrlEncoding) {\n value = encodeURIComponent(param);\n }\n endpoint = replaceAll(endpoint, `{${key}}`, value) ?? \"\";\n }\n return endpoint;\n}\n\nfunction buildRoutePath(\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n for (const pathParam of pathParameters) {\n const allowReserved = typeof pathParam === \"object\" && (pathParam.allowReserved ?? false);\n let value = typeof pathParam === \"object\" ? pathParam.value : pathParam;\n\n if (!options.skipUrlEncoding && !allowReserved) {\n value = encodeURIComponent(value);\n }\n\n routePath = routePath.replace(/\\{[\\w-]+\\}/, String(value));\n }\n return routePath;\n}\n\n/**\n * Replace all of the instances of searchValue in value with the provided replaceValue.\n * @param value - The value to search and replace in.\n * @param searchValue - The value to search for in the value argument.\n * @param replaceValue - The value to replace searchValue with in the value argument.\n * @returns The value where each instance of searchValue was replaced with replacedValue.\n */\nexport function replaceAll(\n value: string | undefined,\n searchValue: string,\n replaceValue: string,\n): string | undefined {\n return !value || !searchValue ? value : value.split(searchValue).join(replaceValue || \"\");\n}\n"]}
|
|
@@ -8,6 +8,8 @@ import type { PathParameterWithOptions, RequestParameters } from "./common.js";
|
|
|
8
8
|
* @returns a full url with path and query parameters
|
|
9
9
|
*/
|
|
10
10
|
export declare function buildRequestUrl(endpoint: string, routePath: string, pathParameters: (string | number | PathParameterWithOptions)[], options?: RequestParameters): string;
|
|
11
|
+
/** @internal */
|
|
12
|
+
export declare function appendQueryParams(url: string, options?: RequestParameters): string;
|
|
11
13
|
export declare function buildBaseUrl(endpoint: string, options: RequestParameters): string;
|
|
12
14
|
/**
|
|
13
15
|
* Replace all of the instances of searchValue in value with the provided replaceValue.
|
|
@@ -17,13 +17,43 @@ export function buildRequestUrl(endpoint, routePath, pathParameters, options = {
|
|
|
17
17
|
return routePath;
|
|
18
18
|
}
|
|
19
19
|
endpoint = buildBaseUrl(endpoint, options);
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
// the route could be
|
|
21
|
+
// 1. a path: "container123/blob456"
|
|
22
|
+
// 2. a component string from template which starts with "?" and may contain more "?" after template is expanded,
|
|
23
|
+
// e.g., "?restype=container&comp=blobs?where=key177196556777405927%3D%27val1177196556777407626%27"
|
|
24
|
+
const updatedRoutePath = buildRoutePath(routePath, pathParameters, options);
|
|
25
|
+
const requestUrl = appendQueryParams(appendPath(endpoint, updatedRoutePath), options);
|
|
22
26
|
const url = new URL(requestUrl);
|
|
23
|
-
return (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
return url.toString();
|
|
28
|
+
}
|
|
29
|
+
function appendPath(endpoint, pathToAppend) {
|
|
30
|
+
const endpointSearchStart = endpoint.indexOf("?");
|
|
31
|
+
const pathSearchStart = pathToAppend.indexOf("?");
|
|
32
|
+
const endpointParts = endpointSearchStart !== -1
|
|
33
|
+
? [endpoint.substring(0, endpointSearchStart), endpoint.substring(endpointSearchStart + 1)]
|
|
34
|
+
: [endpoint, ""];
|
|
35
|
+
const pathParts = pathSearchStart !== -1
|
|
36
|
+
? [pathToAppend.substring(0, pathSearchStart), pathToAppend.substring(pathSearchStart + 1)]
|
|
37
|
+
: [pathToAppend, ""];
|
|
38
|
+
const combinedSearch = [endpointParts[1], pathParts[1].replaceAll("?", "&")]
|
|
39
|
+
.filter(Boolean)
|
|
40
|
+
.join("&");
|
|
41
|
+
const baseEndpoint = endpointParts[0];
|
|
42
|
+
const basePathToAppend = pathParts[0];
|
|
43
|
+
let combinedUrl = baseEndpoint;
|
|
44
|
+
if (!baseEndpoint.endsWith("/") && !basePathToAppend.startsWith("/") && basePathToAppend !== "") {
|
|
45
|
+
combinedUrl += `/${basePathToAppend}`;
|
|
46
|
+
}
|
|
47
|
+
else if (baseEndpoint.endsWith("/") && basePathToAppend.startsWith("/")) {
|
|
48
|
+
combinedUrl += basePathToAppend.substring(1);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
combinedUrl += basePathToAppend;
|
|
52
|
+
}
|
|
53
|
+
if (combinedSearch) {
|
|
54
|
+
combinedUrl += `?${combinedSearch}`;
|
|
55
|
+
}
|
|
56
|
+
return combinedUrl;
|
|
27
57
|
}
|
|
28
58
|
function getQueryParamValue(key, allowReserved, style, param) {
|
|
29
59
|
let separator;
|
|
@@ -62,13 +92,48 @@ function getQueryParamValue(key, allowReserved, style, param) {
|
|
|
62
92
|
.join(separator);
|
|
63
93
|
return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;
|
|
64
94
|
}
|
|
65
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Parses a query string into a map of key/value pairs without decoding the values.
|
|
97
|
+
* This avoids the issue where `URL.searchParams` would decode values, potentially
|
|
98
|
+
* corrupting already-encoded values such as SAS signatures.
|
|
99
|
+
*/
|
|
100
|
+
function simpleParseQueryParams(queryString) {
|
|
101
|
+
const result = new Map();
|
|
102
|
+
if (!queryString || queryString[0] !== "?") {
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
// remove the leading ?
|
|
106
|
+
queryString = queryString.slice(1);
|
|
107
|
+
const pairs = queryString.split("&");
|
|
108
|
+
for (const pair of pairs) {
|
|
109
|
+
const eqIndex = pair.indexOf("=");
|
|
110
|
+
const name = eqIndex === -1 ? pair : pair.substring(0, eqIndex);
|
|
111
|
+
const value = eqIndex === -1 ? "" : pair.substring(eqIndex + 1);
|
|
112
|
+
const existingValue = result.get(name);
|
|
113
|
+
if (existingValue !== undefined) {
|
|
114
|
+
if (Array.isArray(existingValue)) {
|
|
115
|
+
existingValue.push(value);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
result.set(name, [existingValue, value]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
result.set(name, value);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
/** @internal */
|
|
128
|
+
export function appendQueryParams(url, options = {}) {
|
|
66
129
|
if (!options.queryParameters) {
|
|
67
130
|
return url;
|
|
68
131
|
}
|
|
69
132
|
const parsedUrl = new URL(url);
|
|
70
133
|
const queryParams = options.queryParameters;
|
|
71
|
-
|
|
134
|
+
// Parse existing query params from the URL manually to avoid re-encoding issues
|
|
135
|
+
const existingParams = simpleParseQueryParams(parsedUrl.search);
|
|
136
|
+
const newParamStrings = [];
|
|
72
137
|
for (const key of Object.keys(queryParams)) {
|
|
73
138
|
const param = queryParams[key];
|
|
74
139
|
if (param === undefined || param === null) {
|
|
@@ -81,13 +146,13 @@ function appendQueryParams(url, options = {}) {
|
|
|
81
146
|
if (explode) {
|
|
82
147
|
if (Array.isArray(rawValue)) {
|
|
83
148
|
for (const item of rawValue) {
|
|
84
|
-
|
|
149
|
+
newParamStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item));
|
|
85
150
|
}
|
|
86
151
|
}
|
|
87
152
|
else if (typeof rawValue === "object") {
|
|
88
153
|
// For object explode, the name of the query parameter is ignored and we use the object key instead
|
|
89
154
|
for (const [actualKey, value] of Object.entries(rawValue)) {
|
|
90
|
-
|
|
155
|
+
newParamStrings.push(getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value));
|
|
91
156
|
}
|
|
92
157
|
}
|
|
93
158
|
else {
|
|
@@ -96,13 +161,43 @@ function appendQueryParams(url, options = {}) {
|
|
|
96
161
|
}
|
|
97
162
|
}
|
|
98
163
|
else {
|
|
99
|
-
|
|
164
|
+
newParamStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Merge new params into existing params, deduplicating values for the same key
|
|
168
|
+
for (const paramString of newParamStrings) {
|
|
169
|
+
const eqIndex = paramString.indexOf("=");
|
|
170
|
+
const name = paramString.substring(0, eqIndex);
|
|
171
|
+
const value = paramString.substring(eqIndex + 1);
|
|
172
|
+
const existingValue = existingParams.get(name);
|
|
173
|
+
if (existingValue !== undefined) {
|
|
174
|
+
if (Array.isArray(existingValue)) {
|
|
175
|
+
if (!existingValue.includes(value)) {
|
|
176
|
+
existingValue.push(value);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else if (existingValue !== value) {
|
|
180
|
+
existingParams.set(name, [existingValue, value]);
|
|
181
|
+
}
|
|
182
|
+
// if existingValue === value (single string match), no change needed
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
existingParams.set(name, value);
|
|
100
186
|
}
|
|
101
187
|
}
|
|
102
|
-
|
|
103
|
-
|
|
188
|
+
// Reconstruct the search string manually to avoid URL re-encoding
|
|
189
|
+
const searchPieces = [];
|
|
190
|
+
for (const [name, value] of existingParams) {
|
|
191
|
+
if (Array.isArray(value)) {
|
|
192
|
+
for (const subValue of value) {
|
|
193
|
+
searchPieces.push(`${name}=${subValue}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
searchPieces.push(`${name}=${value}`);
|
|
198
|
+
}
|
|
104
199
|
}
|
|
105
|
-
parsedUrl.search
|
|
200
|
+
parsedUrl.search = searchPieces.length ? `?${searchPieces.join("&")}` : "";
|
|
106
201
|
return parsedUrl.toString();
|
|
107
202
|
}
|
|
108
203
|
export function buildBaseUrl(endpoint, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urlHelpers.js","sourceRoot":"","sources":["../../../src/client/urlHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { PathParameterWithOptions, RequestParameters } from \"./common.js\";\n\ntype QueryParameterStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\n\n/**\n * An object that can be passed as a query parameter, allowing for additional options to be set relating to how the parameter is encoded.\n */\ninterface QueryParameterWithOptions {\n /**\n * The value of the query parameter.\n */\n value: unknown;\n\n /**\n * If set to true, value must be an array. Setting this option to true will cause the array to be encoded as multiple query parameters.\n * Setting it to false will cause the array values to be encoded as a single query parameter, with each value separated by a comma ','.\n *\n * For example, with `explode` set to true, a query parameter named \"foo\" with value [\"a\", \"b\", \"c\"] will be encoded as foo=a&foo=b&foo=c.\n * If `explode` was set to false, the same example would instead be encouded as foo=a,b,c.\n *\n * Defaults to false.\n */\n explode?: boolean;\n\n /**\n * Style for encoding arrays. Three possible values:\n * - \"form\": array values will be separated by a comma \",\" in the query parameter value.\n * - \"spaceDelimited\": array values will be separated by a space (\" \", url-encoded to \"%20\").\n * - \"pipeDelimited\": array values will be separated by a pipe (\"|\").\n *\n * Defaults to \"form\".\n */\n style?: QueryParameterStyle;\n}\n\nfunction isQueryParameterWithOptions(x: unknown): x is QueryParameterWithOptions {\n const value = (x as QueryParameterWithOptions).value as any;\n return (\n value !== undefined && value.toString !== undefined && typeof value.toString === \"function\"\n );\n}\n\n/**\n * Builds the request url, filling in query and path parameters\n * @param endpoint - base url which can be a template url\n * @param routePath - path to append to the endpoint\n * @param pathParameters - values of the path parameters\n * @param options - request parameters including query parameters\n * @returns a full url with path and query parameters\n */\nexport function buildRequestUrl(\n endpoint: string,\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n if (routePath.startsWith(\"https://\") || routePath.startsWith(\"http://\")) {\n return routePath;\n }\n endpoint = buildBaseUrl(endpoint, options);\n routePath = buildRoutePath(routePath, pathParameters, options);\n const requestUrl = appendQueryParams(`${endpoint}/${routePath}`, options);\n const url = new URL(requestUrl);\n\n return (\n url\n .toString()\n // Remove double forward slashes\n .replace(/([^:]\\/)\\/+/g, \"$1\")\n );\n}\n\nfunction getQueryParamValue(\n key: string,\n allowReserved: boolean,\n style: QueryParameterStyle,\n param: any,\n): string {\n let separator: string;\n if (style === \"pipeDelimited\") {\n separator = \"|\";\n } else if (style === \"spaceDelimited\") {\n separator = \"%20\";\n } else {\n separator = \",\";\n }\n\n let paramValues: any[];\n if (Array.isArray(param)) {\n paramValues = param;\n } else if (typeof param === \"object\" && param.toString === Object.prototype.toString) {\n // If the parameter is an object without a custom toString implementation (e.g. a Date),\n // then we should deconstruct the object into an array [key1, value1, key2, value2, ...].\n paramValues = Object.entries(param).flat();\n } else {\n paramValues = [param];\n }\n\n const value = paramValues\n .map((p) => {\n if (p === null || p === undefined) {\n return \"\";\n }\n\n if (!p.toString || typeof p.toString !== \"function\") {\n throw new Error(`Query parameters must be able to be represented as string, ${key} can't`);\n }\n\n const rawValue = p.toISOString !== undefined ? p.toISOString() : p.toString();\n return allowReserved ? rawValue : encodeURIComponent(rawValue);\n })\n .join(separator);\n\n return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;\n}\n\nfunction appendQueryParams(url: string, options: RequestParameters = {}): string {\n if (!options.queryParameters) {\n return url;\n }\n const parsedUrl = new URL(url);\n const queryParams = options.queryParameters;\n\n const paramStrings: string[] = [];\n for (const key of Object.keys(queryParams)) {\n const param = queryParams[key] as any;\n if (param === undefined || param === null) {\n continue;\n }\n\n const hasMetadata = isQueryParameterWithOptions(param);\n const rawValue = hasMetadata ? param.value : param;\n const explode = hasMetadata ? (param.explode ?? false) : false;\n const style = hasMetadata && param.style ? param.style : \"form\";\n\n if (explode) {\n if (Array.isArray(rawValue)) {\n for (const item of rawValue) {\n paramStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item));\n }\n } else if (typeof rawValue === \"object\") {\n // For object explode, the name of the query parameter is ignored and we use the object key instead\n for (const [actualKey, value] of Object.entries(rawValue)) {\n paramStrings.push(\n getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value),\n );\n }\n } else {\n // Explode doesn't really make sense for primitives\n throw new Error(\"explode can only be set to true for objects and arrays\");\n }\n } else {\n paramStrings.push(getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue));\n }\n }\n\n if (parsedUrl.search !== \"\") {\n parsedUrl.search += \"&\";\n }\n parsedUrl.search += paramStrings.join(\"&\");\n return parsedUrl.toString();\n}\n\nexport function buildBaseUrl(endpoint: string, options: RequestParameters): string {\n if (!options.pathParameters) {\n return endpoint;\n }\n const pathParams = options.pathParameters;\n for (const [key, param] of Object.entries(pathParams)) {\n if (param === undefined || param === null) {\n throw new Error(`Path parameters ${key} must not be undefined or null`);\n }\n if (!param.toString || typeof param.toString !== \"function\") {\n throw new Error(`Path parameters must be able to be represented as string, ${key} can't`);\n }\n let value = param.toISOString !== undefined ? param.toISOString() : String(param);\n if (!options.skipUrlEncoding) {\n value = encodeURIComponent(param);\n }\n endpoint = replaceAll(endpoint, `{${key}}`, value) ?? \"\";\n }\n return endpoint;\n}\n\nfunction buildRoutePath(\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n for (const pathParam of pathParameters) {\n const allowReserved = typeof pathParam === \"object\" && (pathParam.allowReserved ?? false);\n let value = typeof pathParam === \"object\" ? pathParam.value : pathParam;\n\n if (!options.skipUrlEncoding && !allowReserved) {\n value = encodeURIComponent(value);\n }\n\n routePath = routePath.replace(/\\{[\\w-]+\\}/, String(value));\n }\n return routePath;\n}\n\n/**\n * Replace all of the instances of searchValue in value with the provided replaceValue.\n * @param value - The value to search and replace in.\n * @param searchValue - The value to search for in the value argument.\n * @param replaceValue - The value to replace searchValue with in the value argument.\n * @returns The value where each instance of searchValue was replaced with replacedValue.\n */\nexport function replaceAll(\n value: string | undefined,\n searchValue: string,\n replaceValue: string,\n): string | undefined {\n return !value || !searchValue ? value : value.split(searchValue).join(replaceValue || \"\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"urlHelpers.js","sourceRoot":"","sources":["../../../src/client/urlHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { PathParameterWithOptions, RequestParameters } from \"./common.js\";\n\ntype QueryParameterStyle = \"form\" | \"spaceDelimited\" | \"pipeDelimited\";\n\n/**\n * An object that can be passed as a query parameter, allowing for additional options to be set relating to how the parameter is encoded.\n */\ninterface QueryParameterWithOptions {\n /**\n * The value of the query parameter.\n */\n value: unknown;\n\n /**\n * If set to true, value must be an array. Setting this option to true will cause the array to be encoded as multiple query parameters.\n * Setting it to false will cause the array values to be encoded as a single query parameter, with each value separated by a comma ','.\n *\n * For example, with `explode` set to true, a query parameter named \"foo\" with value [\"a\", \"b\", \"c\"] will be encoded as foo=a&foo=b&foo=c.\n * If `explode` was set to false, the same example would instead be encouded as foo=a,b,c.\n *\n * Defaults to false.\n */\n explode?: boolean;\n\n /**\n * Style for encoding arrays. Three possible values:\n * - \"form\": array values will be separated by a comma \",\" in the query parameter value.\n * - \"spaceDelimited\": array values will be separated by a space (\" \", url-encoded to \"%20\").\n * - \"pipeDelimited\": array values will be separated by a pipe (\"|\").\n *\n * Defaults to \"form\".\n */\n style?: QueryParameterStyle;\n}\n\nfunction isQueryParameterWithOptions(x: unknown): x is QueryParameterWithOptions {\n const value = (x as QueryParameterWithOptions).value as any;\n return (\n value !== undefined && value.toString !== undefined && typeof value.toString === \"function\"\n );\n}\n\n/**\n * Builds the request url, filling in query and path parameters\n * @param endpoint - base url which can be a template url\n * @param routePath - path to append to the endpoint\n * @param pathParameters - values of the path parameters\n * @param options - request parameters including query parameters\n * @returns a full url with path and query parameters\n */\nexport function buildRequestUrl(\n endpoint: string,\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n if (routePath.startsWith(\"https://\") || routePath.startsWith(\"http://\")) {\n return routePath;\n }\n endpoint = buildBaseUrl(endpoint, options);\n // the route could be\n // 1. a path: \"container123/blob456\"\n // 2. a component string from template which starts with \"?\" and may contain more \"?\" after template is expanded,\n // e.g., \"?restype=container&comp=blobs?where=key177196556777405927%3D%27val1177196556777407626%27\"\n const updatedRoutePath = buildRoutePath(routePath, pathParameters, options);\n\n const requestUrl = appendQueryParams(appendPath(endpoint, updatedRoutePath), options);\n const url = new URL(requestUrl);\n\n return url.toString();\n}\n\nfunction appendPath(endpoint: string, pathToAppend: string): string {\n const endpointSearchStart = endpoint.indexOf(\"?\");\n const pathSearchStart = pathToAppend.indexOf(\"?\");\n const endpointParts =\n endpointSearchStart !== -1\n ? [endpoint.substring(0, endpointSearchStart), endpoint.substring(endpointSearchStart + 1)]\n : [endpoint, \"\"];\n const pathParts =\n pathSearchStart !== -1\n ? [pathToAppend.substring(0, pathSearchStart), pathToAppend.substring(pathSearchStart + 1)]\n : [pathToAppend, \"\"];\n\n const combinedSearch = [endpointParts[1], pathParts[1].replaceAll(\"?\", \"&\")]\n .filter(Boolean)\n .join(\"&\");\n const baseEndpoint = endpointParts[0];\n const basePathToAppend = pathParts[0];\n\n let combinedUrl = baseEndpoint;\n if (!baseEndpoint.endsWith(\"/\") && !basePathToAppend.startsWith(\"/\") && basePathToAppend !== \"\") {\n combinedUrl += `/${basePathToAppend}`;\n } else if (baseEndpoint.endsWith(\"/\") && basePathToAppend.startsWith(\"/\")) {\n combinedUrl += basePathToAppend.substring(1);\n } else {\n combinedUrl += basePathToAppend;\n }\n\n if (combinedSearch) {\n combinedUrl += `?${combinedSearch}`;\n }\n\n return combinedUrl;\n}\n\nfunction getQueryParamValue(\n key: string,\n allowReserved: boolean,\n style: QueryParameterStyle,\n param: any,\n): string {\n let separator: string;\n if (style === \"pipeDelimited\") {\n separator = \"|\";\n } else if (style === \"spaceDelimited\") {\n separator = \"%20\";\n } else {\n separator = \",\";\n }\n\n let paramValues: any[];\n if (Array.isArray(param)) {\n paramValues = param;\n } else if (typeof param === \"object\" && param.toString === Object.prototype.toString) {\n // If the parameter is an object without a custom toString implementation (e.g. a Date),\n // then we should deconstruct the object into an array [key1, value1, key2, value2, ...].\n paramValues = Object.entries(param).flat();\n } else {\n paramValues = [param];\n }\n\n const value = paramValues\n .map((p) => {\n if (p === null || p === undefined) {\n return \"\";\n }\n\n if (!p.toString || typeof p.toString !== \"function\") {\n throw new Error(`Query parameters must be able to be represented as string, ${key} can't`);\n }\n\n const rawValue = p.toISOString !== undefined ? p.toISOString() : p.toString();\n return allowReserved ? rawValue : encodeURIComponent(rawValue);\n })\n .join(separator);\n\n return `${allowReserved ? key : encodeURIComponent(key)}=${value}`;\n}\n\n/**\n * Parses a query string into a map of key/value pairs without decoding the values.\n * This avoids the issue where `URL.searchParams` would decode values, potentially\n * corrupting already-encoded values such as SAS signatures.\n */\nfunction simpleParseQueryParams(queryString: string): Map<string, string | string[]> {\n const result = new Map<string, string | string[]>();\n if (!queryString || queryString[0] !== \"?\") {\n return result;\n }\n\n // remove the leading ?\n queryString = queryString.slice(1);\n const pairs = queryString.split(\"&\");\n\n for (const pair of pairs) {\n const eqIndex = pair.indexOf(\"=\");\n const name = eqIndex === -1 ? pair : pair.substring(0, eqIndex);\n const value = eqIndex === -1 ? \"\" : pair.substring(eqIndex + 1);\n\n const existingValue = result.get(name);\n if (existingValue !== undefined) {\n if (Array.isArray(existingValue)) {\n existingValue.push(value);\n } else {\n result.set(name, [existingValue, value]);\n }\n } else {\n result.set(name, value);\n }\n }\n\n return result;\n}\n\n/** @internal */\nexport function appendQueryParams(url: string, options: RequestParameters = {}): string {\n if (!options.queryParameters) {\n return url;\n }\n const parsedUrl = new URL(url);\n const queryParams = options.queryParameters;\n\n // Parse existing query params from the URL manually to avoid re-encoding issues\n const existingParams = simpleParseQueryParams(parsedUrl.search);\n\n const newParamStrings: string[] = [];\n for (const key of Object.keys(queryParams)) {\n const param = queryParams[key] as any;\n if (param === undefined || param === null) {\n continue;\n }\n\n const hasMetadata = isQueryParameterWithOptions(param);\n const rawValue = hasMetadata ? param.value : param;\n const explode = hasMetadata ? (param.explode ?? false) : false;\n const style = hasMetadata && param.style ? param.style : \"form\";\n\n if (explode) {\n if (Array.isArray(rawValue)) {\n for (const item of rawValue) {\n newParamStrings.push(\n getQueryParamValue(key, options.skipUrlEncoding ?? false, style, item),\n );\n }\n } else if (typeof rawValue === \"object\") {\n // For object explode, the name of the query parameter is ignored and we use the object key instead\n for (const [actualKey, value] of Object.entries(rawValue)) {\n newParamStrings.push(\n getQueryParamValue(actualKey, options.skipUrlEncoding ?? false, style, value),\n );\n }\n } else {\n // Explode doesn't really make sense for primitives\n throw new Error(\"explode can only be set to true for objects and arrays\");\n }\n } else {\n newParamStrings.push(\n getQueryParamValue(key, options.skipUrlEncoding ?? false, style, rawValue),\n );\n }\n }\n\n // Merge new params into existing params, deduplicating values for the same key\n for (const paramString of newParamStrings) {\n const eqIndex = paramString.indexOf(\"=\");\n const name = paramString.substring(0, eqIndex);\n const value = paramString.substring(eqIndex + 1);\n\n const existingValue = existingParams.get(name);\n if (existingValue !== undefined) {\n if (Array.isArray(existingValue)) {\n if (!existingValue.includes(value)) {\n existingValue.push(value);\n }\n } else if (existingValue !== value) {\n existingParams.set(name, [existingValue, value]);\n }\n // if existingValue === value (single string match), no change needed\n } else {\n existingParams.set(name, value);\n }\n }\n\n // Reconstruct the search string manually to avoid URL re-encoding\n const searchPieces: string[] = [];\n for (const [name, value] of existingParams) {\n if (Array.isArray(value)) {\n for (const subValue of value) {\n searchPieces.push(`${name}=${subValue}`);\n }\n } else {\n searchPieces.push(`${name}=${value}`);\n }\n }\n\n parsedUrl.search = searchPieces.length ? `?${searchPieces.join(\"&\")}` : \"\";\n return parsedUrl.toString();\n}\n\nexport function buildBaseUrl(endpoint: string, options: RequestParameters): string {\n if (!options.pathParameters) {\n return endpoint;\n }\n const pathParams = options.pathParameters;\n for (const [key, param] of Object.entries(pathParams)) {\n if (param === undefined || param === null) {\n throw new Error(`Path parameters ${key} must not be undefined or null`);\n }\n if (!param.toString || typeof param.toString !== \"function\") {\n throw new Error(`Path parameters must be able to be represented as string, ${key} can't`);\n }\n let value = param.toISOString !== undefined ? param.toISOString() : String(param);\n if (!options.skipUrlEncoding) {\n value = encodeURIComponent(param);\n }\n endpoint = replaceAll(endpoint, `{${key}}`, value) ?? \"\";\n }\n return endpoint;\n}\n\nfunction buildRoutePath(\n routePath: string,\n pathParameters: (string | number | PathParameterWithOptions)[],\n options: RequestParameters = {},\n): string {\n for (const pathParam of pathParameters) {\n const allowReserved = typeof pathParam === \"object\" && (pathParam.allowReserved ?? false);\n let value = typeof pathParam === \"object\" ? pathParam.value : pathParam;\n\n if (!options.skipUrlEncoding && !allowReserved) {\n value = encodeURIComponent(value);\n }\n\n routePath = routePath.replace(/\\{[\\w-]+\\}/, String(value));\n }\n return routePath;\n}\n\n/**\n * Replace all of the instances of searchValue in value with the provided replaceValue.\n * @param value - The value to search and replace in.\n * @param searchValue - The value to search for in the value argument.\n * @param replaceValue - The value to replace searchValue with in the value argument.\n * @returns The value where each instance of searchValue was replaced with replacedValue.\n */\nexport function replaceAll(\n value: string | undefined,\n searchValue: string,\n replaceValue: string,\n): string | undefined {\n return !value || !searchValue ? value : value.split(searchValue).join(replaceValue || \"\");\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typespec/ts-http-runtime",
|
|
3
|
-
"version": "0.3.5-alpha.
|
|
3
|
+
"version": "0.3.5-alpha.20260310.2",
|
|
4
4
|
"description": "Isomorphic client library for making HTTP requests in node.js and browser.",
|
|
5
5
|
"sdk-type": "client",
|
|
6
6
|
"type": "module",
|
|
@@ -139,9 +139,9 @@
|
|
|
139
139
|
"tsx": "^4.20.4",
|
|
140
140
|
"typescript": "~5.9.3",
|
|
141
141
|
"vitest": "^4.0.8",
|
|
142
|
-
"@azure-tools/vite-plugin-browser-test-map": "^1.0.0",
|
|
143
142
|
"@azure/dev-tool": "^1.0.0",
|
|
144
|
-
"@azure/eslint-plugin-azure-sdk": "^3.0.0"
|
|
143
|
+
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
|
|
144
|
+
"@azure-tools/vite-plugin-browser-test-map": "^1.0.0"
|
|
145
145
|
},
|
|
146
146
|
"module": "./dist/esm/index.js",
|
|
147
147
|
"scripts": {
|