@strapi/admin 5.42.1 → 5.44.0
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 +17 -4
- package/dist/admin/admin/src/StrapiApp.js.map +1 -1
- package/dist/admin/admin/src/StrapiApp.mjs +18 -5
- package/dist/admin/admin/src/StrapiApp.mjs.map +1 -1
- package/dist/admin/admin/src/components/Form.js +29 -18
- package/dist/admin/admin/src/components/Form.js.map +1 -1
- package/dist/admin/admin/src/components/Form.mjs +29 -18
- package/dist/admin/admin/src/components/Form.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Date.js +2 -2
- package/dist/admin/admin/src/components/FormInputs/Date.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Date.mjs +2 -2
- package/dist/admin/admin/src/components/FormInputs/Date.mjs.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Context.js +3 -2
- package/dist/admin/admin/src/components/GuidedTour/Context.js.map +1 -1
- package/dist/admin/admin/src/components/GuidedTour/Context.mjs +3 -2
- package/dist/admin/admin/src/components/GuidedTour/Context.mjs.map +1 -1
- package/dist/admin/admin/src/components/Layouts/Layout.js +1 -0
- package/dist/admin/admin/src/components/Layouts/Layout.js.map +1 -1
- package/dist/admin/admin/src/components/Layouts/Layout.mjs +1 -0
- package/dist/admin/admin/src/components/Layouts/Layout.mjs.map +1 -1
- package/dist/admin/admin/src/components/PageHelpers.js +1 -1
- package/dist/admin/admin/src/components/PageHelpers.js.map +1 -1
- package/dist/admin/admin/src/components/PageHelpers.mjs +1 -1
- package/dist/admin/admin/src/components/PageHelpers.mjs.map +1 -1
- package/dist/admin/admin/src/components/Table.js +28 -15
- package/dist/admin/admin/src/components/Table.js.map +1 -1
- package/dist/admin/admin/src/components/Table.mjs +29 -16
- package/dist/admin/admin/src/components/Table.mjs.map +1 -1
- package/dist/admin/admin/src/components/Widgets.js +52 -0
- package/dist/admin/admin/src/components/Widgets.js.map +1 -1
- package/dist/admin/admin/src/components/Widgets.mjs +54 -3
- package/dist/admin/admin/src/components/Widgets.mjs.map +1 -1
- package/dist/admin/admin/src/core/store/configure.js +3 -1
- package/dist/admin/admin/src/core/store/configure.js.map +1 -1
- package/dist/admin/admin/src/core/store/configure.mjs +3 -1
- package/dist/admin/admin/src/core/store/configure.mjs.map +1 -1
- package/dist/admin/admin/src/hooks/usePersistentState.js +9 -4
- package/dist/admin/admin/src/hooks/usePersistentState.js.map +1 -1
- package/dist/admin/admin/src/hooks/usePersistentState.mjs +10 -6
- package/dist/admin/admin/src/hooks/usePersistentState.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.js +4 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.mjs +4 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/LogoInput.mjs.map +1 -1
- package/dist/admin/admin/src/render.js +2 -0
- package/dist/admin/admin/src/render.js.map +1 -1
- package/dist/admin/admin/src/render.mjs +2 -0
- package/dist/admin/admin/src/render.mjs.map +1 -1
- package/dist/admin/admin/src/services/api.js +2 -2
- package/dist/admin/admin/src/services/api.js.map +1 -1
- package/dist/admin/admin/src/services/api.mjs +2 -2
- package/dist/admin/admin/src/services/api.mjs.map +1 -1
- package/dist/admin/admin/src/translations/ar.json.js +4 -1
- package/dist/admin/admin/src/translations/ar.json.js.map +1 -1
- package/dist/admin/admin/src/translations/ar.json.mjs +4 -1
- package/dist/admin/admin/src/translations/ar.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/cs.json.js +736 -13
- package/dist/admin/admin/src/translations/cs.json.js.map +1 -1
- package/dist/admin/admin/src/translations/cs.json.mjs +728 -14
- package/dist/admin/admin/src/translations/cs.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/de.json.js +4 -1
- package/dist/admin/admin/src/translations/de.json.js.map +1 -1
- package/dist/admin/admin/src/translations/de.json.mjs +4 -1
- package/dist/admin/admin/src/translations/de.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +4 -1
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +4 -1
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/es.json.js +4 -1
- package/dist/admin/admin/src/translations/es.json.js.map +1 -1
- package/dist/admin/admin/src/translations/es.json.mjs +4 -1
- package/dist/admin/admin/src/translations/es.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/fr.json.js +4 -1
- package/dist/admin/admin/src/translations/fr.json.js.map +1 -1
- package/dist/admin/admin/src/translations/fr.json.mjs +4 -1
- package/dist/admin/admin/src/translations/fr.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/it.json.js +4 -1
- package/dist/admin/admin/src/translations/it.json.js.map +1 -1
- package/dist/admin/admin/src/translations/it.json.mjs +4 -1
- package/dist/admin/admin/src/translations/it.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/nl.json.js +394 -89
- package/dist/admin/admin/src/translations/nl.json.js.map +1 -1
- package/dist/admin/admin/src/translations/nl.json.mjs +393 -90
- package/dist/admin/admin/src/translations/nl.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/ru.json.js +32 -19
- package/dist/admin/admin/src/translations/ru.json.js.map +1 -1
- package/dist/admin/admin/src/translations/ru.json.mjs +32 -19
- package/dist/admin/admin/src/translations/ru.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/zh-Hans.json.js +4 -1
- package/dist/admin/admin/src/translations/zh-Hans.json.js.map +1 -1
- package/dist/admin/admin/src/translations/zh-Hans.json.mjs +4 -1
- package/dist/admin/admin/src/translations/zh-Hans.json.mjs.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.js +29 -3
- package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.mjs +29 -3
- package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
- package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.js +1 -1
- package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.js.map +1 -1
- package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.mjs +2 -2
- package/dist/admin/ee/admin/src/hooks/useAIUsageWarning.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs +2 -2
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs.map +1 -1
- package/dist/admin/ee/admin/src/services/ai.js +7 -7
- package/dist/admin/ee/admin/src/services/ai.js.map +1 -1
- package/dist/admin/ee/admin/src/services/ai.mjs +6 -6
- package/dist/admin/ee/admin/src/services/ai.mjs.map +1 -1
- package/dist/admin/ee.js +2 -2
- package/dist/admin/ee.mjs +1 -1
- package/dist/admin/index.js +1 -0
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/Widgets.d.ts +2 -1
- package/dist/admin/src/core/store/configure.d.ts +2 -2
- package/dist/admin/src/core/store/hooks.d.ts +2 -2
- package/dist/admin/src/ee.d.ts +1 -1
- package/dist/admin/src/hooks/useAdminRoles.d.ts +1 -1
- package/dist/admin/src/hooks/usePersistentState.d.ts +2 -1
- package/dist/admin/src/index.d.ts +1 -1
- package/dist/admin/src/pages/Settings/pages/Webhooks/hooks/useWebhooks.d.ts +4 -4
- package/dist/admin/src/selectors.d.ts +2 -2
- package/dist/admin/src/services/admin.d.ts +6 -6
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/apiTokens.d.ts +1 -1
- package/dist/admin/src/services/auth.d.ts +11 -11
- package/dist/admin/src/services/contentApi.d.ts +1 -1
- package/dist/admin/src/services/contentManager.d.ts +1 -1
- package/dist/admin/src/services/homepage.d.ts +3 -3
- package/dist/admin/src/services/transferTokens.d.ts +1 -1
- package/dist/admin/src/services/users.d.ts +8 -8
- package/dist/admin/src/services/webhooks.d.ts +2 -2
- package/dist/admin/src/utils/getFetchClient.d.ts +14 -1
- package/dist/admin/tests/utils.d.ts +1 -1
- package/dist/ee/admin/src/services/ai.d.ts +6 -6
- package/dist/ee/admin/src/services/auditLogs.d.ts +1 -1
- package/dist/ee/server/src/index.d.ts +0 -16
- package/dist/ee/server/src/index.d.ts.map +1 -1
- package/dist/server/ee/server/src/index.js +0 -16
- package/dist/server/ee/server/src/index.js.map +1 -1
- package/dist/server/ee/server/src/index.mjs +0 -16
- package/dist/server/ee/server/src/index.mjs.map +1 -1
- package/dist/server/server/src/ai/controllers/ai.js +52 -0
- package/dist/server/server/src/ai/controllers/ai.js.map +1 -0
- package/dist/server/server/src/ai/controllers/ai.mjs +50 -0
- package/dist/server/server/src/ai/controllers/ai.mjs.map +1 -0
- package/dist/server/{ee/server → server}/src/ai/routes/ai.js +1 -2
- package/dist/server/server/src/ai/routes/ai.js.map +1 -0
- package/dist/server/{ee/server → server}/src/ai/routes/ai.mjs +1 -2
- package/dist/server/server/src/ai/routes/ai.mjs.map +1 -0
- package/dist/server/{ee/server/src/ai/containers → server/src/ai/services}/ai.js +107 -32
- package/dist/server/server/src/ai/services/ai.js.map +1 -0
- package/dist/server/{ee/server/src/ai/containers → server/src/ai/services}/ai.mjs +107 -32
- package/dist/server/server/src/ai/services/ai.mjs.map +1 -0
- package/dist/server/server/src/controllers/index.js +3 -1
- package/dist/server/server/src/controllers/index.js.map +1 -1
- package/dist/server/server/src/controllers/index.mjs +3 -1
- package/dist/server/server/src/controllers/index.mjs.map +1 -1
- package/dist/server/server/src/register.js +4 -0
- package/dist/server/server/src/register.js.map +1 -1
- package/dist/server/server/src/register.mjs +4 -0
- package/dist/server/server/src/register.mjs.map +1 -1
- package/dist/server/server/src/routes/index.js +3 -1
- package/dist/server/server/src/routes/index.js.map +1 -1
- package/dist/server/server/src/routes/index.mjs +3 -1
- package/dist/server/server/src/routes/index.mjs.map +1 -1
- package/dist/{ee/server → server}/src/ai/controllers/ai.d.ts +1 -1
- package/dist/server/src/ai/controllers/ai.d.ts.map +1 -0
- package/dist/server/src/ai/routes/ai.d.ts.map +1 -0
- package/dist/server/src/ai/services/ai.d.ts +30 -0
- package/dist/server/src/ai/services/ai.d.ts.map +1 -0
- package/dist/server/src/controllers/index.d.ts +5 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +5 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/shared/contracts/ai.d.ts +3 -3
- package/package.json +11 -11
- package/dist/ee/server/src/ai/containers/ai.d.ts +0 -15
- package/dist/ee/server/src/ai/containers/ai.d.ts.map +0 -1
- package/dist/ee/server/src/ai/controllers/ai.d.ts.map +0 -1
- package/dist/ee/server/src/ai/routes/ai.d.ts.map +0 -1
- package/dist/server/ee/server/src/ai/containers/ai.js.map +0 -1
- package/dist/server/ee/server/src/ai/containers/ai.mjs.map +0 -1
- package/dist/server/ee/server/src/ai/controllers/ai.js +0 -121
- package/dist/server/ee/server/src/ai/controllers/ai.js.map +0 -1
- package/dist/server/ee/server/src/ai/controllers/ai.mjs +0 -119
- package/dist/server/ee/server/src/ai/controllers/ai.mjs.map +0 -1
- package/dist/server/ee/server/src/ai/routes/ai.js.map +0 -1
- package/dist/server/ee/server/src/ai/routes/ai.mjs.map +0 -1
- /package/dist/{ee/server → server}/src/ai/routes/ai.d.ts +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nl.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nl.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -83,7 +83,7 @@ var ru = {
|
|
|
83
83
|
Email: Email,
|
|
84
84
|
"Files Upload": "Загрузка файлов",
|
|
85
85
|
"HomePage.head.title": "Домашняя страница",
|
|
86
|
-
"HomePage.header.title": "
|
|
86
|
+
"HomePage.header.title": "Привет, {name}",
|
|
87
87
|
"HomePage.header.subtitle": "Добро пожаловать в панель администратора",
|
|
88
88
|
"HomePage.widget.loading": "Загрузка содержимого виджета",
|
|
89
89
|
"HomePage.widget.error": "Не удалось загрузить содержимое виджета.",
|
|
@@ -723,32 +723,44 @@ var ru = {
|
|
|
723
723
|
selectButtonTitle: selectButtonTitle,
|
|
724
724
|
skipToContent: skipToContent,
|
|
725
725
|
submit: submit,
|
|
726
|
-
"tours.contentTypeBuilder.Introduction.title": "Конструктор типов
|
|
726
|
+
"tours.contentTypeBuilder.Introduction.title": "Добро пожаловать в Конструктор типов контента!",
|
|
727
727
|
"tours.contentTypeBuilder.Introduction.content": "Создавайте и управляйте структурой вашего контента с помощью типов коллекций, одиночных типов и компонентов.",
|
|
728
|
+
"tours.contentTypeBuilder.AIChat.title": "Пора попробовать!",
|
|
729
|
+
"tours.contentTypeBuilder.AIChat.content": "<p>Если у вас есть вопросы о Конструкторе типов контента или Strapi, задайте их здесь.</p><p>Strapi AI может генерировать схемы, адаптированные под ваши потребности. Запросите именно то, что вам нужно, например:<ul><li>Выбор даты</li><li>Поля для ввода электронной почты и пароля</li><li>Медиафайлы любого типа</li><li>UID</li></ul></p><p>Не стесняйтесь, попробуйте!</p>",
|
|
728
730
|
"tours.contentTypeBuilder.CollectionTypes.title": "Типы коллекций",
|
|
729
731
|
"tours.contentTypeBuilder.CollectionTypes.content": "Структура контента, которая может управлять несколькими записями, такими как статьи или продукты.",
|
|
730
732
|
"tours.contentTypeBuilder.SingleTypes.title": "Одиночные типы",
|
|
731
733
|
"tours.contentTypeBuilder.SingleTypes.content": "Структура контента, которая может управлять только одной записью, такой как домашняя страница или страница контактов.",
|
|
732
734
|
"tours.contentTypeBuilder.Components.title": "Компоненты",
|
|
733
735
|
"tours.contentTypeBuilder.Components.content": "Структура контента, которая может использоваться в нескольких типах коллекций или одиночных типах.",
|
|
734
|
-
"tours.contentTypeBuilder.
|
|
735
|
-
"tours.contentTypeBuilder.
|
|
736
|
+
"tours.contentTypeBuilder.YourTurn.title": "Теперь ваш ход — создайте что-нибудь!",
|
|
737
|
+
"tours.contentTypeBuilder.YourTurn.content": "Создайте тип коллекции или одиночный тип. Нажмите кнопку «+», укажите имя, нажмите «Продолжить», и мы поможем вам сделать всё остальное.",
|
|
738
|
+
"tours.contentTypeBuilder.AddFields.title": "Добавьте поле, чтобы начать",
|
|
739
|
+
"tours.contentTypeBuilder.AddFields.content": "Начните с добавления первого поля, например, имени, изображения или связи. Чтобы тип контента мог что-то содержать, необходимл определить его структуру.",
|
|
740
|
+
"tours.contentTypeBuilder.Save.title": "Не уходите, не сохранив данные!",
|
|
741
|
+
"tours.contentTypeBuilder.Save.content": "Нажмите кнопку «Сохранить», чтобы зафиксировать тип контента и не потерять изменения. Почти готово!",
|
|
742
|
+
"tours.contentTypeBuilder.Finish.title": "Первый шаг: готово! 🎉",
|
|
743
|
+
"tours.contentTypeBuilder.Finish.content": "Вы создали свой первый тип контента! Теперь перейдите в Редактор контента, чтобы начать добавлять записи!",
|
|
744
|
+
"tours.apiTokens.Introduction.title": "И последнее, но не менее важное: API-токены",
|
|
745
|
+
"tours.apiTokens.Introduction.content": "Создавайте и управляйте API-токенами с высоко настраиваемыми разрешениями.",
|
|
746
|
+
"tours.apiTokens.ManageAPIToken.title": "Настройте API-токен",
|
|
747
|
+
"tours.apiTokens.ManageAPIToken.content": "Нажмите на значок «Карандаш», чтобы просмотреть и обновить существующий API-токен.",
|
|
748
|
+
"tours.apiTokens.ViewAPIToken.title": "Посмотрите API-токен",
|
|
749
|
+
"tours.apiTokens.ViewAPIToken.content": "Нажмите кнопку «Просмотреть токен», чтобы увидеть свой API-токен.",
|
|
750
|
+
"tours.apiTokens.CopyAPIToken.title": "Скопируйте ваш API-токен",
|
|
751
|
+
"tours.apiTokens.CopyAPIToken.content": "Нажмите кнопку «Копировать», чтобы сохранить свой API-токен. Он понадобится вам для отправки запросов в ваше приложение. {spacer} Остались вопросы? Узнайте больше об <a>API-токенах</a>.",
|
|
752
|
+
"tours.apiTokens.FinalStep.title": "Поздравляем, пришло время развернуть ваше приложение!",
|
|
753
|
+
"tours.apiTokens.FinalStep.content": "Ваше приложение готово к развёртыванию, и его контент готов к встрече с миром!",
|
|
736
754
|
"tours.contentManager.Introduction.title": "Редактор контента",
|
|
737
755
|
"tours.contentManager.Introduction.content": "Создавайте и управляйте контентом из ваших типов коллекций и одиночных типов.",
|
|
738
|
-
"tours.
|
|
739
|
-
"tours.
|
|
740
|
-
"tours.apiTokens.CreateAnAPIToken.title": "Создать API токен",
|
|
741
|
-
"tours.apiTokens.CreateAnAPIToken.content": "Создайте новый API токен. Выберите имя, продолжительность и тип.",
|
|
742
|
-
"tours.apiTokens.CopyAPIToken.title": "Скопируйте ваш новый API токен",
|
|
743
|
-
"tours.apiTokens.CopyAPIToken.content": "Обязательно сделайте это сейчас, вы больше не сможете его увидеть. Вам нужно будет сгенерировать новый, если вы его потеряете.",
|
|
744
|
-
"tours.apiTokens.FinalStep.title": "Время развернуть ваше приложение!",
|
|
745
|
-
"tours.apiTokens.FinalStep.content": "Ваше приложение готово к развертыванию, и его контент готов к обмену с миром!",
|
|
756
|
+
"tours.contentManager.CreateNewEntry.title": "Создать новую запись",
|
|
757
|
+
"tours.contentManager.CreateNewEntry.content": "Нажмите кнопку «Создать новую запись», чтобы создать и опубликовать новую запись для этого типа коллекции.",
|
|
746
758
|
"tours.contentManager.Fields.title": "Поля",
|
|
747
|
-
"tours.contentManager.Fields.content": "
|
|
759
|
+
"tours.contentManager.Fields.content": "Сначала заполните поля, созданные в Конструкторе типов контента.",
|
|
748
760
|
"tours.contentManager.Publish.title": "Опубликовать",
|
|
749
|
-
"tours.contentManager.Publish.content": "
|
|
750
|
-
"tours.contentManager.FinalStep.title": "Время
|
|
751
|
-
"tours.contentManager.FinalStep.content": "Теперь, когда вы создали и опубликовали
|
|
761
|
+
"tours.contentManager.Publish.content": "Теперь нажмите кнопку «Опубликовать», чтобы сделать ваш контент доступным через API.",
|
|
762
|
+
"tours.contentManager.FinalStep.title": "Время создать API-токены!",
|
|
763
|
+
"tours.contentManager.FinalStep.content": "Теперь, когда вы создали и опубликовали запись, давайте настроим API-токен для управления доступом к вашему контенту.",
|
|
752
764
|
"tours.stepCount": "Шаг {currentStep} из {tourLength}",
|
|
753
765
|
"tours.skip": "Пропустить",
|
|
754
766
|
"tours.next": "Далее",
|
|
@@ -758,8 +770,8 @@ var ru = {
|
|
|
758
770
|
"tours.overview.close": "Закрыть руководство",
|
|
759
771
|
"tours.overview.tasks": "Ваши задачи",
|
|
760
772
|
"tours.overview.contentTypeBuilder.label": "Создайте вашу схему",
|
|
761
|
-
"tours.overview.contentManager.label": "
|
|
762
|
-
"tours.overview.apiTokens.label": "
|
|
773
|
+
"tours.overview.contentManager.label": "Создайте и опубликуйте контент",
|
|
774
|
+
"tours.overview.apiTokens.label": "Скопируйте API-токен",
|
|
763
775
|
"tours.overview.strapiCloud.label": "Разверните ваше приложение в Strapi Cloud",
|
|
764
776
|
"tours.overview.strapiCloud.link": "Читать документацию",
|
|
765
777
|
"tours.overview.tour.link": "Начать",
|
|
@@ -769,9 +781,10 @@ var ru = {
|
|
|
769
781
|
"tours.profile.description": "Вы можете сбросить руководство в любое время.",
|
|
770
782
|
"tours.profile.reset": "Сбросить руководство",
|
|
771
783
|
"tours.profile.notification.success.reset": "Руководство сброшено",
|
|
784
|
+
"tours.overview.completed": "{completed}% выполнено",
|
|
772
785
|
"widget.key-statistics.title": "Статистика проекта",
|
|
773
786
|
"widget.key-statistics.list.admins": "Администраторы",
|
|
774
|
-
"widget.key-statistics.list.apiTokens": "API
|
|
787
|
+
"widget.key-statistics.list.apiTokens": "API-токены",
|
|
775
788
|
"widget.key-statistics.list.assets": "Ассеты",
|
|
776
789
|
"widget.key-statistics.list.components": "Компоненты",
|
|
777
790
|
"widget.key-statistics.list.contentTypes": "Типы контента",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ru.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ru.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -79,7 +79,7 @@ var ru = {
|
|
|
79
79
|
Email: Email,
|
|
80
80
|
"Files Upload": "Загрузка файлов",
|
|
81
81
|
"HomePage.head.title": "Домашняя страница",
|
|
82
|
-
"HomePage.header.title": "
|
|
82
|
+
"HomePage.header.title": "Привет, {name}",
|
|
83
83
|
"HomePage.header.subtitle": "Добро пожаловать в панель администратора",
|
|
84
84
|
"HomePage.widget.loading": "Загрузка содержимого виджета",
|
|
85
85
|
"HomePage.widget.error": "Не удалось загрузить содержимое виджета.",
|
|
@@ -719,32 +719,44 @@ var ru = {
|
|
|
719
719
|
selectButtonTitle: selectButtonTitle,
|
|
720
720
|
skipToContent: skipToContent,
|
|
721
721
|
submit: submit,
|
|
722
|
-
"tours.contentTypeBuilder.Introduction.title": "Конструктор типов
|
|
722
|
+
"tours.contentTypeBuilder.Introduction.title": "Добро пожаловать в Конструктор типов контента!",
|
|
723
723
|
"tours.contentTypeBuilder.Introduction.content": "Создавайте и управляйте структурой вашего контента с помощью типов коллекций, одиночных типов и компонентов.",
|
|
724
|
+
"tours.contentTypeBuilder.AIChat.title": "Пора попробовать!",
|
|
725
|
+
"tours.contentTypeBuilder.AIChat.content": "<p>Если у вас есть вопросы о Конструкторе типов контента или Strapi, задайте их здесь.</p><p>Strapi AI может генерировать схемы, адаптированные под ваши потребности. Запросите именно то, что вам нужно, например:<ul><li>Выбор даты</li><li>Поля для ввода электронной почты и пароля</li><li>Медиафайлы любого типа</li><li>UID</li></ul></p><p>Не стесняйтесь, попробуйте!</p>",
|
|
724
726
|
"tours.contentTypeBuilder.CollectionTypes.title": "Типы коллекций",
|
|
725
727
|
"tours.contentTypeBuilder.CollectionTypes.content": "Структура контента, которая может управлять несколькими записями, такими как статьи или продукты.",
|
|
726
728
|
"tours.contentTypeBuilder.SingleTypes.title": "Одиночные типы",
|
|
727
729
|
"tours.contentTypeBuilder.SingleTypes.content": "Структура контента, которая может управлять только одной записью, такой как домашняя страница или страница контактов.",
|
|
728
730
|
"tours.contentTypeBuilder.Components.title": "Компоненты",
|
|
729
731
|
"tours.contentTypeBuilder.Components.content": "Структура контента, которая может использоваться в нескольких типах коллекций или одиночных типах.",
|
|
730
|
-
"tours.contentTypeBuilder.
|
|
731
|
-
"tours.contentTypeBuilder.
|
|
732
|
+
"tours.contentTypeBuilder.YourTurn.title": "Теперь ваш ход — создайте что-нибудь!",
|
|
733
|
+
"tours.contentTypeBuilder.YourTurn.content": "Создайте тип коллекции или одиночный тип. Нажмите кнопку «+», укажите имя, нажмите «Продолжить», и мы поможем вам сделать всё остальное.",
|
|
734
|
+
"tours.contentTypeBuilder.AddFields.title": "Добавьте поле, чтобы начать",
|
|
735
|
+
"tours.contentTypeBuilder.AddFields.content": "Начните с добавления первого поля, например, имени, изображения или связи. Чтобы тип контента мог что-то содержать, необходимл определить его структуру.",
|
|
736
|
+
"tours.contentTypeBuilder.Save.title": "Не уходите, не сохранив данные!",
|
|
737
|
+
"tours.contentTypeBuilder.Save.content": "Нажмите кнопку «Сохранить», чтобы зафиксировать тип контента и не потерять изменения. Почти готово!",
|
|
738
|
+
"tours.contentTypeBuilder.Finish.title": "Первый шаг: готово! 🎉",
|
|
739
|
+
"tours.contentTypeBuilder.Finish.content": "Вы создали свой первый тип контента! Теперь перейдите в Редактор контента, чтобы начать добавлять записи!",
|
|
740
|
+
"tours.apiTokens.Introduction.title": "И последнее, но не менее важное: API-токены",
|
|
741
|
+
"tours.apiTokens.Introduction.content": "Создавайте и управляйте API-токенами с высоко настраиваемыми разрешениями.",
|
|
742
|
+
"tours.apiTokens.ManageAPIToken.title": "Настройте API-токен",
|
|
743
|
+
"tours.apiTokens.ManageAPIToken.content": "Нажмите на значок «Карандаш», чтобы просмотреть и обновить существующий API-токен.",
|
|
744
|
+
"tours.apiTokens.ViewAPIToken.title": "Посмотрите API-токен",
|
|
745
|
+
"tours.apiTokens.ViewAPIToken.content": "Нажмите кнопку «Просмотреть токен», чтобы увидеть свой API-токен.",
|
|
746
|
+
"tours.apiTokens.CopyAPIToken.title": "Скопируйте ваш API-токен",
|
|
747
|
+
"tours.apiTokens.CopyAPIToken.content": "Нажмите кнопку «Копировать», чтобы сохранить свой API-токен. Он понадобится вам для отправки запросов в ваше приложение. {spacer} Остались вопросы? Узнайте больше об <a>API-токенах</a>.",
|
|
748
|
+
"tours.apiTokens.FinalStep.title": "Поздравляем, пришло время развернуть ваше приложение!",
|
|
749
|
+
"tours.apiTokens.FinalStep.content": "Ваше приложение готово к развёртыванию, и его контент готов к встрече с миром!",
|
|
732
750
|
"tours.contentManager.Introduction.title": "Редактор контента",
|
|
733
751
|
"tours.contentManager.Introduction.content": "Создавайте и управляйте контентом из ваших типов коллекций и одиночных типов.",
|
|
734
|
-
"tours.
|
|
735
|
-
"tours.
|
|
736
|
-
"tours.apiTokens.CreateAnAPIToken.title": "Создать API токен",
|
|
737
|
-
"tours.apiTokens.CreateAnAPIToken.content": "Создайте новый API токен. Выберите имя, продолжительность и тип.",
|
|
738
|
-
"tours.apiTokens.CopyAPIToken.title": "Скопируйте ваш новый API токен",
|
|
739
|
-
"tours.apiTokens.CopyAPIToken.content": "Обязательно сделайте это сейчас, вы больше не сможете его увидеть. Вам нужно будет сгенерировать новый, если вы его потеряете.",
|
|
740
|
-
"tours.apiTokens.FinalStep.title": "Время развернуть ваше приложение!",
|
|
741
|
-
"tours.apiTokens.FinalStep.content": "Ваше приложение готово к развертыванию, и его контент готов к обмену с миром!",
|
|
752
|
+
"tours.contentManager.CreateNewEntry.title": "Создать новую запись",
|
|
753
|
+
"tours.contentManager.CreateNewEntry.content": "Нажмите кнопку «Создать новую запись», чтобы создать и опубликовать новую запись для этого типа коллекции.",
|
|
742
754
|
"tours.contentManager.Fields.title": "Поля",
|
|
743
|
-
"tours.contentManager.Fields.content": "
|
|
755
|
+
"tours.contentManager.Fields.content": "Сначала заполните поля, созданные в Конструкторе типов контента.",
|
|
744
756
|
"tours.contentManager.Publish.title": "Опубликовать",
|
|
745
|
-
"tours.contentManager.Publish.content": "
|
|
746
|
-
"tours.contentManager.FinalStep.title": "Время
|
|
747
|
-
"tours.contentManager.FinalStep.content": "Теперь, когда вы создали и опубликовали
|
|
757
|
+
"tours.contentManager.Publish.content": "Теперь нажмите кнопку «Опубликовать», чтобы сделать ваш контент доступным через API.",
|
|
758
|
+
"tours.contentManager.FinalStep.title": "Время создать API-токены!",
|
|
759
|
+
"tours.contentManager.FinalStep.content": "Теперь, когда вы создали и опубликовали запись, давайте настроим API-токен для управления доступом к вашему контенту.",
|
|
748
760
|
"tours.stepCount": "Шаг {currentStep} из {tourLength}",
|
|
749
761
|
"tours.skip": "Пропустить",
|
|
750
762
|
"tours.next": "Далее",
|
|
@@ -754,8 +766,8 @@ var ru = {
|
|
|
754
766
|
"tours.overview.close": "Закрыть руководство",
|
|
755
767
|
"tours.overview.tasks": "Ваши задачи",
|
|
756
768
|
"tours.overview.contentTypeBuilder.label": "Создайте вашу схему",
|
|
757
|
-
"tours.overview.contentManager.label": "
|
|
758
|
-
"tours.overview.apiTokens.label": "
|
|
769
|
+
"tours.overview.contentManager.label": "Создайте и опубликуйте контент",
|
|
770
|
+
"tours.overview.apiTokens.label": "Скопируйте API-токен",
|
|
759
771
|
"tours.overview.strapiCloud.label": "Разверните ваше приложение в Strapi Cloud",
|
|
760
772
|
"tours.overview.strapiCloud.link": "Читать документацию",
|
|
761
773
|
"tours.overview.tour.link": "Начать",
|
|
@@ -765,9 +777,10 @@ var ru = {
|
|
|
765
777
|
"tours.profile.description": "Вы можете сбросить руководство в любое время.",
|
|
766
778
|
"tours.profile.reset": "Сбросить руководство",
|
|
767
779
|
"tours.profile.notification.success.reset": "Руководство сброшено",
|
|
780
|
+
"tours.overview.completed": "{completed}% выполнено",
|
|
768
781
|
"widget.key-statistics.title": "Статистика проекта",
|
|
769
782
|
"widget.key-statistics.list.admins": "Администраторы",
|
|
770
|
-
"widget.key-statistics.list.apiTokens": "API
|
|
783
|
+
"widget.key-statistics.list.apiTokens": "API-токены",
|
|
771
784
|
"widget.key-statistics.list.assets": "Ассеты",
|
|
772
785
|
"widget.key-statistics.list.components": "Компоненты",
|
|
773
786
|
"widget.key-statistics.list.contentTypes": "Типы контента",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ru.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ru.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -671,7 +671,10 @@ var zhHans = {
|
|
|
671
671
|
"request.error.model.unknown": "此模型不存在",
|
|
672
672
|
selectButtonTitle: selectButtonTitle,
|
|
673
673
|
skipToContent: skipToContent,
|
|
674
|
-
submit: submit
|
|
674
|
+
submit: submit,
|
|
675
|
+
"HomePage.widget.deploy-now.title": "准备上线了吗?",
|
|
676
|
+
"HomePage.widget.deploy-now.description": "部署您的项目。",
|
|
677
|
+
"HomePage.widget.deploy-now.button": "立即部署"
|
|
675
678
|
};
|
|
676
679
|
|
|
677
680
|
exports.Analytics = Analytics;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zh-Hans.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zh-Hans.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -667,7 +667,10 @@ var zhHans = {
|
|
|
667
667
|
"request.error.model.unknown": "此模型不存在",
|
|
668
668
|
selectButtonTitle: selectButtonTitle,
|
|
669
669
|
skipToContent: skipToContent,
|
|
670
|
-
submit: submit
|
|
670
|
+
submit: submit,
|
|
671
|
+
"HomePage.widget.deploy-now.title": "准备上线了吗?",
|
|
672
|
+
"HomePage.widget.deploy-now.description": "部署您的项目。",
|
|
673
|
+
"HomePage.widget.deploy-now.button": "立即部署"
|
|
671
674
|
};
|
|
672
675
|
|
|
673
676
|
export { Analytics, Documentation, Email, Password, Provider, ResetPasswordToken, Role, Username, Users, anErrorOccurred, clearLabel, dark, zhHans as default, light, or, selectButtonTitle, skipToContent, submit };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zh-Hans.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zh-Hans.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -167,7 +167,27 @@ const getToken = ()=>{
|
|
|
167
167
|
// Check if the url has a prepending slash, if not add a slash
|
|
168
168
|
const normalizeUrl = (url)=>hasProtocol(url) ? url : addPrependingSlash(url);
|
|
169
169
|
// Add a response interceptor to return the response
|
|
170
|
-
const responseInterceptor = async (response, validateStatus)=>{
|
|
170
|
+
const responseInterceptor = async (response, validateStatus, responseType = 'json')=>{
|
|
171
|
+
if (responseType !== 'json') {
|
|
172
|
+
if (!response.ok && !validateStatus?.(response.status)) {
|
|
173
|
+
const fetchError = new FetchError('Server Error');
|
|
174
|
+
fetchError.status = response.status;
|
|
175
|
+
throw fetchError;
|
|
176
|
+
}
|
|
177
|
+
let result;
|
|
178
|
+
if (responseType === 'blob') {
|
|
179
|
+
result = await response.blob();
|
|
180
|
+
} else if (responseType === 'text') {
|
|
181
|
+
result = await response.text();
|
|
182
|
+
} else {
|
|
183
|
+
result = await response.arrayBuffer();
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
data: result,
|
|
187
|
+
status: response.status,
|
|
188
|
+
headers: response.headers
|
|
189
|
+
};
|
|
190
|
+
}
|
|
171
191
|
try {
|
|
172
192
|
const result = await response.json();
|
|
173
193
|
/**
|
|
@@ -249,9 +269,15 @@ const getToken = ()=>{
|
|
|
249
269
|
const fetchClient = {
|
|
250
270
|
get: async (url, options)=>{
|
|
251
271
|
const createRequestUrl = makeCreateRequestUrl(options);
|
|
272
|
+
const responseType = options?.responseType ?? 'json';
|
|
252
273
|
const executeRequest = async ()=>{
|
|
274
|
+
const { Authorization } = getDefaultHeaders();
|
|
275
|
+
// For non-JSON response types, omit content negotiation headers that imply JSON
|
|
276
|
+
const defaultHeaders = responseType === 'json' ? getDefaultHeaders() : {
|
|
277
|
+
Authorization
|
|
278
|
+
};
|
|
253
279
|
const headers = new Headers({
|
|
254
|
-
...
|
|
280
|
+
...defaultHeaders,
|
|
255
281
|
...options?.headers
|
|
256
282
|
});
|
|
257
283
|
const response = await fetch(createRequestUrl(url), {
|
|
@@ -259,7 +285,7 @@ const getToken = ()=>{
|
|
|
259
285
|
method: 'GET',
|
|
260
286
|
headers
|
|
261
287
|
});
|
|
262
|
-
return responseInterceptor(response, options?.validateStatus);
|
|
288
|
+
return responseInterceptor(response, options?.validateStatus, responseType);
|
|
263
289
|
};
|
|
264
290
|
return withTokenRefresh(url, executeRequest);
|
|
265
291
|
},
|
|
@@ -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};\n\ntype FetchOptions = {\n params?: any;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n validateStatus?: ((status: number) => boolean) | null;\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: <TData = any>(url: string, config?: FetchOptions) => Promise<FetchResponse<TData>>;\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 ): Promise<FetchResponse<TData>> => {\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 return `${url}?${serializedParams}`;\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\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: 'GET',\n headers,\n });\n\n return responseInterceptor<TData>(response, options?.validateStatus);\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","fetchError","SyntaxError","withTokenRefresh","executeRequest","paramsSerializer","params","serializedParams","qs","encode","addBaseUrl","makeCreateRequestUrl","options","pipe","fetchClient","get","createRequestUrl","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 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 return `${url}?${serializedParams}`;\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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"}
|
|
@@ -165,7 +165,27 @@ const getToken = ()=>{
|
|
|
165
165
|
// Check if the url has a prepending slash, if not add a slash
|
|
166
166
|
const normalizeUrl = (url)=>hasProtocol(url) ? url : addPrependingSlash(url);
|
|
167
167
|
// Add a response interceptor to return the response
|
|
168
|
-
const responseInterceptor = async (response, validateStatus)=>{
|
|
168
|
+
const responseInterceptor = async (response, validateStatus, responseType = 'json')=>{
|
|
169
|
+
if (responseType !== 'json') {
|
|
170
|
+
if (!response.ok && !validateStatus?.(response.status)) {
|
|
171
|
+
const fetchError = new FetchError('Server Error');
|
|
172
|
+
fetchError.status = response.status;
|
|
173
|
+
throw fetchError;
|
|
174
|
+
}
|
|
175
|
+
let result;
|
|
176
|
+
if (responseType === 'blob') {
|
|
177
|
+
result = await response.blob();
|
|
178
|
+
} else if (responseType === 'text') {
|
|
179
|
+
result = await response.text();
|
|
180
|
+
} else {
|
|
181
|
+
result = await response.arrayBuffer();
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
data: result,
|
|
185
|
+
status: response.status,
|
|
186
|
+
headers: response.headers
|
|
187
|
+
};
|
|
188
|
+
}
|
|
169
189
|
try {
|
|
170
190
|
const result = await response.json();
|
|
171
191
|
/**
|
|
@@ -247,9 +267,15 @@ const getToken = ()=>{
|
|
|
247
267
|
const fetchClient = {
|
|
248
268
|
get: async (url, options)=>{
|
|
249
269
|
const createRequestUrl = makeCreateRequestUrl(options);
|
|
270
|
+
const responseType = options?.responseType ?? 'json';
|
|
250
271
|
const executeRequest = async ()=>{
|
|
272
|
+
const { Authorization } = getDefaultHeaders();
|
|
273
|
+
// For non-JSON response types, omit content negotiation headers that imply JSON
|
|
274
|
+
const defaultHeaders = responseType === 'json' ? getDefaultHeaders() : {
|
|
275
|
+
Authorization
|
|
276
|
+
};
|
|
251
277
|
const headers = new Headers({
|
|
252
|
-
...
|
|
278
|
+
...defaultHeaders,
|
|
253
279
|
...options?.headers
|
|
254
280
|
});
|
|
255
281
|
const response = await fetch(createRequestUrl(url), {
|
|
@@ -257,7 +283,7 @@ const getToken = ()=>{
|
|
|
257
283
|
method: 'GET',
|
|
258
284
|
headers
|
|
259
285
|
});
|
|
260
|
-
return responseInterceptor(response, options?.validateStatus);
|
|
286
|
+
return responseInterceptor(response, options?.validateStatus, responseType);
|
|
261
287
|
};
|
|
262
288
|
return withTokenRefresh(url, executeRequest);
|
|
263
289
|
},
|