@zimic/interceptor 1.1.0-canary.1 → 1.1.0-canary.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/http.js CHANGED
@@ -958,16 +958,88 @@ var LocalHttpRequestHandler = class {
958
958
  };
959
959
  var LocalHttpRequestHandler_default = LocalHttpRequestHandler;
960
960
 
961
- // ../zimic-utils/dist/chunk-4RR2YNYT.mjs
962
- var URL_PATH_PARAM_REGEX = /\/:([^/]+)/g;
963
- function createRegExpFromURL(url) {
964
- URL_PATH_PARAM_REGEX.lastIndex = 0;
965
- const urlWithReplacedPathParams = encodeURI(url).replace(/([.()*?+$\\])/g, "\\$1").replace(URL_PATH_PARAM_REGEX, "/(?<$1>[^/]+)").replace(/^(\/)|(\/)$/g, "");
966
- return new RegExp(`^(?:/)?${urlWithReplacedPathParams}(?:/)?$`);
961
+ // ../zimic-utils/dist/chunk-7KDKOZM7.mjs
962
+ function getExtraPatternsToEscape() {
963
+ return /([.(){}+$])/g;
967
964
  }
968
- __name(createRegExpFromURL, "createRegExpFromURL");
969
- __name2(createRegExpFromURL, "createRegExpFromURL");
970
- var createRegExpFromURL_default = createRegExpFromURL;
965
+ __name(getExtraPatternsToEscape, "getExtraPatternsToEscape");
966
+ __name2(getExtraPatternsToEscape, "getExtraPatternsToEscape");
967
+ function getURIEncodedBackSlashPattern() {
968
+ return /%5C/g;
969
+ }
970
+ __name(getURIEncodedBackSlashPattern, "getURIEncodedBackSlashPattern");
971
+ __name2(getURIEncodedBackSlashPattern, "getURIEncodedBackSlashPattern");
972
+ function getPathParamPattern() {
973
+ return /(?<escape>\\)?:(?<identifier>[$_\p{ID_Start}][$\p{ID_Continue}]+)/gu;
974
+ }
975
+ __name(getPathParamPattern, "getPathParamPattern");
976
+ __name2(getPathParamPattern, "getPathParamPattern");
977
+ function getRepeatingPathParamPattern() {
978
+ return /(?<escape>\\)?:(?<identifier>[$_\p{ID_Start}][$\p{ID_Continue}]+)\\+/gu;
979
+ }
980
+ __name(getRepeatingPathParamPattern, "getRepeatingPathParamPattern");
981
+ __name2(getRepeatingPathParamPattern, "getRepeatingPathParamPattern");
982
+ function getOptionalPathParamPattern() {
983
+ return /(?<leadingSlash>\/)?(?<escape>\\)?:(?<identifier>[$_\p{ID_Start}][$\p{ID_Continue}]+)\?(?<trailingSlash>\/)?/gu;
984
+ }
985
+ __name(getOptionalPathParamPattern, "getOptionalPathParamPattern");
986
+ __name2(getOptionalPathParamPattern, "getOptionalPathParamPattern");
987
+ function getOptionalRepeatingPathParamPattern() {
988
+ return /(?<leadingSlash>\/)?(?<escape>\\)?:(?<identifier>[$_\p{ID_Start}][$\p{ID_Continue}]+)\*(?<trailingSlash>\/)?/gu;
989
+ }
990
+ __name(getOptionalRepeatingPathParamPattern, "getOptionalRepeatingPathParamPattern");
991
+ __name2(getOptionalRepeatingPathParamPattern, "getOptionalRepeatingPathParamPattern");
992
+ function createParametrizedPathPattern(path) {
993
+ const replacedURL = encodeURI(path).replace(/^\/+/g, "").replace(/\/+$/g, "").replace(getExtraPatternsToEscape(), "\\$1").replace(getURIEncodedBackSlashPattern(), "\\").replace(
994
+ getOptionalRepeatingPathParamPattern(),
995
+ (_match, leadingSlash, escape, identifier, trailingSlash) => {
996
+ if (escape) {
997
+ return `:${identifier}`;
998
+ }
999
+ const hasSegmentBeforePrefix = leadingSlash === "/";
1000
+ const prefixExpression = hasSegmentBeforePrefix ? "/?" : leadingSlash;
1001
+ const hasSegmentAfterSuffix = trailingSlash === "/";
1002
+ const suffixExpression = hasSegmentAfterSuffix ? "/?" : trailingSlash;
1003
+ if (prefixExpression && suffixExpression) {
1004
+ return `(?:${prefixExpression}(?<${identifier}>.+?)?${suffixExpression})?`;
1005
+ } else if (prefixExpression) {
1006
+ return `(?:${prefixExpression}(?<${identifier}>.+?))?`;
1007
+ } else if (suffixExpression) {
1008
+ return `(?:(?<${identifier}>.+?)${suffixExpression})?`;
1009
+ } else {
1010
+ return `(?<${identifier}>.+?)?`;
1011
+ }
1012
+ }
1013
+ ).replace(getRepeatingPathParamPattern(), (_match, escape, identifier) => {
1014
+ return escape ? `:${identifier}` : `(?<${identifier}>.+)`;
1015
+ }).replace(
1016
+ getOptionalPathParamPattern(),
1017
+ (_match, leadingSlash, escape, identifier, trailingSlash) => {
1018
+ if (escape) {
1019
+ return `:${identifier}`;
1020
+ }
1021
+ const hasNoSegmentBeforePrefix = leadingSlash === "/";
1022
+ const prefixExpression = hasNoSegmentBeforePrefix ? "/?" : leadingSlash;
1023
+ const hasNoSegmentAfterSuffix = trailingSlash === "/";
1024
+ const suffixExpression = hasNoSegmentAfterSuffix ? "/?" : trailingSlash;
1025
+ if (prefixExpression && suffixExpression) {
1026
+ return `(?:${prefixExpression}(?<${identifier}>[^\\/]+?)?${suffixExpression})`;
1027
+ } else if (prefixExpression) {
1028
+ return `(?:${prefixExpression}(?<${identifier}>[^\\/]+?))?`;
1029
+ } else if (suffixExpression) {
1030
+ return `(?:(?<${identifier}>[^\\/]+?)${suffixExpression})?`;
1031
+ } else {
1032
+ return `(?<${identifier}>[^\\/]+?)?`;
1033
+ }
1034
+ }
1035
+ ).replace(getPathParamPattern(), (_match, escape, identifier) => {
1036
+ return escape ? `:${identifier}` : `(?<${identifier}>[^\\/]+?)`;
1037
+ });
1038
+ return new RegExp(`^/?${replacedURL}/?$`);
1039
+ }
1040
+ __name(createParametrizedPathPattern, "createParametrizedPathPattern");
1041
+ __name2(createParametrizedPathPattern, "createParametrizedPathPattern");
1042
+ var createParametrizedPathPattern_default = createParametrizedPathPattern;
971
1043
 
972
1044
  // ../zimic-utils/dist/url/excludeURLParams.mjs
973
1045
  function excludeURLParams(url) {
@@ -981,25 +1053,6 @@ __name(excludeURLParams, "excludeURLParams");
981
1053
  __name2(excludeURLParams, "excludeURLParams");
982
1054
  var excludeURLParams_default = excludeURLParams;
983
1055
 
984
- // ../zimic-utils/dist/url/joinURL.mjs
985
- function joinURL(...parts) {
986
- return parts.map((part, index) => {
987
- const isFirstPart = index === 0;
988
- const isLastPart = index === parts.length - 1;
989
- let partAsString = part.toString();
990
- if (!isFirstPart) {
991
- partAsString = partAsString.replace(/^\//, "");
992
- }
993
- if (!isLastPart) {
994
- partAsString = partAsString.replace(/\/$/, "");
995
- }
996
- return partAsString;
997
- }).filter((part) => part.length > 0).join("/");
998
- }
999
- __name(joinURL, "joinURL");
1000
- __name2(joinURL, "joinURL");
1001
- var joinURL_default = joinURL;
1002
-
1003
1056
  // ../zimic-utils/dist/url/validateURLProtocol.mjs
1004
1057
  var UnsupportedURLProtocolError = class extends TypeError {
1005
1058
  static {
@@ -1198,12 +1251,12 @@ var HttpInterceptorWorker = class _HttpInterceptorWorker {
1198
1251
  request
1199
1252
  );
1200
1253
  }
1201
- static async parseRawRequest(originalRawRequest, options = {}) {
1254
+ static async parseRawRequest(originalRawRequest, options) {
1202
1255
  const rawRequest = originalRawRequest.clone();
1203
1256
  const rawRequestClone = rawRequest.clone();
1204
1257
  const parsedBody = await this.parseRawBody(rawRequest);
1205
1258
  const headers = new http.HttpHeaders(rawRequest.headers);
1206
- const pathParams = options.urlRegex ? this.parseRawPathParams(options.urlRegex, rawRequest) : {};
1259
+ const pathParams = this.parseRawPathParams(rawRequest, options);
1207
1260
  const parsedURL = new URL(rawRequest.url);
1208
1261
  const searchParams = new http.HttpSearchParams(parsedURL.searchParams);
1209
1262
  const parsedRequest = new Proxy(rawRequest, {
@@ -1297,10 +1350,9 @@ var HttpInterceptorWorker = class _HttpInterceptorWorker {
1297
1350
  static isHiddenResponseProperty(property) {
1298
1351
  return HTTP_INTERCEPTOR_RESPONSE_HIDDEN_PROPERTIES.has(property);
1299
1352
  }
1300
- static parseRawPathParams(matchedURLRegex, request) {
1301
- const match = request.url.match(matchedURLRegex);
1302
- const pathParams = { ...match?.groups };
1303
- return pathParams;
1353
+ static parseRawPathParams(request, options) {
1354
+ const match = options?.pathPattern.exec(request.url.replace(options.baseURL, ""));
1355
+ return { ...match?.groups };
1304
1356
  }
1305
1357
  static async parseRawBody(resource) {
1306
1358
  const contentType = resource.headers.get("content-type");
@@ -1653,13 +1705,12 @@ var HttpInterceptorClient = class {
1653
1705
  return;
1654
1706
  }
1655
1707
  this.handlerClientsByMethod[handler.method].set(handler.path, handlerClients);
1656
- const url = joinURL_default(this.baseURLAsString, handler.path);
1657
- const urlRegex = createRegExpFromURL_default(url);
1658
- const registrationResult = this.workerOrThrow.use(this, handler.method, url, async (context) => {
1708
+ const pathPattern = createParametrizedPathPattern_default(handler.path);
1709
+ const registrationResult = this.workerOrThrow.use(this, handler.method, handler.path, async (context) => {
1659
1710
  const response = await this.handleInterceptedRequest(
1660
- urlRegex,
1661
1711
  handler.method,
1662
1712
  handler.path,
1713
+ pathPattern,
1663
1714
  context
1664
1715
  );
1665
1716
  return response;
@@ -1668,9 +1719,10 @@ var HttpInterceptorClient = class {
1668
1719
  handler.registerSyncPromise(registrationResult);
1669
1720
  }
1670
1721
  }
1671
- async handleInterceptedRequest(matchedURLRegex, method, path, { request }) {
1722
+ async handleInterceptedRequest(method, path, pathPattern, { request }) {
1672
1723
  const parsedRequest = await HttpInterceptorWorker_default.parseRawRequest(request, {
1673
- urlRegex: matchedURLRegex
1724
+ baseURL: this.baseURLAsString,
1725
+ pathPattern
1674
1726
  });
1675
1727
  const matchedHandler = await this.findMatchedHandler(method, path, parsedRequest);
1676
1728
  if (!matchedHandler) {
@@ -1742,7 +1794,7 @@ var HttpInterceptorClient = class {
1742
1794
  };
1743
1795
  var HttpInterceptorClient_default = HttpInterceptorClient;
1744
1796
 
1745
- // ../zimic-utils/dist/url/validateURLPathParams.mjs
1797
+ // ../zimic-utils/dist/url/validatePathParams.mjs
1746
1798
  var DuplicatedPathParamError = class extends Error {
1747
1799
  static {
1748
1800
  __name(this, "DuplicatedPathParamError");
@@ -1750,41 +1802,46 @@ var DuplicatedPathParamError = class extends Error {
1750
1802
  static {
1751
1803
  __name2(this, "DuplicatedPathParamError");
1752
1804
  }
1753
- constructor(url, paramName) {
1805
+ constructor(path, paramName) {
1754
1806
  super(
1755
- `The path parameter '${paramName}' appears more than once in the URL '${url.toString()}'. This is not supported. Please make sure that each parameter is unique.`
1807
+ `The path parameter '${paramName}' appears more than once in '${path}'. This is not supported. Please make sure that each parameter is unique.`
1756
1808
  );
1757
1809
  this.name = "DuplicatedPathParamError";
1758
1810
  }
1759
1811
  };
1760
- function validateURLPathParams(url) {
1761
- URL_PATH_PARAM_REGEX.lastIndex = 0;
1762
- const matches = url.toString().matchAll(URL_PATH_PARAM_REGEX);
1812
+ function validatePathParams(path) {
1813
+ const pathParamMatches = path.toString().matchAll(getPathParamPattern());
1763
1814
  const uniqueParamNames = /* @__PURE__ */ new Set();
1764
- for (const match of matches) {
1765
- const paramName = match[1];
1815
+ for (const paramMatch of pathParamMatches) {
1816
+ const paramName = paramMatch.groups?.identifier;
1817
+ if (!paramName) {
1818
+ continue;
1819
+ }
1766
1820
  if (uniqueParamNames.has(paramName)) {
1767
- throw new DuplicatedPathParamError(url, paramName);
1821
+ throw new DuplicatedPathParamError(path, paramName);
1768
1822
  }
1769
1823
  uniqueParamNames.add(paramName);
1770
1824
  }
1771
1825
  }
1772
- __name(validateURLPathParams, "validateURLPathParams");
1773
- __name2(validateURLPathParams, "validateURLPathParams");
1774
- var validateURLPathParams_default = validateURLPathParams;
1826
+ __name(validatePathParams, "validatePathParams");
1827
+ __name2(validatePathParams, "validatePathParams");
1828
+ var validatePathParams_default = validatePathParams;
1775
1829
  var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1776
1830
  static {
1777
1831
  __name(this, "LocalHttpInterceptorWorker");
1778
1832
  }
1779
1833
  internalWorker;
1780
- defaultHttpHandler;
1781
- httpHandlerGroups = [];
1834
+ httpHandlersByMethod = {
1835
+ GET: [],
1836
+ POST: [],
1837
+ PATCH: [],
1838
+ PUT: [],
1839
+ DELETE: [],
1840
+ HEAD: [],
1841
+ OPTIONS: []
1842
+ };
1782
1843
  constructor(_options) {
1783
1844
  super();
1784
- this.defaultHttpHandler = msw.http.all("*", async (context) => {
1785
- const request = context.request;
1786
- return this.bypassOrRejectUnhandledRequest(request);
1787
- });
1788
1845
  }
1789
1846
  get type() {
1790
1847
  return "local";
@@ -1800,11 +1857,16 @@ var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1800
1857
  return this.internalWorker;
1801
1858
  }
1802
1859
  createInternalWorker() {
1860
+ const mswHttpHandler = msw.http.all("*", async (context) => {
1861
+ const request = context.request;
1862
+ const response = await this.createResponseForRequest(request);
1863
+ return response;
1864
+ });
1803
1865
  if (isServerSide() && "setupServer" in mswNode__namespace) {
1804
- return mswNode__namespace.setupServer(this.defaultHttpHandler);
1866
+ return mswNode__namespace.setupServer(mswHttpHandler);
1805
1867
  }
1806
1868
  if (isClientSide() && "setupWorker" in mswBrowser__namespace) {
1807
- return mswBrowser__namespace.setupWorker(this.defaultHttpHandler);
1869
+ return mswBrowser__namespace.setupWorker(mswHttpHandler);
1808
1870
  }
1809
1871
  throw new UnknownHttpInterceptorPlatformError_default();
1810
1872
  }
@@ -1868,34 +1930,60 @@ var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1868
1930
  hasInternalNodeWorker() {
1869
1931
  return !this.hasInternalBrowserWorker();
1870
1932
  }
1871
- use(interceptor, method, rawURL, createResponse) {
1872
- const lowercaseMethod = method.toLowerCase();
1873
- const url = new URL(rawURL);
1874
- excludeURLParams_default(url);
1875
- validateURLPathParams_default(url);
1876
- const httpHandler = msw.http[lowercaseMethod](url.toString(), async (context) => {
1877
- const request = context.request;
1878
- const requestClone = request.clone();
1879
- let response = null;
1880
- try {
1881
- response = await createResponse({ ...context, request });
1882
- } catch (error) {
1883
- console.error(error);
1884
- }
1885
- if (!response) {
1886
- return this.bypassOrRejectUnhandledRequest(requestClone);
1933
+ use(interceptor, method, path, createResponse) {
1934
+ if (!this.isRunning) {
1935
+ throw new NotRunningHttpInterceptorError_default();
1936
+ }
1937
+ validatePathParams_default(path);
1938
+ const methodHandlers = this.httpHandlersByMethod[method];
1939
+ const handler = {
1940
+ baseURL: interceptor.baseURLAsString,
1941
+ method,
1942
+ pathPattern: createParametrizedPathPattern_default(path),
1943
+ interceptor,
1944
+ createResponse: /* @__PURE__ */ __name(async (context) => {
1945
+ const request = context.request;
1946
+ const requestClone = request.clone();
1947
+ let response = null;
1948
+ try {
1949
+ response = await createResponse({ ...context, request });
1950
+ } catch (error) {
1951
+ console.error(error);
1952
+ }
1953
+ if (!response) {
1954
+ return this.bypassOrRejectUnhandledRequest(requestClone);
1955
+ }
1956
+ if (context.request.method === "HEAD") {
1957
+ return new Response(null, {
1958
+ status: response.status,
1959
+ statusText: response.statusText,
1960
+ headers: response.headers
1961
+ });
1962
+ }
1963
+ return response;
1964
+ }, "createResponse")
1965
+ };
1966
+ methodHandlers.push(handler);
1967
+ }
1968
+ async createResponseForRequest(request) {
1969
+ const methodHandlers = this.httpHandlersByMethod[request.method];
1970
+ const requestURL = excludeURLParams_default(new URL(request.url));
1971
+ const requestURLAsString = requestURL.href === `${requestURL.origin}/` ? requestURL.origin : requestURL.href;
1972
+ for (let handlerIndex = methodHandlers.length - 1; handlerIndex >= 0; handlerIndex--) {
1973
+ const handler = methodHandlers[handlerIndex];
1974
+ const matchesBaseURL = requestURLAsString.startsWith(handler.baseURL);
1975
+ if (!matchesBaseURL) {
1976
+ continue;
1887
1977
  }
1888
- if (context.request.method === "HEAD") {
1889
- return new Response(null, {
1890
- status: response.status,
1891
- statusText: response.statusText,
1892
- headers: response.headers
1893
- });
1978
+ const requestPath = requestURLAsString.replace(handler.baseURL, "");
1979
+ const matchesPath = handler.pathPattern.test(requestPath);
1980
+ if (!matchesPath) {
1981
+ continue;
1894
1982
  }
1983
+ const response = await handler.createResponse({ request });
1895
1984
  return response;
1896
- });
1897
- this.internalWorkerOrThrow.use(httpHandler);
1898
- this.httpHandlerGroups.push({ interceptor, httpHandler });
1985
+ }
1986
+ return this.bypassOrRejectUnhandledRequest(request);
1899
1987
  }
1900
1988
  async bypassOrRejectUnhandledRequest(request) {
1901
1989
  const requestClone = request.clone();
@@ -1909,18 +1997,27 @@ var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1909
1997
  }
1910
1998
  clearHandlers() {
1911
1999
  this.internalWorkerOrThrow.resetHandlers();
1912
- this.httpHandlerGroups = [];
2000
+ for (const handlers of Object.values(this.httpHandlersByMethod)) {
2001
+ handlers.length = 0;
2002
+ }
1913
2003
  }
1914
2004
  clearInterceptorHandlers(interceptor) {
1915
- const groupToRemoveIndex = this.httpHandlerGroups.findIndex((group) => group.interceptor === interceptor);
1916
- removeArrayIndex(this.httpHandlerGroups, groupToRemoveIndex);
1917
- this.internalWorkerOrThrow.resetHandlers();
1918
- for (const { httpHandler } of this.httpHandlerGroups) {
1919
- this.internalWorkerOrThrow.use(httpHandler);
2005
+ if (!this.isRunning) {
2006
+ throw new NotRunningHttpInterceptorError_default();
2007
+ }
2008
+ for (const methodHandlers of Object.values(this.httpHandlersByMethod)) {
2009
+ const groupToRemoveIndex = methodHandlers.findIndex((group) => group.interceptor === interceptor);
2010
+ removeArrayIndex(methodHandlers, groupToRemoveIndex);
1920
2011
  }
1921
2012
  }
1922
2013
  get interceptorsWithHandlers() {
1923
- return this.httpHandlerGroups.map((group) => group.interceptor);
2014
+ const interceptors = /* @__PURE__ */ new Set();
2015
+ for (const handlers of Object.values(this.httpHandlersByMethod)) {
2016
+ for (const handler of handlers) {
2017
+ interceptors.add(handler.interceptor);
2018
+ }
2019
+ }
2020
+ return Array.from(interceptors);
1924
2021
  }
1925
2022
  };
1926
2023
  var LocalHttpInterceptorWorker_default = LocalHttpInterceptorWorker;
@@ -2500,21 +2597,17 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2500
2597
  this.isRunning = false;
2501
2598
  });
2502
2599
  }
2503
- async use(interceptor, method, rawURL, createResponse) {
2600
+ async use(interceptor, method, path, createResponse) {
2504
2601
  if (!this.isRunning) {
2505
2602
  throw new NotRunningHttpInterceptorError_default();
2506
2603
  }
2604
+ validatePathParams_default(path);
2507
2605
  const crypto = await importCrypto();
2508
- const url = new URL(rawURL);
2509
- excludeURLParams_default(url);
2510
- validateURLPathParams_default(url);
2511
2606
  const handler = {
2512
2607
  id: crypto.randomUUID(),
2513
- url: {
2514
- base: interceptor.baseURLAsString,
2515
- full: url.toString()
2516
- },
2608
+ baseURL: interceptor.baseURLAsString,
2517
2609
  method,
2610
+ path,
2518
2611
  interceptor,
2519
2612
  async createResponse(context) {
2520
2613
  const response = await createResponse(context);
@@ -2524,8 +2617,9 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2524
2617
  this.httpHandlers.set(handler.id, handler);
2525
2618
  await this.webSocketClient.request("interceptors/workers/commit", {
2526
2619
  id: handler.id,
2527
- url: handler.url,
2528
- method
2620
+ baseURL: handler.baseURL,
2621
+ method: handler.method,
2622
+ path: handler.path
2529
2623
  });
2530
2624
  }
2531
2625
  async clearHandlers() {
@@ -2549,8 +2643,9 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2549
2643
  if (this.webSocketClient.isRunning) {
2550
2644
  const groupsToRecommit = Array.from(this.httpHandlers.values(), (handler) => ({
2551
2645
  id: handler.id,
2552
- url: handler.url,
2553
- method: handler.method
2646
+ baseURL: handler.baseURL,
2647
+ method: handler.method,
2648
+ path: handler.path
2554
2649
  }));
2555
2650
  await this.webSocketClient.request("interceptors/workers/reset", groupsToRecommit);
2556
2651
  }