camox 0.33.0 → 0.33.1
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/components/AuthGate.js +5 -4
- package/dist/features/agent-chat/components/AgentChatThread.js +9 -10
- package/dist/features/preview/components/AssetLightbox.js +10 -9
- package/dist/features/preview/components/PreviewToolbar.js +3 -3
- package/dist/hooks/use-file-upload.js +3 -1
- package/dist/lib/api-client.js +6 -3
- package/dist/lib/auth.js +18 -15
- package/dist/lib/queries.js +6 -4
- package/package.json +4 -4
|
@@ -4,13 +4,14 @@ import { c } from "react/compiler-runtime";
|
|
|
4
4
|
//#region src/components/AuthGate.tsx
|
|
5
5
|
function AuthGate(t0) {
|
|
6
6
|
const $ = c(1);
|
|
7
|
-
if ($[0] !== "
|
|
7
|
+
if ($[0] !== "6de4384ece40c4b5e89894da23db2a5fb013bb295503fd2026710f49f69dd9a6") {
|
|
8
8
|
for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
9
|
-
$[0] = "
|
|
9
|
+
$[0] = "6de4384ece40c4b5e89894da23db2a5fb013bb295503fd2026710f49f69dd9a6";
|
|
10
10
|
}
|
|
11
|
-
const { authenticated, unauthenticated } = t0;
|
|
11
|
+
const { authenticated, unauthenticated, loading: t1 } = t0;
|
|
12
|
+
const loading = t1 === void 0 ? null : t1;
|
|
12
13
|
const { isAuthenticated, isLoading } = useAuthState();
|
|
13
|
-
if (isLoading) return
|
|
14
|
+
if (isLoading) return loading;
|
|
14
15
|
return isAuthenticated ? authenticated : unauthenticated;
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getAuthCookieHeader } from "../../../lib/auth.js";
|
|
1
|
+
import { getAuthCookieHeader, getAuthRequestCredentials } from "../../../lib/auth.js";
|
|
2
2
|
import { getApiClient, getApiUrl, getEnvironmentName } from "../../../lib/api-client.js";
|
|
3
3
|
import { cn } from "../../../lib/utils.js";
|
|
4
4
|
import { previewStore } from "../../preview/previewStore.js";
|
|
@@ -106,9 +106,9 @@ const markdownComponents = {
|
|
|
106
106
|
};
|
|
107
107
|
const MessageBubble = (t0) => {
|
|
108
108
|
const $ = c(34);
|
|
109
|
-
if ($[0] !== "
|
|
109
|
+
if ($[0] !== "72801e2c76f8ef7f0ac3d1552518592bffad57042b24f366613bc1344cfe95d3") {
|
|
110
110
|
for (let $i = 0; $i < 34; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
111
|
-
$[0] = "
|
|
111
|
+
$[0] = "72801e2c76f8ef7f0ac3d1552518592bffad57042b24f366613bc1344cfe95d3";
|
|
112
112
|
}
|
|
113
113
|
const { message, source, isThinkingActive, activeThinkingDurationKeys, thinkingDurations, toolLabelContext, onApprovalResponse } = t0;
|
|
114
114
|
const isUser = message.role === "user";
|
|
@@ -226,9 +226,9 @@ const MessageBubble = (t0) => {
|
|
|
226
226
|
};
|
|
227
227
|
const AgentThinkingIndicator = (t0) => {
|
|
228
228
|
const $ = c(7);
|
|
229
|
-
if ($[0] !== "
|
|
229
|
+
if ($[0] !== "72801e2c76f8ef7f0ac3d1552518592bffad57042b24f366613bc1344cfe95d3") {
|
|
230
230
|
for (let $i = 0; $i < 7; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
231
|
-
$[0] = "
|
|
231
|
+
$[0] = "72801e2c76f8ef7f0ac3d1552518592bffad57042b24f366613bc1344cfe95d3";
|
|
232
232
|
}
|
|
233
233
|
const { durationSeconds } = t0;
|
|
234
234
|
if (durationSeconds !== void 0) {
|
|
@@ -283,16 +283,15 @@ const AgentChatThread = ({ projectId, currentPath, source, disabled, focusKey =
|
|
|
283
283
|
return createPageScaffoldMessages(pageScaffoldContext);
|
|
284
284
|
}, [pageScaffoldContext]);
|
|
285
285
|
const connection = React.useMemo(() => fetchServerSentEvents(`${getApiUrl()}/agent/chat`, () => {
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
};
|
|
286
|
+
const authCookieHeader = getAuthCookieHeader();
|
|
287
|
+
const headers = { "x-camox-client": "studio" };
|
|
288
|
+
if (authCookieHeader) headers["Better-Auth-Cookie"] = authCookieHeader;
|
|
290
289
|
const environmentName = getEnvironmentName();
|
|
291
290
|
if (environmentName) headers["x-environment-name"] = environmentName;
|
|
292
291
|
if (__CAMOX_TELEMETRY_DISABLED__) headers["x-camox-telemetry-disabled"] = "1";
|
|
293
292
|
return {
|
|
294
293
|
headers,
|
|
295
|
-
credentials:
|
|
294
|
+
credentials: getAuthRequestCredentials(authCookieHeader),
|
|
296
295
|
body: {
|
|
297
296
|
projectId,
|
|
298
297
|
currentPath,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getAuthCookieHeader } from "../../../lib/auth.js";
|
|
1
|
+
import { getAuthCookieHeader, getAuthRequestCredentials } from "../../../lib/auth.js";
|
|
2
2
|
import { getApiUrl, getEnvironmentName } from "../../../lib/api-client.js";
|
|
3
3
|
import { fileMutations, fileQueries } from "../../../lib/queries.js";
|
|
4
4
|
import { trackClientEvent } from "../../../lib/telemetry-client.js";
|
|
@@ -21,9 +21,9 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@camox/ui/tooltip";
|
|
|
21
21
|
//#region src/features/preview/components/AssetLightbox.tsx
|
|
22
22
|
function MetadataRow(t0) {
|
|
23
23
|
const $ = c(9);
|
|
24
|
-
if ($[0] !== "
|
|
24
|
+
if ($[0] !== "57c6d07de7206779e7a888ace2e7d9e6b374e2f3c9aed614f5bd25f704694553") {
|
|
25
25
|
for (let $i = 0; $i < 9; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
26
|
-
$[0] = "
|
|
26
|
+
$[0] = "57c6d07de7206779e7a888ace2e7d9e6b374e2f3c9aed614f5bd25f704694553";
|
|
27
27
|
}
|
|
28
28
|
const { label, children } = t0;
|
|
29
29
|
let t1;
|
|
@@ -67,9 +67,9 @@ function MetadataRow(t0) {
|
|
|
67
67
|
}
|
|
68
68
|
function DeliveredSize(t0) {
|
|
69
69
|
const $ = c(16);
|
|
70
|
-
if ($[0] !== "
|
|
70
|
+
if ($[0] !== "57c6d07de7206779e7a888ace2e7d9e6b374e2f3c9aed614f5bd25f704694553") {
|
|
71
71
|
for (let $i = 0; $i < 16; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
72
|
-
$[0] = "
|
|
72
|
+
$[0] = "57c6d07de7206779e7a888ace2e7d9e6b374e2f3c9aed614f5bd25f704694553";
|
|
73
73
|
}
|
|
74
74
|
const { bytes, raw } = t0;
|
|
75
75
|
if (bytes == null) {
|
|
@@ -138,9 +138,9 @@ function DeliveredSize(t0) {
|
|
|
138
138
|
}
|
|
139
139
|
function DeliveredLabel(t0) {
|
|
140
140
|
const $ = c(4);
|
|
141
|
-
if ($[0] !== "
|
|
141
|
+
if ($[0] !== "57c6d07de7206779e7a888ace2e7d9e6b374e2f3c9aed614f5bd25f704694553") {
|
|
142
142
|
for (let $i = 0; $i < 4; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
143
|
-
$[0] = "
|
|
143
|
+
$[0] = "57c6d07de7206779e7a888ace2e7d9e6b374e2f3c9aed614f5bd25f704694553";
|
|
144
144
|
}
|
|
145
145
|
const { children } = t0;
|
|
146
146
|
let t1;
|
|
@@ -302,12 +302,13 @@ const AssetLightbox = ({ open, onOpenChange, fileId }) => {
|
|
|
302
302
|
formData.append("file", droppedFile);
|
|
303
303
|
formData.append("projectId", String(file?.projectId ?? 0));
|
|
304
304
|
const envName = getEnvironmentName();
|
|
305
|
+
const authCookieHeader = getAuthCookieHeader();
|
|
305
306
|
const uploadRes = await fetch(`${getApiUrl()}/files/upload`, {
|
|
306
307
|
method: "POST",
|
|
307
308
|
body: formData,
|
|
308
|
-
credentials:
|
|
309
|
+
credentials: getAuthRequestCredentials(authCookieHeader),
|
|
309
310
|
headers: {
|
|
310
|
-
"Better-Auth-Cookie":
|
|
311
|
+
...authCookieHeader ? { "Better-Auth-Cookie": authCookieHeader } : {},
|
|
311
312
|
...envName ? { "x-environment-name": envName } : {}
|
|
312
313
|
}
|
|
313
314
|
});
|
|
@@ -16,9 +16,9 @@ import { Toggle } from "@camox/ui/toggle";
|
|
|
16
16
|
//#region src/features/preview/components/PreviewToolbar.tsx
|
|
17
17
|
const PreviewToolbar = (t0) => {
|
|
18
18
|
const $ = c(68);
|
|
19
|
-
if ($[0] !== "
|
|
19
|
+
if ($[0] !== "68e35a20462160afd6c2aeaffaf03edcd93240318bca212e17001e624c1d829c") {
|
|
20
20
|
for (let $i = 0; $i < 68; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
21
|
-
$[0] = "
|
|
21
|
+
$[0] = "68e35a20462160afd6c2aeaffaf03edcd93240318bca212e17001e624c1d829c";
|
|
22
22
|
}
|
|
23
23
|
const { onEditModeChange } = t0;
|
|
24
24
|
const isEditMode = useSelector(previewStore, _temp);
|
|
@@ -297,7 +297,7 @@ const PreviewToolbar = (t0) => {
|
|
|
297
297
|
let t37;
|
|
298
298
|
if ($[65] !== t36 || $[66] !== t5) {
|
|
299
299
|
t37 = /* @__PURE__ */ jsxs(FloatingToolbar, {
|
|
300
|
-
className: "bottom-2 justify-between gap-8",
|
|
300
|
+
className: "bottom-2 justify-between gap-8 transition-none",
|
|
301
301
|
children: [t5, t36]
|
|
302
302
|
});
|
|
303
303
|
$[65] = t36;
|
|
@@ -40,8 +40,10 @@ function useFileUpload(options) {
|
|
|
40
40
|
formData.append("file", file);
|
|
41
41
|
formData.append("projectId", String(projectIdRef.current ?? 0));
|
|
42
42
|
const uploadUrl = `${apiUrl}/files/upload`;
|
|
43
|
+
const authCookieHeader = getAuthCookieHeader();
|
|
43
44
|
xhr.open("POST", uploadUrl);
|
|
44
|
-
xhr.
|
|
45
|
+
xhr.withCredentials = !authCookieHeader;
|
|
46
|
+
if (authCookieHeader) xhr.setRequestHeader("Better-Auth-Cookie", authCookieHeader);
|
|
45
47
|
const envName = getEnvironmentName();
|
|
46
48
|
if (envName) xhr.setRequestHeader("x-environment-name", envName);
|
|
47
49
|
xhr.send(formData);
|
package/dist/lib/api-client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getAuthCookieHeader } from "./auth.js";
|
|
1
|
+
import { getAuthCookieHeader, getAuthRequestCredentials } from "./auth.js";
|
|
2
2
|
import { createORPCClient } from "@orpc/client";
|
|
3
3
|
import { RPCLink } from "@orpc/client/fetch";
|
|
4
4
|
import { createTanstackQueryUtils } from "@orpc/tanstack-query";
|
|
@@ -18,10 +18,13 @@ function initApiClient(apiUrl, environmentName) {
|
|
|
18
18
|
url: `${apiUrl}/rpc`,
|
|
19
19
|
headers,
|
|
20
20
|
fetch: (request, init) => {
|
|
21
|
-
|
|
21
|
+
const authCookieHeader = getAuthCookieHeader();
|
|
22
|
+
if (request instanceof Request) {
|
|
23
|
+
if (authCookieHeader) request.headers.set("Better-Auth-Cookie", authCookieHeader);
|
|
24
|
+
}
|
|
22
25
|
return fetch(request, {
|
|
23
26
|
...init,
|
|
24
|
-
credentials:
|
|
27
|
+
credentials: getAuthRequestCredentials(authCookieHeader)
|
|
25
28
|
});
|
|
26
29
|
}
|
|
27
30
|
}));
|
package/dist/lib/auth.js
CHANGED
|
@@ -86,6 +86,9 @@ function getAuthCookieHeader() {
|
|
|
86
86
|
writeServerAuthCookie(cookie);
|
|
87
87
|
return cookie;
|
|
88
88
|
}
|
|
89
|
+
function getAuthRequestCredentials(authCookieHeader = getAuthCookieHeader()) {
|
|
90
|
+
return authCookieHeader ? "omit" : "include";
|
|
91
|
+
}
|
|
89
92
|
function crossDomainClient(opts = {}) {
|
|
90
93
|
let store = null;
|
|
91
94
|
const cookieName = `${opts?.storagePrefix || "better-auth"}_cookie`;
|
|
@@ -154,10 +157,10 @@ function crossDomainClient(opts = {}) {
|
|
|
154
157
|
options = options || {};
|
|
155
158
|
const cookie = getCookie(storage.getItem(cookieName) || "{}");
|
|
156
159
|
writeServerAuthCookie(cookie);
|
|
157
|
-
options.credentials =
|
|
160
|
+
options.credentials = getAuthRequestCredentials(cookie);
|
|
158
161
|
options.headers = {
|
|
159
162
|
...options.headers,
|
|
160
|
-
"Better-Auth-Cookie": cookie
|
|
163
|
+
...cookie ? { "Better-Auth-Cookie": cookie } : {}
|
|
161
164
|
};
|
|
162
165
|
if (url.includes("/sign-out")) {
|
|
163
166
|
await storage.setItem(cookieName, "{}");
|
|
@@ -195,9 +198,9 @@ function createCamoxAuthClient(apiUrl) {
|
|
|
195
198
|
*/
|
|
196
199
|
function useProcessOtt(authClient) {
|
|
197
200
|
const $ = c(5);
|
|
198
|
-
if ($[0] !== "
|
|
201
|
+
if ($[0] !== "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a") {
|
|
199
202
|
for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
200
|
-
$[0] = "
|
|
203
|
+
$[0] = "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a";
|
|
201
204
|
}
|
|
202
205
|
const [ready, setReady] = React.useState(_temp);
|
|
203
206
|
let t0;
|
|
@@ -240,9 +243,9 @@ function _temp() {
|
|
|
240
243
|
const AuthContext = React.createContext(null);
|
|
241
244
|
function useAuthContext() {
|
|
242
245
|
const $ = c(1);
|
|
243
|
-
if ($[0] !== "
|
|
246
|
+
if ($[0] !== "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a") {
|
|
244
247
|
for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
245
|
-
$[0] = "
|
|
248
|
+
$[0] = "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a";
|
|
246
249
|
}
|
|
247
250
|
const ctx = React.useContext(AuthContext);
|
|
248
251
|
if (!ctx) throw new Error("Missing CamoxProvider");
|
|
@@ -250,9 +253,9 @@ function useAuthContext() {
|
|
|
250
253
|
}
|
|
251
254
|
function useProjectSlug() {
|
|
252
255
|
const $ = c(1);
|
|
253
|
-
if ($[0] !== "
|
|
256
|
+
if ($[0] !== "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a") {
|
|
254
257
|
for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
255
|
-
$[0] = "
|
|
258
|
+
$[0] = "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a";
|
|
256
259
|
}
|
|
257
260
|
return useAuthContext().projectSlug;
|
|
258
261
|
}
|
|
@@ -266,18 +269,18 @@ function useAuthState() {
|
|
|
266
269
|
}
|
|
267
270
|
function useIsAuthenticated() {
|
|
268
271
|
const $ = c(1);
|
|
269
|
-
if ($[0] !== "
|
|
272
|
+
if ($[0] !== "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a") {
|
|
270
273
|
for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
271
|
-
$[0] = "
|
|
274
|
+
$[0] = "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a";
|
|
272
275
|
}
|
|
273
276
|
const { isAuthenticated } = useAuthState();
|
|
274
277
|
return isAuthenticated;
|
|
275
278
|
}
|
|
276
279
|
function useSignInRedirect(callbackHref) {
|
|
277
280
|
const $ = c(4);
|
|
278
|
-
if ($[0] !== "
|
|
281
|
+
if ($[0] !== "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a") {
|
|
279
282
|
for (let $i = 0; $i < 4; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
280
|
-
$[0] = "
|
|
283
|
+
$[0] = "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a";
|
|
281
284
|
}
|
|
282
285
|
const { authenticationUrl } = useAuthContext();
|
|
283
286
|
let t0;
|
|
@@ -299,9 +302,9 @@ function useSignInRedirect(callbackHref) {
|
|
|
299
302
|
*/
|
|
300
303
|
function useAuthActions() {
|
|
301
304
|
const $ = c(5);
|
|
302
|
-
if ($[0] !== "
|
|
305
|
+
if ($[0] !== "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a") {
|
|
303
306
|
for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
|
|
304
|
-
$[0] = "
|
|
307
|
+
$[0] = "de1e25b4541f6fe08a345d66b09411c24ed6cbe00d71d076f92227895feaae4a";
|
|
305
308
|
}
|
|
306
309
|
const { authClient, authenticationUrl } = useAuthContext();
|
|
307
310
|
let t0;
|
|
@@ -359,4 +362,4 @@ function _temp2() {
|
|
|
359
362
|
}
|
|
360
363
|
|
|
361
364
|
//#endregion
|
|
362
|
-
export { AuthContext, buildClearServerAuthCookieHeader, createCamoxAuthClient, getAuthCookieHeader, getServerAuthCookieHeader, useAuthActions, useAuthContext, useAuthState, useIsAuthenticated, useProcessOtt, useProjectSlug, useSignInRedirect };
|
|
365
|
+
export { AuthContext, buildClearServerAuthCookieHeader, createCamoxAuthClient, getAuthCookieHeader, getAuthRequestCredentials, getServerAuthCookieHeader, useAuthActions, useAuthContext, useAuthState, useIsAuthenticated, useProcessOtt, useProjectSlug, useSignInRedirect };
|
package/dist/lib/queries.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getAuthCookieHeader } from "./auth.js";
|
|
1
|
+
import { getAuthCookieHeader, getAuthRequestCredentials } from "./auth.js";
|
|
2
2
|
import { getApiUrl, getEnvironmentName, getOrpc } from "./api-client.js";
|
|
3
3
|
import { queryKeys } from "@camox/api-contract/query-keys";
|
|
4
4
|
|
|
@@ -130,7 +130,9 @@ const repeatableItemMutations = {
|
|
|
130
130
|
updatePosition: () => getOrpc().repeatableItems.updatePosition.mutationOptions()
|
|
131
131
|
};
|
|
132
132
|
function ogImageHeaders() {
|
|
133
|
-
const
|
|
133
|
+
const authCookieHeader = getAuthCookieHeader();
|
|
134
|
+
const headers = {};
|
|
135
|
+
if (authCookieHeader) headers["Better-Auth-Cookie"] = authCookieHeader;
|
|
134
136
|
const envName = getEnvironmentName();
|
|
135
137
|
if (envName) headers["x-environment-name"] = envName;
|
|
136
138
|
return headers;
|
|
@@ -153,7 +155,7 @@ const pageMutations = {
|
|
|
153
155
|
method: "POST",
|
|
154
156
|
body: formData,
|
|
155
157
|
headers: ogImageHeaders(),
|
|
156
|
-
credentials:
|
|
158
|
+
credentials: getAuthRequestCredentials()
|
|
157
159
|
});
|
|
158
160
|
if (!res.ok) {
|
|
159
161
|
const body = await res.json().catch(() => null);
|
|
@@ -165,7 +167,7 @@ const pageMutations = {
|
|
|
165
167
|
const res = await fetch(`${getApiUrl()}/pages/${pageId}/og-image`, {
|
|
166
168
|
method: "DELETE",
|
|
167
169
|
headers: ogImageHeaders(),
|
|
168
|
-
credentials:
|
|
170
|
+
credentials: getAuthRequestCredentials()
|
|
169
171
|
});
|
|
170
172
|
if (!res.ok) throw new Error(`Delete failed: ${res.status}`);
|
|
171
173
|
return res.json();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "camox",
|
|
3
|
-
"version": "0.33.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"camox": "./bin/camox.mjs"
|
|
@@ -130,9 +130,9 @@
|
|
|
130
130
|
"shiki": "^4.1.0",
|
|
131
131
|
"streamdown": "^2.5.0",
|
|
132
132
|
"zod": "^4.4.3",
|
|
133
|
-
"@camox/api-contract": "0.33.
|
|
134
|
-
"@camox/
|
|
135
|
-
"@camox/
|
|
133
|
+
"@camox/api-contract": "0.33.1",
|
|
134
|
+
"@camox/cli": "0.33.1",
|
|
135
|
+
"@camox/ui": "0.33.1"
|
|
136
136
|
},
|
|
137
137
|
"devDependencies": {
|
|
138
138
|
"@babel/core": "^7.29.0",
|