@wordpress/api-fetch 7.28.1-next.0f6f9d12c.0 → 7.29.1-next.e256d081a.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/index.js +25 -34
  3. package/build/index.js.map +1 -1
  4. package/build/middlewares/fetch-all-middleware.js +14 -14
  5. package/build/middlewares/fetch-all-middleware.js.map +1 -1
  6. package/build/middlewares/http-v1.js +6 -5
  7. package/build/middlewares/http-v1.js.map +1 -1
  8. package/build/middlewares/media-upload.js +6 -6
  9. package/build/middlewares/media-upload.js.map +1 -1
  10. package/build/middlewares/namespace-endpoint.js +2 -1
  11. package/build/middlewares/namespace-endpoint.js.map +1 -1
  12. package/build/middlewares/nonce.js +7 -5
  13. package/build/middlewares/nonce.js.map +1 -1
  14. package/build/middlewares/preloading.js +10 -7
  15. package/build/middlewares/preloading.js.map +1 -1
  16. package/build/middlewares/root-url.js +2 -2
  17. package/build/middlewares/root-url.js.map +1 -1
  18. package/build/middlewares/theme-preview.js +6 -2
  19. package/build/middlewares/theme-preview.js.map +1 -1
  20. package/build/middlewares/user-locale.js +2 -1
  21. package/build/middlewares/user-locale.js.map +1 -1
  22. package/build/types.js.map +1 -1
  23. package/build/utils/response.js +11 -11
  24. package/build/utils/response.js.map +1 -1
  25. package/build-module/index.js +13 -35
  26. package/build-module/index.js.map +1 -1
  27. package/build-module/middlewares/fetch-all-middleware.js +14 -15
  28. package/build-module/middlewares/fetch-all-middleware.js.map +1 -1
  29. package/build-module/middlewares/http-v1.js +6 -5
  30. package/build-module/middlewares/http-v1.js.map +1 -1
  31. package/build-module/middlewares/media-upload.js +6 -7
  32. package/build-module/middlewares/media-upload.js.map +1 -1
  33. package/build-module/middlewares/namespace-endpoint.js +2 -1
  34. package/build-module/middlewares/namespace-endpoint.js.map +1 -1
  35. package/build-module/middlewares/nonce.js +7 -5
  36. package/build-module/middlewares/nonce.js.map +1 -1
  37. package/build-module/middlewares/preloading.js +10 -7
  38. package/build-module/middlewares/preloading.js.map +1 -1
  39. package/build-module/middlewares/root-url.js +3 -2
  40. package/build-module/middlewares/root-url.js.map +1 -1
  41. package/build-module/middlewares/theme-preview.js +5 -2
  42. package/build-module/middlewares/theme-preview.js.map +1 -1
  43. package/build-module/middlewares/user-locale.js +2 -1
  44. package/build-module/middlewares/user-locale.js.map +1 -1
  45. package/build-module/types.js.map +1 -1
  46. package/build-module/utils/response.js +11 -11
  47. package/build-module/utils/response.js.map +1 -1
  48. package/build-types/index.d.ts +25 -32
  49. package/build-types/index.d.ts.map +1 -1
  50. package/build-types/middlewares/fetch-all-middleware.d.ts +5 -4
  51. package/build-types/middlewares/fetch-all-middleware.d.ts.map +1 -1
  52. package/build-types/middlewares/http-v1.d.ts +8 -3
  53. package/build-types/middlewares/http-v1.d.ts.map +1 -1
  54. package/build-types/middlewares/media-upload.d.ts +5 -4
  55. package/build-types/middlewares/media-upload.d.ts.map +1 -1
  56. package/build-types/middlewares/namespace-endpoint.d.ts +4 -3
  57. package/build-types/middlewares/namespace-endpoint.d.ts.map +1 -1
  58. package/build-types/middlewares/nonce.d.ts +9 -4
  59. package/build-types/middlewares/nonce.d.ts.map +1 -1
  60. package/build-types/middlewares/preloading.d.ts +8 -4
  61. package/build-types/middlewares/preloading.d.ts.map +1 -1
  62. package/build-types/middlewares/root-url.d.ts +8 -4
  63. package/build-types/middlewares/root-url.d.ts.map +1 -1
  64. package/build-types/middlewares/theme-preview.d.ts +8 -4
  65. package/build-types/middlewares/theme-preview.d.ts.map +1 -1
  66. package/build-types/middlewares/user-locale.d.ts +4 -3
  67. package/build-types/middlewares/user-locale.d.ts.map +1 -1
  68. package/build-types/types.d.ts +4 -3
  69. package/build-types/types.d.ts.map +1 -1
  70. package/build-types/utils/response.d.ts +13 -5
  71. package/build-types/utils/response.d.ts.map +1 -1
  72. package/package.json +4 -4
  73. package/src/{index.js → index.ts} +49 -46
  74. package/src/middlewares/{fetch-all-middleware.js → fetch-all-middleware.ts} +24 -20
  75. package/src/middlewares/{http-v1.js → http-v1.ts} +8 -6
  76. package/src/middlewares/{media-upload.js → media-upload.ts} +10 -9
  77. package/src/middlewares/{namespace-endpoint.js → namespace-endpoint.ts} +7 -2
  78. package/src/middlewares/{nonce.js → nonce.ts} +15 -7
  79. package/src/middlewares/{preloading.js → preloading.ts} +21 -11
  80. package/src/middlewares/root-url.ts +47 -0
  81. package/src/middlewares/test/{fetch-all-middleware.js → fetch-all-middleware.ts} +1 -1
  82. package/src/middlewares/test/{http-v1.js → http-v1.ts} +7 -4
  83. package/src/middlewares/test/{media-upload.js → media-upload.ts} +2 -1
  84. package/src/middlewares/test/{namespace-endpoint.js → namespace-endpoint.ts} +2 -1
  85. package/src/middlewares/test/{nonce.js → nonce.ts} +5 -4
  86. package/src/middlewares/test/{preloading.js → preloading.ts} +31 -11
  87. package/src/middlewares/test/{root-url.js → root-url.ts} +2 -1
  88. package/src/middlewares/test/{user-locale.js → user-locale.ts} +9 -8
  89. package/src/middlewares/theme-preview.ts +60 -0
  90. package/src/middlewares/{user-locale.js → user-locale.ts} +4 -2
  91. package/src/types.ts +10 -5
  92. package/src/utils/{response.js → response.ts} +18 -15
  93. package/tsconfig.tsbuildinfo +1 -1
  94. package/src/middlewares/root-url.js +0 -44
  95. package/src/middlewares/theme-preview.js +0 -42
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/api-fetch",
3
- "version": "7.28.1-next.0f6f9d12c.0",
3
+ "version": "7.29.1-next.e256d081a.0",
4
4
  "description": "Utility to make WordPress REST API requests.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -30,11 +30,11 @@
