@strapi/content-type-builder 5.25.0 → 5.26.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/components/AIChat/Chat.js +431 -0
- package/dist/admin/components/AIChat/Chat.js.map +1 -0
- package/dist/admin/components/AIChat/Chat.mjs +429 -0
- package/dist/admin/components/AIChat/Chat.mjs.map +1 -0
- package/dist/admin/components/AIChat/FeedbackModal.js +237 -0
- package/dist/admin/components/AIChat/FeedbackModal.js.map +1 -0
- package/dist/admin/components/AIChat/FeedbackModal.mjs +233 -0
- package/dist/admin/components/AIChat/FeedbackModal.mjs.map +1 -0
- package/dist/admin/components/AIChat/UploadCodeModal.js +427 -0
- package/dist/admin/components/AIChat/UploadCodeModal.js.map +1 -0
- package/dist/admin/components/AIChat/UploadCodeModal.mjs +423 -0
- package/dist/admin/components/AIChat/UploadCodeModal.mjs.map +1 -0
- package/dist/admin/components/AIChat/UploadFigmaModal.js +377 -0
- package/dist/admin/components/AIChat/UploadFigmaModal.js.map +1 -0
- package/dist/admin/components/AIChat/UploadFigmaModal.mjs +373 -0
- package/dist/admin/components/AIChat/UploadFigmaModal.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/Alert.js +46 -0
- package/dist/admin/components/AIChat/components/Alert.js.map +1 -0
- package/dist/admin/components/AIChat/components/Alert.mjs +44 -0
- package/dist/admin/components/AIChat/components/Alert.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/AnimatedBox.js +34 -0
- package/dist/admin/components/AIChat/components/AnimatedBox.js.map +1 -0
- package/dist/admin/components/AIChat/components/AnimatedBox.mjs +32 -0
- package/dist/admin/components/AIChat/components/AnimatedBox.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/Attachments/AttachmentPreview.js +92 -0
- package/dist/admin/components/AIChat/components/Attachments/AttachmentPreview.js.map +1 -0
- package/dist/admin/components/AIChat/components/Attachments/AttachmentPreview.mjs +90 -0
- package/dist/admin/components/AIChat/components/Attachments/AttachmentPreview.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/Attachments/components/Attachment.js +100 -0
- package/dist/admin/components/AIChat/components/Attachments/components/Attachment.js.map +1 -0
- package/dist/admin/components/AIChat/components/Attachments/components/Attachment.mjs +97 -0
- package/dist/admin/components/AIChat/components/Attachments/components/Attachment.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/Base64Image.js +127 -0
- package/dist/admin/components/AIChat/components/Base64Image.js.map +1 -0
- package/dist/admin/components/AIChat/components/Base64Image.mjs +125 -0
- package/dist/admin/components/AIChat/components/Base64Image.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/Collapsible.js +71 -0
- package/dist/admin/components/AIChat/components/Collapsible.js.map +1 -0
- package/dist/admin/components/AIChat/components/Collapsible.mjs +66 -0
- package/dist/admin/components/AIChat/components/Collapsible.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/Dropzone.js +172 -0
- package/dist/admin/components/AIChat/components/Dropzone.js.map +1 -0
- package/dist/admin/components/AIChat/components/Dropzone.mjs +167 -0
- package/dist/admin/components/AIChat/components/Dropzone.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/FloatingPanel.js +166 -0
- package/dist/admin/components/AIChat/components/FloatingPanel.js.map +1 -0
- package/dist/admin/components/AIChat/components/FloatingPanel.mjs +163 -0
- package/dist/admin/components/AIChat/components/FloatingPanel.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/FullScreenImage.js +190 -0
- package/dist/admin/components/AIChat/components/FullScreenImage.js.map +1 -0
- package/dist/admin/components/AIChat/components/FullScreenImage.mjs +187 -0
- package/dist/admin/components/AIChat/components/FullScreenImage.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/ImagePreview.js +87 -0
- package/dist/admin/components/AIChat/components/ImagePreview.js.map +1 -0
- package/dist/admin/components/AIChat/components/ImagePreview.mjs +85 -0
- package/dist/admin/components/AIChat/components/ImagePreview.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/Input.js +126 -0
- package/dist/admin/components/AIChat/components/Input.js.map +1 -0
- package/dist/admin/components/AIChat/components/Input.mjs +121 -0
- package/dist/admin/components/AIChat/components/Input.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/Messages/Marker.js +138 -0
- package/dist/admin/components/AIChat/components/Messages/Marker.js.map +1 -0
- package/dist/admin/components/AIChat/components/Messages/Marker.mjs +136 -0
- package/dist/admin/components/AIChat/components/Messages/Marker.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/Messages/Message.js +214 -0
- package/dist/admin/components/AIChat/components/Messages/Message.js.map +1 -0
- package/dist/admin/components/AIChat/components/Messages/Message.mjs +212 -0
- package/dist/admin/components/AIChat/components/Messages/Message.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/ResizableTextArea.js +78 -0
- package/dist/admin/components/AIChat/components/ResizableTextArea.js.map +1 -0
- package/dist/admin/components/AIChat/components/ResizableTextArea.mjs +76 -0
- package/dist/admin/components/AIChat/components/ResizableTextArea.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/SimpleMenu.js +60 -0
- package/dist/admin/components/AIChat/components/SimpleMenu.js.map +1 -0
- package/dist/admin/components/AIChat/components/SimpleMenu.mjs +35 -0
- package/dist/admin/components/AIChat/components/SimpleMenu.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/StepModal.js +175 -0
- package/dist/admin/components/AIChat/components/StepModal.js.map +1 -0
- package/dist/admin/components/AIChat/components/StepModal.mjs +171 -0
- package/dist/admin/components/AIChat/components/StepModal.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/animations.js +67 -0
- package/dist/admin/components/AIChat/components/animations.js.map +1 -0
- package/dist/admin/components/AIChat/components/animations.mjs +65 -0
- package/dist/admin/components/AIChat/components/animations.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/icons/FigmaIcon.js +50 -0
- package/dist/admin/components/AIChat/components/icons/FigmaIcon.js.map +1 -0
- package/dist/admin/components/AIChat/components/icons/FigmaIcon.mjs +48 -0
- package/dist/admin/components/AIChat/components/icons/FigmaIcon.mjs.map +1 -0
- package/dist/admin/components/AIChat/components/icons/StopIcon.js +25 -0
- package/dist/admin/components/AIChat/components/icons/StopIcon.js.map +1 -0
- package/dist/admin/components/AIChat/components/icons/StopIcon.mjs +23 -0
- package/dist/admin/components/AIChat/components/icons/StopIcon.mjs.map +1 -0
- package/dist/admin/components/AIChat/hooks/useAIFetch.js +107 -0
- package/dist/admin/components/AIChat/hooks/useAIFetch.js.map +1 -0
- package/dist/admin/components/AIChat/hooks/useAIFetch.mjs +96 -0
- package/dist/admin/components/AIChat/hooks/useAIFetch.mjs.map +1 -0
- package/dist/admin/components/AIChat/hooks/useAttachments.js +152 -0
- package/dist/admin/components/AIChat/hooks/useAttachments.js.map +1 -0
- package/dist/admin/components/AIChat/hooks/useAttachments.mjs +150 -0
- package/dist/admin/components/AIChat/hooks/useAttachments.mjs.map +1 -0
- package/dist/admin/components/AIChat/hooks/useChatTitle.js +47 -0
- package/dist/admin/components/AIChat/hooks/useChatTitle.js.map +1 -0
- package/dist/admin/components/AIChat/hooks/useChatTitle.mjs +45 -0
- package/dist/admin/components/AIChat/hooks/useChatTitle.mjs.map +1 -0
- package/dist/admin/components/AIChat/hooks/useCodeUpload.js +212 -0
- package/dist/admin/components/AIChat/hooks/useCodeUpload.js.map +1 -0
- package/dist/admin/components/AIChat/hooks/useCodeUpload.mjs +207 -0
- package/dist/admin/components/AIChat/hooks/useCodeUpload.mjs.map +1 -0
- package/dist/admin/components/AIChat/hooks/useFeedback.js +76 -0
- package/dist/admin/components/AIChat/hooks/useFeedback.js.map +1 -0
- package/dist/admin/components/AIChat/hooks/useFeedback.mjs +74 -0
- package/dist/admin/components/AIChat/hooks/useFeedback.mjs.map +1 -0
- package/dist/admin/components/AIChat/hooks/useFigmaUpload.js +206 -0
- package/dist/admin/components/AIChat/hooks/useFigmaUpload.js.map +1 -0
- package/dist/admin/components/AIChat/hooks/useFigmaUpload.mjs +200 -0
- package/dist/admin/components/AIChat/hooks/useFigmaUpload.mjs.map +1 -0
- package/dist/admin/components/AIChat/hooks/useLastSeenSchemas.js +115 -0
- package/dist/admin/components/AIChat/hooks/useLastSeenSchemas.js.map +1 -0
- package/dist/admin/components/AIChat/hooks/useLastSeenSchemas.mjs +113 -0
- package/dist/admin/components/AIChat/hooks/useLastSeenSchemas.mjs.map +1 -0
- package/dist/admin/components/AIChat/hooks/useTranslations.js +19 -0
- package/dist/admin/components/AIChat/hooks/useTranslations.js.map +1 -0
- package/dist/admin/components/AIChat/hooks/useTranslations.mjs +17 -0
- package/dist/admin/components/AIChat/hooks/useTranslations.mjs.map +1 -0
- package/dist/admin/components/AIChat/lib/aiClient.js +168 -0
- package/dist/admin/components/AIChat/lib/aiClient.js.map +1 -0
- package/dist/admin/components/AIChat/lib/aiClient.mjs +161 -0
- package/dist/admin/components/AIChat/lib/aiClient.mjs.map +1 -0
- package/dist/admin/components/AIChat/lib/constants.js +16 -0
- package/dist/admin/components/AIChat/lib/constants.js.map +1 -0
- package/dist/admin/components/AIChat/lib/constants.mjs +10 -0
- package/dist/admin/components/AIChat/lib/constants.mjs.map +1 -0
- package/dist/admin/components/AIChat/lib/misc.js +8 -0
- package/dist/admin/components/AIChat/lib/misc.js.map +1 -0
- package/dist/admin/components/AIChat/lib/misc.mjs +6 -0
- package/dist/admin/components/AIChat/lib/misc.mjs.map +1 -0
- package/dist/admin/components/AIChat/lib/transforms/schemas/fromCTB.js +46 -0
- package/dist/admin/components/AIChat/lib/transforms/schemas/fromCTB.js.map +1 -0
- package/dist/admin/components/AIChat/lib/transforms/schemas/fromCTB.mjs +44 -0
- package/dist/admin/components/AIChat/lib/transforms/schemas/fromCTB.mjs.map +1 -0
- package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.js +151 -0
- package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.js.map +1 -0
- package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.mjs +148 -0
- package/dist/admin/components/AIChat/lib/transforms/schemas/toCTB.mjs.map +1 -0
- package/dist/admin/components/AIChat/providers/ChatProvider.js +191 -0
- package/dist/admin/components/AIChat/providers/ChatProvider.js.map +1 -0
- package/dist/admin/components/AIChat/providers/ChatProvider.mjs +187 -0
- package/dist/admin/components/AIChat/providers/ChatProvider.mjs.map +1 -0
- package/dist/admin/components/AIChat/providers/SchemaProvider.js +90 -0
- package/dist/admin/components/AIChat/providers/SchemaProvider.js.map +1 -0
- package/dist/admin/components/AIChat/providers/SchemaProvider.mjs +88 -0
- package/dist/admin/components/AIChat/providers/SchemaProvider.mjs.map +1 -0
- package/dist/admin/components/ComponentList.js +1 -0
- package/dist/admin/components/ComponentList.js.map +1 -1
- package/dist/admin/components/ComponentList.mjs +1 -0
- package/dist/admin/components/ComponentList.mjs.map +1 -1
- package/dist/admin/components/DataManager/DataManagerContext.js.map +1 -1
- package/dist/admin/components/DataManager/DataManagerContext.mjs.map +1 -1
- package/dist/admin/components/DataManager/reducer.js +48 -6
- package/dist/admin/components/DataManager/reducer.js.map +1 -1
- package/dist/admin/components/DataManager/reducer.mjs +48 -6
- package/dist/admin/components/DataManager/reducer.mjs.map +1 -1
- package/dist/admin/components/FormModal/utils/canEditContentType.js.map +1 -1
- package/dist/admin/components/FormModal/utils/canEditContentType.mjs.map +1 -1
- package/dist/admin/pages/App/index.js +60 -29
- package/dist/admin/pages/App/index.js.map +1 -1
- package/dist/admin/pages/App/index.mjs +62 -31
- package/dist/admin/pages/App/index.mjs.map +1 -1
- package/dist/admin/pages/ListView/EmptyState.js +75 -9
- package/dist/admin/pages/ListView/EmptyState.js.map +1 -1
- package/dist/admin/pages/ListView/EmptyState.mjs +77 -11
- package/dist/admin/pages/ListView/EmptyState.mjs.map +1 -1
- package/dist/admin/src/components/AIChat/Chat.d.ts +2 -0
- package/dist/admin/src/components/AIChat/FeedbackModal.d.ts +13 -0
- package/dist/admin/src/components/AIChat/UploadCodeModal.d.ts +12 -0
- package/dist/admin/src/components/AIChat/UploadFigmaModal.d.ts +12 -0
- package/dist/admin/src/components/AIChat/components/Alert.d.ts +6 -0
- package/dist/admin/src/components/AIChat/components/AnimatedBox.d.ts +13 -0
- package/dist/admin/src/components/AIChat/components/Attachments/AttachmentPreview.d.ts +9 -0
- package/dist/admin/src/components/AIChat/components/Attachments/components/Attachment.d.ts +27 -0
- package/dist/admin/src/components/AIChat/components/Base64Image.d.ts +9 -0
- package/dist/admin/src/components/AIChat/components/Collapsible.d.ts +18 -0
- package/dist/admin/src/components/AIChat/components/Dropzone.d.ts +35 -0
- package/dist/admin/src/components/AIChat/components/FloatingPanel.d.ts +34 -0
- package/dist/admin/src/components/AIChat/components/FullScreenImage.d.ts +20 -0
- package/dist/admin/src/components/AIChat/components/ImagePreview.d.ts +8 -0
- package/dist/admin/src/components/AIChat/components/ImagePreviewGroup.d.ts +7 -0
- package/dist/admin/src/components/AIChat/components/Input.d.ts +43 -0
- package/dist/admin/src/components/AIChat/components/Messages/Marker.d.ts +2 -0
- package/dist/admin/src/components/AIChat/components/Messages/Message.d.ts +5 -0
- package/dist/admin/src/components/AIChat/components/ResizableTextArea.d.ts +9 -0
- package/dist/admin/src/components/AIChat/components/SimpleMenu.d.ts +32 -0
- package/dist/admin/src/components/AIChat/components/StepModal.d.ts +37 -0
- package/dist/admin/src/components/AIChat/components/animations.d.ts +8 -0
- package/dist/admin/src/components/AIChat/components/icons/FigmaIcon.d.ts +5 -0
- package/dist/admin/src/components/AIChat/components/icons/StopIcon.d.ts +5 -0
- package/dist/admin/src/components/AIChat/hooks/useAIFetch.d.ts +147 -0
- package/dist/admin/src/components/AIChat/hooks/useAttachments.d.ts +8 -0
- package/dist/admin/src/components/AIChat/hooks/useChatTitle.d.ts +13 -0
- package/dist/admin/src/components/AIChat/hooks/useCodeUpload.d.ts +31 -0
- package/dist/admin/src/components/AIChat/hooks/useFeedback.d.ts +7 -0
- package/dist/admin/src/components/AIChat/hooks/useFigmaUpload.d.ts +61 -0
- package/dist/admin/src/components/AIChat/hooks/useLastSeenSchemas.d.ts +10 -0
- package/dist/admin/src/components/AIChat/hooks/useTranslations.d.ts +3 -0
- package/dist/admin/src/components/AIChat/lib/aiClient.d.ts +32 -0
- package/dist/admin/src/components/AIChat/lib/constants.d.ts +12 -0
- package/dist/admin/src/components/AIChat/lib/fileToAttachment.d.ts +2 -0
- package/dist/admin/src/components/AIChat/lib/misc.d.ts +1 -0
- package/dist/admin/src/components/AIChat/lib/transforms/schemas/fromCTB.d.ts +3 -0
- package/dist/admin/src/components/AIChat/lib/transforms/schemas/toCTB.d.ts +16 -0
- package/dist/admin/src/components/AIChat/lib/types/annotations.d.ts +19 -0
- package/dist/admin/src/components/AIChat/lib/types/attachments.d.ts +15 -0
- package/dist/admin/src/components/AIChat/lib/types/feedback.d.ts +1 -0
- package/dist/admin/src/components/AIChat/lib/types/messages.d.ts +26 -0
- package/dist/admin/src/components/AIChat/lib/types/schema.d.ts +20 -0
- package/dist/admin/src/components/AIChat/providers/ChatProvider.d.ts +30 -0
- package/dist/admin/src/components/AIChat/providers/SchemaProvider.d.ts +10 -0
- package/dist/admin/src/components/ComponentList.d.ts +1 -1
- package/dist/admin/src/components/DataManager/DataManagerContext.d.ts +1 -1
- package/dist/admin/translations/ar.json.js +187 -2
- package/dist/admin/translations/ar.json.js.map +1 -1
- package/dist/admin/translations/ar.json.mjs +187 -3
- package/dist/admin/translations/ar.json.mjs.map +1 -1
- package/dist/admin/translations/de.json.js +42 -7
- package/dist/admin/translations/de.json.js.map +1 -1
- package/dist/admin/translations/de.json.mjs +42 -7
- package/dist/admin/translations/de.json.mjs.map +1 -1
- package/dist/admin/translations/en.json.js +53 -2
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +53 -2
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/admin/translations/es.json.js +37 -15
- package/dist/admin/translations/es.json.js.map +1 -1
- package/dist/admin/translations/es.json.mjs +37 -15
- package/dist/admin/translations/es.json.mjs.map +1 -1
- package/dist/admin/translations/fr.json.js +165 -3
- package/dist/admin/translations/fr.json.js.map +1 -1
- package/dist/admin/translations/fr.json.mjs +165 -4
- package/dist/admin/translations/fr.json.mjs.map +1 -1
- package/dist/admin/translations/id.json.js +93 -23
- package/dist/admin/translations/id.json.js.map +1 -1
- package/dist/admin/translations/id.json.mjs +93 -23
- package/dist/admin/translations/id.json.mjs.map +1 -1
- package/dist/admin/translations/it.json.js +75 -6
- package/dist/admin/translations/it.json.js.map +1 -1
- package/dist/admin/translations/it.json.mjs +75 -6
- package/dist/admin/translations/it.json.mjs.map +1 -1
- package/dist/admin/translations/ja.json.js +191 -5
- package/dist/admin/translations/ja.json.js.map +1 -1
- package/dist/admin/translations/ja.json.mjs +191 -6
- package/dist/admin/translations/ja.json.mjs.map +1 -1
- package/dist/admin/translations/ko.json.js +70 -16
- package/dist/admin/translations/ko.json.js.map +1 -1
- package/dist/admin/translations/ko.json.mjs +70 -16
- package/dist/admin/translations/ko.json.mjs.map +1 -1
- package/dist/admin/translations/ms.json.js +104 -31
- package/dist/admin/translations/ms.json.js.map +1 -1
- package/dist/admin/translations/ms.json.mjs +104 -31
- package/dist/admin/translations/ms.json.mjs.map +1 -1
- package/dist/admin/translations/nl.json.js +95 -15
- package/dist/admin/translations/nl.json.js.map +1 -1
- package/dist/admin/translations/nl.json.mjs +95 -15
- package/dist/admin/translations/nl.json.mjs.map +1 -1
- package/dist/admin/translations/pl.json.js +55 -11
- package/dist/admin/translations/pl.json.js.map +1 -1
- package/dist/admin/translations/pl.json.mjs +55 -11
- package/dist/admin/translations/pl.json.mjs.map +1 -1
- package/dist/admin/translations/pt-BR.json.js +54 -10
- package/dist/admin/translations/pt-BR.json.js.map +1 -1
- package/dist/admin/translations/pt-BR.json.mjs +54 -10
- package/dist/admin/translations/pt-BR.json.mjs.map +1 -1
- package/dist/admin/translations/pt.json.js +187 -2
- package/dist/admin/translations/pt.json.js.map +1 -1
- package/dist/admin/translations/pt.json.mjs +187 -3
- package/dist/admin/translations/pt.json.mjs.map +1 -1
- package/dist/admin/translations/ru.json.js +26 -1
- package/dist/admin/translations/ru.json.js.map +1 -1
- package/dist/admin/translations/ru.json.mjs +26 -1
- package/dist/admin/translations/ru.json.mjs.map +1 -1
- package/dist/admin/translations/sk.json.js +21 -1
- package/dist/admin/translations/sk.json.js.map +1 -1
- package/dist/admin/translations/sk.json.mjs +21 -1
- package/dist/admin/translations/sk.json.mjs.map +1 -1
- package/dist/admin/translations/sv.json.js +21 -1
- package/dist/admin/translations/sv.json.js.map +1 -1
- package/dist/admin/translations/sv.json.mjs +21 -1
- package/dist/admin/translations/sv.json.mjs.map +1 -1
- package/dist/admin/translations/th.json.js +21 -1
- package/dist/admin/translations/th.json.js.map +1 -1
- package/dist/admin/translations/th.json.mjs +21 -1
- package/dist/admin/translations/th.json.mjs.map +1 -1
- package/dist/admin/translations/tr.json.js +21 -1
- package/dist/admin/translations/tr.json.js.map +1 -1
- package/dist/admin/translations/tr.json.mjs +21 -1
- package/dist/admin/translations/tr.json.mjs.map +1 -1
- package/dist/admin/translations/uk.json.js +21 -2
- package/dist/admin/translations/uk.json.js.map +1 -1
- package/dist/admin/translations/uk.json.mjs +21 -2
- package/dist/admin/translations/uk.json.mjs.map +1 -1
- package/dist/admin/translations/zh-Hans.json.js +222 -133
- package/dist/admin/translations/zh-Hans.json.js.map +1 -1
- package/dist/admin/translations/zh-Hans.json.mjs +222 -133
- package/dist/admin/translations/zh-Hans.json.mjs.map +1 -1
- package/dist/admin/translations/zh.json.js +21 -1
- package/dist/admin/translations/zh.json.js.map +1 -1
- package/dist/admin/translations/zh.json.mjs +21 -1
- package/dist/admin/translations/zh.json.mjs.map +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +2 -0
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/register.js +98 -0
- package/dist/server/register.js.map +1 -0
- package/dist/server/register.mjs +96 -0
- package/dist/server/register.mjs.map +1 -0
- package/dist/server/src/controllers/ai/auth.d.ts +1 -0
- package/dist/server/src/controllers/ai/auth.d.ts.map +1 -0
- package/dist/server/src/controllers/ai/index.d.ts +1 -0
- package/dist/server/src/controllers/ai/index.d.ts.map +1 -0
- package/dist/server/src/index.d.ts +1 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts +11 -0
- package/dist/server/src/register.d.ts.map +1 -0
- package/package.json +12 -5
- package/dist/admin/components/DataManager/utils/formatSchemas.js +0 -21
- package/dist/admin/components/DataManager/utils/formatSchemas.js.map +0 -1
- package/dist/admin/components/DataManager/utils/formatSchemas.mjs +0 -18
- package/dist/admin/components/DataManager/utils/formatSchemas.mjs.map +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var strapiAdmin = require('@strapi/admin/strapi-admin');
|
|
4
|
+
|
|
5
|
+
let aiTokenCache = null;
|
|
6
|
+
const SESSION_STORAGE_KEY = 'strapi-ai-token';
|
|
7
|
+
const EXPIRY_BUFFER_MS = 60 * 1000;
|
|
8
|
+
const parseExpiryMs = (expiresAt)=>{
|
|
9
|
+
const ms = Date.parse(expiresAt);
|
|
10
|
+
return Number.isFinite(ms) ? ms : null;
|
|
11
|
+
};
|
|
12
|
+
const getTokenState = (expiresAt, bufferMs = EXPIRY_BUFFER_MS, now = Date.now())=>{
|
|
13
|
+
const expMs = parseExpiryMs(expiresAt);
|
|
14
|
+
if (expMs === null) {
|
|
15
|
+
return 'expired';
|
|
16
|
+
}
|
|
17
|
+
if (expMs <= now) {
|
|
18
|
+
return 'expired';
|
|
19
|
+
}
|
|
20
|
+
if (expMs - bufferMs <= now) {
|
|
21
|
+
return 'stale';
|
|
22
|
+
}
|
|
23
|
+
return 'valid';
|
|
24
|
+
};
|
|
25
|
+
const isTokenUsable = (expiresAt, bufferMs = EXPIRY_BUFFER_MS, now = Date.now())=>getTokenState(expiresAt, bufferMs, now) === 'valid';
|
|
26
|
+
const clearAIJwt = ()=>{
|
|
27
|
+
aiTokenCache = null;
|
|
28
|
+
sessionStorage.removeItem(SESSION_STORAGE_KEY);
|
|
29
|
+
};
|
|
30
|
+
const readFromSession = ()=>{
|
|
31
|
+
try {
|
|
32
|
+
const raw = sessionStorage.getItem(SESSION_STORAGE_KEY);
|
|
33
|
+
if (!raw) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const parsed = JSON.parse(raw);
|
|
37
|
+
return parsed;
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const writeToSession = (data)=>{
|
|
43
|
+
sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(data));
|
|
44
|
+
};
|
|
45
|
+
const getAIJwt = async ()=>{
|
|
46
|
+
// Check memory cache
|
|
47
|
+
if (aiTokenCache && isTokenUsable(aiTokenCache.expiresAt)) {
|
|
48
|
+
return aiTokenCache;
|
|
49
|
+
}
|
|
50
|
+
// Check session storage
|
|
51
|
+
const fromSession = readFromSession();
|
|
52
|
+
if (fromSession && isTokenUsable(fromSession.expiresAt)) {
|
|
53
|
+
aiTokenCache = fromSession;
|
|
54
|
+
return aiTokenCache;
|
|
55
|
+
}
|
|
56
|
+
// Fetch from admin endpoint
|
|
57
|
+
try {
|
|
58
|
+
const { get } = strapiAdmin.getFetchClient();
|
|
59
|
+
const { data } = await get('/admin/ai-token');
|
|
60
|
+
const token = data?.token || data?.data?.token;
|
|
61
|
+
const expiresAt = data?.expiresAt || data?.data?.expiresAt;
|
|
62
|
+
if (token && expiresAt) {
|
|
63
|
+
aiTokenCache = {
|
|
64
|
+
token,
|
|
65
|
+
expiresAt
|
|
66
|
+
};
|
|
67
|
+
writeToSession(aiTokenCache);
|
|
68
|
+
return aiTokenCache;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
} catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const prefetchAIToken = async ()=>{
|
|
76
|
+
try {
|
|
77
|
+
// If we already have a valid token (not expiring soon), do nothing
|
|
78
|
+
const existing = await getAIJwt();
|
|
79
|
+
if (existing) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Attempt a fetch to populate cache
|
|
83
|
+
await getAIJwt();
|
|
84
|
+
} catch {
|
|
85
|
+
// no-op
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const safeParseJson = async (response)=>{
|
|
89
|
+
try {
|
|
90
|
+
return await response.json();
|
|
91
|
+
} catch {
|
|
92
|
+
try {
|
|
93
|
+
const text = await response.text();
|
|
94
|
+
return {
|
|
95
|
+
error: text
|
|
96
|
+
};
|
|
97
|
+
} catch {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const buildHeaders = (token, ctx, extra)=>{
|
|
103
|
+
return {
|
|
104
|
+
Authorization: `Bearer ${token}`,
|
|
105
|
+
'X-Strapi-Version': ctx?.strapiVersion || 'latest',
|
|
106
|
+
'X-Strapi-User': ctx?.userId || 'unknown',
|
|
107
|
+
'X-Strapi-Project-Id': ctx?.projectId || 'unknown',
|
|
108
|
+
...extra
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
const shouldRetryForToken = (status, body)=>{
|
|
112
|
+
if (status === 401 || status === 403) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
const msg = (body?.error || '').toString().toLowerCase();
|
|
116
|
+
return msg.includes('expired') || msg.includes('invalid token');
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Generic fetch wrapper for AI endpoints with token injection and single retry on invalidation
|
|
120
|
+
*/ const fetchAI = async (input, options = {})=>{
|
|
121
|
+
// Get token
|
|
122
|
+
const tokenData = await getAIJwt();
|
|
123
|
+
if (!tokenData?.token) {
|
|
124
|
+
const error = new Error('Could not authorize with AI Server. Please contact your administrator.');
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
const make = async (token)=>{
|
|
128
|
+
const headers = buildHeaders(token, options.ctx, options.headers);
|
|
129
|
+
return fetch(input, {
|
|
130
|
+
...options,
|
|
131
|
+
headers
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
let response = await make(tokenData.token);
|
|
135
|
+
let body = undefined;
|
|
136
|
+
try {
|
|
137
|
+
body = await safeParseJson(response.clone());
|
|
138
|
+
} catch {
|
|
139
|
+
// no-op
|
|
140
|
+
}
|
|
141
|
+
if (shouldRetryForToken(response.status, body)) {
|
|
142
|
+
clearAIJwt();
|
|
143
|
+
const refreshed = await getAIJwt();
|
|
144
|
+
if (refreshed?.token && refreshed.token !== tokenData.token) {
|
|
145
|
+
response = await make(refreshed.token);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return response;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Factory to provide a fetch implementation compatible with AI SDK useChat
|
|
152
|
+
* that injects AI JWT + Strapi context headers and retries on token invalidation once.
|
|
153
|
+
*/ const makeChatFetch = (ctx)=>{
|
|
154
|
+
return async (input, options = {})=>{
|
|
155
|
+
return fetchAI(input, {
|
|
156
|
+
...options,
|
|
157
|
+
ctx
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
exports.clearAIJwt = clearAIJwt;
|
|
163
|
+
exports.fetchAI = fetchAI;
|
|
164
|
+
exports.getAIJwt = getAIJwt;
|
|
165
|
+
exports.makeChatFetch = makeChatFetch;
|
|
166
|
+
exports.prefetchAIToken = prefetchAIToken;
|
|
167
|
+
exports.safeParseJson = safeParseJson;
|
|
168
|
+
//# sourceMappingURL=aiClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aiClient.js","sources":["../../../../../admin/src/components/AIChat/lib/aiClient.ts"],"sourcesContent":["import { getFetchClient } from '@strapi/admin/strapi-admin';\n\n/**\n * Centralized AI client utilities:\n * - Token retrieval via admin endpoint using getFetchClient\n * - In-memory + sessionStorage caching with near-expiry buffer\n * - Safe JSON parsing for error handling\n * - Single-retry policy on token invalidation\n */\n\nexport interface AITokenData {\n token: string;\n expiresAt: string;\n}\n\nlet aiTokenCache: AITokenData | null = null;\nconst SESSION_STORAGE_KEY = 'strapi-ai-token';\nconst EXPIRY_BUFFER_MS = 60 * 1000;\n\nconst parseExpiryMs = (expiresAt: string): number | null => {\n const ms = Date.parse(expiresAt);\n return Number.isFinite(ms) ? ms : null;\n};\n\ntype TokenState = 'valid' | 'stale' | 'expired';\n\nconst getTokenState = (\n expiresAt: string,\n bufferMs = EXPIRY_BUFFER_MS,\n now = Date.now()\n): TokenState => {\n const expMs = parseExpiryMs(expiresAt);\n if (expMs === null) {\n return 'expired';\n }\n if (expMs <= now) {\n return 'expired';\n }\n if (expMs - bufferMs <= now) {\n return 'stale';\n }\n\n return 'valid';\n};\n\nconst isTokenUsable = (expiresAt: string, bufferMs = EXPIRY_BUFFER_MS, now = Date.now()): boolean =>\n getTokenState(expiresAt, bufferMs, now) === 'valid';\n\nexport const clearAIJwt = () => {\n aiTokenCache = null;\n sessionStorage.removeItem(SESSION_STORAGE_KEY);\n};\n\nconst readFromSession = (): AITokenData | null => {\n try {\n const raw = sessionStorage.getItem(SESSION_STORAGE_KEY);\n if (!raw) {\n return null;\n }\n\n const parsed = JSON.parse(raw) as AITokenData;\n return parsed;\n } catch {\n return null;\n }\n};\n\nconst writeToSession = (data: AITokenData) => {\n sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(data));\n};\n\nexport const getAIJwt = async (): Promise<AITokenData | null> => {\n // Check memory cache\n if (aiTokenCache && isTokenUsable(aiTokenCache.expiresAt)) {\n return aiTokenCache;\n }\n\n // Check session storage\n const fromSession = readFromSession();\n if (fromSession && isTokenUsable(fromSession.expiresAt)) {\n aiTokenCache = fromSession;\n\n return aiTokenCache;\n }\n\n // Fetch from admin endpoint\n try {\n const { get } = getFetchClient();\n const { data } = await get('/admin/ai-token');\n\n const token = data?.token || data?.data?.token;\n const expiresAt = data?.expiresAt || data?.data?.expiresAt;\n\n if (token && expiresAt) {\n aiTokenCache = { token, expiresAt };\n writeToSession(aiTokenCache);\n\n return aiTokenCache;\n }\n return null;\n } catch {\n return null;\n }\n};\n\nexport const prefetchAIToken = async (): Promise<void> => {\n try {\n // If we already have a valid token (not expiring soon), do nothing\n const existing = await getAIJwt();\n if (existing) {\n return;\n }\n\n // Attempt a fetch to populate cache\n await getAIJwt();\n } catch {\n // no-op\n }\n};\n\nexport const safeParseJson = async (response: Response): Promise<any> => {\n try {\n return await response.json();\n } catch {\n try {\n const text = await response.text();\n\n return { error: text };\n } catch {\n return undefined;\n }\n }\n};\n\nexport interface StrapiContextHeaders {\n strapiVersion?: string | null;\n projectId?: string | null;\n userId?: string | null;\n}\n\nconst buildHeaders = (\n token: string,\n ctx?: StrapiContextHeaders,\n extra?: HeadersInit\n): Record<string, string> => {\n return {\n Authorization: `Bearer ${token}`,\n 'X-Strapi-Version': ctx?.strapiVersion || 'latest',\n 'X-Strapi-User': ctx?.userId || 'unknown',\n 'X-Strapi-Project-Id': ctx?.projectId || 'unknown',\n ...(extra as Record<string, string>),\n };\n};\n\nconst shouldRetryForToken = (status: number, body: any): boolean => {\n if (status === 401 || status === 403) {\n return true;\n }\n\n const msg = (body?.error || '').toString().toLowerCase();\n return msg.includes('expired') || msg.includes('invalid token');\n};\n\nexport interface FetchAIOptions extends RequestInit {\n ctx?: StrapiContextHeaders;\n}\n\n/**\n * Generic fetch wrapper for AI endpoints with token injection and single retry on invalidation\n */\nexport const fetchAI = async (\n input: RequestInfo | URL,\n options: FetchAIOptions = {}\n): Promise<Response> => {\n // Get token\n const tokenData = await getAIJwt();\n\n if (!tokenData?.token) {\n const error = new Error(\n 'Could not authorize with AI Server. Please contact your administrator.'\n );\n\n throw error;\n }\n\n const make = async (token: string): Promise<Response> => {\n const headers = buildHeaders(token, options.ctx, options.headers);\n return fetch(input, {\n ...options,\n headers,\n });\n };\n\n let response = await make(tokenData.token);\n\n let body: unknown | undefined = undefined;\n try {\n body = await safeParseJson(response.clone());\n } catch {\n // no-op\n }\n\n if (shouldRetryForToken(response.status, body)) {\n clearAIJwt();\n\n const refreshed = await getAIJwt();\n\n if (refreshed?.token && refreshed.token !== tokenData.token) {\n response = await make(refreshed.token);\n }\n }\n\n return response;\n};\n\n/**\n * Factory to provide a fetch implementation compatible with AI SDK useChat\n * that injects AI JWT + Strapi context headers and retries on token invalidation once.\n */\nexport const makeChatFetch = (ctx: StrapiContextHeaders) => {\n return async (input: RequestInfo | URL, options: RequestInit = {}): Promise<Response> => {\n return fetchAI(input, { ...options, ctx });\n };\n};\n"],"names":["aiTokenCache","SESSION_STORAGE_KEY","EXPIRY_BUFFER_MS","parseExpiryMs","expiresAt","ms","Date","parse","Number","isFinite","getTokenState","bufferMs","now","expMs","isTokenUsable","clearAIJwt","sessionStorage","removeItem","readFromSession","raw","getItem","parsed","JSON","writeToSession","data","setItem","stringify","getAIJwt","fromSession","get","getFetchClient","token","prefetchAIToken","existing","safeParseJson","response","json","text","error","undefined","buildHeaders","ctx","extra","Authorization","strapiVersion","userId","projectId","shouldRetryForToken","status","body","msg","toString","toLowerCase","includes","fetchAI","input","options","tokenData","Error","make","headers","fetch","clone","refreshed","makeChatFetch"],"mappings":"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"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { getFetchClient } from '@strapi/admin/strapi-admin';
|
|
2
|
+
|
|
3
|
+
let aiTokenCache = null;
|
|
4
|
+
const SESSION_STORAGE_KEY = 'strapi-ai-token';
|
|
5
|
+
const EXPIRY_BUFFER_MS = 60 * 1000;
|
|
6
|
+
const parseExpiryMs = (expiresAt)=>{
|
|
7
|
+
const ms = Date.parse(expiresAt);
|
|
8
|
+
return Number.isFinite(ms) ? ms : null;
|
|
9
|
+
};
|
|
10
|
+
const getTokenState = (expiresAt, bufferMs = EXPIRY_BUFFER_MS, now = Date.now())=>{
|
|
11
|
+
const expMs = parseExpiryMs(expiresAt);
|
|
12
|
+
if (expMs === null) {
|
|
13
|
+
return 'expired';
|
|
14
|
+
}
|
|
15
|
+
if (expMs <= now) {
|
|
16
|
+
return 'expired';
|
|
17
|
+
}
|
|
18
|
+
if (expMs - bufferMs <= now) {
|
|
19
|
+
return 'stale';
|
|
20
|
+
}
|
|
21
|
+
return 'valid';
|
|
22
|
+
};
|
|
23
|
+
const isTokenUsable = (expiresAt, bufferMs = EXPIRY_BUFFER_MS, now = Date.now())=>getTokenState(expiresAt, bufferMs, now) === 'valid';
|
|
24
|
+
const clearAIJwt = ()=>{
|
|
25
|
+
aiTokenCache = null;
|
|
26
|
+
sessionStorage.removeItem(SESSION_STORAGE_KEY);
|
|
27
|
+
};
|
|
28
|
+
const readFromSession = ()=>{
|
|
29
|
+
try {
|
|
30
|
+
const raw = sessionStorage.getItem(SESSION_STORAGE_KEY);
|
|
31
|
+
if (!raw) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const parsed = JSON.parse(raw);
|
|
35
|
+
return parsed;
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const writeToSession = (data)=>{
|
|
41
|
+
sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(data));
|
|
42
|
+
};
|
|
43
|
+
const getAIJwt = async ()=>{
|
|
44
|
+
// Check memory cache
|
|
45
|
+
if (aiTokenCache && isTokenUsable(aiTokenCache.expiresAt)) {
|
|
46
|
+
return aiTokenCache;
|
|
47
|
+
}
|
|
48
|
+
// Check session storage
|
|
49
|
+
const fromSession = readFromSession();
|
|
50
|
+
if (fromSession && isTokenUsable(fromSession.expiresAt)) {
|
|
51
|
+
aiTokenCache = fromSession;
|
|
52
|
+
return aiTokenCache;
|
|
53
|
+
}
|
|
54
|
+
// Fetch from admin endpoint
|
|
55
|
+
try {
|
|
56
|
+
const { get } = getFetchClient();
|
|
57
|
+
const { data } = await get('/admin/ai-token');
|
|
58
|
+
const token = data?.token || data?.data?.token;
|
|
59
|
+
const expiresAt = data?.expiresAt || data?.data?.expiresAt;
|
|
60
|
+
if (token && expiresAt) {
|
|
61
|
+
aiTokenCache = {
|
|
62
|
+
token,
|
|
63
|
+
expiresAt
|
|
64
|
+
};
|
|
65
|
+
writeToSession(aiTokenCache);
|
|
66
|
+
return aiTokenCache;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const prefetchAIToken = async ()=>{
|
|
74
|
+
try {
|
|
75
|
+
// If we already have a valid token (not expiring soon), do nothing
|
|
76
|
+
const existing = await getAIJwt();
|
|
77
|
+
if (existing) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Attempt a fetch to populate cache
|
|
81
|
+
await getAIJwt();
|
|
82
|
+
} catch {
|
|
83
|
+
// no-op
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const safeParseJson = async (response)=>{
|
|
87
|
+
try {
|
|
88
|
+
return await response.json();
|
|
89
|
+
} catch {
|
|
90
|
+
try {
|
|
91
|
+
const text = await response.text();
|
|
92
|
+
return {
|
|
93
|
+
error: text
|
|
94
|
+
};
|
|
95
|
+
} catch {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const buildHeaders = (token, ctx, extra)=>{
|
|
101
|
+
return {
|
|
102
|
+
Authorization: `Bearer ${token}`,
|
|
103
|
+
'X-Strapi-Version': ctx?.strapiVersion || 'latest',
|
|
104
|
+
'X-Strapi-User': ctx?.userId || 'unknown',
|
|
105
|
+
'X-Strapi-Project-Id': ctx?.projectId || 'unknown',
|
|
106
|
+
...extra
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
const shouldRetryForToken = (status, body)=>{
|
|
110
|
+
if (status === 401 || status === 403) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
const msg = (body?.error || '').toString().toLowerCase();
|
|
114
|
+
return msg.includes('expired') || msg.includes('invalid token');
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Generic fetch wrapper for AI endpoints with token injection and single retry on invalidation
|
|
118
|
+
*/ const fetchAI = async (input, options = {})=>{
|
|
119
|
+
// Get token
|
|
120
|
+
const tokenData = await getAIJwt();
|
|
121
|
+
if (!tokenData?.token) {
|
|
122
|
+
const error = new Error('Could not authorize with AI Server. Please contact your administrator.');
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
const make = async (token)=>{
|
|
126
|
+
const headers = buildHeaders(token, options.ctx, options.headers);
|
|
127
|
+
return fetch(input, {
|
|
128
|
+
...options,
|
|
129
|
+
headers
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
let response = await make(tokenData.token);
|
|
133
|
+
let body = undefined;
|
|
134
|
+
try {
|
|
135
|
+
body = await safeParseJson(response.clone());
|
|
136
|
+
} catch {
|
|
137
|
+
// no-op
|
|
138
|
+
}
|
|
139
|
+
if (shouldRetryForToken(response.status, body)) {
|
|
140
|
+
clearAIJwt();
|
|
141
|
+
const refreshed = await getAIJwt();
|
|
142
|
+
if (refreshed?.token && refreshed.token !== tokenData.token) {
|
|
143
|
+
response = await make(refreshed.token);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return response;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Factory to provide a fetch implementation compatible with AI SDK useChat
|
|
150
|
+
* that injects AI JWT + Strapi context headers and retries on token invalidation once.
|
|
151
|
+
*/ const makeChatFetch = (ctx)=>{
|
|
152
|
+
return async (input, options = {})=>{
|
|
153
|
+
return fetchAI(input, {
|
|
154
|
+
...options,
|
|
155
|
+
ctx
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export { clearAIJwt, fetchAI, getAIJwt, makeChatFetch, prefetchAIToken, safeParseJson };
|
|
161
|
+
//# sourceMappingURL=aiClient.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aiClient.mjs","sources":["../../../../../admin/src/components/AIChat/lib/aiClient.ts"],"sourcesContent":["import { getFetchClient } from '@strapi/admin/strapi-admin';\n\n/**\n * Centralized AI client utilities:\n * - Token retrieval via admin endpoint using getFetchClient\n * - In-memory + sessionStorage caching with near-expiry buffer\n * - Safe JSON parsing for error handling\n * - Single-retry policy on token invalidation\n */\n\nexport interface AITokenData {\n token: string;\n expiresAt: string;\n}\n\nlet aiTokenCache: AITokenData | null = null;\nconst SESSION_STORAGE_KEY = 'strapi-ai-token';\nconst EXPIRY_BUFFER_MS = 60 * 1000;\n\nconst parseExpiryMs = (expiresAt: string): number | null => {\n const ms = Date.parse(expiresAt);\n return Number.isFinite(ms) ? ms : null;\n};\n\ntype TokenState = 'valid' | 'stale' | 'expired';\n\nconst getTokenState = (\n expiresAt: string,\n bufferMs = EXPIRY_BUFFER_MS,\n now = Date.now()\n): TokenState => {\n const expMs = parseExpiryMs(expiresAt);\n if (expMs === null) {\n return 'expired';\n }\n if (expMs <= now) {\n return 'expired';\n }\n if (expMs - bufferMs <= now) {\n return 'stale';\n }\n\n return 'valid';\n};\n\nconst isTokenUsable = (expiresAt: string, bufferMs = EXPIRY_BUFFER_MS, now = Date.now()): boolean =>\n getTokenState(expiresAt, bufferMs, now) === 'valid';\n\nexport const clearAIJwt = () => {\n aiTokenCache = null;\n sessionStorage.removeItem(SESSION_STORAGE_KEY);\n};\n\nconst readFromSession = (): AITokenData | null => {\n try {\n const raw = sessionStorage.getItem(SESSION_STORAGE_KEY);\n if (!raw) {\n return null;\n }\n\n const parsed = JSON.parse(raw) as AITokenData;\n return parsed;\n } catch {\n return null;\n }\n};\n\nconst writeToSession = (data: AITokenData) => {\n sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(data));\n};\n\nexport const getAIJwt = async (): Promise<AITokenData | null> => {\n // Check memory cache\n if (aiTokenCache && isTokenUsable(aiTokenCache.expiresAt)) {\n return aiTokenCache;\n }\n\n // Check session storage\n const fromSession = readFromSession();\n if (fromSession && isTokenUsable(fromSession.expiresAt)) {\n aiTokenCache = fromSession;\n\n return aiTokenCache;\n }\n\n // Fetch from admin endpoint\n try {\n const { get } = getFetchClient();\n const { data } = await get('/admin/ai-token');\n\n const token = data?.token || data?.data?.token;\n const expiresAt = data?.expiresAt || data?.data?.expiresAt;\n\n if (token && expiresAt) {\n aiTokenCache = { token, expiresAt };\n writeToSession(aiTokenCache);\n\n return aiTokenCache;\n }\n return null;\n } catch {\n return null;\n }\n};\n\nexport const prefetchAIToken = async (): Promise<void> => {\n try {\n // If we already have a valid token (not expiring soon), do nothing\n const existing = await getAIJwt();\n if (existing) {\n return;\n }\n\n // Attempt a fetch to populate cache\n await getAIJwt();\n } catch {\n // no-op\n }\n};\n\nexport const safeParseJson = async (response: Response): Promise<any> => {\n try {\n return await response.json();\n } catch {\n try {\n const text = await response.text();\n\n return { error: text };\n } catch {\n return undefined;\n }\n }\n};\n\nexport interface StrapiContextHeaders {\n strapiVersion?: string | null;\n projectId?: string | null;\n userId?: string | null;\n}\n\nconst buildHeaders = (\n token: string,\n ctx?: StrapiContextHeaders,\n extra?: HeadersInit\n): Record<string, string> => {\n return {\n Authorization: `Bearer ${token}`,\n 'X-Strapi-Version': ctx?.strapiVersion || 'latest',\n 'X-Strapi-User': ctx?.userId || 'unknown',\n 'X-Strapi-Project-Id': ctx?.projectId || 'unknown',\n ...(extra as Record<string, string>),\n };\n};\n\nconst shouldRetryForToken = (status: number, body: any): boolean => {\n if (status === 401 || status === 403) {\n return true;\n }\n\n const msg = (body?.error || '').toString().toLowerCase();\n return msg.includes('expired') || msg.includes('invalid token');\n};\n\nexport interface FetchAIOptions extends RequestInit {\n ctx?: StrapiContextHeaders;\n}\n\n/**\n * Generic fetch wrapper for AI endpoints with token injection and single retry on invalidation\n */\nexport const fetchAI = async (\n input: RequestInfo | URL,\n options: FetchAIOptions = {}\n): Promise<Response> => {\n // Get token\n const tokenData = await getAIJwt();\n\n if (!tokenData?.token) {\n const error = new Error(\n 'Could not authorize with AI Server. Please contact your administrator.'\n );\n\n throw error;\n }\n\n const make = async (token: string): Promise<Response> => {\n const headers = buildHeaders(token, options.ctx, options.headers);\n return fetch(input, {\n ...options,\n headers,\n });\n };\n\n let response = await make(tokenData.token);\n\n let body: unknown | undefined = undefined;\n try {\n body = await safeParseJson(response.clone());\n } catch {\n // no-op\n }\n\n if (shouldRetryForToken(response.status, body)) {\n clearAIJwt();\n\n const refreshed = await getAIJwt();\n\n if (refreshed?.token && refreshed.token !== tokenData.token) {\n response = await make(refreshed.token);\n }\n }\n\n return response;\n};\n\n/**\n * Factory to provide a fetch implementation compatible with AI SDK useChat\n * that injects AI JWT + Strapi context headers and retries on token invalidation once.\n */\nexport const makeChatFetch = (ctx: StrapiContextHeaders) => {\n return async (input: RequestInfo | URL, options: RequestInit = {}): Promise<Response> => {\n return fetchAI(input, { ...options, ctx });\n };\n};\n"],"names":["aiTokenCache","SESSION_STORAGE_KEY","EXPIRY_BUFFER_MS","parseExpiryMs","expiresAt","ms","Date","parse","Number","isFinite","getTokenState","bufferMs","now","expMs","isTokenUsable","clearAIJwt","sessionStorage","removeItem","readFromSession","raw","getItem","parsed","JSON","writeToSession","data","setItem","stringify","getAIJwt","fromSession","get","getFetchClient","token","prefetchAIToken","existing","safeParseJson","response","json","text","error","undefined","buildHeaders","ctx","extra","Authorization","strapiVersion","userId","projectId","shouldRetryForToken","status","body","msg","toString","toLowerCase","includes","fetchAI","input","options","tokenData","Error","make","headers","fetch","clone","refreshed","makeChatFetch"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-namespace */ const STRAPI_CODE_MIME_TYPE = 'application/vnd.strapi.code';
|
|
4
|
+
const STRAPI_MAX_ATTACHMENTS = 15;
|
|
5
|
+
const STRAPI_MAX_ATTACHMENT_SIZE = 15 * 1024 * 1024; // 15MB
|
|
6
|
+
/* -------------------------------------------------------------------------------------------------
|
|
7
|
+
* APIs
|
|
8
|
+
* -----------------------------------------------------------------------------------------------*/ const STRAPI_AI_URL = process.env.STRAPI_AI_URL?.replace(/\/+$/, '') ?? 'https://strapi-ai.apps.strapi.io';
|
|
9
|
+
const STRAPI_AI_CHAT_URL = `${STRAPI_AI_URL}/schemas/chat`;
|
|
10
|
+
|
|
11
|
+
exports.STRAPI_AI_CHAT_URL = STRAPI_AI_CHAT_URL;
|
|
12
|
+
exports.STRAPI_AI_URL = STRAPI_AI_URL;
|
|
13
|
+
exports.STRAPI_CODE_MIME_TYPE = STRAPI_CODE_MIME_TYPE;
|
|
14
|
+
exports.STRAPI_MAX_ATTACHMENTS = STRAPI_MAX_ATTACHMENTS;
|
|
15
|
+
exports.STRAPI_MAX_ATTACHMENT_SIZE = STRAPI_MAX_ATTACHMENT_SIZE;
|
|
16
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sources":["../../../../../admin/src/components/AIChat/lib/constants.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\nimport type { Schema } from './types/schema';\n\nexport const STRAPI_CODE_MIME_TYPE = 'application/vnd.strapi.code';\nexport const STRAPI_MAX_ATTACHMENTS = 15;\nexport const STRAPI_MAX_ATTACHMENT_SIZE = 15 * 1024 * 1024; // 15MB\n\n/* -------------------------------------------------------------------------------------------------\n * APIs\n * -----------------------------------------------------------------------------------------------*/\nexport const STRAPI_AI_URL =\n process.env.STRAPI_AI_URL?.replace(/\\/+$/, '') ?? 'https://strapi-ai.apps.strapi.io';\nexport const STRAPI_AI_CHAT_URL = `${STRAPI_AI_URL}/schemas/chat`;\nexport const STRAPI_AI_TITLE_URL = `/schemas/chat/generate-title` as const;\nexport const STRAPI_AI_FEEDBACK_URL = `/schemas/chat/feedback` as const;\nexport const STRAPI_AI_PROJECT_URL = `/schemas/chat/attachment` as const;\n\n// AI SDK will also send messages and other relevant data\nexport interface ChatBody {\n schemas: Schema[];\n}\n"],"names":["STRAPI_CODE_MIME_TYPE","STRAPI_MAX_ATTACHMENTS","STRAPI_MAX_ATTACHMENT_SIZE","STRAPI_AI_URL","process","env","replace","STRAPI_AI_CHAT_URL"],"mappings":";;AAAA,qDAGaA,MAAAA,qBAAAA,GAAwB;AAC9B,MAAMC,yBAAyB;MACzBC,0BAA6B,GAAA,EAAA,GAAK,IAAO,GAAA,KAAK;AAE3D;;qGAGaC,MAAAA,aAAAA,GACXC,OAAQC,CAAAA,GAAG,CAACF,aAAa,EAAEG,OAAAA,CAAQ,MAAQ,EAAA,EAAA,CAAA,IAAO;MACvCC,kBAAqB,GAAA,CAAC,EAAEJ,aAAc,CAAA,aAAa;;;;;;;;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-namespace */ const STRAPI_CODE_MIME_TYPE = 'application/vnd.strapi.code';
|
|
2
|
+
const STRAPI_MAX_ATTACHMENTS = 15;
|
|
3
|
+
const STRAPI_MAX_ATTACHMENT_SIZE = 15 * 1024 * 1024; // 15MB
|
|
4
|
+
/* -------------------------------------------------------------------------------------------------
|
|
5
|
+
* APIs
|
|
6
|
+
* -----------------------------------------------------------------------------------------------*/ const STRAPI_AI_URL = process.env.STRAPI_AI_URL?.replace(/\/+$/, '') ?? 'https://strapi-ai.apps.strapi.io';
|
|
7
|
+
const STRAPI_AI_CHAT_URL = `${STRAPI_AI_URL}/schemas/chat`;
|
|
8
|
+
|
|
9
|
+
export { STRAPI_AI_CHAT_URL, STRAPI_AI_URL, STRAPI_CODE_MIME_TYPE, STRAPI_MAX_ATTACHMENTS, STRAPI_MAX_ATTACHMENT_SIZE };
|
|
10
|
+
//# sourceMappingURL=constants.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.mjs","sources":["../../../../../admin/src/components/AIChat/lib/constants.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\nimport type { Schema } from './types/schema';\n\nexport const STRAPI_CODE_MIME_TYPE = 'application/vnd.strapi.code';\nexport const STRAPI_MAX_ATTACHMENTS = 15;\nexport const STRAPI_MAX_ATTACHMENT_SIZE = 15 * 1024 * 1024; // 15MB\n\n/* -------------------------------------------------------------------------------------------------\n * APIs\n * -----------------------------------------------------------------------------------------------*/\nexport const STRAPI_AI_URL =\n process.env.STRAPI_AI_URL?.replace(/\\/+$/, '') ?? 'https://strapi-ai.apps.strapi.io';\nexport const STRAPI_AI_CHAT_URL = `${STRAPI_AI_URL}/schemas/chat`;\nexport const STRAPI_AI_TITLE_URL = `/schemas/chat/generate-title` as const;\nexport const STRAPI_AI_FEEDBACK_URL = `/schemas/chat/feedback` as const;\nexport const STRAPI_AI_PROJECT_URL = `/schemas/chat/attachment` as const;\n\n// AI SDK will also send messages and other relevant data\nexport interface ChatBody {\n schemas: Schema[];\n}\n"],"names":["STRAPI_CODE_MIME_TYPE","STRAPI_MAX_ATTACHMENTS","STRAPI_MAX_ATTACHMENT_SIZE","STRAPI_AI_URL","process","env","replace","STRAPI_AI_CHAT_URL"],"mappings":"AAAA,qDAGaA,MAAAA,qBAAAA,GAAwB;AAC9B,MAAMC,yBAAyB;MACzBC,0BAA6B,GAAA,EAAA,GAAK,IAAO,GAAA,KAAK;AAE3D;;qGAGaC,MAAAA,aAAAA,GACXC,OAAQC,CAAAA,GAAG,CAACF,aAAa,EAAEG,OAAAA,CAAQ,MAAQ,EAAA,EAAA,CAAA,IAAO;MACvCC,kBAAqB,GAAA,CAAC,EAAEJ,aAAc,CAAA,aAAa;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"misc.js","sources":["../../../../../admin/src/components/AIChat/lib/misc.ts"],"sourcesContent":["export const generateId = (size: number = 16) => {\n return crypto.randomUUID().slice(0, size);\n};\n"],"names":["generateId","size","crypto","randomUUID","slice"],"mappings":";;AAAaA,MAAAA,UAAAA,GAAa,CAACC,IAAAA,GAAe,EAAE,GAAA;AAC1C,IAAA,OAAOC,MAAOC,CAAAA,UAAU,EAAGC,CAAAA,KAAK,CAAC,CAAGH,EAAAA,IAAAA,CAAAA;AACtC;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"misc.mjs","sources":["../../../../../admin/src/components/AIChat/lib/misc.ts"],"sourcesContent":["export const generateId = (size: number = 16) => {\n return crypto.randomUUID().slice(0, size);\n};\n"],"names":["generateId","size","crypto","randomUUID","slice"],"mappings":"AAAaA,MAAAA,UAAAA,GAAa,CAACC,IAAAA,GAAe,EAAE,GAAA;AAC1C,IAAA,OAAOC,MAAOC,CAAAA,UAAU,EAAGC,CAAAA,KAAK,CAAC,CAAGH,EAAAA,IAAAA,CAAAA;AACtC;;;;"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
4
|
+
const transformAttributesFromCTBToChat = (attributes)=>{
|
|
5
|
+
return attributes.reduce((acc, attribute)=>{
|
|
6
|
+
const { name, ...rest } = attribute;
|
|
7
|
+
return {
|
|
8
|
+
...acc,
|
|
9
|
+
[name]: rest
|
|
10
|
+
};
|
|
11
|
+
}, {});
|
|
12
|
+
};
|
|
13
|
+
const transformCTBToChat = (schema)=>{
|
|
14
|
+
if (schema.modelType === 'component') {
|
|
15
|
+
return {
|
|
16
|
+
category: schema.category,
|
|
17
|
+
kind: 'component',
|
|
18
|
+
action: 'create',
|
|
19
|
+
modelType: 'component',
|
|
20
|
+
description: schema.info.description,
|
|
21
|
+
name: schema.info.displayName,
|
|
22
|
+
uid: schema.uid,
|
|
23
|
+
attributes: transformAttributesFromCTBToChat(schema.attributes),
|
|
24
|
+
// @ts-expect-error - injected from previous ai messages
|
|
25
|
+
sources: schema.sources
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
kind: schema.kind,
|
|
30
|
+
modelType: schema.modelType,
|
|
31
|
+
description: schema.info.description,
|
|
32
|
+
action: 'create',
|
|
33
|
+
name: schema.info.pluralName,
|
|
34
|
+
uid: schema.uid,
|
|
35
|
+
attributes: transformAttributesFromCTBToChat(schema.attributes),
|
|
36
|
+
// @ts-expect-error - injected from previous ai messages
|
|
37
|
+
sources: schema.sources,
|
|
38
|
+
options: {
|
|
39
|
+
draftAndPublish: schema.options?.draftAndPublish,
|
|
40
|
+
localized: false
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
exports.transformCTBToChat = transformCTBToChat;
|
|
46
|
+
//# sourceMappingURL=fromCTB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fromCTB.js","sources":["../../../../../../../admin/src/components/AIChat/lib/transforms/schemas/fromCTB.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\nimport { Schema } from '../../types/schema';\n\nimport type { ContentType, Component, AnyAttribute } from '../../../../../types';\n\nconst transformAttributesFromCTBToChat = (attributes: AnyAttribute[]) => {\n return attributes.reduce(\n (acc, attribute) => {\n const { name, ...rest } = attribute;\n\n return {\n ...acc,\n [name]: rest,\n };\n },\n {} as Record<string, Omit<AnyAttribute, 'name'>>\n );\n};\n\nexport const transformCTBToChat = (schema: ContentType | Component): Schema => {\n if (schema.modelType === 'component') {\n return {\n category: schema.category,\n kind: 'component',\n action: 'create',\n modelType: 'component',\n description: schema.info.description,\n name: schema.info.displayName,\n\n uid: schema.uid as any,\n attributes: transformAttributesFromCTBToChat(schema.attributes),\n // @ts-expect-error - injected from previous ai messages\n sources: schema.sources,\n } as any;\n }\n\n return {\n kind: schema.kind,\n modelType: schema.modelType,\n description: schema.info.description,\n action: 'create',\n name: schema.info.pluralName,\n uid: schema.uid as any,\n attributes: transformAttributesFromCTBToChat(schema.attributes),\n // @ts-expect-error - injected from previous ai messages\n sources: schema.sources,\n options: {\n draftAndPublish: schema.options?.draftAndPublish,\n localized: false,\n },\n } as any;\n};\n"],"names":["transformAttributesFromCTBToChat","attributes","reduce","acc","attribute","name","rest","transformCTBToChat","schema","modelType","category","kind","action","description","info","displayName","uid","sources","pluralName","options","draftAndPublish","localized"],"mappings":";;AAAA;AAKA,MAAMA,mCAAmC,CAACC,UAAAA,GAAAA;AACxC,IAAA,OAAOA,UAAWC,CAAAA,MAAM,CACtB,CAACC,GAAKC,EAAAA,SAAAA,GAAAA;AACJ,QAAA,MAAM,EAAEC,IAAI,EAAE,GAAGC,MAAM,GAAGF,SAAAA;QAE1B,OAAO;AACL,YAAA,GAAGD,GAAG;AACN,YAAA,CAACE,OAAOC;AACV,SAAA;AACF,KAAA,EACA,EAAC,CAAA;AAEL,CAAA;AAEO,MAAMC,qBAAqB,CAACC,MAAAA,GAAAA;IACjC,IAAIA,MAAAA,CAAOC,SAAS,KAAK,WAAa,EAAA;QACpC,OAAO;AACLC,YAAAA,QAAAA,EAAUF,OAAOE,QAAQ;YACzBC,IAAM,EAAA,WAAA;YACNC,MAAQ,EAAA,QAAA;YACRH,SAAW,EAAA,WAAA;YACXI,WAAaL,EAAAA,MAAAA,CAAOM,IAAI,CAACD,WAAW;YACpCR,IAAMG,EAAAA,MAAAA,CAAOM,IAAI,CAACC,WAAW;AAE7BC,YAAAA,GAAAA,EAAKR,OAAOQ,GAAG;YACff,UAAYD,EAAAA,gCAAAA,CAAiCQ,OAAOP,UAAU,CAAA;;AAE9DgB,YAAAA,OAAAA,EAAST,OAAOS;AAClB,SAAA;AACF;IAEA,OAAO;AACLN,QAAAA,IAAAA,EAAMH,OAAOG,IAAI;AACjBF,QAAAA,SAAAA,EAAWD,OAAOC,SAAS;QAC3BI,WAAaL,EAAAA,MAAAA,CAAOM,IAAI,CAACD,WAAW;QACpCD,MAAQ,EAAA,QAAA;QACRP,IAAMG,EAAAA,MAAAA,CAAOM,IAAI,CAACI,UAAU;AAC5BF,QAAAA,GAAAA,EAAKR,OAAOQ,GAAG;QACff,UAAYD,EAAAA,gCAAAA,CAAiCQ,OAAOP,UAAU,CAAA;;AAE9DgB,QAAAA,OAAAA,EAAST,OAAOS,OAAO;QACvBE,OAAS,EAAA;YACPC,eAAiBZ,EAAAA,MAAAA,CAAOW,OAAO,EAAEC,eAAAA;YACjCC,SAAW,EAAA;AACb;AACF,KAAA;AACF;;;;"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2
|
+
const transformAttributesFromCTBToChat = (attributes)=>{
|
|
3
|
+
return attributes.reduce((acc, attribute)=>{
|
|
4
|
+
const { name, ...rest } = attribute;
|
|
5
|
+
return {
|
|
6
|
+
...acc,
|
|
7
|
+
[name]: rest
|
|
8
|
+
};
|
|
9
|
+
}, {});
|
|
10
|
+
};
|
|
11
|
+
const transformCTBToChat = (schema)=>{
|
|
12
|
+
if (schema.modelType === 'component') {
|
|
13
|
+
return {
|
|
14
|
+
category: schema.category,
|
|
15
|
+
kind: 'component',
|
|
16
|
+
action: 'create',
|
|
17
|
+
modelType: 'component',
|
|
18
|
+
description: schema.info.description,
|
|
19
|
+
name: schema.info.displayName,
|
|
20
|
+
uid: schema.uid,
|
|
21
|
+
attributes: transformAttributesFromCTBToChat(schema.attributes),
|
|
22
|
+
// @ts-expect-error - injected from previous ai messages
|
|
23
|
+
sources: schema.sources
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
kind: schema.kind,
|
|
28
|
+
modelType: schema.modelType,
|
|
29
|
+
description: schema.info.description,
|
|
30
|
+
action: 'create',
|
|
31
|
+
name: schema.info.pluralName,
|
|
32
|
+
uid: schema.uid,
|
|
33
|
+
attributes: transformAttributesFromCTBToChat(schema.attributes),
|
|
34
|
+
// @ts-expect-error - injected from previous ai messages
|
|
35
|
+
sources: schema.sources,
|
|
36
|
+
options: {
|
|
37
|
+
draftAndPublish: schema.options?.draftAndPublish,
|
|
38
|
+
localized: false
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export { transformCTBToChat };
|
|
44
|
+
//# sourceMappingURL=fromCTB.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fromCTB.mjs","sources":["../../../../../../../admin/src/components/AIChat/lib/transforms/schemas/fromCTB.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/ban-ts-comment\nimport { Schema } from '../../types/schema';\n\nimport type { ContentType, Component, AnyAttribute } from '../../../../../types';\n\nconst transformAttributesFromCTBToChat = (attributes: AnyAttribute[]) => {\n return attributes.reduce(\n (acc, attribute) => {\n const { name, ...rest } = attribute;\n\n return {\n ...acc,\n [name]: rest,\n };\n },\n {} as Record<string, Omit<AnyAttribute, 'name'>>\n );\n};\n\nexport const transformCTBToChat = (schema: ContentType | Component): Schema => {\n if (schema.modelType === 'component') {\n return {\n category: schema.category,\n kind: 'component',\n action: 'create',\n modelType: 'component',\n description: schema.info.description,\n name: schema.info.displayName,\n\n uid: schema.uid as any,\n attributes: transformAttributesFromCTBToChat(schema.attributes),\n // @ts-expect-error - injected from previous ai messages\n sources: schema.sources,\n } as any;\n }\n\n return {\n kind: schema.kind,\n modelType: schema.modelType,\n description: schema.info.description,\n action: 'create',\n name: schema.info.pluralName,\n uid: schema.uid as any,\n attributes: transformAttributesFromCTBToChat(schema.attributes),\n // @ts-expect-error - injected from previous ai messages\n sources: schema.sources,\n options: {\n draftAndPublish: schema.options?.draftAndPublish,\n localized: false,\n },\n } as any;\n};\n"],"names":["transformAttributesFromCTBToChat","attributes","reduce","acc","attribute","name","rest","transformCTBToChat","schema","modelType","category","kind","action","description","info","displayName","uid","sources","pluralName","options","draftAndPublish","localized"],"mappings":"AAAA;AAKA,MAAMA,mCAAmC,CAACC,UAAAA,GAAAA;AACxC,IAAA,OAAOA,UAAWC,CAAAA,MAAM,CACtB,CAACC,GAAKC,EAAAA,SAAAA,GAAAA;AACJ,QAAA,MAAM,EAAEC,IAAI,EAAE,GAAGC,MAAM,GAAGF,SAAAA;QAE1B,OAAO;AACL,YAAA,GAAGD,GAAG;AACN,YAAA,CAACE,OAAOC;AACV,SAAA;AACF,KAAA,EACA,EAAC,CAAA;AAEL,CAAA;AAEO,MAAMC,qBAAqB,CAACC,MAAAA,GAAAA;IACjC,IAAIA,MAAAA,CAAOC,SAAS,KAAK,WAAa,EAAA;QACpC,OAAO;AACLC,YAAAA,QAAAA,EAAUF,OAAOE,QAAQ;YACzBC,IAAM,EAAA,WAAA;YACNC,MAAQ,EAAA,QAAA;YACRH,SAAW,EAAA,WAAA;YACXI,WAAaL,EAAAA,MAAAA,CAAOM,IAAI,CAACD,WAAW;YACpCR,IAAMG,EAAAA,MAAAA,CAAOM,IAAI,CAACC,WAAW;AAE7BC,YAAAA,GAAAA,EAAKR,OAAOQ,GAAG;YACff,UAAYD,EAAAA,gCAAAA,CAAiCQ,OAAOP,UAAU,CAAA;;AAE9DgB,YAAAA,OAAAA,EAAST,OAAOS;AAClB,SAAA;AACF;IAEA,OAAO;AACLN,QAAAA,IAAAA,EAAMH,OAAOG,IAAI;AACjBF,QAAAA,SAAAA,EAAWD,OAAOC,SAAS;QAC3BI,WAAaL,EAAAA,MAAAA,CAAOM,IAAI,CAACD,WAAW;QACpCD,MAAQ,EAAA,QAAA;QACRP,IAAMG,EAAAA,MAAAA,CAAOM,IAAI,CAACI,UAAU;AAC5BF,QAAAA,GAAAA,EAAKR,OAAOQ,GAAG;QACff,UAAYD,EAAAA,gCAAAA,CAAiCQ,OAAOP,UAAU,CAAA;;AAE9DgB,QAAAA,OAAAA,EAAST,OAAOS,OAAO;QACvBE,OAAS,EAAA;YACPC,eAAiBZ,EAAAA,MAAAA,CAAOW,OAAO,EAAEC,eAAAA;YACjCC,SAAW,EAAA;AACb;AACF,KAAA;AACF;;;;"}
|