@strapi/admin 5.45.1 → 5.46.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/admin/admin/src/StrapiApp.js +2 -1
- package/dist/admin/admin/src/StrapiApp.js.map +1 -1
- package/dist/admin/admin/src/StrapiApp.mjs +2 -1
- package/dist/admin/admin/src/StrapiApp.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Date.js +2 -0
- package/dist/admin/admin/src/components/FormInputs/Date.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Date.mjs +2 -0
- package/dist/admin/admin/src/components/FormInputs/Date.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/DateTime.js +2 -0
- package/dist/admin/admin/src/components/FormInputs/DateTime.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/DateTime.mjs +2 -0
- package/dist/admin/admin/src/components/FormInputs/DateTime.mjs.map +1 -1
- package/dist/admin/admin/src/components/UpsellBanner.js +112 -61
- package/dist/admin/admin/src/components/UpsellBanner.js.map +1 -1
- package/dist/admin/admin/src/components/UpsellBanner.mjs +115 -64
- package/dist/admin/admin/src/components/UpsellBanner.mjs.map +1 -1
- package/dist/admin/admin/src/constants.js +5 -0
- package/dist/admin/admin/src/constants.js.map +1 -1
- package/dist/admin/admin/src/constants.mjs +5 -0
- package/dist/admin/admin/src/constants.mjs.map +1 -1
- package/dist/admin/admin/src/pages/ProfilePage.js +1 -1
- package/dist/admin/admin/src/pages/ProfilePage.js.map +1 -1
- package/dist/admin/admin/src/pages/ProfilePage.mjs +1 -1
- package/dist/admin/admin/src/pages/ProfilePage.mjs.map +1 -1
- package/dist/admin/admin/src/translations/de.json.js +2 -0
- package/dist/admin/admin/src/translations/de.json.js.map +1 -1
- package/dist/admin/admin/src/translations/de.json.mjs +2 -0
- package/dist/admin/admin/src/translations/de.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +3 -0
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +3 -0
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/es.json.js +3 -0
- package/dist/admin/admin/src/translations/es.json.js.map +1 -1
- package/dist/admin/admin/src/translations/es.json.mjs +3 -0
- package/dist/admin/admin/src/translations/es.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/fr.json.js +2 -0
- package/dist/admin/admin/src/translations/fr.json.js.map +1 -1
- package/dist/admin/admin/src/translations/fr.json.mjs +2 -0
- package/dist/admin/admin/src/translations/fr.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/tr.json.js +216 -1
- package/dist/admin/admin/src/translations/tr.json.js.map +1 -1
- package/dist/admin/admin/src/translations/tr.json.mjs +215 -2
- package/dist/admin/admin/src/translations/tr.json.mjs.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.js +15 -7
- package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.mjs +15 -7
- package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
- package/dist/admin/admin/tests/server.js +123 -119
- package/dist/admin/admin/tests/server.js.map +1 -1
- package/dist/admin/admin/tests/server.mjs +124 -120
- package/dist/admin/admin/tests/server.mjs.map +1 -1
- package/dist/admin/src/components/SubNav.d.ts +12 -4
- package/dist/admin/src/constants.d.ts +6 -0
- package/dist/admin/src/layouts/UnauthenticatedLayout.d.ts +4 -2
- package/dist/admin/src/pages/Settings/pages/Roles/components/CollapseLabel.d.ts +7 -3
- package/dist/admin/src/pages/Settings/pages/Roles/components/ConditionsButton.d.ts +4 -2
- package/dist/admin/src/pages/Settings/pages/Roles/components/HiddenAction.d.ts +1 -1
- package/dist/server/server/src/controllers/api-token.js +4 -5
- package/dist/server/server/src/controllers/api-token.js.map +1 -1
- package/dist/server/server/src/controllers/api-token.mjs +4 -5
- package/dist/server/server/src/controllers/api-token.mjs.map +1 -1
- package/dist/server/server/src/services/api-token.js +37 -18
- package/dist/server/server/src/services/api-token.js.map +1 -1
- package/dist/server/server/src/services/api-token.mjs +38 -19
- package/dist/server/server/src/services/api-token.mjs.map +1 -1
- package/dist/server/server/src/services/index.js +5 -2
- package/dist/server/server/src/services/index.js.map +1 -1
- package/dist/server/server/src/services/index.mjs +5 -2
- package/dist/server/server/src/services/index.mjs.map +1 -1
- package/dist/server/server/src/strategies/content-api-token.js +1 -1
- package/dist/server/server/src/strategies/content-api-token.js.map +1 -1
- package/dist/server/server/src/strategies/content-api-token.mjs +1 -1
- package/dist/server/server/src/strategies/content-api-token.mjs.map +1 -1
- package/dist/server/src/controllers/api-token.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +1 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/api-token.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +2 -0
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/package.json +10 -10
|
@@ -14,6 +14,8 @@ var light = "Açık";
|
|
|
14
14
|
var or = "YA DA";
|
|
15
15
|
var skipToContent = "İçeriğe atla";
|
|
16
16
|
var submit = "Gönder";
|
|
17
|
+
var noPreview = "Önizleme mevcut değil";
|
|
18
|
+
var selectButtonTitle = "Seç";
|
|
17
19
|
var tr = {
|
|
18
20
|
Analytics: Analytics,
|
|
19
21
|
"Auth.components.Oops.text": "Hesabın donduruldu.",
|
|
@@ -536,8 +538,219 @@ var tr = {
|
|
|
536
538
|
or: or,
|
|
537
539
|
"request.error.model.unknown": "Bu model bulunmamaktadır.",
|
|
538
540
|
skipToContent: skipToContent,
|
|
539
|
-
submit: submit
|
|
541
|
+
submit: submit,
|
|
542
|
+
"Auth.form.button.login.providers.error": "Seçilen sağlayıcı üzerinden bağlanılamıyor.",
|
|
543
|
+
"Auth.form.button.login.strapi": "Strapi ile giriş yap",
|
|
544
|
+
"Auth.form.confirmPassword.label": "Şifreyi Onayla",
|
|
545
|
+
"Auth.form.currentPassword.label": "Mevcut Şifre",
|
|
546
|
+
"HomePage.header.subtitle": "Yönetim panelinize hoş geldiniz",
|
|
547
|
+
"HomePage.header.title": "Merhaba {name}",
|
|
548
|
+
"HomePage.widget.error": "Widget içeriği yüklenemedi.",
|
|
549
|
+
"HomePage.widget.loading": "Widget içeriği yükleniyor",
|
|
550
|
+
"HomePage.widget.no-data": "Hiç içerik bulunamadı.",
|
|
551
|
+
"Roles & Permissions": "Roller ve İzinler",
|
|
552
|
+
"Roles.ListPage.notification.delete-all-not-allowed": "Bazı roller kullanıcılarla ilişkilendirildiği için silinemedi",
|
|
553
|
+
"Roles.ListPage.notification.delete-not-allowed": "Bir rol kullanıcılarla ilişkilendirilmişse silinemez",
|
|
554
|
+
"Roles.RoleRow.select-all": "{name} seç ve toplu işlem yap",
|
|
555
|
+
"Roles.RoleRow.user-count": "{number, plural, =0 {# kullanıcı} one {# kullanıcı} other {# kullanıcılar}}",
|
|
556
|
+
"Roles.components.List.empty.withSearch": "Aramayla eşleşen bir rol bulunamadı ({search})...",
|
|
557
|
+
"Settings.apiTokens.createPage.BoundRoute.title": "Bağlı rota",
|
|
558
|
+
"Settings.apiTokens.createPage.permissions.header.hint": "Uygulamanın veya eklentinin eylemlerini seçin ve bağlı rotayı görüntülemek için dişli simgesine tıklayın",
|
|
559
|
+
"Settings.apiTokens.createPage.permissions.header.title": "Gelişmiş ayarlar",
|
|
560
|
+
"Settings.apiTokens.createPage.title": "API Tokeni Oluştur",
|
|
561
|
+
"Settings.apiTokens.lastHour": "son saat",
|
|
562
|
+
"Settings.apiTokens.regenerate": "Yeniden oluştur",
|
|
563
|
+
"Settings.application.customization.auth-logo.carousel-hint": "Kimlik doğrulama sayfalarındaki logoyu değiştirin",
|
|
564
|
+
"Settings.application.customization.carousel.auth-logo.title": "Kimlik doğrulama logosu",
|
|
565
|
+
"Settings.application.customization.carousel.menu-logo.title": "Menü logosu",
|
|
566
|
+
"Settings.application.customization.menu-logo.carousel-hint": "Ana navigasyondaki logoyu değiştirin",
|
|
567
|
+
"Settings.application.customization.size-details": "Maks boyut: {dimension}×{dimension}, Maks dosya boyutu: {size}KB",
|
|
568
|
+
"Settings.application.ee-or-ce": "{communityEdition, select, true {Topluluk Sürümü} other {Kurumsal Sürüm}}",
|
|
569
|
+
"Settings.application.ee.admin-seats.add-seats": "{isHostedOnStrapiCloud, select, true {Koltuk ekle} other {Satış ekibiyle iletişime geç}}",
|
|
570
|
+
"Settings.application.ee.admin-seats.at-limit-tooltip": "Limitte: daha fazla kullanıcı davet etmek için koltuk ekleyin",
|
|
571
|
+
"Settings.application.ee.admin-seats.count": "<text>{enforcementUserCount}</text>/{permittedSeats}",
|
|
572
|
+
"Settings.content-history.description": "İçeriğinizin yaşam döngüsünün her adımında daha fazla kontrol elde edin.",
|
|
573
|
+
"Settings.content-history.not-available": "İçerik Geçmişi yalnızca ücretli bir planın parçası olarak sunulmaktadır. İçeriğinizin yaşam döngüsü üzerinde tam kontrol sağlamak için yükseltme yapın.",
|
|
574
|
+
"Settings.content-history.title": "İçerik Geçmişi",
|
|
575
|
+
"Settings.page.purchase.learn-more.cta": "Daha fazla",
|
|
576
|
+
"Settings.permissions.auditLogs.action": "Eylem",
|
|
577
|
+
"Settings.permissions.auditLogs.admin.auth.success": "Yönetici girişi",
|
|
578
|
+
"Settings.permissions.auditLogs.admin.logout": "Yönetici çıkışı",
|
|
579
|
+
"Settings.permissions.auditLogs.component.create": "Bileşen oluştur",
|
|
580
|
+
"Settings.permissions.auditLogs.component.delete": "Bileşeni sil",
|
|
581
|
+
"Settings.permissions.auditLogs.component.update": "Bileşeni güncelle",
|
|
582
|
+
"Settings.permissions.auditLogs.content-type.create": "İçerik türü oluştur",
|
|
583
|
+
"Settings.permissions.auditLogs.content-type.delete": "İçerik türünü sil",
|
|
584
|
+
"Settings.permissions.auditLogs.content-type.update": "İçerik türünü güncelle",
|
|
585
|
+
"Settings.permissions.auditLogs.date": "Tarih",
|
|
586
|
+
"Settings.permissions.auditLogs.details": "Kayıt Ayrıntıları",
|
|
587
|
+
"Settings.permissions.auditLogs.entry.create": "Girdi oluştur{model, select, undefined {} other { ({model})}}",
|
|
588
|
+
"Settings.permissions.auditLogs.entry.delete": "Girdiyi sil{model, select, undefined {} other { ({model})}}",
|
|
589
|
+
"Settings.permissions.auditLogs.entry.publish": "Girdiyi yayımla {model, select, undefined {} other {({model})}}",
|
|
590
|
+
"Settings.permissions.auditLogs.entry.unpublish": "Girdiyi yayından kaldır{model, select, undefined {} other { ({model})}}",
|
|
591
|
+
"Settings.permissions.auditLogs.entry.update": "Girdiyi güncelle{model, select, undefined {} other { ({model})}}",
|
|
592
|
+
"Settings.permissions.auditLogs.filters.combobox.aria-label": "Filtrelemek için bir seçenek arayın ve seçin",
|
|
593
|
+
"Settings.permissions.auditLogs.listview.header.subtitle": "Çevrenizde gerçekleşen tüm etkinliklerin kayıtları",
|
|
594
|
+
"Settings.permissions.auditLogs.media.create": "Medya oluştur",
|
|
595
|
+
"Settings.permissions.auditLogs.media.delete": "Medyayı sil",
|
|
596
|
+
"Settings.permissions.auditLogs.media.update": "Medyayı güncelle",
|
|
597
|
+
"Settings.permissions.auditLogs.not-available": "Denetim Kayıtları yalnızca ücretli bir planın parçası olarak sunulmaktadır. Tüm etkinliklerin aranabilir ve filtrelenebilir bir görüntüsünü almak için yükseltme yapın.",
|
|
598
|
+
"Settings.permissions.auditLogs.payload": "Yük",
|
|
599
|
+
"Settings.permissions.auditLogs.permission.create": "İzin oluştur",
|
|
600
|
+
"Settings.permissions.auditLogs.permission.delete": "İzni sil",
|
|
601
|
+
"Settings.permissions.auditLogs.permission.update": "İzni güncelle",
|
|
602
|
+
"Settings.permissions.auditLogs.role.create": "Rol oluştur",
|
|
603
|
+
"Settings.permissions.auditLogs.role.delete": "Rolü sil",
|
|
604
|
+
"Settings.permissions.auditLogs.role.update": "Rolü güncelle",
|
|
605
|
+
"Settings.permissions.auditLogs.user": "Kullanıcı",
|
|
606
|
+
"Settings.permissions.auditLogs.user.create": "Kullanıcı oluştur",
|
|
607
|
+
"Settings.permissions.auditLogs.user.delete": "Kullanıcıyı sil",
|
|
608
|
+
"Settings.permissions.auditLogs.user.fullname": "{firstname} {lastname}",
|
|
609
|
+
"Settings.permissions.auditLogs.user.update": "Kullanıcıyı güncelle",
|
|
610
|
+
"Settings.permissions.auditLogs.userId": "Kullanıcı ID",
|
|
611
|
+
"Settings.permissions.conditions.define-conditions": "Koşulları tanımla",
|
|
612
|
+
"Settings.permissions.users.sso.provider.error": "SSO ayarlarını talep ederken bir hata oluştu",
|
|
613
|
+
"Settings.profile.form.section.experience.mode.option-system-label": "Sistem ayarlarını kullan",
|
|
614
|
+
"Settings.sso.form.defaultRole.description": "Yeni kimlik doğrulanan kullanıcıyı seçilen role atar",
|
|
615
|
+
"Settings.sso.form.defaultRole.description-not-allowed": "Yönetici rolleri okuma iznine sahip olmalısınız",
|
|
616
|
+
"Settings.sso.form.defaultRole.label": "Varsayılan rol",
|
|
617
|
+
"Settings.sso.form.localAuthenticationLock.description": "Yerel kimlik doğrulamayı devre dışı bırakmak istediğiniz rolleri seçin",
|
|
618
|
+
"Settings.sso.form.localAuthenticationLock.label": "Yerel kimlik doğrulama kilidi",
|
|
619
|
+
"Settings.sso.not-available": "SSO yalnızca ücretli bir planın parçası olarak sunulmaktadır. Yönetim paneliniz için ek oturum açma ve kayıt yöntemlerini yapılandırmak için yükseltme yapın.",
|
|
620
|
+
"Settings.tokens.ListView.headers.createdAt": "Oluşturulma tarihi",
|
|
621
|
+
"Settings.tokens.ListView.headers.description": "Açıklama",
|
|
622
|
+
"Settings.tokens.ListView.headers.lastUsedAt": "Son kullanma",
|
|
623
|
+
"Settings.tokens.ListView.headers.name": "Ad",
|
|
624
|
+
"Settings.tokens.form.description": "Açıklama",
|
|
625
|
+
"Settings.tokens.form.name": "Ad",
|
|
626
|
+
"Settings.tokens.regenerate": "Yeniden oluştur",
|
|
627
|
+
"Settings.tokens.types.custom": "Özel",
|
|
628
|
+
"Settings.transferTokens.ListView.headers.type": "Token türü",
|
|
629
|
+
"Settings.transferTokens.addFirstToken": "İlk Transfer Tokeninizi Ekleyin",
|
|
630
|
+
"Settings.transferTokens.addNewToken": "Yeni Transfer Token Ekle",
|
|
631
|
+
"Settings.transferTokens.create": "Yeni Transfer Token Oluştur",
|
|
632
|
+
"Settings.transferTokens.createPage.title": "Transfer Token Oluştur",
|
|
633
|
+
"Settings.transferTokens.description": "Oluşturulan transfer tokenlarının listesi",
|
|
634
|
+
"Settings.transferTokens.emptyStateLayout": "Henüz içerik yok...",
|
|
635
|
+
"Settings.transferTokens.title": "Transfer Tokenları",
|
|
636
|
+
"Settings.webhooks.event.select": "Etkinlik seç",
|
|
637
|
+
"Settings.webhooks.events.delete": "Webhook'u sil",
|
|
638
|
+
"Settings.webhooks.events.isLoading": "Etkinlikler yükleniyor",
|
|
639
|
+
"Settings.webhooks.list.loading.success": "Webhook'lar yüklendi",
|
|
640
|
+
"Settings.webhooks.validation.key": "Anahtar gerekli",
|
|
641
|
+
"Settings.webhooks.validation.name.regex": "Ad bir harf ile başlamalı ve yalnızca harfler, sayılar, boşluklar ve alt çizgiler içermelidir",
|
|
642
|
+
"Settings.webhooks.validation.name.required": "Ad gerekli",
|
|
643
|
+
"Settings.webhooks.validation.url.regex": "Değer geçerli bir URL olmalıdır",
|
|
644
|
+
"Settings.webhooks.validation.url.required": "URL gerekli",
|
|
645
|
+
"Settings.webhooks.validation.value": "Değer gerekli",
|
|
646
|
+
"Users.components.List.empty": "Hiç kullanıcı yok...",
|
|
647
|
+
"Users.components.List.empty.withFilters": "Uygulanan filtrelerle eşleşen bir kullanıcı yok...",
|
|
648
|
+
"Users.components.List.empty.withSearch": "Aramayla eşleşen bir kullanıcı yok ({search})...",
|
|
649
|
+
"app.component.table.read": "{target} oku",
|
|
650
|
+
"app.component.table.view": "{target} detayları",
|
|
651
|
+
"app.components.BlockLink.cloud": "Strapi Cloud",
|
|
652
|
+
"app.components.BlockLink.cloud.content": "Strapi projeniz için tam yönetimli bulut barındırma.",
|
|
653
|
+
"app.components.BlockLink.code.content": "Topluluk tarafından geliştirilen gerçek projeleri test ederek öğrenin.",
|
|
654
|
+
"app.components.NpsSurvey.banner-title": "Strapi'yi bir arkadaşınıza veya iş arkadaşınıza tavsiye etme olasılığınız nedir?",
|
|
655
|
+
"app.components.NpsSurvey.dismiss-survey-label": "Anketi kapat",
|
|
656
|
+
"app.components.NpsSurvey.feedback-question": "Geliştirme için herhangi bir öneriniz var mı?",
|
|
657
|
+
"app.components.NpsSurvey.feedback-response": "Geri bildiriminiz için çok teşekkür ederiz!",
|
|
658
|
+
"app.components.NpsSurvey.happy-to-recommend": "Kesinlikle olası",
|
|
659
|
+
"app.components.NpsSurvey.no-recommendation": "Hiç olası değil",
|
|
660
|
+
"app.components.NpsSurvey.submit-feedback": "Geri Bildirim Gönder",
|
|
661
|
+
"app.components.Onboarding.link.build-content": "Bir içerik mimarisi oluştur",
|
|
662
|
+
"app.components.Onboarding.link.manage-content": "İçerik ekle ve yönet",
|
|
663
|
+
"app.components.Onboarding.link.manage-media": "Medya yönet",
|
|
664
|
+
"app.components.Onboarding.link.more-videos": "Daha fazla video izle",
|
|
665
|
+
"app.components.Select.placeholder": "Seç",
|
|
666
|
+
"app.components.Users.MagicLink.connect": "Bu kullanıcıya erişim vermek için bağlantıyı kopyalayıp paylaşın",
|
|
667
|
+
"app.components.Users.MagicLink.connect.sso": "Bu bağlantıyı kullanıcıya gönderin, ilk giriş bir SSO sağlayıcısı ile yapılabilir",
|
|
668
|
+
"app.components.Users.ModalCreateBody.block-title.details": "Kullanıcı detayları",
|
|
669
|
+
"app.components.Users.ModalCreateBody.block-title.roles": "Kullanıcı rolleri",
|
|
670
|
+
"app.components.Users.SortPicker.button-label": "Sırala",
|
|
671
|
+
"app.components.Users.SortPicker.sortby.email_asc": "E-posta (A'dan Z'ye)",
|
|
672
|
+
"app.components.Users.SortPicker.sortby.email_desc": "E-posta (Z'den A'ya)",
|
|
673
|
+
"app.components.Users.SortPicker.sortby.firstname_asc": "Ad (A'dan Z'ye)",
|
|
674
|
+
"app.components.Users.SortPicker.sortby.firstname_desc": "Ad (Z'den A'ya)",
|
|
675
|
+
"app.components.Users.SortPicker.sortby.lastname_asc": "Soyad (A'dan Z'ye)",
|
|
676
|
+
"app.components.Users.SortPicker.sortby.lastname_desc": "Soyad (Z'den A'ya)",
|
|
677
|
+
"app.components.Users.SortPicker.sortby.username_asc": "Kullanıcı adı (A'dan Z'ye)",
|
|
678
|
+
"app.components.Users.SortPicker.sortby.username_desc": "Kullanıcı adı (Z'den A'ya)",
|
|
679
|
+
"app.confirm.body": "Emin misiniz?",
|
|
680
|
+
"app.containers.AuthPage.ForgotPasswordSuccess.text.contact-admin": "Bu bağlantıyı almazsanız, lütfen yöneticinizle iletişime geçin.",
|
|
681
|
+
"app.containers.AuthPage.ForgotPasswordSuccess.text.email": "Şifre kurtarma bağlantınızı almanız birkaç dakika sürebilir.",
|
|
682
|
+
"app.containers.AuthPage.ForgotPasswordSuccess.title": "E-posta gönderildi",
|
|
683
|
+
"app.containers.Users.EditPage.form.active.label": "Aktif",
|
|
684
|
+
"app.containers.Users.EditPage.header.label": "{name} düzenle",
|
|
685
|
+
"app.containers.Users.EditPage.header.label-loading": "Kullanıcıyı düzenle",
|
|
686
|
+
"app.containers.Users.EditPage.roles-bloc-title": "Atanmış roller",
|
|
687
|
+
"app.containers.Users.ModalForm.footer.button-success": "Kullanıcı davet et",
|
|
688
|
+
"app.utils.published": "Yayınlandı",
|
|
689
|
+
"app.utils.ready-to-publish": "Yayınlamaya hazır",
|
|
690
|
+
"app.utils.ready-to-publish-changes": "Değişiklikleri yayınlamaya hazır",
|
|
691
|
+
"app.utils.ready-to-unpublish-changes": "Yayından kaldırmaya hazır",
|
|
692
|
+
"app.utils.refresh": "Yenile",
|
|
693
|
+
"components.Blocks.blocks.code": "Kod bloğu",
|
|
694
|
+
"components.Blocks.blocks.code.languageLabel": "Bir dil seç",
|
|
695
|
+
"components.Blocks.blocks.heading1": "Başlık 1",
|
|
696
|
+
"components.Blocks.blocks.heading2": "Başlık 2",
|
|
697
|
+
"components.Blocks.blocks.heading3": "Başlık 3",
|
|
698
|
+
"components.Blocks.blocks.heading4": "Başlık 4",
|
|
699
|
+
"components.Blocks.blocks.heading5": "Başlık 5",
|
|
700
|
+
"components.Blocks.blocks.heading6": "Başlık 6",
|
|
701
|
+
"components.Blocks.blocks.image": "Görsel",
|
|
702
|
+
"components.Blocks.blocks.orderedList": "Numaralı liste",
|
|
703
|
+
"components.Blocks.blocks.quote": "Alıntı",
|
|
704
|
+
"components.Blocks.blocks.selectBlock": "Bir blok seç",
|
|
705
|
+
"components.Blocks.blocks.text": "Metin",
|
|
706
|
+
"components.Blocks.blocks.unorderedList": "Madde işaretli liste",
|
|
707
|
+
"components.Blocks.collapse": "Daralt",
|
|
708
|
+
"components.Blocks.dnd.instruction": "Blokları yeniden sıralamak için Command veya Control tuşlarına Shift ile birlikte basıp Yukarı veya Aşağı ok tuşlarına basın",
|
|
709
|
+
"components.Blocks.dnd.reorder": "{item}, taşındı. Editördeki yeni konum: {position}.",
|
|
710
|
+
"components.Blocks.expand": "Genişlet",
|
|
711
|
+
"components.Blocks.link": "Bağlantı",
|
|
712
|
+
"components.Blocks.modifiers.bold": "Kalın",
|
|
713
|
+
"components.Blocks.modifiers.code": "Satır içi kod",
|
|
714
|
+
"components.Blocks.modifiers.italic": "İtalik",
|
|
715
|
+
"components.Blocks.modifiers.strikethrough": "Üstü çizili",
|
|
716
|
+
"components.Blocks.modifiers.underline": "Altı çizili",
|
|
717
|
+
"components.Blocks.popover.edit": "Düzenle",
|
|
718
|
+
"components.Blocks.popover.link": "Bağlantı",
|
|
719
|
+
"components.Blocks.popover.link.error": "Lütfen geçerli bir bağlantı girin",
|
|
720
|
+
"components.Blocks.popover.link.placeholder": "Bağlantıyı yapıştırın",
|
|
721
|
+
"components.Blocks.popover.remove": "Kaldır",
|
|
722
|
+
"components.Blocks.popover.text": "Metin",
|
|
723
|
+
"components.Blocks.popover.text.placeholder": "Bağlantı metni girin",
|
|
724
|
+
"components.Input.error.validation.email.withField": "{field} geçersiz bir e-posta",
|
|
725
|
+
"components.Input.error.validation.json.withField": "{field} JSON formatıyla eşleşmiyor",
|
|
726
|
+
"components.Input.error.validation.lowercase.withField": "{field} küçük harflerden oluşmalı",
|
|
727
|
+
"components.Input.error.validation.max.withField": "{field} çok yüksek.",
|
|
728
|
+
"components.Input.error.validation.maxLength.withField": "{field} çok uzun.",
|
|
729
|
+
"components.Input.error.validation.min.withField": "{field} çok düşük.",
|
|
730
|
+
"components.Input.error.validation.minLength.withField": "{field} çok kısa.",
|
|
731
|
+
"components.Input.error.validation.minSupMax.withField": "{field} daha yüksek olamaz",
|
|
732
|
+
"components.Input.error.validation.regex.withField": "{field} regex ile eşleşmiyor.",
|
|
733
|
+
"components.Input.error.validation.required.withField": "{field} gereklidir.",
|
|
734
|
+
"components.Input.error.validation.string": "Bu geçerli bir metin değil.",
|
|
735
|
+
"components.Input.error.validation.unique.withField": "{field} zaten kullanılıyor.",
|
|
736
|
+
"components.ViewSettings.tooltip": "Görünüm ayarları",
|
|
737
|
+
"global.auditLogs": "Denetim Kayıtları",
|
|
738
|
+
"global.close": "Kapat",
|
|
739
|
+
"global.error": "Bir şeyler yanlış gitti",
|
|
740
|
+
"global.fullname": "{firstname} {lastname}",
|
|
741
|
+
"global.home": "Ana Sayfa",
|
|
742
|
+
"global.learn-more": "Daha fazla öğren",
|
|
743
|
+
"global.more": "Daha",
|
|
744
|
+
"global.new": "Yeni",
|
|
745
|
+
noPreview: noPreview,
|
|
746
|
+
"notification.ee.warning.at-seat-limit.title": "{licenseLimitStatus, select, OVER_LIMIT {Aşıldı} AT_LIMIT {Limitte}} koltuk limiti ({currentUserCount}/{permittedSeats})",
|
|
747
|
+
"notification.ee.warning.over-.message": "Kullanıcıları {licenseLimitStatus, select, OVER_LIMIT {davet etmek} AT_LIMIT {yeniden etkinleştirmek}} için koltuk ekleyin. Bunu zaten yaptıysanız ancak Strapi'de henüz yansımadıysa, uygulamanızı yeniden başlattığınızdan emin olun.",
|
|
748
|
+
"notification.error.invalid.configuration": "Geçersiz bir yapılandırmanız var, daha fazla bilgi için sunucu günlüğünüzü kontrol edin.",
|
|
749
|
+
"notification.error.tokennamenotunique": "Ad başka bir tokene zaten atanmış",
|
|
750
|
+
"notification.success.transfertokencreated": "Transfer Token başarıyla oluşturuldu",
|
|
751
|
+
"notification.success.transfertokenedited": "Transfer Token başarıyla düzenlendi",
|
|
752
|
+
selectButtonTitle: selectButtonTitle
|
|
540
753
|
};
|
|
541
754
|
|
|
542
|
-
export { Analytics, Documentation, Email, Password, Provider, ResetPasswordToken, Role, Username, Users, anErrorOccurred, clearLabel, dark, tr as default, light, or, skipToContent, submit };
|
|
755
|
+
export { Analytics, Documentation, Email, Password, Provider, ResetPasswordToken, Role, Username, Users, anErrorOccurred, clearLabel, dark, tr as default, light, noPreview, or, selectButtonTitle, skipToContent, submit };
|
|
543
756
|
//# sourceMappingURL=tr.json.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tr.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tr.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -188,13 +188,15 @@ const getToken = ()=>{
|
|
|
188
188
|
headers: response.headers
|
|
189
189
|
};
|
|
190
190
|
}
|
|
191
|
+
if (response.status === 204) {
|
|
192
|
+
return {
|
|
193
|
+
data: {},
|
|
194
|
+
status: response.status
|
|
195
|
+
};
|
|
196
|
+
}
|
|
191
197
|
try {
|
|
192
198
|
const result = await response.json();
|
|
193
|
-
|
|
194
|
-
* validateStatus allows us to customize when a response should throw an error
|
|
195
|
-
* In native Fetch API, a response is considered "not ok"
|
|
196
|
-
* when the status code falls in the 200 to 299 (inclusive) range
|
|
197
|
-
*/ if (!response.ok && result.error && !validateStatus?.(response.status)) {
|
|
199
|
+
if (!response.ok && result.error && !validateStatus?.(response.status)) {
|
|
198
200
|
const fetchError = new FetchError(result.error.message, {
|
|
199
201
|
data: result
|
|
200
202
|
});
|
|
@@ -210,8 +212,14 @@ const getToken = ()=>{
|
|
|
210
212
|
data: result
|
|
211
213
|
};
|
|
212
214
|
} catch (error) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
+
// An empty 200 body causes `response.json()` to throw a `SyntaxError`. We treat
|
|
216
|
+
// it as success and return an empty payload. We match on `error.name` rather
|
|
217
|
+
// than `instanceof SyntaxError` because constructor identity differs across JS
|
|
218
|
+
// realms — a Response from a different realm (e.g. undici under jsdom in tests,
|
|
219
|
+
// a service worker or iframe in browsers) throws a `SyntaxError` whose
|
|
220
|
+
// constructor is not the same identity as the one this module closes over. Name
|
|
221
|
+
// comparison is realm-agnostic.
|
|
222
|
+
if (error?.name === 'SyntaxError' && response.ok) {
|
|
215
223
|
return {
|
|
216
224
|
data: [],
|
|
217
225
|
status: response.status
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFetchClient.js","sources":["../../../../../admin/src/utils/getFetchClient.ts"],"sourcesContent":["import pipe from 'lodash/fp/pipe';\n// eslint-disable-next-line import/default\nimport qs from 'qs';\n\nimport { getCookieValue, setCookie } from './cookies';\n\nimport type { errors } from '@strapi/utils';\n\nexport type ApiError =\n | errors.ApplicationError\n | errors.ForbiddenError\n | errors.NotFoundError\n | errors.NotImplementedError\n | errors.PaginationError\n | errors.PayloadTooLargeError\n | errors.PolicyError\n | errors.RateLimitError\n | errors.UnauthorizedError\n | errors.ValidationError\n | errors.YupValidationError;\n\nconst STORAGE_KEYS = {\n TOKEN: 'jwtToken',\n USER: 'userInfo',\n};\n\n/**\n * Module-level promise to ensure only one token refresh happens at a time\n */\nlet refreshPromise: Promise<string | null> | null = null;\n\n/**\n * Callback to notify the app when the token is updated (e.g., to update Redux state)\n */\nlet onTokenUpdate: ((token: string) => void) | null = null;\n\n/**\n * Set the callback that will be called when the token is refreshed.\n * This allows the React layer to update Redux state when a token refresh occurs.\n *\n * @param callback - Function to call with the new token, or null to clear\n * @example\n * // In a React component\n * useEffect(() => {\n * setOnTokenUpdate((token) => dispatch(setToken(token)));\n * return () => setOnTokenUpdate(null);\n * }, [dispatch]);\n */\nconst setOnTokenUpdate = (callback: ((token: string) => void) | null): void => {\n onTokenUpdate = callback;\n};\n\n/**\n * Check if the URL is an auth path that should not trigger token refresh.\n * Note: No ^ anchor since the URL may include the baseURL prefix (e.g., \"http://localhost:1337/admin/login\").\n * This differs from baseQuery.ts which uses ^/admin since it receives normalized paths.\n */\nconst isAuthPath = (url: string) => /\\/admin\\/(login|logout|access-token)\\b/.test(url);\n\n/**\n * Store the new token in the appropriate storage (localStorage or cookie)\n * and notify the app to update its state.\n *\n * Uses localStorage if the user selected \"remember me\" during login,\n * otherwise uses cookies for session-based storage.\n *\n * @param token - The JWT token to store\n * @internal Exported for testing purposes\n */\nconst storeToken = (token: string): void => {\n // Check if the original token was stored in localStorage (persist mode)\n const wasPersistedToLocalStorage = Boolean(localStorage.getItem(STORAGE_KEYS.TOKEN));\n\n if (wasPersistedToLocalStorage) {\n localStorage.setItem(STORAGE_KEYS.TOKEN, JSON.stringify(token));\n } else {\n setCookie(STORAGE_KEYS.TOKEN, token);\n }\n\n // Notify the app to update its state (e.g., Redux)\n if (onTokenUpdate) {\n onTokenUpdate(token);\n }\n};\n\n/**\n * Refresh the access token by calling the /admin/access-token endpoint.\n * This uses a low-level fetch to avoid recursion through the interceptor.\n * Returns the new token on success, or null on failure.\n */\nconst refreshAccessToken = async (): Promise<string | null> => {\n const backendURL = window.strapi.backendURL;\n\n try {\n const response = await fetch(`${backendURL}/admin/access-token`, {\n method: 'POST',\n credentials: 'include', // Include cookies for the refresh token\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n console.warn('[Auth] Token refresh failed with status:', response.status);\n return null;\n }\n\n const result = await response.json();\n const token = result?.data?.token as string | undefined;\n\n if (!token) {\n console.warn('[Auth] Token refresh response missing token');\n return null;\n }\n\n storeToken(token);\n return token;\n } catch (error) {\n console.error('[Auth] Token refresh error:', error);\n return null;\n }\n};\n\n/**\n * Attempt to refresh the token if not already refreshing.\n * Uses a module-level promise to prevent concurrent refresh requests.\n *\n * @returns The new authentication token\n * @throws {Error} If the token refresh fails (e.g., refresh token expired)\n * @internal Exported for testing purposes\n */\nconst attemptTokenRefresh = async (): Promise<string> => {\n if (!refreshPromise) {\n refreshPromise = refreshAccessToken().finally(() => {\n refreshPromise = null;\n });\n }\n\n const newToken = await refreshPromise;\n if (!newToken) {\n const error = new Error('Session expired. Please log in again.');\n error.name = 'TokenRefreshError';\n throw error;\n }\n\n return newToken;\n};\n\ntype FetchResponse<TData = any> = {\n data: TData;\n status?: number;\n headers?: Headers;\n};\n\ntype FetchOptions = {\n params?: any;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n validateStatus?: ((status: number) => boolean) | null;\n responseType?: 'json' | 'blob' | 'text' | 'arrayBuffer';\n};\n\ntype FetchConfig = {\n signal?: AbortSignal;\n};\n\ninterface ErrorResponse {\n data: {\n data?: any;\n error: ApiError & { status?: number };\n };\n}\n\nclass FetchError extends Error {\n public name: string;\n public message: string;\n public response?: ErrorResponse;\n public code?: number;\n public status?: number;\n\n constructor(message: string, response?: ErrorResponse) {\n super(message);\n this.name = 'FetchError';\n this.message = message;\n this.response = response;\n this.code = response?.data?.error?.status;\n this.status = response?.data?.error?.status;\n\n // Ensure correct stack trace in error object\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, FetchError);\n }\n }\n}\n\nconst isFetchError = (error: unknown): error is FetchError => {\n return error instanceof FetchError;\n};\n\nconst getToken = (): string | null => {\n const fromLocalStorage = localStorage.getItem(STORAGE_KEYS.TOKEN);\n if (fromLocalStorage) {\n return JSON.parse(fromLocalStorage);\n }\n\n const fromCookie = getCookieValue(STORAGE_KEYS.TOKEN);\n return fromCookie ?? null;\n};\n\ntype FetchClient = {\n get: {\n (url: string, config: FetchOptions & { responseType: 'blob' }): Promise<FetchResponse<Blob>>;\n (url: string, config: FetchOptions & { responseType: 'text' }): Promise<FetchResponse<string>>;\n (\n url: string,\n config: FetchOptions & { responseType: 'arrayBuffer' }\n ): Promise<FetchResponse<ArrayBuffer>>;\n <TData = any>(url: string, config?: FetchOptions): Promise<FetchResponse<TData>>;\n };\n put: <TData = any, TSend = any>(\n url: string,\n data?: TSend,\n config?: FetchOptions\n ) => Promise<FetchResponse<TData>>;\n post: <TData = any, TSend = any>(\n url: string,\n data?: TSend,\n config?: FetchOptions\n ) => Promise<FetchResponse<TData>>;\n del: <TData = any>(url: string, config?: FetchOptions) => Promise<FetchResponse<TData>>;\n};\n\n/**\n * @public\n * @param {FetchConfig} [defaultOptions={}] - Fetch Configs.\n * @returns {FetchClient} A fetch client object with methods for making HTTP requests.\n * @description This is an abstraction around the native fetch exposed by a function. It provides a simple interface to handle API calls\n * to the Strapi backend.\n * @example\n * ```tsx\n * import { getFetchClient } from '@strapi/admin/admin';\n *\n * const myFunct = () => {\n * const { get } = getFetchClient();\n * const requestURL = \"/some-endpoint\";\n *\n * const { data } = await get(requestURL);\n *\n * return data;\n * };\n * ```\n */\nconst getFetchClient = (defaultOptions: FetchConfig = {}): FetchClient => {\n const backendURL = window.strapi.backendURL;\n\n /**\n * Create default headers with the current token.\n * This is a function so we can get a fresh token after refresh.\n */\n const getDefaultHeaders = () => ({\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${getToken()}`,\n });\n\n const isFormDataRequest = (body: unknown) => body instanceof FormData;\n const addPrependingSlash = (url: string) => (url.charAt(0) !== '/' ? `/${url}` : url);\n\n // This regular expression matches a string that starts with either \"http://\" or \"https://\" or any other protocol name in lower case letters, followed by \"://\" and ends with anything else\n const hasProtocol = (url: string) => new RegExp('^(?:[a-z+]+:)?//', 'i').test(url);\n\n // Check if the url has a prepending slash, if not add a slash\n const normalizeUrl = (url: string) => (hasProtocol(url) ? url : addPrependingSlash(url));\n\n // Add a response interceptor to return the response\n const responseInterceptor = async <TData = any>(\n response: Response,\n validateStatus?: FetchOptions['validateStatus'],\n responseType: NonNullable<FetchOptions['responseType']> = 'json'\n ): Promise<FetchResponse<TData>> => {\n if (responseType !== 'json') {\n if (!response.ok && !validateStatus?.(response.status)) {\n const fetchError = new FetchError('Server Error');\n fetchError.status = response.status;\n throw fetchError;\n }\n\n let result: Blob | string | ArrayBuffer;\n if (responseType === 'blob') {\n result = await response.blob();\n } else if (responseType === 'text') {\n result = await response.text();\n } else {\n result = await response.arrayBuffer();\n }\n\n return { data: result as TData, status: response.status, headers: response.headers };\n }\n\n try {\n const result = await response.json();\n\n /**\n * validateStatus allows us to customize when a response should throw an error\n * In native Fetch API, a response is considered \"not ok\"\n * when the status code falls in the 200 to 299 (inclusive) range\n */\n if (!response.ok && result.error && !validateStatus?.(response.status)) {\n const fetchError = new FetchError(result.error.message, { data: result });\n fetchError.status = response.status;\n throw fetchError;\n }\n\n if (!response.ok && !validateStatus?.(response.status)) {\n const fetchError = new FetchError('Unknown Server Error');\n fetchError.status = response.status;\n throw fetchError;\n }\n\n return { data: result };\n } catch (error) {\n if (error instanceof SyntaxError && response.ok) {\n // Making sure that a SyntaxError doesn't throw if it's successful\n return { data: [], status: response.status } as FetchResponse<any>;\n } else {\n throw error;\n }\n }\n };\n\n /**\n * Execute a fetch request with automatic token refresh on 401 errors.\n * @param url - The request URL (used to check if it's an auth path)\n * @param executeRequest - Function that performs the fetch (called again on retry with fresh headers)\n */\n const withTokenRefresh = async <TData>(\n url: string,\n executeRequest: () => Promise<FetchResponse<TData>>\n ): Promise<FetchResponse<TData>> => {\n try {\n return await executeRequest();\n } catch (error) {\n // Only attempt refresh for 401 errors on non-auth paths\n if (isFetchError(error) && error.status === 401 && !isAuthPath(url)) {\n try {\n await attemptTokenRefresh();\n // Retry - executeRequest will call getDefaultHeaders() again, picking up the new token\n return await executeRequest();\n } catch {\n // If refresh fails, throw the original error\n throw error;\n }\n }\n throw error;\n }\n };\n\n const paramsSerializer =\n <Param = unknown>(params?: Param) =>\n (url: string) => {\n if (params) {\n if (typeof params === 'string') {\n return `${url}?${params}`;\n }\n\n /**\n * TODO V6: Encoding should be enabled in this step\n * So the rest of the app doesn't have to worry about it,\n * It's considered a breaking change because it impacts any API request, including the user's custom code\n */\n const serializedParams = qs.stringify(params, { encode: false });\n if (serializedParams) {\n return `${url}?${serializedParams}`;\n }\n return url;\n }\n return url;\n };\n\n const addBaseUrl = (url: Parameters<typeof fetch>[0]) => {\n return `${backendURL}${url}`;\n };\n\n /**\n * We use the factory method because the options\n * are unique to the individual request\n */\n const makeCreateRequestUrl = (options?: FetchOptions) =>\n pipe(normalizeUrl, addBaseUrl, paramsSerializer(options?.params));\n\n const fetchClient: FetchClient = {\n get: async <TData>(url: string, options?: FetchOptions): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n const responseType = options?.responseType ?? 'json';\n\n const executeRequest = async () => {\n const { Authorization } = getDefaultHeaders();\n\n // For non-JSON response types, omit content negotiation headers that imply JSON\n const defaultHeaders = responseType === 'json' ? getDefaultHeaders() : { Authorization };\n\n const headers = new Headers({\n ...defaultHeaders,\n ...options?.headers,\n });\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'GET',\n headers,\n });\n\n return responseInterceptor<TData>(response, options?.validateStatus, responseType);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n post: async <TData, TSend = any>(\n url: string,\n data?: TSend,\n options?: FetchOptions\n ): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n /**\n * we have to remove the Content-Type value if it was a formData request\n * the browser will automatically set the header value\n */\n if (isFormDataRequest(data)) {\n headers.delete('Content-Type');\n }\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'POST',\n headers,\n body: isFormDataRequest(data) ? (data as FormData) : JSON.stringify(data),\n });\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n put: async <TData, TSend = any>(\n url: string,\n data?: TSend,\n options?: FetchOptions\n ): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n /**\n * we have to remove the Content-Type value if it was a formData request\n * the browser will automatically set the header value\n */\n if (isFormDataRequest(data)) {\n headers.delete('Content-Type');\n }\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'PUT',\n headers,\n body: isFormDataRequest(data) ? (data as FormData) : JSON.stringify(data),\n });\n\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n del: async <TData>(url: string, options?: FetchOptions): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'DELETE',\n headers,\n });\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n };\n\n return fetchClient;\n};\n\nexport {\n getFetchClient,\n isFetchError,\n FetchError,\n attemptTokenRefresh,\n storeToken,\n setOnTokenUpdate,\n};\nexport type { FetchOptions, FetchResponse, FetchConfig, FetchClient, ErrorResponse };\n"],"names":["STORAGE_KEYS","TOKEN","refreshPromise","onTokenUpdate","setOnTokenUpdate","callback","isAuthPath","url","test","storeToken","token","wasPersistedToLocalStorage","Boolean","localStorage","getItem","setItem","JSON","stringify","setCookie","refreshAccessToken","backendURL","window","strapi","response","fetch","method","credentials","headers","Accept","ok","console","warn","status","result","json","data","error","attemptTokenRefresh","finally","newToken","Error","name","FetchError","message","code","captureStackTrace","isFetchError","getToken","fromLocalStorage","parse","fromCookie","getCookieValue","getFetchClient","defaultOptions","getDefaultHeaders","Authorization","isFormDataRequest","body","FormData","addPrependingSlash","charAt","hasProtocol","RegExp","normalizeUrl","responseInterceptor","validateStatus","responseType","fetchError","blob","text","arrayBuffer","SyntaxError","withTokenRefresh","executeRequest","paramsSerializer","params","serializedParams","qs","encode","addBaseUrl","makeCreateRequestUrl","options","pipe","fetchClient","get","createRequestUrl","defaultHeaders","Headers","signal","post","delete","put","del"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"getFetchClient.js","sources":["../../../../../admin/src/utils/getFetchClient.ts"],"sourcesContent":["import pipe from 'lodash/fp/pipe';\n// eslint-disable-next-line import/default\nimport qs from 'qs';\n\nimport { getCookieValue, setCookie } from './cookies';\n\nimport type { errors } from '@strapi/utils';\n\nexport type ApiError =\n | errors.ApplicationError\n | errors.ForbiddenError\n | errors.NotFoundError\n | errors.NotImplementedError\n | errors.PaginationError\n | errors.PayloadTooLargeError\n | errors.PolicyError\n | errors.RateLimitError\n | errors.UnauthorizedError\n | errors.ValidationError\n | errors.YupValidationError;\n\nconst STORAGE_KEYS = {\n TOKEN: 'jwtToken',\n USER: 'userInfo',\n};\n\n/**\n * Module-level promise to ensure only one token refresh happens at a time\n */\nlet refreshPromise: Promise<string | null> | null = null;\n\n/**\n * Callback to notify the app when the token is updated (e.g., to update Redux state)\n */\nlet onTokenUpdate: ((token: string) => void) | null = null;\n\n/**\n * Set the callback that will be called when the token is refreshed.\n * This allows the React layer to update Redux state when a token refresh occurs.\n *\n * @param callback - Function to call with the new token, or null to clear\n * @example\n * // In a React component\n * useEffect(() => {\n * setOnTokenUpdate((token) => dispatch(setToken(token)));\n * return () => setOnTokenUpdate(null);\n * }, [dispatch]);\n */\nconst setOnTokenUpdate = (callback: ((token: string) => void) | null): void => {\n onTokenUpdate = callback;\n};\n\n/**\n * Check if the URL is an auth path that should not trigger token refresh.\n * Note: No ^ anchor since the URL may include the baseURL prefix (e.g., \"http://localhost:1337/admin/login\").\n * This differs from baseQuery.ts which uses ^/admin since it receives normalized paths.\n */\nconst isAuthPath = (url: string) => /\\/admin\\/(login|logout|access-token)\\b/.test(url);\n\n/**\n * Store the new token in the appropriate storage (localStorage or cookie)\n * and notify the app to update its state.\n *\n * Uses localStorage if the user selected \"remember me\" during login,\n * otherwise uses cookies for session-based storage.\n *\n * @param token - The JWT token to store\n * @internal Exported for testing purposes\n */\nconst storeToken = (token: string): void => {\n // Check if the original token was stored in localStorage (persist mode)\n const wasPersistedToLocalStorage = Boolean(localStorage.getItem(STORAGE_KEYS.TOKEN));\n\n if (wasPersistedToLocalStorage) {\n localStorage.setItem(STORAGE_KEYS.TOKEN, JSON.stringify(token));\n } else {\n setCookie(STORAGE_KEYS.TOKEN, token);\n }\n\n // Notify the app to update its state (e.g., Redux)\n if (onTokenUpdate) {\n onTokenUpdate(token);\n }\n};\n\n/**\n * Refresh the access token by calling the /admin/access-token endpoint.\n * This uses a low-level fetch to avoid recursion through the interceptor.\n * Returns the new token on success, or null on failure.\n */\nconst refreshAccessToken = async (): Promise<string | null> => {\n const backendURL = window.strapi.backendURL;\n\n try {\n const response = await fetch(`${backendURL}/admin/access-token`, {\n method: 'POST',\n credentials: 'include', // Include cookies for the refresh token\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n console.warn('[Auth] Token refresh failed with status:', response.status);\n return null;\n }\n\n const result = await response.json();\n const token = result?.data?.token as string | undefined;\n\n if (!token) {\n console.warn('[Auth] Token refresh response missing token');\n return null;\n }\n\n storeToken(token);\n return token;\n } catch (error) {\n console.error('[Auth] Token refresh error:', error);\n return null;\n }\n};\n\n/**\n * Attempt to refresh the token if not already refreshing.\n * Uses a module-level promise to prevent concurrent refresh requests.\n *\n * @returns The new authentication token\n * @throws {Error} If the token refresh fails (e.g., refresh token expired)\n * @internal Exported for testing purposes\n */\nconst attemptTokenRefresh = async (): Promise<string> => {\n if (!refreshPromise) {\n refreshPromise = refreshAccessToken().finally(() => {\n refreshPromise = null;\n });\n }\n\n const newToken = await refreshPromise;\n if (!newToken) {\n const error = new Error('Session expired. Please log in again.');\n error.name = 'TokenRefreshError';\n throw error;\n }\n\n return newToken;\n};\n\ntype FetchResponse<TData = any> = {\n data: TData;\n status?: number;\n headers?: Headers;\n};\n\ntype FetchOptions = {\n params?: any;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n validateStatus?: ((status: number) => boolean) | null;\n responseType?: 'json' | 'blob' | 'text' | 'arrayBuffer';\n};\n\ntype FetchConfig = {\n signal?: AbortSignal;\n};\n\ninterface ErrorResponse {\n data: {\n data?: any;\n error: ApiError & { status?: number };\n };\n}\n\nclass FetchError extends Error {\n public name: string;\n public message: string;\n public response?: ErrorResponse;\n public code?: number;\n public status?: number;\n\n constructor(message: string, response?: ErrorResponse) {\n super(message);\n this.name = 'FetchError';\n this.message = message;\n this.response = response;\n this.code = response?.data?.error?.status;\n this.status = response?.data?.error?.status;\n\n // Ensure correct stack trace in error object\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, FetchError);\n }\n }\n}\n\nconst isFetchError = (error: unknown): error is FetchError => {\n return error instanceof FetchError;\n};\n\nconst getToken = (): string | null => {\n const fromLocalStorage = localStorage.getItem(STORAGE_KEYS.TOKEN);\n if (fromLocalStorage) {\n return JSON.parse(fromLocalStorage);\n }\n\n const fromCookie = getCookieValue(STORAGE_KEYS.TOKEN);\n return fromCookie ?? null;\n};\n\ntype FetchClient = {\n get: {\n (url: string, config: FetchOptions & { responseType: 'blob' }): Promise<FetchResponse<Blob>>;\n (url: string, config: FetchOptions & { responseType: 'text' }): Promise<FetchResponse<string>>;\n (\n url: string,\n config: FetchOptions & { responseType: 'arrayBuffer' }\n ): Promise<FetchResponse<ArrayBuffer>>;\n <TData = any>(url: string, config?: FetchOptions): Promise<FetchResponse<TData>>;\n };\n put: <TData = any, TSend = any>(\n url: string,\n data?: TSend,\n config?: FetchOptions\n ) => Promise<FetchResponse<TData>>;\n post: <TData = any, TSend = any>(\n url: string,\n data?: TSend,\n config?: FetchOptions\n ) => Promise<FetchResponse<TData>>;\n del: <TData = any>(url: string, config?: FetchOptions) => Promise<FetchResponse<TData>>;\n};\n\n/**\n * @public\n * @param {FetchConfig} [defaultOptions={}] - Fetch Configs.\n * @returns {FetchClient} A fetch client object with methods for making HTTP requests.\n * @description This is an abstraction around the native fetch exposed by a function. It provides a simple interface to handle API calls\n * to the Strapi backend.\n * @example\n * ```tsx\n * import { getFetchClient } from '@strapi/admin/admin';\n *\n * const myFunct = () => {\n * const { get } = getFetchClient();\n * const requestURL = \"/some-endpoint\";\n *\n * const { data } = await get(requestURL);\n *\n * return data;\n * };\n * ```\n */\nconst getFetchClient = (defaultOptions: FetchConfig = {}): FetchClient => {\n const backendURL = window.strapi.backendURL;\n\n /**\n * Create default headers with the current token.\n * This is a function so we can get a fresh token after refresh.\n */\n const getDefaultHeaders = () => ({\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${getToken()}`,\n });\n\n const isFormDataRequest = (body: unknown) => body instanceof FormData;\n const addPrependingSlash = (url: string) => (url.charAt(0) !== '/' ? `/${url}` : url);\n\n // This regular expression matches a string that starts with either \"http://\" or \"https://\" or any other protocol name in lower case letters, followed by \"://\" and ends with anything else\n const hasProtocol = (url: string) => new RegExp('^(?:[a-z+]+:)?//', 'i').test(url);\n\n // Check if the url has a prepending slash, if not add a slash\n const normalizeUrl = (url: string) => (hasProtocol(url) ? url : addPrependingSlash(url));\n\n // Add a response interceptor to return the response\n const responseInterceptor = async <TData = any>(\n response: Response,\n validateStatus?: FetchOptions['validateStatus'],\n responseType: NonNullable<FetchOptions['responseType']> = 'json'\n ): Promise<FetchResponse<TData>> => {\n if (responseType !== 'json') {\n if (!response.ok && !validateStatus?.(response.status)) {\n const fetchError = new FetchError('Server Error');\n fetchError.status = response.status;\n throw fetchError;\n }\n\n let result: Blob | string | ArrayBuffer;\n if (responseType === 'blob') {\n result = await response.blob();\n } else if (responseType === 'text') {\n result = await response.text();\n } else {\n result = await response.arrayBuffer();\n }\n\n return { data: result as TData, status: response.status, headers: response.headers };\n }\n\n if (response.status === 204) {\n return { data: {} as TData, status: response.status };\n }\n\n try {\n const result = await response.json();\n\n if (!response.ok && result.error && !validateStatus?.(response.status)) {\n const fetchError = new FetchError(result.error.message, { data: result });\n fetchError.status = response.status;\n throw fetchError;\n }\n\n if (!response.ok && !validateStatus?.(response.status)) {\n const fetchError = new FetchError('Unknown Server Error');\n fetchError.status = response.status;\n throw fetchError;\n }\n\n return { data: result };\n } catch (error) {\n // An empty 200 body causes `response.json()` to throw a `SyntaxError`. We treat\n // it as success and return an empty payload. We match on `error.name` rather\n // than `instanceof SyntaxError` because constructor identity differs across JS\n // realms — a Response from a different realm (e.g. undici under jsdom in tests,\n // a service worker or iframe in browsers) throws a `SyntaxError` whose\n // constructor is not the same identity as the one this module closes over. Name\n // comparison is realm-agnostic.\n if ((error as Error | null)?.name === 'SyntaxError' && response.ok) {\n return { data: [], status: response.status } as FetchResponse<any>;\n } else {\n throw error;\n }\n }\n };\n\n /**\n * Execute a fetch request with automatic token refresh on 401 errors.\n * @param url - The request URL (used to check if it's an auth path)\n * @param executeRequest - Function that performs the fetch (called again on retry with fresh headers)\n */\n const withTokenRefresh = async <TData>(\n url: string,\n executeRequest: () => Promise<FetchResponse<TData>>\n ): Promise<FetchResponse<TData>> => {\n try {\n return await executeRequest();\n } catch (error) {\n // Only attempt refresh for 401 errors on non-auth paths\n if (isFetchError(error) && error.status === 401 && !isAuthPath(url)) {\n try {\n await attemptTokenRefresh();\n // Retry - executeRequest will call getDefaultHeaders() again, picking up the new token\n return await executeRequest();\n } catch {\n // If refresh fails, throw the original error\n throw error;\n }\n }\n throw error;\n }\n };\n\n const paramsSerializer =\n <Param = unknown>(params?: Param) =>\n (url: string) => {\n if (params) {\n if (typeof params === 'string') {\n return `${url}?${params}`;\n }\n\n /**\n * TODO V6: Encoding should be enabled in this step\n * So the rest of the app doesn't have to worry about it,\n * It's considered a breaking change because it impacts any API request, including the user's custom code\n */\n const serializedParams = qs.stringify(params, { encode: false });\n if (serializedParams) {\n return `${url}?${serializedParams}`;\n }\n return url;\n }\n return url;\n };\n\n const addBaseUrl = (url: Parameters<typeof fetch>[0]) => {\n return `${backendURL}${url}`;\n };\n\n /**\n * We use the factory method because the options\n * are unique to the individual request\n */\n const makeCreateRequestUrl = (options?: FetchOptions) =>\n pipe(normalizeUrl, addBaseUrl, paramsSerializer(options?.params));\n\n const fetchClient: FetchClient = {\n get: async <TData>(url: string, options?: FetchOptions): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n const responseType = options?.responseType ?? 'json';\n\n const executeRequest = async () => {\n const { Authorization } = getDefaultHeaders();\n\n // For non-JSON response types, omit content negotiation headers that imply JSON\n const defaultHeaders = responseType === 'json' ? getDefaultHeaders() : { Authorization };\n\n const headers = new Headers({\n ...defaultHeaders,\n ...options?.headers,\n });\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'GET',\n headers,\n });\n\n return responseInterceptor<TData>(response, options?.validateStatus, responseType);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n post: async <TData, TSend = any>(\n url: string,\n data?: TSend,\n options?: FetchOptions\n ): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n /**\n * we have to remove the Content-Type value if it was a formData request\n * the browser will automatically set the header value\n */\n if (isFormDataRequest(data)) {\n headers.delete('Content-Type');\n }\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'POST',\n headers,\n body: isFormDataRequest(data) ? (data as FormData) : JSON.stringify(data),\n });\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n put: async <TData, TSend = any>(\n url: string,\n data?: TSend,\n options?: FetchOptions\n ): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n /**\n * we have to remove the Content-Type value if it was a formData request\n * the browser will automatically set the header value\n */\n if (isFormDataRequest(data)) {\n headers.delete('Content-Type');\n }\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'PUT',\n headers,\n body: isFormDataRequest(data) ? (data as FormData) : JSON.stringify(data),\n });\n\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n del: async <TData>(url: string, options?: FetchOptions): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'DELETE',\n headers,\n });\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n };\n\n return fetchClient;\n};\n\nexport {\n getFetchClient,\n isFetchError,\n FetchError,\n attemptTokenRefresh,\n storeToken,\n setOnTokenUpdate,\n};\nexport type { FetchOptions, FetchResponse, FetchConfig, FetchClient, ErrorResponse };\n"],"names":["STORAGE_KEYS","TOKEN","refreshPromise","onTokenUpdate","setOnTokenUpdate","callback","isAuthPath","url","test","storeToken","token","wasPersistedToLocalStorage","Boolean","localStorage","getItem","setItem","JSON","stringify","setCookie","refreshAccessToken","backendURL","window","strapi","response","fetch","method","credentials","headers","Accept","ok","console","warn","status","result","json","data","error","attemptTokenRefresh","finally","newToken","Error","name","FetchError","message","code","captureStackTrace","isFetchError","getToken","fromLocalStorage","parse","fromCookie","getCookieValue","getFetchClient","defaultOptions","getDefaultHeaders","Authorization","isFormDataRequest","body","FormData","addPrependingSlash","charAt","hasProtocol","RegExp","normalizeUrl","responseInterceptor","validateStatus","responseType","fetchError","blob","text","arrayBuffer","withTokenRefresh","executeRequest","paramsSerializer","params","serializedParams","qs","encode","addBaseUrl","makeCreateRequestUrl","options","pipe","fetchClient","get","createRequestUrl","defaultHeaders","Headers","signal","post","delete","put","del"],"mappings":"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"}
|
|
@@ -186,13 +186,15 @@ const getToken = ()=>{
|
|
|
186
186
|
headers: response.headers
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
+
if (response.status === 204) {
|
|
190
|
+
return {
|
|
191
|
+
data: {},
|
|
192
|
+
status: response.status
|
|
193
|
+
};
|
|
194
|
+
}
|
|
189
195
|
try {
|
|
190
196
|
const result = await response.json();
|
|
191
|
-
|
|
192
|
-
* validateStatus allows us to customize when a response should throw an error
|
|
193
|
-
* In native Fetch API, a response is considered "not ok"
|
|
194
|
-
* when the status code falls in the 200 to 299 (inclusive) range
|
|
195
|
-
*/ if (!response.ok && result.error && !validateStatus?.(response.status)) {
|
|
197
|
+
if (!response.ok && result.error && !validateStatus?.(response.status)) {
|
|
196
198
|
const fetchError = new FetchError(result.error.message, {
|
|
197
199
|
data: result
|
|
198
200
|
});
|
|
@@ -208,8 +210,14 @@ const getToken = ()=>{
|
|
|
208
210
|
data: result
|
|
209
211
|
};
|
|
210
212
|
} catch (error) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
+
// An empty 200 body causes `response.json()` to throw a `SyntaxError`. We treat
|
|
214
|
+
// it as success and return an empty payload. We match on `error.name` rather
|
|
215
|
+
// than `instanceof SyntaxError` because constructor identity differs across JS
|
|
216
|
+
// realms — a Response from a different realm (e.g. undici under jsdom in tests,
|
|
217
|
+
// a service worker or iframe in browsers) throws a `SyntaxError` whose
|
|
218
|
+
// constructor is not the same identity as the one this module closes over. Name
|
|
219
|
+
// comparison is realm-agnostic.
|
|
220
|
+
if (error?.name === 'SyntaxError' && response.ok) {
|
|
213
221
|
return {
|
|
214
222
|
data: [],
|
|
215
223
|
status: response.status
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFetchClient.mjs","sources":["../../../../../admin/src/utils/getFetchClient.ts"],"sourcesContent":["import pipe from 'lodash/fp/pipe';\n// eslint-disable-next-line import/default\nimport qs from 'qs';\n\nimport { getCookieValue, setCookie } from './cookies';\n\nimport type { errors } from '@strapi/utils';\n\nexport type ApiError =\n | errors.ApplicationError\n | errors.ForbiddenError\n | errors.NotFoundError\n | errors.NotImplementedError\n | errors.PaginationError\n | errors.PayloadTooLargeError\n | errors.PolicyError\n | errors.RateLimitError\n | errors.UnauthorizedError\n | errors.ValidationError\n | errors.YupValidationError;\n\nconst STORAGE_KEYS = {\n TOKEN: 'jwtToken',\n USER: 'userInfo',\n};\n\n/**\n * Module-level promise to ensure only one token refresh happens at a time\n */\nlet refreshPromise: Promise<string | null> | null = null;\n\n/**\n * Callback to notify the app when the token is updated (e.g., to update Redux state)\n */\nlet onTokenUpdate: ((token: string) => void) | null = null;\n\n/**\n * Set the callback that will be called when the token is refreshed.\n * This allows the React layer to update Redux state when a token refresh occurs.\n *\n * @param callback - Function to call with the new token, or null to clear\n * @example\n * // In a React component\n * useEffect(() => {\n * setOnTokenUpdate((token) => dispatch(setToken(token)));\n * return () => setOnTokenUpdate(null);\n * }, [dispatch]);\n */\nconst setOnTokenUpdate = (callback: ((token: string) => void) | null): void => {\n onTokenUpdate = callback;\n};\n\n/**\n * Check if the URL is an auth path that should not trigger token refresh.\n * Note: No ^ anchor since the URL may include the baseURL prefix (e.g., \"http://localhost:1337/admin/login\").\n * This differs from baseQuery.ts which uses ^/admin since it receives normalized paths.\n */\nconst isAuthPath = (url: string) => /\\/admin\\/(login|logout|access-token)\\b/.test(url);\n\n/**\n * Store the new token in the appropriate storage (localStorage or cookie)\n * and notify the app to update its state.\n *\n * Uses localStorage if the user selected \"remember me\" during login,\n * otherwise uses cookies for session-based storage.\n *\n * @param token - The JWT token to store\n * @internal Exported for testing purposes\n */\nconst storeToken = (token: string): void => {\n // Check if the original token was stored in localStorage (persist mode)\n const wasPersistedToLocalStorage = Boolean(localStorage.getItem(STORAGE_KEYS.TOKEN));\n\n if (wasPersistedToLocalStorage) {\n localStorage.setItem(STORAGE_KEYS.TOKEN, JSON.stringify(token));\n } else {\n setCookie(STORAGE_KEYS.TOKEN, token);\n }\n\n // Notify the app to update its state (e.g., Redux)\n if (onTokenUpdate) {\n onTokenUpdate(token);\n }\n};\n\n/**\n * Refresh the access token by calling the /admin/access-token endpoint.\n * This uses a low-level fetch to avoid recursion through the interceptor.\n * Returns the new token on success, or null on failure.\n */\nconst refreshAccessToken = async (): Promise<string | null> => {\n const backendURL = window.strapi.backendURL;\n\n try {\n const response = await fetch(`${backendURL}/admin/access-token`, {\n method: 'POST',\n credentials: 'include', // Include cookies for the refresh token\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n console.warn('[Auth] Token refresh failed with status:', response.status);\n return null;\n }\n\n const result = await response.json();\n const token = result?.data?.token as string | undefined;\n\n if (!token) {\n console.warn('[Auth] Token refresh response missing token');\n return null;\n }\n\n storeToken(token);\n return token;\n } catch (error) {\n console.error('[Auth] Token refresh error:', error);\n return null;\n }\n};\n\n/**\n * Attempt to refresh the token if not already refreshing.\n * Uses a module-level promise to prevent concurrent refresh requests.\n *\n * @returns The new authentication token\n * @throws {Error} If the token refresh fails (e.g., refresh token expired)\n * @internal Exported for testing purposes\n */\nconst attemptTokenRefresh = async (): Promise<string> => {\n if (!refreshPromise) {\n refreshPromise = refreshAccessToken().finally(() => {\n refreshPromise = null;\n });\n }\n\n const newToken = await refreshPromise;\n if (!newToken) {\n const error = new Error('Session expired. Please log in again.');\n error.name = 'TokenRefreshError';\n throw error;\n }\n\n return newToken;\n};\n\ntype FetchResponse<TData = any> = {\n data: TData;\n status?: number;\n headers?: Headers;\n};\n\ntype FetchOptions = {\n params?: any;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n validateStatus?: ((status: number) => boolean) | null;\n responseType?: 'json' | 'blob' | 'text' | 'arrayBuffer';\n};\n\ntype FetchConfig = {\n signal?: AbortSignal;\n};\n\ninterface ErrorResponse {\n data: {\n data?: any;\n error: ApiError & { status?: number };\n };\n}\n\nclass FetchError extends Error {\n public name: string;\n public message: string;\n public response?: ErrorResponse;\n public code?: number;\n public status?: number;\n\n constructor(message: string, response?: ErrorResponse) {\n super(message);\n this.name = 'FetchError';\n this.message = message;\n this.response = response;\n this.code = response?.data?.error?.status;\n this.status = response?.data?.error?.status;\n\n // Ensure correct stack trace in error object\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, FetchError);\n }\n }\n}\n\nconst isFetchError = (error: unknown): error is FetchError => {\n return error instanceof FetchError;\n};\n\nconst getToken = (): string | null => {\n const fromLocalStorage = localStorage.getItem(STORAGE_KEYS.TOKEN);\n if (fromLocalStorage) {\n return JSON.parse(fromLocalStorage);\n }\n\n const fromCookie = getCookieValue(STORAGE_KEYS.TOKEN);\n return fromCookie ?? null;\n};\n\ntype FetchClient = {\n get: {\n (url: string, config: FetchOptions & { responseType: 'blob' }): Promise<FetchResponse<Blob>>;\n (url: string, config: FetchOptions & { responseType: 'text' }): Promise<FetchResponse<string>>;\n (\n url: string,\n config: FetchOptions & { responseType: 'arrayBuffer' }\n ): Promise<FetchResponse<ArrayBuffer>>;\n <TData = any>(url: string, config?: FetchOptions): Promise<FetchResponse<TData>>;\n };\n put: <TData = any, TSend = any>(\n url: string,\n data?: TSend,\n config?: FetchOptions\n ) => Promise<FetchResponse<TData>>;\n post: <TData = any, TSend = any>(\n url: string,\n data?: TSend,\n config?: FetchOptions\n ) => Promise<FetchResponse<TData>>;\n del: <TData = any>(url: string, config?: FetchOptions) => Promise<FetchResponse<TData>>;\n};\n\n/**\n * @public\n * @param {FetchConfig} [defaultOptions={}] - Fetch Configs.\n * @returns {FetchClient} A fetch client object with methods for making HTTP requests.\n * @description This is an abstraction around the native fetch exposed by a function. It provides a simple interface to handle API calls\n * to the Strapi backend.\n * @example\n * ```tsx\n * import { getFetchClient } from '@strapi/admin/admin';\n *\n * const myFunct = () => {\n * const { get } = getFetchClient();\n * const requestURL = \"/some-endpoint\";\n *\n * const { data } = await get(requestURL);\n *\n * return data;\n * };\n * ```\n */\nconst getFetchClient = (defaultOptions: FetchConfig = {}): FetchClient => {\n const backendURL = window.strapi.backendURL;\n\n /**\n * Create default headers with the current token.\n * This is a function so we can get a fresh token after refresh.\n */\n const getDefaultHeaders = () => ({\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${getToken()}`,\n });\n\n const isFormDataRequest = (body: unknown) => body instanceof FormData;\n const addPrependingSlash = (url: string) => (url.charAt(0) !== '/' ? `/${url}` : url);\n\n // This regular expression matches a string that starts with either \"http://\" or \"https://\" or any other protocol name in lower case letters, followed by \"://\" and ends with anything else\n const hasProtocol = (url: string) => new RegExp('^(?:[a-z+]+:)?//', 'i').test(url);\n\n // Check if the url has a prepending slash, if not add a slash\n const normalizeUrl = (url: string) => (hasProtocol(url) ? url : addPrependingSlash(url));\n\n // Add a response interceptor to return the response\n const responseInterceptor = async <TData = any>(\n response: Response,\n validateStatus?: FetchOptions['validateStatus'],\n responseType: NonNullable<FetchOptions['responseType']> = 'json'\n ): Promise<FetchResponse<TData>> => {\n if (responseType !== 'json') {\n if (!response.ok && !validateStatus?.(response.status)) {\n const fetchError = new FetchError('Server Error');\n fetchError.status = response.status;\n throw fetchError;\n }\n\n let result: Blob | string | ArrayBuffer;\n if (responseType === 'blob') {\n result = await response.blob();\n } else if (responseType === 'text') {\n result = await response.text();\n } else {\n result = await response.arrayBuffer();\n }\n\n return { data: result as TData, status: response.status, headers: response.headers };\n }\n\n try {\n const result = await response.json();\n\n /**\n * validateStatus allows us to customize when a response should throw an error\n * In native Fetch API, a response is considered \"not ok\"\n * when the status code falls in the 200 to 299 (inclusive) range\n */\n if (!response.ok && result.error && !validateStatus?.(response.status)) {\n const fetchError = new FetchError(result.error.message, { data: result });\n fetchError.status = response.status;\n throw fetchError;\n }\n\n if (!response.ok && !validateStatus?.(response.status)) {\n const fetchError = new FetchError('Unknown Server Error');\n fetchError.status = response.status;\n throw fetchError;\n }\n\n return { data: result };\n } catch (error) {\n if (error instanceof SyntaxError && response.ok) {\n // Making sure that a SyntaxError doesn't throw if it's successful\n return { data: [], status: response.status } as FetchResponse<any>;\n } else {\n throw error;\n }\n }\n };\n\n /**\n * Execute a fetch request with automatic token refresh on 401 errors.\n * @param url - The request URL (used to check if it's an auth path)\n * @param executeRequest - Function that performs the fetch (called again on retry with fresh headers)\n */\n const withTokenRefresh = async <TData>(\n url: string,\n executeRequest: () => Promise<FetchResponse<TData>>\n ): Promise<FetchResponse<TData>> => {\n try {\n return await executeRequest();\n } catch (error) {\n // Only attempt refresh for 401 errors on non-auth paths\n if (isFetchError(error) && error.status === 401 && !isAuthPath(url)) {\n try {\n await attemptTokenRefresh();\n // Retry - executeRequest will call getDefaultHeaders() again, picking up the new token\n return await executeRequest();\n } catch {\n // If refresh fails, throw the original error\n throw error;\n }\n }\n throw error;\n }\n };\n\n const paramsSerializer =\n <Param = unknown>(params?: Param) =>\n (url: string) => {\n if (params) {\n if (typeof params === 'string') {\n return `${url}?${params}`;\n }\n\n /**\n * TODO V6: Encoding should be enabled in this step\n * So the rest of the app doesn't have to worry about it,\n * It's considered a breaking change because it impacts any API request, including the user's custom code\n */\n const serializedParams = qs.stringify(params, { encode: false });\n if (serializedParams) {\n return `${url}?${serializedParams}`;\n }\n return url;\n }\n return url;\n };\n\n const addBaseUrl = (url: Parameters<typeof fetch>[0]) => {\n return `${backendURL}${url}`;\n };\n\n /**\n * We use the factory method because the options\n * are unique to the individual request\n */\n const makeCreateRequestUrl = (options?: FetchOptions) =>\n pipe(normalizeUrl, addBaseUrl, paramsSerializer(options?.params));\n\n const fetchClient: FetchClient = {\n get: async <TData>(url: string, options?: FetchOptions): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n const responseType = options?.responseType ?? 'json';\n\n const executeRequest = async () => {\n const { Authorization } = getDefaultHeaders();\n\n // For non-JSON response types, omit content negotiation headers that imply JSON\n const defaultHeaders = responseType === 'json' ? getDefaultHeaders() : { Authorization };\n\n const headers = new Headers({\n ...defaultHeaders,\n ...options?.headers,\n });\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'GET',\n headers,\n });\n\n return responseInterceptor<TData>(response, options?.validateStatus, responseType);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n post: async <TData, TSend = any>(\n url: string,\n data?: TSend,\n options?: FetchOptions\n ): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n /**\n * we have to remove the Content-Type value if it was a formData request\n * the browser will automatically set the header value\n */\n if (isFormDataRequest(data)) {\n headers.delete('Content-Type');\n }\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'POST',\n headers,\n body: isFormDataRequest(data) ? (data as FormData) : JSON.stringify(data),\n });\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n put: async <TData, TSend = any>(\n url: string,\n data?: TSend,\n options?: FetchOptions\n ): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n /**\n * we have to remove the Content-Type value if it was a formData request\n * the browser will automatically set the header value\n */\n if (isFormDataRequest(data)) {\n headers.delete('Content-Type');\n }\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'PUT',\n headers,\n body: isFormDataRequest(data) ? (data as FormData) : JSON.stringify(data),\n });\n\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n del: async <TData>(url: string, options?: FetchOptions): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'DELETE',\n headers,\n });\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n };\n\n return fetchClient;\n};\n\nexport {\n getFetchClient,\n isFetchError,\n FetchError,\n attemptTokenRefresh,\n storeToken,\n setOnTokenUpdate,\n};\nexport type { FetchOptions, FetchResponse, FetchConfig, FetchClient, ErrorResponse };\n"],"names":["STORAGE_KEYS","TOKEN","refreshPromise","onTokenUpdate","setOnTokenUpdate","callback","isAuthPath","url","test","storeToken","token","wasPersistedToLocalStorage","Boolean","localStorage","getItem","setItem","JSON","stringify","setCookie","refreshAccessToken","backendURL","window","strapi","response","fetch","method","credentials","headers","Accept","ok","console","warn","status","result","json","data","error","attemptTokenRefresh","finally","newToken","Error","name","FetchError","message","code","captureStackTrace","isFetchError","getToken","fromLocalStorage","parse","fromCookie","getCookieValue","getFetchClient","defaultOptions","getDefaultHeaders","Authorization","isFormDataRequest","body","FormData","addPrependingSlash","charAt","hasProtocol","RegExp","normalizeUrl","responseInterceptor","validateStatus","responseType","fetchError","blob","text","arrayBuffer","SyntaxError","withTokenRefresh","executeRequest","paramsSerializer","params","serializedParams","qs","encode","addBaseUrl","makeCreateRequestUrl","options","pipe","fetchClient","get","createRequestUrl","defaultHeaders","Headers","signal","post","delete","put","del"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"getFetchClient.mjs","sources":["../../../../../admin/src/utils/getFetchClient.ts"],"sourcesContent":["import pipe from 'lodash/fp/pipe';\n// eslint-disable-next-line import/default\nimport qs from 'qs';\n\nimport { getCookieValue, setCookie } from './cookies';\n\nimport type { errors } from '@strapi/utils';\n\nexport type ApiError =\n | errors.ApplicationError\n | errors.ForbiddenError\n | errors.NotFoundError\n | errors.NotImplementedError\n | errors.PaginationError\n | errors.PayloadTooLargeError\n | errors.PolicyError\n | errors.RateLimitError\n | errors.UnauthorizedError\n | errors.ValidationError\n | errors.YupValidationError;\n\nconst STORAGE_KEYS = {\n TOKEN: 'jwtToken',\n USER: 'userInfo',\n};\n\n/**\n * Module-level promise to ensure only one token refresh happens at a time\n */\nlet refreshPromise: Promise<string | null> | null = null;\n\n/**\n * Callback to notify the app when the token is updated (e.g., to update Redux state)\n */\nlet onTokenUpdate: ((token: string) => void) | null = null;\n\n/**\n * Set the callback that will be called when the token is refreshed.\n * This allows the React layer to update Redux state when a token refresh occurs.\n *\n * @param callback - Function to call with the new token, or null to clear\n * @example\n * // In a React component\n * useEffect(() => {\n * setOnTokenUpdate((token) => dispatch(setToken(token)));\n * return () => setOnTokenUpdate(null);\n * }, [dispatch]);\n */\nconst setOnTokenUpdate = (callback: ((token: string) => void) | null): void => {\n onTokenUpdate = callback;\n};\n\n/**\n * Check if the URL is an auth path that should not trigger token refresh.\n * Note: No ^ anchor since the URL may include the baseURL prefix (e.g., \"http://localhost:1337/admin/login\").\n * This differs from baseQuery.ts which uses ^/admin since it receives normalized paths.\n */\nconst isAuthPath = (url: string) => /\\/admin\\/(login|logout|access-token)\\b/.test(url);\n\n/**\n * Store the new token in the appropriate storage (localStorage or cookie)\n * and notify the app to update its state.\n *\n * Uses localStorage if the user selected \"remember me\" during login,\n * otherwise uses cookies for session-based storage.\n *\n * @param token - The JWT token to store\n * @internal Exported for testing purposes\n */\nconst storeToken = (token: string): void => {\n // Check if the original token was stored in localStorage (persist mode)\n const wasPersistedToLocalStorage = Boolean(localStorage.getItem(STORAGE_KEYS.TOKEN));\n\n if (wasPersistedToLocalStorage) {\n localStorage.setItem(STORAGE_KEYS.TOKEN, JSON.stringify(token));\n } else {\n setCookie(STORAGE_KEYS.TOKEN, token);\n }\n\n // Notify the app to update its state (e.g., Redux)\n if (onTokenUpdate) {\n onTokenUpdate(token);\n }\n};\n\n/**\n * Refresh the access token by calling the /admin/access-token endpoint.\n * This uses a low-level fetch to avoid recursion through the interceptor.\n * Returns the new token on success, or null on failure.\n */\nconst refreshAccessToken = async (): Promise<string | null> => {\n const backendURL = window.strapi.backendURL;\n\n try {\n const response = await fetch(`${backendURL}/admin/access-token`, {\n method: 'POST',\n credentials: 'include', // Include cookies for the refresh token\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n console.warn('[Auth] Token refresh failed with status:', response.status);\n return null;\n }\n\n const result = await response.json();\n const token = result?.data?.token as string | undefined;\n\n if (!token) {\n console.warn('[Auth] Token refresh response missing token');\n return null;\n }\n\n storeToken(token);\n return token;\n } catch (error) {\n console.error('[Auth] Token refresh error:', error);\n return null;\n }\n};\n\n/**\n * Attempt to refresh the token if not already refreshing.\n * Uses a module-level promise to prevent concurrent refresh requests.\n *\n * @returns The new authentication token\n * @throws {Error} If the token refresh fails (e.g., refresh token expired)\n * @internal Exported for testing purposes\n */\nconst attemptTokenRefresh = async (): Promise<string> => {\n if (!refreshPromise) {\n refreshPromise = refreshAccessToken().finally(() => {\n refreshPromise = null;\n });\n }\n\n const newToken = await refreshPromise;\n if (!newToken) {\n const error = new Error('Session expired. Please log in again.');\n error.name = 'TokenRefreshError';\n throw error;\n }\n\n return newToken;\n};\n\ntype FetchResponse<TData = any> = {\n data: TData;\n status?: number;\n headers?: Headers;\n};\n\ntype FetchOptions = {\n params?: any;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n validateStatus?: ((status: number) => boolean) | null;\n responseType?: 'json' | 'blob' | 'text' | 'arrayBuffer';\n};\n\ntype FetchConfig = {\n signal?: AbortSignal;\n};\n\ninterface ErrorResponse {\n data: {\n data?: any;\n error: ApiError & { status?: number };\n };\n}\n\nclass FetchError extends Error {\n public name: string;\n public message: string;\n public response?: ErrorResponse;\n public code?: number;\n public status?: number;\n\n constructor(message: string, response?: ErrorResponse) {\n super(message);\n this.name = 'FetchError';\n this.message = message;\n this.response = response;\n this.code = response?.data?.error?.status;\n this.status = response?.data?.error?.status;\n\n // Ensure correct stack trace in error object\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, FetchError);\n }\n }\n}\n\nconst isFetchError = (error: unknown): error is FetchError => {\n return error instanceof FetchError;\n};\n\nconst getToken = (): string | null => {\n const fromLocalStorage = localStorage.getItem(STORAGE_KEYS.TOKEN);\n if (fromLocalStorage) {\n return JSON.parse(fromLocalStorage);\n }\n\n const fromCookie = getCookieValue(STORAGE_KEYS.TOKEN);\n return fromCookie ?? null;\n};\n\ntype FetchClient = {\n get: {\n (url: string, config: FetchOptions & { responseType: 'blob' }): Promise<FetchResponse<Blob>>;\n (url: string, config: FetchOptions & { responseType: 'text' }): Promise<FetchResponse<string>>;\n (\n url: string,\n config: FetchOptions & { responseType: 'arrayBuffer' }\n ): Promise<FetchResponse<ArrayBuffer>>;\n <TData = any>(url: string, config?: FetchOptions): Promise<FetchResponse<TData>>;\n };\n put: <TData = any, TSend = any>(\n url: string,\n data?: TSend,\n config?: FetchOptions\n ) => Promise<FetchResponse<TData>>;\n post: <TData = any, TSend = any>(\n url: string,\n data?: TSend,\n config?: FetchOptions\n ) => Promise<FetchResponse<TData>>;\n del: <TData = any>(url: string, config?: FetchOptions) => Promise<FetchResponse<TData>>;\n};\n\n/**\n * @public\n * @param {FetchConfig} [defaultOptions={}] - Fetch Configs.\n * @returns {FetchClient} A fetch client object with methods for making HTTP requests.\n * @description This is an abstraction around the native fetch exposed by a function. It provides a simple interface to handle API calls\n * to the Strapi backend.\n * @example\n * ```tsx\n * import { getFetchClient } from '@strapi/admin/admin';\n *\n * const myFunct = () => {\n * const { get } = getFetchClient();\n * const requestURL = \"/some-endpoint\";\n *\n * const { data } = await get(requestURL);\n *\n * return data;\n * };\n * ```\n */\nconst getFetchClient = (defaultOptions: FetchConfig = {}): FetchClient => {\n const backendURL = window.strapi.backendURL;\n\n /**\n * Create default headers with the current token.\n * This is a function so we can get a fresh token after refresh.\n */\n const getDefaultHeaders = () => ({\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${getToken()}`,\n });\n\n const isFormDataRequest = (body: unknown) => body instanceof FormData;\n const addPrependingSlash = (url: string) => (url.charAt(0) !== '/' ? `/${url}` : url);\n\n // This regular expression matches a string that starts with either \"http://\" or \"https://\" or any other protocol name in lower case letters, followed by \"://\" and ends with anything else\n const hasProtocol = (url: string) => new RegExp('^(?:[a-z+]+:)?//', 'i').test(url);\n\n // Check if the url has a prepending slash, if not add a slash\n const normalizeUrl = (url: string) => (hasProtocol(url) ? url : addPrependingSlash(url));\n\n // Add a response interceptor to return the response\n const responseInterceptor = async <TData = any>(\n response: Response,\n validateStatus?: FetchOptions['validateStatus'],\n responseType: NonNullable<FetchOptions['responseType']> = 'json'\n ): Promise<FetchResponse<TData>> => {\n if (responseType !== 'json') {\n if (!response.ok && !validateStatus?.(response.status)) {\n const fetchError = new FetchError('Server Error');\n fetchError.status = response.status;\n throw fetchError;\n }\n\n let result: Blob | string | ArrayBuffer;\n if (responseType === 'blob') {\n result = await response.blob();\n } else if (responseType === 'text') {\n result = await response.text();\n } else {\n result = await response.arrayBuffer();\n }\n\n return { data: result as TData, status: response.status, headers: response.headers };\n }\n\n if (response.status === 204) {\n return { data: {} as TData, status: response.status };\n }\n\n try {\n const result = await response.json();\n\n if (!response.ok && result.error && !validateStatus?.(response.status)) {\n const fetchError = new FetchError(result.error.message, { data: result });\n fetchError.status = response.status;\n throw fetchError;\n }\n\n if (!response.ok && !validateStatus?.(response.status)) {\n const fetchError = new FetchError('Unknown Server Error');\n fetchError.status = response.status;\n throw fetchError;\n }\n\n return { data: result };\n } catch (error) {\n // An empty 200 body causes `response.json()` to throw a `SyntaxError`. We treat\n // it as success and return an empty payload. We match on `error.name` rather\n // than `instanceof SyntaxError` because constructor identity differs across JS\n // realms — a Response from a different realm (e.g. undici under jsdom in tests,\n // a service worker or iframe in browsers) throws a `SyntaxError` whose\n // constructor is not the same identity as the one this module closes over. Name\n // comparison is realm-agnostic.\n if ((error as Error | null)?.name === 'SyntaxError' && response.ok) {\n return { data: [], status: response.status } as FetchResponse<any>;\n } else {\n throw error;\n }\n }\n };\n\n /**\n * Execute a fetch request with automatic token refresh on 401 errors.\n * @param url - The request URL (used to check if it's an auth path)\n * @param executeRequest - Function that performs the fetch (called again on retry with fresh headers)\n */\n const withTokenRefresh = async <TData>(\n url: string,\n executeRequest: () => Promise<FetchResponse<TData>>\n ): Promise<FetchResponse<TData>> => {\n try {\n return await executeRequest();\n } catch (error) {\n // Only attempt refresh for 401 errors on non-auth paths\n if (isFetchError(error) && error.status === 401 && !isAuthPath(url)) {\n try {\n await attemptTokenRefresh();\n // Retry - executeRequest will call getDefaultHeaders() again, picking up the new token\n return await executeRequest();\n } catch {\n // If refresh fails, throw the original error\n throw error;\n }\n }\n throw error;\n }\n };\n\n const paramsSerializer =\n <Param = unknown>(params?: Param) =>\n (url: string) => {\n if (params) {\n if (typeof params === 'string') {\n return `${url}?${params}`;\n }\n\n /**\n * TODO V6: Encoding should be enabled in this step\n * So the rest of the app doesn't have to worry about it,\n * It's considered a breaking change because it impacts any API request, including the user's custom code\n */\n const serializedParams = qs.stringify(params, { encode: false });\n if (serializedParams) {\n return `${url}?${serializedParams}`;\n }\n return url;\n }\n return url;\n };\n\n const addBaseUrl = (url: Parameters<typeof fetch>[0]) => {\n return `${backendURL}${url}`;\n };\n\n /**\n * We use the factory method because the options\n * are unique to the individual request\n */\n const makeCreateRequestUrl = (options?: FetchOptions) =>\n pipe(normalizeUrl, addBaseUrl, paramsSerializer(options?.params));\n\n const fetchClient: FetchClient = {\n get: async <TData>(url: string, options?: FetchOptions): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n const responseType = options?.responseType ?? 'json';\n\n const executeRequest = async () => {\n const { Authorization } = getDefaultHeaders();\n\n // For non-JSON response types, omit content negotiation headers that imply JSON\n const defaultHeaders = responseType === 'json' ? getDefaultHeaders() : { Authorization };\n\n const headers = new Headers({\n ...defaultHeaders,\n ...options?.headers,\n });\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'GET',\n headers,\n });\n\n return responseInterceptor<TData>(response, options?.validateStatus, responseType);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n post: async <TData, TSend = any>(\n url: string,\n data?: TSend,\n options?: FetchOptions\n ): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n /**\n * we have to remove the Content-Type value if it was a formData request\n * the browser will automatically set the header value\n */\n if (isFormDataRequest(data)) {\n headers.delete('Content-Type');\n }\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'POST',\n headers,\n body: isFormDataRequest(data) ? (data as FormData) : JSON.stringify(data),\n });\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n put: async <TData, TSend = any>(\n url: string,\n data?: TSend,\n options?: FetchOptions\n ): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n /**\n * we have to remove the Content-Type value if it was a formData request\n * the browser will automatically set the header value\n */\n if (isFormDataRequest(data)) {\n headers.delete('Content-Type');\n }\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'PUT',\n headers,\n body: isFormDataRequest(data) ? (data as FormData) : JSON.stringify(data),\n });\n\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n del: async <TData>(url: string, options?: FetchOptions): Promise<FetchResponse<TData>> => {\n const createRequestUrl = makeCreateRequestUrl(options);\n\n const executeRequest = async () => {\n const headers = new Headers({\n ...getDefaultHeaders(),\n ...options?.headers,\n });\n\n const response = await fetch(createRequestUrl(url), {\n signal: options?.signal ?? defaultOptions.signal,\n method: 'DELETE',\n headers,\n });\n return responseInterceptor<TData>(response, options?.validateStatus);\n };\n\n return withTokenRefresh(url, executeRequest);\n },\n };\n\n return fetchClient;\n};\n\nexport {\n getFetchClient,\n isFetchError,\n FetchError,\n attemptTokenRefresh,\n storeToken,\n setOnTokenUpdate,\n};\nexport type { FetchOptions, FetchResponse, FetchConfig, FetchClient, ErrorResponse };\n"],"names":["STORAGE_KEYS","TOKEN","refreshPromise","onTokenUpdate","setOnTokenUpdate","callback","isAuthPath","url","test","storeToken","token","wasPersistedToLocalStorage","Boolean","localStorage","getItem","setItem","JSON","stringify","setCookie","refreshAccessToken","backendURL","window","strapi","response","fetch","method","credentials","headers","Accept","ok","console","warn","status","result","json","data","error","attemptTokenRefresh","finally","newToken","Error","name","FetchError","message","code","captureStackTrace","isFetchError","getToken","fromLocalStorage","parse","fromCookie","getCookieValue","getFetchClient","defaultOptions","getDefaultHeaders","Authorization","isFormDataRequest","body","FormData","addPrependingSlash","charAt","hasProtocol","RegExp","normalizeUrl","responseInterceptor","validateStatus","responseType","fetchError","blob","text","arrayBuffer","withTokenRefresh","executeRequest","paramsSerializer","params","serializedParams","qs","encode","addBaseUrl","makeCreateRequestUrl","options","pipe","fetchClient","get","createRequestUrl","defaultHeaders","Headers","signal","post","delete","put","del"],"mappings":";;;;AAqBA,MAAMA,YAAAA,GAAe;IACnBC,KAAAA,EAAO,UAET,CAAA;AAEA;;AAEC,IACD,IAAIC,cAAAA,GAAgD,IAAA;AAEpD;;AAEC,IACD,IAAIC,aAAAA,GAAkD,IAAA;AAEtD;;;;;;;;;;;IAYA,MAAMC,mBAAmB,CAACC,QAAAA,GAAAA;IACxBF,aAAAA,GAAgBE,QAAAA;AAClB;AAEA;;;;AAIC,IACD,MAAMC,UAAAA,GAAa,CAACC,GAAAA,GAAgB,wCAAA,CAAyCC,IAAI,CAACD,GAAAA,CAAAA;AAElF;;;;;;;;;IAUA,MAAME,aAAa,CAACC,KAAAA,GAAAA;;AAElB,IAAA,MAAMC,6BAA6BC,OAAAA,CAAQC,YAAAA,CAAaC,OAAO,CAACd,aAAaC,KAAK,CAAA,CAAA;AAElF,IAAA,IAAIU,0BAAAA,EAA4B;AAC9BE,QAAAA,YAAAA,CAAaE,OAAO,CAACf,YAAAA,CAAaC,KAAK,EAAEe,IAAAA,CAAKC,SAAS,CAACP,KAAAA,CAAAA,CAAAA;IAC1D,CAAA,MAAO;QACLQ,SAAAA,CAAUlB,YAAAA,CAAaC,KAAK,EAAES,KAAAA,CAAAA;AAChC,IAAA;;AAGA,IAAA,IAAIP,aAAAA,EAAe;QACjBA,aAAAA,CAAcO,KAAAA,CAAAA;AAChB,IAAA;AACF;AAEA;;;;AAIC,IACD,MAAMS,kBAAAA,GAAqB,UAAA;AACzB,IAAA,MAAMC,UAAAA,GAAaC,MAAAA,CAAOC,MAAM,CAACF,UAAU;IAE3C,IAAI;AACF,QAAA,MAAMG,WAAW,MAAMC,KAAAA,CAAM,GAAGJ,UAAAA,CAAW,mBAAmB,CAAC,EAAE;YAC/DK,MAAAA,EAAQ,MAAA;YACRC,WAAAA,EAAa,SAAA;YACbC,OAAAA,EAAS;gBACPC,MAAAA,EAAQ,kBAAA;gBACR,cAAA,EAAgB;AAClB;AACF,SAAA,CAAA;QAEA,IAAI,CAACL,QAAAA,CAASM,EAAE,EAAE;AAChBC,YAAAA,OAAAA,CAAQC,IAAI,CAAC,0CAAA,EAA4CR,QAAAA,CAASS,MAAM,CAAA;YACxE,OAAO,IAAA;AACT,QAAA;QAEA,MAAMC,MAAAA,GAAS,MAAMV,QAAAA,CAASW,IAAI,EAAA;QAClC,MAAMxB,KAAAA,GAAQuB,QAAQE,IAAAA,EAAMzB,KAAAA;AAE5B,QAAA,IAAI,CAACA,KAAAA,EAAO;AACVoB,YAAAA,OAAAA,CAAQC,IAAI,CAAC,6CAAA,CAAA;YACb,OAAO,IAAA;AACT,QAAA;QAEAtB,UAAAA,CAAWC,KAAAA,CAAAA;QACX,OAAOA,KAAAA;AACT,IAAA,CAAA,CAAE,OAAO0B,KAAAA,EAAO;QACdN,OAAAA,CAAQM,KAAK,CAAC,6BAAA,EAA+BA,KAAAA,CAAAA;QAC7C,OAAO,IAAA;AACT,IAAA;AACF,CAAA;AAEA;;;;;;;AAOC,UACKC,mBAAAA,GAAsB,UAAA;AAC1B,IAAA,IAAI,CAACnC,cAAAA,EAAgB;QACnBA,cAAAA,GAAiBiB,kBAAAA,EAAAA,CAAqBmB,OAAO,CAAC,IAAA;YAC5CpC,cAAAA,GAAiB,IAAA;AACnB,QAAA,CAAA,CAAA;AACF,IAAA;AAEA,IAAA,MAAMqC,WAAW,MAAMrC,cAAAA;AACvB,IAAA,IAAI,CAACqC,QAAAA,EAAU;QACb,MAAMH,KAAAA,GAAQ,IAAII,KAAAA,CAAM,uCAAA,CAAA;AACxBJ,QAAAA,KAAAA,CAAMK,IAAI,GAAG,mBAAA;QACb,MAAML,KAAAA;AACR,IAAA;IAEA,OAAOG,QAAAA;AACT;AA2BA,MAAMG,UAAAA,SAAmBF,KAAAA,CAAAA;IAOvB,WAAA,CAAYG,OAAe,EAAEpB,QAAwB,CAAE;AACrD,QAAA,KAAK,CAACoB,OAAAA,CAAAA;QACN,IAAI,CAACF,IAAI,GAAG,YAAA;QACZ,IAAI,CAACE,OAAO,GAAGA,OAAAA;QACf,IAAI,CAACpB,QAAQ,GAAGA,QAAAA;AAChB,QAAA,IAAI,CAACqB,IAAI,GAAGrB,QAAAA,EAAUY,MAAMC,KAAAA,EAAOJ,MAAAA;AACnC,QAAA,IAAI,CAACA,MAAM,GAAGT,QAAAA,EAAUY,MAAMC,KAAAA,EAAOJ,MAAAA;;QAGrC,IAAIQ,KAAAA,CAAMK,iBAAiB,EAAE;YAC3BL,KAAAA,CAAMK,iBAAiB,CAAC,IAAI,EAAEH,UAAAA,CAAAA;AAChC,QAAA;AACF,IAAA;AACF;AAEA,MAAMI,eAAe,CAACV,KAAAA,GAAAA;AACpB,IAAA,OAAOA,KAAAA,YAAiBM,UAAAA;AAC1B;AAEA,MAAMK,QAAAA,GAAW,IAAA;AACf,IAAA,MAAMC,gBAAAA,GAAmBnC,YAAAA,CAAaC,OAAO,CAACd,aAAaC,KAAK,CAAA;AAChE,IAAA,IAAI+C,gBAAAA,EAAkB;QACpB,OAAOhC,IAAAA,CAAKiC,KAAK,CAACD,gBAAAA,CAAAA;AACpB,IAAA;IAEA,MAAME,UAAAA,GAAaC,cAAAA,CAAenD,YAAAA,CAAaC,KAAK,CAAA;AACpD,IAAA,OAAOiD,UAAAA,IAAc,IAAA;AACvB,CAAA;AAyBA;;;;;;;;;;;;;;;;;;;AAmBC,IACD,MAAME,cAAAA,GAAiB,CAACC,cAAAA,GAA8B,EAAE,GAAA;AACtD,IAAA,MAAMjC,UAAAA,GAAaC,MAAAA,CAAOC,MAAM,CAACF,UAAU;AAE3C;;;MAIA,MAAMkC,iBAAAA,GAAoB,KAAO;YAC/B1B,MAAAA,EAAQ,kBAAA;YACR,cAAA,EAAgB,kBAAA;YAChB2B,aAAAA,EAAe,CAAC,OAAO,EAAER,QAAAA,EAAAA,CAAAA;SAC3B,CAAA;IAEA,MAAMS,iBAAAA,GAAoB,CAACC,IAAAA,GAAkBA,IAAAA,YAAgBC,QAAAA;AAC7D,IAAA,MAAMC,kBAAAA,GAAqB,CAACpD,GAAAA,GAAiBA,GAAAA,CAAIqD,MAAM,CAAC,CAAA,CAAA,KAAO,GAAA,GAAM,CAAC,CAAC,EAAErD,GAAAA,CAAAA,CAAK,GAAGA,GAAAA;;IAGjF,MAAMsD,WAAAA,GAAc,CAACtD,GAAAA,GAAgB,IAAIuD,OAAO,kBAAA,EAAoB,GAAA,CAAA,CAAKtD,IAAI,CAACD,GAAAA,CAAAA;;AAG9E,IAAA,MAAMwD,eAAe,CAACxD,GAAAA,GAAiBsD,WAAAA,CAAYtD,GAAAA,CAAAA,GAAOA,MAAMoD,kBAAAA,CAAmBpD,GAAAA,CAAAA;;AAGnF,IAAA,MAAMyD,mBAAAA,GAAsB,OAC1BzC,QAAAA,EACA0C,cAAAA,EACAC,eAA0D,MAAM,GAAA;AAEhE,QAAA,IAAIA,iBAAiB,MAAA,EAAQ;YAC3B,IAAI,CAAC3C,SAASM,EAAE,IAAI,CAACoC,cAAAA,GAAiB1C,QAAAA,CAASS,MAAM,CAAA,EAAG;gBACtD,MAAMmC,UAAAA,GAAa,IAAIzB,UAAAA,CAAW,cAAA,CAAA;gBAClCyB,UAAAA,CAAWnC,MAAM,GAAGT,QAAAA,CAASS,MAAM;gBACnC,MAAMmC,UAAAA;AACR,YAAA;YAEA,IAAIlC,MAAAA;AACJ,YAAA,IAAIiC,iBAAiB,MAAA,EAAQ;gBAC3BjC,MAAAA,GAAS,MAAMV,SAAS6C,IAAI,EAAA;YAC9B,CAAA,MAAO,IAAIF,iBAAiB,MAAA,EAAQ;gBAClCjC,MAAAA,GAAS,MAAMV,SAAS8C,IAAI,EAAA;YAC9B,CAAA,MAAO;gBACLpC,MAAAA,GAAS,MAAMV,SAAS+C,WAAW,EAAA;AACrC,YAAA;YAEA,OAAO;gBAAEnC,IAAAA,EAAMF,MAAAA;AAAiBD,gBAAAA,MAAAA,EAAQT,SAASS,MAAM;AAAEL,gBAAAA,OAAAA,EAASJ,SAASI;AAAQ,aAAA;AACrF,QAAA;QAEA,IAAIJ,QAAAA,CAASS,MAAM,KAAK,GAAA,EAAK;YAC3B,OAAO;AAAEG,gBAAAA,IAAAA,EAAM,EAAC;AAAYH,gBAAAA,MAAAA,EAAQT,SAASS;AAAO,aAAA;AACtD,QAAA;QAEA,IAAI;YACF,MAAMC,MAAAA,GAAS,MAAMV,QAAAA,CAASW,IAAI,EAAA;YAElC,IAAI,CAACX,QAAAA,CAASM,EAAE,IAAII,MAAAA,CAAOG,KAAK,IAAI,CAAC6B,cAAAA,GAAiB1C,QAAAA,CAASS,MAAM,CAAA,EAAG;AACtE,gBAAA,MAAMmC,aAAa,IAAIzB,UAAAA,CAAWT,OAAOG,KAAK,CAACO,OAAO,EAAE;oBAAER,IAAAA,EAAMF;AAAO,iBAAA,CAAA;gBACvEkC,UAAAA,CAAWnC,MAAM,GAAGT,QAAAA,CAASS,MAAM;gBACnC,MAAMmC,UAAAA;AACR,YAAA;YAEA,IAAI,CAAC5C,SAASM,EAAE,IAAI,CAACoC,cAAAA,GAAiB1C,QAAAA,CAASS,MAAM,CAAA,EAAG;gBACtD,MAAMmC,UAAAA,GAAa,IAAIzB,UAAAA,CAAW,sBAAA,CAAA;gBAClCyB,UAAAA,CAAWnC,MAAM,GAAGT,QAAAA,CAASS,MAAM;gBACnC,MAAMmC,UAAAA;AACR,YAAA;YAEA,OAAO;gBAAEhC,IAAAA,EAAMF;AAAO,aAAA;AACxB,QAAA,CAAA,CAAE,OAAOG,KAAAA,EAAO;;;;;;;;AAQd,YAAA,IAAI,KAACA,EAAwBK,IAAAA,KAAS,aAAA,IAAiBlB,QAAAA,CAASM,EAAE,EAAE;gBAClE,OAAO;AAAEM,oBAAAA,IAAAA,EAAM,EAAE;AAAEH,oBAAAA,MAAAA,EAAQT,SAASS;AAAO,iBAAA;YAC7C,CAAA,MAAO;gBACL,MAAMI,KAAAA;AACR,YAAA;AACF,QAAA;AACF,IAAA,CAAA;AAEA;;;;MAKA,MAAMmC,gBAAAA,GAAmB,OACvBhE,GAAAA,EACAiE,cAAAA,GAAAA;QAEA,IAAI;AACF,YAAA,OAAO,MAAMA,cAAAA,EAAAA;AACf,QAAA,CAAA,CAAE,OAAOpC,KAAAA,EAAO;;YAEd,IAAIU,YAAAA,CAAaV,UAAUA,KAAAA,CAAMJ,MAAM,KAAK,GAAA,IAAO,CAAC1B,WAAWC,GAAAA,CAAAA,EAAM;gBACnE,IAAI;oBACF,MAAM8B,mBAAAA,EAAAA;;AAEN,oBAAA,OAAO,MAAMmC,cAAAA,EAAAA;AACf,gBAAA,CAAA,CAAE,OAAM;;oBAEN,MAAMpC,KAAAA;AACR,gBAAA;AACF,YAAA;YACA,MAAMA,KAAAA;AACR,QAAA;AACF,IAAA,CAAA;IAEA,MAAMqC,gBAAAA,GACJ,CAAkBC,MAAAA,GAClB,CAACnE,GAAAA,GAAAA;AACC,YAAA,IAAImE,MAAAA,EAAQ;gBACV,IAAI,OAAOA,WAAW,QAAA,EAAU;AAC9B,oBAAA,OAAO,CAAA,EAAGnE,GAAAA,CAAI,CAAC,EAAEmE,MAAAA,CAAAA,CAAQ;AAC3B,gBAAA;AAEA;;;;AAIC,YACD,MAAMC,gBAAAA,GAAmBC,WAAAA,CAAG3D,SAAS,CAACyD,MAAAA,EAAQ;oBAAEG,MAAAA,EAAQ;AAAM,iBAAA,CAAA;AAC9D,gBAAA,IAAIF,gBAAAA,EAAkB;AACpB,oBAAA,OAAO,CAAA,EAAGpE,GAAAA,CAAI,CAAC,EAAEoE,gBAAAA,CAAAA,CAAkB;AACrC,gBAAA;gBACA,OAAOpE,GAAAA;AACT,YAAA;YACA,OAAOA,GAAAA;AACT,QAAA,CAAA;AAEF,IAAA,MAAMuE,aAAa,CAACvE,GAAAA,GAAAA;QAClB,OAAO,CAAA,EAAGa,aAAab,GAAAA,CAAAA,CAAK;AAC9B,IAAA,CAAA;AAEA;;;MAIA,MAAMwE,uBAAuB,CAACC,OAAAA,GAC5BC,KAAKlB,YAAAA,EAAce,UAAAA,EAAYL,iBAAiBO,OAAAA,EAASN,MAAAA,CAAAA,CAAAA;AAE3D,IAAA,MAAMQ,WAAAA,GAA2B;AAC/BC,QAAAA,GAAAA,EAAK,OAAc5E,GAAAA,EAAayE,OAAAA,GAAAA;AAC9B,YAAA,MAAMI,mBAAmBL,oBAAAA,CAAqBC,OAAAA,CAAAA;YAC9C,MAAMd,YAAAA,GAAec,SAASd,YAAAA,IAAgB,MAAA;AAE9C,YAAA,MAAMM,cAAAA,GAAiB,UAAA;gBACrB,MAAM,EAAEjB,aAAa,EAAE,GAAGD,iBAAAA,EAAAA;;gBAG1B,MAAM+B,cAAAA,GAAiBnB,YAAAA,KAAiB,MAAA,GAASZ,iBAAAA,EAAAA,GAAsB;AAAEC,oBAAAA;AAAc,iBAAA;gBAEvF,MAAM5B,OAAAA,GAAU,IAAI2D,OAAAA,CAAQ;AAC1B,oBAAA,GAAGD,cAAc;AACjB,oBAAA,GAAGL,SAASrD;AACd,iBAAA,CAAA;AAEA,gBAAA,MAAMJ,QAAAA,GAAW,MAAMC,KAAAA,CAAM4D,gBAAAA,CAAiB7E,GAAAA,CAAAA,EAAM;oBAClDgF,MAAAA,EAAQP,OAAAA,EAASO,MAAAA,IAAUlC,cAAAA,CAAekC,MAAM;oBAChD9D,MAAAA,EAAQ,KAAA;AACRE,oBAAAA;AACF,iBAAA,CAAA;gBAEA,OAAOqC,mBAAAA,CAA2BzC,QAAAA,EAAUyD,OAAAA,EAASf,cAAAA,EAAgBC,YAAAA,CAAAA;AACvE,YAAA,CAAA;AAEA,YAAA,OAAOK,iBAAiBhE,GAAAA,EAAKiE,cAAAA,CAAAA;AAC/B,QAAA,CAAA;QACAgB,IAAAA,EAAM,OACJjF,KACA4B,IAAAA,EACA6C,OAAAA,GAAAA;AAEA,YAAA,MAAMI,mBAAmBL,oBAAAA,CAAqBC,OAAAA,CAAAA;AAE9C,YAAA,MAAMR,cAAAA,GAAiB,UAAA;gBACrB,MAAM7C,OAAAA,GAAU,IAAI2D,OAAAA,CAAQ;AAC1B,oBAAA,GAAGhC,iBAAAA,EAAmB;AACtB,oBAAA,GAAG0B,SAASrD;AACd,iBAAA,CAAA;AAEA;;;YAIA,IAAI6B,kBAAkBrB,IAAAA,CAAAA,EAAO;AAC3BR,oBAAAA,OAAAA,CAAQ8D,MAAM,CAAC,cAAA,CAAA;AACjB,gBAAA;AAEA,gBAAA,MAAMlE,QAAAA,GAAW,MAAMC,KAAAA,CAAM4D,gBAAAA,CAAiB7E,GAAAA,CAAAA,EAAM;oBAClDgF,MAAAA,EAAQP,OAAAA,EAASO,MAAAA,IAAUlC,cAAAA,CAAekC,MAAM;oBAChD9D,MAAAA,EAAQ,MAAA;AACRE,oBAAAA,OAAAA;AACA8B,oBAAAA,IAAAA,EAAMD,iBAAAA,CAAkBrB,IAAAA,CAAAA,GAASA,IAAAA,GAAoBnB,IAAAA,CAAKC,SAAS,CAACkB,IAAAA;AACtE,iBAAA,CAAA;gBACA,OAAO6B,mBAAAA,CAA2BzC,UAAUyD,OAAAA,EAASf,cAAAA,CAAAA;AACvD,YAAA,CAAA;AAEA,YAAA,OAAOM,iBAAiBhE,GAAAA,EAAKiE,cAAAA,CAAAA;AAC/B,QAAA,CAAA;QACAkB,GAAAA,EAAK,OACHnF,KACA4B,IAAAA,EACA6C,OAAAA,GAAAA;AAEA,YAAA,MAAMI,mBAAmBL,oBAAAA,CAAqBC,OAAAA,CAAAA;AAE9C,YAAA,MAAMR,cAAAA,GAAiB,UAAA;gBACrB,MAAM7C,OAAAA,GAAU,IAAI2D,OAAAA,CAAQ;AAC1B,oBAAA,GAAGhC,iBAAAA,EAAmB;AACtB,oBAAA,GAAG0B,SAASrD;AACd,iBAAA,CAAA;AAEA;;;YAIA,IAAI6B,kBAAkBrB,IAAAA,CAAAA,EAAO;AAC3BR,oBAAAA,OAAAA,CAAQ8D,MAAM,CAAC,cAAA,CAAA;AACjB,gBAAA;AAEA,gBAAA,MAAMlE,QAAAA,GAAW,MAAMC,KAAAA,CAAM4D,gBAAAA,CAAiB7E,GAAAA,CAAAA,EAAM;oBAClDgF,MAAAA,EAAQP,OAAAA,EAASO,MAAAA,IAAUlC,cAAAA,CAAekC,MAAM;oBAChD9D,MAAAA,EAAQ,KAAA;AACRE,oBAAAA,OAAAA;AACA8B,oBAAAA,IAAAA,EAAMD,iBAAAA,CAAkBrB,IAAAA,CAAAA,GAASA,IAAAA,GAAoBnB,IAAAA,CAAKC,SAAS,CAACkB,IAAAA;AACtE,iBAAA,CAAA;gBAEA,OAAO6B,mBAAAA,CAA2BzC,UAAUyD,OAAAA,EAASf,cAAAA,CAAAA;AACvD,YAAA,CAAA;AAEA,YAAA,OAAOM,iBAAiBhE,GAAAA,EAAKiE,cAAAA,CAAAA;AAC/B,QAAA,CAAA;AACAmB,QAAAA,GAAAA,EAAK,OAAcpF,GAAAA,EAAayE,OAAAA,GAAAA;AAC9B,YAAA,MAAMI,mBAAmBL,oBAAAA,CAAqBC,OAAAA,CAAAA;AAE9C,YAAA,MAAMR,cAAAA,GAAiB,UAAA;gBACrB,MAAM7C,OAAAA,GAAU,IAAI2D,OAAAA,CAAQ;AAC1B,oBAAA,GAAGhC,iBAAAA,EAAmB;AACtB,oBAAA,GAAG0B,SAASrD;AACd,iBAAA,CAAA;AAEA,gBAAA,MAAMJ,QAAAA,GAAW,MAAMC,KAAAA,CAAM4D,gBAAAA,CAAiB7E,GAAAA,CAAAA,EAAM;oBAClDgF,MAAAA,EAAQP,OAAAA,EAASO,MAAAA,IAAUlC,cAAAA,CAAekC,MAAM;oBAChD9D,MAAAA,EAAQ,QAAA;AACRE,oBAAAA;AACF,iBAAA,CAAA;gBACA,OAAOqC,mBAAAA,CAA2BzC,UAAUyD,OAAAA,EAASf,cAAAA,CAAAA;AACvD,YAAA,CAAA;AAEA,YAAA,OAAOM,iBAAiBhE,GAAAA,EAAKiE,cAAAA,CAAAA;AAC/B,QAAA;AACF,KAAA;IAEA,OAAOU,WAAAA;AACT;;;;"}
|