30
30
  "types": "build-types",
31
31
  "dependencies": {
32
32
  "@babel/runtime": "7.25.7",
33
- "@wordpress/i18n": "^6.1.1-next.0f6f9d12c.0",
34
- "@wordpress/url": "^4.28.1-next.0f6f9d12c.0"
33
+ "@wordpress/i18n": "^6.2.1-next.e256d081a.0",
34
+ "@wordpress/url": "^4.29.1-next.e256d081a.0"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public"
38
38
  },
39
- "gitHead": "7d4f4367e2f76deddf4a09b540e6b2f9f4c3fe9f"
39
+ "gitHead": "7d529ba9a461795d5f1572d3856de33f744287c2"
40
40
  }
@@ -19,14 +19,17 @@ import {
19
19
  parseResponseAndNormalizeError,
20
20
  parseAndThrowError,
21
21
  } from './utils/response';
22
+ import type {
23
+ APIFetchMiddleware,
24
+ APIFetchOptions,
25
+ FetchHandler,
26
+ } from './types';
22
27
 
23
28
  /**
24
29
  * Default set of header values which should be sent with every request unless
25
30
  * explicitly provided through apiFetch options.
26
- *
27
- * @type {Record<string, string>}
28
31
  */
29
- const DEFAULT_HEADERS = {
32
+ const DEFAULT_HEADERS: APIFetchOptions[ 'headers' ] = {
30
33
  // The backend uses the Accept header as a condition for considering an
31
34
  // incoming request as a REST request.
32
35
  //
@@ -37,20 +40,12 @@ const DEFAULT_HEADERS = {
37
40
  /**
38
41
  * Default set of fetch option values which should be sent with every request
39
42
  * unless explicitly provided through apiFetch options.
40
- *
41
- * @type {Object}
42
43
  */
43
- const DEFAULT_OPTIONS = {
44
+ const DEFAULT_OPTIONS: APIFetchOptions = {
44
45
  credentials: 'include',
45
46
  };
46
47
 
47
- /** @typedef {import('./types').APIFetchMiddleware} APIFetchMiddleware */
48
- /** @typedef {import('./types').APIFetchOptions} APIFetchOptions */
49
-
50
- /**
51
- * @type {import('./types').APIFetchMiddleware[]}
52
- */
53
- const middlewares = [
48
+ const middlewares: Array< APIFetchMiddleware > = [
54
49
  userLocaleMiddleware,
55
50
  namespaceEndpointMiddleware,
56
51
  httpV1Middleware,
@@ -60,9 +55,9 @@ const middlewares = [
60
55
  /**
61
56
  * Register a middleware
62
57
  *
63
- * @param {import('./types').APIFetchMiddleware} middleware
58
+ * @param middleware
64
59
  */
65
- function registerMiddleware( middleware ) {
60
+ function registerMiddleware( middleware: APIFetchMiddleware ) {
66
61
  middlewares.unshift( middleware );
67
62
  }
68
63
 
@@ -70,10 +65,10 @@ function registerMiddleware( middleware ) {
70
65
  * Checks the status of a response, throwing the Response as an error if
71
66
  * it is outside the 200 range.
72
67
  *
73
- * @param {Response} response
74
- * @return {Response} The response if the status is in the 200 range.
68
+ * @param response
69
+ * @return The response if the status is in the 200 range.
75
70
  */
76
- const checkStatus = ( response ) => {
71
+ const checkStatus = ( response: Response ) => {
77
72
  if ( response.status >= 200 && response.status < 300 ) {
78
73
  return response;
79
74
  }
@@ -81,12 +76,7 @@ const checkStatus = ( response ) => {
81
76
  throw response;
82
77
  };
83
78
 
84
- /** @typedef {(options: import('./types').APIFetchOptions) => Promise<any>} FetchHandler*/
85
-
86
- /**
87
- * @type {FetchHandler}
88
- */
89
- const defaultFetchHandler = ( nextOptions ) => {
79
+ const defaultFetchHandler: FetchHandler = ( nextOptions ) => {
90
80
  const { url, path, data, parse = true, ...remainingOptions } = nextOptions;
91
81
  let { body, headers } = nextOptions;
92
82
 
@@ -134,32 +124,48 @@ const defaultFetchHandler = ( nextOptions ) => {
134
124
  );
135
125
  };
136
126
 
137
- /** @type {FetchHandler} */
138
127
  let fetchHandler = defaultFetchHandler;
139
128
 
140
129
  /**
141
130
  * Defines a custom fetch handler for making the requests that will override
142
131
  * the default one using window.fetch
143
132
  *
144
- * @param {FetchHandler} newFetchHandler The new fetch handler
133
+ * @param newFetchHandler The new fetch handler
145
134
  */
146
- function setFetchHandler( newFetchHandler ) {
135
+ function setFetchHandler( newFetchHandler: FetchHandler ) {
147
136
  fetchHandler = newFetchHandler;
148
137
  }
149
138
 
139
+ interface apiFetch {
140
+ < T, Parse extends boolean = true >(
141
+ options: APIFetchOptions< Parse >
142
+ ): Promise< Parse extends true ? T : Response >;
143
+ nonceEndpoint?: string;
144
+ nonceMiddleware?: ReturnType< typeof createNonceMiddleware >;
145
+ use: ( middleware: APIFetchMiddleware ) => void;
146
+ setFetchHandler: ( newFetchHandler: FetchHandler ) => void;
147
+ createNonceMiddleware: typeof createNonceMiddleware;
148
+ createPreloadingMiddleware: typeof createPreloadingMiddleware;
149
+ createRootURLMiddleware: typeof createRootURLMiddleware;
150
+ fetchAllMiddleware: typeof fetchAllMiddleware;
151
+ mediaUploadMiddleware: typeof mediaUploadMiddleware;
152
+ createThemePreviewMiddleware: typeof createThemePreviewMiddleware;
153
+ }
154
+
150
155
  /**
151
- * @template T
152
- * @param {import('./types').APIFetchOptions} options
153
- * @return {Promise<T>} A promise representing the request processed via the registered middlewares.
156
+ * Fetch
157
+ *
158
+ * @param options The options for the fetch.
159
+ * @return A promise representing the request processed via the registered middlewares.
154
160
  */
155
- function apiFetch( options ) {
161
+ const apiFetch: apiFetch = ( options ) => {
156
162
  // creates a nested function chain that calls all middlewares and finally the `fetchHandler`,
157
163
  // converting `middlewares = [ m1, m2, m3 ]` into:
158
164
  // ```
159
165
  // opts1 => m1( opts1, opts2 => m2( opts2, opts3 => m3( opts3, fetchHandler ) ) );
160
166
  // ```
161
- const enhancedHandler = middlewares.reduceRight(
162
- ( /** @type {FetchHandler} */ next, middleware ) => {
167
+ const enhancedHandler = middlewares.reduceRight< FetchHandler >(
168
+ ( next, middleware ) => {
163
169
  return ( workingOptions ) => middleware( workingOptions, next );
164
170
  },
165
171
  fetchHandler
@@ -171,20 +177,16 @@ function apiFetch( options ) {
171
177
  }
172
178
 
173
179
  // If the nonce is invalid, refresh it and try again.
174
- return (
175
- window
176
- // @ts-ignore
177
- .fetch( apiFetch.nonceEndpoint )
178
- .then( checkStatus )
179
- .then( ( data ) => data.text() )
180
- .then( ( text ) => {
181
- // @ts-ignore
182
- apiFetch.nonceMiddleware.nonce = text;
183
- return apiFetch( options );
184
- } )
185
- );
180
+ return window
181
+ .fetch( apiFetch.nonceEndpoint! )
182
+ .then( checkStatus )
183
+ .then( ( data ) => data.text() )
184
+ .then( ( text ) => {
185
+ apiFetch.nonceMiddleware!.nonce = text;
186
+ return apiFetch( options );
187
+ } );
186
188
  } );
187
- }
189
+ };
188
190
 
189
191
  apiFetch.use = registerMiddleware;
190
192
  apiFetch.setFetchHandler = setFetchHandler;
@@ -197,3 +199,4 @@ apiFetch.mediaUploadMiddleware = mediaUploadMiddleware;
197
199
  apiFetch.createThemePreviewMiddleware = createThemePreviewMiddleware;
198
200
 
199
201
  export default apiFetch;
202
+ export * from './types';
@@ -7,15 +7,19 @@ import { addQueryArgs } from '@wordpress/url';
7
7
  * Internal dependencies
8
8
  */
9
9
  import apiFetch from '..';
10
+ import type { APIFetchMiddleware, APIFetchOptions } from '../types';
10
11
 
11
12
  /**
12
13
  * Apply query arguments to both URL and Path, whichever is present.
13
14
  *
14
- * @param {import('../types').APIFetchOptions} props
15
- * @param {Record<string, string | number>} queryArgs
16
- * @return {import('../types').APIFetchOptions} The request with the modified query args
15
+ * @param {APIFetchOptions} props The request options
16
+ * @param {Record< string, string | number >} queryArgs
17
+ * @return The request with the modified query args
17
18
  */
18
- const modifyQuery = ( { path, url, ...options }, queryArgs ) => ( {
19
+ const modifyQuery = (
20
+ { path, url, ...options }: APIFetchOptions,
21
+ queryArgs: Record< string, string | number >
22
+ ): APIFetchOptions => ( {
19
23
  ...options,
20
24
  url: url && addQueryArgs( url, queryArgs ),
21
25
  path: path && addQueryArgs( path, queryArgs ),
@@ -24,17 +28,17 @@ const modifyQuery = ( { path, url, ...options }, queryArgs ) => ( {
24
28
  /**
25
29
  * Duplicates parsing functionality from apiFetch.
26
30
  *
27
- * @param {Response} response
28
- * @return {Promise<any>} Parsed response json.
31
+ * @param response
32
+ * @return Parsed response json.
29
33
  */
30
- const parseResponse = ( response ) =>
34
+ const parseResponse = ( response: Response ) =>
31
35
  response.json ? response.json() : Promise.reject( response );
32
36
 
33
37
  /**
34
- * @param {string | null} linkHeader
35
- * @return {{ next?: string }} The parsed link header.
38
+ * @param linkHeader
39
+ * @return The parsed link header.
36
40
  */
37
- const parseLinkHeader = ( linkHeader ) => {
41
+ const parseLinkHeader = ( linkHeader: string | null ) => {
38
42
  if ( ! linkHeader ) {
39
43
  return {};
40
44
  }
@@ -47,19 +51,19 @@ const parseLinkHeader = ( linkHeader ) => {
47
51
  };
48
52
 
49
53
  /**
50
- * @param {Response} response
51
- * @return {string | undefined} The next page URL.
54
+ * @param response
55
+ * @return The next page URL.
52
56
  */
53
- const getNextPageUrl = ( response ) => {
57
+ const getNextPageUrl = ( response: Response ) => {
54
58
  const { next } = parseLinkHeader( response.headers.get( 'link' ) );
55
59
  return next;
56
60
  };
57
61
 
58
62
  /**
59
- * @param {import('../types').APIFetchOptions} options
60
- * @return {boolean} True if the request contains an unbounded query.
63
+ * @param options
64
+ * @return True if the request contains an unbounded query.
61
65
  */
62
- const requestContainsUnboundedQuery = ( options ) => {
66
+ const requestContainsUnboundedQuery = ( options: APIFetchOptions ) => {
63
67
  const pathIsUnbounded =
64
68
  !! options.path && options.path.indexOf( 'per_page=-1' ) !== -1;
65
69
  const urlIsUnbounded =
@@ -71,10 +75,10 @@ const requestContainsUnboundedQuery = ( options ) => {
71
75
  * The REST API enforces an upper limit on the per_page option. To handle large
72
76
  * collections, apiFetch consumers can pass `per_page=-1`; this middleware will
73
77
  * then recursively assemble a full response array from all available pages.
74
- *
75
- * @type {import('../types').APIFetchMiddleware}
78
+ * @param options
79
+ * @param next
76
80
  */
77
- const fetchAllMiddleware = async ( options, next ) => {
81
+ const fetchAllMiddleware: APIFetchMiddleware = async ( options, next ) => {
78
82
  if ( options.parse === false ) {
79
83
  // If a consumer has opted out of parsing, do not apply middleware.
80
84
  return next( options );
@@ -108,7 +112,7 @@ const fetchAllMiddleware = async ( options, next ) => {
108
112
  }
109
113
 
110
114
  // Iteratively fetch all remaining pages until no "next" header is found.
111
- let mergedResults = /** @type {any[]} */ ( [] ).concat( results );
115
+ let mergedResults = ( [] as Array< any > ).concat( results );
112
116
  while ( nextPage ) {
113
117
  const nextResponse = await apiFetch( {
114
118
  ...options,
@@ -1,7 +1,10 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { APIFetchMiddleware } from '../types';
5
+
1
6
  /**
2
7
  * Set of HTTP methods which are eligible to be overridden.
3
- *
4
- * @type {Set<string>}
5
8
  */
6
9
  const OVERRIDE_METHODS = new Set( [ 'PATCH', 'PUT', 'DELETE' ] );
7
10
 
@@ -12,8 +15,6 @@ const OVERRIDE_METHODS = new Set( [ 'PATCH', 'PUT', 'DELETE' ] );
12
15
  * is `GET`."
13
16
  *
14
17
  * @see https://fetch.spec.whatwg.org/#requests
15
- *
16
- * @type {string}
17
18
  */
18
19
  const DEFAULT_METHOD = 'GET';
19
20
 
@@ -21,9 +22,10 @@ const DEFAULT_METHOD = 'GET';
21
22
  * API Fetch middleware which overrides the request method for HTTP v1
22
23
  * compatibility leveraging the REST API X-HTTP-Method-Override header.
23
24
  *
24
- * @type {import('../types').APIFetchMiddleware}
25
+ * @param options
26
+ * @param next
25
27
  */
26
- const httpV1Middleware = ( options, next ) => {
28
+ const httpV1Middleware: APIFetchMiddleware = ( options, next ) => {
27
29
  const { method = DEFAULT_METHOD } = options;
28
30
  if ( OVERRIDE_METHODS.has( method.toUpperCase() ) ) {
29
31
  options = {
@@ -10,12 +10,13 @@ import {
10
10
  parseAndThrowError,
11
11
  parseResponseAndNormalizeError,
12
12
  } from '../utils/response';
13
+ import type { APIFetchOptions, APIFetchMiddleware } from '../types';
13
14
 
14
15
  /**
15
- * @param {import('../types').APIFetchOptions} options
16
- * @return {boolean} True if the request is for media upload.
16
+ * @param options
17
+ * @return True if the request is for media upload.
17
18
  */
18
- function isMediaUploadRequest( options ) {
19
+ function isMediaUploadRequest( options: APIFetchOptions ) {
19
20
  const isCreateMethod = !! options.method && options.method === 'POST';
20
21
  const isMediaEndpoint =
21
22
  ( !! options.path && options.path.indexOf( '/wp/v2/media' ) !== -1 ) ||
@@ -26,10 +27,10 @@ function isMediaUploadRequest( options ) {
26
27
 
27
28
  /**
28
29
  * Middleware handling media upload failures and retries.
29
- *
30
- * @type {import('../types').APIFetchMiddleware}
30
+ * @param options
31
+ * @param next
31
32
  */
32
- const mediaUploadMiddleware = ( options, next ) => {
33
+ const mediaUploadMiddleware: APIFetchMiddleware = ( options, next ) => {
33
34
  if ( ! isMediaUploadRequest( options ) ) {
34
35
  return next( options );
35
36
  }
@@ -38,10 +39,10 @@ const mediaUploadMiddleware = ( options, next ) => {
38
39
  const maxRetries = 5;
39
40
 
40
41
  /**
41
- * @param {string} attachmentId
42
- * @return {Promise<any>} Processed post response.
42
+ * @param attachmentId
43
+ * @return Processed post response.
43
44
  */
44
- const postProcess = ( attachmentId ) => {
45
+ const postProcess = ( attachmentId: string ): Promise< any > => {
45
46
  retries++;
46
47
  return next( {
47
48
  path: `/wp/v2/media/${ attachmentId }/post-process`,
@@ -1,7 +1,12 @@
1
1
  /**
2
- * @type {import('../types').APIFetchMiddleware}
2
+ * Internal dependencies
3
3
  */
4
- const namespaceAndEndpointMiddleware = ( options, next ) => {
4
+ import type { APIFetchMiddleware } from '../types';
5
+
6
+ const namespaceAndEndpointMiddleware: APIFetchMiddleware = (
7
+ options,
8
+ next
9
+ ) => {
5
10
  let path = options.path;
6
11
  let namespaceTrimmed, endpointTrimmed;
7
12
 
@@ -1,12 +1,20 @@
1
1
  /**
2
- * @param {string} nonce
3
- * @return {import('../types').APIFetchMiddleware & { nonce: string }} A middleware to enhance a request with a nonce.
2
+ * Internal dependencies
4
3
  */
5
- function createNonceMiddleware( nonce ) {
6
- /**
7
- * @type {import('../types').APIFetchMiddleware & { nonce: string }}
8
- */
9
- const middleware = ( options, next ) => {
4
+ import type { APIFetchMiddleware } from '../types';
5
+
6
+ /**
7
+ * @param nonce
8
+ *
9
+ * @return A middleware to enhance a request with a nonce.
10
+ */
11
+ function createNonceMiddleware(
12
+ nonce: string
13
+ ): APIFetchMiddleware & { nonce: string } {
14
+ const middleware: APIFetchMiddleware & { nonce: string } = (
15
+ options,
16
+ next
17
+ ) => {
10
18
  const { headers = {} } = options;
11
19
 
12
20
  // If an 'X-WP-Nonce' header (or any case-insensitive variation
@@ -4,10 +4,17 @@
4
4
  import { addQueryArgs, getQueryArgs, normalizePath } from '@wordpress/url';
5
5
 
6
6
  /**
7
- * @param {Record<string, any>} preloadedData
8
- * @return {import('../types').APIFetchMiddleware} Preloading middleware.
7
+ * Internal dependencies
9
8
  */
10
- function createPreloadingMiddleware( preloadedData ) {
9
+ import type { APIFetchMiddleware } from '../types';
10
+
11
+ /**
12
+ * @param preloadedData
13
+ * @return Preloading middleware.
14
+ */
15
+ function createPreloadingMiddleware(
16
+ preloadedData: Record< string, any >
17
+ ): APIFetchMiddleware {
11
18
  const cache = Object.fromEntries(
12
19
  Object.entries( preloadedData ).map( ( [ path, data ] ) => [
13
20
  normalizePath( path ),
@@ -17,7 +24,6 @@ function createPreloadingMiddleware( preloadedData ) {
17
24
 
18
25
  return ( options, next ) => {
19
26
  const { parse = true } = options;
20
- /** @type {string | void} */
21
27
  let rawPath = options.path;
22
28
  if ( ! rawPath && options.url ) {
23
29
  const { rest_route: pathFromQuery, ...queryArgs } = getQueryArgs(
@@ -63,11 +69,14 @@ function createPreloadingMiddleware( preloadedData ) {
63
69
  /**
64
70
  * This is a helper function that sends a success response.
65
71
  *
66
- * @param {Record<string, any>} responseData
67
- * @param {boolean} parse
68
- * @return {Promise<any>} Promise with the response.
72
+ * @param responseData
73
+ * @param parse
74
+ * @return Promise with the response.
69
75
  */
70
- function prepareResponse( responseData, parse ) {
76
+ function prepareResponse(
77
+ responseData: Record< string, any >,
78
+ parse: boolean
79
+ ) {
71
80
  if ( parse ) {
72
81
  return Promise.resolve( responseData.body );
73
82
  }
@@ -82,12 +91,13 @@ function prepareResponse( responseData, parse ) {
82
91
  );
83
92
  } catch {
84
93
  // See: https://github.com/WordPress/gutenberg/issues/67358#issuecomment-2621163926.
85
- Object.entries( responseData.headers ).forEach( ( [ key, value ] ) => {
94
+ Object.entries(
95
+ responseData.headers as Record< string, string >
96
+ ).forEach( ( [ key, value ] ) => {
86
97
  if ( key.toLowerCase() === 'link' ) {
87
98
  responseData.headers[ key ] = value.replace(
88
99
  /<([^>]+)>/,
89
- ( /** @type {any} */ _, /** @type {string} */ url ) =>
90
- `<${ encodeURI( url ) }>`
100
+ ( _, url ) => `<${ encodeURI( url ) }>`
91
101
  );
92
102
  }
93
103
  } );
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { APIFetchMiddleware } from '../types';
5
+ import namespaceAndEndpointMiddleware from './namespace-endpoint';
6
+
7
+ /**
8
+ * @param rootURL
9
+ * @return Root URL middleware.
10
+ */
11
+ const createRootURLMiddleware =
12
+ ( rootURL: string ): APIFetchMiddleware =>
13
+ ( options, next ) => {
14
+ return namespaceAndEndpointMiddleware( options, ( optionsWithPath ) => {
15
+ let url = optionsWithPath.url;
16
+ let path = optionsWithPath.path;
17
+ let apiRoot;
18
+
19
+ if ( typeof path === 'string' ) {
20
+ apiRoot = rootURL;
21
+
22
+ if ( -1 !== rootURL.indexOf( '?' ) ) {
23
+ path = path.replace( '?', '&' );
24
+ }
25
+
26
+ path = path.replace( /^\//, '' );
27
+
28
+ // API root may already include query parameter prefix if site is
29
+ // configured to use plain permalinks.
30
+ if (
31
+ 'string' === typeof apiRoot &&
32
+ -1 !== apiRoot.indexOf( '?' )
33
+ ) {
34
+ path = path.replace( '?', '&' );
35
+ }
36
+
37
+ url = apiRoot + path;
38
+ }
39
+
40
+ return next( {
41
+ ...optionsWithPath,
42
+ url,
43
+ } );
44
+ } );
45
+ };
46
+
47
+ export default createRootURLMiddleware;
@@ -19,7 +19,7 @@ describe( 'Fetch All Middleware', () => {
19
19
  expect.hasAssertions();
20
20
  const originalOptions = { url: '/posts?per_page=-1' };
21
21
  let counter = 1;
22
- jest.doMock( '../../index.js', () => ( options ) => {
22
+ jest.doMock( '../../index.ts', () => ( options ) => {
23
23
  const expectedUrl =
24
24
  counter === 1
25
25
  ? '/posts?per_page=100'
@@ -1,15 +1,18 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
+ import type { FetchHandler } from '../../types';
4
5
  import httpV1Middleware from '../http-v1';
5
6
 
6
7
  describe( 'HTTP v1 Middleware', () => {
7
8
  it( 'should use a POST for a PUT requests', () => {
8
9
  expect.hasAssertions();
9
10
 
10
- const callback = ( options ) => {
11
+ const callback: FetchHandler = async ( options ) => {
11
12
  expect( options.method ).toBe( 'POST' );
12
- expect( options.headers[ 'X-HTTP-Method-Override' ] ).toBe( 'PUT' );
13
+ expect( options.headers![ 'X-HTTP-Method-Override' ] ).toBe(
14
+ 'PUT'
15
+ );
13
16
  };
14
17
 
15
18
  httpV1Middleware( { method: 'PUT', data: {} }, callback );
@@ -19,7 +22,7 @@ describe( 'HTTP v1 Middleware', () => {
19
22
  expect.hasAssertions();
20
23
 
21
24
  const requestOptions = { method: 'GET', path: '/wp/v2/posts' };
22
- const callback = ( options ) => {
25
+ const callback: FetchHandler = async ( options ) => {
23
26
  expect( options ).toBe( requestOptions );
24
27
  };
25
28
 
@@ -30,7 +33,7 @@ describe( 'HTTP v1 Middleware', () => {
30
33
  expect.hasAssertions();
31
34
 
32
35
  const requestOptions = { path: '/wp/v2/posts' };
33
- const callback = ( options ) => {
36
+ const callback: FetchHandler = async ( options ) => {
34
37
  expect( options ).toBe( requestOptions );
35
38
  };
36
39
 
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
+ import type { FetchHandler } from '../../types';
4
5
  import mediaUploadMiddleware from '../media-upload';
5
6
 
6
7
  describe( 'Media Upload Middleware', () => {
@@ -8,7 +9,7 @@ describe( 'Media Upload Middleware', () => {
8
9
  expect.hasAssertions();
9
10
 
10
11
  const originalOptions = { path: '/wp/v2/media' };
11
- const next = ( options ) => {
12
+ const next: FetchHandler = async ( options ) => {
12
13
  expect( options ).toBe( originalOptions );
13
14
  };
14
15
 
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
+ import type { FetchHandler } from '../../types';
4
5
  import namespaceEndpointMiddleware from '../namespace-endpoint';
5
6
 
6
7
  describe( 'Namespace & Endpoint middleware', () => {
@@ -12,7 +13,7 @@ describe( 'Namespace & Endpoint middleware', () => {
12
13
  namespace: '/wp/v2',
13
14
  endpoint: '/posts',
14
15
  };
15
- const callback = ( options ) => {
16
+ const callback: FetchHandler = async ( options ) => {
16
17
  expect( options.path ).toBe( 'wp/v2/posts' );
17
18
  expect( options.namespace ).toBeUndefined();
18
19
  expect( options.endpoint ).toBeUndefined();
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
+ import type { FetchHandler } from '../../types';
4
5
  import createNonceMiddleware from '../nonce';
5
6
 
6
7
  describe( 'Nonce middleware', () => {
@@ -13,8 +14,8 @@ describe( 'Nonce middleware', () => {
13
14
  method: 'GET',
14
15
  path: '/wp/v2/posts',
15
16
  };
16
- const callback = ( options ) => {
17
- expect( options.headers[ 'X-WP-Nonce' ] ).toBe( nonce );
17
+ const callback: FetchHandler = async ( options ) => {
18
+ expect( options.headers![ 'X-WP-Nonce' ] ).toBe( nonce );
18
19
  };
19
20
 
20
21
  nonceMiddleware( requestOptions, callback );
@@ -31,8 +32,8 @@ describe( 'Nonce middleware', () => {
31
32
  headers: { 'X-WP-Nonce': 'existing nonce' },
32
33
  };
33
34
 
34
- const callback = ( options ) => {
35
- expect( options.headers[ 'X-WP-Nonce' ] ).toBe( 'new nonce' );
35
+ const callback: FetchHandler = async ( options ) => {
36
+ expect( options.headers![ 'X-WP-Nonce' ] ).toBe( 'new nonce' );
36
37
  };
37
38
 
38
39
  nonceMiddleware( requestOptions, callback );