strapi5-plugin-for-stripe 1.0.0 → 1.0.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.
@@ -0,0 +1,564 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { useFetchClient, Page } from "@strapi/strapi/admin";
3
+ import { Routes, Route } from "react-router-dom";
4
+ import { useState, useEffect } from "react";
5
+ import { Box, Flex, Typography, Button, Table, Thead, Tr, Th, Tbody, Td, IconButtonGroup, IconButton, Alert, SingleSelect, SingleSelectOption, NumberInput, TextInput } from "@strapi/design-system";
6
+ import { CodeBlock, Pencil, Trash } from "@strapi/icons";
7
+ const HomePage = () => {
8
+ const { get, post, del, put } = useFetchClient();
9
+ const [productsAndPrices, setProductsAndPrices] = useState({
10
+ prices: [],
11
+ products: []
12
+ });
13
+ const [settings, setSettings] = useState({});
14
+ const [isModalOpen, setIsModalOpen] = useState(false);
15
+ const [mode, setMode] = useState("create");
16
+ const [hasChanges, setHasChanges] = useState(false);
17
+ const [isEmbedModalOpen, setIsEmbedModalOpen] = useState(false);
18
+ const [selectedProduct, setSelectedProduct] = useState(null);
19
+ const [editingIndex, setEditingIndex] = useState(null);
20
+ const [paymentType, setPaymentType] = useState("oneTime");
21
+ const [name, setName] = useState("");
22
+ const [price, setPrice] = useState(0);
23
+ const [paymentInterval, setPaymentInterval] = useState("");
24
+ const [trialPeriodDays, setTrialPeriodDays] = useState(0);
25
+ const [error, setError] = useState("");
26
+ const [success, setSuccess] = useState("");
27
+ const isSubscription = paymentType === "subscription";
28
+ const resetForm = () => {
29
+ setPaymentType("oneTime");
30
+ setName("");
31
+ setPrice();
32
+ setPaymentInterval("");
33
+ setTrialPeriodDays(0);
34
+ setHasChanges(false);
35
+ };
36
+ const loadProducts = async () => {
37
+ const res = await get("/strapi5-plugin-stripe/products");
38
+ setProductsAndPrices(res.data);
39
+ };
40
+ const getSettings = async () => {
41
+ const res = await get("/strapi5-plugin-stripe/settings");
42
+ setSettings(res.data || {});
43
+ };
44
+ useEffect(() => {
45
+ loadProducts();
46
+ getSettings();
47
+ }, []);
48
+ const openCreateModal = () => {
49
+ setMode("create");
50
+ resetForm();
51
+ setIsModalOpen(true);
52
+ };
53
+ const openEditModal = (product, price2, index) => {
54
+ setMode("edit");
55
+ setHasChanges(false);
56
+ setEditingIndex(index);
57
+ setName(product.name);
58
+ setPrice(price2.unit_amount / 100);
59
+ if (price2.recurring) {
60
+ setPaymentType("subscription");
61
+ setPaymentInterval(
62
+ price2.recurring.interval_count ? `${price2.recurring.interval_count}${price2.recurring.interval}s` : price2.recurring.interval
63
+ );
64
+ setTrialPeriodDays(price2.recurring.trial_period_days || 0);
65
+ } else {
66
+ setPaymentType("oneTime");
67
+ setPaymentInterval("");
68
+ setTrialPeriodDays(0);
69
+ }
70
+ setIsModalOpen(true);
71
+ };
72
+ const createProduct = async () => {
73
+ setError("");
74
+ setSuccess("");
75
+ try {
76
+ await post("/strapi5-plugin-stripe/products", {
77
+ currency: settings.currency,
78
+ unit_amount: price * 100,
79
+ product_data: {
80
+ name
81
+ },
82
+ ...isSubscription && {
83
+ recurring: {
84
+ interval: paymentInterval.includes("2") || paymentInterval.includes("6") ? paymentInterval.slice(1, paymentInterval.length - 1) : paymentInterval,
85
+ interval_count: paymentInterval.includes("2") ? "2" : paymentInterval.includes("6") ? "6" : null,
86
+ trial_period_days: isSubscription ? trialPeriodDays : null
87
+ }
88
+ }
89
+ });
90
+ setSuccess("Product created successfully.");
91
+ setIsModalOpen(false);
92
+ resetForm();
93
+ loadProducts();
94
+ } catch (err) {
95
+ setError(
96
+ err?.response?.data?.error?.message || err?.response?.data?.message || err?.message || "An unexpected error occurred."
97
+ );
98
+ }
99
+ };
100
+ const deleteProduct = async (productId, priceId) => {
101
+ setError("");
102
+ setSuccess("");
103
+ try {
104
+ await del(`/strapi5-plugin-stripe/products/${productId}&${priceId}`);
105
+ setSuccess("Product deleted successfully.");
106
+ loadProducts();
107
+ } catch (err) {
108
+ setError(
109
+ err?.response?.data?.error?.message || err?.response?.data?.message || err?.message || "An unexpected error occurred."
110
+ );
111
+ }
112
+ };
113
+ const updateProduct = async (productArr, priceArr) => {
114
+ setError("");
115
+ setSuccess("");
116
+ try {
117
+ let productUpdate = {};
118
+ let mustCreateNewPrice = false;
119
+ if (name !== productArr.name) {
120
+ productUpdate.name = name;
121
+ }
122
+ if (Object.keys(productUpdate).length > 0) {
123
+ await put(
124
+ `/strapi5-plugin-stripe/products/${productArr.id}`,
125
+ productUpdate
126
+ );
127
+ }
128
+ if (priceArr.unit_amount !== price * 100) {
129
+ mustCreateNewPrice = true;
130
+ }
131
+ if (priceArr.recurring) {
132
+ const currentInterval = priceArr.recurring.interval_count ? `${priceArr.recurring.interval_count}${priceArr.recurring.interval}s` : priceArr.recurring.interval;
133
+ if (currentInterval !== paymentInterval) {
134
+ mustCreateNewPrice = true;
135
+ }
136
+ if (priceArr.recurring.trial_period_days !== trialPeriodDays) {
137
+ mustCreateNewPrice = true;
138
+ }
139
+ }
140
+ if (mustCreateNewPrice) {
141
+ const newPrice = await post("/strapi5-plugin-stripe/products", {
142
+ currency: priceArr.currency,
143
+ unit_amount: price * 100,
144
+ product: productArr.id,
145
+ ...isSubscription && {
146
+ recurring: {
147
+ interval: paymentInterval.includes("2") || paymentInterval.includes("6") ? paymentInterval.slice(1, paymentInterval.length - 1) : paymentInterval,
148
+ interval_count: paymentInterval.includes("2") ? 2 : paymentInterval.includes("6") ? 6 : void 0,
149
+ trial_period_days: trialPeriodDays || void 0
150
+ }
151
+ }
152
+ });
153
+ await del(
154
+ `/strapi5-plugin-stripe/prices/${productArr.id}&${priceArr.id}&${newPrice.data.id}`
155
+ );
156
+ }
157
+ setSuccess("Product updated successfully.");
158
+ setIsModalOpen(false);
159
+ resetForm();
160
+ loadProducts();
161
+ } catch (err) {
162
+ setError(
163
+ err?.response?.data?.error?.message || err?.response?.data?.message || err?.message || "An unexpected error occurred."
164
+ );
165
+ }
166
+ };
167
+ const currencySymbol = (price2) => {
168
+ if (price2.currency === "eur") return "€";
169
+ if (price2.currency === "usd") return "$";
170
+ if (price2.currency === "gbp") return "£";
171
+ if (price2.currency === "cad") return "CA$";
172
+ };
173
+ return /* @__PURE__ */ jsxs(Box, { padding: 8, children: [
174
+ /* @__PURE__ */ jsxs(
175
+ Flex,
176
+ {
177
+ justifyContent: "space-between",
178
+ alignItems: "center",
179
+ paddingBottom: 6,
180
+ children: [
181
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", children: "Stripe Products" }),
182
+ /* @__PURE__ */ jsx(Button, { onClick: openCreateModal, children: "Create product" })
183
+ ]
184
+ }
185
+ ),
186
+ /* @__PURE__ */ jsxs(Table, { colCount: 5, rowCount: productsAndPrices.length, children: [
187
+ /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
188
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Name" }) }),
189
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Price" }) }),
190
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Type" }) }),
191
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Interval" }) }),
192
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "IDs" }) }),
193
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Actions" }) })
194
+ ] }) }),
195
+ /* @__PURE__ */ jsx(Tbody, { children: productsAndPrices.prices.map((elm, index) => {
196
+ return /* @__PURE__ */ jsxs(Tr, { children: [
197
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: productsAndPrices.products[index].name }) }),
198
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Typography, { children: [
199
+ elm.unit_amount / 100,
200
+ " ",
201
+ currencySymbol(elm)
202
+ ] }) }),
203
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: elm.type.split("_").map((word) => {
204
+ return word.charAt(0).toUpperCase() + word.slice(1) + " ";
205
+ }) }) }),
206
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: elm.recurring ? elm.recurring.interval_count ? elm.recurring.interval_count + " " + elm.recurring.interval + "s" : elm.recurring.interval : "-" }) }),
207
+ /* @__PURE__ */ jsxs(Td, { children: [
208
+ /* @__PURE__ */ jsx(
209
+ Typography,
210
+ {
211
+ background: "rgba(173, 216, 230, 0.3)",
212
+ padding: "5px",
213
+ borderRadius: "8px",
214
+ children: productsAndPrices.products[index].id
215
+ }
216
+ ),
217
+ /* @__PURE__ */ jsx(Typography, { children: ", " }),
218
+ /* @__PURE__ */ jsx(
219
+ Typography,
220
+ {
221
+ background: "rgba(173, 216, 230, 0.3)",
222
+ padding: "5px",
223
+ borderRadius: "8px",
224
+ children: elm.id
225
+ }
226
+ )
227
+ ] }),
228
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(IconButtonGroup, { children: [
229
+ /* @__PURE__ */ jsx(
230
+ IconButton,
231
+ {
232
+ onClick: () => {
233
+ setSelectedProduct({
234
+ product: productsAndPrices.products[index],
235
+ price: elm
236
+ });
237
+ setIsEmbedModalOpen(true);
238
+ },
239
+ children: /* @__PURE__ */ jsx(CodeBlock, {})
240
+ }
241
+ ),
242
+ /* @__PURE__ */ jsx(
243
+ IconButton,
244
+ {
245
+ variant: "secondary",
246
+ onClick: () => {
247
+ openEditModal(
248
+ productsAndPrices.products[index],
249
+ elm,
250
+ index
251
+ );
252
+ },
253
+ children: /* @__PURE__ */ jsx(Pencil, {})
254
+ }
255
+ ),
256
+ /* @__PURE__ */ jsx(
257
+ IconButton,
258
+ {
259
+ variant: "danger",
260
+ onClick: () => deleteProduct(
261
+ productsAndPrices.products[index].id,
262
+ elm.id
263
+ ),
264
+ children: /* @__PURE__ */ jsx(Trash, {})
265
+ }
266
+ )
267
+ ] }) })
268
+ ] }, elm.id);
269
+ }) })
270
+ ] }),
271
+ /* @__PURE__ */ jsx(Box, { paddingTop: 6, children: success && /* @__PURE__ */ jsx(Box, { paddingBottom: 4, children: /* @__PURE__ */ jsx(Alert, { variant: "success", title: "Success", children: success }) }) }),
272
+ isModalOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
273
+ /* @__PURE__ */ jsx(
274
+ Box,
275
+ {
276
+ position: "fixed",
277
+ top: 0,
278
+ left: 0,
279
+ width: "100vw",
280
+ height: "100vh",
281
+ background: "rgba(0,0,0,0.5)",
282
+ pointerEvents: "none",
283
+ onClick: () => {
284
+ setIsModalOpen(false);
285
+ resetForm();
286
+ }
287
+ }
288
+ ),
289
+ /* @__PURE__ */ jsx(
290
+ Box,
291
+ {
292
+ display: "flex",
293
+ style: {
294
+ flexDirection: "column",
295
+ justifyContent: "center",
296
+ position: "fixed",
297
+ top: "0",
298
+ left: "0",
299
+ width: "100%",
300
+ height: "100%"
301
+ },
302
+ children: /* @__PURE__ */ jsxs(
303
+ Box,
304
+ {
305
+ background: "neutral0",
306
+ width: "900px",
307
+ maxWidth: "90%",
308
+ margin: "auto",
309
+ borderRadius: "8px",
310
+ zIndex: 1e3,
311
+ children: [
312
+ /* @__PURE__ */ jsx(Box, { padding: 6, children: /* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", children: "Create Product / Subscription" }) }),
313
+ /* @__PURE__ */ jsx(Box, { padding: 6, children: /* @__PURE__ */ jsxs(Flex, { wrap: "wrap", gap: 4, children: [
314
+ /* @__PURE__ */ jsxs(Box, { width: "50%", children: [
315
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: "Payment Type" }),
316
+ /* @__PURE__ */ jsxs(
317
+ SingleSelect,
318
+ {
319
+ value: paymentType,
320
+ onChange: (value) => {
321
+ setPaymentType(value);
322
+ setHasChanges(true);
323
+ },
324
+ children: [
325
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "oneTime", children: "One-Time" }),
326
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "subscription", children: "Subscription" })
327
+ ]
328
+ }
329
+ )
330
+ ] }),
331
+ /* @__PURE__ */ jsxs(Box, { width: "50%", children: [
332
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: "Price" }),
333
+ /* @__PURE__ */ jsx(
334
+ NumberInput,
335
+ {
336
+ value: price,
337
+ onValueChange: (value) => {
338
+ setPrice(value);
339
+ setHasChanges(true);
340
+ },
341
+ required: true
342
+ }
343
+ )
344
+ ] }),
345
+ /* @__PURE__ */ jsxs(Box, { width: "50%", children: [
346
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: "Name" }),
347
+ /* @__PURE__ */ jsx(
348
+ TextInput,
349
+ {
350
+ value: name,
351
+ onChange: (e) => {
352
+ setName(e.target.value);
353
+ setHasChanges(true);
354
+ },
355
+ required: true
356
+ }
357
+ )
358
+ ] }),
359
+ /* @__PURE__ */ jsxs(Box, { width: "50%", children: [
360
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: "Payment Interval" }),
361
+ /* @__PURE__ */ jsxs(
362
+ SingleSelect,
363
+ {
364
+ value: paymentInterval,
365
+ onChange: (value) => {
366
+ setPaymentInterval(value);
367
+ setHasChanges(true);
368
+ },
369
+ disabled: paymentType !== "subscription",
370
+ children: [
371
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "week", children: "Every week" }),
372
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "2weeks", children: "Every 2 weeks" }),
373
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "month", children: "Every month" }),
374
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "6months", children: "Every 6 months" }),
375
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "year", children: "Every year" })
376
+ ]
377
+ }
378
+ )
379
+ ] }),
380
+ /* @__PURE__ */ jsxs(Box, { width: "50%", children: [
381
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: "Trial Period Days" }),
382
+ /* @__PURE__ */ jsx(
383
+ NumberInput,
384
+ {
385
+ value: trialPeriodDays,
386
+ onValueChange: (value) => {
387
+ setTrialPeriodDays(value);
388
+ setHasChanges(true);
389
+ },
390
+ disabled: paymentType !== "subscription"
391
+ }
392
+ )
393
+ ] })
394
+ ] }) }),
395
+ /* @__PURE__ */ jsx(Box, { padding: 6, children: error && /* @__PURE__ */ jsx(Box, { paddingBottom: 4, children: /* @__PURE__ */ jsx(Alert, { variant: "danger", title: "Action failed", children: error }) }) }),
396
+ /* @__PURE__ */ jsx(Box, { padding: 6, background: "neutral100", children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
397
+ /* @__PURE__ */ jsx(
398
+ Button,
399
+ {
400
+ variant: "tertiary",
401
+ onClick: () => {
402
+ setIsModalOpen(false);
403
+ },
404
+ children: "Cancel"
405
+ }
406
+ ),
407
+ /* @__PURE__ */ jsx(
408
+ Button,
409
+ {
410
+ onClick: () => mode === "create" ? createProduct() : updateProduct(
411
+ productsAndPrices.products[editingIndex],
412
+ productsAndPrices.prices[editingIndex]
413
+ ),
414
+ disabled: !hasChanges,
415
+ children: mode === "create" ? "Create" : "Update"
416
+ }
417
+ )
418
+ ] }) })
419
+ ]
420
+ }
421
+ )
422
+ }
423
+ )
424
+ ] }),
425
+ isEmbedModalOpen && selectedProduct && /* @__PURE__ */ jsxs(Fragment, { children: [
426
+ /* @__PURE__ */ jsx(
427
+ Box,
428
+ {
429
+ position: "fixed",
430
+ top: 0,
431
+ left: 0,
432
+ width: "100vw",
433
+ height: "100vh",
434
+ background: "rgba(0,0,0,0.5)",
435
+ onClick: () => {
436
+ setIsModalOpen(false);
437
+ resetForm();
438
+ },
439
+ zIndex: 90
440
+ }
441
+ ),
442
+ /* @__PURE__ */ jsx(
443
+ Box,
444
+ {
445
+ display: "flex",
446
+ style: {
447
+ flexDirection: "column",
448
+ justifyContent: "center",
449
+ position: "relative",
450
+ top: "-100px",
451
+ width: "100%",
452
+ height: "100%"
453
+ },
454
+ children: /* @__PURE__ */ jsxs(
455
+ Box,
456
+ {
457
+ background: "neutral0",
458
+ width: "900px",
459
+ maxWidth: "90%",
460
+ margin: "auto",
461
+ borderRadius: "8px",
462
+ zIndex: 100,
463
+ children: [
464
+ /* @__PURE__ */ jsx(Box, { padding: 6, children: /* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", children: "Payment button integration" }) }),
465
+ /* @__PURE__ */ jsxs(Box, { padding: 6, children: [
466
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: "1. Import the script" }),
467
+ /* @__PURE__ */ jsx(
468
+ Box,
469
+ {
470
+ background: "neutral100",
471
+ padding: 4,
472
+ borderRadius: "4px",
473
+ marginTop: 2,
474
+ children: /* @__PURE__ */ jsx("pre", { children: `<script>
475
+ window.addEventListener('load', () => {
476
+ document.querySelectorAll('[data-stripe-checkout]').forEach((btn) => {
477
+ btn.addEventListener('click', () => checkout(btn));
478
+ });
479
+
480
+ const sessionId = new URLSearchParams(location.search).get('session_id');
481
+ if (sessionId) retrieve(sessionId);
482
+ });
483
+
484
+ function checkout(btn) {
485
+ const apiUrl = btn.dataset.apiUrl;
486
+ const priceId = btn.dataset.priceId;
487
+
488
+ if (!apiUrl || !priceId) return;
489
+
490
+ const metadata = {};
491
+ Object.keys(btn.dataset).forEach((k) => {
492
+ if (k.startsWith('metadata')) {
493
+ metadata[k.replace('metadata', '').toLowerCase()] = btn.dataset[k];
494
+ }
495
+ });
496
+
497
+ fetch(apiUrl + "/api/strapi5-plugin-stripe/checkout", {
498
+ method: 'POST',
499
+ headers: { 'Content-Type': 'application/json' },
500
+ body: JSON.stringify({
501
+ priceId,
502
+ customer_email: btn.dataset.email,
503
+ metadata,
504
+ }),
505
+ })
506
+ .then((r) => r.json())
507
+ .then((r) => r.url && (location.href = r.url));
508
+ }
509
+ <\/script>` })
510
+ }
511
+ ),
512
+ /* @__PURE__ */ jsxs(Box, { paddingTop: 4, children: [
513
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: "2. Add the payment button" }),
514
+ /* @__PURE__ */ jsx(
515
+ Box,
516
+ {
517
+ background: "neutral100",
518
+ padding: 4,
519
+ borderRadius: "4px",
520
+ marginTop: 2,
521
+ children: /* @__PURE__ */ jsx("pre", { children: `<button
522
+ data-stripe-checkout
523
+ data-api-url="${window.location.origin}"
524
+ data-price-id="${selectedProduct.price.id}"
525
+ data-email="customer@email.com"
526
+ data-metadata-order-id="ORDER_123"
527
+ >
528
+ Pay now
529
+ </button>` })
530
+ }
531
+ )
532
+ ] }),
533
+ /* @__PURE__ */ jsxs(Box, { paddingTop: 4, children: [
534
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: "3. Notes" }),
535
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", children: [
536
+ /* @__PURE__ */ jsx("br", {}),
537
+ "• ",
538
+ /* @__PURE__ */ jsx("b", { children: "priceId" }),
539
+ " identifies the product price",
540
+ /* @__PURE__ */ jsx("br", {}),
541
+ "• Metadata is optional and available in webhooks",
542
+ /* @__PURE__ */ jsx("br", {}),
543
+ "• Redirect is handled automatically by Stripe, with the session ID as a query parameter"
544
+ ] })
545
+ ] })
546
+ ] }),
547
+ /* @__PURE__ */ jsx(Box, { padding: 6, background: "neutral100", children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(Button, { onClick: () => setIsEmbedModalOpen(false), children: "Close" }) }) })
548
+ ]
549
+ }
550
+ )
551
+ }
552
+ )
553
+ ] })
554
+ ] });
555
+ };
556
+ const App = () => {
557
+ return /* @__PURE__ */ jsxs(Routes, { children: [
558
+ /* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(HomePage, {}) }),
559
+ /* @__PURE__ */ jsx(Route, { path: "*", element: /* @__PURE__ */ jsx(Page.Error, {}) })
560
+ ] });
561
+ };
562
+ export {
563
+ App
564
+ };