PluginProbe
Extendify / 3.2.2
Extendify v3.2.2
3.2.2 3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 All 128 releases
extendify / src / Shared / api / DataApi.js

DataApi.js in Extendify 3.2.2, at src/Shared/api/DataApi.js

117 lines 3.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { AI_HOST, INSIGHTS_HOST } from '@constants';
2 import { reqDataBasics } from '@shared/lib/data';
3 import { useImageGenerationStore } from '@shared/state/generate-images';
4 import apiFetch from '@wordpress/api-fetch';
5 import { __ } from '@wordpress/i18n';
6
7 const imageErrorMessage = (status) => {
8 if (status === 'content_policy_violation') {
9 // translators: shown when the AI image generator refuses a prompt on safety grounds.
10 return __(
11 'That request was blocked by our safety system. Try a different description.',
12 'extendify-local',
13 );
14 }
15 if (status === 'no_image_returned') {
16 // translators: shown when the AI image generator returns nothing, cause unknown.
17 return __(
18 "Couldn't create that image. Try describing it differently.",
19 'extendify-local',
20 );
21 }
22 return __('Service temporarily unavailable', 'extendify-local');
23 };
24
25 const creditsFromHeaders = (headers) => {
26 const read = (name) => {
27 const value = headers.get(name);
28 return value === null ? null : Number(value);
29 };
30 return {
31 remaining: read('x-ratelimit-remaining'),
32 total: read('x-ratelimit-limit'),
33 };
34 };
35
36 export const fetchImageCredits = async () => {
37 const url = new URL(`${AI_HOST}/api/draft/image`);
38 // The limiter keys on the site id, which a GET can only carry in the query.
39 url.searchParams.set('siteId', reqDataBasics.siteId ?? '');
40 const { headers } = await fetch(url, { mode: 'cors' });
41 const credits = creditsFromHeaders(headers);
42
43 if (credits.remaining === null)
44 throw new Error('Response reports no credits');
45
46 return credits;
47 };
48
49 export const generateImage = async (imageData, signal) => {
50 const response = await fetch(`${AI_HOST}/api/draft/image`, {
51 method: 'POST',
52 mode: 'cors',
53 headers: { 'Content-Type': 'application/json' },
54 signal: signal,
55 body: JSON.stringify({
56 ...imageData,
57 globalState: useImageGenerationStore.getState(),
58 ...reqDataBasics,
59 }),
60 });
61
62 const body = await response.json();
63
64 const imageCredits = creditsFromHeaders(response.headers);
65
66 if (!response.ok) {
67 throw { message: imageErrorMessage(body.status), imageCredits };
68 }
69 return {
70 images: body,
71 imageCredits,
72 id: response.headers.get('x-request-id'),
73 };
74 };
75
76 export const recordPluginActivity = async ({ slug, source }) => {
77 try {
78 const res = await fetch(`${INSIGHTS_HOST}/api/v1/plugin-install`, {
79 method: 'POST',
80 headers: { 'Content-Type': 'application/json', 'X-Extendify': 'true' },
81 body: JSON.stringify({
82 ...reqDataBasics,
83 slug,
84 source,
85 siteCreatedAt: window.extSharedData?.siteCreatedAt,
86 }),
87 });
88
89 // this should not break the app.
90 if (!res.ok) {
91 console.error('Bad response from server');
92 return null;
93 }
94
95 return await res.json();
96 } catch (error) {
97 console.error('Error sending plugin installation notification:', error);
98 return null;
99 }
100 };
101
102 export const pingServer = async () =>
103 await apiFetch({ path: '/extendify/v1/shared/ping' });
104
105 export const getPartnerPlugins = async (key) => {
106 const plugins = await apiFetch({
107 path: '/extendify/v1/shared/partner-plugins',
108 });
109 if (!Object.keys(plugins?.data ?? {}).length) {
110 throw new Error('Could not get plugins');
111 }
112 if (key && plugins.data?.[key]) {
113 return plugins.data[key];
114 }
115 return plugins.data;
116 };
117