PluginProbe
ElasticPress / 4.6.0
ElasticPress v4.6.0
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
elasticpress / assets / js / sync / hooks.js

hooks.js in ElasticPress 4.6.0, at assets/js/sync/hooks.js

219 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * WordPress dependencies.
3 */
4 import { useCallback, useRef } from '@wordpress/element';
5 import { __ } from '@wordpress/i18n';
6
7 /**
8 * Internal dependencies.
9 */
10 import { ajaxUrl, nonce } from './config';
11
12 /**
13 * Indexing hook.
14 *
15 * Provides methods for indexing, getting indexing status, and cancelling
16 * indexing. Methods share an abort controller so that requests can
17 * interrupt eachother to avoid multiple sync requests causing race conditions
18 * or duplicate output, such as by rapidly pausing and unpausing indexing.
19 *
20 * @returns {object} Sync, sync status, and cancel functions.
21 */
22 export const useIndex = () => {
23 const abort = useRef(new AbortController());
24 const request = useRef(null);
25
26 const onResponse = useCallback(
27 /**
28 * Handle the response to the request.
29 *
30 * @param {Response} response Request response.
31 * @throws {Error} An error for unexpected responses.
32 * @returns {void}
33 */
34 async (response) => {
35 const responseBody = await response.text();
36
37 const errorMessage = `${__(
38 'ElasticPress: Unexpected response.',
39 'elasticpress',
40 )}\n${responseBody}`;
41
42 /**
43 * Throw an error for non-20X responses.
44 */
45 if (!response.ok) {
46 if (response.status === 403) {
47 /**
48 * A 403 response will occur if the nonce has expired or
49 * if the user's session has expired. Reloading the page
50 * will reset the nonce or prompt the user to log in again.
51 */
52 throw new Error(
53 __(
54 'Permission denied. Reload the sync page and try again.',
55 'elasticpress',
56 ),
57 );
58 } else {
59 /**
60 * Log the raw response to the console to assist with
61 * debugging.
62 */
63 console.error(errorMessage); // eslint-disable-line no-console
64
65 /**
66 * Any other response is unexpected, and the user will
67 * need to troubleshoot.
68 */
69 throw new Error(
70 __(
71 'Something went wrong. Find troubleshooting steps at https://elasticpress.zendesk.com/hc/en-us/sections/360010868652-Troubleshooting.',
72 'elasticpress',
73 ),
74 );
75 }
76 }
77
78 /**
79 * Parse the response and throw an error if it fails.
80 */
81 try {
82 return JSON.parse(responseBody);
83 } catch (e) {
84 /**
85 * Log the raw response to the console to assist with
86 * debugging.
87 */
88 console.error(e.message); // eslint-disable-line no-console
89 console.error(errorMessage); // eslint-disable-line no-console
90
91 /**
92 * Invalid JSON is unexpected at this stage, and the user will
93 * need to troubleshoot.
94 */
95 throw new Error(
96 __(
97 'Unable to parse response. Find troubleshooting steps at https://elasticpress.zendesk.com/hc/en-us/sections/360010868652-Troubleshooting.',
98 'elasticpress',
99 ),
100 );
101 }
102 },
103 [],
104 );
105
106 const onComplete = useCallback(
107 /**
108 * Handle completion of the request, whether successful or not.
109 *
110 * @returns {void}
111 */
112 () => {
113 request.current = null;
114 },
115 [],
116 );
117
118 const sendRequest = useCallback(
119 /**
120 * Send AJAX request.
121 *
122 * Silently catches abort errors and clears the current request on
123 * completion.
124 *
125 * @param {object} options Request options.
126 * @throws {Error} Any non-abort errors.
127 * @returns {Promise} Current request promise.
128 */
129 (options) => {
130 request.current = fetch(ajaxUrl, options).then(onResponse).finally(onComplete);
131
132 return request.current;
133 },
134 [onComplete, onResponse],
135 );
136
137 const cancelIndex = useCallback(
138 /**
139 * Send a request to cancel sync.
140 *
141 * @returns {Promise} Fetch request promise.
142 */
143 async () => {
144 abort.current.abort();
145 abort.current = new AbortController();
146
147 const body = new FormData();
148
149 body.append('action', 'ep_cancel_index');
150 body.append('nonce', nonce);
151
152 const options = {
153 method: 'POST',
154 body,
155 signal: abort.current.signal,
156 };
157
158 return sendRequest(options);
159 },
160 [sendRequest],
161 );
162
163 const index = useCallback(
164 /**
165 * Send a request to sync.
166 *
167 * @param {boolean} putMapping Whether to put mapping.
168 * @returns {Promise} Fetch request promise.
169 */
170 async (putMapping) => {
171 abort.current.abort();
172 abort.current = new AbortController();
173
174 const body = new FormData();
175
176 body.append('action', 'ep_index');
177 body.append('put_mapping', putMapping ? 1 : 0);
178 body.append('nonce', nonce);
179
180 const options = {
181 method: 'POST',
182 body,
183 signal: abort.current.signal,
184 };
185
186 return sendRequest(options);
187 },
188 [sendRequest],
189 );
190
191 const indexStatus = useCallback(
192 /**
193 * Send a request for CLI sync status.
194 *
195 * @returns {Promise} Fetch request promise.
196 */
197 async () => {
198 abort.current.abort();
199 abort.current = new AbortController();
200
201 const body = new FormData();
202
203 body.append('action', 'ep_index_status');
204 body.append('nonce', nonce);
205
206 const options = {
207 method: 'POST',
208 body,
209 signal: abort.current.signal,
210 };
211
212 return sendRequest(options);
213 },
214 [sendRequest],
215 );
216
217 return { cancelIndex, index, indexStatus };
218 };
219